]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
smb: recognizes file deletion over SMB2
authorPhilippe Antoine <contact@catenacyber.fr>
Tue, 13 Jul 2021 06:40:42 +0000 (08:40 +0200)
committerVictor Julien <victor@inliniac.net>
Wed, 1 Sep 2021 06:33:52 +0000 (08:33 +0200)
using set_info_level == SMB2_FILE_DISPOSITION_INFO

rust/src/smb/smb2.rs
rust/src/smb/smb2_records.rs

index f510dead4b52a4cfa1c22050d93d18ab1185d572..5f67ae15ac230a1fbb1deb3c8ea8d0e1444f519f 100644 (file)
@@ -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"<unknown>".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"<unknown>".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"<unknown>".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)) => {
index fa6d62eb8975c5e47208fe6dc1e5daab23914501..bb332dff657bf9c08f21eaa2e8e86180720e3579 100644 (file)
@@ -328,24 +328,62 @@ pub struct Smb2SetInfoRequestRenameRecord<'a> {
     pub name: &'a[u8],
 }
 
-named!(pub parse_smb2_request_setinfo_rename<Smb2SetInfoRequestRenameRecord>,
+named!(pub parse_smb2_request_setinfo_rename<Smb2SetInfoRequestData>,
     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<Smb2SetInfoRequestRenameRecord<'a>>,
+    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<Smb2SetInfoRequestRecord>,
@@ -358,12 +396,12 @@ named!(pub parse_smb2_request_setinfo<Smb2SetInfoRequestRecord>,
         >>  _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,
             })
 ));