]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
smb: configurable max number of transactions per flow 8360/head
authorPhilippe Antoine <pantoine@oisf.net>
Tue, 13 Dec 2022 08:52:43 +0000 (09:52 +0100)
committerVictor Julien <vjulien@oisf.net>
Tue, 10 Jan 2023 10:45:28 +0000 (11:45 +0100)
Ticket: #5753

doc/userguide/configuration/suricata-yaml.rst
rules/smb-events.rules
rust/src/smb/events.rs
rust/src/smb/smb.rs
suricata.yaml.in

index da6eff556d685e0aad14e391662fd878c4e35e42..db8c39306087be157266aa66fe4995d2bad91d3b 100644 (file)
@@ -1722,7 +1722,7 @@ incompatible with ``decode-mime``. If both are enabled,
 Maximum transactions
 ~~~~~~~~~~~~~~~~~~~~
 
-MQTT, FTP, PostgreSQL and NFS have each a `max-tx` parameter that can be customized.
+MQTT, FTP, PostgreSQL, SMB and NFS have each a `max-tx` parameter that can be customized.
 `max-tx` refers to the maximum number of live transactions for each flow.
 An app-layer event `protocol.too_many_transactions` is triggered when this value is reached.
 The point of this parameter is to find a balance between the completeness of analysis
index 159033f898c0be9f0d589877308464d27fc4cd0a..248d75e4b575a4c2802fa4eed84f43dceecd3405 100644 (file)
@@ -41,4 +41,6 @@ alert smb any any -> any any (msg:"SURICATA SMB max READ queue size exceeded"; f
 # checks 'app-layer.protocols.smb.max-read-queue-cnt` against out of order chunks
 alert smb any any -> any any (msg:"SURICATA SMB max READ queue cnt exceeded"; flow:to_client; app-layer-event:smb.read_queue_cnt_exceeded; classtype:protocol-command-decode; sid:2225017; rev:1;)
 
-# next sid 2225018
+alert smb any any -> any any (msg:"SURICATA SMB too many transactions"; app-layer-event:smb.too_many_transactions; classtype:protocol-command-decode; sid:2225018; rev:1;)
+
+# next sid 2225019
index 94bd06613934b690aab576a2ba38ce77cd1aebbf..4a1d30e9cdd77db2550b0e836cf7077a9ff82ad5 100644 (file)
@@ -48,6 +48,8 @@ pub enum SMBEvent {
     WriteQueueCntExceeded,
     /// Unusal NTLMSSP fields order
     UnusualNtlmsspOrder,
+    /// Too many live transactions in one flow
+    TooManyTransactions,
 }
 
 impl SMBTransaction {
index 77f66049756140a82b3ed174676e1a60453b16f8..370d48bd0f5a800c044b7aedaad9a38238720551 100644 (file)
@@ -83,6 +83,8 @@ pub static mut SMB_CFG_MAX_WRITE_QUEUE_CNT: u32 = 0;
 
 static mut ALPROTO_SMB: AppProto = ALPROTO_UNKNOWN;
 
+static mut SMB_MAX_TX: usize = 1024;
+
 pub static mut SURICATA_SMB_FILE_CONFIG: Option<&'static SuricataFileContext> = None;
 
 #[no_mangle]
@@ -714,6 +716,7 @@ pub struct SMBState<> {
 
     /// transactions list
     pub transactions: VecDeque<SMBTransaction>,
+    tx_index_completed: usize,
 
     /// tx counter for assigning incrementing id's to tx's
     tx_id: u64,
@@ -770,6 +773,7 @@ impl SMBState {
             check_post_gap_file_txs: false,
             post_gap_files_checked: false,
             transactions: VecDeque::new(),
+            tx_index_completed: 0,
             tx_id:0,
             dialect:0,
             dialect_vec: None,
@@ -789,6 +793,20 @@ impl SMBState {
         self.tx_id += 1;
         tx.id = self.tx_id;
         SCLogDebug!("TX {} created", tx.id);
+        if self.transactions.len() > unsafe { SMB_MAX_TX } {
+            let mut index = self.tx_index_completed;
+            for tx_old in &mut self.transactions.range_mut(self.tx_index_completed..) {
+                index += 1;
+                if !tx_old.request_done || !tx_old.response_done {
+                    tx_old.request_done = true;
+                    tx_old.response_done = true;
+                    tx_old.set_event(SMBEvent::TooManyTransactions);
+                    break;
+                }
+            }
+            self.tx_index_completed = index;
+
+        }
         return tx;
     }
 
@@ -809,6 +827,7 @@ impl SMBState {
         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);
         }
     }
@@ -2398,6 +2417,13 @@ pub unsafe extern "C" fn rs_smb_register_parser() {
                 Err(_) => { SCLogError!("Invalid max-read-queue-cnt value"); }
             }
         }
+        if let Some(val) = conf_get("app-layer.protocols.smb.max-tx") {
+            if let Ok(v) = val.parse::<usize>() {
+                SMB_MAX_TX = v;
+            } else {
+                SCLogError!("Invalid value for smb.max-tx");
+            }
+        }
     } else {
         SCLogDebug!("Protocol detector and parser disabled for SMB.");
     }
index 62df74e147df570e43bd2c290c5a348aa670e8f7..aca16043ed86fb14166dd0e5d2274355aa3e9da7 100644 (file)
@@ -955,6 +955,8 @@ app-layer:
       enabled: yes
       detection-ports:
         dp: 139, 445
+      # Maximum number of live SMB transactions per flow
+      # max-tx: 1024
 
       # Stream reassembly size for SMB streams. By default track it completely.
       #stream-depth: 0