From 19d701ddf07d855128ded0cf2b573ce468e3bdd6 Mon Sep 17 00:00:00 2001 From: Ashlee Young Date: Wed, 20 Jan 2016 01:10:01 +0000 Subject: Removing Suricata and Audit from source repo, and updated build.sh to avoid building suricata. Will re-address this in C release via tar balls. Change-Id: I3710076f8b7f3313cb3cb5260c4eb0a6834d4f6e Signed-off-by: Ashlee Young --- framework/src/suricata/src/detect-engine-state.c | 2346 ---------------------- 1 file changed, 2346 deletions(-) delete mode 100644 framework/src/suricata/src/detect-engine-state.c (limited to 'framework/src/suricata/src/detect-engine-state.c') diff --git a/framework/src/suricata/src/detect-engine-state.c b/framework/src/suricata/src/detect-engine-state.c deleted file mode 100644 index 05ca25d5..00000000 --- a/framework/src/suricata/src/detect-engine-state.c +++ /dev/null @@ -1,2346 +0,0 @@ -/* Copyright (C) 2007-2013 Open Information Security Foundation - * - * You can copy, redistribute or modify this Program under the terms of - * the GNU General Public License version 2 as published by the Free - * Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -/** - * \defgroup sigstate State support - * - * It is possible to do matching on reconstructed applicative flow. - * This is done by this code. It uses the ::Flow structure to store - * the list of signatures to match on the reconstructed stream. - * - * The Flow::de_state is a ::DetectEngineState structure. This is - * basically a containter for storage item of type ::DeStateStore. - * They contains an array of ::DeStateStoreItem which store the - * state of match for an individual signature identified by - * DeStateStoreItem::sid. - * - * The state is constructed by DeStateDetectStartDetection() which - * also starts the matching. Work is continued by - * DeStateDetectContinueDetection(). - * - * Once a transaction has been analysed DeStateRestartDetection() - * is used to reset the structures. - * - * @{ - */ - -/** - * \file - * - * \author Victor Julien - * \author Anoop Saldanha - * - * \brief State based signature handling. - */ - -#include "suricata-common.h" - -#include "decode.h" - -#include "detect.h" -#include "detect-engine.h" -#include "detect-parse.h" -#include "detect-engine-state.h" -#include "detect-engine-dcepayload.h" - -#include "detect-flowvar.h" - -#include "stream-tcp.h" -#include "stream-tcp-private.h" -#include "stream-tcp-reassemble.h" - -#include "app-layer.h" -#include "app-layer-parser.h" -#include "app-layer-protos.h" -#include "app-layer-htp.h" -#include "app-layer-smb.h" -#include "app-layer-dcerpc-common.h" -#include "app-layer-dcerpc.h" -#include "app-layer-dns-common.h" - -#include "util-unittest.h" -#include "util-unittest-helper.h" -#include "util-profiling.h" - -#include "flow-util.h" - -/** convert enum to string */ -#define CASE_CODE(E) case E: return #E - -/** The DetectEngineThreadCtx::de_state_sig_array contains 2 separate values: - * 1. the first bit tells the prefilter engine to bypass the rule (or not) - * 2. the other bits allow 'ContinueDetect' to specify an offset again the - * base tx id. This offset will then be used by 'StartDetect' to not - * inspect transactions again for the same signature. - * - * The offset in (2) has a max value due to the limited data type. If it is - * set to max the code will fall back to a slower path that validates that - * we're not adding duplicate rules to the detection state. - */ -#define MAX_STORED_TXID_OFFSET 127 - -/******** static internal helpers *********/ - -static inline int StateIsValid(uint16_t alproto, void *alstate) -{ - if (alstate != NULL) { - if (alproto == ALPROTO_HTTP) { - HtpState *htp_state = (HtpState *)alstate; - if (htp_state->conn != NULL) { - return 1; - } - } else { - return 1; - } - } - return 0; -} - -static inline int TxIsLast(uint64_t tx_id, uint64_t total_txs) -{ - if (total_txs - tx_id <= 1) - return 1; - return 0; -} - -static DeStateStore *DeStateStoreAlloc(void) -{ - DeStateStore *d = SCMalloc(sizeof(DeStateStore)); - if (unlikely(d == NULL)) - return NULL; - memset(d, 0, sizeof(DeStateStore)); - - return d; -} -static DeStateStoreFlowRules *DeStateStoreFlowRulesAlloc(void) -{ - DeStateStoreFlowRules *d = SCMalloc(sizeof(DeStateStoreFlowRules)); - if (unlikely(d == NULL)) - return NULL; - memset(d, 0, sizeof(DeStateStoreFlowRules)); - - return d; -} - -static int DeStateSearchState(DetectEngineState *state, uint8_t direction, SigIntId num) -{ - DetectEngineStateDirection *dir_state = &state->dir_state[direction & STREAM_TOSERVER ? 0 : 1]; - DeStateStore *tx_store = dir_state->head; - SigIntId store_cnt; - SigIntId state_cnt = 0; - - for (; tx_store != NULL; tx_store = tx_store->next) { - SCLogDebug("tx_store %p", tx_store); - for (store_cnt = 0; - store_cnt < DE_STATE_CHUNK_SIZE && state_cnt < dir_state->cnt; - store_cnt++, state_cnt++) - { - DeStateStoreItem *item = &tx_store->store[store_cnt]; - if (item->sid == num) { - SCLogDebug("sid %u already in state: %p %p %p %u %u, direction %s", - num, state, dir_state, tx_store, state_cnt, - store_cnt, direction & STREAM_TOSERVER ? "toserver" : "toclient"); - return 1; - } - } - } - return 0; -} - -static void DeStateSignatureAppend(DetectEngineState *state, Signature *s, uint32_t inspect_flags, uint8_t direction) -{ - int jump = 0; - int i = 0; - DetectEngineStateDirection *dir_state = &state->dir_state[direction & STREAM_TOSERVER ? 0 : 1]; - -#ifdef DEBUG_VALIDATION - BUG_ON(DeStateSearchState(state, direction, s->num)); -#endif - DeStateStore *store = dir_state->head; - - if (store == NULL) { - store = DeStateStoreAlloc(); - if (store != NULL) { - dir_state->head = store; - dir_state->tail = store; - } - } else { - jump = dir_state->cnt / DE_STATE_CHUNK_SIZE; - for (i = 0; i < jump; i++) { - store = store->next; - } - if (store == NULL) { - store = DeStateStoreAlloc(); - if (store != NULL) { - dir_state->tail->next = store; - dir_state->tail = store; - } - } - } - - if (store == NULL) - return; - - SigIntId idx = dir_state->cnt++ % DE_STATE_CHUNK_SIZE; - store->store[idx].sid = s->num; - store->store[idx].flags = inspect_flags; - - return; -} - -static void DeStateFlowRuleAppend(DetectEngineStateFlow *state, Signature *s, - SigMatch *sm, uint32_t inspect_flags, - uint8_t direction) -{ - int jump = 0; - int i = 0; - DetectEngineStateDirectionFlow *dir_state = &state->dir_state[direction & STREAM_TOSERVER ? 0 : 1]; - DeStateStoreFlowRules *store = dir_state->head; - - if (store == NULL) { - store = DeStateStoreFlowRulesAlloc(); - if (store != NULL) { - dir_state->head = store; - dir_state->tail = store; - } - } else { - jump = dir_state->cnt / DE_STATE_CHUNK_SIZE; - for (i = 0; i < jump; i++) { - store = store->next; - } - if (store == NULL) { - store = DeStateStoreFlowRulesAlloc(); - if (store != NULL) { - dir_state->tail->next = store; - dir_state->tail = store; - } - } - } - - if (store == NULL) - return; - - SigIntId idx = dir_state->cnt++ % DE_STATE_CHUNK_SIZE; - store->store[idx].sid = s->num; - store->store[idx].flags = inspect_flags; - store->store[idx].nm = sm; - - return; -} - -static void DeStateStoreStateVersion(Flow *f, - const uint8_t alversion, uint8_t direction) -{ - f->detect_alversion[direction & STREAM_TOSERVER ? 0 : 1] = alversion; -} - -static void DeStateStoreFileNoMatchCnt(DetectEngineState *de_state, uint16_t file_no_match, uint8_t direction) -{ - de_state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].filestore_cnt += file_no_match; - - return; -} - -static int DeStateStoreFilestoreSigsCantMatch(SigGroupHead *sgh, DetectEngineState *de_state, uint8_t direction) -{ - if (de_state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].filestore_cnt == sgh->filestore_cnt) - return 1; - else - return 0; -} - -DetectEngineState *DetectEngineStateAlloc(void) -{ - DetectEngineState *d = SCMalloc(sizeof(DetectEngineState)); - if (unlikely(d == NULL)) - return NULL; - memset(d, 0, sizeof(DetectEngineState)); - - return d; -} - -DetectEngineStateFlow *DetectEngineStateFlowAlloc(void) -{ - DetectEngineStateFlow *d = SCMalloc(sizeof(DetectEngineStateFlow)); - if (unlikely(d == NULL)) - return NULL; - memset(d, 0, sizeof(DetectEngineStateFlow)); - - return d; -} - -void DetectEngineStateFree(DetectEngineState *state) -{ - DeStateStore *store; - DeStateStore *store_next; - int i = 0; - - for (i = 0; i < 2; i++) { - store = state->dir_state[i].head; - while (store != NULL) { - store_next = store->next; - SCFree(store); - store = store_next; - } - } - SCFree(state); - - return; -} - -void DetectEngineStateFlowFree(DetectEngineStateFlow *state) -{ - DeStateStoreFlowRules *store; - DeStateStoreFlowRules *store_next; - int i = 0; - - for (i = 0; i < 2; i++) { - store = state->dir_state[i].head; - while (store != NULL) { - store_next = store->next; - SCFree(store); - store = store_next; - } - } - SCFree(state); - - return; -} - -static int HasStoredSigs(Flow *f, uint8_t flags) -{ - if (f->de_state != NULL && f->de_state->dir_state[flags & STREAM_TOSERVER ? 0 : 1].cnt != 0) { - SCLogDebug("global sigs present"); - return 1; - } - - if (AppLayerParserProtocolSupportsTxs(f->proto, f->alproto)) { - AppProto alproto = f->alproto; - void *alstate = FlowGetAppState(f); - if (!StateIsValid(f->alproto, alstate)) { - return 0; - } - - int state = AppLayerParserHasTxDetectState(f->proto, alproto, f->alstate); - if (state == -ENOSYS) { /* proto doesn't support this API call */ - /* fall through */ - } else if (state == 0) { - return 0; - } - /* if state == 1 we also fall through */ - - uint64_t inspect_tx_id = AppLayerParserGetTransactionInspectId(f->alparser, flags); - uint64_t total_txs = AppLayerParserGetTxCnt(f->proto, alproto, alstate); - - for ( ; inspect_tx_id < total_txs; inspect_tx_id++) { - void *inspect_tx = AppLayerParserGetTx(f->proto, alproto, alstate, inspect_tx_id); - if (inspect_tx != NULL) { - DetectEngineState *tx_de_state = AppLayerParserGetTxDetectState(f->proto, alproto, inspect_tx); - if (tx_de_state == NULL) { - continue; - } - if (tx_de_state->dir_state[flags & STREAM_TOSERVER ? 0 : 1].cnt != 0) { - SCLogDebug("tx %u has sigs present", (uint)inspect_tx_id); - return 1; - } - } - } - } - return 0; -} - -/** \brief Check if we need to inspect this state - * - * State needs to be inspected if: - * 1. state has been updated - * 2. we already have de_state in progress - * - * \retval 0 no inspectable state - * \retval 1 inspectable state - * \retval 2 inspectable state, but no update - */ -int DeStateFlowHasInspectableState(Flow *f, AppProto alproto, - const uint8_t alversion, uint8_t flags) -{ - int r = 0; - - FLOWLOCK_WRLOCK(f); - - if (!(flags & STREAM_EOF) && f->de_state && - f->detect_alversion[flags & STREAM_TOSERVER ? 0 : 1] == alversion) { - SCLogDebug("unchanged state"); - r = 2; - } else if (HasStoredSigs(f, flags)) { - r = 1; - } else { - r = 0; - } - FLOWLOCK_UNLOCK(f); - - return r; -} - -static int StoreState(DetectEngineThreadCtx *det_ctx, - Flow *f, const uint8_t flags, const uint8_t alversion, - Signature *s, SigMatch *sm, const uint32_t inspect_flags, - const uint16_t file_no_match) -{ - if (f->de_state == NULL) { - f->de_state = DetectEngineStateFlowAlloc(); - if (f->de_state == NULL) { - return 0; - } - } - - DeStateFlowRuleAppend(f->de_state, s, sm, inspect_flags, flags); - DeStateStoreStateVersion(f, alversion, flags); - return 1; -} - -static void StoreStateTxHandleFiles(DetectEngineThreadCtx *det_ctx, Flow *f, - DetectEngineState *destate, const uint8_t flags, - const uint64_t tx_id, const uint16_t file_no_match) -{ - DeStateStoreFileNoMatchCnt(destate, file_no_match, flags); - if (DeStateStoreFilestoreSigsCantMatch(det_ctx->sgh, destate, flags) == 1) { - FileDisableStoringForTransaction(f, flags & (STREAM_TOCLIENT | STREAM_TOSERVER), tx_id); - destate->dir_state[flags & STREAM_TOSERVER ? 0 : 1].flags |= DETECT_ENGINE_STATE_FLAG_FILE_STORE_DISABLED; - } -} - -static void StoreStateTxFileOnly(DetectEngineThreadCtx *det_ctx, - Flow *f, const uint8_t flags, const uint64_t tx_id, void *tx, - const uint16_t file_no_match) -{ - if (AppLayerParserSupportsTxDetectState(f->proto, f->alproto)) { - DetectEngineState *destate = AppLayerParserGetTxDetectState(f->proto, f->alproto, tx); - if (destate == NULL) { - destate = DetectEngineStateAlloc(); - if (destate == NULL) - return; - if (AppLayerParserSetTxDetectState(f->proto, f->alproto, f->alstate, tx, destate) < 0) { - DetectEngineStateFree(destate); - return; - } - SCLogDebug("destate created for %"PRIu64, tx_id); - } - StoreStateTxHandleFiles(det_ctx, f, destate, flags, tx_id, file_no_match); - } -} - -/** - * \param check_before_add check for duplicates before adding the sig - */ -static void StoreStateTx(DetectEngineThreadCtx *det_ctx, - Flow *f, const uint8_t flags, const uint8_t alversion, - const uint64_t tx_id, void *tx, - Signature *s, SigMatch *sm, - const uint32_t inspect_flags, const uint16_t file_no_match, int check_before_add) -{ - if (AppLayerParserSupportsTxDetectState(f->proto, f->alproto)) { - DetectEngineState *destate = AppLayerParserGetTxDetectState(f->proto, f->alproto, tx); - if (destate == NULL) { - destate = DetectEngineStateAlloc(); - if (destate == NULL) - return; - if (AppLayerParserSetTxDetectState(f->proto, f->alproto, f->alstate, tx, destate) < 0) { - DetectEngineStateFree(destate); - return; - } - SCLogDebug("destate created for %"PRIu64, tx_id); - } - - if (check_before_add == 0 || DeStateSearchState(destate, flags, s->num) == 0) - DeStateSignatureAppend(destate, s, inspect_flags, flags); - DeStateStoreStateVersion(f, alversion, flags); - - StoreStateTxHandleFiles(det_ctx, f, destate, flags, tx_id, file_no_match); - } - SCLogDebug("Stored for TX %"PRIu64, tx_id); -} - -int DeStateDetectStartDetection(ThreadVars *tv, DetectEngineCtx *de_ctx, - DetectEngineThreadCtx *det_ctx, - Signature *s, Packet *p, Flow *f, uint8_t flags, - AppProto alproto, const uint8_t alversion) -{ - SigMatch *sm = NULL; - uint16_t file_no_match = 0; - uint32_t inspect_flags = 0; - uint8_t direction = (flags & STREAM_TOSERVER) ? 0 : 1; - int alert_cnt = 0; - int check_before_add = 0; - - FLOWLOCK_WRLOCK(f); - /* TX based matches (inspect engines) */ - if (AppLayerParserProtocolSupportsTxs(f->proto, alproto)) { - uint64_t tx_id = 0; - uint64_t total_txs = 0; - - void *alstate = FlowGetAppState(f); - if (!StateIsValid(alproto, alstate)) { - goto end; - } - - /* if continue detection already inspected this rule for this tx, - * continue with the first not-inspected tx */ - uint8_t offset = det_ctx->de_state_sig_array[s->num] & 0xef; - tx_id = AppLayerParserGetTransactionInspectId(f->alparser, flags); - if (offset > 0) { - SCLogDebug("using stored_tx_id %u instead of %u", (uint)tx_id+offset, (uint)tx_id); - tx_id += offset; - } - if (offset == MAX_STORED_TXID_OFFSET) { - check_before_add = 1; - } - - total_txs = AppLayerParserGetTxCnt(f->proto, alproto, alstate); - SCLogDebug("total_txs %"PRIu64, total_txs); - - SCLogDebug("starting: start tx %u, packet %u", (uint)tx_id, (uint)p->pcap_cnt); - - for (; tx_id < total_txs; tx_id++) { - int total_matches = 0; - void *tx = AppLayerParserGetTx(f->proto, alproto, alstate, tx_id); - if (tx == NULL) - continue; - det_ctx->tx_id = tx_id; - det_ctx->tx_id_set = 1; - DetectEngineAppInspectionEngine *engine = app_inspection_engine[f->protomap][alproto][direction]; - inspect_flags = 0; - while (engine != NULL) { - if (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, - tx, 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; - } - /* 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) { - if (!(s->flags & SIG_FLAG_NOALERT)) { - PacketAlertAppend(det_ctx, s, p, tx_id, - PACKET_ALERT_FLAG_STATE_MATCH|PACKET_ALERT_FLAG_TX); - } else { - DetectSignatureApplyActions(p, s); - } - alert_cnt = 1; - SCLogDebug("MATCH: tx %u packet %u", (uint)tx_id, (uint)p->pcap_cnt); - } - - /* if this is the last tx in our list, and it's incomplete: then - * we store the state so that ContinueDetection knows about it */ - int tx_is_done = (AppLayerParserGetStateProgress(f->proto, alproto, tx, flags) >= - AppLayerParserGetStateProgressCompletionStatus(f->proto, alproto, flags)); - /* see if we need to consider the next tx in our decision to add - * a sig to the 'no inspect array'. */ - int next_tx_no_progress = 0; - if (!TxIsLast(tx_id, total_txs)) { - void *next_tx = AppLayerParserGetTx(f->proto, alproto, alstate, tx_id+1); - if (next_tx != NULL) { - int c = AppLayerParserGetStateProgress(f->proto, alproto, next_tx, flags); - if (c == 0) { - next_tx_no_progress = 1; - } - } - } - - SCLogDebug("tx %u, packet %u, rule %u, alert_cnt %u, last tx %d, tx_is_done %d, next_tx_no_progress %d", - (uint)tx_id, (uint)p->pcap_cnt, s->num, alert_cnt, - TxIsLast(tx_id, total_txs), tx_is_done, next_tx_no_progress); - - /* if we have something to store (partial match or file store info), - * then we do it now. */ - if (inspect_flags != 0) { - if (!(TxIsLast(tx_id, total_txs)) || !tx_is_done) { - if (engine == NULL || inspect_flags & DE_STATE_FLAG_SIG_CANT_MATCH) { - inspect_flags |= DE_STATE_FLAG_FULL_INSPECT; - } - - /* store */ - StoreStateTx(det_ctx, f, flags, alversion, tx_id, tx, - s, sm, inspect_flags, file_no_match, check_before_add); - } else { - StoreStateTxFileOnly(det_ctx, f, flags, tx_id, tx, file_no_match); - } - } else { - SCLogDebug("no state to store"); - } - if (next_tx_no_progress) - break; - } /* for */ - - /* DCERPC matches */ - } else if (s->sm_lists[DETECT_SM_LIST_DMATCH] != NULL && - (alproto == ALPROTO_DCERPC || alproto == ALPROTO_SMB || - alproto == ALPROTO_SMB2)) - { - void *alstate = FlowGetAppState(f); - if (alstate == NULL) { - goto end; - } - - KEYWORD_PROFILING_SET_LIST(det_ctx, DETECT_SM_LIST_DMATCH); - if (alproto == ALPROTO_SMB || alproto == ALPROTO_SMB2) { - SMBState *smb_state = (SMBState *)alstate; - if (smb_state->dcerpc_present && - DetectEngineInspectDcePayload(de_ctx, det_ctx, s, f, - flags, &smb_state->dcerpc) == 1) { - if (!(s->flags & SIG_FLAG_NOALERT)) { - PacketAlertAppend(det_ctx, s, p, 0, - PACKET_ALERT_FLAG_STATE_MATCH); - } else { - DetectSignatureApplyActions(p, s); - } - alert_cnt = 1; - } - } else { - if (DetectEngineInspectDcePayload(de_ctx, det_ctx, s, f, - flags, alstate) == 1) { - if (!(s->flags & SIG_FLAG_NOALERT)) { - PacketAlertAppend(det_ctx, s, p, 0, - PACKET_ALERT_FLAG_STATE_MATCH); - } else { - DetectSignatureApplyActions(p, s); - } - alert_cnt = 1; - } - } - } - - /* flow based matches */ - KEYWORD_PROFILING_SET_LIST(det_ctx, DETECT_SM_LIST_AMATCH); - sm = s->sm_lists[DETECT_SM_LIST_AMATCH]; - if (sm != NULL) { - void *alstate = FlowGetAppState(f); - if (alstate == NULL) { - goto end; - } - - int match = 0; - for ( ; sm != NULL; sm = sm->next) { - if (sigmatch_table[sm->type].AppLayerMatch != NULL) { - 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 == 1)); - } - } 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 == 1)); - } - - if (match == 0) - break; - if (match == 2) { - inspect_flags |= DE_STATE_FLAG_SIG_CANT_MATCH; - break; - } - } - } - - if (sm == NULL || inspect_flags & DE_STATE_FLAG_SIG_CANT_MATCH) { - if (match == 1) { - if (!(s->flags & SIG_FLAG_NOALERT)) { - PacketAlertAppend(det_ctx, s, p, 0, - PACKET_ALERT_FLAG_STATE_MATCH); - } else { - DetectSignatureApplyActions(p, s); - } - alert_cnt = 1; - } - inspect_flags |= DE_STATE_FLAG_FULL_INSPECT; - } - - StoreState(det_ctx, f, flags, alversion, - s, sm, inspect_flags, file_no_match); - } - - end: - FLOWLOCK_UNLOCK(f); - - det_ctx->tx_id = 0; - det_ctx->tx_id_set = 0; - return alert_cnt ? 1:0; -} - -static int DoInspectItem(ThreadVars *tv, - DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, - 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, int inprogress, // is current tx in progress? - const int next_tx_no_progress) // tx after current is still dormant -{ - 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 (TxIsLast(inspect_tx_id, total_txs) || inprogress || next_tx_no_progress) { - det_ctx->de_state_sig_array[item->sid] = DE_STATE_MATCH_NO_NEW_STATE; - SCLogDebug("skip and bypass: tx %u packet %u", (uint)inspect_tx_id, (uint)p->pcap_cnt); - } else { - SCLogDebug("just skip: tx %u packet %u", (uint)inspect_tx_id, (uint)p->pcap_cnt); - - /* make sure that if we reinspect this right now from - * start detection, we skip this tx we just matched on */ - uint64_t base_tx_id = AppLayerParserGetTransactionInspectId(f->alparser, flags); - uint64_t offset = (inspect_tx_id + 1) - base_tx_id; - if (offset > MAX_STORED_TXID_OFFSET) - offset = MAX_STORED_TXID_OFFSET; - det_ctx->de_state_sig_array[item->sid] = (uint8_t)offset; -#ifdef DEBUG_VALIDATION - BUG_ON(det_ctx->de_state_sig_array[item->sid] & DE_STATE_MATCH_NO_NEW_STATE); // check that we don't set the bit -#endif - SCLogDebug("storing tx_id %u for this sid", (uint)inspect_tx_id + 1); - } - 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 (TxIsLast(inspect_tx_id, total_txs) || inprogress || next_tx_no_progress) { - det_ctx->de_state_sig_array[item->sid] = DE_STATE_MATCH_NO_NEW_STATE; - SCLogDebug("skip and bypass: tx %u packet %u", (uint)inspect_tx_id, (uint)p->pcap_cnt); - } else { - SCLogDebug("just skip: tx %u packet %u", (uint)inspect_tx_id, (uint)p->pcap_cnt); - - /* make sure that if we reinspect this right now from - * start detection, we skip this tx we just matched on */ - uint64_t base_tx_id = AppLayerParserGetTransactionInspectId(f->alparser, flags); - uint64_t offset = (inspect_tx_id + 1) - base_tx_id; - if (offset > MAX_STORED_TXID_OFFSET) - offset = MAX_STORED_TXID_OFFSET; - det_ctx->de_state_sig_array[item->sid] = (uint8_t)offset; -#ifdef DEBUG_VALIDATION - BUG_ON(det_ctx->de_state_sig_array[item->sid] & DE_STATE_MATCH_NO_NEW_STATE); // check that we don't set the bit -#endif - SCLogDebug("storing tx_id %u for this sid", (uint)inspect_tx_id + 1); - } - return 0; - } - } - - uint8_t alert = 0; - uint32_t inspect_flags = 0; - int total_matches = 0; - - RULE_PROFILING_START(p); - - void *alstate = FlowGetAppState(f); - if (!StateIsValid(alproto, alstate)) { - RULE_PROFILING_END(det_ctx, s, 0, p); - return -1; - } - - det_ctx->tx_id = inspect_tx_id; - det_ctx->tx_id_set = 1; - SCLogDebug("inspecting: tx %u packet %u", (uint)inspect_tx_id, (uint)p->pcap_cnt); - - DetectEngineAppInspectionEngine *engine = app_inspection_engine[f->protomap][alproto][(flags & STREAM_TOSERVER) ? 0 : 1]; - void *inspect_tx = AppLayerParserGetTx(f->proto, alproto, alstate, inspect_tx_id); - if (inspect_tx == NULL) { - 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; - } - - item->flags |= inspect_flags; - /* flag this sig to don't inspect again from the detection loop it if - * there is no need for it */ - if (TxIsLast(inspect_tx_id, total_txs) || inprogress || next_tx_no_progress) { - det_ctx->de_state_sig_array[item->sid] = DE_STATE_MATCH_NO_NEW_STATE; - SCLogDebug("inspected, now bypass: tx %u packet %u", (uint)inspect_tx_id, (uint)p->pcap_cnt); - } else { - /* make sure that if we reinspect this right now from - * start detection, we skip this tx we just matched on */ - uint64_t base_tx_id = AppLayerParserGetTransactionInspectId(f->alparser, flags); - uint64_t offset = (inspect_tx_id + 1) - base_tx_id; - if (offset > MAX_STORED_TXID_OFFSET) - offset = MAX_STORED_TXID_OFFSET; - det_ctx->de_state_sig_array[item->sid] = (uint8_t)offset; -#ifdef DEBUG_VALIDATION - BUG_ON(det_ctx->de_state_sig_array[item->sid] & DE_STATE_MATCH_NO_NEW_STATE); // check that we don't set the bit -#endif - SCLogDebug("storing tx_id %u for this sid", (uint)inspect_tx_id + 1); - } - RULE_PROFILING_END(det_ctx, s, (alert == 1), p); - - if (alert) { - det_ctx->flow_locked = 1; - SigMatchSignaturesRunPostMatch(tv, de_ctx, det_ctx, p, s); - det_ctx->flow_locked = 0; - - if (!(s->flags & SIG_FLAG_NOALERT)) { - PacketAlertAppend(det_ctx, s, p, inspect_tx_id, - PACKET_ALERT_FLAG_STATE_MATCH|PACKET_ALERT_FLAG_TX); - } else { - PACKET_UPDATE_ACTION(p, s->action); - } - SCLogDebug("MATCH: tx %u packet %u", (uint)inspect_tx_id, (uint)p->pcap_cnt); - } - - DetectFlowvarProcessList(det_ctx, f); - return 1; -} - -/** \internal - * \brief Continue Detection for a single "flow" rule (AMATCH) - */ -static int DoInspectFlowRule(ThreadVars *tv, - DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, - DeStateStoreFlowRule *item, const uint8_t dir_state_flags, - Packet *p, Flow *f, AppProto alproto, uint8_t flags) -{ - /* flag rules that are either full inspected or unable to match - * in the de_state_sig_array so that prefilter filters them out */ - if (item->flags & (DE_STATE_FLAG_FULL_INSPECT|DE_STATE_FLAG_SIG_CANT_MATCH)) { - 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; - SigMatch *sm = NULL; - Signature *s = de_ctx->sig_array[item->sid]; - - RULE_PROFILING_START(p); - - KEYWORD_PROFILING_SET_LIST(det_ctx, DETECT_SM_LIST_AMATCH); - if (item->nm != NULL) { - void *alstate = FlowGetAppState(f); - if (alstate == NULL) { - 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 == 1)); - } - } 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 == 1)); - } - - if (match == 0) - break; - else if (match == 2) - inspect_flags |= DE_STATE_FLAG_SIG_CANT_MATCH; - else if (match == 1) - total_matches++; - } - } - } - - 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; - } - /* prevent the rule loop from reinspecting this rule */ - det_ctx->de_state_sig_array[item->sid] = DE_STATE_MATCH_NO_NEW_STATE; - } - RULE_PROFILING_END(det_ctx, s, (alert == 1), p); - - /* store the progress in the state */ - item->flags |= inspect_flags; - item->nm = sm; - - if (alert) { - det_ctx->flow_locked = 1; - SigMatchSignaturesRunPostMatch(tv, de_ctx, det_ctx, p, s); - det_ctx->flow_locked = 0; - - if (!(s->flags & SIG_FLAG_NOALERT)) { - 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, const uint8_t alversion) -{ - uint16_t file_no_match = 0; - SigIntId store_cnt = 0; - SigIntId state_cnt = 0; - uint64_t inspect_tx_id = 0; - uint64_t total_txs = 0; - uint8_t direction = (flags & STREAM_TOSERVER) ? 0 : 1; - - FLOWLOCK_WRLOCK(f); - - SCLogDebug("starting continue detection for packet %"PRIu64, p->pcap_cnt); - - if (AppLayerParserProtocolSupportsTxs(f->proto, alproto)) { - void *alstate = FlowGetAppState(f); - if (!StateIsValid(alproto, alstate)) { - FLOWLOCK_UNLOCK(f); - return; - } - - inspect_tx_id = AppLayerParserGetTransactionInspectId(f->alparser, flags); - total_txs = AppLayerParserGetTxCnt(f->proto, alproto, alstate); - - for ( ; inspect_tx_id < total_txs; inspect_tx_id++) { - int inspect_tx_inprogress = 0; - int next_tx_no_progress = 0; - void *inspect_tx = AppLayerParserGetTx(f->proto, alproto, alstate, inspect_tx_id); - if (inspect_tx != NULL) { - int a = AppLayerParserGetStateProgress(f->proto, alproto, inspect_tx, flags); - int b = AppLayerParserGetStateProgressCompletionStatus(f->proto, alproto, flags); - if (a < b) { - inspect_tx_inprogress = 1; - } - SCLogDebug("tx %"PRIu64" (%"PRIu64") => %s", inspect_tx_id, total_txs, - inspect_tx_inprogress ? "in progress" : "done"); - - DetectEngineState *tx_de_state = AppLayerParserGetTxDetectState(f->proto, alproto, inspect_tx); - if (tx_de_state == NULL) { - SCLogDebug("NO STATE tx %"PRIu64" (%"PRIu64")", inspect_tx_id, total_txs); - continue; - } - DetectEngineStateDirection *tx_dir_state = &tx_de_state->dir_state[direction]; - DeStateStore *tx_store = tx_dir_state->head; - - /* see if we need to consider the next tx in our decision to add - * a sig to the 'no inspect array'. */ - if (!TxIsLast(inspect_tx_id, total_txs)) { - void *next_inspect_tx = AppLayerParserGetTx(f->proto, alproto, alstate, inspect_tx_id+1); - if (next_inspect_tx != NULL) { - int c = AppLayerParserGetStateProgress(f->proto, alproto, next_inspect_tx, flags); - if (c == 0) { - next_tx_no_progress = 1; - } - } - } - - /* Loop through stored 'items' (stateful rules) and inspect them */ - state_cnt = 0; - for (; tx_store != NULL; tx_store = tx_store->next) { - SCLogDebug("tx_store %p", tx_store); - for (store_cnt = 0; - store_cnt < DE_STATE_CHUNK_SIZE && state_cnt < tx_dir_state->cnt; - store_cnt++, state_cnt++) - { - DeStateStoreItem *item = &tx_store->store[store_cnt]; - int r = DoInspectItem(tv, de_ctx, det_ctx, - item, tx_dir_state->flags, - p, f, alproto, flags, - inspect_tx_id, total_txs, - &file_no_match, inspect_tx_inprogress, next_tx_no_progress); - if (r < 0) { - SCLogDebug("failed"); - goto end; - } - } - } - } - /* if the current tx is in progress, we won't advance to any newer - * tx' just yet. */ - if (inspect_tx_inprogress) { - SCLogDebug("break out"); - break; - } - } - } - - /* continue on flow based state rules (AMATCH) */ - if (f->de_state != NULL) { - DetectEngineStateDirectionFlow *dir_state = &f->de_state->dir_state[direction]; - DeStateStoreFlowRules *store = dir_state->head; - /* 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++) - { - DeStateStoreFlowRule *rule = &store->store[store_cnt]; - - int r = DoInspectFlowRule(tv, de_ctx, det_ctx, - rule, dir_state->flags, - p, f, alproto, flags); - if (r < 0) { - goto end; - } - } - } - DeStateStoreStateVersion(f, alversion, flags); - } - -end: - FLOWLOCK_UNLOCK(f); - det_ctx->tx_id = 0; - det_ctx->tx_id_set = 0; - return; -} -/** \brief update flow's inspection id's - * - * \param f unlocked flow - * \param flags direction and disruption flags - * - * \note it is possible that f->alstate, f->alparser are NULL */ -void DeStateUpdateInspectTransactionId(Flow *f, const uint8_t flags) -{ - FLOWLOCK_WRLOCK(f); - if (f->alparser && f->alstate) { - AppLayerParserSetTransactionInspectId(f->alparser, f->proto, - f->alproto, f->alstate, flags); - } - FLOWLOCK_UNLOCK(f); - - return; -} - -void DetectEngineStateReset(DetectEngineStateFlow *state, uint8_t direction) -{ - if (state != NULL) { - if (direction & STREAM_TOSERVER) { - state->dir_state[0].cnt = 0; - state->dir_state[0].flags = 0; - } - if (direction & STREAM_TOCLIENT) { - state->dir_state[1].cnt = 0; - state->dir_state[1].flags = 0; - } - } - - return; -} - -/** \brief Reset de state for active tx' - * To be used on detect engine reload. - * \param f write LOCKED flow - */ -void DetectEngineStateResetTxs(Flow *f) -{ - if (AppLayerParserProtocolSupportsTxs(f->proto, f->alproto)) { - void *alstate = FlowGetAppState(f); - if (!StateIsValid(f->alproto, alstate)) { - return; - } - - uint64_t inspect_ts = AppLayerParserGetTransactionInspectId(f->alparser, STREAM_TOCLIENT); - uint64_t inspect_tc = AppLayerParserGetTransactionInspectId(f->alparser, STREAM_TOSERVER); - - uint64_t inspect_tx_id = MIN(inspect_ts, inspect_tc); - - uint64_t total_txs = AppLayerParserGetTxCnt(f->proto, f->alproto, alstate); - - for ( ; inspect_tx_id < total_txs; inspect_tx_id++) { - void *inspect_tx = AppLayerParserGetTx(f->proto, f->alproto, alstate, inspect_tx_id); - if (inspect_tx != NULL) { - DetectEngineState *tx_de_state = AppLayerParserGetTxDetectState(f->proto, f->alproto, inspect_tx); - if (tx_de_state == NULL) { - continue; - } - - tx_de_state->dir_state[0].cnt = 0; - tx_de_state->dir_state[0].filestore_cnt = 0; - tx_de_state->dir_state[0].flags = 0; - - tx_de_state->dir_state[1].cnt = 0; - tx_de_state->dir_state[1].filestore_cnt = 0; - tx_de_state->dir_state[1].flags = 0; - } - } - } -} - -/*********Unittests*********/ - -#ifdef UNITTESTS -#include "flow-util.h" - -static int DeStateTest01(void) -{ - SCLogDebug("sizeof(DetectEngineState)\t\t%"PRIuMAX, - (uintmax_t)sizeof(DetectEngineState)); - SCLogDebug("sizeof(DeStateStore)\t\t\t%"PRIuMAX, - (uintmax_t)sizeof(DeStateStore)); - SCLogDebug("sizeof(DeStateStoreItem)\t\t%"PRIuMAX"", - (uintmax_t)sizeof(DeStateStoreItem)); - - return 1; -} - -static int DeStateTest02(void) -{ - int result = 0; - - DetectEngineState *state = DetectEngineStateAlloc(); - if (state == NULL) { - printf("d == NULL: "); - goto end; - } - - Signature s; - memset(&s, 0x00, sizeof(s)); - - uint8_t direction = STREAM_TOSERVER; - - s.num = 0; - DeStateSignatureAppend(state, &s, 0, direction); - s.num = 11; - DeStateSignatureAppend(state, &s, 0, direction); - s.num = 22; - DeStateSignatureAppend(state, &s, 0, direction); - s.num = 33; - DeStateSignatureAppend(state, &s, 0, direction); - s.num = 44; - DeStateSignatureAppend(state, &s, 0, direction); - s.num = 55; - DeStateSignatureAppend(state, &s, 0, direction); - s.num = 66; - DeStateSignatureAppend(state, &s, 0, direction); - s.num = 77; - DeStateSignatureAppend(state, &s, 0, direction); - s.num = 88; - DeStateSignatureAppend(state, &s, 0, direction); - s.num = 99; - DeStateSignatureAppend(state, &s, 0, direction); - s.num = 100; - DeStateSignatureAppend(state, &s, 0, direction); - s.num = 111; - DeStateSignatureAppend(state, &s, 0, direction); - s.num = 122; - DeStateSignatureAppend(state, &s, 0, direction); - s.num = 133; - DeStateSignatureAppend(state, &s, 0, direction); - s.num = 144; - DeStateSignatureAppend(state, &s, 0, direction); - s.num = 155; - DeStateSignatureAppend(state, &s, 0, direction); - s.num = 166; - DeStateSignatureAppend(state, &s, 0, direction); - - if (state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head == NULL) { - goto end; - } - - if (state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head->store[1].sid != 11) { - goto end; - } - - if (state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head->next == NULL) { - goto end; - } - - if (state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head->store[14].sid != 144) { - goto end; - } - - if (state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head->next->store[0].sid != 155) { - goto end; - } - - if (state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head->next->store[1].sid != 166) { - goto end; - } - - result = 1; -end: - if (state != NULL) { - DetectEngineStateFree(state); - } - return result; -} - -static int DeStateTest03(void) -{ - int result = 0; - - DetectEngineState *state = DetectEngineStateAlloc(); - if (state == NULL) { - printf("d == NULL: "); - goto end; - } - - Signature s; - memset(&s, 0x00, sizeof(s)); - - uint8_t direction = STREAM_TOSERVER; - - s.num = 11; - DeStateSignatureAppend(state, &s, 0, direction); - s.num = 22; - DeStateSignatureAppend(state, &s, DE_STATE_FLAG_URI_INSPECT, direction); - - if (state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head == NULL) { - goto end; - } - - if (state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head->store[0].sid != 11) { - goto end; - } - - if (state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head->store[0].flags & DE_STATE_FLAG_URI_INSPECT) { - goto end; - } - - if (state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head->store[1].sid != 22) { - goto end; - } - - if (!(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head->store[1].flags & DE_STATE_FLAG_URI_INSPECT)) { - goto end; - } - - result = 1; -end: - if (state != NULL) { - DetectEngineStateFree(state); - } - return result; -} - -static int DeStateSigTest01(void) -{ - int result = 0; - Signature *s = NULL; - DetectEngineThreadCtx *det_ctx = NULL; - ThreadVars th_v; - Flow f; - TcpSession ssn; - Packet *p = NULL; - uint8_t httpbuf1[] = "POST / HTTP/1.0\r\n"; - uint8_t httpbuf2[] = "User-Agent: Mozilla/1.0\r\n"; - uint8_t httpbuf3[] = "Cookie: dummy\r\nContent-Length: 10\r\n\r\n"; - uint8_t httpbuf4[] = "Http Body!"; - uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */ - uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */ - uint32_t httplen3 = sizeof(httpbuf3) - 1; /* minus the \0 */ - uint32_t httplen4 = sizeof(httpbuf4) - 1; /* minus the \0 */ - HtpState *http_state = NULL; - AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc(); - - memset(&th_v, 0, sizeof(th_v)); - memset(&f, 0, sizeof(f)); - memset(&ssn, 0, sizeof(ssn)); - - p = UTHBuildPacket(NULL, 0, IPPROTO_TCP); - - FLOW_INITIALIZE(&f); - f.protoctx = (void *)&ssn; - f.proto = IPPROTO_TCP; - f.flags |= FLOW_IPV4; - - p->flow = &f; - p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST; - p->flowflags |= FLOW_PKT_TOSERVER; - p->flowflags |= FLOW_PKT_ESTABLISHED; - f.alproto = ALPROTO_HTTP; - - StreamTcpInitConfig(TRUE); - - DetectEngineCtx *de_ctx = DetectEngineCtxInit(); - if (de_ctx == NULL) { - goto end; - } - - de_ctx->flags |= DE_QUIET; - - s = de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any (content:\"POST\"; http_method; content:\"dummy\"; http_cookie; sid:1; rev:1;)"); - if (s == NULL) { - printf("sig parse failed: "); - goto end; - } - - SigGroupBuild(de_ctx); - DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx); - - SCMutexLock(&f.m); - int r = AppLayerParserParse(alp_tctx, &f, ALPROTO_HTTP, STREAM_TOSERVER, httpbuf1, httplen1); - if (r != 0) { - printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - /* do detect */ - SigMatchSignatures(&th_v, de_ctx, det_ctx, p); - if (PacketAlertCheck(p, 1)) { - printf("sig 1 alerted: "); - goto end; - } - p->alerts.cnt = 0; - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_HTTP, STREAM_TOSERVER, httpbuf2, httplen2); - if (r != 0) { - printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - /* do detect */ - SigMatchSignatures(&th_v, de_ctx, det_ctx, p); - if (PacketAlertCheck(p, 1)) { - printf("sig 1 alerted (2): "); - goto end; - } - p->alerts.cnt = 0; - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_HTTP, STREAM_TOSERVER, httpbuf3, httplen3); - if (r != 0) { - printf("toserver chunk 3 returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - /* do detect */ - SigMatchSignatures(&th_v, de_ctx, det_ctx, p); - if (!(PacketAlertCheck(p, 1))) { - printf("sig 1 didn't alert: "); - goto end; - } - p->alerts.cnt = 0; - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_HTTP, STREAM_TOSERVER, httpbuf4, httplen4); - if (r != 0) { - printf("toserver chunk 4 returned %" PRId32 ", expected 0: ", r); - result = 0; - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - /* do detect */ - SigMatchSignatures(&th_v, de_ctx, det_ctx, p); - if (PacketAlertCheck(p, 1)) { - printf("signature matched, but shouldn't have: "); - goto end; - } - p->alerts.cnt = 0; - - result = 1; -end: - if (alp_tctx != NULL) - AppLayerParserThreadCtxFree(alp_tctx); - if (http_state != NULL) { - HTPStateFree(http_state); - } - if (det_ctx != NULL) { - DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx); - } - if (de_ctx != NULL) { - SigGroupCleanup(de_ctx); - DetectEngineCtxFree(de_ctx); - } - - StreamTcpFreeConfig(TRUE); - FLOW_DESTROY(&f); - UTHFreePacket(p); - return result; -} - -/** \test multiple pipelined http transactions */ -static int DeStateSigTest02(void) -{ - int result = 0; - Signature *s = NULL; - DetectEngineThreadCtx *det_ctx = NULL; - ThreadVars th_v; - Flow f; - TcpSession ssn; - Packet *p = NULL; - uint8_t httpbuf1[] = "POST / HTTP/1.1\r\n"; - uint8_t httpbuf2[] = "User-Agent: Mozilla/1.0\r\nContent-Length: 10\r\n"; - uint8_t httpbuf3[] = "Cookie: dummy\r\n\r\n"; - uint8_t httpbuf4[] = "Http Body!"; - uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */ - uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */ - uint32_t httplen3 = sizeof(httpbuf3) - 1; /* minus the \0 */ - uint32_t httplen4 = sizeof(httpbuf4) - 1; /* minus the \0 */ - uint8_t httpbuf5[] = "GET /?var=val HTTP/1.1\r\n"; - uint8_t httpbuf6[] = "User-Agent: Firefox/1.0\r\n"; - uint8_t httpbuf7[] = "Cookie: dummy2\r\nContent-Length: 10\r\n\r\nHttp Body!"; - uint32_t httplen5 = sizeof(httpbuf5) - 1; /* minus the \0 */ - uint32_t httplen6 = sizeof(httpbuf6) - 1; /* minus the \0 */ - uint32_t httplen7 = sizeof(httpbuf7) - 1; /* minus the \0 */ - AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc(); - - memset(&th_v, 0, sizeof(th_v)); - memset(&f, 0, sizeof(f)); - memset(&ssn, 0, sizeof(ssn)); - - p = UTHBuildPacket(NULL, 0, IPPROTO_TCP); - - FLOW_INITIALIZE(&f); - f.protoctx = (void *)&ssn; - f.proto = IPPROTO_TCP; - f.flags |= FLOW_IPV4; - - p->flow = &f; - p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST; - p->flowflags |= FLOW_PKT_TOSERVER; - p->flowflags |= FLOW_PKT_ESTABLISHED; - f.alproto = ALPROTO_HTTP; - - StreamTcpInitConfig(TRUE); - - DetectEngineCtx *de_ctx = DetectEngineCtxInit(); - if (de_ctx == NULL) { - goto end; - } - - de_ctx->flags |= DE_QUIET; - - s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (content:\"POST\"; http_method; content:\"/\"; http_uri; content:\"Mozilla\"; http_header; content:\"dummy\"; http_cookie; content:\"body\"; nocase; http_client_body; sid:1; rev:1;)"); - if (s == NULL) { - printf("sig parse failed: "); - goto end; - } - s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (content:\"GET\"; http_method; content:\"Firefox\"; http_header; content:\"dummy2\"; http_cookie; sid:2; rev:1;)"); - if (s == NULL) { - printf("sig2 parse failed: "); - goto end; - } - - SigGroupBuild(de_ctx); - DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx); - - SCMutexLock(&f.m); - int r = AppLayerParserParse(alp_tctx, &f, ALPROTO_HTTP, STREAM_TOSERVER, httpbuf1, httplen1); - if (r != 0) { - printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - /* do detect */ - SigMatchSignatures(&th_v, de_ctx, det_ctx, p); - if (PacketAlertCheck(p, 1)) { - printf("sig 1 alerted: "); - goto end; - } - p->alerts.cnt = 0; - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_HTTP, STREAM_TOSERVER, httpbuf2, httplen2); - if (r != 0) { - printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - /* do detect */ - SigMatchSignatures(&th_v, de_ctx, det_ctx, p); - if (PacketAlertCheck(p, 1)) { - printf("sig 1 alerted (2): "); - goto end; - } - p->alerts.cnt = 0; - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_HTTP, STREAM_TOSERVER, httpbuf3, httplen3); - if (r != 0) { - printf("toserver chunk 3 returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - /* do detect */ - SigMatchSignatures(&th_v, de_ctx, det_ctx, p); - if (PacketAlertCheck(p, 1)) { - printf("sig 1 alerted too early: "); - goto end; - } - p->alerts.cnt = 0; - - void *tx = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP, f.alstate, 0); - if (tx == NULL) { - printf("no http tx: "); - goto end; - } - DetectEngineState *tx_de_state = AppLayerParserGetTxDetectState(IPPROTO_TCP, ALPROTO_HTTP, tx); - if (tx_de_state == NULL || tx_de_state->dir_state[0].cnt != 1 || - tx_de_state->dir_state[0].head->store[0].flags != 0x00000001) { - printf("de_state not present or has unexpected content: "); - goto end; - } - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_HTTP, STREAM_TOSERVER, httpbuf4, httplen4); - if (r != 0) { - printf("toserver chunk 4 returned %" PRId32 ", expected 0: ", r); - result = 0; - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - /* do detect */ - SigMatchSignatures(&th_v, de_ctx, det_ctx, p); - if (!(PacketAlertCheck(p, 1))) { - printf("sig 1 didn't match: "); - goto end; - } - p->alerts.cnt = 0; - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_HTTP, STREAM_TOSERVER, httpbuf5, httplen5); - if (r != 0) { - printf("toserver chunk 5 returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - /* do detect */ - SigMatchSignatures(&th_v, de_ctx, det_ctx, p); - if (PacketAlertCheck(p, 1)) { - printf("sig 1 alerted (5): "); - goto end; - } - p->alerts.cnt = 0; - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_HTTP, STREAM_TOSERVER, httpbuf6, httplen6); - if (r != 0) { - printf("toserver chunk 6 returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - /* do detect */ - SigMatchSignatures(&th_v, de_ctx, det_ctx, p); - if ((PacketAlertCheck(p, 1)) || (PacketAlertCheck(p, 2))) { - printf("sig 1 alerted (request 2, chunk 6): "); - goto end; - } - p->alerts.cnt = 0; - - SCLogDebug("sending data chunk 7"); - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_HTTP, STREAM_TOSERVER, httpbuf7, httplen7); - if (r != 0) { - printf("toserver chunk 7 returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - /* do detect */ - SigMatchSignatures(&th_v, de_ctx, det_ctx, p); - if (!(PacketAlertCheck(p, 2))) { - printf("signature 2 didn't match, but should have: "); - goto end; - } - p->alerts.cnt = 0; - - result = 1; -end: - if (alp_tctx != NULL) - AppLayerParserThreadCtxFree(alp_tctx); - if (det_ctx != NULL) { - DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx); - } - if (de_ctx != NULL) { - SigGroupCleanup(de_ctx); - DetectEngineCtxFree(de_ctx); - } - - StreamTcpFreeConfig(TRUE); - FLOW_DESTROY(&f); - UTHFreePacket(p); - return result; -} - -static int DeStateSigTest03(void) -{ - uint8_t httpbuf1[] = "POST /upload.cgi HTTP/1.1\r\n" - "Host: www.server.lan\r\n" - "Content-Type: multipart/form-data; boundary=---------------------------277531038314945\r\n" - "Content-Length: 215\r\n" - "\r\n" - "-----------------------------277531038314945\r\n" - "Content-Disposition: form-data; name=\"uploadfile_0\"; filename=\"somepicture1.jpg\"\r\n" - "Content-Type: image/jpeg\r\n" - "\r\n" - "filecontent\r\n" - "-----------------------------277531038314945--"; - uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */ - ThreadVars th_v; - TcpSession ssn; - int result = 0; - Flow *f = NULL; - Packet *p = NULL; - HtpState *http_state = NULL; - AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc(); - - memset(&th_v, 0, sizeof(th_v)); - memset(&ssn, 0, sizeof(ssn)); - - DetectEngineThreadCtx *det_ctx = NULL; - DetectEngineCtx *de_ctx = DetectEngineCtxInit(); - if (de_ctx == NULL) { - goto end; - } - - de_ctx->flags |= DE_QUIET; - - Signature *s = DetectEngineAppendSig(de_ctx, "alert http any any -> any any (content:\"POST\"; http_method; content:\"upload.cgi\"; http_uri; filestore; sid:1; rev:1;)"); - if (s == NULL) { - printf("sig parse failed: "); - goto end; - } - - SigGroupBuild(de_ctx); - DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx); - - f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80); - if (f == NULL) - goto end; - f->protoctx = &ssn; - f->proto = IPPROTO_TCP; - f->alproto = ALPROTO_HTTP; - - p = UTHBuildPacket(NULL, 0, IPPROTO_TCP); - if (p == NULL) - goto end; - - p->flow = f; - p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST; - p->flowflags |= FLOW_PKT_TOSERVER; - p->flowflags |= FLOW_PKT_ESTABLISHED; - - StreamTcpInitConfig(TRUE); - - SCMutexLock(&f->m); - int r = AppLayerParserParse(alp_tctx, f, ALPROTO_HTTP, STREAM_TOSERVER|STREAM_START|STREAM_EOF, httpbuf1, httplen1); - if (r != 0) { - printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); - result = 0; - SCMutexUnlock(&f->m); - goto end; - } - SCMutexUnlock(&f->m); - - /* do detect */ - SigMatchSignatures(&th_v, de_ctx, det_ctx, p); - if (!(PacketAlertCheck(p, 1))) { - printf("sig 1 didn't alert: "); - goto end; - } - - http_state = f->alstate; - if (http_state == NULL) { - printf("no http state: "); - result = 0; - goto end; - } - - if (http_state->files_ts == NULL) { - printf("no files in state: "); - goto end; - } - - SCMutexLock(&f->m); - FileContainer *files = AppLayerParserGetFiles(p->flow->proto, p->flow->alproto, - p->flow->alstate, STREAM_TOSERVER); - if (files == NULL) { - printf("no stored files: "); - SCMutexUnlock(&f->m); - goto end; - } - SCMutexUnlock(&f->m); - - File *file = files->head; - if (file == NULL) { - printf("no file: "); - goto end; - } - - if (!(file->flags & FILE_STORE)) { - printf("file is set to store, but sig didn't match: "); - goto end; - } - - result = 1; -end: - if (alp_tctx != NULL) - AppLayerParserThreadCtxFree(alp_tctx); - UTHFreeFlow(f); - - if (det_ctx != NULL) { - DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx); - } - if (de_ctx != NULL) { - SigGroupCleanup(de_ctx); - DetectEngineCtxFree(de_ctx); - } - StreamTcpFreeConfig(TRUE); - return result; -} - -static int DeStateSigTest04(void) -{ - uint8_t httpbuf1[] = "POST /upload.cgi HTTP/1.1\r\n" - "Host: www.server.lan\r\n" - "Content-Type: multipart/form-data; boundary=---------------------------277531038314945\r\n" - "Content-Length: 215\r\n" - "\r\n" - "-----------------------------277531038314945\r\n" - "Content-Disposition: form-data; name=\"uploadfile_0\"; filename=\"somepicture1.jpg\"\r\n" - "Content-Type: image/jpeg\r\n" - "\r\n" - "filecontent\r\n" - "-----------------------------277531038314945--"; - uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */ - ThreadVars th_v; - TcpSession ssn; - int result = 0; - Flow *f = NULL; - Packet *p = NULL; - HtpState *http_state = NULL; - AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc(); - - memset(&th_v, 0, sizeof(th_v)); - memset(&ssn, 0, sizeof(ssn)); - - DetectEngineThreadCtx *det_ctx = NULL; - DetectEngineCtx *de_ctx = DetectEngineCtxInit(); - if (de_ctx == NULL) { - goto end; - } - - de_ctx->flags |= DE_QUIET; - - Signature *s = DetectEngineAppendSig(de_ctx, "alert http any any -> any any (content:\"GET\"; http_method; content:\"upload.cgi\"; http_uri; filestore; sid:1; rev:1;)"); - if (s == NULL) { - printf("sig parse failed: "); - goto end; - } - - SigGroupBuild(de_ctx); - DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx); - - f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80); - if (f == NULL) - goto end; - f->protoctx = &ssn; - f->proto = IPPROTO_TCP; - f->alproto = ALPROTO_HTTP; - - p = UTHBuildPacket(NULL, 0, IPPROTO_TCP); - if (p == NULL) - goto end; - - p->flow = f; - p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST; - p->flowflags |= FLOW_PKT_TOSERVER; - p->flowflags |= FLOW_PKT_ESTABLISHED; - - StreamTcpInitConfig(TRUE); - - SCMutexLock(&f->m); - int r = AppLayerParserParse(alp_tctx, f, ALPROTO_HTTP, STREAM_TOSERVER|STREAM_START|STREAM_EOF, httpbuf1, httplen1); - if (r != 0) { - printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); - result = 0; - SCMutexUnlock(&f->m); - goto end; - } - SCMutexUnlock(&f->m); - - /* do detect */ - SigMatchSignatures(&th_v, de_ctx, det_ctx, p); - if (PacketAlertCheck(p, 1)) { - printf("sig 1 alerted: "); - goto end; - } - - http_state = f->alstate; - if (http_state == NULL) { - printf("no http state: "); - result = 0; - goto end; - } - - if (http_state->files_ts == NULL) { - printf("no files in state: "); - goto end; - } - - SCMutexLock(&f->m); - FileContainer *files = AppLayerParserGetFiles(p->flow->proto, p->flow->alproto, - p->flow->alstate, STREAM_TOSERVER); - if (files == NULL) { - printf("no stored files: "); - SCMutexUnlock(&f->m); - goto end; - } - SCMutexUnlock(&f->m); - - File *file = files->head; - if (file == NULL) { - printf("no file: "); - goto end; - } - - if (file->flags & FILE_STORE) { - printf("file is set to store, but sig didn't match: "); - goto end; - } - - result = 1; -end: - if (alp_tctx != NULL) - AppLayerParserThreadCtxFree(alp_tctx); - UTHFreeFlow(f); - - if (det_ctx != NULL) { - DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx); - } - if (de_ctx != NULL) { - SigGroupCleanup(de_ctx); - DetectEngineCtxFree(de_ctx); - } - StreamTcpFreeConfig(TRUE); - return result; -} - -static int DeStateSigTest05(void) -{ - uint8_t httpbuf1[] = "POST /upload.cgi HTTP/1.1\r\n" - "Host: www.server.lan\r\n" - "Content-Type: multipart/form-data; boundary=---------------------------277531038314945\r\n" - "Content-Length: 215\r\n" - "\r\n" - "-----------------------------277531038314945\r\n" - "Content-Disposition: form-data; name=\"uploadfile_0\"; filename=\"somepicture1.jpg\"\r\n" - "Content-Type: image/jpeg\r\n" - "\r\n" - "filecontent\r\n" - "-----------------------------277531038314945--"; - uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */ - ThreadVars th_v; - TcpSession ssn; - int result = 0; - Flow *f = NULL; - Packet *p = NULL; - HtpState *http_state = NULL; - AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc(); - - memset(&th_v, 0, sizeof(th_v)); - memset(&ssn, 0, sizeof(ssn)); - - DetectEngineThreadCtx *det_ctx = NULL; - DetectEngineCtx *de_ctx = DetectEngineCtxInit(); - if (de_ctx == NULL) { - goto end; - } - - de_ctx->flags |= DE_QUIET; - - Signature *s = DetectEngineAppendSig(de_ctx, "alert http any any -> any any (content:\"GET\"; http_method; content:\"upload.cgi\"; http_uri; filename:\"nomatch\"; sid:1; rev:1;)"); - if (s == NULL) { - printf("sig parse failed: "); - goto end; - } - - SigGroupBuild(de_ctx); - DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx); - - f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80); - if (f == NULL) - goto end; - f->protoctx = &ssn; - f->proto = IPPROTO_TCP; - f->alproto = ALPROTO_HTTP; - - p = UTHBuildPacket(NULL, 0, IPPROTO_TCP); - if (p == NULL) - goto end; - - p->flow = f; - p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST; - p->flowflags |= FLOW_PKT_TOSERVER; - p->flowflags |= FLOW_PKT_ESTABLISHED; - - StreamTcpInitConfig(TRUE); - - SCMutexLock(&f->m); - int r = AppLayerParserParse(alp_tctx, f, ALPROTO_HTTP, STREAM_TOSERVER|STREAM_START|STREAM_EOF, httpbuf1, httplen1); - if (r != 0) { - printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); - result = 0; - SCMutexUnlock(&f->m); - goto end; - } - SCMutexUnlock(&f->m); - - /* do detect */ - SigMatchSignatures(&th_v, de_ctx, det_ctx, p); - if (PacketAlertCheck(p, 1)) { - printf("sig 1 alerted: "); - goto end; - } - - http_state = f->alstate; - if (http_state == NULL) { - printf("no http state: "); - result = 0; - goto end; - } - - if (http_state->files_ts == NULL) { - printf("no files in state: "); - goto end; - } - - SCMutexLock(&f->m); - FileContainer *files = AppLayerParserGetFiles(p->flow->proto, p->flow->alproto, - p->flow->alstate, STREAM_TOSERVER); - if (files == NULL) { - printf("no stored files: "); - SCMutexUnlock(&f->m); - goto end; - } - SCMutexUnlock(&f->m); - - File *file = files->head; - if (file == NULL) { - printf("no file: "); - goto end; - } - - if (!(file->flags & FILE_NOSTORE)) { - printf("file is not set to \"no store\": "); - goto end; - } - - result = 1; -end: - if (alp_tctx != NULL) - AppLayerParserThreadCtxFree(alp_tctx); - UTHFreeFlow(f); - - if (det_ctx != NULL) { - DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx); - } - if (de_ctx != NULL) { - SigGroupCleanup(de_ctx); - DetectEngineCtxFree(de_ctx); - } - StreamTcpFreeConfig(TRUE); - return result; -} - -static int DeStateSigTest06(void) -{ - uint8_t httpbuf1[] = "POST /upload.cgi HTTP/1.1\r\n" - "Host: www.server.lan\r\n" - "Content-Type: multipart/form-data; boundary=---------------------------277531038314945\r\n" - "Content-Length: 215\r\n" - "\r\n" - "-----------------------------277531038314945\r\n" - "Content-Disposition: form-data; name=\"uploadfile_0\"; filename=\"somepicture1.jpg\"\r\n" - "Content-Type: image/jpeg\r\n" - "\r\n" - "filecontent\r\n" - "-----------------------------277531038314945--"; - uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */ - ThreadVars th_v; - TcpSession ssn; - int result = 0; - Flow *f = NULL; - Packet *p = NULL; - HtpState *http_state = NULL; - AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc(); - - memset(&th_v, 0, sizeof(th_v)); - memset(&ssn, 0, sizeof(ssn)); - - DetectEngineThreadCtx *det_ctx = NULL; - DetectEngineCtx *de_ctx = DetectEngineCtxInit(); - if (de_ctx == NULL) { - goto end; - } - - de_ctx->flags |= DE_QUIET; - - Signature *s = DetectEngineAppendSig(de_ctx, "alert http any any -> any any (content:\"POST\"; http_method; content:\"upload.cgi\"; http_uri; filename:\"nomatch\"; filestore; sid:1; rev:1;)"); - if (s == NULL) { - printf("sig parse failed: "); - goto end; - } - - SigGroupBuild(de_ctx); - DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx); - - f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80); - if (f == NULL) - goto end; - f->protoctx = &ssn; - f->proto = IPPROTO_TCP; - f->alproto = ALPROTO_HTTP; - - p = UTHBuildPacket(NULL, 0, IPPROTO_TCP); - if (p == NULL) - goto end; - - p->flow = f; - p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST; - p->flowflags |= FLOW_PKT_TOSERVER; - p->flowflags |= FLOW_PKT_ESTABLISHED; - - StreamTcpInitConfig(TRUE); - - SCMutexLock(&f->m); - int r = AppLayerParserParse(alp_tctx, f, ALPROTO_HTTP, STREAM_TOSERVER|STREAM_START|STREAM_EOF, httpbuf1, httplen1); - if (r != 0) { - printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); - result = 0; - SCMutexUnlock(&f->m); - goto end; - } - SCMutexUnlock(&f->m); - - /* do detect */ - SigMatchSignatures(&th_v, de_ctx, det_ctx, p); - if (PacketAlertCheck(p, 1)) { - printf("sig 1 alerted: "); - goto end; - } - - http_state = f->alstate; - if (http_state == NULL) { - printf("no http state: "); - result = 0; - goto end; - } - - if (http_state->files_ts == NULL) { - printf("no files in state: "); - goto end; - } - - SCMutexLock(&f->m); - FileContainer *files = AppLayerParserGetFiles(p->flow->proto, p->flow->alproto, - p->flow->alstate, STREAM_TOSERVER); - if (files == NULL) { - printf("no stored files: "); - SCMutexUnlock(&f->m); - goto end; - } - SCMutexUnlock(&f->m); - - File *file = files->head; - if (file == NULL) { - printf("no file: "); - goto end; - } - - if (!(file->flags & FILE_NOSTORE)) { - printf("file is not set to \"no store\": "); - goto end; - } - - result = 1; -end: - if (alp_tctx != NULL) - AppLayerParserThreadCtxFree(alp_tctx); - UTHFreeFlow(f); - - if (det_ctx != NULL) { - DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx); - } - if (de_ctx != NULL) { - SigGroupCleanup(de_ctx); - DetectEngineCtxFree(de_ctx); - } - StreamTcpFreeConfig(TRUE); - return result; -} - -static int DeStateSigTest07(void) -{ - uint8_t httpbuf1[] = "POST /upload.cgi HTTP/1.1\r\n" - "Host: www.server.lan\r\n" - "Content-Type: multipart/form-data; boundary=---------------------------277531038314945\r\n" - "Content-Length: 215\r\n" - "\r\n" - "-----------------------------277531038314945\r\n" - "Content-Disposition: form-data; name=\"uploadfile_0\"; filename=\"somepicture1.jpg\"\r\n" - "Content-Type: image/jpeg\r\n" - "\r\n"; - - uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */ - uint8_t httpbuf2[] = "filecontent\r\n" - "-----------------------------277531038314945--"; - uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */ - ThreadVars th_v; - TcpSession ssn; - int result = 0; - Flow *f = NULL; - Packet *p = NULL; - HtpState *http_state = NULL; - AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc(); - - memset(&th_v, 0, sizeof(th_v)); - memset(&ssn, 0, sizeof(ssn)); - - DetectEngineThreadCtx *det_ctx = NULL; - DetectEngineCtx *de_ctx = DetectEngineCtxInit(); - if (de_ctx == NULL) { - goto end; - } - - de_ctx->flags |= DE_QUIET; - - Signature *s = DetectEngineAppendSig(de_ctx, "alert http any any -> any any (content:\"GET\"; http_method; content:\"upload.cgi\"; http_uri; filestore; sid:1; rev:1;)"); - if (s == NULL) { - printf("sig parse failed: "); - goto end; - } - - SigGroupBuild(de_ctx); - DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx); - - f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80); - if (f == NULL) - goto end; - f->protoctx = &ssn; - f->proto = IPPROTO_TCP; - f->alproto = ALPROTO_HTTP; - - p = UTHBuildPacket(NULL, 0, IPPROTO_TCP); - if (p == NULL) - goto end; - - p->flow = f; - p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST; - p->flowflags |= FLOW_PKT_TOSERVER; - p->flowflags |= FLOW_PKT_ESTABLISHED; - - StreamTcpInitConfig(TRUE); - - SCLogDebug("\n>>>> processing chunk 1 <<<<\n"); - SCMutexLock(&f->m); - int r = AppLayerParserParse(alp_tctx, f, ALPROTO_HTTP, STREAM_TOSERVER|STREAM_START, httpbuf1, httplen1); - if (r != 0) { - printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); - result = 0; - SCMutexUnlock(&f->m); - goto end; - } - SCMutexUnlock(&f->m); - - /* do detect */ - SigMatchSignatures(&th_v, de_ctx, det_ctx, p); - if (PacketAlertCheck(p, 1)) { - printf("sig 1 alerted: "); - goto end; - } - - SCLogDebug("\n>>>> processing chunk 2 size %u <<<<\n", httplen2); - SCMutexLock(&f->m); - r = AppLayerParserParse(alp_tctx, f, ALPROTO_HTTP, STREAM_TOSERVER|STREAM_EOF, httpbuf2, httplen2); - if (r != 0) { - printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r); - result = 0; - SCMutexUnlock(&f->m); - goto end; - } - SCMutexUnlock(&f->m); - - SigMatchSignatures(&th_v, de_ctx, det_ctx, p); - if (PacketAlertCheck(p, 1)) { - printf("sig 1 alerted: "); - goto end; - } - - http_state = f->alstate; - if (http_state == NULL) { - printf("no http state: "); - result = 0; - goto end; - } - - if (http_state->files_ts == NULL) { - printf("no files in state: "); - goto end; - } - - SCMutexLock(&f->m); - FileContainer *files = AppLayerParserGetFiles(p->flow->proto, p->flow->alproto, - p->flow->alstate, STREAM_TOSERVER); - if (files == NULL) { - printf("no stored files: "); - SCMutexUnlock(&f->m); - goto end; - } - SCMutexUnlock(&f->m); - - File *file = files->head; - if (file == NULL) { - printf("no file: "); - goto end; - } - - if (file->flags & FILE_STORE) { - printf("file is set to store, but sig didn't match: "); - goto end; - } - - result = 1; -end: - if (alp_tctx != NULL) - AppLayerParserThreadCtxFree(alp_tctx); - UTHFreeFlow(f); - - if (det_ctx != NULL) { - DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx); - } - if (de_ctx != NULL) { - SigGroupCleanup(de_ctx); - DetectEngineCtxFree(de_ctx); - } - StreamTcpFreeConfig(TRUE); - return result; -} - -#endif - -void DeStateRegisterTests(void) -{ -#ifdef UNITTESTS - UtRegisterTest("DeStateTest01", DeStateTest01, 1); - UtRegisterTest("DeStateTest02", DeStateTest02, 1); - UtRegisterTest("DeStateTest03", DeStateTest03, 1); - UtRegisterTest("DeStateSigTest01", DeStateSigTest01, 1); - UtRegisterTest("DeStateSigTest02", DeStateSigTest02, 1); - UtRegisterTest("DeStateSigTest03", DeStateSigTest03, 1); - UtRegisterTest("DeStateSigTest04", DeStateSigTest04, 1); - UtRegisterTest("DeStateSigTest05", DeStateSigTest05, 1); - UtRegisterTest("DeStateSigTest06", DeStateSigTest06, 1); - UtRegisterTest("DeStateSigTest07", DeStateSigTest07, 1); -#endif - - return; -} - -/** - * @} - */ -- cgit 1.2.3-korg