1 /* 2 * Copyright (c) 1997 - 2004 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: rsh.c 21516 2007-07-12 12:47:23Z lha $"); 36 37 enum auth_method auth_method; 38 #if defined(KRB4) || defined(KRB5) 39 int do_encrypt = -1; 40 #endif 41 #ifdef KRB5 42 int do_unique_tkfile = 0; 43 char *unique_tkfile = NULL; 44 char tkfile[MAXPATHLEN]; 45 int do_forward = -1; 46 int do_forwardable = -1; 47 krb5_context context; 48 krb5_keyblock *keyblock; 49 krb5_crypto crypto; 50 #endif 51 #ifdef KRB4 52 des_key_schedule schedule; 53 des_cblock iv; 54 #endif 55 int sock_debug = 0; 56 57 #ifdef KRB4 58 static int use_v4 = -1; 59 #endif 60 #ifdef KRB5 61 static int use_v5 = -1; 62 #endif 63 #if defined(KRB4) || defined(KRB5) 64 static int use_only_broken = 0; 65 #else 66 static int use_only_broken = 1; 67 #endif 68 static int use_broken = 1; 69 static char *port_str; 70 static const char *user; 71 static int do_version; 72 static int do_help; 73 static int do_errsock = 1; 74 #ifdef KRB5 75 static char *protocol_version_str; 76 static int protocol_version = 2; 77 #endif 78 79 /* 80 * 81 */ 82 83 static int input = 1; /* Read from stdin */ 84 85 static int 86 rsh_loop (int s, int errsock) 87 { 88 fd_set real_readset; 89 int count = 1; 90 91 #ifdef KRB5 92 if(auth_method == AUTH_KRB5 && protocol_version == 2) 93 init_ivecs(1, errsock != -1); 94 #endif 95 96 if (s >= FD_SETSIZE || (errsock != -1 && errsock >= FD_SETSIZE)) 97 errx (1, "fd too large"); 98 99 FD_ZERO(&real_readset); 100 FD_SET(s, &real_readset); 101 if (errsock != -1) { 102 FD_SET(errsock, &real_readset); 103 ++count; 104 } 105 if(input) 106 FD_SET(STDIN_FILENO, &real_readset); 107 108 for (;;) { 109 int ret; 110 fd_set readset; 111 char buf[RSH_BUFSIZ]; 112 113 readset = real_readset; 114 ret = select (max(s, errsock) + 1, &readset, NULL, NULL, NULL); 115 if (ret < 0) { 116 if (errno == EINTR) 117 continue; 118 else 119 err (1, "select"); 120 } 121 if (FD_ISSET(s, &readset)) { 122 ret = do_read (s, buf, sizeof(buf), ivec_in[0]); 123 if (ret < 0) 124 err (1, "read"); 125 else if (ret == 0) { 126 close (s); 127 FD_CLR(s, &real_readset); 128 if (--count == 0) 129 return 0; 130 } else 131 net_write (STDOUT_FILENO, buf, ret); 132 } 133 if (errsock != -1 && FD_ISSET(errsock, &readset)) { 134 ret = do_read (errsock, buf, sizeof(buf), ivec_in[1]); 135 if (ret < 0) 136 err (1, "read"); 137 else if (ret == 0) { 138 close (errsock); 139 FD_CLR(errsock, &real_readset); 140 if (--count == 0) 141 return 0; 142 } else 143 net_write (STDERR_FILENO, buf, ret); 144 } 145 if (FD_ISSET(STDIN_FILENO, &readset)) { 146 ret = read (STDIN_FILENO, buf, sizeof(buf)); 147 if (ret < 0) 148 err (1, "read"); 149 else if (ret == 0) { 150 close (STDIN_FILENO); 151 FD_CLR(STDIN_FILENO, &real_readset); 152 shutdown (s, SHUT_WR); 153 } else 154 do_write (s, buf, ret, ivec_out[0]); 155 } 156 } 157 } 158 159 #ifdef KRB4 160 static int 161 send_krb4_auth(int s, 162 struct sockaddr *thisaddr, 163 struct sockaddr *thataddr, 164 const char *hostname, 165 const char *remote_user, 166 const char *local_user, 167 size_t cmd_len, 168 const char *cmd) 169 { 170 KTEXT_ST text; 171 CREDENTIALS cred; 172 MSG_DAT msg; 173 int status; 174 size_t len; 175 176 /* the normal default for krb4 should be to disable encryption */ 177 status = krb_sendauth ((do_encrypt == 1) ? KOPT_DO_MUTUAL : 0, 178 s, &text, "rcmd", 179 (char *)hostname, krb_realmofhost (hostname), 180 getpid(), &msg, &cred, schedule, 181 (struct sockaddr_in *)thisaddr, 182 (struct sockaddr_in *)thataddr, 183 KCMD_OLD_VERSION); 184 if (status != KSUCCESS) { 185 warnx("%s: %s", hostname, krb_get_err_text(status)); 186 return 1; 187 } 188 memcpy (iv, cred.session, sizeof(iv)); 189 190 len = strlen(remote_user) + 1; 191 if (net_write (s, remote_user, len) != len) { 192 warn("write"); 193 return 1; 194 } 195 if (net_write (s, cmd, cmd_len) != cmd_len) { 196 warn("write"); 197 return 1; 198 } 199 return 0; 200 } 201 #endif /* KRB4 */ 202 203 #ifdef KRB5 204 /* 205 * Send forward information on `s' for host `hostname', them being 206 * forwardable themselves if `forwardable' 207 */ 208 209 static int 210 krb5_forward_cred (krb5_auth_context auth_context, 211 int s, 212 const char *hostname, 213 int forwardable) 214 { 215 krb5_error_code ret; 216 krb5_ccache ccache; 217 krb5_creds creds; 218 krb5_kdc_flags flags; 219 krb5_data out_data; 220 krb5_principal principal; 221 222 memset (&creds, 0, sizeof(creds)); 223 224 ret = krb5_cc_default (context, &ccache); 225 if (ret) { 226 warnx ("could not forward creds: krb5_cc_default: %s", 227 krb5_get_err_text (context, ret)); 228 return 1; 229 } 230 231 ret = krb5_cc_get_principal (context, ccache, &principal); 232 if (ret) { 233 warnx ("could not forward creds: krb5_cc_get_principal: %s", 234 krb5_get_err_text (context, ret)); 235 return 1; 236 } 237 238 creds.client = principal; 239 240 ret = krb5_build_principal (context, 241 &creds.server, 242 strlen(principal->realm), 243 principal->realm, 244 "krbtgt", 245 principal->realm, 246 NULL); 247 248 if (ret) { 249 warnx ("could not forward creds: krb5_build_principal: %s", 250 krb5_get_err_text (context, ret)); 251 return 1; 252 } 253 254 creds.times.endtime = 0; 255 256 flags.i = 0; 257 flags.b.forwarded = 1; 258 flags.b.forwardable = forwardable; 259 260 ret = krb5_get_forwarded_creds (context, 261 auth_context, 262 ccache, 263 flags.i, 264 hostname, 265 &creds, 266 &out_data); 267 if (ret) { 268 warnx ("could not forward creds: krb5_get_forwarded_creds: %s", 269 krb5_get_err_text (context, ret)); 270 return 1; 271 } 272 273 ret = krb5_write_message (context, 274 (void *)&s, 275 &out_data); 276 krb5_data_free (&out_data); 277 278 if (ret) 279 warnx ("could not forward creds: krb5_write_message: %s", 280 krb5_get_err_text (context, ret)); 281 return 0; 282 } 283 284 static int sendauth_version_error; 285 286 static int 287 send_krb5_auth(int s, 288 struct sockaddr *thisaddr, 289 struct sockaddr *thataddr, 290 const char *hostname, 291 const char *remote_user, 292 const char *local_user, 293 size_t cmd_len, 294 const char *cmd) 295 { 296 krb5_principal server; 297 krb5_data cksum_data; 298 int status; 299 size_t len; 300 krb5_auth_context auth_context = NULL; 301 const char *protocol_string = NULL; 302 krb5_flags ap_opts; 303 char *str; 304 305 status = krb5_sname_to_principal(context, 306 hostname, 307 "host", 308 KRB5_NT_SRV_HST, 309 &server); 310 if (status) { 311 warnx ("%s: %s", hostname, krb5_get_err_text(context, status)); 312 return 1; 313 } 314 315 if(do_encrypt == -1) { 316 krb5_appdefault_boolean(context, NULL, 317 krb5_principal_get_realm(context, server), 318 "encrypt", 319 FALSE, 320 &do_encrypt); 321 } 322 323 cksum_data.length = asprintf (&str, 324 "%u:%s%s%s", 325 ntohs(socket_get_port(thataddr)), 326 do_encrypt ? "-x " : "", 327 cmd, 328 remote_user); 329 if (str == NULL) { 330 warnx ("%s: failed to allocate command", hostname); 331 return 1; 332 } 333 cksum_data.data = str; 334 335 ap_opts = 0; 336 337 if(do_encrypt) 338 ap_opts |= AP_OPTS_MUTUAL_REQUIRED; 339 340 switch(protocol_version) { 341 case 2: 342 ap_opts |= AP_OPTS_USE_SUBKEY; 343 protocol_string = KCMD_NEW_VERSION; 344 break; 345 case 1: 346 protocol_string = KCMD_OLD_VERSION; 347 key_usage = KRB5_KU_OTHER_ENCRYPTED; 348 break; 349 default: 350 abort(); 351 } 352 353 status = krb5_sendauth (context, 354 &auth_context, 355 &s, 356 protocol_string, 357 NULL, 358 server, 359 ap_opts, 360 &cksum_data, 361 NULL, 362 NULL, 363 NULL, 364 NULL, 365 NULL); 366 367 /* do this while we have a principal */ 368 if(do_forward == -1 || do_forwardable == -1) { 369 krb5_const_realm realm = krb5_principal_get_realm(context, server); 370 if (do_forwardable == -1) 371 krb5_appdefault_boolean(context, NULL, realm, 372 "forwardable", FALSE, 373 &do_forwardable); 374 if (do_forward == -1) 375 krb5_appdefault_boolean(context, NULL, realm, 376 "forward", FALSE, 377 &do_forward); 378 } 379 380 krb5_free_principal(context, server); 381 krb5_data_free(&cksum_data); 382 383 if (status) { 384 if(status == KRB5_SENDAUTH_REJECTED && 385 protocol_version == 2 && protocol_version_str == NULL) 386 sendauth_version_error = 1; 387 else 388 krb5_warn(context, status, "%s", hostname); 389 return 1; 390 } 391 392 status = krb5_auth_con_getlocalsubkey (context, auth_context, &keyblock); 393 if(keyblock == NULL) 394 status = krb5_auth_con_getkey (context, auth_context, &keyblock); 395 if (status) { 396 warnx ("krb5_auth_con_getkey: %s", krb5_get_err_text(context, status)); 397 return 1; 398 } 399 400 status = krb5_auth_con_setaddrs_from_fd (context, 401 auth_context, 402 &s); 403 if (status) { 404 warnx("krb5_auth_con_setaddrs_from_fd: %s", 405 krb5_get_err_text(context, status)); 406 return(1); 407 } 408 409 status = krb5_crypto_init(context, keyblock, 0, &crypto); 410 if(status) { 411 warnx ("krb5_crypto_init: %s", krb5_get_err_text(context, status)); 412 return 1; 413 } 414 415 len = strlen(remote_user) + 1; 416 if (net_write (s, remote_user, len) != len) { 417 warn ("write"); 418 return 1; 419 } 420 if (do_encrypt && net_write (s, "-x ", 3) != 3) { 421 warn ("write"); 422 return 1; 423 } 424 if (net_write (s, cmd, cmd_len) != cmd_len) { 425 warn ("write"); 426 return 1; 427 } 428 429 if (do_unique_tkfile) { 430 if (net_write (s, tkfile, strlen(tkfile)) != strlen(tkfile)) { 431 warn ("write"); 432 return 1; 433 } 434 } 435 len = strlen(local_user) + 1; 436 if (net_write (s, local_user, len) != len) { 437 warn ("write"); 438 return 1; 439 } 440 441 if (!do_forward 442 || krb5_forward_cred (auth_context, s, hostname, do_forwardable)) { 443 /* Empty forwarding info */ 444 445 u_char zero[4] = {0, 0, 0, 0}; 446 write (s, &zero, 4); 447 } 448 krb5_auth_con_free (context, auth_context); 449 return 0; 450 } 451 452 #endif /* KRB5 */ 453 454 static int 455 send_broken_auth(int s, 456 struct sockaddr *thisaddr, 457 struct sockaddr *thataddr, 458 const char *hostname, 459 const char *remote_user, 460 const char *local_user, 461 size_t cmd_len, 462 const char *cmd) 463 { 464 size_t len; 465 466 len = strlen(local_user) + 1; 467 if (net_write (s, local_user, len) != len) { 468 warn ("write"); 469 return 1; 470 } 471 len = strlen(remote_user) + 1; 472 if (net_write (s, remote_user, len) != len) { 473 warn ("write"); 474 return 1; 475 } 476 if (net_write (s, cmd, cmd_len) != cmd_len) { 477 warn ("write"); 478 return 1; 479 } 480 return 0; 481 } 482 483 static int 484 proto (int s, int errsock, 485 const char *hostname, const char *local_user, const char *remote_user, 486 const char *cmd, size_t cmd_len, 487 int (*auth_func)(int s, 488 struct sockaddr *this, struct sockaddr *that, 489 const char *hostname, const char *remote_user, 490 const char *local_user, size_t cmd_len, 491 const char *cmd)) 492 { 493 int errsock2; 494 char buf[BUFSIZ]; 495 char *p; 496 size_t len; 497 char reply; 498 struct sockaddr_storage thisaddr_ss; 499 struct sockaddr *thisaddr = (struct sockaddr *)&thisaddr_ss; 500 struct sockaddr_storage thataddr_ss; 501 struct sockaddr *thataddr = (struct sockaddr *)&thataddr_ss; 502 struct sockaddr_storage erraddr_ss; 503 struct sockaddr *erraddr = (struct sockaddr *)&erraddr_ss; 504 socklen_t addrlen; 505 int ret; 506 507 addrlen = sizeof(thisaddr_ss); 508 if (getsockname (s, thisaddr, &addrlen) < 0) { 509 warn ("getsockname(%s)", hostname); 510 return 1; 511 } 512 addrlen = sizeof(thataddr_ss); 513 if (getpeername (s, thataddr, &addrlen) < 0) { 514 warn ("getpeername(%s)", hostname); 515 return 1; 516 } 517 518 if (errsock != -1) { 519 520 addrlen = sizeof(erraddr_ss); 521 if (getsockname (errsock, erraddr, &addrlen) < 0) { 522 warn ("getsockname"); 523 return 1; 524 } 525 526 if (listen (errsock, 1) < 0) { 527 warn ("listen"); 528 return 1; 529 } 530 531 p = buf; 532 snprintf (p, sizeof(buf), "%u", 533 ntohs(socket_get_port(erraddr))); 534 len = strlen(buf) + 1; 535 if(net_write (s, buf, len) != len) { 536 warn ("write"); 537 close (errsock); 538 return 1; 539 } 540 541 542 for (;;) { 543 fd_set fdset; 544 545 if (errsock >= FD_SETSIZE || s >= FD_SETSIZE) 546 errx (1, "fd too large"); 547 548 FD_ZERO(&fdset); 549 FD_SET(errsock, &fdset); 550 FD_SET(s, &fdset); 551 552 ret = select (max(errsock, s) + 1, &fdset, NULL, NULL, NULL); 553 if (ret < 0) { 554 if (errno == EINTR) 555 continue; 556 warn ("select"); 557 close (errsock); 558 return 1; 559 } 560 if (FD_ISSET(errsock, &fdset)) { 561 errsock2 = accept (errsock, NULL, NULL); 562 close (errsock); 563 if (errsock2 < 0) { 564 warn ("accept"); 565 return 1; 566 } 567 break; 568 } 569 570 /* 571 * there should not arrive any data on this fd so if it's 572 * readable it probably indicates that the other side when 573 * away. 574 */ 575 576 if (FD_ISSET(s, &fdset)) { 577 warnx ("socket closed"); 578 close (errsock); 579 errsock2 = -1; 580 break; 581 } 582 } 583 } else { 584 if (net_write (s, "0", 2) != 2) { 585 warn ("write"); 586 return 1; 587 } 588 errsock2 = -1; 589 } 590 591 if ((*auth_func)(s, thisaddr, thataddr, hostname, 592 remote_user, local_user, 593 cmd_len, cmd)) { 594 close (errsock2); 595 return 1; 596 } 597 598 ret = net_read (s, &reply, 1); 599 if (ret < 0) { 600 warn ("read"); 601 close (errsock2); 602 return 1; 603 } else if (ret == 0) { 604 warnx ("unexpected EOF from %s", hostname); 605 close (errsock2); 606 return 1; 607 } 608 if (reply != 0) { 609 610 warnx ("Error from rshd at %s:", hostname); 611 612 while ((ret = read (s, buf, sizeof(buf))) > 0) 613 write (STDOUT_FILENO, buf, ret); 614 write (STDOUT_FILENO,"\n",1); 615 close (errsock2); 616 return 1; 617 } 618 619 if (sock_debug) { 620 int one = 1; 621 if (setsockopt(s, SOL_SOCKET, SO_DEBUG, (void *)&one, sizeof(one)) < 0) 622 warn("setsockopt remote"); 623 if (errsock2 != -1 && 624 setsockopt(errsock2, SOL_SOCKET, SO_DEBUG, 625 (void *)&one, sizeof(one)) < 0) 626 warn("setsockopt stderr"); 627 } 628 629 return rsh_loop (s, errsock2); 630 } 631 632 /* 633 * Return in `res' a copy of the concatenation of `argc, argv' into 634 * malloced space. */ 635 636 static size_t 637 construct_command (char **res, int argc, char **argv) 638 { 639 int i; 640 size_t len = 0; 641 char *tmp; 642 643 for (i = 0; i < argc; ++i) 644 len += strlen(argv[i]) + 1; 645 len = max (1, len); 646 tmp = malloc (len); 647 if (tmp == NULL) 648 errx (1, "malloc %lu failed", (unsigned long)len); 649 650 *tmp = '\0'; 651 for (i = 0; i < argc - 1; ++i) { 652 strlcat (tmp, argv[i], len); 653 strlcat (tmp, " ", len); 654 } 655 if (argc > 0) 656 strlcat (tmp, argv[argc-1], len); 657 *res = tmp; 658 return len; 659 } 660 661 static char * 662 print_addr (const struct sockaddr *sa) 663 { 664 char addr_str[256]; 665 char *res; 666 const char *as = NULL; 667 668 if(sa->sa_family == AF_INET) 669 as = inet_ntop (sa->sa_family, &((struct sockaddr_in*)sa)->sin_addr, 670 addr_str, sizeof(addr_str)); 671 #ifdef HAVE_INET6 672 else if(sa->sa_family == AF_INET6) 673 as = inet_ntop (sa->sa_family, &((struct sockaddr_in6*)sa)->sin6_addr, 674 addr_str, sizeof(addr_str)); 675 #endif 676 if(as == NULL) 677 return NULL; 678 res = strdup(as); 679 if (res == NULL) 680 errx (1, "malloc: out of memory"); 681 return res; 682 } 683 684 static int 685 doit_broken (int argc, 686 char **argv, 687 int hostindex, 688 struct addrinfo *ai, 689 const char *remote_user, 690 const char *local_user, 691 int priv_socket1, 692 int priv_socket2, 693 const char *cmd, 694 size_t cmd_len) 695 { 696 struct addrinfo *a; 697 698 if (connect (priv_socket1, ai->ai_addr, ai->ai_addrlen) < 0) { 699 int save_errno = errno; 700 701 close(priv_socket1); 702 close(priv_socket2); 703 704 for (a = ai->ai_next; a != NULL; a = a->ai_next) { 705 pid_t pid; 706 char *adr = print_addr(a->ai_addr); 707 if(adr == NULL) 708 continue; 709 710 pid = fork(); 711 if (pid < 0) 712 err (1, "fork"); 713 else if(pid == 0) { 714 char **new_argv; 715 int i = 0; 716 717 new_argv = malloc((argc + 2) * sizeof(*new_argv)); 718 if (new_argv == NULL) 719 errx (1, "malloc: out of memory"); 720 new_argv[i] = argv[i]; 721 ++i; 722 if (hostindex == i) 723 new_argv[i++] = adr; 724 new_argv[i++] = "-K"; 725 for(; i <= argc; ++i) 726 new_argv[i] = argv[i - 1]; 727 if (hostindex > 1) 728 new_argv[hostindex + 1] = adr; 729 new_argv[argc + 1] = NULL; 730 execv(PATH_RSH, new_argv); 731 err(1, "execv(%s)", PATH_RSH); 732 } else { 733 int status; 734 free(adr); 735 736 while(waitpid(pid, &status, 0) < 0) 737 ; 738 if(WIFEXITED(status) && WEXITSTATUS(status) == 0) 739 return 0; 740 } 741 } 742 errno = save_errno; 743 warn("%s", argv[hostindex]); 744 return 1; 745 } else { 746 int ret; 747 748 ret = proto (priv_socket1, priv_socket2, 749 argv[hostindex], 750 local_user, remote_user, 751 cmd, cmd_len, 752 send_broken_auth); 753 return ret; 754 } 755 } 756 757 #if defined(KRB4) || defined(KRB5) 758 static int 759 doit (const char *hostname, 760 struct addrinfo *ai, 761 const char *remote_user, 762 const char *local_user, 763 const char *cmd, 764 size_t cmd_len, 765 int (*auth_func)(int s, 766 struct sockaddr *this, struct sockaddr *that, 767 const char *hostname, const char *remote_user, 768 const char *local_user, size_t cmd_len, 769 const char *cmd)) 770 { 771 int error; 772 struct addrinfo *a; 773 int socketfailed = 1; 774 int ret; 775 776 for (a = ai; a != NULL; a = a->ai_next) { 777 int s; 778 int errsock; 779 780 s = socket (a->ai_family, a->ai_socktype, a->ai_protocol); 781 if (s < 0) 782 continue; 783 socketfailed = 0; 784 if (connect (s, a->ai_addr, a->ai_addrlen) < 0) { 785 char addr[128]; 786 if(getnameinfo(a->ai_addr, a->ai_addrlen, 787 addr, sizeof(addr), NULL, 0, NI_NUMERICHOST) == 0) 788 warn ("connect(%s [%s])", hostname, addr); 789 else 790 warn ("connect(%s)", hostname); 791 close (s); 792 continue; 793 } 794 if (do_errsock) { 795 struct addrinfo *ea, *eai; 796 struct addrinfo hints; 797 798 memset (&hints, 0, sizeof(hints)); 799 hints.ai_socktype = a->ai_socktype; 800 hints.ai_protocol = a->ai_protocol; 801 hints.ai_family = a->ai_family; 802 hints.ai_flags = AI_PASSIVE; 803 804 errsock = -1; 805 806 error = getaddrinfo (NULL, "0", &hints, &eai); 807 if (error) 808 errx (1, "getaddrinfo: %s", gai_strerror(error)); 809 for (ea = eai; ea != NULL; ea = ea->ai_next) { 810 errsock = socket (ea->ai_family, ea->ai_socktype, 811 ea->ai_protocol); 812 if (errsock < 0) 813 continue; 814 if (bind (errsock, ea->ai_addr, ea->ai_addrlen) < 0) 815 err (1, "bind"); 816 break; 817 } 818 if (errsock < 0) 819 err (1, "socket"); 820 freeaddrinfo (eai); 821 } else 822 errsock = -1; 823 824 ret = proto (s, errsock, 825 hostname, 826 local_user, remote_user, 827 cmd, cmd_len, auth_func); 828 close (s); 829 return ret; 830 } 831 if(socketfailed) 832 warnx ("failed to contact %s", hostname); 833 return -1; 834 } 835 #endif /* KRB4 || KRB5 */ 836 837 struct getargs args[] = { 838 #ifdef KRB4 839 { "krb4", '4', arg_flag, &use_v4, "Use Kerberos V4" }, 840 #endif 841 #ifdef KRB5 842 { "krb5", '5', arg_flag, &use_v5, "Use Kerberos V5" }, 843 { "forward", 'f', arg_flag, &do_forward, "Forward credentials [krb5]"}, 844 { "forwardable", 'F', arg_flag, &do_forwardable, 845 "Forward forwardable credentials [krb5]" }, 846 { NULL, 'G', arg_negative_flag,&do_forward, "Don't forward credentials" }, 847 { "unique", 'u', arg_flag, &do_unique_tkfile, 848 "Use unique remote credentials cache [krb5]" }, 849 { "tkfile", 'U', arg_string, &unique_tkfile, 850 "Specifies remote credentials cache [krb5]" }, 851 { "protocol", 'P', arg_string, &protocol_version_str, 852 "Protocol version [krb5]", "protocol" }, 853 #endif 854 { "broken", 'K', arg_flag, &use_only_broken, "Use only priv port" }, 855 #if defined(KRB4) || defined(KRB5) 856 { "encrypt", 'x', arg_flag, &do_encrypt, "Encrypt connection" }, 857 { NULL, 'z', arg_negative_flag, &do_encrypt, 858 "Don't encrypt connection", NULL }, 859 #endif 860 { NULL, 'd', arg_flag, &sock_debug, "Enable socket debugging" }, 861 { "input", 'n', arg_negative_flag, &input, "Close stdin" }, 862 { "port", 'p', arg_string, &port_str, "Use this port", 863 "port" }, 864 { "user", 'l', arg_string, &user, "Run as this user", "login" }, 865 { "stderr", 'e', arg_negative_flag, &do_errsock, "Don't open stderr"}, 866 #ifdef KRB5 867 #endif 868 { "version", 0, arg_flag, &do_version, NULL }, 869 { "help", 0, arg_flag, &do_help, NULL } 870 }; 871 872 static void 873 usage (int ret) 874 { 875 arg_printusage (args, 876 sizeof(args) / sizeof(args[0]), 877 NULL, 878 "[login@]host [command]"); 879 exit (ret); 880 } 881 882 /* 883 * 884 */ 885 886 int 887 main(int argc, char **argv) 888 { 889 int priv_port1, priv_port2; 890 int priv_socket1, priv_socket2; 891 int argindex = 0; 892 int error; 893 struct addrinfo hints, *ai; 894 int ret = 1; 895 char *cmd; 896 char *tmp; 897 size_t cmd_len; 898 const char *local_user; 899 char *host = NULL; 900 int host_index = -1; 901 #ifdef KRB5 902 int status; 903 #endif 904 uid_t uid; 905 906 priv_port1 = priv_port2 = IPPORT_RESERVED-1; 907 priv_socket1 = rresvport(&priv_port1); 908 priv_socket2 = rresvport(&priv_port2); 909 uid = getuid (); 910 if (setuid (uid) || (uid != 0 && setuid(0) == 0)) 911 err (1, "setuid"); 912 913 setprogname (argv[0]); 914 915 if (argc >= 2 && argv[1][0] != '-') { 916 host = argv[host_index = 1]; 917 argindex = 1; 918 } 919 920 if (getarg (args, sizeof(args) / sizeof(args[0]), argc, argv, 921 &argindex)) 922 usage (1); 923 924 if (do_help) 925 usage (0); 926 927 if (do_version) { 928 print_version (NULL); 929 return 0; 930 } 931 932 #ifdef KRB5 933 if(protocol_version_str != NULL) { 934 if(strcasecmp(protocol_version_str, "N") == 0) 935 protocol_version = 2; 936 else if(strcasecmp(protocol_version_str, "O") == 0) 937 protocol_version = 1; 938 else { 939 char *end; 940 int v; 941 v = strtol(protocol_version_str, &end, 0); 942 if(*end != '\0' || (v != 1 && v != 2)) { 943 errx(1, "unknown protocol version \"%s\"", 944 protocol_version_str); 945 } 946 protocol_version = v; 947 } 948 } 949 950 status = krb5_init_context (&context); 951 if (status) { 952 if(use_v5 == 1) 953 errx(1, "krb5_init_context failed: %d", status); 954 else 955 use_v5 = 0; 956 } 957 958 /* request for forwardable on the command line means we should 959 also forward */ 960 if (do_forwardable == 1) 961 do_forward = 1; 962 963 #endif 964 965 #if defined(KRB4) && defined(KRB5) 966 if(use_v4 == -1 && use_v5 == 1) 967 use_v4 = 0; 968 if(use_v5 == -1 && use_v4 == 1) 969 use_v5 = 0; 970 #endif 971 972 if (use_only_broken) { 973 #ifdef KRB4 974 use_v4 = 0; 975 #endif 976 #ifdef KRB5 977 use_v5 = 0; 978 #endif 979 } 980 981 if(priv_socket1 < 0) { 982 if (use_only_broken) 983 errx (1, "unable to bind reserved port: is rsh setuid root?"); 984 use_broken = 0; 985 } 986 987 #if defined(KRB4) || defined(KRB5) 988 if (do_encrypt == 1 && use_only_broken) 989 errx (1, "encryption not supported with old style authentication"); 990 #endif 991 992 993 994 #ifdef KRB5 995 if (do_unique_tkfile && unique_tkfile != NULL) 996 errx (1, "Only one of -u and -U allowed."); 997 998 if (do_unique_tkfile) 999 strlcpy(tkfile,"-u ", sizeof(tkfile)); 1000 else if (unique_tkfile != NULL) { 1001 if (strchr(unique_tkfile,' ') != NULL) { 1002 warnx("Space is not allowed in tkfilename"); 1003 usage(1); 1004 } 1005 do_unique_tkfile = 1; 1006 snprintf (tkfile, sizeof(tkfile), "-U %s ", unique_tkfile); 1007 } 1008 #endif 1009 1010 if (host == NULL) { 1011 if (argc - argindex < 1) 1012 usage (1); 1013 else 1014 host = argv[host_index = argindex++]; 1015 } 1016 1017 if((tmp = strchr(host, '@')) != NULL) { 1018 *tmp++ = '\0'; 1019 user = host; 1020 host = tmp; 1021 } 1022 1023 if (argindex == argc) { 1024 close (priv_socket1); 1025 close (priv_socket2); 1026 argv[0] = "rlogin"; 1027 execvp ("rlogin", argv); 1028 err (1, "execvp rlogin"); 1029 } 1030 1031 local_user = get_default_username (); 1032 if (local_user == NULL) 1033 errx (1, "who are you?"); 1034 1035 if (user == NULL) 1036 user = local_user; 1037 1038 cmd_len = construct_command(&cmd, argc - argindex, argv + argindex); 1039 1040 /* 1041 * Try all different authentication methods 1042 */ 1043 1044 #ifdef KRB5 1045 if (ret && use_v5) { 1046 memset (&hints, 0, sizeof(hints)); 1047 hints.ai_socktype = SOCK_STREAM; 1048 hints.ai_protocol = IPPROTO_TCP; 1049 1050 if(port_str == NULL) { 1051 error = getaddrinfo(host, "kshell", &hints, &ai); 1052 if(error == EAI_NONAME) 1053 error = getaddrinfo(host, "544", &hints, &ai); 1054 } else 1055 error = getaddrinfo(host, port_str, &hints, &ai); 1056 1057 if(error) 1058 errx (1, "getaddrinfo: %s", gai_strerror(error)); 1059 1060 auth_method = AUTH_KRB5; 1061 again: 1062 ret = doit (host, ai, user, local_user, cmd, cmd_len, 1063 send_krb5_auth); 1064 if(ret != 0 && sendauth_version_error && 1065 protocol_version == 2) { 1066 protocol_version = 1; 1067 goto again; 1068 } 1069 freeaddrinfo(ai); 1070 } 1071 #endif 1072 #ifdef KRB4 1073 if (ret && use_v4) { 1074 memset (&hints, 0, sizeof(hints)); 1075 hints.ai_socktype = SOCK_STREAM; 1076 hints.ai_protocol = IPPROTO_TCP; 1077 1078 if(port_str == NULL) { 1079 if(do_encrypt) { 1080 error = getaddrinfo(host, "ekshell", &hints, &ai); 1081 if(error == EAI_NONAME) 1082 error = getaddrinfo(host, "545", &hints, &ai); 1083 } else { 1084 error = getaddrinfo(host, "kshell", &hints, &ai); 1085 if(error == EAI_NONAME) 1086 error = getaddrinfo(host, "544", &hints, &ai); 1087 } 1088 } else 1089 error = getaddrinfo(host, port_str, &hints, &ai); 1090 1091 if(error) 1092 errx (1, "getaddrinfo: %s", gai_strerror(error)); 1093 auth_method = AUTH_KRB4; 1094 ret = doit (host, ai, user, local_user, cmd, cmd_len, 1095 send_krb4_auth); 1096 freeaddrinfo(ai); 1097 } 1098 #endif 1099 if (ret && use_broken) { 1100 memset (&hints, 0, sizeof(hints)); 1101 hints.ai_socktype = SOCK_STREAM; 1102 hints.ai_protocol = IPPROTO_TCP; 1103 1104 if(port_str == NULL) { 1105 error = getaddrinfo(host, "shell", &hints, &ai); 1106 if(error == EAI_NONAME) 1107 error = getaddrinfo(host, "514", &hints, &ai); 1108 } else 1109 error = getaddrinfo(host, port_str, &hints, &ai); 1110 1111 if(error) 1112 errx (1, "getaddrinfo: %s", gai_strerror(error)); 1113 1114 auth_method = AUTH_BROKEN; 1115 ret = doit_broken (argc, argv, host_index, ai, 1116 user, local_user, 1117 priv_socket1, 1118 do_errsock ? priv_socket2 : -1, 1119 cmd, cmd_len); 1120 freeaddrinfo(ai); 1121 } 1122 free(cmd); 1123 return ret; 1124 } 1125