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

Diff for /src/usr.bin/ssh/sshd.c between version 1.290 and 1.290.2.1

version 1.290, 2004/03/11 10:21:17 version 1.290.2.1, 2004/08/19 04:13:28
Line 56 
Line 56 
 #include "rsa.h"  #include "rsa.h"
 #include "sshpty.h"  #include "sshpty.h"
 #include "packet.h"  #include "packet.h"
 #include "mpaux.h"  
 #include "log.h"  #include "log.h"
 #include "servconf.h"  #include "servconf.h"
 #include "uidswap.h"  #include "uidswap.h"
 #include "compat.h"  #include "compat.h"
 #include "buffer.h"  #include "buffer.h"
   #include "bufaux.h"
 #include "cipher.h"  #include "cipher.h"
 #include "kex.h"  #include "kex.h"
 #include "key.h"  #include "key.h"
Line 73 
Line 73 
 #include "canohost.h"  #include "canohost.h"
 #include "auth.h"  #include "auth.h"
 #include "misc.h"  #include "misc.h"
   #include "msg.h"
 #include "dispatch.h"  #include "dispatch.h"
 #include "channels.h"  #include "channels.h"
 #include "session.h"  #include "session.h"
Line 92 
Line 93 
 #define O_NOCTTY        0  #define O_NOCTTY        0
 #endif  #endif
   
   /* Re-exec fds */
   #define REEXEC_DEVCRYPTO_RESERVED_FD    (STDERR_FILENO + 1)
   #define REEXEC_STARTUP_PIPE_FD          (STDERR_FILENO + 2)
   #define REEXEC_CONFIG_PASS_FD           (STDERR_FILENO + 3)
   #define REEXEC_MIN_FREE_FD              (STDERR_FILENO + 4)
   
 extern char *__progname;  extern char *__progname;
   
 /* Server configuration options. */  /* Server configuration options. */
Line 129 
Line 136 
 /* Saved arguments to main(). */  /* Saved arguments to main(). */
 char **saved_argv;  char **saved_argv;
   
   /* re-exec */
   int rexeced_flag = 0;
   int rexec_flag = 1;
   int rexec_argc = 0;
   char **rexec_argv;
   
 /*  /*
  * The sockets that the server is listening; this is used in the SIGHUP   * The sockets that the server is listening; this is used in the SIGHUP
  * signal handler.   * signal handler.
Line 195 
Line 208 
 /* global authentication context */  /* global authentication context */
 Authctxt *the_authctxt = NULL;  Authctxt *the_authctxt = NULL;
   
   /* message to be displayed after login */
   Buffer loginmsg;
   
 /* Prototypes for various functions defined later in this file. */  /* Prototypes for various functions defined later in this file. */
 void destroy_sensitive_data(void);  void destroy_sensitive_data(void);
 void demote_sensitive_data(void);  void demote_sensitive_data(void);
