Adding window and isdataat keyword and some unittests

remotes/origin/master-1.0.x
Pablo Rincon 16 years ago committed by Victor Julien
parent 0941c152fd
commit bdf119ade3

@ -1,3 +1,22 @@
For Debian/Ubuntu Users
=======================
After getting the git copy, you will need to get some depends. This
should be enought to get a binary:
cd your_local_git_branch
sudo apt-get -y install libpcre3 libpcre3-dbg libpcre3-dev build-essential autoconf automake libtool libpcap-dev libnet1-dev libyaml-0-1 libyaml-dev
bash autojunk.sh
./configure --enable-unittests
sudo mkdir /var/log/eidps/
cd src
make
./eidps
*****************
Basic Installation
==================

@ -28,6 +28,8 @@ pkt-var.c pkt-var.h \
host.c host.h \
detect.c detect.h \
detect-engine.c detect-engine.h \
detect-isdataat.c detect-isdataat.h \
detect-window.c detect-window.h \
detect-engine-address.c detect-engine-address.h \
detect-engine-address-ipv4.c detect-engine-address-ipv4.h \
detect-engine-address-ipv6.c detect-engine-address-ipv6.h \

@ -240,6 +240,28 @@ DoDetectContent(ThreadVars *t, DetectEngineThreadCtx *det_ctx, Packet *p, Signat
}
}
}
/* If it has matched, check if it's set a "isdataat" option and process it */
if( match == 1 && co->flags & DETECT_CONTENT_ISDATAAT_RELATIVE )
{
/* if the rest of the payload (from the last match) is less than
the "isdataat" there is no data where the rule expected
so match=0
*/
#ifdef DEBUG
printf("detect-content: isdataat: payload_len: %u, used %u, rest %u, isdataat? %u\n", p->payload_len, (m->offset + co->content_len),p->payload_len - (m->offset + co->content_len), co->isdataat );
#endif
if( ! (p->payload_len - (m->offset + co->content_len) >= co->isdataat) )
match=0;
if(match)
{
#ifdef DEBUG
printf("detect-content: MATCHED\n");
#endif
}
}
return match;
}
@ -458,6 +480,8 @@ void DetectContentFree(void *ptr) {
free(cd);
}
#ifdef UNITTESTS /* UNITTESTS */
/**
* \test DetectCotentParseTest01 this is a test to make sure we can deal with escaped colons
*/
@ -639,10 +663,13 @@ int DetectContentParseTest08 (void) {
}
#endif /* UNITTESTS */
/**
* \brief this function registers unit tests for DetectFlow
*/
void DetectContentRegisterTests(void) {
#ifdef UNITTESTS /* UNITTESTS */
UtRegisterTest("DetectContentParseTest01", DetectContentParseTest01, 1);
UtRegisterTest("DetectContentParseTest02", DetectContentParseTest02, 1);
UtRegisterTest("DetectContentParseTest03", DetectContentParseTest03, 1);
@ -651,5 +678,7 @@ void DetectContentRegisterTests(void) {
UtRegisterTest("DetectContentParseTest06", DetectContentParseTest06, 1);
UtRegisterTest("DetectContentParseTest07", DetectContentParseTest07, 1);
UtRegisterTest("DetectContentParseTest08", DetectContentParseTest08, 1);
#endif /* UNITTESTS */
}

@ -7,6 +7,7 @@
#define DETECT_CONTENT_DISTANCE_NEXT 0x08
#define DETECT_CONTENT_WITHIN_NEXT 0x10
#define DETECT_CONTENT_ISDATAAT_RELATIVE 0x16
#define DETECT_CONTENT_RAWBYTES 0x20
@ -17,6 +18,7 @@ typedef struct DetectContentData_ {
uint16_t depth;
uint16_t offset;
uint32_t isdataat;
int32_t distance;
int32_t within;
uint8_t flags;

@ -0,0 +1,561 @@
/**
* \file
* \author Pablo Rincon <pablo.rincon.crespo@gmail.com>
*
* ISDATAAT part of the detection engine.
*/
#include <pcre.h>
#include "eidps-common.h"
#include "debug.h"
#include "decode.h"
#include "detect.h"
#include "util-unittest.h"
#include "detect-isdataat.h"
#include "detect-content.h"
#include "flow.h"
#include "flow-var.h"
/**
* \brief Regex for parsing our isdataat options
*/
#define PARSE_REGEX "^\\s*([0-9]{1,10})\\s*(,\\s*relative)?\\s*(,\\s*rawbytes\\s*)?\\s*$"
static pcre *parse_regex;
static pcre_extra *parse_regex_study;
int DetectIsdataatMatch (ThreadVars *, DetectEngineThreadCtx *, Packet *, Signature *, SigMatch *);
int DetectIsdataatSetup (DetectEngineCtx *, Signature *, SigMatch *, char *);
void DetectIsdataatRegisterTests(void);
void DetectIsdataatFree(void *);
/**
* \brief Registration function for isdataat: keyword
*/
void DetectIsdataatRegister (void) {
sigmatch_table[DETECT_ISDATAAT].name = "isdataat";
sigmatch_table[DETECT_ISDATAAT].Match = DetectIsdataatMatch;
sigmatch_table[DETECT_ISDATAAT].Setup = DetectIsdataatSetup;
sigmatch_table[DETECT_ISDATAAT].Free = DetectIsdataatFree;
sigmatch_table[DETECT_ISDATAAT].RegisterTests = DetectIsdataatRegisterTests;
const char *eb;
int eo;
int opts = 0;
parse_regex = pcre_compile(PARSE_REGEX, opts, &eb, &eo, 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)
{
printf("pcre study failed: %s\n", eb);
goto error;
}
return;
error:
/* XXX */
return;
}
/**
* \brief This function is used to match isdataat on a packet
* \todo We need to add support for rawbytes
*
* \param t pointer to thread vars
* \param det_ctx pointer to the pattern matcher thread
* \param p pointer to the current packet
* \param m pointer to the sigmatch that we will cast into DetectIsdataatData
*
* \retval 0 no match
* \retval 1 match
*/
int DetectIsdataatMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx, Packet *p, Signature *s, SigMatch *m)
{
DetectIsdataatData *idad = (DetectIsdataatData *)m->ctx;
int ret=0;
#ifdef DEBUG
printf("detect-isdataat: payload len : %u , dataat? %u ; relative? %u ...\n", p->payload_len,idad->dataat,idad->flags &ISDATAAT_RELATIVE);
#endif
if(idad->flags & ISDATAAT_RELATIVE)
{
/* Relative to the last matched content, is not performed here */
#ifdef DEBUG
printf("detect-isdataat: Nothing now, this is checked in detect-content.c!\n");
#endif
}
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 */
#ifdef DEBUG
printf("detect-isdataat: matched with payload len : %u , dataat? %u ; relative? %u ...\n", p->payload_len,idad->dataat,idad->flags &ISDATAAT_RELATIVE);
#endif
}
return ret;
}
/**
* \brief This function is used to parse isdataat options passed via isdataat: keyword
*
* \param isdataatstr Pointer to the user provided isdataat options
*
* \retval idad pointer to DetectIsdataatData on success
* \retval NULL on failure
*/
DetectIsdataatData *DetectIsdataatParse (char *isdataatstr)
{
DetectIsdataatData *idad = NULL;
char *args[3] = {NULL,NULL,NULL};
#define MAX_SUBSTRINGS 30
int ret = 0, res = 0;
int ov[MAX_SUBSTRINGS];
int i=0;
ret = pcre_exec(parse_regex, parse_regex_study, isdataatstr, strlen(isdataatstr), 0, 0, ov, MAX_SUBSTRINGS);
if (ret < 1 || ret > 4) {
goto error;
}
if (ret > 1) {
const char *str_ptr;
res = pcre_get_substring((char *)isdataatstr, ov, MAX_SUBSTRINGS, 1, &str_ptr);
if (res < 0) {
printf("DetectIsdataatParse: pcre_get_substring failed\n");
goto error;
}
args[0] = (char *)str_ptr;
if (ret > 2) {
res = pcre_get_substring((char *)isdataatstr, ov, MAX_SUBSTRINGS, 2, &str_ptr);
if (res < 0) {
printf("DetectIsdataatParse: pcre_get_substring failed\n");
goto error;
}
args[1] = (char *)str_ptr;
}
if (ret > 3) {
res = pcre_get_substring((char *)isdataatstr, ov, MAX_SUBSTRINGS, 3, &str_ptr);
if (res < 0) {
printf("DetectIsdataatParse: pcre_get_substring failed\n");
goto error;
}
args[2] = (char *)str_ptr;
}
idad = malloc(sizeof(DetectIsdataatData));
if (idad == NULL) {
printf("DetectIsdataatParse malloc failed\n");
goto error;
}
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;
goto error;
}
if(args[1] !=NULL)
{
idad->flags |= ISDATAAT_RELATIVE;
if(args[2] !=NULL)
idad->flags |= ISDATAAT_RAWBYTES;
}
for (i = 0; i < (ret -1); i++){
if (args[i] != NULL) free(args[i]);
}
return idad;
}
error:
for (i = 0; i < (ret -1); i++){
if (args[i] != NULL) free(args[i]);
}
if (idad != NULL) DetectIsdataatFree(idad);
return NULL;
}
/**
* \brief this function is used to add the parsed isdataatdata into the current signature
*
* \param de_ctx pointer to the Detection Engine Context
* \param s pointer to the Current Signature
* \param m pointer to the Current SigMatch
* \param isdataatstr pointer to the user provided isdataat options
*
* \retval 0 on Success
* \retval -1 on Failure
*/
int DetectIsdataatSetup (DetectEngineCtx *de_ctx, Signature *s, SigMatch *m, char *isdataatstr)
{
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
#ifdef DEBUG
printf("detect-isdataat: Set it in the last parsed contet because it is relative to that content match\n");
#endif
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;
}
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;
}
}
}
else
{
#ifdef DEBUG
printf("detect-isdataat: Set it as a normal SigMatch\n");
#endif
/// else Set it as a normal SigMatch
sm = SigMatchAlloc();
if (sm == NULL)
goto error;
sm->type = DETECT_ISDATAAT;
sm->ctx = (void *)idad;
SigMatchAppend(s,m,sm);
}
return 0;
error:
if (idad != NULL) DetectIsdataatFree(idad);
if (sm != NULL) free(sm);
return -1;
}
/**
* \brief this function will free memory associated with DetectIsdataatData
*
* \param idad pointer to DetectIsdataatData
*/
void DetectIsdataatFree(void *ptr) {
DetectIsdataatData *idad = (DetectIsdataatData *)ptr;
free(idad);
}
#ifdef UNITTESTS
/**
* \test DetectIsdataatTestParse01 is a test to make sure that we return a correct IsdataatData structure
* when given valid isdataat opt
*/
int DetectIsdataatTestParse01 (void) {
int result = 0;
DetectIsdataatData *idad = NULL;
idad = DetectIsdataatParse("30 ");
if (idad != NULL) {
DetectIsdataatFree(idad);
result = 1;
}
return result;
}
/**
* \test DetectIsdataatTestParse02 is a test to make sure that we return a correct IsdataatData structure
* when given valid isdataat opt
*/
int DetectIsdataatTestParse02 (void) {
int result = 0;
DetectIsdataatData *idad = NULL;
idad = DetectIsdataatParse("30 , relative");
if (idad != NULL && idad->flags & ISDATAAT_RELATIVE && !(idad->flags & ISDATAAT_RAWBYTES)) {
DetectIsdataatFree(idad);
result = 1;
}
return result;
}
/**
* \test DetectIsdataatTestParse03 is a test to make sure that we return a correct IsdataatData structure
* when given valid isdataat opt
*/
int DetectIsdataatTestParse03 (void) {
int result = 0;
DetectIsdataatData *idad = NULL;
idad = DetectIsdataatParse("30,relative, rawbytes ");
if (idad != NULL && idad->flags & ISDATAAT_RELATIVE && idad->flags & ISDATAAT_RAWBYTES) {
DetectIsdataatFree(idad);
result = 1;
}
return result;
}
/**
* \test DetectIsdataatTestPacket01 is a test to check if the packet has data at 50 bytes offset non relative
*
*/
int DetectIsdataatTestPacket01 (void) {
int result = 0;
DetectIsdataatData *idad = NULL;
/// 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)
{
printf("DetectIsdataatTestPacket01: expected a DetectIsdataatData pointer (got NULL)\n");
return 0;
}
/* Buid and decode the packet */
uint8_t raw_eth [] = {
0x00,0x25,0x00,0x9e,0xfa,0xfe,0x00,0x02,0xcf,0x74,0xfe,0xe1,0x08,0x00,0x45,0x00
,0x01,0xcc,0xcb,0x91,0x00,0x00,0x34,0x06,0xdf,0xa8,0xd1,0x55,0xe3,0x67,0xc0,0xa8
,0x64,0x8c,0x00,0x50,0xc0,0xb7,0xd1,0x11,0xed,0x63,0x81,0xa9,0x9a,0x05,0x80,0x18
,0x00,0x75,0x0a,0xdd,0x00,0x00,0x01,0x01,0x08,0x0a,0x09,0x8a,0x06,0xd0,0x12,0x21
,0x2a,0x3b,0x48,0x54,0x54,0x50,0x2f,0x31,0x2e,0x31,0x20,0x33,0x30,0x32,0x20,0x46
,0x6f,0x75,0x6e,0x64,0x0d,0x0a,0x4c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x3a,0x20
,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x67,0x6f,0x6f,0x67,0x6c
,0x65,0x2e,0x65,0x73,0x2f,0x0d,0x0a,0x43,0x61,0x63,0x68,0x65,0x2d,0x43,0x6f,0x6e
,0x74,0x72,0x6f,0x6c,0x3a,0x20,0x70,0x72,0x69,0x76,0x61,0x74,0x65,0x0d,0x0a,0x43
,0x6f,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x54,0x79,0x70,0x65,0x3a,0x20,0x74,0x65,0x78
,0x74,0x2f,0x68,0x74,0x6d,0x6c,0x3b,0x20,0x63,0x68,0x61,0x72,0x73,0x65,0x74,0x3d
,0x55,0x54,0x46,0x2d,0x38,0x0d,0x0a,0x44,0x61,0x74,0x65,0x3a,0x20,0x4d,0x6f,0x6e
,0x2c,0x20,0x31,0x34,0x20,0x53,0x65,0x70,0x20,0x32,0x30,0x30,0x39,0x20,0x30,0x38
,0x3a,0x34,0x38,0x3a,0x33,0x31,0x20,0x47,0x4d,0x54,0x0d,0x0a,0x53,0x65,0x72,0x76
,0x65,0x72,0x3a,0x20,0x67,0x77,0x73,0x0d,0x0a,0x43,0x6f,0x6e,0x74,0x65,0x6e,0x74
,0x2d,0x4c,0x65,0x6e,0x67,0x74,0x68,0x3a,0x20,0x32,0x31,0x38,0x0d,0x0a,0x0d,0x0a
,0x3c,0x48,0x54,0x4d,0x4c,0x3e,0x3c,0x48,0x45,0x41,0x44,0x3e,0x3c,0x6d,0x65,0x74
,0x61,0x20,0x68,0x74,0x74,0x70,0x2d,0x65,0x71,0x75,0x69,0x76,0x3d,0x22,0x63,0x6f
,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x74,0x79,0x70,0x65,0x22,0x20,0x63,0x6f,0x6e,0x74
,0x65,0x6e,0x74,0x3d,0x22,0x74,0x65,0x78,0x74,0x2f,0x68,0x74,0x6d,0x6c,0x3b,0x63
,0x68,0x61,0x72,0x73,0x65,0x74,0x3d,0x75,0x74,0x66,0x2d,0x38,0x22,0x3e,0x0a,0x3c
,0x54,0x49,0x54,0x4c,0x45,0x3e,0x33,0x30,0x32,0x20,0x4d,0x6f,0x76,0x65,0x64,0x3c
,0x2f,0x54,0x49,0x54,0x4c,0x45,0x3e,0x3c,0x2f,0x48,0x45,0x41,0x44,0x3e,0x3c,0x42
,0x4f,0x44,0x59,0x3e,0x0a,0x3c,0x48,0x31,0x3e,0x33,0x30,0x32,0x20,0x4d,0x6f,0x76
,0x65,0x64,0x3c,0x2f,0x48,0x31,0x3e,0x0a,0x54,0x68,0x65,0x20,0x64,0x6f,0x63,0x75
,0x6d,0x65,0x6e,0x74,0x20,0x68,0x61,0x73,0x20,0x6d,0x6f,0x76,0x65,0x64,0x0a,0x3c
,0x41,0x20,0x48,0x52,0x45,0x46,0x3d,0x22,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77
,0x77,0x77,0x2e,0x67,0x6f,0x6f,0x67,0x6c,0x65,0x2e,0x65,0x73,0x2f,0x22,0x3e,0x68
,0x65,0x72,0x65,0x3c,0x2f,0x41,0x3e,0x2e,0x0d,0x0a,0x3c,0x2f,0x42,0x4f,0x44,0x59
,0x3e,0x3c,0x2f,0x48,0x54,0x4d,0x4c,0x3e,0x0d,0x0a };
Packet q;
ThreadVars tv;
DecodeThreadVars dtv;
memset(&tv, 0, sizeof(ThreadVars));
memset(&q, 0, sizeof(Packet));
memset(&dtv, 0, sizeof(DecodeThreadVars));
FlowInitConfig(FLOW_QUIET);
DecodeEthernet(&tv, &dtv, &q, raw_eth, sizeof(raw_eth), NULL);
FlowShutdown();
Packet *p=&q;
if (!(PKT_IS_TCP(p))) {
printf("detect-window: TestPacket01: Packet is not TCP\n");
return 0;
}
/* We dont need DetectEngineThreadCtx inside DetectIsdataatMatch, its just to pass it to
the function, since this is a test for this option
Also a Signature is not really needed
*/
DetectEngineThreadCtx *det_ctx=NULL;
Signature *s=NULL;
/* The data of DetectIsdataatData is retrieved inside DetectIsdataatMatch
from a SigMatch struct, so creating a temporal SigMatch
*/
SigMatch m;
m.ctx=idad;
/* Now that we have what we need, just try to Match! */
result=DetectIsdataatMatch (&tv, det_ctx, p, s, &m);
return result;
}
/**
* \test DetectIsdataatTestPacket02 is a test to check if the packet match 6000 bytes offset non relative (it wont)
*
*/
int DetectIsdataatTestPacket02 (void) {
int result = 0;
DetectIsdataatData *idad = NULL;
/// Parse Isdataat Data: if packet data len is greater or equal than 6000 byte it should match
/// The packet has 190 bytes of data so it must not match
idad = DetectIsdataatParse("6000");
if (idad == NULL)
{
printf("DetectIsdataatTestPacket01: expected a DetectIsdataatData pointer (got NULL)\n");
return 0;
}
/* Buid and decode the packet */
uint8_t raw_eth [] = {
0x00,0x25,0x00,0x9e,0xfa,0xfe,0x00,0x02,0xcf,0x74,0xfe,0xe1,0x08,0x00,0x45,0x00
,0x01,0xcc,0xcb,0x91,0x00,0x00,0x34,0x06,0xdf,0xa8,0xd1,0x55,0xe3,0x67,0xc0,0xa8
,0x64,0x8c,0x00,0x50,0xc0,0xb7,0xd1,0x11,0xed,0x63,0x81,0xa9,0x9a,0x05,0x80,0x18
,0x00,0x75,0x0a,0xdd,0x00,0x00,0x01,0x01,0x08,0x0a,0x09,0x8a,0x06,0xd0,0x12,0x21
,0x2a,0x3b,0x48,0x54,0x54,0x50,0x2f,0x31,0x2e,0x31,0x20,0x33,0x30,0x32,0x20,0x46
,0x6f,0x75,0x6e,0x64,0x0d,0x0a,0x4c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x3a,0x20
,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x67,0x6f,0x6f,0x67,0x6c
,0x65,0x2e,0x65,0x73,0x2f,0x0d,0x0a,0x43,0x61,0x63,0x68,0x65,0x2d,0x43,0x6f,0x6e
,0x74,0x72,0x6f,0x6c,0x3a,0x20,0x70,0x72,0x69,0x76,0x61,0x74,0x65,0x0d,0x0a,0x43
,0x6f,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x54,0x79,0x70,0x65,0x3a,0x20,0x74,0x65,0x78
,0x74,0x2f,0x68,0x74,0x6d,0x6c,0x3b,0x20,0x63,0x68,0x61,0x72,0x73,0x65,0x74,0x3d
,0x55,0x54,0x46,0x2d,0x38,0x0d,0x0a,0x44,0x61,0x74,0x65,0x3a,0x20,0x4d,0x6f,0x6e
,0x2c,0x20,0x31,0x34,0x20,0x53,0x65,0x70,0x20,0x32,0x30,0x30,0x39,0x20,0x30,0x38
,0x3a,0x34,0x38,0x3a,0x33,0x31,0x20,0x47,0x4d,0x54,0x0d,0x0a,0x53,0x65,0x72,0x76
,0x65,0x72,0x3a,0x20,0x67,0x77,0x73,0x0d,0x0a,0x43,0x6f,0x6e,0x74,0x65,0x6e,0x74
,0x2d,0x4c,0x65,0x6e,0x67,0x74,0x68,0x3a,0x20,0x32,0x31,0x38,0x0d,0x0a,0x0d,0x0a
,0x3c,0x48,0x54,0x4d,0x4c,0x3e,0x3c,0x48,0x45,0x41,0x44,0x3e,0x3c,0x6d,0x65,0x74
,0x61,0x20,0x68,0x74,0x74,0x70,0x2d,0x65,0x71,0x75,0x69,0x76,0x3d,0x22,0x63,0x6f
,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x74,0x79,0x70,0x65,0x22,0x20,0x63,0x6f,0x6e,0x74
,0x65,0x6e,0x74,0x3d,0x22,0x74,0x65,0x78,0x74,0x2f,0x68,0x74,0x6d,0x6c,0x3b,0x63
,0x68,0x61,0x72,0x73,0x65,0x74,0x3d,0x75,0x74,0x66,0x2d,0x38,0x22,0x3e,0x0a,0x3c
,0x54,0x49,0x54,0x4c,0x45,0x3e,0x33,0x30,0x32,0x20,0x4d,0x6f,0x76,0x65,0x64,0x3c
,0x2f,0x54,0x49,0x54,0x4c,0x45,0x3e,0x3c,0x2f,0x48,0x45,0x41,0x44,0x3e,0x3c,0x42
,0x4f,0x44,0x59,0x3e,0x0a,0x3c,0x48,0x31,0x3e,0x33,0x30,0x32,0x20,0x4d,0x6f,0x76
,0x65,0x64,0x3c,0x2f,0x48,0x31,0x3e,0x0a,0x54,0x68,0x65,0x20,0x64,0x6f,0x63,0x75
,0x6d,0x65,0x6e,0x74,0x20,0x68,0x61,0x73,0x20,0x6d,0x6f,0x76,0x65,0x64,0x0a,0x3c
,0x41,0x20,0x48,0x52,0x45,0x46,0x3d,0x22,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77
,0x77,0x77,0x2e,0x67,0x6f,0x6f,0x67,0x6c,0x65,0x2e,0x65,0x73,0x2f,0x22,0x3e,0x68
,0x65,0x72,0x65,0x3c,0x2f,0x41,0x3e,0x2e,0x0d,0x0a,0x3c,0x2f,0x42,0x4f,0x44,0x59
,0x3e,0x3c,0x2f,0x48,0x54,0x4d,0x4c,0x3e,0x0d,0x0a };
Packet q;
ThreadVars tv;
DecodeThreadVars dtv;
memset(&tv, 0, sizeof(ThreadVars));
memset(&q, 0, sizeof(Packet));
memset(&dtv, 0, sizeof(DecodeThreadVars));
FlowInitConfig(FLOW_QUIET);
DecodeEthernet(&tv, &dtv, &q, raw_eth, sizeof(raw_eth), NULL);
FlowShutdown();
Packet *p=&q;
if (!(PKT_IS_TCP(p))) {
printf("detect-window: TestPacket02: Packet is not TCP\n");
return 0;
}
/* We dont need DetectEngineThreadCtx inside DetectIsdataatMatch, its just to pass it to
the function, since this is a test for this option
Also a Signature is not really needed
*/
DetectEngineThreadCtx *det_ctx=NULL;
Signature *s=NULL;
/* The data of DetectIsdataatData is retrieved inside DetectIsdataatMatch
from a SigMatch struct, so creating a temporal SigMatch
*/
SigMatch m;
m.ctx=idad;
/* Now that we have what we need, just try to Match! */
result=DetectIsdataatMatch (&tv, det_ctx, p, s, &m);
/* Invert it, we dont want this packet to match */
result=!result;
if(result==0)
printf("detect-isdataat: It has matched with isdataat 6000, expecting not to match\n");
return result;
}
#endif
/**
* \brief this function registers unit tests for DetectIsdataat
*/
void DetectIsdataatRegisterTests(void) {
#ifdef UNITTESTS
UtRegisterTest("DetectIsdataatTestParse01", DetectIsdataatTestParse01, 1);
UtRegisterTest("DetectIsdataatTestParse02", DetectIsdataatTestParse02, 1);
UtRegisterTest("DetectIsdataatTestParse03", DetectIsdataatTestParse03, 1);
UtRegisterTest("DetectIsdataatTestPacket01", DetectIsdataatTestPacket01, 1);
UtRegisterTest("DetectIsdataatTestPacket02", DetectIsdataatTestPacket02, 1);
#endif
}

