[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.69 and 1.69.2.4

version 1.69, 2000/10/27 07:32:19 version 1.69.2.4, 2001/05/07 21:09:36
Line 42 
Line 42 
 RCSID("$OpenBSD$");  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 "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 "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"
   #include "sshtty.h"
   
 extern char *__progname;  extern char *__progname;
   
Line 70 
Line 80 
   
 /* 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 112 
Line 123 
  */   */
 volatile int received_window_change_signal = 0;  volatile int received_window_change_signal = 0;
   
 /* Value of argv[0] (set in the main program). */  /* Private host keys. */
 char *av0;  struct {
           Key     **keys;
           int     nkeys;
   } sensitive_data;
   
 /* Flag indicating whether we have a valid host private key loaded. */  
 int host_private_key_loaded = 0;  
   
 /* Host private key. */  
 RSA *host_private_key = NULL;  
   
 /* Original real UID. */  /* Original real UID. */
 uid_t original_real_uid;  uid_t original_real_uid;
   
 /* 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          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 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");
Line 155 
Line 167 
         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 210 
Line 224 
         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 223 
Line 238 
         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 241 
Line 256 
                 if (setrlimit(RLIMIT_CORE, &rlim) < 0)                  if (setrlimit(RLIMIT_CORE, &rlim) < 0)
                         fatal("setrlimit failed: %.100s", strerror(errno));                          fatal("setrlimit failed: %.100s", strerror(errno));
         }          }
           /* Get user data. */
           pw = getpwuid(original_real_uid);
           if (!pw) {
                   log("You don't exist, go away!");
                   exit(1);
           }
           /* Take a copy of the returned structure. */
           pw = pwcopy(pw);
   
         /*          /*
          * Use uid-swapping to give up root privileges for the duration of           * Use uid-swapping to give up root privileges for the duration of
          * option processing.  We will re-instantiate the rights when we are           * option processing.  We will re-instantiate the rights when we are
Line 248 
Line 272 
          * them when the port has been created (actually, when the connection           * them when the port has been created (actually, when the connection
          * has been made, as we may need to create the port several times).           * has been made, as we may need to create the port several times).
          */           */
         temporarily_use_uid(original_real_uid);          temporarily_use_uid(pw);
   
         /*          /*
          * Set our umask to something reasonable, as some files are created           * Set our umask to something reasonable, as some files are created
Line 258 
Line 282 
          */           */
         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") && strcmp(cp, "ssh") && strcmp(cp, "rlogin") &&  
             strcmp(cp, "slogin") && strcmp(cp, "remsh"))  
                 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 293 
Line 305 
                 opt = av[optind][1];                  opt = av[optind][1];
                 if (!opt)                  if (!opt)
                         usage();                          usage();
                 if (strchr("eilcpLRo", opt)) {  /* options with arguments */                  if (strchr("eilcmpLRDo", 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 306 
Line 318 
                         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 349 
Line 364 
                 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':
Line 369 
Line 385 
                                 options.log_level++;                                  options.log_level++;
                                 break;                                  break;
                         } else {                          } else {
                                 fatal("Too high debugging level.\n");                                  fatal("Too high debugging level.");
                         }                          }
                         /* fallthrough */                          /* 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);
                         break;                          break;
Line 386 
Line 403 
                         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 404 
Line 421 
                                 options.cipher = SSH_CIPHER_ILLEGAL;                                  options.cipher = SSH_CIPHER_ILLEGAL;
                         } else {                          } else {
                                 /* SSH1 only */                                  /* SSH1 only */
                                 Cipher *c = cipher_by_name(optarg);                                  options.cipher = cipher_number(optarg);
                                 if (c == NULL || c->number < 0) {                                  if (options.cipher == -1) {
                                         fprintf(stderr, "Unknown cipher type '%s'\n", optarg);                                          fprintf(stderr, "Unknown cipher type '%s'\n", optarg);
                                         exit(1);                                          exit(1);
                                 }                                  }
                                 options.cipher = c->number;                                  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 = a2port(optarg);
                           if (options.port == 0) {
                                   fprintf(stderr, "Bad port '%s'\n", optarg);
                                   exit(1);
                           }
                         break;                          break;
                 case 'l':                  case 'l':
                         options.user = optarg;                          options.user = optarg;
Line 440 
Line 475 
                         }                          }
                         add_local_forward(&options, fwd_port, buf, fwd_host_port);                          add_local_forward(&options, fwd_port, buf, fwd_host_port);
                         break;                          break;
   
                   case 'D':
                           fwd_port = a2port(optarg);
                           if (fwd_port == 0) {
                                   fprintf(stderr, "Bad dynamic port '%s'\n", optarg);
                                   exit(1);
                           }
                           add_local_forward(&options, fwd_port, "socks4", 0);
                           break;
   
                 case 'C':                  case 'C':
                         options.compression = 1;                          options.compression = 1;
                         break;                          break;
