]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
quic: redo quic.version; parser cleanups
authorVictor Julien <vjulien@oisf.net>
Fri, 14 Jan 2022 19:34:04 +0000 (20:34 +0100)
committerVictor Julien <vjulien@oisf.net>
Wed, 19 Jan 2022 13:10:50 +0000 (14:10 +0100)
Reimplement quic.version as sticky buffer.

Removed unused parts of the parser.

Set unidirectional tx flag to fix double matching.

rust/src/quic/detect.rs
rust/src/quic/parser.rs
rust/src/quic/quic.rs
src/detect-quic-version.c

index c5b1fe18c444caddac800ba55c2668be8db459ce..2cff8fc94b51674ec280af5a3d42cd711b95b6dd 100644 (file)
 use crate::quic::quic::{QuicTransaction};
 use std::ptr;
 
+#[no_mangle]
+pub unsafe extern "C" fn rs_quic_tx_get_version(
+    tx: &QuicTransaction, buffer: *mut *const u8, buffer_len: *mut u32,
+) -> u8 {
+    if tx.header.flags.is_long {
+        let s = &tx.header.version_buf;
+        *buffer = s.as_ptr();
+        *buffer_len = s.len() as u32;
+        1
+    } else {
+        *buffer = ptr::null();
+        *buffer_len = 0;
+        0
+    }
+}
+
 #[no_mangle]
 pub unsafe extern "C" fn rs_quic_tx_get_cyu_hash(
     tx: &QuicTransaction, i: u32, buffer: *mut *const u8, buffer_len: *mut u32,
@@ -58,8 +74,3 @@ pub unsafe extern "C" fn rs_quic_tx_get_cyu_string(
         0
     }
 }
