From 493715c0d22fd5445d03d48688ce10f9171d757b Mon Sep 17 00:00:00 2001 From: Victor Julien Date: Fri, 25 Dec 2009 17:27:48 +0100 Subject: [PATCH] Implement alert sid storage in the flow so we can check previous alerts in the flow. --- config.h.in | 7 - src/Makefile.am | 1 + src/decode.h | 4 +- src/detect.c | 16 +- src/detect.h | 1 + src/flow-alert-sid.c | 444 +++++++++++++++++++++++++++++++++++++++++++ src/flow-alert-sid.h | 26 +++ src/flow-bit.h | 2 +- src/flow-var.h | 2 +- src/suricata.c | 2 + src/util-var.c | 12 +- src/util-var.h | 2 +- 12 files changed, 499 insertions(+), 20 deletions(-) create mode 100644 src/flow-alert-sid.c create mode 100644 src/flow-alert-sid.h diff --git a/config.h.in b/config.h.in index fedf813681..9b9d9a8dc8 100644 --- a/config.h.in +++ b/config.h.in @@ -3,9 +3,6 @@ /* Define to 1 if you have the header file. */ #undef HAVE_ARPA_INET_H -/* Define to 1 if you have the header file. */ -#undef HAVE_DLFCN_H - /* Define to 1 if you have the `gettimeofday' function. */ #undef HAVE_GETTIMEOFDAY @@ -114,10 +111,6 @@ /* Define to 1 if the system has the type `_Bool'. */ #undef HAVE__BOOL -/* Define to the sub-directory in which libtool stores uninstalled libraries. - */ -#undef LT_OBJDIR - /* Name of package */ #undef PACKAGE diff --git a/src/Makefile.am b/src/Makefile.am index d5716271ab..a94785e09a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -25,6 +25,7 @@ flow-hash.c flow-hash.h \ flow-util.c flow-util.h \ flow-var.c flow-var.h \ flow-bit.c flow-bit.h \ +flow-alert-sid.c flow-alert-sid.h \ pkt-var.c pkt-var.h \ host.c host.h \ detect.c detect.h \ diff --git a/src/decode.h b/src/decode.h index 699226e37f..8429d97562 100644 --- a/src/decode.h +++ b/src/decode.h @@ -174,11 +174,11 @@ typedef struct HttpUri_ { typedef struct PktVar_ { char *name; - uint8_t *value; - uint16_t value_len; struct PktVar_ *next; /* right now just implement this as a list, * in the long run we have thing of something * faster. */ + uint8_t *value; + uint16_t value_len; } PktVar; typedef struct Packet_ diff --git a/src/detect.c b/src/detect.c index 3ec540ffd4..6c979522ea 100644 --- a/src/detect.c +++ b/src/detect.c @@ -77,6 +77,8 @@ #include "pkt-var.h" +#include "flow-alert-sid.h" + #include "conf.h" #include "conf-yaml-loader.h" #include @@ -427,7 +429,6 @@ inline SigGroupHead *SigMatchSignaturesGetSgh(ThreadVars *th_v, DetectEngineCtx SCReturnPtr(sgh, "SigGroupHead"); } -#include "flow-bit.h" /** \brief application layer detection * * \param sgh signature group head for this proto/addrs/ports @@ -531,6 +532,7 @@ static int SigMatchSignaturesAppLayer(ThreadVars *th_v, DetectEngineCtx *de_ctx, /* if no match function we assume this sm is a match */ SCLogDebug("no app layer match function, sigmatch is (pkt)Match only"); match = 1; + SCLogDebug("no app layer match function, sigmatch is (pkt)Match only"); } else { match = sigmatch_table[sm->type].AppLayerMatch(th_v, det_ctx, p->flow, flags, alstate, s, sm); SCLogDebug("sigmatch AppLayerMatch function returned match %"PRIu32"", match); @@ -551,10 +553,10 @@ static int SigMatchSignaturesAppLayer(ThreadVars *th_v, DetectEngineCtx *de_ctx, if (s->flags & SIG_FLAG_PACKET) { SCLogDebug("checking sid %"PRIu32"", s->id); - if (FlowBitIsset(p->flow, s->id) ) { - SCLogDebug("flowbit sid %"PRIu32", isset", s->id); + if (FlowAlertSidIsset(p->flow, s->id) ) { + SCLogDebug("flowalertsid sid %"PRIu32", isset", s->id); - PacketAlertAppend(p, 1, s->id, s->rev, s->prio, s->msg); + PacketAlertHandle(de_ctx,s,p); /* set verdict on packet */ p->action = s->action; @@ -795,10 +797,10 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh /* set flowbit for this match */ if (s->flags & SIG_FLAG_APPLAYER) { - SCLogDebug("setting flowbit for sig %"PRIu32"", s->id); - FlowBitSet(p->flow, s->id); + SCLogDebug("setting flowalertsid for sig %"PRIu32"", s->id); + FlowAlertSidSet(p->flow, s->id); } else { - PacketAlertAppend(p, s->gid, s->id, s->rev, s->prio, s->msg); + PacketAlertHandle(de_ctx,s,p); /* set verdict on packet */ p->action = s->action; diff --git a/src/detect.h b/src/detect.h index 4103d51e65..783967ea28 100644 --- a/src/detect.h +++ b/src/detect.h @@ -462,6 +462,7 @@ enum { DETECT_PKTVAR, DETECT_NOALERT, DETECT_FLOWBITS, + DETECT_FLOWALERTSID, DETECT_IPV4_CSUM, DETECT_TCPV4_CSUM, DETECT_TCPV6_CSUM, diff --git a/src/flow-alert-sid.c b/src/flow-alert-sid.c new file mode 100644 index 0000000000..a99df7d08d --- /dev/null +++ b/src/flow-alert-sid.c @@ -0,0 +1,444 @@ +/* implement per flow bits + * + * actually, not a bit, but called that way because of Snort's + * flowbits. It's a binary storage. */ + +/* TODO + * - move away from a linked list implementation + * - use different datatypes, such as string, int, etc. + * - have more than one instance of the same var, and be able to match on a + * specific one, or one all at a time. So if a certain capture matches + * multiple times, we can operate on all of them. + */ + +#include "suricata-common.h" +#include "threads.h" +#include "flow-alert-sid.h" +#include "flow.h" +#include "flow-util.h" +#include "flow-private.h" +#include "detect.h" +#include "util-var.h" +#include "util-unittest.h" +#include "util-debug.h" + +/* get the flowbit with idx from the flow */ +static FlowAlertSid *FlowAlertSidGet(Flow *f, uint32_t sid) { + GenericVar *gv = f->flowvar; + for ( ; gv != NULL; gv = gv->next) { + if (gv->type == DETECT_FLOWALERTSID) { + FlowAlertSid *fas = (FlowAlertSid *)gv; + + SCLogDebug("fas->type %"PRIu32", fas->sid %"PRIu32"", fas->type, fas->sid); + if (fas->sid == sid) { + return (FlowAlertSid *)gv; + } + } + } + + return NULL; +} + +/* add a flowbit to the flow */ +static void FlowAlertSidAdd(Flow *f, uint32_t sid) { + FlowAlertSid *fb = FlowAlertSidGet(f, sid); + if (fb == NULL) { + fb = malloc(sizeof(FlowAlertSid)); + if (fb == NULL) + return; + + fb->type = DETECT_FLOWALERTSID; + fb->sid = sid; + fb->next = NULL; + + SCLogDebug("fb->type %u, sid %"PRIu32"", fb->type, fb->sid); + GenericVarAppend(&f->flowvar, (GenericVar *)fb); + SCLogDebug("fb->type %u, sid %"PRIu32"", fb->type, fb->sid); + + SCLogDebug("adding flowalertsid with sid %" PRIu32 " (%"PRIu32")", sid, fb->sid); +#ifdef FLOWALERTSID_STATS + SCMutexLock(&flowbits_mutex); + flowbits_added++; + flowbits_memuse += sizeof(FlowAlertSid); + if (flowbits_memuse > flowbits_memuse_max) + flowbits_memuse_max = flowbits_memuse; + SCMutexUnlock(&flowbits_mutex); +#endif /* FLOWALERTSID_STATS */ + } +} + +static void FlowAlertSidRemove(Flow *f, uint32_t sid) { + FlowAlertSid *fb = FlowAlertSidGet(f, sid); + if (fb == NULL) + return; + + GenericVarRemove(&f->flowvar, (GenericVar *)fb); + + //printf("FlowAlertSidRemove: remove flowbit with idx %" PRIu32 "\n", idx); +#ifdef FLOWALERTSID_STATS + SCMutexLock(&flowbits_mutex); + flowbits_removed++; + if (flowbits_memuse >= sizeof(FlowAlertSid)) + flowbits_memuse -= sizeof(FlowAlertSid); + else { + printf("ERROR: flowbits memory usage going below 0!\n"); + flowbits_memuse = 0; + } + SCMutexUnlock(&flowbits_mutex); +#endif /* FLOWALERTSID_STATS */ +} + +void FlowAlertSidSet(Flow *f, uint32_t sid) { + SCMutexLock(&f->m); + + FlowAlertSid *fb = FlowAlertSidGet(f, sid); + if (fb == NULL) { + FlowAlertSidAdd(f, sid); + } + + SCMutexUnlock(&f->m); +} + +void FlowAlertSidUnset(Flow *f, uint32_t sid) { + SCMutexLock(&f->m); + + FlowAlertSid *fb = FlowAlertSidGet(f, sid); + if (fb != NULL) { + FlowAlertSidRemove(f, sid); + } + + SCMutexUnlock(&f->m); +} + +void FlowAlertSidToggle(Flow *f, uint32_t sid) { + SCMutexLock(&f->m); + + FlowAlertSid *fb = FlowAlertSidGet(f, sid); + if (fb != NULL) { + FlowAlertSidRemove(f, sid); + } else { + FlowAlertSidAdd(f, sid); + } + + SCMutexUnlock(&f->m); +} + +int FlowAlertSidIsset(Flow *f, uint32_t sid) { + int r = 0; + SCMutexLock(&f->m); + + FlowAlertSid *fb = FlowAlertSidGet(f, sid); + if (fb != NULL) { + r = 1; + } + + SCMutexUnlock(&f->m); + return r; +} + +int FlowAlertSidIsnotset(Flow *f, uint32_t sid) { + int r = 0; + SCMutexLock(&f->m); + + FlowAlertSid *fb = FlowAlertSidGet(f, sid); + if (fb == NULL) { + r = 1; + } + + SCMutexUnlock(&f->m); + return r; +} + +void FlowAlertSidFree(FlowAlertSid *fb) { + if (fb == NULL) + return; + + free(fb); + +#ifdef FLOWALERTSID_STATS + SCMutexLock(&flowbits_mutex); + flowbits_removed++; + if (flowbits_memuse >= sizeof(FlowAlertSid)) + flowbits_memuse -= sizeof(FlowAlertSid); + else { + printf("ERROR: flowbits memory usage going below 0!\n"); + flowbits_memuse = 0; + } + SCMutexUnlock(&flowbits_mutex); +#endif /* FLOWALERTSID_STATS */ +} + + +/* TESTS */ +#ifdef UNITTESTS +static int FlowAlertSidTest01 (void) { + int ret = 0; + + Flow f; + memset(&f, 0, sizeof(Flow)); + + FlowAlertSidAdd(&f, 0); + + FlowAlertSid *fb = FlowAlertSidGet(&f,0); + if (fb != NULL) + ret = 1; + + GenericVarFree(f.flowvar); + return ret; +} + +static int FlowAlertSidTest02 (void) { + int ret = 0; + + Flow f; + memset(&f, 0, sizeof(Flow)); + + FlowAlertSid *fb = FlowAlertSidGet(&f,0); + if (fb == NULL) + ret = 1; + + GenericVarFree(f.flowvar); + return ret; +} + +static int FlowAlertSidTest03 (void) { + int ret = 0; + + Flow f; + memset(&f, 0, sizeof(Flow)); + + FlowAlertSidAdd(&f, 0); + + FlowAlertSid *fb = FlowAlertSidGet(&f,0); + if (fb == NULL) { + printf("fb == NULL although it was just added: "); + goto end; + } + + FlowAlertSidRemove(&f, 0); + + fb = FlowAlertSidGet(&f,0); + if (fb != NULL) { + printf("fb != NULL although it was just removed: "); + goto end; + } else { + ret = 1; + } +end: + GenericVarFree(f.flowvar); + return ret; +} + +static int FlowAlertSidTest04 (void) { + int ret = 0; + + Flow f; + memset(&f, 0, sizeof(Flow)); + + FlowAlertSidAdd(&f, 0); + FlowAlertSidAdd(&f, 1); + FlowAlertSidAdd(&f, 2); + FlowAlertSidAdd(&f, 3); + + FlowAlertSid *fb = FlowAlertSidGet(&f,0); + if (fb != NULL) + ret = 1; + + GenericVarFree(f.flowvar); + return ret; +} + +static int FlowAlertSidTest05 (void) { + int ret = 0; + + Flow f; + memset(&f, 0, sizeof(Flow)); + + FlowAlertSidAdd(&f, 0); + FlowAlertSidAdd(&f, 1); + FlowAlertSidAdd(&f, 2); + FlowAlertSidAdd(&f, 3); + + FlowAlertSid *fb = FlowAlertSidGet(&f,1); + if (fb == NULL) { + printf("fb == NULL: "); + goto end; + } + + ret = 1; +end: + GenericVarFree(f.flowvar); + return ret; +} + +static int FlowAlertSidTest06 (void) { + int ret = 0; + + Flow f; + memset(&f, 0, sizeof(Flow)); + + FlowAlertSidAdd(&f, 0); + FlowAlertSidAdd(&f, 1); + FlowAlertSidAdd(&f, 2); + FlowAlertSidAdd(&f, 3); + + FlowAlertSid *fb = FlowAlertSidGet(&f,2); + if (fb != NULL) + ret = 1; + + GenericVarFree(f.flowvar); + return ret; +} + +static int FlowAlertSidTest07 (void) { + int ret = 0; + + Flow f; + memset(&f, 0, sizeof(Flow)); + + FlowAlertSidAdd(&f, 0); + FlowAlertSidAdd(&f, 1); + FlowAlertSidAdd(&f, 2); + FlowAlertSidAdd(&f, 3); + + FlowAlertSid *fb = FlowAlertSidGet(&f,3); + if (fb != NULL) + ret = 1; + + GenericVarFree(f.flowvar); + return ret; +} + +static int FlowAlertSidTest08 (void) { + int ret = 0; + + Flow f; + memset(&f, 0, sizeof(Flow)); + + FlowAlertSidAdd(&f, 0); + FlowAlertSidAdd(&f, 1); + FlowAlertSidAdd(&f, 2); + FlowAlertSidAdd(&f, 3); + + FlowAlertSid *fb = FlowAlertSidGet(&f,0); + if (fb == NULL) + goto end; + + FlowAlertSidRemove(&f,0); + + fb = FlowAlertSidGet(&f,0); + if (fb != NULL) { + printf("fb != NULL even though it was removed: "); + goto end; + } + + ret = 1; +end: + GenericVarFree(f.flowvar); + return ret; +} + +static int FlowAlertSidTest09 (void) { + int ret = 0; + + Flow f; + memset(&f, 0, sizeof(Flow)); + + FlowAlertSidAdd(&f, 0); + FlowAlertSidAdd(&f, 1); + FlowAlertSidAdd(&f, 2); + FlowAlertSidAdd(&f, 3); + + FlowAlertSid *fb = FlowAlertSidGet(&f,1); + if (fb == NULL) + goto end; + + FlowAlertSidRemove(&f,1); + + fb = FlowAlertSidGet(&f,1); + if (fb != NULL) { + printf("fb != NULL even though it was removed: "); + goto end; + } + + ret = 1; +end: + GenericVarFree(f.flowvar); + return ret; +} + +static int FlowAlertSidTest10 (void) { + int ret = 0; + + Flow f; + memset(&f, 0, sizeof(Flow)); + + FlowAlertSidAdd(&f, 0); + FlowAlertSidAdd(&f, 1); + FlowAlertSidAdd(&f, 2); + FlowAlertSidAdd(&f, 3); + + FlowAlertSid *fb = FlowAlertSidGet(&f,2); + if (fb == NULL) + goto end; + + FlowAlertSidRemove(&f,2); + + fb = FlowAlertSidGet(&f,2); + if (fb != NULL) { + printf("fb != NULL even though it was removed: "); + goto end; + } + + ret = 1; +end: + GenericVarFree(f.flowvar); + return ret; +} + +static int FlowAlertSidTest11 (void) { + int ret = 0; + + Flow f; + memset(&f, 0, sizeof(Flow)); + + FlowAlertSidAdd(&f, 0); + FlowAlertSidAdd(&f, 1); + FlowAlertSidAdd(&f, 2); + FlowAlertSidAdd(&f, 3); + + FlowAlertSid *fb = FlowAlertSidGet(&f,3); + if (fb == NULL) + goto end; + + FlowAlertSidRemove(&f,3); + + fb = FlowAlertSidGet(&f,3); + if (fb != NULL) { + printf("fb != NULL even though it was removed: "); + goto end; + } + + ret = 1; +end: + GenericVarFree(f.flowvar); + return ret; +} +#endif /* UNITTESTS */ + +void FlowAlertSidRegisterTests(void) { +#ifdef UNITTESTS + UtRegisterTest("FlowAlertSidTest01", FlowAlertSidTest01, 1); + UtRegisterTest("FlowAlertSidTest02", FlowAlertSidTest02, 1); + UtRegisterTest("FlowAlertSidTest03", FlowAlertSidTest03, 1); + UtRegisterTest("FlowAlertSidTest04", FlowAlertSidTest04, 1); + UtRegisterTest("FlowAlertSidTest05", FlowAlertSidTest05, 1); + UtRegisterTest("FlowAlertSidTest06", FlowAlertSidTest06, 1); + UtRegisterTest("FlowAlertSidTest07", FlowAlertSidTest07, 1); + UtRegisterTest("FlowAlertSidTest08", FlowAlertSidTest08, 1); + UtRegisterTest("FlowAlertSidTest09", FlowAlertSidTest09, 1); + UtRegisterTest("FlowAlertSidTest10", FlowAlertSidTest10, 1); + UtRegisterTest("FlowAlertSidTest11", FlowAlertSidTest11, 1); +#endif /* UNITTESTS */ +} + diff --git a/src/flow-alert-sid.h b/src/flow-alert-sid.h new file mode 100644 index 0000000000..846b0bc7e6 --- /dev/null +++ b/src/flow-alert-sid.h @@ -0,0 +1,26 @@ +/* Copyright (c) 2009 Victor Julien */ +#ifndef __FLOW_ALERT_SID_H__ +#define __FLOW_ALERT_SID_H__ + +#include "flow.h" +#include "util-var.h" + +typedef struct FlowAlertSid_ { + uint8_t type; /* type, DETECT_FLOWALERTSID in this case */ + GenericVar *next; /* right now just implement this as a list, + * in the long run we have think of something + * faster. */ + uint32_t sid; /* sid */ +} FlowAlertSid; + +void FlowAlertSidFree(FlowAlertSid *); +void FlowAlertSidRegisterTests(void); + +void FlowAlertSidSet(Flow *, uint32_t); +void FlowAlertSidUnset(Flow *, uint32_t); +void FlowAlertSidToggle(Flow *, uint32_t); +int FlowAlertSidIsset(Flow *, uint32_t); +int FlowAlertSidIsnotset(Flow *, uint32_t); + +#endif /* __FLOW_ALERT_SID_H__ */ + diff --git a/src/flow-bit.h b/src/flow-bit.h index f130916f4a..99072f4390 100644 --- a/src/flow-bit.h +++ b/src/flow-bit.h @@ -7,10 +7,10 @@ typedef struct FlowBit_ { uint8_t type; /* type, DETECT_FLOWBITS in this case */ - uint16_t idx; /* name idx */ GenericVar *next; /* right now just implement this as a list, * in the long run we have think of something * faster. */ + uint16_t idx; /* name idx */ } FlowBit; void FlowBitFree(FlowBit *); diff --git a/src/flow-var.h b/src/flow-var.h index 2ed8c708f2..423acd63a6 100644 --- a/src/flow-var.h +++ b/src/flow-var.h @@ -32,10 +32,10 @@ typedef struct FlowVarTypeInt_ { /** Generic Flowvar Structure */ typedef struct FlowVar_ { uint8_t type; /* type, DETECT_FLOWVAR in this case */ - uint16_t idx; /* name idx */ GenericVar *next; /* right now just implement this as a list, * in the long run we have think of something * faster. */ + uint16_t idx; /* name idx */ uint8_t datatype; union { FlowVarTypeStr fv_str; diff --git a/src/suricata.c b/src/suricata.c index 0ac60a69f5..f675a115b6 100644 --- a/src/suricata.c +++ b/src/suricata.c @@ -56,6 +56,7 @@ #include "flow.h" #include "flow-var.h" #include "flow-bit.h" +#include "flow-alert-sid.h" #include "pkt-var.h" #include "app-layer-detect-proto.h" @@ -508,6 +509,7 @@ int main(int argc, char **argv) ByteRegisterTests(); MpmRegisterTests(); FlowBitRegisterTests(); + FlowAlertSidRegisterTests(); SCPerfRegisterTests(); DecodePPPRegisterTests(); //HTTPParserRegisterTests(); diff --git a/src/util-var.c b/src/util-var.c index 03475e3bcf..4a3727d55c 100644 --- a/src/util-var.c +++ b/src/util-var.c @@ -5,13 +5,16 @@ #include "flow-var.h" #include "flow-bit.h" +#include "flow-alert-sid.h" #include "pkt-var.h" +#include "util-debug.h" + void GenericVarFree(GenericVar *gv) { if (gv == NULL) return; - //printf("GenericVarFree: gv %p, gv->type %" PRIu32 "\n", gv, gv->type); + SCLogDebug("gv %p, gv->type %" PRIu32 "", gv, gv->type); GenericVar *next_gv = gv->next; switch (gv->type) { @@ -22,6 +25,13 @@ void GenericVarFree(GenericVar *gv) { FlowBitFree(fb); break; } + case DETECT_FLOWALERTSID: + { + FlowAlertSid *fb = (FlowAlertSid *)gv; + SCLogDebug("fb %p, removing", fb); + FlowAlertSidFree(fb); + break; + } case DETECT_FLOWVAR: { FlowVar *fv = (FlowVar *)gv; diff --git a/src/util-var.h b/src/util-var.h index 1b73b0fbe6..f3a6122c5a 100644 --- a/src/util-var.h +++ b/src/util-var.h @@ -3,8 +3,8 @@ typedef struct GenericVar_ { uint8_t type; - uint16_t idx; struct GenericVar_ *next; + uint16_t idx; } GenericVar; void GenericVarFree(GenericVar *);