From d67fd306f855a6d394b9bd8ec494d04723d6dc98 Mon Sep 17 00:00:00 2001 From: Victor Julien Date: Sun, 14 Dec 2014 00:04:14 +0100 Subject: [PATCH] hostbits: implement sigorder Like with flowbits, make sure that 'set's are evaluated before 'isset's, etc. --- src/detect-engine-sigorder.c | 103 +++++++++++++++++++++++++++++++++++ src/detect-engine-sigorder.h | 1 + 2 files changed, 104 insertions(+) diff --git a/src/detect-engine-sigorder.c b/src/detect-engine-sigorder.c index 4a980ad66d..edca49c353 100644 --- a/src/detect-engine-sigorder.c +++ b/src/detect-engine-sigorder.c @@ -25,6 +25,7 @@ #include "suricata-common.h" #include "detect.h" +#include "detect-hostbits.h" #include "detect-flowbits.h" #include "detect-flowint.h" #include "detect-parse.h" @@ -58,6 +59,11 @@ #define DETECT_FLOWINT_TYPE_SET_READ 3 #define DETECT_FLOWINT_TYPE_SET 4 +#define DETECT_HOSTBITS_NOT_USED 1 +#define DETECT_HOSTBITS_TYPE_READ 2 +#define DETECT_HOSTBITS_TYPE_SET_READ 3 +#define DETECT_HOSTBITS_TYPE_SET 4 + /** * \brief Registers a keyword-based, signature ordering function @@ -340,6 +346,75 @@ static inline int SCSigGetPktvarType(Signature *sig) return type; } +/** + * \brief Returns the hostbit type set for this signature. If more than one + * hostbit has been set for the same rule, we return the hostbit 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 hostbit has been set for the rule, we return 0, which indicates + * the least value amongst hostbit types. + * + * \param sig Pointer to the Signature from which the hostbit value has to be + * returned. + * + * \retval hostbits The hostbits type for this signature if it is set; if it is + * not set, return 0 + */ +static inline int SCSigGetHostbitsType(Signature *sig) +{ + DetectHostbitsData *fb = NULL; + int hostbits_user_type = DETECT_HOSTBITS_NOT_USED; + int read = 0; + int write = 0; + SigMatch *sm = sig->sm_lists[DETECT_SM_LIST_MATCH]; + + while (sm != NULL) { + if (sm->type == DETECT_HOSTBITS) { + fb = (DetectHostbitsData *)sm->ctx; + if (fb->cmd == DETECT_HOSTBITS_CMD_ISNOTSET || + fb->cmd == DETECT_HOSTBITS_CMD_ISSET) { + read++; + } else { +#ifdef DEBUG + BUG_ON(1); +#endif + } + } + + sm = sm->next; + } + + sm = sig->sm_lists[DETECT_SM_LIST_POSTMATCH]; + while (sm != NULL) { + if (sm->type == DETECT_HOSTBITS) { + fb = (DetectHostbitsData *)sm->ctx; + if (fb->cmd == DETECT_HOSTBITS_CMD_SET || + fb->cmd == DETECT_HOSTBITS_CMD_UNSET || + fb->cmd == DETECT_HOSTBITS_CMD_TOGGLE) { + write++; + } else { +#ifdef DEBUG + BUG_ON(1); +#endif + } + } + + sm = sm->next; + } + + if (read > 0 && write == 0) { + hostbits_user_type = DETECT_HOSTBITS_TYPE_READ; + } else if (read == 0 && write > 0) { + hostbits_user_type = DETECT_HOSTBITS_TYPE_SET; + } else if (read > 0 && write > 0) { + hostbits_user_type = DETECT_HOSTBITS_TYPE_SET_READ; + } + + SCLogDebug("Sig %s typeval %d", sig->msg, hostbits_user_type); + + return hostbits_user_type; +} + /** * \brief Processes the flowbits data for this signature and caches it for * future use. This is needed to optimize the sig_ordering module. @@ -381,6 +456,18 @@ static inline void SCSigProcessUserDataForPktvar(SCSigSignatureWrapper *sw) sw->user[SC_RADIX_USER_DATA_PKTVAR] = SCSigGetPktvarType(sw->sig); } +/** + * \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 SCSigProcessUserDataForHostbits(SCSigSignatureWrapper *sw) +{ + sw->user[SC_RADIX_USER_DATA_HOSTBITS] = SCSigGetHostbitsType(sw->sig); +} + /* Return 1 if sw1 comes before sw2 in the final list. */ static int SCSigLessThan(SCSigSignatureWrapper *sw1, SCSigSignatureWrapper *sw2, @@ -528,6 +615,20 @@ static int SCSigOrderByFlowintCompare(SCSigSignatureWrapper *sw1, sw2->user[SC_RADIX_USER_DATA_FLOWINT]; } +/** + * \brief Orders an incoming Signature based on its hostbits 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 hostbits + */ +static int SCSigOrderByHostbitsCompare(SCSigSignatureWrapper *sw1, + SCSigSignatureWrapper *sw2) +{ + return sw1->user[SC_RADIX_USER_DATA_HOSTBITS] - + sw2->user[SC_RADIX_USER_DATA_HOSTBITS]; +} + /** * \brief Orders an incoming Signature based on its priority type * @@ -564,6 +665,7 @@ static inline SCSigSignatureWrapper *SCSigAllocSignatureWrapper(Signature *sig) SCSigProcessUserDataForFlowvar(sw); SCSigProcessUserDataForFlowint(sw); SCSigProcessUserDataForPktvar(sw); + SCSigProcessUserDataForHostbits(sw); return sw; } @@ -643,6 +745,7 @@ void SCSigRegisterSignatureOrderingFuncs(DetectEngineCtx *de_ctx) SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByFlowintCompare); SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByFlowvarCompare); SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByPktvarCompare); + SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByHostbitsCompare); SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByPriorityCompare); } diff --git a/src/detect-engine-sigorder.h b/src/detect-engine-sigorder.h index 1451dfc3fa..312165a04b 100644 --- a/src/detect-engine-sigorder.h +++ b/src/detect-engine-sigorder.h @@ -33,6 +33,7 @@ typedef enum{ SC_RADIX_USER_DATA_FLOWVAR, SC_RADIX_USER_DATA_PKTVAR, SC_RADIX_USER_DATA_FLOWINT, + SC_RADIX_USER_DATA_HOSTBITS, SC_RADIX_USER_DATA_MAX } SCRadixUserDataType;