remove all old content inspection engines and references to them. We have cleaned the entire content inspection phase and improved alert accuracy

remotes/origin/HEAD
Anoop Saldanha 15 years ago committed by Victor Julien
parent 35f1f7e8d9
commit d1d5507679

@ -29,7 +29,6 @@
#include "detect.h"
#include "detect-engine.h"
#include "detect-parse.h"
#include "detect-content.h"
#include "detect-pcre.h"
#include "detect-isdataat.h"
#include "detect-bytetest.h"
@ -37,436 +36,14 @@
#include "detect-byte-extract.h"
#include "detect-engine-content-inspection.h"
#include "util-spm.h"
#include "util-spm-bm.h"
#include "stream-tcp-reassemble.h"
#include "stream-tcp.h"
#include "app-layer.h"
#include "app-layer-dcerpc.h"
#include "decode-tcp.h"
#include "flow-util.h"
#include "util-debug.h"
#include "util-unittest.h"
#include "util-unittest-helper.h"
/**
* \brief Run the dce stub match functions for the dce stub based keywords.
*
* The following keywords are inspected:
* - content
* - isdaatat
* - pcre
* - bytejump
* - bytetest
*
* All keywords are evaluated against the dce stub data.
*
* For accounting the last match in relative matching,
* 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 f Flow
* \param payload Pointer to the dce stub to inspect.
* \param payload_len Length of the payload
*
* \retval 0 No match.
* \retval 1 Match.
*/
static int DoInspectDcePayload(DetectEngineCtx *de_ctx,
DetectEngineThreadCtx *det_ctx, Signature *s,
SigMatch *sm, Flow *f, uint8_t *stub,
uint32_t stub_len, DCERPCState *dcerpc_state)
{
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 || stub_len == 0) {
SCReturnInt(0);
}
switch(sm->type) {
case DETECT_CONTENT:
{
DetectContentData *cd = NULL;
cd = (DetectContentData *)sm->ctx;
SCLogDebug("inspecting content %"PRIu32" stub_len %"PRIu32,
cd->id, stub_len);
/* rule parsers should take care of this */
#ifdef DEBUG
BUG_ON(cd->depth != 0 && cd->depth <= cd->offset);
#endif
/* 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 = stub_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 = stub_len;
int distance = cd->distance;
if (cd->flags & DETECT_CONTENT_DISTANCE) {
if (cd->flags & DETECT_CONTENT_DISTANCE_BE) {
distance = det_ctx->bj_values[cd->distance];
}
if (distance < 0 && (uint32_t)(abs(distance)) > offset)
offset = 0;
else
offset += distance;
SCLogDebug("cd->distance %"PRIi32", offset %"PRIu32", depth %"PRIu32,
cd->distance, offset, depth);
}
if (cd->flags & DETECT_CONTENT_WITHIN) {
if (cd->flags & DETECT_CONTENT_WITHIN_BE) {
if ((int32_t)depth > (int32_t)(prev_payload_offset + det_ctx->bj_values[cd->within] + distance)) {
depth = prev_payload_offset + det_ctx->bj_values[cd->within] + distance;
}
} else {
if ((int32_t)depth > (int32_t)(prev_payload_offset + cd->within + distance)) {
depth = prev_payload_offset + cd->within + distance;
}
SCLogDebug("cd->within %"PRIi32", prev_payload_offset "
"%"PRIu32", depth %"PRIu32, cd->within,
prev_payload_offset, depth);
}
}
if (cd->flags & DETECT_CONTENT_DEPTH_BE) {
if ((det_ctx->bj_values[cd->depth] + prev_payload_offset) < depth) {
depth = prev_payload_offset + det_ctx->bj_values[cd->depth];
}
} else {
if (cd->depth != 0) {
if ((cd->depth + prev_payload_offset) < depth) {
depth = prev_payload_offset + cd->depth;
}
SCLogDebug("cd->depth %"PRIu32", depth %"PRIu32,
cd->depth, depth);
}
}
if (cd->flags & DETECT_CONTENT_OFFSET_BE) {
if (det_ctx->bj_values[cd->offset] > offset)
offset = det_ctx->bj_values[cd->offset];
} else {
if (cd->offset > offset) {
offset = cd->offset;
SCLogDebug("setting offset %"PRIu32, offset);
}
}
/* implied no relative matches */
} else {
/* set depth */
if (cd->flags & DETECT_CONTENT_DEPTH_BE) {
depth = det_ctx->bj_values[cd->depth];
} else {
if (cd->depth != 0) {
depth = cd->depth;
}
}
/* set offset */
if (cd->flags & DETECT_CONTENT_OFFSET_BE)
offset = det_ctx->bj_values[cd->offset];
else
offset = cd->offset;
prev_payload_offset = 0;
}
/* update offset with prev_offset if we're searching for
* matches after the first occurence. */
SCLogDebug("offset %"PRIu32", prev_offset %"PRIu32, offset,
prev_offset);
if (prev_offset != 0)
offset = prev_offset;
SCLogDebug("offset %"PRIu32", depth %"PRIu32, offset, depth);
if (depth > stub_len)
depth = stub_len;
/* if offset is bigger than depth we can never match on a
* pattern. We can however, "match" on a negated pattern. */
/* \todo why isn't it >= ?. Same question applies for
* detect-engine-dcepayload.c and detect-engine-uri.c */
if (offset > depth || depth == 0) {
if (cd->flags & DETECT_CONTENT_NEGATED) {
goto match;
} else {
SCReturnInt(0);
}
}
uint8_t *sstub = stub + offset;
uint32_t sstub_len = depth - offset;
uint32_t match_offset = 0;
SCLogDebug("sstub_len %"PRIu32, sstub_len);
#ifdef DEBUG
BUG_ON(sstub_len > stub_len);
#endif
/* do the actual search */
if (cd->flags & DETECT_CONTENT_NOCASE) {
found = BoyerMooreNocase(cd->content, cd->content_len, sstub,
sstub_len, cd->bm_ctx->bmGs,
cd->bm_ctx->bmBc);
} else {
found = BoyerMoore(cd->content, cd->content_len, sstub,
sstub_len, cd->bm_ctx->bmGs,
cd->bm_ctx->bmBc);
}
/* next we evaluate the result in combination with the
* negation flag. */
SCLogDebug("found %p cd negated %s", found,
cd->flags & DETECT_CONTENT_NEGATED ? "true" : "false");
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) {
SCLogDebug("content %"PRIu32" matched at offset %"PRIu32", but "
"negated so no match", cd->id, match_offset);
det_ctx->discontinue_matching = 1;
SCReturnInt(0);
} else {
match_offset = (uint32_t)((found - stub) + cd->content_len);
SCLogDebug("content %"PRIu32" matched at offset %"PRIu32"",
cd->id, match_offset);
det_ctx->payload_offset = match_offset;
if (!(cd->flags & DETECT_CONTENT_RELATIVE_NEXT)) {
SCLogDebug("no relative match coming up, so this is a match");
goto match;
}
/* bail out if we have no next match. Technically this is an
* error, as the current cd has the DETECT_CONTENT_RELATIVE_NEXT
* flag set. */
if (sm->next == NULL) {
SCReturnInt(0);
}
SCLogDebug("content %"PRIu32, cd->id);
/* see if the next payload keywords match. If not, we will
* search for another occurence of this content and see
* if the others match then until we run out of matches */
int r = DoInspectDcePayload(de_ctx, det_ctx, s, sm->next,
f, stub, stub_len, dcerpc_state);
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);
}
case DETECT_ISDATAAT:
{
SCLogDebug("inspecting isdataat");
DetectIsdataatData *id = (DetectIsdataatData *)sm->ctx;
if (id->flags & ISDATAAT_RELATIVE) {
if (det_ctx->payload_offset + id->dataat > stub_len) {
SCLogDebug("det_ctx->payload_offset + id->dataat "
"%"PRIu32" > %"PRIu32,
det_ctx->payload_offset + id->dataat, stub_len);
SCReturnInt(0);
} else {
SCLogDebug("relative isdataat match");
goto match;
}
} else {
if (id->dataat < stub_len) {
SCLogDebug("absolute isdataat match");
goto match;
} else {
SCLogDebug("absolute isdataat mismatch, id->isdataat %"PRIu32", "
"stub_len %"PRIu32"", id->dataat, stub_len);
SCReturnInt(0);
}
}
}
case DETECT_PCRE:
{
SCLogDebug("inspecting pcre");
DetectPcreData *pe = (DetectPcreData *)sm->ctx;
uint32_t prev_payload_offset = det_ctx->payload_offset;
uint32_t prev_offset = 0;
int r = 0;
det_ctx->pcre_match_start_offset = 0;
do {
r = DetectPcrePayloadMatch(det_ctx, s, sm, NULL, f,
stub, stub_len);
if (r == 0) {
det_ctx->discontinue_matching = 1;
SCReturnInt(0);
}
if (!(pe->flags & DETECT_PCRE_RELATIVE_NEXT)) {
SCLogDebug("no relative match coming up, so this is a match");
goto match;
}
/* save it, in case we need to do a pcre match once again */
prev_offset = det_ctx->pcre_match_start_offset;
/* see if the next payload keywords match. If not, we will
* search for another occurence of this pcre and see
* if the others match, until we run out of matches */
r = DoInspectDcePayload(de_ctx, det_ctx, s, sm->next, f, stub,
stub_len, dcerpc_state);
if (r == 1) {
SCReturnInt(1);
}
if (det_ctx->discontinue_matching)
SCReturnInt(0);
det_ctx->payload_offset = prev_payload_offset;
det_ctx->pcre_match_start_offset = prev_offset;
} while (1);
}
case DETECT_BYTETEST:
{
DetectBytetestData *data = (DetectBytetestData *)sm->ctx;
uint8_t flags = data->flags;
int32_t offset = data->offset;;
uint64_t value = data->value;
if (flags & DETECT_BYTETEST_OFFSET_BE) {
offset = det_ctx->bj_values[offset];
}
if (flags & DETECT_BYTETEST_VALUE_BE) {
value = det_ctx->bj_values[value];
}
/* if we have dce enabled we will have to use the endianness
* specified by the dce header */
if (flags & DETECT_BYTETEST_DCE) {
/* enable the endianness flag temporarily. once we are done
* processing we reset the flags to the original value*/
flags |= ((dcerpc_state->dcerpc.dcerpchdr.packed_drep[0] & 0x10) ?
DETECT_BYTETEST_LITTLE: 0);
}
if (DetectBytetestDoMatch(det_ctx, s, sm, stub, stub_len, flags, offset, value) != 1) {
SCReturnInt(0);
}
goto match;
}
case DETECT_BYTEJUMP:
{
DetectBytejumpData *data = (DetectBytejumpData *)sm->ctx;
uint8_t flags = data->flags;
int32_t offset = data->offset;;
if (flags & DETECT_BYTEJUMP_OFFSET_BE) {
offset = det_ctx->bj_values[offset];
}
/* if we have dce enabled we will have to use the endianness
* specified by the dce header */
if (flags & DETECT_BYTEJUMP_DCE) {
/* enable the endianness flag temporarily. once we are done
* processing we reset the flags to the original value*/
flags |= ((dcerpc_state->dcerpc.dcerpchdr.packed_drep[0] & 0x10) ?
DETECT_BYTEJUMP_LITTLE : 0);
}
if (DetectBytejumpDoMatch(det_ctx, s, sm, stub, stub_len, flags, offset) != 1) {
SCReturnInt(0);
}
goto match;
}
case DETECT_BYTE_EXTRACT:
{
DetectByteExtractData *bed = (DetectByteExtractData *)sm->ctx;
uint8_t endian = bed->endian;
/* if we have dce enabled we will have to use the endianness
* specified by the dce header */
if (bed->flags & DETECT_BYTE_EXTRACT_FLAG_ENDIAN &&
endian == DETECT_BYTE_EXTRACT_ENDIAN_DCE) {
/* enable the endianness flag temporarily. once we are done
* processing we reset the flags to the original value*/
endian |= ((dcerpc_state->dcerpc.dcerpchdr.packed_drep[0] == 0x10) ?
DETECT_BYTE_EXTRACT_ENDIAN_LITTLE : DETECT_BYTE_EXTRACT_ENDIAN_BIG);
}
if (DetectByteExtractDoMatch(det_ctx, sm, s, stub, stub_len,
&det_ctx->bj_values[bed->local_id], endian) != 1) {
SCReturnInt(0);
}
goto match;
}
/* we should never get here, but bail out just in case */
default:
{
SCLogDebug("sm->type %u", sm->type);
#ifdef DEBUG
BUG_ON(1);
#endif
}
}
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 = DoInspectDcePayload(de_ctx, det_ctx, s, sm->next, f, stub,
stub_len, dcerpc_state);
SCReturnInt(r);
} else {
SCReturnInt(1);
}
}
/**
* \brief Do the content inspection & validation for a signature against dce stub.
*

@ -40,24 +40,13 @@
#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 "detect-engine-content-inspection.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"
@ -66,248 +55,6 @@
#include "app-layer-htp.h"
#include "app-layer-protos.h"
/**
* \brief Run the actual payload match function for http request body.
*
* For accounting the last match in relative matching the
* det_ctx->payload_offset int 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 request body to inspect.
* \param payload_len Length of the request body.
*
* \retval 0 no match.
* \retval 1 match.
*/
static int DoInspectHttpClientBody(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_CLIENT_BODY) {
if (payload_len == 0) {
SCReturnInt(0);
}
DetectContentData *cd = (DetectContentData *)sm->ctx;
SCLogDebug("inspecting content %"PRIu32" payload_len %"PRIu32, cd->id, payload_len);
//if (cd->flags & DETECT_CONTENT_HCBD_MPM && !(cd->flags & DETECT_CONTENT_NEGATED))
// goto match;
/* rule parsers should take care of this */
#ifdef DEBUG
BUG_ON(cd->depth != 0 && cd->depth <= cd->offset);
#endif
/* 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 + cd->distance)) {
depth = prev_payload_offset + cd->within + cd->distance;
}
}
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;
#ifdef DEBUG
BUG_ON(spayload_len > payload_len);
#endif
/* do the actual search with boyer moore precooked ctx */
if (cd->flags & DETECT_CONTENT_NOCASE) {
found = BoyerMooreNocase(cd->content, cd->content_len,
spayload, spayload_len,
cd->bm_ctx->bmGs, cd->bm_ctx->bmBc);
} else {
found = BoyerMoore(cd->content, cd->content_len,
spayload, spayload_len,
cd->bm_ctx->bmGs, cd->bm_ctx->bmBc);
}
/* next we evaluate the result in combination with the
* negation flag. */
if (found == NULL && !(cd->flags & DETECT_CONTENT_NEGATED)) {
SCReturnInt(0);
} else if (found == NULL && cd->flags & DETECT_CONTENT_NEGATED) {
goto match;
} else if (found != NULL && cd->flags & DETECT_CONTENT_NEGATED) {
det_ctx->discontinue_matching = 1;
SCReturnInt(0);
} else {
match_offset = (uint32_t)((found - payload) + cd->content_len);
det_ctx->payload_offset = match_offset;
if (!(cd->flags & DETECT_CONTENT_RELATIVE_NEXT)) {
SCLogDebug("no relative match coming up, so this is a match");
goto match;
}
/* bail out if we have no next match. Technically this is an
* error, as the current cd has the DETECT_CONTENT_RELATIVE_NEXT
* flag set. */
if (sm->next == NULL) {
SCReturnInt(0);
}
/* see if the next payload keywords match. If not, we will
* search for another occurence of this http client body content
* and see if the others match then until we run out of matches */
int r = DoInspectHttpClientBody(de_ctx, det_ctx, s, sm->next,
payload, payload_len);
if (r == 1) {
SCReturnInt(1);
}
if (det_ctx->discontinue_matching)
SCReturnInt(0);
/* set the previous match offset to the start of this match + 1 */
prev_offset = (match_offset - (cd->content_len - 1));
SCLogDebug("trying to see if there is another match after "
"prev_offset %"PRIu32, prev_offset);
}
} while(1);
} else if (sm->type == DETECT_PCRE) {
SCLogDebug("inspecting pcre");
DetectPcreData *pe = (DetectPcreData *)sm->ctx;
uint32_t prev_payload_offset = det_ctx->payload_offset;
uint32_t prev_offset = 0;
int r = 0;
det_ctx->pcre_match_start_offset = 0;
do {
r = DetectPcrePayloadMatch(det_ctx, s, sm, NULL, NULL,
payload, payload_len);
if (r == 0) {
det_ctx->discontinue_matching = 1;
SCReturnInt(0);
}
if (!(pe->flags & DETECT_PCRE_RELATIVE_NEXT)) {
SCLogDebug("no relative match coming up, so this is a match");
goto match;
}
/* save it, in case we need to do a pcre match once again */
prev_offset = det_ctx->pcre_match_start_offset;
/* see if the next payload keywords match. If not, we will
* search for another occurence of this pcre and see
* if the others match, until we run out of matches */
int r = DoInspectHttpClientBody(de_ctx, det_ctx, s, sm->next,
payload, payload_len);
if (r == 1) {
SCReturnInt(1);
}
if (det_ctx->discontinue_matching)
SCReturnInt(0);
det_ctx->payload_offset = prev_payload_offset;
det_ctx->pcre_match_start_offset = prev_offset;
} while (1);
} else {
/* we should never get here, but bail out just in case */
SCLogDebug("sm->type %u", sm->type);
#ifdef DEBUG
BUG_ON(1);
#endif
}
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 = DoInspectHttpClientBody(de_ctx, det_ctx, s, sm->next, payload,
payload_len);
SCReturnInt(r);
} else {
SCReturnInt(1);
}
}
/**
* \brief Helps buffer request bodies for different transactions and stores them
* away in detection code.

@ -40,24 +40,13 @@
#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 "detect-engine-content-inspection.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"
@ -66,249 +55,6 @@
#include "app-layer-htp.h"
#include "app-layer-protos.h"
/**
* \brief Run the actual payload match function for http cookie.
*
* For accounting the last match in relative matching the
* det_ctx->payload_offset var is used.
*
* \param de_ctx Detection engine context.
* \param det_ctx Detection engine thread context.
* \param s Signature to inspect.
* \param sm SigMatch to inspect.
* \param payload Ptr to the http cookie buffer to inspect.
* \param payload_len Length of the http cookie buffer.
*
* \retval 0 no match.
* \retval 1 match.
*/
static int DoInspectHttpCookie(DetectEngineCtx *de_ctx,
DetectEngineThreadCtx *det_ctx,
Signature *s, SigMatch *sm,
uint8_t *payload, uint32_t payload_len)
{
SCEnter();
det_ctx->inspection_recursion_counter++;
if (det_ctx->inspection_recursion_counter == de_ctx->inspection_recursion_limit) {
det_ctx->discontinue_matching = 1;
SCReturnInt(0);
}
if (sm == NULL) {
SCReturnInt(0);
}
if (sm->type == DETECT_AL_HTTP_COOKIE) {
if (payload_len == 0) {
SCReturnInt(0);
}
DetectContentData *cd = (DetectContentData *)sm->ctx;
SCLogDebug("inspecting http cookie %"PRIu32" payload_len %"PRIu32,
cd->id, payload_len);
//if (cd->flags & DETECT_CONTENT_HCD_MPM && !(cd->flags & DETECT_CONTENT_NEGATED))
// goto match;
/* rule parsers should take care of this */
#ifdef DEBUG
BUG_ON(cd->depth != 0 && cd->depth <= cd->offset);
#endif
/* 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 + cd->distance)) {
depth = prev_payload_offset + cd->within + cd->distance;
}
}
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;
#ifdef DEBUG
BUG_ON(spayload_len > payload_len);
#endif
/* do the actual search with boyer moore precooked ctx */
if (cd->flags & DETECT_CONTENT_NOCASE) {
found = BoyerMooreNocase(cd->content, cd->content_len,
spayload, spayload_len,
cd->bm_ctx->bmGs, cd->bm_ctx->bmBc);
} else {
found = BoyerMoore(cd->content, cd->content_len,
spayload, spayload_len,
cd->bm_ctx->bmGs, cd->bm_ctx->bmBc);
}
/* next we evaluate the result in combination with the
* negation flag. */
if (found == NULL && !(cd->flags & DETECT_CONTENT_NEGATED)) {
SCReturnInt(0);
} else if (found == NULL && cd->flags & DETECT_CONTENT_NEGATED) {
goto match;
} else if (found != NULL && cd->flags & DETECT_CONTENT_NEGATED) {
det_ctx->discontinue_matching = 1;
SCReturnInt(0);
} else {
match_offset = (uint32_t)((found - payload) + cd->content_len);
det_ctx->payload_offset = match_offset;
if (!(cd->flags & DETECT_CONTENT_RELATIVE_NEXT)) {
SCLogDebug("no relative match coming up, so this is a match");
goto match;
}
/* bail out if we have no next match. Technically this is an
* error, as the current cd has the DETECT_CONTENT_RELATIVE_NEXT
* flag set. */
if (sm->next == NULL) {
SCReturnInt(0);
}
/* see if the next payload keywords match. If not, we will
* search for another occurence of this http cookie content
* and see if the others match then until we run out of matches */
int r = DoInspectHttpCookie(de_ctx, det_ctx, s, sm->next,
payload, payload_len);
if (r == 1) {
SCReturnInt(1);
}
if (det_ctx->discontinue_matching)
SCReturnInt(0);
/* set the previous match offset to the start of this match + 1 */
prev_offset = (match_offset - (cd->content_len - 1));
SCLogDebug("trying to see if there is another match after "
"prev_offset %"PRIu32, prev_offset);
}
} while(1);
} else if (sm->type == DETECT_PCRE_HTTPCOOKIE) {
SCLogDebug("inspecting pcre");
DetectPcreData *pe = (DetectPcreData *)sm->ctx;
uint32_t prev_payload_offset = det_ctx->payload_offset;
uint32_t prev_offset = 0;
int r = 0;
det_ctx->pcre_match_start_offset = 0;
do {
r = DetectPcrePayloadMatch(det_ctx, s, sm, NULL, NULL,
payload, payload_len);
if (r == 0) {
det_ctx->discontinue_matching = 1;
SCReturnInt(0);
}
if (!(pe->flags & DETECT_PCRE_RELATIVE_NEXT)) {
SCLogDebug("no relative match coming up, so this is a match");
goto match;
}
/* save it, in case we need to do a pcre match once again */
prev_offset = det_ctx->pcre_match_start_offset;
/* see if the next payload keywords match. If not, we will
* search for another occurence of this pcre and see
* if the others match, until we run out of matches */
int r = DoInspectHttpCookie(de_ctx, det_ctx, s, sm->next,
payload, payload_len);
if (r == 1) {
SCReturnInt(1);
}
if (det_ctx->discontinue_matching)
SCReturnInt(0);
det_ctx->payload_offset = prev_payload_offset;
det_ctx->pcre_match_start_offset = prev_offset;
} while (1);
} else {
/* we should never get here, but bail out just in case */
SCLogDebug("sm->type %u", sm->type);
#ifdef DEBUG
BUG_ON(1);
#endif
}
SCReturnInt(0);
match:
/* this sigmatch matched, inspect the next one. If it was the last,
* the payload portion of the signature matched. */
if (sm->next != NULL) {
int r = DoInspectHttpCookie(de_ctx, det_ctx, s, sm->next, payload,
payload_len);
SCReturnInt(r);
} else {
SCReturnInt(1);
}
}
int DetectEngineRunHttpCookieMpm(DetectEngineThreadCtx *det_ctx, Flow *f,
HtpState *htp_state, uint8_t flags)
{

@ -40,24 +40,13 @@
#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 "detect-engine-content-inspection.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"
@ -66,249 +55,6 @@
#include "app-layer-htp.h"
#include "app-layer-protos.h"
/**
* \brief Run the actual payload match function for http header.
*
* For accounting the last match in relative matching the
* det_ctx->payload_offset var is used.
*
* \param de_ctx Detection engine context.
* \param det_ctx Detection engine thread context.
* \param s Signature to inspect.
* \param sm SigMatch to inspect.
* \param payload Ptr to the http headers buffer to inspect.
* \param payload_len Length of the http headers buffer.
*
* \retval 0 no match.
* \retval 1 match.
*/
static int DoInspectHttpHeader(DetectEngineCtx *de_ctx,
DetectEngineThreadCtx *det_ctx,
Signature *s, SigMatch *sm,
uint8_t *payload, uint32_t payload_len)
{
SCEnter();
det_ctx->inspection_recursion_counter++;
if (det_ctx->inspection_recursion_counter == de_ctx->inspection_recursion_limit) {
det_ctx->discontinue_matching = 1;
SCReturnInt(0);
}
if (sm == NULL) {
SCReturnInt(0);
}
if (sm->type == DETECT_AL_HTTP_HEADER) {
if (payload_len == 0) {
SCReturnInt(0);
}
DetectContentData *cd = (DetectContentData *)sm->ctx;
SCLogDebug("inspecting http headers %"PRIu32" payload_len %"PRIu32,
cd->id, payload_len);
//if (cd->flags & DETECT_CONTENT_HHD_MPM && !(cd->flags & DETECT_CONTENT_NEGATED))
// goto match;
/* rule parsers should take care of this */
#ifdef DEBUG
BUG_ON(cd->depth != 0 && cd->depth <= cd->offset);
#endif
/* 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 + cd->distance)) {
depth = prev_payload_offset + cd->within + cd->distance;
}
}
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;
#ifdef DEBUG
BUG_ON(spayload_len > payload_len);
#endif
/* do the actual search with boyer moore precooked ctx */
if (cd->flags & DETECT_CONTENT_NOCASE) {
found = BoyerMooreNocase(cd->content, cd->content_len,
spayload, spayload_len,
cd->bm_ctx->bmGs, cd->bm_ctx->bmBc);
} else {
found = BoyerMoore(cd->content, cd->content_len,
spayload, spayload_len,
cd->bm_ctx->bmGs, cd->bm_ctx->bmBc);
}
/* next we evaluate the result in combination with the
* negation flag. */
if (found == NULL && !(cd->flags & DETECT_CONTENT_NEGATED)) {
SCReturnInt(0);
} else if (found == NULL && cd->flags & DETECT_CONTENT_NEGATED) {
goto match;
} else if (found != NULL && cd->flags & DETECT_CONTENT_NEGATED) {
det_ctx->discontinue_matching = 1;
SCReturnInt(0);
} else {
match_offset = (uint32_t)((found - payload) + cd->content_len);
det_ctx->payload_offset = match_offset;
if (!(cd->flags & DETECT_CONTENT_RELATIVE_NEXT)) {
SCLogDebug("no relative match coming up, so this is a match");
goto match;
}
/* bail out if we have no next match. Technically this is an
* error, as the current cd has the DETECT_CONTENT_RELATIVE_NEXT
* flag set. */
if (sm->next == NULL) {
SCReturnInt(0);
}
/* see if the next payload keywords match. If not, we will
* search for another occurence of this http header content and
* see if the others match then until we run out of matches */
int r = DoInspectHttpHeader(de_ctx, det_ctx, s, sm->next,
payload, payload_len);
if (r == 1) {
SCReturnInt(1);
}
if (det_ctx->discontinue_matching)
SCReturnInt(0);
/* set the previous match offset to the start of this match + 1 */
prev_offset = (match_offset - (cd->content_len - 1));
SCLogDebug("trying to see if there is another match after "
"prev_offset %"PRIu32, prev_offset);
}
} while(1);
} else if (sm->type == DETECT_PCRE) {
SCLogDebug("inspecting pcre");
DetectPcreData *pe = (DetectPcreData *)sm->ctx;
uint32_t prev_payload_offset = det_ctx->payload_offset;
uint32_t prev_offset = 0;
int r = 0;
det_ctx->pcre_match_start_offset = 0;
do {
r = DetectPcrePayloadMatch(det_ctx, s, sm, NULL, NULL,
payload, payload_len);
if (r == 0) {
det_ctx->discontinue_matching = 1;
SCReturnInt(0);
}
if (!(pe->flags & DETECT_PCRE_RELATIVE_NEXT)) {
SCLogDebug("no relative match coming up, so this is a match");
goto match;
}
/* save it, in case we need to do a pcre match once again */
prev_offset = det_ctx->pcre_match_start_offset;
/* see if the next payload keywords match. If not, we will
* search for another occurence of this pcre and see
* if the others match, until we run out of matches */
int r = DoInspectHttpHeader(de_ctx, det_ctx, s, sm->next,
payload, payload_len);
if (r == 1) {
SCReturnInt(1);
}
if (det_ctx->discontinue_matching)
SCReturnInt(0);
det_ctx->payload_offset = prev_payload_offset;
det_ctx->pcre_match_start_offset = prev_offset;
} while (1);
} else {
/* we should never get here, but bail out just in case */
SCLogDebug("sm->type %u", sm->type);
#ifdef DEBUG
BUG_ON(1);
#endif
}
SCReturnInt(0);
match:
/* this sigmatch matched, inspect the next one. If it was the last,
* the payload portion of the signature matched. */
if (sm->next != NULL) {
int r = DoInspectHttpHeader(de_ctx, det_ctx, s, sm->next, payload,
payload_len);
SCReturnInt(r);
} else {
SCReturnInt(1);
}
}
/**
* \brief Helps buffer http normalized headers from different transactions and
* stores them away in detection context.

@ -40,24 +40,13 @@
#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 "detect-engine-content-inspection.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"
@ -66,249 +55,6 @@
#include "app-layer-htp.h"
#include "app-layer-protos.h"
/**
* \brief Run the actual payload match function for http method.
*
* For accounting the last match in relative matching the
* det_ctx->payload_offset var is used.
*
* \param de_ctx Detection engine context.
* \param det_ctx Detection engine thread context.
* \param s Signature to inspect.
* \param sm SigMatch to inspect.
* \param payload Ptr to the http method buffer to inspect.
* \param payload_len Length of the http raw headers buffer.
*
* \retval 0 no match.
* \retval 1 match.
*/
static int DoInspectHttpMethod(DetectEngineCtx *de_ctx,
DetectEngineThreadCtx *det_ctx,
Signature *s, SigMatch *sm,
uint8_t *payload, uint32_t payload_len)
{
SCEnter();
det_ctx->inspection_recursion_counter++;
if (det_ctx->inspection_recursion_counter == de_ctx->inspection_recursion_limit) {
det_ctx->discontinue_matching = 1;
SCReturnInt(0);
}
if (sm == NULL) {
SCReturnInt(0);
}
if (sm->type == DETECT_AL_HTTP_METHOD) {
if (payload_len == 0) {
SCReturnInt(0);
}
DetectContentData *cd = (DetectContentData *)sm->ctx;
SCLogDebug("inspecting http method %"PRIu32" payload_len %"PRIu32,
cd->id, payload_len);
//if (cd->flags & DETECT_CONTENT_HMD_MPM && !(cd->flags & DETECT_CONTENT_NEGATED))
// goto match;
/* rule parsers should take care of this */
#ifdef DEBUG
BUG_ON(cd->depth != 0 && cd->depth <= cd->offset);
#endif
/* 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 + cd->distance)) {
depth = prev_payload_offset + cd->within + cd->distance;
}
}
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;
#ifdef DEBUG
BUG_ON(spayload_len > payload_len);
#endif
/* do the actual search with boyer moore precooked ctx */
if (cd->flags & DETECT_CONTENT_NOCASE) {
found = BoyerMooreNocase(cd->content, cd->content_len,
spayload, spayload_len,
cd->bm_ctx->bmGs, cd->bm_ctx->bmBc);
} else {
found = BoyerMoore(cd->content, cd->content_len,
spayload, spayload_len,
cd->bm_ctx->bmGs, cd->bm_ctx->bmBc);
}
/* next we evaluate the result in combination with the
* negation flag. */
if (found == NULL && !(cd->flags & DETECT_CONTENT_NEGATED)) {
SCReturnInt(0);
} else if (found == NULL && cd->flags & DETECT_CONTENT_NEGATED) {
goto match;
} else if (found != NULL && cd->flags & DETECT_CONTENT_NEGATED) {
det_ctx->discontinue_matching = 1;
SCReturnInt(0);
} else {
match_offset = (uint32_t)((found - payload) + cd->content_len);
det_ctx->payload_offset = match_offset;
if (!(cd->flags & DETECT_CONTENT_RELATIVE_NEXT)) {
SCLogDebug("no relative match coming up, so this is a match");
goto match;
}
/* bail out if we have no next match. Technically this is an
* error, as the current cd has the DETECT_CONTENT_RELATIVE_NEXT
* flag set. */
if (sm->next == NULL) {
SCReturnInt(0);
}
/* see if the next payload keywords match. If not, we will
* search for another occurence of this http raw header content
* and see if the others match then until we run out of matches */
int r = DoInspectHttpMethod(de_ctx, det_ctx, s, sm->next,
payload, payload_len);
if (r == 1) {
SCReturnInt(1);
}
if (det_ctx->discontinue_matching)
SCReturnInt(0);
/* set the previous match offset to the start of this match + 1 */
prev_offset = (match_offset - (cd->content_len - 1));
SCLogDebug("trying to see if there is another match after "
"prev_offset %"PRIu32, prev_offset);
}
} while(1);
} else if (sm->type == DETECT_PCRE_HTTPMETHOD) {
SCLogDebug("inspecting pcre");
DetectPcreData *pe = (DetectPcreData *)sm->ctx;
uint32_t prev_payload_offset = det_ctx->payload_offset;
uint32_t prev_offset = 0;
int r = 0;
det_ctx->pcre_match_start_offset = 0;
do {
r = DetectPcrePayloadMatch(det_ctx, s, sm, NULL, NULL,
payload, payload_len);
if (r == 0) {
det_ctx->discontinue_matching = 1;
SCReturnInt(0);
}
if (!(pe->flags & DETECT_PCRE_RELATIVE_NEXT)) {
SCLogDebug("no relative match coming up, so this is a match");
goto match;
}
/* save it, in case we need to do a pcre match once again */
prev_offset = det_ctx->pcre_match_start_offset;
/* see if the next payload keywords match. If not, we will
* search for another occurence of this pcre and see
* if the others match, until we run out of matches */
int r = DoInspectHttpMethod(de_ctx, det_ctx, s, sm->next,
payload, payload_len);
if (r == 1) {
SCReturnInt(1);
}
if (det_ctx->discontinue_matching)
SCReturnInt(0);
det_ctx->payload_offset = prev_payload_offset;
det_ctx->pcre_match_start_offset = prev_offset;
} while (1);
} else {
/* we should never get here, but bail out just in case */
SCLogDebug("sm->type %u", sm->type);
#ifdef DEBUG
BUG_ON(1);
#endif
}
SCReturnInt(0);
match:
/* this sigmatch matched, inspect the next one. If it was the last,
* the payload portion of the signature matched. */
if (sm->next != NULL) {
int r = DoInspectHttpMethod(de_ctx, det_ctx, s, sm->next, payload,
payload_len);
SCReturnInt(r);
} else {
SCReturnInt(1);
}
}
int DetectEngineRunHttpMethodMpm(DetectEngineThreadCtx *det_ctx, Flow *f,
HtpState *htp_state, uint8_t flags)
{

@ -40,24 +40,13 @@
#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 "detect-engine-content-inspection.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"
@ -66,248 +55,6 @@
#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 */
#ifdef DEBUG
BUG_ON(cd->depth != 0 && cd->depth <= cd->offset);
#endif
/* 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 + cd->distance)) {
depth = prev_payload_offset + cd->within + cd->distance;
}
}
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;
#ifdef DEBUG
BUG_ON(spayload_len > payload_len);
#endif
/* do the actual search with boyer moore precooked ctx */
if (cd->flags & DETECT_CONTENT_NOCASE) {
found = BoyerMooreNocase(cd->content, cd->content_len,
spayload, spayload_len,
cd->bm_ctx->bmGs, cd->bm_ctx->bmBc);
} else {
found = BoyerMoore(cd->content, cd->content_len,
spayload, spayload_len,
cd->bm_ctx->bmGs, cd->bm_ctx->bmBc);
}
/* next we evaluate the result in combination with the
* negation flag. */
if (found == NULL && !(cd->flags & DETECT_CONTENT_NEGATED)) {
SCReturnInt(0);
} else if (found == NULL && cd->flags & DETECT_CONTENT_NEGATED) {
goto match;
} else if (found != NULL && cd->flags & DETECT_CONTENT_NEGATED) {
det_ctx->discontinue_matching = 1;
SCReturnInt(0);
} else {
match_offset = (uint32_t)((found - payload) + cd->content_len);
det_ctx->payload_offset = match_offset;
if (!(cd->flags & DETECT_CONTENT_RELATIVE_NEXT)) {
SCLogDebug("no relative match coming up, so this is a match");
goto match;
}
/* bail out if we have no next match. Technically this is an
* error, as the current cd has the DETECT_CONTENT_RELATIVE_NEXT
* flag set. */
if (sm->next == NULL) {
SCReturnInt(0);
}
/* see if the next payload keywords match. If not, we will
* search for another occurence of this http raw header content
* and see if the others match then until we run out of matches */
int r = 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 if (sm->type == DETECT_PCRE) {
SCLogDebug("inspecting pcre");
DetectPcreData *pe = (DetectPcreData *)sm->ctx;
uint32_t prev_payload_offset = det_ctx->payload_offset;
uint32_t prev_offset = 0;
int r = 0;
det_ctx->pcre_match_start_offset = 0;
do {
r = DetectPcrePayloadMatch(det_ctx, s, sm, NULL, NULL,
payload, payload_len);
if (r == 0) {
det_ctx->discontinue_matching = 1;
SCReturnInt(0);
}
if (!(pe->flags & DETECT_PCRE_RELATIVE_NEXT)) {
SCLogDebug("no relative match coming up, so this is a match");
goto match;
}
/* save it, in case we need to do a pcre match once again */
prev_offset = det_ctx->pcre_match_start_offset;
/* see if the next payload keywords match. If not, we will
* search for another occurence of this pcre and see
* if the others match, until we run out of matches */
int r = DoInspectHttpRawHeader(de_ctx, det_ctx, s, sm->next,
payload, payload_len);
if (r == 1) {
SCReturnInt(1);
}
if (det_ctx->discontinue_matching)
SCReturnInt(0);
det_ctx->payload_offset = prev_payload_offset;
det_ctx->pcre_match_start_offset = prev_offset;
} while (1);
} else {
/* we should never get here, but bail out just in case */
SCLogDebug("sm->type %u", sm->type);
#ifdef DEBUG
BUG_ON(1);
#endif
}
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);
}
}
int DetectEngineRunHttpRawHeaderMpm(DetectEngineThreadCtx *det_ctx, Flow *f,
HtpState *htp_state, uint8_t flags)

