]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
rust/ike: convert parser to nom7 functions and upgrade dependency
authorPierre Chifflier <chifflier@wzdftpd.net>
Wed, 12 Jan 2022 13:12:26 +0000 (14:12 +0100)
committerVictor Julien <vjulien@oisf.net>
Thu, 10 Feb 2022 11:39:04 +0000 (12:39 +0100)
rust/Cargo.toml.in
rust/src/ike/ike.rs
rust/src/ike/ikev1.rs
rust/src/ike/parser.rs

index 7dff99e4304e557171c926e57da5924f009a493a..1e407bdddc72236a266cef49916ea06fcb249a08 100644 (file)
@@ -41,7 +41,7 @@ sawp = "~0.5.0"
 der-parser = "~4.0.2"
 kerberos-parser = "~0.5.0"
 ntp-parser = "~0.4.0"
-ipsec-parser = "~0.5.0"
+ipsec-parser = "~0.7.0"
 snmp-parser = "~0.6.0"
 tls-parser = "~0.9.4"
 x509-parser = "~0.6.5"
index eebb847b659327657adc86ae13e3c9c4cae09764..cb7677ad36fb47e66318464dd306e606e7463aa2 100644 (file)
@@ -26,7 +26,7 @@ use crate::core::{self, *};
 use crate::ike::ikev1::{handle_ikev1, IkeV1Header, Ikev1Container};
 use crate::ike::ikev2::{handle_ikev2, Ikev2Container};
 use crate::ike::parser::*;
-use nom;
+use nom7::Err;
 use std;
 use std::collections::HashSet;
 use std::ffi::CString;
@@ -215,7 +215,7 @@ impl IKEState {
                 }
                 return AppLayerResult::ok(); // todo either remove outer loop or check header length-field if we have completely read everything
             }
-            Err(nom::Err::Incomplete(_)) => {
+            Err(Err::Incomplete(_)) => {
                 SCLogDebug!("Insufficient data while parsing IKE");
                 return AppLayerResult::err();
             }
index 02aa5b0cb19793ece2a302eafff2cad2478b3f79..7d76ed0e8714a31d8935deab424841749aa50d08 100644 (file)
@@ -22,7 +22,7 @@ use crate::common::to_hex;
 use crate::core::Direction;
 use crate::ike::ike::{IKEState, IkeEvent};
 use crate::ike::parser::*;
-use nom;
+use nom7::Err;
 use std;
 use std::collections::HashSet;
 
@@ -153,7 +153,7 @@ pub fn handle_ikev1(
                     state.set_event(IkeEvent::PayloadExtraData);
                 }
             }
