]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
smb: log file FID/GUID as fuid
authorVictor Julien <victor@inliniac.net>
Wed, 14 Mar 2018 09:26:40 +0000 (10:26 +0100)
committerVictor Julien <victor@inliniac.net>
Wed, 14 Mar 2018 09:54:55 +0000 (10:54 +0100)
rust/src/smb/files.rs
rust/src/smb/log.rs
rust/src/smb/smb.rs
rust/src/smb/smb1.rs
rust/src/smb/smb2.rs

index 7064ab2ec196cfa82570697b30f5960cc4b18438..83a0ffd4bc4e4db031ed6c347a5071bdd97f4624 100644 (file)
@@ -26,7 +26,7 @@ use smb::smb::*;
 #[derive(Debug)]
 pub struct SMBTransactionFile {
     pub direction: u8,
-    pub guid: Vec<u8>,
+    pub fuid: Vec<u8>,
     pub file_name: Vec<u8>,
     pub share_name: Vec<u8>,
     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<u8>, file_name: &Vec<u8>, direction: u8)
+    pub fn new_file_tx(&mut self, fuid: &Vec<u8>, file_name: &Vec<u8>, 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<u8>, direction: u8)
+    pub fn get_file_tx_by_fuid(&mut self, fuid: &Vec<u8>, 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 {
index 87c612e478e08ba323aec8797bc2ab7bdafdb467..8b58fa0344e65b8ef414a93319c93ce41eb2c31b 100644 (file)
@@ -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<u8>) -> 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<u8>) -> 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", "<share_root>");
+            };
 
-            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();
index c6ada4429baefb5ec661583feba5d2c45eac530a..9fcf4ba8080131f3d05103be49aaf29887bc56d9 100644 (file)
@@ -371,6 +371,7 @@ pub struct SMBTransactionCreate {
     pub delete_on_close: bool,
     pub directory: bool,
     pub filename: Vec<u8>,
+    pub guid: Vec<u8>,
 
     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,
index 8fafe0ea7de43b0b8c3749d68b4953da9a3b8628..df704551cd2e9d27fbbf26059486569e06c84f0d 100644 (file)
@@ -135,7 +135,7 @@ fn smb1_close_file(state: &mut SMBState, fid: &Vec<u8>)
 {
     // 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<u8>)
                     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<u8>)
                     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;
index 7f4ee2642b05ba5ef2e5e08d6e66629f5fb01711..9da07ba57ca9825520d6123fa15e78be0c0af9a5 100644 (file)
@@ -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();
                             }
                         }
                     }