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 \
--- /dev/null
+/* 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;
+}
--- /dev/null
+/* 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__ */
#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"
#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,
{
*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) {
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;
}
}
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",