Skip to content

Commit

Permalink
doh2: handle dns message in POST requests
Browse files Browse the repository at this point in the history
Ticket: 5773

Handles both directions the same way for data if content type is
application/dns-message
  • Loading branch information
catenacyber authored and victorjulien committed Jul 20, 2024
1 parent bd5ad0d commit 6e12475
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 23 deletions.
7 changes: 7 additions & 0 deletions rust/src/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
53 changes: 30 additions & 23 deletions rust/src/http2/http2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>,
}
Expand Down Expand Up @@ -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,
}
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand Down Expand Up @@ -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(());
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit 6e12475

Please sign in to comment.