Change stateful detection engine to be able to start the stateful detection separate from other sigs. Fixes bugs #213, #214, #215.

remotes/origin/master-1.0.x
Victor Julien 15 years ago
parent 05ae4f99d8
commit 0d008c8135

@ -44,13 +44,16 @@
#include "util-unittest.h" #include "util-unittest.h"
#include "util-profiling.h" #include "util-profiling.h"
/** convert enum to string */
#define CASE_CODE(E) case E: return #E #define CASE_CODE(E) case E: return #E
/** \brief get string for match enum */
const char *DeStateMatchResultToString(DeStateMatchResult res) const char *DeStateMatchResultToString(DeStateMatchResult res)
{ {
switch (res) { switch (res) {
CASE_CODE (DE_STATE_MATCH_NOSTATE);
CASE_CODE (DE_STATE_MATCH_FULL); CASE_CODE (DE_STATE_MATCH_FULL);
CASE_CODE (DE_STATE_MATCH_PARTIAL); CASE_CODE (DE_STATE_MATCH_PARTIAL);
CASE_CODE (DE_STATE_MATCH_STORED);
CASE_CODE (DE_STATE_MATCH_NEW); CASE_CODE (DE_STATE_MATCH_NEW);
} }
@ -439,6 +442,12 @@ int DeStateDetectContinueDetection(ThreadVars *tv, DetectEngineCtx *de_ctx, Dete
PROFILING_START; PROFILING_START;
/* if we already fully matched previously, detect that here */
if (item->flags & DE_STATE_FLAG_FULL_MATCH) {
det_ctx->de_state_sig_array[item->sid] = DE_STATE_MATCH_FULL;
goto next_sig;
}
/* let's continue detection */ /* let's continue detection */
/* first, check uricontent */ /* first, check uricontent */
@ -513,6 +522,7 @@ int DeStateDetectContinueDetection(ThreadVars *tv, DetectEngineCtx *de_ctx, Dete
if (!appinspect || (appinspect == appmatch)) { if (!appinspect || (appinspect == appmatch)) {
det_ctx->de_state_sig_array[item->sid] = DE_STATE_MATCH_NEW; det_ctx->de_state_sig_array[item->sid] = DE_STATE_MATCH_NEW;
SCLogDebug("state set to %s", DeStateMatchResultToString(DE_STATE_MATCH_NEW)); SCLogDebug("state set to %s", DeStateMatchResultToString(DE_STATE_MATCH_NEW));
item->flags |= DE_STATE_FLAG_FULL_MATCH;
} else { } else {
det_ctx->de_state_sig_array[item->sid] = DE_STATE_MATCH_PARTIAL; det_ctx->de_state_sig_array[item->sid] = DE_STATE_MATCH_PARTIAL;
SCLogDebug("state set to %s", DeStateMatchResultToString(DE_STATE_MATCH_PARTIAL)); SCLogDebug("state set to %s", DeStateMatchResultToString(DE_STATE_MATCH_PARTIAL));
@ -523,15 +533,20 @@ int DeStateDetectContinueDetection(ThreadVars *tv, DetectEngineCtx *de_ctx, Dete
if (appinspect > 0 && (appinspect == appmatch)) { if (appinspect > 0 && (appinspect == appmatch)) {
det_ctx->de_state_sig_array[item->sid] = DE_STATE_MATCH_NEW; det_ctx->de_state_sig_array[item->sid] = DE_STATE_MATCH_NEW;
SCLogDebug("state set to %s", DeStateMatchResultToString(DE_STATE_MATCH_NEW)); SCLogDebug("state set to %s", DeStateMatchResultToString(DE_STATE_MATCH_NEW));
item->flags |= DE_STATE_FLAG_FULL_MATCH;
} else if (uinspect && !umatch) { } else if (uinspect && !umatch) {
det_ctx->de_state_sig_array[item->sid] = DE_STATE_MATCH_PARTIAL; det_ctx->de_state_sig_array[item->sid] = DE_STATE_MATCH_PARTIAL;
SCLogDebug("state set to %s", DeStateMatchResultToString(DE_STATE_MATCH_PARTIAL)); SCLogDebug("state set to %s", DeStateMatchResultToString(DE_STATE_MATCH_PARTIAL));
} else {
det_ctx->de_state_sig_array[item->sid] = DE_STATE_MATCH_PARTIAL;
SCLogDebug("state set to %s", DeStateMatchResultToString(DE_STATE_MATCH_PARTIAL));
} }
} }
SCLogDebug("signature %"PRIu32" match state %s", SCLogDebug("signature %"PRIu32" match state %s",
s->id, DeStateMatchResultToString(det_ctx->de_state_sig_array[item->sid])); s->id, DeStateMatchResultToString(det_ctx->de_state_sig_array[item->sid]));
next_sig:
RULE_PROFILING_END(s, match); RULE_PROFILING_END(s, match);
} }

@ -47,12 +47,14 @@
#define DE_STATE_FLAG_PAYLOAD_MATCH 0x01 /**< payload part of the sig matched */ #define DE_STATE_FLAG_PAYLOAD_MATCH 0x01 /**< payload part of the sig matched */
#define DE_STATE_FLAG_URI_MATCH 0x02 /**< uri part of the sig matched */ #define DE_STATE_FLAG_URI_MATCH 0x02 /**< uri part of the sig matched */
#define DE_STATE_FLAG_DCE_MATCH 0x04 /**< dce payload inspection part matched */ #define DE_STATE_FLAG_DCE_MATCH 0x04 /**< dce payload inspection part matched */
#define DE_STATE_FLAG_FULL_MATCH 0x08 /**< sig already fully matched */
/** per signature detection engine state */
typedef enum { typedef enum {
DE_STATE_MATCH_FULL = 0, /**< sig already fully matched, no state */ DE_STATE_MATCH_NOSTATE = 0, /**< no state for this sig*/
DE_STATE_MATCH_FULL, /**< sig already fully matched */
DE_STATE_MATCH_PARTIAL, /**< partial state match */ DE_STATE_MATCH_PARTIAL, /**< partial state match */
DE_STATE_MATCH_STORED, /**< stored match in the state */ DE_STATE_MATCH_NEW, /**< new (full) match this run */
DE_STATE_MATCH_NEW, /**< new match */
} DeStateMatchResult; } DeStateMatchResult;
/** \brief State storage for a single signature */ /** \brief State storage for a single signature */

@ -421,7 +421,6 @@ int SigLoadSignatures (DetectEngineCtx *de_ctx, char *sig_file)
* *
* \param de_ctx detection engine ctx * \param de_ctx detection engine ctx
* \param det_ctx detection engine thread ctx -- array is stored here * \param det_ctx detection engine thread ctx -- array is stored here
* \param de_state_start flag to indicate if we're at the start of a stateful run
* \param p packet * \param p packet
* \param alproto application layer protocol * \param alproto application layer protocol
* *
@ -432,8 +431,7 @@ int SigLoadSignatures (DetectEngineCtx *de_ctx, char *sig_file)
* 4. num * 4. num
*/ */
static void SigMatchSignaturesBuildMatchArray(DetectEngineCtx *de_ctx, static void SigMatchSignaturesBuildMatchArray(DetectEngineCtx *de_ctx,
DetectEngineThreadCtx *det_ctx, char de_state_start, Packet *p, DetectEngineThreadCtx *det_ctx, Packet *p, uint16_t alproto)
uint16_t alproto)
{ {
uint32_t i; uint32_t i;
@ -498,11 +496,15 @@ static void SigMatchSignaturesBuildMatchArray(DetectEngineCtx *de_ctx,
if (s->flags & SIG_FLAG_AMATCH || s->flags & SIG_FLAG_UMATCH || if (s->flags & SIG_FLAG_AMATCH || s->flags & SIG_FLAG_UMATCH ||
s->flags & SIG_FLAG_DMATCH) s->flags & SIG_FLAG_DMATCH)
{ {
if (de_state_start == FALSE) { /* we run after DeStateDetectContinueDetection, so we might have
if (det_ctx->de_state_sig_array[s->num] != DE_STATE_MATCH_NEW) { * state NEW here. In that case we'd want to continue detection
SCLogDebug("not a new match, ignoring"); * for this sig. If we have NOSTATE, stateful detection didn't
continue; * start yet for this sig, so we will inspect it.
} */
if (det_ctx->de_state_sig_array[s->num] != DE_STATE_MATCH_NEW &&
det_ctx->de_state_sig_array[s->num] != DE_STATE_MATCH_NOSTATE) {
SCLogDebug("de state not NEW or NOSTATE, ignoring");
continue;
} }
} }
@ -817,22 +819,18 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh
det_ctx->de_mpm_scanned_uri = FALSE; det_ctx->de_mpm_scanned_uri = FALSE;
/* stateful app layer detection */ /* stateful app layer detection */
char de_state_start = FALSE;
/* initialize to 0 (DE_STATE_MATCH_FULL) */ /* initialize to 0 (DE_STATE_MATCH_NOSTATE) */
memset(det_ctx->de_state_sig_array, 0x00, det_ctx->de_state_sig_array_len); memset(det_ctx->de_state_sig_array, 0x00, det_ctx->de_state_sig_array_len);
if (alstate != NULL) {
if (DeStateFlowHasState(p->flow)) { /* if applicable, continue stateful detection */
DeStateDetectContinueDetection(th_v, de_ctx, det_ctx, p->flow, if (p->flow != NULL && DeStateFlowHasState(p->flow)) {
flags, alstate, alproto); DeStateDetectContinueDetection(th_v, de_ctx, det_ctx, p->flow,
} else { flags, alstate, alproto);
de_state_start = TRUE;
}
} else {
de_state_start = TRUE;
} }
/* build the match array */ /* build the match array */
SigMatchSignaturesBuildMatchArray(de_ctx, det_ctx, de_state_start, p, alproto); SigMatchSignaturesBuildMatchArray(de_ctx, det_ctx, p, alproto);
/* inspect the sigs against the packet */ /* inspect the sigs against the packet */
for (idx = 0; idx < det_ctx->match_array_cnt; idx++) { for (idx = 0; idx < det_ctx->match_array_cnt; idx++) {
@ -944,18 +942,18 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh
goto next; goto next;
} }
if (de_state_start == TRUE) { if (det_ctx->de_state_sig_array[s->num] == DE_STATE_MATCH_NOSTATE) {
SCLogDebug("stateful app layer match inspection starting"); SCLogDebug("stateful app layer match inspection starting");
if (DeStateDetectStartDetection(th_v, de_ctx, det_ctx, s, if (DeStateDetectStartDetection(th_v, de_ctx, det_ctx, s,
p->flow, flags, alstate, alproto) != 1) p->flow, flags, alstate, alproto) != 1)
goto next; goto next;
} else { } else {
SCLogDebug("already having a destate");
SCLogDebug("signature %"PRIu32" (%"PRIuMAX"): %s", SCLogDebug("signature %"PRIu32" (%"PRIuMAX"): %s",
s->id, (uintmax_t)s->num, DeStateMatchResultToString(det_ctx->de_state_sig_array[s->num])); s->id, (uintmax_t)s->num, DeStateMatchResultToString(det_ctx->de_state_sig_array[s->num]));
if (det_ctx->de_state_sig_array[s->num] != DE_STATE_MATCH_NEW) { if (det_ctx->de_state_sig_array[s->num] != DE_STATE_MATCH_NEW) {
if (s->pmatch == NULL && s->dmatch == NULL) { goto next;
goto next;
}
} }
} }
} }

Loading…
Cancel
Save