@ -39,25 +39,13 @@
#include "detect-engine-mpm.h"
#include "detect-parse.h"
#include "detect-engine-state.h"
#include "detect-urilen.h"
#include "detect-pcre.h"
#include "detect-isdataat.h"
#include "detect-bytetest.h"
#include "detect-bytejump.h"
#include "detect-engine-content-inspection.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"
@ -66,309 +54,6 @@
#include "app-layer-htp.h"
#include "app-layer-protos.h"
/**
* \brief Run the actual payload match function for http raw uri.
*
* 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 uri to inspect.
* \param payload_len Length of the http raw uri.
*
* \retval 0 no match.
* \retval 1 match.
*/
static int DoInspectHttpRawUri(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_URI) {
if (payload_len == 0) {
SCReturnInt(0);
}
DetectContentData *cd = (DetectContentData *)sm->ctx;
/* disabled to avoid the FP from inspecting multiple transactions */
//if (cd->flags & DETECT_CONTENT_HRUD_MPM && !(cd->flags & DETECT_CONTENT_NEGATED))
// goto match;
/* rule parsers should take care of this */
#ifdef DEBUG
BUG_ON(cd->depth != 0 && cd->depth <= cd->offset);
#endif
/* 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 + cd->distance)) {
depth = prev_payload_offset + cd->within + cd->distance;
}
}
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;
#ifdef DEBUG
BUG_ON(spayload_len > payload_len);
#endif
/* do the actual search with boyer moore precooked ctx */
if (cd->flags & DETECT_CONTENT_NOCASE) {
found = BoyerMooreNocase(cd->content, cd->content_len,
spayload, spayload_len,
cd->bm_ctx->bmGs, cd->bm_ctx->bmBc);
} else {
found = BoyerMoore(cd->content, cd->content_len,
spayload, spayload_len,
cd->bm_ctx->bmGs, cd->bm_ctx->bmBc);
}
/* next we evaluate the result in combination with the
* negation flag. */
if (found == NULL && !(cd->flags & DETECT_CONTENT_NEGATED)) {
SCReturnInt(0);
} else if (found == NULL && cd->flags & DETECT_CONTENT_NEGATED) {
goto match;
} else if (found != NULL && cd->flags & DETECT_CONTENT_NEGATED) {
det_ctx->discontinue_matching = 1;
SCReturnInt(0);
} else {
match_offset = (uint32_t)((found - payload) + cd->content_len);
det_ctx->payload_offset = match_offset;
if (!(cd->flags & DETECT_CONTENT_RELATIVE_NEXT)) {
SCLogDebug("no relative match coming up, so this is a match");
goto match;
}
/* bail out if we have no next match. Technically this is an
* error, as the current cd has the DETECT_CONTENT_RELATIVE_NEXT
* flag set. */
if (sm->next == NULL) {
SCReturnInt(0);
}
/* see if the next payload keywords match. If not, we will
* search for another occurence of this http header content and
* see if the others match then until we run out of matches */
int r = DoInspectHttpRawUri(de_ctx, det_ctx, s, sm->next,
payload, payload_len);
if (r == 1) {
SCReturnInt(1);
}
if (det_ctx->discontinue_matching)
SCReturnInt(0);
/* set the previous match offset to the start of this match + 1 */
prev_offset = (match_offset - (cd->content_len - 1));
SCLogDebug("trying to see if there is another match after "
"prev_offset %"PRIu32, prev_offset);
}
} while(1);
} else if (sm->type == DETECT_PCRE) {
SCLogDebug("inspecting pcre");
DetectPcreData *pe = (DetectPcreData *)sm->ctx;
uint32_t prev_payload_offset = det_ctx->payload_offset;
uint32_t prev_offset = 0;
int r = 0;
det_ctx->pcre_match_start_offset = 0;
do {
r = DetectPcrePayloadMatch(det_ctx, s, sm, NULL, NULL,
payload, payload_len);
if (r == 0) {
det_ctx->discontinue_matching = 1;
SCReturnInt(0);
}
if (!(pe->flags & DETECT_PCRE_RELATIVE_NEXT)) {
SCLogDebug("no relative match coming up, so this is a match");
goto match;
}
/* save it, in case we need to do a pcre match once again */
prev_offset = det_ctx->pcre_match_start_offset;
/* see if the next payload keywords match. If not, we will
* search for another occurence of this pcre and see
* if the others match, until we run out of matches */
int r = DoInspectHttpRawUri(de_ctx, det_ctx, s, sm->next,
payload, payload_len);
if (r == 1) {
SCReturnInt(1);
}
if (det_ctx->discontinue_matching)
SCReturnInt(0);
det_ctx->payload_offset = prev_payload_offset;
det_ctx->pcre_match_start_offset = prev_offset;
} while (1);
} else if (sm->type == DETECT_ISDATAAT) {
SCLogDebug("inspecting isdataat");
DetectIsdataatData *id = (DetectIsdataatData *)sm->ctx;
if (id->flags & ISDATAAT_RELATIVE) {
if (det_ctx->payload_offset + id->dataat > payload_len) {
SCLogDebug("det_ctx->payload_offset + id->dataat %"PRIu32" > %"PRIu32, det_ctx->payload_offset + id->dataat, payload_len);
if (id->flags & ISDATAAT_NEGATED)
goto match;
SCReturnInt(0);
} else {
SCLogDebug("relative isdataat match");
if (id->flags & ISDATAAT_NEGATED)
SCReturnInt(0);
goto match;
}
} else {
if (id->dataat < payload_len) {
SCLogDebug("absolute isdataat match");
if (id->flags & ISDATAAT_NEGATED)
SCReturnInt(0);
goto match;
} else {
SCLogDebug("absolute isdataat mismatch, id->isdataat %"PRIu32", payload_len %"PRIu32"", id->dataat,payload_len);
if (id->flags & ISDATAAT_NEGATED)
goto match;
SCReturnInt(0);
}
}
} else if (sm->type == DETECT_AL_URILEN) {
SCLogDebug("inspecting uri len");
int r = 0;
DetectUrilenData *urilend = (DetectUrilenData *) sm->ctx;
switch (urilend->mode) {
case DETECT_URILEN_EQ:
if (payload_len == urilend->urilen1)
r = 1;
break;
case DETECT_URILEN_LT:
if (payload_len < urilend->urilen1)
r = 1;
break;
case DETECT_URILEN_GT:
if (payload_len > urilend->urilen1)
r = 1;
break;
case DETECT_URILEN_RA:
if (payload_len > urilend->urilen1 &&
payload_len < urilend->urilen2) {
r = 1;
}
break;
}
if (r == 1) {
goto match;
}
SCReturnInt(0);
} else {
/* we should never get here, but bail out just in case */
SCLogDebug("sm->type %u", sm->type);
#ifdef DEBUG
BUG_ON(1);
#endif
}
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 = DoInspectHttpRawUri(de_ctx, det_ctx, s, sm->next, payload,
payload_len);
SCReturnInt(r);
} else {
SCReturnInt(1);
}
}
/**
* \brief Run the mpm against raw http uris.

@ -41,25 +41,13 @@
#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 "detect-byte-extract.h"
#include "detect-engine-content-inspection.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"
@ -68,321 +56,6 @@
#include "app-layer-htp.h"
#include "app-layer-protos.h"
/**
* \brief Run the actual payload match function for http response body.
*
* For accounting the last match in relative matching the
* det_ctx->payload_offset int 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 response body to inspect.
* \param payload_len Length of the response body.
*
* \retval 0 no match.
* \retval 1 match.
*/
static int DoInspectHttpServerBody(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_SERVER_BODY) {
if (payload_len == 0) {
SCReturnInt(0);
}
DetectContentData *cd = (DetectContentData *)sm->ctx;
SCLogDebug("inspecting content %"PRIu32" payload_len %"PRIu32, cd->id, payload_len);
//if (cd->flags & DETECT_CONTENT_HSBD_MPM && !(cd->flags & DETECT_CONTENT_NEGATED))
// goto match;
/* rule parsers should take care of this */
#ifdef DEBUG
BUG_ON(cd->depth != 0 && cd->depth <= cd->offset);
#endif
/* 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 + cd->distance)) {
depth = prev_payload_offset + cd->within + cd->distance;
}
}
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;
#ifdef DEBUG
BUG_ON(spayload_len > payload_len);
#endif
/* do the actual search with boyer moore precooked ctx */
if (cd->flags & DETECT_CONTENT_NOCASE) {
found = BoyerMooreNocase(cd->content, cd->content_len,
spayload, spayload_len,
cd->bm_ctx->bmGs, cd->bm_ctx->bmBc);
} else {
found = BoyerMoore(cd->content, cd->content_len,
spayload, spayload_len,
cd->bm_ctx->bmGs, cd->bm_ctx->bmBc);
}
/* next we evaluate the result in combination with the
* negation flag. */
if (found == NULL && !(cd->flags & DETECT_CONTENT_NEGATED)) {
SCReturnInt(0);
} else if (found == NULL && cd->flags & DETECT_CONTENT_NEGATED) {
goto match;
} else if (found != NULL && cd->flags & DETECT_CONTENT_NEGATED) {
det_ctx->discontinue_matching = 1;
SCReturnInt(0);
} else {
match_offset = (uint32_t)((found - payload) + cd->content_len);
det_ctx->payload_offset = match_offset;
if (!(cd->flags & DETECT_CONTENT_RELATIVE_NEXT)) {
SCLogDebug("no relative match coming up, so this is a match");
goto match;
}
/* bail out if we have no next match. Technically this is an
* error, as the current cd has the DETECT_CONTENT_RELATIVE_NEXT
* flag set. */
if (sm->next == NULL) {
SCReturnInt(0);
}
/* see if the next payload keywords match. If not, we will
* search for another occurence of this http server body content
* and see if the others match then until we run out of matches */
int r = DoInspectHttpServerBody(de_ctx, det_ctx, s, sm->next,
payload, payload_len);
if (r == 1) {
SCReturnInt(1);
}
if (det_ctx->discontinue_matching)
SCReturnInt(0);
/* set the previous match offset to the start of this match + 1 */
prev_offset = (match_offset - (cd->content_len - 1));
SCLogDebug("trying to see if there is another match after "
"prev_offset %"PRIu32, prev_offset);
}
} while(1);
} else if (sm->type == DETECT_ISDATAAT) {
{
SCLogDebug("inspecting isdataat");
DetectIsdataatData *id = (DetectIsdataatData *)sm->ctx;
if (id->flags & ISDATAAT_RELATIVE) {
if (det_ctx->payload_offset + id->dataat > payload_len) {
SCLogDebug("det_ctx->payload_offset + id->dataat %"PRIu32" > %"PRIu32, det_ctx->payload_offset + id->dataat, payload_len);
if (id->flags & ISDATAAT_NEGATED)
goto match;
SCReturnInt(0);
} else {
SCLogDebug("relative isdataat match");
if (id->flags & ISDATAAT_NEGATED)
SCReturnInt(0);
goto match;
}
} else {
if (id->dataat < payload_len) {
SCLogDebug("absolute isdataat match");
if (id->flags & ISDATAAT_NEGATED)
SCReturnInt(0);
goto match;
} else {
SCLogDebug("absolute isdataat mismatch, id->isdataat %"PRIu32", payload_len %"PRIu32"", id->dataat,payload_len);
if (id->flags & ISDATAAT_NEGATED)
goto match;
SCReturnInt(0);
}
}
}
} else if (sm->type == DETECT_PCRE) {
SCLogDebug("inspecting pcre");
DetectPcreData *pe = (DetectPcreData *)sm->ctx;
uint32_t prev_payload_offset = det_ctx->payload_offset;
uint32_t prev_offset = 0;
int r = 0;
det_ctx->pcre_match_start_offset = 0;
do {
r = DetectPcrePayloadMatch(det_ctx, s, sm, NULL, NULL,
payload, payload_len);
if (r == 0) {
det_ctx->discontinue_matching = 1;
SCReturnInt(0);
}
if (!(pe->flags & DETECT_PCRE_RELATIVE_NEXT)) {
SCLogDebug("no relative match coming up, so this is a match");
goto match;
}
/* save it, in case we need to do a pcre match once again */
prev_offset = det_ctx->pcre_match_start_offset;
/* see if the next payload keywords match. If not, we will
* search for another occurence of this pcre and see
* if the others match, until we run out of matches */
int r = DoInspectHttpServerBody(de_ctx, det_ctx, s, sm->next,
payload, payload_len);
if (r == 1) {
SCReturnInt(1);
}
if (det_ctx->discontinue_matching)
SCReturnInt(0);
det_ctx->payload_offset = prev_payload_offset;
det_ctx->pcre_match_start_offset = prev_offset;
} while (1);
} else if (sm->type == DETECT_BYTETEST) {
DetectBytetestData *btd = (DetectBytetestData *)sm->ctx;
int32_t offset = btd->offset;
uint64_t value = btd->value;
if (btd->flags & DETECT_BYTETEST_OFFSET_BE) {
offset = det_ctx->bj_values[offset];
}
if (btd->flags & DETECT_BYTETEST_VALUE_BE) {
value = det_ctx->bj_values[value];
}
if (DetectBytetestDoMatch(det_ctx,s,sm,payload,payload_len, btd->flags,
offset, value) != 1) {
SCReturnInt(0);
}
goto match;
} else if (sm->type == DETECT_BYTEJUMP) {
DetectBytejumpData *bjd = (DetectBytejumpData *)sm->ctx;
int32_t offset = bjd->offset;
if (bjd->flags & DETECT_BYTEJUMP_OFFSET_BE) {
offset = det_ctx->bj_values[offset];
}
if (DetectBytejumpDoMatch(det_ctx,s,sm,payload,payload_len,
bjd->flags, offset) != 1) {
SCReturnInt(0);
}
goto match;
} else if (sm->type == DETECT_BYTE_EXTRACT) {
DetectByteExtractData *bed = (DetectByteExtractData *)sm->ctx;
if (DetectByteExtractDoMatch(det_ctx, sm, s, payload,
payload_len,
&det_ctx->bj_values[bed->local_id],
bed->endian) != 1) {
SCReturnInt(0);
}
goto match;
} else {
/* we should never get here, but bail out just in case */
SCLogDebug("sm->type %u", sm->type);
#ifdef DEBUG
BUG_ON(1);
#endif
}
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 = DoInspectHttpServerBody(de_ctx, det_ctx, s, sm->next, payload,
payload_len);
SCReturnInt(r);
} else {
SCReturnInt(1);
}
}
/**
* \brief Helps buffer response bodies for different transactions and stores them
* away in detection code.

@ -31,423 +31,14 @@
#include "detect.h"
#include "detect-engine.h"
#include "detect-parse.h"
#include "detect-content.h"
#include "detect-pcre.h"
#include "detect-isdataat.h"
#include "detect-bytetest.h"
#include "detect-bytejump.h"
#include "detect-byte-extract.h"
#include "detect-replace.h"
#include "detect-engine-content-inspection.h"
#include "util-spm.h"
#include "util-spm-bm.h"
#include "util-debug.h"
#include "util-print.h"
#include "util-unittest.h"
#include "util-unittest-helper.h"
/** \brief Run the actual payload match functions
*
* The follwing keywords are inspected:
* - content
* - isdaatat
* - pcre
* - bytejump
* - bytetest
*
* All keywords are evaluated against the payload with payload_len.
*
* For accounting the last match in relative matching the
* det_ctx->payload_offset int 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 f flow (for pcre flowvar storage)
* \param payload ptr to the payload to inspect
* \param payload_len length of the payload
*
* \retval 0 no match
* \retval 1 match
*/
static int DoInspectPacketPayload(DetectEngineCtx *de_ctx,
DetectEngineThreadCtx *det_ctx, Signature *s, SigMatch *sm,
Packet *p, Flow *f, 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 || payload_len == 0) {
SCReturnInt(0);
}
switch(sm->type) {
case DETECT_CONTENT:
{
DetectContentData *cd = (DetectContentData *)sm->ctx;
SCLogDebug("inspecting content %"PRIu32" payload_len %"PRIu32, cd->id, payload_len);
/* we might have already have this content matched by the mpm.
* (if there is any other reason why we'd want to avoid checking
* it here, please fill it in) */
//if (det_ctx->flags & DETECT_ENGINE_THREAD_CTX_INSPECTING_PACKET) {
// if (cd->flags & DETECT_CONTENT_PACKET_MPM && !(cd->flags & DETECT_CONTENT_NEGATED)) {
// /* we will remove this check in the end */
// if (!DETECT_CONTENT_IS_SINGLE(cd))
// abort();
// //goto match;
// }
//} else if (det_ctx->flags & DETECT_ENGINE_THREAD_CTX_INSPECTING_STREAM) {
if (det_ctx->flags & DETECT_ENGINE_THREAD_CTX_INSPECTING_STREAM) {
if (cd->flags & DETECT_CONTENT_STREAM_MPM && !(cd->flags & DETECT_CONTENT_NEGATED)) {
goto match;
}
}
/* rule parsers should take care of this */
#ifdef DEBUG
BUG_ON(cd->depth != 0 && cd->depth <= cd->offset);
#endif
/* 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("det_ctx->payload_offset %"PRIu32, det_ctx->payload_offset);
offset = prev_payload_offset;
depth = payload_len;
int distance = cd->distance;
if (cd->flags & DETECT_CONTENT_DISTANCE) {
if (cd->flags & DETECT_CONTENT_DISTANCE_BE) {
distance = det_ctx->bj_values[cd->distance];
}
if (distance < 0 && (uint32_t)(abs(distance)) > offset)
offset = 0;
else
offset += distance;
SCLogDebug("cd->distance %"PRIi32", offset %"PRIu32", depth %"PRIu32,
distance, offset, depth);
}
if (cd->flags & DETECT_CONTENT_WITHIN) {
if (cd->flags & DETECT_CONTENT_WITHIN_BE) {
if ((int32_t)depth > (int32_t)(prev_payload_offset + det_ctx->bj_values[cd->within] + distance)) {
depth = prev_payload_offset + det_ctx->bj_values[cd->within] + distance;
}
} else {
if ((int32_t)depth > (int32_t)(prev_payload_offset + cd->within + distance)) {
depth = prev_payload_offset + cd->within + distance;
}
SCLogDebug("cd->within %"PRIi32", det_ctx->payload_offset %"PRIu32", depth %"PRIu32,
cd->within, prev_payload_offset, depth);
}
}
if (cd->flags & DETECT_CONTENT_DEPTH_BE) {
if ((det_ctx->bj_values[cd->depth] + prev_payload_offset) < depth) {
depth = prev_payload_offset + det_ctx->bj_values[cd->depth];
}
} else {
if (cd->depth != 0) {
if ((cd->depth + prev_payload_offset) < depth) {
depth = prev_payload_offset + cd->depth;
}
SCLogDebug("cd->depth %"PRIu32", depth %"PRIu32, cd->depth, depth);
}
}
if (cd->flags & DETECT_CONTENT_OFFSET_BE) {
if (det_ctx->bj_values[cd->offset] > offset)
offset = det_ctx->bj_values[cd->offset];
} else {
if (cd->offset > offset) {
offset = cd->offset;
SCLogDebug("setting offset %"PRIu32, offset);
}
}
} else { /* implied no relative matches */
/* set depth */
if (cd->flags & DETECT_CONTENT_DEPTH_BE) {
depth = det_ctx->bj_values[cd->depth];
} else {
if (cd->depth != 0) {
depth = cd->depth;
}
}
/* set offset */
if (cd->flags & DETECT_CONTENT_OFFSET_BE)
offset = det_ctx->bj_values[cd->offset];
else
offset = cd->offset;
prev_payload_offset = 0;
}
/* update offset with prev_offset if we're searching for
* matches after the first occurence. */
SCLogDebug("offset %"PRIu32", prev_offset %"PRIu32, offset, prev_offset);
if (prev_offset != 0)
offset = prev_offset;
SCLogDebug("offset %"PRIu32", depth %"PRIu32, offset, depth);
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;
SCLogDebug("spayload_len %"PRIu32, spayload_len);
#ifdef DEBUG
BUG_ON(spayload_len > payload_len);
#endif
//PrintRawDataFp(stdout,cd->content,cd->content_len);
//PrintRawDataFp(stdout,spayload,spayload_len);
/* \todo Add another optimization here. If cd->content_len is
* greater than spayload_len found is anyways NULL */
/* do the actual search */
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. */
SCLogDebug("found %p cd negated %s", found, cd->flags & DETECT_CONTENT_NEGATED ? "true" : "false");
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) {
SCLogDebug("content %"PRIu32" matched at offset %"PRIu32", but negated so no match", cd->id, match_offset);
/* don't bother carrying recursive matches now, for preceding
* relative keywords */
det_ctx->discontinue_matching = 1;
SCReturnInt(0);
} else {
match_offset = (uint32_t)((found - payload) + cd->content_len);
SCLogDebug("content %"PRIu32" matched at offset %"PRIu32"", cd->id, match_offset);
det_ctx->payload_offset = match_offset;
/* Match branch, add replace to the list if needed */
if (cd->flags & DETECT_CONTENT_REPLACE) {
if (p) {
/* we will need to replace content if match is confirmed */
det_ctx->replist = DetectReplaceAddToList(det_ctx->replist, found, cd);
} else
SCLogWarning(SC_ERR_INVALID_VALUE, "Can't modify payload without packet");
}
if (!(cd->flags & DETECT_CONTENT_RELATIVE_NEXT)) {
SCLogDebug("no relative match coming up, so this is a match");
goto match;
}
/* bail out if we have no next match. Technically this is an
* error, as the current cd has the DETECT_CONTENT_RELATIVE_NEXT
* flag set. */
if (sm->next == NULL) {
SCReturnInt(0);
}
SCLogDebug("content %"PRIu32, cd->id);
/* see if the next payload keywords match. If not, we will
* search for another occurence of this content and see
* if the others match then until we run out of matches */
int r = DoInspectPacketPayload(de_ctx,det_ctx,s,sm->next, p, f, 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);
}
case DETECT_ISDATAAT:
{
SCLogDebug("inspecting isdataat");
DetectIsdataatData *id = (DetectIsdataatData *)sm->ctx;
if (id->flags & ISDATAAT_RELATIVE) {
if (det_ctx->payload_offset + id->dataat > payload_len) {
SCLogDebug("det_ctx->payload_offset + id->dataat %"PRIu32" > %"PRIu32, det_ctx->payload_offset + id->dataat, payload_len);
if (id->flags & ISDATAAT_NEGATED)
goto match;
SCReturnInt(0);
} else {
SCLogDebug("relative isdataat match");
if (id->flags & ISDATAAT_NEGATED)
SCReturnInt(0);
goto match;
}
} else {
if (id->dataat < payload_len) {
SCLogDebug("absolute isdataat match");
if (id->flags & ISDATAAT_NEGATED)
SCReturnInt(0);
goto match;
} else {
SCLogDebug("absolute isdataat mismatch, id->isdataat %"PRIu32", payload_len %"PRIu32"", id->dataat,payload_len);
if (id->flags & ISDATAAT_NEGATED)
goto match;
SCReturnInt(0);
}
}
}
case DETECT_PCRE:
{
SCLogDebug("inspecting pcre");
DetectPcreData *pe = (DetectPcreData *)sm->ctx;
uint32_t prev_payload_offset = det_ctx->payload_offset;
uint32_t prev_offset = 0;
int r = 0;
det_ctx->pcre_match_start_offset = 0;
do {
r = DetectPcrePayloadMatch(det_ctx, s, sm, p, f,
payload, payload_len);
if (r == 0) {
det_ctx->discontinue_matching = 1;
SCReturnInt(0);
}
if (!(pe->flags & DETECT_PCRE_RELATIVE_NEXT)) {
SCLogDebug("no relative match coming up, so this is a match");
goto match;
}
/* save it, in case we need to do a pcre match once again */
prev_offset = det_ctx->pcre_match_start_offset;
/* see if the next payload keywords match. If not, we will
* search for another occurence of this pcre and see
* if the others match, until we run out of matches */
r = DoInspectPacketPayload(de_ctx, det_ctx, s, sm->next, p,
f, payload, payload_len);
if (r == 1) {
SCReturnInt(1);
}
if (det_ctx->discontinue_matching)
SCReturnInt(0);
det_ctx->payload_offset = prev_payload_offset;
det_ctx->pcre_match_start_offset = prev_offset;
} while (1);
}
case DETECT_BYTETEST:
{
DetectBytetestData *btd = (DetectBytetestData *)sm->ctx;
int32_t offset = btd->offset;
uint64_t value = btd->value;
if (btd->flags & DETECT_BYTETEST_OFFSET_BE) {
offset = det_ctx->bj_values[offset];
}
if (btd->flags & DETECT_BYTETEST_VALUE_BE) {
value = det_ctx->bj_values[value];
}
if (DetectBytetestDoMatch(det_ctx,s,sm,payload,payload_len, btd->flags,
offset, value) != 1) {
SCReturnInt(0);
}
goto match;
}
case DETECT_BYTEJUMP:
{
DetectBytejumpData *bjd = (DetectBytejumpData *)sm->ctx;
int32_t offset = bjd->offset;
if (bjd->flags & DETECT_BYTEJUMP_OFFSET_BE) {
offset = det_ctx->bj_values[offset];
}
if (DetectBytejumpDoMatch(det_ctx,s,sm,payload,payload_len,
bjd->flags, offset) != 1) {
SCReturnInt(0);
}
goto match;
}
case DETECT_BYTE_EXTRACT:
{
DetectByteExtractData *bed = (DetectByteExtractData *)sm->ctx;
if (DetectByteExtractDoMatch(det_ctx, sm, s, payload,
payload_len,
&det_ctx->bj_values[bed->local_id],
bed->endian) != 1) {
SCReturnInt(0);
}
goto match;
}
/* we should never get here, but bail out just in case */
default:
{
SCLogDebug("sm->type %u", sm->type);
#ifdef DEBUG
BUG_ON(1);
#endif
}
}
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 = DoInspectPacketPayload(de_ctx,det_ctx,s,sm->next, p, f, payload, payload_len);
SCReturnInt(r);
} else {
SCReturnInt(1);
}
}
/**
* \brief Do the content inspection & validation for a signature
*

@ -31,27 +31,13 @@
#include "detect-engine.h"
#include "detect-parse.h"
#include "detect-engine-state.h"
#include "detect-uricontent.h"
#include "detect-urilen.h"
#include "detect-pcre.h"
#include "detect-isdataat.h"
#include "detect-bytetest.h"
#include "detect-bytejump.h"
#include "detect-byte-extract.h"
#include "detect-engine-content-inspection.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"
@ -60,364 +46,6 @@
#include "app-layer-htp.h"
#include "app-layer-protos.h"
/**
* \brief Run the actual payload match function for uricontent.
*
* For accounting the last match in relative matching the
* det_ctx->payload_offset int 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 uricontent payload to inspect.
* \param payload_len Length of the uricontent payload.
*
* \retval 0 no match.
* \retval 1 match.
*/
static int DoInspectPacketUri(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_URICONTENT) {
if (payload_len == 0) {
SCReturnInt(0);
}
DetectContentData *ud = NULL;
ud = (DetectContentData *)sm->ctx;
SCLogDebug("inspecting content %"PRIu32" payload_len %"PRIu32, ud->id, payload_len);
//if (ud->flags & DETECT_CONTENT_URI_MPM && !(ud->flags & DETECT_CONTENT_NEGATED))
// goto match;
/* rule parsers should take care of this */
#ifdef DEBUG
BUG_ON(ud->depth != 0 && ud->depth <= ud->offset);
#endif
/* 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 (ud->flags & DETECT_CONTENT_DISTANCE ||
ud->flags & DETECT_CONTENT_WITHIN) {
SCLogDebug("prev_payload_offset %"PRIu32, prev_payload_offset);
offset = prev_payload_offset;
depth = payload_len;
int distance = ud->distance;
if (ud->flags & DETECT_CONTENT_DISTANCE) {
if (ud->flags & DETECT_CONTENT_DISTANCE_BE) {
distance = det_ctx->bj_values[ud->distance];
}
if (distance < 0 && (uint32_t)(abs(distance)) > offset)
offset = 0;
else
offset += distance;
SCLogDebug("ud->distance %"PRIi32", offset %"PRIu32", depth %"PRIu32,
distance, offset, depth);
}
if (ud->flags & DETECT_CONTENT_WITHIN) {
if (ud->flags & DETECT_CONTENT_WITHIN_BE) {
if ((int32_t)depth > (int32_t)(prev_payload_offset + det_ctx->bj_values[ud->within] + distance)) {
depth = prev_payload_offset + det_ctx->bj_values[ud->within] + distance;
}
} else {
if ((int32_t)depth > (int32_t)(prev_payload_offset + ud->within + distance)) {
depth = prev_payload_offset + ud->within + distance;
}
SCLogDebug("ud->within %"PRIi32", prev_payload_offset %"PRIu32", depth %"PRIu32,
ud->within, prev_payload_offset, depth);
}
}
if (ud->flags & DETECT_CONTENT_DEPTH_BE) {
if ((det_ctx->bj_values[ud->depth] + prev_payload_offset) < depth) {
depth = prev_payload_offset + det_ctx->bj_values[ud->depth];
}
} else {
if (ud->depth != 0) {
if ((ud->depth + prev_payload_offset) < depth) {
depth = prev_payload_offset + ud->depth;
}
SCLogDebug("ud->depth %"PRIu32", depth %"PRIu32, ud->depth, depth);
}
}
if (ud->flags & DETECT_CONTENT_OFFSET_BE) {
if (det_ctx->bj_values[ud->offset] > offset)
offset = det_ctx->bj_values[ud->offset];
} else {
if (ud->offset > offset) {
offset = ud->offset;
SCLogDebug("setting offset %"PRIu32, offset);
}
}
} else { /* implied no relative matches */
/* set depth */
if (ud->flags & DETECT_CONTENT_DEPTH_BE) {
depth = det_ctx->bj_values[ud->depth];
} else {
if (ud->depth != 0) {
depth = ud->depth;
}
}
/* set offset */
if (ud->flags & DETECT_CONTENT_OFFSET_BE)
offset = det_ctx->bj_values[ud->offset];
else
offset = ud->offset;
prev_payload_offset = 0;
}
/* update offset with prev_offset if we're searching for
* matches after the first occurence. */
SCLogDebug("offset %"PRIu32", prev_offset %"PRIu32, prev_offset, depth);
if (prev_offset != 0)
offset = prev_offset;
SCLogDebug("offset %"PRIu32", depth %"PRIu32, offset, depth);
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 (ud->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;
SCLogDebug("spayload_len %"PRIu32, spayload_len);
#ifdef DEBUG
BUG_ON(spayload_len > payload_len);
#endif
//PrintRawDataFp(stdout,ud->content,ud->content_len);
/* If we got no matches from the mpm, avoid searching (just check if negated) */
//if (det_ctx->de_have_httpuri == TRUE) {
/* do the actual search with boyer moore precooked ctx */
if (ud->flags & DETECT_CONTENT_NOCASE)
found = BoyerMooreNocase(ud->content, ud->content_len, spayload, spayload_len, ud->bm_ctx->bmGs, ud->bm_ctx->bmBc);
else
found = BoyerMoore(ud->content, ud->content_len, spayload, spayload_len, ud->bm_ctx->bmGs, ud->bm_ctx->bmBc);
//} else {
// found = NULL;
//}
/* next we evaluate the result in combination with the
* negation flag. */
SCLogDebug("found %p ud negated %s", found, ud->flags & DETECT_CONTENT_NEGATED ? "true" : "false");
if (found == NULL && !(ud->flags & DETECT_CONTENT_NEGATED)) {
SCReturnInt(0);
} else if (found == NULL && ud->flags & DETECT_CONTENT_NEGATED) {
goto match;
} else if (found != NULL && ud->flags & DETECT_CONTENT_NEGATED) {
SCLogDebug("uricontent %"PRIu32" matched at offset %"PRIu32", but negated so no match", ud->id, match_offset);
det_ctx->discontinue_matching = 1;
SCReturnInt(0);
} else {
match_offset = (uint32_t)((found - payload) + ud->content_len);
SCLogDebug("uricontent %"PRIu32" matched at offset %"PRIu32"", ud->id, match_offset);
det_ctx->payload_offset = match_offset;
if (!(ud->flags & DETECT_CONTENT_RELATIVE_NEXT)) {
SCLogDebug("no relative match coming up, so this is a match");
goto match;
}
/* bail out if we have no next match. Technically this is an
* error, as the current cd has the DETECT_CONTENT_RELATIVE_NEXT
* flag set. */
if (sm->next == NULL) {
SCReturnInt(0);
}
SCLogDebug("uricontent %"PRIu32, ud->id);
/* see if the next payload keywords match. If not, we will
* search for another occurence of this uricontent and see
* if the others match then until we run out of matches */
int r = DoInspectPacketUri(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 - (ud->content_len - 1));
SCLogDebug("trying to see if there is another match after prev_offset %"PRIu32, prev_offset);
}
} while(1);
} else if (sm->type == DETECT_PCRE) {
SCLogDebug("inspecting pcre");
DetectPcreData *pe = (DetectPcreData *)sm->ctx;
uint32_t prev_payload_offset = det_ctx->payload_offset;
uint32_t prev_offset = 0;
int r = 0;
det_ctx->pcre_match_start_offset = 0;
do {
r = DetectPcrePayloadMatch(det_ctx, s, sm, NULL, NULL,
payload, payload_len);
if (r == 0) {
det_ctx->discontinue_matching = 1;
SCReturnInt(0);
}
if (!(pe->flags & DETECT_PCRE_RELATIVE_NEXT)) {
SCLogDebug("no relative match coming up, so this is a match");
goto match;
}
/* save it, in case we need to do a pcre match once again */
prev_offset = det_ctx->pcre_match_start_offset;
/* see if the next payload keywords match. If not, we will
* search for another occurence of this pcre and see
* if the others match, until we run out of matches */
r = DoInspectPacketUri(de_ctx, det_ctx, s, sm->next,
payload, payload_len);
if (r == 1) {
SCReturnInt(1);
}
if (det_ctx->discontinue_matching)
SCReturnInt(0);
det_ctx->payload_offset = prev_payload_offset;
det_ctx->pcre_match_start_offset = prev_offset;
} while (1);
} else if (sm->type == DETECT_ISDATAAT) {
SCLogDebug("inspecting isdataat");
DetectIsdataatData *id = (DetectIsdataatData *)sm->ctx;
if (id->flags & ISDATAAT_RELATIVE) {
if (det_ctx->payload_offset + id->dataat > payload_len) {
SCLogDebug("det_ctx->payload_offset + id->dataat %"PRIu32" > %"PRIu32, det_ctx->payload_offset + id->dataat, payload_len);
if (id->flags & ISDATAAT_NEGATED)
goto match;
SCReturnInt(0);
} else {
SCLogDebug("relative isdataat match");
if (id->flags & ISDATAAT_NEGATED)
SCReturnInt(0);
goto match;
}
} else {
if (id->dataat < payload_len) {
SCLogDebug("absolute isdataat match");
if (id->flags & ISDATAAT_NEGATED)
SCReturnInt(0);
goto match;
} else {
SCLogDebug("absolute isdataat mismatch, id->isdataat %"PRIu32", payload_len %"PRIu32"", id->dataat,payload_len);
if (id->flags & ISDATAAT_NEGATED)
goto match;
SCReturnInt(0);
}
}
} else if (sm->type == DETECT_AL_URILEN) {
SCLogDebug("inspecting uri len");
int r = 0;
DetectUrilenData *urilend = (DetectUrilenData *) sm->ctx;
switch (urilend->mode) {
case DETECT_URILEN_EQ:
if (payload_len == urilend->urilen1)
r = 1;
break;
case DETECT_URILEN_LT:
if (payload_len < urilend->urilen1)
r = 1;
break;
case DETECT_URILEN_GT:
if (payload_len > urilend->urilen1)
r = 1;
break;
case DETECT_URILEN_RA:
if (payload_len > urilend->urilen1 &&
payload_len < urilend->urilen2) {
r = 1;
}
break;
}
if (r == 1) {
goto match;
}
SCReturnInt(0);
} else if (sm->type == DETECT_BYTE_EXTRACT) {
DetectByteExtractData *bed = (DetectByteExtractData *)sm->ctx;
if (DetectByteExtractDoMatch(det_ctx, sm, s, payload,
payload_len,
&det_ctx->bj_values[bed->local_id],
bed->endian) != 1) {
SCReturnInt(0);
}
goto match;
} else {
/* we should never get here, but bail out just in case */
SCLogDebug("sm->type %u", sm->type);
#ifdef DEBUG
BUG_ON(1);
#endif
}
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 = DoInspectPacketUri(de_ctx, det_ctx, s, sm->next, payload,
payload_len);
SCReturnInt(r);
} else {
SCReturnInt(1);
}
}
/** \brief Do the content inspection & validation for a signature
*
* \param de_ctx Detection engine context

Loading…
Cancel
Save