]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
smb1: disable 'generic tx's for common commands
authorVictor Julien <victor@inliniac.net>
Wed, 7 Mar 2018 17:23:17 +0000 (18:23 +0100)
committerVictor Julien <victor@inliniac.net>
Mon, 12 Mar 2018 14:34:43 +0000 (15:34 +0100)
Don't create a generic TX for each READ, WRITE, TRANS, TRANS2,
except if they cause events to trigger.

rust/src/smb/smb.rs
rust/src/smb/smb1.rs
rust/src/smb/smb1_session.rs

index b32a8acd3b9b1677c832ee91ca287e23c3be0f6b..2dab57447e9a699b2c7772c4caba3283e4ff359c 100644 (file)
@@ -1252,7 +1252,6 @@ impl SMBState {
         };
 
         self.check_gap_resync(max_tx_id);
-        self._debug_tx_stats();
         0
     }
 
@@ -1482,6 +1481,7 @@ impl SMBState {
             }
         };
         self.check_gap_resync(max_tx_id);
+        self._debug_tx_stats();
         0
     }
 
index 5554cb87d0b1f0e4d1a32ce5804557d3ffe5bd5a..64afbefb78021184ce5445033d6bc0e0ba6c2369 100644 (file)
@@ -122,11 +122,13 @@ pub fn smb1_command_string(c: u8) -> String {
 // later we'll use this to determine if we need to
 // track a ssn per type
 pub fn smb1_create_new_tx(_cmd: u8) -> bool {
-//    if _cmd == SMB1_COMMAND_READ_ANDX {
-//        false
-//    } else {
-        true
-//    }
+    match _cmd {
+        SMB1_COMMAND_READ_ANDX |
+        SMB1_COMMAND_WRITE_ANDX |
+        SMB1_COMMAND_TRANS |
+        SMB1_COMMAND_TRANS2 => { false },
+        _ => { true },
+    }
 }
 
 fn smb1_close_file(state: &mut SMBState, fid: &Vec<u8>)
@@ -609,58 +611,51 @@ pub fn smb1_trans_response_record<'b>(state: &mut SMBState, r: &SmbRecord<'b>)
 {
     let mut events : Vec<SMBEvent> = Vec::new();
 
-    if r.nt_status == SMB_NTSTATUS_SUCCESS || r.nt_status == SMB_NTSTATUS_BUFFER_OVERFLOW {
-        match parse_smb_trans_response_record(r.data) {
-            IResult::Done(_, rd) => {
-                SCLogDebug!("TRANS response {:?}", rd);
+    match parse_smb_trans_response_record(r.data) {
+        IResult::Done(_, rd) => {
+            SCLogDebug!("TRANS response {:?}", rd);
 
-                // see if we have a stored fid
-                let fid = match state.ssn2vec_map.remove(
-                        &SMBCommonHdr::from1(r, SMBHDR_TYPE_GUID)) {
-                    Some(f) => f,
-                    None => Vec::new(),
+            // see if we have a stored fid
+            let fid = match state.ssn2vec_map.remove(
+                    &SMBCommonHdr::from1(r, SMBHDR_TYPE_GUID)) {
+                Some(f) => f,
+                None => Vec::new(),
+            };
+            SCLogDebug!("FID {:?}", fid);
+
+            // if we get status 'BUFFER_OVERFLOW' this is only a part of
+            // the data. Store it in the ssn/tree for later use.
+            if r.nt_status == SMB_NTSTATUS_BUFFER_OVERFLOW {
+                state.ssnguid2vec_map.insert(SMBHashKeyHdrGuid::new(
+                            SMBCommonHdr::from1(r, SMBHDR_TYPE_TRANS_FRAG), fid),
+                        rd.data.to_vec());
+            } else {
+                let txn_hdr = SMBCommonHdr::from1(r, SMBHDR_TYPE_TXNAME);
+                let is_dcerpc = match state.ssn2vec_map.remove(&txn_hdr) {
+                    None => false,
+                    Some(s) => {
+                        let (sername, is_dcerpc) = get_service_for_nameslice(&s);
+                        SCLogDebug!("service: {} dcerpc {}", sername, is_dcerpc);
+                        is_dcerpc
+                    },
                 };
-                SCLogDebug!("FID {:?}", fid);
-
-                // if we get status 'BUFFER_OVERFLOW' this is only a part of
-                // the data. Store it in the ssn/tree for later use.
-                if r.nt_status == SMB_NTSTATUS_BUFFER_OVERFLOW {
-                    state.ssnguid2vec_map.insert(SMBHashKeyHdrGuid::new(
-                                SMBCommonHdr::from1(r, SMBHDR_TYPE_TRANS_FRAG), fid),
-                            rd.data.to_vec());
-                } else {
-                    let txn_hdr = SMBCommonHdr::from1(r, SMBHDR_TYPE_TXNAME);
-                    let is_dcerpc = match state.ssn2vec_map.remove(&txn_hdr) {
-                        None => false,
-                        Some(s) => {
-                            let (sername, is_dcerpc) = get_service_for_nameslice(&s);
-                            SCLogDebug!("service: {} dcerpc {}", sername, is_dcerpc);
-                            is_dcerpc
-                        },
-                    };
-                    if is_dcerpc {
-                        SCLogDebug!("SMBv1 TRANS TO PIPE");
-                        let hdr = SMBCommonHdr::from1(r, SMBHDR_TYPE_HEADER);
-                        let vercmd = SMBVerCmdStat::new1_with_ntstatus(r.command, r.nt_status);
-                        smb_read_dcerpc_record(state, vercmd, hdr, &fid, &rd.data);
-                    }
+                if is_dcerpc {
+                    SCLogDebug!("SMBv1 TRANS TO PIPE");
+                    let hdr = SMBCommonHdr::from1(r, SMBHDR_TYPE_HEADER);
+                    let vercmd = SMBVerCmdStat::new1_with_ntstatus(r.command, r.nt_status);
+                    smb_read_dcerpc_record(state, vercmd, hdr, &fid, &rd.data);
                 }
-            },
+            }
+        },
             _ => {
-               events.push(SMBEvent::MalformedData);
+                events.push(SMBEvent::MalformedData);
             },
-        }
     }
+
     // generic tx as well. Set events if needed.
     smb1_response_record_generic(state, r, events);
 }
 
-fn smb1_request_record_generic<'b>(state: &mut SMBState, r: &SmbRecord<'b>, events: Vec<SMBEvent>) {
-    let tx_key = SMBCommonHdr::from1(r, SMBHDR_TYPE_GENERICTX);
-    let tx = state.new_generic_tx(1, r.command as u16, tx_key);
-    tx.set_events(events);
-}
-
 /// Handle WRITE, WRITE_ANDX, WRITE_AND_CLOSE request records
 pub fn smb1_write_request_record<'b>(state: &mut SMBState, r: &SmbRecord<'b>)
 {
@@ -739,21 +734,6 @@ pub fn smb1_write_request_record<'b>(state: &mut SMBState, r: &SmbRecord<'b>)
     smb1_request_record_generic(state, r, events);
 }
 
