detect: unify functions for multi-buffer

Ticket: 6575

Multi buffers keywords now use a single registration function
DetectAppLayerMultiRegister with a GetBuffer argument.

This GetBuffer function pointer is similar to the ones used by
single-buffer keyword, except that it takes an additional
parameter which is the index of the buffer to get.
Under the hood, an anonymous union between these 2 functions
pointers types is used.

In the end, this deduplicates code, especially the calls to
DetectEngineContentInspection
pull/11139/head
Philippe Antoine 1 year ago committed by Victor Julien
parent 55bc5f2290
commit ce16a56a1f

@ -30,12 +30,6 @@
#include "util-profiling.h"
#include "rust.h"
typedef struct PrefilterMpm {
int list_id;
const MpmCtx *mpm_ctx;
const DetectEngineTransforms *transforms;
} PrefilterMpm;
static int detect_buffer_id = 0;
static int DetectSetup(DetectEngineCtx *de_ctx, Signature *s, const char *str)
@ -50,8 +44,9 @@ static int DetectSetup(DetectEngineCtx *de_ctx, Signature *s, const char *str)
return 0;
}
static InspectionBuffer *GetBuffer(DetectEngineThreadCtx *det_ctx, uint8_t flags,
const DetectEngineTransforms *transforms, void *txv, uint32_t index, int list_id)
static InspectionBuffer *GetBuffer(DetectEngineThreadCtx *det_ctx,
const DetectEngineTransforms *transforms, Flow *f, uint8_t flags, void *txv, int list_id,
uint32_t index)
{
InspectionBuffer *buffer = InspectionBufferMultipleForListGet(det_ctx, list_id, index);
if (buffer == NULL) {
@ -74,74 +69,6 @@ static InspectionBuffer *GetBuffer(DetectEngineThreadCtx *det_ctx, uint8_t flags
return buffer;
}
static uint8_t DetectEngineInspectCb(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)
{
const DetectEngineTransforms *transforms = NULL;
if (!engine->mpm) {
transforms = engine->v2.transforms;
}
for (uint32_t i = 0;; i++) {
InspectionBuffer *buffer = GetBuffer(det_ctx, flags, transforms, txv, i, engine->sm_list);
if (buffer == NULL || buffer->inspect == NULL) {
break;
}
const bool match = DetectEngineContentInspectionBuffer(de_ctx, det_ctx, s, engine->smd,
NULL, f, buffer, DETECT_ENGINE_CONTENT_INSPECTION_MODE_STATE);
if (match) {
return DETECT_ENGINE_INSPECT_SIG_MATCH;
}
}
return DETECT_ENGINE_INSPECT_SIG_NO_MATCH;
}
static void PrefilterTx(DetectEngineThreadCtx *det_ctx, const void *pectx, Packet *p, Flow *f,
void *txv, const uint64_t idx, const AppLayerTxData *_txd, const uint8_t flags)
{
SCEnter();
const PrefilterMpm *ctx = (const PrefilterMpm *)pectx;
const MpmCtx *mpm_ctx = ctx->mpm_ctx;
const int list_id = ctx->list_id;
for (uint32_t i = 0;; i++) {
InspectionBuffer *buffer = GetBuffer(det_ctx, flags, ctx->transforms, txv, i, list_id);
if (buffer == NULL) {
break;
}
if (buffer->inspect_len >= mpm_ctx->minlen) {
(void)mpm_table[mpm_ctx->mpm_type].Search(
mpm_ctx, &det_ctx->mtc, &det_ctx->pmq, buffer->inspect, buffer->inspect_len);
PREFILTER_PROFILING_ADD_BYTES(det_ctx, buffer->inspect_len);
}
}
}
static void PrefilterMpmFree(void *ptr)
{
SCFree(ptr);
}
static int PrefilterMpmRegister(DetectEngineCtx *de_ctx, SigGroupHead *sgh, MpmCtx *mpm_ctx,
const DetectBufferMpmRegistry *mpm_reg, int list_id)
{
PrefilterMpm *pectx = SCCalloc(1, sizeof(*pectx));
if (pectx == NULL) {
return -1;
}
pectx->list_id = list_id;
pectx->mpm_ctx = mpm_ctx;
pectx->transforms = &mpm_reg->transforms;
return PrefilterAppendTxEngine(de_ctx, sgh, PrefilterTx, mpm_reg->app_v2.alproto,
mpm_reg->app_v2.tx_min_progress, pectx, PrefilterMpmFree, mpm_reg->pname);
}
void DetectDnsAnswerNameRegister(void)
{
static const char *keyword = "dns.answer.name";
@ -154,16 +81,9 @@ void DetectDnsAnswerNameRegister(void)
/* Register in the TO_SERVER direction, even though this is not
normal, it could be provided as part of a request. */
DetectAppLayerInspectEngineRegister(
keyword, ALPROTO_DNS, SIG_FLAG_TOSERVER, 0, DetectEngineInspectCb, NULL);
DetectAppLayerMpmRegister(
keyword, SIG_FLAG_TOSERVER, 2, PrefilterMpmRegister, NULL, ALPROTO_DNS, 1);
DetectAppLayerMultiRegister(keyword, ALPROTO_DNS, SIG_FLAG_TOSERVER, 0, GetBuffer, 2, 1);
/* Register in the TO_CLIENT direction. */
DetectAppLayerInspectEngineRegister(
keyword, ALPROTO_DNS, SIG_FLAG_TOCLIENT, 0, DetectEngineInspectCb, NULL);
DetectAppLayerMpmRegister(
keyword, SIG_FLAG_TOCLIENT, 2, PrefilterMpmRegister, NULL, ALPROTO_DNS, 1);
DetectAppLayerMultiRegister(keyword, ALPROTO_DNS, SIG_FLAG_TOCLIENT, 0, GetBuffer, 2, 1);
DetectBufferTypeSetDescriptionByName(keyword, "dns answer name");
DetectBufferTypeSupportsMultiInstance(keyword);

@ -30,12 +30,6 @@
#include "util-profiling.h"
#include "rust.h"
typedef struct PrefilterMpm {
int list_id;
const MpmCtx *mpm_ctx;
const DetectEngineTransforms *transforms;
} PrefilterMpm;
static int detect_buffer_id = 0;
static int DetectSetup(DetectEngineCtx *de_ctx, Signature *s, const char *str)
@ -50,8 +44,9 @@ static int DetectSetup(DetectEngineCtx *de_ctx, Signature *s, const char *str)
return 0;
}
static InspectionBuffer *GetBuffer(DetectEngineThreadCtx *det_ctx, const uint8_t flags,
const DetectEngineTransforms *transforms, void *txv, uint32_t index, int list_id)
static InspectionBuffer *GetBuffer(DetectEngineThreadCtx *det_ctx,
const DetectEngineTransforms *transforms, Flow *f, const uint8_t flags, void *txv,
int list_id, uint32_t index)
{
InspectionBuffer *buffer = InspectionBufferMultipleForListGet(det_ctx, list_id, index);
if (buffer == NULL) {
@ -74,74 +69,6 @@ static InspectionBuffer *GetBuffer(DetectEngineThreadCtx *det_ctx, const uint8_t
return buffer;
}
static uint8_t DetectEngineInspectCb(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)
{
const DetectEngineTransforms *transforms = NULL;
if (!engine->mpm) {
transforms = engine->v2.transforms;
}
for (uint32_t i = 0;; i++) {
InspectionBuffer *buffer = GetBuffer(det_ctx, flags, transforms, txv, i, engine->sm_list);
if (buffer == NULL || buffer->inspect == NULL) {
break;
}
const bool match = DetectEngineContentInspectionBuffer(de_ctx, det_ctx, s, engine->smd,
NULL, f, buffer, DETECT_ENGINE_CONTENT_INSPECTION_MODE_STATE);
if (match) {
return DETECT_ENGINE_INSPECT_SIG_MATCH;
}
}
return DETECT_ENGINE_INSPECT_SIG_NO_MATCH;
}
static void PrefilterTx(DetectEngineThreadCtx *det_ctx, const void *pectx, Packet *p, Flow *f,
void *txv, const uint64_t idx, const AppLayerTxData *_txd, const uint8_t flags)
{
SCEnter();
const PrefilterMpm *ctx = (const PrefilterMpm *)pectx;
const MpmCtx *mpm_ctx = ctx->mpm_ctx;
const int list_id = ctx->list_id;
for (uint32_t i = 0;; i++) {
InspectionBuffer *buffer = GetBuffer(det_ctx, flags, ctx->transforms, txv, i, list_id);
if (buffer == NULL) {
break;
}
if (buffer->inspect_len >= mpm_ctx->minlen) {
(void)mpm_table[mpm_ctx->mpm_type].Search(
mpm_ctx, &det_ctx->mtc, &det_ctx->pmq, buffer->inspect, buffer->inspect_len);
PREFILTER_PROFILING_ADD_BYTES(det_ctx, buffer->inspect_len);
}
}
}
static void PrefilterMpmFree(void *ptr)
{
SCFree(ptr);
}
static int PrefilterMpmRegister(DetectEngineCtx *de_ctx, SigGroupHead *sgh, MpmCtx *mpm_ctx,
const DetectBufferMpmRegistry *mpm_reg, int list_id)
{
PrefilterMpm *pectx = SCCalloc(1, sizeof(*pectx));
if (pectx == NULL) {
return -1;
}
pectx->list_id = list_id;
pectx->mpm_ctx = mpm_ctx;
pectx->transforms = &mpm_reg->transforms;
return PrefilterAppendTxEngine(de_ctx, sgh, PrefilterTx, mpm_reg->app_v2.alproto,
mpm_reg->app_v2.tx_min_progress, pectx, PrefilterMpmFree, mpm_reg->pname);
}
void DetectDnsQueryNameRegister(void)
{
static const char *keyword = "dns.query.name";
@ -154,15 +81,8 @@ void DetectDnsQueryNameRegister(void)
/* Register in both directions as the query is usually echoed back
in the response. */
DetectAppLayerInspectEngineRegister(
keyword, ALPROTO_DNS, SIG_FLAG_TOSERVER, 0, DetectEngineInspectCb, NULL);
DetectAppLayerMpmRegister(
keyword, SIG_FLAG_TOSERVER, 2, PrefilterMpmRegister, NULL, ALPROTO_DNS, 1);
DetectAppLayerInspectEngineRegister(
keyword, ALPROTO_DNS, SIG_FLAG_TOCLIENT, 0, DetectEngineInspectCb, NULL);
DetectAppLayerMpmRegister(
keyword, SIG_FLAG_TOCLIENT, 2, PrefilterMpmRegister, NULL, ALPROTO_DNS, 1);
DetectAppLayerMultiRegister(keyword, ALPROTO_DNS, SIG_FLAG_TOSERVER, 0, GetBuffer, 2, 1);
DetectAppLayerMultiRegister(keyword, ALPROTO_DNS, SIG_FLAG_TOCLIENT, 0, GetBuffer, 2, 1);
DetectBufferTypeSetDescriptionByName(keyword, "dns query name");
DetectBufferTypeSupportsMultiInstance(keyword);

@ -67,19 +67,13 @@ static void DetectDnsQueryRegisterTests(void);
#endif
static int g_dns_query_buffer_id = 0;
struct DnsQueryGetDataArgs {
uint32_t local_id; /**< used as index into thread inspect array */
void *txv;
};
static InspectionBuffer *DnsQueryGetData(DetectEngineThreadCtx *det_ctx,
const DetectEngineTransforms *transforms, Flow *f, struct DnsQueryGetDataArgs *cbdata,
int list_id)
const DetectEngineTransforms *transforms, Flow *f, const uint8_t flags, void *txv,
int list_id, uint32_t local_id)
{
SCEnter();
InspectionBuffer *buffer =
InspectionBufferMultipleForListGet(det_ctx, list_id, cbdata->local_id);
InspectionBuffer *buffer = InspectionBufferMultipleForListGet(det_ctx, list_id, local_id);
if (buffer == NULL)
return NULL;
if (buffer->initialized)
@ -87,7 +81,7 @@ static InspectionBuffer *DnsQueryGetData(DetectEngineThreadCtx *det_ctx,
const uint8_t *data;
uint32_t data_len;
if (SCDnsTxGetQueryName(cbdata->txv, false, cbdata->local_id, &data, &data_len) == 0) {
if (SCDnsTxGetQueryName(txv, false, local_id, &data, &data_len) == 0) {
InspectionBufferSetupMultiEmpty(buffer);
return NULL;
}
@ -97,96 +91,6 @@ static InspectionBuffer *DnsQueryGetData(DetectEngineThreadCtx *det_ctx,
SCReturnPtr(buffer, "InspectionBuffer");
}
static uint8_t DetectEngineInspectDnsQuery(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx,
const DetectEngineAppInspectionEngine *engine, const Signature *s, Flow *f, uint8_t flags,
void *alstate, void *txv, uint64_t tx_id)
{
uint32_t local_id = 0;
const DetectEngineTransforms *transforms = NULL;
if (!engine->mpm) {
transforms = engine->v2.transforms;
}
while(1) {
struct DnsQueryGetDataArgs cbdata = { local_id, txv, };
InspectionBuffer *buffer =
DnsQueryGetData(det_ctx, transforms, f, &cbdata, engine->sm_list);
if (buffer == NULL || buffer->inspect == NULL)
break;
const bool match = DetectEngineContentInspectionBuffer(de_ctx, det_ctx, s, engine->smd,
NULL, f, buffer, DETECT_ENGINE_CONTENT_INSPECTION_MODE_STATE);
if (match) {
return DETECT_ENGINE_INSPECT_SIG_MATCH;
}
local_id++;
}
return DETECT_ENGINE_INSPECT_SIG_NO_MATCH;
}
typedef struct PrefilterMpmDnsQuery {
int list_id;
const MpmCtx *mpm_ctx;
const DetectEngineTransforms *transforms;
} PrefilterMpmDnsQuery;
/** \brief DnsQuery DnsQuery Mpm prefilter callback
*
* \param det_ctx detection engine thread ctx
* \param p packet to inspect
* \param f flow to inspect
* \param txv tx to inspect
* \param pectx inspection context
*/
static void PrefilterTxDnsQuery(DetectEngineThreadCtx *det_ctx, const void *pectx, Packet *p,
Flow *f, void *txv, const uint64_t idx, const AppLayerTxData *_txd, const uint8_t flags)
{
SCEnter();
const PrefilterMpmDnsQuery *ctx = (const PrefilterMpmDnsQuery *)pectx;
const MpmCtx *mpm_ctx = ctx->mpm_ctx;
const int list_id = ctx->list_id;
uint32_t local_id = 0;
while(1) {
// loop until we get a NULL
struct DnsQueryGetDataArgs cbdata = { local_id, txv };
InspectionBuffer *buffer = DnsQueryGetData(det_ctx, ctx->transforms, f, &cbdata, list_id);
if (buffer == NULL)
break;
if (buffer->inspect_len >= mpm_ctx->minlen) {
(void)mpm_table[mpm_ctx->mpm_type].Search(
mpm_ctx, &det_ctx->mtc, &det_ctx->pmq, buffer->inspect, buffer->inspect_len);
PREFILTER_PROFILING_ADD_BYTES(det_ctx, buffer->inspect_len);
}
local_id++;
}
}
static void PrefilterMpmDnsQueryFree(void *ptr)
{
SCFree(ptr);
}
static int PrefilterMpmDnsQueryRegister(DetectEngineCtx *de_ctx, SigGroupHead *sgh, MpmCtx *mpm_ctx,
const DetectBufferMpmRegistry *mpm_reg, int list_id)
{
PrefilterMpmDnsQuery *pectx = SCCalloc(1, sizeof(*pectx));
if (pectx == NULL)
return -1;
pectx->list_id = list_id;
pectx->mpm_ctx = mpm_ctx;
pectx->transforms = &mpm_reg->transforms;
return PrefilterAppendTxEngine(de_ctx, sgh, PrefilterTxDnsQuery,
mpm_reg->app_v2.alproto, mpm_reg->app_v2.tx_min_progress,
pectx, PrefilterMpmDnsQueryFree, mpm_reg->pname);
}
/**
* \brief Registration function for keyword: dns_query
*/
@ -203,11 +107,8 @@ void DetectDnsQueryRegister (void)
sigmatch_table[DETECT_AL_DNS_QUERY].flags |= SIGMATCH_NOOPT;
sigmatch_table[DETECT_AL_DNS_QUERY].flags |= SIGMATCH_INFO_STICKY_BUFFER;
DetectAppLayerMpmRegister(
"dns_query", SIG_FLAG_TOSERVER, 2, PrefilterMpmDnsQueryRegister, NULL, ALPROTO_DNS, 1);
DetectAppLayerInspectEngineRegister(
"dns_query", ALPROTO_DNS, SIG_FLAG_TOSERVER, 1, DetectEngineInspectDnsQuery, NULL);
DetectAppLayerMultiRegister(
"dns_query", ALPROTO_DNS, SIG_FLAG_TOSERVER, 1, DnsQueryGetData, 2, 1);
DetectBufferTypeSetDescriptionByName("dns_query",
"dns request query");

@ -86,9 +86,9 @@ static int g_mpm_list_cnt[DETECT_BUFFER_MPM_TYPE_SIZE] = { 0, 0, 0 };
*
* \note to be used at start up / registration only. Errors are fatal.
*/
void DetectAppLayerMpmRegister(const char *name, int direction, int priority,
static void RegisterInternal(const char *name, int direction, int priority,
PrefilterRegisterFunc PrefilterRegister, InspectionBufferGetDataPtr GetData,
AppProto alproto, int tx_min_progress)
InspectionMultiBufferGetDataPtr GetMultiData, AppProto alproto, int tx_min_progress)
{
SCLogDebug("registering %s/%d/%d/%p/%p/%u/%d", name, direction, priority,
PrefilterRegister, GetData, alproto, tx_min_progress);
@ -119,7 +119,11 @@ void DetectAppLayerMpmRegister(const char *name, int direction, int priority,
am->type = DETECT_BUFFER_MPM_TYPE_APP;
am->PrefilterRegisterWithListId = PrefilterRegister;
am->app_v2.GetData = GetData;
if (GetData != NULL) {
am->app_v2.GetData = GetData;
} else if (GetMultiData != NULL) {
am->app_v2.GetMultiData = GetMultiData;
}
am->app_v2.alproto = alproto;
am->app_v2.tx_min_progress = tx_min_progress;
@ -139,6 +143,22 @@ void DetectAppLayerMpmRegister(const char *name, int direction, int priority,
SupportFastPatternForSigMatchList(sm_list, priority);
}
void DetectAppLayerMpmRegister(const char *name, int direction, int priority,
PrefilterRegisterFunc PrefilterRegister, InspectionBufferGetDataPtr GetData,
AppProto alproto, int tx_min_progress)
{
RegisterInternal(
name, direction, priority, PrefilterRegister, GetData, NULL, alproto, tx_min_progress);
}
void DetectAppLayerMpmMultiRegister(const char *name, int direction, int priority,
PrefilterRegisterFunc PrefilterRegister, InspectionMultiBufferGetDataPtr GetData,
AppProto alproto, int tx_min_progress)
{
RegisterInternal(
name, direction, priority, PrefilterRegister, NULL, GetData, alproto, tx_min_progress);
}
/** \brief copy a mpm engine from parent_id, add in transforms */
void DetectAppLayerMpmRegisterByParentId(DetectEngineCtx *de_ctx,
const int id, const int parent_id,

@ -90,6 +90,9 @@ typedef int (*PrefilterRegisterFunc)(DetectEngineCtx *de_ctx, SigGroupHead *sgh,
void DetectAppLayerMpmRegister(const char *name, int direction, int priority,
PrefilterRegisterFunc PrefilterRegister, InspectionBufferGetDataPtr GetData,
AppProto alproto, int tx_min_progress);
void DetectAppLayerMpmMultiRegister(const char *name, int direction, int priority,
PrefilterRegisterFunc PrefilterRegister, InspectionMultiBufferGetDataPtr GetData,
AppProto alproto, int tx_min_progress);
void DetectAppLayerMpmRegisterByParentId(
DetectEngineCtx *de_ctx,
const int id, const int parent_id,
@ -122,6 +125,7 @@ int PrefilterGenericMpmFrameRegister(DetectEngineCtx *de_ctx, SigGroupHead *sgh,
typedef struct PrefilterMpmListId {
int list_id;
const MpmCtx *mpm_ctx;
InspectionMultiBufferGetDataPtr GetData;
const DetectEngineTransforms *transforms;
} PrefilterMpmListId;

@ -763,6 +763,59 @@ int PrefilterGenericMpmRegister(DetectEngineCtx *de_ctx, SigGroupHead *sgh, MpmC
return r;
}
static void PrefilterMultiGenericMpmFree(void *ptr)
{
// PrefilterMpmListId
SCFree(ptr);
}
static void PrefilterMultiMpm(DetectEngineThreadCtx *det_ctx, const void *pectx, Packet *p, Flow *f,
void *txv, const uint64_t idx, const AppLayerTxData *_txd, const uint8_t flags)
{
SCEnter();
const PrefilterMpmListId *ctx = (const PrefilterMpmListId *)pectx;
const MpmCtx *mpm_ctx = ctx->mpm_ctx;
SCLogDebug("running on list %d", ctx->list_id);
uint32_t local_id = 0;
do {
// loop until we get a NULL
InspectionBuffer *buffer =
ctx->GetData(det_ctx, ctx->transforms, f, flags, txv, ctx->list_id, local_id);
if (buffer == NULL)
break;
if (buffer->inspect_len >= mpm_ctx->minlen) {
(void)mpm_table[mpm_ctx->mpm_type].Search(
mpm_ctx, &det_ctx->mtc, &det_ctx->pmq, buffer->inspect, buffer->inspect_len);
PREFILTER_PROFILING_ADD_BYTES(det_ctx, buffer->inspect_len);
}
local_id++;
} while (1);
}
int PrefilterMultiGenericMpmRegister(DetectEngineCtx *de_ctx, SigGroupHead *sgh, MpmCtx *mpm_ctx,
const DetectBufferMpmRegistry *mpm_reg, int list_id)
{
SCEnter();
PrefilterMpmListId *pectx = SCCalloc(1, sizeof(*pectx));
if (pectx == NULL)
return -1;
pectx->list_id = list_id;
pectx->GetData = mpm_reg->app_v2.GetMultiData;
pectx->mpm_ctx = mpm_ctx;
pectx->transforms = &mpm_reg->transforms;
int r = PrefilterAppendTxEngine(de_ctx, sgh, PrefilterMultiMpm, mpm_reg->app_v2.alproto,
mpm_reg->app_v2.tx_min_progress, pectx, PrefilterMultiGenericMpmFree, mpm_reg->pname);
if (r != 0) {
SCFree(pectx);
}
return r;
}
/* generic mpm for pkt engines */
typedef struct PrefilterMpmPktCtx {

@ -89,6 +89,9 @@ void PrefilterDeinit(DetectEngineCtx *de_ctx);
int PrefilterGenericMpmRegister(DetectEngineCtx *de_ctx, SigGroupHead *sgh, MpmCtx *mpm_ctx,
const DetectBufferMpmRegistry *mpm_reg, int list_id);
int PrefilterMultiGenericMpmRegister(DetectEngineCtx *de_ctx, SigGroupHead *sgh, MpmCtx *mpm_ctx,
const DetectBufferMpmRegistry *mpm_reg, int list_id);
int PrefilterGenericMpmPktRegister(DetectEngineCtx *de_ctx, SigGroupHead *sgh, MpmCtx *mpm_ctx,
const DetectBufferMpmRegistry *mpm_reg, int list_id);

@ -166,8 +166,9 @@ void DetectPktInspectEngineRegister(const char *name,
/** \brief register inspect engine at start up time
*
* \note errors are fatal */
void DetectAppLayerInspectEngineRegister(const char *name, AppProto alproto, uint32_t dir,
int progress, InspectEngineFuncPtr Callback, InspectionBufferGetDataPtr GetData)
static void AppLayerInspectEngineRegisterInternal(const char *name, AppProto alproto, uint32_t dir,
int progress, InspectEngineFuncPtr Callback, InspectionBufferGetDataPtr GetData,
InspectionMultiBufferGetDataPtr GetMultiData)
{
BUG_ON(progress >= 48);
@ -187,6 +188,10 @@ void DetectAppLayerInspectEngineRegister(const char *name, AppProto alproto, uin
SCLogError("Invalid arguments: must register "
"GetData with DetectEngineInspectBufferGeneric");
BUG_ON(1);
} else if (Callback == DetectEngineInspectMultiBufferGeneric && GetMultiData == NULL) {
SCLogError("Invalid arguments: must register "
"GetData with DetectEngineInspectMultiBufferGeneric");
BUG_ON(1);
}
uint8_t direction;
@ -207,7 +212,11 @@ void DetectAppLayerInspectEngineRegister(const char *name, AppProto alproto, uin
new_engine->sm_list_base = (uint16_t)sm_list;
new_engine->progress = (int16_t)progress;
new_engine->v2.Callback = Callback;
new_engine->v2.GetData = GetData;
if (Callback == DetectEngineInspectBufferGeneric) {
new_engine->v2.GetData = GetData;
} else if (Callback == DetectEngineInspectMultiBufferGeneric) {
new_engine->v2.GetMultiData = GetMultiData;
}
if (g_app_inspect_engines == NULL) {
g_app_inspect_engines = new_engine;
@ -221,6 +230,12 @@ void DetectAppLayerInspectEngineRegister(const char *name, AppProto alproto, uin
}
}
void DetectAppLayerInspectEngineRegister(const char *name, AppProto alproto, uint32_t dir,
int progress, InspectEngineFuncPtr Callback, InspectionBufferGetDataPtr GetData)
{
AppLayerInspectEngineRegisterInternal(name, alproto, dir, progress, Callback, GetData, NULL);
}
/* copy an inspect engine with transforms to a new list id. */
static void DetectAppLayerInspectEngineCopy(
DetectEngineCtx *de_ctx,
@ -2164,6 +2179,46 @@ uint8_t DetectEngineInspectBufferGeneric(DetectEngineCtx *de_ctx, DetectEngineTh
}
}
// wrapper for both DetectAppLayerInspectEngineRegister and DetectAppLayerMpmRegister
// with cast of callback function
void DetectAppLayerMultiRegister(const char *name, AppProto alproto, uint32_t dir, int progress,
InspectionMultiBufferGetDataPtr GetData, int priority, int tx_min_progress)
{
AppLayerInspectEngineRegisterInternal(
name, alproto, dir, progress, DetectEngineInspectMultiBufferGeneric, NULL, GetData);
DetectAppLayerMpmMultiRegister(name, dir, priority, PrefilterMultiGenericMpmRegister, GetData,
alproto, tx_min_progress);
}
uint8_t DetectEngineInspectMultiBufferGeneric(DetectEngineCtx *de_ctx,
DetectEngineThreadCtx *det_ctx, const DetectEngineAppInspectionEngine *engine,
const Signature *s, Flow *f, uint8_t flags, void *alstate, void *txv, uint64_t tx_id)
{
uint32_t local_id = 0;
const DetectEngineTransforms *transforms = NULL;
if (!engine->mpm) {
transforms = engine->v2.transforms;
}
do {
InspectionBuffer *buffer = engine->v2.GetMultiData(
det_ctx, transforms, f, flags, txv, engine->sm_list, local_id);
if (buffer == NULL || buffer->inspect == NULL)
break;
// The GetData functions set buffer->flags to DETECT_CI_FLAGS_SINGLE
// This is not meant for streaming buffers
const bool match = DetectEngineContentInspectionBuffer(de_ctx, det_ctx, s, engine->smd,
NULL, f, buffer, DETECT_ENGINE_CONTENT_INSPECTION_MODE_STATE);
if (match) {
return DETECT_ENGINE_INSPECT_SIG_MATCH;
}
local_id++;
} while (1);
return DETECT_ENGINE_INSPECT_SIG_NO_MATCH;
}
/**
* \brief Do the content inspection & validation for a signature
*

@ -146,6 +146,10 @@ uint8_t DetectEngineInspectBufferGeneric(DetectEngineCtx *de_ctx, DetectEngineTh
const DetectEngineAppInspectionEngine *engine, const Signature *s, Flow *f, uint8_t flags,
void *alstate, void *txv, uint64_t tx_id);
uint8_t DetectEngineInspectMultiBufferGeneric(DetectEngineCtx *de_ctx,
DetectEngineThreadCtx *det_ctx, const DetectEngineAppInspectionEngine *engine,
const Signature *s, Flow *f, uint8_t flags, void *alstate, void *txv, uint64_t tx_id);
int DetectEngineInspectPktBufferGeneric(
DetectEngineThreadCtx *det_ctx,
const DetectEnginePktInspectionEngine *engine,
@ -164,6 +168,9 @@ int DetectEngineInspectPktBufferGeneric(
void DetectAppLayerInspectEngineRegister(const char *name, AppProto alproto, uint32_t dir,
int progress, InspectEngineFuncPtr Callback2, InspectionBufferGetDataPtr GetData);
void DetectAppLayerMultiRegister(const char *name, AppProto alproto, uint32_t dir, int progress,
InspectionMultiBufferGetDataPtr GetData, int priority, int tx_min_progress);
void DetectPktInspectEngineRegister(const char *name,
InspectionBufferGetPktDataPtr GetPktData,
InspectionBufferPktInspectFunc Callback);

@ -466,113 +466,6 @@ static int g_http_response_header_buffer_id = 0;
static int g_request_header_thread_id = 0;
static int g_response_header_thread_id = 0;
static InspectionBuffer *GetHttp2HeaderData(DetectEngineThreadCtx *det_ctx, const uint8_t flags,
const DetectEngineTransforms *transforms, Flow *_f, const struct MpmListIdDataArgs *cbdata,
int list_id)
{
SCEnter();
InspectionBuffer *buffer =
InspectionBufferMultipleForListGet(det_ctx, list_id, cbdata->local_id);
if (buffer == NULL)
return NULL;
if (buffer->initialized)
return buffer;
uint32_t b_len = 0;
const uint8_t *b = NULL;
if (rs_http2_tx_get_header(cbdata->txv, flags, cbdata->local_id, &b, &b_len) != 1) {
InspectionBufferSetupMultiEmpty(buffer);
return NULL;
}
if (b == NULL || b_len == 0) {
InspectionBufferSetupMultiEmpty(buffer);
return NULL;
}
InspectionBufferSetupMulti(buffer, transforms, b, b_len);
SCReturnPtr(buffer, "InspectionBuffer");
}
static void PrefilterTxHttp2Header(DetectEngineThreadCtx *det_ctx, const void *pectx, Packet *p,
Flow *f, void *txv, const uint64_t idx, const AppLayerTxData *_txd, const uint8_t flags)
{
SCEnter();
const PrefilterMpmListId *ctx = (const PrefilterMpmListId *)pectx;
const MpmCtx *mpm_ctx = ctx->mpm_ctx;
const int list_id = ctx->list_id;
uint32_t local_id = 0;
while (1) {
// loop until we get a NULL
struct MpmListIdDataArgs cbdata = { local_id, txv };
InspectionBuffer *buffer =
GetHttp2HeaderData(det_ctx, flags, ctx->transforms, f, &cbdata, list_id);
if (buffer == NULL)
break;
if (buffer->inspect_len >= mpm_ctx->minlen) {
(void)mpm_table[mpm_ctx->mpm_type].Search(
mpm_ctx, &det_ctx->mtc, &det_ctx->pmq, buffer->inspect, buffer->inspect_len);
PREFILTER_PROFILING_ADD_BYTES(det_ctx, buffer->inspect_len);
}
local_id++;
}
}
static uint8_t DetectEngineInspectHttp2Header(DetectEngineCtx *de_ctx,
DetectEngineThreadCtx *det_ctx, const DetectEngineAppInspectionEngine *engine,
const Signature *s, Flow *f, uint8_t flags, void *alstate, void *txv, uint64_t tx_id)
{
uint32_t local_id = 0;
const DetectEngineTransforms *transforms = NULL;
if (!engine->mpm) {
transforms = engine->v2.transforms;
}
while (1) {
struct MpmListIdDataArgs cbdata = {
local_id,
txv,
};
InspectionBuffer *buffer =
GetHttp2HeaderData(det_ctx, flags, transforms, f, &cbdata, engine->sm_list);
if (buffer == NULL || buffer->inspect == NULL)
break;
const bool match = DetectEngineContentInspection(de_ctx, det_ctx, s, engine->smd, NULL, f,
buffer->inspect, buffer->inspect_len, buffer->inspect_offset,
DETECT_CI_FLAGS_SINGLE, DETECT_ENGINE_CONTENT_INSPECTION_MODE_STATE);
if (match) {
return DETECT_ENGINE_INSPECT_SIG_MATCH;
}
local_id++;
}
return DETECT_ENGINE_INSPECT_SIG_NO_MATCH;
}
static int PrefilterMpmHttp2HeaderRegister(DetectEngineCtx *de_ctx, SigGroupHead *sgh,
MpmCtx *mpm_ctx, const DetectBufferMpmRegistry *mpm_reg, int list_id)
{
PrefilterMpmListId *pectx = SCCalloc(1, sizeof(*pectx));
if (pectx == NULL)
return -1;
pectx->list_id = list_id;
pectx->mpm_ctx = mpm_ctx;
pectx->transforms = &mpm_reg->transforms;
return PrefilterAppendTxEngine(de_ctx, sgh, PrefilterTxHttp2Header, mpm_reg->app_v2.alproto,
mpm_reg->app_v2.tx_min_progress, pectx, PrefilterMpmHttpHeaderFree, mpm_reg->name);
}
typedef struct HttpMultiBufItem {
uint8_t *buffer;
size_t len;
@ -610,14 +503,42 @@ static void HttpMultiBufHeaderThreadDataFree(void *data)
SCFree(td);
}
static InspectionBuffer *GetHttp1HeaderData(DetectEngineThreadCtx *det_ctx, const uint8_t flags,
const DetectEngineTransforms *transforms, Flow *f, const struct MpmListIdDataArgs *cbdata,
int list_id)
static InspectionBuffer *GetHttp2HeaderData(DetectEngineThreadCtx *det_ctx,
const DetectEngineTransforms *transforms, Flow *f, const uint8_t flags, void *txv,
int list_id, uint32_t local_id)
{
SCEnter();
InspectionBuffer *buffer =
InspectionBufferMultipleForListGet(det_ctx, list_id, cbdata->local_id);
InspectionBuffer *buffer = InspectionBufferMultipleForListGet(det_ctx, list_id, local_id);
if (buffer == NULL)
return NULL;
if (buffer->initialized)
return buffer;
uint32_t b_len = 0;
const uint8_t *b = NULL;
if (rs_http2_tx_get_header(txv, flags, local_id, &b, &b_len) != 1) {
InspectionBufferSetupMultiEmpty(buffer);
return NULL;
}
if (b == NULL || b_len == 0) {
InspectionBufferSetupMultiEmpty(buffer);
return NULL;
}
InspectionBufferSetupMulti(buffer, transforms, b, b_len);
buffer->flags = DETECT_CI_FLAGS_SINGLE;
SCReturnPtr(buffer, "InspectionBuffer");
}
static InspectionBuffer *GetHttp1HeaderData(DetectEngineThreadCtx *det_ctx,
const DetectEngineTransforms *transforms, Flow *f, const uint8_t flags, void *txv,
int list_id, uint32_t local_id)
{
SCEnter();
InspectionBuffer *buffer = InspectionBufferMultipleForListGet(det_ctx, list_id, local_id);
if (buffer == NULL)
return NULL;
if (buffer->initialized)
@ -635,7 +556,7 @@ static InspectionBuffer *GetHttp1HeaderData(DetectEngineThreadCtx *det_ctx, cons
return NULL;
}
htp_tx_t *tx = (htp_tx_t *)cbdata->txv;
htp_tx_t *tx = (htp_tx_t *)txv;
htp_table_t *headers;
if (flags & STREAM_TOSERVER) {
headers = tx->request_headers;
@ -643,7 +564,7 @@ static InspectionBuffer *GetHttp1HeaderData(DetectEngineThreadCtx *det_ctx, cons
headers = tx->response_headers;
}
size_t no_of_headers = htp_table_size(headers);
if (cbdata->local_id == 0) {
if (local_id == 0) {
// We initialize a big buffer on first item
// Then, we will just use parts of it
hdr_td->len = 0;
@ -682,93 +603,17 @@ static InspectionBuffer *GetHttp1HeaderData(DetectEngineThreadCtx *det_ctx, cons
// cbdata->local_id is the index of the requested header buffer
// hdr_td->len is the number of header buffers
if (cbdata->local_id < hdr_td->len) {
if (local_id < hdr_td->len) {
// we have one valid header buffer
InspectionBufferSetupMulti(buffer, transforms, hdr_td->items[cbdata->local_id].buffer,
hdr_td->items[cbdata->local_id].len);
InspectionBufferSetupMulti(
buffer, transforms, hdr_td->items[local_id].buffer, hdr_td->items[local_id].len);
buffer->flags = DETECT_CI_FLAGS_SINGLE;
SCReturnPtr(buffer, "InspectionBuffer");
} // else there are no more header buffer to get
InspectionBufferSetupMultiEmpty(buffer);
return NULL;
}
static void PrefilterTxHttp1Header(DetectEngineThreadCtx *det_ctx, const void *pectx, Packet *p,
Flow *f, void *txv, const uint64_t idx, const AppLayerTxData *_txd, const uint8_t flags)
{
SCEnter();
const PrefilterMpmListId *ctx = (const PrefilterMpmListId *)pectx;
const MpmCtx *mpm_ctx = ctx->mpm_ctx;
const int list_id = ctx->list_id;
uint32_t local_id = 0;
while (1) {
// loop until we get a NULL
struct MpmListIdDataArgs cbdata = { local_id, txv };
InspectionBuffer *buffer =
GetHttp1HeaderData(det_ctx, flags, ctx->transforms, f, &cbdata, list_id);
if (buffer == NULL)
break;
if (buffer->inspect_len >= mpm_ctx->minlen) {
(void)mpm_table[mpm_ctx->mpm_type].Search(
mpm_ctx, &det_ctx->mtc, &det_ctx->pmq, buffer->inspect, buffer->inspect_len);
PREFILTER_PROFILING_ADD_BYTES(det_ctx, buffer->inspect_len);
}
local_id++;
}
}
static int PrefilterMpmHttp1HeaderRegister(DetectEngineCtx *de_ctx, SigGroupHead *sgh,
MpmCtx *mpm_ctx, const DetectBufferMpmRegistry *mpm_reg, int list_id)
{
PrefilterMpmListId *pectx = SCCalloc(1, sizeof(*pectx));
if (pectx == NULL)
return -1;
pectx->list_id = list_id;
pectx->mpm_ctx = mpm_ctx;
pectx->transforms = &mpm_reg->transforms;
return PrefilterAppendTxEngine(de_ctx, sgh, PrefilterTxHttp1Header, mpm_reg->app_v2.alproto,
mpm_reg->app_v2.tx_min_progress, pectx, PrefilterMpmHttpHeaderFree, mpm_reg->name);
}
static uint8_t DetectEngineInspectHttp1Header(DetectEngineCtx *de_ctx,
DetectEngineThreadCtx *det_ctx, const DetectEngineAppInspectionEngine *engine,
const Signature *s, Flow *f, uint8_t flags, void *alstate, void *txv, uint64_t tx_id)
{
uint32_t local_id = 0;
const DetectEngineTransforms *transforms = NULL;
if (!engine->mpm) {
transforms = engine->v2.transforms;
}
while (1) {
struct MpmListIdDataArgs cbdata = {
local_id,
txv,
};
InspectionBuffer *buffer =
GetHttp1HeaderData(det_ctx, flags, transforms, f, &cbdata, engine->sm_list);
if (buffer == NULL || buffer->inspect == NULL)
break;
const bool match = DetectEngineContentInspection(de_ctx, det_ctx, s, engine->smd, NULL, f,
(uint8_t *)buffer->inspect, buffer->inspect_len, buffer->inspect_offset,
DETECT_CI_FLAGS_SINGLE, DETECT_ENGINE_CONTENT_INSPECTION_MODE_STATE);
if (match) {
return DETECT_ENGINE_INSPECT_SIG_MATCH;
}
local_id++;
}
return DETECT_ENGINE_INSPECT_SIG_NO_MATCH;
}
static int DetectHTTPRequestHeaderSetup(DetectEngineCtx *de_ctx, Signature *s, const char *arg)
{
if (DetectBufferSetActiveList(de_ctx, s, g_http_request_header_buffer_id) < 0)
@ -790,14 +635,10 @@ void DetectHttpRequestHeaderRegister(void)
sigmatch_table[DETECT_HTTP_REQUEST_HEADER].flags |=
SIGMATCH_NOOPT | SIGMATCH_INFO_STICKY_BUFFER;
DetectAppLayerMpmRegister("http_request_header", SIG_FLAG_TOSERVER, 2,
PrefilterMpmHttp2HeaderRegister, NULL, ALPROTO_HTTP2, HTTP2StateOpen);
DetectAppLayerInspectEngineRegister("http_request_header", ALPROTO_HTTP2, SIG_FLAG_TOSERVER,
HTTP2StateOpen, DetectEngineInspectHttp2Header, NULL);
DetectAppLayerMpmRegister("http_request_header", SIG_FLAG_TOSERVER, 2,
PrefilterMpmHttp1HeaderRegister, NULL, ALPROTO_HTTP1, 0);
DetectAppLayerInspectEngineRegister("http_request_header", ALPROTO_HTTP1, SIG_FLAG_TOSERVER,
HTP_REQUEST_HEADERS, DetectEngineInspectHttp1Header, NULL);
DetectAppLayerMultiRegister("http_request_header", ALPROTO_HTTP2, SIG_FLAG_TOSERVER,
HTTP2StateOpen, GetHttp2HeaderData, 2, HTTP2StateOpen);
DetectAppLayerMultiRegister("http_request_header", ALPROTO_HTTP1, SIG_FLAG_TOSERVER,
HTP_REQUEST_HEADERS, GetHttp1HeaderData, 2, 0);
DetectBufferTypeSetDescriptionByName("http_request_header", "HTTP header name and value");
g_http_request_header_buffer_id = DetectBufferTypeGetByName("http_request_header");
@ -827,14 +668,10 @@ void DetectHttpResponseHeaderRegister(void)
sigmatch_table[DETECT_HTTP_RESPONSE_HEADER].flags |=
SIGMATCH_NOOPT | SIGMATCH_INFO_STICKY_BUFFER;
DetectAppLayerMpmRegister("http_response_header", SIG_FLAG_TOCLIENT, 2,
PrefilterMpmHttp2HeaderRegister, NULL, ALPROTO_HTTP2, HTTP2StateOpen);
DetectAppLayerInspectEngineRegister("http_response_header", ALPROTO_HTTP2, SIG_FLAG_TOCLIENT,
HTTP2StateOpen, DetectEngineInspectHttp2Header, NULL);
DetectAppLayerMpmRegister("http_response_header", SIG_FLAG_TOCLIENT, 2,
PrefilterMpmHttp1HeaderRegister, NULL, ALPROTO_HTTP1, 0);
DetectAppLayerInspectEngineRegister("http_response_header", ALPROTO_HTTP1, SIG_FLAG_TOCLIENT,
HTP_RESPONSE_HEADERS, DetectEngineInspectHttp1Header, NULL);
DetectAppLayerMultiRegister("http_response_header", ALPROTO_HTTP2, SIG_FLAG_TOCLIENT,
HTTP2StateOpen, GetHttp2HeaderData, 2, HTTP2StateOpen);
DetectAppLayerMultiRegister("http_response_header", ALPROTO_HTTP1, SIG_FLAG_TOCLIENT,
HTP_RESPONSE_HEADERS, GetHttp1HeaderData, 2, 0);
DetectBufferTypeSetDescriptionByName("http_response_header", "HTTP header name and value");
g_http_response_header_buffer_id = DetectBufferTypeGetByName("http_response_header");

@ -86,11 +86,6 @@ static int DetectHTTP2settingsSetup (DetectEngineCtx *, Signature *, const char
void DetectHTTP2settingsFree (DetectEngineCtx *, void *);
static int DetectHTTP2headerNameSetup(DetectEngineCtx *de_ctx, Signature *s, const char *arg);
static int PrefilterMpmHttp2HeaderNameRegister(DetectEngineCtx *de_ctx, SigGroupHead *sgh,
MpmCtx *mpm_ctx, const DetectBufferMpmRegistry *mpm_reg, int list_id);
static uint8_t DetectEngineInspectHttp2HeaderName(DetectEngineCtx *de_ctx,
DetectEngineThreadCtx *det_ctx, const DetectEngineAppInspectionEngine *engine,
const Signature *s, Flow *f, uint8_t flags, void *alstate, void *txv, uint64_t tx_id);
#ifdef UNITTESTS
void DetectHTTP2RegisterTests (void);
@ -103,6 +98,36 @@ static int g_http2_header_name_buffer_id = 0;
* \brief Registration function for HTTP2 keywords
*/
static InspectionBuffer *GetHttp2HNameData(DetectEngineThreadCtx *det_ctx,
const DetectEngineTransforms *transforms, Flow *_f, const uint8_t flags, void *txv,
int list_id, uint32_t local_id)
{
SCEnter();
InspectionBuffer *buffer = InspectionBufferMultipleForListGet(det_ctx, list_id, local_id);
if (buffer == NULL)
return NULL;
if (buffer->initialized)
return buffer;
uint32_t b_len = 0;
const uint8_t *b = NULL;
if (rs_http2_tx_get_header_name(txv, flags, local_id, &b, &b_len) != 1) {
InspectionBufferSetupMultiEmpty(buffer);
return NULL;
}
if (b == NULL || b_len == 0) {
InspectionBufferSetupMultiEmpty(buffer);
return NULL;
}
InspectionBufferSetupMulti(buffer, transforms, b, b_len);
buffer->flags = DETECT_CI_FLAGS_SINGLE;
SCReturnPtr(buffer, "InspectionBuffer");
}
void DetectHttp2Register(void)
{
sigmatch_table[DETECT_HTTP2_FRAMETYPE].name = "http2.frametype";
@ -177,14 +202,10 @@ void DetectHttp2Register(void)
sigmatch_table[DETECT_HTTP2_HEADERNAME].Setup = DetectHTTP2headerNameSetup;
sigmatch_table[DETECT_HTTP2_HEADERNAME].flags |= SIGMATCH_NOOPT | SIGMATCH_INFO_STICKY_BUFFER;
DetectAppLayerMpmRegister("http2_header_name", SIG_FLAG_TOCLIENT, 2,
PrefilterMpmHttp2HeaderNameRegister, NULL, ALPROTO_HTTP2, HTTP2StateOpen);
DetectAppLayerInspectEngineRegister("http2_header_name", ALPROTO_HTTP2, SIG_FLAG_TOCLIENT,
HTTP2StateOpen, DetectEngineInspectHttp2HeaderName, NULL);
DetectAppLayerMpmRegister("http2_header_name", SIG_FLAG_TOSERVER, 2,
PrefilterMpmHttp2HeaderNameRegister, NULL, ALPROTO_HTTP2, HTTP2StateOpen);
DetectAppLayerInspectEngineRegister("http2_header_name", ALPROTO_HTTP2, SIG_FLAG_TOSERVER,
HTTP2StateOpen, DetectEngineInspectHttp2HeaderName, NULL);
DetectAppLayerMultiRegister("http2_header_name", ALPROTO_HTTP2, SIG_FLAG_TOCLIENT,
HTTP2StateOpen, GetHttp2HNameData, 2, HTTP2StateOpen);
DetectAppLayerMultiRegister("http2_header_name", ALPROTO_HTTP2, SIG_FLAG_TOSERVER,
HTTP2StateOpen, GetHttp2HNameData, 2, HTTP2StateOpen);
DetectBufferTypeSupportsMultiInstance("http2_header_name");
DetectBufferTypeSetDescriptionByName("http2_header_name",
"HTTP2 header name");
@ -597,119 +618,6 @@ static int DetectHTTP2headerNameSetup(DetectEngineCtx *de_ctx, Signature *s, con
return 0;
}
static void PrefilterMpmHttp2HNameFree(void *ptr)
{
SCFree(ptr);
}
static InspectionBuffer *GetHttp2HNameData(DetectEngineThreadCtx *det_ctx, const uint8_t flags,
const DetectEngineTransforms *transforms, Flow *_f, const struct MpmListIdDataArgs *cbdata,
int list_id)
{
SCEnter();
InspectionBuffer *buffer =
InspectionBufferMultipleForListGet(det_ctx, list_id, cbdata->local_id);
if (buffer == NULL)
return NULL;
if (buffer->initialized)
return buffer;
uint32_t b_len = 0;
const uint8_t *b = NULL;
if (rs_http2_tx_get_header_name(cbdata->txv, flags, cbdata->local_id, &b, &b_len) != 1) {
InspectionBufferSetupMultiEmpty(buffer);
return NULL;
}
if (b == NULL || b_len == 0) {
InspectionBufferSetupMultiEmpty(buffer);
return NULL;
}
InspectionBufferSetupMulti(buffer, transforms, b, b_len);
SCReturnPtr(buffer, "InspectionBuffer");
}
static void PrefilterTxHttp2HName(DetectEngineThreadCtx *det_ctx, const void *pectx, Packet *p,
Flow *f, void *txv, const uint64_t idx, const AppLayerTxData *_txd, const uint8_t flags)
{
SCEnter();
const PrefilterMpmListId *ctx = (const PrefilterMpmListId *)pectx;
const MpmCtx *mpm_ctx = ctx->mpm_ctx;
const int list_id = ctx->list_id;
uint32_t local_id = 0;
while(1) {
// loop until we get a NULL
struct MpmListIdDataArgs cbdata = { local_id, txv };
InspectionBuffer *buffer =
GetHttp2HNameData(det_ctx, flags, ctx->transforms, f, &cbdata, list_id);
if (buffer == NULL)
break;
if (buffer->inspect_len >= mpm_ctx->minlen) {
(void)mpm_table[mpm_ctx->mpm_type].Search(
mpm_ctx, &det_ctx->mtc, &det_ctx->pmq, buffer->inspect, buffer->inspect_len);
PREFILTER_PROFILING_ADD_BYTES(det_ctx, buffer->inspect_len);
}
local_id++;
}
}
static int PrefilterMpmHttp2HeaderNameRegister(DetectEngineCtx *de_ctx, SigGroupHead *sgh,
MpmCtx *mpm_ctx, const DetectBufferMpmRegistry *mpm_reg, int list_id)
{
//TODOask use PrefilterMpmListId elsewhere
PrefilterMpmListId *pectx = SCCalloc(1, sizeof(*pectx));
if (pectx == NULL)
return -1;
pectx->list_id = list_id;
pectx->mpm_ctx = mpm_ctx;
pectx->transforms = &mpm_reg->transforms;
return PrefilterAppendTxEngine(de_ctx, sgh, PrefilterTxHttp2HName,
mpm_reg->app_v2.alproto, mpm_reg->app_v2.tx_min_progress,
pectx, PrefilterMpmHttp2HNameFree, mpm_reg->name);
}
static uint8_t DetectEngineInspectHttp2HeaderName(DetectEngineCtx *de_ctx,
DetectEngineThreadCtx *det_ctx, const DetectEngineAppInspectionEngine *engine,
const Signature *s, Flow *f, uint8_t flags, void *alstate, void *txv, uint64_t tx_id)
{
uint32_t local_id = 0;
const DetectEngineTransforms *transforms = NULL;
if (!engine->mpm) {
transforms = engine->v2.transforms;
}
while (1) {
//TODOask use MpmListIdDataArgs elsewhere
struct MpmListIdDataArgs cbdata = { local_id, txv, };
InspectionBuffer *buffer =
GetHttp2HNameData(det_ctx, flags, transforms, f, &cbdata, engine->sm_list);
if (buffer == NULL || buffer->inspect == NULL)
break;
const bool match = DetectEngineContentInspection(de_ctx, det_ctx, s, engine->smd, NULL, f,
buffer->inspect, buffer->inspect_len, buffer->inspect_offset,
DETECT_CI_FLAGS_SINGLE, DETECT_ENGINE_CONTENT_INSPECTION_MODE_STATE);
if (match) {
return DETECT_ENGINE_INSPECT_SIG_MATCH;
}
local_id++;
}
return DETECT_ENGINE_INSPECT_SIG_NO_MATCH;
}
#ifdef UNITTESTS
#include "tests/detect-http2.c"
#endif

@ -37,31 +37,15 @@
static int DetectIkeVendorSetup(DetectEngineCtx *, Signature *, const char *);
typedef struct {
char *vendor;
} DetectIkeVendorData;
struct IkeVendorGetDataArgs {
uint32_t local_id;
void *txv;
};
typedef struct PrefilterMpmIkeVendor {
int list_id;
const MpmCtx *mpm_ctx;
const DetectEngineTransforms *transforms;
} PrefilterMpmIkeVendor;
static int g_ike_vendor_buffer_id = 0;
static InspectionBuffer *IkeVendorGetData(DetectEngineThreadCtx *det_ctx,
const DetectEngineTransforms *transforms, Flow *f, struct IkeVendorGetDataArgs *cbdata,
int list_id)
const DetectEngineTransforms *transforms, Flow *f, const uint8_t flags, void *txv,
int list_id, uint32_t local_id)
{
SCEnter();
InspectionBuffer *buffer =
InspectionBufferMultipleForListGet(det_ctx, list_id, cbdata->local_id);
InspectionBuffer *buffer = InspectionBufferMultipleForListGet(det_ctx, list_id, local_id);
if (buffer == NULL)
return NULL;
if (buffer->initialized)
@ -69,103 +53,17 @@ static InspectionBuffer *IkeVendorGetData(DetectEngineThreadCtx *det_ctx,
const uint8_t *data;
uint32_t data_len;
if (rs_ike_tx_get_vendor(cbdata->txv, cbdata->local_id, &data, &data_len) == 0) {
if (rs_ike_tx_get_vendor(txv, local_id, &data, &data_len) == 0) {
InspectionBufferSetupMultiEmpty(buffer);
return NULL;
}
InspectionBufferSetupMulti(buffer, transforms, data, data_len);
buffer->flags = DETECT_CI_FLAGS_SINGLE;
SCReturnPtr(buffer, "InspectionBuffer");
}
/** \brief IkeVendor Mpm prefilter callback
*
* \param det_ctx detection engine thread ctx
* \param p packet to inspect
* \param f flow to inspect
* \param txv tx to inspect
* \param pectx inspection context
*/
static void PrefilterTxIkeVendor(DetectEngineThreadCtx *det_ctx, const void *pectx, Packet *p,
Flow *f, void *txv, const uint64_t idx, const AppLayerTxData *_txd, const uint8_t flags)
{
SCEnter();
const PrefilterMpmIkeVendor *ctx = (const PrefilterMpmIkeVendor *)pectx;
const MpmCtx *mpm_ctx = ctx->mpm_ctx;
const int list_id = ctx->list_id;
uint32_t local_id = 0;
while (1) {
struct IkeVendorGetDataArgs cbdata = { local_id, txv };
InspectionBuffer *buffer = IkeVendorGetData(det_ctx, ctx->transforms, f, &cbdata, list_id);
if (buffer == NULL)
break;
if (buffer->inspect_len >= mpm_ctx->minlen) {
(void)mpm_table[mpm_ctx->mpm_type].Search(
mpm_ctx, &det_ctx->mtc, &det_ctx->pmq, buffer->inspect, buffer->inspect_len);
PREFILTER_PROFILING_ADD_BYTES(det_ctx, buffer->inspect_len);
}
local_id++;
}
SCReturn;
}
static void PrefilterMpmIkeVendorFree(void *ptr)
{
if (ptr != NULL)
SCFree(ptr);
}
static int PrefilterMpmIkeVendorRegister(DetectEngineCtx *de_ctx, SigGroupHead *sgh,
MpmCtx *mpm_ctx, const DetectBufferMpmRegistry *mpm_reg, int list_id)
{
PrefilterMpmIkeVendor *pectx = SCCalloc(1, sizeof(*pectx));
if (pectx == NULL)
return -1;
pectx->list_id = list_id;
pectx->mpm_ctx = mpm_ctx;
pectx->transforms = &mpm_reg->transforms;
return PrefilterAppendTxEngine(de_ctx, sgh, PrefilterTxIkeVendor, mpm_reg->app_v2.alproto,
mpm_reg->app_v2.tx_min_progress, pectx, PrefilterMpmIkeVendorFree, mpm_reg->pname);
}
static uint8_t DetectEngineInspectIkeVendor(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx,
const DetectEngineAppInspectionEngine *engine, const Signature *s, Flow *f, uint8_t flags,
void *alstate, void *txv, uint64_t tx_id)
{
uint32_t local_id = 0;
const DetectEngineTransforms *transforms = NULL;
if (!engine->mpm) {
transforms = engine->v2.transforms;
}
while (1) {
struct IkeVendorGetDataArgs cbdata = {
local_id,
txv,
};
InspectionBuffer *buffer =
IkeVendorGetData(det_ctx, transforms, f, &cbdata, engine->sm_list);
if (buffer == NULL || buffer->inspect == NULL)
break;
const bool match = DetectEngineContentInspection(de_ctx, det_ctx, s, engine->smd, NULL, f,
buffer->inspect, buffer->inspect_len, buffer->inspect_offset,
DETECT_CI_FLAGS_SINGLE, DETECT_ENGINE_CONTENT_INSPECTION_MODE_STATE);
if (match) {
return DETECT_ENGINE_INSPECT_SIG_MATCH;
}
local_id++;
}
return DETECT_ENGINE_INSPECT_SIG_NO_MATCH;
}
/**
* \brief Registration function for ike.vendor keyword.
*/
@ -178,11 +76,8 @@ void DetectIkeVendorRegister(void)
sigmatch_table[DETECT_AL_IKE_VENDOR].flags |= SIGMATCH_NOOPT;
sigmatch_table[DETECT_AL_IKE_VENDOR].flags |= SIGMATCH_INFO_STICKY_BUFFER;
DetectAppLayerMpmRegister("ike.vendor", SIG_FLAG_TOSERVER, 1, PrefilterMpmIkeVendorRegister,
NULL, ALPROTO_IKE, 1);
DetectAppLayerInspectEngineRegister(
"ike.vendor", ALPROTO_IKE, SIG_FLAG_TOSERVER, 1, DetectEngineInspectIkeVendor, NULL);
DetectAppLayerMultiRegister(
"ike.vendor", ALPROTO_IKE, SIG_FLAG_TOSERVER, 1, IkeVendorGetData, 1, 1);
g_ike_vendor_buffer_id = DetectBufferTypeGetByName("ike.vendor");

@ -38,11 +38,6 @@
static int g_krb5_cname_buffer_id = 0;
struct Krb5PrincipalNameDataArgs {
uint32_t local_id; /**< used as index into thread inspect array */
void *txv;
};
static int DetectKrb5CNameSetup(DetectEngineCtx *de_ctx, Signature *s, const char *arg)
{
if (DetectBufferSetActiveList(de_ctx, s, g_krb5_cname_buffer_id) < 0)
@ -55,13 +50,12 @@ static int DetectKrb5CNameSetup(DetectEngineCtx *de_ctx, Signature *s, const cha
}
static InspectionBuffer *GetKrb5CNameData(DetectEngineThreadCtx *det_ctx,
const DetectEngineTransforms *transforms, Flow *_f,
const struct Krb5PrincipalNameDataArgs *cbdata, int list_id)
const DetectEngineTransforms *transforms, Flow *f, const uint8_t flags, void *txv,
int list_id, uint32_t local_id)
{
SCEnter();
InspectionBuffer *buffer =
InspectionBufferMultipleForListGet(det_ctx, list_id, cbdata->local_id);
InspectionBuffer *buffer = InspectionBufferMultipleForListGet(det_ctx, list_id, local_id);
if (buffer == NULL)
return NULL;
if (buffer->initialized)
@ -70,7 +64,7 @@ static InspectionBuffer *GetKrb5CNameData(DetectEngineThreadCtx *det_ctx,
uint32_t b_len = 0;
const uint8_t *b = NULL;
if (rs_krb5_tx_get_cname(cbdata->txv, cbdata->local_id, &b, &b_len) != 1) {
if (rs_krb5_tx_get_cname(txv, local_id, &b, &b_len) != 1) {
InspectionBufferSetupMultiEmpty(buffer);
return NULL;
}
@ -80,103 +74,11 @@ static InspectionBuffer *GetKrb5CNameData(DetectEngineThreadCtx *det_ctx,
}
InspectionBufferSetupMulti(buffer, transforms, b, b_len);
buffer->flags = DETECT_CI_FLAGS_SINGLE;
SCReturnPtr(buffer, "InspectionBuffer");
}
static uint8_t DetectEngineInspectKrb5CName(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx,
const DetectEngineAppInspectionEngine *engine, const Signature *s, Flow *f, uint8_t flags,
void *alstate, void *txv, uint64_t tx_id)
{
uint32_t local_id = 0;
const DetectEngineTransforms *transforms = NULL;
if (!engine->mpm) {
transforms = engine->v2.transforms;
}
while (1) {
struct Krb5PrincipalNameDataArgs cbdata = { local_id, txv, };
InspectionBuffer *buffer =
GetKrb5CNameData(det_ctx, transforms, f, &cbdata, engine->sm_list);
if (buffer == NULL || buffer->inspect == NULL)
break;
const bool match = DetectEngineContentInspection(de_ctx, det_ctx, s, engine->smd, NULL, f,
buffer->inspect, buffer->inspect_len, buffer->inspect_offset,
DETECT_CI_FLAGS_SINGLE, DETECT_ENGINE_CONTENT_INSPECTION_MODE_STATE);
if (match) {
return DETECT_ENGINE_INSPECT_SIG_MATCH;
}
local_id++;
}
return DETECT_ENGINE_INSPECT_SIG_NO_MATCH;
}
typedef struct PrefilterMpmKrb5Name {
int list_id;
const MpmCtx *mpm_ctx;
const DetectEngineTransforms *transforms;
} PrefilterMpmKrb5Name;
/** \brief Krb5CName Krb5CName Mpm prefilter callback
*
* \param det_ctx detection engine thread ctx
* \param p packet to inspect
* \param f flow to inspect
* \param txv tx to inspect
* \param pectx inspection context
*/
static void PrefilterTxKrb5CName(DetectEngineThreadCtx *det_ctx, const void *pectx, Packet *p,
Flow *f, void *txv, const uint64_t idx, const AppLayerTxData *_txd, const uint8_t flags)
{
SCEnter();
const PrefilterMpmKrb5Name *ctx = (const PrefilterMpmKrb5Name *)pectx;
const MpmCtx *mpm_ctx = ctx->mpm_ctx;
const int list_id = ctx->list_id;
uint32_t local_id = 0;
while(1) {
// loop until we get a NULL
struct Krb5PrincipalNameDataArgs cbdata = { local_id, txv };
InspectionBuffer *buffer = GetKrb5CNameData(det_ctx, ctx->transforms, f, &cbdata, list_id);
if (buffer == NULL)
break;
if (buffer->inspect_len >= mpm_ctx->minlen) {
(void)mpm_table[mpm_ctx->mpm_type].Search(
mpm_ctx, &det_ctx->mtc, &det_ctx->pmq, buffer->inspect, buffer->inspect_len);
PREFILTER_PROFILING_ADD_BYTES(det_ctx, buffer->inspect_len);
}
local_id++;
}
}
static void PrefilterMpmKrb5NameFree(void *ptr)
{
SCFree(ptr);
}
static int PrefilterMpmKrb5CNameRegister(DetectEngineCtx *de_ctx, SigGroupHead *sgh,
MpmCtx *mpm_ctx, const DetectBufferMpmRegistry *mpm_reg, int list_id)
{
PrefilterMpmKrb5Name *pectx = SCCalloc(1, sizeof(*pectx));
if (pectx == NULL)
return -1;
pectx->list_id = list_id;
pectx->mpm_ctx = mpm_ctx;
pectx->transforms = &mpm_reg->transforms;
return PrefilterAppendTxEngine(de_ctx, sgh, PrefilterTxKrb5CName,
mpm_reg->app_v2.alproto, mpm_reg->app_v2.tx_min_progress,
pectx, PrefilterMpmKrb5NameFree, mpm_reg->name);
}
void DetectKrb5CNameRegister(void)
{
sigmatch_table[DETECT_AL_KRB5_CNAME].name = "krb5.cname";
@ -186,11 +88,8 @@ void DetectKrb5CNameRegister(void)
sigmatch_table[DETECT_AL_KRB5_CNAME].flags |= SIGMATCH_NOOPT|SIGMATCH_INFO_STICKY_BUFFER;
sigmatch_table[DETECT_AL_KRB5_CNAME].desc = "sticky buffer to match on Kerberos 5 client name";
DetectAppLayerMpmRegister("krb5_cname", SIG_FLAG_TOCLIENT, 2, PrefilterMpmKrb5CNameRegister,
NULL, ALPROTO_KRB5, 1);
DetectAppLayerInspectEngineRegister(
"krb5_cname", ALPROTO_KRB5, SIG_FLAG_TOCLIENT, 0, DetectEngineInspectKrb5CName, NULL);
DetectAppLayerMultiRegister(
"krb5_cname", ALPROTO_KRB5, SIG_FLAG_TOCLIENT, 0, GetKrb5CNameData, 2, 1);
DetectBufferTypeSetDescriptionByName("krb5_cname",
"Kerberos 5 ticket client name");

@ -38,11 +38,6 @@
static int g_krb5_sname_buffer_id = 0;
struct Krb5PrincipalNameDataArgs {
uint32_t local_id; /**< used as index into thread inspect array */
void *txv;
};
static int DetectKrb5SNameSetup(DetectEngineCtx *de_ctx, Signature *s, const char *arg)
{
if (DetectBufferSetActiveList(de_ctx, s, g_krb5_sname_buffer_id) < 0)
@ -55,13 +50,12 @@ static int DetectKrb5SNameSetup(DetectEngineCtx *de_ctx, Signature *s, const cha
}
static InspectionBuffer *GetKrb5SNameData(DetectEngineThreadCtx *det_ctx,
const DetectEngineTransforms *transforms, Flow *_f,
const struct Krb5PrincipalNameDataArgs *cbdata, int list_id)
const DetectEngineTransforms *transforms, Flow *f, const uint8_t flags, void *txv,
int list_id, uint32_t local_id)
{
SCEnter();
InspectionBuffer *buffer =
InspectionBufferMultipleForListGet(det_ctx, list_id, cbdata->local_id);
InspectionBuffer *buffer = InspectionBufferMultipleForListGet(det_ctx, list_id, local_id);
if (buffer == NULL)
return NULL;
if (buffer->initialized)
@ -70,7 +64,7 @@ static InspectionBuffer *GetKrb5SNameData(DetectEngineThreadCtx *det_ctx,
uint32_t b_len = 0;
const uint8_t *b = NULL;
if (rs_krb5_tx_get_sname(cbdata->txv, cbdata->local_id, &b, &b_len) != 1) {
if (rs_krb5_tx_get_sname(txv, local_id, &b, &b_len) != 1) {
InspectionBufferSetupMultiEmpty(buffer);
return NULL;
}
@ -85,98 +79,6 @@ static InspectionBuffer *GetKrb5SNameData(DetectEngineThreadCtx *det_ctx,
SCReturnPtr(buffer, "InspectionBuffer");
}
static uint8_t DetectEngineInspectKrb5SName(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx,
const DetectEngineAppInspectionEngine *engine, const Signature *s, Flow *f, uint8_t flags,
void *alstate, void *txv, uint64_t tx_id)
{
uint32_t local_id = 0;
const DetectEngineTransforms *transforms = NULL;
if (!engine->mpm) {
transforms = engine->v2.transforms;
}
while (1) {
struct Krb5PrincipalNameDataArgs cbdata = { local_id, txv, };
InspectionBuffer *buffer =
GetKrb5SNameData(det_ctx, transforms, f, &cbdata, engine->sm_list);
if (buffer == NULL || buffer->inspect == NULL)
break;
const bool match = DetectEngineContentInspectionBuffer(de_ctx, det_ctx, s, engine->smd,
NULL, f, buffer, DETECT_ENGINE_CONTENT_INSPECTION_MODE_STATE);
if (match) {
return DETECT_ENGINE_INSPECT_SIG_MATCH;
}
local_id++;
}
return DETECT_ENGINE_INSPECT_SIG_NO_MATCH;
}
typedef struct PrefilterMpmKrb5Name {
int list_id;
const MpmCtx *mpm_ctx;
const DetectEngineTransforms *transforms;
} PrefilterMpmKrb5Name;
/** \brief Krb5SName Krb5SName Mpm prefilter callback
*
* \param det_ctx detection engine thread ctx
* \param p packet to inspect
* \param f flow to inspect
* \param txv tx to inspect
* \param pectx inspection context
*/
static void PrefilterTxKrb5SName(DetectEngineThreadCtx *det_ctx, const void *pectx, Packet *p,
Flow *f, void *txv, const uint64_t idx, const AppLayerTxData *_txd, const uint8_t flags)
{
SCEnter();
const PrefilterMpmKrb5Name *ctx = (const PrefilterMpmKrb5Name *)pectx;
const MpmCtx *mpm_ctx = ctx->mpm_ctx;
const int list_id = ctx->list_id;
uint32_t local_id = 0;
while(1) {
// loop until we get a NULL
struct Krb5PrincipalNameDataArgs cbdata = { local_id, txv };
InspectionBuffer *buffer = GetKrb5SNameData(det_ctx, ctx->transforms, f, &cbdata, list_id);
if (buffer == NULL)
break;
if (buffer->inspect_len >= mpm_ctx->minlen) {
(void)mpm_table[mpm_ctx->mpm_type].Search(
mpm_ctx, &det_ctx->mtc, &det_ctx->pmq, buffer->inspect, buffer->inspect_len);
PREFILTER_PROFILING_ADD_BYTES(det_ctx, buffer->inspect_len);
}
local_id++;
}
}
static void PrefilterMpmKrb5NameFree(void *ptr)
{
SCFree(ptr);
}
static int PrefilterMpmKrb5SNameRegister(DetectEngineCtx *de_ctx, SigGroupHead *sgh,
MpmCtx *mpm_ctx, const DetectBufferMpmRegistry *mpm_reg, int list_id)
{
PrefilterMpmKrb5Name *pectx = SCCalloc(1, sizeof(*pectx));
if (pectx == NULL)
return -1;
pectx->list_id = list_id;
pectx->mpm_ctx = mpm_ctx;
pectx->transforms = &mpm_reg->transforms;
return PrefilterAppendTxEngine(de_ctx, sgh, PrefilterTxKrb5SName,
mpm_reg->app_v2.alproto, mpm_reg->app_v2.tx_min_progress,
pectx, PrefilterMpmKrb5NameFree, mpm_reg->name);
}
void DetectKrb5SNameRegister(void)
{
sigmatch_table[DETECT_AL_KRB5_SNAME].name = "krb5.sname";
@ -186,11 +88,8 @@ void DetectKrb5SNameRegister(void)
sigmatch_table[DETECT_AL_KRB5_SNAME].flags |= SIGMATCH_NOOPT|SIGMATCH_INFO_STICKY_BUFFER;
sigmatch_table[DETECT_AL_KRB5_SNAME].desc = "sticky buffer to match on Kerberos 5 server name";
DetectAppLayerMpmRegister("krb5_sname", SIG_FLAG_TOCLIENT, 2, PrefilterMpmKrb5SNameRegister,
NULL, ALPROTO_KRB5, 1);
DetectAppLayerInspectEngineRegister(
"krb5_sname", ALPROTO_KRB5, SIG_FLAG_TOCLIENT, 0, DetectEngineInspectKrb5SName, NULL);
DetectAppLayerMultiRegister(
"krb5_sname", ALPROTO_KRB5, SIG_FLAG_TOCLIENT, 0, GetKrb5SNameData, 2, 1);
DetectBufferTypeSetDescriptionByName("krb5_sname",
"Kerberos 5 ticket server name");

@ -59,19 +59,16 @@ static int g_mqtt_subscribe_topic_buffer_id = 0;
static uint32_t subscribe_topic_match_limit = 100;
struct MQTTSubscribeTopicGetDataArgs {
uint32_t local_id;
void *txv;
};
static InspectionBuffer *MQTTSubscribeTopicGetData(DetectEngineThreadCtx *det_ctx,
const DetectEngineTransforms *transforms, Flow *f,
struct MQTTSubscribeTopicGetDataArgs *cbdata, int list_id)
const DetectEngineTransforms *transforms, Flow *f, const uint8_t flags, void *txv,
int list_id, uint32_t local_id)
{
SCEnter();
InspectionBuffer *buffer =
InspectionBufferMultipleForListGet(det_ctx, list_id, cbdata->local_id);
if (subscribe_topic_match_limit > 0 && local_id >= subscribe_topic_match_limit)
return NULL;
InspectionBuffer *buffer = InspectionBufferMultipleForListGet(det_ctx, list_id, local_id);
if (buffer == NULL)
return NULL;
if (buffer->initialized)
@ -79,107 +76,17 @@ static InspectionBuffer *MQTTSubscribeTopicGetData(DetectEngineThreadCtx *det_ct
const uint8_t *data;
uint32_t data_len;
if (rs_mqtt_tx_get_subscribe_topic(cbdata->txv, cbdata->local_id, &data, &data_len) == 0) {
if (rs_mqtt_tx_get_subscribe_topic(txv, local_id, &data, &data_len) == 0) {
InspectionBufferSetupMultiEmpty(buffer);
return NULL;
}
InspectionBufferSetupMulti(buffer, transforms, data, data_len);
buffer->flags = DETECT_CI_FLAGS_SINGLE;
SCReturnPtr(buffer, "InspectionBuffer");
}
static uint8_t DetectEngineInspectMQTTSubscribeTopic(DetectEngineCtx *de_ctx,
DetectEngineThreadCtx *det_ctx, const DetectEngineAppInspectionEngine *engine,
const Signature *s, Flow *f, uint8_t flags, void *alstate, void *txv, uint64_t tx_id)
{
uint32_t local_id = 0;
const DetectEngineTransforms *transforms = NULL;
if (!engine->mpm) {
transforms = engine->v2.transforms;
}
while ((subscribe_topic_match_limit == 0) || local_id < subscribe_topic_match_limit) {
struct MQTTSubscribeTopicGetDataArgs cbdata = { local_id, txv, };
InspectionBuffer *buffer =
MQTTSubscribeTopicGetData(det_ctx, transforms, f, &cbdata, engine->sm_list);
if (buffer == NULL || buffer->inspect == NULL)
break;
const bool match = DetectEngineContentInspection(de_ctx, det_ctx, s, engine->smd, NULL, f,
buffer->inspect, buffer->inspect_len, buffer->inspect_offset,
DETECT_CI_FLAGS_SINGLE, DETECT_ENGINE_CONTENT_INSPECTION_MODE_STATE);
if (match) {
return DETECT_ENGINE_INSPECT_SIG_MATCH;
}
local_id++;
}
return DETECT_ENGINE_INSPECT_SIG_NO_MATCH;
}
typedef struct PrefilterMpmMQTTSubscribeTopic {
int list_id;
const MpmCtx *mpm_ctx;
const DetectEngineTransforms *transforms;
} PrefilterMpmMQTTSubscribeTopic;
/** \brief MQTTSubscribeTopic MQTTSubscribeTopic Mpm prefilter callback
*
* \param det_ctx detection engine thread ctx
* \param p packet to inspect
* \param f flow to inspect
* \param txv tx to inspect
* \param pectx inspection context
*/
static void PrefilterTxMQTTSubscribeTopic(DetectEngineThreadCtx *det_ctx, const void *pectx,
Packet *p, Flow *f, void *txv, const uint64_t idx, const AppLayerTxData *_txd,
const uint8_t flags)
{
SCEnter();
const PrefilterMpmMQTTSubscribeTopic *ctx = (const PrefilterMpmMQTTSubscribeTopic *)pectx;
const MpmCtx *mpm_ctx = ctx->mpm_ctx;
const int list_id = ctx->list_id;
uint32_t local_id = 0;
while ((subscribe_topic_match_limit == 0) || local_id < subscribe_topic_match_limit) {
struct MQTTSubscribeTopicGetDataArgs cbdata = { local_id, txv };
InspectionBuffer *buffer =
MQTTSubscribeTopicGetData(det_ctx, ctx->transforms, f, &cbdata, list_id);
if (buffer == NULL)
break;
if (buffer->inspect_len >= mpm_ctx->minlen) {
(void)mpm_table[mpm_ctx->mpm_type].Search(
mpm_ctx, &det_ctx->mtc, &det_ctx->pmq, buffer->inspect, buffer->inspect_len);
PREFILTER_PROFILING_ADD_BYTES(det_ctx, buffer->inspect_len);
}
local_id++;
}
}
static void PrefilterMpmMQTTSubscribeTopicFree(void *ptr)
{
if (ptr != NULL)
SCFree(ptr);
}
static int PrefilterMpmMQTTSubscribeTopicRegister(DetectEngineCtx *de_ctx, SigGroupHead *sgh,
MpmCtx *mpm_ctx, const DetectBufferMpmRegistry *mpm_reg, int list_id)
{
PrefilterMpmMQTTSubscribeTopic *pectx = SCCalloc(1, sizeof(*pectx));
if (pectx == NULL)
return -1;
pectx->list_id = list_id;
pectx->mpm_ctx = mpm_ctx;
pectx->transforms = &mpm_reg->transforms;
return PrefilterAppendTxEngine(de_ctx, sgh, PrefilterTxMQTTSubscribeTopic,
mpm_reg->app_v2.alproto, mpm_reg->app_v2.tx_min_progress,
pectx, PrefilterMpmMQTTSubscribeTopicFree, mpm_reg->pname);
}
/**
* \brief Registration function for keyword: mqtt.subscribe.topic
*/
@ -203,11 +110,8 @@ void DetectMQTTSubscribeTopicRegister (void)
subscribe_topic_match_limit);
}
DetectAppLayerMpmRegister("mqtt.subscribe.topic", SIG_FLAG_TOSERVER, 1,
PrefilterMpmMQTTSubscribeTopicRegister, NULL, ALPROTO_MQTT, 1);
DetectAppLayerInspectEngineRegister("mqtt.subscribe.topic", ALPROTO_MQTT, SIG_FLAG_TOSERVER, 1,
DetectEngineInspectMQTTSubscribeTopic, NULL);
DetectAppLayerMultiRegister("mqtt.subscribe.topic", ALPROTO_MQTT, SIG_FLAG_TOSERVER, 1,
MQTTSubscribeTopicGetData, 1, 1);
DetectBufferTypeSetDescriptionByName("mqtt.subscribe.topic",
"subscribe topic query");

@ -59,19 +59,16 @@ static int g_mqtt_unsubscribe_topic_buffer_id = 0;
static uint32_t unsubscribe_topic_match_limit = 100;
struct MQTTUnsubscribeTopicGetDataArgs {
uint32_t local_id;
void *txv;
};
static InspectionBuffer *MQTTUnsubscribeTopicGetData(DetectEngineThreadCtx *det_ctx,
const DetectEngineTransforms *transforms, Flow *f,
struct MQTTUnsubscribeTopicGetDataArgs *cbdata, int list_id)
const DetectEngineTransforms *transforms, Flow *f, const uint8_t flags, void *txv,
int list_id, uint32_t local_id)
{
SCEnter();
InspectionBuffer *buffer =
InspectionBufferMultipleForListGet(det_ctx, list_id, cbdata->local_id);
if (unsubscribe_topic_match_limit > 0 && local_id >= unsubscribe_topic_match_limit)
return NULL;
InspectionBuffer *buffer = InspectionBufferMultipleForListGet(det_ctx, list_id, local_id);
if (buffer == NULL)
return NULL;
if (buffer->initialized)
@ -79,107 +76,17 @@ static InspectionBuffer *MQTTUnsubscribeTopicGetData(DetectEngineThreadCtx *det_
const uint8_t *data;
uint32_t data_len;
if (rs_mqtt_tx_get_unsubscribe_topic(cbdata->txv, cbdata->local_id, &data, &data_len) == 0) {
if (rs_mqtt_tx_get_unsubscribe_topic(txv, local_id, &data, &data_len) == 0) {
InspectionBufferSetupMultiEmpty(buffer);
return NULL;
}
InspectionBufferSetupMulti(buffer, transforms, data, data_len);
buffer->flags = DETECT_CI_FLAGS_SINGLE;
SCReturnPtr(buffer, "InspectionBuffer");
}
static uint8_t DetectEngineInspectMQTTUnsubscribeTopic(DetectEngineCtx *de_ctx,
DetectEngineThreadCtx *det_ctx, const DetectEngineAppInspectionEngine *engine,
const Signature *s, Flow *f, uint8_t flags, void *alstate, void *txv, uint64_t tx_id)
{
uint32_t local_id = 0;
const DetectEngineTransforms *transforms = NULL;
if (!engine->mpm) {
transforms = engine->v2.transforms;
}
while ((unsubscribe_topic_match_limit == 0) || local_id < unsubscribe_topic_match_limit) {
struct MQTTUnsubscribeTopicGetDataArgs cbdata = { local_id, txv, };
InspectionBuffer *buffer =
MQTTUnsubscribeTopicGetData(det_ctx, transforms, f, &cbdata, engine->sm_list);
if (buffer == NULL || buffer->inspect == NULL)
break;
const bool match = DetectEngineContentInspection(de_ctx, det_ctx, s, engine->smd, NULL, f,
buffer->inspect, buffer->inspect_len, buffer->inspect_offset,
DETECT_CI_FLAGS_SINGLE, DETECT_ENGINE_CONTENT_INSPECTION_MODE_STATE);
if (match) {
return DETECT_ENGINE_INSPECT_SIG_MATCH;
}
local_id++;
}
return DETECT_ENGINE_INSPECT_SIG_NO_MATCH;
}
typedef struct PrefilterMpmMQTTUnsubscribeTopic {
int list_id;
const MpmCtx *mpm_ctx;
const DetectEngineTransforms *transforms;
} PrefilterMpmMQTTUnsubscribeTopic;
/** \brief MQTTUnsubscribeTopic MQTTUnsubscribeTopic Mpm prefilter callback
*
* \param det_ctx detection engine thread ctx
* \param p packet to inspect
* \param f flow to inspect
* \param txv tx to inspect
* \param pectx inspection context
*/
static void PrefilterTxMQTTUnsubscribeTopic(DetectEngineThreadCtx *det_ctx, const void *pectx,
Packet *p, Flow *f, void *txv, const uint64_t idx, const AppLayerTxData *_txd,
const uint8_t flags)
{
SCEnter();
const PrefilterMpmMQTTUnsubscribeTopic *ctx = (const PrefilterMpmMQTTUnsubscribeTopic *)pectx;
const MpmCtx *mpm_ctx = ctx->mpm_ctx;
const int list_id = ctx->list_id;
uint32_t local_id = 0;
while ((unsubscribe_topic_match_limit == 0) || local_id < unsubscribe_topic_match_limit) {
struct MQTTUnsubscribeTopicGetDataArgs cbdata = { local_id, txv };
InspectionBuffer *buffer =
MQTTUnsubscribeTopicGetData(det_ctx, ctx->transforms, f, &cbdata, list_id);
if (buffer == NULL)
break;
if (buffer->inspect_len >= mpm_ctx->minlen) {
(void)mpm_table[mpm_ctx->mpm_type].Search(
mpm_ctx, &det_ctx->mtc, &det_ctx->pmq, buffer->inspect, buffer->inspect_len);
PREFILTER_PROFILING_ADD_BYTES(det_ctx, buffer->inspect_len);
}
local_id++;
}
}
static void PrefilterMpmMQTTUnsubscribeTopicFree(void *ptr)
{
if (ptr != NULL)
SCFree(ptr);
}
static int PrefilterMpmMQTTUnsubscribeTopicRegister(DetectEngineCtx *de_ctx, SigGroupHead *sgh,
MpmCtx *mpm_ctx, const DetectBufferMpmRegistry *mpm_reg, int list_id)
{
PrefilterMpmMQTTUnsubscribeTopic *pectx = SCCalloc(1, sizeof(*pectx));
if (pectx == NULL)
return -1;
pectx->list_id = list_id;
pectx->mpm_ctx = mpm_ctx;
pectx->transforms = &mpm_reg->transforms;
return PrefilterAppendTxEngine(de_ctx, sgh, PrefilterTxMQTTUnsubscribeTopic,
mpm_reg->app_v2.alproto, mpm_reg->app_v2.tx_min_progress,
pectx, PrefilterMpmMQTTUnsubscribeTopicFree, mpm_reg->pname);
}
/**
* \brief Registration function for keyword: mqtt.unsubscribe.topic
*/
@ -203,11 +110,8 @@ void DetectMQTTUnsubscribeTopicRegister (void)
unsubscribe_topic_match_limit);
}
DetectAppLayerMpmRegister("mqtt.unsubscribe.topic", SIG_FLAG_TOSERVER, 1,
PrefilterMpmMQTTUnsubscribeTopicRegister, NULL, ALPROTO_MQTT, 1);
DetectAppLayerInspectEngineRegister("mqtt.unsubscribe.topic", ALPROTO_MQTT, SIG_FLAG_TOSERVER,
1, DetectEngineInspectMQTTUnsubscribeTopic, NULL);
DetectAppLayerMultiRegister("mqtt.unsubscribe.topic", ALPROTO_MQTT, SIG_FLAG_TOSERVER, 1,
MQTTUnsubscribeTopicGetData, 1, 1);
DetectBufferTypeSetDescriptionByName("mqtt.unsubscribe.topic",
"unsubscribe topic query");

@ -44,11 +44,6 @@ static void DetectQuicCyuHashRegisterTests(void);
#define BUFFER_DESC "QUIC CYU Hash"
static int g_buffer_id = 0;
struct QuicHashGetDataArgs {
uint32_t local_id; /**< used as index into thread inspect array */
void *txv;
};
static int DetectQuicCyuHashSetup(DetectEngineCtx *de_ctx, Signature *s, const char *arg)
{
if (DetectBufferSetActiveList(de_ctx, s, g_buffer_id) < 0)
@ -61,13 +56,14 @@ static int DetectQuicCyuHashSetup(DetectEngineCtx *de_ctx, Signature *s, const c
}
static InspectionBuffer *QuicHashGetData(DetectEngineThreadCtx *det_ctx,
const DetectEngineTransforms *transforms, Flow *f, struct QuicHashGetDataArgs *cbdata,
int list_id)
const DetectEngineTransforms *transforms, Flow *f, const uint8_t flags, void *txv,
int list_id, uint32_t local_id)
{
SCEnter();
InspectionBuffer *buffer =
InspectionBufferMultipleForListGet(det_ctx, list_id, cbdata->local_id);
if (local_id > UINT16_MAX)
return NULL;
InspectionBuffer *buffer = InspectionBufferMultipleForListGet(det_ctx, list_id, local_id);
if (buffer == NULL)
return NULL;
if (buffer->initialized)
@ -75,109 +71,17 @@ static InspectionBuffer *QuicHashGetData(DetectEngineThreadCtx *det_ctx,
const uint8_t *data;
uint32_t data_len;
if (rs_quic_tx_get_cyu_hash(cbdata->txv, (uint16_t)cbdata->local_id, &data, &data_len) == 0) {
if (rs_quic_tx_get_cyu_hash(txv, local_id, &data, &data_len) == 0) {
InspectionBufferSetupMultiEmpty(buffer);
return NULL;
}
InspectionBufferSetupMulti(buffer, transforms, data, data_len);
buffer->flags = DETECT_CI_FLAGS_SINGLE;
SCReturnPtr(buffer, "InspectionBuffer");
}
static uint8_t DetectEngineInspectQuicHash(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx,
const DetectEngineAppInspectionEngine *engine, const Signature *s, Flow *f, uint8_t flags,
void *alstate, void *txv, uint64_t tx_id)
{
uint32_t local_id = 0;
const DetectEngineTransforms *transforms = NULL;
if (!engine->mpm) {
transforms = engine->v2.transforms;
}
while (1) {
struct QuicHashGetDataArgs cbdata = {
local_id,
txv,
};
InspectionBuffer *buffer =
QuicHashGetData(det_ctx, transforms, f, &cbdata, engine->sm_list);
if (buffer == NULL || buffer->inspect == NULL)
break;
const bool match = DetectEngineContentInspection(de_ctx, det_ctx, s, engine->smd, NULL, f,
buffer->inspect, buffer->inspect_len, buffer->inspect_offset,
DETECT_CI_FLAGS_SINGLE, DETECT_ENGINE_CONTENT_INSPECTION_MODE_STATE);
if (match) {
return DETECT_ENGINE_INSPECT_SIG_MATCH;
}
local_id++;
}
return DETECT_ENGINE_INSPECT_SIG_NO_MATCH;
}
typedef struct PrefilterMpmQuicHash {
int list_id;
const MpmCtx *mpm_ctx;
const DetectEngineTransforms *transforms;
} PrefilterMpmQuicHash;
/** \brief QuicHash Mpm prefilter callback
*
* \param det_ctx detection engine thread ctx
* \param p packet to inspect
* \param f flow to inspect
* \param txv tx to inspect
* \param pectx inspection context
*/
static void PrefilterTxQuicHash(DetectEngineThreadCtx *det_ctx, const void *pectx, Packet *p,
Flow *f, void *txv, const uint64_t idx, const AppLayerTxData *_txd, const uint8_t flags)
{
SCEnter();
const PrefilterMpmQuicHash *ctx = (const PrefilterMpmQuicHash *)pectx;
const MpmCtx *mpm_ctx = ctx->mpm_ctx;
const int list_id = ctx->list_id;
uint32_t local_id = 0;
while (1) {
// loop until we get a NULL
struct QuicHashGetDataArgs cbdata = { local_id, txv };
InspectionBuffer *buffer = QuicHashGetData(det_ctx, ctx->transforms, f, &cbdata, list_id);
if (buffer == NULL)
break;
if (buffer->inspect_len >= mpm_ctx->minlen) {
(void)mpm_table[mpm_ctx->mpm_type].Search(
mpm_ctx, &det_ctx->mtc, &det_ctx->pmq, buffer->inspect, buffer->inspect_len);
PREFILTER_PROFILING_ADD_BYTES(det_ctx, buffer->inspect_len);
}
local_id++;
}
}
static void PrefilterMpmQuicHashFree(void *ptr)
{
SCFree(ptr);
}
static int PrefilterMpmQuicHashRegister(DetectEngineCtx *de_ctx, SigGroupHead *sgh, MpmCtx *mpm_ctx,
const DetectBufferMpmRegistry *mpm_reg, int list_id)
{
PrefilterMpmQuicHash *pectx = SCCalloc(1, sizeof(*pectx));
if (pectx == NULL)
return -1;
pectx->list_id = list_id;
pectx->mpm_ctx = mpm_ctx;
pectx->transforms = &mpm_reg->transforms;
return PrefilterAppendTxEngine(de_ctx, sgh, PrefilterTxQuicHash, mpm_reg->app_v2.alproto,
mpm_reg->app_v2.tx_min_progress, pectx, PrefilterMpmQuicHashFree, mpm_reg->pname);
}
static bool DetectQuicHashValidateCallback(const Signature *s, const char **sigerror)
{
for (uint32_t x = 0; x < s->init_data->buffer_index; x++) {
@ -230,11 +134,8 @@ void DetectQuicCyuHashRegister(void)
sigmatch_table[DETECT_AL_QUIC_CYU_HASH].RegisterTests = DetectQuicCyuHashRegisterTests;
#endif
DetectAppLayerMpmRegister(
BUFFER_NAME, SIG_FLAG_TOSERVER, 2, PrefilterMpmQuicHashRegister, NULL, ALPROTO_QUIC, 1);
DetectAppLayerInspectEngineRegister(
BUFFER_NAME, ALPROTO_QUIC, SIG_FLAG_TOSERVER, 0, DetectEngineInspectQuicHash, NULL);
DetectAppLayerMultiRegister(
BUFFER_NAME, ALPROTO_QUIC, SIG_FLAG_TOSERVER, 0, QuicHashGetData, 2, 1);
DetectBufferTypeSetDescriptionByName(BUFFER_NAME, BUFFER_DESC);

@ -42,11 +42,6 @@ static void DetectQuicCyuStringRegisterTests(void);
#define BUFFER_DESC "QUIC CYU String"
static int g_buffer_id = 0;
struct QuicStringGetDataArgs {
uint32_t local_id; /**< used as index into thread inspect array */
void *txv;
};
static int DetectQuicCyuStringSetup(DetectEngineCtx *de_ctx, Signature *s, const char *arg)
{
if (DetectBufferSetActiveList(de_ctx, s, g_buffer_id) < 0)
@ -59,13 +54,12 @@ static int DetectQuicCyuStringSetup(DetectEngineCtx *de_ctx, Signature *s, const
}
static InspectionBuffer *QuicStringGetData(DetectEngineThreadCtx *det_ctx,
const DetectEngineTransforms *transforms, Flow *f, struct QuicStringGetDataArgs *cbdata,
int list_id)
const DetectEngineTransforms *transforms, Flow *f, const uint8_t flags, void *txv,
int list_id, uint32_t local_id)
{
SCEnter();
InspectionBuffer *buffer =
InspectionBufferMultipleForListGet(det_ctx, list_id, cbdata->local_id);
InspectionBuffer *buffer = InspectionBufferMultipleForListGet(det_ctx, list_id, local_id);
if (buffer == NULL)
return NULL;
if (buffer->initialized)
@ -73,103 +67,17 @@ static InspectionBuffer *QuicStringGetData(DetectEngineThreadCtx *det_ctx,
const uint8_t *data;
uint32_t data_len;
if (rs_quic_tx_get_cyu_string(cbdata->txv, cbdata->local_id, &data, &data_len) == 0) {
if (rs_quic_tx_get_cyu_string(txv, local_id, &data, &data_len) == 0) {
InspectionBufferSetupMultiEmpty(buffer);
return NULL;
}
InspectionBufferSetupMulti(buffer, transforms, data, data_len);
buffer->flags = DETECT_CI_FLAGS_SINGLE;
SCReturnPtr(buffer, "InspectionBuffer");
}
static uint8_t DetectEngineInspectQuicString(DetectEngineCtx *de_ctx,
DetectEngineThreadCtx *det_ctx, const DetectEngineAppInspectionEngine *engine,
const Signature *s, Flow *f, uint8_t flags, void *alstate, void *txv, uint64_t tx_id)
{
uint32_t local_id = 0;
const DetectEngineTransforms *transforms = NULL;
if (!engine->mpm) {
transforms = engine->v2.transforms;
}
while (1) {
struct QuicStringGetDataArgs cbdata = {
local_id,
txv,
};
InspectionBuffer *buffer =
QuicStringGetData(det_ctx, transforms, f, &cbdata, engine->sm_list);
if (buffer == NULL || buffer->inspect == NULL)
break;
const bool match = DetectEngineContentInspection(de_ctx, det_ctx, s, engine->smd, NULL, f,
buffer->inspect, buffer->inspect_len, buffer->inspect_offset,
DETECT_CI_FLAGS_SINGLE, DETECT_ENGINE_CONTENT_INSPECTION_MODE_STATE);
if (match) {
return DETECT_ENGINE_INSPECT_SIG_MATCH;
}
local_id++;
}
return DETECT_ENGINE_INSPECT_SIG_NO_MATCH;
}
/** \brief QuicString Mpm prefilter callback
*
* \param det_ctx detection engine thread ctx
* \param p packet to inspect
* \param f flow to inspect
* \param txv tx to inspect
* \param pectx inspection context
*/
static void PrefilterTxQuicString(DetectEngineThreadCtx *det_ctx, const void *pectx, Packet *p,
Flow *f, void *txv, const uint64_t idx, const AppLayerTxData *_txd, const uint8_t flags)
{
SCEnter();
const PrefilterMpmListId *ctx = (const PrefilterMpmListId *)pectx;
const MpmCtx *mpm_ctx = ctx->mpm_ctx;
const int list_id = ctx->list_id;
uint32_t local_id = 0;
while (1) {
// loop until we get a NULL
struct QuicStringGetDataArgs cbdata = { local_id, txv };
InspectionBuffer *buffer = QuicStringGetData(det_ctx, ctx->transforms, f, &cbdata, list_id);
if (buffer == NULL)
break;
if (buffer->inspect_len >= mpm_ctx->minlen) {
(void)mpm_table[mpm_ctx->mpm_type].Search(
mpm_ctx, &det_ctx->mtc, &det_ctx->pmq, buffer->inspect, buffer->inspect_len);
PREFILTER_PROFILING_ADD_BYTES(det_ctx, buffer->inspect_len);
}
local_id++;
}
}
static void PrefilterMpmListIdFree(void *ptr)
{
SCFree(ptr);
}
static int PrefilterMpmListIdRegister(DetectEngineCtx *de_ctx, SigGroupHead *sgh, MpmCtx *mpm_ctx,
const DetectBufferMpmRegistry *mpm_reg, int list_id)
{
PrefilterMpmListId *pectx = SCCalloc(1, sizeof(*pectx));
if (pectx == NULL)
return -1;
pectx->list_id = list_id;
pectx->mpm_ctx = mpm_ctx;
pectx->transforms = &mpm_reg->transforms;
return PrefilterAppendTxEngine(de_ctx, sgh, PrefilterTxQuicString, mpm_reg->app_v2.alproto,
mpm_reg->app_v2.tx_min_progress, pectx, PrefilterMpmListIdFree, mpm_reg->pname);
}
void DetectQuicCyuStringRegister(void)
{
/* quic.cyu.string sticky buffer */
@ -183,11 +91,8 @@ void DetectQuicCyuStringRegister(void)
sigmatch_table[DETECT_AL_QUIC_CYU_STRING].RegisterTests = DetectQuicCyuStringRegisterTests;
#endif
DetectAppLayerMpmRegister(
BUFFER_NAME, SIG_FLAG_TOSERVER, 2, PrefilterMpmListIdRegister, NULL, ALPROTO_QUIC, 1);
DetectAppLayerInspectEngineRegister(
BUFFER_NAME, ALPROTO_QUIC, SIG_FLAG_TOSERVER, 0, DetectEngineInspectQuicString, NULL);
DetectAppLayerMultiRegister(
BUFFER_NAME, ALPROTO_QUIC, SIG_FLAG_TOSERVER, 0, QuicStringGetData, 2, 1);
DetectBufferTypeSetDescriptionByName(BUFFER_NAME, BUFFER_DESC);

@ -59,25 +59,53 @@ static int DetectTlsCertsSetup(DetectEngineCtx *, Signature *, const char *);
#ifdef UNITTESTS
static void DetectTlsCertsRegisterTests(void);
#endif
static uint8_t DetectEngineInspectTlsCerts(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx,
const DetectEngineAppInspectionEngine *engine, const Signature *s, Flow *f, uint8_t flags,
void *alstate, void *txv, uint64_t tx_id);
static int PrefilterMpmTlsCertsRegister(DetectEngineCtx *de_ctx, SigGroupHead *sgh, MpmCtx *mpm_ctx,
const DetectBufferMpmRegistry *mpm_reg, int list_id);
static int g_tls_certs_buffer_id = 0;
struct TlsCertsGetDataArgs {
uint32_t local_id; /**< used as index into thread inspect array */
static InspectionBuffer *TlsCertsGetData(DetectEngineThreadCtx *det_ctx,
const DetectEngineTransforms *transforms, Flow *f, const uint8_t flags, void *txv,
int list_id, uint32_t local_id)
{
SCEnter();
InspectionBuffer *buffer = InspectionBufferMultipleForListGet(det_ctx, list_id, local_id);
if (buffer == NULL || buffer->initialized)
return buffer;
const SSLState *ssl_state = (SSLState *)f->alstate;
const SSLStateConnp *connp;
if (flags & STREAM_TOSERVER) {
connp = &ssl_state->client_connp;
} else {
connp = &ssl_state->server_connp;
}
if (TAILQ_EMPTY(&connp->certs)) {
InspectionBufferSetupMultiEmpty(buffer);
return NULL;
}
SSLCertsChain *cert;
const uint8_t flags;
};
if (local_id == 0) {
cert = TAILQ_FIRST(&connp->certs);
} else {
// TODO optimize ?
cert = TAILQ_FIRST(&connp->certs);
for (uint32_t i = 0; i < local_id; i++) {
cert = TAILQ_NEXT(cert, next);
}
}
if (cert == NULL) {
InspectionBufferSetupMultiEmpty(buffer);
return NULL;
}
InspectionBufferSetupMulti(buffer, transforms, cert->cert_data, cert->cert_len);
buffer->flags = DETECT_CI_FLAGS_SINGLE;
typedef struct PrefilterMpmTlsCerts {
int list_id;
const MpmCtx *mpm_ctx;
const DetectEngineTransforms *transforms;
} PrefilterMpmTlsCerts;
SCReturnPtr(buffer, "InspectionBuffer");
}
/**
* \brief Registration function for keyword: tls.certs
@ -94,17 +122,10 @@ void DetectTlsCertsRegister(void)
sigmatch_table[DETECT_AL_TLS_CERTS].flags |= SIGMATCH_NOOPT;
sigmatch_table[DETECT_AL_TLS_CERTS].flags |= SIGMATCH_INFO_STICKY_BUFFER;
DetectAppLayerInspectEngineRegister("tls.certs", ALPROTO_TLS, SIG_FLAG_TOCLIENT,
TLS_STATE_CERT_READY, DetectEngineInspectTlsCerts, NULL);
DetectAppLayerMpmRegister("tls.certs", SIG_FLAG_TOCLIENT, 2, PrefilterMpmTlsCertsRegister, NULL,
ALPROTO_TLS, TLS_STATE_CERT_READY);
DetectAppLayerInspectEngineRegister("tls.certs", ALPROTO_TLS, SIG_FLAG_TOSERVER,
TLS_STATE_CERT_READY, DetectEngineInspectTlsCerts, NULL);
DetectAppLayerMpmRegister("tls.certs", SIG_FLAG_TOSERVER, 2, PrefilterMpmTlsCertsRegister, NULL,
ALPROTO_TLS, TLS_STATE_CERT_READY);
DetectAppLayerMultiRegister("tls.certs", ALPROTO_TLS, SIG_FLAG_TOCLIENT, TLS_STATE_CERT_READY,
TlsCertsGetData, 2, 1);
DetectAppLayerMultiRegister("tls.certs", ALPROTO_TLS, SIG_FLAG_TOSERVER, TLS_STATE_CERT_READY,
TlsCertsGetData, 2, 1);
DetectBufferTypeSetDescriptionByName("tls.certs", "TLS certificate");
@ -135,126 +156,6 @@ static int DetectTlsCertsSetup(DetectEngineCtx *de_ctx, Signature *s,
return 0;
}
static InspectionBuffer *TlsCertsGetData(DetectEngineThreadCtx *det_ctx,
const DetectEngineTransforms *transforms, Flow *f,
struct TlsCertsGetDataArgs *cbdata, int list_id)
{
SCEnter();
InspectionBuffer *buffer =
InspectionBufferMultipleForListGet(det_ctx, list_id, cbdata->local_id);
if (buffer == NULL || buffer->initialized)
return buffer;
const SSLState *ssl_state = (SSLState *)f->alstate;
const SSLStateConnp *connp;
if (cbdata->flags & STREAM_TOSERVER) {
connp = &ssl_state->client_connp;
} else {
connp = &ssl_state->server_connp;
}
if (TAILQ_EMPTY(&connp->certs)) {
InspectionBufferSetupMultiEmpty(buffer);
return NULL;
}
if (cbdata->cert == NULL) {
cbdata->cert = TAILQ_FIRST(&connp->certs);
} else {
cbdata->cert = TAILQ_NEXT(cbdata->cert, next);
}
if (cbdata->cert == NULL) {
InspectionBufferSetupMultiEmpty(buffer);
return NULL;
}
InspectionBufferSetupMulti(buffer, transforms, cbdata->cert->cert_data, cbdata->cert->cert_len);
SCReturnPtr(buffer, "InspectionBuffer");
}
static uint8_t DetectEngineInspectTlsCerts(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx,
const DetectEngineAppInspectionEngine *engine, const Signature *s, Flow *f, uint8_t flags,
void *alstate, void *txv, uint64_t tx_id)
{
const DetectEngineTransforms *transforms = NULL;
if (!engine->mpm) {
transforms = engine->v2.transforms;
}
struct TlsCertsGetDataArgs cbdata = { .local_id = 0, .cert = NULL, .flags = flags };
while (1)
{
InspectionBuffer *buffer = TlsCertsGetData(det_ctx, transforms, f,
&cbdata, engine->sm_list);
if (buffer == NULL || buffer->inspect == NULL)
break;
const bool match = DetectEngineContentInspection(de_ctx, det_ctx, s, engine->smd, NULL, f,
buffer->inspect, buffer->inspect_len, buffer->inspect_offset,
DETECT_CI_FLAGS_SINGLE, DETECT_ENGINE_CONTENT_INSPECTION_MODE_STATE);
if (match) {
return DETECT_ENGINE_INSPECT_SIG_MATCH;
}
cbdata.local_id++;
}
return DETECT_ENGINE_INSPECT_SIG_NO_MATCH;
}
static void PrefilterTxTlsCerts(DetectEngineThreadCtx *det_ctx, const void *pectx, Packet *p,
Flow *f, void *txv, const uint64_t idx, const AppLayerTxData *_txd, const uint8_t flags)
{
SCEnter();
const PrefilterMpmTlsCerts *ctx = (const PrefilterMpmTlsCerts *)pectx;
const MpmCtx *mpm_ctx = ctx->mpm_ctx;
const int list_id = ctx->list_id;
struct TlsCertsGetDataArgs cbdata = { .local_id = 0, .cert = NULL, .flags = flags };
while (1)
{
InspectionBuffer *buffer = TlsCertsGetData(det_ctx, ctx->transforms,
f, &cbdata, list_id);
if (buffer == NULL)
break;
if (buffer->inspect_len >= mpm_ctx->minlen) {
(void)mpm_table[mpm_ctx->mpm_type].Search(
mpm_ctx, &det_ctx->mtc, &det_ctx->pmq, buffer->inspect, buffer->inspect_len);
PREFILTER_PROFILING_ADD_BYTES(det_ctx, buffer->inspect_len);
}
cbdata.local_id++;
}
}
static void PrefilterMpmTlsCertsFree(void *ptr)
{
SCFree(ptr);
}
static int PrefilterMpmTlsCertsRegister(DetectEngineCtx *de_ctx, SigGroupHead *sgh, MpmCtx *mpm_ctx,
const DetectBufferMpmRegistry *mpm_reg, int list_id)
{
PrefilterMpmTlsCerts *pectx = SCCalloc(1, sizeof(*pectx));
if (pectx == NULL)
return -1;
pectx->list_id = list_id;
pectx->mpm_ctx = mpm_ctx;
pectx->transforms = &mpm_reg->transforms;
return PrefilterAppendTxEngine(de_ctx, sgh, PrefilterTxTlsCerts,
mpm_reg->app_v2.alproto, mpm_reg->app_v2.tx_min_progress,
pectx, PrefilterMpmTlsCertsFree, mpm_reg->name);
}
static int g_tls_cert_buffer_id = 0;
#define BUFFER_NAME "tls_validity"
#define KEYWORD_ID DETECT_AL_TLS_CHAIN_LEN

@ -52,20 +52,12 @@
#include "util-profiling.h"
static int DetectTlsSubjectAltNameSetup(DetectEngineCtx *, Signature *, const char *);
static uint8_t DetectEngineInspectTlsSubjectAltName(DetectEngineCtx *de_ctx,
DetectEngineThreadCtx *det_ctx, const DetectEngineAppInspectionEngine *engine,
const Signature *s, Flow *f, uint8_t flags, void *alstate, void *txv, uint64_t tx_id);
static int PrefilterMpmTlsSubjectAltNameRegister(DetectEngineCtx *de_ctx, SigGroupHead *sgh,
MpmCtx *mpm_ctx, const DetectBufferMpmRegistry *mpm_reg, int list_id);
static InspectionBuffer *TlsSubjectAltNameGetData(DetectEngineThreadCtx *det_ctx,
const DetectEngineTransforms *transforms, Flow *f, uint8_t flags, void *txv, int list_id,
uint32_t index);
static int g_tls_subjectaltname_buffer_id = 0;
typedef struct PrefilterMpmTlsSubjectAltName {
int list_id;
const MpmCtx *mpm_ctx;
const DetectEngineTransforms *transforms;
} PrefilterMpmTlsSubjectAltName;
/**
* \brief Registration function for keyword: tls.subjectaltname
*/
@ -80,11 +72,8 @@ void DetectTlsSubjectAltNameRegister(void)
sigmatch_table[DETECT_AL_TLS_SUBJECTALTNAME].flags |= SIGMATCH_NOOPT;
sigmatch_table[DETECT_AL_TLS_SUBJECTALTNAME].flags |= SIGMATCH_INFO_STICKY_BUFFER;
DetectAppLayerInspectEngineRegister("tls.subjectaltname", ALPROTO_TLS, SIG_FLAG_TOCLIENT,
TLS_STATE_CERT_READY, DetectEngineInspectTlsSubjectAltName, NULL);
DetectAppLayerMpmRegister("tls.subjectaltname", SIG_FLAG_TOCLIENT, 2,
PrefilterMpmTlsSubjectAltNameRegister, NULL, ALPROTO_TLS, TLS_STATE_CERT_READY);
DetectAppLayerMultiRegister("tls.subjectaltname", ALPROTO_TLS, SIG_FLAG_TOCLIENT, 0,
TlsSubjectAltNameGetData, 2, TLS_STATE_CERT_READY);
DetectBufferTypeSetDescriptionByName("tls.subjectaltname", "TLS Subject Alternative Name");
@ -115,7 +104,8 @@ static int DetectTlsSubjectAltNameSetup(DetectEngineCtx *de_ctx, Signature *s, c
}
static InspectionBuffer *TlsSubjectAltNameGetData(DetectEngineThreadCtx *det_ctx,
const DetectEngineTransforms *transforms, Flow *f, uint8_t flags, uint16_t idx, int list_id)
const DetectEngineTransforms *transforms, Flow *f, uint8_t flags, void *txv, int list_id,
uint32_t idx)
{
SCEnter();
InspectionBuffer *buffer = InspectionBufferMultipleForListGet(det_ctx, list_id, idx);
@ -133,76 +123,7 @@ static InspectionBuffer *TlsSubjectAltNameGetData(DetectEngineThreadCtx *det_ctx
InspectionBufferSetupMulti(buffer, transforms, (const uint8_t *)connp->cert0_sans[idx],
strlen(connp->cert0_sans[idx]));
buffer->flags = DETECT_CI_FLAGS_SINGLE;
SCReturnPtr(buffer, "InspectionBuffer");
}
static uint8_t DetectEngineInspectTlsSubjectAltName(DetectEngineCtx *de_ctx,
DetectEngineThreadCtx *det_ctx, const DetectEngineAppInspectionEngine *engine,
const Signature *s, Flow *f, uint8_t flags, void *alstate, void *txv, uint64_t tx_id)
{
const DetectEngineTransforms *transforms = NULL;
if (!engine->mpm) {
transforms = engine->v2.transforms;
}
for (uint16_t i = 0;; i++) {
InspectionBuffer *buffer =
TlsSubjectAltNameGetData(det_ctx, transforms, f, flags, i, engine->sm_list);
if (buffer == NULL || buffer->inspect == NULL)
break;
const bool match = DetectEngineContentInspection(de_ctx, det_ctx, s, engine->smd, NULL, f,
buffer->inspect, buffer->inspect_len, buffer->inspect_offset,
DETECT_CI_FLAGS_SINGLE, DETECT_ENGINE_CONTENT_INSPECTION_MODE_STATE);
if (match) {
return DETECT_ENGINE_INSPECT_SIG_MATCH;
}
}
return DETECT_ENGINE_INSPECT_SIG_NO_MATCH;
}
static void PrefilterTxTlsSubjectAltName(DetectEngineThreadCtx *det_ctx, const void *pectx,
Packet *p, Flow *f, void *txv, const uint64_t idx, const AppLayerTxData *_txd,
const uint8_t flags)
{
SCEnter();
const PrefilterMpmTlsSubjectAltName *ctx = (const PrefilterMpmTlsSubjectAltName *)pectx;
const MpmCtx *mpm_ctx = ctx->mpm_ctx;
const int list_id = ctx->list_id;
for (uint16_t i = 0;; i++) {
InspectionBuffer *buffer =
TlsSubjectAltNameGetData(det_ctx, ctx->transforms, f, flags, i, list_id);
if (buffer == NULL)
break;
if (buffer->inspect_len >= mpm_ctx->minlen) {
(void)mpm_table[mpm_ctx->mpm_type].Search(
mpm_ctx, &det_ctx->mtc, &det_ctx->pmq, buffer->inspect, buffer->inspect_len);
PREFILTER_PROFILING_ADD_BYTES(det_ctx, buffer->inspect_len);
}
}
}
static void PrefilterMpmTlsSubjectAltNameFree(void *ptr)
{
SCFree(ptr);
}
static int PrefilterMpmTlsSubjectAltNameRegister(DetectEngineCtx *de_ctx, SigGroupHead *sgh,
MpmCtx *mpm_ctx, const DetectBufferMpmRegistry *mpm_reg, int list_id)
{
PrefilterMpmTlsSubjectAltName *pectx = SCCalloc(1, sizeof(*pectx));
if (pectx == NULL)
return -1;
pectx->list_id = list_id;
pectx->mpm_ctx = mpm_ctx;
pectx->transforms = &mpm_reg->transforms;
return PrefilterAppendTxEngine(de_ctx, sgh, PrefilterTxTlsSubjectAltName,
mpm_reg->app_v2.alproto, mpm_reg->app_v2.tx_min_progress, pectx,
PrefilterMpmTlsSubjectAltNameFree, mpm_reg->name);
}

@ -417,6 +417,9 @@ typedef InspectionBuffer *(*InspectionBufferGetDataPtr)(
const DetectEngineTransforms *transforms,
Flow *f, const uint8_t flow_flags,
void *txv, const int list_id);
typedef InspectionBuffer *(*InspectionMultiBufferGetDataPtr)(struct DetectEngineThreadCtx_ *det_ctx,
const DetectEngineTransforms *transforms, Flow *f, const uint8_t flow_flags, void *txv,
const int list_id, const uint32_t local_id);
struct DetectEngineAppInspectionEngine_;
typedef uint8_t (*InspectEngineFuncPtr)(struct DetectEngineCtx_ *de_ctx,
@ -435,7 +438,10 @@ typedef struct DetectEngineAppInspectionEngine_ {
int16_t progress;
struct {
InspectionBufferGetDataPtr GetData;
union {
InspectionBufferGetDataPtr GetData;
InspectionMultiBufferGetDataPtr GetMultiData;
};
InspectEngineFuncPtr Callback;
/** pointer to the transforms in the 'DetectBuffer entry for this list */
const DetectEngineTransforms *transforms;
@ -695,7 +701,10 @@ typedef struct DetectBufferMpmRegistry_ {
union {
/* app-layer matching: use if type == DETECT_BUFFER_MPM_TYPE_APP */
struct {
InspectionBufferGetDataPtr GetData;
union {
InspectionBufferGetDataPtr GetData;
InspectionMultiBufferGetDataPtr GetMultiData;
};
AppProto alproto;
int tx_min_progress;
} app_v2;

Loading…
Cancel
Save