]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
smb1: extract rename info from TRANS2 3289/head
authorVictor Julien <victor@inliniac.net>
Thu, 15 Mar 2018 15:50:38 +0000 (16:50 +0100)
committerVictor Julien <victor@inliniac.net>
Thu, 15 Mar 2018 16:20:30 +0000 (17:20 +0100)
Exclude TRANS2 from generic TX lookup bypass.

rust/src/smb/smb1.rs
rust/src/smb/smb1_records.rs

index f39c2e6baddfd79720b5a3ec44100df88a572822..c33a91ee18bdb2cb05ce011555cfe3be81d9eafc 100644 (file)
@@ -133,6 +133,18 @@ pub fn smb1_create_new_tx(cmd: u8) -> bool {
     }
 }
 
+// see if we're going to do a lookup for a TX.
+// related to smb1_create_new_tx(), however it
+// excludes the 'maybe' commands like TRANS2
+pub fn smb1_check_tx(cmd: u8) -> bool {
+    match cmd {
+        SMB1_COMMAND_READ_ANDX |
+        SMB1_COMMAND_WRITE_ANDX |
+        SMB1_COMMAND_TRANS => { false },
+        _ => { true },
+    }
+}
+
 fn smb1_close_file(state: &mut SMBState, fid: &Vec<u8>)
 {
     // we can have created 2 txs for a FID: one for reads
@@ -199,7 +211,79 @@ pub fn smb1_request_record<'b>(state: &mut SMBState, r: &SmbRecord<'b>) -> u32 {
                 },
             }
         },
-
+        SMB1_COMMAND_TRANS2 => {
+            match parse_smb_trans2_request_record(r.data) {
+                IResult::Done(_, rd) => {
+                    SCLogDebug!("TRANS2 DONE {:?}", rd);
+
+                    if rd.subcmd == 8 {
+                        match parse_trans2_request_params_set_file_info(rd.setup_blob) {
+                            IResult::Done(_, pd) => {
+                                SCLogDebug!("TRANS2 SET_FILE_INFO PARAMS DONE {:?}", pd);
+
+                                if pd.loi == 1010 {
+                                    match parse_trans2_request_data_set_file_info_rename(rd.data_blob) {
+                                        IResult::Done(_, ren) => {
+                                            SCLogDebug!("TRANS2 SET_FILE_INFO DATA RENAME DONE {:?}", ren);
+                                            let tx_hdr = SMBCommonHdr::from1(r, SMBHDR_TYPE_GENERICTX);
+                                            let mut newname = ren.newname.to_vec();
+                                            newname.retain(|&i|i != 0x00);
+
+                                            let mut frankenfid = pd.fid.to_vec();
+                                            frankenfid.extend_from_slice(&u32_as_bytes(r.ssn_id));
+
+                                            let oldname = match state.guid2name_map.get(&frankenfid) {
+                                                Some(n) => n.to_vec(),
+                                                None => b"<unknown>".to_vec(),
+                                            };
+                                            let tx = state.new_rename_tx(pd.fid.to_vec(), oldname, newname);
+                                            tx.hdr = tx_hdr;
+                                            tx.request_done = true;
+                                            tx.vercmd.set_smb1_cmd(SMB1_COMMAND_TRANS2);
+                                            true
+                                        },
+                                        IResult::Incomplete(n) => {
+                                            SCLogDebug!("TRANS2 SET_FILE_INFO DATA RENAME INCOMPLETE {:?}", n);
+                                            events.push(SMBEvent::MalformedData);
+                                            false
+                                        },
+                                        IResult::Error(e) => {
+                                            SCLogDebug!("TRANS2 SET_FILE_INFO DATA RENAME ERROR {:?}", e);
+                                            events.push(SMBEvent::MalformedData);
+                                            false
+                                        },
+                                    }
+                                } else {
+                                    false
+                                }
+                            },
+                            IResult::Incomplete(n) => {
+                                SCLogDebug!("TRANS2 SET_FILE_INFO PARAMS INCOMPLETE {:?}", n);
+                                events.push(SMBEvent::MalformedData);
+                                false
+                            },
+                            IResult::Error(e) => {
+                                SCLogDebug!("TRANS2 SET_FILE_INFO PARAMS ERROR {:?}", e);
+                                events.push(SMBEvent::MalformedData);
+                                false
+                            },
+                        }
+                    } else {
+                        false
+                    }
+                },
+                IResult::Incomplete(n) => {
+                    SCLogDebug!("TRANS2 INCOMPLETE {:?}", n);
+                    events.push(SMBEvent::MalformedData);
+                    false
+                },
+                IResult::Error(e) => {
+                    SCLogDebug!("TRANS2 ERROR {:?}", e);
+                    events.push(SMBEvent::MalformedData);
+                    false
+                },
+            }
+        },
         SMB1_COMMAND_READ_ANDX => {
             match parse_smb_read_andx_request_record(r.data) {
                 IResult::Done(_, rr) => {
@@ -355,8 +439,7 @@ pub fn smb1_request_record<'b>(state: &mut SMBState, r: &SmbRecord<'b>) -> u32 {
             false
         },
         _ => {
-            if r.command == SMB1_COMMAND_TRANS2 ||
-               r.command == SMB1_COMMAND_LOGOFF_ANDX ||
+            if r.command == SMB1_COMMAND_LOGOFF_ANDX ||
                r.command == SMB1_COMMAND_TREE_DISCONNECT ||
                r.command == SMB1_COMMAND_NT_TRANS ||
                r.command == SMB1_COMMAND_NT_CANCEL ||
@@ -577,7 +660,7 @@ pub fn smb1_response_record<'b>(state: &mut SMBState, r: &SmbRecord<'b>) -> u32
             },
             _ => {},
         }
