]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
dcerpc: use AppLayerResult::incomplete API
authorShivani Bhardwaj <shivani@oisf.net>
Fri, 21 Jul 2023 07:28:50 +0000 (12:58 +0530)
committerVictor Julien <victor@inliniac.net>
Thu, 30 Jan 2025 09:52:05 +0000 (10:52 +0100)
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

rust/src/dcerpc/dcerpc.rs

index 51f980ec670a60f2d0586b0368bca890ee4d8fba..8ac78f13554edb19976abf964ad1d6b09e716619 100644 (file)
@@ -312,8 +312,6 @@ pub struct DCERPCState {
     pub bindack: Option<DCERPCBindAck>,
     pub transactions: VecDeque<DCERPCTransaction>,
     tx_index_completed: usize,
-    pub buffer_ts: Vec<u8>,
-    pub buffer_tc: Vec<u8>,
     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<u8>;
+        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<u8>,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;