[BACK]Return to ssh.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / ssh

Diff for /src/usr.bin/ssh/ssh.c between version 1.51.2.5 and 1.52

version 1.51.2.5, 2001/03/21 18:53:13 version 1.52, 2000/05/15 06:52:55
Line 2 
Line 2 
  * Author: Tatu Ylonen <ylo@cs.hut.fi>   * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland   * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
  *                    All rights reserved   *                    All rights reserved
    * Created: Sat Mar 18 16:36:11 1995 ylo
  * Ssh client program.  This program can be used to log into a remote machine.   * Ssh client program.  This program can be used to log into a remote machine.
  * The software supports strong authentication, encryption, and forwarding   * The software supports strong authentication, encryption, and forwarding
  * of X11, TCP/IP, and authentication connections.   * of X11, TCP/IP, and authentication connections.
  *   *
  * As far as I am concerned, the code I have written for this software   * Modified to work with SSL by Niels Provos <provos@citi.umich.edu> in Canada.
  * can be used freely for any purpose.  Any derived versions of this  
  * software must be clearly marked as such, and if the derived work is  
  * incompatible with the protocol description in the RFC file, it must be  
  * called by a name other than "ssh" or "Secure Shell".  
  *  
  * Copyright (c) 1999 Niels Provos.  All rights reserved.  
  *  
  * Modified to work with SSL by Niels Provos <provos@citi.umich.edu>  
  * in Canada (German citizen).  
  *  
  * Redistribution and use in source and binary forms, with or without  
  * modification, are permitted provided that the following conditions  
  * are met:  
  * 1. Redistributions of source code must retain the above copyright  
  *    notice, this list of conditions and the following disclaimer.  
  * 2. Redistributions in binary form must reproduce the above copyright  
  *    notice, this list of conditions and the following disclaimer in the  
  *    documentation and/or other materials provided with the distribution.  
  *  
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR  
  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES  
  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  
  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,  
  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT  
  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,  
  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY  
  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT  
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF  
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  
  */   */
   
 #include "includes.h"  #include "includes.h"
 RCSID("$OpenBSD$");  RCSID("$Id$");
   
 #include <openssl/evp.h>  #include <openssl/evp.h>
 #include <openssl/err.h>  #include <openssl/dsa.h>
   #include <openssl/rsa.h>
   
 #include "ssh.h"  
 #include "ssh1.h"  
 #include "ssh2.h"  
 #include "compat.h"  
 #include "cipher.h"  
 #include "xmalloc.h"  #include "xmalloc.h"
   #include "ssh.h"
 #include "packet.h"  #include "packet.h"
 #include "buffer.h"  #include "buffer.h"
   #include "authfd.h"
   #include "readconf.h"
 #include "uidswap.h"  #include "uidswap.h"
   
   #include "ssh2.h"
   #include "compat.h"
 #include "channels.h"  #include "channels.h"
 #include "key.h"  #include "key.h"
 #include "authfd.h"  
 #include "authfile.h"  #include "authfile.h"
 #include "pathnames.h"  
 #include "clientloop.h"  
 #include "log.h"  
 #include "readconf.h"  
 #include "sshconnect.h"  
 #include "tildexpand.h"  
 #include "dispatch.h"  
 #include "misc.h"  
 #include "kex.h"  
 #include "mac.h"  
   
 extern char *__progname;  extern char *__progname;
   
Line 79 
Line 42 
   
 /* Flag indicating whether a tty should be allocated */  /* Flag indicating whether a tty should be allocated */
 int tty_flag = 0;  int tty_flag = 0;
 int no_tty_flag = 0;  
 int force_tty_flag = 0;  
   
 /* don't exec a shell */  /* don't exec a shell */
 int no_shell_flag = 0;  int no_shell_flag = 0;
   int no_tty_flag = 0;
   
 /*  /*
  * Flag indicating that nothing should be read from stdin.  This can be set   * Flag indicating that nothing should be read from stdin.  This can be set
Line 122 
Line 84 
  */   */
 volatile int received_window_change_signal = 0;  volatile int received_window_change_signal = 0;
   
   /* Value of argv[0] (set in the main program). */
   char *av0;
   
 /* Flag indicating whether we have a valid host private key loaded. */  /* Flag indicating whether we have a valid host private key loaded. */
 int host_private_key_loaded = 0;  int host_private_key_loaded = 0;
   
