1 /* 2 * Copyright (c) 1997-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 "rsh_locl.h" 35 RCSID("$Id: rshd.c,v 1.51.2.1 2003/08/19 11:36:17 joda Exp $"); 36 37 int 38 login_access( struct passwd *user, char *from); 39 40 enum auth_method auth_method; 41 42 #ifdef KRB5 43 krb5_context context; 44 krb5_keyblock *keyblock; 45 krb5_crypto crypto; 46 #endif 47 48 #ifdef KRB4 49 des_key_schedule schedule; 50 des_cblock iv; 51 #endif 52 53 #ifdef KRB5 54 krb5_ccache ccache, ccache2; 55 int kerberos_status = 0; 56 #endif 57 58 int do_encrypt = 0; 59 60 static int do_unique_tkfile = 0; 61 static char tkfile[MAXPATHLEN] = ""; 62 63 static int do_inetd = 1; 64 static char *port_str; 65 static int do_rhosts = 1; 66 static int do_kerberos = 0; 67 #define DO_KRB4 2 68 #define DO_KRB5 4 69 static int do_vacuous = 0; 70 static int do_log = 1; 71 static int do_newpag = 1; 72 static int do_addr_verify = 0; 73 static int do_keepalive = 1; 74 static int do_version; 75 static int do_help = 0; 76 77 #if defined(KRB5) && defined(DCE) 78 int dfsk5ok = 0; 79 int dfspag = 0; 80 int dfsfwd = 0; 81 krb5_ticket *user_ticket; 82 #endif 83 84 static void 85 syslog_and_die (const char *m, ...) 86 __attribute__ ((format (printf, 1, 2))); 87 88 static void 89 syslog_and_die (const char *m, ...) 90 { 91 va_list args; 92 93 va_start(args, m); 94 vsyslog (LOG_ERR, m, args); 95 va_end(args); 96 exit (1); 97 } 98 99 static void 100 fatal (int, const char*, const char *, ...) 101 __attribute__ ((noreturn, format (printf, 3, 4))); 102 103 static void 104 fatal (int sock, const char *what, const char *m, ...) 105 { 106 va_list args; 107 char buf[BUFSIZ]; 108 size_t len; 109 110 *buf = 1; 111 va_start(args, m); 112 len = vsnprintf (buf + 1, sizeof(buf) - 1, m, args); 113 len = min(len, sizeof(buf) - 1); 114 va_end(args); 115 if(what != NULL) 116 syslog (LOG_ERR, "%s: %m: %s", what, buf + 1); 117 else 118 syslog (LOG_ERR, "%s", buf + 1); 119 net_write (sock, buf, len + 1); 120 exit (1); 121 } 122 123 static char * 124 read_str (int s, size_t sz, char *expl) 125 { 126 char *str = malloc(sz); 127 char *p = str; 128 if(str == NULL) 129 fatal(s, NULL, "%s too long", expl); 130 while(p < str + sz) { 131 if(net_read(s, p, 1) != 1) 132 syslog_and_die("read: %m"); 133 if(*p == '\0') 134 return str; 135 p++; 136 } 137 fatal(s, NULL, "%s too long", expl); 138 } 139 140 static int 141 recv_bsd_auth (int s, u_char *buf, 142 struct sockaddr_in *thisaddr, 143 struct sockaddr_in *thataddr, 144 char **client_username, 145 char **server_username, 146 char **cmd) 147 { 148 struct passwd *pwd; 149 150 *client_username = read_str (s, USERNAME_SZ, "local username"); 151 *server_username = read_str (s, USERNAME_SZ, "remote username"); 152 *cmd = read_str (s, ARG_MAX + 1, "command"); 153 pwd = getpwnam(*server_username); 154 if (pwd == NULL) 155 fatal(s, NULL, "Login incorrect."); 156 if (iruserok(thataddr->sin_addr.s_addr, pwd->pw_uid == 0, 157 *client_username, *server_username)) 158 fatal(s, NULL, "Login incorrect."); 159 return 0; 160 } 161 162 #ifdef KRB4 163 static int 164 recv_krb4_auth (int s, u_char *buf, 165 struct sockaddr *thisaddr, 166 struct sockaddr *thataddr, 167 char **client_username, 168 char **server_username, 169 char **cmd) 170 { 171 int status; 172 int32_t options; 173 KTEXT_ST ticket; 174 AUTH_DAT auth; 175 char instance[INST_SZ + 1]; 176 char version[KRB_SENDAUTH_VLEN + 1]; 177 178 if (memcmp (buf, KRB_SENDAUTH_VERS, 4) != 0) 179 return -1; 180 if (net_read (s, buf + 4, KRB_SENDAUTH_VLEN - 4) != 181 KRB_SENDAUTH_VLEN - 4) 182 syslog_and_die ("reading auth info: %m"); 183 if (memcmp (buf, KRB_SENDAUTH_VERS, KRB_SENDAUTH_VLEN) != 0) 184 syslog_and_die("unrecognized auth protocol: %.8s", buf); 185 186 options = KOPT_IGNORE_PROTOCOL; 187 if (do_encrypt) 188 options |= KOPT_DO_MUTUAL; 189 k_getsockinst (s, instance, sizeof(instance)); 190 status = krb_recvauth (options, 191 s, 192 &ticket, 193 "rcmd", 194 instance, 195 (struct sockaddr_in *)thataddr, 196 (struct sockaddr_in *)thisaddr, 197 &auth, 198 "", 199 schedule, 200 version); 201 if (status != KSUCCESS) 202 syslog_and_die ("recvauth: %s", krb_get_err_text(status)); 203 if (strncmp (version, KCMD_OLD_VERSION, KRB_SENDAUTH_VLEN) != 0) 204 syslog_and_die ("bad version: %s", version); 205 206 *server_username = read_str (s, USERNAME_SZ, "remote username"); 207 if (kuserok (&auth, *server_username) != 0) 208 fatal (s, NULL, "Permission denied."); 209 *cmd = read_str (s, ARG_MAX + 1, "command"); 210 211 syslog(LOG_INFO|LOG_AUTH, 212 "kerberos v4 shell from %s on %s as %s, cmd '%.80s'", 213 krb_unparse_name_long(auth.pname, auth.pinst, auth.prealm), 214 215 inet_ntoa(((struct sockaddr_in *)thataddr)->sin_addr), 216 *server_username, 217 *cmd); 218 219 memcpy (iv, auth.session, sizeof(iv)); 220 221 return 0; 222 } 223 224 #endif /* KRB4 */ 225 226 #ifdef KRB5 227 static int 228 save_krb5_creds (int s, 229 krb5_auth_context auth_context, 230 krb5_principal client) 231 232 { 233 int ret; 234 krb5_data remote_cred; 235 236 krb5_data_zero (&remote_cred); 237 ret= krb5_read_message (context, (void *)&s, &remote_cred); 238 if (ret) { 239 krb5_data_free(&remote_cred); 240 return 0; 241 } 242 if (remote_cred.length == 0) 243 return 0; 244 245 ret = krb5_cc_gen_new(context, &krb5_mcc_ops, &ccache); 246 if (ret) { 247 krb5_data_free(&remote_cred); 248 return 0; 249 } 250 251 krb5_cc_initialize(context,ccache,client); 252 ret = krb5_rd_cred2(context, auth_context, ccache, &remote_cred); 253 if(ret != 0) 254 syslog(LOG_INFO|LOG_AUTH, 255 "reading creds: %s", krb5_get_err_text(context, ret)); 256 krb5_data_free (&remote_cred); 257 if (ret) 258 return 0; 259 return 1; 260 } 261 262 static void 263 krb5_start_session (void) 264 { 265 krb5_error_code ret; 266 267 ret = krb5_cc_resolve (context, tkfile, &ccache2); 268 if (ret) { 269 krb5_cc_destroy(context, ccache); 270 return; 271 } 272 273 ret = krb5_cc_copy_cache (context, ccache, ccache2); 274 if (ret) { 275 krb5_cc_destroy(context, ccache); 276 return ; 277 } 278 279 krb5_cc_close(context, ccache2); 280 krb5_cc_destroy(context, ccache); 281 return; 282 } 283 284 static int protocol_version; 285 286 static krb5_boolean 287 match_kcmd_version(const void *data, const char *version) 288 { 289 if(strcmp(version, KCMD_NEW_VERSION) == 0) { 290 protocol_version = 2; 291 return TRUE; 292 } 293 if(strcmp(version, KCMD_OLD_VERSION) == 0) { 294 protocol_version = 1; 295 key_usage = KRB5_KU_OTHER_ENCRYPTED; 296 return TRUE; 297 } 298 return FALSE; 299 } 300 301 302 static int 303 recv_krb5_auth (int s, u_char *buf, 304 struct sockaddr *thisaddr, 305 struct sockaddr *thataddr, 306 char **client_username, 307 char **server_username, 308 char **cmd) 309 { 310 u_int32_t len; 311 krb5_auth_context auth_context = NULL; 312 krb5_ticket *ticket; 313 krb5_error_code status; 314 krb5_data cksum_data; 315 krb5_principal server; 316 317 if (memcmp (buf, "\x00\x00\x00\x13", 4) != 0) 318 return -1; 319 len = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | (buf[3]); 320 321 if (net_read(s, buf, len) != len) 322 syslog_and_die ("reading auth info: %m"); 323 if (len != sizeof(KRB5_SENDAUTH_VERSION) 324 || memcmp (buf, KRB5_SENDAUTH_VERSION, len) != 0) 325 syslog_and_die ("bad sendauth version: %.8s", buf); 326 327 status = krb5_sock_to_principal (context, 328 s, 329 "host", 330 KRB5_NT_SRV_HST, 331 &server); 332 if (status) 333 syslog_and_die ("krb5_sock_to_principal: %s", 334 krb5_get_err_text(context, status)); 335 336 status = krb5_recvauth_match_version(context, 337 &auth_context, 338 &s, 339 match_kcmd_version, 340 NULL, 341 server, 342 KRB5_RECVAUTH_IGNORE_VERSION, 343 NULL, 344 &ticket); 345 krb5_free_principal (context, server); 346 if (status) 347 syslog_and_die ("krb5_recvauth: %s", 348 krb5_get_err_text(context, status)); 349 350 *server_username = read_str (s, USERNAME_SZ, "remote username"); 351 *cmd = read_str (s, ARG_MAX + 1, "command"); 352 *client_username = read_str (s, ARG_MAX + 1, "local username"); 353 354 if(protocol_version == 2) { 355 status = krb5_auth_con_getremotesubkey(context, auth_context, 356 &keyblock); 357 if(status != 0 || keyblock == NULL) 358 syslog_and_die("failed to get remote subkey"); 359 } else if(protocol_version == 1) { 360 status = krb5_auth_con_getkey (context, auth_context, &keyblock); 361 if(status != 0 || keyblock == NULL) 362 syslog_and_die("failed to get key"); 363 } 364 if (status != 0 || keyblock == NULL) 365 syslog_and_die ("krb5_auth_con_getkey: %s", 366 krb5_get_err_text(context, status)); 367 368 status = krb5_crypto_init(context, keyblock, 0, &crypto); 369 if(status) 370 syslog_and_die("krb5_crypto_init: %s", 371 krb5_get_err_text(context, status)); 372 373 374 cksum_data.length = asprintf ((char **)&cksum_data.data, 375 "%u:%s%s", 376 ntohs(socket_get_port (thisaddr)), 377 *cmd, 378 *server_username); 379 380 status = krb5_verify_authenticator_checksum(context, 381 auth_context, 382 cksum_data.data, 383 cksum_data.length); 384 385 if (status) 386 syslog_and_die ("krb5_verify_authenticator_checksum: %s", 387 krb5_get_err_text(context, status)); 388 389 free (cksum_data.data); 390 391 if (strncmp (*client_username, "-u ", 3) == 0) { 392 do_unique_tkfile = 1; 393 memmove (*client_username, *client_username + 3, 394 strlen(*client_username) - 2); 395 } 396 397 if (strncmp (*client_username, "-U ", 3) == 0) { 398 char *end, *temp_tkfile; 399 400 do_unique_tkfile = 1; 401 if (strncmp (*client_username + 3, "FILE:", 5) == 0) { 402 temp_tkfile = tkfile; 403 } else { 404 strcpy (tkfile, "FILE:"); 405 temp_tkfile = tkfile + 5; 406 } 407 end = strchr(*client_username + 3,' '); 408 strncpy(temp_tkfile, *client_username + 3, end - *client_username - 3); 409 temp_tkfile[end - *client_username - 3] = '\0'; 410 memmove (*client_username, end + 1, strlen(end+1)+1); 411 } 412 413 kerberos_status = save_krb5_creds (s, auth_context, ticket->client); 414 415 if(!krb5_kuserok (context, 416 ticket->client, 417 *server_username)) 418 fatal (s, NULL, "Permission denied."); 419 420 if (strncmp (*cmd, "-x ", 3) == 0) { 421 do_encrypt = 1; 422 memmove (*cmd, *cmd + 3, strlen(*cmd) - 2); 423 } else { 424 if(do_encrypt) 425 fatal (s, NULL, "Encryption is required."); 426 do_encrypt = 0; 427 } 428 429 { 430 char *name; 431 432 if (krb5_unparse_name (context, ticket->client, &name) == 0) { 433 char addr_str[256]; 434 435 if (inet_ntop (thataddr->sa_family, 436 socket_get_address (thataddr), 437 addr_str, sizeof(addr_str)) == NULL) 438 strlcpy (addr_str, "unknown address", 439 sizeof(addr_str)); 440 441 syslog(LOG_INFO|LOG_AUTH, 442 "kerberos v5 shell from %s on %s as %s, cmd '%.80s'", 443 name, 444 addr_str, 445 *server_username, 446 *cmd); 447 free (name); 448 } 449 } 450 451 #if defined(DCE) 452 user_ticket = ticket; 453 #endif 454 455 return 0; 456 } 457 #endif /* KRB5 */ 458 459 static void 460 loop (int from0, int to0, 461 int to1, int from1, 462 int to2, int from2) 463 { 464 fd_set real_readset; 465 int max_fd; 466 int count = 2; 467 468 if(from0 >= FD_SETSIZE || from1 >= FD_SETSIZE || from2 >= FD_SETSIZE) 469 errx (1, "fd too large"); 470 471 #ifdef KRB5 472 if(auth_method == AUTH_KRB5 && protocol_version == 2) 473 init_ivecs(0); 474 #endif 475 476 FD_ZERO(&real_readset); 477 FD_SET(from0, &real_readset); 478 FD_SET(from1, &real_readset); 479 FD_SET(from2, &real_readset); 480 max_fd = max(from0, max(from1, from2)) + 1; 481 for (;;) { 482 int ret; 483 fd_set readset = real_readset; 484 char buf[RSH_BUFSIZ]; 485 486 ret = select (max_fd, &readset, NULL, NULL, NULL); 487 if (ret < 0) { 488 if (errno == EINTR) 489 continue; 490 else 491 syslog_and_die ("select: %m"); 492 } 493 if (FD_ISSET(from0, &readset)) { 494 ret = do_read (from0, buf, sizeof(buf), ivec_in[0]); 495 if (ret < 0) 496 syslog_and_die ("read: %m"); 497 else if (ret == 0) { 498 close (from0); 499 close (to0); 500 FD_CLR(from0, &real_readset); 501 } else 502 net_write (to0, buf, ret); 503 } 504 if (FD_ISSET(from1, &readset)) { 505 ret = read (from1, buf, sizeof(buf)); 506 if (ret < 0) 507 syslog_and_die ("read: %m"); 508 else if (ret == 0) { 509 close (from1); 510 close (to1); 511 FD_CLR(from1, &real_readset); 512 if (--count == 0) 513 exit (0); 514 } else 515 do_write (to1, buf, ret, ivec_out[0]); 516 } 517 if (FD_ISSET(from2, &readset)) { 518 ret = read (from2, buf, sizeof(buf)); 519 if (ret < 0) 520 syslog_and_die ("read: %m"); 521 else if (ret == 0) { 522 close (from2); 523 close (to2); 524 FD_CLR(from2, &real_readset); 525 if (--count == 0) 526 exit (0); 527 } else 528 do_write (to2, buf, ret, ivec_out[1]); 529 } 530 } 531 } 532 533 /* 534 * Used by `setup_copier' to create some pipe-like means of 535 * communcation. Real pipes would probably be the best thing, but 536 * then the shell doesn't understand it's talking to rshd. If 537 * socketpair doesn't work everywhere, some autoconf magic would have 538 * to be added here. 539 * 540 * If it fails creating the `pipe', it aborts by calling fatal. 541 */ 542 543 static void 544 pipe_a_like (int fd[2]) 545 { 546 if (socketpair (AF_UNIX, SOCK_STREAM, 0, fd) < 0) 547 fatal (STDOUT_FILENO, "socketpair", "Pipe creation failed."); 548 } 549 550 /* 551 * Start a child process and leave the parent copying data to and from it. */ 552 553 static void 554 setup_copier (void) 555 { 556 int p0[2], p1[2], p2[2]; 557 pid_t pid; 558 559 pipe_a_like(p0); 560 pipe_a_like(p1); 561 pipe_a_like(p2); 562 pid = fork (); 563 if (pid < 0) 564 fatal (STDOUT_FILENO, "fork", "Could not create child process."); 565 if (pid == 0) { /* child */ 566 close (p0[1]); 567 close (p1[0]); 568 close (p2[0]); 569 dup2 (p0[0], STDIN_FILENO); 570 dup2 (p1[1], STDOUT_FILENO); 571 dup2 (p2[1], STDERR_FILENO); 572 close (p0[0]); 573 close (p1[1]); 574 close (p2[1]); 575 } else { /* parent */ 576 close (p0[0]); 577 close (p1[1]); 578 close (p2[1]); 579 580 if (net_write (STDOUT_FILENO, "", 1) != 1) 581 fatal (STDOUT_FILENO, "net_write", "Write failure."); 582 583 loop (STDIN_FILENO, p0[1], 584 STDOUT_FILENO, p1[0], 585 STDERR_FILENO, p2[0]); 586 } 587 } 588 589 /* 590 * Is `port' a ``reserverd'' port? 591 */ 592 593 static int 594 is_reserved(u_short port) 595 { 596 return ntohs(port) < IPPORT_RESERVED; 597 } 598 599 /* 600 * Set the necessary part of the environment in `env'. 601 */ 602 603 static void 604 setup_environment (char ***env, const struct passwd *pwd) 605 { 606 int i, j, path; 607 char **e; 608 609 i = 0; 610 path = 0; 611 *env = NULL; 612 613 i = read_environment(_PATH_ETC_ENVIRONMENT, env); 614 e = *env; 615 for (j = 0; j < i; j++) { 616 if (!strncmp(e[j], "PATH=", 5)) { 617 path = 1; 618 } 619 } 620 621 e = *env; 622 e = realloc(e, (i + 7) * sizeof(char *)); 623 624 asprintf (&e[i++], "USER=%s", pwd->pw_name); 625 asprintf (&e[i++], "HOME=%s", pwd->pw_dir); 626 asprintf (&e[i++], "SHELL=%s", pwd->pw_shell); 627 if (! path) { 628 asprintf (&e[i++], "PATH=%s", _PATH_DEFPATH); 629 } 630 asprintf (&e[i++], "SSH_CLIENT=only_to_make_bash_happy"); 631 #if defined(DCE) 632 if (getenv("KRB5CCNAME")) 633 asprintf (&e[i++], "KRB5CCNAME=%s", getenv("KRB5CCNAME")); 634 #else 635 if (do_unique_tkfile) 636 asprintf (&e[i++], "KRB5CCNAME=%s", tkfile); 637 #endif 638 e[i++] = NULL; 639 *env = e; 640 } 641 642 static void 643 doit (void) 644 { 645 u_char buf[BUFSIZ]; 646 u_char *p; 647 struct sockaddr_storage thisaddr_ss; 648 struct sockaddr *thisaddr = (struct sockaddr *)&thisaddr_ss; 649 struct sockaddr_storage thataddr_ss; 650 struct sockaddr *thataddr = (struct sockaddr *)&thataddr_ss; 651 struct sockaddr_storage erraddr_ss; 652 struct sockaddr *erraddr = (struct sockaddr *)&erraddr_ss; 653 socklen_t thisaddr_len, thataddr_len; 654 int port; 655 int errsock = -1; 656 char *client_user, *server_user, *cmd; 657 struct passwd *pwd; 658 int s = STDIN_FILENO; 659 char **env; 660 int ret; 661 char that_host[NI_MAXHOST]; 662 663 thisaddr_len = sizeof(thisaddr_ss); 664 if (getsockname (s, thisaddr, &thisaddr_len) < 0) 665 syslog_and_die("getsockname: %m"); 666 thataddr_len = sizeof(thataddr_ss); 667 if (getpeername (s, thataddr, &thataddr_len) < 0) 668 syslog_and_die ("getpeername: %m"); 669 670 /* check for V4MAPPED addresses? */ 671 672 if (do_kerberos == 0 && !is_reserved(socket_get_port(thataddr))) 673 fatal(s, NULL, "Permission denied."); 674 675 p = buf; 676 port = 0; 677 for(;;) { 678 if (net_read (s, p, 1) != 1) 679 syslog_and_die ("reading port number: %m"); 680 if (*p == '\0') 681 break; 682 else if (isdigit(*p)) 683 port = port * 10 + *p - '0'; 684 else 685 syslog_and_die ("non-digit in port number: %c", *p); 686 } 687 688 if (do_kerberos == 0 && !is_reserved(htons(port))) 689 fatal(s, NULL, "Permission denied."); 690 691 if (port) { 692 int priv_port = IPPORT_RESERVED - 1; 693 694 /* 695 * There's no reason to require a ``privileged'' port number 696 * here, but for some reason the brain dead rsh clients 697 * do... :-( 698 */ 699 700 erraddr->sa_family = thataddr->sa_family; 701 socket_set_address_and_port (erraddr, 702 socket_get_address (thataddr), 703 htons(port)); 704 705 /* 706 * we only do reserved port for IPv4 707 */ 708 709 if (erraddr->sa_family == AF_INET) 710 errsock = rresvport (&priv_port); 711 else 712 errsock = socket (erraddr->sa_family, SOCK_STREAM, 0); 713 if (errsock < 0) 714 syslog_and_die ("socket: %m"); 715 if (connect (errsock, 716 erraddr, 717 socket_sockaddr_size (erraddr)) < 0) { 718 syslog (LOG_WARNING, "connect: %m"); 719 close (errsock); 720 } 721 } 722 723 if(do_kerberos) { 724 if (net_read (s, buf, 4) != 4) 725 syslog_and_die ("reading auth info: %m"); 726 727 #ifdef KRB4 728 if ((do_kerberos & DO_KRB4) && 729 recv_krb4_auth (s, buf, thisaddr, thataddr, 730 &client_user, 731 &server_user, 732 &cmd) == 0) 733 auth_method = AUTH_KRB4; 734 else 735 #endif /* KRB4 */ 736 #ifdef KRB5 737 if((do_kerberos & DO_KRB5) && 738 recv_krb5_auth (s, buf, thisaddr, thataddr, 739 &client_user, 740 &server_user, 741 &cmd) == 0) 742 auth_method = AUTH_KRB5; 743 else 744 #endif /* KRB5 */ 745 syslog_and_die ("unrecognized auth protocol: %x %x %x %x", 746 buf[0], buf[1], buf[2], buf[3]); 747 } else { 748 if(recv_bsd_auth (s, buf, 749 (struct sockaddr_in *)thisaddr, 750 (struct sockaddr_in *)thataddr, 751 &client_user, 752 &server_user, 753 &cmd) == 0) { 754 auth_method = AUTH_BROKEN; 755 if(do_vacuous) { 756 printf("Remote host requires Kerberos authentication\n"); 757 exit(0); 758 } 759 } else 760 syslog_and_die("recv_bsd_auth failed"); 761 } 762 763 #if defined(DCE) && defined(_AIX) 764 esetenv("AUTHSTATE", "DCE", 1); 765 #endif 766 767 pwd = getpwnam (server_user); 768 if (pwd == NULL) 769 fatal (s, NULL, "Login incorrect."); 770 771 if (*pwd->pw_shell == '\0') 772 pwd->pw_shell = _PATH_BSHELL; 773 774 if (pwd->pw_uid != 0 && access (_PATH_NOLOGIN, F_OK) == 0) 775 fatal (s, NULL, "Login disabled."); 776 777 778 ret = getnameinfo_verified (thataddr, thataddr_len, 779 that_host, sizeof(that_host), 780 NULL, 0, 0); 781 if (ret) 782 fatal (s, NULL, "getnameinfo: %s", gai_strerror(ret)); 783 784 if (login_access(pwd, that_host) == 0) { 785 syslog(LOG_NOTICE, "Kerberos rsh denied to %s from %s", 786 server_user, that_host); 787 fatal(s, NULL, "Permission denied."); 788 } 789 790 #ifdef HAVE_GETSPNAM 791 { 792 struct spwd *sp; 793 long today; 794 795 sp = getspnam(server_user); 796 if (sp != NULL) { 797 today = time(0)/(24L * 60 * 60); 798 if (sp->sp_expire > 0) 799 if (today > sp->sp_expire) 800 fatal(s, NULL, "Account has expired."); 801 } 802 } 803 #endif 804 805 806 #ifdef KRB5 807 { 808 int fd; 809 810 if (!do_unique_tkfile) 811 snprintf(tkfile,sizeof(tkfile),"FILE:/tmp/krb5cc_%u",pwd->pw_uid); 812 else if (*tkfile=='\0') { 813 snprintf(tkfile,sizeof(tkfile),"FILE:/tmp/krb5cc_XXXXXX"); 814 fd = mkstemp(tkfile+5); 815 close(fd); 816 unlink(tkfile+5); 817 } 818 819 if (kerberos_status) 820 krb5_start_session(); 821 } 822 chown(tkfile + 5, pwd->pw_uid, -1); 823 824 #if defined(DCE) 825 if (kerberos_status) { 826 esetenv("KRB5CCNAME", tkfile, 1); 827 dfspag = krb5_dfs_pag(context, kerberos_status, user_ticket->client, server_user); 828 } 829 #endif 830 831 #endif 832 833 #ifdef HAVE_SETLOGIN 834 if (setlogin(pwd->pw_name) < 0) 835 syslog(LOG_ERR, "setlogin() failed: %m"); 836 #endif 837 838 #ifdef HAVE_SETPCRED 839 if (setpcred (pwd->pw_name, NULL) == -1) 840 syslog(LOG_ERR, "setpcred() failure: %m"); 841 #endif /* HAVE_SETPCRED */ 842 843 if (initgroups (pwd->pw_name, pwd->pw_gid) < 0) 844 fatal (s, "initgroups", "Login incorrect."); 845 846 if (setgid(pwd->pw_gid) < 0) 847 fatal (s, "setgid", "Login incorrect."); 848 849 if (setuid (pwd->pw_uid) < 0) 850 fatal (s, "setuid", "Login incorrect."); 851 852 if (chdir (pwd->pw_dir) < 0) 853 fatal (s, "chdir", "Remote directory."); 854 855 if (errsock >= 0) { 856 if (dup2 (errsock, STDERR_FILENO) < 0) 857 fatal (s, "dup2", "Cannot dup stderr."); 858 close (errsock); 859 } 860 861 setup_environment (&env, pwd); 862 863 if (do_encrypt) { 864 setup_copier (); 865 } else { 866 if (net_write (s, "", 1) != 1) 867 fatal (s, "net_write", "write failed"); 868 } 869 870 #if defined(KRB4) || defined(KRB5) 871 if(k_hasafs()) { 872 char cell[64]; 873 874 if(do_newpag) 875 k_setpag(); 876 #ifdef KRB4 877 if (k_afs_cell_of_file (pwd->pw_dir, cell, sizeof(cell)) == 0) 878 krb_afslog_uid_home (cell, NULL, pwd->pw_uid, pwd->pw_dir); 879 krb_afslog_uid_home(NULL, NULL, pwd->pw_uid, pwd->pw_dir); 880 #endif 881 882 #ifdef KRB5 883 /* XXX */ 884 if (kerberos_status) { 885 krb5_ccache ccache; 886 krb5_error_code status; 887 888 status = krb5_cc_resolve (context, tkfile, &ccache); 889 if (!status) { 890 if (k_afs_cell_of_file (pwd->pw_dir, cell, sizeof(cell)) == 0) 891 krb5_afslog_uid_home(context, ccache, cell, NULL, 892 pwd->pw_uid, pwd->pw_dir); 893 krb5_afslog_uid_home(context, ccache, NULL, NULL, 894 pwd->pw_uid, pwd->pw_dir); 895 krb5_cc_close (context, ccache); 896 } 897 } 898 #endif /* KRB5 */ 899 } 900 #endif /* KRB5 || KRB4 */ 901 execle (pwd->pw_shell, pwd->pw_shell, "-c", cmd, NULL, env); 902 err(1, "exec %s", pwd->pw_shell); 903 } 904 905 struct getargs args[] = { 906 { NULL, 'a', arg_flag, &do_addr_verify }, 907 { "keepalive", 'n', arg_negative_flag, &do_keepalive }, 908 { "inetd", 'i', arg_negative_flag, &do_inetd, 909 "Not started from inetd" }, 910 #if defined(KRB4) || defined(KRB5) 911 { "kerberos", 'k', arg_flag, &do_kerberos, 912 "Implement kerberised services" }, 913 { "encrypt", 'x', arg_flag, &do_encrypt, 914 "Implement encrypted service" }, 915 #endif 916 { "rhosts", 'l', arg_negative_flag, &do_rhosts, 917 "Don't check users .rhosts" }, 918 { "port", 'p', arg_string, &port_str, "Use this port", 919 "port" }, 920 { "vacuous", 'v', arg_flag, &do_vacuous, 921 "Don't accept non-kerberised connections" }, 922 #if defined(KRB4) || defined(KRB5) 923 { NULL, 'P', arg_negative_flag, &do_newpag, 924 "Don't put process in new PAG" }, 925 #endif 926 /* compatibility flag: */ 927 { NULL, 'L', arg_flag, &do_log }, 928 { "version", 0, arg_flag, &do_version }, 929 { "help", 0, arg_flag, &do_help } 930 }; 931 932 static void 933 usage (int ret) 934 { 935 if(isatty(STDIN_FILENO)) 936 arg_printusage (args, 937 sizeof(args) / sizeof(args[0]), 938 NULL, 939 ""); 940 else 941 syslog (LOG_ERR, "Usage: %s [-ikxlvPL] [-p port]", getprogname()); 942 exit (ret); 943 } 944 945 946 int 947 main(int argc, char **argv) 948 { 949 int optind = 0; 950 int on = 1; 951 952 setprogname (argv[0]); 953 roken_openlog ("rshd", LOG_ODELAY | LOG_PID, LOG_AUTH); 954 955 if (getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, 956 &optind)) 957 usage(1); 958 959 if(do_help) 960 usage (0); 961 962 if (do_version) { 963 print_version(NULL); 964 exit(0); 965 } 966 967 #if defined(KRB4) || defined(KRB5) 968 if (do_encrypt) 969 do_kerberos = 1; 970 971 if(do_kerberos) 972 do_kerberos = DO_KRB4 | DO_KRB5; 973 #endif 974 975 if (do_keepalive && 976 setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, (char *)&on, 977 sizeof(on)) < 0) 978 syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m"); 979 980 /* set SO_LINGER? */ 981 982 #ifdef KRB5 983 if((do_kerberos & DO_KRB5) && krb5_init_context (&context) != 0) 984 do_kerberos &= ~DO_KRB5; 985 #endif 986 987 if (!do_inetd) { 988 int error; 989 struct addrinfo *ai = NULL, hints; 990 char portstr[NI_MAXSERV]; 991 992 memset (&hints, 0, sizeof(hints)); 993 hints.ai_flags = AI_PASSIVE; 994 hints.ai_socktype = SOCK_STREAM; 995 hints.ai_family = PF_UNSPEC; 996 997 if(port_str != NULL) { 998 error = getaddrinfo (NULL, port_str, &hints, &ai); 999 if (error) 1000 errx (1, "getaddrinfo: %s", gai_strerror (error)); 1001 } 1002 if (ai == NULL) { 1003 #if defined(KRB4) || defined(KRB5) 1004 if (do_kerberos) { 1005 if (do_encrypt) { 1006 error = getaddrinfo(NULL, "ekshell", &hints, &ai); 1007 if(error == EAI_NONAME) { 1008 snprintf(portstr, sizeof(portstr), "%d", 545); 1009 error = getaddrinfo(NULL, portstr, &hints, &ai); 1010 } 1011 if(error) 1012 errx (1, "getaddrinfo: %s", gai_strerror (error)); 1013 } else { 1014 error = getaddrinfo(NULL, "kshell", &hints, &ai); 1015 if(error == EAI_NONAME) { 1016 snprintf(portstr, sizeof(portstr), "%d", 544); 1017 error = getaddrinfo(NULL, portstr, &hints, &ai); 1018 } 1019 if(error) 1020 errx (1, "getaddrinfo: %s", gai_strerror (error)); 1021 } 1022 } else 1023 #endif 1024 { 1025 error = getaddrinfo(NULL, "shell", &hints, &ai); 1026 if(error == EAI_NONAME) { 1027 snprintf(portstr, sizeof(portstr), "%d", 514); 1028 error = getaddrinfo(NULL, portstr, &hints, &ai); 1029 } 1030 if(error) 1031 errx (1, "getaddrinfo: %s", gai_strerror (error)); 1032 } 1033 } 1034 mini_inetd_addrinfo (ai); 1035 freeaddrinfo(ai); 1036 } 1037 1038 signal (SIGPIPE, SIG_IGN); 1039 1040 doit (); 1041 return 0; 1042 } 1043