]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
smb2: parse and log timestamps in CREATE
authorVictor Julien <victor@inliniac.net>
Fri, 9 Mar 2018 09:27:13 +0000 (10:27 +0100)
committerVictor Julien <victor@inliniac.net>
Mon, 12 Mar 2018 14:34:43 +0000 (15:34 +0100)
rust/src/smb/log.rs
rust/src/smb/smb.rs
rust/src/smb/smb2.rs
rust/src/smb/smb2_records.rs

index 774e4a98e2cbccfb28b9c1a47b98c2d6d274320d..d6fd44920eb56b9b7cc7c1df72a07d8adfc2516b 100644 (file)
@@ -193,6 +193,13 @@ fn smb_common_header(state: &SMBState, tx: &SMBTransaction) -> Json
             } else {
                 js.set_string("access", "normal");
             }
+
+            // field names inspired by Bro
+            js.set_integer("created", x.create_ts as u64);
+            js.set_integer("accessed", x.last_access_ts as u64);
+            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);
         },
         Some(SMBTransactionTypeData::NEGOTIATE(ref x)) => {
             if x.smb_ver == 1 {
index 2dab57447e9a699b2c7772c4caba3283e4ff359c..64883785ac0cfb291c5e8746451e8a6209458974 100644 (file)
@@ -304,6 +304,32 @@ impl SMBVerCmdStat {
     }
 }
 
+/// "The FILETIME structure is a 64-bit value that represents the number of
+/// 100-nanosecond intervals that have elapsed since January 1, 1601,
+/// Coordinated Universal Time (UTC)."
+#[derive(Eq, PartialEq, Debug, Clone)]
+pub struct SMBFiletime {
+    ts: u64, 
+}
+
+impl SMBFiletime {
+    pub fn new(raw: u64) -> SMBFiletime {
+        SMBFiletime {
+            ts: raw,
+        }
+    }
+
+    /// inspired by Bro, convert FILETIME to secs since unix epoch
+    pub fn as_unix(&self) -> u32 {
+        if self.ts > 116_444_736_000_000_000_u64 {
+            let ts = self.ts / 10000000 - 11644473600;
+            ts as u32
+        } else {
+            0
+        }
+    }
+}
+
 #[derive(Debug)]
 pub enum SMBTransactionTypeData {
     FILE(SMBTransactionFile),
@@ -320,6 +346,13 @@ pub struct SMBTransactionCreate {
     pub delete_on_close: bool,
     pub directory: bool,
     pub filename: Vec<u8>,
+
+    pub create_ts: u32,
+    pub last_access_ts: u32,
+    pub last_write_ts: u32,
+    pub last_change_ts: u32,
+
+    pub size: u64,
 }
 
 impl SMBTransactionCreate {
@@ -329,6 +362,11 @@ impl SMBTransactionCreate {
             delete_on_close: del,
             directory: dir,
             filename: filename,
+            create_ts: 0,
+            last_access_ts: 0,
+            last_write_ts: 0,
+            last_change_ts: 0,
+            size: 0,
         }
     }
 }
index bd068f34693a02b0b19b137ddb8f85dd0b2cc358..f1462c79eade8cc30fec485da679ce0982ec5ce2 100644 (file)
@@ -597,22 +597,37 @@ pub fn smb2_response_record<'b>(state: &mut SMBState, r: &Smb2Record<'b>)
                         SCLogDebug!("SMBv2: Create response => {:?}", cr);
 
                         let guid_key = SMBCommonHdr::from2(r, SMBHDR_TYPE_FILENAME);
-                        match state.ssn2vec_map.remove(&guid_key) {
-                            Some(mut p) => {
-                                p.retain(|&i|i != 0x00);
-                                state.guid2name_map.insert(cr.guid.to_vec(), p);
-                            },
-                            _ => {
-                                SCLogDebug!("SMBv2 response: GUID NOT FOUND");
-                            },
+                        if let Some(mut p) = state.ssn2vec_map.remove(&guid_key) {
+                            p.retain(|&i|i != 0x00);
+                            state.guid2name_map.insert(cr.guid.to_vec(), p);
+                        } else {
+                            SCLogDebug!("SMBv2 response: GUID NOT FOUND");
+                        }
+
+                        let tx_hdr = SMBCommonHdr::from2(r, SMBHDR_TYPE_GENERICTX);
+                        if let Some(tx) = state.get_generic_tx(2, r.command, &tx_hdr) {
+                            SCLogDebug!("tx {} with {}/{} marked as done",
+                                    tx.id, r.command, &smb2_command_string(r.command));
+                            tx.set_status(r.nt_status, false);
+                            tx.response_done = true;
+
+                            if let Some(SMBTransactionTypeData::CREATE(ref mut tdn)) = tx.type_data {
+                                tdn.create_ts = cr.create_ts.as_unix();
+                                tdn.last_access_ts = cr.last_access_ts.as_unix();
+                                tdn.last_write_ts = cr.last_write_ts.as_unix();
+                                tdn.last_change_ts = cr.last_change_ts.as_unix();
+                                tdn.size = cr.size;
+                            }
                         }
                     }
                     _ => {
                         events.push(SMBEvent::MalformedData);
                     },
                 }
+                true
+            } else {
+                false
             }
-            false
         },
         SMB2_COMMAND_TREE_DISCONNECT => {
             // normally removed when processing request,
index c750e3939b31c9aaeb75e1ce5be819f2c6ffb1fa..2283b2a907c249b202b7d7f9bd0e49df3815ece0 100644 (file)
@@ -16,6 +16,7 @@
  */
 
 use nom::{rest, le_u8, le_u16, le_u32, le_u64, AsBytes};
+use smb::smb::*;
 
 #[derive(Debug,PartialEq)]
 pub struct Smb2SecBlobRecord<'a> {
@@ -339,15 +340,36 @@ named!(pub parse_smb2_response_read<Smb2ReadResponseRecord>,
 #[derive(Debug,PartialEq)]
 pub struct Smb2CreateResponseRecord<'a> {
     pub guid: &'a[u8],
+    pub create_ts: SMBFiletime,
+    pub last_access_ts: SMBFiletime,
+    pub last_write_ts: SMBFiletime,
+    pub last_change_ts: SMBFiletime,
+    pub size: u64,
 }
 
 named!(pub parse_smb2_response_create<Smb2CreateResponseRecord>,
     do_parse!(
-            skip1: take!(64)
+            ssize: le_u16
+        >>  oplock: le_u8
+        >>  resp_flags: le_u8
+        >>  create_action: le_u32
+        >>  create_ts: le_u64
+        >>  last_access_ts: le_u64
+        >>  last_write_ts: le_u64
+        >>  last_change_ts: le_u64
+        >>  alloc_size: le_u64
+        >>  eof: le_u64
+        >>  attrs: le_u32
+        >>  padding: take!(4)
         >>  guid: take!(16)
         >>  skip2: take!(8)
         >>  (Smb2CreateResponseRecord {
                 guid : guid,
+                create_ts: SMBFiletime::new(create_ts),
+                last_access_ts: SMBFiletime::new(last_access_ts),
+                last_write_ts: SMBFiletime::new(last_write_ts),
+                last_change_ts: SMBFiletime::new(last_change_ts),
+                size: eof,
             })
 ));