-fn smb1_response_record_generic<'b>(state: &mut SMBState, r: &SmbRecord<'b>, events: Vec<SMBEvent>) {
-    // see if we want a tx per READ command
-    if smb1_create_new_tx(r.command) {
-        let tx_key = SMBCommonHdr::from1(r, SMBHDR_TYPE_GENERICTX);
-        let tx = state.get_generic_tx(1, r.command as u16, &tx_key);
-        if let Some(tx) = tx {
-            tx.request_done = true;
-            tx.response_done = true;
-            SCLogDebug!("tx {} cmd {} is done", tx.id, r.command);
-            tx.set_status(r.nt_status, r.is_dos_error);
-            tx.set_events(events);
-        }
-    }
-}
-
 pub fn smb1_read_response_record<'b>(state: &mut SMBState, r: &SmbRecord<'b>)
 {
     let mut events : Vec<SMBEvent> = Vec::new();
@@ -834,3 +814,42 @@ pub fn smb1_read_response_record<'b>(state: &mut SMBState, r: &SmbRecord<'b>)
     // generic tx as well. Set events if needed.
     smb1_response_record_generic(state, r, events);
 }
+
+/// create a tx for a command / response pair if we're
+/// configured to do so, or if this is a tx especially
+/// for setting an event.
+fn smb1_request_record_generic<'b>(state: &mut SMBState, r: &SmbRecord<'b>, events: Vec<SMBEvent>) {
+    if smb1_create_new_tx(r.command) || events.len() > 0 {
+        let tx_key = SMBCommonHdr::from1(r, SMBHDR_TYPE_GENERICTX);
+        let tx = state.new_generic_tx(1, r.command as u16, tx_key);
+        tx.set_events(events);
+    }
+}
+
+/// update or create a tx for a command / reponse pair based
+/// on the response. We only create a tx for the response side
+/// if we didn't already update a tx, and we have to set events
+fn smb1_response_record_generic<'b>(state: &mut SMBState, r: &SmbRecord<'b>, events: Vec<SMBEvent>) {
+    // see if we want a tx per command
+    if smb1_create_new_tx(r.command) {
+        let tx_key = SMBCommonHdr::from1(r, SMBHDR_TYPE_GENERICTX);
+        let tx = state.get_generic_tx(1, r.command as u16, &tx_key);
+        if let Some(tx) = tx {
+            tx.request_done = true;
+            tx.response_done = true;
+            SCLogDebug!("tx {} cmd {} is done", tx.id, r.command);
+            tx.set_status(r.nt_status, r.is_dos_error);
+            tx.set_events(events);
+            return;
+        }
+    }
+    if events.len() > 0 {
+        let tx_key = SMBCommonHdr::from1(r, SMBHDR_TYPE_GENERICTX);
+        let tx = state.new_generic_tx(1, r.command as u16, tx_key);
+        tx.request_done = true;
+        tx.response_done = true;
+        SCLogDebug!("tx {} cmd {} is done", tx.id, r.command);
+        tx.set_status(r.nt_status, r.is_dos_error);
+        tx.set_events(events);
+    }
+}
index 6965dd8d3d25777fa1b1eb349cf3f31771fc103c..4fd971cc2592596aaeff9d28c9b2a55bffa4b6a3 100644 (file)
@@ -223,7 +223,7 @@ pub fn smb1_session_setup_response(state: &mut SMBState, r: &SmbRecord)
                 SCLogDebug!("smb1_session_setup_response: tx {:?}", tx);
             },
             None => {
-                SCLogNotice!("smb1_session_setup_response: tx not found for {:?}", r);
+                SCLogDebug!("smb1_session_setup_response: tx not found for {:?}", r);
             },
         }
     }