]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
detect: add udp.hdr sticky buffer
authorVictor Julien <victor@inliniac.net>
Wed, 19 Jun 2019 14:51:44 +0000 (16:51 +0200)
committerVictor Julien <victor@inliniac.net>
Fri, 21 Jun 2019 05:16:17 +0000 (07:16 +0200)
src/Makefile.am
src/detect-engine-mpm.c
src/detect-engine-register.c
src/detect-engine-register.h
src/detect-udphdr.c [new file with mode: 0644]
src/detect-udphdr.h [new file with mode: 0644]
src/tests/detect-udphdr.c [new file with mode: 0644]

index b589dbf52664be5e942bb91862344964b8598854..875f9b8441b6257d6b73a4c7ceb4a38fe78b4a03 100644 (file)
@@ -248,6 +248,7 @@ detect-tcp-flags.c detect-tcp-flags.h \
 detect-tcp-seq.c detect-tcp-seq.h \
 detect-tcp-window.c detect-tcp-window.h \
 detect-tcphdr.c detect-tcphdr.h \
+detect-udphdr.c detect-udphdr.h \
 detect-tcpmss.c detect-tcpmss.h \
 detect-template.c detect-template.h \
 detect-template2.c detect-template2.h \
index 9ecf78f7dbfe4b522814b2cd1a9880da3e7c54c0..35ddd59af418fa23e17e56abf7fa942bf5eefa38 100644 (file)
@@ -42,7 +42,9 @@
 #include "util-memcpy.h"
 #include "conf.h"
 #include "detect-fast-pattern.h"
+
 #include "detect-tcphdr.h"
+#include "detect-udphdr.h"
 
 #include "flow.h"
 #include "flow-var.h"
@@ -1415,12 +1417,20 @@ int PatternMatchPrepareGroup(DetectEngineCtx *de_ctx, SigGroupHead *sh)
             if (mpm_store != NULL) {
                 PrefilterPktPayloadRegister(de_ctx, sh, mpm_store->mpm_ctx);
             }
