]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
http_header: common detection code
authorVictor Julien <victor@inliniac.net>
Mon, 19 Dec 2016 14:45:12 +0000 (15:45 +0100)
committerVictor Julien <victor@inliniac.net>
Thu, 16 Feb 2017 09:35:41 +0000 (10:35 +0100)
src/Makefile.am
src/detect-http-header-common.c [new file with mode: 0644]
src/detect-http-header-common.h [new file with mode: 0644]
src/detect-http-header-names.c

index 298eec7c43d04fad85df98a76b53cf7b089e0def..c3e9a196fc3e4f2358266c4ebcb651d46955b22c 100644 (file)
@@ -164,6 +164,7 @@ detect-hostbits.c detect-hostbits.h \
 detect-http-client-body.c detect-http-client-body.h \
 detect-http-cookie.c detect-http-cookie.h \
 detect-http-header.c detect-http-header.h \
+detect-http-header-common.c detect-http-header-common.h \
 detect-http-header-names.c detect-http-header-names.h \
 detect-http-hh.c detect-http-hh.h \
 detect-http-hrh.c detect-http-hrh.h \
diff --git a/src/detect-http-header-common.c b/src/detect-http-header-common.c
new file mode 100644 (file)
index 0000000..1ab9b73
--- /dev/null
@@ -0,0 +1,206 @@
+/* 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
+ * 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 httplayer
+ *
+ * @{
+ */
+
+#include "suricata-common.h"
+#include "threads.h"
+#include "decode.h"
+
+#include "detect.h"
+#include "detect-parse.h"
+#include "detect-engine.h"
+#include "detect-engine-mpm.h"
+#include "detect-engine-state.h"
+#include "detect-engine-prefilter.h"
+#include "detect-engine-content-inspection.h"
+#include "detect-content.h"
+#include "detect-pcre.h"
+
+#include "flow.h"
+#include "flow-var.h"
+#include "flow-util.h"
+
+#include "util-debug.h"
+#include "util-unittest.h"
+#include "util-unittest-helper.h"
+#include "util-spm.h"
+#include "util-print.h"
+
+#include "app-layer.h"
+#include "app-layer-parser.h"
+
+#include "app-layer-htp.h"
+#include "detect-http-header.h"
+#include "stream-tcp.h"
+
+#include "util-print.h"
+
+#include "detect-http-header-common.h"
+
+static inline int CreateSpace(HttpHeaderThreadData *td, uint64_t size);
+
+void *HttpHeaderThreadDataInit(void *data)
+{
+    HttpHeaderThreadData *td = SCCalloc(1, sizeof(*td));
+    if (td != NULL) {
+        if (data == NULL) {
+            td->tx_step = 4;
+            td->size_step = 512;
+        } else {
+            HttpHeaderThreadDataConfig *c = data;
+            td->tx_step = c->tx_step;
+            td->size_step = c->size_step;
+        }
+
+        /* initialize minimal buffers */
+        (void)CreateSpace(td, 1);
+        int i;
+        for (i = 0; i < td->buffers_size; i++) {
+            (void)HttpHeaderExpandBuffer(td, &td->buffers[i], 1);
+        }
+    }
+    return td;
+}
+
+void HttpHeaderThreadDataFree(void *data)
+{
+    HttpHeaderThreadData *hdrnames = data;
+
+    int i;
+    for (i = 0; i < hdrnames->buffers_size; i++) {
+        if (hdrnames->buffers[i].buffer)
+            SCFree(hdrnames->buffers[i].buffer);
+        if (hdrnames->buffers[i].size) {
+            SCLogDebug("hdrnames->buffers[%d].size %u (%u)",
+                    i, hdrnames->buffers[i].size, hdrnames->buffers_size);
+        }
+    }
+    SCFree(hdrnames->buffers);
+    SCFree(hdrnames);
+}
+
+static void Reset(HttpHeaderThreadData *hdrnames, uint64_t tick)
+{
+    uint16_t i;
+    for (i = 0; i < hdrnames->buffers_list_len; i++) {
+        hdrnames->buffers[i].len = 0;
+    }
+    hdrnames->buffers_list_len = 0;
+    hdrnames->start_tx_id = 0;
+    hdrnames->tick = tick;
+}
+
+static inline int CreateSpace(HttpHeaderThreadData *td, uint64_t size)
+{
+    if (size >= SHRT_MAX)
+        return -1;
+
+    if (size > td->buffers_size) {
+        uint16_t extra = td->tx_step;
+        while (td->buffers_size + extra < size) {
+            extra += td->tx_step;
+        }
+        SCLogDebug("adding %u to the buffer", (uint)extra);
+
+        void *ptmp = SCRealloc(td->buffers,
+                         (td->buffers_size + extra) * sizeof(HttpHeaderBuffer));
+        if (ptmp == NULL) {
+            SCFree(td->buffers);
+            td->buffers = NULL;
+            td->buffers_size = 0;
+            td->buffers_list_len = 0;
+            return -1;
+        }
+        td->buffers = ptmp;
+        memset(td->buffers + td->buffers_size, 0, extra * sizeof(HttpHeaderBuffer));
+        td->buffers_size += extra;
+    }
+    return 0;
+}
+
+int HttpHeaderExpandBuffer(HttpHeaderThreadData *td,
+        HttpHeaderBuffer *buf, uint32_t size)
+{
+    size_t extra = td->size_step;
+    while ((buf->size + extra) < (size + buf->len)) {
+        extra += td->size_step;
+    }
+    SCLogDebug("adding %u to the buffer", (uint)extra);
+
+    uint8_t *new_buffer = SCRealloc(buf->buffer, buf->size + extra);
+    if (unlikely(new_buffer == NULL)) {
+        buf->len = 0;
+        return -1;
+    }
+    buf->buffer = new_buffer;
+    buf->size += extra;
+    return 0;
+}
+
+HttpHeaderBuffer *HttpHeaderGetBufferSpaceForTXID(DetectEngineThreadCtx *det_ctx,
+        Flow *f, uint8_t flags, uint64_t tx_id, const int keyword_id,
+        HttpHeaderThreadData **ret_hdr_td)
+{
+    int index = 0;
+    *ret_hdr_td = NULL;
+
+    HttpHeaderThreadData *hdr_td =
+        DetectThreadCtxGetGlobalKeywordThreadCtx(det_ctx, keyword_id);
+    if (hdr_td == NULL)
+        return NULL;
+    if (hdr_td->tick != det_ctx->ticker)
+        Reset(hdr_td, det_ctx->ticker);
+    *ret_hdr_td = hdr_td;
+
+    if (hdr_td->buffers_list_len == 0) {
+        /* get the inspect id to use as a 'base id' */
+        uint64_t base_inspect_id = AppLayerParserGetTransactionInspectId(f->alparser, flags);
+        BUG_ON(base_inspect_id > tx_id);
+        /* see how many space we need for the current tx_id */
+        uint64_t txs = (tx_id - base_inspect_id) + 1;
+        if (CreateSpace(hdr_td, txs) < 0)
+            return NULL;
+
+        index = (tx_id - base_inspect_id);
+        hdr_td->start_tx_id = base_inspect_id;
+        hdr_td->buffers_list_len = txs;
+    } else {
+        /* tx fits in our current buffers */
+        if ((tx_id - hdr_td->start_tx_id) < hdr_td->buffers_list_len) {
+            /* if we previously reassembled, return that buffer */
+            if (hdr_td->buffers[(tx_id - hdr_td->start_tx_id)].len != 0) {
+                return &hdr_td->buffers[(tx_id - hdr_td->start_tx_id)];
+            }
+            /* otherwise fall through */
+        } else {
+            /* not enough space, lets expand */
+            uint64_t txs = (tx_id - hdr_td->start_tx_id) + 1;
+            if (CreateSpace(hdr_td, txs) < 0)
+                return NULL;
+
+            hdr_td->buffers_list_len = txs;
+        }
+        index = (tx_id - hdr_td->start_tx_id);
+    }
+    HttpHeaderBuffer *buf = &hdr_td->buffers[index];
+    return buf;
+}
diff --git a/src/detect-http-header-common.h b/src/detect-http-header-common.h
new file mode 100644 (file)
index 0000000..c6fc5c6
--- /dev/null
@@ -0,0 +1,58 @@
+/* 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
+ * 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_HTTP_HEADER_COMMON_H__
+#define __DETECT_HTTP_HEADER_COMMON_H__
+
+typedef struct HttpHeaderBuffer_ {
+    uint8_t *buffer;
+    uint32_t size;      /**< buffer size */
+    uint32_t len;       /**< part of buffer in use */
+} HttpHeaderBuffer;
+
+typedef struct HttpHeaderThreadConfig_ {
+    uint16_t tx_step;
+    uint16_t size_step;
+} HttpHeaderThreadDataConfig;
+
+typedef struct HttpHeaderThreadData_ {
+    HttpHeaderBuffer *buffers;  /**< array of buffers */
+    uint16_t buffers_size;      /**< number of buffers */
+    uint16_t buffers_list_len;
+    uint16_t size_step;         /**< increase size of HttpHeaderBuffer::buffer with this */
+    uint16_t tx_step;           /**< increase number of txs with this */
+    uint64_t start_tx_id;
+    uint64_t tick;
+} HttpHeaderThreadData;
+
+void *HttpHeaderThreadDataInit(void *data);
+void HttpHeaderThreadDataFree(void *data);
+
+HttpHeaderBuffer *HttpHeaderGetBufferSpaceForTXID(DetectEngineThreadCtx *det_ctx,
+        Flow *f, uint8_t flags, uint64_t tx_id, const int keyword_id,
+        HttpHeaderThreadData **ret_hdr_td);
+
+int HttpHeaderExpandBuffer(HttpHeaderThreadData *td,
+        HttpHeaderBuffer *buf, uint32_t size);
+
+#endif /* __DETECT_HTTP_HEADER_COMMON_H__ */
index df7165f270a5f72430094fce253ea5226ca826ad..bdb204d2e15e4bf8aab25d4a661bd7c03e647c8a 100644 (file)
@@ -43,6 +43,7 @@
 #include "detect-engine-content-inspection.h"
 #include "detect-content.h"
 #include "detect-pcre.h"