Line 134 
Line 99 
 /* command to be executed */  /* command to be executed */
 Buffer command;  Buffer command;
   
 /* Should we execute a command or invoke a subsystem? */  
 int subsystem_flag = 0;  
   
 /* Prints a help message to the user.  This function never returns. */  /* Prints a help message to the user.  This function never returns. */
   
 void  void
 usage(void)  usage()
 {  {
         fprintf(stderr, "Usage: %s [options] host [command]\n", __progname);          fprintf(stderr, "Usage: %s [options] host [command]\n", av0);
         fprintf(stderr, "Options:\n");          fprintf(stderr, "Options:\n");
         fprintf(stderr, "  -l user     Log in using this user name.\n");          fprintf(stderr, "  -l user     Log in using this user name.\n");
         fprintf(stderr, "  -n          Redirect input from " _PATH_DEVNULL ".\n");          fprintf(stderr, "  -n          Redirect input from /dev/null.\n");
         fprintf(stderr, "  -A          Enable authentication agent forwarding.\n");  
         fprintf(stderr, "  -a          Disable authentication agent forwarding.\n");          fprintf(stderr, "  -a          Disable authentication agent forwarding.\n");
 #ifdef AFS  #ifdef AFS
         fprintf(stderr, "  -k          Disable Kerberos ticket and AFS token forwarding.\n");          fprintf(stderr, "  -k          Disable Kerberos ticket and AFS token forwarding.\n");
 #endif                          /* AFS */  #endif                          /* AFS */
         fprintf(stderr, "  -X          Enable X11 connection forwarding.\n");          fprintf(stderr, "  -X          Enable X11 connection forwarding.\n");
         fprintf(stderr, "  -x          Disable X11 connection forwarding.\n");          fprintf(stderr, "  -x          Disable X11 connection forwarding.\n");
         fprintf(stderr, "  -i file     Identity for public key authentication "          fprintf(stderr, "  -i file     Identity for RSA authentication (default: ~/.ssh/identity).\n");
             "(default: ~/.ssh/identity)\n");  
         fprintf(stderr, "  -t          Tty; allocate a tty even if command is given.\n");          fprintf(stderr, "  -t          Tty; allocate a tty even if command is given.\n");
         fprintf(stderr, "  -T          Do not allocate a tty.\n");          fprintf(stderr, "  -T          Do not allocate a tty.\n");
         fprintf(stderr, "  -v          Verbose; display verbose debugging messages.\n");          fprintf(stderr, "  -v          Verbose; display verbose debugging messages.\n");
         fprintf(stderr, "              Multiple -v increases verbosity.\n");  
         fprintf(stderr, "  -V          Display version number only.\n");          fprintf(stderr, "  -V          Display version number only.\n");
         fprintf(stderr, "  -P          Don't allocate a privileged port.\n");          fprintf(stderr, "  -P          Don't allocate a privileged port.\n");
         fprintf(stderr, "  -q          Quiet; don't display any warning messages.\n");          fprintf(stderr, "  -q          Quiet; don't display any warning messages.\n");
Line 166 
Line 125 
         fprintf(stderr, "  -e char     Set escape character; ``none'' = disable (default: ~).\n");          fprintf(stderr, "  -e char     Set escape character; ``none'' = disable (default: ~).\n");
   
         fprintf(stderr, "  -c cipher   Select encryption algorithm: "          fprintf(stderr, "  -c cipher   Select encryption algorithm: "
             "``3des'', ``blowfish''\n");                          "``3des'', "
         fprintf(stderr, "  -m macs     Specify MAC algorithms for protocol version 2.\n");                          "``blowfish''\n");
         fprintf(stderr, "  -p port     Connect to this port.  Server must be on the same port.\n");          fprintf(stderr, "  -p port     Connect to this port.  Server must be on the same port.\n");
         fprintf(stderr, "  -L listen-port:host:port   Forward local port to remote address\n");          fprintf(stderr, "  -L listen-port:host:port   Forward local port to remote address\n");
         fprintf(stderr, "  -R listen-port:host:port   Forward remote port to local address\n");          fprintf(stderr, "  -R listen-port:host:port   Forward remote port to local address\n");
         fprintf(stderr, "              These cause %s to listen for connections on a port, and\n", __progname);          fprintf(stderr, "              These cause %s to listen for connections on a port, and\n", av0);
         fprintf(stderr, "              forward them to the other side by connecting to host:port.\n");          fprintf(stderr, "              forward them to the other side by connecting to host:port.\n");
         fprintf(stderr, "  -C          Enable compression.\n");          fprintf(stderr, "  -C          Enable compression.\n");
         fprintf(stderr, "  -N          Do not execute a shell or command.\n");          fprintf(stderr, "  -N          Do not execute a shell or command.\n");
         fprintf(stderr, "  -g          Allow remote hosts to connect to forwarded ports.\n");          fprintf(stderr, "  -g          Allow remote hosts to connect to forwarded ports.\n");
         fprintf(stderr, "  -1          Force protocol version 1.\n");  
         fprintf(stderr, "  -2          Force protocol version 2.\n");  
         fprintf(stderr, "  -4          Use IPv4 only.\n");          fprintf(stderr, "  -4          Use IPv4 only.\n");
         fprintf(stderr, "  -6          Use IPv6 only.\n");          fprintf(stderr, "  -6          Use IPv6 only.\n");
           fprintf(stderr, "  -2          Force protocol version 2.\n");
         fprintf(stderr, "  -o 'option' Process the option as if it was read from a configuration file.\n");          fprintf(stderr, "  -o 'option' Process the option as if it was read from a configuration file.\n");
         fprintf(stderr, "  -s          Invoke command (mandatory) as SSH2 subsystem.\n");  
         exit(1);          exit(1);
 }  }
   