-            Err(nom::Err::Incomplete(_)) => {
+            Err(Err::Incomplete(_)) => {
                 SCLogDebug!("Insufficient data while parsing IKEV1");
                 return AppLayerResult::err();
             }
index f9cfa0831a2e75d61b75e9c9f7f57b2aabee6c10..cc79b4ecb8583b2a66e5f7d002fc6718ca416ec6 100644 (file)
 
 use crate::common::to_hex;
 use core::fmt;
-use nom::number::streaming::{be_u16, be_u32, be_u64, be_u8};
-use nom::*;
+use nom7::bytes::streaming::take;
+use nom7::combinator::{complete, cond, map};
+use nom7::multi::many0;
+use nom7::number::streaming::{be_u16, be_u32, be_u64, be_u8};
+use nom7::{Err, IResult};
 use std::collections::HashSet;
 
 // Generic ISAKMP "Container" structs
@@ -248,107 +251,87 @@ pub struct SaAttribute {
     pub hex_value: Option<String>,
 }
 
-named! {pub parse_isakmp_header<IsakmpHeader>,
-    do_parse!(
-        init_spi: be_u64 >>
-        resp_spi: be_u64 >>
-        np:       be_u8 >>
-        vers: bits!(
-            tuple!(take_bits!(4u8),take_bits!(4u8))
-        ) >>
-        ex:       be_u8 >>
-        flags:    be_u8 >>
-        id:       be_u32 >>
-        l:        be_u32 >>
-        (
-            IsakmpHeader {
-                init_spi,
-                resp_spi,
-                next_payload: np,
-                maj_ver: vers.0,
-                min_ver: vers.1,
-                exch_type: ex,
-                flags,
-                msg_id: id,
-                length: l,
-            }
-        )
-    )
+pub fn parse_isakmp_header(i: &[u8]) -> IResult<&[u8], IsakmpHeader> {
+    let (i, init_spi) = be_u64(i)?;
+    let (i, resp_spi) = be_u64(i)?;
+    let (i, next_payload) = be_u8(i)?;
+    let (i, vers_byte) = be_u8(i)?;
+    let vers = (vers_byte >> 4, vers_byte & 0b1111);
+    let (i, exch_type) = be_u8(i)?;
+    let (i, flags) = be_u8(i)?;
+    let (i, msg_id) = be_u32(i)?;
+    let (i, length) = be_u32(i)?;
+    let hdr =
+        IsakmpHeader {
+            init_spi,
+            resp_spi,
+            next_payload,
+            maj_ver: vers.0,
+            min_ver: vers.1,
+            exch_type,
+            flags,
+            msg_id,
+            length,
+        };
+    Ok((i, hdr))
 }
 
 pub fn parse_security_association(i: &[u8]) -> IResult<&[u8], SecurityAssociationPayload> {
-    do_parse!(
-        i,
-        domain_of_interpretation: be_u32
-            >> situation: cond!(domain_of_interpretation == 1, take!(4))
-            >> data: cond!(
-                domain_of_interpretation == 1 && i.len() >= 8,
-                take!(i.len() - 8)
-            )
-            >> (SecurityAssociationPayload {
-                domain_of_interpretation,
-                situation,
-                data
-            })
-    )
+    let start_i = i;
+    let (i, domain_of_interpretation) = be_u32(i)?;
+    let (i, situation) = cond(domain_of_interpretation == 1, take(4_usize))(i)?;
+    let (i, data) = cond(
+        domain_of_interpretation == 1 && start_i.len() >= 8,
+        |b| take(start_i.len() - 8)(b)
+        )(i)?;
+    Ok((i, SecurityAssociationPayload {
+        domain_of_interpretation,
+        situation,
+        data
+    }))
 }
 
 pub fn parse_key_exchange(i: &[u8], length: u16) -> IResult<&[u8], KeyExchangePayload> {
-    do_parse!(
-        i,
-        key_exchange_data: take!(length) >> (KeyExchangePayload { key_exchange_data })
-    )
+    let (i, key_exchange_data) = take(length as usize)(i)?;
+    Ok((i, KeyExchangePayload { key_exchange_data }))
 }
 
 pub fn parse_proposal(i: &[u8]) -> IResult<&[u8], ProposalPayload> {
-    do_parse!(
-        i,
-        proposal_number: be_u8
-            >> proposal_type: be_u8
-            >> spi_size: be_u8
-            >> number_transforms: be_u8
-            >> spi: take!(spi_size)
-            >> payload_data:
-                cond!(
-                    (i.len() as i16 - 4) - spi_size as i16 >= 0,
-                    take!((i.len() as u16 - 4) - spi_size as u16)
-                )
-            >> (ProposalPayload {
-                proposal_number,
-                proposal_type,
-                spi_size,
-                number_transforms,
-                spi,
-                data: if let Some(_data) = payload_data {
-                    _data
-                } else {
-                    b""
-                }
-            })
-    )
+    let start_i = i;
+    let (i, proposal_number) = be_u8(i)?;
+    let (i, proposal_type) = be_u8(i)?;
+    let (i, spi_size) = be_u8(i)?;
+    let (i, number_transforms) = be_u8(i)?;
+    let (i, spi) = take(spi_size as usize)(i)?;
+    let (i, payload_data) = cond(
+        (start_i.len() as i16 - 4) - spi_size as i16 >= 0,
+        |b| take((start_i.len() - 4) - spi_size as usize)(b)
+        )(i)?;
+    let payload = ProposalPayload {
+        proposal_number,
+        proposal_type,
+        spi_size,
+        number_transforms,
+        spi,
+        data: payload_data.unwrap_or_default(),
+    };
+    Ok((i, payload))
 }
 
 pub fn parse_transform(i: &[u8], length: u16) -> IResult<&[u8], TransformPayload> {
-    do_parse!(
-        i,
-        transform_number: be_u8
-            >> transform_type: be_u8
-            >> be_u16
-            >> payload_data: cond!(length >= 4, take!(length - 4))
-            >> (TransformPayload {
-                transform_number,
-                transform_type,
-                sa_attributes: if let Some(_data) = payload_data {
-                    _data
-                } else {
-                    b""
-                }
-            })
-    )
+    let (i, transform_number) = be_u8(i)?;
+    let (i, transform_type) = be_u8(i)?;
+    let (i, _) = be_u16(i)?;
+    let (i, payload_data) = cond(length >= 4, |b| take(length - 4)(b))(i)?;
+    Ok((i, TransformPayload {
+        transform_number,
+        transform_type,
+        sa_attributes: payload_data.unwrap_or_default(),
+    }))
 }
 
 pub fn parse_vendor_id(i: &[u8], length: u16) -> IResult<&[u8], VendorPayload> {
-    map!(i, take!(length), |v| VendorPayload { vendor_id: v })
+    map(take(length), |v| VendorPayload { vendor_id: v })(i)
 }
 
 fn get_attribute_type(v: u16) -> AttributeType {
@@ -452,75 +435,70 @@ fn get_group_description(v: u16) -> AttributeValue {
     }
 }
 
-named! { pub parse_sa_attribute<&[u8], Vec<SaAttribute>>,
-    many0!(
-        complete!(
-            do_parse!(
-                format: bits!(tuple!(take_bits!(1u8),take_bits!(15u16))) >>
-                attribute_length_or_value: be_u16 >>  // depends on format bit: 1 -> value | 0 -> number of following bytes
-                numeric_variable_value: cond!(format.0 == 0 && attribute_length_or_value == 4, be_u32) >>  // interpret as number
-                variable_attribute_value: cond!(format.0 == 0 && attribute_length_or_value != 4, take!(attribute_length_or_value)) >>
-                (
-                    SaAttribute {
-                        attribute_format: format.0,
-                        attribute_type: get_attribute_type(format.1),
-                        attribute_value : match format.1 {
-                            1 => get_encryption_algorithm(attribute_length_or_value),
-                            2 => get_hash_algorithm(attribute_length_or_value),
-                            3 => get_authentication_method(attribute_length_or_value),
-                            4 => get_group_description(attribute_length_or_value),
-                            11 => match attribute_length_or_value {
-                                1 => AttributeValue::LifeTypeSeconds,
-                                2 => AttributeValue::LifeTypeKilobytes,
-                                _ => AttributeValue::Unknown
-                            }
-                            _ => AttributeValue::Unknown
-                        },
-                        numeric_value: match format.0 {
-                            1 => Some(attribute_length_or_value as u32),
-                            0 => {
-                                numeric_variable_value
-                            },
-                            _ => None,
-                        },
-                        hex_value: match format.0 {
-                            0 => {
-                                variable_attribute_value.map(|_variable_attribute_value| to_hex(_variable_attribute_value))
-                            }
-                            _ => None,
-                        }
-                    }
-                )
-            )
-        )
-    )
+pub fn parse_sa_attribute(i: &[u8]) -> IResult<&[u8], Vec<SaAttribute>> {
+    fn parse_attribute(i: &[u8]) -> IResult<&[u8], SaAttribute> {
+        let (i, b) = be_u16(i)?;
+        let format = (
+            (b >> 15) as u8,
+            b & 0x7f_ff
+            );
+        let (i, attribute_length_or_value) = be_u16(i)?; // depends on format bit) = 1 -> value | 0 -> number of following bytes
+        let (i, numeric_variable_value) = cond(format.0 == 0 && attribute_length_or_value == 4, be_u32) (i)?; // interpret as number
+        let (i, variable_attribute_value) = cond(format.0 == 0 && attribute_length_or_value != 4, take(attribute_length_or_value))(i)?;
+        let attr = SaAttribute {
+            attribute_format: format.0,
+            attribute_type: get_attribute_type(format.1),
+            attribute_value : match format.1 {
+                1 => get_encryption_algorithm(attribute_length_or_value),
+                2 => get_hash_algorithm(attribute_length_or_value),
+                3 => get_authentication_method(attribute_length_or_value),
+                4 => get_group_description(attribute_length_or_value),
+                11 => match attribute_length_or_value {
+                    1 => AttributeValue::LifeTypeSeconds,
+                    2 => AttributeValue::LifeTypeKilobytes,
+                    _ => AttributeValue::Unknown
+                }
+                _ => AttributeValue::Unknown
+            },
+            numeric_value: match format.0 {
+                1 => Some(attribute_length_or_value as u32),
+                0 => {
+                    numeric_variable_value
+                },
+                _ => None,
+            },
+            hex_value: match format.0 {
+                0 => {
+                    variable_attribute_value.map(|_variable_attribute_value| to_hex(_variable_attribute_value))
+                }
+                _ => None,
+            }
+        };
+        Ok((i, attr))
+    }
+    many0(complete(parse_attribute))(i)
 }
 
 pub fn parse_nonce(i: &[u8], length: u16) -> IResult<&[u8], NoncePayload> {
-    map!(i, take!(length), |v| NoncePayload { nonce_data: v })
-}
-
-named! { pub parse_ikev1_payload_list<&[u8], Vec<IsakmpPayload>>,
-    many0!(
-        complete!(
-            do_parse!(
-                next_payload: be_u8 >>
-                reserved: be_u8 >>
-                payload_length: be_u16 >>
-                payload_data: cond!(payload_length >= 4, take!(payload_length - 4)) >>
-                (
-                    IsakmpPayload {
-                        payload_header: IsakmpPayloadHeader {
-                            next_payload,
-                            reserved,
-                            payload_length
-                        },
-                        data: if let Some(_data) = payload_data { _data } else { b"" }
-                    }
-                )
-            )
-        )
-    )
+    map(take(length), |v| NoncePayload { nonce_data: v })(i)
+}
+
+pub fn parse_ikev1_payload_list(i: &[u8]) -> IResult<&[u8], Vec<IsakmpPayload>> {
+    fn parse_payload(i: &[u8]) -> IResult<&[u8], IsakmpPayload> {
+        let (i, next_payload) = be_u8(i)?;
+        let (i, reserved) = be_u8(i)?;
+        let (i, payload_length) = be_u16(i)?;
+        let (i, payload_data) = cond(payload_length >= 4, |b| take(payload_length - 4)(b))(i)?;
+        Ok((i, IsakmpPayload {
+            payload_header: IsakmpPayloadHeader {
+                next_payload,
+                reserved,
+                payload_length
+            },
+            data: payload_data.unwrap_or_default(),
+        }))
+    }
+    many0(complete(parse_payload))(i)
 }
 
 #[derive(FromPrimitive, Debug)]
@@ -658,7 +636,7 @@ fn parse_proposal_payload<'a>(
                     }
                     Ok(())
                 }
-                Err(nom::Err::Incomplete(_)) => {
+                Err(Err::Incomplete(_)) => {
                     SCLogDebug!("Incomplete data parsing payload list");
                     Err(())
                 }
@@ -668,7 +646,7 @@ fn parse_proposal_payload<'a>(
                 }
             }
         }
-        Err(nom::Err::Incomplete(_)) => {
+        Err(Err::Incomplete(_)) => {
             SCLogDebug!("Incomplete data");
             Err(())
         }
@@ -708,7 +686,7 @@ fn parse_security_association_payload<'a>(
                                 cur_payload_type = isakmp_payload.payload_header.next_payload;
                             }
                         }
-                        Err(nom::Err::Incomplete(_)) => {
+                        Err(Err::Incomplete(_)) => {
                             SCLogDebug!("Incomplete data parsing payload list");
                             return Err(());
                         }
@@ -721,7 +699,7 @@ fn parse_security_association_payload<'a>(
             }
             Ok(())
         }
-        Err(nom::Err::Incomplete(_)) => {
+        Err(Err::Incomplete(_)) => {
             SCLogDebug!("Incomplete data");
             Err(())
         }