Line 756 
Line 772 
         exit(1);          exit(1);
 }  }
   
   static void
   send_rexec_state(int fd, Buffer *conf)
   {
           Buffer m;
   
           debug3("%s: entering fd = %d config len %d", __func__, fd,
               buffer_len(conf));
   
           /*
            * Protocol from reexec master to child:
            *      string  configuration
            *      u_int   ephemeral_key_follows
            *      bignum  e               (only if ephemeral_key_follows == 1)
            *      bignum  n                       "
            *      bignum  d                       "
            *      bignum  iqmp                    "
            *      bignum  p                       "
            *      bignum  q                       "
            */
           buffer_init(&m);
           buffer_put_cstring(&m, buffer_ptr(conf));
   
           if (sensitive_data.server_key != NULL &&
               sensitive_data.server_key->type == KEY_RSA1) {
                   buffer_put_int(&m, 1);
                   buffer_put_bignum(&m, sensitive_data.server_key->rsa->e);
                   buffer_put_bignum(&m, sensitive_data.server_key->rsa->n);
                   buffer_put_bignum(&m, sensitive_data.server_key->rsa->d);
                   buffer_put_bignum(&m, sensitive_data.server_key->rsa->iqmp);
                   buffer_put_bignum(&m, sensitive_data.server_key->rsa->p);
                   buffer_put_bignum(&m, sensitive_data.server_key->rsa->q);
           } else
                   buffer_put_int(&m, 0);
   
           if (ssh_msg_send(fd, 0, &m) == -1)
                   fatal("%s: ssh_msg_send failed", __func__);
   
           buffer_free(&m);
   
           debug3("%s: done", __func__);
   }
   
   static void
   recv_rexec_state(int fd, Buffer *conf)
   {
           Buffer m;
           char *cp;
           u_int len;
   
           debug3("%s: entering fd = %d", __func__, fd);
   
           buffer_init(&m);
   
           if (ssh_msg_recv(fd, &m) == -1)
                   fatal("%s: ssh_msg_recv failed", __func__);
           if (buffer_get_char(&m) != 0)
                   fatal("%s: rexec version mismatch", __func__);
   
           cp = buffer_get_string(&m, &len);
           if (conf != NULL)
                   buffer_append(conf, cp, len + 1);
           xfree(cp);
   
           if (buffer_get_int(&m)) {
                   if (sensitive_data.server_key != NULL)
                           key_free(sensitive_data.server_key);
                   sensitive_data.server_key = key_new_private(KEY_RSA1);
                   buffer_get_bignum(&m, sensitive_data.server_key->rsa->e);
                   buffer_get_bignum(&m, sensitive_data.server_key->rsa->n);
                   buffer_get_bignum(&m, sensitive_data.server_key->rsa->d);
                   buffer_get_bignum(&m, sensitive_data.server_key->rsa->iqmp);
                   buffer_get_bignum(&m, sensitive_data.server_key->rsa->p);
                   buffer_get_bignum(&m, sensitive_data.server_key->rsa->q);
                   rsa_generate_additional_parameters(
                       sensitive_data.server_key->rsa);
           }
           buffer_free(&m);
   
           debug3("%s: done", __func__);
   }
   
 /*  /*
  * Main program for the daemon.   * Main program for the daemon.
  */   */
Line 764 
Line 861 
 {  {
         extern char *optarg;          extern char *optarg;
         extern int optind;          extern int optind;
         int opt, sock_in = 0, sock_out = 0, newsock, j, i, fdsetsz, on = 1;          int opt, j, i, fdsetsz, on = 1;
           int sock_in = -1, sock_out = -1, newsock = -1;
         pid_t pid;          pid_t pid;
         socklen_t fromlen;          socklen_t fromlen;
         fd_set *fdset;          fd_set *fdset;
Line 776 
Line 874 
         char ntop[NI_MAXHOST], strport[NI_MAXSERV];          char ntop[NI_MAXHOST], strport[NI_MAXSERV];
         char *line;          char *line;
         int listen_sock, maxfd;          int listen_sock, maxfd;
         int startup_p[2];          int startup_p[2], config_s[2];
         int startups = 0;          int startups = 0;
         Key *key;          Key *key;
         Authctxt *authctxt;          Authctxt *authctxt;
         int ret, key_used = 0;          int ret, key_used = 0;
           Buffer cfg;
   
         /* Save argv. */          /* Save argv. */
         saved_argv = av;          saved_argv = av;
           rexec_argc = ac;
   
         /* Initialize configuration options to their default values. */          /* Initialize configuration options to their default values. */
         initialize_server_options(&options);          initialize_server_options(&options);
   
         /* Parse command-line arguments. */          /* Parse command-line arguments. */
         while ((opt = getopt(ac, av, "f:p:b:k:h:g:u:o:dDeiqtQ46")) != -1) {          while ((opt = getopt(ac, av, "f:p:b:k:h:g:u:o:dDeiqrtQR46")) != -1) {
                 switch (opt) {                  switch (opt) {
                 case '4':                  case '4':
                         IPv4or6 = AF_INET;                          IPv4or6 = AF_INET;
Line 816 
Line 916 
                 case 'i':                  case 'i':
                         inetd_flag = 1;                          inetd_flag = 1;
                         break;                          break;
                   case 'r':
                           rexec_flag = 0;
                           break;
                   case 'R':
                           rexeced_flag = 1;
                           inetd_flag = 1;
                           break;
                 case 'Q':                  case 'Q':
                         /* ignored */                          /* ignored */
                         break;                          break;
Line 879 
Line 986 
                         break;                          break;
                 }                  }
         }          }
           if (rexeced_flag || inetd_flag)
                   rexec_flag = 0;
           if (rexec_flag && (av[0] == NULL || *av[0] != '/'))
                   fatal("sshd re-exec requires execution with an absolute path");
           if (rexeced_flag)
                   closefrom(REEXEC_MIN_FREE_FD);
           else
                   closefrom(REEXEC_DEVCRYPTO_RESERVED_FD);
   
         SSLeay_add_all_algorithms();          SSLeay_add_all_algorithms();
         channel_set_af(IPv4or6);          channel_set_af(IPv4or6);
   
Line 893 
Line 1009 
             SYSLOG_FACILITY_AUTH : options.log_facility,              SYSLOG_FACILITY_AUTH : options.log_facility,
             log_stderr || !inetd_flag);              log_stderr || !inetd_flag);
   
         /* Read server configuration options from the configuration file. */          sensitive_data.server_key = NULL;
         read_server_config(&options, config_file_name);          sensitive_data.ssh1_host_key = NULL;
           sensitive_data.have_ssh1_key = 0;
           sensitive_data.have_ssh2_key = 0;
   
           /* Fetch our configuration */
           buffer_init(&cfg);
           if (rexeced_flag)
                   recv_rexec_state(REEXEC_CONFIG_PASS_FD, &cfg);
           else
                   load_server_config(config_file_name, &cfg);
   
           parse_server_config(&options,
               rexeced_flag ? "rexec" : config_file_name, &cfg);
   
           if (!rexec_flag)
                   buffer_free(&cfg);
   
         /* Fill in default values for those options not explicitly set. */          /* Fill in default values for those options not explicitly set. */
         fill_default_server_options(&options);          fill_default_server_options(&options);
   
