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