Line 456 
Line 501 
                                          "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 466 
Line 514 
                 usage();                  usage();
   
         SSLeay_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 478 
Line 527 
         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.\n");
                           usage();
                   }
         } else {          } else {
                 /* A command has been specified.  Store it into the                  /* A command has been specified.  Store it into the
                    buffer. */                     buffer. */
Line 496 
Line 549 
         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. */          /*
         pw = getpwuid(original_real_uid);           * Initialize "log" output.  Since we are the client all output
         if (!pw) {           * actually goes to stderr.
                 fprintf(stderr, "You don't exist, go away!\n");           */
                 exit(1);          log_init(av[0], options.log_level == -1 ? SYSLOG_LEVEL_INFO : options.log_level,
         }              SYSLOG_FACILITY_USER, 1);
         /* Take a copy of the returned structure. */  
         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_class = xstrdup(pw->pw_class);  
         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. */  
         log_init(av[0], options.log_level, SYSLOG_FACILITY_USER, 0);  
   
         /* 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);
   
Line 562 
Line 587 
   
         /* 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 577 
Line 603 
                 restore_uid();                  restore_uid();
   
                 /* Switch to the original uid permanently. */                  /* Switch to the original uid permanently. */
                 permanently_set_uid(original_real_uid);                  permanently_set_uid(pw);
   
                 /* Execute rsh. */                  /* Execute rsh. */
                 rsh_connect(host, options.user, &command);                  rsh_connect(host, options.user, &command);
Line 586 
Line 612 
         /* 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,              pw, 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 604 
Line 625 
          * authentication. This must be done before releasing extra           * authentication. This must be done before releasing extra
          * privileges, because the file is only readable by root.           * privileges, because the file is only readable by root.
          */           */
         if (ok && (options.protocol & SSH_PROTO_1)) {          sensitive_data.nkeys = 0;
                 Key k;          sensitive_data.keys = NULL;
                 host_private_key = RSA_new();          if (ok && (options.rhosts_rsa_authentication ||
                 k.type = KEY_RSA;              options.hostbased_authentication)) {
                 k.rsa = host_private_key;                  sensitive_data.nkeys = 3;
                 if (load_private_key(HOST_KEY_FILE, "", &k, NULL))                  sensitive_data.keys = xmalloc(sensitive_data.nkeys*sizeof(Key));
                         host_private_key_loaded = 1;                  sensitive_data.keys[0] = key_load_private_type(KEY_RSA1,
                       _PATH_HOST_KEY_FILE, "", NULL);
                   sensitive_data.keys[1] = key_load_private_type(KEY_DSA,
                       _PATH_HOST_DSA_KEY_FILE, "", NULL);
                   sensitive_data.keys[2] = key_load_private_type(KEY_RSA,
                       _PATH_HOST_RSA_KEY_FILE, "", NULL);
         }          }
         /*          /*
          * Get rid of any extra privileges that we may have.  We will no           * Get rid of any extra privileges that we may have.  We will no
Line 627 
Line 653 
          * process, read the private hostkey and impersonate the host.           * process, read the private hostkey and impersonate the host.
          * OpenBSD does not allow ptracing of setuid processes.           * OpenBSD does not allow ptracing of setuid processes.
          */           */
         permanently_set_uid(original_real_uid);          permanently_set_uid(pw);
   
         /*          /*
          * 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, 0700) < 0)                  if (mkdir(buf, 0700) < 0)
                         error("Could not create directory '%.200s'.", buf);                          error("Could not create directory '%.200s'.", buf);
Line 654 
Line 680 
                 }                  }
                 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(sensitive_data.keys, sensitive_data.nkeys,
                   host, (struct sockaddr *)&hostaddr, original_real_uid);              host, (struct sockaddr *)&hostaddr, pw);
   
         /* We no longer need the host private key.  Clear it now. */          /* We no longer need the private host keys.  Clear them now. */
         if (host_private_key_loaded)          if (sensitive_data.nkeys != 0) {
                 RSA_free(host_private_key);     /* Destroys contents safely */                  for (i = 0; i < sensitive_data.nkeys; i++) {
                           if (sensitive_data.keys[i] != NULL) {
                                   /* Destroys contents safely */
                                   debug3("clear hostkey %d", i);
                                   key_free(sensitive_data.keys[i]);
                                   sensitive_data.keys[i] = NULL;
                           }
                   }
                   xfree(sensitive_data.keys);
           }
   
         exit_status = compat20 ? ssh_session2() : ssh_session();          exit_status = compat20 ? ssh_session2() : ssh_session();
         packet_close();          packet_close();
