From db1cd2f35eb5e9461364cbd56bdc7843df59444a Mon Sep 17 00:00:00 2001 From: mouring Date: Thu, 29 Mar 2001 00:36:16 +0000 Subject: [PATCH] - provos@cvs.openbsd.org 2001/03/27 17:46:50 [compat.c compat.h dh.c dh.h ssh2.h sshconnect2.c sshd.c version.h] make dh group exchange more flexible, allow min and max group size, okay markus@, deraadt@ --- ChangeLog | 4 ++++ compat.c | 12 ++++++++---- compat.h | 3 ++- dh.c | 19 +++++++++++++------ dh.h | 7 +++++-- ssh2.h | 5 +++-- sshconnect2.c | 35 +++++++++++++++++++++++++++++------ sshd.c | 34 +++++++++++++++++++++++++++++----- version.h | 6 +++--- 9 files changed, 96 insertions(+), 29 deletions(-) diff --git a/ChangeLog b/ChangeLog index 57dba9a8..0dfde010 100644 --- a/ChangeLog +++ b/ChangeLog @@ -16,6 +16,10 @@ [compat.c compat.h ssh-rsa.c] some older systems use NID_md5 instead of NID_sha1 for RSASSA-PKCS1-v1_5 signatures in SSH protocol 2, ok djm@ + - provos@cvs.openbsd.org 2001/03/27 17:46:50 + [compat.c compat.h dh.c dh.h ssh2.h sshconnect2.c sshd.c version.h] + make dh group exchange more flexible, allow min and max group size, + okay markus@, deraadt@ 20010328 - (djm) Reorder tests and library inclusion for Krb4/AFS to try to diff --git a/compat.c b/compat.c index 98372e20..686016f8 100644 --- a/compat.c +++ b/compat.c @@ -23,7 +23,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: compat.c,v 1.41 2001/03/27 10:57:00 markus Exp $"); +RCSID("$OpenBSD: compat.c,v 1.42 2001/03/27 17:46:49 provos Exp $"); #ifdef HAVE_LIBPCRE # include @@ -68,10 +68,14 @@ compat_datafellows(const char *version) int bugs; } check[] = { { "^OpenSSH[-_]2\\.[012]", - SSH_OLD_SESSIONID|SSH_BUG_BANNER }, - { "^OpenSSH_2\\.3\\.0", SSH_BUG_BANNER|SSH_BUG_BIGENDIANAES }, + SSH_OLD_SESSIONID|SSH_BUG_BANNER| + SSH_OLD_DHGEX }, + { "^OpenSSH_2\\.3\\.0", SSH_BUG_BANNER|SSH_BUG_BIGENDIANAES| + SSH_OLD_DHGEX}, { "^OpenSSH_2\\.5\\.[01]p1", - SSH_BUG_BIGENDIANAES }, + SSH_BUG_BIGENDIANAES|SSH_OLD_DHGEX }, + { "^OpenSSH_2\\.5\\.[012]", + SSH_OLD_DHGEX }, { "^OpenSSH", 0 }, { "MindTerm", 0 }, { "^2\\.1\\.0", SSH_BUG_SIGBLOB|SSH_BUG_HMAC| diff --git a/compat.h b/compat.h index 03f23611..e4ca5c1b 100644 --- a/compat.h +++ b/compat.h @@ -21,7 +21,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* RCSID("$OpenBSD: compat.h,v 1.20 2001/03/27 10:57:00 markus Exp $"); */ +/* RCSID("$OpenBSD: compat.h,v 1.21 2001/03/27 17:46:49 provos Exp $"); */ #ifndef COMPAT_H #define COMPAT_H @@ -45,6 +45,7 @@ #define SSH_BUG_SCANNER 0x0800 #define SSH_BUG_BIGENDIANAES 0x1000 #define SSH_BUG_RSASIGMD5 0x2000 +#define SSH_OLD_DHGEX 0x4000 void enable_compat13(void); void enable_compat20(void); diff --git a/dh.c b/dh.c index ac73f840..5f441ee1 100644 --- a/dh.c +++ b/dh.c @@ -23,7 +23,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: dh.c,v 1.8 2001/03/05 17:58:22 stevesk Exp $"); +RCSID("$OpenBSD: dh.c,v 1.9 2001/03/27 17:46:49 provos Exp $"); #include "xmalloc.h" @@ -69,6 +69,8 @@ parse_prime(int linenum, char *line, struct dhgroup *dhg) if (cp == NULL || *strsize == '\0' || (dhg->size = atoi(strsize)) == 0) goto fail; + /* The whole group is one bit larger */ + dhg->size++; gen = strsep(&cp, " "); /* gen */ if (cp == NULL || *gen == '\0') goto fail; @@ -95,7 +97,7 @@ parse_prime(int linenum, char *line, struct dhgroup *dhg) } DH * -choose_dh(int minbits) +choose_dh(int min, int wantbits, int max) { FILE *f; char line[1024]; @@ -118,8 +120,11 @@ choose_dh(int minbits) BN_free(dhg.g); BN_free(dhg.p); - if ((dhg.size > minbits && dhg.size < best) || - (dhg.size > best && best < minbits)) { + if (dhg.size > max || dhg.size < min) + continue; + + if ((dhg.size > wantbits && dhg.size < best) || + (dhg.size > best && best < wantbits)) { best = dhg.size; bestcount = 0; } @@ -129,8 +134,8 @@ choose_dh(int minbits) fclose (f); if (bestcount == 0) { - log("WARNING: no primes in %s, using old prime", _PATH_DH_PRIMES); - return (dh_new_group1()); + log("WARNING: no suitable primes in %s", _PATH_DH_PRIMES); + return (NULL); } f = fopen(_PATH_DH_PRIMES, "r"); @@ -143,6 +148,8 @@ choose_dh(int minbits) while (fgets(line, sizeof(line), f)) { if (!parse_prime(linenum, line, &dhg)) continue; + if (dhg.size > max || dhg.size < min) + continue; if (dhg.size != best) continue; if (linenum++ != which) { diff --git a/dh.h b/dh.h index f08d70e3..70b326e9 100644 --- a/dh.h +++ b/dh.h @@ -1,4 +1,4 @@ -/* $OpenBSD: dh.h,v 1.2 2001/01/29 01:58:15 niklas Exp $ */ +/* $OpenBSD: dh.h,v 1.3 2001/03/27 17:46:49 provos Exp $ */ /* * Copyright (c) 2000 Niels Provos. All rights reserved. @@ -32,6 +32,9 @@ struct dhgroup { BIGNUM *p; }; -DH *choose_dh(int minbits); +DH *choose_dh(int min, int nbits, int max); + +#define DH_GRP_MIN 1024 +#define DH_GRP_MAX 8192 #endif diff --git a/ssh2.h b/ssh2.h index fe0146cb..e45aef27 100644 --- a/ssh2.h +++ b/ssh2.h @@ -52,7 +52,7 @@ * * 192-255 Local extensions */ -/* RCSID("$OpenBSD: ssh2.h,v 1.5 2000/10/11 04:02:17 provos Exp $"); */ +/* RCSID("$OpenBSD: ssh2.h,v 1.6 2001/03/27 17:46:49 provos Exp $"); */ /* transport layer: generic */ @@ -74,10 +74,11 @@ #define SSH2_MSG_KEXDH_REPLY 31 /* dh-group-exchange */ -#define SSH2_MSG_KEX_DH_GEX_REQUEST 30 +#define SSH2_MSG_KEX_DH_GEX_REQUEST_OLD 30 #define SSH2_MSG_KEX_DH_GEX_GROUP 31 #define SSH2_MSG_KEX_DH_GEX_INIT 32 #define SSH2_MSG_KEX_DH_GEX_REPLY 33 +#define SSH2_MSG_KEX_DH_GEX_REQUEST 34 /* user authentication: generic */ diff --git a/sshconnect2.c b/sshconnect2.c index f636fb3d..da8c8229 100644 --- a/sshconnect2.c +++ b/sshconnect2.c @@ -23,7 +23,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: sshconnect2.c,v 1.56 2001/03/26 08:07:09 markus Exp $"); +RCSID("$OpenBSD: sshconnect2.c,v 1.57 2001/03/27 17:46:49 provos Exp $"); #include #include @@ -46,6 +46,7 @@ RCSID("$OpenBSD: sshconnect2.c,v 1.56 2001/03/26 08:07:09 markus Exp $"); #include "sshconnect.h" #include "authfile.h" #include "cli.h" +#include "dh.h" #include "dispatch.h" #include "authfd.h" #include "log.h" @@ -309,7 +310,7 @@ ssh_dhgex_client(Kex *kex, char *host, struct sockaddr *hostaddr, int plen, dlen; u_int klen, kout; char *signature = NULL; - u_int slen, nbits; + u_int slen, nbits, min, max; char *server_host_key_blob = NULL; Key *server_host_key; u_int sbloblen; @@ -322,14 +323,31 @@ ssh_dhgex_client(Kex *kex, char *host, struct sockaddr *hostaddr, nbits = dh_estimate(kex->we_need * 8); - debug("Sending SSH2_MSG_KEX_DH_GEX_REQUEST."); - packet_start(SSH2_MSG_KEX_DH_GEX_REQUEST); - packet_put_int(nbits); + 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 = MIN(DH_GRP_MAX, nbits * 1.25); + + 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, "\nnbits = %d", nbits); + fprintf(stderr, "\nmin = %d, nbits = %d, max = %d", min, nbits, max); #endif debug("Wait SSH2_MSG_KEX_DH_GEX_GROUP."); @@ -344,6 +362,11 @@ ssh_dhgex_client(Kex *kex, char *host, struct sockaddr *hostaddr, 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); diff --git a/sshd.c b/sshd.c index 961aeeaa..65cb832d 100644 --- a/sshd.c +++ b/sshd.c @@ -40,7 +40,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: sshd.c,v 1.180 2001/03/27 10:34:08 markus Exp $"); +RCSID("$OpenBSD: sshd.c,v 1.181 2001/03/27 17:46:49 provos Exp $"); #include #include @@ -1614,7 +1614,7 @@ ssh_dhgex_server(Kex *kex, Buffer *client_kexinit, Buffer *server_kexinit) int i; #endif int payload_len, dlen; - int slen, nbits; + int slen, nbits, type, min, max; u_char *signature = NULL; u_char *server_host_key_blob = NULL; u_int sbloblen; @@ -1632,9 +1632,33 @@ ssh_dhgex_server(Kex *kex, Buffer *client_kexinit, Buffer *server_kexinit) /* 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); + 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); diff --git a/version.h b/version.h index 8ece8d0e..bdf8c1d2 100644 --- a/version.h +++ b/version.h @@ -1,3 +1,3 @@ -/* $OpenBSD: version.h,v 1.20 2001/03/19 17:12:10 markus Exp $ */ - -#define SSH_VERSION "OpenSSH_2.5.2p1" +/* $OpenBSD: version.h,v 1.21 2001/03/27 17:46:50 provos Exp $ */ + +#define SSH_VERSION "OpenSSH_2.5.3p1" -- 2.45.2