]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
detect: add http.uri sticky buffer keyword
authorVictor Julien <victor@inliniac.net>
Mon, 26 Nov 2018 14:25:04 +0000 (15:25 +0100)
committerVictor Julien <victor@inliniac.net>
Tue, 29 Jan 2019 12:27:56 +0000 (13:27 +0100)
src/detect-engine-register.h
src/detect-engine-uri.c
src/detect-http-uri.c
src/tests/detect.c

index 0f0e7d1a6b7e0d221146064a15539ba8d52d8f70..9cc563fa464ee11e9075e16b7624a0ad7da53514 100644 (file)
@@ -129,6 +129,7 @@ enum {
     DETECT_AL_HTTP_HEADER_REFERER,
     DETECT_AL_HTTP_RAW_HEADER,
     DETECT_AL_HTTP_URI,
+    DETECT_HTTP_URI,
     DETECT_AL_HTTP_RAW_URI,
     DETECT_AL_HTTP_STAT_MSG,
     DETECT_AL_HTTP_STAT_CODE,
index acbe2960369df30397f3e9c881097058c251a942..c19215e90f8ff5a25ac3f4e894a01ee1e51f8321 100644 (file)
 #include "app-layer-protos.h"
 #include "util-validate.h"
 
-/** \brief HTTP URI Mpm prefilter callback
- *
- *  \param det_ctx detection engine thread ctx
- *  \param p packet to inspect
- *  \param f flow to inspect
- *  \param txv tx to inspect
- *  \param pectx inspection context
- */
-static void PrefilterTxUri(DetectEngineThreadCtx *det_ctx, const void *pectx,
-        Packet *p, Flow *f, void *txv,
-        const uint64_t idx, const uint8_t flags)
-{
-    SCEnter();
-
-    const MpmCtx *mpm_ctx = (MpmCtx *)pectx;
-    htp_tx_t *tx = (htp_tx_t *)txv;
-    HtpTxUserData *tx_ud = htp_tx_get_user_data(tx);
-
-    if (tx_ud == NULL || tx_ud->request_uri_normalized == NULL)
-        return;
-
-    const uint32_t uri_len = bstr_len(tx_ud->request_uri_normalized);
-    const uint8_t *uri = bstr_ptr(tx_ud->request_uri_normalized);
-
-    if (uri_len >= mpm_ctx->minlen) {
-        (void)mpm_table[mpm_ctx->mpm_type].Search(mpm_ctx,
-                &det_ctx->mtcu, &det_ctx->pmq, uri, uri_len);
-    }
-}
-
-int PrefilterTxUriRegister(DetectEngineCtx *de_ctx,
-        SigGroupHead *sgh, MpmCtx *mpm_ctx)
-{
-    SCEnter();
-
-    return PrefilterAppendTxEngine(de_ctx, sgh, PrefilterTxUri,
-        ALPROTO_HTTP, HTP_REQUEST_LINE,
-        mpm_ctx, NULL, "http_uri");
-}
-
-/**
- * \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.
- * \retval 2 Sig can't match.
- */
-int DetectEngineInspectHttpUri(ThreadVars *tv,
-        DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx,
-        const Signature *s, const SigMatchData *smd,
-        Flow *f, uint8_t flags, void *alstate, void *txv, uint64_t tx_id)
-{
-    HtpTxUserData *tx_ud = htp_tx_get_user_data(txv);
-
-    if (tx_ud == NULL || tx_ud->request_uri_normalized == NULL) {
-        if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, txv, flags) > HTP_REQUEST_LINE)
-            return DETECT_ENGINE_INSPECT_SIG_CANT_MATCH;
-        else
-            return DETECT_ENGINE_INSPECT_SIG_NO_MATCH;
-    }
-
-    det_ctx->discontinue_matching = 0;
-    det_ctx->buffer_offset = 0;
-    det_ctx->inspection_recursion_counter = 0;
-
-#if 0
-    PrintRawDataFp(stdout, (uint8_t *)bstr_ptr(tx_ud->request_uri_normalized),
-                   bstr_len(tx_ud->request_uri_normalized));
-#endif
-
-    /* Inspect all the uricontents fetched on each
-     * transaction at the app layer */
-    int r = DetectEngineContentInspection(de_ctx, det_ctx, s, smd,
-                                          f,
-                                          bstr_ptr(tx_ud->request_uri_normalized),
-                                          bstr_len(tx_ud->request_uri_normalized),
-                                          0, DETECT_CI_FLAGS_SINGLE,
-                                          DETECT_ENGINE_CONTENT_INSPECTION_MODE_STATE, NULL);
-    if (r == 1) {
-        return DETECT_ENGINE_INSPECT_SIG_MATCH;
-    } else {
-        return DETECT_ENGINE_INSPECT_SIG_CANT_MATCH;
-    }
-}
-
 /***********************************Unittests**********************************/
 
 #ifdef UNITTESTS
