diff --git a/Cargo.toml b/Cargo.toml index 8e96876..1f5f8bf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,7 @@ homepage = "https://github.com/rusticata/ipsec-parser" repository = "https://github.com/rusticata/ipsec-parser.git" documentation = "https://docs.rs/ipsec-parser" name = "ipsec-parser" -version = "0.3.0" +version = "0.4.0" authors = ["Pierre Chifflier "] categories = ["parsing"] @@ -20,7 +20,7 @@ include = [ ] [dependencies] -nom = "4.0" +nom = "4.1" rusticata-macros = "1.0" [badges] diff --git a/src/esp.rs b/src/esp.rs index 70844c5..5e553ae 100644 --- a/src/esp.rs +++ b/src/esp.rs @@ -1,6 +1,6 @@ -use nom::{IResult,be_u32,rest}; -use ikev2::IkeV2Header; -use ikev2_parser::parse_ikev2_header; +use crate::ikev2::IkeV2Header; +use crate::ikev2_parser::parse_ikev2_header; +use nom::{be_u32, rest, IResult}; /// Encapsulating Security Payload Packet Format /// @@ -9,7 +9,7 @@ use ikev2_parser::parse_ikev2_header; pub struct ESPHeader<'a> { pub spi_index: &'a [u8], pub seq: u32, - pub data: &'a[u8] + pub data: &'a [u8], } /// UDP-encapsulated Packet Formats @@ -21,7 +21,6 @@ pub enum ESPData<'a> { IKE(IkeV2Header), } - /// Parse an encapsulated ESP packet /// /// The type of encapsulated data depends on the first field (`spi_index`): 0 is a forbidden SPI @@ -29,7 +28,7 @@ pub enum ESPData<'a> { /// Any other value indicates an ESP header. /// /// *Note: input is entirely consumed* -pub fn parse_esp_encapsulated<'a>(i: &'a[u8]) -> IResult<&'a[u8],ESPData<'a>> { +pub fn parse_esp_encapsulated<'a>(i: &'a [u8]) -> IResult<&'a [u8], ESPData<'a>> { if peek!(i, be_u32)?.1 == 0 { parse_ikev2_header(i).map(|x| (x.0, ESPData::IKE(x.1))) } else { @@ -46,18 +45,16 @@ pub fn parse_esp_encapsulated<'a>(i: &'a[u8]) -> IResult<&'a[u8],ESPData<'a>> { /// - the payload data (which can be encrypted) /// /// *Note: input is entirely consumed* -pub fn parse_esp_header<'a>(i: &'a[u8]) -> IResult<&'a[u8],ESPHeader<'a>> { +pub fn parse_esp_header<'a>(i: &'a [u8]) -> IResult<&'a [u8], ESPHeader<'a>> { do_parse!( i, - spi_index: take!(4) >> - seq: be_u32 >> - data: rest >> - ( - ESPHeader{ + spi_index: take!(4) + >> seq: be_u32 + >> data: rest + >> (ESPHeader { spi_index: spi_index, seq: seq, data: data - } - ) + }) ) } diff --git a/src/ikev2.rs b/src/ikev2.rs index ac4cbd8..8c77479 100644 --- a/src/ikev2.rs +++ b/src/ikev2.rs @@ -1,17 +1,17 @@ -use std::net::{IpAddr,Ipv4Addr,Ipv6Addr}; +use crate::ikev2_notify::NotifyType; +use crate::ikev2_transforms::*; use std::fmt; -use ikev2_transforms::*; -use ikev2_notify::NotifyType; +use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; /// Payload exchange type: SA, Auth, CreateChildSA, etc. #[derive(Copy, Clone, PartialEq, Eq)] pub struct IkeExchangeType(pub u8); impl IkeExchangeType { - pub const IKE_SA_INIT : IkeExchangeType = IkeExchangeType(34); - pub const IKE_AUTH : IkeExchangeType = IkeExchangeType(35); - pub const CREATE_CHILD_SA : IkeExchangeType = IkeExchangeType(36); - pub const INFORMATIONAL : IkeExchangeType = IkeExchangeType(37); + pub const IKE_SA_INIT: IkeExchangeType = IkeExchangeType(34); + pub const IKE_AUTH: IkeExchangeType = IkeExchangeType(35); + pub const CREATE_CHILD_SA: IkeExchangeType = IkeExchangeType(36); + pub const INFORMATIONAL: IkeExchangeType = IkeExchangeType(37); } impl fmt::Debug for IkeExchangeType { @@ -21,7 +21,7 @@ impl fmt::Debug for IkeExchangeType { 35 => f.write_str("IKE_AUTH"), 36 => f.write_str("CREATE_CHILD_SA"), 37 => f.write_str("INFORMATIONAL"), - n => f.debug_tuple("IkeExchangeType").field(&n).finish(), + n => f.debug_tuple("IkeExchangeType").field(&n).finish(), } } } @@ -33,9 +33,9 @@ impl fmt::Debug for IkeExchangeType { pub struct ProtocolID(pub u8); impl ProtocolID { - pub const IKE : ProtocolID = ProtocolID(1); - pub const AH : ProtocolID = ProtocolID(2); - pub const ESP : ProtocolID = ProtocolID(3); + pub const IKE: ProtocolID = ProtocolID(1); + pub const AH: ProtocolID = ProtocolID(2); + pub const ESP: ProtocolID = ProtocolID(3); } impl fmt::Debug for ProtocolID { @@ -49,9 +49,9 @@ impl fmt::Debug for ProtocolID { } } -pub const IKEV2_FLAG_INITIATOR : u8 = 0b1000; -pub const IKEV2_FLAG_VERSION : u8 = 0b10000; -pub const IKEV2_FLAG_RESPONSE : u8 = 0b100000; +pub const IKEV2_FLAG_INITIATOR: u8 = 0b1000; +pub const IKEV2_FLAG_VERSION: u8 = 0b10000; +pub const IKEV2_FLAG_RESPONSE: u8 = 0b100000; /// The IKE Header /// @@ -86,7 +86,7 @@ pub const IKEV2_FLAG_RESPONSE : u8 = 0b100000; /// "network byte order"). /// /// Defined in [RFC7296](https://tools.ietf.org/html/rfc7296) section 3.1 -#[derive(Clone, Debug,PartialEq)] +#[derive(Clone, Debug, PartialEq)] pub struct IkeV2Header { pub init_spi: u64, pub resp_spi: u64, @@ -105,29 +105,29 @@ pub struct IkePayloadType(pub u8); #[allow(non_upper_case_globals)] impl IkePayloadType { - pub const NoNextPayload : IkePayloadType = IkePayloadType(0); - pub const SecurityAssociation : IkePayloadType = IkePayloadType(33); - pub const KeyExchange : IkePayloadType = IkePayloadType(34); - pub const IdentInitiator : IkePayloadType = IkePayloadType(35); - pub const IdentResponder : IkePayloadType = IkePayloadType(36); - pub const Certificate : IkePayloadType = IkePayloadType(37); - pub const CertificateRequest : IkePayloadType = IkePayloadType(38); - pub const Authentication : IkePayloadType = IkePayloadType(39); - pub const Nonce : IkePayloadType = IkePayloadType(40); - pub const Notify : IkePayloadType = IkePayloadType(41); - pub const Delete : IkePayloadType = IkePayloadType(42); - pub const VendorID : IkePayloadType = IkePayloadType(43); - pub const TrafficSelectorInitiator : IkePayloadType = IkePayloadType(44); - pub const TrafficSelectorResponder : IkePayloadType = IkePayloadType(45); - pub const EncryptedAndAuthenticated : IkePayloadType = IkePayloadType(46); - pub const Configuration : IkePayloadType = IkePayloadType(47); - pub const ExtensibleAuthentication : IkePayloadType = IkePayloadType(48); + pub const NoNextPayload: IkePayloadType = IkePayloadType(0); + pub const SecurityAssociation: IkePayloadType = IkePayloadType(33); + pub const KeyExchange: IkePayloadType = IkePayloadType(34); + pub const IdentInitiator: IkePayloadType = IkePayloadType(35); + pub const IdentResponder: IkePayloadType = IkePayloadType(36); + pub const Certificate: IkePayloadType = IkePayloadType(37); + pub const CertificateRequest: IkePayloadType = IkePayloadType(38); + pub const Authentication: IkePayloadType = IkePayloadType(39); + pub const Nonce: IkePayloadType = IkePayloadType(40); + pub const Notify: IkePayloadType = IkePayloadType(41); + pub const Delete: IkePayloadType = IkePayloadType(42); + pub const VendorID: IkePayloadType = IkePayloadType(43); + pub const TrafficSelectorInitiator: IkePayloadType = IkePayloadType(44); + pub const TrafficSelectorResponder: IkePayloadType = IkePayloadType(45); + pub const EncryptedAndAuthenticated: IkePayloadType = IkePayloadType(46); + pub const Configuration: IkePayloadType = IkePayloadType(47); + pub const ExtensibleAuthentication: IkePayloadType = IkePayloadType(48); } impl fmt::Debug for IkePayloadType { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self.0 { - 0 => f.write_str("NoNextPayload"), + 0 => f.write_str("NoNextPayload"), 33 => f.write_str("SecurityAssociation"), 34 => f.write_str("KeyExchange"), 35 => f.write_str("IdentInitiator"), @@ -144,7 +144,7 @@ impl fmt::Debug for IkePayloadType { 46 => f.write_str("EncryptedAndAuthenticated"), 47 => f.write_str("Configuration"), 48 => f.write_str("ExtensibleAuthentication"), - n => f.debug_tuple("IkePayloadType").field(&n).finish(), + n => f.debug_tuple("IkePayloadType").field(&n).finish(), } } } @@ -152,10 +152,10 @@ impl fmt::Debug for IkePayloadType { /// Generic (unparsed payload) /// /// Defined in [RFC7296] -#[derive(Debug,PartialEq)] +#[derive(Debug, PartialEq)] pub struct IkeV2GenericPayload<'a> { pub hdr: IkeV2PayloadHeader, - pub payload: &'a[u8], + pub payload: &'a [u8], } /// Ciphersuite Proposal @@ -226,7 +226,7 @@ pub struct IkeV2GenericPayload<'a> { /// in the header of each transform. /// /// Defined in [RFC7296](https://tools.ietf.org/html/rfc7296) section 3.3.1 -#[derive(Clone,Debug,PartialEq)] +#[derive(Clone, Debug, PartialEq)] pub struct IkeV2Proposal<'a> { pub last: u8, pub reserved: u8, @@ -235,7 +235,7 @@ pub struct IkeV2Proposal<'a> { pub protocol_id: ProtocolID, pub spi_size: u8, pub num_transforms: u8, - pub spi: Option<&'a[u8]>, + pub spi: Option<&'a [u8]>, pub transforms: Vec>, } @@ -247,11 +247,11 @@ pub struct IkeV2Proposal<'a> { /// payload header followed by the Diffie-Hellman public value itself. /// /// Defined in [RFC7296](https://tools.ietf.org/html/rfc7296) section 3.4 -#[derive(Debug,PartialEq)] +#[derive(Debug, PartialEq)] pub struct KeyExchangePayload<'a> { pub dh_group: IkeTransformDHType, pub reserved: u16, - pub kex_data: &'a[u8], + pub kex_data: &'a [u8], } /// Identification Payloads @@ -268,12 +268,12 @@ pub struct KeyExchangePayload<'a> { /// data related to the other party. /// /// Defined in [RFC7296](https://tools.ietf.org/html/rfc7296) section 3.5 -#[derive(Debug,PartialEq)] +#[derive(Debug, PartialEq)] pub struct IdentificationPayload<'a> { pub id_type: IdentificationType, pub reserved1: u8, pub reserved2: u16, - pub ident_data: &'a[u8], + pub ident_data: &'a [u8], } /// Type of Identification @@ -282,29 +282,29 @@ pub struct IdentificationType(pub u8); impl IdentificationType { /// A single four (4) octet IPv4 address. - pub const ID_IPV4_ADDR : IdentificationType = IdentificationType(1); + pub const ID_IPV4_ADDR: IdentificationType = IdentificationType(1); /// A fully-qualified domain name string. An example of an ID_FQDN /// is "example.com". The string MUST NOT contain any terminators /// (e.g., NULL, CR, etc.). All characters in the ID_FQDN are ASCII; /// for an "internationalized domain name", the syntax is as defined /// in [IDNA], for example "xn--tmonesimerkki-bfbb.example.net". - pub const ID_FQDN : IdentificationType = IdentificationType(2); + pub const ID_FQDN: IdentificationType = IdentificationType(2); /// A fully-qualified RFC 822 email address string. An example of a /// ID_RFC822_ADDR is "jsmith@example.com". The string MUST NOT /// contain any terminators. Because of [EAI], implementations would /// be wise to treat this field as UTF-8 encoded text, not as /// pure ASCII. - pub const ID_RFC822_ADDR : IdentificationType = IdentificationType(3); + pub const ID_RFC822_ADDR: IdentificationType = IdentificationType(3); /// A single sixteen (16) octet IPv6 address. - pub const ID_IPV6_ADDR : IdentificationType = IdentificationType(5); + pub const ID_IPV6_ADDR: IdentificationType = IdentificationType(5); /// The binary Distinguished Encoding Rules (DER) encoding of an ASN.1 X.500 Distinguished /// Name. - pub const ID_DER_ASN1_DN : IdentificationType = IdentificationType(9); + pub const ID_DER_ASN1_DN: IdentificationType = IdentificationType(9); /// The binary DER encoding of an ASN.1 X.509 GeneralName. - pub const ID_DER_ASN1_GN : IdentificationType = IdentificationType(10); + pub const ID_DER_ASN1_GN: IdentificationType = IdentificationType(10); /// An opaque octet stream that may be used to pass vendor-specific information necessary to do /// certain proprietary types of identification. - pub const ID_KEY_ID : IdentificationType = IdentificationType(11); + pub const ID_KEY_ID: IdentificationType = IdentificationType(11); } /// Certificate Payload @@ -321,10 +321,10 @@ impl IdentificationType { /// than certificates may be passed in this payload. /// /// Defined in [RFC7296](https://tools.ietf.org/html/rfc7296) section 3.6 -#[derive(Debug,PartialEq)] +#[derive(Debug, PartialEq)] pub struct CertificatePayload<'a> { pub cert_encoding: CertificateEncoding, - pub cert_data: &'a[u8], + pub cert_data: &'a [u8], } /// Certificate Encoding @@ -336,33 +336,33 @@ pub struct CertificateEncoding(pub u8); #[allow(non_upper_case_globals)] impl CertificateEncoding { /// PKCS #7 wrapped X.509 certificate - pub const Pkcs7_X509 : CertificateEncoding = CertificateEncoding(1); + pub const Pkcs7_X509: CertificateEncoding = CertificateEncoding(1); /// PGP Certificate - pub const PgpCert : CertificateEncoding = CertificateEncoding(2); + pub const PgpCert: CertificateEncoding = CertificateEncoding(2); /// DNS Signed Key - pub const DnsKey : CertificateEncoding = CertificateEncoding(3); + pub const DnsKey: CertificateEncoding = CertificateEncoding(3); /// X.509 Certificate - Signature - pub const X509Sig : CertificateEncoding = CertificateEncoding(4); + pub const X509Sig: CertificateEncoding = CertificateEncoding(4); /// Kerberos Token - pub const Kerberos : CertificateEncoding = CertificateEncoding(6); + pub const Kerberos: CertificateEncoding = CertificateEncoding(6); /// Certificate Revocation List (CRL) - pub const Crl : CertificateEncoding = CertificateEncoding(7); + pub const Crl: CertificateEncoding = CertificateEncoding(7); /// Authority Revocation List (ARL) - pub const Arl : CertificateEncoding = CertificateEncoding(8); + pub const Arl: CertificateEncoding = CertificateEncoding(8); /// SPKI Certificate - pub const SpkiCert : CertificateEncoding = CertificateEncoding(9); + pub const SpkiCert: CertificateEncoding = CertificateEncoding(9); /// X.509 Certificate - Attribute - pub const X509CertAttr : CertificateEncoding = CertificateEncoding(10); + pub const X509CertAttr: CertificateEncoding = CertificateEncoding(10); /// Deprecated (was Raw RSA Key) - pub const OldRsaKey : CertificateEncoding = CertificateEncoding(11); + pub const OldRsaKey: CertificateEncoding = CertificateEncoding(11); /// Hash and URL of X.509 certificate - pub const X509Cert_HashUrl : CertificateEncoding = CertificateEncoding(12); + pub const X509Cert_HashUrl: CertificateEncoding = CertificateEncoding(12); /// Hash and URL of X.509 bundle - pub const X509Bundle_HashUrl : CertificateEncoding = CertificateEncoding(13); + pub const X509Bundle_HashUrl: CertificateEncoding = CertificateEncoding(13); /// OCSP Content ([RFC4806](https://tools.ietf.org/html/rfc4806)) - pub const OCSPContent : CertificateEncoding = CertificateEncoding(14); + pub const OCSPContent: CertificateEncoding = CertificateEncoding(14); /// Raw Public Key ([RFC7670](https://tools.ietf.org/html/rfc7670)) - pub const RawPublicKey : CertificateEncoding = CertificateEncoding(15); + pub const RawPublicKey: CertificateEncoding = CertificateEncoding(15); } /// Certificate Request Payload @@ -374,10 +374,10 @@ impl CertificateEncoding { /// sender needs to get the certificate of the receiver. /// /// Defined in [RFC7296](https://tools.ietf.org/html/rfc7296) section 3.7 -#[derive(Debug,PartialEq)] +#[derive(Debug, PartialEq)] pub struct CertificateRequestPayload<'a> { pub cert_encoding: CertificateEncoding, - pub ca_data: &'a[u8], + pub ca_data: &'a [u8], } /// Authentication Payload @@ -386,10 +386,10 @@ pub struct CertificateRequestPayload<'a> { /// data used for authentication purposes. /// /// Defined in [RFC7296](https://tools.ietf.org/html/rfc7296) section 3.8 -#[derive(Debug,PartialEq)] +#[derive(Debug, PartialEq)] pub struct AuthenticationPayload<'a> { pub auth_method: AuthenticationMethod, - pub auth_data: &'a[u8], + pub auth_data: &'a [u8], } /// Method of authentication used. @@ -401,28 +401,27 @@ pub struct AuthenticationMethod(pub u8); #[allow(non_upper_case_globals)] impl AuthenticationMethod { /// RSA Digital Signature - pub const RsaSig : AuthenticationMethod = AuthenticationMethod(1); + pub const RsaSig: AuthenticationMethod = AuthenticationMethod(1); /// Shared Key Message Integrity Code - pub const SharedKeyMIC : AuthenticationMethod = AuthenticationMethod(2); + pub const SharedKeyMIC: AuthenticationMethod = AuthenticationMethod(2); /// DSS Digital Signature - pub const DssSig : AuthenticationMethod = AuthenticationMethod(3); + pub const DssSig: AuthenticationMethod = AuthenticationMethod(3); /// ECDSA with SHA-256 on the P-256 curve - pub const EcdsaSha256P256 : AuthenticationMethod = AuthenticationMethod(9); + pub const EcdsaSha256P256: AuthenticationMethod = AuthenticationMethod(9); /// ECDSA with SHA-384 on the P-384 curve - pub const EcdsaSha384P384 : AuthenticationMethod = AuthenticationMethod(10); + pub const EcdsaSha384P384: AuthenticationMethod = AuthenticationMethod(10); /// ECDSA with SHA-512 on the P-512 curve - pub const EcdsaSha512P512 : AuthenticationMethod = AuthenticationMethod(11); + pub const EcdsaSha512P512: AuthenticationMethod = AuthenticationMethod(11); /// Generic Secure Password Authentication Method - pub const GenericPass : AuthenticationMethod = AuthenticationMethod(12); + pub const GenericPass: AuthenticationMethod = AuthenticationMethod(12); /// NULL Authentication - pub const Null : AuthenticationMethod = AuthenticationMethod(13); + pub const Null: AuthenticationMethod = AuthenticationMethod(13); /// Digital Signature - pub const DigitalSig : AuthenticationMethod = AuthenticationMethod(14); + pub const DigitalSig: AuthenticationMethod = AuthenticationMethod(14); /// Test if value is in unassigned range pub fn is_unassigned(&self) -> bool { - (self.0 >= 4 && self.0 <= 8) || - (self.0 >= 15 && self.0 <= 200) + (self.0 >= 4 && self.0 <= 8) || (self.0 >= 15 && self.0 <= 200) } /// Test if value is in private use range @@ -431,7 +430,6 @@ impl AuthenticationMethod { } } - /// Nonce Payload /// /// The Nonce payload, denoted as Ni and Nr in this document for the @@ -441,7 +439,7 @@ impl AuthenticationMethod { /// Defined in [RFC7296](https://tools.ietf.org/html/rfc7296) section 3.9 #[derive(PartialEq)] pub struct NoncePayload<'a> { - pub nonce_data: &'a[u8], + pub nonce_data: &'a [u8], } /// Notify Payload @@ -458,8 +456,8 @@ pub struct NotifyPayload<'a> { pub protocol_id: ProtocolID, pub spi_size: u8, pub notify_type: NotifyType, - pub spi: Option<&'a[u8]>, - pub notify_data: Option<&'a[u8]>, + pub spi: Option<&'a [u8]>, + pub notify_data: Option<&'a [u8]>, } /// Delete Payload @@ -476,12 +474,12 @@ pub struct NotifyPayload<'a> { /// different protocol. /// /// Defined in [RFC7296](https://tools.ietf.org/html/rfc7296) section 3.11 -#[derive(Debug,PartialEq)] +#[derive(Debug, PartialEq)] pub struct DeletePayload<'a> { pub protocol_id: ProtocolID, pub spi_size: u8, pub num_spi: u16, - pub spi: &'a[u8], + pub spi: &'a [u8], } /// Vendor ID Payload @@ -514,9 +512,9 @@ pub struct DeletePayload<'a> { /// away. /// /// Defined in [RFC7296](https://tools.ietf.org/html/rfc7296) section 3.12 -#[derive(Debug,PartialEq)] +#[derive(Debug, PartialEq)] pub struct VendorIDPayload<'a> { - pub vendor_id: &'a[u8], + pub vendor_id: &'a [u8], } /// Type of Traffic Selector @@ -530,32 +528,32 @@ pub struct TSType(pub u8); #[allow(non_upper_case_globals)] impl TSType { /// A range of IPv4 addresses - pub const IPv4AddrRange : TSType = TSType(7); + pub const IPv4AddrRange: TSType = TSType(7); /// A range of IPv6 addresses - pub const IPv6AddrRange : TSType = TSType(8); + pub const IPv6AddrRange: TSType = TSType(8); /// Fibre Channel Traffic Selectors ([RFC4595](https://tools.ietf.org/html/rfc4595)) - pub const FcAddrRange : TSType = TSType(9); + pub const FcAddrRange: TSType = TSType(9); } /// Traffic Selector /// /// Defined in [RFC7296](https://tools.ietf.org/html/rfc7296) section 3.13.1 -#[derive(Debug,PartialEq)] +#[derive(Debug, PartialEq)] pub struct TrafficSelector<'a> { pub ts_type: TSType, pub ip_proto_id: u8, pub sel_length: u16, pub start_port: u16, pub end_port: u16, - pub start_addr: &'a[u8], - pub end_addr: &'a[u8], + pub start_addr: &'a [u8], + pub end_addr: &'a [u8], } -fn ipv4_from_slice(b:&[u8]) -> Ipv4Addr { +fn ipv4_from_slice(b: &[u8]) -> Ipv4Addr { Ipv4Addr::new(b[0], b[1], b[2], b[3]) } -fn ipv6_from_slice(b:&[u8]) -> Ipv6Addr { +fn ipv6_from_slice(b: &[u8]) -> Ipv6Addr { Ipv6Addr::new( (b[0] as u16) << 8 | (b[1] as u16), (b[2] as u16) << 8 | (b[3] as u16), @@ -598,10 +596,10 @@ impl<'a> TrafficSelector<'a> { /// payload header followed by individual Traffic Selectors. /// /// Defined in [RFC7296](https://tools.ietf.org/html/rfc7296) section 3.13 -#[derive(Debug,PartialEq)] +#[derive(Debug, PartialEq)] pub struct TrafficSelectorPayload<'a> { pub num_ts: u8, - pub reserved: &'a[u8], // 3 bytes + pub reserved: &'a [u8], // 3 bytes pub ts: Vec>, } @@ -610,7 +608,7 @@ pub struct TrafficSelectorPayload<'a> { /// The content of an IKE message is one of the defined payloads. /// /// Defined in [RFC7296](https://tools.ietf.org/html/rfc7296) section 3.2 -#[derive(Debug,PartialEq)] +#[derive(Debug, PartialEq)] pub enum IkeV2PayloadContent<'a> { SA(Vec>), KE(KeyExchangePayload<'a>), @@ -626,7 +624,7 @@ pub enum IkeV2PayloadContent<'a> { TSi(TrafficSelectorPayload<'a>), TSr(TrafficSelectorPayload<'a>), - Unknown(&'a[u8]), + Unknown(&'a [u8]), Dummy, } @@ -634,7 +632,7 @@ pub enum IkeV2PayloadContent<'a> { /// Generic Payload Header /// /// Defined in [RFC7296](https://tools.ietf.org/html/rfc7296) section 3.2 -#[derive(Clone,Debug,PartialEq)] +#[derive(Clone, Debug, PartialEq)] pub struct IkeV2PayloadHeader { pub next_payload_type: IkePayloadType, pub critical: bool, @@ -645,7 +643,7 @@ pub struct IkeV2PayloadHeader { /// IKE Message Payload /// /// Defined in [RFC7296](https://tools.ietf.org/html/rfc7296) section 3 -#[derive(Debug,PartialEq)] +#[derive(Debug, PartialEq)] pub struct IkeV2Payload<'a> { pub hdr: IkeV2PayloadHeader, pub content: IkeV2PayloadContent<'a>, diff --git a/src/ikev2_debug.rs b/src/ikev2_debug.rs index dbb6e2f..44ef996 100644 --- a/src/ikev2_debug.rs +++ b/src/ikev2_debug.rs @@ -2,30 +2,38 @@ use std::fmt; use rusticata_macros::debug::HexSlice; -use ikev2::*; -use ikev2_transforms::*; +use crate::ikev2::*; +use crate::ikev2_transforms::*; // ------------------------- ikev2_transforms.rs ------------------------------ // impl<'a> fmt::Debug for IkeV2RawTransform<'a> { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { let (tf_type, tf_id) = match self.transform_type { - IkeTransformType::EncryptionAlgorithm => { - ("EncryptionAlgorithm".to_string(),format!("{:?}", self.transform_id)) - }, - IkeTransformType::PseudoRandomFunction => { - ("PseudoRandomFunction".to_string(),format!("{:?}", self.transform_id)) - }, - IkeTransformType::IntegrityAlgorithm => { - ("IntegrityAlgorithm".to_string(),format!("{:?}", self.transform_id)) - }, - IkeTransformType::DiffieHellmanGroup => { - ("DiffieHellmanGroup".to_string(),format!("{:?}", self.transform_id)) - }, - IkeTransformType::ExtendedSequenceNumbers => { - ("ExtendedSequenceNumbers".to_string(),format!("{:?}", self.transform_id)) - }, - _ => (format!("", self.transform_type.0),"".to_string()), + IkeTransformType::EncryptionAlgorithm => ( + "EncryptionAlgorithm".to_string(), + format!("{:?}", self.transform_id), + ), + IkeTransformType::PseudoRandomFunction => ( + "PseudoRandomFunction".to_string(), + format!("{:?}", self.transform_id), + ), + IkeTransformType::IntegrityAlgorithm => ( + "IntegrityAlgorithm".to_string(), + format!("{:?}", self.transform_id), + ), + IkeTransformType::DiffieHellmanGroup => ( + "DiffieHellmanGroup".to_string(), + format!("{:?}", self.transform_id), + ), + IkeTransformType::ExtendedSequenceNumbers => ( + "ExtendedSequenceNumbers".to_string(), + format!("{:?}", self.transform_id), + ), + _ => ( + format!("", self.transform_type.0), + "".to_string(), + ), }; fmt.debug_struct("IkeV2RawTransform") .field("last", &self.last) @@ -44,7 +52,7 @@ impl<'a> fmt::Debug for IkeV2RawTransform<'a> { impl<'a> fmt::Debug for NoncePayload<'a> { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fmt.debug_struct("NoncePayload") - .field("nonce_data", &HexSlice{d:self.nonce_data}) + .field("nonce_data", &HexSlice { d: self.nonce_data }) .finish() } } @@ -56,7 +64,7 @@ impl<'a> fmt::Debug for NotifyPayload<'a> { .field("spi_size", &self.spi_size) .field("notify_type", &self.notify_type) .field("spi", &self.spi) - .field("notify_data", &self.notify_data.map(|o|{HexSlice{d:o}})) + .field("notify_data", &self.notify_data.map(|o| HexSlice { d: o })) .finish() } } diff --git a/src/ikev2_notify.rs b/src/ikev2_notify.rs index c99103a..630199d 100644 --- a/src/ikev2_notify.rs +++ b/src/ikev2_notify.rs @@ -39,68 +39,72 @@ pub struct NotifyType(pub u16); impl NotifyType { // error types - pub const UNSUPPORTED_CRITICAL_PAYLOAD : NotifyType = NotifyType(1); - pub const INVALID_IKE_SPI : NotifyType = NotifyType(4); - pub const INVALID_MAJOR_VERSION : NotifyType = NotifyType(5); - pub const INVALID_SYNTAX : NotifyType = NotifyType(7); - pub const INVALID_MESSAGE_ID : NotifyType = NotifyType(9); - pub const INVALID_SPI : NotifyType = NotifyType(11); - pub const NO_PROPOSAL_CHOSEN : NotifyType = NotifyType(14); - pub const INVALID_KE_PAYLOAD : NotifyType = NotifyType(17); - pub const AUTHENTICATION_FAILED : NotifyType = NotifyType(24); - pub const SINGLE_PAIR_REQUIRED : NotifyType = NotifyType(34); - pub const NO_ADDITIONAL_SAS : NotifyType = NotifyType(35); - pub const INTERNAL_ADDRESS_FAILURE : NotifyType = NotifyType(36); - pub const FAILED_CP_REQUIRED : NotifyType = NotifyType(37); - pub const TS_UNACCEPTABLE : NotifyType = NotifyType(38); - pub const INVALID_SELECTORS : NotifyType = NotifyType(39); - pub const TEMPORARY_FAILURE : NotifyType = NotifyType(43); - pub const CHILD_SA_NOT_FOUND : NotifyType = NotifyType(44); + pub const UNSUPPORTED_CRITICAL_PAYLOAD: NotifyType = NotifyType(1); + pub const INVALID_IKE_SPI: NotifyType = NotifyType(4); + pub const INVALID_MAJOR_VERSION: NotifyType = NotifyType(5); + pub const INVALID_SYNTAX: NotifyType = NotifyType(7); + pub const INVALID_MESSAGE_ID: NotifyType = NotifyType(9); + pub const INVALID_SPI: NotifyType = NotifyType(11); + pub const NO_PROPOSAL_CHOSEN: NotifyType = NotifyType(14); + pub const INVALID_KE_PAYLOAD: NotifyType = NotifyType(17); + pub const AUTHENTICATION_FAILED: NotifyType = NotifyType(24); + pub const SINGLE_PAIR_REQUIRED: NotifyType = NotifyType(34); + pub const NO_ADDITIONAL_SAS: NotifyType = NotifyType(35); + pub const INTERNAL_ADDRESS_FAILURE: NotifyType = NotifyType(36); + pub const FAILED_CP_REQUIRED: NotifyType = NotifyType(37); + pub const TS_UNACCEPTABLE: NotifyType = NotifyType(38); + pub const INVALID_SELECTORS: NotifyType = NotifyType(39); + pub const TEMPORARY_FAILURE: NotifyType = NotifyType(43); + pub const CHILD_SA_NOT_FOUND: NotifyType = NotifyType(44); // status types - pub const INITIAL_CONTACT : NotifyType = NotifyType(16384); - pub const SET_WINDOW_SIZE : NotifyType = NotifyType(16385); - pub const ADDITIONAL_TS_POSSIBLE : NotifyType = NotifyType(16386); - pub const IPCOMP_SUPPORTED : NotifyType = NotifyType(16387); - pub const NAT_DETECTION_SOURCE_IP : NotifyType = NotifyType(16388); - pub const NAT_DETECTION_DESTINATION_IP : NotifyType = NotifyType(16389); - pub const COOKIE : NotifyType = NotifyType(16390); - pub const USE_TRANSPORT_MODE : NotifyType = NotifyType(16391); - pub const HTTP_CERT_LOOKUP_SUPPORTED : NotifyType = NotifyType(16392); - pub const REKEY_SA : NotifyType = NotifyType(16393); - pub const ESP_TFC_PADDING_NOT_SUPPORTED : NotifyType = NotifyType(16394); - pub const NON_FIRST_FRAGMENTS_ALSO : NotifyType = NotifyType(16395); + pub const INITIAL_CONTACT: NotifyType = NotifyType(16384); + pub const SET_WINDOW_SIZE: NotifyType = NotifyType(16385); + pub const ADDITIONAL_TS_POSSIBLE: NotifyType = NotifyType(16386); + pub const IPCOMP_SUPPORTED: NotifyType = NotifyType(16387); + pub const NAT_DETECTION_SOURCE_IP: NotifyType = NotifyType(16388); + pub const NAT_DETECTION_DESTINATION_IP: NotifyType = NotifyType(16389); + pub const COOKIE: NotifyType = NotifyType(16390); + pub const USE_TRANSPORT_MODE: NotifyType = NotifyType(16391); + pub const HTTP_CERT_LOOKUP_SUPPORTED: NotifyType = NotifyType(16392); + pub const REKEY_SA: NotifyType = NotifyType(16393); + pub const ESP_TFC_PADDING_NOT_SUPPORTED: NotifyType = NotifyType(16394); + pub const NON_FIRST_FRAGMENTS_ALSO: NotifyType = NotifyType(16395); // - pub const MULTIPLE_AUTH_SUPPORTED : NotifyType = NotifyType(16404); - pub const ANOTHER_AUTH_FOLLOWS : NotifyType = NotifyType(16405); - pub const REDIRECT_SUPPORTED : NotifyType = NotifyType(16406); + pub const MULTIPLE_AUTH_SUPPORTED: NotifyType = NotifyType(16404); + pub const ANOTHER_AUTH_FOLLOWS: NotifyType = NotifyType(16405); + pub const REDIRECT_SUPPORTED: NotifyType = NotifyType(16406); // - pub const IKEV2_FRAGMENTATION_SUPPORTED : NotifyType = NotifyType(16430); - pub const SIGNATURE_HASH_ALGORITHMS : NotifyType = NotifyType(16431); + pub const IKEV2_FRAGMENTATION_SUPPORTED: NotifyType = NotifyType(16430); + pub const SIGNATURE_HASH_ALGORITHMS: NotifyType = NotifyType(16431); - pub fn is_error(&self) -> bool { self.0 < 16384 } - pub fn is_status(&self) -> bool { self.0 > 16384 } + pub fn is_error(&self) -> bool { + self.0 < 16384 + } + pub fn is_status(&self) -> bool { + self.0 > 16384 + } } impl fmt::Debug for NotifyType { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self.0 { - 1 => f.write_str("UNSUPPORTED_CRITICAL_PAYLOAD"), - 4 => f.write_str("INVALID_IKE_SPI"), - 5 => f.write_str("INVALID_MAJOR_VERSION"), - 7 => f.write_str("INVALID_SYNTAX"), - 9 => f.write_str("INVALID_MESSAGE_ID"), - 11 => f.write_str("INVALID_SPI"), - 14 => f.write_str("NO_PROPOSAL_CHOSEN"), - 17 => f.write_str("INVALID_KE_PAYLOAD"), - 24 => f.write_str("AUTHENTICATION_FAILED"), - 34 => f.write_str("SINGLE_PAIR_REQUIRED"), - 35 => f.write_str("NO_ADDITIONAL_SAS"), - 36 => f.write_str("INTERNAL_ADDRESS_FAILURE"), - 37 => f.write_str("FAILED_CP_REQUIRED"), - 38 => f.write_str("TS_UNACCEPTABLE"), - 39 => f.write_str("INVALID_SELECTORS"), - 43 => f.write_str("TEMPORARY_FAILURE"), - 44 => f.write_str("CHILD_SA_NOT_FOUND"), + 1 => f.write_str("UNSUPPORTED_CRITICAL_PAYLOAD"), + 4 => f.write_str("INVALID_IKE_SPI"), + 5 => f.write_str("INVALID_MAJOR_VERSION"), + 7 => f.write_str("INVALID_SYNTAX"), + 9 => f.write_str("INVALID_MESSAGE_ID"), + 11 => f.write_str("INVALID_SPI"), + 14 => f.write_str("NO_PROPOSAL_CHOSEN"), + 17 => f.write_str("INVALID_KE_PAYLOAD"), + 24 => f.write_str("AUTHENTICATION_FAILED"), + 34 => f.write_str("SINGLE_PAIR_REQUIRED"), + 35 => f.write_str("NO_ADDITIONAL_SAS"), + 36 => f.write_str("INTERNAL_ADDRESS_FAILURE"), + 37 => f.write_str("FAILED_CP_REQUIRED"), + 38 => f.write_str("TS_UNACCEPTABLE"), + 39 => f.write_str("INVALID_SELECTORS"), + 43 => f.write_str("TEMPORARY_FAILURE"), + 44 => f.write_str("CHILD_SA_NOT_FOUND"), // 16384 => f.write_str("INITIAL_CONTACT"), 16385 => f.write_str("SET_WINDOW_SIZE"), @@ -122,7 +126,7 @@ impl fmt::Debug for NotifyType { 16430 => f.write_str("IKEV2_FRAGMENTATION_SUPPORTED"), 16431 => f.write_str("SIGNATURE_HASH_ALGORITHMS"), // - n => f.debug_tuple("Notify").field(&n).finish(), + n => f.debug_tuple("Notify").field(&n).finish(), } } } diff --git a/src/ikev2_parser.rs b/src/ikev2_parser.rs index 2864a05..b494a7b 100644 --- a/src/ikev2_parser.rs +++ b/src/ikev2_parser.rs @@ -1,7 +1,7 @@ +use crate::ikev2::*; +use crate::ikev2_notify::NotifyType; +use crate::ikev2_transforms::*; use nom::{self, *}; -use ikev2::*; -use ikev2_transforms::*; -use ikev2_notify::NotifyType; named!(pub parse_ikev2_header, do_parse!( @@ -107,180 +107,191 @@ named!(pub parse_ikev2_proposal, ) ); -pub fn parse_ikev2_payload_sa<'a>(i: &'a[u8], _length: u16) -> IResult<&'a[u8],IkeV2PayloadContent<'a>> { - map!( - i, - many1!(complete!(parse_ikev2_proposal)), - |v| IkeV2PayloadContent::SA(v) - ) +pub fn parse_ikev2_payload_sa<'a>( + i: &'a [u8], + _length: u16, +) -> IResult<&'a [u8], IkeV2PayloadContent<'a>> { + map!(i, many1!(complete!(parse_ikev2_proposal)), |v| { + IkeV2PayloadContent::SA(v) + }) } -pub fn parse_ikev2_payload_kex<'a>(i: &'a[u8], length: u16) -> IResult<&'a[u8],IkeV2PayloadContent<'a>> { - do_parse!(i, - dh: be_u16 - >> reserved: be_u16 - >> error_if!(length < 4, ErrorKind::Custom(128)) - >> data: take!(length-4) - >> ( - IkeV2PayloadContent::KE( - KeyExchangePayload{ - dh_group: IkeTransformDHType(dh), - reserved: reserved, - kex_data: data, - } - ) - ) +pub fn parse_ikev2_payload_kex<'a>( + i: &'a [u8], + length: u16, +) -> IResult<&'a [u8], IkeV2PayloadContent<'a>> { + do_parse!( + i, + dh: be_u16 + >> reserved: be_u16 + >> error_if!(length < 4, ErrorKind::Custom(128)) + >> data: take!(length - 4) + >> (IkeV2PayloadContent::KE(KeyExchangePayload { + dh_group: IkeTransformDHType(dh), + reserved: reserved, + kex_data: data, + })) ) } -pub fn parse_ikev2_payload_ident_init<'a>(i: &'a[u8], length: u16) -> IResult<&'a[u8],IkeV2PayloadContent<'a>> { - do_parse!(i, - id_type: be_u8 - >> reserved1: be_u8 - >> reserved2: be_u16 - >> error_if!(length < 4, ErrorKind::Custom(128)) - >> data: take!(length-4) - >> ( - IkeV2PayloadContent::IDi( - IdentificationPayload{ - id_type: IdentificationType(id_type), - reserved1: reserved1, - reserved2: reserved2, - ident_data: data, - } - ) - )) +pub fn parse_ikev2_payload_ident_init<'a>( + i: &'a [u8], + length: u16, +) -> IResult<&'a [u8], IkeV2PayloadContent<'a>> { + do_parse!( + i, + id_type: be_u8 + >> reserved1: be_u8 + >> reserved2: be_u16 + >> error_if!(length < 4, ErrorKind::Custom(128)) + >> data: take!(length - 4) + >> (IkeV2PayloadContent::IDi(IdentificationPayload { + id_type: IdentificationType(id_type), + reserved1: reserved1, + reserved2: reserved2, + ident_data: data, + })) + ) } -pub fn parse_ikev2_payload_ident_resp<'a>(i: &'a[u8], length: u16) -> IResult<&'a[u8],IkeV2PayloadContent<'a>> { - do_parse!(i, - id_type: be_u8 - >> reserved1: be_u8 - >> reserved2: be_u16 - >> error_if!(length < 4, ErrorKind::Custom(128)) - >> data: take!(length-4) - >> ( - IkeV2PayloadContent::IDr( - IdentificationPayload{ - id_type: IdentificationType(id_type), - reserved1: reserved1, - reserved2: reserved2, - ident_data: data, - } - ) - )) +pub fn parse_ikev2_payload_ident_resp<'a>( + i: &'a [u8], + length: u16, +) -> IResult<&'a [u8], IkeV2PayloadContent<'a>> { + do_parse!( + i, + id_type: be_u8 + >> reserved1: be_u8 + >> reserved2: be_u16 + >> error_if!(length < 4, ErrorKind::Custom(128)) + >> data: take!(length - 4) + >> (IkeV2PayloadContent::IDr(IdentificationPayload { + id_type: IdentificationType(id_type), + reserved1: reserved1, + reserved2: reserved2, + ident_data: data, + })) + ) } -pub fn parse_ikev2_payload_certificate<'a>(i: &'a[u8], length: u16) -> IResult<&'a[u8],IkeV2PayloadContent<'a>> { - do_parse!(i, - encoding: be_u8 - >> error_if!(length < 1, ErrorKind::Custom(128)) - >> data: take!(length-1) - >> ( - IkeV2PayloadContent::Certificate( - CertificatePayload{ - cert_encoding: CertificateEncoding(encoding), - cert_data: data, - } - ) - )) +pub fn parse_ikev2_payload_certificate<'a>( + i: &'a [u8], + length: u16, +) -> IResult<&'a [u8], IkeV2PayloadContent<'a>> { + do_parse!( + i, + encoding: be_u8 + >> error_if!(length < 1, ErrorKind::Custom(128)) + >> data: take!(length - 1) + >> (IkeV2PayloadContent::Certificate(CertificatePayload { + cert_encoding: CertificateEncoding(encoding), + cert_data: data, + })) + ) } -pub fn parse_ikev2_payload_certificate_request<'a>(i: &'a[u8], length: u16) -> IResult<&'a[u8],IkeV2PayloadContent<'a>> { - do_parse!(i, - encoding: be_u8 - >> error_if!(length < 1, ErrorKind::Custom(128)) - >> data: take!(length-1) - >> ( - IkeV2PayloadContent::CertificateRequest( - CertificateRequestPayload{ - cert_encoding: CertificateEncoding(encoding), - ca_data: data, - } - ) - )) +pub fn parse_ikev2_payload_certificate_request<'a>( + i: &'a [u8], + length: u16, +) -> IResult<&'a [u8], IkeV2PayloadContent<'a>> { + do_parse!( + i, + encoding: be_u8 + >> error_if!(length < 1, ErrorKind::Custom(128)) + >> data: take!(length - 1) + >> (IkeV2PayloadContent::CertificateRequest(CertificateRequestPayload { + cert_encoding: CertificateEncoding(encoding), + ca_data: data, + })) + ) } -pub fn parse_ikev2_payload_authentication<'a>(i: &'a[u8], length: u16) -> IResult<&'a[u8],IkeV2PayloadContent<'a>> { - do_parse!(i, - method: be_u8 >> - error_if!(length < 4, ErrorKind::Custom(128)) >> - data: take!(length-4) >> - ( - IkeV2PayloadContent::Authentication( - AuthenticationPayload{ - auth_method: AuthenticationMethod(method), - auth_data: data, - } - ) - )) +pub fn parse_ikev2_payload_authentication<'a>( + i: &'a [u8], + length: u16, +) -> IResult<&'a [u8], IkeV2PayloadContent<'a>> { + do_parse!( + i, + method: be_u8 + >> error_if!(length < 4, ErrorKind::Custom(128)) + >> data: take!(length - 4) + >> (IkeV2PayloadContent::Authentication(AuthenticationPayload { + auth_method: AuthenticationMethod(method), + auth_data: data, + })) + ) } -pub fn parse_ikev2_payload_nonce<'a>(i: &'a[u8], length: u16) -> IResult<&'a[u8],IkeV2PayloadContent<'a>> { - do_parse!(i, - data: take!(length) - >> ( - IkeV2PayloadContent::Nonce( - NoncePayload{ - nonce_data: data, - } - ) - )) +pub fn parse_ikev2_payload_nonce<'a>( + i: &'a [u8], + length: u16, +) -> IResult<&'a [u8], IkeV2PayloadContent<'a>> { + do_parse!( + i, + data: take!(length) >> (IkeV2PayloadContent::Nonce(NoncePayload { nonce_data: data })) + ) } -pub fn parse_ikev2_payload_notify<'a>(i: &'a[u8], length: u16) -> IResult<&'a[u8],IkeV2PayloadContent<'a>> { - do_parse!(i, - proto_id: be_u8 >> - spi_sz: be_u8 >> - notif_type: be_u16 >> - spi: cond!(spi_sz > 0, take!(spi_sz)) >> - notif_data: cond!(length > 8 + spi_sz as u16, take!(length-(8+spi_sz as u16))) >> - ( - IkeV2PayloadContent::Notify( - NotifyPayload{ - protocol_id: ProtocolID(proto_id), - spi_size: spi_sz, - notify_type: NotifyType(notif_type), - spi: spi, - notify_data: notif_data, - } - ) - )) +pub fn parse_ikev2_payload_notify<'a>( + i: &'a [u8], + length: u16, +) -> IResult<&'a [u8], IkeV2PayloadContent<'a>> { + do_parse!( + i, + proto_id: be_u8 + >> spi_sz: be_u8 + >> notif_type: be_u16 + >> spi: cond!(spi_sz > 0, take!(spi_sz)) + >> notif_data: + cond!( + length > 8 + spi_sz as u16, + take!(length - (8 + spi_sz as u16)) + ) + >> (IkeV2PayloadContent::Notify(NotifyPayload { + protocol_id: ProtocolID(proto_id), + spi_size: spi_sz, + notify_type: NotifyType(notif_type), + spi: spi, + notify_data: notif_data, + })) + ) } -pub fn parse_ikev2_payload_vendor_id<'a>(i: &'a[u8], length: u16) -> IResult<&'a[u8],IkeV2PayloadContent<'a>> { - do_parse!(i, - error_if!(length < 8, ErrorKind::Custom(128)) >> - vendor_id: take!(length-8) >> - ( - IkeV2PayloadContent::VendorID( - VendorIDPayload{ - vendor_id: vendor_id, - } - ) - )) +pub fn parse_ikev2_payload_vendor_id<'a>( + i: &'a [u8], + length: u16, +) -> IResult<&'a [u8], IkeV2PayloadContent<'a>> { + do_parse!( + i, + error_if!(length < 8, ErrorKind::Custom(128)) + >> vendor_id: take!(length - 8) + >> (IkeV2PayloadContent::VendorID(VendorIDPayload { + vendor_id: vendor_id, + })) + ) } -pub fn parse_ikev2_payload_delete<'a>(i: &'a[u8], length: u16) -> IResult<&'a[u8],IkeV2PayloadContent<'a>> { - do_parse!(i, - proto_id: be_u8 >> - spi_sz: be_u8 >> - num_spi: be_u16 >> - error_if!(length < 8, ErrorKind::Custom(128)) >> - spi: take!(length-8) >> - ( - IkeV2PayloadContent::Delete( - DeletePayload{ - protocol_id: ProtocolID(proto_id), - spi_size: spi_sz, - num_spi: num_spi, - spi: spi, - } - ) - )) +pub fn parse_ikev2_payload_delete<'a>( + i: &'a [u8], + length: u16, +) -> IResult<&'a [u8], IkeV2PayloadContent<'a>> { + do_parse!( + i, + proto_id: be_u8 + >> spi_sz: be_u8 + >> num_spi: be_u16 + >> error_if!(length < 8, ErrorKind::Custom(128)) + >> spi: take!(length - 8) + >> (IkeV2PayloadContent::Delete(DeletePayload { + protocol_id: ProtocolID(proto_id), + spi_size: spi_sz, + num_spi: num_spi, + spi: spi, + })) + ) } -fn parse_ts_addr<'a>(i: &'a[u8], t: u8) -> IResult<&'a[u8],&'a[u8]> { +fn parse_ts_addr<'a>(i: &'a [u8], t: u8) -> IResult<&'a [u8], &'a [u8]> { match t { 7 => take!(i, 4), 8 => take!(i, 16), @@ -288,17 +299,17 @@ fn parse_ts_addr<'a>(i: &'a[u8], t: u8) -> IResult<&'a[u8],&'a[u8]> { } } -fn parse_ikev2_ts<'a>(i: &'a[u8]) -> IResult<&'a[u8],TrafficSelector<'a>> { - do_parse!(i, - ts_type: be_u8 - >> ip_proto_id: be_u8 - >> sel_length: be_u16 - >> start_port: be_u16 - >> end_port: be_u16 - >> start_addr: apply!(parse_ts_addr,ts_type) - >> end_addr: apply!(parse_ts_addr,ts_type) - >> ( - TrafficSelector{ +fn parse_ikev2_ts<'a>(i: &'a [u8]) -> IResult<&'a [u8], TrafficSelector<'a>> { + do_parse!( + i, + ts_type: be_u8 + >> ip_proto_id: be_u8 + >> sel_length: be_u16 + >> start_port: be_u16 + >> end_port: be_u16 + >> start_addr: apply!(parse_ts_addr, ts_type) + >> end_addr: apply!(parse_ts_addr, ts_type) + >> (TrafficSelector { ts_type: TSType(ts_type), ip_proto_id: ip_proto_id, sel_length: sel_length, @@ -306,83 +317,97 @@ fn parse_ikev2_ts<'a>(i: &'a[u8]) -> IResult<&'a[u8],TrafficSelector<'a>> { end_port: end_port, start_addr: start_addr, end_addr: end_addr, - } - )) + }) + ) } -pub fn parse_ikev2_payload_ts<'a>(i: &'a[u8], length: u16) -> IResult<&'a[u8],TrafficSelectorPayload<'a>> { - do_parse!(i, - num_ts: be_u8 - >> reserved: take!(3) - >> error_if!(length < 4, ErrorKind::Custom(128)) - >> ts: flat_map!(take!(length-4), - many1!(complete!(parse_ikev2_ts)) - ) - >> ( - TrafficSelectorPayload{ +pub fn parse_ikev2_payload_ts<'a>( + i: &'a [u8], + length: u16, +) -> IResult<&'a [u8], TrafficSelectorPayload<'a>> { + do_parse!( + i, + num_ts: be_u8 + >> reserved: take!(3) + >> error_if!(length < 4, ErrorKind::Custom(128)) + >> ts: flat_map!(take!(length - 4), many1!(complete!(parse_ikev2_ts))) + >> (TrafficSelectorPayload { num_ts: num_ts, reserved: reserved, ts: ts, - } - )) + }) + ) } -pub fn parse_ikev2_payload_ts_init<'a>(i: &'a[u8], length: u16) -> IResult<&'a[u8],IkeV2PayloadContent<'a>> { - map!(i, - call!(parse_ikev2_payload_ts,length), - |x| IkeV2PayloadContent::TSi(x) - ) +pub fn parse_ikev2_payload_ts_init<'a>( + i: &'a [u8], + length: u16, +) -> IResult<&'a [u8], IkeV2PayloadContent<'a>> { + map!(i, call!(parse_ikev2_payload_ts, length), |x| { + IkeV2PayloadContent::TSi(x) + }) } -pub fn parse_ikev2_payload_ts_resp<'a>(i: &'a[u8], length: u16) -> IResult<&'a[u8],IkeV2PayloadContent<'a>> { - map!(i, - call!(parse_ikev2_payload_ts,length), - |x| IkeV2PayloadContent::TSr(x) - ) +pub fn parse_ikev2_payload_ts_resp<'a>( + i: &'a [u8], + length: u16, +) -> IResult<&'a [u8], IkeV2PayloadContent<'a>> { + map!(i, call!(parse_ikev2_payload_ts, length), |x| { + IkeV2PayloadContent::TSr(x) + }) } -pub fn parse_ikev2_payload_unknown<'a>(i: &'a[u8], length: u16) -> IResult<&'a[u8],IkeV2PayloadContent<'a>> { - map!(i, take!(length), |d| { IkeV2PayloadContent::Unknown(d) }) +pub fn parse_ikev2_payload_unknown<'a>( + i: &'a [u8], + length: u16, +) -> IResult<&'a [u8], IkeV2PayloadContent<'a>> { + map!(i, take!(length), |d| IkeV2PayloadContent::Unknown(d)) } -pub fn parse_ikev2_payload_with_type(i: &[u8], length: u16, next_payload_type: IkePayloadType) -> IResult<&[u8],IkeV2PayloadContent> { +pub fn parse_ikev2_payload_with_type( + i: &[u8], + length: u16, + next_payload_type: IkePayloadType, +) -> IResult<&[u8], IkeV2PayloadContent> { let f = match next_payload_type { // IkePayloadType::NoNextPayload => parse_ikev2_payload_unknown, // XXX ? - IkePayloadType::SecurityAssociation => parse_ikev2_payload_sa, - IkePayloadType::KeyExchange => parse_ikev2_payload_kex, - IkePayloadType::IdentInitiator => parse_ikev2_payload_ident_init, - IkePayloadType::IdentResponder => parse_ikev2_payload_ident_resp, - IkePayloadType::Certificate => parse_ikev2_payload_certificate, - IkePayloadType::CertificateRequest => parse_ikev2_payload_certificate_request, - IkePayloadType::Authentication => parse_ikev2_payload_authentication, - IkePayloadType::Nonce => parse_ikev2_payload_nonce, - IkePayloadType::Notify => parse_ikev2_payload_notify, - IkePayloadType::Delete => parse_ikev2_payload_delete, - IkePayloadType::VendorID => parse_ikev2_payload_vendor_id, + IkePayloadType::SecurityAssociation => parse_ikev2_payload_sa, + IkePayloadType::KeyExchange => parse_ikev2_payload_kex, + IkePayloadType::IdentInitiator => parse_ikev2_payload_ident_init, + IkePayloadType::IdentResponder => parse_ikev2_payload_ident_resp, + IkePayloadType::Certificate => parse_ikev2_payload_certificate, + IkePayloadType::CertificateRequest => parse_ikev2_payload_certificate_request, + IkePayloadType::Authentication => parse_ikev2_payload_authentication, + IkePayloadType::Nonce => parse_ikev2_payload_nonce, + IkePayloadType::Notify => parse_ikev2_payload_notify, + IkePayloadType::Delete => parse_ikev2_payload_delete, + IkePayloadType::VendorID => parse_ikev2_payload_vendor_id, IkePayloadType::TrafficSelectorInitiator => parse_ikev2_payload_ts_init, IkePayloadType::TrafficSelectorResponder => parse_ikev2_payload_ts_resp, // None => parse_ikev2_payload_unknown, _ => parse_ikev2_payload_unknown, // _ => panic!("unknown type {}",next_payload_type), }; - flat_map!(i,take!(length),call!(f,length)) + flat_map!(i, take!(length), call!(f, length)) } fn parse_ikev2_payload_list_fold<'a>( - res_v: Result>,&'static str>, - p: IkeV2GenericPayload<'a> + res_v: Result>, &'static str>, + p: IkeV2GenericPayload<'a>, ) -> Result>, &'static str> { let mut v = res_v?; // println!("parse_payload_list_fold: v.len={} p={:?}",v.len(),p); let next_payload_type = match v.last() { Some(el) => el.hdr.next_payload_type, - None => { return Err("parse_ikev2_payload_list_fold: next payload type"); }, + None => { + return Err("parse_ikev2_payload_list_fold: next payload type"); + } }; if p.hdr.payload_length < 4 { return Err("parse_ikev2_payload_list_fold: p.hdr.payload_length"); } let res = parse_ikev2_payload_with_type(p.payload, p.hdr.payload_length - 4, next_payload_type); - if let Ok( (rem, p2) ) = res { + if let Ok((rem, p2)) = res { if rem.len() != 0 { return Err("parse_ikev2_payload_list_fold: rem is not empty"); } @@ -397,20 +422,22 @@ fn parse_ikev2_payload_list_fold<'a>( } } -pub fn parse_ikev2_payload_list<'a>(i: &'a[u8], initial_type: IkePayloadType) -> IResult<&'a[u8],Result>,&'static str>> { - fold_many1!(i, +pub fn parse_ikev2_payload_list<'a>( + i: &'a [u8], + initial_type: IkePayloadType, +) -> IResult<&'a [u8], Result>, &'static str>> { + fold_many1!( + i, complete!(parse_ikev2_payload_generic), - Ok(vec![ - IkeV2Payload { - hdr:IkeV2PayloadHeader{ - next_payload_type: initial_type, - critical: false, - reserved: 0, - payload_length: 0 - }, - content:IkeV2PayloadContent::Dummy, + Ok(vec![IkeV2Payload { + hdr: IkeV2PayloadHeader { + next_payload_type: initial_type, + critical: false, + reserved: 0, + payload_length: 0 }, - ]), + content: IkeV2PayloadContent::Dummy, + },]), parse_ikev2_payload_list_fold ) // XXX should we split_first() the vector and return all but the first element ? @@ -419,101 +446,110 @@ pub fn parse_ikev2_payload_list<'a>(i: &'a[u8], initial_type: IkePayloadType) -> /// Parse an IKEv2 message /// /// Parse the IKEv2 header and payload list -pub fn parse_ikev2_message<'a>(i: &[u8]) -> IResult<&[u8],(IkeV2Header,Result,&'static str>)> { +pub fn parse_ikev2_message<'a>( + i: &[u8], +) -> IResult<&[u8], (IkeV2Header, Result, &'static str>)> { do_parse!( i, - hdr: parse_ikev2_header >> - error_if!(hdr.length < 28, ErrorKind::Custom(128) ) >> - msg: flat_map!(take!(hdr.length-28), call!(parse_ikev2_payload_list, hdr.next_payload)) >> - ( hdr,msg ) + hdr: parse_ikev2_header + >> error_if!(hdr.length < 28, ErrorKind::Custom(128)) + >> msg: flat_map!( + take!(hdr.length - 28), + call!(parse_ikev2_payload_list, hdr.next_payload) + ) + >> (hdr, msg) ) } #[cfg(test)] mod tests { - use ikev2_parser::*; - -static IKEV2_INIT_REQ: &'static [u8] = &[ - 0x01, 0xf8, 0xc3, 0xd4, 0xbb, 0x77, 0x3f, 0x2f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x21, 0x20, 0x22, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x48, 0x22, 0x00, 0x00, 0x30, - 0x00, 0x00, 0x00, 0x2c, 0x01, 0x01, 0x00, 0x04, 0x03, 0x00, 0x00, 0x0c, 0x01, 0x00, 0x00, 0x14, - 0x80, 0x0e, 0x00, 0x80, 0x03, 0x00, 0x00, 0x08, 0x03, 0x00, 0x00, 0x0c, 0x03, 0x00, 0x00, 0x08, - 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x08, 0x04, 0x00, 0x00, 0x1e, 0x28, 0x00, 0x00, 0x88, - 0x00, 0x1e, 0x00, 0x00, 0x8f, 0xe6, 0xf3, 0x6e, 0x88, 0x7b, 0x18, 0x9b, 0x5e, 0xce, 0xf2, 0x56, - 0xf9, 0x8d, 0x76, 0xaa, 0xcb, 0x07, 0xb3, 0xb9, 0x58, 0xee, 0x73, 0xea, 0x7b, 0x73, 0xb1, 0x04, - 0x7e, 0xa4, 0x2a, 0x4e, 0x44, 0x1f, 0xb9, 0x3e, 0xf9, 0xa9, 0xab, 0x0c, 0x54, 0x5a, 0xa7, 0x46, - 0x2e, 0x58, 0x3c, 0x06, 0xb2, 0xed, 0x91, 0x8d, 0x11, 0xca, 0x67, 0xdb, 0x21, 0x6b, 0xb8, 0xad, - 0xbf, 0x57, 0x3f, 0xba, 0x5a, 0xa6, 0x7d, 0x49, 0x83, 0x4b, 0xa9, 0x93, 0x6f, 0x4c, 0xe9, 0x66, - 0xcd, 0x57, 0x5c, 0xba, 0x07, 0x42, 0xfa, 0x0b, 0xe8, 0xb9, 0xd0, 0x25, 0xc4, 0xb9, 0xdf, 0x29, - 0xd7, 0xe4, 0x6e, 0xd6, 0x54, 0x78, 0xaa, 0x95, 0x02, 0xbf, 0x25, 0x55, 0x71, 0xfa, 0x9e, 0xcb, - 0x05, 0xea, 0x8f, 0x7b, 0x14, 0x0e, 0x1d, 0xdf, 0xb4, 0x03, 0x5f, 0x2d, 0x21, 0x66, 0x58, 0x6e, - 0x42, 0x72, 0x32, 0x03, 0x29, 0x00, 0x00, 0x24, 0xe3, 0x3b, 0x52, 0xaa, 0x6f, 0x6d, 0x62, 0x87, - 0x16, 0xd7, 0xab, 0xc6, 0x45, 0xa6, 0xcc, 0x97, 0x07, 0x43, 0x3d, 0x85, 0x83, 0xde, 0xab, 0x97, - 0xdb, 0xbf, 0x08, 0xce, 0x0f, 0xad, 0x59, 0x71, 0x29, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x40, 0x04, - 0xcc, 0xc0, 0x64, 0x5c, 0x1e, 0xeb, 0xc2, 0x1d, 0x09, 0x2b, 0xf0, 0x7f, 0xca, 0x34, 0xc3, 0xe6, - 0x2b, 0x20, 0xec, 0x8f, 0x29, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x40, 0x05, 0x15, 0x39, 0x75, 0x77, - 0xf5, 0x54, 0x87, 0xa3, 0x8f, 0xd8, 0xaf, 0x70, 0xb0, 0x9c, 0x20, 0x9c, 0xff, 0x4a, 0x37, 0xd1, - 0x29, 0x00, 0x00, 0x10, 0x00, 0x00, 0x40, 0x2f, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, - 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x40, 0x16 -]; - -#[test] -fn test_ikev2_init_req() { - let empty = &b""[..]; - let bytes = &IKEV2_INIT_REQ[0..28]; - let expected = Ok((empty,IkeV2Header{ - init_spi: 0x01f8c3d4bb773f2f, - resp_spi: 0x0, - next_payload: IkePayloadType::SecurityAssociation, - maj_ver: 2, - min_ver: 0, - exch_type: IkeExchangeType::IKE_SA_INIT, - flags: 0x8, - msg_id: 0, - length: 328, - })); - let res = parse_ikev2_header(&bytes); - assert_eq!(res, expected); -} + use crate::ikev2_parser::*; + + static IKEV2_INIT_REQ: &'static [u8] = &[ + 0x01, 0xf8, 0xc3, 0xd4, 0xbb, 0x77, 0x3f, 0x2f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x21, 0x20, 0x22, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x48, 0x22, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x00, 0x2c, 0x01, 0x01, 0x00, 0x04, 0x03, 0x00, 0x00, 0x0c, 0x01, + 0x00, 0x00, 0x14, 0x80, 0x0e, 0x00, 0x80, 0x03, 0x00, 0x00, 0x08, 0x03, 0x00, 0x00, 0x0c, + 0x03, 0x00, 0x00, 0x08, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x08, 0x04, 0x00, 0x00, + 0x1e, 0x28, 0x00, 0x00, 0x88, 0x00, 0x1e, 0x00, 0x00, 0x8f, 0xe6, 0xf3, 0x6e, 0x88, 0x7b, + 0x18, 0x9b, 0x5e, 0xce, 0xf2, 0x56, 0xf9, 0x8d, 0x76, 0xaa, 0xcb, 0x07, 0xb3, 0xb9, 0x58, + 0xee, 0x73, 0xea, 0x7b, 0x73, 0xb1, 0x04, 0x7e, 0xa4, 0x2a, 0x4e, 0x44, 0x1f, 0xb9, 0x3e, + 0xf9, 0xa9, 0xab, 0x0c, 0x54, 0x5a, 0xa7, 0x46, 0x2e, 0x58, 0x3c, 0x06, 0xb2, 0xed, 0x91, + 0x8d, 0x11, 0xca, 0x67, 0xdb, 0x21, 0x6b, 0xb8, 0xad, 0xbf, 0x57, 0x3f, 0xba, 0x5a, 0xa6, + 0x7d, 0x49, 0x83, 0x4b, 0xa9, 0x93, 0x6f, 0x4c, 0xe9, 0x66, 0xcd, 0x57, 0x5c, 0xba, 0x07, + 0x42, 0xfa, 0x0b, 0xe8, 0xb9, 0xd0, 0x25, 0xc4, 0xb9, 0xdf, 0x29, 0xd7, 0xe4, 0x6e, 0xd6, + 0x54, 0x78, 0xaa, 0x95, 0x02, 0xbf, 0x25, 0x55, 0x71, 0xfa, 0x9e, 0xcb, 0x05, 0xea, 0x8f, + 0x7b, 0x14, 0x0e, 0x1d, 0xdf, 0xb4, 0x03, 0x5f, 0x2d, 0x21, 0x66, 0x58, 0x6e, 0x42, 0x72, + 0x32, 0x03, 0x29, 0x00, 0x00, 0x24, 0xe3, 0x3b, 0x52, 0xaa, 0x6f, 0x6d, 0x62, 0x87, 0x16, + 0xd7, 0xab, 0xc6, 0x45, 0xa6, 0xcc, 0x97, 0x07, 0x43, 0x3d, 0x85, 0x83, 0xde, 0xab, 0x97, + 0xdb, 0xbf, 0x08, 0xce, 0x0f, 0xad, 0x59, 0x71, 0x29, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x40, + 0x04, 0xcc, 0xc0, 0x64, 0x5c, 0x1e, 0xeb, 0xc2, 0x1d, 0x09, 0x2b, 0xf0, 0x7f, 0xca, 0x34, + 0xc3, 0xe6, 0x2b, 0x20, 0xec, 0x8f, 0x29, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x40, 0x05, 0x15, + 0x39, 0x75, 0x77, 0xf5, 0x54, 0x87, 0xa3, 0x8f, 0xd8, 0xaf, 0x70, 0xb0, 0x9c, 0x20, 0x9c, + 0xff, 0x4a, 0x37, 0xd1, 0x29, 0x00, 0x00, 0x10, 0x00, 0x00, 0x40, 0x2f, 0x00, 0x01, 0x00, + 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x40, 0x16, + ]; + + #[test] + fn test_ikev2_init_req() { + let empty = &b""[..]; + let bytes = &IKEV2_INIT_REQ[0..28]; + let expected = Ok(( + empty, + IkeV2Header { + init_spi: 0x01f8c3d4bb773f2f, + resp_spi: 0x0, + next_payload: IkePayloadType::SecurityAssociation, + maj_ver: 2, + min_ver: 0, + exch_type: IkeExchangeType::IKE_SA_INIT, + flags: 0x8, + msg_id: 0, + length: 328, + }, + )); + let res = parse_ikev2_header(&bytes); + assert_eq!(res, expected); + } -static IKEV2_INIT_RESP: &'static [u8] = include_bytes!("../assets/ike-sa-init-resp.bin"); - -#[test] -fn test_ikev2_init_resp() { - let bytes = IKEV2_INIT_RESP; - let (rem, ref hdr) = parse_ikev2_header(&bytes).expect("parsing header failed"); - let (rem2, res_p) = parse_ikev2_payload_list(rem, hdr.next_payload).expect("parsing payload failed"); - assert!(rem2.is_empty()); - let p = res_p.expect("parsing payload failed"); - // there are 5 items + dummy => 6 - assert_eq!(p.len(), 6); - // first one is always dummy - assert_eq!(p[0].content, IkeV2PayloadContent::Dummy); -} + static IKEV2_INIT_RESP: &'static [u8] = include_bytes!("../assets/ike-sa-init-resp.bin"); + + #[test] + fn test_ikev2_init_resp() { + let bytes = IKEV2_INIT_RESP; + let (rem, ref hdr) = parse_ikev2_header(&bytes).expect("parsing header failed"); + let (rem2, res_p) = + parse_ikev2_payload_list(rem, hdr.next_payload).expect("parsing payload failed"); + assert!(rem2.is_empty()); + let p = res_p.expect("parsing payload failed"); + // there are 5 items + dummy => 6 + assert_eq!(p.len(), 6); + // first one is always dummy + assert_eq!(p[0].content, IkeV2PayloadContent::Dummy); + } -static IKEV2_PAYLOAD_SA: &'static [u8] = &[ - 0x22, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x24, 0x01, 0x01, 0x00, 0x03, 0x03, 0x00, 0x00, 0x0c, - 0x01, 0x00, 0x00, 0x14, 0x80, 0x0e, 0x00, 0x80, 0x03, 0x00, 0x00, 0x08, 0x02, 0x00, 0x00, 0x05, - 0x00, 0x00, 0x00, 0x08, 0x04, 0x00, 0x00, 0x1e -]; - -#[test] -fn test_ikev2_payload_sa() { - let bytes = IKEV2_PAYLOAD_SA; - let expected1 = IkeV2GenericPayload{ - hdr: IkeV2PayloadHeader { - next_payload_type: IkePayloadType::KeyExchange, - critical: false, - reserved: 0, - payload_length: 40, - }, - payload: &bytes[4..], - }; - let (_, res) = parse_ikev2_payload_generic(&bytes).expect("Failed to parse"); - assert_eq!(res, expected1); - let attrs1 = &[0x80, 0x0e, 0x00, 0x80]; - let expected2 = IkeV2PayloadContent::SA(vec![ - IkeV2Proposal { + static IKEV2_PAYLOAD_SA: &'static [u8] = &[ + 0x22, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x24, 0x01, 0x01, 0x00, 0x03, 0x03, 0x00, 0x00, + 0x0c, 0x01, 0x00, 0x00, 0x14, 0x80, 0x0e, 0x00, 0x80, 0x03, 0x00, 0x00, 0x08, 0x02, 0x00, + 0x00, 0x05, 0x00, 0x00, 0x00, 0x08, 0x04, 0x00, 0x00, 0x1e, + ]; + + #[test] + fn test_ikev2_payload_sa() { + let bytes = IKEV2_PAYLOAD_SA; + let expected1 = IkeV2GenericPayload { + hdr: IkeV2PayloadHeader { + next_payload_type: IkePayloadType::KeyExchange, + critical: false, + reserved: 0, + payload_length: 40, + }, + payload: &bytes[4..], + }; + let (_, res) = parse_ikev2_payload_generic(&bytes).expect("Failed to parse"); + assert_eq!(res, expected1); + let attrs1 = &[0x80, 0x0e, 0x00, 0x80]; + let expected2 = IkeV2PayloadContent::SA(vec![IkeV2Proposal { last: 0, reserved: 0, proposal_length: 36, @@ -523,7 +559,7 @@ fn test_ikev2_payload_sa() { num_transforms: 3, spi: None, transforms: vec![ - IkeV2RawTransform{ + IkeV2RawTransform { last: 3, reserved1: 0, transform_length: 12, @@ -532,7 +568,7 @@ fn test_ikev2_payload_sa() { transform_id: 20, attributes: Some(attrs1), }, - IkeV2RawTransform{ + IkeV2RawTransform { last: 3, reserved1: 0, transform_length: 8, @@ -541,7 +577,7 @@ fn test_ikev2_payload_sa() { transform_id: 5, attributes: None, }, - IkeV2RawTransform{ + IkeV2RawTransform { last: 0, reserved1: 0, transform_length: 8, @@ -551,21 +587,19 @@ fn test_ikev2_payload_sa() { attributes: None, }, ], - }, - ] - ); + }]); - let (rem, res2) = parse_ikev2_payload_sa(res.payload,0).expect("Failed to parse"); - assert!(rem.is_empty()); - assert_eq!(res2, expected2); -} + let (rem, res2) = parse_ikev2_payload_sa(res.payload, 0).expect("Failed to parse"); + assert!(rem.is_empty()); + assert_eq!(res2, expected2); + } -#[test] -fn test_ikev2_parse_payload_many() { - // let empty = &b""[..]; - let bytes = &IKEV2_INIT_REQ[28..]; - let res = parse_ikev2_payload_list(&bytes, IkePayloadType::SecurityAssociation); - println!("{:?}",res); -} + #[test] + fn test_ikev2_parse_payload_many() { + // let empty = &b""[..]; + let bytes = &IKEV2_INIT_REQ[28..]; + let res = parse_ikev2_payload_list(&bytes, IkePayloadType::SecurityAssociation); + println!("{:?}", res); + } } diff --git a/src/ikev2_transforms.rs b/src/ikev2_transforms.rs index a87dc16..d801284 100644 --- a/src/ikev2_transforms.rs +++ b/src/ikev2_transforms.rs @@ -9,14 +9,13 @@ pub struct IkeTransformType(pub u8); #[allow(non_upper_case_globals)] impl IkeTransformType { - pub const EncryptionAlgorithm : IkeTransformType = IkeTransformType(1); - pub const PseudoRandomFunction : IkeTransformType = IkeTransformType(2); - pub const IntegrityAlgorithm : IkeTransformType = IkeTransformType(3); - pub const DiffieHellmanGroup : IkeTransformType = IkeTransformType(4); - pub const ExtendedSequenceNumbers : IkeTransformType = IkeTransformType(5); + pub const EncryptionAlgorithm: IkeTransformType = IkeTransformType(1); + pub const PseudoRandomFunction: IkeTransformType = IkeTransformType(2); + pub const IntegrityAlgorithm: IkeTransformType = IkeTransformType(3); + pub const DiffieHellmanGroup: IkeTransformType = IkeTransformType(4); + pub const ExtendedSequenceNumbers: IkeTransformType = IkeTransformType(5); } - /// Encryption values /// /// Defined in [RFC7296](https://tools.ietf.org/html/rfc7296) section 3.3.2 @@ -27,55 +26,59 @@ pub struct IkeTransformEncType(pub u16); impl IkeTransformEncType { // 0 is reserved - pub const ENCR_DES_IV64 : IkeTransformEncType = IkeTransformEncType(1); - pub const ENCR_DES : IkeTransformEncType = IkeTransformEncType(2); - pub const ENCR_3DES : IkeTransformEncType = IkeTransformEncType(3); - pub const ENCR_RC5 : IkeTransformEncType = IkeTransformEncType(4); - pub const ENCR_IDEA : IkeTransformEncType = IkeTransformEncType(5); - pub const ENCR_CAST : IkeTransformEncType = IkeTransformEncType(6); - pub const ENCR_BLOWFISH : IkeTransformEncType = IkeTransformEncType(7); - pub const ENCR_3IDEA : IkeTransformEncType = IkeTransformEncType(8); - pub const ENCR_DES_IV32 : IkeTransformEncType = IkeTransformEncType(9); + pub const ENCR_DES_IV64: IkeTransformEncType = IkeTransformEncType(1); + pub const ENCR_DES: IkeTransformEncType = IkeTransformEncType(2); + pub const ENCR_3DES: IkeTransformEncType = IkeTransformEncType(3); + pub const ENCR_RC5: IkeTransformEncType = IkeTransformEncType(4); + pub const ENCR_IDEA: IkeTransformEncType = IkeTransformEncType(5); + pub const ENCR_CAST: IkeTransformEncType = IkeTransformEncType(6); + pub const ENCR_BLOWFISH: IkeTransformEncType = IkeTransformEncType(7); + pub const ENCR_3IDEA: IkeTransformEncType = IkeTransformEncType(8); + pub const ENCR_DES_IV32: IkeTransformEncType = IkeTransformEncType(9); // 10 is reserved - pub const ENCR_NULL : IkeTransformEncType = IkeTransformEncType(11); - pub const ENCR_AES_CBC : IkeTransformEncType = IkeTransformEncType(12); - pub const ENCR_AES_CTR : IkeTransformEncType = IkeTransformEncType(13); - pub const ENCR_AES_CCM_8 : IkeTransformEncType = IkeTransformEncType(14); - pub const ENCR_AES_CCM_12 : IkeTransformEncType = IkeTransformEncType(15); - pub const ENCR_AES_CCM_16 : IkeTransformEncType = IkeTransformEncType(16); + pub const ENCR_NULL: IkeTransformEncType = IkeTransformEncType(11); + pub const ENCR_AES_CBC: IkeTransformEncType = IkeTransformEncType(12); + pub const ENCR_AES_CTR: IkeTransformEncType = IkeTransformEncType(13); + pub const ENCR_AES_CCM_8: IkeTransformEncType = IkeTransformEncType(14); + pub const ENCR_AES_CCM_12: IkeTransformEncType = IkeTransformEncType(15); + pub const ENCR_AES_CCM_16: IkeTransformEncType = IkeTransformEncType(16); // 17 is unassigned - pub const ENCR_AES_GCM_8 : IkeTransformEncType = IkeTransformEncType(18); - pub const ENCR_AES_GCM_12 : IkeTransformEncType = IkeTransformEncType(19); - pub const ENCR_AES_GCM_16 : IkeTransformEncType = IkeTransformEncType(20); - pub const ENCR_NULL_AUTH_AES_GMAC : IkeTransformEncType = IkeTransformEncType(21); + pub const ENCR_AES_GCM_8: IkeTransformEncType = IkeTransformEncType(18); + pub const ENCR_AES_GCM_12: IkeTransformEncType = IkeTransformEncType(19); + pub const ENCR_AES_GCM_16: IkeTransformEncType = IkeTransformEncType(20); + pub const ENCR_NULL_AUTH_AES_GMAC: IkeTransformEncType = IkeTransformEncType(21); // 22 is reserved for IEEE P1619 XTS-AES - pub const ENCR_CAMELLIA_CBC : IkeTransformEncType = IkeTransformEncType(23); - pub const ENCR_CAMELLIA_CTR : IkeTransformEncType = IkeTransformEncType(24); - pub const ENCR_CAMELLIA_CCM_8 : IkeTransformEncType = IkeTransformEncType(25); - pub const ENCR_CAMELLIA_CCM_12 : IkeTransformEncType = IkeTransformEncType(26); - pub const ENCR_CAMELLIA_CCM_16 : IkeTransformEncType = IkeTransformEncType(27); - pub const ENCR_CHACHA20_POLY1305 : IkeTransformEncType = IkeTransformEncType(28); // [RFC7634] + pub const ENCR_CAMELLIA_CBC: IkeTransformEncType = IkeTransformEncType(23); + pub const ENCR_CAMELLIA_CTR: IkeTransformEncType = IkeTransformEncType(24); + pub const ENCR_CAMELLIA_CCM_8: IkeTransformEncType = IkeTransformEncType(25); + pub const ENCR_CAMELLIA_CCM_12: IkeTransformEncType = IkeTransformEncType(26); + pub const ENCR_CAMELLIA_CCM_16: IkeTransformEncType = IkeTransformEncType(27); + pub const ENCR_CHACHA20_POLY1305: IkeTransformEncType = IkeTransformEncType(28); // [RFC7634] } impl IkeTransformEncType { pub fn is_aead(&self) -> bool { match *self { - IkeTransformEncType::ENCR_AES_CCM_8 | - IkeTransformEncType::ENCR_AES_CCM_12 | - IkeTransformEncType::ENCR_AES_CCM_16 | - IkeTransformEncType::ENCR_AES_GCM_8 | - IkeTransformEncType::ENCR_AES_GCM_12 | - IkeTransformEncType::ENCR_AES_GCM_16 | - IkeTransformEncType::ENCR_CAMELLIA_CCM_8 | - IkeTransformEncType::ENCR_CAMELLIA_CCM_12 | - IkeTransformEncType::ENCR_CAMELLIA_CCM_16 | - IkeTransformEncType::ENCR_CHACHA20_POLY1305 => true, + IkeTransformEncType::ENCR_AES_CCM_8 + | IkeTransformEncType::ENCR_AES_CCM_12 + | IkeTransformEncType::ENCR_AES_CCM_16 + | IkeTransformEncType::ENCR_AES_GCM_8 + | IkeTransformEncType::ENCR_AES_GCM_12 + | IkeTransformEncType::ENCR_AES_GCM_16 + | IkeTransformEncType::ENCR_CAMELLIA_CCM_8 + | IkeTransformEncType::ENCR_CAMELLIA_CCM_12 + | IkeTransformEncType::ENCR_CAMELLIA_CCM_16 + | IkeTransformEncType::ENCR_CHACHA20_POLY1305 => true, _ => false, } } - pub fn is_unassigned(&self) -> bool { self.0 >= 23 && self.0 <= 1023 } - pub fn is_private_use(&self) -> bool { self.0 >= 1024 } + pub fn is_unassigned(&self) -> bool { + self.0 >= 23 && self.0 <= 1023 + } + pub fn is_private_use(&self) -> bool { + self.0 >= 1024 + } } /// Pseudo-Random Function values @@ -87,18 +90,22 @@ impl IkeTransformEncType { pub struct IkeTransformPRFType(pub u16); impl IkeTransformPRFType { - pub const PRF_NULL : IkeTransformPRFType = IkeTransformPRFType(0); - pub const PRF_HMAC_MD5 : IkeTransformPRFType = IkeTransformPRFType(1); - pub const PRF_HMAC_SHA1 : IkeTransformPRFType = IkeTransformPRFType(2); - pub const PRF_HMAC_TIGER : IkeTransformPRFType = IkeTransformPRFType(3); - pub const PRF_AES128_XCBC : IkeTransformPRFType = IkeTransformPRFType(4); - pub const PRF_HMAC_SHA2_256 : IkeTransformPRFType = IkeTransformPRFType(5); - pub const PRF_HMAC_SHA2_384 : IkeTransformPRFType = IkeTransformPRFType(6); - pub const PRF_HMAC_SHA2_512 : IkeTransformPRFType = IkeTransformPRFType(7); - pub const PRF_AES128_CMAC : IkeTransformPRFType = IkeTransformPRFType(8); + pub const PRF_NULL: IkeTransformPRFType = IkeTransformPRFType(0); + pub const PRF_HMAC_MD5: IkeTransformPRFType = IkeTransformPRFType(1); + pub const PRF_HMAC_SHA1: IkeTransformPRFType = IkeTransformPRFType(2); + pub const PRF_HMAC_TIGER: IkeTransformPRFType = IkeTransformPRFType(3); + pub const PRF_AES128_XCBC: IkeTransformPRFType = IkeTransformPRFType(4); + pub const PRF_HMAC_SHA2_256: IkeTransformPRFType = IkeTransformPRFType(5); + pub const PRF_HMAC_SHA2_384: IkeTransformPRFType = IkeTransformPRFType(6); + pub const PRF_HMAC_SHA2_512: IkeTransformPRFType = IkeTransformPRFType(7); + pub const PRF_AES128_CMAC: IkeTransformPRFType = IkeTransformPRFType(8); - pub fn is_unassigned(&self) -> bool { self.0 >= 9 && self.0 <= 1023 } - pub fn is_private_use(&self) -> bool { self.0 >= 1024 } + pub fn is_unassigned(&self) -> bool { + self.0 >= 9 && self.0 <= 1023 + } + pub fn is_private_use(&self) -> bool { + self.0 >= 1024 + } } /// Authentication / Integrity values @@ -108,24 +115,28 @@ impl IkeTransformPRFType { pub struct IkeTransformAuthType(pub u16); impl IkeTransformAuthType { - pub const NONE : IkeTransformAuthType = IkeTransformAuthType(0); - pub const AUTH_HMAC_MD5_96 : IkeTransformAuthType = IkeTransformAuthType(1); - pub const AUTH_HMAC_SHA1_96 : IkeTransformAuthType = IkeTransformAuthType(2); - pub const AUTH_DES_MAC : IkeTransformAuthType = IkeTransformAuthType(3); - pub const AUTH_KPDK_MD5 : IkeTransformAuthType = IkeTransformAuthType(4); - pub const AUTH_AES_XCBC_96 : IkeTransformAuthType = IkeTransformAuthType(5); - pub const AUTH_HMAC_MD5_128 : IkeTransformAuthType = IkeTransformAuthType(6); - pub const AUTH_HMAC_SHA1_160 : IkeTransformAuthType = IkeTransformAuthType(7); - pub const AUTH_AES_CMAC_96 : IkeTransformAuthType = IkeTransformAuthType(8); - pub const AUTH_AES_128_GMAC : IkeTransformAuthType = IkeTransformAuthType(9); - pub const AUTH_AES_192_GMAC : IkeTransformAuthType = IkeTransformAuthType(10); - pub const AUTH_AES_256_GMAC : IkeTransformAuthType = IkeTransformAuthType(11); - pub const AUTH_HMAC_SHA2_256_128 : IkeTransformAuthType = IkeTransformAuthType(12); - pub const AUTH_HMAC_SHA2_384_192 : IkeTransformAuthType = IkeTransformAuthType(13); - pub const AUTH_HMAC_SHA2_512_256 : IkeTransformAuthType = IkeTransformAuthType(14); + pub const NONE: IkeTransformAuthType = IkeTransformAuthType(0); + pub const AUTH_HMAC_MD5_96: IkeTransformAuthType = IkeTransformAuthType(1); + pub const AUTH_HMAC_SHA1_96: IkeTransformAuthType = IkeTransformAuthType(2); + pub const AUTH_DES_MAC: IkeTransformAuthType = IkeTransformAuthType(3); + pub const AUTH_KPDK_MD5: IkeTransformAuthType = IkeTransformAuthType(4); + pub const AUTH_AES_XCBC_96: IkeTransformAuthType = IkeTransformAuthType(5); + pub const AUTH_HMAC_MD5_128: IkeTransformAuthType = IkeTransformAuthType(6); + pub const AUTH_HMAC_SHA1_160: IkeTransformAuthType = IkeTransformAuthType(7); + pub const AUTH_AES_CMAC_96: IkeTransformAuthType = IkeTransformAuthType(8); + pub const AUTH_AES_128_GMAC: IkeTransformAuthType = IkeTransformAuthType(9); + pub const AUTH_AES_192_GMAC: IkeTransformAuthType = IkeTransformAuthType(10); + pub const AUTH_AES_256_GMAC: IkeTransformAuthType = IkeTransformAuthType(11); + pub const AUTH_HMAC_SHA2_256_128: IkeTransformAuthType = IkeTransformAuthType(12); + pub const AUTH_HMAC_SHA2_384_192: IkeTransformAuthType = IkeTransformAuthType(13); + pub const AUTH_HMAC_SHA2_512_256: IkeTransformAuthType = IkeTransformAuthType(14); - pub fn is_unassigned(&self) -> bool { self.0 >= 15 && self.0 <= 1023 } - pub fn is_private_use(&self) -> bool { self.0 >= 1024 } + pub fn is_unassigned(&self) -> bool { + self.0 >= 15 && self.0 <= 1023 + } + pub fn is_private_use(&self) -> bool { + self.0 >= 1024 + } } /// Diffie-Hellman values @@ -138,32 +149,36 @@ pub struct IkeTransformDHType(pub u16); #[allow(non_upper_case_globals)] impl IkeTransformDHType { - pub const None : IkeTransformDHType = IkeTransformDHType(0); - pub const Modp768 : IkeTransformDHType = IkeTransformDHType(1); - pub const Modp1024 : IkeTransformDHType = IkeTransformDHType(2); - pub const Modp1536 : IkeTransformDHType = IkeTransformDHType(5); - pub const Modp2048 : IkeTransformDHType = IkeTransformDHType(14); - pub const Modp3072 : IkeTransformDHType = IkeTransformDHType(15); - pub const Modp4096 : IkeTransformDHType = IkeTransformDHType(16); - pub const Modp6144 : IkeTransformDHType = IkeTransformDHType(17); - pub const Modp8192 : IkeTransformDHType = IkeTransformDHType(18); - pub const Ecp256 : IkeTransformDHType = IkeTransformDHType(19); - pub const Ecp384 : IkeTransformDHType = IkeTransformDHType(20); - pub const Ecp521 : IkeTransformDHType = IkeTransformDHType(21); - pub const Modp1024s160 : IkeTransformDHType = IkeTransformDHType(22); - pub const Modp2048s224 : IkeTransformDHType = IkeTransformDHType(23); - pub const Modp2048s256 : IkeTransformDHType = IkeTransformDHType(24); - pub const Ecp192 : IkeTransformDHType = IkeTransformDHType(25); - pub const Ecp224 : IkeTransformDHType = IkeTransformDHType(26); - pub const BrainpoolP224r1 : IkeTransformDHType = IkeTransformDHType(27); - pub const BrainpoolP256r1 : IkeTransformDHType = IkeTransformDHType(28); - pub const BrainpoolP384r1 : IkeTransformDHType = IkeTransformDHType(29); - pub const BrainpoolP512r1 : IkeTransformDHType = IkeTransformDHType(30); - pub const Curve25519 : IkeTransformDHType = IkeTransformDHType(31); - pub const Curve448 : IkeTransformDHType = IkeTransformDHType(32); + pub const None: IkeTransformDHType = IkeTransformDHType(0); + pub const Modp768: IkeTransformDHType = IkeTransformDHType(1); + pub const Modp1024: IkeTransformDHType = IkeTransformDHType(2); + pub const Modp1536: IkeTransformDHType = IkeTransformDHType(5); + pub const Modp2048: IkeTransformDHType = IkeTransformDHType(14); + pub const Modp3072: IkeTransformDHType = IkeTransformDHType(15); + pub const Modp4096: IkeTransformDHType = IkeTransformDHType(16); + pub const Modp6144: IkeTransformDHType = IkeTransformDHType(17); + pub const Modp8192: IkeTransformDHType = IkeTransformDHType(18); + pub const Ecp256: IkeTransformDHType = IkeTransformDHType(19); + pub const Ecp384: IkeTransformDHType = IkeTransformDHType(20); + pub const Ecp521: IkeTransformDHType = IkeTransformDHType(21); + pub const Modp1024s160: IkeTransformDHType = IkeTransformDHType(22); + pub const Modp2048s224: IkeTransformDHType = IkeTransformDHType(23); + pub const Modp2048s256: IkeTransformDHType = IkeTransformDHType(24); + pub const Ecp192: IkeTransformDHType = IkeTransformDHType(25); + pub const Ecp224: IkeTransformDHType = IkeTransformDHType(26); + pub const BrainpoolP224r1: IkeTransformDHType = IkeTransformDHType(27); + pub const BrainpoolP256r1: IkeTransformDHType = IkeTransformDHType(28); + pub const BrainpoolP384r1: IkeTransformDHType = IkeTransformDHType(29); + pub const BrainpoolP512r1: IkeTransformDHType = IkeTransformDHType(30); + pub const Curve25519: IkeTransformDHType = IkeTransformDHType(31); + pub const Curve448: IkeTransformDHType = IkeTransformDHType(32); - pub fn is_unassigned(&self) -> bool { self.0 >= 15 && self.0 <= 1023 } - pub fn is_private_use(&self) -> bool { self.0 >= 1024 } + pub fn is_unassigned(&self) -> bool { + self.0 >= 15 && self.0 <= 1023 + } + pub fn is_private_use(&self) -> bool { + self.0 >= 1024 + } } /// Extended Sequence Number values @@ -174,8 +189,8 @@ pub struct IkeTransformESNType(pub u16); #[allow(non_upper_case_globals)] impl IkeTransformESNType { - pub const NoESN : IkeTransformESNType = IkeTransformESNType(0); - pub const ESN : IkeTransformESNType = IkeTransformESNType(1); + pub const NoESN: IkeTransformESNType = IkeTransformESNType(0); + pub const ESN: IkeTransformESNType = IkeTransformESNType(1); } /// Raw representation of a transform (cryptographic algorithm) and parameters @@ -183,7 +198,7 @@ impl IkeTransformESNType { /// Use the `From` method to convert it to a [`IkeV2Transform`](enum.IkeV2Transform.html) /// /// Defined in [RFC7296](https://tools.ietf.org/html/rfc7296) section 3.3 -#[derive(Clone,PartialEq)] +#[derive(Clone, PartialEq)] pub struct IkeV2RawTransform<'a> { pub last: u8, pub reserved1: u8, @@ -191,7 +206,7 @@ pub struct IkeV2RawTransform<'a> { pub transform_type: IkeTransformType, pub reserved2: u8, pub transform_id: u16, - pub attributes: Option<&'a[u8]>, + pub attributes: Option<&'a [u8]>, } /// IKEv2 Transform (cryptographic algorithm) @@ -200,7 +215,7 @@ pub struct IkeV2RawTransform<'a> { /// etc.). To store the parameters, use [`IkeV2RawTransform`](struct.IkeV2RawTransform.html). /// /// Defined in [RFC7296](https://tools.ietf.org/html/rfc7296) section 3.3 -#[derive(Debug,PartialEq)] +#[derive(Debug, PartialEq)] pub enum IkeV2Transform { Encryption(IkeTransformEncType), PRF(IkeTransformPRFType), @@ -208,7 +223,7 @@ pub enum IkeV2Transform { DH(IkeTransformDHType), ESN(IkeTransformESNType), /// Unknown tranform (type,id) - Unknown(IkeTransformType,u16), + Unknown(IkeTransformType, u16), } impl<'a> From<&'a IkeV2RawTransform<'a>> for IkeV2Transform { @@ -216,20 +231,20 @@ impl<'a> From<&'a IkeV2RawTransform<'a>> for IkeV2Transform { match r.transform_type { IkeTransformType::EncryptionAlgorithm => { IkeV2Transform::Encryption(IkeTransformEncType(r.transform_id)) - }, + } IkeTransformType::PseudoRandomFunction => { IkeV2Transform::PRF(IkeTransformPRFType(r.transform_id)) - }, + } IkeTransformType::IntegrityAlgorithm => { IkeV2Transform::Auth(IkeTransformAuthType(r.transform_id)) - }, + } IkeTransformType::DiffieHellmanGroup => { IkeV2Transform::DH(IkeTransformDHType(r.transform_id)) - }, + } IkeTransformType::ExtendedSequenceNumbers => { IkeV2Transform::ESN(IkeTransformESNType(r.transform_id)) - }, - _ => IkeV2Transform::Unknown(r.transform_type,r.transform_id) + } + _ => IkeV2Transform::Unknown(r.transform_type, r.transform_id), } } } @@ -256,15 +271,15 @@ impl fmt::Debug for IkeTransformType { impl fmt::Debug for IkeTransformEncType { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self.0 { - 1 => f.write_str("ENCR_DES_IV64"), - 2 => f.write_str("ENCR_DES"), - 3 => f.write_str("ENCR_3DES"), - 4 => f.write_str("ENCR_RC5"), - 5 => f.write_str("ENCR_IDEA"), - 6 => f.write_str("ENCR_CAST"), - 7 => f.write_str("ENCR_BLOWFISH"), - 8 => f.write_str("ENCR_3IDEA"), - 9 => f.write_str("ENCR_DES_IV32"), + 1 => f.write_str("ENCR_DES_IV64"), + 2 => f.write_str("ENCR_DES"), + 3 => f.write_str("ENCR_3DES"), + 4 => f.write_str("ENCR_RC5"), + 5 => f.write_str("ENCR_IDEA"), + 6 => f.write_str("ENCR_CAST"), + 7 => f.write_str("ENCR_BLOWFISH"), + 8 => f.write_str("ENCR_3IDEA"), + 9 => f.write_str("ENCR_DES_IV32"), 11 => f.write_str("ENCR_NULL"), 12 => f.write_str("ENCR_AES_CBC"), 13 => f.write_str("ENCR_AES_CTR"), @@ -281,7 +296,7 @@ impl fmt::Debug for IkeTransformEncType { 26 => f.write_str("ENCR_CAMELLIA_CCM_12"), 27 => f.write_str("ENCR_CAMELLIA_CCM_16"), 28 => f.write_str("ENCR_CHACHA20_POLY1305"), - n => f.debug_tuple("IkeTransformEncType").field(&n).finish(), + n => f.debug_tuple("IkeTransformEncType").field(&n).finish(), } } } @@ -289,16 +304,16 @@ impl fmt::Debug for IkeTransformEncType { impl fmt::Debug for IkeTransformPRFType { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self.0 { - 0 => f.write_str("Null"), - 1 => f.write_str("PRF_HMAC_MD5"), - 2 => f.write_str("PRF_HMAC_SHA1"), - 3 => f.write_str("PRF_HMAC_TIGER"), - 4 => f.write_str("PRF_AES128_XCBC"), - 5 => f.write_str("PRF_HMAC_SHA2_256"), - 6 => f.write_str("PRF_HMAC_SHA2_384"), - 7 => f.write_str("PRF_HMAC_SHA2_512"), - 8 => f.write_str("PRF_AES128_CMAC"), - n => f.debug_tuple("IkeTransformPRFType").field(&n).finish(), + 0 => f.write_str("Null"), + 1 => f.write_str("PRF_HMAC_MD5"), + 2 => f.write_str("PRF_HMAC_SHA1"), + 3 => f.write_str("PRF_HMAC_TIGER"), + 4 => f.write_str("PRF_AES128_XCBC"), + 5 => f.write_str("PRF_HMAC_SHA2_256"), + 6 => f.write_str("PRF_HMAC_SHA2_384"), + 7 => f.write_str("PRF_HMAC_SHA2_512"), + 8 => f.write_str("PRF_AES128_CMAC"), + n => f.debug_tuple("IkeTransformPRFType").field(&n).finish(), } } } @@ -306,22 +321,22 @@ impl fmt::Debug for IkeTransformPRFType { impl fmt::Debug for IkeTransformAuthType { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self.0 { - 0 => f.write_str("NONE"), - 1 => f.write_str("AUTH_HMAC_MD5_96"), - 2 => f.write_str("AUTH_HMAC_SHA1_96"), - 3 => f.write_str("AUTH_DES_MAC"), - 4 => f.write_str("AUTH_KPDK_MD5"), - 5 => f.write_str("AUTH_AES_XCBC_96"), - 6 => f.write_str("AUTH_HMAC_MD5_128"), - 7 => f.write_str("AUTH_HMAC_SHA1_128"), - 8 => f.write_str("AUTH_AES_CMAC_96"), - 9 => f.write_str("AUTH_AES_128_GMAC"), + 0 => f.write_str("NONE"), + 1 => f.write_str("AUTH_HMAC_MD5_96"), + 2 => f.write_str("AUTH_HMAC_SHA1_96"), + 3 => f.write_str("AUTH_DES_MAC"), + 4 => f.write_str("AUTH_KPDK_MD5"), + 5 => f.write_str("AUTH_AES_XCBC_96"), + 6 => f.write_str("AUTH_HMAC_MD5_128"), + 7 => f.write_str("AUTH_HMAC_SHA1_128"), + 8 => f.write_str("AUTH_AES_CMAC_96"), + 9 => f.write_str("AUTH_AES_128_GMAC"), 10 => f.write_str("AUTH_AES_192_GMAC"), 11 => f.write_str("AUTH_AES_256_GMAC"), 12 => f.write_str("AUTH_HMAC_SHA2_256_128"), 13 => f.write_str("AUTH_HMAC_SHA2_384_192"), 14 => f.write_str("AUTH_HMAC_SHA2_512_256"), - n => f.debug_tuple("IkeTransformAuthType").field(&n).finish(), + n => f.debug_tuple("IkeTransformAuthType").field(&n).finish(), } } } @@ -329,10 +344,10 @@ impl fmt::Debug for IkeTransformAuthType { impl fmt::Debug for IkeTransformDHType { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self.0 { - 0 => f.write_str("None"), - 1 => f.write_str("768-bit MODP Group"), - 2 => f.write_str("1024-bit MODP Group"), - 5 => f.write_str("1536-bit MODP Group"), + 0 => f.write_str("None"), + 1 => f.write_str("768-bit MODP Group"), + 2 => f.write_str("1024-bit MODP Group"), + 5 => f.write_str("1536-bit MODP Group"), 14 => f.write_str("2048-bit MODP Group"), 15 => f.write_str("3072-bit MODP Group"), 16 => f.write_str("4096-bit MODP Group"), @@ -352,7 +367,7 @@ impl fmt::Debug for IkeTransformDHType { 30 => f.write_str("brainpoolP512r1"), 31 => f.write_str("Curve25519"), 32 => f.write_str("Curve448"), - n => f.debug_tuple("IkeTransformDHType").field(&n).finish(), + n => f.debug_tuple("IkeTransformDHType").field(&n).finish(), } } } diff --git a/src/lib.rs b/src/lib.rs index f190c78..1eb7791 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -60,17 +60,17 @@ extern crate rusticata_macros; extern crate nom; mod ikev2; -pub use ikev2::*; +pub use crate::ikev2::*; mod ikev2_notify; -pub use ikev2_notify::*; +pub use crate::ikev2_notify::*; mod ikev2_transforms; -pub use ikev2_transforms::*; +pub use crate::ikev2_transforms::*; mod ikev2_parser; -pub use ikev2_parser::*; +pub use crate::ikev2_parser::*; mod ikev2_debug; -pub use ikev2_debug::*; +pub use crate::ikev2_debug::*; mod esp; -pub use esp::*; +pub use crate::esp::*; diff --git a/tests/ikev2.rs b/tests/ikev2.rs index bb9fcac..60ea373 100644 --- a/tests/ikev2.rs +++ b/tests/ikev2.rs @@ -1,93 +1,98 @@ -extern crate nom; extern crate ipsec_parser; +extern crate nom; mod ikev2 { -use ipsec_parser::*; + use ipsec_parser::*; -static IKEV2_MSG: &'static [u8] = &[ - 0x00, 0x00, 0x00, 0x00, 0xbc, 0xa1, 0x93, 0x7a, 0x7c, 0x2f, 0xf5, 0xb9, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x21, 0x20, 0x22, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x2c, - 0x22, 0x00, 0x00, 0xa4, 0x02, 0x00, 0x00, 0x24, 0x01, 0x01, 0x00, 0x03, 0x03, 0x00, 0x00, 0x0c, - 0x01, 0x00, 0x00, 0x14, 0x80, 0x0e, 0x00, 0x80, 0x03, 0x00, 0x00, 0x08, 0x02, 0x00, 0x00, 0x05, - 0x00, 0x00, 0x00, 0x08, 0x04, 0x00, 0x00, 0x1c, 0x02, 0x00, 0x00, 0x24, 0x02, 0x01, 0x00, 0x03, - 0x03, 0x00, 0x00, 0x0c, 0x01, 0x00, 0x00, 0x14, 0x80, 0x0e, 0x00, 0x80, 0x03, 0x00, 0x00, 0x08, - 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x08, 0x04, 0x00, 0x00, 0x13, 0x02, 0x00, 0x00, 0x2c, - 0x03, 0x01, 0x00, 0x04, 0x03, 0x00, 0x00, 0x0c, 0x01, 0x00, 0x00, 0x0d, 0x80, 0x0e, 0x00, 0x80, - 0x03, 0x00, 0x00, 0x08, 0x03, 0x00, 0x00, 0x0c, 0x03, 0x00, 0x00, 0x08, 0x02, 0x00, 0x00, 0x05, - 0x00, 0x00, 0x00, 0x08, 0x04, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x2c, 0x04, 0x01, 0x00, 0x04, - 0x03, 0x00, 0x00, 0x0c, 0x01, 0x00, 0x00, 0x0d, 0x80, 0x0e, 0x00, 0x80, 0x03, 0x00, 0x00, 0x08, - 0x03, 0x00, 0x00, 0x0c, 0x03, 0x00, 0x00, 0x08, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x08, - 0x04, 0x00, 0x00, 0x13, 0x28, 0x00, 0x00, 0x48, 0x00, 0x1c, 0x00, 0x00, 0x4d, 0x23, 0xb8, 0xf2, - 0x2c, 0x03, 0xae, 0x3a, 0xb4, 0x0a, 0xf9, 0xfa, 0x76, 0xc2, 0x3c, 0x7b, 0xa6, 0xc5, 0x69, 0x81, - 0xe1, 0x3c, 0x32, 0xfb, 0xc3, 0x69, 0x54, 0xc8, 0x7a, 0x96, 0xcb, 0xfa, 0x34, 0x63, 0x7c, 0x6f, - 0x31, 0xb6, 0x50, 0xce, 0x5d, 0x87, 0x17, 0x00, 0x5c, 0xe7, 0x93, 0xc2, 0xee, 0xaf, 0xf1, 0xc5, - 0x66, 0x28, 0x08, 0x11, 0xd9, 0x42, 0xd1, 0xb8, 0xe8, 0x02, 0x68, 0xbb, 0x00, 0x00, 0x00, 0x24, - 0x99, 0xe2, 0xa3, 0x73, 0xcc, 0x44, 0xad, 0x10, 0xfb, 0x78, 0xdd, 0xa2, 0x52, 0x06, 0xa4, 0xa9, - 0xb7, 0x55, 0x8e, 0x0d, 0x82, 0x69, 0x79, 0x9c, 0x68, 0x00, 0x36, 0x2c, 0x46, 0xa0, 0xbf, 0x7b -]; + static IKEV2_MSG: &'static [u8] = &[ + 0x00, 0x00, 0x00, 0x00, 0xbc, 0xa1, 0x93, 0x7a, 0x7c, 0x2f, 0xf5, 0xb9, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x20, 0x22, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x2c, 0x22, 0x00, 0x00, 0xa4, 0x02, 0x00, 0x00, 0x24, 0x01, 0x01, 0x00, 0x03, 0x03, + 0x00, 0x00, 0x0c, 0x01, 0x00, 0x00, 0x14, 0x80, 0x0e, 0x00, 0x80, 0x03, 0x00, 0x00, 0x08, + 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x08, 0x04, 0x00, 0x00, 0x1c, 0x02, 0x00, 0x00, + 0x24, 0x02, 0x01, 0x00, 0x03, 0x03, 0x00, 0x00, 0x0c, 0x01, 0x00, 0x00, 0x14, 0x80, 0x0e, + 0x00, 0x80, 0x03, 0x00, 0x00, 0x08, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x08, 0x04, + 0x00, 0x00, 0x13, 0x02, 0x00, 0x00, 0x2c, 0x03, 0x01, 0x00, 0x04, 0x03, 0x00, 0x00, 0x0c, + 0x01, 0x00, 0x00, 0x0d, 0x80, 0x0e, 0x00, 0x80, 0x03, 0x00, 0x00, 0x08, 0x03, 0x00, 0x00, + 0x0c, 0x03, 0x00, 0x00, 0x08, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x08, 0x04, 0x00, + 0x00, 0x1c, 0x00, 0x00, 0x00, 0x2c, 0x04, 0x01, 0x00, 0x04, 0x03, 0x00, 0x00, 0x0c, 0x01, + 0x00, 0x00, 0x0d, 0x80, 0x0e, 0x00, 0x80, 0x03, 0x00, 0x00, 0x08, 0x03, 0x00, 0x00, 0x0c, + 0x03, 0x00, 0x00, 0x08, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x08, 0x04, 0x00, 0x00, + 0x13, 0x28, 0x00, 0x00, 0x48, 0x00, 0x1c, 0x00, 0x00, 0x4d, 0x23, 0xb8, 0xf2, 0x2c, 0x03, + 0xae, 0x3a, 0xb4, 0x0a, 0xf9, 0xfa, 0x76, 0xc2, 0x3c, 0x7b, 0xa6, 0xc5, 0x69, 0x81, 0xe1, + 0x3c, 0x32, 0xfb, 0xc3, 0x69, 0x54, 0xc8, 0x7a, 0x96, 0xcb, 0xfa, 0x34, 0x63, 0x7c, 0x6f, + 0x31, 0xb6, 0x50, 0xce, 0x5d, 0x87, 0x17, 0x00, 0x5c, 0xe7, 0x93, 0xc2, 0xee, 0xaf, 0xf1, + 0xc5, 0x66, 0x28, 0x08, 0x11, 0xd9, 0x42, 0xd1, 0xb8, 0xe8, 0x02, 0x68, 0xbb, 0x00, 0x00, + 0x00, 0x24, 0x99, 0xe2, 0xa3, 0x73, 0xcc, 0x44, 0xad, 0x10, 0xfb, 0x78, 0xdd, 0xa2, 0x52, + 0x06, 0xa4, 0xa9, 0xb7, 0x55, 0x8e, 0x0d, 0x82, 0x69, 0x79, 0x9c, 0x68, 0x00, 0x36, 0x2c, + 0x46, 0xa0, 0xbf, 0x7b, + ]; -#[test] -fn test_ipsec_ike_sa() { - let bytes = &IKEV2_MSG[4..32]; - let ike_sa = &IKEV2_MSG[32..]; - let expected = IkeV2Header{ - init_spi: 0xbca1937a7c2ff5b9, - resp_spi: 0x0, - next_payload: IkePayloadType::SecurityAssociation, - maj_ver: 2, - min_ver: 0, - exch_type: IkeExchangeType::IKE_SA_INIT, - flags: 0x8, - msg_id: 0, - length: 300, - }; - let (_, res) = parse_ikev2_header(&bytes).expect("failed to parse header"); - // println!("{:?}",res); - assert_eq!(res, expected); + #[test] + fn test_ipsec_ike_sa() { + let bytes = &IKEV2_MSG[4..32]; + let ike_sa = &IKEV2_MSG[32..]; + let expected = IkeV2Header { + init_spi: 0xbca1937a7c2ff5b9, + resp_spi: 0x0, + next_payload: IkePayloadType::SecurityAssociation, + maj_ver: 2, + min_ver: 0, + exch_type: IkeExchangeType::IKE_SA_INIT, + flags: 0x8, + msg_id: 0, + length: 300, + }; + let (_, res) = parse_ikev2_header(&bytes).expect("failed to parse header"); + // println!("{:?}",res); + assert_eq!(res, expected); - let (_, hdr) = parse_ikev2_payload_generic(&ike_sa).expect("failed to parse payload"); - // println!("{:?}",res_sa); - let (rem, sa) = parse_ikev2_payload_sa(hdr.payload,0).unwrap(); - assert_eq!(rem.len(), 0); - match sa { - IkeV2PayloadContent::SA(ref sa_list) => { - assert_eq!(sa_list.len(),4); - // for sa in sa_list.iter() { - // println!("sa: {:?}", sa); - // } - sa_list.iter().zip(&[3, 3, 4, 4]).for_each(|(a,b)| - assert_eq!(a.num_transforms, *b)); - sa_list.iter().for_each(|a| - assert_eq!(a.transforms.len(), a.num_transforms as usize)); - }, - _ => assert!(false), + let (_, hdr) = parse_ikev2_payload_generic(&ike_sa).expect("failed to parse payload"); + // println!("{:?}",res_sa); + let (rem, sa) = parse_ikev2_payload_sa(hdr.payload, 0).unwrap(); + assert_eq!(rem.len(), 0); + match sa { + IkeV2PayloadContent::SA(ref sa_list) => { + assert_eq!(sa_list.len(), 4); + // for sa in sa_list.iter() { + // println!("sa: {:?}", sa); + // } + sa_list + .iter() + .zip(&[3, 3, 4, 4]) + .for_each(|(a, b)| assert_eq!(a.num_transforms, *b)); + sa_list + .iter() + .for_each(|a| assert_eq!(a.transforms.len(), a.num_transforms as usize)); + } + _ => assert!(false), + } } -} -static IKEV2_INIT_REQ: &'static [u8] = include_bytes!("../assets/ike-sa-init-req.bin"); + static IKEV2_INIT_REQ: &'static [u8] = include_bytes!("../assets/ike-sa-init-req.bin"); -#[test] -fn test_ipsec_ike_message() { - let bytes = IKEV2_INIT_REQ; - let expected_header = IkeV2Header{ - init_spi: 0x54c184961bc3fd77, - resp_spi: 0x0, - next_payload: IkePayloadType::SecurityAssociation, - maj_ver: 2, - min_ver: 0, - exch_type: IkeExchangeType::IKE_SA_INIT, - flags: 0x8, - msg_id: 0, - length: 256, - }; - let (rem, (hdr, res_list)) = parse_ikev2_message(&bytes).expect("failed to parse header"); - let list = res_list.expect("failed to parse payload"); - assert_eq!(rem.len(),0); - assert_eq!(hdr, expected_header); - assert_eq!(list.len(),4); - for (a,b) in list.iter().zip(&[33, 34, 40, 0]) { - assert_eq!(a.hdr.next_payload_type, IkePayloadType(*b)); + #[test] + fn test_ipsec_ike_message() { + let bytes = IKEV2_INIT_REQ; + let expected_header = IkeV2Header { + init_spi: 0x54c184961bc3fd77, + resp_spi: 0x0, + next_payload: IkePayloadType::SecurityAssociation, + maj_ver: 2, + min_ver: 0, + exch_type: IkeExchangeType::IKE_SA_INIT, + flags: 0x8, + msg_id: 0, + length: 256, + }; + let (rem, (hdr, res_list)) = parse_ikev2_message(&bytes).expect("failed to parse header"); + let list = res_list.expect("failed to parse payload"); + assert_eq!(rem.len(), 0); + assert_eq!(hdr, expected_header); + assert_eq!(list.len(), 4); + for (a, b) in list.iter().zip(&[33, 34, 40, 0]) { + assert_eq!(a.hdr.next_payload_type, IkePayloadType(*b)); + } } -} } // mod ikev2