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 * Copyright (c) 2000, 2001, 2002 Markus Friedl. All rights reserved. 17 * 18 * Modified to work with SSL by Niels Provos <provos@citi.umich.edu> 19 * in Canada (German citizen). 20 * 21 * Redistribution and use in source and binary forms, with or without 22 * modification, are permitted provided that the following conditions 23 * are met: 24 * 1. Redistributions of source code must retain the above copyright 25 * notice, this list of conditions and the following disclaimer. 26 * 2. Redistributions in binary form must reproduce the above copyright 27 * notice, this list of conditions and the following disclaimer in the 28 * documentation and/or other materials provided with the distribution. 29 * 30 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 31 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 32 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 33 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 34 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 35 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 36 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 37 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 38 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 39 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 40 */ 41 /* 42 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 43 * Use is subject to license terms. 44 */ 45 46 #include "includes.h" 47 RCSID("$OpenBSD: ssh.c,v 1.186 2002/09/19 01:58:18 djm Exp $"); 48 49 #include <openssl/err.h> 50 51 #include "ssh.h" 52 #include "ssh1.h" 53 #include "ssh2.h" 54 #include "compat.h" 55 #include "cipher.h" 56 #include "xmalloc.h" 57 #include "packet.h" 58 #include "buffer.h" 59 #include "channels.h" 60 #include "key.h" 61 #include "authfd.h" 62 #include "authfile.h" 63 #include "pathnames.h" 64 #include "clientloop.h" 65 #include "log.h" 66 #include "readconf.h" 67 #include "sshconnect.h" 68 #include "tildexpand.h" 69 #include "dispatch.h" 70 #include "misc.h" 71 #include "kex.h" 72 #include "mac.h" 73 #include "sshtty.h" 74 75 #include "g11n.h" 76 77 #ifdef HAVE___PROGNAME 78 extern char *__progname; 79 #else 80 char *__progname; 81 #endif 82 83 /* Flag indicating whether IPv4 or IPv6. This can be set on the command line. 84 Default value is AF_UNSPEC means both IPv4 and IPv6. */ 85 #ifdef IPV4_DEFAULT 86 int IPv4or6 = AF_INET; 87 #else 88 int IPv4or6 = AF_UNSPEC; 89 #endif 90 91 /* Flag indicating whether debug mode is on. This can be set on the command line. */ 92 int debug_flag = 0; 93 94 /* Flag indicating whether a tty should be allocated */ 95 int tty_flag = 0; 96 int no_tty_flag = 0; 97 int force_tty_flag = 0; 98 99 /* don't exec a shell */ 100 int no_shell_flag = 0; 101 102 /* 103 * Flag indicating that nothing should be read from stdin. This can be set 104 * on the command line. 105 */ 106 int stdin_null_flag = 0; 107 108 /* 109 * Flag indicating that ssh should fork after authentication. This is useful 110 * so that the passphrase can be entered manually, and then ssh goes to the 111 * background. 112 */ 113 int fork_after_authentication_flag = 0; 114 115 /* 116 * General data structure for command line options and options configurable 117 * in configuration files. See readconf.h. 118 */ 119 Options options; 120 121 /* optional user configfile */ 122 char *config = NULL; 123 124 /* 125 * Name of the host we are connecting to. This is the name given on the 126 * command line, or the HostName specified for the user-supplied name in a 127 * configuration file. 128 */ 129 char *host; 130 131 /* socket address the host resolves to */ 132 struct sockaddr_storage hostaddr; 133 134 /* Private host keys. */ 135 Sensitive sensitive_data; 136 137 /* Original real UID. */ 138 uid_t original_real_uid; 139 uid_t original_effective_uid; 140 141 /* command to be executed */ 142 Buffer command; 143 144 /* Should we execute a command or invoke a subsystem? */ 145 int subsystem_flag = 0; 146 147 /* # of replies received for global requests */ 148 static int client_global_request_id = 0; 149 150 /* pid of proxycommand child process */ 151 pid_t proxy_command_pid = 0; 152 153 /* Prints a help message to the user. This function never returns. */ 154 155 static void 156 usage(void) 157 { 158 fprintf(stderr, 159 gettext("Usage: %s [options] host [command]\n" 160 "Options:\n" 161 " -l user Log in using this user name.\n" 162 " -n Redirect input from /dev/null.\n" 163 " -F config Config file (default: ~/%s).\n" 164 " -A Enable authentication agent forwarding.\n" 165 " -a Disable authentication agent forwarding " 166 "(default).\n" 167 #ifdef AFS 168 " -k Disable Kerberos ticket and AFS token " 169 "forwarding.\n" 170 #endif /* AFS */ 171 " -X Enable X11 connection forwarding.\n" 172 " -x Disable X11 connection forwarding (default).\n" 173 " -i file Identity for public key authentication " 174 "(default: ~/.ssh/identity)\n" 175 " -t Tty; allocate a tty even if command is given.\n" 176 " -T Do not allocate a tty.\n" 177 " -v Verbose; display verbose debugging messages.\n" 178 " Multiple -v increases verbosity.\n" 179 " -V Display version number only.\n" 180 " -q Quiet; don't display any warning messages.\n" 181 " -f Fork into background after authentication.\n" 182 " -e char Set escape character; ``none'' = disable " 183 "(default: ~).\n" 184 " -c cipher Select encryption algorithm\n" 185 " -m macs Specify MAC algorithms for protocol version 2.\n" 186 " -p port Connect to this port. Server must be " 187 "on the same port.\n" 188 " -L listen-port:host:port Forward local port to " 189 "remote address\n" 190 " -R listen-port:host:port Forward remote port to " 191 "local address\n" 192 " These cause %s to listen for connections " 193 "on a port, and\n" 194 " forward them to the other side by " 195 "connecting to host:port.\n" 196 " -D port Enable dynamic application-level " 197 "port forwarding.\n" 198 " -C Enable compression.\n" 199 " -N Do not execute a shell or command.\n" 200 " -g Allow remote hosts to connect to forwarded " 201 "ports.\n" 202 " -1 Force protocol version 1.\n" 203 " -2 Force protocol version 2.\n" 204 " -4 Use IPv4 only.\n" 205 " -6 Use IPv6 only.\n" 206 " -o 'option' Process the option as if it was read " 207 "from a configuration file.\n" 208 " -s Invoke command (mandatory) as SSH2 subsystem.\n" 209 " -b addr Local IP address.\n"), 210 __progname, _PATH_SSH_USER_CONFFILE, __progname); 211 exit(1); 212 } 213 214 static int ssh_session(void); 215 static int ssh_session2(void); 216 static void load_public_identity_files(void); 217 static void rsh_connect(char *host, char *user, Buffer * command); 218 219 /* 220 * Main program for the ssh client. 221 */ 222 int 223 main(int ac, char **av) 224 { 225 int i, opt, exit_status; 226 char *p, *cp, buf[256], *pw_name, *pw_dir; 227 struct stat st; 228 struct passwd *pw; 229 int dummy; 230 extern int optind, optreset; 231 extern char *optarg; 232 Forward fwd; 233 234 __progname = get_progname(av[0]); 235 236 (void) g11n_setlocale(LC_ALL, ""); 237 238 init_rng(); 239 240 /* 241 * Save the original real uid. It will be needed later (uid-swapping 242 * may clobber the real uid). 243 */ 244 original_real_uid = getuid(); 245 original_effective_uid = geteuid(); 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 PRIV_END; 255 256 #ifdef HAVE_SETRLIMIT 257 /* If we are installed setuid root be careful to not drop core. */ 258 if (original_real_uid != original_effective_uid) { 259 struct rlimit rlim; 260 rlim.rlim_cur = rlim.rlim_max = 0; 261 if (setrlimit(RLIMIT_CORE, &rlim) < 0) 262 fatal("setrlimit failed: %.100s", strerror(errno)); 263 } 264 #endif 265 /* 266 * Get user data. It may happen that NIS or LDAP connection breaks down 267 * during the user's session. We should try to do our best and use the 268 * HOME and LOGNAME variables. Remember that the SSH client might be the 269 * only tool available to fix the problem with the naming services. 270 */ 271 pw = getpwuid(original_real_uid); 272 if (pw == NULL) { 273 if ((pw_dir = getenv("HOME")) == NULL) { 274 log("User account's password entry not found and HOME " 275 "not set. Set it manually and try again. " 276 "Exiting."); 277 exit(1); 278 } 279 log("User account's password entry not found, using " 280 "the HOME variable."); 281 282 if ((pw_name = getenv("LOGNAME")) == NULL) { 283 log("Need a local user name but LOGNAME is not set. " 284 "Set it manually and try again. Exiting."); 285 exit(1); 286 } 287 log("Local user name '%s' set from the LOGNAME variable.", 288 pw_name); 289 290 pw_dir = xstrdup(pw_dir); 291 pw_name = xstrdup(pw_name); 292 } else { 293 pw_name = xstrdup(pw->pw_name); 294 pw_dir = xstrdup(pw->pw_dir); 295 } 296 297 /* 298 * Set our umask to something reasonable, as some files are created 299 * with the default umask. This will make them world-readable but 300 * writable only by the owner, which is ok for all files for which we 301 * don't set the modes explicitly. 302 */ 303 umask(022); 304 305 /* Initialize option structure to indicate that no values have been set. */ 306 initialize_options(&options); 307 308 /* Parse command-line arguments. */ 309 host = NULL; 310 311 again: 312 while ((opt = getopt(ac, av, 313 "1246ab:c:e:fgi:kl:m:no:p:qstvxACD:F:I:L:NPR:TVX")) != -1) { 314 switch (opt) { 315 case '1': 316 options.protocol = SSH_PROTO_1; 317 break; 318 case '2': 319 options.protocol = SSH_PROTO_2; 320 break; 321 case '4': 322 IPv4or6 = AF_INET; 323 break; 324 case '6': 325 IPv4or6 = AF_INET6; 326 break; 327 case 'n': 328 stdin_null_flag = 1; 329 break; 330 case 'f': 331 fork_after_authentication_flag = 1; 332 stdin_null_flag = 1; 333 break; 334 case 'x': 335 options.forward_x11 = 0; 336 break; 337 case 'X': 338 options.forward_x11 = 1; 339 break; 340 case 'g': 341 options.gateway_ports = 1; 342 break; 343 case 'P': /* deprecated */ 344 fprintf(stderr, gettext("Warning: Option -P has " 345 "been deprecated\n")); 346 options.use_privileged_port = 0; 347 break; 348 case 'a': 349 options.forward_agent = 0; 350 break; 351 case 'A': 352 options.forward_agent = 1; 353 break; 354 #ifdef AFS 355 case 'k': 356 options.kerberos_tgt_passing = 0; 357 options.afs_token_passing = 0; 358 break; 359 #endif 360 case 'i': 361 if (stat(optarg, &st) < 0) { 362 fprintf(stderr, 363 gettext("Warning: Identity file %s " 364 "does not exist.\n"), optarg); 365 break; 366 } 367 if (options.num_identity_files >= 368 SSH_MAX_IDENTITY_FILES) 369 fatal("Too many identity files specified " 370 "(max %d)", SSH_MAX_IDENTITY_FILES); 371 options.identity_files[options.num_identity_files++] = 372 xstrdup(optarg); 373 break; 374 case 'I': 375 fprintf(stderr, "no support for smartcards.\n"); 376 break; 377 case 't': 378 if (tty_flag) 379 force_tty_flag = 1; 380 tty_flag = 1; 381 break; 382 case 'v': 383 if (0 == debug_flag) { 384 debug_flag = 1; 385 options.log_level = SYSLOG_LEVEL_DEBUG1; 386 } else if (options.log_level < SYSLOG_LEVEL_DEBUG3) { 387 options.log_level++; 388 break; 389 } else 390 fatal("Too high debugging level."); 391 /* FALLTHROUGH */ 392 case 'V': 393 fprintf(stderr, 394 gettext("%s, SSH protocols %d.%d/%d.%d, " 395 "OpenSSL 0x%8.8lx\n"), 396 SSH_VERSION, 397 PROTOCOL_MAJOR_1, PROTOCOL_MINOR_1, 398 PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2, 399 SSLeay()); 400 if (opt == 'V') 401 exit(0); 402 break; 403 case 'q': 404 options.log_level = SYSLOG_LEVEL_QUIET; 405 break; 406 case 'e': 407 if (optarg[0] == '^' && optarg[2] == 0 && 408 (u_char) optarg[1] >= 64 && 409 (u_char) optarg[1] < 128) 410 options.escape_char = (u_char) optarg[1] & 31; 411 else if (strlen(optarg) == 1) 412 options.escape_char = (u_char) optarg[0]; 413 else if (strcmp(optarg, "none") == 0) 414 options.escape_char = SSH_ESCAPECHAR_NONE; 415 else { 416 fprintf(stderr, 417 gettext("Bad escape character '%s'.\n"), 418 optarg); 419 exit(1); 420 } 421 break; 422 case 'c': 423 if (ciphers_valid(optarg)) { 424 /* SSH2 only */ 425 options.ciphers = xstrdup(optarg); 426 options.cipher = SSH_CIPHER_ILLEGAL; 427 } else { 428 /* SSH1 only */ 429 options.cipher = cipher_number(optarg); 430 if (options.cipher == -1) { 431 fprintf(stderr, 432 gettext("Unknown cipher " 433 "type '%s'\n"), 434 optarg); 435 exit(1); 436 } 437 if (options.cipher == SSH_CIPHER_3DES) 438 options.ciphers = "3des-cbc"; 439 else if (options.cipher == SSH_CIPHER_BLOWFISH) 440 options.ciphers = "blowfish-cbc"; 441 else 442 options.ciphers = (char *)-1; 443 } 444 break; 445 case 'm': 446 if (mac_valid(optarg)) 447 options.macs = xstrdup(optarg); 448 else { 449 fprintf(stderr, 450 gettext("Unknown mac type '%s'\n"), 451 optarg); 452 exit(1); 453 } 454 break; 455 case 'p': 456 options.port = a2port(optarg); 457 if (options.port == 0) { 458 fprintf(stderr, gettext("Bad port '%s'\n"), 459 optarg); 460 exit(1); 461 } 462 break; 463 case 'l': 464 options.user = optarg; 465 break; 466 467 case 'L': 468 if (parse_forward(1, &fwd, optarg)) 469 add_local_forward(&options, &fwd); 470 else 471 fatal("Bad local forwarding specification " 472 "'%s'\n", optarg); 473 break; 474 475 case 'R': 476 if (parse_forward(1, &fwd, optarg)) 477 add_remote_forward(&options, &fwd); 478 else 479 fatal("Bad remote forwarding specification " 480 "'%s'\n", optarg); 481 break; 482 483 case 'D': 484 if (parse_forward(0, &fwd, optarg) == 0) 485 fatal("Bad dynamic forwarding specification " 486 "'%s'\n", optarg); 487 fwd.connect_host = "socks"; 488 add_local_forward(&options, &fwd); 489 break; 490 491 case 'C': 492 options.compression = 1; 493 break; 494 case 'N': 495 no_shell_flag = 1; 496 no_tty_flag = 1; 497 break; 498 case 'T': 499 no_tty_flag = 1; 500 break; 501 case 'o': 502 dummy = 1; 503 if (process_config_line(&options, host ? host : "", 504 optarg, "command-line", 0, &dummy) != 0) 505 exit(1); 506 break; 507 case 's': 508 subsystem_flag = 1; 509 break; 510 case 'b': 511 options.bind_address = optarg; 512 break; 513 case 'F': 514 config = optarg; 515 break; 516 default: 517 usage(); 518 } 519 } 520 521 ac -= optind; 522 av += optind; 523 524 if (ac > 0 && !host && **av != '-') { 525 if (strchr(*av, '@')) { 526 p = xstrdup(*av); 527 cp = strchr(p, '@'); 528 if (cp == NULL || cp == p) 529 usage(); 530 options.user = p; 531 *cp = '\0'; 532 host = ++cp; 533 } else 534 host = *av; 535 ac--, av++; 536 if (ac > 0) { 537 optind = 0; 538 optreset = 1; 539 goto again; 540 } 541 } 542 543 /* Check that we got a host name. */ 544 if (!host) 545 usage(); 546 547 SSLeay_add_all_algorithms(); 548 ERR_load_crypto_strings(); 549 channel_set_af(IPv4or6); 550 551 /* Initialize the command to execute on remote host. */ 552 buffer_init(&command); 553 554 /* 555 * Save the command to execute on the remote host in a buffer. There 556 * is no limit on the length of the command, except by the maximum 557 * packet size. Also sets the tty flag if there is no command. 558 */ 559 if (!ac) { 560 /* No command specified - execute shell on a tty. */ 561 tty_flag = 1; 562 if (subsystem_flag) { 563 fprintf(stderr, 564 gettext("You must specify a subsystem " 565 "to invoke.\n")); 566 usage(); 567 } 568 } else { 569 /* A command has been specified. Store it into the buffer. */ 570 for (i = 0; i < ac; i++) { 571 if (i) 572 buffer_append(&command, " ", 1); 573 buffer_append(&command, av[i], strlen(av[i])); 574 } 575 } 576 577 /* Cannot fork to background if no command. */ 578 if (fork_after_authentication_flag && buffer_len(&command) == 0 && !no_shell_flag) 579 fatal("Cannot fork into background without a command to execute."); 580 581 /* Allocate a tty by default if no command specified. */ 582 if (buffer_len(&command) == 0) 583 tty_flag = 1; 584 585 /* Force no tty */ 586 if (no_tty_flag) 587 tty_flag = 0; 588 /* Do not allocate a tty if stdin is not a tty. */ 589 if (!isatty(fileno(stdin)) && !force_tty_flag) { 590 if (tty_flag) 591 log("Pseudo-terminal will not be allocated because stdin is not a terminal."); 592 tty_flag = 0; 593 } 594 595 /* 596 * Initialize "log" output. Since we are the client all output 597 * actually goes to stderr. 598 */ 599 log_init(av[0], options.log_level == -1 ? SYSLOG_LEVEL_INFO : options.log_level, 600 SYSLOG_FACILITY_USER, 1); 601 602 /* 603 * Read per-user configuration file. Ignore the system wide config 604 * file if the user specifies a config file on the command line. 605 */ 606 if (config != NULL) { 607 if (!read_config_file(config, host, &options)) 608 fatal("Can't open user config file %.100s: " 609 "%.100s", config, strerror(errno)); 610 } else { 611 snprintf(buf, sizeof buf, "%.100s/%.100s", pw_dir, 612 _PATH_SSH_USER_CONFFILE); 613 (void)read_config_file(buf, host, &options); 614 615 /* Read systemwide configuration file after use config. */ 616 (void)read_config_file(_PATH_HOST_CONFIG_FILE, host, &options); 617 } 618 619 process_unknown_options(&options); 620 621 /* Fill configuration defaults. */ 622 fill_default_options(&options); 623 624 /* reinit */ 625 log_init(av[0], options.log_level, SYSLOG_FACILITY_USER, 1); 626 627 seed_rng(); 628 629 if (options.user == NULL) 630 options.user = xstrdup(pw_name); 631 632 if (options.hostname != NULL) 633 host = options.hostname; 634 635 /* Disable rhosts authentication if not running as root. */ 636 #ifdef HAVE_CYGWIN 637 /* Ignore uid if running under Windows */ 638 if (!options.use_privileged_port) { 639 #else 640 if (original_effective_uid != 0 || !options.use_privileged_port) { 641 #endif 642 debug("Rhosts Authentication disabled, " 643 "originating port will not be trusted."); 644 options.rhosts_authentication = 0; 645 } 646 /* Open a connection to the remote host. */ 647 648 /* XXX OpenSSH has deprecated UseRsh */ 649 if (options.use_rsh) { 650 seteuid(original_real_uid); 651 setuid(original_real_uid); 652 rsh_connect(host, options.user, &command); 653 fatal("rsh_connect returned"); 654 } 655 656 if (ssh_connect(host, &hostaddr, options.port, IPv4or6, 657 options.connection_attempts, 658 #ifdef HAVE_CYGWIN 659 options.use_privileged_port, 660 #else 661 original_effective_uid == 0 && options.use_privileged_port, 662 #endif 663 options.proxy_command) != 0) { 664 /* XXX OpenSSH has deprecated FallbackToRsh */ 665 if (options.fallback_to_rsh) { 666 seteuid(original_real_uid); 667 setuid(original_real_uid); 668 rsh_connect(host, options.user, &command); 669 fatal("rsh_connect returned"); 670 } 671 exit(1); 672 } 673 674 /* 675 * If we successfully made the connection, load the host private key 676 * in case we will need it later for combined rsa-rhosts 677 * authentication. This must be done before releasing extra 678 * privileges, because the file is only readable by root. 679 * If we cannot access the private keys, load the public keys 680 * instead and try to execute the ssh-keysign helper instead. 681 */ 682 sensitive_data.nkeys = 0; 683 sensitive_data.keys = NULL; 684 sensitive_data.external_keysign = 0; 685 if (options.rhosts_rsa_authentication || 686 options.hostbased_authentication) { 687 sensitive_data.nkeys = 3; 688 sensitive_data.keys = xmalloc(sensitive_data.nkeys * 689 sizeof(Key)); 690 691 PRIV_START; 692 sensitive_data.keys[0] = key_load_private_type(KEY_RSA1, 693 _PATH_HOST_KEY_FILE, "", NULL); 694 sensitive_data.keys[1] = key_load_private_type(KEY_DSA, 695 _PATH_HOST_DSA_KEY_FILE, "", NULL); 696 sensitive_data.keys[2] = key_load_private_type(KEY_RSA, 697 _PATH_HOST_RSA_KEY_FILE, "", NULL); 698 PRIV_END; 699 700 if (options.hostbased_authentication == 1 && 701 sensitive_data.keys[0] == NULL && 702 sensitive_data.keys[1] == NULL && 703 sensitive_data.keys[2] == NULL) { 704 sensitive_data.keys[1] = key_load_public( 705 _PATH_HOST_DSA_KEY_FILE, NULL); 706 sensitive_data.keys[2] = key_load_public( 707 _PATH_HOST_RSA_KEY_FILE, NULL); 708 sensitive_data.external_keysign = 1; 709 } 710 } 711 /* 712 * Get rid of any extra privileges that we may have. We will no 713 * longer need them. Also, extra privileges could make it very hard 714 * to read identity files and other non-world-readable files from the 715 * user's home directory if it happens to be on a NFS volume where 716 * root is mapped to nobody. 717 */ 718 seteuid(original_real_uid); 719 setuid(original_real_uid); 720 721 /* 722 * Now that we are back to our own permissions, create ~/.ssh 723 * directory if it doesn\'t already exist. 724 */ 725 snprintf(buf, sizeof buf, "%.100s%s%.100s", pw_dir, 726 strcmp(pw_dir, "/") ? "/" : "", _PATH_SSH_USER_DIR); 727 xfree(pw_dir); 728 if (stat(buf, &st) < 0) 729 if (mkdir(buf, 0700) < 0) 730 error("Could not create directory '%.200s'.", buf); 731 732 /* load options.identity_files */ 733 load_public_identity_files(); 734 735 /* Expand ~ in known host file names. */ 736 /* XXX mem-leaks: */ 737 options.system_hostfile = 738 tilde_expand_filename(options.system_hostfile, original_real_uid); 739 options.user_hostfile = 740 tilde_expand_filename(options.user_hostfile, original_real_uid); 741 options.system_hostfile2 = 742 tilde_expand_filename(options.system_hostfile2, original_real_uid); 743 options.user_hostfile2 = 744 tilde_expand_filename(options.user_hostfile2, original_real_uid); 745 746 signal(SIGPIPE, SIG_IGN); /* ignore SIGPIPE early */ 747 748 /* Log into the remote system. This never returns if the login fails. */ 749 ssh_login(&sensitive_data, host, (struct sockaddr *)&hostaddr, pw_name); 750 xfree(pw_name); 751 752 /* We no longer need the private host keys. Clear them now. */ 753 if (sensitive_data.nkeys != 0) { 754 for (i = 0; i < sensitive_data.nkeys; i++) { 755 if (sensitive_data.keys[i] != NULL) { 756 /* Destroys contents safely */ 757 debug3("clear hostkey %d", i); 758 key_free(sensitive_data.keys[i]); 759 sensitive_data.keys[i] = NULL; 760 } 761 } 762 xfree(sensitive_data.keys); 763 } 764 for (i = 0; i < options.num_identity_files; i++) { 765 if (options.identity_files[i]) { 766 xfree(options.identity_files[i]); 767 options.identity_files[i] = NULL; 768 } 769 if (options.identity_keys[i]) { 770 key_free(options.identity_keys[i]); 771 options.identity_keys[i] = NULL; 772 } 773 } 774 775 exit_status = compat20 ? ssh_session2() : ssh_session(); 776 packet_close(); 777 778 /* 779 * Send SIGHUP to proxy command if used. We don't wait() in 780 * case it hangs and instead rely on init to reap the child 781 */ 782 if (proxy_command_pid > 1) 783 kill(proxy_command_pid, SIGHUP); 784 785 return exit_status; 786 } 787 788 static void 789 ssh_init_forwarding(void) 790 { 791 int success = 0; 792 int i; 793 794 /* Initiate local TCP/IP port forwardings. */ 795 for (i = 0; i < options.num_local_forwards; i++) { 796 debug("Local connections to %.200s:%d forwarded to remote " 797 "address %.200s:%d", 798 (options.local_forwards[i].listen_host == NULL) ? 799 (options.gateway_ports ? "*" : "LOCALHOST") : 800 options.local_forwards[i].listen_host, 801 options.local_forwards[i].listen_port, 802 options.local_forwards[i].connect_host, 803 options.local_forwards[i].connect_port); 804 success += channel_setup_local_fwd_listener( 805 options.local_forwards[i].listen_host, 806 options.local_forwards[i].listen_port, 807 options.local_forwards[i].connect_host, 808 options.local_forwards[i].connect_port, 809 options.gateway_ports); 810 } 811 if (i > 0 && success == 0) 812 error("Could not request local forwarding."); 813 814 /* Initiate remote TCP/IP port forwardings. */ 815 for (i = 0; i < options.num_remote_forwards; i++) { 816 debug("Remote connections from %.200s:%d forwarded to " 817 "local address %.200s:%d", 818 (options.remote_forwards[i].listen_host == NULL) ? 819 "LOCALHOST" : options.remote_forwards[i].listen_host, 820 options.remote_forwards[i].listen_port, 821 options.remote_forwards[i].connect_host, 822 options.remote_forwards[i].connect_port); 823 if (channel_request_remote_forwarding( 824 options.remote_forwards[i].listen_host, 825 options.remote_forwards[i].listen_port, 826 options.remote_forwards[i].connect_host, 827 options.remote_forwards[i].connect_port) < 0) { 828 log("Warning: Could not request remote forwarding."); 829 } 830 } 831 } 832 833 static void 834 check_agent_present(void) 835 { 836 if (options.forward_agent) { 837 /* Clear agent forwarding if we don't have an agent. */ 838 if (!ssh_agent_present()) 839 options.forward_agent = 0; 840 } 841 } 842 843 static int 844 ssh_session(void) 845 { 846 int type; 847 int interactive = 0; 848 int have_tty = 0; 849 struct winsize ws; 850 char *cp; 851 const char *display; 852 853 /* Enable compression if requested. */ 854 if (options.compression) { 855 debug("Requesting compression at level %d.", options.compression_level); 856 857 if (options.compression_level < 1 || options.compression_level > 9) 858 fatal("Compression level must be from 1 (fast) to 9 (slow, best)."); 859 860 /* Send the request. */ 861 packet_start(SSH_CMSG_REQUEST_COMPRESSION); 862 packet_put_int(options.compression_level); 863 packet_send(); 864 packet_write_wait(); 865 type = packet_read(); 866 if (type == SSH_SMSG_SUCCESS) 867 packet_start_compression(options.compression_level); 868 else if (type == SSH_SMSG_FAILURE) 869 log("Warning: Remote host refused compression."); 870 else 871 packet_disconnect("Protocol error waiting for compression response."); 872 } 873 /* Allocate a pseudo tty if appropriate. */ 874 if (tty_flag) { 875 debug("Requesting pty."); 876 877 /* Start the packet. */ 878 packet_start(SSH_CMSG_REQUEST_PTY); 879 880 /* Store TERM in the packet. There is no limit on the 881 length of the string. */ 882 cp = getenv("TERM"); 883 if (!cp) 884 cp = ""; 885 packet_put_cstring(cp); 886 887 /* Store window size in the packet. */ 888 if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) < 0) 889 memset(&ws, 0, sizeof(ws)); 890 packet_put_int(ws.ws_row); 891 packet_put_int(ws.ws_col); 892 packet_put_int(ws.ws_xpixel); 893 packet_put_int(ws.ws_ypixel); 894 895 /* Store tty modes in the packet. */ 896 tty_make_modes(fileno(stdin), NULL); 897 898 /* Send the packet, and wait for it to leave. */ 899 packet_send(); 900 packet_write_wait(); 901 902 /* Read response from the server. */ 903 type = packet_read(); 904 if (type == SSH_SMSG_SUCCESS) { 905 interactive = 1; 906 have_tty = 1; 907 } else if (type == SSH_SMSG_FAILURE) 908 log("Warning: Remote host failed or refused to allocate a pseudo tty."); 909 else 910 packet_disconnect("Protocol error waiting for pty request response."); 911 } 912 /* Request X11 forwarding if enabled and DISPLAY is set. */ 913 display = getenv("DISPLAY"); 914 if (options.forward_x11 && display != NULL) { 915 char *proto, *data; 916 /* Get reasonable local authentication information. */ 917 client_x11_get_proto(display, options.xauth_location, 918 options.forward_x11_trusted, &proto, &data); 919 /* Request forwarding with authentication spoofing. */ 920 debug("Requesting X11 forwarding with authentication spoofing."); 921 x11_request_forwarding_with_spoofing(0, display, proto, data); 922 923 /* Read response from the server. */ 924 type = packet_read(); 925 if (type == SSH_SMSG_SUCCESS) { 926 interactive = 1; 927 } else if (type == SSH_SMSG_FAILURE) { 928 log("Warning: Remote host denied X11 forwarding."); 929 } else { 930 packet_disconnect("Protocol error waiting for X11 forwarding"); 931 } 932 } 933 /* Tell the packet module whether this is an interactive session. */ 934 packet_set_interactive(interactive); 935 936 /* Request authentication agent forwarding if appropriate. */ 937 check_agent_present(); 938 939 if (options.forward_agent) { 940 debug("Requesting authentication agent forwarding."); 941 auth_request_forwarding(); 942 943 /* Read response from the server. */ 944 type = packet_read(); 945 packet_check_eom(); 946 if (type != SSH_SMSG_SUCCESS) 947 log("Warning: Remote host denied authentication agent forwarding."); 948 } 949 950 /* Initiate port forwardings. */ 951 ssh_init_forwarding(); 952 953 /* If requested, let ssh continue in the background. */ 954 if (fork_after_authentication_flag) 955 if (daemon(1, 1) < 0) 956 fatal("daemon() failed: %.200s", strerror(errno)); 957 958 /* 959 * If a command was specified on the command line, execute the 960 * command now. Otherwise request the server to start a shell. 961 */ 962 if (buffer_len(&command) > 0) { 963 int len = buffer_len(&command); 964 if (len > 900) 965 len = 900; 966 debug("Sending command: %.*s", len, (u_char *)buffer_ptr(&command)); 967 packet_start(SSH_CMSG_EXEC_CMD); 968 packet_put_string(buffer_ptr(&command), buffer_len(&command)); 969 packet_send(); 970 packet_write_wait(); 971 } else { 972 debug("Requesting shell."); 973 packet_start(SSH_CMSG_EXEC_SHELL); 974 packet_send(); 975 packet_write_wait(); 976 } 977 978 /* Enter the interactive session. */ 979 return client_loop(have_tty, tty_flag ? 980 options.escape_char : SSH_ESCAPECHAR_NONE, 0); 981 } 982 983 static void 984 client_subsystem_reply(int type, u_int32_t seq, void *ctxt) 985 { 986 int id, len; 987 988 id = packet_get_int(); 989 len = buffer_len(&command); 990 if (len > 900) 991 len = 900; 992 packet_check_eom(); 993 if (type == SSH2_MSG_CHANNEL_FAILURE) 994 fatal("Request for subsystem '%.*s' failed on channel %d", 995 len, (u_char *)buffer_ptr(&command), id); 996 } 997 998 void 999 client_global_request_reply_fwd(int type, u_int32_t seq, void *ctxt) 1000 { 1001 int i; 1002 1003 i = client_global_request_id++; 1004 if (i >= options.num_remote_forwards) 1005 return; 1006 debug("remote forward %s for: listen %d, connect %s:%d", 1007 type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure", 1008 options.remote_forwards[i].listen_port, 1009 options.remote_forwards[i].connect_host, 1010 options.remote_forwards[i].connect_port); 1011 if (type == SSH2_MSG_REQUEST_FAILURE) 1012 log("Warning: remote port forwarding failed for listen port %d", 1013 options.remote_forwards[i].listen_port); 1014 } 1015 1016 static 1017 void 1018 ssh_session2_setlocale(int id) 1019 { 1020 char *loc; 1021 1022 #define remote_setlocale(envvar) \ 1023 if ((loc = getenv(envvar)) != NULL) {\ 1024 channel_request_start(id, "env", 0);\ 1025 debug2("Sent request for environment variable %s=%s", envvar, \ 1026 loc); \ 1027 packet_put_cstring(envvar);\ 1028 packet_put_cstring(loc);\ 1029 packet_send();\ 1030 } 1031 1032 remote_setlocale("LANG") 1033 1034 remote_setlocale("LC_CTYPE") 1035 remote_setlocale("LC_COLLATE") 1036 remote_setlocale("LC_TIME") 1037 remote_setlocale("LC_NUMERIC") 1038 remote_setlocale("LC_MONETARY") 1039 remote_setlocale("LC_MESSAGES") 1040 1041 remote_setlocale("LC_ALL") 1042 } 1043 1044 /* request pty/x11/agent/tcpfwd/shell for channel */ 1045 static void 1046 ssh_session2_setup(int id, void *arg) 1047 { 1048 int len; 1049 const char *display; 1050 int interactive = 0; 1051 struct termios tio; 1052 1053 debug("ssh_session2_setup: id %d", id); 1054 1055 ssh_session2_setlocale(id); 1056 1057 if (tty_flag) { 1058 struct winsize ws; 1059 char *cp; 1060 cp = getenv("TERM"); 1061 if (!cp) 1062 cp = ""; 1063 /* Store window size in the packet. */ 1064 if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) < 0) 1065 memset(&ws, 0, sizeof(ws)); 1066 1067 channel_request_start(id, "pty-req", 0); 1068 packet_put_cstring(cp); 1069 packet_put_int(ws.ws_col); 1070 packet_put_int(ws.ws_row); 1071 packet_put_int(ws.ws_xpixel); 1072 packet_put_int(ws.ws_ypixel); 1073 tio = get_saved_tio(); 1074 tty_make_modes(/*ignored*/ 0, &tio); 1075 packet_send(); 1076 interactive = 1; 1077 /* XXX wait for reply */ 1078 } 1079 1080 display = getenv("DISPLAY"); 1081 if (options.forward_x11 && display != NULL) { 1082 char *proto, *data; 1083 /* Get reasonable local authentication information. */ 1084 client_x11_get_proto(display, options.xauth_location, 1085 options.forward_x11_trusted, &proto, &data); 1086 /* Request forwarding with authentication spoofing. */ 1087 debug("Requesting X11 forwarding with authentication spoofing."); 1088 x11_request_forwarding_with_spoofing(id, display, proto, data); 1089 interactive = 1; 1090 /* XXX wait for reply */ 1091 } 1092 1093 check_agent_present(); 1094 if (options.forward_agent) { 1095 debug("Requesting authentication agent forwarding."); 1096 channel_request_start(id, "auth-agent-req@openssh.com", 0); 1097 packet_send(); 1098 } 1099 1100 len = buffer_len(&command); 1101 if (len > 0) { 1102 if (len > 900) 1103 len = 900; 1104 if (subsystem_flag) { 1105 debug("Sending subsystem: %.*s", len, (u_char *)buffer_ptr(&command)); 1106 channel_request_start(id, "subsystem", /*want reply*/ 1); 1107 /* register callback for reply */ 1108 /* XXX we assume that client_loop has already been called */ 1109 dispatch_set(SSH2_MSG_CHANNEL_FAILURE, &client_subsystem_reply); 1110 dispatch_set(SSH2_MSG_CHANNEL_SUCCESS, &client_subsystem_reply); 1111 } else { 1112 debug("Sending command: %.*s", len, (u_char *)buffer_ptr(&command)); 1113 channel_request_start(id, "exec", 0); 1114 } 1115 packet_put_string(buffer_ptr(&command), buffer_len(&command)); 1116 packet_send(); 1117 } else { 1118 channel_request_start(id, "shell", 0); 1119 packet_send(); 1120 } 1121 1122 packet_set_interactive(interactive); 1123 } 1124 1125 /* open new channel for a session */ 1126 static int 1127 ssh_session2_open(void) 1128 { 1129 Channel *c; 1130 int window, packetmax, in, out, err; 1131 1132 if (stdin_null_flag) { 1133 in = open(_PATH_DEVNULL, O_RDONLY); 1134 } else { 1135 in = dup(STDIN_FILENO); 1136 } 1137 out = dup(STDOUT_FILENO); 1138 err = dup(STDERR_FILENO); 1139 1140 if (in < 0 || out < 0 || err < 0) 1141 fatal("dup() in/out/err failed"); 1142 1143 /* enable nonblocking unless tty */ 1144 if (!isatty(in)) 1145 set_nonblock(in); 1146 if (!isatty(out)) 1147 set_nonblock(out); 1148 if (!isatty(err)) 1149 set_nonblock(err); 1150 1151 window = CHAN_SES_WINDOW_DEFAULT; 1152 packetmax = CHAN_SES_PACKET_DEFAULT; 1153 if (tty_flag) { 1154 window >>= 1; 1155 packetmax >>= 1; 1156 } 1157 c = channel_new( 1158 "session", SSH_CHANNEL_OPENING, in, out, err, 1159 window, packetmax, CHAN_EXTENDED_WRITE, 1160 xstrdup("client-session"), /*nonblock*/0); 1161 1162 debug3("ssh_session2_open: channel_new: %d", c->self); 1163 1164 channel_send_open(c->self); 1165 if (!no_shell_flag) 1166 channel_register_confirm(c->self, ssh_session2_setup); 1167 1168 return c->self; 1169 } 1170 1171 static int 1172 ssh_session2(void) 1173 { 1174 int id = -1; 1175 1176 /* XXX should be pre-session */ 1177 ssh_init_forwarding(); 1178 1179 if (!no_shell_flag || (datafellows & SSH_BUG_DUMMYCHAN)) 1180 id = ssh_session2_open(); 1181 1182 /* If requested, let ssh continue in the background. */ 1183 if (fork_after_authentication_flag) 1184 client_daemonize(); 1185 1186 return (client_loop(tty_flag, tty_flag ? 1187 options.escape_char : SSH_ESCAPECHAR_NONE, id)); 1188 } 1189 1190 static void 1191 load_public_identity_files(void) 1192 { 1193 char *filename; 1194 int i = 0; 1195 Key *public; 1196 1197 for (; i < options.num_identity_files; i++) { 1198 filename = tilde_expand_filename(options.identity_files[i], 1199 original_real_uid); 1200 public = key_load_public(filename, NULL); 1201 debug("identity file %s type %d", filename, 1202 public ? public->type : -1); 1203 xfree(options.identity_files[i]); 1204 options.identity_files[i] = filename; 1205 options.identity_keys[i] = public; 1206 } 1207 } 1208 1209 /* 1210 * Connects to the given host using rsh(or prints an error message and exits 1211 * if rsh is not available). This function never returns. 1212 */ 1213 static void 1214 rsh_connect(char *host, char *user, Buffer * command) 1215 { 1216 char *args[10]; 1217 int i; 1218 1219 log("Using rsh. WARNING: Connection will not be encrypted."); 1220 /* Build argument list for rsh. */ 1221 i = 0; 1222 args[i++] = _PATH_RSH; 1223 /* host may have to come after user on some systems */ 1224 args[i++] = host; 1225 if (user) { 1226 args[i++] = "-l"; 1227 args[i++] = user; 1228 } 1229 if (buffer_len(command) > 0) { 1230 buffer_append(command, "\0", 1); 1231 args[i++] = buffer_ptr(command); 1232 } 1233 args[i++] = NULL; 1234 if (debug_flag) { 1235 for (i = 0; args[i]; i++) { 1236 if (i != 0) 1237 (void) fprintf(stderr, " "); 1238 (void) fprintf(stderr, "%s", args[i]); 1239 } 1240 (void) fprintf(stderr, "\n"); 1241 } 1242 (void) execv(_PATH_RSH, args); 1243 perror(_PATH_RSH); 1244 exit(1); 1245 }