[BACK]Return to sshd.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / crypto / external / bsd / openssh / dist

Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.

Diff for /src/crypto/external/bsd/openssh/dist/sshd.c between version 1.8.4.1 and 1.8.4.2

version 1.8.4.1, 2012/04/02 18:28:12 version 1.8.4.2, 2017/08/15 05:27:53
Line 1 
Line 1 
 /*      $NetBSD$        */  /*      $NetBSD$        */
 /* $OpenBSD: sshd.c,v 1.385 2011/06/23 09:34:13 djm Exp $ */  /* $OpenBSD: sshd.c,v 1.485 2017/03/15 03:52:30 deraadt Exp $ */
 /*  /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>   * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland   * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
Line 65  __RCSID("$NetBSD$");
Line 65  __RCSID("$NetBSD$");
 #include <stdlib.h>  #include <stdlib.h>
 #include <string.h>  #include <string.h>
 #include <unistd.h>  #include <unistd.h>
   #include <limits.h>
   
 #include <openssl/dh.h>  #ifdef WITH_OPENSSL
 #include <openssl/bn.h>  #include <openssl/bn.h>
 #include <openssl/md5.h>  #endif
 #include <openssl/rand.h>  
   
 #include "xmalloc.h"  #include "xmalloc.h"
 #include "ssh.h"  #include "ssh.h"
 #include "ssh1.h"  
 #include "ssh2.h"  #include "ssh2.h"
 #include "rsa.h"  #include "rsa.h"
 #include "sshpty.h"  #include "sshpty.h"
 #include "packet.h"  #include "packet.h"
 #include "log.h"  #include "log.h"
 #include "buffer.h"  #include "buffer.h"
   #include "misc.h"
   #include "match.h"
 #include "servconf.h"  #include "servconf.h"
 #include "uidswap.h"  #include "uidswap.h"
 #include "compat.h"  #include "compat.h"
 #include "cipher.h"  #include "cipher.h"
   #include "digest.h"
 #include "key.h"  #include "key.h"
 #include "kex.h"  #include "kex.h"
 #include "dh.h"  
 #include "myproposal.h"  #include "myproposal.h"
 #include "authfile.h"  #include "authfile.h"
 #include "pathnames.h"  #include "pathnames.h"
Line 94  __RCSID("$NetBSD$");
Line 95  __RCSID("$NetBSD$");
 #include "canohost.h"  #include "canohost.h"
 #include "hostfile.h"  #include "hostfile.h"
 #include "auth.h"  #include "auth.h"
   #include "authfd.h"
 #include "misc.h"  #include "misc.h"
 #include "msg.h"  #include "msg.h"
 #include "dispatch.h"  #include "dispatch.h"
 #include "channels.h"  #include "channels.h"
 #include "session.h"  #include "session.h"
 #include "monitor_mm.h"  
 #include "monitor.h"  #include "monitor.h"
 #ifdef GSSAPI  #ifdef GSSAPI
 #include "ssh-gss.h"  #include "ssh-gss.h"
 #endif  #endif
 #include "monitor_wrap.h"  #include "monitor_wrap.h"
 #include "roaming.h"  
 #include "ssh-sandbox.h"  #include "ssh-sandbox.h"
 #include "version.h"  #include "version.h"
 #include "random.h"  #include "ssherr.h"
   
   #include "pfilter.h"
   
 #ifdef LIBWRAP  #ifdef LIBWRAP
 #include <tcpd.h>  #include <tcpd.h>
Line 121  int deny_severity = LOG_WARNING;
Line 123  int deny_severity = LOG_WARNING;
 #include "ldapauth.h"  #include "ldapauth.h"
 #endif  #endif
   
 #ifndef O_NOCTTY  #ifndef HOST_NAME_MAX
 #define O_NOCTTY        0  #define HOST_NAME_MAX MAXHOSTNAMELEN
 #endif  #endif
   
 /* Re-exec fds */  /* Re-exec fds */
 #define REEXEC_DEVCRYPTO_RESERVED_FD    (STDERR_FILENO + 1)  #define REEXEC_DEVCRYPTO_RESERVED_FD    (STDERR_FILENO + 1)
 #define REEXEC_STARTUP_PIPE_FD          (STDERR_FILENO + 2)  #define REEXEC_STARTUP_PIPE_FD          (STDERR_FILENO + 2)
 #define REEXEC_CONFIG_PASS_FD           (STDERR_FILENO + 3)  #define REEXEC_CONFIG_PASS_FD           (STDERR_FILENO + 3)
 #define REEXEC_DEVURANDOM_FD            (STDERR_FILENO + 4)  #define REEXEC_MIN_FREE_FD              (STDERR_FILENO + 4)
 #define REEXEC_MIN_FREE_FD              (STDERR_FILENO + 5)  
   
 int urandom_fd = -1;  
   
 int myflag = 0;  
   
   
 extern char *__progname;  extern char *__progname;
   
Line 189  int num_listen_socks = 0;
Line 185  int num_listen_socks = 0;
 char *client_version_string = NULL;  char *client_version_string = NULL;
 char *server_version_string = NULL;  char *server_version_string = NULL;
   
 /* for rekeying XXX fixme */  /* Daemon's agent connection */
 Kex *xxx_kex;  int auth_sock = -1;
   int have_agent = 0;
   
 /*  /*
  * Any really sensitive data in the application is contained in this   * Any really sensitive data in the application is contained in this
Line 201  Kex *xxx_kex;
Line 198  Kex *xxx_kex;
  * not very useful.  Currently, memory locking is not implemented.   * not very useful.  Currently, memory locking is not implemented.
  */   */
 struct {  struct {
         Key     *server_key;            /* ephemeral server key */  
         Key     *ssh1_host_key;         /* ssh1 host key */  
         Key     **host_keys;            /* all private host keys */          Key     **host_keys;            /* all private host keys */
           Key     **host_pubkeys;         /* all public host keys */
         Key     **host_certificates;    /* all public host certificates */          Key     **host_certificates;    /* all public host certificates */
         int     have_ssh1_key;  
         int     have_ssh2_key;          int     have_ssh2_key;
         u_char  ssh1_cookie[SSH_SESSION_KEY_LENGTH];  
 } sensitive_data;  } sensitive_data;
   
 /*  
  * Flag indicating whether the RSA server key needs to be regenerated.  
  * Is set in the SIGALRM handler and cleared when the key is regenerated.  
  */  
 static volatile sig_atomic_t key_do_regen = 0;  
   
 /* This is set to true when a signal is received. */  /* This is set to true when a signal is received. */
 static volatile sig_atomic_t received_sighup = 0;  static volatile sig_atomic_t received_sighup = 0;
 static volatile sig_atomic_t received_sigterm = 0;  static volatile sig_atomic_t received_sigterm = 0;
Line 228  u_char *session_id2 = NULL;
Line 216  u_char *session_id2 = NULL;
 u_int session_id2_len = 0;  u_int session_id2_len = 0;
   
 /* record remote hostname or ip */  /* record remote hostname or ip */
 u_int utmp_len = MAXHOSTNAMELEN;  u_int utmp_len = HOST_NAME_MAX+1;
   
 /* options.max_startup sized array of fd ints */  /* options.max_startup sized array of fd ints */
 int *startup_pipes = NULL;  int *startup_pipes = NULL;
Line 237  int startup_pipe;  /* in child */
Line 225  int startup_pipe;  /* in child */
 /* variables used for privilege separation */  /* variables used for privilege separation */
 int use_privsep = -1;  int use_privsep = -1;
 struct monitor *pmonitor = NULL;  struct monitor *pmonitor = NULL;
   int privsep_is_preauth = 1;
   
 /* global authentication context */  /* global authentication context */
 Authctxt *the_authctxt = NULL;  Authctxt *the_authctxt = NULL;
Line 250  Buffer loginmsg;
Line 239  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);
   
 static void do_ssh1_kex(void);  
 static void do_ssh2_kex(void);  static void do_ssh2_kex(void);
   
 /*  /*
Line 303  __dead static void
Line 290  __dead static void
 sighup_restart(void)  sighup_restart(void)
 {  {
         logit("Received SIGHUP; restarting.");          logit("Received SIGHUP; restarting.");
           if (options.pid_file != NULL)
                   unlink(options.pid_file);
         close_listen_socks();          close_listen_socks();
         close_startup_pipes();          close_startup_pipes();
         alarm(0);  /* alarm timer persists across exec */          alarm(0);  /* alarm timer persists across exec */
