]> andersk Git - openssh.git/commitdiff
- markus@cvs.openbsd.org 2001/04/03 19:53:29
authormouring <mouring>
Wed, 4 Apr 2001 01:56:17 +0000 (01:56 +0000)
committermouring <mouring>
Wed, 4 Apr 2001 01:56:17 +0000 (01:56 +0000)
     [dh.c dh.h kex.c kex.h sshconnect2.c sshd.c]
     move kex to kex*.c, used dispatch_set() callbacks for kex. should
     make rekeying easier.

ChangeLog
dh.c
dh.h
kex.c
kex.h
sshconnect2.c
sshd.c

index fe9ef327fdfa41c51944464bd45827a75ea76460..9bca5c3fb6c9f4601c4f8f4081be5bde9aea29c1 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -6,6 +6,10 @@
    - stevesk@cvs.openbsd.org 2001/04/03 13:56:11
      [sftp-glob.c ssh-agent.c ssh-keygen.c]
      free() -> xfree()
+   - markus@cvs.openbsd.org 2001/04/03 19:53:29
+     [dh.c dh.h kex.c kex.h sshconnect2.c sshd.c]
+     move kex to kex*.c, used dispatch_set() callbacks for kex. should
+     make rekeying easier.
 
 20010403
  - OpenBSD CVS Sync
diff --git a/dh.c b/dh.c
index 6c53b0038d0175c7c8ff8be46d6151eba9691f78..03b9fd1b84eaf5ecf554d863ce5a381a932d2f09 100644 (file)
--- a/dh.c
+++ b/dh.c
@@ -23,7 +23,7 @@
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: dh.c,v 1.11 2001/03/29 21:17:39 markus Exp $");
+RCSID("$OpenBSD: dh.c,v 1.12 2001/04/03 19:53:29 markus Exp $");
 
 #include "xmalloc.h"
 
@@ -273,3 +273,22 @@ dh_new_group1(void)
 
        return (dh_new_group_asc(gen, group1));
 }
+
+/*
+ * Estimates the group order for a Diffie-Hellman group that has an
+ * attack complexity approximately the same as O(2**bits).  Estimate
+ * with:  O(exp(1.9223 * (ln q)^(1/3) (ln ln q)^(2/3)))
+ */
+
+int
+dh_estimate(int bits)
+{
+
+       if (bits < 64)
+               return (512);   /* O(2**63) */
+       if (bits < 128)
+               return (1024);  /* O(2**86) */
+       if (bits < 192)
+               return (2048);  /* O(2**116) */
+       return (4096);          /* O(2**156) */
+}
diff --git a/dh.h b/dh.h
index 13d2fa1620e396ad1c20992098bae49b7cc1c343..e8b2944ce9ff7f79b138a63f692c583e9c599dfe 100644 (file)
--- a/dh.h
+++ b/dh.h
@@ -1,4 +1,4 @@
-/*     $OpenBSD: dh.h,v 1.4 2001/03/29 21:17:39 markus Exp $   */
+/*     $OpenBSD: dh.h,v 1.5 2001/04/03 19:53:29 markus Exp $   */
 
 /*
  * Copyright (c) 2000 Niels Provos.  All rights reserved.
@@ -40,6 +40,8 @@ DH    *dh_new_group1(void);
 void   dh_gen_key(DH *, int);
 int    dh_pub_is_valid(DH *dh, BIGNUM *dh_pub);
 
+int    dh_estimate(int bits);
+
 #define DH_GRP_MIN     1024
 #define DH_GRP_MAX     8192
 
diff --git a/kex.c b/kex.c
index 576d4b56e774fa9a6772f256bb1d68095ea028d7..a0a5b46fef81103c799fab9935032faba2a42a16 100644 (file)
--- a/kex.c
+++ b/kex.c
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: kex.c,v 1.25 2001/03/29 21:17:39 markus Exp $");
+RCSID("$OpenBSD: kex.c,v 1.26 2001/04/03 19:53:29 markus Exp $");
 
 #include <openssl/crypto.h>
-#include <openssl/bio.h>
-#include <openssl/bn.h>
-#include <openssl/pem.h>
 
 #include "ssh2.h"
 #include "xmalloc.h"
@@ -42,233 +39,169 @@ RCSID("$OpenBSD: kex.c,v 1.25 2001/03/29 21:17:39 markus Exp $");
 #include "log.h"
 #include "mac.h"
 #include "match.h"
+#include "dispatch.h"
 
 #define KEX_COOKIE_LEN 16
 
-Buffer *
-kex_init(char *myproposal[PROPOSAL_MAX])
+void   kex_kexinit_finish(Kex *kex);
+void   kex_choose_conf(Kex *k);
+
+/* put algorithm proposal into buffer */
+void
+kex_prop2buf(Buffer *b, char *proposal[PROPOSAL_MAX])
 {
-       int first_kex_packet_follows = 0;
-       u_char cookie[KEX_COOKIE_LEN];
        u_int32_t rand = 0;
        int i;
-       Buffer *ki = xmalloc(sizeof(*ki));
+
+       buffer_clear(b);
        for (i = 0; i < KEX_COOKIE_LEN; i++) {
                if (i % 4 == 0)
                        rand = arc4random();
-               cookie[i] = rand & 0xff;
+               buffer_put_char(b, rand & 0xff);
                rand >>= 8;
        }
-       buffer_init(ki);
-       buffer_append(ki, (char *)cookie, sizeof cookie);
        for (i = 0; i < PROPOSAL_MAX; i++)
-               buffer_put_cstring(ki, myproposal[i]);
-       buffer_put_char(ki, first_kex_packet_follows);
-       buffer_put_int(ki, 0);                          /* uint32 reserved */
-       return ki;
+               buffer_put_cstring(b, proposal[i]);
+       buffer_put_char(b, 0);                  /* first_kex_packet_follows */
+       buffer_put_int(b, 0);                   /* uint32 reserved */
 }
 
