Adding detect_content chunks handling for max_pattern_length and unittests. Updating modifiers to use it.

remotes/origin/master-1.0.x
Pablo Rincon 16 years ago committed by Victor Julien
parent 981ca859cb
commit f233f9fa31

File diff suppressed because it is too large Load Diff

@ -1,15 +1,27 @@
#ifndef __DETECT_CONTENT_H__
#define __DETECT_CONTENT_H__
#define DETECT_CONTENT_NOCASE 0x01
#define DETECT_CONTENT_DISTANCE 0x02
#define DETECT_CONTENT_WITHIN 0x04
#define DETECT_CONTENT_NOCASE 0x01
#define DETECT_CONTENT_DISTANCE 0x02
#define DETECT_CONTENT_WITHIN 0x04
#define DETECT_CONTENT_DISTANCE_NEXT 0x08
#define DETECT_CONTENT_WITHIN_NEXT 0x10
#define DETECT_CONTENT_ISDATAAT_RELATIVE 0x16
#define DETECT_CONTENT_DISTANCE_NEXT 0x08
#define DETECT_CONTENT_WITHIN_NEXT 0x10
#define DETECT_CONTENT_ISDATAAT_RELATIVE 0x20
#define DETECT_CONTENT_RAWBYTES 0x20
#define DETECT_CONTENT_RAWBYTES 0x40
/** Set if the pattern is split into multiple chunks */
#define DETECT_CONTENT_IS_CHUNK 0x80
/** 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;
@ -22,13 +34,43 @@ typedef struct DetectContentData_ {
int32_t distance;
int32_t within;
uint8_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;
} DetectContentData;
/* prototypes */
void DetectContentRegister (void);
uint32_t DetectContentMaxId(DetectEngineCtx *);
DetectContentData *DetectContentParse (char *contentstr);
void DetectContentPrint(DetectContentData *);
/** This function search backwards the first applicable SigMatch holding
* a DETECT_CONTENT context. Modifiers must call this */
SigMatch *DetectContentFindApplicableSM(SigMatch *);
/** 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 *);
#endif /* __DETECT_CONTENT_H__ */

