From: Eric Leblond Date: Wed, 14 Dec 2016 16:59:23 +0000 (+0100) Subject: detect-metadata: store metadata key value pairs X-Git-Tag: suricata-4.1.0-beta1~244 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=474fc60671d90c2fe6f960cef7e9ef50848071df;p=thirdparty%2Fsuricata.git detect-metadata: store metadata key value pairs This patch updates the Signature structure so it contains the metadata under a key value form. Later patch will make that dictionary available in the events. --- diff --git a/src/detect-metadata.c b/src/detect-metadata.c index 87d4d745f7..ae61735c39 100644 --- a/src/detect-metadata.c +++ b/src/detect-metadata.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2007-2010 Open Information Security Foundation +/* Copyright (C) 2007-2017 Open Information Security Foundation * * You can copy, redistribute or modify this Program under the terms of * the GNU General Public License version 2 as published by the Free @@ -28,23 +28,148 @@ #include "suricata-common.h" #include "detect.h" +#include "detect-parse.h" #include "detect-metadata.h" +#define PARSE_REGEX "^\\s*([^\\s]+)\\s+([^\\s]+)(?:,\\s*([^\\s]+)\\s+([^\\s]+))*$" +#define PARSE_TAG_REGEX "\\s*([^\\s]+)\\s+([^,]+)\\s*" + +static pcre *parse_regex; +static pcre_extra *parse_regex_study; +static pcre *parse_tag_regex; +static pcre_extra *parse_tag_regex_study; + static int DetectMetadataSetup (DetectEngineCtx *, Signature *, const char *); void DetectMetadataRegister (void) { sigmatch_table[DETECT_METADATA].name = "metadata"; - sigmatch_table[DETECT_METADATA].desc = "ignored by suricata"; + sigmatch_table[DETECT_METADATA].desc = "used by suricata for logging"; sigmatch_table[DETECT_METADATA].url = DOC_URL DOC_VERSION "/rules/meta.html#metadata"; sigmatch_table[DETECT_METADATA].Match = NULL; sigmatch_table[DETECT_METADATA].Setup = DetectMetadataSetup; sigmatch_table[DETECT_METADATA].Free = NULL; sigmatch_table[DETECT_METADATA].RegisterTests = NULL; + + DetectSetupParseRegexes(PARSE_REGEX, &parse_regex, &parse_regex_study); + DetectSetupParseRegexes(PARSE_TAG_REGEX, &parse_tag_regex, &parse_tag_regex_study); +} + +/** + * \brief Free a Metadata object + */ +void DetectMetadataFree(DetectMetadata *mdata) +{ + SCEnter(); + + if (mdata->key != NULL) { + SCFree((void *)mdata->key); + } + if (mdata->value != NULL) { + SCFree((void *)mdata->value); + } + SCFree(mdata); + + SCReturn; +} + +static int DetectMetadataParse(Signature *s, const char *metadatastr) +{ +#define MAX_SUBSTRINGS 30 + int ret = 0, res = 0; + int ov[MAX_SUBSTRINGS]; + + ret = pcre_exec(parse_regex, parse_regex_study, metadatastr, + strlen(metadatastr), 0, 0, ov, MAX_SUBSTRINGS); + if (ret < 2) { + /* Only warn user that the metadata are not parsed due + * to invalid format */ + SCLogInfo("signature metadata not in key value format, ret %" PRId32 + ", string %s", ret, metadatastr); + return 0; + } + + char *saveptr = NULL; + size_t metadatalen = strlen(metadatastr)+1; + char rawstr[metadatalen]; + strlcpy(rawstr, metadatastr, metadatalen); + char * kv = strtok_r(rawstr, ",", &saveptr); + const char *key = NULL; + const char *value = NULL; + char pkey[256]; + char pvalue[256]; + + /* now check key value */ + do { + DetectMetadata *dkv; + + ret = pcre_exec(parse_tag_regex, parse_tag_regex_study, kv, strlen(kv), 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; + } + + res = pcre_copy_substring(kv, ov, MAX_SUBSTRINGS, 1, pkey, sizeof(pkey)); + if (res < 0) { + SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_copy_substring failed"); + goto error; + } + key = SCStrdup(pkey); + if (key == NULL) { + SCLogError(SC_ERR_MEM_ALLOC, "can't create metadata key"); + goto error; + } + + res = pcre_copy_substring(kv, ov, MAX_SUBSTRINGS, 2, pvalue, sizeof(pvalue)); + if (res < 0) { + SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_copy_substring failed"); + goto error; + } + value = SCStrdup(pvalue); + if (value == NULL) { + SCLogError(SC_ERR_MEM_ALLOC, "can't create metadata value"); + goto error; + } + + SCLogDebug("key: %s, value: %s", key, value); + + dkv = SCMalloc(sizeof(DetectMetadata)); + if (dkv) { + dkv->key = key; + if (!dkv->key) { + SCFree(dkv); + } else { + dkv->value = value; + if (!dkv->value) { + SCFree((void *)dkv->key); + SCFree(dkv); + } else { + dkv->next = s->metadata; + s->metadata = dkv; + } + } + } else { + goto error; + } + + kv = strtok_r(NULL, ",", &saveptr); + } while (kv); + + return 0; + +error: + if (key) + SCFree((void *)key); + if (value) + SCFree((void *)value); + return -1; } -static int DetectMetadataSetup (DetectEngineCtx *de_ctx, Signature *s, const char *rawstr) +static int DetectMetadataSetup(DetectEngineCtx *de_ctx, Signature *s, const char *rawstr) { + DetectMetadataParse(s, rawstr); + return 0; } diff --git a/src/detect-metadata.h b/src/detect-metadata.h index bcb4c01c5e..c7ab33d8fa 100644 --- a/src/detect-metadata.h +++ b/src/detect-metadata.h @@ -24,8 +24,22 @@ #ifndef __DETECT_METADATA_H__ #define __DETECT_METADATA_H__ +/** + * \brief Signature metadata list. + */ +typedef struct DetectMetadata_ { + /* pointer to key */ + const char *key; + /* value data */ + const char *value; + /* next reference in the signature */ + struct DetectMetadata_ *next; +} DetectMetadata; + /* prototypes */ void DetectMetadataRegister (void); +void DetectMetadataFree(DetectMetadata *mdata); + #endif /* __DETECT_METADATA_H__ */ diff --git a/src/detect-parse.c b/src/detect-parse.c index c24c1cf88d..b7e2ac4add 100644 --- a/src/detect-parse.c +++ b/src/detect-parse.c @@ -1184,6 +1184,36 @@ Signature *SigAlloc (void) return sig; } +/** + * \internal + * \brief Free Medadata list + * + * \param s Pointer to the signature + */ +static void SigMetadataFree(Signature *s) +{ + SCEnter(); + + DetectMetadata *mdata = NULL; + DetectMetadata *next_mdata = NULL; + + if (s == NULL) { + SCReturn; + } + + SCLogDebug("s %p, s->metadata %p", s, s->metadata); + + for (mdata = s->metadata; mdata != NULL;) { + next_mdata = mdata->next; + DetectMetadataFree(mdata); + mdata = next_mdata; + } + + s->metadata = NULL; + + SCReturn; +} + /** * \internal * \brief Free Reference list @@ -1294,6 +1324,7 @@ void SigFree(Signature *s) } SigRefFree(s); + SigMetadataFree(s); DetectEngineAppInspectionEngineSignatureFree(s); diff --git a/src/detect.h b/src/detect.h index f4bf189da5..9d86f23633 100644 --- a/src/detect.h +++ b/src/detect.h @@ -30,6 +30,7 @@ #include "detect-engine-proto.h" #include "detect-reference.h" +#include "detect-metadata.h" #include "packet-queue.h" #include "util-prefilter.h" @@ -457,6 +458,8 @@ typedef struct Signature_ { char *class_msg; /** Reference */ DetectReference *references; + /** Metadata */ + DetectMetadata *metadata; /* Be careful, this pointer is only valid while parsing the sig, * to warn the user about any possible problem */