]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
rust/dcerpc: convert parser to nom7 functions
authorPierre Chifflier <chifflier@wzdftpd.net>
Wed, 19 Jan 2022 10:41:52 +0000 (11:41 +0100)
committerVictor Julien <vjulien@oisf.net>
Sun, 13 Feb 2022 20:37:32 +0000 (21:37 +0100)
rust/src/dcerpc/dcerpc.rs
rust/src/dcerpc/dcerpc_udp.rs
rust/src/dcerpc/parser.rs

index f0e1fdfe7ae8c9ba6ecf5a770b4f28b90b4f6efb..a4758366abec40b62726e915402df27a794c8dbc 100644 (file)
@@ -18,9 +18,9 @@
 use crate::applayer::*;
 use crate::core::{self, *};
 use crate::dcerpc::parser;
-use nom::error::ErrorKind;
-use nom::number::Endianness;
-use nom;
+use nom7::error::{Error, ErrorKind};
+use nom7::number::Endianness;
+use nom7::{Err, IResult, Needed};
 use std;
 use std::cmp;
 use std::ffi::CString;
@@ -575,7 +575,7 @@ impl DCERPCState {
         }
     }
 
-    pub fn search_dcerpc_record<'a>(&mut self, i: &'a[u8]) -> nom::IResult<&'a[u8], &'a[u8]> {
+    pub fn search_dcerpc_record<'a>(&mut self, i: &'a[u8]) -> IResult<&'a[u8], &'a[u8]> {
         let mut d = i;
         while d.len() >= 2 {
             if d[0] == 0x05 && d[1] == 0x00 {
@@ -583,7 +583,7 @@ impl DCERPCState {
             }
             d = &d[1..];
         }
-        Err(nom::Err::Incomplete(nom::Needed::Size(2 as usize - d.len())))
+        Err(Err::Incomplete(Needed::new(2 as usize - d.len())))
     }
 
     /// Makes a call to the nom parser for parsing DCERPC Header.
@@ -613,12 +613,12 @@ impl DCERPCState {
                 self.header = Some(header);
                 (input.len() - leftover_bytes.len()) as i32
             }
-            Err(nom::Err::Incomplete(_)) => {
+            Err(Err::Incomplete(_)) => {
                 // Insufficient data.
                 SCLogDebug!("Insufficient data while parsing DCERPC header");
                 -1
             }
-            Err(nom::Err::Error(([], ErrorKind::Eof))) => {
+            Err(Err::Error(Error{code:ErrorKind::Eof, ..})) => {
                 SCLogDebug!("EoF reached while parsing DCERPC header");
                 -1
             }
@@ -652,7 +652,7 @@ impl DCERPCState {
                 }
                 (input.len() - leftover_bytes.len()) as i32
             }
-            Err(nom::Err::Incomplete(_)) => {
+            Err(Err::Incomplete(_)) => {
                 // Insufficient data.
                 SCLogDebug!("Insufficient data while parsing DCERPC BIND CTXItem");
                 -1
@@ -692,7 +692,7 @@ impl DCERPCState {
                 // of bindctxitems)
                 (input.len() - leftover_bytes.len()) as i32 + retval * numctxitems as i32
             }
-            Err(nom::Err::Incomplete(_)) => {
+            Err(Err::Incomplete(_)) => {
                 // Insufficient data.
                 SCLogDebug!("Insufficient data while parsing DCERPC BIND header");
                 -1
@@ -727,7 +727,7 @@ impl DCERPCState {
                 }
                 (input.len() - leftover_bytes.len()) as i32
             }
-            Err(nom::Err::Incomplete(_)) => {
+            Err(Err::Incomplete(_)) => {
                 // Insufficient data.
                 SCLogDebug!("Insufficient data while parsing DCERPC BINDACK");
                 -1
@@ -877,7 +877,7 @@ impl DCERPCState {
                 );
                 parsed
             }
-            Err(nom::Err::Incomplete(_)) => {
+            Err(Err::Incomplete(_)) => {
                 // Insufficient data.
                 SCLogDebug!("Insufficient data while parsing DCERPC REQUEST");
                 -1
index b98ee827bb8984e098749263c068096c7f9d1a97..51e9a583d8ad9fbf53683bcd0e754d3ee656ecbe 100644 (file)
@@ -21,6 +21,7 @@ use crate::dcerpc::dcerpc::{
     DCERPCTransaction, DCERPC_TYPE_REQUEST, DCERPC_TYPE_RESPONSE, PFCL1_FRAG, PFCL1_LASTFRAG,
     rs_dcerpc_get_alstate_progress, ALPROTO_DCERPC, PARSER_NAME,
 };
+use nom7::Err;
 use std;
 use std::ffi::CString;
 use crate::dcerpc::parser;
@@ -189,7 +190,7 @@ impl DCERPCUDPState {
                     return AppLayerResult::err();
                 }
             }
-            Err(nom::Err::Incomplete(_)) => {
+            Err(Err::Incomplete(_)) => {
                 // Insufficient data.
                 SCLogDebug!("Insufficient data while parsing DCERPC request");
                 return AppLayerResult::err();
index 9771a28be0cb117f8adebf0a544003191e8beb10..2ff42886921849e947fc3ad17f13f48131c33216 100644 (file)
@@ -18,8 +18,12 @@ use crate::dcerpc::dcerpc::{
     BindCtxItem, DCERPCBind, DCERPCBindAck, DCERPCBindAckResult, DCERPCHdr, DCERPCRequest, Uuid,
 };
 use crate::dcerpc::dcerpc_udp::DCERPCHdrUdp;
-use nom::number::complete::{le_u16, le_u32, le_u8};
-use nom::number::Endianness;
+use nom7::bytes::streaming::take;
+use nom7::combinator::cond;
+use nom7::number::complete::{le_u16, le_u32, le_u8, u16, u32};
+use nom7::number::Endianness;
+use nom7::multi::count;
+use nom7::IResult;
 
 fn uuid_to_vec(uuid: Uuid) -> Vec<u8> {
     let mut uuidtmp = uuid;
@@ -49,216 +53,192 @@ fn assemble_uuid(uuid: Uuid) -> Vec<u8> {
     vect
 }
 
-named!(pub parse_uuid<Uuid>,
-    do_parse!(
-        time_low: take!(4)
-        >> time_mid: take!(2)
-        >> time_hi_and_version: take!(2)
-        >> clock_seq_hi_and_reserved: le_u8
-        >> clock_seq_low: le_u8
-        >> node: take!(6)
-        >> (
-             Uuid {
-                time_low: time_low.to_vec(),
-                time_mid: time_mid.to_vec(),
-                time_hi_and_version: time_hi_and_version.to_vec(),
-                clock_seq_hi_and_reserved: clock_seq_hi_and_reserved,
-                clock_seq_low: clock_seq_low,
-                node: node.to_vec(),
-            }
-        )
-    )
-);
+pub fn parse_uuid(i: &[u8]) -> IResult<&[u8], Uuid> {
+    let (i, time_low) = take(4_usize)(i)?;
+    let (i, time_mid) = take(2_usize)(i)?;
+    let (i, time_hi_and_version) = take(2_usize)(i)?;
+    let (i, clock_seq_hi_and_reserved) = le_u8(i)?;
+    let (i, clock_seq_low) = le_u8(i)?;
+    let (i, node) = take(6_usize)(i)?;
+    let uuid = Uuid {
+        time_low: time_low.to_vec(),
+        time_mid: time_mid.to_vec(),
+        time_hi_and_version: time_hi_and_version.to_vec(),
+        clock_seq_hi_and_reserved,
+        clock_seq_low,
+        node: node.to_vec(),
+    };
+    Ok((i, uuid))
+}
 
-named!(pub parse_dcerpc_udp_header<DCERPCHdrUdp>,
-    do_parse!(
-        rpc_vers: le_u8
-        >> pkt_type: le_u8
-        >> flags1: le_u8
-        >> flags2: le_u8
-        >> drep: take!(3)
-        >> endianness: value!(if drep[0] == 0 { Endianness::Big } else { Endianness::Little })
-        >> serial_hi: le_u8
-        >> objectuuid: take!(16)
-        >> interfaceuuid: take!(16)
-        >> activityuuid: take!(16)
-        >> server_boot: u32!(endianness)
-        >> if_vers: u32!(endianness)
-        >> seqnum: u32!(endianness)
-        >> opnum: u16!(endianness)
-        >> ihint: u16!(endianness)
-        >> ahint: u16!(endianness)
-        >> fraglen: u16!(endianness)
-        >> fragnum: u16!(endianness)
-        >> auth_proto: le_u8
-        >> serial_lo: le_u8
-        >> (
-             DCERPCHdrUdp {
-                rpc_vers: rpc_vers,
-                pkt_type: pkt_type,
-                flags1: flags1,
-                flags2: flags2,
-                drep: drep.to_vec(),
-                serial_hi: serial_hi,
-                objectuuid: match parse_uuid(objectuuid) {
-                    Ok((_, vect)) => assemble_uuid(vect),
-                    Err(_e) => {
-                        SCLogDebug!("{}", _e);
-                        vec![0]
-                    },
-                },
-                interfaceuuid: match parse_uuid(interfaceuuid) {
-                    Ok((_, vect)) => assemble_uuid(vect),
-                    Err(_e) => {
-                        SCLogDebug!("{}", _e);
-                        vec![0]
-                    },
-                },
-                activityuuid: match parse_uuid(activityuuid){
-                    Ok((_, vect)) => assemble_uuid(vect),
-                    Err(_e) => {
-                        SCLogDebug!("{}", _e);
-                        vec![0]
-                    },
-                },
-                server_boot: server_boot,
-                if_vers: if_vers,
-                seqnum: seqnum,
-                opnum: opnum,
-                ihint: ihint,
-                ahint: ahint,
-                fraglen: fraglen,
-                fragnum: fragnum,
-                auth_proto: auth_proto,
-                serial_lo: serial_lo,
-            }
-        )
-    )
-);
+pub fn parse_dcerpc_udp_header(i: &[u8]) -> IResult<&[u8], DCERPCHdrUdp> {
+    let (i, rpc_vers) = le_u8(i)?;
+    let (i, pkt_type) = le_u8(i)?;
+    let (i, flags1) = le_u8(i)?;
+    let (i, flags2) = le_u8(i)?;
+    let (i, drep) = take(3_usize)(i)?;
+    let endianness = if drep[0] == 0 { Endianness::Big } else { Endianness::Little };
+    let (i, serial_hi) = le_u8(i)?;
+    let (i, objectuuid) = take(16_usize)(i)?;
+    let (i, interfaceuuid) = take(16_usize)(i)?;
+    let (i, activityuuid) = take(16_usize)(i)?;
+    let (i, server_boot) = u32(endianness)(i)?;
+    let (i, if_vers) = u32(endianness)(i)?;
+    let (i, seqnum) = u32(endianness)(i)?;
+    let (i, opnum) = u16(endianness)(i)?;
+    let (i, ihint) = u16(endianness)(i)?;
+    let (i, ahint) = u16(endianness)(i)?;
+    let (i, fraglen) = u16(endianness)(i)?;
+    let (i, fragnum) = u16(endianness)(i)?;
+    let (i, auth_proto) = le_u8(i)?;
+    let (i, serial_lo) = le_u8(i)?;
+    let header = DCERPCHdrUdp {
+        rpc_vers,
+        pkt_type,
+        flags1,
+        flags2,
+        drep: drep.to_vec(),
+        serial_hi,
+        objectuuid: match parse_uuid(objectuuid) {
+            Ok((_, vect)) => assemble_uuid(vect),
+            Err(_e) => {
+                SCLogDebug!("{}", _e);
+                vec![0]
+            },
+        },
+        interfaceuuid: match parse_uuid(interfaceuuid) {
+            Ok((_, vect)) => assemble_uuid(vect),
+            Err(_e) => {
+                SCLogDebug!("{}", _e);
+                vec![0]
+            },
+        },
+        activityuuid: match parse_uuid(activityuuid){
+            Ok((_, vect)) => assemble_uuid(vect),
+            Err(_e) => {
+                SCLogDebug!("{}", _e);
+                vec![0]
+            },
+        },
+        server_boot,
+        if_vers,
+        seqnum,
+        opnum,
+        ihint,
+        ahint,
+        fraglen,
+        fragnum,
+        auth_proto,
+        serial_lo,
+    };
+    Ok((i, header))
+}
 
-named!(pub parse_dcerpc_bindack_result<DCERPCBindAckResult>,
-    do_parse!(
-        ack_result: le_u16
-        >>  ack_reason: le_u16
-        >>  transfer_syntax: take!(16)
-        >>  syntax_version: le_u32
-        >> (
-             DCERPCBindAckResult {
-                ack_result:ack_result,
-                ack_reason:ack_reason,
-                transfer_syntax:transfer_syntax.to_vec(),
-                syntax_version:syntax_version,
-            }
-        )
-    )
-);
+pub fn parse_dcerpc_bindack_result(i: &[u8]) -> IResult<&[u8], DCERPCBindAckResult> {
+    let (i, ack_result) = le_u16(i)?;
+    let (i,  ack_reason) = le_u16(i)?;
+    let (i,  transfer_syntax) = take(16_usize)(i)?;
+    let (i,  syntax_version) = le_u32(i)?;
+    let result = DCERPCBindAckResult {
+        ack_result,
+        ack_reason,
+        transfer_syntax: transfer_syntax.to_vec(),
+        syntax_version,
+    };
+    Ok((i, result))
+}
 
-named!(pub parse_dcerpc_bindack<DCERPCBindAck>,
-    do_parse!(
-        _max_xmit_frag: le_u16
-        >> _max_recv_frag: le_u16
-        >> _assoc_group: take!(4)
-        >> sec_addr_len: le_u16
-        >> take!(sec_addr_len)
-        >> cond!((sec_addr_len + 2) % 4 != 0, take!(4 - (sec_addr_len + 2) % 4))
-        >> numctxitems: le_u8
-        >> take!(3) // Padding
-        >> ctxitems: count!(parse_dcerpc_bindack_result, numctxitems as usize)
-        >> (
-             DCERPCBindAck {
-                accepted_uuid_list: Vec::new(),
-                sec_addr_len: sec_addr_len,
-                numctxitems: numctxitems,
-                ctxitems: ctxitems,
-            }
-        )
-    )
-);
+pub fn parse_dcerpc_bindack(i: &[u8]) -> IResult<&[u8], DCERPCBindAck> {
+    let (i, _max_xmit_frag) = le_u16(i)?;
+    let (i, _max_recv_frag) = le_u16(i)?;
+    let (i, _assoc_group) = take(4_usize)(i)?;
+    let (i, sec_addr_len) = le_u16(i)?;
+    let (i, _) = take(sec_addr_len)(i)?;
+    let (i, _) = cond((sec_addr_len + 2) % 4 != 0, |b| take(4 - (sec_addr_len + 2) % 4)(b))(i)?;
+    let (i, numctxitems) = le_u8(i)?;
+    let (i, _) = take(3_usize)(i)?; // Padding
+    let (i, ctxitems) = count(parse_dcerpc_bindack_result, numctxitems as usize)(i)?;
+    let result = DCERPCBindAck {
+        accepted_uuid_list: Vec::new(),
+        sec_addr_len,
+        numctxitems,
+        ctxitems,
+    };
+    Ok((i, result))
+}
 
-named_args!(pub parse_bindctx_item(endianness: Endianness) <BindCtxItem>,
-    do_parse!(
-        ctxid: u16!(endianness)
-        >> _num_trans_items: le_u8
-        >> take!(1) // Reservid bit
-        >> uuid: take!(16)
-        >> version: u16!(endianness)
-        >> versionminor: u16!(endianness)
-        >> take!(20)
-        >> (
-             BindCtxItem {
-                ctxid: ctxid,
-                // UUID parsing for TCP seems to change as per endianness
-                uuid: match parse_uuid(uuid) {
-                    Ok((_, vect)) => match endianness {
-                        Endianness::Little => assemble_uuid(vect),
-                        _ => uuid_to_vec(vect),
-                    },
-                    // Shouldn't happen
-                    Err(_e) => {vec![0]},
-                },
-                version: version,
-                versionminor: versionminor,
-            }
-        )
-    )
-);
+pub fn parse_bindctx_item(i: &[u8], endianness: Endianness) -> IResult<&[u8], BindCtxItem> {
+    let (i, ctxid) = u16(endianness)(i)?;
+    let (i, _num_trans_items) = le_u8(i)?;
+    let (i, _) = take(1_usize)(i)?; // Reservid bit
+    let (i, uuid) = take(16_usize)(i)?;
+    let (i, version) = u16(endianness)(i)?;
+    let (i, versionminor) = u16(endianness)(i)?;
+    let (i, _) = take(20_usize)(i)?;
+    let result = BindCtxItem {
+        ctxid,
+        // UUID parsing for TCP seems to change as per endianness
+        uuid: match parse_uuid(uuid) {
+            Ok((_, vect)) => match endianness {
+                Endianness::Little => assemble_uuid(vect),
+                _ => uuid_to_vec(vect),
+            },
+            // Shouldn't happen
+            Err(_e) => {vec![0]},
+        },
+        version,
+        versionminor,
+    };
+    Ok((i, result))
+}
 
-named!(pub parse_dcerpc_bind<DCERPCBind>,
-    do_parse!(
-        _max_xmit_frag: le_u16
-        >> _max_recv_frag: le_u16
-        >> _assoc_group_id: le_u32
-        >> numctxitems: le_u8
-        >> take!(3)
-        >> (
-             DCERPCBind {
-                numctxitems: numctxitems,
-                uuid_list: Vec::new(),
-            }
-        )
-    )
-);
+pub fn parse_dcerpc_bind(i: &[u8]) -> IResult<&[u8], DCERPCBind> {
+    let (i, _max_xmit_frag) = le_u16(i)?;
+    let (i, _max_recv_frag) = le_u16(i)?;
+    let (i, _assoc_group_id) = le_u32(i)?;
+    let (i, numctxitems) = le_u8(i)?;
+    let (i, _) = take(3_usize)(i)?;
+    let result = DCERPCBind {
+        numctxitems,
+        uuid_list: Vec::new(),
+    };
+    Ok((i, result))
+}
 
-named!(pub parse_dcerpc_header<DCERPCHdr>,
-    do_parse!(
-        rpc_vers: le_u8
-        >> rpc_vers_minor: le_u8
-        >> hdrtype: le_u8
-        >> pfc_flags: le_u8
-        >> packed_drep: take!(4)
-        >> endianness: value!(if packed_drep[0] & 0x10 == 0 { Endianness::Big } else { Endianness::Little })
-        >> frag_length: u16!(endianness)
-        >> auth_length: u16!(endianness)
-        >> call_id: u32!(endianness)
-        >> (
-             DCERPCHdr {
-                rpc_vers: rpc_vers,
-                rpc_vers_minor: rpc_vers_minor,
-                hdrtype: hdrtype,
-                pfc_flags: pfc_flags,
-                packed_drep: packed_drep.to_vec(),
-                frag_length: frag_length,
-                auth_length: auth_length,
-                call_id: call_id,
-            }
-        )
-    )
-);
+pub fn parse_dcerpc_header(i: &[u8]) -> IResult<&[u8], DCERPCHdr> {
+    let (i, rpc_vers) = le_u8(i)?;
+    let (i, rpc_vers_minor) = le_u8(i)?;
+    let (i, hdrtype) = le_u8(i)?;
+    let (i, pfc_flags) = le_u8(i)?;
+    let (i, packed_drep) = take(4_usize)(i)?;
+    let endianness = if packed_drep[0] & 0x10 == 0 { Endianness::Big } else { Endianness::Little };
+    let (i, frag_length) = u16(endianness)(i)?;
+    let (i, auth_length) = u16(endianness)(i)?;
+    let (i, call_id) = u32(endianness)(i)?;
+    let header = DCERPCHdr {
+        rpc_vers,
+        rpc_vers_minor,
+        hdrtype,
+        pfc_flags,
+        packed_drep: packed_drep.to_vec(),
+        frag_length,
+        auth_length,
+        call_id,
+    };
+    Ok((i, header))
+}
 
-named_args!(pub parse_dcerpc_request(endianness: Endianness) <DCERPCRequest>,
-    do_parse!(
-        _pad: take!(4)
-        >> ctxid: u16!(endianness)
-        >> opnum: u16!(endianness)
-        >> (
-             DCERPCRequest {
-                ctxid: ctxid,
-                opnum: opnum,
-                first_request_seen: 1,
-            }
-        )
-    )
-);
+pub fn parse_dcerpc_request(i: &[u8], endianness: Endianness) -> IResult<&[u8], DCERPCRequest> {
+    let (i, _pad) = take(4_usize)(i)?;
+    let (i, ctxid) = u16(endianness)(i)?;
+    let (i, opnum) = u16(endianness)(i)?;
+    let req = DCERPCRequest {
+        ctxid,
+        opnum,
+        first_request_seen: 1,
+    };
+    Ok((i, req))
+}
 
 #[cfg(test)]
 mod tests {