1 /* 2 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * All rights reserved 5 * Ssh client program. This program can be used to log into a remote machine. 6 * The software supports strong authentication, encryption, and forwarding 7 * of X11, TCP/IP, and authentication connections. 8 * 9 * As far as I am concerned, the code I have written for this software 10 * can be used freely for any purpose. Any derived versions of this 11 * software must be clearly marked as such, and if the derived work is 12 * incompatible with the protocol description in the RFC file, it must be 13 * called by a name other than "ssh" or "Secure Shell". 14 * 15 * Copyright (c) 1999 Niels Provos. All rights reserved. 16 * 17 * Modified to work with SSL by Niels Provos <provos@citi.umich.edu> 18 * in Canada (German citizen). 19 * 20 * Redistribution and use in source and binary forms, with or without 21 * modification, are permitted provided that the following conditions 22 * are met: 23 * 1. Redistributions of source code must retain the above copyright 24 * notice, this list of conditions and the following disclaimer. 25 * 2. Redistributions in binary form must reproduce the above copyright 26 * notice, this list of conditions and the following disclaimer in the 27 * documentation and/or other materials provided with the distribution. 28 * 29 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 30 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 31 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 32 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 33 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 34 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 38 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 39 */ 40 41 #include "includes.h" 42 RCSID("$OpenBSD: ssh.c,v 1.65 2000/09/07 20:40:30 markus Exp $"); 43 RCSID("$FreeBSD$"); 44 45 #include <openssl/evp.h> 46 #include <openssl/dsa.h> 47 #include <openssl/rsa.h> 48 49 #include "xmalloc.h" 50 #include "ssh.h" 51 #include "packet.h" 52 #include "buffer.h" 53 #include "readconf.h" 54 #include "uidswap.h" 55 56 #include "ssh2.h" 57 #include "compat.h" 58 #include "channels.h" 59 #include "key.h" 60 #include "authfd.h" 61 #include "authfile.h" 62 63 extern char *__progname; 64 65 /* Flag indicating whether IPv4 or IPv6. This can be set on the command line. 66 Default value is AF_UNSPEC means both IPv4 and IPv6. */ 67 int IPv4or6 = AF_UNSPEC; 68 69 /* Flag indicating whether debug mode is on. This can be set on the command line. */ 70 int debug_flag = 0; 71 72 /* Flag indicating whether a tty should be allocated */ 73 int tty_flag = 0; 74 75 /* don't exec a shell */ 76 int no_shell_flag = 0; 77 int no_tty_flag = 0; 78 79 /* 80 * Flag indicating that nothing should be read from stdin. This can be set 81 * on the command line. 82 */ 83 int stdin_null_flag = 0; 84 85 /* 86 * Flag indicating that ssh should fork after authentication. This is useful 87 * so that the pasphrase can be entered manually, and then ssh goes to the 88 * background. 89 */ 90 int fork_after_authentication_flag = 0; 91 92 /* 93 * General data structure for command line options and options configurable 94 * in configuration files. See readconf.h. 95 */ 96 Options options; 97 98 /* 99 * Name of the host we are connecting to. This is the name given on the 100 * command line, or the HostName specified for the user-supplied name in a 101 * configuration file. 102 */ 103 char *host; 104 105 /* socket address the host resolves to */ 106 struct sockaddr_storage hostaddr; 107 108 /* 109 * Flag to indicate that we have received a window change signal which has 110 * not yet been processed. This will cause a message indicating the new 111 * window size to be sent to the server a little later. This is volatile 112 * because this is updated in a signal handler. 113 */ 114 volatile int received_window_change_signal = 0; 115 116 /* Value of argv[0] (set in the main program). */ 117 char *av0; 118 119 /* Flag indicating whether we have a valid host private key loaded. */ 120 int host_private_key_loaded = 0; 121 122 /* Host private key. */ 123 RSA *host_private_key = NULL; 124 125 /* Original real UID. */ 126 uid_t original_real_uid; 127 128 /* command to be executed */ 129 Buffer command; 130 131 /* Prints a help message to the user. This function never returns. */ 132 133 void 134 usage() 135 { 136 fprintf(stderr, "Usage: %s [options] host [command]\n", av0); 137 fprintf(stderr, "Options:\n"); 138 fprintf(stderr, " -l user Log in using this user name.\n"); 139 fprintf(stderr, " -n Redirect input from /dev/null.\n"); 140 fprintf(stderr, " -A Enable authentication agent forwarding.\n"); 141 fprintf(stderr, " -a Disable authentication agent forwarding.\n"); 142 #ifdef AFS 143 fprintf(stderr, " -k Disable Kerberos ticket and AFS token forwarding.\n"); 144 #endif /* AFS */ 145 fprintf(stderr, " -X Enable X11 connection forwarding.\n"); 146 fprintf(stderr, " -x Disable X11 connection forwarding.\n"); 147 fprintf(stderr, " -i file Identity for RSA authentication (default: ~/.ssh/identity).\n"); 148 fprintf(stderr, " -t Tty; allocate a tty even if command is given.\n"); 149 fprintf(stderr, " -T Do not allocate a tty.\n"); 150 fprintf(stderr, " -v Verbose; display verbose debugging messages.\n"); 151 fprintf(stderr, " -V Display version number only.\n"); 152 fprintf(stderr, " -P Don't allocate a privileged port.\n"); 153 fprintf(stderr, " -q Quiet; don't display any warning messages.\n"); 154 fprintf(stderr, " -f Fork into background after authentication.\n"); 155 fprintf(stderr, " -e char Set escape character; ``none'' = disable (default: ~).\n"); 156 157 fprintf(stderr, " -c cipher Select encryption algorithm: " 158 "``3des'', " 159 "``blowfish''\n"); 160 fprintf(stderr, " -p port Connect to this port. Server must be on the same port.\n"); 161 fprintf(stderr, " -L listen-port:host:port Forward local port to remote address\n"); 162 fprintf(stderr, " -R listen-port:host:port Forward remote port to local address\n"); 163 fprintf(stderr, " These cause %s to listen for connections on a port, and\n", av0); 164 fprintf(stderr, " forward them to the other side by connecting to host:port.\n"); 165 fprintf(stderr, " -C Enable compression.\n"); 166 fprintf(stderr, " -N Do not execute a shell or command.\n"); 167 fprintf(stderr, " -g Allow remote hosts to connect to forwarded ports.\n"); 168 fprintf(stderr, " -4 Use IPv4 only.\n"); 169 fprintf(stderr, " -6 Use IPv6 only.\n"); 170 fprintf(stderr, " -2 Force protocol version 2.\n"); 171 fprintf(stderr, " -o 'option' Process the option as if it was read from a configuration file.\n"); 172 exit(1); 173 } 174 175 /* 176 * Connects to the given host using rsh (or prints an error message and exits 177 * if rsh is not available). This function never returns. 178 */ 179 void 180 rsh_connect(char *host, char *user, Buffer * command) 181 { 182 char *args[10]; 183 int i; 184 185 log("Using rsh. WARNING: Connection will not be encrypted."); 186 /* Build argument list for rsh. */ 187 i = 0; 188 #ifndef _PATH_RSH 189 #define _PATH_RSH "/usr/bin/rsh" 190 #endif 191 args[i++] = _PATH_RSH; 192 /* host may have to come after user on some systems */ 193 args[i++] = host; 194 if (user) { 195 args[i++] = "-l"; 196 args[i++] = user; 197 } 198 if (buffer_len(command) > 0) { 199 buffer_append(command, "\0", 1); 200 args[i++] = buffer_ptr(command); 201 } 202 args[i++] = NULL; 203 if (debug_flag) { 204 for (i = 0; args[i]; i++) { 205 if (i != 0) 206 fprintf(stderr, " "); 207 fprintf(stderr, "%s", args[i]); 208 } 209 fprintf(stderr, "\n"); 210 } 211 execv(_PATH_RSH, args); 212 perror(_PATH_RSH); 213 exit(1); 214 } 215 216 int ssh_session(void); 217 int ssh_session2(void); 218 219 /* 220 * Main program for the ssh client. 221 */ 222 int 223 main(int ac, char **av) 224 { 225 int i, opt, optind, exit_status, ok; 226 u_short fwd_port, fwd_host_port; 227 char *optarg, *cp, buf[256]; 228 struct stat st; 229 struct passwd *pw, pwcopy; 230 int dummy; 231 uid_t original_effective_uid; 232 233 /* 234 * Save the original real uid. It will be needed later (uid-swapping 235 * may clobber the real uid). 236 */ 237 original_real_uid = getuid(); 238 original_effective_uid = geteuid(); 239 240 /* If we are installed setuid root be careful to not drop core. */ 241 if (original_real_uid != original_effective_uid) { 242 struct rlimit rlim; 243 rlim.rlim_cur = rlim.rlim_max = 0; 244 if (setrlimit(RLIMIT_CORE, &rlim) < 0) 245 fatal("setrlimit failed: %.100s", strerror(errno)); 246 } 247 /* 248 * Use uid-swapping to give up root privileges for the duration of 249 * option processing. We will re-instantiate the rights when we are 250 * ready to create the privileged port, and will permanently drop 251 * them when the port has been created (actually, when the connection 252 * has been made, as we may need to create the port several times). 253 */ 254 temporarily_use_uid(original_real_uid); 255 256 /* 257 * Set our umask to something reasonable, as some files are created 258 * with the default umask. This will make them world-readable but 259 * writable only by the owner, which is ok for all files for which we 260 * don't set the modes explicitly. 261 */ 262 umask(022); 263 264 /* Save our own name. */ 265 av0 = av[0]; 266 267 /* Initialize option structure to indicate that no values have been set. */ 268 initialize_options(&options); 269 270 /* Parse command-line arguments. */ 271 host = NULL; 272 273 /* If program name is not one of the standard names, use it as host name. */ 274 if (strchr(av0, '/')) 275 cp = strrchr(av0, '/') + 1; 276 else 277 cp = av0; 278 if (strcmp(cp, "rsh") && strcmp(cp, "ssh") && strcmp(cp, "rlogin") && 279 strcmp(cp, "slogin") && strcmp(cp, "remsh")) 280 host = cp; 281 282 for (optind = 1; optind < ac; optind++) { 283 if (av[optind][0] != '-') { 284 if (host) 285 break; 286 if ((cp = strchr(av[optind], '@'))) { 287 if(cp == av[optind]) 288 usage(); 289 options.user = av[optind]; 290 *cp = '\0'; 291 host = ++cp; 292 } else 293 host = av[optind]; 294 continue; 295 } 296 opt = av[optind][1]; 297 if (!opt) 298 usage(); 299 if (strchr("eilcpLRo", opt)) { /* options with arguments */ 300 optarg = av[optind] + 2; 301 if (strcmp(optarg, "") == 0) { 302 if (optind >= ac - 1) 303 usage(); 304 optarg = av[++optind]; 305 } 306 } else { 307 if (av[optind][2]) 308 usage(); 309 optarg = NULL; 310 } 311 switch (opt) { 312 case '2': 313 options.protocol = SSH_PROTO_2; 314 break; 315 case '4': 316 IPv4or6 = AF_INET; 317 break; 318 case '6': 319 IPv4or6 = AF_INET6; 320 break; 321 case 'n': 322 stdin_null_flag = 1; 323 break; 324 case 'f': 325 fork_after_authentication_flag = 1; 326 stdin_null_flag = 1; 327 break; 328 case 'x': 329 options.forward_x11 = 0; 330 break; 331 case 'X': 332 options.forward_x11 = 1; 333 break; 334 case 'g': 335 options.gateway_ports = 1; 336 break; 337 case 'P': 338 options.use_privileged_port = 0; 339 break; 340 case 'a': 341 options.forward_agent = 0; 342 break; 343 case 'A': 344 options.forward_agent = 1; 345 break; 346 #ifdef AFS 347 case 'k': 348 options.krb4_tgt_passing = 0; 349 options.krb5_tgt_passing = 0; 350 options.afs_token_passing = 0; 351 break; 352 #endif 353 case 'i': 354 if (stat(optarg, &st) < 0) { 355 fprintf(stderr, "Warning: Identity file %s does not exist.\n", 356 optarg); 357 break; 358 } 359 if (options.num_identity_files >= SSH_MAX_IDENTITY_FILES) 360 fatal("Too many identity files specified (max %d)", 361 SSH_MAX_IDENTITY_FILES); 362 options.identity_files[options.num_identity_files++] = 363 xstrdup(optarg); 364 break; 365 case 't': 366 tty_flag = 1; 367 break; 368 case 'v': 369 case 'V': 370 fprintf(stderr, "SSH Version %s, protocol versions %d.%d/%d.%d.\n", 371 SSH_VERSION, 372 PROTOCOL_MAJOR_1, PROTOCOL_MINOR_1, 373 PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2); 374 fprintf(stderr, "Compiled with SSL (0x%8.8lx).\n", SSLeay()); 375 if (opt == 'V') 376 exit(0); 377 debug_flag = 1; 378 options.log_level = SYSLOG_LEVEL_DEBUG; 379 break; 380 case 'q': 381 options.log_level = SYSLOG_LEVEL_QUIET; 382 break; 383 case 'e': 384 if (optarg[0] == '^' && optarg[2] == 0 && 385 (unsigned char) optarg[1] >= 64 && (unsigned char) optarg[1] < 128) 386 options.escape_char = (unsigned char) optarg[1] & 31; 387 else if (strlen(optarg) == 1) 388 options.escape_char = (unsigned char) optarg[0]; 389 else if (strcmp(optarg, "none") == 0) 390 options.escape_char = -2; 391 else { 392 fprintf(stderr, "Bad escape character '%s'.\n", optarg); 393 exit(1); 394 } 395 break; 396 case 'c': 397 if (ciphers_valid(optarg)) { 398 /* SSH2 only */ 399 options.ciphers = xstrdup(optarg); 400 options.cipher = SSH_CIPHER_ILLEGAL; 401 } else { 402 /* SSH1 only */ 403 options.cipher = cipher_number(optarg); 404 if (options.cipher == -1) { 405 fprintf(stderr, "Unknown cipher type '%s'\n", optarg); 406 exit(1); 407 } 408 } 409 break; 410 case 'p': 411 options.port = atoi(optarg); 412 break; 413 case 'l': 414 options.user = optarg; 415 break; 416 case 'R': 417 if (sscanf(optarg, "%hu/%255[^/]/%hu", &fwd_port, buf, 418 &fwd_host_port) != 3 && 419 sscanf(optarg, "%hu:%255[^:]:%hu", &fwd_port, buf, 420 &fwd_host_port) != 3) { 421 fprintf(stderr, "Bad forwarding specification '%s'.\n", optarg); 422 usage(); 423 /* NOTREACHED */ 424 } 425 add_remote_forward(&options, fwd_port, buf, fwd_host_port); 426 break; 427 case 'L': 428 if (sscanf(optarg, "%hu/%255[^/]/%hu", &fwd_port, buf, 429 &fwd_host_port) != 3 && 430 sscanf(optarg, "%hu:%255[^:]:%hu", &fwd_port, buf, 431 &fwd_host_port) != 3) { 432 fprintf(stderr, "Bad forwarding specification '%s'.\n", optarg); 433 usage(); 434 /* NOTREACHED */ 435 } 436 add_local_forward(&options, fwd_port, buf, fwd_host_port); 437 break; 438 case 'C': 439 options.compression = 1; 440 break; 441 case 'N': 442 no_shell_flag = 1; 443 no_tty_flag = 1; 444 break; 445 case 'T': 446 no_tty_flag = 1; 447 break; 448 case 'o': 449 dummy = 1; 450 if (process_config_line(&options, host ? host : "", optarg, 451 "command-line", 0, &dummy) != 0) 452 exit(1); 453 break; 454 default: 455 usage(); 456 } 457 } 458 459 /* Check that we got a host name. */ 460 if (!host) 461 usage(); 462 463 SSLeay_add_all_algorithms(); 464 465 /* Initialize the command to execute on remote host. */ 466 buffer_init(&command); 467 468 /* 469 * Save the command to execute on the remote host in a buffer. There 470 * is no limit on the length of the command, except by the maximum 471 * packet size. Also sets the tty flag if there is no command. 472 */ 473 if (optind == ac) { 474 /* No command specified - execute shell on a tty. */ 475 tty_flag = 1; 476 } else { 477 /* A command has been specified. Store it into the 478 buffer. */ 479 for (i = optind; i < ac; i++) { 480 if (i > optind) 481 buffer_append(&command, " ", 1); 482 buffer_append(&command, av[i], strlen(av[i])); 483 } 484 } 485 486 /* Cannot fork to background if no command. */ 487 if (fork_after_authentication_flag && buffer_len(&command) == 0 && !no_shell_flag) 488 fatal("Cannot fork into background without a command to execute."); 489 490 /* Allocate a tty by default if no command specified. */ 491 if (buffer_len(&command) == 0) 492 tty_flag = 1; 493 494 /* Do not allocate a tty if stdin is not a tty. */ 495 if (!isatty(fileno(stdin))) { 496 if (tty_flag) 497 fprintf(stderr, "Pseudo-terminal will not be allocated because stdin is not a terminal.\n"); 498 tty_flag = 0; 499 } 500 /* force */ 501 if (no_tty_flag) 502 tty_flag = 0; 503 504 /* Get user data. */ 505 pw = getpwuid(original_real_uid); 506 if (!pw) { 507 fprintf(stderr, "You don't exist, go away!\n"); 508 exit(1); 509 } 510 /* Take a copy of the returned structure. */ 511 memset(&pwcopy, 0, sizeof(pwcopy)); 512 pwcopy.pw_name = xstrdup(pw->pw_name); 513 pwcopy.pw_passwd = xstrdup(pw->pw_passwd); 514 pwcopy.pw_uid = pw->pw_uid; 515 pwcopy.pw_gid = pw->pw_gid; 516 pwcopy.pw_class = xstrdup(pw->pw_class); 517 pwcopy.pw_dir = xstrdup(pw->pw_dir); 518 pwcopy.pw_shell = xstrdup(pw->pw_shell); 519 pwcopy.pw_class = xstrdup(pw->pw_class); 520 pwcopy.pw_expire = pw->pw_expire; 521 pwcopy.pw_change = pw->pw_change; 522 pw = &pwcopy; 523 524 /* Initialize "log" output. Since we are the client all output 525 actually goes to the terminal. */ 526 log_init(av[0], options.log_level, SYSLOG_FACILITY_USER, 0); 527 528 /* Read per-user configuration file. */ 529 snprintf(buf, sizeof buf, "%.100s/%.100s", pw->pw_dir, SSH_USER_CONFFILE); 530 read_config_file(buf, host, &options); 531 532 /* Read systemwide configuration file. */ 533 read_config_file(HOST_CONFIG_FILE, host, &options); 534 535 /* Fill configuration defaults. */ 536 fill_default_options(&options); 537 538 /* reinit */ 539 log_init(av[0], options.log_level, SYSLOG_FACILITY_USER, 0); 540 541 /* check if RSA support exists */ 542 if ((options.protocol & SSH_PROTO_1) && 543 rsa_alive() == 0) { 544 log("%s: no RSA support in libssl and libcrypto. See ssl(8).", 545 __progname); 546 log("Disabling protocol version 1"); 547 options.protocol &= ~ (SSH_PROTO_1|SSH_PROTO_1_PREFERRED); 548 } 549 if (! options.protocol & (SSH_PROTO_1|SSH_PROTO_2)) { 550 fprintf(stderr, "%s: No protocol version available.\n", 551 __progname); 552 exit(1); 553 } 554 555 if (options.user == NULL) 556 options.user = xstrdup(pw->pw_name); 557 558 if (options.hostname != NULL) 559 host = options.hostname; 560 561 /* Find canonic host name. */ 562 if (strchr(host, '.') == 0) { 563 struct addrinfo hints; 564 struct addrinfo *ai = NULL; 565 int errgai; 566 memset(&hints, 0, sizeof(hints)); 567 hints.ai_family = IPv4or6; 568 hints.ai_flags = AI_CANONNAME; 569 hints.ai_socktype = SOCK_STREAM; 570 errgai = getaddrinfo(host, NULL, &hints, &ai); 571 if (errgai == 0) { 572 if (ai->ai_canonname != NULL) 573 host = xstrdup(ai->ai_canonname); 574 freeaddrinfo(ai); 575 } 576 } 577 /* Disable rhosts authentication if not running as root. */ 578 if (original_effective_uid != 0 || !options.use_privileged_port) { 579 options.rhosts_authentication = 0; 580 options.rhosts_rsa_authentication = 0; 581 } 582 /* 583 * If using rsh has been selected, exec it now (without trying 584 * anything else). Note that we must release privileges first. 585 */ 586 if (options.use_rsh) { 587 /* 588 * Restore our superuser privileges. This must be done 589 * before permanently setting the uid. 590 */ 591 restore_uid(); 592 593 /* Switch to the original uid permanently. */ 594 permanently_set_uid(original_real_uid); 595 596 /* Execute rsh. */ 597 rsh_connect(host, options.user, &command); 598 fatal("rsh_connect returned"); 599 } 600 /* Restore our superuser privileges. */ 601 restore_uid(); 602 603 /* 604 * Open a connection to the remote host. This needs root privileges 605 * if rhosts_{rsa_}authentication is enabled. 606 */ 607 608 ok = ssh_connect(host, &hostaddr, options.port, 609 options.connection_attempts, 610 !options.rhosts_authentication && 611 !options.rhosts_rsa_authentication, 612 original_real_uid, 613 options.proxy_command); 614 615 /* 616 * If we successfully made the connection, load the host private key 617 * in case we will need it later for combined rsa-rhosts 618 * authentication. This must be done before releasing extra 619 * privileges, because the file is only readable by root. 620 */ 621 if (ok && (options.protocol & SSH_PROTO_1)) { 622 Key k; 623 host_private_key = RSA_new(); 624 k.type = KEY_RSA; 625 k.rsa = host_private_key; 626 if (load_private_key(HOST_KEY_FILE, "", &k, NULL)) 627 host_private_key_loaded = 1; 628 } 629 /* 630 * Get rid of any extra privileges that we may have. We will no 631 * longer need them. Also, extra privileges could make it very hard 632 * to read identity files and other non-world-readable files from the 633 * user's home directory if it happens to be on a NFS volume where 634 * root is mapped to nobody. 635 */ 636 637 /* 638 * Note that some legacy systems need to postpone the following call 639 * to permanently_set_uid() until the private hostkey is destroyed 640 * with RSA_free(). Otherwise the calling user could ptrace() the 641 * process, read the private hostkey and impersonate the host. 642 * OpenBSD does not allow ptracing of setuid processes. 643 */ 644 permanently_set_uid(original_real_uid); 645 646 /* 647 * Now that we are back to our own permissions, create ~/.ssh 648 * directory if it doesn\'t already exist. 649 */ 650 snprintf(buf, sizeof buf, "%.100s/%.100s", pw->pw_dir, SSH_USER_DIR); 651 if (stat(buf, &st) < 0) 652 if (mkdir(buf, 0700) < 0) 653 error("Could not create directory '%.200s'.", buf); 654 655 /* Check if the connection failed, and try "rsh" if appropriate. */ 656 if (!ok) { 657 if (options.port != 0) 658 log("Secure connection to %.100s on port %hu refused%.100s.", 659 host, options.port, 660 options.fallback_to_rsh ? "; reverting to insecure method" : ""); 661 else 662 log("Secure connection to %.100s refused%.100s.", host, 663 options.fallback_to_rsh ? "; reverting to insecure method" : ""); 664 665 if (options.fallback_to_rsh) { 666 rsh_connect(host, options.user, &command); 667 fatal("rsh_connect returned"); 668 } 669 exit(1); 670 } 671 /* Expand ~ in options.identity_files. */ 672 /* XXX mem-leaks */ 673 for (i = 0; i < options.num_identity_files; i++) 674 options.identity_files[i] = 675 tilde_expand_filename(options.identity_files[i], original_real_uid); 676 for (i = 0; i < options.num_identity_files2; i++) 677 options.identity_files2[i] = 678 tilde_expand_filename(options.identity_files2[i], original_real_uid); 679 /* Expand ~ in known host file names. */ 680 options.system_hostfile = tilde_expand_filename(options.system_hostfile, 681 original_real_uid); 682 options.user_hostfile = tilde_expand_filename(options.user_hostfile, 683 original_real_uid); 684 options.system_hostfile2 = tilde_expand_filename(options.system_hostfile2, 685 original_real_uid); 686 options.user_hostfile2 = tilde_expand_filename(options.user_hostfile2, 687 original_real_uid); 688 689 /* Log into the remote system. This never returns if the login fails. */ 690 ssh_login(host_private_key_loaded, host_private_key, 691 host, (struct sockaddr *)&hostaddr, original_real_uid); 692 693 /* We no longer need the host private key. Clear it now. */ 694 if (host_private_key_loaded) 695 RSA_free(host_private_key); /* Destroys contents safely */ 696 697 exit_status = compat20 ? ssh_session2() : ssh_session(); 698 packet_close(); 699 return exit_status; 700 } 701 702 void 703 x11_get_proto(char *proto, int proto_len, char *data, int data_len) 704 { 705 char line[512]; 706 FILE *f; 707 int got_data = 0, i; 708 709 if (options.xauth_location) { 710 /* Try to get Xauthority information for the display. */ 711 snprintf(line, sizeof line, "%.100s list %.200s 2>/dev/null", 712 options.xauth_location, getenv("DISPLAY")); 713 f = popen(line, "r"); 714 if (f && fgets(line, sizeof(line), f) && 715 sscanf(line, "%*s %s %s", proto, data) == 2) 716 got_data = 1; 717 if (f) 718 pclose(f); 719 } 720 /* 721 * If we didn't get authentication data, just make up some 722 * data. The forwarding code will check the validity of the 723 * response anyway, and substitute this data. The X11 724 * server, however, will ignore this fake data and use 725 * whatever authentication mechanisms it was using otherwise 726 * for the local connection. 727 */ 728 if (!got_data) { 729 u_int32_t rand = 0; 730 731 strlcpy(proto, "MIT-MAGIC-COOKIE-1", proto_len); 732 for (i = 0; i < 16; i++) { 733 if (i % 4 == 0) 734 rand = arc4random(); 735 snprintf(data + 2 * i, data_len - 2 * i, "%02x", rand & 0xff); 736 rand >>= 8; 737 } 738 } 739 } 740 741 int 742 ssh_session(void) 743 { 744 int type; 745 int i; 746 int plen; 747 int interactive = 0; 748 int have_tty = 0; 749 struct winsize ws; 750 int authfd; 751 char *cp; 752 753 /* Enable compression if requested. */ 754 if (options.compression) { 755 debug("Requesting compression at level %d.", options.compression_level); 756 757 if (options.compression_level < 1 || options.compression_level > 9) 758 fatal("Compression level must be from 1 (fast) to 9 (slow, best)."); 759 760 /* Send the request. */ 761 packet_start(SSH_CMSG_REQUEST_COMPRESSION); 762 packet_put_int(options.compression_level); 763 packet_send(); 764 packet_write_wait(); 765 type = packet_read(&plen); 766 if (type == SSH_SMSG_SUCCESS) 767 packet_start_compression(options.compression_level); 768 else if (type == SSH_SMSG_FAILURE) 769 log("Warning: Remote host refused compression."); 770 else 771 packet_disconnect("Protocol error waiting for compression response."); 772 } 773 /* Allocate a pseudo tty if appropriate. */ 774 if (tty_flag) { 775 debug("Requesting pty."); 776 777 /* Start the packet. */ 778 packet_start(SSH_CMSG_REQUEST_PTY); 779 780 /* Store TERM in the packet. There is no limit on the 781 length of the string. */ 782 cp = getenv("TERM"); 783 if (!cp) 784 cp = ""; 785 packet_put_string(cp, strlen(cp)); 786 787 /* Store window size in the packet. */ 788 if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) < 0) 789 memset(&ws, 0, sizeof(ws)); 790 packet_put_int(ws.ws_row); 791 packet_put_int(ws.ws_col); 792 packet_put_int(ws.ws_xpixel); 793 packet_put_int(ws.ws_ypixel); 794 795 /* Store tty modes in the packet. */ 796 tty_make_modes(fileno(stdin)); 797 798 /* Send the packet, and wait for it to leave. */ 799 packet_send(); 800 packet_write_wait(); 801 802 /* Read response from the server. */ 803 type = packet_read(&plen); 804 if (type == SSH_SMSG_SUCCESS) { 805 interactive = 1; 806 have_tty = 1; 807 } else if (type == SSH_SMSG_FAILURE) 808 log("Warning: Remote host failed or refused to allocate a pseudo tty."); 809 else 810 packet_disconnect("Protocol error waiting for pty request response."); 811 } 812 /* Request X11 forwarding if enabled and DISPLAY is set. */ 813 if (options.forward_x11 && getenv("DISPLAY") != NULL) { 814 char proto[512], data[512]; 815 /* Get reasonable local authentication information. */ 816 x11_get_proto(proto, sizeof proto, data, sizeof data); 817 /* Request forwarding with authentication spoofing. */ 818 debug("Requesting X11 forwarding with authentication spoofing."); 819 x11_request_forwarding_with_spoofing(0, proto, data); 820 821 /* Read response from the server. */ 822 type = packet_read(&plen); 823 if (type == SSH_SMSG_SUCCESS) { 824 interactive = 1; 825 } else if (type == SSH_SMSG_FAILURE) { 826 log("Warning: Remote host denied X11 forwarding."); 827 } else { 828 packet_disconnect("Protocol error waiting for X11 forwarding"); 829 } 830 } 831 /* Tell the packet module whether this is an interactive session. */ 832 packet_set_interactive(interactive, options.keepalives); 833 834 /* Clear agent forwarding if we don\'t have an agent. */ 835 authfd = ssh_get_authentication_socket(); 836 if (authfd < 0) 837 options.forward_agent = 0; 838 else 839 ssh_close_authentication_socket(authfd); 840 841 /* Request authentication agent forwarding if appropriate. */ 842 if (options.forward_agent) { 843 debug("Requesting authentication agent forwarding."); 844 auth_request_forwarding(); 845 846 /* Read response from the server. */ 847 type = packet_read(&plen); 848 packet_integrity_check(plen, 0, type); 849 if (type != SSH_SMSG_SUCCESS) 850 log("Warning: Remote host denied authentication agent forwarding."); 851 } 852 /* Initiate local TCP/IP port forwardings. */ 853 for (i = 0; i < options.num_local_forwards; i++) { 854 debug("Connections to local port %d forwarded to remote address %.200s:%d", 855 options.local_forwards[i].port, 856 options.local_forwards[i].host, 857 options.local_forwards[i].host_port); 858 channel_request_local_forwarding(options.local_forwards[i].port, 859 options.local_forwards[i].host, 860 options.local_forwards[i].host_port, 861 options.gateway_ports); 862 } 863 864 /* Initiate remote TCP/IP port forwardings. */ 865 for (i = 0; i < options.num_remote_forwards; i++) { 866 debug("Connections to remote port %d forwarded to local address %.200s:%d", 867 options.remote_forwards[i].port, 868 options.remote_forwards[i].host, 869 options.remote_forwards[i].host_port); 870 channel_request_remote_forwarding(options.remote_forwards[i].port, 871 options.remote_forwards[i].host, 872 options.remote_forwards[i].host_port); 873 } 874 875 /* If requested, let ssh continue in the background. */ 876 if (fork_after_authentication_flag) 877 if (daemon(1, 1) < 0) 878 fatal("daemon() failed: %.200s", strerror(errno)); 879 880 /* 881 * If a command was specified on the command line, execute the 882 * command now. Otherwise request the server to start a shell. 883 */ 884 if (buffer_len(&command) > 0) { 885 int len = buffer_len(&command); 886 if (len > 900) 887 len = 900; 888 debug("Sending command: %.*s", len, buffer_ptr(&command)); 889 packet_start(SSH_CMSG_EXEC_CMD); 890 packet_put_string(buffer_ptr(&command), buffer_len(&command)); 891 packet_send(); 892 packet_write_wait(); 893 } else { 894 debug("Requesting shell."); 895 packet_start(SSH_CMSG_EXEC_SHELL); 896 packet_send(); 897 packet_write_wait(); 898 } 899 900 /* Enter the interactive session. */ 901 return client_loop(have_tty, tty_flag ? options.escape_char : -1, 0); 902 } 903 904 void 905 init_local_fwd(void) 906 { 907 int i; 908 /* Initiate local TCP/IP port forwardings. */ 909 for (i = 0; i < options.num_local_forwards; i++) { 910 debug("Connections to local port %d forwarded to remote address %.200s:%d", 911 options.local_forwards[i].port, 912 options.local_forwards[i].host, 913 options.local_forwards[i].host_port); 914 channel_request_local_forwarding(options.local_forwards[i].port, 915 options.local_forwards[i].host, 916 options.local_forwards[i].host_port, 917 options.gateway_ports); 918 } 919 } 920 921 extern void client_set_session_ident(int id); 922 923 void 924 client_init(int id, void *arg) 925 { 926 int len; 927 debug("client_init id %d arg %d", id, (int)arg); 928 929 if (no_shell_flag) 930 goto done; 931 932 if (tty_flag) { 933 struct winsize ws; 934 char *cp; 935 cp = getenv("TERM"); 936 if (!cp) 937 cp = ""; 938 /* Store window size in the packet. */ 939 if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) < 0) 940 memset(&ws, 0, sizeof(ws)); 941 942 channel_request_start(id, "pty-req", 0); 943 packet_put_cstring(cp); 944 packet_put_int(ws.ws_col); 945 packet_put_int(ws.ws_row); 946 packet_put_int(ws.ws_xpixel); 947 packet_put_int(ws.ws_ypixel); 948 packet_put_cstring(""); /* XXX: encode terminal modes */ 949 packet_send(); 950 /* XXX wait for reply */ 951 } 952 if (options.forward_x11 && 953 getenv("DISPLAY") != NULL) { 954 char proto[512], data[512]; 955 /* Get reasonable local authentication information. */ 956 x11_get_proto(proto, sizeof proto, data, sizeof data); 957 /* Request forwarding with authentication spoofing. */ 958 debug("Requesting X11 forwarding with authentication spoofing."); 959 x11_request_forwarding_with_spoofing(id, proto, data); 960 /* XXX wait for reply */ 961 } 962 963 len = buffer_len(&command); 964 if (len > 0) { 965 if (len > 900) 966 len = 900; 967 debug("Sending command: %.*s", len, buffer_ptr(&command)); 968 channel_request_start(id, "exec", 0); 969 packet_put_string(buffer_ptr(&command), len); 970 packet_send(); 971 } else { 972 channel_request(id, "shell", 0); 973 } 974 /* channel_callback(id, SSH2_MSG_OPEN_CONFIGMATION, client_init, 0); */ 975 done: 976 /* register different callback, etc. XXX */ 977 client_set_session_ident(id); 978 } 979 980 int 981 ssh_session2(void) 982 { 983 int window, packetmax, id; 984 int in, out, err; 985 986 if (stdin_null_flag) { 987 in = open("/dev/null", O_RDONLY); 988 } else { 989 in = dup(STDIN_FILENO); 990 } 991 out = dup(STDOUT_FILENO); 992 err = dup(STDERR_FILENO); 993 994 if (in < 0 || out < 0 || err < 0) 995 fatal("dup() in/out/err failed"); 996 997 /* should be pre-session */ 998 init_local_fwd(); 999 1000 /* If requested, let ssh continue in the background. */ 1001 if (fork_after_authentication_flag) 1002 if (daemon(1, 1) < 0) 1003 fatal("daemon() failed: %.200s", strerror(errno)); 1004 1005 window = CHAN_SES_WINDOW_DEFAULT; 1006 packetmax = CHAN_SES_PACKET_DEFAULT; 1007 if (!tty_flag) { 1008 window *= 2; 1009 packetmax *=2; 1010 } 1011 id = channel_new( 1012 "session", SSH_CHANNEL_OPENING, in, out, err, 1013 window, packetmax, CHAN_EXTENDED_WRITE, 1014 xstrdup("client-session")); 1015 1016 channel_open(id); 1017 channel_register_callback(id, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, client_init, (void *)0); 1018 1019 return client_loop(tty_flag, tty_flag ? options.escape_char : -1, id); 1020 } 1021