-/* send kexinit, parse and save reply */
-void
-kex_exchange_kexinit(
-    Buffer *my_kexinit, Buffer *peer_kexint,
-    char *peer_proposal[PROPOSAL_MAX])
+/* parse buffer and return algorithm proposal */
+char **
+kex_buf2prop(Buffer *raw)
 {
+       Buffer b;
        int i;
-       char *ptr;
-       int plen;
+       char **proposal;
 
-       debug("send KEXINIT");
-       packet_start(SSH2_MSG_KEXINIT);
-       packet_put_raw(buffer_ptr(my_kexinit), buffer_len(my_kexinit));
-       packet_send();
-       packet_write_wait();
-       debug("done");
-
-       /*
-        * read and save raw KEXINIT payload in buffer. this is used during
-        * computation of the session_id and the session keys.
-        */
-       debug("wait KEXINIT");
-       packet_read_expect(&plen, SSH2_MSG_KEXINIT);
-       ptr = packet_get_raw(&plen);
-       buffer_append(peer_kexint, ptr, plen);
-
-       /* parse packet and save algorithm proposal */
+       proposal = xmalloc(PROPOSAL_MAX * sizeof(char *));
+
+       buffer_init(&b);
+       buffer_append(&b, buffer_ptr(raw), buffer_len(raw));
        /* skip cookie */
        for (i = 0; i < KEX_COOKIE_LEN; i++)
-               packet_get_char();
+               buffer_get_char(&b);
        /* extract kex init proposal strings */
        for (i = 0; i < PROPOSAL_MAX; i++) {
-               peer_proposal[i] = packet_get_string(NULL);
-               debug("got kexinit: %s", peer_proposal[i]);
+               proposal[i] = buffer_get_string(&b,NULL);
+               debug2("kex_parse_kexinit: %s", proposal[i]);
        }
-       /* first kex follow / reserved */
-       i = packet_get_char();
-       debug("first kex follow: %d ", i);
-       i = packet_get_int();
-       debug("reserved: %d ", i);
-       packet_done();
-       debug("done");
+       /* first kex follows / reserved */
+       i = buffer_get_char(&b);
+       debug2("kex_parse_kexinit: first_kex_follows %d ", i);
+       i = buffer_get_int(&b);
+       debug2("kex_parse_kexinit: reserved %d ", i);
+       buffer_free(&b);
+       return proposal;
 }
 
-#ifdef DEBUG_KEX
 void
-dump_digest(u_char *digest, int len)
+kex_prop_free(char **proposal)
 {
        int i;
-       for (i = 0; i< len; i++){
-               fprintf(stderr, "%02x", digest[i]);
-               if(i%2!=0)
-                       fprintf(stderr, " ");
-       }
-       fprintf(stderr, "\n");
+
+       for (i = 0; i < PROPOSAL_MAX; i++)
+               xfree(proposal[i]);
+       xfree(proposal);
 }
-#endif
 
-u_char *
-kex_hash(
-    char *client_version_string,
-    char *server_version_string,
-    char *ckexinit, int ckexinitlen,
-    char *skexinit, int skexinitlen,
-    char *serverhostkeyblob, int sbloblen,
-    BIGNUM *client_dh_pub,
-    BIGNUM *server_dh_pub,
-    BIGNUM *shared_secret)
+void
+kex_protocol_error(int type, int plen, void *ctxt)
 {
-       Buffer b;
-       static u_char digest[EVP_MAX_MD_SIZE];
-       EVP_MD *evp_md = EVP_sha1();
-       EVP_MD_CTX md;
-
-       buffer_init(&b);
-       buffer_put_string(&b, client_version_string, strlen(client_version_string));
-       buffer_put_string(&b, server_version_string, strlen(server_version_string));
-
-       /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */
-       buffer_put_int(&b, ckexinitlen+1);
-       buffer_put_char(&b, SSH2_MSG_KEXINIT);
-       buffer_append(&b, ckexinit, ckexinitlen);
-       buffer_put_int(&b, skexinitlen+1);
-       buffer_put_char(&b, SSH2_MSG_KEXINIT);
-       buffer_append(&b, skexinit, skexinitlen);
-
-       buffer_put_string(&b, serverhostkeyblob, sbloblen);
-       buffer_put_bignum2(&b, client_dh_pub);
-       buffer_put_bignum2(&b, server_dh_pub);
-       buffer_put_bignum2(&b, shared_secret);
-
-#ifdef DEBUG_KEX
-       buffer_dump(&b);
-#endif
+        error("Hm, kex protocol error: type %d plen %d", type, plen);
+}
 
-       EVP_DigestInit(&md, evp_md);
-       EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b));
-       EVP_DigestFinal(&md, digest, NULL);
+void
+kex_send_newkeys(void)
+{
+       packet_start(SSH2_MSG_NEWKEYS);
+       packet_send();
+       /* packet_write_wait(); */
+       debug("SSH2_MSG_NEWKEYS sent");
+}
 
