1/*
2 * Copyright (c) 1995 - 2003 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 *
17 * 3. Neither the name of the Institute nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#include "kx.h"
35
36RCSID("$Id$");
37
38static pid_t wait_on_pid = -1;
39static int   done        = 0;
40
41/*
42 * Signal handler that justs waits for the children when they die.
43 */
44
45static RETSIGTYPE
46childhandler (int sig)
47{
48     pid_t pid;
49     int status;
50
51     do {
52       pid = waitpid (-1, &status, WNOHANG|WUNTRACED);
53       if (pid > 0 && pid == wait_on_pid)
54	   done = 1;
55     } while(pid > 0);
56     signal (SIGCHLD, childhandler);
57     SIGRETURN(0);
58}
59
60/*
61 * Print the error message `format' and `...' on fd and die.
62 */
63
64void
65fatal (kx_context *kc, int fd, char *format, ...)
66{
67    u_char msg[1024];
68    u_char *p;
69    va_list args;
70    int len;
71
72    va_start(args, format);
73    p = msg;
74    *p++ = ERROR;
75    vsnprintf ((char *)p + 4, sizeof(msg) - 5, format, args);
76    syslog (LOG_ERR, "%s", (char *)p + 4);
77    len = strlen ((char *)p + 4);
78    p += kx_put_int (len, p, 4, 4);
79    p += len;
80    kx_write (kc, fd, msg, p - msg);
81    va_end(args);
82    exit (1);
83}
84
85/*
86 * Remove all sockets and cookie files.
87 */
88
89static void
90cleanup(int nsockets, struct x_socket *sockets)
91{
92    int i;
93
94    if(xauthfile[0])
95	unlink(xauthfile);
96    for (i = 0; i < nsockets; ++i) {
97	if (sockets[i].pathname != NULL) {
98	    unlink (sockets[i].pathname);
99	    free (sockets[i].pathname);
100	}
101    }
102    free(sockets);
103}
104
105/*
106 * Prepare to receive a connection on `sock'.
107 */
108
109static int
110recv_conn (int sock, kx_context *kc,
111	   int *dispnr, int *nsockets, struct x_socket **sockets,
112	   int tcp_flag)
113{
114     u_char msg[1024], *p;
115     char user[256];
116     socklen_t addrlen;
117     struct passwd *passwd;
118     char remotehost[MaxHostNameLen];
119     char remoteaddr[INET6_ADDRSTRLEN];
120     int ret = 1;
121     int flags;
122     int len;
123     uint32_t tmp32;
124
125     memset(kc, 0, sizeof(*kc));
126     *nsockets = 0;
127     *sockets = NULL;
128     *dispnr = 0;
129
130     addrlen = sizeof(kc->__ss_this);
131     kc->thisaddr = (struct sockaddr*)&kc->__ss_this;
132     if (getsockname (sock, kc->thisaddr, &addrlen) < 0) {
133	 syslog (LOG_ERR, "getsockname: %m");
134	 exit (1);
135     }
136     kc->thisaddr_len = addrlen;
137     addrlen = sizeof(kc->__ss_that);
138     kc->thataddr = (struct sockaddr*)&kc->__ss_that;
139     if (getpeername (sock, kc->thataddr, &addrlen) < 0) {
140	 syslog (LOG_ERR, "getpeername: %m");
141	 exit (1);
142     }
143     kc->thataddr_len = addrlen;
144
145     getnameinfo_verified (kc->thataddr,
146			   kc->thataddr_len,
147			   remotehost, sizeof(remotehost),
148			   NULL, 0, 0);
149
150     if (net_read (sock, msg, 4) != 4) {
151	 syslog (LOG_ERR, "read: %m");
152	 exit (1);
153     }
154
155#ifdef KRB5
156     if (ret && recv_v5_auth (kc, sock, msg) == 0)
157	 ret = 0;
158#endif
159     if (ret) {
160	 syslog (LOG_ERR, "unrecognized auth protocol: %x %x %x %x",
161		 msg[0], msg[1], msg[2], msg[3]);
162	 exit (1);
163     }
164
165     len = kx_read (kc, sock, msg, sizeof(msg));
166     if (len < 0) {
167	 syslog (LOG_ERR, "kx_read failed");
168	 exit (1);
169     }
170     p = (u_char *)msg;
171     if (*p != INIT)
172	 fatal(kc, sock, "Bad message");
173     p++;
174     if ((p - msg) < sizeof(msg))
175	 fatal(kc, sock, "user");
176
177     p += kx_get_int (p, &tmp32, 4, 0);
178     if (tmp32 >= sizeof(user) - 1)
179	 fatal(kc, sock, "user name too long");
180     if ((p - msg) + tmp32 >= sizeof(msg))
181	 fatal(kc, sock, "user too long");
182     memcpy (user, p, tmp32);
183     p += tmp32;
184     user[tmp32] = '\0';
185
186     passwd = k_getpwnam (user);
187     if (passwd == NULL)
188	 fatal (kc, sock, "cannot find uid for %s", user);
189
190     if (context_userok (kc, user) != 0)
191	 fatal (kc, sock, "%s not allowed to login as %s",
192		kc->user, user);
193
194     if ((p - msg) >= sizeof(msg))
195	 fatal(kc, sock, "user too long");
196
197     flags = *p++;
198
199     if (flags & PASSIVE) {
200	 pid_t pid;
201	 int tmp;
202
203	 tmp = get_xsockets (nsockets, sockets, tcp_flag);
204	 if (tmp < 0) {
205	     fatal (kc, sock, "Cannot create X socket(s): %s",
206		    strerror(errno));
207	 }
208	 *dispnr = tmp;
209
210	 if (chown_xsockets (*nsockets, *sockets,
211			    passwd->pw_uid, passwd->pw_gid)) {
212	     cleanup (*nsockets, *sockets);
213	     fatal (kc, sock, "Cannot chown sockets: %s",
214		    strerror(errno));
215	 }
216
217	 pid = fork();
218	 if (pid == -1) {
219	     cleanup (*nsockets, *sockets);
220	     fatal (kc, sock, "fork: %s", strerror(errno));
221	 } else if (pid != 0) {
222	     wait_on_pid = pid;
223	     while (!done)
224		 pause ();
225	     cleanup (*nsockets, *sockets);
226	     exit (0);
227	 }
228     }
229
230     if (setgid (passwd->pw_gid) ||
231	 initgroups(passwd->pw_name, passwd->pw_gid) ||
232#ifdef HAVE_GETUDBNAM /* XXX this happens on crays */
233	 setjob(passwd->pw_uid, 0) == -1 ||
234#endif
235	 setuid(passwd->pw_uid)) {
236	 syslog(LOG_ERR, "setting uid/groups: %m");
237	 fatal (kc, sock, "cannot set uid");
238     }
239
240     ret = getnameinfo(kc->thataddr, kc->thataddr_len,
241		       remoteaddr, sizeof(remoteaddr),
242		       NULL, 0, NI_NUMERICHOST);
243     if (ret != 0)
244	 fatal (kc, sock, "getnameinfo failed: %s", gai_strerror(ret));
245
246     syslog (LOG_INFO, "from %s(%s): %s -> %s",
247	     remotehost, remoteaddr,
248	     kc->user, user);
249     umask(077);
250     if (!(flags & PASSIVE)) {
251	 p += kx_get_int (p, &tmp32, 4, 0);
252	 if (tmp32 > display_size)
253	     fatal(kc, sock, "display too large");
254	 if ((p - msg) + tmp32 + 8 >= sizeof(msg))
255	     fatal(kc, sock, "user too long");
256	 memcpy (display, p, tmp32);
257	 display[tmp32] = '\0';
258	 p += tmp32;
259	 p += kx_get_int (p, &tmp32, 4, 0);
260	 len = min(tmp32, xauthfile_size);
261	 memcpy (xauthfile, p, len);
262	 xauthfile[len] = '\0';
263     }
264#if defined(SO_KEEPALIVE) && defined(HAVE_SETSOCKOPT)
265     if (flags & KEEP_ALIVE) {
266	 int one = 1;
267
268	 setsockopt (sock, SOL_SOCKET, SO_KEEPALIVE, (void *)&one,
269		     sizeof(one));
270     }
271#endif
272     return flags;
273}
274
275/*
276 *
277 */
278
279static int
280passive_session (kx_context *kc, int fd, int sock, int cookiesp)
281{
282    if (verify_and_remove_cookies (fd, sock, cookiesp))
283	return 1;
284    else
285	return copy_encrypted (kc, fd, sock);
286}
287
288/*
289 *
290 */
291
292static int
293active_session (kx_context *kc, int fd, int sock, int cookiesp)
294{
295    fd = connect_local_xsocket(0);
296
297    if (replace_cookie (fd, sock, xauthfile, cookiesp))
298	return 1;
299    else
300	return copy_encrypted (kc, fd, sock);
301}
302
303/*
304 * Handle a new connection.
305 */
306
307static int
308doit_conn (kx_context *kc,
309	   int fd, int meta_sock, int flags, int cookiesp)
310{
311    int sock, sock2, port;
312    struct sockaddr_storage __ss_addr;
313    struct sockaddr *addr = (struct sockaddr*)&__ss_addr;
314    struct sockaddr_storage __ss_thisaddr;
315    struct sockaddr *thisaddr = (struct sockaddr*)&__ss_thisaddr;
316    socklen_t addrlen;
317    u_char msg[1024], *p;
318
319    sock = socket (kc->thisaddr->sa_family, SOCK_STREAM, 0);
320    if (sock < 0) {
321	syslog (LOG_ERR, "socket: %m");
322	return 1;
323    }
324#if defined(TCP_NODELAY) && defined(HAVE_SETSOCKOPT)
325    {
326	int one = 1;
327	setsockopt (sock, IPPROTO_TCP, TCP_NODELAY, (void *)&one, sizeof(one));
328    }
329#endif
330#if defined(SO_KEEPALIVE) && defined(HAVE_SETSOCKOPT)
331    if (flags & KEEP_ALIVE) {
332	int one = 1;
333
334	setsockopt (sock, SOL_SOCKET, SO_KEEPALIVE, (void *)&one,
335		    sizeof(one));
336    }
337#endif
338    memset (&__ss_addr, 0, sizeof(__ss_addr));
339    addr->sa_family = kc->thisaddr->sa_family;
340    if (kc->thisaddr_len > sizeof(__ss_addr)) {
341	syslog(LOG_ERR, "error in af");
342	return 1;
343    }
344    if (bind (sock, addr, kc->thisaddr_len) < 0) {
345	syslog (LOG_ERR, "bind: %m");
346	return 1;
347    }
348    addrlen = sizeof(__ss_addr);
349    if (getsockname (sock, addr, &addrlen) < 0) {
350	syslog (LOG_ERR, "getsockname: %m");
351	return 1;
352    }
353    if (listen (sock, SOMAXCONN) < 0) {
354	syslog (LOG_ERR, "listen: %m");
355	return 1;
356    }
357    port = socket_get_port(addr);
358
359    p = msg;
360    *p++ = NEW_CONN;
361    p += kx_put_int (ntohs(port), p, 4, 4);
362
363    if (kx_write (kc, meta_sock, msg, p - msg) < 0) {
364	syslog (LOG_ERR, "write: %m");
365	return 1;
366    }
367
368    addrlen = sizeof(__ss_thisaddr);
369    sock2 = accept (sock, thisaddr, &addrlen);
370    if (sock2 < 0) {
371	syslog (LOG_ERR, "accept: %m");
372	return 1;
373    }
374    close (sock);
375    close (meta_sock);
376
377    if (flags & PASSIVE)
378	return passive_session (kc, fd, sock2, cookiesp);
379    else
380	return active_session (kc, fd, sock2, cookiesp);
381}
382
383/*
384 *  Is the current user the owner of the console?
385 */
386
387static void
388check_user_console (kx_context *kc, int fd)
389{
390     struct stat sb;
391
392     if (stat ("/dev/console", &sb) < 0)
393	 fatal (kc, fd, "Cannot stat /dev/console: %s", strerror(errno));
394     if (getuid() != sb.st_uid)
395	 fatal (kc, fd, "Permission denied");
396}
397
398/* close down the new connection with a reasonable error message */
399static void
400close_connection(int fd, const char *message)
401{
402    char buf[264]; /* max message */
403    char *p;
404    int lsb = 0;
405    size_t mlen;
406
407    mlen = strlen(message);
408    if(mlen > 255)
409	mlen = 255;
410
411    /* read first part of connection packet, to get byte order */
412    if(read(fd, buf, 6) != 6) {
413	close(fd);
414	return;
415    }
416    if(buf[0] == 0x6c)
417	lsb++;
418    p = buf;
419    *p++ = 0;				/* failed */
420    *p++ = mlen;			/* length of message */
421    p += 4;				/* skip protocol version */
422    p += 2;				/* skip additional length */
423    memcpy(p, message, mlen);		/* copy message */
424    p += mlen;
425    while((p - buf) % 4)		/* pad to multiple of 4 bytes */
426	*p++ = 0;
427
428    /* now fill in length of additional data */
429    if(lsb) {
430	buf[6] = (p - buf - 8) / 4;
431	buf[7] = 0;
432    }else{
433	buf[6] = 0;
434	buf[7] = (p - buf - 8) / 4;
435    }
436    write(fd, buf, p - buf);
437    close(fd);
438}
439
440
441/*
442 * Handle a passive session on `sock'
443 */
444
445static int
446doit_passive (kx_context *kc,
447	      int sock,
448	      int flags,
449	      int dispnr,
450	      int nsockets,
451	      struct x_socket *sockets,
452	      int tcp_flag)
453{
454    int tmp;
455    int len;
456    size_t rem;
457    u_char msg[1024], *p;
458    int error;
459
460    display_num = dispnr;
461    if (tcp_flag)
462	snprintf (display, display_size, "localhost:%u", display_num);
463    else
464	snprintf (display, display_size, ":%u", display_num);
465    error = create_and_write_cookie (xauthfile, xauthfile_size,
466				     cookie, cookie_len);
467    if (error) {
468	cleanup(nsockets, sockets);
469	fatal (kc, sock, "Cookie-creation failed: %s", strerror(error));
470	return 1;
471    }
472
473    p = msg;
474    rem = sizeof(msg);
475    *p++ = ACK;
476    --rem;
477
478    len = strlen (display);
479    tmp = kx_put_int (len, p, rem, 4);
480    if (tmp < 0 || rem < len + 4) {
481	syslog (LOG_ERR, "doit: buffer too small");
482	cleanup(nsockets, sockets);
483	return 1;
484    }
485    p += tmp;
486    rem -= tmp;
487
488    memcpy (p, display, len);
489    p += len;
490    rem -= len;
491
492    len = strlen (xauthfile);
493    tmp = kx_put_int (len, p, rem, 4);
494    if (tmp < 0 || rem < len + 4) {
495	syslog (LOG_ERR, "doit: buffer too small");
496	cleanup(nsockets, sockets);
497	return 1;
498    }
499    p += tmp;
500    rem -= tmp;
501
502    memcpy (p, xauthfile, len);
503    p += len;
504    rem -= len;
505
506    if(kx_write (kc, sock, msg, p - msg) < 0) {
507	syslog (LOG_ERR, "write: %m");
508	cleanup(nsockets, sockets);
509	return 1;
510    }
511    for (;;) {
512	pid_t child;
513	int fd = -1;
514	fd_set fds;
515	int i;
516	int ret;
517	int cookiesp = TRUE;
518
519	FD_ZERO(&fds);
520	if (sock >= FD_SETSIZE) {
521	    syslog (LOG_ERR, "fd too large");
522	    cleanup(nsockets, sockets);
523	    return 1;
524	}
525
526	FD_SET(sock, &fds);
527	for (i = 0; i < nsockets; ++i) {
528	    if (sockets[i].fd >= FD_SETSIZE) {
529		syslog (LOG_ERR, "fd too large");
530		cleanup(nsockets, sockets);
531		return 1;
532	    }
533	    FD_SET(sockets[i].fd, &fds);
534	}
535	ret = select(FD_SETSIZE, &fds, NULL, NULL, NULL);
536	if(ret <= 0)
537	    continue;
538	if(FD_ISSET(sock, &fds)){
539	    /* there are no processes left on the remote side
540	     */
541	    cleanup(nsockets, sockets);
542	    exit(0);
543	} else if(ret) {
544	    for (i = 0; i < nsockets; ++i) {
545		if (FD_ISSET(sockets[i].fd, &fds)) {
546		    if (sockets[i].flags == TCP) {
547			struct sockaddr_storage __ss_peer;
548			struct sockaddr *peer = (struct sockaddr*)&__ss_peer;
549			socklen_t slen = sizeof(__ss_peer);
550
551			fd = accept (sockets[i].fd,
552				     peer,
553				     &slen);
554			if (fd < 0 && errno != EINTR)
555			    syslog (LOG_ERR, "accept: %m");
556
557			/* XXX */
558			if (fd >= 0 && suspicious_address (fd, peer)) {
559			    close (fd);
560			    fd = -1;
561			    errno = EINTR;
562			}
563		    } else if(sockets[i].flags == UNIX_SOCKET) {
564			socklen_t zero = 0;
565
566			fd = accept (sockets[i].fd, NULL, &zero);
567
568			if (fd < 0 && errno != EINTR)
569			    syslog (LOG_ERR, "accept: %m");
570#ifdef MAY_HAVE_X11_PIPES
571		    } else if(sockets[i].flags == STREAM_PIPE) {
572			/*
573			 * this code tries to handle the
574			 * send fd-over-pipe stuff for
575			 * solaris
576			 */
577
578			struct strrecvfd strrecvfd;
579
580			ret = ioctl (sockets[i].fd,
581				     I_RECVFD, &strrecvfd);
582			if (ret < 0 && errno != EINTR) {
583			    syslog (LOG_ERR, "ioctl I_RECVFD: %m");
584			}
585
586			/* XXX */
587			if (ret == 0) {
588			    if (strrecvfd.uid != getuid()) {
589				close (strrecvfd.fd);
590				fd = -1;
591				errno = EINTR;
592			    } else {
593				fd = strrecvfd.fd;
594				cookiesp = FALSE;
595			    }
596			}
597#endif /* MAY_HAVE_X11_PIPES */
598		    } else
599			abort ();
600		    break;
601		}
602	    }
603	}
604	if (fd < 0) {
605	    if (errno == EINTR)
606		continue;
607	    else
608		return 1;
609	}
610
611	child = fork ();
612	if (child < 0) {
613	    syslog (LOG_ERR, "fork: %m");
614	    if(errno != EAGAIN)
615		return 1;
616	    close_connection(fd, strerror(errno));
617	} else if (child == 0) {
618	    for (i = 0; i < nsockets; ++i)
619		close (sockets[i].fd);
620	    return doit_conn (kc, fd, sock, flags, cookiesp);
621	} else {
622	    close (fd);
623	}
624    }
625}
626
627/*
628 * Handle an active session on `sock'
629 */
630
631static int
632doit_active (kx_context *kc,
633	     int sock,
634	     int flags,
635	     int tcp_flag)
636{
637    u_char msg[1024], *p;
638
639    check_user_console (kc, sock);
640
641    p = msg;
642    *p++ = ACK;
643
644    if(kx_write (kc, sock, msg, p - msg) < 0) {
645	syslog (LOG_ERR, "write: %m");
646	return 1;
647    }
648    for (;;) {
649	pid_t child;
650	int len;
651
652	len = kx_read (kc, sock, msg, sizeof(msg));
653	if (len < 0) {
654	    syslog (LOG_ERR, "read: %m");
655	    return 1;
656	}
657	p = (u_char *)msg;
658	if (*p != NEW_CONN) {
659	    syslog (LOG_ERR, "bad_message: %d", *p);
660	    return 1;
661	}
662
663	child = fork ();
664	if (child < 0) {
665	    syslog (LOG_ERR, "fork: %m");
666	    if (errno != EAGAIN)
667		return 1;
668	} else if (child == 0) {
669	    return doit_conn (kc, sock, sock, flags, 1);
670	} else {
671	}
672    }
673}
674
675/*
676 * Receive a connection on `sock' and process it.
677 */
678
679static int
680doit(int sock, int tcp_flag)
681{
682    int ret;
683    kx_context context;
684    int dispnr;
685    int nsockets;
686    struct x_socket *sockets;
687    int flags;
688
689    flags = recv_conn (sock, &context, &dispnr, &nsockets, &sockets, tcp_flag);
690
691    if (flags & PASSIVE) {
692	ret = doit_passive (&context, sock, flags, dispnr,
693			    nsockets, sockets, tcp_flag);
694    } else {
695	ret = doit_active (&context, sock, flags, tcp_flag);
696	cleanup(nsockets, sockets);
697    }
698    context_destroy (&context);
699    return ret;
700}
701
702static char *port_str		= NULL;
703static int inetd_flag		= 1;
704static int tcp_flag		= 0;
705static int version_flag		= 0;
706static int help_flag		= 0;
707
708struct getargs args[] = {
709    { "inetd",		'i',	arg_negative_flag,	&inetd_flag,
710      "Not started from inetd" },
711    { "tcp",		't',	arg_flag,	&tcp_flag,	"Use TCP" },
712    { "port",		'p',	arg_string,	&port_str,	"Use this port",
713      "port" },
714    { "version",	0, 	arg_flag,		&version_flag },
715    { "help",		0, 	arg_flag,		&help_flag }
716};
717
718static void
719usage(int ret)
720{
721    arg_printusage (args,
722		    sizeof(args) / sizeof(args[0]),
723		    NULL,
724		    "host");
725    exit (ret);
726}
727
728/*
729 * kxd - receive a forwarded X conncection
730 */
731
732int
733main (int argc, char **argv)
734{
735    int port;
736    int optidx = 0;
737
738    setprogname (argv[0]);
739    roken_openlog ("kxd", LOG_ODELAY | LOG_PID, LOG_DAEMON);
740
741    if (getarg (args, sizeof(args) / sizeof(args[0]), argc, argv,
742		&optidx))
743	usage (1);
744
745    if (help_flag)
746	usage (0);
747
748    if (version_flag) {
749	print_version (NULL);
750	return 0;
751    }
752
753    if(port_str) {
754	struct servent *s = roken_getservbyname (port_str, "tcp");
755
756	if (s)
757	    port = s->s_port;
758	else {
759	    char *ptr;
760
761	    port = strtol (port_str, &ptr, 10);
762	    if (port == 0 && ptr == port_str)
763		errx (1, "bad port `%s'", port_str);
764	    port = htons(port);
765	}
766    } else {
767#if defined(KRB5)
768	port = krb5_getportbyname(NULL, "kx", "tcp", KX_PORT);
769#else
770#error define KRB5
771#endif
772    }
773
774    if (!inetd_flag)
775	mini_inetd (port, NULL);
776
777     signal (SIGCHLD, childhandler);
778     return doit(STDIN_FILENO, tcp_flag);
779}
780