]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
lib/buffers: ensure packets have differing sequence numbers
authorAlexander Sosedkin <asosedkin@redhat.com>
Tue, 21 Apr 2026 14:52:48 +0000 (16:52 +0200)
committerAlexander Sosedkin <asosedkin@redhat.com>
Wed, 29 Apr 2026 13:35:02 +0000 (15:35 +0200)
There should normally be no packets with same sequence number and
differing handshake type, unless an adversary crafts them.
Discarding them allows to get rid of packets
with duplicate sequence ID in the buffer,
relieving us from the question of how to sort them later.

Reported-by: Joshua Rogers of AISLE Research Team <joshua@joshua.hu>
Fixes: #1848
Fixes: CVE-2026-42009
Fixes: GNUTLS-SA-2026-04-29-2
CVSS: 7.5 High CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
lib/buffers.c

index 62f140ed3c1456cd050ed3be5ee24138d58a813d..48f4a3210c0693793639239aa0c29ce2c2521c60 100644 (file)
@@ -971,8 +971,20 @@ static int merge_handshake_packet(gnutls_session_t session,
                session->internals.handshake_recv_buffer;
 
        for (i = 0; i < session->internals.handshake_recv_buffer_size; i++) {
-               if (recv_buf[i].htype == hsk->htype &&
-                   recv_buf[i].sequence == hsk->sequence) {
+               if (recv_buf[i].sequence == hsk->sequence) {
+                       if (recv_buf[i].htype != hsk->htype) {
+                               _gnutls_audit_log(
+                                       session,
+                                       "Discarded unexpected handshake packet "
+                                       "with duplicate sequence %d, but "
+                                       "mismatched type %s (previously %s)\n",
+                                       hsk->sequence,
+                                       _gnutls_handshake2str(hsk->htype),
+                                       _gnutls_handshake2str(
+                                               recv_buf[i].htype));
+                               _gnutls_handshake_buffer_clear(hsk);
+                               return 0;
+                       }
                        exists = 1;
                        pos = i;
                        break;