-       buffer_free(&b);
+void
+kex_input_newkeys(int type, int plen, void *ctxt)
+{
+       Kex *kex = ctxt;
+       int i;
 
-#ifdef DEBUG_KEX
-       dump_digest(digest, evp_md->md_size);
-#endif
-       return digest;
+       debug("SSH2_MSG_NEWKEYS received");
+       kex->newkeys = 1;
+       for (i = 30; i <= 49; i++)
+               dispatch_set(i, &kex_protocol_error);
+       buffer_clear(&kex->peer);
+       buffer_clear(&kex->my);
+       kex->flags &= ~KEX_INIT_SENT;
 }
 
-u_char *
-kex_hash_gex(
-    char *client_version_string,
-    char *server_version_string,
-    char *ckexinit, int ckexinitlen,
-    char *skexinit, int skexinitlen,
-    char *serverhostkeyblob, int sbloblen,
-    int min, int wantbits, int max, BIGNUM *prime, BIGNUM *gen,
-    BIGNUM *client_dh_pub,
-    BIGNUM *server_dh_pub,
-    BIGNUM *shared_secret)
+void
+kex_send_kexinit(Kex *kex)
 {
-       Buffer b;
-       static u_char digest[EVP_MAX_MD_SIZE];
-       EVP_MD *evp_md = EVP_sha1();
-       EVP_MD_CTX md;
-
-       buffer_init(&b);
-       buffer_put_string(&b, client_version_string, strlen(client_version_string));
-       buffer_put_string(&b, server_version_string, strlen(server_version_string));
-
-       /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */
-       buffer_put_int(&b, ckexinitlen+1);
-       buffer_put_char(&b, SSH2_MSG_KEXINIT);
-       buffer_append(&b, ckexinit, ckexinitlen);
-       buffer_put_int(&b, skexinitlen+1);
-       buffer_put_char(&b, SSH2_MSG_KEXINIT);
-       buffer_append(&b, skexinit, skexinitlen);
-
-       buffer_put_string(&b, serverhostkeyblob, sbloblen);
-       if (min == -1 || max == -1) 
-               buffer_put_int(&b, wantbits);
-       else {
-               buffer_put_int(&b, min);
-               buffer_put_int(&b, wantbits);
-               buffer_put_int(&b, max);
-       }
-       buffer_put_bignum2(&b, prime);
-       buffer_put_bignum2(&b, gen);
-       buffer_put_bignum2(&b, client_dh_pub);
-       buffer_put_bignum2(&b, server_dh_pub);
-       buffer_put_bignum2(&b, shared_secret);
+       packet_start(SSH2_MSG_KEXINIT);
+       packet_put_raw(buffer_ptr(&kex->my), buffer_len(&kex->my));
+       packet_send();
+       debug("SSH2_MSG_KEXINIT sent");
+       kex->flags |= KEX_INIT_SENT;
+}
 
-#ifdef DEBUG_KEX
-       buffer_dump(&b);
-#endif
+void
+kex_input_kexinit(int type, int plen, void *ctxt)
+{
+       char *ptr;
+       int dlen;
+       Kex *kex = (Kex *)ctxt;
 
-       EVP_DigestInit(&md, evp_md);
-       EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b));
-       EVP_DigestFinal(&md, digest, NULL);
+       dispatch_set(SSH2_MSG_KEXINIT, &kex_protocol_error);
+       debug("SSH2_MSG_KEXINIT received");
 
-       buffer_free(&b);
+       ptr = packet_get_raw(&dlen);
+       buffer_append(&kex->peer, ptr, dlen);
 
-#ifdef DEBUG_KEX
-       dump_digest(digest, evp_md->md_size);
-#endif
-       return digest;
+       kex_kexinit_finish(kex);
 }
 
-u_char *
-derive_key(int id, int need, u_char *hash, BIGNUM *shared_secret)
+Kex *
+kex_start(char *proposal[PROPOSAL_MAX])
 {
-       Buffer b;
-       EVP_MD *evp_md = EVP_sha1();
-       EVP_MD_CTX md;
-       char c = id;
-       int have;
-       int mdsz = evp_md->md_size;
-       u_char *digest = xmalloc(((need+mdsz-1)/mdsz)*mdsz);
-
-       buffer_init(&b);
-       buffer_put_bignum2(&b, shared_secret);
+       Kex *kex;
+       int i;
 
-       EVP_DigestInit(&md, evp_md);
-       EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b));  /* shared_secret K */
-       EVP_DigestUpdate(&md, hash, mdsz);              /* transport-06 */
-       EVP_DigestUpdate(&md, &c, 1);                   /* key id */
-       EVP_DigestUpdate(&md, hash, mdsz);              /* session id */
-       EVP_DigestFinal(&md, digest, NULL);
+       kex = xmalloc(sizeof(*kex));
+       memset(kex, 0, sizeof(*kex));
+       buffer_init(&kex->peer);
+       buffer_init(&kex->my);
+       kex_prop2buf(&kex->my, proposal);
+       kex->newkeys = 0;
+
+       kex_send_kexinit(kex);                                  /* we start */
+       /* Numbers 30-49 are used for kex packets */
+       for (i = 30; i <= 49; i++)
+               dispatch_set(i, kex_protocol_error);
+
+       dispatch_set(SSH2_MSG_KEXINIT, &kex_input_kexinit);
+       dispatch_set(SSH2_MSG_NEWKEYS, &kex_input_newkeys);
+       return kex;
+}
 