+            mpm_store = MpmStorePrepareBuffer(de_ctx, sh, MPMB_L4HDR_TS);
+            if (mpm_store != NULL) {
+                PrefilterUdpHeaderRegister(de_ctx, sh, mpm_store->mpm_ctx);
+            }
         }
         if (SGH_DIRECTION_TC(sh)) {
             mpm_store = MpmStorePrepareBuffer(de_ctx, sh, MPMB_UDP_TC);
             if (mpm_store != NULL) {
                 PrefilterPktPayloadRegister(de_ctx, sh, mpm_store->mpm_ctx);
             }
+            mpm_store = MpmStorePrepareBuffer(de_ctx, sh, MPMB_L4HDR_TC);
+            if (mpm_store != NULL) {
+                PrefilterUdpHeaderRegister(de_ctx, sh, mpm_store->mpm_ctx);
+            }
         }
     } else {
         mpm_store = MpmStorePrepareBuffer(de_ctx, sh, MPMB_OTHERIP);
index 3f67b8757bf6ad9e1a92befbb7c2819b6e20d367..84066e7a6374fe3d368e031f05a2ac72c070a9a0 100644 (file)
 #include "detect-template2.h"
 #include "detect-tcphdr.h"
 #include "detect-tcpmss.h"
+#include "detect-udphdr.h"
 #include "detect-krb5-cname.h"
 #include "detect-krb5-errcode.h"
 #include "detect-krb5-msgtype.h"
@@ -526,6 +527,7 @@ void SigTableSetup(void)
     DetectTemplateRegister();
     DetectTemplate2Register();
     DetectTcphdrRegister();
+    DetectUdphdrRegister();
     DetectTcpmssRegister();
     DetectKrb5CNameRegister();
     DetectKrb5ErrCodeRegister();
index 76ee057933df9fcefbebc2727eae3e4ab608dfb1..c7f38c5784c706ed8bb23f1c72ffcb2dc59caf19 100644 (file)
@@ -226,6 +226,7 @@ enum {
     DETECT_TEMPLATE,
     DETECT_TEMPLATE2,
     DETECT_TCPHDR,
+    DETECT_UDPHDR,
     DETECT_TCPMSS,
     DETECT_FTPDATA,
     DETECT_TARGET,
diff --git a/src/detect-udphdr.c b/src/detect-udphdr.c
new file mode 100644 (file)
index 0000000..2bc5d80
--- /dev/null
@@ -0,0 +1,166 @@
+/* Copyright (C) 2007-2019 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>
+ *
+ */
+
+#include "suricata-common.h"
+
+#include "detect.h"
+#include "detect-parse.h"
+#include "detect-engine.h"
+#include "detect-engine-prefilter.h"
+#include "detect-engine-content-inspection.h"
+#include "detect-fast-pattern.h"
+#include "detect-udphdr.h"
+
+/* prototypes */
+static int DetectUdphdrSetup (DetectEngineCtx *, Signature *, const char *);
+#ifdef UNITTESTS
+void DetectUdphdrRegisterTests (void);
+#endif
+
+/**
+ * \brief Registration function for tcphdr: keyword
+ */
+
+void DetectUdphdrRegister(void)
+{
+    sigmatch_table[DETECT_UDPHDR].name = "udp.hdr";
+    sigmatch_table[DETECT_UDPHDR].desc = "sticky buffer to match on the UDP header";
+    sigmatch_table[DETECT_UDPHDR].url = DOC_URL DOC_VERSION "/rules/header-keywords.html#udphdr";
+    sigmatch_table[DETECT_UDPHDR].Setup = DetectUdphdrSetup;
+    sigmatch_table[DETECT_UDPHDR].flags |= SIGMATCH_NOOPT | SIGMATCH_INFO_STICKY_BUFFER;
+#ifdef UNITTESTS
+    sigmatch_table[DETECT_UDPHDR].RegisterTests = DetectUdphdrRegisterTests;
+#endif
+    SupportFastPatternForSigMatchList(DETECT_SM_LIST_L4HDR, 2);
+    return;
+}
+
+/**
+ * \brief this function is used to atcphdrd the parsed tcphdr data into the current signature
+ *
+ * \param de_ctx pointer to the Detection Engine Context
+ * \param s pointer to the Current Signature
+ * \param tcphdrstr pointer to the user provided tcphdr options
+ *
+ * \retval 0 on Success
+ * \retval -1 on Failure
+ */
+static int DetectUdphdrSetup (DetectEngineCtx *de_ctx, Signature *s, const char *tcphdrstr)
+{
+    if (!(DetectProtoContainsProto(&s->proto, IPPROTO_UDP)))
+        return -1;
+
+    s->flags |= SIG_FLAG_REQUIRE_PACKET;
+
+    if (DetectBufferSetActiveList(s, DETECT_SM_LIST_L4HDR) < 0)
+        return -1;
+
+    return 0;
+}
+
+static void PrefilterUdpHeader(DetectEngineThreadCtx *det_ctx,
+        Packet *p, const void *pectx)
+{
+    SCEnter();
+
+    if (((uint8_t *)p->udph + (ptrdiff_t)UDP_HEADER_LEN) >
+            ((uint8_t *)GET_PKT_DATA(p) + (ptrdiff_t)GET_PKT_LEN(p)))
+    {
+        SCLogDebug("data out of range: %p > %p",
+                ((uint8_t *)p->udph + (ptrdiff_t)UDP_HEADER_LEN),
+                ((uint8_t *)GET_PKT_DATA(p) + (ptrdiff_t)GET_PKT_LEN(p)));
+        SCReturn;
+    }
+
+    const MpmCtx *mpm_ctx = (MpmCtx *)pectx;
+    if (UDP_HEADER_LEN < mpm_ctx->minlen)
+        SCReturn;
+
+    (void)mpm_table[mpm_ctx->mpm_type].Search(mpm_ctx,
+            &det_ctx->mtc, &det_ctx->pmq,
+            (uint8_t *)p->udph, UDP_HEADER_LEN);
+}
+
+int PrefilterUdpHeaderRegister(DetectEngineCtx *de_ctx,
+        SigGroupHead *sgh, MpmCtx *mpm_ctx)
+{
+    return PrefilterAppendEngine(de_ctx, sgh,
+            PrefilterUdpHeader, mpm_ctx, NULL, "udp.hdr");
+}
+
+/**
+ *  \brief Do the content inspection & validation for a signature
+ *
+ *  \param det_ctx Detection engine thread context
+ *  \param s Signature to inspect
+ *  \param p Packet
+ *
+ *  \retval false no match
+ *  \retval true match
+ */
+bool DetectEngineInspectRuleUdpHeaderMatches(
+     ThreadVars *tv, DetectEngineThreadCtx *det_ctx,
+     const Signature *s, const SigMatchData *sm_data,
+     Flow *f, Packet *p,
+     uint8_t *alert_flags)
+{
+    SCEnter();
+
+    BUG_ON(sm_data == NULL);
+    BUG_ON(sm_data != s->sm_arrays[DETECT_SM_LIST_L4HDR]);
+
+    if (!(PKT_IS_UDP(p))) {
+        SCReturnInt(false);
+    }
+    if (((uint8_t *)p->udph + (ptrdiff_t)UDP_HEADER_LEN) >
+            ((uint8_t *)GET_PKT_DATA(p) + (ptrdiff_t)GET_PKT_LEN(p)))
+    {
+        SCLogDebug("data out of range: %p > %p",
+                ((uint8_t *)p->udph + (ptrdiff_t)UDP_HEADER_LEN),
+                ((uint8_t *)GET_PKT_DATA(p) + (ptrdiff_t)GET_PKT_LEN(p)));
+        SCReturnInt(false);
+    }
+
+#ifdef DEBUG
+    det_ctx->payload_persig_cnt++;
+    det_ctx->payload_persig_size += UDP_HEADER_LEN;
+#endif
+    det_ctx->buffer_offset = 0;
+    det_ctx->discontinue_matching = 0;
+    det_ctx->inspection_recursion_counter = 0;
+    det_ctx->replist = NULL;
+
+    int r = DetectEngineContentInspection(det_ctx->de_ctx, det_ctx,
+            s, sm_data,
+            p, NULL, (uint8_t *)p->udph, UDP_HEADER_LEN, 0,
+            DETECT_CI_FLAGS_SINGLE, DETECT_ENGINE_CONTENT_INSPECTION_MODE_HEADER);
+    if (r == 1) {
+        SCReturnInt(true);
+    }
+    SCReturnInt(false);
+}
+
+#ifdef UNITTESTS
+#include "tests/detect-udphdr.c"
+#endif
diff --git a/src/detect-udphdr.h b/src/detect-udphdr.h
new file mode 100644 (file)
index 0000000..29a7e07
--- /dev/null
@@ -0,0 +1,36 @@
+/* Copyright (C) 2007-2019 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_UDPHDR_H
+#define _DETECT_UDPHDR_H
+
+int PrefilterUdpHeaderRegister(DetectEngineCtx *de_ctx,
+        SigGroupHead *sgh, MpmCtx *mpm_ctx);
+bool DetectEngineInspectRuleUdpHeaderMatches(
+     ThreadVars *tv, DetectEngineThreadCtx *det_ctx,
+     const Signature *s, const SigMatchData *sm_data,
+     Flow *f, Packet *p,
+     uint8_t *alert_flags);
+void DetectUdphdrRegister(void);
+
+#endif /* _DETECT_UDPHDR_H */
diff --git a/src/tests/detect-udphdr.c b/src/tests/detect-udphdr.c
new file mode 100644 (file)
index 0000000..5e661fb
--- /dev/null
@@ -0,0 +1,47 @@
+/* Copyright (C) 2007-2018 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.
+ */
+
+#include "../suricata-common.h"
+
+#include "../detect.h"
+#include "../detect-parse.h"
+#include "../detect-engine-prefilter-common.h"
+
+#include "../detect-tcphdr.h"
+
+#include "../util-unittest.h"
+
+static int DetectUdphdrParseTest01 (void)
+{
+    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+    FAIL_IF_NULL(de_ctx);
+
+    Signature *sig = DetectEngineAppendSig(de_ctx,
+            "alert udp any any -> any any (udp.hdr; content:\"A\"; sid:1; rev:1;)");
+    FAIL_IF_NULL(sig);
+
+    DetectEngineCtxFree(de_ctx);
+    PASS;
+}
+
+/**
+ * \brief this function registers unit tests for DetectUdphdr
+ */
+void DetectUdphdrRegisterTests(void)
+{
+    UtRegisterTest("DetectUdphdrParseTest01", DetectUdphdrParseTest01);
+}