Adding unittest helper functions for building generic packets, checking arrays of expected match results, perform generic tests, etc. Look at util-unittest-helper.c and detect-ipproto.c for references

remotes/origin/master-1.0.x
Pablo Rincon 17 years ago committed by Victor Julien
parent 095f2cf6ef
commit b6a3395c08

@ -104,6 +104,7 @@ util-mpm-b2g.c util-mpm-b2g.h \
util-mpm-b3g.c util-mpm-b3g.h \
util-cidr.c util-cidr.h \
util-unittest.c util-unittest.h \
util-unittest-helper.c util-unittest-helper.h \
util-hash.c util-hash.h \
util-hashlist.c util-hashlist.h \
util-bloomfilter.c util-bloomfilter.h \

@ -532,7 +532,6 @@ 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 it has matched, check if it's set a "isdataat" option and process it */
if (match == 1 && (co->flags & DETECT_CONTENT_ISDATAAT_RELATIVE) &&
co->negated == 0) {

@ -2,11 +2,14 @@
#define __DETECT_ENGINE_H__
#include "detect.h"
#include "tm-modules.h"
/* prototypes */
DetectEngineCtx *DetectEngineCtxInit(void);
void DetectEngineCtxFree(DetectEngineCtx *);
TmEcode DetectEngineThreadCtxInit(ThreadVars *, void *, void **);
TmEcode DetectEngineThreadCtxDeinit(ThreadVars *, void *);
//inline uint32_t DetectEngineGetMaxSigId(DetectEngineCtx *);
/* faster as a macro than a inline function on my box -- VJ */
#define DetectEngineGetMaxSigId(de_ctx) ((de_ctx)->signum)

@ -22,6 +22,7 @@
#include "util-debug.h"
#include "util-unittest.h"
#include "util-unittest-helper.h"
/**
* \brief Regex for parsing "id" option, matching number or "number"
@ -301,298 +302,51 @@ int DetectIdTestParse04 (void) {
}
/**
* \test DetectIdTestPacket01 is a test to check "id" option with constructed
* packets, expecting to match
* Parse Id Data: expecting ip_id == 41158
* The packet has ip_id == 41158 so it must match
* \test DetectIdTestSig01
* \brief Test to check "id" keyword with constructed packets
*/
int DetectIdTestPacket01 (void) {
DetectIdData *id_d = NULL;
id_d = DetectIdParse(" 41158");
if (id_d == NULL) {
SCLogDebug("DetectIdTestPacket01: expected a DetectIdData pointer"
" (got NULL)\n");
return 0;
}
/* Buid and decode the packet */
uint8_t raw_eth [] = {
0x00, 0x14, 0xf8, 0x50, 0xf9, 0x09, 0x00, 0x10,
0xdc, 0x4f, 0xe6, 0x09, 0x08, 0x00, 0x45, 0x00,
0x00, 0x3c, 0xa0, 0xc6, 0x40, 0x00, 0x40, 0x06,
0xab, 0x46, 0xc0, 0xa8, 0x00, 0xdc, 0x4b, 0x7d,
0xe1, 0xad, 0xbe, 0x23, 0x00, 0x50, 0xf4, 0x66,
0x71, 0xe5, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x02,
0x16, 0xd0, 0x45, 0xf0, 0x00, 0x00, 0x02, 0x04,
0x05, 0xb4, 0x04, 0x02, 0x08, 0x0a, 0x06, 0xae,
0xd1, 0x23, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03,
0x03, 0x06 };
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_IPV4(p))) {
SCLogDebug("detect-id: TestPacket01: Packet is not IPV4\n");
return 0;
}
DetectEngineThreadCtx *det_ctx=NULL;
Signature *s=NULL;
SigMatch m;
m.ctx=id_d;
/* Now that we have what we need, just try to Match! */
return DetectIdMatch (&tv, det_ctx, p, s, &m);
}
/**
* \test DetectIdTestPacket02 is a test to check "id" option with
* constructed packets
* Parse Id Data: expecting ip_id == 41159
* The packet has ip_id == 41158 so it must NOT match
*/
int DetectIdTestPacket02 (void) {
DetectIdData *id_d = NULL;
id_d = DetectIdParse("41159 ");
if (id_d == NULL) {
SCLogDebug("DetectIdTestPacket01: expected a DetectIdData pointer"
" (got NULL)\n");
return 0;
}
/* Buid and decode the packet */
uint8_t raw_eth [] = {
0x00, 0x14, 0xf8, 0x50, 0xf9, 0x09, 0x00, 0x10,
0xdc, 0x4f, 0xe6, 0x09, 0x08, 0x00, 0x45, 0x00,
0x00, 0x3c, 0xa0, 0xc6, 0x40, 0x00, 0x40, 0x06,
0xab, 0x46, 0xc0, 0xa8, 0x00, 0xdc, 0x4b, 0x7d,
0xe1, 0xad, 0xbe, 0x23, 0x00, 0x50, 0xf4, 0x66,
0x71, 0xe5, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x02,
0x16, 0xd0, 0x45, 0xf0, 0x00, 0x00, 0x02, 0x04,
0x05, 0xb4, 0x04, 0x02, 0x08, 0x0a, 0x06, 0xae,
0xd1, 0x23, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03,
0x03, 0x06 };
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_IPV4(p))) {
SCLogDebug("detect-id: TestPacket01: Packet is not IPV4\n");
return 0;
}
DetectEngineThreadCtx *det_ctx=NULL;
Signature *s=NULL;
SigMatch m;
m.ctx=id_d;
/* Now that we have what we need, just try "not" to Match! */
if (DetectIdMatch (&tv, det_ctx, p, s, &m))
return 0;
else
return 1;
}
/**
* \test SigTest41IdKeyword01Real
* \brief Test to check "id" keyword with constructed packets,
* \brief expecting to match the ip->id
*/
int DetectIdTestSig1(void) {
int result = 1;
// Buid and decode the packet
uint8_t raw_eth [] = {
0x00, 0x14, 0xf8, 0x50, 0xf9, 0x09, 0x00, 0x10,
0xdc, 0x4f, 0xe6, 0x09, 0x08, 0x00, 0x45, 0x00,
0x00, 0x3c, 0xa0, 0xc6, 0x40, 0x00, 0x40, 0x06,
0xab, 0x46, 0xc0, 0xa8, 0x00, 0xdc, 0x4b, 0x7d,
0xe1, 0xad, 0xbe, 0x23, 0x00, 0x50, 0xf4, 0x66,
0x71, 0xe5, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x02,
0x16, 0xd0, 0x45, 0xf0, 0x00, 0x00, 0x02, 0x04,
0x05, 0xb4, 0x04, 0x02, 0x08, 0x0a, 0x06, 0xae,
0xd1, 0x23, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03,
0x03, 0x06 };
Packet p;
DecodeThreadVars dtv;
ThreadVars th_v;
DetectEngineThreadCtx *det_ctx = NULL;
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) {
result = 0;
goto end;
}
de_ctx->flags |= DE_QUIET;
de_ctx->sig_list = SigInit(de_ctx,"alert tcp any any -> any any"
" (msg:\"SigTest41IdKeyword01 match\";"
" id:41158; sid:10141;)");
if (de_ctx->sig_list == NULL) {
result = 0;
goto end;
}
SigGroupBuild(de_ctx);
DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
SigMatchSignatures(&th_v, de_ctx, det_ctx, &p);
if (PacketAlertCheck(&p, 10141) == 0) {
result=0;
int DetectIdTestMatch01(void) {
int result = 0;
uint8_t *buf = (uint8_t *)"Hi all!";
uint16_t buflen = strlen((char *)buf);
Packet *p[3];
p[0] = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
p[1] = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_UDP);
p[2] = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_ICMP);
if (p[0] == NULL || p[1] == NULL ||p[2] == NULL)
goto end;
}
SigGroupCleanup(de_ctx);
SigCleanSignatures(de_ctx);
DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
DetectEngineCtxFree(de_ctx);
FlowShutdown();
return result;
end:
if (de_ctx != NULL) {
SigGroupCleanup(de_ctx);
SigCleanSignatures(de_ctx);
}
/* TCP IP id = 1234 */
p[0]->ip4h->ip_id = htons(1234);
if (det_ctx != NULL) {
DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
}
/* UDP IP id = 5678 */
p[1]->ip4h->ip_id = htons(5678);
if (de_ctx != NULL) {
DetectEngineCtxFree(de_ctx);
}
/* UDP IP id = 91011 */
p[2]->ip4h->ip_id = htons(5101);
FlowShutdown();
char *sigs[3];
sigs[0]= "alert ip any any -> any any (msg:\"Testing id 1\"; id:1234; sid:1;)";
sigs[1]= "alert ip any any -> any any (msg:\"Testing id 2\"; id:5678; sid:2;)";
sigs[2]= "alert ip any any -> any any (msg:\"Testing id 3\"; id:5101; sid:3;)";
return result;
}
uint32_t sid[3] = {1, 2, 3};
/**
* \test
* \brief Test to check "id" keyword with constructed packets,
* \brief not expecting to match the ip->id
*/
int DetectIdTestSig2(void) {
int result = 1;
// Buid and decode the packet
uint8_t raw_eth [] = {
0x00, 0x14, 0xf8, 0x50, 0xf9, 0x09, 0x00, 0x10,
0xdc, 0x4f, 0xe6, 0x09, 0x08, 0x00, 0x45, 0x00,
0x00, 0x3c, 0xa0, 0xc6, 0x40, 0x00, 0x40, 0x06,
0xab, 0x46, 0xc0, 0xa8, 0x00, 0xdc, 0x4b, 0x7d,
0xe1, 0xad, 0xbe, 0x23, 0x00, 0x50, 0xf4, 0x66,
0x71, 0xe5, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x02,
0x16, 0xd0, 0x45, 0xf0, 0x00, 0x00, 0x02, 0x04,
0x05, 0xb4, 0x04, 0x02, 0x08, 0x0a, 0x06, 0xae,
0xd1, 0x23, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03,
0x03, 0x06 };
Packet p;
DecodeThreadVars dtv;
ThreadVars th_v;
DetectEngineThreadCtx *det_ctx = NULL;
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) {
result=0;
goto end;
}
uint32_t results[3][3] = {
/* packet 0 match sid 1 but should not match sid 2 */
{1, 0, 0},
/* packet 1 should not match */
{0, 1, 0},
/* packet 2 should not match */
{0, 0, 1} };
de_ctx->flags |= DE_QUIET;
de_ctx->sig_list = SigInit(de_ctx,"alert tcp any any -> any any"
" (msg:\"SigTest42IdKeyword02"
" I should not match!\";"
" id:41159; sid:10142;)");
if (de_ctx->sig_list == NULL) {
result = 0;
goto end;
}
SigGroupBuild(de_ctx);
DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
SigMatchSignatures(&th_v, de_ctx, det_ctx, &p);
if (PacketAlertCheck(&p, 10142) == 1) {
result = 0;
goto end;
}
SigGroupCleanup(de_ctx);
SigCleanSignatures(de_ctx);
DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
DetectEngineCtxFree(de_ctx);
FlowShutdown();
return result;
result = UTHGenericTest(p, 3, sigs, sid, (uint32_t *) results, 3);
UTHFreePackets(p, 3);
end:
if (de_ctx)
{
SigGroupCleanup(de_ctx);
SigCleanSignatures(de_ctx);
}
if (det_ctx)
DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
if (de_ctx)
DetectEngineCtxFree(de_ctx);
FlowShutdown();
return result;
}
#endif /* UNITTESTS */
/**
@ -604,10 +358,7 @@ void DetectIdRegisterTests(void) {
UtRegisterTest("DetectIdTestParse02", DetectIdTestParse02, 1);
UtRegisterTest("DetectIdTestParse03", DetectIdTestParse03, 1);
UtRegisterTest("DetectIdTestParse04", DetectIdTestParse04, 1);
UtRegisterTest("DetectIdTestPacket01", DetectIdTestPacket01 , 1);
UtRegisterTest("DetectIdTestPacket02", DetectIdTestPacket02 , 1);
UtRegisterTest("DetectIdTestSig1", DetectIdTestSig1, 1);
UtRegisterTest("DetectIdTestSig2", DetectIdTestSig2, 1);
UtRegisterTest("DetectIdTestMatch01", DetectIdTestMatch01, 1);
#endif /* UNITTESTS */
}

