diff --git a/src/Makefile.am b/src/Makefile.am index cf34dac053..2b473e2bb2 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -66,6 +66,7 @@ detect-engine-uri.c detect-engine-uri.h \ 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-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 597aad305d..7b55985c72 100644 --- a/src/detect-content.h +++ b/src/detect-content.h @@ -48,6 +48,7 @@ #define DETECT_CONTENT_HCBD_MPM 0x00004000 #define DETECT_CONTENT_HHD_MPM 0x00008000 #define DETECT_CONTENT_HRHD_MPM 0x00010000 +#define DETECT_CONTENT_HMD_MPM 0x00020000 #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 27d7b91d96..6b6ebc05f9 100644 --- a/src/detect-depth.c +++ b/src/detect-depth.c @@ -85,16 +85,18 @@ static int DetectDepthSetup (DetectEngineCtx *de_ctx, Signature *s, char *depths break; default: - pm = SigMatchGetLastSMFromLists(s, 10, + pm = SigMatchGetLastSMFromLists(s, 12, 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_RAW_HEADER, s->sm_lists_tail[DETECT_SM_LIST_HRHDMATCH], + DETECT_AL_HTTP_METHOD, s->sm_lists_tail[DETECT_SM_LIST_HMDMATCH]); if (pm == NULL) { SCLogError(SC_ERR_DEPTH_MISSING_CONTENT, "depth needs " "preceeding content, uricontent option, http_client_body, " - "http_header option or http_raw_header option"); + "http_header option, http_raw_header option or " + "http_method option"); if (dubbed) SCFree(str); return -1; @@ -257,6 +259,34 @@ static int DetectDepthSetup (DetectEngineCtx *de_ctx, Signature *s, char *depths break; + case DETECT_AL_HTTP_METHOD: + 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 9625534444..63d7b305f8 100644 --- a/src/detect-distance.c +++ b/src/detect-distance.c @@ -168,16 +168,17 @@ static int DetectDistanceSetup (DetectEngineCtx *de_ctx, Signature *s, } } } else { - pm = SigMatchGetLastSMFromLists(s, 10, + pm = SigMatchGetLastSMFromLists(s, 12, 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_RAW_HEADER, s->sm_lists_tail[DETECT_SM_LIST_HRHDMATCH], + DETECT_AL_HTTP_METHOD, s->sm_lists_tail[DETECT_SM_LIST_HMDMATCH]); if (pm == NULL) { SCLogError(SC_ERR_WITHIN_MISSING_CONTENT, "within needs" "preceeding content, uricontent option, http_client_body, " - "http_header or http_raw_header option"); + "http_header, http_raw_header or http_method option"); if (dubbed) SCFree(str); return -1; @@ -529,6 +530,59 @@ static int DetectDistanceSetup (DetectEngineCtx *de_ctx, Signature *s, break; + case DETECT_AL_HTTP_METHOD: + 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_METHOD, pm->prev, + DETECT_PCRE, pm->prev); + if (pm == NULL) { + SCLogError(SC_ERR_DISTANCE_MISSING_CONTENT, "distance for " + "http_method needs preceeding http_method " + "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-hmd.c b/src/detect-engine-hmd.c new file mode 100644 index 0000000000..01e9de061f --- /dev/null +++ b/src/detect-engine-hmd.c @@ -0,0 +1,2029 @@ +/* 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-hmd.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 method. + * + * 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 method buffer to inspect. + * \param payload_len Length of the http raw headers buffer. + * + * \retval 0 no match. + * \retval 1 match. + */ +static int DoInspectHttpMethod(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_METHOD) { + if (payload_len == 0) { + SCReturnInt(0); + } + + DetectContentData *cd = (DetectContentData *)sm->ctx; + SCLogDebug("inspecting http method %"PRIu32" payload_len %"PRIu32, + cd->id, payload_len); + + if (cd->flags & DETECT_CONTENT_HMD_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 raw header content + * and see if the others match then until we run out of matches */ + int r = DoInspectHttpMethod(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 = DoInspectHttpMethod(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 = DoInspectHttpMethod(de_ctx, det_ctx, s, sm->next, payload, + payload_len); + SCReturnInt(r); + } else { + SCReturnInt(1); + } +} + +int DetectEngineRunHttpMethodMpm(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 || tx->request_method == NULL) + continue; + + cnt += HttpMethodPatternSearch(det_ctx, + (uint8_t *)bstr_ptr(tx->request_method), + bstr_len(tx->request_method)); + } + + end: + SCMutexUnlock(&f->m); + return cnt; +} + +/** + * \brief Do the http_method 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 DetectEngineInspectHttpMethod(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 || tx->request_method == NULL) + continue; + + r = DoInspectHttpMethod(de_ctx, det_ctx, s, s->sm_lists[DETECT_SM_LIST_HMDMATCH], + (uint8_t *)bstr_ptr(tx->request_method), + bstr_len(tx->request_method)); + if (r == 1) { + break; + } + } + +end: + SCMutexUnlock(&f->m); + SCReturnInt(r); +} + +/***********************************Unittests**********************************/ + +#ifdef UNITTESTS + +/** + * \test Test that the http_method content matches against a http request + * which holds the content. + */ +static int DetectEngineHttpMethodTest01(void) +{ + TcpSession ssn; + Packet *p = NULL; + ThreadVars th_v; + DetectEngineCtx *de_ctx = NULL; + DetectEngineThreadCtx *det_ctx = NULL; + HtpState *http_state = NULL; + Flow f; + uint8_t http_buf[] = + "GET /index.html HTTP/1.0\r\n" + "Host: 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:\"GET\"; http_method; " + "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_method content matches against a http request + * which holds the content. + */ +static int DetectEngineHttpMethodTest02(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" + "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_method; " + "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_method content matches against a http request + * which holds the content. + */ +static int DetectEngineHttpMethodTest03(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" + "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_method; " + "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_method content matches against a http request + * which holds the content. + */ +static int DetectEngineHttpMethodTest04(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" + "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_method; " + "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_method content matches against a http request + * which holds the content. + */ +static int DetectEngineHttpMethodTest05(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" + "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_method; " + "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_method content matches against a http request + * which holds the content. + */ +static int DetectEngineHttpMethodTest06(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" + "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_method; " + "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_method content matches against a http request + * which holds the content. + */ +static int DetectEngineHttpMethodTest07(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" + "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_method; " + "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_method content matches against a http request + * which holds the content. + */ +static int DetectEngineHttpMethodTest08(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" + "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_method; " + "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_method content matches against a http request + * which holds the content. + */ +static int DetectEngineHttpMethodTest09(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" + "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_method; " + "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_method content matches against a http request + * which holds the content. + */ +static int DetectEngineHttpMethodTest10(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" + "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_method; " + "content:EC; within:4; http_method; " + "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_method content matches against a http request + * which holds the content. + */ +static int DetectEngineHttpMethodTest11(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" + "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_method; " + "content:!EC; within:3; http_method; " + "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_method content matches against a http request + * which holds the content. + */ +static int DetectEngineHttpMethodTest12(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" + "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_method; " + "content:EC; within:3; http_method; " + "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_method content matches against a http request + * which holds the content. + */ +static int DetectEngineHttpMethodTest13(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" + "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_method; " + "content:!EC; within:4; http_method; " + "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_method content matches against a http request + * which holds the content. + */ +static int DetectEngineHttpMethodTest14(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" + "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_method; " + "content:EC; distance:2; http_method; " + "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_method content matches against a http request + * which holds the content. + */ +static int DetectEngineHttpMethodTest15(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" + "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_method; " + "content:!EC; distance:3; http_method; " + "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_method content matches against a http request + * which holds the content. + */ +static int DetectEngineHttpMethodTest16(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" + "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_method; " + "content:EC; distance:3; http_method; " + "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_method content matches against a http request + * which holds the content. + */ +static int DetectEngineHttpMethodTest17(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" + "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_method; " + "content:!EC; distance:2; http_method; " + "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 DetectEngineHttpMethodRegisterTests(void) +{ + +#ifdef UNITTESTS + UtRegisterTest("DetectEngineHttpMethodTest01", + DetectEngineHttpMethodTest01, 1); + UtRegisterTest("DetectEngineHttpMethodTest02", + DetectEngineHttpMethodTest02, 1); + UtRegisterTest("DetectEngineHttpMethodTest03", + DetectEngineHttpMethodTest03, 1); + UtRegisterTest("DetectEngineHttpMethodTest04", + DetectEngineHttpMethodTest04, 1); + UtRegisterTest("DetectEngineHttpMethodTest05", + DetectEngineHttpMethodTest05, 1); + UtRegisterTest("DetectEngineHttpMethodTest06", + DetectEngineHttpMethodTest06, 1); + UtRegisterTest("DetectEngineHttpMethodTest07", + DetectEngineHttpMethodTest07, 1); + UtRegisterTest("DetectEngineHttpMethodTest08", + DetectEngineHttpMethodTest08, 1); + UtRegisterTest("DetectEngineHttpMethodTest09", + DetectEngineHttpMethodTest09, 1); + UtRegisterTest("DetectEngineHttpMethodTest10", + DetectEngineHttpMethodTest10, 1); + UtRegisterTest("DetectEngineHttpMethodTest11", + DetectEngineHttpMethodTest11, 1); + UtRegisterTest("DetectEngineHttpMethodTest12", + DetectEngineHttpMethodTest12, 1); + UtRegisterTest("DetectEngineHttpMethodTest13", + DetectEngineHttpMethodTest13, 1); + UtRegisterTest("DetectEngineHttpMethodTest14", + DetectEngineHttpMethodTest14, 1); + UtRegisterTest("DetectEngineHttpMethodTest15", + DetectEngineHttpMethodTest15, 1); + UtRegisterTest("DetectEngineHttpMethodTest16", + DetectEngineHttpMethodTest16, 1); + UtRegisterTest("DetectEngineHttpMethodTest17", + DetectEngineHttpMethodTest17, 1); +#endif /* UNITTESTS */ + + return; +} diff --git a/src/detect-engine-hmd.h b/src/detect-engine-hmd.h new file mode 100644 index 0000000000..18bddcfb14 --- /dev/null +++ b/src/detect-engine-hmd.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_HMD_H__ +#define __DETECT_ENGINE_HMD_H__ + +#include "app-layer-htp.h" + +int DetectEngineInspectHttpMethod(DetectEngineCtx *, DetectEngineThreadCtx *, + Signature *, Flow *, uint8_t, void *); +int DetectEngineRunHttpMethodMpm(DetectEngineThreadCtx *, Flow *, HtpState *); +void DetectEngineHttpMethodRegisterTests(void); + +#endif /* __DETECT_ENGINE_HMD_H__ */ diff --git a/src/detect-engine-mpm.c b/src/detect-engine-mpm.c index 0b70814b25..c4fc886772 100644 --- a/src/detect-engine-mpm.c +++ b/src/detect-engine-mpm.c @@ -331,6 +331,31 @@ uint32_t HttpRawHeaderPatternSearch(DetectEngineThreadCtx *det_ctx, SCReturnUInt(ret); } +/** + * \brief Http method match -- searches for one pattern per signature. + * + * \param det_ctx Detection engine thread ctx. + * \param method Method to inspect. + * \param method_len Method length. + * + * \retval ret Number of matches. + */ +uint32_t HttpMethodPatternSearch(DetectEngineThreadCtx *det_ctx, + uint8_t *raw_method, uint32_t raw_method_len) +{ + SCEnter(); + + if (det_ctx->sgh->mpm_hmd_ctx == NULL) + SCReturnUInt(0); + + uint32_t ret; + ret = mpm_table[det_ctx->sgh->mpm_hmd_ctx->mpm_type]. + Search(det_ctx->sgh->mpm_hmd_ctx, &det_ctx->mtcu, + &det_ctx->pmq, raw_method, raw_method_len); + + SCReturnUInt(ret); +} + /** \brief Pattern match -- searches for only one pattern per signature. * * \param det_ctx detection engine thread ctx @@ -627,6 +652,7 @@ static void PopulateMpmAddPatternToMpm(DetectEngineCtx *de_ctx, DetectContentData *hcbd = NULL; DetectContentData *hhd = NULL; DetectContentData *hrhd = NULL; + DetectContentData *hmd = NULL; switch (mpm_sm->type) { case DETECT_CONTENT: { @@ -799,7 +825,7 @@ static void PopulateMpmAddPatternToMpm(DetectEngineCtx *de_ctx, } /* tell matcher we are inspecting uri */ s->flags |= SIG_FLAG_MPM_URICONTENT; - s->mpm_uripattern_id = ud->id; + s->mpm_http_pattern_id = ud->id; if (ud->flags & DETECT_CONTENT_NEGATED) s->flags |= SIG_FLAG_MPM_URICONTENT_NEG; @@ -854,7 +880,7 @@ static void PopulateMpmAddPatternToMpm(DetectEngineCtx *de_ctx, } /* tell matcher we are inspecting uri */ s->flags |= SIG_FLAG_MPM_HCBDCONTENT; - s->mpm_hcbdpattern_id = hcbd->id; + s->mpm_http_pattern_id = hcbd->id; if (hcbd->flags & DETECT_CONTENT_NEGATED) s->flags |= SIG_FLAG_MPM_HCBDCONTENT_NEG; @@ -909,7 +935,7 @@ static void PopulateMpmAddPatternToMpm(DetectEngineCtx *de_ctx, } /* tell matcher we are inspecting uri */ s->flags |= SIG_FLAG_MPM_HHDCONTENT; - s->mpm_hhdpattern_id = hhd->id; + s->mpm_http_pattern_id = hhd->id; if (hhd->flags & DETECT_CONTENT_NEGATED) s->flags |= SIG_FLAG_MPM_HHDCONTENT_NEG; @@ -964,7 +990,7 @@ static void PopulateMpmAddPatternToMpm(DetectEngineCtx *de_ctx, } /* tell matcher we are inspecting uri */ s->flags |= SIG_FLAG_MPM_HRHDCONTENT; - s->mpm_hrhdpattern_id = hrhd->id; + s->mpm_http_pattern_id = hrhd->id; if (hrhd->flags & DETECT_CONTENT_NEGATED) s->flags |= SIG_FLAG_MPM_HRHDCONTENT_NEG; @@ -973,6 +999,61 @@ static void PopulateMpmAddPatternToMpm(DetectEngineCtx *de_ctx, break; } /* case DETECT_AL_HTTP_RAW_HEADER */ + case DETECT_AL_HTTP_METHOD: + { + hmd = (DetectContentData *)mpm_sm->ctx; + if (hmd->flags & DETECT_CONTENT_FAST_PATTERN_CHOP) { + /* add the content to the "hmd" mpm */ + if (hmd->flags & DETECT_CONTENT_NOCASE) { + mpm_table[sgh->mpm_hmd_ctx->mpm_type]. + AddPatternNocase(sgh->mpm_hmd_ctx, + hmd->content + hmd->fp_chop_offset, + hmd->fp_chop_len, + 0, 0, hmd->id, s->num, flags); + } else { + mpm_table[sgh->mpm_hmd_ctx->mpm_type]. + AddPattern(sgh->mpm_hmd_ctx, + hmd->content + hmd->fp_chop_offset, + hmd->fp_chop_len, + 0, 0, hmd->id, s->num, flags); + } + } else { + if (hmd->flags & DETECT_CONTENT_FAST_PATTERN_ONLY) { + if (DETECT_CONTENT_IS_SINGLE(hmd)) { + hmd->flags |= DETECT_CONTENT_HMD_MPM; + } + + /* see if we can bypass the match validation for this pattern */ + } else { + if (DETECT_CONTENT_IS_SINGLE(hmd)) { + hmd->flags |= DETECT_CONTENT_HMD_MPM; + } + } /* else - if (hmd->flags & DETECT_CONTENT_FAST_PATTERN_ONLY) */ + + /* add the content to the "hmd" mpm */ + if (hmd->flags & DETECT_CONTENT_NOCASE) { + mpm_table[sgh->mpm_hmd_ctx->mpm_type]. + AddPatternNocase(sgh->mpm_hmd_ctx, + hmd->content, hmd->content_len, + 0, 0, hmd->id, s->num, flags); + } else { + mpm_table[sgh->mpm_hmd_ctx->mpm_type]. + AddPattern(sgh->mpm_hmd_ctx, + hmd->content, hmd->content_len, + 0, 0, hmd->id, s->num, flags); + } + } + /* tell matcher we are inspecting uri */ + s->flags |= SIG_FLAG_MPM_HMDCONTENT; + s->mpm_http_pattern_id = hmd->id; + if (hmd->flags & DETECT_CONTENT_NEGATED) + s->flags |= SIG_FLAG_MPM_HMDCONTENT_NEG; + + sgh->flags |= SIG_GROUP_HEAD_MPM_HMD; + + break; + } /* case DETECT_AL_HTTP_METHOD */ + } /* switch (mpm_sm->type) */ SCLogDebug("%"PRIu32" adding cd->id %"PRIu32" to the mpm phase " @@ -1270,6 +1351,8 @@ int PatternMatchPrepareGroup(DetectEngineCtx *de_ctx, SigGroupHead *sh) uint32_t has_co_hhd = 0; /* used to indicate if sgh has atleast one sig with http_raw_header */ uint32_t has_co_hrhd = 0; + /* used to indicate if sgh has atleast one sig with http_method */ + uint32_t has_co_hmd = 0; //uint32_t cnt = 0; uint32_t sig = 0; @@ -1304,6 +1387,9 @@ int PatternMatchPrepareGroup(DetectEngineCtx *de_ctx, SigGroupHead *sh) has_co_hrhd = 1; } + if (s->sm_lists[DETECT_SM_LIST_HMDMATCH] != NULL) { + has_co_hmd = 1; + } } if (has_co_packet > 0) { @@ -1324,6 +1410,9 @@ int PatternMatchPrepareGroup(DetectEngineCtx *de_ctx, SigGroupHead *sh) if (has_co_hrhd > 0) { sh->flags |= SIG_GROUP_HAVEHRHDCONTENT; } + if (has_co_hmd > 0) { + sh->flags |= SIG_GROUP_HAVEHMDCONTENT; + } /* intialize contexes */ if (sh->flags & SIG_GROUP_HAVECONTENT) { @@ -1434,12 +1523,31 @@ int PatternMatchPrepareGroup(DetectEngineCtx *de_ctx, SigGroupHead *sh) #endif } + if (sh->flags & SIG_GROUP_HAVEHMDCONTENT) { + if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_SINGLE) { + sh->mpm_hmd_ctx = MpmFactoryGetMpmCtxForProfile(de_ctx->sgh_mpm_context_hmd); + } else { + sh->mpm_hmd_ctx = MpmFactoryGetMpmCtxForProfile(MPM_CTX_FACTORY_UNIQUE_CONTEXT); + } + if (sh->mpm_hmd_ctx == NULL) { + SCLogDebug("sh->mpm_hmd_ctx == NULL. This should never happen"); + exit(EXIT_FAILURE); + } + +#ifndef __SC_CUDA_SUPPORT__ + MpmInitCtx(sh->mpm_hmd_ctx, de_ctx->mpm_matcher, -1); +#else + MpmInitCtx(sh->mpm_hmd_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_HAVEHRHDCONTENT || + sh->flags & SIG_GROUP_HAVEHMDCONTENT) { PatternMatchPreparePopulateMpm(de_ctx, sh); @@ -1510,6 +1618,17 @@ int PatternMatchPrepareGroup(DetectEngineCtx *de_ctx, SigGroupHead *sh) } } } + if (sh->mpm_hmd_ctx != NULL) { + if (sh->mpm_hmd_ctx->pattern_cnt == 0) { + MpmFactoryReClaimMpmCtx(sh->mpm_hmd_ctx); + sh->mpm_hmd_ctx = NULL; + } else { + if (sh->flags & SIG_GROUP_HAVEHMDCONTENT) { + if (mpm_table[sh->mpm_hmd_ctx->mpm_type].Prepare != NULL) + mpm_table[sh->mpm_hmd_ctx->mpm_type].Prepare(sh->mpm_hmd_ctx); + } + } + } } /* if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) */ } else { @@ -1525,6 +1644,8 @@ int PatternMatchPrepareGroup(DetectEngineCtx *de_ctx, SigGroupHead *sh) sh->mpm_hhd_ctx = NULL; MpmFactoryReClaimMpmCtx(sh->mpm_hrhd_ctx); sh->mpm_hrhd_ctx = NULL; + MpmFactoryReClaimMpmCtx(sh->mpm_hmd_ctx); + sh->mpm_hmd_ctx = NULL; } diff --git a/src/detect-engine-mpm.h b/src/detect-engine-mpm.h index adfcfc3350..c358458bce 100644 --- a/src/detect-engine-mpm.h +++ b/src/detect-engine-mpm.h @@ -40,6 +40,7 @@ uint32_t StreamPatternSearch(DetectEngineThreadCtx *, Packet *, StreamMsg *, uin uint32_t HttpClientBodyPatternSearch(DetectEngineThreadCtx *, uint8_t *, uint32_t); uint32_t HttpHeaderPatternSearch(DetectEngineThreadCtx *, uint8_t *, uint32_t); uint32_t HttpRawHeaderPatternSearch(DetectEngineThreadCtx *, uint8_t *, uint32_t); +uint32_t HttpMethodPatternSearch(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 ad065684b0..66c09fe5ec 100644 --- a/src/detect-engine-state.c +++ b/src/detect-engine-state.c @@ -34,6 +34,7 @@ #include "detect-engine-hcbd.h" #include "detect-engine-hhd.h" #include "detect-engine-hrhd.h" +#include "detect-engine-hmd.h" #include "detect-engine-dcepayload.h" #include "stream-tcp.h" @@ -205,10 +206,13 @@ int DeStateUpdateInspectTransactionId(Flow *f, char direction) { * \param uri did uri already match (if any) * \param dce did dce already match (if any) * \param hcbd did http client body already match (if any) + * + * \todo Need to use an array to transfer all these args. Pushing so + * many args is slow. */ static void DeStateSignatureAppend(DetectEngineState *state, Signature *s, SigMatch *sm, char uri, char dce, char hcbd, - char hhd, char hrhd) { + char hhd, char hrhd, char hmd) { DeStateStore *store = state->tail; if (store == NULL) { @@ -251,6 +255,9 @@ static void DeStateSignatureAppend(DetectEngineState *state, Signature *s, if (hrhd) { store->store[idx].flags |= DE_STATE_FLAG_HRHD_MATCH; } + if (hmd) { + store->store[idx].flags |= DE_STATE_FLAG_HMD_MATCH; + } store->store[idx].nm = sm; state->cnt++; @@ -316,6 +323,8 @@ int DeStateDetectStartDetection(ThreadVars *tv, DetectEngineCtx *de_ctx, char hhdinspect = 0; char hrhdmatch = 0; char hrhdinspect = 0; + char hmdinspect = 0; + char hmdmatch = 0; char dmatch = 0; char dinspect = 0; char appinspect = 0; @@ -367,6 +376,14 @@ int DeStateDetectStartDetection(ThreadVars *tv, DetectEngineCtx *de_ctx, } SCLogDebug("inspecting http raw header"); } + if (s->sm_lists[DETECT_SM_LIST_HMDMATCH] != NULL) { + hmdinspect = 1; + if (DetectEngineInspectHttpMethod(de_ctx, det_ctx, s, f, + flags, alstate) == 1) { + hmdmatch = 1; + } + SCLogDebug("inspecting http method"); + } } else if (alproto == ALPROTO_DCERPC || alproto == ALPROTO_SMB || alproto == ALPROTO_SMB2) { if (s->sm_lists[DETECT_SM_LIST_DMATCH] != NULL) { @@ -398,8 +415,8 @@ int DeStateDetectStartDetection(ThreadVars *tv, DetectEngineCtx *de_ctx, } } - appinspect = uinspect + dinspect + hcbdinspect + hhdinspect + hrhdinspect; - appmatch = umatch + dmatch + hcbdmatch + hhdmatch + hrhdmatch; + appinspect = uinspect + dinspect + hcbdinspect + hhdinspect + hrhdinspect + hmdinspect; + appmatch = umatch + dmatch + hcbdmatch + hhdmatch + hrhdmatch + hmdmatch; if (s->sm_lists[DETECT_SM_LIST_AMATCH] != NULL) { for ( ; sm != NULL; sm = sm->next) { @@ -442,7 +459,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", sm, umatch, dmatch, hcbdmatch, hhdmatch, hrhdmatch); + "hhd %d, hrhd %d hmd %d", sm, umatch, dmatch, hcbdmatch, + hhdmatch, hrhdmatch, hmdmatch); SCMutexLock(&f->de_state_m); /* match or no match, we store the state anyway @@ -453,7 +471,7 @@ 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); + DeStateSignatureAppend(f->de_state, s, sm, umatch, dmatch, hcbdmatch, hhdmatch, hrhdmatch, hmdmatch); } SCMutexUnlock(&f->de_state_m); @@ -481,6 +499,8 @@ int DeStateDetectContinueDetection(ThreadVars *tv, DetectEngineCtx *de_ctx, Dete char hhdinspect = 0; char hrhdmatch = 0; char hrhdinspect = 0; + char hmdmatch = 0; + char hmdinspect = 0; char dmatch = 0; char dinspect = 0; char appinspect = 0; @@ -513,6 +533,8 @@ int DeStateDetectContinueDetection(ThreadVars *tv, DetectEngineCtx *de_ctx, Dete hhdinspect = 0; hrhdmatch = 0; hrhdinspect = 0; + hmdmatch = 0; + hmdinspect = 0; dmatch = 0; dinspect = 0; appinspect = 0; @@ -595,6 +617,19 @@ int DeStateDetectContinueDetection(ThreadVars *tv, DetectEngineCtx *de_ctx, Dete } } } + if (s->sm_lists[DETECT_SM_LIST_HMDMATCH] != NULL) { + if (!(item->flags & DE_STATE_FLAG_HMD_MATCH)) { + SCLogDebug("inspecting http method data"); + hmdinspect = 1; + + if (DetectEngineInspectHttpMethod(de_ctx, det_ctx, s, f, + flags, alstate) == 1) { + SCLogDebug("http method matched"); + item->flags |= DE_STATE_FLAG_HMD_MATCH; + hmdmatch = 1; + } + } + } } else if (alproto == ALPROTO_DCERPC || alproto == ALPROTO_SMB || alproto == ALPROTO_SMB2) { if (s->sm_lists[DETECT_SM_LIST_DMATCH] != NULL) { @@ -633,8 +668,8 @@ int DeStateDetectContinueDetection(ThreadVars *tv, DetectEngineCtx *de_ctx, Dete } - appinspect = uinspect + dinspect + hcbdinspect + hhdinspect + hrhdinspect; - appmatch = umatch + dmatch + hcbdmatch + hhdmatch + hrhdmatch; + appinspect = uinspect + dinspect + hcbdinspect + hhdinspect + hrhdinspect + hmdinspect; + appmatch = umatch + dmatch + hcbdmatch + hhdmatch + hrhdmatch + hmdmatch; SCLogDebug("appinspect %d, appmatch %d", appinspect, appmatch); /* next, check the other sig matches */ @@ -774,39 +809,39 @@ static int DeStateTest02(void) { memset(&s, 0x00, sizeof(s)); s.num = 0; - DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0); + DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0, 0); s.num = 11; - DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0); + DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0, 0); s.num = 22; - DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0); + DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0, 0); s.num = 33; - DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0); + DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0, 0); s.num = 44; - DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0); + DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0, 0); s.num = 55; - DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0); + DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0, 0); s.num = 66; - DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0); + DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0, 0); s.num = 77; - DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0); + DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0, 0); s.num = 88; - DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0); + DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0, 0); s.num = 99; - DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0); + DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0, 0); s.num = 100; - DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0); + DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0, 0); s.num = 111; - DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0); + DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0, 0); s.num = 122; - DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0); + DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0, 0); s.num = 133; - DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0); + DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0, 0); s.num = 144; - DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0); + DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0, 0); s.num = 155; - DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0); + DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0, 0); s.num = 166; - DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0); + DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0, 0); if (state->head == NULL) { goto end; @@ -849,9 +884,9 @@ static int DeStateTest03(void) { memset(&s, 0x00, sizeof(s)); s.num = 11; - DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0); + DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0, 0); s.num = 22; - DeStateSignatureAppend(state, &s, NULL, 1, 0, 0, 0, 0); + DeStateSignatureAppend(state, &s, NULL, 1, 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 3d5bd34c38..6c8298ff0c 100644 --- a/src/detect-engine-state.h +++ b/src/detect-engine-state.h @@ -50,7 +50,8 @@ #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_FULL_MATCH 0x40 /**< sig already fully matched */ +#define DE_STATE_FLAG_HMD_MATCH 0x40 /**< hmd payload inspection part matched */ +#define DE_STATE_FLAG_FULL_MATCH 0x80 /**< 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 79c349e6e6..47d334d82d 100644 --- a/src/detect-fast-pattern.c +++ b/src/detect-fast-pattern.c @@ -134,6 +134,9 @@ void SupportFastPatternForSigMatchTypes(void) SupportFastPatternForSigMatchType(DETECT_AL_HTTP_RAW_HEADER); SupportFastPatternForSigMatchList(DETECT_SM_LIST_HRHDMATCH); + SupportFastPatternForSigMatchType(DETECT_AL_HTTP_METHOD); + SupportFastPatternForSigMatchList(DETECT_SM_LIST_HMDMATCH); + return; } @@ -202,21 +205,23 @@ static int DetectFastPatternSetup(DetectEngineCtx *de_ctx, Signature *s, char *a s->sm_lists_tail[DETECT_SM_LIST_UMATCH] == NULL && 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_HRHDMATCH] == NULL && + s->sm_lists_tail[DETECT_SM_LIST_HMDMATCH] == 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 and " - "http_raw_header"); + "uricontent, http_client_body, http_header, " + "http_raw_header and http_method"); return -1; } - SigMatch *pm = SigMatchGetLastSMFromLists(s, 10, + SigMatch *pm = SigMatchGetLastSMFromLists(s, 12, 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_RAW_HEADER, s->sm_lists_tail[DETECT_SM_LIST_HRHDMATCH], + DETECT_AL_HTTP_METHOD, s->sm_lists_tail[DETECT_SM_LIST_HMDMATCH]); if (pm == NULL) { SCLogError(SC_ERR_INVALID_SIGNATURE, "fast_pattern found inside " "the rule, without a content context. Please use a " @@ -7661,6 +7666,1129 @@ int DetectFastPatternTest260(void) return result; } + + + + + + + + + + + + + + + + + + +int DetectFastPatternTest261(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_method; " + "content:!oneonetwo; fast_pattern:3,4; http_method; " + "content:three; http_method; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HMDMATCH]->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 DetectFastPatternTest262(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_method; " + "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_HMDMATCH]; + 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 DetectFastPatternTest263(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_method; " + "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_HMDMATCH]; + 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 DetectFastPatternTest264(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_method; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + + result = 0; + sm = de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HMDMATCH]; + 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 DetectFastPatternTest265(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_method; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + + result = 0; + sm = de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HMDMATCH]; + 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 DetectFastPatternTest266(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_method; content:two; fast_pattern:only; http_method; distance:10; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest267(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_method; content:two; distance:10; fast_pattern:only; http_method; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest268(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_method; content:two; fast_pattern:only; http_method; within:10; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest269(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_method; content:two; within:10; fast_pattern:only; http_method; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest270(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_method; content:two; fast_pattern:only; http_method; offset:10; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest271(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_method; content:two; offset:10; fast_pattern:only; http_method; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest272(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_method; content:two; fast_pattern:only; http_method; depth:10; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest273(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_method; content:two; depth:10; fast_pattern:only; http_method; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest274(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_method; content:!two; fast_pattern:only; http_method; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest275(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_method; content:two; http_method; distance:30; content:two; fast_pattern:only; http_method; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HMDMATCH]->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 DetectFastPatternTest276(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_method; content:two; http_method; within:30; content:two; fast_pattern:only; http_method; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HMDMATCH]->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 DetectFastPatternTest277(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_method; content:two; http_method; offset:30; content:two; fast_pattern:only; http_method; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HMDMATCH]->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 DetectFastPatternTest278(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_method; content:two; http_method; depth:30; content:two; fast_pattern:only; http_method; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HMDMATCH]->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 DetectFastPatternTest279(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_method; content:two; http_method; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HMDMATCH]->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 DetectFastPatternTest280(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_method; content:!one; fast_pattern; http_method; distance:20; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest281(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_method; content:!one; fast_pattern; http_method; within:20; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest282(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_method; content:!one; fast_pattern; http_method; offset:20; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest283(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_method; content:!one; fast_pattern; http_method; depth:20; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest284(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_method; content:oneonetwo; fast_pattern:3,4; http_method; content:three; http_method; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HMDMATCH]->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 DetectFastPatternTest285(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_method; content:oneonetwo; fast_pattern:3,4; http_method; content:three; http_method; distance:30; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HMDMATCH]->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 DetectFastPatternTest286(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_method; content:oneonetwo; fast_pattern:3,4; http_method; content:three; http_method; within:30; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HMDMATCH]->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 DetectFastPatternTest287(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_method; content:oneonetwo; fast_pattern:3,4; http_method; content:three; http_method; offset:30; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HMDMATCH]->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 DetectFastPatternTest288(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_method; content:oneonetwo; fast_pattern:3,4; http_method; content:three; http_method; depth:30; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HMDMATCH]->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 DetectFastPatternTest289(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_method; content:two; http_method; distance:10; content:oneonethree; fast_pattern:3,4; http_method; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HMDMATCH]->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 DetectFastPatternTest290(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_method; content:two; http_method; within:10; content:oneonethree; fast_pattern:3,4; http_method; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HMDMATCH]->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 DetectFastPatternTest291(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_method; content:two; http_method; offset:10; content:oneonethree; fast_pattern:3,4; http_method; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HMDMATCH]->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 DetectFastPatternTest292(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_method; content:two; http_method; depth:10; content:oneonethree; fast_pattern:3,4; http_method; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HMDMATCH]->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 DetectFastPatternTest293(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_method; content:two; fast_pattern:65977,4; http_method; content:three; http_method; distance:10; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest294(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_method; content:oneonetwo; fast_pattern:3,65977; http_method; content:three; distance:10; http_method; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest295(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_method; content:two; fast_pattern:65534,4; http_method; content:three; http_method; distance:10; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest296(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_method; content:!oneonetwo; fast_pattern:3,4; http_method; content:three; http_method; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HMDMATCH]->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 DetectFastPatternTest297(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_method; content:!oneonetwo; fast_pattern:3,4; http_method; distance:10; content:three; http_method; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest298(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_method; content:!oneonetwo; fast_pattern:3,4; http_method; within:10; content:three; http_method; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest299(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_method; content:!oneonetwo; fast_pattern:3,4; http_method; offset:10; content:three; http_method; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest300(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_method; content:!oneonetwo; fast_pattern:3,4; http_method; depth:10; content:three; http_method; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest301(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_method; content:!oneonetwo; fast_pattern:3,4; http_method; content:three; http_method; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HMDMATCH]->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) @@ -7939,6 +9067,49 @@ void DetectFastPatternRegisterTests(void) UtRegisterTest("DetectFastPatternTest258", DetectFastPatternTest258, 1); UtRegisterTest("DetectFastPatternTest259", DetectFastPatternTest259, 1); UtRegisterTest("DetectFastPatternTest260", DetectFastPatternTest260, 1); + /* http_raw_header fast_pattern tests ^ */ + /* http_method fast_pattern tests v */ + UtRegisterTest("DetectFastPatternTest261", DetectFastPatternTest261, 1); + UtRegisterTest("DetectFastPatternTest262", DetectFastPatternTest262, 1); + UtRegisterTest("DetectFastPatternTest263", DetectFastPatternTest263, 1); + UtRegisterTest("DetectFastPatternTest264", DetectFastPatternTest264, 1); + UtRegisterTest("DetectFastPatternTest265", DetectFastPatternTest265, 1); + UtRegisterTest("DetectFastPatternTest266", DetectFastPatternTest266, 1); + UtRegisterTest("DetectFastPatternTest267", DetectFastPatternTest267, 1); + UtRegisterTest("DetectFastPatternTest268", DetectFastPatternTest268, 1); + UtRegisterTest("DetectFastPatternTest269", DetectFastPatternTest269, 1); + UtRegisterTest("DetectFastPatternTest270", DetectFastPatternTest270, 1); + UtRegisterTest("DetectFastPatternTest271", DetectFastPatternTest271, 1); + UtRegisterTest("DetectFastPatternTest272", DetectFastPatternTest272, 1); + UtRegisterTest("DetectFastPatternTest273", DetectFastPatternTest273, 1); + UtRegisterTest("DetectFastPatternTest274", DetectFastPatternTest274, 1); + UtRegisterTest("DetectFastPatternTest275", DetectFastPatternTest275, 1); + UtRegisterTest("DetectFastPatternTest276", DetectFastPatternTest276, 1); + UtRegisterTest("DetectFastPatternTest277", DetectFastPatternTest277, 1); + UtRegisterTest("DetectFastPatternTest278", DetectFastPatternTest278, 1); + UtRegisterTest("DetectFastPatternTest279", DetectFastPatternTest279, 1); + UtRegisterTest("DetectFastPatternTest280", DetectFastPatternTest280, 1); + UtRegisterTest("DetectFastPatternTest281", DetectFastPatternTest281, 1); + UtRegisterTest("DetectFastPatternTest282", DetectFastPatternTest282, 1); + UtRegisterTest("DetectFastPatternTest283", DetectFastPatternTest283, 1); + UtRegisterTest("DetectFastPatternTest284", DetectFastPatternTest284, 1); + UtRegisterTest("DetectFastPatternTest285", DetectFastPatternTest285, 1); + UtRegisterTest("DetectFastPatternTest286", DetectFastPatternTest286, 1); + UtRegisterTest("DetectFastPatternTest287", DetectFastPatternTest287, 1); + UtRegisterTest("DetectFastPatternTest288", DetectFastPatternTest288, 1); + UtRegisterTest("DetectFastPatternTest289", DetectFastPatternTest289, 1); + UtRegisterTest("DetectFastPatternTest290", DetectFastPatternTest290, 1); + UtRegisterTest("DetectFastPatternTest291", DetectFastPatternTest291, 1); + UtRegisterTest("DetectFastPatternTest292", DetectFastPatternTest292, 1); + UtRegisterTest("DetectFastPatternTest293", DetectFastPatternTest293, 1); + UtRegisterTest("DetectFastPatternTest294", DetectFastPatternTest294, 1); + UtRegisterTest("DetectFastPatternTest295", DetectFastPatternTest295, 1); + UtRegisterTest("DetectFastPatternTest296", DetectFastPatternTest296, 1); + UtRegisterTest("DetectFastPatternTest297", DetectFastPatternTest297, 1); + UtRegisterTest("DetectFastPatternTest298", DetectFastPatternTest298, 1); + UtRegisterTest("DetectFastPatternTest299", DetectFastPatternTest299, 1); + UtRegisterTest("DetectFastPatternTest300", DetectFastPatternTest300, 1); + UtRegisterTest("DetectFastPatternTest301", DetectFastPatternTest301, 1); #endif return; diff --git a/src/detect-flow.c b/src/detect-flow.c index 1927cb3848..e714476f27 100644 --- a/src/detect-flow.c +++ b/src/detect-flow.c @@ -315,7 +315,7 @@ int DetectFlowSetup (DetectEngineCtx *de_ctx, Signature *s, char *flowstr) SigMatchAppendPacket(s, sm); - s->flags |= SIG_FLAG_FLOW; + s->init_flags |= SIG_FLAG_FLOW; return 0; error: diff --git a/src/detect-http-method.c b/src/detect-http-method.c index 5a2d0c8c22..7483d753b8 100644 --- a/src/detect-http-method.c +++ b/src/detect-http-method.c @@ -34,6 +34,7 @@ #include "detect-engine-mpm.h" #include "detect-engine-state.h" #include "detect-content.h" +#include "detect-pcre.h" #include "flow.h" #include "flow-var.h" @@ -64,7 +65,8 @@ void DetectHttpMethodFree(void *); void DetectHttpMethodRegister(void) { sigmatch_table[DETECT_AL_HTTP_METHOD].name = "http_method"; sigmatch_table[DETECT_AL_HTTP_METHOD].Match = NULL; - sigmatch_table[DETECT_AL_HTTP_METHOD].AppLayerMatch = DetectHttpMethodMatch; + //sigmatch_table[DETECT_AL_HTTP_METHOD].AppLayerMatch = DetectHttpMethodMatch; + sigmatch_table[DETECT_AL_HTTP_METHOD].AppLayerMatch = NULL; sigmatch_table[DETECT_AL_HTTP_METHOD].alproto = ALPROTO_HTTP; sigmatch_table[DETECT_AL_HTTP_METHOD].Setup = DetectHttpMethodSetup; sigmatch_table[DETECT_AL_HTTP_METHOD].Free = DetectHttpMethodFree; @@ -140,113 +142,106 @@ int DetectHttpMethodMatch(ThreadVars *t, DetectEngineThreadCtx *det_ctx, } /** - * \brief this function is used to add the parsed "http_method" option - * \brief into the current signature + * \brief This function is used to add the parsed "http_method" option + * into the current signature. * - * \param de_ctx pointer to the Detection Engine Context - * \param s pointer to the Current Signature - * \param str pointer to the user provided option string + * \param de_ctx Pointer to the Detection Engine Context. + * \param s Pointer to the Current Signature. + * \param str Pointer to the user provided option string. * - * \retval 0 on Success - * \retval -1 on Failure + * \retval 0 on Success. + * \retval -1 on Failure. */ static int DetectHttpMethodSetup(DetectEngineCtx *de_ctx, Signature *s, char *str) { SCEnter(); - DetectContentData *data = NULL; - /** new sig match to replace previous content */ - SigMatch *nm = NULL; + DetectContentData *cd = NULL; if ((str != NULL) && (strcmp(str, "") != 0)) { - SCLogError(SC_ERR_INVALID_ARGUMENT, - "http_method does not take an argument"); + SCLogError(SC_ERR_INVALID_ARGUMENT, "http_method does not take an argument"); SCReturnInt(-1); } if (s->sm_lists_tail[DETECT_SM_LIST_PMATCH] == NULL) { - SCLogError(SC_ERR_INVALID_SIGNATURE, - "http_method modifier used before any signature match"); + SCLogError(SC_ERR_INVALID_SIGNATURE, "http_method modifier used " + "before any signature match"); SCReturnInt(-1); } - SigMatch *pm = DetectContentGetLastPattern(s->sm_lists_tail[DETECT_SM_LIST_PMATCH]); - if (pm == NULL) { - SCLogError(SC_ERR_INVALID_SIGNATURE, - "http_method modifies \"content\", but none was found"); + SigMatch *sm = DetectContentGetLastPattern(s->sm_lists_tail[DETECT_SM_LIST_PMATCH]); + if (sm == NULL) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "http_method modifies \"content\", " + "but none was found"); SCReturnInt(-1); } - /** \todo snort docs only mention rawbytes, not fast_pattern */ - if (((DetectContentData *)pm->ctx)->flags & DETECT_CONTENT_FAST_PATTERN) - { - SCLogWarning(SC_WARN_COMPATIBILITY, - "http_method cannot be used with \"fast_pattern\" currently." - "Unsetting fast_pattern on this modifier. Signature ==> %s", s->sig_str); - ((DetectContentData *)pm->ctx)->flags &= ~DETECT_CONTENT_FAST_PATTERN; - } else if (((DetectContentData *)pm->ctx)->flags & DETECT_CONTENT_RAWBYTES) - { - SCLogError(SC_ERR_INVALID_SIGNATURE, - "http_method cannot be used with \"rawbytes\""); + cd = (DetectContentData *)sm->ctx; + if (cd->flags & DETECT_CONTENT_RAWBYTES) + { + SCLogError(SC_ERR_INVALID_SIGNATURE, "http_method cannot be used " + "with \"rawbytes\""); SCReturnInt(-1); } - /* Setup the new sigmatch */ - 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; } - data = SCMalloc(sizeof(DetectContentData)); - if (data == NULL) - goto error; - - memset(data, 0x00, sizeof(DetectContentData)); - - data->content_len = ((DetectContentData *)pm->ctx)->content_len; - data->content = ((DetectContentData *)pm->ctx)->content; - /* transfer the nocase flag if it has already been set */ - if (((DetectContentData *)pm->ctx)->flags & DETECT_CONTENT_NOCASE) { - data->flags |= DETECT_CONTENT_NOCASE; - } - /* transfer the negate flag */ - if (((DetectContentData *)pm->ctx)->flags & DETECT_CONTENT_NEGATED) { - data->flags |= DETECT_CONTENT_NEGATED; + 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_METHOD, + s->sm_lists_tail[DETECT_SM_LIST_HMDMATCH], + DETECT_PCRE, + s->sm_lists_tail[DETECT_SM_LIST_HMDMATCH]); + if (pm == NULL) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "http_method seen with a " + "distance or within without a previous http_method " + "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_METHOD); + sm->type = DETECT_AL_HTTP_METHOD; - data->id = DetectPatternGetId(de_ctx->mpm_pattern_id_store, data, DETECT_AL_HTTP_METHOD); - - nm->type = DETECT_AL_HTTP_METHOD; - nm->ctx = (void *)data; - - /* pull the previous content from the pmatch list, append - * the new match to the match list */ - SigMatchReplaceContent(s, pm, nm); + /* 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_HMDMATCH], + &s->sm_lists_tail[DETECT_SM_LIST_HMDMATCH]); - /* free the old content sigmatch, the memory for the pattern - * is taken over by our new sigmatch */ - BoyerMooreCtxDeInit(((DetectContentData *)pm->ctx)->bm_ctx); - SCFree(pm->ctx); - SCFree(pm); - - /* Flagged the signature as to inspect the app layer data */ + /* flag the signature to indicate that we scan 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; - } - s->alproto = ALPROTO_HTTP; + SCReturnInt(0); error: - if (data != NULL) DetectHttpMethodFree(data); - if (nm != NULL) { - if (nm->ctx != NULL) DetectHttpMethodFree(nm); - SCFree(nm); - } SCReturnInt(-1); } @@ -289,8 +284,10 @@ int DetectHttpMethodTest01(void) } end: - if (de_ctx != NULL) SigCleanSignatures(de_ctx); - if (de_ctx != NULL) DetectEngineCtxFree(de_ctx); + if (de_ctx != NULL) + SigCleanSignatures(de_ctx); + if (de_ctx != NULL) + DetectEngineCtxFree(de_ctx); return result; } @@ -314,8 +311,10 @@ int DetectHttpMethodTest02(void) } end: - if (de_ctx != NULL) SigCleanSignatures(de_ctx); - if (de_ctx != NULL) DetectEngineCtxFree(de_ctx); + if (de_ctx != NULL) + SigCleanSignatures(de_ctx); + if (de_ctx != NULL) + DetectEngineCtxFree(de_ctx); return result; } @@ -340,8 +339,10 @@ int DetectHttpMethodTest03(void) } end: - if (de_ctx != NULL) SigCleanSignatures(de_ctx); - if (de_ctx != NULL) DetectEngineCtxFree(de_ctx); + if (de_ctx != NULL) + SigCleanSignatures(de_ctx); + if (de_ctx != NULL) + DetectEngineCtxFree(de_ctx); return result; } @@ -367,8 +368,10 @@ int DetectHttpMethodTest04(void) } end: - if (de_ctx != NULL) SigCleanSignatures(de_ctx); - if (de_ctx != NULL) DetectEngineCtxFree(de_ctx); + if (de_ctx != NULL) + SigCleanSignatures(de_ctx); + if (de_ctx != NULL) + DetectEngineCtxFree(de_ctx); return result; } @@ -394,8 +397,10 @@ int DetectHttpMethodTest05(void) } end: - if (de_ctx != NULL) SigCleanSignatures(de_ctx); - if (de_ctx != NULL) DetectEngineCtxFree(de_ctx); + if (de_ctx != NULL) + SigCleanSignatures(de_ctx); + if (de_ctx != NULL) + DetectEngineCtxFree(de_ctx); return result; } @@ -420,13 +425,13 @@ int DetectHttpMethodTest06(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_HMDMATCH] == NULL) { + printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HMDMATCH] == NULL\n"); goto end; } DetectContentData *cd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->ctx; - DetectContentData *hmd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_AMATCH]->ctx; + DetectContentData *hmd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HMDMATCH]->ctx; if (cd->id == hmd->id) goto end; @@ -459,13 +464,13 @@ int DetectHttpMethodTest07(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_HMDMATCH] == NULL) { + printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HMDMATCH] == NULL\n"); goto end; } DetectContentData *cd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->ctx; - DetectContentData *hmd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_AMATCH]->ctx; + DetectContentData *hmd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HMDMATCH]->ctx; if (cd->id == hmd->id) goto end; @@ -498,13 +503,13 @@ int DetectHttpMethodTest08(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_HMDMATCH] == NULL) { + printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HMDMATCH] == NULL\n"); goto end; } DetectContentData *cd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->ctx; - DetectContentData *hmd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_AMATCH]->ctx; + DetectContentData *hmd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HMDMATCH]->ctx; if (cd->id != 0 || hmd->id != 1) goto end; @@ -537,13 +542,13 @@ int DetectHttpMethodTest09(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_HMDMATCH] == NULL) { + printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HMDMATCH] == NULL\n"); goto end; } DetectContentData *cd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->ctx; - DetectContentData *hmd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_AMATCH]->ctx; + DetectContentData *hmd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HMDMATCH]->ctx; if (cd->id != 1 || hmd->id != 0) goto end; @@ -577,14 +582,14 @@ int DetectHttpMethodTest10(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_HMDMATCH] == NULL) { + printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HMDMATCH] == NULL\n"); goto end; } DetectContentData *cd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->ctx; - DetectContentData *hmd1 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_AMATCH]->ctx; - DetectContentData *hmd2 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_AMATCH]->prev->ctx; + DetectContentData *hmd1 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HMDMATCH]->ctx; + DetectContentData *hmd2 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HMDMATCH]->prev->ctx; if (cd->id != 1 || hmd1->id != 0 || hmd2->id != 0) goto end; @@ -618,14 +623,14 @@ int DetectHttpMethodTest11(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_HMDMATCH] == NULL) { + printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HMDMATCH] == NULL\n"); goto end; } DetectContentData *cd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->ctx; - DetectContentData *hmd1 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_AMATCH]->ctx; - DetectContentData *hmd2 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_AMATCH]->prev->ctx; + DetectContentData *hmd1 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HMDMATCH]->ctx; + DetectContentData *hmd2 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HMDMATCH]->prev->ctx; if (cd->id != 2 || hmd1->id != 0 || hmd2->id != 0) goto end; @@ -659,13 +664,13 @@ static int DetectHttpMethodTest12(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: "); + if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HMDMATCH] == NULL) { + printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HMDMATCH] == NULL: "); goto end; } - DetectContentData *hmd1 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_AMATCH]->ctx; - DetectContentData *hmd2 = de_ctx->sig_list->next->sm_lists_tail[DETECT_SM_LIST_AMATCH]->ctx; + DetectContentData *hmd1 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HMDMATCH]->ctx; + DetectContentData *hmd2 = de_ctx->sig_list->next->sm_lists_tail[DETECT_SM_LIST_HMDMATCH]->ctx; if (!(hmd1->flags & DETECT_CONTENT_NOCASE)) { printf("nocase flag not set on sig 1: "); diff --git a/src/detect-nocase.c b/src/detect-nocase.c index 0c50eb4ed2..570daea920 100644 --- a/src/detect-nocase.c +++ b/src/detect-nocase.c @@ -188,7 +188,7 @@ static int DetectNocaseSetup (DetectEngineCtx *de_ctx, Signature *s, char *nulls 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_AMATCH]); + DETECT_AL_HTTP_METHOD, s->sm_lists_tail[DETECT_SM_LIST_HMDMATCH]); 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 9b92081628..4c18f9d6e8 100644 --- a/src/detect-offset.c +++ b/src/detect-offset.c @@ -82,16 +82,17 @@ int DetectOffsetSetup (DetectEngineCtx *de_ctx, Signature *s, char *offsetstr) break; default: - pm = SigMatchGetLastSMFromLists(s, 10, + pm = SigMatchGetLastSMFromLists(s, 12, 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_RAW_HEADER, s->sm_lists_tail[DETECT_SM_LIST_HRHDMATCH], + DETECT_AL_HTTP_METHOD, s->sm_lists_tail[DETECT_SM_LIST_HMDMATCH]); if (pm == NULL) { SCLogError(SC_ERR_WITHIN_MISSING_CONTENT, "offset needs" "preceeding content or uricontent option, http_client_body " - "http_header or http_raw_header option"); + "http_header, http_raw_header or http_method option"); if (dubbed) SCFree(str); return -1; @@ -273,6 +274,37 @@ int DetectOffsetSetup (DetectEngineCtx *de_ctx, Signature *s, char *offsetstr) break; + case DETECT_AL_HTTP_METHOD: + 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 fd435e1afa..cc1657744a 100644 --- a/src/detect-parse.c +++ b/src/detect-parse.c @@ -935,7 +935,7 @@ static int SigParseBasics(Signature *s, char *sigstr, char ***result, uint8_t ad /* Check if it is bidirectional */ if (strcmp(arr[CONFIG_DIREC], "<>") == 0) - s->flags |= SIG_FLAG_BIDIREC; + s->init_flags |= SIG_FLAG_BIDIREC; /* Parse Address & Ports */ if (SigParseAddress(s, arr[CONFIG_SRC], SIG_DIREC_SRC ^ addrs_direction) < 0) @@ -1417,10 +1417,10 @@ Signature *SigInit(DetectEngineCtx *de_ctx, char *sigstr) { if (sigmatch_table[sm->type].AppLayerMatch != NULL) sig->flags |= SIG_FLAG_APPLAYER; if (sigmatch_table[sm->type].Match != NULL) - sig->flags |= SIG_FLAG_PACKET; + sig->init_flags |= SIG_FLAG_PACKET; } } else { - sig->flags |= SIG_FLAG_PACKET; + sig->init_flags |= SIG_FLAG_PACKET; } } @@ -1436,10 +1436,12 @@ Signature *SigInit(DetectEngineCtx *de_ctx, char *sigstr) { sig->flags |= SIG_FLAG_STATE_MATCH; if (sig->sm_lists[DETECT_SM_LIST_HRHDMATCH]) sig->flags |= SIG_FLAG_STATE_MATCH; + if (sig->sm_lists[DETECT_SM_LIST_HMDMATCH]) + 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", - sig->flags & SIG_FLAG_PACKET ? "set" : "not set"); + sig->init_flags & SIG_FLAG_PACKET ? "set" : "not set"); SigBuildAddressMatchArray(sig); @@ -1549,7 +1551,7 @@ Signature *SigInitReal(DetectEngineCtx *de_ctx, char *sigstr) { } } } - if (sig->flags & SIG_FLAG_BIDIREC) { + if (sig->init_flags & SIG_FLAG_BIDIREC) { /* Allocate a copy of this signature with the addresses siwtched This copy will be installed at sig->next */ sig->next = SigAlloc(); @@ -1611,10 +1613,10 @@ Signature *SigInitReal(DetectEngineCtx *de_ctx, char *sigstr) { if (sigmatch_table[sm->type].AppLayerMatch != NULL) sig->flags |= SIG_FLAG_APPLAYER; if (sigmatch_table[sm->type].Match != NULL) - sig->flags |= SIG_FLAG_PACKET; + sig->init_flags |= SIG_FLAG_PACKET; } } else { - sig->flags |= SIG_FLAG_PACKET; + sig->init_flags |= SIG_FLAG_PACKET; } } @@ -1630,12 +1632,14 @@ Signature *SigInitReal(DetectEngineCtx *de_ctx, char *sigstr) { sig->flags |= SIG_FLAG_STATE_MATCH; if (sig->sm_lists[DETECT_SM_LIST_HRHDMATCH]) sig->flags |= SIG_FLAG_STATE_MATCH; + if (sig->sm_lists[DETECT_SM_LIST_HMDMATCH]) + sig->flags |= SIG_FLAG_STATE_MATCH; SigBuildAddressMatchArray(sig); SCLogDebug("sig %"PRIu32" SIG_FLAG_APPLAYER: %s, SIG_FLAG_PACKET: %s", sig->id, sig->flags & SIG_FLAG_APPLAYER ? "set" : "not set", - sig->flags & SIG_FLAG_PACKET ? "set" : "not set"); + sig->init_flags & SIG_FLAG_PACKET ? "set" : "not set"); /* validate signature, SigValidate will report the error reason */ if (SigValidate(sig) == 0) { @@ -1849,7 +1853,7 @@ static inline int DetectEngineSignatureIsDuplicate(DetectEngineCtx *de_ctx, if (sw_dup->s_prev == NULL) { SigDuplWrapper sw_temp; memset(&sw_temp, 0, sizeof(SigDuplWrapper)); - if (sw_dup->s->flags & SIG_FLAG_BIDIREC) { + if (sw_dup->s->init_flags & SIG_FLAG_BIDIREC) { sw_temp.s = sw_dup->s->next->next; de_ctx->sig_list = sw_dup->s->next->next; SigFree(sw_dup->s->next); @@ -1867,7 +1871,7 @@ static inline int DetectEngineSignatureIsDuplicate(DetectEngineCtx *de_ctx, } else { SigDuplWrapper sw_temp; memset(&sw_temp, 0, sizeof(SigDuplWrapper)); - if (sw_dup->s->flags & SIG_FLAG_BIDIREC) { + if (sw_dup->s->init_flags & SIG_FLAG_BIDIREC) { sw_temp.s = sw_dup->s->next->next; sw_dup->s_prev->next = sw_dup->s->next->next; SigFree(sw_dup->s->next); @@ -1926,7 +1930,7 @@ Signature *DetectEngineAppendSig(DetectEngineCtx *de_ctx, char *sigstr) { if (dup_sig == 1) goto error; - if (sig->flags & SIG_FLAG_BIDIREC) { + if (sig->init_flags & SIG_FLAG_BIDIREC) { if (sig->next != NULL) { sig->next->next = de_ctx->sig_list; } else { @@ -2436,7 +2440,7 @@ int SigTestBidirec01 (void) { goto end; if (sig->next != NULL) goto end; - if (sig->flags & SIG_FLAG_BIDIREC) + if (sig->init_flags & SIG_FLAG_BIDIREC) goto end; if (de_ctx->signum != 1) goto end; @@ -2469,7 +2473,7 @@ int SigTestBidirec02 (void) { goto end; if (de_ctx->sig_list != sig) goto end; - if (!(sig->flags & SIG_FLAG_BIDIREC)) + if (!(sig->init_flags & SIG_FLAG_BIDIREC)) goto end; if (sig->next == NULL) goto end; @@ -2478,7 +2482,7 @@ int SigTestBidirec02 (void) { copy = sig->next; if (copy->next != NULL) goto end; - if (!(copy->flags & SIG_FLAG_BIDIREC)) + if (!(copy->init_flags & SIG_FLAG_BIDIREC)) goto end; result = 1; @@ -2631,7 +2635,7 @@ int SigTestBidirec04 (void) { sig = DetectEngineAppendSig(de_ctx, "alert tcp 192.168.1.1 any <> any any (msg:\"SigTestBidirec03 sid 2 bidirectional\"; sid:2;)"); if (sig == NULL) goto end; - if ( !(sig->flags & SIG_FLAG_BIDIREC)) + if ( !(sig->init_flags & SIG_FLAG_BIDIREC)) goto end; if (sig->next == NULL) goto end; diff --git a/src/detect-tls-version.c b/src/detect-tls-version.c index f799612445..92288b244a 100644 --- a/src/detect-tls-version.c +++ b/src/detect-tls-version.c @@ -598,7 +598,7 @@ static int DetectTlsVersionTestDetect03(void) { goto end; } - if (s->flags & SIG_FLAG_PACKET) { + if (s->init_flags & SIG_FLAG_PACKET) { SCLogDebug("SIG_FLAG_PACKET flags"); } diff --git a/src/detect-within.c b/src/detect-within.c index f280c79c6b..90d891c4e4 100644 --- a/src/detect-within.c +++ b/src/detect-within.c @@ -171,16 +171,17 @@ static int DetectWithinSetup (DetectEngineCtx *de_ctx, Signature *s, char *withi } } } else { - pm = SigMatchGetLastSMFromLists(s, 10, + pm = SigMatchGetLastSMFromLists(s, 12, 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_RAW_HEADER, s->sm_lists_tail[DETECT_SM_LIST_HRHDMATCH], + DETECT_AL_HTTP_METHOD, s->sm_lists_tail[DETECT_SM_LIST_HMDMATCH]); if (pm == NULL) { SCLogError(SC_ERR_WITHIN_MISSING_CONTENT, "within needs" "preceeding content, uricontent, http_client_body, " - "http_header or http_raw_header option"); + "http_header, http_raw_header or http_method option"); if (dubbed) SCFree(str); return -1; @@ -554,6 +555,60 @@ static int DetectWithinSetup (DetectEngineCtx *de_ctx, Signature *s, char *withi break; + case DETECT_AL_HTTP_METHOD: + 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_METHOD, pm->prev, + DETECT_PCRE, pm->prev); + if (pm == NULL) { + SCLogError(SC_ERR_DISTANCE_MISSING_CONTENT, "distance for http_method " + "needs preceeding http_method 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 48acf2867c..af2e2cde03 100644 --- a/src/detect.c +++ b/src/detect.c @@ -118,6 +118,7 @@ #include "detect-engine-hcbd.h" #include "detect-engine-hhd.h" #include "detect-engine-hrhd.h" +#include "detect-engine-hmd.h" #include "util-rule-vars.h" @@ -703,14 +704,14 @@ static void SigMatchSignaturesBuildMatchArray(DetectEngineCtx *de_ctx, SCLogDebug("Mask match. mask %02X, s->mask %02x, after AND %02x", mask, s->mask, mask & s->mask); #if 0 - if (!(p->flags & PKT_HAS_FLOW) && s->flags & SIG_FLAG_FLOW) { + if (!(p->flags & PKT_HAS_FLOW) && s->init_flags & SIG_FLAG_FLOW) { SCLogDebug("flow in sig but not in packet"); continue; } /* filter out the sigs that inspect the payload, if packet no payload inspection flag is set*/ - if ((p->flags & PKT_NOPAYLOAD_INSPECTION) && (s->flags & SIG_FLAG_PAYLOAD)) { + if ((p->flags & PKT_NOPAYLOAD_INSPECTION) && (s->init_flags & SIG_FLAG_PAYLOAD)) { SCLogDebug("no payload inspection enabled and sig has payload portion."); continue; } @@ -774,8 +775,8 @@ static void SigMatchSignaturesBuildMatchArray(DetectEngineCtx *de_ctx, } if (s->full_sig->flags & SIG_FLAG_MPM_URICONTENT) { - if (!(det_ctx->pmq.pattern_id_bitarray[(s->mpm_uripattern_id / 8)] & - (1 << (s->mpm_uripattern_id % 8)))) { + if (!(det_ctx->pmq.pattern_id_bitarray[(s->mpm_http_pattern_id / 8)] & + (1 << (s->mpm_http_pattern_id % 8)))) { if (!(s->full_sig->flags & SIG_FLAG_MPM_URICONTENT_NEG)) { continue; } @@ -783,8 +784,8 @@ static void SigMatchSignaturesBuildMatchArray(DetectEngineCtx *de_ctx, } if (s->flags & SIG_FLAG_MPM_HCBDCONTENT) { - if (!(det_ctx->pmq.pattern_id_bitarray[(s->mpm_hcbdpattern_id / 8)] & - (1 << (s->mpm_hcbdpattern_id % 8)))) { + 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_HCBDCONTENT_NEG)) { continue; } @@ -792,8 +793,8 @@ static void SigMatchSignaturesBuildMatchArray(DetectEngineCtx *de_ctx, } if (s->flags & SIG_FLAG_MPM_HHDCONTENT) { - if (!(det_ctx->pmq.pattern_id_bitarray[(s->mpm_hhdpattern_id / 8)] & - (1 << (s->mpm_hhdpattern_id % 8)))) { + 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_HHDCONTENT_NEG)) { continue; } @@ -801,14 +802,23 @@ static void SigMatchSignaturesBuildMatchArray(DetectEngineCtx *de_ctx, } if (s->flags & SIG_FLAG_MPM_HRHDCONTENT) { - if (!(det_ctx->pmq.pattern_id_bitarray[(s->mpm_hrhdpattern_id / 8)] & - (1 << (s->mpm_hrhdpattern_id % 8)))) { + 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_HRHDCONTENT_NEG)) { continue; } } } + if (s->flags & SIG_FLAG_MPM_HMDCONTENT) { + 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_HMDCONTENT_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) { @@ -1043,6 +1053,10 @@ static inline void DetectMpmPrefilter(DetectEngineCtx *de_ctx, cnt = DetectEngineRunHttpRawHeaderMpm(det_ctx, p->flow, alstate); SCLogDebug("hrhd search: cnt %" PRIu32, cnt); } + if (det_ctx->sgh->flags & SIG_GROUP_HEAD_MPM_HMD) { + cnt = DetectEngineRunHttpMethodMpm(det_ctx, p->flow, alstate); + SCLogDebug("hmd search: cnt %" PRIu32, cnt); + } } } else { SCLogDebug("NOT p->flowflags & FLOW_PKT_ESTABLISHED"); @@ -1673,6 +1687,9 @@ int SignatureIsIPOnly(DetectEngineCtx *de_ctx, Signature *s) { if (s->sm_lists[DETECT_SM_LIST_HRHDMATCH] != NULL) return 0; + if (s->sm_lists[DETECT_SM_LIST_HMDMATCH] != NULL) + return 0; + if (s->sm_lists[DETECT_SM_LIST_AMATCH] != NULL) return 0; @@ -1753,6 +1770,9 @@ static int SignatureIsDEOnly(DetectEngineCtx *de_ctx, Signature *s) { if (s->sm_lists[DETECT_SM_LIST_HRHDMATCH] != NULL) return 0; + if (s->sm_lists[DETECT_SM_LIST_HMDMATCH] != NULL) + return 0; + SigMatch *sm = s->sm_lists[DETECT_SM_LIST_MATCH]; /* check for conflicting keywords */ for ( ;sm != NULL; sm = sm->next) { @@ -1843,6 +1863,11 @@ static int SignatureCreateMask(Signature *s) { SCLogDebug("sig requires http app state"); } + if (s->sm_lists[DETECT_SM_LIST_HMDMATCH] != 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) { @@ -1892,7 +1917,7 @@ static int SignatureCreateMask(Signature *s) { SCLogDebug("sig requires flow"); } - if (s->flags & SIG_FLAG_FLOW) { + if (s->init_flags & SIG_FLAG_FLOW) { s->mask |= SIG_MASK_REQUIRE_FLOW; SCLogDebug("sig requires flow"); } @@ -1931,6 +1956,9 @@ static void SigInitStandardMpmFactoryContexts(DetectEngineCtx *de_ctx) de_ctx->sgh_mpm_context_hrhd = MpmFactoryRegisterMpmCtxProfile("hrhd", MPM_CTX_FACTORY_FLAGS_PREPARE_WITH_SIG_GROUP_BUILD); + de_ctx->sgh_mpm_context_hmd = + MpmFactoryRegisterMpmCtxProfile("hmd", + MPM_CTX_FACTORY_FLAGS_PREPARE_WITH_SIG_GROUP_BUILD); de_ctx->sgh_mpm_context_app_proto_detect = MpmFactoryRegisterMpmCtxProfile("app_proto_detect", 0); @@ -1987,12 +2015,12 @@ int SigAddressPrepareStage1(DetectEngineCtx *de_ctx) { /* see if any sig is inspecting the packet payload */ } else if (SignatureIsInspectingPayload(de_ctx, tmp_s) == 1) { - tmp_s->flags |= SIG_FLAG_PAYLOAD; + tmp_s->init_flags |= SIG_FLAG_PAYLOAD; cnt_payload++; SCLogDebug("Signature %"PRIu32" is considered \"Payload inspecting\"", tmp_s->id); } else if (SignatureIsDEOnly(de_ctx, tmp_s) == 1) { - tmp_s->flags |= SIG_FLAG_DEONLY; + tmp_s->init_flags |= SIG_FLAG_DEONLY; SCLogDebug("Signature %"PRIu32" is considered \"Decoder Event only\"", tmp_s->id); cnt_deonly++; } @@ -2140,7 +2168,7 @@ error: static int DetectEngineLookupFlowAddSig(DetectEngineCtx *de_ctx, Signature *s, int family) { uint8_t flags = 0; - if (s->flags & SIG_FLAG_FLOW) { + if (s->init_flags & SIG_FLAG_FLOW) { SigMatch *sm = s->sm_lists[DETECT_SM_LIST_MATCH]; for ( ; sm != NULL; sm = sm->next) { if (sm->type != DETECT_FLOW) @@ -2575,7 +2603,7 @@ int SigAddressPrepareStage2(DetectEngineCtx *de_ctx) { SCLogDebug("tmp_s->id %"PRIu32, tmp_s->id); if (tmp_s->flags & SIG_FLAG_IPONLY) { IPOnlyAddSignature(de_ctx, &de_ctx->io_ctx, tmp_s); - } else if (tmp_s->flags & SIG_FLAG_DEONLY) { + } else if (tmp_s->init_flags & SIG_FLAG_DEONLY) { DetectEngineAddDecoderEventSig(de_ctx, tmp_s); } else { DetectEngineLookupFlowAddSig(de_ctx, tmp_s, AF_INET); @@ -3778,6 +3806,12 @@ int SigGroupBuild (DetectEngineCtx *de_ctx) { } //printf("hrhd- %d\n", mpm_ctx->pattern_cnt); + mpm_ctx = MpmFactoryGetMpmCtxForProfile(de_ctx->sgh_mpm_context_hmd); + if (mpm_table[de_ctx->mpm_matcher].Prepare != NULL) { + mpm_table[de_ctx->mpm_matcher].Prepare(mpm_ctx); + } + //printf("hmd- %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); @@ -7989,7 +8023,7 @@ int SigTest40NoPayloadInspection02(void) { //PatternMatchPrepare(mpm_ctx,MPM_B2G); DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx); - if (!(de_ctx->sig_list->flags & SIG_FLAG_PAYLOAD)) + if (!(de_ctx->sig_list->init_flags & SIG_FLAG_PAYLOAD)) result = 0; SigMatchSignatures(&th_v, de_ctx, det_ctx, p); diff --git a/src/detect.h b/src/detect.h index 9821992a9e..57220028ac 100644 --- a/src/detect.h +++ b/src/detect.h @@ -92,6 +92,8 @@ enum { DETECT_SM_LIST_HHDMATCH, /* list for http_raw_header keyword and the ones relative to it */ DETECT_SM_LIST_HRHDMATCH, + /* list for http_method keyword and the ones relative to it */ + DETECT_SM_LIST_HMDMATCH, DETECT_SM_LIST_MAX, }; @@ -214,38 +216,46 @@ typedef struct DetectPort_ { #define SIG_FLAG_DP_ANY 0x00000010 /**< destination port is any */ #define SIG_FLAG_NOALERT 0x00000020 /**< no alert flag is set */ -#define SIG_FLAG_IPONLY 0x00000040 /**< ip only signature */ -#define SIG_FLAG_DEONLY 0x00000080 /**< decode event only signature */ -#define SIG_FLAG_MPM 0x00000100 /**< sig has mpm portion (content) */ -#define SIG_FLAG_MPM_URI 0x00000200 /**< sig has mpm portion (uricontent) */ -#define SIG_FLAG_PAYLOAD 0x00000400 /**< signature is inspecting the packet payload */ -#define SIG_FLAG_DSIZE 0x00000800 /**< signature has a dsize setting */ +#define SIG_FLAG_MPM 0x00000040 /**< sig has mpm portion (content) */ +#define SIG_FLAG_MPM_URI 0x00000080 /**< sig has mpm portion (uricontent) */ +#define SIG_FLAG_DSIZE 0x00000100 /**< signature has a dsize setting */ -#define SIG_FLAG_FLOW 0x00001000 /**< signature has a flow setting */ -#define SIG_FLAG_APPLAYER 0x00002000 /**< signature applies to app layer instead of packets */ -#define SIG_FLAG_BIDIREC 0x00004000 /**< signature has bidirectional operator */ -#define SIG_FLAG_PACKET 0x00008000 /**< signature has matches against a packet (as opposed to app layer) */ +#define SIG_FLAG_APPLAYER 0x00000200 /**< signature applies to app layer instead of packets */ +#define SIG_FLAG_IPONLY 0x00000400 /**< ip only signature */ -#define SIG_FLAG_STATE_MATCH 0x00010000 /**< signature has matches that require stateful inspection */ -#define SIG_FLAG_HAS_NO_PKT_AND_STREAM_CONTENT 0x00020000 -#define SIG_FLAG_MPM_PACKET 0x00040000 -#define SIG_FLAG_MPM_PACKET_NEG 0x00080000 +#define SIG_FLAG_STATE_MATCH 0x00000800 /**< signature has matches that require stateful inspection */ +#define SIG_FLAG_HAS_NO_PKT_AND_STREAM_CONTENT 0x00001000 +#define SIG_FLAG_MPM_PACKET 0x00002000 +#define SIG_FLAG_MPM_PACKET_NEG 0x00004000 -#define SIG_FLAG_MPM_STREAM 0x00100000 -#define SIG_FLAG_MPM_STREAM_NEG 0x00200000 -#define SIG_FLAG_MPM_URICONTENT 0x00400000 -#define SIG_FLAG_MPM_URICONTENT_NEG 0x00800000 +#define SIG_FLAG_MPM_STREAM 0x00008000 +#define SIG_FLAG_MPM_STREAM_NEG 0x00010000 -#define SIG_FLAG_MPM_HHDCONTENT 0x01000000 -#define SIG_FLAG_MPM_HHDCONTENT_NEG 0x02000000 -#define SIG_FLAG_MPM_HRHDCONTENT 0x04000000 -#define SIG_FLAG_MPM_HRHDCONTENT_NEG 0x08000000 +#define SIG_FLAG_MPM_URICONTENT 0x00020000 +#define SIG_FLAG_MPM_URICONTENT_NEG 0x00040000 -#define SIG_FLAG_MPM_HCBDCONTENT 0x10000000 -#define SIG_FLAG_MPM_HCBDCONTENT_NEG 0x20000000 +#define SIG_FLAG_MPM_HHDCONTENT 0x00080000 +#define SIG_FLAG_MPM_HHDCONTENT_NEG 0x00100000 + +#define SIG_FLAG_MPM_HRHDCONTENT 0x00200000 +#define SIG_FLAG_MPM_HRHDCONTENT_NEG 0x00400000 + +#define SIG_FLAG_MPM_HCBDCONTENT 0x00800000 +#define SIG_FLAG_MPM_HCBDCONTENT_NEG 0x01000000 + +#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. */ + +/* signature init flags */ +#define SIG_FLAG_DEONLY 0x00000001 /**< decode event only signature */ +#define SIG_FLAG_PACKET 0x00000002 /**< signature has matches against a packet (as opposed to app layer) */ +#define SIG_FLAG_FLOW 0x00000004 /**< signature has a flow setting */ +#define SIG_FLAG_BIDIREC 0x00000008 /**< signature has bidirectional operator */ +#define SIG_FLAG_PAYLOAD 0x00000010 /**< signature is inspecting the packet payload */ -#define SIG_FLAG_REQUIRE_FLOWVAR 0x40000000 /**< signature can only match if a flowbit, flowvar or flowint is available. */ /* signature mask flags */ #define SIG_MASK_REQUIRE_PAYLOAD 0x01 @@ -309,10 +319,7 @@ typedef struct SignatureHeader_ { union { struct { /** pattern in the mpm matcher */ - PatIntId mpm_uripattern_id; - PatIntId mpm_hcbdpattern_id; - PatIntId mpm_hhdpattern_id; - PatIntId mpm_hrhdpattern_id; + PatIntId mpm_http_pattern_id; }; uint64_t hdr_copy3; }; @@ -352,11 +359,7 @@ typedef struct Signature_ { }; union { struct { - /** pattern in the mpm matcher */ - PatIntId mpm_uripattern_id; - PatIntId mpm_hcbdpattern_id; - PatIntId mpm_hhdpattern_id; - PatIntId mpm_hrhdpattern_id; + PatIntId mpm_http_pattern_id; }; uint64_t hdr_copy3; }; @@ -454,6 +457,9 @@ typedef struct Signature_ { /** address settings for this signature */ DetectAddressHead src, dst; + /* used to hold flags that are predominantly used during init */ + uint32_t init_flags; + /** ptr to the next sig in the list */ struct Signature_ *next; } Signature; @@ -647,6 +653,7 @@ typedef struct DetectEngineCtx_ { int32_t sgh_mpm_context_hcbd; int32_t sgh_mpm_context_hhd; int32_t sgh_mpm_context_hrhd; + int32_t sgh_mpm_context_hmd; int32_t sgh_mpm_context_app_proto_detect; /** sgh for signatures that match against invalid packets. In those cases @@ -803,17 +810,19 @@ typedef struct SigTableElmt_ { #define SIG_GROUP_HAVEHCBDCONTENT 0x00000008 #define SIG_GROUP_HAVEHHDCONTENT 0x00000010 #define SIG_GROUP_HAVEHRHDCONTENT 0x00000020 -#define SIG_GROUP_HEAD_MPM_COPY 0x00000040 -#define SIG_GROUP_HEAD_MPM_URI_COPY 0x00000080 -#define SIG_GROUP_HEAD_MPM_STREAM_COPY 0x00000100 -#define SIG_GROUP_HEAD_FREE 0x00000200 -#define SIG_GROUP_HEAD_MPM_PACKET 0x00000400 -#define SIG_GROUP_HEAD_MPM_STREAM 0x00000800 -#define SIG_GROUP_HEAD_MPM_URI 0x00001000 -#define SIG_GROUP_HEAD_MPM_HCBD 0x00002000 -#define SIG_GROUP_HEAD_MPM_HHD 0x00004000 -#define SIG_GROUP_HEAD_MPM_HRHD 0x00008000 -#define SIG_GROUP_HEAD_REFERENCED 0x00010000 /**< sgh is being referenced by others, don't clear */ +#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 */ typedef struct SigGroupHeadInitData_ { /* list of content containers @@ -857,6 +866,7 @@ typedef struct SigGroupHead_ { MpmCtx *mpm_hcbd_ctx; MpmCtx *mpm_hhd_ctx; MpmCtx *mpm_hrhd_ctx; + MpmCtx *mpm_hmd_ctx; uint16_t mpm_streamcontent_maxlen; uint16_t mpm_uricontent_maxlen; diff --git a/src/suricata.c b/src/suricata.c index c1f3821baf..bf6d8b94c5 100644 --- a/src/suricata.c +++ b/src/suricata.c @@ -57,6 +57,7 @@ #include "detect-engine-hcbd.h" #include "detect-engine-hhd.h" #include "detect-engine-hrhd.h" +#include "detect-engine-hmd.h" #include "detect-engine-state.h" #include "detect-engine-tag.h" #include "detect-fast-pattern.h" @@ -1018,6 +1019,7 @@ int main(int argc, char **argv) DetectEngineHttpClientBodyRegisterTests(); DetectEngineHttpHeaderRegisterTests(); DetectEngineHttpRawHeaderRegisterTests(); + DetectEngineHttpMethodRegisterTests(); DetectEngineRegisterTests(); SCLogRegisterTests(); if (list_unittests) {