diff --git a/src/Makefile.am b/src/Makefile.am index ce7d7ca611..3b8eb2b35d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -64,6 +64,7 @@ detect-engine-payload.c detect-engine-payload.h \ detect-engine-dcepayload.c detect-engine-dcepayload.h \ 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-state.c detect-engine-state.h \ detect-parse.c detect-parse.h \ detect-ack.c detect-ack.h \ @@ -114,6 +115,7 @@ detect-icode.c detect-icode.h \ detect-http-cookie.c detect-http-cookie.h \ detect-http-method.c detect-http-method.h \ detect-http-header.c detect-http-header.h \ +detect-http-raw-header.c detect-http-raw-header.h \ detect-http-uri.c detect-http-uri.h \ detect-tls-version.c detect-tls-version.h \ detect-ssh-proto-version.c detect-ssh-proto-version.h \ diff --git a/src/detect-content.h b/src/detect-content.h index 2a5bfb7301..150b491afb 100644 --- a/src/detect-content.h +++ b/src/detect-content.h @@ -46,6 +46,7 @@ #define DETECT_CONTENT_STREAM_MPM 0x1000 #define DETECT_CONTENT_URI_MPM 0x2000 #define DETECT_CONTENT_HCBD_MPM 0x4000 +#define DETECT_CONTENT_HHD_MPM 0x8000 #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 c0dd8d0338..531ebaedbb 100644 --- a/src/detect-depth.c +++ b/src/detect-depth.c @@ -21,7 +21,7 @@ * \author Victor Julien * \author Anoop Saldanha * - * Implements the depth keyword + * Implements the depth keyword. */ #include "suricata-common.h" @@ -60,9 +60,9 @@ static int DetectDepthSetup (DetectEngineCtx *de_ctx, Signature *s, char *depths DetectContentData *ud = NULL; /* strip "'s */ - if (depthstr[0] == '\"' && depthstr[strlen(depthstr)-1] == '\"') { - str = SCStrdup(depthstr+1); - str[strlen(depthstr)-2] = '\0'; + if (depthstr[0] == '\"' && depthstr[strlen(depthstr) - 1] == '\"') { + str = SCStrdup(depthstr + 1); + str[strlen(depthstr) - 2] = '\0'; dubbed = 1; } @@ -83,13 +83,15 @@ static int DetectDepthSetup (DetectEngineCtx *de_ctx, Signature *s, char *depths break; default: - pm = SigMatchGetLastSMFromLists(s, 6, + pm = SigMatchGetLastSMFromLists(s, 8, 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_CLIENT_BODY, s->sm_lists_tail[DETECT_SM_LIST_HCBDMATCH], + DETECT_AL_HTTP_HEADER, s->sm_lists_tail[DETECT_SM_LIST_HHDMATCH]); if (pm == NULL) { SCLogError(SC_ERR_DEPTH_MISSING_CONTENT, "depth needs " - "preceeding content or uricontent option or http_client_body option"); + "preceeding content, uricontent option, http_client_body " + "or http_header option"); if (dubbed) SCFree(str); return -1; @@ -196,12 +198,38 @@ static int DetectDepthSetup (DetectEngineCtx *de_ctx, Signature *s, char *depths break; + case DETECT_AL_HTTP_HEADER: + 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"); - if (dubbed) SCFree(str); - return -1; - break; + goto error; } if (dubbed) diff --git a/src/detect-distance.c b/src/detect-distance.c index 6e75bfe0f6..0b7bf95dee 100644 --- a/src/detect-distance.c +++ b/src/detect-distance.c @@ -123,7 +123,8 @@ static int DetectDistanceSetup (DetectEngineCtx *de_ctx, Signature *s, SigMatchTransferSigMatchAcrossLists(pm1, &s->sm_lists[DETECT_SM_LIST_PMATCH], &s->sm_lists_tail[DETECT_SM_LIST_PMATCH], - &s->sm_lists[DETECT_SM_LIST_DMATCH], &s->sm_lists_tail[DETECT_SM_LIST_DMATCH]); + &s->sm_lists[DETECT_SM_LIST_DMATCH], + &s->sm_lists_tail[DETECT_SM_LIST_DMATCH]); pm = pm1; } else { /* within is against pm1 and we continue this way */ @@ -137,7 +138,8 @@ static int DetectDistanceSetup (DetectEngineCtx *de_ctx, Signature *s, SigMatchTransferSigMatchAcrossLists(pm1, &s->sm_lists[DETECT_SM_LIST_PMATCH], &s->sm_lists_tail[DETECT_SM_LIST_PMATCH], - &s->sm_lists[DETECT_SM_LIST_DMATCH], &s->sm_lists_tail[DETECT_SM_LIST_DMATCH]); + &s->sm_lists[DETECT_SM_LIST_DMATCH], + &s->sm_lists_tail[DETECT_SM_LIST_DMATCH]); pm = pm1; } else { /* within is against pm1 and we continue this way */ @@ -164,14 +166,15 @@ static int DetectDistanceSetup (DetectEngineCtx *de_ctx, Signature *s, } } } else { - pm = SigMatchGetLastSMFromLists(s, 6, + pm = SigMatchGetLastSMFromLists(s, 8, 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_CLIENT_BODY, s->sm_lists_tail[DETECT_SM_LIST_HCBDMATCH], + DETECT_AL_HTTP_HEADER, s->sm_lists_tail[DETECT_SM_LIST_HHDMATCH]); if (pm == NULL) { SCLogError(SC_ERR_WITHIN_MISSING_CONTENT, "within needs" - "preceeding content or uricontent option or http_client_body options"); + "preceeding content, uricontent option, http_client_body " + "or http_header option"); if (dubbed) SCFree(str); return -1; @@ -389,6 +392,7 @@ static int DetectDistanceSetup (DetectEngineCtx *de_ctx, Signature *s, cd->flags |= DETECT_CONTENT_DISTANCE; + /* reassigning pm */ pm = SigMatchGetLastSMFromLists(s, 2, DETECT_AL_HTTP_CLIENT_BODY, pm->prev); if (pm == NULL) { @@ -396,7 +400,52 @@ static int DetectDistanceSetup (DetectEngineCtx *de_ctx, Signature *s, "needs preceeding http_client_body content"); goto error; } + /* 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; + + case DETECT_AL_HTTP_HEADER: + 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, 2, + DETECT_AL_HTTP_HEADER, pm->prev); + if (pm == NULL) { + SCLogError(SC_ERR_DISTANCE_MISSING_CONTENT, "distance for http_header " + "needs preceeding http_header content"); + goto error; + } + /* reassigning cd */ cd = (DetectContentData *)pm->ctx; if (cd->flags & DETECT_CONTENT_FAST_PATTERN_ONLY) { SCLogError(SC_ERR_INVALID_SIGNATURE, "Previous keyword " @@ -405,22 +454,23 @@ static int DetectDistanceSetup (DetectEngineCtx *de_ctx, Signature *s, "only content"); goto error; } - ((DetectContentData *)pm->ctx)->flags |= DETECT_CONTENT_RELATIVE_NEXT; + cd->flags |= DETECT_CONTENT_RELATIVE_NEXT; break; default: SCLogError(SC_ERR_DISTANCE_MISSING_CONTENT, "distance needs two " "preceeding content or uricontent options"); - if (dubbed) SCFree(str); - return -1; - break; + goto error; } - if (dubbed) SCFree(str); + if (dubbed) + SCFree(str); return 0; + error: - if (dubbed) SCFree(str); + if (dubbed) + SCFree(str); return -1; } diff --git a/src/detect-engine-hcbd.c b/src/detect-engine-hcbd.c index e7a0fc3b1f..cdd90e45eb 100644 --- a/src/detect-engine-hcbd.c +++ b/src/detect-engine-hcbd.c @@ -29,8 +29,6 @@ #include "detect-engine-mpm.h" #include "detect-parse.h" #include "detect-engine-state.h" -#include "detect-uricontent.h" -#include "detect-urilen.h" #include "detect-pcre.h" #include "detect-isdataat.h" #include "detect-bytetest.h" @@ -208,8 +206,8 @@ static int DoInspectHttpClientBody(DetectEngineCtx *de_ctx, BUG_ON(sm->next == NULL); /* see if the next payload keywords match. If not, we will - * search for another occurence of this uricontent and see - * if the others match then until we run out of matches */ + * search for another occurence of this http client body content + * and see if the others match then until we run out of matches */ int r = DoInspectHttpClientBody(de_ctx, det_ctx, s, sm->next, payload, payload_len); if (r == 1) { @@ -2681,7 +2679,7 @@ end: #endif /* UNITTESTS */ -void HttpClientBodyRegisterTests(void) +void DetectEngineHttpClientBodyRegisterTests(void) { #ifdef UNITTESTS diff --git a/src/detect-engine-hcbd.h b/src/detect-engine-hcbd.h index 98d808aad1..7eca6fc999 100644 --- a/src/detect-engine-hcbd.h +++ b/src/detect-engine-hcbd.h @@ -28,7 +28,7 @@ int DetectEngineInspectHttpClientBody(DetectEngineCtx *, DetectEngineThreadCtx *, Signature *, Flow *, uint8_t, void *); void DetectEngineCleanHCBDBuffers(DetectEngineThreadCtx *); -void HttpClientBodyRegisterTests(void); +void DetectEngineHttpClientBodyRegisterTests(void); #endif /* __DETECT_ENGINE_HCBD_H__ */ diff --git a/src/detect-engine-hhd.c b/src/detect-engine-hhd.c new file mode 100644 index 0000000000..e6c36086a9 --- /dev/null +++ b/src/detect-engine-hhd.c @@ -0,0 +1,2230 @@ +/* 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-hhd.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 header. + * + * 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 headers buffer to inspect. + * \param payload_len Length of the http headers buffer. + * + * \retval 0 no match. + * \retval 1 match. + */ +static int DoInspectHttpHeader(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_HEADER) { + if (payload_len == 0) { + SCReturnInt(0); + } + + DetectContentData *cd = (DetectContentData *)sm->ctx; + SCLogDebug("inspecting http headers %"PRIu32" payload_len %"PRIu32, + cd->id, payload_len); + + if (cd->flags & DETECT_CONTENT_HHD_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; + } + + BUG_ON(sm->next == NULL); + + /* see if the next payload keywords match. If not, we will + * search for another occurence of this http header content and + * see if the others match then until we run out of matches */ + int r = DoInspectHttpHeader(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 { + /* 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 = DoInspectHttpHeader(de_ctx, det_ctx, s, sm->next, payload, + payload_len); + SCReturnInt(r); + } else { + SCReturnInt(1); + } +} + +/** + * \brief Helps buffer http normalized headers from different transactions and + * stores them away in detection context. Also calls the mpm on the + * buffers. + * + * \param det_ctx Detection engine thread ctx. + * \param f Pointer to the flow. + * \param htp_state http state. + * + * \retval cnt The match count from the mpm call. If call_mpm is 0, the retval + * is ignored. + */ +static uint32_t DetectEngineInspectHttpHeaderMpmInspect(DetectEngineThreadCtx *det_ctx, + Signature *s, Flow *f, + HtpState *htp_state) +{ + uint32_t cnt = 0; + size_t idx = 0; + htp_tx_t *tx = NULL; + int i = 0; + + for (idx = AppLayerTransactionGetInspectId(f); + i < det_ctx->hhd_buffers_list_len; idx++, i++) { + + /* if the buffer already exists, use it */ + if (det_ctx->hhd_buffers[i] != NULL) { + if (s->mpm_flags & SIG_FLAG_MPM_HHDCONTENT) { + cnt += HttpHeaderPatternSearch(det_ctx, + det_ctx->hhd_buffers[i], + det_ctx->hhd_buffers_len[i]); + } + continue; + } + + tx = list_get(htp_state->connp->conn->transactions, idx); + if (tx == NULL) + continue; + + htp_header_t *h = NULL; + uint8_t *headers_buffer = NULL; + uint32_t headers_buffer_len = 0; + table_iterator_reset(tx->request_headers); + while (table_iterator_next(tx->request_headers, (void **)&h) != NULL) { + int size1 = bstr_size(h->name); + int size2 = bstr_size(h->value); + /* the extra 4 bytes if for ": " and "\r\n" */ + headers_buffer = realloc(headers_buffer, headers_buffer_len + size1 + size2 + 4); + if (headers_buffer == NULL) { + SCLogError(SC_ERR_MEM_ALLOC, "Error allocating memory\n"); + exit(EXIT_FAILURE); + } + memcpy(headers_buffer + headers_buffer_len, bstr_ptr(h->name), size1); + headers_buffer_len += size1; + headers_buffer[headers_buffer_len] = ':'; + headers_buffer[headers_buffer_len + 1] = ' '; + headers_buffer_len += 2; + memcpy(headers_buffer + headers_buffer_len, bstr_ptr(h->value), size2); + headers_buffer_len += size2 + 2; + /* \r */ + headers_buffer[headers_buffer_len - 2] = '\r'; + /* \n */ + headers_buffer[headers_buffer_len - 1] = '\n'; + } + + /* store the buffers. We will need it for further inspection */ + det_ctx->hhd_buffers[i] = headers_buffer; + det_ctx->hhd_buffers_len[i] = headers_buffer_len; + + /* carry out the mpm */ + if (s->mpm_flags & SIG_FLAG_MPM_HHDCONTENT) + cnt += HttpHeaderPatternSearch(det_ctx, headers_buffer, headers_buffer_len); + } /* for (idx = AppLayerTransactionGetInspectId(f); .. */ + + SCReturnUInt(cnt); +} + +/** + * \brief Do the http_header content inspection for a signature. + * + * \param de_ctx Detection engine context. + * \param det_ctx Detection engine thread context. + * \param s Signature to inspect. + * \param f Flow. + * \param flags App layer flags. + * \param state App layer state. + * + * \retval 0 No match. + * \retval 1 Match. + */ +int DetectEngineInspectHttpHeader(DetectEngineCtx *de_ctx, + DetectEngineThreadCtx *det_ctx, + Signature *s, Flow *f, uint8_t flags, + void *alstate) +{ + SCEnter(); + int r = 0; + HtpState *htp_state = NULL; + int i = 0; + + htp_state = (HtpState *)alstate; + if (htp_state == NULL) { + SCLogDebug("no HTTP state"); + SCReturnInt(0); + } + + /* locking the flow, we will inspect the htp state */ + SCMutexLock(&f->m); + + if (htp_state->connp == NULL) { + SCLogDebug("HTP state has no connp"); + goto end; + } + + /* it is either the first entry into this function. If it is not, + * then we just don't have any http transactions */ + if (det_ctx->hhd_buffers_list_len == 0) { + /* get the transaction id */ + int tmp_idx = AppLayerTransactionGetInspectId(f); + /* error! get out of here */ + if (tmp_idx == -1) + goto end; + + /* let's get the transaction count. We need this to hold the header + * buffer for each transaction */ + det_ctx->hhd_buffers_list_len = list_size(htp_state->connp->conn->transactions) - tmp_idx; + /* no transactions?! cool. get out of here */ + if (det_ctx->hhd_buffers_list_len == 0) + goto end; + + /* assign space to hold buffers. Each per transaction */ + det_ctx->hhd_buffers = SCMalloc(det_ctx->hhd_buffers_list_len * sizeof(uint8_t *)); + if (det_ctx->hhd_buffers == NULL) { + SCLogError(SC_ERR_MEM_ALLOC, "Error allocating memory"); + return 0; + } + memset(det_ctx->hhd_buffers, 0, det_ctx->hhd_buffers_list_len * sizeof(uint8_t *)); + + det_ctx->hhd_buffers_len = SCMalloc(det_ctx->hhd_buffers_list_len * sizeof(uint32_t)); + if (det_ctx->hhd_buffers_len == NULL) { + SCLogError(SC_ERR_MEM_ALLOC, "Error allocating memory"); + return 0; + } + memset(det_ctx->hhd_buffers_len, 0, det_ctx->hhd_buffers_list_len * sizeof(uint32_t)); + } /* if (det_ctx->hhd_buffers_list_len == 0) */ + + if (s->mpm_flags & SIG_FLAG_MPM_HHDCONTENT) { + if (det_ctx->de_mpm_scanned_hhd == FALSE) { + uint32_t cnt = DetectEngineInspectHttpHeaderMpmInspect(det_ctx, s, + f, htp_state); + if (cnt <= 0) + det_ctx->de_have_hhd = FALSE; + + det_ctx->de_mpm_scanned_hhd = TRUE; + } + } else { + DetectEngineInspectHttpHeaderMpmInspect(det_ctx, s, f, htp_state); + } + + if (det_ctx->de_have_hhd == FALSE && + s->mpm_flags & SIG_FLAG_MPM_HHDCONTENT && + !(s->mpm_flags & SIG_FLAG_MPM_HHDCONTENT_NEG)) { + SCLogDebug("mpm results failure for http headers. Get out of here"); + goto end; + } + + if ((s->mpm_flags & SIG_FLAG_MPM_HHDCONTENT) && (det_ctx->de_mpm_scanned_hhd == TRUE)) { + /* filter out the sig that needs a match, but have no matches */ + if (!(s->mpm_flags & SIG_FLAG_MPM_HHDCONTENT_NEG) && + !(det_ctx->pmq.pattern_id_bitarray[(s->mpm_hhdpattern_id / 8)] & (1 << (s->mpm_hhdpattern_id % 8)))) { + goto end; + } + } + + for (i = 0; i < det_ctx->hhd_buffers_list_len; i++) { + uint8_t *hhd_buffer = det_ctx->hhd_buffers[i]; + uint32_t hhd_buffer_len = det_ctx->hhd_buffers_len[i]; + + if (hhd_buffer == NULL) + continue; + + r = DoInspectHttpHeader(de_ctx, det_ctx, s, s->sm_lists[DETECT_SM_LIST_HHDMATCH], + hhd_buffer, hhd_buffer_len); + if (r == 1) { + break; + } + } + +end: + SCMutexUnlock(&f->m); + SCReturnInt(r); +} + +/** + * \brief Clean the hhd buffers. + * + * \param det_ctx Pointer to the detection engine thread ctx. + */ +void DetectEngineCleanHHDBuffers(DetectEngineThreadCtx *det_ctx) +{ + if (det_ctx->hhd_buffers_list_len != 0) { + int i; + for (i = 0; i < det_ctx->hhd_buffers_list_len; i++) { + if (det_ctx->hhd_buffers[i] != NULL) + SCFree(det_ctx->hhd_buffers[i]); + } + SCFree(det_ctx->hhd_buffers); + det_ctx->hhd_buffers = NULL; + det_ctx->hhd_buffers_list_len = 0; + } + + return; +} + +/***********************************Unittests**********************************/ + +#ifdef UNITTESTS + +/** + *\test Test that the http_header content matches against a http request + * which holds the content. + */ +static int DetectEngineHttpHeaderTest01(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:\"one\"; http_header; " + "sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + + SigGroupBuild(de_ctx); + DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx); + + int r = AppLayerParse(&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_header content matches against a http request + * which holds the content. + */ +static int DetectEngineHttpHeaderTest02(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:\"one\"; depth:15; http_header; " + "sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + + SigGroupBuild(de_ctx); + DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx); + + int r = AppLayerParse(&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_header content matches against a http request + * which holds the content. + */ +static int DetectEngineHttpHeaderTest03(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:!one; depth:5; http_header; " + "sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + + SigGroupBuild(de_ctx); + DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx); + + int r = AppLayerParse(&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_header content matches against a http request + * which holds the content. + */ +static int DetectEngineHttpHeaderTest04(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:one; depth:5; http_header; " + "sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + + SigGroupBuild(de_ctx); + DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx); + + int r = AppLayerParse(&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_header content matches against a http request + * which holds the content. + */ +static int DetectEngineHttpHeaderTest05(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:!one; depth:15; http_header; " + "sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + + SigGroupBuild(de_ctx); + DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx); + + int r = AppLayerParse(&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_header content matches against a http request + * which holds the content. + */ +static int DetectEngineHttpHeaderTest06(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:\"one\"; offset:10; http_header; " + "sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + + SigGroupBuild(de_ctx); + DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx); + + int r = AppLayerParse(&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_header content matches against a http request + * which holds the content. + */ +static int DetectEngineHttpHeaderTest07(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:!one; offset:15; http_header; " + "sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + + SigGroupBuild(de_ctx); + DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx); + + int r = AppLayerParse(&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_header content matches against a http request + * which holds the content. + */ +static int DetectEngineHttpHeaderTest08(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:one; offset:15; http_header; " + "sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + + SigGroupBuild(de_ctx); + DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx); + + int r = AppLayerParse(&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_header content matches against a http request + * which holds the content. + */ +static int DetectEngineHttpHeaderTest09(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:!one; offset:10; http_header; " + "sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + + SigGroupBuild(de_ctx); + DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx); + + int r = AppLayerParse(&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_header content matches against a http request + * which holds the content. + */ +static int DetectEngineHttpHeaderTest10(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:one; http_header; content:three; http_header; within:10; " + "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_header content matches against a http request + * which holds the content. + */ +static int DetectEngineHttpHeaderTest11(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:one; http_header; content:!three; http_header; within:5; " + "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_header content matches against a http request + * which holds the content. + */ +static int DetectEngineHttpHeaderTest12(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:one; http_header; content:!three; http_header; within:10; " + "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_header content matches against a http request + * which holds the content. + */ +static int DetectEngineHttpHeaderTest13(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:one; http_header; content:three; http_header; within:5; " + "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_header content matches against a http request + * which holds the content. + */ +static int DetectEngineHttpHeaderTest14(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:one; http_header; content:five; http_header; distance:7; " + "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_header content matches against a http request + * which holds the content. + */ +static int DetectEngineHttpHeaderTest15(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:one; http_header; content:!five; http_header; distance:15; " + "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_header content matches against a http request + * which holds the content. + */ +static int DetectEngineHttpHeaderTest16(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:one; http_header; content:!five; http_header; distance:7; " + "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_header content matches against a http request + * which holds the content. + */ +static int DetectEngineHttpHeaderTest17(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:one; http_header; content:five; http_header; distance:15; " + "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_header content matches against a http request + * which holds the content. + */ +static int DetectEngineHttpHeaderTest18(void) +{ + TcpSession ssn; + Packet *p = NULL; + ThreadVars th_v; + DetectEngineCtx *de_ctx = NULL; + DetectEngineThreadCtx *det_ctx = NULL; + Flow f; + uint8_t http_buf[] = + "Host: www.onetwothreefourfivesixsevenfive.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:one; http_header; content:five; http_header; " + "sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + + SigGroupBuild(de_ctx); + DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx); + + /* start the search phase */ + det_ctx->sgh = SigMatchSignaturesGetSgh(de_ctx, det_ctx, p); + uint32_t r = HttpHeaderPatternSearch(det_ctx, http_buf, http_len); + if (r != 2) { + printf("expected result 2, got %"PRIu32": ", r); + 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_header content matches against a http request + * which holds the content. + */ +static int DetectEngineHttpHeaderTest19(void) +{ + TcpSession ssn; + Packet *p = NULL; + ThreadVars th_v; + DetectEngineCtx *de_ctx = NULL; + DetectEngineThreadCtx *det_ctx = NULL; + Flow f; + uint8_t http_buf[] = + "Host: www.onetwothreefourfivesixsevenfive.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:one; http_header; fast_pattern; content:five; http_header; " + "sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + + SigGroupBuild(de_ctx); + DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx); + + /* start the search phase */ + det_ctx->sgh = SigMatchSignaturesGetSgh(de_ctx, det_ctx, p); + uint32_t r = HttpHeaderPatternSearch(det_ctx, http_buf, http_len); + if (r != 1) { + printf("expected result 1, got %"PRIu32": ", r); + 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 DetectEngineHttpHeaderRegisterTests(void) +{ + +#ifdef UNITTESTS + UtRegisterTest("DetectEngineHttpHeaderTest01", + DetectEngineHttpHeaderTest01, 1); + UtRegisterTest("DetectEngineHttpHeaderTest02", + DetectEngineHttpHeaderTest02, 1); + UtRegisterTest("DetectEngineHttpHeaderTest03", + DetectEngineHttpHeaderTest03, 1); + UtRegisterTest("DetectEngineHttpHeaderTest04", + DetectEngineHttpHeaderTest04, 1); + UtRegisterTest("DetectEngineHttpHeaderTest05", + DetectEngineHttpHeaderTest05, 1); + UtRegisterTest("DetectEngineHttpHeaderTest06", + DetectEngineHttpHeaderTest06, 1); + UtRegisterTest("DetectEngineHttpHeaderTest07", + DetectEngineHttpHeaderTest07, 1); + UtRegisterTest("DetectEngineHttpHeaderTest08", + DetectEngineHttpHeaderTest08, 1); + UtRegisterTest("DetectEngineHttpHeaderTest09", + DetectEngineHttpHeaderTest09, 1); + UtRegisterTest("DetectEngineHttpHeaderTest10", + DetectEngineHttpHeaderTest10, 1); + UtRegisterTest("DetectEngineHttpHeaderTest11", + DetectEngineHttpHeaderTest11, 1); + UtRegisterTest("DetectEngineHttpHeaderTest12", + DetectEngineHttpHeaderTest12, 1); + UtRegisterTest("DetectEngineHttpHeaderTest13", + DetectEngineHttpHeaderTest13, 1); + UtRegisterTest("DetectEngineHttpHeaderTest14", + DetectEngineHttpHeaderTest14, 1); + UtRegisterTest("DetectEngineHttpHeaderTest15", + DetectEngineHttpHeaderTest15, 1); + UtRegisterTest("DetectEngineHttpHeaderTest16", + DetectEngineHttpHeaderTest16, 1); + UtRegisterTest("DetectEngineHttpHeaderTest17", + DetectEngineHttpHeaderTest17, 1); + UtRegisterTest("DetectEngineHttpHeaderTest18", + DetectEngineHttpHeaderTest18, 1); + UtRegisterTest("DetectEngineHttpHeaderTest19", + DetectEngineHttpHeaderTest19, 1); +#endif /* UNITTESTS */ + + return; +} diff --git a/src/detect-engine-hhd.h b/src/detect-engine-hhd.h new file mode 100644 index 0000000000..f0186a234e --- /dev/null +++ b/src/detect-engine-hhd.h @@ -0,0 +1,32 @@ +/* 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_HHD_H__ +#define __DETECT_ENGINE_HHD_H__ + +int DetectEngineInspectHttpHeader(DetectEngineCtx *, DetectEngineThreadCtx *, + Signature *, Flow *, uint8_t, void *); +void DetectEngineCleanHHDBuffers(DetectEngineThreadCtx *); +void DetectEngineHttpHeaderRegisterTests(void); + +#endif /* __DETECT_ENGINE_HHD_H__ */ + diff --git a/src/detect-engine-mpm.c b/src/detect-engine-mpm.c index bd970993c3..26ab39701f 100644 --- a/src/detect-engine-mpm.c +++ b/src/detect-engine-mpm.c @@ -263,12 +263,14 @@ uint32_t UriPatternSearch(DetectEngineThreadCtx *det_ctx, SCReturnUInt(ret); } -/** \brief Uri Pattern match -- searches for one pattern per signature. +/** \brief Http client body pattern match -- searches for one pattern per + * signature. * - * \param det_ctx detection engine thread ctx - * \param p packet to inspect + * \param det_ctx Detection engine thread ctx. + * \param body The request body to inspect. + * \param body_len Body length. * - * \retval ret number of matches + * \retval ret Number of matches. */ uint32_t HttpClientBodyPatternSearch(DetectEngineThreadCtx *det_ctx, uint8_t *body, uint32_t body_len) @@ -286,6 +288,31 @@ uint32_t HttpClientBodyPatternSearch(DetectEngineThreadCtx *det_ctx, SCReturnUInt(ret); } +/** + * \brief Http header match -- searches for one pattern per signature. + * + * \param det_ctx Detection engine thread ctx. + * \param headers Headers to inspect. + * \param headers_len Headers length. + * + * \retval ret Number of matches. + */ +uint32_t HttpHeaderPatternSearch(DetectEngineThreadCtx *det_ctx, + uint8_t *headers, uint32_t headers_len) +{ + SCEnter(); + + if (det_ctx->sgh->mpm_hhd_ctx == NULL) + SCReturnUInt(0); + + uint32_t ret; + ret = mpm_table[det_ctx->sgh->mpm_hhd_ctx->mpm_type]. + Search(det_ctx->sgh->mpm_hhd_ctx, &det_ctx->mtcu, + &det_ctx->pmq, headers, headers_len); + + SCReturnUInt(ret); +} + /** \brief Pattern match -- searches for only one pattern per signature. * * \param tv threadvars @@ -581,6 +608,7 @@ static void PopulateMpmAddPatternToMpm(DetectEngineCtx *de_ctx, DetectContentData *cd = NULL; DetectContentData *ud = NULL; DetectContentData *hcbd = NULL; + DetectContentData *hhd = NULL; switch (mpm_sm->type) { case DETECT_CONTENT: { @@ -731,7 +759,7 @@ static void PopulateMpmAddPatternToMpm(DetectEngineCtx *de_ctx, } } /* else - if (ud->flags & DETECT_CONTENT_FAST_PATTERN_ONLY) */ - /* add the content to the "packet" mpm */ + /* add the content to the "uri" mpm */ if (ud->flags & DETECT_CONTENT_NOCASE) { mpm_table[sgh->mpm_uri_ctx->mpm_type]. AddPatternNocase(sgh->mpm_uri_ctx, @@ -757,7 +785,7 @@ static void PopulateMpmAddPatternToMpm(DetectEngineCtx *de_ctx, { hcbd = (DetectContentData *)mpm_sm->ctx; if (hcbd->flags & DETECT_CONTENT_FAST_PATTERN_CHOP) { - /* add the content to the "uri" mpm */ + /* add the content to the "hcbd" mpm */ if (hcbd->flags & DETECT_CONTENT_NOCASE) { mpm_table[sgh->mpm_hcbd_ctx->mpm_type]. AddPatternNocase(sgh->mpm_hcbd_ctx, @@ -784,7 +812,7 @@ static void PopulateMpmAddPatternToMpm(DetectEngineCtx *de_ctx, } } /* else - if (hcbd->flags & DETECT_CONTENT_FAST_PATTERN_ONLY) */ - /* add the content to the "packet" mpm */ + /* add the content to the "hcbd" mpm */ if (hcbd->flags & DETECT_CONTENT_NOCASE) { mpm_table[sgh->mpm_hcbd_ctx->mpm_type]. AddPatternNocase(sgh->mpm_hcbd_ctx, @@ -806,6 +834,59 @@ static void PopulateMpmAddPatternToMpm(DetectEngineCtx *de_ctx, break; } /* case DETECT_AL_HTTP_CLIENT_BODY */ + case DETECT_AL_HTTP_HEADER: + { + hhd = (DetectContentData *)mpm_sm->ctx; + if (hhd->flags & DETECT_CONTENT_FAST_PATTERN_CHOP) { + /* add the content to the "hhd" mpm */ + if (hhd->flags & DETECT_CONTENT_NOCASE) { + mpm_table[sgh->mpm_hhd_ctx->mpm_type]. + AddPatternNocase(sgh->mpm_hhd_ctx, + hhd->content + hhd->fp_chop_offset, + hhd->fp_chop_len, + 0, 0, hhd->id, s->num, flags); + } else { + mpm_table[sgh->mpm_hhd_ctx->mpm_type]. + AddPattern(sgh->mpm_hhd_ctx, + hhd->content + hhd->fp_chop_offset, + hhd->fp_chop_len, + 0, 0, hhd->id, s->num, flags); + } + } else { + if (hhd->flags & DETECT_CONTENT_FAST_PATTERN_ONLY) { + if (DETECT_CONTENT_IS_SINGLE(hhd)) { + hhd->flags |= DETECT_CONTENT_HHD_MPM; + } + + /* see if we can bypass the match validation for this pattern */ + } else { + if (DETECT_CONTENT_IS_SINGLE(hhd)) { + hhd->flags |= DETECT_CONTENT_HHD_MPM; + } + } /* else - if (hhd->flags & DETECT_CONTENT_FAST_PATTERN_ONLY) */ + + /* add the content to the "hhd" mpm */ + if (hhd->flags & DETECT_CONTENT_NOCASE) { + mpm_table[sgh->mpm_hhd_ctx->mpm_type]. + AddPatternNocase(sgh->mpm_hhd_ctx, + hhd->content, hhd->content_len, + 0, 0, hhd->id, s->num, flags); + } else { + mpm_table[sgh->mpm_hhd_ctx->mpm_type]. + AddPattern(sgh->mpm_hhd_ctx, + hhd->content, hhd->content_len, + 0, 0, hhd->id, s->num, flags); + } + } + /* tell matcher we are inspecting uri */ + s->mpm_flags |= SIG_FLAG_MPM_HHDCONTENT; + s->mpm_hhdpattern_id = hhd->id; + if (hhd->flags & DETECT_CONTENT_NEGATED) + s->mpm_flags |= SIG_FLAG_MPM_HHDCONTENT_NEG; + + break; + } /* case DETECT_AL_HTTP_HEADER */ + } /* switch (mpm_sm->type) */ SCLogDebug("%"PRIu32" adding cd->id %"PRIu32" to the mpm phase " @@ -1853,7 +1934,10 @@ int PatternMatchPrepareGroup(DetectEngineCtx *de_ctx, SigGroupHead *sh) uint32_t has_co_packet = 0; /**< our sgh has packet payload inspecting content */ uint32_t has_co_stream = 0; /**< our sgh has stream inspecting content */ uint32_t has_co_uri = 0; /**< our sgh has uri inspecting content */ + /* used to indicate if sgh has atleast one sig with http_client_body */ uint32_t has_co_hcbd = 0; + /* used to indicate if sgh has atleast one sig with http_header */ + uint32_t has_co_hhd = 0; //uint32_t cnt = 0; uint32_t sig = 0; @@ -1888,6 +1972,11 @@ int PatternMatchPrepareGroup(DetectEngineCtx *de_ctx, SigGroupHead *sh) if (s->sm_lists[DETECT_SM_LIST_HCBDMATCH] != NULL) { has_co_hcbd = 1; } + + if (s->sm_lists[DETECT_SM_LIST_HHDMATCH] != NULL) { + has_co_hhd = 1; + } + } if (has_co_packet > 0) { @@ -1902,6 +1991,9 @@ int PatternMatchPrepareGroup(DetectEngineCtx *de_ctx, SigGroupHead *sh) if (has_co_hcbd > 0) { sh->flags |= SIG_GROUP_HAVEHCBDCONTENT; } + if (has_co_hhd > 0) { + sh->flags |= SIG_GROUP_HAVEHHDCONTENT; + } /* intialize contexes */ if (sh->flags & SIG_GROUP_HAVECONTENT) { @@ -1965,7 +2057,7 @@ int PatternMatchPrepareGroup(DetectEngineCtx *de_ctx, SigGroupHead *sh) sh->mpm_hcbd_ctx = MpmFactoryGetMpmCtxForProfile(MPM_CTX_FACTORY_UNIQUE_CONTEXT); } if (sh->mpm_hcbd_ctx == NULL) { - SCLogDebug("sh->mpm_stream_ctx == NULL. This should never happen"); + SCLogDebug("sh->mpm_hcbd_ctx == NULL. This should never happen"); exit(EXIT_FAILURE); } @@ -1976,6 +2068,24 @@ int PatternMatchPrepareGroup(DetectEngineCtx *de_ctx, SigGroupHead *sh) #endif } + if (sh->flags & SIG_GROUP_HAVEHHDCONTENT) { + if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_SINGLE) { + sh->mpm_hhd_ctx = MpmFactoryGetMpmCtxForProfile(de_ctx->sgh_mpm_context_hhd); + } else { + sh->mpm_hhd_ctx = MpmFactoryGetMpmCtxForProfile(MPM_CTX_FACTORY_UNIQUE_CONTEXT); + } + if (sh->mpm_hhd_ctx == NULL) { + SCLogDebug("sh->mpm_hhd_ctx == NULL. This should never happen"); + exit(EXIT_FAILURE); + } + +#ifndef __SC_CUDA_SUPPORT__ + MpmInitCtx(sh->mpm_hhd_ctx, de_ctx->mpm_matcher, -1); +#else + MpmInitCtx(sh->mpm_hhd_ctx, de_ctx->mpm_matcher, de_ctx->cuda_rc_mod_handle); +#endif + } + /* for each signature in this group do */ //for (sig = 0; sig < sh->sig_cnt; sig++) { // s = sh->match_array[sig]; @@ -2108,7 +2218,8 @@ int PatternMatchPrepareGroup(DetectEngineCtx *de_ctx, SigGroupHead *sh) 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_HAVEHCBDCONTENT || + sh->flags & SIG_GROUP_HAVEHHDCONTENT) { PatternMatchPreparePopulateMpm(de_ctx, sh); @@ -2157,6 +2268,18 @@ int PatternMatchPrepareGroup(DetectEngineCtx *de_ctx, SigGroupHead *sh) } } } + if (sh->mpm_hhd_ctx != NULL) { + if (sh->mpm_hhd_ctx->pattern_cnt == 0) { + MpmFactoryReClaimMpmCtx(sh->mpm_hhd_ctx); + sh->mpm_hhd_ctx = NULL; + } else { + if (sh->flags & SIG_GROUP_HAVEHHDCONTENT) { + if (mpm_table[sh->mpm_hhd_ctx->mpm_type].Prepare != NULL) + mpm_table[sh->mpm_hhd_ctx->mpm_type].Prepare(sh->mpm_hhd_ctx); + } + } + } + } /* if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) */ } else { MpmFactoryReClaimMpmCtx(sh->mpm_ctx); @@ -2167,6 +2290,8 @@ int PatternMatchPrepareGroup(DetectEngineCtx *de_ctx, SigGroupHead *sh) sh->mpm_uri_ctx = NULL; MpmFactoryReClaimMpmCtx(sh->mpm_hcbd_ctx); sh->mpm_hcbd_ctx = NULL; + MpmFactoryReClaimMpmCtx(sh->mpm_hhd_ctx); + sh->mpm_hhd_ctx = NULL; } ///* uricontent */ diff --git a/src/detect-engine-mpm.h b/src/detect-engine-mpm.h index 6b57df8ccb..394b2c664c 100644 --- a/src/detect-engine-mpm.h +++ b/src/detect-engine-mpm.h @@ -37,6 +37,7 @@ uint32_t PacketPatternSearch(ThreadVars *, DetectEngineThreadCtx *, Packet *); uint32_t UriPatternSearch(DetectEngineThreadCtx *, uint8_t *, uint16_t); uint32_t StreamPatternSearch(ThreadVars *, DetectEngineThreadCtx *, Packet *, StreamMsg *, uint8_t); uint32_t HttpClientBodyPatternSearch(DetectEngineThreadCtx *, uint8_t *, uint32_t); +uint32_t HttpHeaderPatternSearch(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 0c0b3a1ecc..9369884892 100644 --- a/src/detect-engine-state.c +++ b/src/detect-engine-state.c @@ -32,6 +32,7 @@ #include "detect-engine-uri.h" #include "detect-engine-hcbd.h" +#include "detect-engine-hhd.h" #include "detect-engine-dcepayload.h" #include "stream-tcp.h" @@ -204,7 +205,9 @@ int DeStateUpdateInspectTransactionId(Flow *f, char direction) { * \param dce did dce already match (if any) * \param hcbd did http client body already match (if any) */ -static void DeStateSignatureAppend(DetectEngineState *state, Signature *s, SigMatch *sm, char uri, char dce, char hcbd) { +static void DeStateSignatureAppend(DetectEngineState *state, Signature *s, + SigMatch *sm, char uri, char dce, char hcbd, + char hhd) { DeStateStore *store = state->tail; if (store == NULL) { @@ -241,6 +244,9 @@ static void DeStateSignatureAppend(DetectEngineState *state, Signature *s, SigMa if (hcbd) { store->store[idx].flags |= DE_STATE_FLAG_HCBD_MATCH; } + if (hhd) { + store->store[idx].flags |= DE_STATE_FLAG_HHD_MATCH; + } store->store[idx].nm = sm; state->cnt++; @@ -302,6 +308,8 @@ int DeStateDetectStartDetection(ThreadVars *tv, DetectEngineCtx *de_ctx, char uinspect = 0; char hcbdmatch = 0; char hcbdinspect = 0; + char hhdmatch = 0; + char hhdinspect = 0; char dmatch = 0; char dinspect = 0; char appinspect = 0; @@ -313,7 +321,7 @@ int DeStateDetectStartDetection(ThreadVars *tv, DetectEngineCtx *de_ctx, SCLogDebug("s->id %"PRIu32, s->id); - /* Check the uricontent keywords here. */ + /* Check the uricontent, http client body, http header keywords here */ if (alproto == ALPROTO_HTTP && (flags & STREAM_TOSERVER)) { if (s->sm_lists[DETECT_SM_LIST_UMATCH] != NULL) { uinspect = 1; @@ -337,6 +345,15 @@ int DeStateDetectStartDetection(ThreadVars *tv, DetectEngineCtx *de_ctx, } SCLogDebug("inspecting http client body"); } + if (s->sm_lists[DETECT_SM_LIST_HHDMATCH] != NULL) { + hhdinspect = 1; + if (DetectEngineInspectHttpHeader(de_ctx, det_ctx, s, f, + flags, alstate) == 1) { + hhdmatch = 1; + } + SCLogDebug("inspecting http client body"); + } + } else if (alproto == ALPROTO_DCERPC || alproto == ALPROTO_SMB || alproto == ALPROTO_SMB2) { if (s->sm_lists[DETECT_SM_LIST_DMATCH] != NULL) { dinspect = 1; @@ -367,8 +384,8 @@ int DeStateDetectStartDetection(ThreadVars *tv, DetectEngineCtx *de_ctx, } } - appinspect = uinspect + dinspect + hcbdinspect; - appmatch = umatch + dmatch + hcbdmatch; + appinspect = uinspect + dinspect + hcbdinspect + hhdinspect; + appmatch = umatch + dmatch + hcbdmatch + hhdmatch; if (s->sm_lists[DETECT_SM_LIST_AMATCH] != NULL) { for ( ; sm != NULL; sm = sm->next) { @@ -410,8 +427,8 @@ int DeStateDetectStartDetection(ThreadVars *tv, DetectEngineCtx *de_ctx, } } - SCLogDebug("detection done, store results: sm %p, uri %d, dce %d, hcbd %d", - sm, umatch, dmatch, hcbdmatch); + SCLogDebug("detection done, store results: sm %p, uri %d, dce %d, hcbd %d " + "hhd %d", sm, umatch, dmatch, hcbdmatch, hhdmatch); SCMutexLock(&f->de_state_m); /* match or no match, we store the state anyway @@ -421,7 +438,8 @@ int DeStateDetectStartDetection(ThreadVars *tv, DetectEngineCtx *de_ctx, f->de_state = DetectEngineStateAlloc(); } if (f->de_state != NULL) { - DeStateSignatureAppend(f->de_state, s, sm, umatch, dmatch, hcbdmatch); + /* \todo shift to an array to transfer these match values*/ + DeStateSignatureAppend(f->de_state, s, sm, umatch, dmatch, hcbdmatch, hhdmatch); } SCMutexUnlock(&f->de_state_m); @@ -445,6 +463,8 @@ int DeStateDetectContinueDetection(ThreadVars *tv, DetectEngineCtx *de_ctx, Dete char uinspect = 0; char hcbdmatch = 0; char hcbdinspect = 0; + char hhdmatch = 0; + char hhdinspect = 0; char dmatch = 0; char dinspect = 0; char appinspect = 0; @@ -473,6 +493,8 @@ int DeStateDetectContinueDetection(ThreadVars *tv, DetectEngineCtx *de_ctx, Dete uinspect = 0; hcbdmatch = 0; hcbdinspect = 0; + hhdmatch = 0; + hhdinspect = 0; dmatch = 0; dinspect = 0; appinspect = 0; @@ -523,12 +545,25 @@ int DeStateDetectContinueDetection(ThreadVars *tv, DetectEngineCtx *de_ctx, Dete if (DetectEngineInspectHttpClientBody(de_ctx, det_ctx, s, f, flags, alstate) == 1) { - SCLogDebug("uri matched"); + SCLogDebug("http client body matched"); item->flags |= DE_STATE_FLAG_HCBD_MATCH; hcbdmatch = 1; } } } + if (s->sm_lists[DETECT_SM_LIST_HHDMATCH] != NULL) { + if (!(item->flags & DE_STATE_FLAG_HHD_MATCH)) { + SCLogDebug("inspecting http header data"); + hhdinspect = 1; + + if (DetectEngineInspectHttpHeader(de_ctx, det_ctx, s, f, + flags, alstate) == 1) { + SCLogDebug("http header matched"); + item->flags |= DE_STATE_FLAG_HHD_MATCH; + hhdmatch = 1; + } + } + } } else if (alproto == ALPROTO_DCERPC || alproto == ALPROTO_SMB || alproto == ALPROTO_SMB2) { if (s->sm_lists[DETECT_SM_LIST_DMATCH] != NULL) { if (!(item->flags & DE_STATE_FLAG_DCE_MATCH)) { @@ -566,8 +601,8 @@ int DeStateDetectContinueDetection(ThreadVars *tv, DetectEngineCtx *de_ctx, Dete } - appinspect = uinspect + dinspect + hcbdinspect; - appmatch = umatch + dmatch + hcbdmatch; + appinspect = uinspect + dinspect + hcbdinspect + hhdinspect; + appmatch = umatch + dmatch + hcbdmatch + hhdmatch; SCLogDebug("appinspect %d, appmatch %d", appinspect, appmatch); /* next, check the other sig matches */ @@ -707,39 +742,39 @@ static int DeStateTest02(void) { memset(&s, 0x00, sizeof(s)); s.num = 0; - DeStateSignatureAppend(state, &s, NULL, 0, 0, 0); + DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0); s.num = 11; - DeStateSignatureAppend(state, &s, NULL, 0, 0, 0); + DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0); s.num = 22; - DeStateSignatureAppend(state, &s, NULL, 0, 0, 0); + DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0); s.num = 33; - DeStateSignatureAppend(state, &s, NULL, 0, 0, 0); + DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0); s.num = 44; - DeStateSignatureAppend(state, &s, NULL, 0, 0, 0); + DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0); s.num = 55; - DeStateSignatureAppend(state, &s, NULL, 0, 0, 0); + DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0); s.num = 66; - DeStateSignatureAppend(state, &s, NULL, 0, 0, 0); + DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0); s.num = 77; - DeStateSignatureAppend(state, &s, NULL, 0, 0, 0); + DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0); s.num = 88; - DeStateSignatureAppend(state, &s, NULL, 0, 0, 0); + DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0); s.num = 99; - DeStateSignatureAppend(state, &s, NULL, 0, 0, 0); + DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0); s.num = 100; - DeStateSignatureAppend(state, &s, NULL, 0, 0, 0); + DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0); s.num = 111; - DeStateSignatureAppend(state, &s, NULL, 0, 0, 0); + DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0); s.num = 122; - DeStateSignatureAppend(state, &s, NULL, 0, 0, 0); + DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0); s.num = 133; - DeStateSignatureAppend(state, &s, NULL, 0, 0, 0); + DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0); s.num = 144; - DeStateSignatureAppend(state, &s, NULL, 0, 0, 0); + DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0); s.num = 155; - DeStateSignatureAppend(state, &s, NULL, 0, 0, 0); + DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0); s.num = 166; - DeStateSignatureAppend(state, &s, NULL, 0, 0, 0); + DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0); if (state->head == NULL) { goto end; @@ -782,9 +817,9 @@ static int DeStateTest03(void) { memset(&s, 0x00, sizeof(s)); s.num = 11; - DeStateSignatureAppend(state, &s, NULL, 0, 0, 0); + DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0); s.num = 22; - DeStateSignatureAppend(state, &s, NULL, 1, 0, 0); + DeStateSignatureAppend(state, &s, NULL, 1, 0, 0, 0); if (state->head == NULL) { goto end; diff --git a/src/detect-engine-state.h b/src/detect-engine-state.h index dba2504971..6511c39c1b 100644 --- a/src/detect-engine-state.h +++ b/src/detect-engine-state.h @@ -48,7 +48,8 @@ #define DE_STATE_FLAG_URI_MATCH 0x02 /**< uri part of the sig matched */ #define DE_STATE_FLAG_DCE_MATCH 0x04 /**< dce payload inspection part matched */ #define DE_STATE_FLAG_HCBD_MATCH 0x08 /**< hcbd payload inspection part matched */ -#define DE_STATE_FLAG_FULL_MATCH 0x10 /**< sig already fully matched */ +#define DE_STATE_FLAG_HHD_MATCH 0x10 /**< hcbd payload inspection part matched */ +#define DE_STATE_FLAG_FULL_MATCH 0x20 /**< 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 936e44e1a2..1c84b683fe 100644 --- a/src/detect-fast-pattern.c +++ b/src/detect-fast-pattern.c @@ -128,6 +128,9 @@ void SupportFastPatternForSigMatchTypes(void) SupportFastPatternForSigMatchType(DETECT_AL_HTTP_CLIENT_BODY); SupportFastPatternForSigMatchList(DETECT_SM_LIST_HCBDMATCH); + SupportFastPatternForSigMatchType(DETECT_AL_HTTP_HEADER); + SupportFastPatternForSigMatchList(DETECT_SM_LIST_HHDMATCH); + return; } @@ -194,18 +197,20 @@ static int DetectFastPatternSetup(DetectEngineCtx *de_ctx, Signature *s, char *a if (s->sm_lists_tail[DETECT_SM_LIST_PMATCH] == NULL && 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_HCBDMATCH] == NULL && + s->sm_lists_tail[DETECT_SM_LIST_HHDMATCH] == 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 and http_client_body"); + "uricontent, http_client_body and http_header"); return -1; } - SigMatch *pm = SigMatchGetLastSMFromLists(s, 6, + SigMatch *pm = SigMatchGetLastSMFromLists(s, 8, 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_CLIENT_BODY, s->sm_lists_tail[DETECT_SM_LIST_HCBDMATCH], + DETECT_AL_HTTP_HEADER, s->sm_lists_tail[DETECT_SM_LIST_HHDMATCH]); if (pm == NULL) { SCLogError(SC_ERR_INVALID_SIGNATURE, "fast_pattern found inside " "the rule, without a content context. Please use a " @@ -5417,199 +5422,1367 @@ int DetectFastPatternTest178(void) return result; } -#endif -void DetectFastPatternRegisterTests(void) + + + + + + + + + + + + + + + + + + + + +int DetectFastPatternTest179(void) { + DetectEngineCtx *de_ctx = NULL; + int result = 0; -#ifdef UNITTESTS - UtRegisterTest("DetectFastPatternTest01", DetectFastPatternTest01, 1); - UtRegisterTest("DetectFastPatternTest02", DetectFastPatternTest02, 1); - UtRegisterTest("DetectFastPatternTest03", DetectFastPatternTest03, 1); - UtRegisterTest("DetectFastPatternTest04", DetectFastPatternTest04, 1); - UtRegisterTest("DetectFastPatternTest05", DetectFastPatternTest05, 1); - UtRegisterTest("DetectFastPatternTest06", DetectFastPatternTest06, 1); - UtRegisterTest("DetectFastPatternTest07", DetectFastPatternTest07, 1); - UtRegisterTest("DetectFastPatternTest08", DetectFastPatternTest08, 1); - UtRegisterTest("DetectFastPatternTest09", DetectFastPatternTest09, 1); - UtRegisterTest("DetectFastPatternTest10", DetectFastPatternTest10, 1); - UtRegisterTest("DetectFastPatternTest11", DetectFastPatternTest11, 1); - UtRegisterTest("DetectFastPatternTest12", DetectFastPatternTest12, 1); - UtRegisterTest("DetectFastPatternTest13", DetectFastPatternTest13, 1); - UtRegisterTest("DetectFastPatternTest14", DetectFastPatternTest14, 1); - UtRegisterTest("DetectFastPatternTest15", DetectFastPatternTest15, 1); - UtRegisterTest("DetectFastPatternTest16", DetectFastPatternTest16, 1); - UtRegisterTest("DetectFastPatternTest17", DetectFastPatternTest17, 1); - UtRegisterTest("DetectFastPatternTest18", DetectFastPatternTest18, 1); - UtRegisterTest("DetectFastPatternTest19", DetectFastPatternTest19, 1); - UtRegisterTest("DetectFastPatternTest20", DetectFastPatternTest20, 1); - UtRegisterTest("DetectFastPatternTest21", DetectFastPatternTest21, 1); - UtRegisterTest("DetectFastPatternTest22", DetectFastPatternTest22, 1); - UtRegisterTest("DetectFastPatternTest23", DetectFastPatternTest23, 1); - UtRegisterTest("DetectFastPatternTest24", DetectFastPatternTest24, 1); - UtRegisterTest("DetectFastPatternTest25", DetectFastPatternTest25, 1); - UtRegisterTest("DetectFastPatternTest26", DetectFastPatternTest26, 1); - UtRegisterTest("DetectFastPatternTest27", DetectFastPatternTest27, 1); - UtRegisterTest("DetectFastPatternTest28", DetectFastPatternTest28, 1); - UtRegisterTest("DetectFastPatternTest29", DetectFastPatternTest29, 1); - UtRegisterTest("DetectFastPatternTest30", DetectFastPatternTest30, 1); - UtRegisterTest("DetectFastPatternTest31", DetectFastPatternTest31, 1); - UtRegisterTest("DetectFastPatternTest32", DetectFastPatternTest32, 1); - UtRegisterTest("DetectFastPatternTest33", DetectFastPatternTest33, 1); - UtRegisterTest("DetectFastPatternTest34", DetectFastPatternTest34, 1); - UtRegisterTest("DetectFastPatternTest35", DetectFastPatternTest35, 1); - UtRegisterTest("DetectFastPatternTest36", DetectFastPatternTest36, 1); - UtRegisterTest("DetectFastPatternTest37", DetectFastPatternTest37, 1); - UtRegisterTest("DetectFastPatternTest38", DetectFastPatternTest38, 1); - UtRegisterTest("DetectFastPatternTest39", DetectFastPatternTest39, 1); - UtRegisterTest("DetectFastPatternTest40", DetectFastPatternTest40, 1); - UtRegisterTest("DetectFastPatternTest41", DetectFastPatternTest41, 1); - UtRegisterTest("DetectFastPatternTest42", DetectFastPatternTest42, 1); - UtRegisterTest("DetectFastPatternTest43", DetectFastPatternTest43, 1); - UtRegisterTest("DetectFastPatternTest44", DetectFastPatternTest44, 1); - UtRegisterTest("DetectFastPatternTest45", DetectFastPatternTest45, 1); - UtRegisterTest("DetectFastPatternTest46", DetectFastPatternTest46, 1); - UtRegisterTest("DetectFastPatternTest47", DetectFastPatternTest47, 1); - UtRegisterTest("DetectFastPatternTest48", DetectFastPatternTest48, 1); - UtRegisterTest("DetectFastPatternTest49", DetectFastPatternTest49, 1); - UtRegisterTest("DetectFastPatternTest50", DetectFastPatternTest50, 1); - UtRegisterTest("DetectFastPatternTest51", DetectFastPatternTest51, 1); - UtRegisterTest("DetectFastPatternTest52", DetectFastPatternTest52, 1); - UtRegisterTest("DetectFastPatternTest53", DetectFastPatternTest53, 1); - /* content fast_pattern tests ^ */ - /* uricontent fast_pattern tests v */ - UtRegisterTest("DetectFastPatternTest54", DetectFastPatternTest54, 1); - UtRegisterTest("DetectFastPatternTest55", DetectFastPatternTest55, 1); - UtRegisterTest("DetectFastPatternTest56", DetectFastPatternTest56, 1); - UtRegisterTest("DetectFastPatternTest57", DetectFastPatternTest57, 1); - UtRegisterTest("DetectFastPatternTest58", DetectFastPatternTest58, 1); - UtRegisterTest("DetectFastPatternTest59", DetectFastPatternTest59, 1); - UtRegisterTest("DetectFastPatternTest60", DetectFastPatternTest60, 1); - UtRegisterTest("DetectFastPatternTest61", DetectFastPatternTest61, 1); - UtRegisterTest("DetectFastPatternTest62", DetectFastPatternTest62, 1); - UtRegisterTest("DetectFastPatternTest63", DetectFastPatternTest63, 1); - UtRegisterTest("DetectFastPatternTest64", DetectFastPatternTest64, 1); - UtRegisterTest("DetectFastPatternTest65", DetectFastPatternTest65, 1); - UtRegisterTest("DetectFastPatternTest66", DetectFastPatternTest66, 1); - UtRegisterTest("DetectFastPatternTest67", DetectFastPatternTest67, 1); - UtRegisterTest("DetectFastPatternTest68", DetectFastPatternTest68, 1); - UtRegisterTest("DetectFastPatternTest69", DetectFastPatternTest69, 1); - UtRegisterTest("DetectFastPatternTest70", DetectFastPatternTest70, 1); - UtRegisterTest("DetectFastPatternTest71", DetectFastPatternTest71, 1); - UtRegisterTest("DetectFastPatternTest72", DetectFastPatternTest72, 1); - UtRegisterTest("DetectFastPatternTest73", DetectFastPatternTest73, 1); - UtRegisterTest("DetectFastPatternTest74", DetectFastPatternTest74, 1); - UtRegisterTest("DetectFastPatternTest75", DetectFastPatternTest75, 1); - UtRegisterTest("DetectFastPatternTest76", DetectFastPatternTest76, 1); - UtRegisterTest("DetectFastPatternTest77", DetectFastPatternTest77, 1); - UtRegisterTest("DetectFastPatternTest78", DetectFastPatternTest78, 1); - UtRegisterTest("DetectFastPatternTest79", DetectFastPatternTest79, 1); - UtRegisterTest("DetectFastPatternTest80", DetectFastPatternTest80, 1); - UtRegisterTest("DetectFastPatternTest81", DetectFastPatternTest81, 1); - UtRegisterTest("DetectFastPatternTest82", DetectFastPatternTest82, 1); - UtRegisterTest("DetectFastPatternTest83", DetectFastPatternTest83, 1); - UtRegisterTest("DetectFastPatternTest84", DetectFastPatternTest84, 1); - UtRegisterTest("DetectFastPatternTest85", DetectFastPatternTest85, 1); - UtRegisterTest("DetectFastPatternTest86", DetectFastPatternTest86, 1); - UtRegisterTest("DetectFastPatternTest87", DetectFastPatternTest87, 1); - UtRegisterTest("DetectFastPatternTest88", DetectFastPatternTest88, 1); - UtRegisterTest("DetectFastPatternTest89", DetectFastPatternTest89, 1); - UtRegisterTest("DetectFastPatternTest90", DetectFastPatternTest90, 1); - UtRegisterTest("DetectFastPatternTest91", DetectFastPatternTest91, 1); - UtRegisterTest("DetectFastPatternTest92", DetectFastPatternTest92, 1); - /* uricontent fast_pattern tests ^ */ - /* http_uri fast_pattern tests v */ - UtRegisterTest("DetectFastPatternTest93", DetectFastPatternTest93, 1); - UtRegisterTest("DetectFastPatternTest94", DetectFastPatternTest94, 1); - UtRegisterTest("DetectFastPatternTest95", DetectFastPatternTest95, 1); - UtRegisterTest("DetectFastPatternTest96", DetectFastPatternTest96, 1); - UtRegisterTest("DetectFastPatternTest97", DetectFastPatternTest97, 1); - UtRegisterTest("DetectFastPatternTest98", DetectFastPatternTest98, 1); - UtRegisterTest("DetectFastPatternTest99", DetectFastPatternTest99, 1); - UtRegisterTest("DetectFastPatternTest100", DetectFastPatternTest100, 1); - UtRegisterTest("DetectFastPatternTest101", DetectFastPatternTest101, 1); - UtRegisterTest("DetectFastPatternTest102", DetectFastPatternTest102, 1); - UtRegisterTest("DetectFastPatternTest103", DetectFastPatternTest103, 1); - UtRegisterTest("DetectFastPatternTest104", DetectFastPatternTest104, 1); - UtRegisterTest("DetectFastPatternTest105", DetectFastPatternTest105, 1); - UtRegisterTest("DetectFastPatternTest106", DetectFastPatternTest106, 1); - UtRegisterTest("DetectFastPatternTest107", DetectFastPatternTest107, 1); - UtRegisterTest("DetectFastPatternTest108", DetectFastPatternTest108, 1); - UtRegisterTest("DetectFastPatternTest109", DetectFastPatternTest109, 1); - UtRegisterTest("DetectFastPatternTest110", DetectFastPatternTest110, 1); - UtRegisterTest("DetectFastPatternTest111", DetectFastPatternTest111, 1); - UtRegisterTest("DetectFastPatternTest112", DetectFastPatternTest112, 1); - UtRegisterTest("DetectFastPatternTest113", DetectFastPatternTest113, 1); - UtRegisterTest("DetectFastPatternTest114", DetectFastPatternTest114, 1); - UtRegisterTest("DetectFastPatternTest115", DetectFastPatternTest115, 1); - UtRegisterTest("DetectFastPatternTest116", DetectFastPatternTest116, 1); - UtRegisterTest("DetectFastPatternTest117", DetectFastPatternTest117, 1); - UtRegisterTest("DetectFastPatternTest118", DetectFastPatternTest118, 1); - UtRegisterTest("DetectFastPatternTest119", DetectFastPatternTest119, 1); - UtRegisterTest("DetectFastPatternTest120", DetectFastPatternTest120, 1); - UtRegisterTest("DetectFastPatternTest121", DetectFastPatternTest121, 1); - UtRegisterTest("DetectFastPatternTest122", DetectFastPatternTest122, 1); - UtRegisterTest("DetectFastPatternTest123", DetectFastPatternTest123, 1); - UtRegisterTest("DetectFastPatternTest124", DetectFastPatternTest124, 1); - UtRegisterTest("DetectFastPatternTest125", DetectFastPatternTest125, 1); - UtRegisterTest("DetectFastPatternTest126", DetectFastPatternTest126, 1); - UtRegisterTest("DetectFastPatternTest127", DetectFastPatternTest127, 1); - UtRegisterTest("DetectFastPatternTest128", DetectFastPatternTest128, 1); - UtRegisterTest("DetectFastPatternTest129", DetectFastPatternTest129, 1); - UtRegisterTest("DetectFastPatternTest130", DetectFastPatternTest130, 1); - UtRegisterTest("DetectFastPatternTest131", DetectFastPatternTest131, 1); - UtRegisterTest("DetectFastPatternTest132", DetectFastPatternTest132, 1); - UtRegisterTest("DetectFastPatternTest133", DetectFastPatternTest133, 1); - /* http_uri fast_pattern tests ^ */ - /* http_client_body fast_pattern tests v */ - UtRegisterTest("DetectFastPatternTest134", DetectFastPatternTest134, 1); - UtRegisterTest("DetectFastPatternTest135", DetectFastPatternTest135, 1); - UtRegisterTest("DetectFastPatternTest136", DetectFastPatternTest136, 1); - UtRegisterTest("DetectFastPatternTest137", DetectFastPatternTest137, 1); - UtRegisterTest("DetectFastPatternTest138", DetectFastPatternTest138, 1); - UtRegisterTest("DetectFastPatternTest139", DetectFastPatternTest139, 1); - UtRegisterTest("DetectFastPatternTest140", DetectFastPatternTest140, 1); - UtRegisterTest("DetectFastPatternTest141", DetectFastPatternTest141, 1); - UtRegisterTest("DetectFastPatternTest142", DetectFastPatternTest142, 1); - UtRegisterTest("DetectFastPatternTest143", DetectFastPatternTest143, 1); - UtRegisterTest("DetectFastPatternTest144", DetectFastPatternTest144, 1); - UtRegisterTest("DetectFastPatternTest145", DetectFastPatternTest145, 1); - UtRegisterTest("DetectFastPatternTest146", DetectFastPatternTest146, 1); - UtRegisterTest("DetectFastPatternTest147", DetectFastPatternTest147, 1); - UtRegisterTest("DetectFastPatternTest148", DetectFastPatternTest148, 1); - UtRegisterTest("DetectFastPatternTest149", DetectFastPatternTest149, 1); - UtRegisterTest("DetectFastPatternTest150", DetectFastPatternTest150, 1); - UtRegisterTest("DetectFastPatternTest151", DetectFastPatternTest151, 1); - UtRegisterTest("DetectFastPatternTest152", DetectFastPatternTest152, 1); - UtRegisterTest("DetectFastPatternTest153", DetectFastPatternTest153, 1); - UtRegisterTest("DetectFastPatternTest154", DetectFastPatternTest154, 1); - UtRegisterTest("DetectFastPatternTest155", DetectFastPatternTest155, 1); - UtRegisterTest("DetectFastPatternTest156", DetectFastPatternTest156, 1); - UtRegisterTest("DetectFastPatternTest157", DetectFastPatternTest157, 1); - UtRegisterTest("DetectFastPatternTest158", DetectFastPatternTest158, 1); - UtRegisterTest("DetectFastPatternTest159", DetectFastPatternTest159, 1); - UtRegisterTest("DetectFastPatternTest160", DetectFastPatternTest160, 1); - UtRegisterTest("DetectFastPatternTest161", DetectFastPatternTest161, 1); - UtRegisterTest("DetectFastPatternTest162", DetectFastPatternTest162, 1); - UtRegisterTest("DetectFastPatternTest163", DetectFastPatternTest163, 1); - UtRegisterTest("DetectFastPatternTest164", DetectFastPatternTest164, 1); - UtRegisterTest("DetectFastPatternTest165", DetectFastPatternTest165, 1); - UtRegisterTest("DetectFastPatternTest166", DetectFastPatternTest166, 1); - UtRegisterTest("DetectFastPatternTest167", DetectFastPatternTest167, 1); - UtRegisterTest("DetectFastPatternTest168", DetectFastPatternTest168, 1); - UtRegisterTest("DetectFastPatternTest169", DetectFastPatternTest169, 1); - UtRegisterTest("DetectFastPatternTest170", DetectFastPatternTest170, 1); - UtRegisterTest("DetectFastPatternTest171", DetectFastPatternTest171, 1); - UtRegisterTest("DetectFastPatternTest172", DetectFastPatternTest172, 1); - UtRegisterTest("DetectFastPatternTest173", DetectFastPatternTest173, 1); - UtRegisterTest("DetectFastPatternTest174", DetectFastPatternTest174, 1); - /* http_client_body fast_pattern tests ^ */ - /* content fast_pattern tests v */ - UtRegisterTest("DetectFastPatternTest175", DetectFastPatternTest175, 1); - UtRegisterTest("DetectFastPatternTest176", DetectFastPatternTest176, 1); - UtRegisterTest("DetectFastPatternTest177", DetectFastPatternTest177, 1); - UtRegisterTest("DetectFastPatternTest178", DetectFastPatternTest178, 1); + 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_header; " + "content:!two; fast_pattern:3,4; http_header; " + "content:three; http_header; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HHDMATCH]->prev->ctx; + if (ud->flags & DETECT_CONTENT_FAST_PATTERN && + ud->flags & DETECT_CONTENT_NEGATED && + !(ud->flags & DETECT_CONTENT_FAST_PATTERN_ONLY) && + ud->flags & 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 DetectFastPatternTest180(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_header; " + "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_HHDMATCH]; + 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 DetectFastPatternTest181(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:3,4; http_header; " + "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_HHDMATCH]; + 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 DetectFastPatternTest182(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_header; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + + result = 0; + sm = de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HHDMATCH]; + DetectContentData *ud = sm->ctx; + if (sm != NULL) { + if (ud->flags & DETECT_CONTENT_FAST_PATTERN && + ud->flags & DETECT_CONTENT_FAST_PATTERN_ONLY && + !(ud->flags & 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 DetectFastPatternTest183(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:3,4; http_header; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + + result = 0; + sm = de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HHDMATCH]; + DetectContentData *ud = sm->ctx; + if (sm != NULL) { + if (ud->flags & DETECT_CONTENT_FAST_PATTERN && + !(ud->flags & DETECT_CONTENT_FAST_PATTERN_ONLY) && + ud->flags & 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 DetectFastPatternTest184(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_header; content:two; fast_pattern:only; http_header; distance:10; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest185(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_header; content:two; distance:10; fast_pattern:only; http_header; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest186(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_header; content:two; fast_pattern:only; http_header; within:10; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest187(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_header; content:two; within:10; fast_pattern:only; http_header; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest188(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_header; content:two; fast_pattern:only; http_header; offset:10; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest189(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_header; content:two; offset:10; fast_pattern:only; http_header; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest190(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_header; content:two; fast_pattern:only; http_header; depth:10; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest191(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_header; content:two; depth:10; fast_pattern:only; http_header; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest192(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_header; content:!two; fast_pattern:only; http_header; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest193(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_header; content:two; http_header; distance:30; content:two; fast_pattern:only; http_header; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HHDMATCH]->ctx; + if (ud->flags & DETECT_CONTENT_FAST_PATTERN && + ud->flags & DETECT_CONTENT_FAST_PATTERN_ONLY && + !(ud->flags & 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 DetectFastPatternTest194(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_header; content:two; http_header; within:30; content:two; fast_pattern:only; http_header; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HHDMATCH]->ctx; + if (ud->flags & DETECT_CONTENT_FAST_PATTERN && + ud->flags & DETECT_CONTENT_FAST_PATTERN_ONLY && + !(ud->flags & 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 DetectFastPatternTest195(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_header; content:two; http_header; offset:30; content:two; fast_pattern:only; http_header; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HHDMATCH]->ctx; + if (ud->flags & DETECT_CONTENT_FAST_PATTERN && + ud->flags & DETECT_CONTENT_FAST_PATTERN_ONLY && + !(ud->flags & 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 DetectFastPatternTest196(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_header; content:two; http_header; depth:30; content:two; fast_pattern:only; http_header; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HHDMATCH]->ctx; + if (ud->flags & DETECT_CONTENT_FAST_PATTERN && + ud->flags & DETECT_CONTENT_FAST_PATTERN_ONLY && + !(ud->flags & 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 DetectFastPatternTest197(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_header; content:two; http_header; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HHDMATCH]->prev->ctx; + if (ud->flags & DETECT_CONTENT_FAST_PATTERN && + ud->flags & DETECT_CONTENT_NEGATED && + !(ud->flags & DETECT_CONTENT_FAST_PATTERN_ONLY) && + !(ud->flags & 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 DetectFastPatternTest198(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_header; content:!one; fast_pattern; http_header; distance:20; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest199(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_header; content:!one; fast_pattern; http_header; within:20; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest200(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_header; content:!one; fast_pattern; http_header; offset:20; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest201(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_header; content:!one; fast_pattern; http_header; depth:20; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest202(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_header; content:two; fast_pattern:3,4; http_header; content:three; http_header; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HHDMATCH]->prev->ctx; + if (ud->flags & DETECT_CONTENT_FAST_PATTERN && + !(ud->flags & DETECT_CONTENT_FAST_PATTERN_ONLY) && + ud->flags & 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 DetectFastPatternTest203(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_header; content:two; fast_pattern:3,4; http_header; content:three; http_header; distance:30; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HHDMATCH]->prev->ctx; + if (ud->flags & DETECT_CONTENT_FAST_PATTERN && + !(ud->flags & DETECT_CONTENT_FAST_PATTERN_ONLY) && + ud->flags & 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 DetectFastPatternTest204(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_header; content:two; fast_pattern:3,4; http_header; content:three; http_header; within:30; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HHDMATCH]->prev->ctx; + if (ud->flags & DETECT_CONTENT_FAST_PATTERN && + !(ud->flags & DETECT_CONTENT_FAST_PATTERN_ONLY) && + ud->flags & 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 DetectFastPatternTest205(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_header; content:two; fast_pattern:3,4; http_header; content:three; http_header; offset:30; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HHDMATCH]->prev->ctx; + if (ud->flags & DETECT_CONTENT_FAST_PATTERN && + !(ud->flags & DETECT_CONTENT_FAST_PATTERN_ONLY) && + ud->flags & 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 DetectFastPatternTest206(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_header; content:two; fast_pattern:3,4; http_header; content:three; http_header; depth:30; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HHDMATCH]->prev->ctx; + if (ud->flags & DETECT_CONTENT_FAST_PATTERN && + !(ud->flags & DETECT_CONTENT_FAST_PATTERN_ONLY) && + ud->flags & 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 DetectFastPatternTest207(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_header; content:two; http_header; distance:10; content:three; fast_pattern:3,4; http_header; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HHDMATCH]->ctx; + if (ud->flags & DETECT_CONTENT_FAST_PATTERN && + !(ud->flags & DETECT_CONTENT_FAST_PATTERN_ONLY) && + ud->flags & 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 DetectFastPatternTest208(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_header; content:two; http_header; within:10; content:three; fast_pattern:3,4; http_header; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HHDMATCH]->ctx; + if (ud->flags & DETECT_CONTENT_FAST_PATTERN && + !(ud->flags & DETECT_CONTENT_FAST_PATTERN_ONLY) && + ud->flags & 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 DetectFastPatternTest209(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_header; content:two; http_header; offset:10; content:three; fast_pattern:3,4; http_header; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HHDMATCH]->ctx; + if (ud->flags & DETECT_CONTENT_FAST_PATTERN && + !(ud->flags & DETECT_CONTENT_FAST_PATTERN_ONLY) && + ud->flags & 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 DetectFastPatternTest210(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_header; content:two; http_header; depth:10; content:three; fast_pattern:3,4; http_header; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HHDMATCH]->ctx; + if (ud->flags & DETECT_CONTENT_FAST_PATTERN && + !(ud->flags & DETECT_CONTENT_FAST_PATTERN_ONLY) && + ud->flags & 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 DetectFastPatternTest211(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_header; content:two; fast_pattern:65977,4; http_header; content:three; http_header; distance:10; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest212(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_header; content:two; fast_pattern:3,65977; http_header; content:three; distance:10; http_header; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest213(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_header; content:two; fast_pattern:65534,4; http_header; content:three; http_header; distance:10; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest214(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_header; content:!two; fast_pattern:3,4; http_header; content:three; http_header; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HHDMATCH]->prev->ctx; + if (ud->flags & DETECT_CONTENT_FAST_PATTERN && + ud->flags & DETECT_CONTENT_NEGATED && + !(ud->flags & DETECT_CONTENT_FAST_PATTERN_ONLY) && + ud->flags & 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 DetectFastPatternTest215(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_header; content:!two; fast_pattern:3,4; http_header; distance:10; content:three; http_header; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest216(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_header; content:!two; fast_pattern:3,4; http_header; within:10; content:three; http_header; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest217(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_header; content:!two; fast_pattern:3,4; http_header; offset:10; content:three; http_header; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest218(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_header; content:!two; fast_pattern:3,4; http_header; depth:10; content:three; http_header; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest219(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_header; content:!two; fast_pattern:3,4; http_header; content:three; http_header; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HHDMATCH]->prev->ctx; + if (ud->flags & DETECT_CONTENT_FAST_PATTERN && + ud->flags & DETECT_CONTENT_NEGATED && + !(ud->flags & DETECT_CONTENT_FAST_PATTERN_ONLY) && + ud->flags & 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) +{ + +#ifdef UNITTESTS + UtRegisterTest("DetectFastPatternTest01", DetectFastPatternTest01, 1); + UtRegisterTest("DetectFastPatternTest02", DetectFastPatternTest02, 1); + UtRegisterTest("DetectFastPatternTest03", DetectFastPatternTest03, 1); + UtRegisterTest("DetectFastPatternTest04", DetectFastPatternTest04, 1); + UtRegisterTest("DetectFastPatternTest05", DetectFastPatternTest05, 1); + UtRegisterTest("DetectFastPatternTest06", DetectFastPatternTest06, 1); + UtRegisterTest("DetectFastPatternTest07", DetectFastPatternTest07, 1); + UtRegisterTest("DetectFastPatternTest08", DetectFastPatternTest08, 1); + UtRegisterTest("DetectFastPatternTest09", DetectFastPatternTest09, 1); + UtRegisterTest("DetectFastPatternTest10", DetectFastPatternTest10, 1); + UtRegisterTest("DetectFastPatternTest11", DetectFastPatternTest11, 1); + UtRegisterTest("DetectFastPatternTest12", DetectFastPatternTest12, 1); + UtRegisterTest("DetectFastPatternTest13", DetectFastPatternTest13, 1); + UtRegisterTest("DetectFastPatternTest14", DetectFastPatternTest14, 1); + UtRegisterTest("DetectFastPatternTest15", DetectFastPatternTest15, 1); + UtRegisterTest("DetectFastPatternTest16", DetectFastPatternTest16, 1); + UtRegisterTest("DetectFastPatternTest17", DetectFastPatternTest17, 1); + UtRegisterTest("DetectFastPatternTest18", DetectFastPatternTest18, 1); + UtRegisterTest("DetectFastPatternTest19", DetectFastPatternTest19, 1); + UtRegisterTest("DetectFastPatternTest20", DetectFastPatternTest20, 1); + UtRegisterTest("DetectFastPatternTest21", DetectFastPatternTest21, 1); + UtRegisterTest("DetectFastPatternTest22", DetectFastPatternTest22, 1); + UtRegisterTest("DetectFastPatternTest23", DetectFastPatternTest23, 1); + UtRegisterTest("DetectFastPatternTest24", DetectFastPatternTest24, 1); + UtRegisterTest("DetectFastPatternTest25", DetectFastPatternTest25, 1); + UtRegisterTest("DetectFastPatternTest26", DetectFastPatternTest26, 1); + UtRegisterTest("DetectFastPatternTest27", DetectFastPatternTest27, 1); + UtRegisterTest("DetectFastPatternTest28", DetectFastPatternTest28, 1); + UtRegisterTest("DetectFastPatternTest29", DetectFastPatternTest29, 1); + UtRegisterTest("DetectFastPatternTest30", DetectFastPatternTest30, 1); + UtRegisterTest("DetectFastPatternTest31", DetectFastPatternTest31, 1); + UtRegisterTest("DetectFastPatternTest32", DetectFastPatternTest32, 1); + UtRegisterTest("DetectFastPatternTest33", DetectFastPatternTest33, 1); + UtRegisterTest("DetectFastPatternTest34", DetectFastPatternTest34, 1); + UtRegisterTest("DetectFastPatternTest35", DetectFastPatternTest35, 1); + UtRegisterTest("DetectFastPatternTest36", DetectFastPatternTest36, 1); + UtRegisterTest("DetectFastPatternTest37", DetectFastPatternTest37, 1); + UtRegisterTest("DetectFastPatternTest38", DetectFastPatternTest38, 1); + UtRegisterTest("DetectFastPatternTest39", DetectFastPatternTest39, 1); + UtRegisterTest("DetectFastPatternTest40", DetectFastPatternTest40, 1); + UtRegisterTest("DetectFastPatternTest41", DetectFastPatternTest41, 1); + UtRegisterTest("DetectFastPatternTest42", DetectFastPatternTest42, 1); + UtRegisterTest("DetectFastPatternTest43", DetectFastPatternTest43, 1); + UtRegisterTest("DetectFastPatternTest44", DetectFastPatternTest44, 1); + UtRegisterTest("DetectFastPatternTest45", DetectFastPatternTest45, 1); + UtRegisterTest("DetectFastPatternTest46", DetectFastPatternTest46, 1); + UtRegisterTest("DetectFastPatternTest47", DetectFastPatternTest47, 1); + UtRegisterTest("DetectFastPatternTest48", DetectFastPatternTest48, 1); + UtRegisterTest("DetectFastPatternTest49", DetectFastPatternTest49, 1); + UtRegisterTest("DetectFastPatternTest50", DetectFastPatternTest50, 1); + UtRegisterTest("DetectFastPatternTest51", DetectFastPatternTest51, 1); + UtRegisterTest("DetectFastPatternTest52", DetectFastPatternTest52, 1); + UtRegisterTest("DetectFastPatternTest53", DetectFastPatternTest53, 1); + /* content fast_pattern tests ^ */ + /* uricontent fast_pattern tests v */ + UtRegisterTest("DetectFastPatternTest54", DetectFastPatternTest54, 1); + UtRegisterTest("DetectFastPatternTest55", DetectFastPatternTest55, 1); + UtRegisterTest("DetectFastPatternTest56", DetectFastPatternTest56, 1); + UtRegisterTest("DetectFastPatternTest57", DetectFastPatternTest57, 1); + UtRegisterTest("DetectFastPatternTest58", DetectFastPatternTest58, 1); + UtRegisterTest("DetectFastPatternTest59", DetectFastPatternTest59, 1); + UtRegisterTest("DetectFastPatternTest60", DetectFastPatternTest60, 1); + UtRegisterTest("DetectFastPatternTest61", DetectFastPatternTest61, 1); + UtRegisterTest("DetectFastPatternTest62", DetectFastPatternTest62, 1); + UtRegisterTest("DetectFastPatternTest63", DetectFastPatternTest63, 1); + UtRegisterTest("DetectFastPatternTest64", DetectFastPatternTest64, 1); + UtRegisterTest("DetectFastPatternTest65", DetectFastPatternTest65, 1); + UtRegisterTest("DetectFastPatternTest66", DetectFastPatternTest66, 1); + UtRegisterTest("DetectFastPatternTest67", DetectFastPatternTest67, 1); + UtRegisterTest("DetectFastPatternTest68", DetectFastPatternTest68, 1); + UtRegisterTest("DetectFastPatternTest69", DetectFastPatternTest69, 1); + UtRegisterTest("DetectFastPatternTest70", DetectFastPatternTest70, 1); + UtRegisterTest("DetectFastPatternTest71", DetectFastPatternTest71, 1); + UtRegisterTest("DetectFastPatternTest72", DetectFastPatternTest72, 1); + UtRegisterTest("DetectFastPatternTest73", DetectFastPatternTest73, 1); + UtRegisterTest("DetectFastPatternTest74", DetectFastPatternTest74, 1); + UtRegisterTest("DetectFastPatternTest75", DetectFastPatternTest75, 1); + UtRegisterTest("DetectFastPatternTest76", DetectFastPatternTest76, 1); + UtRegisterTest("DetectFastPatternTest77", DetectFastPatternTest77, 1); + UtRegisterTest("DetectFastPatternTest78", DetectFastPatternTest78, 1); + UtRegisterTest("DetectFastPatternTest79", DetectFastPatternTest79, 1); + UtRegisterTest("DetectFastPatternTest80", DetectFastPatternTest80, 1); + UtRegisterTest("DetectFastPatternTest81", DetectFastPatternTest81, 1); + UtRegisterTest("DetectFastPatternTest82", DetectFastPatternTest82, 1); + UtRegisterTest("DetectFastPatternTest83", DetectFastPatternTest83, 1); + UtRegisterTest("DetectFastPatternTest84", DetectFastPatternTest84, 1); + UtRegisterTest("DetectFastPatternTest85", DetectFastPatternTest85, 1); + UtRegisterTest("DetectFastPatternTest86", DetectFastPatternTest86, 1); + UtRegisterTest("DetectFastPatternTest87", DetectFastPatternTest87, 1); + UtRegisterTest("DetectFastPatternTest88", DetectFastPatternTest88, 1); + UtRegisterTest("DetectFastPatternTest89", DetectFastPatternTest89, 1); + UtRegisterTest("DetectFastPatternTest90", DetectFastPatternTest90, 1); + UtRegisterTest("DetectFastPatternTest91", DetectFastPatternTest91, 1); + UtRegisterTest("DetectFastPatternTest92", DetectFastPatternTest92, 1); + /* uricontent fast_pattern tests ^ */ + /* http_uri fast_pattern tests v */ + UtRegisterTest("DetectFastPatternTest93", DetectFastPatternTest93, 1); + UtRegisterTest("DetectFastPatternTest94", DetectFastPatternTest94, 1); + UtRegisterTest("DetectFastPatternTest95", DetectFastPatternTest95, 1); + UtRegisterTest("DetectFastPatternTest96", DetectFastPatternTest96, 1); + UtRegisterTest("DetectFastPatternTest97", DetectFastPatternTest97, 1); + UtRegisterTest("DetectFastPatternTest98", DetectFastPatternTest98, 1); + UtRegisterTest("DetectFastPatternTest99", DetectFastPatternTest99, 1); + UtRegisterTest("DetectFastPatternTest100", DetectFastPatternTest100, 1); + UtRegisterTest("DetectFastPatternTest101", DetectFastPatternTest101, 1); + UtRegisterTest("DetectFastPatternTest102", DetectFastPatternTest102, 1); + UtRegisterTest("DetectFastPatternTest103", DetectFastPatternTest103, 1); + UtRegisterTest("DetectFastPatternTest104", DetectFastPatternTest104, 1); + UtRegisterTest("DetectFastPatternTest105", DetectFastPatternTest105, 1); + UtRegisterTest("DetectFastPatternTest106", DetectFastPatternTest106, 1); + UtRegisterTest("DetectFastPatternTest107", DetectFastPatternTest107, 1); + UtRegisterTest("DetectFastPatternTest108", DetectFastPatternTest108, 1); + UtRegisterTest("DetectFastPatternTest109", DetectFastPatternTest109, 1); + UtRegisterTest("DetectFastPatternTest110", DetectFastPatternTest110, 1); + UtRegisterTest("DetectFastPatternTest111", DetectFastPatternTest111, 1); + UtRegisterTest("DetectFastPatternTest112", DetectFastPatternTest112, 1); + UtRegisterTest("DetectFastPatternTest113", DetectFastPatternTest113, 1); + UtRegisterTest("DetectFastPatternTest114", DetectFastPatternTest114, 1); + UtRegisterTest("DetectFastPatternTest115", DetectFastPatternTest115, 1); + UtRegisterTest("DetectFastPatternTest116", DetectFastPatternTest116, 1); + UtRegisterTest("DetectFastPatternTest117", DetectFastPatternTest117, 1); + UtRegisterTest("DetectFastPatternTest118", DetectFastPatternTest118, 1); + UtRegisterTest("DetectFastPatternTest119", DetectFastPatternTest119, 1); + UtRegisterTest("DetectFastPatternTest120", DetectFastPatternTest120, 1); + UtRegisterTest("DetectFastPatternTest121", DetectFastPatternTest121, 1); + UtRegisterTest("DetectFastPatternTest122", DetectFastPatternTest122, 1); + UtRegisterTest("DetectFastPatternTest123", DetectFastPatternTest123, 1); + UtRegisterTest("DetectFastPatternTest124", DetectFastPatternTest124, 1); + UtRegisterTest("DetectFastPatternTest125", DetectFastPatternTest125, 1); + UtRegisterTest("DetectFastPatternTest126", DetectFastPatternTest126, 1); + UtRegisterTest("DetectFastPatternTest127", DetectFastPatternTest127, 1); + UtRegisterTest("DetectFastPatternTest128", DetectFastPatternTest128, 1); + UtRegisterTest("DetectFastPatternTest129", DetectFastPatternTest129, 1); + UtRegisterTest("DetectFastPatternTest130", DetectFastPatternTest130, 1); + UtRegisterTest("DetectFastPatternTest131", DetectFastPatternTest131, 1); + UtRegisterTest("DetectFastPatternTest132", DetectFastPatternTest132, 1); + UtRegisterTest("DetectFastPatternTest133", DetectFastPatternTest133, 1); + /* http_uri fast_pattern tests ^ */ + /* http_client_body fast_pattern tests v */ + UtRegisterTest("DetectFastPatternTest134", DetectFastPatternTest134, 1); + UtRegisterTest("DetectFastPatternTest135", DetectFastPatternTest135, 1); + UtRegisterTest("DetectFastPatternTest136", DetectFastPatternTest136, 1); + UtRegisterTest("DetectFastPatternTest137", DetectFastPatternTest137, 1); + UtRegisterTest("DetectFastPatternTest138", DetectFastPatternTest138, 1); + UtRegisterTest("DetectFastPatternTest139", DetectFastPatternTest139, 1); + UtRegisterTest("DetectFastPatternTest140", DetectFastPatternTest140, 1); + UtRegisterTest("DetectFastPatternTest141", DetectFastPatternTest141, 1); + UtRegisterTest("DetectFastPatternTest142", DetectFastPatternTest142, 1); + UtRegisterTest("DetectFastPatternTest143", DetectFastPatternTest143, 1); + UtRegisterTest("DetectFastPatternTest144", DetectFastPatternTest144, 1); + UtRegisterTest("DetectFastPatternTest145", DetectFastPatternTest145, 1); + UtRegisterTest("DetectFastPatternTest146", DetectFastPatternTest146, 1); + UtRegisterTest("DetectFastPatternTest147", DetectFastPatternTest147, 1); + UtRegisterTest("DetectFastPatternTest148", DetectFastPatternTest148, 1); + UtRegisterTest("DetectFastPatternTest149", DetectFastPatternTest149, 1); + UtRegisterTest("DetectFastPatternTest150", DetectFastPatternTest150, 1); + UtRegisterTest("DetectFastPatternTest151", DetectFastPatternTest151, 1); + UtRegisterTest("DetectFastPatternTest152", DetectFastPatternTest152, 1); + UtRegisterTest("DetectFastPatternTest153", DetectFastPatternTest153, 1); + UtRegisterTest("DetectFastPatternTest154", DetectFastPatternTest154, 1); + UtRegisterTest("DetectFastPatternTest155", DetectFastPatternTest155, 1); + UtRegisterTest("DetectFastPatternTest156", DetectFastPatternTest156, 1); + UtRegisterTest("DetectFastPatternTest157", DetectFastPatternTest157, 1); + UtRegisterTest("DetectFastPatternTest158", DetectFastPatternTest158, 1); + UtRegisterTest("DetectFastPatternTest159", DetectFastPatternTest159, 1); + UtRegisterTest("DetectFastPatternTest160", DetectFastPatternTest160, 1); + UtRegisterTest("DetectFastPatternTest161", DetectFastPatternTest161, 1); + UtRegisterTest("DetectFastPatternTest162", DetectFastPatternTest162, 1); + UtRegisterTest("DetectFastPatternTest163", DetectFastPatternTest163, 1); + UtRegisterTest("DetectFastPatternTest164", DetectFastPatternTest164, 1); + UtRegisterTest("DetectFastPatternTest165", DetectFastPatternTest165, 1); + UtRegisterTest("DetectFastPatternTest166", DetectFastPatternTest166, 1); + UtRegisterTest("DetectFastPatternTest167", DetectFastPatternTest167, 1); + UtRegisterTest("DetectFastPatternTest168", DetectFastPatternTest168, 1); + UtRegisterTest("DetectFastPatternTest169", DetectFastPatternTest169, 1); + UtRegisterTest("DetectFastPatternTest170", DetectFastPatternTest170, 1); + UtRegisterTest("DetectFastPatternTest171", DetectFastPatternTest171, 1); + UtRegisterTest("DetectFastPatternTest172", DetectFastPatternTest172, 1); + UtRegisterTest("DetectFastPatternTest173", DetectFastPatternTest173, 1); + UtRegisterTest("DetectFastPatternTest174", DetectFastPatternTest174, 1); + /* http_client_body fast_pattern tests ^ */ + /* content fast_pattern tests v */ + UtRegisterTest("DetectFastPatternTest175", DetectFastPatternTest175, 1); + UtRegisterTest("DetectFastPatternTest176", DetectFastPatternTest176, 1); + UtRegisterTest("DetectFastPatternTest177", DetectFastPatternTest177, 1); + UtRegisterTest("DetectFastPatternTest178", DetectFastPatternTest178, 1); + /* content fast_pattern tests ^ */ + /* http_header fast_pattern tests v */ + UtRegisterTest("DetectFastPatternTest179", DetectFastPatternTest179, 1); + UtRegisterTest("DetectFastPatternTest180", DetectFastPatternTest180, 1); + UtRegisterTest("DetectFastPatternTest181", DetectFastPatternTest181, 1); + UtRegisterTest("DetectFastPatternTest182", DetectFastPatternTest182, 1); + UtRegisterTest("DetectFastPatternTest183", DetectFastPatternTest183, 1); + UtRegisterTest("DetectFastPatternTest184", DetectFastPatternTest184, 1); + UtRegisterTest("DetectFastPatternTest185", DetectFastPatternTest185, 1); + UtRegisterTest("DetectFastPatternTest186", DetectFastPatternTest186, 1); + UtRegisterTest("DetectFastPatternTest187", DetectFastPatternTest187, 1); + UtRegisterTest("DetectFastPatternTest188", DetectFastPatternTest188, 1); + UtRegisterTest("DetectFastPatternTest189", DetectFastPatternTest189, 1); + UtRegisterTest("DetectFastPatternTest190", DetectFastPatternTest190, 1); + UtRegisterTest("DetectFastPatternTest191", DetectFastPatternTest191, 1); + UtRegisterTest("DetectFastPatternTest192", DetectFastPatternTest192, 1); + UtRegisterTest("DetectFastPatternTest193", DetectFastPatternTest193, 1); + UtRegisterTest("DetectFastPatternTest194", DetectFastPatternTest194, 1); + UtRegisterTest("DetectFastPatternTest195", DetectFastPatternTest195, 1); + UtRegisterTest("DetectFastPatternTest196", DetectFastPatternTest196, 1); + UtRegisterTest("DetectFastPatternTest197", DetectFastPatternTest197, 1); + UtRegisterTest("DetectFastPatternTest198", DetectFastPatternTest198, 1); + UtRegisterTest("DetectFastPatternTest199", DetectFastPatternTest199, 1); + UtRegisterTest("DetectFastPatternTest200", DetectFastPatternTest200, 1); + UtRegisterTest("DetectFastPatternTest201", DetectFastPatternTest201, 1); + UtRegisterTest("DetectFastPatternTest202", DetectFastPatternTest202, 1); + UtRegisterTest("DetectFastPatternTest203", DetectFastPatternTest203, 1); + UtRegisterTest("DetectFastPatternTest204", DetectFastPatternTest204, 1); + UtRegisterTest("DetectFastPatternTest205", DetectFastPatternTest205, 1); + UtRegisterTest("DetectFastPatternTest206", DetectFastPatternTest206, 1); + UtRegisterTest("DetectFastPatternTest207", DetectFastPatternTest207, 1); + UtRegisterTest("DetectFastPatternTest208", DetectFastPatternTest208, 1); + UtRegisterTest("DetectFastPatternTest209", DetectFastPatternTest209, 1); + UtRegisterTest("DetectFastPatternTest210", DetectFastPatternTest210, 1); + UtRegisterTest("DetectFastPatternTest211", DetectFastPatternTest211, 1); + UtRegisterTest("DetectFastPatternTest212", DetectFastPatternTest212, 1); + UtRegisterTest("DetectFastPatternTest213", DetectFastPatternTest213, 1); + UtRegisterTest("DetectFastPatternTest214", DetectFastPatternTest214, 1); + UtRegisterTest("DetectFastPatternTest215", DetectFastPatternTest215, 1); + UtRegisterTest("DetectFastPatternTest216", DetectFastPatternTest216, 1); + UtRegisterTest("DetectFastPatternTest217", DetectFastPatternTest217, 1); + UtRegisterTest("DetectFastPatternTest218", DetectFastPatternTest218, 1); + UtRegisterTest("DetectFastPatternTest219", DetectFastPatternTest219, 1); #endif return; diff --git a/src/detect-http-client-body.c b/src/detect-http-client-body.c index d0a5975add..ceca954e03 100644 --- a/src/detect-http-client-body.c +++ b/src/detect-http-client-body.c @@ -188,20 +188,11 @@ int DetectHttpClientBodyMatch(ThreadVars *t, DetectEngineThreadCtx *det_ctx, */ int DetectHttpClientBodySetup(DetectEngineCtx *de_ctx, Signature *s, char *arg) { - /* http_client_body_data (hcbd) */ - DetectContentData *hcbd = NULL; - SigMatch *nm = NULL; + DetectContentData *cd = NULL; SigMatch *sm = NULL; if (arg != NULL && strcmp(arg, "") != 0) { - SCLogError(SC_ERR_INVALID_ARGUMENT, "http_client_body supplied with no " - "args"); - return -1; - } - - if (s->sm_lists_tail[DETECT_SM_LIST_PMATCH] == NULL) { - SCLogError(SC_ERR_INVALID_SIGNATURE, "http_client_body found inside the " - "rule, without any preceding content keywords"); + SCLogError(SC_ERR_INVALID_ARGUMENT, "http_client_body supplied with args"); return -1; } @@ -216,19 +207,21 @@ int DetectHttpClientBodySetup(DetectEngineCtx *de_ctx, Signature *s, char *arg) return -1; } + cd = (DetectContentData *)sm->ctx; + /* http_client_body should not be used with the rawbytes rule */ - if ( ((DetectContentData *)sm->ctx)->flags & DETECT_CONTENT_RAWBYTES) { + if (cd->flags & DETECT_CONTENT_RAWBYTES) { SCLogError(SC_ERR_INVALID_SIGNATURE, "http_client_body rule can not " "be used with the rawbytes rule keyword"); return -1; } if (s->alproto != ALPROTO_UNKNOWN && s->alproto != ALPROTO_HTTP) { - SCLogError(SC_ERR_CONFLICTING_RULE_KEYWORDS, "rule contains conflicting keywords"); + SCLogError(SC_ERR_CONFLICTING_RULE_KEYWORDS, "rule contains a non http " + "alproto set"); goto error; } - DetectContentData *cd = (DetectContentData *)sm->ctx; if (cd->flags & DETECT_CONTENT_WITHIN || cd->flags & DETECT_CONTENT_DISTANCE) { SigMatch *pm = SigMatchGetLastSMFromLists(s, 4, DETECT_CONTENT, sm->prev, @@ -272,11 +265,11 @@ int DetectHttpClientBodySetup(DetectEngineCtx *de_ctx, Signature *s, char *arg) return 0; error: - if (hcbd != NULL) - DetectHttpClientBodyFree(hcbd); + if (cd != NULL) + DetectHttpClientBodyFree(cd); - if(nm != NULL) - SCFree(nm); + if (sm != NULL) + SCFree(sm); return -1; } diff --git a/src/detect-http-header.c b/src/detect-http-header.c index cba40e2319..c9a0529501 100644 --- a/src/detect-http-header.c +++ b/src/detect-http-header.c @@ -21,8 +21,6 @@ * \author Pablo Rincon * * Implements support for http_header keyword. - * - * \todo this is actually the raw match. */ #include "suricata-common.h" @@ -35,6 +33,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" @@ -75,23 +74,6 @@ void DetectHttpHeaderRegister(void) sigmatch_table[DETECT_AL_HTTP_HEADER].flags |= SIGMATCH_PAYLOAD ; } -/** - * \brief Registers the keyword handlers for the "http_raw_header" keyword. - */ -void DetectHttpRawHeaderRegister(void) -{ - sigmatch_table[DETECT_AL_HTTP_RAW_HEADER].name = "http_raw_header"; - sigmatch_table[DETECT_AL_HTTP_RAW_HEADER].Match = NULL; - sigmatch_table[DETECT_AL_HTTP_RAW_HEADER].AppLayerMatch = DetectHttpHeaderMatch; - sigmatch_table[DETECT_AL_HTTP_RAW_HEADER].alproto = ALPROTO_HTTP; - sigmatch_table[DETECT_AL_HTTP_RAW_HEADER].Setup = DetectHttpHeaderSetup; - sigmatch_table[DETECT_AL_HTTP_RAW_HEADER].Free = DetectHttpHeaderFree; - //sigmatch_table[DETECT_AL_HTTP_RAW_HEADER].RegisterTests = DetectHttpHeaderRegisterTests; - sigmatch_table[DETECT_AL_HTTP_RAW_HEADER].RegisterTests = NULL; - - sigmatch_table[DETECT_AL_HTTP_RAW_HEADER].flags |= SIGMATCH_PAYLOAD ; -} - /** * \brief App layer match function for the "http_header" keyword. * @@ -194,23 +176,16 @@ void DetectHttpHeaderFree(void *ptr) */ int DetectHttpHeaderSetup(DetectEngineCtx *de_ctx, Signature *s, char *arg) { - /* http_header_data (hhd) */ - DetectContentData *hhd = NULL; - SigMatch *nm = NULL; + DetectContentData *cd = NULL; SigMatch *sm = NULL; if (arg != NULL && strcmp(arg, "") != 0) { - SCLogError(SC_ERR_INVALID_ARGUMENT, "http_header supplied with no args"); + SCLogError(SC_ERR_INVALID_ARGUMENT, "http_header supplied with args"); return -1; } - if (s->sm_lists_tail[DETECT_SM_LIST_PMATCH] == NULL) { - SCLogError(SC_ERR_INVALID_SIGNATURE, "http_header found inside the " - "rule, without any preceding content keywords"); - return -1; - } - - sm = DetectContentGetLastPattern(s->sm_lists_tail[DETECT_SM_LIST_PMATCH]); + sm = SigMatchGetLastSMFromLists(s, 2, + DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_PMATCH]); /* if still we are unable to find any content previous keywords, it is an * invalid rule */ if (sm == NULL) { @@ -221,59 +196,57 @@ int DetectHttpHeaderSetup(DetectEngineCtx *de_ctx, Signature *s, char *arg) return -1; } - if (((DetectContentData *)sm->ctx)->flags & DETECT_CONTENT_FAST_PATTERN) { - SCLogWarning(SC_WARN_COMPATIBILITY, - "http_header cannot be used with \"fast_pattern\" currently." - "Unsetting fast_pattern on this modifier. Signature ==> %s", s->sig_str); - ((DetectContentData *)sm->ctx)->flags &= ~DETECT_CONTENT_FAST_PATTERN; - } + /* cast for further use */ + cd = (DetectContentData *)sm->ctx; /* http_header should not be used with the rawbytes rule */ - if (((DetectContentData *)sm->ctx)->flags & DETECT_CONTENT_RAWBYTES) { + if (cd->flags & DETECT_CONTENT_RAWBYTES) { SCLogError(SC_ERR_INVALID_SIGNATURE, "http_header rule can not " "be used with the rawbytes rule keyword"); return -1; } if (s->alproto != ALPROTO_UNKNOWN && s->alproto != ALPROTO_HTTP) { - SCLogError(SC_ERR_CONFLICTING_RULE_KEYWORDS, "rule contains conflicting keywords"); + SCLogError(SC_ERR_CONFLICTING_RULE_KEYWORDS, "rule contains a non http " + "alproto set"); goto error; } - /* setup the HttpHeaderData's data from content data structure's data */ - hhd = SCMalloc(sizeof(DetectContentData)); - if (hhd == NULL) { - SCLogError(SC_ERR_MEM_ALLOC, "Error allocating memory"); - exit(EXIT_FAILURE); - } - memset(hhd, 0, sizeof(DetectContentData)); - - /* transfer the pattern details from the content struct to the clientbody struct */ - DetectContentData *cd = (DetectContentData *)sm->ctx; - hhd->content = cd->content; - hhd->content_len = cd->content_len; - hhd->flags |= cd->flags & DETECT_CONTENT_NOCASE ? DETECT_CONTENT_NOCASE : 0; - hhd->flags |= cd->flags & DETECT_CONTENT_NEGATED ? DETECT_CONTENT_NEGATED : 0; - //hhd->id = ((DetectContentData *)sm->ctx)->id; - hhd->id = DetectPatternGetId(de_ctx->mpm_pattern_id_store, hhd, DETECT_AL_HTTP_HEADER); - - nm = SigMatchAlloc(); - if (nm == NULL) { - SCLogError(SC_ERR_MEM_ALLOC, "Error allocating memory"); - goto error; - } - nm->type = DETECT_AL_HTTP_HEADER; - nm->ctx = (void *)hhd; + if (cd->flags & DETECT_CONTENT_WITHIN || cd->flags & DETECT_CONTENT_DISTANCE) { + SigMatch *pm = SigMatchGetLastSMFromLists(s, 4, + DETECT_CONTENT, sm->prev, + DETECT_PCRE, sm->prev); + /* pm 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; + } - /* pull the previous content from the pmatch list, append - * the new match to the match list */ - SigMatchReplaceContent(s, sm, nm); + /* please note. reassigning pm */ + pm = SigMatchGetLastSMFromLists(s, 2, + DETECT_AL_HTTP_HEADER, + s->sm_lists_tail[DETECT_SM_LIST_HHDMATCH]); + if (pm == NULL) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "http_header seen with a " + "distance or within without a previous http_header " + "content. Invalidating signature."); + goto error; + } + 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_HEADER); + sm->type = DETECT_AL_HTTP_HEADER; - /* free the old content sigmatch, the content pattern memory - * is taken over by the new sigmatch */ - BoyerMooreCtxDeInit(((DetectContentData *)sm->ctx)->bm_ctx); - SCFree(sm->ctx); - SCFree(sm); + /* transfer the sm from the pmatch list to hhdmatch list */ + SigMatchTransferSigMatchAcrossLists(sm, + &s->sm_lists[DETECT_SM_LIST_PMATCH], + &s->sm_lists_tail[DETECT_SM_LIST_PMATCH], + &s->sm_lists[DETECT_SM_LIST_HHDMATCH], + &s->sm_lists_tail[DETECT_SM_LIST_HHDMATCH]); /* flag the signature to indicate that we scan the app layer data */ s->flags |= SIG_FLAG_APPLAYER; @@ -282,9 +255,10 @@ int DetectHttpHeaderSetup(DetectEngineCtx *de_ctx, Signature *s, char *arg) return 0; error: - if (hhd != NULL) - DetectHttpHeaderFree(hhd); - if(nm != NULL) + if (cd != NULL) + DetectHttpHeaderFree(cd); + + if(sm != NULL) SCFree(sm); return -1; @@ -321,11 +295,12 @@ static int DetectHttpHeaderTest01(void) goto end; } - sm = de_ctx->sig_list->sm_lists[DETECT_SM_LIST_MATCH]; + sm = de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HHDMATCH]; if (sm != NULL) { result &= (sm->type == DETECT_AL_HTTP_HEADER); result &= (sm->next == NULL); } else { + result = 0; printf("Error updating content pattern to http_header pattern: "); } @@ -853,6 +828,7 @@ static int DetectHttpHeaderTest09(void) goto end; de_ctx->flags |= DE_QUIET; + de_ctx->mpm_matcher = MPM_AC; de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any " "(msg:\"http header test\"; " @@ -882,7 +858,7 @@ static int DetectHttpHeaderTest09(void) SigMatchSignatures(&th_v, de_ctx, det_ctx, p1); if ((PacketAlertCheck(p1, 1))) { - printf("sid 1 didn't match but should have: "); + printf("sid 1 matched but shouldn't have: "); goto end; } @@ -1352,13 +1328,13 @@ int DetectHttpHeaderTest14(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_HHDMATCH] == NULL) { + printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HHDMATCH] == NULL\n"); goto end; } DetectContentData *cd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->ctx; - DetectContentData *hhd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_AMATCH]->ctx; + DetectContentData *hhd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HHDMATCH]->ctx; if (cd->id == hhd->id) goto end; @@ -1391,13 +1367,13 @@ int DetectHttpHeaderTest15(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_HHDMATCH] == NULL) { + printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HHDMATCH] == NULL\n"); goto end; } DetectContentData *cd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->ctx; - DetectContentData *hhd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_AMATCH]->ctx; + DetectContentData *hhd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HHDMATCH]->ctx; if (cd->id == hhd->id) goto end; @@ -1430,13 +1406,13 @@ int DetectHttpHeaderTest16(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_HHDMATCH] == NULL) { + printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HHDMATCH] == NULL\n"); goto end; } DetectContentData *cd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->ctx; - DetectContentData *hhd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_AMATCH]->ctx; + DetectContentData *hhd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HHDMATCH]->ctx; if (cd->id != 0 || hhd->id != 1) goto end; @@ -1469,13 +1445,13 @@ int DetectHttpHeaderTest17(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_HHDMATCH] == NULL) { + printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HHDMATCH] == NULL\n"); goto end; } DetectContentData *cd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->ctx; - DetectContentData *hhd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_AMATCH]->ctx; + DetectContentData *hhd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HHDMATCH]->ctx; if (cd->id != 1 || hhd->id != 0) goto end; @@ -1509,14 +1485,14 @@ int DetectHttpHeaderTest18(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_HHDMATCH] == NULL) { + printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HHDMATCH] == NULL\n"); goto end; } DetectContentData *cd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->ctx; - DetectContentData *hhd1 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_AMATCH]->ctx; - DetectContentData *hhd2 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_AMATCH]->prev->ctx; + DetectContentData *hhd1 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HHDMATCH]->ctx; + DetectContentData *hhd2 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HHDMATCH]->prev->ctx; if (cd->id != 1 || hhd1->id != 0 || hhd2->id != 0) goto end; @@ -1550,14 +1526,14 @@ int DetectHttpHeaderTest19(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_HHDMATCH] == NULL) { + printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HHDMATCH] == NULL\n"); goto end; } DetectContentData *cd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->ctx; - DetectContentData *hhd1 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_AMATCH]->ctx; - DetectContentData *hhd2 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_AMATCH]->prev->ctx; + DetectContentData *hhd1 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HHDMATCH]->ctx; + DetectContentData *hhd2 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HHDMATCH]->prev->ctx; if (cd->id != 2 || hhd1->id != 0 || hhd2->id != 0) goto end; diff --git a/src/detect-http-raw-header.c b/src/detect-http-raw-header.c index 22d054d556..335ef4bfbd 100644 --- a/src/detect-http-raw-header.c +++ b/src/detect-http-raw-header.c @@ -294,7 +294,7 @@ static int DetectHttpRawHeaderTest01(void) de_ctx->flags |= DE_QUIET; de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " "(msg:\"Testing http_header\"; " - "content:one; http_header; sid:1;)"); + "content:one; http_raw_header; sid:1;)"); if (de_ctx->sig_list != NULL) { result = 1; } else { @@ -335,7 +335,7 @@ static int DetectHttpRawHeaderTest02(void) de_ctx->flags |= DE_QUIET; de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " "(msg:\"Testing http_header\"; " - "content:one; http_header:; sid:1;)"); + "content:one; http_raw_header:; sid:1;)"); if (de_ctx->sig_list != NULL) result = 1; else @@ -365,7 +365,7 @@ static int DetectHttpRawHeaderTest03(void) de_ctx->flags |= DE_QUIET; de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " "(msg:\"Testing http_header\"; " - "http_header; sid:1;)"); + "http_raw_header; sid:1;)"); if (de_ctx->sig_list == NULL) result = 1; else @@ -395,7 +395,7 @@ static int DetectHttpRawHeaderTest04(void) de_ctx->flags |= DE_QUIET; de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " "(msg:\"Testing http_header\"; " - "content:one; rawbytes; http_header; sid:1;)"); + "content:one; rawbytes; http_raw_header; sid:1;)"); if (de_ctx->sig_list == NULL) result = 1; else @@ -425,7 +425,7 @@ static int DetectHttpRawHeaderTest05(void) de_ctx->flags |= DE_QUIET; de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " "(msg:\"Testing http_header\"; " - "content:one; nocase; http_header; sid:1;)"); + "content:one; nocase; http_raw_header; sid:1;)"); if (de_ctx->sig_list != NULL) result = 1; else @@ -490,7 +490,7 @@ static int DetectHttpRawHeaderTest06(void) de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any " "(msg:\"http header test\"; " - "content:\"Content-Type: text/html\"; http_header; " + "content:\"Content-Type: text/html\"; http_raw_header; " "sid:1;)"); if (de_ctx->sig_list == NULL) goto end; @@ -596,7 +596,7 @@ static int DetectHttpRawHeaderTest07(void) de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any " "(msg:\"http header test\"; " - "content:Mozilla; http_header; " + "content:Mozilla; http_raw_header; " "sid:1;)"); if (de_ctx->sig_list == NULL) goto end; @@ -716,7 +716,7 @@ static int DetectHttpRawHeaderTest08(void) de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any " "(msg:\"http header test\"; " - "content:\"Gecko/20091221 Firefox/3.5.7\"; http_header; " + "content:\"Gecko/20091221 Firefox/3.5.7\"; http_raw_header; " "sid:1;)"); if (de_ctx->sig_list == NULL) goto end; @@ -837,7 +837,7 @@ static int DetectHttpRawHeaderTest09(void) de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any " "(msg:\"http header test\"; " - "content:\"Firefox/3.5.7|0D 0A|Content\"; http_header; " + "content:\"Firefox/3.5.7|0D 0A|Content\"; http_raw_header; " "sid:1;)"); if (de_ctx->sig_list == NULL) goto end; @@ -958,7 +958,7 @@ static int DetectHttpRawHeaderTest10(void) de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any " "(msg:\"http header test\"; " - "content:\"firefox/3.5.7|0D 0A|content\"; nocase; http_header;" + "content:\"firefox/3.5.7|0D 0A|content\"; nocase; http_raw_header;" "sid:1;)"); if (de_ctx->sig_list == NULL) goto end; @@ -1071,7 +1071,7 @@ static int DetectHttpRawHeaderTest11(void) de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any " "(msg:\"http header test\"; " - "content:!lalalalala; http_header; " + "content:!lalalalala; http_raw_header; " "sid:1;)"); if (de_ctx->sig_list == NULL) goto end; @@ -1168,7 +1168,7 @@ static int DetectHttpRawHeaderTest12(void) de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any " "(msg:\"http header test\"; " - "content:!\"User-Agent: Mozilla/5.0 \"; http_header; " + "content:!\"User-Agent: Mozilla/5.0 \"; http_raw_header; " "sid:1;)"); if (de_ctx->sig_list == NULL) goto end; @@ -1266,7 +1266,7 @@ static int DetectHttpRawHeaderTest13(void) de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any " "(msg:\"http header test\"; " - "content:\"Host: www.openinfosecfoundation.org\"; http_header; " + "content:\"Host: www.openinfosecfoundation.org\"; http_raw_header; " "sid:1;)"); if (de_ctx->sig_list == NULL) goto end; @@ -1322,7 +1322,7 @@ int DetectHttpRawHeaderTest14(void) de_ctx->flags |= DE_QUIET; de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " - "(content:one; content:one; http_header; sid:1;)"); + "(content:one; content:one; http_raw_header; sid:1;)"); if (de_ctx->sig_list == NULL) { printf("de_ctx->sig_list == NULL\n"); goto end; @@ -1361,7 +1361,7 @@ int DetectHttpRawHeaderTest15(void) de_ctx->flags |= DE_QUIET; de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " - "(content:one; http_header; content:one; sid:1;)"); + "(content:one; http_raw_header; content:one; sid:1;)"); if (de_ctx->sig_list == NULL) { printf("de_ctx->sig_list == NULL\n"); goto end; @@ -1400,7 +1400,7 @@ int DetectHttpRawHeaderTest16(void) de_ctx->flags |= DE_QUIET; de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " - "(content:one; content:one; content:one; http_header; content:one; sid:1;)"); + "(content:one; content:one; content:one; http_raw_header; content:one; sid:1;)"); if (de_ctx->sig_list == NULL) { printf("de_ctx->sig_list == NULL\n"); goto end; @@ -1439,7 +1439,7 @@ int DetectHttpRawHeaderTest17(void) de_ctx->flags |= DE_QUIET; de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " - "(content:one; http_header; content:one; content:one; content:one; sid:1;)"); + "(content:one; http_raw_header; content:one; content:one; content:one; sid:1;)"); if (de_ctx->sig_list == NULL) { printf("de_ctx->sig_list == NULL\n"); goto end; @@ -1478,8 +1478,8 @@ int DetectHttpRawHeaderTest18(void) de_ctx->flags |= DE_QUIET; de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " - "(content:one; http_header; " - "content:one; content:one; http_header; content:one; sid:1;)"); + "(content:one; http_raw_header; " + "content:one; content:one; http_raw_header; content:one; sid:1;)"); if (de_ctx->sig_list == NULL) { printf("de_ctx->sig_list == NULL\n"); goto end; @@ -1519,8 +1519,8 @@ int DetectHttpRawHeaderTest19(void) de_ctx->flags |= DE_QUIET; de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " - "(content:one; http_header; " - "content:one; content:one; http_header; content:two; sid:1;)"); + "(content:one; http_raw_header; " + "content:one; content:one; http_raw_header; content:two; sid:1;)"); if (de_ctx->sig_list == NULL) { printf("de_ctx->sig_list == NULL\n"); goto end; diff --git a/src/detect-nocase.c b/src/detect-nocase.c index 11fded0845..70f87f34bd 100644 --- a/src/detect-nocase.c +++ b/src/detect-nocase.c @@ -185,8 +185,8 @@ static int DetectNocaseSetup (DetectEngineCtx *de_ctx, Signature *s, char *nulls 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_COOKIE, s->sm_lists_tail[DETECT_SM_LIST_AMATCH], - DETECT_AL_HTTP_HEADER, s->sm_lists_tail[DETECT_SM_LIST_AMATCH], DETECT_AL_HTTP_METHOD, s->sm_lists_tail[DETECT_SM_LIST_AMATCH]); if (pm == NULL) { SCLogError(SC_ERR_NOCASE_MISSING_PATTERN, "\"nocase\" needs a preceeding" diff --git a/src/detect-offset.c b/src/detect-offset.c index f986933870..10a6adad8e 100644 --- a/src/detect-offset.c +++ b/src/detect-offset.c @@ -21,7 +21,7 @@ * \author Victor Julien * \author Anoop Saldanha * - * Implements the offset keyword + * Implements the offset keyword. */ #include "suricata-common.h" @@ -80,10 +80,11 @@ int DetectOffsetSetup (DetectEngineCtx *de_ctx, Signature *s, char *offsetstr) break; default: - pm = SigMatchGetLastSMFromLists(s, 6, + pm = SigMatchGetLastSMFromLists(s, 8, 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_CLIENT_BODY, s->sm_lists_tail[DETECT_SM_LIST_HCBDMATCH], + DETECT_AL_HTTP_HEADER, s->sm_lists_tail[DETECT_SM_LIST_HHDMATCH]); if (pm == NULL) { SCLogError(SC_ERR_WITHIN_MISSING_CONTENT, "offset needs" "preceeding content or uricontent option or http_client_body option"); @@ -206,14 +207,41 @@ int DetectOffsetSetup (DetectEngineCtx *de_ctx, Signature *s, char *offsetstr) break; + case DETECT_AL_HTTP_HEADER: + 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"); - if (dubbed) - SCFree(str); - return -1; - - break; + goto error; } if (dubbed) diff --git a/src/detect-within.c b/src/detect-within.c index 2854157ced..e9addf652d 100644 --- a/src/detect-within.c +++ b/src/detect-within.c @@ -169,13 +169,15 @@ static int DetectWithinSetup (DetectEngineCtx *de_ctx, Signature *s, char *withi } } } else { - pm = SigMatchGetLastSMFromLists(s, 6, + pm = SigMatchGetLastSMFromLists(s, 8, 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_CLIENT_BODY, s->sm_lists_tail[DETECT_SM_LIST_HCBDMATCH], + DETECT_AL_HTTP_HEADER, s->sm_lists_tail[DETECT_SM_LIST_HHDMATCH]); if (pm == NULL) { SCLogError(SC_ERR_WITHIN_MISSING_CONTENT, "within needs" - "preceeding content or uricontent or http_client_body option"); + "preceeding content, uricontent, http_client_body or " + "http_header option"); if (dubbed) SCFree(str); return -1; @@ -412,6 +414,7 @@ static int DetectWithinSetup (DetectEngineCtx *de_ctx, Signature *s, char *withi cd->flags |= DETECT_CONTENT_WITHIN; + /* reassigning pm */ pm = SigMatchGetLastSMFromLists(s, 2, DETECT_AL_HTTP_CLIENT_BODY, pm->prev); if (pm == NULL) { @@ -419,7 +422,54 @@ static int DetectWithinSetup (DetectEngineCtx *de_ctx, Signature *s, char *withi "needs preceeding http_client_body content"); goto error; } + /* 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; + + case DETECT_AL_HTTP_HEADER: + 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", ud->within, + ud->content_len); + goto error; + } + cd->flags |= DETECT_CONTENT_WITHIN; + + /* reassigning pm */ + pm = SigMatchGetLastSMFromLists(s, 2, + DETECT_AL_HTTP_HEADER, pm->prev); + if (pm == NULL) { + SCLogError(SC_ERR_DISTANCE_MISSING_CONTENT, "distance for http_header_body " + "needs preceeding http_header content"); + goto error; + } + /* reassigning cd */ cd = (DetectContentData *)pm->ctx; if (cd->flags & DETECT_CONTENT_FAST_PATTERN_ONLY) { SCLogError(SC_ERR_INVALID_SIGNATURE, "Previous keyword " @@ -428,17 +478,14 @@ static int DetectWithinSetup (DetectEngineCtx *de_ctx, Signature *s, char *withi "only content"); goto error; } - ((DetectContentData *)pm->ctx)->flags |= DETECT_CONTENT_RELATIVE_NEXT; + cd->flags |= DETECT_CONTENT_RELATIVE_NEXT; break; default: SCLogError(SC_ERR_WITHIN_MISSING_CONTENT, "within needs two " "preceeding content or uricontent options"); - if (dubbed) - SCFree(str); - return -1; - break; + goto error; } if (dubbed) @@ -451,6 +498,8 @@ error: return -1; } +/***********************************Unittests**********************************/ + #ifdef UNITTESTS #include "util-unittest-helper.h" /** diff --git a/src/detect.c b/src/detect.c index b7646db517..27b95355d2 100644 --- a/src/detect.c +++ b/src/detect.c @@ -112,9 +112,11 @@ #include "detect-detection-filter.h" #include "detect-http-client-body.h" #include "detect-http-header.h" +#include "detect-http-raw-header.h" #include "detect-http-uri.h" #include "detect-http-stat-msg.h" #include "detect-engine-hcbd.h" +#include "detect-engine-hhd.h" #include "util-rule-vars.h" @@ -682,7 +684,8 @@ static void SigMatchSignaturesBuildMatchArray(DetectEngineCtx *de_ctx, /* de_state check, filter out all signatures that already had a match before * or just partially match */ if (s->flags & SIG_FLAG_AMATCH || s->flags & SIG_FLAG_UMATCH || - s->flags & SIG_FLAG_DMATCH || s->flags & SIG_FLAG_HCBDMATCH) + s->flags & SIG_FLAG_DMATCH || s->flags & SIG_FLAG_HCBDMATCH || + s->flags & SIG_FLAG_HHDMATCH) { /* we run after DeStateDetectContinueDetection, so we might have * state NEW here. In that case we'd want to continue detection @@ -876,6 +879,9 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh det_ctx->de_have_hcbd = TRUE; det_ctx->de_mpm_scanned_hcbd = FALSE; + det_ctx->de_have_hhd = TRUE; + det_ctx->de_mpm_scanned_hhd = FALSE; + SCEnter(); /* No need to perform any detection on this packet, if the the given flag is set.*/ @@ -1173,7 +1179,9 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh if (s->sm_lists[DETECT_SM_LIST_AMATCH] != NULL || s->sm_lists[DETECT_SM_LIST_UMATCH] != NULL || s->sm_lists[DETECT_SM_LIST_DMATCH] != NULL || - s->sm_lists[DETECT_SM_LIST_HCBDMATCH]) { + s->sm_lists[DETECT_SM_LIST_HCBDMATCH] != NULL || + s->sm_lists[DETECT_SM_LIST_HHDMATCH] != NULL) { + if (alstate == NULL) { SCLogDebug("state matches but no state, we can't match"); goto next; @@ -1311,6 +1319,7 @@ end: //} DetectEngineCleanHCBDBuffers(det_ctx); + DetectEngineCleanHHDBuffers(det_ctx); /* store the found sgh (or NULL) in the flow to save us from looking it * up again for the next packet. Also return any stream chunk we processed @@ -1485,6 +1494,9 @@ int SignatureIsIPOnly(DetectEngineCtx *de_ctx, Signature *s) { if (s->sm_lists[DETECT_SM_LIST_HCBDMATCH] != NULL) return 0; + if (s->sm_lists[DETECT_SM_LIST_HHDMATCH] != NULL) + return 0; + if (s->sm_lists[DETECT_SM_LIST_AMATCH] != NULL) return 0; @@ -1559,6 +1571,9 @@ static int SignatureIsDEOnly(DetectEngineCtx *de_ctx, Signature *s) { if (s->sm_lists[DETECT_SM_LIST_HCBDMATCH] != NULL) return 0; + if (s->sm_lists[DETECT_SM_LIST_HHDMATCH] != NULL) + return 0; + SigMatch *sm = s->sm_lists[DETECT_SM_LIST_MATCH]; /* check for conflicting keywords */ for ( ;sm != NULL; sm = sm->next) { @@ -1651,6 +1666,11 @@ static int SignatureCreateMask(Signature *s) { SCLogDebug("sig requires http app state"); } + if (s->sm_lists[DETECT_SM_LIST_HHDMATCH] != 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) { @@ -1726,6 +1746,9 @@ static void SigInitStandardMpmFactoryContexts(DetectEngineCtx *de_ctx) de_ctx->sgh_mpm_context_hcbd = MpmFactoryRegisterMpmCtxProfile("hcbd", MPM_CTX_FACTORY_FLAGS_PREPARE_WITH_SIG_GROUP_BUILD); + de_ctx->sgh_mpm_context_hhd = + MpmFactoryRegisterMpmCtxProfile("hhd", + MPM_CTX_FACTORY_FLAGS_PREPARE_WITH_SIG_GROUP_BUILD); de_ctx->sgh_mpm_context_app_proto_detect = MpmFactoryRegisterMpmCtxProfile("app_proto_detect", 0); @@ -3680,6 +3703,12 @@ int SigGroupBuild (DetectEngineCtx *de_ctx) { } //printf("hcbd- %d\n", mpm_ctx->pattern_cnt); + mpm_ctx = MpmFactoryGetMpmCtxForProfile(de_ctx->sgh_mpm_context_hhd); + if (mpm_table[de_ctx->mpm_matcher].Prepare != NULL) { + mpm_table[de_ctx->mpm_matcher].Prepare(mpm_ctx); + } + //printf("hhd- %d\n", mpm_ctx->pattern_cnt); + mpm_ctx = MpmFactoryGetMpmCtxForProfile(de_ctx->sgh_mpm_context_stream); if (mpm_table[de_ctx->mpm_matcher].Prepare != NULL) { mpm_table[de_ctx->mpm_matcher].Prepare(mpm_ctx); diff --git a/src/detect.h b/src/detect.h index e1175f3aea..65bb0b0b56 100644 --- a/src/detect.h +++ b/src/detect.h @@ -86,7 +86,12 @@ enum { DETECT_SM_LIST_AMATCH, DETECT_SM_LIST_DMATCH, DETECT_SM_LIST_TMATCH, + /* list for http_client_body keyword and the ones relative to it */ DETECT_SM_LIST_HCBDMATCH, + /* list for http_header keyword and the ones relative to it */ + DETECT_SM_LIST_HHDMATCH, + /* list for http_raw_header keyword and the ones relative to it */ + DETECT_SM_LIST_HRHDMATCH, DETECT_SM_LIST_MAX, }; @@ -229,17 +234,23 @@ typedef struct DetectPort_ { #define SIG_FLAG_AMATCH 0x00080000 #define SIG_FLAG_DMATCH 0x00100000 #define SIG_FLAG_HCBDMATCH 0x00200000 +#define SIG_FLAG_HHDMATCH 0x00400000 -#define SIG_FLAG_MPM_PACKET 0x00400000 -#define SIG_FLAG_MPM_PACKET_NEG 0x00800000 -#define SIG_FLAG_MPM_STREAM 0x01000000 -#define SIG_FLAG_MPM_STREAM_NEG 0x02000000 -#define SIG_FLAG_MPM_URICONTENT 0x04000000 -#define SIG_FLAG_MPM_URICONTENT_NEG 0x08000000 -#define SIG_FLAG_MPM_HCBDCONTENT 0x10000000 -#define SIG_FLAG_MPM_HCBDCONTENT_NEG 0x20000000 +#define SIG_FLAG_MPM_PACKET 0x00800000 +#define SIG_FLAG_MPM_PACKET_NEG 0x01000000 +#define SIG_FLAG_MPM_STREAM 0x02000000 +#define SIG_FLAG_MPM_STREAM_NEG 0x04000000 +#define SIG_FLAG_MPM_URICONTENT 0x08000000 +#define SIG_FLAG_MPM_URICONTENT_NEG 0x10000000 +#define SIG_FLAG_MPM_HCBDCONTENT 0x20000000 +#define SIG_FLAG_MPM_HCBDCONTENT_NEG 0x40000000 + +#define SIG_FLAG_HAS_NO_PKT_AND_STREAM_CONTENT 0x80000000 + +/* the mpm specific flags in Signature, held in Signature->mpm_flags */ +#define SIG_FLAG_MPM_HHDCONTENT 0x00000001 +#define SIG_FLAG_MPM_HHDCONTENT_NEG 0x00000002 -#define SIG_FLAG_HAS_NO_PKT_AND_STREAM_CONTENT 0x40000000 /* signature mask flags */ #define SIG_MASK_REQUIRE_PAYLOAD 0x01 @@ -338,6 +349,9 @@ typedef struct Signature_ { uint64_t hdr_copy2; }; + /* mpm flags */ + uint32_t mpm_flags; + //PatIntId mpm_pattern_id; //PatIntId mpm_stream_pattern_id; @@ -356,6 +370,7 @@ typedef struct Signature_ { /** pattern in the mpm matcher */ PatIntId mpm_uripattern_id; PatIntId mpm_hcbdpattern_id; + PatIntId mpm_hhdpattern_id; /* the fast pattern added from this signature */ SigMatch *mpm_sm; @@ -609,6 +624,7 @@ typedef struct DetectEngineCtx_ { /* maximum recursion depth for content inspection */ int inspection_recursion_limit; + /* conf parameter that limits the length of the http request body inspected */ int hcbd_buffer_limit; /* array containing all sgh's in use so we can loop @@ -621,6 +637,7 @@ typedef struct DetectEngineCtx_ { int32_t sgh_mpm_context_stream; int32_t sgh_mpm_context_uri; int32_t sgh_mpm_context_hcbd; + int32_t sgh_mpm_context_hhd; int32_t sgh_mpm_context_app_proto_detect; /** sgh for signatures that match against invalid packets. In those cases @@ -668,10 +685,18 @@ typedef struct DetectionEngineThreadCtx_ { char de_have_hcbd; char de_mpm_scanned_hcbd; + /* detectione engine context for hhd mpm */ + char de_have_hhd; + char de_mpm_scanned_hhd; + uint8_t **hcbd_buffers; uint32_t *hcbd_buffers_len; uint16_t hcbd_buffers_list_len; + uint8_t **hhd_buffers; + uint32_t *hhd_buffers_len; + uint16_t hhd_buffers_list_len; + /** id for alert counter */ uint16_t counter_alerts; @@ -763,11 +788,12 @@ typedef struct SigTableElmt_ { #define SIG_GROUP_HAVEURICONTENT 0x0002 #define SIG_GROUP_HAVESTREAMCONTENT 0x0004 #define SIG_GROUP_HAVEHCBDCONTENT 0x0008 -#define SIG_GROUP_HEAD_MPM_COPY 0x0010 -#define SIG_GROUP_HEAD_MPM_URI_COPY 0x0020 -#define SIG_GROUP_HEAD_MPM_STREAM_COPY 0x0040 -#define SIG_GROUP_HEAD_FREE 0x0080 -#define SIG_GROUP_HEAD_REFERENCED 0x0100 /**< sgh is being referenced by others, don't clear */ +#define SIG_GROUP_HAVEHHDCONTENT 0x0010 +#define SIG_GROUP_HEAD_MPM_COPY 0x0020 +#define SIG_GROUP_HEAD_MPM_URI_COPY 0x0040 +#define SIG_GROUP_HEAD_MPM_STREAM_COPY 0x0080 +#define SIG_GROUP_HEAD_FREE 0x0100 +#define SIG_GROUP_HEAD_REFERENCED 0x0200 /**< sgh is being referenced by others, don't clear */ typedef struct SigGroupHeadInitData_ { /* list of content containers @@ -810,6 +836,7 @@ typedef struct SigGroupHead_ { MpmCtx *mpm_stream_ctx; MpmCtx *mpm_uri_ctx; MpmCtx *mpm_hcbd_ctx; + MpmCtx *mpm_hhd_ctx; uint16_t mpm_uricontent_maxlen; uint16_t pad1; #if __WORDSIZE == 64 diff --git a/src/suricata.c b/src/suricata.c index 1b304081f2..ec957345f8 100644 --- a/src/suricata.c +++ b/src/suricata.c @@ -54,6 +54,7 @@ #include "detect-engine-dcepayload.h" #include "detect-engine-uri.h" #include "detect-engine-hcbd.h" +#include "detect-engine-hhd.h" #include "detect-engine-state.h" #include "detect-engine-tag.h" #include "detect-fast-pattern.h" @@ -968,7 +969,8 @@ int main(int argc, char **argv) DeStateRegisterTests(); DetectRingBufferRegisterTests(); MemcmpRegisterTests(); - HttpClientBodyRegisterTests(); + DetectEngineHttpClientBodyRegisterTests(); + DetectEngineHttpHeaderRegisterTests(); DetectEngineRegisterTests(); SCLogRegisterTests(); if (list_unittests) {