]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MINOR: quic: drop multiple Retry on same connection master
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Fri, 7 Aug 2026 14:56:18 +0000 (16:56 +0200)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Fri, 7 Aug 2026 15:10:33 +0000 (17:10 +0200)
Ensures that only a single Retry packet is handled by a QUIC haproxy
client per connection. This is mandated by RFC 9000. The first received
token should still be sufficient to validate the connection.

This change is applied directly in quic_rx_pkt_parse(). In case of
multiple Retry, packets are silently ignored, whether token is identical
or not.

This fix is particularly important to prevent a memory leak on several
elements, first <retry_token> member of quic_conn. This also concerns
elements from the TLS stack as initial encryption level would be
reinitialized needlessly.

Reported-by: Claude (ANT-2026-CJ4Z875H)
This must be backported up to 3.3.

src/quic_rx.c

index 7cc1aaf14aae6e1ff972f762f8de48e193e98569..594bd293aef142b46727aa6c42c9e9fadb88adc2 100644 (file)
@@ -2062,6 +2062,19 @@ static int quic_rx_pkt_parse(struct quic_conn *qc, struct quic_rx_packet *pkt,
                                goto drop;
                        }
 
+                       /* RFC 9000 17.2.5.2. Handling a Retry Packet
+                        *
+                        * A client MUST accept and process at most one Retry packet for each
+                        * connection attempt. After the client has received and processed an
+                        * Initial or Retry packet from the server, it MUST discard any
+                        * subsequent Retry packets that it receives.
+                        */
+                       if (qc->retry_token) {
+                               TRACE_PROTO("Drop duplicate Retry packet",
+                                           QUIC_EV_CONN_LPKT, NULL, NULL, NULL, pkt->version);
+                               goto drop_silent;
+                       }
+
                        if (!quic_retry_packet_check(qc, pkt, beg, end, pos, &qc->retry_token_len))
                                /* TODO: should close the connection? */
                                goto drop;