]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
detect-metadata: store metadata key value pairs
authorEric Leblond <eric@regit.org>
Wed, 14 Dec 2016 16:59:23 +0000 (17:59 +0100)
committerJason Ish <ish@unx.ca>
Tue, 30 Jan 2018 19:23:48 +0000 (13:23 -0600)
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.

src/detect-metadata.c
src/detect-metadata.h
src/detect-parse.c
src/detect.h

index 87d4d745f743c972727157d4e88219007b5600ae..ae61735c39a9584b36ae4a84dbecaac6ef404671 100644 (file)
@@ -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
 
 #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;
 }
 
index bcb4c01c5e8b336e8a3bbc71cfc8bcd4cb50a406..c7ab33d8fa168692fd72b6972589915df7867f6c 100644 (file)
 #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__ */
 
index c24c1cf88d38050abea5911d4f28c9d236b2290b..b7e2ac4adda5437ddb72988dac7729397cca5900 100644 (file)
@@ -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);
 
index f4bf189da5db4ce7bc6d00f0599056fab9d1e32a..9d86f236335da4fac58a1af79a644ecbde3e6dc6 100644 (file)
@@ -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 */