Line 223 
Line 180 
         exit(1);          exit(1);
 }  }
   
 int     ssh_session(void);  int ssh_session(void);
 int     ssh_session2(void);  int ssh_session2(void);
 void    load_public_identity_files(void);  
   
 /*  /*
  * Main program for the ssh client.   * Main program for the ssh client.
Line 237 
Line 193 
         u_short fwd_port, fwd_host_port;          u_short fwd_port, fwd_host_port;
         char *optarg, *cp, buf[256];          char *optarg, *cp, buf[256];
         struct stat st;          struct stat st;
         struct passwd *pw;          struct passwd *pw, pwcopy;
         int dummy;          int dummy;
         uid_t original_effective_uid;          uid_t original_effective_uid;
   
Line 272 
Line 228 
          */           */
         umask(022);          umask(022);
   
           /* Save our own name. */
           av0 = av[0];
   
         /* Initialize option structure to indicate that no values have been set. */          /* Initialize option structure to indicate that no values have been set. */
         initialize_options(&options);          initialize_options(&options);
   
         /* Parse command-line arguments. */          /* Parse command-line arguments. */
         host = NULL;          host = NULL;
   
           /* If program name is not one of the standard names, use it as host name. */
           if (strchr(av0, '/'))
                   cp = strrchr(av0, '/') + 1;
           else
                   cp = av0;
           if (strcmp(cp, "rsh") != 0 && strcmp(cp, "ssh") != 0 &&
               strcmp(cp, "rlogin") != 0 && strcmp(cp, "slogin") != 0)
                   host = cp;
   
         for (optind = 1; optind < ac; optind++) {          for (optind = 1; optind < ac; optind++) {
                 if (av[optind][0] != '-') {                  if (av[optind][0] != '-') {
                         if (host)                          if (host)
Line 295 
Line 263 
                 opt = av[optind][1];                  opt = av[optind][1];
                 if (!opt)                  if (!opt)
                         usage();                          usage();
                 if (strchr("eilcmpLRo", opt)) { /* options with arguments */                  if (strchr("eilcpLRo", opt)) {  /* options with arguments */
                         optarg = av[optind] + 2;                          optarg = av[optind] + 2;
                         if (strcmp(optarg, "") == 0) {                          if (strcmp(optarg, "") == 0) {
                                 if (optind >= ac - 1)                                  if (optind >= ac - 1)
Line 308 
Line 276 
                         optarg = NULL;                          optarg = NULL;
                 }                  }
                 switch (opt) {                  switch (opt) {
                 case '1':  
                         options.protocol = SSH_PROTO_1;  
                         break;  
                 case '2':                  case '2':
                         options.protocol = SSH_PROTO_2;                          options.protocol = SSH_PROTO_2;
                         break;                          break;
Line 342 
Line 307 
                 case 'a':                  case 'a':
                         options.forward_agent = 0;                          options.forward_agent = 0;
                         break;                          break;
                 case 'A':  
                         options.forward_agent = 1;  
                         break;  
 #ifdef AFS  #ifdef AFS
                 case 'k':                  case 'k':
                         options.kerberos_tgt_passing = 0;                          options.kerberos_tgt_passing = 0;
Line 354 
Line 316 
                 case 'i':                  case 'i':
                         if (stat(optarg, &st) < 0) {                          if (stat(optarg, &st) < 0) {
                                 fprintf(stderr, "Warning: Identity file %s does not exist.\n",                                  fprintf(stderr, "Warning: Identity file %s does not exist.\n",
                                     optarg);                                          optarg);
                                 break;                                  break;
                         }                          }
                         if (options.num_identity_files >= SSH_MAX_IDENTITY_FILES)                          if (options.num_identity_files >= SSH_MAX_IDENTITY_FILES)
                                 fatal("Too many identity files specified (max %d)",                                  fatal("Too many identity files specified (max %d)",
                                     SSH_MAX_IDENTITY_FILES);                                        SSH_MAX_IDENTITY_FILES);
                         options.identity_files[options.num_identity_files++] = xstrdup(optarg);                          options.identity_files[options.num_identity_files++] =
                                   xstrdup(optarg);
                         break;                          break;
                 case 't':                  case 't':
                         if (tty_flag)  
                                 force_tty_flag = 1;  
                         tty_flag = 1;                          tty_flag = 1;
                         break;                          break;
                 case 'v':                  case 'v':
                         if (0 == debug_flag) {  
                                 debug_flag = 1;  
                                 options.log_level = SYSLOG_LEVEL_DEBUG1;  
                         } else if (options.log_level < SYSLOG_LEVEL_DEBUG3) {  
                                 options.log_level++;  
                                 break;  
                         } else {  
                                 fatal("Too high debugging level.");  
                         }  
                         /* fallthrough */  
                 case 'V':                  case 'V':
                         fprintf(stderr,                          fprintf(stderr, "SSH Version %s, protocol versions %d.%d/%d.%d.\n",
                             "%s, SSH protocols %d.%d/%d.%d, OpenSSL 0x%8.8lx\n",  
                             SSH_VERSION,                              SSH_VERSION,
                             PROTOCOL_MAJOR_1, PROTOCOL_MINOR_1,                              PROTOCOL_MAJOR_1, PROTOCOL_MINOR_1,
                             PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2,                              PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2);
                             SSLeay());                          fprintf(stderr, "Compiled with SSL (0x%8.8lx).\n", SSLeay());
                         if (opt == 'V')                          if (opt == 'V')
                                 exit(0);                                  exit(0);
                           debug_flag = 1;
                           options.log_level = SYSLOG_LEVEL_DEBUG;
                         break;                          break;
                 case 'q':                  case 'q':
                         options.log_level = SYSLOG_LEVEL_QUIET;                          options.log_level = SYSLOG_LEVEL_QUIET;
                         break;                          break;
                 case 'e':                  case 'e':
                         if (optarg[0] == '^' && optarg[2] == 0 &&                          if (optarg[0] == '^' && optarg[2] == 0 &&
                             (u_char) optarg[1] >= 64 && (u_char) optarg[1] < 128)                              (unsigned char) optarg[1] >= 64 && (unsigned char) optarg[1] < 128)
                                 options.escape_char = (u_char) optarg[1] & 31;                                  options.escape_char = (unsigned char) optarg[1] & 31;
                         else if (strlen(optarg) == 1)                          else if (strlen(optarg) == 1)
                                 options.escape_char = (u_char) optarg[0];                                  options.escape_char = (unsigned char) optarg[0];
                         else if (strcmp(optarg, "none") == 0)                          else if (strcmp(optarg, "none") == 0)
                                 options.escape_char = -2;                                  options.escape_char = -2;
                         else {                          else {
Line 416 
Line 368 
                                         fprintf(stderr, "Unknown cipher type '%s'\n", optarg);                                          fprintf(stderr, "Unknown cipher type '%s'\n", optarg);
                                         exit(1);                                          exit(1);
                                 }                                  }
                                 if (options.cipher == SSH_CIPHER_3DES) {  
                                         options.ciphers = "3des-cbc";  
                                 } else if (options.cipher == SSH_CIPHER_BLOWFISH) {  
                                         options.ciphers = "blowfish-cbc";  
                                 } else {  
                                         options.ciphers = (char *)-1;  
                                 }  
                         }                          }
                         break;                          break;
                 case 'm':  
                         if (mac_valid(optarg))  
                                 options.macs = xstrdup(optarg);  
                         else {  
                                 fprintf(stderr, "Unknown mac type '%s'\n", optarg);  
                                 exit(1);  
                         }  
                         break;  
                 case 'p':                  case 'p':
                         options.port = atoi(optarg);                          options.port = atoi(optarg);
                         break;                          break;
Line 477 
Line 414 
                                          "command-line", 0, &dummy) != 0)                                           "command-line", 0, &dummy) != 0)
                                 exit(1);                                  exit(1);
                         break;                          break;
                 case 's':  
                         subsystem_flag = 1;  
                         break;  
                 default:                  default:
                         usage();                          usage();
                 }                  }
