]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
smb: generic event per trans/read/write for tx events
authorVictor Julien <victor@inliniac.net>
Wed, 7 Mar 2018 14:29:49 +0000 (15:29 +0100)
committerVictor Julien <victor@inliniac.net>
Mon, 12 Mar 2018 14:34:43 +0000 (15:34 +0100)
rust/src/smb/smb1.rs

index 33c41a9f68b2e4c7d66bdb9b00aeb93927ad73ba..5554cb87d0b1f0e4d1a32ce5804557d3ffe5bd5a 100644 (file)
@@ -561,6 +561,8 @@ pub fn get_service_for_nameslice(nameslice: &[u8]) -> (&'static str, bool)
 
 pub fn smb1_trans_request_record<'b>(state: &mut SMBState, r: &SmbRecord<'b>)
 {
+    let mut events : Vec<SMBEvent> = Vec::new();
+
     match parse_smb_trans_request_record(r.data, r) {
         IResult::Done(_, rd) => {
             SCLogDebug!("TRANS request {:?}", rd);
@@ -597,64 +599,73 @@ pub fn smb1_trans_request_record<'b>(state: &mut SMBState, r: &SmbRecord<'b>)
             }
         },
         _ => {
-            state.set_event(SMBEvent::MalformedData);
+            events.push(SMBEvent::MalformedData);
         },
     }
+    smb1_request_record_generic(state, r, events);
 }
 
 pub fn smb1_trans_response_record<'b>(state: &mut SMBState, r: &SmbRecord<'b>)
 {
-    match parse_smb_trans_response_record(r.data) {
-        IResult::Done(_, rd) => {
-            SCLogDebug!("TRANS response {:?}", rd);
+    let mut events : Vec<SMBEvent> = 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 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);
 
-            // 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
-                    },
+                // 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(),
                 };
-                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);
+                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);
+                    }
                 }
-            }
-        },
-        _ => {
-            state.set_event(SMBEvent::MalformedData);
-        },
+            },
+            _ => {
+               events.push(SMBEvent::MalformedData);
+            },
+        }
     }
+    // generic tx as well. Set events if needed.
+    smb1_response_record_generic(state, r, events);
 }
 
-fn smb1_write_request_record_generic_error<'b>(state: &mut SMBState, r: &SmbRecord<'b>, event: SMBEvent) {
+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_event(event);
+    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>)
 {
+    let mut events : Vec<SMBEvent> = Vec::new();
+
     let result = if r.command == SMB1_COMMAND_WRITE_ANDX {
         parse_smb1_write_andx_request_record(r.data)
     } else if r.command == SMB1_COMMAND_WRITE {
@@ -722,12 +733,13 @@ pub fn smb1_write_request_record<'b>(state: &mut SMBState, r: &SmbRecord<'b>)
             }
         },
         _ => {
-            smb1_write_request_record_generic_error(state, r, SMBEvent::MalformedData);
+            events.push(SMBEvent::MalformedData);
         },
     }
+    smb1_request_record_generic(state, r, events);
 }
 
-fn smb1_read_response_record_generic<'b>(state: &mut SMBState, r: &SmbRecord<'b>, events: Vec<SMBEvent>) {
+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);
@@ -820,5 +832,5 @@ pub fn smb1_read_response_record<'b>(state: &mut SMBState, r: &SmbRecord<'b>)
     }
 
     // generic tx as well. Set events if needed.
-    smb1_read_response_record_generic(state, r, events);
+    smb1_response_record_generic(state, r, events);
 }