-
-#[no_mangle]
-pub extern "C" fn rs_quic_tx_get_version(tx: &QuicTransaction) -> u32 {
-    tx.header.version.into()
-}
index d3283de7cc74cfbdf4f0e2f3e32f76394d798125..7888e9c9956887fcc1b6716937a60a58b6e79e88 100644 (file)
@@ -76,7 +76,7 @@ pub enum QuicType {
 
 #[derive(Debug, PartialEq)]
 pub struct PublicFlags {
-    is_long: bool,
+    pub is_long: bool,
 }
 
 impl PublicFlags {
@@ -93,6 +93,7 @@ pub struct QuicHeader {
     pub flags: PublicFlags,
     pub ty: QuicType,
     pub version: QuicVersion,
+    pub version_buf: Vec<u8>,
     pub dcid: Vec<u8>,
     pub scid: Vec<u8>,
 }
@@ -111,6 +112,7 @@ impl QuicHeader {
             flags,
             ty,
             version,
+            version_buf: Vec::new(),
             dcid,
             scid,
         }
@@ -132,12 +134,14 @@ impl QuicHeader {
                     flags,
                     ty: QuicType::Short,
                     version: QuicVersion(0),
+                    version_buf: Vec::new(),
                     dcid: dcid.to_vec(),
                     scid: Vec::new(),
                 },
             ));
         } else {
             // Decode Long header
+            let (_, version_buf) = take(4_usize)(rest)?;
             let (rest, version) = map(be_u32, QuicVersion)(rest)?;
 
             let ty = if version == QuicVersion(0) {
@@ -213,6 +217,7 @@ impl QuicHeader {
                     flags,
                     ty,
                     version,
+                    version_buf: version_buf.to_vec(),
                     dcid,
                     scid,
                 },
@@ -253,6 +258,7 @@ mod tests {
                 flags: PublicFlags { is_long: true },
                 ty: QuicType::Initial,
                 version: QuicVersion(0xff00001d),
+                version_buf: vec![0xff, 0x00, 0x00, 0x1d],
                 dcid: hex::decode("91d0b10ac886039973885dfa07c46943")
                     .unwrap()
                     .to_vec(),
@@ -275,6 +281,7 @@ mod tests {
                 flags: PublicFlags { is_long: true },
                 ty: QuicType::Initial,
                 version: QuicVersion::Q044,
+                version_buf: vec![0x51, 0x30, 0x34, 0x34],
                 dcid: hex::decode("05cad2cc06c4d0e4").unwrap().to_vec(),
                 scid: Vec::new(),
             },
index a7a6cb5255ddd98f8381d7e0f0d18e633f3d531a..3fe23d6382e953c71b0f36a9c1926d5fbc548407 100644 (file)
@@ -20,7 +20,7 @@ use super::{
     parser::{QuicData, QuicHeader},
 };
 use crate::applayer::{self, *};
-use crate::core::{self, AppProto, Flow, ALPROTO_FAILED, ALPROTO_UNKNOWN, IPPROTO_UDP};
+use crate::core::{AppProto, Flow, ALPROTO_FAILED, ALPROTO_UNKNOWN, IPPROTO_UDP};
 use std::ffi::CString;
 
 static mut ALPROTO_QUIC: AppProto = ALPROTO_UNKNOWN;
@@ -32,9 +32,6 @@ pub struct QuicTransaction {
     tx_id: u64,
     pub header: QuicHeader,
     pub cyu: Vec<Cyu>,
-
-    de_state: Option<*mut core::DetectEngineState>,
-    events: *mut core::AppLayerDecoderEvents,
     tx_data: AppLayerTxData,
 }
 
@@ -45,26 +42,9 @@ impl QuicTransaction {
             tx_id: 0,
             header,
             cyu,
-            de_state: None,
-            events: std::ptr::null_mut(),
             tx_data: AppLayerTxData::new(),
         }
     }
-
-    fn free(&mut self) {
-        if !self.events.is_null() {
-            core::sc_app_layer_decoder_events_free_events(&mut self.events);
-        }
-        if let Some(state) = self.de_state {
-            core::sc_detect_engine_state_free(state);
-        }
-    }
-}
-
-impl Drop for QuicTransaction {
-    fn drop(&mut self) {
-        self.free();
-    }
 }
 
 pub struct QuicState {
@@ -231,30 +211,6 @@ pub unsafe extern "C" fn rs_quic_tx_get_alstate_progress(
     return 1;
 }
 
-#[no_mangle]
-pub unsafe extern "C" fn rs_quic_state_get_events(
-    tx: *mut std::os::raw::c_void,
-) -> *mut core::AppLayerDecoderEvents {
-    let tx = cast_pointer!(tx, QuicTransaction);
-    return tx.events;
-}
-
-#[no_mangle]
-pub extern "C" fn rs_quic_state_get_event_info(
-    _event_name: *const std::os::raw::c_char, _event_id: *mut std::os::raw::c_int,
-    _event_type: *mut core::AppLayerEventType,
-) -> std::os::raw::c_int {
-    return -1;
-}
-
-#[no_mangle]
-pub extern "C" fn rs_quic_state_get_event_info_by_id(
-    _event_id: std::os::raw::c_int, _event_name: *mut *const std::os::raw::c_char,
-    _event_type: *mut core::AppLayerEventType,
-) -> i8 {
-    return -1;
-}
-
 #[no_mangle]
 pub unsafe extern "C" fn rs_quic_state_get_tx_iterator(
     _ipproto: u8, _alproto: AppProto, state: *mut std::os::raw::c_void, min_tx_id: u64,
@@ -299,15 +255,15 @@ pub unsafe extern "C" fn rs_quic_register_parser() {
         tx_comp_st_ts: 1,
         tx_comp_st_tc: 1,
         tx_get_progress: rs_quic_tx_get_alstate_progress,
-        get_eventinfo: Some(rs_quic_state_get_event_info),
-        get_eventinfo_byid: Some(rs_quic_state_get_event_info_by_id),
+        get_eventinfo: None,
+        get_eventinfo_byid: None,
         localstorage_new: None,
         localstorage_free: None,
         get_files: None,
         get_tx_iterator: Some(rs_quic_state_get_tx_iterator),
         get_tx_data: rs_quic_get_tx_data,
         apply_tx_config: None,
-        flags: 0,
+        flags: APP_LAYER_PARSER_OPT_UNIDIR_TXS,
         truncate: None,
         get_frame_id_by_name: None,
         get_frame_name_by_id: None,
index 12640dac92d8891e058393265b4d53515a18ca23..d97f62ac1e9573290408916e3306dd84c977b900 100644 (file)
@@ -25,6 +25,8 @@
 #include "detect.h"
 #include "detect-parse.h"
 #include "detect-engine.h"
+#include "detect-engine-prefilter.h"
+#include "detect-engine-mpm.h"
 #include "detect-engine-content-inspection.h"
 #include "detect-engine-uint.h"
 #include "detect-quic-version.h"
 static void DetectQuicVersionRegisterTests(void);
 #endif
 
+#define BUFFER_NAME  "quic_version"
+#define KEYWORD_NAME "quic.version"
+#define KEYWORD_ID   DETECT_AL_QUIC_VERSION
+
 static int quic_version_id = 0;
 
-static int DetectQuicVersionMatch(DetectEngineThreadCtx *det_ctx, Flow *f, uint8_t flags,
-        void *state, void *txv, const Signature *s, const SigMatchCtx *ctx);
 static int DetectQuicVersionSetup(DetectEngineCtx *, Signature *, const char *);
-void DetectQuicVersionFree(DetectEngineCtx *de_ctx, void *);
 
-static int DetectEngineInspectQuicVersionGeneric(DetectEngineCtx *de_ctx,
-        DetectEngineThreadCtx *det_ctx, const struct DetectEngineAppInspectionEngine_ *engine,
-        const Signature *s, Flow *f, uint8_t flags, void *alstate, void *txv, uint64_t tx_id);
+static InspectionBuffer *GetVersionData(DetectEngineThreadCtx *det_ctx,
+        const DetectEngineTransforms *transforms, Flow *_f, const uint8_t _flow_flags, void *txv,
+        const int list_id)
+{
+    InspectionBuffer *buffer = InspectionBufferGet(det_ctx, list_id);
+    if (buffer->inspect == NULL) {
+        uint32_t b_len = 0;
+        const uint8_t *b = NULL;
+
+        if (rs_quic_tx_get_version(txv, &b, &b_len) != 1)
+            return NULL;
+        if (b == NULL || b_len == 0)
+            return NULL;
+
+        InspectionBufferSetup(det_ctx, list_id, buffer, b, b_len);
+        InspectionBufferApplyTransforms(buffer, transforms);
+    }
+    return buffer;
+}
 
 /**
  * \brief Registration function for quic.version: keyword
  */
 void DetectQuicVersionRegister(void)
 {
-    sigmatch_table[DETECT_AL_QUIC_VERSION].name = "quic.version";
+    sigmatch_table[DETECT_AL_QUIC_VERSION].name = KEYWORD_NAME;
     sigmatch_table[DETECT_AL_QUIC_VERSION].desc = "match Quic version";
     sigmatch_table[DETECT_AL_QUIC_VERSION].url = "/rules/quic-keywords.html#quic-version";
-    sigmatch_table[DETECT_AL_QUIC_VERSION].AppLayerTxMatch = DetectQuicVersionMatch;
     sigmatch_table[DETECT_AL_QUIC_VERSION].Setup = DetectQuicVersionSetup;
-    sigmatch_table[DETECT_AL_QUIC_VERSION].Free = DetectQuicVersionFree;
+    sigmatch_table[DETECT_AL_QUIC_VERSION].flags |= SIGMATCH_NOOPT | SIGMATCH_INFO_STICKY_BUFFER;
 #ifdef UNITTESTS
     sigmatch_table[DETECT_AL_QUIC_VERSION].RegisterTests = DetectQuicVersionRegisterTests;
 #endif
 
-    DetectAppLayerInspectEngineRegister2("quic.version", ALPROTO_QUIC, SIG_FLAG_TOSERVER, 1,
-            DetectEngineInspectQuicVersionGeneric, NULL);
+    DetectAppLayerMpmRegister2(BUFFER_NAME, SIG_FLAG_TOSERVER, 2, PrefilterGenericMpmRegister,
+            GetVersionData, ALPROTO_QUIC, 1);
+    DetectAppLayerMpmRegister2(BUFFER_NAME, SIG_FLAG_TOCLIENT, 2, PrefilterGenericMpmRegister,
+            GetVersionData, ALPROTO_QUIC, 1);
 
-    quic_version_id = DetectBufferTypeGetByName("quic.version");
-}
+    DetectAppLayerInspectEngineRegister2(BUFFER_NAME, ALPROTO_QUIC, SIG_FLAG_TOSERVER, 1,
+            DetectEngineInspectBufferGeneric, GetVersionData);
+    DetectAppLayerInspectEngineRegister2(BUFFER_NAME, ALPROTO_QUIC, SIG_FLAG_TOCLIENT, 1,
+            DetectEngineInspectBufferGeneric, GetVersionData);
 
-static int DetectEngineInspectQuicVersionGeneric(DetectEngineCtx *de_ctx,
-        DetectEngineThreadCtx *det_ctx, const struct DetectEngineAppInspectionEngine_ *engine,
-        const Signature *s, Flow *f, uint8_t flags, void *alstate, void *txv, uint64_t tx_id)
-{
-    return DetectEngineInspectGenericList(
-            de_ctx, det_ctx, s, engine->smd, f, flags, alstate, txv, tx_id);
-}
-
-/**
- * \internal
- * \brief Function to match protocol version of an Quic Tx
- *
- * \param det_ctx Pointer to the pattern matcher thread.
- * \param f       Pointer to the current flow.
- * \param flags   Flags.
- * \param state   App layer state.
- * \param txv     Pointer to the transaction.
- * \param s       Pointer to the Signature.
- * \param ctx     Pointer to the sigmatch that we will cast into DetectQuicVersionData.
- *
- * \retval 0 no match.
- * \retval 1 match.
- */
-static int DetectQuicVersionMatch(DetectEngineThreadCtx *det_ctx, Flow *f, uint8_t flags,
-        void *state, void *txv, const Signature *s, const SigMatchCtx *ctx)
-{
-    const DetectU32Data *de = (const DetectU32Data *)ctx;
-    uint32_t version;
-
-    version = rs_quic_tx_get_version(txv);
-
-    return DetectU32Match(version, de);
+    quic_version_id = DetectBufferTypeGetByName(BUFFER_NAME);
 }
 
 /**
@@ -115,45 +106,13 @@ static int DetectQuicVersionMatch(DetectEngineThreadCtx *det_ctx, Flow *f, uint8
  */
 static int DetectQuicVersionSetup(DetectEngineCtx *de_ctx, Signature *s, const char *rawstr)
 {
-    SigMatch *sm = NULL;
-    DetectU32Data *de = NULL;
-
-    if (DetectSignatureSetAppProto(s, ALPROTO_QUIC) < 0)
+    if (DetectBufferSetActiveList(s, quic_version_id) < 0)
         return -1;
 
-    de = DetectU32Parse(rawstr);
-    if (de == NULL)
+    if (DetectSignatureSetAppProto(s, ALPROTO_QUIC) < 0)
         return -1;
 
-    sm = SigMatchAlloc();
-    if (sm == NULL)
-        goto error;
-
-    sm->type = DETECT_AL_QUIC_VERSION;
-    sm->ctx = (SigMatchCtx *)de;
-
-    SigMatchAppendSMToList(s, sm, quic_version_id);
-
     return 0;
-
-error:
-    if (de != NULL)
-        SCFree(de);
-    if (sm != NULL)
-        SCFree(sm);
-    return -1;
-}
-
-/**
- * \internal
- * \brief this function will free memory associated with DetectQuicVersionData
- *
- * \param de pointer to DetectQuicVersionData
- */
-void DetectQuicVersionFree(DetectEngineCtx *de_ctx, void *de_ptr)
-{
-    if (de_ptr != NULL)
-        SCFree(de_ptr);
 }
 
 #ifdef UNITTESTS
@@ -170,35 +129,11 @@ static int QuicVersionTestParse01(void)
     FAIL_IF_NULL(de_ctx);
 
     Signature *sig = DetectEngineAppendSig(
-            de_ctx, "alert ip any any -> any any (quic.version:3; sid:1; rev:1;)");
-    FAIL_IF_NULL(sig);
-
-    sig = DetectEngineAppendSig(
-            de_ctx, "alert ip any any -> any any (quic.version:3; sid:2; rev:1;)");
-    FAIL_IF_NULL(sig);
-
-    DetectEngineCtxFree(de_ctx);
-
-    PASS;
-}
-
-/**
- * \test QuicVersionTestParse02 is a test for a valid value
- *
- *  \retval 1 on success
- *  \retval 0 on failure
- */
-static int QuicVersionTestParse02(void)
-{
-    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
-    FAIL_IF_NULL(de_ctx);
-
-    Signature *sig = DetectEngineAppendSig(
-            de_ctx, "alert ip any any -> any any (quic.version:>3; sid:1; rev:1;)");
+            de_ctx, "alert ip any any -> any any (quic.version; content:\"Q046\"; sid:1; rev:1;)");
     FAIL_IF_NULL(sig);
 
     sig = DetectEngineAppendSig(
-            de_ctx, "alert ip any any -> any any (quic.version:<44; sid:2; rev:1;)");
+            de_ctx, "alert ip any any -> any any (quic.version; content:\"|00|\"; sid:2; rev:1;)");
     FAIL_IF_NULL(sig);
 
     DetectEngineCtxFree(de_ctx);
@@ -226,35 +161,13 @@ static int QuicVersionTestParse03(void)
     PASS;
 }
 
-/**
- * \test QuicVersionTestParse04 is a test for an invalid value
- *
- *  \retval 1 on success
- *  \retval 0 on failure
- */
-static int QuicVersionTestParse04(void)
-{
-    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
-    FAIL_IF_NULL(de_ctx);
-
-    Signature *sig = DetectEngineAppendSig(
-            de_ctx, "alert ip any any -> any any (quic.version:<4294967296; sid:1; rev:1;)");
-    FAIL_IF_NOT_NULL(sig);
-
-    DetectEngineCtxFree(de_ctx);
-
-    PASS;
-}
-
 /**
  * \brief this function registers unit tests for QuicVersion
  */
 void DetectQuicVersionRegisterTests(void)
 {
     UtRegisterTest("QuicVersionTestParse01", QuicVersionTestParse01);
-    UtRegisterTest("QuicVersionTestParse02", QuicVersionTestParse02);
     UtRegisterTest("QuicVersionTestParse03", QuicVersionTestParse03);
-    UtRegisterTest("QuicVersionTestParse04", QuicVersionTestParse04);
 }
 
 #endif /* UNITTESTS */