]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
doh2: handle dns message in POST requests
authorPhilippe Antoine <pantoine@oisf.net>
Thu, 28 Mar 2024 15:55:10 +0000 (16:55 +0100)
committerVictor Julien <victor@inliniac.net>
Sat, 20 Jul 2024 08:37:58 +0000 (10:37 +0200)
Ticket: 5773

Handles both directions the same way for data if content type is
application/dns-message

rust/src/core.rs
rust/src/http2/http2.rs

index abb27ea578fe6c8abf9ce5b18cc46ed8a0dc2458..bca228131124ef07194f29d307fd671e6fe0b14d 100644 (file)
@@ -61,6 +61,13 @@ impl Direction {
     pub fn is_to_client(&self) -> bool {
        matches!(self, Self::ToClient)
     }
+
+    pub fn index(&self) -> usize {
+        match self {
+            Self::ToClient => 0,
+            _ => 1,
+        }
+    }
 }
 
 impl Default for Direction {
index 6620c040de4ec4cf446b4879b32d2bfa3904db5e..2c561c70d4a99ce391d55ac2f6e2c7b32f084c59 100644 (file)
@@ -151,9 +151,9 @@ pub struct HTTP2Transaction {
     pub req_line: Vec<u8>,
     pub resp_line: Vec<u8>,
 
-    is_doh_response: bool,
+    is_doh_data: [bool; 2],
     // dns response buffer
-    pub doh_response_buf: Vec<u8>,
+    pub doh_data_buf: [Vec<u8>; 2],
     pub dns_request_tx: Option<DNSTransaction>,
     pub dns_response_tx: Option<DNSTransaction>,
 }
@@ -187,8 +187,8 @@ impl HTTP2Transaction {
             escaped: Vec::with_capacity(16),
             req_line: Vec::new(),
             resp_line: Vec::new(),
-            is_doh_response: false,
-            doh_response_buf: Vec::new(),
+            is_doh_data: [false; 2],
+            doh_data_buf: Default::default(),
             dns_request_tx: None,
             dns_response_tx: None,
         }
@@ -235,7 +235,7 @@ impl HTTP2Transaction {
                 }
             } else if block.name.as_ref() == b"content-type" {
                 if block.value.as_ref() == b"application/dns-message" {
-                    self.is_doh_response = true;
+                    self.is_doh_data[dir.index()] = true;
                 }
             } else if block.name.as_ref() == b":path" {
                 path = Some(&block.value);
@@ -260,7 +260,7 @@ impl HTTP2Transaction {
                 }
             }
         }
-        if doh && unsafe {ALPROTO_DOH2} != ALPROTO_UNKNOWN {
+        if doh && unsafe { ALPROTO_DOH2 } != ALPROTO_UNKNOWN {
             if let Some(p) = path {
                 if let Ok((_, dns_req)) = parser::doh_extract_request(p) {
                     return Some(dns_req);
@@ -345,11 +345,11 @@ impl HTTP2Transaction {
                 &xid,
             );
         };
-        if unsafe {ALPROTO_DOH2} != ALPROTO_UNKNOWN {
+        if unsafe { ALPROTO_DOH2 } != ALPROTO_UNKNOWN {
             // we store DNS response, and process it when complete
-            if self.is_doh_response && self.doh_response_buf.len() < 0xFFFF {
+            if self.is_doh_data[dir.index()] && self.doh_data_buf[dir.index()].len() < 0xFFFF {
                 // a DNS message is U16_MAX
-                self.doh_response_buf.extend_from_slice(decompressed);
+                self.doh_data_buf[dir.index()].extend_from_slice(decompressed);
             }
         }
         return Ok(());
@@ -432,6 +432,26 @@ impl HTTP2Transaction {
         }
         return r;
     }
+
+    fn handle_dns_data(&mut self, over: bool, dir: Direction, flow: *const Flow) {
+        if !self.doh_data_buf[dir.index()].is_empty() && over {
+            if dir.is_to_client() {
+                if let Ok(mut dtx) = dns_parse_response(&self.doh_data_buf[dir.index()]) {
+                    dtx.id = 1;
+                    self.dns_response_tx = Some(dtx);
+                    unsafe {
+                        AppLayerForceProtocolChange(flow, ALPROTO_DOH2);
+                    }
+                }
+            } else if let Ok(mut dtx) = dns_parse_request(&self.doh_data_buf[dir.index()]) {
+                dtx.id = 1;
+                self.dns_request_tx = Some(dtx);
+                unsafe {
+                    AppLayerForceProtocolChange(flow, ALPROTO_DOH2);
+                }
+            }
+        }
+    }
 }
 
 impl Drop for HTTP2Transaction {
@@ -1165,20 +1185,7 @@ impl HTTP2State {
                                         flow,
                                     ) {
                                         Ok(_) => {
-                                            if !tx_same.doh_response_buf.is_empty() && over {
-                                                if let Ok(mut dtx) =
-                                                    dns_parse_response(&tx_same.doh_response_buf)
-                                                {
-                                                    dtx.id = 1;
-                                                    tx_same.dns_response_tx = Some(dtx);
-                                                    unsafe {
-                                                        AppLayerForceProtocolChange(
-                                                            flow,
-                                                            ALPROTO_DOH2,
-                                                        );
-                                                    }
-                                                }
-                                            }
+                                            tx_same.handle_dns_data(over, dir, flow);
                                         }
                                         _ => {
                                             self.set_event(HTTP2Event::FailedDecompression);