Line 489 
Line 423 
         if (!host)          if (!host)
                 usage();                  usage();
   
         SSLeay_add_all_algorithms();          OpenSSL_add_all_algorithms();
         ERR_load_crypto_strings();  
   
         /* Initialize the command to execute on remote host. */          /* Initialize the command to execute on remote host. */
         buffer_init(&command);          buffer_init(&command);
Line 503 
Line 436 
         if (optind == ac) {          if (optind == ac) {
                 /* No command specified - execute shell on a tty. */                  /* No command specified - execute shell on a tty. */
                 tty_flag = 1;                  tty_flag = 1;
                 if (subsystem_flag) {  
                         fprintf(stderr, "You must specify a subsystem to invoke.");  
                         usage();  
                 }  
         } else {          } else {
                 /* A command has been specified.  Store it into the                  /* A command has been specified.  Store it into the
                    buffer. */                     buffer. */
Line 518 
Line 447 
         }          }
   
         /* Cannot fork to background if no command. */          /* Cannot fork to background if no command. */
         if (fork_after_authentication_flag && buffer_len(&command) == 0 && !no_shell_flag)          if (fork_after_authentication_flag && buffer_len(&command) == 0)
                 fatal("Cannot fork into background without a command to execute.");                  fatal("Cannot fork into background without a command to execute.");
   
         /* Allocate a tty by default if no command specified. */          /* Allocate a tty by default if no command specified. */
         if (buffer_len(&command) == 0)          if (buffer_len(&command) == 0)
                 tty_flag = 1;                  tty_flag = 1;
   
         /* Force no tty*/  
         if (no_tty_flag)  
                 tty_flag = 0;  
         /* Do not allocate a tty if stdin is not a tty. */          /* Do not allocate a tty if stdin is not a tty. */
         if (!isatty(fileno(stdin)) && !force_tty_flag) {          if (!isatty(fileno(stdin))) {
                 if (tty_flag)                  if (tty_flag)
                         log("Pseudo-terminal will not be allocated because stdin is not a terminal.");                          fprintf(stderr, "Pseudo-terminal will not be allocated because stdin is not a terminal.\n");
                 tty_flag = 0;                  tty_flag = 0;
         }          }
           /* force */
           if (no_tty_flag)
                   tty_flag = 0;
   
         /* Get user data. */          /* Get user data. */
         pw = getpwuid(original_real_uid);          pw = getpwuid(original_real_uid);
         if (!pw) {          if (!pw) {
                 log("You don't exist, go away!");                  fprintf(stderr, "You don't exist, go away!\n");
                 exit(1);                  exit(1);
         }          }
         /* Take a copy of the returned structure. */          /* Take a copy of the returned structure. */
         pw = pwcopy(pw);          memset(&pwcopy, 0, sizeof(pwcopy));
           pwcopy.pw_name = xstrdup(pw->pw_name);
           pwcopy.pw_passwd = xstrdup(pw->pw_passwd);
           pwcopy.pw_uid = pw->pw_uid;
           pwcopy.pw_gid = pw->pw_gid;
           pwcopy.pw_dir = xstrdup(pw->pw_dir);
           pwcopy.pw_shell = xstrdup(pw->pw_shell);
           pw = &pwcopy;
   
         /*          /* Initialize "log" output.  Since we are the client all output
          * Initialize "log" output.  Since we are the client all output             actually goes to the terminal. */
          * actually goes to stderr.          log_init(av[0], options.log_level, SYSLOG_FACILITY_USER, 0);
          */  
         log_init(av[0], SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_USER, 1);  
   
         /* Read per-user configuration file. */          /* Read per-user configuration file. */
         snprintf(buf, sizeof buf, "%.100s/%.100s", pw->pw_dir, _PATH_SSH_USER_CONFFILE);          snprintf(buf, sizeof buf, "%.100s/%.100s", pw->pw_dir, SSH_USER_CONFFILE);
         read_config_file(buf, host, &options);          read_config_file(buf, host, &options);
   
         /* Read systemwide configuration file. */          /* Read systemwide configuration file. */
         read_config_file(_PATH_HOST_CONFIG_FILE, host, &options);          read_config_file(HOST_CONFIG_FILE, host, &options);
   
         /* Fill configuration defaults. */          /* Fill configuration defaults. */
         fill_default_options(&options);          fill_default_options(&options);
   
         /* reinit */          /* reinit */
         log_init(av[0], options.log_level, SYSLOG_FACILITY_USER, 1);          log_init(av[0], options.log_level, SYSLOG_FACILITY_USER, 0);
   
           /* check if RSA support exists */
           if ((options.protocol & SSH_PROTO_1) &&
               rsa_alive() == 0) {
                   log("%s: no RSA support in libssl and libcrypto.  See ssl(8).",
                       __progname);
                   log("Disabling protocol version 1");
                   options.protocol &= ~ (SSH_PROTO_1|SSH_PROTO_1_PREFERRED);
           }
           if (! options.protocol & (SSH_PROTO_1|SSH_PROTO_2)) {
                   fprintf(stderr, "%s: No protocol version available.\n",
                       __progname);
                   exit(1);
           }
   
         if (options.user == NULL)          if (options.user == NULL)
                 options.user = xstrdup(pw->pw_name);                  options.user = xstrdup(pw->pw_name);
   
         if (options.hostname != NULL)          if (options.hostname != NULL)
                 host = options.hostname;                  host = options.hostname;
   
           /* Find canonic host name. */
           if (strchr(host, '.') == 0) {
                   struct addrinfo hints;
                   struct addrinfo *ai = NULL;
                   int errgai;
                   memset(&hints, 0, sizeof(hints));
                   hints.ai_family = IPv4or6;
                   hints.ai_flags = AI_CANONNAME;
                   hints.ai_socktype = SOCK_STREAM;
                   errgai = getaddrinfo(host, NULL, &hints, &ai);
                   if (errgai == 0) {
                           if (ai->ai_canonname != NULL)
                                   host = xstrdup(ai->ai_canonname);
                           freeaddrinfo(ai);
                   }
           }
         /* Disable rhosts authentication if not running as root. */          /* Disable rhosts authentication if not running as root. */
         if (original_effective_uid != 0 || !options.use_privileged_port) {          if (original_effective_uid != 0 || !options.use_privileged_port) {
                 debug("Rhosts Authentication disabled, "  
                     "originating port will not be trusted.");  
                 options.rhosts_authentication = 0;                  options.rhosts_authentication = 0;
                   options.rhosts_rsa_authentication = 0;
         }          }
         /*          /*
          * If using rsh has been selected, exec it now (without trying           * If using rsh has been selected, exec it now (without trying
Line 596 
Line 559 
         /* Restore our superuser privileges. */          /* Restore our superuser privileges. */
         restore_uid();          restore_uid();
   
         /* Open a connection to the remote host. */          /*
            * Open a connection to the remote host.  This needs root privileges
            * if rhosts_{rsa_}authentication is enabled.
            */
   
         ok = ssh_connect(host, &hostaddr, options.port,          ok = ssh_connect(host, &hostaddr, options.port,
             options.connection_attempts,                           options.connection_attempts,
             original_effective_uid != 0 || !options.use_privileged_port,                           !options.rhosts_authentication &&
             original_real_uid,                           !options.rhosts_rsa_authentication,
             options.proxy_command);                           original_real_uid,
                            options.proxy_command);
   
         /*          /*
          * If we successfully made the connection, load the host private key           * If we successfully made the connection, load the host private key
Line 613 
Line 580 
         if (ok && (options.protocol & SSH_PROTO_1)) {          if (ok && (options.protocol & SSH_PROTO_1)) {
                 Key k;                  Key k;
                 host_private_key = RSA_new();                  host_private_key = RSA_new();
                 k.type = KEY_RSA1;                  k.type = KEY_RSA;
                 k.rsa = host_private_key;                  k.rsa = host_private_key;
                 if (load_private_key(_PATH_HOST_KEY_FILE, "", &k, NULL))                  if (load_private_key(HOST_KEY_FILE, "", &k, NULL))
                         host_private_key_loaded = 1;                          host_private_key_loaded = 1;
         }          }
         /*          /*
Line 639 
Line 606 
          * Now that we are back to our own permissions, create ~/.ssh           * Now that we are back to our own permissions, create ~/.ssh
          * directory if it doesn\'t already exist.           * directory if it doesn\'t already exist.
          */           */
         snprintf(buf, sizeof buf, "%.100s/%.100s", pw->pw_dir, _PATH_SSH_USER_DIR);          snprintf(buf, sizeof buf, "%.100s/%.100s", pw->pw_dir, SSH_USER_DIR);
         if (stat(buf, &st) < 0)          if (stat(buf, &st) < 0)
                 if (mkdir(buf, 0700) < 0)                  if (mkdir(buf, 0755) < 0)
                         error("Could not create directory '%.200s'.", buf);                          error("Could not create directory '%.200s'.", buf);
   
         /* Check if the connection failed, and try "rsh" if appropriate. */          /* Check if the connection failed, and try "rsh" if appropriate. */
