rust/ike: convert parser to nom7 functions and upgrade dependency

pull/6971/head
Pierre Chifflier 4 years ago committed by Victor Julien
parent 3493537ec3
commit fa63945bdc

@ -41,7 +41,7 @@ sawp = "~0.5.0"
der-parser = "~4.0.2" der-parser = "~4.0.2"
kerberos-parser = "~0.5.0" kerberos-parser = "~0.5.0"
ntp-parser = "~0.4.0" ntp-parser = "~0.4.0"
ipsec-parser = "~0.5.0" ipsec-parser = "~0.7.0"
snmp-parser = "~0.6.0" snmp-parser = "~0.6.0"
tls-parser = "~0.9.4" tls-parser = "~0.9.4"
x509-parser = "~0.6.5" x509-parser = "~0.6.5"

@ -26,7 +26,7 @@ use crate::core::{self, *};
use crate::ike::ikev1::{handle_ikev1, IkeV1Header, Ikev1Container}; use crate::ike::ikev1::{handle_ikev1, IkeV1Header, Ikev1Container};
use crate::ike::ikev2::{handle_ikev2, Ikev2Container}; use crate::ike::ikev2::{handle_ikev2, Ikev2Container};
use crate::ike::parser::*; use crate::ike::parser::*;
use nom; use nom7::Err;
use std; use std;
use std::collections::HashSet; use std::collections::HashSet;
use std::ffi::CString; 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 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"); SCLogDebug!("Insufficient data while parsing IKE");
return AppLayerResult::err(); return AppLayerResult::err();
} }

@ -22,7 +22,7 @@ use crate::common::to_hex;
use crate::core::Direction; use crate::core::Direction;
use crate::ike::ike::{IKEState, IkeEvent}; use crate::ike::ike::{IKEState, IkeEvent};
use crate::ike::parser::*; use crate::ike::parser::*;
use nom; use nom7::Err;
use std; use std;
use std::collections::HashSet; use std::collections::HashSet;
@ -153,7 +153,7 @@ pub fn handle_ikev1(
state.set_event(IkeEvent::PayloadExtraData); state.set_event(IkeEvent::PayloadExtraData);
} }
} }
Err(nom::Err::Incomplete(_)) => { Err(Err::Incomplete(_)) => {
SCLogDebug!("Insufficient data while parsing IKEV1"); SCLogDebug!("Insufficient data while parsing IKEV1");
return AppLayerResult::err(); return AppLayerResult::err();
} }

