use crate::core::*;
use crate::applayer;
use crate::applayer::*;
+use crate::frames::*;
use crate::conf::*;
use crate::filecontainer::*;
use crate::applayer::{AppLayerResult, AppLayerTxData, AppLayerEvent};
use crate::smb::files::*;
use crate::smb::smb2_ioctl::*;
+#[repr(C)]
+pub enum SMBFrameType {
+ NBSSPdu = 0,
+ NBSSHdr = 1,
+ NBSSData = 2,
+ SMB1Pdu = 3,
+ SMB1Hdr = 4,
+ SMB1Data = 5,
+ SMB2Pdu = 6,
+ SMB2Hdr = 7,
+ SMB2Data = 8,
+ SMB3Pdu = 9,
+ SMB3Hdr = 10,
+ SMB3Data = 11,
+}
+
+impl SMBFrameType {
+ fn from_u8(value: u8) -> Option<SMBFrameType> {
+ match value {
+ 0 => Some(SMBFrameType::NBSSPdu),
+ 1 => Some(SMBFrameType::NBSSHdr),
+ 2 => Some(SMBFrameType::NBSSData),
+ 3 => Some(SMBFrameType::SMB1Pdu),
+ 4 => Some(SMBFrameType::SMB1Hdr),
+ 5 => Some(SMBFrameType::SMB1Data),
+ 6 => Some(SMBFrameType::SMB2Pdu),
+ 7 => Some(SMBFrameType::SMB2Hdr),
+ 8 => Some(SMBFrameType::SMB2Data),
+ 9 => Some(SMBFrameType::SMB3Pdu),
+ 10 => Some(SMBFrameType::SMB3Hdr),
+ 11 => Some(SMBFrameType::SMB3Data),
+ _ => None,
+ }
+ }
+}
+
+fn smb_frame_type_string(s: &str) -> i32 {
+ match s {
+ "nbss.pdu" => SMBFrameType::NBSSPdu as i32,
+ "nbss.hdr" => SMBFrameType::NBSSHdr as i32,
+ "nbss.data" => SMBFrameType::NBSSData as i32,
+ "smb1.pdu" => SMBFrameType::SMB1Pdu as i32,
+ "smb1.hdr" => SMBFrameType::SMB1Hdr as i32,
+ "smb1.data" => SMBFrameType::SMB1Data as i32,
+ "smb2.pdu" => SMBFrameType::SMB2Pdu as i32,
+ "smb2.hdr" => SMBFrameType::SMB2Hdr as i32,
+ "smb2.data" => SMBFrameType::SMB2Data as i32,
+ "smb3.pdu" => SMBFrameType::SMB3Pdu as i32,
+ "smb3.hdr" => SMBFrameType::SMB3Hdr as i32,
+ "smb3.data" => SMBFrameType::SMB3Data as i32,
+ _ => -1,
+ }
+}
+
+fn smb_frame_string_type(id: u8) -> *const std::os::raw::c_char {
+ if let Some(s) = SMBFrameType::from_u8(id) {
+ let estr = match s {
+ SMBFrameType::NBSSPdu => "nbss.pdu\0",
+ SMBFrameType::NBSSHdr => "nbss.hdr\0",
+ SMBFrameType::NBSSData => "nbss.data\0",
+ SMBFrameType::SMB1Pdu => "smb1.pdu\0",
+ SMBFrameType::SMB1Hdr => "smb1.hdr\0",
+ SMBFrameType::SMB1Data => "smb1.data\0",
+ SMBFrameType::SMB2Pdu => "smb2.pdu\0",
+ SMBFrameType::SMB2Hdr => "smb2.hdr\0",
+ SMBFrameType::SMB2Data => "smb2.data\0",
+ SMBFrameType::SMB3Pdu => "smb3.pdu\0",
+ SMBFrameType::SMB3Hdr => "smb3.hdr\0",
+ SMBFrameType::SMB3Data => "smb3.data\0",
+ };
+
+ return estr.as_ptr() as *const std::os::raw::c_char;
+ }
+ return std::ptr::null();
+}
+
pub const MIN_REC_SIZE: u16 = 32 + 4; // SMB hdr + nbss hdr
pub const SMB_CONFIG_DEFAULT_STREAM_DEPTH: u32 = 0;
return consumed;
}
+ fn add_nbss_ts_frames(&mut self, flow: *const Flow, stream_slice: &StreamSlice, input: &[u8], nbss_len: i64) -> (Option<Frame>, Option<Frame>, Option<Frame>) {
+ let nbss_pdu = Frame::new_ts(flow, stream_slice, input, nbss_len + 4, SMBFrameType::NBSSPdu as u8);
+ SCLogDebug!("NBSS PDU frame {:?}", nbss_pdu);
+ let nbss_hdr_frame = Frame::new_ts(flow, stream_slice, input, 4 as i64, SMBFrameType::NBSSHdr as u8);
+ SCLogDebug!("NBSS HDR frame {:?}", nbss_hdr_frame);
+ let nbss_data_frame = Frame::new_ts(flow, stream_slice, &input[4..], nbss_len, SMBFrameType::NBSSData as u8);
+ SCLogDebug!("NBSS DATA frame {:?}", nbss_data_frame);
+ (nbss_pdu, nbss_hdr_frame, nbss_data_frame)
+ }
+
+ fn add_smb1_ts_pdu_frame(&mut self, flow: *const Flow, stream_slice: &StreamSlice, input: &[u8], nbss_len: i64) -> Option<Frame> {
+ let smb_pdu = Frame::new_ts(flow, stream_slice, input, nbss_len, SMBFrameType::SMB1Pdu as u8);
+ SCLogDebug!("SMB PDU frame {:?}", smb_pdu);
+ smb_pdu
+ }
+ fn add_smb1_ts_hdr_data_frames(&mut self, flow: *const Flow, stream_slice: &StreamSlice, input: &[u8], nbss_len: i64) {
+ let _smb1_hdr = Frame::new_ts(flow, stream_slice, input, 32 as i64, SMBFrameType::SMB1Hdr as u8);
+ SCLogDebug!("SMBv1 HDR frame {:?}", _smb1_hdr);
+ if input.len() > 32 {
+ let _smb1_data = Frame::new_ts(flow, stream_slice, &input[32..], (nbss_len - 32) as i64, SMBFrameType::SMB1Data as u8);
+ SCLogDebug!("SMBv1 DATA frame {:?}", _smb1_data);
+ }
+ }
+
+ fn add_smb2_ts_pdu_frame(&mut self, flow: *const Flow, stream_slice: &StreamSlice, input: &[u8], nbss_len: i64) -> Option<Frame> {
+ let smb_pdu = Frame::new_ts(flow, stream_slice, input, nbss_len, SMBFrameType::SMB2Pdu as u8);
+ SCLogDebug!("SMBv2 PDU frame {:?}", smb_pdu);
+ smb_pdu
+ }
+ fn add_smb2_ts_hdr_data_frames(&mut self, flow: *const Flow, stream_slice: &StreamSlice, input: &[u8], nbss_len: i64, hdr_len: i64) {
+ let _smb2_hdr = Frame::new_ts(flow, stream_slice, input, hdr_len, SMBFrameType::SMB2Hdr as u8);
+ SCLogDebug!("SMBv2 HDR frame {:?}", _smb2_hdr);
+ if input.len() > hdr_len as usize {
+ let _smb2_data = Frame::new_ts(flow, stream_slice, &input[hdr_len as usize..], nbss_len - hdr_len, SMBFrameType::SMB2Data as u8);
+ SCLogDebug!("SMBv2 DATA frame {:?}", _smb2_data);
+ }
+ }
+
+ fn add_smb3_ts_pdu_frame(&mut self, flow: *const Flow, stream_slice: &StreamSlice, input: &[u8], nbss_len: i64) -> Option<Frame> {
+ let smb_pdu = Frame::new_ts(flow, stream_slice, input, nbss_len, SMBFrameType::SMB3Pdu as u8);
+ SCLogDebug!("SMBv3 PDU frame {:?}", smb_pdu);
+ smb_pdu
+ }
+ fn add_smb3_ts_hdr_data_frames(&mut self, flow: *const Flow, stream_slice: &StreamSlice, input: &[u8], nbss_len: i64) {
+ let _smb3_hdr = Frame::new_ts(flow, stream_slice, input, 52 as i64, SMBFrameType::SMB3Hdr as u8);
+ SCLogDebug!("SMBv3 HDR frame {:?}", _smb3_hdr);
+ if input.len() > 52 {
+ let _smb3_data = Frame::new_ts(flow, stream_slice, &input[52..], (nbss_len - 52) as i64, SMBFrameType::SMB3Data as u8);
+ SCLogDebug!("SMBv3 DATA frame {:?}", _smb3_data);
+ }
+ }
+
/// return bytes consumed
- pub fn parse_tcp_data_ts_partial<'b>(&mut self, input: &'b[u8]) -> usize
+ pub fn parse_tcp_data_ts_partial<'b>(&mut self, flow: *const Flow, stream_slice: &StreamSlice, input: &'b[u8]) -> usize
{
SCLogDebug!("incomplete of size {}", input.len());
if input.len() < 512 {
return 0;
}
smb1_write_request_record(self, r, SMB1_HEADER_SIZE, SMB1_COMMAND_WRITE_ANDX);
+
+ self.add_nbss_ts_frames(flow, stream_slice, input, nbss_part_hdr.length as i64);
+ self.add_smb1_ts_pdu_frame(flow, stream_slice, nbss_part_hdr.data, nbss_part_hdr.length as i64);
+ self.add_smb1_ts_hdr_data_frames(flow, stream_slice, nbss_part_hdr.data, nbss_part_hdr.length as i64);
+
let consumed = input.len() - output.len();
return consumed;
}
}
} else if smb.version == 0xfe_u8 { // SMB2
- SCLogDebug!("NBSS record {:?}", nbss_part_hdr);
SCLogDebug!("SMBv2 record");
match parse_smb2_request_record(nbss_part_hdr.data) {
Ok((_, ref smb_record)) => {
&smb2_command_string(smb_record.command));
if smb_record.command == SMB2_COMMAND_WRITE {
smb2_write_request_record(self, smb_record);
+
+ self.add_nbss_ts_frames(flow, stream_slice, input, nbss_part_hdr.length as i64);
+ self.add_smb2_ts_pdu_frame(flow, stream_slice, nbss_part_hdr.data, nbss_part_hdr.length as i64);
+ self.add_smb2_ts_hdr_data_frames(flow, stream_slice, nbss_part_hdr.data, nbss_part_hdr.length as i64, smb_record.header_len as i64);
+
let consumed = input.len() - output.len();
SCLogDebug!("consumed {}", consumed);
return consumed;
}
/// Parsing function, handling TCP chunks fragmentation
- pub fn parse_tcp_data_ts<'b>(&mut self, i: &'b[u8]) -> AppLayerResult
+ pub fn parse_tcp_data_ts<'b>(&mut self, flow: *const Flow, stream_slice: &StreamSlice) -> AppLayerResult
{
- let mut cur_i = i;
+ let mut cur_i = stream_slice.as_slice();
let consumed = self.handle_skip(Direction::ToServer, cur_i.len() as u32);
if consumed > 0 {
if consumed > cur_i.len() as u32 {
break;
},
_ => {
- let mut consumed = i.len();
+ let mut consumed = stream_slice.len();
if consumed < 4 {
consumed = 0;
} else {
while cur_i.len() > 0 { // min record size
match parse_nbss_record(cur_i) {
Ok((rem, ref nbss_hdr)) => {
+ SCLogDebug!("nbss frame offset {} len {}", stream_slice.offset_from(cur_i), cur_i.len() - rem.len());
+ let (_, _, nbss_data_frame) = self.add_nbss_ts_frames(flow, stream_slice, cur_i, nbss_hdr.length as i64);
+
if nbss_hdr.message_type == NBSS_MSGTYPE_SESSION_MESSAGE {
// we have the full records size worth of data,
// let's parse it
match parse_smb_version(nbss_hdr.data) {
Ok((_, ref smb)) => {
+
SCLogDebug!("SMB {:?}", smb);
if smb.version == 0xff_u8 { // SMB1
+
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);
+ 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 let Some(frame) = nbss_data_frame {
+ frame.add_event(flow, 0, SMBEvent::MalformedData as u8);
+ }
self.set_event(SMBEvent::MalformedData);
return AppLayerResult::err();
},
SCLogDebug!("SMBv2 record");
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);
+ 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);
nbss_data = nbss_data_rem;
},
_ => {
+ if let Some(frame) = nbss_data_frame {
+ frame.add_event(flow, 0, SMBEvent::MalformedData as u8);
+ }
self.set_event(SMBEvent::MalformedData);
return AppLayerResult::err();
},
}
}
} else if smb.version == 0xfd_u8 { // SMB3 transform
+
let mut nbss_data = nbss_hdr.data;
while nbss_data.len() > 0 {
SCLogDebug!("SMBv3 transform record");
match parse_smb3_transform_record(nbss_data) {
Ok((nbss_data_rem, ref _smb3_record)) => {
+ let record_len = (nbss_data.len() - nbss_data_rem.len()) as i64;
+ self.add_smb3_ts_pdu_frame(flow, stream_slice, nbss_data, record_len);
+ self.add_smb3_ts_hdr_data_frames(flow, stream_slice, nbss_data, record_len);
nbss_data = nbss_data_rem;
},
_ => {
+ if let Some(frame) = nbss_data_frame {
+ frame.add_event(flow, 0, SMBEvent::MalformedData as u8);
+ }
self.set_event(SMBEvent::MalformedData);
return AppLayerResult::err();
},
let n = usize::from(n) + cur_i.len();
// 512 is the minimum for parse_tcp_data_ts_partial
if n >= 512 && cur_i.len() < 512 {
- let total_consumed = i.len() - cur_i.len();
- return AppLayerResult::incomplete(total_consumed as u32, 512);
+ let total_consumed = stream_slice.offset_from(cur_i);
+ return AppLayerResult::incomplete(total_consumed, 512);
}
- let consumed = self.parse_tcp_data_ts_partial(cur_i);
+ let consumed = self.parse_tcp_data_ts_partial(flow, stream_slice, cur_i);
if consumed == 0 {
// if we consumed none we will buffer the entire record
- let total_consumed = i.len() - cur_i.len();
+ let total_consumed = stream_slice.offset_from(cur_i);
SCLogDebug!("setting consumed {} need {} needed {:?} total input {}",
- total_consumed, n, needed, i.len());
+ total_consumed, n, needed, stream_slice.len());
let need = n;
return AppLayerResult::incomplete(total_consumed as u32, need as u32);
}
AppLayerResult::ok()
}
+ fn add_nbss_tc_frames(&mut self, flow: *const Flow, stream_slice: &StreamSlice, input: &[u8], nbss_len: i64) -> (Option<Frame>, Option<Frame>, Option<Frame>) {
+ let nbss_pdu = Frame::new_tc(flow, stream_slice, input, nbss_len + 4, SMBFrameType::NBSSPdu as u8);
+ SCLogDebug!("NBSS PDU frame {:?}", nbss_pdu);
+ let nbss_hdr_frame = Frame::new_tc(flow, stream_slice, input, 4 as i64, SMBFrameType::NBSSHdr as u8);
+ SCLogDebug!("NBSS HDR frame {:?}", nbss_hdr_frame);
+ let nbss_data_frame = Frame::new_tc(flow, stream_slice, &input[4..], nbss_len, SMBFrameType::NBSSData as u8);
+ SCLogDebug!("NBSS DATA frame {:?}", nbss_data_frame);
+ (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_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);
+ SCLogDebug!("SMBv1 HDR frame {:?}", _smb1_hdr);
+ if input.len() > SMB1_HEADER_SIZE {
+ let _smb1_data = Frame::new_tc(flow, stream_slice, &input[SMB1_HEADER_SIZE..], (nbss_len - SMB1_HEADER_SIZE as i64) as i64,
+ SMBFrameType::SMB1Data as u8);
+ SCLogDebug!("SMBv1 DATA frame {:?}", _smb1_data);
+ }
+ }
+
+ 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_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);
+ SCLogDebug!("SMBv2 HDR frame {:?}", _smb2_hdr);
+ if input.len() > hdr_len as usize {
+ let _smb2_data = Frame::new_tc(flow, stream_slice, &input[hdr_len as usize ..], nbss_len - hdr_len, SMBFrameType::SMB2Data as u8);
+ SCLogDebug!("SMBv2 DATA frame {:?}", _smb2_data);
+ }
+ }
+
+ fn add_smb3_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::SMB3Pdu as u8);
+ SCLogDebug!("SMBv3 PDU frame {:?}", _smb_pdu);
+ }
+ fn add_smb3_tc_hdr_data_frames(&mut self, flow: *const Flow, stream_slice: &StreamSlice, input: &[u8], nbss_len: i64) {
+ let _smb3_hdr = Frame::new_tc(flow, stream_slice, input, 52 as i64, SMBFrameType::SMB3Hdr as u8);
+ SCLogDebug!("SMBv3 HDR frame {:?}", _smb3_hdr);
+ if input.len() > 52 {
+ let _smb3_data = Frame::new_tc(flow, stream_slice, &input[52..], (nbss_len - 52) as i64, SMBFrameType::SMB3Data as u8);
+ SCLogDebug!("SMBv3 DATA frame {:?}", _smb3_data);
+ }
+ }
+
/// return bytes consumed
- pub fn parse_tcp_data_tc_partial<'b>(&mut self, input: &'b[u8]) -> usize
+ pub fn parse_tcp_data_tc_partial<'b>(&mut self, flow: *const Flow, stream_slice: &StreamSlice, input: &'b[u8]) -> usize
{
SCLogDebug!("incomplete of size {}", input.len());
if input.len() < 512 {
return 0;
}
- match parse_nbss_record_partial(input) {
- Ok((output, ref nbss_part_hdr)) => {
- SCLogDebug!("parse_nbss_record_partial ok, output len {}", output.len());
- if nbss_part_hdr.message_type == NBSS_MSGTYPE_SESSION_MESSAGE {
- match parse_smb_version(nbss_part_hdr.data) {
- Ok((_, ref smb)) => {
- SCLogDebug!("SMB {:?}", smb);
- if smb.version == 255u8 { // SMB1
- SCLogDebug!("SMBv1 record");
- match parse_smb_record(nbss_part_hdr.data) {
- Ok((_, ref r)) => {
- SCLogDebug!("SMB1: partial record {}",
- r.command);
- if r.command == SMB1_COMMAND_READ_ANDX {
- let tree_key = SMBCommonHdr::new(SMBHDR_TYPE_SHARE,
- r.ssn_id as u64, r.tree_id as u32, 0);
- let is_pipe = match self.ssn2tree_map.get(&tree_key) {
- Some(n) => n.is_pipe,
- None => false,
- };
- if is_pipe {
- return 0;
- }
- smb1_read_response_record(self, r, SMB1_HEADER_SIZE);
- let consumed = input.len() - output.len();
- return consumed;
- }
- },
- _ => { },
- }
- } else if smb.version == 254u8 { // SMB2
- SCLogDebug!("SMBv2 record");
- match parse_smb2_response_record(nbss_part_hdr.data) {
- Ok((_, ref smb_record)) => {
- SCLogDebug!("SMB2: partial record {}",
- &smb2_command_string(smb_record.command));
- if smb_record.command == SMB2_COMMAND_READ {
- smb2_read_response_record(self, smb_record);
- let consumed = input.len() - output.len();
- return consumed;
- }
- },
- _ => { },
+ if let Ok((output, ref nbss_part_hdr)) = parse_nbss_record_partial(input) {
+ SCLogDebug!("parse_nbss_record_partial ok, output len {}", output.len());
+ if nbss_part_hdr.message_type == NBSS_MSGTYPE_SESSION_MESSAGE {
+ if let Ok((_, ref smb)) = parse_smb_version(nbss_part_hdr.data) {
+ SCLogDebug!("SMB {:?}", smb);
+ if smb.version == 255u8 { // SMB1
+ SCLogDebug!("SMBv1 record");
+ if let Ok((_, ref r)) = parse_smb_record(nbss_part_hdr.data) {
+ SCLogDebug!("SMB1: partial record {}",
+ r.command);
+ if r.command == SMB1_COMMAND_READ_ANDX {
+ let tree_key = SMBCommonHdr::new(SMBHDR_TYPE_SHARE,
+ r.ssn_id as u64, r.tree_id as u32, 0);
+ let is_pipe = match self.ssn2tree_map.get(&tree_key) {
+ Some(n) => n.is_pipe,
+ None => false,
+ };
+ if is_pipe {
+ return 0;
}
+
+ // create NBSS frames here so we don't get double frames
+ // when we don't consume the data now.
+ self.add_nbss_tc_frames(flow, stream_slice, input, nbss_part_hdr.length as i64);
+ self.add_smb1_tc_pdu_frame(flow, stream_slice, nbss_part_hdr.data, nbss_part_hdr.length as i64);
+ self.add_smb1_tc_hdr_data_frames(flow, stream_slice, nbss_part_hdr.data, nbss_part_hdr.length as i64);
+
+ smb1_read_response_record(self, r, SMB1_HEADER_SIZE);
+ let consumed = input.len() - output.len();
+ return consumed;
}
- // no SMB3 here yet, will buffer full records
- },
- _ => { },
+ }
+ } else if smb.version == 254u8 { // SMB2
+ SCLogDebug!("SMBv2 record");
+ if let Ok((_, ref smb_record)) = parse_smb2_response_record(nbss_part_hdr.data) {
+ SCLogDebug!("SMB2: partial record {}",
+ &smb2_command_string(smb_record.command));
+ if smb_record.command == SMB2_COMMAND_READ {
+ // create NBSS frames here so we don't get double frames
+ // when we don't consume the data now.
+ self.add_nbss_tc_frames(flow, stream_slice, input, nbss_part_hdr.length as i64);
+ self.add_smb2_tc_pdu_frame(flow, stream_slice, nbss_part_hdr.data, nbss_part_hdr.length as i64);
+ self.add_smb2_tc_hdr_data_frames(flow, stream_slice, nbss_part_hdr.data, nbss_part_hdr.length as i64, smb_record.header_len as i64);
+
+ smb2_read_response_record(self, smb_record);
+ let consumed = input.len() - output.len();
+ return consumed;
+ }
+ }
}
+ // no SMB3 here yet, will buffer full records
}
- },
- _ => { },
+ }
}
-
return 0;
}
/// Parsing function, handling TCP chunks fragmentation
- pub fn parse_tcp_data_tc<'b>(&mut self, i: &'b[u8]) -> AppLayerResult
+ pub fn parse_tcp_data_tc<'b>(&mut self, flow: *const Flow, stream_slice: &StreamSlice) -> AppLayerResult
{
- let mut cur_i = i;
+ let mut cur_i = stream_slice.as_slice();
let consumed = self.handle_skip(Direction::ToClient, cur_i.len() as u32);
if consumed > 0 {
if consumed > cur_i.len() as u32 {
break;
},
_ => {
- let mut consumed = i.len();
+ let mut consumed = stream_slice.len();
if consumed < 4 {
consumed = 0;
} else {
while cur_i.len() > 0 { // min record size
match parse_nbss_record(cur_i) {
Ok((rem, ref nbss_hdr)) => {
+ SCLogDebug!("nbss record offset {} len {}", stream_slice.offset_from(cur_i), cur_i.len() - rem.len());
+ self.add_nbss_tc_frames(flow, stream_slice, cur_i, nbss_hdr.length as i64);
+ SCLogDebug!("nbss frames added");
+
if nbss_hdr.message_type == NBSS_MSGTYPE_SESSION_MESSAGE {
// we have the full records size worth of data,
// let's parse it
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);
+ self.add_smb1_tc_hdr_data_frames(flow, stream_slice, nbss_hdr.data, nbss_hdr.length as i64);
smb1_response_record(self, smb_record);
},
_ => {
SCLogDebug!("SMBv2 record");
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);
+ 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);
nbss_data = nbss_data_rem;
},
SCLogDebug!("SMBv3 transform record");
match parse_smb3_transform_record(nbss_data) {
Ok((nbss_data_rem, ref _smb3_record)) => {
+ let record_len = (nbss_data.len() - nbss_data_rem.len()) as i64;
+ self.add_smb3_tc_pdu_frame(flow, stream_slice, nbss_data, record_len);
+ self.add_smb3_tc_hdr_data_frames(flow, stream_slice, nbss_data, record_len);
nbss_data = nbss_data_rem;
},
_ => {
let n = usize::from(n) + cur_i.len();
// 512 is the minimum for parse_tcp_data_tc_partial
if n >= 512 && cur_i.len() < 512 {
- let total_consumed = i.len() - cur_i.len();
- return AppLayerResult::incomplete(total_consumed as u32, 512);
+ let total_consumed = stream_slice.offset_from(cur_i);
+ return AppLayerResult::incomplete(total_consumed, 512);
}
- let consumed = self.parse_tcp_data_tc_partial(cur_i);
+ let consumed = self.parse_tcp_data_tc_partial(flow, stream_slice, cur_i);
if consumed == 0 {
// if we consumed none we will buffer the entire record
- let total_consumed = i.len() - cur_i.len();
+ let total_consumed = stream_slice.offset_from(cur_i);
SCLogDebug!("setting consumed {} need {} needed {:?} total input {}",
- total_consumed, n, needed, i.len());
+ total_consumed, n, needed, stream_slice.len());
let need = n;
return AppLayerResult::incomplete(total_consumed as u32, need as u32);
}
}
state.update_ts(flow.get_last_time().as_secs());
- state.parse_tcp_data_ts(stream_slice.as_slice())
+ state.parse_tcp_data_ts(flow, &stream_slice)
}
#[no_mangle]
if stream_slice.is_gap() {
return rs_smb_parse_response_tcp_gap(state, stream_slice.gap_size());
}
- SCLogDebug!("parsing {} bytes of response data", stream_slice.len());
/* START with MISTREAM set: record might be starting the middle. */
if stream_slice.flags() & (STREAM_START|STREAM_MIDSTREAM) == (STREAM_START|STREAM_MIDSTREAM) {
}
state.update_ts(flow.get_last_time().as_secs());
- state.parse_tcp_data_tc(stream_slice.as_slice())
+ state.parse_tcp_data_tc(flow, &stream_slice)
}
#[no_mangle]
return ALPROTO_SMB;
}
+pub unsafe extern "C" fn smb_frames_get_frame_id_by_name(name: *const std::os::raw::c_char) -> std::os::raw::c_int {
+ if let Ok(s) = std::ffi::CStr::from_ptr(name).to_str() {
+ smb_frame_type_string(s) as std::os::raw::c_int
+ } else {
+ -1
+ }
+}
+
+pub unsafe extern "C" fn smb_frames_get_frame_by_id(id: u8) -> *const std::os::raw::c_char {
+ smb_frame_string_type(id)
+}
+
fn register_pattern_probe() -> i8 {
let mut r = 0;
unsafe {
apply_tx_config: None,
flags: APP_LAYER_PARSER_OPT_ACCEPT_GAPS,
truncate: Some(rs_smb_state_truncate),
- get_frame_id_by_name: None,
- get_frame_name_by_id: None,
+ get_frame_id_by_name: Some(smb_frames_get_frame_id_by_name),
+ get_frame_name_by_id: Some(smb_frames_get_frame_by_id),
};
let ip_proto_str = CString::new("tcp").unwrap();