@ -23,6 +23,7 @@
#include "util-byte.h"
#include "util-unittest.h"
#include "util-unittest-helper.h"
#include "util-debug.h"
@ -521,83 +522,40 @@ end:
}
static int DetectIPProtoTestSig1(void) {
int result = 0;
uint8_t *buf = (uint8_t *)
"GET /one/ HTTP/1.1\r\n"
"Host: one.example.org\r\n"
"\r\n";
uint16_t buflen = strlen((char *)buf);
Packet p;
Signature *s = NULL;
ThreadVars th_v;
DetectEngineThreadCtx *det_ctx;
int result = 0;
memset(&th_v, 0, sizeof(th_v));
memset(&p, 0, sizeof(p));
p.src.family = AF_INET;
p.dst.family = AF_INET;
p.payload = buf;
p.payload_len = buflen;
p.proto = IPPROTO_TCP;
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
if (de_ctx == NULL) {
goto end;
}
//de_ctx->flags |= DE_QUIET;
s = de_ctx->sig_list = SigInit(de_ctx,"alert ip any any -> any any (msg:\"Not tcp\"; ip_proto:!tcp; content:\"GET \"; sid:1;)");
if (s == NULL) {
goto end;
}
s = s->next = SigInit(de_ctx,"alert ip any any -> any any (msg:\"Less than 7\"; content:\"GET \"; ip_proto:<7; sid:2;)");
if (s == NULL) {
goto end;
}
s = s->next = SigInit(de_ctx,"alert ip any any -> any any (msg:\"Greater than 5\"; content:\"GET \"; ip_proto:>5; sid:3;)");
if (s == NULL) {
Packet *p = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
if (p == NULL)
goto end;
}
s = s->next = SigInit(de_ctx,"alert ip any any -> any any (msg:\"Equals tcp\"; content:\"GET \"; ip_proto:tcp; sid:4;)");
if (s == NULL) {
goto end;
}
SigGroupBuild(de_ctx);
DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
SigMatchSignatures(&th_v, de_ctx, det_ctx, &p);
if (PacketAlertCheck(&p, 1)) {
printf("sid 1 alerted, but should not have: ");
goto cleanup;
} else if (PacketAlertCheck(&p, 2) == 0) {
printf("sid 2 did not alert, but should have: ");
goto cleanup;
} else if (PacketAlertCheck(&p, 3) == 0) {
printf("sid 3 did not alert, but should have: ");
goto cleanup;
} else if (PacketAlertCheck(&p, 4) == 0) {
printf("sid 4 did not alert, but should have: ");
goto cleanup;
}
result = 1;
cleanup:
SigGroupCleanup(de_ctx);
SigCleanSignatures(de_ctx);
DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
DetectEngineCtxFree(de_ctx);
char *sigs[4];
sigs[0] = "alert ip any any -> any any (msg:\"Not tcp\"; ip_proto:!tcp; content:\"GET \"; sid:1;)";
sigs[1] = "alert ip any any -> any any (msg:\"Less than 7\"; content:\"GET \"; ip_proto:<7; sid:2;)";
sigs[2] = "alert ip any any -> any any (msg:\"Greater than 5\"; content:\"GET \"; ip_proto:>5; sid:3;)";
sigs[3] = "alert ip any any -> any any (msg:\"Equals tcp\"; content:\"GET \"; ip_proto:tcp; sid:4;)";
/* sids to match */
uint32_t sid[4] = {1, 2, 3, 4};
/* expected matches for each sid within this packet we are testing */
uint32_t results[4] = {0, 1, 1, 1};
/* remember that UTHGenericTest expect the first parameter
* as an array of packet pointers. And also a bidimensional array of results
* For example:
* results[numpacket][position] should hold the number of times
* that the sid at sid[position] matched that packet (should be always 1..)
* But here we built it as unidimensional array
*/
result = UTHGenericTest(&p, 1, sigs, sid, results, 4);
UTHFreePacket(p);
end:
DetectSigGroupPrintMemory();
DetectAddressPrintMemory();
end:
return result;
}