-       /* expand */
-       for (have = mdsz; need > have; have += mdsz) {
-               EVP_DigestInit(&md, evp_md);
-               EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b));
-               EVP_DigestUpdate(&md, hash, mdsz);
-               EVP_DigestUpdate(&md, digest, have);
-               EVP_DigestFinal(&md, digest + have, NULL);
+void
+kex_kexinit_finish(Kex *kex)
+{
+       if (!(kex->flags & KEX_INIT_SENT))
+               kex_send_kexinit(kex);
+
+       kex_choose_conf(kex);
+
+       switch(kex->kex_type) {
+       case DH_GRP1_SHA1:
+               kexdh(kex);
+               break;
+       case DH_GEX_SHA1:
+               kexgex(kex);
+               break;
+       default:
+               fatal("Unsupported key exchange %d", kex->kex_type);
        }
-       buffer_free(&b);
-#ifdef DEBUG_KEX
-       fprintf(stderr, "Digest '%c'== ", c);
-       dump_digest(digest, need);
-#endif
-       return digest;
 }
 
 void
@@ -340,17 +273,25 @@ choose_hostkeyalg(Kex *k, char *client, char *server)
        xfree(hostkeyalg);
 }
 
-Kex *
-kex_choose_conf(char *cprop[PROPOSAL_MAX], char *sprop[PROPOSAL_MAX], int server)
+void
+kex_choose_conf(Kex *k)
 {
+       char **my, **peer;
+       char **cprop, **sprop;
        int mode;
        int ctos;                               /* direction: if true client-to-server */
        int need;
-       Kex *k;
 
-       k = xmalloc(sizeof(*k));
-       memset(k, 0, sizeof(*k));
-       k->server = server;
+       my   = kex_buf2prop(&k->my);
+       peer = kex_buf2prop(&k->peer);
+
+       if (k->server) {
+               cprop=peer;
+               sprop=my;
+       } else {
+               cprop=my;
+               sprop=peer;
+       }
 
        for (mode = 0; mode < MODE_MAX; mode++) {
                int nenc, nmac, ncomp;
@@ -381,11 +322,51 @@ kex_choose_conf(char *cprop[PROPOSAL_MAX], char *sprop[PROPOSAL_MAX], int server
        }
        /* XXX need runden? */
        k->we_need = need;
-       return k;
+
+       kex_prop_free(my);
+       kex_prop_free(peer);
+
+}
+
+u_char *
+derive_key(int id, int need, u_char *hash, BIGNUM *shared_secret)
+{
+       Buffer b;
+       EVP_MD *evp_md = EVP_sha1();
+       EVP_MD_CTX md;
+       char c = id;
+       int have;
+       int mdsz = evp_md->md_size;
+       u_char *digest = xmalloc(((need+mdsz-1)/mdsz)*mdsz);
+
+       buffer_init(&b);
+       buffer_put_bignum2(&b, shared_secret);
+
+       EVP_DigestInit(&md, evp_md);
+       EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b));  /* shared_secret K */
+       EVP_DigestUpdate(&md, hash, mdsz);              /* transport-06 */
+       EVP_DigestUpdate(&md, &c, 1);                   /* key id */
+       EVP_DigestUpdate(&md, hash, mdsz);              /* session id */
+       EVP_DigestFinal(&md, digest, NULL);
+
+       /* expand */
+       for (have = mdsz; need > have; have += mdsz) {
+               EVP_DigestInit(&md, evp_md);
+               EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b));
+               EVP_DigestUpdate(&md, hash, mdsz);
+               EVP_DigestUpdate(&md, digest, have);
+               EVP_DigestFinal(&md, digest + have, NULL);
+       }
+       buffer_free(&b);
+#ifdef DEBUG_KEX
+       fprintf(stderr, "key '%c'== ", c);
+       dump_digest("key", digest, need);
+#endif
+       return digest;
 }
 
 #define NKEYS  6
-int
+void
 kex_derive_keys(Kex *k, u_char *hash, BIGNUM *shared_secret)
 {
        int i;
@@ -402,5 +383,22 @@ kex_derive_keys(Kex *k, u_char *hash, BIGNUM *shared_secret)
                k->enc[mode].key = keys[ctos ? 2 : 3];
                k->mac[mode].key = keys[ctos ? 4 : 5];
        }
-       return 0;
 }
+
+#if defined(DEBUG_KEX) || defined(DEBUG_KEXDH)
+void
+dump_digest(char *msg, u_char *digest, int len)
+{
+       int i;
+
+       fprintf(stderr, "%s\n", msg);
+       for (i = 0; i< len; i++){
+               fprintf(stderr, "%02x", digest[i]);
+               if (i%32 == 31)
+                       fprintf(stderr, "\n");
+               else if (i%8 == 7)
+                       fprintf(stderr, " ");
+       }
+       fprintf(stderr, "\n");
+}
+#endif
diff --git a/kex.h b/kex.h
index 4cc87d52707bdf42baa60ed9ee1ccf44c5fee5dc..58f6d82c0b2d725bb6bf49b30aadec088123686b 100644 (file)
--- a/kex.h
+++ b/kex.h
@@ -1,4 +1,4 @@
-/*     $OpenBSD: kex.h,v 1.17 2001/03/29 21:17:40 markus Exp $ */
+/*     $OpenBSD: kex.h,v 1.18 2001/04/03 19:53:29 markus Exp $ */
 
 /*
  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
@@ -28,6 +28,8 @@
 
 #include <openssl/evp.h>
 #include "buffer.h"
+#include "cipher.h"
+#include "key.h"
 
 #define        KEX_DH1         "diffie-hellman-group1-sha1"
 #define        KEX_DHGEX       "diffie-hellman-group-exchange-sha1"
@@ -82,6 +84,7 @@ struct Comp {
        int             enabled;
        char            *name;
 };
+#define KEX_INIT_SENT  0x0001
 struct Kex {
        Enc             enc [MODE_MAX];
        Mac             mac [MODE_MAX];
@@ -91,40 +94,31 @@ struct Kex {
        char            *name;
        int             hostkey_type;
        int             kex_type;
+
+       /* used during kex */
+       Buffer          my;
+       Buffer          peer;
+       int             newkeys;
+       int             flags;
+       void            *state;
+       char            *client_version_string;
+       char            *server_version_string;
+
+       int             (*check_host_key)(Key *hostkey);
+       Key             *(*load_host_key)(int type);
 };
 
