]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
dcerpc: maximum number of live transactions also for UDP
authorPhilippe Antoine <pantoine@oisf.net>
Thu, 8 Jun 2023 12:25:01 +0000 (14:25 +0200)
committerVictor Julien <vjulien@oisf.net>
Tue, 27 Jun 2023 14:27:04 +0000 (16:27 +0200)
Ticket: #6129

Avoids that quadratic complexity gets too bad

(cherry picked from commit d40dca5e55286c57e9a83018975022c4f08bf6d1)

rust/src/dcerpc/dcerpc.rs
rust/src/dcerpc/dcerpc_udp.rs

index b874954ee2178dc9ae72f3acd15d23b238f17b2c..e922fb3ac0f53df2f5718fd178dce61d2b255a3a 100644 (file)
@@ -109,6 +109,8 @@ pub const DCERPC_TYPE_ORPHANED: u8 = 19;
 pub const DCERPC_TYPE_RTS: u8 = 20;
 pub const DCERPC_TYPE_UNKNOWN: u8 = 99;
 
+pub(super) static mut DCERPC_MAX_TX: usize = 1024;
+
 pub fn dcerpc_type_string(t: u8) -> String {
     match t {
         DCERPC_TYPE_REQUEST => "REQUEST",
index 3ed1801b2b07d3f47e0e5566221851ed2f2461bb..e39c5f14a091bcf2f173ab1a38fe4d1f2935d747 100644 (file)
@@ -20,7 +20,7 @@ use std::mem::transmute;
 use crate::applayer::{AppLayerResult, AppLayerTxData};
 use crate::core;
 use crate::dcerpc::dcerpc::{
-    DCERPCTransaction, DCERPC_TYPE_REQUEST, DCERPC_TYPE_RESPONSE, PFCL1_FRAG, PFCL1_LASTFRAG,
+    DCERPCTransaction, DCERPC_MAX_TX, DCERPC_TYPE_REQUEST, DCERPC_TYPE_RESPONSE, PFCL1_FRAG, PFCL1_LASTFRAG,
 };
 use std::collections::VecDeque;
 use crate::dcerpc::parser;
@@ -55,12 +55,14 @@ pub struct DCERPCHdrUdp {
 pub struct DCERPCUDPState {
     pub tx_id: u64,
     pub transactions: VecDeque<DCERPCTransaction>,
+    tx_index_completed: usize,
 }
 
 impl DCERPCUDPState {
     pub fn new() -> DCERPCUDPState {
         return DCERPCUDPState {
             tx_id: 0,
+            tx_index_completed: 0,
             transactions: VecDeque::new(),
         };
     }
@@ -72,6 +74,18 @@ impl DCERPCUDPState {
         tx.activityuuid = hdr.activityuuid.to_vec();
         tx.seqnum = hdr.seqnum;
         self.tx_id += 1;
+        if self.transactions.len() > unsafe { DCERPC_MAX_TX } {
+            let mut index = self.tx_index_completed;
+            for tx_old in &mut self.transactions.iter_mut().skip(self.tx_index_completed) {
+                index += 1;
+                if !tx_old.req_done || !tx_old.resp_done {
+                    tx_old.req_done = true;
+                    tx_old.resp_done = true;
+                    break;
+                }
+            }
+            self.tx_index_completed = index;
+        }
         tx
     }
 
@@ -92,6 +106,7 @@ impl DCERPCUDPState {
         if found {
             SCLogDebug!("freeing TX with ID {} TX.ID {} at index {} left: {} max id: {}",
                             tx_id, tx_id+1, index, self.transactions.len(), self.tx_id);
+            self.tx_index_completed = 0;
             self.transactions.remove(index);
         }
     }