2 * Copyright (c) 1995 - 2003 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
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.
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.
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
36 RCSID("$Id: kxd.c,v 1.71.2.2 2003/05/15 15:11:35 lha Exp $");
38 static pid_t wait_on_pid = -1;
42 * Signal handler that justs waits for the children when they die.
46 childhandler (int sig)
52 pid = waitpid (-1, &status, WNOHANG|WUNTRACED);
53 if (pid > 0 && pid == wait_on_pid)
56 signal (SIGCHLD, childhandler);
61 * Print the error message `format' and `...' on fd and die.
65 fatal (kx_context *kc, int fd, char *format, ...)
72 va_start(args, format);
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 += KRB_PUT_INT (len, p, 4, 4);
80 kx_write (kc, fd, msg, p - msg);
86 * Remove all sockets and cookie files.
90 cleanup(int nsockets, struct x_socket *sockets)
96 for (i = 0; i < nsockets; ++i) {
97 if (sockets[i].pathname != NULL) {
98 unlink (sockets[i].pathname);
99 free (sockets[i].pathname);
105 * Prepare to receive a connection on `sock'.
109 recv_conn (int sock, kx_context *kc,
110 int *dispnr, int *nsockets, struct x_socket **sockets,
113 u_char msg[1024], *p;
116 struct passwd *passwd;
117 char remotehost[MaxHostNameLen];
118 char remoteaddr[INET6_ADDRSTRLEN];
124 addrlen = sizeof(kc->__ss_this);
125 kc->thisaddr = (struct sockaddr*)&kc->__ss_this;
126 if (getsockname (sock, kc->thisaddr, &addrlen) < 0) {
127 syslog (LOG_ERR, "getsockname: %m");
130 kc->thisaddr_len = addrlen;
131 addrlen = sizeof(kc->__ss_that);
132 kc->thataddr = (struct sockaddr*)&kc->__ss_that;
133 if (getpeername (sock, kc->thataddr, &addrlen) < 0) {
134 syslog (LOG_ERR, "getpeername: %m");
137 kc->thataddr_len = addrlen;
139 getnameinfo_verified (kc->thataddr,
141 remotehost, sizeof(remotehost),
144 if (net_read (sock, msg, 4) != 4) {
145 syslog (LOG_ERR, "read: %m");
150 if (ret && recv_v5_auth (kc, sock, msg) == 0)
154 if (ret && recv_v4_auth (kc, sock, msg) == 0)
158 syslog (LOG_ERR, "unrecognized auth protocol: %x %x %x %x",
159 msg[0], msg[1], msg[2], msg[3]);
163 len = kx_read (kc, sock, msg, sizeof(msg));
165 syslog (LOG_ERR, "kx_read failed");
170 fatal(kc, sock, "Bad message");
172 p += krb_get_int (p, &tmp32, 4, 0);
173 len = min(sizeof(user), tmp32);
174 memcpy (user, p, len);
178 passwd = k_getpwnam (user);
180 fatal (kc, sock, "cannot find uid for %s", user);
182 if (context_userok (kc, user) != 0)
183 fatal (kc, sock, "%s not allowed to login as %s",
188 if (flags & PASSIVE) {
192 tmp = get_xsockets (nsockets, sockets, tcp_flag);
194 fatal (kc, sock, "Cannot create X socket(s): %s",
199 if (chown_xsockets (*nsockets, *sockets,
200 passwd->pw_uid, passwd->pw_gid)) {
201 cleanup (*nsockets, *sockets);
202 fatal (kc, sock, "Cannot chown sockets: %s",
208 cleanup (*nsockets, *sockets);
209 fatal (kc, sock, "fork: %s", strerror(errno));
210 } else if (pid != 0) {
214 cleanup (*nsockets, *sockets);
219 if (setgid (passwd->pw_gid) ||
220 initgroups(passwd->pw_name, passwd->pw_gid) ||
221 #ifdef HAVE_GETUDBNAM /* XXX this happens on crays */
222 setjob(passwd->pw_uid, 0) == -1 ||
224 setuid(passwd->pw_uid)) {
225 syslog(LOG_ERR, "setting uid/groups: %m");
226 fatal (kc, sock, "cannot set uid");
229 ret = getnameinfo(kc->thataddr, kc->thataddr_len,
230 remoteaddr, sizeof(remoteaddr),
231 NULL, 0, NI_NUMERICHOST);
233 fatal (kc, sock, "getnameinfo failed: %s", gai_strerror(ret));
235 syslog (LOG_INFO, "from %s(%s): %s -> %s",
236 remotehost, remoteaddr,
239 if (!(flags & PASSIVE)) {
240 p += krb_get_int (p, &tmp32, 4, 0);
241 len = min(tmp32, display_size);
242 memcpy (display, p, len);
245 p += krb_get_int (p, &tmp32, 4, 0);
246 len = min(tmp32, xauthfile_size);
247 memcpy (xauthfile, p, len);
248 xauthfile[len] = '\0';
251 #if defined(SO_KEEPALIVE) && defined(HAVE_SETSOCKOPT)
252 if (flags & KEEP_ALIVE) {
255 setsockopt (sock, SOL_SOCKET, SO_KEEPALIVE, (void *)&one,
267 passive_session (kx_context *kc, int fd, int sock, int cookiesp)
269 if (verify_and_remove_cookies (fd, sock, cookiesp))
272 return copy_encrypted (kc, fd, sock);
280 active_session (kx_context *kc, int fd, int sock, int cookiesp)
282 fd = connect_local_xsocket(0);
284 if (replace_cookie (fd, sock, xauthfile, cookiesp))
287 return copy_encrypted (kc, fd, sock);
291 * Handle a new connection.
295 doit_conn (kx_context *kc,
296 int fd, int meta_sock, int flags, int cookiesp)
298 int sock, sock2, port;
299 struct sockaddr_storage __ss_addr;
300 struct sockaddr *addr = (struct sockaddr*)&__ss_addr;
301 struct sockaddr_storage __ss_thisaddr;
302 struct sockaddr *thisaddr = (struct sockaddr*)&__ss_thisaddr;
304 u_char msg[1024], *p;
306 sock = socket (kc->thisaddr->sa_family, SOCK_STREAM, 0);
308 syslog (LOG_ERR, "socket: %m");
311 #if defined(TCP_NODELAY) && defined(HAVE_SETSOCKOPT)
314 setsockopt (sock, IPPROTO_TCP, TCP_NODELAY, (void *)&one, sizeof(one));
317 #if defined(SO_KEEPALIVE) && defined(HAVE_SETSOCKOPT)
318 if (flags & KEEP_ALIVE) {
321 setsockopt (sock, SOL_SOCKET, SO_KEEPALIVE, (void *)&one,
325 memset (&__ss_addr, 0, sizeof(__ss_addr));
326 addr->sa_family = kc->thisaddr->sa_family;
327 if (kc->thisaddr_len > sizeof(__ss_addr)) {
328 syslog(LOG_ERR, "error in af");
331 if (bind (sock, addr, kc->thisaddr_len) < 0) {
332 syslog (LOG_ERR, "bind: %m");
335 addrlen = sizeof(__ss_addr);
336 if (getsockname (sock, addr, &addrlen) < 0) {
337 syslog (LOG_ERR, "getsockname: %m");
340 if (listen (sock, SOMAXCONN) < 0) {
341 syslog (LOG_ERR, "listen: %m");
344 port = socket_get_port(addr);
348 p += KRB_PUT_INT (ntohs(port), p, 4, 4);
350 if (kx_write (kc, meta_sock, msg, p - msg) < 0) {
351 syslog (LOG_ERR, "write: %m");
355 addrlen = sizeof(__ss_thisaddr);
356 sock2 = accept (sock, thisaddr, &addrlen);
358 syslog (LOG_ERR, "accept: %m");
365 return passive_session (kc, fd, sock2, cookiesp);
367 return active_session (kc, fd, sock2, cookiesp);
371 * Is the current user the owner of the console?
375 check_user_console (kx_context *kc, int fd)
379 if (stat ("/dev/console", &sb) < 0)
380 fatal (kc, fd, "Cannot stat /dev/console: %s", strerror(errno));
381 if (getuid() != sb.st_uid)
382 fatal (kc, fd, "Permission denied");
385 /* close down the new connection with a reasonable error message */
387 close_connection(int fd, const char *message)
389 char buf[264]; /* max message */
394 mlen = strlen(message);
398 /* read first part of connection packet, to get byte order */
399 if(read(fd, buf, 6) != 6) {
406 *p++ = 0; /* failed */
407 *p++ = mlen; /* length of message */
408 p += 4; /* skip protocol version */
409 p += 2; /* skip additional length */
410 memcpy(p, message, mlen); /* copy message */
412 while((p - buf) % 4) /* pad to multiple of 4 bytes */
415 /* now fill in length of additional data */
417 buf[6] = (p - buf - 8) / 4;
421 buf[7] = (p - buf - 8) / 4;
423 write(fd, buf, p - buf);
429 * Handle a passive session on `sock'
433 doit_passive (kx_context *kc,
438 struct x_socket *sockets,
444 u_char msg[1024], *p;
447 display_num = dispnr;
449 snprintf (display, display_size, "localhost:%u", display_num);
451 snprintf (display, display_size, ":%u", display_num);
452 error = create_and_write_cookie (xauthfile, xauthfile_size,
455 cleanup(nsockets, sockets);
456 fatal (kc, sock, "Cookie-creation failed: %s", strerror(error));
465 len = strlen (display);
466 tmp = KRB_PUT_INT (len, p, rem, 4);
467 if (tmp < 0 || rem < len + 4) {
468 syslog (LOG_ERR, "doit: buffer too small");
469 cleanup(nsockets, sockets);
475 memcpy (p, display, len);
479 len = strlen (xauthfile);
480 tmp = KRB_PUT_INT (len, p, rem, 4);
481 if (tmp < 0 || rem < len + 4) {
482 syslog (LOG_ERR, "doit: buffer too small");
483 cleanup(nsockets, sockets);
489 memcpy (p, xauthfile, len);
493 if(kx_write (kc, sock, msg, p - msg) < 0) {
494 syslog (LOG_ERR, "write: %m");
495 cleanup(nsockets, sockets);
507 if (sock >= FD_SETSIZE) {
508 syslog (LOG_ERR, "fd too large");
509 cleanup(nsockets, sockets);
514 for (i = 0; i < nsockets; ++i) {
515 if (sockets[i].fd >= FD_SETSIZE) {
516 syslog (LOG_ERR, "fd too large");
517 cleanup(nsockets, sockets);
520 FD_SET(sockets[i].fd, &fds);
522 ret = select(FD_SETSIZE, &fds, NULL, NULL, NULL);
525 if(FD_ISSET(sock, &fds)){
526 /* there are no processes left on the remote side
528 cleanup(nsockets, sockets);
531 for (i = 0; i < nsockets; ++i) {
532 if (FD_ISSET(sockets[i].fd, &fds)) {
533 if (sockets[i].flags == TCP) {
534 struct sockaddr_storage __ss_peer;
535 struct sockaddr *peer = (struct sockaddr*)&__ss_peer;
536 socklen_t len = sizeof(__ss_peer);
538 fd = accept (sockets[i].fd,
541 if (fd < 0 && errno != EINTR)
542 syslog (LOG_ERR, "accept: %m");
545 if (fd >= 0 && suspicious_address (fd, peer)) {
550 } else if(sockets[i].flags == UNIX_SOCKET) {
553 fd = accept (sockets[i].fd, NULL, &zero);
555 if (fd < 0 && errno != EINTR)
556 syslog (LOG_ERR, "accept: %m");
557 #ifdef MAY_HAVE_X11_PIPES
558 } else if(sockets[i].flags == STREAM_PIPE) {
560 * this code tries to handle the
561 * send fd-over-pipe stuff for
565 struct strrecvfd strrecvfd;
567 ret = ioctl (sockets[i].fd,
568 I_RECVFD, &strrecvfd);
569 if (ret < 0 && errno != EINTR) {
570 syslog (LOG_ERR, "ioctl I_RECVFD: %m");
575 if (strrecvfd.uid != getuid()) {
576 close (strrecvfd.fd);
584 #endif /* MAY_HAVE_X11_PIPES */
600 syslog (LOG_ERR, "fork: %m");
603 close_connection(fd, strerror(errno));
604 } else if (child == 0) {
605 for (i = 0; i < nsockets; ++i)
606 close (sockets[i].fd);
607 return doit_conn (kc, fd, sock, flags, cookiesp);
615 * Handle an active session on `sock'
619 doit_active (kx_context *kc,
624 u_char msg[1024], *p;
626 check_user_console (kc, sock);
631 if(kx_write (kc, sock, msg, p - msg) < 0) {
632 syslog (LOG_ERR, "write: %m");
639 len = kx_read (kc, sock, msg, sizeof(msg));
641 syslog (LOG_ERR, "read: %m");
645 if (*p != NEW_CONN) {
646 syslog (LOG_ERR, "bad_message: %d", *p);
652 syslog (LOG_ERR, "fork: %m");
655 } else if (child == 0) {
656 return doit_conn (kc, sock, sock, flags, 1);
663 * Receive a connection on `sock' and process it.
667 doit(int sock, int tcp_flag)
673 struct x_socket *sockets;
676 flags = recv_conn (sock, &context, &dispnr, &nsockets, &sockets, tcp_flag);
679 ret = doit_passive (&context, sock, flags, dispnr,
680 nsockets, sockets, tcp_flag);
682 ret = doit_active (&context, sock, flags, tcp_flag);
683 context_destroy (&context);
687 static char *port_str = NULL;
688 static int inetd_flag = 1;
689 static int tcp_flag = 0;
690 static int version_flag = 0;
691 static int help_flag = 0;
693 struct getargs args[] = {
694 { "inetd", 'i', arg_negative_flag, &inetd_flag,
695 "Not started from inetd" },
696 { "tcp", 't', arg_flag, &tcp_flag, "Use TCP" },
697 { "port", 'p', arg_string, &port_str, "Use this port",
699 { "version", 0, arg_flag, &version_flag },
700 { "help", 0, arg_flag, &help_flag }
706 arg_printusage (args,
707 sizeof(args) / sizeof(args[0]),
714 * kxd - receive a forwarded X conncection
718 main (int argc, char **argv)
723 setprogname (argv[0]);
724 roken_openlog ("kxd", LOG_ODELAY | LOG_PID, LOG_DAEMON);
726 if (getarg (args, sizeof(args) / sizeof(args[0]), argc, argv,
734 print_version (NULL);
739 struct servent *s = roken_getservbyname (port_str, "tcp");
746 port = strtol (port_str, &ptr, 10);
747 if (port == 0 && ptr == port_str)
748 errx (1, "bad port `%s'", port_str);
753 port = krb5_getportbyname(NULL, "kx", "tcp", KX_PORT);
755 port = k_getportbyname ("kx", "tcp", htons(KX_PORT));
757 #error define KRB4 or KRB5
764 signal (SIGCHLD, childhandler);
765 return doit(STDIN_FILENO, tcp_flag);