@ -39,10 +39,32 @@ int DetectDepthSetup (DetectEngineCtx *de_ctx, Signature *s, SigMatch *m, char *
DetectPcreData *pe = (DetectPcreData *)pm->ctx;
pe->depth = (uint32_t)atoi(str);
//printf("DetectDepthSetup: set depth %" PRIu32 " for previous pcre\n", pe->depth);
} else if (pm->type == DETECT_CONTENT) {
/** Search for the first previous DetectContent
* SigMatch (it can be the same as this one) */
pm = DetectContentFindApplicableSM(m);
if (pm == NULL) {
printf("DetectDepthSetup: Unknown previous keyword!\n");
return -1;
}
DetectContentData *cd = (DetectContentData *)pm->ctx;
if (cd == NULL) {
printf("DetectDepthSetup: Unknown previous keyword!\n");
return -1;
}
cd->depth = (uint32_t)atoi(str);
/** 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);
} else {
printf("DetectDepthSetup: Unknown previous keyword!\n");
}

@ -45,14 +45,32 @@ int DetectDistanceSetup (DetectEngineCtx *de_ctx, Signature *s, SigMatch *m, cha
pe->distance = strtol(str, NULL, 10);
pe->flags |= DETECT_PCRE_DISTANCE;
//printf("DetectDistanceSetup: set distance %" PRId32 " for previous pcre\n", pe->distance);
} else if (pm->type == DETECT_CONTENT) {
/** Search for the first previous DetectContent
* SigMatch (it can be the same as this one) */
pm = DetectContentFindApplicableSM(m);
if (pm == NULL) {
printf("DetectDistanceSetup: Unknown previous keyword!\n");
return -1;
}
DetectContentData *cd = (DetectContentData *)pm->ctx;
if (cd == NULL) {
printf("DetectDistanceSetup: Unknown previous keyword!\n");
return -1;
}
cd->distance = strtol(str, NULL, 10);
cd->flags |= DETECT_CONTENT_DISTANCE;
/** 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);
} else if (pm->type == DETECT_URICONTENT) {
DetectUricontentData *cd = (DetectUricontentData *)pm->ctx;

@ -604,8 +604,8 @@ void DetectIdRegisterTests(void) {
UtRegisterTest("DetectIdTestParse02", DetectIdTestParse02, 1);
UtRegisterTest("DetectIdTestParse03", DetectIdTestParse03, 1);
UtRegisterTest("DetectIdTestParse04", DetectIdTestParse04, 1);
UtRegisterTest("DetectIdTestPacket01" , DetectIdTestPacket01 , 1);
UtRegisterTest("DetectIdTestPacket02" , DetectIdTestPacket02 , 1);
UtRegisterTest("DetectIdTestPacket01", DetectIdTestPacket01 , 1);
UtRegisterTest("DetectIdTestPacket02", DetectIdTestPacket02 , 1);
UtRegisterTest("DetectIdTestSig1", DetectIdTestSig1, 1);
UtRegisterTest("DetectIdTestSig2", DetectIdTestSig2, 1);

@ -19,11 +19,12 @@
#include "flow-var.h"
#include "util-debug.h"
#include "util-byte.h"
/**
* \brief Regex for parsing our isdataat options
*/
#define PARSE_REGEX "^\\s*([0-9]{1,10})\\s*(,\\s*relative)?\\s*(,\\s*rawbytes\\s*)?\\s*$"
#define PARSE_REGEX "^\\s*([0-9]{1,5})\\s*(,\\s*relative)?\\s*(,\\s*rawbytes\\s*)?\\s*$"
static pcre *parse_regex;
static pcre_extra *parse_regex_study;
@ -50,15 +51,13 @@ void DetectIsdataatRegister (void) {
int opts = 0;
parse_regex = pcre_compile(PARSE_REGEX, opts, &eb, &eo, NULL);
if(parse_regex == NULL)
{
if(parse_regex == NULL) {
printf("pcre compile of \"%s\" failed at offset %" PRId32 ": %s\n", PARSE_REGEX, eo, eb);
goto error;
}
parse_regex_study = pcre_study(parse_regex, 0, &eb);
if(eb != NULL)
{
if(eb != NULL) {
printf("pcre study failed: %s\n", eb);
goto error;
}
@ -88,16 +87,12 @@ int DetectIsdataatMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx, Packet *
SCLogDebug("payload_len: %u , dataat? %u ; relative? %u...", p->payload_len,idad->dataat,idad->flags &ISDATAAT_RELATIVE);
if(idad->flags & ISDATAAT_RELATIVE)
{
/* Relative to the last matched content, is not performed here */
}
else
if(!(idad->flags & ISDATAAT_RELATIVE) && p->payload_len >= idad->dataat) {
ret = 1; /* its not relative and we have more data in the packet than the offset of isdataat */
/* Relative to the last matched content is not performed here */
if(!(idad->flags & ISDATAAT_RELATIVE) && p->payload_len >= idad->dataat) {
ret = 1; /* its not relative and we have more data in the packet than the offset of isdataat */
SCLogDebug("matched with payload_len: %u , dataat? %u ; relative? %u...", p->payload_len,idad->dataat,idad->flags &ISDATAAT_RELATIVE);
}
SCLogDebug("matched with payload_len: %u , dataat? %u ; relative? %u...", p->payload_len,idad->dataat,idad->flags &ISDATAAT_RELATIVE);
}
return ret;
}
@ -158,27 +153,28 @@ DetectIsdataatData *DetectIsdataatParse (char *isdataatstr)
}
idad->flags = 0;
idad->dataat= 0;
if(args[0] != NULL)
idad->dataat=atoi(args[0]);
if(idad->dataat < ISDATAAT_MIN || idad->dataat > ISDATAAT_MAX) {
printf("detect-isdataat: DetectIsdataatParse: isdataat out of range\n");
free(idad);
idad=NULL;
idad->dataat = 0;
if (args[0] != NULL) {
if (ByteExtractStringUint16(&idad->dataat, 10,
strlen(args[0]), args[0]) < 0 ) {
printf("detect-isdataat: DetectIsdataatParse: isdataat out of range\n");
free(idad);
idad=NULL;
goto error;
}
} else {
goto error;
}
if(args[1] !=NULL)
{
if (args[1] !=NULL) {
idad->flags |= ISDATAAT_RELATIVE;
if(args[2] !=NULL)
idad->flags |= ISDATAAT_RAWBYTES;
}
for (i = 0; i < (ret -1); i++){
for (i = 0; i < (ret -1); i++) {
if (args[i] != NULL) free(args[i]);
}
@ -212,64 +208,45 @@ int DetectIsdataatSetup (DetectEngineCtx *de_ctx, Signature *s, SigMatch *m, cha
{
DetectIsdataatData *idad = NULL;
SigMatch *sm = NULL;
SigMatch *search_sm_content = NULL;
DetectContentData *cd = NULL;
idad = DetectIsdataatParse(isdataatstr);
if (idad == NULL) goto error;
if(idad->flags & ISDATAAT_RELATIVE)
{
/// Set it in the last parsed contet because it is relative to that content match
if(idad->flags & ISDATAAT_RELATIVE) {
/** Set it in the last parsed contet because it is relative to that content match */
SCLogDebug("set it in the last parsed content because it is relative to that content match");
if( m == NULL )
{
if( m == NULL ) {
printf("detect-isdataat: No previous content, the flag 'relative' cant be used without content\n");
goto error;
}
else
{
search_sm_content=m;
/// Searching last content
uint8_t found=0;
while(search_sm_content != NULL && !found)
{
if(search_sm_content->type== DETECT_CONTENT) //Found content
found=1;
else
search_sm_content=search_sm_content->prev;
} else {
SigMatch *pm = NULL;
/** Search for the first previous DetectContent
* SigMatch (it can be the same as this one) */
pm = DetectContentFindApplicableSM(m);
if (pm == NULL) {
printf("DetectIsdataatSetup: Unknown previous keyword!\n");
return -1;
}
if(search_sm_content != NULL)
{
/* Found */
cd=(DetectContentData*)search_sm_content->ctx;
if(cd != NULL)
{
cd->flags |= DETECT_CONTENT_ISDATAAT_RELATIVE;
cd->isdataat=idad->dataat;
}
else
{
printf("detect-isdataat: No content data found in a SigMatch of DETECT_CONTENT type\n");
goto error;
}
}
else
{
printf("detect-isdataat: No previous content, the flag 'relative' cant be used without content\n");
goto error;
cd = (DetectContentData *)pm->ctx;
if (cd == NULL) {
printf("DetectIsdataatSetup: Unknown previous keyword!\n");
return -1;
}
cd->flags |= DETECT_CONTENT_ISDATAAT_RELATIVE;
cd->isdataat = idad->dataat;
/** Propagate the changes */
DetectContentPropagateIsdataat(pm);
}
}
else
{
else {
SCLogDebug("set it as a normal SigMatch");
/// else Set it as a normal SigMatch
/** else Set it as a normal SigMatch */
sm = SigMatchAlloc();
if (sm == NULL)
goto error;
@ -362,8 +339,7 @@ int DetectIsdataatTestPacket01 (void) {
/// Parse Isdataat Data: if packet data len is greater or equal than 50 byte it should match
/// The packet has 190 bytes of data so it must match
idad = DetectIsdataatParse("50");
if (idad == NULL)
{
if (idad == NULL) {
printf("DetectIsdataatTestPacket01: expected a DetectIsdataatData pointer (got NULL)\n");
return 0;
}

@ -8,7 +8,7 @@
#define ISDATAAT_MAX 65535
typedef struct DetectIsdataatData_ {
uint32_t dataat; /* data offset to match */
uint16_t dataat; /* data offset to match */
uint8_t flags; /* isdataat options*/
} DetectIsdataatData;

@ -41,10 +41,32 @@ int DetectOffsetSetup (DetectEngineCtx *de_ctx, Signature *s, SigMatch *m, char
//DetectPcreData *pe = (DetectPcreData *)pm->ctx;
//pe->offset = (uint32_t)atoi(str); /* XXX */
//printf("DetectOffsetSetup: set offset %" PRIu32 " for previous pcre\n", pe->offset);
} else if (pm->type == DETECT_CONTENT) {
/** Search for the first previous DetectContent
* SigMatch (it can be the same as this one) */
pm = DetectContentFindApplicableSM(m);
if (pm == NULL) {
printf("DetectOffsetSetup: Unknown previous keyword!\n");
return -1;
}
DetectContentData *cd = (DetectContentData *)pm->ctx;
if (cd == NULL) {
printf("DetectOffsetSetup: Unknown previous keyword!\n");
return -1;
}
cd->offset = (uint32_t)atoi(str); /* XXX */
/** Propagate the modifiers through the first chunk
* (SigMatch) if we're dealing with chunks */
if (cd->flags & DETECT_CONTENT_IS_CHUNK)
DetectContentPropagateOffset(pm);
//DetectContentPrint(cd);
//printf("DetectOffsetSetup: set offset %" PRIu32 " for previous content\n", cd->offset);
} else {
printf("DetectOffsetSetup: Unknown previous keyword!\n");
}

@ -50,14 +50,32 @@ int DetectWithinSetup (DetectEngineCtx *de_ctx, Signature *s, SigMatch *m, char
pe->within = strtol(str, NULL, 10);
pe->flags |= DETECT_PCRE_WITHIN;
//printf("DetectWithinSetup: set within %" PRId32 " for previous pcre\n", pe->within);
} else if (pm->type == DETECT_CONTENT) {
/** Search for the first previous DetectContent
* SigMatch (it can be the same as this one) */
pm = DetectContentFindApplicableSM(m);
if (pm == NULL) {
printf("DetectWithinSetup: Unknown previous keyword!\n");
return -1;
}
DetectContentData *cd = (DetectContentData *)pm->ctx;
if (cd == NULL) {
printf("DetectWithinSetup: Unknown previous keyword!\n");
return -1;
}
cd->within = strtol(str, NULL, 10);
cd->flags |= DETECT_CONTENT_WITHIN;
/** Propagate the modifiers through the first chunk
* (SigMatch) if we're dealing with chunks */
if (cd->flags & DETECT_CONTENT_IS_CHUNK)
DetectContentPropagateWithin(pm);
//DetectContentPrint(cd);
//printf("DetectWithinSetup: set within %" PRId32 " for previous content\n", cd->within);
} else if (pm->type == DETECT_URICONTENT) {
DetectUricontentData *ud = (DetectUricontentData *)pm->ctx;

@ -146,6 +146,7 @@ typedef struct Signature_ {
uint32_t gid; /**< generator id */
SigIntId num; /**< signature number, internal id */
uint32_t id; /**< sid, set by the 'sid' rule keyword */
uint8_t nchunk_groups; /**< Internal chunk grp id (for splitted patterns) */
char *msg;
/** addresses, ports and proto this sig matches on */

@ -59,6 +59,7 @@ void B2gRegisterTests(void);
void MpmB2gRegister (void) {
mpm_table[MPM_B2G].name = "b2g";
mpm_table[MPM_B2G].max_pattern_length = B2G_WORD_SIZE;
mpm_table[MPM_B2G].InitCtx = B2gInitCtx;
mpm_table[MPM_B2G].InitThreadCtx = B2gThreadInitCtx;
mpm_table[MPM_B2G].DestroyCtx = B2gDestroyCtx;

@ -54,6 +54,7 @@ void B3gRegisterTests(void);
void MpmB3gRegister (void) {
mpm_table[MPM_B3G].name = "b3g";
mpm_table[MPM_B3G].max_pattern_length = B3G_WORD_SIZE;
mpm_table[MPM_B3G].InitCtx = B3gInitCtx;
mpm_table[MPM_B3G].InitThreadCtx = B3gThreadInitCtx;
mpm_table[MPM_B3G].DestroyCtx = B3gDestroyCtx;

@ -76,6 +76,7 @@ static uint8_t lowercasetable[256];
void MpmWuManberRegister (void) {
mpm_table[MPM_WUMANBER].name = "wumanber";
mpm_table[MPM_WUMANBER].max_pattern_length = 0;
mpm_table[MPM_WUMANBER].InitCtx = WmInitCtx;
mpm_table[MPM_WUMANBER].InitThreadCtx = WmThreadInitCtx;
mpm_table[MPM_WUMANBER].DestroyCtx = WmDestroyCtx;

@ -248,6 +248,19 @@ MpmEndMatch *MpmAllocEndMatch (MpmCtx *ctx)
return e;
}
/**
* \brief Return the pattern max length of a registered matcher
* \retval 0 if it has no limit
* \retval max_pattern_length of the specified matcher type
* \retval -1 if the type is not registered return -1
*/
int32_t MpmMatcherGetMaxPatternLength(uint16_t matcher) {
if (matcher < MPM_TABLE_SIZE && matcher >= 0)
return mpm_table[matcher].max_pattern_length;
else
return -1;
}
void MpmEndMatchFree(MpmCtx *ctx, MpmEndMatch *em) {
ctx->memory_cnt--;
ctx->memory_size -= sizeof(MpmEndMatch);

@ -97,6 +97,7 @@ typedef struct MpmCtx_ {
typedef struct MpmTableElmt_ {
char *name;
uint8_t max_pattern_length;
void (*InitCtx)(struct MpmCtx_ *);
void (*InitThreadCtx)(struct MpmCtx_ *, struct MpmThreadCtx_ *, uint32_t);
void (*DestroyCtx)(struct MpmCtx_ *);
@ -132,6 +133,9 @@ void MpmMatchFreeSpares(MpmThreadCtx *mpm_ctx, MpmMatch *m);
void MpmTableSetup(void);
void MpmRegisterTests(void);
/** Return the max pattern length of a Matcher type given as arg */
int32_t MpmMatcherGetMaxPatternLength(uint16_t);
void MpmInitCtx (MpmCtx *mpm_ctx, uint16_t matcher);
void MpmInitThreadCtx(MpmThreadCtx *mpm_thread_ctx, uint16_t, uint32_t);

Loading…
Cancel
Save