diff --git a/src/detect-engine-hrhd.c b/src/detect-engine-hrhd.c index e8161d9336..c0b9cd478d 100644 --- a/src/detect-engine-hrhd.c +++ b/src/detect-engine-hrhd.c @@ -308,7 +308,8 @@ match: } } -int DetectEngineRunHttpRawHeaderMpm(DetectEngineThreadCtx *det_ctx, Flow *f, HtpState *htp_state) +int DetectEngineRunHttpRawHeaderMpm(DetectEngineThreadCtx *det_ctx, Flow *f, + HtpState *htp_state, uint8_t flags) { htp_tx_t *tx = NULL; uint32_t cnt = 0; @@ -340,12 +341,17 @@ int DetectEngineRunHttpRawHeaderMpm(DetectEngineThreadCtx *det_ctx, Flow *f, Htp continue; bstr *raw_headers = htp_tx_get_request_headers_raw(tx); - if (raw_headers == NULL) - continue; - - cnt += HttpRawHeaderPatternSearch(det_ctx, - (uint8_t *)bstr_ptr(raw_headers), - bstr_len(raw_headers)); + if (raw_headers != NULL) { + cnt += HttpRawHeaderPatternSearch(det_ctx, + (uint8_t *)bstr_ptr(raw_headers), + bstr_len(raw_headers)); + } + raw_headers = htp_tx_get_response_headers_raw(tx); + if (raw_headers != NULL) { + cnt += HttpRawHeaderPatternSearch(det_ctx, + (uint8_t *)bstr_ptr(raw_headers), + bstr_len(raw_headers)); + } } end: @@ -401,7 +407,12 @@ int DetectEngineInspectHttpRawHeader(DetectEngineCtx *de_ctx, if (tx == NULL) continue; - bstr *raw_headers = htp_tx_get_request_headers_raw(tx); + bstr *raw_headers; + if (flags & STREAM_TOSERVER) { + raw_headers = htp_tx_get_request_headers_raw(tx); + } else { + raw_headers = htp_tx_get_response_headers_raw(tx); + } if (raw_headers == NULL) continue; @@ -2995,6 +3006,276 @@ end: return result; } +static int DetectEngineHttpRawHeaderTest28(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 http_buf1[] = + "GET /index.html HTTP/1.0\r\n" + "Host: www.openinfosecfoundation.org\r\n" + "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n" + "\r\n"; + uint32_t http_buf1_len = sizeof(http_buf1) - 1; + uint8_t http_buf2[] = + "HTTP/1.0 200 ok\r\n" + "Content-Type: text/html\r\n" + "Content-Length: 6\r\n" + "\r\n" + "abcdef"; + uint32_t http_buf2_len = sizeof(http_buf2) - 1; + int result = 0; + + 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); + + FLOW_INITIALIZE(&f); + f.protoctx = (void *)&ssn; + f.flags |= FLOW_IPV4; + + p1->flow = &f; + p1->flowflags |= FLOW_PKT_TOSERVER; + p1->flowflags |= FLOW_PKT_ESTABLISHED; + p1->flags |= PKT_HAS_FLOW | PKT_STREAM_EST; + p2->flow = &f; + p2->flowflags |= FLOW_PKT_TOCLIENT; + p2->flowflags |= FLOW_PKT_ESTABLISHED; + p2->flags |= PKT_HAS_FLOW | PKT_STREAM_EST; + f.alproto = ALPROTO_HTTP; + + StreamTcpInitConfig(TRUE); + + de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + + de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any " + "(msg:\"http header test\"; " + "content:\"Content-Length: 6\"; http_raw_header; " + "sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + + SigGroupBuild(de_ctx); + DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx); + + int r = AppLayerParse(NULL, &f, ALPROTO_HTTP, STREAM_TOSERVER, http_buf1, + http_buf1_len); + if (r != 0) { + printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); + result = 0; + goto end; + } + + http_state = f.alstate; + if (http_state == NULL) { + printf("no http state: \n"); + result = 0; + goto end; + } + + /* do detect */ + SigMatchSignatures(&th_v, de_ctx, det_ctx, p1); + + if (PacketAlertCheck(p1, 1)) { + printf("sid 1 matched but shouldn't have\n"); + goto end; + } + + r = AppLayerParse(NULL, &f, ALPROTO_HTTP, STREAM_TOCLIENT, http_buf2, http_buf2_len); + if (r != 0) { + printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r); + result = 0; + goto end; + } + + /* do detect */ + SigMatchSignatures(&th_v, de_ctx, det_ctx, p2); + + if (!PacketAlertCheck(p2, 1)) { + printf("sid 1 didn't match but should have"); + goto end; + } + + result = 1; + +end: + if (de_ctx != NULL) + SigGroupCleanup(de_ctx); + if (de_ctx != NULL) + SigCleanSignatures(de_ctx); + if (de_ctx != NULL) + DetectEngineCtxFree(de_ctx); + + StreamTcpFreeConfig(TRUE); + FLOW_DESTROY(&f); + UTHFreePackets(&p1, 1); + UTHFreePackets(&p2, 1); + return result; +} + +static int DetectEngineHttpRawHeaderTest29(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 http_buf1[] = + "GET /index.html HTTP/1.0\r\n" + "Host: www.openinfosecfoundation.org\r\n" + "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n" + "\r\n"; + uint32_t http_buf1_len = sizeof(http_buf1) - 1; + uint8_t http_buf2[] = + "HTTP/1.0 200 ok\r\n" + "Content-Type: text/html\r\n" + "Content-Length: 6\r\n" + "\r\n" + "abcdef"; + uint32_t http_buf2_len = sizeof(http_buf2) - 1; + int result = 0; + + 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); + + FLOW_INITIALIZE(&f); + f.protoctx = (void *)&ssn; + f.flags |= FLOW_IPV4; + + p1->flow = &f; + p1->flowflags |= FLOW_PKT_TOSERVER; + p1->flowflags |= FLOW_PKT_ESTABLISHED; + p1->flags |= PKT_HAS_FLOW | PKT_STREAM_EST; + p2->flow = &f; + p2->flowflags |= FLOW_PKT_TOCLIENT; + p2->flowflags |= FLOW_PKT_ESTABLISHED; + p2->flags |= PKT_HAS_FLOW | PKT_STREAM_EST; + f.alproto = ALPROTO_HTTP; + + StreamTcpInitConfig(TRUE); + + de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + + de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any " + "(msg:\"http header test\"; " + "content:\"Content-Length: 7\"; http_raw_header; " + "sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + + SigGroupBuild(de_ctx); + DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx); + + int r = AppLayerParse(NULL, &f, ALPROTO_HTTP, STREAM_TOSERVER, http_buf1, + http_buf1_len); + if (r != 0) { + printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); + result = 0; + goto end; + } + + http_state = f.alstate; + if (http_state == NULL) { + printf("no http state: \n"); + result = 0; + goto end; + } + + /* do detect */ + SigMatchSignatures(&th_v, de_ctx, det_ctx, p1); + + if (PacketAlertCheck(p1, 1)) { + printf("sid 1 matched but shouldn't have\n"); + goto end; + } + + r = AppLayerParse(NULL, &f, ALPROTO_HTTP, STREAM_TOCLIENT, http_buf2, http_buf2_len); + if (r != 0) { + printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r); + result = 0; + goto end; + } + + /* do detect */ + SigMatchSignatures(&th_v, de_ctx, det_ctx, p2); + + if (PacketAlertCheck(p2, 1)) { + printf("sid 1 matched but shouldn't have"); + goto end; + } + + result = 1; + +end: + if (de_ctx != NULL) + SigGroupCleanup(de_ctx); + if (de_ctx != NULL) + SigCleanSignatures(de_ctx); + if (de_ctx != NULL) + DetectEngineCtxFree(de_ctx); + + StreamTcpFreeConfig(TRUE); + FLOW_DESTROY(&f); + UTHFreePackets(&p1, 1); + UTHFreePackets(&p2, 1); + return result; +} + +#if 0 + +static int DetectEngineHttpRawHeaderTest30(void) +{ + int result = 0; + DetectEngineCtx *de_ctx = DetectEngineCtxInit(); + + if (de_ctx == NULL) { + goto end; + } + + de_ctx->sig_list = SigInit(de_ctx, "alert http any any -> any any " + "(msg:\"http header test\"; " + "content:\"Content-Length: 6\"; http_raw_header; " + "content:\"User-Agent: Mozilla\"; http_raw_header; " + "sid:1;)"); + if (de_ctx->sig_list != NULL) { + goto end; + } + + result = 1; + + end: + if (de_ctx != NULL) + SigCleanSignatures(de_ctx); + if (de_ctx != NULL) + DetectEngineCtxFree(de_ctx); + return result; +} + +#endif /* #if 0 */ + #endif /* UNITTESTS */ void DetectEngineHttpRawHeaderRegisterTests(void) @@ -3055,6 +3336,14 @@ void DetectEngineHttpRawHeaderRegisterTests(void) DetectEngineHttpRawHeaderTest26, 1); UtRegisterTest("DetectEngineHttpRawHeaderTest27", DetectEngineHttpRawHeaderTest27, 1); + UtRegisterTest("DetectEngineHttpRawHeaderTest28", + DetectEngineHttpRawHeaderTest28, 1); + UtRegisterTest("DetectEngineHttpRawHeaderTest29", + DetectEngineHttpRawHeaderTest29, 1); +#if 0 + UtRegisterTest("DetectEngineHttpRawHeaderTest30", + DetectEngineHttpRawHeaderTest30, 1); +#endif #endif /* UNITTESTS */ return; diff --git a/src/detect-engine-hrhd.h b/src/detect-engine-hrhd.h index 0d723720ae..5a92bb535a 100644 --- a/src/detect-engine-hrhd.h +++ b/src/detect-engine-hrhd.h @@ -26,7 +26,8 @@ #include "app-layer-htp.h" int DetectEngineInspectHttpRawHeader(DetectEngineCtx *, DetectEngineThreadCtx *, Signature *, Flow *, uint8_t, void *); -int DetectEngineRunHttpRawHeaderMpm(DetectEngineThreadCtx *, Flow *, HtpState *); +int DetectEngineRunHttpRawHeaderMpm(DetectEngineThreadCtx *, Flow *, HtpState *, + uint8_t); void DetectEngineHttpRawHeaderRegisterTests(void); #endif /* __DETECT_ENGINE_HHD_H__ */ diff --git a/src/detect.c b/src/detect.c index bfcb174e7f..aaa9d11daf 100644 --- a/src/detect.c +++ b/src/detect.c @@ -1167,7 +1167,7 @@ static inline void DetectMpmPrefilter(DetectEngineCtx *de_ctx, } if (det_ctx->sgh->flags & SIG_GROUP_HEAD_MPM_HRHD) { PACKET_PROFILING_DETECT_START(p, PROF_DETECT_MPM_HRHD); - DetectEngineRunHttpRawHeaderMpm(det_ctx, p->flow, alstate); + DetectEngineRunHttpRawHeaderMpm(det_ctx, p->flow, alstate, flags); PACKET_PROFILING_DETECT_END(p, PROF_DETECT_MPM_HRHD); } if (det_ctx->sgh->flags & SIG_GROUP_HEAD_MPM_HMD) {