more strictly enforce KEX state-machine by banning packet types
authordjm <djm@openbsd.org>
Sun, 31 Jan 2021 22:55:29 +0000 (22:55 +0000)
committerdjm <djm@openbsd.org>
Sun, 31 Jan 2021 22:55:29 +0000 (22:55 +0000)
once they are received. Fixes memleak caused by duplicate
SSH2_MSG_KEX_DH_GEX_REQUEST (spotted by portable OpenSSH kex_fuzz
via oss-fuzz #30078).

ok markus@

usr.bin/ssh/kex.c
usr.bin/ssh/kex.h
usr.bin/ssh/kexgen.c
usr.bin/ssh/kexgexc.c
usr.bin/ssh/kexgexs.c

index 8f019d5..b218691 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: kex.c,v 1.166 2021/01/27 23:49:46 djm Exp $ */
+/* $OpenBSD: kex.c,v 1.167 2021/01/31 22:55:29 djm Exp $ */
 /*
  * Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved.
  *
@@ -390,7 +390,7 @@ kex_prop_free(char **proposal)
 }
 
 /* ARGSUSED */
-static int
+int
 kex_protocol_error(int type, u_int32_t seq, struct ssh *ssh)
 {
        int r;
index c81b491..212fd35 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: kex.h,v 1.113 2021/01/27 10:05:28 djm Exp $ */
+/* $OpenBSD: kex.h,v 1.114 2021/01/31 22:55:29 djm Exp $ */
 
 /*
  * Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved.
@@ -186,6 +186,7 @@ int  kex_verify_host_key(struct ssh *, struct sshkey *);
 int     kex_send_kexinit(struct ssh *);
 int     kex_input_kexinit(int, u_int32_t, struct ssh *);
 int     kex_input_ext_info(int, u_int32_t, struct ssh *);
+int     kex_protocol_error(int, u_int32_t, struct ssh *);
 int     kex_derive_keys(struct ssh *, u_char *, u_int, const struct sshbuf *);
 int     kex_send_newkeys(struct ssh *);
 int     kex_start_rekex(struct ssh *);
index 3f13982..bad1599 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: kexgen.c,v 1.5 2020/12/29 00:59:15 djm Exp $ */
+/* $OpenBSD: kexgen.c,v 1.6 2021/01/31 22:55:29 djm Exp $ */
 /*
  * Copyright (c) 2019 Markus Friedl.  All rights reserved.
  *
@@ -145,6 +145,9 @@ input_kex_gen_reply(int type, u_int32_t seq, struct ssh *ssh)
        size_t slen, hashlen;
        int r;
 
+       debug("SSH2_MSG_KEX_ECDH_REPLY received");
+       ssh_dispatch_set(ssh, SSH2_MSG_KEX_ECDH_REPLY, &kex_protocol_error);
+
        /* hostkey */
        if ((r = sshpkt_getb_froms(ssh, &server_host_key_blob)) != 0)
                goto out;
@@ -251,6 +254,9 @@ input_kex_gen_init(int type, u_int32_t seq, struct ssh *ssh)
        size_t slen, hashlen;
        int r;
 
+       debug("SSH2_MSG_KEX_ECDH_INIT received");
+       ssh_dispatch_set(ssh, SSH2_MSG_KEX_ECDH_INIT, &kex_protocol_error);
+
        if ((r = kex_load_hostkey(ssh, &server_host_private,
            &server_host_public)) != 0)
                goto out;
index 6e00904..75d843c 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: kexgexc.c,v 1.36 2021/01/27 09:26:54 djm Exp $ */
+/* $OpenBSD: kexgexc.c,v 1.37 2021/01/31 22:55:29 djm Exp $ */
 /*
  * Copyright (c) 2000 Niels Provos.  All rights reserved.
  * Copyright (c) 2001 Markus Friedl.  All rights reserved.
@@ -76,6 +76,7 @@ kexgex_client(struct ssh *ssh)
        fprintf(stderr, "\nmin = %d, nbits = %d, max = %d\n",
            kex->min, kex->nbits, kex->max);
 #endif
+       debug("expecting SSH2_MSG_KEX_DH_GEX_GROUP");
        ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_GROUP,
            &input_kex_dh_gex_group);
        r = 0;
@@ -91,7 +92,8 @@ input_kex_dh_gex_group(int type, u_int32_t seq, struct ssh *ssh)
        const BIGNUM *pub_key;
        int r, bits;
 
-       debug("got SSH2_MSG_KEX_DH_GEX_GROUP");
+       debug("SSH2_MSG_KEX_DH_GEX_GROUP received");
+       ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_GROUP, &kex_protocol_error);
 
        if ((r = sshpkt_get_bignum2(ssh, &p)) != 0 ||
            (r = sshpkt_get_bignum2(ssh, &g)) != 0 ||
@@ -123,7 +125,7 @@ input_kex_dh_gex_group(int type, u_int32_t seq, struct ssh *ssh)
        BN_print_fp(stderr, pub_key);
        fprintf(stderr, "\n");
 #endif
-       ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_GROUP, NULL);
+       debug("expecting SSH2_MSG_KEX_DH_GEX_REPLY");
        ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_REPLY, &input_kex_dh_gex_reply);
        r = 0;
 out:
@@ -146,7 +148,9 @@ input_kex_dh_gex_reply(int type, u_int32_t seq, struct ssh *ssh)
        size_t slen, hashlen;
        int r;
 
-       debug("got SSH2_MSG_KEX_DH_GEX_REPLY");
+       debug("SSH2_MSG_KEX_DH_GEX_REPLY received");
+       ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_REPLY, &kex_protocol_error);
+
        /* key, cert */
        if ((r = sshpkt_getb_froms(ssh, &server_host_key_blob)) != 0)
                goto out;
index eaaaab3..43c2410 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: kexgexs.c,v 1.42 2019/01/23 00:30:41 djm Exp $ */
+/* $OpenBSD: kexgexs.c,v 1.43 2021/01/31 22:55:29 djm Exp $ */
 /*
  * Copyright (c) 2000 Niels Provos.  All rights reserved.
  * Copyright (c) 2001 Markus Friedl.  All rights reserved.
@@ -70,6 +70,8 @@ input_kex_dh_gex_request(int type, u_int32_t seq, struct ssh *ssh)
        const BIGNUM *dh_p, *dh_g;
 
        debug("SSH2_MSG_KEX_DH_GEX_REQUEST received");
+       ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_REQUEST, &kex_protocol_error);
+
        if ((r = sshpkt_get_u32(ssh, &min)) != 0 ||
            (r = sshpkt_get_u32(ssh, &nbits)) != 0 ||
            (r = sshpkt_get_u32(ssh, &max)) != 0 ||
@@ -129,6 +131,9 @@ input_kex_dh_gex_init(int type, u_int32_t seq, struct ssh *ssh)
        size_t slen, hashlen;
        int r;
 
+       debug("SSH2_MSG_KEX_DH_GEX_INIT received");
+       ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_INIT, &kex_protocol_error);
+
        if ((r = kex_load_hostkey(ssh, &server_host_private,
            &server_host_public)) != 0)
                goto out;