-Buffer *kex_init(char *myproposal[PROPOSAL_MAX]);
-void
-kex_exchange_kexinit(
-    Buffer *my_kexinit, Buffer *peer_kexint,
-    char *peer_proposal[PROPOSAL_MAX]);
-Kex *
-kex_choose_conf(char *cprop[PROPOSAL_MAX],
-    char *sprop[PROPOSAL_MAX], int server);
-int    kex_derive_keys(Kex *k, u_char *hash, BIGNUM *shared_secret);
+void   kex_derive_keys(Kex *k, u_char *hash, BIGNUM *shared_secret);
 void   packet_set_kex(Kex *k);
+Kex    *kex_start(char *proposal[PROPOSAL_MAX]);
+void   kex_send_newkeys(void);
+void   kex_protocol_error(int type, int plen, void *ctxt);
 
-u_char *
-kex_hash(
-    char *client_version_string,
-    char *server_version_string,
-    char *ckexinit, int ckexinitlen,
-    char *skexinit, int skexinitlen,
-    char *serverhostkeyblob, int sbloblen,
-    BIGNUM *client_dh_pub,
-    BIGNUM *server_dh_pub,
-    BIGNUM *shared_secret);
+void   kexdh(Kex *);
+void   kexgex(Kex *);
+
+#if defined(DEBUG_KEX) || defined(DEBUG_KEXDH)
+void   dump_digest(char *msg, u_char *digest, int len);
+#endif
 
-u_char *
-kex_hash_gex(
-    char *client_version_string,
-    char *server_version_string,
-    char *ckexinit, int ckexinitlen,
-    char *skexinit, int skexinitlen,
-    char *serverhostkeyblob, int sbloblen,
-    int min, int wantbits, int max,
-    BIGNUM *prime, BIGNUM *gen,
-    BIGNUM *client_dh_pub,
-    BIGNUM *server_dh_pub,
-    BIGNUM *shared_secret);
 #endif
index 460d614f04928c677157ee29203a4e8e48e3a5ff..4ed39a23ee641eab3990a1748ff334c54708b62f 100644 (file)
@@ -23,7 +23,7 @@
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: sshconnect2.c,v 1.60 2001/03/29 21:06:21 stevesk Exp $");
+RCSID("$OpenBSD: sshconnect2.c,v 1.61 2001/04/03 19:53:29 markus Exp $");
 
 #include <openssl/bn.h>
 #include <openssl/md5.h>
@@ -47,15 +47,12 @@ RCSID("$OpenBSD: sshconnect2.c,v 1.60 2001/03/29 21:06:21 stevesk Exp $");
 #include "authfile.h"
 #include "cli.h"
 #include "dh.h"
-#include "dispatch.h"
 #include "authfd.h"
 #include "log.h"
 #include "readconf.h"
 #include "readpass.h"
 #include "match.h"
-
-void ssh_dh1_client(Kex *, char *, struct sockaddr *, Buffer *, Buffer *);
-void ssh_dhgex_client(Kex *, char *, struct sockaddr *, Buffer *, Buffer *);
+#include "dispatch.h"
 
 /* import */
 extern char *client_version_string;
@@ -69,13 +66,24 @@ extern Options options;
 u_char *session_id2 = NULL;
 int session_id2_len = 0;
 