Line 353  grace_alarm_handler(int sig)
Line 342  grace_alarm_handler(int sig)
         if (use_privsep && pmonitor != NULL && pmonitor->m_pid > 0)          if (use_privsep && pmonitor != NULL && pmonitor->m_pid > 0)
                 kill(pmonitor->m_pid, SIGALRM);                  kill(pmonitor->m_pid, SIGALRM);
   
         /* Log error and exit. */          /*
         sigdie("Timeout before authentication for %s", get_remote_ipaddr());           * Try to kill any processes that we have spawned, E.g. authorized
 }           * keys command helpers.
            */
 /*          if (getpgid(0) == getpid()) {
  * Signal handler for the key regeneration alarm.  Note that this                  signal(SIGTERM, SIG_IGN);
  * alarm only occurs in the daemon waiting for connections, and it does not                  killpg(0, SIGTERM);
  * do anything with the private key or random state before forking.          }
  * Thus there should be no concurrency control/asynchronous execution  
  * problems.  
  */  
 static void  
 generate_ephemeral_server_key(void)  
 {  
         verbose("Generating %s%d bit RSA key.",  
             sensitive_data.server_key ? "new " : "", options.server_key_bits);  
         if (sensitive_data.server_key != NULL)  
                 key_free(sensitive_data.server_key);  
         sensitive_data.server_key = key_generate(KEY_RSA1,  
             options.server_key_bits);  
         verbose("RSA key generation complete.");  
   
         arc4random_buf(sensitive_data.ssh1_cookie, SSH_SESSION_KEY_LENGTH);  
         arc4random_stir();  
 }  
   
 /*ARGSUSED*/  
 static void  
 key_regeneration_alarm(int sig)  
 {  
         int save_errno = errno;  
   
         signal(SIGALRM, SIG_DFL);          pfilter_notify(1);
         errno = save_errno;          /* Log error and exit. */
         key_do_regen = 1;          sigdie("Timeout before authentication for %s port %d",
               ssh_remote_ipaddr(active_state), ssh_remote_port(active_state));
 }  }
   
 static void  static void
 sshd_exchange_identification(int sock_in, int sock_out)  sshd_exchange_identification(struct ssh *ssh, int sock_in, int sock_out)
 {  {
         u_int i;          u_int i;
         int mismatch;  
         int remote_major, remote_minor;          int remote_major, remote_minor;
         int major, minor;  
         char *s;          char *s;
         const char *newline = "\n";  
         char buf[256];                  /* Must not be larger than remote_version. */          char buf[256];                  /* Must not be larger than remote_version. */
         char remote_version[256];       /* Must be at least as big as buf. */          char remote_version[256];       /* Must be at least as big as buf. */
   
         if ((options.protocol & SSH_PROTO_1) &&          xasprintf(&server_version_string, "SSH-%d.%d-%.100s%s%s\r\n",
             (options.protocol & SSH_PROTO_2)) {              PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2, SSH_VERSION,
                 major = PROTOCOL_MAJOR_1;              *options.version_addendum == '\0' ? "" : " ",
                 minor = 99;              options.version_addendum);
         } else if (options.protocol & SSH_PROTO_2) {  
                 major = PROTOCOL_MAJOR_2;  
                 minor = PROTOCOL_MINOR_2;  
                 newline = "\r\n";  
         } else {  
                 major = PROTOCOL_MAJOR_1;  
                 minor = PROTOCOL_MINOR_1;  
         }  
         snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s%s", major, minor,  
             SSH_RELEASE, newline);  
         server_version_string = xstrdup(buf);  
   
         /* Send our protocol version identification. */          /* Send our protocol version identification. */
         if (roaming_atomicio(vwrite, sock_out, server_version_string,          if (atomicio(vwrite, sock_out, server_version_string,
             strlen(server_version_string))              strlen(server_version_string))
             != strlen(server_version_string)) {              != strlen(server_version_string)) {
                 logit("Could not write ident string to %s", get_remote_ipaddr());                  logit("Could not write ident string to %s port %d",
                       ssh_remote_ipaddr(ssh), ssh_remote_port(ssh));
                 cleanup_exit(255);                  cleanup_exit(255);
         }          }
   
         /* Read other sides version identification. */          /* Read other sides version identification. */
         memset(buf, 0, sizeof(buf));          memset(buf, 0, sizeof(buf));
         for (i = 0; i < sizeof(buf) - 1; i++) {          for (i = 0; i < sizeof(buf) - 1; i++) {
                 if (roaming_atomicio(read, sock_in, &buf[i], 1) != 1) {                  if (atomicio(read, sock_in, &buf[i], 1) != 1) {
                         logit("Did not receive identification string from %s",                          logit("Did not receive identification string "
                             get_remote_ipaddr());                              "from %s port %d",
                               ssh_remote_ipaddr(ssh), ssh_remote_port(ssh));
                         cleanup_exit(255);                          cleanup_exit(255);
                 }                  }
                 if (buf[i] == '\r') {                  if (buf[i] == '\r') {
Line 458  sshd_exchange_identification(int sock_in
Line 413  sshd_exchange_identification(int sock_in
             &remote_major, &remote_minor, remote_version) != 3) {              &remote_major, &remote_minor, remote_version) != 3) {
                 s = __UNCONST("Protocol mismatch.\n");                  s = __UNCONST("Protocol mismatch.\n");
                 (void) atomicio(vwrite, sock_out, s, strlen(s));                  (void) atomicio(vwrite, sock_out, s, strlen(s));
                   logit("Bad protocol version identification '%.100s' "
                       "from %s port %d", client_version_string,
                       ssh_remote_ipaddr(ssh), ssh_remote_port(ssh));
                 close(sock_in);                  close(sock_in);
                 close(sock_out);                  close(sock_out);
                 logit("Bad protocol version identification '%.100s' from %s",  
                     client_version_string, get_remote_ipaddr());  
                 cleanup_exit(255);                  cleanup_exit(255);
         }          }
         debug("Client protocol version %d.%d; client software version %.100s",          debug("Client protocol version %d.%d; client software version %.100s",
             remote_major, remote_minor, remote_version);              remote_major, remote_minor, remote_version);
         logit("SSH: Server;Ltype: Version;Remote: %s-%d;Protocol: %d.%d;Client: %.100s",          logit("SSH: Server;Ltype: Version;Remote: %s-%d;Protocol: %d.%d;Client: %.100s",
               get_remote_ipaddr(), get_remote_port(),                ssh_remote_ipaddr(ssh), ssh_remote_port(ssh),
             remote_major, remote_minor, remote_version);              remote_major, remote_minor, remote_version);
   
         compat_datafellows(remote_version);          ssh->compat = compat_datafellows(remote_version);
   
         if (datafellows & SSH_BUG_PROBE) {          if ((ssh->compat & SSH_BUG_PROBE) != 0) {
                 logit("probed from %s with %s.  Don't panic.",                  logit("probed from %s port %d with %s.  Don't panic.",
                     get_remote_ipaddr(), client_version_string);                      ssh_remote_ipaddr(ssh), ssh_remote_port(ssh),
                       client_version_string);
                 cleanup_exit(255);                  cleanup_exit(255);
         }          }
           if ((ssh->compat & SSH_BUG_SCANNER) != 0) {
         if (datafellows & SSH_BUG_SCANNER) {                  logit("scanned from %s port %d with %s.  Don't panic.",
                 logit("scanned from %s with %s.  Don't panic.",                      ssh_remote_ipaddr(ssh), ssh_remote_port(ssh),
                     get_remote_ipaddr(), client_version_string);                      client_version_string);
                 cleanup_exit(255);                  cleanup_exit(255);
         }          }
           if ((ssh->compat & SSH_BUG_RSASIGMD5) != 0) {
         mismatch = 0;                  logit("Client version \"%.100s\" uses unsafe RSA signature "
         switch (remote_major) {                      "scheme; disabling use of RSA keys", remote_version);
         case 1:          }
                 if (remote_minor == 99) {          if ((ssh->compat & SSH_BUG_DERIVEKEY) != 0) {
                         if (options.protocol & SSH_PROTO_2)                  fatal("Client version \"%.100s\" uses unsafe key agreement; "
                                 enable_compat20();                      "refusing connection", remote_version);
                         else  
                                 mismatch = 1;  
                         break;  
                 }  
                 if (!(options.protocol & SSH_PROTO_1)) {  
                         mismatch = 1;  
                         break;  
                 }  
                 if (remote_minor < 3) {  
                         packet_disconnect("Your ssh version is too old and "  
                             "is no longer supported.  Please install a newer version.");  
                 } else if (remote_minor == 3) {  
                         /* note that this disables agent-forwarding */  
                         enable_compat13();  
                 }  
                 break;  
         case 2:  
                 if (options.protocol & SSH_PROTO_2) {  
                         enable_compat20();  
                         break;  
                 }  
                 /* FALLTHROUGH */  
         default:  
                 mismatch = 1;  
                 break;  
         }          }
   
         chop(server_version_string);          chop(server_version_string);
         debug("Local version string %.200s", server_version_string);          debug("Local version string %.200s", server_version_string);
   
         if (mismatch) {          if (remote_major == 2 ||
               (remote_major == 1 && remote_minor == 99)) {
                   enable_compat20();
           } else {
                 s = __UNCONST("Protocol major versions differ.\n");                  s = __UNCONST("Protocol major versions differ.\n");
                 (void) atomicio(vwrite, sock_out, s, strlen(s));                  (void) atomicio(vwrite, sock_out, s, strlen(s));
                 close(sock_in);                  close(sock_in);
                 close(sock_out);                  close(sock_out);
                 logit("Protocol major versions differ for %s: %.200s vs. %.200s",                  logit("Protocol major versions differ for %s port %d: "
                     get_remote_ipaddr(),                      "%.200s vs. %.200s",
                       ssh_remote_ipaddr(ssh), ssh_remote_port(ssh),
                     server_version_string, client_version_string);                      server_version_string, client_version_string);
                 cleanup_exit(255);                  cleanup_exit(255);
         }          }
Line 537  destroy_sensitive_data(void)
Line 474  destroy_sensitive_data(void)
 {  {
         int i;          int i;
   
         if (sensitive_data.server_key) {  
                 key_free(sensitive_data.server_key);  
                 sensitive_data.server_key = NULL;  
         }  
         for (i = 0; i < options.num_host_key_files; i++) {          for (i = 0; i < options.num_host_key_files; i++) {
                 if (sensitive_data.host_keys[i]) {                  if (sensitive_data.host_keys[i]) {
                         key_free(sensitive_data.host_keys[i]);                          key_free(sensitive_data.host_keys[i]);
Line 551  destroy_sensitive_data(void)
Line 484  destroy_sensitive_data(void)
                         sensitive_data.host_certificates[i] = NULL;                          sensitive_data.host_certificates[i] = NULL;
                 }                  }
         }          }
         sensitive_data.ssh1_host_key = NULL;  
         memset(sensitive_data.ssh1_cookie, 0, SSH_SESSION_KEY_LENGTH);  
 }  }
   
 /* Demote private to public keys for network child */  /* Demote private to public keys for network child */
Line 562  demote_sensitive_data(void)
Line 493  demote_sensitive_data(void)
         Key *tmp;          Key *tmp;
         int i;          int i;
   
         if (sensitive_data.server_key) {  
                 tmp = key_demote(sensitive_data.server_key);  
                 key_free(sensitive_data.server_key);  
                 sensitive_data.server_key = tmp;  
         }  
   
         for (i = 0; i < options.num_host_key_files; i++) {          for (i = 0; i < options.num_host_key_files; i++) {
                 if (sensitive_data.host_keys[i]) {                  if (sensitive_data.host_keys[i]) {
                         tmp = key_demote(sensitive_data.host_keys[i]);                          tmp = key_demote(sensitive_data.host_keys[i]);
                         key_free(sensitive_data.host_keys[i]);                          key_free(sensitive_data.host_keys[i]);
                         sensitive_data.host_keys[i] = tmp;                          sensitive_data.host_keys[i] = tmp;
                         if (tmp->type == KEY_RSA1)  
                                 sensitive_data.ssh1_host_key = tmp;  
                 }                  }
                 /* Certs do not need demotion */                  /* Certs do not need demotion */
         }          }
   
         /* We do not clear ssh1_host key and cookie.  XXX - Okay Niels? */  
 }  }
   
 static void  static void
 privsep_preauth_child(void)  privsep_preauth_child(void)
 {  {
         u_int32_t rnd[32];  
         gid_t gidset[1];          gid_t gidset[1];
         struct passwd *pw;          struct passwd *pw;
   
         /* Enable challenge-response authentication for privilege separation */          /* Enable challenge-response authentication for privilege separation */
         privsep_challenge_enable();          privsep_challenge_enable();
   
         if (read(urandom_fd, rnd, sizeof(rnd)) != sizeof(rnd)) {  #ifdef GSSAPI
             fatal("privsep_preauth_child: entropy read failed");          /* Cache supported mechanism OIDs for later use */
         }          if (options.gss_authentication)
         RAND_seed(rnd, sizeof(rnd));                  ssh_gssapi_prepare_supported_oids();
   #endif
         arc4random_stir();  
   
         /* Demote the private keys to public keys. */          /* Demote the private keys to public keys. */
         demote_sensitive_data();          demote_sensitive_data();
   
         if ((pw = getpwnam(SSH_PRIVSEP_USER)) == NULL)          /* Demote the child */
                 fatal("Privilege separation user %s does not exist",          if (getuid() == 0 || geteuid() == 0) {
                     SSH_PRIVSEP_USER);                  if ((pw = getpwnam(SSH_PRIVSEP_USER)) == NULL)
         memset(pw->pw_passwd, 0, strlen(pw->pw_passwd));                          fatal("Privilege separation user %s does not exist",
         endpwent();                              SSH_PRIVSEP_USER);
                   explicit_bzero(pw->pw_passwd, strlen(pw->pw_passwd));
         /* Change our root directory */                  endpwent();
         if (chroot(_PATH_PRIVSEP_CHROOT_DIR) == -1)  
                 fatal("chroot(\"%s\"): %s", _PATH_PRIVSEP_CHROOT_DIR,  
                     strerror(errno));  
         if (chdir("/") == -1)  
                 fatal("chdir(\"/\"): %s", strerror(errno));  
   
         /* Drop our privileges */                  /* Change our root directory */
         debug3("privsep user:group %u:%u", (u_int)pw->pw_uid,                  if (chroot(_PATH_PRIVSEP_CHROOT_DIR) == -1)
             (u_int)pw->pw_gid);                          fatal("chroot(\"%s\"): %s", _PATH_PRIVSEP_CHROOT_DIR,
 #if 0                              strerror(errno));
         /* XXX not ready, too heavy after chroot */                  if (chdir("/") == -1)
         do_setusercontext(pw);                          fatal("chdir(\"/\"): %s", strerror(errno));
 #else  
         gidset[0] = pw->pw_gid;                  /*
         if (setgroups(1, gidset) < 0)                   * Drop our privileges
                 fatal("setgroups: %.100s", strerror(errno));                   * NB. Can't use setusercontext() after chroot.
         permanently_set_uid(pw);                   */
 #endif                  debug3("privsep user:group %u:%u", (u_int)pw->pw_uid,
                       (u_int)pw->pw_gid);
                   gidset[0] = pw->pw_gid;
                   if (setgroups(1, gidset) < 0)
                           fatal("setgroups: %.100s", strerror(errno));
                   permanently_set_uid(pw);
           }
 }  }
   
 static int  static int
 privsep_preauth(Authctxt *authctxt)  privsep_preauth(Authctxt *authctxt)
 {  {
         int status;          int status, r;
         pid_t pid;          pid_t pid;
         struct ssh_sandbox *box = NULL;          struct ssh_sandbox *box = NULL;
   
         /* Set up unprivileged child process to deal with network data */          /* Set up unprivileged child process to deal with network data */
         pmonitor = monitor_init();          pmonitor = monitor_init();
         /* Store a pointer to the kex for later rekeying */          /* Store a pointer to the kex for later rekeying */
         pmonitor->m_pkex = &xxx_kex;          pmonitor->m_pkex = &active_state->kex;
   
         if (use_privsep == PRIVSEP_SANDBOX)          if (use_privsep == PRIVSEP_ON)
                 box = ssh_sandbox_init();                  box = ssh_sandbox_init();
         pid = fork();          pid = fork();
         if (pid == -1) {          if (pid == -1) {
Line 649  privsep_preauth(Authctxt *authctxt)
Line 569  privsep_preauth(Authctxt *authctxt)
         } else if (pid != 0) {          } else if (pid != 0) {
                 debug2("Network child is on pid %ld", (long)pid);                  debug2("Network child is on pid %ld", (long)pid);
   
                   pmonitor->m_pid = pid;
                   if (have_agent) {
                           r = ssh_get_authentication_socket(&auth_sock);
                           if (r != 0) {
                                   error("Could not get agent socket: %s",
                                       ssh_err(r));
                                   have_agent = 0;
                           }
                   }
                 if (box != NULL)                  if (box != NULL)
                         ssh_sandbox_parent_preauth(box, pid);                          ssh_sandbox_parent_preauth(box, pid);
                 pmonitor->m_pid = pid;  
                 monitor_child_preauth(authctxt, pmonitor);                  monitor_child_preauth(authctxt, pmonitor);
   
                 /* Sync memory */  
                 monitor_sync(pmonitor);  
   
                 /* Wait for the child's exit status */                  /* Wait for the child's exit status */
                 while (waitpid(pid, &status, 0) < 0) {                  while (waitpid(pid, &status, 0) < 0) {
                         if (errno != EINTR)                          if (errno == EINTR)
                                 fatal("%s: waitpid: %s", __func__,                                  continue;
                                     strerror(errno));                          pmonitor->m_pid = -1;
                           fatal("%s: waitpid: %s", __func__, strerror(errno));
                 }                  }
                   privsep_is_preauth = 0;
                   pmonitor->m_pid = -1;
                 if (WIFEXITED(status)) {                  if (WIFEXITED(status)) {
                         if (WEXITSTATUS(status) != 0)                          if (WEXITSTATUS(status) != 0)
                                 fatal("%s: preauth child exited with status %d",                                  fatal("%s: preauth child exited with status %d",
Line 681  privsep_preauth(Authctxt *authctxt)
Line 609  privsep_preauth(Authctxt *authctxt)
                 /* Arrange for logging to be sent to the monitor */                  /* Arrange for logging to be sent to the monitor */
                 set_log_handler(mm_log_handler, pmonitor);                  set_log_handler(mm_log_handler, pmonitor);
   
                 /* Demote the child */                  privsep_preauth_child();
                 if (getuid() == 0 || geteuid() == 0)  
                         privsep_preauth_child();  
                 setproctitle("%s", "[net]");                  setproctitle("%s", "[net]");
                 if (box != NULL)                  if (box != NULL)
                         ssh_sandbox_child(box);                          ssh_sandbox_child(box);
Line 695  privsep_preauth(Authctxt *authctxt)
Line 621  privsep_preauth(Authctxt *authctxt)
 static void  static void
 privsep_postauth(Authctxt *authctxt)  privsep_postauth(Authctxt *authctxt)
 {  {
         u_int32_t rnd[32];          if (authctxt->pw->pw_uid == 0) {
   
         if (authctxt->pw->pw_uid == 0 || options.use_login) {  
                 /* File descriptor passing is broken or root login */                  /* File descriptor passing is broken or root login */
                 use_privsep = 0;                  use_privsep = 0;
                 goto skip;                  goto skip;
Line 726  privsep_postauth(Authctxt *authctxt)
Line 650  privsep_postauth(Authctxt *authctxt)
         /* Demote the private keys to public keys. */          /* Demote the private keys to public keys. */
         demote_sensitive_data();          demote_sensitive_data();
   
         if (read(urandom_fd, rnd, sizeof(rnd)) != sizeof(rnd)) {  
             fatal("privsep_postauth: entropy read failed");  
         }  
         RAND_seed(rnd, sizeof(rnd));  
   
         arc4random_stir();  
   
         /* Drop privileges */          /* Drop privileges */
         do_setusercontext(authctxt->pw);          do_setusercontext(authctxt->pw);
   
Line 760  list_hostkey_types(void)
Line 677  list_hostkey_types(void)
         for (i = 0; i < options.num_host_key_files; i++) {          for (i = 0; i < options.num_host_key_files; i++) {
                 key = sensitive_data.host_keys[i];                  key = sensitive_data.host_keys[i];
                 if (key == NULL)                  if (key == NULL)
                           key = sensitive_data.host_pubkeys[i];
                   if (key == NULL)
                         continue;                          continue;
                   /* Check that the key is accepted in HostkeyAlgorithms */
                   if (match_pattern_list(sshkey_ssh_name(key),
                       options.hostkeyalgorithms, 0) != 1) {
                           debug3("%s: %s key not permitted by HostkeyAlgorithms",
                               __func__, sshkey_ssh_name(key));
                           continue;
                   }
                 switch (key->type) {                  switch (key->type) {
                 case KEY_RSA:                  case KEY_RSA:
                 case KEY_DSA:                  case KEY_DSA:
                 case KEY_ECDSA:                  case KEY_ECDSA:
                   case KEY_ED25519:
                         if (buffer_len(&b) > 0)                          if (buffer_len(&b) > 0)
                                 buffer_append(&b, ",", 1);                                  buffer_append(&b, ",", 1);
                         p = key_ssh_name(key);                          p = key_ssh_name(key);
                         buffer_append(&b, p, strlen(p));                          buffer_append(&b, p, strlen(p));
   
                           /* for RSA we also support SHA2 signatures */
                           if (key->type == KEY_RSA) {
                                   p = ",rsa-sha2-512,rsa-sha2-256";
                                   buffer_append(&b, p, strlen(p));
                           }
                         break;                          break;
                 }                  }
                 /* If the private key has a cert peer, then list that too */                  /* If the private key has a cert peer, then list that too */
Line 776  list_hostkey_types(void)
Line 709  list_hostkey_types(void)
                 if (key == NULL)                  if (key == NULL)
                         continue;                          continue;
                 switch (key->type) {                  switch (key->type) {
                 case KEY_RSA_CERT_V00:  
                 case KEY_DSA_CERT_V00:  
                 case KEY_RSA_CERT:                  case KEY_RSA_CERT:
                 case KEY_DSA_CERT:                  case KEY_DSA_CERT:
                 case KEY_ECDSA_CERT:                  case KEY_ECDSA_CERT:
                   case KEY_ED25519_CERT:
                         if (buffer_len(&b) > 0)                          if (buffer_len(&b) > 0)
                                 buffer_append(&b, ",", 1);                                  buffer_append(&b, ",", 1);
                         p = key_ssh_name(key);                          p = key_ssh_name(key);
Line 788  list_hostkey_types(void)
Line 720  list_hostkey_types(void)
                         break;                          break;
                 }                  }
         }          }
         buffer_append(&b, "\0", 1);          if ((ret = sshbuf_dup_string(&b)) == NULL)
         ret = xstrdup(buffer_ptr(&b));                  fatal("%s: sshbuf_dup_string failed", __func__);
         buffer_free(&b);          buffer_free(&b);
         debug("list_hostkey_types: %s", ret);          debug("list_hostkey_types: %s", ret);
         return ret;          return ret;
 }  }
   
 static Key *  static Key *
 get_hostkey_by_type(int type, int need_private)  get_hostkey_by_type(int type, int nid, int need_private, struct ssh *ssh)
 {  {
         int i;          int i;
         Key *key;          Key *key;
   
         for (i = 0; i < options.num_host_key_files; i++) {          for (i = 0; i < options.num_host_key_files; i++) {
                 switch (type) {                  switch (type) {
                 case KEY_RSA_CERT_V00:  
                 case KEY_DSA_CERT_V00:  
                 case KEY_RSA_CERT:                  case KEY_RSA_CERT:
                 case KEY_DSA_CERT:                  case KEY_DSA_CERT:
                 case KEY_ECDSA_CERT:                  case KEY_ECDSA_CERT:
                   case KEY_ED25519_CERT:
                         key = sensitive_data.host_certificates[i];                          key = sensitive_data.host_certificates[i];
                         break;                          break;
                 default:                  default:
                         key = sensitive_data.host_keys[i];                          key = sensitive_data.host_keys[i];
                           if (key == NULL && !need_private)
                                   key = sensitive_data.host_pubkeys[i];
                         break;                          break;
                 }                  }
                 if (key != NULL && key->type == type)                  if (key != NULL && key->type == type &&
                       (key->type != KEY_ECDSA || key->ecdsa_nid == nid))
                         return need_private ?                          return need_private ?
                             sensitive_data.host_keys[i] : key;                              sensitive_data.host_keys[i] : key;
         }          }
Line 822  get_hostkey_by_type(int type, int need_p
Line 756  get_hostkey_by_type(int type, int need_p
 }  }
   
 Key *  Key *
 get_hostkey_public_by_type(int type)  get_hostkey_public_by_type(int type, int nid, struct ssh *ssh)
 {  {
         return get_hostkey_by_type(type, 0);          return get_hostkey_by_type(type, nid, 0, ssh);
 }  }
   
 Key *  Key *
 get_hostkey_private_by_type(int type)  get_hostkey_private_by_type(int type, int nid, struct ssh *ssh)
 {  {
         return get_hostkey_by_type(type, 1);          return get_hostkey_by_type(type, nid, 1, ssh);
 }  }
   
 Key *  Key *
Line 841  get_hostkey_by_index(int ind)
Line 775  get_hostkey_by_index(int ind)
         return (sensitive_data.host_keys[ind]);          return (sensitive_data.host_keys[ind]);
 }  }
   
   Key *
   get_hostkey_public_by_index(int ind, struct ssh *ssh)
   {
           if (ind < 0 || ind >= options.num_host_key_files)
                   return (NULL);
           return (sensitive_data.host_pubkeys[ind]);
   }
   
 int  int
 get_hostkey_index(Key *key)  get_hostkey_index(Key *key, int compare, struct ssh *ssh)
 {  {
         int i;          int i;
   
         for (i = 0; i < options.num_host_key_files; i++) {          for (i = 0; i < options.num_host_key_files; i++) {
                 if (key_is_cert(key)) {                  if (key_is_cert(key)) {
                         if (key == sensitive_data.host_certificates[i])                          if (key == sensitive_data.host_certificates[i] ||
                               (compare && sensitive_data.host_certificates[i] &&
                               sshkey_equal(key,
                               sensitive_data.host_certificates[i])))
                                 return (i);                                  return (i);
                 } else {                  } else {
                         if (key == sensitive_data.host_keys[i])                          if (key == sensitive_data.host_keys[i] ||
                               (compare && sensitive_data.host_keys[i] &&
                               sshkey_equal(key, sensitive_data.host_keys[i])))
                                   return (i);
                           if (key == sensitive_data.host_pubkeys[i] ||
                               (compare && sensitive_data.host_pubkeys[i] &&
                               sshkey_equal(key, sensitive_data.host_pubkeys[i])))
                                 return (i);                                  return (i);
                 }                  }
         }          }
         return (-1);          return (-1);
 }  }
   
   /* Inform the client of all hostkeys */
   static void
   notify_hostkeys(struct ssh *ssh)
   {
           struct sshbuf *buf;
           struct sshkey *key;
           int i, nkeys, r;
           char *fp;
   
           /* Some clients cannot cope with the hostkeys message, skip those. */
           if (datafellows & SSH_BUG_HOSTKEYS)
                   return;
   
           if ((buf = sshbuf_new()) == NULL)
                   fatal("%s: sshbuf_new", __func__);
           for (i = nkeys = 0; i < options.num_host_key_files; i++) {
                   key = get_hostkey_public_by_index(i, ssh);
                   if (key == NULL || key->type == KEY_UNSPEC ||
                       sshkey_is_cert(key))
                           continue;
                   fp = sshkey_fingerprint(key, options.fingerprint_hash,
                       SSH_FP_DEFAULT);
                   debug3("%s: key %d: %s %s", __func__, i,
                       sshkey_ssh_name(key), fp);
                   free(fp);
                   if (nkeys == 0) {
                           packet_start(SSH2_MSG_GLOBAL_REQUEST);
                           packet_put_cstring("hostkeys-00@openssh.com");
                           packet_put_char(0); /* want-reply */
                   }
                   sshbuf_reset(buf);
                   if ((r = sshkey_putb(key, buf)) != 0)
                           fatal("%s: couldn't put hostkey %d: %s",
                               __func__, i, ssh_err(r));
                   packet_put_string(sshbuf_ptr(buf), sshbuf_len(buf));
                   nkeys++;
           }
           debug3("%s: sent %d hostkeys", __func__, nkeys);
           if (nkeys == 0)
                   fatal("%s: no hostkeys", __func__);
           packet_send();
           sshbuf_free(buf);
   }
   
 /*  /*
  * returns 1 if connection should be dropped, 0 otherwise.   * returns 1 if connection should be dropped, 0 otherwise.
  * dropping starts at connection #max_startups_begin with a probability   * dropping starts at connection #max_startups_begin with a probability
Line 890  __dead static void
Line 885  __dead static void
 usage(void)  usage(void)
 {  {
         fprintf(stderr, "%s, %s\n",          fprintf(stderr, "%s, %s\n",
             SSH_VERSION, SSLeay_version(SSLEAY_VERSION));              SSH_VERSION,
   #ifdef WITH_OPENSSL
               SSLeay_version(SSLEAY_VERSION)
   #else
               "without OpenSSL"
   #endif
           );
         fprintf(stderr,          fprintf(stderr,
 "usage: sshd [-46DdeiqTt] [-b bits] [-C connection_spec] [-c host_cert_file]\n"  "usage: sshd [-46DdeiqTt] [-C connection_spec] [-c host_cert_file]\n"
 "            [-f config_file] [-g login_grace_time] [-h host_key_file]\n"  "            [-E log_file] [-f config_file] [-g login_grace_time]\n"
 "            [-k key_gen_time] [-o option] [-p port] [-u len]\n"  "            [-h host_key_file] [-o option] [-p port] [-u len]\n"
         );          );
         exit(1);          exit(1);
 }  }
   
 static void  static void
 send_rexec_state(int fd, Buffer *conf)  send_rexec_state(int fd, struct sshbuf *conf)
 {  {
         Buffer m;          struct sshbuf *m;
           int r;
   
         debug3("%s: entering fd = %d config len %d", __func__, fd,          debug3("%s: entering fd = %d config len %zu", __func__, fd,
             buffer_len(conf));              sshbuf_len(conf));
   
         /*          /*
          * Protocol from reexec master to child:           * Protocol from reexec master to child:
          *      string  configuration           *      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);          if ((m = sshbuf_new()) == NULL)
         buffer_put_cstring(&m, buffer_ptr(conf));                  fatal("%s: sshbuf_new failed", __func__);
           if ((r = sshbuf_put_stringb(m, conf)) != 0)
         if (sensitive_data.server_key != NULL &&                  fatal("%s: buffer error: %s", __func__, ssh_err(r));
             sensitive_data.server_key->type == KEY_RSA1) {          if (ssh_msg_send(fd, 0, m) == -1)
                 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__);                  fatal("%s: ssh_msg_send failed", __func__);
   
         buffer_free(&m);          sshbuf_free(m);
   
         debug3("%s: done", __func__);          debug3("%s: done", __func__);
 }  }
Line 959  recv_rexec_state(int fd, Buffer *conf)
Line 943  recv_rexec_state(int fd, Buffer *conf)
   
         cp = buffer_get_string(&m, &len);          cp = buffer_get_string(&m, &len);
         if (conf != NULL)          if (conf != NULL)
                 buffer_append(conf, cp, len + 1);                  buffer_append(conf, cp, len);
         xfree(cp);          free(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);          buffer_free(&m);
   
         debug3("%s: done", __func__);          debug3("%s: done", __func__);
Line 1006  server_accept_inetd(int *sock_in, int *s
Line 977  server_accept_inetd(int *sock_in, int *s
         if ((fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {          if ((fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {
                 dup2(fd, STDIN_FILENO);                  dup2(fd, STDIN_FILENO);
                 dup2(fd, STDOUT_FILENO);                  dup2(fd, STDOUT_FILENO);
                 if (fd > STDOUT_FILENO)                  if (!log_stderr)
                           dup2(fd, STDERR_FILENO);
                   if (fd > (log_stderr ? STDERR_FILENO : STDOUT_FILENO))
                         close(fd);                          close(fd);
         }          }
         debug("inetd sockets after dupping: %d, %d", *sock_in, *sock_out);          debug("inetd sockets after dupping: %d, %d", *sock_in, *sock_out);
Line 1049  server_listen(void)
Line 1022  server_listen(void)
                         close(listen_sock);                          close(listen_sock);
                         continue;                          continue;
                 }                  }
                   if (fcntl(listen_sock, F_SETFD, FD_CLOEXEC) == -1) {
                           verbose("socket: CLOEXEC: %s", strerror(errno));
                           close(listen_sock);
                           continue;
                   }
                 /*                  /*
                  * Set socket options.                   * Set socket options.
                  * Allow local port reuse in TIME_WAIT.                   * Allow local port reuse in TIME_WAIT.
Line 1095  server_accept_loop(int *sock_in, int *so
Line 1073  server_accept_loop(int *sock_in, int *so
 {  {
         fd_set *fdset;          fd_set *fdset;
         int i, j, ret, maxfd;          int i, j, ret, maxfd;
         int key_used = 0, startups = 0;          int startups = 0;
         int startup_p[2] = { -1 , -1 };          int startup_p[2] = { -1 , -1 };
         struct sockaddr_storage from;          struct sockaddr_storage from;
         socklen_t fromlen;          socklen_t fromlen;
         pid_t pid;          pid_t pid;
         uint8_t rnd[32];  
   
         /* setup fd set for accept */          /* setup fd set for accept */
         fdset = NULL;          fdset = NULL;
Line 1113  server_accept_loop(int *sock_in, int *so
Line 1090  server_accept_loop(int *sock_in, int *so
         for (i = 0; i < options.max_startups; i++)          for (i = 0; i < options.max_startups; i++)
                 startup_pipes[i] = -1;                  startup_pipes[i] = -1;
   
           pfilter_init();
         /*          /*
          * Stay listening for connections until the system crashes or           * Stay listening for connections until the system crashes or
          * the daemon is killed with a signal.           * the daemon is killed with a signal.
Line 1120  server_accept_loop(int *sock_in, int *so
Line 1098  server_accept_loop(int *sock_in, int *so
         for (;;) {          for (;;) {
                 if (received_sighup)                  if (received_sighup)
                         sighup_restart();                          sighup_restart();
                 if (fdset != NULL)                  free(fdset);
                         xfree(fdset);                  fdset = xcalloc(howmany(maxfd + 1, NFDBITS),
                 fdset = (fd_set *)xcalloc(howmany(maxfd + 1, NFDBITS),  
                     sizeof(fd_mask));                      sizeof(fd_mask));
   
                 for (i = 0; i < num_listen_socks; i++)                  for (i = 0; i < num_listen_socks; i++)
Line 1139  server_accept_loop(int *sock_in, int *so
Line 1116  server_accept_loop(int *sock_in, int *so
                         logit("Received signal %d; terminating.",                          logit("Received signal %d; terminating.",
                             (int) received_sigterm);                              (int) received_sigterm);
                         close_listen_socks();                          close_listen_socks();
                         unlink(options.pid_file);                          if (options.pid_file != NULL)
                                   unlink(options.pid_file);
                         exit(received_sigterm == SIGTERM ? 0 : 255);                          exit(received_sigterm == SIGTERM ? 0 : 255);
                 }                  }
                 if (key_used && key_do_regen) {  
                         generate_ephemeral_server_key();  
                         key_used = 0;  
                         key_do_regen = 0;  
                 }  
                 if (ret < 0)                  if (ret < 0)
                         continue;                          continue;
   
Line 1170  server_accept_loop(int *sock_in, int *so
Line 1143  server_accept_loop(int *sock_in, int *so
                         *newsock = accept(listen_socks[i],                          *newsock = accept(listen_socks[i],
                             (struct sockaddr *)&from, &fromlen);                              (struct sockaddr *)&from, &fromlen);
                         if (*newsock < 0) {                          if (*newsock < 0) {
                                 if (errno != EINTR && errno != EWOULDBLOCK)                                  if (errno != EINTR && errno != EWOULDBLOCK &&
                                         error("accept: %.100s", strerror(errno));                                      errno != ECONNABORTED)
                                           error("accept: %.100s",
                                               strerror(errno));
                                   if (errno == EMFILE || errno == ENFILE)
                                           usleep(100 * 1000);
                                 continue;                                  continue;
                         }                          }
                         if (unset_nonblock(*newsock) == -1) {                          if (unset_nonblock(*newsock) == -1) {
Line 1179  server_accept_loop(int *sock_in, int *so
Line 1156  server_accept_loop(int *sock_in, int *so
                                 continue;                                  continue;
                         }                          }
                         if (drop_connection(startups) == 1) {                          if (drop_connection(startups) == 1) {
                                 debug("drop connection #%d", startups);                                  char *laddr = get_local_ipaddr(*newsock);
                                   char *raddr = get_peer_ipaddr(*newsock);
   
                                   verbose("drop connection #%d from [%s]:%d "
                                       "on [%s]:%d past MaxStartups", startups,
                                       raddr, get_peer_port(*newsock),
                                       laddr, get_local_port(*newsock));
                                   free(laddr);
                                   free(raddr);
                                 close(*newsock);                                  close(*newsock);
                                 continue;                                  continue;
                         }                          }
Line 1274  server_accept_loop(int *sock_in, int *so
Line 1259  server_accept_loop(int *sock_in, int *so
                                 close(config_s[0]);                                  close(config_s[0]);
                                 close(config_s[1]);                                  close(config_s[1]);
                         }                          }
   
                         /*  
                          * Mark that the key has been used (it  
                          * was "given" to the child).  
                          */  
                         if ((options.protocol & SSH_PROTO_1) &&  
                             key_used == 0) {  
                                 /* Schedule server key regeneration alarm. */  
                                 signal(SIGALRM, key_regeneration_alarm);  
                                 alarm(options.key_regeneration_time);  
                                 key_used = 1;  
                         }  
   
                         close(*newsock);                          close(*newsock);
   
                         /*  
                          * Ensure that our random state differs  
                          * from that of the child  
                          */  
                         if (read(urandom_fd, rnd, sizeof(rnd)) !=  
                             sizeof(rnd)) {  
                                 fatal("server_accept_loop: "  
                                       "entropy read failed");  
                         }  
                         RAND_seed(rnd, sizeof(rnd));  
                         arc4random_stir();  
                 }                  }
   
                 /* child process check (or debug mode) */                  /* child process check (or debug mode) */
Line 1308  server_accept_loop(int *sock_in, int *so
Line 1268  server_accept_loop(int *sock_in, int *so
         }          }
 }  }
   
   /*
    * If IP options are supported, make sure there are none (log and
    * return an error if any are found).  Basically we are worried about
    * source routing; it can be used to pretend you are somebody
    * (ip-address) you are not. That itself may be "almost acceptable"
    * under certain circumstances, but rhosts autentication is useless
    * if source routing is accepted. Notice also that if we just dropped
    * source routing here, the other side could use IP spoofing to do
    * rest of the interaction and could still bypass security.  So we
    * exit here if we detect any IP options.
    */
   static void
   check_ip_options(struct ssh *ssh)
   {
           int sock_in = ssh_packet_get_connection_in(ssh);
           struct sockaddr_storage from;
           socklen_t fromlen = sizeof(from);
   #ifdef IP_OPTIONS
           socklen_t option_size, i;
           u_char opts[200];
           socklen_t i, option_size = sizeof(opts), fromlen = sizeof(from);
           char text[sizeof(opts) * 3 + 1];
   #endif
   
           memset(&from, 0, sizeof(from));
           if (getpeername(sock_in, (struct sockaddr *)&from,
               &fromlen) < 0)
                   return;
           if (from.ss_family != AF_INET)
                   return;
           /* XXX IPv6 options? */
   #ifdef IP_OPTIONS
           if (getsockopt(sock_in, IPPROTO_IP, IP_OPTIONS, opts,
               &option_size) >= 0 && option_size != 0) {
                   text[0] = '\0';
                   for (i = 0; i < option_size; i++)
                           snprintf(text + i*3, sizeof(text) - i*3,
                               " %2.2x", opts[i]);
                   fatal("Connection from %.100s port %d with IP opts: %.800s",
                       ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), text);
           }
   #endif
           return;
   }
   
 /*  /*
  * Main program for the daemon.   * Main program for the daemon.
Line 1315  server_accept_loop(int *sock_in, int *so
Line 1319  server_accept_loop(int *sock_in, int *so
 int  int
 main(int ac, char **av)  main(int ac, char **av)
 {  {
           struct ssh *ssh = NULL;
         extern char *optarg;          extern char *optarg;
         extern int optind;          extern int optind;
         int opt, i, j, on = 1;          int r, opt, i, j, on = 1, already_daemon;
         int sock_in = -1, sock_out = -1, newsock = -1;          int sock_in = -1, sock_out = -1, newsock = -1;
         const char *remote_ip;          const char *remote_ip;
         char *test_user = NULL, *test_host = NULL, *test_addr = NULL;  
         int remote_port;          int remote_port;
         char *line, *p, *cp;          char *fp, *line, *laddr, *logfile = NULL;
         int config_s[2] = { -1 , -1 };          int config_s[2] = { -1 , -1 };
           u_int n;
         u_int64_t ibytes, obytes;          u_int64_t ibytes, obytes;
         mode_t new_umask;          mode_t new_umask;
         Key *key;          Key *key;
           Key *pubkey;
           int keytype;
         Authctxt *authctxt;          Authctxt *authctxt;
         uint8_t rnd[32];          struct connection_info *connection_info = get_connection_info(0, 0);
   
           ssh_malloc_init();      /* must be called before any mallocs */
         /* Save argv. */          /* Save argv. */
         saved_argv = av;          saved_argv = av;
         rexec_argc = ac;          rexec_argc = ac;
Line 1341  main(int ac, char **av)
Line 1349  main(int ac, char **av)
         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:C:dDeiqrtQRT46")) != -1) {          while ((opt = getopt(ac, av,
               "C:E:b:c:f:g:h:k:o:p:u:46DQRTdeiqrt")) != -1) {
                 switch (opt) {                  switch (opt) {
                 case '4':                  case '4':
                         options.address_family = AF_INET;                          options.address_family = AF_INET;
Line 1370  main(int ac, char **av)
Line 1379  main(int ac, char **av)
                 case 'D':                  case 'D':
                         no_daemon_flag = 1;                          no_daemon_flag = 1;
                         break;                          break;
                   case 'E':
                           logfile = optarg;
                           /* FALLTHROUGH */
                 case 'e':                  case 'e':
                         log_stderr = 1;                          log_stderr = 1;
                         break;                          break;
Line 1390  main(int ac, char **av)
Line 1402  main(int ac, char **av)
                         options.log_level = SYSLOG_LEVEL_QUIET;                          options.log_level = SYSLOG_LEVEL_QUIET;
                         break;                          break;
                 case 'b':                  case 'b':
                         options.server_key_bits = (int)strtonum(optarg, 256,                          /* protocol 1, ignored */
                             32768, NULL);  
                         break;                          break;
                 case 'p':                  case 'p':
                         options.ports_from_cmdline = 1;                          options.ports_from_cmdline = 1;
Line 1412  main(int ac, char **av)
Line 1423  main(int ac, char **av)
                         }                          }
                         break;                          break;
                 case 'k':                  case 'k':
                         if ((options.key_regeneration_time = convtime(optarg)) == -1) {                          /* protocol 1, ignored */
                                 fprintf(stderr, "Invalid key regeneration interval.\n");  
                                 exit(1);  
                         }  
                         break;                          break;
                 case 'h':                  case 'h':
                         if (options.num_host_key_files >= MAX_HOSTKEYS) {                          if (options.num_host_key_files >= MAX_HOSTKEYS) {
Line 1432  main(int ac, char **av)
Line 1440  main(int ac, char **av)
                         test_flag = 2;                          test_flag = 2;
                         break;                          break;
                 case 'C':                  case 'C':
                         cp = optarg;                          if (parse_server_match_testspec(connection_info,
                         while ((p = strsep(&cp, ",")) && *p != '\0') {                              optarg) == -1)
                                 if (strncmp(p, "addr=", 5) == 0)                                  exit(1);
                                         test_addr = xstrdup(p + 5);  
                                 else if (strncmp(p, "host=", 5) == 0)  
                                         test_host = xstrdup(p + 5);  
                                 else if (strncmp(p, "user=", 5) == 0)  
                                         test_user = xstrdup(p + 5);  
                                 else {  
                                         fprintf(stderr, "Invalid test "  
                                             "mode specification %s\n", p);  
                                         exit(1);  
                                 }  
                         }  
                         break;                          break;
                 case 'u':                  case 'u':
                         utmp_len = (u_int)strtonum(optarg, 0, MAXHOSTNAMELEN+1, NULL);                          utmp_len = (u_int)strtonum(optarg, 0, HOST_NAME_MAX+1+1, NULL);
                         if (utmp_len > MAXHOSTNAMELEN) {                          if (utmp_len > HOST_NAME_MAX+1) {
                                 fprintf(stderr, "Invalid utmp length.\n");                                  fprintf(stderr, "Invalid utmp length.\n");
                                 exit(1);                                  exit(1);
                         }                          }
Line 1457  main(int ac, char **av)
Line 1454  main(int ac, char **av)
                 case 'o':                  case 'o':
                         line = xstrdup(optarg);                          line = xstrdup(optarg);
                         if (process_server_config_line(&options, line,                          if (process_server_config_line(&options, line,
                             "command-line", 0, NULL, NULL, NULL, NULL) != 0)                              "command-line", 0, NULL, NULL) != 0)
                                 exit(1);                                  exit(1);
                         xfree(line);                          free(line);
                         break;                          break;
                 case '?':                  case '?':
                 default:                  default:
Line 1472  main(int ac, char **av)
Line 1469  main(int ac, char **av)
         if (!test_flag && (rexec_flag && (av[0] == NULL || *av[0] != '/')))          if (!test_flag && (rexec_flag && (av[0] == NULL || *av[0] != '/')))
                 fatal("sshd re-exec requires execution with an absolute path");                  fatal("sshd re-exec requires execution with an absolute path");
         if (rexeced_flag)          if (rexeced_flag)
                 closefrom(REEXEC_MIN_FREE_FD);                  r = closefrom(REEXEC_MIN_FREE_FD);
         else          else
                 closefrom(REEXEC_DEVCRYPTO_RESERVED_FD);                  r = closefrom(REEXEC_DEVCRYPTO_RESERVED_FD);
           if (r == -1)
                   fatal("closefrom failed: %.200s", strerror(errno));
   
   #ifdef WITH_OPENSSL
         OpenSSL_add_all_algorithms();          OpenSSL_add_all_algorithms();
   #endif
   
         /*          /* If requested, redirect the logs to the specified logfile. */
          * The OpenSSL PRNG is used by key-generation functions we          if (logfile != NULL)
          * rely on for security.  Seed it ourselves, so that:                  log_redirect_stderr_to(logfile);
          *  
          *      A) it does not seed itself from somewhere questionable,  
          *         such as the libc arc4random or, worse, getpid().  
          *      B) it does not reopen /dev/urandom on systems where  
          *         this is expensive (generator keyed on open, etc).  
          *  
          * Note that /dev/urandom will never return the same data to  
          * two callers, even if they have the same dup'd reference to it.  
          */  
         if (rexeced_flag) {  
                 urandom_fd = REEXEC_DEVURANDOM_FD;  
         } else {  
                 urandom_fd = open("/dev/urandom", O_RDONLY);  
                 if (urandom_fd == -1) {  
                         fatal("sshd requires random device");  
                 }  
                 /* Might as well do this here; why do it later? */  
                 dup2(urandom_fd, REEXEC_DEVURANDOM_FD);  
                 close(urandom_fd);  
                 urandom_fd = REEXEC_DEVURANDOM_FD;  
         }  
         if (read(urandom_fd, rnd, sizeof(rnd)) != sizeof(rnd)) {  
                 fatal("entropy read failed");  
         }  
         RAND_seed(rnd, sizeof(rnd));  
   
         /*          /*
          * Force logging to stderr until we have loaded the private host           * Force logging to stderr until we have loaded the private host
          * key (unless started from inetd)           * key (unless started from inetd)
Line 1518  main(int ac, char **av)
Line 1493  main(int ac, char **av)
             SYSLOG_FACILITY_AUTH : options.log_facility,              SYSLOG_FACILITY_AUTH : options.log_facility,
             log_stderr || !inetd_flag);              log_stderr || !inetd_flag);
   
         sensitive_data.server_key = NULL;  
         sensitive_data.ssh1_host_key = NULL;  
         sensitive_data.have_ssh1_key = 0;  
         sensitive_data.have_ssh2_key = 0;          sensitive_data.have_ssh2_key = 0;
   
         /*          /*
Line 1528  main(int ac, char **av)
Line 1500  main(int ac, char **av)
          * the parameters we need.  If we're not doing an extended test,           * the parameters we need.  If we're not doing an extended test,
          * do not silently ignore connection test params.           * do not silently ignore connection test params.
          */           */
         if (test_flag >= 2 &&          if (test_flag >= 2 && server_match_spec_complete(connection_info) == 0)
            (test_user != NULL || test_host != NULL || test_addr != NULL)  
             && (test_user == NULL || test_host == NULL || test_addr == NULL))  
                 fatal("user, host and addr are all required when testing "                  fatal("user, host and addr are all required when testing "
                    "Match configs");                     "Match configs");
         if (test_flag < 2 && (test_user != NULL || test_host != NULL ||          if (test_flag < 2 && server_match_spec_complete(connection_info) >= 0)
             test_addr != NULL))  
                 fatal("Config test connection parameter (-C) provided without "                  fatal("Config test connection parameter (-C) provided without "
                    "test mode (-T)");                     "test mode (-T)");
   
Line 1542  main(int ac, char **av)
Line 1511  main(int ac, char **av)
         buffer_init(&cfg);          buffer_init(&cfg);
         if (rexeced_flag)          if (rexeced_flag)
                 recv_rexec_state(REEXEC_CONFIG_PASS_FD, &cfg);                  recv_rexec_state(REEXEC_CONFIG_PASS_FD, &cfg);
         else          else if (strcasecmp(config_file_name, "none") != 0)
                 load_server_config(config_file_name, &cfg);                  load_server_config(config_file_name, &cfg);
   
         parse_server_config(&options, rexeced_flag ? "rexec" : config_file_name,          parse_server_config(&options, rexeced_flag ? "rexec" : config_file_name,
             &cfg, NULL, NULL, NULL);              &cfg, NULL);
   
         /* 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 1555  main(int ac, char **av)
Line 1524  main(int ac, char **av)
         if (options.challenge_response_authentication)          if (options.challenge_response_authentication)
                 options.kbd_interactive_authentication = 1;                  options.kbd_interactive_authentication = 1;
   
           /* Check that options are sensible */
           if (options.authorized_keys_command_user == NULL &&
               (options.authorized_keys_command != NULL &&
               strcasecmp(options.authorized_keys_command, "none") != 0))
                   fatal("AuthorizedKeysCommand set without "
                       "AuthorizedKeysCommandUser");
           if (options.authorized_principals_command_user == NULL &&
               (options.authorized_principals_command != NULL &&
               strcasecmp(options.authorized_principals_command, "none") != 0))
                   fatal("AuthorizedPrincipalsCommand set without "
                       "AuthorizedPrincipalsCommandUser");
   
           /*
            * Check whether there is any path through configured auth methods.
            * Unfortunately it is not possible to verify this generally before
            * daemonisation in the presence of Match block, but this catches
            * and warns for trivial misconfigurations that could break login.
            */
           if (options.num_auth_methods != 0) {
                   for (n = 0; n < options.num_auth_methods; n++) {
                           if (auth2_methods_valid(options.auth_methods[n],
                               1) == 0)
                                   break;
                   }
                   if (n >= options.num_auth_methods)
                           fatal("AuthenticationMethods cannot be satisfied by "
                               "enabled authentication methods");
           }
   
         /* set default channel AF */          /* set default channel AF */
         channel_set_af(options.address_family);          channel_set_af(options.address_family);
   
Line 1565  main(int ac, char **av)
Line 1563  main(int ac, char **av)
         }          }
   
 #ifdef WITH_LDAP_PUBKEY  #ifdef WITH_LDAP_PUBKEY
     /* ldap_options_print(&options.lpk); */          /* ldap_options_print(&options.lpk); */
     /* XXX initialize/check ldap connection and set *LD */          /* XXX initialize/check ldap connection and set *LD */
     if (options.lpk.on) {          if (options.lpk.on) {
         if (options.lpk.l_conf && (ldap_parse_lconf(&options.lpk) < 0) )              if (options.lpk.l_conf && (ldap_parse_lconf(&options.lpk) < 0) )
             error("[LDAP] could not parse %s", options.lpk.l_conf);                  error("[LDAP] could not parse %s", options.lpk.l_conf);
         if (ldap_connect(&options.lpk) < 0)              if (ldap_connect(&options.lpk) < 0)
             error("[LDAP] could not initialize ldap connection");                  error("[LDAP] could not initialize ldap connection");
     }          }
 #endif  #endif
         debug("sshd version %.100s", SSH_VERSION);          debug("sshd version %s, %s", SSH_VERSION,
   #ifdef WITH_OPENSSL
         /* load private host keys */              SSLeay_version(SSLEAY_VERSION)
   #else
               "without OpenSSL"
   #endif
           );
   
           /* load host keys */
         sensitive_data.host_keys = xcalloc(options.num_host_key_files,          sensitive_data.host_keys = xcalloc(options.num_host_key_files,
             sizeof(Key *));              sizeof(Key *));
         for (i = 0; i < options.num_host_key_files; i++)          sensitive_data.host_pubkeys = xcalloc(options.num_host_key_files,
                 sensitive_data.host_keys[i] = NULL;              sizeof(Key *));
   
           if (options.host_key_agent) {
                   if (strcmp(options.host_key_agent, SSH_AUTHSOCKET_ENV_NAME))
                           setenv(SSH_AUTHSOCKET_ENV_NAME,
                               options.host_key_agent, 1);
                   if ((r = ssh_get_authentication_socket(NULL)) == 0)
                           have_agent = 1;
                   else
                           error("Could not connect to agent \"%s\": %s",
                               options.host_key_agent, ssh_err(r));
           }
   
         for (i = 0; i < options.num_host_key_files; i++) {          for (i = 0; i < options.num_host_key_files; i++) {
                   if (options.host_key_files[i] == NULL)
                           continue;
                 key = key_load_private(options.host_key_files[i], "", NULL);                  key = key_load_private(options.host_key_files[i], "", NULL);
                   pubkey = key_load_public(options.host_key_files[i], NULL);
   
                   if ((pubkey != NULL && pubkey->type == KEY_RSA1) ||
                       (key != NULL && key->type == KEY_RSA1)) {
                           verbose("Ignoring RSA1 key %s",
                               options.host_key_files[i]);
                           key_free(key);
                           key_free(pubkey);
                           continue;
                   }
                   if (pubkey == NULL && key != NULL)
                           pubkey = key_demote(key);
                 sensitive_data.host_keys[i] = key;                  sensitive_data.host_keys[i] = key;
                 if (key == NULL) {                  sensitive_data.host_pubkeys[i] = pubkey;
   
                   if (key == NULL && pubkey != NULL && have_agent) {
                           debug("will rely on agent for hostkey %s",
                               options.host_key_files[i]);
                           keytype = pubkey->type;
                   } else if (key != NULL) {
                           keytype = key->type;
                   } else {
                         error("Could not load host key: %s",                          error("Could not load host key: %s",
                             options.host_key_files[i]);                              options.host_key_files[i]);
                         sensitive_data.host_keys[i] = NULL;                          sensitive_data.host_keys[i] = NULL;
                           sensitive_data.host_pubkeys[i] = NULL;
                         continue;                          continue;
                 }                  }
                 switch (key->type) {  
                 case KEY_RSA1:                  switch (keytype) {
                         sensitive_data.ssh1_host_key = key;  
                         sensitive_data.have_ssh1_key = 1;  
                         break;  
                 case KEY_RSA:                  case KEY_RSA:
                 case KEY_DSA:                  case KEY_DSA:
                 case KEY_ECDSA:                  case KEY_ECDSA:
                         sensitive_data.have_ssh2_key = 1;                  case KEY_ED25519:
                           if (have_agent || key != NULL)
                                   sensitive_data.have_ssh2_key = 1;
                         break;                          break;
                 }                  }
                 debug("private host key: #%d type %d %s", i, key->type,                  if ((fp = sshkey_fingerprint(pubkey, options.fingerprint_hash,
                     key_type(key));                      SSH_FP_DEFAULT)) == NULL)
         }                          fatal("sshkey_fingerprint failed");
         if ((options.protocol & SSH_PROTO_1) && !sensitive_data.have_ssh1_key) {                  debug("%s host key #%d: %s %s",
                 logit("Disabling protocol version 1. Could not load host key");                      key ? "private" : "agent", i, sshkey_ssh_name(pubkey), fp);
                 options.protocol &= ~SSH_PROTO_1;                  free(fp);
         }  
         if ((options.protocol & SSH_PROTO_2) && !sensitive_data.have_ssh2_key) {  
                 logit("Disabling protocol version 2. Could not load host key");  
                 options.protocol &= ~SSH_PROTO_2;  
         }          }
         if (!(options.protocol & (SSH_PROTO_1|SSH_PROTO_2))) {          if (!sensitive_data.have_ssh2_key) {
                 logit("sshd: no hostkeys available -- exiting.");                  logit("sshd: no hostkeys available -- exiting.");
                 exit(1);                  exit(1);
         }          }
Line 1628  main(int ac, char **av)
Line 1661  main(int ac, char **av)
                 sensitive_data.host_certificates[i] = NULL;                  sensitive_data.host_certificates[i] = NULL;
   
         for (i = 0; i < options.num_host_cert_files; i++) {          for (i = 0; i < options.num_host_cert_files; i++) {
                   if (options.host_cert_files[i] == NULL)
                           continue;
                 key = key_load_public(options.host_cert_files[i], NULL);                  key = key_load_public(options.host_cert_files[i], NULL);
                 if (key == NULL) {                  if (key == NULL) {
                         error("Could not load host certificate: %s",                          error("Could not load host certificate: %s",
Line 1658  main(int ac, char **av)
Line 1693  main(int ac, char **av)
                 debug("host certificate: #%d type %d %s", j, key->type,                  debug("host certificate: #%d type %d %s", j, key->type,
                     key_type(key));                      key_type(key));
         }          }
         /* Check certain values for sanity. */  
         if (options.protocol & SSH_PROTO_1) {  
                 if (options.server_key_bits < 512 ||  
                     options.server_key_bits > 32768) {  
                         fprintf(stderr, "Bad server key size.\n");  
                         exit(1);  
                 }  
                 /*  
                  * Check that server and host key lengths differ sufficiently. This  
                  * is necessary to make double encryption work with rsaref. Oh, I  
                  * hate software patents. I dont know if this can go? Niels  
                  */  
                 if (options.server_key_bits >  
                     BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) -  
                     SSH_KEY_BITS_RESERVED && options.server_key_bits <  
                     BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) +  
                     SSH_KEY_BITS_RESERVED) {  
                         options.server_key_bits =  
                             BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) +  
                             SSH_KEY_BITS_RESERVED;  
                         debug("Forcing server key to %d bits to make it differ from host key.",  
                             options.server_key_bits);  
                 }  
         }  
   
         if (use_privsep) {          if (use_privsep) {
                 struct stat st;                  struct stat st;
Line 1699  main(int ac, char **av)
Line 1710  main(int ac, char **av)
         }          }
   
         if (test_flag > 1) {          if (test_flag > 1) {
                 if (test_user != NULL && test_addr != NULL && test_host != NULL)                  if (server_match_spec_complete(connection_info) == 1)
                         parse_server_match_config(&options, test_user,                          parse_server_match_config(&options, connection_info);
                             test_host, test_addr);  
                 dump_config(&options);                  dump_config(&options);
         }          }
   
Line 1729  main(int ac, char **av)
Line 1739  main(int ac, char **av)
         log_init(__progname, options.log_level, options.log_facility, log_stderr);          log_init(__progname, options.log_level, options.log_facility, log_stderr);
   
         /*          /*
          * If not in debugging mode, and not started from inetd, disconnect           * If not in debugging mode, not started from inetd and not already
          * from the controlling terminal, and fork.  The original process           * daemonized (eg re-exec via SIGHUP), disconnect from the controlling
          * exits.           * terminal, and fork.  The original process exits.
          */           */
         if (!(debug_flag || inetd_flag || no_daemon_flag)) {          already_daemon = daemonized();
                 int fd;          if (!(debug_flag || inetd_flag || no_daemon_flag || already_daemon)) {
   
                 if (daemon(0, 0) < 0)                  if (daemon(0, 0) < 0)
                         fatal("daemon() failed: %.200s", strerror(errno));                          fatal("daemon() failed: %.200s", strerror(errno));
   
                 /* Disconnect from the controlling tty. */                  disconnect_controlling_tty();
                 fd = open(_PATH_TTY, O_RDWR | O_NOCTTY);  
                 if (fd >= 0) {  
                         (void) ioctl(fd, TIOCNOTTY, NULL);  
                         close(fd);  
                 }  
         }          }
         /* Reinitialize the log (because of the fork above). */          /* Reinitialize the log (because of the fork above). */
         log_init(__progname, options.log_level, options.log_facility, log_stderr);          log_init(__progname, options.log_level, options.log_facility, log_stderr);
   
         /* Initialize the fast random number generator. */  
         arc4random_stir();  
   
         /* Chdir to the root directory so that the current disk can be          /* Chdir to the root directory so that the current disk can be
            unmounted if desired. */             unmounted if desired. */
         chdir("/");          if (chdir("/") == -1)
                   error("chdir(\"/\"): %s", strerror(errno));
   
         /* ignore SIGPIPE */          /* ignore SIGPIPE */
         signal(SIGPIPE, SIG_IGN);          signal(SIGPIPE, SIG_IGN);
Line 1765  main(int ac, char **av)
Line 1768  main(int ac, char **av)
         } else {          } else {
                 server_listen();                  server_listen();
   
                 if (options.protocol & SSH_PROTO_1)  
                         generate_ephemeral_server_key();  
   
                 signal(SIGHUP, sighup_handler);                  signal(SIGHUP, sighup_handler);
                 signal(SIGCHLD, main_sigchld_handler);                  signal(SIGCHLD, main_sigchld_handler);
                 signal(SIGTERM, sigterm_handler);                  signal(SIGTERM, sigterm_handler);
Line 1777  main(int ac, char **av)
Line 1777  main(int ac, char **av)
                  * Write out the pid file after the sigterm handler                   * Write out the pid file after the sigterm handler
                  * is setup and the listen sockets are bound                   * is setup and the listen sockets are bound
                  */                   */
                 if (!debug_flag) {                  if (options.pid_file != NULL && !debug_flag) {
                         FILE *f = fopen(options.pid_file, "w");                          FILE *f = fopen(options.pid_file, "w");
   
                         if (f == NULL) {                          if (f == NULL) {
Line 1814  main(int ac, char **av)
Line 1814  main(int ac, char **av)
                 dup2(STDIN_FILENO, STDOUT_FILENO);                  dup2(STDIN_FILENO, STDOUT_FILENO);
                 if (startup_pipe == -1)                  if (startup_pipe == -1)
                         close(REEXEC_STARTUP_PIPE_FD);                          close(REEXEC_STARTUP_PIPE_FD);
                 else                  else if (startup_pipe != REEXEC_STARTUP_PIPE_FD) {
                         dup2(startup_pipe, REEXEC_STARTUP_PIPE_FD);                          dup2(startup_pipe, REEXEC_STARTUP_PIPE_FD);
                           close(startup_pipe);
                           startup_pipe = REEXEC_STARTUP_PIPE_FD;
                   }
   
                 dup2(config_s[1], REEXEC_CONFIG_PASS_FD);                  dup2(config_s[1], REEXEC_CONFIG_PASS_FD);
                 close(config_s[1]);                  close(config_s[1]);
                 if (startup_pipe != -1)  
                         close(startup_pipe);  
   
                 execv(rexec_argv[0], rexec_argv);                  execv(rexec_argv[0], rexec_argv);
   
Line 1831  main(int ac, char **av)
Line 1832  main(int ac, char **av)
                     options.log_facility, log_stderr);                      options.log_facility, log_stderr);
   
                 /* Clean up fds */                  /* Clean up fds */
                 startup_pipe = REEXEC_STARTUP_PIPE_FD;  
                 close(config_s[1]);  
                 close(REEXEC_CONFIG_PASS_FD);                  close(REEXEC_CONFIG_PASS_FD);
                 newsock = sock_out = sock_in = dup(STDIN_FILENO);                  newsock = sock_out = sock_in = dup(STDIN_FILENO);
                 if ((fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {                  if ((fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {
Line 1867  main(int ac, char **av)
Line 1866  main(int ac, char **av)
          */           */
         packet_set_connection(sock_in, sock_out);          packet_set_connection(sock_in, sock_out);
         packet_set_server();          packet_set_server();
           ssh = active_state; /* XXX */
           check_ip_options(ssh);
   
         /* Set SO_KEEPALIVE if requested. */          /* Set SO_KEEPALIVE if requested. */
         if (options.tcp_keep_alive && packet_connection_is_on_socket() &&          if (options.tcp_keep_alive && packet_connection_is_on_socket() &&
             setsockopt(sock_in, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)) < 0)              setsockopt(sock_in, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)) < 0)
                 error("setsockopt SO_KEEPALIVE: %.100s", strerror(errno));                  error("setsockopt SO_KEEPALIVE: %.100s", strerror(errno));
   
         if ((remote_port = get_remote_port()) < 0) {          if ((remote_port = ssh_remote_port(ssh)) < 0) {
                 debug("get_remote_port failed");                  debug("ssh_remote_port failed");
                 cleanup_exit(255);                  cleanup_exit(255);
         }          }
   
         /*          /*
          * We use get_canonical_hostname with usedns = 0 instead of  
          * get_remote_ipaddr here so IP options will be checked.  
          */  
         (void) get_canonical_hostname(0);  
         /*  
          * The rest of the code depends on the fact that           * The rest of the code depends on the fact that
          * get_remote_ipaddr() caches the remote ip, even if           * ssh_remote_ipaddr() caches the remote ip, even if
          * the socket goes away.           * the socket goes away.
          */           */
         remote_ip = get_remote_ipaddr();          remote_ip = ssh_remote_ipaddr(ssh);
   
 #ifdef LIBWRAP  #ifdef LIBWRAP
         /* Check whether logins are denied from this host. */          /* Check whether logins are denied from this host. */
Line 1908  main(int ac, char **av)
Line 1904  main(int ac, char **av)
 #endif /* LIBWRAP */  #endif /* LIBWRAP */
   
         /* Log the connection. */          /* Log the connection. */
         verbose("Connection from %.500s port %d", remote_ip, remote_port);          laddr = get_local_ipaddr(sock_in);
           verbose("Connection from %s port %d on %s port %d",
               remote_ip, remote_port, laddr,  ssh_local_port(ssh));
           free(laddr);
   
         /* set the HPN options for the child */          /* set the HPN options for the child */
         channel_set_hpn(options.hpn_disabled, options.hpn_buffer_size);          channel_set_hpn(options.hpn_disabled, options.hpn_buffer_size);
Line 1925  main(int ac, char **av)
Line 1924  main(int ac, char **av)
         if (!debug_flag)          if (!debug_flag)
                 alarm(options.login_grace_time);                  alarm(options.login_grace_time);
   
         sshd_exchange_identification(sock_in, sock_out);          sshd_exchange_identification(ssh, sock_in, sock_out);
   
         /* In inetd mode, generate ephemeral key only for proto 1 connections */  
         if (!compat20 && inetd_flag && sensitive_data.server_key == NULL)  
                 generate_ephemeral_server_key();  
   
         packet_set_nonblocking();          packet_set_nonblocking();
   
         /* allocate authentication context */          /* allocate authentication context */
Line 1943  main(int ac, char **av)
Line 1937  main(int ac, char **av)
         buffer_init(&loginmsg);          buffer_init(&loginmsg);
         auth_debug_reset();          auth_debug_reset();
   
         if (use_privsep)          if (use_privsep) {
                 if (privsep_preauth(authctxt) == 1)                  if (privsep_preauth(authctxt) == 1)
                         goto authenticated;                          goto authenticated;
           } else if (have_agent) {
                   if ((r = ssh_get_authentication_socket(&auth_sock)) != 0) {
                           error("Unable to get agent socket: %s", ssh_err(r));
                           have_agent = 0;
                   }
           }
   
         /* perform the key exchange */          /* perform the key exchange */
         /* authenticate user and start session */          /* authenticate user and start session */
         if (compat20) {          do_ssh2_kex();
                 do_ssh2_kex();          do_authentication2(authctxt);
                 do_authentication2(authctxt);  
         } else {  
                 do_ssh1_kex();  
                 do_authentication(authctxt);  
         }  
         /*          /*
          * If we use privilege separation, the unprivileged child transfers           * If we use privilege separation, the unprivileged child transfers
          * the current keystate and exits           * the current keystate and exits
Line 1992  main(int ac, char **av)
Line 1988  main(int ac, char **av)
         if (use_privsep) {          if (use_privsep) {
                 privsep_postauth(authctxt);                  privsep_postauth(authctxt);
                 /* the monitor process [priv] will not return */                  /* the monitor process [priv] will not return */
                 if (!compat20)  
                         destroy_sensitive_data();  
         }          }
   
         packet_set_timeout(options.client_alive_interval,          packet_set_timeout(options.client_alive_interval,
             options.client_alive_count_max);              options.client_alive_count_max);
   
           /* Try to send all our hostkeys to the client */
           notify_hostkeys(active_state);
   
         /* Start session. */          /* Start session. */
         do_authenticated(authctxt);          do_authenticated(authctxt);
   
Line 2008  main(int ac, char **av)
Line 2005  main(int ac, char **av)
 #endif /* USE_PAM */  #endif /* USE_PAM */
   
         /* The connection has been terminated. */          /* The connection has been terminated. */
         packet_get_state(MODE_IN, NULL, NULL, NULL, &ibytes);          packet_get_bytes(&ibytes, &obytes);
         packet_get_state(MODE_OUT, NULL, NULL, NULL, &obytes);  
         verbose("Transferred: sent %llu, received %llu bytes",          verbose("Transferred: sent %llu, received %llu bytes",
             (unsigned long long)obytes, (unsigned long long)ibytes);              (unsigned long long)obytes, (unsigned long long)ibytes);
   
Line 2022  main(int ac, char **av)
Line 2018  main(int ac, char **av)
         exit(0);          exit(0);
 }  }
   
 /*  
  * Decrypt session_key_int using our private server key and private host key  
  * (key with larger modulus first).  
  */  
 int  int
 ssh1_session_key(BIGNUM *session_key_int)  sshd_hostkey_sign(Key *privkey, Key *pubkey, u_char **signature, size_t *slen,
       const u_char *data, size_t dlen, const char *alg, u_int flag)
 {  {
         int rsafail = 0;          int r;
           u_int xxx_slen, xxx_dlen = dlen;
   
         if (BN_cmp(sensitive_data.server_key->rsa->n,          if (privkey) {
             sensitive_data.ssh1_host_key->rsa->n) > 0) {                  if (PRIVSEP(key_sign(privkey, signature, &xxx_slen, data, xxx_dlen,
                 /* Server key has bigger modulus. */                      alg) < 0))
                 if (BN_num_bits(sensitive_data.server_key->rsa->n) <                          fatal("%s: key_sign failed", __func__);
                     BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) +                  if (slen)
                     SSH_KEY_BITS_RESERVED) {                          *slen = xxx_slen;
                         fatal("do_connection: %s: "          } else if (use_privsep) {
                             "server_key %d < host_key %d + SSH_KEY_BITS_RESERVED %d",                  if (mm_key_sign(pubkey, signature, &xxx_slen, data, xxx_dlen,
                             get_remote_ipaddr(),                      alg) < 0)
                             BN_num_bits(sensitive_data.server_key->rsa->n),                          fatal("%s: pubkey_sign failed", __func__);
                             BN_num_bits(sensitive_data.ssh1_host_key->rsa->n),                  if (slen)
                             SSH_KEY_BITS_RESERVED);                          *slen = xxx_slen;
                 }  
                 if (rsa_private_decrypt(session_key_int, session_key_int,  
                     sensitive_data.server_key->rsa) <= 0)  
                         rsafail++;  
                 if (rsa_private_decrypt(session_key_int, session_key_int,  
                     sensitive_data.ssh1_host_key->rsa) <= 0)  
                         rsafail++;  
         } else {          } else {
                 /* Host key has bigger modulus (or they are equal). */                  if ((r = ssh_agent_sign(auth_sock, pubkey, signature, slen,
                 if (BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) <                      data, dlen, alg, datafellows)) != 0)
                     BN_num_bits(sensitive_data.server_key->rsa->n) +                          fatal("%s: ssh_agent_sign failed: %s",
                     SSH_KEY_BITS_RESERVED) {                              __func__, ssh_err(r));
                         fatal("do_connection: %s: "  
                             "host_key %d < server_key %d + SSH_KEY_BITS_RESERVED %d",  
                             get_remote_ipaddr(),  
                             BN_num_bits(sensitive_data.ssh1_host_key->rsa->n),  
                             BN_num_bits(sensitive_data.server_key->rsa->n),  
                             SSH_KEY_BITS_RESERVED);  
                 }  
                 if (rsa_private_decrypt(session_key_int, session_key_int,  
                     sensitive_data.ssh1_host_key->rsa) < 0)  
                         rsafail++;  
                 if (rsa_private_decrypt(session_key_int, session_key_int,  
                     sensitive_data.server_key->rsa) < 0)  
                         rsafail++;  
         }          }
         return (rsafail);          return 0;
 }  }
 /*  
  * SSH1 key exchange  
  */  
 static void  
 do_ssh1_kex(void)  
 {  
         int i, len;  
         int rsafail = 0;  
         BIGNUM *session_key_int;  
         u_char session_key[SSH_SESSION_KEY_LENGTH];  
         u_char cookie[8];  
         u_int cipher_type, auth_mask, protocol_flags;  
   
         /*  
          * Generate check bytes that the client must send back in the user  
          * packet in order for it to be accepted; this is used to defy ip  
          * spoofing attacks.  Note that this only works against somebody  
          * doing IP spoofing from a remote machine; any machine on the local  
          * network can still see outgoing packets and catch the random  
          * cookie.  This only affects rhosts authentication, and this is one  
          * of the reasons why it is inherently insecure.  
          */  
         arc4random_buf(cookie, sizeof(cookie));  
   
         /*  /* SSH2 key exchange */
          * Send our public key.  We include in the packet 64 bits of random  
          * data that must be matched in the reply in order to prevent IP  
          * spoofing.  
          */  
         packet_start(SSH_SMSG_PUBLIC_KEY);  
         for (i = 0; i < 8; i++)  
                 packet_put_char(cookie[i]);  
   
         /* Store our public server RSA key. */  
         packet_put_int(BN_num_bits(sensitive_data.server_key->rsa->n));  
         packet_put_bignum(sensitive_data.server_key->rsa->e);  
         packet_put_bignum(sensitive_data.server_key->rsa->n);  
   
         /* Store our public host RSA key. */  
         packet_put_int(BN_num_bits(sensitive_data.ssh1_host_key->rsa->n));  
         packet_put_bignum(sensitive_data.ssh1_host_key->rsa->e);  
         packet_put_bignum(sensitive_data.ssh1_host_key->rsa->n);  
   
         /* Put protocol flags. */  
         packet_put_int(SSH_PROTOFLAG_HOST_IN_FWD_OPEN);  
   
         /* Declare which ciphers we support. */  
         packet_put_int(cipher_mask_ssh1(0));  
   
         /* Declare supported authentication types. */  
         auth_mask = 0;  
         if (options.rhosts_rsa_authentication)  
                 auth_mask |= 1 << SSH_AUTH_RHOSTS_RSA;  
         if (options.rsa_authentication)  
                 auth_mask |= 1 << SSH_AUTH_RSA;  
 #if defined(KRB4) || defined(KRB5)  
         if (options.kerberos_authentication)  
                 auth_mask |= 1 << SSH_AUTH_KERBEROS;  
 #endif  
 #if defined(AFS) || defined(KRB5)  
         if (options.kerberos_tgt_passing)  
                 auth_mask |= 1 << SSH_PASS_KERBEROS_TGT;  
 #endif  
 #ifdef AFS  
         if (options.afs_token_passing)  
                 auth_mask |= 1 << SSH_PASS_AFS_TOKEN;  
 #endif  
         if (options.challenge_response_authentication == 1)  
                 auth_mask |= 1 << SSH_AUTH_TIS;  
         if (options.password_authentication)  
                 auth_mask |= 1 << SSH_AUTH_PASSWORD;  
         packet_put_int(auth_mask);  
   
         /* Send the packet and wait for it to be sent. */  
         packet_send();  
         packet_write_wait();  
   
         debug("Sent %d bit server key and %d bit host key.",  
             BN_num_bits(sensitive_data.server_key->rsa->n),  
             BN_num_bits(sensitive_data.ssh1_host_key->rsa->n));  
   
         /* Read clients reply (cipher type and session key). */  
         packet_read_expect(SSH_CMSG_SESSION_KEY);  
   
         /* Get cipher type and check whether we accept this. */  
         cipher_type = packet_get_char();  
   
         if (!(cipher_mask_ssh1(0) & (1 << cipher_type)))  
                 packet_disconnect("Warning: client selects unsupported cipher.");  
   
         /* Get check bytes from the packet.  These must match those we  
            sent earlier with the public key packet. */  
         for (i = 0; i < 8; i++)  
                 if (cookie[i] != packet_get_char())  
                         packet_disconnect("IP Spoofing check bytes do not match.");  
   
         debug("Encryption type: %.200s", cipher_name(cipher_type));  
   
         /* Get the encrypted integer. */  
         if ((session_key_int = BN_new()) == NULL)  
                 fatal("do_ssh1_kex: BN_new failed");  
         packet_get_bignum(session_key_int);  
   
         protocol_flags = packet_get_int();  
         packet_set_protocol_flags(protocol_flags);  
         packet_check_eom();  
   
         /* Decrypt session_key_int using host/server keys */  
         rsafail = PRIVSEP(ssh1_session_key(session_key_int));  
   
         /*  
          * Extract session key from the decrypted integer.  The key is in the  
          * least significant 256 bits of the integer; the first byte of the  
          * key is in the highest bits.  
          */  
         if (!rsafail) {  
                 (void) BN_mask_bits(session_key_int, sizeof(session_key) * 8);  
                 len = BN_num_bytes(session_key_int);  
                 if (len < 0 || (u_int)len > sizeof(session_key)) {  
                         error("do_ssh1_kex: bad session key len from %s: "  
                             "session_key_int %d > sizeof(session_key) %lu",  
                             get_remote_ipaddr(), len, (u_long)sizeof(session_key));  
                         rsafail++;  
                 } else {  
                         memset(session_key, 0, sizeof(session_key));  
                         BN_bn2bin(session_key_int,  
                             session_key + sizeof(session_key) - len);  
   
                         derive_ssh1_session_id(  
                             sensitive_data.ssh1_host_key->rsa->n,  
                             sensitive_data.server_key->rsa->n,  
                             cookie, session_id);  
                         /*  
                          * Xor the first 16 bytes of the session key with the  
                          * session id.  
                          */  
                         for (i = 0; i < 16; i++)  
                                 session_key[i] ^= session_id[i];  
                 }  
         }  
         if (rsafail) {  
                 int bytes = BN_num_bytes(session_key_int);  
                 u_char *buf = xmalloc(bytes);  
                 MD5_CTX md;  
   
                 logit("do_connection: generating a fake encryption key");  
                 BN_bn2bin(session_key_int, buf);  
                 MD5_Init(&md);  
                 MD5_Update(&md, buf, bytes);  
                 MD5_Update(&md, sensitive_data.ssh1_cookie, SSH_SESSION_KEY_LENGTH);  
                 MD5_Final(session_key, &md);  
                 MD5_Init(&md);  
                 MD5_Update(&md, session_key, 16);  
                 MD5_Update(&md, buf, bytes);  
                 MD5_Update(&md, sensitive_data.ssh1_cookie, SSH_SESSION_KEY_LENGTH);  
                 MD5_Final(session_key + 16, &md);  
                 memset(buf, 0, bytes);  
                 xfree(buf);  
                 for (i = 0; i < 16; i++)  
                         session_id[i] = session_key[i] ^ session_key[i + 16];  
         }  
         /* Destroy the private and public keys. No longer. */  
         destroy_sensitive_data();  
   
         if (use_privsep)  
                 mm_ssh1_session_id(session_id);  
   
         /* Destroy the decrypted integer.  It is no longer needed. */  
         BN_clear_free(session_key_int);  
   
         /* Set the session key.  From this on all communications will be encrypted. */  
         packet_set_encryption_key(session_key, SSH_SESSION_KEY_LENGTH, cipher_type);  
   
         /* Destroy our copy of the session key.  It is no longer needed. */  
         memset(session_key, 0, sizeof(session_key));  
   
         debug("Received session key; encryption turned on.");  
   
         /* Send an acknowledgment packet.  Note that this packet is sent encrypted. */  
         packet_start(SSH_SMSG_SUCCESS);  
         packet_send();  
         packet_write_wait();  
 }  
   
 /*  
  * SSH2 key exchange: diffie-hellman-group1-sha1  
  */  
 static void  static void
 do_ssh2_kex(void)  do_ssh2_kex(void)
 {  {
         Kex *kex;          const char *myproposal[PROPOSAL_MAX] = { KEX_SERVER };
           struct kex *kex;
           int r;
   
         myflag++;          myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal(
         debug ("MYFLAG IS %d", myflag);              options.kex_algorithms);
         if (options.ciphers != NULL) {  
                 myproposal[PROPOSAL_ENC_ALGS_CTOS] =          if (strcmp(options.ciphers, KEX_SERVER_ENCRYPT) == 0 &&
                 myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers;              options.none_enabled == 1) {
         } else if (options.none_enabled == 1) {  
                 debug ("WARNING: None cipher enabled");                  debug ("WARNING: None cipher enabled");
                 myproposal[PROPOSAL_ENC_ALGS_CTOS] =                  myproposal[PROPOSAL_ENC_ALGS_CTOS] =
                 myproposal[PROPOSAL_ENC_ALGS_STOC] = KEX_ENCRYPT_INCLUDE_NONE;                  myproposal[PROPOSAL_ENC_ALGS_STOC] = KEX_SERVER_ENCRYPT_INCLUDE_NONE;
           } else {
                   myproposal[PROPOSAL_ENC_ALGS_CTOS] =
                   myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers;
         }          }
   
         myproposal[PROPOSAL_ENC_ALGS_CTOS] =          myproposal[PROPOSAL_ENC_ALGS_CTOS] =
             compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_CTOS]);              compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_CTOS]);
         myproposal[PROPOSAL_ENC_ALGS_STOC] =          myproposal[PROPOSAL_ENC_ALGS_STOC] =
             compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_STOC]);              compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_STOC]);
   
         if (options.macs != NULL) {          myproposal[PROPOSAL_MAC_ALGS_CTOS] =
                 myproposal[PROPOSAL_MAC_ALGS_CTOS] =              myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs;
                 myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs;  
         }  
         if (options.compression == COMP_NONE) {          if (options.compression == COMP_NONE) {
                 myproposal[PROPOSAL_COMP_ALGS_CTOS] =                  myproposal[PROPOSAL_COMP_ALGS_CTOS] =
                 myproposal[PROPOSAL_COMP_ALGS_STOC] = "none";                      myproposal[PROPOSAL_COMP_ALGS_STOC] = "none";
         } else if (options.compression == COMP_DELAYED) {  
                 myproposal[PROPOSAL_COMP_ALGS_CTOS] =  
                 myproposal[PROPOSAL_COMP_ALGS_STOC] = "none,zlib@openssh.com";  
         }          }
         if (options.kex_algorithms != NULL)  
                 myproposal[PROPOSAL_KEX_ALGS] = options.kex_algorithms;  
   
         myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = list_hostkey_types();          if (options.rekey_limit || options.rekey_interval)
                   packet_set_rekey_limits(options.rekey_limit,
                       options.rekey_interval);
   
           myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = compat_pkalg_proposal(
               list_hostkey_types());
   
         /* start key exchange */          /* start key exchange */
         kex = kex_setup(myproposal);          if ((r = kex_setup(active_state, myproposal)) != 0)
                   fatal("kex_setup: %s", ssh_err(r));
           kex = active_state->kex;
   #ifdef WITH_OPENSSL
         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_GRP14_SHA1] = kexdh_server;
           kex->kex[KEX_DH_GRP14_SHA256] = kexdh_server;
           kex->kex[KEX_DH_GRP16_SHA512] = kexdh_server;
           kex->kex[KEX_DH_GRP18_SHA512] = kexdh_server;
         kex->kex[KEX_DH_GEX_SHA1] = kexgex_server;          kex->kex[KEX_DH_GEX_SHA1] = kexgex_server;
         kex->kex[KEX_DH_GEX_SHA256] = kexgex_server;          kex->kex[KEX_DH_GEX_SHA256] = kexgex_server;
         kex->kex[KEX_ECDH_SHA2] = kexecdh_server;          kex->kex[KEX_ECDH_SHA2] = kexecdh_server;
   #endif
           kex->kex[KEX_C25519_SHA256] = kexc25519_server;
         kex->server = 1;          kex->server = 1;
         kex->client_version_string=client_version_string;          kex->client_version_string=client_version_string;
         kex->server_version_string=server_version_string;          kex->server_version_string=server_version_string;
         kex->load_host_public_key=&get_hostkey_public_by_type;          kex->load_host_public_key=&get_hostkey_public_by_type;
         kex->load_host_private_key=&get_hostkey_private_by_type;          kex->load_host_private_key=&get_hostkey_private_by_type;
         kex->host_key_index=&get_hostkey_index;          kex->host_key_index=&get_hostkey_index;
           kex->sign = sshd_hostkey_sign;
   
         xxx_kex = kex;          dispatch_run(DISPATCH_BLOCK, &kex->done, active_state);
   
         dispatch_run(DISPATCH_BLOCK, &kex->done, kex);  
   
         session_id2 = kex->session_id;          session_id2 = kex->session_id;
         session_id2_len = kex->session_id_len;          session_id2_len = kex->session_id_len;
Line 2329  do_ssh2_kex(void)
Line 2129  do_ssh2_kex(void)
 void  void
 cleanup_exit(int i)  cleanup_exit(int i)
 {  {
         if (the_authctxt)          if (the_authctxt) {
                 do_cleanup(the_authctxt);                  do_cleanup(the_authctxt);
                   if (use_privsep && privsep_is_preauth &&
                       pmonitor != NULL && pmonitor->m_pid > 1) {
                           debug("Killing privsep child %d", pmonitor->m_pid);
                           if (kill(pmonitor->m_pid, SIGKILL) != 0 &&
                               errno != ESRCH)
                                   error("%s: kill(%d): %s", __func__,
                                       pmonitor->m_pid, strerror(errno));
                   }
           }
         _exit(i);          _exit(i);
 }  }

Legend:
Removed from v.1.8.4.1  
changed lines
  Added in v.1.8.4.2

CVSweb <webmaster@jp.NetBSD.org>