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