From: Victor Julien Date: Wed, 14 Mar 2018 09:26:40 +0000 (+0100) Subject: smb: log file FID/GUID as fuid X-Git-Tag: suricata-4.1.0-beta1~59 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fb986abe81f5948724eb152318ec9b592120e6b5;p=thirdparty%2Fsuricata.git smb: log file FID/GUID as fuid --- diff --git a/rust/src/smb/files.rs b/rust/src/smb/files.rs index 7064ab2ec1..83a0ffd4bc 100644 --- a/rust/src/smb/files.rs +++ b/rust/src/smb/files.rs @@ -26,7 +26,7 @@ use smb::smb::*; #[derive(Debug)] pub struct SMBTransactionFile { pub direction: u8, - pub guid: Vec, + pub fuid: Vec, pub file_name: Vec, pub share_name: Vec, pub file_tracker: FileTransferTracker, @@ -36,7 +36,7 @@ impl SMBTransactionFile { pub fn new() -> SMBTransactionFile { return SMBTransactionFile { direction: 0, - guid: Vec::new(), + fuid: Vec::new(), file_name: Vec::new(), share_name: Vec::new(), file_tracker: FileTransferTracker::new(), @@ -91,7 +91,7 @@ pub fn filetracker_newchunk(ft: &mut FileTransferTracker, files: &mut FileContai } impl SMBState { - pub fn new_file_tx(&mut self, file_guid: &Vec, file_name: &Vec, direction: u8) + pub fn new_file_tx(&mut self, fuid: &Vec, file_name: &Vec, direction: u8) -> (&mut SMBTransaction, &mut FileContainer, u16) { let mut tx = self.new_tx(); @@ -99,7 +99,7 @@ impl SMBState { match tx.type_data { Some(SMBTransactionTypeData::FILE(ref mut d)) => { d.direction = direction; - d.guid = file_guid.to_vec(); + d.fuid = fuid.to_vec(); d.file_name = file_name.to_vec(); d.file_tracker.tx_id = tx.id - 1; }, @@ -113,14 +113,14 @@ impl SMBState { return (tx_ref.unwrap(), files, flags) } - pub fn get_file_tx_by_guid(&mut self, guid: &Vec, direction: u8) + pub fn get_file_tx_by_fuid(&mut self, fuid: &Vec, direction: u8) -> Option<(&mut SMBTransaction, &mut FileContainer, u16)> { - let g = guid.to_vec(); + let f = fuid.to_vec(); for tx in &mut self.transactions { let found = match tx.type_data { Some(SMBTransactionTypeData::FILE(ref mut d)) => { - direction == d.direction && g == d.guid + direction == d.direction && f == d.fuid }, _ => { false }, }; @@ -131,7 +131,7 @@ impl SMBState { return Some((tx, files, flags)); } } - SCLogDebug!("SMB: Failed to find SMB TX with GUID {:?}", guid); + SCLogDebug!("SMB: Failed to find SMB TX with FUID {:?}", fuid); return None; } @@ -190,7 +190,7 @@ impl SMBState { let ssn_gap = self.ts_ssn_gap | self.tc_ssn_gap; // get the tx and update it - let consumed = match self.get_file_tx_by_guid(&file_handle, direction) { + let consumed = match self.get_file_tx_by_fuid(&file_handle, direction) { Some((tx, files, flags)) => { if let Some(SMBTransactionTypeData::FILE(ref mut tdf)) = tx.type_data { if ssn_gap { diff --git a/rust/src/smb/log.rs b/rust/src/smb/log.rs index 87c612e478..8b58fa0344 100644 --- a/rust/src/smb/log.rs +++ b/rust/src/smb/log.rs @@ -25,7 +25,6 @@ use smb::smb1::*; use smb::smb2::*; use smb::dcerpc::*; use smb::funcs::*; -use nom; #[cfg(not(feature = "debug"))] fn debug_add_progress(_js: &Json, _tx: &SMBTransaction) { } @@ -36,6 +35,24 @@ fn debug_add_progress(js: &Json, tx: &SMBTransaction) { js.set_boolean("response_done", tx.request_done); } +/// take in a file GUID (16 bytes) or FID (2 bytes). Also deal +/// with our frankenFID (2 bytes + 4 user_id) +fn fuid_to_string(fuid: &Vec) -> String { + let fuid_len = fuid.len(); + if fuid_len == 16 { + guid_to_string(fuid) + } else if fuid_len == 2 { + let o = format!("{:02x}{:02x}", fuid[1], fuid[0]); + o.to_string() + } else if fuid_len == 6 { + let pure_fid = &fuid[0..2]; + let o = format!("{:02x}{:02x}", pure_fid[1], pure_fid[0]); + o.to_string() + } else { + "".to_string() + } +} + fn guid_to_string(guid: &Vec) -> String { if guid.len() == 16 { let output = format!("{:02x}{:02x}{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}", @@ -243,6 +260,9 @@ fn smb_common_header(state: &SMBState, tx: &SMBTransaction) -> Json js.set_integer("modified", x.last_write_ts as u64); js.set_integer("changed", x.last_change_ts as u64); js.set_integer("size", x.size); + + let gs = fuid_to_string(&x.guid); + js.set_string("fuid", &gs); }, Some(SMBTransactionTypeData::NEGOTIATE(ref x)) => { if x.smb_ver == 1 { @@ -304,21 +324,16 @@ fn smb_common_header(state: &SMBState, tx: &SMBTransaction) -> Json Some(SMBTransactionTypeData::FILE(ref x)) => { let file_name = String::from_utf8_lossy(&x.file_name); js.set_string("filename", &file_name); - let share_name = String::from_utf8_lossy(&x.share_name); - js.set_string("share", &share_name); - + if x.share_name.len() > 0 { + let share_name = String::from_utf8_lossy(&x.share_name); + js.set_string("share", &share_name); + } else { + // name suggestion from Bro + js.set_string("share", ""); + }; - if x.guid.len() >= 2 { - let fid_s = &x.guid[0..2]; - let fid_n = match nom::le_u16(&fid_s) { - nom::IResult::Done(_, x) => { - x as u16 - } - _ => 0 as u16 - }; - let fid_hex_str = format!("0x{:00x}", fid_n); - js.set_string("fid", &fid_hex_str); - } + let gs = fuid_to_string(&x.fuid); + js.set_string("fuid", &gs); }, Some(SMBTransactionTypeData::DCERPC(ref x)) => { let jsd = Json::object(); diff --git a/rust/src/smb/smb.rs b/rust/src/smb/smb.rs index c6ada4429b..9fcf4ba808 100644 --- a/rust/src/smb/smb.rs +++ b/rust/src/smb/smb.rs @@ -371,6 +371,7 @@ pub struct SMBTransactionCreate { pub delete_on_close: bool, pub directory: bool, pub filename: Vec, + pub guid: Vec, pub create_ts: u32, pub last_access_ts: u32, @@ -387,6 +388,7 @@ impl SMBTransactionCreate { delete_on_close: del, directory: dir, filename: filename, + guid: Vec::new(), create_ts: 0, last_access_ts: 0, last_write_ts: 0, diff --git a/rust/src/smb/smb1.rs b/rust/src/smb/smb1.rs index 8fafe0ea7d..df704551cd 100644 --- a/rust/src/smb/smb1.rs +++ b/rust/src/smb/smb1.rs @@ -135,7 +135,7 @@ fn smb1_close_file(state: &mut SMBState, fid: &Vec) { // we can have created 2 txs for a FID: one for reads // and one for writes. So close both. - match state.get_file_tx_by_guid(&fid, STREAM_TOSERVER) { + match state.get_file_tx_by_fuid(&fid, STREAM_TOSERVER) { Some((tx, files, flags)) => { SCLogDebug!("found tx {}", tx.id); if let Some(SMBTransactionTypeData::FILE(ref mut tdf)) = tx.type_data { @@ -146,13 +146,11 @@ fn smb1_close_file(state: &mut SMBState, fid: &Vec) tx.response_done = true; SCLogDebug!("tx {} is done", tx.id); } - // as a precaution, reset guid so it can be reused - tdf.guid.clear(); // TODO review } }, None => { }, } - match state.get_file_tx_by_guid(&fid, STREAM_TOCLIENT) { + match state.get_file_tx_by_fuid(&fid, STREAM_TOCLIENT) { Some((tx, files, flags)) => { SCLogDebug!("found tx {}", tx.id); if let Some(SMBTransactionTypeData::FILE(ref mut tdf)) = tx.type_data { @@ -163,8 +161,6 @@ fn smb1_close_file(state: &mut SMBState, fid: &Vec) tx.response_done = true; SCLogDebug!("tx {} is done", tx.id); } - // as a precaution, reset guid so it can be reused - tdf.guid.clear(); // TODO review now that fid is improved } }, None => { }, @@ -513,6 +509,7 @@ pub fn smb1_response_record<'b>(state: &mut SMBState, r: &SmbRecord<'b>) -> u32 tdn.last_write_ts = cr.last_write_ts.as_unix(); tdn.last_change_ts = cr.last_change_ts.as_unix(); tdn.size = cr.file_size; + tdn.guid = cr.fid.to_vec(); } } true @@ -713,7 +710,7 @@ pub fn smb1_write_request_record<'b>(state: &mut SMBState, r: &SmbRecord<'b>) Some(n) => n.to_vec(), None => Vec::new(), }; - let found = match state.get_file_tx_by_guid(&file_fid, STREAM_TOSERVER) { + let found = match state.get_file_tx_by_fuid(&file_fid, STREAM_TOSERVER) { Some((tx, files, flags)) => { let file_id : u32 = tx.id as u32; if let Some(SMBTransactionTypeData::FILE(ref mut tdf)) = tx.type_data { @@ -797,7 +794,7 @@ pub fn smb1_read_response_record<'b>(state: &mut SMBState, r: &SmbRecord<'b>) Some(n) => n.to_vec(), None => Vec::new(), }; - let found = match state.get_file_tx_by_guid(&file_fid, STREAM_TOCLIENT) { + let found = match state.get_file_tx_by_fuid(&file_fid, STREAM_TOCLIENT) { Some((tx, files, flags)) => { if let Some(SMBTransactionTypeData::FILE(ref mut tdf)) = tx.type_data { let file_id : u32 = tx.id as u32; diff --git a/rust/src/smb/smb2.rs b/rust/src/smb/smb2.rs index 7f4ee2642b..9da07ba57c 100644 --- a/rust/src/smb/smb2.rs +++ b/rust/src/smb/smb2.rs @@ -132,7 +132,7 @@ pub fn smb2_read_response_record<'b>(state: &mut SMBState, r: &Smb2Record<'b>) SCLogDebug!("SMBv2 READ: GUID {:?} offset {}", file_guid, offset); // look up existing tracker and if we have it update it - let found = match state.get_file_tx_by_guid(&file_guid, STREAM_TOCLIENT) { + let found = match state.get_file_tx_by_fuid(&file_guid, STREAM_TOCLIENT) { Some((tx, files, flags)) => { if let Some(SMBTransactionTypeData::FILE(ref mut tdf)) = tx.type_data { let file_id : u32 = tx.id as u32; @@ -209,7 +209,7 @@ pub fn smb2_write_request_record<'b>(state: &mut SMBState, r: &Smb2Record<'b>) None => Vec::new(), }; - let found = match state.get_file_tx_by_guid(&file_guid, STREAM_TOSERVER) { + let found = match state.get_file_tx_by_fuid(&file_guid, STREAM_TOSERVER) { Some((tx, files, flags)) => { if let Some(SMBTransactionTypeData::FILE(ref mut tdf)) = tx.type_data { let file_id : u32 = tx.id as u32; @@ -385,7 +385,7 @@ pub fn smb2_request_record<'b>(state: &mut SMBState, r: &Smb2Record<'b>) SMB2_COMMAND_CLOSE => { match parse_smb2_request_close(r.data) { IResult::Done(_, cd) => { - let found_ts = match state.get_file_tx_by_guid(&cd.guid.to_vec(), STREAM_TOSERVER) { + let found_ts = match state.get_file_tx_by_fuid(&cd.guid.to_vec(), STREAM_TOSERVER) { Some((tx, files, flags)) => { if !tx.request_done { if let Some(SMBTransactionTypeData::FILE(ref mut tdf)) = tx.type_data { @@ -399,7 +399,7 @@ pub fn smb2_request_record<'b>(state: &mut SMBState, r: &Smb2Record<'b>) }, None => { false }, }; - let found_tc = match state.get_file_tx_by_guid(&cd.guid.to_vec(), STREAM_TOCLIENT) { + let found_tc = match state.get_file_tx_by_fuid(&cd.guid.to_vec(), STREAM_TOCLIENT) { Some((tx, files, flags)) => { if !tx.request_done { if let Some(SMBTransactionTypeData::FILE(ref mut tdf)) = tx.type_data { @@ -498,7 +498,7 @@ pub fn smb2_response_record<'b>(state: &mut SMBState, r: &Smb2Record<'b>) Vec::new() }, }; - let found = match state.get_file_tx_by_guid(&file_guid, STREAM_TOCLIENT) { + let found = match state.get_file_tx_by_fuid(&file_guid, STREAM_TOCLIENT) { Some((tx, files, flags)) => { if !tx.request_done { if let Some(SMBTransactionTypeData::FILE(ref mut tdf)) = tx.type_data { @@ -547,6 +547,7 @@ pub fn smb2_response_record<'b>(state: &mut SMBState, r: &Smb2Record<'b>) tdn.last_write_ts = cr.last_write_ts.as_unix(); tdn.last_change_ts = cr.last_change_ts.as_unix(); tdn.size = cr.size; + tdn.guid = cr.guid.to_vec(); } } }