From: Pierre Chifflier Date: Fri, 12 Nov 2021 17:20:51 +0000 (+0100) Subject: rust/smb: convert parser to nom7 functions (SMB2) X-Git-Tag: suricata-7.0.0-beta1~1115 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8d77ce1ffc10c6003ee9281d1c5137deac3fc29f;p=thirdparty%2Fsuricata.git rust/smb: convert parser to nom7 functions (SMB2) --- diff --git a/rust/src/smb/smb2.rs b/rust/src/smb/smb2.rs index 271428f3d6..e85906d8d3 100644 --- a/rust/src/smb/smb2.rs +++ b/rust/src/smb/smb2.rs @@ -15,7 +15,7 @@ * 02110-1301, USA. */ -use nom; +use nom7::Err; use crate::core::*; @@ -392,13 +392,13 @@ pub fn smb2_request_record<'b>(state: &mut SMBState, r: &Smb2Record<'b>) _ => false, } }, - Err(nom::Err::Incomplete(_n)) => { + Err(Err::Incomplete(_n)) => { SCLogDebug!("SMB2_COMMAND_SET_INFO: {:?}", _n); events.push(SMBEvent::MalformedData); false }, - Err(nom::Err::Error(_e)) | - Err(nom::Err::Failure(_e)) => { + Err(Err::Error(_e)) | + Err(Err::Failure(_e)) => { SCLogDebug!("SMB2_COMMAND_SET_INFO: {:?}", _e); events.push(SMBEvent::MalformedData); false diff --git a/rust/src/smb/smb2_records.rs b/rust/src/smb/smb2_records.rs index 01ffc5d77a..c892faad47 100644 --- a/rust/src/smb/smb2_records.rs +++ b/rust/src/smb/smb2_records.rs @@ -15,40 +15,41 @@ * 02110-1301, USA. */ -use nom; -use nom::IResult; -use nom::combinator::rest; -use nom::number::streaming::{le_u8, le_u16, le_u32, le_u64}; use crate::smb::smb::*; use crate::smb::nbss_records::NBSS_MSGTYPE_SESSION_MESSAGE; +use nom7::bits::{bits, streaming::take as take_bits}; +use nom7::bytes::streaming::{tag, take}; +use nom7::combinator::{cond, map_parser, rest}; +use nom7::error::{make_error, Error, ErrorKind}; +use nom7::multi::count; +use nom7::number::streaming::{le_u8, le_u16, le_u32, le_u64}; +use nom7::sequence::tuple; +use nom7::{Err, IResult, Needed}; #[derive(Debug,PartialEq)] pub struct Smb2SecBlobRecord<'a> { pub data: &'a[u8], } -named!(pub parse_smb2_sec_blob, - do_parse!( - data: rest - >> ( Smb2SecBlobRecord { - data: data, - }) -)); +pub fn parse_smb2_sec_blob(i: &[u8]) -> IResult<&[u8], Smb2SecBlobRecord> { + let (i, data) = rest(i)?; + Ok((i, Smb2SecBlobRecord { data })) +} #[derive(Debug,PartialEq)] pub struct Smb2RecordDir<> { pub request: bool, } -named!(pub parse_smb2_record_direction, - do_parse!( - _server_component: tag!(b"\xfeSMB") - >> _skip: take!(12) - >> flags: le_u8 - >> (Smb2RecordDir { - request: flags & 0x01 == 0, - }) -)); +pub fn parse_smb2_record_direction(i: &[u8]) -> IResult<&[u8], Smb2RecordDir> { + let (i, _server_component) = tag(b"\xfeSMB")(i)?; + let (i, _skip) = take(12_usize)(i)?; + let (i, flags) = le_u8(i)?; + let record = Smb2RecordDir { + request: flags & 0x01 == 0, + }; + Ok((i, record)) +} #[derive(Debug,PartialEq)] pub struct Smb2Record<'a> { @@ -69,49 +70,50 @@ impl<'a> Smb2Record<'a> { } fn parse_smb2_request_flags(i:&[u8]) -> IResult<&[u8],(u8,u8,u8,u32,u8,u8,u8,u8)> { - bits!(i, - tuple!( - take_bits!(2u8), // reserved / unused - take_bits!(1u8), // replay op - take_bits!(1u8), // dfs op - take_bits!(24u32), // reserved / unused - take_bits!(1u8), // signing - take_bits!(1u8), // chained - take_bits!(1u8), // async - take_bits!(1u8) // response - )) -} - -named!(pub parse_smb2_request_record, - do_parse!( - _server_component: tag!(b"\xfeSMB") - >> hlen: le_u16 - >> _credit_charge: le_u16 - >> _channel_seq: le_u16 - >> _reserved: take!(2) - >> command: le_u16 - >> _credits_requested: le_u16 - >> flags: parse_smb2_request_flags - >> chain_offset: le_u32 - >> message_id: le_u64 - >> _process_id: le_u32 - >> tree_id: le_u32 - >> session_id: le_u64 - >> _signature: take!(16) - // there is probably a cleaner way to do this - >> data_c: cond!(chain_offset > hlen as u32, take!(chain_offset - hlen as u32)) - >> data_r: cond!(chain_offset <= hlen as u32, rest) - >> (Smb2Record { - direction: flags.7, - nt_status: 0, - command:command, - message_id: message_id, - tree_id: tree_id, - async_id: 0, - session_id: session_id, - data: if data_c != None { data_c.unwrap() } else { data_r.unwrap() } - }) -)); + bits::<_, _, Error<(&[u8], usize)>, _, _>(tuple(( + take_bits(2u8), // reserved / unused + take_bits(1u8), // replay op + take_bits(1u8), // dfs op + take_bits(24u32), // reserved / unused + take_bits(1u8), // signing + take_bits(1u8), // chained + take_bits(1u8), // async + take_bits(1u8) // response + )))(i) +} + +pub fn parse_smb2_request_record(i: &[u8]) -> IResult<&[u8], Smb2Record> { + let (i, _server_component) = tag(b"\xfeSMB")(i)?; + let (i, hlen) = le_u16(i)?; + let (i, _credit_charge) = le_u16(i)?; + let (i, _channel_seq) = le_u16(i)?; + let (i, _reserved) = take(2_usize)(i)?; + let (i, command) = le_u16(i)?; + let (i, _credits_requested) = le_u16(i)?; + let (i, flags) = parse_smb2_request_flags(i)?; + let (i, chain_offset) = le_u32(i)?; + let (i, message_id) = le_u64(i)?; + let (i, _process_id) = le_u32(i)?; + let (i, tree_id) = le_u32(i)?; + let (i, session_id) = le_u64(i)?; + let (i, _signature) = take(16_usize)(i)?; + let (i, data) = if chain_offset > hlen as u32 { + take(chain_offset - hlen as u32)(i)? + } else { + rest(i)? + }; + let record = Smb2Record { + direction: flags.7, + nt_status: 0, + command, + message_id, + tree_id, + async_id: 0, + session_id, + data, + }; + Ok((i, record)) +} #[derive(Debug,PartialEq)] pub struct Smb2NegotiateProtocolRequestRecord<'a> { @@ -119,23 +121,23 @@ pub struct Smb2NegotiateProtocolRequestRecord<'a> { pub client_guid: &'a[u8], } -named!(pub parse_smb2_request_negotiate_protocol, - do_parse!( - _struct_size: take!(2) - >> dialects_count: le_u16 - >> _sec_mode: le_u16 - >> _reserved1: le_u16 - >> _capabilities: le_u32 - >> client_guid: take!(16) - >> _ctx_offset: le_u32 - >> _ctx_cnt: le_u16 - >> _reserved2: le_u16 - >> dia_vec: count!(le_u16, dialects_count as usize) - >> (Smb2NegotiateProtocolRequestRecord { - dialects_vec: dia_vec, - client_guid: client_guid, - }) -)); +pub fn parse_smb2_request_negotiate_protocol(i: &[u8]) -> IResult<&[u8], Smb2NegotiateProtocolRequestRecord> { + let (i, _struct_size) = take(2_usize)(i)?; + let (i, dialects_count) = le_u16(i)?; + let (i, _sec_mode) = le_u16(i)?; + let (i, _reserved1) = le_u16(i)?; + let (i, _capabilities) = le_u32(i)?; + let (i, client_guid) = take(16_usize)(i)?; + let (i, _ctx_offset) = le_u32(i)?; + let (i, _ctx_cnt) = le_u16(i)?; + let (i, _reserved2) = le_u16(i)?; + let (i, dia_vec) = count(le_u16, dialects_count as usize)(i)?; + let record = Smb2NegotiateProtocolRequestRecord { + dialects_vec: dia_vec, + client_guid, + }; + Ok((i, record)) +} #[derive(Debug,PartialEq)] pub struct Smb2NegotiateProtocolResponseRecord<'a> { @@ -143,28 +145,28 @@ pub struct Smb2NegotiateProtocolResponseRecord<'a> { pub server_guid: &'a[u8], } -named!(pub parse_smb2_response_negotiate_protocol, - do_parse!( - _struct_size: take!(2) - >> _skip1: take!(2) - >> dialect: le_u16 - >> _ctx_cnt: le_u16 - >> server_guid: take!(16) - >> (Smb2NegotiateProtocolResponseRecord { - dialect, - server_guid - }) -)); - -named!(pub parse_smb2_response_negotiate_protocol_error, - do_parse!( - _struct_size: take!(2) - >> _skip1: take!(2) - >> (Smb2NegotiateProtocolResponseRecord { - dialect: 0, - server_guid: &[], - }) -)); +pub fn parse_smb2_response_negotiate_protocol(i: &[u8]) -> IResult<&[u8], Smb2NegotiateProtocolResponseRecord> { + let (i, _struct_size) = take(2_usize)(i)?; + let (i, _skip1) = take(2_usize)(i)?; + let (i, dialect) = le_u16(i)?; + let (i, _ctx_cnt) = le_u16(i)?; + let (i, server_guid) = take(16_usize)(i)?; + let record = Smb2NegotiateProtocolResponseRecord { + dialect, + server_guid + }; + Ok((i, record)) +} + +pub fn parse_smb2_response_negotiate_protocol_error(i: &[u8]) -> IResult<&[u8], Smb2NegotiateProtocolResponseRecord> { + let (i, _struct_size) = take(2_usize)(i)?; + let (i, _skip1) = take(2_usize)(i)?; + let record = Smb2NegotiateProtocolResponseRecord { + dialect: 0, + server_guid: &[], + }; + Ok((i, record)) +} #[derive(Debug,PartialEq)] @@ -172,55 +174,49 @@ pub struct Smb2SessionSetupRequestRecord<'a> { pub data: &'a[u8], } -named!(pub parse_smb2_request_session_setup, - do_parse!( - _struct_size: take!(2) - >> _flags: le_u8 - >> _security_mode: le_u8 - >> _capabilities: le_u32 - >> _channel: le_u32 - >> _sec_offset: le_u16 - >> _sec_len: le_u16 - >> _prev_ssn_id: take!(8) - >> data: rest - >> (Smb2SessionSetupRequestRecord { - data:data, - }) -)); - +pub fn parse_smb2_request_session_setup(i: &[u8]) -> IResult<&[u8], Smb2SessionSetupRequestRecord> { + let (i, _struct_size) = take(2_usize)(i)?; + let (i, _flags) = le_u8(i)?; + let (i, _security_mode) = le_u8(i)?; + let (i, _capabilities) = le_u32(i)?; + let (i, _channel) = le_u32(i)?; + let (i, _sec_offset) = le_u16(i)?; + let (i, _sec_len) = le_u16(i)?; + let (i, _prev_ssn_id) = take(8_usize)(i)?; + let (i, data) = rest(i)?; + let record = Smb2SessionSetupRequestRecord { data }; + Ok((i, record)) +} #[derive(Debug,PartialEq)] pub struct Smb2TreeConnectRequestRecord<'a> { pub share_name: &'a[u8], } -named!(pub parse_smb2_request_tree_connect, - do_parse!( - _struct_size: take!(2) - >> _offset_length: take!(4) - >> data: rest - >> (Smb2TreeConnectRequestRecord { - share_name:data, - }) -)); +pub fn parse_smb2_request_tree_connect(i: &[u8]) -> IResult<&[u8], Smb2TreeConnectRequestRecord> { + let (i, _struct_size) = take(2_usize)(i)?; + let (i, _offset_length) = take(4_usize)(i)?; + let (i, data) = rest(i)?; + let record = Smb2TreeConnectRequestRecord { + share_name:data, + }; + Ok((i, record)) +} #[derive(Debug,PartialEq)] pub struct Smb2TreeConnectResponseRecord<> { pub share_type: u8, } -named!(pub parse_smb2_response_tree_connect, - do_parse!( - _struct_size: take!(2) - >> share_type: le_u8 - >> _share_flags: le_u32 - >> _share_caps: le_u32 - >> _access_mask: le_u32 - >> (Smb2TreeConnectResponseRecord { - share_type - }) -)); - +pub fn parse_smb2_response_tree_connect(i: &[u8]) -> IResult<&[u8], Smb2TreeConnectResponseRecord> { + let (i, _struct_size) = take(2_usize)(i)?; + let (i, share_type) = le_u8(i)?; + let (i, _share_flags) = le_u32(i)?; + let (i, _share_caps) = le_u32(i)?; + let (i, _access_mask) = le_u32(i)?; + let record = Smb2TreeConnectResponseRecord { share_type }; + Ok((i, record)) +} #[derive(Debug,PartialEq)] pub struct Smb2CreateRequestRecord<'a> { @@ -229,22 +225,22 @@ pub struct Smb2CreateRequestRecord<'a> { pub data: &'a[u8], } -named!(pub parse_smb2_request_create, - do_parse!( - _skip1: take!(36) - >> disposition: le_u32 - >> create_options: le_u32 - >> _file_name_offset: le_u16 - >> file_name_length: le_u16 - >> _skip2: take!(8) - >> data: take!(file_name_length) - >> _skip3: rest - >> (Smb2CreateRequestRecord { - disposition, - create_options, - data - }) -)); +pub fn parse_smb2_request_create(i: &[u8]) -> IResult<&[u8], Smb2CreateRequestRecord> { + let (i, _skip1) = take(36_usize)(i)?; + let (i, disposition) = le_u32(i)?; + let (i, create_options) = le_u32(i)?; + let (i, _file_name_offset) = le_u16(i)?; + let (i, file_name_length) = le_u16(i)?; + let (i, _skip2) = take(8_usize)(i)?; + let (i, data) = take(file_name_length)(i)?; + let (i, _skip3) = rest(i)?; + let record = Smb2CreateRequestRecord { + disposition, + create_options, + data + }; + Ok((i, record)) +} #[derive(Debug,PartialEq)] pub struct Smb2IOCtlRequestRecord<'a> { @@ -254,26 +250,26 @@ pub struct Smb2IOCtlRequestRecord<'a> { pub data: &'a[u8], } -named!(pub parse_smb2_request_ioctl, - do_parse!( - _skip: take!(2) // structure size - >> take!(2) // reserved - >> func: le_u32 - >> guid: take!(16) - >> _indata_offset: le_u32 - >> indata_len: le_u32 - >> take!(4) - >> _outdata_offset: le_u32 - >> _outdata_len: le_u32 - >> take!(12) - >> data: take!(indata_len) - >> (Smb2IOCtlRequestRecord { - is_pipe: (func == 0x0011c017), - function: func, - guid:guid, - data:data, - }) -)); +pub fn parse_smb2_request_ioctl(i: &[u8]) -> IResult<&[u8], Smb2IOCtlRequestRecord> { + let (i, _skip) = take(2_usize) (i)?;// structure size + let (i, _) = take(2_usize) (i)?;// reserved + let (i, func) = le_u32(i)?; + let (i, guid) = take(16_usize)(i)?; + let (i, _indata_offset) = le_u32(i)?; + let (i, indata_len) = le_u32(i)?; + let (i, _) = take(4_usize)(i)?; + let (i, _outdata_offset) = le_u32(i)?; + let (i, _outdata_len) = le_u32(i)?; + let (i, _) = take(12_usize)(i)?; + let (i, data) = take(indata_len)(i)?; + let record = Smb2IOCtlRequestRecord { + is_pipe: (func == 0x0011c017), + function: func, + guid, + data, + }; + Ok((i, record)) +} #[derive(Debug,PartialEq)] pub struct Smb2IOCtlResponseRecord<'a> { @@ -286,73 +282,69 @@ pub struct Smb2IOCtlResponseRecord<'a> { pub outdata_offset: u32, } -named!(pub parse_smb2_response_ioctl, - do_parse!( - _skip: take!(2) // structure size - >> take!(2) // reserved - >> func: le_u32 - >> guid: take!(16) - >> indata_offset: le_u32 - >> indata_len: le_u32 - >> outdata_offset: le_u32 - >> outdata_len: le_u32 - >> take!(8) - >> take!(indata_len) - >> data: take!(outdata_len) - >> (Smb2IOCtlResponseRecord { - is_pipe: (func == 0x0011c017), - guid:guid, - data:data, - indata_len:indata_len, - outdata_len:outdata_len, - indata_offset:indata_offset, - outdata_offset:outdata_offset, - }) -)); +pub fn parse_smb2_response_ioctl(i: &[u8]) -> IResult<&[u8], Smb2IOCtlResponseRecord> { + let (i, _skip) = take(2_usize)(i)?; // structure size + let (i, _) = take(2_usize)(i)?; // reserved + let (i, func) = le_u32(i)?; + let (i, guid) = take(16_usize)(i)?; + let (i, indata_offset) = le_u32(i)?; + let (i, indata_len) = le_u32(i)?; + let (i, outdata_offset) = le_u32(i)?; + let (i, outdata_len) = le_u32(i)?; + let (i, _) = take(8_usize)(i)?; + let (i, _) = take(indata_len)(i)?; + let (i, data) = take(outdata_len)(i)?; + let record = Smb2IOCtlResponseRecord { + is_pipe: (func == 0x0011c017), + guid, + data, + indata_len, + outdata_len, + indata_offset, + outdata_offset, + }; + Ok((i, record)) +} #[derive(Debug,PartialEq)] pub struct Smb2CloseRequestRecord<'a> { pub guid: &'a[u8], } -named!(pub parse_smb2_request_close, - do_parse!( - _skip: take!(8) - >> guid: take!(16) - >> (Smb2CloseRequestRecord { - guid - }) -)); +pub fn parse_smb2_request_close(i: &[u8]) -> IResult<&[u8], Smb2CloseRequestRecord> { + let (i, _skip) = take(8_usize)(i)?; + let (i, guid) = take(16_usize)(i)?; + let record = Smb2CloseRequestRecord { guid }; + Ok((i, record)) +} #[derive(Debug)] pub struct Smb2SetInfoRequestRenameRecord<'a> { pub name: &'a[u8], } -named!(pub parse_smb2_request_setinfo_rename, - do_parse!( - _replace: le_u8 - >> _reserved: take!(7) - >> _root_handle: take!(8) - >> name_len: le_u32 - >> name: take!(name_len) - >> (Smb2SetInfoRequestData::RENAME(Smb2SetInfoRequestRenameRecord { - name - })) -)); +pub fn parse_smb2_request_setinfo_rename(i: &[u8]) -> IResult<&[u8], Smb2SetInfoRequestData> { + let (i, _replace) = le_u8(i)?; + let (i, _reserved) = take(7_usize)(i)?; + let (i, _root_handle) = take(8_usize)(i)?; + let (i, name_len) = le_u32(i)?; + let (i, name) = take(name_len)(i)?; + let record = Smb2SetInfoRequestData::RENAME(Smb2SetInfoRequestRenameRecord { name }); + Ok((i, record)) +} #[derive(Debug)] pub struct Smb2SetInfoRequestDispoRecord { pub delete: bool, } -named!(pub parse_smb2_request_setinfo_disposition<&[u8], Smb2SetInfoRequestData>, - do_parse!( - info: le_u8 >> - (Smb2SetInfoRequestData::DISPOSITION(Smb2SetInfoRequestDispoRecord { - delete: info & 1 != 0, - })) -)); +pub fn parse_smb2_request_setinfo_disposition(i: &[u8]) -> IResult<&[u8], Smb2SetInfoRequestData> { + let (i, info) = le_u8(i)?; + let record = Smb2SetInfoRequestData::DISPOSITION(Smb2SetInfoRequestDispoRecord { + delete: info & 1 != 0, + }); + Ok((i, record)) +} #[derive(Debug)] pub enum Smb2SetInfoRequestData<'a> { @@ -387,24 +379,27 @@ fn parse_smb2_request_setinfo_data( return Ok((i, Smb2SetInfoRequestData::UNHANDLED)); } -named!(pub parse_smb2_request_setinfo, - do_parse!( - _struct_size: le_u16 - >> class: le_u8 - >> infolvl: le_u8 - >> setinfo_size: le_u32 - >> _setinfo_offset: le_u16 - >> _reserved: take!(2) - >> _additional_info: le_u32 - >> guid: take!(16) - >> data: flat_map!(take!(setinfo_size), call!(parse_smb2_request_setinfo_data, class, infolvl)) - >> (Smb2SetInfoRequestRecord { - guid: guid, - class: class, - infolvl: infolvl, - data: data, - }) -)); +pub fn parse_smb2_request_setinfo(i: &[u8]) -> IResult<&[u8], Smb2SetInfoRequestRecord> { + let (i, _struct_size) = le_u16(i)?; + let (i, class) = le_u8(i)?; + let (i, infolvl) = le_u8(i)?; + let (i, setinfo_size) = le_u32(i)?; + let (i, _setinfo_offset) = le_u16(i)?; + let (i, _reserved) = take(2_usize)(i)?; + let (i, _additional_info) = le_u32(i)?; + let (i, guid) = take(16_usize)(i)?; + let (i, data) = map_parser( + take(setinfo_size), + |b| parse_smb2_request_setinfo_data(b, class, infolvl) + )(i)?; + let record = Smb2SetInfoRequestRecord { + guid, + class, + infolvl, + data, + }; + Ok((i, record)) +} #[derive(Debug,PartialEq)] pub struct Smb2WriteRequestRecord<'a> { @@ -415,24 +410,24 @@ pub struct Smb2WriteRequestRecord<'a> { } // can be called on incomplete records -named!(pub parse_smb2_request_write, - do_parse!( - _skip1: take!(4) - >> wr_len: le_u32 - >> wr_offset: le_u64 - >> guid: take!(16) - >> _channel: le_u32 - >> _remaining_bytes: le_u32 - >> _write_flags: le_u32 - >> _skip2: take!(4) - >> data: call!(parse_smb2_data, wr_len) - >> (Smb2WriteRequestRecord { - wr_len:wr_len, - wr_offset:wr_offset, - guid:guid, - data:data, - }) -)); +pub fn parse_smb2_request_write(i: &[u8]) -> IResult<&[u8], Smb2WriteRequestRecord> { + let (i, _skip1) = take(4_usize)(i)?; + let (i, wr_len) = le_u32(i)?; + let (i, wr_offset) = le_u64(i)?; + let (i, guid) = take(16_usize)(i)?; + let (i, _channel) = le_u32(i)?; + let (i, _remaining_bytes) = le_u32(i)?; + let (i, _write_flags) = le_u32(i)?; + let (i, _skip2) = take(4_usize)(i)?; + let (i, data) = parse_smb2_data(i, wr_len)?; + let record = Smb2WriteRequestRecord { + wr_len, + wr_offset, + guid, + data, + }; + Ok((i, record)) +} #[derive(Debug,PartialEq)] pub struct Smb2ReadRequestRecord<'a> { @@ -441,22 +436,22 @@ pub struct Smb2ReadRequestRecord<'a> { pub guid: &'a[u8], } -named!(pub parse_smb2_request_read, - do_parse!( - _skip1: take!(4) - >> rd_len: le_u32 - >> rd_offset: le_u64 - >> guid: take!(16) - >> _min_count: le_u32 - >> _channel: le_u32 - >> _remaining_bytes: le_u32 - >> _skip2: take!(4) - >> (Smb2ReadRequestRecord { - rd_len:rd_len, - rd_offset:rd_offset, - guid:guid, - }) -)); +pub fn parse_smb2_request_read(i: &[u8]) -> IResult<&[u8], Smb2ReadRequestRecord> { + let (i, _skip1) = take(4_usize)(i)?; + let (i, rd_len) = le_u32(i)?; + let (i, rd_offset) = le_u64(i)?; + let (i, guid) = take(16_usize)(i)?; + let (i, _min_count) = le_u32(i)?; + let (i, _channel) = le_u32(i)?; + let (i, _remaining_bytes) = le_u32(i)?; + let (i, _skip2) = take(4_usize)(i)?; + let record = Smb2ReadRequestRecord { + rd_len, + rd_offset, + guid, + }; + Ok((i, record)) +} #[derive(Debug,PartialEq)] pub struct Smb2ReadResponseRecord<'a> { @@ -473,24 +468,24 @@ fn parse_smb2_data<'a>(i: &'a[u8], len: u32) if len as usize > i.len() { rest(i) } else { - take!(i, len) + take(len)(i) } } // can be called on incomplete records -named!(pub parse_smb2_response_read, - do_parse!( - _struct_size: le_u16 - >> _data_offset: le_u16 - >> rd_len: le_u32 - >> _rd_rem: le_u32 - >> _padding: take!(4) - >> data: call!(parse_smb2_data, rd_len) - >> (Smb2ReadResponseRecord { - len : rd_len, - data : data, - }) -)); +pub fn parse_smb2_response_read(i: &[u8]) -> IResult<&[u8], Smb2ReadResponseRecord> { + let (i, _struct_size) = le_u16(i)?; + let (i, _data_offset) = le_u16(i)?; + let (i, rd_len) = le_u32(i)?; + let (i, _rd_rem) = le_u32(i)?; + let (i, _padding) = take(4_usize)(i)?; + let (i, data) = parse_smb2_data(i, rd_len)?; + let record = Smb2ReadResponseRecord { + len: rd_len, + data, + }; + Ok((i, record)) +} #[derive(Debug,PartialEq)] pub struct Smb2CreateResponseRecord<'a> { @@ -502,77 +497,77 @@ pub struct Smb2CreateResponseRecord<'a> { pub size: u64, } -named!(pub parse_smb2_response_create, - do_parse!( - _ssize: le_u16 - >> _oplock: le_u8 - >> _resp_flags: le_u8 - >> _create_action: le_u32 - >> create_ts: le_u64 - >> last_access_ts: le_u64 - >> last_write_ts: le_u64 - >> last_change_ts: le_u64 - >> _alloc_size: le_u64 - >> eof: le_u64 - >> _attrs: le_u32 - >> _padding: take!(4) - >> guid: take!(16) - >> _skip2: take!(8) - >> (Smb2CreateResponseRecord { - guid : guid, - create_ts: SMBFiletime::new(create_ts), - last_access_ts: SMBFiletime::new(last_access_ts), - last_write_ts: SMBFiletime::new(last_write_ts), - last_change_ts: SMBFiletime::new(last_change_ts), - size: eof, - }) -)); +pub fn parse_smb2_response_create(i: &[u8]) -> IResult<&[u8], Smb2CreateResponseRecord> { + let (i, _ssize) = le_u16(i)?; + let (i, _oplock) = le_u8(i)?; + let (i, _resp_flags) = le_u8(i)?; + let (i, _create_action) = le_u32(i)?; + let (i, create_ts) = le_u64(i)?; + let (i, last_access_ts) = le_u64(i)?; + let (i, last_write_ts) = le_u64(i)?; + let (i, last_change_ts) = le_u64(i)?; + let (i, _alloc_size) = le_u64(i)?; + let (i, eof) = le_u64(i)?; + let (i, _attrs) = le_u32(i)?; + let (i, _padding) = take(4_usize)(i)?; + let (i, guid) = take(16_usize)(i)?; + let (i, _skip2) = take(8_usize)(i)?; + let record = Smb2CreateResponseRecord { + guid, + create_ts: SMBFiletime::new(create_ts), + last_access_ts: SMBFiletime::new(last_access_ts), + last_write_ts: SMBFiletime::new(last_write_ts), + last_change_ts: SMBFiletime::new(last_change_ts), + size: eof, + }; + Ok((i, record)) +} #[derive(Debug,PartialEq)] pub struct Smb2WriteResponseRecord<> { pub wr_cnt: u32, } -named!(pub parse_smb2_response_write, - do_parse!( - _skip1: take!(4) - >> wr_cnt: le_u32 - >> _skip2: take!(6) - >> (Smb2WriteResponseRecord { - wr_cnt : wr_cnt, - }) -)); - -named!(pub parse_smb2_response_record, - do_parse!( - tag!(b"\xfeSMB") - >> hlen: le_u16 - >> _credit_charge: le_u16 - >> nt_status: le_u32 - >> command: le_u16 - >> _credit_granted: le_u16 - >> flags: parse_smb2_request_flags - >> chain_offset: le_u32 - >> message_id: le_u64 - >> _process_id: cond!(flags.6==0, le_u32) - >> tree_id: cond!(flags.6==0, le_u32) - >> async_id: cond!(flags.6==1, le_u64) - >> session_id: le_u64 - >> _signature: take!(16) - // there is probably a cleaner way to do this - >> data_c: cond!(chain_offset > hlen as u32, take!(chain_offset - hlen as u32)) - >> data_r: cond!(chain_offset <= hlen as u32, rest) - >> (Smb2Record { - direction: flags.7, - nt_status: nt_status, - message_id: message_id, - tree_id: tree_id.unwrap_or(0), - async_id: async_id.unwrap_or(0), - session_id: session_id, - command:command, - data: data_c.or(data_r).unwrap() - }) -)); +pub fn parse_smb2_response_write(i: &[u8]) -> IResult<&[u8], Smb2WriteResponseRecord> { + let (i, _skip1) = take(4_usize)(i)?; + let (i, wr_cnt) = le_u32(i)?; + let (i, _skip2) = take(6_usize)(i)?; + let record = Smb2WriteResponseRecord { wr_cnt }; + Ok((i, record)) +} + +pub fn parse_smb2_response_record(i: &[u8]) -> IResult<&[u8], Smb2Record> { + let (i, _) = tag(b"\xfeSMB")(i)?; + let (i, hlen) = le_u16(i)?; + let (i, _credit_charge) = le_u16(i)?; + let (i, nt_status) = le_u32(i)?; + let (i, command) = le_u16(i)?; + let (i, _credit_granted) = le_u16(i)?; + let (i, flags) = parse_smb2_request_flags(i)?; + let (i, chain_offset) = le_u32(i)?; + let (i, message_id) = le_u64(i)?; + let (i, _process_id) = cond(flags.6 == 0, le_u32)(i)?; + let (i, tree_id) = cond(flags.6 == 0, le_u32)(i)?; + let (i, async_id) = cond(flags.6 == 1, le_u64)(i)?; + let (i, session_id) = le_u64(i)?; + let (i, _signature) = take(16_usize)(i)?; + let (i, data) = if chain_offset > hlen as u32 { + take(chain_offset - hlen as u32)(i)? + } else { + rest(i)? + }; + let record = Smb2Record { + direction: flags.7, + nt_status, + message_id, + tree_id: tree_id.unwrap_or(0), + async_id: async_id.unwrap_or(0), + session_id, + command, + data, + }; + Ok((i, record)) +} fn smb_basic_search(d: &[u8]) -> usize { let needle = b"SMB"; @@ -588,12 +583,12 @@ fn smb_basic_search(d: &[u8]) -> usize { return 0; } -pub fn search_smb_record<'a>(i: &'a [u8]) -> nom::IResult<&'a [u8], &'a [u8]> { +pub fn search_smb_record<'a>(i: &'a [u8]) -> IResult<&'a [u8], &'a [u8]> { let mut d = i; while d.len() >= 4 { let index = smb_basic_search(d); if index == 0 { - return Err(nom::Err::Error((d, nom::error::ErrorKind::Eof))); + return Err(Err::Error(make_error(d, ErrorKind::Eof))); } if d[index - 1] == 0xfe || d[index - 1] == 0xff || d[index - 1] == 0xfd { // if we have enough data, check nbss @@ -603,5 +598,5 @@ pub fn search_smb_record<'a>(i: &'a [u8]) -> nom::IResult<&'a [u8], &'a [u8]> { } d = &d[index + 3..]; } - Err(nom::Err::Incomplete(nom::Needed::Size(4 as usize - d.len()))) + Err(Err::Incomplete(Needed::new(4 as usize - d.len()))) }