From bcb0b9ef9bd595ef226da8095cea15b624c10401 Mon Sep 17 00:00:00 2001 From: Pablo Rincon Date: Thu, 24 Jun 2010 02:19:29 +0200 Subject: [PATCH] Moving urilen inspection to detect-engine-uri. Adding unittests for pcre /U and urilen, in combination with uricontent --- src/detect-engine-uri.c | 1596 ++++++++++++++++++++++++++++++++++++++- src/detect-urilen.c | 4 +- src/detect-urilen.h | 2 + 3 files changed, 1596 insertions(+), 6 deletions(-) diff --git a/src/detect-engine-uri.c b/src/detect-engine-uri.c index 9580698460..0ffb71a065 100644 --- a/src/detect-engine-uri.c +++ b/src/detect-engine-uri.c @@ -20,7 +20,7 @@ * \author Victor Julien * \author Pablo Rincon Crespo * - * Based on detect-engine-payload.c + * Based on detect-engine-uri.c */ #include "suricata-common.h" @@ -32,6 +32,7 @@ #include "detect-parse.h" #include "detect-engine-state.h" #include "detect-uricontent.h" +#include "detect-urilen.h" #include "detect-pcre.h" #include "detect-isdataat.h" #include "detect-bytetest.h" @@ -235,6 +236,37 @@ static int DoInspectPacketUri(DetectEngineCtx *de_ctx, goto match; } + SCReturnInt(0); + } else if (sm->type == DETECT_AL_URILEN) { + SCLogDebug("inspecting uri len"); + + int r = 0; + DetectUrilenData *urilend = (DetectUrilenData *) sm->ctx; + + switch (urilend->mode) { + case DETECT_URILEN_EQ: + if (payload_len == urilend->urilen1) + r = 1; + break; + case DETECT_URILEN_LT: + if (payload_len < urilend->urilen1) + r = 1; + break; + case DETECT_URILEN_GT: + if (payload_len > urilend->urilen1) + r = 1; + break; + case DETECT_URILEN_RA: + if (payload_len > urilend->urilen1 && + payload_len < urilend->urilen2) + r = 1; + break; + } + + if (r == 1) { + goto match; + } + SCReturnInt(0); } else { /* we should never get here, but bail out just in case */ @@ -372,10 +404,10 @@ end: /***********************************Unittests**********************************/ #ifdef UNITTESTS - +/** \test Test a simple uricontent option */ static int UriTestSig01(void) { - int result = 1; + int result = 0; Flow f; HtpState *http_state = NULL; uint8_t http_buf1[] = "POST /one HTTP/1.0\r\n" @@ -424,7 +456,7 @@ static int UriTestSig01(void) de_ctx->flags |= DE_QUIET; s = de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " - "(msg:\"Test pcre U option\"; " + "(msg:\"Test uricontent option\"; " "uricontent:one; sid:1;)"); if (s == NULL) { goto end; @@ -453,6 +485,126 @@ static int UriTestSig01(void) goto end; } + DetectEngineStateReset(f.de_state); + + r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER, http_buf2, http_buf2_len); + if (r != 0) { + printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); + goto end; + } + + http_state = f.aldata[AlpGetStateIdx(ALPROTO_HTTP)]; + if (http_state == NULL) { + printf("no http state: "); + goto end; + } + + if (!PacketAlertCheck(&p, 1)) { + printf("sig 1 alerted, but it should not: "); + goto end; + } + + /* do detect */ + SigMatchSignatures(&tv, de_ctx, det_ctx, &p); + + result = 1; + +end: + if (det_ctx != NULL) + DetectEngineThreadCtxDeinit(&tv, det_ctx); + if (de_ctx != NULL) + SigGroupCleanup(de_ctx); + if (de_ctx != NULL) + DetectEngineCtxFree(de_ctx); + + StreamTcpFreeConfig(TRUE); + FLOW_DESTROY(&f); + return result; +} + +/** \test Test the pcre /U option */ +static int UriTestSig02(void) +{ + int result = 0; + Flow f; + HtpState *http_state = NULL; + uint8_t http_buf1[] = "POST /on HTTP/1.0\r\n" + "User-Agent: Mozilla/1.0\r\n" + "Cookie: hellocatch\r\n\r\n"; + uint32_t http_buf1_len = sizeof(http_buf1) - 1; + uint8_t http_buf2[] = "POST /one HTTP/1.0\r\n" + "User-Agent: Mozilla/1.0\r\n" + "Cookie: hellocatch\r\n\r\n"; + uint32_t http_buf2_len = sizeof(http_buf2) - 1; + TcpSession ssn; + Packet p; + Signature *s = NULL; + ThreadVars tv; + DetectEngineThreadCtx *det_ctx = NULL; + + memset(&tv, 0, sizeof(ThreadVars)); + memset(&p, 0, sizeof(Packet)); + memset(&f, 0, sizeof(Flow)); + memset(&ssn, 0, sizeof(TcpSession)); + + p.src.family = AF_INET; + p.dst.family = AF_INET; + p.payload = http_buf1; + p.payload_len = http_buf1_len; + p.proto = IPPROTO_TCP; + + FLOW_INITIALIZE(&f); + f.protoctx = (void *)&ssn; + f.src.family = AF_INET; + f.dst.family = AF_INET; + + p.flow = &f; + p.flowflags |= FLOW_PKT_TOSERVER; + p.flowflags |= FLOW_PKT_ESTABLISHED; + f.alproto = ALPROTO_HTTP; + + StreamTcpInitConfig(TRUE); + FlowL7DataPtrInit(&f); + + DetectEngineCtx *de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) { + goto end; + } + de_ctx->mpm_matcher = MPM_B2G; + de_ctx->flags |= DE_QUIET; + + s = de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " + "(msg:\"Test pcre /U option\"; " + "pcre:/one/U; sid:1;)"); + if (s == NULL) { + goto end; + } + + SigGroupBuild(de_ctx); + DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx); + + int r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER, http_buf1, http_buf1_len); + if (r != 0) { + printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); + goto end; + } + + http_state = f.aldata[AlpGetStateIdx(ALPROTO_HTTP)]; + if (http_state == NULL) { + printf("no http state: "); + goto end; + } + + /* do detect */ + SigMatchSignatures(&tv, de_ctx, det_ctx, &p); + + if (PacketAlertCheck(&p, 1)) { + printf("sig 1 alerted with payload2, but it should not: "); + goto end; + } + + DetectEngineStateReset(f.de_state); + r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER, http_buf2, http_buf2_len); if (r != 0) { printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); @@ -465,14 +617,1437 @@ static int UriTestSig01(void) goto end; } + /* do detect */ + SigMatchSignatures(&tv, de_ctx, det_ctx, &p); + if (!PacketAlertCheck(&p, 1)) { + printf("sig 1 didnt alert, but it should: "); + goto end; + } + + result = 1; + +end: + if (det_ctx != NULL) + DetectEngineThreadCtxDeinit(&tv, det_ctx); + if (de_ctx != NULL) + SigGroupCleanup(de_ctx); + if (de_ctx != NULL) + DetectEngineCtxFree(de_ctx); + + StreamTcpFreeConfig(TRUE); + FLOW_DESTROY(&f); + return result; +} + +/** \test Test the pcre /U option */ +static int UriTestSig03(void) +{ + int result = 0; + Flow f; + HtpState *http_state = NULL; + uint8_t http_buf1[] = "POST /one HTTP/1.0\r\n" + "User-Agent: Mozilla/1.0\r\n" + "Cookie: hellocatch\r\n\r\n"; + uint32_t http_buf1_len = sizeof(http_buf1) - 1; + uint8_t http_buf2[] = "POST /oneself HTTP/1.0\r\n" + "User-Agent: Mozilla/1.0\r\n" + "Cookie: hellocatch\r\n\r\n"; + uint32_t http_buf2_len = sizeof(http_buf2) - 1; + TcpSession ssn; + Packet p; + Signature *s = NULL; + ThreadVars tv; + DetectEngineThreadCtx *det_ctx = NULL; + + memset(&tv, 0, sizeof(ThreadVars)); + memset(&p, 0, sizeof(Packet)); + memset(&f, 0, sizeof(Flow)); + memset(&ssn, 0, sizeof(TcpSession)); + + p.src.family = AF_INET; + p.dst.family = AF_INET; + p.payload = http_buf1; + p.payload_len = http_buf1_len; + p.proto = IPPROTO_TCP; + + FLOW_INITIALIZE(&f); + f.protoctx = (void *)&ssn; + f.src.family = AF_INET; + f.dst.family = AF_INET; + + p.flow = &f; + p.flowflags |= FLOW_PKT_TOSERVER; + p.flowflags |= FLOW_PKT_ESTABLISHED; + f.alproto = ALPROTO_HTTP; + + StreamTcpInitConfig(TRUE); + FlowL7DataPtrInit(&f); + + DetectEngineCtx *de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) { + goto end; + } + de_ctx->mpm_matcher = MPM_B2G; + de_ctx->flags |= DE_QUIET; + + s = de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " + "(msg:\"Test pcre /U option\"; " + "pcre:/blah/U; sid:1;)"); + if (s == NULL) { + goto end; + } + + SigGroupBuild(de_ctx); + DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx); + + int r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER, http_buf1, http_buf1_len); + if (r != 0) { + printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); + goto end; + } + + http_state = f.aldata[AlpGetStateIdx(ALPROTO_HTTP)]; + if (http_state == NULL) { + printf("no http state: "); + goto end; + } + + /* do detect */ + SigMatchSignatures(&tv, de_ctx, det_ctx, &p); + + if (PacketAlertCheck(&p, 1)) { printf("sig 1 alerted, but it should not: "); goto end; } + DetectEngineStateReset(f.de_state); + + r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER, http_buf2, http_buf2_len); + if (r != 0) { + printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); + goto end; + } + + http_state = f.aldata[AlpGetStateIdx(ALPROTO_HTTP)]; + if (http_state == NULL) { + printf("no http state: "); + goto end; + } + /* do detect */ SigMatchSignatures(&tv, de_ctx, det_ctx, &p); + + if (PacketAlertCheck(&p, 1)) { + printf("sig 1 alerted, but it should not: "); + goto end; + } + + result = 1; + +end: + if (det_ctx != NULL) + DetectEngineThreadCtxDeinit(&tv, det_ctx); + if (de_ctx != NULL) + SigGroupCleanup(de_ctx); + if (de_ctx != NULL) + DetectEngineCtxFree(de_ctx); + + StreamTcpFreeConfig(TRUE); + FLOW_DESTROY(&f); + return result; +} + +/** \test Test the urilen option */ +static int UriTestSig04(void) +{ + int result = 0; + Flow f; + HtpState *http_state = NULL; + uint8_t http_buf1[] = "POST /one HTTP/1.0\r\n" + "User-Agent: Mozilla/1.0\r\n" + "Cookie: hellocatch\r\n\r\n"; + uint32_t http_buf1_len = sizeof(http_buf1) - 1; + uint8_t http_buf2[] = "POST /oneself HTTP/1.0\r\n" + "User-Agent: Mozilla/1.0\r\n" + "Cookie: hellocatch\r\n\r\n"; + uint32_t http_buf2_len = sizeof(http_buf2) - 1; + TcpSession ssn; + Packet p; + Signature *s = NULL; + ThreadVars tv; + DetectEngineThreadCtx *det_ctx = NULL; + + memset(&tv, 0, sizeof(ThreadVars)); + memset(&p, 0, sizeof(Packet)); + memset(&f, 0, sizeof(Flow)); + memset(&ssn, 0, sizeof(TcpSession)); + + p.src.family = AF_INET; + p.dst.family = AF_INET; + p.payload = http_buf1; + p.payload_len = http_buf1_len; + p.proto = IPPROTO_TCP; + + FLOW_INITIALIZE(&f); + f.protoctx = (void *)&ssn; + f.src.family = AF_INET; + f.dst.family = AF_INET; + + p.flow = &f; + p.flowflags |= FLOW_PKT_TOSERVER; + p.flowflags |= FLOW_PKT_ESTABLISHED; + f.alproto = ALPROTO_HTTP; + + StreamTcpInitConfig(TRUE); + FlowL7DataPtrInit(&f); + + DetectEngineCtx *de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) { + goto end; + } + de_ctx->mpm_matcher = MPM_B2G; + de_ctx->flags |= DE_QUIET; + + s = de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " + "(msg:\"Test urilen option\"; " + "urilen:>20; sid:1;)"); + if (s == NULL) { + goto end; + } + + SigGroupBuild(de_ctx); + DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx); + + int r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER, http_buf1, http_buf1_len); + if (r != 0) { + printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); + goto end; + } + + http_state = f.aldata[AlpGetStateIdx(ALPROTO_HTTP)]; + if (http_state == NULL) { + printf("no http state: "); + goto end; + } + + /* do detect */ + SigMatchSignatures(&tv, de_ctx, det_ctx, &p); + + if (PacketAlertCheck(&p, 1)) { + printf("sig 1 alerted, but it should not: "); + goto end; + } + + DetectEngineStateReset(f.de_state); + + r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER, http_buf2, http_buf2_len); + if (r != 0) { + printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); + goto end; + } + + http_state = f.aldata[AlpGetStateIdx(ALPROTO_HTTP)]; + if (http_state == NULL) { + printf("no http state: "); + goto end; + } + + /* do detect */ + SigMatchSignatures(&tv, de_ctx, det_ctx, &p); + + + if (PacketAlertCheck(&p, 1)) { + printf("sig 1 alerted, but it should not: "); + goto end; + } + + result = 1; + +end: + if (det_ctx != NULL) + DetectEngineThreadCtxDeinit(&tv, det_ctx); + if (de_ctx != NULL) + SigGroupCleanup(de_ctx); + if (de_ctx != NULL) + DetectEngineCtxFree(de_ctx); + + StreamTcpFreeConfig(TRUE); + FLOW_DESTROY(&f); + return result; +} + +/** \test Test the urilen option */ +static int UriTestSig05(void) +{ + int result = 0; + Flow f; + HtpState *http_state = NULL; + uint8_t http_buf1[] = "POST /one HTTP/1.0\r\n" + "User-Agent: Mozilla/1.0\r\n" + "Cookie: hellocatch\r\n\r\n"; + uint32_t http_buf1_len = sizeof(http_buf1) - 1; + uint8_t http_buf2[] = "POST /oneself HTTP/1.0\r\n" + "User-Agent: Mozilla/1.0\r\n" + "Cookie: hellocatch\r\n\r\n"; + uint32_t http_buf2_len = sizeof(http_buf2) - 1; + TcpSession ssn; + Packet p; + Signature *s = NULL; + ThreadVars tv; + DetectEngineThreadCtx *det_ctx = NULL; + + memset(&tv, 0, sizeof(ThreadVars)); + memset(&p, 0, sizeof(Packet)); + memset(&f, 0, sizeof(Flow)); + memset(&ssn, 0, sizeof(TcpSession)); + + p.src.family = AF_INET; + p.dst.family = AF_INET; + p.payload = http_buf1; + p.payload_len = http_buf1_len; + p.proto = IPPROTO_TCP; + + FLOW_INITIALIZE(&f); + f.protoctx = (void *)&ssn; + f.src.family = AF_INET; + f.dst.family = AF_INET; + + p.flow = &f; + p.flowflags |= FLOW_PKT_TOSERVER; + p.flowflags |= FLOW_PKT_ESTABLISHED; + f.alproto = ALPROTO_HTTP; + + StreamTcpInitConfig(TRUE); + FlowL7DataPtrInit(&f); + + DetectEngineCtx *de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) { + goto end; + } + de_ctx->mpm_matcher = MPM_B2G; + de_ctx->flags |= DE_QUIET; + + s = de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " + "(msg:\"Test urilen option\"; " + "urilen:>4; sid:1;)"); + if (s == NULL) { + goto end; + } + + SigGroupBuild(de_ctx); + DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx); + + int r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER, http_buf1, http_buf1_len); + if (r != 0) { + printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); + goto end; + } + + http_state = f.aldata[AlpGetStateIdx(ALPROTO_HTTP)]; + if (http_state == NULL) { + printf("no http state: "); + goto end; + } + + /* do detect */ + SigMatchSignatures(&tv, de_ctx, det_ctx, &p); + + if (PacketAlertCheck(&p, 1)) { + printf("sig 1 alerted, but it should not: "); + goto end; + } + + DetectEngineStateReset(f.de_state); + + r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER, http_buf2, http_buf2_len); + if (r != 0) { + printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); + goto end; + } + + http_state = f.aldata[AlpGetStateIdx(ALPROTO_HTTP)]; + if (http_state == NULL) { + printf("no http state: "); + goto end; + } + + /* do detect */ + SigMatchSignatures(&tv, de_ctx, det_ctx, &p); + + + if (!PacketAlertCheck(&p, 1)) { + printf("sig 1 didnt alert with payload2, but it should: "); + goto end; + } + + result = 1; + +end: + if (det_ctx != NULL) + DetectEngineThreadCtxDeinit(&tv, det_ctx); + if (de_ctx != NULL) + SigGroupCleanup(de_ctx); + if (de_ctx != NULL) + DetectEngineCtxFree(de_ctx); + + StreamTcpFreeConfig(TRUE); + FLOW_DESTROY(&f); + return result; +} + +/** \test Test the pcre /U option */ +static int UriTestSig06(void) +{ + int result = 0; + Flow f; + HtpState *http_state = NULL; + uint8_t http_buf1[] = "POST /oneoneoneone HTTP/1.0\r\n" + "User-Agent: Mozilla/1.0\r\n" + "Cookie: hellocatch\r\n\r\n"; + uint32_t http_buf1_len = sizeof(http_buf1) - 1; + uint8_t http_buf2[] = "POST /oneself HTTP/1.0\r\n" + "User-Agent: Mozilla/1.0\r\n" + "Cookie: hellocatch\r\n\r\n"; + uint32_t http_buf2_len = sizeof(http_buf2) - 1; + TcpSession ssn; + Packet p; + Signature *s = NULL; + ThreadVars tv; + DetectEngineThreadCtx *det_ctx = NULL; + + memset(&tv, 0, sizeof(ThreadVars)); + memset(&p, 0, sizeof(Packet)); + memset(&f, 0, sizeof(Flow)); + memset(&ssn, 0, sizeof(TcpSession)); + + p.src.family = AF_INET; + p.dst.family = AF_INET; + p.payload = http_buf1; + p.payload_len = http_buf1_len; + p.proto = IPPROTO_TCP; + + FLOW_INITIALIZE(&f); + f.protoctx = (void *)&ssn; + f.src.family = AF_INET; + f.dst.family = AF_INET; + + p.flow = &f; + p.flowflags |= FLOW_PKT_TOSERVER; + p.flowflags |= FLOW_PKT_ESTABLISHED; + f.alproto = ALPROTO_HTTP; + + StreamTcpInitConfig(TRUE); + FlowL7DataPtrInit(&f); + + DetectEngineCtx *de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) { + goto end; + } + de_ctx->mpm_matcher = MPM_B2G; + de_ctx->flags |= DE_QUIET; + + s = de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " + "(msg:\"Test pcre /U option\"; " + "pcre:/(oneself)+/U; sid:1;)"); + if (s == NULL) { + goto end; + } + + SigGroupBuild(de_ctx); + DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx); + + int r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER, http_buf1, http_buf1_len); + if (r != 0) { + printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); + goto end; + } + + http_state = f.aldata[AlpGetStateIdx(ALPROTO_HTTP)]; + if (http_state == NULL) { + printf("no http state: "); + goto end; + } + + /* do detect */ + SigMatchSignatures(&tv, de_ctx, det_ctx, &p); + + if (PacketAlertCheck(&p, 1)) { + printf("sig 1 alerted, but it should not: "); + goto end; + } + + DetectEngineStateReset(f.de_state); + + r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER, http_buf2, http_buf2_len); + if (r != 0) { + printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); + goto end; + } + + http_state = f.aldata[AlpGetStateIdx(ALPROTO_HTTP)]; + if (http_state == NULL) { + printf("no http state: "); + goto end; + } + + /* do detect */ + SigMatchSignatures(&tv, de_ctx, det_ctx, &p); + + if (!PacketAlertCheck(&p, 1)) { + printf("sig 1 didnt alert on payload2, but it should: "); + goto end; + } + + result = 1; + +end: + if (det_ctx != NULL) + DetectEngineThreadCtxDeinit(&tv, det_ctx); + if (de_ctx != NULL) + SigGroupCleanup(de_ctx); + if (de_ctx != NULL) + DetectEngineCtxFree(de_ctx); + + StreamTcpFreeConfig(TRUE); + FLOW_DESTROY(&f); + return result; +} + +/** \test Test the pcre /U option in combination with urilen */ +static int UriTestSig07(void) +{ + int result = 0; + Flow f; + HtpState *http_state = NULL; + uint8_t http_buf1[] = "POST /oneoneoneone HTTP/1.0\r\n" + "User-Agent: Mozilla/1.0\r\n" + "Cookie: hellocatch\r\n\r\n"; + uint32_t http_buf1_len = sizeof(http_buf1) - 1; + uint8_t http_buf2[] = "POST /oneoneself HTTP/1.0\r\n" + "User-Agent: Mozilla/1.0\r\n" + "Cookie: hellocatch\r\n\r\n"; + uint32_t http_buf2_len = sizeof(http_buf2) - 1; + TcpSession ssn; + Packet p; + Signature *s = NULL; + ThreadVars tv; + DetectEngineThreadCtx *det_ctx = NULL; + + memset(&tv, 0, sizeof(ThreadVars)); + memset(&p, 0, sizeof(Packet)); + memset(&f, 0, sizeof(Flow)); + memset(&ssn, 0, sizeof(TcpSession)); + + p.src.family = AF_INET; + p.dst.family = AF_INET; + p.payload = http_buf1; + p.payload_len = http_buf1_len; + p.proto = IPPROTO_TCP; + + FLOW_INITIALIZE(&f); + f.protoctx = (void *)&ssn; + f.src.family = AF_INET; + f.dst.family = AF_INET; + + p.flow = &f; + p.flowflags |= FLOW_PKT_TOSERVER; + p.flowflags |= FLOW_PKT_ESTABLISHED; + f.alproto = ALPROTO_HTTP; + + StreamTcpInitConfig(TRUE); + FlowL7DataPtrInit(&f); + + DetectEngineCtx *de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) { + goto end; + } + de_ctx->mpm_matcher = MPM_B2G; + de_ctx->flags |= DE_QUIET; + + s = de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " + "(msg:\"Test pcre /U option with urilen \"; " + "pcre:/(one){2,}(self)?/U; urilen:3<>20; sid:1;)"); + if (s == NULL) { + goto end; + } + + SigGroupBuild(de_ctx); + DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx); + + int r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER, http_buf1, http_buf1_len); + if (r != 0) { + printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); + goto end; + } + + http_state = f.aldata[AlpGetStateIdx(ALPROTO_HTTP)]; + if (http_state == NULL) { + printf("no http state: "); + goto end; + } + + /* do detect */ + SigMatchSignatures(&tv, de_ctx, det_ctx, &p); + + if (!PacketAlertCheck(&p, 1)) { + printf("sig 1 didnt alert, but it should: "); + goto end; + } + + DetectEngineStateReset(f.de_state); + + r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER, http_buf2, http_buf2_len); + if (r != 0) { + printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); + goto end; + } + + http_state = f.aldata[AlpGetStateIdx(ALPROTO_HTTP)]; + if (http_state == NULL) { + printf("no http state: "); + goto end; + } + + /* do detect */ + SigMatchSignatures(&tv, de_ctx, det_ctx, &p); + + if (!PacketAlertCheck(&p, 1)) { + printf("sig 1 didnt alert with payload2, but it should: "); + goto end; + } + + result = 1; + +end: + if (det_ctx != NULL) + DetectEngineThreadCtxDeinit(&tv, det_ctx); + if (de_ctx != NULL) + SigGroupCleanup(de_ctx); + if (de_ctx != NULL) + DetectEngineCtxFree(de_ctx); + + StreamTcpFreeConfig(TRUE); + FLOW_DESTROY(&f); + return result; +} + +/** \test Test the pcre /U option in combination with urilen */ +static int UriTestSig08(void) +{ + int result = 0; + Flow f; + HtpState *http_state = NULL; + uint8_t http_buf1[] = "POST /oneoneoneone HTTP/1.0\r\n" + "User-Agent: Mozilla/1.0\r\n" + "Cookie: hellocatch\r\n\r\n"; + uint32_t http_buf1_len = sizeof(http_buf1) - 1; + uint8_t http_buf2[] = "POST /oneoneself HTTP/1.0\r\n" + "User-Agent: Mozilla/1.0\r\n" + "Cookie: hellocatch\r\n\r\n"; + uint32_t http_buf2_len = sizeof(http_buf2) - 1; + TcpSession ssn; + Packet p; + Signature *s = NULL; + ThreadVars tv; + DetectEngineThreadCtx *det_ctx = NULL; + + memset(&tv, 0, sizeof(ThreadVars)); + memset(&p, 0, sizeof(Packet)); + memset(&f, 0, sizeof(Flow)); + memset(&ssn, 0, sizeof(TcpSession)); + + p.src.family = AF_INET; + p.dst.family = AF_INET; + p.payload = http_buf1; + p.payload_len = http_buf1_len; + p.proto = IPPROTO_TCP; + + FLOW_INITIALIZE(&f); + f.protoctx = (void *)&ssn; + f.src.family = AF_INET; + f.dst.family = AF_INET; + + p.flow = &f; + p.flowflags |= FLOW_PKT_TOSERVER; + p.flowflags |= FLOW_PKT_ESTABLISHED; + f.alproto = ALPROTO_HTTP; + + StreamTcpInitConfig(TRUE); + FlowL7DataPtrInit(&f); + + DetectEngineCtx *de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) { + goto end; + } + de_ctx->mpm_matcher = MPM_B2G; + de_ctx->flags |= DE_QUIET; + + s = de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " + "(msg:\"Test pcre /U option with urilen\"; " + "pcre:/(blabla){2,}(self)?/U; urilen:3<>20; sid:1;)"); + if (s == NULL) { + goto end; + } + + SigGroupBuild(de_ctx); + DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx); + + int r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER, http_buf1, http_buf1_len); + if (r != 0) { + printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); + goto end; + } + + http_state = f.aldata[AlpGetStateIdx(ALPROTO_HTTP)]; + if (http_state == NULL) { + printf("no http state: "); + goto end; + } + + /* do detect */ + SigMatchSignatures(&tv, de_ctx, det_ctx, &p); + + if (PacketAlertCheck(&p, 1)) { + printf("sig 1 alerted, but it should not: "); + goto end; + } + + DetectEngineStateReset(f.de_state); + + r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER, http_buf2, http_buf2_len); + if (r != 0) { + printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); + goto end; + } + + http_state = f.aldata[AlpGetStateIdx(ALPROTO_HTTP)]; + if (http_state == NULL) { + printf("no http state: "); + goto end; + } + + /* do detect */ + SigMatchSignatures(&tv, de_ctx, det_ctx, &p); + + if (PacketAlertCheck(&p, 1)) { + printf("sig 1 alerted, but it should not: "); + goto end; + } + + result = 1; + +end: + if (det_ctx != NULL) + DetectEngineThreadCtxDeinit(&tv, det_ctx); + if (de_ctx != NULL) + SigGroupCleanup(de_ctx); + if (de_ctx != NULL) + DetectEngineCtxFree(de_ctx); + + StreamTcpFreeConfig(TRUE); + FLOW_DESTROY(&f); + return result; +} + +/** \test Test the pcre /U option in combination with urilen */ +static int UriTestSig09(void) +{ + int result = 0; + Flow f; + HtpState *http_state = NULL; + uint8_t http_buf1[] = "POST /oneoneoneone HTTP/1.0\r\n" + "User-Agent: Mozilla/1.0\r\n" + "Cookie: hellocatch\r\n\r\n"; + uint32_t http_buf1_len = sizeof(http_buf1) - 1; + uint8_t http_buf2[] = "POST /oneoneself HTTP/1.0\r\n" + "User-Agent: Mozilla/1.0\r\n" + "Cookie: hellocatch\r\n\r\n"; + uint32_t http_buf2_len = sizeof(http_buf2) - 1; + TcpSession ssn; + Packet p; + Signature *s = NULL; + ThreadVars tv; + DetectEngineThreadCtx *det_ctx = NULL; + + memset(&tv, 0, sizeof(ThreadVars)); + memset(&p, 0, sizeof(Packet)); + memset(&f, 0, sizeof(Flow)); + memset(&ssn, 0, sizeof(TcpSession)); + + p.src.family = AF_INET; + p.dst.family = AF_INET; + p.payload = http_buf1; + p.payload_len = http_buf1_len; + p.proto = IPPROTO_TCP; + + FLOW_INITIALIZE(&f); + f.protoctx = (void *)&ssn; + f.src.family = AF_INET; + f.dst.family = AF_INET; + + p.flow = &f; + p.flowflags |= FLOW_PKT_TOSERVER; + p.flowflags |= FLOW_PKT_ESTABLISHED; + f.alproto = ALPROTO_HTTP; + + StreamTcpInitConfig(TRUE); + FlowL7DataPtrInit(&f); + + DetectEngineCtx *de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) { + goto end; + } + de_ctx->mpm_matcher = MPM_B2G; + de_ctx->flags |= DE_QUIET; + + s = de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " + "(msg:\"Test pcre /U option with urilen \"; " + "pcre:/(one){2,}(self)?/U; urilen:<2; sid:1;)"); + if (s == NULL) { + goto end; + } + + SigGroupBuild(de_ctx); + DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx); + + int r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER, http_buf1, http_buf1_len); + if (r != 0) { + printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); + goto end; + } + + http_state = f.aldata[AlpGetStateIdx(ALPROTO_HTTP)]; + if (http_state == NULL) { + printf("no http state: "); + goto end; + } + + /* do detect */ + SigMatchSignatures(&tv, de_ctx, det_ctx, &p); + + if (PacketAlertCheck(&p, 1)) { + printf("sig 1 alerted, but it should not: "); + goto end; + } + + DetectEngineStateReset(f.de_state); + + r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER, http_buf2, http_buf2_len); + if (r != 0) { + printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); + goto end; + } + + http_state = f.aldata[AlpGetStateIdx(ALPROTO_HTTP)]; + if (http_state == NULL) { + printf("no http state: "); + goto end; + } + + /* do detect */ + SigMatchSignatures(&tv, de_ctx, det_ctx, &p); + + if (PacketAlertCheck(&p, 1)) { + printf("sig 1 alerted, but it should not: "); + goto end; + } + + result = 1; + +end: + if (det_ctx != NULL) + DetectEngineThreadCtxDeinit(&tv, det_ctx); + if (de_ctx != NULL) + SigGroupCleanup(de_ctx); + if (de_ctx != NULL) + DetectEngineCtxFree(de_ctx); + + StreamTcpFreeConfig(TRUE); + FLOW_DESTROY(&f); + return result; +} + +/** \test Test the uricontent option in combination with urilen */ +static int UriTestSig10(void) +{ + int result = 0; + Flow f; + HtpState *http_state = NULL; + uint8_t http_buf1[] = "POST /oneoneoneone HTTP/1.0\r\n" + "User-Agent: Mozilla/1.0\r\n" + "Cookie: hellocatch\r\n\r\n"; + uint32_t http_buf1_len = sizeof(http_buf1) - 1; + uint8_t http_buf2[] = "POST /oneoneself HTTP/1.0\r\n" + "User-Agent: Mozilla/1.0\r\n" + "Cookie: hellocatch\r\n\r\n"; + uint32_t http_buf2_len = sizeof(http_buf2) - 1; + TcpSession ssn; + Packet p; + Signature *s = NULL; + ThreadVars tv; + DetectEngineThreadCtx *det_ctx = NULL; + + memset(&tv, 0, sizeof(ThreadVars)); + memset(&p, 0, sizeof(Packet)); + memset(&f, 0, sizeof(Flow)); + memset(&ssn, 0, sizeof(TcpSession)); + + p.src.family = AF_INET; + p.dst.family = AF_INET; + p.payload = http_buf1; + p.payload_len = http_buf1_len; + p.proto = IPPROTO_TCP; + + FLOW_INITIALIZE(&f); + f.protoctx = (void *)&ssn; + f.src.family = AF_INET; + f.dst.family = AF_INET; + + p.flow = &f; + p.flowflags |= FLOW_PKT_TOSERVER; + p.flowflags |= FLOW_PKT_ESTABLISHED; + f.alproto = ALPROTO_HTTP; + + StreamTcpInitConfig(TRUE); + FlowL7DataPtrInit(&f); + + DetectEngineCtx *de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) { + goto end; + } + de_ctx->mpm_matcher = MPM_B2G; + de_ctx->flags |= DE_QUIET; + + s = de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " + "(msg:\"Test uricontent with urilen option\"; " + "uricontent:one; urilen:<2; sid:1;)"); + if (s == NULL) { + goto end; + } + + SigGroupBuild(de_ctx); + DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx); + + int r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER, http_buf1, http_buf1_len); + if (r != 0) { + printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); + goto end; + } + + http_state = f.aldata[AlpGetStateIdx(ALPROTO_HTTP)]; + if (http_state == NULL) { + printf("no http state: "); + goto end; + } + + /* do detect */ + SigMatchSignatures(&tv, de_ctx, det_ctx, &p); + + if (PacketAlertCheck(&p, 1)) { + printf("sig 1 alerted, but it should not: "); + goto end; + } + + DetectEngineStateReset(f.de_state); + + r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER, http_buf2, http_buf2_len); + if (r != 0) { + printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); + goto end; + } + + http_state = f.aldata[AlpGetStateIdx(ALPROTO_HTTP)]; + if (http_state == NULL) { + printf("no http state: "); + goto end; + } + + /* do detect */ + SigMatchSignatures(&tv, de_ctx, det_ctx, &p); + + if (PacketAlertCheck(&p, 1)) { + printf("sig 1 alerted, but it should not: "); + goto end; + } + + result = 1; + +end: + if (det_ctx != NULL) + DetectEngineThreadCtxDeinit(&tv, det_ctx); + if (de_ctx != NULL) + SigGroupCleanup(de_ctx); + if (de_ctx != NULL) + DetectEngineCtxFree(de_ctx); + + StreamTcpFreeConfig(TRUE); + FLOW_DESTROY(&f); + return result; +} + +/** \test Test content, uricontent, urilen, pcre /U options */ +static int UriTestSig11(void) +{ + int result = 0; + Flow f; + HtpState *http_state = NULL; + uint8_t http_buf1[] = "POST /oneoneoneone HTTP/1.0\r\n" + "User-Agent: Mozilla/1.0\r\n" + "Cookie: hellocatch\r\n\r\n"; + uint32_t http_buf1_len = sizeof(http_buf1) - 1; + uint8_t http_buf2[] = "POST /oneoneself HTTP/1.0\r\n" + "User-Agent: Mozilla/1.0\r\n" + "Cookie: hellocatch\r\n\r\n"; + uint32_t http_buf2_len = sizeof(http_buf2) - 1; + TcpSession ssn; + Packet p; + Signature *s = NULL; + ThreadVars tv; + DetectEngineThreadCtx *det_ctx = NULL; + + memset(&tv, 0, sizeof(ThreadVars)); + memset(&p, 0, sizeof(Packet)); + memset(&f, 0, sizeof(Flow)); + memset(&ssn, 0, sizeof(TcpSession)); + + p.src.family = AF_INET; + p.dst.family = AF_INET; + p.payload = http_buf1; + p.payload_len = http_buf1_len; + p.proto = IPPROTO_TCP; + + FLOW_INITIALIZE(&f); + f.protoctx = (void *)&ssn; + f.src.family = AF_INET; + f.dst.family = AF_INET; + + p.flow = &f; + p.flowflags |= FLOW_PKT_TOSERVER; + p.flowflags |= FLOW_PKT_ESTABLISHED; + f.alproto = ALPROTO_HTTP; + + StreamTcpInitConfig(TRUE); + FlowL7DataPtrInit(&f); + + DetectEngineCtx *de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) { + goto end; + } + de_ctx->mpm_matcher = MPM_B2G; + de_ctx->flags |= DE_QUIET; + + s = de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " + "(msg:\"Test content, uricontent, pcre /U and urilen options\"; " + "content:one; uricontent:one; pcre:/(one){2,}(self)?/U;" + "urilen:<2; sid:1;)"); + if (s == NULL) { + goto end; + } + + SigGroupBuild(de_ctx); + DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx); + + int r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER, http_buf1, http_buf1_len); + if (r != 0) { + printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); + goto end; + } + + http_state = f.aldata[AlpGetStateIdx(ALPROTO_HTTP)]; + if (http_state == NULL) { + printf("no http state: "); + goto end; + } + + /* do detect */ + SigMatchSignatures(&tv, de_ctx, det_ctx, &p); + + if (PacketAlertCheck(&p, 1)) { + printf("sig 1 alerted, but it should not: "); + goto end; + } + + DetectEngineStateReset(f.de_state); + + r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER, http_buf2, http_buf2_len); + if (r != 0) { + printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); + goto end; + } + + http_state = f.aldata[AlpGetStateIdx(ALPROTO_HTTP)]; + if (http_state == NULL) { + printf("no http state: "); + goto end; + } + + /* do detect */ + SigMatchSignatures(&tv, de_ctx, det_ctx, &p); + + if (PacketAlertCheck(&p, 1)) { + printf("sig 1 alerted, but it should not: "); + goto end; + } + + result = 1; + +end: + if (det_ctx != NULL) + DetectEngineThreadCtxDeinit(&tv, det_ctx); + if (de_ctx != NULL) + SigGroupCleanup(de_ctx); + if (de_ctx != NULL) + DetectEngineCtxFree(de_ctx); + + StreamTcpFreeConfig(TRUE); + FLOW_DESTROY(&f); + return result; +} + +/** \test Test uricontent, urilen, pcre /U options */ +static int UriTestSig12(void) +{ + int result = 0; + Flow f; + HtpState *http_state = NULL; + uint8_t http_buf1[] = "POST /oneoneoneone HTTP/1.0\r\n" + "User-Agent: Mozilla/1.0\r\n" + "Cookie: hellocatch\r\n\r\n"; + uint32_t http_buf1_len = sizeof(http_buf1) - 1; + uint8_t http_buf2[] = "POST /oneoneself HTTP/1.0\r\n" + "User-Agent: Mozilla/1.0\r\n" + "Cookie: hellocatch\r\n\r\n"; + uint32_t http_buf2_len = sizeof(http_buf2) - 1; + TcpSession ssn; + Packet p; + Signature *s = NULL; + ThreadVars tv; + DetectEngineThreadCtx *det_ctx = NULL; + + memset(&tv, 0, sizeof(ThreadVars)); + memset(&p, 0, sizeof(Packet)); + memset(&f, 0, sizeof(Flow)); + memset(&ssn, 0, sizeof(TcpSession)); + + p.src.family = AF_INET; + p.dst.family = AF_INET; + p.payload = http_buf1; + p.payload_len = http_buf1_len; + p.proto = IPPROTO_TCP; + + FLOW_INITIALIZE(&f); + f.protoctx = (void *)&ssn; + f.src.family = AF_INET; + f.dst.family = AF_INET; + + p.flow = &f; + p.flowflags |= FLOW_PKT_TOSERVER; + p.flowflags |= FLOW_PKT_ESTABLISHED; + f.alproto = ALPROTO_HTTP; + + StreamTcpInitConfig(TRUE); + FlowL7DataPtrInit(&f); + + DetectEngineCtx *de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) { + goto end; + } + de_ctx->mpm_matcher = MPM_B2G; + de_ctx->flags |= DE_QUIET; + + s = de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " + "(msg:\"Test pcre /U, uricontent and urilen option\"; " + "uricontent:one; " + "pcre:/(one)+self/U; urilen:>2; sid:1;)"); + if (s == NULL) { + goto end; + } + + SigGroupBuild(de_ctx); + DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx); + + int r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER, http_buf1, http_buf1_len); + if (r != 0) { + printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); + goto end; + } + + http_state = f.aldata[AlpGetStateIdx(ALPROTO_HTTP)]; + if (http_state == NULL) { + printf("no http state: "); + goto end; + } + + /* do detect */ + SigMatchSignatures(&tv, de_ctx, det_ctx, &p); + + if (PacketAlertCheck(&p, 1)) { + printf("sig 1 alerted, but it should not: "); + goto end; + } + + DetectEngineStateReset(f.de_state); + + r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER, http_buf2, http_buf2_len); + if (r != 0) { + printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); + goto end; + } + + http_state = f.aldata[AlpGetStateIdx(ALPROTO_HTTP)]; + if (http_state == NULL) { + printf("no http state: "); + goto end; + } + + /* do detect */ + SigMatchSignatures(&tv, de_ctx, det_ctx, &p); + + if (!PacketAlertCheck(&p, 1)) { + printf("sig 1 didnt alert with payload2, but it should: "); + goto end; + } + + result = 1; + +end: + if (det_ctx != NULL) + DetectEngineThreadCtxDeinit(&tv, det_ctx); + if (de_ctx != NULL) + SigGroupCleanup(de_ctx); + if (de_ctx != NULL) + DetectEngineCtxFree(de_ctx); + + StreamTcpFreeConfig(TRUE); + FLOW_DESTROY(&f); + return result; +} + +/** \test Test uricontent, urilen */ +static int UriTestSig13(void) +{ + int result = 0; + Flow f; + HtpState *http_state = NULL; + uint8_t http_buf1[] = "POST /one HTTP/1.0\r\n" + "User-Agent: Mozilla/1.0\r\n" + "Cookie: hellocatch\r\n\r\n"; + uint32_t http_buf1_len = sizeof(http_buf1) - 1; + uint8_t http_buf2[] = "POST /oneself HTTP/1.0\r\n" + "User-Agent: Mozilla/1.0\r\n" + "Cookie: hellocatch\r\n\r\n"; + uint32_t http_buf2_len = sizeof(http_buf2) - 1; + TcpSession ssn; + Packet p; + Signature *s = NULL; + ThreadVars tv; + DetectEngineThreadCtx *det_ctx = NULL; + + memset(&tv, 0, sizeof(ThreadVars)); + memset(&p, 0, sizeof(Packet)); + memset(&f, 0, sizeof(Flow)); + memset(&ssn, 0, sizeof(TcpSession)); + + p.src.family = AF_INET; + p.dst.family = AF_INET; + p.payload = http_buf1; + p.payload_len = http_buf1_len; + p.proto = IPPROTO_TCP; + + FLOW_INITIALIZE(&f); + f.protoctx = (void *)&ssn; + f.src.family = AF_INET; + f.dst.family = AF_INET; + + p.flow = &f; + p.flowflags |= FLOW_PKT_TOSERVER; + p.flowflags |= FLOW_PKT_ESTABLISHED; + f.alproto = ALPROTO_HTTP; + + StreamTcpInitConfig(TRUE); + FlowL7DataPtrInit(&f); + + DetectEngineCtx *de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) { + goto end; + } + de_ctx->mpm_matcher = MPM_B2G; + de_ctx->flags |= DE_QUIET; + + s = de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " + "(msg:\"Test urilen option\"; " + "urilen:>2; uricontent:one; sid:1;)"); + if (s == NULL) { + goto end; + } + + SigGroupBuild(de_ctx); + DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx); + + int r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER, http_buf1, http_buf1_len); + if (r != 0) { + printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); + goto end; + } + + http_state = f.aldata[AlpGetStateIdx(ALPROTO_HTTP)]; + if (http_state == NULL) { + printf("no http state: "); + goto end; + } + + /* do detect */ + SigMatchSignatures(&tv, de_ctx, det_ctx, &p); + + if (!PacketAlertCheck(&p, 1)) { + printf("sig 1 didnt alert with pkt, but it should: "); + goto end; + } + + DetectEngineStateReset(f.de_state); + + r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER, http_buf2, http_buf2_len); + if (r != 0) { + printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); + goto end; + } + + http_state = f.aldata[AlpGetStateIdx(ALPROTO_HTTP)]; + if (http_state == NULL) { + printf("no http state: "); + goto end; + } + + /* do detect */ + SigMatchSignatures(&tv, de_ctx, det_ctx, &p); + + + if (!PacketAlertCheck(&p, 1)) { + printf("sig 1 didnt alert with payload2, but it should: "); + goto end; + } + + result = 1; + +end: + if (det_ctx != NULL) + DetectEngineThreadCtxDeinit(&tv, det_ctx); + if (de_ctx != NULL) + SigGroupCleanup(de_ctx); + if (de_ctx != NULL) + DetectEngineCtxFree(de_ctx); + + StreamTcpFreeConfig(TRUE); + FLOW_DESTROY(&f); + return result; +} + +/** \test Test uricontent, pcre /U */ +static int UriTestSig14(void) +{ + int result = 0; + Flow f; + HtpState *http_state = NULL; + uint8_t http_buf1[] = "POST /one HTTP/1.0\r\n" + "User-Agent: Mozilla/1.0\r\n" + "Cookie: hellocatch\r\n\r\n"; + uint32_t http_buf1_len = sizeof(http_buf1) - 1; + uint8_t http_buf2[] = "POST /oneself HTTP/1.0\r\n" + "User-Agent: Mozilla/1.0\r\n" + "Cookie: hellocatch\r\n\r\n"; + uint32_t http_buf2_len = sizeof(http_buf2) - 1; + TcpSession ssn; + Packet p; + Signature *s = NULL; + ThreadVars tv; + DetectEngineThreadCtx *det_ctx = NULL; + + memset(&tv, 0, sizeof(ThreadVars)); + memset(&p, 0, sizeof(Packet)); + memset(&f, 0, sizeof(Flow)); + memset(&ssn, 0, sizeof(TcpSession)); + + p.src.family = AF_INET; + p.dst.family = AF_INET; + p.payload = http_buf1; + p.payload_len = http_buf1_len; + p.proto = IPPROTO_TCP; + + FLOW_INITIALIZE(&f); + f.protoctx = (void *)&ssn; + f.src.family = AF_INET; + f.dst.family = AF_INET; + + p.flow = &f; + p.flowflags |= FLOW_PKT_TOSERVER; + p.flowflags |= FLOW_PKT_ESTABLISHED; + f.alproto = ALPROTO_HTTP; + + StreamTcpInitConfig(TRUE); + FlowL7DataPtrInit(&f); + + DetectEngineCtx *de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) { + goto end; + } + de_ctx->mpm_matcher = MPM_B2G; + de_ctx->flags |= DE_QUIET; + + s = de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " + "(msg:\"Test uricontent option\"; " + "uricontent:one; pcre:/one(self)?/U;sid:1;)"); + if (s == NULL) { + goto end; + } + + SigGroupBuild(de_ctx); + DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx); + + int r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER, http_buf1, http_buf1_len); + if (r != 0) { + printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); + goto end; + } + + http_state = f.aldata[AlpGetStateIdx(ALPROTO_HTTP)]; + if (http_state == NULL) { + printf("no http state: "); + goto end; + } + + /* do detect */ + SigMatchSignatures(&tv, de_ctx, det_ctx, &p); + + if (!PacketAlertCheck(&p, 1)) { + printf("sig 1 didnt alert with pkt, but it should: "); + goto end; + } + + DetectEngineStateReset(f.de_state); + + r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER, http_buf2, http_buf2_len); + if (r != 0) { + printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); + goto end; + } + + http_state = f.aldata[AlpGetStateIdx(ALPROTO_HTTP)]; + if (http_state == NULL) { + printf("no http state: "); + goto end; + } + + /* do detect */ + SigMatchSignatures(&tv, de_ctx, det_ctx, &p); + + + if (!PacketAlertCheck(&p, 1)) { + printf("sig 1 didnt alert with payload2, but it should: "); + goto end; + } + result = 1; end: @@ -495,6 +2070,19 @@ void UriRegisterTests(void) #ifdef UNITTESTS UtRegisterTest("UriTestSig01", UriTestSig01, 1); + UtRegisterTest("UriTestSig02", UriTestSig02, 1); + UtRegisterTest("UriTestSig03", UriTestSig03, 1); + UtRegisterTest("UriTestSig04", UriTestSig04, 1); + UtRegisterTest("UriTestSig05", UriTestSig05, 1); + UtRegisterTest("UriTestSig06", UriTestSig06, 1); + UtRegisterTest("UriTestSig07", UriTestSig07, 1); + UtRegisterTest("UriTestSig08", UriTestSig08, 1); + UtRegisterTest("UriTestSig09", UriTestSig09, 1); + UtRegisterTest("UriTestSig10", UriTestSig10, 1); + UtRegisterTest("UriTestSig11", UriTestSig11, 1); + UtRegisterTest("UriTestSig12", UriTestSig12, 1); + UtRegisterTest("UriTestSig13", UriTestSig13, 1); + UtRegisterTest("UriTestSig14", UriTestSig14, 1); #endif /* UNITTESTS */ return; diff --git a/src/detect-urilen.c b/src/detect-urilen.c index 2b0763c759..0cbdce55b5 100644 --- a/src/detect-urilen.c +++ b/src/detect-urilen.c @@ -62,7 +62,7 @@ void DetectUrilenRegister(void) sigmatch_table[DETECT_AL_URILEN].name = "urilen"; sigmatch_table[DETECT_AL_URILEN].Match = NULL; sigmatch_table[DETECT_AL_URILEN].alproto = ALPROTO_HTTP; - sigmatch_table[DETECT_AL_URILEN].AppLayerMatch = DetectUrilenMatch; + sigmatch_table[DETECT_AL_URILEN].AppLayerMatch = NULL /**< We handle this at detect-engine-uri.c now */; sigmatch_table[DETECT_AL_URILEN].Setup = DetectUrilenSetup; sigmatch_table[DETECT_AL_URILEN].Free = DetectUrilenFree; sigmatch_table[DETECT_AL_URILEN].RegisterTests = DetectUrilenRegisterTests; @@ -301,7 +301,7 @@ static int DetectUrilenSetup (DetectEngineCtx *de_ctx, Signature *s, char *urile sm->type = DETECT_AL_URILEN; sm->ctx = (void *)urilend; - SigMatchAppendAppLayer(s, sm); + SigMatchAppendUricontent(s,sm); /* Flagged the signature as to inspect the app layer data */ s->flags |= SIG_FLAG_APPLAYER; diff --git a/src/detect-urilen.h b/src/detect-urilen.h index d176968c08..b83892f376 100644 --- a/src/detect-urilen.h +++ b/src/detect-urilen.h @@ -35,6 +35,8 @@ typedef struct DetectUrilenData_ { uint8_t mode; /**< operator used in the signature */ }DetectUrilenData; +int DetectUrilenMatch (ThreadVars *, DetectEngineThreadCtx *, Flow *, + uint8_t, void *, Signature *, SigMatch *); void DetectUrilenRegister(void); #endif /* _DETECT_URILEN_H */