From 3455765983d7c609f6720fff879c8f1a273442f9 Mon Sep 17 00:00:00 2001 From: ben Date: Sat, 3 Sep 2005 13:41:43 +0000 Subject: [PATCH] Restructure things so that a single entry in the KEX preference list can correspond to multiple SSH-2 KEX algorithms. We already do the equivalent for cipher algorithms. git-svn-id: svn://svn.tartarus.org/sgt/putty@6262 cda61777-01e9-0310-a592-d414129be87e --- ssh.c | 30 ++++++++++++++++++------------ ssh.h | 11 ++++++++--- sshdh.c | 33 ++++++++++++++++++++++++++++++--- 3 files changed, 56 insertions(+), 18 deletions(-) diff --git a/ssh.c b/ssh.c index 763e1fdb..91bfa884 100644 --- a/ssh.c +++ b/ssh.c @@ -4996,7 +4996,7 @@ static int do_ssh2_transport(Ssh ssh, void *vin, int inlen, void *hkey; /* actual host key */ unsigned char exchange_hash[20]; int n_preferred_kex; - const struct ssh_kex *preferred_kex[KEX_MAX]; + const struct ssh_kexes *preferred_kex[KEX_MAX]; int n_preferred_ciphers; const struct ssh2_ciphers *preferred_ciphers[CIPHER_MAX]; const struct ssh_compress *preferred_comp; @@ -5119,12 +5119,14 @@ static int do_ssh2_transport(Ssh ssh, void *vin, int inlen, ssh2_pkt_addstring_start(s->pktout); commalist_started = 0; for (i = 0; i < s->n_preferred_kex; i++) { - const struct ssh_kex *k = s->preferred_kex[i]; + const struct ssh_kexes *k = s->preferred_kex[i]; if (!k) continue; /* warning flag */ - if (commalist_started) - ssh2_pkt_addstring_str(s->pktout, ","); - ssh2_pkt_addstring_str(s->pktout, s->preferred_kex[i]->name); - commalist_started = 1; + for (j = 0; j < k->nkexes; j++) { + if (commalist_started) + ssh2_pkt_addstring_str(s->pktout, ","); + ssh2_pkt_addstring_str(s->pktout, k->list[j]->name); + commalist_started = 1; + } } /* List server host key algorithms. */ ssh2_pkt_addstring_start(s->pktout); @@ -5241,13 +5243,17 @@ static int do_ssh2_transport(Ssh ssh, void *vin, int inlen, preferred = NULL; for (i = 0; i < s->n_preferred_kex; i++) { - const struct ssh_kex *k = s->preferred_kex[i]; + const struct ssh_kexes *k = s->preferred_kex[i]; if (!k) { s->warn_kex = TRUE; } else { - if (!preferred) preferred = k->name; - if (in_commasep_string(k->name, str, len)) - ssh->kex = k; + for (j = 0; j < k->nkexes; j++) { + if (!preferred) preferred = k->list[j]->name; + if (in_commasep_string(k->list[j]->name, str, len)) { + ssh->kex = k->list[j]; + break; + } + } } if (ssh->kex) break; @@ -5528,7 +5534,7 @@ static int do_ssh2_transport(Ssh ssh, void *vin, int inlen, set_busy_status(ssh->frontend, BUSY_NOT); hash_string(ssh->kex->hash, ssh->exhash, s->hostkeydata, s->hostkeylen); - if (ssh->kex == &ssh_diffiehellman_gex) { + if (!ssh->kex->pdata) { hash_uint32(ssh->kex->hash, ssh->exhash, s->pbits); hash_mpint(ssh->kex->hash, ssh->exhash, s->p); hash_mpint(ssh->kex->hash, ssh->exhash, s->g); @@ -5717,7 +5723,7 @@ static int do_ssh2_transport(Ssh ssh, void *vin, int inlen, */ freebn(s->f); freebn(s->K); - if (ssh->kex == &ssh_diffiehellman_gex) { + if (!ssh->kex->pdata) { freebn(s->g); freebn(s->p); } diff --git a/ssh.h b/ssh.h index 45405d3e..43060c92 100644 --- a/ssh.h +++ b/ssh.h @@ -206,6 +206,11 @@ struct ssh_kex { const struct ssh_hash *hash; }; +struct ssh_kexes { + int nkexes; + const struct ssh_kex *const *list; +}; + struct ssh_signkey { void *(*newkey) (char *data, int len); void (*freekey) (void *key); @@ -256,9 +261,9 @@ extern const struct ssh2_ciphers ssh2_blowfish; extern const struct ssh2_ciphers ssh2_arcfour; extern const struct ssh_hash ssh_sha1; extern const struct ssh_hash ssh_sha256; -extern const struct ssh_kex ssh_diffiehellman_group1; -extern const struct ssh_kex ssh_diffiehellman_group14; -extern const struct ssh_kex ssh_diffiehellman_gex; +extern const struct ssh_kexes ssh_diffiehellman_group1; +extern const struct ssh_kexes ssh_diffiehellman_group14; +extern const struct ssh_kexes ssh_diffiehellman_gex; extern const struct ssh_signkey ssh_dss; extern const struct ssh_signkey ssh_rsa; extern const struct ssh_mac ssh_hmac_md5; diff --git a/sshdh.c b/sshdh.c index 9d24908e..8d984625 100644 --- a/sshdh.c +++ b/sshdh.c @@ -46,21 +46,48 @@ static const unsigned char P14[] = { */ static const unsigned char G[] = { 2 }; -const struct ssh_kex ssh_diffiehellman_group1 = { +static const struct ssh_kex ssh_diffiehellman_group1_sha1 = { "diffie-hellman-group1-sha1", "group1", P1, G, lenof(P1), lenof(G), &ssh_sha1 }; -const struct ssh_kex ssh_diffiehellman_group14 = { +static const struct ssh_kex *const group1_list[] = { + &ssh_diffiehellman_group1_sha1 +}; + +const struct ssh_kexes ssh_diffiehellman_group1 = { + sizeof(group1_list) / sizeof(*group1_list), + group1_list +}; + +static const struct ssh_kex ssh_diffiehellman_group14_sha1 = { "diffie-hellman-group14-sha1", "group14", P14, G, lenof(P14), lenof(G), &ssh_sha1 }; -const struct ssh_kex ssh_diffiehellman_gex = { +static const struct ssh_kex *const group14_list[] = { + &ssh_diffiehellman_group14_sha1 +}; + +const struct ssh_kexes ssh_diffiehellman_group14 = { + sizeof(group14_list) / sizeof(*group14_list), + group14_list +}; + +static const struct ssh_kex ssh_diffiehellman_gex_sha1 = { "diffie-hellman-group-exchange-sha1", NULL, NULL, NULL, 0, 0, &ssh_sha1 }; +static const struct ssh_kex *const gex_list[] = { + &ssh_diffiehellman_gex_sha1 +}; + +const struct ssh_kexes ssh_diffiehellman_gex = { + sizeof(gex_list) / sizeof(*gex_list), + gex_list +}; + /* * Variables. */ -- 2.11.0