+char *xxx_host;
+struct sockaddr *xxx_hostaddr;
+
+int
+check_host_key_callback(Key *hostkey)
+{
+       check_host_key(xxx_host, xxx_hostaddr, hostkey,
+           options.user_hostfile2, options.system_hostfile2);
+       return 0;
+}
+
 void
 ssh_kex2(char *host, struct sockaddr *hostaddr)
 {
-       int i, plen;
        Kex *kex;
-       Buffer *client_kexinit, *server_kexinit;
-       char *sprop[PROPOSAL_MAX];
+
+       xxx_host = host;
+       xxx_hostaddr = hostaddr;
 
        if (options.ciphers == (char *)-1) {
                log("No valid ciphers for protocol version 2 given, using defaults.");
@@ -101,46 +109,13 @@ ssh_kex2(char *host, struct sockaddr *hostaddr)
                myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs;
        }
 
-       /* buffers with raw kexinit messages */
-       server_kexinit = xmalloc(sizeof(*server_kexinit));
-       buffer_init(server_kexinit);
-       client_kexinit = kex_init(myproposal);
-
-       /* algorithm negotiation */
-       kex_exchange_kexinit(client_kexinit, server_kexinit, sprop);
-       kex = kex_choose_conf(myproposal, sprop, 0);
-       for (i = 0; i < PROPOSAL_MAX; i++)
-               xfree(sprop[i]);
-
-       /* server authentication and session key agreement */
-       switch(kex->kex_type) {
-       case DH_GRP1_SHA1:
-               ssh_dh1_client(kex, host, hostaddr,
-                              client_kexinit, server_kexinit);
-               break;
-       case DH_GEX_SHA1:
-               ssh_dhgex_client(kex, host, hostaddr, client_kexinit,
-                                server_kexinit);
-               break;
-       default:
-               fatal("Unsupported key exchange %d", kex->kex_type);
-       }
-
-       buffer_free(client_kexinit);
-       buffer_free(server_kexinit);
-       xfree(client_kexinit);
-       xfree(server_kexinit);
+       kex = kex_start(myproposal);
+       kex->client_version_string=client_version_string;
+       kex->server_version_string=server_version_string;
+       kex->check_host_key=&check_host_key_callback;
 
-       debug("Wait SSH2_MSG_NEWKEYS.");
-       packet_read_expect(&plen, SSH2_MSG_NEWKEYS);
-       packet_done();
-       debug("GOT SSH2_MSG_NEWKEYS.");
-
-       debug("send SSH2_MSG_NEWKEYS.");
-       packet_start(SSH2_MSG_NEWKEYS);
-       packet_send();
-       packet_write_wait();
-       debug("done: send SSH2_MSG_NEWKEYS.");
+       /* start key exchange */
+       dispatch_run(DISPATCH_BLOCK, &kex->newkeys, kex);
 
 #ifdef DEBUG_KEXDH
        /* send 1st encrypted/maced/compressed message */
@@ -149,339 +124,7 @@ ssh_kex2(char *host, struct sockaddr *hostaddr)
        packet_send();
        packet_write_wait();
 #endif
-       debug("done: KEX2.");
-}
-
-/* diffie-hellman-group1-sha1 */
-
-void
-ssh_dh1_client(Kex *kex, char *host, struct sockaddr *hostaddr,
-              Buffer *client_kexinit, Buffer *server_kexinit)
-{
-#ifdef DEBUG_KEXDH
-       int i;
-#endif
-       int plen, dlen;
-       u_int klen, kout;
-       char *signature = NULL;
-       u_int slen;
-       char *server_host_key_blob = NULL;
-       Key *server_host_key;
-       u_int sbloblen;
-       DH *dh;
-       BIGNUM *dh_server_pub = 0;
-       BIGNUM *shared_secret = 0;
-       u_char *kbuf;
-       u_char *hash;
-
-       debug("Sending SSH2_MSG_KEXDH_INIT.");
-       /* generate and send 'e', client DH public key */
-       dh = dh_new_group1();
-       dh_gen_key(dh, kex->we_need * 8);
-       packet_start(SSH2_MSG_KEXDH_INIT);
-       packet_put_bignum2(dh->pub_key);
-       packet_send();
-       packet_write_wait();
-
-#ifdef DEBUG_KEXDH
-       fprintf(stderr, "\np= ");
-       BN_print_fp(stderr, dh->p);
-       fprintf(stderr, "\ng= ");
-       BN_print_fp(stderr, dh->g);
-       fprintf(stderr, "\npub= ");
-       BN_print_fp(stderr, dh->pub_key);
-       fprintf(stderr, "\n");
-       DHparams_print_fp(stderr, dh);
-#endif
-
-       debug("Wait SSH2_MSG_KEXDH_REPLY.");
-
-       packet_read_expect(&plen, SSH2_MSG_KEXDH_REPLY);
-
-       debug("Got SSH2_MSG_KEXDH_REPLY.");
-
-       /* key, cert */
-       server_host_key_blob = packet_get_string(&sbloblen);
-       server_host_key = key_from_blob(server_host_key_blob, sbloblen);
-       if (server_host_key == NULL)
-               fatal("cannot decode server_host_key_blob");
-
-       check_host_key(host, hostaddr, server_host_key,
-                      options.user_hostfile2, options.system_hostfile2);
-
-       /* DH paramter f, server public DH key */
-       dh_server_pub = BN_new();
-       if (dh_server_pub == NULL)
-               fatal("dh_server_pub == NULL");
-       packet_get_bignum2(dh_server_pub, &dlen);
-
-#ifdef DEBUG_KEXDH
-       fprintf(stderr, "\ndh_server_pub= ");
-       BN_print_fp(stderr, dh_server_pub);
-       fprintf(stderr, "\n");
-       debug("bits %d", BN_num_bits(dh_server_pub));
-#endif
-
-       /* signed H */
-       signature = packet_get_string(&slen);
-       packet_done();
-
-       if (!dh_pub_is_valid(dh, dh_server_pub))
-               packet_disconnect("bad server public DH value");
-
-       klen = DH_size(dh);
-       kbuf = xmalloc(klen);
-       kout = DH_compute_key(kbuf, dh_server_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);
-
-       /* calc and verify H */
-       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),
-           server_host_key_blob, sbloblen,
-           dh->pub_key,
-           dh_server_pub,
-           shared_secret
-       );
-       xfree(server_host_key_blob);
-       DH_free(dh);
-       BN_free(dh_server_pub);
-#ifdef DEBUG_KEXDH
-       fprintf(stderr, "hash == ");
-       for (i = 0; i< 20; i++)
-               fprintf(stderr, "%02x", (hash[i])&0xff);
-       fprintf(stderr, "\n");
-#endif
-       if (key_verify(server_host_key, (u_char *)signature, slen, hash, 20) != 1)
-               fatal("key_verify failed for server_host_key");
-       key_free(server_host_key);
-       xfree(signature);
-
-       kex_derive_keys(kex, hash, shared_secret);
-       BN_clear_free(shared_secret);
-       packet_set_kex(kex);
-
-       /* save session id */
-       session_id2_len = 20;
-       session_id2 = xmalloc(session_id2_len);
-       memcpy(session_id2, hash, session_id2_len);
-}
-
-/* diffie-hellman-group-exchange-sha1 */
-
-/*
- * Estimates the group order for a Diffie-Hellman group that has an
- * attack complexity approximately the same as O(2**bits).  Estimate
- * with:  O(exp(1.9223 * (ln q)^(1/3) (ln ln q)^(2/3)))
- */
-
-int
-dh_estimate(int bits)
-{
-
-       if (bits < 64)
-               return (512);   /* O(2**63) */
-       if (bits < 128)
-               return (1024);  /* O(2**86) */
-       if (bits < 192)
-               return (2048);  /* O(2**116) */
-       return (4096);          /* O(2**156) */
-}
-
-void
-ssh_dhgex_client(Kex *kex, char *host, struct sockaddr *hostaddr,
-                Buffer *client_kexinit, Buffer *server_kexinit)
-{
-#ifdef DEBUG_KEXDH
-       int i;
-#endif
-       int plen, dlen;
-       u_int klen, kout;
-       char *signature = NULL;
-       u_int slen, nbits, min, max;
-       char *server_host_key_blob = NULL;
-       Key *server_host_key;
-       u_int sbloblen;
-       DH *dh;
-       BIGNUM *dh_server_pub = 0;
-       BIGNUM *shared_secret = 0;
-       BIGNUM *p = 0, *g = 0;
-       u_char *kbuf;
-       u_char *hash;
-
-       nbits = dh_estimate(kex->we_need * 8);
-
-       if (datafellows & SSH_OLD_DHGEX) {
-               debug("Sending SSH2_MSG_KEX_DH_GEX_REQUEST_OLD.");
-
-               /* Old GEX request */
-               packet_start(SSH2_MSG_KEX_DH_GEX_REQUEST_OLD);
-               packet_put_int(nbits);
-               min = DH_GRP_MIN;
-               max = DH_GRP_MAX;
-       } else {
-               debug("Sending SSH2_MSG_KEX_DH_GEX_REQUEST.");
-
-               /* New GEX request */
-               min = DH_GRP_MIN;
-               max = DH_GRP_MAX;
-
-               packet_start(SSH2_MSG_KEX_DH_GEX_REQUEST);
-               packet_put_int(min);
-               packet_put_int(nbits);
-               packet_put_int(max);
-       }
-       packet_send();
-       packet_write_wait();
-
-#ifdef DEBUG_KEXDH
-       fprintf(stderr, "\nmin = %d, nbits = %d, max = %d", min, nbits, max);
-#endif
-
-       debug("Wait SSH2_MSG_KEX_DH_GEX_GROUP.");
-
-       packet_read_expect(&plen, SSH2_MSG_KEX_DH_GEX_GROUP);
-
-       debug("Got SSH2_MSG_KEX_DH_GEX_GROUP.");
-
-       if ((p = BN_new()) == NULL)
-               fatal("BN_new");
-       packet_get_bignum2(p, &dlen);
-       if ((g = BN_new()) == NULL)
-               fatal("BN_new");
-       packet_get_bignum2(g, &dlen);
-
-       if (BN_num_bits(p) < min || BN_num_bits(p) > max)
-               fatal("DH_GEX group out of range: %d !< %d !< %d",
-                   min, BN_num_bits(p), max);
-
-       dh = dh_new_group(g, p);
-
-       dh_gen_key(dh, kex->we_need * 8);
-
-#ifdef DEBUG_KEXDH
-       fprintf(stderr, "\np= ");
-       BN_print_fp(stderr, dh->p);
-       fprintf(stderr, "\ng= ");
-       BN_print_fp(stderr, dh->g);
-       fprintf(stderr, "\npub= ");
-       BN_print_fp(stderr, dh->pub_key);
-       fprintf(stderr, "\n");
-       DHparams_print_fp(stderr, dh);
-#endif
-
-       debug("Sending SSH2_MSG_KEX_DH_GEX_INIT.");
-       /* generate and send 'e', client DH public key */
-       packet_start(SSH2_MSG_KEX_DH_GEX_INIT);
-       packet_put_bignum2(dh->pub_key);
-       packet_send();
-       packet_write_wait();
-
-       debug("Wait SSH2_MSG_KEX_DH_GEX_REPLY.");
-
-       packet_read_expect(&plen, SSH2_MSG_KEX_DH_GEX_REPLY);
-
-       debug("Got SSH2_MSG_KEXDH_REPLY.");
-
-       /* key, cert */
-       server_host_key_blob = packet_get_string(&sbloblen);
-       server_host_key = key_from_blob(server_host_key_blob, sbloblen);
-       if (server_host_key == NULL)
-               fatal("cannot decode server_host_key_blob");
-
-       check_host_key(host, hostaddr, server_host_key,
-                      options.user_hostfile2, options.system_hostfile2);
-
-       /* DH paramter f, server public DH key */
-       dh_server_pub = BN_new();
-       if (dh_server_pub == NULL)
-               fatal("dh_server_pub == NULL");
-       packet_get_bignum2(dh_server_pub, &dlen);
-
-#ifdef DEBUG_KEXDH
-       fprintf(stderr, "\ndh_server_pub= ");
-       BN_print_fp(stderr, dh_server_pub);
-       fprintf(stderr, "\n");
-       debug("bits %d", BN_num_bits(dh_server_pub));
-#endif
-
-       /* signed H */
-       signature = packet_get_string(&slen);
-       packet_done();
-
-       if (!dh_pub_is_valid(dh, dh_server_pub))
-               packet_disconnect("bad server public DH value");
-
-       klen = DH_size(dh);
-       kbuf = xmalloc(klen);
-       kout = DH_compute_key(kbuf, dh_server_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);
-
-       if (datafellows & SSH_OLD_DHGEX) {
-               /* These values are not included in the hash */
-               min = -1;
-               max = -1;
-       }
-
-       /* calc and verify H */
-       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),
-           server_host_key_blob, sbloblen,
-           min, nbits, max,
-           dh->p, dh->g,
-           dh->pub_key,
-           dh_server_pub,
-           shared_secret
-       );
-       xfree(server_host_key_blob);
-       DH_free(dh);
-       BN_free(dh_server_pub);
-#ifdef DEBUG_KEXDH
-       fprintf(stderr, "hash == ");
-       for (i = 0; i< 20; i++)
-               fprintf(stderr, "%02x", (hash[i])&0xff);
-       fprintf(stderr, "\n");
-#endif
-       if (key_verify(server_host_key, (u_char *)signature, slen, hash, 20) != 1)
-               fatal("key_verify failed for server_host_key");
-       key_free(server_host_key);
-       xfree(signature);
-
-       kex_derive_keys(kex, hash, shared_secret);
-       BN_clear_free(shared_secret);
-       packet_set_kex(kex);
-
-       /* save session id */
-       session_id2_len = 20;
-       session_id2 = xmalloc(session_id2_len);
-       memcpy(session_id2, hash, session_id2_len);
+       debug("done: ssh_kex2.");
 }
 
 /*
@@ -563,6 +206,7 @@ ssh_userauth2(const char *server_user, char *host)
        Authctxt authctxt;
        int type;
        int plen;
+       int i;
 
        if (options.challenge_reponse_authentication)
                options.kbd_interactive_authentication = 1;
@@ -603,7 +247,10 @@ ssh_userauth2(const char *server_user, char *host)
        /* initial userauth request */
        userauth_none(&authctxt);
 