Line 660 
Line 627 
                 }                  }
                 exit(1);                  exit(1);
         }          }
         /* load options.identity_files */          /* Expand ~ in options.identity_files. */
         load_public_identity_files();          /* XXX mem-leaks */
           for (i = 0; i < options.num_identity_files; i++)
                   options.identity_files[i] =
                           tilde_expand_filename(options.identity_files[i], original_real_uid);
           for (i = 0; i < options.num_identity_files2; i++)
                   options.identity_files2[i] =
                           tilde_expand_filename(options.identity_files2[i], original_real_uid);
         /* Expand ~ in known host file names. */          /* Expand ~ in known host file names. */
         /* XXX mem-leaks: */          options.system_hostfile = tilde_expand_filename(options.system_hostfile,
         options.system_hostfile =              original_real_uid);
             tilde_expand_filename(options.system_hostfile, original_real_uid);          options.user_hostfile = tilde_expand_filename(options.user_hostfile,
         options.user_hostfile =              original_real_uid);
             tilde_expand_filename(options.user_hostfile, original_real_uid);          options.system_hostfile2 = tilde_expand_filename(options.system_hostfile2,
         options.system_hostfile2 =              original_real_uid);
             tilde_expand_filename(options.system_hostfile2, original_real_uid);          options.user_hostfile2 = tilde_expand_filename(options.user_hostfile2,
         options.user_hostfile2 =              original_real_uid);
             tilde_expand_filename(options.user_hostfile2, original_real_uid);  
   
         /* Log into the remote system.  This never returns if the login fails. */          /* Log into the remote system.  This never returns if the login fails. */
         ssh_login(host_private_key_loaded, host_private_key,          ssh_login(host_private_key_loaded, host_private_key,
Line 694 
Line 665 
         FILE *f;          FILE *f;
         int got_data = 0, i;          int got_data = 0, i;
   
         if (options.xauth_location) {  #ifdef XAUTH_PATH
                 /* Try to get Xauthority information for the display. */          /* Try to get Xauthority information for the display. */
                 snprintf(line, sizeof line, "%.100s list %.200s 2>" _PATH_DEVNULL,          snprintf(line, sizeof line, "%.100s list %.200s 2>/dev/null",
                     options.xauth_location, getenv("DISPLAY"));                   XAUTH_PATH, getenv("DISPLAY"));
                 f = popen(line, "r");          f = popen(line, "r");
                 if (f && fgets(line, sizeof(line), f) &&          if (f && fgets(line, sizeof(line), f) &&
                     sscanf(line, "%*s %s %s", proto, data) == 2)              sscanf(line, "%*s %s %s", proto, data) == 2)
                         got_data = 1;                  got_data = 1;
                 if (f)          if (f)
                         pclose(f);                  pclose(f);
         }  #endif /* XAUTH_PATH */
         /*          /*
          * If we didn't get authentication data, just make up some           * If we didn't get authentication data, just make up some
          * data.  The forwarding code will check the validity of the           * data.  The forwarding code will check the validity of the
Line 726 
Line 697 
         }          }
 }  }
   
 void  
 ssh_init_forwarding(void)  
 {  
         int success = 0;  
         int i;  
   
         /* Initiate local TCP/IP port forwardings. */  
         for (i = 0; i < options.num_local_forwards; i++) {  
                 debug("Connections to local port %d forwarded to remote address %.200s:%d",  
                     options.local_forwards[i].port,  
                     options.local_forwards[i].host,  
                     options.local_forwards[i].host_port);  
                 success += channel_request_local_forwarding(  
                     options.local_forwards[i].port,  
                     options.local_forwards[i].host,  
                     options.local_forwards[i].host_port,  
                     options.gateway_ports);  
         }  
         if (i > 0 && success == 0)  
                 error("Could not request local forwarding.");  
   
         /* Initiate remote TCP/IP port forwardings. */  
         for (i = 0; i < options.num_remote_forwards; i++) {  
                 debug("Connections to remote port %d forwarded to local address %.200s:%d",  
                     options.remote_forwards[i].port,  
                     options.remote_forwards[i].host,  
                     options.remote_forwards[i].host_port);  
                 channel_request_remote_forwarding(  
                     options.remote_forwards[i].port,  
                     options.remote_forwards[i].host,  
                     options.remote_forwards[i].host_port);  
         }  
 }  
   
 void  
 check_agent_present(void)  
 {  
         if (options.forward_agent) {  
                 /* Clear agent forwarding if we don\'t have an agent. */  
                 int authfd = ssh_get_authentication_socket();  
                 if (authfd < 0)  
                         options.forward_agent = 0;  
                 else  
                         ssh_close_authentication_socket(authfd);  
         }  
 }  
   
 int  int
 ssh_session(void)  ssh_session(void)
 {  {
         int type;          int type;
           int i;
         int plen;          int plen;
         int interactive = 0;          int interactive = 0;
         int have_tty = 0;          int have_tty = 0;
         struct winsize ws;          struct winsize ws;
           int authfd;
         char *cp;          char *cp;
   
         /* Enable compression if requested. */          /* Enable compression if requested. */
Line 862 
Line 788 
                 }                  }
         }          }
         /* Tell the packet module whether this is an interactive session. */          /* Tell the packet module whether this is an interactive session. */
         packet_set_interactive(interactive);          packet_set_interactive(interactive, options.keepalives);
   
         /* Request authentication agent forwarding if appropriate. */          /* Clear agent forwarding if we don\'t have an agent. */
         check_agent_present();          authfd = ssh_get_authentication_socket();
           if (authfd < 0)
                   options.forward_agent = 0;
           else
                   ssh_close_authentication_socket(authfd);
   
           /* Request authentication agent forwarding if appropriate. */
         if (options.forward_agent) {          if (options.forward_agent) {
                 debug("Requesting authentication agent forwarding.");                  debug("Requesting authentication agent forwarding.");
                 auth_request_forwarding();                  auth_request_forwarding();
Line 877 
Line 808 
                 if (type != SSH_SMSG_SUCCESS)                  if (type != SSH_SMSG_SUCCESS)
                         log("Warning: Remote host denied authentication agent forwarding.");                          log("Warning: Remote host denied authentication agent forwarding.");
         }          }
           /* Initiate local TCP/IP port forwardings. */
           for (i = 0; i < options.num_local_forwards; i++) {
                   debug("Connections to local port %d forwarded to remote address %.200s:%d",
                         options.local_forwards[i].port,
                         options.local_forwards[i].host,
                         options.local_forwards[i].host_port);
                   channel_request_local_forwarding(options.local_forwards[i].port,
                                                    options.local_forwards[i].host,
                                                    options.local_forwards[i].host_port,
                                                    options.gateway_ports);
           }
   
         /* Initiate port forwardings. */          /* Initiate remote TCP/IP port forwardings. */
         ssh_init_forwarding();          for (i = 0; i < options.num_remote_forwards; i++) {
                   debug("Connections to remote port %d forwarded to local address %.200s:%d",
                         options.remote_forwards[i].port,
                         options.remote_forwards[i].host,
                         options.remote_forwards[i].host_port);
                   channel_request_remote_forwarding(options.remote_forwards[i].port,
                                                     options.remote_forwards[i].host,
                                                     options.remote_forwards[i].host_port);
           }
   
         /* If requested, let ssh continue in the background. */          /* If requested, let ssh continue in the background. */
         if (fork_after_authentication_flag)          if (fork_after_authentication_flag)
