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-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);
}

@ -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 */

@ -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;
}
}
}

Loading…
Cancel
Save