return alert_cnt ? 1:0;
}
+static int DoInspectItem(ThreadVars *tv,
+ DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx,
+ const int alproto_supports_txs,
+ DeStateStoreItem *item, const uint8_t dir_state_flags,
+ Packet *p, Flow *f, AppProto alproto, uint8_t flags,
+ const uint64_t inspect_tx_id, const uint64_t total_txs,
+
+ uint16_t *file_no_match)
+{
+ Signature *s = de_ctx->sig_array[item->sid];
+
+ /* check if a sig in state 'full inspect' needs to be reconsidered
+ * as the result of a new file in the existing tx */
+ if (item->flags & DE_STATE_FLAG_FULL_INSPECT) {
+ if (item->flags & (DE_STATE_FLAG_FILE_TC_INSPECT|DE_STATE_FLAG_FILE_TS_INSPECT)) {
+ if ((flags & STREAM_TOCLIENT) &&
+ (dir_state_flags & DETECT_ENGINE_STATE_FLAG_FILE_TC_NEW))
+ {
+ item->flags &= ~DE_STATE_FLAG_FILE_TC_INSPECT;
+ item->flags &= ~DE_STATE_FLAG_FULL_INSPECT;
+ }
+
+ if ((flags & STREAM_TOSERVER) &&
+ (dir_state_flags & DETECT_ENGINE_STATE_FLAG_FILE_TS_NEW))
+ {
+ item->flags &= ~DE_STATE_FLAG_FILE_TS_INSPECT;
+ item->flags &= ~DE_STATE_FLAG_FULL_INSPECT;
+ }
+ }
+
+ if (item->flags & DE_STATE_FLAG_FULL_INSPECT) {
+ if (alproto_supports_txs) {
+ if (TxIsLast(inspect_tx_id, total_txs)) {
+ det_ctx->de_state_sig_array[item->sid] = DE_STATE_MATCH_NO_NEW_STATE;
+ }
+ } else {
+ det_ctx->de_state_sig_array[item->sid] = DE_STATE_MATCH_NO_NEW_STATE;
+ }
+ return 0;
+ }
+ }
+
+ /* check if a sig in state 'cant match' needs to be reconsidered
+ * as the result of a new file in the existing tx */
+ if (item->flags & DE_STATE_FLAG_SIG_CANT_MATCH) {
+ if ((flags & STREAM_TOSERVER) &&
+ (item->flags & DE_STATE_FLAG_FILE_TS_INSPECT) &&
+ (dir_state_flags & DETECT_ENGINE_STATE_FLAG_FILE_TS_NEW))
+ {
+ item->flags &= ~DE_STATE_FLAG_FILE_TS_INSPECT;
+ item->flags &= ~DE_STATE_FLAG_SIG_CANT_MATCH;
+ } else if ((flags & STREAM_TOCLIENT) &&
+ (item->flags & DE_STATE_FLAG_FILE_TC_INSPECT) &&
+ (dir_state_flags & DETECT_ENGINE_STATE_FLAG_FILE_TC_NEW))
+ {
+ item->flags &= ~DE_STATE_FLAG_FILE_TC_INSPECT;
+ item->flags &= ~DE_STATE_FLAG_SIG_CANT_MATCH;
+ } else {
+ if (alproto_supports_txs) {
+ if (TxIsLast(inspect_tx_id, total_txs)) {
+ det_ctx->de_state_sig_array[item->sid] = DE_STATE_MATCH_NO_NEW_STATE;
+ }
+ } else {
+ det_ctx->de_state_sig_array[item->sid] = DE_STATE_MATCH_NO_NEW_STATE;
+ }
+ return 0;
+ }
+ }
+
+ uint8_t alert = 0;
+ uint32_t inspect_flags = 0;
+ int total_matches = 0;
+
+ RULE_PROFILING_START(p);
+
+ if (alproto_supports_txs) {
+ FLOWLOCK_WRLOCK(f);
+ void *alstate = FlowGetAppState(f);
+ if (!StateIsValid(alproto, alstate)) {
+ FLOWLOCK_UNLOCK(f);
+ RULE_PROFILING_END(det_ctx, s, 0, p);
+ return -1;
+ }
+
+ det_ctx->tx_id = inspect_tx_id;
+ det_ctx->tx_id_set = 1;
+ DetectEngineAppInspectionEngine *engine = app_inspection_engine[FlowGetProtoMapping(f->proto)][alproto][(flags & STREAM_TOSERVER) ? 0 : 1];
+ void *inspect_tx = AppLayerParserGetTx(f->proto, alproto, alstate, inspect_tx_id);
+ if (inspect_tx == NULL) {
+ FLOWLOCK_UNLOCK(f);
+ RULE_PROFILING_END(det_ctx, s, 0, p);
+ return -1;
+ }
+
+ while (engine != NULL) {
+ if (!(item->flags & engine->inspect_flags) &&
+ s->sm_lists[engine->sm_list] != NULL)
+ {
+ KEYWORD_PROFILING_SET_LIST(det_ctx, engine->sm_list);
+ int match = engine->Callback(tv, de_ctx, det_ctx, s, f,
+ flags, alstate, inspect_tx, inspect_tx_id);
+ if (match == DETECT_ENGINE_INSPECT_SIG_MATCH) {
+ inspect_flags |= engine->inspect_flags;
+ engine = engine->next;
+ total_matches++;
+ continue;
+ } else if (match == DETECT_ENGINE_INSPECT_SIG_CANT_MATCH) {
+ inspect_flags |= DE_STATE_FLAG_SIG_CANT_MATCH;
+ inspect_flags |= engine->inspect_flags;
+ } else if (match == DETECT_ENGINE_INSPECT_SIG_CANT_MATCH_FILESTORE) {
+ inspect_flags |= DE_STATE_FLAG_SIG_CANT_MATCH;
+ inspect_flags |= engine->inspect_flags;
+ (*file_no_match)++;
+ }
+ break;
+ }
+ engine = engine->next;
+ }
+ if (total_matches > 0 && (engine == NULL || inspect_flags & DE_STATE_FLAG_SIG_CANT_MATCH)) {
+ if (engine == NULL)
+ alert = 1;
+ inspect_flags |= DE_STATE_FLAG_FULL_INSPECT;
+ }
+
+ FLOWLOCK_UNLOCK(f);
+ }
+
+ /* count AMATCH matches */
+ total_matches = 0;
+ SigMatch *sm = NULL;
+
+ KEYWORD_PROFILING_SET_LIST(det_ctx, DETECT_SM_LIST_AMATCH);
+ if (item->nm != NULL) {
+ /* RDLOCK would be nicer, but at least tlsstore needs
+ * write lock currently. */
+ FLOWLOCK_WRLOCK(f);
+ void *alstate = FlowGetAppState(f);
+ if (alstate == NULL) {
+ FLOWLOCK_UNLOCK(f);
+ RULE_PROFILING_END(det_ctx, s, 0 /* no match */, p);
+ return -1;
+ }
+
+ for (sm = item->nm; sm != NULL; sm = sm->next) {
+ if (sigmatch_table[sm->type].AppLayerMatch != NULL)
+ {
+ int match = 0;
+ if (alproto == ALPROTO_SMB || alproto == ALPROTO_SMB2) {
+ SMBState *smb_state = (SMBState *)alstate;
+ if (smb_state->dcerpc_present) {
+ KEYWORD_PROFILING_START;
+ match = sigmatch_table[sm->type].
+ AppLayerMatch(tv, det_ctx, f, flags, &smb_state->dcerpc, s, sm);
+ KEYWORD_PROFILING_END(det_ctx, sm->type, (match > 0));
+ }
+ } else {
+ KEYWORD_PROFILING_START;
+ match = sigmatch_table[sm->type].
+ AppLayerMatch(tv, det_ctx, f, flags, alstate, s, sm);
+ KEYWORD_PROFILING_END(det_ctx, sm->type, (match > 0));
+ }
+
+ if (match == 0)
+ break;
+ else if (match == 2)
+ inspect_flags |= DE_STATE_FLAG_SIG_CANT_MATCH;
+ else if (match == 1)
+ total_matches++;
+ }
+ }
+ FLOWLOCK_UNLOCK(f);
+ }
+
+ if (s->sm_lists[DETECT_SM_LIST_AMATCH] != NULL) {
+ if (total_matches > 0 && (sm == NULL || inspect_flags & DE_STATE_FLAG_SIG_CANT_MATCH)) {
+ if (sm == NULL)
+ alert = 1;
+ inspect_flags |= DE_STATE_FLAG_FULL_INSPECT;
+ }
+ det_ctx->de_state_sig_array[item->sid] = DE_STATE_MATCH_NO_NEW_STATE;
+ }
+ RULE_PROFILING_END(det_ctx, s, (alert == 1), p);
+
+ item->flags |= inspect_flags;
+ item->nm = sm;
+ if (TxIsLast(inspect_tx_id, total_txs)) {
+ det_ctx->de_state_sig_array[item->sid] = DE_STATE_MATCH_NO_NEW_STATE;
+ }
+
+ if (alert) {
+ SigMatchSignaturesRunPostMatch(tv, de_ctx, det_ctx, p, s);
+
+ if (!(s->flags & SIG_FLAG_NOALERT)) {
+ 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 {
+ DetectSignatureApplyActions(p, s);
+ }
+ }
+
+ DetectFlowvarProcessList(det_ctx, f);
+ return 1;
+}
+
void DeStateDetectContinueDetection(ThreadVars *tv, DetectEngineCtx *de_ctx,
DetectEngineThreadCtx *det_ctx,
Packet *p, Flow *f, uint8_t flags,
AppProto alproto, uint16_t alversion)
{
- DetectEngineAppInspectionEngine *engine = NULL;
- SigMatch *sm = NULL;
uint16_t file_no_match = 0;
- uint32_t inspect_flags = 0;
-
- void *alstate = NULL;
- SMBState *smb_state = NULL;
-
SigIntId store_cnt = 0;
SigIntId state_cnt = 0;
- int match = 0;
- uint8_t alert = 0;
-
- void *inspect_tx = NULL;
uint64_t inspect_tx_id = 0;
uint64_t total_txs = 0;
uint8_t alproto_supports_txs = 0;
uint8_t reset_de_state = 0;
- /* this was introduced later to allow protocols that had both app
- * keywords with transaction keywords. Without this we would
- * assume that we have an alert if engine == NULL */
- uint8_t total_matches = 0;
SCMutexLock(&f->de_state_m);
DetectEngineStateDirection *dir_state = &f->de_state->dir_state[flags & STREAM_TOSERVER ? 0 : 1];
if (AppLayerParserProtocolSupportsTxs(f->proto, alproto)) {
FLOWLOCK_RDLOCK(f);
- alstate = FlowGetAppState(f);
+ void *alstate = FlowGetAppState(f);
if (!StateIsValid(alproto, alstate)) {
FLOWLOCK_UNLOCK(f);
SCMutexUnlock(&f->de_state_m);
inspect_tx_id = AppLayerParserGetTransactionInspectId(f->alparser, flags);
total_txs = AppLayerParserGetTxCnt(f->proto, alproto, alstate);
- inspect_tx = AppLayerParserGetTx(f->proto, alproto, alstate, inspect_tx_id);
+ void *inspect_tx = AppLayerParserGetTx(f->proto, alproto, alstate, inspect_tx_id);
if (inspect_tx != NULL) {
if (AppLayerParserGetStateProgress(f->proto, alproto, inspect_tx, flags) >=
AppLayerParserGetStateProgressCompletionStatus(f->proto, alproto, flags)) {
alproto_supports_txs = 1;
}
+ /* Loop through stored 'items' (stateful rules) and inspect them */
for (; store != NULL; store = store->next) {
for (store_cnt = 0;
store_cnt < DE_STATE_CHUNK_SIZE && state_cnt < dir_state->cnt;
store_cnt++, state_cnt++)
{
- total_matches = 0;
DeStateStoreItem *item = &store->store[store_cnt];
- Signature *s = de_ctx->sig_array[item->sid];
-
- if (item->flags & DE_STATE_FLAG_FULL_INSPECT) {
- if (item->flags & (DE_STATE_FLAG_FILE_TC_INSPECT |
- DE_STATE_FLAG_FILE_TS_INSPECT)) {
- if ((flags & STREAM_TOCLIENT) &&
- (dir_state->flags & DETECT_ENGINE_STATE_FLAG_FILE_TC_NEW))
- {
- item->flags &= ~DE_STATE_FLAG_FILE_TC_INSPECT;
- item->flags &= ~DE_STATE_FLAG_FULL_INSPECT;
- }
-
- if ((flags & STREAM_TOSERVER) &&
- (dir_state->flags & DETECT_ENGINE_STATE_FLAG_FILE_TS_NEW))
- {
- item->flags &= ~DE_STATE_FLAG_FILE_TS_INSPECT;
- item->flags &= ~DE_STATE_FLAG_FULL_INSPECT;
- }
- }
-
- if (item->flags & DE_STATE_FLAG_FULL_INSPECT) {
- if (alproto_supports_txs) {
- if (TxIsLast(inspect_tx_id, total_txs)) {
- det_ctx->de_state_sig_array[item->sid] = DE_STATE_MATCH_NO_NEW_STATE;
- }
- } else {
- det_ctx->de_state_sig_array[item->sid] = DE_STATE_MATCH_NO_NEW_STATE;
- }
- continue;
- }
- }
-
- if (item->flags & DE_STATE_FLAG_SIG_CANT_MATCH) {
- if ((flags & STREAM_TOSERVER) &&
- (item->flags & DE_STATE_FLAG_FILE_TS_INSPECT) &&
- (dir_state->flags & DETECT_ENGINE_STATE_FLAG_FILE_TS_NEW))
- {
- item->flags &= ~DE_STATE_FLAG_FILE_TS_INSPECT;
- item->flags &= ~DE_STATE_FLAG_SIG_CANT_MATCH;
- } else if ((flags & STREAM_TOCLIENT) &&
- (item->flags & DE_STATE_FLAG_FILE_TC_INSPECT) &&
- (dir_state->flags & DETECT_ENGINE_STATE_FLAG_FILE_TC_NEW))
- {
- item->flags &= ~DE_STATE_FLAG_FILE_TC_INSPECT;
- item->flags &= ~DE_STATE_FLAG_SIG_CANT_MATCH;
- } else {
- if (alproto_supports_txs) {
- if (TxIsLast(inspect_tx_id, total_txs)) {
- det_ctx->de_state_sig_array[item->sid] = DE_STATE_MATCH_NO_NEW_STATE;
- }
- } else {
- det_ctx->de_state_sig_array[item->sid] = DE_STATE_MATCH_NO_NEW_STATE;
- }
- continue;
- }
- }
-
- alert = 0;
- inspect_flags = 0;
- match = 0;
-
- RULE_PROFILING_START(p);
-
- if (alproto_supports_txs) {
- FLOWLOCK_WRLOCK(f);
- alstate = FlowGetAppState(f);
- if (!StateIsValid(alproto, alstate)) {
- FLOWLOCK_UNLOCK(f);
- RULE_PROFILING_END(det_ctx, s, match, p);
- goto end;
- }
-
- det_ctx->tx_id = inspect_tx_id;
- det_ctx->tx_id_set = 1;
- engine = app_inspection_engine[FlowGetProtoMapping(f->proto)][alproto][(flags & STREAM_TOSERVER) ? 0 : 1];
- inspect_tx = AppLayerParserGetTx(f->proto, alproto, alstate, inspect_tx_id);
- if (inspect_tx == NULL) {
- FLOWLOCK_UNLOCK(f);
- RULE_PROFILING_END(det_ctx, s, match, p);
- goto end;
- }
- while (engine != NULL) {
- if (!(item->flags & engine->inspect_flags) &&
- s->sm_lists[engine->sm_list] != NULL)
- {
- KEYWORD_PROFILING_SET_LIST(det_ctx, engine->sm_list);
- match = engine->Callback(tv, de_ctx, det_ctx, s, f,
- flags, alstate, inspect_tx, inspect_tx_id);
- if (match == DETECT_ENGINE_INSPECT_SIG_MATCH) {
- inspect_flags |= engine->inspect_flags;
- engine = engine->next;
- total_matches++;
- continue;
- } else if (match == DETECT_ENGINE_INSPECT_SIG_CANT_MATCH) {
- inspect_flags |= DE_STATE_FLAG_SIG_CANT_MATCH;
- inspect_flags |= engine->inspect_flags;
- } else if (match == DETECT_ENGINE_INSPECT_SIG_CANT_MATCH_FILESTORE) {
- inspect_flags |= DE_STATE_FLAG_SIG_CANT_MATCH;
- inspect_flags |= engine->inspect_flags;
- file_no_match++;
- }
- break;
- }
- engine = engine->next;
- }
- if (total_matches > 0 && (engine == NULL || inspect_flags & DE_STATE_FLAG_SIG_CANT_MATCH)) {
- if (engine == NULL)
- alert = 1;
- inspect_flags |= DE_STATE_FLAG_FULL_INSPECT;
- }
-
- FLOWLOCK_UNLOCK(f);
- }
-
- /* count AMATCH matches */
- total_matches = 0;
-
- KEYWORD_PROFILING_SET_LIST(det_ctx, DETECT_SM_LIST_AMATCH);
- if (item->nm != NULL) {
- /* RDLOCK would be nicer, but at least tlsstore needs
- * write lock currently. */
- FLOWLOCK_WRLOCK(f);
- alstate = FlowGetAppState(f);
- if (alstate == NULL) {
- FLOWLOCK_UNLOCK(f);
- RULE_PROFILING_END(det_ctx, s, 0 /* no match */, p);
- goto end;
- }
-
- for (sm = item->nm; sm != NULL; sm = sm->next) {
- if (sigmatch_table[sm->type].AppLayerMatch != NULL)
- {
- if (alproto == ALPROTO_SMB || alproto == ALPROTO_SMB2) {
- smb_state = (SMBState *)alstate;
- if (smb_state->dcerpc_present) {
- KEYWORD_PROFILING_START;
- match = sigmatch_table[sm->type].
- AppLayerMatch(tv, det_ctx, f, flags, &smb_state->dcerpc, s, sm);
- KEYWORD_PROFILING_END(det_ctx, sm->type, (match > 0));
- }
- } else {
- KEYWORD_PROFILING_START;
- match = sigmatch_table[sm->type].
- AppLayerMatch(tv, det_ctx, f, flags, alstate, s, sm);
- KEYWORD_PROFILING_END(det_ctx, sm->type, (match > 0));
- }
-
- if (match == 0)
- break;
- else if (match == 2)
- inspect_flags |= DE_STATE_FLAG_SIG_CANT_MATCH;
- else if (match == 1)
- total_matches++;
- }
- }
- FLOWLOCK_UNLOCK(f);
- }
- RULE_PROFILING_END(det_ctx, s, match, p);
-
- if (s->sm_lists[DETECT_SM_LIST_AMATCH] != NULL) {
- if (total_matches > 0 && (sm == NULL || inspect_flags & DE_STATE_FLAG_SIG_CANT_MATCH)) {
- if (sm == NULL)
- alert = 1;
- inspect_flags |= DE_STATE_FLAG_FULL_INSPECT;
- }
- det_ctx->de_state_sig_array[item->sid] = DE_STATE_MATCH_NO_NEW_STATE;
- }
-
- item->flags |= inspect_flags;
- item->nm = sm;
- if (TxIsLast(inspect_tx_id, total_txs)) {
- det_ctx->de_state_sig_array[item->sid] = DE_STATE_MATCH_NO_NEW_STATE;
- }
-
- if (alert) {
- SigMatchSignaturesRunPostMatch(tv, de_ctx, det_ctx, p, s);
- if (!(s->flags & SIG_FLAG_NOALERT)) {
- 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 {
- DetectSignatureApplyActions(p, s);
- }
+ int r = DoInspectItem(tv, de_ctx, det_ctx, alproto_supports_txs,
+ item, dir_state->flags,
+ p, f, alproto, flags,
+ inspect_tx_id, total_txs,
+ &file_no_match);
+ if (r < 0) {
+ goto end;
}
-
- DetectFlowvarProcessList(det_ctx, f);
}
}