]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
rust/smb: add custom error handling
authorPierre Chifflier <chifflier@wzdftpd.net>
Thu, 31 Oct 2019 07:21:12 +0000 (08:21 +0100)
committerVictor Julien <victor@inliniac.net>
Mon, 2 Mar 2020 16:16:42 +0000 (17:16 +0100)
rust/src/smb/dcerpc_records.rs
rust/src/smb/error.rs [new file with mode: 0644]
rust/src/smb/mod.rs
rust/src/smb/smb1_records.rs
rust/src/smb/smb_records.rs

index 3d0e4e1a8ff2ea7a7f9eaa35897046dfbcc65797..fa47a0cfda83063ce45bb44784300751cfa18dfa 100644 (file)
@@ -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 (file)
index 0000000..ab9c863
--- /dev/null
@@ -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 <chifflier@wzdftpd.net>
+use nom::error::{ErrorKind, ParseError};
+
+#[derive(Debug)]
+pub enum SmbError {
+    BadEncoding,
+    RecordTooSmall,
+    NomError(ErrorKind),
+}
+
+impl<I> ParseError<I> 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)
+    }
+}
index 65e1577ffc2ff375a424cb2a185c1aa6312eca66..2d4d5e9b7c5a08a9cd2e4f959fd2f0a25eb367c6 100644 (file)
@@ -15,6 +15,7 @@
  * 02110-1301, USA.
  */
 
+pub mod error;
 pub mod smb_records;
 pub mod smb1_records;
 pub mod smb2_records;
index 83271a256b92a8d37d9927de0714c17a01e3ecba..148631fbf8fd84a6b1408c045e9a873bd1d28ca7 100644 (file)
@@ -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<u8>>
+fn smb_get_unicode_string_with_offset(i: &[u8], offset: usize) -> IResult<&[u8], Vec<u8>, 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<u8>> {
+pub fn smb1_get_string<'a>(i: &'a[u8], r: &SmbRecord, offset: usize) -> IResult<&'a[u8], Vec<u8>, 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<SmbPipeProtocolRecord>,
+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<SmbPipeProtocolRecord>)>,
+named!(pub parse_smb_trans_request_record_params<&[u8], (SmbRecordTransRequestParams, Option<SmbPipeProtocolRecord>), 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<u8>,
 }
 
-named!(pub parse_smb_rename_request_record<SmbRequestRenameRecord>,
+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<u8>,
 }
 
-named!(pub parse_trans2_request_params_set_path_info<Trans2RecordParamSetPathInfo>,
+named!(pub parse_trans2_request_params_set_path_info<&[u8], Trans2RecordParamSetPathInfo, SmbError>,
     do_parse!(
             loi: le_u16
         >>  _reserved: take!(4)
index 3d19fe9bfd48130b1bb533697a31d47642a90595..04c971bd690d0ef60ee4e55ef0f787f7cd93ee69 100644 (file)
  * 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<u8>>
+pub fn smb_get_unicode_string(blob: &[u8]) -> IResult<&[u8], Vec<u8>, SmbError>
 {
     SCLogDebug!("get_unicode_string: blob {} {:?}", blob.len(), blob);
     let mut name : Vec<u8> = Vec::new();
@@ -43,11 +43,11 @@ pub fn smb_get_unicode_string(blob: &[u8]) -> IResult<&[u8], Vec<u8>>
         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<Vec<u8>>,
+named!(pub smb_get_ascii_string<&[u8], Vec<u8>, SmbError>,
     do_parse!(
             s: take_until_and_consume!("\x00")
         >> ( s.to_vec() )