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