[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 and 1.51.2.5

version 1.51, 2000/05/08 17:12:15 version 1.51.2.5, 2001/03/21 18:53:13
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.
  *   *
  * Modified to work with SSL by Niels Provos <provos@citi.umich.edu> in Canada.   * As far as I am concerned, the code I have written for this software
    * 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("$Id$");  RCSID("$OpenBSD$");
   
 #include <openssl/evp.h>  #include <openssl/evp.h>
 #include <openssl/dsa.h>  #include <openssl/err.h>
 #include <openssl/rsa.h>  
   
 #include "xmalloc.h"  
 #include "ssh.h"  #include "ssh.h"
   #include "ssh1.h"
   #include "ssh2.h"
   #include "compat.h"
   #include "cipher.h"
   #include "xmalloc.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 42 
Line 79 
   
 /* 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 84 
Line 122 
  */   */
 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 99 
Line 134 
 /* 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()  usage(void)
 {  {
         fprintf(stderr, "Usage: %s [options] host [command]\n", av0);          fprintf(stderr, "Usage: %s [options] host [command]\n", __progname);
         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 /dev/null.\n");          fprintf(stderr, "  -n          Redirect input from " _PATH_DEVNULL ".\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          Disable X11 connection forwarding.\n");          fprintf(stderr, "  -x          Disable X11 connection forwarding.\n");
         fprintf(stderr, "  -i file     Identity for RSA authentication (default: ~/.ssh/identity).\n");          fprintf(stderr, "  -i file     Identity for public key authentication "
               "(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 124 
Line 166 
         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'', "              "``3des'', ``blowfish''\n");
                         "``blowfish''\n");          fprintf(stderr, "  -m macs     Specify MAC algorithms for protocol version 2.\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", av0);          fprintf(stderr, "              These cause %s to listen for connections on a port, and\n", __progname);
         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 179 
Line 223 
         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 192 
Line 237 
         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, pwcopy;          struct passwd *pw;
         int dummy;          int dummy;
         uid_t original_effective_uid;          uid_t original_effective_uid;
   
Line 227 
Line 272 
          */           */
         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 262 
Line 295 
                 opt = av[optind][1];                  opt = av[optind][1];
                 if (!opt)                  if (!opt)
                         usage();                          usage();
                 if (strchr("eilcpLRo", opt)) {  /* options with arguments */                  if (strchr("eilcmpLRo", 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 275 
Line 308 
                         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 306 
Line 342 
                 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 315 
Line 354 
                 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++] =                          options.identity_files[options.num_identity_files++] = xstrdup(optarg);
                                 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, "SSH Version %s, protocol versions %d.%d/%d.%d.\n",                          fprintf(stderr,
                               "%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,
                         fprintf(stderr, "Compiled with SSL (0x%8.8lx).\n", SSLeay());                              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 &&
                             (unsigned char) optarg[1] >= 64 && (unsigned char) optarg[1] < 128)                              (u_char) optarg[1] >= 64 && (u_char) optarg[1] < 128)
                                 options.escape_char = (unsigned char) optarg[1] & 31;                                  options.escape_char = (u_char) optarg[1] & 31;
                         else if (strlen(optarg) == 1)                          else if (strlen(optarg) == 1)
                                 options.escape_char = (unsigned char) optarg[0];                                  options.escape_char = (u_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 367 
Line 416 
                                         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 413 
Line 477 
                                          "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 422 
Line 489 
         if (!host)          if (!host)
                 usage();                  usage();
   
         OpenSSL_add_all_algorithms();          SSLeay_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 435 
Line 503 
         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 446 
Line 518 
         }          }
   
         /* Cannot fork to background if no command. */          /* Cannot fork to background if no command. */
         if (fork_after_authentication_flag && buffer_len(&command) == 0)          if (fork_after_authentication_flag && buffer_len(&command) == 0 && !no_shell_flag)
                 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))) {          if (!isatty(fileno(stdin)) && !force_tty_flag) {
                 if (tty_flag)                  if (tty_flag)
                         fprintf(stderr, "Pseudo-terminal will not be allocated because stdin is not a terminal.\n");                          log("Pseudo-terminal will not be allocated because stdin is not a terminal.");
                 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) {
                 fprintf(stderr, "You don't exist, go away!\n");                  log("You don't exist, go away!");
                 exit(1);                  exit(1);
         }          }
         /* Take a copy of the returned structure. */          /* Take a copy of the returned structure. */
         memset(&pwcopy, 0, sizeof(pwcopy));          pw = pwcopy(pw);
         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          /*
            actually goes to the terminal. */           * Initialize "log" output.  Since we are the client all output
         log_init(av[0], options.log_level, SYSLOG_FACILITY_USER, 0);           * actually goes to stderr.
            */
           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, SSH_USER_CONFFILE);          snprintf(buf, sizeof buf, "%.100s/%.100s", pw->pw_dir, _PATH_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(HOST_CONFIG_FILE, host, &options);          read_config_file(_PATH_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, 0);          log_init(av[0], options.log_level, SYSLOG_FACILITY_USER, 1);
   
         /* 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 558 
Line 596 
         /* 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,
                          !options.rhosts_authentication &&              original_effective_uid != 0 || !options.use_privileged_port,
                          !options.rhosts_rsa_authentication,              original_real_uid,
                          original_real_uid,              options.proxy_command);
                          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 579 
Line 613 
         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_RSA;                  k.type = KEY_RSA1;
                 k.rsa = host_private_key;                  k.rsa = host_private_key;
                 if (load_private_key(HOST_KEY_FILE, "", &k, NULL))                  if (load_private_key(_PATH_HOST_KEY_FILE, "", &k, NULL))
                         host_private_key_loaded = 1;                          host_private_key_loaded = 1;
         }          }
         /*          /*
Line 605 
Line 639 
          * 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, SSH_USER_DIR);          snprintf(buf, sizeof buf, "%.100s/%.100s", pw->pw_dir, _PATH_SSH_USER_DIR);
         if (stat(buf, &st) < 0)          if (stat(buf, &st) < 0)
                 if (mkdir(buf, 0755) < 0)                  if (mkdir(buf, 0700) < 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 626 
Line 660 
                 }                  }
                 exit(1);                  exit(1);
         }          }
         /* Expand ~ in options.identity_files. */          /* load options.identity_files */
         /* XXX mem-leaks */          load_public_identity_files();
         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. */
         options.system_hostfile = tilde_expand_filename(options.system_hostfile,          /* XXX mem-leaks: */
             original_real_uid);          options.system_hostfile =
         options.user_hostfile = tilde_expand_filename(options.user_hostfile,              tilde_expand_filename(options.system_hostfile, original_real_uid);
             original_real_uid);          options.user_hostfile =
         options.system_hostfile2 = tilde_expand_filename(options.system_hostfile2,              tilde_expand_filename(options.user_hostfile, original_real_uid);
             original_real_uid);          options.system_hostfile2 =
         options.user_hostfile2 = tilde_expand_filename(options.user_hostfile2,              tilde_expand_filename(options.system_hostfile2, original_real_uid);
             original_real_uid);          options.user_hostfile2 =
               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 664 
Line 694 
         FILE *f;          FILE *f;
         int got_data = 0, i;          int got_data = 0, i;
   
 #ifdef XAUTH_PATH          if (options.xauth_location) {
         /* Try to get Xauthority information for the display. */                  /* Try to get Xauthority information for the display. */
         snprintf(line, sizeof line, "%.100s list %.200s 2>/dev/null",                  snprintf(line, sizeof line, "%.100s list %.200s 2>" _PATH_DEVNULL,
                  XAUTH_PATH, getenv("DISPLAY"));                      options.xauth_location, 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 696 
Line 726 
         }          }
 }  }
   
   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 787 