index 3c481c2ee4a90db75efb4577a87e3bd5f9d6e72b..e55bea8d54547a5cf96a1b7033286ecdd9d93058 100644 (file)
@@ -37,6 +37,7 @@
 #include "detect-parse.h"
 #include "detect-engine.h"
 #include "detect-engine-mpm.h"
+#include "detect-engine-prefilter.h"
 #include "detect-content.h"
 #include "detect-pcre.h"
 #include "detect-urilen.h"
@@ -61,30 +62,41 @@ static void DetectHttpUriRegisterTests(void);
 static void DetectHttpUriSetupCallback(const DetectEngineCtx *de_ctx,
                                        Signature *s);
 static bool DetectHttpUriValidateCallback(const Signature *s, const char **sigerror);
-
+static InspectionBuffer *GetData(DetectEngineThreadCtx *det_ctx,
+        const DetectEngineTransforms *transforms,
+        Flow *_f, const uint8_t _flow_flags,
+        void *txv, const int list_id);
+static int DetectHttpUriSetupSticky(DetectEngineCtx *de_ctx, Signature *s, const char *str);
 static int g_http_uri_buffer_id = 0;
 
 /**
- * \brief Registration function for keyword: http_uri
+ * \brief Registration function for keywords: http_uri and http.uri
  */
 void DetectHttpUriRegister (void)
 {
+    /* http_uri content modifier */
     sigmatch_table[DETECT_AL_HTTP_URI].name = "http_uri";
     sigmatch_table[DETECT_AL_HTTP_URI].desc = "content modifier to match specifically and only on the HTTP uri-buffer";
     sigmatch_table[DETECT_AL_HTTP_URI].url = DOC_URL DOC_VERSION "/rules/http-keywords.html#http-uri-and-http-raw-uri";
-    sigmatch_table[DETECT_AL_HTTP_URI].Match = NULL;
     sigmatch_table[DETECT_AL_HTTP_URI].Setup = DetectHttpUriSetup;
-    sigmatch_table[DETECT_AL_HTTP_URI].Free  = NULL;
     sigmatch_table[DETECT_AL_HTTP_URI].RegisterTests = DetectHttpUriRegisterTests;
-
     sigmatch_table[DETECT_AL_HTTP_URI].flags |= SIGMATCH_NOOPT;
 
-    DetectAppLayerMpmRegister("http_uri", SIG_FLAG_TOSERVER, 2,
-            PrefilterTxUriRegister);
+    /* http.uri sticky buffer */
+    sigmatch_table[DETECT_HTTP_URI].name = "http.uri";
+    sigmatch_table[DETECT_HTTP_URI].alias = "http.uri.normalized";
+    sigmatch_table[DETECT_HTTP_URI].desc = "sticky buffer to match specifically and only on the normalized HTTP URI buffer";
+    sigmatch_table[DETECT_HTTP_URI].url = DOC_URL DOC_VERSION "/rules/tls-keywords.html#http-uri";
+    sigmatch_table[DETECT_HTTP_URI].Setup = DetectHttpUriSetupSticky;
+    sigmatch_table[DETECT_HTTP_URI].flags |= SIGMATCH_NOOPT;
+
+    DetectAppLayerInspectEngineRegister2("http_uri", ALPROTO_HTTP,
+            SIG_FLAG_TOSERVER, HTP_REQUEST_LINE,
+            DetectEngineInspectBufferGeneric, GetData);
 
-    DetectAppLayerInspectEngineRegister("http_uri",
-            ALPROTO_HTTP, SIG_FLAG_TOSERVER, HTP_REQUEST_LINE,
-            DetectEngineInspectHttpUri);
+    DetectAppLayerMpmRegister2("http_uri", SIG_FLAG_TOSERVER, 2,
+            PrefilterGenericMpmRegister, GetData, ALPROTO_HTTP,
+            HTP_REQUEST_LINE);
 
     DetectBufferTypeSetDescriptionByName("http_uri",
             "http request uri");
@@ -98,7 +110,6 @@ void DetectHttpUriRegister (void)
     g_http_uri_buffer_id = DetectBufferTypeGetByName("http_uri");
 }
 
