From eec22ce19b597d56efea8470a2c665374f14794d Mon Sep 17 00:00:00 2001 From: Victor Julien Date: Thu, 26 Feb 2015 17:23:49 +0100 Subject: [PATCH] detect-state: rip per sig detect out of ContinueDetect --- src/detect-engine-state.c | 424 ++++++++++++++++++++------------------ 1 file changed, 218 insertions(+), 206 deletions(-) diff --git a/src/detect-engine-state.c b/src/detect-engine-state.c index c6c5b08326..3ac87b4308 100644 --- a/src/detect-engine-state.c +++ b/src/detect-engine-state.c @@ -466,33 +466,226 @@ int DeStateDetectStartDetection(ThreadVars *tv, DetectEngineCtx *de_ctx, 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]; @@ -500,7 +693,7 @@ void DeStateDetectContinueDetection(ThreadVars *tv, DetectEngineCtx *de_ctx, 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); @@ -509,7 +702,7 @@ void DeStateDetectContinueDetection(ThreadVars *tv, DetectEngineCtx *de_ctx, 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)) { @@ -520,203 +713,22 @@ void DeStateDetectContinueDetection(ThreadVars *tv, DetectEngineCtx *de_ctx, 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); } } -- 2.47.2