} 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 {
}
}
+/// "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),
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 {
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,
}
}
}
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,
*/
use nom::{rest, le_u8, le_u16, le_u32, le_u64, AsBytes};
+use smb::smb::*;
#[derive(Debug,PartialEq)]
pub struct Smb2SecBlobRecord<'a> {
#[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,
})
));