summaryrefslogtreecommitdiffstats
path: root/src/detect-http2.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/detect-http2.c757
1 files changed, 757 insertions, 0 deletions
diff --git a/src/detect-http2.c b/src/detect-http2.c
new file mode 100644
index 0000000..40cbe3e
--- /dev/null
+++ b/src/detect-http2.c
@@ -0,0 +1,757 @@
+/* Copyright (C) 2020-2022 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 Philippe Antoine <p.antoine@catenacyber.fr>
+ *
+ */
+
+#include "suricata-common.h"
+
+#include "detect.h"
+#include "detect-parse.h"
+#include "detect-content.h"
+
+#include "detect-engine.h"
+#include "detect-engine-uint.h"
+#include "detect-engine-mpm.h"
+#include "detect-engine-prefilter.h"
+#include "detect-engine-content-inspection.h"
+
+#include "detect-http2.h"
+#include "util-byte.h"
+#include "rust.h"
+#include "util-profiling.h"
+
+#ifdef UNITTESTS
+void DetectHTTP2frameTypeRegisterTests (void);
+void DetectHTTP2errorCodeRegisterTests (void);
+void DetectHTTP2priorityRegisterTests (void);
+void DetectHTTP2windowRegisterTests (void);
+void DetectHTTP2settingsRegisterTests (void);
+void DetectHTTP2sizeUpdateRegisterTests (void);
+#endif
+
+/* prototypes */
+static int DetectHTTP2frametypeMatch(DetectEngineThreadCtx *det_ctx,
+ Flow *f, uint8_t flags, void *state, void *txv, const Signature *s,
+ const SigMatchCtx *ctx);
+static int DetectHTTP2frametypeSetup (DetectEngineCtx *, Signature *, const char *);
+void DetectHTTP2frametypeFree (DetectEngineCtx *, void *);
+
+static int DetectHTTP2errorcodeMatch(DetectEngineThreadCtx *det_ctx,
+ Flow *f, uint8_t flags, void *state, void *txv, const Signature *s,
+ const SigMatchCtx *ctx);
+static int DetectHTTP2errorcodeSetup (DetectEngineCtx *, Signature *, const char *);
+void DetectHTTP2errorcodeFree (DetectEngineCtx *, void *);
+
+static int DetectHTTP2priorityMatch(DetectEngineThreadCtx *det_ctx,
+ Flow *f, uint8_t flags, void *state, void *txv, const Signature *s,
+ const SigMatchCtx *ctx);
+static int DetectHTTP2prioritySetup (DetectEngineCtx *, Signature *, const char *);
+void DetectHTTP2priorityFree (DetectEngineCtx *, void *);
+
+static int DetectHTTP2windowMatch(DetectEngineThreadCtx *det_ctx,
+ Flow *f, uint8_t flags, void *state, void *txv, const Signature *s,
+ const SigMatchCtx *ctx);
+static int DetectHTTP2windowSetup (DetectEngineCtx *, Signature *, const char *);
+void DetectHTTP2windowFree (DetectEngineCtx *, void *);
+
+static int DetectHTTP2sizeUpdateMatch(DetectEngineThreadCtx *det_ctx,
+ Flow *f, uint8_t flags, void *state, void *txv, const Signature *s,
+ const SigMatchCtx *ctx);
+static int DetectHTTP2sizeUpdateSetup (DetectEngineCtx *, Signature *, const char *);
+void DetectHTTP2sizeUpdateFree (DetectEngineCtx *, void *);
+
+static int DetectHTTP2settingsMatch(DetectEngineThreadCtx *det_ctx,
+ Flow *f, uint8_t flags, void *state, void *txv, const Signature *s,
+ const SigMatchCtx *ctx);
+static int DetectHTTP2settingsSetup (DetectEngineCtx *, Signature *, const char *);
+void DetectHTTP2settingsFree (DetectEngineCtx *, void *);
+
+static int DetectHTTP2headerNameSetup(DetectEngineCtx *de_ctx, Signature *s, const char *arg);
+static int PrefilterMpmHttp2HeaderNameRegister(DetectEngineCtx *de_ctx, SigGroupHead *sgh,
+ MpmCtx *mpm_ctx, const DetectBufferMpmRegistry *mpm_reg, int list_id);
+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);
+
+#ifdef UNITTESTS
+void DetectHTTP2RegisterTests (void);
+#endif
+
+static int g_http2_match_buffer_id = 0;
+static int g_http2_header_name_buffer_id = 0;
+
+/**
+ * \brief Registration function for HTTP2 keywords
+ */
+
+void DetectHttp2Register(void)
+{
+ sigmatch_table[DETECT_HTTP2_FRAMETYPE].name = "http2.frametype";
+ sigmatch_table[DETECT_HTTP2_FRAMETYPE].desc = "match on HTTP2 frame type field";
+ sigmatch_table[DETECT_HTTP2_FRAMETYPE].url = "/rules/http2-keywords.html#frametype";
+ sigmatch_table[DETECT_HTTP2_FRAMETYPE].Match = NULL;
+ sigmatch_table[DETECT_HTTP2_FRAMETYPE].AppLayerTxMatch = DetectHTTP2frametypeMatch;
+ sigmatch_table[DETECT_HTTP2_FRAMETYPE].Setup = DetectHTTP2frametypeSetup;
+ sigmatch_table[DETECT_HTTP2_FRAMETYPE].Free = DetectHTTP2frametypeFree;
+#ifdef UNITTESTS
+ sigmatch_table[DETECT_HTTP2_FRAMETYPE].RegisterTests = DetectHTTP2frameTypeRegisterTests;
+#endif
+
+ sigmatch_table[DETECT_HTTP2_ERRORCODE].name = "http2.errorcode";
+ sigmatch_table[DETECT_HTTP2_ERRORCODE].desc = "match on HTTP2 error code field";
+ sigmatch_table[DETECT_HTTP2_ERRORCODE].url = "/rules/http2-keywords.html#errorcode";
+ sigmatch_table[DETECT_HTTP2_ERRORCODE].Match = NULL;
+ sigmatch_table[DETECT_HTTP2_ERRORCODE].AppLayerTxMatch = DetectHTTP2errorcodeMatch;
+ sigmatch_table[DETECT_HTTP2_ERRORCODE].Setup = DetectHTTP2errorcodeSetup;
+ sigmatch_table[DETECT_HTTP2_ERRORCODE].Free = DetectHTTP2errorcodeFree;
+#ifdef UNITTESTS
+ sigmatch_table[DETECT_HTTP2_ERRORCODE].RegisterTests = DetectHTTP2errorCodeRegisterTests;
+#endif
+
+ sigmatch_table[DETECT_HTTP2_PRIORITY].name = "http2.priority";
+ sigmatch_table[DETECT_HTTP2_PRIORITY].desc = "match on HTTP2 priority weight field";
+ sigmatch_table[DETECT_HTTP2_PRIORITY].url = "/rules/http2-keywords.html#priority";
+ sigmatch_table[DETECT_HTTP2_PRIORITY].Match = NULL;
+ sigmatch_table[DETECT_HTTP2_PRIORITY].AppLayerTxMatch = DetectHTTP2priorityMatch;
+ sigmatch_table[DETECT_HTTP2_PRIORITY].Setup = DetectHTTP2prioritySetup;
+ sigmatch_table[DETECT_HTTP2_PRIORITY].Free = DetectHTTP2priorityFree;
+#ifdef UNITTESTS
+ sigmatch_table[DETECT_HTTP2_PRIORITY].RegisterTests = DetectHTTP2priorityRegisterTests;
+#endif
+
+ sigmatch_table[DETECT_HTTP2_WINDOW].name = "http2.window";
+ sigmatch_table[DETECT_HTTP2_WINDOW].desc = "match on HTTP2 window update size increment field";
+ sigmatch_table[DETECT_HTTP2_WINDOW].url = "/rules/http2-keywords.html#window";
+ sigmatch_table[DETECT_HTTP2_WINDOW].Match = NULL;
+ sigmatch_table[DETECT_HTTP2_WINDOW].AppLayerTxMatch = DetectHTTP2windowMatch;
+ sigmatch_table[DETECT_HTTP2_WINDOW].Setup = DetectHTTP2windowSetup;
+ sigmatch_table[DETECT_HTTP2_WINDOW].Free = DetectHTTP2windowFree;
+#ifdef UNITTESTS
+ sigmatch_table[DETECT_HTTP2_WINDOW].RegisterTests = DetectHTTP2windowRegisterTests;
+#endif
+
+ sigmatch_table[DETECT_HTTP2_SIZEUPDATE].name = "http2.size_update";
+ sigmatch_table[DETECT_HTTP2_SIZEUPDATE].desc = "match on HTTP2 dynamic headers table size update";
+ sigmatch_table[DETECT_HTTP2_SIZEUPDATE].url = "/rules/http2-keywords.html#sizeupdate";
+ sigmatch_table[DETECT_HTTP2_SIZEUPDATE].Match = NULL;
+ sigmatch_table[DETECT_HTTP2_SIZEUPDATE].AppLayerTxMatch = DetectHTTP2sizeUpdateMatch;
+ sigmatch_table[DETECT_HTTP2_SIZEUPDATE].Setup = DetectHTTP2sizeUpdateSetup;
+ sigmatch_table[DETECT_HTTP2_SIZEUPDATE].Free = DetectHTTP2sizeUpdateFree;
+#ifdef UNITTESTS
+ sigmatch_table[DETECT_HTTP2_SIZEUPDATE].RegisterTests = DetectHTTP2sizeUpdateRegisterTests;
+#endif
+
+ sigmatch_table[DETECT_HTTP2_SETTINGS].name = "http2.settings";
+ sigmatch_table[DETECT_HTTP2_SETTINGS].desc = "match on HTTP2 settings identifier and value fields";
+ sigmatch_table[DETECT_HTTP2_SETTINGS].url = "/rules/http2-keywords.html#settings";
+ sigmatch_table[DETECT_HTTP2_SETTINGS].Match = NULL;
+ sigmatch_table[DETECT_HTTP2_SETTINGS].AppLayerTxMatch = DetectHTTP2settingsMatch;
+ sigmatch_table[DETECT_HTTP2_SETTINGS].Setup = DetectHTTP2settingsSetup;
+ sigmatch_table[DETECT_HTTP2_SETTINGS].Free = DetectHTTP2settingsFree;
+#ifdef UNITTESTS
+ sigmatch_table[DETECT_HTTP2_SETTINGS].RegisterTests = DetectHTTP2settingsRegisterTests;
+#endif
+
+ sigmatch_table[DETECT_HTTP2_HEADERNAME].name = "http2.header_name";
+ sigmatch_table[DETECT_HTTP2_HEADERNAME].desc = "sticky buffer to match on one HTTP2 header name";
+ sigmatch_table[DETECT_HTTP2_HEADERNAME].url = "/rules/http2-keywords.html#header_name";
+ sigmatch_table[DETECT_HTTP2_HEADERNAME].Setup = DetectHTTP2headerNameSetup;
+ sigmatch_table[DETECT_HTTP2_HEADERNAME].flags |= SIGMATCH_NOOPT | SIGMATCH_INFO_STICKY_BUFFER;
+
+ DetectAppLayerMpmRegister2("http2_header_name", SIG_FLAG_TOCLIENT, 2,
+ PrefilterMpmHttp2HeaderNameRegister, NULL,
+ ALPROTO_HTTP2, HTTP2StateOpen);
+ DetectAppLayerInspectEngineRegister2("http2_header_name",
+ ALPROTO_HTTP2, SIG_FLAG_TOCLIENT, HTTP2StateOpen,
+ DetectEngineInspectHttp2HeaderName, NULL);
+ DetectAppLayerMpmRegister2("http2_header_name", SIG_FLAG_TOSERVER, 2,
+ PrefilterMpmHttp2HeaderNameRegister, NULL,
+ ALPROTO_HTTP2, HTTP2StateOpen);
+ DetectAppLayerInspectEngineRegister2("http2_header_name",
+ ALPROTO_HTTP2, SIG_FLAG_TOSERVER, HTTP2StateOpen,
+ DetectEngineInspectHttp2HeaderName, NULL);
+ DetectBufferTypeSupportsMultiInstance("http2_header_name");
+ DetectBufferTypeSetDescriptionByName("http2_header_name",
+ "HTTP2 header name");
+ g_http2_header_name_buffer_id = DetectBufferTypeGetByName("http2_header_name");
+
+ DetectAppLayerInspectEngineRegister2(
+ "http2", ALPROTO_HTTP2, SIG_FLAG_TOSERVER, 0, DetectEngineInspectGenericList, NULL);
+ DetectAppLayerInspectEngineRegister2(
+ "http2", ALPROTO_HTTP2, SIG_FLAG_TOCLIENT, 0, DetectEngineInspectGenericList, NULL);
+
+ g_http2_match_buffer_id = DetectBufferTypeRegister("http2");
+ return;
+}
+
+/**
+ * \brief This function is used to match HTTP2 frame type rule option on a transaction with those passed via http2.frametype:
+ *
+ * \retval 0 no match
+ * \retval 1 match
+ */
+static int DetectHTTP2frametypeMatch(DetectEngineThreadCtx *det_ctx,
+ Flow *f, uint8_t flags, void *state, void *txv, const Signature *s,
+ const SigMatchCtx *ctx)
+
+{
+ uint8_t *detect = (uint8_t *)ctx;
+
+ return rs_http2_tx_has_frametype(txv, flags, *detect);
+}
+
+static int DetectHTTP2FuncParseFrameType(const char *str, uint8_t *ft)
+{
+ // first parse numeric value
+ if (ByteExtractStringUint8(ft, 10, (uint16_t)strlen(str), str) >= 0) {
+ return 1;
+ }
+
+ // it it failed so far, parse string value from enumeration
+ int r = rs_http2_parse_frametype(str);
+ if (r >= 0 && r <= UINT8_MAX) {
+ *ft = (uint8_t)r;
+ return 1;
+ }
+
+ return 0;
+}
+
+/**
+ * \brief this function is used to attach the parsed http2.frametype data into the current signature
+ *
+ * \param de_ctx pointer to the Detection Engine Context
+ * \param s pointer to the Current Signature
+ * \param str pointer to the user provided http2.frametype options
+ *
+ * \retval 0 on Success
+ * \retval -1 on Failure
+ */
+static int DetectHTTP2frametypeSetup (DetectEngineCtx *de_ctx, Signature *s, const char *str)
+{
+ uint8_t frame_type;
+
+ if (DetectSignatureSetAppProto(s, ALPROTO_HTTP2) != 0)
+ return -1;
+
+ if (!DetectHTTP2FuncParseFrameType(str, &frame_type)) {
+ SCLogError("Invalid argument \"%s\" supplied to http2.frametype keyword.", str);
+ return -1;
+ }
+
+ uint8_t *http2ft = SCCalloc(1, sizeof(uint8_t));
+ if (http2ft == NULL)
+ return -1;
+ *http2ft = frame_type;
+
+ SigMatch *sm = SigMatchAlloc();
+ if (sm == NULL) {
+ DetectHTTP2frametypeFree(NULL, http2ft);
+ return -1;
+ }
+
+ sm->type = DETECT_HTTP2_FRAMETYPE;
+ sm->ctx = (SigMatchCtx *)http2ft;
+
+ SigMatchAppendSMToList(s, sm, g_http2_match_buffer_id);
+
+ return 0;
+}
+
+/**
+ * \brief this function will free memory associated with uint8_t
+ *
+ * \param ptr pointer to uint8_t
+ */
+void DetectHTTP2frametypeFree(DetectEngineCtx *de_ctx, void *ptr)
+{
+ SCFree(ptr);
+}
+
+/**
+ * \brief This function is used to match HTTP2 error code rule option on a transaction with those passed via http2.errorcode:
+ *
+ * \retval 0 no match
+ * \retval 1 match
+ */
+static int DetectHTTP2errorcodeMatch(DetectEngineThreadCtx *det_ctx,
+ Flow *f, uint8_t flags, void *state, void *txv, const Signature *s,
+ const SigMatchCtx *ctx)
+
+{
+ uint32_t *detect = (uint32_t *)ctx;
+
+ return rs_http2_tx_has_errorcode(txv, flags, *detect);
+ //TODOask handle negation rules
+}
+
+static int DetectHTTP2FuncParseErrorCode(const char *str, uint32_t *ec)
+{
+ // first parse numeric value
+ if (ByteExtractStringUint32(ec, 10, (uint16_t)strlen(str), str) >= 0) {
+ return 1;
+ }
+
+ // it it failed so far, parse string value from enumeration
+ int r = rs_http2_parse_errorcode(str);
+ if (r >= 0) {
+ *ec = r;
+ return 1;
+ }
+
+ return 0;
+}
+
+/**
+ * \brief this function is used to attach the parsed http2.errorcode data into the current signature
+ *
+ * \param de_ctx pointer to the Detection Engine Context
+ * \param s pointer to the Current Signature
+ * \param str pointer to the user provided http2.errorcode options
+ *
+ * \retval 0 on Success
+ * \retval -1 on Failure
+ */
+static int DetectHTTP2errorcodeSetup (DetectEngineCtx *de_ctx, Signature *s, const char *str)
+{
+ uint32_t error_code;
+
+ if (DetectSignatureSetAppProto(s, ALPROTO_HTTP2) != 0)
+ return -1;
+
+ if (!DetectHTTP2FuncParseErrorCode(str, &error_code)) {
+ SCLogError("Invalid argument \"%s\" supplied to http2.errorcode keyword.", str);
+ return -1;
+ }
+
+ uint32_t *http2ec = SCCalloc(1, sizeof(uint32_t));
+ if (http2ec == NULL)
+ return -1;
+ *http2ec = error_code;
+
+ SigMatch *sm = SigMatchAlloc();
+ if (sm == NULL) {
+ DetectHTTP2errorcodeFree(NULL, http2ec);
+ return -1;
+ }
+
+ sm->type = DETECT_HTTP2_ERRORCODE;
+ sm->ctx = (SigMatchCtx *)http2ec;
+
+ SigMatchAppendSMToList(s, sm, g_http2_match_buffer_id);
+
+ return 0;
+}
+
+/**
+ * \brief this function will free memory associated with uint32_t
+ *
+ * \param ptr pointer to uint32_t
+ */
+void DetectHTTP2errorcodeFree(DetectEngineCtx *de_ctx, void *ptr)
+{
+ SCFree(ptr);
+}
+
+/**
+ * \brief This function is used to match HTTP2 error code rule option on a transaction with those passed via http2.priority:
+ *
+ * \retval 0 no match
+ * \retval 1 match
+ */
+static int DetectHTTP2priorityMatch(DetectEngineThreadCtx *det_ctx,
+ Flow *f, uint8_t flags, void *state, void *txv, const Signature *s,
+ const SigMatchCtx *ctx)
+
+{
+ uint32_t nb = 0;
+ int value = rs_http2_tx_get_next_priority(txv, flags, nb);
+ const DetectU8Data *du8 = (const DetectU8Data *)ctx;
+ while (value >= 0) {
+ if (DetectU8Match((uint8_t)value, du8)) {
+ return 1;
+ }
+ nb++;
+ value = rs_http2_tx_get_next_priority(txv, flags, nb);
+ }
+ return 0;
+}
+
+/**
+ * \brief this function is used to attach the parsed http2.priority data into the current signature
+ *
+ * \param de_ctx pointer to the Detection Engine Context
+ * \param s pointer to the Current Signature
+ * \param str pointer to the user provided http2.priority options
+ *
+ * \retval 0 on Success
+ * \retval -1 on Failure
+ */
+static int DetectHTTP2prioritySetup (DetectEngineCtx *de_ctx, Signature *s, const char *str)
+{
+ if (DetectSignatureSetAppProto(s, ALPROTO_HTTP2) != 0)
+ return -1;
+
+ DetectU8Data *prio = DetectU8Parse(str);
+ if (prio == NULL)
+ return -1;
+
+ SigMatch *sm = SigMatchAlloc();
+ if (sm == NULL) {
+ rs_detect_u8_free(prio);
+ return -1;
+ }
+
+ sm->type = DETECT_HTTP2_PRIORITY;
+ sm->ctx = (SigMatchCtx *)prio;
+
+ SigMatchAppendSMToList(s, sm, g_http2_match_buffer_id);
+
+ return 0;
+}
+
+/**
+ * \brief this function will free memory associated with uint32_t
+ *
+ * \param ptr pointer to DetectU8Data
+ */
+void DetectHTTP2priorityFree(DetectEngineCtx *de_ctx, void *ptr)
+{
+ rs_detect_u8_free(ptr);
+}
+
+/**
+ * \brief This function is used to match HTTP2 window rule option on a transaction with those passed via http2.window:
+ *
+ * \retval 0 no match
+ * \retval 1 match
+ */
+static int DetectHTTP2windowMatch(DetectEngineThreadCtx *det_ctx,
+ Flow *f, uint8_t flags, void *state, void *txv, const Signature *s,
+ const SigMatchCtx *ctx)
+
+{
+ uint32_t nb = 0;
+ int value = rs_http2_tx_get_next_window(txv, flags, nb);
+ const DetectU32Data *du32 = (const DetectU32Data *)ctx;
+ while (value >= 0) {
+ if (DetectU32Match(value, du32)) {
+ return 1;
+ }
+ nb++;
+ value = rs_http2_tx_get_next_window(txv, flags, nb);
+ }
+ return 0;
+}
+
+/**
+ * \brief this function is used to attach the parsed http2.window data into the current signature
+ *
+ * \param de_ctx pointer to the Detection Engine Context
+ * \param s pointer to the Current Signature
+ * \param str pointer to the user provided http2.window options
+ *
+ * \retval 0 on Success
+ * \retval -1 on Failure
+ */
+static int DetectHTTP2windowSetup (DetectEngineCtx *de_ctx, Signature *s, const char *str)
+{
+ if (DetectSignatureSetAppProto(s, ALPROTO_HTTP2) != 0)
+ return -1;
+
+ DetectU32Data *wu = DetectU32Parse(str);
+ if (wu == NULL)
+ return -1;
+
+ SigMatch *sm = SigMatchAlloc();
+ if (sm == NULL) {
+ rs_detect_u32_free(wu);
+ return -1;
+ }
+
+ sm->type = DETECT_HTTP2_WINDOW;
+ sm->ctx = (SigMatchCtx *)wu;
+
+ SigMatchAppendSMToList(s, sm, g_http2_match_buffer_id);
+
+ return 0;
+}
+
+/**
+ * \brief this function will free memory associated with uint32_t
+ *
+ * \param ptr pointer to DetectU8Data
+ */
+void DetectHTTP2windowFree(DetectEngineCtx *de_ctx, void *ptr)
+{
+ rs_detect_u32_free(ptr);
+}
+
+/**
+ * \brief This function is used to match HTTP2 size update rule option on a transaction with those passed via http2.size_update:
+ *
+ * \retval 0 no match
+ * \retval 1 match
+ */
+static int DetectHTTP2sizeUpdateMatch(DetectEngineThreadCtx *det_ctx,
+ Flow *f, uint8_t flags, void *state, void *txv, const Signature *s,
+ const SigMatchCtx *ctx)
+
+{
+ return rs_http2_detect_sizeupdatectx_match(ctx, txv, flags);
+}
+
+/**
+ * \brief this function is used to attach the parsed http2.size_update data into the current signature
+ *
+ * \param de_ctx pointer to the Detection Engine Context
+ * \param s pointer to the Current Signature
+ * \param str pointer to the user provided http2.size_update options
+ *
+ * \retval 0 on Success
+ * \retval -1 on Failure
+ */
+static int DetectHTTP2sizeUpdateSetup (DetectEngineCtx *de_ctx, Signature *s, const char *str)
+{
+ if (DetectSignatureSetAppProto(s, ALPROTO_HTTP2) != 0)
+ return -1;
+
+ void *su = rs_detect_u64_parse(str);
+ if (su == NULL)
+ return -1;
+
+ SigMatch *sm = SigMatchAlloc();
+ if (sm == NULL) {
+ DetectHTTP2settingsFree(NULL, su);
+ return -1;
+ }
+
+ sm->type = DETECT_HTTP2_SIZEUPDATE;
+ sm->ctx = (SigMatchCtx *)su;
+
+ SigMatchAppendSMToList(s, sm, g_http2_match_buffer_id);
+
+ return 0;
+}
+
+/**
+ * \brief this function will free memory associated with uint32_t
+ *
+ * \param ptr pointer to DetectU8Data
+ */
+void DetectHTTP2sizeUpdateFree(DetectEngineCtx *de_ctx, void *ptr)
+{
+ rs_detect_u64_free(ptr);
+}
+
+/**
+ * \brief This function is used to match HTTP2 error code rule option on a transaction with those passed via http2.settings:
+ *
+ * \retval 0 no match
+ * \retval 1 match
+ */
+static int DetectHTTP2settingsMatch(DetectEngineThreadCtx *det_ctx,
+ Flow *f, uint8_t flags, void *state, void *txv, const Signature *s,
+ const SigMatchCtx *ctx)
+
+{
+ return rs_http2_detect_settingsctx_match(ctx, txv, flags);
+}
+
+/**
+ * \brief this function is used to attach the parsed http2.settings data into the current signature
+ *
+ * \param de_ctx pointer to the Detection Engine Context
+ * \param s pointer to the Current Signature
+ * \param str pointer to the user provided http2.settings options
+ *
+ * \retval 0 on Success
+ * \retval -1 on Failure
+ */
+static int DetectHTTP2settingsSetup (DetectEngineCtx *de_ctx, Signature *s, const char *str)
+{
+ if (DetectSignatureSetAppProto(s, ALPROTO_HTTP2) != 0)
+ return -1;
+
+ void *http2set = rs_http2_detect_settingsctx_parse(str);
+ if (http2set == NULL)
+ return -1;
+
+ SigMatch *sm = SigMatchAlloc();
+ if (sm == NULL) {
+ DetectHTTP2settingsFree(NULL, http2set);
+ return -1;
+ }
+
+ sm->type = DETECT_HTTP2_SETTINGS;
+ sm->ctx = (SigMatchCtx *)http2set;
+
+ SigMatchAppendSMToList(s, sm, g_http2_match_buffer_id);
+
+ return 0;
+}
+
+/**
+ * \brief this function will free memory associated with rust signature context
+ *
+ * \param ptr pointer to rust signature context
+ */
+void DetectHTTP2settingsFree(DetectEngineCtx *de_ctx, void *ptr)
+{
+ rs_http2_detect_settingsctx_free(ptr);
+}
+
+static int DetectHTTP2headerNameSetup(DetectEngineCtx *de_ctx, Signature *s, const char *arg)
+{
+ if (DetectBufferSetActiveList(de_ctx, s, g_http2_header_name_buffer_id) < 0)
+ return -1;
+
+ if (DetectSignatureSetAppProto(s, ALPROTO_HTTP2) != 0)
+ return -1;
+
+ return 0;
+}
+
+static void PrefilterMpmHttp2HNameFree(void *ptr)
+{
+ SCFree(ptr);
+}
+
+static InspectionBuffer *GetHttp2HNameData(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_name(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 PrefilterTxHttp2HName(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 =
+ GetHttp2HNameData(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 PrefilterMpmHttp2HeaderNameRegister(DetectEngineCtx *de_ctx, SigGroupHead *sgh,
+ MpmCtx *mpm_ctx, const DetectBufferMpmRegistry *mpm_reg, int list_id)
+{
+ //TODOask use PrefilterMpmListId elsewhere
+ 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, PrefilterTxHttp2HName,
+ mpm_reg->app_v2.alproto, mpm_reg->app_v2.tx_min_progress,
+ pectx, PrefilterMpmHttp2HNameFree, mpm_reg->name);
+}
+
+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)
+{
+ uint32_t local_id = 0;
+
+ const DetectEngineTransforms *transforms = NULL;
+ if (!engine->mpm) {
+ transforms = engine->v2.transforms;
+ }
+
+ while (1) {
+ //TODOask use MpmListIdDataArgs elsewhere
+ struct MpmListIdDataArgs cbdata = { local_id, txv, };
+ InspectionBuffer *buffer =
+ GetHttp2HNameData(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