]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
rust: upgrade versions of BER/DER, Kerberos and SNMP parsers
authorPierre Chifflier <chifflier@wzdftpd.net>
Tue, 11 Jan 2022 14:50:55 +0000 (15:50 +0100)
committerVictor Julien <vjulien@oisf.net>
Thu, 29 Sep 2022 08:37:50 +0000 (10:37 +0200)
rust/Cargo.toml.in
rust/src/asn1/mod.rs
rust/src/kerberos.rs
rust/src/krb/krb5.rs
rust/src/nfs/nfs4.rs
rust/src/smb/auth.rs
rust/src/snmp/snmp.rs

index 7201555c8931b00e662864425934adf083d0c4b7..c299dd3a376ca39db398d0849e76c24fa7701d48 100644 (file)
@@ -41,11 +41,11 @@ aes-gcm = "~0.8.0"
 
 sawp-modbus = "~0.11.0"
 sawp = "~0.11.0"
-der-parser = "~4.0.2"
+der-parser = "~6.0"
 kerberos-parser = "~0.7.1"
 ntp-parser = "~0.6.0"
 ipsec-parser = "~0.7.0"
-snmp-parser = "~0.6.0"
+snmp-parser = "~0.8.0"
 tls-parser = "~0.11.0"
 x509-parser = "~0.14.0"
 libc = "~0.2.82"
