Further simplify content api: merge flags that indicate a next relative match, remove chunks as they are unnecessary now, make negated a bitflag.

remotes/origin/master-1.0.x
Victor Julien 16 years ago
parent f0d68b633e
commit 80dc4f1dbe

@ -10,6 +10,7 @@
#include "detect-parse.h"
#include "detect-bytejump.h"
#include "detect-content.h"
#include "util-byte.h"
#include "util-unittest.h"
@ -489,6 +490,19 @@ int DetectBytejumpSetup(DetectEngineCtx *de_ctx, Signature *s, char *optstr)
data = DetectBytejumpParse(optstr);
if (data == NULL) goto error;
if (data->flags & DETECT_BYTEJUMP_RELATIVE) {
/** Search for the first previous DetectContent
* SigMatch (it can be the same as this one) */
SigMatch *pm = DetectContentFindPrevApplicableSM(s->pmatch_tail);
if (pm == NULL) {
SCLogError(SC_ERR_BYTEJUMP_MISSING_CONTENT, "relative bytejump match needs a previous content option");
goto error;
}
DetectContentData *cd = (DetectContentData *)pm->ctx;
cd->flags |= DETECT_CONTENT_RELATIVE_NEXT;
}
sm = SigMatchAlloc();
if (sm == NULL)
goto error;

@ -515,7 +515,7 @@ int DetectBytetestSetup(DetectEngineCtx *de_ctx, Signature *s, char *optstr)
}
DetectContentData *cd = (DetectContentData *)pm->ctx;
cd->flags |= DETECT_CONTENT_BYTETEST_NEXT;
cd->flags |= DETECT_CONTENT_RELATIVE_NEXT;
}
sm = SigMatchAlloc();

File diff suppressed because it is too large Load Diff