Line 862 
                 }                  }
         }          }
         /* Tell the packet module whether this is an interactive session. */          /* Tell the packet module whether this is an interactive session. */
         packet_set_interactive(interactive, options.keepalives);          packet_set_interactive(interactive);
   
         /* Clear agent forwarding if we don\'t have an agent. */  
         authfd = ssh_get_authentication_socket();  
         if (authfd < 0)  
                 options.forward_agent = 0;  
         else  
                 ssh_close_authentication_socket(authfd);  
   
         /* Request authentication agent forwarding if appropriate. */          /* Request authentication agent forwarding if appropriate. */
           check_agent_present();
   
         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 807 
Line 877 
                 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 remote TCP/IP port forwardings. */          /* Initiate port forwardings. */
         for (i = 0; i < options.num_remote_forwards; i++) {          ssh_init_forwarding();
                 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 856 
Line 907 
         }          }
   
         /* Enter the interactive session. */          /* Enter the interactive session. */
         return client_loop(have_tty, tty_flag ? options.escape_char : -1);          return client_loop(have_tty, tty_flag ? options.escape_char : -1, 0);
 }  }
   
 void  void
 init_local_fwd(void)  client_subsystem_reply(int type, int plen, void *ctxt)
 {  {
         int i;          int id, len;
         /* Initiate local TCP/IP port forwardings. */  
         for (i = 0; i < options.num_local_forwards; i++) {          id = packet_get_int();
                 debug("Connections to local port %d forwarded to remote address %.200s:%d",          len = buffer_len(&command);
                       options.local_forwards[i].port,          if (len > 900)
                       options.local_forwards[i].host,                  len = 900;
                       options.local_forwards[i].host_port);          packet_done();
                 channel_request_local_forwarding(options.local_forwards[i].port,          if (type == SSH2_MSG_CHANNEL_FAILURE)
                                                  options.local_forwards[i].host,                  fatal("Request for subsystem '%.*s' failed on channel %d",
                                                  options.local_forwards[i].host_port,                      len, buffer_ptr(&command), id);
                                                  options.gateway_ports);  
         }  
 }  }
   
 extern void client_set_session_ident(int id);  
   
 void  void
 client_init(int id, void *arg)  ssh_session2_callback(int id, void *arg)
 {  {
         int len;          int len;
         debug("client_init id %d arg %d", id, (int)arg);          int interactive = 0;
   
           debug("client_init id %d arg %ld", id, (long)arg);
   
         if (no_shell_flag)          if (no_shell_flag)
                 goto done;                  goto done;
   
Line 905 
Line 954 
                 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 915 
Line 965 
                 /* 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;
                 debug("Sending command: %.*s", len, buffer_ptr(&command));                  if (subsystem_flag) {
                 channel_request_start(id, "exec", 0);                          debug("Sending subsystem: %.*s", len, buffer_ptr(&command));
                 packet_put_string(buffer_ptr(&command), len);                          channel_request_start(id, "subsystem", /*want reply*/ 1);
                           /* 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 */
         client_set_session_ident(id);          packet_set_interactive(interactive);
 }  }
   
 int  int
 ssh_session2(void)  ssh_session2(void)
 {  {
         int window, packetmax, id;          int window, packetmax, id;
         int in  = dup(STDIN_FILENO);          int in, out, err;
         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("dump in/out/err failed");                  fatal("dup() in/out/err failed");
   
         /* should be pre-session */          /* enable nonblocking unless tty */
         init_local_fwd();          if (!isatty(in))
                   set_nonblock(in);
         window = 32*1024;          if (!isatty(out))
         if (tty_flag) {                  set_nonblock(out);
                 packetmax = window/8;          if (!isatty(err))
         } else {                  set_nonblock(err);
   
           /* 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 = window/2;                  packetmax *=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, xstrdup("client-session"));              window, packetmax, CHAN_EXTENDED_WRITE,
               xstrdup("client-session"), /*nonblock*/0);
   
   
         channel_open(id);          channel_open(id);
         channel_register_callback(id, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, client_init, (void *)0);          channel_register_callback(id, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION,
                ssh_session2_callback, (void *)0);
   
         return client_loop(tty_flag, tty_flag ? options.escape_char : -1);          return client_loop(tty_flag, tty_flag ? options.escape_char : -1, id);
   }
   
   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  
changed lines
  Added in v.1.51.2.5