]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
smb2: improve read/write record parsing
authorVictor Julien <victor@inliniac.net>
Sat, 24 Mar 2018 09:15:52 +0000 (10:15 +0100)
committerVictor Julien <victor@inliniac.net>
Mon, 26 Mar 2018 07:05:26 +0000 (09:05 +0200)
parse_smb2_response_read()/parse_smb2_response_write() can be called on
incomplete data, so they didn't use the read/write length field to grab
the data field. Instead it just used rest(). However in some cases
SMB2 records have trailing data, which would be included in the
READ/WRITE data.

This patch addresses this by using the length field if enough data is
available.

rust/src/smb/smb2_records.rs

index ce0fac97b08e584bc58319d2ddedd00da2868c68..d068dbb5e146939079024508f732af06b2959f65 100644 (file)
@@ -15,7 +15,7 @@
  * 02110-1301, USA.
  */
 
-use nom::{rest, le_u8, le_u16, le_u32, le_u64, AsBytes};
+use nom::{rest, le_u8, le_u16, le_u32, le_u64, AsBytes, IResult};
 use smb::smb::*;
 
 #[derive(Debug,PartialEq)]
@@ -352,6 +352,7 @@ pub struct Smb2WriteRequestRecord<'a> {
     pub data: &'a[u8],
 }
 
+// can be called on incomplete records
 named!(pub parse_smb2_request_write<Smb2WriteRequestRecord>,
     do_parse!(
             skip1: take!(4)
@@ -362,7 +363,7 @@ named!(pub parse_smb2_request_write<Smb2WriteRequestRecord>,
         >>  remaining_bytes: le_u32
         >>  write_flags: le_u32
         >>  skip2: take!(4)
-        >>  data: rest
+        >>  data: apply!(parse_smb2_data, wr_len)
         >>  (Smb2WriteRequestRecord {
                 wr_len:wr_len,
                 wr_offset:wr_offset,
@@ -401,12 +402,31 @@ pub struct Smb2ReadResponseRecord<'a> {
     pub data: &'a[u8],
 }
 
+// parse read/write data. If all is available, 'take' it.
+// otherwise just return what we have. So this may return
+// partial data.
+fn parse_smb2_data<'a>(i: &'a[u8], len: u32)
+    -> IResult<&'a[u8], &'a[u8]>
+{
+    if len as usize > i.len() {
+        IResult::Done(&[], i)
+    } else {
+        do_parse!(i,
+                data: take!(len)
+            >> (data)
+        )
+    }
+}
+
+// can be called on incomplete records
 named!(pub parse_smb2_response_read<Smb2ReadResponseRecord>,
     do_parse!(
-            skip1: take!(4)
+            struct_size: le_u16
+        >>  data_offset: le_u16
         >>  rd_len: le_u32
-        >>  skip2: take!(8)
-        >>  data: rest
+        >>  rd_rem: le_u32
+        >>  _padding: take!(4)
+        >>  data: apply!(parse_smb2_data, rd_len)
         >>  (Smb2ReadResponseRecord {
                 len : rd_len,
                 data : data,