From 415b036dca5cb89409d2002b366ee489755d5d37 Mon Sep 17 00:00:00 2001 From: Philippe Antoine Date: Thu, 23 Mar 2023 10:43:07 +0100 Subject: [PATCH] http1: implement http.request_header So that it is generic for HTTP1 and HTTP2 Ticket: #5780 --- doc/userguide/rules/http-keywords.rst | 37 +++ doc/userguide/rules/http2-keywords.rst | 31 --- src/detect-engine-register.c | 2 + src/detect-http-header.c | 321 +++++++++++++++++++++++++ src/detect-http-header.h | 2 + src/detect-http2.c | 181 -------------- 6 files changed, 362 insertions(+), 212 deletions(-) diff --git a/doc/userguide/rules/http-keywords.rst b/doc/userguide/rules/http-keywords.rst index 4063165739..fa8c5ff1e2 100644 --- a/doc/userguide/rules/http-keywords.rst +++ b/doc/userguide/rules/http-keywords.rst @@ -684,6 +684,43 @@ like ``distance``, ``offset``, ``within``, etc. The ``nocase`` keyword is not allowed anymore. Keep in mind that you need to specify a lowercase pattern. +http.request_header +------------------- + +Match on the name and value of a HTTP request header (HTTP1 or HTTP2). + +For HTTP2, name and value get concatenated by ": ", colon and space. +To detect if a http2 header name contains ':', +the keyword ``http2.header_name`` can be used. + +Examples:: + + http.request_header; content:"agent: nghttp2"; + http.request_header; content:"custom-header: I love::colons"; + +``http.request_header`` is a 'sticky buffer'. + +``http.request_header`` can be used as ``fast_pattern``. + + +http.response_header +-------------------- + +Match on the name and value of a HTTP response header (HTTP1 or HTTP2). + +For HTTP2, name and value get concatenated by ": ", colon and space. +To detect if a http2 header name contains ':', +the keyword ``http2.header_name`` can be used. + +Examples:: + + http.response_header; content:"server: nghttp2"; + http.response_header; content:"custom-header: I love::colons"; + +``http.response_header`` is a 'sticky buffer'. + +``http.response_header`` can be used as ``fast_pattern``. + Notes ~~~~~ diff --git a/doc/userguide/rules/http2-keywords.rst b/doc/userguide/rules/http2-keywords.rst index f02c54e5f5..37cb855e0a 100644 --- a/doc/userguide/rules/http2-keywords.rst +++ b/doc/userguide/rules/http2-keywords.rst @@ -110,37 +110,6 @@ Examples:: ``http2.header_name`` can be used as ``fast_pattern``. -http.request_header -------------------- - -Match on the name and value of a HTTP2 request header from a HEADER frame (or PUSH_PROMISE or CONTINUATION). -Name and value get concatenated by ": ", colon and space. - -Examples:: - - http.request_header; content:"agent: nghttp2"; - http.request_header; content:"custom-header: I love::colons"; - -``http.request_header`` is a 'sticky buffer'. - -``http.request_header`` can be used as ``fast_pattern``. - - -http.response_header --------------------- - -Match on the name and value of a HTTP2 response header from a HEADER frame (or PUSH_PROMISE or CONTINUATION). -Name and value get concatenated by ": ", colon and space. - -Examples:: - - http.response_header; content:"server: nghttp2"; - http.response_header; content:"custom-header: I love::colons"; - -``http.response_header`` is a 'sticky buffer'. - -``http.response_header`` can be used as ``fast_pattern``. - Additional information ---------------------- diff --git a/src/detect-engine-register.c b/src/detect-engine-register.c index 9ab4d3a18a..c56757e13f 100644 --- a/src/detect-engine-register.c +++ b/src/detect-engine-register.c @@ -477,6 +477,8 @@ void SigTableSetup(void) DetectHttpResponseLineRegister(); DetectHttpServerBodyRegister(); DetectHttpHeaderRegister(); + DetectHttpRequestHeaderRegister(); + DetectHttpResponseHeaderRegister(); DetectHttpHeaderNamesRegister(); DetectHttpHeadersRegister(); DetectHttpProtocolRegister(); diff --git a/src/detect-http-header.c b/src/detect-http-header.c index 87dce2e8e1..cc11cdf0c0 100644 --- a/src/detect-http-header.c +++ b/src/detect-http-header.c @@ -465,6 +465,327 @@ void DetectHttpHeaderRegister(void) HttpHeaderThreadDataInit, &g_td_config, HttpHeaderThreadDataFree); } +static int g_http_request_header_buffer_id = 0; +static int g_http_response_header_buffer_id = 0; + +static InspectionBuffer *GetHttp2HeaderData(DetectEngineThreadCtx *det_ctx, const uint8_t flags, + const DetectEngineTransforms *transforms, Flow *_f, const struct MpmListIdDataArgs *cbdata, + int list_id) +{ + SCEnter(); + + InspectionBuffer *buffer = + InspectionBufferMultipleForListGet(det_ctx, list_id, cbdata->local_id); + if (buffer == NULL) + return NULL; + if (buffer->initialized) + return buffer; + + uint32_t b_len = 0; + const uint8_t *b = NULL; + + if (rs_http2_tx_get_header(cbdata->txv, flags, cbdata->local_id, &b, &b_len) != 1) { + InspectionBufferSetupMultiEmpty(buffer); + return NULL; + } + if (b == NULL || b_len == 0) { + InspectionBufferSetupMultiEmpty(buffer); + return NULL; + } + + InspectionBufferSetupMulti(buffer, transforms, b, b_len); + + SCReturnPtr(buffer, "InspectionBuffer"); +} + +static void PrefilterTxHttp2Header(DetectEngineThreadCtx *det_ctx, const void *pectx, Packet *p, + Flow *f, void *txv, const uint64_t idx, const AppLayerTxData *_txd, const uint8_t flags) +{ + SCEnter(); + + const PrefilterMpmListId *ctx = (const PrefilterMpmListId *)pectx; + const MpmCtx *mpm_ctx = ctx->mpm_ctx; + const int list_id = ctx->list_id; + + uint32_t local_id = 0; + + while (1) { + // loop until we get a NULL + + struct MpmListIdDataArgs cbdata = { local_id, txv }; + InspectionBuffer *buffer = + GetHttp2HeaderData(det_ctx, flags, ctx->transforms, f, &cbdata, list_id); + if (buffer == NULL) + break; + + if (buffer->inspect_len >= mpm_ctx->minlen) { + (void)mpm_table[mpm_ctx->mpm_type].Search( + mpm_ctx, &det_ctx->mtcu, &det_ctx->pmq, buffer->inspect, buffer->inspect_len); + PREFILTER_PROFILING_ADD_BYTES(det_ctx, buffer->inspect_len); + } + + local_id++; + } +} + +static uint8_t DetectEngineInspectHttp2Header(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) +{ + uint32_t local_id = 0; + + const DetectEngineTransforms *transforms = NULL; + if (!engine->mpm) { + transforms = engine->v2.transforms; + } + + while (1) { + struct MpmListIdDataArgs cbdata = { + local_id, + txv, + }; + InspectionBuffer *buffer = + GetHttp2HeaderData(det_ctx, flags, transforms, f, &cbdata, engine->sm_list); + + if (buffer == NULL || buffer->inspect == NULL) + break; + + det_ctx->buffer_offset = 0; + det_ctx->discontinue_matching = 0; + det_ctx->inspection_recursion_counter = 0; + + const int match = DetectEngineContentInspection(de_ctx, det_ctx, s, engine->smd, NULL, f, + (uint8_t *)buffer->inspect, buffer->inspect_len, buffer->inspect_offset, + DETECT_CI_FLAGS_SINGLE, DETECT_ENGINE_CONTENT_INSPECTION_MODE_STATE); + if (match == 1) { + return DETECT_ENGINE_INSPECT_SIG_MATCH; + } + local_id++; + } + + return DETECT_ENGINE_INSPECT_SIG_NO_MATCH; +} + +static int PrefilterMpmHttp2HeaderRegister(DetectEngineCtx *de_ctx, SigGroupHead *sgh, + MpmCtx *mpm_ctx, const DetectBufferMpmRegistry *mpm_reg, int list_id) +{ + PrefilterMpmListId *pectx = SCCalloc(1, sizeof(*pectx)); + if (pectx == NULL) + return -1; + pectx->list_id = list_id; + pectx->mpm_ctx = mpm_ctx; + pectx->transforms = &mpm_reg->transforms; + + return PrefilterAppendTxEngine(de_ctx, sgh, PrefilterTxHttp2Header, mpm_reg->app_v2.alproto, + mpm_reg->app_v2.tx_min_progress, pectx, PrefilterMpmHttpHeaderFree, mpm_reg->name); +} + +static InspectionBuffer *GetHttp1HeaderData(DetectEngineThreadCtx *det_ctx, const uint8_t flags, + const DetectEngineTransforms *transforms, Flow *f, const struct MpmListIdDataArgs *cbdata, + int list_id) +{ + SCEnter(); + + InspectionBuffer *buffer = + InspectionBufferMultipleForListGet(det_ctx, list_id, cbdata->local_id); + if (buffer == NULL) + return NULL; + if (buffer->initialized) + return buffer; + + HttpHeaderThreadData *hdr_td = NULL; + HttpHeaderBuffer *buf = + HttpHeaderGetBufferSpace(det_ctx, f, flags, g_keyword_thread_id, &hdr_td); + if (unlikely(buf == NULL)) { + return NULL; + } + + htp_tx_t *tx = (htp_tx_t *)cbdata->txv; + htp_table_t *headers; + if (flags & STREAM_TOSERVER) { + headers = tx->request_headers; + } else { + headers = tx->response_headers; + } + if (cbdata->local_id < htp_table_size(headers)) { + htp_header_t *h = htp_table_get_index(headers, cbdata->local_id, NULL); + size_t size1 = bstr_size(h->name); + size_t size2 = bstr_size(h->value); + size_t b_len = size1 + 2 + size2; + if (b_len > buf->size) { + if (HttpHeaderExpandBuffer(hdr_td, buf, b_len) != 0) { + return NULL; + } + } + memcpy(buf->buffer, bstr_ptr(h->name), bstr_size(h->name)); + buf->buffer[size1] = ':'; + buf->buffer[size1 + 1] = ' '; + memcpy(buf->buffer + size1 + 2, bstr_ptr(h->value), bstr_size(h->value)); + buf->len = b_len; + } else { + InspectionBufferSetupMultiEmpty(buffer); + return NULL; + } + if (buf->len == 0) { + InspectionBufferSetupMultiEmpty(buffer); + return NULL; + } + + InspectionBufferSetupMulti(buffer, transforms, buf->buffer, buf->len); + + SCReturnPtr(buffer, "InspectionBuffer"); +} + +static void PrefilterTxHttp1Header(DetectEngineThreadCtx *det_ctx, const void *pectx, Packet *p, + Flow *f, void *txv, const uint64_t idx, const AppLayerTxData *_txd, const uint8_t flags) +{ + SCEnter(); + + const PrefilterMpmListId *ctx = (const PrefilterMpmListId *)pectx; + const MpmCtx *mpm_ctx = ctx->mpm_ctx; + const int list_id = ctx->list_id; + + uint32_t local_id = 0; + + while (1) { + // loop until we get a NULL + + struct MpmListIdDataArgs cbdata = { local_id, txv }; + InspectionBuffer *buffer = + GetHttp1HeaderData(det_ctx, flags, ctx->transforms, f, &cbdata, list_id); + if (buffer == NULL) + break; + + if (buffer->inspect_len >= mpm_ctx->minlen) { + (void)mpm_table[mpm_ctx->mpm_type].Search( + mpm_ctx, &det_ctx->mtcu, &det_ctx->pmq, buffer->inspect, buffer->inspect_len); + PREFILTER_PROFILING_ADD_BYTES(det_ctx, buffer->inspect_len); + } + + local_id++; + } +} + +static int PrefilterMpmHttp1HeaderRegister(DetectEngineCtx *de_ctx, SigGroupHead *sgh, + MpmCtx *mpm_ctx, const DetectBufferMpmRegistry *mpm_reg, int list_id) +{ + PrefilterMpmListId *pectx = SCCalloc(1, sizeof(*pectx)); + if (pectx == NULL) + return -1; + pectx->list_id = list_id; + pectx->mpm_ctx = mpm_ctx; + pectx->transforms = &mpm_reg->transforms; + + return PrefilterAppendTxEngine(de_ctx, sgh, PrefilterTxHttp1Header, mpm_reg->app_v2.alproto, + mpm_reg->app_v2.tx_min_progress, pectx, PrefilterMpmHttpHeaderFree, mpm_reg->name); +} + +static uint8_t DetectEngineInspectHttp1Header(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) +{ + uint32_t local_id = 0; + + const DetectEngineTransforms *transforms = NULL; + if (!engine->mpm) { + transforms = engine->v2.transforms; + } + + while (1) { + struct MpmListIdDataArgs cbdata = { + local_id, + txv, + }; + InspectionBuffer *buffer = + GetHttp1HeaderData(det_ctx, flags, transforms, f, &cbdata, engine->sm_list); + + if (buffer == NULL || buffer->inspect == NULL) + break; + + det_ctx->buffer_offset = 0; + det_ctx->discontinue_matching = 0; + det_ctx->inspection_recursion_counter = 0; + + const int match = DetectEngineContentInspection(de_ctx, det_ctx, s, engine->smd, NULL, f, + (uint8_t *)buffer->inspect, buffer->inspect_len, buffer->inspect_offset, + DETECT_CI_FLAGS_SINGLE, DETECT_ENGINE_CONTENT_INSPECTION_MODE_STATE); + if (match == 1) { + return DETECT_ENGINE_INSPECT_SIG_MATCH; + } + local_id++; + } + + return DETECT_ENGINE_INSPECT_SIG_NO_MATCH; +} + +static int DetectHTTPRequestHeaderSetup(DetectEngineCtx *de_ctx, Signature *s, const char *arg) +{ + if (DetectBufferSetActiveList(de_ctx, s, g_http_request_header_buffer_id) < 0) + return -1; + + if (DetectSignatureSetAppProto(s, ALPROTO_HTTP) != 0) + return -1; + + return 0; +} + +void DetectHttpRequestHeaderRegister(void) +{ + sigmatch_table[DETECT_HTTP_REQUEST_HEADER].name = "http.request_header"; + sigmatch_table[DETECT_HTTP_REQUEST_HEADER].desc = + "sticky buffer to match on only one HTTP header name and value"; + sigmatch_table[DETECT_HTTP_REQUEST_HEADER].url = "/rules/http-keywords.html#request_header"; + sigmatch_table[DETECT_HTTP_REQUEST_HEADER].Setup = DetectHTTPRequestHeaderSetup; + sigmatch_table[DETECT_HTTP_REQUEST_HEADER].flags |= + SIGMATCH_NOOPT | SIGMATCH_INFO_STICKY_BUFFER; + + DetectAppLayerMpmRegister2("http_request_header", SIG_FLAG_TOSERVER, 2, + PrefilterMpmHttp2HeaderRegister, NULL, ALPROTO_HTTP2, HTTP2StateOpen); + DetectAppLayerInspectEngineRegister2("http_request_header", ALPROTO_HTTP2, SIG_FLAG_TOSERVER, + HTTP2StateOpen, DetectEngineInspectHttp2Header, NULL); + DetectAppLayerMpmRegister2("http_request_header", SIG_FLAG_TOSERVER, 2, + PrefilterMpmHttp1HeaderRegister, NULL, ALPROTO_HTTP1, 0); + DetectAppLayerInspectEngineRegister2("http_request_header", ALPROTO_HTTP1, SIG_FLAG_TOSERVER, + HTP_REQUEST_HEADERS, DetectEngineInspectHttp1Header, NULL); + + DetectBufferTypeSetDescriptionByName("http_request_header", "HTTP header name and value"); + g_http_request_header_buffer_id = DetectBufferTypeGetByName("http_request_header"); +} + +static int DetectHTTPResponseHeaderSetup(DetectEngineCtx *de_ctx, Signature *s, const char *arg) +{ + if (DetectBufferSetActiveList(de_ctx, s, g_http_response_header_buffer_id) < 0) + return -1; + + if (DetectSignatureSetAppProto(s, ALPROTO_HTTP) != 0) + return -1; + + return 0; +} + +void DetectHttpResponseHeaderRegister(void) +{ + sigmatch_table[DETECT_HTTP_RESPONSE_HEADER].name = "http.response_header"; + sigmatch_table[DETECT_HTTP_RESPONSE_HEADER].desc = + "sticky buffer to match on only one HTTP header name and value"; + sigmatch_table[DETECT_HTTP_RESPONSE_HEADER].url = "/rules/http2-keywords.html#response_header"; + sigmatch_table[DETECT_HTTP_RESPONSE_HEADER].Setup = DetectHTTPResponseHeaderSetup; + sigmatch_table[DETECT_HTTP_RESPONSE_HEADER].flags |= + SIGMATCH_NOOPT | SIGMATCH_INFO_STICKY_BUFFER; + + DetectAppLayerMpmRegister2("http_response_header", SIG_FLAG_TOCLIENT, 2, + PrefilterMpmHttp2HeaderRegister, NULL, ALPROTO_HTTP2, HTTP2StateOpen); + DetectAppLayerInspectEngineRegister2("http_response_header", ALPROTO_HTTP2, SIG_FLAG_TOCLIENT, + HTTP2StateOpen, DetectEngineInspectHttp2Header, NULL); + DetectAppLayerMpmRegister2("http_response_header", SIG_FLAG_TOCLIENT, 2, + PrefilterMpmHttp1HeaderRegister, NULL, ALPROTO_HTTP1, 0); + DetectAppLayerInspectEngineRegister2("http_response_header", ALPROTO_HTTP1, SIG_FLAG_TOCLIENT, + HTP_RESPONSE_HEADERS, DetectEngineInspectHttp1Header, NULL); + + DetectBufferTypeSetDescriptionByName("http_response_header", "HTTP header name and value"); + g_http_response_header_buffer_id = DetectBufferTypeGetByName("http_response_header"); +} + /************************************Unittests*********************************/ #ifdef UNITTESTS diff --git a/src/detect-http-header.h b/src/detect-http-header.h index 5327b5b815..369386f400 100644 --- a/src/detect-http-header.h +++ b/src/detect-http-header.h @@ -26,5 +26,7 @@ void DetectHttpHeaderRegister(void); void DetectHttpRawHeaderRegister(void); +void DetectHttpRequestHeaderRegister(void); +void DetectHttpResponseHeaderRegister(void); #endif /* __DETECT_HTTP_HEADER_H__ */ diff --git a/src/detect-http2.c b/src/detect-http2.c index 380d655715..40cbe3e3a7 100644 --- a/src/detect-http2.c +++ b/src/detect-http2.c @@ -92,22 +92,12 @@ static uint8_t DetectEngineInspectHttp2HeaderName(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); -static int DetectHTTPRequestHeaderSetup(DetectEngineCtx *de_ctx, Signature *s, const char *arg); -static int DetectHTTPResponseHeaderSetup(DetectEngineCtx *de_ctx, Signature *s, const char *arg); -static int PrefilterMpmHttp2HeaderRegister(DetectEngineCtx *de_ctx, SigGroupHead *sgh, - MpmCtx *mpm_ctx, const DetectBufferMpmRegistry *mpm_reg, int list_id); -static uint8_t DetectEngineInspectHttp2Header(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); - #ifdef UNITTESTS void DetectHTTP2RegisterTests (void); #endif static int g_http2_match_buffer_id = 0; static int g_http2_header_name_buffer_id = 0; -static int g_http_request_header_buffer_id = 0; -static int g_http_response_header_buffer_id = 0; /** * \brief Registration function for HTTP2 keywords @@ -204,36 +194,6 @@ void DetectHttp2Register(void) "HTTP2 header name"); g_http2_header_name_buffer_id = DetectBufferTypeGetByName("http2_header_name"); - sigmatch_table[DETECT_HTTP_REQUEST_HEADER].name = "http.request_header"; - sigmatch_table[DETECT_HTTP_REQUEST_HEADER].desc = - "sticky buffer to match on only one HTTP header name and value"; - sigmatch_table[DETECT_HTTP_REQUEST_HEADER].url = "/rules/http2-keywords.html#request_header"; - sigmatch_table[DETECT_HTTP_REQUEST_HEADER].Setup = DetectHTTPRequestHeaderSetup; - sigmatch_table[DETECT_HTTP_REQUEST_HEADER].flags |= - SIGMATCH_NOOPT | SIGMATCH_INFO_STICKY_BUFFER; - - DetectAppLayerMpmRegister2("http_request_header", SIG_FLAG_TOSERVER, 2, - PrefilterMpmHttp2HeaderRegister, NULL, ALPROTO_HTTP2, HTTP2StateOpen); - DetectAppLayerInspectEngineRegister2("http_request_header", ALPROTO_HTTP2, SIG_FLAG_TOSERVER, - HTTP2StateOpen, DetectEngineInspectHttp2Header, NULL); - DetectBufferTypeSetDescriptionByName("http_request_header", "HTTP header name and value"); - g_http_request_header_buffer_id = DetectBufferTypeGetByName("http_request_header"); - - sigmatch_table[DETECT_HTTP_RESPONSE_HEADER].name = "http.response_header"; - sigmatch_table[DETECT_HTTP_RESPONSE_HEADER].desc = - "sticky buffer to match on only one HTTP header name and value"; - sigmatch_table[DETECT_HTTP_RESPONSE_HEADER].url = "/rules/http2-keywords.html#response_header"; - sigmatch_table[DETECT_HTTP_RESPONSE_HEADER].Setup = DetectHTTPResponseHeaderSetup; - sigmatch_table[DETECT_HTTP_RESPONSE_HEADER].flags |= - SIGMATCH_NOOPT | SIGMATCH_INFO_STICKY_BUFFER; - - DetectAppLayerMpmRegister2("http_response_header", SIG_FLAG_TOCLIENT, 2, - PrefilterMpmHttp2HeaderRegister, NULL, ALPROTO_HTTP2, HTTP2StateOpen); - DetectAppLayerInspectEngineRegister2("http_response_header", ALPROTO_HTTP2, SIG_FLAG_TOCLIENT, - HTTP2StateOpen, DetectEngineInspectHttp2Header, NULL); - DetectBufferTypeSetDescriptionByName("http_response_header", "HTTP header name and value"); - g_http_response_header_buffer_id = DetectBufferTypeGetByName("http_response_header"); - DetectAppLayerInspectEngineRegister2( "http2", ALPROTO_HTTP2, SIG_FLAG_TOSERVER, 0, DetectEngineInspectGenericList, NULL); DetectAppLayerInspectEngineRegister2( @@ -792,147 +752,6 @@ static uint8_t DetectEngineInspectHttp2HeaderName(DetectEngineCtx *de_ctx, return DETECT_ENGINE_INSPECT_SIG_NO_MATCH; } -static int DetectHTTPRequestHeaderSetup(DetectEngineCtx *de_ctx, Signature *s, const char *arg) -{ - if (DetectBufferSetActiveList(de_ctx, s, g_http_request_header_buffer_id) < 0) - return -1; - - if (DetectSignatureSetAppProto(s, ALPROTO_HTTP2) != 0) - return -1; - - return 0; -} - -static int DetectHTTPResponseHeaderSetup(DetectEngineCtx *de_ctx, Signature *s, const char *arg) -{ - if (DetectBufferSetActiveList(de_ctx, s, g_http_response_header_buffer_id) < 0) - return -1; - - if (DetectSignatureSetAppProto(s, ALPROTO_HTTP2) != 0) - return -1; - - return 0; -} - -static void PrefilterMpmHttp2HeaderFree(void *ptr) -{ - SCFree(ptr); -} - -static InspectionBuffer *GetHttp2HeaderData(DetectEngineThreadCtx *det_ctx, const uint8_t flags, - const DetectEngineTransforms *transforms, Flow *_f, const struct MpmListIdDataArgs *cbdata, - int list_id) -{ - SCEnter(); - - InspectionBuffer *buffer = - InspectionBufferMultipleForListGet(det_ctx, list_id, cbdata->local_id); - if (buffer == NULL) - return NULL; - if (buffer->initialized) - return buffer; - - uint32_t b_len = 0; - const uint8_t *b = NULL; - - if (rs_http2_tx_get_header(cbdata->txv, flags, cbdata->local_id, &b, &b_len) != 1) { - InspectionBufferSetupMultiEmpty(buffer); - return NULL; - } - if (b == NULL || b_len == 0) { - InspectionBufferSetupMultiEmpty(buffer); - return NULL; - } - - InspectionBufferSetupMulti(buffer, transforms, b, b_len); - - SCReturnPtr(buffer, "InspectionBuffer"); -} - -static void PrefilterTxHttp2Header(DetectEngineThreadCtx *det_ctx, const void *pectx, Packet *p, - Flow *f, void *txv, const uint64_t idx, const AppLayerTxData *_txd, const uint8_t flags) -{ - SCEnter(); - - const PrefilterMpmListId *ctx = (const PrefilterMpmListId *)pectx; - const MpmCtx *mpm_ctx = ctx->mpm_ctx; - const int list_id = ctx->list_id; - - uint32_t local_id = 0; - - while(1) { - // loop until we get a NULL - - struct MpmListIdDataArgs cbdata = { local_id, txv }; - InspectionBuffer *buffer = - GetHttp2HeaderData(det_ctx, flags, ctx->transforms, f, &cbdata, list_id); - if (buffer == NULL) - break; - - if (buffer->inspect_len >= mpm_ctx->minlen) { - (void)mpm_table[mpm_ctx->mpm_type].Search(mpm_ctx, - &det_ctx->mtcu, &det_ctx->pmq, - buffer->inspect, buffer->inspect_len); - PREFILTER_PROFILING_ADD_BYTES(det_ctx, buffer->inspect_len); - } - - local_id++; - } -} - -static int PrefilterMpmHttp2HeaderRegister(DetectEngineCtx *de_ctx, SigGroupHead *sgh, - MpmCtx *mpm_ctx, const DetectBufferMpmRegistry *mpm_reg, int list_id) -{ - PrefilterMpmListId *pectx = SCCalloc(1, sizeof(*pectx)); - if (pectx == NULL) - return -1; - pectx->list_id = list_id; - pectx->mpm_ctx = mpm_ctx; - pectx->transforms = &mpm_reg->transforms; - - return PrefilterAppendTxEngine(de_ctx, sgh, PrefilterTxHttp2Header, - mpm_reg->app_v2.alproto, mpm_reg->app_v2.tx_min_progress, - pectx, PrefilterMpmHttp2HeaderFree, mpm_reg->name); -} - -static uint8_t DetectEngineInspectHttp2Header(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) -{ - uint32_t local_id = 0; - - const DetectEngineTransforms *transforms = NULL; - if (!engine->mpm) { - transforms = engine->v2.transforms; - } - - while (1) { - struct MpmListIdDataArgs cbdata = { local_id, txv, }; - InspectionBuffer *buffer = - GetHttp2HeaderData(det_ctx, flags, transforms, f, &cbdata, engine->sm_list); - - if (buffer == NULL || buffer->inspect == NULL) - break; - - det_ctx->buffer_offset = 0; - det_ctx->discontinue_matching = 0; - det_ctx->inspection_recursion_counter = 0; - - const int match = DetectEngineContentInspection(de_ctx, det_ctx, s, engine->smd, - NULL, f, - (uint8_t *)buffer->inspect, - buffer->inspect_len, - buffer->inspect_offset, DETECT_CI_FLAGS_SINGLE, - DETECT_ENGINE_CONTENT_INSPECTION_MODE_STATE); - if (match == 1) { - return DETECT_ENGINE_INSPECT_SIG_MATCH; - } - local_id++; - } - - return DETECT_ENGINE_INSPECT_SIG_NO_MATCH; -} - #ifdef UNITTESTS #include "tests/detect-http2.c" #endif