From 564a6c9a20f90c40346ec1478b87be070dd4e38e Mon Sep 17 00:00:00 2001 From: Giuseppe Longo Date: Tue, 6 Aug 2024 20:39:46 +0200 Subject: [PATCH] rust/ldap: handle GAPs Following the same logic as for PGSQL, if there is a gap in an LDAP request or response, the parser tries to sync up again by checking if the message can be parsed and effectively parses it on the next call. Ticket #7176 --- rust/src/ldap/ldap.rs | 59 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 57 insertions(+), 2 deletions(-) diff --git a/rust/src/ldap/ldap.rs b/rust/src/ldap/ldap.rs index 14f3ee5e74..4c9c3947d7 100644 --- a/rust/src/ldap/ldap.rs +++ b/rust/src/ldap/ldap.rs @@ -90,6 +90,8 @@ pub struct LdapState { tx_index_completed: usize, request_frame: Option, response_frame: Option, + request_gap: bool, + response_gap: bool, } impl State for LdapState { @@ -111,6 +113,8 @@ impl LdapState { tx_index_completed: 0, request_frame: None, response_frame: None, + request_gap: false, + response_gap: false, } } @@ -178,6 +182,22 @@ impl LdapState { return AppLayerResult::ok(); } + if self.request_gap { + match ldap_parse_msg(input) { + Ok((_, msg)) => { + let ldap_msg = LdapMessage::from(msg); + if ldap_msg.is_unknown() { + return AppLayerResult::err(); + } + AppLayerResult::ok(); + } + Err(_e) => { + return AppLayerResult::err(); + } + } + self.request_gap = false; + } + let mut start = input; while !start.is_empty() { if self.request_frame.is_none() { @@ -223,6 +243,22 @@ impl LdapState { return AppLayerResult::ok(); } + if self.response_gap { + match ldap_parse_msg(input) { + Ok((_, msg)) => { + let ldap_msg = LdapMessage::from(msg); + if ldap_msg.is_unknown() { + return AppLayerResult::err(); + } + AppLayerResult::ok(); + } + Err(_e) => { + return AppLayerResult::err(); + } + } + self.response_gap = false; + } + let mut start = input; while !start.is_empty() { if self.response_frame.is_none() { @@ -398,6 +434,14 @@ impl LdapState { self.response_frame = None; } } + + fn on_request_gap(&mut self, _size: u32) { + self.request_gap = true; + } + + fn on_response_gap(&mut self, _size: u32) { + self.response_gap = true; + } } fn tx_is_complete(op: &ProtocolOp, dir: Direction) -> bool { @@ -490,7 +534,13 @@ unsafe extern "C" fn SCLdapParseRequest( } } let state = cast_pointer!(state, LdapState); - state.parse_request(flow, stream_slice) + + if stream_slice.is_gap() { + state.on_request_gap(stream_slice.gap_size()); + } else { + return state.parse_request(flow, stream_slice); + } + AppLayerResult::ok() } #[no_mangle] @@ -506,7 +556,12 @@ unsafe extern "C" fn SCLdapParseResponse( } } let state = cast_pointer!(state, LdapState); - state.parse_response(flow, stream_slice) + if stream_slice.is_gap() { + state.on_response_gap(stream_slice.gap_size()); + } else { + return state.parse_response(flow, stream_slice); + } + AppLayerResult::ok() } #[no_mangle]