2 * Author: Tatu Ylonen <ylo@cs.hut.fi>
3 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
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.
10 * Modified to work with SSL by Niels Provos <provos@citi.umich.edu> in Canada.
24 #ifdef HAVE___PROGNAME
25 extern char *__progname;
26 #else /* HAVE___PROGNAME */
27 const char *__progname = "ssh";
28 #endif /* HAVE___PROGNAME */
30 /* Flag indicating whether debug mode is on. This can be set on the command line. */
33 /* Flag indicating whether to allocate a pseudo tty. This can be set on the command
34 line, and is automatically set if no command is given on the command line. */
37 /* Flag indicating that nothing should be read from stdin. This can be set
38 on the command line. */
39 int stdin_null_flag = 0;
41 /* Flag indicating that ssh should fork after authentication. This is useful
42 so that the pasphrase can be entered manually, and then ssh goes to the
44 int fork_after_authentication_flag = 0;
46 /* General data structure for command line options and options configurable
47 in configuration files. See readconf.h. */
50 /* Name of the host we are connecting to. This is the name given on the
51 command line, or the HostName specified for the user-supplied name
52 in a configuration file. */
55 /* socket address the host resolves to */
56 struct sockaddr_in hostaddr;
58 /* Flag to indicate that we have received a window change signal which has
59 not yet been processed. This will cause a message indicating the new
60 window size to be sent to the server a little later. This is volatile
61 because this is updated in a signal handler. */
62 volatile int received_window_change_signal = 0;
64 /* Value of argv[0] (set in the main program). */
67 /* Flag indicating whether we have a valid host private key loaded. */
68 int host_private_key_loaded = 0;
70 /* Host private key. */
71 RSA *host_private_key = NULL;
73 /* Original real UID. */
74 uid_t original_real_uid;
76 /* Prints a help message to the user. This function never returns. */
81 fprintf(stderr, "Usage: %s [options] host [command]\n", av0);
82 fprintf(stderr, "Options:\n");
83 fprintf(stderr, " -l user Log in using this user name.\n");
84 fprintf(stderr, " -n Redirect input from /dev/null.\n");
85 fprintf(stderr, " -a Disable authentication agent forwarding.\n");
87 fprintf(stderr, " -k Disable Kerberos ticket and AFS token forwarding.\n");
89 fprintf(stderr, " -x Disable X11 connection forwarding.\n");
90 fprintf(stderr, " -i file Identity for RSA authentication (default: ~/.ssh/identity).\n");
91 fprintf(stderr, " -t Tty; allocate a tty even if command is given.\n");
92 fprintf(stderr, " -v Verbose; display verbose debugging messages.\n");
93 fprintf(stderr, " -V Display version number only.\n");
94 fprintf(stderr, " -P Don't allocate a privileged port.\n");
95 fprintf(stderr, " -q Quiet; don't display any warning messages.\n");
96 fprintf(stderr, " -f Fork into background after authentication.\n");
97 fprintf(stderr, " -e char Set escape character; ``none'' = disable (default: ~).\n");
99 fprintf(stderr, " -c cipher Select encryption algorithm: "
102 fprintf(stderr, " -p port Connect to this port. Server must be on the same port.\n");
103 fprintf(stderr, " -L listen-port:host:port Forward local port to remote address\n");
104 fprintf(stderr, " -R listen-port:host:port Forward remote port to local address\n");
105 fprintf(stderr, " These cause %s to listen for connections on a port, and\n", av0);
106 fprintf(stderr, " forward them to the other side by connecting to host:port.\n");
107 fprintf(stderr, " -C Enable compression.\n");
108 fprintf(stderr, " -g Allow remote hosts to connect to forwarded ports.\n");
109 fprintf(stderr, " -o 'option' Process the option as if it was read from a configuration file.\n");
114 * Connects to the given host using rsh (or prints an error message and exits
115 * if rsh is not available). This function never returns.
118 rsh_connect(char *host, char *user, Buffer * command)
123 log("Using rsh. WARNING: Connection will not be encrypted.");
124 /* Build argument list for rsh. */
126 args[i++] = _PATH_RSH;
127 /* host may have to come after user on some systems */
133 if (buffer_len(command) > 0) {
134 buffer_append(command, "\0", 1);
135 args[i++] = buffer_ptr(command);
139 for (i = 0; args[i]; i++) {
141 fprintf(stderr, " ");
142 fprintf(stderr, "%s", args[i]);
144 fprintf(stderr, "\n");
146 execv(_PATH_RSH, args);
152 * Main program for the ssh client.
155 main(int ac, char **av)
157 int i, opt, optind, type, exit_status, ok, fwd_port, fwd_host_port,
159 char *optarg, *cp, buf[256];
163 struct passwd *pw, pwcopy;
164 int interactive = 0, dummy;
165 uid_t original_effective_uid;
168 /* Save the original real uid. It will be needed later
169 (uid-swapping may clobber the real uid). */
170 original_real_uid = getuid();
171 original_effective_uid = geteuid();
173 /* If we are installed setuid root be careful to not drop core. */
174 if (original_real_uid != original_effective_uid) {
176 rlim.rlim_cur = rlim.rlim_max = 0;
177 if (setrlimit(RLIMIT_CORE, &rlim) < 0)
178 fatal("setrlimit failed: %.100s", strerror(errno));
180 /* Use uid-swapping to give up root privileges for the duration of
181 option processing. We will re-instantiate the rights when we
182 are ready to create the privileged port, and will permanently
183 drop them when the port has been created (actually, when the
184 connection has been made, as we may need to create the port
186 temporarily_use_uid(original_real_uid);
188 /* Set our umask to something reasonable, as some files are
189 created with the default umask. This will make them
190 world-readable but writable only by the owner, which is ok for
191 all files for which we don't set the modes explicitly. */
194 /* Save our own name. */
197 /* Initialize option structure to indicate that no values have been set. */
198 initialize_options(&options);
200 /* Parse command-line arguments. */
203 /* If program name is not one of the standard names, use it as host name. */
204 if (strchr(av0, '/'))
205 cp = strrchr(av0, '/') + 1;
208 if (strcmp(cp, "rsh") != 0 && strcmp(cp, "ssh") != 0 &&
209 strcmp(cp, "rlogin") != 0 && strcmp(cp, "slogin") != 0)
212 for (optind = 1; optind < ac; optind++) {
213 if (av[optind][0] != '-') {
216 if ((cp = strchr(av[optind], '@'))) {
217 options.user = av[optind];
227 if (strchr("eilcpLRo", opt)) { /* options with arguments */
228 optarg = av[optind] + 2;
229 if (strcmp(optarg, "") == 0) {
230 if (optind >= ac - 1)
232 optarg = av[++optind];
245 fork_after_authentication_flag = 1;
250 options.forward_x11 = 0;
254 options.forward_x11 = 1;
258 options.gateway_ports = 1;
262 options.use_privileged_port = 0;
266 options.forward_agent = 0;
270 options.kerberos_tgt_passing = 0;
271 options.afs_token_passing = 0;
275 if (stat(optarg, &st) < 0) {
276 fprintf(stderr, "Warning: Identity file %s does not exist.\n",
280 if (options.num_identity_files >= SSH_MAX_IDENTITY_FILES)
281 fatal("Too many identity files specified (max %d)",
282 SSH_MAX_IDENTITY_FILES);
283 options.identity_files[options.num_identity_files++] =
293 fprintf(stderr, "SSH Version %s, protocol version %d.%d.\n",
294 SSH_VERSION, PROTOCOL_MAJOR, PROTOCOL_MINOR);
295 fprintf(stderr, "Compiled with SSL.\n");
299 options.log_level = SYSLOG_LEVEL_DEBUG;
303 options.log_level = SYSLOG_LEVEL_QUIET;
307 if (optarg[0] == '^' && optarg[2] == 0 &&
308 (unsigned char) optarg[1] >= 64 && (unsigned char) optarg[1] < 128)
309 options.escape_char = (unsigned char) optarg[1] & 31;
310 else if (strlen(optarg) == 1)
311 options.escape_char = (unsigned char) optarg[0];
312 else if (strcmp(optarg, "none") == 0)
313 options.escape_char = -2;
315 fprintf(stderr, "Bad escape character '%s'.\n", optarg);
321 options.cipher = cipher_number(optarg);
322 if (options.cipher == -1) {
323 fprintf(stderr, "Unknown cipher type '%s'\n", optarg);
329 options.port = atoi(optarg);
330 if (options.port < 1 || options.port > 65535) {
331 fprintf(stderr, "Bad port %s.\n", optarg);
337 options.user = optarg;
341 if (sscanf(optarg, "%d:%255[^:]:%d", &fwd_port, buf,
342 &fwd_host_port) != 3) {
343 fprintf(stderr, "Bad forwarding specification '%s'.\n", optarg);
347 add_remote_forward(&options, fwd_port, buf, fwd_host_port);
351 if (sscanf(optarg, "%d:%255[^:]:%d", &fwd_port, buf,
352 &fwd_host_port) != 3) {
353 fprintf(stderr, "Bad forwarding specification '%s'.\n", optarg);
357 add_local_forward(&options, fwd_port, buf, fwd_host_port);
361 options.compression = 1;
366 if (process_config_line(&options, host ? host : "", optarg,
367 "command-line", 0, &dummy) != 0)
376 /* Check that we got a host name. */
380 /* check if RSA support exists */
381 if (rsa_alive() == 0) {
383 "%s: no RSA support in libssl and libcrypto. See ssl(8).\n",
387 /* Initialize the command to execute on remote host. */
388 buffer_init(&command);
390 /* Save the command to execute on the remote host in a buffer.
391 There is no limit on the length of the command, except by the
392 maximum packet size. Also sets the tty flag if there is no
395 /* No command specified - execute shell on a tty. */
398 /* A command has been specified. Store it into the
400 for (i = optind; i < ac; i++) {
402 buffer_append(&command, " ", 1);
403 buffer_append(&command, av[i], strlen(av[i]));
407 /* Cannot fork to background if no command. */
408 if (fork_after_authentication_flag && buffer_len(&command) == 0)
409 fatal("Cannot fork into background without a command to execute.");
411 /* Allocate a tty by default if no command specified. */
412 if (buffer_len(&command) == 0)
415 /* Do not allocate a tty if stdin is not a tty. */
416 if (!isatty(fileno(stdin))) {
418 fprintf(stderr, "Pseudo-terminal will not be allocated because stdin is not a terminal.\n");
422 pw = getpwuid(original_real_uid);
424 fprintf(stderr, "You don't exist, go away!\n");
427 /* Take a copy of the returned structure. */
428 memset(&pwcopy, 0, sizeof(pwcopy));
429 pwcopy.pw_name = xstrdup(pw->pw_name);
430 pwcopy.pw_passwd = xstrdup(pw->pw_passwd);
431 pwcopy.pw_uid = pw->pw_uid;
432 pwcopy.pw_gid = pw->pw_gid;
433 pwcopy.pw_dir = xstrdup(pw->pw_dir);
434 pwcopy.pw_shell = xstrdup(pw->pw_shell);
437 /* Initialize "log" output. Since we are the client all output
438 actually goes to the terminal. */
439 log_init(av[0], options.log_level, SYSLOG_FACILITY_USER, 0);
441 /* Read per-user configuration file. */
442 snprintf(buf, sizeof buf, "%.100s/%.100s", pw->pw_dir, SSH_USER_CONFFILE);
443 read_config_file(buf, host, &options);
445 /* Read systemwide configuration file. */
446 read_config_file(HOST_CONFIG_FILE, host, &options);
448 /* Fill configuration defaults. */
449 fill_default_options(&options);
452 log_init(av[0], options.log_level, SYSLOG_FACILITY_USER, 0);
454 if (options.user == NULL)
455 options.user = xstrdup(pw->pw_name);
457 if (options.hostname != NULL)
458 host = options.hostname;
460 /* Find canonic host name. */
461 if (strchr(host, '.') == 0) {
462 struct hostent *hp = gethostbyname(host);
464 if (strchr(hp->h_name, '.') != 0)
465 host = xstrdup(hp->h_name);
466 else if (hp->h_aliases != 0
467 && hp->h_aliases[0] != 0
468 && strchr(hp->h_aliases[0], '.') != 0)
469 host = xstrdup(hp->h_aliases[0]);
472 /* Disable rhosts authentication if not running as root. */
473 if (original_effective_uid != 0 || !options.use_privileged_port) {
474 options.rhosts_authentication = 0;
475 options.rhosts_rsa_authentication = 0;
477 /* If using rsh has been selected, exec it now (without trying
478 anything else). Note that we must release privileges first. */
479 if (options.use_rsh) {
480 /* Restore our superuser privileges. This must be done
481 before permanently setting the uid. */
484 /* Switch to the original uid permanently. */
485 permanently_set_uid(original_real_uid);
488 rsh_connect(host, options.user, &command);
489 fatal("rsh_connect returned");
491 /* Restore our superuser privileges. */
494 /* Open a connection to the remote host. This needs root
495 privileges if rhosts_{rsa_}authentication is enabled. */
497 ok = ssh_connect(host, &hostaddr, options.port,
498 options.connection_attempts,
499 !options.rhosts_authentication &&
500 !options.rhosts_rsa_authentication,
502 options.proxy_command);
504 /* If we successfully made the connection, load the host private
505 key in case we will need it later for combined rsa-rhosts
506 authentication. This must be done before releasing extra
507 privileges, because the file is only readable by root. */
509 host_private_key = RSA_new();
510 if (load_private_key(HOST_KEY_FILE, "", host_private_key, NULL))
511 host_private_key_loaded = 1;
513 /* Get rid of any extra privileges that we may have. We will no
514 longer need them. Also, extra privileges could make it very
515 hard to read identity files and other non-world-readable files
516 from the user's home directory if it happens to be on a NFS
517 volume where root is mapped to nobody. */
519 /* Note that some legacy systems need to postpone the following
520 call to permanently_set_uid() until the private hostkey is
521 destroyed with RSA_free(). Otherwise the calling user could
522 ptrace() the process, read the private hostkey and impersonate
523 the host. OpenBSD does not allow ptracing of setuid processes. */
525 permanently_set_uid(original_real_uid);
527 /* Now that we are back to our own permissions, create ~/.ssh
528 directory if it doesn\'t already exist. */
529 snprintf(buf, sizeof buf, "%.100s/%.100s", pw->pw_dir, SSH_USER_DIR);
530 if (stat(buf, &st) < 0)
531 if (mkdir(buf, 0755) < 0)
532 error("Could not create directory '%.200s'.", buf);
534 /* Check if the connection failed, and try "rsh" if appropriate. */
536 if (options.port != 0)
537 log("Secure connection to %.100s on port %d refused%.100s.",
539 options.fallback_to_rsh ? "; reverting to insecure method" : "");
541 log("Secure connection to %.100s refused%.100s.", host,
542 options.fallback_to_rsh ? "; reverting to insecure method" : "");
544 if (options.fallback_to_rsh) {
545 rsh_connect(host, options.user, &command);
546 fatal("rsh_connect returned");
550 /* Expand ~ in options.identity_files. */
551 for (i = 0; i < options.num_identity_files; i++)
552 options.identity_files[i] =
553 tilde_expand_filename(options.identity_files[i], original_real_uid);
555 /* Expand ~ in known host file names. */
556 options.system_hostfile = tilde_expand_filename(options.system_hostfile,
558 options.user_hostfile = tilde_expand_filename(options.user_hostfile,
561 /* Log into the remote system. This never returns if the login fails. */
562 ssh_login(host_private_key_loaded, host_private_key,
563 host, &hostaddr, original_real_uid);
565 /* We no longer need the host private key. Clear it now. */
566 if (host_private_key_loaded)
567 RSA_free(host_private_key); /* Destroys contents safely */
569 /* Close connection cleanly after attack. */
570 cipher_attack_detected = packet_disconnect;
572 /* If requested, fork and let ssh continue in the background. */
573 if (fork_after_authentication_flag) {
576 fatal("fork failed: %.100s", strerror(errno));
581 /* Enable compression if requested. */
582 if (options.compression) {
583 debug("Requesting compression at level %d.", options.compression_level);
585 if (options.compression_level < 1 || options.compression_level > 9)
586 fatal("Compression level must be from 1 (fast) to 9 (slow, best).");
588 /* Send the request. */
589 packet_start(SSH_CMSG_REQUEST_COMPRESSION);
590 packet_put_int(options.compression_level);
593 type = packet_read(&plen);
594 if (type == SSH_SMSG_SUCCESS)
595 packet_start_compression(options.compression_level);
596 else if (type == SSH_SMSG_FAILURE)
597 log("Warning: Remote host refused compression.");
599 packet_disconnect("Protocol error waiting for compression response.");
601 /* Allocate a pseudo tty if appropriate. */
603 debug("Requesting pty.");
605 /* Start the packet. */
606 packet_start(SSH_CMSG_REQUEST_PTY);
608 /* Store TERM in the packet. There is no limit on the
609 length of the string. */
613 packet_put_string(cp, strlen(cp));
615 /* Store window size in the packet. */
616 if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) < 0)
617 memset(&ws, 0, sizeof(ws));
618 packet_put_int(ws.ws_row);
619 packet_put_int(ws.ws_col);
620 packet_put_int(ws.ws_xpixel);
621 packet_put_int(ws.ws_ypixel);
623 /* Store tty modes in the packet. */
624 tty_make_modes(fileno(stdin));
626 /* Send the packet, and wait for it to leave. */
630 /* Read response from the server. */
631 type = packet_read(&plen);
632 if (type == SSH_SMSG_SUCCESS)
634 else if (type == SSH_SMSG_FAILURE)
635 log("Warning: Remote host failed or refused to allocate a pseudo tty.");
637 packet_disconnect("Protocol error waiting for pty request response.");
639 /* Request X11 forwarding if enabled and DISPLAY is set. */
640 if (options.forward_x11 && getenv("DISPLAY") != NULL) {
641 char line[512], proto[512], data[512];
643 int forwarded = 0, got_data = 0, i;
646 /* Try to get Xauthority information for the display. */
647 snprintf(line, sizeof line, "%.100s list %.200s 2>/dev/null",
648 XAUTH_PATH, getenv("DISPLAY"));
649 f = popen(line, "r");
650 if (f && fgets(line, sizeof(line), f) &&
651 sscanf(line, "%*s %s %s", proto, data) == 2)
655 #endif /* XAUTH_PATH */
656 /* If we didn't get authentication data, just make up some
657 data. The forwarding code will check the validity of
658 the response anyway, and substitute this data. The X11
659 server, however, will ignore this fake data and use
660 whatever authentication mechanisms it was using
661 otherwise for the local connection. */
665 strlcpy(proto, "MIT-MAGIC-COOKIE-1", sizeof proto);
666 for (i = 0; i < 16; i++) {
669 snprintf(data + 2 * i, sizeof data - 2 * i, "%02x", rand & 0xff);
673 /* Got local authentication reasonable information.
674 Request forwarding with authentication spoofing. */
675 debug("Requesting X11 forwarding with authentication spoofing.");
676 x11_request_forwarding_with_spoofing(proto, data);
678 /* Read response from the server. */
679 type = packet_read(&plen);
680 if (type == SSH_SMSG_SUCCESS) {
683 } else if (type == SSH_SMSG_FAILURE)
684 log("Warning: Remote host denied X11 forwarding.");
686 packet_disconnect("Protocol error waiting for X11 forwarding");
688 /* Tell the packet module whether this is an interactive session. */
689 packet_set_interactive(interactive, options.keepalives);
691 /* Clear agent forwarding if we don\'t have an agent. */
692 authfd = ssh_get_authentication_socket();
694 options.forward_agent = 0;
696 ssh_close_authentication_socket(authfd);
698 /* Request authentication agent forwarding if appropriate. */
699 if (options.forward_agent) {
700 debug("Requesting authentication agent forwarding.");
701 auth_request_forwarding();
703 /* Read response from the server. */
704 type = packet_read(&plen);
705 packet_integrity_check(plen, 0, type);
706 if (type != SSH_SMSG_SUCCESS)
707 log("Warning: Remote host denied authentication agent forwarding.");
709 /* Initiate local TCP/IP port forwardings. */
710 for (i = 0; i < options.num_local_forwards; i++) {
711 debug("Connections to local port %d forwarded to remote address %.200s:%d",
712 options.local_forwards[i].port,
713 options.local_forwards[i].host,
714 options.local_forwards[i].host_port);
715 channel_request_local_forwarding(options.local_forwards[i].port,
716 options.local_forwards[i].host,
717 options.local_forwards[i].host_port);
720 /* Initiate remote TCP/IP port forwardings. */
721 for (i = 0; i < options.num_remote_forwards; i++) {
722 debug("Connections to remote port %d forwarded to local address %.200s:%d",
723 options.remote_forwards[i].port,
724 options.remote_forwards[i].host,
725 options.remote_forwards[i].host_port);
726 channel_request_remote_forwarding(options.remote_forwards[i].port,
727 options.remote_forwards[i].host,
728 options.remote_forwards[i].host_port);
731 /* If a command was specified on the command line, execute the
732 command now. Otherwise request the server to start a shell. */
733 if (buffer_len(&command) > 0) {
734 int len = buffer_len(&command);
737 debug("Sending command: %.*s", len, buffer_ptr(&command));
738 packet_start(SSH_CMSG_EXEC_CMD);
739 packet_put_string(buffer_ptr(&command), buffer_len(&command));
743 debug("Requesting shell.");
744 packet_start(SSH_CMSG_EXEC_SHELL);
749 /* Enter the interactive session. */
750 exit_status = client_loop(tty_flag, tty_flag ? options.escape_char : -1);
752 /* Close the connection to the remote host. */
755 /* Exit with the status returned by the program on the remote side. */