@ -2,7 +2,7 @@
* \file
* \author Pablo Rincon <pablo.rincon.crespo@gmail.com>
*
* ISDATAAT part of the detection engine.
* Isdataat: part of the detection engine.
*/
#include "suricata-common.h"
@ -11,6 +11,7 @@
#include "detect.h"
#include "util-unittest.h"
#include "util-unittest-helper.h"
#include "detect-isdataat.h"
#include "detect-content.h"
@ -83,18 +84,20 @@ error:
int DetectIsdataatMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx, Packet *p, Signature *s, SigMatch *m)
{
DetectIsdataatData *idad = (DetectIsdataatData *)m->ctx;
int ret=0;
SCLogDebug("payload_len: %u , dataat? %u ; relative? %u...", p->payload_len,idad->dataat,idad->flags &ISDATAAT_RELATIVE);
/* 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 */
/* Relative to the last matched content is not performed here, returning match (content should take care of this)*/
if (idad->flags & ISDATAAT_RELATIVE)
return 1;
/* its not relative and we have more data in the packet than the offset of isdataat */
if (p->payload_len >= idad->dataat) {
SCLogDebug("matched with payload_len: %u , dataat? %u ; relative? %u...", p->payload_len,idad->dataat,idad->flags &ISDATAAT_RELATIVE);
return 1;
}
return ret;
return 0;
}
/**
@ -328,192 +331,44 @@ int DetectIsdataatTestParse03 (void) {
}
/**
* \test DetectIsdataatTestPacket01 is a test to check if the packet has data at 50 bytes offset non relative
*
* \test DetectIsdataatTestPacket01 is a test to check matches of
* isdataat, and isdataat 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");
uint8_t *buf = (uint8_t *)"Hi all!";
uint16_t buflen = strlen((char *)buf);
Packet *p[3];
p[0] = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
p[1] = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_UDP);
p[2] = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_ICMP);
if (p[0] == NULL || p[1] == NULL ||p[2] == NULL)
goto end;
char *sigs[5];
sigs[0]= "alert ip any any -> any any (msg:\"Testing window 1\"; isdataat:6; sid:1;)";
sigs[1]= "alert ip any any -> any any (msg:\"Testing window 2\"; content:\"all\"; isdataat:1, relative; isdataat:7; sid:2;)";
sigs[2]= "alert ip any any -> any any (msg:\"Testing window 3\"; isdataat:8; sid:3;)";
sigs[3]= "alert ip any any -> any any (msg:\"Testing window 4\"; content:\"Hi\"; isdataat:5, relative; sid:4;)";
sigs[4]= "alert ip any any -> any any (msg:\"Testing window 4\"; content:\"Hi\"; isdataat:6, relative; sid:5;)";
uint32_t sid[5] = {1, 2, 3, 4, 5};
uint32_t results[3][5] = {
/* packet 0 match sid 1 but should not match sid 2 */
{1, 1, 0, 1, 0},
/* packet 1 should not match */
{1, 1, 0, 1, 0},
/* packet 2 should not match */
{1, 1, 0, 1, 0} };
result = UTHGenericTest(p, 3, sigs, sid, (uint32_t *) results, 5);
UTHFreePackets(p, 3);
end:
return result;
}
#endif
/**
@ -525,6 +380,5 @@ void DetectIsdataatRegisterTests(void) {
UtRegisterTest("DetectIsdataatTestParse02", DetectIsdataatTestParse02, 1);
UtRegisterTest("DetectIsdataatTestParse03", DetectIsdataatTestParse03, 1);
UtRegisterTest("DetectIsdataatTestPacket01", DetectIsdataatTestPacket01, 1);
UtRegisterTest("DetectIsdataatTestPacket02", DetectIsdataatTestPacket02, 1);
#endif
}

@ -541,10 +541,10 @@ int SigParse(DetectEngineCtx *de_ctx, Signature *s, char *sigstr, uint8_t addrs_
if (basics != NULL) {
int i = 0;
while (basics[i] != NULL) {
free(basics[i]);
//free(basics[i]);
i++;
}
free(basics);
//free(basics);
}
SCReturnInt(ret);
@ -825,14 +825,16 @@ error:
Signature *DetectEngineAppendSig(DetectEngineCtx *de_ctx, char *sigstr) {
Signature *sig = SigInitReal(de_ctx, sigstr);
if (sig == NULL)
goto error;
return NULL;
if (sig->flags & SIG_FLAG_BIDIREC) {
if (sig->next != NULL)
if (sig->next != NULL) {
sig->next->next = de_ctx->sig_list;
else
} else {
goto error;
} else {
}
}
else {
/* if this sig is the first one, sig_list should be null */
sig->next = de_ctx->sig_list;
}

