diff --git a/rust/src/smb/events.rs b/rust/src/smb/events.rs index f8b3055ede..b2a49ca1aa 100644 --- a/rust/src/smb/events.rs +++ b/rust/src/smb/events.rs @@ -27,6 +27,10 @@ pub enum SMBEvent { DuplicateNegotiate, NegotiateMalformedDialects, FileOverlap, + /// A request was seen in the to client direction. + RequestToClient, + /// A response was seen in the to server direction, + ResponseToServer, } impl SMBTransaction { diff --git a/rust/src/smb/smb.rs b/rust/src/smb/smb.rs index eaf886395c..d50bbd9050 100644 --- a/rust/src/smb/smb.rs +++ b/rust/src/smb/smb.rs @@ -1453,9 +1453,18 @@ impl SMBState { SCLogDebug!("SMBv1 record"); match parse_smb_record(nbss_hdr.data) { Ok((_, ref smb_record)) => { - self.add_smb1_ts_pdu_frame(flow, stream_slice, nbss_hdr.data, nbss_hdr.length as i64); + let pdu_frame = self.add_smb1_ts_pdu_frame(flow, stream_slice, nbss_hdr.data, nbss_hdr.length as i64); self.add_smb1_ts_hdr_data_frames(flow, stream_slice, nbss_hdr.data, nbss_hdr.length as i64); - smb1_request_record(self, smb_record); + if smb_record.is_request() { + smb1_request_record(self, smb_record); + } else { + // If we recevied a response when expecting a request, set an event + // on the PDU frame instead of handling the response. + SCLogDebug!("SMB1 reply seen from client to server"); + if let Some(frame) = pdu_frame { + frame.add_event(flow, 0, SMBEvent::ResponseToServer as u8); + } + } }, _ => { if let Some(frame) = nbss_data_frame { @@ -1472,10 +1481,19 @@ impl SMBState { match parse_smb2_request_record(nbss_data) { Ok((nbss_data_rem, ref smb_record)) => { let record_len = (nbss_data.len() - nbss_data_rem.len()) as i64; - self.add_smb2_ts_pdu_frame(flow, stream_slice, nbss_data, record_len); + let pdu_frame = self.add_smb2_ts_pdu_frame(flow, stream_slice, nbss_data, record_len); self.add_smb2_ts_hdr_data_frames(flow, stream_slice, nbss_data, record_len, smb_record.header_len as i64); SCLogDebug!("nbss_data_rem {}", nbss_data_rem.len()); - smb2_request_record(self, smb_record); + if smb_record.is_request() { + smb2_request_record(self, smb_record); + } else { + // If we recevied a response when expecting a request, set an event + // on the PDU frame instead of handling the response. + SCLogDebug!("SMB2 reply seen from client to server"); + if let Some(frame) = pdu_frame { + frame.add_event(flow, 0, SMBEvent::ResponseToServer as u8); + } + } nbss_data = nbss_data_rem; }, _ => { @@ -1571,9 +1589,10 @@ impl SMBState { (nbss_pdu, nbss_hdr_frame, nbss_data_frame) } - fn add_smb1_tc_pdu_frame(&mut self, flow: *const Flow, stream_slice: &StreamSlice, input: &[u8], nbss_len: i64) { - let _smb_pdu = Frame::new_tc(flow, stream_slice, input, nbss_len, SMBFrameType::SMB1Pdu as u8); - SCLogDebug!("SMB PDU frame {:?}", _smb_pdu); + fn add_smb1_tc_pdu_frame(&mut self, flow: *const Flow, stream_slice: &StreamSlice, input: &[u8], nbss_len: i64) -> Option { + let smb_pdu = Frame::new_tc(flow, stream_slice, input, nbss_len, SMBFrameType::SMB1Pdu as u8); + SCLogDebug!("SMB PDU frame {:?}", smb_pdu); + smb_pdu } fn add_smb1_tc_hdr_data_frames(&mut self, flow: *const Flow, stream_slice: &StreamSlice, input: &[u8], nbss_len: i64) { let _smb1_hdr = Frame::new_tc(flow, stream_slice, input, SMB1_HEADER_SIZE as i64, SMBFrameType::SMB1Hdr as u8); @@ -1585,9 +1604,10 @@ impl SMBState { } } - fn add_smb2_tc_pdu_frame(&mut self, flow: *const Flow, stream_slice: &StreamSlice, input: &[u8], nbss_len: i64) { - let _smb_pdu = Frame::new_tc(flow, stream_slice, input, nbss_len, SMBFrameType::SMB2Pdu as u8); - SCLogDebug!("SMBv2 PDU frame {:?}", _smb_pdu); + fn add_smb2_tc_pdu_frame(&mut self, flow: *const Flow, stream_slice: &StreamSlice, input: &[u8], nbss_len: i64) -> Option { + let smb_pdu = Frame::new_tc(flow, stream_slice, input, nbss_len, SMBFrameType::SMB2Pdu as u8); + SCLogDebug!("SMBv2 PDU frame {:?}", smb_pdu); + smb_pdu } fn add_smb2_tc_hdr_data_frames(&mut self, flow: *const Flow, stream_slice: &StreamSlice, input: &[u8], nbss_len: i64, hdr_len: i64) { let _smb2_hdr = Frame::new_tc(flow, stream_slice, input, hdr_len, SMBFrameType::SMB2Hdr as u8); @@ -1764,9 +1784,16 @@ impl SMBState { SCLogDebug!("SMBv1 record"); match parse_smb_record(nbss_hdr.data) { Ok((_, ref smb_record)) => { - self.add_smb1_tc_pdu_frame(flow, stream_slice, nbss_hdr.data, nbss_hdr.length as i64); + let pdu_frame = self.add_smb1_tc_pdu_frame(flow, stream_slice, nbss_hdr.data, nbss_hdr.length as i64); self.add_smb1_tc_hdr_data_frames(flow, stream_slice, nbss_hdr.data, nbss_hdr.length as i64); - smb1_response_record(self, smb_record); + if smb_record.is_response() { + smb1_response_record(self, smb_record); + } else { + SCLogDebug!("SMB1 request seen from server to client"); + if let Some(frame) = pdu_frame { + frame.add_event(flow, 1, SMBEvent::RequestToClient as u8); + } + } }, _ => { self.set_event(SMBEvent::MalformedData); @@ -1780,9 +1807,16 @@ impl SMBState { match parse_smb2_response_record(nbss_data) { Ok((nbss_data_rem, ref smb_record)) => { let record_len = (nbss_data.len() - nbss_data_rem.len()) as i64; - self.add_smb2_tc_pdu_frame(flow, stream_slice, nbss_data, record_len); + let pdu_frame = self.add_smb2_tc_pdu_frame(flow, stream_slice, nbss_data, record_len); self.add_smb2_tc_hdr_data_frames(flow, stream_slice, nbss_data, record_len, smb_record.header_len as i64); - smb2_response_record(self, smb_record); + if smb_record.is_response() { + smb2_response_record(self, smb_record); + } else { + SCLogDebug!("SMB2 request seen from server to client"); + if let Some(frame) = pdu_frame { + frame.add_event(flow, 1, SMBEvent::RequestToClient as u8); + } + } nbss_data = nbss_data_rem; }, _ => { diff --git a/rust/src/smb/smb2_records.rs b/rust/src/smb/smb2_records.rs index 2d8950bcfc..d069ef0486 100644 --- a/rust/src/smb/smb2_records.rs +++ b/rust/src/smb/smb2_records.rs @@ -69,6 +69,14 @@ impl<'a> Smb2Record<'a> { pub fn is_async(&self) -> bool { self.async_id != 0 } + + pub fn is_request(&self) -> bool { + self.direction == 0 + } + + pub fn is_response(&self) -> bool { + self.direction == 1 + } } #[derive(Debug)]