]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
DNS: adding dns_request content modifier
authorVictor Julien <victor@inliniac.net>
Sat, 20 Apr 2013 17:37:05 +0000 (19:37 +0200)
committerVictor Julien <victor@inliniac.net>
Thu, 27 Jun 2013 12:25:58 +0000 (14:25 +0200)
15 files changed:
src/Makefile.am
src/app-layer-dns-common.c
src/app-layer-protos.h
src/detect-app-layer-event.c
src/detect-dns-query.c [new file with mode: 0644]
src/detect-dns-query.h [new file with mode: 0644]
src/detect-engine-content-inspection.h
src/detect-engine-dns.c [new file with mode: 0644]
src/detect-engine-dns.h [new file with mode: 0644]
src/detect-engine-state.c
src/detect-engine-state.h
src/detect-engine.c
src/detect-parse.c
src/detect.c
src/detect.h

index 4f393911822f7418e76b69abb46230131d23bf57..0c2ecff36408ed4cc226f2a59d974483e746659d 100644 (file)
@@ -73,6 +73,7 @@ detect-dce-stub-data.c detect-dce-stub-data.h \
 detect-depth.c detect-depth.h \
 detect-detection-filter.c detect-detection-filter.h \
 detect-distance.c detect-distance.h \
+detect-dns-query.c detect-dns-query.h \
 detect-dsize.c detect-dsize.h \
 detect-engine-address.c detect-engine-address.h \
 detect-engine-address-ipv4.c detect-engine-address-ipv4.h \
@@ -82,6 +83,7 @@ detect-engine-analyzer.c detect-engine-analyzer.h \
 detect-engine.c detect-engine.h \
 detect-engine-content-inspection.c detect-engine-content-inspection.h \
 detect-engine-dcepayload.c detect-engine-dcepayload.h \
+detect-engine-dns.c detect-engine-dns.h \
 detect-engine-event.c detect-engine-event.h \
 detect-engine-file.c detect-engine-file.h \
 detect-engine-hcbd.c detect-engine-hcbd.h \
