]> andersk Git - openssh.git/blobdiff - sshd.c
- markus@cvs.openbsd.org 2001/11/09 19:08:35
[openssh.git] / sshd.c
diff --git a/sshd.c b/sshd.c
index 384d4082dcc09e24ed7f2eebc8cfa256db7c3493..22ea8990e868fb66a2e1d859ed9fced590e246b9 100644 (file)
--- a/sshd.c
+++ b/sshd.c
@@ -40,7 +40,7 @@
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: sshd.c,v 1.175 2001/03/18 23:30:55 deraadt Exp $");
+RCSID("$OpenBSD: sshd.c,v 1.208 2001/11/09 19:08:35 markus Exp $");
 
 #include <openssl/dh.h>
 #include <openssl/bn.h>
@@ -70,6 +70,8 @@ RCSID("$OpenBSD: sshd.c,v 1.175 2001/03/18 23:30:55 deraadt Exp $");
 #include "canohost.h"
 #include "auth.h"
 #include "misc.h"
+#include "dispatch.h"
+#include "channels.h"
 
 #ifdef LIBWRAP
 #include <tcpd.h>
@@ -112,6 +114,9 @@ int IPv4or6 = AF_UNSPEC;
  */
 int debug_flag = 0;
 
+/* Flag indicating that the daemon should only test the configuration and keys. */
+int test_flag = 0;
+
 /* Flag indicating that the daemon is being started from inetd. */
 int inetd_flag = 0;
 
@@ -140,6 +145,9 @@ int num_listen_socks = 0;
 char *client_version_string = NULL;
 char *server_version_string = NULL;
 
+/* for rekeying XXX fixme */
+Kex *xxx_kex;
+
 /*
  * Any really sensitive data in the application is contained in this
  * structure. The idea is that this structure could be locked into memory so
@@ -163,8 +171,9 @@ struct {
  */
 int key_do_regen = 0;
 
-/* This is set to true when SIGHUP is received. */
+/* This is set to true when a signal is received. */
 int received_sighup = 0;
+int received_sigterm = 0;
 
 /* session identifier, used by RSA-auth */
 u_char session_id[16];
@@ -177,16 +186,15 @@ int session_id2_len = 0;
 u_int utmp_len = MAXHOSTNAMELEN;
 
 /* Prototypes for various functions defined later in this file. */
-void do_ssh1_kex(void);
-void do_ssh2_kex(void);
+void destroy_sensitive_data(void);
 
-void ssh_dh1_server(Kex *, Buffer *_kexinit, Buffer *);
-void ssh_dhgex_server(Kex *, Buffer *_kexinit, Buffer *);
+static void do_ssh1_kex(void);
+static void do_ssh2_kex(void);
 
 /*
  * Close all listening sockets
  */
