From: Philippe Antoine Date: Tue, 10 Jan 2023 10:08:36 +0000 (+0100) Subject: dcerpc: config limit maximum number of live transactions X-Git-Tag: suricata-7.0.0-rc1~60 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b52293b6090f47bc9400b99ea6b0d833e568894f;p=thirdparty%2Fsuricata.git dcerpc: config limit maximum number of live transactions As is done for other protocols Ticket: #5779 --- diff --git a/doc/userguide/configuration/suricata-yaml.rst b/doc/userguide/configuration/suricata-yaml.rst index 84b953f564..fa96d04b54 100644 --- a/doc/userguide/configuration/suricata-yaml.rst +++ b/doc/userguide/configuration/suricata-yaml.rst @@ -1722,7 +1722,7 @@ incompatible with ``decode-mime``. If both are enabled, Maximum transactions ~~~~~~~~~~~~~~~~~~~~ -MQTT, FTP, PostgreSQL, SMB and NFS have each a `max-tx` parameter that can be customized. +MQTT, FTP, PostgreSQL, SMB, DCERPC 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 diff --git a/rust/src/dcerpc/dcerpc.rs b/rust/src/dcerpc/dcerpc.rs index 1622706373..5cefc2c347 100644 --- a/rust/src/dcerpc/dcerpc.rs +++ b/rust/src/dcerpc/dcerpc.rs @@ -25,6 +25,7 @@ use std; use std::cmp; use std::ffi::CString; use std::collections::VecDeque; +use crate::conf::conf_get; // Constant DCERPC UDP Header length pub const DCERPC_HDR_LEN: u16 = 16; @@ -110,6 +111,8 @@ pub const DCERPC_TYPE_ORPHANED: u8 = 19; pub const DCERPC_TYPE_RTS: u8 = 20; pub const DCERPC_TYPE_UNKNOWN: u8 = 99; +static mut DCERPC_MAX_TX: usize = 1024; + pub static mut ALPROTO_DCERPC: AppProto = ALPROTO_UNKNOWN; pub fn dcerpc_type_string(t: u8) -> String { @@ -305,6 +308,7 @@ pub struct DCERPCState { pub bind: Option, pub bindack: Option, pub transactions: VecDeque, + tx_index_completed: usize, pub buffer_ts: Vec, pub buffer_tc: Vec, pub pad: u8, @@ -352,6 +356,18 @@ impl DCERPCState { self.tx_id += 1; tx.req_done = self.ts_ssn_trunc; tx.resp_done = self.tc_ssn_trunc; + if self.transactions.len() > unsafe { DCERPC_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.req_done || !tx_old.resp_done { + tx_old.req_done = true; + tx_old.resp_done = true; + break; + } + } + self.tx_index_completed = index; + } tx } @@ -372,6 +388,7 @@ impl DCERPCState { 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); } } @@ -1397,6 +1414,13 @@ pub unsafe extern "C" fn rs_dcerpc_register_parser() { { let _ = AppLayerRegisterParser(&parser, alproto); } + if let Some(val) = conf_get("app-layer.protocols.dcerpc.max-tx") { + if let Ok(v) = val.parse::() { + DCERPC_MAX_TX = v; + } else { + SCLogError!("Invalid value for smb.max-tx"); + } + } SCLogDebug!("Rust DCERPC parser registered."); } else { SCLogDebug!("Protocol detector and parser disabled for DCERPC."); diff --git a/suricata.yaml.in b/suricata.yaml.in index 74a8b60dc0..2d59bdae3a 100644 --- a/suricata.yaml.in +++ b/suricata.yaml.in @@ -900,6 +900,8 @@ app-layer: # max-tx: 1024 dcerpc: enabled: yes + # Maximum number of live DCERPC transactions per flow + # max-tx: 1024 ftp: enabled: yes # memcap: 64mb