detect: rewrite of the detect engine

Use per tx detect_flags to track prefilter. Detect flags are used for 2
things:
1. marking tx as fully inspected
2. tracking already run prefilter (incl mpm) engines

This supercedes the MpmIDs API for directionless tracking
of the prefilter engines.

When we have no SGH we have to flag the txs that are 'complete'
as inspected as well.

Special handling for the stream engine:

If a rule mixes TX inspection and STREAM inspection, we can encounter
the case where the rule is evaluated against multiple transactions
during a single inspection run. As the stream data is exactly the same
for each of those runs, it's wasteful to rerun inspection of the stream
portion of the rule.

This patch enables caching of the stream 'inspect engine' result in
the local 'RuleMatchCandidateTx' array. This is valid only during the
live of a single inspection run.

Remove stateful inspection from 'mask' (SignatureMask). The mask wasn't
used in most cases for those rules anyway, as there we rely on the
prefilter. Add a alproto check to catch the remaining cases.

When building the active non-mpm/non-prefilter list check not just
the mask, but also the alproto. This especially helps stateful rules
with negated mpm.

Simplify AppLayerParserHasDecoderEvents usage in detection to only
return true if protocol detection events are set. Other detection is done
in inspect engines.

Move rule group lookup and handling into it's own function. Handle
'post lookup' tasks immediately, instead of after the first detect
run. The tasks were independent of the initial detection.

Many cleanups and much refactoring.
pull/3182/head
Victor Julien 9 years ago
parent 8cda2a4351
commit af51e0f5a1

@ -678,7 +678,8 @@ uint64_t AppLayerParserGetTransactionInspectId(AppLayerParserState *pstate, uint
}
void AppLayerParserSetTransactionInspectId(const Flow *f, AppLayerParserState *pstate,
void *alstate, const uint8_t flags)
void *alstate, const uint8_t flags,
bool tag_txs_as_inspected)
{
SCEnter();
@ -686,19 +687,49 @@ void AppLayerParserSetTransactionInspectId(const Flow *f, AppLayerParserState *p
const uint64_t total_txs = AppLayerParserGetTxCnt(f, alstate);
uint64_t idx = AppLayerParserGetTransactionInspectId(pstate, flags);
const int state_done_progress = AppLayerParserGetStateProgressCompletionStatus(f->alproto, flags);
const uint8_t ipproto = f->proto;
const AppProto alproto = f->alproto;
for (; idx < total_txs; idx++) {
void *tx = AppLayerParserGetTx(f->proto, f->alproto, alstate, idx);
void *tx = AppLayerParserGetTx(ipproto, alproto, alstate, idx);
if (tx == NULL)
continue;
int state_progress = AppLayerParserGetStateProgress(f->proto, f->alproto, tx, flags);
if (state_progress >= state_done_progress)
int state_progress = AppLayerParserGetStateProgress(ipproto, alproto, tx, flags);
if (state_progress >= state_done_progress) {
if (tag_txs_as_inspected) {
uint64_t detect_flags = AppLayerParserGetTxDetectFlags(ipproto, alproto, tx, flags);
if ((detect_flags & APP_LAYER_TX_INSPECTED_FLAG) == 0) {
detect_flags |= APP_LAYER_TX_INSPECTED_FLAG;
AppLayerParserSetTxDetectFlags(ipproto, alproto, tx, flags, detect_flags);
SCLogDebug("%p/%"PRIu64" in-order tx is done for direction %s. Flag %016"PRIx64,
tx, idx, flags & STREAM_TOSERVER ? "toserver" : "toclient", detect_flags);
}
}
continue;
else
} else
break;
}
pstate->inspect_id[direction] = idx;
/* if necessary we flag all txs that are complete as 'inspected' */
if (tag_txs_as_inspected) {
for (; idx < total_txs; idx++) {
void *tx = AppLayerParserGetTx(ipproto, alproto, alstate, idx);
if (tx == NULL)
continue;
int state_progress = AppLayerParserGetStateProgress(ipproto, alproto, tx, flags);
if (state_progress >= state_done_progress) {
uint64_t detect_flags = AppLayerParserGetTxDetectFlags(ipproto, alproto, tx, flags);
if ((detect_flags & APP_LAYER_TX_INSPECTED_FLAG) == 0) {
detect_flags |= APP_LAYER_TX_INSPECTED_FLAG;
AppLayerParserSetTxDetectFlags(ipproto, alproto, tx, flags, detect_flags);
SCLogDebug("%p/%"PRIu64" out of order tx is done for direction %s. Flag %016"PRIx64,
tx, idx, flags & STREAM_TOSERVER ? "toserver" : "toclient", detect_flags);
}
}
}
}
SCReturn;
}
@ -1174,48 +1205,21 @@ void AppLayerParserSetEOF(AppLayerParserState *pstate)
SCReturn;
}
bool AppLayerParserHasDecoderEvents(const Flow *f,
void *alstate, AppLayerParserState *pstate,
const uint8_t flags)
/* return true if there are app parser decoder events. These are
* only the ones that are set during protocol detection. */
bool AppLayerParserHasDecoderEvents(AppLayerParserState *pstate)
{
SCEnter();
if (alstate == NULL || pstate == NULL)
goto not_present;
AppLayerDecoderEvents *decoder_events;
uint64_t tx_id;
uint64_t max_id;
if (AppLayerParserProtocolIsTxEventAware(f->proto, f->alproto)) {
/* fast path if supported by alproto */
if (alp_ctx.ctxs[f->protomap][f->alproto].StateHasEvents != NULL) {
if (alp_ctx.ctxs[f->protomap][f->alproto].
StateHasEvents(alstate) == 1)
{
goto present;
}
} else {
/* check each tx */
tx_id = AppLayerParserGetTransactionInspectId(pstate, flags);
max_id = AppLayerParserGetTxCnt(f, alstate);
for ( ; tx_id < max_id; tx_id++) {
decoder_events = AppLayerParserGetEventsByTx(f->proto, f->alproto, alstate, tx_id);
if (decoder_events && decoder_events->cnt)
goto present;
}
}
}
if (pstate == NULL)
return false;
decoder_events = AppLayerParserGetDecoderEvents(pstate);
const AppLayerDecoderEvents *decoder_events = AppLayerParserGetDecoderEvents(pstate);
if (decoder_events && decoder_events->cnt)
goto present;
return true;
/* if we have reached here, we don't have events */
not_present:
return false;
present:
return true;
}
/** \brief simpler way to globally test if a alproto is registered

@ -195,7 +195,7 @@ LoggerId AppLayerParserGetTxLogged(const Flow *f, void *alstate, void *tx);
uint64_t AppLayerParserGetTransactionInspectId(AppLayerParserState *pstate, uint8_t direction);
void AppLayerParserSetTransactionInspectId(const Flow *f, AppLayerParserState *pstate,
void *alstate, const uint8_t flags);
void *alstate, const uint8_t flags, bool tag_txs_as_inspected);
AppLayerDecoderEvents *AppLayerParserGetDecoderEvents(AppLayerParserState *pstate);
void AppLayerParserSetDecoderEvents(AppLayerParserState *pstate, AppLayerDecoderEvents *devents);
@ -232,8 +232,7 @@ int AppLayerParserSetTxMpmIDs(uint8_t ipproto, AppProto alproto, void *tx, uint6
int AppLayerParserParse(ThreadVars *tv, AppLayerParserThreadCtx *tctx, Flow *f, AppProto alproto,
uint8_t flags, uint8_t *input, uint32_t input_len);
void AppLayerParserSetEOF(AppLayerParserState *pstate);
bool AppLayerParserHasDecoderEvents(const Flow *f, void *alstate, AppLayerParserState *pstate,
const uint8_t flags);
bool AppLayerParserHasDecoderEvents(AppLayerParserState *pstate);
int AppLayerParserIsTxAware(AppProto alproto);
int AppLayerParserProtocolIsTxAware(uint8_t ipproto, AppProto alproto);
int AppLayerParserProtocolIsTxEventAware(uint8_t ipproto, AppProto alproto);

@ -58,6 +58,7 @@ enum AppProtoEnum {
/* keep last */
ALPROTO_MAX,
};
// NOTE: if ALPROTO's get >= 256, update SignatureNonPrefilterStore
/* not using the enum as that is a unsigned int, so 4 bytes */
typedef uint16_t AppProto;

