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