diff --git a/src/Makefile.am b/src/Makefile.am index 2b473e2bb2..a1956a5f28 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -67,6 +67,7 @@ detect-engine-hcbd.c detect-engine-hcbd.h \ detect-engine-hhd.c detect-engine-hhd.h \ detect-engine-hrhd.c detect-engine-hrhd.h \ detect-engine-hmd.c detect-engine-hmd.h \ +detect-engine-hcd.c detect-engine-hcd.h \ detect-engine-state.c detect-engine-state.h \ detect-parse.c detect-parse.h \ detect-ack.c detect-ack.h \ diff --git a/src/detect-content.h b/src/detect-content.h index 7b55985c72..5e1dd55ab3 100644 --- a/src/detect-content.h +++ b/src/detect-content.h @@ -49,6 +49,7 @@ #define DETECT_CONTENT_HHD_MPM 0x00008000 #define DETECT_CONTENT_HRHD_MPM 0x00010000 #define DETECT_CONTENT_HMD_MPM 0x00020000 +#define DETECT_CONTENT_HCD_MPM 0x00040000 #define DETECT_CONTENT_IS_SINGLE(c) (!((c)->flags & DETECT_CONTENT_DISTANCE || \ (c)->flags & DETECT_CONTENT_WITHIN || \ diff --git a/src/detect-depth.c b/src/detect-depth.c index 6b6ebc05f9..d55fd5630e 100644 --- a/src/detect-depth.c +++ b/src/detect-depth.c @@ -85,18 +85,19 @@ static int DetectDepthSetup (DetectEngineCtx *de_ctx, Signature *s, char *depths break; default: - pm = SigMatchGetLastSMFromLists(s, 12, + pm = SigMatchGetLastSMFromLists(s, 14, DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_PMATCH], DETECT_URICONTENT, s->sm_lists_tail[DETECT_SM_LIST_UMATCH], DETECT_AL_HTTP_CLIENT_BODY, s->sm_lists_tail[DETECT_SM_LIST_HCBDMATCH], DETECT_AL_HTTP_HEADER, s->sm_lists_tail[DETECT_SM_LIST_HHDMATCH], DETECT_AL_HTTP_RAW_HEADER, s->sm_lists_tail[DETECT_SM_LIST_HRHDMATCH], - DETECT_AL_HTTP_METHOD, s->sm_lists_tail[DETECT_SM_LIST_HMDMATCH]); + DETECT_AL_HTTP_METHOD, s->sm_lists_tail[DETECT_SM_LIST_HMDMATCH], + DETECT_AL_HTTP_COOKIE, s->sm_lists_tail[DETECT_SM_LIST_HCDMATCH]); if (pm == NULL) { SCLogError(SC_ERR_DEPTH_MISSING_CONTENT, "depth needs " "preceeding content, uricontent option, http_client_body, " "http_header option, http_raw_header option or " - "http_method option"); + "http_method option or http_cookie option"); if (dubbed) SCFree(str); return -1; @@ -287,6 +288,34 @@ static int DetectDepthSetup (DetectEngineCtx *de_ctx, Signature *s, char *depths break; + case DETECT_AL_HTTP_COOKIE: + cd = (DetectContentData *)pm->ctx; + if (cd->flags & DETECT_CONTENT_NEGATED) { + if (cd->flags & DETECT_CONTENT_FAST_PATTERN) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "You can't have a relative " + "negated keyword set along with a fast_pattern"); + goto error; + } + } else { + if (cd->flags & DETECT_CONTENT_FAST_PATTERN_ONLY) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "You can't have a relative " + "keyword set along with a fast_pattern:only;"); + goto error; + } + } + + cd->depth = (uint32_t)atoi(str); + if (cd->depth < cd->content_len) { + cd->depth = cd->content_len; + SCLogDebug("depth increased to %"PRIu32" to match pattern len ", + cd->depth); + } + /* Now update the real limit, as depth is relative to the offset */ + cd->depth += cd->offset; + cd->flags |= DETECT_CONTENT_DEPTH; + + break; + default: SCLogError(SC_ERR_DEPTH_MISSING_CONTENT, "depth needs a preceeding " "content (or uricontent) option"); diff --git a/src/detect-distance.c b/src/detect-distance.c index 63d7b305f8..6491b01ded 100644 --- a/src/detect-distance.c +++ b/src/detect-distance.c @@ -168,17 +168,19 @@ static int DetectDistanceSetup (DetectEngineCtx *de_ctx, Signature *s, } } } else { - pm = SigMatchGetLastSMFromLists(s, 12, + pm = SigMatchGetLastSMFromLists(s, 14, DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_PMATCH], DETECT_URICONTENT, s->sm_lists_tail[DETECT_SM_LIST_UMATCH], DETECT_AL_HTTP_CLIENT_BODY, s->sm_lists_tail[DETECT_SM_LIST_HCBDMATCH], DETECT_AL_HTTP_HEADER, s->sm_lists_tail[DETECT_SM_LIST_HHDMATCH], DETECT_AL_HTTP_RAW_HEADER, s->sm_lists_tail[DETECT_SM_LIST_HRHDMATCH], - DETECT_AL_HTTP_METHOD, s->sm_lists_tail[DETECT_SM_LIST_HMDMATCH]); + DETECT_AL_HTTP_METHOD, s->sm_lists_tail[DETECT_SM_LIST_HMDMATCH], + DETECT_AL_HTTP_COOKIE, s->sm_lists_tail[DETECT_SM_LIST_HCDMATCH]); if (pm == NULL) { SCLogError(SC_ERR_WITHIN_MISSING_CONTENT, "within needs" "preceeding content, uricontent option, http_client_body, " - "http_header, http_raw_header or http_method option"); + "http_header, http_raw_header or http_method or " + "http_cookie option"); if (dubbed) SCFree(str); return -1; @@ -583,6 +585,59 @@ static int DetectDistanceSetup (DetectEngineCtx *de_ctx, Signature *s, break; + case DETECT_AL_HTTP_COOKIE: + cd = (DetectContentData *)pm->ctx; + if (cd->flags & DETECT_CONTENT_NEGATED) { + if (cd->flags & DETECT_CONTENT_FAST_PATTERN) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "You can't have a relative " + "negated keyword set along with a fast_pattern"); + goto error; + } + } else { + if (cd->flags & DETECT_CONTENT_FAST_PATTERN_ONLY) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "You can't have a relative " + "keyword set along with a fast_pattern:only;"); + goto error; + } + } + + cd->distance = strtol(str, NULL, 10); + if (cd->flags & DETECT_CONTENT_WITHIN) { + if ((cd->distance + cd->content_len) > cd->within) { + cd->within = cd->distance + cd->content_len; + } + } + cd->flags |= DETECT_CONTENT_DISTANCE; + + /* reassigning pm */ + pm = SigMatchGetLastSMFromLists(s, 4, + DETECT_AL_HTTP_COOKIE, pm->prev, + DETECT_PCRE, pm->prev); + if (pm == NULL) { + SCLogError(SC_ERR_DISTANCE_MISSING_CONTENT, "distance for " + "http_cookie needs preceeding http_cookie " + "content"); + goto error; + } + + if (pm->type == DETECT_PCRE) { + DetectPcreData *tmp_pd = (DetectPcreData *)pm->ctx; + tmp_pd->flags |= DETECT_PCRE_RELATIVE_NEXT; + } else { + /* reassigning cd */ + cd = (DetectContentData *)pm->ctx; + if (cd->flags & DETECT_CONTENT_FAST_PATTERN_ONLY) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "Previous keyword " + "has a fast_pattern:only; set. You can't " + "have relative keywords around a fast_pattern " + "only content"); + goto error; + } + cd->flags |= DETECT_CONTENT_RELATIVE_NEXT; + } + + break; + default: SCLogError(SC_ERR_DISTANCE_MISSING_CONTENT, "distance needs two " "preceeding content or uricontent options"); diff --git a/src/detect-engine-hcd.c b/src/detect-engine-hcd.c new file mode 100644 index 0000000000..b0e484cf98 --- /dev/null +++ b/src/detect-engine-hcd.c @@ -0,0 +1,2059 @@ +/* Copyright (C) 2007-2010 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 + */ + +#include "suricata-common.h" +#include "suricata.h" +#include "decode.h" + +#include "detect.h" +#include "detect-engine.h" +#include "detect-engine-hcd.h" +#include "detect-engine-mpm.h" +#include "detect-parse.h" +#include "detect-engine-state.h" +#include "detect-pcre.h" +#include "detect-isdataat.h" +#include "detect-bytetest.h" +#include "detect-bytejump.h" + +#include "flow-util.h" +#include "util-spm.h" +#include "util-debug.h" +#include "util-print.h" +#include "flow.h" +#include "detect-flow.h" +#include "flow-var.h" +#include "threads.h" +#include "flow-alert-sid.h" + +#include "stream-tcp.h" +#include "stream.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" + +/** + * \brief Run the actual payload match function for http cookie. + * + * For accounting the last match in relative matching the + * det_ctx->payload_offset var is used. + * + * \param de_ctx Detection engine context. + * \param det_ctx Detection engine thread context. + * \param s Signature to inspect. + * \param sm SigMatch to inspect. + * \param payload Ptr to the http cookie buffer to inspect. + * \param payload_len Length of the http cookie buffer. + * + * \retval 0 no match. + * \retval 1 match. + */ +static int DoInspectHttpCookie(DetectEngineCtx *de_ctx, + DetectEngineThreadCtx *det_ctx, + Signature *s, SigMatch *sm, + uint8_t *payload, uint32_t payload_len) +{ + SCEnter(); + + det_ctx->inspection_recursion_counter++; + + if (det_ctx->inspection_recursion_counter == de_ctx->inspection_recursion_limit) { + det_ctx->discontinue_matching = 1; + SCReturnInt(0); + } + + if (sm == NULL) { + SCReturnInt(0); + } + + if (sm->type == DETECT_AL_HTTP_COOKIE) { + if (payload_len == 0) { + SCReturnInt(0); + } + + DetectContentData *cd = (DetectContentData *)sm->ctx; + SCLogDebug("inspecting http cookie %"PRIu32" payload_len %"PRIu32, + cd->id, payload_len); + + if (cd->flags & DETECT_CONTENT_HCD_MPM && !(cd->flags & DETECT_CONTENT_NEGATED)) + goto match; + + /* rule parsers should take care of this */ + BUG_ON(cd->depth != 0 && cd->depth <= cd->offset); + + /* search for our pattern, checking the matches recursively. + * if we match we look for the next SigMatch as well */ + uint8_t *found = NULL; + uint32_t offset = 0; + uint32_t depth = payload_len; + uint32_t prev_offset = 0; /**< used in recursive searching */ + uint32_t prev_payload_offset = det_ctx->payload_offset; + + do { + if (cd->flags & DETECT_CONTENT_DISTANCE || + cd->flags & DETECT_CONTENT_WITHIN) { + SCLogDebug("prev_payload_offset %"PRIu32, prev_payload_offset); + + offset = prev_payload_offset; + depth = payload_len; + + if (cd->flags & DETECT_CONTENT_DISTANCE) { + if (cd->distance < 0 && (uint32_t)(abs(cd->distance)) > offset) + offset = 0; + else + offset += cd->distance; + } + + if (cd->flags & DETECT_CONTENT_WITHIN) { + if ((int32_t)depth > (int32_t)(prev_payload_offset + cd->within)) { + depth = prev_payload_offset + cd->within; + } + } + + if (cd->depth != 0) { + if ((cd->depth + prev_payload_offset) < depth) { + depth = prev_payload_offset + cd->depth; + } + } + + if (cd->offset > offset) { + offset = cd->offset; + } + } else { /* implied no relative matches */ + /* set depth */ + if (cd->depth != 0) { + depth = cd->depth; + } + + /* set offset */ + offset = cd->offset; + prev_payload_offset = 0; + } + + /* update offset with prev_offset if we're searching for + * matches after the first occurence. */ + if (prev_offset != 0) + offset = prev_offset; + + if (depth > payload_len) + depth = payload_len; + + /* if offset is bigger than depth we can never match on a pattern. + * We can however, "match" on a negated pattern. */ + if (offset > depth || depth == 0) { + if (cd->flags & DETECT_CONTENT_NEGATED) { + goto match; + } else { + SCReturnInt(0); + } + } + + uint8_t *spayload = payload + offset; + uint32_t spayload_len = depth - offset; + uint32_t match_offset = 0; + BUG_ON(spayload_len > payload_len); + + /* do the actual search with boyer moore precooked ctx */ + if (cd->flags & DETECT_CONTENT_NOCASE) { + found = BoyerMooreNocase(cd->content, cd->content_len, + spayload, spayload_len, + cd->bm_ctx->bmGs, cd->bm_ctx->bmBc); + } else { + found = BoyerMoore(cd->content, cd->content_len, + spayload, spayload_len, + cd->bm_ctx->bmGs, cd->bm_ctx->bmBc); + } + + /* next we evaluate the result in combination with the + * negation flag. */ + if (found == NULL && !(cd->flags & DETECT_CONTENT_NEGATED)) { + SCReturnInt(0); + } else if (found == NULL && cd->flags & DETECT_CONTENT_NEGATED) { + goto match; + } else if (found != NULL && cd->flags & DETECT_CONTENT_NEGATED) { + det_ctx->discontinue_matching = 1; + SCReturnInt(0); + } else { + match_offset = (uint32_t)((found - payload) + cd->content_len); + det_ctx->payload_offset = match_offset; + + if (!(cd->flags & DETECT_CONTENT_RELATIVE_NEXT)) { + SCLogDebug("no relative match coming up, so this is a match"); + goto match; + } + + /* bail out if we have no next match. Technically this is an + * error, as the current cd has the DETECT_CONTENT_RELATIVE_NEXT + * flag set. */ + if (sm->next == NULL) { + SCReturnInt(0); + } + + /* see if the next payload keywords match. If not, we will + * search for another occurence of this http cookie content + * and see if the others match then until we run out of matches */ + int r = DoInspectHttpCookie(de_ctx, det_ctx, s, sm->next, + payload, payload_len); + if (r == 1) { + SCReturnInt(1); + } + + if (det_ctx->discontinue_matching) + SCReturnInt(0); + + /* set the previous match offset to the start of this match + 1 */ + prev_offset = (match_offset - (cd->content_len - 1)); + SCLogDebug("trying to see if there is another match after " + "prev_offset %"PRIu32, prev_offset); + } + + } while(1); + + } else if (sm->type == DETECT_PCRE) { + SCLogDebug("inspecting pcre"); + DetectPcreData *pe = (DetectPcreData *)sm->ctx; + uint32_t prev_payload_offset = det_ctx->payload_offset; + uint32_t prev_offset = 0; + int r = 0; + + det_ctx->pcre_match_start_offset = 0; + do { + r = DetectPcrePayloadMatch(det_ctx, s, sm, NULL, NULL, + payload, payload_len); + + if (r == 0) { + det_ctx->discontinue_matching = 1; + SCReturnInt(0); + } + + if (!(pe->flags & DETECT_PCRE_RELATIVE_NEXT)) { + SCLogDebug("no relative match coming up, so this is a match"); + goto match; + } + + /* save it, in case we need to do a pcre match once again */ + prev_offset = det_ctx->pcre_match_start_offset; + + /* see if the next payload keywords match. If not, we will + * search for another occurence of this pcre and see + * if the others match, until we run out of matches */ + int r = DoInspectHttpCookie(de_ctx, det_ctx, s, sm->next, + payload, payload_len); + if (r == 1) { + SCReturnInt(1); + } + + if (det_ctx->discontinue_matching) + SCReturnInt(0); + + det_ctx->payload_offset = prev_payload_offset; + det_ctx->pcre_match_start_offset = prev_offset; + } while (1); + } else { + /* we should never get here, but bail out just in case */ + BUG_ON(1); + } + + SCReturnInt(0); + +match: + /* this sigmatch matched, inspect the next one. If it was the last, + * the payload portion of the signature matched. */ + if (sm->next != NULL) { + int r = DoInspectHttpCookie(de_ctx, det_ctx, s, sm->next, payload, + payload_len); + SCReturnInt(r); + } else { + SCReturnInt(1); + } +} + +int DetectEngineRunHttpCookieMpm(DetectEngineThreadCtx *det_ctx, Flow *f, + HtpState *htp_state) +{ + htp_tx_t *tx = NULL; + int i; + uint32_t cnt = 0; + size_t idx; + + /* we need to lock because the buffers are not actually true buffers + * but are ones that point to a buffer given by libhtp */ + SCMutexLock(&f->m); + + 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); + int list_size = list_size(htp_state->connp->conn->transactions) - idx; + for (i = 0; i < list_size; idx++, i++) { + + tx = list_get(htp_state->connp->conn->transactions, idx); + if (tx == NULL) + continue; + + htp_header_t *h = (htp_header_t *)table_getc(tx->request_headers, + "Cookie"); + if (h == NULL) { + SCLogDebug("HTTP cookie header not present in this request"); + goto end; + } + + cnt += HttpCookiePatternSearch(det_ctx, + (uint8_t *)bstr_ptr(h->value), + bstr_len(h->value)); + } + + end: + SCMutexUnlock(&f->m); + return cnt; +} + +/** + * \brief Do the http_cookie 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 DetectEngineInspectHttpCookie(DetectEngineCtx *de_ctx, + DetectEngineThreadCtx *det_ctx, + Signature *s, Flow *f, uint8_t flags, + void *alstate) +{ + SCEnter(); + int r = 0; + HtpState *htp_state = NULL; + htp_tx_t *tx = NULL; + int i = 0; + size_t idx; + + SCMutexLock(&f->m); + + htp_state = (HtpState *)alstate; + 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); + int list_size = list_size(htp_state->connp->conn->transactions) - idx; + for (i = 0; i < list_size; idx++, i++) { + tx = list_get(htp_state->connp->conn->transactions, idx); + if (tx == NULL) + continue; + + htp_header_t *h = (htp_header_t *)table_getc(tx->request_headers, + "Cookie"); + if (h == NULL) { + SCLogDebug("HTTP cookie header not present in this request"); + goto end; + } + + r = DoInspectHttpCookie(de_ctx, det_ctx, s, s->sm_lists[DETECT_SM_LIST_HCDMATCH], + (uint8_t *)bstr_ptr(h->value), + bstr_len(h->value)); + if (r == 1) { + break; + } + } + +end: + SCMutexUnlock(&f->m); + SCReturnInt(r); +} + +/***********************************Unittests**********************************/ + +#ifdef UNITTESTS + +/** + * \test Test that the http_cookie content matches against a http request + * which holds the content. + */ +static int DetectEngineHttpCookieTest01(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" + "Cookie: CONNECT\r\n" + "Host: 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.src.family = AF_INET; + f.dst.family = AF_INET; + p->flow = &f; + p->flowflags |= FLOW_PKT_TOSERVER; + p->flowflags |= FLOW_PKT_ESTABLISHED; + p->flags |= PKT_HAS_FLOW; + f.alproto = ALPROTO_HTTP; + + StreamTcpInitConfig(TRUE); + FlowL7DataPtrInit(&f); + + de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + + de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any " + "(msg:\"http header test\"; " + "content:\"CONNECT\"; http_cookie; " + "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(&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.aldata[AlpGetStateIdx(ALPROTO_HTTP)]; + 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); + + FlowL7DataPtrFree(&f); + StreamTcpFreeConfig(TRUE); + FLOW_DESTROY(&f); + UTHFreePackets(&p, 1); + return result; +} + +/** + * \test Test that the http_cookie content matches against a http request + * which holds the content. + */ +static int DetectEngineHttpCookieTest02(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[] = + "CONNECT /index.html HTTP/1.0\r\n" + "Cookie: CONNECT\r\n" + "Host: 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.src.family = AF_INET; + f.dst.family = AF_INET; + p->flow = &f; + p->flowflags |= FLOW_PKT_TOSERVER; + p->flowflags |= FLOW_PKT_ESTABLISHED; + p->flags |= PKT_HAS_FLOW; + f.alproto = ALPROTO_HTTP; + + StreamTcpInitConfig(TRUE); + FlowL7DataPtrInit(&f); + + de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + + de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any " + "(msg:\"http header test\"; " + "content:\"CO\"; depth:4; http_cookie; " + "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(&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.aldata[AlpGetStateIdx(ALPROTO_HTTP)]; + 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); + + FlowL7DataPtrFree(&f); + StreamTcpFreeConfig(TRUE); + FLOW_DESTROY(&f); + UTHFreePackets(&p, 1); + return result; +} + +/** + * \test Test that the http_cookie content matches against a http request + * which holds the content. + */ +static int DetectEngineHttpCookieTest03(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[] = + "CONNECT /index.html HTTP/1.0\r\n" + "Cookie: CONNECT\r\n" + "Host: 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.src.family = AF_INET; + f.dst.family = AF_INET; + p->flow = &f; + p->flowflags |= FLOW_PKT_TOSERVER; + p->flowflags |= FLOW_PKT_ESTABLISHED; + p->flags |= PKT_HAS_FLOW; + f.alproto = ALPROTO_HTTP; + + StreamTcpInitConfig(TRUE); + FlowL7DataPtrInit(&f); + + de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + + de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any " + "(msg:\"http header test\"; " + "content:!ECT; depth:4; http_cookie; " + "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(&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.aldata[AlpGetStateIdx(ALPROTO_HTTP)]; + 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); + + FlowL7DataPtrFree(&f); + StreamTcpFreeConfig(TRUE); + FLOW_DESTROY(&f); + UTHFreePackets(&p, 1); + return result; +} + +/** + * \test Test that the http_cookie content matches against a http request + * which holds the content. + */ +static int DetectEngineHttpCookieTest04(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[] = + "CONNECT /index.html HTTP/1.0\r\n" + "Cookie: CONNECT\r\n" + "Host: 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.src.family = AF_INET; + f.dst.family = AF_INET; + p->flow = &f; + p->flowflags |= FLOW_PKT_TOSERVER; + p->flowflags |= FLOW_PKT_ESTABLISHED; + p->flags |= PKT_HAS_FLOW; + f.alproto = ALPROTO_HTTP; + + StreamTcpInitConfig(TRUE); + FlowL7DataPtrInit(&f); + + de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + + de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any " + "(msg:\"http header test\"; " + "content:ECT; depth:4; http_cookie; " + "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(&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.aldata[AlpGetStateIdx(ALPROTO_HTTP)]; + 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); + + FlowL7DataPtrFree(&f); + StreamTcpFreeConfig(TRUE); + FLOW_DESTROY(&f); + UTHFreePackets(&p, 1); + return result; +} + +/** + * \test Test that the http_cookie content matches against a http request + * which holds the content. + */ +static int DetectEngineHttpCookieTest05(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[] = + "CONNECT /index.html HTTP/1.0\r\n" + "Cookie: CONNECT\r\n" + "Host: 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.src.family = AF_INET; + f.dst.family = AF_INET; + p->flow = &f; + p->flowflags |= FLOW_PKT_TOSERVER; + p->flowflags |= FLOW_PKT_ESTABLISHED; + p->flags |= PKT_HAS_FLOW; + f.alproto = ALPROTO_HTTP; + + StreamTcpInitConfig(TRUE); + FlowL7DataPtrInit(&f); + + de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + + de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any " + "(msg:\"http header test\"; " + "content:!CON; depth:4; http_cookie; " + "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(&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.aldata[AlpGetStateIdx(ALPROTO_HTTP)]; + 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); + + FlowL7DataPtrFree(&f); + StreamTcpFreeConfig(TRUE); + FLOW_DESTROY(&f); + UTHFreePackets(&p, 1); + return result; +} + +/** + * \test Test that the http_cookie content matches against a http request + * which holds the content. + */ +static int DetectEngineHttpCookieTest06(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[] = + "CONNECT /index.html HTTP/1.0\r\n" + "Cookie: CONNECT\r\n" + "Host: 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.src.family = AF_INET; + f.dst.family = AF_INET; + p->flow = &f; + p->flowflags |= FLOW_PKT_TOSERVER; + p->flowflags |= FLOW_PKT_ESTABLISHED; + p->flags |= PKT_HAS_FLOW; + f.alproto = ALPROTO_HTTP; + + StreamTcpInitConfig(TRUE); + FlowL7DataPtrInit(&f); + + de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + + de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any " + "(msg:\"http header test\"; " + "content:\"ECT\"; offset:3; http_cookie; " + "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(&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.aldata[AlpGetStateIdx(ALPROTO_HTTP)]; + 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); + + FlowL7DataPtrFree(&f); + StreamTcpFreeConfig(TRUE); + FLOW_DESTROY(&f); + UTHFreePackets(&p, 1); + return result; +} + +/** + * \test Test that the http_cookie content matches against a http request + * which holds the content. + */ +static int DetectEngineHttpCookieTest07(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[] = + "CONNECT /index.html HTTP/1.0\r\n" + "Cookie: CONNECT\r\n" + "Host: 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.src.family = AF_INET; + f.dst.family = AF_INET; + p->flow = &f; + p->flowflags |= FLOW_PKT_TOSERVER; + p->flowflags |= FLOW_PKT_ESTABLISHED; + p->flags |= PKT_HAS_FLOW; + f.alproto = ALPROTO_HTTP; + + StreamTcpInitConfig(TRUE); + FlowL7DataPtrInit(&f); + + de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + + de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any " + "(msg:\"http header test\"; " + "content:!CO; offset:3; http_cookie; " + "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(&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.aldata[AlpGetStateIdx(ALPROTO_HTTP)]; + 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); + + FlowL7DataPtrFree(&f); + StreamTcpFreeConfig(TRUE); + FLOW_DESTROY(&f); + UTHFreePackets(&p, 1); + return result; +} + +/** + * \test Test that the http_cookie content matches against a http request + * which holds the content. + */ +static int DetectEngineHttpCookieTest08(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[] = + "CONNECT /index.html HTTP/1.0\r\n" + "Cookie: CONNECT\r\n" + "Host: 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.src.family = AF_INET; + f.dst.family = AF_INET; + p->flow = &f; + p->flowflags |= FLOW_PKT_TOSERVER; + p->flowflags |= FLOW_PKT_ESTABLISHED; + p->flags |= PKT_HAS_FLOW; + f.alproto = ALPROTO_HTTP; + + StreamTcpInitConfig(TRUE); + FlowL7DataPtrInit(&f); + + de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + + de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any " + "(msg:\"http header test\"; " + "content:!ECT; offset:3; http_cookie; " + "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(&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.aldata[AlpGetStateIdx(ALPROTO_HTTP)]; + 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); + + FlowL7DataPtrFree(&f); + StreamTcpFreeConfig(TRUE); + FLOW_DESTROY(&f); + UTHFreePackets(&p, 1); + return result; +} + +/** + * \test Test that the http_cookie content matches against a http request + * which holds the content. + */ +static int DetectEngineHttpCookieTest09(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[] = + "CONNECT /index.html HTTP/1.0\r\n" + "Cookie: CONNECT\r\n" + "Host: 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.src.family = AF_INET; + f.dst.family = AF_INET; + p->flow = &f; + p->flowflags |= FLOW_PKT_TOSERVER; + p->flowflags |= FLOW_PKT_ESTABLISHED; + p->flags |= PKT_HAS_FLOW; + f.alproto = ALPROTO_HTTP; + + StreamTcpInitConfig(TRUE); + FlowL7DataPtrInit(&f); + + de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + + de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any " + "(msg:\"http header test\"; " + "content:CON; offset:3; http_cookie; " + "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(&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.aldata[AlpGetStateIdx(ALPROTO_HTTP)]; + 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); + + FlowL7DataPtrFree(&f); + StreamTcpFreeConfig(TRUE); + FLOW_DESTROY(&f); + UTHFreePackets(&p, 1); + return result; +} + +/** + * \test Test that the http_cookie content matches against a http request + * which holds the content. + */ +static int DetectEngineHttpCookieTest10(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[] = + "CONNECT /index.html HTTP/1.0\r\n" + "Cookie: CONNECT\r\n" + "Host: 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.src.family = AF_INET; + f.dst.family = AF_INET; + p->flow = &f; + p->flowflags |= FLOW_PKT_TOSERVER; + p->flowflags |= FLOW_PKT_ESTABLISHED; + p->flags |= PKT_HAS_FLOW; + f.alproto = ALPROTO_HTTP; + + StreamTcpInitConfig(TRUE); + FlowL7DataPtrInit(&f); + + de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + + de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any " + "(msg:\"http header test\"; " + "content:CO; http_cookie; " + "content:EC; within:4; http_cookie; " + "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(&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.aldata[AlpGetStateIdx(ALPROTO_HTTP)]; + 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); + + FlowL7DataPtrFree(&f); + StreamTcpFreeConfig(TRUE); + FLOW_DESTROY(&f); + UTHFreePackets(&p, 1); + return result; +} + +/** + * \test Test that the http_cookie content matches against a http request + * which holds the content. + */ +static int DetectEngineHttpCookieTest11(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[] = + "CONNECT /index.html HTTP/1.0\r\n" + "Cookie: CONNECT\r\n" + "Host: 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.src.family = AF_INET; + f.dst.family = AF_INET; + p->flow = &f; + p->flowflags |= FLOW_PKT_TOSERVER; + p->flowflags |= FLOW_PKT_ESTABLISHED; + p->flags |= PKT_HAS_FLOW; + f.alproto = ALPROTO_HTTP; + + StreamTcpInitConfig(TRUE); + FlowL7DataPtrInit(&f); + + de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + + de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any " + "(msg:\"http header test\"; " + "content:CO; http_cookie; " + "content:!EC; within:3; http_cookie; " + "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(&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.aldata[AlpGetStateIdx(ALPROTO_HTTP)]; + 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); + + FlowL7DataPtrFree(&f); + StreamTcpFreeConfig(TRUE); + FLOW_DESTROY(&f); + UTHFreePackets(&p, 1); + return result; +} + +/** + * \test Test that the http_cookie content matches against a http request + * which holds the content. + */ +static int DetectEngineHttpCookieTest12(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[] = + "CONNECT /index.html HTTP/1.0\r\n" + "Cookie: CONNECT\r\n" + "Host: 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.src.family = AF_INET; + f.dst.family = AF_INET; + p->flow = &f; + p->flowflags |= FLOW_PKT_TOSERVER; + p->flowflags |= FLOW_PKT_ESTABLISHED; + p->flags |= PKT_HAS_FLOW; + f.alproto = ALPROTO_HTTP; + + StreamTcpInitConfig(TRUE); + FlowL7DataPtrInit(&f); + + de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + + de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any " + "(msg:\"http header test\"; " + "content:CO; http_cookie; " + "content:EC; within:3; http_cookie; " + "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(&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.aldata[AlpGetStateIdx(ALPROTO_HTTP)]; + 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); + + FlowL7DataPtrFree(&f); + StreamTcpFreeConfig(TRUE); + FLOW_DESTROY(&f); + UTHFreePackets(&p, 1); + return result; +} + +/** + * \test Test that the http_cookie content matches against a http request + * which holds the content. + */ +static int DetectEngineHttpCookieTest13(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[] = + "CONNECT /index.html HTTP/1.0\r\n" + "Cookie: CONNECT\r\n" + "Host: 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.src.family = AF_INET; + f.dst.family = AF_INET; + p->flow = &f; + p->flowflags |= FLOW_PKT_TOSERVER; + p->flowflags |= FLOW_PKT_ESTABLISHED; + p->flags |= PKT_HAS_FLOW; + f.alproto = ALPROTO_HTTP; + + StreamTcpInitConfig(TRUE); + FlowL7DataPtrInit(&f); + + de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + + de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any " + "(msg:\"http header test\"; " + "content:CO; http_cookie; " + "content:!EC; within:4; http_cookie; " + "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(&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.aldata[AlpGetStateIdx(ALPROTO_HTTP)]; + 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); + + FlowL7DataPtrFree(&f); + StreamTcpFreeConfig(TRUE); + FLOW_DESTROY(&f); + UTHFreePackets(&p, 1); + return result; +} + +/** + * \test Test that the http_cookie content matches against a http request + * which holds the content. + */ +static int DetectEngineHttpCookieTest14(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[] = + "CONNECT /index.html HTTP/1.0\r\n" + "Cookie: CONNECT\r\n" + "Host: 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.src.family = AF_INET; + f.dst.family = AF_INET; + p->flow = &f; + p->flowflags |= FLOW_PKT_TOSERVER; + p->flowflags |= FLOW_PKT_ESTABLISHED; + p->flags |= PKT_HAS_FLOW; + f.alproto = ALPROTO_HTTP; + + StreamTcpInitConfig(TRUE); + FlowL7DataPtrInit(&f); + + de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + + de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any " + "(msg:\"http header test\"; " + "content:CO; http_cookie; " + "content:EC; distance:2; http_cookie; " + "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(&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.aldata[AlpGetStateIdx(ALPROTO_HTTP)]; + 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); + + FlowL7DataPtrFree(&f); + StreamTcpFreeConfig(TRUE); + FLOW_DESTROY(&f); + UTHFreePackets(&p, 1); + return result; +} + +/** + * \test Test that the http_cookie content matches against a http request + * which holds the content. + */ +static int DetectEngineHttpCookieTest15(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[] = + "CONNECT /index.html HTTP/1.0\r\n" + "Cookie: CONNECT\r\n" + "Host: 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.src.family = AF_INET; + f.dst.family = AF_INET; + p->flow = &f; + p->flowflags |= FLOW_PKT_TOSERVER; + p->flowflags |= FLOW_PKT_ESTABLISHED; + p->flags |= PKT_HAS_FLOW; + f.alproto = ALPROTO_HTTP; + + StreamTcpInitConfig(TRUE); + FlowL7DataPtrInit(&f); + + de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + + de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any " + "(msg:\"http header test\"; " + "content:CO; http_cookie; " + "content:!EC; distance:3; http_cookie; " + "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(&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.aldata[AlpGetStateIdx(ALPROTO_HTTP)]; + 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); + + FlowL7DataPtrFree(&f); + StreamTcpFreeConfig(TRUE); + FLOW_DESTROY(&f); + UTHFreePackets(&p, 1); + return result; +} + +/** + * \test Test that the http_cookie content matches against a http request + * which holds the content. + */ +static int DetectEngineHttpCookieTest16(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[] = + "CONNECT /index.html HTTP/1.0\r\n" + "Cookie: CONNECT\r\n" + "Host: 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.src.family = AF_INET; + f.dst.family = AF_INET; + p->flow = &f; + p->flowflags |= FLOW_PKT_TOSERVER; + p->flowflags |= FLOW_PKT_ESTABLISHED; + p->flags |= PKT_HAS_FLOW; + f.alproto = ALPROTO_HTTP; + + StreamTcpInitConfig(TRUE); + FlowL7DataPtrInit(&f); + + de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + + de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any " + "(msg:\"http header test\"; " + "content:CO; http_cookie; " + "content:EC; distance:3; http_cookie; " + "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(&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.aldata[AlpGetStateIdx(ALPROTO_HTTP)]; + 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); + + FlowL7DataPtrFree(&f); + StreamTcpFreeConfig(TRUE); + FLOW_DESTROY(&f); + UTHFreePackets(&p, 1); + return result; +} + +/** + * \test Test that the http_cookie content matches against a http request + * which holds the content. + */ +static int DetectEngineHttpCookieTest17(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[] = + "CONNECT /index.html HTTP/1.0\r\n" + "Cookie: CONNECT\r\n" + "Host: 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.src.family = AF_INET; + f.dst.family = AF_INET; + p->flow = &f; + p->flowflags |= FLOW_PKT_TOSERVER; + p->flowflags |= FLOW_PKT_ESTABLISHED; + p->flags |= PKT_HAS_FLOW; + f.alproto = ALPROTO_HTTP; + + StreamTcpInitConfig(TRUE); + FlowL7DataPtrInit(&f); + + de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + + de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any " + "(msg:\"http header test\"; " + "content:CO; http_cookie; " + "content:!EC; distance:2; http_cookie; " + "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(&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.aldata[AlpGetStateIdx(ALPROTO_HTTP)]; + 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); + + FlowL7DataPtrFree(&f); + StreamTcpFreeConfig(TRUE); + FLOW_DESTROY(&f); + UTHFreePackets(&p, 1); + return result; +} + +#endif /* UNITTESTS */ + +void DetectEngineHttpCookieRegisterTests(void) +{ + +#ifdef UNITTESTS + UtRegisterTest("DetectEngineHttpCookieTest01", + DetectEngineHttpCookieTest01, 1); + UtRegisterTest("DetectEngineHttpCookieTest02", + DetectEngineHttpCookieTest02, 1); + UtRegisterTest("DetectEngineHttpCookieTest03", + DetectEngineHttpCookieTest03, 1); + UtRegisterTest("DetectEngineHttpCookieTest04", + DetectEngineHttpCookieTest04, 1); + UtRegisterTest("DetectEngineHttpCookieTest05", + DetectEngineHttpCookieTest05, 1); + UtRegisterTest("DetectEngineHttpCookieTest06", + DetectEngineHttpCookieTest06, 1); + UtRegisterTest("DetectEngineHttpCookieTest07", + DetectEngineHttpCookieTest07, 1); + UtRegisterTest("DetectEngineHttpCookieTest08", + DetectEngineHttpCookieTest08, 1); + UtRegisterTest("DetectEngineHttpCookieTest09", + DetectEngineHttpCookieTest09, 1); + UtRegisterTest("DetectEngineHttpCookieTest10", + DetectEngineHttpCookieTest10, 1); + UtRegisterTest("DetectEngineHttpCookieTest11", + DetectEngineHttpCookieTest11, 1); + UtRegisterTest("DetectEngineHttpCookieTest12", + DetectEngineHttpCookieTest12, 1); + UtRegisterTest("DetectEngineHttpCookieTest13", + DetectEngineHttpCookieTest13, 1); + UtRegisterTest("DetectEngineHttpCookieTest14", + DetectEngineHttpCookieTest14, 1); + UtRegisterTest("DetectEngineHttpCookieTest15", + DetectEngineHttpCookieTest15, 1); + UtRegisterTest("DetectEngineHttpCookieTest16", + DetectEngineHttpCookieTest16, 1); + UtRegisterTest("DetectEngineHttpCookieTest17", + DetectEngineHttpCookieTest17, 1); +#endif /* UNITTESTS */ + + return; +} diff --git a/src/detect-engine-hcd.h b/src/detect-engine-hcd.h new file mode 100644 index 0000000000..fdd033f682 --- /dev/null +++ b/src/detect-engine-hcd.h @@ -0,0 +1,33 @@ +/* Copyright (C) 2007-2010 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_HCD_H__ +#define __DETECT_ENGINE_HCD_H__ + +#include "app-layer-htp.h" + +int DetectEngineInspectHttpCookie(DetectEngineCtx *, DetectEngineThreadCtx *, + Signature *, Flow *, uint8_t, void *); +int DetectEngineRunHttpCookieMpm(DetectEngineThreadCtx *, Flow *, HtpState *); +void DetectEngineHttpCookieRegisterTests(void); + +#endif /* __DETECT_ENGINE_HCD_H__ */ diff --git a/src/detect-engine-mpm.c b/src/detect-engine-mpm.c index c4fc886772..f3402baad2 100644 --- a/src/detect-engine-mpm.c +++ b/src/detect-engine-mpm.c @@ -356,6 +356,31 @@ uint32_t HttpMethodPatternSearch(DetectEngineThreadCtx *det_ctx, SCReturnUInt(ret); } +/** + * \brief Http cookie match -- searches for one pattern per signature. + * + * \param det_ctx Detection engine thread ctx. + * \param cookie Cookie to inspect. + * \param cookie_len Cookie length. + * + * \retval ret Number of matches. + */ +uint32_t HttpCookiePatternSearch(DetectEngineThreadCtx *det_ctx, + uint8_t *cookie, uint32_t cookie_len) +{ + SCEnter(); + + if (det_ctx->sgh->mpm_hcd_ctx == NULL) + SCReturnUInt(0); + + uint32_t ret; + ret = mpm_table[det_ctx->sgh->mpm_hcd_ctx->mpm_type]. + Search(det_ctx->sgh->mpm_hcd_ctx, &det_ctx->mtcu, + &det_ctx->pmq, cookie, cookie_len); + + SCReturnUInt(ret); +} + /** \brief Pattern match -- searches for only one pattern per signature. * * \param det_ctx detection engine thread ctx @@ -653,6 +678,7 @@ static void PopulateMpmAddPatternToMpm(DetectEngineCtx *de_ctx, DetectContentData *hhd = NULL; DetectContentData *hrhd = NULL; DetectContentData *hmd = NULL; + DetectContentData *hcd = NULL; switch (mpm_sm->type) { case DETECT_CONTENT: { @@ -1043,7 +1069,7 @@ static void PopulateMpmAddPatternToMpm(DetectEngineCtx *de_ctx, 0, 0, hmd->id, s->num, flags); } } - /* tell matcher we are inspecting uri */ + /* tell matcher we are inspecting method */ s->flags |= SIG_FLAG_MPM_HMDCONTENT; s->mpm_http_pattern_id = hmd->id; if (hmd->flags & DETECT_CONTENT_NEGATED) @@ -1054,6 +1080,61 @@ static void PopulateMpmAddPatternToMpm(DetectEngineCtx *de_ctx, break; } /* case DETECT_AL_HTTP_METHOD */ + case DETECT_AL_HTTP_COOKIE: + { + hcd = (DetectContentData *)mpm_sm->ctx; + if (hcd->flags & DETECT_CONTENT_FAST_PATTERN_CHOP) { + /* add the content to the "hcd" mpm */ + if (hcd->flags & DETECT_CONTENT_NOCASE) { + mpm_table[sgh->mpm_hcd_ctx->mpm_type]. + AddPatternNocase(sgh->mpm_hcd_ctx, + hcd->content + hcd->fp_chop_offset, + hcd->fp_chop_len, + 0, 0, hcd->id, s->num, flags); + } else { + mpm_table[sgh->mpm_hcd_ctx->mpm_type]. + AddPattern(sgh->mpm_hcd_ctx, + hcd->content + hcd->fp_chop_offset, + hcd->fp_chop_len, + 0, 0, hcd->id, s->num, flags); + } + } else { + if (hcd->flags & DETECT_CONTENT_FAST_PATTERN_ONLY) { + if (DETECT_CONTENT_IS_SINGLE(hcd)) { + hcd->flags |= DETECT_CONTENT_HCD_MPM; + } + + /* see if we can bypass the match validation for this pattern */ + } else { + if (DETECT_CONTENT_IS_SINGLE(hcd)) { + hcd->flags |= DETECT_CONTENT_HCD_MPM; + } + } /* else - if (hcd->flags & DETECT_CONTENT_FAST_PATTERN_ONLY) */ + + /* add the content to the "hcd" mpm */ + if (hcd->flags & DETECT_CONTENT_NOCASE) { + mpm_table[sgh->mpm_hcd_ctx->mpm_type]. + AddPatternNocase(sgh->mpm_hcd_ctx, + hcd->content, hcd->content_len, + 0, 0, hcd->id, s->num, flags); + } else { + mpm_table[sgh->mpm_hcd_ctx->mpm_type]. + AddPattern(sgh->mpm_hcd_ctx, + hcd->content, hcd->content_len, + 0, 0, hcd->id, s->num, flags); + } + } + /* tell matcher we are inspecting cookie */ + s->flags |= SIG_FLAG_MPM_HCDCONTENT; + s->mpm_http_pattern_id = hcd->id; + if (hcd->flags & DETECT_CONTENT_NEGATED) + s->flags |= SIG_FLAG_MPM_HCDCONTENT_NEG; + + sgh->flags |= SIG_GROUP_HEAD_MPM_HCD; + + break; + } /* case DETECT_AL_HTTP_COOKIE */ + } /* switch (mpm_sm->type) */ SCLogDebug("%"PRIu32" adding cd->id %"PRIu32" to the mpm phase " @@ -1353,6 +1434,8 @@ int PatternMatchPrepareGroup(DetectEngineCtx *de_ctx, SigGroupHead *sh) uint32_t has_co_hrhd = 0; /* used to indicate if sgh has atleast one sig with http_method */ uint32_t has_co_hmd = 0; + /* used to indicate if sgh has atleast one sig with http_cookie */ + uint32_t has_co_hcd = 0; //uint32_t cnt = 0; uint32_t sig = 0; @@ -1390,6 +1473,10 @@ int PatternMatchPrepareGroup(DetectEngineCtx *de_ctx, SigGroupHead *sh) if (s->sm_lists[DETECT_SM_LIST_HMDMATCH] != NULL) { has_co_hmd = 1; } + + if (s->sm_lists[DETECT_SM_LIST_HCDMATCH] != NULL) { + has_co_hcd = 1; + } } if (has_co_packet > 0) { @@ -1413,6 +1500,9 @@ int PatternMatchPrepareGroup(DetectEngineCtx *de_ctx, SigGroupHead *sh) if (has_co_hmd > 0) { sh->flags |= SIG_GROUP_HAVEHMDCONTENT; } + if (has_co_hcd > 0) { + sh->flags |= SIG_GROUP_HAVEHCDCONTENT; + } /* intialize contexes */ if (sh->flags & SIG_GROUP_HAVECONTENT) { @@ -1541,13 +1631,32 @@ int PatternMatchPrepareGroup(DetectEngineCtx *de_ctx, SigGroupHead *sh) #endif } + if (sh->flags & SIG_GROUP_HAVEHCDCONTENT) { + if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_SINGLE) { + sh->mpm_hcd_ctx = MpmFactoryGetMpmCtxForProfile(de_ctx->sgh_mpm_context_hcd); + } else { + sh->mpm_hcd_ctx = MpmFactoryGetMpmCtxForProfile(MPM_CTX_FACTORY_UNIQUE_CONTEXT); + } + if (sh->mpm_hcd_ctx == NULL) { + SCLogDebug("sh->mpm_hcd_ctx == NULL. This should never happen"); + exit(EXIT_FAILURE); + } + +#ifndef __SC_CUDA_SUPPORT__ + MpmInitCtx(sh->mpm_hcd_ctx, de_ctx->mpm_matcher, -1); +#else + MpmInitCtx(sh->mpm_hcd_ctx, de_ctx->mpm_matcher, de_ctx->cuda_rc_mod_handle); +#endif + } + if (sh->flags & SIG_GROUP_HAVECONTENT || sh->flags & SIG_GROUP_HAVESTREAMCONTENT || sh->flags & SIG_GROUP_HAVEURICONTENT || sh->flags & SIG_GROUP_HAVEHCBDCONTENT || sh->flags & SIG_GROUP_HAVEHHDCONTENT || sh->flags & SIG_GROUP_HAVEHRHDCONTENT || - sh->flags & SIG_GROUP_HAVEHMDCONTENT) { + sh->flags & SIG_GROUP_HAVEHMDCONTENT || + sh->flags & SIG_GROUP_HAVEHCDCONTENT) { PatternMatchPreparePopulateMpm(de_ctx, sh); @@ -1629,6 +1738,17 @@ int PatternMatchPrepareGroup(DetectEngineCtx *de_ctx, SigGroupHead *sh) } } } + if (sh->mpm_hcd_ctx != NULL) { + if (sh->mpm_hcd_ctx->pattern_cnt == 0) { + MpmFactoryReClaimMpmCtx(sh->mpm_hcd_ctx); + sh->mpm_hcd_ctx = NULL; + } else { + if (sh->flags & SIG_GROUP_HAVEHCDCONTENT) { + if (mpm_table[sh->mpm_hcd_ctx->mpm_type].Prepare != NULL) + mpm_table[sh->mpm_hcd_ctx->mpm_type].Prepare(sh->mpm_hcd_ctx); + } + } + } } /* if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) */ } else { @@ -1646,6 +1766,8 @@ int PatternMatchPrepareGroup(DetectEngineCtx *de_ctx, SigGroupHead *sh) sh->mpm_hrhd_ctx = NULL; MpmFactoryReClaimMpmCtx(sh->mpm_hmd_ctx); sh->mpm_hmd_ctx = NULL; + MpmFactoryReClaimMpmCtx(sh->mpm_hcd_ctx); + sh->mpm_hcd_ctx = NULL; } diff --git a/src/detect-engine-mpm.h b/src/detect-engine-mpm.h index c358458bce..fa6fdaa69a 100644 --- a/src/detect-engine-mpm.h +++ b/src/detect-engine-mpm.h @@ -41,6 +41,7 @@ uint32_t HttpClientBodyPatternSearch(DetectEngineThreadCtx *, uint8_t *, uint32_ uint32_t HttpHeaderPatternSearch(DetectEngineThreadCtx *, uint8_t *, uint32_t); uint32_t HttpRawHeaderPatternSearch(DetectEngineThreadCtx *, uint8_t *, uint32_t); uint32_t HttpMethodPatternSearch(DetectEngineThreadCtx *, uint8_t *, uint32_t); +uint32_t HttpCookiePatternSearch(DetectEngineThreadCtx *, uint8_t *, uint32_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 66c09fe5ec..d54d38b158 100644 --- a/src/detect-engine-state.c +++ b/src/detect-engine-state.c @@ -35,6 +35,7 @@ #include "detect-engine-hhd.h" #include "detect-engine-hrhd.h" #include "detect-engine-hmd.h" +#include "detect-engine-hcd.h" #include "detect-engine-dcepayload.h" #include "stream-tcp.h" @@ -212,7 +213,7 @@ int DeStateUpdateInspectTransactionId(Flow *f, char direction) { */ static void DeStateSignatureAppend(DetectEngineState *state, Signature *s, SigMatch *sm, char uri, char dce, char hcbd, - char hhd, char hrhd, char hmd) { + char hhd, char hrhd, char hmd, char hcd) { DeStateStore *store = state->tail; if (store == NULL) { @@ -258,6 +259,9 @@ static void DeStateSignatureAppend(DetectEngineState *state, Signature *s, if (hmd) { store->store[idx].flags |= DE_STATE_FLAG_HMD_MATCH; } + if (hcd) { + store->store[idx].flags |= DE_STATE_FLAG_HCD_MATCH; + } store->store[idx].nm = sm; state->cnt++; @@ -325,6 +329,8 @@ int DeStateDetectStartDetection(ThreadVars *tv, DetectEngineCtx *de_ctx, char hrhdinspect = 0; char hmdinspect = 0; char hmdmatch = 0; + char hcdinspect = 0; + char hcdmatch = 0; char dmatch = 0; char dinspect = 0; char appinspect = 0; @@ -384,6 +390,14 @@ int DeStateDetectStartDetection(ThreadVars *tv, DetectEngineCtx *de_ctx, } SCLogDebug("inspecting http method"); } + if (s->sm_lists[DETECT_SM_LIST_HCDMATCH] != NULL) { + hcdinspect = 1; + if (DetectEngineInspectHttpCookie(de_ctx, det_ctx, s, f, + flags, alstate) == 1) { + hcdmatch = 1; + } + SCLogDebug("inspecting http cookie"); + } } else if (alproto == ALPROTO_DCERPC || alproto == ALPROTO_SMB || alproto == ALPROTO_SMB2) { if (s->sm_lists[DETECT_SM_LIST_DMATCH] != NULL) { @@ -415,8 +429,8 @@ int DeStateDetectStartDetection(ThreadVars *tv, DetectEngineCtx *de_ctx, } } - appinspect = uinspect + dinspect + hcbdinspect + hhdinspect + hrhdinspect + hmdinspect; - appmatch = umatch + dmatch + hcbdmatch + hhdmatch + hrhdmatch + hmdmatch; + appinspect = uinspect + dinspect + hcbdinspect + hhdinspect + hrhdinspect + hmdinspect + hcdinspect; + appmatch = umatch + dmatch + hcbdmatch + hhdmatch + hrhdmatch + hmdmatch + hcdmatch; if (s->sm_lists[DETECT_SM_LIST_AMATCH] != NULL) { for ( ; sm != NULL; sm = sm->next) { @@ -459,8 +473,8 @@ int DeStateDetectStartDetection(ThreadVars *tv, DetectEngineCtx *de_ctx, } SCLogDebug("detection done, store results: sm %p, uri %d, dce %d, hcbd %d, " - "hhd %d, hrhd %d hmd %d", sm, umatch, dmatch, hcbdmatch, - hhdmatch, hrhdmatch, hmdmatch); + "hhd %d, hrhd %d hmd %d hcd %d", sm, umatch, dmatch, hcbdmatch, + hhdmatch, hrhdmatch, hmdmatch, hcdmatch); SCMutexLock(&f->de_state_m); /* match or no match, we store the state anyway @@ -471,7 +485,8 @@ int DeStateDetectStartDetection(ThreadVars *tv, DetectEngineCtx *de_ctx, } if (f->de_state != NULL) { /* \todo shift to an array to transfer these match values*/ - DeStateSignatureAppend(f->de_state, s, sm, umatch, dmatch, hcbdmatch, hhdmatch, hrhdmatch, hmdmatch); + DeStateSignatureAppend(f->de_state, s, sm, umatch, dmatch, hcbdmatch, + hhdmatch, hrhdmatch, hmdmatch, hcdmatch); } SCMutexUnlock(&f->de_state_m); @@ -501,6 +516,8 @@ int DeStateDetectContinueDetection(ThreadVars *tv, DetectEngineCtx *de_ctx, Dete char hrhdinspect = 0; char hmdmatch = 0; char hmdinspect = 0; + char hcdmatch = 0; + char hcdinspect = 0; char dmatch = 0; char dinspect = 0; char appinspect = 0; @@ -535,6 +552,8 @@ int DeStateDetectContinueDetection(ThreadVars *tv, DetectEngineCtx *de_ctx, Dete hrhdinspect = 0; hmdmatch = 0; hmdinspect = 0; + hcdmatch = 0; + hcdinspect = 0; dmatch = 0; dinspect = 0; appinspect = 0; @@ -630,6 +649,19 @@ int DeStateDetectContinueDetection(ThreadVars *tv, DetectEngineCtx *de_ctx, Dete } } } + if (s->sm_lists[DETECT_SM_LIST_HCDMATCH] != NULL) { + if (!(item->flags & DE_STATE_FLAG_HCD_MATCH)) { + SCLogDebug("inspecting http cookie data"); + hcdinspect = 1; + + if (DetectEngineInspectHttpCookie(de_ctx, det_ctx, s, f, + flags, alstate) == 1) { + SCLogDebug("http cookie matched"); + item->flags |= DE_STATE_FLAG_HCD_MATCH; + hcdmatch = 1; + } + } + } } else if (alproto == ALPROTO_DCERPC || alproto == ALPROTO_SMB || alproto == ALPROTO_SMB2) { if (s->sm_lists[DETECT_SM_LIST_DMATCH] != NULL) { @@ -668,8 +700,8 @@ int DeStateDetectContinueDetection(ThreadVars *tv, DetectEngineCtx *de_ctx, Dete } - appinspect = uinspect + dinspect + hcbdinspect + hhdinspect + hrhdinspect + hmdinspect; - appmatch = umatch + dmatch + hcbdmatch + hhdmatch + hrhdmatch + hmdmatch; + appinspect = uinspect + dinspect + hcbdinspect + hhdinspect + hrhdinspect + hmdinspect + hcdinspect; + appmatch = umatch + dmatch + hcbdmatch + hhdmatch + hrhdmatch + hmdmatch + hcdmatch; SCLogDebug("appinspect %d, appmatch %d", appinspect, appmatch); /* next, check the other sig matches */ @@ -809,39 +841,39 @@ static int DeStateTest02(void) { memset(&s, 0x00, sizeof(s)); s.num = 0; - DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0, 0); + DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0, 0, 0); s.num = 11; - DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0, 0); + DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0, 0, 0); s.num = 22; - DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0, 0); + DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0, 0, 0); s.num = 33; - DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0, 0); + DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0, 0, 0); s.num = 44; - DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0, 0); + DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0, 0, 0); s.num = 55; - DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0, 0); + DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0, 0, 0); s.num = 66; - DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0, 0); + DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0, 0, 0); s.num = 77; - DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0, 0); + DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0, 0, 0); s.num = 88; - DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0, 0); + DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0, 0, 0); s.num = 99; - DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0, 0); + DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0, 0, 0); s.num = 100; - DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0, 0); + DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0, 0, 0); s.num = 111; - DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0, 0); + DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0, 0, 0); s.num = 122; - DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0, 0); + DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0, 0, 0); s.num = 133; - DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0, 0); + DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0, 0, 0); s.num = 144; - DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0, 0); + DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0, 0, 0); s.num = 155; - DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0, 0); + DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0, 0, 0); s.num = 166; - DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0, 0); + DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0, 0, 0); if (state->head == NULL) { goto end; @@ -884,9 +916,9 @@ static int DeStateTest03(void) { memset(&s, 0x00, sizeof(s)); s.num = 11; - DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0, 0); + DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0, 0, 0); s.num = 22; - DeStateSignatureAppend(state, &s, NULL, 1, 0, 0, 0, 0, 0); + DeStateSignatureAppend(state, &s, NULL, 1, 0, 0, 0, 0, 0, 0); if (state->head == NULL) { goto end; diff --git a/src/detect-engine-state.h b/src/detect-engine-state.h index 6c8298ff0c..362ad61ede 100644 --- a/src/detect-engine-state.h +++ b/src/detect-engine-state.h @@ -44,14 +44,15 @@ /** number of DeStateStoreItem's in one DeStateStore object */ #define DE_STATE_CHUNK_SIZE 16 -#define DE_STATE_FLAG_PAYLOAD_MATCH 0x01 /**< payload part of the sig matched */ -#define DE_STATE_FLAG_URI_MATCH 0x02 /**< uri part of the sig matched */ -#define DE_STATE_FLAG_DCE_MATCH 0x04 /**< dce payload inspection part matched */ -#define DE_STATE_FLAG_HCBD_MATCH 0x08 /**< hcbd payload inspection part matched */ -#define DE_STATE_FLAG_HHD_MATCH 0x10 /**< hhd payload inspection part matched */ -#define DE_STATE_FLAG_HRHD_MATCH 0x20 /**< hrhd payload inspection part matched */ -#define DE_STATE_FLAG_HMD_MATCH 0x40 /**< hmd payload inspection part matched */ -#define DE_STATE_FLAG_FULL_MATCH 0x80 /**< sig already fully matched */ +#define DE_STATE_FLAG_PAYLOAD_MATCH 0x0001 /**< payload part of the sig matched */ +#define DE_STATE_FLAG_URI_MATCH 0x0002 /**< uri part of the sig matched */ +#define DE_STATE_FLAG_DCE_MATCH 0x0004 /**< dce payload inspection part matched */ +#define DE_STATE_FLAG_HCBD_MATCH 0x0008 /**< hcbd payload inspection part matched */ +#define DE_STATE_FLAG_HHD_MATCH 0x0010 /**< hhd payload inspection part matched */ +#define DE_STATE_FLAG_HRHD_MATCH 0x0020 /**< hrhd payload inspection part matched */ +#define DE_STATE_FLAG_HMD_MATCH 0x0040 /**< hmd payload inspection part matched */ +#define DE_STATE_FLAG_HCD_MATCH 0x0080 /**< hcd payload inspection part matched */ +#define DE_STATE_FLAG_FULL_MATCH 0x0100 /**< sig already fully matched */ /** per signature detection engine state */ typedef enum { diff --git a/src/detect-fast-pattern.c b/src/detect-fast-pattern.c index 47d334d82d..b45f35deac 100644 --- a/src/detect-fast-pattern.c +++ b/src/detect-fast-pattern.c @@ -137,6 +137,9 @@ void SupportFastPatternForSigMatchTypes(void) SupportFastPatternForSigMatchType(DETECT_AL_HTTP_METHOD); SupportFastPatternForSigMatchList(DETECT_SM_LIST_HMDMATCH); + SupportFastPatternForSigMatchType(DETECT_AL_HTTP_COOKIE); + SupportFastPatternForSigMatchList(DETECT_SM_LIST_HCDMATCH); + return; } @@ -206,12 +209,13 @@ static int DetectFastPatternSetup(DetectEngineCtx *de_ctx, Signature *s, char *a s->sm_lists_tail[DETECT_SM_LIST_HCBDMATCH] == NULL && s->sm_lists_tail[DETECT_SM_LIST_HHDMATCH] == NULL && s->sm_lists_tail[DETECT_SM_LIST_HRHDMATCH] == NULL && - s->sm_lists_tail[DETECT_SM_LIST_HMDMATCH] == NULL) { + s->sm_lists_tail[DETECT_SM_LIST_HMDMATCH] == NULL && + s->sm_lists_tail[DETECT_SM_LIST_HCDMATCH] == 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_header, " - "http_raw_header and http_method"); + "http_raw_header, http_method or http_cookie option"); return -1; } @@ -221,7 +225,8 @@ static int DetectFastPatternSetup(DetectEngineCtx *de_ctx, Signature *s, char *a DETECT_AL_HTTP_CLIENT_BODY, s->sm_lists_tail[DETECT_SM_LIST_HCBDMATCH], DETECT_AL_HTTP_HEADER, s->sm_lists_tail[DETECT_SM_LIST_HHDMATCH], DETECT_AL_HTTP_RAW_HEADER, s->sm_lists_tail[DETECT_SM_LIST_HRHDMATCH], - DETECT_AL_HTTP_METHOD, s->sm_lists_tail[DETECT_SM_LIST_HMDMATCH]); + DETECT_AL_HTTP_METHOD, s->sm_lists_tail[DETECT_SM_LIST_HMDMATCH], + DETECT_AL_HTTP_COOKIE, s->sm_lists_tail[DETECT_SM_LIST_HCDMATCH]); if (pm == NULL) { SCLogError(SC_ERR_INVALID_SIGNATURE, "fast_pattern found inside " "the rule, without a content context. Please use a " @@ -8789,6 +8794,1125 @@ int DetectFastPatternTest301(void) return result; } + + + + + + + + + + + + + +int DetectFastPatternTest302(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_cookie; " + "content:!oneonetwo; fast_pattern:3,4; http_cookie; " + "content:three; http_cookie; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HCDMATCH]->prev->ctx; + if (ud->flags & DETECT_CONTENT_FAST_PATTERN && + 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; +} + +/** + * \test Checks if a fast_pattern is registered in a Signature for uricontent. + */ +int DetectFastPatternTest303(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_cookie; " + "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_HCDMATCH]; + if (sm != NULL) { + if ( ((DetectContentData *)sm->ctx)->flags & + DETECT_CONTENT_FAST_PATTERN) { + 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 DetectFastPatternTest304(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_cookie; " + "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_HCDMATCH]; + if (sm != NULL) { + if ( ((DetectContentData *)sm->ctx)->flags & + DETECT_CONTENT_FAST_PATTERN) { + result = 1; + } else { + result = 0; + } + } + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest305(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_cookie; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + + result = 0; + sm = de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HCDMATCH]; + DetectContentData *ud = sm->ctx; + if (sm != NULL) { + if (ud->flags & DETECT_CONTENT_FAST_PATTERN && + 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 DetectFastPatternTest306(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_cookie; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + + result = 0; + sm = de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HCDMATCH]; + DetectContentData *ud = sm->ctx; + if (sm != NULL) { + if (ud->flags & DETECT_CONTENT_FAST_PATTERN && + !(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 DetectFastPatternTest307(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_cookie; content:two; fast_pattern:only; http_cookie; distance:10; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest308(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_cookie; content:two; distance:10; fast_pattern:only; http_cookie; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest309(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_cookie; content:two; fast_pattern:only; http_cookie; within:10; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest310(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_cookie; content:two; within:10; fast_pattern:only; http_cookie; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest311(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_cookie; content:two; fast_pattern:only; http_cookie; offset:10; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest312(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_cookie; content:two; offset:10; fast_pattern:only; http_cookie; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest313(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_cookie; content:two; fast_pattern:only; http_cookie; depth:10; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest314(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_cookie; content:two; depth:10; fast_pattern:only; http_cookie; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest315(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_cookie; content:!two; fast_pattern:only; http_cookie; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest316(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_cookie; content:two; http_cookie; distance:30; content:two; fast_pattern:only; http_cookie; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HCDMATCH]->ctx; + if (ud->flags & DETECT_CONTENT_FAST_PATTERN && + 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 DetectFastPatternTest317(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_cookie; content:two; http_cookie; within:30; content:two; fast_pattern:only; http_cookie; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HCDMATCH]->ctx; + if (ud->flags & DETECT_CONTENT_FAST_PATTERN && + 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 DetectFastPatternTest318(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_cookie; content:two; http_cookie; offset:30; content:two; fast_pattern:only; http_cookie; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HCDMATCH]->ctx; + if (ud->flags & DETECT_CONTENT_FAST_PATTERN && + 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 DetectFastPatternTest319(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_cookie; content:two; http_cookie; depth:30; content:two; fast_pattern:only; http_cookie; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HCDMATCH]->ctx; + if (ud->flags & DETECT_CONTENT_FAST_PATTERN && + 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 DetectFastPatternTest320(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_cookie; content:two; http_cookie; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HCDMATCH]->prev->ctx; + if (ud->flags & DETECT_CONTENT_FAST_PATTERN && + 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 DetectFastPatternTest321(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_cookie; content:!one; fast_pattern; http_cookie; distance:20; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest322(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_cookie; content:!one; fast_pattern; http_cookie; within:20; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest323(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_cookie; content:!one; fast_pattern; http_cookie; offset:20; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest324(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_cookie; content:!one; fast_pattern; http_cookie; depth:20; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest325(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_cookie; content:oneonetwo; fast_pattern:3,4; http_cookie; content:three; http_cookie; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HCDMATCH]->prev->ctx; + if (ud->flags & DETECT_CONTENT_FAST_PATTERN && + !(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 DetectFastPatternTest326(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_cookie; content:oneonetwo; fast_pattern:3,4; http_cookie; content:three; http_cookie; distance:30; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HCDMATCH]->prev->ctx; + if (ud->flags & DETECT_CONTENT_FAST_PATTERN && + !(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 DetectFastPatternTest327(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_cookie; content:oneonetwo; fast_pattern:3,4; http_cookie; content:three; http_cookie; within:30; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HCDMATCH]->prev->ctx; + if (ud->flags & DETECT_CONTENT_FAST_PATTERN && + !(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 DetectFastPatternTest328(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_cookie; content:oneonetwo; fast_pattern:3,4; http_cookie; content:three; http_cookie; offset:30; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HCDMATCH]->prev->ctx; + if (ud->flags & DETECT_CONTENT_FAST_PATTERN && + !(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 DetectFastPatternTest329(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_cookie; content:oneonetwo; fast_pattern:3,4; http_cookie; content:three; http_cookie; depth:30; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HCDMATCH]->prev->ctx; + if (ud->flags & DETECT_CONTENT_FAST_PATTERN && + !(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 DetectFastPatternTest330(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_cookie; content:two; http_cookie; distance:10; content:oneonethree; fast_pattern:3,4; http_cookie; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HCDMATCH]->ctx; + if (ud->flags & DETECT_CONTENT_FAST_PATTERN && + !(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 DetectFastPatternTest331(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_cookie; content:two; http_cookie; within:10; content:oneonethree; fast_pattern:3,4; http_cookie; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HCDMATCH]->ctx; + if (ud->flags & DETECT_CONTENT_FAST_PATTERN && + !(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 DetectFastPatternTest332(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_cookie; content:two; http_cookie; offset:10; content:oneonethree; fast_pattern:3,4; http_cookie; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HCDMATCH]->ctx; + if (ud->flags & DETECT_CONTENT_FAST_PATTERN && + !(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 DetectFastPatternTest333(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_cookie; content:two; http_cookie; depth:10; content:oneonethree; fast_pattern:3,4; http_cookie; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HCDMATCH]->ctx; + if (ud->flags & DETECT_CONTENT_FAST_PATTERN && + !(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 DetectFastPatternTest334(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_cookie; content:two; fast_pattern:65977,4; http_cookie; content:three; http_cookie; distance:10; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest335(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_cookie; content:oneonetwo; fast_pattern:3,65977; http_cookie; content:three; distance:10; http_cookie; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest336(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_cookie; content:two; fast_pattern:65534,4; http_cookie; content:three; http_cookie; distance:10; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest337(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_cookie; content:!oneonetwo; fast_pattern:3,4; http_cookie; content:three; http_cookie; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HCDMATCH]->prev->ctx; + if (ud->flags & DETECT_CONTENT_FAST_PATTERN && + 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 DetectFastPatternTest338(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_cookie; content:!oneonetwo; fast_pattern:3,4; http_cookie; distance:10; content:three; http_cookie; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest339(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_cookie; content:!oneonetwo; fast_pattern:3,4; http_cookie; within:10; content:three; http_cookie; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest340(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_cookie; content:!oneonetwo; fast_pattern:3,4; http_cookie; offset:10; content:three; http_cookie; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest341(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_cookie; content:!oneonetwo; fast_pattern:3,4; http_cookie; depth:10; content:three; http_cookie; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest342(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_cookie; content:!oneonetwo; fast_pattern:3,4; http_cookie; content:three; http_cookie; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HCDMATCH]->prev->ctx; + if (ud->flags & DETECT_CONTENT_FAST_PATTERN && + 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) @@ -9110,6 +10234,49 @@ void DetectFastPatternRegisterTests(void) UtRegisterTest("DetectFastPatternTest299", DetectFastPatternTest299, 1); UtRegisterTest("DetectFastPatternTest300", DetectFastPatternTest300, 1); UtRegisterTest("DetectFastPatternTest301", DetectFastPatternTest301, 1); + /* http_method fast_pattern tests ^ */ + /* http_cookie fast_pattern tests v */ + UtRegisterTest("DetectFastPatternTest302", DetectFastPatternTest302, 1); + UtRegisterTest("DetectFastPatternTest303", DetectFastPatternTest303, 1); + UtRegisterTest("DetectFastPatternTest304", DetectFastPatternTest304, 1); + UtRegisterTest("DetectFastPatternTest305", DetectFastPatternTest305, 1); + UtRegisterTest("DetectFastPatternTest306", DetectFastPatternTest306, 1); + UtRegisterTest("DetectFastPatternTest307", DetectFastPatternTest307, 1); + UtRegisterTest("DetectFastPatternTest308", DetectFastPatternTest308, 1); + UtRegisterTest("DetectFastPatternTest309", DetectFastPatternTest309, 1); + UtRegisterTest("DetectFastPatternTest310", DetectFastPatternTest310, 1); + UtRegisterTest("DetectFastPatternTest311", DetectFastPatternTest311, 1); + UtRegisterTest("DetectFastPatternTest312", DetectFastPatternTest312, 1); + UtRegisterTest("DetectFastPatternTest313", DetectFastPatternTest313, 1); + UtRegisterTest("DetectFastPatternTest314", DetectFastPatternTest314, 1); + UtRegisterTest("DetectFastPatternTest315", DetectFastPatternTest315, 1); + UtRegisterTest("DetectFastPatternTest316", DetectFastPatternTest316, 1); + UtRegisterTest("DetectFastPatternTest317", DetectFastPatternTest317, 1); + UtRegisterTest("DetectFastPatternTest318", DetectFastPatternTest318, 1); + UtRegisterTest("DetectFastPatternTest319", DetectFastPatternTest319, 1); + UtRegisterTest("DetectFastPatternTest320", DetectFastPatternTest320, 1); + UtRegisterTest("DetectFastPatternTest321", DetectFastPatternTest321, 1); + UtRegisterTest("DetectFastPatternTest322", DetectFastPatternTest322, 1); + UtRegisterTest("DetectFastPatternTest323", DetectFastPatternTest323, 1); + UtRegisterTest("DetectFastPatternTest324", DetectFastPatternTest324, 1); + UtRegisterTest("DetectFastPatternTest325", DetectFastPatternTest325, 1); + UtRegisterTest("DetectFastPatternTest326", DetectFastPatternTest326, 1); + UtRegisterTest("DetectFastPatternTest327", DetectFastPatternTest327, 1); + UtRegisterTest("DetectFastPatternTest328", DetectFastPatternTest328, 1); + UtRegisterTest("DetectFastPatternTest329", DetectFastPatternTest329, 1); + UtRegisterTest("DetectFastPatternTest330", DetectFastPatternTest330, 1); + UtRegisterTest("DetectFastPatternTest331", DetectFastPatternTest331, 1); + UtRegisterTest("DetectFastPatternTest332", DetectFastPatternTest332, 1); + UtRegisterTest("DetectFastPatternTest333", DetectFastPatternTest333, 1); + UtRegisterTest("DetectFastPatternTest334", DetectFastPatternTest334, 1); + UtRegisterTest("DetectFastPatternTest335", DetectFastPatternTest335, 1); + UtRegisterTest("DetectFastPatternTest336", DetectFastPatternTest336, 1); + UtRegisterTest("DetectFastPatternTest337", DetectFastPatternTest337, 1); + UtRegisterTest("DetectFastPatternTest338", DetectFastPatternTest338, 1); + UtRegisterTest("DetectFastPatternTest339", DetectFastPatternTest339, 1); + UtRegisterTest("DetectFastPatternTest340", DetectFastPatternTest340, 1); + UtRegisterTest("DetectFastPatternTest341", DetectFastPatternTest341, 1); + UtRegisterTest("DetectFastPatternTest342", DetectFastPatternTest342, 1); #endif return; diff --git a/src/detect-http-cookie.c b/src/detect-http-cookie.c index b3c4b8be4e..f7e8de28d3 100644 --- a/src/detect-http-cookie.c +++ b/src/detect-http-cookie.c @@ -33,6 +33,7 @@ #include "detect-engine.h" #include "detect-engine-mpm.h" #include "detect-content.h" +#include "detect-pcre.h" #include "flow.h" #include "flow-var.h" @@ -65,7 +66,8 @@ void DetectHttpCookieFree(void *); void DetectHttpCookieRegister (void) { sigmatch_table[DETECT_AL_HTTP_COOKIE].name = "http_cookie"; sigmatch_table[DETECT_AL_HTTP_COOKIE].Match = NULL; - sigmatch_table[DETECT_AL_HTTP_COOKIE].AppLayerMatch = DetectHttpCookieMatch; + sigmatch_table[DETECT_AL_HTTP_COOKIE].AppLayerMatch = NULL; + //sigmatch_table[DETECT_AL_HTTP_COOKIE].AppLayerMatch = DetectHttpCookieMatch; sigmatch_table[DETECT_AL_HTTP_COOKIE].alproto = ALPROTO_HTTP; sigmatch_table[DETECT_AL_HTTP_COOKIE].Setup = DetectHttpCookieSetup; sigmatch_table[DETECT_AL_HTTP_COOKIE].Free = DetectHttpCookieFree; @@ -196,92 +198,97 @@ void DetectHttpCookieFree(void *ptr) static int DetectHttpCookieSetup (DetectEngineCtx *de_ctx, Signature *s, char *str) { - DetectContentData *hd = NULL; + DetectContentData *cd = NULL; SigMatch *sm = NULL; - /** new sig match to replace previous content */ - SigMatch *nm = NULL; - if (str != NULL && strcmp(str, "") != 0) { - SCLogError(SC_ERR_INVALID_ARGUMENT, "http_cookie shouldn't be supplied with" - " an argument"); + SCLogError(SC_ERR_INVALID_ARGUMENT, "http_cookie shouldn't be supplied " + "with an argument"); return -1; } if (s->sm_lists_tail[DETECT_SM_LIST_PMATCH] == NULL) { SCLogError(SC_ERR_INVALID_SIGNATURE, "http_cookie found inside the " - "rule, without any preceding content keywords"); + "rule, without any preceding content keywords"); return -1; } - SigMatch *pm = DetectContentGetLastPattern(s->sm_lists_tail[DETECT_SM_LIST_PMATCH]); - if (pm == NULL) { + sm = DetectContentGetLastPattern(s->sm_lists_tail[DETECT_SM_LIST_PMATCH]); + if (sm == NULL) { SCLogWarning(SC_ERR_INVALID_SIGNATURE, "http_cookie found inside " "the rule, without a content context. Please use a " "content keyword before using http_cookie"); return -1; } - /* http_cookie should not be used with the fast_pattern rule */ - if (((DetectContentData *)pm->ctx)->flags & DETECT_CONTENT_FAST_PATTERN) { - SCLogWarning(SC_WARN_COMPATIBILITY, "http_cookie rule can not " - "be used with the fast_pattern rule keyword. " - "Unsetting fast_pattern on this modifier. Signature ==> %s", s->sig_str); - ((DetectContentData *)pm->ctx)->flags &= ~DETECT_CONTENT_FAST_PATTERN; + cd = (DetectContentData *)sm->ctx; + /* http_cookie should not be used with the rawbytes rule */ - } else if (((DetectContentData *)pm->ctx)->flags & DETECT_CONTENT_RAWBYTES) { + if (cd->flags & DETECT_CONTENT_RAWBYTES) { SCLogError(SC_ERR_INVALID_SIGNATURE, "http_cookie rule can not " - "be used with the rawbytes rule keyword"); + "be used with the rawbytes rule keyword"); return -1; } - nm = SigMatchAlloc(); - if (nm == NULL) { - SCLogError(SC_ERR_MEM_ALLOC, "SigMatchAlloc failed"); + if (s->alproto != ALPROTO_UNKNOWN && s->alproto != ALPROTO_HTTP) { + SCLogError(SC_ERR_CONFLICTING_RULE_KEYWORDS, "rule contains a non http " + "alproto set"); goto error; } - /* Setup the HttpCookie data from Content data structure */ - hd = SCMalloc(sizeof(DetectContentData)); - if (hd == NULL) - goto error; - memset(hd, 0, sizeof(DetectContentData)); - - hd->content_len = ((DetectContentData *)pm->ctx)->content_len; - hd->content = ((DetectContentData *)pm->ctx)->content; - hd->flags |= (((DetectContentData *)pm->ctx)->flags & DETECT_CONTENT_NOCASE) ? - DETECT_CONTENT_NOCASE : 0; - hd->flags |= (((DetectContentData *)pm->ctx)->flags & DETECT_CONTENT_NEGATED) ? - DETECT_CONTENT_NEGATED : 0; - hd->id = DetectPatternGetId(de_ctx->mpm_pattern_id_store, hd, DETECT_AL_HTTP_COOKIE); - nm->type = DETECT_AL_HTTP_COOKIE; - //hd->id = ((DetectContentData *)pm->ctx)->id; - nm->ctx = (void *)hd; - - /* pull the previous content from the pmatch list, append - * the new match to the match list */ - SigMatchReplaceContent(s, pm, nm); - - /* free the old content sigmatch, the content pattern memory - * is taken over by the new sigmatch */ - BoyerMooreCtxDeInit(((DetectContentData *)pm->ctx)->bm_ctx); - SCFree(pm->ctx); - SCFree(pm); - - /* Flagged the signature as to inspect the app layer data */ - s->flags |= SIG_FLAG_APPLAYER; - - if (s->alproto != ALPROTO_UNKNOWN && s->alproto != ALPROTO_HTTP) { - SCLogError(SC_ERR_CONFLICTING_RULE_KEYWORDS, "rule contains conflicting keywords."); - 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); + if (pm != NULL) { + /* pm is never NULL. So no NULL check */ + 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) */ + + /* please note. reassigning pm */ + pm = SigMatchGetLastSMFromLists(s, 4, + DETECT_AL_HTTP_COOKIE, + s->sm_lists_tail[DETECT_SM_LIST_HCDMATCH], + DETECT_PCRE, + s->sm_lists_tail[DETECT_SM_LIST_HCDMATCH]); + if (pm == NULL) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "http_cookie seen with a " + "distance or within without a previous http_cookie " + "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_AL_HTTP_COOKIE); + sm->type = DETECT_AL_HTTP_COOKIE; + /* transfer the sm from the pmatch list to hmdmatch list */ + SigMatchTransferSigMatchAcrossLists(sm, + &s->sm_lists[DETECT_SM_LIST_PMATCH], + &s->sm_lists_tail[DETECT_SM_LIST_PMATCH], + &s->sm_lists[DETECT_SM_LIST_HCDMATCH], + &s->sm_lists_tail[DETECT_SM_LIST_HCDMATCH]); + + /* flag the signature to indicate that we scan the app layer data */ + s->flags |= SIG_FLAG_APPLAYER; s->alproto = ALPROTO_HTTP; + return 0; + error: - if (hd != NULL) DetectHttpCookieFree(hd); - if(sm !=NULL) SCFree(sm); return -1; } @@ -364,7 +371,7 @@ int DetectHttpCookieTest03(void) } result = 0; - sm = de_ctx->sig_list->sm_lists[DETECT_SM_LIST_AMATCH]; + sm = de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HCDMATCH]; if (sm == NULL) { printf("no sigmatch(es): "); goto end; @@ -457,9 +464,9 @@ int DetectHttpCookieTest06(void) Signature *s = de_ctx->sig_list; - BUG_ON(s->sm_lists[DETECT_SM_LIST_AMATCH] == NULL); + BUG_ON(s->sm_lists[DETECT_SM_LIST_HCDMATCH] == NULL); - if (s->sm_lists[DETECT_SM_LIST_AMATCH]->type != DETECT_AL_HTTP_COOKIE) + if (s->sm_lists[DETECT_SM_LIST_HCDMATCH]->type != DETECT_AL_HTTP_COOKIE) goto end; if (s->sm_lists[DETECT_SM_LIST_UMATCH] == NULL) { @@ -500,13 +507,13 @@ int DetectHttpCookieTest07(void) goto end; } - if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_AMATCH] == NULL) { - printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_AMATCH] == NULL\n"); + if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HCDMATCH] == NULL) { + printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HCDMATCH] == NULL\n"); goto end; } DetectContentData *cd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->ctx; - DetectContentData *hcd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_AMATCH]->ctx; + DetectContentData *hcd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HCDMATCH]->ctx; if (cd->id == hcd->id) goto end; @@ -539,13 +546,13 @@ int DetectHttpCookieTest08(void) goto end; } - if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_AMATCH] == NULL) { - printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_AMATCH] == NULL\n"); + if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HCDMATCH] == NULL) { + printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HCDMATCH] == NULL\n"); goto end; } DetectContentData *cd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->ctx; - DetectContentData *hcd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_AMATCH]->ctx; + DetectContentData *hcd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HCDMATCH]->ctx; if (cd->id == hcd->id) goto end; @@ -578,13 +585,13 @@ int DetectHttpCookieTest09(void) goto end; } - if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_AMATCH] == NULL) { - printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_AMATCH] == NULL\n"); + if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HCDMATCH] == NULL) { + printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HCDMATCH] == NULL\n"); goto end; } DetectContentData *cd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->ctx; - DetectContentData *hcd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_AMATCH]->ctx; + DetectContentData *hcd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HCDMATCH]->ctx; if (cd->id != 0 || hcd->id != 1) goto end; @@ -617,13 +624,13 @@ int DetectHttpCookieTest10(void) goto end; } - if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_AMATCH] == NULL) { - printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_AMATCH] == NULL\n"); + if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HCDMATCH] == NULL) { + printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HCDMATCH] == NULL\n"); goto end; } DetectContentData *cd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->ctx; - DetectContentData *hcd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_AMATCH]->ctx; + DetectContentData *hcd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HCDMATCH]->ctx; if (cd->id != 1 || hcd->id != 0) goto end; @@ -657,14 +664,14 @@ int DetectHttpCookieTest11(void) goto end; } - if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_AMATCH] == NULL) { - printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_AMATCH] == NULL\n"); + if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HCDMATCH] == NULL) { + printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HCDMATCH] == NULL\n"); goto end; } DetectContentData *cd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->ctx; - DetectContentData *hcd1 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_AMATCH]->ctx; - DetectContentData *hcd2 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_AMATCH]->prev->ctx; + DetectContentData *hcd1 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HCDMATCH]->ctx; + DetectContentData *hcd2 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HCDMATCH]->prev->ctx; if (cd->id != 1 || hcd1->id != 0 || hcd2->id != 0) goto end; @@ -698,14 +705,14 @@ int DetectHttpCookieTest12(void) goto end; } - if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_AMATCH] == NULL) { - printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_AMATCH] == NULL\n"); + if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HCDMATCH] == NULL) { + printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HCDMATCH] == NULL\n"); goto end; } DetectContentData *cd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->ctx; - DetectContentData *hcd1 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_AMATCH]->ctx; - DetectContentData *hcd2 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_AMATCH]->prev->ctx; + DetectContentData *hcd1 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HCDMATCH]->ctx; + DetectContentData *hcd2 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HCDMATCH]->prev->ctx; if (cd->id != 2 || hcd1->id != 0 || hcd2->id != 0) goto end; diff --git a/src/detect-http-method.c b/src/detect-http-method.c index 7483d753b8..6cc1c27d9a 100644 --- a/src/detect-http-method.c +++ b/src/detect-http-method.c @@ -177,8 +177,7 @@ static int DetectHttpMethodSetup(DetectEngineCtx *de_ctx, Signature *s, char *st cd = (DetectContentData *)sm->ctx; - if (cd->flags & DETECT_CONTENT_RAWBYTES) - { + if (cd->flags & DETECT_CONTENT_RAWBYTES) { SCLogError(SC_ERR_INVALID_SIGNATURE, "http_method cannot be used " "with \"rawbytes\""); SCReturnInt(-1); diff --git a/src/detect-nocase.c b/src/detect-nocase.c index 570daea920..b2d9f603c3 100644 --- a/src/detect-nocase.c +++ b/src/detect-nocase.c @@ -187,8 +187,8 @@ static int DetectNocaseSetup (DetectEngineCtx *de_ctx, Signature *s, char *nulls DETECT_AL_HTTP_CLIENT_BODY, s->sm_lists_tail[DETECT_SM_LIST_HCBDMATCH], DETECT_AL_HTTP_HEADER, s->sm_lists_tail[DETECT_SM_LIST_HHDMATCH], DETECT_AL_HTTP_RAW_HEADER, s->sm_lists_tail[DETECT_SM_LIST_HRHDMATCH], - DETECT_AL_HTTP_COOKIE, s->sm_lists_tail[DETECT_SM_LIST_AMATCH], - DETECT_AL_HTTP_METHOD, s->sm_lists_tail[DETECT_SM_LIST_HMDMATCH]); + DETECT_AL_HTTP_METHOD, s->sm_lists_tail[DETECT_SM_LIST_HMDMATCH], + DETECT_AL_HTTP_COOKIE, s->sm_lists_tail[DETECT_SM_LIST_HCDMATCH]); if (pm == NULL) { SCLogError(SC_ERR_NOCASE_MISSING_PATTERN, "\"nocase\" needs a preceeding" " content, uricontent, http_client_body, http_header, http_method, http_uri, http_cookie option"); diff --git a/src/detect-offset.c b/src/detect-offset.c index 4c18f9d6e8..5cae3068aa 100644 --- a/src/detect-offset.c +++ b/src/detect-offset.c @@ -82,17 +82,19 @@ int DetectOffsetSetup (DetectEngineCtx *de_ctx, Signature *s, char *offsetstr) break; default: - pm = SigMatchGetLastSMFromLists(s, 12, + pm = SigMatchGetLastSMFromLists(s, 14, DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_PMATCH], DETECT_URICONTENT, s->sm_lists_tail[DETECT_SM_LIST_UMATCH], DETECT_AL_HTTP_CLIENT_BODY, s->sm_lists_tail[DETECT_SM_LIST_HCBDMATCH], DETECT_AL_HTTP_HEADER, s->sm_lists_tail[DETECT_SM_LIST_HHDMATCH], DETECT_AL_HTTP_RAW_HEADER, s->sm_lists_tail[DETECT_SM_LIST_HRHDMATCH], - DETECT_AL_HTTP_METHOD, s->sm_lists_tail[DETECT_SM_LIST_HMDMATCH]); + DETECT_AL_HTTP_METHOD, s->sm_lists_tail[DETECT_SM_LIST_HMDMATCH], + DETECT_AL_HTTP_COOKIE, s->sm_lists_tail[DETECT_SM_LIST_HCDMATCH]); if (pm == NULL) { SCLogError(SC_ERR_WITHIN_MISSING_CONTENT, "offset needs" "preceeding content or uricontent option, http_client_body " - "http_header, http_raw_header or http_method option"); + "http_header, http_raw_header, http_method or " + "http_cookie option"); if (dubbed) SCFree(str); return -1; @@ -305,6 +307,37 @@ int DetectOffsetSetup (DetectEngineCtx *de_ctx, Signature *s, char *offsetstr) break; + case DETECT_AL_HTTP_COOKIE: + cd = (DetectContentData *)pm->ctx; + if (cd->flags & DETECT_CONTENT_NEGATED) { + if (cd->flags & DETECT_CONTENT_FAST_PATTERN) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "You can't have a relative " + "negated keyword set along with a fast_pattern"); + goto error; + } + } else { + if (cd->flags & DETECT_CONTENT_FAST_PATTERN_ONLY) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "You can't have a relative " + "keyword set along with a fast_pattern:only;"); + goto error; + } + } + + cd->offset = (uint32_t)atoi(str); + if (cd->depth != 0) { + if (cd->depth < cd->content_len) { + SCLogDebug("depth increased to %"PRIu32" to match pattern len", + cd->content_len); + cd->depth = cd->content_len; + } + /* Updating the depth as is relative to the offset */ + cd->depth += cd->offset; + } + + cd->flags |= DETECT_CONTENT_OFFSET; + + break; + default: SCLogError(SC_ERR_OFFSET_MISSING_CONTENT, "offset needs a preceeding" " content or uricontent option"); diff --git a/src/detect-parse.c b/src/detect-parse.c index cc1657744a..70ee59ce81 100644 --- a/src/detect-parse.c +++ b/src/detect-parse.c @@ -1438,6 +1438,8 @@ Signature *SigInit(DetectEngineCtx *de_ctx, char *sigstr) { sig->flags |= SIG_FLAG_STATE_MATCH; if (sig->sm_lists[DETECT_SM_LIST_HMDMATCH]) sig->flags |= SIG_FLAG_STATE_MATCH; + if (sig->sm_lists[DETECT_SM_LIST_HCDMATCH]) + sig->flags |= SIG_FLAG_STATE_MATCH; SCLogDebug("sig %"PRIu32" SIG_FLAG_APPLAYER: %s, SIG_FLAG_PACKET: %s", sig->id, sig->flags & SIG_FLAG_APPLAYER ? "set" : "not set", @@ -1634,6 +1636,8 @@ Signature *SigInitReal(DetectEngineCtx *de_ctx, char *sigstr) { sig->flags |= SIG_FLAG_STATE_MATCH; if (sig->sm_lists[DETECT_SM_LIST_HMDMATCH]) sig->flags |= SIG_FLAG_STATE_MATCH; + if (sig->sm_lists[DETECT_SM_LIST_HCDMATCH]) + sig->flags |= SIG_FLAG_STATE_MATCH; SigBuildAddressMatchArray(sig); diff --git a/src/detect-within.c b/src/detect-within.c index 90d891c4e4..1013d1c73a 100644 --- a/src/detect-within.c +++ b/src/detect-within.c @@ -171,17 +171,19 @@ static int DetectWithinSetup (DetectEngineCtx *de_ctx, Signature *s, char *withi } } } else { - pm = SigMatchGetLastSMFromLists(s, 12, + pm = SigMatchGetLastSMFromLists(s, 14, DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_PMATCH], DETECT_URICONTENT, s->sm_lists_tail[DETECT_SM_LIST_UMATCH], DETECT_AL_HTTP_CLIENT_BODY, s->sm_lists_tail[DETECT_SM_LIST_HCBDMATCH], DETECT_AL_HTTP_HEADER, s->sm_lists_tail[DETECT_SM_LIST_HHDMATCH], DETECT_AL_HTTP_RAW_HEADER, s->sm_lists_tail[DETECT_SM_LIST_HRHDMATCH], - DETECT_AL_HTTP_METHOD, s->sm_lists_tail[DETECT_SM_LIST_HMDMATCH]); + DETECT_AL_HTTP_METHOD, s->sm_lists_tail[DETECT_SM_LIST_HMDMATCH], + DETECT_AL_HTTP_COOKIE, s->sm_lists_tail[DETECT_SM_LIST_HCDMATCH]); if (pm == NULL) { SCLogError(SC_ERR_WITHIN_MISSING_CONTENT, "within needs" "preceeding content, uricontent, http_client_body, " - "http_header, http_raw_header or http_method option"); + "http_header, http_raw_header, http_method or " + "http_cookie option"); if (dubbed) SCFree(str); return -1; @@ -609,6 +611,60 @@ static int DetectWithinSetup (DetectEngineCtx *de_ctx, Signature *s, char *withi break; + case DETECT_AL_HTTP_COOKIE: + cd = (DetectContentData *)pm->ctx; + if (cd->flags & DETECT_CONTENT_NEGATED) { + if (cd->flags & DETECT_CONTENT_FAST_PATTERN) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "You can't have a relative " + "negated keyword set along with a fast_pattern"); + goto error; + } + } else { + if (cd->flags & DETECT_CONTENT_FAST_PATTERN_ONLY) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "You can't have a relative " + "keyword set along with a fast_pattern:only;"); + goto error; + } + } + + cd->within = strtol(str, NULL, 10); + if (cd->within < (int32_t)cd->content_len) { + SCLogError(SC_ERR_WITHIN_INVALID, "within argument \"%"PRIi32"\" is " + "less than the content length \"%"PRIu32"\" which is invalid, since " + "this will never match. Invalidating signature", cd->within, + cd->content_len); + goto error; + } + cd->flags |= DETECT_CONTENT_WITHIN; + + /* reassigning pm */ + pm = SigMatchGetLastSMFromLists(s, 4, + DETECT_AL_HTTP_COOKIE, pm->prev, + DETECT_PCRE, pm->prev); + if (pm == NULL) { + SCLogError(SC_ERR_DISTANCE_MISSING_CONTENT, "distance for http_cookie " + "needs preceeding http_cookie content"); + goto error; + } + + if (pm->type == DETECT_PCRE) { + DetectPcreData *tmp_pd = (DetectPcreData *)pm->ctx; + tmp_pd->flags |= DETECT_PCRE_RELATIVE_NEXT; + } else { + /* reassigning cd */ + cd = (DetectContentData *)pm->ctx; + if (cd->flags & DETECT_CONTENT_FAST_PATTERN_ONLY) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "Previous keyword " + "has a fast_pattern:only; set. You can't " + "have relative keywords around a fast_pattern " + "only content"); + goto error; + } + cd->flags |= DETECT_CONTENT_RELATIVE_NEXT; + } + + break; + default: SCLogError(SC_ERR_WITHIN_MISSING_CONTENT, "within needs two " "preceeding content or uricontent options"); diff --git a/src/detect.c b/src/detect.c index af2e2cde03..959fc7659f 100644 --- a/src/detect.c +++ b/src/detect.c @@ -119,6 +119,7 @@ #include "detect-engine-hhd.h" #include "detect-engine-hrhd.h" #include "detect-engine-hmd.h" +#include "detect-engine-hcd.h" #include "util-rule-vars.h" @@ -819,6 +820,14 @@ static void SigMatchSignaturesBuildMatchArray(DetectEngineCtx *de_ctx, } } + if (s->flags & SIG_FLAG_MPM_HCDCONTENT) { + if (!(det_ctx->pmq.pattern_id_bitarray[(s->mpm_http_pattern_id / 8)] & + (1 << (s->mpm_http_pattern_id % 8)))) { + if (!(s->flags & SIG_FLAG_MPM_HCDCONTENT_NEG)) { + continue; + } + } + } /* de_state check, filter out all signatures that already had a match before * or just partially match */ if (s->flags & SIG_FLAG_STATE_MATCH) { @@ -1057,6 +1066,10 @@ static inline void DetectMpmPrefilter(DetectEngineCtx *de_ctx, cnt = DetectEngineRunHttpMethodMpm(det_ctx, p->flow, alstate); SCLogDebug("hmd search: cnt %" PRIu32, cnt); } + if (det_ctx->sgh->flags & SIG_GROUP_HEAD_MPM_HCD) { + cnt = DetectEngineRunHttpCookieMpm(det_ctx, p->flow, alstate); + SCLogDebug("hcd search: cnt %" PRIu32, cnt); + } } } else { SCLogDebug("NOT p->flowflags & FLOW_PKT_ESTABLISHED"); @@ -1690,6 +1703,9 @@ int SignatureIsIPOnly(DetectEngineCtx *de_ctx, Signature *s) { if (s->sm_lists[DETECT_SM_LIST_HMDMATCH] != NULL) return 0; + if (s->sm_lists[DETECT_SM_LIST_HCDMATCH] != NULL) + return 0; + if (s->sm_lists[DETECT_SM_LIST_AMATCH] != NULL) return 0; @@ -1773,6 +1789,9 @@ static int SignatureIsDEOnly(DetectEngineCtx *de_ctx, Signature *s) { if (s->sm_lists[DETECT_SM_LIST_HMDMATCH] != NULL) return 0; + if (s->sm_lists[DETECT_SM_LIST_HCDMATCH] != NULL) + return 0; + SigMatch *sm = s->sm_lists[DETECT_SM_LIST_MATCH]; /* check for conflicting keywords */ for ( ;sm != NULL; sm = sm->next) { @@ -1868,6 +1887,11 @@ static int SignatureCreateMask(Signature *s) { SCLogDebug("sig requires http app state"); } + if (s->sm_lists[DETECT_SM_LIST_HCDMATCH] != 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) { @@ -1959,6 +1983,9 @@ static void SigInitStandardMpmFactoryContexts(DetectEngineCtx *de_ctx) de_ctx->sgh_mpm_context_hmd = MpmFactoryRegisterMpmCtxProfile("hmd", MPM_CTX_FACTORY_FLAGS_PREPARE_WITH_SIG_GROUP_BUILD); + de_ctx->sgh_mpm_context_hcd = + MpmFactoryRegisterMpmCtxProfile("hcd", + MPM_CTX_FACTORY_FLAGS_PREPARE_WITH_SIG_GROUP_BUILD); de_ctx->sgh_mpm_context_app_proto_detect = MpmFactoryRegisterMpmCtxProfile("app_proto_detect", 0); @@ -3812,6 +3839,12 @@ int SigGroupBuild (DetectEngineCtx *de_ctx) { } //printf("hmd- %d\n", mpm_ctx->pattern_cnt); + mpm_ctx = MpmFactoryGetMpmCtxForProfile(de_ctx->sgh_mpm_context_hcd); + if (mpm_table[de_ctx->mpm_matcher].Prepare != NULL) { + mpm_table[de_ctx->mpm_matcher].Prepare(mpm_ctx); + } + //printf("hcd- %d\n", mpm_ctx->pattern_cnt); + mpm_ctx = MpmFactoryGetMpmCtxForProfile(de_ctx->sgh_mpm_context_stream); if (mpm_table[de_ctx->mpm_matcher].Prepare != NULL) { mpm_table[de_ctx->mpm_matcher].Prepare(mpm_ctx); diff --git a/src/detect.h b/src/detect.h index 57220028ac..21cb306f03 100644 --- a/src/detect.h +++ b/src/detect.h @@ -94,6 +94,8 @@ enum { DETECT_SM_LIST_HRHDMATCH, /* list for http_method keyword and the ones relative to it */ DETECT_SM_LIST_HMDMATCH, + /* list for http_cookie keyword and the ones relative to it */ + DETECT_SM_LIST_HCDMATCH, DETECT_SM_LIST_MAX, }; @@ -247,7 +249,10 @@ typedef struct DetectPort_ { #define SIG_FLAG_MPM_HMDCONTENT 0x02000000 #define SIG_FLAG_MPM_HMDCONTENT_NEG 0x04000000 -#define SIG_FLAG_REQUIRE_FLOWVAR 0x08000000 /**< signature can only match if a flowbit, flowvar or flowint is available. */ +#define SIG_FLAG_MPM_HCDCONTENT 0x08000000 +#define SIG_FLAG_MPM_HCDCONTENT_NEG 0x10000000 + +#define SIG_FLAG_REQUIRE_FLOWVAR 0x20000000 /**< signature can only match if a flowbit, flowvar or flowint is available. */ /* signature init flags */ #define SIG_FLAG_DEONLY 0x00000001 /**< decode event only signature */ @@ -654,6 +659,7 @@ typedef struct DetectEngineCtx_ { int32_t sgh_mpm_context_hhd; int32_t sgh_mpm_context_hrhd; int32_t sgh_mpm_context_hmd; + int32_t sgh_mpm_context_hcd; int32_t sgh_mpm_context_app_proto_detect; /** sgh for signatures that match against invalid packets. In those cases @@ -811,18 +817,20 @@ typedef struct SigTableElmt_ { #define SIG_GROUP_HAVEHHDCONTENT 0x00000010 #define SIG_GROUP_HAVEHRHDCONTENT 0x00000020 #define SIG_GROUP_HAVEHMDCONTENT 0x00000040 -#define SIG_GROUP_HEAD_MPM_COPY 0x00000080 -#define SIG_GROUP_HEAD_MPM_URI_COPY 0x00000100 -#define SIG_GROUP_HEAD_MPM_STREAM_COPY 0x00000200 -#define SIG_GROUP_HEAD_FREE 0x00000400 -#define SIG_GROUP_HEAD_MPM_PACKET 0x00000800 -#define SIG_GROUP_HEAD_MPM_STREAM 0x00001000 -#define SIG_GROUP_HEAD_MPM_URI 0x00002000 -#define SIG_GROUP_HEAD_MPM_HCBD 0x00004000 -#define SIG_GROUP_HEAD_MPM_HHD 0x00008000 -#define SIG_GROUP_HEAD_MPM_HRHD 0x00010000 -#define SIG_GROUP_HEAD_MPM_HMD 0x00020000 -#define SIG_GROUP_HEAD_REFERENCED 0x00040000 /**< sgh is being referenced by others, don't clear */ +#define SIG_GROUP_HAVEHCDCONTENT 0x00000080 +#define SIG_GROUP_HEAD_MPM_COPY 0x00000100 +#define SIG_GROUP_HEAD_MPM_URI_COPY 0x00000200 +#define SIG_GROUP_HEAD_MPM_STREAM_COPY 0x00000400 +#define SIG_GROUP_HEAD_FREE 0x00000800 +#define SIG_GROUP_HEAD_MPM_PACKET 0x00001000 +#define SIG_GROUP_HEAD_MPM_STREAM 0x00002000 +#define SIG_GROUP_HEAD_MPM_URI 0x00004000 +#define SIG_GROUP_HEAD_MPM_HCBD 0x00008000 +#define SIG_GROUP_HEAD_MPM_HHD 0x00010000 +#define SIG_GROUP_HEAD_MPM_HRHD 0x00020000 +#define SIG_GROUP_HEAD_MPM_HMD 0x00040000 +#define SIG_GROUP_HEAD_MPM_HCD 0x00080000 +#define SIG_GROUP_HEAD_REFERENCED 0x00100000 /**< sgh is being referenced by others, don't clear */ typedef struct SigGroupHeadInitData_ { /* list of content containers @@ -867,6 +875,7 @@ typedef struct SigGroupHead_ { MpmCtx *mpm_hhd_ctx; MpmCtx *mpm_hrhd_ctx; MpmCtx *mpm_hmd_ctx; + MpmCtx *mpm_hcd_ctx; uint16_t mpm_streamcontent_maxlen; uint16_t mpm_uricontent_maxlen; diff --git a/src/suricata.c b/src/suricata.c index bf6d8b94c5..a6469ecaa1 100644 --- a/src/suricata.c +++ b/src/suricata.c @@ -58,6 +58,7 @@ #include "detect-engine-hhd.h" #include "detect-engine-hrhd.h" #include "detect-engine-hmd.h" +#include "detect-engine-hcd.h" #include "detect-engine-state.h" #include "detect-engine-tag.h" #include "detect-fast-pattern.h" @@ -1020,6 +1021,7 @@ int main(int argc, char **argv) DetectEngineHttpHeaderRegisterTests(); DetectEngineHttpRawHeaderRegisterTests(); DetectEngineHttpMethodRegisterTests(); + DetectEngineHttpCookieRegisterTests(); DetectEngineRegisterTests(); SCLogRegisterTests(); if (list_unittests) {