diff --git a/src/detect-engine-state.c b/src/detect-engine-state.c index 574828768b..a7adac2190 100644 --- a/src/detect-engine-state.c +++ b/src/detect-engine-state.c @@ -44,13 +44,16 @@ #include "util-unittest.h" #include "util-profiling.h" +/** convert enum to string */ #define CASE_CODE(E) case E: return #E + +/** \brief get string for match enum */ const char *DeStateMatchResultToString(DeStateMatchResult res) { switch (res) { + CASE_CODE (DE_STATE_MATCH_NOSTATE); CASE_CODE (DE_STATE_MATCH_FULL); CASE_CODE (DE_STATE_MATCH_PARTIAL); - CASE_CODE (DE_STATE_MATCH_STORED); CASE_CODE (DE_STATE_MATCH_NEW); } @@ -439,6 +442,12 @@ int DeStateDetectContinueDetection(ThreadVars *tv, DetectEngineCtx *de_ctx, Dete 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 */ /* first, check uricontent */ @@ -513,6 +522,7 @@ int DeStateDetectContinueDetection(ThreadVars *tv, DetectEngineCtx *de_ctx, Dete if (!appinspect || (appinspect == appmatch)) { det_ctx->de_state_sig_array[item->sid] = DE_STATE_MATCH_NEW; SCLogDebug("state set to %s", DeStateMatchResultToString(DE_STATE_MATCH_NEW)); + item->flags |= DE_STATE_FLAG_FULL_MATCH; } else { det_ctx->de_state_sig_array[item->sid] = 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)) { det_ctx->de_state_sig_array[item->sid] = 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) { det_ctx->de_state_sig_array[item->sid] = 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", s->id, DeStateMatchResultToString(det_ctx->de_state_sig_array[item->sid])); +next_sig: RULE_PROFILING_END(s, match); } diff --git a/src/detect-engine-state.h b/src/detect-engine-state.h index 1fa6843e54..63f813e119 100644 --- a/src/detect-engine-state.h +++ b/src/detect-engine-state.h @@ -47,12 +47,14 @@ #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_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 { - 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_STORED, /**< stored match in the state */ - DE_STATE_MATCH_NEW, /**< new match */ + DE_STATE_MATCH_NEW, /**< new (full) match this run */ } DeStateMatchResult; /** \brief State storage for a single signature */ diff --git a/src/detect.c b/src/detect.c index 426b2e6a7a..76a1fd373e 100644 --- a/src/detect.c +++ b/src/detect.c @@ -421,7 +421,6 @@ int SigLoadSignatures (DetectEngineCtx *de_ctx, char *sig_file) * * \param de_ctx detection engine ctx * \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 alproto application layer protocol * @@ -432,8 +431,7 @@ int SigLoadSignatures (DetectEngineCtx *de_ctx, char *sig_file) * 4. num */ static void SigMatchSignaturesBuildMatchArray(DetectEngineCtx *de_ctx, - DetectEngineThreadCtx *det_ctx, char de_state_start, Packet *p, - uint16_t alproto) + DetectEngineThreadCtx *det_ctx, Packet *p, uint16_t alproto) { uint32_t i; @@ -498,11 +496,15 @@ static void SigMatchSignaturesBuildMatchArray(DetectEngineCtx *de_ctx, if (s->flags & SIG_FLAG_AMATCH || s->flags & SIG_FLAG_UMATCH || s->flags & SIG_FLAG_DMATCH) { - if (de_state_start == FALSE) { - if (det_ctx->de_state_sig_array[s->num] != DE_STATE_MATCH_NEW) { - SCLogDebug("not a new match, ignoring"); - continue; - } + /* we run after DeStateDetectContinueDetection, so we might have + * state NEW here. In that case we'd want to continue detection + * for this sig. If we have NOSTATE, stateful detection didn't + * 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; /* 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); - if (alstate != NULL) { - if (DeStateFlowHasState(p->flow)) { - DeStateDetectContinueDetection(th_v, de_ctx, det_ctx, p->flow, - flags, alstate, alproto); - } else { - de_state_start = TRUE; - } - } else { - de_state_start = TRUE; + + /* if applicable, continue stateful detection */ + if (p->flow != NULL && DeStateFlowHasState(p->flow)) { + DeStateDetectContinueDetection(th_v, de_ctx, det_ctx, p->flow, + flags, alstate, alproto); } /* 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 */ 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; } - 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"); if (DeStateDetectStartDetection(th_v, de_ctx, det_ctx, s, p->flow, flags, alstate, alproto) != 1) goto next; } else { + SCLogDebug("already having a destate"); + SCLogDebug("signature %"PRIu32" (%"PRIuMAX"): %s", 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 (s->pmatch == NULL && s->dmatch == NULL) { - goto next; - } + goto next; } } }