From c80160b96d429c9d3816dcf7476bc3f33129fdd5 Mon Sep 17 00:00:00 2001 From: Pablo Rincon Date: Mon, 21 Dec 2009 11:48:19 +0100 Subject: [PATCH] More examples of unittest helper functions usage reference --- src/detect-engine-address.c | 25 +++--- src/detect-engine-siggroup.c | 1 + src/detect-parse.c | 63 +++++---------- src/detect.c | 93 +++------------------- src/flow.c | 5 +- src/util-unittest-helper.c | 145 +++++++++++++++++++++++++++++++---- src/util-unittest-helper.h | 6 ++ 7 files changed, 186 insertions(+), 152 deletions(-) diff --git a/src/detect-engine-address.c b/src/detect-engine-address.c index c1818fe9a0..65b0c4bcc0 100644 --- a/src/detect-engine-address.c +++ b/src/detect-engine-address.c @@ -256,9 +256,10 @@ void DetectAddressCleanupList(DetectAddress *head) return; for (cur = head; cur != NULL; ) { - next = cur->next; - DetectAddressFree(cur); - cur = next; + next = cur->next; + cur->next = NULL; + DetectAddressFree(cur); + cur = next; } return; @@ -1274,12 +1275,18 @@ DetectAddressHead *DetectAddressHeadInit(void) void DetectAddressHeadCleanup(DetectAddressHead *gh) { if (gh != NULL) { - DetectAddressCleanupList(gh->any_head); - gh->any_head = NULL; - DetectAddressCleanupList(gh->ipv4_head); - gh->ipv4_head = NULL; - DetectAddressCleanupList(gh->ipv6_head); - gh->ipv6_head = NULL; + if (gh->any_head != NULL) { + DetectAddressCleanupList(gh->any_head); + gh->any_head = NULL; + } + if (gh->ipv4_head != NULL) { + DetectAddressCleanupList(gh->ipv4_head); + gh->ipv4_head = NULL; + } + if (gh->ipv6_head != NULL) { + DetectAddressCleanupList(gh->ipv6_head); + gh->ipv6_head = NULL; + } } return; diff --git a/src/detect-engine-siggroup.c b/src/detect-engine-siggroup.c index 099e090570..b261953198 100644 --- a/src/detect-engine-siggroup.c +++ b/src/detect-engine-siggroup.c @@ -147,6 +147,7 @@ void SigGroupHeadFree(SigGroupHead *sgh) if (sgh->init != NULL) { SigGroupHeadInitDataFree(sgh->init); + sgh->init = NULL; } free(sgh); diff --git a/src/detect-parse.c b/src/detect-parse.c index 85a5e2bd22..485fc93f84 100644 --- a/src/detect-parse.c +++ b/src/detect-parse.c @@ -23,6 +23,7 @@ #include "util-classification-config.h" #include "util-unittest.h" +#include "util-unittest-helper.h" #include "util-debug.h" #include "string.h" #include "detect-parse.h" @@ -1222,24 +1223,14 @@ int SigTestBidirec03 (void) { de_ctx->flags |= DE_QUIET; - sig = DetectEngineAppendSig(de_ctx, "alert tcp any any -> 192.168.1.1 any (msg:\"SigTestBidirec03 sid 1\"; sid:1;)"); - if (sig == NULL) - goto end; - sig = DetectEngineAppendSig(de_ctx, "alert tcp any any <> 192.168.1.1 any (msg:\"SigTestBidirec03 sid 2 bidirectional\"; sid:2;)"); - if (sig == NULL) - goto end; - if ( !(sig->flags & SIG_FLAG_BIDIREC)) - goto end; - if (sig->next == NULL) - goto end; - if (sig->next->next == NULL) - goto end; - if (sig->next->next->next != NULL) - goto end; - if (de_ctx->signum != 3) - goto end; + char *sigs[3]; + sigs[0] = "alert tcp any any -> 192.168.1.1 any (msg:\"SigTestBidirec03 sid 1\"; sid:1;)"; + sigs[1] = "alert tcp any any <> 192.168.1.1 any (msg:\"SigTestBidirec03 sid 2 bidirectional\"; sid:2;)"; + sigs[2] = "alert tcp any any -> 192.168.1.1 any (msg:\"SigTestBidirec03 sid 3\"; sid:3;)"; + UTHAppendSigs(de_ctx, sigs, 3); - sig = DetectEngineAppendSig(de_ctx, "alert tcp any any -> 192.168.1.1 any (msg:\"SigTestBidirec03 sid 3\"; sid:3;)"); + /* Checking that bidirectional rules are set correctly */ + sig = de_ctx->sig_list; if (sig == NULL) goto end; if (sig->next == NULL) @@ -1310,38 +1301,20 @@ int SigTestBidirec03 (void) { 0x6b,0x65,0x65,0x70,0x2d,0x61,0x6c,0x69, 0x76,0x65,0x0d,0x0a,0x0d,0x0a }; /* end rawpkt1_ether */ - Packet p; - DecodeThreadVars dtv; - ThreadVars th_v; - DetectEngineThreadCtx *det_ctx; - - memset(&th_v, 0, sizeof(th_v)); - memset(&dtv, 0, sizeof(DecodeThreadVars)); - memset(&p, 0, sizeof(p)); - FlowInitConfig(FLOW_QUIET); - DecodeEthernet(&th_v, &dtv, &p, rawpkt1_ether, sizeof(rawpkt1_ether), NULL); - DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx); - - SigGroupBuild(de_ctx); - //PatternMatchPrepare(mpm_ctx, MPM_B2G); - SigMatchSignatures(&th_v, de_ctx, det_ctx, &p); - - /* all the sids should match with a packet going to 192.168.1.1 port 80 */ - if (PacketAlertCheck(&p, 1) == 1 && PacketAlertCheck(&p, 2) == 1 && - PacketAlertCheck(&p, 3) == 1) { - result = 1; - } + Packet *p = UTHBuildPacketFromEth(rawpkt1_ether, sizeof(rawpkt1_ether)); FlowShutdown(); - //PatternMatchDestroy(mpm_ctx); - DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx); + if (p == NULL) { + SCLogDebug("Error building packet"); + goto end; + } + UTHMatchPackets(de_ctx, &p, 1); + + uint32_t sids[3] = {1, 2, 3}; + uint32_t results[3] = {1, 1, 1}; + result = UTHCheckPacketMatchResults(p, sids, results, 1); end: - if (de_ctx != NULL) { - SigCleanSignatures(de_ctx); - SigGroupCleanup(de_ctx); - DetectEngineCtxFree(de_ctx); - } return result; } diff --git a/src/detect.c b/src/detect.c index 7af86fb86e..1c304bf41a 100644 --- a/src/detect.c +++ b/src/detect.c @@ -92,6 +92,7 @@ #include "util-classification-config.h" #include "util-print.h" #include "util-unittest.h" +#include "util-unittest-helper.h" #include "util-debug.h" #include "util-hashlist.h" @@ -3128,38 +3129,11 @@ static int SigTest01Real (int mpm_type) { "Host: two.example.org\r\n" "\r\n\r\n"; uint16_t buflen = strlen((char *)buf); - Packet p; - ThreadVars th_v; - DetectEngineThreadCtx *det_ctx; + Packet *p = UTHBuildPacket( buf, buflen, IPPROTO_TCP); 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->mpm_matcher = mpm_type; - - de_ctx->flags |= DE_QUIET; - - de_ctx->sig_list = SigInit(de_ctx,"alert tcp any any -> any any (msg:\"HTTP URI cap\"; content:\"GET \"; depth:4; pcre:\"/GET (?P.*) HTTP\\/\\d\\.\\d\\r\\n/G\"; recursive; sid:1;)"); - 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, 1) == 0) { + char sig[] = "alert tcp any any -> any any (msg:\"HTTP URI cap\"; content:\"GET \"; depth:4; pcre:\"/GET (?P.*) HTTP\\/\\d\\.\\d\\r\\n/G\"; recursive; sid:1;)"; + if (UTHPacketMatchSigMpm(p, sig, mpm_type) == 0) { result = 0; goto end; } @@ -3167,18 +3141,14 @@ static int SigTest01Real (int mpm_type) { //printf("URI0 \"%s\", len %" PRIu32 "\n", p.http_uri.raw[0], p.http_uri.raw_size[0]); //printf("URI1 \"%s\", len %" PRIu32 "\n", p.http_uri.raw[1], p.http_uri.raw_size[1]); - if (p.http_uri.raw_size[0] == 5 && - memcmp(p.http_uri.raw[0], "/one/", 5) == 0 && - p.http_uri.raw_size[1] == 5 && - memcmp(p.http_uri.raw[1], "/two/", 5) == 0) + if (p->http_uri.raw_size[0] == 5 && + memcmp(p->http_uri.raw[0], "/one/", 5) == 0 && + p->http_uri.raw_size[1] == 5 && + memcmp(p->http_uri.raw[1], "/two/", 5) == 0) { result = 1; } - SigGroupCleanup(de_ctx); - - DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx); - DetectEngineCtxFree(de_ctx); end: return result; } @@ -3202,50 +3172,11 @@ static int SigTest02Real (int mpm_type) { "Host: two.example.org\r\n" "\r\n\r\n"; uint16_t buflen = strlen((char *)buf); - Packet p; - 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->mpm_matcher = mpm_type; - de_ctx->flags |= DE_QUIET; - - de_ctx->sig_list = SigInit(de_ctx,"alert tcp any any -> any any (msg:\"HTTP TEST\"; content:\"Host: one.example.org\"; offset:20; depth:41; sid:1;)"); - 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, 1)) - result = 1; - - SigGroupCleanup(de_ctx); - SigCleanSignatures(de_ctx); - - DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx); - //PatternMatchDestroy(mpm_ctx); - DetectEngineCtxFree(de_ctx); -end: - return result; + Packet *p = UTHBuildPacket( buf, buflen, IPPROTO_TCP); + char sig[] = "alert tcp any any -> any any (msg:\"HTTP TEST\"; content:\"Host: one.example.org\"; offset:20; depth:41; sid:1;)"; + return UTHPacketMatchSigMpm(p, sig, mpm_type); } + static int SigTest02B2g (void) { return SigTest02Real(MPM_B2G); } diff --git a/src/flow.c b/src/flow.c index 427bea3f75..907a65e9bc 100644 --- a/src/flow.c +++ b/src/flow.c @@ -563,7 +563,10 @@ void FlowShutdown(void) { } } - free(flow_hash); + if (flow_hash != NULL) { + free(flow_hash); + flow_hash = NULL; + } flow_memuse -= flow_config.hash_size * sizeof(FlowBucket); SCMutexDestroy(&flow_memuse_mutex); diff --git a/src/util-unittest-helper.c b/src/util-unittest-helper.c index 0237e6a861..5c6832f072 100644 --- a/src/util-unittest-helper.c +++ b/src/util-unittest-helper.c @@ -57,7 +57,7 @@ Packet *UTHBuildPacketReal(uint8_t *payload, uint16_t payload_len, p->dst.addr_data32[0] = in.s_addr; p->dp = dport; - switch(ipproto) { + switch (ipproto) { case IPPROTO_UDP: p->ip4h = malloc(sizeof(IPV4Hdr)); if (p->ip4h == NULL) { @@ -115,6 +115,75 @@ Packet *UTHBuildPacket(uint8_t *payload, uint16_t payload_len, 41424, 80); } +/** + * \brief UTHBuildPacketArrayFromEth is a wrapper that build a packets from an array of + * packets in ethernet rawbytes. Hint: It also share the flows. + * + * \param raw_eth pointer to the array of ethernet packets in rawbytes + * \param pktsize pointer to the array of sizes corresponding to each buffer pointed + * from pktsize. + * \param numpkts number of packets in the array + * + * \retval Packet pointer to the array of built in packets; NULL if something fail + */ +Packet **UTHBuildPacketArrayFromEth(uint8_t *raw_eth[], int *pktsize, int numpkts) { + DecodeThreadVars dtv; + ThreadVars th_v; + if (raw_eth == NULL || pktsize == NULL || numpkts <= 0) { + SCLogError(SC_INVALID_ARGUMENT, "The arrays cant be null, and the number" + " of packets should be grater thatn zero"); + return NULL; + } + Packet **p = NULL; + p = malloc(sizeof(Packet *) * numpkts); + if (p == NULL) { + SCLogError(SC_ERR_MEM_ALLOC, "Error allocating memory for the packet array"); + return NULL; + } + + memset(&dtv, 0, sizeof(DecodeThreadVars)); + memset(&th_v, 0, sizeof(th_v)); + + int i = 0; + for (; i < numpkts; i++) { + p[i] = malloc(sizeof(Packet)); + if (p[i] == NULL) { + SCLogError(SC_ERR_MEM_ALLOC, "Error allocating memory for a packet of the array"); + return NULL; + } + memset(p[i], 0, sizeof(Packet)); + DecodeEthernet(&th_v, &dtv, p[i], raw_eth[i], pktsize[i], NULL); + } + return p; +} + +/** + * \brief UTHBuildPacketFromEth is a wrapper that build a packet for the rawbytes + * + * \param raw_eth pointer to the rawbytes containing an ethernet packet + * (and any other headers inside) + * \param pktsize pointer to the length of the payload + * + * \retval Packet pointer to the built in packet; NULL if something fail + */ +Packet *UTHBuildPacketFromEth(uint8_t *raw_eth, uint16_t pktsize) { + DecodeThreadVars dtv; + ThreadVars th_v; + Packet *p = malloc(sizeof(Packet)); + if (p == NULL) { + SCLogError(SC_ERR_MEM_ALLOC, "Error allocating memory for the packet"); + return 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, pktsize, NULL); + FlowShutdown(); + return p; +} + /** * \brief UTHBuildPacketSrcDst is a wrapper that build packets specifying IPs * and defaulting ports @@ -175,7 +244,7 @@ void UTHFreePacket(Packet *p) { if (p == NULL) return; - switch(p->proto) { + switch (p->proto) { case IPPROTO_UDP: if (p->udph != NULL) free(p->udph); @@ -249,7 +318,7 @@ end: } /** - * \brief UTHCheckPacketMatches: function to check if a packet some sids + * \brief UTHCheckPacketMatches: function to check if a packet match some sids * * * \param p pointer to the Packet @@ -406,6 +475,7 @@ int UTHMatchPackets(DetectEngineCtx *de_ctx, Packet **p, int num_packets) { * and others may not. That check will be outside */ end: + SigGroupCleanup(de_ctx); if (det_ctx != NULL) { DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx); } @@ -414,8 +484,8 @@ end: } /** - * \test Test if a packet match a signature given as string - * Useful for unittests with only one packet and one signature + * \test Test if a packet match a signature given as string and a mpm_type + * Hint: 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 @@ -423,7 +493,7 @@ end: * \retval return 1 if match * \retval return 0 if not */ -int UTHPacketMatchSig(Packet *p, char *sig) { +int UTHPacketMatchSigMpm(Packet *p, char *sig, uint16_t mpm_type) { int result = 1; DecodeThreadVars dtv; @@ -441,6 +511,7 @@ int UTHPacketMatchSig(Packet *p, char *sig) { } de_ctx->flags |= DE_QUIET; + de_ctx->mpm_matcher = mpm_type; de_ctx->sig_list = SigInit(de_ctx, sig); if (de_ctx->sig_list == NULL) { @@ -449,7 +520,7 @@ int UTHPacketMatchSig(Packet *p, char *sig) { } SigGroupBuild(de_ctx); - //PatternMatchPrepare(mpm_ctx, MPM_B2G); + //PatternMatchPrepare(mpm_ctx, mpm_type); DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx); SigMatchSignatures(&th_v, de_ctx, det_ctx, p); @@ -467,16 +538,58 @@ end: 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) { +/** + * \test Test if a packet match a signature given as string + * Hint: 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); + 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; } -*/ #ifdef UNITTESTS diff --git a/src/util-unittest-helper.h b/src/util-unittest-helper.h index 45b4726d07..c6f580e338 100644 --- a/src/util-unittest-helper.h +++ b/src/util-unittest-helper.h @@ -5,6 +5,11 @@ Packet *UTHBuildPacketReal(uint8_t *, uint16_t, uint16_t, char *, char *, uint16 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); + +int UTHPacketMatchSigMpm(Packet *, char *, uint16_t); +Packet **UTHBuildPacketArrayFromEth(uint8_t **, int *, int); +Packet *UTHBuildPacketFromEth(uint8_t *, uint16_t); + void UTHFreePacket(Packet *); void UTHFreePackets(Packet **, int); @@ -13,6 +18,7 @@ int UTHMatchPackets(DetectEngineCtx *, Packet **, int); int UTHPacketMatchSig(Packet *p, char *); int UTHCheckPacketMatch(Packet *, uint32_t *, uint32_t *, int); +int UTHCheckPacketMatchResults(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);