diff --git a/src/decode.h b/src/decode.h index ab8c782a88..bfd22e979c 100644 --- a/src/decode.h +++ b/src/decode.h @@ -248,6 +248,7 @@ typedef struct PacketAlert_ { uint8_t action; /* Internal num, used for sorting */ uint8_t flags; struct Signature_ *s; + uint64_t tx_id; } PacketAlert; /** After processing an alert by the thresholding module, if at @@ -258,6 +259,8 @@ typedef struct PacketAlert_ { #define PACKET_ALERT_FLAG_STATE_MATCH 0x02 /** alert was generated based on stream */ #define PACKET_ALERT_FLAG_STREAM_MATCH 0x04 +/** alert is in a tx, tx_id set */ +#define PACKET_ALERT_FLAG_TX 0x08 #define PACKET_ALERT_MAX 15 diff --git a/src/detect-engine-alert.c b/src/detect-engine-alert.c index e22bb2d292..3d111fd7db 100644 --- a/src/detect-engine-alert.c +++ b/src/detect-engine-alert.c @@ -175,7 +175,7 @@ int PacketAlertRemove(Packet *p, uint16_t pos) * \param flags alert flags * \param alert_msg ptr to StreamMsg object that the signature matched on */ -int PacketAlertAppend(DetectEngineThreadCtx *det_ctx, Signature *s, Packet *p, uint8_t flags) +int PacketAlertAppend(DetectEngineThreadCtx *det_ctx, Signature *s, Packet *p, uint64_t tx_id, uint8_t flags) { int i = 0; @@ -192,6 +192,7 @@ int PacketAlertAppend(DetectEngineThreadCtx *det_ctx, Signature *s, Packet *p, u p->alerts.alerts[p->alerts.cnt].action = s->action; p->alerts.alerts[p->alerts.cnt].flags = flags; p->alerts.alerts[p->alerts.cnt].s = s; + p->alerts.alerts[p->alerts.cnt].tx_id = tx_id; } else { /* We need to make room for this s->num (a bit ugly with memcpy but we are planning changes here)*/ @@ -205,6 +206,7 @@ int PacketAlertAppend(DetectEngineThreadCtx *det_ctx, Signature *s, Packet *p, u p->alerts.alerts[i].action = s->action; p->alerts.alerts[i].flags = flags; p->alerts.alerts[i].s = s; + p->alerts.alerts[i].tx_id = tx_id; } /* Update the count */ diff --git a/src/detect-engine-alert.h b/src/detect-engine-alert.h index 8bff764dd4..6f200b268d 100644 --- a/src/detect-engine-alert.h +++ b/src/detect-engine-alert.h @@ -29,7 +29,7 @@ #include "detect.h" void PacketAlertFinalize(DetectEngineCtx *, DetectEngineThreadCtx *, Packet *); -int PacketAlertAppend(DetectEngineThreadCtx *, Signature *, Packet *, uint8_t); +int PacketAlertAppend(DetectEngineThreadCtx *, Signature *, Packet *, uint64_t tx_id, uint8_t); int PacketAlertCheck(Packet *, uint32_t); int PacketAlertRemove(Packet *, uint16_t); void PacketAlertTagInit(void); diff --git a/src/detect-engine-iponly.c b/src/detect-engine-iponly.c index d22d339f37..0dc648d8c4 100644 --- a/src/detect-engine-iponly.c +++ b/src/detect-engine-iponly.c @@ -1084,9 +1084,9 @@ void IPOnlyMatchPacket(ThreadVars *tv, } if (!(s->flags & SIG_FLAG_NOALERT)) { if (s->action & ACTION_DROP) - PacketAlertAppend(det_ctx, s, p, PACKET_ALERT_FLAG_DROP_FLOW); + PacketAlertAppend(det_ctx, s, p, 0, PACKET_ALERT_FLAG_DROP_FLOW); else - PacketAlertAppend(det_ctx, s, p, 0); + PacketAlertAppend(det_ctx, s, p, 0, 0); } else { /* apply actions for noalert/rule suppressed as well */ PACKET_UPDATE_ACTION(p, s->action); diff --git a/src/detect-engine-state.c b/src/detect-engine-state.c index b10af8049d..90ce81e5d3 100644 --- a/src/detect-engine-state.c +++ b/src/detect-engine-state.c @@ -236,7 +236,7 @@ int DeStateFlowHasInspectableState(Flow *f, uint16_t alproto, uint16_t alversion int DeStateDetectStartDetection(ThreadVars *tv, DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, - Signature *s, Flow *f, uint8_t flags, + Signature *s, Packet *p, Flow *f, uint8_t flags, void *alstate, uint16_t alproto, uint16_t alversion) { DetectEngineAppInspectionEngine *engine = NULL; @@ -310,8 +310,17 @@ int DeStateDetectStartDetection(ThreadVars *tv, DetectEngineCtx *de_ctx, /* all the engines seem to be exhausted at this point. If we * didn't have a match in one of the engines we would have * broken off and engine wouldn't be NULL. Hence the alert. */ - if (engine == NULL && total_matches > 0) - alert_cnt++; + if (engine == NULL && total_matches > 0) { + + if (!(s->flags & SIG_FLAG_NOALERT)) { + PacketAlertAppend(det_ctx, s, p, tx_id, + PACKET_ALERT_FLAG_STATE_MATCH|PACKET_ALERT_FLAG_TX); + } else { + PACKET_UPDATE_ACTION(p, s->action); + } + + alert_cnt = 1; + } if (tx_id == (total_txs - 1)) { void *tx = AppLayerGetTx(alproto, alstate, tx_id); @@ -337,12 +346,27 @@ int DeStateDetectStartDetection(ThreadVars *tv, DetectEngineCtx *de_ctx, if (smb_state->dcerpc_present && DetectEngineInspectDcePayload(de_ctx, det_ctx, s, f, flags, &smb_state->dcerpc) == 1) { - alert_cnt++; + if (!(s->flags & SIG_FLAG_NOALERT)) { + PacketAlertAppend(det_ctx, s, p, 0, + PACKET_ALERT_FLAG_STATE_MATCH); + } else { + PACKET_UPDATE_ACTION(p, s->action); + } + + alert_cnt = 1; } } else { if (DetectEngineInspectDcePayload(de_ctx, det_ctx, s, f, flags, alstate) == 1) { - alert_cnt++; + alert_cnt = 1; + + if (!(s->flags & SIG_FLAG_NOALERT)) { + PacketAlertAppend(det_ctx, s, p, 0, + PACKET_ALERT_FLAG_STATE_MATCH); + } else { + PACKET_UPDATE_ACTION(p, s->action); + } + } } } @@ -373,8 +397,15 @@ int DeStateDetectStartDetection(ThreadVars *tv, DetectEngineCtx *de_ctx, if (s->sm_lists[DETECT_SM_LIST_AMATCH] != NULL) { store_de_state = 1; if (sm == NULL || inspect_flags & DE_STATE_FLAG_SIG_CANT_MATCH) { - if (match == 1) + if (match == 1) { + if (!(s->flags & SIG_FLAG_NOALERT)) { + PacketAlertAppend(det_ctx, s, p, 0, + PACKET_ALERT_FLAG_STATE_MATCH); + } else { + PACKET_UPDATE_ACTION(p, s->action); + } alert_cnt = 1; + } inspect_flags |= DE_STATE_FLAG_FULL_INSPECT; } } @@ -405,7 +436,7 @@ int DeStateDetectStartDetection(ThreadVars *tv, DetectEngineCtx *de_ctx, SCMutexUnlock(&f->de_state_m); end: - return alert_cnt; + return alert_cnt ? 1:0; } void DeStateDetectContinueDetection(ThreadVars *tv, DetectEngineCtx *de_ctx, @@ -621,7 +652,12 @@ void DeStateDetectContinueDetection(ThreadVars *tv, DetectEngineCtx *de_ctx, SigMatchSignaturesRunPostMatch(tv, de_ctx, det_ctx, p, s); if (!(s->flags & SIG_FLAG_NOALERT)) { - PacketAlertAppend(det_ctx, s, p, 0); + if (alproto_supports_txs) + PacketAlertAppend(det_ctx, s, p, inspect_tx_id, + PACKET_ALERT_FLAG_STATE_MATCH|PACKET_ALERT_FLAG_TX); + else + PacketAlertAppend(det_ctx, s, p, 0, + PACKET_ALERT_FLAG_STATE_MATCH); } else { PACKET_UPDATE_ACTION(p, s->action); } diff --git a/src/detect-engine-state.h b/src/detect-engine-state.h index 72d934317a..7606278f9d 100644 --- a/src/detect-engine-state.h +++ b/src/detect-engine-state.h @@ -170,7 +170,7 @@ int DeStateFlowHasInspectableState(Flow *f, uint16_t alproto, uint16_t alversion */ int DeStateDetectStartDetection(ThreadVars *tv, DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, - Signature *s, Flow *f, uint8_t flags, + Signature *s, Packet *p, Flow *f, uint8_t flags, void *alstate, uint16_t alproto, uint16_t alversion); diff --git a/src/detect.c b/src/detect.c index d84d485676..79b60365e3 100644 --- a/src/detect.c +++ b/src/detect.c @@ -1103,8 +1103,8 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh SigMatch *sm = NULL; uint16_t alversion = 0; int reset_de_state = 0; + int state_alert = 0; int alerts = 0; - int i; int app_decoder_events = 0; SCEnter(); @@ -1305,7 +1305,7 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh /* inspect the sigs against the packet */ for (idx = 0; idx < det_ctx->match_array_cnt; idx++) { RULE_PROFILING_START; - alerts = 0; + state_alert = 0; #ifdef PROFILING smatch = 0; #endif @@ -1492,11 +1492,16 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh } SCLogDebug("stateful app layer match inspection starting"); + + /* if DeStateDetectStartDetection matches, it's a full + * signature match. It will then call PacketAlertAppend + * itself, so we can skip it below. This is done so it + * can store the tx_id with the alert */ PACKET_PROFILING_DETECT_START(p, PROF_DETECT_STATEFUL); - alerts = DeStateDetectStartDetection(th_v, de_ctx, det_ctx, s, - p->flow, flags, alstate, alproto, alversion); + state_alert = DeStateDetectStartDetection(th_v, de_ctx, det_ctx, s, + p, p->flow, flags, alstate, alproto, alversion); PACKET_PROFILING_DETECT_END(p, PROF_DETECT_STATEFUL); - if (alerts == 0) + if (state_alert == 0) goto next; /* match */ @@ -1506,11 +1511,6 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh alert_flags |= PACKET_ALERT_FLAG_STATE_MATCH; } - /* If we have reached this stage and we don't have any alerts, it - * indicates that we didn't have a stateful sig, hence we set alerts - * to 1. But if we have an alert set, then the sig is definitely a - * stateful sig and we need to retain the no of alerts */ - alerts = (alerts == 0) ? 1 : alerts; #ifdef PROFILING smatch = 1; #endif @@ -1518,12 +1518,14 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh SigMatchSignaturesRunPostMatch(th_v, de_ctx, det_ctx, p, s); if (!(s->flags & SIG_FLAG_NOALERT)) { - for (i = 0; i < alerts; i++) - PacketAlertAppend(det_ctx, s, p, alert_flags); + /* stateful sigs call PacketAlertAppend from DeStateDetectStartDetection */ + if (!state_alert) + PacketAlertAppend(det_ctx, s, p, 0, alert_flags); } else { /* apply actions even if not alerting */ PACKET_UPDATE_ACTION(p, s->action); } + alerts++; next: DetectFlowvarProcessList(det_ctx, p->flow); DetectReplaceFree(det_ctx->replist);