@ -20,6 +20,7 @@
#include "util-byte.h"
#include "util-unittest.h"
#include "util-unittest-helper.h"
static int DetectSeqSetup(DetectEngineCtx *, Signature *s, SigMatch *m,
char *sidstr);
@ -124,70 +125,16 @@ static void DetectSeqFree(void *ptr)
#ifdef UNITTESTS
/**
* \internal
* \brief This test tests sameip success and failure.
* \test DetectSeqSigTest01 tests parses
*/
static int DetectSeqSigTest01Real(int mpm_type)
static int DetectSeqSigTest01(void)
{
uint8_t *buf = (uint8_t *)"";
uint16_t buflen = strlen((char *)buf);
Packet p[3];
ThreadVars th_v;
DetectEngineThreadCtx *det_ctx;
int result = 0;
uint8_t tcp_hdr0[] = {
0x00, 0x50, 0x8e, 0x16, 0x0d, 0x59, 0xcd, 0x3c,
0xcf, 0x0d, 0x21, 0x80, 0xa0, 0x12, 0x16, 0xa0,
0xfa, 0x03, 0x00, 0x00, 0x02, 0x04, 0x05, 0xb4,
0x04, 0x02, 0x08, 0x0a, 0x6e, 0x18, 0x78, 0x73,
0x01, 0x71, 0x74, 0xde, 0x01, 0x03, 0x03, 0x02
};
uint8_t tcp_hdr1[] = {
0x00, 0x50, 0x8e, 0x16, 0x0d, 0x59, 0xcd, 0x3c,
0xcf, 0x0d, 0x21, 0x80, 0xa0, 0x12, 0x16, 0xa0,
0xfa, 0x03, 0x00, 0x00, 0x02, 0x04, 0x05, 0xb4,
0x04, 0x02, 0x08, 0x0a, 0x6e, 0x18, 0x78, 0x73,
0x01, 0x71, 0x74, 0xde, 0x01, 0x03, 0x03, 0x02
};
memset(&th_v, 0, sizeof(th_v));
/* TCP w/seq=42 */
memset(&p[0], 0, sizeof(p[0]));
p[0].src.family = AF_INET;
p[0].dst.family = AF_INET;
p[0].payload = buf;
p[0].payload_len = buflen;
p[0].proto = IPPROTO_TCP;
p[0].tcph = (TCPHdr *)tcp_hdr0;
p[0].tcph->th_seq = htonl(42);
/* TCP w/seq=100 */
memset(&p[1], 0, sizeof(p[1]));
p[1].src.family = AF_INET;
p[1].dst.family = AF_INET;
p[1].payload = buf;
p[1].payload_len = buflen;
p[1].proto = IPPROTO_TCP;
p[1].tcph = (TCPHdr *)tcp_hdr1;
p[1].tcph->th_seq = htonl(100);
/* ICMP */
memset(&p[2], 0, sizeof(p[2]));
p[2].src.family = AF_INET;
p[2].dst.family = AF_INET;
p[2].payload = buf;
p[2].payload_len = buflen;
p[2].proto = IPPROTO_ICMP;
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
if (de_ctx == NULL) {
if (de_ctx == NULL)
goto end;
}
de_ctx->mpm_matcher = mpm_type;
de_ctx->flags |= DE_QUIET;
/* These three are crammed in here as there is no Parse */
if (SigInit(de_ctx,
@ -195,107 +142,73 @@ static int DetectSeqSigTest01Real(int mpm_type)
"(msg:\"Testing seq\";seq:foo;sid:1;)") != NULL)
{
printf("invalid seq accepted: ");
goto cleanup_engine;
goto cleanup;
}
if (SigInit(de_ctx,
"alert tcp any any -> any any "
"(msg:\"Testing seq\";seq:9999999999;sid:1;)") != NULL)
{
printf("overflowing seq accepted: ");
goto cleanup_engine;
goto cleanup;
}
if (SigInit(de_ctx,
"alert tcp any any -> any any "
"(msg:\"Testing seq\";seq:-100;sid:1;)") != NULL)
{
printf("negative seq accepted: ");
goto cleanup_engine;
}
de_ctx->sig_list = SigInit(de_ctx,
"alert tcp any any -> any any "
"(msg:\"Testing seq\";seq:41;sid:1;)");
if (de_ctx->sig_list == NULL) {
goto cleanup_engine;
}
de_ctx->sig_list->next = SigInit(de_ctx,
"alert tcp any any -> any any "
"(msg:\"Testing seq\";seq:42;sid:2;)");
if (de_ctx->sig_list->next == NULL) {
goto cleanup_engine;
}
SigGroupBuild(de_ctx);
DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
SigMatchSignatures(&th_v, de_ctx, det_ctx, &p[0]);
if (PacketAlertCheck(&p[0], 1) != 0) {
printf("sid 1 alerted, but should not have: ");
goto cleanup;
}
if (PacketAlertCheck(&p[0], 2) == 0) {
printf("sid 2 did not alert, but should have: ");
goto cleanup;
}
SigMatchSignatures(&th_v, de_ctx, det_ctx, &p[1]);
if (PacketAlertCheck(&p[1], 1) != 0) {
printf("sid 1 alerted, but should not have: ");
goto cleanup;
}
if (PacketAlertCheck(&p[1], 2) != 0) {
printf("sid 2 alerted, but should not have: ");
goto cleanup;
}
SigMatchSignatures(&th_v, de_ctx, det_ctx, &p[1]);
if (PacketAlertCheck(&p[2], 1) != 0) {
printf("sid 1 alerted, but should not have: ");
goto cleanup;
}
if (PacketAlertCheck(&p[2], 2) != 0) {
printf("sid 2 alerted, but should not have: ");
goto cleanup;
}
result = 1;
cleanup:
SigGroupCleanup(de_ctx);
SigCleanSignatures(de_ctx);
DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
cleanup_engine:
DetectEngineCtxFree(de_ctx);
if (de_ctx) {
SigGroupCleanup(de_ctx);
SigCleanSignatures(de_ctx);
DetectEngineCtxFree(de_ctx);
}
end:
return result;
}
/**
* \test DetectSeqSigTest01B2g tests sameip under B2g MPM
* \test DetectSeqSigTest02 tests seq keyword
*/
static int DetectSeqSigTest01B2g(void)
static int DetectSeqSigTest02(void)
{
return DetectSeqSigTest01Real(MPM_B2G);
}
int result = 0;
uint8_t *buf = (uint8_t *)"Hi all!";
uint16_t buflen = strlen((char *)buf);
Packet *p[3];
p[0] = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
p[1] = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
p[2] = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_ICMP);
if (p[0] == NULL || p[1] == NULL ||p[2] == NULL)
goto end;
/**
* \test DetectSeqSigTest01B2g tests sameip under B3g MPM
*/
static int DetectSeqSigTest01B3g(void)
{
return DetectSeqSigTest01Real(MPM_B3G);
}
/* TCP w/seq=42 */
p[0]->tcph->th_seq = htonl(42);
/**
* \test DetectSeqSigTest01B2g tests sameip under WuManber MPM
*/
static int DetectSeqSigTest01Wm(void)
{
return DetectSeqSigTest01Real(MPM_WUMANBER);
/* TCP w/seq=100 */
p[1]->tcph->th_seq = htonl(100);
char *sigs[2];
sigs[0]= "alert tcp any any -> any any (msg:\"Testing seq\"; seq:41; sid:1;)";
sigs[1]= "alert tcp any any -> any any (msg:\"Testing seq\"; seq:42; sid:2;)";
uint32_t sid[2] = {1, 2};
uint32_t results[3][2] = {
/* packet 0 match sid 1 but should not match sid 2 */
{0, 1},
/* packet 1 should not match */
{0, 0},
/* packet 2 should not match */
{0, 0} };
result = UTHGenericTest(p, 3, sigs, sid, (uint32_t *) results, 2);
UTHFreePackets(p, 3);
end:
return result;
}
#endif /* UNITTESTS */
@ -307,9 +220,8 @@ static int DetectSeqSigTest01Wm(void)
static void DetectSeqRegisterTests(void)
{
#ifdef UNITTESTS
UtRegisterTest("DetectSeqSigTest01B2g", DetectSeqSigTest01B2g, 1);
UtRegisterTest("DetectSeqSigTest01B3g", DetectSeqSigTest01B3g, 1);
UtRegisterTest("DetectSeqSigTest01Wm", DetectSeqSigTest01Wm, 1);
UtRegisterTest("DetectSeqSigTest01", DetectSeqSigTest01, 1);
UtRegisterTest("DetectSeqSigTest02", DetectSeqSigTest02, 1);
#endif /* UNITTESTS */
}