Line 694 
Line 725 
   
         if (options.xauth_location) {          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,
                     options.xauth_location, 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) &&
Line 724 
Line 755 
         }          }
 }  }
   
   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 779 
Line 855 
                 packet_put_int(ws.ws_ypixel);                  packet_put_int(ws.ws_ypixel);
   
                 /* Store tty modes in the packet. */                  /* Store tty modes in the packet. */
                 tty_make_modes(fileno(stdin));                  tty_make_modes(fileno(stdin), NULL);
   
                 /* Send the packet, and wait for it to leave. */                  /* Send the packet, and wait for it to leave. */
                 packet_send();                  packet_send();
Line 815 
Line 891 
                 }                  }
         }          }
         /* 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 835 
Line 906 
                 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 888 
Line 940 
 }  }
   
 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;
           struct termios tio;
   
         if (no_shell_flag)          debug("client_init id %d arg %ld", id, (long)arg);
                 goto done;  
   
         if (tty_flag) {          if (tty_flag) {
                 struct winsize ws;                  struct winsize ws;
Line 931 
Line 979 
                 packet_put_int(ws.ws_row);                  packet_put_int(ws.ws_row);
                 packet_put_int(ws.ws_xpixel);                  packet_put_int(ws.ws_xpixel);
                 packet_put_int(ws.ws_ypixel);                  packet_put_int(ws.ws_ypixel);
                 packet_put_cstring("");         /* XXX: encode terminal modes */                  tio = get_saved_tio();
                   tty_make_modes(/*ignored*/ 0, &tio);
                 packet_send();                  packet_send();
                   interactive = 1;
                 /* XXX wait for reply */                  /* XXX wait for reply */
         }          }
         if (options.forward_x11 &&          if (options.forward_x11 &&
Line 943 
Line 993 
                 /* 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:  
         /* 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_command(void)
 {  {
         int window, packetmax, id;          int id, window, packetmax;
         int in, out, err;          int in, out, err;
   
         if (stdin_null_flag) {          if (stdin_null_flag) {
                 in = open("/dev/null", O_RDONLY);                  in = open(_PATH_DEVNULL, O_RDONLY);
         } else {          } else {
                 in = dup(STDIN_FILENO);                  in = dup(STDIN_FILENO);
         }          }
Line 988 
Line 1055 
         if (!isatty(err))          if (!isatty(err))
                 set_nonblock(err);                  set_nonblock(err);
   
         /* should be pre-session */  
         init_local_fwd();  
   
         /* 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;          window = CHAN_SES_WINDOW_DEFAULT;
         packetmax = CHAN_SES_PACKET_DEFAULT;          packetmax = CHAN_SES_PACKET_DEFAULT;
         if (!tty_flag) {          if (!tty_flag) {
Line 1007 
Line 1066 
             window, packetmax, CHAN_EXTENDED_WRITE,              window, packetmax, CHAN_EXTENDED_WRITE,
             xstrdup("client-session"), /*nonblock*/0);              xstrdup("client-session"), /*nonblock*/0);
   
   debug("channel_new: %d", id);
   
         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 id;
   }
   
   int
   ssh_session2(void)
   {
           int id;
   
           /* XXX should be pre-session */
           ssh_init_forwarding();
   
           id = no_shell_flag ? -1 : ssh_session2_command();
   
           /* If requested, let ssh continue in the background. */
           if (fork_after_authentication_flag)
                   if (daemon(1, 1) < 0)
                           fatal("daemon() failed: %.200s", strerror(errno));
   
         return client_loop(tty_flag, tty_flag ? options.escape_char : -1, id);          return client_loop(tty_flag, tty_flag ? options.escape_char : -1, id);
   }
   
   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_load_public(filename, 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.69  
changed lines
  Added in v.1.69.2.4