From: djm Date: Sun, 31 Jan 2021 22:55:29 +0000 (+0000) Subject: more strictly enforce KEX state-machine by banning packet types X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=1c4876f5ca4b2d6c9f7a9242687874d938e3c3fd;p=openbsd more strictly enforce KEX state-machine by banning packet types 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@ --- diff --git a/usr.bin/ssh/kex.c b/usr.bin/ssh/kex.c index 8f019d51da5..b21869196bf 100644 --- a/usr.bin/ssh/kex.c +++ b/usr.bin/ssh/kex.c @@ -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; diff --git a/usr.bin/ssh/kex.h b/usr.bin/ssh/kex.h index c81b491188f..212fd35d56b 100644 --- a/usr.bin/ssh/kex.h +++ b/usr.bin/ssh/kex.h @@ -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 *); diff --git a/usr.bin/ssh/kexgen.c b/usr.bin/ssh/kexgen.c index 3f1398299d1..bad15994522 100644 --- a/usr.bin/ssh/kexgen.c +++ b/usr.bin/ssh/kexgen.c @@ -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; diff --git a/usr.bin/ssh/kexgexc.c b/usr.bin/ssh/kexgexc.c index 6e00904e58c..75d843c9c43 100644 --- a/usr.bin/ssh/kexgexc.c +++ b/usr.bin/ssh/kexgexc.c @@ -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; diff --git a/usr.bin/ssh/kexgexs.c b/usr.bin/ssh/kexgexs.c index eaaaab31834..43c2410d4a7 100644 --- a/usr.bin/ssh/kexgexs.c +++ b/usr.bin/ssh/kexgexs.c @@ -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;