[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.169 and 1.169.2.4

version 1.169, 2002/03/26 11:37:05 version 1.169.2.4, 2002/10/11 14:51:53
Line 53 
Line 53 
 #include "xmalloc.h"  #include "xmalloc.h"
 #include "packet.h"  #include "packet.h"
 #include "buffer.h"  #include "buffer.h"
 #include "uidswap.h"  
 #include "channels.h"  #include "channels.h"
 #include "key.h"  #include "key.h"
 #include "authfd.h"  #include "authfd.h"
Line 99 
Line 98 
   
 /*  /*
  * Flag indicating that ssh should fork after authentication.  This is useful   * Flag indicating that ssh should fork after authentication.  This is useful
  * so that the pasphrase can be entered manually, and then ssh goes to the   * so that the passphrase can be entered manually, and then ssh goes to the
  * background.   * background.
  */   */
 int fork_after_authentication_flag = 0;  int fork_after_authentication_flag = 0;
Line 124 
Line 123 
 struct sockaddr_storage hostaddr;  struct sockaddr_storage hostaddr;
   
 /* Private host keys. */  /* Private host keys. */
 struct {  Sensitive sensitive_data;
         Key     **keys;  
         int     nkeys;  
 } sensitive_data;  
   
 /* Original real UID. */  /* Original real UID. */
 uid_t original_real_uid;  uid_t original_real_uid;
   uid_t original_effective_uid;
   
 /* command to be executed */  /* command to be executed */
 Buffer command;  Buffer command;
Line 138 
Line 135 
 /* Should we execute a command or invoke a subsystem? */  /* Should we execute a command or invoke a subsystem? */
 int subsystem_flag = 0;  int subsystem_flag = 0;
   
   /* # of replies received for global requests */
   static int client_global_request_id = 0;
   
   /* pid of proxycommand child process */
   pid_t proxy_command_pid = 0;
   
 /* Prints a help message to the user.  This function never returns. */  /* Prints a help message to the user.  This function never returns. */
   
 static void  static void
Line 166 
Line 169 
         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, "              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, "  -q          Quiet; don't display any warning messages.\n");          fprintf(stderr, "  -q          Quiet; don't display any warning messages.\n");
         fprintf(stderr, "  -f          Fork into background after authentication.\n");          fprintf(stderr, "  -f          Fork into background after authentication.\n");
         fprintf(stderr, "  -e char     Set escape character; ``none'' = disable (default: ~).\n");          fprintf(stderr, "  -e char     Set escape character; ``none'' = disable (default: ~).\n");
Line 192 
Line 194 
         exit(1);          exit(1);
 }  }
   
 /*  
  * Connects to the given host using rsh (or prints an error message and exits  
  * if rsh is not available).  This function never returns.  
  */  
 static void  
 rsh_connect(char *host, char *user, Buffer * command)  
 {  
         char *args[10];  
         int i;  
   
         log("Using rsh.  WARNING: Connection will not be encrypted.");  
         /* Build argument list for rsh. */  
         i = 0;  
         args[i++] = _PATH_RSH;  
         /* host may have to come after user on some systems */  
         args[i++] = host;  
         if (user) {  
                 args[i++] = "-l";  
                 args[i++] = user;  
         }  
         if (buffer_len(command) > 0) {  
                 buffer_append(command, "\0", 1);  
                 args[i++] = buffer_ptr(command);  
         }  
         args[i++] = NULL;  
         if (debug_flag) {  
                 for (i = 0; args[i]; i++) {  
                         if (i != 0)  
                                 fprintf(stderr, " ");  
                         fprintf(stderr, "%s", args[i]);  
                 }  
                 fprintf(stderr, "\n");  
         }  
         execv(_PATH_RSH, args);  
         perror(_PATH_RSH);  
         exit(1);  
 }  
   
 static int ssh_session(void);  static int ssh_session(void);
 static int ssh_session2(void);  static int ssh_session2(void);
 static void load_public_identity_files(void);  static void load_public_identity_files(void);
