diff --git a/src/detect-content.h b/src/detect-content.h index 150b491afb..597aad305d 100644 --- a/src/detect-content.h +++ b/src/detect-content.h @@ -26,27 +26,28 @@ /* Flags affecting this content */ -#define DETECT_CONTENT_NOCASE 0x0001 -#define DETECT_CONTENT_DISTANCE 0x0002 -#define DETECT_CONTENT_WITHIN 0x0004 -#define DETECT_CONTENT_OFFSET 0x0008 -#define DETECT_CONTENT_DEPTH 0x0010 -#define DETECT_CONTENT_FAST_PATTERN 0x0020 -#define DETECT_CONTENT_FAST_PATTERN_ONLY 0x0040 -#define DETECT_CONTENT_FAST_PATTERN_CHOP 0x0080 +#define DETECT_CONTENT_NOCASE 0x00000001 +#define DETECT_CONTENT_DISTANCE 0x00000002 +#define DETECT_CONTENT_WITHIN 0x00000004 +#define DETECT_CONTENT_OFFSET 0x00000008 +#define DETECT_CONTENT_DEPTH 0x00000010 +#define DETECT_CONTENT_FAST_PATTERN 0x00000020 +#define DETECT_CONTENT_FAST_PATTERN_ONLY 0x00000040 +#define DETECT_CONTENT_FAST_PATTERN_CHOP 0x00000080 /** content applies to a "raw"/undecoded field if applicable */ -#define DETECT_CONTENT_RAWBYTES 0x0100 +#define DETECT_CONTENT_RAWBYTES 0x00000100 /** content is negated */ -#define DETECT_CONTENT_NEGATED 0x0200 +#define DETECT_CONTENT_NEGATED 0x00000200 /** a relative match to this content is next, used in matching phase */ -#define DETECT_CONTENT_RELATIVE_NEXT 0x0400 +#define DETECT_CONTENT_RELATIVE_NEXT 0x00000400 -#define DETECT_CONTENT_PACKET_MPM 0x0800 -#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_PACKET_MPM 0x00000800 +#define DETECT_CONTENT_STREAM_MPM 0x00001000 +#define DETECT_CONTENT_URI_MPM 0x00002000 +#define DETECT_CONTENT_HCBD_MPM 0x00004000 +#define DETECT_CONTENT_HHD_MPM 0x00008000 +#define DETECT_CONTENT_HRHD_MPM 0x00010000 #define DETECT_CONTENT_IS_SINGLE(c) (!((c)->flags & DETECT_CONTENT_DISTANCE || \ (c)->flags & DETECT_CONTENT_WITHIN || \ @@ -59,7 +60,10 @@ typedef struct DetectContentData_ { uint8_t *content; uint8_t content_len; - uint16_t flags; + /* would want to move PatIntId here and flags down to remove the padding + * gap, but I think the first four members was used as a template for + * casting. \todo check this and fix it if posssible */ + uint32_t flags; PatIntId id; uint16_t depth; uint16_t offset; diff --git a/src/detect-depth.c b/src/detect-depth.c index 531ebaedbb..50ad41da16 100644 --- a/src/detect-depth.c +++ b/src/detect-depth.c @@ -83,15 +83,16 @@ static int DetectDepthSetup (DetectEngineCtx *de_ctx, Signature *s, char *depths break; default: - pm = SigMatchGetLastSMFromLists(s, 8, + pm = SigMatchGetLastSMFromLists(s, 10, 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_HEADER, s->sm_lists_tail[DETECT_SM_LIST_HHDMATCH], + DETECT_AL_HTTP_RAW_HEADER, s->sm_lists_tail[DETECT_SM_LIST_HRHDMATCH]); if (pm == NULL) { SCLogError(SC_ERR_DEPTH_MISSING_CONTENT, "depth needs " - "preceeding content, uricontent option, http_client_body " - "or http_header option"); + "preceeding content, uricontent option, http_client_body, " + "http_header option or http_raw_header option"); if (dubbed) SCFree(str); return -1; @@ -226,6 +227,34 @@ static int DetectDepthSetup (DetectEngineCtx *de_ctx, Signature *s, char *depths break; + case DETECT_AL_HTTP_RAW_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"); diff --git a/src/detect-distance.c b/src/detect-distance.c index 0b7bf95dee..fcad76c5de 100644 --- a/src/detect-distance.c +++ b/src/detect-distance.c @@ -66,9 +66,9 @@ static int DetectDistanceSetup (DetectEngineCtx *de_ctx, Signature *s, SigMatch *pm = NULL; /* strip "'s */ - if (distancestr[0] == '\"' && distancestr[strlen(distancestr)-1] == '\"') { - str = SCStrdup(distancestr+1); - str[strlen(distancestr)-2] = '\0'; + if (distancestr[0] == '\"' && distancestr[strlen(distancestr) - 1] == '\"') { + str = SCStrdup(distancestr + 1); + str[strlen(distancestr) - 2] = '\0'; dubbed = 1; } @@ -166,15 +166,16 @@ static int DetectDistanceSetup (DetectEngineCtx *de_ctx, Signature *s, } } } else { - pm = SigMatchGetLastSMFromLists(s, 8, + pm = SigMatchGetLastSMFromLists(s, 10, 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_HEADER, s->sm_lists_tail[DETECT_SM_LIST_HHDMATCH], + DETECT_AL_HTTP_RAW_HEADER, s->sm_lists_tail[DETECT_SM_LIST_HRHDMATCH]); if (pm == NULL) { SCLogError(SC_ERR_WITHIN_MISSING_CONTENT, "within needs" - "preceeding content, uricontent option, http_client_body " - "or http_header option"); + "preceeding content, uricontent option, http_client_body, " + "http_header or http_raw_header option"); if (dubbed) SCFree(str); return -1; @@ -458,6 +459,52 @@ static int DetectDistanceSetup (DetectEngineCtx *de_ctx, Signature *s, break; + case DETECT_AL_HTTP_RAW_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_RAW_HEADER, pm->prev); + if (pm == NULL) { + SCLogError(SC_ERR_DISTANCE_MISSING_CONTENT, "distance for " + "http_raw_header needs preceeding http_raw_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 " + "has a fast_pattern:only; set. You can't " + "have relative keywords around a fast_pattern " + "only content"); + goto error; + } + cd->flags |= DETECT_CONTENT_RELATIVE_NEXT; + + break; + default: SCLogError(SC_ERR_DISTANCE_MISSING_CONTENT, "distance needs two " "preceeding content or uricontent options"); diff --git a/src/detect-engine-hcbd.c b/src/detect-engine-hcbd.c index cdd90e45eb..45387ae13a 100644 --- a/src/detect-engine-hcbd.c +++ b/src/detect-engine-hcbd.c @@ -270,7 +270,7 @@ static uint32_t DetectEngineInspectHttpClientBodyMpmInspect(DetectEngineCtx *de_ /* if the buffer already exists, use it */ if (det_ctx->hcbd_buffers[i] != NULL) { /* we only call the mpm if the hcbd mpm has been set */ - if (s->flags & SIG_FLAG_MPM_HCBDCONTENT) { + if (s->mpm_flags & SIG_FLAG_MPM_HCBDCONTENT) { cnt += HttpClientBodyPatternSearch(det_ctx, det_ctx->hcbd_buffers[i], det_ctx->hcbd_buffers_len[i]); @@ -331,7 +331,7 @@ static uint32_t DetectEngineInspectHttpClientBodyMpmInspect(DetectEngineCtx *de_ det_ctx->hcbd_buffers_len[i] = chunks_buffer_len; /* carry out the mpm if we have hcbd mpm set */ - if (s->flags & SIG_FLAG_MPM_HCBDCONTENT) + if (s->mpm_flags & SIG_FLAG_MPM_HCBDCONTENT) cnt += HttpClientBodyPatternSearch(det_ctx, chunks_buffer, chunks_buffer_len); } /* else - if (htud->body.nchunks == 0) */ } /* for (idx = AppLayerTransactionGetInspectId(f); .. */ @@ -408,7 +408,7 @@ int DetectEngineInspectHttpClientBody(DetectEngineCtx *de_ctx, memset(det_ctx->hcbd_buffers_len, 0, det_ctx->hcbd_buffers_list_len * sizeof(uint32_t)); } /* if (det_ctx->hcbd_buffers_list_len == 0) */ - if (s->flags & SIG_FLAG_MPM_HCBDCONTENT) { + if (s->mpm_flags & SIG_FLAG_MPM_HCBDCONTENT) { if (det_ctx->de_mpm_scanned_hcbd == FALSE) { uint32_t cnt = DetectEngineInspectHttpClientBodyMpmInspect(de_ctx, det_ctx, s, @@ -424,16 +424,16 @@ int DetectEngineInspectHttpClientBody(DetectEngineCtx *de_ctx, } if (det_ctx->de_have_hcbd == FALSE && - s->flags & SIG_FLAG_MPM_HCBDCONTENT && - !(s->flags & SIG_FLAG_MPM_HCBDCONTENT_NEG)) { + s->mpm_flags & SIG_FLAG_MPM_HCBDCONTENT && + !(s->mpm_flags & SIG_FLAG_MPM_HCBDCONTENT_NEG)) { SCLogDebug("mpm results failure for client_body. Get out of here"); goto end; } - if ((s->flags & SIG_FLAG_MPM_HCBDCONTENT) && (det_ctx->de_mpm_scanned_hcbd == TRUE)) { + if ((s->mpm_flags & SIG_FLAG_MPM_HCBDCONTENT) && (det_ctx->de_mpm_scanned_hcbd == TRUE)) { /* filter out the sig that needs a match, but have no matches */ if (!(det_ctx->pmq.pattern_id_bitarray[(s->mpm_hcbdpattern_id / 8)] & (1 << (s->mpm_hcbdpattern_id % 8))) && - !(s->flags & SIG_FLAG_MPM_HCBDCONTENT_NEG)) { + !(s->mpm_flags & SIG_FLAG_MPM_HCBDCONTENT_NEG)) { goto end; } } diff --git a/src/detect-engine-hhd.c b/src/detect-engine-hhd.c index e6c36086a9..1d0354c8c2 100644 --- a/src/detect-engine-hhd.c +++ b/src/detect-engine-hhd.c @@ -254,8 +254,7 @@ match: * \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. + * \retval cnt The match count from the mpm call. */ static uint32_t DetectEngineInspectHttpHeaderMpmInspect(DetectEngineThreadCtx *det_ctx, Signature *s, Flow *f, diff --git a/src/detect-engine-hrhd.c b/src/detect-engine-hrhd.c new file mode 100644 index 0000000000..b60531f866 --- /dev/null +++ b/src/detect-engine-hrhd.c @@ -0,0 +1,2202 @@ +/* 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-hrhd.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 raw 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 raw headers buffer to inspect. + * \param payload_len Length of the http raw headers buffer. + * + * \retval 0 no match. + * \retval 1 match. + */ +static int DoInspectHttpRawHeader(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_RAW_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_HRHD_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 raw header content + * and see if the others match then until we run out of matches */ + int r = DoInspectHttpRawHeader(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 = DoInspectHttpRawHeader(de_ctx, det_ctx, s, sm->next, payload, + payload_len); + SCReturnInt(r); + } else { + SCReturnInt(1); + } +} + +/** + * \brief Helps buffer http raw 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. + */ +static uint32_t DetectEngineInspectHttpRawHeaderMpmInspect(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->hrhd_buffers_list_len; idx++, i++) { + + /* if the buffer already exists, use it */ + if (det_ctx->hrhd_buffers[i] != NULL) { + if (s->mpm_flags & SIG_FLAG_MPM_HRHDCONTENT) { + cnt += HttpRawHeaderPatternSearch(det_ctx, + det_ctx->hrhd_buffers[i], + det_ctx->hrhd_buffers_len[i]); + } + continue; + } + + tx = list_get(htp_state->connp->conn->transactions, idx); + if (tx == NULL) + continue; + + bstr *raw_headers = htp_tx_get_request_headers_raw(tx); + if (raw_headers == NULL) + continue; + /* store the buffers. We will need it for further inspection */ + det_ctx->hrhd_buffers[i] = (uint8_t *)bstr_ptr(raw_headers); + det_ctx->hrhd_buffers_len[i] = bstr_len(raw_headers); + + /* carry out the mpm */ + if (s->mpm_flags & SIG_FLAG_MPM_HRHDCONTENT) + cnt += HttpRawHeaderPatternSearch(det_ctx, det_ctx->hrhd_buffers[i], + det_ctx->hrhd_buffers_len[i]); + } /* for (idx = AppLayerTransactionGetInspectId(f); .. */ + + SCReturnUInt(cnt); +} + +/** + * \brief Do the http_raw_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 DetectEngineInspectHttpRawHeader(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->hrhd_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->hrhd_buffers_list_len = list_size(htp_state->connp->conn->transactions) - tmp_idx; + /* no transactions?! cool. get out of here */ + if (det_ctx->hrhd_buffers_list_len == 0) + goto end; + + /* assign space to hold buffers. Each per transaction */ + det_ctx->hrhd_buffers = SCMalloc(det_ctx->hrhd_buffers_list_len * sizeof(uint8_t *)); + if (det_ctx->hrhd_buffers == NULL) { + SCLogError(SC_ERR_MEM_ALLOC, "Error allocating memory"); + return 0; + } + memset(det_ctx->hrhd_buffers, 0, det_ctx->hrhd_buffers_list_len * sizeof(uint8_t *)); + + det_ctx->hrhd_buffers_len = SCMalloc(det_ctx->hrhd_buffers_list_len * sizeof(uint32_t)); + if (det_ctx->hrhd_buffers_len == NULL) { + SCLogError(SC_ERR_MEM_ALLOC, "Error allocating memory"); + return 0; + } + memset(det_ctx->hrhd_buffers_len, 0, det_ctx->hrhd_buffers_list_len * sizeof(uint32_t)); + } /* if (det_ctx->hrhd_buffers_list_len == 0) */ + + if (s->mpm_flags & SIG_FLAG_MPM_HRHDCONTENT) { + if (det_ctx->de_mpm_scanned_hrhd == FALSE) { + uint32_t cnt = DetectEngineInspectHttpRawHeaderMpmInspect(det_ctx, s, + f, htp_state); + if (cnt <= 0) + det_ctx->de_have_hrhd = FALSE; + + det_ctx->de_mpm_scanned_hrhd = TRUE; + } + } else { + DetectEngineInspectHttpRawHeaderMpmInspect(det_ctx, s, f, htp_state); + } + + if (det_ctx->de_have_hrhd == FALSE && + s->mpm_flags & SIG_FLAG_MPM_HRHDCONTENT && + !(s->mpm_flags & SIG_FLAG_MPM_HRHDCONTENT_NEG)) { + SCLogDebug("mpm results failure for http raw headers. Get out of here"); + goto end; + } + + if ((s->mpm_flags & SIG_FLAG_MPM_HRHDCONTENT) && (det_ctx->de_mpm_scanned_hrhd == TRUE)) { + /* filter out the sig that needs a match, but have no matches */ + if (!(s->mpm_flags & SIG_FLAG_MPM_HRHDCONTENT_NEG) && + !(det_ctx->pmq.pattern_id_bitarray[(s->mpm_hrhdpattern_id / 8)] & (1 << (s->mpm_hrhdpattern_id % 8)))) { + goto end; + } + } + + for (i = 0; i < det_ctx->hrhd_buffers_list_len; i++) { + uint8_t *hrhd_buffer = det_ctx->hrhd_buffers[i]; + uint32_t hrhd_buffer_len = det_ctx->hrhd_buffers_len[i]; + + if (hrhd_buffer == NULL) + continue; + + r = DoInspectHttpRawHeader(de_ctx, det_ctx, s, s->sm_lists[DETECT_SM_LIST_HRHDMATCH], + hrhd_buffer, hrhd_buffer_len); + if (r == 1) { + break; + } + } + +end: + SCMutexUnlock(&f->m); + SCReturnInt(r); +} + +/** + * \brief Clean the hrhd buffers. + * + * \param det_ctx Pointer to the detection engine thread ctx. + */ +void DetectEngineCleanHRHDBuffers(DetectEngineThreadCtx *det_ctx) +{ + if (det_ctx->hrhd_buffers_list_len != 0) { + SCFree(det_ctx->hrhd_buffers); + det_ctx->hrhd_buffers = NULL; + det_ctx->hrhd_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 DetectEngineHttpRawHeaderTest01(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_raw_header; " + "sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + + SigGroupBuild(de_ctx); + DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx); + + int r = AppLayerParse(&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 DetectEngineHttpRawHeaderTest02(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_raw_header; " + "sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + + SigGroupBuild(de_ctx); + DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx); + + int r = AppLayerParse(&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 DetectEngineHttpRawHeaderTest03(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_raw_header; " + "sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + + SigGroupBuild(de_ctx); + DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx); + + int r = AppLayerParse(&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 DetectEngineHttpRawHeaderTest04(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_raw_header; " + "sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + + SigGroupBuild(de_ctx); + DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx); + + int r = AppLayerParse(&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 DetectEngineHttpRawHeaderTest05(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_raw_header; " + "sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + + SigGroupBuild(de_ctx); + DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx); + + int r = AppLayerParse(&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 DetectEngineHttpRawHeaderTest06(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_raw_header; " + "sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + + SigGroupBuild(de_ctx); + DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx); + + int r = AppLayerParse(&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 DetectEngineHttpRawHeaderTest07(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_raw_header; " + "sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + + SigGroupBuild(de_ctx); + DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx); + + int r = AppLayerParse(&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 DetectEngineHttpRawHeaderTest08(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_raw_header; " + "sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + + SigGroupBuild(de_ctx); + DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx); + + int r = AppLayerParse(&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 DetectEngineHttpRawHeaderTest09(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_raw_header; " + "sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + + SigGroupBuild(de_ctx); + DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx); + + int r = AppLayerParse(&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 DetectEngineHttpRawHeaderTest10(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_raw_header; content:three; http_raw_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 DetectEngineHttpRawHeaderTest11(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_raw_header; content:!three; http_raw_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 DetectEngineHttpRawHeaderTest12(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_raw_header; content:!three; http_raw_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 DetectEngineHttpRawHeaderTest13(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_raw_header; content:three; http_raw_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 DetectEngineHttpRawHeaderTest14(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_raw_header; content:five; http_raw_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 DetectEngineHttpRawHeaderTest15(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_raw_header; content:!five; http_raw_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 DetectEngineHttpRawHeaderTest16(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_raw_header; content:!five; http_raw_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 DetectEngineHttpRawHeaderTest17(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_raw_header; content:five; http_raw_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 DetectEngineHttpRawHeaderTest18(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_raw_header; content:five; http_raw_header; " + "sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + + SigGroupBuild(de_ctx); + DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx); + + /* start the search phase */ + det_ctx->sgh = SigMatchSignaturesGetSgh(de_ctx, det_ctx, p); + uint32_t r = HttpRawHeaderPatternSearch(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 DetectEngineHttpRawHeaderTest19(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_raw_header; fast_pattern; content:five; http_raw_header; " + "sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + + SigGroupBuild(de_ctx); + DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx); + + /* start the search phase */ + det_ctx->sgh = SigMatchSignaturesGetSgh(de_ctx, det_ctx, p); + uint32_t r = HttpRawHeaderPatternSearch(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 DetectEngineHttpRawHeaderRegisterTests(void) +{ + +#ifdef UNITTESTS + UtRegisterTest("DetectEngineHttpRawHeaderTest01", + DetectEngineHttpRawHeaderTest01, 1); + UtRegisterTest("DetectEngineHttpRawHeaderTest02", + DetectEngineHttpRawHeaderTest02, 1); + UtRegisterTest("DetectEngineHttpRawHeaderTest03", + DetectEngineHttpRawHeaderTest03, 1); + UtRegisterTest("DetectEngineHttpRawHeaderTest04", + DetectEngineHttpRawHeaderTest04, 1); + UtRegisterTest("DetectEngineHttpRawHeaderTest05", + DetectEngineHttpRawHeaderTest05, 1); + UtRegisterTest("DetectEngineHttpRawHeaderTest06", + DetectEngineHttpRawHeaderTest06, 1); + UtRegisterTest("DetectEngineHttpRawHeaderTest07", + DetectEngineHttpRawHeaderTest07, 1); + UtRegisterTest("DetectEngineHttpRawHeaderTest08", + DetectEngineHttpRawHeaderTest08, 1); + UtRegisterTest("DetectEngineHttpRawHeaderTest09", + DetectEngineHttpRawHeaderTest09, 1); + UtRegisterTest("DetectEngineHttpRawHeaderTest10", + DetectEngineHttpRawHeaderTest10, 1); + UtRegisterTest("DetectEngineHttpRawHeaderTest11", + DetectEngineHttpRawHeaderTest11, 1); + UtRegisterTest("DetectEngineHttpRawHeaderTest12", + DetectEngineHttpRawHeaderTest12, 1); + UtRegisterTest("DetectEngineHttpRawHeaderTest13", + DetectEngineHttpRawHeaderTest13, 1); + UtRegisterTest("DetectEngineHttpRawHeaderTest14", + DetectEngineHttpRawHeaderTest14, 1); + UtRegisterTest("DetectEngineHttpRawHeaderTest15", + DetectEngineHttpRawHeaderTest15, 1); + UtRegisterTest("DetectEngineHttpRawHeaderTest16", + DetectEngineHttpRawHeaderTest16, 1); + UtRegisterTest("DetectEngineHttpRawHeaderTest17", + DetectEngineHttpRawHeaderTest17, 1); + UtRegisterTest("DetectEngineHttpRawHeaderTest18", + DetectEngineHttpRawHeaderTest18, 1); + UtRegisterTest("DetectEngineHttpRawHeaderTest19", + DetectEngineHttpRawHeaderTest19, 1); +#endif /* UNITTESTS */ + + return; +} diff --git a/src/detect-engine-hrhd.h b/src/detect-engine-hrhd.h new file mode 100644 index 0000000000..c8e4408411 --- /dev/null +++ b/src/detect-engine-hrhd.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_HRHD_H__ +#define __DETECT_ENGINE_HRHD_H__ + +int DetectEngineInspectHttpRawHeader(DetectEngineCtx *, DetectEngineThreadCtx *, + Signature *, Flow *, uint8_t, void *); +void DetectEngineCleanHRHDBuffers(DetectEngineThreadCtx *); +void DetectEngineHttpRawHeaderRegisterTests(void); + +#endif /* __DETECT_ENGINE_HHD_H__ */ + diff --git a/src/detect-engine-mpm.c b/src/detect-engine-mpm.c index 26ab39701f..c491d7fbaf 100644 --- a/src/detect-engine-mpm.c +++ b/src/detect-engine-mpm.c @@ -313,6 +313,31 @@ uint32_t HttpHeaderPatternSearch(DetectEngineThreadCtx *det_ctx, SCReturnUInt(ret); } +/** + * \brief Http raw header match -- searches for one pattern per signature. + * + * \param det_ctx Detection engine thread ctx. + * \param headers Raw headers to inspect. + * \param headers_len Raw headers length. + * + * \retval ret Number of matches. + */ +uint32_t HttpRawHeaderPatternSearch(DetectEngineThreadCtx *det_ctx, + uint8_t *raw_headers, uint32_t raw_headers_len) +{ + SCEnter(); + + if (det_ctx->sgh->mpm_hrhd_ctx == NULL) + SCReturnUInt(0); + + uint32_t ret; + ret = mpm_table[det_ctx->sgh->mpm_hrhd_ctx->mpm_type]. + Search(det_ctx->sgh->mpm_hrhd_ctx, &det_ctx->mtcu, + &det_ctx->pmq, raw_headers, raw_headers_len); + + SCReturnUInt(ret); +} + /** \brief Pattern match -- searches for only one pattern per signature. * * \param tv threadvars @@ -609,6 +634,7 @@ static void PopulateMpmAddPatternToMpm(DetectEngineCtx *de_ctx, DetectContentData *ud = NULL; DetectContentData *hcbd = NULL; DetectContentData *hhd = NULL; + DetectContentData *hrhd = NULL; switch (mpm_sm->type) { case DETECT_CONTENT: { @@ -826,10 +852,10 @@ static void PopulateMpmAddPatternToMpm(DetectEngineCtx *de_ctx, } } /* tell matcher we are inspecting uri */ - s->flags |= SIG_FLAG_MPM_HCBDCONTENT; + s->mpm_flags |= SIG_FLAG_MPM_HCBDCONTENT; s->mpm_hcbdpattern_id = hcbd->id; if (hcbd->flags & DETECT_CONTENT_NEGATED) - s->flags |= SIG_FLAG_MPM_HCBDCONTENT_NEG; + s->mpm_flags |= SIG_FLAG_MPM_HCBDCONTENT_NEG; break; } /* case DETECT_AL_HTTP_CLIENT_BODY */ @@ -887,6 +913,59 @@ static void PopulateMpmAddPatternToMpm(DetectEngineCtx *de_ctx, break; } /* case DETECT_AL_HTTP_HEADER */ + case DETECT_AL_HTTP_RAW_HEADER: + { + hrhd = (DetectContentData *)mpm_sm->ctx; + if (hrhd->flags & DETECT_CONTENT_FAST_PATTERN_CHOP) { + /* add the content to the "hrhd" mpm */ + if (hrhd->flags & DETECT_CONTENT_NOCASE) { + mpm_table[sgh->mpm_hrhd_ctx->mpm_type]. + AddPatternNocase(sgh->mpm_hrhd_ctx, + hrhd->content + hrhd->fp_chop_offset, + hrhd->fp_chop_len, + 0, 0, hrhd->id, s->num, flags); + } else { + mpm_table[sgh->mpm_hrhd_ctx->mpm_type]. + AddPattern(sgh->mpm_hrhd_ctx, + hrhd->content + hrhd->fp_chop_offset, + hrhd->fp_chop_len, + 0, 0, hrhd->id, s->num, flags); + } + } else { + if (hrhd->flags & DETECT_CONTENT_FAST_PATTERN_ONLY) { + if (DETECT_CONTENT_IS_SINGLE(hrhd)) { + hrhd->flags |= DETECT_CONTENT_HRHD_MPM; + } + + /* see if we can bypass the match validation for this pattern */ + } else { + if (DETECT_CONTENT_IS_SINGLE(hrhd)) { + hrhd->flags |= DETECT_CONTENT_HRHD_MPM; + } + } /* else - if (hrhd->flags & DETECT_CONTENT_FAST_PATTERN_ONLY) */ + + /* add the content to the "hrhd" mpm */ + if (hrhd->flags & DETECT_CONTENT_NOCASE) { + mpm_table[sgh->mpm_hrhd_ctx->mpm_type]. + AddPatternNocase(sgh->mpm_hrhd_ctx, + hrhd->content, hrhd->content_len, + 0, 0, hrhd->id, s->num, flags); + } else { + mpm_table[sgh->mpm_hrhd_ctx->mpm_type]. + AddPattern(sgh->mpm_hrhd_ctx, + hrhd->content, hrhd->content_len, + 0, 0, hrhd->id, s->num, flags); + } + } + /* tell matcher we are inspecting uri */ + s->mpm_flags |= SIG_FLAG_MPM_HRHDCONTENT; + s->mpm_hrhdpattern_id = hrhd->id; + if (hrhd->flags & DETECT_CONTENT_NEGATED) + s->mpm_flags |= SIG_FLAG_MPM_HRHDCONTENT_NEG; + + break; + } /* case DETECT_AL_HTTP_RAW_HEADER */ + } /* switch (mpm_sm->type) */ SCLogDebug("%"PRIu32" adding cd->id %"PRIu32" to the mpm phase " @@ -1938,6 +2017,8 @@ int PatternMatchPrepareGroup(DetectEngineCtx *de_ctx, SigGroupHead *sh) uint32_t has_co_hcbd = 0; /* used to indicate if sgh has atleast one sig with http_header */ uint32_t has_co_hhd = 0; + /* used to indicate if sgh has atleast one sig with http_raw_header */ + uint32_t has_co_hrhd = 0; //uint32_t cnt = 0; uint32_t sig = 0; @@ -1977,6 +2058,10 @@ int PatternMatchPrepareGroup(DetectEngineCtx *de_ctx, SigGroupHead *sh) has_co_hhd = 1; } + if (s->sm_lists[DETECT_SM_LIST_HRHDMATCH] != NULL) { + has_co_hrhd = 1; + } + } if (has_co_packet > 0) { @@ -1994,6 +2079,9 @@ int PatternMatchPrepareGroup(DetectEngineCtx *de_ctx, SigGroupHead *sh) if (has_co_hhd > 0) { sh->flags |= SIG_GROUP_HAVEHHDCONTENT; } + if (has_co_hrhd > 0) { + sh->flags |= SIG_GROUP_HAVEHRHDCONTENT; + } /* intialize contexes */ if (sh->flags & SIG_GROUP_HAVECONTENT) { @@ -2086,6 +2174,24 @@ int PatternMatchPrepareGroup(DetectEngineCtx *de_ctx, SigGroupHead *sh) #endif } + if (sh->flags & SIG_GROUP_HAVEHRHDCONTENT) { + if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_SINGLE) { + sh->mpm_hrhd_ctx = MpmFactoryGetMpmCtxForProfile(de_ctx->sgh_mpm_context_hrhd); + } else { + sh->mpm_hrhd_ctx = MpmFactoryGetMpmCtxForProfile(MPM_CTX_FACTORY_UNIQUE_CONTEXT); + } + if (sh->mpm_hrhd_ctx == NULL) { + SCLogDebug("sh->mpm_hrhd_ctx == NULL. This should never happen"); + exit(EXIT_FAILURE); + } + +#ifndef __SC_CUDA_SUPPORT__ + MpmInitCtx(sh->mpm_hrhd_ctx, de_ctx->mpm_matcher, -1); +#else + MpmInitCtx(sh->mpm_hrhd_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]; @@ -2219,7 +2325,8 @@ int PatternMatchPrepareGroup(DetectEngineCtx *de_ctx, SigGroupHead *sh) sh->flags & SIG_GROUP_HAVESTREAMCONTENT || sh->flags & SIG_GROUP_HAVEURICONTENT || sh->flags & SIG_GROUP_HAVEHCBDCONTENT || - sh->flags & SIG_GROUP_HAVEHHDCONTENT) { + sh->flags & SIG_GROUP_HAVEHHDCONTENT || + sh->flags & SIG_GROUP_HAVEHRHDCONTENT) { PatternMatchPreparePopulateMpm(de_ctx, sh); @@ -2279,6 +2386,17 @@ int PatternMatchPrepareGroup(DetectEngineCtx *de_ctx, SigGroupHead *sh) } } } + if (sh->mpm_hrhd_ctx != NULL) { + if (sh->mpm_hrhd_ctx->pattern_cnt == 0) { + MpmFactoryReClaimMpmCtx(sh->mpm_hrhd_ctx); + sh->mpm_hrhd_ctx = NULL; + } else { + if (sh->flags & SIG_GROUP_HAVEHRHDCONTENT) { + if (mpm_table[sh->mpm_hrhd_ctx->mpm_type].Prepare != NULL) + mpm_table[sh->mpm_hrhd_ctx->mpm_type].Prepare(sh->mpm_hrhd_ctx); + } + } + } } /* if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) */ } else { @@ -2292,6 +2410,8 @@ int PatternMatchPrepareGroup(DetectEngineCtx *de_ctx, SigGroupHead *sh) sh->mpm_hcbd_ctx = NULL; MpmFactoryReClaimMpmCtx(sh->mpm_hhd_ctx); sh->mpm_hhd_ctx = NULL; + MpmFactoryReClaimMpmCtx(sh->mpm_hrhd_ctx); + sh->mpm_hrhd_ctx = NULL; } ///* uricontent */ diff --git a/src/detect-engine-mpm.h b/src/detect-engine-mpm.h index 394b2c664c..0e5f572485 100644 --- a/src/detect-engine-mpm.h +++ b/src/detect-engine-mpm.h @@ -38,6 +38,7 @@ 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); +uint32_t HttpRawHeaderPatternSearch(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 9369884892..ad065684b0 100644 --- a/src/detect-engine-state.c +++ b/src/detect-engine-state.c @@ -33,6 +33,7 @@ #include "detect-engine-uri.h" #include "detect-engine-hcbd.h" #include "detect-engine-hhd.h" +#include "detect-engine-hrhd.h" #include "detect-engine-dcepayload.h" #include "stream-tcp.h" @@ -207,7 +208,7 @@ int DeStateUpdateInspectTransactionId(Flow *f, char direction) { */ static void DeStateSignatureAppend(DetectEngineState *state, Signature *s, SigMatch *sm, char uri, char dce, char hcbd, - char hhd) { + char hhd, char hrhd) { DeStateStore *store = state->tail; if (store == NULL) { @@ -247,6 +248,9 @@ static void DeStateSignatureAppend(DetectEngineState *state, Signature *s, if (hhd) { store->store[idx].flags |= DE_STATE_FLAG_HHD_MATCH; } + if (hrhd) { + store->store[idx].flags |= DE_STATE_FLAG_HRHD_MATCH; + } store->store[idx].nm = sm; state->cnt++; @@ -310,6 +314,8 @@ int DeStateDetectStartDetection(ThreadVars *tv, DetectEngineCtx *de_ctx, char hcbdinspect = 0; char hhdmatch = 0; char hhdinspect = 0; + char hrhdmatch = 0; + char hrhdinspect = 0; char dmatch = 0; char dinspect = 0; char appinspect = 0; @@ -351,7 +357,15 @@ int DeStateDetectStartDetection(ThreadVars *tv, DetectEngineCtx *de_ctx, flags, alstate) == 1) { hhdmatch = 1; } - SCLogDebug("inspecting http client body"); + SCLogDebug("inspecting http header"); + } + if (s->sm_lists[DETECT_SM_LIST_HRHDMATCH] != NULL) { + hrhdinspect = 1; + if (DetectEngineInspectHttpRawHeader(de_ctx, det_ctx, s, f, + flags, alstate) == 1) { + hrhdmatch = 1; + } + SCLogDebug("inspecting http raw header"); } } else if (alproto == ALPROTO_DCERPC || alproto == ALPROTO_SMB || alproto == ALPROTO_SMB2) { @@ -384,8 +398,8 @@ int DeStateDetectStartDetection(ThreadVars *tv, DetectEngineCtx *de_ctx, } } - appinspect = uinspect + dinspect + hcbdinspect + hhdinspect; - appmatch = umatch + dmatch + hcbdmatch + hhdmatch; + appinspect = uinspect + dinspect + hcbdinspect + hhdinspect + hrhdinspect; + appmatch = umatch + dmatch + hcbdmatch + hhdmatch + hrhdmatch; if (s->sm_lists[DETECT_SM_LIST_AMATCH] != NULL) { for ( ; sm != NULL; sm = sm->next) { @@ -427,8 +441,8 @@ int DeStateDetectStartDetection(ThreadVars *tv, DetectEngineCtx *de_ctx, } } - SCLogDebug("detection done, store results: sm %p, uri %d, dce %d, hcbd %d " - "hhd %d", sm, umatch, dmatch, hcbdmatch, hhdmatch); + SCLogDebug("detection done, store results: sm %p, uri %d, dce %d, hcbd %d, " + "hhd %d, hrhd %d", sm, umatch, dmatch, hcbdmatch, hhdmatch, hrhdmatch); SCMutexLock(&f->de_state_m); /* match or no match, we store the state anyway @@ -439,7 +453,7 @@ int DeStateDetectStartDetection(ThreadVars *tv, DetectEngineCtx *de_ctx, } if (f->de_state != NULL) { /* \todo shift to an array to transfer these match values*/ - DeStateSignatureAppend(f->de_state, s, sm, umatch, dmatch, hcbdmatch, hhdmatch); + DeStateSignatureAppend(f->de_state, s, sm, umatch, dmatch, hcbdmatch, hhdmatch, hrhdmatch); } SCMutexUnlock(&f->de_state_m); @@ -465,6 +479,8 @@ int DeStateDetectContinueDetection(ThreadVars *tv, DetectEngineCtx *de_ctx, Dete char hcbdinspect = 0; char hhdmatch = 0; char hhdinspect = 0; + char hrhdmatch = 0; + char hrhdinspect = 0; char dmatch = 0; char dinspect = 0; char appinspect = 0; @@ -495,6 +511,8 @@ int DeStateDetectContinueDetection(ThreadVars *tv, DetectEngineCtx *de_ctx, Dete hcbdinspect = 0; hhdmatch = 0; hhdinspect = 0; + hrhdmatch = 0; + hrhdinspect = 0; dmatch = 0; dinspect = 0; appinspect = 0; @@ -564,6 +582,20 @@ int DeStateDetectContinueDetection(ThreadVars *tv, DetectEngineCtx *de_ctx, Dete } } } + if (s->sm_lists[DETECT_SM_LIST_HRHDMATCH] != NULL) { + if (!(item->flags & DE_STATE_FLAG_HRHD_MATCH)) { + SCLogDebug("inspecting http raw header data"); + hrhdinspect = 1; + + if (DetectEngineInspectHttpRawHeader(de_ctx, det_ctx, s, f, + flags, alstate) == 1) { + SCLogDebug("http raw header matched"); + item->flags |= DE_STATE_FLAG_HRHD_MATCH; + hrhdmatch = 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)) { @@ -601,8 +633,8 @@ int DeStateDetectContinueDetection(ThreadVars *tv, DetectEngineCtx *de_ctx, Dete } - appinspect = uinspect + dinspect + hcbdinspect + hhdinspect; - appmatch = umatch + dmatch + hcbdmatch + hhdmatch; + appinspect = uinspect + dinspect + hcbdinspect + hhdinspect + hrhdinspect; + appmatch = umatch + dmatch + hcbdmatch + hhdmatch + hrhdmatch; SCLogDebug("appinspect %d, appmatch %d", appinspect, appmatch); /* next, check the other sig matches */ @@ -742,39 +774,39 @@ static int DeStateTest02(void) { memset(&s, 0x00, sizeof(s)); s.num = 0; - DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0); + DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0); s.num = 11; - DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0); + DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0); s.num = 22; - DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0); + DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0); s.num = 33; - DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0); + DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0); s.num = 44; - DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0); + DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0); s.num = 55; - DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0); + DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0); s.num = 66; - DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0); + DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0); s.num = 77; - DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0); + DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0); s.num = 88; - DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0); + DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0); s.num = 99; - DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0); + DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0); s.num = 100; - DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0); + DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0); s.num = 111; - DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0); + DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0); s.num = 122; - DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0); + DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0); s.num = 133; - DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0); + DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0); s.num = 144; - DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0); + DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0); s.num = 155; - DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0); + DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0); s.num = 166; - DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0); + DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0); if (state->head == NULL) { goto end; @@ -817,9 +849,9 @@ static int DeStateTest03(void) { memset(&s, 0x00, sizeof(s)); s.num = 11; - DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0); + DeStateSignatureAppend(state, &s, NULL, 0, 0, 0, 0, 0); s.num = 22; - DeStateSignatureAppend(state, &s, NULL, 1, 0, 0, 0); + DeStateSignatureAppend(state, &s, NULL, 1, 0, 0, 0, 0); if (state->head == NULL) { goto end; diff --git a/src/detect-engine-state.h b/src/detect-engine-state.h index 6511c39c1b..3d5bd34c38 100644 --- a/src/detect-engine-state.h +++ b/src/detect-engine-state.h @@ -48,8 +48,9 @@ #define DE_STATE_FLAG_URI_MATCH 0x02 /**< uri part of the sig matched */ #define DE_STATE_FLAG_DCE_MATCH 0x04 /**< dce payload inspection part matched */ #define DE_STATE_FLAG_HCBD_MATCH 0x08 /**< hcbd payload inspection part matched */ -#define DE_STATE_FLAG_HHD_MATCH 0x10 /**< hcbd payload inspection part matched */ -#define DE_STATE_FLAG_FULL_MATCH 0x20 /**< sig already fully matched */ +#define DE_STATE_FLAG_HHD_MATCH 0x10 /**< hhd payload inspection part matched */ +#define DE_STATE_FLAG_HRHD_MATCH 0x20 /**< hrhd payload inspection part matched */ +#define DE_STATE_FLAG_FULL_MATCH 0x40 /**< sig already fully matched */ /** per signature detection engine state */ typedef enum { diff --git a/src/detect-fast-pattern.c b/src/detect-fast-pattern.c index 167637d4b2..789588cb61 100644 --- a/src/detect-fast-pattern.c +++ b/src/detect-fast-pattern.c @@ -131,6 +131,9 @@ void SupportFastPatternForSigMatchTypes(void) SupportFastPatternForSigMatchType(DETECT_AL_HTTP_HEADER); SupportFastPatternForSigMatchList(DETECT_SM_LIST_HHDMATCH); + SupportFastPatternForSigMatchType(DETECT_AL_HTTP_RAW_HEADER); + SupportFastPatternForSigMatchList(DETECT_SM_LIST_HRHDMATCH); + return; } @@ -198,19 +201,22 @@ 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_HHDMATCH] == NULL) { + s->sm_lists_tail[DETECT_SM_LIST_HHDMATCH] == NULL && + s->sm_lists_tail[DETECT_SM_LIST_HRHDMATCH] == NULL) { SCLogWarning(SC_WARN_COMPATIBILITY, "fast_pattern found inside the " "rule, without a preceding content based keyword. " "Currently we provide fast_pattern support for content, " - "uricontent, http_client_body and http_header"); + "uricontent, http_client_body, http_header and " + "http_raw_header"); return -1; } - SigMatch *pm = SigMatchGetLastSMFromLists(s, 8, + SigMatch *pm = SigMatchGetLastSMFromLists(s, 10, 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_HEADER, s->sm_lists_tail[DETECT_SM_LIST_HHDMATCH], + DETECT_AL_HTTP_RAW_HEADER, s->sm_lists_tail[DETECT_SM_LIST_HRHDMATCH]); if (pm == NULL) { SCLogError(SC_ERR_INVALID_SIGNATURE, "fast_pattern found inside " "the rule, without a content context. Please use a " @@ -5429,26 +5435,7 @@ int DetectFastPatternTest178(void) return result; } - - - - - - - - - - - - - - - - - - - - +/*****http_header tests v ******/ int DetectFastPatternTest179(void) { @@ -6555,6 +6542,1125 @@ int DetectFastPatternTest219(void) return result; } + + + + + + + + + + + + +/********* http_raw_header tests v *****/ + +int DetectFastPatternTest220(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:one; http_raw_header; " + "content:!oneonetwo; fast_pattern:3,4; http_raw_header; " + "content:three; http_raw_header; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHDMATCH]->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 DetectFastPatternTest221(void) +{ + SigMatch *sm = NULL; + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:\"/one/\"; fast_pattern:only; http_raw_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_HRHDMATCH]; + 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 DetectFastPatternTest222(void) +{ + SigMatch *sm = NULL; + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:oneoneone; fast_pattern:3,4; http_raw_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_HRHDMATCH]; + 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 DetectFastPatternTest223(void) +{ + SigMatch *sm = NULL; + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:one; fast_pattern:only; http_raw_header; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + + result = 0; + sm = de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HRHDMATCH]; + 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 DetectFastPatternTest224(void) +{ + SigMatch *sm = NULL; + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:oneoneone; fast_pattern:3,4; http_raw_header; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + + result = 0; + sm = de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HRHDMATCH]; + 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 DetectFastPatternTest225(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:one; http_raw_header; content:two; fast_pattern:only; http_raw_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 DetectFastPatternTest226(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:one; http_raw_header; content:two; distance:10; fast_pattern:only; http_raw_header; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest227(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:one; http_raw_header; content:two; fast_pattern:only; http_raw_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 DetectFastPatternTest228(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:one; http_raw_header; content:two; within:10; fast_pattern:only; http_raw_header; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest229(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:one; http_raw_header; content:two; fast_pattern:only; http_raw_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 DetectFastPatternTest230(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:one; http_raw_header; content:two; offset:10; fast_pattern:only; http_raw_header; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest231(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:one; http_raw_header; content:two; fast_pattern:only; http_raw_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 DetectFastPatternTest232(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:one; http_raw_header; content:two; depth:10; fast_pattern:only; http_raw_header; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest233(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:one; http_raw_header; content:!two; fast_pattern:only; http_raw_header; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest234(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content: one; http_raw_header; content:two; http_raw_header; distance:30; content:two; fast_pattern:only; http_raw_header; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHDMATCH]->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 DetectFastPatternTest235(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:one; http_raw_header; content:two; http_raw_header; within:30; content:two; fast_pattern:only; http_raw_header; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHDMATCH]->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 DetectFastPatternTest236(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:one; http_raw_header; content:two; http_raw_header; offset:30; content:two; fast_pattern:only; http_raw_header; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHDMATCH]->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 DetectFastPatternTest237(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:one; http_raw_header; content:two; http_raw_header; depth:30; content:two; fast_pattern:only; http_raw_header; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHDMATCH]->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 DetectFastPatternTest238(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:!one; fast_pattern; http_raw_header; content:two; http_raw_header; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHDMATCH]->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 DetectFastPatternTest239(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:two; http_raw_header; content:!one; fast_pattern; http_raw_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 DetectFastPatternTest240(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:two; http_raw_header; content:!one; fast_pattern; http_raw_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 DetectFastPatternTest241(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:two; http_raw_header; content:!one; fast_pattern; http_raw_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 DetectFastPatternTest242(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:two; http_raw_header; content:!one; fast_pattern; http_raw_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 DetectFastPatternTest243(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:one; http_raw_header; content:oneonetwo; fast_pattern:3,4; http_raw_header; content:three; http_raw_header; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHDMATCH]->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 DetectFastPatternTest244(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:one; http_raw_header; content:oneonetwo; fast_pattern:3,4; http_raw_header; content:three; http_raw_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_HRHDMATCH]->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 DetectFastPatternTest245(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:one; http_raw_header; content:oneonetwo; fast_pattern:3,4; http_raw_header; content:three; http_raw_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_HRHDMATCH]->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 DetectFastPatternTest246(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:one; http_raw_header; content:oneonetwo; fast_pattern:3,4; http_raw_header; content:three; http_raw_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_HRHDMATCH]->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 DetectFastPatternTest247(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:one; http_raw_header; content:oneonetwo; fast_pattern:3,4; http_raw_header; content:three; http_raw_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_HRHDMATCH]->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 DetectFastPatternTest248(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:one; http_raw_header; content:two; http_raw_header; distance:10; content:oneonethree; fast_pattern:3,4; http_raw_header; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHDMATCH]->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 DetectFastPatternTest249(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:one; http_raw_header; content:two; http_raw_header; within:10; content:oneonethree; fast_pattern:3,4; http_raw_header; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHDMATCH]->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 DetectFastPatternTest250(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:one; http_raw_header; content:two; http_raw_header; offset:10; content:oneonethree; fast_pattern:3,4; http_raw_header; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHDMATCH]->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 DetectFastPatternTest251(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:one; http_raw_header; content:two; http_raw_header; depth:10; content:oneonethree; fast_pattern:3,4; http_raw_header; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHDMATCH]->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 DetectFastPatternTest252(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:one; http_raw_header; content:two; fast_pattern:65977,4; http_raw_header; content:three; http_raw_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 DetectFastPatternTest253(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:one; http_raw_header; content:oneonetwo; fast_pattern:3,65977; http_raw_header; content:three; distance:10; http_raw_header; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest254(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:one; http_raw_header; content:two; fast_pattern:65534,4; http_raw_header; content:three; http_raw_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 DetectFastPatternTest255(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:one; http_raw_header; content:!oneonetwo; fast_pattern:3,4; http_raw_header; content:three; http_raw_header; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHDMATCH]->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 DetectFastPatternTest256(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:one; http_raw_header; content:!oneonetwo; fast_pattern:3,4; http_raw_header; distance:10; content:three; http_raw_header; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest257(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:one; http_raw_header; content:!oneonetwo; fast_pattern:3,4; http_raw_header; within:10; content:three; http_raw_header; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest258(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:one; http_raw_header; content:!oneonetwo; fast_pattern:3,4; http_raw_header; offset:10; content:three; http_raw_header; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest259(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:one; http_raw_header; content:!oneonetwo; fast_pattern:3,4; http_raw_header; depth:10; content:three; http_raw_header; sid:1;)"); + if (de_ctx->sig_list != NULL) + goto end; + + result = 1; + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +int DetectFastPatternTest260(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if ( (de_ctx = DetectEngineCtxInit()) == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any " + "(content:one; http_raw_header; content:!oneonetwo; fast_pattern:3,4; http_raw_header; content:three; http_raw_header; sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + DetectContentData *ud = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHDMATCH]->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) @@ -6790,6 +7896,49 @@ void DetectFastPatternRegisterTests(void) UtRegisterTest("DetectFastPatternTest217", DetectFastPatternTest217, 1); UtRegisterTest("DetectFastPatternTest218", DetectFastPatternTest218, 1); UtRegisterTest("DetectFastPatternTest219", DetectFastPatternTest219, 1); + /* http_header fast_pattern tests ^ */ + /* http_raw_header fast_pattern tests v */ + UtRegisterTest("DetectFastPatternTest220", DetectFastPatternTest220, 1); + UtRegisterTest("DetectFastPatternTest221", DetectFastPatternTest221, 1); + UtRegisterTest("DetectFastPatternTest222", DetectFastPatternTest222, 1); + UtRegisterTest("DetectFastPatternTest223", DetectFastPatternTest223, 1); + UtRegisterTest("DetectFastPatternTest224", DetectFastPatternTest224, 1); + UtRegisterTest("DetectFastPatternTest225", DetectFastPatternTest225, 1); + UtRegisterTest("DetectFastPatternTest226", DetectFastPatternTest226, 1); + UtRegisterTest("DetectFastPatternTest227", DetectFastPatternTest227, 1); + UtRegisterTest("DetectFastPatternTest228", DetectFastPatternTest228, 1); + UtRegisterTest("DetectFastPatternTest229", DetectFastPatternTest229, 1); + UtRegisterTest("DetectFastPatternTest230", DetectFastPatternTest230, 1); + UtRegisterTest("DetectFastPatternTest231", DetectFastPatternTest231, 1); + UtRegisterTest("DetectFastPatternTest232", DetectFastPatternTest232, 1); + UtRegisterTest("DetectFastPatternTest233", DetectFastPatternTest233, 1); + UtRegisterTest("DetectFastPatternTest234", DetectFastPatternTest234, 1); + UtRegisterTest("DetectFastPatternTest235", DetectFastPatternTest235, 1); + UtRegisterTest("DetectFastPatternTest236", DetectFastPatternTest236, 1); + UtRegisterTest("DetectFastPatternTest237", DetectFastPatternTest237, 1); + UtRegisterTest("DetectFastPatternTest238", DetectFastPatternTest238, 1); + UtRegisterTest("DetectFastPatternTest239", DetectFastPatternTest239, 1); + UtRegisterTest("DetectFastPatternTest240", DetectFastPatternTest240, 1); + UtRegisterTest("DetectFastPatternTest241", DetectFastPatternTest241, 1); + UtRegisterTest("DetectFastPatternTest242", DetectFastPatternTest242, 1); + UtRegisterTest("DetectFastPatternTest243", DetectFastPatternTest243, 1); + UtRegisterTest("DetectFastPatternTest244", DetectFastPatternTest244, 1); + UtRegisterTest("DetectFastPatternTest245", DetectFastPatternTest245, 1); + UtRegisterTest("DetectFastPatternTest246", DetectFastPatternTest246, 1); + UtRegisterTest("DetectFastPatternTest247", DetectFastPatternTest247, 1); + UtRegisterTest("DetectFastPatternTest248", DetectFastPatternTest248, 1); + UtRegisterTest("DetectFastPatternTest249", DetectFastPatternTest249, 1); + UtRegisterTest("DetectFastPatternTest250", DetectFastPatternTest250, 1); + UtRegisterTest("DetectFastPatternTest251", DetectFastPatternTest251, 1); + UtRegisterTest("DetectFastPatternTest252", DetectFastPatternTest252, 1); + UtRegisterTest("DetectFastPatternTest253", DetectFastPatternTest253, 1); + UtRegisterTest("DetectFastPatternTest254", DetectFastPatternTest254, 1); + UtRegisterTest("DetectFastPatternTest255", DetectFastPatternTest255, 1); + UtRegisterTest("DetectFastPatternTest256", DetectFastPatternTest256, 1); + UtRegisterTest("DetectFastPatternTest257", DetectFastPatternTest257, 1); + UtRegisterTest("DetectFastPatternTest258", DetectFastPatternTest258, 1); + UtRegisterTest("DetectFastPatternTest259", DetectFastPatternTest259, 1); + UtRegisterTest("DetectFastPatternTest260", DetectFastPatternTest260, 1); #endif return; diff --git a/src/detect-http-header.c b/src/detect-http-header.c index c9a0529501..ebd33ccdba 100644 --- a/src/detect-http-header.c +++ b/src/detect-http-header.c @@ -65,13 +65,15 @@ void DetectHttpHeaderRegister(void) { sigmatch_table[DETECT_AL_HTTP_HEADER].name = "http_header"; sigmatch_table[DETECT_AL_HTTP_HEADER].Match = NULL; - sigmatch_table[DETECT_AL_HTTP_HEADER].AppLayerMatch = DetectHttpHeaderMatch; - sigmatch_table[DETECT_AL_HTTP_HEADER].alproto = ALPROTO_HTTP; + sigmatch_table[DETECT_AL_HTTP_HEADER].AppLayerMatch = NULL; sigmatch_table[DETECT_AL_HTTP_HEADER].Setup = DetectHttpHeaderSetup; sigmatch_table[DETECT_AL_HTTP_HEADER].Free = DetectHttpHeaderFree; sigmatch_table[DETECT_AL_HTTP_HEADER].RegisterTests = DetectHttpHeaderRegisterTests; + sigmatch_table[DETECT_AL_HTTP_HEADER].alproto = ALPROTO_HTTP; sigmatch_table[DETECT_AL_HTTP_HEADER].flags |= SIGMATCH_PAYLOAD ; + + return; } /** @@ -258,7 +260,7 @@ error: if (cd != NULL) DetectHttpHeaderFree(cd); - if(sm != NULL) + if (sm != NULL) SCFree(sm); return -1; diff --git a/src/detect-http-raw-header.c b/src/detect-http-raw-header.c index 335ef4bfbd..9e44a812e8 100644 --- a/src/detect-http-raw-header.c +++ b/src/detect-http-raw-header.c @@ -33,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" @@ -64,13 +65,16 @@ 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 = DetectHttpRawHeaderMatch; - sigmatch_table[DETECT_AL_HTTP_RAW_HEADER].alproto = ALPROTO_HTTP; + sigmatch_table[DETECT_AL_HTTP_RAW_HEADER].AppLayerMatch = NULL; + //sigmatch_table[DETECT_AL_HTTP_RAW_HEADER].AppLayerMatch = DetectHttpRawHeaderMatch; sigmatch_table[DETECT_AL_HTTP_RAW_HEADER].Setup = DetectHttpRawHeaderSetup; sigmatch_table[DETECT_AL_HTTP_RAW_HEADER].Free = DetectHttpRawHeaderFree; sigmatch_table[DETECT_AL_HTTP_RAW_HEADER].RegisterTests = DetectHttpRawHeaderRegisterTests; + sigmatch_table[DETECT_AL_HTTP_RAW_HEADER].alproto = ALPROTO_HTTP; - sigmatch_table[DETECT_AL_HTTP_RAW_HEADER].flags |= SIGMATCH_PAYLOAD ; + sigmatch_table[DETECT_AL_HTTP_RAW_HEADER].flags |= SIGMATCH_PAYLOAD; + + return; } /** @@ -88,8 +92,8 @@ void DetectHttpRawHeaderRegister(void) * \retval 0 On no match. */ int DetectHttpRawHeaderMatch(ThreadVars *t, DetectEngineThreadCtx *det_ctx, - Flow *f, uint8_t flags, void *state, Signature *s, - SigMatch *m) + Flow *f, uint8_t flags, void *state, Signature *s, + SigMatch *m) { SCEnter(); @@ -150,12 +154,12 @@ int DetectHttpRawHeaderMatch(ThreadVars *t, DetectEngineThreadCtx *det_ctx, */ void DetectHttpRawHeaderFree(void *ptr) { - DetectContentData *hrhd = (DetectContentData *)ptr; - if (hrhd == NULL) + DetectContentData *cd = (DetectContentData *)ptr; + if (cd == NULL) return; - if (hrhd->content != NULL) - SCFree(hrhd->content); - SCFree(hrhd); + if (cd->content != NULL) + SCFree(cd->content); + SCFree(cd); return; } @@ -175,9 +179,7 @@ void DetectHttpRawHeaderFree(void *ptr) */ int DetectHttpRawHeaderSetup(DetectEngineCtx *de_ctx, Signature *s, char *arg) { - /* http_raw_header_data (hrhd) */ - DetectContentData *hrhd = NULL; - SigMatch *nm = NULL; + DetectContentData *cd = NULL; SigMatch *sm = NULL; if (arg != NULL && strcmp(arg, "") != 0) { @@ -185,14 +187,8 @@ int DetectHttpRawHeaderSetup(DetectEngineCtx *de_ctx, Signature *s, char *arg) return -1; } - if (s->sm_lists_tail[DETECT_SM_LIST_PMATCH] == NULL) { - SCLogError(SC_ERR_INVALID_SIGNATURE, "http_raw_header found inside the " - "rule, without any preceding content keywords"); - return -1; - } - sm = DetectContentGetLastPattern(s->sm_lists_tail[DETECT_SM_LIST_PMATCH]); - /* if still we are unable to find any content previous keywords, it is an + /* if still we are unable to find any previous content keywords, it is an * invalid rule */ if (sm == NULL) { SCLogError(SC_ERR_INVALID_SIGNATURE, "\"http_raw_header\" keyword " @@ -202,59 +198,56 @@ int DetectHttpRawHeaderSetup(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; - } + 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 */ - hrhd = SCMalloc(sizeof(DetectContentData)); - if (hrhd == NULL) { - SCLogError(SC_ERR_MEM_ALLOC, "Error allocating memory"); - exit(EXIT_FAILURE); - } - memset(hrhd, 0, sizeof(DetectContentData)); - - /* transfer the pattern details from the content struct to the clientbody struct */ - DetectContentData *cd = (DetectContentData *)sm->ctx; - hrhd->content = cd->content; - hrhd->content_len = cd->content_len; - hrhd->flags |= cd->flags & DETECT_CONTENT_NOCASE ? DETECT_CONTENT_NOCASE : 0; - hrhd->flags |= cd->flags & DETECT_CONTENT_NEGATED ? DETECT_CONTENT_NEGATED : 0; - //hrhd->id = ((DetectContentData *)sm->ctx)->id; - hrhd->id = DetectPatternGetId(de_ctx->mpm_pattern_id_store, hrhd, 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 *)hrhd; + 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_RAW_HEADER, + s->sm_lists_tail[DETECT_SM_LIST_HRHDMATCH]); + if (pm == NULL) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "http_raw_header seen with a " + "distance or within without a previous http_raw_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_RAW_HEADER); + sm->type = DETECT_AL_HTTP_RAW_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 hrhdmatch list */ + SigMatchTransferSigMatchAcrossLists(sm, + &s->sm_lists[DETECT_SM_LIST_PMATCH], + &s->sm_lists_tail[DETECT_SM_LIST_PMATCH], + &s->sm_lists[DETECT_SM_LIST_HRHDMATCH], + &s->sm_lists_tail[DETECT_SM_LIST_HRHDMATCH]); /* flag the signature to indicate that we scan the app layer data */ s->flags |= SIG_FLAG_APPLAYER; @@ -263,9 +256,9 @@ int DetectHttpRawHeaderSetup(DetectEngineCtx *de_ctx, Signature *s, char *arg) return 0; error: - if (hrhd != NULL) - DetectHttpRawHeaderFree(hrhd); - if(nm != NULL) + if (cd != NULL) + DetectHttpRawHeaderFree(cd); + if (sm != NULL) SCFree(sm); return -1; @@ -302,11 +295,12 @@ static int DetectHttpRawHeaderTest01(void) goto end; } - sm = de_ctx->sig_list->sm_lists[DETECT_SM_LIST_MATCH]; + sm = de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HRHDMATCH]; if (sm != NULL) { - result &= (sm->type == DETECT_AL_HTTP_HEADER); + result &= (sm->type == DETECT_AL_HTTP_RAW_HEADER); result &= (sm->next == NULL); } else { + result = 0; printf("Error updating content pattern to http_header pattern: "); } @@ -1333,13 +1327,13 @@ int DetectHttpRawHeaderTest14(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_HRHDMATCH] == NULL) { + printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HRHDMATCH] == NULL\n"); goto end; } DetectContentData *cd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->ctx; - DetectContentData *hrhd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_AMATCH]->ctx; + DetectContentData *hrhd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHDMATCH]->ctx; if (cd->id == hrhd->id) goto end; @@ -1372,13 +1366,13 @@ int DetectHttpRawHeaderTest15(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_HRHDMATCH] == NULL) { + printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HRHDMATCH] == NULL\n"); goto end; } DetectContentData *cd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->ctx; - DetectContentData *hrhd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_AMATCH]->ctx; + DetectContentData *hrhd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHDMATCH]->ctx; if (cd->id == hrhd->id) goto end; @@ -1411,13 +1405,13 @@ int DetectHttpRawHeaderTest16(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_HRHDMATCH] == NULL) { + printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HRHDMATCH] == NULL\n"); goto end; } DetectContentData *cd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->ctx; - DetectContentData *hrhd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_AMATCH]->ctx; + DetectContentData *hrhd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHDMATCH]->ctx; if (cd->id != 0 || hrhd->id != 1) goto end; @@ -1450,13 +1444,13 @@ int DetectHttpRawHeaderTest17(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_HRHDMATCH] == NULL) { + printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HRHDMATCH] == NULL\n"); goto end; } DetectContentData *cd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->ctx; - DetectContentData *hrhd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_AMATCH]->ctx; + DetectContentData *hrhd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHDMATCH]->ctx; if (cd->id != 1 || hrhd->id != 0) goto end; @@ -1490,14 +1484,14 @@ int DetectHttpRawHeaderTest18(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_HRHDMATCH] == NULL) { + printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HRHDMATCH] == NULL\n"); goto end; } DetectContentData *cd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->ctx; - DetectContentData *hrhd1 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_AMATCH]->ctx; - DetectContentData *hrhd2 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_AMATCH]->prev->ctx; + DetectContentData *hrhd1 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHDMATCH]->ctx; + DetectContentData *hrhd2 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHDMATCH]->prev->ctx; if (cd->id != 1 || hrhd1->id != 0 || hrhd2->id != 0) goto end; @@ -1531,14 +1525,14 @@ int DetectHttpRawHeaderTest19(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_HRHDMATCH] == NULL) { + printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HRHDMATCH] == NULL\n"); goto end; } DetectContentData *cd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->ctx; - DetectContentData *hrhd1 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_AMATCH]->ctx; - DetectContentData *hrhd2 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_AMATCH]->prev->ctx; + DetectContentData *hrhd1 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHDMATCH]->ctx; + DetectContentData *hrhd2 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HRHDMATCH]->prev->ctx; if (cd->id != 2 || hrhd1->id != 0 || hrhd2->id != 0) goto end; diff --git a/src/detect-http-raw-header.h b/src/detect-http-raw-header.h index 5327b5b815..f6b480b2b9 100644 --- a/src/detect-http-raw-header.h +++ b/src/detect-http-raw-header.h @@ -21,10 +21,9 @@ * \author Pablo Rincon */ -#ifndef __DETECT_HTTP_HEADER_H__ -#define __DETECT_HTTP_HEADER_H__ +#ifndef __DETECT_HTTP_RAW_HEADER_H__ +#define __DETECT_HTTP_RAW_HEADER_H__ -void DetectHttpHeaderRegister(void); void DetectHttpRawHeaderRegister(void); -#endif /* __DETECT_HTTP_HEADER_H__ */ +#endif /* __DETECT_HTTP_RAW_HEADER_H__ */ diff --git a/src/detect-nocase.c b/src/detect-nocase.c index 70f87f34bd..0c50eb4ed2 100644 --- a/src/detect-nocase.c +++ b/src/detect-nocase.c @@ -181,11 +181,12 @@ static int DetectNocaseSetup (DetectEngineCtx *de_ctx, Signature *s, char *nulls /* Search for the first previous SigMatch that supports nocase */ //SigMatch *pm = SigMatchGetLastNocasePattern(s); - SigMatch *pm = SigMatchGetLastSMFromLists(s, 12, + SigMatch *pm = SigMatchGetLastSMFromLists(s, 14, DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_PMATCH], DETECT_URICONTENT, s->sm_lists_tail[DETECT_SM_LIST_UMATCH], DETECT_AL_HTTP_CLIENT_BODY, s->sm_lists_tail[DETECT_SM_LIST_HCBDMATCH], DETECT_AL_HTTP_HEADER, s->sm_lists_tail[DETECT_SM_LIST_HHDMATCH], + DETECT_AL_HTTP_RAW_HEADER, s->sm_lists_tail[DETECT_SM_LIST_HRHDMATCH], DETECT_AL_HTTP_COOKIE, s->sm_lists_tail[DETECT_SM_LIST_AMATCH], DETECT_AL_HTTP_METHOD, s->sm_lists_tail[DETECT_SM_LIST_AMATCH]); if (pm == NULL) { @@ -199,6 +200,7 @@ static int DetectNocaseSetup (DetectEngineCtx *de_ctx, Signature *s, char *nulls DetectContentData *dhcb = NULL; DetectContentData *dhcd = NULL; DetectContentData *dhhd = NULL; + DetectContentData *dhrhd = NULL; DetectContentData *dhmd = NULL; switch (pm->type) { @@ -233,6 +235,10 @@ static int DetectNocaseSetup (DetectEngineCtx *de_ctx, Signature *s, char *nulls dhhd =(DetectContentData *) pm->ctx; dhhd->flags |= DETECT_CONTENT_NOCASE; break; + case DETECT_AL_HTTP_RAW_HEADER: + dhrhd =(DetectContentData *) pm->ctx; + dhrhd->flags |= DETECT_CONTENT_NOCASE; + break; case DETECT_AL_HTTP_METHOD: dhmd =(DetectContentData *) pm->ctx; dhmd->flags |= DETECT_CONTENT_NOCASE; diff --git a/src/detect-offset.c b/src/detect-offset.c index 10a6adad8e..4bc90daacc 100644 --- a/src/detect-offset.c +++ b/src/detect-offset.c @@ -80,14 +80,16 @@ int DetectOffsetSetup (DetectEngineCtx *de_ctx, Signature *s, char *offsetstr) break; default: - pm = SigMatchGetLastSMFromLists(s, 8, + pm = SigMatchGetLastSMFromLists(s, 10, 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_HEADER, s->sm_lists_tail[DETECT_SM_LIST_HHDMATCH], + DETECT_AL_HTTP_RAW_HEADER, s->sm_lists_tail[DETECT_SM_LIST_HRHDMATCH]); if (pm == NULL) { SCLogError(SC_ERR_WITHIN_MISSING_CONTENT, "offset needs" - "preceeding content or uricontent option or http_client_body option"); + "preceeding content or uricontent option, http_client_body " + "http_header or http_raw_header option"); if (dubbed) SCFree(str); return -1; @@ -238,6 +240,37 @@ int DetectOffsetSetup (DetectEngineCtx *de_ctx, Signature *s, char *offsetstr) break; + case DETECT_AL_HTTP_RAW_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"); diff --git a/src/detect-within.c b/src/detect-within.c index e9addf652d..6d11bb0fa5 100644 --- a/src/detect-within.c +++ b/src/detect-within.c @@ -169,15 +169,16 @@ static int DetectWithinSetup (DetectEngineCtx *de_ctx, Signature *s, char *withi } } } else { - pm = SigMatchGetLastSMFromLists(s, 8, + pm = SigMatchGetLastSMFromLists(s, 10, 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_HEADER, s->sm_lists_tail[DETECT_SM_LIST_HHDMATCH], + DETECT_AL_HTTP_RAW_HEADER, s->sm_lists_tail[DETECT_SM_LIST_HRHDMATCH]); if (pm == NULL) { SCLogError(SC_ERR_WITHIN_MISSING_CONTENT, "within needs" - "preceeding content, uricontent, http_client_body or " - "http_header option"); + "preceeding content, uricontent, http_client_body, " + "http_header or http_raw_header option"); if (dubbed) SCFree(str); return -1; @@ -465,7 +466,7 @@ static int DetectWithinSetup (DetectEngineCtx *de_ctx, Signature *s, char *withi pm = SigMatchGetLastSMFromLists(s, 2, DETECT_AL_HTTP_HEADER, pm->prev); if (pm == NULL) { - SCLogError(SC_ERR_DISTANCE_MISSING_CONTENT, "distance for http_header_body " + SCLogError(SC_ERR_DISTANCE_MISSING_CONTENT, "distance for http_header " "needs preceeding http_header content"); goto error; } @@ -482,6 +483,53 @@ static int DetectWithinSetup (DetectEngineCtx *de_ctx, Signature *s, char *withi break; + case DETECT_AL_HTTP_RAW_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_RAW_HEADER, pm->prev); + if (pm == NULL) { + SCLogError(SC_ERR_DISTANCE_MISSING_CONTENT, "distance for http_raw_header " + "needs preceeding http_raw_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 " + "has a fast_pattern:only; set. You can't " + "have relative keywords around a fast_pattern " + "only content"); + goto error; + } + cd->flags |= DETECT_CONTENT_RELATIVE_NEXT; + + break; + default: SCLogError(SC_ERR_WITHIN_MISSING_CONTENT, "within needs two " "preceeding content or uricontent options"); diff --git a/src/detect.c b/src/detect.c index d07a2f4088..56a559d668 100644 --- a/src/detect.c +++ b/src/detect.c @@ -117,6 +117,7 @@ #include "detect-http-stat-msg.h" #include "detect-engine-hcbd.h" #include "detect-engine-hhd.h" +#include "detect-engine-hrhd.h" #include "util-rule-vars.h" @@ -695,7 +696,7 @@ static void SigMatchSignaturesBuildMatchArray(DetectEngineCtx *de_ctx, * 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_HHDMATCH) + s->flags & SIG_FLAG_HHDMATCH || s->flags & SIG_FLAG_HRHDMATCH) { /* we run after DeStateDetectContinueDetection, so we might have * state NEW here. In that case we'd want to continue detection @@ -892,6 +893,9 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh det_ctx->de_have_hhd = TRUE; det_ctx->de_mpm_scanned_hhd = FALSE; + det_ctx->de_have_hrhd = TRUE; + det_ctx->de_mpm_scanned_hrhd = FALSE; + SCEnter(); /* No need to perform any detection on this packet, if the the given flag is set.*/ @@ -1190,7 +1194,8 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh s->sm_lists[DETECT_SM_LIST_UMATCH] != NULL || s->sm_lists[DETECT_SM_LIST_DMATCH] != NULL || s->sm_lists[DETECT_SM_LIST_HCBDMATCH] != NULL || - s->sm_lists[DETECT_SM_LIST_HHDMATCH] != NULL) { + s->sm_lists[DETECT_SM_LIST_HHDMATCH] != NULL || + s->sm_lists[DETECT_SM_LIST_HRHDMATCH] != NULL) { if (alstate == NULL) { SCLogDebug("state matches but no state, we can't match"); @@ -1330,6 +1335,7 @@ end: DetectEngineCleanHCBDBuffers(det_ctx); DetectEngineCleanHHDBuffers(det_ctx); + DetectEngineCleanHRHDBuffers(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 @@ -1507,6 +1513,9 @@ int SignatureIsIPOnly(DetectEngineCtx *de_ctx, Signature *s) { if (s->sm_lists[DETECT_SM_LIST_HHDMATCH] != NULL) return 0; + if (s->sm_lists[DETECT_SM_LIST_HRHDMATCH] != NULL) + return 0; + if (s->sm_lists[DETECT_SM_LIST_AMATCH] != NULL) return 0; @@ -1584,6 +1593,9 @@ static int SignatureIsDEOnly(DetectEngineCtx *de_ctx, Signature *s) { if (s->sm_lists[DETECT_SM_LIST_HHDMATCH] != NULL) return 0; + if (s->sm_lists[DETECT_SM_LIST_HRHDMATCH] != NULL) + return 0; + SigMatch *sm = s->sm_lists[DETECT_SM_LIST_MATCH]; /* check for conflicting keywords */ for ( ;sm != NULL; sm = sm->next) { @@ -1681,6 +1693,11 @@ static int SignatureCreateMask(Signature *s) { SCLogDebug("sig requires http app state"); } + if (s->sm_lists[DETECT_SM_LIST_HRHDMATCH] != 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) { @@ -1759,6 +1776,9 @@ static void SigInitStandardMpmFactoryContexts(DetectEngineCtx *de_ctx) de_ctx->sgh_mpm_context_hhd = MpmFactoryRegisterMpmCtxProfile("hhd", MPM_CTX_FACTORY_FLAGS_PREPARE_WITH_SIG_GROUP_BUILD); + de_ctx->sgh_mpm_context_hrhd = + MpmFactoryRegisterMpmCtxProfile("hrhd", + MPM_CTX_FACTORY_FLAGS_PREPARE_WITH_SIG_GROUP_BUILD); de_ctx->sgh_mpm_context_app_proto_detect = MpmFactoryRegisterMpmCtxProfile("app_proto_detect", 0); @@ -3719,6 +3739,12 @@ int SigGroupBuild (DetectEngineCtx *de_ctx) { } //printf("hhd- %d\n", mpm_ctx->pattern_cnt); + mpm_ctx = MpmFactoryGetMpmCtxForProfile(de_ctx->sgh_mpm_context_hrhd); + if (mpm_table[de_ctx->mpm_matcher].Prepare != NULL) { + mpm_table[de_ctx->mpm_matcher].Prepare(mpm_ctx); + } + //printf("hrhd- %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 65bb0b0b56..66a3a976e5 100644 --- a/src/detect.h +++ b/src/detect.h @@ -235,21 +235,24 @@ typedef struct DetectPort_ { #define SIG_FLAG_DMATCH 0x00100000 #define SIG_FLAG_HCBDMATCH 0x00200000 #define SIG_FLAG_HHDMATCH 0x00400000 +#define SIG_FLAG_HRHDMATCH 0x00800000 -#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_MPM_PACKET 0x01000000 +#define SIG_FLAG_MPM_PACKET_NEG 0x02000000 +#define SIG_FLAG_MPM_STREAM 0x04000000 +#define SIG_FLAG_MPM_STREAM_NEG 0x08000000 +#define SIG_FLAG_MPM_URICONTENT 0x10000000 +#define SIG_FLAG_MPM_URICONTENT_NEG 0x20000000 -#define SIG_FLAG_HAS_NO_PKT_AND_STREAM_CONTENT 0x80000000 +#define SIG_FLAG_HAS_NO_PKT_AND_STREAM_CONTENT 0x40000000 /* 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_MPM_HHDCONTENT 0x00000001 +#define SIG_FLAG_MPM_HHDCONTENT_NEG 0x00000002 +#define SIG_FLAG_MPM_HRHDCONTENT 0x00000004 +#define SIG_FLAG_MPM_HRHDCONTENT_NEG 0x00000008 +#define SIG_FLAG_MPM_HCBDCONTENT 0x00000010 +#define SIG_FLAG_MPM_HCBDCONTENT_NEG 0x00000020 /* signature mask flags */ @@ -371,6 +374,7 @@ typedef struct Signature_ { PatIntId mpm_uripattern_id; PatIntId mpm_hcbdpattern_id; PatIntId mpm_hhdpattern_id; + PatIntId mpm_hrhdpattern_id; /* the fast pattern added from this signature */ SigMatch *mpm_sm; @@ -638,6 +642,7 @@ typedef struct DetectEngineCtx_ { int32_t sgh_mpm_context_uri; int32_t sgh_mpm_context_hcbd; int32_t sgh_mpm_context_hhd; + int32_t sgh_mpm_context_hrhd; int32_t sgh_mpm_context_app_proto_detect; /** sgh for signatures that match against invalid packets. In those cases @@ -689,6 +694,10 @@ typedef struct DetectionEngineThreadCtx_ { char de_have_hhd; char de_mpm_scanned_hhd; + /* detectione engine context for hrhd mpm */ + char de_have_hrhd; + char de_mpm_scanned_hrhd; + uint8_t **hcbd_buffers; uint32_t *hcbd_buffers_len; uint16_t hcbd_buffers_list_len; @@ -697,6 +706,10 @@ typedef struct DetectionEngineThreadCtx_ { uint32_t *hhd_buffers_len; uint16_t hhd_buffers_list_len; + uint8_t **hrhd_buffers; + uint32_t *hrhd_buffers_len; + uint16_t hrhd_buffers_list_len; + /** id for alert counter */ uint16_t counter_alerts; @@ -789,11 +802,12 @@ typedef struct SigTableElmt_ { #define SIG_GROUP_HAVESTREAMCONTENT 0x0004 #define SIG_GROUP_HAVEHCBDCONTENT 0x0008 #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 */ +#define SIG_GROUP_HAVEHRHDCONTENT 0x0020 +#define SIG_GROUP_HEAD_MPM_COPY 0x0040 +#define SIG_GROUP_HEAD_MPM_URI_COPY 0x0080 +#define SIG_GROUP_HEAD_MPM_STREAM_COPY 0x0100 +#define SIG_GROUP_HEAD_FREE 0x0200 +#define SIG_GROUP_HEAD_REFERENCED 0x0400 /**< sgh is being referenced by others, don't clear */ typedef struct SigGroupHeadInitData_ { /* list of content containers @@ -837,6 +851,7 @@ typedef struct SigGroupHead_ { MpmCtx *mpm_uri_ctx; MpmCtx *mpm_hcbd_ctx; MpmCtx *mpm_hhd_ctx; + MpmCtx *mpm_hrhd_ctx; uint16_t mpm_uricontent_maxlen; uint16_t pad1; #if __WORDSIZE == 64 diff --git a/src/suricata.c b/src/suricata.c index ec957345f8..035f398795 100644 --- a/src/suricata.c +++ b/src/suricata.c @@ -55,6 +55,7 @@ #include "detect-engine-uri.h" #include "detect-engine-hcbd.h" #include "detect-engine-hhd.h" +#include "detect-engine-hrhd.h" #include "detect-engine-state.h" #include "detect-engine-tag.h" #include "detect-fast-pattern.h" @@ -971,6 +972,7 @@ int main(int argc, char **argv) MemcmpRegisterTests(); DetectEngineHttpClientBodyRegisterTests(); DetectEngineHttpHeaderRegisterTests(); + DetectEngineHttpRawHeaderRegisterTests(); DetectEngineRegisterTests(); SCLogRegisterTests(); if (list_unittests) { diff --git a/src/util-memcmp.h b/src/util-memcmp.h index ba44e078cd..37078e4d19 100644 --- a/src/util-memcmp.h +++ b/src/util-memcmp.h @@ -206,101 +206,101 @@ static inline int SCMemcmpLowercase(void *s1, void *s2, size_t len) { -#elif defined(__SSE3__) - -#include /* for SSE3 */ - -#define SCMEMCMP_BYTES 16 - -static inline int SCMemcmp(void *s1, void *s2, size_t len) { - size_t offset = 0; - __m128i b1, b2, c; - - do { - /* do unaligned loads using _mm_loadu_si128. On my Core2 E6600 using - * _mm_lddqu_si128 was about 2% slower even though it's supposed to - * be faster. */ - b1 = _mm_loadu_si128((const __m128i *) s1); - b2 = _mm_loadu_si128((const __m128i *) s2); - c = _mm_cmpeq_epi8(b1, b2); - - int diff = len - offset; - if (diff < 16) { - int rmask = ~(0xFFFFFFFF << diff); - - if ((_mm_movemask_epi8(c) & rmask) != rmask) { - return 1; - } - } else { - if (_mm_movemask_epi8(c) != 0x0000FFFF) { - return 1; - } - } - - offset += SCMEMCMP_BYTES; - s1 += SCMEMCMP_BYTES; - s2 += SCMEMCMP_BYTES; - } while (len > offset); - - return 0; -} - -#define UPPER_LOW 0x40 /* "A" - 1 */ -#define UPPER_HIGH 0x5B /* "Z" + 1 */ -#define UPPER_DELTA 0xDF /* 0xFF - 0x20 */ - -static inline int SCMemcmpLowercase(void *s1, void *s2, size_t len) { - size_t offset = 0; - __m128i b1, b2, mask1, mask2, upper1, upper2, delta; - - /* setup registers for upper to lower conversion */ - upper1 = _mm_set1_epi8(UPPER_LOW); - upper2 = _mm_set1_epi8(UPPER_HIGH); - delta = _mm_set1_epi8(UPPER_DELTA); - - do { - /* unaligned loading of the bytes to compare */ - b1 = _mm_loadu_si128((const __m128i *) s1); - b2 = _mm_loadu_si128((const __m128i *) s2); - - /* mark all chars bigger than upper1 */ - mask1 = _mm_cmpgt_epi8(b2, upper1); - /* mark all chars lower than upper2 */ - mask2 = _mm_cmplt_epi8(b2, upper2); - /* merge the two, leaving only those that are true in both */ - mask1 = _mm_cmpeq_epi8(mask1, mask2); - - /* sub delta leaves 0x20 only for uppercase positions, the - rest is 0x00 due to the saturation (reuse mask1 reg)*/ - mask1 = _mm_subs_epu8(mask1, delta); - - /* add to b2, converting uppercase to lowercase */ - b2 = _mm_add_epi8(b2, mask1); - - /* now all is lowercase, let's do the actual compare (reuse mask1 reg) */ - mask1 = _mm_cmpeq_epi8(b1, b2); - - int diff = len - offset; - if (diff < 16) { - int rmask = ~(0xFFFFFFFF << diff); - - if ((_mm_movemask_epi8(mask1) & rmask) != rmask) { - return 1; - } - } else { - if (_mm_movemask_epi8(mask1) != 0x0000FFFF) { - return 1; - } - } - - offset += SCMEMCMP_BYTES; - s1 += SCMEMCMP_BYTES; - s2 += SCMEMCMP_BYTES; - } while (len > offset); - - return 0; -} - +//#elif defined(__SSE3__) +// +//#include /* for SSE3 */ +// +//#define SCMEMCMP_BYTES 16 +// +//static inline int SCMemcmp(void *s1, void *s2, size_t len) { +// size_t offset = 0; +// __m128i b1, b2, c; +// +// do { +// /* do unaligned loads using _mm_loadu_si128. On my Core2 E6600 using +// * _mm_lddqu_si128 was about 2% slower even though it's supposed to +// * be faster. */ +// b1 = _mm_loadu_si128((const __m128i *) s1); +// b2 = _mm_loadu_si128((const __m128i *) s2); +// c = _mm_cmpeq_epi8(b1, b2); +// +// int diff = len - offset; +// if (diff < 16) { +// int rmask = ~(0xFFFFFFFF << diff); +// +// if ((_mm_movemask_epi8(c) & rmask) != rmask) { +// return 1; +// } +// } else { +// if (_mm_movemask_epi8(c) != 0x0000FFFF) { +// return 1; +// } +// } +// +// offset += SCMEMCMP_BYTES; +// s1 += SCMEMCMP_BYTES; +// s2 += SCMEMCMP_BYTES; +// } while (len > offset); +// +// return 0; +//} +// +//#define UPPER_LOW 0x40 /* "A" - 1 */ +//#define UPPER_HIGH 0x5B /* "Z" + 1 */ +//#define UPPER_DELTA 0xDF /* 0xFF - 0x20 */ +// +//static inline int SCMemcmpLowercase(void *s1, void *s2, size_t len) { +// size_t offset = 0; +// __m128i b1, b2, mask1, mask2, upper1, upper2, delta; +// +// /* setup registers for upper to lower conversion */ +// upper1 = _mm_set1_epi8(UPPER_LOW); +// upper2 = _mm_set1_epi8(UPPER_HIGH); +// delta = _mm_set1_epi8(UPPER_DELTA); +// +// do { +// /* unaligned loading of the bytes to compare */ +// b1 = _mm_loadu_si128((const __m128i *) s1); +// b2 = _mm_loadu_si128((const __m128i *) s2); +// +// /* mark all chars bigger than upper1 */ +// mask1 = _mm_cmpgt_epi8(b2, upper1); +// /* mark all chars lower than upper2 */ +// mask2 = _mm_cmplt_epi8(b2, upper2); +// /* merge the two, leaving only those that are true in both */ +// mask1 = _mm_cmpeq_epi8(mask1, mask2); +// +// /* sub delta leaves 0x20 only for uppercase positions, the +// rest is 0x00 due to the saturation (reuse mask1 reg)*/ +// mask1 = _mm_subs_epu8(mask1, delta); +// +// /* add to b2, converting uppercase to lowercase */ +// b2 = _mm_add_epi8(b2, mask1); +// +// /* now all is lowercase, let's do the actual compare (reuse mask1 reg) */ +// mask1 = _mm_cmpeq_epi8(b1, b2); +// +// int diff = len - offset; +// if (diff < 16) { +// int rmask = ~(0xFFFFFFFF << diff); +// +// if ((_mm_movemask_epi8(mask1) & rmask) != rmask) { +// return 1; +// } +// } else { +// if (_mm_movemask_epi8(mask1) != 0x0000FFFF) { +// return 1; +// } +// } +// +// offset += SCMEMCMP_BYTES; +// s1 += SCMEMCMP_BYTES; +// s2 += SCMEMCMP_BYTES; +// } while (len > offset); +// +// return 0; +//} +// #else /* No SIMD support, fall back to plain memcmp and a home grown lowercase one */