From f658ffbc9c21fea6268867df77e081561d4f4d23 Mon Sep 17 00:00:00 2001 From: Anoop Saldanha Date: Mon, 21 Sep 2009 10:15:49 +0530 Subject: [PATCH] Order the signatures based on certain rule parameters like actions, flowbits, flowvar, pktvar, priority etc --- src/Makefile.am | 1 + src/detect-engine-sigorder.c | 1526 ++++++++++++++++++++++++++++++++++ src/detect-engine-sigorder.h | 59 ++ src/detect-engine.c | 2 + src/detect-pktvar.c | 2 +- src/detect.c | 5 + src/detect.h | 10 + src/eidps.c | 2 + 8 files changed, 1606 insertions(+), 1 deletion(-) create mode 100644 src/detect-engine-sigorder.c create mode 100644 src/detect-engine-sigorder.h diff --git a/src/Makefile.am b/src/Makefile.am index bd005cab36..b818c1578a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -28,6 +28,7 @@ flow-bit.c flow-bit.h \ pkt-var.c pkt-var.h \ host.c host.h \ detect.c detect.h \ +detect-engine-sigorder.c detect-engine-sigorder.h \ detect-engine.c detect-engine.h \ detect-isdataat.c detect-isdataat.h \ detect-window.c detect-window.h \ diff --git a/src/detect-engine-sigorder.c b/src/detect-engine-sigorder.c new file mode 100644 index 0000000000..aa1fcbde8a --- /dev/null +++ b/src/detect-engine-sigorder.c @@ -0,0 +1,1526 @@ +/** Copyright (c) 2009 Open Information Security Foundation. + * \author Anoop Saldanha + */ + +#include +#include +#include +#include + +#include "eidps-common.h" +#include "detect.h" +#include "detect-flowbits.h" +#include "detect-engine-sigorder.h" +#include "detect-pcre.h" + +#include "util-unittest.h" + +#define DETECT_FLOWVAR_NOT_USED 1 +#define DETECT_FLOWVAR_TYPE_READ 2 +#define DETECT_FLOWVAR_TYPE_SET 3 + +#define DETECT_PKTVAR_NOT_USED 1 +#define DETECT_PKTVAR_TYPE_READ 2 +#define DETECT_PKTVAR_TYPE_SET 3 + + +/** + * \brief Registers a keyword-based, signature ordering function + * + * \param de_ctx Pointer to the detection engine context from which the + * signatures have to be ordered. + * \param FuncPtr Pointer to the signature ordering function. The prototype of + * the signature ordering function should accept a pointer to a + * SCSigSignatureWrapper as its argument and shouldn't return + * anything + */ +static void SCSigRegisterSignatureOrderingFunc(DetectEngineCtx *de_ctx, + void (*FuncPtr)(DetectEngineCtx *de_ctx, SCSigSignatureWrapper *)) +{ + SCSigOrderFunc *curr = NULL; + SCSigOrderFunc *prev = NULL; + SCSigOrderFunc *temp = NULL; + + curr = de_ctx->sc_sig_order_funcs; + prev = curr; + while (curr != NULL) { + prev = curr; + if (curr->FuncPtr == FuncPtr) + break; + + curr = curr->next; + } + + if (curr != NULL) + return; + + if ( (temp = malloc(sizeof(SCSigOrderFunc))) == NULL) { + printf("Error allocating memory\n"); + exit(EXIT_FAILURE); + } + memset(temp, 0, sizeof(SCSigOrderFunc)); + + temp->FuncPtr = FuncPtr; + + if (prev == NULL) + de_ctx->sc_sig_order_funcs = temp; + else + prev->next = temp; + + return; +} + +/** + * \brief Returns the flowbit type set for this signature. If more than one + * flowbit has been set for the same rule, we return the flowbit type of + * the maximum priority/value, where priority/value is maximum for the + * ones that set the value and the lowest for ones that read the value. + * If no flowbit has been set for the rule, we return 0, which indicates + * the least value amongst flowbit types. + * + * \param sig Pointer to the Signature from which the flowbit value has to be + * returned. + * + * \retval flowbits The flowbits type for this signature if it is set; if it is + * not set, return 0 + */ +static inline int SCSigGetFlowbitsType(Signature *sig) +{ + SigMatch *sm = sig->match; + DetectFlowbitsData *fb = NULL; + int flowbits = 0; + + while (sm != NULL) { + if (sm->type == DETECT_FLOWBITS) { + fb = (DetectFlowbitsData *)sm->ctx; + if (flowbits < fb->cmd) + flowbits = fb->cmd; + } + + sm = sm->next; + } + + return flowbits; +} + +/** + * \brief Returns whether the flowvar set for this rule, sets the flowvar or + * reads the flowvar. If the rule sets the flowvar the function returns + * DETECT_FLOWVAR_TYPE_SET(3), if it reads the flowvar the function + * returns DETECT_FLOWVAR_TYPE_READ(2), and if flowvar is not used in this + * rule the function returns DETECT_FLOWVAR_NOT_USED(1) + * + * \param sig Pointer to the Signature from which the flowvar type has to be + * returned. + * + * \retval type DETECT_FLOWVAR_TYPE_SET(3) if the rule sets the flowvar, + * DETECT_FLOWVAR_TYPE_READ(2) if it reads, and + * DETECT_FLOWVAR_NOT_USED(1) if flowvar is not used. + */ +static inline int SCSigGetFlowvarType(Signature *sig) +{ + SigMatch *sm = sig->match; + DetectPcreData *pd = NULL; + int type = DETECT_FLOWVAR_NOT_USED; + + while (sm != NULL) { + pd = (DetectPcreData *)sm->ctx; + if (sm->type == DETECT_PCRE && pd->flags & DETECT_PCRE_CAPTURE_FLOW) { + type = DETECT_FLOWVAR_TYPE_SET; + return type; + } + + if (sm->type == DETECT_FLOWVAR) + type = DETECT_FLOWVAR_TYPE_READ; + + sm = sm->next; + } + + return type; +} + +/** + * \brief Returns whether the pktvar set for this rule, sets the flowvar or + * reads the pktvar. If the rule sets the pktvar the function returns + * DETECT_PKTVAR_TYPE_SET(3), if it reads the pktvar the function + * returns DETECT_PKTVAR_TYPE_READ(2), and if pktvar is not used in this + * rule the function returns DETECT_PKTVAR_NOT_USED(1) + * + * \param sig Pointer to the Signature from which the pktvar type has to be + * returned. + * + * \retval type DETECT_PKTVAR_TYPE_SET(3) if the rule sets the flowvar, + * DETECT_PKTVAR_TYPE_READ(2) if it reads, and + * DETECT_PKTVAR_NOT_USED(1) if pktvar is not used. + */ +static inline int SCSigGetPktvarType(Signature *sig) +{ + SigMatch *sm = sig->match; + DetectPcreData *pd = NULL; + int type = DETECT_PKTVAR_NOT_USED; + + while (sm != NULL) { + pd = (DetectPcreData *)sm->ctx; + if (sm->type == DETECT_PCRE && pd->flags & DETECT_PCRE_CAPTURE_PKT) { + type = DETECT_PKTVAR_TYPE_SET; + return type; + } + + if (sm->type == DETECT_PKTVAR) + type = DETECT_PKTVAR_TYPE_READ; + + sm = sm->next; + } + + return type; +} + +/** + * \brief Processes the flowbits data for this signature and caches it for + * future use. This is needed to optimize the sig_ordering module. + * + * \param sw The sigwrapper/signature for which the flowbits data has to be + * cached + */ +static inline void SCSigProcessUserDataForFlowbits(SCSigSignatureWrapper *sw) +{ + *((int *)(sw->user[SC_RADIX_USER_DATA_FLOWBITS])) = SCSigGetFlowbitsType(sw->sig); + + return; +} + +/** + * \brief Processes the flowvar data for this signature and caches it for + * future use. This is needed to optimize the sig_ordering module. + * + * \param sw The sigwrapper/signature for which the flowvar data has to be + * cached + */ +static inline void SCSigProcessUserDataForFlowvar(SCSigSignatureWrapper *sw) +{ + *((int *)(sw->user[SC_RADIX_USER_DATA_FLOWVAR])) = SCSigGetFlowvarType(sw->sig); + + return; +} + +/** + * \brief Processes the pktvar data for this signature and caches it for + * future use. This is needed to optimize the sig_ordering module. + * + * \param sw The sigwrapper/signature for which the pktvar data has to be + * cached + */ +static inline void SCSigProcessUserDataForPktvar(SCSigSignatureWrapper *sw) +{ + *((int *)(sw->user[SC_RADIX_USER_DATA_PKTVAR])) = SCSigGetPktvarType(sw->sig); + + return; +} + +/** + * \brief Orders an incoming Signature based on its action + * + * \param de_ctx Pointer to the detection engine context from which the + * signatures have to be ordered. + * \param sw The new signature that has to be ordered based on its action + */ +static void SCSigOrderByAction(DetectEngineCtx *de_ctx, + SCSigSignatureWrapper *sw) +{ + SCSigSignatureWrapper *min = NULL; + SCSigSignatureWrapper *max = NULL; + SCSigSignatureWrapper *prev = NULL; + + if (de_ctx->sc_sig_sig_wrapper == NULL) { + de_ctx->sc_sig_sig_wrapper = sw; + sw->min = NULL; + sw->max = NULL; + return; + } + + min = sw->min; + max = sw->max; + if (min == NULL) + min = de_ctx->sc_sig_sig_wrapper; + else + min = min->next; + + while (min != max) { + prev = min; + /* the sorting logic */ + if (sw->sig->action <= min->sig->action) { + min = min->next; + continue; + } + + if (min->prev == sw) + break; + + if (sw->next != NULL) + sw->next->prev = sw->prev; + if (sw->prev != NULL) + sw->prev->next = sw->next; + if (de_ctx->sc_sig_sig_wrapper == sw) + de_ctx->sc_sig_sig_wrapper = sw->next; + + sw->next = min; + sw->prev = min->prev; + + if (min->prev != NULL) + min->prev->next = sw; + else + de_ctx->sc_sig_sig_wrapper = sw; + + min->prev = sw; + + break; + } + + if (min == max && prev != sw) { + if (sw->next != NULL) { + sw->next->prev = sw->prev; + sw->prev->next = sw->next; + } + + if (min == NULL) { + prev->next = sw; + sw->prev = prev; + sw->next = NULL; + } else { + sw->prev = min->prev; + sw->next = min; + min->prev->next = sw; + min->prev = sw; + } + } + + /* set the min signature for this keyword, for the next ordering function */ + min = sw; + while (min != sw->min) { + if (min->sig->action != sw->sig->action) + break; + + min = min->prev; + } + sw->min = min; + + /* set the max signature for this keyword + 1, for the next ordering func */ + max = sw; + while (max != sw->max) { + if (max->sig->action != sw->sig->action) + break; + + max = max->next; + } + sw->max = max; + + return; +} + +/** + * \brief Orders an incoming Signature based on its flowbits type + * + * \param de_ctx Pointer to the detection engine context from which the + * signatures have to be ordered. + * \param sw The new signature that has to be ordered based on its flowbits + */ +static void SCSigOrderByFlowbits(DetectEngineCtx *de_ctx, + SCSigSignatureWrapper *sw) +{ + SCSigSignatureWrapper *min = NULL; + SCSigSignatureWrapper *max = NULL; + SCSigSignatureWrapper *prev = NULL; + + if (de_ctx->sc_sig_sig_wrapper == NULL) { + de_ctx->sc_sig_sig_wrapper = sw; + sw->min = NULL; + sw->max = NULL; + return; + } + + min = sw->min; + max = sw->max; + if (min == NULL) + min = de_ctx->sc_sig_sig_wrapper; + else + min = min->next; + + while (min != max) { + prev = min; + /* the sorting logic */ + if ( *((int *)(sw->user[SC_RADIX_USER_DATA_FLOWBITS])) <= + *((int *)(min->user[SC_RADIX_USER_DATA_FLOWBITS])) ) { + min = min->next; + continue; + } + + if (min->prev == sw) + break; + + if (sw->next != NULL) + sw->next->prev = sw->prev; + if (sw->prev != NULL) + sw->prev->next = sw->next; + if (de_ctx->sc_sig_sig_wrapper == sw) + de_ctx->sc_sig_sig_wrapper = sw->next; + + sw->next = min; + sw->prev = min->prev; + + if (min->prev != NULL) + min->prev->next = sw; + else + de_ctx->sc_sig_sig_wrapper = sw; + + min->prev = sw; + + break; + } + + if (min == max && prev != sw) { + if (sw->next != NULL) { + sw->next->prev = sw->prev; + sw->prev->next = sw->next; + } + + if (min == NULL) { + prev->next = sw; + sw->prev = prev; + sw->next = NULL; + } else { + sw->prev = min->prev; + sw->next = min; + min->prev->next = sw; + min->prev = sw; + } + } + + /* set the min signature for this keyword, for the next ordering function */ + min = sw; + while (min != sw->min) { + if ( *((int *)(sw->user[SC_RADIX_USER_DATA_FLOWBITS])) != + *((int *)(min->user[SC_RADIX_USER_DATA_FLOWBITS])) ) + break; + + min = min->prev; + } + sw->min = min; + + /* set the max signature for this keyword + 1, for the next ordering func */ + max = sw; + while (max != sw->max) { + if ( *((int *)(sw->user[SC_RADIX_USER_DATA_FLOWBITS])) != + *((int *)(max->user[SC_RADIX_USER_DATA_FLOWBITS])) ) + break; + + max = max->next; + } + sw->max = max; + + return; + +} + +/** + * \brief Orders an incoming Signature based on its flowvar type + * + * \param de_ctx Pointer to the detection engine context from which the + * signatures have to be ordered. + * \param sw The new signature that has to be ordered based on its flowvar + */ +static void SCSigOrderByFlowvar(DetectEngineCtx *de_ctx, + SCSigSignatureWrapper *sw) +{ + SCSigSignatureWrapper *min = NULL; + SCSigSignatureWrapper *max = NULL; + SCSigSignatureWrapper *prev = NULL; + + if (de_ctx->sc_sig_sig_wrapper == NULL) { + de_ctx->sc_sig_sig_wrapper = sw; + sw->min = NULL; + sw->max = NULL; + return; + } + + min = sw->min; + max = sw->max; + if (min == NULL) + min = de_ctx->sc_sig_sig_wrapper; + else + min = min->next; + + while (min != max) { + prev = min; + /* the sorting logic */ + if ( *((int *)(sw->user[SC_RADIX_USER_DATA_FLOWVAR])) <= + *((int *)(min->user[SC_RADIX_USER_DATA_FLOWVAR])) ) { + min = min->next; + continue; + } + + if (min->prev == sw) + break; + + if (sw->next != NULL) + sw->next->prev = sw->prev; + if (sw->prev != NULL) + sw->prev->next = sw->next; + if (de_ctx->sc_sig_sig_wrapper == sw) + de_ctx->sc_sig_sig_wrapper = sw->next; + + sw->next = min; + sw->prev = min->prev; + + if (min->prev != NULL) + min->prev->next = sw; + else + de_ctx->sc_sig_sig_wrapper = sw; + + min->prev = sw; + + break; + } + + if (min == max && prev != sw) { + if (sw->next != NULL) { + sw->next->prev = sw->prev; + sw->prev->next = sw->next; + } + + if (min == NULL) { + prev->next = sw; + sw->prev = prev; + sw->next = NULL; + } else { + sw->prev = min->prev; + sw->next = min; + min->prev->next = sw; + min->prev = sw; + } + } + + /* set the min signature for this keyword, for the next ordering function */ + min = sw; + while (min != sw->min) { + if ( *((int *)(sw->user[SC_RADIX_USER_DATA_FLOWVAR])) != + *((int *)(min->user[SC_RADIX_USER_DATA_FLOWVAR])) ) + break; + + min = min->prev; + } + sw->min = min; + + /* set the max signature for this keyword + 1, for the next ordering func */ + max = sw; + while (max != sw->max) { + if ( *((int *)(sw->user[SC_RADIX_USER_DATA_FLOWVAR])) != + *((int *)(max->user[SC_RADIX_USER_DATA_FLOWVAR])) ) + break; + + max = max->next; + } + sw->max = max; + + return; +} + +/** + * \brief Orders an incoming Signature based on its pktvar type + * + * \param de_ctx Pointer to the detection engine context from which the + * signatures have to be ordered. + * \param sw The new signature that has to be ordered based on its pktvar + */ +static void SCSigOrderByPktvar(DetectEngineCtx *de_ctx, + SCSigSignatureWrapper *sw) +{ + SCSigSignatureWrapper *min = NULL; + SCSigSignatureWrapper *max = NULL; + SCSigSignatureWrapper *prev = NULL; + + if (de_ctx->sc_sig_sig_wrapper == NULL) { + de_ctx->sc_sig_sig_wrapper = sw; + sw->min = NULL; + sw->max = NULL; + return; + } + + min = sw->min; + max = sw->max; + if (min == NULL) + min = de_ctx->sc_sig_sig_wrapper; + else + min = min->next; + while (min != max) { + prev = min; + /* the sorting logic */ + if ( *((int *)(sw->user[SC_RADIX_USER_DATA_PKTVAR])) <= + *((int *)(min->user[SC_RADIX_USER_DATA_PKTVAR])) ) { + min = min->next; + continue; + } + + if (min->prev == sw) + break; + + if (sw->next != NULL) + sw->next->prev = sw->prev; + if (sw->prev != NULL) + sw->prev->next = sw->next; + if (de_ctx->sc_sig_sig_wrapper == sw) + de_ctx->sc_sig_sig_wrapper = sw->next; + + sw->next = min; + sw->prev = min->prev; + + if (min->prev != NULL) + min->prev->next = sw; + else + de_ctx->sc_sig_sig_wrapper = sw; + + min->prev = sw; + + break; + } + + if (min == max && prev != sw) { + if (sw->next != NULL) { + sw->next->prev = sw->prev; + sw->prev->next = sw->next; + } + + if (min == NULL) { + prev->next = sw; + sw->prev = prev; + sw->next = NULL; + } else { + sw->prev = min->prev; + sw->next = min; + min->prev->next = sw; + min->prev = sw; + } + } + + /* set the min signature for this keyword, for the next ordering function */ + min = sw; + while (min != sw->min) { + if ( *((int *)(sw->user[SC_RADIX_USER_DATA_PKTVAR])) != + *((int *)(min->user[SC_RADIX_USER_DATA_PKTVAR])) ) + break; + + min = min->prev; + } + sw->min = min; + + /* set the max signature for this keyword + 1, for the next ordering func */ + max = sw; + while (max != sw->max) { + if ( *((int *)(sw->user[SC_RADIX_USER_DATA_PKTVAR])) != + *((int *)(max->user[SC_RADIX_USER_DATA_PKTVAR])) ) + break; + + max = max->next; + } + sw->max = max; + + return; +} + +/** + * \brief Orders an incoming Signature based on its priority type + * + * \param de_ctx Pointer to the detection engine context from which the + * signatures have to be ordered. + * \param sw The new signature that has to be ordered based on its priority + */ +static void SCSigOrderByPriority(DetectEngineCtx *de_ctx, + SCSigSignatureWrapper *sw) +{ + SCSigSignatureWrapper *min = NULL; + SCSigSignatureWrapper *max = NULL; + SCSigSignatureWrapper *prev = NULL; + + if (de_ctx->sc_sig_sig_wrapper == NULL) { + de_ctx->sc_sig_sig_wrapper = sw; + sw->min = NULL; + sw->max = NULL; + return; + } + + min = sw->min; + max = sw->max; + if (min == NULL) + min = de_ctx->sc_sig_sig_wrapper; + else + min = min->next; + + while (min != max) { + prev = min; + /* the sorting logic */ + if (sw->sig->prio >= min->sig->prio) { + min = min->next; + continue; + } + + if (min->prev == sw) + break; + + if (sw->next != NULL) + sw->next->prev = sw->prev; + if (sw->prev != NULL) + sw->prev->next = sw->next; + if (de_ctx->sc_sig_sig_wrapper == sw) + de_ctx->sc_sig_sig_wrapper = sw->next; + + sw->next = min; + sw->prev = min->prev; + + if (min->prev != NULL) + min->prev->next = sw; + else + de_ctx->sc_sig_sig_wrapper = sw; + + min->prev = sw; + + break; + } + + if (min == max && prev != sw) { + if (sw->next != NULL) { + sw->next->prev = sw->prev; + sw->prev->next = sw->next; + } + + if (min == NULL) { + prev->next = sw; + sw->prev = prev; + sw->next = NULL; + } else { + sw->prev = min->prev; + sw->next = min; + min->prev->next = sw; + min->prev = sw; + } + } + + /* set the min signature for this keyword, for the next ordering function */ + min = sw; + while (min != sw->min) { + if (min->sig->prio != sw->sig->prio) + break; + + min = min->prev; + } + sw->min = min; + + /* set the max signature for this keyword + 1, for the next ordering func */ + max = sw; + while (max != sw->max) { + if (max->sig->prio != sw->sig->prio) + break; + + max = max->next; + } + sw->max = max; + + return; +} + +/** + * \brief Creates a Wrapper around the Signature + * + * \param Pointer to the Signature to be wrapped + * + * \retval sw Pointer to the wrapper that holds the signature + */ +static inline SCSigSignatureWrapper *SCSigAllocSignatureWrapper(Signature *sig) +{ + SCSigSignatureWrapper *sw = NULL; + int i = 0; + + if ( (sw = malloc(sizeof(SCSigSignatureWrapper))) == NULL) { + printf("Error allocating memory\n"); + exit(EXIT_FAILURE); + } + memset(sw, 0, sizeof(SCSigSignatureWrapper)); + + sw->sig = sig; + + if ( (sw->user = malloc(SC_RADIX_USER_DATA_MAX * sizeof(int *))) == NULL) { + printf("Error allocating memory\n"); + exit(EXIT_FAILURE); + } + memset(sw->user, 0, SC_RADIX_USER_DATA_MAX * sizeof(int *)); + + for (i = 0; i < SC_RADIX_USER_DATA_MAX; i++) { + if ( (sw->user[i] = malloc(sizeof(int))) == NULL) { + printf("Error allocating memory\n"); + exit(EXIT_FAILURE); + } + memset(sw->user[i], 0, sizeof(int)); + } + + /* Process data from the signature into a cache for further use by the + * sig_ordering module */ + SCSigProcessUserDataForFlowbits(sw); + SCSigProcessUserDataForFlowvar(sw); + SCSigProcessUserDataForPktvar(sw); + + return sw; +} + +/** + * \brief Orders the signatures + * + * \param de_ctx Pointer to the Detection Engine Context that holds the + * signatures to be ordered + */ +void SCSigOrderSignatures(DetectEngineCtx *de_ctx) +{ + SCSigOrderFunc *funcs = NULL; + Signature *sig = NULL; + SCSigSignatureWrapper *sigw = NULL; + + int i = 0; + + printf("Ordering Signatures in memory\n"); + + sig = de_ctx->sig_list; + while (sig != NULL) { + i++; + sigw = SCSigAllocSignatureWrapper(sig); + funcs = de_ctx->sc_sig_order_funcs; + while (funcs != NULL) { + funcs->FuncPtr(de_ctx, sigw); + + funcs = funcs->next; + } + sig = sig->next; + } + +#ifndef UNITTESTS + printf("SCSigOrderSignatures: Total Signatures to be processed by the" + "sigordering module: %d\n", i); +#endif + + /* Re-order it in the Detection Engine Context sig_list */ + de_ctx->sig_list = NULL; + sigw = de_ctx->sc_sig_sig_wrapper; + i = 0; + while (sigw != NULL) { + i++; + if (de_ctx->sig_list == NULL) { + sigw->sig->next = NULL; + de_ctx->sig_list = sigw->sig; + sig = de_ctx->sig_list; + sigw = sigw->next; + continue; + } + + sigw->sig->next = NULL; + sig->next = sigw->sig; + sig = sig->next; + sigw = sigw->next; + } + +#ifndef UNITTESTS + printf("SCSigOrderSignatures: Total Signatures reordered by the sigordering" + "module: %d\n", i); +#endif + + return; +} + +/** + * \brief Lets you register the Signature ordering functions. The order in + * which the functions are registered, show the priority. The first + * function registered provides more priority than the function + * registered after it. To add a new registration function, register + * it by listing it in the correct position in the below sequence, + * based on the priority you would want to offer to that keyword. + * + * \param de_ctx Pointer to the detection engine context from which the + * signatures have to be ordered. + */ +void SCSigRegisterSignatureOrderingFuncs(DetectEngineCtx *de_ctx) +{ + printf("Registering Signature Ordering functions\n"); + + SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByAction); + SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByFlowbits); + SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByFlowvar); + SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByPktvar); + SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByPriority); + + return; +} + +/** + * \brief De-registers all the signature ordering functions registered + * + * \param de_ctx Pointer to the detection engine context from which the + * signatures were ordered. + */ +void SCSigSignatureOrderingModuleCleanup(DetectEngineCtx *de_ctx) +{ + SCSigOrderFunc *funcs = NULL; + SCSigSignatureWrapper *sigw = NULL; + void *temp = NULL; + + /* clean the memory alloted to the signature ordering funcs */ + funcs = de_ctx->sc_sig_order_funcs; + while (funcs != NULL) { + temp = funcs; + funcs = funcs->next; + free(temp); + } + de_ctx->sc_sig_order_funcs = NULL; + + /* clean the memory alloted to the signature wrappers */ + sigw = de_ctx->sc_sig_sig_wrapper; + while (sigw != NULL) { + temp = sigw; + sigw = sigw->next; + free(temp); + } + de_ctx->sc_sig_sig_wrapper = NULL; + + return; +} + +/* -------------------------------------Unittests-----------------------------*/ + +DetectEngineCtx *DetectEngineCtxInit(void); +Signature *SigInit(DetectEngineCtx *, char *); +void SigFree(Signature *); +void DetectEngineCtxFree(DetectEngineCtx *); + +#ifndef UNITTESTS + +static int SCSigTestSignatureOrdering01(void) +{ + SCSigOrderFunc *temp = NULL; + int i = 0; + + DetectEngineCtx *de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) + goto end; + + SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByAction); + SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByAction); + SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByAction); + SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByAction); + SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByAction); + SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByPriority); + SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByFlowbits); + SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByFlowbits); + SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByFlowvar); + SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByPktvar); + SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByFlowvar); + + temp = de_ctx->sc_sig_order_funcs; + while (temp != NULL) { + i++; + temp = temp->next; + } + + DetectEngineCtxFree(de_ctx); + + return (i == 5); + end: + return 0; +} + +static int SCSigTestSignatureOrdering02(void) +{ + int result = 1; + Signature *prevsig = NULL, *sig = NULL; + SCSigSignatureWrapper *sw = NULL; + int prev_code = 0; + + DetectEngineCtx *de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) + goto end; + + sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:0; depth:4; pcre:\"/220[- ]/\"; classtype:non-standard-protocol; sid:2003055; rev:4;)"); + if (sig == NULL) { + goto end; + } + prevsig = sig; + de_ctx->sig_list = sig; + + sig = SigInit(de_ctx, "drop tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:0; depth:4; pcre:\"/220[- ]/\"; classtype:non-standard-protocol; sid:2003055; rev:4;)"); + if (sig == NULL) { + goto end; + } + prevsig->next = sig; + prevsig = sig; + + sig = SigInit(de_ctx, "drop tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:10; depth:4; pcre:\"/220[- ]/\"; classtype:non-standard-protocol; sid:2003055; rev:4;)"); + if (sig == NULL) { + goto end; + } + prevsig->next = sig; + prevsig = sig; + + sig = SigInit(de_ctx, "pass tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:0; depth:4; pcre:\"/220[- ]/\"; classtype:non-standard-protocol; sid:2003055; flowvar:http_host,\"www.oisf.net\"; rev:4; priority:1; )"); + if (sig == NULL) { + goto end; + } + prevsig->next = sig; + prevsig = sig; + + sig = SigInit(de_ctx, "reject tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:0; depth:4; pcre:\"/220[- ]/\"; classtype:non-standard-protocol; sid:2003055; rev:4; priority:1;)"); + if (sig == NULL) { + goto end; + } + prevsig->next = sig; + prevsig = sig; + + sig = SigInit(de_ctx, "pass tcp any !21:902 -> any any (msg:\"Testing sigordering\"; pcre:\"/^User-Agent: (?P.*)\\r\\n/m\"; content:\"220\"; offset:10; depth:4; classtype:non-standard-protocol; sid:2003055; rev:4; priority:3;)"); + if (sig == NULL) { + goto end; + } + prevsig->next = sig; + prevsig = sig; + + sig = SigInit(de_ctx, "pass tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:10; depth:4; pcre:\"/220[- ]/\"; classtype:non-standard-protocol; sid:2003055; rev:4; priority:3;)"); + if (sig == NULL) { + goto end; + } + prevsig->next = sig; + prevsig = sig; + + sig = SigInit(de_ctx, "pass tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:10; depth:4; pcre:\"/220[- ]/\"; classtype:non-standard-protocol; sid:2003055; rev:4; priority:2;)"); + if (sig == NULL) { + goto end; + } + prevsig->next = sig; + prevsig = sig; + + + sig = SigInit(de_ctx, "reject tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:10; depth:4; pcre:\"/^User-Agent: (?P.*)\\r\\n/m\"; classtype:non-standard-protocol; sid:2003055; rev:4; priority:3; flowbits:set,TEST.one; flowbits:noalert;)"); + if (sig == NULL) { + goto end; + } + prevsig->next = sig; + prevsig = sig; + + sig = SigInit(de_ctx, "rejectsrc tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:11; depth:4; pcre:\"/220[- ]/\"; classtype:non-standard-protocol; sid:2003055; rev:4;priority:3;)"); + if (sig == NULL) { + goto end; + } + prevsig->next = sig; + prevsig = sig; + + sig = SigInit(de_ctx, "rejectdst tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:11; depth:4; pcre:\"/220[- ]/\"; classtype:non-standard-protocol; sid:2003055; rev:4;)"); + if (sig == NULL) { + goto end; + } + prevsig->next = sig; + prevsig = sig; + + sig = SigInit(de_ctx, "rejectboth tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:11; depth:4; pcre:\"/220[- ]/\"; classtype:non-standard-protocol; sid:2003055; rev:4;)"); + if (sig == NULL) { + goto end; + } + prevsig->next = sig; + prevsig = sig; + + sig = SigInit(de_ctx, "reject tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:12; depth:4; pcre:\"/220[- ]/\"; classtype:non-standard-protocol; sid:2003055; rev:4; pktvar:http_host,\"www.oisf.net\"; priority:2; flowbits:isnotset,TEST.two;)"); + if (sig == NULL) { + goto end; + } + prevsig->next = sig; + prevsig = sig; + + sig = SigInit(de_ctx, "reject tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:12; depth:4; pcre:\"/220[- ]/\"; classtype:non-standard-protocol; sid:2003055; rev:4; priority:2; flowbits:set,TEST.two;)"); + if (sig == NULL) { + goto end; + } + prevsig->next = sig; + prevsig = sig; + + SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByAction); + SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByFlowbits); + SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByFlowvar); + SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByPktvar); + SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByPriority); + SCSigOrderSignatures(de_ctx); + + sw = de_ctx->sc_sig_sig_wrapper; +#ifdef DEBUG + printf("%d - ", sw->sig->action); + printf("%d - ", SCSigGetFlowbitsType(sw->sig)); + printf("%d - ", SCSigGetFlowvarType(sw->sig)); + printf("%d - ", SCSigGetPktvarType(sw->sig)); + printf("%d\n", sw->sig->prio); +#endif + prev_code = sw->sig->action; + sw = sw->next; + while (sw != NULL) { +#ifdef DEBUG + printf("%d - ", sw->sig->action); + printf("%d - ", SCSigGetFlowbitsType(sw->sig)); + printf("%d - ", SCSigGetFlowvarType(sw->sig)); + printf("%d - ", SCSigGetPktvarType(sw->sig)); + printf("%d\n", sw->sig->prio); +#endif + result &= (prev_code >= sw->sig->action); + prev_code = sw->sig->action; + sw = sw->next; + } + + SigFree(sig); + DetectEngineCtxFree(de_ctx); +end: + return result; +} + +static int SCSigTestSignatureOrdering03(void) +{ + int result = 1; + Signature *prevsig = NULL, *sig = NULL; + SCSigSignatureWrapper *sw = NULL; + int prev_code = 0; + + DetectEngineCtx *de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) + goto end; + + sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:0; depth:4; pcre:\"/220[- ]/\"; classtype:non-standard-protocol; sid:2003055; rev:4; priority:3;)"); + if (sig == NULL) { + goto end; + } + prevsig = sig; + de_ctx->sig_list = sig; + + sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:0; depth:4; pcre:\"/220[- ]/\"; classtype:non-standard-protocol; sid:2003055; rev:4; priority:2;)"); + if (sig == NULL) { + goto end; + } + prevsig->next = sig; + prevsig = sig; + + sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:10; depth:4; pcre:\"/^User-Agent: (?P.*)\\r\\n/m\"; classtype:non-standard-protocol; sid:2003055; flowbits:unset,TEST.one; rev:4; priority:2;)"); + if (sig == NULL) { + goto end; + } + prevsig->next = sig; + prevsig = sig; + + sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:0; depth:4; pcre:\"/^User-Agent: (?P.*)\\r\\n/m\"; flowbits:isset,TEST.one; sid:2003055; rev:4; priority:1;)"); + if (sig == NULL) { + goto end; + } + prevsig->next = sig; + prevsig = sig; + + sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:0; depth:4; pcre:\"/220[- ]/\"; classtype:non-standard-protocol; sid:2003055; rev:4; priority:2;)"); + if (sig == NULL) { + goto end; + } + prevsig->next = sig; + prevsig = sig; + + sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:10; flowbits:isnotset,TEST.one; pcre:\"/^User-Agent: (?P.*)\\r\\n/m\"; sid:2003055; rev:4;)"); + if (sig == NULL) { + goto end; + } + prevsig->next = sig; + prevsig = sig; + + sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:10; depth:4; pcre:\"/220[- ]/\"; flowbits:unset,TEST.one; classtype:non-standard-protocol; sid:2003055; rev:4; priority:3;)"); + if (sig == NULL) { + goto end; + } + prevsig->next = sig; + prevsig = sig; + + sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:10; depth:4; pcre:\"/220[- ]/\"; flowbits:toggle,TEST.one; classtype:non-standard-protocol; sid:2003055; rev:4; priority:1; pktvar:http_host,\"www.oisf.net\";)"); + if (sig == NULL) { + goto end; + } + prevsig->next = sig; + prevsig = sig; + + + sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:10; depth:4; classtype:non-standard-protocol; sid:2003055; rev:4; flowbits:set,TEST.one; flowbits:noalert; pktvar:http_host,\"www.oisf.net\";)"); + if (sig == NULL) { + goto end; + } + prevsig->next = sig; + prevsig = sig; + + sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:11; depth:4; pcre:\"/220[- ]/\"; classtype:non-standard-protocol; sid:2003055; rev:4; priority:3;)"); + if (sig == NULL) { + goto end; + } + prevsig->next = sig; + prevsig = sig; + + sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:11; depth:4; pcre:\"/220[- ]/\"; classtype:non-standard-protocol; sid:2003055; rev:4;)"); + if (sig == NULL) { + goto end; + } + prevsig->next = sig; + prevsig = sig; + + sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:11; depth:4; pcre:\"/220[- ]/\"; classtype:non-standard-protocol; sid:2003055; rev:4;)"); + if (sig == NULL) { + goto end; + } + prevsig->next = sig; + prevsig = sig; + + sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:12; depth:4; pcre:\"/220[- ]/\"; classtype:non-standard-protocol; sid:2003055; rev:4; flowbits:isnotset,TEST.one;)"); + if (sig == NULL) { + goto end; + } + prevsig->next = sig; + prevsig = sig; + + sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:12; depth:4; pcre:\"/220[- ]/\"; classtype:non-standard-protocol; sid:2003055; rev:4; flowbits:set,TEST.one;)"); + if (sig == NULL) { + goto end; + } + prevsig->next = sig; + prevsig = sig; + + SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByAction); + SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByFlowbits); + SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByFlowvar); + SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByPktvar); + SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByPriority); + SCSigOrderSignatures(de_ctx); + + sw = de_ctx->sc_sig_sig_wrapper; +#ifdef DEBUG + printf("%d\n", SCSigGetFlowbitsType(sw->sig)); +#endif + prev_code = SCSigGetFlowbitsType(sw->sig); + sw = sw->next; + while (sw != NULL) { +#ifdef DEBUG + printf("%d\n", SCSigGetFlowbitsType(sw->sig)); +#endif + result &= (prev_code >= SCSigGetFlowbitsType(sw->sig)); + prev_code = SCSigGetFlowbitsType(sw->sig); + sw = sw->next; + } + + SigFree(sig); + DetectEngineCtxFree(de_ctx); +end: + return result; +} + +static int SCSigTestSignatureOrdering04(void) +{ + int result = 1; + Signature *prevsig = NULL, *sig = NULL; + SCSigSignatureWrapper *sw = NULL; + int prev_code = 0; + + DetectEngineCtx *de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) + goto end; + + sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:0; depth:4; pcre:\"/220[- ]/\"; classtype:non-standard-protocol; sid:2003055; rev:4;)"); + if (sig == NULL) { + goto end; + } + prevsig = sig; + de_ctx->sig_list = sig; + + sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; pcre:\"/^User-Agent: (?P.*)\\r\\n/m\"; content:\"220\"; offset:10; classtype:non-standard-protocol; sid:2003055; rev:4; priority:3;)"); + if (sig == NULL) { + goto end; + } + prevsig->next = sig; + prevsig = sig; + + sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:10; depth:4; pcre:\"/^User-Agent: (?P.*)\\r\\n/m\"; classtype:non-standard-protocol; sid:2003055; rev:4; priority:3;)"); + if (sig == NULL) { + goto end; + } + prevsig->next = sig; + prevsig = sig; + + sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:10; depth:4; pcre:\"/^User-Agent: (?P.*)\\r\\n/m\"; classtype:non-standard-protocol; sid:2003055; rev:4; priority:3; flowvar:http_host,\"www.oisf.net\";)"); + if (sig == NULL) { + goto end; + } + prevsig->next = sig; + prevsig = sig; + + sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:11; depth:4; pcre:\"/^User-Agent: (?P.*)\\r\\n/m\"; pcre:\"/220[- ]/\"; classtype:non-standard-protocol; sid:2003055; rev:4;priority:3;)"); + if (sig == NULL) { + goto end; + } + prevsig->next = sig; + prevsig = sig; + + sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:11; depth:4; pcre:\"/^User-Agent: (?P.*)\\r\\n/m\"; classtype:non-standard-protocol; pktvar:http_host,\"www.oisf.net\"; sid:2003055; rev:4; priority:1; )"); + if (sig == NULL) { + goto end; + } + prevsig->next = sig; + prevsig = sig; + + sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:11; depth:4; pcre:\"/220[- ]/\"; classtype:non-standard-protocol; sid:2003055; rev:4; flowvar:http_host,\"www.oisf.net\"; pktvar:http_host,\"www.oisf.net\"; priority:1;)"); + if (sig == NULL) { + goto end; + } + prevsig->next = sig; + prevsig = sig; + + sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:12; depth:4; pcre:\"/220[- ]/\"; classtype:non-standard-protocol; sid:2003055; rev:4; priority:2; flowvar:http_host,\"www.oisf.net\";)"); + if (sig == NULL) { + goto end; + } + prevsig->next = sig; + prevsig = sig; + + sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:12; depth:4; pcre:\"/220[- ]/\"; classtype:non-standard-protocol; sid:2003055; rev:4; priority:2; flowvar:http_host,\"www.oisf.net\";)"); + if (sig == NULL) { + goto end; + } + prevsig->next = sig; + prevsig = sig; + + SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByAction); + SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByFlowbits); + SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByFlowvar); + SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByPktvar); + SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByPriority); + SCSigOrderSignatures(de_ctx); + + sw = de_ctx->sc_sig_sig_wrapper; +#ifdef DEBUG + printf("%d - ", SCSigGetFlowvarType(sw->sig)); +#endif + prev_code = SCSigGetFlowvarType(sw->sig); + sw = sw->next; + while (sw != NULL) { +#ifdef DEBUG + printf("%d - ", SCSigGetFlowvarType(sw->sig)); +#endif + result &= (prev_code >= SCSigGetFlowvarType(sw->sig)); + prev_code = SCSigGetFlowvarType(sw->sig); + sw = sw->next; + } + + SigFree(sig); + DetectEngineCtxFree(de_ctx); +end: + return result; +} + +static int SCSigTestSignatureOrdering05(void) +{ + int result = 1; + Signature *prevsig = NULL, *sig = NULL; + SCSigSignatureWrapper *sw = NULL; + int prev_code = 0; + + DetectEngineCtx *de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) + goto end; + + sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:0; depth:4; pcre:\"/220[- ]/\"; classtype:non-standard-protocol; sid:2003055; rev:4;)"); + if (sig == NULL) { + goto end; + } + prevsig = sig; + de_ctx->sig_list = sig; + + sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; pcre:\"/^User-Agent: (?P.*)\\r\\n/m\"; content:\"220\"; offset:10; classtype:non-standard-protocol; sid:2003055; rev:4; priority:3;)"); + if (sig == NULL) { + goto end; + } + prevsig->next = sig; + prevsig = sig; + + sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:10; depth:4; pcre:\"/^User-Agent: (?P.*)\\r\\n/m\"; classtype:non-standard-protocol; sid:2003055; rev:4; priority:3;)"); + if (sig == NULL) { + goto end; + } + prevsig->next = sig; + prevsig = sig; + + sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:10; depth:4; pcre:\"/^User-Agent: (?P.*)\\r\\n/m\"; classtype:non-standard-protocol; sid:2003055; rev:4; priority:3; pktvar:http_host,\"www.oisf.net\";)"); + if (sig == NULL) { + goto end; + } + prevsig->next = sig; + prevsig = sig; + + sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:11; depth:4; pcre:\"/220[- ]/\"; classtype:non-standard-protocol; sid:2003055; rev:4;priority:3;)"); + if (sig == NULL) { + goto end; + } + prevsig->next = sig; + prevsig = sig; + + sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:11; depth:4; pcre:\"/220[- ]/\"; classtype:non-standard-protocol; sid:2003055; rev:4;)"); + if (sig == NULL) { + goto end; + } + prevsig->next = sig; + prevsig = sig; + + sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:11; depth:4; pcre:\"/220[- ]/\"; classtype:non-standard-protocol; sid:2003055; rev:4; pktvar:http_host,\"www.oisf.net\";)"); + if (sig == NULL) { + goto end; + } + prevsig->next = sig; + prevsig = sig; + + sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:12; depth:4; pcre:\"/220[- ]/\"; classtype:non-standard-protocol; sid:2003055; rev:4; priority:2; pktvar:http_host,\"www.oisf.net\";)"); + if (sig == NULL) { + goto end; + } + prevsig->next = sig; + prevsig = sig; + + SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByAction); + SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByFlowbits); + SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByFlowvar); + SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByPktvar); + SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByPriority); + SCSigOrderSignatures(de_ctx); + + sw = de_ctx->sc_sig_sig_wrapper; +#ifdef DEBUG + printf("%d - ", SCSigGetPktvarType(sw->sig)); +#endif + prev_code = SCSigGetPktvarType(sw->sig); + sw = sw->next; + while (sw != NULL) { +#ifdef DEBUG + printf("%d - ", SCSigGetPktvarType(sw->sig)); +#endif + result &= (prev_code >= SCSigGetPktvarType(sw->sig)); + prev_code = SCSigGetPktvarType(sw->sig); + sw = sw->next; + } + + SigFree(sig); + DetectEngineCtxFree(de_ctx); +end: + return result; +} + +static int SCSigTestSignatureOrdering06(void) +{ + int result = 1; + Signature *prevsig = NULL, *sig = NULL; + SCSigSignatureWrapper *sw = NULL; + int prev_code = 0; + + DetectEngineCtx *de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) + goto end; + + sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:0; depth:4; pcre:\"/220[- ]/\"; classtype:non-standard-protocol; sid:2003055; rev:4;)"); + if (sig == NULL) { + goto end; + } + prevsig = sig; + de_ctx->sig_list = sig; + + sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:10; classtype:non-standard-protocol; sid:2003055; rev:4; priority:2;)"); + if (sig == NULL) { + goto end; + } + prevsig->next = sig; + prevsig = sig; + + sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:10; depth:4; classtype:non-standard-protocol; sid:2003055; rev:4; priority:3;)"); + if (sig == NULL) { + goto end; + } + prevsig->next = sig; + prevsig = sig; + + sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:10; depth:4; classtype:non-standard-protocol; sid:2003055; rev:4; priority:2;)"); + if (sig == NULL) { + goto end; + } + prevsig->next = sig; + prevsig = sig; + + sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:11; depth:4; pcre:\"/220[- ]/\"; classtype:non-standard-protocol; sid:2003055; rev:4; priority:2;)"); + if (sig == NULL) { + goto end; + } + prevsig->next = sig; + prevsig = sig; + + sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:11; depth:4; pcre:\"/220[- ]/\"; classtype:non-standard-protocol; sid:2003055; rev:4; priority:1;)"); + if (sig == NULL) { + goto end; + } + prevsig->next = sig; + prevsig = sig; + + sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:11; depth:4; pcre:\"/220[- ]/\"; classtype:non-standard-protocol; sid:2003055; rev:4; priority:2;)"); + if (sig == NULL) { + goto end; + } + prevsig->next = sig; + prevsig = sig; + + sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:12; depth:4; pcre:\"/220[- ]/\"; classtype:non-standard-protocol; sid:2003055; rev:4; priority:2;)"); + if (sig == NULL) { + goto end; + } + prevsig->next = sig; + prevsig = sig; + + SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByAction); + SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByFlowbits); + SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByFlowvar); + SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByPktvar); + SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByPriority); + SCSigOrderSignatures(de_ctx); + + sw = de_ctx->sc_sig_sig_wrapper; +#ifdef DEBUG + printf("%d - ", sw->sig->prio)); +#endif + prev_code = sw->sig->prio; + sw = sw->next; + while (sw != NULL) { +#ifdef DEBUG + printf("%d - ", sw->sig->prio)); +#endif + result &= (prev_code <= sw->sig->prio); + prev_code = sw->sig->prio; + sw = sw->next; + } + + SigFree(sig); + DetectEngineCtxFree(de_ctx); +end: + return result; +} + +#endif + +void SCSigRegisterSignatureOrderingTests(void) +{ + +#ifndef UNITTESTS + + UtRegisterTest("SCSigTestSignatureOrdering01", SCSigTestSignatureOrdering01, 1); + UtRegisterTest("SCSigTestSignatureOrdering02", SCSigTestSignatureOrdering02, 1); + UtRegisterTest("SCSigTestSignatureOrdering03", SCSigTestSignatureOrdering03, 1); + UtRegisterTest("SCSigTestSignatureOrdering04", SCSigTestSignatureOrdering04, 1); + UtRegisterTest("SCSigTestSignatureOrdering05", SCSigTestSignatureOrdering05, 1); + UtRegisterTest("SCSigTestSignatureOrdering06", SCSigTestSignatureOrdering06, 1); + +#endif + +} diff --git a/src/detect-engine-sigorder.h b/src/detect-engine-sigorder.h new file mode 100644 index 0000000000..c79e040448 --- /dev/null +++ b/src/detect-engine-sigorder.h @@ -0,0 +1,59 @@ +/** Copyright (c) 2009 Open Information Security Foundation. + * \author Anoop Saldanha + */ + +#ifndef __DETECT_ENGINE_SIGORDER_H__ +#define __DETECT_ENGINE_SIGORDER_H__ + +/** + * \brief Different kinds of helper data that can be used by the signature + * ordering module. Used by the "user" field in SCSigSignatureWrapper + */ +typedef enum{ + SC_RADIX_USER_DATA_FLOWBITS, + SC_RADIX_USER_DATA_FLOWVAR, + SC_RADIX_USER_DATA_PKTVAR, + SC_RADIX_USER_DATA_MAX +} SCRadixUserDataType; + +/** + * \brief Signature wrapper used by signature ordering module while ordering + * signatures + */ +typedef struct SCSigSignatureWrapper_ { + /* the wrapped signature */ + Signature *sig; + + /* used as the lower limit SCSigSignatureWrapper that is used by the next + * ordering function, which will order the incoming Sigwrapper after this + * (min) wrapper */ + struct SCSigSignatureWrapper_ *min; + /* used as the upper limit SCSigSignatureWrapper that is used by the next + * ordering function, which will order the incoming Sigwrapper below this + * (max) wrapper */ + struct SCSigSignatureWrapper_ *max; + + /* user data that is to be associated with this sigwrapper */ + int **user; + + struct SCSigSignatureWrapper_ *next; + struct SCSigSignatureWrapper_ *prev; +} SCSigSignatureWrapper; + +/** + * \brief Structure holding the signature ordering function used by the + * signature ordering module + */ +typedef struct SCSigOrderFunc_ { + /* Pointer to the Signature Ordering function */ + void (*FuncPtr)(DetectEngineCtx *, SCSigSignatureWrapper *); + + struct SCSigOrderFunc_ *next; +} SCSigOrderFunc; + +void SCSigOrderSignatures(DetectEngineCtx *); +void SCSigRegisterSignatureOrderingFuncs(DetectEngineCtx *); +void SCSigRegisterSignatureOrderingTests(void); +void SCSigSignatureOrderingModuleCleanup(DetectEngineCtx *); + +#endif /* __DETECT_ENGINE_SIGORDER_H__ */ diff --git a/src/detect-engine.c b/src/detect-engine.c index faa68f69ac..df93fcc6c3 100644 --- a/src/detect-engine.c +++ b/src/detect-engine.c @@ -6,6 +6,7 @@ #include "flow.h" #include "detect-parse.h" +#include "detect-engine-sigorder.h" #include "detect-engine-siggroup.h" #include "detect-engine-address.h" @@ -55,6 +56,7 @@ void DetectEngineCtxFree(DetectEngineCtx *de_ctx) { SigGroupHeadMpmUriHashFree(de_ctx); SigGroupHeadSPortHashFree(de_ctx); SigGroupHeadDPortHashFree(de_ctx); + SCSigSignatureOrderingModuleCleanup(de_ctx); DetectPortSpHashFree(de_ctx); DetectPortDpHashFree(de_ctx); diff --git a/src/detect-pktvar.c b/src/detect-pktvar.c index afa299cc09..86ec28f211 100644 --- a/src/detect-pktvar.c +++ b/src/detect-pktvar.c @@ -198,7 +198,7 @@ int DetectPktvarSetup (DetectEngineCtx *de_ctx, Signature *s, SigMatch *m, char if (sm == NULL) goto error; - sm->type = DETECT_FLOWVAR; + sm->type = DETECT_PKTVAR; sm->ctx = (void *)cd; SigMatchAppend(s,m,sm); diff --git a/src/detect.c b/src/detect.c index 7170fc026e..7dbf57e679 100644 --- a/src/detect.c +++ b/src/detect.c @@ -49,6 +49,7 @@ #include "detect-flowbits.h" #include "detect-csum.h" #include "detect-stream_size.h" +#include "detect-engine-sigorder.h" #include "action-globals.h" #include "tm-modules.h" @@ -239,6 +240,10 @@ int SigLoadSignatures (DetectEngineCtx *de_ctx, char *sig_file) return -1; } + SCSigRegisterSignatureOrderingFuncs(de_ctx); + SCSigOrderSignatures(de_ctx); + SCSigSignatureOrderingModuleCleanup(de_ctx); + /* Setup the signature group lookup structure and * pattern matchers */ SigGroupBuild(de_ctx); diff --git a/src/detect.h b/src/detect.h index 913492d8ce..d2f23e13bf 100644 --- a/src/detect.h +++ b/src/detect.h @@ -1,6 +1,8 @@ #ifndef __DETECT_H__ #define __DETECT_H__ +#include + #include "detect-engine-proto.h" #include "packet-queue.h" @@ -10,6 +12,10 @@ #define COUNTER_DETECT_ALERTS 1 +/* forward declarations for the structures from detect-engine-sigorder.h */ +struct SCSigOrderFunc_; +struct SCSigSignatureWrapper_; + /* * DETECT ADDRESS */ @@ -213,6 +219,10 @@ typedef struct DetectEngineCtx_ { uint32_t signum; + /* used by the signature ordering module */ + struct SCSigOrderFunc_ *sc_sig_order_funcs; + struct SCSigSignatureWrapper_ *sc_sig_sig_wrapper; + /* main sigs */ DetectEngineLookupDsize dsize_gh[DSIZE_STATES]; diff --git a/src/eidps.c b/src/eidps.c index f2f0e99cd6..f26e7dce8a 100644 --- a/src/eidps.c +++ b/src/eidps.c @@ -68,6 +68,7 @@ #include "conf-yaml-loader.h" #include "runmodes.h" +#include "detect-engine-sigorder.h" /* * we put this here, because we only use it here in main. @@ -417,6 +418,7 @@ int main(int argc, char **argv) ConfRegisterTests(); TmqhFlowRegisterTests(); FlowRegisterTests(); + SCSigRegisterSignatureOrderingTests(); uint32_t failed = UtRunTests(); UtCleanup(); if (failed) exit(EXIT_FAILURE);