From: Shivani Bhardwaj Date: Fri, 21 Jul 2023 07:28:50 +0000 (+0530) Subject: dcerpc: use AppLayerResult::incomplete API X-Git-Tag: suricata-8.0.0-beta1~494 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=74de1042a9faaf2f6a1061a571211ed21f0b98f7;p=thirdparty%2Fsuricata.git dcerpc: use AppLayerResult::incomplete API Instead of own internal mechanism of buffering in case of fragmented data, use AppLayerResult::incomplete API to let the AppLayer Parser take care of it. This makes the memory use more efficient. Remove any unneeded variables and code with the introduction of this API. Ticket 5699 --- diff --git a/rust/src/dcerpc/dcerpc.rs b/rust/src/dcerpc/dcerpc.rs index 51f980ec67..8ac78f1355 100644 --- a/rust/src/dcerpc/dcerpc.rs +++ b/rust/src/dcerpc/dcerpc.rs @@ -312,8 +312,6 @@ pub struct DCERPCState { pub bindack: Option, pub transactions: VecDeque, tx_index_completed: usize, - pub buffer_ts: Vec, - pub buffer_tc: Vec, pub pad: u8, pub padleft: u16, pub bytes_consumed: i32, @@ -451,29 +449,15 @@ impl DCERPCState { pub fn clean_buffer(&mut self, direction: Direction) { match direction { Direction::ToServer => { - self.buffer_ts.clear(); self.ts_gap = false; } Direction::ToClient => { - self.buffer_tc.clear(); self.tc_gap = false; } } self.bytes_consumed = 0; } - pub fn extend_buffer(&mut self, buffer: &[u8], direction: Direction) { - match direction { - Direction::ToServer => { - self.buffer_ts.extend_from_slice(buffer); - } - Direction::ToClient => { - self.buffer_tc.extend_from_slice(buffer); - } - } - self.data_needed_for_dir = direction; - } - pub fn reset_direction(&mut self, direction: Direction) { if direction == Direction::ToServer { self.data_needed_for_dir = Direction::ToClient; @@ -916,11 +900,10 @@ impl DCERPCState { } pub fn handle_input_data(&mut self, input: &[u8], direction: Direction) -> AppLayerResult { - let mut parsed; + let mut parsed = 0; let retval; let mut cur_i = input; - let input_len = cur_i.len(); - let mut v: Vec; + let mut input_len = cur_i.len(); // Set any query's completion status to false in the beginning self.query_completed = false; @@ -955,69 +938,41 @@ impl DCERPCState { } } - // Overwrite the dcerpc_state data in case of multiple complete queries in the - // same direction - if self.prev_dir == direction { - self.data_needed_for_dir = direction; - } - - let buffer = match direction { - Direction::ToServer => { - v = self.buffer_ts.split_off(0); - v.extend_from_slice(cur_i); - v.as_slice() - } - Direction::ToClient => { - v = self.buffer_tc.split_off(0); - v.extend_from_slice(cur_i); - v.as_slice() - } - }; - - if self.data_needed_for_dir != direction && !buffer.is_empty() { - return AppLayerResult::err(); - } - - // Set data_needed_for_dir in the same direction in case there is an issue with upcoming parsing - self.data_needed_for_dir = direction; - // Check if header data was complete. In case of EoF or incomplete data, wait for more // data else return error - if self.bytes_consumed < DCERPC_HDR_LEN.into() && input_len > 0 { - parsed = self.process_header(buffer); + if self.header.is_none() && !cur_i.is_empty() { + parsed = self.process_header(cur_i); if parsed == -1 { - self.extend_buffer(buffer, direction); - return AppLayerResult::ok(); + return AppLayerResult::incomplete(0, DCERPC_HDR_LEN as u32); } if parsed < 0 { return AppLayerResult::err(); } self.bytes_consumed += parsed; + input_len -= parsed as usize; } let fraglen = self.get_hdr_fraglen().unwrap_or(0); - if (buffer.len()) < fraglen as usize { + if (input_len + self.bytes_consumed as usize) < fraglen as usize { SCLogDebug!("Possibly fragmented data, waiting for more.."); - self.extend_buffer(buffer, direction); - return AppLayerResult::ok(); + return AppLayerResult::incomplete(self.bytes_consumed as u32, (fraglen - self.bytes_consumed as u16) as u32); } else { self.query_completed = true; } - parsed = self.bytes_consumed; let current_call_id = self.get_hdr_call_id().unwrap_or(0); match self.get_hdr_type() { Some(x) => match x { DCERPC_TYPE_BIND | DCERPC_TYPE_ALTER_CONTEXT => { - retval = self.process_bind_pdu(&buffer[parsed as usize..]); + retval = self.process_bind_pdu(&cur_i[parsed as usize..]); if retval == -1 { return AppLayerResult::err(); } } DCERPC_TYPE_BINDACK | DCERPC_TYPE_ALTER_CONTEXT_RESP => { - retval = self.process_bindack_pdu(&buffer[parsed as usize..]); + retval = self.process_bindack_pdu(&cur_i[parsed as usize..]); if retval == -1 { return AppLayerResult::err(); } @@ -1037,7 +992,7 @@ impl DCERPCState { } } DCERPC_TYPE_REQUEST => { - retval = self.process_request_pdu(&buffer[parsed as usize..]); + retval = self.process_request_pdu(&cur_i[parsed as usize..]); if retval < 0 { return AppLayerResult::err(); } @@ -1057,7 +1012,7 @@ impl DCERPCState { } }; retval = self.handle_common_stub( - &buffer[parsed as usize..], + &cur_i[parsed as usize..], 0, Direction::ToClient, ); @@ -1084,6 +1039,7 @@ impl DCERPCState { } self.post_gap_housekeeping(direction); self.prev_dir = direction; + self.header = None; return AppLayerResult::ok(); } } @@ -1092,7 +1048,7 @@ fn evaluate_stub_params( input: &[u8], input_len: usize, hdrflags: u8, lenleft: u16, stub_data_buffer: &mut Vec,stub_data_buffer_reset: &mut bool, ) -> u16 { - + let fragtype = hdrflags & (PFC_FIRST_FRAG | PFC_LAST_FRAG); // min of usize and u16 is a valid u16 let stub_len: u16 = cmp::min(lenleft as usize, input_len) as u16;