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