]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
output-json-dns: add new configuration
authorGiuseppe Longo <glongo@stamus-networks.com>
Tue, 28 Nov 2017 08:51:48 +0000 (09:51 +0100)
committerVictor Julien <victor@inliniac.net>
Wed, 14 Mar 2018 21:29:39 +0000 (22:29 +0100)
This patch adds a new configuration for dns,
introducing a "version" that permits to switch
between the new and old format to provide
backward compatibility.

The new configuration is made up of these new fields:
- version
- requests (query)
- response (answer)
- types (custom)

src/output-json-dns.c
suricata.yaml.in

index 8920b1b2886d6e728eebb4f567719adaf811d26a..1ab31e66a90be03676adf51a671e707093787d74 100644 (file)
@@ -187,6 +187,11 @@ typedef enum {
     DNS_RRTYPE_MAX,
 } DnsRRTypes;
 
+typedef enum {
+    DNS_VERSION_1 = 1,
+    DNS_VERSION_2
+} DnsVersion;
+
 static struct {
     const char *config_rrtype;
     uint64_t flags;
@@ -255,6 +260,7 @@ typedef struct LogDnsFileCtx_ {
     LogFileCtx *file_ctx;
     uint64_t flags; /** Store mode */
     bool include_metadata;
+    DnsVersion version;
 } LogDnsFileCtx;
 
 typedef struct LogDnsLogThread_ {
@@ -816,54 +822,107 @@ static void LogDnsLogDeInitCtxSub(OutputCtx *output_ctx)
     SCFree(output_ctx);
 }
 
-static void JsonDnsLogInitFilters(LogDnsFileCtx *dnslog_ctx, ConfNode *conf)
+static void JsonDnsLogParseConfig(LogDnsFileCtx *dnslog_ctx, ConfNode *conf,
+                                  const char *query_key, const char *answer_key,
+                                  const char *answer_types_key)
 {
-    dnslog_ctx->flags = ~0UL;
+    const char *query = ConfNodeLookupChildValue(conf, query_key);
+    if (query != NULL) {
+        if (ConfValIsTrue(query)) {
+            dnslog_ctx->flags |= LOG_QUERIES;
+        } else {
+            dnslog_ctx->flags &= ~LOG_QUERIES;
+        }
+    } else {
+        if (dnslog_ctx->version == DNS_VERSION_2) {
+            dnslog_ctx->flags |= LOG_QUERIES;
+        }
+    }
 
-    if (conf) {
-        const char *query = ConfNodeLookupChildValue(conf, "query");
-        if (query != NULL) {
-            if (ConfValIsTrue(query)) {
-                dnslog_ctx->flags |= LOG_QUERIES;
-            } else {
-                dnslog_ctx->flags &= ~LOG_QUERIES;
-            }
+    const char *response = ConfNodeLookupChildValue(conf, answer_key);
+    if (response != NULL) {
+        if (ConfValIsTrue(response)) {
+            dnslog_ctx->flags |= LOG_ANSWERS;
+        } else {
+            dnslog_ctx->flags &= ~LOG_ANSWERS;
         }
-        const char *response = ConfNodeLookupChildValue(conf, "answer");
-        if (response != NULL) {
-            if (ConfValIsTrue(response)) {
-                dnslog_ctx->flags |= LOG_ANSWERS;
-            } else {
-                dnslog_ctx->flags &= ~LOG_ANSWERS;
-            }
+    } else {
+        if (dnslog_ctx->version == DNS_VERSION_2) {
+            dnslog_ctx->flags |= LOG_ANSWERS;
         }
-        ConfNode *custom;
-        if ((custom = ConfNodeLookupChild(conf, "custom")) != NULL) {
-            dnslog_ctx->flags &= ~LOG_ALL_RRTYPES;
-            ConfNode *field;
-            TAILQ_FOREACH(field, &custom->head, next)
+    }
+
+    ConfNode *custom;
+    if ((custom = ConfNodeLookupChild(conf, answer_types_key)) != NULL) {
+        dnslog_ctx->flags &= ~LOG_ALL_RRTYPES;
+        ConfNode *field;
+        TAILQ_FOREACH(field, &custom->head, next)
+        {
+            if (field != NULL)
             {
-                if (field != NULL)
+                DnsRRTypes f;
+                for (f = DNS_RRTYPE_A; f < DNS_RRTYPE_MAX; f++)
                 {
-                    DnsRRTypes f;
-                    for (f = DNS_RRTYPE_A; f < DNS_RRTYPE_MAX; f++)
+                    if (strcasecmp(dns_rrtype_fields[f].config_rrtype,
+                                   field->val) == 0)
                     {
-                        if (strcasecmp(dns_rrtype_fields[f].config_rrtype,
-                                       field->val) == 0)
-                        {
-                            dnslog_ctx->flags |= dns_rrtype_fields[f].flags;
-                            break;
-                        }
+                        dnslog_ctx->flags |= dns_rrtype_fields[f].flags;
+                        break;
                     }
                 }
             }
         }
+    } else {
+        if (dnslog_ctx->version == DNS_VERSION_2) {
+            dnslog_ctx->flags |= LOG_ALL_RRTYPES;
+        }
+    }
+}
+
+static void JsonDnsLogInitFilters(LogDnsFileCtx *dnslog_ctx, ConfNode *conf)
+{
+    dnslog_ctx->flags = ~0UL;
+
+    if (conf) {
+        intmax_t version;
+        int ret = ConfGetChildValueInt(conf, "version", &version);
+        if (ret) {
+            switch(version) {
+                case 1:
+                    dnslog_ctx->version = DNS_VERSION_1;
+                    break;
+                case 2:
+                    dnslog_ctx->version = DNS_VERSION_2;
+                    break;
+                default:
+                    SCLogWarning(SC_ERR_INVALID_ARGUMENT,
+                                 "Invalid version option: %ji, "
+                                 "forcing it to version 1", version);
+                    dnslog_ctx->version = DNS_VERSION_1;
+                    break;
+            }
+        } else {
+            SCLogWarning(SC_ERR_INVALID_ARGUMENT,
+                         "Version not found, forcing it to version 1");
+            dnslog_ctx->version = DNS_VERSION_1;
+        }
+
+        if (dnslog_ctx->version == DNS_VERSION_1) {
+            JsonDnsLogParseConfig(dnslog_ctx, conf, "query", "answer", "custom");
+        } else {
+            JsonDnsLogParseConfig(dnslog_ctx, conf, "requests", "responses", "types");
+        }
     }
 }
 
 static OutputInitResult JsonDnsLogInitCtxSub(ConfNode *conf, OutputCtx *parent_ctx)
 {
     OutputInitResult result = { NULL, false };
+    const char *enabled = ConfNodeLookupChildValue(conf, "enabled");
+    if (enabled != NULL && !ConfValIsTrue(enabled)) {
+        return result;
+    }
+
     OutputJsonCtx *ojc = parent_ctx->data;
 
     LogDnsFileCtx *dnslog_ctx = SCMalloc(sizeof(LogDnsFileCtx));
@@ -904,6 +963,11 @@ static OutputInitResult JsonDnsLogInitCtxSub(ConfNode *conf, OutputCtx *parent_c
 static OutputInitResult JsonDnsLogInitCtx(ConfNode *conf)
 {
     OutputInitResult result = { NULL, false };
+    const char *enabled = ConfNodeLookupChildValue(conf, "enabled");
+    if (enabled != NULL && !ConfValIsTrue(enabled)) {
+        return result;
+    }
+
     LogFileCtx *file_ctx = LogFileNewCtx();
 
     if(file_ctx == NULL) {
index e5fcd0cd783ad816559ffcf38d0228de4c7bb22a..2f57336967e251e891b563181c008cf9da6c85a5 100644 (file)
@@ -205,13 +205,35 @@ outputs:
             # the example below adds three additional fields when uncommented
             #custom: [Accept-Encoding, Accept-Language, Authorization]
         - dns:
-            # control logging of queries and answers
-            # default yes, no to disable
-            query: yes     # enable logging of DNS queries
-            answer: yes    # enable logging of DNS answers
-            # control which RR types are logged
-            # all enabled if custom not specified
-            #custom: [a, aaaa, cname, mx, ns, ptr, txt]
+            # This configuration uses the new DNS logging format,
+            # the old configuration is still available:
+            # http://suricata.readthedocs.io/en/latest/configuration/suricata-yaml.html#eve-extensible-event-format
+            # Use version 2 logging with the new format:
+            # dns answers will be logged in one single event
+            # rather than an event for each of it.
+            # Without setting a version the version
+            # will fallback to 1 for backwards compatibility.
+            version: 2
+
+            # Enable/disable this logger. Default: enabled.
+            #enabled: no
+
+            # Control logging of requests and responses:
+            # - requests: enable logging of DNS queries
+            # - responses: enable logging of DNS answers
+            # By default both requests and responses are logged.
+            #requests: no
+            #responses: no
+
+            # Format of answer logging:
+            # - detailed: array item per answer
+            # - grouped: answers aggregated by type
+            # Default: all
+            #formats: [detailed, grouped]
+
+            # Answer types to log.
+            # Default: all
+            #types: [a, aaaa, cname, mx, ns, ptr, txt]
         - tls:
             extended: yes     # enable this for extended logging information
             # output TLS transaction where the session is resumed using a