-
 /**
  * \brief this function setups the http_uri modifier keyword used in the rule
  *
@@ -130,6 +141,48 @@ static void DetectHttpUriSetupCallback(const DetectEngineCtx *de_ctx,
     DetectUrilenApplyToContent(s, g_http_uri_buffer_id);
 }
 
+/**
+ * \brief this function setup the http.uri 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
+ */
+static int DetectHttpUriSetupSticky(DetectEngineCtx *de_ctx, Signature *s, const char *str)
+{
+    DetectBufferSetActiveList(s, g_http_uri_buffer_id);
+    s->alproto = ALPROTO_HTTP;
+    return 0;
+}
+
+static InspectionBuffer *GetData(DetectEngineThreadCtx *det_ctx,
+        const DetectEngineTransforms *transforms, Flow *_f,
+        const uint8_t _flow_flags, void *txv, const int list_id)
+{
+    SCEnter();
+
+    InspectionBuffer *buffer = InspectionBufferGet(det_ctx, list_id);
+    if (buffer->inspect == NULL) {
+        htp_tx_t *tx = (htp_tx_t *)txv;
+        HtpTxUserData *tx_ud = htp_tx_get_user_data(tx);
+
+        if (tx_ud == NULL || tx_ud->request_uri_normalized == NULL) {
+            SCLogDebug("no tx_id or uri");
+            return NULL;
+        }
+
+        const uint32_t data_len = bstr_len(tx_ud->request_uri_normalized);
+        const uint8_t *data = bstr_ptr(tx_ud->request_uri_normalized);
+
+        InspectionBufferSetup(buffer, data, data_len);
+        InspectionBufferApplyTransforms(buffer, transforms);
+    }
+
+    return buffer;
+}
+
 /******************************** UNITESTS **********************************/
 
 #ifdef UNITTESTS
index 69c0504611b605ac4247122d1533b521512c4b7e..087ead6bda0444cb73012fbd916151e46e149a01 100644 (file)
@@ -313,14 +313,15 @@ static int SigTest06 (void)
     DetectEngineThreadCtx *det_ctx = NULL;
     Flow f;
     TcpSession ssn;
-    int result = 0;
     AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+    FAIL_IF_NULL(alp_tctx);
 
     memset(&th_v, 0, sizeof(th_v));
     memset(&f, 0, sizeof(f));
     memset(&ssn, 0, sizeof(ssn));
 
     p = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
+    FAIL_IF_NULL(p);
 
     FLOW_INITIALIZE(&f);
     f.protoctx = (void *)&ssn;
@@ -335,58 +336,34 @@ static int SigTest06 (void)
     StreamTcpInitConfig(TRUE);
 
     DetectEngineCtx *de_ctx = DetectEngineCtxInit();
-    if (de_ctx == NULL) {
-        goto end;
-    }
-
+    FAIL_IF_NULL(de_ctx);
     de_ctx->flags |= DE_QUIET;
 
-    de_ctx->sig_list = SigInit(de_ctx,"alert tcp any any -> any any (msg:\"HTTP URI cap\"; content:\"GET \"; depth:4; pcre:\"/GET (?P<pkt_http_uri>.*) HTTP\\/\\d\\.\\d\\r\\n/G\"; sid:1;)");
-    if (de_ctx->sig_list == NULL) {
-        result = 0;
-        goto end;
-    }
+    Signature *s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"HTTP URI cap\"; content:\"GET \"; depth:4; pcre:\"/GET (?P<pkt_http_uri>.*) HTTP\\/\\d\\.\\d\\r\\n/G\"; sid:1;)");
+    FAIL_IF_NULL(s);
 
-    de_ctx->sig_list->next = SigInit(de_ctx,"alert tcp any any -> any any (msg:\"HTTP URI test\"; uricontent:\"two\"; sid:2;)");
-    if (de_ctx->sig_list->next == NULL) {
-        result = 0;
-        goto end;
-    }
+    s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"HTTP URI test\"; uricontent:\"two\"; sid:2;)");
+    FAIL_IF_NULL(s);
 
     SigGroupBuild(de_ctx);
     DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+    FAIL_IF_NULL(det_ctx);
 
-    FLOWLOCK_WRLOCK(&f);
     int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
                                 STREAM_TOSERVER, buf, buflen);
-    if (r != 0) {
-        printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
-        result = 0;
-        FLOWLOCK_UNLOCK(&f);
-        goto end;
-    }
-    FLOWLOCK_UNLOCK(&f);
+    FAIL_IF(r != 0);
 
     SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
-    if (PacketAlertCheck(p, 1) && PacketAlertCheck(p, 2))
-        result = 1;
-    else
-        printf("sid:1 %s, sid:2 %s: ",
-            PacketAlertCheck(p, 1) ? "OK" : "FAIL",
-            PacketAlertCheck(p, 2) ? "OK" : "FAIL");
-
-    SigGroupCleanup(de_ctx);
-    SigCleanSignatures(de_ctx);
+    FAIL_IF_NOT(PacketAlertCheck(p, 1));
+    FAIL_IF_NOT(PacketAlertCheck(p, 2));
 
     DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
     DetectEngineCtxFree(de_ctx);
-end:
-    if (alp_tctx != NULL)
-        AppLayerParserThreadCtxFree(alp_tctx);
+    AppLayerParserThreadCtxFree(alp_tctx);
     UTHFreePackets(&p, 1);
     StreamTcpFreeConfig(TRUE);
     FLOW_DESTROY(&f);
-    return result;
+    PASS;
 }
 
 static int SigTest07 (void)