@ -58,7 +58,6 @@ static int DetectEngineAptEventInspect(ThreadVars *tv,
const Signature *s, const SigMatchData *smd,
Flow *f, uint8_t flags, void *alstate,
void *tx, uint64_t tx_id);
static void DetectAppLayerEventSetupCallback(Signature *s);
static int g_applayer_events_list_id = 0;
/**
@ -81,9 +80,6 @@ void DetectAppLayerEventRegister(void)
ALPROTO_UNKNOWN, SIG_FLAG_TOCLIENT, 0,
DetectEngineAptEventInspect);
DetectBufferTypeRegisterSetupCallback("app-layer-events",
DetectAppLayerEventSetupCallback);
g_applayer_events_list_id = DetectBufferTypeGetByName("app-layer-events");
}
@ -146,38 +142,6 @@ static int DetectAppLayerEventPktMatch(ThreadVars *t, DetectEngineThreadCtx *det
aled->event_id);
}
static void DetectAppLayerEventSetupCallback(Signature *s)
{
SigMatch *sm;
for (sm = s->init_data->smlists[g_applayer_events_list_id] ; sm != NULL; sm = sm->next) {
switch (sm->type) {
case DETECT_AL_APP_LAYER_EVENT:
{
DetectAppLayerEventData *aed = (DetectAppLayerEventData *)sm->ctx;
switch (aed->alproto) {
case ALPROTO_HTTP:
s->mask |= SIG_MASK_REQUIRE_HTTP_STATE;
SCLogDebug("sig %u requires http app state (http event)", s->id);
break;
case ALPROTO_SMTP:
s->mask |= SIG_MASK_REQUIRE_SMTP_STATE;
SCLogDebug("sig %u requires smtp app state (smtp event)", s->id);
break;
case ALPROTO_DNS:
s->mask |= SIG_MASK_REQUIRE_DNS_STATE;
SCLogDebug("sig %u requires dns app state (dns event)", s->id);
break;
case ALPROTO_TLS:
s->mask |= SIG_MASK_REQUIRE_TLS_STATE;
SCLogDebug("sig %u requires tls app state (tls event)", s->id);
break;
}
break;
}
}
}
}
static DetectAppLayerEventData *DetectAppLayerEventParsePkt(const char *arg,
AppLayerEventType *event_type)
{

@ -403,7 +403,7 @@ deonly:
*/
void
PacketCreateMask(Packet *p, SignatureMask *mask, AppProto alproto,
bool has_state, bool app_decoder_events)
bool app_decoder_events)
{
if (!(p->flags & PKT_NOPAYLOAD_INSPECTION) && p->payload_len > 0) {
SCLogDebug("packet has payload");
@ -433,62 +433,6 @@ PacketCreateMask(Packet *p, SignatureMask *mask, AppProto alproto,
if (p->flags & PKT_HAS_FLOW) {
SCLogDebug("packet has flow");
(*mask) |= SIG_MASK_REQUIRE_FLOW;
if (has_state) {
switch(alproto) {
case ALPROTO_HTTP:
SCLogDebug("packet/flow has http state");
(*mask) |= SIG_MASK_REQUIRE_HTTP_STATE;
break;
case ALPROTO_SMB:
case ALPROTO_SMB2:
case ALPROTO_DCERPC:
SCLogDebug("packet/flow has dce state");
(*mask) |= SIG_MASK_REQUIRE_DCE_STATE;
break;
case ALPROTO_SSH:
SCLogDebug("packet/flow has ssh state");
(*mask) |= SIG_MASK_REQUIRE_SSH_STATE;
break;
case ALPROTO_TLS:
SCLogDebug("packet/flow has tls state");
(*mask) |= SIG_MASK_REQUIRE_TLS_STATE;
break;
case ALPROTO_DNS:
SCLogDebug("packet/flow has dns state");
(*mask) |= SIG_MASK_REQUIRE_DNS_STATE;
break;
case ALPROTO_FTP:
SCLogDebug("packet/flow has ftp state");
(*mask) |= SIG_MASK_REQUIRE_FTP_STATE;
break;
case ALPROTO_FTPDATA:
SCLogDebug("packet/flow has ftpdata state");
(*mask) |= SIG_MASK_REQUIRE_FTPDATA_STATE;
break;
case ALPROTO_SMTP:
SCLogDebug("packet/flow has smtp state");
(*mask) |= SIG_MASK_REQUIRE_SMTP_STATE;
break;
case ALPROTO_ENIP:
SCLogDebug("packet/flow has enip state");
(*mask) |= SIG_MASK_REQUIRE_ENIP_STATE;
break;
case ALPROTO_DNP3:
SCLogDebug("packet/flow has dnp3 state");
(*mask) |= SIG_MASK_REQUIRE_DNP3_STATE;
break;
case ALPROTO_TEMPLATE:
SCLogDebug("packet/flow has template state");
(*mask) |= SIG_MASK_REQUIRE_TEMPLATE_STATE;
break;
default:
SCLogDebug("packet/flow has other state");
break;
}
} else {
SCLogDebug("no alstate");
}
}
}
@ -593,59 +537,6 @@ static int SignatureCreateMask(Signature *s)
}
}
if (s->alproto == ALPROTO_SSH) {
s->mask |= SIG_MASK_REQUIRE_SSH_STATE;
SCLogDebug("sig requires ssh state");
}
if (s->alproto == ALPROTO_TLS) {
s->mask |= SIG_MASK_REQUIRE_TLS_STATE;
SCLogDebug("sig requires tls state");
}
if (s->alproto == ALPROTO_DNS) {
s->mask |= SIG_MASK_REQUIRE_DNS_STATE;
SCLogDebug("sig requires dns state");
}
if (s->alproto == ALPROTO_DNP3) {
s->mask |= SIG_MASK_REQUIRE_DNP3_STATE;
SCLogDebug("sig requires dnp3 state");
}
if (s->alproto == ALPROTO_FTP) {
s->mask |= SIG_MASK_REQUIRE_FTP_STATE;
SCLogDebug("sig requires ftp state");
}
if (s->alproto == ALPROTO_FTPDATA) {
s->mask |= SIG_MASK_REQUIRE_FTPDATA_STATE;
SCLogDebug("sig requires ftp data state");
}
if (s->alproto == ALPROTO_SMTP) {
s->mask |= SIG_MASK_REQUIRE_SMTP_STATE;
SCLogDebug("sig requires smtp state");
}
if (s->alproto == ALPROTO_ENIP) {
s->mask |= SIG_MASK_REQUIRE_ENIP_STATE;
SCLogDebug("sig requires enip state");
}
if (s->alproto == ALPROTO_TEMPLATE) {
s->mask |= SIG_MASK_REQUIRE_TEMPLATE_STATE;
SCLogDebug("sig requires template state");
}
if ((s->mask & SIG_MASK_REQUIRE_DCE_STATE) ||
(s->mask & SIG_MASK_REQUIRE_HTTP_STATE) ||
(s->mask & SIG_MASK_REQUIRE_SSH_STATE) ||
(s->mask & SIG_MASK_REQUIRE_DNS_STATE) ||
(s->mask & SIG_MASK_REQUIRE_DNP3_STATE) ||
(s->mask & SIG_MASK_REQUIRE_FTP_STATE) ||
(s->mask & SIG_MASK_REQUIRE_FTPDATA_STATE) ||
(s->mask & SIG_MASK_REQUIRE_SMTP_STATE) ||
(s->mask & SIG_MASK_REQUIRE_ENIP_STATE) ||
(s->mask & SIG_MASK_REQUIRE_TEMPLATE_STATE) ||
(s->mask & SIG_MASK_REQUIRE_TLS_STATE))
{
s->mask |= SIG_MASK_REQUIRE_FLOW;
SCLogDebug("sig requires flow");
}
if (s->init_data->init_flags & SIG_FLAG_INIT_FLOW) {
s->mask |= SIG_MASK_REQUIRE_FLOW;
SCLogDebug("sig requires flow");

@ -19,7 +19,7 @@
#define __DETECT_ENGINE_BUILD_H__
void PacketCreateMask(Packet *p, SignatureMask *mask, AppProto alproto,
bool has_state, bool app_decoder_events);
bool app_decoder_events);
int SignatureIsFilestoring(const Signature *);
int SignatureIsFilemagicInspecting(const Signature *);

