From: Victor Julien Date: Mon, 23 Jan 2023 13:57:33 +0000 (+0100) Subject: files: move FileContainer into FileTransferTracker X-Git-Tag: suricata-7.0.0-rc1~108 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6cc9811eddf783169d58e11ad164889e5634544b;p=thirdparty%2Fsuricata.git files: move FileContainer into FileTransferTracker Update SMB, NFS, HTTP2. --- diff --git a/rust/src/filetracker.rs b/rust/src/filetracker.rs index 6330ed8063..4585608d9b 100644 --- a/rust/src/filetracker.rs +++ b/rust/src/filetracker.rs @@ -56,6 +56,9 @@ pub struct FileTransferTracker { track_id: u32, chunk_left: u32, + pub file: FileContainer, + pub file_flags: u16, + pub tx_id: u64, fill_bytes: u8, @@ -82,35 +85,32 @@ impl FileTransferTracker { !self.file_open } - fn open(&mut self, config: &'static SuricataFileContext, - files: &mut FileContainer, flags: u16, name: &[u8]) -> i32 + fn open(&mut self, config: &'static SuricataFileContext, name: &[u8]) -> i32 { - let r = files.file_open(config, self.track_id, name, flags); + let r = self.file.file_open(config, self.track_id, name, self.file_flags); if r == 0 { self.file_open = true; } r } - pub fn close(&mut self, config: &'static SuricataFileContext, - files: &mut FileContainer, flags: u16) + pub fn close(&mut self, config: &'static SuricataFileContext) { if !self.file_is_truncated { SCLogDebug!("closing file with id {}", self.track_id); - files.file_close(config, &self.track_id, flags); + self.file.file_close(config, &self.track_id, self.file_flags); } self.file_open = false; self.tracked = 0; } - pub fn trunc (&mut self, config: &'static SuricataFileContext, - files: &mut FileContainer, flags: u16) + pub fn trunc (&mut self, config: &'static SuricataFileContext) { if self.file_is_truncated || !self.file_open { return; } - let myflags = flags | 1; // TODO util-file.c::FILE_TRUNCATED - files.file_close(config, &self.track_id, myflags); + let myflags = self.file_flags | 1; // TODO util-file.c::FILE_TRUNCATED + self.file.file_close(config, &self.track_id, myflags); SCLogDebug!("truncated file"); self.file_is_truncated = true; self.chunks.clear(); @@ -125,13 +125,12 @@ impl FileTransferTracker { } pub fn new_chunk(&mut self, config: &'static SuricataFileContext, - files: &mut FileContainer, flags: u16, name: &[u8], data: &[u8], chunk_offset: u64, chunk_size: u32, fill_bytes: u8, is_last: bool, xid: &u32) -> u32 { if self.chunk_left != 0 || self.fill_bytes != 0 { SCLogDebug!("current chunk incomplete: truncating"); - self.trunc(config, files, flags); + self.trunc(config); } SCLogDebug!("NEW CHUNK: chunk_size {} fill_bytes {}", chunk_size, fill_bytes); @@ -143,7 +142,7 @@ impl FileTransferTracker { SCLogDebug!("NEW CHUNK IS OOO: expected {}, got {}", self.tracked, chunk_offset); if is_last { SCLogDebug!("last chunk is out of order, this means we missed data before"); - self.trunc(config, files, flags); + self.trunc(config); } self.chunk_is_ooo = true; self.cur_ooo_chunk_offset = chunk_offset; @@ -159,11 +158,11 @@ impl FileTransferTracker { if !self.file_open { SCLogDebug!("NEW CHUNK: FILE OPEN"); self.track_id = *xid; - self.open(config, files, flags, name); + self.open(config, name); } if self.file_open { - let res = self.update(config, files, flags, data, 0); + let res = self.update(config, data, 0); SCLogDebug!("NEW CHUNK: update res {:?}", res); return res; } @@ -174,8 +173,7 @@ impl FileTransferTracker { /// update the file tracker /// If gap_size > 0 'data' should not be used. /// return how much we consumed of data - pub fn update(&mut self, config: &'static SuricataFileContext, - files: &mut FileContainer, flags: u16, data: &[u8], gap_size: u32) -> u32 + pub fn update(&mut self, config: &'static SuricataFileContext, data: &[u8], gap_size: u32) -> u32 { if self.file_is_truncated { let consumed = std::cmp::min(data.len() as u32, self.chunk_left); @@ -192,7 +190,7 @@ impl FileTransferTracker { //SCLogDebug!("UPDATE: nothing to do"); if self.chunk_is_last { SCLogDebug!("last empty chunk, closing"); - self.close(config, files, flags); + self.close(config); self.chunk_is_last = false; } return 0 @@ -217,7 +215,7 @@ impl FileTransferTracker { let d = &data[0..self.chunk_left as usize]; if !self.chunk_is_ooo { - let res = files.file_append(config, &self.track_id, d, is_gap); + let res = self.file.file_append(config, &self.track_id, d, is_gap); match res { 0 => { }, -2 => { @@ -270,7 +268,7 @@ impl FileTransferTracker { Some(c) => { self.in_flight -= c.chunk.len() as u64; - let res = files.file_append(config, &self.track_id, &c.chunk, c.contains_gap); + let res = self.file.file_append(config, &self.track_id, &c.chunk, c.contains_gap); match res { 0 => { }, -2 => { @@ -302,7 +300,7 @@ impl FileTransferTracker { } if self.chunk_is_last { SCLogDebug!("last chunk, closing"); - self.close(config, files, flags); + self.close(config); self.chunk_is_last = false; } else { SCLogDebug!("NOT last chunk, keep going"); @@ -310,7 +308,7 @@ impl FileTransferTracker { } else { if !self.chunk_is_ooo { - let res = files.file_append(config, &self.track_id, data, is_gap); + let res = self.file.file_append(config, &self.track_id, data, is_gap); match res { 0 => { }, -2 => { diff --git a/rust/src/http2/http2.rs b/rust/src/http2/http2.rs index 63fc31c73e..63032cc5b6 100644 --- a/rust/src/http2/http2.rs +++ b/rust/src/http2/http2.rs @@ -137,13 +137,11 @@ pub struct HTTP2Transaction { pub tx_data: AppLayerTxData, pub ft_tc: FileTransferTracker, - ft_ts: FileTransferTracker, + pub ft_ts: FileTransferTracker, //temporary escaped header for detection //must be attached to transaction for memory management (be freed at the right time) pub escaped: Vec>, - - pub files: Files, } impl Transaction for HTTP2Transaction { @@ -173,7 +171,6 @@ impl HTTP2Transaction { ft_tc: FileTransferTracker::new(), ft_ts: FileTransferTracker::new(), escaped: Vec::with_capacity(16), - files: Files::default(), } } @@ -210,8 +207,8 @@ impl HTTP2Transaction { } pub fn update_file_flags(&mut self, flow_file_flags: u16) { - self.files.flags_ts = unsafe { FileFlowFlagsToFlags(flow_file_flags, STREAM_TOSERVER) | FILE_USE_DETECT }; - self.files.flags_tc = unsafe { FileFlowFlagsToFlags(flow_file_flags, STREAM_TOCLIENT) | FILE_USE_DETECT }; + self.ft_ts.file_flags = unsafe { FileFlowFlagsToFlags(flow_file_flags, STREAM_TOSERVER) | FILE_USE_DETECT }; + self.ft_tc.file_flags = unsafe { FileFlowFlagsToFlags(flow_file_flags, STREAM_TOCLIENT) | FILE_USE_DETECT }; } fn decompress<'a>( @@ -250,11 +247,8 @@ impl HTTP2Transaction { range::http2_range_append(sfcm, self.file_range, decompressed) } } - let (files, flags) = self.files.get(Direction::ToClient); self.ft_tc.new_chunk( sfcm, - files, - flags, b"", decompressed, self.ft_tc.tracked, //offset = append @@ -268,11 +262,8 @@ impl HTTP2Transaction { if !self.ft_ts.file_open { self.tx_data.incr_files_opened(); } - let (files, flags) = self.files.get(Direction::ToServer); self.ft_ts.new_chunk( sfcm, - files, - flags, b"", decompressed, self.ft_ts.tracked, //offset = append @@ -365,8 +356,8 @@ impl HTTP2Transaction { impl Drop for HTTP2Transaction { fn drop(&mut self) { if let Some(sfcm) = unsafe { SURICATA_HTTP2_FILE_CONFIG } { - self.files.files_ts.free(sfcm); - self.files.files_tc.free(sfcm); + self.ft_ts.file.free(sfcm); + self.ft_tc.file.free(sfcm); } self.free(); } @@ -466,7 +457,7 @@ impl HTTP2State { if let Some(sfcm) = unsafe { SURICATA_HTTP2_FILE_CONFIG } { (c.HTPFileCloseHandleRange)( sfcm.files_sbcfg, - &mut tx.files.files_tc, + &mut tx.ft_tc.file, 0, tx.file_range, std::ptr::null_mut(), @@ -507,7 +498,7 @@ impl HTTP2State { if let Some(sfcm) = unsafe { SURICATA_HTTP2_FILE_CONFIG } { (c.HTPFileCloseHandleRange)( sfcm.files_sbcfg, - &mut tx.files.files_tc, + &mut tx.ft_tc.file, 0, tx.file_range, std::ptr::null_mut(), @@ -1216,9 +1207,12 @@ pub unsafe extern "C" fn rs_http2_getfiles( tx: *mut std::os::raw::c_void, direction: u8, ) -> AppLayerGetFileState { let tx = cast_pointer!(tx, HTTP2Transaction); - let (files, _flags) = tx.files.get(direction.into()); if let Some(sfcm) = { SURICATA_HTTP2_FILE_CONFIG } { - return AppLayerGetFileState { fc: files, cfg: sfcm.files_sbcfg } + if direction & STREAM_TOSERVER != 0 { + return AppLayerGetFileState { fc: &mut tx.ft_ts.file, cfg: sfcm.files_sbcfg } + } else { + return AppLayerGetFileState { fc: &mut tx.ft_tc.file, cfg: sfcm.files_sbcfg } + } } AppLayerGetFileState::err() } diff --git a/rust/src/http2/range.rs b/rust/src/http2/range.rs index a6510a37d9..9c96899443 100644 --- a/rust/src/http2/range.rs +++ b/rust/src/http2/range.rs @@ -131,7 +131,7 @@ pub fn http2_range_open( // whole file in one range return; } - let (_, flags) = tx.files.get(dir); + let flags = if dir == Direction::ToServer { tx.ft_ts.file_flags } else { tx.ft_tc.file_flags }; if let Ok((key, index)) = http2_range_key_get(tx) { let name = &key[index..]; tx.file_range = unsafe { @@ -162,7 +162,11 @@ pub fn http2_range_close( ) { let added = if let Some(c) = unsafe { SC } { if let Some(sfcm) = unsafe { SURICATA_HTTP2_FILE_CONFIG } { - let (files, flags) = tx.files.get(dir); + let (files, flags) = if dir == Direction::ToServer { + (&mut tx.ft_ts.file, tx.ft_ts.file_flags) + } else { + (&mut tx.ft_tc.file, tx.ft_tc.file_flags) + }; let added = (c.HTPFileCloseHandleRange)( sfcm.files_sbcfg, files, diff --git a/rust/src/nfs/nfs.rs b/rust/src/nfs/nfs.rs index 152b0c2946..475b7b7be1 100644 --- a/rust/src/nfs/nfs.rs +++ b/rust/src/nfs/nfs.rs @@ -123,6 +123,10 @@ pub enum NFSTransactionTypeData { #[derive(Default, Debug)] pub struct NFSTransactionFile { + /// file transactions are unidirectional in the sense that they track + /// a single file on one direction + pub direction: Direction, // Direction::ToClient or Direction::ToServer + /// additional procedures part of a single file transfer. Currently /// only COMMIT on WRITEs. pub file_additional_procs: Vec, @@ -139,9 +143,6 @@ pub struct NFSTransactionFile { /// file tracker for a single file. Boxed so that we don't use /// as much space if we're not a file tx. pub file_tracker: FileTransferTracker, - - /// storage for the actual file - pub files: Files, } impl NFSTransactionFile { @@ -152,8 +153,8 @@ impl NFSTransactionFile { } } pub fn update_file_flags(&mut self, flow_file_flags: u16) { - self.files.flags_ts = unsafe { FileFlowFlagsToFlags(flow_file_flags, STREAM_TOSERVER) | FILE_USE_DETECT }; - self.files.flags_tc = unsafe { FileFlowFlagsToFlags(flow_file_flags, STREAM_TOCLIENT) | FILE_USE_DETECT }; + let dir_flag = if self.direction == Direction::ToServer { STREAM_TOSERVER } else { STREAM_TOCLIENT }; + self.file_tracker.file_flags = unsafe { FileFlowFlagsToFlags(flow_file_flags, dir_flag) | FILE_USE_DETECT }; } } @@ -161,9 +162,11 @@ impl NFSTransactionFile { pub unsafe extern "C" fn rs_nfs_gettxfiles(_state: *mut std::ffi::c_void, tx: *mut std::ffi::c_void, direction: u8) -> AppLayerGetFileState { let tx = cast_pointer!(tx, NFSTransaction); if let Some(NFSTransactionTypeData::FILE(ref mut tdf)) = tx.type_data { - let (files, _flags) = tdf.files.get(direction.into()); - if let Some(sfcm) = { SURICATA_NFS_FILE_CONFIG } { - return AppLayerGetFileState { fc: files, cfg: sfcm.files_sbcfg } + let tx_dir : u8 = tdf.direction.into(); + if direction & tx_dir != 0 { + if let Some(sfcm) = { SURICATA_NFS_FILE_CONFIG } { + return AppLayerGetFileState { fc: &mut tdf.file_tracker.file, cfg: sfcm.files_sbcfg } + } } } AppLayerGetFileState::err() @@ -199,9 +202,6 @@ pub struct NFSTransaction { /// is a special file tx that we look up by file_handle instead of XID pub is_file_tx: bool, pub is_file_closed: bool, - /// file transactions are unidirectional in the sense that they track - /// a single file on one direction - pub file_tx_direction: Direction, // Direction::ToClient or Direction::ToServer pub file_handle: Vec, /// Procedure type specific data @@ -238,7 +238,6 @@ impl NFSTransaction { nfs_version:0, is_file_tx: false, is_file_closed: false, - file_tx_direction: Direction::ToServer, file_handle:Vec::new(), type_data: None, tx_data: AppLayerTxData::new(), @@ -261,8 +260,7 @@ impl Drop for NFSTransaction { fn drop(&mut self) { if let Some(NFSTransactionTypeData::FILE(ref mut tdf)) = self.type_data { if let Some(sfcm) = unsafe { SURICATA_NFS_FILE_CONFIG } { - tdf.files.files_ts.free(sfcm); - tdf.files.files_tc.free(sfcm); + tdf.file_tracker.file.free(sfcm); } } self.free(); @@ -298,37 +296,33 @@ impl NFSRequestXidMap { } /// little wrapper around the FileTransferTracker::new_chunk method -pub fn filetracker_newchunk(ft: &mut FileTransferTracker, files: &mut FileContainer, - flags: u16, name: &[u8], data: &[u8], +pub fn filetracker_newchunk(ft: &mut FileTransferTracker, name: &[u8], data: &[u8], chunk_offset: u64, chunk_size: u32, fill_bytes: u8, is_last: bool, xid: &u32) { if let Some(sfcm) = unsafe { SURICATA_NFS_FILE_CONFIG } { - ft.new_chunk(sfcm, files, flags, name, data, chunk_offset, + ft.new_chunk(sfcm, name, data, chunk_offset, chunk_size, fill_bytes, is_last, xid); } } -fn filetracker_trunc(ft: &mut FileTransferTracker, files: &mut FileContainer, - flags: u16) +fn filetracker_trunc(ft: &mut FileTransferTracker) { if let Some(sfcm) = unsafe { SURICATA_NFS_FILE_CONFIG } { - ft.trunc(sfcm, files, flags); + ft.trunc(sfcm); } } -pub fn filetracker_close(ft: &mut FileTransferTracker, files: &mut FileContainer, - flags: u16) +pub fn filetracker_close(ft: &mut FileTransferTracker) { if let Some(sfcm) = unsafe { SURICATA_NFS_FILE_CONFIG } { - ft.close(sfcm, files, flags); + ft.close(sfcm); } } -fn filetracker_update(ft: &mut FileTransferTracker, files: &mut FileContainer, - flags: u16, data: &[u8], gap_size: u32) -> u32 +fn filetracker_update(ft: &mut FileTransferTracker, data: &[u8], gap_size: u32) -> u32 { if let Some(sfcm) = unsafe { SURICATA_NFS_FILE_CONFIG } { - ft.update(sfcm, files, flags, data, gap_size) + ft.update(sfcm, data, gap_size) } else { 0 } @@ -621,8 +615,7 @@ impl NFSState { if self.ts > f.post_gap_ts { tx.request_done = true; tx.response_done = true; - let (files, flags) = f.files.get(tx.file_tx_direction); - filetracker_trunc(&mut f.file_tracker, files, flags); + filetracker_trunc(&mut f.file_tracker); } else { post_gap_txs = true; } @@ -733,10 +726,10 @@ impl NFSState { tx.file_name = file_name.to_vec(); tx.file_handle = file_handle.to_vec(); tx.is_file_tx = true; - tx.file_tx_direction = direction; tx.type_data = Some(NFSTransactionTypeData::FILE(NFSTransactionFile::new())); if let Some(NFSTransactionTypeData::FILE(ref mut d)) = tx.type_data { + d.direction = direction; d.file_tracker.tx_id = tx.id - 1; tx.tx_data.update_file_flags(self.state_data.file_flags); d.update_file_flags(tx.tx_data.file_flags); @@ -757,7 +750,7 @@ impl NFSState { for tx in &mut self.transactions { if let Some(NFSTransactionTypeData::FILE(ref mut d)) = tx.type_data { if tx.is_file_tx && !tx.is_file_closed && - direction == tx.file_tx_direction && + direction == d.direction && tx.file_handle == fh { tx.tx_data.update_file_flags(self.state_data.file_flags); @@ -797,8 +790,7 @@ impl NFSState { let found = match self.get_file_tx_by_handle(&file_handle, Direction::ToServer) { Some(tx) => { if let Some(NFSTransactionTypeData::FILE(ref mut tdf)) = tx.type_data { - let (files, flags) = tdf.files.get(Direction::ToServer); - filetracker_newchunk(&mut tdf.file_tracker, files, flags, + filetracker_newchunk(&mut tdf.file_tracker, &file_name, w.file_data, w.offset, w.file_len, fill_bytes as u8, is_last, &r.hdr.xid); tdf.chunk_count += 1; @@ -818,8 +810,7 @@ impl NFSState { if !found { let tx = self.new_file_tx(&file_handle, &file_name, Direction::ToServer); if let Some(NFSTransactionTypeData::FILE(ref mut tdf)) = tx.type_data { - let (files, flags) = tdf.files.get(Direction::ToServer); - filetracker_newchunk(&mut tdf.file_tracker, files, flags, + filetracker_newchunk(&mut tdf.file_tracker, &file_name, w.file_data, w.offset, w.file_len, fill_bytes as u8, is_last, &r.hdr.xid); tx.procedure = NFSPROC3_WRITE; @@ -972,12 +963,11 @@ impl NFSState { let consumed = match self.get_file_tx_by_handle(&file_handle, direction) { Some(tx) => { if let Some(NFSTransactionTypeData::FILE(ref mut tdf)) = tx.type_data { - let (files, flags) = tdf.files.get(direction); if ssn_gap { let queued_data = tdf.file_tracker.get_queued_size(); if queued_data > 2000000 { // TODO should probably be configurable SCLogDebug!("QUEUED size {} while we've seen GAPs. Truncating file.", queued_data); - filetracker_trunc(&mut tdf.file_tracker, files, flags); + filetracker_trunc(&mut tdf.file_tracker); } } @@ -987,7 +977,7 @@ impl NFSState { } tdf.chunk_count += 1; - let cs = filetracker_update(&mut tdf.file_tracker, files, flags, data, gap_size); + let cs = filetracker_update(&mut tdf.file_tracker, data, gap_size); /* see if we need to close the tx */ if tdf.file_tracker.is_done() { if direction == Direction::ToClient { @@ -1076,8 +1066,7 @@ impl NFSState { Some(tx) => { SCLogDebug!("updated TX {:?}", tx); if let Some(NFSTransactionTypeData::FILE(ref mut tdf)) = tx.type_data { - let (files, flags) = tdf.files.get(Direction::ToClient); - filetracker_newchunk(&mut tdf.file_tracker, files, flags, + filetracker_newchunk(&mut tdf.file_tracker, &file_name, reply.data, chunk_offset, reply.count, fill_bytes as u8, is_last, &r.hdr.xid); tdf.chunk_count += 1; @@ -1105,8 +1094,7 @@ impl NFSState { if !found { let tx = self.new_file_tx(&file_handle, &file_name, Direction::ToClient); if let Some(NFSTransactionTypeData::FILE(ref mut tdf)) = tx.type_data { - let (files, flags) = tdf.files.get(Direction::ToClient); - filetracker_newchunk(&mut tdf.file_tracker, files, flags, + filetracker_newchunk(&mut tdf.file_tracker, &file_name, reply.data, chunk_offset, reply.count, fill_bytes as u8, is_last, &r.hdr.xid); tx.procedure = if nfs_version < 4 { NFSPROC3_READ } else { NFSPROC4_READ }; diff --git a/rust/src/nfs/nfs3.rs b/rust/src/nfs/nfs3.rs index 89dd0705d2..0de27d5965 100644 --- a/rust/src/nfs/nfs3.rs +++ b/rust/src/nfs/nfs3.rs @@ -120,10 +120,9 @@ impl NFSState { let file_handle = rd.handle.value.to_vec(); if let Some(tx) = self.get_file_tx_by_handle(&file_handle, Direction::ToServer) { if let Some(NFSTransactionTypeData::FILE(ref mut tdf)) = tx.type_data { - let (files, flags) = tdf.files.get(Direction::ToServer); tdf.chunk_count += 1; tdf.file_additional_procs.push(NFSPROC3_COMMIT); - filetracker_close(&mut tdf.file_tracker, files, flags); + filetracker_close(&mut tdf.file_tracker); tdf.file_last_xid = r.hdr.xid; tx.is_last = true; tx.request_done = true; diff --git a/rust/src/nfs/nfs4.rs b/rust/src/nfs/nfs4.rs index 7bb650caca..d0d365972b 100644 --- a/rust/src/nfs/nfs4.rs +++ b/rust/src/nfs/nfs4.rs @@ -68,8 +68,7 @@ impl NFSState { let found = match self.get_file_tx_by_handle(&file_handle, Direction::ToServer) { Some(tx) => { if let Some(NFSTransactionTypeData::FILE(ref mut tdf)) = tx.type_data { - let (files, flags) = tdf.files.get(Direction::ToServer); - filetracker_newchunk(&mut tdf.file_tracker, files, flags, + filetracker_newchunk(&mut tdf.file_tracker, &file_name, w.data, w.offset, w.write_len, fill_bytes as u8, is_last, &r.hdr.xid); tdf.chunk_count += 1; @@ -86,8 +85,7 @@ impl NFSState { if !found { let tx = self.new_file_tx(&file_handle, &file_name, Direction::ToServer); if let Some(NFSTransactionTypeData::FILE(ref mut tdf)) = tx.type_data { - let (files, flags) = tdf.files.get(Direction::ToServer); - filetracker_newchunk(&mut tdf.file_tracker, files, flags, + filetracker_newchunk(&mut tdf.file_tracker, &file_name, w.data, w.offset, w.write_len, fill_bytes as u8, is_last, &r.hdr.xid); tx.procedure = NFSPROC4_WRITE; @@ -117,8 +115,7 @@ impl NFSState { let file_handle = fh.to_vec(); if let Some(tx) = self.get_file_tx_by_handle(&file_handle, Direction::ToServer) { if let Some(NFSTransactionTypeData::FILE(ref mut tdf)) = tx.type_data { - let (files, flags) = tdf.files.get(Direction::ToServer); - filetracker_close(&mut tdf.file_tracker, files, flags); + filetracker_close(&mut tdf.file_tracker); tdf.file_last_xid = r.hdr.xid; tx.is_last = true; tx.request_done = true; diff --git a/rust/src/smb/files.rs b/rust/src/smb/files.rs index 9d759729ea..996794b529 100644 --- a/rust/src/smb/files.rs +++ b/rust/src/smb/files.rs @@ -33,7 +33,7 @@ pub struct SMBTransactionFile { /// after a gap, this will be set to a time in the future. If the file /// receives no updates before that, it will be considered complete. pub post_gap_ts: u64, - pub files: Files, + //pub files: Files, } impl SMBTransactionFile { @@ -45,43 +45,39 @@ impl SMBTransactionFile { } pub fn update_file_flags(&mut self, flow_file_flags: u16) { - self.files.flags_ts = unsafe { FileFlowFlagsToFlags(flow_file_flags, STREAM_TOSERVER) | FILE_USE_DETECT }; - self.files.flags_tc = unsafe { FileFlowFlagsToFlags(flow_file_flags, STREAM_TOCLIENT) | FILE_USE_DETECT }; + let dir_flag = if self.direction == Direction::ToServer { STREAM_TOSERVER } else { STREAM_TOCLIENT }; + self.file_tracker.file_flags = unsafe { FileFlowFlagsToFlags(flow_file_flags, dir_flag) | FILE_USE_DETECT }; } } /// little wrapper around the FileTransferTracker::new_chunk method -pub fn filetracker_newchunk(ft: &mut FileTransferTracker, files: &mut FileContainer, - flags: u16, name: &[u8], data: &[u8], +pub fn filetracker_newchunk(ft: &mut FileTransferTracker, name: &[u8], data: &[u8], chunk_offset: u64, chunk_size: u32, is_last: bool, xid: &u32) { if let Some(sfcm) = unsafe { SURICATA_SMB_FILE_CONFIG } { - ft.new_chunk(sfcm, files, flags, name, data, chunk_offset, + ft.new_chunk(sfcm, name, data, chunk_offset, chunk_size, 0, is_last, xid); } } -pub fn filetracker_trunc(ft: &mut FileTransferTracker, files: &mut FileContainer, - flags: u16) +pub fn filetracker_trunc(ft: &mut FileTransferTracker) { if let Some(sfcm) = unsafe { SURICATA_SMB_FILE_CONFIG } { - ft.trunc(sfcm, files, flags); + ft.trunc(sfcm); } } -pub fn filetracker_close(ft: &mut FileTransferTracker, files: &mut FileContainer, - flags: u16) +pub fn filetracker_close(ft: &mut FileTransferTracker) { if let Some(sfcm) = unsafe { SURICATA_SMB_FILE_CONFIG } { - ft.close(sfcm, files, flags); + ft.close(sfcm); } } -fn filetracker_update(ft: &mut FileTransferTracker, files: &mut FileContainer, - flags: u16, data: &[u8], gap_size: u32) -> u32 +fn filetracker_update(ft: &mut FileTransferTracker, data: &[u8], gap_size: u32) -> u32 { if let Some(sfcm) = unsafe { SURICATA_SMB_FILE_CONFIG } { - ft.update(sfcm, files, flags, data, gap_size) + ft.update(sfcm, data, gap_size) } else { 0 } @@ -204,12 +200,11 @@ impl SMBState { let consumed = match self.get_file_tx_by_fuid(&file_handle, direction) { Some(tx) => { if let Some(SMBTransactionTypeData::FILE(ref mut tdf)) = tx.type_data { - let (files, flags) = tdf.files.get(direction); if ssn_gap { let queued_data = tdf.file_tracker.get_queued_size(); if queued_data > 2000000 { // TODO should probably be configurable SCLogDebug!("QUEUED size {} while we've seen GAPs. Truncating file.", queued_data); - filetracker_trunc(&mut tdf.file_tracker, files, flags); + filetracker_trunc(&mut tdf.file_tracker); } } @@ -219,7 +214,7 @@ impl SMBState { } let file_data = &data[0..data_to_handle_len]; - filetracker_update(&mut tdf.file_tracker, files, flags, file_data, gap_size) + filetracker_update(&mut tdf.file_tracker, file_data, gap_size) } else { 0 } @@ -238,9 +233,11 @@ use crate::applayer::AppLayerGetFileState; pub unsafe extern "C" fn rs_smb_gettxfiles(_state: *mut std::ffi::c_void, tx: *mut std::ffi::c_void, direction: u8) -> AppLayerGetFileState { let tx = cast_pointer!(tx, SMBTransaction); if let Some(SMBTransactionTypeData::FILE(ref mut tdf)) = tx.type_data { - let (files, _flags) = tdf.files.get(direction.into()); - if let Some(sfcm) = { SURICATA_SMB_FILE_CONFIG } { - return AppLayerGetFileState { fc: files, cfg: sfcm.files_sbcfg } + let tx_dir : u8 = tdf.direction.into(); + if direction & tx_dir != 0 { + if let Some(sfcm) = { SURICATA_SMB_FILE_CONFIG } { + return AppLayerGetFileState { fc: &mut tdf.file_tracker.file, cfg: sfcm.files_sbcfg } + } } } AppLayerGetFileState::err() diff --git a/rust/src/smb/smb.rs b/rust/src/smb/smb.rs index 5d04039f13..f4a78d2851 100644 --- a/rust/src/smb/smb.rs +++ b/rust/src/smb/smb.rs @@ -530,8 +530,7 @@ impl Drop for SMBTransaction { fn drop(&mut self) { if let Some(SMBTransactionTypeData::FILE(ref mut tdf)) = self.type_data { if let Some(sfcm) = unsafe { SURICATA_SMB_FILE_CONFIG } { - tdf.files.files_ts.free(sfcm); - tdf.files.files_tc.free(sfcm); + tdf.file_tracker.file.free(sfcm); } } self.free(); @@ -1103,8 +1102,7 @@ impl SMBState { if self.ts > f.post_gap_ts { tx.request_done = true; tx.response_done = true; - let (files, flags) = f.files.get(f.direction); - filetracker_trunc(&mut f.file_tracker, files, flags); + filetracker_trunc(&mut f.file_tracker); } else { post_gap_txs = true; } diff --git a/rust/src/smb/smb1.rs b/rust/src/smb/smb1.rs index 3ddcf6ddf7..e6f42ccfcc 100644 --- a/rust/src/smb/smb1.rs +++ b/rust/src/smb/smb1.rs @@ -155,8 +155,7 @@ fn smb1_close_file(state: &mut SMBState, fid: &[u8], direction: Direction) if let Some(SMBTransactionTypeData::FILE(ref mut tdf)) = tx.type_data { if !tx.request_done { SCLogDebug!("closing file tx {} FID {:?}", tx.id, fid); - let (files, flags) = tdf.files.get(direction); - filetracker_close(&mut tdf.file_tracker, files, flags); + filetracker_close(&mut tdf.file_tracker); tx.request_done = true; tx.response_done = true; SCLogDebug!("tx {} is done", tx.id); @@ -965,8 +964,7 @@ pub fn smb1_write_request_record<'b>(state: &mut SMBState, r: &SmbRecord<'b>, an if rd.offset < tdf.file_tracker.tracked { set_event_fileoverlap = true; } - let (files, flags) = tdf.files.get(Direction::ToServer); - filetracker_newchunk(&mut tdf.file_tracker, files, flags, + filetracker_newchunk(&mut tdf.file_tracker, &file_name, rd.data, rd.offset, rd.len, false, &file_id); SCLogDebug!("FID {:?} found at tx {} => {:?}", file_fid, tx.id, tx); @@ -993,12 +991,10 @@ pub fn smb1_write_request_record<'b>(state: &mut SMBState, r: &SmbRecord<'b>, an if rd.offset < tdf.file_tracker.tracked { set_event_fileoverlap = true; } - let (files, flags) = tdf.files.get(Direction::ToServer); - filetracker_newchunk(&mut tdf.file_tracker, files, flags, + filetracker_newchunk(&mut tdf.file_tracker, &file_name, rd.data, rd.offset, rd.len, false, &file_id); tdf.share_name = share_name; - SCLogDebug!("files {:?}", files); SCLogDebug!("tdf {:?}", tdf); } tx.vercmd.set_smb1_cmd(SMB1_COMMAND_WRITE_ANDX); @@ -1063,8 +1059,7 @@ pub fn smb1_read_response_record<'b>(state: &mut SMBState, r: &SmbRecord<'b>, an if offset < tdf.file_tracker.tracked { set_event_fileoverlap = true; } - let (files, flags) = tdf.files.get(Direction::ToClient); - filetracker_newchunk(&mut tdf.file_tracker, files, flags, + filetracker_newchunk(&mut tdf.file_tracker, &file_name, rd.data, offset, rd.len, false, &file_id); } @@ -1080,8 +1075,7 @@ pub fn smb1_read_response_record<'b>(state: &mut SMBState, r: &SmbRecord<'b>, an if offset < tdf.file_tracker.tracked { set_event_fileoverlap = true; } - let (files, flags) = tdf.files.get(Direction::ToClient); - filetracker_newchunk(&mut tdf.file_tracker, files, flags, + filetracker_newchunk(&mut tdf.file_tracker, &file_name, rd.data, offset, rd.len, false, &file_id); tdf.share_name = share_name; diff --git a/rust/src/smb/smb2.rs b/rust/src/smb/smb2.rs index b9fb924ffc..e83e312f1f 100644 --- a/rust/src/smb/smb2.rs +++ b/rust/src/smb/smb2.rs @@ -171,8 +171,7 @@ pub fn smb2_read_response_record<'b>(state: &mut SMBState, r: &Smb2Record<'b>) state.set_event(SMBEvent::ReadQueueCntExceeded); state.set_skip(Direction::ToClient, rd.len, rd.data.len() as u32); } else { - let (files, flags) = tdf.files.get(Direction::ToClient); - filetracker_newchunk(&mut tdf.file_tracker, files, flags, + filetracker_newchunk(&mut tdf.file_tracker, &tdf.file_name, rd.data, offset, rd.len, false, &file_id); } @@ -245,8 +244,7 @@ pub fn smb2_read_response_record<'b>(state: &mut SMBState, r: &Smb2Record<'b>) state.set_event(SMBEvent::ReadQueueCntExceeded); state.set_skip(Direction::ToClient, rd.len, rd.data.len() as u32); } else { - let (files, flags) = tdf.files.get(Direction::ToClient); - filetracker_newchunk(&mut tdf.file_tracker, files, flags, + filetracker_newchunk(&mut tdf.file_tracker, &file_name, rd.data, offset, rd.len, false, &file_id); } @@ -311,8 +309,7 @@ pub fn smb2_write_request_record<'b>(state: &mut SMBState, r: &Smb2Record<'b>) state.set_event(SMBEvent::WriteQueueCntExceeded); state.set_skip(Direction::ToServer, wr.wr_len, wr.data.len() as u32); } else { - let (files, flags) = tdf.files.get(Direction::ToServer); - filetracker_newchunk(&mut tdf.file_tracker, files, flags, + filetracker_newchunk(&mut tdf.file_tracker, &file_name, wr.data, wr.wr_offset, wr.wr_len, false, &file_id); } @@ -380,8 +377,7 @@ pub fn smb2_write_request_record<'b>(state: &mut SMBState, r: &Smb2Record<'b>) state.set_event(SMBEvent::WriteQueueCntExceeded); state.set_skip(Direction::ToServer, wr.wr_len, wr.data.len() as u32); } else { - let (files, flags) = tdf.files.get(Direction::ToServer); - filetracker_newchunk(&mut tdf.file_tracker, files, flags, + filetracker_newchunk(&mut tdf.file_tracker, &file_name, wr.data, wr.wr_offset, wr.wr_len, false, &file_id); } @@ -594,8 +590,7 @@ pub fn smb2_request_record<'b>(state: &mut SMBState, r: &Smb2Record<'b>) Some(tx) => { if !tx.request_done { if let Some(SMBTransactionTypeData::FILE(ref mut tdf)) = tx.type_data { - let (files, flags) = tdf.files.get(Direction::ToServer); - filetracker_close(&mut tdf.file_tracker, files, flags); + filetracker_close(&mut tdf.file_tracker); } } tx.request_done = true; @@ -609,8 +604,7 @@ pub fn smb2_request_record<'b>(state: &mut SMBState, r: &Smb2Record<'b>) Some(tx) => { if !tx.request_done { if let Some(SMBTransactionTypeData::FILE(ref mut tdf)) = tx.type_data { - let (files, flags) = tdf.files.get(Direction::ToClient); - filetracker_close(&mut tdf.file_tracker, files, flags); + filetracker_close(&mut tdf.file_tracker); } } tx.request_done = true; @@ -708,8 +702,7 @@ pub fn smb2_response_record<'b>(state: &mut SMBState, r: &Smb2Record<'b>) Some(tx) => { if !tx.request_done { if let Some(SMBTransactionTypeData::FILE(ref mut tdf)) = tx.type_data { - let (files, flags) = tdf.files.get(Direction::ToClient); - filetracker_close(&mut tdf.file_tracker, files, flags); + filetracker_close(&mut tdf.file_tracker); } } tx.set_status(r.nt_status, false);