index 7d33bc0a9bb869e0fdfe0d7f7067276ac24a9e5c..5a2b4d15de98a95a7681245d658a48f0558e496e 100644 (file)
@@ -83,10 +83,13 @@ impl<'a> Asn1<'a> {
 
     /// Checks a BerObject and subnodes against the Asn1 checks
     fn check_object(obj: &BerObject, ad: &DetectAsn1Data) -> Option<Asn1Check> {
+        // get length
+        // Note that if length is indefinite (BER), this will return None
+        let len = obj.header.len.primitive().ok()?;
         // oversize_length will check if a node has a length greater than
         // the user supplied length
         if let Some(oversize_length) = ad.oversize_length {
-            if obj.header.len > oversize_length as u64
+            if len > oversize_length as usize
                 || obj.content.as_slice().unwrap_or(&[]).len() > oversize_length as usize
             {
                 return Some(Asn1Check::OversizeLength);
@@ -101,8 +104,8 @@ impl<'a> Asn1<'a> {
                 && obj.header.is_primitive())
         {
             if let BerObjectContent::BitString(bits, _v) = &obj.content {
-                if obj.header.len > 0
-                    && *bits as u64 > obj.header.len.saturating_mul(8)
+                if len > 0
+                    && *bits as usize > len.saturating_mul(8)
                 {
                     return Some(Asn1Check::BitstringOverflow);
                 }
@@ -118,10 +121,10 @@ impl<'a> Asn1<'a> {
                 && obj.header.is_primitive())
         {
             if let Ok(data) = obj.content.as_slice() {
-                if obj.header.len > 0
+                if len > 0
                     && !data.is_empty()
                     && data[0] & 0xC0 == 0
-                    && (obj.header.len > 256 || data.len() > 256)
+                    && (len > 256 || data.len() > 256)
                 {
                     return Some(Asn1Check::DoubleOverflow);
                 }
index c980e0fd68249097fffbc28486e878d48599d984..c4f1fca4997f6f122d262ff81a49db97399b4e46 100644 (file)
  * 02110-1301, USA.
  */
 
+use nom7::IResult;
+use nom7::error::{ErrorKind, ParseError};
+use nom7::number::streaming::le_u16;
 use der_parser;
 use der_parser::der::parse_der_oid;
 use der_parser::error::BerError;
 use kerberos_parser::krb5::{ApReq, PrincipalName, Realm};
 use kerberos_parser::krb5_parser::parse_ap_req;
-use nom;
-use nom::error::{ErrorKind, ParseError};
-use nom::number::complete::le_u16;
-use nom::IResult;
 
 #[derive(Debug)]
 pub enum SecBlobError {
@@ -55,22 +54,19 @@ pub struct Kerberos5Ticket {
     pub sname: PrincipalName,
 }
 
-fn parse_kerberos5_request_do(blob: &[u8]) -> IResult<&[u8], ApReq, SecBlobError> {
-    let (_, b) = der_parser::parse_der(blob).map_err(nom::Err::convert)?;
-    let blob = b
-        .as_slice()
-        .or(Err(nom::Err::Error(SecBlobError::KrbFmtError)))?;
-    let (blob, _) = parse_der_oid(blob).map_err(nom::Err::convert)?;
-    let (blob, _) = le_u16(blob)?;
-    // Should be parse_ap_req(blob).map_err(nom::Err::convert)
-    // But upgraded kerberos parser uses a newer der_parser crate
-    // Hence the enum `der_parser::error::BerError` are different
-    // and we cannot convert to SecBlobError with the From impl
-    // Next is to upgrade the der_parser crate (and nom to nom7 by the way)
-    match parse_ap_req(blob) {
-        Ok((blob, ap_req)) => Ok((blob, ap_req)),
-        _ => Err(nom::Err::Error(SecBlobError::KrbReqError)),
-    }
+fn parse_kerberos5_request_do(blob: &[u8]) -> IResult<&[u8], ApReq, SecBlobError>
+{
+    let (_,b) = der_parser::parse_der(blob).map_err(nom7::Err::convert)?;
+    let blob = b.as_slice().or(
+        Err(nom7::Err::Error(SecBlobError::KrbFmtError))
+    )?;
+    let parser = |i| {
+        let (i, _base_o) = parse_der_oid(i)?;
+        let (i, _tok_id) = le_u16(i)?;
+        let (i, ap_req) = parse_ap_req(i)?;
+        Ok((i, ap_req))
+    };
+    parser(blob).map_err(nom7::Err::convert)
 }
 
 pub fn parse_kerberos5_request(blob: &[u8]) -> IResult<&[u8], Kerberos5Ticket, SecBlobError> {
index c7210238e76e4e4e2f9b0fae838edeebcf08aa28..fdee89d3ca1914af304d4f3507ea8dee19536a62 100644 (file)
@@ -19,9 +19,8 @@
 
 use std;
 use std::ffi::CString;
-use nom;
-use nom::IResult;
-use nom::number::streaming::be_u32;
+use nom7::{Err, IResult};
+use nom7::number::streaming::be_u32;
 use der_parser::der::der_read_element_header;
 use der_parser::ber::BerClass;
 use kerberos_parser::krb5_parser;
@@ -186,7 +185,7 @@ impl KRB5State {
                 }
                 0
             },
-            Err(nom::Err::Incomplete(_)) => {
+            Err(Err::Incomplete(_)) => {
                 SCLogDebug!("Insufficient data while parsing KRB5 data");
                 self.set_event(KRB5Event::MalformedData);
                 -1
@@ -346,7 +345,7 @@ pub unsafe extern "C" fn rs_krb5_probing_parser(_flow: *const Flow,
             }
             return ALPROTO_FAILED;
         },
-        Err(nom::Err::Incomplete(_)) => {
+        Err(Err::Incomplete(_)) => {
             return ALPROTO_UNKNOWN;
         },
         Err(_) => {
@@ -370,7 +369,7 @@ pub unsafe extern "C" fn rs_krb5_probing_parser_tcp(_flow: *const Flow,
             return rs_krb5_probing_parser(_flow, direction,
                     rem.as_ptr(), rem.len() as u32, rdir);
         },
-        Err(nom::Err::Incomplete(_)) => {
+        Err(Err::Incomplete(_)) => {
             return ALPROTO_UNKNOWN;
         },
         Err(_) => {
@@ -442,7 +441,7 @@ pub unsafe extern "C" fn rs_krb5_parse_request_tcp(_flow: *const core::Flow,
                     state.record_ts = record as usize;
                     cur_i = rem;
                 },
-                Err(nom::Err::Incomplete(_)) => {
+                Err(Err::Incomplete(_)) => {
                     state.defrag_buf_ts.extend_from_slice(cur_i);
                     return AppLayerResult::ok();
                 }
@@ -500,7 +499,7 @@ pub unsafe extern "C" fn rs_krb5_parse_response_tcp(_flow: *const core::Flow,
                     state.record_tc = record as usize;
                     cur_i = rem;
                 },
-                Err(nom::Err::Incomplete(_)) => {
+                Err(Err::Incomplete(_)) => {
                     state.defrag_buf_tc.extend_from_slice(cur_i);
                     return AppLayerResult::ok();
                 }
index d714ceadb8ec6bc467ed21a9c44a507ff161d362..7c4c48127ee7c37af7b23a976a853db0bb3c6af8 100644 (file)
@@ -17,9 +17,9 @@
 
 // written by Victor Julien
 
-use nom::bytes::streaming::take;
-use nom::number::streaming::be_u32;
-use nom7::Err;
+use nom7::bytes::streaming::take;
+use nom7::number::streaming::be_u32;
+use nom7::{Err, IResult};
 
 use crate::core::*;
 use crate::nfs::nfs::*;
@@ -30,8 +30,7 @@ use crate::nfs::types::*;
 
 use crate::kerberos::{parse_kerberos5_request, Kerberos5Ticket, SecBlobError};
 
-// use the old nom type until both SMB and NFS are migrated to nom 7
-fn parse_req_gssapi(i: &[u8]) -> nom::IResult<&[u8], Kerberos5Ticket, SecBlobError> {
+fn parse_req_gssapi(i: &[u8]) -> IResult<&[u8], Kerberos5Ticket, SecBlobError> {
     let (i, len) = be_u32(i)?;
     let (i, buf) = take(len as usize)(i)?;
     let (_, ap) = parse_kerberos5_request(buf)?;
index bd15ca666e3b982df3e19f6e7016b699cf209139..f3efdf874ac837106edfbb9ddefab02e7db155b1 100644 (file)
@@ -20,26 +20,25 @@ use crate::kerberos::*;
 use crate::smb::ntlmssp_records::*;
 use crate::smb::smb::*;
 
-use nom;
-use nom::IResult;
+use nom7::{Err, IResult};
 use der_parser::ber::BerObjectContent;
 use der_parser::der::{parse_der_oid, parse_der_sequence};
 
 fn parse_secblob_get_spnego(blob: &[u8]) -> IResult<&[u8], &[u8], SecBlobError>
 {
-    let (rem, base_o) = der_parser::parse_der(blob).map_err(nom::Err::convert)?;
+    let (rem, base_o) = der_parser::parse_der(blob).map_err(Err::convert)?;
     SCLogDebug!("parse_secblob_get_spnego: base_o {:?}", base_o);
     let d = match base_o.content.as_slice() {
-        Err(_) => { return Err(nom::Err::Error(SecBlobError::NotSpNego)); },
+        Err(_) => { return Err(Err::Error(SecBlobError::NotSpNego)); },
         Ok(d) => d,
     };
-    let (next, o) = parse_der_oid(d).map_err(nom::Err::convert)?;
+    let (next, o) = parse_der_oid(d).map_err(Err::convert)?;
     SCLogDebug!("parse_secblob_get_spnego: sub_o {:?}", o);
 
     let oid = match o.content.as_oid() {
         Ok(oid) => oid,
         Err(_) => {
-            return Err(nom::Err::Error(SecBlobError::NotSpNego));
+            return Err(Err::Error(SecBlobError::NotSpNego));
         },
     };
     SCLogDebug!("oid {}", oid.to_string());
@@ -49,7 +48,7 @@ fn parse_secblob_get_spnego(blob: &[u8]) -> IResult<&[u8], &[u8], SecBlobError>
             SCLogDebug!("SPNEGO {}", oid);
         },
         _ => {
-            return Err(nom::Err::Error(SecBlobError::NotSpNego));
+            return Err(Err::Error(SecBlobError::NotSpNego));
         },
     }
 
@@ -60,14 +59,14 @@ fn parse_secblob_get_spnego(blob: &[u8]) -> IResult<&[u8], &[u8], SecBlobError>
 
 fn parse_secblob_spnego_start(blob: &[u8]) -> IResult<&[u8], &[u8], SecBlobError>
 {
-    let (rem, o) = der_parser::parse_der(blob).map_err(nom::Err::convert)?;
+    let (rem, o) = der_parser::parse_der(blob).map_err(Err::convert)?;
     let d = match o.content.as_slice() {
         Ok(d) => {
             SCLogDebug!("d: next data len {}",d.len());
             d
         },
         _ => {
-            return Err(nom::Err::Error(SecBlobError::NotSpNego));
+            return Err(Err::Error(SecBlobError::NotSpNego));
         },
     };
     Ok((rem, d))
index 9e05c3d4caf81fd039697a882ee6e9a192b2c86b..e6a769820436f62bf7227f416c370e9421a86091 100644 (file)
@@ -26,9 +26,8 @@ use std::ffi::CString;
 use der_parser::ber::BerObjectContent;
 use der_parser::der::parse_der_sequence;
 use der_parser::oid::Oid;
-use nom;
-use nom::IResult;
-use nom::error::ErrorKind;
+use nom7::{Err, IResult};
+use nom7::error::{ErrorKind, make_error};
 
 #[derive(AppLayerEvent)]
 pub enum SNMPEvent {
@@ -343,11 +342,11 @@ fn parse_pdu_enveloppe_version(i:&[u8]) -> IResult<&[u8],u32> {
                 },
                 _ => ()
             };
-            Err(nom::Err::Error(error_position!(i, ErrorKind::Verify)))
+            Err(Err::Error(make_error(i, ErrorKind::Verify)))
         },
-        Err(nom::Err::Incomplete(i)) => Err(nom::Err::Incomplete(i)),
-        Err(nom::Err::Failure(_)) |
-        Err(nom::Err::Error(_))      => Err(nom::Err::Error(error_position!(i,ErrorKind::Verify)))
+        Err(Err::Incomplete(i)) => Err(Err::Incomplete(i)),
+        Err(Err::Failure(_)) |
+        Err(Err::Error(_))      => Err(Err::Error(make_error(i,ErrorKind::Verify)))
     }
 }
 
@@ -361,9 +360,9 @@ pub unsafe extern "C" fn rs_snmp_probing_parser(_flow: *const Flow,
     let alproto = ALPROTO_SNMP;
     if slice.len() < 4 { return ALPROTO_FAILED; }
     match parse_pdu_enveloppe_version(slice) {
-        Ok((_,_))                    => alproto,
-        Err(nom::Err::Incomplete(_)) => ALPROTO_UNKNOWN,
-        _                            => ALPROTO_FAILED,
+        Ok((_,_))               => alproto,
+        Err(Err::Incomplete(_)) => ALPROTO_UNKNOWN,
+        _                       => ALPROTO_FAILED,
     }
 }