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;
tx_id: u64,
pub header: QuicHeader,
pub cyu: Vec<Cyu>,
-
- de_state: Option<*mut core::DetectEngineState>,
- events: *mut core::AppLayerDecoderEvents,
tx_data: AppLayerTxData,
}
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 {
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,
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,
#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);
}
/**
*/
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
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);
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 */