@ -1,64 +1,39 @@
#ifndef __DETECT_CONTENT_H__
#define __DETECT_CONTENT_H__
#define DETECT_CONTENT_NOCASE 0x0001
#define DETECT_CONTENT_DISTANCE 0x0002
#define DETECT_CONTENT_WITHIN 0x0004
/* Flags affecting this content */
#define DETECT_CONTENT_FAST_PATTERN 0x0008
#define DETECT_CONTENT_DISTANCE_NEXT 0x0010
#define DETECT_CONTENT_WITHIN_NEXT 0x0020
#define DETECT_CONTENT_ISDATAAT_RELATIVE 0x0040
#define DETECT_CONTENT_BYTETEST_NEXT 0x0080
#define DETECT_CONTENT_NOCASE 0x01
#define DETECT_CONTENT_DISTANCE 0x02
#define DETECT_CONTENT_WITHIN 0x04
#define DETECT_CONTENT_FAST_PATTERN 0x08
/** content applies to a "raw"/undecoded field if applicable */
#define DETECT_CONTENT_RAWBYTES 0x10
/** content is negated */
#define DETECT_CONTENT_NEGATED 0x20
#define DETECT_CONTENT_RAWBYTES 0x0100
/** Set if the pattern is split into multiple chunks */
#define DETECT_CONTENT_IS_CHUNK 0x0200
/** a relative match to this content is next, used in matching phase */
#define DETECT_CONTENT_RELATIVE_NEXT 0x40
#define DETECT_CONTENT_IS_SINGLE(c) (!((c)->flags & DETECT_CONTENT_DISTANCE || \
(c)->flags & DETECT_CONTENT_WITHIN || \
(c)->flags & DETECT_CONTENT_DISTANCE_NEXT || \
(c)->flags & DETECT_CONTENT_WITHIN_NEXT || \
(c)->flags & DETECT_CONTENT_ISDATAAT_RELATIVE || \
(c)->flags & DETECT_CONTENT_IS_CHUNK || \
(c)->flags & DETECT_CONTENT_RELATIVE || \
(c)->depth > 0 || \
(c)->within > 0))
/** Used for modifier propagations, to know if they are
* yet updated or not */
#define CHUNK_UPDATED_DEPTH 0x01
#define CHUNK_UPDATED_OFFSET 0x02
#define CHUNK_UPDATED_ISDATAAT 0x04
#define CHUNK_UPDATED_DISTANCE 0x08
#define CHUNK_UPDATED_WITHIN 0x10
typedef struct DetectContentData_ {
uint8_t *content; /**< ptr to chunk of memory containing the pattern */
uint8_t content_len;/**< length of the pattern (and size of the memory) */
uint32_t id; /**< unique pattern id */
uint8_t negated;
uint32_t id; /**< unique pattern id */
uint16_t depth;
uint16_t offset;
uint32_t isdataat;
/** distance from the last match this match should start.
* Can be negative */
int32_t distance;
int32_t within;
uint16_t flags;
/** The group this chunk belongs to, relative to the signature
* It start from 1, and the last SigMatch of the list should be
* also the total number of DetectContent "Real" Patterns loaded
* from the Signature */
uint8_t chunk_group_id;
/** The id number for this chunk in the current group of chunks
* Starts from 0, and a chunk with chunk_id == 0 should be the
* of the current chunk group where real modifiers are set before
* propagation */
uint8_t chunk_id;
/** For modifier propagations (the new flags) */
uint8_t chunk_flags;
uint8_t flags;
} DetectContentData;
/* prototypes */
@ -83,17 +58,6 @@ SigMatch *DetectContentHasPrevSMPattern(SigMatch *);
SigMatch *SigMatchGetLastPattern(Signature *s);
/** After setting a new modifier, we should call one of the followings */
int DetectContentPropagateDepth(SigMatch *);
int DetectContentPropagateIsdataat(SigMatch *);
int DetectContentPropagateWithin(SigMatch *);
int DetectContentPropagateOffset(SigMatch *);
int DetectContentPropagateDistance(SigMatch *);
int DetectContentPropagateIsdataat(SigMatch *);
/** This shall not be called from outside detect-content.c (used internally)*/
int DetectContentPropagateModifiers(SigMatch *);
void DetectContentFree(void *);
int DetectContentTableInitHash(DetectEngineCtx *);

@ -54,14 +54,6 @@ static int DetectDepthSetup (DetectEngineCtx *de_ctx, Signature *s, char *depths
cd->depth = cd->content_len + cd->offset;
}
/** Propagate the modifiers through the first chunk
* (SigMatch) if we're dealing with chunks */
if (cd->flags & DETECT_CONTENT_IS_CHUNK)
DetectContentPropagateDepth(pm);
//DetectContentPrint(cd);
//printf("DetectDepthSetup: set depth %" PRIu32 " for previous content\n", cd->depth);
if (dubbed) SCFree(str);
return 0;
}