@ -17,8 +17,11 @@
use crate::common::to_hex; use crate::common::to_hex;
use core::fmt; use core::fmt;
use nom::number::streaming::{be_u16, be_u32, be_u64, be_u8}; use nom7::bytes::streaming::take;
use nom::*; 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; use std::collections::HashSet;
// Generic ISAKMP "Container" structs // Generic ISAKMP "Container" structs
@ -248,107 +251,87 @@ pub struct SaAttribute {
pub hex_value: Option<String>, pub hex_value: Option<String>,
} }
named! {pub parse_isakmp_header<IsakmpHeader>, pub fn parse_isakmp_header(i: &[u8]) -> IResult<&[u8], IsakmpHeader> {
do_parse!( let (i, init_spi) = be_u64(i)?;
init_spi: be_u64 >> let (i, resp_spi) = be_u64(i)?;
resp_spi: be_u64 >> let (i, next_payload) = be_u8(i)?;
np: be_u8 >> let (i, vers_byte) = be_u8(i)?;
vers: bits!( let vers = (vers_byte >> 4, vers_byte & 0b1111);
tuple!(take_bits!(4u8),take_bits!(4u8)) let (i, exch_type) = be_u8(i)?;
) >> let (i, flags) = be_u8(i)?;
ex: be_u8 >> let (i, msg_id) = be_u32(i)?;
flags: be_u8 >> let (i, length) = be_u32(i)?;
id: be_u32 >> let hdr =
l: be_u32 >> IsakmpHeader {
( init_spi,
IsakmpHeader { resp_spi,
init_spi, next_payload,
resp_spi, maj_ver: vers.0,
next_payload: np, min_ver: vers.1,
maj_ver: vers.0, exch_type,
min_ver: vers.1, flags,
exch_type: ex, msg_id,
flags, length,
msg_id: id, };
length: l, Ok((i, hdr))
}
)
)
} }
pub fn parse_security_association(i: &[u8]) -> IResult<&[u8], SecurityAssociationPayload> { pub fn parse_security_association(i: &[u8]) -> IResult<&[u8], SecurityAssociationPayload> {
do_parse!( let start_i = i;
i, let (i, domain_of_interpretation) = be_u32(i)?;
domain_of_interpretation: be_u32 let (i, situation) = cond(domain_of_interpretation == 1, take(4_usize))(i)?;
>> situation: cond!(domain_of_interpretation == 1, take!(4)) let (i, data) = cond(
>> data: cond!( domain_of_interpretation == 1 && start_i.len() >= 8,
domain_of_interpretation == 1 && i.len() >= 8, |b| take(start_i.len() - 8)(b)
take!(i.len() - 8) )(i)?;
) Ok((i, SecurityAssociationPayload {
>> (SecurityAssociationPayload { domain_of_interpretation,
domain_of_interpretation, situation,
situation, data
data }))
})
)
} }
pub fn parse_key_exchange(i: &[u8], length: u16) -> IResult<&[u8], KeyExchangePayload> { pub fn parse_key_exchange(i: &[u8], length: u16) -> IResult<&[u8], KeyExchangePayload> {
do_parse!( let (i, key_exchange_data) = take(length as usize)(i)?;
i, Ok((i, KeyExchangePayload { key_exchange_data }))
key_exchange_data: take!(length) >> (KeyExchangePayload { key_exchange_data })
)
} }
pub fn parse_proposal(i: &[u8]) -> IResult<&[u8], ProposalPayload> { pub fn parse_proposal(i: &[u8]) -> IResult<&[u8], ProposalPayload> {
do_parse!( let start_i = i;
i, let (i, proposal_number) = be_u8(i)?;
proposal_number: be_u8 let (i, proposal_type) = be_u8(i)?;
>> proposal_type: be_u8 let (i, spi_size) = be_u8(i)?;
>> spi_size: be_u8 let (i, number_transforms) = be_u8(i)?;
>> number_transforms: be_u8 let (i, spi) = take(spi_size as usize)(i)?;
>> spi: take!(spi_size) let (i, payload_data) = cond(
>> payload_data: (start_i.len() as i16 - 4) - spi_size as i16 >= 0,
cond!( |b| take((start_i.len() - 4) - spi_size as usize)(b)
(i.len() as i16 - 4) - spi_size as i16 >= 0, )(i)?;
take!((i.len() as u16 - 4) - spi_size as u16) let payload = ProposalPayload {
) proposal_number,
>> (ProposalPayload { proposal_type,
proposal_number, spi_size,
proposal_type, number_transforms,
spi_size, spi,
number_transforms, data: payload_data.unwrap_or_default(),
spi, };
data: if let Some(_data) = payload_data { Ok((i, payload))
_data
} else {
b""
}
})
)
} }
pub fn parse_transform(i: &[u8], length: u16) -> IResult<&[u8], TransformPayload> { pub fn parse_transform(i: &[u8], length: u16) -> IResult<&[u8], TransformPayload> {
do_parse!( let (i, transform_number) = be_u8(i)?;
i, let (i, transform_type) = be_u8(i)?;
transform_number: be_u8 let (i, _) = be_u16(i)?;
>> transform_type: be_u8 let (i, payload_data) = cond(length >= 4, |b| take(length - 4)(b))(i)?;
>> be_u16 Ok((i, TransformPayload {
>> payload_data: cond!(length >= 4, take!(length - 4)) transform_number,
>> (TransformPayload { transform_type,
transform_number, sa_attributes: payload_data.unwrap_or_default(),
transform_type, }))
sa_attributes: if let Some(_data) = payload_data {
_data
} else {
b""
}
})
)
} }
pub fn parse_vendor_id(i: &[u8], length: u16) -> IResult<&[u8], VendorPayload> { 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 { 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>>, pub fn parse_sa_attribute(i: &[u8]) -> IResult<&[u8], Vec<SaAttribute>> {
many0!( fn parse_attribute(i: &[u8]) -> IResult<&[u8], SaAttribute> {
complete!( let (i, b) = be_u16(i)?;
do_parse!( let format = (
format: bits!(tuple!(take_bits!(1u8),take_bits!(15u16))) >> (b >> 15) as u8,
attribute_length_or_value: be_u16 >> // depends on format bit: 1 -> value | 0 -> number of following bytes b & 0x7f_ff
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)) >> 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
SaAttribute { let (i, variable_attribute_value) = cond(format.0 == 0 && attribute_length_or_value != 4, take(attribute_length_or_value))(i)?;
attribute_format: format.0, let attr = SaAttribute {
attribute_type: get_attribute_type(format.1), attribute_format: format.0,
attribute_value : match format.1 { attribute_type: get_attribute_type(format.1),
1 => get_encryption_algorithm(attribute_length_or_value), attribute_value : match format.1 {
2 => get_hash_algorithm(attribute_length_or_value), 1 => get_encryption_algorithm(attribute_length_or_value),
3 => get_authentication_method(attribute_length_or_value), 2 => get_hash_algorithm(attribute_length_or_value),
4 => get_group_description(attribute_length_or_value), 3 => get_authentication_method(attribute_length_or_value),
11 => match attribute_length_or_value { 4 => get_group_description(attribute_length_or_value),
1 => AttributeValue::LifeTypeSeconds, 11 => match attribute_length_or_value {
2 => AttributeValue::LifeTypeKilobytes, 1 => AttributeValue::LifeTypeSeconds,
_ => AttributeValue::Unknown 2 => AttributeValue::LifeTypeKilobytes,
} _ => AttributeValue::Unknown
_ => AttributeValue::Unknown }
}, _ => AttributeValue::Unknown
numeric_value: match format.0 { },
1 => Some(attribute_length_or_value as u32), numeric_value: match format.0 {
0 => { 1 => Some(attribute_length_or_value as u32),
numeric_variable_value 0 => {
}, numeric_variable_value
_ => None, },
}, _ => None,
hex_value: match format.0 { },
0 => { hex_value: match format.0 {
variable_attribute_value.map(|_variable_attribute_value| to_hex(_variable_attribute_value)) 0 => {
} variable_attribute_value.map(|_variable_attribute_value| to_hex(_variable_attribute_value))
_ => None, }
} _ => None,
} }
) };
) Ok((i, attr))
) }
) many0(complete(parse_attribute))(i)
} }
pub fn parse_nonce(i: &[u8], length: u16) -> IResult<&[u8], NoncePayload> { pub fn parse_nonce(i: &[u8], length: u16) -> IResult<&[u8], NoncePayload> {
map!(i, take!(length), |v| NoncePayload { nonce_data: v }) map(take(length), |v| NoncePayload { nonce_data: v })(i)
} }
named! { pub parse_ikev1_payload_list<&[u8], Vec<IsakmpPayload>>, pub fn parse_ikev1_payload_list(i: &[u8]) -> IResult<&[u8], Vec<IsakmpPayload>> {
many0!( fn parse_payload(i: &[u8]) -> IResult<&[u8], IsakmpPayload> {
complete!( let (i, next_payload) = be_u8(i)?;
do_parse!( let (i, reserved) = be_u8(i)?;
next_payload: be_u8 >> let (i, payload_length) = be_u16(i)?;
reserved: be_u8 >> let (i, payload_data) = cond(payload_length >= 4, |b| take(payload_length - 4)(b))(i)?;
payload_length: be_u16 >> Ok((i, IsakmpPayload {
payload_data: cond!(payload_length >= 4, take!(payload_length - 4)) >> payload_header: IsakmpPayloadHeader {
( next_payload,
IsakmpPayload { reserved,
payload_header: IsakmpPayloadHeader { payload_length
next_payload, },
reserved, data: payload_data.unwrap_or_default(),
payload_length }))
}, }
data: if let Some(_data) = payload_data { _data } else { b"" } many0(complete(parse_payload))(i)
}
)
)
)
)
} }
#[derive(FromPrimitive, Debug)] #[derive(FromPrimitive, Debug)]
@ -658,7 +636,7 @@ fn parse_proposal_payload<'a>(
} }
Ok(()) Ok(())
} }
Err(nom::Err::Incomplete(_)) => { Err(Err::Incomplete(_)) => {
SCLogDebug!("Incomplete data parsing payload list"); SCLogDebug!("Incomplete data parsing payload list");
Err(()) Err(())
} }
@ -668,7 +646,7 @@ fn parse_proposal_payload<'a>(
} }
} }
} }
Err(nom::Err::Incomplete(_)) => { Err(Err::Incomplete(_)) => {
SCLogDebug!("Incomplete data"); SCLogDebug!("Incomplete data");
Err(()) Err(())
} }
@ -708,7 +686,7 @@ fn parse_security_association_payload<'a>(
cur_payload_type = isakmp_payload.payload_header.next_payload; cur_payload_type = isakmp_payload.payload_header.next_payload;
} }
} }
Err(nom::Err::Incomplete(_)) => { Err(Err::Incomplete(_)) => {
SCLogDebug!("Incomplete data parsing payload list"); SCLogDebug!("Incomplete data parsing payload list");
return Err(()); return Err(());
} }
@ -721,7 +699,7 @@ fn parse_security_association_payload<'a>(
} }
Ok(()) Ok(())
} }
Err(nom::Err::Incomplete(_)) => { Err(Err::Incomplete(_)) => {
SCLogDebug!("Incomplete data"); SCLogDebug!("Incomplete data");
Err(()) Err(())
} }

Loading…
Cancel
Save