From: Philippe Antoine Date: Fri, 21 Feb 2025 09:38:06 +0000 (+0100) Subject: quic: discard late retry packets X-Git-Tag: suricata-8.0.0-beta1~382 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=726de5520f77e778cd2511bf262611079ae2528d;p=thirdparty%2Fsuricata.git quic: discard late retry packets Ticket: 7556 See RFC 9000 section 17.2.5.2 : 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. --- diff --git a/rust/src/quic/quic.rs b/rust/src/quic/quic.rs index 165fc44dc6..03407dbae0 100644 --- a/rust/src/quic/quic.rs +++ b/rust/src/quic/quic.rs @@ -120,6 +120,7 @@ pub struct QuicState { crypto_fraglen_ts: u32, hello_tc: bool, hello_ts: bool, + has_retried: bool, transactions: VecDeque, } @@ -135,6 +136,7 @@ impl Default for QuicState { crypto_fraglen_ts: 0, hello_tc: false, hello_ts: false, + has_retried: false, transactions: VecDeque::new(), } } @@ -339,10 +341,17 @@ impl QuicState { // unprotect/decrypt packet if self.keys.is_none() && header.ty == QuicType::Initial { self.keys = quic_keys_initial(u32::from(header.version), &header.dcid); - } else if !to_server && self.keys.is_some() && header.ty == QuicType::Retry { + } else if !to_server + && self.keys.is_some() + && header.ty == QuicType::Retry + && !self.has_retried + { // a retry packet discards the current keys, client will resend an initial packet with new keys self.hello_ts = false; self.keys = None; + // RFC 9000 17.2.5.2 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. + self.has_retried = true; } // header.length was checked against rest.len() during parsing let (mut framebuf, next_buf) = rest.split_at(header.length.into());