diff --git a/src/detect-http-header-names.c b/src/detect-http-header-names.c index 0f947b2dbb..5d065e1bac 100644 --- a/src/detect-http-header-names.c +++ b/src/detect-http-header-names.c @@ -65,7 +65,8 @@ #include "util-print.h" -#define KEYWORD_NAME "http_header_names" +#define KEYWORD_NAME "http.header_names" +#define KEYWORD_NAME_LEGACY "http_header_names" #define KEYWORD_DOC "http-keywords.html#http-header-names" #define BUFFER_NAME "http_header_names" #define BUFFER_DESC "http header names" @@ -77,9 +78,8 @@ static int g_keyword_thread_id = 0; 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, - Flow *f, HtpState *htp_state, uint8_t flags, - uint32_t *buffer_len) + DetectEngineThreadCtx *det_ctx, + Flow *f, uint8_t flags, uint32_t *buffer_len) { *buffer_len = 0; @@ -150,6 +150,12 @@ static uint8_t *GetBufferForTX(htp_tx_t *tx, uint64_t tx_id, return buf->buffer; } +typedef struct PrefilterMpmHttpHeaderCtx { + int list_id; + const MpmCtx *mpm_ctx; + const DetectEngineTransforms *transforms; +} PrefilterMpmHttpHeaderCtx; + /** \brief HTTP Headers Mpm prefilter callback * * \param det_ctx detection engine thread ctx @@ -165,71 +171,67 @@ static void PrefilterTxHttpRequestHeaderNames(DetectEngineThreadCtx *det_ctx, { SCEnter(); - const MpmCtx *mpm_ctx = (MpmCtx *)pectx; htp_tx_t *tx = (htp_tx_t *)txv; - if (tx->request_headers == NULL) return; - HtpState *htp_state = f->alstate; - uint32_t buffer_len = 0; - const uint8_t *buffer = GetBufferForTX(tx, idx, - NULL, det_ctx, f, htp_state, - flags, &buffer_len); - - 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); + const PrefilterMpmHttpHeaderCtx *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 = InspectionBufferGet(det_ctx, list_id); + if (buffer->inspect == NULL) { + uint32_t rawdata_len = 0; + uint8_t *rawdata = GetBufferForTX(txv, idx, det_ctx, + f, flags, &rawdata_len); + if (rawdata_len == 0) + return; + + /* setup buffer and apply transforms */ + InspectionBufferSetup(buffer, rawdata, rawdata_len); + InspectionBufferApplyTransforms(buffer, ctx->transforms); } -} -#if 0 -static void PrefilterTxHttpRequestTrailers(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; - if (tx->request_headers == NULL) - return; - 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 && !htud->request_has_trailers) - return; + const uint32_t data_len = buffer->inspect_len; + const uint8_t *data = buffer->inspect; - HtpState *htp_state = f->alstate; - uint32_t buffer_len = 0; - const uint8_t *buffer = DetectEngineHHDGetBufferForTX(tx, idx, - NULL, det_ctx, - f, htp_state, - flags, - &buffer_len); + SCLogDebug("mpm'ing buffer:"); + //PrintRawDataFp(stdout, data, data_len); - if (buffer_len >= mpm_ctx->minlen) { + if (data != NULL && data_len >= mpm_ctx->minlen) { (void)mpm_table[mpm_ctx->mpm_type].Search(mpm_ctx, - &det_ctx->mtcu, &det_ctx->pmq, buffer, buffer_len); + &det_ctx->mtcu, &det_ctx->pmq, data, data_len); } } -#endif + +static void PrefilterMpmHttpHeaderFree(void *ptr) +{ + SCFree(ptr); +} + static int PrefilterTxHttpRequestHeaderNamesRegister(DetectEngineCtx *de_ctx, - SigGroupHead *sgh, MpmCtx *mpm_ctx) + SigGroupHead *sgh, MpmCtx *mpm_ctx, + const DetectMpmAppLayerRegistery *mpm_reg, int list_id) { SCEnter(); + PrefilterMpmHttpHeaderCtx *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, PrefilterTxHttpRequestHeaderNames, - ALPROTO_HTTP, HTP_REQUEST_HEADERS, - mpm_ctx, NULL, KEYWORD_NAME " (request)"); - return r; -#if 0 - if (r != 0) + mpm_reg->v2.alproto, HTP_REQUEST_HEADERS, + pectx, PrefilterMpmHttpHeaderFree, mpm_reg->pname); + if (r != 0) { + SCFree(pectx); return r; - return PrefilterAppendTxEngine(sgh, PrefilterTxHttpRequestTrailers, - ALPROTO_HTTP, HTP_REQUEST_TRAILER, - mpm_ctx, NULL, "http_header (request)"); -#endif + } + + return r; } /** \brief HTTP Headers Mpm prefilter callback @@ -247,109 +249,120 @@ static void PrefilterTxHttpResponseHeaderNames(DetectEngineThreadCtx *det_ctx, { SCEnter(); - const MpmCtx *mpm_ctx = (MpmCtx *)pectx; htp_tx_t *tx = (htp_tx_t *)txv; - if (tx->response_headers == NULL) return; - HtpState *htp_state = f->alstate; - uint32_t buffer_len = 0; - const uint8_t *buffer = GetBufferForTX(tx, idx, NULL, det_ctx, - f, htp_state, flags, &buffer_len); - - 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); + const PrefilterMpmHttpHeaderCtx *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 = InspectionBufferGet(det_ctx, list_id); + if (buffer->inspect == NULL) { + uint32_t rawdata_len = 0; + uint8_t *rawdata = GetBufferForTX(txv, idx, det_ctx, + f, flags, &rawdata_len); + if (rawdata_len == 0) + return; + + /* setup buffer and apply transforms */ + InspectionBufferSetup(buffer, rawdata, rawdata_len); + InspectionBufferApplyTransforms(buffer, ctx->transforms); } -} -#if 0 -static void PrefilterTxHttpResponseTrailers(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; - if (tx->response_headers == NULL) - return; - 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 && !htud->response_has_trailers) - return; + const uint32_t data_len = buffer->inspect_len; + const uint8_t *data = buffer->inspect; - HtpState *htp_state = f->alstate; - uint32_t buffer_len = 0; - const uint8_t *buffer = DetectEngineHHDGetBufferForTX(tx, idx, - NULL, det_ctx, - f, htp_state, - flags, - &buffer_len); + SCLogDebug("mpm'ing buffer:"); + //PrintRawDataFp(stdout, data, data_len); - if (buffer_len >= mpm_ctx->minlen) { + if (data != NULL && data_len >= mpm_ctx->minlen) { (void)mpm_table[mpm_ctx->mpm_type].Search(mpm_ctx, - &det_ctx->mtcu, &det_ctx->pmq, buffer, buffer_len); + &det_ctx->mtcu, &det_ctx->pmq, data, data_len); } } -#endif + static int PrefilterTxHttpResponseHeaderNamesRegister(DetectEngineCtx *de_ctx, - SigGroupHead *sgh, MpmCtx *mpm_ctx) + SigGroupHead *sgh, MpmCtx *mpm_ctx, + const DetectMpmAppLayerRegistery *mpm_reg, int list_id) { SCEnter(); + PrefilterMpmHttpHeaderCtx *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, PrefilterTxHttpResponseHeaderNames, - ALPROTO_HTTP, HTP_RESPONSE_HEADERS, - mpm_ctx, NULL, KEYWORD_NAME " (response)"); - return r; -#if 0 - if (r != 0) + mpm_reg->v2.alproto, HTP_RESPONSE_HEADERS, + pectx, PrefilterMpmHttpHeaderFree, mpm_reg->pname); + if (r != 0) { + SCFree(pectx); return r; - return PrefilterAppendTxEngine(sgh, PrefilterTxHttpResponseTrailers, - ALPROTO_HTTP, HTP_RESPONSE_TRAILER, - mpm_ctx, NULL, "http_header (response)"); -#endif + } + + return r; } -static int InspectEngineHttpHeaderNames(ThreadVars *tv, +static int InspectEngineHttpHeaderNames( 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) + const DetectEngineAppInspectionEngine *engine, + const Signature *s, + Flow *f, uint8_t flags, void *alstate, void *txv, uint64_t tx_id) { - HtpState *htp_state = (HtpState *)alstate; - uint32_t buffer_len = 0; - uint8_t *buffer = GetBufferForTX(tx, tx_id, - de_ctx, det_ctx, f, htp_state, - flags, &buffer_len); - if (buffer_len == 0) - goto end; + const int list_id = engine->sm_list; + InspectionBuffer *buffer = InspectionBufferGet(det_ctx, list_id); + if (buffer->inspect == NULL) { + SCLogDebug("setting up inspect buffer %d", list_id); + + /* if prefilter didn't already run, we need to consider transformations */ + const DetectEngineTransforms *transforms = NULL; + if (!engine->mpm) { + transforms = engine->v2.transforms; + } + + uint32_t rawdata_len = 0; + uint8_t *rawdata = GetBufferForTX(txv, tx_id, det_ctx, + f, flags, &rawdata_len); + if (rawdata_len == 0) { + SCLogDebug("no data"); + goto end; + } + /* setup buffer and apply transforms */ + InspectionBufferSetup(buffer, rawdata, rawdata_len); + InspectionBufferApplyTransforms(buffer, transforms); + } + + const uint32_t data_len = buffer->inspect_len; + const uint8_t *data = buffer->inspect; + const uint64_t offset = buffer->inspect_offset; 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, - buffer, buffer_len, - 0, DETECT_CI_FLAGS_SINGLE, - DETECT_ENGINE_CONTENT_INSPECTION_MODE_STATE, NULL); + int r = DetectEngineContentInspection(de_ctx, det_ctx, s, engine->smd, + f, (uint8_t *)data, data_len, offset, + 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, tx, flags) > HTP_REQUEST_HEADERS) + 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, tx, flags) > HTP_RESPONSE_HEADERS) + 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; } /** - * \brief The setup function for the http_header keyword for a signature. + * \brief The setup function for the http.header_names keyword for a signature. * * \param de_ctx Pointer to the detection engine context. * \param s Pointer to signature for the current Signature being parsed @@ -363,33 +376,41 @@ static int InspectEngineHttpHeaderNames(ThreadVars *tv, */ static int DetectHttpHeaderNamesSetup(DetectEngineCtx *de_ctx, Signature *s, const char *arg) { - s->init_data->list = g_buffer_id; + if (DetectBufferSetActiveList(s, g_buffer_id) < 0) + return -1; + + if (DetectSignatureSetAppProto(s, ALPROTO_HTTP) < 0) + return -1; + return 0; } /** - * \brief Registers the keyword handlers for the "http_header" keyword. + * \brief Registers the keyword handlers for the "http.header_names" keyword. */ void DetectHttpHeaderNamesRegister(void) { sigmatch_table[DETECT_AL_HTTP_HEADER_NAMES].name = KEYWORD_NAME; + sigmatch_table[DETECT_AL_HTTP_HEADER_NAMES].alias = KEYWORD_NAME_LEGACY; sigmatch_table[DETECT_AL_HTTP_HEADER_NAMES].desc = BUFFER_NAME " sticky buffer"; sigmatch_table[DETECT_AL_HTTP_HEADER_NAMES].url = DOC_URL DOC_VERSION "/rules/" KEYWORD_DOC; sigmatch_table[DETECT_AL_HTTP_HEADER_NAMES].Setup = DetectHttpHeaderNamesSetup; - sigmatch_table[DETECT_AL_HTTP_HEADER_NAMES].flags |= SIGMATCH_NOOPT ; + sigmatch_table[DETECT_AL_HTTP_HEADER_NAMES].flags |= SIGMATCH_NOOPT | SIGMATCH_INFO_STICKY_BUFFER; - DetectAppLayerMpmRegister(BUFFER_NAME, SIG_FLAG_TOSERVER, 2, - PrefilterTxHttpRequestHeaderNamesRegister); - DetectAppLayerMpmRegister(BUFFER_NAME, SIG_FLAG_TOCLIENT, 2, - PrefilterTxHttpResponseHeaderNamesRegister); + DetectAppLayerMpmRegister2(BUFFER_NAME, SIG_FLAG_TOSERVER, 2, + PrefilterTxHttpRequestHeaderNamesRegister, NULL, ALPROTO_HTTP, + HTP_REQUEST_HEADERS); + DetectAppLayerMpmRegister2(BUFFER_NAME, SIG_FLAG_TOCLIENT, 2, + PrefilterTxHttpResponseHeaderNamesRegister, NULL, ALPROTO_HTTP, + HTP_RESPONSE_HEADERS); - DetectAppLayerInspectEngineRegister(BUFFER_NAME, + DetectAppLayerInspectEngineRegister2(BUFFER_NAME, ALPROTO_HTTP, SIG_FLAG_TOSERVER, HTP_REQUEST_HEADERS, - InspectEngineHttpHeaderNames); - DetectAppLayerInspectEngineRegister(BUFFER_NAME, + InspectEngineHttpHeaderNames, NULL); + DetectAppLayerInspectEngineRegister2(BUFFER_NAME, ALPROTO_HTTP, SIG_FLAG_TOCLIENT, HTP_RESPONSE_HEADERS, - InspectEngineHttpHeaderNames); + InspectEngineHttpHeaderNames, NULL); DetectBufferTypeSetDescriptionByName(BUFFER_NAME, BUFFER_DESC);