-       dispatch_init(&input_userauth_error);
+       //dispatch_init(&input_userauth_error);
+        for (i = 50; i <= 254; i++) {
+                dispatch_set(i, &input_userauth_error);
+        }
        dispatch_set(SSH2_MSG_USERAUTH_SUCCESS, &input_userauth_success);
        dispatch_set(SSH2_MSG_USERAUTH_FAILURE, &input_userauth_failure);
        dispatch_set(SSH2_MSG_USERAUTH_BANNER, &input_userauth_banner);
diff --git a/sshd.c b/sshd.c
index b5e2d0f6f715e20a80e474e8b0efcf4a3ee8fd9a..c54675962188c30316dc40c62c2e3d097a01e4ff 100644 (file)
--- a/sshd.c
+++ b/sshd.c
@@ -40,7 +40,7 @@
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: sshd.c,v 1.185 2001/03/29 23:42:01 djm Exp $");
+RCSID("$OpenBSD: sshd.c,v 1.186 2001/04/03 19:53:29 markus Exp $");
 
 #include <openssl/dh.h>
 #include <openssl/bn.h>
@@ -70,6 +70,7 @@ RCSID("$OpenBSD: sshd.c,v 1.185 2001/03/29 23:42:01 djm Exp $");
 #include "canohost.h"
 #include "auth.h"
 #include "misc.h"