Line 907 
Line 857 
         }          }
   
         /* Enter the interactive session. */          /* Enter the interactive session. */
         return client_loop(have_tty, tty_flag ? options.escape_char : -1, 0);          return client_loop(have_tty, tty_flag ? options.escape_char : -1);
 }  }
   
 void  void
 client_subsystem_reply(int type, int plen, void *ctxt)  init_local_fwd(void)
 {  {
         int id, len;          int i;
           /* Initiate local TCP/IP port forwardings. */
         id = packet_get_int();          for (i = 0; i < options.num_local_forwards; i++) {
         len = buffer_len(&command);                  debug("Connections to local port %d forwarded to remote address %.200s:%d",
         if (len > 900)                        options.local_forwards[i].port,
                 len = 900;                        options.local_forwards[i].host,
         packet_done();                        options.local_forwards[i].host_port);
         if (type == SSH2_MSG_CHANNEL_FAILURE)                  channel_request_local_forwarding(options.local_forwards[i].port,
                 fatal("Request for subsystem '%.*s' failed on channel %d",                                                   options.local_forwards[i].host,
                     len, buffer_ptr(&command), id);                                                   options.local_forwards[i].host_port,
                                                    options.gateway_ports);
           }
 }  }
   
   extern void client_set_session_ident(int id);
   
 void  void
 ssh_session2_callback(int id, void *arg)  client_init(int id, void *arg)
 {  {
         int len;          int len;
         int interactive = 0;          debug("client_init id %d arg %d", id, (int)arg);
   
         debug("client_init id %d arg %ld", id, (long)arg);  
   
         if (no_shell_flag)          if (no_shell_flag)
                 goto done;                  goto done;
   
Line 954 
Line 906 
                 packet_put_int(ws.ws_ypixel);                  packet_put_int(ws.ws_ypixel);
                 packet_put_cstring("");         /* XXX: encode terminal modes */                  packet_put_cstring("");         /* XXX: encode terminal modes */
                 packet_send();                  packet_send();
                 interactive = 1;  
                 /* XXX wait for reply */                  /* XXX wait for reply */
         }          }
         if (options.forward_x11 &&          if (options.forward_x11 &&
Line 965 
Line 916 
                 /* Request forwarding with authentication spoofing. */                  /* Request forwarding with authentication spoofing. */
                 debug("Requesting X11 forwarding with authentication spoofing.");                  debug("Requesting X11 forwarding with authentication spoofing.");
                 x11_request_forwarding_with_spoofing(id, proto, data);                  x11_request_forwarding_with_spoofing(id, proto, data);
                 interactive = 1;  
                 /* XXX wait for reply */                  /* XXX wait for reply */
         }          }
   
         check_agent_present();  
         if (options.forward_agent) {  
                 debug("Requesting authentication agent forwarding.");  
                 channel_request_start(id, "auth-agent-req@openssh.com", 0);  
                 packet_send();  
         }  
   
         len = buffer_len(&command);          len = buffer_len(&command);
         if (len > 0) {          if (len > 0) {
                 if (len > 900)                  if (len > 900)
                         len = 900;                          len = 900;
                 if (subsystem_flag) {                  debug("Sending command: %.*s", len, buffer_ptr(&command));
                         debug("Sending subsystem: %.*s", len, buffer_ptr(&command));                  channel_request_start(id, "exec", 0);
                         channel_request_start(id, "subsystem", /*want reply*/ 1);                  packet_put_string(buffer_ptr(&command), len);
                         /* register callback for reply */  
                         /* XXX we asume that client_loop has already been called */  
                         dispatch_set(SSH2_MSG_CHANNEL_FAILURE, &client_subsystem_reply);  
                         dispatch_set(SSH2_MSG_CHANNEL_SUCCESS, &client_subsystem_reply);  
                 } else {  
                         debug("Sending command: %.*s", len, buffer_ptr(&command));  
                         channel_request_start(id, "exec", 0);  
                 }  
                 packet_put_string(buffer_ptr(&command), buffer_len(&command));  
                 packet_send();                  packet_send();
         } else {          } else {
                 channel_request(id, "shell", 0);                  channel_request(id, "shell", 0);
         }          }
         /* channel_callback(id, SSH2_MSG_OPEN_CONFIGMATION, client_init, 0); */          /* channel_callback(id, SSH2_MSG_OPEN_CONFIGMATION, client_init, 0); */
   
 done:  done:
         /* register different callback, etc. XXX */          /* register different callback, etc. XXX */
         packet_set_interactive(interactive);          client_set_session_ident(id);
 }  }
   
 int  int
 ssh_session2(void)  ssh_session2(void)
 {  {
         int window, packetmax, id;          int window, packetmax, id;
         int in, out, err;          int in  = dup(STDIN_FILENO);
           int out = dup(STDOUT_FILENO);
           int err = dup(STDERR_FILENO);
   
         if (stdin_null_flag) {  
                 in = open(_PATH_DEVNULL, O_RDONLY);  
         } else {  
                 in = dup(STDIN_FILENO);  
         }  
         out = dup(STDOUT_FILENO);  
         err = dup(STDERR_FILENO);  
   
         if (in < 0 || out < 0 || err < 0)          if (in < 0 || out < 0 || err < 0)
                 fatal("dup() in/out/err failed");                  fatal("dump in/out/err failed");
   
         /* enable nonblocking unless tty */          /* should be pre-session */
         if (!isatty(in))          init_local_fwd();
                 set_nonblock(in);  
         if (!isatty(out))          window = 32*1024;
                 set_nonblock(out);          if (tty_flag) {
         if (!isatty(err))                  packetmax = window/8;
                 set_nonblock(err);          } else {
   
         /* XXX should be pre-session */  
         ssh_init_forwarding();  
   
         /* If requested, let ssh continue in the background. */  
         if (fork_after_authentication_flag)  
                 if (daemon(1, 1) < 0)  
                         fatal("daemon() failed: %.200s", strerror(errno));  
   
         window = CHAN_SES_WINDOW_DEFAULT;  
         packetmax = CHAN_SES_PACKET_DEFAULT;  
         if (!tty_flag) {  
                 window *= 2;                  window *= 2;
                 packetmax *=2;                  packetmax = window/2;
         }          }
   
         id = channel_new(          id = channel_new(
             "session", SSH_CHANNEL_OPENING, in, out, err,              "session", SSH_CHANNEL_OPENING, in, out, err,
             window, packetmax, CHAN_EXTENDED_WRITE,              window, packetmax, CHAN_EXTENDED_WRITE, xstrdup("client-session"));
             xstrdup("client-session"), /*nonblock*/0);  
   
   
         channel_open(id);          channel_open(id);
         channel_register_callback(id, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION,          channel_register_callback(id, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, client_init, (void *)0);
              ssh_session2_callback, (void *)0);  
   
         return client_loop(tty_flag, tty_flag ? options.escape_char : -1, id);          return client_loop(tty_flag, tty_flag ? options.escape_char : -1);
 }  
   
 int  
 guess_identity_file_type(const char *filename)  
 {  
         struct stat st;  
         Key *public;  
         int type = KEY_RSA1; /* default */  
   
         if (stat(filename, &st) < 0) {  
                 /* ignore this key */  
                 return KEY_UNSPEC;  
         }  
         public = key_new(type);  
         if (!load_public_key(filename, public, NULL)) {  
                 /* ok, so we will assume this is 'some' key */  
                 type = KEY_UNSPEC;  
         }  
         key_free(public);  
         return type;  
 }  
   
 void  
 load_public_identity_files(void)  
 {  
         char *filename;  
         Key *public;  
         int i;  
   
         for (i = 0; i < options.num_identity_files; i++) {  
                 filename = tilde_expand_filename(options.identity_files[i],  
                     original_real_uid);  
                 public = key_new(KEY_RSA1);  
                 if (!load_public_key(filename, public, NULL)) {  
                         key_free(public);  
                         public = key_new(KEY_UNSPEC);  
                         if (!try_load_public_key(filename, public, NULL)) {  
                                 debug("unknown identity file %s", filename);  
                                 key_free(public);  
                                 public = NULL;  
                         }  
                 }  
                 debug("identity file %s type %d", filename,  
                     public ? public->type : -1);  
                 xfree(options.identity_files[i]);  
                 options.identity_files[i] = filename;  
                 options.identity_keys[i] = public;  
         }  
 }  }

Legend:
Removed from v.1.51.2.5  
changed lines
  Added in v.1.52