From 02fb39b9135d7da1a4b9d3ee7d6883d630b49c6a Mon Sep 17 00:00:00 2001 From: Gurvinder Singh Date: Fri, 23 Oct 2009 17:22:29 +0300 Subject: [PATCH] detect-engine-proto unit tests and comments --- src/detect-engine-proto.c | 274 +++++++++++++++++++++++++++++++++++--- src/detect-engine-proto.h | 5 +- 2 files changed, 261 insertions(+), 18 deletions(-) diff --git a/src/detect-engine-proto.c b/src/detect-engine-proto.c index 18f1754280..531daeeed4 100644 --- a/src/detect-engine-proto.c +++ b/src/detect-engine-proto.c @@ -13,13 +13,20 @@ #include "util-cidr.h" #include "util-byte.h" #include "util-unittest.h" +#include "util-debug.h" #include "detect-engine-siggroup.h" -int DetectProtoSetup (DetectEngineCtx *de_ctx, Signature *s, SigMatch *m, char *sidstr); +/*Prototypes*/ +int DetectProtoSetup (DetectEngineCtx *de_ctx, Signature *s, SigMatch *m, + char *sidstr); void DetectProtoTests (void); -void DetectProtoRegister (void) { +/** + * \brief To register the protocol detection function + */ +void DetectProtoRegister (void) +{ sigmatch_table[DETECT_PROTO].name = "__proto__"; sigmatch_table[DETECT_PROTO].Match = NULL; sigmatch_table[DETECT_PROTO].Setup = DetectProtoSetup; @@ -27,9 +34,18 @@ void DetectProtoRegister (void) { sigmatch_table[DETECT_PROTO].RegisterTests = DetectProtoTests; } -DetectProto *DetectProtoInit(void) { +/** + * \brief Function to initialize the protocol detection and + * allocate memory to the DetectProto structure. + * + * \retval DetectProtoc instance pointer if successful otherwise NULL + */ + +DetectProto *DetectProtoInit(void) +{ DetectProto *dp = malloc(sizeof(DetectProto)); if (dp == NULL) { + SCLogDebug("DetectProtoInit: Error in memory allocation"); return NULL; } memset(dp,0,sizeof(DetectProto)); @@ -38,11 +54,12 @@ DetectProto *DetectProtoInit(void) { } /** - * \brief Free a DetectAddressGroup object + * \brief Free a DetectProto object * * \param dp Pointer to the DetectProto instance to be freed */ -void DetectProtoFree(DetectProto *dp) { +void DetectProtoFree(DetectProto *dp) +{ if (dp == NULL) return; @@ -58,28 +75,34 @@ void DetectProtoFree(DetectProto *dp) { * * \retval 0 Always return 0. */ -int DetectProtoParse(DetectProto *dp, char *str) { +int DetectProtoParse(DetectProto *dp, char *str) +{ int proto; if (strcasecmp(str, "tcp") == 0) { proto = IPPROTO_TCP; dp->proto[proto / 8] |= 1 << (proto % 8); + SCLogDebug("DetectProtoParse: TCP protocol detected"); } else if (strcasecmp(str, "udp") == 0) { proto = IPPROTO_UDP; dp->proto[proto / 8] |= 1 << (proto % 8); + SCLogDebug("DetectProtoParse: UDP protocol detected"); } else if (strcasecmp(str, "icmp") == 0) { proto = IPPROTO_ICMP; dp->proto[proto / 8] |= 1 << (proto % 8); + SCLogDebug("DetectProtoParse: ICMP protocol detected"); } else if (strcasecmp(str,"ip") == 0) { /* Proto "ip" is treated as an "any" */ dp->flags |= DETECT_PROTO_ANY; memset(dp->proto, 0xff, sizeof(dp->proto)); + SCLogDebug("DetectProtoParse: IP protocol detected"); } else { uint8_t proto_u8; /* Used to avoid sign extension */ /* Extract out a 0-256 value with validation checks */ if (ByteExtractStringUint8(&proto_u8, 10, 0, str) == -1) { // XXX + SCLogDebug("DetectProtoParse: Error in extracting byte string"); goto error; } proto = (int)proto_u8; @@ -98,8 +121,20 @@ error: return -1; } +/** + * \brief this function is used to add the parsed protocol into the current + * signature currently it is not used for the defined function. + * + * \param de_ctx pointer to the Detection Engine Context + * \param s pointer to the Current Signature + * \param m pointer to the Current SigMatch + * \param str pointer to the user provided protocol string + * + * \retval 0 on Success + */ /* XXX remove */ -int DetectProtoSetup (DetectEngineCtx *de_ctx, Signature *s, SigMatch *m, char *str) +int DetectProtoSetup (DetectEngineCtx *de_ctx, Signature *s, SigMatch *m, + char *str) { return 0; } @@ -107,7 +142,56 @@ int DetectProtoSetup (DetectEngineCtx *de_ctx, Signature *s, SigMatch *m, char * /* TESTS */ #ifdef UNITTESTS -static int ProtoTestParse01 (void) { +#include "detect-engine.h" +#include "detect-parse.h" +#include "detect-engine-mpm.h" +/** + * \brief this function is used to initialize the detection engine context and + * setup the signature with passed values. + */ +static int DetectProtoInitTest(DetectEngineCtx **de_ctx, Signature **sig, + DetectProto *dp, char *str) { + char fullstr[1024]; + int result = 0; + + *de_ctx = NULL; + *sig = NULL; + + if (snprintf(fullstr, 1024, "alert %s any any -> any any (msg:\"DetectProto" + " test\"; sid:1;)", str) >= 1024) + { + goto end; + } + + *de_ctx = DetectEngineCtxInit(); + if (*de_ctx == NULL) { + goto end; + } + + (*de_ctx)->flags |= DE_QUIET; + + (*de_ctx)->sig_list = SigInit(*de_ctx, fullstr); + if ((*de_ctx)->sig_list == NULL) { + goto end; + } + + *sig = (*de_ctx)->sig_list; + + if (DetectProtoParse(dp, str) != 0) + goto end; + + result = 1; + +end: + return result; +} + +/** + * \test ProtoTestParse01 is a test to make sure that we parse the + * protocol correctly, when given valid proto option. + */ +static int ProtoTestParse01 (void) +{ DetectProto dp; memset(&dp,0,sizeof(DetectProto)); @@ -116,10 +200,15 @@ static int ProtoTestParse01 (void) { return 1; } + SCLogDebug("ProtoTestParse01: Error in parsing the \"6\" string"); return 0; } - -static int ProtoTestParse02 (void) { +/** + * \test ProtoTestParse02 is a test to make sure that we parse the + * protocol correctly, when given "tcp" as proto option. + */ +static int ProtoTestParse02 (void) +{ DetectProto dp; memset(&dp,0,sizeof(DetectProto)); @@ -128,10 +217,15 @@ static int ProtoTestParse02 (void) { return 1; } + SCLogDebug("ProtoTestParse02: Error in parsing the \"tcp\" string"); return 0; } - -static int ProtoTestParse03 (void) { +/** + * \test ProtoTestParse03 is a test to make sure that we parse the + * protocol correctly, when given "ip" as proto option. + */ +static int ProtoTestParse03 (void) +{ DetectProto dp; memset(&dp,0,sizeof(DetectProto)); @@ -140,10 +234,15 @@ static int ProtoTestParse03 (void) { return 1; } + SCLogDebug("ProtoTestParse03: Error in parsing the \"ip\" string"); return 0; } - -static int ProtoTestParse04 (void) { +/** + * \test ProtoTestParse04 is a test to make sure that we do not parse the + * protocol, when given an invalid proto option. + */ +static int ProtoTestParse04 (void) +{ DetectProto dp; memset(&dp,0,sizeof(DetectProto)); @@ -153,17 +252,160 @@ static int ProtoTestParse04 (void) { return 1; } + SCLogDebug("ProtoTestParse04: it should not parsing the \"4242\" string"); return 0; } -#endif /* UNITTESTS */ +/** + * \test ProtoTestParse05 is a test to make sure that we do not parse the + * protocol, when given an invalid proto option. + */ +static int ProtoTestParse05 (void) +{ + DetectProto dp; + memset(&dp,0,sizeof(DetectProto)); + + /* Check for a bad string */ + int r = DetectProtoParse(&dp, "tcp/udp"); + if (r == -1) { + return 1; + } + + SCLogDebug("ProtoTestParse05: it should not parsing the \"4242\" string"); + return 0; +} + +/** + * \test DetectIPProtoTestSetup01 is a test for a protocol setting up in + * signature. + */ +static int DetectProtoTestSetup01(void) +{ + DetectProto dp; + Signature *sig = NULL; + DetectEngineCtx *de_ctx = NULL; + int result = 0; + int i; + + memset(&dp, 0, sizeof(dp)); + + result = DetectProtoInitTest(&de_ctx, &sig, &dp, "tcp"); + if (result == 0) { + goto end; + } + + result = 0; + + /* The signature proto should be TCP */ + if (!(sig->proto.proto[(IPPROTO_TCP/8)] & (1<<(IPPROTO_TCP%8)))) { + printf("failed in sig matching\n"); + goto cleanup; + } + for (i = 2; i < 256/8; i++) { + if (sig->proto.proto[i] != 0) { + printf("failed in sig clear\n"); + goto cleanup; + } + } + result = 1; -void DetectProtoTests(void) { +cleanup: + SigGroupCleanup(de_ctx); + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); +end: + return result; +} + +/** + * \test DetectProtoTestSig01 is a test for checking the working of protocol + * detection by setting up the signature and later testing its working + * by matching the received packet against the sig. + */ + +static int DetectProtoTestSig01(void) { + 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.proto = IPPROTO_TCP; + p.flowflags |= FLOW_PKT_TOSERVER; + + DetectEngineCtx *de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) { + goto end; + } + + de_ctx->flags |= DE_QUIET; + + s = de_ctx->sig_list = SigInit(de_ctx,"alert udp any any -> any any " + "(msg:\"Not tcp\"; sid:1;)"); + + if (s == NULL) + goto end; + + s = s->next = SigInit(de_ctx,"alert ip any any -> any any " + "(msg:\"IP\"; sid:2;)"); + + if (s == NULL) + goto end; + + s = s->next = SigInit(de_ctx,"alert tcp any any -> any any " + "(msg:\"TCP\"; sid:3;)"); + + if (s == NULL) + 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, 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; + } + + result = 1; + +cleanup: + SigGroupCleanup(de_ctx); + SigCleanSignatures(de_ctx); + + DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx); + PatternMatchDestroy(mpm_ctx); + DetectEngineCtxFree(de_ctx); + +end: + return result; +} +#endif /* UNITTESTS */ + +/** + * \brief this function registers unit tests for DetectProto + */ +void DetectProtoTests(void) +{ #ifdef UNITTESTS UtRegisterTest("ProtoTestParse01", ProtoTestParse01, 1); UtRegisterTest("ProtoTestParse02", ProtoTestParse02, 1); UtRegisterTest("ProtoTestParse03", ProtoTestParse03, 1); UtRegisterTest("ProtoTestParse04", ProtoTestParse04, 1); + UtRegisterTest("ProtoTestParse05", ProtoTestParse05, 1); + UtRegisterTest("DetectProtoTestSetup01", DetectProtoTestSetup01, 1); + UtRegisterTest("DetectProtoTestSig01", DetectProtoTestSig01, 1); #endif /* UNITTESTS */ } diff --git a/src/detect-engine-proto.h b/src/detect-engine-proto.h index a4df940a19..1a15d227da 100644 --- a/src/detect-engine-proto.h +++ b/src/detect-engine-proto.h @@ -1,10 +1,11 @@ #ifndef __DETECT_PROTO_H__ #define __DETECT_PROTO_H__ -#define DETECT_PROTO_ANY 0x1 +#define DETECT_PROTO_ANY 0x1 /**< Flag to indicate that given protocol + is considered as IP */ typedef struct DetectProto_ { - uint8_t proto[256/8]; /* bitarray for 256 bits */ + uint8_t proto[256/8]; /* bit array for 256 bits */ uint8_t flags; } DetectProto;