Line 240 
Line 204 
 int  int
 main(int ac, char **av)  main(int ac, char **av)
 {  {
         int i, opt, exit_status, cerr;          int i, opt, exit_status;
         u_short fwd_port, fwd_host_port;          u_short fwd_port, fwd_host_port;
         char sfwd_port[6], sfwd_host_port[6];          char sfwd_port[6], sfwd_host_port[6];
         char *p, *cp, buf[256];          char *p, *cp, buf[256];
         struct stat st;          struct stat st;
         struct passwd *pw;          struct passwd *pw;
         int dummy;          int dummy;
         uid_t original_effective_uid;  
         extern int optind, optreset;          extern int optind, optreset;
         extern char *optarg;          extern char *optarg;
   
Line 258 
Line 221 
         original_real_uid = getuid();          original_real_uid = getuid();
         original_effective_uid = geteuid();          original_effective_uid = geteuid();
   
           /*
            * Use uid-swapping to give up root privileges for the duration of
            * option processing.  We will re-instantiate the rights when we are
            * ready to create the privileged port, and will permanently drop
            * them when the port has been created (actually, when the connection
            * has been made, as we may need to create the port several times).
            */
           PRIV_END;
   
         /* If we are installed setuid root be careful to not drop core. */          /* If we are installed setuid root be careful to not drop core. */
         if (original_real_uid != original_effective_uid) {          if (original_real_uid != original_effective_uid) {
                 struct rlimit rlim;                  struct rlimit rlim;
Line 275 
Line 247 
         pw = pwcopy(pw);          pw = pwcopy(pw);
   
         /*          /*
          * Use uid-swapping to give up root privileges for the duration of  
          * option processing.  We will re-instantiate the rights when we are  
          * ready to create the privileged port, and will permanently drop  
          * them when the port has been created (actually, when the connection  
          * has been made, as we may need to create the port several times).  
          */  
         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
          * with the default umask.  This will make them world-readable but           * with the default umask.  This will make them world-readable but
          * writable only by the owner, which is ok for all files for which we           * writable only by the owner, which is ok for all files for which we
Line 329 
Line 292 
                 case 'g':                  case 'g':
                         options.gateway_ports = 1;                          options.gateway_ports = 1;
                         break;                          break;
                 case 'P':                  case 'P':       /* deprecated */
                         options.use_privileged_port = 0;                          options.use_privileged_port = 0;
                         break;                          break;
                 case 'a':                  case 'a':
Line 578 
Line 541 
         if (buffer_len(&command) == 0)          if (buffer_len(&command) == 0)
                 tty_flag = 1;                  tty_flag = 1;
   
         /* Force no tty*/          /* Force no tty */
         if (no_tty_flag)          if (no_tty_flag)
                 tty_flag = 0;                  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. */
Line 630 
Line 593 
                     "originating port will not be trusted.");                      "originating port will not be trusted.");
                 options.rhosts_authentication = 0;                  options.rhosts_authentication = 0;
         }          }
         /*  
          * If using rsh has been selected, exec it now (without trying  
          * anything else).  Note that we must release privileges first.  
          */  
         if (options.use_rsh) {  
                 /*  
                  * Restore our superuser privileges.  This must be done  
                  * before permanently setting the uid.  
                  */  
                 restore_uid();  
   
                 /* Switch to the original uid permanently. */  
                 permanently_set_uid(pw);  
   
                 /* Execute rsh. */  
                 rsh_connect(host, options.user, &command);  
                 fatal("rsh_connect returned");  
         }  
         /* Restore our superuser privileges. */  
         restore_uid();  
   
         /* Open a connection to the remote host. */          /* Open a connection to the remote host. */
   
         cerr = ssh_connect(host, &hostaddr, options.port, IPv4or6,          if (ssh_connect(host, &hostaddr, options.port, IPv4or6,
             options.connection_attempts,              options.connection_attempts,
             original_effective_uid != 0 || !options.use_privileged_port,              original_effective_uid == 0 && options.use_privileged_port,
             pw, options.proxy_command);              options.proxy_command) != 0)
                   exit(1);
   
         /*          /*
          * If we successfully made the connection, load the host private key           * If we successfully made the connection, load the host private key
          * in case we will need it later for combined rsa-rhosts           * in case we will need it later for combined rsa-rhosts
          * 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 we cannot access the private keys, load the public keys
            * instead and try to execute the ssh-keysign helper instead.
          */           */
         sensitive_data.nkeys = 0;          sensitive_data.nkeys = 0;
         sensitive_data.keys = NULL;          sensitive_data.keys = NULL;
         if (!cerr && (options.rhosts_rsa_authentication ||          sensitive_data.external_keysign = 0;
             options.hostbased_authentication)) {          if (options.rhosts_rsa_authentication ||
               options.hostbased_authentication) {
                 sensitive_data.nkeys = 3;                  sensitive_data.nkeys = 3;
                 sensitive_data.keys = xmalloc(sensitive_data.nkeys*sizeof(Key));                  sensitive_data.keys = xmalloc(sensitive_data.nkeys *
                       sizeof(Key));
   
                   PRIV_START;
                 sensitive_data.keys[0] = key_load_private_type(KEY_RSA1,                  sensitive_data.keys[0] = key_load_private_type(KEY_RSA1,
                     _PATH_HOST_KEY_FILE, "", NULL);                      _PATH_HOST_KEY_FILE, "", NULL);
                 sensitive_data.keys[1] = key_load_private_type(KEY_DSA,                  sensitive_data.keys[1] = key_load_private_type(KEY_DSA,
                     _PATH_HOST_DSA_KEY_FILE, "", NULL);                      _PATH_HOST_DSA_KEY_FILE, "", NULL);
                 sensitive_data.keys[2] = key_load_private_type(KEY_RSA,                  sensitive_data.keys[2] = key_load_private_type(KEY_RSA,
                     _PATH_HOST_RSA_KEY_FILE, "", NULL);                      _PATH_HOST_RSA_KEY_FILE, "", NULL);
                   PRIV_END;
   
                   if (options.hostbased_authentication == 1 &&
                       sensitive_data.keys[0] == NULL &&
                       sensitive_data.keys[1] == NULL &&
                       sensitive_data.keys[2] == NULL) {
                           sensitive_data.keys[1] = key_load_public(
                               _PATH_HOST_DSA_KEY_FILE, NULL);
                           sensitive_data.keys[2] = key_load_public(
                               _PATH_HOST_RSA_KEY_FILE, NULL);
                           sensitive_data.external_keysign = 1;
                   }
         }          }
         /*          /*
          * 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 684 
Line 645 
          * user's home directory if it happens to be on a NFS volume where           * user's home directory if it happens to be on a NFS volume where
          * root is mapped to nobody.           * root is mapped to nobody.
          */           */
           seteuid(original_real_uid);
           setuid(original_real_uid);
   
         /*          /*
          * Note that some legacy systems need to postpone the following call  
          * to permanently_set_uid() until the private hostkey is destroyed  
          * with RSA_free().  Otherwise the calling user could ptrace() the  
          * process, read the private hostkey and impersonate the host.  
          * OpenBSD does not allow ptracing of setuid processes.  
          */  
         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.
          */           */
