From: Philippe Antoine Date: Mon, 4 Apr 2022 20:45:56 +0000 (+0200) Subject: smb: check on param parsing X-Git-Tag: suricata-6.0.6~65 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d80fbfd4c6ed52480a891e5cd2f66220822c9a23;p=thirdparty%2Fsuricata.git smb: check on param parsing Ticket: 5246 so as not to overflow u16 (cherry picked from commit 817a5001a50a90800547e66fef067c0443eb9f72) --- diff --git a/rust/src/smb/smb1_records.rs b/rust/src/smb/smb1_records.rs index 18f80d93ef..8747ef84e3 100644 --- a/rust/src/smb/smb1_records.rs +++ b/rust/src/smb/smb1_records.rs @@ -16,11 +16,13 @@ */ use crate::smb::error::SmbError; -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::smb_records::*; +use nom::bytes::streaming:: take; +use nom::combinator::{cond, rest, verify}; +use nom::number::streaming::{le_u8, le_u16, le_u32, le_u64}; +use nom::IResult; + // SMB_FLAGS_REPLY in Microsoft docs. const SMB1_FLAGS_RESPONSE: u8 = 0x80; @@ -656,37 +658,41 @@ pub struct SmbRequestTrans2Record<'a> { pub data_blob: &'a[u8], } -named!(pub parse_smb_trans2_request_record, - do_parse!( - _wct: le_u8 - >> _total_param_cnt: le_u16 - >> _total_data_cnt: le_u16 - >> _max_param_cnt: le_u16 - >> _max_data_cnt: le_u16 - >> _max_setup_cnt: le_u8 - >> _reserved1: take!(1) - >> _flags: le_u16 - >> _timeout: le_u32 - >> _reserved2: take!(2) - >> param_cnt: le_u16 - >> _param_offset: le_u16 - >> data_cnt: le_u16 - >> _data_offset: le_u16 - >> _setup_cnt: le_u8 - >> _reserved3: take!(1) - >> subcmd: le_u16 - >> _bcc: le_u16 - >> _padding: take!(3) - //TODO test and use _param_offset and _data_offset - >> setup_blob: take!(param_cnt) - >> data_blob: take!(data_cnt) - - >> (SmbRequestTrans2Record { - subcmd, - setup_blob, - data_blob - })) -); +pub fn parse_smb_trans2_request_record(i: &[u8]) -> IResult<&[u8], SmbRequestTrans2Record> { + let (i, _wct) = le_u8(i)?; + let (i, _total_param_cnt) = le_u16(i)?; + let (i, _total_data_cnt) = le_u16(i)?; + let (i, _max_param_cnt) = le_u16(i)?; + let (i, _max_data_cnt) = le_u16(i)?; + let (i, _max_setup_cnt) = le_u8(i)?; + let (i, _reserved1) = take(1_usize)(i)?; + let (i, _flags) = le_u16(i)?; + let (i, _timeout) = le_u32(i)?; + let (i, _reserved2) = take(2_usize)(i)?; + let (i, param_cnt) = le_u16(i)?; + let (i, param_offset) = verify(le_u16, |&v| v <= (std::u16::MAX - param_cnt))(i)?; + let (i, data_cnt) = le_u16(i)?; + let (i, data_offset) = le_u16(i)?; + let (i, _setup_cnt) = le_u8(i)?; + let (i, _reserved3) = take(1_usize)(i)?; + let (i, subcmd) = le_u16(i)?; + let (i, _bcc) = le_u16(i)?; + //TODO test and use param_offset + let (i, _padding) = take(3_usize)(i)?; + let (i, setup_blob) = take(param_cnt)(i)?; + let (i, _padding2) = cond( + data_offset > param_offset + param_cnt, + |b| take(data_offset - param_offset - param_cnt)(b) + )(i)?; + let (i, data_blob) = take(data_cnt)(i)?; + + let record = SmbRequestTrans2Record { + subcmd, + setup_blob, + data_blob + }; + Ok((i, record)) +} #[derive(Debug,PartialEq)] pub struct SmbResponseCreateAndXRecord<'a> {