-    } else if !have_tx && smb1_create_new_tx(r.command) {
+    } else if !have_tx && smb1_check_tx(r.command) {
         let tx_key = SMBCommonHdr::new(SMBHDR_TYPE_GENERICTX,
                 key_ssn_id as u64, key_tree_id as u32, key_multiplex_id as u64);
         let _have_tx2 = match state.get_generic_tx(1, r.command as u16, &tx_key) {
index ed37ff481cd9e26affb8d45171f9e4081fb363c0..baceac64e76f8cb0472158703aad06913c02cf36 100644 (file)
@@ -564,6 +564,79 @@ named!(pub parse_smb_create_andx_request_record<SmbRequestCreateAndXRecord>,
            }))
 );
 
+#[derive(Debug,PartialEq)]
+pub struct Trans2RecordParamSetFileInfo<'a> {
+    pub fid: &'a[u8],
+    pub loi: u16,
+}
+
+named!(pub parse_trans2_request_params_set_file_info<Trans2RecordParamSetFileInfo>,
+    do_parse!(
+            fid: take!(2)
+        >>  loi: le_u16
+        >> (Trans2RecordParamSetFileInfo {
+                fid:fid,
+                loi:loi,
+            })
+));
+
+#[derive(Debug,PartialEq)]
+pub struct Trans2RecordParamSetFileInfoRename<'a> {
+    pub replace: bool,
+    pub newname: &'a[u8],
+}
+
+named!(pub parse_trans2_request_data_set_file_info_rename<Trans2RecordParamSetFileInfoRename>,
+    do_parse!(
+            replace: le_u8
+        >>  _reserved: take!(3)
+        >>  root_dir: take!(4)
+        >>  newname_len: le_u32
+        >>  newname: take!(newname_len)
+        >> (Trans2RecordParamSetFileInfoRename {
+                replace: replace==1,
+                newname: newname,
+            })
+));
+
+#[derive(Debug,PartialEq)]
+pub struct SmbRequestTrans2Record<'a> {
+    pub subcmd: u16,
+    pub setup_blob: &'a[u8],
+    pub data_blob: &'a[u8],
+}
+
+named!(pub parse_smb_trans2_request_record<SmbRequestTrans2Record>,
+    do_parse!(
+            wct: le_u8
+        >>  total_param_cnt: le_u16
+        >>  total_data_cnt: le_u16
+        >>  max_param_cnt: le_u16
+        >>  max_data_cnt: le_u16
+        >>  max_setup_cnt: le_u8
+        >>  _reserved1: take!(1)
+        >>  flags: le_u16
+        >>  timeout: le_u32
+        >>  _reserved2: take!(2)
+        >>  param_cnt: le_u16
+        >>  param_offset: le_u16
+        >>  data_cnt: le_u16
+        >>  data_offset: le_u16
+        >>  setup_cnt: le_u8
+        >>  _reserved3: take!(1)
+        >>  subcmd: le_u16
+        >>  bcc: le_u16
+        >>  _padding: take!(3)
+        >>  setup_blob: take!(param_cnt)
+        >>  data_blob: take!(data_cnt)
+
+        >> (SmbRequestTrans2Record {
+                subcmd: subcmd,
+                setup_blob: setup_blob,
+                data_blob: data_blob,
+           }))
+);
+
 #[derive(Debug,PartialEq)]
 pub struct SmbResponseCreateAndXRecord<'a> {
     pub fid: &'a[u8],