@ -68,29 +68,15 @@ static int DetectDistanceSetup (DetectEngineCtx *de_ctx, Signature *s, char *dis
}
}
/** Propagate the modifiers through the first chunk
* (SigMatch) if we're dealing with chunks */
if (cd->flags & DETECT_CONTENT_IS_CHUNK)
DetectContentPropagateDistance(pm);
//DetectContentPrint(cd);
//printf("DetectDistanceSetup: set distance %" PRId32 " for previous content\n", cd->distance);
pm = DetectContentFindPrevApplicableSM(s->pmatch_tail->prev);
if (pm == NULL) {
SCLogError(SC_ERR_DISTANCE_MISSING_CONTENT, "distance needs two preceeding content options");
goto error;
}
if (pm->type == DETECT_PCRE) {
DetectPcreData *pe = (DetectPcreData *)pm->ctx;
pe->flags |= DETECT_PCRE_DISTANCE_NEXT;
} else if (pm->type == DETECT_CONTENT) {
if (pm->type == DETECT_CONTENT) {
DetectContentData *cd = (DetectContentData *)pm->ctx;
cd->flags |= DETECT_CONTENT_DISTANCE_NEXT;
} else if (pm->type == DETECT_URICONTENT) {
DetectUricontentData *cd = (DetectUricontentData *)pm->ctx;
cd->flags |= DETECT_URICONTENT_DISTANCE_NEXT;
cd->flags |= DETECT_CONTENT_RELATIVE_NEXT;
} else {
SCLogError(SC_ERR_RULE_KEYWORD_UNKNOWN, "Unknown previous-previous keyword!");
goto error;

@ -16,6 +16,10 @@
#include "util-spm.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
*
@ -61,10 +65,11 @@ static inline int DoInspectPacketPayload(DetectEngineCtx *de_ctx,
/* search for our pattern, checking the matches recursively.
* if we match we look for the next SigMatch as well */
uint8_t *found = NULL;
do {
uint32_t offset = 0;
uint32_t depth = payload_len;
uint32_t offset = 0;
uint32_t depth = payload_len;
uint32_t prev_offset = 0; /**< used in recursive searching */
do {
if (cd->flags & DETECT_CONTENT_DISTANCE ||
cd->flags & DETECT_CONTENT_WITHIN) {
SCLogDebug("det_ctx->payload_offset %"PRIu32, det_ctx->payload_offset);
@ -112,6 +117,11 @@ static inline int DoInspectPacketPayload(DetectEngineCtx *de_ctx,
offset = cd->offset;
}
/* update offset with prev_offset if we're searching for
* matches after the first occurence. */
SCLogDebug("offset %"PRIu32", prev_offset %"PRIu32, prev_offset, depth);
offset += prev_offset;
SCLogDebug("offset %"PRIu32", depth %"PRIu32, offset, depth);
if (depth > payload_len)
@ -120,7 +130,7 @@ static inline int DoInspectPacketPayload(DetectEngineCtx *de_ctx,
/* 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->negated == 1) {
if (cd->flags & DETECT_CONTENT_NEGATED) {
goto match;
} else {
SCReturnInt(0);
@ -129,6 +139,7 @@ static inline int DoInspectPacketPayload(DetectEngineCtx *de_ctx,
uint8_t *spayload = payload + offset;
uint32_t spayload_len = depth - offset;
uint32_t match_offset = 0;
SCLogDebug("spayload_len %"PRIu32, spayload_len);
BUG_ON(spayload_len > payload_len);
@ -140,36 +151,44 @@ static inline int DoInspectPacketPayload(DetectEngineCtx *de_ctx,
/* next we evaluate the result in combination with the
* negation flag. */
SCLogDebug("found %p cd->negated %d", found, cd->negated);
SCLogDebug("found %p cd negated %s", found, cd->flags & DETECT_CONTENT_NEGATED ? "true" : "false");
if (found == NULL && cd->negated == 0) {
if (found == NULL && !(cd->flags & DETECT_CONTENT_NEGATED)) {
SCReturnInt(0);
} else if (found == NULL && cd->negated == 1) {
} else if (found == NULL && cd->flags & DETECT_CONTENT_NEGATED) {
goto match;
} else if (found != NULL && cd->negated == 1) {
} else if (found != NULL && cd->flags & DETECT_CONTENT_NEGATED) {
#ifdef DEBUG
uint32_t match_offset = (uint32_t)((found - payload) + cd->content_len);
match_offset = (uint32_t)((found - payload) + cd->content_len);
SCLogDebug("content %"PRIu32" matched at offset %"PRIu32", but negated so no match", cd->id, match_offset);
#endif
SCReturnInt(0);
} else {
uint32_t match_offset = (uint32_t)((found - payload) + cd->content_len);
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;
if (cd->flags & DETECT_CONTENT_ISDATAAT_RELATIVE) {
if (det_ctx->payload_offset + cd->isdataat > payload_len) {
SCLogDebug("det_ctx->payload_offset + cd->isdataat %"PRIu32" > %"PRIu32, det_ctx->payload_offset + cd->isdataat, payload_len);
SCReturnInt(0);
} else {
SCLogDebug("relative isdataat match");
}
if (!(cd->flags & DETECT_CONTENT_RELATIVE_NEXT)) {
SCLogDebug("no relative match coming up, so this is a match");
goto match;
}
}
SCLogDebug("content %"PRIu32", next? %s", cd->id, sm->next?"true":"false");
BUG_ON(sm->next == NULL);
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 */
int r = DoInspectPacketPayload(de_ctx,det_ctx,s,sm->next, f, flags, alstate, p, payload, payload_len);
if (r == 1) {
SCReturnInt(1);
}
/* 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);
}
goto match;
} while(1);
}
case DETECT_ISDATAAT:
@ -177,14 +196,22 @@ static inline int DoInspectPacketPayload(DetectEngineCtx *de_ctx,
SCLogDebug("inspecting isdataat");
DetectIsdataatData *id = (DetectIsdataatData *)sm->ctx;
BUG_ON(id->flags & ISDATAAT_RELATIVE);
if (id->dataat < payload_len) {
SCLogDebug("absolute isdataat match");
goto match;
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);
SCReturnInt(0);
} else {
SCLogDebug("relative isdataat match");
goto match;
}
} else {
SCLogDebug("absolute isdataat mismatch, id->isdataat %"PRIu32", payload_len %"PRIu32"", id->dataat,payload_len);
SCReturnInt(0);
if (id->dataat < payload_len) {
SCLogDebug("absolute isdataat match");
goto match;
} else {
SCLogDebug("absolute isdataat mismatch, id->isdataat %"PRIu32", payload_len %"PRIu32"", id->dataat,payload_len);
SCReturnInt(0);
}
}
}
case DETECT_PCRE:
@ -199,34 +226,6 @@ static inline int DoInspectPacketPayload(DetectEngineCtx *de_ctx,
SCReturnInt(0);
}
case DETECT_PCRE_HTTPBODY:
{
SCLogDebug("inspecting pcre http body");
int r = DetectPcreALDoMatch(det_ctx, s, sm, f, flags, alstate);
if (r != 1) {
SCReturnInt(0);
}
goto match;
}
case DETECT_AL_HTTP_COOKIE:
{
int r = DetectHttpCookieDoMatch(det_ctx, s, sm, f, flags, alstate);
if (r != 1) {
SCReturnInt(0);
}
goto match;
}
case DETECT_AL_HTTP_METHOD:
{
int r = DetectHttpMethodDoMatch(det_ctx, s, sm, f, flags, alstate);
if (r != 1) {
SCReturnInt(0);
}
goto match;
}
case DETECT_BYTETEST:
{
if (DetectBytetestDoMatch(det_ctx,s,sm,payload,payload_len) != 1) {
@ -243,12 +242,9 @@ static inline int DoInspectPacketPayload(DetectEngineCtx *de_ctx,
goto match;
}
/* assume unsupported matches match */
default:
{
SCLogDebug("inspecting default, match assumed");
goto match;
BUG_ON(1);
}
}
@ -297,3 +293,33 @@ int DetectEngineInspectPacketPayload(DetectEngineCtx *de_ctx,
SCReturnInt(0);
}
#ifdef UNITTESTS
static int PayloadTestSig01 (void) {
uint8_t *buf = (uint8_t *)
"abcabcd";
uint16_t buflen = strlen((char *)buf);
Packet *p = UTHBuildPacket( buf, buflen, IPPROTO_TCP);
int result = 0;
char sig[] = "alert tcp any any -> any any (content:\"abc\"; content:\"d\"; distance:0; within:1; sid:1;)";
if (UTHPacketMatchSigMpm(p, sig, MPM_B2G) == 0) {
result = 0;
goto end;
}
result = 1;
end:
if (p != NULL)
UTHFreePacket(p);
return result;
}
#endif /* UNITTESTS */
void PayloadRegisterTests(void) {
#ifdef UNITTESTS
UtRegisterTest("PayloadTestSig01", PayloadTestSig01, 1);
#endif /* UNITTESTS */
}

@ -5,5 +5,7 @@ int DetectEngineInspectPacketPayload(DetectEngineCtx *,
DetectEngineThreadCtx *, Signature *, Flow *, uint8_t,
void *, Packet *);
void PayloadRegisterTests(void);
#endif /* __DETECT_ENGINE_PAYLOAD_H__ */

@ -242,25 +242,17 @@ int DetectIsdataatSetup (DetectEngineCtx *de_ctx, Signature *s, char *isdataatst
return -1;
}
cd->flags |= DETECT_CONTENT_ISDATAAT_RELATIVE;
cd->isdataat = idad->dataat;
/** Propagate the changes */
DetectContentPropagateIsdataat(pm);
cd->flags |= DETECT_CONTENT_RELATIVE_NEXT;
}
else {
SCLogDebug("set it as a normal SigMatch");
/** else Set it as a normal SigMatch */
sm = SigMatchAlloc();
if (sm == NULL)
goto error;
sm = SigMatchAlloc();
if (sm == NULL)
goto error;
sm->type = DETECT_ISDATAAT;
sm->ctx = (void *)idad;
sm->type = DETECT_ISDATAAT;
sm->ctx = (void *)idad;
SigMatchAppendPayload(s,sm);
}
SigMatchAppendPayload(s, sm);
return 0;

@ -35,7 +35,7 @@ int DetectOffsetSetup (DetectEngineCtx *de_ctx, Signature *s, char *offsetstr)
dubbed = 1;
}
/** Search for the first previous DetectContent
/* Search for the first previous DetectContent
* SigMatch (it can be the same as this one) */
SigMatch *pm = DetectContentFindPrevApplicableSM(s->pmatch_tail);
if (pm == NULL) {
@ -61,11 +61,6 @@ int DetectOffsetSetup (DetectEngineCtx *de_ctx, Signature *s, char *offsetstr)
}
}
/** Propagate the modifiers through the first chunk
* (SigMatch) if we're dealing with chunks */
if (cd->flags & DETECT_CONTENT_IS_CHUNK)
DetectContentPropagateOffset(pm);
if (dubbed) SCFree(str);
return 0;
}

@ -709,7 +709,7 @@ Signature *SigInit(DetectEngineCtx *de_ctx, char *sigstr) {
sig->flags |= SIG_FLAG_MPM;
if (cd->negated == 1) {
if (cd->flags & DETECT_CONTENT_NEGATED) {
sig->flags |= SIG_FLAG_MPM_NEGCONTENT;
}
}
@ -825,7 +825,7 @@ Signature *SigInitReal(DetectEngineCtx *de_ctx, char *sigstr) {
sig->flags |= SIG_FLAG_MPM;
if (cd->negated == 1) {
if (cd->flags & DETECT_CONTENT_NEGATED) {
sig->flags |= SIG_FLAG_MPM_NEGCONTENT;
}
}

@ -2,7 +2,7 @@
/** \file
* \author Victor Julien <victor@inliniac.net>
* \todo within logic is not Snort compat atm: it is applied to pcre and uricontent as well */
*/
#include "suricata-common.h"
#include "decode.h"
@ -65,27 +65,16 @@ static int DetectWithinSetup (DetectEngineCtx *de_ctx, Signature *s, char *withi
}
}
/** Propagate the modifiers through the first chunk
* (SigMatch) if we're dealing with chunks */
if (cd->flags & DETECT_CONTENT_IS_CHUNK)
DetectContentPropagateWithin(pm);
pm = DetectContentFindPrevApplicableSM(s->pmatch_tail->prev);
if (pm == NULL) {
SCLogError(SC_ERR_WITHIN_MISSING_CONTENT, "within needs two preceeding content options");
goto error;
}
/* Set the within next flag on the prev sigmatch */
if (pm->type == DETECT_PCRE) {
DetectPcreData *pe = (DetectPcreData *)pm->ctx;
pe->flags |= DETECT_PCRE_WITHIN_NEXT;
} else if (pm->type == DETECT_CONTENT) {
/* Set the relative next flag on the prev sigmatch */
if (pm->type == DETECT_CONTENT) {
DetectContentData *cd = (DetectContentData *)pm->ctx;
cd->flags |= DETECT_CONTENT_WITHIN_NEXT;
} else if (pm->type == DETECT_URICONTENT) {
DetectUricontentData *ud = (DetectUricontentData *)pm->ctx;
ud->flags |= DETECT_URICONTENT_WITHIN_NEXT;
cd->flags |= DETECT_CONTENT_RELATIVE_NEXT;
} else {
printf("DetectWithinSetup: Unknown previous-previous keyword!\n");
goto error;

@ -26,6 +26,7 @@
#include "detect-engine.h"
#include "detect-engine-mpm.h"
#include "detect-engine-sigorder.h"
#include "detect-engine-payload.h"
#include "tm-queuehandlers.h"
#include "tm-queues.h"
@ -757,6 +758,7 @@ int main(int argc, char **argv)
#ifdef __SC_CUDA_SUPPORT__
SCCudaRegisterTests();
#endif
PayloadRegisterTests();
if (list_unittests) {
UtListTests(regex_arg);
}

@ -78,6 +78,7 @@ const char * SCErrorToString(SCError err)
CASE_CODE (SC_ERR_FLAGS_MODIFIER);
CASE_CODE (SC_ERR_DISTANCE_MISSING_CONTENT);
CASE_CODE (SC_ERR_BYTETEST_MISSING_CONTENT);
CASE_CODE (SC_ERR_BYTEJUMP_MISSING_CONTENT);
CASE_CODE (SC_ERR_WITHIN_MISSING_CONTENT);
CASE_CODE (SC_ERR_DEPTH_MISSING_CONTENT);
CASE_CODE (SC_ERR_OFFSET_MISSING_CONTENT);

@ -104,6 +104,7 @@ typedef enum {
SC_ERR_OFFSET_MISSING_CONTENT,
SC_ERR_DEPTH_MISSING_CONTENT,
SC_ERR_BYTETEST_MISSING_CONTENT,
SC_ERR_BYTEJUMP_MISSING_CONTENT,
SC_ERR_NOCASE_MISSING_PATTERN,
SC_ERR_RAWBYTES_MISSING_CONTENT,
SC_ERR_NO_URICONTENT_NEGATION,

@ -305,7 +305,7 @@ void B2gFreePattern(MpmCtx *mpm_ctx, B2gPattern *p) {
static inline int B2gAddPattern(MpmCtx *mpm_ctx, uint8_t *pat, uint16_t patlen, uint16_t offset, uint16_t depth, uint32_t pid, uint32_t sid, uint8_t flags) {
B2gCtx *ctx = (B2gCtx *)mpm_ctx->ctx;
SCLogDebug("ctx %p len %"PRIu16" pid %" PRIu32 ", nocase %s", ctx, patlen, pid, nocase ? "true" : "false");
SCLogDebug("ctx %p len %"PRIu16" pid %" PRIu32, ctx, patlen, pid);
if (patlen == 0)
return 0;

@ -494,7 +494,9 @@ end:
* \retval return 0 if not
*/
int UTHPacketMatchSigMpm(Packet *p, char *sig, uint16_t mpm_type) {
int result = 1;
SCEnter();
int result = 0;
DecodeThreadVars dtv;
@ -539,7 +541,7 @@ end:
if (de_ctx != NULL)
DetectEngineCtxFree(de_ctx);
return result;
SCReturnInt(result);
}
/**

Loading…
Cancel
Save