From: Victor Julien Date: Thu, 29 Nov 2018 07:31:06 +0000 (+0100) Subject: detect/http_raw_header: use inspect v2 api X-Git-Tag: suricata-5.0.0-beta1~252 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=25f974eb29859be8f5734b969ba43cdbd2cf530b;p=thirdparty%2Fsuricata.git detect/http_raw_header: use inspect v2 api --- diff --git a/src/detect-engine-hrhd.c b/src/detect-engine-hrhd.c index 4836ec7a20..67919fca2c 100644 --- a/src/detect-engine-hrhd.c +++ b/src/detect-engine-hrhd.c @@ -61,162 +61,6 @@ #include "util-validate.h" -/** \brief HTTP Raw Header Mpm prefilter callback - * - * \param det_ctx detection engine thread ctx - * \param p packet to inspect - * \param f flow to inspect - * \param txv tx to inspect - * \param pectx inspection context - */ -static void PrefilterTxRequestHeadersRaw(DetectEngineThreadCtx *det_ctx, - const void *pectx, - Packet *p, Flow *f, void *txv, - const uint64_t idx, const uint8_t flags) -{ - SCEnter(); - - const MpmCtx *mpm_ctx = (MpmCtx *)pectx; - htp_tx_t *tx = (htp_tx_t *)txv; - HtpTxUserData *tx_ud = htp_tx_get_user_data(tx); - if (tx_ud == NULL || tx_ud->request_headers_raw == NULL) - return; - - const uint32_t buffer_len = tx_ud->request_headers_raw_len; - const uint8_t *buffer = tx_ud->request_headers_raw; - - if (buffer_len >= mpm_ctx->minlen) { - (void)mpm_table[mpm_ctx->mpm_type].Search(mpm_ctx, - &det_ctx->mtcu, &det_ctx->pmq, buffer, buffer_len); - } -} - -int PrefilterTxRequestHeadersRawRegister(DetectEngineCtx *de_ctx, - SigGroupHead *sgh, MpmCtx *mpm_ctx) -{ - SCEnter(); - - int r = PrefilterAppendTxEngine(de_ctx, sgh, PrefilterTxRequestHeadersRaw, - ALPROTO_HTTP, HTP_REQUEST_HEADERS+1, /* inspect when headers complete */ - mpm_ctx, NULL, "http_raw_header (request)"); - if (r != 0) - return r; - return PrefilterAppendTxEngine(de_ctx, sgh, PrefilterTxRequestHeadersRaw, - ALPROTO_HTTP, HTP_REQUEST_TRAILER+1, /* inspect when trailer complete */ - mpm_ctx, NULL, "http_raw_header (request)"); -} - -/** \brief HTTP Raw Header Mpm prefilter callback - * - * \param det_ctx detection engine thread ctx - * \param p packet to inspect - * \param f flow to inspect - * \param txv tx to inspect - * \param pectx inspection context - */ -static void PrefilterTxResponseHeadersRaw(DetectEngineThreadCtx *det_ctx, - const void *pectx, - Packet *p, Flow *f, void *txv, - const uint64_t idx, const uint8_t flags) -{ - SCEnter(); - - const MpmCtx *mpm_ctx = (MpmCtx *)pectx; - htp_tx_t *tx = (htp_tx_t *)txv; - HtpTxUserData *tx_ud = htp_tx_get_user_data(tx); - if (tx_ud == NULL || tx_ud->response_headers_raw == NULL) - return; - - const uint32_t buffer_len = tx_ud->response_headers_raw_len; - const uint8_t *buffer = tx_ud->response_headers_raw; - - if (buffer_len >= mpm_ctx->minlen) { - (void)mpm_table[mpm_ctx->mpm_type].Search(mpm_ctx, - &det_ctx->mtcu, &det_ctx->pmq, buffer, buffer_len); - } -} - -int PrefilterTxResponseHeadersRawRegister(DetectEngineCtx *de_ctx, - SigGroupHead *sgh, MpmCtx *mpm_ctx) -{ - SCEnter(); - - int r = PrefilterAppendTxEngine(de_ctx, sgh, PrefilterTxResponseHeadersRaw, - ALPROTO_HTTP, HTP_RESPONSE_HEADERS+1, /* inspect when headers complete */ - mpm_ctx, NULL, "http_raw_header (response)"); - if (r != 0) - return r; - return PrefilterAppendTxEngine(de_ctx, sgh, PrefilterTxResponseHeadersRaw, - ALPROTO_HTTP, HTP_RESPONSE_TRAILER+1, /* inspect when trailer complete */ - mpm_ctx, NULL, "http_raw_header (response)"); -} - -/** - * \brief Do the http_raw_header content inspection for a signature. - * - * \param de_ctx Detection engine context. - * \param det_ctx Detection engine thread context. - * \param s Signature to inspect. - * \param f Flow. - * \param flags App layer flags. - * \param state App layer state. - * - * \retval 0 No match. - * \retval 1 Match. - */ -int DetectEngineInspectHttpRawHeader(ThreadVars *tv, - DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, - const Signature *s, const SigMatchData *smd, - Flow *f, uint8_t flags, void *alstate, void *txv, uint64_t tx_id) -{ - HtpTxUserData *tx_ud = NULL; - uint8_t *headers_raw = NULL; - uint32_t headers_raw_len = 0; - - if (flags & STREAM_TOSERVER) { - if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, txv, flags) <= HTP_REQUEST_HEADERS) - return DETECT_ENGINE_INSPECT_SIG_NO_MATCH; - } else { - if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, txv, flags) <= HTP_RESPONSE_HEADERS) - return DETECT_ENGINE_INSPECT_SIG_NO_MATCH; - } - - tx_ud = htp_tx_get_user_data(txv); - if (tx_ud == NULL) - goto end; - if (flags & STREAM_TOSERVER) { - headers_raw = tx_ud->request_headers_raw; - headers_raw_len = tx_ud->request_headers_raw_len; - } else { - headers_raw = tx_ud->response_headers_raw; - headers_raw_len = tx_ud->response_headers_raw_len; - } - if (headers_raw == NULL) - goto end; - - det_ctx->buffer_offset = 0; - det_ctx->discontinue_matching = 0; - det_ctx->inspection_recursion_counter = 0; - int r = DetectEngineContentInspection(de_ctx, det_ctx, s, smd, - f, - headers_raw, - headers_raw_len, - 0, DETECT_CI_FLAGS_SINGLE, - DETECT_ENGINE_CONTENT_INSPECTION_MODE_STATE, NULL); - if (r == 1) - return DETECT_ENGINE_INSPECT_SIG_MATCH; - - end: - if (flags & STREAM_TOSERVER) { - if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, txv, flags) > HTP_REQUEST_HEADERS) - return DETECT_ENGINE_INSPECT_SIG_CANT_MATCH; - } else { - if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, txv, flags) > HTP_RESPONSE_HEADERS) - return DETECT_ENGINE_INSPECT_SIG_CANT_MATCH; - } - return DETECT_ENGINE_INSPECT_SIG_NO_MATCH; -} - /***********************************Unittests**********************************/ #ifdef UNITTESTS @@ -1805,12 +1649,8 @@ end: static int DetectEngineHttpRawHeaderTest20(void) { TcpSession ssn; - Packet *p1 = NULL; - Packet *p2 = NULL; ThreadVars th_v; - DetectEngineCtx *de_ctx = NULL; DetectEngineThreadCtx *det_ctx = NULL; - HtpState *http_state = NULL; Flow f; uint8_t http1_buf[] = "GET /index.html HTTP/1.0\r\n" @@ -1820,15 +1660,17 @@ static int DetectEngineHttpRawHeaderTest20(void) "\r\n"; uint32_t http1_len = sizeof(http1_buf) - 1; uint32_t http2_len = sizeof(http2_buf) - 1; - int result = 0; AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc(); + FAIL_IF_NULL(alp_tctx); memset(&th_v, 0, sizeof(th_v)); memset(&f, 0, sizeof(f)); memset(&ssn, 0, sizeof(ssn)); - p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP); - p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP); + Packet *p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP); + FAIL_IF_NULL(p1); + Packet *p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP); + FAIL_IF_NULL(p2); FLOW_INITIALIZE(&f); f.protoctx = (void *)&ssn; @@ -1847,81 +1689,49 @@ static int DetectEngineHttpRawHeaderTest20(void) StreamTcpInitConfig(TRUE); - de_ctx = DetectEngineCtxInit(); - if (de_ctx == NULL) - goto end; - + DetectEngineCtx *de_ctx = DetectEngineCtxInit(); + FAIL_IF_NULL(de_ctx); de_ctx->flags |= DE_QUIET; - de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any " - "(msg:\"http client body test\"; flow:to_server; " - "pcre:/body1/D; " - "content:!\"dummy\"; http_raw_header; within:7; " - "sid:1;)"); - if (de_ctx->sig_list == NULL) - goto end; + Signature *s = DetectEngineAppendSig(de_ctx, "alert http any any -> any any " + "(flow:to_server; pcre:/body1/D; " + "content:!\"dummy\"; http_raw_header; within:7; " + "sid:1;)"); + FAIL_IF_NULL(s); SigGroupBuild(de_ctx); DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx); + FAIL_IF_NULL(det_ctx); - FLOWLOCK_WRLOCK(&f); int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP, STREAM_TOSERVER, http1_buf, http1_len); - if (r != 0) { - printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); - result = 0; - FLOWLOCK_UNLOCK(&f); - goto end; - } - FLOWLOCK_UNLOCK(&f); + FAIL_IF_NOT(r == 0); - http_state = f.alstate; - if (http_state == NULL) { - printf("no http state: \n"); - result = 0; - goto end; - } + HtpState *http_state = f.alstate; + FAIL_IF_NULL(http_state); /* do detect */ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1); + FAIL_IF(PacketAlertCheck(p1, 1)); - if (PacketAlertCheck(p1, 1)) { - printf("sid 1 matched but shouldn't have\n"); - goto end; - } - - FLOWLOCK_WRLOCK(&f); r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP, STREAM_TOSERVER, http2_buf, http2_len); - if (r != 0) { - printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r); - result = 0; - FLOWLOCK_UNLOCK(&f); - goto end; - } - FLOWLOCK_UNLOCK(&f); + FAIL_IF_NOT(r == 0); /* do detect */ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2); - if (!PacketAlertCheck(p2, 1)) { - printf("sid 1 didn't match but shouldn't have"); - goto end; - } - - result = 1; + FAIL_IF(!PacketAlertCheck(p2, 1)); -end: - if (alp_tctx != NULL) - AppLayerParserThreadCtxFree(alp_tctx); - if (de_ctx != NULL) - DetectEngineCtxFree(de_ctx); + AppLayerParserThreadCtxFree(alp_tctx); + DetectEngineCtxFree(de_ctx); StreamTcpFreeConfig(TRUE); FLOW_DESTROY(&f); UTHFreePackets(&p1, 1); UTHFreePackets(&p2, 1); - return result; + + PASS; } static int DetectEngineHttpRawHeaderTest21(void) diff --git a/src/detect-engine-hrhd.h b/src/detect-engine-hrhd.h index 177aad829a..1c4436fed9 100644 --- a/src/detect-engine-hrhd.h +++ b/src/detect-engine-hrhd.h @@ -23,18 +23,6 @@ #ifndef __DETECT_ENGINE_HRHD_H__ #define __DETECT_ENGINE_HRHD_H__ -#include "app-layer-htp.h" - -int PrefilterTxRequestHeadersRawRegister(DetectEngineCtx *de_ctx, - SigGroupHead *sgh, MpmCtx *mpm_ctx); -int PrefilterTxResponseHeadersRawRegister(DetectEngineCtx *de_ctx, - SigGroupHead *sgh, MpmCtx *mpm_ctx); - -int DetectEngineInspectHttpRawHeader(ThreadVars *tv, - DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, - const Signature *s, const SigMatchData *smd, - Flow *f, uint8_t flags, void *alstate, void *tx, uint64_t tx_id); - void DetectEngineHttpRawHeaderRegisterTests(void); #endif /* __DETECT_ENGINE_HHD_H__ */ diff --git a/src/detect-http-raw-header.c b/src/detect-http-raw-header.c index 8269cb28a6..bddab2406d 100644 --- a/src/detect-http-raw-header.c +++ b/src/detect-http-raw-header.c @@ -38,7 +38,7 @@ #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-content.h" #include "detect-pcre.h" @@ -64,6 +64,16 @@ static int DetectHttpRawHeaderSetup(DetectEngineCtx *, Signature *, const char * static void DetectHttpRawHeaderRegisterTests(void); static _Bool DetectHttpRawHeaderValidateCallback(const Signature *s, const char **sigerror); static int g_http_raw_header_buffer_id = 0; +static InspectionBuffer *GetData(DetectEngineThreadCtx *det_ctx, + const DetectEngineTransforms *transforms, Flow *_f, + const uint8_t flow_flags, void *txv, const int list_id); + +static int PrefilterMpmHttpHeaderRawRequestRegister(DetectEngineCtx *de_ctx, + SigGroupHead *sgh, MpmCtx *mpm_ctx, + const DetectMpmAppLayerRegistery *mpm_reg, int list_id); +static int PrefilterMpmHttpHeaderRawResponseRegister(DetectEngineCtx *de_ctx, + SigGroupHead *sgh, MpmCtx *mpm_ctx, + const DetectMpmAppLayerRegistery *mpm_reg, int list_id); /** * \brief Registers the keyword handlers for the "http_raw_header" keyword. @@ -73,20 +83,21 @@ void DetectHttpRawHeaderRegister(void) sigmatch_table[DETECT_AL_HTTP_RAW_HEADER].name = "http_raw_header"; sigmatch_table[DETECT_AL_HTTP_RAW_HEADER].Setup = DetectHttpRawHeaderSetup; sigmatch_table[DETECT_AL_HTTP_RAW_HEADER].RegisterTests = DetectHttpRawHeaderRegisterTests; - sigmatch_table[DETECT_AL_HTTP_RAW_HEADER].flags |= SIGMATCH_NOOPT; - DetectAppLayerMpmRegister("http_raw_header", SIG_FLAG_TOSERVER, 2, - PrefilterTxRequestHeadersRawRegister); - DetectAppLayerMpmRegister("http_raw_header", SIG_FLAG_TOCLIENT, 2, - PrefilterTxResponseHeadersRawRegister); + DetectAppLayerInspectEngineRegister2("http_raw_header", ALPROTO_HTTP, + SIG_FLAG_TOSERVER, HTP_REQUEST_HEADERS+1, + DetectEngineInspectBufferGeneric, GetData); + DetectAppLayerInspectEngineRegister2("http_raw_header", ALPROTO_HTTP, + SIG_FLAG_TOCLIENT, HTP_RESPONSE_HEADERS+1, + DetectEngineInspectBufferGeneric, GetData); - DetectAppLayerInspectEngineRegister("http_raw_header", - ALPROTO_HTTP, SIG_FLAG_TOSERVER, HTP_REQUEST_HEADERS, - DetectEngineInspectHttpRawHeader); - DetectAppLayerInspectEngineRegister("http_raw_header", - ALPROTO_HTTP, SIG_FLAG_TOCLIENT, HTP_RESPONSE_HEADERS, - DetectEngineInspectHttpRawHeader); + DetectAppLayerMpmRegister2("http_raw_header", SIG_FLAG_TOSERVER, 2, + PrefilterMpmHttpHeaderRawRequestRegister, NULL, ALPROTO_HTTP, + 0); /* progress handled in register */ + DetectAppLayerMpmRegister2("http_raw_header", SIG_FLAG_TOCLIENT, 2, + PrefilterMpmHttpHeaderRawResponseRegister, NULL, ALPROTO_HTTP, + 0); /* progress handled in register */ DetectBufferTypeSetDescriptionByName("http_raw_header", "raw http headers"); @@ -132,6 +143,179 @@ static _Bool DetectHttpRawHeaderValidateCallback(const Signature *s, const char return TRUE; } +static InspectionBuffer *GetData(DetectEngineThreadCtx *det_ctx, + const DetectEngineTransforms *transforms, Flow *_f, + const uint8_t flow_flags, void *txv, const int list_id) +{ + InspectionBuffer *buffer = InspectionBufferGet(det_ctx, list_id); + if (buffer->inspect == NULL) { + htp_tx_t *tx = (htp_tx_t *)txv; + + HtpTxUserData *tx_ud = htp_tx_get_user_data(tx); + if (tx_ud == NULL) + return NULL; + + const bool ts = ((flow_flags & STREAM_TOSERVER) != 0); + const uint8_t *data = ts ? + tx_ud->request_headers_raw : tx_ud->response_headers_raw; + if (data == NULL) + return NULL; + const uint8_t data_len = ts ? + tx_ud->request_headers_raw_len : tx_ud->response_headers_raw_len; + + InspectionBufferSetup(buffer, data, data_len); + InspectionBufferApplyTransforms(buffer, transforms); + } + + return buffer; +} + +typedef struct PrefilterMpmHttpHeaderRawCtx { + int list_id; + const MpmCtx *mpm_ctx; + const DetectEngineTransforms *transforms; +} PrefilterMpmHttpHeaderRawCtx; + +/** \brief Generic Mpm prefilter callback + * + * \param det_ctx detection engine thread ctx + * \param p packet to inspect + * \param f flow to inspect + * \param txv tx to inspect + * \param pectx inspection context + */ +static void PrefilterMpmHttpHeaderRaw(DetectEngineThreadCtx *det_ctx, + const void *pectx, + Packet *p, Flow *f, void *txv, + const uint64_t idx, const uint8_t flags) +{ + SCEnter(); + + const PrefilterMpmHttpHeaderRawCtx *ctx = pectx; + const MpmCtx *mpm_ctx = ctx->mpm_ctx; + SCLogDebug("running on list %d", ctx->list_id); + + const int list_id = ctx->list_id; + + InspectionBuffer *buffer = GetData(det_ctx, ctx->transforms, f, + flags, txv, list_id); + if (buffer == NULL) + return; + + const uint32_t data_len = buffer->inspect_len; + const uint8_t *data = buffer->inspect; + + SCLogDebug("mpm'ing buffer:"); + //PrintRawDataFp(stdout, data, data_len); + + if (data != NULL && data_len >= mpm_ctx->minlen) { + (void)mpm_table[mpm_ctx->mpm_type].Search(mpm_ctx, + &det_ctx->mtcu, &det_ctx->pmq, data, data_len); + } +} + +static void PrefilterMpmHttpTrailerRaw(DetectEngineThreadCtx *det_ctx, + const void *pectx, + Packet *p, Flow *f, void *txv, + const uint64_t idx, const uint8_t flags) +{ + SCEnter(); + + htp_tx_t *tx = txv; + const HtpTxUserData *htud = (const HtpTxUserData *)htp_tx_get_user_data(tx); + /* if the request wasn't flagged as having a trailer, we skip */ + if (htud && ( + ((flags & STREAM_TOSERVER) && !htud->request_has_trailers) || + ((flags & STREAM_TOCLIENT) && !htud->response_has_trailers))) { + SCReturn; + } + PrefilterMpmHttpHeaderRaw(det_ctx, pectx, p, f, txv, idx, flags); + SCReturn; +} + +static void PrefilterMpmHttpHeaderRawFree(void *ptr) +{ + SCFree(ptr); +} + +static int PrefilterMpmHttpHeaderRawRequestRegister(DetectEngineCtx *de_ctx, + SigGroupHead *sgh, MpmCtx *mpm_ctx, + const DetectMpmAppLayerRegistery *mpm_reg, int list_id) +{ + SCEnter(); + + /* header */ + PrefilterMpmHttpHeaderRawCtx *pectx = SCCalloc(1, sizeof(*pectx)); + if (pectx == NULL) + return -1; + pectx->list_id = list_id; + pectx->mpm_ctx = mpm_ctx; + pectx->transforms = &mpm_reg->v2.transforms; + + int r = PrefilterAppendTxEngine(de_ctx, sgh, PrefilterMpmHttpHeaderRaw, + mpm_reg->v2.alproto, HTP_REQUEST_HEADERS+1, + pectx, PrefilterMpmHttpHeaderRawFree, mpm_reg->pname); + if (r != 0) { + SCFree(pectx); + return r; + } + + /* trailer */ + pectx = SCCalloc(1, sizeof(*pectx)); + if (pectx == NULL) + return -1; + pectx->list_id = list_id; + pectx->mpm_ctx = mpm_ctx; + pectx->transforms = &mpm_reg->v2.transforms; + + r = PrefilterAppendTxEngine(de_ctx, sgh, PrefilterMpmHttpTrailerRaw, + mpm_reg->v2.alproto, HTP_REQUEST_TRAILER+1, + pectx, PrefilterMpmHttpHeaderRawFree, mpm_reg->pname); + if (r != 0) { + SCFree(pectx); + } + return r; +} + +static int PrefilterMpmHttpHeaderRawResponseRegister(DetectEngineCtx *de_ctx, + SigGroupHead *sgh, MpmCtx *mpm_ctx, + const DetectMpmAppLayerRegistery *mpm_reg, int list_id) +{ + SCEnter(); + + /* header */ + PrefilterMpmHttpHeaderRawCtx *pectx = SCCalloc(1, sizeof(*pectx)); + if (pectx == NULL) + return -1; + pectx->list_id = list_id; + pectx->mpm_ctx = mpm_ctx; + pectx->transforms = &mpm_reg->v2.transforms; + + int r = PrefilterAppendTxEngine(de_ctx, sgh, PrefilterMpmHttpHeaderRaw, + mpm_reg->v2.alproto, HTP_RESPONSE_HEADERS, + pectx, PrefilterMpmHttpHeaderRawFree, mpm_reg->pname); + if (r != 0) { + SCFree(pectx); + return r; + } + + /* trailer */ + pectx = SCCalloc(1, sizeof(*pectx)); + if (pectx == NULL) + return -1; + pectx->list_id = list_id; + pectx->mpm_ctx = mpm_ctx; + pectx->transforms = &mpm_reg->v2.transforms; + + r = PrefilterAppendTxEngine(de_ctx, sgh, PrefilterMpmHttpTrailerRaw, + mpm_reg->v2.alproto, HTP_RESPONSE_TRAILER, + pectx, PrefilterMpmHttpHeaderRawFree, mpm_reg->pname); + if (r != 0) { + SCFree(pectx); + } + return r; +} + /************************************Unittests*********************************/ #ifdef UNITTESTS