From: Anoop Saldanha Date: Sat, 2 Feb 2013 03:01:28 +0000 (+0530) Subject: Add support for the new keyword - http_raw_host header. X-Git-Tag: suricata-1.4.1~43 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=3511f91bba561d0620b9082ab7dd3c4294400925;p=thirdparty%2Fsuricata.git Add support for the new keyword - http_raw_host header. The corresponding pcre modifier would be 'Z'. --- diff --git a/src/Makefile.am b/src/Makefile.am index 77dd6d15e3..719adba5b2 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -87,6 +87,7 @@ detect-engine-hcd.c detect-engine-hcd.h \ detect-engine-hhd.c detect-engine-hhd.h \ detect-engine-hmd.c detect-engine-hmd.h \ detect-engine-hrhd.c detect-engine-hrhd.h \ +detect-engine-hrhhd.c detect-engine-hrhhd.h \ detect-engine-hrud.c detect-engine-hrud.h \ detect-engine-hsbd.c detect-engine-hsbd.h \ detect-engine-hscd.c detect-engine-hscd.h \ @@ -126,6 +127,7 @@ detect-http-client-body.c detect-http-client-body.h \ detect-http-cookie.c detect-http-cookie.h \ detect-http-header.c detect-http-header.h \ detect-http-hh.c detect-http-hh.h \ +detect-http-hrh.c detect-http-hrh.h \ detect-http-method.c detect-http-method.h \ detect-http-raw-header.c detect-http-raw-header.h \ detect-http-raw-uri.c detect-http-raw-uri.h \ diff --git a/src/detect-depth.c b/src/detect-depth.c index 619b75aeda..89cbdc8835 100644 --- a/src/detect-depth.c +++ b/src/detect-depth.c @@ -87,7 +87,7 @@ static int DetectDepthSetup (DetectEngineCtx *de_ctx, Signature *s, char *depths break; default: - pm = SigMatchGetLastSMFromLists(s, 26, + pm = SigMatchGetLastSMFromLists(s, 28, DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_PMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_UMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HRUDMATCH], @@ -100,14 +100,15 @@ static int DetectDepthSetup (DetectEngineCtx *de_ctx, Signature *s, char *depths DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HSCDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HSMDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HUADMATCH], - DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HHHDMATCH]); + DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HHHDMATCH], + DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH]); if (pm == NULL) { SCLogError(SC_ERR_DEPTH_MISSING_CONTENT, "depth needs " "preceding content, uricontent option, http_client_body, " "http_server_body, http_header option, http_raw_header option, " "http_method option, http_cookie, http_raw_uri, " - "http_stat_msg, http_stat_code, http_user_agent or " - "http_host option"); + "http_stat_msg, http_stat_code, http_user_agent, " + "http_host or http_raw_host option"); if (dubbed) SCFree(str); return -1; diff --git a/src/detect-distance.c b/src/detect-distance.c index 6e919e256e..ddb01e393b 100644 --- a/src/detect-distance.c +++ b/src/detect-distance.c @@ -162,7 +162,7 @@ static int DetectDistanceSetup (DetectEngineCtx *de_ctx, Signature *s, } } } else { - pm = SigMatchGetLastSMFromLists(s, 26, + pm = SigMatchGetLastSMFromLists(s, 28, DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_PMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_UMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HRUDMATCH], @@ -175,13 +175,14 @@ static int DetectDistanceSetup (DetectEngineCtx *de_ctx, Signature *s, DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HSCDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HSMDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HUADMATCH], - DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HHHDMATCH]); + DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HHHDMATCH], + DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH]); if (pm == NULL) { SCLogError(SC_ERR_WITHIN_MISSING_CONTENT, "within needs " "preceding content, uricontent option, http_client_body, " "http_server_body, http_header, http_raw_header, http_method, " "http_cookie, http_raw_uri, http_stat_msg, http_stat_code, " - "http_user_agent or http_host option"); + "http_user_agent, http_host or http_raw_host option"); if (dubbed) SCFree(str); return -1; diff --git a/src/detect-engine-content-inspection.h b/src/detect-engine-content-inspection.h index cd0b0893ea..19f0126778 100644 --- a/src/detect-engine-content-inspection.h +++ b/src/detect-engine-content-inspection.h @@ -40,6 +40,7 @@ enum { DETECT_ENGINE_CONTENT_INSPECTION_MODE_HSMD, DETECT_ENGINE_CONTENT_INSPECTION_MODE_HUAD, DETECT_ENGINE_CONTENT_INSPECTION_MODE_HHHD, + DETECT_ENGINE_CONTENT_INSPECTION_MODE_HRHHD, }; int DetectEngineContentInspection(DetectEngineCtx *, diff --git a/src/detect-engine-hrhhd.c b/src/detect-engine-hrhhd.c new file mode 100644 index 0000000000..e4e85c65d1 --- /dev/null +++ b/src/detect-engine-hrhhd.c @@ -0,0 +1,1780 @@ +/* Copyright (C) 2007-2013 Open Information Security Foundation + * + * You can copy, redistribute or modify this Program under the terms of + * the GNU General Public License version 2 as published by the Free + * Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +/** + * \ingroup httplayer + * + * @{ + */ + + +/** \file + * + * \author Anoop Saldanha + * + * \brief Handle HTTP host header. + * HRHHD - Http Raw Host Header Data + * + */ + +#include "suricata-common.h" +#include "suricata.h" +#include "decode.h" + +#include "detect.h" +#include "detect-engine.h" +#include "detect-engine-mpm.h" +#include "detect-parse.h" +#include "detect-engine-state.h" +#include "detect-engine-content-inspection.h" + +#include "flow-util.h" +#include "util-debug.h" +#include "util-print.h" +#include "flow.h" + +#include "app-layer-parser.h" + +#include "util-unittest.h" +#include "util-unittest-helper.h" +#include "app-layer.h" +#include "app-layer-htp.h" +#include "app-layer-protos.h" + +#include "detect-engine-hrhhd.h" + +int DetectEngineRunHttpHRHMpm(DetectEngineThreadCtx *det_ctx, Flow *f, + HtpState *htp_state, uint8_t flags) +{ + htp_tx_t *tx = NULL; + uint32_t cnt = 0; + int idx; + + /* we need to lock because the buffers are not actually true buffers + * but are ones that point to a buffer given by libhtp */ + FLOWLOCK_RDLOCK(f); + + if (htp_state == NULL) { + SCLogDebug("no HTTP state"); + goto end; + } + + if (htp_state->connp == NULL || htp_state->connp->conn == NULL) { + SCLogDebug("HTP state has no conn(p)"); + goto end; + } + + idx = AppLayerTransactionGetInspectId(f); + if (idx == -1) { + goto end; + } + + int size = (int)list_size(htp_state->connp->conn->transactions); + for (; idx < size; idx++) { + + uint8_t *hname; + uint32_t hname_len; + + tx = list_get(htp_state->connp->conn->transactions, idx); + if (tx == NULL) + continue; + + if (tx->parsed_uri_incomplete == NULL || tx->parsed_uri_incomplete->hostname == NULL) { + htp_header_t *h = NULL; + h = (htp_header_t *)table_getc(tx->request_headers, "Host"); + if (h == NULL) { + SCLogDebug("HTTP host header not present in this request"); + continue; + } + hname = (uint8_t *)bstr_ptr(h->value); + hname_len = bstr_len(h->value); + } else { + hname = (uint8_t *)bstr_ptr(tx->parsed_uri_incomplete->hostname); + if (hname == NULL) + continue; + hname_len = bstr_len(tx->parsed_uri_incomplete->hostname); + } + + cnt += HttpHRHPatternSearch(det_ctx, hname, hname_len, flags); + } + + end: + FLOWLOCK_UNLOCK(f); + return cnt; +} + +/** + * \brief Do the http_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 DetectEngineInspectHttpHRH(ThreadVars *tv, + DetectEngineCtx *de_ctx, + DetectEngineThreadCtx *det_ctx, + Signature *s, Flow *f, uint8_t flags, + void *alstate, int tx_id) +{ + HtpState *htp_state = (HtpState *)alstate; + htp_tx_t *tx = list_get(htp_state->connp->conn->transactions, tx_id); + uint8_t *hname; + uint32_t hname_len; + + if (tx == NULL) + return 0; + if (tx->parsed_uri_incomplete == NULL || tx->parsed_uri_incomplete->hostname == NULL) { + htp_header_t *h = NULL; + h = (htp_header_t *)table_getc(tx->request_headers, "Host"); + if (h == NULL) { + SCLogDebug("HTTP host header not present in this request"); + return 0; + } + hname = (uint8_t *)bstr_ptr(h->value); + hname_len = bstr_len(h->value); + } else { + hname = (uint8_t *)bstr_ptr(tx->parsed_uri_incomplete->hostname); + if (hname == NULL) + return 0; + hname_len = bstr_len(tx->parsed_uri_incomplete->hostname); + } + + det_ctx->buffer_offset = 0; + det_ctx->discontinue_matching = 0; + det_ctx->inspection_recursion_counter = 0; + int r = DetectEngineContentInspection(de_ctx, det_ctx, s, s->sm_lists[DETECT_SM_LIST_HRHHDMATCH], + f, + hname, hname_len, + DETECT_ENGINE_CONTENT_INSPECTION_MODE_HRHHD, NULL); + if (r == 1) + return 1; + + return 0; +} + +/***********************************Unittests**********************************/ + +#ifdef UNITTESTS + +/** + * \test Test that the http_raw_host content matches against a http request + * which holds the content. + */ +static int DetectEngineHttpHRHTest01(void) +{ + TcpSession ssn; + Packet *p = NULL; + ThreadVars th_v; + DetectEngineCtx *de_ctx = NULL; + DetectEngineThreadCtx *det_ctx = NULL; + HtpState *http_state = NULL; + Flow f; + uint8_t http_buf[] = + "GET /index.html HTTP/1.0\r\n" + "Host: CONNECT\r\n" + "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n"; + uint32_t http_len = sizeof(http_buf) - 1; + int result = 0; + + memset(&th_v, 0, sizeof(th_v)); + memset(&f, 0, sizeof(f)); + memset(&ssn, 0, sizeof(ssn)); + + p = UTHBuildPacket(NULL, 0, IPPROTO_TCP); + + FLOW_INITIALIZE(&f); + f.protoctx = (void *)&ssn; + f.flags |= FLOW_IPV4; + p->flow = &f; + p->flowflags |= FLOW_PKT_TOSERVER; + p->flowflags |= FLOW_PKT_ESTABLISHED; + p->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 host header test\"; " + "content:\"CONNECT\"; http_raw_host; " + "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_buf, http_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: "); + result = 0; + goto end; + } + + /* do detect */ + SigMatchSignatures(&th_v, de_ctx, det_ctx, p); + + if (!(PacketAlertCheck(p, 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(&p, 1); + return result; +} + +/** + * \test Test that the http_raw_host content matches against a http request + * which holds the content. + */ +static int DetectEngineHttpHRHTest02(void) +{ + TcpSession ssn; + Packet *p = NULL; + ThreadVars th_v; + DetectEngineCtx *de_ctx = NULL; + DetectEngineThreadCtx *det_ctx = NULL; + HtpState *http_state = NULL; + Flow f; + uint8_t http_buf[] = + "GET /index.html HTTP/1.0\r\n" + "Host: CONNECT\r\n" + "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n"; + uint32_t http_len = sizeof(http_buf) - 1; + int result = 0; + + memset(&th_v, 0, sizeof(th_v)); + memset(&f, 0, sizeof(f)); + memset(&ssn, 0, sizeof(ssn)); + + p = UTHBuildPacket(NULL, 0, IPPROTO_TCP); + + FLOW_INITIALIZE(&f); + f.protoctx = (void *)&ssn; + f.flags |= FLOW_IPV4; + p->flow = &f; + p->flowflags |= FLOW_PKT_TOSERVER; + p->flowflags |= FLOW_PKT_ESTABLISHED; + p->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 host header test\"; " + "content:\"CO\"; depth:4; http_raw_host; " + "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_buf, http_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: "); + result = 0; + goto end; + } + + /* do detect */ + SigMatchSignatures(&th_v, de_ctx, det_ctx, p); + + if (!(PacketAlertCheck(p, 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(&p, 1); + return result; +} + +/** + * \test Test that the http_raw_host content matches against a http request + * which holds the content. + */ +static int DetectEngineHttpHRHTest03(void) +{ + TcpSession ssn; + Packet *p = NULL; + ThreadVars th_v; + DetectEngineCtx *de_ctx = NULL; + DetectEngineThreadCtx *det_ctx = NULL; + HtpState *http_state = NULL; + Flow f; + uint8_t http_buf[] = + "GET /index.html HTTP/1.0\r\n" + "Host: CONNECT\r\n" + "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n"; + uint32_t http_len = sizeof(http_buf) - 1; + int result = 0; + + memset(&th_v, 0, sizeof(th_v)); + memset(&f, 0, sizeof(f)); + memset(&ssn, 0, sizeof(ssn)); + + p = UTHBuildPacket(NULL, 0, IPPROTO_TCP); + + FLOW_INITIALIZE(&f); + f.protoctx = (void *)&ssn; + f.flags |= FLOW_IPV4; + p->flow = &f; + p->flowflags |= FLOW_PKT_TOSERVER; + p->flowflags |= FLOW_PKT_ESTABLISHED; + p->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_raw_host header test\"; " + "content:!\"ECT\"; depth:4; http_raw_host; " + "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_buf, http_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: "); + result = 0; + goto end; + } + + /* do detect */ + SigMatchSignatures(&th_v, de_ctx, det_ctx, p); + + if (!(PacketAlertCheck(p, 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(&p, 1); + return result; +} + +/** + * \test Test that the http_raw_host content matches against a http request + * which holds the content. + */ +static int DetectEngineHttpHRHTest04(void) +{ + TcpSession ssn; + Packet *p = NULL; + ThreadVars th_v; + DetectEngineCtx *de_ctx = NULL; + DetectEngineThreadCtx *det_ctx = NULL; + HtpState *http_state = NULL; + Flow f; + uint8_t http_buf[] = + "GET /index.html HTTP/1.0\r\n" + "Host: CONNECT\r\n" + "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n"; + uint32_t http_len = sizeof(http_buf) - 1; + int result = 0; + + memset(&th_v, 0, sizeof(th_v)); + memset(&f, 0, sizeof(f)); + memset(&ssn, 0, sizeof(ssn)); + + p = UTHBuildPacket(NULL, 0, IPPROTO_TCP); + + FLOW_INITIALIZE(&f); + f.protoctx = (void *)&ssn; + f.flags |= FLOW_IPV4; + p->flow = &f; + p->flowflags |= FLOW_PKT_TOSERVER; + p->flowflags |= FLOW_PKT_ESTABLISHED; + p->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 host header test\"; " + "content:\"ECT\"; depth:4; http_raw_host; " + "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_buf, http_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: "); + result = 0; + goto end; + } + + /* do detect */ + SigMatchSignatures(&th_v, de_ctx, det_ctx, p); + + if (PacketAlertCheck(p, 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(&p, 1); + return result; +} + +/** + * \test Test that the http_raw_host content matches against a http request + * which holds the content. + */ +static int DetectEngineHttpHRHTest05(void) +{ + TcpSession ssn; + Packet *p = NULL; + ThreadVars th_v; + DetectEngineCtx *de_ctx = NULL; + DetectEngineThreadCtx *det_ctx = NULL; + HtpState *http_state = NULL; + Flow f; + uint8_t http_buf[] = + "GET /index.html HTTP/1.0\r\n" + "Host: CONNECT\r\n" + "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n"; + uint32_t http_len = sizeof(http_buf) - 1; + int result = 0; + + memset(&th_v, 0, sizeof(th_v)); + memset(&f, 0, sizeof(f)); + memset(&ssn, 0, sizeof(ssn)); + + p = UTHBuildPacket(NULL, 0, IPPROTO_TCP); + + FLOW_INITIALIZE(&f); + f.protoctx = (void *)&ssn; + f.flags |= FLOW_IPV4; + p->flow = &f; + p->flowflags |= FLOW_PKT_TOSERVER; + p->flowflags |= FLOW_PKT_ESTABLISHED; + p->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 host header test\"; " + "content:!\"CON\"; depth:4; http_raw_host; " + "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_buf, http_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: "); + result = 0; + goto end; + } + + /* do detect */ + SigMatchSignatures(&th_v, de_ctx, det_ctx, p); + + if (PacketAlertCheck(p, 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(&p, 1); + return result; +} + +/** + * \test Test that the http_raw_host header content matches against a http request + * which holds the content. + */ +static int DetectEngineHttpHRHTest06(void) +{ + TcpSession ssn; + Packet *p = NULL; + ThreadVars th_v; + DetectEngineCtx *de_ctx = NULL; + DetectEngineThreadCtx *det_ctx = NULL; + HtpState *http_state = NULL; + Flow f; + uint8_t http_buf[] = + "GET /index.html HTTP/1.0\r\n" + "Host: CONNECT\r\n" + "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n"; + uint32_t http_len = sizeof(http_buf) - 1; + int result = 0; + + memset(&th_v, 0, sizeof(th_v)); + memset(&f, 0, sizeof(f)); + memset(&ssn, 0, sizeof(ssn)); + + p = UTHBuildPacket(NULL, 0, IPPROTO_TCP); + + FLOW_INITIALIZE(&f); + f.protoctx = (void *)&ssn; + f.flags |= FLOW_IPV4; + p->flow = &f; + p->flowflags |= FLOW_PKT_TOSERVER; + p->flowflags |= FLOW_PKT_ESTABLISHED; + p->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 host header test\"; " + "content:\"ECT\"; offset:3; http_raw_host; " + "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_buf, http_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: "); + result = 0; + goto end; + } + + /* do detect */ + SigMatchSignatures(&th_v, de_ctx, det_ctx, p); + + if (!(PacketAlertCheck(p, 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(&p, 1); + return result; +} + +/** + * \test Test that the http_raw_host content matches against a http request + * which holds the content. + */ +static int DetectEngineHttpHRHTest07(void) +{ + TcpSession ssn; + Packet *p = NULL; + ThreadVars th_v; + DetectEngineCtx *de_ctx = NULL; + DetectEngineThreadCtx *det_ctx = NULL; + HtpState *http_state = NULL; + Flow f; + uint8_t http_buf[] = + "GET /index.html HTTP/1.0\r\n" + "Host: CONNECT\r\n" + "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n"; + uint32_t http_len = sizeof(http_buf) - 1; + int result = 0; + + memset(&th_v, 0, sizeof(th_v)); + memset(&f, 0, sizeof(f)); + memset(&ssn, 0, sizeof(ssn)); + + p = UTHBuildPacket(NULL, 0, IPPROTO_TCP); + + FLOW_INITIALIZE(&f); + f.protoctx = (void *)&ssn; + f.flags |= FLOW_IPV4; + p->flow = &f; + p->flowflags |= FLOW_PKT_TOSERVER; + p->flowflags |= FLOW_PKT_ESTABLISHED; + p->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 host header test\"; " + "content:!\"CO\"; offset:3; http_raw_host; " + "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_buf, http_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: "); + result = 0; + goto end; + } + + /* do detect */ + SigMatchSignatures(&th_v, de_ctx, det_ctx, p); + + if (!(PacketAlertCheck(p, 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(&p, 1); + return result; +} + +/** + * \test Test that the http_raw_host header content matches against a http request + * which holds the content. + */ +static int DetectEngineHttpHRHTest08(void) +{ + TcpSession ssn; + Packet *p = NULL; + ThreadVars th_v; + DetectEngineCtx *de_ctx = NULL; + DetectEngineThreadCtx *det_ctx = NULL; + HtpState *http_state = NULL; + Flow f; + uint8_t http_buf[] = + "GET /index.html HTTP/1.0\r\n" + "Host: CONNECT\r\n" + "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n"; + uint32_t http_len = sizeof(http_buf) - 1; + int result = 0; + + memset(&th_v, 0, sizeof(th_v)); + memset(&f, 0, sizeof(f)); + memset(&ssn, 0, sizeof(ssn)); + + p = UTHBuildPacket(NULL, 0, IPPROTO_TCP); + + FLOW_INITIALIZE(&f); + f.protoctx = (void *)&ssn; + f.flags |= FLOW_IPV4; + p->flow = &f; + p->flowflags |= FLOW_PKT_TOSERVER; + p->flowflags |= FLOW_PKT_ESTABLISHED; + p->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 host header test\"; " + "content:!\"ECT\"; offset:3; http_raw_host; " + "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_buf, http_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: "); + result = 0; + goto end; + } + + /* do detect */ + SigMatchSignatures(&th_v, de_ctx, det_ctx, p); + + if (PacketAlertCheck(p, 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(&p, 1); + return result; +} + +/** + * \test Test that the http_raw_host header content matches against a http request + * which holds the content. + */ +static int DetectEngineHttpHRHTest09(void) +{ + TcpSession ssn; + Packet *p = NULL; + ThreadVars th_v; + DetectEngineCtx *de_ctx = NULL; + DetectEngineThreadCtx *det_ctx = NULL; + HtpState *http_state = NULL; + Flow f; + uint8_t http_buf[] = + "GET /index.html HTTP/1.0\r\n" + "Host: CONNECT\r\n" + "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n"; + uint32_t http_len = sizeof(http_buf) - 1; + int result = 0; + + memset(&th_v, 0, sizeof(th_v)); + memset(&f, 0, sizeof(f)); + memset(&ssn, 0, sizeof(ssn)); + + p = UTHBuildPacket(NULL, 0, IPPROTO_TCP); + + FLOW_INITIALIZE(&f); + f.protoctx = (void *)&ssn; + f.flags |= FLOW_IPV4; + p->flow = &f; + p->flowflags |= FLOW_PKT_TOSERVER; + p->flowflags |= FLOW_PKT_ESTABLISHED; + p->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 host header test\"; " + "content:\"CON\"; offset:3; http_raw_host; " + "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_buf, http_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: "); + result = 0; + goto end; + } + + /* do detect */ + SigMatchSignatures(&th_v, de_ctx, det_ctx, p); + + if (PacketAlertCheck(p, 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(&p, 1); + return result; +} + +/** + * \test Test that the http_raw_host header content matches against a http request + * which holds the content. + */ +static int DetectEngineHttpHRHTest10(void) +{ + TcpSession ssn; + Packet *p = NULL; + ThreadVars th_v; + DetectEngineCtx *de_ctx = NULL; + DetectEngineThreadCtx *det_ctx = NULL; + HtpState *http_state = NULL; + Flow f; + uint8_t http_buf[] = + "GET /index.html HTTP/1.0\r\n" + "Host: CONNECT\r\n" + "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n"; + uint32_t http_len = sizeof(http_buf) - 1; + int result = 0; + + memset(&th_v, 0, sizeof(th_v)); + memset(&f, 0, sizeof(f)); + memset(&ssn, 0, sizeof(ssn)); + + p = UTHBuildPacket(NULL, 0, IPPROTO_TCP); + + FLOW_INITIALIZE(&f); + f.protoctx = (void *)&ssn; + f.flags |= FLOW_IPV4; + p->flow = &f; + p->flowflags |= FLOW_PKT_TOSERVER; + p->flowflags |= FLOW_PKT_ESTABLISHED; + p->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_raw_host header test\"; " + "content:\"CO\"; http_raw_host; " + "content:\"EC\"; within:4; http_raw_host; " + "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_buf, http_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: "); + result = 0; + goto end; + } + + /* do detect */ + SigMatchSignatures(&th_v, de_ctx, det_ctx, p); + + if (!PacketAlertCheck(p, 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(&p, 1); + return result; +} + +/** + * \test Test that the http_raw_host header content matches against a http request + * which holds the content. + */ +static int DetectEngineHttpHRHTest11(void) +{ + TcpSession ssn; + Packet *p = NULL; + ThreadVars th_v; + DetectEngineCtx *de_ctx = NULL; + DetectEngineThreadCtx *det_ctx = NULL; + HtpState *http_state = NULL; + Flow f; + uint8_t http_buf[] = + "GET /index.html HTTP/1.0\r\n" + "Host: CONNECT\r\n" + "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n"; + uint32_t http_len = sizeof(http_buf) - 1; + int result = 0; + + memset(&th_v, 0, sizeof(th_v)); + memset(&f, 0, sizeof(f)); + memset(&ssn, 0, sizeof(ssn)); + + p = UTHBuildPacket(NULL, 0, IPPROTO_TCP); + + FLOW_INITIALIZE(&f); + f.protoctx = (void *)&ssn; + f.flags |= FLOW_IPV4; + p->flow = &f; + p->flowflags |= FLOW_PKT_TOSERVER; + p->flowflags |= FLOW_PKT_ESTABLISHED; + p->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_raw_host header test\"; " + "content:\"CO\"; http_raw_host; " + "content:!\"EC\"; within:3; http_raw_host; " + "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_buf, http_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: "); + result = 0; + goto end; + } + + /* do detect */ + SigMatchSignatures(&th_v, de_ctx, det_ctx, p); + + if (!PacketAlertCheck(p, 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(&p, 1); + return result; +} + +/** + * \test Test that the http_raw_host header content matches against a http request + * which holds the content. + */ +static int DetectEngineHttpHRHTest12(void) +{ + TcpSession ssn; + Packet *p = NULL; + ThreadVars th_v; + DetectEngineCtx *de_ctx = NULL; + DetectEngineThreadCtx *det_ctx = NULL; + HtpState *http_state = NULL; + Flow f; + uint8_t http_buf[] = + "GET /index.html HTTP/1.0\r\n" + "Host: CONNECT\r\n" + "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n"; + uint32_t http_len = sizeof(http_buf) - 1; + int result = 0; + + memset(&th_v, 0, sizeof(th_v)); + memset(&f, 0, sizeof(f)); + memset(&ssn, 0, sizeof(ssn)); + + p = UTHBuildPacket(NULL, 0, IPPROTO_TCP); + + FLOW_INITIALIZE(&f); + f.protoctx = (void *)&ssn; + f.flags |= FLOW_IPV4; + p->flow = &f; + p->flowflags |= FLOW_PKT_TOSERVER; + p->flowflags |= FLOW_PKT_ESTABLISHED; + p->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_raw_host header test\"; " + "content:\"CO\"; http_raw_host; " + "content:\"EC\"; within:3; http_raw_host; " + "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_buf, http_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: "); + result = 0; + goto end; + } + + /* do detect */ + SigMatchSignatures(&th_v, de_ctx, det_ctx, p); + + if (PacketAlertCheck(p, 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(&p, 1); + return result; +} + +/** + * \test Test that the http_raw_host header content matches against a http request + * which holds the content. + */ +static int DetectEngineHttpHRHTest13(void) +{ + TcpSession ssn; + Packet *p = NULL; + ThreadVars th_v; + DetectEngineCtx *de_ctx = NULL; + DetectEngineThreadCtx *det_ctx = NULL; + HtpState *http_state = NULL; + Flow f; + uint8_t http_buf[] = + "GET /index.html HTTP/1.0\r\n" + "Host: CONNECT\r\n" + "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n"; + uint32_t http_len = sizeof(http_buf) - 1; + int result = 0; + + memset(&th_v, 0, sizeof(th_v)); + memset(&f, 0, sizeof(f)); + memset(&ssn, 0, sizeof(ssn)); + + p = UTHBuildPacket(NULL, 0, IPPROTO_TCP); + + FLOW_INITIALIZE(&f); + f.protoctx = (void *)&ssn; + f.flags |= FLOW_IPV4; + p->flow = &f; + p->flowflags |= FLOW_PKT_TOSERVER; + p->flowflags |= FLOW_PKT_ESTABLISHED; + p->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_raw_host header test\"; " + "content:\"CO\"; http_raw_host; " + "content:!\"EC\"; within:4; http_raw_host; " + "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_buf, http_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: "); + result = 0; + goto end; + } + + /* do detect */ + SigMatchSignatures(&th_v, de_ctx, det_ctx, p); + + if (PacketAlertCheck(p, 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(&p, 1); + return result; +} + +/** + * \test Test that the http_raw_host header content matches against a http request + * which holds the content. + */ +static int DetectEngineHttpHRHTest14(void) +{ + TcpSession ssn; + Packet *p = NULL; + ThreadVars th_v; + DetectEngineCtx *de_ctx = NULL; + DetectEngineThreadCtx *det_ctx = NULL; + HtpState *http_state = NULL; + Flow f; + uint8_t http_buf[] = + "GET /index.html HTTP/1.0\r\n" + "Host: CONNECT\r\n" + "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n"; + uint32_t http_len = sizeof(http_buf) - 1; + int result = 0; + + memset(&th_v, 0, sizeof(th_v)); + memset(&f, 0, sizeof(f)); + memset(&ssn, 0, sizeof(ssn)); + + p = UTHBuildPacket(NULL, 0, IPPROTO_TCP); + + FLOW_INITIALIZE(&f); + f.protoctx = (void *)&ssn; + f.flags |= FLOW_IPV4; + p->flow = &f; + p->flowflags |= FLOW_PKT_TOSERVER; + p->flowflags |= FLOW_PKT_ESTABLISHED; + p->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_raw_host header test\"; " + "content:\"CO\"; http_raw_host; " + "content:\"EC\"; distance:2; http_raw_host; " + "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_buf, http_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: "); + result = 0; + goto end; + } + + /* do detect */ + SigMatchSignatures(&th_v, de_ctx, det_ctx, p); + + if (!PacketAlertCheck(p, 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(&p, 1); + return result; +} + +/** + * \test Test that the http_raw_host header content matches against a http request + * which holds the content. + */ +static int DetectEngineHttpHRHTest15(void) +{ + TcpSession ssn; + Packet *p = NULL; + ThreadVars th_v; + DetectEngineCtx *de_ctx = NULL; + DetectEngineThreadCtx *det_ctx = NULL; + HtpState *http_state = NULL; + Flow f; + uint8_t http_buf[] = + "GET /index.html HTTP/1.0\r\n" + "Host: CONNECT\r\n" + "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n"; + uint32_t http_len = sizeof(http_buf) - 1; + int result = 0; + + memset(&th_v, 0, sizeof(th_v)); + memset(&f, 0, sizeof(f)); + memset(&ssn, 0, sizeof(ssn)); + + p = UTHBuildPacket(NULL, 0, IPPROTO_TCP); + + FLOW_INITIALIZE(&f); + f.protoctx = (void *)&ssn; + f.flags |= FLOW_IPV4; + p->flow = &f; + p->flowflags |= FLOW_PKT_TOSERVER; + p->flowflags |= FLOW_PKT_ESTABLISHED; + p->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_raw_host header test\"; " + "content:\"CO\"; http_raw_host; " + "content:!\"EC\"; distance:3; http_raw_host; " + "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_buf, http_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: "); + result = 0; + goto end; + } + + /* do detect */ + SigMatchSignatures(&th_v, de_ctx, det_ctx, p); + + if (!PacketAlertCheck(p, 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(&p, 1); + return result; +} + +/** + * \test Test that the http_raw_host header content matches against a http request + * which holds the content. + */ +static int DetectEngineHttpHRHTest16(void) +{ + TcpSession ssn; + Packet *p = NULL; + ThreadVars th_v; + DetectEngineCtx *de_ctx = NULL; + DetectEngineThreadCtx *det_ctx = NULL; + HtpState *http_state = NULL; + Flow f; + uint8_t http_buf[] = + "GET /index.html HTTP/1.0\r\n" + "Host: CONNECT\r\n" + "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n"; + uint32_t http_len = sizeof(http_buf) - 1; + int result = 0; + + memset(&th_v, 0, sizeof(th_v)); + memset(&f, 0, sizeof(f)); + memset(&ssn, 0, sizeof(ssn)); + + p = UTHBuildPacket(NULL, 0, IPPROTO_TCP); + + FLOW_INITIALIZE(&f); + f.protoctx = (void *)&ssn; + f.flags |= FLOW_IPV4; + p->flow = &f; + p->flowflags |= FLOW_PKT_TOSERVER; + p->flowflags |= FLOW_PKT_ESTABLISHED; + p->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_raw_host header test\"; " + "content:\"CO\"; http_raw_host; " + "content:\"EC\"; distance:3; http_raw_host; " + "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_buf, http_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: "); + result = 0; + goto end; + } + + /* do detect */ + SigMatchSignatures(&th_v, de_ctx, det_ctx, p); + + if (PacketAlertCheck(p, 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(&p, 1); + return result; +} + +/** + * \test Test that the http_raw_host header content matches against a http request + * which holds the content. + */ +static int DetectEngineHttpHRHTest17(void) +{ + TcpSession ssn; + Packet *p = NULL; + ThreadVars th_v; + DetectEngineCtx *de_ctx = NULL; + DetectEngineThreadCtx *det_ctx = NULL; + HtpState *http_state = NULL; + Flow f; + uint8_t http_buf[] = + "GET /index.html HTTP/1.0\r\n" + "Host: CONNECT\r\n" + "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n"; + uint32_t http_len = sizeof(http_buf) - 1; + int result = 0; + + memset(&th_v, 0, sizeof(th_v)); + memset(&f, 0, sizeof(f)); + memset(&ssn, 0, sizeof(ssn)); + + p = UTHBuildPacket(NULL, 0, IPPROTO_TCP); + + FLOW_INITIALIZE(&f); + f.protoctx = (void *)&ssn; + f.flags |= FLOW_IPV4; + p->flow = &f; + p->flowflags |= FLOW_PKT_TOSERVER; + p->flowflags |= FLOW_PKT_ESTABLISHED; + p->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_raw_host header test\"; " + "content:\"CO\"; http_raw_host; " + "content:!\"EC\"; distance:2; http_raw_host; " + "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_buf, http_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: "); + result = 0; + goto end; + } + + /* do detect */ + SigMatchSignatures(&th_v, de_ctx, det_ctx, p); + + if (PacketAlertCheck(p, 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(&p, 1); + return result; +} + +#endif /* UNITTESTS */ + +void DetectEngineHttpHRHRegisterTests(void) +{ + +#ifdef UNITTESTS + UtRegisterTest("DetectEngineHttpHRHTest01", + DetectEngineHttpHRHTest01, 1); + UtRegisterTest("DetectEngineHttpHRHTest02", + DetectEngineHttpHRHTest02, 1); + UtRegisterTest("DetectEngineHttpHRHTest03", + DetectEngineHttpHRHTest03, 1); + UtRegisterTest("DetectEngineHttpHRHTest04", + DetectEngineHttpHRHTest04, 1); + UtRegisterTest("DetectEngineHttpHRHTest05", + DetectEngineHttpHRHTest05, 1); + UtRegisterTest("DetectEngineHttpHRHTest06", + DetectEngineHttpHRHTest06, 1); + UtRegisterTest("DetectEngineHttpHRHTest07", + DetectEngineHttpHRHTest07, 1); + UtRegisterTest("DetectEngineHttpHRHTest08", + DetectEngineHttpHRHTest08, 1); + UtRegisterTest("DetectEngineHttpHRHTest09", + DetectEngineHttpHRHTest09, 1); + UtRegisterTest("DetectEngineHttpHRHTest10", + DetectEngineHttpHRHTest10, 1); + UtRegisterTest("DetectEngineHttpHRHTest11", + DetectEngineHttpHRHTest11, 1); + UtRegisterTest("DetectEngineHttpHRHTest12", + DetectEngineHttpHRHTest12, 1); + UtRegisterTest("DetectEngineHttpHRHTest13", + DetectEngineHttpHRHTest13, 1); + UtRegisterTest("DetectEngineHttpHRHTest14", + DetectEngineHttpHRHTest14, 1); + UtRegisterTest("DetectEngineHttpHRHTest15", + DetectEngineHttpHRHTest15, 1); + UtRegisterTest("DetectEngineHttpHRHTest16", + DetectEngineHttpHRHTest16, 1); + UtRegisterTest("DetectEngineHttpHRHTest17", + DetectEngineHttpHRHTest17, 1); +#endif /* UNITTESTS */ + + return; +} +/** + * @} + */ diff --git a/src/detect-engine-hrhhd.h b/src/detect-engine-hrhhd.h new file mode 100644 index 0000000000..05ec8be912 --- /dev/null +++ b/src/detect-engine-hrhhd.h @@ -0,0 +1,34 @@ +/* Copyright (C) 2007-2013 Open Information Security Foundation + * + * You can copy, redistribute or modify this Program under the terms of + * the GNU General Public License version 2 as published by the Free + * Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +/** \file + * + * \author Anoop Saldanha + */ + +#ifndef __DETECT_ENGINE_HRHHD_H__ +#define __DETECT_ENGINE_HRHHD_H__ + +#include "app-layer-htp.h" + +int DetectEngineInspectHttpHRH(ThreadVars *tv, + DetectEngineCtx *, DetectEngineThreadCtx *, + Signature *, Flow *, uint8_t, void *, int); +int DetectEngineRunHttpHRHMpm(DetectEngineThreadCtx *, Flow *, HtpState *, uint8_t); +void DetectEngineHttpHRHRegisterTests(void); + +#endif /* __DETECT_ENGINE_HRHHD_H__ */ diff --git a/src/detect-engine-mpm.c b/src/detect-engine-mpm.c index c996ab8b2c..de07883aa1 100644 --- a/src/detect-engine-mpm.c +++ b/src/detect-engine-mpm.c @@ -671,6 +671,41 @@ uint32_t HttpHHPatternSearch(DetectEngineThreadCtx *det_ctx, SCReturnUInt(ret); } +/** + * \brief Http raw host header match -- searches for one pattern per signature. + * + * \param det_ctx Detection engine thread ctx. + * \param hrh Raw hostname to inspect. + * \param hrh_len Raw hostname buffer length. + * \param flags Flags + * + * \retval ret Number of matches. + */ +uint32_t HttpHRHPatternSearch(DetectEngineThreadCtx *det_ctx, + uint8_t *hrh, uint32_t hrh_len, uint8_t flags) +{ + SCEnter(); + + uint32_t ret; + if (flags & STREAM_TOSERVER) { + if (det_ctx->sgh->mpm_hrhhd_ctx_ts == NULL) + SCReturnUInt(0); + + ret = mpm_table[det_ctx->sgh->mpm_hrhhd_ctx_ts->mpm_type]. + Search(det_ctx->sgh->mpm_hrhhd_ctx_ts, &det_ctx->mtcu, + &det_ctx->pmq, hrh, hrh_len); + } else { + if (det_ctx->sgh->mpm_hrhhd_ctx_tc == NULL) + SCReturnUInt(0); + + ret = mpm_table[det_ctx->sgh->mpm_hrhhd_ctx_tc->mpm_type]. + Search(det_ctx->sgh->mpm_hrhhd_ctx_tc, &det_ctx->mtcu, + &det_ctx->pmq, hrh, hrh_len); + } + + SCReturnUInt(ret); +} + /** \brief Pattern match -- searches for only one pattern per signature. * * \param det_ctx detection engine thread ctx @@ -1491,6 +1526,7 @@ static void PopulateMpmAddPatternToMpm(DetectEngineCtx *de_ctx, case DETECT_SM_LIST_HSCDMATCH: case DETECT_SM_LIST_HUADMATCH: case DETECT_SM_LIST_HHHDMATCH: + case DETECT_SM_LIST_HRHHDMATCH: { MpmCtx *mpm_ctx_ts = NULL; MpmCtx *mpm_ctx_tc = NULL; @@ -1607,6 +1643,15 @@ static void PopulateMpmAddPatternToMpm(DetectEngineCtx *de_ctx, sig_flags |= SIG_FLAG_MPM_HTTP; if (cd->flags & DETECT_CONTENT_NEGATED) sig_flags |= SIG_FLAG_MPM_HTTP_NEG; + } else if (sm_list == DETECT_SM_LIST_HRHHDMATCH) { + if (s->flags & SIG_FLAG_TOSERVER) + mpm_ctx_ts = sgh->mpm_hrhhd_ctx_ts; + if (s->flags & SIG_FLAG_TOCLIENT) + mpm_ctx_tc = sgh->mpm_hrhhd_ctx_tc; + sgh_flags = SIG_GROUP_HEAD_MPM_HRHHD; + sig_flags |= SIG_FLAG_MPM_HTTP; + if (cd->flags & DETECT_CONTENT_NEGATED) + sig_flags |= SIG_FLAG_MPM_HTTP_NEG; } if (cd->flags & DETECT_CONTENT_FAST_PATTERN_CHOP) { @@ -1874,6 +1919,8 @@ int PatternMatchPrepareGroup(DetectEngineCtx *de_ctx, SigGroupHead *sh) uint32_t has_co_huad = 0; /* used to indicate if sgh has atleast one sig with http_host */ uint32_t has_co_hhhd = 0; + /* used to indicate if sgh has atleast one sig with http_raw_host */ + uint32_t has_co_hrhhd = 0; //uint32_t cnt = 0; uint32_t sig = 0; @@ -1937,6 +1984,10 @@ int PatternMatchPrepareGroup(DetectEngineCtx *de_ctx, SigGroupHead *sh) if (s->sm_lists[DETECT_SM_LIST_HHHDMATCH] != NULL) { has_co_hhhd = 1; } + + if (s->sm_lists[DETECT_SM_LIST_HRHHDMATCH] != NULL) { + has_co_hrhhd = 1; + } } /* intialize contexes */ @@ -2283,6 +2334,28 @@ int PatternMatchPrepareGroup(DetectEngineCtx *de_ctx, SigGroupHead *sh) #endif } + if (has_co_hrhhd) { + if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_SINGLE) { + sh->mpm_hrhhd_ctx_ts = MpmFactoryGetMpmCtxForProfile(de_ctx, de_ctx->sgh_mpm_context_hrhhd, 0); + sh->mpm_hrhhd_ctx_tc = MpmFactoryGetMpmCtxForProfile(de_ctx, de_ctx->sgh_mpm_context_hrhhd, 1); + } else { + sh->mpm_hrhhd_ctx_ts = MpmFactoryGetMpmCtxForProfile(de_ctx, MPM_CTX_FACTORY_UNIQUE_CONTEXT, 0); + sh->mpm_hrhhd_ctx_tc = MpmFactoryGetMpmCtxForProfile(de_ctx, MPM_CTX_FACTORY_UNIQUE_CONTEXT, 1); + } + if (sh->mpm_hrhhd_ctx_ts == NULL || sh->mpm_hrhhd_ctx_tc == NULL) { + SCLogDebug("sh->mpm_hrhhd_ctx == NULL. This should never happen"); + exit(EXIT_FAILURE); + } + +#ifndef __SC_CUDA_SUPPORT__ + MpmInitCtx(sh->mpm_hrhhd_ctx_ts, de_ctx->mpm_matcher, -1); + MpmInitCtx(sh->mpm_hrhhd_ctx_tc, de_ctx->mpm_matcher, -1); +#else + MpmInitCtx(sh->mpm_hrhhd_ctx_ts, de_ctx->mpm_matcher, de_ctx->cuda_rc_mod_handle); + MpmInitCtx(sh->mpm_hrhhd_ctx_tc, de_ctx->mpm_matcher, de_ctx->cuda_rc_mod_handle); +#endif + } + if (has_co_packet || has_co_stream || has_co_uri || @@ -2296,7 +2369,8 @@ int PatternMatchPrepareGroup(DetectEngineCtx *de_ctx, SigGroupHead *sh) has_co_hscd || has_co_hrud || has_co_huad || - has_co_hhhd) { + has_co_hhhd || + has_co_hrhhd) { PatternMatchPreparePopulateMpm(de_ctx, sh); @@ -2663,6 +2737,28 @@ int PatternMatchPrepareGroup(DetectEngineCtx *de_ctx, SigGroupHead *sh) } } } + if (sh->mpm_hrhhd_ctx_ts != NULL) { + if (sh->mpm_hrhhd_ctx_ts->pattern_cnt == 0) { + MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_hrhhd_ctx_ts); + sh->mpm_hrhhd_ctx_ts = NULL; + } else { + if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) { + if (mpm_table[sh->mpm_hrhhd_ctx_ts->mpm_type].Prepare != NULL) + mpm_table[sh->mpm_hrhhd_ctx_ts->mpm_type].Prepare(sh->mpm_hrhhd_ctx_ts); + } + } + } + if (sh->mpm_hrhhd_ctx_tc != NULL) { + if (sh->mpm_hrhhd_ctx_tc->pattern_cnt == 0) { + MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_hrhhd_ctx_tc); + sh->mpm_hrhhd_ctx_tc = NULL; + } else { + if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) { + if (mpm_table[sh->mpm_hrhhd_ctx_tc->mpm_type].Prepare != NULL) + mpm_table[sh->mpm_hrhhd_ctx_tc->mpm_type].Prepare(sh->mpm_hrhhd_ctx_tc); + } + } + } //} /* if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) */ } else { MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_proto_other_ctx); @@ -2696,6 +2792,8 @@ int PatternMatchPrepareGroup(DetectEngineCtx *de_ctx, SigGroupHead *sh) sh->mpm_huad_ctx_ts = NULL; MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_hhhd_ctx_ts); sh->mpm_hhhd_ctx_ts = NULL; + MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_hrhhd_ctx_ts); + sh->mpm_hrhhd_ctx_ts = NULL; MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_proto_tcp_ctx_tc); sh->mpm_proto_tcp_ctx_tc = NULL; @@ -2725,6 +2823,8 @@ int PatternMatchPrepareGroup(DetectEngineCtx *de_ctx, SigGroupHead *sh) sh->mpm_huad_ctx_tc = NULL; MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_hhhd_ctx_tc); sh->mpm_hhhd_ctx_tc = NULL; + MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_hrhhd_ctx_tc); + sh->mpm_hrhhd_ctx_tc = NULL; } return 0; diff --git a/src/detect-engine-mpm.h b/src/detect-engine-mpm.h index 76d35c8dad..c9488ea90b 100644 --- a/src/detect-engine-mpm.h +++ b/src/detect-engine-mpm.h @@ -50,6 +50,7 @@ uint32_t HttpStatMsgPatternSearch(DetectEngineThreadCtx *, uint8_t *, uint32_t, uint32_t HttpStatCodePatternSearch(DetectEngineThreadCtx *, uint8_t *, uint32_t, uint8_t); uint32_t HttpUAPatternSearch(DetectEngineThreadCtx *, uint8_t *, uint32_t, uint8_t); uint32_t HttpHHPatternSearch(DetectEngineThreadCtx *, uint8_t *, uint32_t, uint8_t); +uint32_t HttpHRHPatternSearch(DetectEngineThreadCtx *, uint8_t *, uint32_t, uint8_t); void PacketPatternCleanup(ThreadVars *, DetectEngineThreadCtx *); void StreamPatternCleanup(ThreadVars *t, DetectEngineThreadCtx *det_ctx, StreamMsg *smsg); diff --git a/src/detect-engine-state.c b/src/detect-engine-state.c index 7578dc2df7..9067083c5c 100644 --- a/src/detect-engine-state.c +++ b/src/detect-engine-state.c @@ -68,6 +68,7 @@ #include "detect-engine-hscd.h" #include "detect-engine-hua.h" #include "detect-engine-hhhd.h" +#include "detect-engine-hrhhd.h" #include "detect-engine-dcepayload.h" #include "detect-engine-file.h" diff --git a/src/detect-engine-state.h b/src/detect-engine-state.h index 30ecf7d326..3f8b0ed346 100644 --- a/src/detect-engine-state.h +++ b/src/detect-engine-state.h @@ -69,6 +69,7 @@ #define DE_STATE_FLAG_HSCD_MATCH 1 << 15 /**< hscd payload inspection part matched */ #define DE_STATE_FLAG_HUAD_MATCH 1 << 16 /**< huad payload inspection part matched */ #define DE_STATE_FLAG_HHHD_MATCH 1 << 17 /**< hhhd payload inspection part matched */ +#define DE_STATE_FLAG_HRHHD_MATCH 1 << 18 /**< hrhhd payload inspection part matched */ #define DE_STATE_FLAG_URI_INSPECT DE_STATE_FLAG_URI_MATCH /**< uri part of the sig inspected */ #define DE_STATE_FLAG_DCE_INSPECT DE_STATE_FLAG_DCE_MATCH /**< dce payload inspection part inspected */ @@ -85,6 +86,7 @@ #define DE_STATE_FLAG_HSCD_INSPECT DE_STATE_FLAG_HSCD_MATCH /**< hscd payload inspection part inspected */ #define DE_STATE_FLAG_HUAD_INSPECT DE_STATE_FLAG_HUAD_MATCH /**< huad payload inspection part inspected */ #define DE_STATE_FLAG_HHHD_INSPECT DE_STATE_FLAG_HHHD_MATCH /**< hhhd payload inspection part inspected */ +#define DE_STATE_FLAG_HRHHD_INSPECT DE_STATE_FLAG_HRHHD_MATCH /**< hrhhd payload inspection part inspected */ /* state flags */ #define DE_STATE_FILE_STORE_DISABLED 0x0001 diff --git a/src/detect-engine.c b/src/detect-engine.c index d2398b1b97..959ae8de40 100644 --- a/src/detect-engine.c +++ b/src/detect-engine.c @@ -54,6 +54,7 @@ #include "detect-engine-hscd.h" #include "detect-engine-hua.h" #include "detect-engine-hhhd.h" +#include "detect-engine-hrhhd.h" #include "detect-engine-file.h" #include "detect-engine.h" @@ -207,6 +208,12 @@ void DetectEngineRegisterAppInspectionEngines(void) DE_STATE_FLAG_HHHD_MATCH, 0, DetectEngineInspectHttpHH }, + { ALPROTO_HTTP, + DETECT_SM_LIST_HRHHDMATCH, + DE_STATE_FLAG_HRHHD_INSPECT, + DE_STATE_FLAG_HRHHD_MATCH, + 0, + DetectEngineInspectHttpHRH }, }; struct tmp_t data_toclient[] = { diff --git a/src/detect-fast-pattern.c b/src/detect-fast-pattern.c index f61f3718a6..12e947731d 100644 --- a/src/detect-fast-pattern.c +++ b/src/detect-fast-pattern.c @@ -98,6 +98,7 @@ void SupportFastPatternForSigMatchTypes(void) SupportFastPatternForSigMatchList(DETECT_SM_LIST_HSCDMATCH); SupportFastPatternForSigMatchList(DETECT_SM_LIST_HUADMATCH); SupportFastPatternForSigMatchList(DETECT_SM_LIST_HHHDMATCH); + SupportFastPatternForSigMatchList(DETECT_SM_LIST_HRHHDMATCH); return; } @@ -176,18 +177,19 @@ static int DetectFastPatternSetup(DetectEngineCtx *de_ctx, Signature *s, char *a s->sm_lists_tail[DETECT_SM_LIST_HSMDMATCH] == NULL && s->sm_lists_tail[DETECT_SM_LIST_HSCDMATCH] == NULL && s->sm_lists_tail[DETECT_SM_LIST_HUADMATCH] == NULL && - s->sm_lists_tail[DETECT_SM_LIST_HHHDMATCH] == NULL) { + s->sm_lists_tail[DETECT_SM_LIST_HHHDMATCH] == NULL && + s->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH] == NULL) { SCLogWarning(SC_WARN_COMPATIBILITY, "fast_pattern found inside the " "rule, without a preceding content based keyword. " "Currently we provide fast_pattern support for content, " "uricontent, http_client_body, http_server_body, http_header, " "http_raw_header, http_method, http_cookie, " "http_raw_uri, http_stat_msg, http_stat_code, " - "http_user_agent or http_hostoption"); + "http_user_agent, http_host or http_raw_host option"); return -1; } - SigMatch *pm = SigMatchGetLastSMFromLists(s, 26, + SigMatch *pm = SigMatchGetLastSMFromLists(s, 28, DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_PMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_UMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HCBDMATCH], @@ -200,7 +202,8 @@ static int DetectFastPatternSetup(DetectEngineCtx *de_ctx, Signature *s, char *a DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HSCDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HRUDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HUADMATCH], - DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HHHDMATCH]); + DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HHHDMATCH], + DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH]); if (pm == NULL) { SCLogError(SC_ERR_INVALID_SIGNATURE, "fast_pattern found inside " "the rule, without a content context. Please use a " @@ -18103,6 +18106,1210 @@ int DetectFastPatternTest629(void) } + + + + + + + + + + + + + + + + + +int DetectFastPatternTest630(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:\"one\"; http_raw_host; nocase; " + "content:!\"oneonetwo\"; fast_pattern:3,4; http_raw_host; nocase; " + "content:\"three\"; http_raw_host; nocase; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH]->prev->ctx; + if (ud->flags & DETECT_CONTENT_FAST_PATTERN && + ud->flags & DETECT_CONTENT_NEGATED && + ud->flags & DETECT_CONTENT_NOCASE && + !(ud->flags & DETECT_CONTENT_FAST_PATTERN_ONLY) && + ud->flags & DETECT_CONTENT_FAST_PATTERN_CHOP && + ud->fp_chop_offset == 3 && + ud->fp_chop_len == 4) { + result = 1; + } else { + result = 0; + } + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +/** + * \test Checks if a fast_pattern is registered in a Signature for uricontent. + */ +int DetectFastPatternTest631(void) +{ + SigMatch *sm = NULL; + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:\"one\"; fast_pattern:only; http_raw_host; nocase; " + "msg:\"Testing fast_pattern\"; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + + result = 0; + sm = de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HRHHDMATCH]; + if (sm != NULL) { + if ( (((DetectContentData *)sm->ctx)->flags & + DETECT_CONTENT_FAST_PATTERN) && + (((DetectContentData *)sm->ctx)->flags & + DETECT_CONTENT_NOCASE)) { + result = 1; + } else { + result = 0; + } + } + + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +/** + * \test Checks if a fast_pattern is registered in a Signature for uricontent. + */ +int DetectFastPatternTest632(void) +{ + SigMatch *sm = NULL; + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:\"oneoneone\"; fast_pattern:3,4; http_raw_host; nocase; " + "msg:\"Testing fast_pattern\"; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + + result = 0; + sm = de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HRHHDMATCH]; + if (sm != NULL) { + if ( (((DetectContentData *)sm->ctx)->flags & + DETECT_CONTENT_FAST_PATTERN) && + (((DetectContentData *)sm->ctx)->flags & + DETECT_CONTENT_NOCASE)) { + result = 1; + } else { + result = 0; + } + } + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest633(void) +{ + SigMatch *sm = NULL; + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:\"one\"; fast_pattern:only; http_raw_host; nocase; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + + sm = de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HRHHDMATCH]; + if (sm == NULL) { + goto end; + } + DetectContentData *ud = sm->ctx; + if (ud->flags & DETECT_CONTENT_FAST_PATTERN && + ud->flags & DETECT_CONTENT_NOCASE && + ud->flags & DETECT_CONTENT_FAST_PATTERN_ONLY && + !(ud->flags & DETECT_CONTENT_FAST_PATTERN_CHOP) && + ud->fp_chop_offset == 0 && + ud->fp_chop_len == 0) { + result = 1; + } else { + result = 0; + } + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest634(void) +{ + SigMatch *sm = NULL; + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:\"oneoneone\"; fast_pattern:3,4; http_raw_host; nocase; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + + sm = de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HRHHDMATCH]; + if (sm == NULL) { + goto end; + } + + DetectContentData *ud = sm->ctx; + if (ud->flags & DETECT_CONTENT_FAST_PATTERN && + ud->flags & DETECT_CONTENT_NOCASE && + !(ud->flags & DETECT_CONTENT_FAST_PATTERN_ONLY) && + ud->flags & DETECT_CONTENT_FAST_PATTERN_CHOP && + ud->fp_chop_offset == 3 && + ud->fp_chop_len == 4) { + result = 1; + } else { + result = 0; + } + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest635(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:\"one\"; http_raw_host; nocase; " + "content:\"two\"; fast_pattern:only; http_raw_host; distance:10; nocase; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest636(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:\"one\"; http_raw_host; nocase; " + "content:\"two\"; distance:10; fast_pattern:only; http_raw_host; nocase; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest637(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:\"one\"; http_raw_host; nocase; " + "content:\"two\"; fast_pattern:only; http_raw_host; within:10; nocase; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest638(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:\"one\"; http_raw_host; nocase; " + "content:\"two\"; within:10; fast_pattern:only; http_raw_host; nocase; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest639(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:\"one\"; http_raw_host; nocase; " + "content:\"two\"; fast_pattern:only; http_raw_host; offset:10; nocase; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest640(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:\"one\"; http_raw_host; nocase; " + "content:\"two\"; offset:10; fast_pattern:only; http_raw_host; nocase; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest641(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:\"one\"; http_raw_host; nocase; " + "content:\"two\"; fast_pattern:only; http_raw_host; depth:10; nocase; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest642(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:\"one\"; http_raw_host; nocase; " + "content:\"two\"; depth:10; fast_pattern:only; http_raw_host; nocase; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest643(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:\"one\"; http_raw_host; nocase; " + "content:!\"two\"; fast_pattern:only; http_raw_host; nocase; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest644(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:\" one\"; http_raw_host; nocase; " + "content:\"two\"; http_raw_host; distance:30; nocase; " + "content:\"two\"; fast_pattern:only; http_raw_host; nocase; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH]->ctx; + if (ud->flags & DETECT_CONTENT_FAST_PATTERN && + ud->flags & DETECT_CONTENT_NOCASE && + ud->flags & DETECT_CONTENT_FAST_PATTERN_ONLY && + !(ud->flags & DETECT_CONTENT_FAST_PATTERN_CHOP) && + ud->fp_chop_offset == 0 && + ud->fp_chop_len == 0) { + result = 1; + } else { + result = 0; + } + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest645(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:\"one\"; http_raw_host; nocase; " + "content:\"two\"; http_raw_host; within:30; nocase; " + "content:\"two\"; fast_pattern:only; http_raw_host; nocase; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH]->ctx; + if (ud->flags & DETECT_CONTENT_FAST_PATTERN && + ud->flags & DETECT_CONTENT_NOCASE && + ud->flags & DETECT_CONTENT_FAST_PATTERN_ONLY && + !(ud->flags & DETECT_CONTENT_FAST_PATTERN_CHOP) && + ud->fp_chop_offset == 0 && + ud->fp_chop_len == 0) { + result = 1; + } else { + result = 0; + } + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest646(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:\"one\"; http_raw_host; nocase; " + "content:\"two\"; http_raw_host; offset:30; nocase; " + "content:\"two\"; fast_pattern:only; http_raw_host; nocase; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH]->ctx; + if (ud->flags & DETECT_CONTENT_FAST_PATTERN && + ud->flags & DETECT_CONTENT_NOCASE && + ud->flags & DETECT_CONTENT_FAST_PATTERN_ONLY && + !(ud->flags & DETECT_CONTENT_FAST_PATTERN_CHOP) && + ud->fp_chop_offset == 0 && + ud->fp_chop_len == 0) { + result = 1; + } else { + result = 0; + } + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest647(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:\"one\"; http_raw_host; nocase; " + "content:\"two\"; http_raw_host; depth:30; nocase; " + "content:\"two\"; fast_pattern:only; http_raw_host; nocase; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH]->ctx; + if (ud->flags & DETECT_CONTENT_FAST_PATTERN && + ud->flags & DETECT_CONTENT_NOCASE && + ud->flags & DETECT_CONTENT_FAST_PATTERN_ONLY && + !(ud->flags & DETECT_CONTENT_FAST_PATTERN_CHOP) && + ud->fp_chop_offset == 0 && + ud->fp_chop_len == 0) { + result = 1; + } else { + result = 0; + } + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest648(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:!\"one\"; fast_pattern; http_raw_host; nocase; " + "content:\"two\"; http_raw_host; nocase; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH]->prev->ctx; + if (ud->flags & DETECT_CONTENT_FAST_PATTERN && + ud->flags & DETECT_CONTENT_NOCASE && + ud->flags & DETECT_CONTENT_NEGATED && + !(ud->flags & DETECT_CONTENT_FAST_PATTERN_ONLY) && + !(ud->flags & DETECT_CONTENT_FAST_PATTERN_CHOP) && + ud->fp_chop_offset == 0 && + ud->fp_chop_len == 0) { + result = 1; + } else { + result = 0; + } + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest649(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:\"two\"; http_raw_host; nocase; " + "content:!\"one\"; fast_pattern; http_raw_host; distance:20; nocase; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest650(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:\"two\"; http_raw_host; nocase; " + "content:!\"one\"; fast_pattern; http_raw_host; within:20; nocase; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest651(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:\"two\"; http_raw_host; nocase; " + "content:!\"one\"; fast_pattern; http_raw_host; offset:20; nocase; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest652(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:\"two\"; http_raw_host; nocase; " + "content:!\"one\"; fast_pattern; http_raw_host; depth:20; nocase; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest653(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:\"one\"; http_raw_host; nocase; " + "content:\"oneonetwo\"; fast_pattern:3,4; http_raw_host; nocase; " + "content:\"three\"; http_raw_host; nocase; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH]->prev->ctx; + if (ud->flags & DETECT_CONTENT_FAST_PATTERN && + ud->flags & DETECT_CONTENT_NOCASE && + !(ud->flags & DETECT_CONTENT_FAST_PATTERN_ONLY) && + ud->flags & DETECT_CONTENT_FAST_PATTERN_CHOP && + ud->fp_chop_offset == 3 && + ud->fp_chop_len == 4) { + result = 1; + } else { + result = 0; + } + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest654(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:\"one\"; http_raw_host; nocase; " + "content:\"oneonetwo\"; fast_pattern:3,4; http_raw_host; nocase; " + "content:\"three\"; http_raw_host; distance:30; nocase; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH]->prev->ctx; + if (ud->flags & DETECT_CONTENT_FAST_PATTERN && + ud->flags & DETECT_CONTENT_NOCASE && + !(ud->flags & DETECT_CONTENT_FAST_PATTERN_ONLY) && + ud->flags & DETECT_CONTENT_FAST_PATTERN_CHOP && + ud->fp_chop_offset == 3 && + ud->fp_chop_len == 4) { + result = 1; + } else { + result = 0; + } + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest655(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:\"one\"; http_raw_host; nocase; " + "content:\"oneonetwo\"; fast_pattern:3,4; http_raw_host; nocase; " + "content:\"three\"; http_raw_host; within:30; nocase; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH]->prev->ctx; + if (ud->flags & DETECT_CONTENT_FAST_PATTERN && + ud->flags & DETECT_CONTENT_NOCASE && + !(ud->flags & DETECT_CONTENT_FAST_PATTERN_ONLY) && + ud->flags & DETECT_CONTENT_FAST_PATTERN_CHOP && + ud->fp_chop_offset == 3 && + ud->fp_chop_len == 4) { + result = 1; + } else { + result = 0; + } + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest656(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:\"one\"; http_raw_host; nocase; " + "content:\"oneonetwo\"; fast_pattern:3,4; http_raw_host; nocase; " + "content:\"three\"; http_raw_host; offset:30; nocase; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH]->prev->ctx; + if (ud->flags & DETECT_CONTENT_FAST_PATTERN && + ud->flags & DETECT_CONTENT_NOCASE && + !(ud->flags & DETECT_CONTENT_FAST_PATTERN_ONLY) && + ud->flags & DETECT_CONTENT_FAST_PATTERN_CHOP && + ud->fp_chop_offset == 3 && + ud->fp_chop_len == 4) { + result = 1; + } else { + result = 0; + } + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest657(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:\"one\"; http_raw_host; nocase; " + "content:\"oneonetwo\"; fast_pattern:3,4; http_raw_host; nocase; " + "content:\"three\"; http_raw_host; depth:30; nocase; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH]->prev->ctx; + if (ud->flags & DETECT_CONTENT_FAST_PATTERN && + ud->flags & DETECT_CONTENT_NOCASE && + !(ud->flags & DETECT_CONTENT_FAST_PATTERN_ONLY) && + ud->flags & DETECT_CONTENT_FAST_PATTERN_CHOP && + ud->fp_chop_offset == 3 && + ud->fp_chop_len == 4) { + result = 1; + } else { + result = 0; + } + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest658(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:\"one\"; http_raw_host; nocase; " + "content:\"two\"; http_raw_host; distance:10; nocase; " + "content:\"oneonethree\"; fast_pattern:3,4; http_raw_host; nocase; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH]->ctx; + if (ud->flags & DETECT_CONTENT_FAST_PATTERN && + ud->flags & DETECT_CONTENT_NOCASE && + !(ud->flags & DETECT_CONTENT_FAST_PATTERN_ONLY) && + ud->flags & DETECT_CONTENT_FAST_PATTERN_CHOP && + ud->fp_chop_offset == 3 && + ud->fp_chop_len == 4) { + result = 1; + } else { + result = 0; + } + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest659(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:\"one\"; http_raw_host; nocase; " + "content:\"two\"; http_raw_host; within:10; nocase; " + "content:\"oneonethree\"; fast_pattern:3,4; http_raw_host; nocase; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH]->ctx; + if (ud->flags & DETECT_CONTENT_FAST_PATTERN && + ud->flags & DETECT_CONTENT_NOCASE && + !(ud->flags & DETECT_CONTENT_FAST_PATTERN_ONLY) && + ud->flags & DETECT_CONTENT_FAST_PATTERN_CHOP && + ud->fp_chop_offset == 3 && + ud->fp_chop_len == 4) { + result = 1; + } else { + result = 0; + } + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest660(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:\"one\"; http_raw_host; nocase; " + "content:\"two\"; http_raw_host; offset:10; nocase; " + "content:\"oneonethree\"; fast_pattern:3,4; http_raw_host; nocase; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH]->ctx; + if (ud->flags & DETECT_CONTENT_FAST_PATTERN && + ud->flags & DETECT_CONTENT_NOCASE && + !(ud->flags & DETECT_CONTENT_FAST_PATTERN_ONLY) && + ud->flags & DETECT_CONTENT_FAST_PATTERN_CHOP && + ud->fp_chop_offset == 3 && + ud->fp_chop_len == 4) { + result = 1; + } else { + result = 0; + } + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest661(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:\"one\"; http_raw_host; nocase; " + "content:\"two\"; http_raw_host; depth:10; nocase; " + "content:\"oneonethree\"; fast_pattern:3,4; http_raw_host; nocase; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH]->ctx; + if (ud->flags & DETECT_CONTENT_FAST_PATTERN && + ud->flags & DETECT_CONTENT_NOCASE && + !(ud->flags & DETECT_CONTENT_FAST_PATTERN_ONLY) && + ud->flags & DETECT_CONTENT_FAST_PATTERN_CHOP && + ud->fp_chop_offset == 3 && + ud->fp_chop_len == 4) { + result = 1; + } else { + result = 0; + } + + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest662(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:\"one\"; http_raw_host; nocase; " + "content:\"two\"; fast_pattern:65977,4; http_raw_host; nocase; " + "content:\"three\"; http_raw_host; distance:10; nocase; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest663(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:\"one\"; http_raw_host; nocase; " + "content:\"oneonetwo\"; fast_pattern:3,65977; http_raw_host; nocase; " + "content:\"three\"; distance:10; http_raw_host; nocase; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest664(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:\"one\"; http_raw_host; nocase; " + "content:\"two\"; fast_pattern:65534,4; http_raw_host; nocase; " + "content:\"three\"; http_raw_host; distance:10; nocase; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest665(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:\"one\"; http_raw_host; nocase; " + "content:!\"oneonetwo\"; fast_pattern:3,4; http_raw_host; nocase; " + "content:\"three\"; http_raw_host; nocase; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH]->prev->ctx; + if (ud->flags & DETECT_CONTENT_FAST_PATTERN && + ud->flags & DETECT_CONTENT_NOCASE && + ud->flags & DETECT_CONTENT_NEGATED && + !(ud->flags & DETECT_CONTENT_FAST_PATTERN_ONLY) && + ud->flags & DETECT_CONTENT_FAST_PATTERN_CHOP && + ud->fp_chop_offset == 3 && + ud->fp_chop_len == 4) { + result = 1; + } else { + result = 0; + } + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest666(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:\"one\"; http_raw_host; nocase; " + "content:!\"oneonetwo\"; fast_pattern:3,4; http_raw_host; distance:10; nocase; " + "content:\"three\"; http_raw_host; nocase; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest667(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:\"one\"; http_raw_host; nocase; " + "content:!\"oneonetwo\"; fast_pattern:3,4; http_raw_host; within:10; nocase; " + "content:\"three\"; http_raw_host; nocase; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest668(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:\"one\"; http_raw_host; nocase; " + "content:!\"oneonetwo\"; fast_pattern:3,4; http_raw_host; offset:10; nocase; " + "content:\"three\"; http_raw_host; nocase; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest669(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:\"one\"; http_raw_host; nocase; " + "content:!\"oneonetwo\"; fast_pattern:3,4; http_raw_host; depth:10; nocase; " + "content:\"three\"; http_raw_host; nocase; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest670(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:\"one\"; http_raw_host; nocase; " + "content:!\"oneonetwo\"; fast_pattern:3,4; http_raw_host; nocase; " + "content:\"three\"; http_raw_host; nocase; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH]->prev->ctx; + if (ud->flags & DETECT_CONTENT_FAST_PATTERN && + ud->flags & DETECT_CONTENT_NOCASE && + ud->flags & DETECT_CONTENT_NEGATED && + !(ud->flags & DETECT_CONTENT_FAST_PATTERN_ONLY) && + ud->flags & DETECT_CONTENT_FAST_PATTERN_CHOP && + ud->fp_chop_offset == 3 && + ud->fp_chop_len == 4) { + result = 1; + } else { + result = 0; + } + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + #endif void DetectFastPatternRegisterTests(void) @@ -18768,6 +19975,49 @@ void DetectFastPatternRegisterTests(void) UtRegisterTest("DetectFastPatternTest627", DetectFastPatternTest627, 1); UtRegisterTest("DetectFastPatternTest628", DetectFastPatternTest628, 1); UtRegisterTest("DetectFastPatternTest629", DetectFastPatternTest629, 1); + /* http_host fast_pattern tests ^ */ + /* http_rawhost fast_pattern tests v */ + UtRegisterTest("DetectFastPatternTest630", DetectFastPatternTest630, 1); + UtRegisterTest("DetectFastPatternTest631", DetectFastPatternTest631, 1); + UtRegisterTest("DetectFastPatternTest632", DetectFastPatternTest632, 1); + UtRegisterTest("DetectFastPatternTest633", DetectFastPatternTest633, 1); + UtRegisterTest("DetectFastPatternTest634", DetectFastPatternTest634, 1); + UtRegisterTest("DetectFastPatternTest635", DetectFastPatternTest635, 1); + UtRegisterTest("DetectFastPatternTest636", DetectFastPatternTest636, 1); + UtRegisterTest("DetectFastPatternTest637", DetectFastPatternTest637, 1); + UtRegisterTest("DetectFastPatternTest638", DetectFastPatternTest638, 1); + UtRegisterTest("DetectFastPatternTest639", DetectFastPatternTest639, 1); + UtRegisterTest("DetectFastPatternTest640", DetectFastPatternTest640, 1); + UtRegisterTest("DetectFastPatternTest641", DetectFastPatternTest641, 1); + UtRegisterTest("DetectFastPatternTest642", DetectFastPatternTest642, 1); + UtRegisterTest("DetectFastPatternTest643", DetectFastPatternTest643, 1); + UtRegisterTest("DetectFastPatternTest644", DetectFastPatternTest644, 1); + UtRegisterTest("DetectFastPatternTest645", DetectFastPatternTest645, 1); + UtRegisterTest("DetectFastPatternTest646", DetectFastPatternTest646, 1); + UtRegisterTest("DetectFastPatternTest647", DetectFastPatternTest647, 1); + UtRegisterTest("DetectFastPatternTest648", DetectFastPatternTest648, 1); + UtRegisterTest("DetectFastPatternTest649", DetectFastPatternTest649, 1); + UtRegisterTest("DetectFastPatternTest650", DetectFastPatternTest650, 1); + UtRegisterTest("DetectFastPatternTest651", DetectFastPatternTest651, 1); + UtRegisterTest("DetectFastPatternTest652", DetectFastPatternTest652, 1); + UtRegisterTest("DetectFastPatternTest653", DetectFastPatternTest653, 1); + UtRegisterTest("DetectFastPatternTest654", DetectFastPatternTest654, 1); + UtRegisterTest("DetectFastPatternTest655", DetectFastPatternTest655, 1); + UtRegisterTest("DetectFastPatternTest656", DetectFastPatternTest656, 1); + UtRegisterTest("DetectFastPatternTest657", DetectFastPatternTest657, 1); + UtRegisterTest("DetectFastPatternTest658", DetectFastPatternTest658, 1); + UtRegisterTest("DetectFastPatternTest659", DetectFastPatternTest659, 1); + UtRegisterTest("DetectFastPatternTest660", DetectFastPatternTest660, 1); + UtRegisterTest("DetectFastPatternTest661", DetectFastPatternTest661, 1); + UtRegisterTest("DetectFastPatternTest662", DetectFastPatternTest662, 1); + UtRegisterTest("DetectFastPatternTest663", DetectFastPatternTest663, 1); + UtRegisterTest("DetectFastPatternTest664", DetectFastPatternTest664, 1); + UtRegisterTest("DetectFastPatternTest665", DetectFastPatternTest665, 1); + UtRegisterTest("DetectFastPatternTest666", DetectFastPatternTest666, 1); + UtRegisterTest("DetectFastPatternTest667", DetectFastPatternTest667, 1); + UtRegisterTest("DetectFastPatternTest668", DetectFastPatternTest668, 1); + UtRegisterTest("DetectFastPatternTest669", DetectFastPatternTest669, 1); + UtRegisterTest("DetectFastPatternTest670", DetectFastPatternTest670, 1); #endif return; diff --git a/src/detect-http-hrh.c b/src/detect-http-hrh.c new file mode 100644 index 0000000000..7df63ab5cc --- /dev/null +++ b/src/detect-http-hrh.c @@ -0,0 +1,2475 @@ +/* Copyright (C) 2007-2013 Open Information Security Foundation + * + * You can copy, redistribute or modify this Program under the terms of + * the GNU General Public License version 2 as published by the Free + * Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +/** + * \ingroup httplayer + * + * @{ + */ + + +/** + * \file + * + * \author Anoop Saldanha + * + * Implements support for the http_raw_host keyword. + */ + +#include "suricata-common.h" +#include "threads.h" +#include "decode.h" + +#include "detect.h" +#include "detect-parse.h" +#include "detect-engine.h" +#include "detect-engine-mpm.h" +#include "detect-engine-state.h" +#include "detect-content.h" +#include "detect-pcre.h" + +#include "flow.h" +#include "flow-var.h" +#include "flow-util.h" + +#include "util-debug.h" +#include "util-unittest.h" +#include "util-unittest-helper.h" +#include "util-spm.h" + +#include "app-layer.h" + +#include "app-layer-htp.h" +#include "stream-tcp.h" +#include "detect-http-hrh.h" + +int DetectHttpHRHSetup(DetectEngineCtx *, Signature *, char *); +void DetectHttpHRHRegisterTests(void); +void DetectHttpHRHFree(void *); + +/** + * \brief Registers the keyword handlers for the "http_raw_host" keyword. + */ +void DetectHttpHRHRegister(void) +{ + sigmatch_table[DETECT_AL_HTTP_RAW_HOST].name = "http_raw_host"; + sigmatch_table[DETECT_AL_HTTP_RAW_HOST].desc = "content modifier to match only on the HTTP host header"; + sigmatch_table[DETECT_AL_HTTP_RAW_HOST].Match = NULL; + sigmatch_table[DETECT_AL_HTTP_RAW_HOST].AppLayerMatch = NULL; + sigmatch_table[DETECT_AL_HTTP_RAW_HOST].Setup = DetectHttpHRHSetup; + sigmatch_table[DETECT_AL_HTTP_RAW_HOST].Free = DetectHttpHRHFree; + sigmatch_table[DETECT_AL_HTTP_RAW_HOST].RegisterTests = DetectHttpHRHRegisterTests; + sigmatch_table[DETECT_AL_HTTP_RAW_HOST].alproto = ALPROTO_HTTP; + + sigmatch_table[DETECT_AL_HTTP_RAW_HOST].flags |= SIGMATCH_PAYLOAD ; + + return; +} + +/** + * \brief The setup function for the http_raw_host keyword for a signature. + * + * \param de_ctx Pointer to the detection engine context. + * \param s Pointer to the signature for the current Signature being + * parsed from the rules. + * \param m Pointer to the head of the SigMatch for the current rule + * being parsed. + * \param arg Pointer to the string holding the keyword value. + * + * \retval 0 On success + * \retval -1 On failure + */ +int DetectHttpHRHSetup(DetectEngineCtx *de_ctx, Signature *s, char *arg) +{ + DetectContentData *cd = NULL; + SigMatch *sm = NULL; + + if (arg != NULL && strcmp(arg, "") != 0) { + SCLogError(SC_ERR_INVALID_ARGUMENT, "http_raw_host not supplied with args"); + goto error; + } + + sm = SigMatchGetLastSMFromLists(s, 2, + DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_PMATCH]); + /* if we still can't find any previous content keywords, it's an invalid + * rule */ + if (sm == NULL) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "\"http_raw_host\" keyword " + "found inside the rule without a content context. " + "Please use a \"content\" keyword before using the " + "\"http_raw_host\" keyword"); + goto error; + } + + cd = (DetectContentData *)sm->ctx; + + /* http_raw_host should not be used with the rawbytes rule */ + if (cd->flags & DETECT_CONTENT_RAWBYTES) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "http_raw_host rule can not " + "be used with the rawbytes rule keyword"); + goto error; + } + + if (s->alproto != ALPROTO_UNKNOWN && s->alproto != ALPROTO_HTTP) { + SCLogError(SC_ERR_CONFLICTING_RULE_KEYWORDS, "rule contains a non http " + "alproto set"); + goto error; + } + + if (s->flags & SIG_FLAG_TOCLIENT) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "http_raw_host can not be used " + "with flow:to_client or flow:from_server. "); + goto error; + } + + if ((cd->flags & DETECT_CONTENT_WITHIN) || (cd->flags & DETECT_CONTENT_DISTANCE)) { + SigMatch *pm = SigMatchGetLastSMFromLists(s, 4, + DETECT_CONTENT, sm->prev, + DETECT_PCRE, sm->prev); + /* pm can be NULL now. To accomodate parsing sigs like - + * content:one; http_modifier; content:two; distance:0; http_modifier */ + if (pm != NULL) { + if (pm->type == DETECT_CONTENT) { + DetectContentData *tmp_cd = (DetectContentData *)pm->ctx; + tmp_cd->flags &= ~DETECT_CONTENT_RELATIVE_NEXT; + } else { + DetectPcreData *tmp_pd = (DetectPcreData *)pm->ctx; + tmp_pd->flags &= ~ DETECT_PCRE_RELATIVE_NEXT; + } + + } /* if (pm != NULL) */ + + /* reassigning pm */ + pm = SigMatchGetLastSMFromLists(s, 4, + DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH], + DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH]); + if (pm == NULL) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "http_raw_host seen with a " + "distance or within without a previous http_raw_host " + "content. Invalidating signature."); + goto error; + } + if (pm->type == DETECT_PCRE) { + DetectPcreData *tmp_pd = (DetectPcreData *)pm->ctx; + tmp_pd->flags |= DETECT_PCRE_RELATIVE_NEXT; + } else { + DetectContentData *tmp_cd = (DetectContentData *)pm->ctx; + tmp_cd->flags |= DETECT_CONTENT_RELATIVE_NEXT; + } + } + cd->id = DetectPatternGetId(de_ctx->mpm_pattern_id_store, cd, DETECT_SM_LIST_HRHHDMATCH); + sm->type = DETECT_CONTENT; + + /* transfer the sm from the pmatch list to hrhhdmatch list */ + SigMatchTransferSigMatchAcrossLists(sm, + &s->sm_lists[DETECT_SM_LIST_PMATCH], + &s->sm_lists_tail[DETECT_SM_LIST_PMATCH], + &s->sm_lists[DETECT_SM_LIST_HRHHDMATCH], + &s->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH]); + + /* flag the signature to indicate that we scan the app layer data */ + s->flags |= SIG_FLAG_APPLAYER; + s->alproto = ALPROTO_HTTP; + + return 0; + +error: + return -1; +} + +/** + * \brief The function to free the http_raw_host data. + * + * \param ptr Pointer to the http_raw_host. + */ +void DetectHttpHRHFree(void *ptr) +{ + DetectContentData *hrhhd = (DetectContentData *)ptr; + if (hrhhd == NULL) + return; + + if (hrhhd->content != NULL) + SCFree(hrhhd->content); + + BoyerMooreCtxDeInit(hrhhd->bm_ctx); + SCFree(hrhhd); + + return; +} + +/************************************Unittests*********************************/ + +#ifdef UNITTESTS + +#include "stream-tcp-reassemble.h" + +/** + * \test Test that a signature containting a http_raw_host is correctly parsed + * and the keyword is registered. + */ +static int DetectHttpHRHTest01(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " + "(msg:\"Testing http_raw_host\"; " + "content:\"one\"; http_raw_host; sid:1;)"); + if (de_ctx->sig_list != NULL) { + result = 1; + } else { + goto end; + } + + end: + SigGroupCleanup(de_ctx); + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + + return result; +} + +/** + * \test Test that a signature containing an valid http_raw_host entry is + * parsed. + */ +static int DetectHttpHRHTest02(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " + "(msg:\"Testing http_raw_host\"; " + "content:\"one\"; http_raw_host; sid:1;)"); + if (de_ctx->sig_list != NULL) + result = 1; + + end: + SigGroupCleanup(de_ctx); + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + + return result; +} + +/** + * \test Test that an invalid signature containing no content but a + * http_raw_host is invalidated. + */ +static int DetectHttpHRHTest03(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " + "(msg:\"Testing http_raw_host\"; " + "http_raw_host; sid:1;)"); + if (de_ctx->sig_list == NULL) + result = 1; + + end: + SigGroupCleanup(de_ctx); + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + + return result; +} + +/** + * \test Test that an invalid signature containing a rawbytes along with a + * http_raw_host is invalidated. + */ +static int DetectHttpHRHTest04(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " + "(msg:\"Testing http_raw_host\"; " + "content:\"one\"; rawbytes; http_raw_host; sid:1;)"); + if (de_ctx->sig_list == NULL) + result = 1; + + end: + SigGroupCleanup(de_ctx); + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + + return result; +} + +/** + * \test Test that a http_raw_host with nocase is parsed. + */ +static int DetectHttpHRHTest05(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " + "(msg:\"Testing http_raw_host\"; " + "content:\"one\"; http_raw_host; sid:1;)"); + if (de_ctx->sig_list != NULL) + result = 1; + + end: + SigGroupCleanup(de_ctx); + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + + return result; +} + +/** + *\test Test that the http_raw_host content matches against a http request + * which holds the content. + */ +static int DetectHttpHRHTest06(void) +{ + TcpSession ssn; + Packet *p = NULL; + ThreadVars th_v; + DetectEngineCtx *de_ctx = NULL; + DetectEngineThreadCtx *det_ctx = NULL; + HtpState *http_state = NULL; + Flow f; + uint8_t http_buf[] = + "GET /index.html HTTP/1.0\r\n" + "User-Agent: www.openinfosecfoundation.org\r\n" + "Host: This is dummy message body\r\n" + "Content-Type: text/html\r\n" + "\r\n"; + uint32_t http_len = sizeof(http_buf) - 1; + int result = 0; + + memset(&th_v, 0, sizeof(th_v)); + memset(&f, 0, sizeof(f)); + memset(&ssn, 0, sizeof(ssn)); + + p = UTHBuildPacket(NULL, 0, IPPROTO_TCP); + + FLOW_INITIALIZE(&f); + f.protoctx = (void *)&ssn; + f.flags |= FLOW_IPV4; + + p->flow = &f; + p->flowflags |= FLOW_PKT_TOSERVER; + p->flowflags |= FLOW_PKT_ESTABLISHED; + p->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 host test\"; " + "content:\"message\"; http_raw_host; " + "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_buf, http_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, p); + + if (!(PacketAlertCheck(p, 1))) { + printf("sid 1 didn't match but should have\n"); + 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(&p, 1); + return result; +} + +/** + *\test Test that the http_raw_host content matches against a http request + * which holds the content. + */ +static int DetectHttpHRHTest07(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" + "User-Agent: www.openinfosecfoundation.org\r\n" + "Host: This is dummy message"; + uint8_t http2_buf[] = + "body1\r\n\r\n"; + uint32_t http1_len = sizeof(http1_buf) - 1; + uint32_t http2_len = sizeof(http2_buf) - 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_TOSERVER; + 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 host test\"; " + "content:\"message\"; http_raw_host; " + "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, http1_buf, http1_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: "); + goto end; + } + + /* do detect */ + SigMatchSignatures(&th_v, de_ctx, det_ctx, p1); + + if (PacketAlertCheck(p1, 1)) { + printf("sid 1 matched on p1 but shouldn't have: "); + goto end; + } + + r = AppLayerParse(NULL, &f, ALPROTO_HTTP, STREAM_TOSERVER, http2_buf, http2_len); + if (r != 0) { + printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); + goto end; + } + + /* do detect */ + SigMatchSignatures(&th_v, de_ctx, det_ctx, p2); + if (!(PacketAlertCheck(p2, 1))) { + printf("sid 1 didn't match on p2 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; +} + +/** + *\test Test that the http_raw_host content matches against a http request + * which holds the content. + */ +static int DetectHttpHRHTest08(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" + "User-Agent: www.openinfosecfoundation.org\r\n" + "host: This is dummy mess"; + uint8_t http2_buf[] = + "age body\r\n\r\n"; + uint32_t http1_len = sizeof(http1_buf) - 1; + uint32_t http2_len = sizeof(http2_buf) - 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_TOSERVER; + 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 host test\"; " + "content:\"message\"; http_raw_host; " + "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, http1_buf, http1_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: "); + result = 0; + goto end; + } + + /* do detect */ + SigMatchSignatures(&th_v, de_ctx, det_ctx, p1); + + if ((PacketAlertCheck(p1, 1))) { + printf("sid 1 didn't match but should have"); + goto end; + } + + r = AppLayerParse(NULL, &f, ALPROTO_HTTP, STREAM_TOSERVER, http2_buf, http2_len); + if (r != 0) { + printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", 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; +} + +/** + *\test Test that the http_raw_host content matches against a http request + * which holds the content, against a cross boundary present pattern. + */ +static int DetectHttpHRHTest09(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" + "User-Agent: www.openinfosecfoundation.org\r\n" + "Host: This is dummy body1"; + uint8_t http2_buf[] = + "This is dummy message body2\r\n" + "Content-Type: text/html\r\n" + "Content-Length: 46\r\n" + "\r\n" + "This is dummy body1"; + uint32_t http1_len = sizeof(http1_buf) - 1; + uint32_t http2_len = sizeof(http2_buf) - 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_TOSERVER; + 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 host test\"; " + "content:\"body1This\"; http_raw_host; " + "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, http1_buf, http1_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: "); + result = 0; + goto end; + } + + /* do detect */ + SigMatchSignatures(&th_v, de_ctx, det_ctx, p1); + + if ((PacketAlertCheck(p1, 1))) { + printf("sid 1 didn't match but should have"); + goto end; + } + + r = AppLayerParse(NULL, &f, ALPROTO_HTTP, STREAM_TOSERVER, http2_buf, http2_len); + if (r != 0) { + printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", 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; +} + +/** + *\test Test that the http_raw_host content matches against a http request + * against a case insensitive pattern. + */ +static int DetectHttpHRHTest10(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" + "User-Agent: www.openinfosecfoundation.org\r\n" + "Host: This is dummy bodY1"; + uint8_t http2_buf[] = + "This is dummy message body2\r\n" + "Content-Type: text/html\r\n" + "Content-Length: 46\r\n" + "\r\n" + "This is dummy bodY1"; + uint32_t http1_len = sizeof(http1_buf) - 1; + uint32_t http2_len = sizeof(http2_buf) - 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_TOSERVER; + 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 host test\"; " + "content:\"bodY1This\"; http_raw_host; " + "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, http1_buf, http1_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 didn't match but should have\n"); + goto end; + } + + r = AppLayerParse(NULL, &f, ALPROTO_HTTP, STREAM_TOSERVER, http2_buf, http2_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; +} + +/** + *\test Test that the negated http_raw_host content matches against a + * http request which doesn't hold the content. + */ +static int DetectHttpHRHTest11(void) +{ + TcpSession ssn; + Packet *p = NULL; + ThreadVars th_v; + DetectEngineCtx *de_ctx = NULL; + DetectEngineThreadCtx *det_ctx = NULL; + HtpState *http_state = NULL; + Flow f; + uint8_t http_buf[] = + "GET /index.html HTTP/1.0\r\n" + "User-Agent: www.openinfosecfoundation.org\r\n" + "Host: This is dummy message body\r\n" + "Content-Type: text/html\r\n" + "\r\n"; + uint32_t http_len = sizeof(http_buf) - 1; + int result = 0; + + memset(&th_v, 0, sizeof(th_v)); + memset(&f, 0, sizeof(f)); + memset(&ssn, 0, sizeof(ssn)); + + p = UTHBuildPacket(NULL, 0, IPPROTO_TCP); + + FLOW_INITIALIZE(&f); + f.protoctx = (void *)&ssn; + f.flags |= FLOW_IPV4; + + p->flow = &f; + p->flowflags |= FLOW_PKT_TOSERVER; + p->flowflags |= FLOW_PKT_ESTABLISHED; + p->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 host test\"; " + "content:!\"message\"; http_raw_host; " + "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_buf, http_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: "); + result = 0; + goto end; + } + + /* do detect */ + SigMatchSignatures(&th_v, de_ctx, det_ctx, p); + + if (PacketAlertCheck(p, 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(&p, 1); + return result; +} + +/** + *\test Negative test that the negated http_raw_host content matches against a + * http request which holds hold the content. + */ +static int DetectHttpHRHTest12(void) +{ + TcpSession ssn; + Packet *p = NULL; + ThreadVars th_v; + DetectEngineCtx *de_ctx = NULL; + DetectEngineThreadCtx *det_ctx = NULL; + HtpState *http_state = NULL; + Flow f; + uint8_t http_buf[] = + "GET /index.html HTTP/1.0\r\n" + "User-Agent: www.openinfosecfoundation.org\r\n" + "Host: This is dummy body\r\n" + "\r\n"; + uint32_t http_len = sizeof(http_buf) - 1; + int result = 0; + + memset(&th_v, 0, sizeof(th_v)); + memset(&f, 0, sizeof(f)); + memset(&ssn, 0, sizeof(ssn)); + + p = UTHBuildPacket(NULL, 0, IPPROTO_TCP); + + FLOW_INITIALIZE(&f); + f.protoctx = (void *)&ssn; + f.flags |= FLOW_IPV4; + + p->flow = &f; + p->flowflags |= FLOW_PKT_TOSERVER; + p->flowflags |= FLOW_PKT_ESTABLISHED; + p->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 host test\"; " + "content:!\"message\"; http_raw_host; " + "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_buf, http_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: "); + result = 0; + goto end; + } + + /* do detect */ + SigMatchSignatures(&th_v, de_ctx, det_ctx, p); + + if (!(PacketAlertCheck(p, 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(&p, 1); + return result; +} + +/** + * \test Test that the http_raw_host content matches against a http request + * which holds the content. + */ +static int DetectHttpHRHTest13(void) +{ + TcpSession ssn; + Packet *p = NULL; + ThreadVars th_v; + DetectEngineCtx *de_ctx = NULL; + DetectEngineThreadCtx *det_ctx = NULL; + HtpState *http_state = NULL; + Flow f; + uint8_t http_buf[] = + "GET /index.html HTTP/1.0\r\n" + "User-Agent: www.openinfosecfoundation.org\r\n" + "Host: longbufferabcdefghijklmnopqrstuvwxyz0123456789bufferend\r\n" + "Content-Type: text/html\r\n" + "\r\n"; + uint32_t http_len = sizeof(http_buf) - 1; + int result = 0; + + + memset(&th_v, 0, sizeof(th_v)); + memset(&f, 0, sizeof(f)); + memset(&ssn, 0, sizeof(ssn)); + + p = UTHBuildPacket(NULL, 0, IPPROTO_TCP); + + FLOW_INITIALIZE(&f); + f.protoctx = (void *)&ssn; + f.flags |= FLOW_IPV4; + + p->flow = &f; + p->flowflags |= FLOW_PKT_TOSERVER; + p->flowflags |= FLOW_PKT_ESTABLISHED; + p->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 host test\"; " + "content:\"abcdefghijklmnopqrstuvwxyz0123456789\"; http_raw_host; " + "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_buf, http_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: "); + result = 0; + goto end; + } + + /* do detect */ + SigMatchSignatures(&th_v, de_ctx, det_ctx, p); + + if (!(PacketAlertCheck(p, 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(&p, 1); + return result; +} + +/** + * \test multiple http transactions and body chunks of request handling + */ +static int DetectHttpHRHTest14(void) +{ + int result = 0; + Signature *s = NULL; + DetectEngineThreadCtx *det_ctx = NULL; + ThreadVars th_v; + Flow f; + TcpSession ssn; + Packet *p = NULL; + uint8_t httpbuf1[] = "POST / HTTP/1.1\r\n"; + uint8_t httpbuf2[] = "Cookie: dummy1\r\n"; + uint8_t httpbuf3[] = "Host: Body one!!\r\n\r\n"; + uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */ + uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */ + uint32_t httplen3 = sizeof(httpbuf3) - 1; /* minus the \0 */ + uint8_t httpbuf4[] = "GET /?var=val HTTP/1.1\r\n"; + uint8_t httpbuf5[] = "Cookie: dummy2\r\n"; + uint8_t httpbuf6[] = "Host: Body two\r\n\r\n"; + uint32_t httplen4 = sizeof(httpbuf4) - 1; /* minus the \0 */ + uint32_t httplen5 = sizeof(httpbuf5) - 1; /* minus the \0 */ + uint32_t httplen6 = sizeof(httpbuf6) - 1; /* minus the \0 */ + + memset(&th_v, 0, sizeof(th_v)); + memset(&f, 0, sizeof(f)); + memset(&ssn, 0, sizeof(ssn)); + + p = UTHBuildPacket(NULL, 0, IPPROTO_TCP); + + FLOW_INITIALIZE(&f); + f.protoctx = (void *)&ssn; + f.proto = IPPROTO_TCP; + f.flags |= FLOW_IPV4; + + p->flow = &f; + p->flowflags |= FLOW_PKT_TOSERVER; + p->flowflags |= FLOW_PKT_ESTABLISHED; + p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST; + f.alproto = ALPROTO_HTTP; + + StreamTcpInitConfig(TRUE); + + DetectEngineCtx *de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) { + goto end; + } + + de_ctx->flags |= DE_QUIET; + + s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (content:\"POST\"; http_method; content:\"dummy1\"; http_cookie; content:\"Body one\"; http_raw_host; sid:1; rev:1;)"); + if (s == NULL) { + printf("sig parse failed: "); + goto end; + } + s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (content:\"GET\"; http_method; content:\"dummy2\"; http_cookie; content:\"Body two\"; http_raw_host; sid:2; rev:1;)"); + if (s == NULL) { + printf("sig2 parse failed: "); + goto end; + } + + SigGroupBuild(de_ctx); + DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx); + + int r = AppLayerParse(NULL, &f, ALPROTO_HTTP, STREAM_TOSERVER, httpbuf1, httplen1); + if (r != 0) { + printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); + goto end; + } + + /* do detect */ + SigMatchSignatures(&th_v, de_ctx, det_ctx, p); + if (PacketAlertCheck(p, 1)) { + printf("sig 1 alerted: "); + goto end; + } + p->alerts.cnt = 0; + + r = AppLayerParse(NULL, &f, ALPROTO_HTTP, STREAM_TOSERVER, httpbuf2, httplen2); + if (r != 0) { + printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r); + goto end; + } + + /* do detect */ + SigMatchSignatures(&th_v, de_ctx, det_ctx, p); + if (PacketAlertCheck(p, 1)) { + printf("sig 1 alerted (2): "); + goto end; + } + p->alerts.cnt = 0; + + r = AppLayerParse(NULL, &f, ALPROTO_HTTP, STREAM_TOSERVER, httpbuf3, httplen3); + if (r != 0) { + printf("toserver chunk 3 returned %" PRId32 ", expected 0: ", r); + goto end; + } + + /* do detect */ + SigMatchSignatures(&th_v, de_ctx, det_ctx, p); + if (!(PacketAlertCheck(p, 1))) { + printf("sig 1 didn't alert: "); + goto end; + } + p->alerts.cnt = 0; + + r = AppLayerParse(NULL, &f, ALPROTO_HTTP, STREAM_TOSERVER, httpbuf4, httplen4); + if (r != 0) { + printf("toserver chunk 5 returned %" PRId32 ", expected 0: ", r); + goto end; + } + + /* do detect */ + SigMatchSignatures(&th_v, de_ctx, det_ctx, p); + if (PacketAlertCheck(p, 1) || PacketAlertCheck(p, 2)) { + printf("sig 1 alerted (4): "); + goto end; + } + p->alerts.cnt = 0; + + r = AppLayerParse(NULL, &f, ALPROTO_HTTP, STREAM_TOSERVER, httpbuf5, httplen5); + if (r != 0) { + printf("toserver chunk 6 returned %" PRId32 ", expected 0: ", r); + goto end; + } + + /* do detect */ + SigMatchSignatures(&th_v, de_ctx, det_ctx, p); + if ((PacketAlertCheck(p, 1)) || (PacketAlertCheck(p, 2))) { + printf("sig 1 alerted (request 2, chunk 6): "); + goto end; + } + p->alerts.cnt = 0; + + SCLogDebug("sending data chunk 7"); + + r = AppLayerParse(NULL, &f, ALPROTO_HTTP, STREAM_TOSERVER, httpbuf6, httplen6); + if (r != 0) { + printf("toserver chunk 7 returned %" PRId32 ", expected 0: ", r); + goto end; + } + + /* do detect */ + SigMatchSignatures(&th_v, de_ctx, det_ctx, p); + if (PacketAlertCheck(p, 1) || !(PacketAlertCheck(p, 2))) { + printf("signature 2 didn't match or sig 1 matched, but shouldn't have: "); + goto end; + } + p->alerts.cnt = 0; + + HtpState *htp_state = f.alstate; + if (htp_state == NULL) { + printf("no http state: "); + result = 0; + goto end; + } + + if (list_size(htp_state->connp->conn->transactions) != 2) { + printf("The http app layer doesn't have 2 transactions, but it should: "); + goto end; + } + + result = 1; +end: + if (det_ctx != NULL) { + DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx); + } + if (de_ctx != NULL) { + SigGroupCleanup(de_ctx); + DetectEngineCtxFree(de_ctx); + } + + StreamTcpFreeConfig(TRUE); + FLOW_DESTROY(&f); + UTHFreePacket(p); + return result; +} + +int DetectHttpHRHTest16(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " + "(content:\"one\"; content:\"one\"; http_raw_host; sid:1;)"); + if (de_ctx->sig_list == NULL) { + printf("de_ctx->sig_list == NULL\n"); + goto end; + } + + if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] == NULL) { + printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] == NULL\n"); + goto end; + } + + if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HRHHDMATCH] == NULL) { + printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HRHHDMATCH] == NULL\n"); + goto end; + } + + DetectContentData *cd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->ctx; + DetectContentData *hrhhd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH]->ctx; + if (cd->id == hrhhd->id) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectHttpHRHTest17(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " + "(content:\"one\"; http_raw_host; content:\"one\"; sid:1;)"); + if (de_ctx->sig_list == NULL) { + printf("de_ctx->sig_list == NULL\n"); + goto end; + } + + if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] == NULL) { + printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] == NULL\n"); + goto end; + } + + if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HRHHDMATCH] == NULL) { + printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HRHHDMATCH] == NULL\n"); + goto end; + } + + DetectContentData *cd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->ctx; + DetectContentData *hrhhd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH]->ctx; + if (cd->id == hrhhd->id) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectHttpHRHTest18(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " + "(content:\"one\"; content:\"one\"; content:\"one\"; http_raw_host; content:\"one\"; sid:1;)"); + if (de_ctx->sig_list == NULL) { + printf("de_ctx->sig_list == NULL\n"); + goto end; + } + + if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] == NULL) { + printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] == NULL\n"); + goto end; + } + + if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HRHHDMATCH] == NULL) { + printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HRHHDMATCH] == NULL\n"); + goto end; + } + + DetectContentData *cd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->ctx; + DetectContentData *hrhhd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH]->ctx; + if (cd->id != 0 || hrhhd->id != 1) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectHttpHRHTest19(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " + "(content:\"one\"; http_raw_host; content:\"one\"; content:\"one\"; content:\"one\"; sid:1;)"); + if (de_ctx->sig_list == NULL) { + printf("de_ctx->sig_list == NULL\n"); + goto end; + } + + if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] == NULL) { + printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] == NULL\n"); + goto end; + } + + if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HRHHDMATCH] == NULL) { + printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HRHHDMATCH] == NULL\n"); + goto end; + } + + DetectContentData *cd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->ctx; + DetectContentData *hrhhd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH]->ctx; + if (cd->id != 1 || hrhhd->id != 0) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectHttpHRHTest20(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " + "(content:\"one\"; http_raw_host; " + "content:\"one\"; content:\"one\"; http_raw_host; content:\"one\"; sid:1;)"); + if (de_ctx->sig_list == NULL) { + printf("de_ctx->sig_list == NULL\n"); + goto end; + } + + if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] == NULL) { + printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] == NULL\n"); + goto end; + } + + if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HRHHDMATCH] == NULL) { + printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HRHHDMATCH] == NULL\n"); + goto end; + } + + DetectContentData *cd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->ctx; + DetectContentData *hrhhd1 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH]->ctx; + DetectContentData *hrhhd2 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH]->prev->ctx; + if (cd->id != 1 || hrhhd1->id != 0 || hrhhd2->id != 0) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectHttpHRHTest21(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " + "(content:\"one\"; http_raw_host; " + "content:\"one\"; content:\"one\"; http_raw_host; content:\"two\"; sid:1;)"); + if (de_ctx->sig_list == NULL) { + printf("de_ctx->sig_list == NULL\n"); + goto end; + } + + if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] == NULL) { + printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] == NULL\n"); + goto end; + } + + if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HRHHDMATCH] == NULL) { + printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HRHHDMATCH] == NULL\n"); + goto end; + } + + DetectContentData *cd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->ctx; + DetectContentData *hrhhd1 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH]->ctx; + DetectContentData *hrhhd2 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH]->prev->ctx; + if (cd->id != 2 || hrhhd1->id != 0 || hrhhd2->id != 0) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + + + + + + + + + + + + + + +int DetectHttpHRHTest22(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " + "(content:\"one\"; content:\"two\"; http_raw_host; " + "content:\"three\"; distance:10; http_raw_host; content:\"four\"; sid:1;)"); + if (de_ctx->sig_list == NULL) { + printf("de_ctx->sig_list == NULL\n"); + goto end; + } + + if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] == NULL) { + printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] == NULL\n"); + goto end; + } + + if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HRHHDMATCH] == NULL) { + printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HRHHDMATCH] == NULL\n"); + goto end; + } + + DetectContentData *cd1 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->prev->ctx; + DetectContentData *cd2 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->ctx; + DetectContentData *hrhhd1 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH]->prev->ctx; + DetectContentData *hrhhd2 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH]->ctx; + if (cd1->flags != 0 || memcmp(cd1->content, "one", cd1->content_len) != 0 || + cd2->flags != 0 || memcmp(cd2->content, "four", cd2->content_len) != 0 || + hrhhd1->flags != (DETECT_CONTENT_RELATIVE_NEXT) || + memcmp(hrhhd1->content, "two", hrhhd1->content_len) != 0 || + hrhhd2->flags != (DETECT_CONTENT_DISTANCE) || + memcmp(hrhhd2->content, "three", hrhhd1->content_len) != 0) { + goto end; + } + + if (!DETECT_CONTENT_IS_SINGLE(cd1) || + !DETECT_CONTENT_IS_SINGLE(cd2) || + DETECT_CONTENT_IS_SINGLE(hrhhd1) || + DETECT_CONTENT_IS_SINGLE(hrhhd2)) { + goto end; + } + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectHttpHRHTest23(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " + "(content:\"one\"; http_raw_host; pcre:/two/; " + "content:\"three\"; distance:10; http_raw_host; content:\"four\"; sid:1;)"); + if (de_ctx->sig_list == NULL) { + printf("de_ctx->sig_list == NULL\n"); + goto end; + } + + if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] == NULL) { + printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] == NULL\n"); + goto end; + } + + if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HRHHDMATCH] == NULL) { + printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HRHHDMATCH] == NULL\n"); + goto end; + } + + DetectPcreData *pd1 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->prev->ctx; + DetectContentData *cd2 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->ctx; + DetectContentData *hrhhd1 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH]->prev->ctx; + DetectContentData *hrhhd2 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH]->ctx; + if (pd1->flags != 0 || + cd2->flags != 0 || memcmp(cd2->content, "four", cd2->content_len) != 0 || + hrhhd1->flags != (DETECT_CONTENT_RELATIVE_NEXT) || + memcmp(hrhhd1->content, "one", hrhhd1->content_len) != 0 || + hrhhd2->flags != (DETECT_CONTENT_DISTANCE) || + memcmp(hrhhd2->content, "three", hrhhd1->content_len) != 0) { + goto end; + } + + if (!DETECT_CONTENT_IS_SINGLE(cd2) || + DETECT_CONTENT_IS_SINGLE(hrhhd1) || + DETECT_CONTENT_IS_SINGLE(hrhhd2)) { + goto end; + } + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectHttpHRHTest24(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " + "(content:\"one\"; http_raw_host; pcre:/two/; " + "content:\"three\"; distance:10; within:15; http_raw_host; content:\"four\"; sid:1;)"); + if (de_ctx->sig_list == NULL) { + printf("de_ctx->sig_list == NULL\n"); + goto end; + } + + if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] == NULL) { + printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] == NULL\n"); + goto end; + } + + if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HRHHDMATCH] == NULL) { + printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HRHHDMATCH] == NULL\n"); + goto end; + } + + DetectPcreData *pd1 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->prev->ctx; + DetectContentData *cd2 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->ctx; + DetectContentData *hrhhd1 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH]->prev->ctx; + DetectContentData *hrhhd2 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH]->ctx; + if (pd1->flags != 0 || + cd2->flags != 0 || memcmp(cd2->content, "four", cd2->content_len) != 0 || + hrhhd1->flags != (DETECT_CONTENT_RELATIVE_NEXT) || + memcmp(hrhhd1->content, "one", hrhhd1->content_len) != 0 || + hrhhd2->flags != (DETECT_CONTENT_DISTANCE | DETECT_CONTENT_WITHIN) || + memcmp(hrhhd2->content, "three", hrhhd1->content_len) != 0) { + goto end; + } + + if (!DETECT_CONTENT_IS_SINGLE(cd2) || + DETECT_CONTENT_IS_SINGLE(hrhhd1) || + DETECT_CONTENT_IS_SINGLE(hrhhd2)) { + goto end; + } + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectHttpHRHTest25(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " + "(content:\"one\"; http_raw_host; pcre:/two/; " + "content:\"three\"; distance:10; http_raw_host; " + "content:\"four\"; distance:10; sid:1;)"); + if (de_ctx->sig_list == NULL) { + printf("de_ctx->sig_list == NULL\n"); + goto end; + } + + if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] == NULL) { + printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] == NULL\n"); + goto end; + } + + if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HRHHDMATCH] == NULL) { + printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HRHHDMATCH] == NULL\n"); + goto end; + } + + DetectPcreData *pd1 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->prev->ctx; + DetectContentData *cd2 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->ctx; + DetectContentData *hrhhd1 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH]->prev->ctx; + DetectContentData *hrhhd2 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH]->ctx; + if (pd1->flags != DETECT_PCRE_RELATIVE_NEXT || + cd2->flags != DETECT_CONTENT_DISTANCE || + memcmp(cd2->content, "four", cd2->content_len) != 0 || + hrhhd1->flags != (DETECT_CONTENT_RELATIVE_NEXT) || + memcmp(hrhhd1->content, "one", hrhhd1->content_len) != 0 || + hrhhd2->flags != (DETECT_CONTENT_DISTANCE) || + memcmp(hrhhd2->content, "three", hrhhd1->content_len) != 0) { + goto end; + } + + if (DETECT_CONTENT_IS_SINGLE(cd2) || + DETECT_CONTENT_IS_SINGLE(hrhhd1) || + DETECT_CONTENT_IS_SINGLE(hrhhd2)) { + goto end; + } + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectHttpHRHTest26(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " + "(content:\"one\"; offset:10; http_raw_host; pcre:/two/; " + "content:\"three\"; distance:10; http_raw_host; within:10; " + "content:\"four\"; distance:10; sid:1;)"); + if (de_ctx->sig_list == NULL) { + printf("de_ctx->sig_list == NULL\n"); + goto end; + } + + if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] == NULL) { + printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] == NULL\n"); + goto end; + } + + if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HRHHDMATCH] == NULL) { + printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HRHHDMATCH] == NULL\n"); + goto end; + } + + DetectPcreData *pd1 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->prev->ctx; + DetectContentData *cd2 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->ctx; + DetectContentData *hrhhd1 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH]->prev->ctx; + DetectContentData *hrhhd2 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH]->ctx; + if (pd1->flags != (DETECT_PCRE_RELATIVE_NEXT) || + cd2->flags != DETECT_CONTENT_DISTANCE || + memcmp(cd2->content, "four", cd2->content_len) != 0 || + hrhhd1->flags != (DETECT_CONTENT_RELATIVE_NEXT | DETECT_CONTENT_OFFSET) || + memcmp(hrhhd1->content, "one", hrhhd1->content_len) != 0 || + hrhhd2->flags != (DETECT_CONTENT_DISTANCE | DETECT_CONTENT_WITHIN) || + memcmp(hrhhd2->content, "three", hrhhd1->content_len) != 0) { + printf ("failed: http_raw_host incorrect flags"); + goto end; + } + + if (DETECT_CONTENT_IS_SINGLE(cd2) || + DETECT_CONTENT_IS_SINGLE(hrhhd1) || + DETECT_CONTENT_IS_SINGLE(hrhhd2)) { + goto end; + } + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectHttpHRHTest27(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " + "(content:\"one\"; offset:10; http_raw_host; pcre:/two/; " + "content:\"three\"; distance:10; http_raw_host; within:10; " + "content:\"four\"; distance:10; sid:1;)"); + if (de_ctx->sig_list == NULL) { + printf("de_ctx->sig_list == NULL\n"); + goto end; + } + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectHttpHRHTest28(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " + "(content:\"one\"; http_raw_host; nocase; pcre:/two/; " + "content:\"three\"; http_raw_host; depth:10; " + "content:\"four\"; distance:10; sid:1;)"); + if (de_ctx->sig_list == NULL) { + printf("de_ctx->sig_list == NULL\n"); + goto end; + } + + if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] == NULL) { + printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] == NULL\n"); + goto end; + } + + if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HRHHDMATCH] == NULL) { + printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HRHHDMATCH] == NULL\n"); + goto end; + } + + DetectPcreData *pd1 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->prev->ctx; + DetectContentData *cd2 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->ctx; + DetectContentData *hrhhd1 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH]->prev->ctx; + DetectContentData *hrhhd2 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH]->ctx; + if (pd1->flags != (DETECT_PCRE_RELATIVE_NEXT) || + cd2->flags != DETECT_CONTENT_DISTANCE || + memcmp(cd2->content, "four", cd2->content_len) != 0 || + hrhhd1->flags != (DETECT_CONTENT_NOCASE) || + memcmp(hrhhd1->content, "one", hrhhd1->content_len) != 0 || + hrhhd2->flags != (DETECT_CONTENT_DEPTH) || + memcmp(hrhhd2->content, "three", hrhhd1->content_len) != 0) { + goto end; + } + + if (DETECT_CONTENT_IS_SINGLE(cd2) || + !DETECT_CONTENT_IS_SINGLE(hrhhd1) || + DETECT_CONTENT_IS_SINGLE(hrhhd2)) { + goto end; + } + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectHttpHRHTest29(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " + "(content:\"one\"; http_raw_host; " + "content:\"two\"; distance:0; http_raw_host; sid:1;)"); + if (de_ctx->sig_list == NULL) { + printf("de_ctx->sig_list == NULL\n"); + goto end; + } + + if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] != NULL) { + printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] != NULL\n"); + goto end; + } + + if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HRHHDMATCH] == NULL) { + printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HRHHDMATCH] == NULL\n"); + goto end; + } + + DetectContentData *hrhhd1 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH]->prev->ctx; + DetectContentData *hrhhd2 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH]->ctx; + if (hrhhd1->flags != (DETECT_CONTENT_RELATIVE_NEXT) || + memcmp(hrhhd1->content, "one", hrhhd1->content_len) != 0 || + hrhhd2->flags != (DETECT_CONTENT_DISTANCE) || + memcmp(hrhhd2->content, "two", hrhhd1->content_len) != 0) { + goto end; + } + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectHttpHRHTest30(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " + "(content:\"one\"; http_raw_host; " + "content:\"two\"; within:5; http_raw_host; sid:1;)"); + if (de_ctx->sig_list == NULL) { + printf("de_ctx->sig_list == NULL\n"); + goto end; + } + + if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] != NULL) { + printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] != NULL\n"); + goto end; + } + + if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HRHHDMATCH] == NULL) { + printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HRHHDMATCH] == NULL\n"); + goto end; + } + + DetectContentData *hrhhd1 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH]->prev->ctx; + DetectContentData *hrhhd2 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH]->ctx; + if (hrhhd1->flags != (DETECT_CONTENT_RELATIVE_NEXT) || + memcmp(hrhhd1->content, "one", hrhhd1->content_len) != 0 || + hrhhd2->flags != (DETECT_CONTENT_WITHIN) || + memcmp(hrhhd2->content, "two", hrhhd1->content_len) != 0) { + goto end; + } + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectHttpHRHTest31(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " + "(content:\"one\"; within:5; http_raw_host; sid:1;)"); + if (de_ctx->sig_list != NULL) { + printf("de_ctx->sig_list != NULL\n"); + goto end; + } + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectHttpHRHTest32(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " + "(content:\"one\"; http_raw_host; within:5; sid:1;)"); + if (de_ctx->sig_list == NULL) { + printf("de_ctx->sig_list != NULL\n"); + goto end; + } + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectHttpHRHTest33(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " + "(content:\"one\"; within:5; sid:1;)"); + if (de_ctx->sig_list != NULL) { + printf("de_ctx->sig_list != NULL\n"); + goto end; + } + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectHttpHRHTest34(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " + "(pcre:/one/Zi; " + "content:\"two\"; within:5; http_raw_host; sid:1;)"); + if (de_ctx->sig_list == NULL) { + printf("de_ctx->sig_list == NULL\n"); + goto end; + } + + if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] != NULL) { + printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] != NULL\n"); + goto end; + } + + if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HRHHDMATCH] == NULL) { + printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HRHHDMATCH] == NULL\n"); + goto end; + } + + if (de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH] == NULL || + de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH]->type != DETECT_CONTENT || + de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH]->prev == NULL || + de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH]->prev->type != DETECT_PCRE) { + + goto end; + } + + DetectPcreData *pd1 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH]->prev->ctx; + DetectContentData *hrhhd2 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH]->ctx; + if (pd1->flags != (DETECT_PCRE_RELATIVE_NEXT | DETECT_PCRE_HTTP_RAW_HOST | DETECT_PCRE_CASELESS) || + hrhhd2->flags != (DETECT_CONTENT_WITHIN) || + memcmp(hrhhd2->content, "two", hrhhd2->content_len) != 0) { + goto end; + } + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectHttpHRHTest35(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " + "(content:\"two\"; http_raw_host; " + "pcre:/one/ZRi; sid:1;)"); + if (de_ctx->sig_list == NULL) { + printf("de_ctx->sig_list == NULL\n"); + goto end; + } + + if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] != NULL) { + printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] != NULL\n"); + goto end; + } + + if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HRHHDMATCH] == NULL) { + printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HRHHDMATCH] == NULL\n"); + goto end; + } + + if (de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH] == NULL || + de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH]->type != DETECT_PCRE || + de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH]->prev == NULL || + de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH]->prev->type != DETECT_CONTENT) { + + goto end; + } + + DetectContentData *hrhhd1 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH]->prev->ctx; + DetectPcreData *pd2 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH]->ctx; + if (pd2->flags != (DETECT_PCRE_RELATIVE | DETECT_PCRE_HTTP_RAW_HOST | DETECT_PCRE_CASELESS) || + hrhhd1->flags != (DETECT_CONTENT_RELATIVE_NEXT) || + memcmp(hrhhd1->content, "two", hrhhd1->content_len) != 0) { + goto end; + } + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectHttpHRHTest36(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " + "(pcre:/one/Zi; " + "content:\"two\"; distance:5; http_raw_host; sid:1;)"); + if (de_ctx->sig_list == NULL) { + printf("de_ctx->sig_list == NULL\n"); + goto end; + } + + if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] != NULL) { + printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] != NULL\n"); + goto end; + } + + if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HRHHDMATCH] == NULL) { + printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HRHHDMATCH] == NULL\n"); + goto end; + } + + if (de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH] == NULL || + de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH]->type != DETECT_CONTENT || + de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH]->prev == NULL || + de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH]->prev->type != DETECT_PCRE) { + + goto end; + } + + DetectPcreData *pd1 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH]->prev->ctx; + DetectContentData *hrhhd2 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH]->ctx; + if (pd1->flags != (DETECT_PCRE_RELATIVE_NEXT | DETECT_PCRE_HTTP_RAW_HOST | DETECT_PCRE_CASELESS) || + hrhhd2->flags != (DETECT_CONTENT_DISTANCE) || + memcmp(hrhhd2->content, "two", hrhhd2->content_len) != 0) { + goto end; + } + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +/** + *\test Test that the http_raw_host content matches against a http request + * against a case insensitive pattern. + */ +static int DetectHttpHRHTest37(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" + "User-Agent: www.openinfosecfoundation.org\r\n" + "Host: This is dummy bodY1"; + uint8_t http2_buf[] = + "This is dummy message body2\r\n" + "Content-Type: text/html\r\n" + "Content-Length: 46\r\n" + "\r\n" + "This is dummy bodY1"; + uint32_t http1_len = sizeof(http1_buf) - 1; + uint32_t http2_len = sizeof(http2_buf) - 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_TOSERVER; + 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 host test\"; " + "content:\"body1this\"; http_raw_host; nocase; " + "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, http1_buf, http1_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 didn't match but should have\n"); + goto end; + } + + r = AppLayerParse(NULL, &f, ALPROTO_HTTP, STREAM_TOSERVER, http2_buf, http2_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; +} + +#endif /* UNITTESTS */ + +void DetectHttpHRHRegisterTests(void) +{ +#ifdef UNITTESTS + UtRegisterTest("DetectHttpHRHTest01", DetectHttpHRHTest01, 1); + UtRegisterTest("DetectHttpHRHTest02", DetectHttpHRHTest02, 1); + UtRegisterTest("DetectHttpHRHTest03", DetectHttpHRHTest03, 1); + UtRegisterTest("DetectHttpHRHTest04", DetectHttpHRHTest04, 1); + UtRegisterTest("DetectHttpHRHTest05", DetectHttpHRHTest05, 1); + UtRegisterTest("DetectHttpHRHTest06", DetectHttpHRHTest06, 1); + UtRegisterTest("DetectHttpHRHTest07", DetectHttpHRHTest07, 1); + UtRegisterTest("DetectHttpHRHTest08", DetectHttpHRHTest08, 1); + UtRegisterTest("DetectHttpHRHTest09", DetectHttpHRHTest09, 1); + UtRegisterTest("DetectHttpHRHTest10", DetectHttpHRHTest10, 1); + UtRegisterTest("DetectHttpHRHTest11", DetectHttpHRHTest11, 1); + UtRegisterTest("DetectHttpHRHTest12", DetectHttpHRHTest12, 1); + UtRegisterTest("DetectHttpHRHTest13", DetectHttpHRHTest13, 1); + UtRegisterTest("DetectHttpHRHTest14", DetectHttpHRHTest14, 1); + + UtRegisterTest("DetectHttpHRHTest16", DetectHttpHRHTest16, 1); + UtRegisterTest("DetectHttpHRHTest17", DetectHttpHRHTest17, 1); + UtRegisterTest("DetectHttpHRHTest18", DetectHttpHRHTest18, 1); + UtRegisterTest("DetectHttpHRHTest19", DetectHttpHRHTest19, 1); + UtRegisterTest("DetectHttpHRHTest20", DetectHttpHRHTest20, 1); + UtRegisterTest("DetectHttpHRHTest21", DetectHttpHRHTest21, 1); + + UtRegisterTest("DetectHttpHRHTest22", DetectHttpHRHTest22, 1); + UtRegisterTest("DetectHttpHRHTest23", DetectHttpHRHTest23, 1); + UtRegisterTest("DetectHttpHRHTest24", DetectHttpHRHTest24, 1); + UtRegisterTest("DetectHttpHRHTest25", DetectHttpHRHTest25, 1); + UtRegisterTest("DetectHttpHRHTest26", DetectHttpHRHTest26, 1); + UtRegisterTest("DetectHttpHRHTest27", DetectHttpHRHTest27, 1); + UtRegisterTest("DetectHttpHRHTest28", DetectHttpHRHTest28, 1); + UtRegisterTest("DetectHttpHRHTest29", DetectHttpHRHTest29, 1); + UtRegisterTest("DetectHttpHRHTest30", DetectHttpHRHTest30, 1); + UtRegisterTest("DetectHttpHRHTest31", DetectHttpHRHTest31, 1); + UtRegisterTest("DetectHttpHRHTest32", DetectHttpHRHTest32, 1); + UtRegisterTest("DetectHttpHRHTest33", DetectHttpHRHTest33, 1); + UtRegisterTest("DetectHttpHRHTest34", DetectHttpHRHTest34, 1); + UtRegisterTest("DetectHttpHRHTest35", DetectHttpHRHTest35, 1); + UtRegisterTest("DetectHttpHRHTest36", DetectHttpHRHTest36, 1); + UtRegisterTest("DetectHttpHRHTest37", DetectHttpHRHTest37, 1); +#endif /* UNITTESTS */ + + return; +} +/** + * @} + */ diff --git a/src/detect-http-hrh.h b/src/detect-http-hrh.h new file mode 100644 index 0000000000..0255f167ec --- /dev/null +++ b/src/detect-http-hrh.h @@ -0,0 +1,29 @@ +/* Copyright (C) 2007-2013 Open Information Security Foundation + * + * You can copy, redistribute or modify this Program under the terms of + * the GNU General Public License version 2 as published by the Free + * Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +/** + * \file + * + * \author Anoop Saldanha + */ + +#ifndef __DETECT_HTTP_HRH_H__ +#define __DETECT_HTTP_HRH_H__ + +void DetectHttpHRHRegister(void); + +#endif /* __DETECT_HTTP_HRH_H__ */ diff --git a/src/detect-isdataat.c b/src/detect-isdataat.c index b2c7a6c236..df934bc4d2 100644 --- a/src/detect-isdataat.c +++ b/src/detect-isdataat.c @@ -353,7 +353,7 @@ int DetectIsdataatSetup (DetectEngineCtx *de_ctx, Signature *s, char *isdataatst } return 0; } - pm = SigMatchGetLastSMFromLists(s, 60, + pm = SigMatchGetLastSMFromLists(s, 66, DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_PMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_UMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HCBDMATCH], @@ -367,6 +367,7 @@ int DetectIsdataatSetup (DetectEngineCtx *de_ctx, Signature *s, char *isdataatst DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HSCDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HUADMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HHHDMATCH], + DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH], DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_PMATCH], DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_UMATCH], DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_HCBDMATCH], @@ -378,6 +379,7 @@ int DetectIsdataatSetup (DetectEngineCtx *de_ctx, Signature *s, char *isdataatst DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_HRUDMATCH], DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_HUADMATCH], DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_HHHDMATCH], + DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH], DETECT_BYTEJUMP, s->sm_lists_tail[DETECT_SM_LIST_PMATCH], DETECT_BYTE_EXTRACT, s->sm_lists_tail[DETECT_SM_LIST_PMATCH], DETECT_BYTE_EXTRACT, s->sm_lists_tail[DETECT_SM_LIST_DMATCH], @@ -391,8 +393,8 @@ int DetectIsdataatSetup (DetectEngineCtx *de_ctx, Signature *s, char *isdataatst "http_client_body, http_header, http_raw_header, " "http_method, http_cookie, http_raw_uri, " "http_stat_msg, http_stat_code, byte_test, " - "byte_extract, byte_jump, http_user_agent or " - "http_host keyword"); + "byte_extract, byte_jump, http_user_agent, " + "http_host or http_raw_host keyword"); goto error; } else { int list_type = SigMatchListSMBelongsTo(s, pm); diff --git a/src/detect-nocase.c b/src/detect-nocase.c index fec0f7cc90..336e3883e7 100644 --- a/src/detect-nocase.c +++ b/src/detect-nocase.c @@ -76,7 +76,7 @@ static int DetectNocaseSetup (DetectEngineCtx *de_ctx, Signature *s, char *nulls } /* Search for the first previous SigMatch that supports nocase */ - SigMatch *pm = SigMatchGetLastSMFromLists(s, 26, + SigMatch *pm = SigMatchGetLastSMFromLists(s, 28, DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_PMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_UMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HCBDMATCH], @@ -89,13 +89,14 @@ static int DetectNocaseSetup (DetectEngineCtx *de_ctx, Signature *s, char *nulls DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HSCDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HCDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HUADMATCH], - DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HHHDMATCH]); + DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HHHDMATCH], + DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH]); if (pm == NULL) { SCLogError(SC_ERR_NOCASE_MISSING_PATTERN, "\"nocase\" needs a preceding " "content, uricontent, http_client_body, http_server_body, " "http_header, http_method, http_uri, http_cookie, " "http_raw_uri, http_stat_msg, http_stat_code, " - "http_user_agent or http_host option"); + "http_user_agent, http_host or http_raw_host option"); SCReturnInt(-1); } diff --git a/src/detect-offset.c b/src/detect-offset.c index f6b16991c0..204104b836 100644 --- a/src/detect-offset.c +++ b/src/detect-offset.c @@ -85,7 +85,7 @@ int DetectOffsetSetup (DetectEngineCtx *de_ctx, Signature *s, char *offsetstr) break; default: - pm = SigMatchGetLastSMFromLists(s, 26, + pm = SigMatchGetLastSMFromLists(s, 28, DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_PMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_UMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HCBDMATCH], @@ -98,14 +98,15 @@ int DetectOffsetSetup (DetectEngineCtx *de_ctx, Signature *s, char *offsetstr) DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HSCDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HRUDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HUADMATCH], - DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HHHDMATCH]); + DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HHHDMATCH], + DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH]); if (pm == NULL) { SCLogError(SC_ERR_OFFSET_MISSING_CONTENT, "offset needs " "preceding content or uricontent option, http_client_body, " "http_header, http_raw_header, http_method, " "http_cookie, http_raw_uri, http_stat_msg, " - "http_stat_code, http_user_agent or " - "http_host option"); + "http_stat_code, http_user_agent, " + "http_host or http_raw_host option"); if (dubbed) SCFree(str); return -1; diff --git a/src/detect-parse.c b/src/detect-parse.c index cb460860e9..ede6811b19 100644 --- a/src/detect-parse.c +++ b/src/detect-parse.c @@ -1116,7 +1116,8 @@ static int SigValidate(Signature *s) { DETECT_REPLACE, s->sm_lists_tail[DETECT_SM_LIST_HSCDMATCH], DETECT_REPLACE, s->sm_lists_tail[DETECT_SM_LIST_HCDMATCH], DETECT_REPLACE, s->sm_lists_tail[DETECT_SM_LIST_HUADMATCH], - DETECT_REPLACE, s->sm_lists_tail[DETECT_SM_LIST_HHHDMATCH]); + DETECT_REPLACE, s->sm_lists_tail[DETECT_SM_LIST_HHHDMATCH], + DETECT_REPLACE, s->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH]); if (pm != NULL) { SCLogError(SC_ERR_INVALID_SIGNATURE, "Signature has" " replace keyword linked with a modified content" @@ -1136,7 +1137,8 @@ static int SigValidate(Signature *s) { s->sm_lists_tail[DETECT_SM_LIST_HSCDMATCH] || s->sm_lists_tail[DETECT_SM_LIST_HCDMATCH] || s->sm_lists_tail[DETECT_SM_LIST_HUADMATCH] || - s->sm_lists_tail[DETECT_SM_LIST_HHHDMATCH]) + s->sm_lists_tail[DETECT_SM_LIST_HHHDMATCH] || + s->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH]) { SCLogError(SC_ERR_INVALID_SIGNATURE, "Signature combines packet " "specific matches (like dsize, flags, ttl) with stream / " @@ -1287,6 +1289,8 @@ static Signature *SigInitHelper(DetectEngineCtx *de_ctx, char *sigstr, sig->flags |= SIG_FLAG_STATE_MATCH; if (sig->sm_lists[DETECT_SM_LIST_HHHDMATCH]) sig->flags |= SIG_FLAG_STATE_MATCH; + if (sig->sm_lists[DETECT_SM_LIST_HRHHDMATCH]) + sig->flags |= SIG_FLAG_STATE_MATCH; if (!(sig->init_flags & SIG_FLAG_INIT_FLOW)) { sig->flags |= SIG_FLAG_TOSERVER; diff --git a/src/detect-pcre.c b/src/detect-pcre.c index c74be7f00a..beb8248ece 100644 --- a/src/detect-pcre.c +++ b/src/detect-pcre.c @@ -393,6 +393,13 @@ DetectPcreData *DetectPcreParse (DetectEngineCtx *de_ctx, char *regexstr) } pd->flags |= DETECT_PCRE_HTTP_HOST; break; + case 'Z': + if (pd->flags & DETECT_PCRE_RAWBYTES) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "regex modifier 'Z' inconsistent with 'B'"); + goto error; + } + pd->flags |= DETECT_PCRE_HTTP_RAW_HOST; + break; case 'H': /* snort's option */ if (pd->flags & DETECT_PCRE_RAW_HEADER) { SCLogError(SC_ERR_INVALID_SIGNATURE, "regex modifier 'H' inconsistent with 'D'"); @@ -645,7 +652,8 @@ static int DetectPcreSetup (DetectEngineCtx *de_ctx, Signature *s, char *regexst (pd->flags & DETECT_PCRE_HTTP_SERVER_BODY) || (pd->flags & DETECT_PCRE_HTTP_RAW_URI) || (pd->flags & DETECT_PCRE_HTTP_USER_AGENT) || - (pd->flags & DETECT_PCRE_HTTP_HOST) ) { + (pd->flags & DETECT_PCRE_HTTP_HOST) || + (pd->flags & DETECT_PCRE_HTTP_RAW_HOST) ) { SCLogError(SC_ERR_CONFLICTING_RULE_KEYWORDS, "Invalid option. " "DCERPC rule has pcre keyword with http related modifier."); goto error; @@ -709,6 +717,17 @@ static int DetectPcreSetup (DetectEngineCtx *de_ctx, Signature *s, char *regexst s->alproto = ALPROTO_HTTP; SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_HHHDMATCH); + } else if (pd->flags & DETECT_PCRE_HTTP_RAW_HOST) { + SCLogDebug("Raw Host inspection modifier set on pcre"); + if (s->alproto != ALPROTO_UNKNOWN && s->alproto != ALPROTO_HTTP) { + SCLogError(SC_ERR_CONFLICTING_RULE_KEYWORDS, "rule contains " + "conflicting keywords."); + goto error; + } + s->flags |= SIG_FLAG_APPLAYER; + s->alproto = ALPROTO_HTTP; + + SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_HRHHDMATCH); } else if (pd->flags & DETECT_PCRE_METHOD) { //sm->type = DETECT_PCRE_HTTPMETHOD; @@ -943,7 +962,7 @@ static int DetectPcreParseTest02 (void) { static int DetectPcreParseTest03 (void) { int result = 1; DetectPcreData *pd = NULL; - char *teststring = "/blah/UZi"; + char *teststring = "/blah/UNi"; DetectEngineCtx *de_ctx = DetectEngineCtxInit(); if (de_ctx == NULL) return 0; diff --git a/src/detect-pcre.h b/src/detect-pcre.h index 92d3f11648..986ca0a3d5 100644 --- a/src/detect-pcre.h +++ b/src/detect-pcre.h @@ -47,10 +47,10 @@ #define DETECT_PCRE_HTTP_STAT_CODE 0x08000 #define DETECT_PCRE_HTTP_USER_AGENT 0x10000 #define DETECT_PCRE_HTTP_HOST 0x20000 +#define DETECT_PCRE_HTTP_RAW_HOST 0x40000 - -#define DETECT_PCRE_NEGATE 0x40000 -#define DETECT_PCRE_CASELESS 0x80000 +#define DETECT_PCRE_NEGATE 0x80000 +#define DETECT_PCRE_CASELESS 0x100000 typedef struct DetectPcreData_ { /* pcre options */ diff --git a/src/detect-within.c b/src/detect-within.c index cdb8ed339a..c609ab9da5 100644 --- a/src/detect-within.c +++ b/src/detect-within.c @@ -165,7 +165,7 @@ static int DetectWithinSetup (DetectEngineCtx *de_ctx, Signature *s, char *withi } } } else { - pm = SigMatchGetLastSMFromLists(s, 26, + pm = SigMatchGetLastSMFromLists(s, 28, DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_PMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_UMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HCBDMATCH], @@ -178,14 +178,15 @@ static int DetectWithinSetup (DetectEngineCtx *de_ctx, Signature *s, char *withi DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HSCDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HRUDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HUADMATCH], - DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HHHDMATCH]); + DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HHHDMATCH], + DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH]); if (pm == NULL) { SCLogError(SC_ERR_WITHIN_MISSING_CONTENT, "\"within\" requires " "preceding content, uricontent, http_client_body, " "http_server_body, http_header, http_raw_header, " "http_method, http_cookie, http_raw_uri, " - "http_stat_msg, http_stat_code, http_user_agent or " - "http_host option"); + "http_stat_msg, http_stat_code, http_user_agent, " + "http_host or http_raw_host option"); if (dubbed) SCFree(str); return -1; diff --git a/src/detect.c b/src/detect.c index 7c8bc274d3..1aee82a8c7 100644 --- a/src/detect.c +++ b/src/detect.c @@ -53,6 +53,7 @@ #include "detect-http-method.h" #include "detect-http-ua.h" #include "detect-http-hh.h" +#include "detect-http-hrh.h" #include "detect-engine-event.h" #include "decode.h" @@ -138,6 +139,7 @@ #include "detect-engine-hscd.h" #include "detect-engine-hua.h" #include "detect-engine-hhhd.h" +#include "detect-engine-hrhhd.h" #include "detect-byte-extract.h" #include "detect-file-data.h" #include "detect-pkt-data.h" @@ -1019,6 +1021,11 @@ static inline void DetectMpmPrefilter(DetectEngineCtx *de_ctx, DetectEngineRunHttpHHMpm(det_ctx, p->flow, alstate, flags); PACKET_PROFILING_DETECT_END(p, PROF_DETECT_MPM_HHHD); } + if (det_ctx->sgh->flags & SIG_GROUP_HEAD_MPM_HRHHD) { + PACKET_PROFILING_DETECT_START(p, PROF_DETECT_MPM_HRHHD); + DetectEngineRunHttpHRHMpm(det_ctx, p->flow, alstate, flags); + PACKET_PROFILING_DETECT_END(p, PROF_DETECT_MPM_HRHHD); + } } else { /* implied FLOW_PKT_TOCLIENT */ if ((p->flowflags & FLOW_PKT_TOCLIENT) && (det_ctx->sgh->flags & SIG_GROUP_HEAD_MPM_HSBD)) { PACKET_PROFILING_DETECT_START(p, PROF_DETECT_MPM_HSBD); @@ -1973,6 +1980,9 @@ int SignatureIsIPOnly(DetectEngineCtx *de_ctx, Signature *s) { if (s->sm_lists[DETECT_SM_LIST_HHHDMATCH] != NULL) return 0; + if (s->sm_lists[DETECT_SM_LIST_HRHHDMATCH] != NULL) + return 0; + if (s->sm_lists[DETECT_SM_LIST_AMATCH] != NULL) return 0; @@ -2071,7 +2081,8 @@ static int SignatureIsDEOnly(DetectEngineCtx *de_ctx, Signature *s) { s->sm_lists[DETECT_SM_LIST_HSCDMATCH] != NULL || s->sm_lists[DETECT_SM_LIST_HRUDMATCH] != NULL || s->sm_lists[DETECT_SM_LIST_HUADMATCH] != NULL || - s->sm_lists[DETECT_SM_LIST_HHHDMATCH] != NULL) + s->sm_lists[DETECT_SM_LIST_HHHDMATCH] != NULL || + s->sm_lists[DETECT_SM_LIST_HRHHDMATCH] != NULL) { SCReturnInt(0); } @@ -2239,6 +2250,11 @@ static int SignatureCreateMask(Signature *s) { SCLogDebug("sig requires http app state"); } + if (s->sm_lists[DETECT_SM_LIST_HRHHDMATCH] != NULL) { + s->mask |= SIG_MASK_REQUIRE_HTTP_STATE; + SCLogDebug("sig requires http app state"); + } + SigMatch *sm; for (sm = s->sm_lists[DETECT_SM_LIST_AMATCH] ; sm != NULL; sm = sm->next) { switch(sm->type) { @@ -2408,6 +2424,9 @@ static void SigInitStandardMpmFactoryContexts(DetectEngineCtx *de_ctx) de_ctx->sgh_mpm_context_hhhd = MpmFactoryRegisterMpmCtxProfile(de_ctx, "hhhd", MPM_CTX_FACTORY_FLAGS_PREPARE_WITH_SIG_GROUP_BUILD); + de_ctx->sgh_mpm_context_hrhhd = + MpmFactoryRegisterMpmCtxProfile(de_ctx, "hrhhd", + MPM_CTX_FACTORY_FLAGS_PREPARE_WITH_SIG_GROUP_BUILD); de_ctx->sgh_mpm_context_app_proto_detect = MpmFactoryRegisterMpmCtxProfile(de_ctx, "app_proto_detect", 0); @@ -4598,6 +4617,18 @@ int SigGroupBuild (DetectEngineCtx *de_ctx) { mpm_table[de_ctx->mpm_matcher].Prepare(mpm_ctx); } //printf("hhhd- %d\n", mpm_ctx->pattern_cnt); + + mpm_ctx = MpmFactoryGetMpmCtxForProfile(de_ctx, de_ctx->sgh_mpm_context_hrhhd, 0); + if (mpm_table[de_ctx->mpm_matcher].Prepare != NULL) { + mpm_table[de_ctx->mpm_matcher].Prepare(mpm_ctx); + } + //printf("hrhhd- %d\n", mpm_ctx->pattern_cnt); + + mpm_ctx = MpmFactoryGetMpmCtxForProfile(de_ctx, de_ctx->sgh_mpm_context_hrhhd, 1); + if (mpm_table[de_ctx->mpm_matcher].Prepare != NULL) { + mpm_table[de_ctx->mpm_matcher].Prepare(mpm_ctx); + } + //printf("hrhhd- %d\n", mpm_ctx->pattern_cnt); } // SigAddressPrepareStage5(de_ctx); @@ -4815,6 +4846,7 @@ void SigTableSetup(void) { DetectAppLayerEventRegister(); DetectHttpUARegister(); DetectHttpHHRegister(); + DetectHttpHRHRegister(); DetectLuajitRegister(); DetectIPRepRegister(); diff --git a/src/detect.h b/src/detect.h index e3c3c3fd52..41a5da82d5 100644 --- a/src/detect.h +++ b/src/detect.h @@ -109,6 +109,8 @@ enum { DETECT_SM_LIST_HUADMATCH, /* list for http_host keyword and the ones relative to it */ DETECT_SM_LIST_HHHDMATCH, + /* list for http_raw_host keyword and the ones relative to it */ + DETECT_SM_LIST_HRHHDMATCH, DETECT_SM_LIST_FILEMATCH, @@ -673,6 +675,7 @@ typedef struct DetectEngineCtx_ { int32_t sgh_mpm_context_hscd; int32_t sgh_mpm_context_huad; int32_t sgh_mpm_context_hhhd; + int32_t sgh_mpm_context_hrhhd; int32_t sgh_mpm_context_app_proto_detect; /* the max local id used amongst all sigs */ @@ -888,8 +891,9 @@ typedef struct SigTableElmt_ { #define SIG_GROUP_HEAD_MPM_HSCD (1 << 17) #define SIG_GROUP_HEAD_MPM_HUAD (1 << 18) #define SIG_GROUP_HEAD_MPM_HHHD (1 << 19) -#define SIG_GROUP_HEAD_HAVEFILEMD5 (1 << 20) -#define SIG_GROUP_HEAD_HAVEFILESIZE (1 << 21) +#define SIG_GROUP_HEAD_MPM_HRHHD (1 << 20) +#define SIG_GROUP_HEAD_HAVEFILEMD5 (1 << 21) +#define SIG_GROUP_HEAD_HAVEFILESIZE (1 << 22) typedef struct SigGroupHeadInitData_ { /* list of content containers @@ -949,6 +953,7 @@ typedef struct SigGroupHead_ { MpmCtx *mpm_hscd_ctx_ts; MpmCtx *mpm_huad_ctx_ts; MpmCtx *mpm_hhhd_ctx_ts; + MpmCtx *mpm_hrhhd_ctx_ts; MpmCtx *mpm_proto_tcp_ctx_tc; MpmCtx *mpm_proto_udp_ctx_tc; @@ -965,6 +970,7 @@ typedef struct SigGroupHead_ { MpmCtx *mpm_hscd_ctx_tc; MpmCtx *mpm_huad_ctx_tc; MpmCtx *mpm_hhhd_ctx_tc; + MpmCtx *mpm_hrhhd_ctx_tc; uint16_t mpm_uricontent_maxlen; @@ -1076,6 +1082,7 @@ enum { DETECT_AL_HTTP_STAT_CODE, DETECT_AL_HTTP_USER_AGENT, DETECT_AL_HTTP_HOST, + DETECT_AL_HTTP_RAW_HOST, DETECT_AL_SSH_PROTOVERSION, DETECT_AL_SSH_SOFTWAREVERSION, DETECT_AL_SSL_VERSION, diff --git a/src/suricata-common.h b/src/suricata-common.h index 5e07d9cb47..04543e1539 100644 --- a/src/suricata-common.h +++ b/src/suricata-common.h @@ -282,6 +282,7 @@ typedef enum PacketProfileDetectId_ { PROF_DETECT_MPM_HSCD, PROF_DETECT_MPM_HUAD, PROF_DETECT_MPM_HHHD, + PROF_DETECT_MPM_HRHHD, PROF_DETECT_IPONLY, PROF_DETECT_RULES, PROF_DETECT_STATEFUL, diff --git a/src/suricata.c b/src/suricata.c index 7d7d05ef83..660d278886 100644 --- a/src/suricata.c +++ b/src/suricata.c @@ -80,6 +80,7 @@ #include "detect-engine-hscd.h" #include "detect-engine-hua.h" #include "detect-engine-hhhd.h" +#include "detect-engine-hrhhd.h" #include "detect-engine-state.h" #include "detect-engine-tag.h" #include "detect-fast-pattern.h" @@ -1692,6 +1693,7 @@ int main(int argc, char **argv) DetectEngineHttpStatCodeRegisterTests(); DetectEngineHttpUARegisterTests(); DetectEngineHttpHHRegisterTests(); + DetectEngineHttpHRHRegisterTests(); DetectEngineRegisterTests(); SCLogRegisterTests(); SMTPParserRegisterTests();