diff --git a/src/detect-engine-register.h b/src/detect-engine-register.h index 0f0e7d1a6b..9cc563fa46 100644 --- a/src/detect-engine-register.h +++ b/src/detect-engine-register.h @@ -129,6 +129,7 @@ enum { DETECT_AL_HTTP_HEADER_REFERER, DETECT_AL_HTTP_RAW_HEADER, DETECT_AL_HTTP_URI, + DETECT_HTTP_URI, DETECT_AL_HTTP_RAW_URI, DETECT_AL_HTTP_STAT_MSG, DETECT_AL_HTTP_STAT_CODE, diff --git a/src/detect-engine-uri.c b/src/detect-engine-uri.c index acbe296036..c19215e90f 100644 --- a/src/detect-engine-uri.c +++ b/src/detect-engine-uri.c @@ -51,99 +51,6 @@ #include "app-layer-protos.h" #include "util-validate.h" -/** \brief HTTP URI 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 PrefilterTxUri(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_uri_normalized == NULL) - return; - - const uint32_t uri_len = bstr_len(tx_ud->request_uri_normalized); - const uint8_t *uri = bstr_ptr(tx_ud->request_uri_normalized); - - if (uri_len >= mpm_ctx->minlen) { - (void)mpm_table[mpm_ctx->mpm_type].Search(mpm_ctx, - &det_ctx->mtcu, &det_ctx->pmq, uri, uri_len); - } -} - -int PrefilterTxUriRegister(DetectEngineCtx *de_ctx, - SigGroupHead *sgh, MpmCtx *mpm_ctx) -{ - SCEnter(); - - return PrefilterAppendTxEngine(de_ctx, sgh, PrefilterTxUri, - ALPROTO_HTTP, HTP_REQUEST_LINE, - mpm_ctx, NULL, "http_uri"); -} - -/** - * \brief Do the content inspection & validation for a signature - * - * \param de_ctx Detection engine context - * \param det_ctx Detection engine thread context - * \param s Signature to inspect - * \param sm SigMatch to inspect - * \param f Flow - * \param flags app layer flags - * \param state App layer state - * - * \retval 0 no match. - * \retval 1 match. - * \retval 2 Sig can't match. - */ -int DetectEngineInspectHttpUri(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 = htp_tx_get_user_data(txv); - - if (tx_ud == NULL || tx_ud->request_uri_normalized == NULL) { - if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, txv, flags) > HTP_REQUEST_LINE) - return DETECT_ENGINE_INSPECT_SIG_CANT_MATCH; - else - return DETECT_ENGINE_INSPECT_SIG_NO_MATCH; - } - - det_ctx->discontinue_matching = 0; - det_ctx->buffer_offset = 0; - det_ctx->inspection_recursion_counter = 0; - -#if 0 - PrintRawDataFp(stdout, (uint8_t *)bstr_ptr(tx_ud->request_uri_normalized), - bstr_len(tx_ud->request_uri_normalized)); -#endif - - /* Inspect all the uricontents fetched on each - * transaction at the app layer */ - int r = DetectEngineContentInspection(de_ctx, det_ctx, s, smd, - f, - bstr_ptr(tx_ud->request_uri_normalized), - bstr_len(tx_ud->request_uri_normalized), - 0, DETECT_CI_FLAGS_SINGLE, - DETECT_ENGINE_CONTENT_INSPECTION_MODE_STATE, NULL); - if (r == 1) { - return DETECT_ENGINE_INSPECT_SIG_MATCH; - } else { - return DETECT_ENGINE_INSPECT_SIG_CANT_MATCH; - } -} - /***********************************Unittests**********************************/ #ifdef UNITTESTS diff --git a/src/detect-http-uri.c b/src/detect-http-uri.c index 3c481c2ee4..e55bea8d54 100644 --- a/src/detect-http-uri.c +++ b/src/detect-http-uri.c @@ -37,6 +37,7 @@ #include "detect-parse.h" #include "detect-engine.h" #include "detect-engine-mpm.h" +#include "detect-engine-prefilter.h" #include "detect-content.h" #include "detect-pcre.h" #include "detect-urilen.h" @@ -61,30 +62,41 @@ static void DetectHttpUriRegisterTests(void); static void DetectHttpUriSetupCallback(const DetectEngineCtx *de_ctx, Signature *s); static bool DetectHttpUriValidateCallback(const Signature *s, const char **sigerror); - +static InspectionBuffer *GetData(DetectEngineThreadCtx *det_ctx, + const DetectEngineTransforms *transforms, + Flow *_f, const uint8_t _flow_flags, + void *txv, const int list_id); +static int DetectHttpUriSetupSticky(DetectEngineCtx *de_ctx, Signature *s, const char *str); static int g_http_uri_buffer_id = 0; /** - * \brief Registration function for keyword: http_uri + * \brief Registration function for keywords: http_uri and http.uri */ void DetectHttpUriRegister (void) { + /* http_uri content modifier */ sigmatch_table[DETECT_AL_HTTP_URI].name = "http_uri"; sigmatch_table[DETECT_AL_HTTP_URI].desc = "content modifier to match specifically and only on the HTTP uri-buffer"; sigmatch_table[DETECT_AL_HTTP_URI].url = DOC_URL DOC_VERSION "/rules/http-keywords.html#http-uri-and-http-raw-uri"; - sigmatch_table[DETECT_AL_HTTP_URI].Match = NULL; sigmatch_table[DETECT_AL_HTTP_URI].Setup = DetectHttpUriSetup; - sigmatch_table[DETECT_AL_HTTP_URI].Free = NULL; sigmatch_table[DETECT_AL_HTTP_URI].RegisterTests = DetectHttpUriRegisterTests; - sigmatch_table[DETECT_AL_HTTP_URI].flags |= SIGMATCH_NOOPT; - DetectAppLayerMpmRegister("http_uri", SIG_FLAG_TOSERVER, 2, - PrefilterTxUriRegister); + /* http.uri sticky buffer */ + sigmatch_table[DETECT_HTTP_URI].name = "http.uri"; + sigmatch_table[DETECT_HTTP_URI].alias = "http.uri.normalized"; + sigmatch_table[DETECT_HTTP_URI].desc = "sticky buffer to match specifically and only on the normalized HTTP URI buffer"; + sigmatch_table[DETECT_HTTP_URI].url = DOC_URL DOC_VERSION "/rules/tls-keywords.html#http-uri"; + sigmatch_table[DETECT_HTTP_URI].Setup = DetectHttpUriSetupSticky; + sigmatch_table[DETECT_HTTP_URI].flags |= SIGMATCH_NOOPT; + + DetectAppLayerInspectEngineRegister2("http_uri", ALPROTO_HTTP, + SIG_FLAG_TOSERVER, HTP_REQUEST_LINE, + DetectEngineInspectBufferGeneric, GetData); - DetectAppLayerInspectEngineRegister("http_uri", - ALPROTO_HTTP, SIG_FLAG_TOSERVER, HTP_REQUEST_LINE, - DetectEngineInspectHttpUri); + DetectAppLayerMpmRegister2("http_uri", SIG_FLAG_TOSERVER, 2, + PrefilterGenericMpmRegister, GetData, ALPROTO_HTTP, + HTP_REQUEST_LINE); DetectBufferTypeSetDescriptionByName("http_uri", "http request uri"); @@ -98,7 +110,6 @@ void DetectHttpUriRegister (void) g_http_uri_buffer_id = DetectBufferTypeGetByName("http_uri"); } - /** * \brief this function setups the http_uri modifier keyword used in the rule * @@ -130,6 +141,48 @@ static void DetectHttpUriSetupCallback(const DetectEngineCtx *de_ctx, DetectUrilenApplyToContent(s, g_http_uri_buffer_id); } +/** + * \brief this function setup the http.uri keyword used in the rule + * + * \param de_ctx Pointer to the Detection Engine Context + * \param s Pointer to the Signature to which the current keyword belongs + * \param str Should hold an empty string always + * + * \retval 0 On success + */ +static int DetectHttpUriSetupSticky(DetectEngineCtx *de_ctx, Signature *s, const char *str) +{ + DetectBufferSetActiveList(s, g_http_uri_buffer_id); + s->alproto = ALPROTO_HTTP; + return 0; +} + +static InspectionBuffer *GetData(DetectEngineThreadCtx *det_ctx, + const DetectEngineTransforms *transforms, Flow *_f, + const uint8_t _flow_flags, void *txv, const int list_id) +{ + SCEnter(); + + 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 || tx_ud->request_uri_normalized == NULL) { + SCLogDebug("no tx_id or uri"); + return NULL; + } + + const uint32_t data_len = bstr_len(tx_ud->request_uri_normalized); + const uint8_t *data = bstr_ptr(tx_ud->request_uri_normalized); + + InspectionBufferSetup(buffer, data, data_len); + InspectionBufferApplyTransforms(buffer, transforms); + } + + return buffer; +} + /******************************** UNITESTS **********************************/ #ifdef UNITTESTS diff --git a/src/tests/detect.c b/src/tests/detect.c index 69c0504611..087ead6bda 100644 --- a/src/tests/detect.c +++ b/src/tests/detect.c @@ -313,14 +313,15 @@ static int SigTest06 (void) DetectEngineThreadCtx *det_ctx = NULL; Flow f; TcpSession ssn; - 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)); p = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP); + FAIL_IF_NULL(p); FLOW_INITIALIZE(&f); f.protoctx = (void *)&ssn; @@ -335,58 +336,34 @@ static int SigTest06 (void) StreamTcpInitConfig(TRUE); DetectEngineCtx *de_ctx = DetectEngineCtxInit(); - if (de_ctx == NULL) { - goto end; - } - + FAIL_IF_NULL(de_ctx); de_ctx->flags |= DE_QUIET; - de_ctx->sig_list = SigInit(de_ctx,"alert tcp any any -> any any (msg:\"HTTP URI cap\"; content:\"GET \"; depth:4; pcre:\"/GET (?P.*) HTTP\\/\\d\\.\\d\\r\\n/G\"; sid:1;)"); - if (de_ctx->sig_list == NULL) { - result = 0; - goto end; - } + Signature *s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"HTTP URI cap\"; content:\"GET \"; depth:4; pcre:\"/GET (?P.*) HTTP\\/\\d\\.\\d\\r\\n/G\"; sid:1;)"); + FAIL_IF_NULL(s); - de_ctx->sig_list->next = SigInit(de_ctx,"alert tcp any any -> any any (msg:\"HTTP URI test\"; uricontent:\"two\"; sid:2;)"); - if (de_ctx->sig_list->next == NULL) { - result = 0; - goto end; - } + s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"HTTP URI test\"; uricontent:\"two\"; sid:2;)"); + 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, buf, buflen); - if (r != 0) { - printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); - result = 0; - FLOWLOCK_UNLOCK(&f); - goto end; - } - FLOWLOCK_UNLOCK(&f); + FAIL_IF(r != 0); SigMatchSignatures(&th_v, de_ctx, det_ctx, p); - if (PacketAlertCheck(p, 1) && PacketAlertCheck(p, 2)) - result = 1; - else - printf("sid:1 %s, sid:2 %s: ", - PacketAlertCheck(p, 1) ? "OK" : "FAIL", - PacketAlertCheck(p, 2) ? "OK" : "FAIL"); - - SigGroupCleanup(de_ctx); - SigCleanSignatures(de_ctx); + FAIL_IF_NOT(PacketAlertCheck(p, 1)); + FAIL_IF_NOT(PacketAlertCheck(p, 2)); DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx); DetectEngineCtxFree(de_ctx); -end: - if (alp_tctx != NULL) - AppLayerParserThreadCtxFree(alp_tctx); + AppLayerParserThreadCtxFree(alp_tctx); UTHFreePackets(&p, 1); StreamTcpFreeConfig(TRUE); FLOW_DESTROY(&f); - return result; + PASS; } static int SigTest07 (void)