@ -974,9 +974,9 @@ int IPOnlyMatchCompatSMs(ThreadVars *tv,
* \param p Pointer to the Packet to match against
*/
void IPOnlyMatchPacket(ThreadVars *tv,
DetectEngineCtx *de_ctx,
const DetectEngineCtx *de_ctx,
DetectEngineThreadCtx *det_ctx,
DetectEngineIPOnlyCtx *io_ctx,
const DetectEngineIPOnlyCtx *io_ctx,
DetectEngineIPOnlyThreadCtx *io_tctx, Packet *p)
{
SigNumArray *src = NULL;

@ -37,8 +37,8 @@ typedef struct SigNumArray_ {
void IPOnlyCIDRListFree(IPOnlyCIDRItem *tmphead);
int IPOnlySigParseAddress(const DetectEngineCtx *, Signature *, const char *, char);
void IPOnlyMatchPacket(ThreadVars *tv, DetectEngineCtx *,
DetectEngineThreadCtx *, DetectEngineIPOnlyCtx *,
void IPOnlyMatchPacket(ThreadVars *tv, const DetectEngineCtx *,
DetectEngineThreadCtx *, const DetectEngineIPOnlyCtx *,
DetectEngineIPOnlyThreadCtx *, Packet *);
void IPOnlyInit(DetectEngineCtx *, DetectEngineIPOnlyCtx *);
void IPOnlyPrint(DetectEngineCtx *, DetectEngineIPOnlyCtx *);

@ -326,9 +326,6 @@ int DetectEngineInspectStream(ThreadVars *tv,
if (ssn == NULL)
return DETECT_ENGINE_INSPECT_SIG_CANT_MATCH;
if (det_ctx->stream_already_inspected)
return det_ctx->stream_last_result;
uint64_t unused;
struct StreamContentInspectEngineData inspect_data = { de_ctx, det_ctx, s, smd, f };
int match = StreamReassembleRaw(f->protoctx, p,
@ -349,19 +346,15 @@ int DetectEngineInspectStream(ThreadVars *tv,
SCLogDebug("%s ran stream for sid %u on packet %"PRIu64" and we %s",
is_last? "LAST:" : "normal:", s->id, p->pcap_cnt,
match ? "matched" : "didn't match");
det_ctx->stream_already_inspected = true;
if (match) {
det_ctx->stream_last_result = DETECT_ENGINE_INSPECT_SIG_MATCH;
return DETECT_ENGINE_INSPECT_SIG_MATCH;
} else {
if (is_last) {
det_ctx->stream_last_result = DETECT_ENGINE_INSPECT_SIG_CANT_MATCH;
//SCLogNotice("last, so DETECT_ENGINE_INSPECT_SIG_CANT_MATCH");
return DETECT_ENGINE_INSPECT_SIG_CANT_MATCH;
}
/* TODO maybe we can set 'CANT_MATCH' for EOF too? */
det_ctx->stream_last_result = DETECT_ENGINE_INSPECT_SIG_NO_MATCH;
return DETECT_ENGINE_INSPECT_SIG_NO_MATCH;
}
}

@ -88,75 +88,60 @@ static inline void QuickSortSigIntId(SigIntId *sids, uint32_t n)
QuickSortSigIntId(l, sids + n - l);
}
static inline void PrefilterTx(DetectEngineThreadCtx *det_ctx,
const SigGroupHead *sgh, Packet *p, const uint8_t flags)
/**
* \brief run prefilter engines on a transaction
*/
void DetectRunPrefilterTx(DetectEngineThreadCtx *det_ctx,
const SigGroupHead *sgh,
Packet *p,
const uint8_t ipproto,
const uint8_t flow_flags,
const AppProto alproto,
void *alstate,
DetectTransaction *tx)
{
SCEnter();
const AppProto alproto = p->flow->alproto;
const uint8_t ipproto = p->proto;
if (!(AppLayerParserProtocolIsTxAware(ipproto, alproto)))
SCReturn;
void *alstate = p->flow->alstate;
uint64_t idx = AppLayerParserGetTransactionInspectId(p->flow->alparser, flags);
const uint64_t total_txs = AppLayerParserGetTxCnt(p->flow, alstate);
/* HACK test HTTP state here instead of in each engine */
if (alproto == ALPROTO_HTTP) {
HtpState *htp_state = (HtpState *)alstate;
if (unlikely(htp_state->connp == NULL)) {
SCLogDebug("no HTTP connp");
SCReturn;
}
}
/* run our engines against each tx */
for (; idx < total_txs; idx++) {
void *tx = AppLayerParserGetTx(ipproto, alproto, alstate, idx);
if (tx == NULL)
continue;
uint64_t mpm_ids = AppLayerParserGetTxMpmIDs(ipproto, alproto, tx);
const int tx_progress = AppLayerParserGetStateProgress(ipproto, alproto, tx, flags);
SCLogDebug("tx %p progress %d", tx, tx_progress);
PrefilterEngine *engine = sgh->tx_engines;
do {
if (engine->alproto != alproto)
goto next;
if (engine->tx_min_progress > tx_progress)
/* reset rule store */
det_ctx->pmq.rule_id_array_cnt = 0;
SCLogDebug("tx %p progress %d", tx->tx_ptr, tx->tx_progress);
PrefilterEngine *engine = sgh->tx_engines;
do {
if (engine->alproto != alproto)
goto next;
if (engine->tx_min_progress > tx->tx_progress)
goto next;
if (tx->tx_progress > engine->tx_min_progress) {
if (tx->prefilter_flags & (1<<(engine->id))) {
goto next;
if (tx_progress > engine->tx_min_progress) {
if (mpm_ids & (1<<(engine->gid))) {
goto next;
}
}
}
PROFILING_PREFILTER_START(p);
engine->cb.PrefilterTx(det_ctx, engine->pectx,
p, p->flow, tx, idx, flags);
PROFILING_PREFILTER_END(p, engine->gid);
PROFILING_PREFILTER_START(p);
engine->cb.PrefilterTx(det_ctx, engine->pectx,
p, p->flow, tx->tx_ptr, tx->tx_id, flow_flags);
PROFILING_PREFILTER_END(p, engine->gid);
if (tx_progress > engine->tx_min_progress) {
mpm_ids |= (1<<(engine->gid));
}
next:
if (engine->is_last)
break;
engine++;
} while (1);
if (mpm_ids != 0) {
//SCLogNotice("tx %p Mpm IDs: %"PRIx64, tx, mpm_ids);
AppLayerParserSetTxMpmIDs(ipproto, alproto, tx, mpm_ids);
if (tx->tx_progress > engine->tx_min_progress) {
tx->prefilter_flags |= (1<<(engine->id));
}
next:
if (engine->is_last)
break;
engine++;
} while (1);
/* Sort the rule list to lets look at pmq.
* NOTE due to merging of 'stream' pmqs we *MAY* have duplicate entries */
if (likely(det_ctx->pmq.rule_id_array_cnt > 1)) {
PACKET_PROFILING_DETECT_START(p, PROF_DETECT_PF_SORT1);
QuickSortSigIntId(det_ctx->pmq.rule_id_array, det_ctx->pmq.rule_id_array_cnt);
PACKET_PROFILING_DETECT_END(p, PROF_DETECT_PF_SORT1);
}
}
void Prefilter(DetectEngineThreadCtx *det_ctx, const SigGroupHead *sgh,
Packet *p, const uint8_t flags, const bool has_state)
Packet *p, const uint8_t flags)
{
SCEnter();
@ -197,17 +182,6 @@ void Prefilter(DetectEngineThreadCtx *det_ctx, const SigGroupHead *sgh,
PACKET_PROFILING_DETECT_END(p, PROF_DETECT_PF_PAYLOAD);
}
/* run tx engines */
if (((p->proto == IPPROTO_TCP && p->flowflags & FLOW_PKT_ESTABLISHED) || p->proto != IPPROTO_TCP) && has_state) {
if (sgh->tx_engines != NULL && p->flow != NULL &&
p->flow->alproto != ALPROTO_UNKNOWN && p->flow->alstate != NULL)
{
PACKET_PROFILING_DETECT_START(p, PROF_DETECT_PF_TX);
PrefilterTx(det_ctx, sgh, p, flags);
PACKET_PROFILING_DETECT_END(p, PROF_DETECT_PF_TX);
}
}
/* Sort the rule list to lets look at pmq.
* NOTE due to merging of 'stream' pmqs we *MAY* have duplicate entries */
if (likely(det_ctx->pmq.rule_id_array_cnt > 1)) {

@ -24,8 +24,10 @@
#ifndef __DETECT_ENGINE_PREFILTER_H__
#define __DETECT_ENGINE_PREFILTER_H__
#include "detect-engine-state.h"
void Prefilter(DetectEngineThreadCtx *, const SigGroupHead *, Packet *p,
const uint8_t flags, const bool has_state);
const uint8_t flags);
int PrefilterAppendEngine(SigGroupHead *sgh,
void (*Prefilter)(DetectEngineThreadCtx *det_ctx, Packet *p, const void *pectx),
@ -43,6 +45,15 @@ int PrefilterAppendTxEngine(SigGroupHead *sgh,
void *pectx, void (*FreeFunc)(void *pectx),
const char *name);
void DetectRunPrefilterTx(DetectEngineThreadCtx *det_ctx,
const SigGroupHead *sgh,
Packet *p,
const uint8_t ipproto,
const uint8_t flow_flags,
const AppProto alproto,
void *alstate,
DetectTransaction *tx);
void PrefilterFreeEnginesList(PrefilterEngineList *list);
void PrefilterSetupRuleGroup(DetectEngineCtx *de_ctx, SigGroupHead *sgh);

@ -57,7 +57,8 @@ static void DumpFp(const SigMatch *sm, char *pat_orig, uint32_t pat_orig_sz, cha
#endif
SCMutex g_rule_dump_write_m = SCMUTEX_INITIALIZER;
void RulesDumpMatchArray(const DetectEngineThreadCtx *det_ctx, const Packet *p)
void RulesDumpMatchArray(const DetectEngineThreadCtx *det_ctx,
const SigGroupHead *sgh, const Packet *p)
{
json_t *js = CreateJSONHeader(p, 0, "inspectedrules");
if (js == NULL)
@ -66,7 +67,7 @@ void RulesDumpMatchArray(const DetectEngineThreadCtx *det_ctx, const Packet *p)
if (ir == NULL)
return;
json_object_set_new(ir, "rule_group_id", json_integer(det_ctx->sgh->id));
json_object_set_new(ir, "rule_group_id", json_integer(sgh->id));
json_object_set_new(ir, "rule_cnt", json_integer(det_ctx->match_array_cnt));
json_t *js_array = json_array();

@ -24,6 +24,7 @@
#ifndef _DETECT_ENGINE_PROFILE_H
#define _DETECT_ENGINE_PROFILE_H
void RulesDumpMatchArray(const DetectEngineThreadCtx *det_ctx, const Packet *p);
void RulesDumpMatchArray(const DetectEngineThreadCtx *det_ctx,
const SigGroupHead *sgh, const Packet *p);
#endif /* _DETECT_ENGINE_PROFILE_H */

@ -696,6 +696,7 @@ int SigGroupHeadBuildNonPrefilterArray(DetectEngineCtx *de_ctx, SigGroupHead *sg
BUG_ON(sgh->non_pf_other_store_array == NULL);
sgh->non_pf_other_store_array[sgh->non_pf_other_store_cnt].id = s->num;
sgh->non_pf_other_store_array[sgh->non_pf_other_store_cnt].mask = s->mask;
sgh->non_pf_other_store_array[sgh->non_pf_other_store_cnt].alproto = s->alproto;
sgh->non_pf_other_store_cnt++;
}
@ -703,6 +704,7 @@ int SigGroupHeadBuildNonPrefilterArray(DetectEngineCtx *de_ctx, SigGroupHead *sg
BUG_ON(sgh->non_pf_syn_store_array == NULL);
sgh->non_pf_syn_store_array[sgh->non_pf_syn_store_cnt].id = s->num;
sgh->non_pf_syn_store_array[sgh->non_pf_syn_store_cnt].mask = s->mask;
sgh->non_pf_syn_store_array[sgh->non_pf_syn_store_cnt].alproto = s->alproto;
sgh->non_pf_syn_store_cnt++;
}
}

@ -81,6 +81,7 @@
/** convert enum to string */
#define CASE_CODE(E) case E: return #E
#if 0
/** The DetectEngineThreadCtx::de_state_sig_array contains 2 separate values:
* 1. the first bit tells the prefilter engine to bypass the rule (or not)
* 2. the other bits allow 'ContinueDetect' to specify an offset again the
@ -94,6 +95,7 @@
#define MAX_STORED_TXID_OFFSET 127
/******** static internal helpers *********/
#endif
static inline int StateIsValid(uint16_t alproto, void *alstate)
{
@ -110,12 +112,14 @@ static inline int StateIsValid(uint16_t alproto, void *alstate)
return 0;
}
#if 0
static inline int TxIsLast(uint64_t tx_id, uint64_t total_txs)
{
if (total_txs - tx_id <= 1)
return 1;
return 0;
}
#endif
static DeStateStore *DeStateStoreAlloc(void)
{
@ -127,6 +131,7 @@ static DeStateStore *DeStateStoreAlloc(void)
return d;
}
#ifdef DEBUG_VALIDATION
static int DeStateSearchState(DetectEngineState *state, uint8_t direction, SigIntId num)
{
DetectEngineStateDirection *dir_state = &state->dir_state[direction & STREAM_TOSERVER ? 0 : 1];
@ -151,6 +156,7 @@ static int DeStateSearchState(DetectEngineState *state, uint8_t direction, SigIn
}
return 0;
}
#endif
static void DeStateSignatureAppend(DetectEngineState *state,
const Signature *s, uint32_t inspect_flags, uint8_t direction)
@ -194,21 +200,6 @@ static void DeStateSignatureAppend(DetectEngineState *state,
return;
}
static void DeStateStoreFileNoMatchCnt(DetectEngineState *de_state, uint16_t file_no_match, uint8_t direction)
{
de_state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].filestore_cnt += file_no_match;
return;
}
static int DeStateStoreFilestoreSigsCantMatch(const SigGroupHead *sgh, DetectEngineState *de_state, uint8_t direction)
{
if (de_state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].filestore_cnt == sgh->filestore_cnt)
return 1;
else
return 0;
}
DetectEngineState *DetectEngineStateAlloc(void)
{
DetectEngineState *d = SCMalloc(sizeof(DetectEngineState));
@ -238,75 +229,37 @@ void DetectEngineStateFree(DetectEngineState *state)
return;
}
static int HasStoredSigs(const Flow *f, const uint8_t flags)
static void StoreFileNoMatchCnt(DetectEngineState *de_state, uint16_t file_no_match, uint8_t direction)
{
AppProto alproto = f->alproto;
void *alstate = FlowGetAppState(f);
if (!StateIsValid(f->alproto, alstate)) {
return 0;
}
int state = AppLayerParserHasTxDetectState(f->proto, alproto, f->alstate);
if (state == -ENOSYS) { /* proto doesn't support this API call */
/* fall through */
} else if (state == 0) {
return 0;
}
/* if state == 1 we also fall through */
uint64_t inspect_tx_id = AppLayerParserGetTransactionInspectId(f->alparser, flags);
uint64_t total_txs = AppLayerParserGetTxCnt(f, alstate);
de_state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].filestore_cnt += file_no_match;
for ( ; inspect_tx_id < total_txs; inspect_tx_id++) {
void *inspect_tx = AppLayerParserGetTx(f->proto, alproto, alstate, inspect_tx_id);
if (inspect_tx != NULL) {
DetectEngineState *tx_de_state = AppLayerParserGetTxDetectState(f->proto, alproto, inspect_tx);
if (tx_de_state == NULL) {
continue;
}
if (tx_de_state->dir_state[flags & STREAM_TOSERVER ? 0 : 1].cnt != 0) {
SCLogDebug("tx %"PRIu64" has sigs present", inspect_tx_id);
return 1;
}
}
}
return 0;
return;
}
/** \brief Check if we need to inspect this state
*
* State needs to be inspected if:
* 1. state has been updated
* 2. we already have de_state in progress
*
* \retval 0 no inspectable state
* \retval 1 inspectable state
*/
int DeStateFlowHasInspectableState(const Flow *f, const uint8_t flags)
static bool StoreFilestoreSigsCantMatch(const SigGroupHead *sgh, const DetectEngineState *de_state, uint8_t direction)
{
int r = 0;
if (HasStoredSigs(f, flags)) {
r = 1;
} else {
r = 0;
}
return r;
if (de_state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].filestore_cnt == sgh->filestore_cnt)
return true;
else
return false;
}
static void StoreStateTxHandleFiles(DetectEngineThreadCtx *det_ctx, Flow *f,
DetectEngineState *destate, const uint8_t flags,
static void StoreStateTxHandleFiles(const SigGroupHead *sgh, Flow *f,
DetectEngineState *destate, const uint8_t flow_flags,
const uint64_t tx_id, const uint16_t file_no_match)
{
SCLogDebug("tx %"PRIu64", file_no_match %u", tx_id, file_no_match);
DeStateStoreFileNoMatchCnt(destate, file_no_match, flags);
if (DeStateStoreFilestoreSigsCantMatch(det_ctx->sgh, destate, flags) == 1) {
FileDisableStoringForTransaction(f, flags & (STREAM_TOCLIENT | STREAM_TOSERVER), tx_id);
StoreFileNoMatchCnt(destate, file_no_match, flow_flags);
if (StoreFilestoreSigsCantMatch(sgh, destate, flow_flags)) {
FileDisableStoringForTransaction(f, flow_flags & (STREAM_TOCLIENT | STREAM_TOSERVER), tx_id);
}
}
static void StoreStateTxFileOnly(DetectEngineThreadCtx *det_ctx,
Flow *f, const uint8_t flags, const uint64_t tx_id, void *tx,
void DetectRunStoreStateTx(
const SigGroupHead *sgh,
Flow *f, void *tx, uint64_t tx_id,
const Signature *s,
uint32_t inspect_flags, uint8_t flow_flags,
const uint16_t file_no_match)
{
DetectEngineState *destate = AppLayerParserGetTxDetectState(f->proto, f->alproto, tx);
@ -320,9 +273,33 @@ static void StoreStateTxFileOnly(DetectEngineThreadCtx *det_ctx,
}
SCLogDebug("destate created for %"PRIu64, tx_id);
}
StoreStateTxHandleFiles(det_ctx, f, destate, flags, tx_id, file_no_match);
DeStateSignatureAppend(destate, s, inspect_flags, flow_flags);
StoreStateTxHandleFiles(sgh, f, destate, flow_flags, tx_id, file_no_match);
SCLogDebug("Stored for TX %"PRIu64, tx_id);
}
void DetectRunStoreStateTxFileOnly(
const SigGroupHead *sgh,
Flow *f, void *tx, uint64_t tx_id,
const uint8_t flow_flags,
const uint16_t file_no_match)
{
DetectEngineState *destate = AppLayerParserGetTxDetectState(f->proto, f->alproto, tx);
if (destate == NULL) {
destate = DetectEngineStateAlloc();
if (destate == NULL)
return;
if (AppLayerParserSetTxDetectState(f, f->alstate, tx, destate) < 0) {
DetectEngineStateFree(destate);
return;
}
SCLogDebug("destate created for %"PRIu64, tx_id);
}
StoreStateTxHandleFiles(sgh, f, destate, flow_flags, tx_id, file_no_match);
}
#if 0
/**
* \param check_before_add check for duplicates before adding the sig
*/
@ -353,6 +330,62 @@ static void StoreStateTx(DetectEngineThreadCtx *det_ctx,
SCLogDebug("Stored for TX %"PRIu64, tx_id);
}
static int HasStoredSigs(const Flow *f, const uint8_t flags)
{
AppProto alproto = f->alproto;
void *alstate = FlowGetAppState(f);
if (!StateIsValid(f->alproto, alstate)) {
return 0;
}
int state = AppLayerParserHasTxDetectState(f->proto, alproto, f->alstate);
if (state == -ENOSYS) { /* proto doesn't support this API call */
/* fall through */
} else if (state == 0) {
return 0;
}
/* if state == 1 we also fall through */
uint64_t inspect_tx_id = AppLayerParserGetTransactionInspectId(f->alparser, flags);
uint64_t total_txs = AppLayerParserGetTxCnt(f, alstate);
for ( ; inspect_tx_id < total_txs; inspect_tx_id++) {
void *inspect_tx = AppLayerParserGetTx(f->proto, alproto, alstate, inspect_tx_id);
if (inspect_tx != NULL) {
DetectEngineState *tx_de_state = AppLayerParserGetTxDetectState(f->proto, alproto, inspect_tx);
if (tx_de_state == NULL) {
continue;
}
if (tx_de_state->dir_state[flags & STREAM_TOSERVER ? 0 : 1].cnt != 0) {
SCLogDebug("tx %"PRIu64" has sigs present", inspect_tx_id);
return 1;
}
}
}
return 0;
}
/** \brief Check if we need to inspect this state
*
* State needs to be inspected if:
* 1. state has been updated
* 2. we already have de_state in progress
*
* \retval 0 no inspectable state
* \retval 1 inspectable state
*/
int DeStateFlowHasInspectableState(const Flow *f, const uint8_t flags)
{
int r = 0;
if (HasStoredSigs(f, flags)) {
r = 1;
} else {
r = 0;
}
return r;
}
/* returns: true match, false no match */
bool DeStateDetectStartDetection(ThreadVars *tv,
DetectEngineCtx *de_ctx,
@ -822,17 +855,23 @@ end:
det_ctx->tx_id_set = 0;
return;
}
#endif
/** \brief update flow's inspection id's
*
* \param f unlocked flow
* \param flags direction and disruption flags
* \param tag_txs_as_inspected if true all 'complete' txs will be marked
* 'inspected'
*
* \note it is possible that f->alstate, f->alparser are NULL */
void DeStateUpdateInspectTransactionId(Flow *f, const uint8_t flags)
void DeStateUpdateInspectTransactionId(Flow *f, const uint8_t flags,
const bool tag_txs_as_inspected)
{
if (f->alparser && f->alstate) {
AppLayerParserSetTransactionInspectId(f, f->alparser,
f->alstate, flags);
f->alstate, flags,
tag_txs_as_inspected);
}
return;
}

@ -82,8 +82,8 @@
* the HAS_NEW_STATE flag, while if we don't have a new tx, we set
* NO_NEW_STATE, to avoid getting the sig reinspected for the already
* inspected tx. */
#define DE_STATE_MATCH_HAS_NEW_STATE 0x00
#define DE_STATE_MATCH_NO_NEW_STATE 0x80
//#define DE_STATE_MATCH_HAS_NEW_STATE 0x00
//#define DE_STATE_MATCH_NO_NEW_STATE 0x80
typedef struct DeStateStoreItem_ {
uint32_t flags;
@ -108,6 +108,18 @@ typedef struct DetectEngineState_ {
DetectEngineStateDirection dir_state[2];
} DetectEngineState;
// TODO
typedef struct DetectTransaction_ {
void *tx_ptr;
const uint64_t tx_id;
DetectEngineStateDirection *de_state;
const uint64_t detect_flags; /* detect flags get/set from/to applayer */
uint64_t prefilter_flags; /* prefilter flags for direction, to be updated by prefilter code */
const uint64_t prefilter_flags_orig; /* prefilter flags for direction, before prefilter has run */
const int tx_progress;
const int tx_end_state;
} DetectTransaction;
/**
* \brief Alloc a DetectEngineState object.
*
@ -173,12 +185,27 @@ void DeStateDetectContinueDetection(ThreadVars *tv, DetectEngineCtx *de_ctx,
* \param f unlocked flow
* \param flags direction and disruption flags
*/
void DeStateUpdateInspectTransactionId(Flow *f, const uint8_t flags);
void DeStateUpdateInspectTransactionId(Flow *f, const uint8_t flags,
const bool tag_txs_as_inspected);
void DetectEngineStateResetTxs(Flow *f);
void DeStateRegisterTests(void);
void DetectRunStoreStateTx(
const SigGroupHead *sgh,
Flow *f, void *tx, uint64_t tx_id,
const Signature *s,
uint32_t inspect_flags, uint8_t flow_flags,
const uint16_t file_no_match);
void DetectRunStoreStateTxFileOnly(
const SigGroupHead *sgh,
Flow *f, void *tx, uint64_t tx_id,
const uint8_t flow_flags,
const uint16_t file_no_match);
#endif /* __DETECT_ENGINE_STATE_H__ */
/**

@ -168,6 +168,7 @@ static void AppendStreamInspectEngine(Signature *s, SigMatchData *stream, int di
}
new_engine->alproto = ALPROTO_UNKNOWN; /* all */
new_engine->dir = direction;
new_engine->stream = true;
new_engine->sm_list = DETECT_SM_LIST_PMATCH;
new_engine->smd = stream;
new_engine->Callback = DetectEngineInspectStream;
@ -1738,14 +1739,6 @@ static TmEcode ThreadCtxDoInit (DetectEngineCtx *de_ctx, DetectEngineThreadCtx *
/* DeState */
if (de_ctx->sig_array_len > 0) {
det_ctx->de_state_sig_array_len = de_ctx->sig_array_len;
det_ctx->de_state_sig_array = SCMalloc(det_ctx->de_state_sig_array_len * sizeof(uint8_t));
if (det_ctx->de_state_sig_array == NULL) {
return TM_ECODE_FAILED;
}
memset(det_ctx->de_state_sig_array, 0,
det_ctx->de_state_sig_array_len * sizeof(uint8_t));
det_ctx->match_array_len = de_ctx->sig_array_len;
det_ctx->match_array = SCMalloc(det_ctx->match_array_len * sizeof(Signature *));
if (det_ctx->match_array == NULL) {
@ -1753,6 +1746,8 @@ static TmEcode ThreadCtxDoInit (DetectEngineCtx *de_ctx, DetectEngineThreadCtx *
}
memset(det_ctx->match_array, 0,
det_ctx->match_array_len * sizeof(Signature *));
RuleMatchCandidateTxArrayInit(det_ctx, de_ctx->sig_array_len);
}
/* byte_extract storage */
@ -1957,11 +1952,11 @@ static void DetectEngineThreadCtxFree(DetectEngineThreadCtx *det_ctx)
if (det_ctx->non_pf_id_array != NULL)
SCFree(det_ctx->non_pf_id_array);
if (det_ctx->de_state_sig_array != NULL)
SCFree(det_ctx->de_state_sig_array);
if (det_ctx->match_array != NULL)
SCFree(det_ctx->match_array);
RuleMatchCandidateTxArrayFree(det_ctx);
if (det_ctx->bj_values != NULL)
SCFree(det_ctx->bj_values);

@ -172,11 +172,6 @@ static void DetectFiledataSetupCallback(Signature *s)
if (s->alproto == ALPROTO_HTTP || s->alproto == ALPROTO_UNKNOWN) {
AppLayerHtpEnableRequestBodyCallback();
}
if (s->alproto == ALPROTO_HTTP) {
s->mask |= SIG_MASK_REQUIRE_HTTP_STATE;
} else if (s->alproto == ALPROTO_SMTP) {
s->mask |= SIG_MASK_REQUIRE_SMTP_STATE;
}
SCLogDebug("callback invoked by %u", s->id);
}

@ -99,7 +99,6 @@ static void DetectHttpClientBodySetupCallback(Signature *s)
{
SCLogDebug("callback invoked by %u", s->id);
AppLayerHtpEnableRequestBodyCallback();
s->mask |= SIG_MASK_REQUIRE_HTTP_STATE;
}
/**

@ -64,7 +64,6 @@
static int DetectHttpCookieSetup (DetectEngineCtx *, Signature *, const char *);
static void DetectHttpCookieRegisterTests(void);
static void DetectHttpCookieFree(void *);
static void DetectHttpCookieSetupCallback(Signature *s);
static int g_http_cookie_buffer_id = 0;
/**
@ -97,9 +96,6 @@ void DetectHttpCookieRegister(void)
DetectBufferTypeSetDescriptionByName("http_cookie",
"http cookie header");
DetectBufferTypeRegisterSetupCallback("http_cookie",
DetectHttpCookieSetupCallback);
g_http_cookie_buffer_id = DetectBufferTypeGetByName("http_cookie");
}
@ -137,13 +133,6 @@ static int DetectHttpCookieSetup(DetectEngineCtx *de_ctx, Signature *s, const ch
ALPROTO_HTTP);
}
static void DetectHttpCookieSetupCallback(Signature *s)
{
SCLogDebug("callback invoked by %u", s->id);
s->mask |= SIG_MASK_REQUIRE_HTTP_STATE;
}
/******************************** UNITESTS **********************************/
#ifdef UNITTESTS

@ -365,12 +365,6 @@ static int DetectHttpHeaderNamesSetup(DetectEngineCtx *de_ctx, Signature *s, con
return 0;
}
static void DetectHttpHeaderNamesSetupCallback(Signature *s)
{
SCLogDebug("callback invoked by %u", s->id);
s->mask |= SIG_MASK_REQUIRE_HTTP_STATE;
}
/**
* \brief Registers the keyword handlers for the "http_header" keyword.
*/
@ -398,9 +392,6 @@ void DetectHttpHeaderNamesRegister(void)
DetectBufferTypeSetDescriptionByName(BUFFER_NAME,
BUFFER_DESC);
DetectBufferTypeRegisterSetupCallback(BUFFER_NAME,
DetectHttpHeaderNamesSetupCallback);
g_buffer_id = DetectBufferTypeGetByName(BUFFER_NAME);
g_keyword_thread_id = DetectRegisterThreadCtxGlobalFuncs(KEYWORD_NAME,

@ -65,7 +65,6 @@
static int DetectHttpHeaderSetup(DetectEngineCtx *, Signature *, const char *);
static void DetectHttpHeaderRegisterTests(void);
static void DetectHttpHeaderSetupCallback(Signature *);
static int g_http_header_buffer_id = 0;
static int g_keyword_thread_id = 0;
@ -367,12 +366,6 @@ static int DetectHttpHeaderSetup(DetectEngineCtx *de_ctx, Signature *s, const ch
ALPROTO_HTTP);
}
static void DetectHttpHeaderSetupCallback(Signature *s)
{
SCLogDebug("callback invoked by %u", s->id);
s->mask |= SIG_MASK_REQUIRE_HTTP_STATE;
}
/**
* \brief Registers the keyword handlers for the "http_header" keyword.
*/
@ -401,9 +394,6 @@ void DetectHttpHeaderRegister(void)
DetectBufferTypeSetDescriptionByName("http_header",
"http headers");
DetectBufferTypeRegisterSetupCallback("http_header",
DetectHttpHeaderSetupCallback);
g_http_header_buffer_id = DetectBufferTypeGetByName("http_header");
g_keyword_thread_id = DetectRegisterThreadCtxGlobalFuncs("http_header",

@ -322,12 +322,6 @@ static int DetectHttpHeadersSetup(DetectEngineCtx *de_ctx, Signature *s, const c
return 0;
}
static void DetectHttpHeadersSetupCallback(Signature *s)
{
SCLogDebug("callback invoked by %u", s->id);
s->mask |= SIG_MASK_REQUIRE_HTTP_STATE;
}
static void DetectHttpHeadersRegisterStub(void)
{
sigmatch_table[KEYWORD_ID].name = KEYWORD_NAME;
@ -356,8 +350,5 @@ static void DetectHttpHeadersRegisterStub(void)
DetectBufferTypeSetDescriptionByName(BUFFER_NAME, BUFFER_DESC);
DetectBufferTypeRegisterSetupCallback(BUFFER_NAME,
DetectHttpHeadersSetupCallback);
g_buffer_id = DetectBufferTypeGetByName(BUFFER_NAME);
}

@ -62,7 +62,6 @@
static int DetectHttpHHSetup(DetectEngineCtx *, Signature *, const char *);
static void DetectHttpHHRegisterTests(void);
static void DetectHttpHHFree(void *);
static void DetectHttpHostSetupCallback(Signature *s);
static _Bool DetectHttpHostValidateCallback(const Signature *s, const char **sigerror);
static int g_http_host_buffer_id = 0;
@ -90,9 +89,6 @@ void DetectHttpHHRegister(void)
DetectBufferTypeSetDescriptionByName("http_host",
"http host header");
DetectBufferTypeRegisterSetupCallback("http_host",
DetectHttpHostSetupCallback);
DetectBufferTypeRegisterValidateCallback("http_host",
DetectHttpHostValidateCallback);
@ -120,12 +116,6 @@ static int DetectHttpHHSetup(DetectEngineCtx *de_ctx, Signature *s, const char *
ALPROTO_HTTP);
}
static void DetectHttpHostSetupCallback(Signature *s)
{
SCLogDebug("callback invoked by %u", s->id);
s->mask |= SIG_MASK_REQUIRE_HTTP_STATE;
}
static _Bool DetectHttpHostValidateCallback(const Signature *s, const char **sigerror)
{
const SigMatch *sm = s->init_data->smlists[g_http_host_buffer_id];

@ -62,7 +62,6 @@
static int DetectHttpHRHSetup(DetectEngineCtx *, Signature *, const char *);
static void DetectHttpHRHRegisterTests(void);
static void DetectHttpHRHFree(void *);
static void DetectHttpHostRawSetupCallback(Signature *);
static int g_http_raw_host_buffer_id = 0;
/**
@ -89,9 +88,6 @@ void DetectHttpHRHRegister(void)
DetectBufferTypeSetDescriptionByName("http_raw_host",
"http raw host header");
DetectBufferTypeRegisterSetupCallback("http_raw_host",
DetectHttpHostRawSetupCallback);
g_http_raw_host_buffer_id = DetectBufferTypeGetByName("http_raw_host");
}
@ -116,12 +112,6 @@ int DetectHttpHRHSetup(DetectEngineCtx *de_ctx, Signature *s, const char *arg)
ALPROTO_HTTP);
}
static void DetectHttpHostRawSetupCallback(Signature *s)
{
SCLogDebug("callback invoked by %u", s->id);
s->mask |= SIG_MASK_REQUIRE_HTTP_STATE;
}
/**
* \brief The function to free the http_raw_host data.
*

@ -64,7 +64,6 @@ static int g_http_method_buffer_id = 0;
static int DetectHttpMethodSetup(DetectEngineCtx *, Signature *, const char *);
void DetectHttpMethodRegisterTests(void);
void DetectHttpMethodFree(void *);
static void DetectHttpMethodSetupCallback(Signature *s);
static _Bool DetectHttpMethodValidateCallback(const Signature *s, const char **sigerror);
/**
@ -91,8 +90,6 @@ void DetectHttpMethodRegister(void)
DetectBufferTypeSetDescriptionByName("http_method",
"http request method");
DetectBufferTypeRegisterSetupCallback("http_method",
DetectHttpMethodSetupCallback);
DetectBufferTypeRegisterValidateCallback("http_method",
DetectHttpMethodValidateCallback);
@ -134,12 +131,6 @@ void DetectHttpMethodFree(void *ptr)
SCFree(data);
}
static void DetectHttpMethodSetupCallback(Signature *s)
{
SCLogDebug("callback invoked by %u", s->id);
s->mask |= SIG_MASK_REQUIRE_HTTP_STATE;
}
/**
* \retval 1 valid
* \retval 0 invalid

@ -200,12 +200,6 @@ static int DetectHttpProtocolSetup(DetectEngineCtx *de_ctx, Signature *s, const
return 0;
}
static void DetectHttpProtocolSetupCallback(Signature *s)
{
SCLogDebug("callback invoked by %u", s->id);
s->mask |= SIG_MASK_REQUIRE_HTTP_STATE;
}
/**
* \brief Registers the keyword handlers for the "http_header" keyword.
*/
@ -233,8 +227,5 @@ void DetectHttpProtocolRegister(void)
DetectBufferTypeSetDescriptionByName(BUFFER_NAME,
BUFFER_DESC);
DetectBufferTypeRegisterSetupCallback(BUFFER_NAME,
DetectHttpProtocolSetupCallback);
g_buffer_id = DetectBufferTypeGetByName(BUFFER_NAME);
}

@ -64,7 +64,6 @@ static int DetectHttpRawHeaderSetup(DetectEngineCtx *, Signature *, const char *
static void DetectHttpRawHeaderRegisterTests(void);
static void DetectHttpRawHeaderFree(void *);
static _Bool DetectHttpRawHeaderValidateCallback(const Signature *s, const char **sigerror);
static void DetectHttpRawHeaderSetupCallback(Signature *s);
static int g_http_raw_header_buffer_id = 0;
/**
@ -97,8 +96,6 @@ void DetectHttpRawHeaderRegister(void)
DetectBufferTypeRegisterValidateCallback("http_raw_header",
DetectHttpRawHeaderValidateCallback);
DetectBufferTypeRegisterSetupCallback("http_raw_header",
DetectHttpRawHeaderSetupCallback);
g_http_raw_header_buffer_id = DetectBufferTypeGetByName("http_raw_header");
}
@ -157,12 +154,6 @@ static _Bool DetectHttpRawHeaderValidateCallback(const Signature *s, const char
return TRUE;
}
static void DetectHttpRawHeaderSetupCallback(Signature *s)
{
SCLogDebug("callback invoked by %u", s->id);
s->mask |= SIG_MASK_REQUIRE_HTTP_STATE;
}
/************************************Unittests*********************************/
#ifdef UNITTESTS

@ -121,7 +121,6 @@ static bool DetectHttpRawUriValidateCallback(const Signature *s, const char **si
static void DetectHttpRawUriSetupCallback(Signature *s)
{
SCLogDebug("callback invoked by %u", s->id);
s->mask |= SIG_MASK_REQUIRE_HTTP_STATE;
DetectUrilenApplyToContent(s, g_http_raw_uri_buffer_id);
}

@ -67,7 +67,6 @@ static int DetectEngineInspectHttpRequestLine(ThreadVars *tv,
DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx,
const Signature *s, const SigMatchData *smd,
Flow *f, uint8_t flags, void *alstate, void *txv, uint64_t tx_id);
static void DetectHttpRequestLineSetupCallback(Signature *s);
static int g_http_request_line_buffer_id = 0;
/**
@ -94,9 +93,6 @@ void DetectHttpRequestLineRegister(void)
DetectBufferTypeSetDescriptionByName("http_request_line",
"http request line");
DetectBufferTypeRegisterSetupCallback("http_request_line",
DetectHttpRequestLineSetupCallback);
g_http_request_line_buffer_id = DetectBufferTypeGetByName("http_request_line");
}
@ -120,12 +116,6 @@ static int DetectHttpRequestLineSetup(DetectEngineCtx *de_ctx, Signature *s, con
return 0;
}
static void DetectHttpRequestLineSetupCallback(Signature *s)
{
SCLogDebug("callback invoked by %u", s->id);
s->mask |= SIG_MASK_REQUIRE_HTTP_STATE;
}
/** \brief HTTP request line Mpm prefilter callback
*
* \param det_ctx detection engine thread ctx

@ -67,7 +67,6 @@ static int DetectEngineInspectHttpResponseLine(ThreadVars *tv,
DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx,
const Signature *s, const SigMatchData *smd,
Flow *f, uint8_t flags, void *alstate, void *txv, uint64_t tx_id);
static void DetectHttpResponseLineSetupCallback(Signature *s);
static int g_http_response_line_id = 0;
/**
@ -94,9 +93,6 @@ void DetectHttpResponseLineRegister(void)
DetectBufferTypeSetDescriptionByName("http_response_line",
"http response line");
DetectBufferTypeRegisterSetupCallback("http_response_line",
DetectHttpResponseLineSetupCallback);
g_http_response_line_id = DetectBufferTypeGetByName("http_response_line");
}
@ -120,12 +116,6 @@ static int DetectHttpResponseLineSetup(DetectEngineCtx *de_ctx, Signature *s, co
return 0;
}
static void DetectHttpResponseLineSetupCallback(Signature *s)
{
SCLogDebug("callback invoked by %u", s->id);
s->mask |= SIG_MASK_REQUIRE_HTTP_STATE;
}
/** \brief HTTP response line Mpm prefilter callback
*
* \param det_ctx detection engine thread ctx

@ -289,12 +289,6 @@ static int DetectHttpStartSetup(DetectEngineCtx *de_ctx, Signature *s, const cha
return 0;
}
static void DetectHttpStartSetupCallback(Signature *s)
{
SCLogDebug("callback invoked by %u", s->id);
s->mask |= SIG_MASK_REQUIRE_HTTP_STATE;
}
/**
* \brief Registers the keyword handlers for the "http_header" keyword.
*/
@ -322,9 +316,6 @@ void DetectHttpStartRegister(void)
DetectBufferTypeSetDescriptionByName(BUFFER_NAME,
BUFFER_DESC);
DetectBufferTypeRegisterSetupCallback(BUFFER_NAME,
DetectHttpStartSetupCallback);
g_buffer_id = DetectBufferTypeGetByName(BUFFER_NAME);
g_keyword_thread_id = DetectRegisterThreadCtxGlobalFuncs(KEYWORD_NAME,

@ -65,7 +65,6 @@
static int DetectHttpStatCodeSetup(DetectEngineCtx *, Signature *, const char *);
static void DetectHttpStatCodeRegisterTests(void);
static void DetectHttpStatCodeSetupCallback(Signature *);
static int g_http_stat_code_buffer_id = 0;
/**
@ -93,9 +92,6 @@ void DetectHttpStatCodeRegister (void)
DetectBufferTypeSetDescriptionByName("http_stat_code",
"http response status code");
DetectBufferTypeRegisterSetupCallback("http_stat_code",
DetectHttpStatCodeSetupCallback);
g_http_stat_code_buffer_id = DetectBufferTypeGetByName("http_stat_code");
}
@ -118,12 +114,6 @@ static int DetectHttpStatCodeSetup(DetectEngineCtx *de_ctx, Signature *s, const
ALPROTO_HTTP);
}
static void DetectHttpStatCodeSetupCallback(Signature *s)
{
SCLogDebug("callback invoked by %u", s->id);
s->mask |= SIG_MASK_REQUIRE_HTTP_STATE;
}
#ifdef UNITTESTS
/**

@ -65,7 +65,6 @@
static int DetectHttpStatMsgSetup(DetectEngineCtx *, Signature *, const char *);
static void DetectHttpStatMsgRegisterTests(void);
static void DetectHttpStatMsgSetupCallback(Signature *s);
static int g_http_stat_msg_buffer_id = 0;
/**
@ -93,9 +92,6 @@ void DetectHttpStatMsgRegister (void)
DetectBufferTypeSetDescriptionByName("http_stat_msg",
"http response status message");
DetectBufferTypeRegisterSetupCallback("http_stat_msg",
DetectHttpStatMsgSetupCallback);
g_http_stat_msg_buffer_id = DetectBufferTypeGetByName("http_stat_msg");
}
@ -118,12 +114,6 @@ static int DetectHttpStatMsgSetup(DetectEngineCtx *de_ctx, Signature *s, const c
ALPROTO_HTTP);
}
static void DetectHttpStatMsgSetupCallback(Signature *s)
{
SCLogDebug("callback invoked by %u", s->id);
s->mask |= SIG_MASK_REQUIRE_HTTP_STATE;
}
#ifdef UNITTESTS
/**

@ -62,7 +62,6 @@
static int DetectHttpUASetup(DetectEngineCtx *, Signature *, const char *);
static void DetectHttpUARegisterTests(void);
static void DetectHttpUAFree(void *);
static void DetectHttpUASetupCallback(Signature *);
static int g_http_ua_buffer_id = 0;
/**
@ -90,9 +89,6 @@ void DetectHttpUARegister(void)
DetectBufferTypeSetDescriptionByName("http_user_agent",
"http user agent");
DetectBufferTypeRegisterSetupCallback("http_user_agent",
DetectHttpUASetupCallback);
g_http_ua_buffer_id = DetectBufferTypeGetByName("http_user_agent");
}
@ -117,12 +113,6 @@ int DetectHttpUASetup(DetectEngineCtx *de_ctx, Signature *s, const char *arg)
ALPROTO_HTTP);
}
static void DetectHttpUASetupCallback(Signature *s)
{
SCLogDebug("callback invoked by %u", s->id);
s->mask |= SIG_MASK_REQUIRE_HTTP_STATE;
}
/**
* \brief The function to free the http_user_agent data.
*

@ -125,7 +125,6 @@ static bool DetectHttpUriValidateCallback(const Signature *s, const char **siger
static void DetectHttpUriSetupCallback(Signature *s)
{
SCLogDebug("callback invoked by %u", s->id);
s->mask |= SIG_MASK_REQUIRE_HTTP_STATE;
DetectUrilenApplyToContent(s, g_http_uri_buffer_id);
}

@ -176,12 +176,6 @@ static int DetectSshProtocolSetup(DetectEngineCtx *de_ctx, Signature *s, const c
return 0;
}
static void DetectSshProtocolSetupCallback(Signature *s)
{
SCLogDebug("callback invoked by %u", s->id);
s->mask |= SIG_MASK_REQUIRE_SSH_STATE;
}
void DetectSshProtocolRegister(void)
{
sigmatch_table[DETECT_AL_SSH_PROTOCOL].name = KEYWORD_NAME;
@ -205,8 +199,5 @@ void DetectSshProtocolRegister(void)
DetectBufferTypeSetDescriptionByName(BUFFER_NAME,
BUFFER_DESC);
DetectBufferTypeRegisterSetupCallback(BUFFER_NAME,
DetectSshProtocolSetupCallback);
g_buffer_id = DetectBufferTypeGetByName(BUFFER_NAME);
}

@ -176,12 +176,6 @@ static int DetectSshSoftwareSetup(DetectEngineCtx *de_ctx, Signature *s, const c
return 0;
}
static void DetectSshSoftwareSetupCallback(Signature *s)
{
SCLogDebug("callback invoked by %u", s->id);
s->mask |= SIG_MASK_REQUIRE_SSH_STATE;
}
void DetectSshSoftwareRegister(void)
{
sigmatch_table[DETECT_AL_SSH_SOFTWARE].name = KEYWORD_NAME;
@ -205,8 +199,5 @@ void DetectSshSoftwareRegister(void)
DetectBufferTypeSetDescriptionByName(BUFFER_NAME,
BUFFER_DESC);
DetectBufferTypeRegisterSetupCallback(BUFFER_NAME,
DetectSshSoftwareSetupCallback);
g_buffer_id = DetectBufferTypeGetByName(BUFFER_NAME);
}

File diff suppressed because it is too large Load Diff

@ -260,21 +260,11 @@ typedef struct DetectPort_ {
#define SIG_MASK_REQUIRE_FLAGS_INITDEINIT (1<<2) /* SYN, FIN, RST */
#define SIG_MASK_REQUIRE_FLAGS_UNUSUAL (1<<3) /* URG, ECN, CWR */
#define SIG_MASK_REQUIRE_NO_PAYLOAD (1<<4)
#define SIG_MASK_REQUIRE_HTTP_STATE (1<<5)
#define SIG_MASK_REQUIRE_DCE_STATE (1<<6)
//
#define SIG_MASK_REQUIRE_ENGINE_EVENT (1<<7)
#define SIG_MASK_REQUIRE_SSH_STATE (1<<8)
#define SIG_MASK_REQUIRE_TLS_STATE (1<<9)
#define SIG_MASK_REQUIRE_DNS_STATE (1<<10)
#define SIG_MASK_REQUIRE_FTP_STATE (1<<11)
#define SIG_MASK_REQUIRE_FTPDATA_STATE (1<<12)
#define SIG_MASK_REQUIRE_SMTP_STATE (1<<13)
#define SIG_MASK_REQUIRE_TEMPLATE_STATE (1<<14)
#define SIG_MASK_REQUIRE_ENIP_STATE (1<<15)
#define SIG_MASK_REQUIRE_DNP3_STATE (1<<16)
/* for now a uint8_t is enough */
#define SignatureMask uint32_t
#define SignatureMask uint8_t
#define DETECT_ENGINE_THREAD_CTX_STREAM_CONTENT_MATCH 0x0004
@ -342,7 +332,8 @@ typedef struct DetectEngineAppInspectionEngine_ {
uint8_t dir;
uint8_t id; /**< per sig id used in state keeping */
uint16_t mpm:1;
uint16_t sm_list:15;
uint16_t stream:1;
uint16_t sm_list:14;
int16_t progress;
/* \retval 0 No match. Don't discontinue matching yet. We need more data.
@ -809,8 +800,24 @@ typedef struct FiledataReassembledBody_ {
typedef struct SignatureNonPrefilterStore_ {
SigIntId id;
SignatureMask mask;
uint8_t alproto;
} SignatureNonPrefilterStore;
/** array of TX inspect rule candidates */
typedef struct RuleMatchCandidateTx {
SigIntId id; /**< internal signature id */
uint32_t *flags; /**< inspect flags ptr */
union {
struct {
bool stream_stored;
uint8_t stream_result;
};
uint32_t stream_reset;
};
const Signature *s; /**< ptr to sig */
} RuleMatchCandidateTx;
/**
* Detection engine thread data.
*/
@ -883,8 +890,6 @@ typedef struct DetectEngineThreadCtx_ {
/** ID of the transaction currently being inspected. */
uint64_t tx_id;
Packet *p;
bool stream_already_inspected;
int stream_last_result;
SC_ATOMIC_DECLARE(int, so_far_used_by_detect);
@ -900,11 +905,8 @@ typedef struct DetectEngineThreadCtx_ {
/** size in use */
SigIntId match_array_cnt;
/** Array of sigs that had a state change */
SigIntId de_state_sig_array_len;
uint8_t *de_state_sig_array;
const struct SigGroupHead_ *sgh;
RuleMatchCandidateTx *tx_candidates;
uint32_t tx_candidates_size;
SignatureNonPrefilterStore *non_pf_store_ptr;
uint32_t non_pf_store_cnt;
@ -1245,11 +1247,11 @@ Signature *DetectGetTagSignature(void);
int DetectRegisterThreadCtxFuncs(DetectEngineCtx *, const char *name, void *(*InitFunc)(void *), void *data, void (*FreeFunc)(void *), int);
void *DetectThreadCtxGetKeywordThreadCtx(DetectEngineThreadCtx *, int);
int SigMatchSignaturesRunPostMatch(ThreadVars *tv,
DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, Packet *p,
const Signature *s);
void DetectSignatureApplyActions(Packet *p, const Signature *s, const uint8_t);
void RuleMatchCandidateTxArrayInit(DetectEngineThreadCtx *det_ctx, uint32_t size);
void RuleMatchCandidateTxArrayFree(DetectEngineThreadCtx *det_ctx);
void DetectFlowbitsAnalyze(DetectEngineCtx *de_ctx);
#include "detect-engine-build.h"

Loading…
Cancel
Save