]> andersk Git - openssh.git/blobdiff - sshd.c
- deraadt@cvs.openbsd.org 2001/02/04 16:56:23
[openssh.git] / sshd.c
diff --git a/sshd.c b/sshd.c
index 4a01ebec7e485583cafb8c68e40644e7a768bb66..e329112992a418caf50f3e90beb6ec2fa97ab49c 100644 (file)
--- a/sshd.c
+++ b/sshd.c
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: sshd.c,v 1.135 2000/11/29 21:11:59 markus Exp $");
+RCSID("$OpenBSD: sshd.c,v 1.163 2001/02/04 23:56:23 deraadt Exp $");
 
+#include <openssl/dh.h>
+#include <openssl/bn.h>
+#include <openssl/hmac.h>
+
+#include "ssh.h"
+#include "ssh1.h"
+#include "ssh2.h"
 #include "xmalloc.h"
 #include "rsa.h"
-#include "ssh.h"
 #include "pty.h"
 #include "packet.h"
 #include "mpaux.h"
+#include "log.h"
 #include "servconf.h"
 #include "uidswap.h"
 #include "compat.h"
 #include "buffer.h"
-
-#include "ssh2.h"
-#include <openssl/dh.h>
-#include <openssl/bn.h>
-#include <openssl/hmac.h>
+#include "cipher.h"
 #include "kex.h"
-#include <openssl/dsa.h>
-#include <openssl/rsa.h>
 #include "key.h"
 #include "dh.h"
-
-#include "auth.h"
 #include "myproposal.h"
 #include "authfile.h"
+#include "pathnames.h"
+#include "atomicio.h"
+#include "canohost.h"
+#include "auth.h"
+#include "misc.h"
 
 #ifdef LIBWRAP
 #include <tcpd.h>
@@ -88,7 +92,7 @@ char *__progname;
 ServerOptions options;
 
 /* Name of the server configuration file. */
-char *config_file_name = SERVER_CONFIG_FILE;
+char *config_file_name = _PATH_SERVER_CONFIG_FILE;
 
 /*
  * Flag indicating whether IPv4 or IPv6.  This can be set on the command line.
@@ -117,9 +121,6 @@ int no_daemon_flag = 0;
 /* debug goes to stderr unless inetd_flag is set */
 int log_stderr = 0;
 
-/* argv[0] without path. */
-char *av0;
-
 /* Saved arguments to main(). */
 char **saved_argv;
 int saved_argc;
@@ -156,27 +157,27 @@ struct {
 } sensitive_data;
 
 /*
- * Flag indicating whether the current session key has been used.  This flag
- * is set whenever the key is used, and cleared when the key is regenerated.
+ * Flag indicating whether the RSA server key needs to be regenerated.
+ * Is set in the SIGALRM handler and cleared when the key is regenerated.
  */
-int key_used = 0;
+int key_do_regen = 0;
 
 /* This is set to true when SIGHUP is received. */
 int received_sighup = 0;
 
 /* session identifier, used by RSA-auth */
-unsigned char session_id[16];
+u_char session_id[16];
 
 /* same for ssh2 */
-unsigned char *session_id2 = NULL;
+u_char *session_id2 = NULL;
 int session_id2_len = 0;
 
 /* record remote hostname or ip */
-unsigned int utmp_len = MAXHOSTNAMELEN;
+u_int utmp_len = MAXHOSTNAMELEN;
 
 /* Prototypes for various functions defined later in this file. */
-void do_ssh1_kex();
-void do_ssh2_kex();
+void do_ssh1_kex(void);
+void do_ssh2_kex(void);
 
 void ssh_dh1_server(Kex *, Buffer *_kexinit, Buffer *);
 void ssh_dhgex_server(Kex *, Buffer *_kexinit, Buffer *);
@@ -215,7 +216,7 @@ sighup_restart()
        log("Received SIGHUP; restarting.");
        close_listen_socks();
        execv(saved_argv[0], saved_argv);
