#[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,
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(),
}
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();
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;
},
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 },
};
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;
}
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 {
use smb::smb2::*;
use smb::dcerpc::*;
use smb::funcs::*;
-use nom;
#[cfg(not(feature = "debug"))]
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}",
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 {
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();
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,
delete_on_close: del,
directory: dir,
filename: filename,
+ guid: Vec::new(),
create_ts: 0,
last_access_ts: 0,
last_write_ts: 0,
{
// 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 {
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 {
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 => { },
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
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 {
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;
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;
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;
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 {
},
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 {
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 {
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();
}
}
}