From fde753d9d2d8ee150675da9c35071236d8ba1639 Mon Sep 17 00:00:00 2001 From: Philippe Antoine Date: Tue, 13 Jul 2021 08:40:42 +0200 Subject: [PATCH] smb: recognizes file deletion over SMB2 using set_info_level == SMB2_FILE_DISPOSITION_INFO --- rust/src/smb/smb2.rs | 43 ++++++++++++++++++++----------- rust/src/smb/smb2_records.rs | 50 +++++++++++++++++++++++++++++++----- 2 files changed, 72 insertions(+), 21 deletions(-) diff --git a/rust/src/smb/smb2.rs b/rust/src/smb/smb2.rs index f510dead4b..5f67ae15ac 100644 --- a/rust/src/smb/smb2.rs +++ b/rust/src/smb/smb2.rs @@ -358,21 +358,34 @@ pub fn smb2_request_record<'b>(state: &mut SMBState, r: &Smb2Record<'b>) Ok((_, rd)) => { SCLogDebug!("SMB2_COMMAND_SET_INFO: {:?}", rd); - if let Some(ref ren) = rd.rename { - let tx_hdr = SMBCommonHdr::from2(r, SMBHDR_TYPE_GENERICTX); - let mut newname = ren.name.to_vec(); - newname.retain(|&i|i != 0x00); - let oldname = match state.guid2name_map.get(rd.guid) { - Some(n) => { n.to_vec() }, - None => { b"".to_vec() }, - }; - let tx = state.new_rename_tx(rd.guid.to_vec(), oldname, newname); - tx.hdr = tx_hdr; - tx.request_done = true; - tx.vercmd.set_smb2_cmd(SMB2_COMMAND_SET_INFO); - true - } else { - false + match rd.data { + Smb2SetInfoRequestData::RENAME(ref ren) => { + let tx_hdr = SMBCommonHdr::from2(r, SMBHDR_TYPE_GENERICTX); + let mut newname = ren.name.to_vec(); + newname.retain(|&i|i != 0x00); + let oldname = match state.guid2name_map.get(rd.guid) { + Some(n) => { n.to_vec() }, + None => { b"".to_vec() }, + }; + let tx = state.new_rename_tx(rd.guid.to_vec(), oldname, newname); + tx.hdr = tx_hdr; + tx.request_done = true; + tx.vercmd.set_smb2_cmd(SMB2_COMMAND_SET_INFO); + true + } + Smb2SetInfoRequestData::DISPOSITION(ref dis) => { + let tx_hdr = SMBCommonHdr::from2(r, SMBHDR_TYPE_GENERICTX); + let fname = match state.guid2name_map.get(rd.guid) { + Some(n) => { n.to_vec() }, + None => { b"".to_vec() }, + }; + let tx = state.new_setfileinfo_tx(fname, rd.guid.to_vec(), rd.class as u16, rd.infolvl as u16, dis.delete); + tx.hdr = tx_hdr; + tx.request_done = true; + tx.vercmd.set_smb2_cmd(SMB2_COMMAND_SET_INFO); + true + } + _ => false, } }, Err(nom::Err::Incomplete(_n)) => { diff --git a/rust/src/smb/smb2_records.rs b/rust/src/smb/smb2_records.rs index fa6d62eb89..bb332dff65 100644 --- a/rust/src/smb/smb2_records.rs +++ b/rust/src/smb/smb2_records.rs @@ -328,24 +328,62 @@ pub struct Smb2SetInfoRequestRenameRecord<'a> { pub name: &'a[u8], } -named!(pub parse_smb2_request_setinfo_rename, +named!(pub parse_smb2_request_setinfo_rename, do_parse!( _replace: le_u8 >> _reserved: take!(7) >> _root_handle: take!(8) >> name_len: le_u32 >> name: take!(name_len) - >> (Smb2SetInfoRequestRenameRecord { + >> (Smb2SetInfoRequestData::RENAME(Smb2SetInfoRequestRenameRecord { name - }) + })) +)); + +#[derive(Debug)] +pub struct Smb2SetInfoRequestDispoRecord { + pub delete: bool, +} + +named!(pub parse_smb2_request_setinfo_disposition<&[u8], Smb2SetInfoRequestData>, + do_parse!( + info: le_u8 >> + (Smb2SetInfoRequestData::DISPOSITION(Smb2SetInfoRequestDispoRecord { + delete: info & 1 != 0, + })) )); +#[derive(Debug)] +pub enum Smb2SetInfoRequestData<'a> { + DISPOSITION(Smb2SetInfoRequestDispoRecord), + RENAME(Smb2SetInfoRequestRenameRecord<'a>), + UNHANDLED, +} + #[derive(Debug)] pub struct Smb2SetInfoRequestRecord<'a> { pub guid: &'a[u8], pub class: u8, pub infolvl: u8, - pub rename: Option>, + pub data: Smb2SetInfoRequestData<'a>, +} + +fn parse_smb2_request_setinfo_data( + i: &[u8], class: u8, infolvl: u8, +) -> IResult<&[u8], Smb2SetInfoRequestData> { + if class == 1 { + // constants from [MS-FSCC] section 2.4 + match infolvl { + 10 => { + return parse_smb2_request_setinfo_rename(i); + } + 0xd => { + return parse_smb2_request_setinfo_disposition(i); + } + _ => {} + } + } + return Ok((i, Smb2SetInfoRequestData::UNHANDLED)); } named!(pub parse_smb2_request_setinfo, @@ -358,12 +396,12 @@ named!(pub parse_smb2_request_setinfo, >> _reserved: take!(2) >> _additional_info: le_u32 >> guid: take!(16) - >> rename: cond!(class == 1 && infolvl == 10, flat_map!(take!(setinfo_size),parse_smb2_request_setinfo_rename)) + >> data: flat_map!(take!(setinfo_size), call!(parse_smb2_request_setinfo_data, class, infolvl)) >> (Smb2SetInfoRequestRecord { guid: guid, class: class, infolvl: infolvl, - rename: rename, + data: data, }) )); -- 2.47.2