@ -14,7 +14,10 @@
#include "flow.h"
#include "flow-var.h"
#include "util-debug.h"
#include "util-unittest.h"
#include "util-unittest-helper.h"
#include "util-byte.h"
/**
* \brief Regex for parsing our window option
@ -24,8 +27,8 @@
static pcre *parse_regex;
static pcre_extra *parse_regex_study;
int DetectWindowMatch (ThreadVars *, DetectEngineThreadCtx *, Packet *, Signature *, SigMatch *);
int DetectWindowSetup (DetectEngineCtx *, Signature *, SigMatch *, char *);
int DetectWindowMatch(ThreadVars *, DetectEngineThreadCtx *, Packet *, Signature *, SigMatch *);
int DetectWindowSetup(DetectEngineCtx *, Signature *, SigMatch *, char *);
void DetectWindowRegisterTests(void);
void DetectWindowFree(void *);
@ -78,32 +81,17 @@ error:
* \retval 0 no match
* \retval 1 match
*/
int DetectWindowMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx, Packet *p, Signature *s, SigMatch *m)
{
int ret=0;
int DetectWindowMatch(ThreadVars *t, DetectEngineThreadCtx *det_ctx, Packet *p, Signature *s, SigMatch *m) {
DetectWindowData *wd = (DetectWindowData *)m->ctx;
if ( !(PKT_IS_TCP(p)) || wd == NULL) {
return 0;
}
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;
}
if ( (!wd->negated && wd->size == TCP_GET_WINDOW(p)) || (wd->negated && wd->size != TCP_GET_WINDOW(p))) {
return 1;
}
return ret;
return 0;
}
/**
@ -114,8 +102,7 @@ int DetectWindowMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx, Packet *p,
* \retval wd pointer to DetectWindowData on success
* \retval NULL on failure
*/
DetectWindowData *DetectWindowParse (char *windowstr)
{
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
@ -145,16 +132,11 @@ DetectWindowData *DetectWindowParse (char *windowstr)
goto error;
}
args[0] = (char *)str_ptr;
// Detect if it's negated
if(args[0][0]=='!')
wd->negated=1;
/* 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
wd->negated = 0;
if (ret > 2) {
res = pcre_get_substring((char *)windowstr, ov, MAX_SUBSTRINGS, 2, &str_ptr);
@ -162,21 +144,20 @@ DetectWindowData *DetectWindowParse (char *windowstr)
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 > MAX_WINDOW_VALUE)
{
/* Get the window size if it's a valid value (in packets, we should alert if this doesn't happend from decode) */
if (-1 == ByteExtractStringUint16(&wd->size, 10, 0, str_ptr)) {
goto error;
}
#ifdef WINDOW_DEBUG
printf("detect-window: window size-> %u\n", wd->size);
#endif
/* If greater than 1GB window */
if (wd->size < MIN_WINDOW_VALUE || wd->size > MAX_WINDOW_VALUE) {
goto error;
}
}
}
int i=0;
int i = 0;
for (i = 0; i < (ret -1); i++){
if (args[i] != NULL) free(args[i]);
}
@ -310,172 +291,44 @@ int DetectWindowTestParse04 (void) {
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
* \test DetectWindowTestPacket01 is a test to check window with constructed packets
*/
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);
uint8_t *buf = (uint8_t *)"Hi all!";
uint16_t buflen = strlen((char *)buf);
Packet *p[3];
p[0] = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
p[1] = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
p[2] = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_ICMP);
if (p[0] == NULL || p[1] == NULL ||p[2] == NULL)
goto end;
/* TCP wwindow = 40 */
p[0]->tcph->th_win = htons(40);
/* TCP window = 41 */
p[1]->tcph->th_win = htons(41);
char *sigs[2];
sigs[0]= "alert tcp any any -> any any (msg:\"Testing window 1\"; window:40; sid:1;)";
sigs[1]= "alert tcp any any -> any any (msg:\"Testing window 2\"; window:41; sid:2;)";
uint32_t sid[2] = {1, 2};
uint32_t results[3][2] = {
/* packet 0 match sid 1 but should not match sid 2 */
{1, 0},
/* packet 1 should not match */
{0, 1},
/* packet 2 should not match */
{0, 0} };
result = UTHGenericTest(p, 3, sigs, sid, (uint32_t *) results, 2);
UTHFreePackets(p, 3);
end:
return result;
}
@ -491,6 +344,5 @@ void DetectWindowRegisterTests(void) {
UtRegisterTest("DetectWindowTestParse03", DetectWindowTestParse03, 1);
UtRegisterTest("DetectWindowTestParse04", DetectWindowTestParse04, 1);
UtRegisterTest("DetectWindowTestPacket01" , DetectWindowTestPacket01 , 1);
UtRegisterTest("DetectWindowTestPacket02" , DetectWindowTestPacket02 , 1);
#endif /* UNITTESTS */
}

@ -6,7 +6,7 @@
typedef struct DetectWindowData_ {
uint8_t negated; /** negated? 1=True : 0=False */
uint32_t size; /** window size to match */
uint16_t size; /** window size to match */
} DetectWindowData;
/* prototypes */