-void
+static void
 close_listen_socks(void)
 {
        int i;
@@ -200,7 +208,7 @@ close_listen_socks(void)
  * the effect is to reread the configuration file (and to regenerate
  * the server key).
  */
-void
+static void
 sighup_handler(int sig)
 {
        received_sighup = 1;
@@ -211,7 +219,7 @@ sighup_handler(int sig)
  * Called from the main program after receiving SIGHUP.
  * Restarts the server.
  */
-void
+static void
 sighup_restart(void)
 {
        log("Received SIGHUP; restarting.");
@@ -223,23 +231,18 @@ sighup_restart(void)
 
 /*
  * Generic signal handler for terminating signals in the master daemon.
- * These close the listen socket; not closing it seems to cause "Address
- * already in use" problems on some machines, which is inconvenient.
  */
-void
+static void
 sigterm_handler(int sig)
 {
-       log("Received signal %d; terminating.", sig);
-       close_listen_socks();
-       unlink(options.pid_file);
-       exit(255);
+       received_sigterm = sig;
 }
 
 /*
  * SIGCHLD handler.  This is called whenever a child dies.  This will then
- * reap any zombies left by exited c.
+ * reap any zombies left by exited children.
  */
-void
+static void
 main_sigchld_handler(int sig)
 {
        int save_errno = errno;
@@ -255,9 +258,11 @@ main_sigchld_handler(int sig)
 /*
  * Signal handler for the alarm after the login grace period has expired.
  */
-void
+static void
 grace_alarm_handler(int sig)
 {
+       /* XXX no idea how fix this signal handler */
+
        /* Close the connection. */
        packet_close();
 
@@ -272,18 +277,19 @@ grace_alarm_handler(int sig)
  * Thus there should be no concurrency control/asynchronous execution
  * problems.
  */
-void
+static void
 generate_ephemeral_server_key(void)
 {
        u_int32_t rand = 0;
        int i;
 
-       log("Generating %s%d bit RSA key.", sensitive_data.server_key ? "new " : "",
-           options.server_key_bits);
+       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);
-       log("RSA key generation complete.");
+       sensitive_data.server_key = key_generate(KEY_RSA1,
+           options.server_key_bits);
+       verbose("RSA key generation complete.");
 
        for (i = 0; i < SSH_SESSION_KEY_LENGTH; i++) {
                if (i % 4 == 0)
@@ -294,7 +300,7 @@ generate_ephemeral_server_key(void)
        arc4random_stir();
 }
 
-void
+static void
 key_regeneration_alarm(int sig)
 {
        int save_errno = errno;
@@ -303,7 +309,7 @@ key_regeneration_alarm(int sig)
        key_do_regen = 1;
 }
 
-void
+static void
 sshd_exchange_identification(int sock_in, int sock_out)
 {
        int i, mismatch;
@@ -331,21 +337,20 @@ sshd_exchange_identification(int sock_in, int sock_out)
                /* Send our protocol version identification. */
                if (atomicio(write, sock_out, server_version_string, strlen(server_version_string))
                    != strlen(server_version_string)) {
-                       log("Could not write ident string to %s.", get_remote_ipaddr());
+                       log("Could not write ident string to %s", get_remote_ipaddr());
                        fatal_cleanup();
                }
 
                /* Read other side's version identification. */
-               memset(buf, 0, sizeof(buf)); 
+               memset(buf, 0, sizeof(buf));
                for (i = 0; i < sizeof(buf) - 1; i++) {
                        if (atomicio(read, sock_in, &buf[i], 1) != 1) {
-                               log("Did not receive identification string from %s.",
+                               log("Did not receive identification string from %s",
                                    get_remote_ipaddr());
                                fatal_cleanup();
                        }
                        if (buf[i] == '\r') {
-                               buf[i] = '\n';
-                               buf[i + 1] = 0;
+                               buf[i] = 0;
                                /* Kludge for F-Secure Macintosh < 1.0.2 */
                                if (i == 12 &&
                                    strncmp(buf, "SSH-1.5-W1.0", 12) == 0)
@@ -353,8 +358,7 @@ sshd_exchange_identification(int sock_in, int sock_out)
                                continue;
                        }
                        if (buf[i] == '\n') {
-                               /* buf[i] == '\n' */
-                               buf[i + 1] = 0;
+                               buf[i] = 0;
                                break;
                        }
                }
@@ -420,7 +424,6 @@ sshd_exchange_identification(int sock_in, int sock_out)
                break;
        }
        chop(server_version_string);
-       chop(client_version_string);
        debug("Local version string %.200s", server_version_string);
 
        if (mismatch) {
@@ -433,8 +436,6 @@ sshd_exchange_identification(int sock_in, int sock_out)
                    server_version_string, client_version_string);
                fatal_cleanup();
        }
-       if (compat20)
-               packet_set_ssh2_format();
 }
 
 
@@ -457,41 +458,8 @@ destroy_sensitive_data(void)
        sensitive_data.ssh1_host_key = NULL;
        memset(sensitive_data.ssh1_cookie, 0, SSH_SESSION_KEY_LENGTH);
 }
-Key *
-load_private_key_autodetect(const char *filename)
-{
-       struct stat st;
-       int type;
-       Key *public, *private;
-
-       if (stat(filename, &st) < 0) {
-               perror(filename);
-               return NULL;
-       }
-       /*
-        * try to load the public key. right now this only works for RSA1,
-        * since SSH2 keys are fully encrypted
-        */
-       type = KEY_RSA1;
-       public = key_new(type);
-       if (!load_public_key(filename, public, NULL)) {
-               /* ok, so we will assume this is 'some' key */
-               type = KEY_UNSPEC;
-       }
-       key_free(public);
-
-       /* Ok, try key with empty passphrase */
-       private = key_new(type);
-       if (load_private_key(filename, "", private, NULL)) {
-               debug("load_private_key_autodetect: type %d %s",
-                   private->type, key_type(private));
-               return private;
-       }
-       key_free(private);
-       return NULL;
-}
 
-char *
+static char *
 list_hostkey_types(void)
 {
        static char buf[1024];
@@ -516,7 +484,7 @@ list_hostkey_types(void)
        return buf;
 }
 
-Key *
+static Key *
 get_hostkey_by_type(int type)
 {
        int i;
@@ -534,7 +502,7 @@ get_hostkey_by_type(int type)
  * of (max_startups_rate/100). the probability increases linearly until
  * all connections are dropped for startups > max_startups
  */
-int
+static int
 drop_connection(int startups)
 {
        double p, r;
@@ -582,6 +550,7 @@ main(int ac, char **av)
        int listen_sock, maxfd;
        int startup_p[2];
        int startups = 0;
+       Key *key;
        int ret, key_used = 0;
 
        __progname = get_progname(av[0]);
@@ -595,7 +564,7 @@ main(int ac, char **av)
        initialize_server_options(&options);
 
        /* Parse command-line arguments. */
-       while ((opt = getopt(ac, av, "f:p:b:k:h:g:V:u:dDiqQ46")) != -1) {
+       while ((opt = getopt(ac, av, "f:p:b:k:h:g:V:u:dDeiqtQ46")) != -1) {
                switch (opt) {
                case '4':
                        IPv4or6 = AF_INET;
@@ -620,6 +589,9 @@ main(int ac, char **av)
                case 'D':
                        no_daemon_flag = 1;
                        break;
+               case 'e':
+                       log_stderr = 1;
+                       break;
                case 'i':
                        inetd_flag = 1;
                        break;
@@ -638,13 +610,23 @@ main(int ac, char **av)
                                fprintf(stderr, "too many ports.\n");
                                exit(1);
                        }
-                       options.ports[options.num_ports++] = atoi(optarg);
+                       options.ports[options.num_ports++] = a2port(optarg);
+                       if (options.ports[options.num_ports-1] == 0) {
+                               fprintf(stderr, "Bad port number.\n");
+                               exit(1);
+                       }
                        break;
                case 'g':
-                       options.login_grace_time = atoi(optarg);
+                       if ((options.login_grace_time = convtime(optarg)) == -1) {
+                               fprintf(stderr, "Invalid login grace time.\n");
+                               exit(1);
+                       }
                        break;
                case 'k':
-                       options.key_regeneration_time = atoi(optarg);
+                       if ((options.key_regeneration_time = convtime(optarg)) == -1) {
+                               fprintf(stderr, "Invalid key regeneration interval.\n");
+                               exit(1);
+                       }
                        break;
                case 'h':
                        if (options.num_host_key_files >= MAX_HOSTKEYS) {
@@ -658,6 +640,9 @@ main(int ac, char **av)
                        /* only makes sense with inetd_flag, i.e. no listen() */
                        inetd_flag = 1;
                        break;
+               case 't':
+                       test_flag = 1;
+                       break;
                case 'u':
                        utmp_len = atoi(optarg);
                        break;
@@ -670,6 +655,7 @@ main(int ac, char **av)
                        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, "  -t         Only test configuration file and keys\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");
@@ -683,6 +669,8 @@ main(int ac, char **av)
                        exit(1);
                }
        }
+       SSLeay_add_all_algorithms();
+       channel_set_af(IPv4or6);
 
        /*
         * Force logging to stderr until we have loaded the private host
@@ -693,6 +681,13 @@ main(int ac, char **av)
            options.log_facility == -1 ? SYSLOG_FACILITY_AUTH : options.log_facility,
            !inetd_flag);
 
+#ifdef _CRAY
+       /* Cray can define user privs drop all prives now!
+        * Not needed on PRIV_SU systems!
+        */
+       drop_cray_privs();
+#endif
+
        seed_rng();
 
        /* Read server configuration options from the configuration file. */
@@ -719,10 +714,12 @@ main(int ac, char **av)
        sensitive_data.have_ssh2_key = 0;
 
        for(i = 0; i < options.num_host_key_files; i++) {
-               Key *key = load_private_key_autodetect(options.host_key_files[i]);
+               key = key_load_private(options.host_key_files[i], "", NULL);
+               sensitive_data.host_keys[i] = key;
                if (key == NULL) {
-                       error("Could not load host key: %.200s: %.100s",
-                           options.host_key_files[i], strerror(errno));
+                       error("Could not load host key: %s",
+                           options.host_key_files[i]);
+                       sensitive_data.host_keys[i] = NULL;
                        continue;
                }
                switch(key->type){
@@ -735,7 +732,8 @@ main(int ac, char **av)
                        sensitive_data.have_ssh2_key = 1;
                        break;
                }
-               sensitive_data.host_keys[i] = key;
+               debug("private host key: #%d type %d %s", i, key->type,
+                   key_type(key));
        }
        if ((options.protocol & SSH_PROTO_1) && !sensitive_data.have_ssh1_key) {
                log("Disabling protocol version 1. Could not load host key");
@@ -773,6 +771,10 @@ main(int ac, char **av)
                }
        }
 
+       /* Configuration looks good, so exit if in test mode. */
+       if (test_flag)
+               exit(0);
+
 #ifdef HAVE_SCO_PROTECTED_PW
        (void) set_auth_parameters(ac, av);
 #endif
@@ -812,12 +814,15 @@ main(int ac, char **av)
        /* Chdir to the root directory so that the current disk can be
           unmounted if desired. */
        chdir("/");
+       
+       /* ignore SIGPIPE */
+       signal(SIGPIPE, SIG_IGN);
 
        /* Start listening for a socket, unless started from inetd. */
        if (inetd_flag) {
-               int s1, s2;
+               int s1;
                s1 = dup(0);    /* Make sure descriptors 0, 1, and 2 are in use. */
-               s2 = dup(s1);
+               dup(s1);
                sock_in = dup(0);
                sock_out = dup(1);
                startup_pipe = -1;
@@ -891,6 +896,22 @@ main(int ac, char **av)
                if (!num_listen_socks)
                        fatal("Cannot bind any address.");
 
+               if (options.protocol & SSH_PROTO_1)
+                       generate_ephemeral_server_key();
+
+               /*
+                * Arrange to restart on SIGHUP.  The handler needs
+                * listen_sock.
+                */
+               signal(SIGHUP, sighup_handler);
+
+               signal(SIGTERM, sigterm_handler);
+               signal(SIGQUIT, sigterm_handler);
+
+               /* Arrange SIGCHLD to be caught. */
+               signal(SIGCHLD, main_sigchld_handler);
+
+               /* Write out the pid file after the sigterm handler is setup */
                if (!debug_flag) {
                        /*
                         * Record our pid in /var/run/sshd.pid to make it
@@ -905,17 +926,6 @@ main(int ac, char **av)
                                fclose(f);
                        }
                }
-               if (options.protocol & SSH_PROTO_1)
-                       generate_ephemeral_server_key();
-
-               /* Arrange to restart on SIGHUP.  The handler needs listen_sock. */
-               signal(SIGHUP, sighup_handler);
-
-               signal(SIGTERM, sigterm_handler);
-               signal(SIGQUIT, sigterm_handler);
-
-               /* Arrange SIGCHLD to be caught. */
-               signal(SIGCHLD, main_sigchld_handler);
 
                /* setup fd set for listen */
                fdset = NULL;
@@ -951,6 +961,13 @@ main(int ac, char **av)
                        ret = select(maxfd+1, fdset, NULL, NULL, NULL);
                        if (ret < 0 && errno != EINTR)
                                error("select: %.100s", strerror(errno));
+                       if (received_sigterm) {
+                               log("Received signal %d; terminating.",
+                                   received_sigterm);
+                               close_listen_socks();
+                               unlink(options.pid_file);
+                               exit(255);
+                       }
                        if (key_used && key_do_regen) {
                                generate_ephemeral_server_key();
                                key_used = 0;
@@ -1123,13 +1140,13 @@ main(int ac, char **av)
        {
                struct request_info req;
 
-               request_init(&req, RQ_DAEMON, __progname, RQ_FILE, sock_in, NULL);
+               request_init(&req, RQ_DAEMON, __progname, RQ_FILE, sock_in, 0);
                fromhost(&req);
 
                if (!hosts_access(&req)) {
+                       refuse(&req);
                        close(sock_in);
                        close(sock_out);
-                       refuse(&req);
                }
 /*XXX IPv6 verbose("Connection from %.500s port %d", eval_client(&req), remote_port); */
        }
@@ -1160,16 +1177,16 @@ main(int ac, char **av)
        if (remote_port >= IPPORT_RESERVED ||
            remote_port < IPPORT_RESERVED / 2) {
                debug("Rhosts Authentication disabled, "
-                   "originating port not trusted.");
+                   "originating port %d not trusted.", remote_port);
                options.rhosts_authentication = 0;
        }
-#ifdef KRB4
+#if defined(KRB4) && !defined(KRB5)
        if (!packet_connection_is_ipv4() &&
            options.kerberos_authentication) {
                debug("Kerberos Authentication disabled, only available for IPv4.");
                options.kerberos_authentication = 0;
        }
-#endif /* KRB4 */
+#endif /* KRB4 && !KRB5 */
 #ifdef AFS
        /* If machine has AFS, set process authentication group. */
        if (k_hasafs()) {
@@ -1189,13 +1206,6 @@ main(int ac, char **av)
                do_ssh1_kex();
                do_authentication();
        }
-
-#ifdef KRB4
-       /* Cleanup user's ticket cache file. */
-       if (options.kerberos_ticket_cleanup)
-               (void) dest_tkt();
-#endif /* KRB4 */
-
        /* The connection has been terminated. */
        verbose("Closing connection to %.100s", remote_ip);
 
@@ -1210,7 +1220,7 @@ main(int ac, char **av)
 /*
  * SSH1 key exchange
  */
-void
+static void
 do_ssh1_kex(void)
 {
        int i, len;
@@ -1271,17 +1281,19 @@ do_ssh1_kex(void)
                auth_mask |= 1 << SSH_AUTH_RHOSTS_RSA;
        if (options.rsa_authentication)
                auth_mask |= 1 << SSH_AUTH_RSA;
-#ifdef KRB4
+#if defined(KRB4) || defined(KRB5)
        if (options.kerberos_authentication)
                auth_mask |= 1 << SSH_AUTH_KERBEROS;
 #endif
-#ifdef AFS
+#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_reponse_authentication == 1)
+       if (options.challenge_response_authentication == 1)
                auth_mask |= 1 << SSH_AUTH_TIS;
        if (options.password_authentication)
                auth_mask |= 1 << SSH_AUTH_PASSWORD;
@@ -1431,58 +1443,39 @@ do_ssh1_kex(void)
 /*
  * SSH2 key exchange: diffie-hellman-group1-sha1
  */
-void
+static void
 do_ssh2_kex(void)
 {
-       Buffer *server_kexinit;
-       Buffer *client_kexinit;
-       int payload_len;
-       int i;
        Kex *kex;
-       char *cprop[PROPOSAL_MAX];
-
-/* KEXINIT */
 
        if (options.ciphers != NULL) {
                myproposal[PROPOSAL_ENC_ALGS_CTOS] =
                myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers;
        }
+       myproposal[PROPOSAL_ENC_ALGS_CTOS] =
+           compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_CTOS]);
+       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_STOC] = options.macs;
        }
        myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = list_hostkey_types();
 
-       server_kexinit = kex_init(myproposal);
-       client_kexinit = xmalloc(sizeof(*client_kexinit));
-       buffer_init(client_kexinit);
-
-       /* algorithm negotiation */
-       kex_exchange_kexinit(server_kexinit, client_kexinit, cprop);
-       kex = kex_choose_conf(cprop, myproposal, 1);
-       for (i = 0; i < PROPOSAL_MAX; i++)
-               xfree(cprop[i]);
+       /* start key exchange */
+       kex = kex_setup(myproposal);
+       kex->server = 1;
+       kex->client_version_string=client_version_string;
+       kex->server_version_string=server_version_string;
+       kex->load_host_key=&get_hostkey_by_type;
 
-       switch (kex->kex_type) {
-       case DH_GRP1_SHA1:
-               ssh_dh1_server(kex, client_kexinit, server_kexinit);
-               break;
-       case DH_GEX_SHA1:
-               ssh_dhgex_server(kex, client_kexinit, server_kexinit);
-               break;
-       default:
-               fatal("Unsupported key exchange %d", kex->kex_type);
-       }
+       xxx_kex = kex;
 
-       debug("send SSH2_MSG_NEWKEYS.");
-       packet_start(SSH2_MSG_NEWKEYS);
-       packet_send();
-       packet_write_wait();
-       debug("done: send SSH2_MSG_NEWKEYS.");
+       dispatch_run(DISPATCH_BLOCK, &kex->done, kex);
 
-       debug("Wait SSH2_MSG_NEWKEYS.");
-       packet_read_expect(&payload_len, SSH2_MSG_NEWKEYS);
-       debug("GOT SSH2_MSG_NEWKEYS.");
+       session_id2 = kex->session_id;
+       session_id2_len = kex->session_id_len;
 
 #ifdef DEBUG_KEXDH
        /* send 1st encrypted/maced/compressed message */
@@ -1491,285 +1484,5 @@ do_ssh2_kex(void)
        packet_send();
        packet_write_wait();
 #endif
-
-       debug("done: KEX2.");
-}
-
-/*
- * SSH2 key exchange
- */
-
-/* diffie-hellman-group1-sha1 */
-
-void
-ssh_dh1_server(Kex *kex, Buffer *client_kexinit, Buffer *server_kexinit)
-{
-#ifdef DEBUG_KEXDH
-       int i;
-#endif
-       int payload_len, dlen;
-       int slen;
-       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;
-       Key *hostkey;
-
-       hostkey = get_hostkey_by_type(kex->hostkey_type);
-       if (hostkey == NULL)
-               fatal("Unsupported hostkey type %d", kex->hostkey_type);
-
-/* KEXDH */
-       /* generate DH key */
-       dh = dh_new_group1();                   /* XXX depends on 'kex' */
-       dh_gen_key(dh, kex->we_need * 8);
-
-       debug("Wait SSH2_MSG_KEXDH_INIT.");
-       packet_read_expect(&payload_len, SSH2_MSG_KEXDH_INIT);
-
-       /* key, cert */
-       dh_client_pub = BN_new();
-       if (dh_client_pub == NULL)
-               fatal("dh_client_pub == NULL");
-       packet_get_bignum2(dh_client_pub, &dlen);
-
-#ifdef DEBUG_KEXDH
-       fprintf(stderr, "\ndh_client_pub= ");
-       BN_print_fp(stderr, dh_client_pub);
-       fprintf(stderr, "\n");
-       debug("bits %d", BN_num_bits(dh_client_pub));
-#endif
-
-#ifdef DEBUG_KEXDH
-       fprintf(stderr, "\np= ");
-       BN_print_fp(stderr, dh->p);
-       fprintf(stderr, "\ng= ");
-       bn_print(dh->g);
-       fprintf(stderr, "\npub= ");
-       BN_print_fp(stderr, dh->pub_key);
-       fprintf(stderr, "\n");
-       DHparams_print_fp(stderr, dh);
-#endif
-       if (!dh_pub_is_valid(dh, dh_client_pub))
-               packet_disconnect("bad client public DH value");
-
-       klen = DH_size(dh);
-       kbuf = xmalloc(klen);
-       kout = DH_compute_key(kbuf, dh_client_pub, dh);
-
-#ifdef DEBUG_KEXDH
-       debug("shared secret: len %d/%d", klen, kout);
-       fprintf(stderr, "shared secret == ");
-       for (i = 0; i< kout; i++)
-               fprintf(stderr, "%02x", (kbuf[i])&0xff);
-       fprintf(stderr, "\n");
-#endif
-       shared_secret = BN_new();
-
-       BN_bin2bn(kbuf, kout, shared_secret);
-       memset(kbuf, 0, klen);
-       xfree(kbuf);
-
-       /* XXX precompute? */
-       key_to_blob(hostkey, &server_host_key_blob, &sbloblen);
-
-       /* calc H */                    /* XXX depends on 'kex' */
-       hash = kex_hash(
-           client_version_string,
-           server_version_string,
-           buffer_ptr(client_kexinit), buffer_len(client_kexinit),
-           buffer_ptr(server_kexinit), buffer_len(server_kexinit),
-           (char *)server_host_key_blob, sbloblen,
-           dh_client_pub,
-           dh->pub_key,
-           shared_secret
-       );
-       buffer_free(client_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++)
-               fprintf(stderr, "%02x", (hash[i])&0xff);
-       fprintf(stderr, "\n");
-#endif
-       /* save session id := H */
-       /* XXX hashlen depends on KEX */
-       session_id2_len = 20;
-       session_id2 = xmalloc(session_id2_len);
-       memcpy(session_id2, hash, session_id2_len);
-
-       /* sign H */
-       /* XXX hashlen depends on KEX */
-       key_sign(hostkey, &signature, &slen, hash, 20);
-
-       destroy_sensitive_data();
-
-       /* send server hostkey, DH pubkey 'f' and singed H */
-       packet_start(SSH2_MSG_KEXDH_REPLY);
-       packet_put_string((char *)server_host_key_blob, sbloblen);
-       packet_put_bignum2(dh->pub_key);        /* f */
-       packet_put_string((char *)signature, slen);
-       packet_send();
-       xfree(signature);
-       xfree(server_host_key_blob);
-       packet_write_wait();
-
-       kex_derive_keys(kex, hash, shared_secret);
-       BN_clear_free(shared_secret);
-       packet_set_kex(kex);
-
-       /* have keys, free DH */
-       DH_free(dh);
-}
-
-/* diffie-hellman-group-exchange-sha1 */
-
-void
-ssh_dhgex_server(Kex *kex, Buffer *client_kexinit, Buffer *server_kexinit)
-{
-#ifdef DEBUG_KEXDH
-       int i;
-#endif
-       int payload_len, dlen;
-       int slen, nbits;
-       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;
-       Key *hostkey;
-
-       hostkey = get_hostkey_by_type(kex->hostkey_type);
-       if (hostkey == NULL)
-               fatal("Unsupported hostkey type %d", kex->hostkey_type);
-
-/* KEXDHGEX */
-       debug("Wait SSH2_MSG_KEX_DH_GEX_REQUEST.");
-       packet_read_expect(&payload_len, SSH2_MSG_KEX_DH_GEX_REQUEST);
-       nbits = packet_get_int();
-       dh = choose_dh(nbits);
-
-       debug("Sending SSH2_MSG_KEX_DH_GEX_GROUP.");
-       packet_start(SSH2_MSG_KEX_DH_GEX_GROUP);
-       packet_put_bignum2(dh->p);
-       packet_put_bignum2(dh->g);
-       packet_send();
-       packet_write_wait();
-
-       /* Compute our exchange value in parallel with the client */
-
-       dh_gen_key(dh, kex->we_need * 8);
-
-       debug("Wait SSH2_MSG_KEX_DH_GEX_INIT.");
-       packet_read_expect(&payload_len, SSH2_MSG_KEX_DH_GEX_INIT);
-
-       /* key, cert */
-       dh_client_pub = BN_new();
-       if (dh_client_pub == NULL)
-               fatal("dh_client_pub == NULL");
-       packet_get_bignum2(dh_client_pub, &dlen);
-
-#ifdef DEBUG_KEXDH
-       fprintf(stderr, "\ndh_client_pub= ");
-       BN_print_fp(stderr, dh_client_pub);
-       fprintf(stderr, "\n");
-       debug("bits %d", BN_num_bits(dh_client_pub));
-#endif
-
-#ifdef DEBUG_KEXDH
-       fprintf(stderr, "\np= ");
-       BN_print_fp(stderr, dh->p);
-       fprintf(stderr, "\ng= ");
-       bn_print(dh->g);
-       fprintf(stderr, "\npub= ");
-       BN_print_fp(stderr, dh->pub_key);
-       fprintf(stderr, "\n");
-       DHparams_print_fp(stderr, dh);
-#endif
-       if (!dh_pub_is_valid(dh, dh_client_pub))
-               packet_disconnect("bad client public DH value");
-
-       klen = DH_size(dh);
-       kbuf = xmalloc(klen);
-       kout = DH_compute_key(kbuf, dh_client_pub, dh);
-
-#ifdef DEBUG_KEXDH
-       debug("shared secret: len %d/%d", klen, kout);
-       fprintf(stderr, "shared secret == ");
-       for (i = 0; i< kout; i++)
-               fprintf(stderr, "%02x", (kbuf[i])&0xff);
-       fprintf(stderr, "\n");
-#endif
-       shared_secret = BN_new();
-
-       BN_bin2bn(kbuf, kout, shared_secret);
-       memset(kbuf, 0, klen);
-       xfree(kbuf);
-
-       /* XXX precompute? */
-       key_to_blob(hostkey, &server_host_key_blob, &sbloblen);
-
-       /* calc H */                    /* XXX depends on 'kex' */
-       hash = kex_hash_gex(
-           client_version_string,
-           server_version_string,
-           buffer_ptr(client_kexinit), buffer_len(client_kexinit),
-           buffer_ptr(server_kexinit), buffer_len(server_kexinit),
-           (char *)server_host_key_blob, sbloblen,
-           nbits, dh->p, dh->g,
-           dh_client_pub,
-           dh->pub_key,
-           shared_secret
-       );
-       buffer_free(client_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++)
-               fprintf(stderr, "%02x", (hash[i])&0xff);
-       fprintf(stderr, "\n");
-#endif
-       /* save session id := H */
-       /* XXX hashlen depends on KEX */
-       session_id2_len = 20;
-       session_id2 = xmalloc(session_id2_len);
-       memcpy(session_id2, hash, session_id2_len);
-
-       /* sign H */
-       /* XXX hashlen depends on KEX */
-       key_sign(hostkey, &signature, &slen, hash, 20);
-
-       destroy_sensitive_data();
-
-       /* send server hostkey, DH pubkey 'f' and singed H */
-       packet_start(SSH2_MSG_KEX_DH_GEX_REPLY);
-       packet_put_string((char *)server_host_key_blob, sbloblen);
-       packet_put_bignum2(dh->pub_key);        /* f */
-       packet_put_string((char *)signature, slen);
-       packet_send();
-       xfree(signature);
-       xfree(server_host_key_blob);
-       packet_write_wait();
-
-       kex_derive_keys(kex, hash, shared_secret);
-       BN_clear_free(shared_secret);
-       packet_set_kex(kex);
-
-       /* have keys, free DH */
-       DH_free(dh);
+       debug("KEX done");
 }
This page took 0.07059 seconds and 4 git commands to generate.