remove det_ctx->payload_offset and use det_ctx->buffer_offset. Update hscd and hsmd to use the new generic content inspection engine

remotes/origin/HEAD
Anoop Saldanha 14 years ago committed by Victor Julien
parent d1d5507679
commit 603d4a719a

@ -152,11 +152,11 @@ int DetectByteExtractDoMatch(DetectEngineThreadCtx *det_ctx, SigMatch *sm,
* the packet from that point.
*/
if (data->flags & DETECT_BYTE_EXTRACT_FLAG_RELATIVE) {
SCLogDebug("relative, working with det_ctx->payload_offset %"PRIu32", "
"data->offset %"PRIu32"", det_ctx->payload_offset, data->offset);
SCLogDebug("relative, working with det_ctx->buffer_offset %"PRIu32", "
"data->offset %"PRIu32"", det_ctx->buffer_offset, data->offset);
ptr = payload + det_ctx->payload_offset;
len = payload_len - det_ctx->payload_offset;
ptr = payload + det_ctx->buffer_offset;
len = payload_len - det_ctx->buffer_offset;
/* No match if there is no relative base */
if (len == 0) {
@ -217,7 +217,7 @@ int DetectByteExtractDoMatch(DetectEngineThreadCtx *det_ctx, SigMatch *sm,
ptr += extbytes;
det_ctx->payload_offset = ptr - payload;
det_ctx->buffer_offset = ptr - payload;
*value = val;

@ -126,8 +126,8 @@ int DetectBytejumpDoMatch(DetectEngineThreadCtx *det_ctx, Signature *s,
* the packet from that point.
*/
if (flags & DETECT_BYTEJUMP_RELATIVE) {
ptr = payload + det_ctx->payload_offset;
len = payload_len - det_ctx->payload_offset;
ptr = payload + det_ctx->buffer_offset;
len = payload_len - det_ctx->buffer_offset;
/* No match if there is no relative base */
if (ptr == NULL || len == 0) {
@ -211,7 +211,7 @@ int DetectBytejumpDoMatch(DetectEngineThreadCtx *det_ctx, Signature *s,
#endif /* DEBUG */
/* Adjust the detection context to the jump location. */
det_ctx->payload_offset = jumpptr - payload;
det_ctx->buffer_offset = jumpptr - payload;
SCReturnInt(1);
}
@ -234,8 +234,8 @@ int DetectBytejumpMatch(ThreadVars *t, DetectEngineThreadCtx *det_ctx,
* the packet from that point.
*/
if (data->flags & DETECT_BYTEJUMP_RELATIVE) {
ptr = p->payload + det_ctx->payload_offset;
len = p->payload_len - det_ctx->payload_offset;
ptr = p->payload + det_ctx->buffer_offset;
len = p->payload_len - det_ctx->buffer_offset;
/* No match if there is no relative base */
if (ptr == NULL || len == 0) {
@ -320,7 +320,7 @@ int DetectBytejumpMatch(ThreadVars *t, DetectEngineThreadCtx *det_ctx,
#endif /* DEBUG */
/* Adjust the detection context to the jump location. */
det_ctx->payload_offset = jumpptr - p->payload;
det_ctx->buffer_offset = jumpptr - p->payload;
return 1;
}

@ -130,11 +130,11 @@ int DetectBytetestDoMatch(DetectEngineThreadCtx *det_ctx, Signature *s, SigMatch
* the packet from that point.
*/
if (flags & DETECT_BYTETEST_RELATIVE) {
SCLogDebug("relative, working with det_ctx->payload_offset %"PRIu32", "
"data->offset %"PRIu32"", det_ctx->payload_offset, data->offset);
SCLogDebug("relative, working with det_ctx->buffer_offset %"PRIu32", "
"data->offset %"PRIu32"", det_ctx->buffer_offset, data->offset);
ptr = payload + det_ctx->payload_offset;
len = payload_len - det_ctx->payload_offset;
ptr = payload + det_ctx->buffer_offset;
len = payload_len - det_ctx->buffer_offset;
/* No match if there is no relative base */
if (ptr == NULL || len == 0) {

@ -52,6 +52,41 @@
#include "util-unittest.h"
#include "util-unittest-helper.h"
/**
* \brief Run the actual payload match functions
*
* The following keywords are inspected:
* - content, including all the http and dce modified contents
* - isdaatat
* - pcre
* - bytejump
* - bytetest
* - byte_extract
* - urilen
* -
*
* All keywords are evaluated against the buffer with buffer_len.
*
* For accounting the last match in relative matching the
* det_ctx->buffer_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 buffer Ptr to the buffer to inspect
* \param buffer_len Length of the payload
* \param inspection_mode Refers to the engine inspection mode we are currently
* inspecting. Can be payload, stream, one of the http
* buffer inspection modes or dce inspection mode.
* \param data Used to send some custom data. For example in
* payload inspection mode, data contains packet ptr,
* and under dce inspection mode, contains dce state.
*
* \retval 0 no match
* \retval 1 match
*/
int DetectEngineContentInspection(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx,
Signature *s, SigMatch *sm,
Flow *f,
@ -80,7 +115,9 @@ int DetectEngineContentInspection(DetectEngineCtx *de_ctx, DetectEngineThreadCtx
sm->type == DETECT_AL_HTTP_CLIENT_BODY ||
sm->type == DETECT_AL_HTTP_SERVER_BODY ||
sm->type == DETECT_AL_HTTP_COOKIE ||
sm->type == DETECT_AL_HTTP_METHOD) {
sm->type == DETECT_AL_HTTP_METHOD ||
sm->type == DETECT_AL_HTTP_STAT_CODE ||
sm->type == DETECT_AL_HTTP_STAT_MSG) {
DetectContentData *cd = (DetectContentData *)sm->ctx;
SCLogDebug("inspecting content %"PRIu32" buffer_len %"PRIu32, cd->id, buffer_len);
@ -105,12 +142,12 @@ int DetectEngineContentInspection(DetectEngineCtx *de_ctx, DetectEngineThreadCtx
uint32_t offset = 0;
uint32_t depth = buffer_len;
uint32_t prev_offset = 0; /**< used in recursive searching */
uint32_t prev_buffer_offset = det_ctx->payload_offset;
uint32_t prev_buffer_offset = det_ctx->buffer_offset;
do {
if (cd->flags & DETECT_CONTENT_DISTANCE ||
cd->flags & DETECT_CONTENT_WITHIN) {
SCLogDebug("det_ctx->payload_offset %"PRIu32, det_ctx->payload_offset);
SCLogDebug("det_ctx->buffer_offset %"PRIu32, det_ctx->buffer_offset);
offset = prev_buffer_offset;
depth = buffer_len;
@ -139,7 +176,7 @@ int DetectEngineContentInspection(DetectEngineCtx *de_ctx, DetectEngineThreadCtx
depth = prev_buffer_offset + cd->within + distance;
}
SCLogDebug("cd->within %"PRIi32", det_ctx->payload_offset %"PRIu32", depth %"PRIu32,
SCLogDebug("cd->within %"PRIi32", det_ctx->buffer_offset %"PRIu32", depth %"PRIu32,
cd->within, prev_buffer_offset, depth);
}
}
@ -240,7 +277,7 @@ int DetectEngineContentInspection(DetectEngineCtx *de_ctx, DetectEngineThreadCtx
} else {
match_offset = (uint32_t)((found - buffer) + cd->content_len);
SCLogDebug("content %"PRIu32" matched at offset %"PRIu32"", cd->id, match_offset);
det_ctx->payload_offset = match_offset;
det_ctx->buffer_offset = match_offset;
/* Match branch, add replace to the list if needed */
if (cd->flags & DETECT_CONTENT_REPLACE) {
@ -288,8 +325,8 @@ int DetectEngineContentInspection(DetectEngineCtx *de_ctx, DetectEngineThreadCtx
DetectIsdataatData *id = (DetectIsdataatData *)sm->ctx;
if (id->flags & ISDATAAT_RELATIVE) {
if (det_ctx->payload_offset + id->dataat > buffer_len) {
SCLogDebug("det_ctx->payload_offset + id->dataat %"PRIu32" > %"PRIu32, det_ctx->payload_offset + id->dataat, buffer_len);
if (det_ctx->buffer_offset + id->dataat > buffer_len) {
SCLogDebug("det_ctx->buffer_offset + id->dataat %"PRIu32" > %"PRIu32, det_ctx->buffer_offset + id->dataat, buffer_len);
if (id->flags & ISDATAAT_NEGATED)
goto match;
SCReturnInt(0);
@ -316,7 +353,7 @@ int DetectEngineContentInspection(DetectEngineCtx *de_ctx, DetectEngineThreadCtx
} else if (sm->type == DETECT_PCRE) {
SCLogDebug("inspecting pcre");
DetectPcreData *pe = (DetectPcreData *)sm->ctx;
uint32_t prev_buffer_offset = det_ctx->payload_offset;
uint32_t prev_buffer_offset = det_ctx->buffer_offset;
uint32_t prev_offset = 0;
int r = 0;
@ -352,7 +389,7 @@ int DetectEngineContentInspection(DetectEngineCtx *de_ctx, DetectEngineThreadCtx
if (det_ctx->discontinue_matching)
SCReturnInt(0);
det_ctx->payload_offset = prev_buffer_offset;
det_ctx->buffer_offset = prev_buffer_offset;
det_ctx->pcre_match_start_offset = prev_offset;
} while (1);

@ -36,6 +36,8 @@ enum {
DETECT_ENGINE_CONTENT_INSPECTION_MODE_HSBD,
DETECT_ENGINE_CONTENT_INSPECTION_MODE_HCD,
DETECT_ENGINE_CONTENT_INSPECTION_MODE_HMD,
DETECT_ENGINE_CONTENT_INSPECTION_MODE_HSCD,
DETECT_ENGINE_CONTENT_INSPECTION_MODE_HSMD,
};
int DetectEngineContentInspection(DetectEngineCtx *,

@ -78,7 +78,7 @@ int DetectEngineInspectDcePayload(DetectEngineCtx *de_ctx,
dce_stub_data = dcerpc_state->dcerpc.dcerpcrequest.stub_data_buffer;
dce_stub_data_len = dcerpc_state->dcerpc.dcerpcrequest.stub_data_buffer_len;
det_ctx->payload_offset = 0;
det_ctx->buffer_offset = 0;
det_ctx->discontinue_matching = 0;
det_ctx->inspection_recursion_counter = 0;
@ -100,7 +100,7 @@ int DetectEngineInspectDcePayload(DetectEngineCtx *de_ctx,
dce_stub_data = dcerpc_state->dcerpc.dcerpcresponse.stub_data_buffer;
dce_stub_data_len = dcerpc_state->dcerpc.dcerpcresponse.stub_data_buffer_len;
det_ctx->payload_offset = 0;
det_ctx->buffer_offset = 0;
det_ctx->discontinue_matching = 0;
det_ctx->inspection_recursion_counter = 0;

@ -253,6 +253,10 @@ int DetectEngineInspectHttpClientBody(DetectEngineCtx *de_ctx,
if (hcbd_buffer == NULL)
continue;
det_ctx->buffer_offset = 0;
det_ctx->discontinue_matching = 0;
det_ctx->inspection_recursion_counter = 0;
r = DetectEngineContentInspection(de_ctx, det_ctx, s, s->sm_lists[DETECT_SM_LIST_HCBDMATCH],
f,
hcbd_buffer,

@ -160,6 +160,10 @@ int DetectEngineInspectHttpCookie(DetectEngineCtx *de_ctx,
continue;
}
det_ctx->buffer_offset = 0;
det_ctx->discontinue_matching = 0;
det_ctx->inspection_recursion_counter = 0;
r = DetectEngineContentInspection(de_ctx, det_ctx, s, s->sm_lists[DETECT_SM_LIST_HCDMATCH],
f,
(uint8_t *)bstr_ptr(h->value),

@ -274,6 +274,10 @@ int DetectEngineInspectHttpHeader(DetectEngineCtx *de_ctx,
if (hhd_buffer == NULL)
continue;
det_ctx->buffer_offset = 0;
det_ctx->discontinue_matching = 0;
det_ctx->inspection_recursion_counter = 0;
r = DetectEngineContentInspection(de_ctx, det_ctx, s, s->sm_lists[DETECT_SM_LIST_HHDMATCH],
f,
hhd_buffer,

@ -148,6 +148,10 @@ int DetectEngineInspectHttpMethod(DetectEngineCtx *de_ctx,
if (tx == NULL || tx->request_method == NULL)
continue;
det_ctx->buffer_offset = 0;
det_ctx->discontinue_matching = 0;
det_ctx->inspection_recursion_counter = 0;
r = DetectEngineContentInspection(de_ctx, det_ctx, s, s->sm_lists[DETECT_SM_LIST_HMDMATCH],
f,
(uint8_t *)bstr_ptr(tx->request_method),

@ -169,6 +169,9 @@ int DetectEngineInspectHttpRawHeader(DetectEngineCtx *de_ctx,
if (raw_headers == NULL)
continue;
det_ctx->buffer_offset = 0;
det_ctx->discontinue_matching = 0;
det_ctx->inspection_recursion_counter = 0;
r = DetectEngineContentInspection(de_ctx, det_ctx, s, s->sm_lists[DETECT_SM_LIST_HRHDMATCH],
f,
(uint8_t *)bstr_ptr(raw_headers),

@ -160,7 +160,7 @@ int DetectEngineInspectHttpRawUri(DetectEngineCtx *de_ctx,
continue;
det_ctx->discontinue_matching = 0;
det_ctx->payload_offset = 0;
det_ctx->buffer_offset = 0;
det_ctx->inspection_recursion_counter = 0;
/* Inspect all the uricontents fetched on each

@ -254,6 +254,10 @@ int DetectEngineInspectHttpServerBody(DetectEngineCtx *de_ctx,
if (hsbd_buffer == NULL)
continue;
det_ctx->buffer_offset = 0;
det_ctx->discontinue_matching = 0;
det_ctx->inspection_recursion_counter = 0;
r = DetectEngineContentInspection(de_ctx, det_ctx, s, s->sm_lists[DETECT_SM_LIST_HSBDMATCH],
f,
hsbd_buffer,

@ -37,23 +37,13 @@
#include "detect-engine-hscd.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"
@ -62,278 +52,6 @@
#include "app-layer-htp.h"
#include "app-layer-protos.h"
/**
* \brief Run the actual payload match function for http stat code.
*
* 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 stat code to inspect.
* \param payload_len Length of the http stat code.
*
* \retval 0 no match.
* \retval 1 match.
*/
static int DoInspectHttpStatCode(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_STAT_CODE) {
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 = DoInspectHttpStatCode(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 = DoInspectHttpStatCode(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 {
/* 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 = DoInspectHttpStatCode(de_ctx, det_ctx, s, sm->next, payload,
payload_len);
SCReturnInt(r);
} else {
SCReturnInt(1);
}
}
/**
* \brief Run the mpm against http stat code.
*
@ -439,13 +157,15 @@ int DetectEngineInspectHttpStatCode(DetectEngineCtx *de_ctx,
continue;
det_ctx->discontinue_matching = 0;
det_ctx->payload_offset = 0;
det_ctx->buffer_offset = 0;
det_ctx->inspection_recursion_counter = 0;
r = DoInspectHttpStatCode(de_ctx, det_ctx, s,
s->sm_lists[DETECT_SM_LIST_HSCDMATCH],
(uint8_t *)bstr_ptr(tx->response_status),
bstr_len(tx->response_status));
r = DetectEngineContentInspection(de_ctx, det_ctx, s,
s->sm_lists[DETECT_SM_LIST_HSCDMATCH],
f,
(uint8_t *)bstr_ptr(tx->response_status),
bstr_len(tx->response_status),
DETECT_ENGINE_CONTENT_INSPECTION_MODE_HSCD, NULL);
if (r == 1) {
goto end;
}

@ -37,23 +37,13 @@
#include "detect-engine-hsmd.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"
@ -62,278 +52,6 @@
#include "app-layer-htp.h"
#include "app-layer-protos.h"
/**
* \brief Run the actual payload match function for http stat msg.
*
* 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 stat msg to inspect.
* \param payload_len Length of the http stat msg.
*
* \retval 0 no match.
* \retval 1 match.
*/
static int DoInspectHttpStatMsg(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_STAT_MSG) {
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 = DoInspectHttpStatMsg(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 = DoInspectHttpStatMsg(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 {
/* 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 = DoInspectHttpStatMsg(de_ctx, det_ctx, s, sm->next, payload,
payload_len);
SCReturnInt(r);
} else {
SCReturnInt(1);
}
}
/**
* \brief Run the mpm against http stat msg.
*
@ -439,13 +157,15 @@ int DetectEngineInspectHttpStatMsg(DetectEngineCtx *de_ctx,
continue;
det_ctx->discontinue_matching = 0;
det_ctx->payload_offset = 0;
det_ctx->buffer_offset = 0;
det_ctx->inspection_recursion_counter = 0;
r = DoInspectHttpStatMsg(de_ctx, det_ctx, s,
s->sm_lists[DETECT_SM_LIST_HSMDMATCH],
(uint8_t *)bstr_ptr(tx->response_message),
bstr_len(tx->response_message));
r = DetectEngineContentInspection(de_ctx, det_ctx, s,
s->sm_lists[DETECT_SM_LIST_HSMDMATCH],
f,
(uint8_t *)bstr_ptr(tx->response_message),
bstr_len(tx->response_message),
DETECT_ENGINE_CONTENT_INSPECTION_MODE_HSMD, NULL);
if (r == 1) {
goto end;
}

@ -64,7 +64,7 @@ int DetectEngineInspectPacketPayload(DetectEngineCtx *de_ctx,
SCReturnInt(0);
}
det_ctx->payload_offset = 0;
det_ctx->buffer_offset = 0;
det_ctx->discontinue_matching = 0;
det_ctx->inspection_recursion_counter = 0;
det_ctx->replist = NULL;
@ -109,7 +109,7 @@ int DetectEngineInspectStreamPayload(DetectEngineCtx *de_ctx,
SCReturnInt(0);
}
det_ctx->payload_offset = 0;
det_ctx->buffer_offset = 0;
det_ctx->discontinue_matching = 0;
det_ctx->inspection_recursion_counter = 0;
//det_ctx->flags |= DETECT_ENGINE_THREAD_CTX_INSPECTING_STREAM;

@ -102,7 +102,7 @@ int DetectEngineInspectPacketUris(DetectEngineCtx *de_ctx,
continue;
det_ctx->discontinue_matching = 0;
det_ctx->payload_offset = 0;
det_ctx->buffer_offset = 0;
det_ctx->inspection_recursion_counter = 0;
//PrintRawDataFp(stdout, (uint8_t *)bstr_ptr(tx->request_uri_normalized),

@ -491,11 +491,11 @@ int DetectPcrePayloadMatch(DetectEngineThreadCtx *det_ctx, Signature *s,
// SCReturnInt(0);
if (s->flags & SIG_FLAG_RECURSIVE) {
ptr = payload + det_ctx->payload_offset;
len = payload_len - det_ctx->payload_offset;
ptr = payload + det_ctx->buffer_offset;
len = payload_len - det_ctx->buffer_offset;
} else if (pe->flags & DETECT_PCRE_RELATIVE) {
ptr = payload + det_ctx->payload_offset;
len = payload_len - det_ctx->payload_offset;
ptr = payload + det_ctx->buffer_offset;
len = payload_len - det_ctx->buffer_offset;
} else {
ptr = payload;
len = payload_len;
@ -546,7 +546,7 @@ int DetectPcrePayloadMatch(DetectEngineThreadCtx *det_ctx, Signature *s,
}
/* update offset for pcre RELATIVE */
det_ctx->payload_offset = (ptr + ov[1]) - payload;
det_ctx->buffer_offset = (ptr + ov[1]) - payload;
det_ctx->pcre_match_start_offset = (ptr + ov[0] + 1) - payload;
ret = 1;
@ -588,11 +588,11 @@ int DetectPcrePacketPayloadMatch(DetectEngineThreadCtx *det_ctx, Packet *p, Sign
SCReturnInt(0);
if (s->flags & SIG_FLAG_RECURSIVE) {
ptr = p->payload + det_ctx->payload_offset;
len = p->payload_len - det_ctx->payload_offset;
ptr = p->payload + det_ctx->buffer_offset;
len = p->payload_len - det_ctx->buffer_offset;
} else if (pe->flags & DETECT_PCRE_RELATIVE) {
ptr = p->payload + det_ctx->payload_offset;
len = p->payload_len - det_ctx->payload_offset;
ptr = p->payload + det_ctx->buffer_offset;
len = p->payload_len - det_ctx->buffer_offset;
if (ptr == NULL || len == 0)
SCReturnInt(0);
} else {
@ -635,7 +635,7 @@ int DetectPcrePacketPayloadMatch(DetectEngineThreadCtx *det_ctx, Packet *p, Sign
}
/* update offset for pcre RELATIVE */
det_ctx->payload_offset = (ptr+ov[1]) - p->payload;
det_ctx->buffer_offset = (ptr+ov[1]) - p->payload;
ret = 1;
}
@ -681,11 +681,11 @@ int DetectPcrePayloadDoMatch(DetectEngineThreadCtx *det_ctx, Signature *s,
SCReturnInt(0);
if (s->flags & SIG_FLAG_RECURSIVE) {
ptr = data + det_ctx->payload_offset;
len = data_len - det_ctx->payload_offset;
ptr = data + det_ctx->buffer_offset;
len = data_len - det_ctx->buffer_offset;
} else if (pe->flags & DETECT_PCRE_RELATIVE) {
ptr = data + det_ctx->payload_offset;
len = data_len - det_ctx->payload_offset;
ptr = data + det_ctx->buffer_offset;
len = data_len - det_ctx->buffer_offset;
if (ptr == NULL || len == 0)
SCReturnInt(0);
} else {
@ -728,7 +728,7 @@ int DetectPcrePayloadDoMatch(DetectEngineThreadCtx *det_ctx, Signature *s,
}
/* update offset for pcre RELATIVE */
det_ctx->payload_offset = (ptr + ov[1]) - data;
det_ctx->buffer_offset = (ptr + ov[1]) - data;
ret = 1;
}

@ -695,7 +695,6 @@ typedef struct DetectionEngineThreadCtx_ {
/** offset into the payload of the last match by:
* content, pcre, etc */
uint32_t buffer_offset;
uint32_t payload_offset;
/* used by pcre match function alone */
uint32_t pcre_match_start_offset;
@ -724,14 +723,6 @@ typedef struct DetectionEngineThreadCtx_ {
/* holds the current recursion depth on content inspection */
int inspection_recursion_counter;
/* dce stub data */
uint8_t *dce_stub_data;
/* dce stub data len */
uint32_t dce_stub_data_len;
/* offset into the payload of the last match for dce related sigmatches,
* stored in s->sm_lists[DETECT_SM_LIST_DMATCH], by content, pcre, etc */
uint32_t dce_payload_offset;
/** array of signature pointers we're going to inspect in the detection
* loop. */
Signature **match_array;

Loading…
Cancel
Save