From d1bf34a4276b026da431c51a44ad1f7a93dd73e3 Mon Sep 17 00:00:00 2001 From: Pierre Chifflier Date: Thu, 31 Oct 2019 08:21:12 +0100 Subject: [PATCH] rust/smb: add custom error handling --- rust/src/smb/dcerpc_records.rs | 10 +++++----- rust/src/smb/error.rs | 35 ++++++++++++++++++++++++++++++++++ rust/src/smb/mod.rs | 1 + rust/src/smb/smb1_records.rs | 21 ++++++++++---------- rust/src/smb/smb_records.rs | 8 ++++---- 5 files changed, 56 insertions(+), 19 deletions(-) create mode 100644 rust/src/smb/error.rs diff --git a/rust/src/smb/dcerpc_records.rs b/rust/src/smb/dcerpc_records.rs index 3d0e4e1a8f..fa47a0cfda 100644 --- a/rust/src/smb/dcerpc_records.rs +++ b/rust/src/smb/dcerpc_records.rs @@ -15,9 +15,9 @@ * 02110-1301, USA. */ +use crate::smb::error::SmbError; use nom; use nom::IResult; -use nom::error::ErrorKind; use nom::combinator::rest; use nom::number::Endianness; use nom::number::complete::{be_u16, le_u8, le_u16, le_u32}; @@ -30,10 +30,10 @@ pub struct DceRpcResponseRecord<'a> { /// parse a packet type 'response' DCERPC record. Implemented /// as function to be able to pass the fraglen in. pub fn parse_dcerpc_response_record(i:&[u8], frag_len: u16 ) - -> IResult<&[u8], DceRpcResponseRecord> + -> IResult<&[u8], DceRpcResponseRecord, SmbError> { if frag_len < 24 { - return Err(nom::Err::Error(error_position!(i,ErrorKind::Custom(128)))); + return Err(nom::Err::Error(SmbError::RecordTooSmall)); } do_parse!(i, take!(8) @@ -53,10 +53,10 @@ pub struct DceRpcRequestRecord<'a> { /// parse a packet type 'request' DCERPC record. Implemented /// as function to be able to pass the fraglen in. pub fn parse_dcerpc_request_record(i:&[u8], frag_len: u16, little: bool) - -> IResult<&[u8], DceRpcRequestRecord> + -> IResult<&[u8], DceRpcRequestRecord, SmbError> { if frag_len < 24 { - return Err(nom::Err::Error(error_position!(i,ErrorKind::Custom(128)))); + return Err(nom::Err::Error(SmbError::RecordTooSmall)); } do_parse!(i, take!(6) diff --git a/rust/src/smb/error.rs b/rust/src/smb/error.rs new file mode 100644 index 0000000000..ab9c863674 --- /dev/null +++ b/rust/src/smb/error.rs @@ -0,0 +1,35 @@ +/* Copyright (C) 2019 Open Information Security Foundation + * + * You can copy, redistribute or modify this Program under the terms of + * the GNU General Public License version 2 as published by the Free + * Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +// Author: Pierre Chifflier +use nom::error::{ErrorKind, ParseError}; + +#[derive(Debug)] +pub enum SmbError { + BadEncoding, + RecordTooSmall, + NomError(ErrorKind), +} + +impl ParseError for SmbError { + fn from_error_kind(_input: I, kind: ErrorKind) -> Self { + SmbError::NomError(kind) + } + fn append(_input: I, kind: ErrorKind, _other: Self) -> Self { + SmbError::NomError(kind) + } +} diff --git a/rust/src/smb/mod.rs b/rust/src/smb/mod.rs index 65e1577ffc..2d4d5e9b7c 100644 --- a/rust/src/smb/mod.rs +++ b/rust/src/smb/mod.rs @@ -15,6 +15,7 @@ * 02110-1301, USA. */ +pub mod error; pub mod smb_records; pub mod smb1_records; pub mod smb2_records; diff --git a/rust/src/smb/smb1_records.rs b/rust/src/smb/smb1_records.rs index 83271a256b..148631fbf8 100644 --- a/rust/src/smb/smb1_records.rs +++ b/rust/src/smb/smb1_records.rs @@ -15,6 +15,7 @@ * 02110-1301, USA. */ +use crate::smb::error::SmbError; use crate::log::*; use nom::IResult; use nom::combinator::rest; @@ -22,7 +23,7 @@ use nom::number::complete::{le_u8, le_u16, le_u32, le_u64}; use crate::smb::smb::*; use crate::smb::smb_records::*; -fn smb_get_unicode_string_with_offset(i: &[u8], offset: usize) -> IResult<&[u8], Vec> +fn smb_get_unicode_string_with_offset(i: &[u8], offset: usize) -> IResult<&[u8], Vec, SmbError> { do_parse!(i, cond!(offset % 2 == 1, take!(1)) @@ -32,7 +33,7 @@ fn smb_get_unicode_string_with_offset(i: &[u8], offset: usize) -> IResult<&[u8], } /// take a string, unicode or ascii based on record -pub fn smb1_get_string<'a>(i: &'a[u8], r: &SmbRecord, offset: usize) -> IResult<&'a[u8], Vec> { +pub fn smb1_get_string<'a>(i: &'a[u8], r: &SmbRecord, offset: usize) -> IResult<&'a[u8], Vec, SmbError> { if r.has_unicode_support() { smb_get_unicode_string_with_offset(i, offset) } else { @@ -198,7 +199,7 @@ pub struct SmbRecordTreeConnectAndX<'a> { pub service: &'a[u8], } -pub fn parse_smb_connect_tree_andx_record<'a>(i: &'a[u8], r: &SmbRecord) -> IResult<&'a[u8], SmbRecordTreeConnectAndX<'a>> { +pub fn parse_smb_connect_tree_andx_record<'a>(i: &'a[u8], r: &SmbRecord) -> IResult<&'a[u8], SmbRecordTreeConnectAndX<'a>, SmbError> { do_parse!(i, _skip1: take!(7) >> pwlen: le_u16 @@ -226,7 +227,7 @@ pub struct SmbPipeProtocolRecord<'a> { pub fid: &'a[u8], } -named!(pub parse_smb_trans_request_record_pipe, +named!(pub parse_smb_trans_request_record_pipe<&[u8], SmbPipeProtocolRecord, SmbError>, do_parse!( fun: le_u16 >> fid: take!(2) @@ -248,7 +249,7 @@ pub struct SmbRecordTransRequestParams<> { bcc: u16, } -named!(pub parse_smb_trans_request_record_params<(SmbRecordTransRequestParams, Option)>, +named!(pub parse_smb_trans_request_record_params<&[u8], (SmbRecordTransRequestParams, Option), SmbError>, do_parse!( wct: le_u8 >> _total_param_cnt: le_u16 @@ -286,7 +287,7 @@ pub struct SmbRecordTransRequestData<'a> { pub fn parse_smb_trans_request_record_data(i: &[u8], pad1: usize, param_cnt: u16, pad2: usize, data_len: u16) - -> IResult<&[u8], SmbRecordTransRequestData> + -> IResult<&[u8], SmbRecordTransRequestData, SmbError> { do_parse!(i, take!(pad1) @@ -300,7 +301,7 @@ pub fn parse_smb_trans_request_record_data(i: &[u8], } pub fn parse_smb_trans_request_record<'a, 'b>(i: &'a[u8], r: &SmbRecord<'b>) - -> IResult<&'a[u8], SmbRecordTransRequest<'a>> + -> IResult<&'a[u8], SmbRecordTransRequest<'a>, SmbError> { let (rem, (params, pipe)) = parse_smb_trans_request_record_params(i)?; let mut offset = 32 + (i.len() - rem.len()); // init with SMB header @@ -516,7 +517,7 @@ pub struct SmbRequestRenameRecord { pub newname: Vec, } -named!(pub parse_smb_rename_request_record, +named!(pub parse_smb_rename_request_record<&[u8], SmbRequestRenameRecord, SmbError>, do_parse!( _wct: le_u8 >> _search_attr: le_u16 @@ -539,7 +540,7 @@ pub struct SmbRequestCreateAndXRecord<> { } pub fn parse_smb_create_andx_request_record<'a>(i: &'a[u8], r: &SmbRecord) - -> IResult<&'a[u8], SmbRequestCreateAndXRecord<>> + -> IResult<&'a[u8], SmbRequestCreateAndXRecord<>, SmbError> { do_parse!(i, _skip1: take!(6) @@ -613,7 +614,7 @@ pub struct Trans2RecordParamSetPathInfo<> { pub oldname: Vec, } -named!(pub parse_trans2_request_params_set_path_info, +named!(pub parse_trans2_request_params_set_path_info<&[u8], Trans2RecordParamSetPathInfo, SmbError>, do_parse!( loi: le_u16 >> _reserved: take!(4) diff --git a/rust/src/smb/smb_records.rs b/rust/src/smb/smb_records.rs index 3d19fe9bfd..04c971bd69 100644 --- a/rust/src/smb/smb_records.rs +++ b/rust/src/smb/smb_records.rs @@ -15,15 +15,15 @@ * 02110-1301, USA. */ +use crate::smb::error::SmbError; use nom; use nom::IResult; -use nom::error::ErrorKind; use crate::log::*; /// parse a UTF16 string that is null terminated. Normally by 2 null /// bytes, but at the end of the data it can also be a single null. /// Skip every second byte. -pub fn smb_get_unicode_string(blob: &[u8]) -> IResult<&[u8], Vec> +pub fn smb_get_unicode_string(blob: &[u8]) -> IResult<&[u8], Vec, SmbError> { SCLogDebug!("get_unicode_string: blob {} {:?}", blob.len(), blob); let mut name : Vec = Vec::new(); @@ -43,11 +43,11 @@ pub fn smb_get_unicode_string(blob: &[u8]) -> IResult<&[u8], Vec> name.push(c[0]); c = &c[2..]; } - Err(nom::Err::Error(error_position!(blob,ErrorKind::Custom(130)))) + Err(nom::Err::Error(SmbError::BadEncoding)) } // parse an ASCII string that is null terminated -named!(pub smb_get_ascii_string>, +named!(pub smb_get_ascii_string<&[u8], Vec, SmbError>, do_parse!( s: take_until_and_consume!("\x00") >> ( s.to_vec() ) -- 2.47.2