suricata
detect-http-header.c
Go to the documentation of this file.
1/* Copyright (C) 2007-2022 Open Information Security Foundation
2 *
3 * You can copy, redistribute or modify this Program under the terms of
4 * the GNU General Public License version 2 as published by the Free
5 * Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * version 2 along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 */
17
18/**
19 * \ingroup httplayer
20 *
21 * @{
22 */
23
24
25/**
26 * \file
27 *
28 * \author Pablo Rincon <pablo.rincon.crespo@gmail.com>
29 *
30 * Implements support for http_header keyword.
31 */
32
33#include "suricata-common.h"
34#include "threads.h"
35#include "decode.h"
36
37#include "detect.h"
38#include "detect-parse.h"
39#include "detect-engine.h"
41#include "detect-engine-mpm.h"
42#include "detect-engine-state.h"
45#include "detect-content.h"
46#include "detect-pcre.h"
47
48#include "util-debug.h"
49#include "util-print.h"
50#include "util-memcmp.h"
51#include "util-profiling.h"
52#include "util-validate.h"
53
54#include "app-layer.h"
55#include "app-layer-parser.h"
56
57#include "app-layer-htp.h"
58#include "detect-http-header.h"
60
61static int DetectHttpHeaderSetup(DetectEngineCtx *, Signature *, const char *);
62#ifdef UNITTESTS
63static void DetectHttpHeaderRegisterTests(void);
64#endif
65static int g_http_header_buffer_id = 0;
66static int g_keyword_thread_id = 0;
67
68#define BUFFER_SIZE_STEP 1024
69static HttpHeaderThreadDataConfig g_td_config = { BUFFER_SIZE_STEP };
70
71static uint8_t *GetBufferForTX(
72 htp_tx_t *tx, DetectEngineThreadCtx *det_ctx, Flow *f, uint8_t flags, uint32_t *buffer_len)
73{
74 *buffer_len = 0;
75
76 HttpHeaderThreadData *hdr_td = NULL;
77 HttpHeaderBuffer *buf =
78 HttpHeaderGetBufferSpace(det_ctx, f, flags, g_keyword_thread_id, &hdr_td);
79 if (unlikely(buf == NULL)) {
80 return NULL;
81 }
82
83 const htp_headers_t *headers;
84 if (flags & STREAM_TOSERVER) {
85 if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP1, tx, flags) <=
86 HTP_REQUEST_PROGRESS_HEADERS)
87 return NULL;
88 headers = htp_tx_request_headers(tx);
89 } else {
90 if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP1, tx, flags) <=
91 HTP_RESPONSE_PROGRESS_HEADERS)
92 return NULL;
93 headers = htp_tx_response_headers(tx);
94 }
95 if (headers == NULL)
96 return NULL;
97
98 size_t i = 0;
99 size_t no_of_headers = htp_headers_size(headers);
100 for (; i < no_of_headers; i++) {
101 const htp_header_t *h = htp_headers_get_index(headers, i);
102 size_t size1 = htp_header_name_len(h);
103 size_t size2 = htp_header_value_len(h);
104
105 if (flags & STREAM_TOSERVER) {
106 if (size1 == 6 && SCMemcmpLowercase("cookie", htp_header_name_ptr(h), 6) == 0) {
107 continue;
108 }
109 } else {
110 if (size1 == 10 && SCMemcmpLowercase("set-cookie", htp_header_name_ptr(h), 10) == 0) {
111 continue;
112 }
113 }
114
115 size_t size = size1 + size2 + 4;
116#if 0
117 if (i + 1 == no_of_headers)
118 size += 2;
119#endif
120 if (size + buf->len > buf->size) {
121 if (HttpHeaderExpandBuffer(hdr_td, buf, size) != 0) {
122 return NULL;
123 }
124 }
125
126 memcpy(buf->buffer + buf->len, htp_header_name_ptr(h), htp_header_name_len(h));
127 buf->len += htp_header_name_len(h);
128 buf->buffer[buf->len++] = ':';
129 buf->buffer[buf->len++] = ' ';
130 memcpy(buf->buffer + buf->len, htp_header_value_ptr(h), htp_header_value_len(h));
131 buf->len += htp_header_value_len(h);
132 buf->buffer[buf->len++] = '\r';
133 buf->buffer[buf->len++] = '\n';
134#if 0 // looks like this breaks existing rules
135 if (i + 1 == no_of_headers) {
136 buf->buffer[buf->len++] = '\r';
137 buf->buffer[buf->len++] = '\n';
138 }
139#endif
140 }
141
142 *buffer_len = buf->len;
143 return buf->buffer;
144}
145
146static InspectionBuffer *GetBuffer2ForTX(DetectEngineThreadCtx *det_ctx,
147 const DetectEngineTransforms *transforms, Flow *_f, const uint8_t flow_flags, void *txv,
148 const int list_id)
149{
150 InspectionBuffer *buffer = InspectionBufferGet(det_ctx, list_id);
151 if (buffer->inspect == NULL) {
152 uint32_t b_len = 0;
153 const uint8_t *b = NULL;
154
155 if (SCHttp2TxGetHeaders(txv, flow_flags, &b, &b_len) != 1)
156 return NULL;
157 if (b == NULL || b_len == 0)
158 return NULL;
159
160 InspectionBufferSetupAndApplyTransforms(det_ctx, list_id, buffer, b, b_len, transforms);
161 }
162
163 return buffer;
164}
165
166/** \internal
167 * \brief custom inspect function to utilize the cached headers
168 */
169static uint8_t DetectEngineInspectBufferHttpHeader(DetectEngineCtx *de_ctx,
171 const Signature *s, Flow *f, uint8_t flags, void *alstate, void *txv, uint64_t tx_id)
172{
173 SCEnter();
174
175 const int list_id = engine->sm_list;
176 InspectionBuffer *buffer = InspectionBufferGet(det_ctx, list_id);
177 bool eof =
179 if (buffer->inspect == NULL) {
180 SCLogDebug("setting up inspect buffer %d", list_id);
181
182 /* if prefilter didn't already run, we need to consider transformations */
183 const DetectEngineTransforms *transforms = NULL;
184 if (!engine->mpm) {
185 transforms = engine->v2.transforms;
186 }
187
188 uint32_t rawdata_len = 0;
189 uint8_t *rawdata = GetBufferForTX(txv, det_ctx, f, flags, &rawdata_len);
190 if (rawdata_len == 0) {
191 SCLogDebug("no data");
192 if (engine->match_on_null && eof) {
194 }
195 goto end;
196 }
197 /* setup buffer and apply transforms */
199 det_ctx, list_id, buffer, rawdata, rawdata_len, transforms);
200 }
201
202 const uint32_t data_len = buffer->inspect_len;
203 const uint8_t *data = buffer->inspect;
204 const uint64_t offset = buffer->inspect_offset;
205
206 /* Inspect all the uricontents fetched on each
207 * transaction at the app layer */
208 const bool match = DetectEngineContentInspection(de_ctx, det_ctx, s, engine->smd, NULL, f,
209 (uint8_t *)data, data_len, offset, DETECT_CI_FLAGS_SINGLE,
211 if (match) {
213 }
214end:
215 if (eof) {
217 }
219}
220
226
227/** \brief Generic Mpm prefilter callback
228 *
229 * \param det_ctx detection engine thread ctx
230 * \param p packet to inspect
231 * \param f flow to inspect
232 * \param txv tx to inspect
233 * \param pectx inspection context
234 */
235static void PrefilterMpmHttpHeader(DetectEngineThreadCtx *det_ctx, const void *pectx, Packet *p,
236 Flow *f, void *txv, const uint64_t idx, const AppLayerTxData *_txd, const uint8_t flags)
237{
238 SCEnter();
239
240 const PrefilterMpmHttpHeaderCtx *ctx = pectx;
241 const MpmCtx *mpm_ctx = ctx->mpm_ctx;
242 SCLogDebug("running on list %d", ctx->list_id);
243
244 const int list_id = ctx->list_id;
245 InspectionBuffer *buffer = InspectionBufferGet(det_ctx, list_id);
246 if (buffer->inspect == NULL) {
247 uint32_t rawdata_len = 0;
248 uint8_t *rawdata = GetBufferForTX(txv, det_ctx, f, flags, &rawdata_len);
249 if (rawdata_len == 0)
250 return;
251
252 /* setup buffer and apply transforms */
254 det_ctx, list_id, buffer, rawdata, rawdata_len, ctx->transforms);
255 }
256
257 const uint32_t data_len = buffer->inspect_len;
258 const uint8_t *data = buffer->inspect;
259
260 SCLogDebug("mpm'ing buffer:");
261 //PrintRawDataFp(stdout, data, data_len);
262
263 if (data != NULL && data_len >= mpm_ctx->minlen) {
264 (void)mpm_table[mpm_ctx->mpm_type].Search(
265 mpm_ctx, &det_ctx->mtc, &det_ctx->pmq, data, data_len);
266 PREFILTER_PROFILING_ADD_BYTES(det_ctx, data_len);
267 }
268}
269
270static void PrefilterMpmHttpTrailer(DetectEngineThreadCtx *det_ctx, const void *pectx, Packet *p,
271 Flow *f, void *txv, const uint64_t idx, const AppLayerTxData *_txd, const uint8_t flags)
272{
273 SCEnter();
274
275 htp_tx_t *tx = txv;
276 const HtpTxUserData *htud = (const HtpTxUserData *)htp_tx_get_user_data(tx);
277 /* if the request wasn't flagged as having a trailer, we skip */
278 if (((flags & STREAM_TOSERVER) && !htud->request_has_trailers) ||
279 ((flags & STREAM_TOCLIENT) && !htud->response_has_trailers)) {
280 SCReturn;
281 }
282 PrefilterMpmHttpHeader(det_ctx, pectx, p, f, txv, idx, _txd, flags);
283 SCReturn;
284}
285
286static void PrefilterMpmHttpHeaderFree(void *ptr)
287{
288 SCFree(ptr);
289}
290
291static int PrefilterMpmHttpHeaderRequestRegister(DetectEngineCtx *de_ctx, SigGroupHead *sgh,
292 MpmCtx *mpm_ctx, const DetectBufferMpmRegistry *mpm_reg, int list_id)
293{
294 SCEnter();
295
296 /* header */
297 PrefilterMpmHttpHeaderCtx *pectx = SCCalloc(1, sizeof(*pectx));
298 if (pectx == NULL)
299 return -1;
300 pectx->list_id = list_id;
301 pectx->mpm_ctx = mpm_ctx;
302 pectx->transforms = &mpm_reg->transforms;
303
304 int r = PrefilterAppendTxEngine(de_ctx, sgh, PrefilterMpmHttpHeader, mpm_reg->app_v2.alproto,
305 HTP_REQUEST_PROGRESS_HEADERS, pectx, PrefilterMpmHttpHeaderFree, mpm_reg->pname);
306 if (r != 0) {
307 SCFree(pectx);
308 return r;
309 }
310
311 /* trailer */
312 pectx = SCCalloc(1, sizeof(*pectx));
313 if (pectx == NULL)
314 return -1;
315 pectx->list_id = list_id;
316 pectx->mpm_ctx = mpm_ctx;
317 pectx->transforms = &mpm_reg->transforms;
318
319 r = PrefilterAppendTxEngine(de_ctx, sgh, PrefilterMpmHttpTrailer, mpm_reg->app_v2.alproto,
320 HTP_REQUEST_PROGRESS_TRAILER, pectx, PrefilterMpmHttpHeaderFree, mpm_reg->pname);
321 if (r != 0) {
322 SCFree(pectx);
323 }
324 return r;
325}
326
327static int PrefilterMpmHttpHeaderResponseRegister(DetectEngineCtx *de_ctx, SigGroupHead *sgh,
328 MpmCtx *mpm_ctx, const DetectBufferMpmRegistry *mpm_reg, int list_id)
329{
330 SCEnter();
331
332 /* header */
333 PrefilterMpmHttpHeaderCtx *pectx = SCCalloc(1, sizeof(*pectx));
334 if (pectx == NULL)
335 return -1;
336 pectx->list_id = list_id;
337 pectx->mpm_ctx = mpm_ctx;
338 pectx->transforms = &mpm_reg->transforms;
339
340 int r = PrefilterAppendTxEngine(de_ctx, sgh, PrefilterMpmHttpHeader, mpm_reg->app_v2.alproto,
341 HTP_RESPONSE_PROGRESS_HEADERS, pectx, PrefilterMpmHttpHeaderFree, mpm_reg->pname);
342 if (r != 0) {
343 SCFree(pectx);
344 return r;
345 }
346
347 /* trailer */
348 pectx = SCCalloc(1, sizeof(*pectx));
349 if (pectx == NULL)
350 return -1;
351 pectx->list_id = list_id;
352 pectx->mpm_ctx = mpm_ctx;
353 pectx->transforms = &mpm_reg->transforms;
354
355 r = PrefilterAppendTxEngine(de_ctx, sgh, PrefilterMpmHttpTrailer, mpm_reg->app_v2.alproto,
356 HTP_RESPONSE_PROGRESS_TRAILER, pectx, PrefilterMpmHttpHeaderFree, mpm_reg->pname);
357 if (r != 0) {
358 SCFree(pectx);
359 }
360 return r;
361}
362
363/**
364 * \brief The setup function for the http_header keyword for a signature.
365 *
366 * \param de_ctx Pointer to the detection engine context.
367 * \param s Pointer to signature for the current Signature being parsed
368 * from the rules.
369 * \param m Pointer to the head of the SigMatchs for the current rule
370 * being parsed.
371 * \param arg Pointer to the string holding the keyword value.
372 *
373 * \retval 0 On success.
374 * \retval -1 On failure.
375 */
376static int DetectHttpHeaderSetup(DetectEngineCtx *de_ctx, Signature *s, const char *arg)
377{
379 de_ctx, s, arg, DETECT_HTTP_HEADER_CM, g_http_header_buffer_id, ALPROTO_HTTP1);
380}
381
382/**
383 * \brief this function setup the http.header keyword used in the rule
384 *
385 * \param de_ctx Pointer to the Detection Engine Context
386 * \param s Pointer to the Signature to which the current keyword belongs
387 * \param str Should hold an empty string always
388 *
389 * \retval 0 On success
390 */
391static int DetectHttpHeaderSetupSticky(DetectEngineCtx *de_ctx, Signature *s, const char *str)
392{
393 if (SCDetectBufferSetActiveList(de_ctx, s, g_http_header_buffer_id) < 0)
394 return -1;
396 return -1;
397 return 0;
398}
399
400/**
401 * \brief Registers the keyword handlers for the "http_header" keyword.
402 */
404{
405 /* http_header content modifier */
408 "content modifier to match only on the HTTP header-buffer";
410 "/rules/http-keywords.html#http-header-and-http-raw-header";
411 sigmatch_table[DETECT_HTTP_HEADER_CM].Setup = DetectHttpHeaderSetup;
412#ifdef UNITTESTS
414#endif
418
419 /* http.header sticky buffer */
420 sigmatch_table[DETECT_HTTP_HEADER].name = "http.header";
421 sigmatch_table[DETECT_HTTP_HEADER].desc = "sticky buffer to match on the normalized HTTP header-buffer";
422 sigmatch_table[DETECT_HTTP_HEADER].url = "/rules/http-keywords.html#http-header-and-http-raw-header";
423 sigmatch_table[DETECT_HTTP_HEADER].Setup = DetectHttpHeaderSetupSticky;
426
428 HTP_REQUEST_PROGRESS_HEADERS, DetectEngineInspectBufferHttpHeader, NULL);
430 PrefilterMpmHttpHeaderRequestRegister, NULL, ALPROTO_HTTP1,
431 0); /* not used, registered twice: HEADERS/TRAILER */
432
434 HTP_RESPONSE_PROGRESS_HEADERS, DetectEngineInspectBufferHttpHeader, NULL);
436 PrefilterMpmHttpHeaderResponseRegister, NULL, ALPROTO_HTTP1,
437 0); /* not used, registered twice: HEADERS/TRAILER */
438
440 HTTP2StateDataClient, DetectEngineInspectBufferGeneric, GetBuffer2ForTX);
442 GetBuffer2ForTX, ALPROTO_HTTP2, HTTP2StateDataClient);
443
445 HTTP2StateDataServer, DetectEngineInspectBufferGeneric, GetBuffer2ForTX);
447 GetBuffer2ForTX, ALPROTO_HTTP2, HTTP2StateDataServer);
448
450 "http headers");
451
452 g_http_header_buffer_id = DetectBufferTypeGetByName("http_header");
453
454 g_keyword_thread_id = DetectRegisterThreadCtxGlobalFuncs("http_header",
456}
457
458static int g_http_request_header_buffer_id = 0;
459static int g_http_response_header_buffer_id = 0;
460static int g_request_header_thread_id = 0;
461static int g_response_header_thread_id = 0;
462
463typedef struct HttpMultiBufItem {
464 uint8_t *buffer;
465 uint32_t len;
467
469 // array of items, being defined as a buffer with its length just above
471 // capacity of items (size of allocation)
472 size_t cap;
473 // length of items (number in use)
474 size_t len;
476
477static void *HttpMultiBufHeaderThreadDataInit(void *data)
478{
479 HttpMultiBufHeaderThreadData *td = SCCalloc(1, sizeof(*td));
480
481 /* This return value check to satisfy our Cocci malloc checks. */
482 if (td == NULL) {
483 SCLogError("failed to allocate %" PRIuMAX " bytes: %s", (uintmax_t)sizeof(*td),
484 strerror(errno));
485 return NULL;
486 }
487 return td;
488}
489
490static void HttpMultiBufHeaderThreadDataFree(void *data)
491{
493 for (size_t i = 0; i < td->cap; i++) {
494 SCFree(td->items[i].buffer);
495 }
496 SCFree(td->items);
497 SCFree(td);
498}
499
500static bool GetHttp1HeaderData(DetectEngineThreadCtx *det_ctx, const void *txv, const uint8_t flags,
501 uint32_t local_id, const uint8_t **buf, uint32_t *buf_len)
502{
503 SCEnter();
504
505 int kw_thread_id;
506 if (flags & STREAM_TOSERVER) {
507 kw_thread_id = g_request_header_thread_id;
508 } else {
509 kw_thread_id = g_response_header_thread_id;
510 }
512 DetectThreadCtxGetGlobalKeywordThreadCtx(det_ctx, kw_thread_id);
513 if (unlikely(hdr_td == NULL)) {
514 return false;
515 }
516
517 htp_tx_t *tx = (htp_tx_t *)txv;
518 const htp_headers_t *headers;
519 if (flags & STREAM_TOSERVER) {
520 headers = htp_tx_request_headers(tx);
521 } else {
522 headers = htp_tx_response_headers(tx);
523 }
524 size_t no_of_headers = htp_headers_size(headers);
525 if (local_id == 0) {
526 // We initialize a big buffer on first item
527 // Then, we will just use parts of it
528 hdr_td->len = 0;
529 if (hdr_td->cap < no_of_headers) {
530 void *new_buffer = SCRealloc(hdr_td->items, no_of_headers * sizeof(HttpMultiBufItem));
531 if (unlikely(new_buffer == NULL)) {
532 return NULL;
533 }
534 hdr_td->items = new_buffer;
535 // zeroes the new part of the items
536 memset(hdr_td->items + hdr_td->cap, 0,
537 (no_of_headers - hdr_td->cap) * sizeof(HttpMultiBufItem));
538 hdr_td->cap = no_of_headers;
539 }
540 for (size_t i = 0; i < no_of_headers; i++) {
541 const htp_header_t *h = htp_headers_get_index(headers, i);
542 uint32_t size1 = (uint32_t)htp_header_name_len(h);
543 uint32_t size2 = (uint32_t)htp_header_value_len(h);
544 uint32_t size = size1 + size2 + 2;
545 if (hdr_td->items[i].len < size) {
546 // Use realloc, as this pointer is not freed until HttpMultiBufHeaderThreadDataFree
547 void *tmp = SCRealloc(hdr_td->items[i].buffer, size);
548 if (unlikely(tmp == NULL)) {
549 return NULL;
550 }
551 hdr_td->items[i].buffer = tmp;
552 }
553 memcpy(hdr_td->items[i].buffer, htp_header_name_ptr(h), size1);
554 hdr_td->items[i].buffer[size1] = ':';
555 hdr_td->items[i].buffer[size1 + 1] = ' ';
556 memcpy(hdr_td->items[i].buffer + size1 + 2, htp_header_value_ptr(h), size2);
557 hdr_td->items[i].len = size;
558 }
559 hdr_td->len = no_of_headers;
560 }
561
562 // cbdata->local_id is the index of the requested header buffer
563 // hdr_td->len is the number of header buffers
564 if (local_id < hdr_td->len) {
565 // we have one valid header buffer
566 *buf = hdr_td->items[local_id].buffer;
567 *buf_len = hdr_td->items[local_id].len;
568 return true;
569 } // else there are no more header buffer to get
570 return false;
571}
572
573static int DetectHTTPRequestHeaderSetup(DetectEngineCtx *de_ctx, Signature *s, const char *arg)
574{
575 if (SCDetectBufferSetActiveList(de_ctx, s, g_http_request_header_buffer_id) < 0)
576 return -1;
577
579 return -1;
580
581 return 0;
582}
583
585{
586 sigmatch_table[DETECT_HTTP_REQUEST_HEADER].name = "http.request_header";
588 "sticky buffer to match on only one HTTP header name and value";
589 sigmatch_table[DETECT_HTTP_REQUEST_HEADER].url = "/rules/http-keywords.html#request_header";
590 sigmatch_table[DETECT_HTTP_REQUEST_HEADER].Setup = DetectHTTPRequestHeaderSetup;
593
595 HTTP2StateOpen, SCHttp2TxGetHeader, 2);
597 HTP_REQUEST_PROGRESS_HEADERS, GetHttp1HeaderData, 2);
598
599 DetectBufferTypeSetDescriptionByName("http_request_header", "HTTP header name and value");
600 g_http_request_header_buffer_id = DetectBufferTypeGetByName("http_request_header");
601 DetectBufferTypeSupportsMultiInstance("http_request_header");
602 g_request_header_thread_id = DetectRegisterThreadCtxGlobalFuncs("http_request_header",
603 HttpMultiBufHeaderThreadDataInit, NULL, HttpMultiBufHeaderThreadDataFree);
604}
605
606static int DetectHTTPResponseHeaderSetup(DetectEngineCtx *de_ctx, Signature *s, const char *arg)
607{
608 if (SCDetectBufferSetActiveList(de_ctx, s, g_http_response_header_buffer_id) < 0)
609 return -1;
610
612 return -1;
613
614 return 0;
615}
616
618{
619 sigmatch_table[DETECT_HTTP_RESPONSE_HEADER].name = "http.response_header";
621 "sticky buffer to match on only one HTTP header name and value";
622 sigmatch_table[DETECT_HTTP_RESPONSE_HEADER].url = "/rules/http2-keywords.html#response_header";
623 sigmatch_table[DETECT_HTTP_RESPONSE_HEADER].Setup = DetectHTTPResponseHeaderSetup;
626
628 HTTP2StateOpen, SCHttp2TxGetHeader, 2);
630 HTP_RESPONSE_PROGRESS_HEADERS, GetHttp1HeaderData, 2);
631
632 DetectBufferTypeSetDescriptionByName("http_response_header", "HTTP header name and value");
633 g_http_response_header_buffer_id = DetectBufferTypeGetByName("http_response_header");
634 DetectBufferTypeSupportsMultiInstance("http_response_header");
635 g_response_header_thread_id = DetectRegisterThreadCtxGlobalFuncs("http_response_header",
636 HttpMultiBufHeaderThreadDataInit, NULL, HttpMultiBufHeaderThreadDataFree);
637}
638
639/************************************Unittests*********************************/
640
641#ifdef UNITTESTS
643#endif
644
645/**
646 * @}
647 */
uint8_t len
int AppLayerParserGetStateProgress(uint8_t ipproto, AppProto alproto, void *alstate, uint8_t flags)
get the progress value for a tx/protocol
struct AppLayerTxData AppLayerTxData
@ ALPROTO_HTTP2
@ ALPROTO_HTTP
@ ALPROTO_HTTP1
uint8_t flags
Definition decode-gre.h:0
int SCDetectBufferSetActiveList(DetectEngineCtx *de_ctx, Signature *s, const int list)
bool DetectEngineContentInspection(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, const Signature *s, const SigMatchData *smd, Packet *p, Flow *f, const uint8_t *buffer, const uint32_t buffer_len, const uint64_t stream_start_offset, const uint8_t flags, const enum DetectContentInspectionType inspection_mode)
wrapper around DetectEngineContentInspectionInternal to return true/false only
@ DETECT_ENGINE_CONTENT_INSPECTION_MODE_STATE
#define DETECT_CI_FLAGS_SINGLE
void InspectionBufferSetupAndApplyTransforms(DetectEngineThreadCtx *det_ctx, const int list_id, InspectionBuffer *buffer, const uint8_t *data, const uint32_t data_len, const DetectEngineTransforms *transforms)
setup the buffer with our initial data
InspectionBuffer * InspectionBufferGet(DetectEngineThreadCtx *det_ctx, const int list_id)
void DetectAppLayerMpmRegister(const char *name, int direction, int priority, PrefilterRegisterFunc PrefilterRegister, InspectionBufferGetDataPtr GetData, AppProto alproto, int tx_min_progress)
register an app layer keyword for mpm
int PrefilterGenericMpmRegister(DetectEngineCtx *de_ctx, SigGroupHead *sgh, MpmCtx *mpm_ctx, const DetectBufferMpmRegistry *mpm_reg, int list_id)
int PrefilterAppendTxEngine(DetectEngineCtx *de_ctx, SigGroupHead *sgh, PrefilterTxFn PrefilterTxFunc, AppProto alproto, int tx_min_progress, void *pectx, void(*FreeFunc)(void *pectx), const char *name)
@ DETECT_HTTP_REQUEST_HEADER
@ DETECT_HTTP_RESPONSE_HEADER
@ DETECT_HTTP_HEADER
@ DETECT_HTTP_HEADER_CM
Data structures and function prototypes for keeping state for the detection engine.
#define DETECT_ENGINE_INSPECT_SIG_MATCH
#define DETECT_ENGINE_INSPECT_SIG_CANT_MATCH
#define DETECT_ENGINE_INSPECT_SIG_NO_MATCH
int DetectRegisterThreadCtxGlobalFuncs(const char *name, void *(*InitFunc)(void *), void *data, void(*FreeFunc)(void *))
Register Thread keyword context Funcs (Global)
void DetectBufferTypeSetDescriptionByName(const char *name, const char *desc)
void DetectBufferTypeSupportsMultiInstance(const char *name)
uint8_t DetectEngineInspectBufferGeneric(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, const DetectEngineAppInspectionEngine *engine, const Signature *s, Flow *f, uint8_t flags, void *alstate, void *txv, uint64_t tx_id)
Do the content inspection & validation for a signature.
void DetectAppLayerInspectEngineRegister(const char *name, AppProto alproto, uint32_t dir, int progress, InspectEngineFuncPtr Callback, InspectionBufferGetDataPtr GetData)
Registers an app inspection engine.
void * DetectThreadCtxGetGlobalKeywordThreadCtx(DetectEngineThreadCtx *det_ctx, int id)
Retrieve thread local keyword ctx by id.
void DetectAppLayerMultiRegister(const char *name, AppProto alproto, uint32_t dir, int progress, InspectionMultiBufferGetDataPtr GetData, int priority)
int DetectBufferTypeGetByName(const char *name)
void DetectHttpHeaderRegister(void)
Registers the keyword handlers for the "http_header" keyword.
#define BUFFER_SIZE_STEP
void DetectHttpResponseHeaderRegister(void)
void DetectHttpRequestHeaderRegister(void)
int SCDetectSignatureSetAppProto(Signature *s, AppProto alproto)
int DetectEngineContentModifierBufferSetup(DetectEngineCtx *de_ctx, Signature *s, const char *arg, int sm_type, int sm_list, AppProto alproto)
SigTableElmt * sigmatch_table
#define SIGMATCH_NOOPT
Definition detect.h:1651
#define SIG_FLAG_TOCLIENT
Definition detect.h:272
#define SIGMATCH_INFO_STICKY_BUFFER
Definition detect.h:1676
#define SIG_FLAG_TOSERVER
Definition detect.h:271
#define SIGMATCH_INFO_CONTENT_MODIFIER
Definition detect.h:1674
DetectEngineCtx * de_ctx
int HttpHeaderExpandBuffer(HttpHeaderThreadData *td, HttpHeaderBuffer *buf, size_t size)
HttpHeaderBuffer * HttpHeaderGetBufferSpace(DetectEngineThreadCtx *det_ctx, Flow *f, uint8_t flags, const int keyword_id, HttpHeaderThreadData **ret_hdr_td)
void * HttpHeaderThreadDataInit(void *data)
void HttpHeaderThreadDataFree(void *data)
struct Thresholds ctx
one time registration of keywords at start up
Definition detect.h:762
DetectEngineTransforms transforms
Definition detect.h:775
struct DetectBufferMpmRegistry_::@98::@100 app_v2
const DetectEngineTransforms * transforms
Definition detect.h:436
struct DetectEngineAppInspectionEngine_::@90 v2
main detection engine ctx
Definition detect.h:932
MpmThreadCtx mtc
Definition detect.h:1345
PrefilterRuleStore pmq
Definition detect.h:1349
Flow data structure.
Definition flow.h:356
uint8_t proto
Definition flow.h:378
AppProto alproto
application level protocol
Definition flow.h:450
uint8_t request_has_trailers
uint8_t response_has_trailers
uint8_t mpm_type
Definition util-mpm.h:95
uint16_t minlen
Definition util-mpm.h:104
uint32_t(* Search)(const struct MpmCtx_ *, struct MpmThreadCtx_ *, PrefilterRuleStore *, const uint8_t *, uint32_t)
Definition util-mpm.h:178
const DetectEngineTransforms * transforms
Container for matching data for a signature group.
Definition detect.h:1629
const char * url
Definition detect.h:1462
int(* Setup)(DetectEngineCtx *, Signature *, const char *)
Definition detect.h:1441
uint16_t alternative
Definition detect.h:1457
uint16_t flags
Definition detect.h:1450
const char * desc
Definition detect.h:1461
void(* RegisterTests)(void)
Definition detect.h:1448
const char * name
Definition detect.h:1459
Signature container.
Definition detect.h:668
#define str(s)
void DetectHttpHeaderRegisterTests(void)
#define SCEnter(...)
Definition util-debug.h:277
#define SCLogDebug(...)
Definition util-debug.h:275
#define SCLogError(...)
Macro used to log ERROR messages.
Definition util-debug.h:267
#define SCReturn
Definition util-debug.h:279
#define SCFree(p)
Definition util-mem.h:61
#define SCRealloc(ptr, sz)
Definition util-mem.h:50
#define SCCalloc(nm, sz)
Definition util-mem.h:53
MpmTableElmt mpm_table[MPM_TABLE_SIZE]
Definition util-mpm.c:47
#define unlikely(expr)
#define PREFILTER_PROFILING_ADD_BYTES(det_ctx, bytes)
uint64_t offset