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