@ -0,0 +1,19 @@
#ifndef __DETECT_ISDATAAT_H__
#define __DETECT_ISDATAAT_H__
#define ISDATAAT_RELATIVE 0x01
#define ISDATAAT_RAWBYTES 0x02
#define ISDATAAT_MIN 0
#define ISDATAAT_MAX 65535
typedef struct DetectIsdataatData_ {
uint32_t dataat; /* data offset to match */
uint8_t flags; /* isdataat options*/
} DetectIsdataatData;
/* prototypes */
void DetectIsdataatRegister (void);
#endif /* __DETECT_ISDATAAT_H__ */

@ -0,0 +1,499 @@
/**
* \file
* \author Pablo Rincon Crespo <pablo.rincon.crespo@gmail.com>
*
* WINDOW tcp window option, part of the detection engine.
*/
#include <pcre.h>
#include "eidps-common.h"
#include "debug.h"
#include "decode.h"
#include "detect.h"
#include "detect-window.h"
#include "flow.h"
#include "flow-var.h"
#include "util-unittest.h"
/**
* \brief Regex for parsing our window option
*/
#define PARSE_REGEX "^\\s*([!])?\\s*([0-9]{1,9}+)\\s*$"
static pcre *parse_regex;
static pcre_extra *parse_regex_study;
int DetectWindowMatch (ThreadVars *, DetectEngineThreadCtx *, Packet *, Signature *, SigMatch *);
int DetectWindowSetup (DetectEngineCtx *, Signature *, SigMatch *, char *);
void DetectWindowRegisterTests(void);
void DetectWindowFree(void *);
/**
* \brief Registration function for window: keyword
*/
void DetectWindowRegister (void) {
sigmatch_table[DETECT_WINDOW].name = "window";
sigmatch_table[DETECT_WINDOW].Match = DetectWindowMatch;
sigmatch_table[DETECT_WINDOW].Setup = DetectWindowSetup;
sigmatch_table[DETECT_WINDOW].Free = DetectWindowFree;
sigmatch_table[DETECT_WINDOW].RegisterTests = DetectWindowRegisterTests;
const char *eb;
int eo;
int opts = 0;
#ifdef WINDOW_DEBUG
printf("detect-window: Registering window rule option\n");
#endif
parse_regex = pcre_compile(PARSE_REGEX, opts, &eb, &eo, 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)
{
printf("pcre study failed: %s\n", eb);
goto error;
}
return;
error:
/* XXX */
return;
}
/**
* \brief This function is used to match the window size on a packet
*
* \param t pointer to thread vars
* \param det_ctx pointer to the pattern matcher thread
* \param p pointer to the current packet
* \param m pointer to the sigmatch that we will cast into DetectWindowData
*
* \retval 0 no match
* \retval 1 match
*/
int DetectWindowMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx, Packet *p, Signature *s, SigMatch *m)
{
int ret=0;
DetectWindowData *wd = (DetectWindowData *)m->ctx;
if(wd != NULL)
{
/**
* To match a packet with a widow size rule, we need a TCP packet,
* and we must look if the size is negated or not
*/
if (!(PKT_IS_TCP(p))) {
return 0;
}
if((!wd->negated && wd->size==TCP_GET_WINDOW(p)) || (wd->negated && wd->size!=TCP_GET_WINDOW(p)))
{
#ifdef WINDOW_DEBUG
printf("detect-window: packet is TCP Proto and matched with packet window size %d and rule option size %d negated: %d!!!\n", TCP_GET_WINDOW(p), wd->size, wd->negated);
#endif
ret=1;
}
}
return ret;
}
/**
* \brief This function is used to parse window options passed via window: keyword
*
* \param windowstr Pointer to the user provided window options (negation! and size)
*
* \retval wd pointer to DetectWindowData on success
* \retval NULL on failure
*/
DetectWindowData *DetectWindowParse (char *windowstr)
{
DetectWindowData *wd = NULL;
char *args[3] = {NULL,NULL,NULL}; /* PR: Why PCRE MAX_SUBSTRING must be multiple of 3? */
#define MAX_SUBSTRINGS 30
int ret = 0, res = 0;
int ov[MAX_SUBSTRINGS];
ret = pcre_exec(parse_regex, parse_regex_study, windowstr, strlen(windowstr), 0, 0, ov, MAX_SUBSTRINGS);
if (ret < 1 || ret > 3) {
goto error;
}
wd = malloc(sizeof(DetectWindowData));
if (wd == NULL) {
printf("DetectWindowParse malloc failed\n");
goto error;
}
if (ret > 1) {
const char *str_ptr;
res = pcre_get_substring((char *)windowstr, ov, MAX_SUBSTRINGS, 1, &str_ptr);
if (res < 0) {
printf("DetectWindowParse: pcre_get_substring failed\n");
goto error;
}
args[0] = (char *)str_ptr;
/// Detect if it's negated
if(args[0][0]=='!')
wd->negated=1;
else
wd->negated=0;
#ifdef WINDOW_DEBUG
if(wd->negated)
printf("detect-window: Negation: %s\n", windowstr);
#endif
if (ret > 2) {
res = pcre_get_substring((char *)windowstr, ov, MAX_SUBSTRINGS, 2, &str_ptr);
if (res < 0) {
printf("DetectWindowParse: pcre_get_substring failed\n");
goto error;
}
wd->size = atoi((char *)str_ptr);
/// Get the window size if it's a valid value (in packets, we should alert if this doesn't happend from decode)
if(wd->size<MIN_WINDOW_VALUE || wd->size>MAX_WINDOW_VALUE) //If greater than 1GB window
{
goto error;
}
#ifdef WINDOW_DEBUG
printf("detect-window: window size-> %u\n", wd->size);
#endif
}
}
int i=0;
for (i = 0; i < (ret -1); i++){
if (args[i] != NULL) free(args[i]);
}
return wd;
error:
for (i = 0; i < (ret -1); i++){
if (args[i] != NULL) free(args[i]);
}
if (wd != NULL) DetectWindowFree(wd);
return NULL;
}
/**
* \brief this function is used to add the parsed window sizedata into the current signature
*
* \param de_ctx pointer to the Detection Engine Context
* \param s pointer to the Current Signature
* \param m pointer to the Current SigMatch
* \param windowstr pointer to the user provided window options
*
* \retval 0 on Success
* \retval -1 on Failure
*/
int DetectWindowSetup (DetectEngineCtx *de_ctx, Signature *s, SigMatch *m, char *windowstr)
{
DetectWindowData *wd = NULL;
SigMatch *sm = NULL;
wd = DetectWindowParse(windowstr);
if (wd == NULL) goto error;
/* Okay so far so good, lets get this into a SigMatch
* and put it in the Signature. */
sm = SigMatchAlloc();
if (sm == NULL)
goto error;
sm->type = DETECT_WINDOW;
sm->ctx = (void *)wd;
SigMatchAppend(s,m,sm);
return 0;
error:
if (wd != NULL) DetectWindowFree(wd);
if (sm != NULL) free(sm);
return -1;
}
/**
* \brief this function will free memory associated with DetectWindowData
*
* \param wd pointer to DetectWindowData
*/
void DetectWindowFree(void *ptr) {
DetectWindowData *wd = (DetectWindowData *)ptr;
free(wd);
}
#ifdef UNITTESTS /* UNITTESTS */
/**
* \test DetectWindowTestParse01 is a test to make sure that we set the size correctly
* when given valid window opt
*/
int DetectWindowTestParse01 (void) {
int result = 0;
DetectWindowData *wd = NULL;
wd = DetectWindowParse("35402");
if (wd != NULL &&wd->size==35402) {
DetectWindowFree(wd);
result = 1;
}
return result;
}
/**
* \test DetectWindowTestParse02 is a test for setting the window opt negated
*/
int DetectWindowTestParse02 (void) {
int result = 0;
DetectWindowData *wd = NULL;
wd = DetectWindowParse("!35402");
if (wd != NULL) {
if (wd->negated == 1 && wd->size==35402) {
result = 1;
} else {
printf("expected wd->negated=1 and wd->size=35402\n");
}
DetectWindowFree(wd);
}
return result;
}
/**
* \test DetectWindowTestParse03 is a test to check for an empty value
*/
int DetectWindowTestParse03 (void) {
int result = 0;
DetectWindowData *wd = NULL;
wd = DetectWindowParse("");
if (wd == NULL) {
result = 1;
} else {
printf("expected a NULL pointer (It was an empty string)\n");
}
DetectWindowFree(wd);
return result;
}
/**
* \test DetectWindowTestParse03 is a test to check for a big value
*/
int DetectWindowTestParse04 (void) {
int result = 0;
DetectWindowData *wd = NULL;
wd = DetectWindowParse("1235402");
if (wd != NULL) {
printf("expected a NULL pointer (It was exceeding the MAX window size)\n");
DetectWindowFree(wd);
}else
result=1;
return result;
}
/**
* \test DetectWindowTestPacket01 is a test to check window with constructed packets, expecting to match a negated size
* Parse Window Data: if th_win is not 55455 it should Match!
* The packet is less than 55455 so it must match
*/
int DetectWindowTestPacket01 (void) {
int result = 0;
DetectWindowData *wd = NULL;
wd = DetectWindowParse("!55455");
if (wd == NULL)
{
printf("DetectWindowTestPacket01: expected a DetectWindowData pointer (got NULL)\n");
return 0;
}
/* Buid and decode the packet */
uint8_t raw_eth [] = {
0x00,0x25,0x00,0x9e,0xfa,0xfe,0x00,0x02,0xcf,0x74,0xfe,0xe1,0x08,0x00,0x45,0x00
,0x01,0xcc,0xcb,0x91,0x00,0x00,0x34,0x06,0xdf,0xa8,0xd1,0x55,0xe3,0x67,0xc0,0xa8
,0x64,0x8c,0x00,0x50,0xc0,0xb7,0xd1,0x11,0xed,0x63,0x81,0xa9,0x9a,0x05,0x80,0x18
,0x00,0x75,0x0a,0xdd,0x00,0x00,0x01,0x01,0x08,0x0a,0x09,0x8a,0x06,0xd0,0x12,0x21
,0x2a,0x3b,0x48,0x54,0x54,0x50,0x2f,0x31,0x2e,0x31,0x20,0x33,0x30,0x32,0x20,0x46
,0x6f,0x75,0x6e,0x64,0x0d,0x0a,0x4c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x3a,0x20
,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x67,0x6f,0x6f,0x67,0x6c
,0x65,0x2e,0x65,0x73,0x2f,0x0d,0x0a,0x43,0x61,0x63,0x68,0x65,0x2d,0x43,0x6f,0x6e
,0x74,0x72,0x6f,0x6c,0x3a,0x20,0x70,0x72,0x69,0x76,0x61,0x74,0x65,0x0d,0x0a,0x43
,0x6f,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x54,0x79,0x70,0x65,0x3a,0x20,0x74,0x65,0x78
,0x74,0x2f,0x68,0x74,0x6d,0x6c,0x3b,0x20,0x63,0x68,0x61,0x72,0x73,0x65,0x74,0x3d
,0x55,0x54,0x46,0x2d,0x38,0x0d,0x0a,0x44,0x61,0x74,0x65,0x3a,0x20,0x4d,0x6f,0x6e
,0x2c,0x20,0x31,0x34,0x20,0x53,0x65,0x70,0x20,0x32,0x30,0x30,0x39,0x20,0x30,0x38
,0x3a,0x34,0x38,0x3a,0x33,0x31,0x20,0x47,0x4d,0x54,0x0d,0x0a,0x53,0x65,0x72,0x76
,0x65,0x72,0x3a,0x20,0x67,0x77,0x73,0x0d,0x0a,0x43,0x6f,0x6e,0x74,0x65,0x6e,0x74
,0x2d,0x4c,0x65,0x6e,0x67,0x74,0x68,0x3a,0x20,0x32,0x31,0x38,0x0d,0x0a,0x0d,0x0a
,0x3c,0x48,0x54,0x4d,0x4c,0x3e,0x3c,0x48,0x45,0x41,0x44,0x3e,0x3c,0x6d,0x65,0x74
,0x61,0x20,0x68,0x74,0x74,0x70,0x2d,0x65,0x71,0x75,0x69,0x76,0x3d,0x22,0x63,0x6f
,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x74,0x79,0x70,0x65,0x22,0x20,0x63,0x6f,0x6e,0x74
,0x65,0x6e,0x74,0x3d,0x22,0x74,0x65,0x78,0x74,0x2f,0x68,0x74,0x6d,0x6c,0x3b,0x63
,0x68,0x61,0x72,0x73,0x65,0x74,0x3d,0x75,0x74,0x66,0x2d,0x38,0x22,0x3e,0x0a,0x3c
,0x54,0x49,0x54,0x4c,0x45,0x3e,0x33,0x30,0x32,0x20,0x4d,0x6f,0x76,0x65,0x64,0x3c
,0x2f,0x54,0x49,0x54,0x4c,0x45,0x3e,0x3c,0x2f,0x48,0x45,0x41,0x44,0x3e,0x3c,0x42
,0x4f,0x44,0x59,0x3e,0x0a,0x3c,0x48,0x31,0x3e,0x33,0x30,0x32,0x20,0x4d,0x6f,0x76
,0x65,0x64,0x3c,0x2f,0x48,0x31,0x3e,0x0a,0x54,0x68,0x65,0x20,0x64,0x6f,0x63,0x75
,0x6d,0x65,0x6e,0x74,0x20,0x68,0x61,0x73,0x20,0x6d,0x6f,0x76,0x65,0x64,0x0a,0x3c
,0x41,0x20,0x48,0x52,0x45,0x46,0x3d,0x22,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77
,0x77,0x77,0x2e,0x67,0x6f,0x6f,0x67,0x6c,0x65,0x2e,0x65,0x73,0x2f,0x22,0x3e,0x68
,0x65,0x72,0x65,0x3c,0x2f,0x41,0x3e,0x2e,0x0d,0x0a,0x3c,0x2f,0x42,0x4f,0x44,0x59
,0x3e,0x3c,0x2f,0x48,0x54,0x4d,0x4c,0x3e,0x0d,0x0a };
Packet q;
ThreadVars tv;
DecodeThreadVars dtv;
memset(&tv, 0, sizeof(ThreadVars));
memset(&q, 0, sizeof(Packet));
memset(&dtv, 0, sizeof(DecodeThreadVars));
FlowInitConfig(FLOW_QUIET);
DecodeEthernet(&tv, &dtv, &q, raw_eth, sizeof(raw_eth), NULL);
FlowShutdown();
Packet *p=&q;
if (!(PKT_IS_TCP(p))) {
printf("detect-window: TestPacket01: Packet is not TCP\n");
return 0;
}
/* We dont need DetectEngineThreadCtx inside DetectWindowMatch, its just to pass it to
the function, since this is a test for this option
Also a Signature is not really needed
*/
DetectEngineThreadCtx *det_ctx=NULL;
Signature *s=NULL;
SigMatch m;
m.ctx=wd;
/* Now that we have what we need, just try to Match! */
result=DetectWindowMatch (&tv, det_ctx, p, s, &m);
return result;
}
/**
* \test DetectWindowTestPacket02 is a test to check window with constructed packets, expecting to match a size
* Parse Window Data: if th_win is 190 it should Match!
* The packet tcp window is 190 so it must match
*/
int DetectWindowTestPacket02 (void) {
int result = 0;
DetectWindowData *wd = NULL;
wd = DetectWindowParse("117");
if (wd == NULL)
{
printf("DetectWindowTestPacket02: expected a DetectWindowData pointer (got NULL)\n");
return 0;
}
uint8_t raw_eth [] = {
0x00,0x25,0x00,0x9e,0xfa,0xfe,0x00,0x02,0xcf,0x74,0xfe,0xe1,0x08,0x00,0x45,0x00
,0x01,0xcc,0xcb,0x91,0x00,0x00,0x34,0x06,0xdf,0xa8,0xd1,0x55,0xe3,0x67,0xc0,0xa8
,0x64,0x8c,0x00,0x50,0xc0,0xb7,0xd1,0x11,0xed,0x63,0x81,0xa9,0x9a,0x05,0x80,0x18
,0x00,0x75,0x0a,0xdd,0x00,0x00,0x01,0x01,0x08,0x0a,0x09,0x8a,0x06,0xd0,0x12,0x21
,0x2a,0x3b,0x48,0x54,0x54,0x50,0x2f,0x31,0x2e,0x31,0x20,0x33,0x30,0x32,0x20,0x46
,0x6f,0x75,0x6e,0x64,0x0d,0x0a,0x4c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x3a,0x20
,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x67,0x6f,0x6f,0x67,0x6c
,0x65,0x2e,0x65,0x73,0x2f,0x0d,0x0a,0x43,0x61,0x63,0x68,0x65,0x2d,0x43,0x6f,0x6e
,0x74,0x72,0x6f,0x6c,0x3a,0x20,0x70,0x72,0x69,0x76,0x61,0x74,0x65,0x0d,0x0a,0x43
,0x6f,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x54,0x79,0x70,0x65,0x3a,0x20,0x74,0x65,0x78
,0x74,0x2f,0x68,0x74,0x6d,0x6c,0x3b,0x20,0x63,0x68,0x61,0x72,0x73,0x65,0x74,0x3d
,0x55,0x54,0x46,0x2d,0x38,0x0d,0x0a,0x44,0x61,0x74,0x65,0x3a,0x20,0x4d,0x6f,0x6e
,0x2c,0x20,0x31,0x34,0x20,0x53,0x65,0x70,0x20,0x32,0x30,0x30,0x39,0x20,0x30,0x38
,0x3a,0x34,0x38,0x3a,0x33,0x31,0x20,0x47,0x4d,0x54,0x0d,0x0a,0x53,0x65,0x72,0x76
,0x65,0x72,0x3a,0x20,0x67,0x77,0x73,0x0d,0x0a,0x43,0x6f,0x6e,0x74,0x65,0x6e,0x74
,0x2d,0x4c,0x65,0x6e,0x67,0x74,0x68,0x3a,0x20,0x32,0x31,0x38,0x0d,0x0a,0x0d,0x0a
,0x3c,0x48,0x54,0x4d,0x4c,0x3e,0x3c,0x48,0x45,0x41,0x44,0x3e,0x3c,0x6d,0x65,0x74
,0x61,0x20,0x68,0x74,0x74,0x70,0x2d,0x65,0x71,0x75,0x69,0x76,0x3d,0x22,0x63,0x6f
,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x74,0x79,0x70,0x65,0x22,0x20,0x63,0x6f,0x6e,0x74
,0x65,0x6e,0x74,0x3d,0x22,0x74,0x65,0x78,0x74,0x2f,0x68,0x74,0x6d,0x6c,0x3b,0x63
,0x68,0x61,0x72,0x73,0x65,0x74,0x3d,0x75,0x74,0x66,0x2d,0x38,0x22,0x3e,0x0a,0x3c
,0x54,0x49,0x54,0x4c,0x45,0x3e,0x33,0x30,0x32,0x20,0x4d,0x6f,0x76,0x65,0x64,0x3c
,0x2f,0x54,0x49,0x54,0x4c,0x45,0x3e,0x3c,0x2f,0x48,0x45,0x41,0x44,0x3e,0x3c,0x42
,0x4f,0x44,0x59,0x3e,0x0a,0x3c,0x48,0x31,0x3e,0x33,0x30,0x32,0x20,0x4d,0x6f,0x76
,0x65,0x64,0x3c,0x2f,0x48,0x31,0x3e,0x0a,0x54,0x68,0x65,0x20,0x64,0x6f,0x63,0x75
,0x6d,0x65,0x6e,0x74,0x20,0x68,0x61,0x73,0x20,0x6d,0x6f,0x76,0x65,0x64,0x0a,0x3c
,0x41,0x20,0x48,0x52,0x45,0x46,0x3d,0x22,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77
,0x77,0x77,0x2e,0x67,0x6f,0x6f,0x67,0x6c,0x65,0x2e,0x65,0x73,0x2f,0x22,0x3e,0x68
,0x65,0x72,0x65,0x3c,0x2f,0x41,0x3e,0x2e,0x0d,0x0a,0x3c,0x2f,0x42,0x4f,0x44,0x59
,0x3e,0x3c,0x2f,0x48,0x54,0x4d,0x4c,0x3e,0x0d,0x0a };
Packet q;
ThreadVars tv;
DecodeThreadVars dtv;
memset(&tv, 0, sizeof(ThreadVars));
memset(&q, 0, sizeof(Packet));
memset(&dtv, 0, sizeof(DecodeThreadVars));
FlowInitConfig(FLOW_QUIET);
DecodeEthernet(&tv, &dtv, &q, raw_eth, sizeof(raw_eth), NULL);
FlowShutdown();
Packet *p=&q;
if (!(PKT_IS_TCP(p))) {
printf("DetectWindowTestPacket02: TestPacket01: Packet is not TCP\n");
return 0;
}
DetectEngineThreadCtx *det_ctx=NULL;
Signature *s=NULL;
SigMatch m;
m.ctx=wd;
/* Now that we have what we need, just try to Match! */
result=DetectWindowMatch (&tv, det_ctx, p, s, &m);
return result;
}
#endif /* UNITTESTS */
/**
* \brief this function registers unit tests for DetectWindow
*/
void DetectWindowRegisterTests(void) {
#ifdef UNITTESTS /* UNITTESTS */
UtRegisterTest("DetectWindowTestParse01", DetectWindowTestParse01, 1);
UtRegisterTest("DetectWindowTestParse02", DetectWindowTestParse02, 1);
UtRegisterTest("DetectWindowTestParse03", DetectWindowTestParse03, 1);
UtRegisterTest("DetectWindowTestParse04", DetectWindowTestParse04, 1);
UtRegisterTest("DetectWindowTestPacket01" , DetectWindowTestPacket01 , 1);
UtRegisterTest("DetectWindowTestPacket02" , DetectWindowTestPacket02 , 1);
#endif /* UNITTESTS */
}