index a1fb7329b8a06914787cb9ab5174a7d3acb17a5a..46925b999430da9d3b832d0b6c10f8207267caf7 100644 (file)
@@ -74,13 +74,23 @@ void DNSStateFree(void *s) {
 }
 
 void *DNSGetTx(void *alstate, uint64_t tx_id) {
-    /* todo */
+    DNSState *dns_state = (DNSState *)alstate;
+    DNSTransaction *tx = NULL;
+
+    TAILQ_FOREACH(tx, &dns_state->tx_list, next) {
+        SCLogDebug("tx->tx_num %u, tx_id %"PRIu64, tx->tx_num, tx_id);
+        if ((tx_id+1) != tx->tx_num)
+            continue;
+
+        return tx;
+    }
+
     return NULL;
 }
 
 uint64_t DNSGetTxCnt(void *alstate) {
     DNSState *dns_state = (DNSState *)alstate;
-    return (uint64_t)dns_state->transaction_cnt;
+    return (uint64_t)dns_state->transaction_max;
 }
 
 int DNSGetAlstateProgress(void *tx, uint8_t direction) {
index c065509be05140d56aee4a9648beb4ab9c75418f..8c1c93154fce6c387ba437d9ac5230d081d76b34 100644 (file)
@@ -39,8 +39,11 @@ enum {
     ALPROTO_DCERPC,
     ALPROTO_DCERPC_UDP,
     ALPROTO_IRC,
+
+    ALPROTO_DNS,
     ALPROTO_DNS_UDP,
     ALPROTO_DNS_TCP,
+
     /* used by the probing parser when alproto detection fails
      * permanently for that particular stream */
     ALPROTO_FAILED,
index 147a30ba1412370f64c7ac1ac72f067bab179800..b20417ccb698bb131bff066308ea09f5dd2cc99c 100644 (file)
@@ -158,13 +158,17 @@ int DetectAppLayerEventSetup(DetectEngineCtx *de_ctx, Signature *s, char *arg)
     sm->ctx = (void *)data;
 
     if (s->alproto != ALPROTO_UNKNOWN) {
-        if (s->alproto != ((DetectAppLayerEventData *)sm->ctx)->alproto) {
+        if (s->alproto == ALPROTO_DNS &&
+                (data->alproto == ALPROTO_DNS_UDP || data->alproto == ALPROTO_DNS_TCP))
+        {
+            SCLogDebug("DNS app layer event");
+        } else if (s->alproto != data->alproto) {
             SCLogError(SC_ERR_CONFLICTING_RULE_KEYWORDS, "rule contains "
                        "conflicting keywords needing different alprotos");
             goto error;
         }
     } else {
-        s->alproto = ((DetectAppLayerEventData *)sm->ctx)->alproto;
+        s->alproto = data->alproto;
     }
 
     SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_AMATCH);
diff --git a/src/detect-dns-query.c b/src/detect-dns-query.c
new file mode 100644 (file)
index 0000000..39d0a60
--- /dev/null
@@ -0,0 +1,91 @@
+/* Copyright (C) 2013 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
+ * Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 2 along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * \ingroup dnslayer
+ *
+ * @{
+ */
+
+
+/**
+ * \file
+ *
+ * \author Victor Julien <victor@inliniac.net>
+ */
+
+#include "suricata-common.h"
+#include "threads.h"
+#include "debug.h"
+#include "decode.h"
+#include "detect.h"
+
+#include "detect-parse.h"
+#include "detect-engine.h"
+#include "detect-engine-mpm.h"
+#include "detect-content.h"
+#include "detect-pcre.h"
+
+#include "flow.h"
+#include "flow-var.h"
+
+#include "util-debug.h"
+#include "util-unittest.h"
+#include "util-spm.h"
+#include "util-print.h"
+
+#include "app-layer.h"
+
+#include "detect-dns-query.h"
+
+static int DetectDnsQuerySetup (DetectEngineCtx *, Signature *, char *);
+
+/**
+ * \brief Registration function for keyword: http_uri
+ */
+void DetectDnsQueryRegister (void) {
+    sigmatch_table[DETECT_AL_DNS_QUERY].name = "dns_query";
+    sigmatch_table[DETECT_AL_DNS_QUERY].desc = "content modifier to match specifically and only on the DNS query-buffer";
+    sigmatch_table[DETECT_AL_DNS_QUERY].Match = NULL;
+    sigmatch_table[DETECT_AL_DNS_QUERY].AppLayerMatch = NULL;
+    sigmatch_table[DETECT_AL_DNS_QUERY].alproto = ALPROTO_DNS;
+    sigmatch_table[DETECT_AL_DNS_QUERY].Setup = DetectDnsQuerySetup;
+    sigmatch_table[DETECT_AL_DNS_QUERY].Free  = NULL;
+    sigmatch_table[DETECT_AL_DNS_QUERY].RegisterTests = NULL;
+
+    sigmatch_table[DETECT_AL_DNS_QUERY].flags |= SIGMATCH_PAYLOAD;
+}
+
+
+/**
+ * \brief this function setups the dns_query modifier keyword used in the rule
+ *
+ * \param de_ctx   Pointer to the Detection Engine Context
+ * \param s        Pointer to the Signature to which the current keyword belongs
+ * \param str      Should hold an empty string always
+ *
+ * \retval  0 On success
+ * \retval -1 On failure
+ */
+
+static int DetectDnsQuerySetup(DetectEngineCtx *de_ctx, Signature *s, char *str)
+{
+    return DetectEngineContentModifierBufferSetup(de_ctx, s, str,
+                                                  DETECT_AL_DNS_QUERY,
+                                                  DETECT_SM_LIST_DNSQUERY_MATCH,
+                                                  ALPROTO_DNS, NULL);
+}
diff --git a/src/detect-dns-query.h b/src/detect-dns-query.h
new file mode 100644 (file)
index 0000000..c894b87
--- /dev/null
@@ -0,0 +1,29 @@
+/* Copyright (C) 2013 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
+ * Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 2 along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * \file
+ *
+ * \author Victor Julien <victor@inliniac.net>
+ */
+
+#ifndef __DETECT_DNS_QUERY_H__
+#define __DETECT_DNS_QUERY_H__
+
+void DetectDnsQueryRegister (void);
+
+#endif /* __DETECT_DNS_QUERY_H__ */
index 3fff4a869be7bec47c14d2bff147953a9653e2b8..090e39495dca45c8f2427c1c6af8e591501a4639 100644 (file)
@@ -47,6 +47,7 @@ enum {
     DETECT_ENGINE_CONTENT_INSPECTION_MODE_HUAD,
     DETECT_ENGINE_CONTENT_INSPECTION_MODE_HHHD,
     DETECT_ENGINE_CONTENT_INSPECTION_MODE_HRHHD,
+    DETECT_ENGINE_CONTENT_INSPECTION_MODE_DNSQUERY,
 };
 
 int DetectEngineContentInspection(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx,
diff --git a/src/detect-engine-dns.c b/src/detect-engine-dns.c
new file mode 100644 (file)
index 0000000..e904838
--- /dev/null
@@ -0,0 +1,92 @@
+/* Copyright (C) 2013 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
+ * Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 2 along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/** \file
+ *
+ *  \author Victor Julien <victor@inliniac.net>
+ *
+ *  Based on detect-engine-uri.c
+ */
+
+#include "suricata-common.h"
+#include "suricata.h"
+#include "decode.h"
+
+#include "detect.h"
+#include "detect-engine.h"
+#include "detect-parse.h"
+#include "detect-engine-state.h"
+#include "detect-engine-content-inspection.h"
+
+#include "flow-util.h"
+#include "util-debug.h"
+#include "util-print.h"
+#include "flow.h"
+
+#include "app-layer.h"
+#include "app-layer-parser.h"
+#include "app-layer-protos.h"
+#include "app-layer-dns-common.h"
+
+#include "util-unittest.h"
+#include "util-unittest-helper.h"
+
+/** \brief Do the content inspection & validation for a signature
+ *
+ *  \param de_ctx Detection engine context
+ *  \param det_ctx Detection engine thread context
+ *  \param s Signature to inspect
+ *  \param sm SigMatch to inspect
+ *  \param f Flow
+ *  \param flags app layer flags
+ *  \param state App layer state
+ *
+ *  \retval 0 no match
+ *  \retval 1 match
+ */
+int DetectEngineInspectDnsQueryName(ThreadVars *tv,
+                                  DetectEngineCtx *de_ctx,
+                                  DetectEngineThreadCtx *det_ctx,
+                                  Signature *s, Flow *f, uint8_t flags,
+                                  void *alstate, void *txv, uint64_t tx_id)
+{
+    DNSTransaction *tx = (DNSTransaction *)txv;
+    DNSQueryEntry *query = NULL;
+    uint8_t *buffer;
+    uint16_t buffer_len;
+    int r = 0;
+
+    TAILQ_FOREACH(query, &tx->query_list, next) {
+        SCLogDebug("tx %p query %p", tx, query);
+        det_ctx->discontinue_matching = 0;
+        det_ctx->buffer_offset = 0;
+        det_ctx->inspection_recursion_counter = 0;
+
+        buffer = (uint8_t *)((uint8_t *)query + sizeof(DNSQueryEntry));
+        buffer_len = query->len;
+
+        //PrintRawDataFp(stdout, buffer, buffer_len);
+
+        r = DetectEngineContentInspection(de_ctx, det_ctx,
+                s, s->sm_lists[DETECT_SM_LIST_DNSQUERY_MATCH],
+                f, buffer, buffer_len, 0,
+                DETECT_ENGINE_CONTENT_INSPECTION_MODE_DNSQUERY, NULL);
+        if (r == 1)
+            break;
+    }
+    return r;
+}
diff --git a/src/detect-engine-dns.h b/src/detect-engine-dns.h
new file mode 100644 (file)
index 0000000..419f0fe
--- /dev/null
@@ -0,0 +1,30 @@
+/* Copyright (C) 2013 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
+ * Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 2 along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/** \file
+ *
+ *  \author Victor Julien <victor@inliniac.net>
+ */
+
+#ifndef __DETECT_ENGINE_DNS_H__
+#define __DETECT_ENGINE_DNS_H__
+
+int DetectEngineInspectDnsQueryName(ThreadVars *, DetectEngineCtx *de_ctx,
+                                    DetectEngineThreadCtx *, Signature *,
+                                    Flow *, uint8_t, void *, void *, uint64_t);
+
+#endif /* __DETECT_ENGINE_DNS_H__ */
index 62effe57c1f9c8f6ed9700aadc46170711c9c41f..738cd7645e125771633513bc7c13229fbf49e949 100644 (file)
@@ -69,6 +69,7 @@
 #include "app-layer-smb.h"
 #include "app-layer-dcerpc-common.h"
 #include "app-layer-dcerpc.h"
+#include "app-layer-dns-common.h"
 
 #include "util-unittest.h"
 #include "util-unittest-helper.h"
@@ -265,14 +266,16 @@ int DeStateDetectStartDetection(ThreadVars *tv, DetectEngineCtx *de_ctx,
     if (AppLayerAlprotoSupportsTxs(alproto)) {
         FLOWLOCK_WRLOCK(f);
 
-        htp_state = (HtpState *)alstate;
-        if (htp_state->connp == NULL || htp_state->connp->conn == NULL) {
-            FLOWLOCK_UNLOCK(f);
-            goto end;
+        if (alproto == ALPROTO_HTTP) {
+            htp_state = (HtpState *)alstate;
+            if (htp_state->connp == NULL || htp_state->connp->conn == NULL) {
+                FLOWLOCK_UNLOCK(f);
+                goto end;
+            }
         }
 
         tx_id = AppLayerTransactionGetInspectId(f, flags);
-        total_txs = AppLayerGetTxCnt(alproto, htp_state);
+        total_txs = AppLayerGetTxCnt(alproto, alstate);
         for (; tx_id < total_txs; tx_id++) {
             total_matches = 0;
             tx = AppLayerGetTx(alproto, alstate, tx_id);
@@ -526,11 +529,13 @@ void DeStateDetectContinueDetection(ThreadVars *tv, DetectEngineCtx *de_ctx,
             if (alproto_supports_txs) {
                 FLOWLOCK_WRLOCK(f);
 
-                htp_state = (HtpState *)alstate;
-                if (htp_state->connp == NULL || htp_state->connp->conn == NULL) {
-                    FLOWLOCK_UNLOCK(f);
-                    RULE_PROFILING_END(det_ctx, s, match);
-                    goto end;
+                if (alproto == ALPROTO_HTTP) {
+                    htp_state = (HtpState *)alstate;
+                    if (htp_state->connp == NULL || htp_state->connp->conn == NULL) {
+                        FLOWLOCK_UNLOCK(f);
+                        RULE_PROFILING_END(det_ctx, s, match);
+                        goto end;
+                    }
                 }
 
                 engine = app_inspection_engine[alproto][(flags & STREAM_TOSERVER) ? 0 : 1];
index 17ac46ebebeec8233e5b22fe0ddd71183141b5c3..06fd568b4ecbfcc0a7a4d90199d5dc777915a447 100644 (file)
@@ -74,6 +74,7 @@
 #define DE_STATE_FLAG_FILE_TS_INSPECT     (1 << 14)
 #define DE_STATE_FLAG_FULL_INSPECT        (1 << 15)
 #define DE_STATE_FLAG_SIG_CANT_MATCH      (1 << 16)
+#define DE_STATE_FLAG_DNSQUERY_INSPECT    (1 << 17)
 
 /* state flags */
 #define DETECT_ENGINE_STATE_FLAG_FILE_STORE_DISABLED 0x0001
index c5f6d931d31211283b9303e1e384d384c2c346c5..72727d77c7cb7bdd6b81b520e35b88d3daad42ca 100644 (file)
@@ -56,6 +56,7 @@
 #include "detect-engine-hhhd.h"
 #include "detect-engine-hrhhd.h"
 #include "detect-engine-file.h"
+#include "detect-engine-dns.h"
 
 #include "detect-engine.h"
 #include "detect-engine-state.h"
@@ -214,6 +215,13 @@ void DetectEngineRegisterAppInspectionEngines(void)
           DE_STATE_FLAG_HRHHD_INSPECT,
           0,
           DetectEngineInspectHttpHRH },
+        /* DNS */
+        { ALPROTO_DNS,
+          DETECT_SM_LIST_DNSQUERY_MATCH,
+          DE_STATE_FLAG_DNSQUERY_INSPECT,
+          DE_STATE_FLAG_DNSQUERY_INSPECT,
+          0,
+          DetectEngineInspectDnsQueryName },
     };
 
     struct tmp_t data_toclient[] = {
index 2b32842fbf2597b9ef61d662c66c91c11e958a45..98324d65c1631ffb081d71114ecc25fbdad10b27 100644 (file)
@@ -779,7 +779,7 @@ static int SigParseBasics(Signature *s, char *sigstr, char ***result, uint8_t ad
             goto error;
         if (SigParseProto(s, "dnsudp") < 0)
             goto error;
-
+        s->alproto = ALPROTO_DNS;
     } else {
         if (SigParseProto(s, arr[CONFIG_PROTO]) < 0)
             goto error;
@@ -1402,6 +1402,8 @@ static Signature *SigInitHelper(DetectEngineCtx *de_ctx, char *sigstr,
         sig->flags |= SIG_FLAG_STATE_MATCH;
     if (sig->sm_lists[DETECT_SM_LIST_HRHHDMATCH])
         sig->flags |= SIG_FLAG_STATE_MATCH;
+    if (sig->sm_lists[DETECT_SM_LIST_DNSQUERY_MATCH])
+        sig->flags |= SIG_FLAG_STATE_MATCH;
 
     if (!(sig->init_flags & SIG_FLAG_INIT_FLOW)) {
         sig->flags |= SIG_FLAG_TOSERVER;
index 1e397101561689c5ab40c66c6725c1e674364a12..284572297719968b37d88b9a57bb197dfdb58a4c 100644 (file)
 #include "detect-luajit.h"
 #include "detect-iprep.h"
 #include "detect-geoip.h"
+#include "detect-dns-query.h"
 
 #include "util-rule-vars.h"
 
@@ -505,6 +506,11 @@ static inline int SigMatchSignaturesBuildMatchArrayAddSignature(DetectEngineThre
                     SCLogDebug("DCERPC sig, alproto not SMB or SMB2");
                     return 0;
                 }
+            } else if (s->alproto == ALPROTO_DNS) {
+                if (alproto != ALPROTO_DNS_UDP && alproto != ALPROTO_DNS_TCP) {
+                    SCLogDebug("DNS sig, alproto not DNS/TCP or DNS/UDP");
+                    return 0;
+                }
             } else {
                 SCLogDebug("alproto mismatch");
                 return 0;
@@ -4869,6 +4875,7 @@ void SigTableSetup(void) {
     DetectHttpHRHRegister();
     DetectLuajitRegister();
     DetectIPRepRegister();
+    DetectDnsQueryRegister();
 
     uint8_t i = 0;
     for (i = 0; i < DETECT_TBLSIZE; i++) {
index 0dbdd6581552044bc360c2d5694687a924104a47..35ff5d3b3420ae5344020e2b2df39313087b0323 100644 (file)
@@ -115,6 +115,8 @@ enum {
 
     DETECT_SM_LIST_FILEMATCH,
 
+    DETECT_SM_LIST_DNSQUERY_MATCH,
+
     /* list for post match actions: flowbit set, flowint increment, etc */
     DETECT_SM_LIST_POSTMATCH,
 
@@ -1122,6 +1124,8 @@ enum {
     DETECT_LUAJIT,
     DETECT_IPREP,
 
+    DETECT_AL_DNS_QUERY,
+
     /* make sure this stays last */
     DETECT_TBLSIZE,
 };