From 89baf93a40f10c6cec5714836b13437d9bf686d4 Mon Sep 17 00:00:00 2001 From: Breno Silva Date: Thu, 15 Apr 2010 19:00:57 -0300 Subject: [PATCH 1/4] Reference Support --- src/alert-fastlog.c | 52 ++-- src/decode.h | 3 + src/detect-engine-threshold.c | 20 +- src/detect-parse.c | 20 ++ src/detect-reference.c | 470 +++++++++++++++++++++++++++++++++- src/detect-reference.h | 38 ++- src/detect.c | 3 +- src/detect.h | 6 +- 8 files changed, 569 insertions(+), 43 deletions(-) diff --git a/src/alert-fastlog.c b/src/alert-fastlog.c index 11fd8e612a..fc137ce5a1 100644 --- a/src/alert-fastlog.c +++ b/src/alert-fastlog.c @@ -29,6 +29,7 @@ #include "detect-parse.h" #include "detect-engine.h" #include "detect-engine-mpm.h" +#include "detect-reference.h" #include "util-classification-config.h" #include "output.h" @@ -91,15 +92,16 @@ static void CreateTimeString (const struct timeval *ts, char *str, size_t size) uint32_t sec = ts->tv_sec % 86400; snprintf(str, size, "%02d/%02d/%02d-%02d:%02d:%02d.%06u", - t->tm_mon + 1, t->tm_mday, t->tm_year - 100, - sec / 3600, (sec % 3600) / 60, sec % 60, - (uint32_t) ts->tv_usec); + t->tm_mon + 1, t->tm_mday, t->tm_year - 100, + sec / 3600, (sec % 3600) / 60, sec % 60, + (uint32_t) ts->tv_usec); } TmEcode AlertFastLogIPv4(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq) { AlertFastLogThread *aft = (AlertFastLogThread *)data; int i; + References *sref = NULL; char timebuf[64]; if (p->alerts.cnt == 0) @@ -119,8 +121,16 @@ TmEcode AlertFastLogIPv4(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq) inet_ntop(AF_INET, (const void *)GET_IPV4_SRC_ADDR_PTR(p), srcip, sizeof(srcip)); inet_ntop(AF_INET, (const void *)GET_IPV4_DST_ADDR_PTR(p), dstip, sizeof(dstip)); - fprintf(aft->file_ctx->fp, "%s [**] [%" PRIu32 ":%" PRIu32 ":%" PRIu32 "] %s [**] [Classification: %s] [Priority: %" PRIu32 "] {%" PRIu32 "} %s:%" PRIu32 " -> %s:%" PRIu32 "\n", - timebuf, pa->gid, pa->sid, pa->rev, pa->msg, pa->class_msg, pa->prio, IPV4_GET_IPPROTO(p), srcip, p->sp, dstip, p->dp); + fprintf(aft->file_ctx->fp, "%s [**] [%" PRIu32 ":%" PRIu32 ":%" PRIu32 "] %s [**] [Classification: %s] [Priority: %" PRIu32 "] {%" PRIu32 "} %s:%" PRIu32 " -> %s:%" PRIu32 " ", + timebuf, pa->gid, pa->sid, pa->rev, pa->msg, pa->class_msg, pa->prio, IPV4_GET_IPPROTO(p), srcip, p->sp, dstip, p->dp); + if(pa->sigref != NULL) { + for (sref = pa->sigref; sref != NULL; sref = sref->next) { + fprintf(aft->file_ctx->fp,"[Xref => %s]",sref->reference); + } + } + + fprintf(aft->file_ctx->fp,"\n"); + fflush(aft->file_ctx->fp); } SCMutexUnlock(&aft->file_ctx->fp_mutex); @@ -132,6 +142,7 @@ TmEcode AlertFastLogIPv6(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq) { AlertFastLogThread *aft = (AlertFastLogThread *)data; int i; + References *sref = NULL; char timebuf[64]; if (p->alerts.cnt == 0) @@ -150,10 +161,19 @@ TmEcode AlertFastLogIPv6(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq) inet_ntop(AF_INET6, (const void *)GET_IPV6_SRC_ADDR(p), srcip, sizeof(srcip)); inet_ntop(AF_INET6, (const void *)GET_IPV6_DST_ADDR(p), dstip, sizeof(dstip)); - fprintf(aft->file_ctx->fp, "%s [**] [%" PRIu32 ":%" PRIu32 ":%" PRIu32 "] %s [**] [Classification: %s] [Priority: %" PRIu32 "] {%" PRIu32 "} %s:%" PRIu32 " -> %s:%" PRIu32 "\n", + fprintf(aft->file_ctx->fp, "%s [**] [%" PRIu32 ":%" PRIu32 ":%" PRIu32 "] %s [**] [Classification: %s] [Priority: %" PRIu32 "] {%" PRIu32 "} %s:%" PRIu32 " -> %s:%" PRIu32 " ", timebuf, pa->gid, pa->sid, pa->rev, pa->msg, pa->class_msg, pa->prio, IPV6_GET_L4PROTO(p), srcip, p->sp, dstip, p->dp); + + if(pa->sigref != NULL) { + for (sref = pa->sigref; sref != NULL; sref = sref->next) { + fprintf(aft->file_ctx->fp,"[Xref => %s]",sref->reference); + } + } + + fprintf(aft->file_ctx->fp,"\n"); + + fflush(aft->file_ctx->fp); } - fflush(aft->file_ctx->fp); SCMutexUnlock(&aft->file_ctx->fp_mutex); return TM_ECODE_OK; @@ -237,7 +257,7 @@ OutputCtx *AlertFastLogInitCtx(ConfNode *conf) OutputCtx *output_ctx = SCCalloc(1, sizeof(OutputCtx)); if (output_ctx == NULL) { SCLogError(SC_ERR_MEM_ALLOC, - "Failed to allocated memory for OutputCtx"); + "Failed to allocated memory for OutputCtx"); exit(EXIT_FAILURE); } output_ctx->data = logfile_ctx; @@ -271,7 +291,7 @@ static int AlertFastLogOpenFileCtx(LogFileCtx *file_ctx, const char *filename) if (file_ctx->fp == NULL) { SCLogError(SC_ERR_FOPEN, "ERROR: failed to open %s: %s", log_path, - strerror(errno)); + strerror(errno)); return -1; } @@ -314,8 +334,8 @@ int AlertFastLogTest01() SCClassConfDeleteDummyClassificationConfigFD(); de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " - "(msg:\"FastLog test\"; content:GET; " - "Classtype:unknown; sid:1;)"); + "(msg:\"FastLog test\"; content:GET; " + "Classtype:unknown; sid:1;)"); result = (de_ctx->sig_list != NULL); SigGroupBuild(de_ctx); @@ -375,8 +395,8 @@ int AlertFastLogTest02() SCClassConfDeleteDummyClassificationConfigFD(); de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " - "(msg:\"FastLog test\"; content:GET; " - "Classtype:unknown; sid:1;)"); + "(msg:\"FastLog test\"; content:GET; " + "Classtype:unknown; sid:1;)"); result = (de_ctx->sig_list != NULL); if (result == 0) printf("sig parse failed: "); @@ -389,7 +409,7 @@ int AlertFastLogTest02() result = (strcmp(p.alerts.alerts[0].class_msg, "Unknown Traffic") != 0); if (result == 0) printf("p.alerts.alerts[0].class_msg %s: ", p.alerts.alerts[0].class_msg); result = (strcmp(p.alerts.alerts[0].class_msg, - "Unknown are we") == 0); + "Unknown are we") == 0); if (result == 0) printf("p.alerts.alerts[0].class_msg %s: ", p.alerts.alerts[0].class_msg); } else { result = 0; @@ -424,7 +444,7 @@ void AlertFastLogRegisterTests(void) #ifdef __SC_CUDA_SUPPORT__ UtRegisterTest("AlertFastLogCudaContextInit", - SCCudaHlTestEnvCudaContextInit, 1); + SCCudaHlTestEnvCudaContextInit, 1); #endif UtRegisterTest("AlertFastLogTest01", AlertFastLogTest01, 1); @@ -432,7 +452,7 @@ void AlertFastLogRegisterTests(void) #ifdef __SC_CUDA_SUPPORT__ UtRegisterTest("AlertFastLogCudaContextDeInit", - SCCudaHlTestEnvCudaContextDeInit, 1); + SCCudaHlTestEnvCudaContextDeInit, 1); #endif #endif /* UNITTESTS */ diff --git a/src/decode.h b/src/decode.h index e3e05e3e60..089f3b75c3 100644 --- a/src/decode.h +++ b/src/decode.h @@ -34,6 +34,8 @@ #include "decode-raw.h" #include "decode-vlan.h" +#include "detect-reference.h" + /* forward declaration */ struct DetectionEngineThreadCtx_; @@ -170,6 +172,7 @@ typedef struct PacketAlert_ { uint8_t prio; char *msg; char *class_msg; + References *sigref; } PacketAlert; #define PACKET_ALERT_MAX 256 diff --git a/src/detect-engine-threshold.c b/src/detect-engine-threshold.c index f376d58015..f637735ec0 100644 --- a/src/detect-engine-threshold.c +++ b/src/detect-engine-threshold.c @@ -53,7 +53,7 @@ void PacketAlertHandle(DetectEngineCtx *de_ctx, Signature *sig, Packet *p) /* if have none just alert, otherwise handle thresholding */ if (td == NULL) { - PacketAlertAppend(p, sig->gid, sig->id, sig->rev, sig->prio, sig->msg, sig->class_msg); + PacketAlertAppend(p, sig->gid, sig->id, sig->rev, sig->prio, sig->msg, sig->class_msg, sig->sigref); } else { PacketAlertThreshold(de_ctx, td, p, sig); } @@ -277,20 +277,20 @@ void PacketAlertThreshold(DetectEngineCtx *de_ctx, DetectThresholdData *td, Pack if (lookup_tsh != NULL) { if ((ts.tv_sec - lookup_tsh->tv_sec1) < td->seconds) { if (lookup_tsh->current_count < td->count) { - PacketAlertAppend(p, s->gid, s->id, s->rev, s->prio, s->msg, s->class_msg); + PacketAlertAppend(p, s->gid, s->id, s->rev, s->prio, s->msg, s->class_msg, s->sigref); } lookup_tsh->current_count++; } else { lookup_tsh->tv_sec1 = ts.tv_sec; lookup_tsh->current_count = 1; - PacketAlertAppend(p, s->gid, s->id, s->rev, s->prio, s->msg, s->class_msg); + PacketAlertAppend(p, s->gid, s->id, s->rev, s->prio, s->msg, s->class_msg, s->sigref); } } else { ste->tv_sec1 = ts.tv_sec; ste->current_count = 1; - PacketAlertAppend(p, s->gid, s->id, s->rev, s->prio, s->msg, s->class_msg); + PacketAlertAppend(p, s->gid, s->id, s->rev, s->prio, s->msg, s->class_msg, s->sigref); ThresholdHashAdd(de_ctx, ste, p); ste = NULL; @@ -307,7 +307,7 @@ void PacketAlertThreshold(DetectEngineCtx *de_ctx, DetectThresholdData *td, Pack lookup_tsh->current_count++; if (lookup_tsh->current_count >= td->count) { - PacketAlertAppend(p, s->gid, s->id, s->rev, s->prio, s->msg, s->class_msg); + PacketAlertAppend(p, s->gid, s->id, s->rev, s->prio, s->msg, s->class_msg, s->sigref); lookup_tsh->current_count = 0; } } else { @@ -319,7 +319,7 @@ void PacketAlertThreshold(DetectEngineCtx *de_ctx, DetectThresholdData *td, Pack ste->tv_sec1 = ts.tv_sec; if (td->count == 1) { - PacketAlertAppend(p, s->gid, s->id, s->rev, s->prio, s->msg, s->class_msg); + PacketAlertAppend(p, s->gid, s->id, s->rev, s->prio, s->msg, s->class_msg, s->sigref); ste->current_count = 0; } else { ThresholdHashAdd(de_ctx,ste,p); @@ -337,7 +337,7 @@ void PacketAlertThreshold(DetectEngineCtx *de_ctx, DetectThresholdData *td, Pack if ((ts.tv_sec - lookup_tsh->tv_sec1) < td->seconds) { lookup_tsh->current_count++; if (lookup_tsh->current_count == td->count) { - PacketAlertAppend(p, s->gid, s->id, s->rev, s->prio, s->msg, s->class_msg); + PacketAlertAppend(p, s->gid, s->id, s->rev, s->prio, s->msg, s->class_msg, s->sigref); } } else { lookup_tsh->tv_sec1 = ts.tv_sec; @@ -348,7 +348,7 @@ void PacketAlertThreshold(DetectEngineCtx *de_ctx, DetectThresholdData *td, Pack ste->tv_sec1 = ts.tv_sec; if (td->count == 1) { - PacketAlertAppend(p, s->gid, s->id, s->rev, s->prio, s->msg, s->class_msg); + PacketAlertAppend(p, s->gid, s->id, s->rev, s->prio, s->msg, s->class_msg, s->sigref); ste->current_count = 0; } else { ThresholdHashAdd(de_ctx,ste,p); @@ -367,7 +367,7 @@ void PacketAlertThreshold(DetectEngineCtx *de_ctx, DetectThresholdData *td, Pack if ((ts.tv_sec - lookup_tsh->tv_sec1) < td->seconds) { lookup_tsh->current_count++; if (lookup_tsh->current_count >= td->count) { - PacketAlertAppend(p, s->gid, s->id, s->rev, s->prio, s->msg, s->class_msg); + PacketAlertAppend(p, s->gid, s->id, s->rev, s->prio, s->msg, s->class_msg, s->sigref); } } else { lookup_tsh->tv_sec1 = ts.tv_sec; @@ -378,7 +378,7 @@ void PacketAlertThreshold(DetectEngineCtx *de_ctx, DetectThresholdData *td, Pack ste->tv_sec1 = ts.tv_sec; if (td->count == 1) { - PacketAlertAppend(p, s->gid, s->id, s->rev, s->prio, s->msg, s->class_msg); + PacketAlertAppend(p, s->gid, s->id, s->rev, s->prio, s->msg, s->class_msg, s->sigref); } ThresholdHashAdd(de_ctx, ste, p); ste = NULL; diff --git a/src/detect-parse.c b/src/detect-parse.c index 1c374770db..3b98b3dbe7 100644 --- a/src/detect-parse.c +++ b/src/detect-parse.c @@ -11,6 +11,7 @@ #include "detect-content.h" #include "detect-uricontent.h" +#include "detect-reference.h" #include "flow.h" @@ -683,6 +684,23 @@ Signature *SigAlloc (void) { return sig; } +/** + * \brief Free Reference list + * + * \param s Pointer to the signature + */ +void SigRefFree(Signature *s) { + References *sref = NULL; + if (s == NULL) + return; + + if(s->sigref != NULL) { + for (sref = s->sigref; sref != NULL; sref = sref->next) { + SCFree(sref); + } + } +} + void SigFree(Signature *s) { if (s == NULL) return; @@ -712,6 +730,8 @@ void SigFree(Signature *s) { if (s->msg != NULL) SCFree(s->msg); + SigRefFree(s); + SCFree(s); } diff --git a/src/detect-reference.c b/src/detect-reference.c index 06488226e9..4cc7e75144 100644 --- a/src/detect-reference.c +++ b/src/detect-reference.c @@ -1,33 +1,477 @@ -/* REFERENCE part of the detection engine. */ +/* Copyright (c) 2009 Open Information Security Foundation */ + +/** \file + * \author Breno Silva + */ #include "suricata-common.h" +#include "suricata.h" +#include "detect.h" +#include "detect-parse.h" +#include "detect-engine.h" +#include "detect-engine-mpm.h" + +#include "decode.h" #include "detect.h" +#include "flow-var.h" +#include "decode-events.h" +#include "stream-tcp.h" + +#include "detect-reference.h" + +#include "util-unittest.h" +#include "util-byte.h" +#include "util-debug.h" + +#define PARSE_REGEX "^\\s*(cve|nessus|url|mcafee|bugtraq|arachnids)\\s*,\\s*([a-zA-Z0-9\\-_\\.\\/\\?\\=]+)\\s*" + +/* Static prefix for references - Maybe we should move them to reference.config in the future */ +char REFERENCE_BUGTRAQ[] = "http://www.securityfocus.com/bid/"; +char REFERENCE_CVE[] = "http://cve.mitre.org/cgi-bin/cvename.cgi?name="; +char REFERENCE_NESSUS[] = "http://cgi.nessus.org/plugins/dump.php3?id="; +char REFERENCE_ARACHNIDS[] = "http://www.whitehats.com/info/IDS"; +char REFERENCE_MCAFEE[] = "http://vil.nai.com/vil/dispVirus.asp?virus_k="; +char REFERENCE_URL[] = "http://"; + +static pcre *parse_regex; +static pcre_extra *parse_regex_study; -static int DetectReferenceSetup (DetectEngineCtx *, Signature *, char *); +static int DetectReferenceSetup (DetectEngineCtx *, Signature *s, char *str); + +/** + * \brief Registration function for reference: keyword + */ void DetectReferenceRegister (void) { sigmatch_table[DETECT_REFERENCE].name = "reference"; sigmatch_table[DETECT_REFERENCE].Match = NULL; sigmatch_table[DETECT_REFERENCE].Setup = DetectReferenceSetup; sigmatch_table[DETECT_REFERENCE].Free = NULL; - sigmatch_table[DETECT_REFERENCE].RegisterTests = NULL; + sigmatch_table[DETECT_REFERENCE].RegisterTests = ReferenceRegisterTests; + + const char *eb; + int opts = 0; + int eo; + + parse_regex = pcre_compile(PARSE_REGEX, opts, &eb, &eo, NULL); + if (parse_regex == NULL) + { + SCLogError(SC_ERR_PCRE_COMPILE, "pcre compile of \"%s\" failed at offset %" PRId32 ": %s", PARSE_REGEX, eo, eb); + goto error; + } + + parse_regex_study = pcre_study(parse_regex, 0, &eb); + if (eb != NULL) + { + SCLogError(SC_ERR_PCRE_STUDY, "pcre study failed: %s", eb); + goto error; + } + +error: + return; + } -int DetectReferenceSetup (DetectEngineCtx *de_ctx, Signature *s, char *rawstr) +/** + * \internal + * \brief This function is used to parse reference options passed via reference: keyword + * + * \param rawstr Pointer to the user provided reference options + * + * \retval sigref pointer to signature reference on success + * \retval NULL on failure + */ +static char *DetectReferenceParse (char *rawstr) { - char *str = rawstr; - char dubbed = 0; + DetectReferenceData *ref = NULL; + char *sigref = NULL; +#define MAX_SUBSTRINGS 30 + int ret = 0, res = 0; + int ov[MAX_SUBSTRINGS]; + const char *ref_key = NULL; + const char *ref_content = NULL; + int sig_len = 0; + + ret = pcre_exec(parse_regex, parse_regex_study, rawstr, strlen(rawstr), 0, 0, ov, MAX_SUBSTRINGS); + + if (ret < 2) { + SCLogError(SC_ERR_PCRE_MATCH, "pcre_exec parse error, ret %" PRId32 ", string %s", ret, rawstr); + goto error; + } + + ref = SCMalloc(sizeof(DetectReferenceData)); + if (ref == NULL) { + SCLogError(SC_ERR_MEM_ALLOC, "malloc failed"); + goto error; + } + + memset(ref,0,sizeof(DetectReferenceData)); + + res = pcre_get_substring((char *)rawstr, ov, MAX_SUBSTRINGS,1, &ref_key); + + if (res < 0) { + SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed"); + goto error; + } + + res = pcre_get_substring((char *)rawstr, ov, MAX_SUBSTRINGS,2, &ref_content); + + if (res < 0) { + SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed"); + goto error; + } + + if (ref_key == NULL || ref_content == NULL) + goto error; + + if (strcasecmp(ref_key,"cve") == 0) { + ref->reference = REFERENCE_CVE; + } else if (strcasecmp(ref_key,"bugtraq") == 0) { + ref->reference = REFERENCE_BUGTRAQ; + } else if (strcasecmp(ref_key,"nessus") == 0) { + ref->reference = REFERENCE_NESSUS; + } else if (strcasecmp(ref_key,"url") == 0) { + ref->reference = REFERENCE_URL; + } else if (strcasecmp(ref_key,"mcafee") == 0) { + ref->reference = REFERENCE_MCAFEE; + } else if (strcasecmp(ref_key,"arachnids") == 0) { + ref->reference = REFERENCE_ARACHNIDS; + } + + sig_len = (strlen(ref->reference) + strlen(ref_content)+1); - /* strip "'s */ - if (rawstr[0] == '\"' && rawstr[strlen(rawstr)-1] == '\"') { - str = SCStrdup(rawstr+1); - str[strlen(rawstr)-2] = '\0'; - dubbed = 1; + sigref = SCMalloc(sig_len+1); + if (sigref == NULL) { + SCLogError(SC_ERR_MEM_ALLOC, "malloc failed"); + goto error; } - /* XXX */ + memset(sigref,0,sig_len); + + strlcpy(sigref,ref->reference,strlen(ref->reference)+1); + strlcat(sigref,ref_content,sig_len); + + sigref[strlen(sigref)] = '\0'; + + if (ref) SCFree(ref); + if (ref_key) SCFree((char *)ref_key); + if (ref_content) SCFree((char *)ref_content); + return sigref; + +error: + + if (ref_key) SCFree((char *)ref_key); + if (ref_content) SCFree((char *)ref_content); + if (ref) SCFree(ref); + + return NULL; +} + +/** + * \internal + * \brief this function is used to add the parsed reference into the current signature + * + * \param de_ctx pointer to the Detection Engine Context + * \param s pointer to the Current Signature + * \param m pointer to the Current SigMatch + * \param rawstr pointer to the user provided reference options + * + * \retval 0 on Success + * \retval -1 on Failure + */ +static int DetectReferenceSetup (DetectEngineCtx *de_ctx, Signature *s, char *rawstr) +{ + char *ref = NULL; + References *sref = NULL; + References *actual_reference = NULL; + + ref = DetectReferenceParse(rawstr); + if (ref == NULL) + goto error; + + if(s->sigref == NULL) { + + s->sigref = SCMalloc(sizeof(References)); + if (s->sigref == NULL) { + SCLogError(SC_ERR_MEM_ALLOC, "malloc failed"); + goto error; + } + + s->sigref->reference = ref; + s->sigref->next = NULL; + + } else { + + sref = SCMalloc(sizeof(References)); + if (sref == NULL) { + SCLogError(SC_ERR_MEM_ALLOC, "malloc failed"); + goto error; + } + + sref->reference = ref; + sref->next = NULL; + + actual_reference = s->sigref; + + while (actual_reference->next != NULL) { + actual_reference = actual_reference->next; + } + + actual_reference->next = sref; + } - if (dubbed) SCFree(str); return 0; + +error: + if (ref) SCFree(ref); + if (sref) SCFree(sref); + return -1; +} + +/* + * ONLY TESTS BELOW THIS COMMENT + */ +#ifdef UNITTESTS + +/** + * \test DetectReferenceParseTest01 is a test for one valid reference. + * + * \retval 1 on succces + * \retval 0 on failure + */ +static int DetectReferenceParseTest01(void) +{ + int result = 0; + + uint8_t raw_icmpv4[] = { + 0x08, 0x00, 0x42, 0xb4, 0x02, 0x00, 0x08, 0xa8, + 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, + 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, + 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x61, + 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69}; + Packet p; + Signature *s = NULL; + DecodeThreadVars dtv; + ThreadVars th_v; + DetectEngineThreadCtx *det_ctx = NULL; + IPV4Hdr ip4h; + References *sref = NULL; + + memset(&p, 0, sizeof(Packet)); + memset(&ip4h, 0, sizeof(IPV4Hdr)); + memset(&dtv, 0, sizeof(DecodeThreadVars)); + memset(&th_v, 0, sizeof(ThreadVars)); + + FlowInitConfig(FLOW_QUIET); + + p.src.family = AF_INET; + p.dst.family = AF_INET; + p.src.addr_data32[0] = 0x01020304; + p.dst.addr_data32[0] = 0x04030201; + + ip4h.ip_src.s_addr = p.src.addr_data32[0]; + ip4h.ip_dst.s_addr = p.dst.addr_data32[0]; + p.ip4h = &ip4h; + + DecodeICMPV4(&th_v, &dtv, &p, raw_icmpv4, sizeof(raw_icmpv4), NULL); + + DetectEngineCtx *de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) { + goto end; + } + + de_ctx->flags |= DE_QUIET; + + s = de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any (msg:\"One reference\"; reference:cve,001-2010; sid:2;)"); + + if (s == NULL) { + goto end; + } + + if (s->sigref == NULL) { + goto cleanup; + } + + for (sref = s->sigref; sref != NULL; sref = sref->next) { + if (strcmp(sref->reference,"http://cve.mitre.org/cgi-bin/cvename.cgi?name=001-2010") != 0) { + goto cleanup; + } + } + + result = 1; + +cleanup: + if (s) SigFree(s); + if (det_ctx) DetectEngineCtxFree(de_ctx); + + FlowShutdown(); +end: + return result; + } +/** + * \test DetectReferenceParseTest02 is a test for two valid references. + * + * \retval 1 on succces + * \retval 0 on failure + */ +static int DetectReferenceParseTest02(void) +{ + int result = 0; + + uint8_t raw_icmpv4[] = { + 0x08, 0x00, 0x42, 0xb4, 0x02, 0x00, 0x08, 0xa8, + 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, + 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, + 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x61, + 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69}; + Packet p; + Signature *s = NULL; + DecodeThreadVars dtv; + ThreadVars th_v; + DetectEngineThreadCtx *det_ctx = NULL; + IPV4Hdr ip4h; + References *sref = NULL; + + memset(&p, 0, sizeof(Packet)); + memset(&ip4h, 0, sizeof(IPV4Hdr)); + memset(&dtv, 0, sizeof(DecodeThreadVars)); + memset(&th_v, 0, sizeof(ThreadVars)); + + FlowInitConfig(FLOW_QUIET); + + p.src.family = AF_INET; + p.dst.family = AF_INET; + p.src.addr_data32[0] = 0x01020304; + p.dst.addr_data32[0] = 0x04030201; + + ip4h.ip_src.s_addr = p.src.addr_data32[0]; + ip4h.ip_dst.s_addr = p.dst.addr_data32[0]; + p.ip4h = &ip4h; + + DecodeICMPV4(&th_v, &dtv, &p, raw_icmpv4, sizeof(raw_icmpv4), NULL); + + DetectEngineCtx *de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) { + goto end; + } + + de_ctx->flags |= DE_QUIET; + + s = de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any (msg:\"Two references\"; reference:url,www.openinfosecfoundation.org; reference:cve,001-2010; sid:2;)"); + + if (s == NULL) { + goto end; + } + + if (s->sigref == NULL) { + goto cleanup; + } + + for (sref = s->sigref; sref != NULL; sref = sref->next) { + + if (strcmp(sref->reference,"http://www.openinfosecfoundation.org") == 0) { + result++; + } + + if (strcmp(sref->reference,"http://cve.mitre.org/cgi-bin/cvename.cgi?name=001-2010") == 0) { + result++; + } + } + + if (result == 2) { + result = 1; + } + +cleanup: + if (s) SigFree(s); + if (det_ctx) DetectEngineCtxFree(de_ctx); + + FlowShutdown(); +end: + return result; + +} + +/** + * \test DetectReferenceParseTest03 is a test for one invalid reference. + * + * \retval 1 on succces + * \retval 0 on failure + */ +static int DetectReferenceParseTest03(void) +{ + int result = 0; + + uint8_t raw_icmpv4[] = { + 0x08, 0x00, 0x42, 0xb4, 0x02, 0x00, 0x08, 0xa8, + 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, + 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, + 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x61, + 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69}; + Packet p; + Signature *s = NULL; + DecodeThreadVars dtv; + ThreadVars th_v; + DetectEngineThreadCtx *det_ctx = NULL; + IPV4Hdr ip4h; + References *sref = NULL; + + memset(&p, 0, sizeof(Packet)); + memset(&ip4h, 0, sizeof(IPV4Hdr)); + memset(&dtv, 0, sizeof(DecodeThreadVars)); + memset(&th_v, 0, sizeof(ThreadVars)); + + FlowInitConfig(FLOW_QUIET); + + p.src.family = AF_INET; + p.dst.family = AF_INET; + p.src.addr_data32[0] = 0x01020304; + p.dst.addr_data32[0] = 0x04030201; + + ip4h.ip_src.s_addr = p.src.addr_data32[0]; + ip4h.ip_dst.s_addr = p.dst.addr_data32[0]; + p.ip4h = &ip4h; + + DecodeICMPV4(&th_v, &dtv, &p, raw_icmpv4, sizeof(raw_icmpv4), NULL); + + DetectEngineCtx *de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) { + goto end; + } + + de_ctx->flags |= DE_QUIET; + + s = de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any (msg:\"Two references\"; reference:url,www.openinfosecfoundation.org; reference:oisf,001-2010; sid:2;)"); + + if (s == NULL) { + goto end; + } + + if (s->sigref == NULL) { + goto cleanup; + } + + for (sref = s->sigref; sref != NULL; sref = sref->next) { + result++; + } + +cleanup: + if (s) SigFree(s); + if (det_ctx) DetectEngineCtxFree(de_ctx); + + FlowShutdown(); +end: + return result; + +} +#endif /* UNITTESTS */ + +void ReferenceRegisterTests(void) { +#ifdef UNITTESTS + UtRegisterTest("DetectReferenceParseTest01", DetectReferenceParseTest01, 1); + UtRegisterTest("DetectReferenceParseTest02", DetectReferenceParseTest02, 1); + UtRegisterTest("DetectReferenceParseTest03", DetectReferenceParseTest03, 0); +#endif /* UNITTESTS */ +} diff --git a/src/detect-reference.h b/src/detect-reference.h index 61c6deac77..851cf8c761 100644 --- a/src/detect-reference.h +++ b/src/detect-reference.h @@ -1,8 +1,42 @@ +/* Copyright (c) 2009 Open Information Security Foundation */ + +/** \file + * \author Breno Silva + */ + #ifndef __DETECT_REFERENCE_H__ #define __DETECT_REFERENCE_H__ -/* prototypes */ +#include "decode-events.h" +#include "decode-ipv4.h" +#include "decode-tcp.h" + +/** Signature reference list */ +typedef struct References_ { + char *reference; /**< reference data */ + struct References_ *next; /**< next reference in the signature */ +} References; + +/** + * \typedef DetectReferenceData + * A typedef for DetectReferenceData_ + */ + +typedef struct DetectReferenceData_ { + char *reference; /**< 0 reference prefix 1 - reference data */ +} DetectReferenceData; + + +/** + * Registration function for reference: keyword + */ + void DetectReferenceRegister (void); -#endif /* __DETECT_REFERENCE_H__ */ +/** + * This function registers unit tests for Reference + */ + +void ReferenceRegisterTests(void); +#endif /*__DETECT_REFERENCE_H__ */ diff --git a/src/detect.c b/src/detect.c index 07818771a5..211b863a13 100644 --- a/src/detect.c +++ b/src/detect.c @@ -389,7 +389,7 @@ int PacketAlertCheck(Packet *p, uint32_t sid) } int PacketAlertAppend(Packet *p, uint32_t gid, uint32_t sid, uint8_t rev, - uint8_t prio, char *msg, char *class_msg) + uint8_t prio, char *msg, char *class_msg, References *sigref) { if (p->alerts.cnt == PACKET_ALERT_MAX) return 0; @@ -406,6 +406,7 @@ int PacketAlertAppend(Packet *p, uint32_t gid, uint32_t sid, uint8_t rev, p->alerts.alerts[p->alerts.cnt].prio = prio; p->alerts.alerts[p->alerts.cnt].msg = msg; p->alerts.alerts[p->alerts.cnt].class_msg = class_msg; + p->alerts.alerts[p->alerts.cnt].sigref = sigref; p->alerts.cnt++; return 0; diff --git a/src/detect.h b/src/detect.h index 6fb5394e79..cf362eb0ac 100644 --- a/src/detect.h +++ b/src/detect.h @@ -6,6 +6,7 @@ #include "flow.h" #include "detect-engine-proto.h" +#include "detect-reference.h" #include "packet-queue.h" #include "util-mpm.h" @@ -208,6 +209,9 @@ typedef struct Signature_ { /** classification message */ char *class_msg; + /** Reference */ + References *sigref; + /** addresses, ports and proto this sig matches on */ DetectAddressHead src, dst; DetectProto proto; @@ -660,7 +664,7 @@ int SigGroupCleanup(); void SigAddressPrepareBidirectionals (DetectEngineCtx *); int PacketAlertAppend(Packet *, uint32_t, uint32_t, uint8_t, uint8_t, char *, - char *); + char *, References *); int SigLoadSignatures (DetectEngineCtx *, char *); void SigTableSetup(void); From fe7ece997ae5138f32f5480438188fd835006d89 Mon Sep 17 00:00:00 2001 From: Victor Julien Date: Fri, 16 Apr 2010 11:35:16 +0200 Subject: [PATCH 2/4] Different approach to the reference keyword. Lots of cleanups, bug fixes in reference keyword code and tests. --- src/alert-fastlog.c | 17 +- src/decode.h | 2 +- src/detect-engine-threshold.c | 20 +- src/detect-parse.c | 31 +++- src/detect-reference.c | 334 ++++++++++++---------------------- src/detect-reference.h | 32 ++-- src/detect.c | 4 +- src/detect.h | 4 +- src/util-error.c | 1 + src/util-error.h | 1 + 10 files changed, 182 insertions(+), 264 deletions(-) diff --git a/src/alert-fastlog.c b/src/alert-fastlog.c index fc137ce5a1..418b4a910c 100644 --- a/src/alert-fastlog.c +++ b/src/alert-fastlog.c @@ -101,7 +101,7 @@ TmEcode AlertFastLogIPv4(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq) { AlertFastLogThread *aft = (AlertFastLogThread *)data; int i; - References *sref = NULL; + Reference *ref = NULL; char timebuf[64]; if (p->alerts.cnt == 0) @@ -123,9 +123,10 @@ TmEcode AlertFastLogIPv4(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq) fprintf(aft->file_ctx->fp, "%s [**] [%" PRIu32 ":%" PRIu32 ":%" PRIu32 "] %s [**] [Classification: %s] [Priority: %" PRIu32 "] {%" PRIu32 "} %s:%" PRIu32 " -> %s:%" PRIu32 " ", timebuf, pa->gid, pa->sid, pa->rev, pa->msg, pa->class_msg, pa->prio, IPV4_GET_IPPROTO(p), srcip, p->sp, dstip, p->dp); - if(pa->sigref != NULL) { - for (sref = pa->sigref; sref != NULL; sref = sref->next) { - fprintf(aft->file_ctx->fp,"[Xref => %s]",sref->reference); + + if(pa->references != NULL) { + for (ref = pa->references; ref != NULL; ref = ref->next) { + fprintf(aft->file_ctx->fp,"[Xref => %s%s]", ref->key, ref->reference); } } @@ -142,7 +143,7 @@ TmEcode AlertFastLogIPv6(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq) { AlertFastLogThread *aft = (AlertFastLogThread *)data; int i; - References *sref = NULL; + Reference *ref = NULL; char timebuf[64]; if (p->alerts.cnt == 0) @@ -164,9 +165,9 @@ TmEcode AlertFastLogIPv6(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq) fprintf(aft->file_ctx->fp, "%s [**] [%" PRIu32 ":%" PRIu32 ":%" PRIu32 "] %s [**] [Classification: %s] [Priority: %" PRIu32 "] {%" PRIu32 "} %s:%" PRIu32 " -> %s:%" PRIu32 " ", timebuf, pa->gid, pa->sid, pa->rev, pa->msg, pa->class_msg, pa->prio, IPV6_GET_L4PROTO(p), srcip, p->sp, dstip, p->dp); - if(pa->sigref != NULL) { - for (sref = pa->sigref; sref != NULL; sref = sref->next) { - fprintf(aft->file_ctx->fp,"[Xref => %s]",sref->reference); + if(pa->references != NULL) { + for (ref = pa->references; ref != NULL; ref = ref->next) { + fprintf(aft->file_ctx->fp,"[Xref => %s%s]", ref->key, ref->reference); } } diff --git a/src/decode.h b/src/decode.h index 089f3b75c3..d3f672a142 100644 --- a/src/decode.h +++ b/src/decode.h @@ -172,7 +172,7 @@ typedef struct PacketAlert_ { uint8_t prio; char *msg; char *class_msg; - References *sigref; + Reference *references; } PacketAlert; #define PACKET_ALERT_MAX 256 diff --git a/src/detect-engine-threshold.c b/src/detect-engine-threshold.c index f637735ec0..d152e9c239 100644 --- a/src/detect-engine-threshold.c +++ b/src/detect-engine-threshold.c @@ -53,7 +53,7 @@ void PacketAlertHandle(DetectEngineCtx *de_ctx, Signature *sig, Packet *p) /* if have none just alert, otherwise handle thresholding */ if (td == NULL) { - PacketAlertAppend(p, sig->gid, sig->id, sig->rev, sig->prio, sig->msg, sig->class_msg, sig->sigref); + PacketAlertAppend(p, sig->gid, sig->id, sig->rev, sig->prio, sig->msg, sig->class_msg, sig->references); } else { PacketAlertThreshold(de_ctx, td, p, sig); } @@ -277,20 +277,20 @@ void PacketAlertThreshold(DetectEngineCtx *de_ctx, DetectThresholdData *td, Pack if (lookup_tsh != NULL) { if ((ts.tv_sec - lookup_tsh->tv_sec1) < td->seconds) { if (lookup_tsh->current_count < td->count) { - PacketAlertAppend(p, s->gid, s->id, s->rev, s->prio, s->msg, s->class_msg, s->sigref); + PacketAlertAppend(p, s->gid, s->id, s->rev, s->prio, s->msg, s->class_msg, s->references); } lookup_tsh->current_count++; } else { lookup_tsh->tv_sec1 = ts.tv_sec; lookup_tsh->current_count = 1; - PacketAlertAppend(p, s->gid, s->id, s->rev, s->prio, s->msg, s->class_msg, s->sigref); + PacketAlertAppend(p, s->gid, s->id, s->rev, s->prio, s->msg, s->class_msg, s->references); } } else { ste->tv_sec1 = ts.tv_sec; ste->current_count = 1; - PacketAlertAppend(p, s->gid, s->id, s->rev, s->prio, s->msg, s->class_msg, s->sigref); + PacketAlertAppend(p, s->gid, s->id, s->rev, s->prio, s->msg, s->class_msg, s->references); ThresholdHashAdd(de_ctx, ste, p); ste = NULL; @@ -307,7 +307,7 @@ void PacketAlertThreshold(DetectEngineCtx *de_ctx, DetectThresholdData *td, Pack lookup_tsh->current_count++; if (lookup_tsh->current_count >= td->count) { - PacketAlertAppend(p, s->gid, s->id, s->rev, s->prio, s->msg, s->class_msg, s->sigref); + PacketAlertAppend(p, s->gid, s->id, s->rev, s->prio, s->msg, s->class_msg, s->references); lookup_tsh->current_count = 0; } } else { @@ -319,7 +319,7 @@ void PacketAlertThreshold(DetectEngineCtx *de_ctx, DetectThresholdData *td, Pack ste->tv_sec1 = ts.tv_sec; if (td->count == 1) { - PacketAlertAppend(p, s->gid, s->id, s->rev, s->prio, s->msg, s->class_msg, s->sigref); + PacketAlertAppend(p, s->gid, s->id, s->rev, s->prio, s->msg, s->class_msg, s->references); ste->current_count = 0; } else { ThresholdHashAdd(de_ctx,ste,p); @@ -337,7 +337,7 @@ void PacketAlertThreshold(DetectEngineCtx *de_ctx, DetectThresholdData *td, Pack if ((ts.tv_sec - lookup_tsh->tv_sec1) < td->seconds) { lookup_tsh->current_count++; if (lookup_tsh->current_count == td->count) { - PacketAlertAppend(p, s->gid, s->id, s->rev, s->prio, s->msg, s->class_msg, s->sigref); + PacketAlertAppend(p, s->gid, s->id, s->rev, s->prio, s->msg, s->class_msg, s->references); } } else { lookup_tsh->tv_sec1 = ts.tv_sec; @@ -348,7 +348,7 @@ void PacketAlertThreshold(DetectEngineCtx *de_ctx, DetectThresholdData *td, Pack ste->tv_sec1 = ts.tv_sec; if (td->count == 1) { - PacketAlertAppend(p, s->gid, s->id, s->rev, s->prio, s->msg, s->class_msg, s->sigref); + PacketAlertAppend(p, s->gid, s->id, s->rev, s->prio, s->msg, s->class_msg, s->references); ste->current_count = 0; } else { ThresholdHashAdd(de_ctx,ste,p); @@ -367,7 +367,7 @@ void PacketAlertThreshold(DetectEngineCtx *de_ctx, DetectThresholdData *td, Pack if ((ts.tv_sec - lookup_tsh->tv_sec1) < td->seconds) { lookup_tsh->current_count++; if (lookup_tsh->current_count >= td->count) { - PacketAlertAppend(p, s->gid, s->id, s->rev, s->prio, s->msg, s->class_msg, s->sigref); + PacketAlertAppend(p, s->gid, s->id, s->rev, s->prio, s->msg, s->class_msg, s->references); } } else { lookup_tsh->tv_sec1 = ts.tv_sec; @@ -378,7 +378,7 @@ void PacketAlertThreshold(DetectEngineCtx *de_ctx, DetectThresholdData *td, Pack ste->tv_sec1 = ts.tv_sec; if (td->count == 1) { - PacketAlertAppend(p, s->gid, s->id, s->rev, s->prio, s->msg, s->class_msg, s->sigref); + PacketAlertAppend(p, s->gid, s->id, s->rev, s->prio, s->msg, s->class_msg, s->references); } ThresholdHashAdd(de_ctx, ste, p); ste = NULL; diff --git a/src/detect-parse.c b/src/detect-parse.c index 3b98b3dbe7..66d0757677 100644 --- a/src/detect-parse.c +++ b/src/detect-parse.c @@ -685,20 +685,32 @@ Signature *SigAlloc (void) { } /** + * \internal * \brief Free Reference list * * \param s Pointer to the signature */ -void SigRefFree(Signature *s) { - References *sref = NULL; - if (s == NULL) - return; +static void SigRefFree (Signature *s) { + SCEnter(); - if(s->sigref != NULL) { - for (sref = s->sigref; sref != NULL; sref = sref->next) { - SCFree(sref); - } + Reference *ref = NULL; + Reference *next_ref = NULL; + + if (s == NULL) { + SCReturn; } + + SCLogDebug("s %p, s->references %p", s, s->references); + + for (ref = s->references; ref != NULL;) { + next_ref = ref->next; + DetectReferenceFree(ref); + ref = next_ref; + } + + s->references = NULL; + + SCReturn; } void SigFree(Signature *s) { @@ -728,7 +740,8 @@ void SigFree(Signature *s) { DetectPortCleanupList(s->dp); } - if (s->msg != NULL) SCFree(s->msg); + if (s->msg != NULL) + SCFree(s->msg); SigRefFree(s); diff --git a/src/detect-reference.c b/src/detect-reference.c index 4cc7e75144..55b873b13b 100644 --- a/src/detect-reference.c +++ b/src/detect-reference.c @@ -1,6 +1,7 @@ -/* Copyright (c) 2009 Open Information Security Foundation */ +/* Copyright (c) 2009, 2010 Open Information Security Foundation */ -/** \file +/** + * \file * \author Breno Silva */ @@ -23,7 +24,7 @@ #include "util-byte.h" #include "util-debug.h" -#define PARSE_REGEX "^\\s*(cve|nessus|url|mcafee|bugtraq|arachnids)\\s*,\\s*([a-zA-Z0-9\\-_\\.\\/\\?\\=]+)\\s*" +#define PARSE_REGEX "^\\s*(cve|nessus|url|mcafee|bugtraq|arachnids)\\s*,\"?\\s*\"?\\s*([a-zA-Z0-9\\-_\\.\\/\\?\\=]+)\"?\\s*\"?" /* Static prefix for references - Maybe we should move them to reference.config in the future */ char REFERENCE_BUGTRAQ[] = "http://www.securityfocus.com/bid/"; @@ -53,6 +54,8 @@ void DetectReferenceRegister (void) { int opts = 0; int eo; + opts |= PCRE_CASELESS; + parse_regex = pcre_compile(PARSE_REGEX, opts, &eb, &eo, NULL); if (parse_regex == NULL) { @@ -72,50 +75,61 @@ error: } +/** + * \brief Free a Reference object + */ +void DetectReferenceFree(Reference *ref) { + SCEnter(); + + if (ref->reference != NULL) { + SCFree(ref->reference); + } + SCFree(ref); + + SCReturn; +} + /** * \internal * \brief This function is used to parse reference options passed via reference: keyword * * \param rawstr Pointer to the user provided reference options * - * \retval sigref pointer to signature reference on success + * \retval ref pointer to signature reference on success * \retval NULL on failure */ -static char *DetectReferenceParse (char *rawstr) +static Reference *DetectReferenceParse (char *rawstr) { - DetectReferenceData *ref = NULL; - char *sigref = NULL; + SCEnter(); + + Reference *ref = NULL; + char *str = NULL; #define MAX_SUBSTRINGS 30 int ret = 0, res = 0; int ov[MAX_SUBSTRINGS]; const char *ref_key = NULL; const char *ref_content = NULL; - int sig_len = 0; ret = pcre_exec(parse_regex, parse_regex_study, rawstr, strlen(rawstr), 0, 0, ov, MAX_SUBSTRINGS); - if (ret < 2) { SCLogError(SC_ERR_PCRE_MATCH, "pcre_exec parse error, ret %" PRId32 ", string %s", ret, rawstr); goto error; } - ref = SCMalloc(sizeof(DetectReferenceData)); + ref = SCMalloc(sizeof(Reference)); if (ref == NULL) { - SCLogError(SC_ERR_MEM_ALLOC, "malloc failed"); + SCLogError(SC_ERR_MEM_ALLOC, "malloc failed: %s", strerror(errno)); goto error; } - - memset(ref,0,sizeof(DetectReferenceData)); + memset(ref, 0, sizeof(Reference)); res = pcre_get_substring((char *)rawstr, ov, MAX_SUBSTRINGS,1, &ref_key); - if (res < 0) { SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed"); goto error; } res = pcre_get_substring((char *)rawstr, ov, MAX_SUBSTRINGS,2, &ref_content); - if (res < 0) { SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed"); goto error; @@ -125,46 +139,52 @@ static char *DetectReferenceParse (char *rawstr) goto error; if (strcasecmp(ref_key,"cve") == 0) { - ref->reference = REFERENCE_CVE; + ref->key = REFERENCE_CVE; } else if (strcasecmp(ref_key,"bugtraq") == 0) { - ref->reference = REFERENCE_BUGTRAQ; + ref->key = REFERENCE_BUGTRAQ; } else if (strcasecmp(ref_key,"nessus") == 0) { - ref->reference = REFERENCE_NESSUS; + ref->key = REFERENCE_NESSUS; } else if (strcasecmp(ref_key,"url") == 0) { - ref->reference = REFERENCE_URL; + ref->key = REFERENCE_URL; } else if (strcasecmp(ref_key,"mcafee") == 0) { - ref->reference = REFERENCE_MCAFEE; + ref->key = REFERENCE_MCAFEE; } else if (strcasecmp(ref_key,"arachnids") == 0) { - ref->reference = REFERENCE_ARACHNIDS; + ref->key = REFERENCE_ARACHNIDS; + } else { + SCLogError(SC_ERR_REFERENCE_UNKNOWN, "unknown reference key \"%s\". " + "Supported keys are cve, bugtraq, nessus, url, mcafee, " + "arachnids.", ref_key); + goto error; } - sig_len = (strlen(ref->reference) + strlen(ref_content)+1); - - sigref = SCMalloc(sig_len+1); - if (sigref == NULL) { - SCLogError(SC_ERR_MEM_ALLOC, "malloc failed"); + /* make a copy so we can free pcre's substring */ + str = SCStrdup((char *)ref_content); + if (str == NULL) { + SCLogError(SC_ERR_MEM_ALLOC, "strdup failed: %s", strerror(errno)); goto error; } - memset(sigref,0,sig_len); - - strlcpy(sigref,ref->reference,strlen(ref->reference)+1); - strlcat(sigref,ref_content,sig_len); + ref->reference = str; - sigref[strlen(sigref)] = '\0'; + /* free the substrings */ + pcre_free_substring(ref_key); + pcre_free_substring(ref_content); - if (ref) SCFree(ref); - if (ref_key) SCFree((char *)ref_key); - if (ref_content) SCFree((char *)ref_content); - return sigref; + SCReturnPtr(ref, "Reference"); error: + if (ref_key != NULL) { + pcre_free_substring(ref_key); + } + if (ref_content != NULL) { + pcre_free_substring(ref_content); + } - if (ref_key) SCFree((char *)ref_key); - if (ref_content) SCFree((char *)ref_content); - if (ref) SCFree(ref); + if (ref != NULL) { + DetectReferenceFree(ref); + } - return NULL; + SCReturnPtr(NULL, "Reference"); } /** @@ -181,51 +201,40 @@ error: */ static int DetectReferenceSetup (DetectEngineCtx *de_ctx, Signature *s, char *rawstr) { - char *ref = NULL; - References *sref = NULL; - References *actual_reference = NULL; + SCEnter(); + + Reference *ref = NULL; + Reference *actual_reference = NULL; ref = DetectReferenceParse(rawstr); if (ref == NULL) goto error; - if(s->sigref == NULL) { - - s->sigref = SCMalloc(sizeof(References)); - if (s->sigref == NULL) { - SCLogError(SC_ERR_MEM_ALLOC, "malloc failed"); - goto error; - } - - s->sigref->reference = ref; - s->sigref->next = NULL; + SCLogDebug("ref %s %s", ref->key, ref->reference); + if (s->references == NULL) { + s->references = ref; + ref->next = NULL; } else { - - sref = SCMalloc(sizeof(References)); - if (sref == NULL) { - SCLogError(SC_ERR_MEM_ALLOC, "malloc failed"); - goto error; - } - - sref->reference = ref; - sref->next = NULL; - - actual_reference = s->sigref; + actual_reference = s->references; while (actual_reference->next != NULL) { actual_reference = actual_reference->next; } - actual_reference->next = sref; + actual_reference->next = ref; + ref->next = NULL; } - return 0; + SCLogDebug("s->references %p", s->references); + SCReturnInt(0); error: - if (ref) SCFree(ref); - if (sref) SCFree(sref); - return -1; + if (ref != NULL) { + DetectReferenceFree(ref); + } + + SCReturnInt(-1); } /* @@ -234,7 +243,7 @@ error: #ifdef UNITTESTS /** - * \test DetectReferenceParseTest01 is a test for one valid reference. + * \test one valid reference. * * \retval 1 on succces * \retval 0 on failure @@ -242,42 +251,12 @@ error: static int DetectReferenceParseTest01(void) { int result = 0; - - uint8_t raw_icmpv4[] = { - 0x08, 0x00, 0x42, 0xb4, 0x02, 0x00, 0x08, 0xa8, - 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, - 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, - 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x61, - 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69}; - Packet p; Signature *s = NULL; - DecodeThreadVars dtv; - ThreadVars th_v; - DetectEngineThreadCtx *det_ctx = NULL; - IPV4Hdr ip4h; - References *sref = NULL; - - memset(&p, 0, sizeof(Packet)); - memset(&ip4h, 0, sizeof(IPV4Hdr)); - memset(&dtv, 0, sizeof(DecodeThreadVars)); - memset(&th_v, 0, sizeof(ThreadVars)); - - FlowInitConfig(FLOW_QUIET); - - p.src.family = AF_INET; - p.dst.family = AF_INET; - p.src.addr_data32[0] = 0x01020304; - p.dst.addr_data32[0] = 0x04030201; - - ip4h.ip_src.s_addr = p.src.addr_data32[0]; - ip4h.ip_dst.s_addr = p.dst.addr_data32[0]; - p.ip4h = &ip4h; - - DecodeICMPV4(&th_v, &dtv, &p, raw_icmpv4, sizeof(raw_icmpv4), NULL); + Reference *ref = NULL; DetectEngineCtx *de_ctx = DetectEngineCtxInit(); if (de_ctx == NULL) { - goto end; + goto cleanup; } de_ctx->flags |= DE_QUIET; @@ -285,33 +264,31 @@ static int DetectReferenceParseTest01(void) s = de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any (msg:\"One reference\"; reference:cve,001-2010; sid:2;)"); if (s == NULL) { - goto end; + goto cleanup; } - if (s->sigref == NULL) { + if (s->references == NULL) { goto cleanup; } - for (sref = s->sigref; sref != NULL; sref = sref->next) { - if (strcmp(sref->reference,"http://cve.mitre.org/cgi-bin/cvename.cgi?name=001-2010") != 0) { - goto cleanup; - } + ref = s->references; + if (strcmp(ref->key,"http://cve.mitre.org/cgi-bin/cvename.cgi?name=") != 0 || + strcmp(ref->reference,"001-2010") != 0) { + goto cleanup; } result = 1; cleanup: - if (s) SigFree(s); - if (det_ctx) DetectEngineCtxFree(de_ctx); - - FlowShutdown(); -end: + if (de_ctx != NULL) { + DetectEngineCtxFree(de_ctx); + } return result; } /** - * \test DetectReferenceParseTest02 is a test for two valid references. + * \test for two valid references. * * \retval 1 on succces * \retval 0 on failure @@ -319,83 +296,53 @@ end: static int DetectReferenceParseTest02(void) { int result = 0; - - uint8_t raw_icmpv4[] = { - 0x08, 0x00, 0x42, 0xb4, 0x02, 0x00, 0x08, 0xa8, - 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, - 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, - 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x61, - 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69}; - Packet p; Signature *s = NULL; - DecodeThreadVars dtv; - ThreadVars th_v; - DetectEngineThreadCtx *det_ctx = NULL; - IPV4Hdr ip4h; - References *sref = NULL; - - memset(&p, 0, sizeof(Packet)); - memset(&ip4h, 0, sizeof(IPV4Hdr)); - memset(&dtv, 0, sizeof(DecodeThreadVars)); - memset(&th_v, 0, sizeof(ThreadVars)); - - FlowInitConfig(FLOW_QUIET); - - p.src.family = AF_INET; - p.dst.family = AF_INET; - p.src.addr_data32[0] = 0x01020304; - p.dst.addr_data32[0] = 0x04030201; - - ip4h.ip_src.s_addr = p.src.addr_data32[0]; - ip4h.ip_dst.s_addr = p.dst.addr_data32[0]; - p.ip4h = &ip4h; - - DecodeICMPV4(&th_v, &dtv, &p, raw_icmpv4, sizeof(raw_icmpv4), NULL); DetectEngineCtx *de_ctx = DetectEngineCtxInit(); if (de_ctx == NULL) { - goto end; + goto cleanup; } de_ctx->flags |= DE_QUIET; s = de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any (msg:\"Two references\"; reference:url,www.openinfosecfoundation.org; reference:cve,001-2010; sid:2;)"); - if (s == NULL) { - goto end; + printf("sig parse failed: "); + goto cleanup; } - if (s->sigref == NULL) { + if (s->references == NULL || s->references->next == NULL) { + printf("no ref or not enough refs: "); goto cleanup; } - for (sref = s->sigref; sref != NULL; sref = sref->next) { - - if (strcmp(sref->reference,"http://www.openinfosecfoundation.org") == 0) { - result++; - } + if (strcmp(s->references->key, "http://") != 0 || + strcmp(s->references->reference, "www.openinfosecfoundation.org") != 0) { + printf("first ref failed: "); + goto cleanup; - if (strcmp(sref->reference,"http://cve.mitre.org/cgi-bin/cvename.cgi?name=001-2010") == 0) { - result++; - } } - if (result == 2) { - result = 1; + if (strcmp(s->references->next->key, + "http://cve.mitre.org/cgi-bin/cvename.cgi?name=") != 0 || + strcmp(s->references->next->reference, "001-2010") != 0) { + printf("second ref failed: "); + goto cleanup; + } -cleanup: - if (s) SigFree(s); - if (det_ctx) DetectEngineCtxFree(de_ctx); + result = 1; - FlowShutdown(); -end: +cleanup: + if (de_ctx != NULL) { + DetectEngineCtxFree(de_ctx); + } return result; } /** - * \test DetectReferenceParseTest03 is a test for one invalid reference. + * \test parsing: invalid reference * * \retval 1 on succces * \retval 0 on failure @@ -403,68 +350,27 @@ end: static int DetectReferenceParseTest03(void) { int result = 0; - - uint8_t raw_icmpv4[] = { - 0x08, 0x00, 0x42, 0xb4, 0x02, 0x00, 0x08, 0xa8, - 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, - 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, - 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x61, - 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69}; - Packet p; Signature *s = NULL; - DecodeThreadVars dtv; - ThreadVars th_v; - DetectEngineThreadCtx *det_ctx = NULL; - IPV4Hdr ip4h; - References *sref = NULL; - - memset(&p, 0, sizeof(Packet)); - memset(&ip4h, 0, sizeof(IPV4Hdr)); - memset(&dtv, 0, sizeof(DecodeThreadVars)); - memset(&th_v, 0, sizeof(ThreadVars)); - - FlowInitConfig(FLOW_QUIET); - - p.src.family = AF_INET; - p.dst.family = AF_INET; - p.src.addr_data32[0] = 0x01020304; - p.dst.addr_data32[0] = 0x04030201; - - ip4h.ip_src.s_addr = p.src.addr_data32[0]; - ip4h.ip_dst.s_addr = p.dst.addr_data32[0]; - p.ip4h = &ip4h; - - DecodeICMPV4(&th_v, &dtv, &p, raw_icmpv4, sizeof(raw_icmpv4), NULL); - DetectEngineCtx *de_ctx = DetectEngineCtxInit(); if (de_ctx == NULL) { - goto end; + goto cleanup; } de_ctx->flags |= DE_QUIET; - s = de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any (msg:\"Two references\"; reference:url,www.openinfosecfoundation.org; reference:oisf,001-2010; sid:2;)"); - - if (s == NULL) { - goto end; - } - - if (s->sigref == NULL) { + s = de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any (msg:\"invalid ref\"; reference:unknownkey,001-2010; sid:2;)"); + if (s != NULL) { + printf("sig parsed even though it's invalid: "); goto cleanup; } - for (sref = s->sigref; sref != NULL; sref = sref->next) { - result++; - } - + result = 1; cleanup: - if (s) SigFree(s); - if (det_ctx) DetectEngineCtxFree(de_ctx); + if (de_ctx != NULL) { + DetectEngineCtxFree(de_ctx); + } - FlowShutdown(); -end: return result; - } #endif /* UNITTESTS */ @@ -472,6 +378,6 @@ void ReferenceRegisterTests(void) { #ifdef UNITTESTS UtRegisterTest("DetectReferenceParseTest01", DetectReferenceParseTest01, 1); UtRegisterTest("DetectReferenceParseTest02", DetectReferenceParseTest02, 1); - UtRegisterTest("DetectReferenceParseTest03", DetectReferenceParseTest03, 0); + UtRegisterTest("DetectReferenceParseTest03", DetectReferenceParseTest03, 1); #endif /* UNITTESTS */ } diff --git a/src/detect-reference.h b/src/detect-reference.h index 851cf8c761..21bc79d07c 100644 --- a/src/detect-reference.h +++ b/src/detect-reference.h @@ -1,6 +1,7 @@ -/* Copyright (c) 2009 Open Information Security Foundation */ +/* Copyright (c) 2009, 2010 Open Information Security Foundation */ -/** \file +/** + * \file * \author Breno Silva */ @@ -12,31 +13,26 @@ #include "decode-tcp.h" /** Signature reference list */ -typedef struct References_ { - char *reference; /**< reference data */ - struct References_ *next; /**< next reference in the signature */ -} References; - -/** - * \typedef DetectReferenceData - * A typedef for DetectReferenceData_ - */ - -typedef struct DetectReferenceData_ { - char *reference; /**< 0 reference prefix 1 - reference data */ -} DetectReferenceData; - +typedef struct Reference_ { + char *key; /**< pointer to key */ + char *reference; /**< reference data */ + struct Reference_ *next; /**< next reference in the signature */ +} Reference; /** * Registration function for reference: keyword */ - void DetectReferenceRegister (void); /** * This function registers unit tests for Reference */ - void ReferenceRegisterTests(void); +/** + * Free function for a Reference object + */ +void DetectReferenceFree(Reference *); + #endif /*__DETECT_REFERENCE_H__ */ + diff --git a/src/detect.c b/src/detect.c index 211b863a13..f981739bee 100644 --- a/src/detect.c +++ b/src/detect.c @@ -389,7 +389,7 @@ int PacketAlertCheck(Packet *p, uint32_t sid) } int PacketAlertAppend(Packet *p, uint32_t gid, uint32_t sid, uint8_t rev, - uint8_t prio, char *msg, char *class_msg, References *sigref) + uint8_t prio, char *msg, char *class_msg, Reference *references) { if (p->alerts.cnt == PACKET_ALERT_MAX) return 0; @@ -406,7 +406,7 @@ int PacketAlertAppend(Packet *p, uint32_t gid, uint32_t sid, uint8_t rev, p->alerts.alerts[p->alerts.cnt].prio = prio; p->alerts.alerts[p->alerts.cnt].msg = msg; p->alerts.alerts[p->alerts.cnt].class_msg = class_msg; - p->alerts.alerts[p->alerts.cnt].sigref = sigref; + p->alerts.alerts[p->alerts.cnt].references = references; p->alerts.cnt++; return 0; diff --git a/src/detect.h b/src/detect.h index cf362eb0ac..770bc1cb93 100644 --- a/src/detect.h +++ b/src/detect.h @@ -210,7 +210,7 @@ typedef struct Signature_ { char *class_msg; /** Reference */ - References *sigref; + Reference *references; /** addresses, ports and proto this sig matches on */ DetectAddressHead src, dst; @@ -664,7 +664,7 @@ int SigGroupCleanup(); void SigAddressPrepareBidirectionals (DetectEngineCtx *); int PacketAlertAppend(Packet *, uint32_t, uint32_t, uint8_t, uint8_t, char *, - char *, References *); + char *, Reference *); int SigLoadSignatures (DetectEngineCtx *, char *); void SigTableSetup(void); diff --git a/src/util-error.c b/src/util-error.c index 80ac78c7cb..6d65d1a62a 100644 --- a/src/util-error.c +++ b/src/util-error.c @@ -138,6 +138,7 @@ const char * SCErrorToString(SCError err) CASE_CODE (SC_ERR_LIBNET_WRITE_FAILED); CASE_CODE (SC_ERR_LIBNET_NOT_ENABLED); CASE_CODE (SC_ERR_UNIFIED_LOG_FILE_HEADER); + CASE_CODE (SC_ERR_REFERENCE_UNKNOWN); default: return "UNKNOWN_ERROR"; diff --git a/src/util-error.h b/src/util-error.h index 7d392417ef..cc32e86c78 100644 --- a/src/util-error.h +++ b/src/util-error.h @@ -156,6 +156,7 @@ typedef enum { SC_ERR_UNIFIED_LOG_FILE_HEADER, /**< Error to indicate the unified file header writing function has been failed */ + SC_ERR_REFERENCE_UNKNOWN, /**< unknown reference key (cve, url, etc) */ } SCError; From 2d45a5994a2166679ac7c99757bf6963b192e96b Mon Sep 17 00:00:00 2001 From: Victor Julien Date: Fri, 16 Apr 2010 11:43:49 +0200 Subject: [PATCH 3/4] Fix invalid free in HTP config deinit. --- src/app-layer-htp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app-layer-htp.c b/src/app-layer-htp.c index bc3ae35f48..045c3867bc 100644 --- a/src/app-layer-htp.c +++ b/src/app-layer-htp.c @@ -644,10 +644,10 @@ void HTPFreeConfig(void) SCFree(cfglist.cfg); while (nextrec != NULL) { HTPCfgRec *htprec = nextrec; + nextrec = nextrec->next; SCFree(htprec->cfg); SCFree(htprec); - nextrec = nextrec->next; } SCReturn; } From 47037ef9ecd2a8709929b099c1610762ebca5720 Mon Sep 17 00:00:00 2001 From: Anoop Saldanha Date: Fri, 16 Apr 2010 12:13:15 +0530 Subject: [PATCH 4/4] fix for bug 115 --- src/counters.c | 36 ++++++++++++++ src/counters.h | 1 + src/detect-engine-iponly.c | 6 ++- src/detect-engine-iponly.h | 4 +- src/detect-engine-threshold.c | 30 ++++++------ src/detect-engine-threshold.h | 6 ++- src/detect-engine.c | 3 ++ src/detect.c | 91 +++++++++++++++++++++++++++++------ src/detect.h | 6 ++- 9 files changed, 146 insertions(+), 37 deletions(-) diff --git a/src/counters.c b/src/counters.c index 5fb41f77f3..665255782f 100644 --- a/src/counters.c +++ b/src/counters.c @@ -1536,6 +1536,42 @@ int SCPerfUpdateCounterArray(SCPerfCounterArray *pca, SCPerfContext *pctx, return 1; } +/* + * \brief Get the value of the local copy of the counter that hold this id. + * + * \param id The counter id. + * \param pca Pointer to the SCPerfCounterArray. + * + * \retval 0 on success. + * \retval -1 on error. + */ +double SCPerfGetLocalCounterValue(uint16_t id, SCPerfCounterArray *pca) +{ + if (pca == NULL) { + SCLogDebug("pca NULL inside SCPerfUpdateCounterArray"); + return -1; + } + + if ((id < 1) || (id > pca->size)) { + SCLogDebug("counter doesn't exist"); + return -1; + } + + /* we check the type of the counter. Whether it's a counter that holds an + * unsigned_int_64 value or double value */ + switch (pca->head[id].pc->value->type) { + /* the counter holds an unsigned_int_64 value */ + case SC_PERF_TYPE_UINT64: + return pca->head[id].ui64_cnt; + /* the counter holds a double */ + case SC_PERF_TYPE_DOUBLE: + return pca->head[id].d_cnt; + default: + /* this can never happen */ + return -1; + } +} + /** * \brief The output interface dispatcher for the counter api */ diff --git a/src/counters.h b/src/counters.h index ee6a90886f..ff44a96ee8 100644 --- a/src/counters.h +++ b/src/counters.h @@ -229,6 +229,7 @@ inline void SCPerfCounterSetUI64(uint16_t, SCPerfCounterArray *, uint64_t); inline void SCPerfCounterSetDouble(uint16_t, SCPerfCounterArray *, double); int SCPerfUpdateCounterArray(SCPerfCounterArray *, SCPerfContext *, int); +double SCPerfGetLocalCounterValue(uint16_t, SCPerfCounterArray *); void SCPerfOutputCounters(void); diff --git a/src/detect-engine-iponly.c b/src/detect-engine-iponly.c index 6cb04918c4..9c188403c7 100644 --- a/src/detect-engine-iponly.c +++ b/src/detect-engine-iponly.c @@ -859,7 +859,9 @@ void DetectEngineIPOnlyThreadDeinit(DetectEngineIPOnlyThreadCtx *io_tctx) { * \param io_ctx Pointer to the current ip only thread detection engine * \param p Pointer to the Packet to match against */ -void IPOnlyMatchPacket(DetectEngineCtx *de_ctx, DetectEngineIPOnlyCtx *io_ctx, +void IPOnlyMatchPacket(DetectEngineCtx *de_ctx, + DetectEngineThreadCtx *det_ctx, + DetectEngineIPOnlyCtx *io_ctx, DetectEngineIPOnlyThreadCtx *io_tctx, Packet *p) { SCRadixNode *srcnode = NULL, *dstnode = NULL; @@ -933,7 +935,7 @@ void IPOnlyMatchPacket(DetectEngineCtx *de_ctx, DetectEngineIPOnlyCtx *io_ctx, u * 8 + i, s->id, s->msg); if (!(s->flags & SIG_FLAG_NOALERT)) { - PacketAlertHandle(de_ctx,s,p); + PacketAlertHandle(de_ctx, det_ctx, s, p); /* set verdict on packet */ p->action |= s->action; diff --git a/src/detect-engine-iponly.h b/src/detect-engine-iponly.h index 9704572987..be8086d05c 100644 --- a/src/detect-engine-iponly.h +++ b/src/detect-engine-iponly.h @@ -28,7 +28,9 @@ int IPOnlyCIDRItemParseSingle(IPOnlyCIDRItem *dd, char *str); int IPOnlyCIDRItemSetup(IPOnlyCIDRItem *gh, char *s); void IPOnlyCIDRListPrint(IPOnlyCIDRItem *); -void IPOnlyMatchPacket(DetectEngineCtx *, DetectEngineIPOnlyCtx *, DetectEngineIPOnlyThreadCtx *, Packet *); +void IPOnlyMatchPacket(DetectEngineCtx *, DetectEngineThreadCtx *, + DetectEngineIPOnlyCtx *, DetectEngineIPOnlyThreadCtx *, + Packet *); void IPOnlyInit(DetectEngineCtx *, DetectEngineIPOnlyCtx *); void IPOnlyPrint(DetectEngineCtx *, DetectEngineIPOnlyCtx *); void IPOnlyDeinit(DetectEngineCtx *, DetectEngineIPOnlyCtx *); diff --git a/src/detect-engine-threshold.c b/src/detect-engine-threshold.c index d152e9c239..30d79fb538 100644 --- a/src/detect-engine-threshold.c +++ b/src/detect-engine-threshold.c @@ -42,20 +42,21 @@ * \param p Packet structure * */ -void PacketAlertHandle(DetectEngineCtx *de_ctx, Signature *sig, Packet *p) +void PacketAlertHandle(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, + Signature *s, Packet *p) { SCEnter(); /* retrieve the sig match data */ - DetectThresholdData *td = SigGetThresholdType(sig,p); + DetectThresholdData *td = SigGetThresholdType(s,p); SCLogDebug("td %p", td); /* if have none just alert, otherwise handle thresholding */ if (td == NULL) { - PacketAlertAppend(p, sig->gid, sig->id, sig->rev, sig->prio, sig->msg, sig->class_msg, sig->references); + PacketAlertAppend(det_ctx, s, p); } else { - PacketAlertThreshold(de_ctx, td, p, sig); + PacketAlertThreshold(de_ctx, det_ctx, td, p, s); } SCReturn; @@ -224,7 +225,8 @@ void ThresholdHashAdd(DetectEngineCtx *de_ctx, DetectThresholdEntry *tsh_ptr, Pa * \param s Signature structure * */ -void PacketAlertThreshold(DetectEngineCtx *de_ctx, DetectThresholdData *td, Packet *p, Signature *s) +void PacketAlertThreshold(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, + DetectThresholdData *td, Packet *p, Signature *s) { SCEnter(); @@ -277,20 +279,20 @@ void PacketAlertThreshold(DetectEngineCtx *de_ctx, DetectThresholdData *td, Pack if (lookup_tsh != NULL) { if ((ts.tv_sec - lookup_tsh->tv_sec1) < td->seconds) { if (lookup_tsh->current_count < td->count) { - PacketAlertAppend(p, s->gid, s->id, s->rev, s->prio, s->msg, s->class_msg, s->references); + PacketAlertAppend(det_ctx, s, p); } lookup_tsh->current_count++; } else { lookup_tsh->tv_sec1 = ts.tv_sec; lookup_tsh->current_count = 1; - PacketAlertAppend(p, s->gid, s->id, s->rev, s->prio, s->msg, s->class_msg, s->references); + PacketAlertAppend(det_ctx, s, p); } } else { ste->tv_sec1 = ts.tv_sec; ste->current_count = 1; - PacketAlertAppend(p, s->gid, s->id, s->rev, s->prio, s->msg, s->class_msg, s->references); + PacketAlertAppend(det_ctx, s, p); ThresholdHashAdd(de_ctx, ste, p); ste = NULL; @@ -307,7 +309,7 @@ void PacketAlertThreshold(DetectEngineCtx *de_ctx, DetectThresholdData *td, Pack lookup_tsh->current_count++; if (lookup_tsh->current_count >= td->count) { - PacketAlertAppend(p, s->gid, s->id, s->rev, s->prio, s->msg, s->class_msg, s->references); + PacketAlertAppend(det_ctx, s, p); lookup_tsh->current_count = 0; } } else { @@ -319,7 +321,7 @@ void PacketAlertThreshold(DetectEngineCtx *de_ctx, DetectThresholdData *td, Pack ste->tv_sec1 = ts.tv_sec; if (td->count == 1) { - PacketAlertAppend(p, s->gid, s->id, s->rev, s->prio, s->msg, s->class_msg, s->references); + PacketAlertAppend(det_ctx, s, p); ste->current_count = 0; } else { ThresholdHashAdd(de_ctx,ste,p); @@ -337,7 +339,7 @@ void PacketAlertThreshold(DetectEngineCtx *de_ctx, DetectThresholdData *td, Pack if ((ts.tv_sec - lookup_tsh->tv_sec1) < td->seconds) { lookup_tsh->current_count++; if (lookup_tsh->current_count == td->count) { - PacketAlertAppend(p, s->gid, s->id, s->rev, s->prio, s->msg, s->class_msg, s->references); + PacketAlertAppend(det_ctx, s, p); } } else { lookup_tsh->tv_sec1 = ts.tv_sec; @@ -348,7 +350,7 @@ void PacketAlertThreshold(DetectEngineCtx *de_ctx, DetectThresholdData *td, Pack ste->tv_sec1 = ts.tv_sec; if (td->count == 1) { - PacketAlertAppend(p, s->gid, s->id, s->rev, s->prio, s->msg, s->class_msg, s->references); + PacketAlertAppend(det_ctx, s, p); ste->current_count = 0; } else { ThresholdHashAdd(de_ctx,ste,p); @@ -367,7 +369,7 @@ void PacketAlertThreshold(DetectEngineCtx *de_ctx, DetectThresholdData *td, Pack if ((ts.tv_sec - lookup_tsh->tv_sec1) < td->seconds) { lookup_tsh->current_count++; if (lookup_tsh->current_count >= td->count) { - PacketAlertAppend(p, s->gid, s->id, s->rev, s->prio, s->msg, s->class_msg, s->references); + PacketAlertAppend(det_ctx, s, p); } } else { lookup_tsh->tv_sec1 = ts.tv_sec; @@ -378,7 +380,7 @@ void PacketAlertThreshold(DetectEngineCtx *de_ctx, DetectThresholdData *td, Pack ste->tv_sec1 = ts.tv_sec; if (td->count == 1) { - PacketAlertAppend(p, s->gid, s->id, s->rev, s->prio, s->msg, s->class_msg, s->references); + PacketAlertAppend(det_ctx, s, p); } ThresholdHashAdd(de_ctx, ste, p); ste = NULL; diff --git a/src/detect-engine-threshold.h b/src/detect-engine-threshold.h index 6fcf013acc..1e72e051d7 100644 --- a/src/detect-engine-threshold.h +++ b/src/detect-engine-threshold.h @@ -12,9 +12,11 @@ #define THRESHOLD_HASH_SIZE 0xffff -void PacketAlertHandle(DetectEngineCtx *de_ctx, Signature *sig, Packet *p); +void PacketAlertHandle(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *, + Signature *sig, Packet *p); DetectThresholdData *SigGetThresholdType(Signature *, Packet *); -void PacketAlertThreshold(DetectEngineCtx *,DetectThresholdData *, Packet *, Signature *); +void PacketAlertThreshold(DetectEngineCtx *, DetectEngineThreadCtx *, + DetectThresholdData *, Packet *, Signature *); void ThresholdFreeFunc(void *data); char ThresholdCompareFunc(void *data1, uint16_t len1, void *data2,uint16_t len2); uint32_t ThresholdHashFunc(HashListTable *ht, void *data, uint16_t datalen); diff --git a/src/detect-engine.c b/src/detect-engine.c index c0c3b6f6a5..1785f655a2 100644 --- a/src/detect-engine.c +++ b/src/detect-engine.c @@ -437,6 +437,9 @@ TmEcode DetectEngineThreadCtxInit(ThreadVars *tv, void *initdata, void **data) { tv->sc_perf_pca = SCPerfGetAllCountersArray(&tv->sc_perf_pctx); SCPerfAddToClubbedTMTable(tv->name, &tv->sc_perf_pctx); + /* this detection engine context belongs to this thread instance */ + det_ctx->tv = tv; + *data = (void *)det_ctx; #ifdef __SC_CUDA_SUPPORT__ diff --git a/src/detect.c b/src/detect.c index f981739bee..2e933dddfd 100644 --- a/src/detect.c +++ b/src/detect.c @@ -388,27 +388,28 @@ int PacketAlertCheck(Packet *p, uint32_t sid) return match; } -int PacketAlertAppend(Packet *p, uint32_t gid, uint32_t sid, uint8_t rev, - uint8_t prio, char *msg, char *class_msg, Reference *references) +int PacketAlertAppend(DetectEngineThreadCtx *det_ctx, Signature *s, Packet *p) { if (p->alerts.cnt == PACKET_ALERT_MAX) return 0; - SCLogDebug("sid %"PRIu32"", sid); + SCLogDebug("sid %"PRIu32"", s->id); - if (gid > 1) - p->alerts.alerts[p->alerts.cnt].gid = gid; + if (s->gid > 1) + p->alerts.alerts[p->alerts.cnt].gid = s->gid; else p->alerts.alerts[p->alerts.cnt].gid = 1; - p->alerts.alerts[p->alerts.cnt].sid = sid; - p->alerts.alerts[p->alerts.cnt].rev = rev; - p->alerts.alerts[p->alerts.cnt].prio = prio; - p->alerts.alerts[p->alerts.cnt].msg = msg; - p->alerts.alerts[p->alerts.cnt].class_msg = class_msg; - p->alerts.alerts[p->alerts.cnt].references = references; + p->alerts.alerts[p->alerts.cnt].sid = s->id; + p->alerts.alerts[p->alerts.cnt].rev = s->rev; + p->alerts.alerts[p->alerts.cnt].prio = s->prio; + p->alerts.alerts[p->alerts.cnt].msg = s->msg; + p->alerts.alerts[p->alerts.cnt].class_msg = s->class_msg; + p->alerts.alerts[p->alerts.cnt].references = s->references; p->alerts.cnt++; + SCPerfCounterIncr(det_ctx->counter_alerts, det_ctx->tv->sc_perf_pca); + return 0; } @@ -507,7 +508,7 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh (p->flowflags & FLOW_PKT_TOCLIENT && !(p->flowflags & FLOW_PKT_TOCLIENT_IPONLY_SET))) { SCLogDebug("testing against \"ip-only\" signatures"); - IPOnlyMatchPacket(de_ctx, &de_ctx->io_ctx, &det_ctx->io_ctx, p); + IPOnlyMatchPacket(de_ctx, det_ctx, &de_ctx->io_ctx, &det_ctx->io_ctx, p); /* save in the flow that we scanned this direction... locking is * done in the FlowSetIPOnlyFlag function. */ if (p->flow != NULL) { @@ -521,7 +522,7 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh if (p->flow->flags & FLOW_ACTION_DROP) p->action |= ACTION_DROP; } else { /* Even without flow we should match the packet src/dst */ - IPOnlyMatchPacket(de_ctx, &de_ctx->io_ctx, &det_ctx->io_ctx, p); + IPOnlyMatchPacket(de_ctx, det_ctx, &de_ctx->io_ctx, &det_ctx->io_ctx, p); } /* we assume we have an uri when we start inspection */ @@ -681,7 +682,7 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh fmatch = 1; if (!(s->flags & SIG_FLAG_NOALERT)) { - PacketAlertHandle(de_ctx,s,p); + PacketAlertHandle(de_ctx, det_ctx, s, p); /* set verdict on packet */ p->action |= s->action; } @@ -719,7 +720,7 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh if (!(s->flags & SIG_FLAG_NOALERT)) { /* only add once */ if (rmatch == 0) { - PacketAlertHandle(de_ctx,s,p); + PacketAlertHandle(de_ctx, det_ctx, s, p); /* set verdict on packet */ p->action |= s->action; } @@ -765,7 +766,7 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh if (!(s->flags & SIG_FLAG_NOALERT)) { /* set flowbit for this match */ - PacketAlertHandle(de_ctx,s,p); + PacketAlertHandle(de_ctx, det_ctx, s, p); /* set verdict on packet */ p->action |= s->action; @@ -8463,6 +8464,62 @@ static int SigTestDepthOffset01Wm (void) { return SigTestDepthOffset01Real(MPM_WUMANBER); } +static int SigTestDetectAlertCounter(void) +{ + Packet p; + ThreadVars tv; + DetectEngineThreadCtx *det_ctx = NULL; + int result = 0; + + memset(&tv, 0, sizeof(tv)); + DetectEngineCtx *de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) { + goto end; + } + + de_ctx->mpm_matcher = MPM_B2G; + de_ctx->flags |= DE_QUIET; + + de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any (msg:\"Test counter\"; " + "content:\"boo\"; sid:1;)"); + if (de_ctx->sig_list == NULL) { + goto end; + } + + SigGroupBuild(de_ctx); + tv.name = "detect_test"; + DetectEngineThreadCtxInit(&tv, de_ctx, (void *)&det_ctx); + + memset(&p, 0, sizeof(p)); + p.src.family = AF_INET; + p.dst.family = AF_INET; + p.payload = (uint8_t *)"boo"; + p.payload_len = strlen((char *)p.payload); + p.proto = IPPROTO_TCP; + Detect(&tv, &p, det_ctx, NULL); + result = (SCPerfGetLocalCounterValue(det_ctx->counter_alerts, tv.sc_perf_pca) == 1); + + Detect(&tv, &p, det_ctx, NULL); + result &= (SCPerfGetLocalCounterValue(det_ctx->counter_alerts, tv.sc_perf_pca) == 2); + + p.payload = (uint8_t *)"roo"; + p.payload_len = strlen((char *)p.payload); + Detect(&tv, &p, det_ctx, NULL); + result &= (SCPerfGetLocalCounterValue(det_ctx->counter_alerts, tv.sc_perf_pca) == 2); + + p.payload = (uint8_t *)"laboosa"; + p.payload_len = strlen((char *)p.payload); + Detect(&tv, &p, det_ctx, NULL); + result &= (SCPerfGetLocalCounterValue(det_ctx->counter_alerts, tv.sc_perf_pca) == 3); + +end: + SigGroupCleanup(de_ctx); + SigCleanSignatures(de_ctx); + + DetectEngineThreadCtxDeinit(&tv, (void *)det_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} #endif /* UNITTESTS */ @@ -8664,6 +8721,8 @@ void SigRegisterTests(void) { UtRegisterTest("SigTestDepthOffset01B3g", SigTestDepthOffset01B3g, 1); UtRegisterTest("SigTestDepthOffset01Wm", SigTestDepthOffset01Wm, 1); + UtRegisterTest("SigTestDetectAlertCounter", SigTestDetectAlertCounter, 1); + #endif /* UNITTESTS */ } diff --git a/src/detect.h b/src/detect.h index 770bc1cb93..006a7fde87 100644 --- a/src/detect.h +++ b/src/detect.h @@ -415,6 +415,9 @@ enum { * Detection engine thread data. */ typedef struct DetectionEngineThreadCtx_ { + /* the thread to which this detection engine thread belongs */ + ThreadVars *tv; + /* detection engine variables */ /** offset into the payload of the last match by: @@ -663,8 +666,7 @@ int SigGroupBuild(DetectEngineCtx *); int SigGroupCleanup(); void SigAddressPrepareBidirectionals (DetectEngineCtx *); -int PacketAlertAppend(Packet *, uint32_t, uint32_t, uint8_t, uint8_t, char *, - char *, Reference *); +int PacketAlertAppend(DetectEngineThreadCtx *, Signature *s, Packet *); int SigLoadSignatures (DetectEngineCtx *, char *); void SigTableSetup(void);