]> git.ipfire.org Git - thirdparty/openssh-portable.git/commitdiff
upstream: make the transport protocol stricter by disconnecting if
authordjm@openbsd.org <djm@openbsd.org>
Sun, 31 May 2026 04:44:38 +0000 (04:44 +0000)
committerDamien Miller <djm@mindrot.org>
Sun, 31 May 2026 05:03:56 +0000 (15:03 +1000)
the peer sends non-KEX messages during a key re-exchange.

Previously an evil peer could continue sending non-KEX messages
without penalty, causing memory to be wasted up until the
connection terminated or the server/client hit a OOM limit.

reported by Marko Jevtic; ok markus@

OpenBSD-Commit-ID: 8937f0f2096156f5c68ae2dce77956373589d757

kex.c
kex.h
packet.c

diff --git a/kex.c b/kex.c
index 85b112c75f2156bb763b446a7c92f2aa93c4b499..11b271d474842a10ae8d355babcf820bc0c88fab 100644 (file)
--- a/kex.c
+++ b/kex.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kex.c,v 1.193 2026/03/05 05:40:35 djm Exp $ */
+/* $OpenBSD: kex.c,v 1.194 2026/05/31 04:44:38 djm Exp $ */
 /*
  * Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved.
  *
@@ -566,7 +566,7 @@ kex_input_newkeys(int type, uint32_t seq, struct ssh *ssh)
        kex->done = 1;
        kex->flags &= ~KEX_INITIAL;
        sshbuf_reset(kex->peer);
-       kex->flags &= ~KEX_INIT_SENT;
+       kex->flags &= ~(KEX_INIT_SENT|KEX_INIT_RECVD);
        return 0;
 }
 
@@ -624,6 +624,11 @@ kex_input_kexinit(int type, uint32_t seq, struct ssh *ssh)
        }
        free(kex->name);
        kex->name = NULL;
+       if ((kex->flags & KEX_INIT_RECVD) != 0) {
+               ssh_packet_disconnect(ssh,
+                   "multiple KEXINIT received from peer");
+       }
+       kex->flags |= KEX_INIT_RECVD;
        ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_protocol_error);
        ptr = sshpkt_ptr(ssh, &dlen);
        if ((r = sshbuf_put(kex->peer, ptr, dlen)) != 0)
diff --git a/kex.h b/kex.h
index 4f6d92164c7e82b8c52791490307994e903a2054..a4d50f1a3d24d3542c33da9f696a79fd3a95ac81 100644 (file)
--- a/kex.h
+++ b/kex.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: kex.h,v 1.129 2026/03/05 05:40:36 djm Exp $ */
+/* $OpenBSD: kex.h,v 1.130 2026/05/31 04:44:38 djm Exp $ */
 
 /*
  * Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved.
@@ -115,6 +115,7 @@ enum kex_exchange {
 #define KEX_HAS_PING                   0x0020
 #define KEX_HAS_EXT_INFO_IN_AUTH       0x0040
 #define KEX_HAS_NEWAGENT               0x0080 /* only set in client */
+#define KEX_INIT_RECVD                 0x0100
 
 /* kex->pq */
 #define KEX_NOT_PQ                     0
index 78316626fe661f5a08faafe31eac9631e917671b..8d8f73ca026345fcd43a0b8b1468979a4031b392 100644 (file)
--- a/packet.c
+++ b/packet.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: packet.c,v 1.337 2026/05/31 04:37:56 djm Exp $ */
+/* $OpenBSD: packet.c,v 1.338 2026/05/31 04:44:38 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -1949,6 +1949,13 @@ ssh_packet_read_poll_seqnr(struct ssh *ssh, u_char *typep, uint32_t *seqnr_p)
                        DBG(debug("Received SSH2_MSG_PONG len %zu", len));
                        break;
                default:
+                       if (ssh->kex != NULL &&
+                           (ssh->kex->flags & KEX_INIT_RECVD) != 0 &&
+                           !ssh_packet_type_is_kex(*typep)) {
+                               error("non-transport message %u received "
+                                   "from peer during key exchange", *typep);
+                               return SSH_ERR_PROTOCOL_ERROR;
+                       }
                        return 0;
                }
        }