@ -0,0 +1,16 @@
#ifndef __DETECT_WINDOW_H__
#define __DETECT_WINDOW_H__
#define MIN_WINDOW_VALUE 0
#define MAX_WINDOW_VALUE 65535
typedef struct DetectWindowData_ {
uint8_t negated; /** negated? 1=True : 0=False */
uint32_t size; /** window size to match */
} DetectWindowData;
/* prototypes */
void DetectWindowRegister (void);
#endif /* __DETECT_WINDOW_H__ */

@ -40,6 +40,8 @@
#include "detect-msg.h"
#include "detect-rev.h"
#include "detect-flow.h"
#include "detect-window.h"
#include "detect-isdataat.h"
#include "detect-dsize.h"
#include "detect-flowvar.h"
#include "detect-pktvar.h"
@ -568,6 +570,10 @@ static int SignatureIsIPOnly(DetectEngineCtx *de_ctx, Signature *s) {
return 0;
} else if (sm->type == DETECT_FLOW) {
return 0;
} else if (sm->type == DETECT_WINDOW) {
return 0;
} else if (sm->type == DETECT_ISDATAAT) {
return 0;
} else if (sm->type == DETECT_PKTVAR) {
return 0;
} else if (sm->type == DETECT_FLOWVAR) {
@ -2497,6 +2503,8 @@ void SigTableSetup(void) {
DetectDistanceRegister();
DetectOffsetRegister();
DetectFlowRegister();
DetectWindowRegister();
DetectIsdataatRegister();
DetectDsizeRegister();
DetectFlowvarRegister();
DetectPktvarRegister();
@ -5916,6 +5924,253 @@ static int SigTest39Wm (void) {
}
/**
* \test SigTestContentAndIsdataatKeywords01 is a test to check window with constructed packets,
* \brief expecting to match a size
*/
int SigTestContentAndIsdataatKeywords01Real (int mpm_type) {
int result = 0;
// Buid and decode the packet
uint8_t raw_eth [] = {
0x00,0x25,0x00,0x9e,0xfa,0xfe,0x00,0x02,0xcf,0x74,0xfe,0xe1,0x08,0x00,0x45,0x00
,0x01,0xcc,0xcb,0x91,0x00,0x00,0x34,0x06,0xdf,0xa8,0xd1,0x55,0xe3,0x67,0xc0,0xa8
,0x64,0x8c,0x00,0x50,0xc0,0xb7,0xd1,0x11,0xed,0x63,0x81,0xa9,0x9a,0x05,0x80,0x18
,0x00,0x75,0x0a,0xdd,0x00,0x00,0x01,0x01,0x08,0x0a,0x09,0x8a,0x06,0xd0,0x12,0x21
,0x2a,0x3b,0x48,0x54,0x54,0x50,0x2f,0x31,0x2e,0x31,0x20,0x33,0x30,0x32,0x20,0x46
,0x6f,0x75,0x6e,0x64,0x0d,0x0a,0x4c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x3a,0x20
,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x67,0x6f,0x6f,0x67,0x6c
,0x65,0x2e,0x65,0x73,0x2f,0x0d,0x0a,0x43,0x61,0x63,0x68,0x65,0x2d,0x43,0x6f,0x6e
,0x74,0x72,0x6f,0x6c,0x3a,0x20,0x70,0x72,0x69,0x76,0x61,0x74,0x65,0x0d,0x0a,0x43
,0x6f,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x54,0x79,0x70,0x65,0x3a,0x20,0x74,0x65,0x78
,0x74,0x2f,0x68,0x74,0x6d,0x6c,0x3b,0x20,0x63,0x68,0x61,0x72,0x73,0x65,0x74,0x3d
,0x55,0x54,0x46,0x2d,0x38,0x0d,0x0a,0x44,0x61,0x74,0x65,0x3a,0x20,0x4d,0x6f,0x6e
,0x2c,0x20,0x31,0x34,0x20,0x53,0x65,0x70,0x20,0x32,0x30,0x30,0x39,0x20,0x30,0x38
,0x3a,0x34,0x38,0x3a,0x33,0x31,0x20,0x47,0x4d,0x54,0x0d,0x0a,0x53,0x65,0x72,0x76
,0x65,0x72,0x3a,0x20,0x67,0x77,0x73,0x0d,0x0a,0x43,0x6f,0x6e,0x74,0x65,0x6e,0x74
,0x2d,0x4c,0x65,0x6e,0x67,0x74,0x68,0x3a,0x20,0x32,0x31,0x38,0x0d,0x0a,0x0d,0x0a
,0x3c,0x48,0x54,0x4d,0x4c,0x3e,0x3c,0x48,0x45,0x41,0x44,0x3e,0x3c,0x6d,0x65,0x74
,0x61,0x20,0x68,0x74,0x74,0x70,0x2d,0x65,0x71,0x75,0x69,0x76,0x3d,0x22,0x63,0x6f
,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x74,0x79,0x70,0x65,0x22,0x20,0x63,0x6f,0x6e,0x74
,0x65,0x6e,0x74,0x3d,0x22,0x74,0x65,0x78,0x74,0x2f,0x68,0x74,0x6d,0x6c,0x3b,0x63
,0x68,0x61,0x72,0x73,0x65,0x74,0x3d,0x75,0x74,0x66,0x2d,0x38,0x22,0x3e,0x0a,0x3c
,0x54,0x49,0x54,0x4c,0x45,0x3e,0x33,0x30,0x32,0x20,0x4d,0x6f,0x76,0x65,0x64,0x3c
,0x2f,0x54,0x49,0x54,0x4c,0x45,0x3e,0x3c,0x2f,0x48,0x45,0x41,0x44,0x3e,0x3c,0x42
,0x4f,0x44,0x59,0x3e,0x0a,0x3c,0x48,0x31,0x3e,0x33,0x30,0x32,0x20,0x4d,0x6f,0x76
,0x65,0x64,0x3c,0x2f,0x48,0x31,0x3e,0x0a,0x54,0x68,0x65,0x20,0x64,0x6f,0x63,0x75
,0x6d,0x65,0x6e,0x74,0x20,0x68,0x61,0x73,0x20,0x6d,0x6f,0x76,0x65,0x64,0x0a,0x3c
,0x41,0x20,0x48,0x52,0x45,0x46,0x3d,0x22,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77
,0x77,0x77,0x2e,0x67,0x6f,0x6f,0x67,0x6c,0x65,0x2e,0x65,0x73,0x2f,0x22,0x3e,0x68
,0x65,0x72,0x65,0x3c,0x2f,0x41,0x3e,0x2e,0x0d,0x0a,0x3c,0x2f,0x42,0x4f,0x44,0x59
,0x3e,0x3c,0x2f,0x48,0x54,0x4d,0x4c,0x3e,0x0d,0x0a };
Packet p;
DecodeThreadVars dtv;
ThreadVars th_v;
DetectEngineThreadCtx *det_ctx;
memset(&p, 0, sizeof(Packet));
memset(&dtv, 0, sizeof(DecodeThreadVars));
memset(&th_v, 0, sizeof(th_v));
FlowInitConfig(FLOW_QUIET);
DecodeEthernet(&th_v, &dtv, &p, raw_eth, sizeof(raw_eth), NULL);
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
if (de_ctx == NULL) {
goto end;
}
de_ctx->flags |= DE_QUIET;
de_ctx->sig_list = SigInit(de_ctx,"alert tcp any any -> any any (msg:\"SigTestContentAndIsdataatKeywords01 \"; content:\"HTTP\"; isdataat:404, relative; sid:101;)");
if (de_ctx->sig_list == NULL) {
result = 0;
goto end;
}
SigGroupBuild(de_ctx);
PatternMatchPrepare(mpm_ctx, mpm_type);
DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
SigMatchSignatures(&th_v, de_ctx, det_ctx, &p);
if (PacketAlertCheck(&p, 101) == 0) {
result = 0;
goto end;
} else {
result=1;
}
SigGroupCleanup(de_ctx);
SigCleanSignatures(de_ctx);
DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
PatternMatchDestroy(mpm_ctx);
DetectEngineCtxFree(de_ctx);
FlowShutdown();
return result;
end:
if(de_ctx)
{
SigGroupCleanup(de_ctx);
SigCleanSignatures(de_ctx);
}
if(det_ctx)
DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
PatternMatchDestroy(mpm_ctx);
if(de_ctx)
DetectEngineCtxFree(de_ctx);
FlowShutdown();
return result;
}
/**
* \test SigTestContentAndIsdataatKeywords02 is a test to check window with constructed packets,
* \brief not expecting to match a size
*/
int SigTestContentAndIsdataatKeywords02Real (int mpm_type) {
int result = 0;
// Buid and decode the packet
uint8_t raw_eth [] = {
0x00,0x25,0x00,0x9e,0xfa,0xfe,0x00,0x02,0xcf,0x74,0xfe,0xe1,0x08,0x00,0x45,0x00
,0x01,0xcc,0xcb,0x91,0x00,0x00,0x34,0x06,0xdf,0xa8,0xd1,0x55,0xe3,0x67,0xc0,0xa8
,0x64,0x8c,0x00,0x50,0xc0,0xb7,0xd1,0x11,0xed,0x63,0x81,0xa9,0x9a,0x05,0x80,0x18
,0x00,0x75,0x0a,0xdd,0x00,0x00,0x01,0x01,0x08,0x0a,0x09,0x8a,0x06,0xd0,0x12,0x21
,0x2a,0x3b,0x48,0x54,0x54,0x50,0x2f,0x31,0x2e,0x31,0x20,0x33,0x30,0x32,0x20,0x46
,0x6f,0x75,0x6e,0x64,0x0d,0x0a,0x4c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x3a,0x20
,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x67,0x6f,0x6f,0x67,0x6c
,0x65,0x2e,0x65,0x73,0x2f,0x0d,0x0a,0x43,0x61,0x63,0x68,0x65,0x2d,0x43,0x6f,0x6e
,0x74,0x72,0x6f,0x6c,0x3a,0x20,0x70,0x72,0x69,0x76,0x61,0x74,0x65,0x0d,0x0a,0x43
,0x6f,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x54,0x79,0x70,0x65,0x3a,0x20,0x74,0x65,0x78
,0x74,0x2f,0x68,0x74,0x6d,0x6c,0x3b,0x20,0x63,0x68,0x61,0x72,0x73,0x65,0x74,0x3d
,0x55,0x54,0x46,0x2d,0x38,0x0d,0x0a,0x44,0x61,0x74,0x65,0x3a,0x20,0x4d,0x6f,0x6e
,0x2c,0x20,0x31,0x34,0x20,0x53,0x65,0x70,0x20,0x32,0x30,0x30,0x39,0x20,0x30,0x38
,0x3a,0x34,0x38,0x3a,0x33,0x31,0x20,0x47,0x4d,0x54,0x0d,0x0a,0x53,0x65,0x72,0x76
,0x65,0x72,0x3a,0x20,0x67,0x77,0x73,0x0d,0x0a,0x43,0x6f,0x6e,0x74,0x65,0x6e,0x74
,0x2d,0x4c,0x65,0x6e,0x67,0x74,0x68,0x3a,0x20,0x32,0x31,0x38,0x0d,0x0a,0x0d,0x0a
,0x3c,0x48,0x54,0x4d,0x4c,0x3e,0x3c,0x48,0x45,0x41,0x44,0x3e,0x3c,0x6d,0x65,0x74
,0x61,0x20,0x68,0x74,0x74,0x70,0x2d,0x65,0x71,0x75,0x69,0x76,0x3d,0x22,0x63,0x6f
,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x74,0x79,0x70,0x65,0x22,0x20,0x63,0x6f,0x6e,0x74
,0x65,0x6e,0x74,0x3d,0x22,0x74,0x65,0x78,0x74,0x2f,0x68,0x74,0x6d,0x6c,0x3b,0x63
,0x68,0x61,0x72,0x73,0x65,0x74,0x3d,0x75,0x74,0x66,0x2d,0x38,0x22,0x3e,0x0a,0x3c
,0x54,0x49,0x54,0x4c,0x45,0x3e,0x33,0x30,0x32,0x20,0x4d,0x6f,0x76,0x65,0x64,0x3c
,0x2f,0x54,0x49,0x54,0x4c,0x45,0x3e,0x3c,0x2f,0x48,0x45,0x41,0x44,0x3e,0x3c,0x42
,0x4f,0x44,0x59,0x3e,0x0a,0x3c,0x48,0x31,0x3e,0x33,0x30,0x32,0x20,0x4d,0x6f,0x76
,0x65,0x64,0x3c,0x2f,0x48,0x31,0x3e,0x0a,0x54,0x68,0x65,0x20,0x64,0x6f,0x63,0x75
,0x6d,0x65,0x6e,0x74,0x20,0x68,0x61,0x73,0x20,0x6d,0x6f,0x76,0x65,0x64,0x0a,0x3c
,0x41,0x20,0x48,0x52,0x45,0x46,0x3d,0x22,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77
,0x77,0x77,0x2e,0x67,0x6f,0x6f,0x67,0x6c,0x65,0x2e,0x65,0x73,0x2f,0x22,0x3e,0x68
,0x65,0x72,0x65,0x3c,0x2f,0x41,0x3e,0x2e,0x0d,0x0a,0x3c,0x2f,0x42,0x4f,0x44,0x59
,0x3e,0x3c,0x2f,0x48,0x54,0x4d,0x4c,0x3e,0x0d,0x0a };
Packet p;
DecodeThreadVars dtv;
ThreadVars th_v;
DetectEngineThreadCtx *det_ctx;
memset(&p, 0, sizeof(Packet));
memset(&dtv, 0, sizeof(DecodeThreadVars));
memset(&th_v, 0, sizeof(th_v));
FlowInitConfig(FLOW_QUIET);
DecodeEthernet(&th_v, &dtv, &p, raw_eth, sizeof(raw_eth), NULL);
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
if (de_ctx == NULL) {
goto end;
}
de_ctx->flags |= DE_QUIET;
de_ctx->sig_list = SigInit(de_ctx,"alert tcp any any -> any any (msg:\"SigTestContentAndIsdataatKeywords01 \"; content:\"HTTP\"; isdataat:500, relative; sid:101;)");
if (de_ctx->sig_list == NULL) {
result = 0;
goto end;
}
SigGroupBuild(de_ctx);
PatternMatchPrepare(mpm_ctx, mpm_type);
DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
SigMatchSignatures(&th_v, de_ctx, det_ctx, &p);
if (PacketAlertCheck(&p, 101) == 0) {
result = 1;
goto end;
} else {
result=0;
}
SigGroupCleanup(de_ctx);
SigCleanSignatures(de_ctx);
DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
PatternMatchDestroy(mpm_ctx);
DetectEngineCtxFree(de_ctx);
FlowShutdown();
return result;
end:
if(de_ctx)
{
SigGroupCleanup(de_ctx);
SigCleanSignatures(de_ctx);
}
if(det_ctx)
DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
PatternMatchDestroy(mpm_ctx);
if(de_ctx)
DetectEngineCtxFree(de_ctx);
FlowShutdown();
return result;
}
// Wrapper functions to pass the mpm_type
static int SigTestContentAndIsdataatKeywords01B2g (void) {
return SigTestContentAndIsdataatKeywords01Real(MPM_B2G);
}
static int SigTestContentAndIsdataatKeywords01B3g (void) {
return SigTestContentAndIsdataatKeywords01Real(MPM_B3G);
}
static int SigTestContentAndIsdataatKeywords01Wm (void) {
return SigTestContentAndIsdataatKeywords01Real(MPM_WUMANBER);
}
static int SigTestContentAndIsdataatKeywords02B2g (void) {
return SigTestContentAndIsdataatKeywords02Real(MPM_B2G);
}
static int SigTestContentAndIsdataatKeywords02B3g (void) {
return SigTestContentAndIsdataatKeywords02Real(MPM_B3G);
}
static int SigTestContentAndIsdataatKeywords02Wm (void) {
return SigTestContentAndIsdataatKeywords02Real(MPM_WUMANBER);
}
#endif /* UNITTESTS */
void SigRegisterTests(void) {
@ -6037,6 +6292,18 @@ void SigRegisterTests(void) {
UtRegisterTest("SigTest35NegativeICMPV4Keyword",
SigTest35NegativeICMPV4Keyword, 1);
/* The following tests check content options with isdataat options
relative to that content match
*/
UtRegisterTest("SigTestContentAndIsdataatKeywords01B2g", SigTestContentAndIsdataatKeywords01B2g, 1);
UtRegisterTest("SigTestContentAndIsdataatKeywords01B3g", SigTestContentAndIsdataatKeywords01B3g, 1);
UtRegisterTest("SigTestContentAndIsdataatKeywords01Wm" , SigTestContentAndIsdataatKeywords01Wm, 1);
UtRegisterTest("SigTestContentAndIsdataatKeywords02B2g", SigTestContentAndIsdataatKeywords02B2g, 1);
UtRegisterTest("SigTestContentAndIsdataatKeywords02B3g", SigTestContentAndIsdataatKeywords02B3g, 1);
UtRegisterTest("SigTestContentAndIsdataatKeywords02Wm" , SigTestContentAndIsdataatKeywords02Wm, 1);
/* We need to enable these tests, as soon as we add the ICMPv6 protocol
support in our rules engine */
//UtRegisterTest("SigTest36ICMPV6Keyword", SigTest36ICMPV6Keyword, 1);

@ -374,6 +374,8 @@ typedef struct SigGroupHead_ {
/** sigmatch is compatible with a decode event only rule */
#define SIGMATCH_DEONLY_COMPAT 0x04
/** Remember to add the options in SignatureIsIPOnly() at detect.c otherwise it wont be part of a signature group */
enum {
DETECT_SID,
DETECT_PRIORITY,
@ -396,6 +398,8 @@ enum {
DETECT_BYTETEST,
DETECT_BYTEJUMP,
DETECT_FLOW,
DETECT_WINDOW,
DETECT_ISDATAAT,
DETECT_DSIZE,
DETECT_FLOWVAR,
DETECT_PKTVAR,

Loading…
Cancel
Save