Line 703 
Line 657 
                 if (mkdir(buf, 0700) < 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. */  
         if (cerr) {  
                 if (!options.fallback_to_rsh)  
                         exit(1);  
                 if (options.port != 0)  
                         log("Secure connection to %.100s on port %hu refused; "  
                             "reverting to insecure method",  
                             host, options.port);  
                 else  
                         log("Secure connection to %.100s refused; "  
                             "reverting to insecure method.", host);  
   
                 rsh_connect(host, options.user, &command);  
                 fatal("rsh_connect returned");  
         }  
         /* load options.identity_files */          /* load options.identity_files */
         load_public_identity_files();          load_public_identity_files();
   
Line 735 
Line 674 
         signal(SIGPIPE, SIG_IGN); /* ignore SIGPIPE early */          signal(SIGPIPE, SIG_IGN); /* ignore SIGPIPE early */
   
         /* 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(sensitive_data.keys, sensitive_data.nkeys,          ssh_login(&sensitive_data, host, (struct sockaddr *)&hostaddr, pw);
             host, (struct sockaddr *)&hostaddr, pw);  
   
         /* We no longer need the private host keys.  Clear them now. */          /* We no longer need the private host keys.  Clear them now. */
         if (sensitive_data.nkeys != 0) {          if (sensitive_data.nkeys != 0) {
Line 763 
Line 701 
   
         exit_status = compat20 ? ssh_session2() : ssh_session();          exit_status = compat20 ? ssh_session2() : ssh_session();
         packet_close();          packet_close();
   
           /*
            * Send SIGHUP to proxy command if used. We don't wait() in
            * case it hangs and instead rely on init to reap the child
            */
           if (proxy_command_pid > 1)
                   kill(proxy_command_pid, SIGHUP);
   
         return exit_status;          return exit_status;
 }  }
   
Line 774 
Line 720 
         FILE *f;          FILE *f;
         int got_data = 0, i;          int got_data = 0, i;
         char *display;          char *display;
           struct stat st;
   
         *_proto = proto;          *_proto = proto;
         *_data = data;          *_data = data;
         proto[0] = data[0] = '\0';          proto[0] = data[0] = '\0';
         if (options.xauth_location && (display = getenv("DISPLAY"))) {          if (!options.xauth_location ||
               (stat(options.xauth_location, &st) == -1)) {
                   debug("No xauth program.");
           } else {
                   if ((display = getenv("DISPLAY")) == NULL) {
                           debug("x11_get_proto: DISPLAY not set");
                           return;
                   }
                 /* Try to get Xauthority information for the display. */                  /* Try to get Xauthority information for the display. */
                 if (strncmp(display, "localhost:", 10) == 0)                  if (strncmp(display, "localhost:", 10) == 0)
                         /*                          /*
Line 788 
Line 742 
                          * XXX: "localhost" match to determine FamilyLocal                           * XXX: "localhost" match to determine FamilyLocal
                          *      is not perfect.                           *      is not perfect.
                          */                           */
                         snprintf(line, sizeof line, "%.100s list unix:%s 2>"                          snprintf(line, sizeof line, "%s list unix:%s 2>"
                             _PATH_DEVNULL, options.xauth_location, display+10);                              _PATH_DEVNULL, options.xauth_location, display+10);
                 else                  else
                         snprintf(line, sizeof line, "%.100s list %.200s 2>"                          snprintf(line, sizeof line, "%s list %.200s 2>"
                             _PATH_DEVNULL, options.xauth_location, display);                              _PATH_DEVNULL, options.xauth_location, display);
                 debug2("x11_get_proto %s", line);                  debug2("x11_get_proto: %s", line);
                 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 %511s %511s", proto, data) == 2)                      sscanf(line, "%*s %511s %511s", proto, data) == 2)
Line 812 
Line 766 
         if (!got_data) {          if (!got_data) {
                 u_int32_t rand = 0;                  u_int32_t rand = 0;
   
                   log("Warning: No xauth data; using fake authentication data for X11 forwarding.");
                 strlcpy(proto, "MIT-MAGIC-COOKIE-1", sizeof proto);                  strlcpy(proto, "MIT-MAGIC-COOKIE-1", sizeof proto);
                 for (i = 0; i < 16; i++) {                  for (i = 0; i < 16; i++) {
                         if (i % 4 == 0)                          if (i % 4 == 0)
Line 861 
Line 816 
 {  {
         if (options.forward_agent) {          if (options.forward_agent) {
                 /* Clear agent forwarding if we don\'t have an agent. */                  /* Clear agent forwarding if we don\'t have an agent. */
                 int authfd = ssh_get_authentication_socket();                  if (!ssh_agent_present())
                 if (authfd < 0)  
                         options.forward_agent = 0;                          options.forward_agent = 0;
                 else  
                         ssh_close_authentication_socket(authfd);  
         }          }
 }  }
   
Line 1021 
Line 973 
                     len, (u_char *)buffer_ptr(&command), id);                      len, (u_char *)buffer_ptr(&command), id);
 }  }
   
   void
   client_global_request_reply(int type, u_int32_t seq, void *ctxt)
   {
           int i;
   
           i = client_global_request_id++;
           if (i >= options.num_remote_forwards) {
                   debug("client_global_request_reply: too many replies %d > %d",
                       i, options.num_remote_forwards);
                   return;
           }
           debug("remote forward %s for: listen %d, connect %s:%d",
               type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure",
               options.remote_forwards[i].port,
               options.remote_forwards[i].host,
               options.remote_forwards[i].host_port);
           if (type == SSH2_MSG_REQUEST_FAILURE)
                   log("Warning: remote port forwarding failed for listen port %d",
                       options.remote_forwards[i].port);
   }
   
 /* request pty/x11/agent/tcpfwd/shell for channel */  /* request pty/x11/agent/tcpfwd/shell for channel */
 static void  static void
 ssh_session2_setup(int id, void *arg)  ssh_session2_setup(int id, void *arg)
Line 1080 
Line 1053 
                         debug("Sending subsystem: %.*s", len, (u_char *)buffer_ptr(&command));                          debug("Sending subsystem: %.*s", len, (u_char *)buffer_ptr(&command));
                         channel_request_start(id, "subsystem", /*want reply*/ 1);                          channel_request_start(id, "subsystem", /*want reply*/ 1);
                         /* register callback for reply */                          /* register callback for reply */
                         /* XXX we asume that client_loop has already been called */                          /* XXX we assume that client_loop has already been called */
                         dispatch_set(SSH2_MSG_CHANNEL_FAILURE, &client_subsystem_reply);                          dispatch_set(SSH2_MSG_CHANNEL_FAILURE, &client_subsystem_reply);
                         dispatch_set(SSH2_MSG_CHANNEL_SUCCESS, &client_subsystem_reply);                          dispatch_set(SSH2_MSG_CHANNEL_SUCCESS, &client_subsystem_reply);
                 } else {                  } else {

Legend:
Removed from v.1.169  
changed lines
  Added in v.1.169.2.4