+#include "detect-http-header-common.h"
 
 #include "flow.h"
 #include "flow-var.h"
@@ -72,158 +73,7 @@ static int g_keyword_thread_id = 0;
 
 #define BUFFER_TX_STEP      4
 #define BUFFER_SIZE_STEP    256
-
-typedef struct Buffer_ {
-    uint8_t *buffer;
-    uint32_t size;      /**< buffer size */
-    uint32_t len;       /**< part of buffer in use */
-} Buffer;
-
-typedef struct HttpHeaderNamesThreadData_ {
-    Buffer *buffers;        /**< array of buffers */
-    uint16_t buffers_size;  /**< number of buffers */
-    uint16_t buffers_list_len;
-    uint64_t start_tx_id;
-    uint64_t tick;
-} HttpHeaderNamesThreadData;
-
-static inline int CreateSpace(HttpHeaderNamesThreadData *hn, uint64_t size);
-static inline int ExpandBuffer(Buffer *buf, uint32_t size);
-
-static void *HttpHeaderNamesThreadDataInit(void *data)
-{
-    HttpHeaderNamesThreadData *d = SCCalloc(1, sizeof(*d));
-    if (d != NULL) {
-        /* initialize minimal buffers */
-        (void)CreateSpace(d, 1);
-        int i;
-        for (i = 0; i < d->buffers_size; i++) {
-            (void)ExpandBuffer(&d->buffers[i], 1);
-        }
-    }
-    return d;
-}
-
-static void HttpHeaderNamesThreadDataFree(void *data)
-{
-    HttpHeaderNamesThreadData *hdrnames = data;
-
-    int i;
-    for (i = 0; i < hdrnames->buffers_size; i++) {
-        if (hdrnames->buffers[i].buffer)
-            SCFree(hdrnames->buffers[i].buffer);
-        if (hdrnames->buffers[i].size) {
-            SCLogDebug("hdrnames->buffers[%d].size %u (%u)",
-                    i, hdrnames->buffers[i].size, hdrnames->buffers_size);
-        }
-    }
-    SCFree(hdrnames->buffers);
-    SCFree(hdrnames);
-}
-
-static void Reset(HttpHeaderNamesThreadData *hdrnames, uint64_t tick)
-{
-    uint16_t i;
-    for (i = 0; i < hdrnames->buffers_list_len; i++) {
-        hdrnames->buffers[i].len = 0;
-    }
-    hdrnames->buffers_list_len = 0;
-    hdrnames->start_tx_id = 0;
-    hdrnames->tick = tick;
-}
-
-static inline int CreateSpace(HttpHeaderNamesThreadData *hn, uint64_t size)
-{
-    if (size >= SHRT_MAX)
-        return -1;
-
-    if (size > hn->buffers_size) {
-        uint16_t extra = BUFFER_TX_STEP;
-        while (hn->buffers_size + extra < size) {
-            extra += BUFFER_TX_STEP;
-        }
-        SCLogDebug("adding %u to the buffer", (uint)extra);
-
-        void *ptmp = SCRealloc(hn->buffers,
-                         (hn->buffers_size + extra) * sizeof(Buffer));
-        if (ptmp == NULL) {
-            SCFree(hn->buffers);
-            hn->buffers = NULL;
-            hn->buffers_size = 0;
-            hn->buffers_list_len = 0;
-            return -1;
-        }
-        hn->buffers = ptmp;
-        memset(hn->buffers + hn->buffers_size, 0, extra * sizeof(Buffer));
-        hn->buffers_size += extra;
-    }
-
-    return 0;
-}
-
-static inline int ExpandBuffer(Buffer *buf, uint32_t size)
-{
-    size_t extra = BUFFER_SIZE_STEP;
-    while ((buf->size + extra) < (size + buf->len)) {
-        extra += BUFFER_SIZE_STEP;
-    }
-    SCLogDebug("adding %u to the buffer", (uint)extra);
-
-    uint8_t *new_buffer = SCRealloc(buf->buffer, buf->size + extra);
-    if (unlikely(new_buffer == NULL)) {
-        buf->len = 0;
-        return -1;
-    }
-    buf->buffer = new_buffer;
-    buf->size += extra;
-    return 0;
-}
-
-static Buffer *GetBufferSpaceForTXID(DetectEngineThreadCtx *det_ctx,
-        Flow *f, uint8_t flags, uint64_t tx_id)
-{
-    int index = 0;
-
-    HttpHeaderNamesThreadData *hdrnames =
-        DetectThreadCtxGetGlobalKeywordThreadCtx(det_ctx, g_keyword_thread_id);
-    if (hdrnames == NULL)
-        return NULL;
-    if (hdrnames->tick != det_ctx->ticker)
-        Reset(hdrnames, det_ctx->ticker);
-
-    if (hdrnames->buffers_list_len == 0) {
-        /* get the inspect id to use as a 'base id' */
-        uint64_t base_inspect_id = AppLayerParserGetTransactionInspectId(f->alparser, flags);
-        BUG_ON(base_inspect_id > tx_id);
-        /* see how many space we need for the current tx_id */
-        uint64_t txs = (tx_id - base_inspect_id) + 1;
-        if (CreateSpace(hdrnames, txs) < 0)
-            return NULL;
-
-        index = (tx_id - base_inspect_id);
-        hdrnames->start_tx_id = base_inspect_id;
-        hdrnames->buffers_list_len = txs;
-    } else {
-        /* tx fits in our current buffers */
-        if ((tx_id - hdrnames->start_tx_id) < hdrnames->buffers_list_len) {
-            /* if we previously reassembled, return that buffer */
-            if (hdrnames->buffers[(tx_id - hdrnames->start_tx_id)].len != 0) {
-                return &hdrnames->buffers[(tx_id - hdrnames->start_tx_id)];
-            }
-            /* otherwise fall through */
-        } else {
-            /* not enough space, lets expand */
-            uint64_t txs = (tx_id - hdrnames->start_tx_id) + 1;
-            if (CreateSpace(hdrnames, txs) < 0)
-                return NULL;
-
-            hdrnames->buffers_list_len = txs;
-        }
-        index = (tx_id - hdrnames->start_tx_id);
-    }
-    Buffer *buf = &hdrnames->buffers[index];
-    return buf;
-}
+static HttpHeaderThreadDataConfig g_td_config = { BUFFER_TX_STEP, BUFFER_SIZE_STEP };
 
 static uint8_t *GetBufferForTX(htp_tx_t *tx, uint64_t tx_id,
         DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx,
@@ -232,7 +82,9 @@ static uint8_t *GetBufferForTX(htp_tx_t *tx, uint64_t tx_id,
 {
     *buffer_len = 0;
 
-    Buffer *buf = GetBufferSpaceForTXID(det_ctx, f, flags, tx_id);
+    HttpHeaderThreadData *hdr_td = NULL;
+    HttpHeaderBuffer *buf = HttpHeaderGetBufferSpaceForTXID(det_ctx, f, flags,
+            tx_id, g_keyword_thread_id, &hdr_td);
     if (unlikely(buf == NULL)) {
         return NULL;
     } else if (buf->len > 0) {
@@ -269,7 +121,7 @@ static uint8_t *GetBufferForTX(htp_tx_t *tx, uint64_t tx_id,
 
         SCLogDebug("size %u + buf->len %u vs buf->size %u", (uint)size, buf->len, buf->size);
         if (size + buf->len > buf->size) {
-            if (ExpandBuffer(buf, size) != 0) {
+            if (HttpHeaderExpandBuffer(hdr_td, buf, size) != 0) {
                 return NULL;
             }
         }
@@ -551,7 +403,7 @@ void DetectHttpHeaderNamesRegister(void)
     g_buffer_id = DetectBufferTypeGetByName(BUFFER_NAME);
 
     g_keyword_thread_id = DetectRegisterThreadCtxGlobalFuncs(KEYWORD_NAME,
-            HttpHeaderNamesThreadDataInit, HttpHeaderNamesThreadDataFree);
+            HttpHeaderThreadDataInit, &g_td_config, HttpHeaderThreadDataFree);
 
     SCLogDebug("keyword %s registered. Thread id %d. "
             "Buffer %s registered. Buffer id %d",