+#include "dispatch.h"
 
 #ifdef LIBWRAP
 #include <tcpd.h>
@@ -1407,14 +1408,7 @@ do_ssh1_kex(void)
 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] =
@@ -1431,36 +1425,14 @@ do_ssh2_kex(void)
        }
        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]);
-
-       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);
-       }
-
-       debug("send SSH2_MSG_NEWKEYS.");
-       packet_start(SSH2_MSG_NEWKEYS);
-       packet_send();
-       packet_write_wait();
-       debug("done: send SSH2_MSG_NEWKEYS.");
+       kex = kex_start(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;
 
-       debug("Wait SSH2_MSG_NEWKEYS.");
-       packet_read_expect(&payload_len, SSH2_MSG_NEWKEYS);
-       debug("GOT SSH2_MSG_NEWKEYS.");
+       /* start key exchange */
+       dispatch_run(DISPATCH_BLOCK, &kex->newkeys, kex);
 
 #ifdef DEBUG_KEXDH
        /* send 1st encrypted/maced/compressed message */
@@ -1469,316 +1441,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, type, min, max;
-       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.");
-       type = packet_read(&payload_len);
-       if (type != SSH2_MSG_KEX_DH_GEX_REQUEST_OLD &&
-           type != SSH2_MSG_KEX_DH_GEX_REQUEST)
-               packet_disconnect("Protocol error: expected type %d or %d, got %d",
-                   SSH2_MSG_KEX_DH_GEX_REQUEST_OLD,
-                   SSH2_MSG_KEX_DH_GEX_REQUEST,
-                   type);
-       if (type == SSH2_MSG_KEX_DH_GEX_REQUEST_OLD) {
-               nbits = packet_get_int();
-               min = DH_GRP_MIN;
-               max = DH_GRP_MAX;
-       } else {
-               min = packet_get_int();
-               nbits = packet_get_int();
-               max = packet_get_int();
-
-               min = MAX(DH_GRP_MIN, min);
-               max = MIN(DH_GRP_MAX, max);
-       }
-
-       if (max < min || nbits < min || max < nbits)
-               fatal("DH_GEX_REQUEST, bad parameters: %d !< %d !< %d",
-                   min, nbits, max);
-
-       dh = choose_dh(min, nbits, max);
-       if (dh == NULL)
-               packet_disconnect("Protocol error: no matching DH grp found");
-
-       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);
-
-       if (type == SSH2_MSG_KEX_DH_GEX_REQUEST_OLD) {
-               /* These values are not included in the hash */
-               min = -1;
-               max = -1;
-       }
-
-       /* 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,
-           min, nbits, max,
-           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.104193 seconds and 5 git commands to generate.