diff --git a/rust/src/smb/debug.rs b/rust/src/smb/debug.rs index f2c3d9a7a393..0c19a2c58d02 100644 --- a/rust/src/smb/debug.rs +++ b/rust/src/smb/debug.rs @@ -69,8 +69,8 @@ impl SMBState { #[cfg(feature = "debug")] pub fn _debug_state_stats(&self) { - SCLogDebug!("ssn2vec_map {} guid2name_cache {} read_offset_cache {} ssn2tree_cache {} dcerpc_rec_frag_cache {} file_ts_guid {} file_tc_guid {} transactions {}", - self.ssn2vec_map.len(), + SCLogDebug!("ssn2vec_cache {} guid2name_cache {} read_offset_cache {} ssn2tree_cache {} dcerpc_rec_frag_cache {} file_ts_guid {} file_tc_guid {} transactions {}", + self.ssn2vec_cache.len(), self.guid2name_cache.len(), self.read_offset_cache.len(), self.ssn2tree_cache.len(), diff --git a/rust/src/smb/smb.rs b/rust/src/smb/smb.rs index 004bff9f2fae..901ed2a23927 100644 --- a/rust/src/smb/smb.rs +++ b/rust/src/smb/smb.rs @@ -28,7 +28,6 @@ use std; use std::str; use std::ffi::{self, CString}; -use std::collections::HashMap; use std::collections::VecDeque; use nom7::{Err, Needed}; @@ -90,6 +89,8 @@ pub static mut SMB_CFG_MAX_READ_OFFSET_CACHE_SIZE: usize = 128; pub static mut SMB_CFG_MAX_TREE_CACHE_SIZE: usize = 512; /// For SMBState::dcerpc_rec_frag_cache pub static mut SMB_CFG_MAX_FRAG_CACHE_SIZE: usize = 128; +/// For SMBState::ssn2vec_cache +pub static mut SMB_CFG_MAX_SSN2VEC_CACHE_SIZE: usize = 512; static mut ALPROTO_SMB: AppProto = ALPROTO_UNKNOWN; @@ -697,7 +698,7 @@ pub struct SMBState<> { pub state_data: AppLayerStateData, /// map ssn/tree/msgid to vec (guid/name/share) - pub ssn2vec_map: HashMap>, + pub ssn2vec_cache: LruCache>, /// map guid to filename /// @@ -785,7 +786,7 @@ impl SMBState { pub fn new() -> Self { Self { state_data:AppLayerStateData::new(), - ssn2vec_map:HashMap::new(), + ssn2vec_cache:LruCache::new(NonZeroUsize::new(unsafe { SMB_CFG_MAX_SSN2VEC_CACHE_SIZE }).unwrap()), guid2name_cache:LruCache::new(NonZeroUsize::new(unsafe { SMB_CFG_MAX_GUID_CACHE_SIZE }).unwrap()), read_offset_cache:LruCache::new(NonZeroUsize::new(unsafe { SMB_CFG_MAX_READ_OFFSET_CACHE_SIZE }).unwrap()), ssn2tree_cache:LruCache::new(NonZeroUsize::new(unsafe { SMB_CFG_MAX_TREE_CACHE_SIZE }).unwrap()), @@ -2497,6 +2498,18 @@ pub unsafe extern "C" fn rs_smb_register_parser() { SCLogError!("Invalid max-dcerpc-frag-cache-size value"); } } + let retval = conf_get("app-layer.protocols.smb.max-session-cache-size"); + if let Some(val) = retval { + if let Ok(v) = val.parse::() { + if v > 0 { + SMB_CFG_MAX_SSN2VEC_CACHE_SIZE = v; + } else { + SCLogError!("Invalid max-session-cache-size value"); + } + } else { + SCLogError!("Invalid max-session-cache-size value"); + } + } SCLogConfig!("read: max record size: {}, max queued chunks {}, max queued size {}", SMB_CFG_MAX_READ_SIZE, SMB_CFG_MAX_READ_QUEUE_CNT, SMB_CFG_MAX_READ_QUEUE_SIZE); SCLogConfig!("write: max record size: {}, max queued chunks {}, max queued size {}", diff --git a/rust/src/smb/smb1.rs b/rust/src/smb/smb1.rs index 7c49b3bdc8d4..c74ab5fd0269 100644 --- a/rust/src/smb/smb1.rs +++ b/rust/src/smb/smb1.rs @@ -479,7 +479,7 @@ fn smb1_request_record_one(state: &mut SMBState, r: &SmbRecord, command: u8, and let name_key = SMBCommonHdr::from1(r, SMBHDR_TYPE_FILENAME); let name_val = cr.file_name.to_vec(); - state.ssn2vec_map.insert(name_key, name_val); + state.ssn2vec_cache.put(name_key, name_val); let tx_hdr = SMBCommonHdr::from1(r, SMBHDR_TYPE_GENERICTX); let tx = state.new_create_tx(&cr.file_name, @@ -537,7 +537,7 @@ fn smb1_request_record_one(state: &mut SMBState, r: &SmbRecord, command: u8, and fid.extend_from_slice(&u32_as_bytes(r.ssn_id)); let _name = state.guid2name_cache.pop(&fid); - state.ssn2vec_map.insert(SMBCommonHdr::from1(r, SMBHDR_TYPE_GUID), fid.to_vec()); + state.ssn2vec_cache.put(SMBCommonHdr::from1(r, SMBHDR_TYPE_GUID), fid.to_vec()); SCLogDebug!("closing FID {:?}/{:?}", cd.fid, fid); smb1_close_file(state, &fid, Direction::ToServer); @@ -727,7 +727,7 @@ fn smb1_response_record_one(state: &mut SMBState, r: &SmbRecord, command: u8, an SCLogDebug!("Create AndX {:?}", cr); let guid_key = SMBCommonHdr::from1(r, SMBHDR_TYPE_FILENAME); - if let Some(mut p) = state.ssn2vec_map.remove(&guid_key) { + if let Some(mut p) = state.ssn2vec_cache.pop(&guid_key) { p.retain(|&i|i != 0x00); let mut fid = cr.fid.to_vec(); @@ -767,7 +767,7 @@ fn smb1_response_record_one(state: &mut SMBState, r: &SmbRecord, command: u8, an } }, SMB1_COMMAND_CLOSE => { - let fid = state.ssn2vec_map.remove(&SMBCommonHdr::from1(r, SMBHDR_TYPE_GUID)); + let fid = state.ssn2vec_cache.pop(&SMBCommonHdr::from1(r, SMBHDR_TYPE_GUID)); if let Some(fid) = fid { SCLogDebug!("closing FID {:?}", fid); smb1_close_file(state, &fid, Direction::ToClient); @@ -857,7 +857,7 @@ pub fn smb1_trans_request_record(state: &mut SMBState, r: &SmbRecord) let mut pipe_dcerpc = false; if rd.pipe.is_some() { let pipe = rd.pipe.unwrap(); - state.ssn2vec_map.insert(SMBCommonHdr::from1(r, SMBHDR_TYPE_GUID), + state.ssn2vec_cache.put(SMBCommonHdr::from1(r, SMBHDR_TYPE_GUID), pipe.fid.to_vec()); let mut frankenfid = pipe.fid.to_vec(); @@ -893,7 +893,7 @@ pub fn smb1_trans_response_record(state: &mut SMBState, r: &SmbRecord) SCLogDebug!("TRANS response {:?}", rd); // see if we have a stored fid - let fid = state.ssn2vec_map.remove( + let fid = state.ssn2vec_cache.pop( &SMBCommonHdr::from1(r, SMBHDR_TYPE_GUID)).unwrap_or_default(); SCLogDebug!("FID {:?}", fid); diff --git a/rust/src/smb/smb2.rs b/rust/src/smb/smb2.rs index 5eb57dd7b726..97deb702ecef 100644 --- a/rust/src/smb/smb2.rs +++ b/rust/src/smb/smb2.rs @@ -299,7 +299,7 @@ pub fn smb2_write_request_record(state: &mut SMBState, r: &Smb2Record, nbss_rema /* update key-guid map */ let guid_key = SMBCommonHdr::from2(r, SMBHDR_TYPE_GUID); - state.ssn2vec_map.insert(guid_key, wr.guid.to_vec()); + state.ssn2vec_cache.put(guid_key, wr.guid.to_vec()); let file_guid = wr.guid.to_vec(); let file_name = match state.guid2name_cache.get(&file_guid) { @@ -448,7 +448,7 @@ pub fn smb2_request_record(state: &mut SMBState, r: &Smb2Record) b"".to_vec() } else { guid_key.msg_id -= 1; - match state.ssn2vec_map.get(&guid_key) { + match state.ssn2vec_cache.get(&guid_key) { Some(n) => { n.to_vec() }, None => { b"".to_vec()}, } @@ -558,7 +558,7 @@ pub fn smb2_request_record(state: &mut SMBState, r: &Smb2Record) SCLogDebug!("create_options {:08x}", cr.create_options); let name_key = SMBCommonHdr::from2_notree(r, SMBHDR_TYPE_FILENAME); - state.ssn2vec_map.insert(name_key, cr.data.to_vec()); + state.ssn2vec_cache.put(name_key, cr.data.to_vec()); let tx_hdr = SMBCommonHdr::from2(r, SMBHDR_TYPE_GENERICTX); let tx = state.new_create_tx(cr.data, cr.disposition, del, dir, tx_hdr); @@ -651,7 +651,7 @@ pub fn smb2_response_record(state: &mut SMBState, r: &Smb2Record) /* search key-guid map */ let guid_key = SMBCommonHdr::new(SMBHDR_TYPE_GUID, r.session_id, r.tree_id, r.message_id); - let _guid_vec = state.ssn2vec_map.remove(&guid_key).unwrap_or_default(); + let _guid_vec = state.ssn2vec_cache.pop(&guid_key).unwrap_or_default(); SCLogDebug!("SMBv2 write response for GUID {:?}", _guid_vec); } else { events.push(SMBEvent::MalformedData); @@ -693,7 +693,7 @@ pub fn smb2_response_record(state: &mut SMBState, r: &Smb2Record) SCLogDebug!("SMBv2: Create response => {:?}", cr); let guid_key = SMBCommonHdr::from2_notree(r, SMBHDR_TYPE_FILENAME); - if let Some(mut p) = state.ssn2vec_map.remove(&guid_key) { + if let Some(mut p) = state.ssn2vec_cache.pop(&guid_key) { p.retain(|&i|i != 0x00); _ = state.guid2name_cache.put(cr.guid.to_vec(), p); } else {