@ -2610,7 +2610,6 @@ int SigAddressCleanupStage1(DetectEngineCtx *de_ctx) {
void DbgPrintSigs(DetectEngineCtx *de_ctx, SigGroupHead *sgh) {
if (sgh == NULL) {
printf("\n");
return;
}
uint32_t sig;

@ -75,6 +75,7 @@
#include "util-host-os-info.h"
#include "util-cidr.h"
#include "util-unittest.h"
#include "util-unittest-helper.h"
#include "util-time.h"
#include "util-rule-vars.h"
#include "util-classification-config.h"
@ -548,6 +549,7 @@ int main(int argc, char **argv)
UtRunSelftest(regex_arg); /* inits and cleans up again */
}
UtInitialize();
UTHRegisterTests();
TmModuleRegisterTests();
SigTableRegisterTests();
HashTableRegisterTests();

@ -0,0 +1,639 @@
/** Copyright (c) 2009 Open Information Security Foundation
*
* \author Pablo Rincon Crespo <pablo.rincon.crespo@gmail.com>
*
* This file provide a set of helper functions for reducing the complexity
* when constructing unittests
*/
#include "suricata-common.h"
#include "decode.h"
#include "detect.h"
#include "detect-parse.h"
#include "util-debug.h"
#include "util-error.h"
#include "util-unittest.h"
#include "util-unittest-helper.h"
#include <stdarg.h>
#include "detect-engine.h"
/**
* \brief UTHBuildPacketReal is a function that create tcp/udp packets for unittests
* specifying ip and port sources and destinations
*
* \param payload pointer to the payloadd buffer
* \param payload_len pointer to the length of the payload
* \param ipproto Protocols allowed atm are IPPROTO_TCP and IPPROTO_UDP
* \param src pointer to a string containing the ip source
* \param dst pointer to a string containing the ip destination
* \param sport pointer to a string containing the port source
* \param dport pointer to a string containing the port destination
*
* \retval Packet pointer to the built in packet
*/
Packet *UTHBuildPacketReal(uint8_t *payload, uint16_t payload_len,
uint16_t ipproto, char *src, char *dst,
uint16_t sport, uint16_t dport) {
struct in_addr in;
Packet *p = malloc(sizeof(Packet));
if (p == NULL) {
SCLogError(SC_ERR_MEM_ALLOC, "Error allocating packet");
exit(EXIT_FAILURE);
}
memset(p, 0, sizeof(Packet));
p->src.family = AF_INET;
p->dst.family = AF_INET;
p->payload = payload;
p->payload_len = payload_len;
p->proto = ipproto;
inet_pton(AF_INET, src, &in);
p->src.addr_data32[0] = in.s_addr;
p->sp = sport;
inet_pton(AF_INET, dst, &in);
p->dst.addr_data32[0] = in.s_addr;
p->dp = dport;
switch(ipproto) {
case IPPROTO_UDP:
p->ip4h = malloc(sizeof(IPV4Hdr));
if (p->ip4h == NULL) {
SCLogError(SC_ERR_MEM_ALLOC, "Error allocating packet ip4h");
exit(EXIT_FAILURE);
}
p->udph = malloc(sizeof(UDPHdr));
if (p->udph == NULL) {
SCLogError(SC_ERR_MEM_ALLOC, "Error allocating packet udph");
exit(EXIT_FAILURE);
}
p->udph->uh_sport = sport;
p->udph->uh_dport = dport;
break;
case IPPROTO_TCP:
p->ip4h = malloc(sizeof(IPV4Hdr));
if (p->ip4h == NULL) {
SCLogError(SC_ERR_MEM_ALLOC, "Error allocating packet ip4h");
exit(EXIT_FAILURE);
}
p->tcph = malloc(sizeof(TCPHdr));
if (p->tcph == NULL) {
SCLogError(SC_ERR_MEM_ALLOC, "Error allocating packet tcph");
exit(EXIT_FAILURE);
}
p->tcph->th_sport = sport;
p->tcph->th_dport = dport;
break;
case IPPROTO_ICMP:
p->ip4h = malloc(sizeof(IPV4Hdr));
if (p->ip4h == NULL) {
SCLogError(SC_ERR_MEM_ALLOC, "Error allocating packet ip4h");
exit(EXIT_FAILURE);
}
break;
/* TODO: Add more protocols */
}
return p;
}
/**
* \brief UTHBuildPacket is a wrapper that build packets with default ip
* and port fields
*
* \param payload pointer to the payloadd buffer
* \param payload_len pointer to the length of the payload
* \param ipproto Protocols allowed atm are IPPROTO_TCP and IPPROTO_UDP
*
* \retval Packet pointer to the built in packet
*/
Packet *UTHBuildPacket(uint8_t *payload, uint16_t payload_len,
uint16_t ipproto) {
return UTHBuildPacketReal(payload, payload_len, ipproto,
"192.168.1.5", "192.168.1.1",
41424, 80);
}
/**
* \brief UTHBuildPacketSrcDst is a wrapper that build packets specifying IPs
* and defaulting ports
*
* \param payload pointer to the payloadd buffer
* \param payload_len pointer to the length of the payload
* \param ipproto Protocols allowed atm are IPPROTO_TCP and IPPROTO_UDP
*
* \retval Packet pointer to the built in packet
*/
Packet *UTHBuildPacketSrcDst(uint8_t *payload, uint16_t payload_len,
uint16_t ipproto, char *src, char *dst) {
return UTHBuildPacketReal(payload, payload_len, ipproto,
src, dst,
41424, 80);
}
/**
* \brief UTHBuildPacketSrcDstPorts is a wrapper that build packets specifying
* src and dst ports and defaulting IPs
*
* \param payload pointer to the payloadd buffer
* \param payload_len pointer to the length of the payload
* \param ipproto Protocols allowed atm are IPPROTO_TCP and IPPROTO_UDP
*
* \retval Packet pointer to the built in packet
*/
Packet *UTHBuildPacketSrcDstPorts(uint8_t *payload, uint16_t payload_len,
uint16_t ipproto, uint16_t sport, uint16_t dport) {
return UTHBuildPacketReal(payload, payload_len, ipproto,
"192.168.1.5", "192.168.1.1",
sport, dport);
}
/**
* \brief UTHFreePackets: function to release the allocated data
* from UTHBuildPacket and the packet itself
*
* \param p pointer to the Packet
*/
void UTHFreePackets(Packet **p, int numpkts) {
if (p == NULL)
return;
int i = 0;
for (; i < numpkts; i++) {
UTHFreePacket(p[i]);
}
}
/**
* \brief UTHFreePacket: function to release the allocated data
* from UTHBuildPacket and the packet itself
*
* \param p pointer to the Packet
*/
void UTHFreePacket(Packet *p) {
if (p == NULL)
return;
switch(p->proto) {
case IPPROTO_UDP:
if (p->udph != NULL)
free(p->udph);
if (p->ip4h != NULL)
free(p->ip4h);
break;
case IPPROTO_TCP:
if (p->tcph != NULL)
free(p->tcph);
if (p->ip4h != NULL)
free(p->ip4h);
break;
case IPPROTO_ICMP:
if (p->ip4h != NULL)
free(p->ip4h);
break;
/* TODO: Add more protocols */
}
free(p);
}
/**
* \brief UTHGenericTest: function that perfom a generic check taking care of
* as maximum common unittest elements as possible.
* It will create a detection engine, append an array
* of signatures an check the spected results for each
* of them, it check matches for an array of packets
*
* \param pkt pointer to the array of packets
* \param numpkts number of packets to match
* \param sigs array of char* pointing to signatures to load
* \param numsigs number of signatures to load and check
* \param results pointer to arrays of numbers, each of them foreach packet
* to check if sids matches that packet as espected with
* that number of times or not. The size of results should be
* numpkts * numsigs * sizeof(uint16_t *)
*
* Example:
* result[1][3] would mean the number of times the pkt[1]
* match the sid[3]
*
* \retval int 1 if the match of all the sids is the specified has the
* specified results; 0 if not
*/
int UTHGenericTest(Packet **pkt, int numpkts, char *sigs[], uint32_t sids[], uint32_t *results, int numsigs) {
int result = 0;
if (pkt == NULL || sigs == NULL || numpkts == 0
|| sids == NULL || results == NULL || numsigs == 0) {
SCLogError(SC_INVALID_ARGUMENT, "Arguments invalid, that the pointer/arrays are not NULL, and the number of signatures and packets is > 0");
goto end;
}
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
if (de_ctx == NULL) {
goto end;
}
if (UTHAppendSigs(de_ctx, sigs, numsigs) == 0)
goto cleanup;
result = UTHMatchPacketsWithResults(de_ctx, pkt, numpkts, sids, results, numsigs);
cleanup:
if (de_ctx != NULL) {
SigGroupCleanup(de_ctx);
SigCleanSignatures(de_ctx);
DetectEngineCtxFree(de_ctx);
}
end:
return result;
}
/**
* \brief UTHCheckPacketMatches: function to check if a packet some sids
*
*
* \param p pointer to the Packet
* \param sigs array of char* pointing to signatures to load
* \param numsigs number of signatures to load from the array
* \param results pointer to an array of numbers to check if sids matches
* that number of times or not.
*
* \retval int 1 if the match of all the sids is the specified has the
* specified results; 0 if not
*/
int UTHCheckPacketMatchResults(Packet *p, uint32_t sids[], uint32_t results[], int numsids) {
if (p == NULL || sids == NULL) {
SCLogError(SC_INVALID_ARGUMENT, "Arguments invalid, check if the packet is NULL, and if the array contain sids is set");
return 0;
}
int i = 0;
int res = 1;
for (; i < numsids; i++) {
uint16_t r = PacketAlertCheck(p, sids[i]);
if (r != results[i]) {
SCLogInfo("Sid %"PRIu32" matched %"PRIu16" times, and not %"PRIu16" as espected", sids[i], r, results[i]);
res = 0;
} else {
SCLogInfo("Sid %"PRIu32" matched %"PRIu16" times, as expected", sids[i], r);
}
}
return res;
}
/**
* \brief UTHAppendSigs: Add sigs to the detection_engine checking for errors
*
* \param de_ctx pointer to the DetectEngineCtx used
* \param sigs array of char* pointing to signatures to load
* \param numsigs number of signatures to load from the array
* (size of the array)
*
* \retval int 0 if we have errors; 1 if all the signatures loaded succesfuly
*/
int UTHAppendSigs(DetectEngineCtx *de_ctx, char *sigs[], int numsigs) {
if (de_ctx == NULL || numsigs <= 0 || sigs == NULL) {
SCLogError(SC_INVALID_ARGUMENT, "Arguments invalid, check if sigs or de_ctx are NULL, and if the array contain sigs");
return 0;
}
//SCLogDebug("Adding %d signatures for the current unittest", numsigs);
Signature *s;
int i = 0;
for ( ; i < numsigs; i++) {
if (sigs[i] == NULL) {
SCLogError(SC_INVALID_ARGUMENT, "Check the signature"
" at position %d", i);
return 0;
}
s = DetectEngineAppendSig(de_ctx, sigs[i]);
if (s == NULL) {
SCLogError(SC_INVALID_ARGUMENT, "Check the signature at"
" position %d (%s)", i, sigs[i]);
return 0;
}
}
//SCLogDebug("Added %d signatures to the de_ctx of the unittest", i);
return 1;
}
/**
* \test UTHMatchPacketsWithResults Match a packet or a array of packets against sigs
* of a de_ctx, checking that each signature match match X times for certain packets
*
* \param de_ctx pointer with the signatures loaded
* \param p pointer to the array of packets
* \param num_packets number of packets in the array
*
* \retval return 1 if all goes well
* \retval return 0 if something fail
*/
int UTHMatchPacketsWithResults(DetectEngineCtx *de_ctx, Packet **p, int num_packets, uint32_t sids[], uint32_t *results, int numsigs) {
int result = 0;
if (de_ctx == NULL || p == NULL) {
SCLogError(SC_INVALID_ARGUMENT, "packet or de_ctx was null");
result = 0;
goto end;
}
DecodeThreadVars dtv;
ThreadVars th_v;
DetectEngineThreadCtx *det_ctx = NULL;
memset(&dtv, 0, sizeof(DecodeThreadVars));
memset(&th_v, 0, sizeof(th_v));
//de_ctx->flags |= DE_QUIET;
SigGroupBuild(de_ctx);
DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
int i = 0;
for (; i < num_packets; i++) {
SigMatchSignatures(&th_v, de_ctx, det_ctx, p[i]);
if (UTHCheckPacketMatchResults(p[i], sids, &results[(i * numsigs)], numsigs) == 0)
goto cleanup;
}
/* so far, so good ;) */
result = 1;
cleanup:
if (det_ctx != NULL)
DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
end:
return result;
}
/**
* \test UTHMatchPackets Match a packet or a array of packets against sigs
* of a de_ctx, but note that the return value doesn't mean that we have a
* match, we have to check it later with PacketAlertCheck()
*
* \param de_ctx pointer with the signatures loaded
* \param p pointer to the array of packets
* \param num_packets number of packets in the array
*
* \retval return 1 if all goes well
* \retval return 0 if something fail
*/
int UTHMatchPackets(DetectEngineCtx *de_ctx, Packet **p, int num_packets) {
int result = 1;
if (de_ctx == NULL || p == NULL) {
SCLogError(SC_INVALID_ARGUMENT, "packet or de_ctx was null");
result = 0;
goto end;
}
DecodeThreadVars dtv;
ThreadVars th_v;
DetectEngineThreadCtx *det_ctx = NULL;
memset(&dtv, 0, sizeof(DecodeThreadVars));
memset(&th_v, 0, sizeof(th_v));
//de_ctx->flags |= DE_QUIET;
SigGroupBuild(de_ctx);
DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
int i = 0;
for (; i < num_packets; i++)
SigMatchSignatures(&th_v, de_ctx, det_ctx, p[i]);
/* Here we don't check if the packet matched or not, because
* the de_ctx can have multiple signatures, and some of them may match
* and others may not. That check will be outside
*/
end:
if (det_ctx != NULL) {
DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
}
return result;
}
/**
* \test Test if a packet match a signature given as string
* Useful for unittests with only one packet and one signature
*
* \param sig pointer to the string signature to test
* \param sid sid number of the signature
*
* \retval return 1 if match
* \retval return 0 if not
*/
int UTHPacketMatchSig(Packet *p, char *sig) {
int result = 1;
DecodeThreadVars dtv;
ThreadVars th_v;
DetectEngineThreadCtx *det_ctx = NULL;
memset(&dtv, 0, sizeof(DecodeThreadVars));
memset(&th_v, 0, sizeof(th_v));
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
if (de_ctx == NULL) {
result=0;
goto end;
}
de_ctx->flags |= DE_QUIET;
de_ctx->sig_list = SigInit(de_ctx, sig);
if (de_ctx->sig_list == NULL) {
result = 0;
goto end;
}
SigGroupBuild(de_ctx);
//PatternMatchPrepare(mpm_ctx, MPM_B2G);
DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
if (PacketAlertCheck(p, de_ctx->sig_list->id) != 1) {
result = 0;
goto end;
}
end:
if (det_ctx != NULL)
DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
if (de_ctx != NULL)
DetectEngineCtxFree(de_ctx);
return result;
}
/*
static int UTHBuildStream(Signature *s, uint8_t *payload, uint16_t payload_len, Proto tcp/udp) {
}
static int UTHInitFlow(Signature *s, uint8_t *payload, uint16_t payload_len, Proto tcp/udp) {
}
static int UTHInitConfigApi(Signature *s, uint8_t *payload, uint16_t payload_len, Proto tcp/udp) {
}
static int UTHInitDeCtx(Signature *s, uint8_t *payload, uint16_t payload_len, Proto tcp/udp) {
}
*/
#ifdef UNITTESTS
/**
* \brief CheckUTHTestPacket wrapper to check packets for unittests
*/
int CheckUTHTestPacket(Packet *p, uint16_t ipproto) {
uint16_t sport = 41424;
uint16_t dport = 80;
uint8_t payload[] = "Payload";
uint8_t len = sizeof(payload);
if (p == NULL)
return 0;
if (p->payload_len != len)
return 0;
if (strncmp((char *)payload, (char *)p->payload, len) != 0)
return 0;
if (p->src.family != AF_INET)
return 0;
if (p->dst.family != AF_INET)
return 0;
if (p->proto != ipproto)
return 0;
switch(ipproto) {
case IPPROTO_UDP:
if (p->udph == NULL)
return 0;
if (p->udph->uh_sport != sport)
return 0;
if (p->udph->uh_dport != dport)
return 0;
break;
case IPPROTO_TCP:
if (p->tcph == NULL)
return 0;
if (p->tcph->th_sport != sport)
return 0;
if (p->tcph->th_dport != dport)
return 0;
break;
}
return 1;
}
/**
* \brief UTHBuildPacketRealTest01 wrapper to check packets for unittests
*/
int UTHBuildPacketRealTest01(void) {
uint8_t payload[] = "Payload";
Packet *p = UTHBuildPacketReal(payload, sizeof(payload), IPPROTO_TCP,
"192.168.1.5", "192.168.1.1", 41424, 80);
return CheckUTHTestPacket(p, IPPROTO_TCP);
}
/**
* \brief UTHBuildPacketRealTest02 wrapper to check packets for unittests
*/
int UTHBuildPacketRealTest02(void) {
uint8_t payload[] = "Payload";
Packet *p = UTHBuildPacketReal(payload, sizeof(payload), IPPROTO_UDP,
"192.168.1.5", "192.168.1.1", 41424, 80);
return CheckUTHTestPacket(p, IPPROTO_UDP);
}
/**
* \brief UTHBuildPacketTest01 wrapper to check packets for unittests
*/
int UTHBuildPacketTest01(void) {
uint8_t payload[] = "Payload";
Packet *p = UTHBuildPacket(payload, sizeof(payload), IPPROTO_TCP);
return CheckUTHTestPacket(p, IPPROTO_TCP);
}
/**
* \brief UTHBuildPacketTest02 wrapper to check packets for unittests
*/
int UTHBuildPacketTest02(void) {
uint8_t payload[] = "Payload";
Packet *p = UTHBuildPacket(payload, sizeof(payload), IPPROTO_UDP);
return CheckUTHTestPacket(p, IPPROTO_UDP);
}
/**
* \brief UTHBuildPacketSrcDstTest01 wrapper to check packets for unittests
*/
int UTHBuildPacketSrcDstTest01(void) {
uint8_t payload[] = "Payload";
Packet *p = UTHBuildPacketSrcDst(payload, sizeof(payload), IPPROTO_TCP,
"192.168.1.5", "192.168.1.1");
return CheckUTHTestPacket(p, IPPROTO_TCP);
}
/**
* \brief UTHBuildPacketSrcDstTest02 wrapper to check packets for unittests
*/
int UTHBuildPacketSrcDstTest02(void) {
uint8_t payload[] = "Payload";
Packet *p = UTHBuildPacketSrcDst(payload, sizeof(payload), IPPROTO_UDP,
"192.168.1.5", "192.168.1.1");
return CheckUTHTestPacket(p, IPPROTO_UDP);
}
/**
* \brief UTHBuildPacketSrcDstPortsTest01 wrapper to check packets for unittests
*/
int UTHBuildPacketSrcDstPortsTest01(void) {
uint8_t payload[] = "Payload";
Packet *p = UTHBuildPacketSrcDstPorts(payload, sizeof(payload), IPPROTO_TCP,
41424, 80);
return CheckUTHTestPacket(p, IPPROTO_TCP);
}
/**
* \brief UTHBuildPacketSrcDstPortsTest02 wrapper to check packets for unittests
*/
int UTHBuildPacketSrcDstPortsTest02(void) {
uint8_t payload[] = "Payload";
Packet *p = UTHBuildPacketSrcDstPorts(payload, sizeof(payload), IPPROTO_UDP,
41424, 80);
return CheckUTHTestPacket(p, IPPROTO_UDP);
}
#endif /* UNITTESTS */
void UTHRegisterTests(void) {
#ifdef UNITTESTS
UtRegisterTest("UTHBuildPacketRealTest01", UTHBuildPacketRealTest01, 1);
UtRegisterTest("UTHBuildPacketRealTest02", UTHBuildPacketRealTest02, 1);
UtRegisterTest("UTHBuildPacketTest01", UTHBuildPacketTest01, 1);
UtRegisterTest("UTHBuildPacketTest02", UTHBuildPacketTest02, 1);
UtRegisterTest("UTHBuildPacketSrcDstTest01", UTHBuildPacketSrcDstTest01, 1);
UtRegisterTest("UTHBuildPacketSrcDstTest02", UTHBuildPacketSrcDstTest02, 1);
UtRegisterTest("UTHBuildPacketSrcDstPortsTest01", UTHBuildPacketSrcDstPortsTest01, 1);
UtRegisterTest("UTHBuildPacketSrcDstPortsTest02", UTHBuildPacketSrcDstPortsTest02, 1);
#endif /* UNITTESTS */
}

@ -0,0 +1,21 @@
#ifndef __UTIL_UNITTEST_HELPER__
#define __UTIL_UNITTEST_HELPER__
Packet *UTHBuildPacketReal(uint8_t *, uint16_t, uint16_t, char *, char *, uint16_t, uint16_t);
Packet *UTHBuildPacket(uint8_t *, uint16_t, uint16_t);
Packet *UTHBuildPacketSrcDst(uint8_t *, uint16_t, uint16_t, char *, char *);
Packet *UTHBuildPacketSrcDstPorts(uint8_t *, uint16_t, uint16_t, uint16_t, uint16_t);
void UTHFreePacket(Packet *);
void UTHFreePackets(Packet **, int);
int UTHAppendSigs(DetectEngineCtx *, char **, int);
int UTHMatchPackets(DetectEngineCtx *, Packet **, int);
int UTHPacketMatchSig(Packet *p, char *);
int UTHCheckPacketMatch(Packet *, uint32_t *, uint32_t *, int);
int UTHMatchPacketsWithResults(DetectEngineCtx *, Packet **, int, uint32_t *, uint32_t *, int);
int UTHGenericTest(Packet **, int, char **, uint32_t *, uint32_t *, int);
void UTHRegisterTests(void);
#endif /* __UTIL_UNITTEST_HELPER__ */
Loading…
Cancel
Save