-       log("RESTART FAILED: av0='%s', error: %s.", av0, strerror(errno));
+       log("RESTART FAILED: av[0]='%.100s', error: %.100s.", saved_argv[0], strerror(errno));
        exit(1);
 }
 
@@ -270,7 +271,6 @@ grace_alarm_handler(int sig)
  * Thus there should be no concurrency control/asynchronous execution
  * problems.
  */
-/* XXX do we really want this work to be done in a signal handler ? -m */
 void
 generate_empheral_server_key(void)
 {
@@ -282,21 +282,14 @@ generate_empheral_server_key(void)
        arc4random_stir();
        log("RSA key generation complete.");
 }
+
 void
 key_regeneration_alarm(int sig)
 {
        int save_errno = errno;
-
-       /* Check if we should generate a new key. */
-       if (key_used) {
-               /* This should really be done in the background. */
-               generate_empheral_server_key();
-               key_used = 0;
-       }
-       /* Reschedule the alarm. */
-       signal(SIGALRM, key_regeneration_alarm);
-       alarm(options.key_regeneration_time);
+       signal(SIGALRM, SIG_DFL);
        errno = save_errno;
+       key_do_regen = 1;
 }
 
 void
@@ -436,7 +429,7 @@ destroy_sensitive_data(void)
                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]) {
                        key_free(sensitive_data.host_keys[i]);
                        sensitive_data.host_keys[i] = NULL;
@@ -558,7 +551,6 @@ main(int ac, char **av)
        int opt, sock_in = 0, sock_out = 0, newsock, j, i, fdsetsz, on = 1;
        pid_t pid;
        socklen_t fromlen;
-       int silent = 0;
        fd_set *fdset;
        struct sockaddr_storage from;
        const char *remote_ip;
@@ -570,23 +562,20 @@ main(int ac, char **av)
        int listen_sock, maxfd;
        int startup_p[2];
        int startups = 0;
+       int ret, key_used = 0;
 
        __progname = get_progname(av[0]);
        init_rng();
 
-       /* Save argv[0]. */
+       /* Save argv. */
        saved_argc = ac;
        saved_argv = av;
-       if (strchr(av[0], '/'))
-               av0 = strrchr(av[0], '/') + 1;
-       else
-               av0 = av[0];
 
        /* Initialize configuration options to their default values. */
        initialize_server_options(&options);
 
        /* Parse command-line arguments. */
-       while ((opt = getopt(ac, av, "f:p:b:k:h:g:V:u:dDiqQ46")) != EOF) {
+       while ((opt = getopt(ac, av, "f:p:b:k:h:g:V:u:dDiqQ46")) != -1) {
                switch (opt) {
                case '4':
                        IPv4or6 = AF_INET;
@@ -615,7 +604,7 @@ main(int ac, char **av)
                        inetd_flag = 1;
                        break;
                case 'Q':
-                       silent = 1;
+                       /* ignored */
                        break;
                case 'q':
                        options.log_level = SYSLOG_LEVEL_QUIET;
@@ -655,18 +644,19 @@ main(int ac, char **av)
                case '?':
                default:
                        fprintf(stderr, "sshd version %s\n", SSH_VERSION);
-                       fprintf(stderr, "Usage: %s [options]\n", av0);
+                       fprintf(stderr, "Usage: %s [options]\n", __progname);
                        fprintf(stderr, "Options:\n");
-                       fprintf(stderr, "  -f file    Configuration file (default %s)\n", SERVER_CONFIG_FILE);
+                       fprintf(stderr, "  -f file    Configuration file (default %s)\n", _PATH_SERVER_CONFIG_FILE);
                        fprintf(stderr, "  -d         Debugging mode (multiple -d means more debugging)\n");
                        fprintf(stderr, "  -i         Started from inetd\n");
+                       fprintf(stderr, "  -D         Do not fork into daemon mode\n");
                        fprintf(stderr, "  -q         Quiet (no logging)\n");
                        fprintf(stderr, "  -p port    Listen on the specified port (default: 22)\n");
                        fprintf(stderr, "  -k seconds Regenerate server key every this many seconds (default: 3600)\n");
-                       fprintf(stderr, "  -g seconds Grace period for authentication (default: 300)\n");
+                       fprintf(stderr, "  -g seconds Grace period for authentication (default: 600)\n");
                        fprintf(stderr, "  -b bits    Size of server RSA key (default: 768 bits)\n");
                        fprintf(stderr, "  -h file    File from which to read host key (default: %s)\n",
-                           HOST_KEY_FILE);
+                           _PATH_HOST_KEY_FILE);
                        fprintf(stderr, "  -u len     Maximum hostname length for utmp recording\n");
                        fprintf(stderr, "  -4         Use IPv4 only\n");
                        fprintf(stderr, "  -6         Use IPv6 only\n");
@@ -678,10 +668,10 @@ main(int ac, char **av)
         * Force logging to stderr until we have loaded the private host
         * key (unless started from inetd)
         */
-       log_init(av0,
+       log_init(__progname,
            options.log_level == -1 ? SYSLOG_LEVEL_INFO : options.log_level,
            options.log_facility == -1 ? SYSLOG_FACILITY_AUTH : options.log_facility,
-           !silent && !inetd_flag);
+           !inetd_flag);
 
        /* Read server configuration options from the configuration file. */
        read_server_config(&options, config_file_name);
@@ -699,6 +689,8 @@ main(int ac, char **av)
 
        /* load private host keys */
        sensitive_data.host_keys = xmalloc(options.num_host_key_files*sizeof(Key*));
+       for(i = 0; i < options.num_host_key_files; i++)
+               sensitive_data.host_keys[i] = NULL;
        sensitive_data.server_key = NULL;
        sensitive_data.ssh1_host_key = NULL;
        sensitive_data.have_ssh1_key = 0;
@@ -731,9 +723,7 @@ main(int ac, char **av)
                log("Disabling protocol version 2. Could not load host key");
                options.protocol &= ~SSH_PROTO_2;
        }
-       if (! options.protocol & (SSH_PROTO_1|SSH_PROTO_2)) {
-               if (silent == 0)
-                       fprintf(stderr, "sshd: no hostkeys available -- exiting.\n");
+       if (!(options.protocol & (SSH_PROTO_1|SSH_PROTO_2))) {
                log("sshd: no hostkeys available -- exiting.\n");
                exit(1);
        }
@@ -768,7 +758,7 @@ main(int ac, char **av)
        /* Initialize the log (it is reinitialized below in case we forked). */
        if (debug_flag && !inetd_flag)
                log_stderr = 1;
-       log_init(av0, 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
@@ -792,7 +782,7 @@ main(int ac, char **av)
 #endif /* TIOCNOTTY */
        }
        /* Reinitialize the log (because of the fork above). */
-       log_init(av0, options.log_level, options.log_facility, log_stderr);
+       log_init(__progname, options.log_level, options.log_facility, log_stderr);
 
        /* Initialize the random number generator. */
        arc4random_stir();
@@ -881,26 +871,21 @@ main(int ac, char **av)
 
                if (!debug_flag) {
                        /*
-                        * Record our pid in /etc/sshd_pid to make it easier
-                        * to kill the correct sshd.  We don\'t want to do
-                        * this before the bind above because the bind will
+                        * Record our pid in /var/run/sshd.pid to make it
+                        * easier to kill the correct sshd.  We don't want to
+                        * do this before the bind above because the bind will
                         * fail if there already is a daemon, and this will
                         * overwrite any old pid in the file.
                         */
                        f = fopen(options.pid_file, "wb");
                        if (f) {
-                               fprintf(f, "%u\n", (unsigned int) getpid());
+                               fprintf(f, "%u\n", (u_int) getpid());
                                fclose(f);
                        }
                }
-               if (options.protocol & SSH_PROTO_1) {
+               if (options.protocol & SSH_PROTO_1)
                        generate_empheral_server_key();
 
-                       /* Schedule server key regeneration alarm. */
-                       signal(SIGALRM, key_regeneration_alarm);
-                       alarm(options.key_regeneration_time);
-               }
-
                /* Arrange to restart on SIGHUP.  The handler needs listen_sock. */
                signal(SIGHUP, sighup_handler);
 
@@ -930,7 +915,7 @@ main(int ac, char **av)
                                sighup_restart();
                        if (fdset != NULL)
                                xfree(fdset);
-                       fdsetsz = howmany(maxfd, NFDBITS) * sizeof(fd_mask);
+                       fdsetsz = howmany(maxfd+1, NFDBITS) * sizeof(fd_mask);
                        fdset = (fd_set *)xmalloc(fdsetsz);
                        memset(fdset, 0, fdsetsz);
 
@@ -941,18 +926,24 @@ main(int ac, char **av)
                                        FD_SET(startup_pipes[i], fdset);
 
                        /* Wait in select until there is a connection. */
-                       if (select(maxfd + 1, fdset, NULL, NULL, NULL) < 0) {
-                               if (errno != EINTR)
-                                       error("select: %.100s", strerror(errno));
-                               continue;
+                       ret = select(maxfd+1, fdset, NULL, NULL, NULL);
+                       if (ret < 0 && errno != EINTR)
+                               error("select: %.100s", strerror(errno));
+                       if (key_used && key_do_regen) {
+                               generate_empheral_server_key();
+                               key_used = 0;
+                               key_do_regen = 0;
                        }
+                       if (ret < 0)
+                               continue;
+
                        for (i = 0; i < options.max_startups; i++)
                                if (startup_pipes[i] != -1 &&
                                    FD_ISSET(startup_pipes[i], fdset)) {
                                        /*
                                         * the read end of the pipe is ready
                                         * if the child has closed the pipe
-                                        * after successfull authentication
+                                        * after successful authentication
                                         * or if the child has died
                                         */
                                        close(startup_pipes[i]);
@@ -992,7 +983,7 @@ main(int ac, char **av)
                                                startups++;
                                                break;
                                        }
-                               
+
                                /*
                                 * Got connection.  Fork a child to handle it, unless
                                 * we are in debugging mode.
@@ -1031,7 +1022,7 @@ main(int ac, char **av)
                                                close_listen_socks();
                                                sock_in = newsock;
                                                sock_out = newsock;
-                                               log_init(av0, options.log_level, options.log_facility, log_stderr);
+                                               log_init(__progname, options.log_level, options.log_facility, log_stderr);
                                                break;
                                        }
                                }
@@ -1045,7 +1036,13 @@ main(int ac, char **av)
                                close(startup_p[1]);
 
                                /* Mark that the key has been used (it was "given" to the child). */
-                               key_used = 1;
+                               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;
+                               }
 
                                arc4random_stir();
 
@@ -1083,6 +1080,12 @@ main(int ac, char **av)
        linger.l_linger = 5;
        setsockopt(sock_in, SOL_SOCKET, SO_LINGER, (void *) &linger, sizeof(linger));
 
+       /* Set keepalives if requested. */
+       if (options.keepalives &&
+           setsockopt(sock_in, SOL_SOCKET, SO_KEEPALIVE, (void *)&on,
+           sizeof(on)) < 0)
+               error("setsockopt SO_KEEPALIVE: %.100s", strerror(errno));
+
        /*
         * Register our connection.  This turns encryption off because we do
         * not have a key.
@@ -1098,7 +1101,7 @@ main(int ac, char **av)
        {
                struct request_info req;
 
-               request_init(&req, RQ_DAEMON, av0, RQ_FILE, sock_in, NULL);
+               request_init(&req, RQ_DAEMON, __progname, RQ_FILE, sock_in, NULL);
                fromhost(&req);
 
                if (!hosts_access(&req)) {
@@ -1126,18 +1129,17 @@ main(int ac, char **av)
 
        sshd_exchange_identification(sock_in, sock_out);
        /*
-        * Check that the connection comes from a privileged port.  Rhosts-
-        * and Rhosts-RSA-Authentication only make sense from priviledged
+        * Check that the connection comes from a privileged port.
+        * Rhosts-Authentication only makes sense from priviledged
         * programs.  Of course, if the intruder has root access on his local
         * machine, he can connect from any port.  So do not use these
         * authentication methods from machines that you do not trust.
         */
        if (remote_port >= IPPORT_RESERVED ||
            remote_port < IPPORT_RESERVED / 2) {
-               debug("Rhosts Authentication methods disabled, "
+               debug("Rhosts Authentication disabled, "
                    "originating port not trusted.");
                options.rhosts_authentication = 0;
-               options.rhosts_rsa_authentication = 0;
        }
 #ifdef KRB4
        if (!packet_connection_is_ipv4() &&
@@ -1180,14 +1182,15 @@ main(int ac, char **av)
  * SSH1 key exchange
  */
 void
-do_ssh1_kex()
+do_ssh1_kex(void)
 {
        int i, len;
        int plen, slen;
+       int rsafail = 0;
        BIGNUM *session_key_int;
-       unsigned char session_key[SSH_SESSION_KEY_LENGTH];
-       unsigned char cookie[8];
-       unsigned int cipher_type, auth_mask, protocol_flags;
+       u_char session_key[SSH_SESSION_KEY_LENGTH];
+       u_char cookie[8];
+       u_int cipher_type, auth_mask, protocol_flags;
        u_int32_t rand = 0;
 
        /*
@@ -1249,10 +1252,8 @@ do_ssh1_kex()
        if (options.afs_token_passing)
                auth_mask |= 1 << SSH_PASS_AFS_TOKEN;
 #endif
-#ifdef SKEY
-       if (options.skey_authentication == 1)
+       if (options.challenge_reponse_authentication == 1)
                auth_mask |= 1 << SSH_AUTH_TIS;
-#endif
        if (options.password_authentication)
                auth_mask |= 1 << SSH_AUTH_PASSWORD;
        packet_put_int(auth_mask);
@@ -1296,7 +1297,7 @@ do_ssh1_kex()
         * with larger modulus first).
         */
        if (BN_cmp(sensitive_data.server_key->rsa->n, sensitive_data.ssh1_host_key->rsa->n) > 0) {
-               /* Private key has bigger modulus. */
+               /* Server key has bigger modulus. */
                if (BN_num_bits(sensitive_data.server_key->rsa->n) <
                    BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) + SSH_KEY_BITS_RESERVED) {
                        fatal("do_connection: %s: server_key %d < host_key %d + SSH_KEY_BITS_RESERVED %d",
@@ -1305,10 +1306,12 @@ do_ssh1_kex()
                            BN_num_bits(sensitive_data.ssh1_host_key->rsa->n),
                            SSH_KEY_BITS_RESERVED);
                }
-               rsa_private_decrypt(session_key_int, session_key_int,
-                   sensitive_data.server_key->rsa);
-               rsa_private_decrypt(session_key_int, session_key_int,
-                   sensitive_data.ssh1_host_key->rsa);
+               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 {
                /* Host key has bigger modulus (or they are equal). */
                if (BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) <
@@ -1319,10 +1322,12 @@ do_ssh1_kex()
                            BN_num_bits(sensitive_data.server_key->rsa->n),
                            SSH_KEY_BITS_RESERVED);
                }
-               rsa_private_decrypt(session_key_int, session_key_int,
-                   sensitive_data.ssh1_host_key->rsa);
-               rsa_private_decrypt(session_key_int, session_key_int,
-                   sensitive_data.server_key->rsa);
+               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++;
        }
 
        compute_session_id(session_id, cookie,
@@ -1337,15 +1342,29 @@ do_ssh1_kex()
         * least significant 256 bits of the integer; the first byte of the
         * key is in the highest bits.
         */
-       BN_mask_bits(session_key_int, sizeof(session_key) * 8);
-       len = BN_num_bytes(session_key_int);
-       if (len < 0 || len > sizeof(session_key))
-               fatal("do_connection: bad len from %s: session_key_int %d > sizeof(session_key) %d",
-                   get_remote_ipaddr(),
-                   len, sizeof(session_key));
-       memset(session_key, 0, sizeof(session_key));
-       BN_bn2bin(session_key_int, session_key + sizeof(session_key) - len);
-
+       if (!rsafail) {
+               BN_mask_bits(session_key_int, sizeof(session_key) * 8);
+               len = BN_num_bytes(session_key_int);
+               if (len < 0 || len > sizeof(session_key)) {
+                       error("do_connection: bad session key len from %s: "
+                           "session_key_int %d > sizeof(session_key) %d",
+                           get_remote_ipaddr(), len, (int)sizeof(session_key));
+                       rsafail++;
+               } else {
+                       memset(session_key, 0, sizeof(session_key));
+                       BN_bn2bin(session_key_int,
+                           session_key + sizeof(session_key) - len);
+               }
+       }
+       if (rsafail) {
+               log("do_connection: generating a fake encryption key");
+               for (i = 0; i < SSH_SESSION_KEY_LENGTH; i++) {
+                       if (i % 4 == 0)
+                               rand = arc4random();
+                       session_key[i] = rand & 0xff;
+                       rand >>= 8;
+               }
+       }
        /* Destroy the decrypted integer.  It is no longer needed. */
        BN_clear_free(session_key_int);
 
@@ -1371,7 +1390,7 @@ do_ssh1_kex()
  * SSH2 key exchange: diffie-hellman-group1-sha1
  */
 void
-do_ssh2_kex()
+do_ssh2_kex(void)
 {
        Buffer *server_kexinit;
        Buffer *client_kexinit;
@@ -1444,12 +1463,12 @@ ssh_dh1_server(Kex *kex, Buffer *client_kexinit, Buffer *server_kexinit)
 #endif
        int payload_len, dlen;
        int slen;
-       unsigned char *signature = NULL;
-       unsigned char *server_host_key_blob = NULL;
-       unsigned int sbloblen;
-       unsigned int klen, kout;
-       unsigned char *kbuf;
-       unsigned char *hash;
+       u_char *signature = NULL;
+       u_char *server_host_key_blob = NULL;
+       u_int sbloblen;
+       u_int klen, kout;
+       u_char *kbuf;
+       u_char *hash;
        BIGNUM *shared_secret = 0;
        DH *dh;
        BIGNUM *dh_client_pub = 0;
@@ -1460,6 +1479,10 @@ ssh_dh1_server(Kex *kex, Buffer *client_kexinit, Buffer *server_kexinit)
                fatal("Unsupported hostkey type %d", kex->hostkey_type);
 
 /* KEXDH */
+       /* generate DH key */
+       dh = dh_new_group1();                   /* XXX depends on 'kex' */
+       dh_gen_key(dh);
+
        debug("Wait SSH2_MSG_KEXDH_INIT.");
        packet_read_expect(&payload_len, SSH2_MSG_KEXDH_INIT);
 
@@ -1476,9 +1499,6 @@ ssh_dh1_server(Kex *kex, Buffer *client_kexinit, Buffer *server_kexinit)
        debug("bits %d", BN_num_bits(dh_client_pub));
 #endif
 
-       /* generate DH key */
-       dh = dh_new_group1();                   /* XXX depends on 'kex' */
-
 #ifdef DEBUG_KEXDH
        fprintf(stderr, "\np= ");
        BN_print_fp(stderr, dh->p);
@@ -1487,7 +1507,7 @@ ssh_dh1_server(Kex *kex, Buffer *client_kexinit, Buffer *server_kexinit)
        fprintf(stderr, "\npub= ");
        BN_print_fp(stderr, dh->pub_key);
        fprintf(stderr, "\n");
-        DHparams_print_fp(stderr, dh);
+       DHparams_print_fp(stderr, dh);
 #endif
        if (!dh_pub_is_valid(dh, dh_client_pub))
                packet_disconnect("bad client public DH value");
@@ -1527,6 +1547,7 @@ ssh_dh1_server(Kex *kex, Buffer *client_kexinit, Buffer *server_kexinit)
        buffer_free(server_kexinit);
        xfree(client_kexinit);
        xfree(server_kexinit);
+       BN_free(dh_client_pub);
 #ifdef DEBUG_KEXDH
        fprintf(stderr, "hash == ");
        for (i = 0; i< 20; i++)
@@ -1556,6 +1577,7 @@ ssh_dh1_server(Kex *kex, Buffer *client_kexinit, Buffer *server_kexinit)
        packet_write_wait();
 
        kex_derive_keys(kex, hash, shared_secret);
+       BN_clear_free(shared_secret);
        packet_set_kex(kex);
 
        /* have keys, free DH */
@@ -1572,12 +1594,12 @@ ssh_dhgex_server(Kex *kex, Buffer *client_kexinit, Buffer *server_kexinit)
 #endif
        int payload_len, dlen;
        int slen, nbits;
-       unsigned char *signature = NULL;
-       unsigned char *server_host_key_blob = NULL;
-       unsigned int sbloblen;
-       unsigned int klen, kout;
-       unsigned char *kbuf;
-       unsigned char *hash;
+       u_char *signature = NULL;
+       u_char *server_host_key_blob = NULL;
+       u_int sbloblen;
+       u_int klen, kout;
+       u_char *kbuf;
+       u_char *hash;
        BIGNUM *shared_secret = 0;
        DH *dh;
        BIGNUM *dh_client_pub = 0;
@@ -1600,6 +1622,10 @@ ssh_dhgex_server(Kex *kex, Buffer *client_kexinit, Buffer *server_kexinit)
        packet_send();
        packet_write_wait();
 
+       /* Compute our exchange value in parallel with the client */
+
+       dh_gen_key(dh);
+
        debug("Wait SSH2_MSG_KEX_DH_GEX_INIT.");
        packet_read_expect(&payload_len, SSH2_MSG_KEX_DH_GEX_INIT);
 
@@ -1624,7 +1650,7 @@ ssh_dhgex_server(Kex *kex, Buffer *client_kexinit, Buffer *server_kexinit)
        fprintf(stderr, "\npub= ");
        BN_print_fp(stderr, dh->pub_key);
        fprintf(stderr, "\n");
-        DHparams_print_fp(stderr, dh);
+       DHparams_print_fp(stderr, dh);
 #endif
        if (!dh_pub_is_valid(dh, dh_client_pub))
                packet_disconnect("bad client public DH value");
@@ -1665,6 +1691,7 @@ ssh_dhgex_server(Kex *kex, Buffer *client_kexinit, Buffer *server_kexinit)
        buffer_free(server_kexinit);
        xfree(client_kexinit);
        xfree(server_kexinit);
+       BN_free(dh_client_pub);
 #ifdef DEBUG_KEXDH
        fprintf(stderr, "hash == ");
        for (i = 0; i< 20; i++)
@@ -1694,6 +1721,7 @@ ssh_dhgex_server(Kex *kex, Buffer *client_kexinit, Buffer *server_kexinit)
        packet_write_wait();
 
        kex_derive_keys(kex, hash, shared_secret);
+       BN_clear_free(shared_secret);
        packet_set_kex(kex);
 
        /* have keys, free DH */
This page took 0.28613 seconds and 4 git commands to generate.