Line 912 
Line 1043 
             sizeof(Key *));              sizeof(Key *));
         for (i = 0; i < options.num_host_key_files; i++)          for (i = 0; i < options.num_host_key_files; i++)
                 sensitive_data.host_keys[i] = NULL;                  sensitive_data.host_keys[i] = NULL;
         sensitive_data.server_key = NULL;  
         sensitive_data.ssh1_host_key = NULL;  
         sensitive_data.have_ssh1_key = 0;  
         sensitive_data.have_ssh2_key = 0;  
   
         for (i = 0; i < options.num_host_key_files; i++) {          for (i = 0; i < options.num_host_key_files; i++) {
                 key = key_load_private(options.host_key_files[i], "", NULL);                  key = key_load_private(options.host_key_files[i], "", NULL);
Line 997 
Line 1124 
         if (test_flag)          if (test_flag)
                 exit(0);                  exit(0);
   
           if (rexec_flag) {
                   rexec_argv = xmalloc(sizeof(char *) * (rexec_argc + 2));
                   for (i = 0; i < rexec_argc; i++) {
                           debug("rexec_argv[%d]='%s'", i, saved_argv[i]);
                           rexec_argv[i] = saved_argv[i];
                   }
                   rexec_argv[rexec_argc] = "-R";
                   rexec_argv[rexec_argc + 1] = NULL;
           }
   
         /* Initialize the log (it is reinitialized below in case we forked). */          /* Initialize the log (it is reinitialized below in case we forked). */
         if (debug_flag && !inetd_flag)          if (debug_flag && !inetd_flag)
                 log_stderr = 1;                  log_stderr = 1;
Line 1038 
Line 1175 
   
         /* Start listening for a socket, unless started from inetd. */          /* Start listening for a socket, unless started from inetd. */
         if (inetd_flag) {          if (inetd_flag) {
                 int s1;                  int fd;
                 s1 = dup(0);    /* Make sure descriptors 0, 1, and 2 are in use. */  
                 dup(s1);  
                 sock_in = dup(0);  
                 sock_out = dup(1);  
                 startup_pipe = -1;                  startup_pipe = -1;
                   if (rexeced_flag) {
                           close(REEXEC_CONFIG_PASS_FD);
                           sock_in = sock_out = dup(STDIN_FILENO);
                           if (!debug_flag) {
                                   startup_pipe = dup(REEXEC_STARTUP_PIPE_FD);
                                   close(REEXEC_STARTUP_PIPE_FD);
                           }
                   } else {
                           sock_in = dup(STDIN_FILENO);
                           sock_out = dup(STDOUT_FILENO);
                   }
                 /*                  /*
                  * We intentionally do not close the descriptors 0, 1, and 2                   * We intentionally do not close the descriptors 0, 1, and 2
                  * as our code for setting the descriptors won\'t work if                   * as our code for setting the descriptors won't work if
                  * ttyfd happens to be one of those.                   * ttyfd happens to be one of those.
                  */                   */
                   if ((fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {
                           dup2(fd, STDIN_FILENO);
                           dup2(fd, STDOUT_FILENO);
                           if (fd > STDOUT_FILENO)
                                   close(fd);
                   }
                 debug("inetd sockets after dupping: %d, %d", sock_in, sock_out);                  debug("inetd sockets after dupping: %d, %d", sock_in, sock_out);
                 if (options.protocol & SSH_PROTO_1)                  if ((options.protocol & SSH_PROTO_1) &&
                       sensitive_data.server_key == NULL)
                         generate_ephemeral_server_key();                          generate_ephemeral_server_key();
         } else {          } else {
                 for (ai = options.listen_addrs; ai; ai = ai->ai_next) {                  for (ai = options.listen_addrs; ai; ai = ai->ai_next) {
Line 1073 
Line 1225 
                                 verbose("socket: %.100s", strerror(errno));                                  verbose("socket: %.100s", strerror(errno));
                                 continue;                                  continue;
                         }                          }
                         if (fcntl(listen_sock, F_SETFL, O_NONBLOCK) < 0) {                          if (set_nonblock(listen_sock) == -1) {
                                 error("listen_sock O_NONBLOCK: %s", strerror(errno));  
                                 close(listen_sock);                                  close(listen_sock);
                                 continue;                                  continue;
                         }                          }
Line 1216 
Line 1367 
                                                 error("accept: %.100s", strerror(errno));                                                  error("accept: %.100s", strerror(errno));
                                         continue;                                          continue;
                                 }                                  }
                                 if (fcntl(newsock, F_SETFL, 0) < 0) {                                  if (unset_nonblock(newsock) == -1) {
                                         error("newsock del O_NONBLOCK: %s", strerror(errno));  
                                         close(newsock);                                          close(newsock);
                                         continue;                                          continue;
                                 }                                  }
Line 1231 
Line 1381 
                                         continue;                                          continue;
                                 }                                  }
   
                                   if (rexec_flag && socketpair(AF_UNIX,
                                       SOCK_STREAM, 0, config_s) == -1) {
                                           error("reexec socketpair: %s",
                                               strerror(errno));
                                           close(newsock);
                                           close(startup_p[0]);
                                           close(startup_p[1]);
                                           continue;
                                   }
   
                                 for (j = 0; j < options.max_startups; j++)                                  for (j = 0; j < options.max_startups; j++)
                                         if (startup_pipes[j] == -1) {                                          if (startup_pipes[j] == -1) {
                                                 startup_pipes[j] = startup_p[0];                                                  startup_pipes[j] = startup_p[0];
Line 1254 
Line 1414 
                                         close_listen_socks();                                          close_listen_socks();
                                         sock_in = newsock;                                          sock_in = newsock;
                                         sock_out = newsock;                                          sock_out = newsock;
                                           close(startup_p[0]);
                                           close(startup_p[1]);
                                         startup_pipe = -1;                                          startup_pipe = -1;
                                         pid = getpid();                                          pid = getpid();
                                           if (rexec_flag) {
                                                   send_rexec_state(config_s[0],
                                                       &cfg);
                                                   close(config_s[0]);
                                           }
                                         break;                                          break;
                                 } else {                                  } else {
                                         /*                                          /*
Line 1277 
Line 1444 
                                                 sock_in = newsock;                                                  sock_in = newsock;
                                                 sock_out = newsock;                                                  sock_out = newsock;
                                                 log_init(__progname, options.log_level, options.log_facility, log_stderr);                                                  log_init(__progname, options.log_level, options.log_facility, log_stderr);
                                                   close(config_s[0]);
                                                 break;                                                  break;
                                         }                                          }
                                 }                                  }
Line 1289 
Line 1457 
   
                                 close(startup_p[1]);                                  close(startup_p[1]);
   
                                   if (rexec_flag) {
                                           send_rexec_state(config_s[0], &cfg);
                                           close(config_s[0]);
                                           close(config_s[1]);
                                   }
   
                                 /* Mark that the key has been used (it was "given" to the child). */                                  /* Mark that the key has been used (it was "given" to the child). */
                                 if ((options.protocol & SSH_PROTO_1) &&                                  if ((options.protocol & SSH_PROTO_1) &&
                                     key_used == 0) {                                      key_used == 0) {
Line 1320 
Line 1494 
         if (!debug_flag && !inetd_flag && setsid() < 0)          if (!debug_flag && !inetd_flag && setsid() < 0)
                 error("setsid: %.100s", strerror(errno));                  error("setsid: %.100s", strerror(errno));
   
           if (rexec_flag) {
                   int fd;
   
                   debug("rexec start in %d out %d newsock %d pipe %d sock %d",
                       sock_in, sock_out, newsock, startup_pipe, config_s[0]);
                   dup2(newsock, STDIN_FILENO);
                   dup2(STDIN_FILENO, STDOUT_FILENO);
                   if (startup_pipe == -1)
                           close(REEXEC_STARTUP_PIPE_FD);
                   else
                           dup2(startup_pipe, REEXEC_STARTUP_PIPE_FD);
   
                   dup2(config_s[1], REEXEC_CONFIG_PASS_FD);
                   close(config_s[1]);
                   if (startup_pipe != -1)
                           close(startup_pipe);
   
                   execv(rexec_argv[0], rexec_argv);
   
                   /* Reexec has failed, fall back and continue */
                   error("rexec of %s failed: %s", rexec_argv[0], strerror(errno));
                   recv_rexec_state(REEXEC_CONFIG_PASS_FD, NULL);
                   log_init(__progname, options.log_level,
                       options.log_facility, log_stderr);
   
                   /* Clean up fds */
                   startup_pipe = REEXEC_STARTUP_PIPE_FD;
                   close(config_s[1]);
                   close(REEXEC_CONFIG_PASS_FD);
                   newsock = sock_out = sock_in = dup(STDIN_FILENO);
                   if ((fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {
                           dup2(fd, STDIN_FILENO);
                           dup2(fd, STDOUT_FILENO);
                           if (fd > STDERR_FILENO)
                                   close(fd);
                   }
                   debug("rexec cleanup in %d out %d newsock %d pipe %d sock %d",
                       sock_in, sock_out, newsock, startup_pipe, config_s[0]);
           }
   
         /*          /*
          * Disable the key regeneration alarm.  We will not regenerate the           * Disable the key regeneration alarm.  We will not regenerate the
          * key since we are no longer in a position to give it to anyone. We           * key since we are no longer in a position to give it to anyone. We
Line 1349 
Line 1563 
   
 #ifdef LIBWRAP  #ifdef LIBWRAP
         /* Check whether logins are denied from this host. */          /* Check whether logins are denied from this host. */
         {          if (packet_connection_is_on_socket()) {
                 struct request_info req;                  struct request_info req;
   
                 request_init(&req, RQ_DAEMON, __progname, RQ_FILE, sock_in, 0);                  request_init(&req, RQ_DAEMON, __progname, RQ_FILE, sock_in, 0);
Line 1394 
Line 1608 
                 if (privsep_preauth(authctxt) == 1)                  if (privsep_preauth(authctxt) == 1)
                         goto authenticated;                          goto authenticated;
   
           /* prepare buffer to collect messages to display to user after login */
           buffer_init(&loginmsg);
   
         /* perform the key exchange */          /* perform the key exchange */
         /* authenticate user and start session */          /* authenticate user and start session */
         if (compat20) {          if (compat20) {
Line 1603 
Line 1820 
                         BN_bn2bin(session_key_int,                          BN_bn2bin(session_key_int,
                             session_key + sizeof(session_key) - len);                              session_key + sizeof(session_key) - len);
   
                         compute_session_id(session_id, cookie,                          derive_ssh1_session_id(
                             sensitive_data.ssh1_host_key->rsa->n,                              sensitive_data.ssh1_host_key->rsa->n,
                             sensitive_data.server_key->rsa->n);                              sensitive_data.server_key->rsa->n,
                               cookie, session_id);
                         /*                          /*
                          * Xor the first 16 bytes of the session key with the                           * Xor the first 16 bytes of the session key with the
                          * session id.                           * session id.
Line 1688 
Line 1906 
         /* start key exchange */          /* start key exchange */
         kex = kex_setup(myproposal);          kex = kex_setup(myproposal);
         kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server;          kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server;
           kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server;
         kex->kex[KEX_DH_GEX_SHA1] = kexgex_server;          kex->kex[KEX_DH_GEX_SHA1] = kexgex_server;
         kex->server = 1;          kex->server = 1;
         kex->client_version_string=client_version_string;          kex->client_version_string=client_version_string;

Legend:
Removed from v.1.290  
changed lines
  Added in v.1.290.2.1