From bc99328ec8f2ee0057d6c7ac17d41e1539f88dad Mon Sep 17 00:00:00 2001 From: Anoop Saldanha Date: Tue, 27 Jul 2010 16:43:46 +0530 Subject: [PATCH] define a new conf paramter detect-engine:inspection-recursion-limit; Defines a recursion limit for content inspection code --- src/conf-yaml-loader.h | 2 +- src/detect-engine-dcepayload.c | 9 ++ src/detect-engine-payload.c | 8 ++ src/detect-engine-uri.c | 8 ++ src/detect-engine.c | 228 +++++++++++++++++++++++++++++++++ src/detect-engine.h | 1 + src/detect.h | 6 + src/suricata.c | 2 +- 8 files changed, 262 insertions(+), 2 deletions(-) diff --git a/src/conf-yaml-loader.h b/src/conf-yaml-loader.h index 82b5b683ed..22dfb87773 100644 --- a/src/conf-yaml-loader.h +++ b/src/conf-yaml-loader.h @@ -25,7 +25,7 @@ #define __CONF_YAML_LOADER_H__ int ConfYamlLoadFile(const char *); -void ConfYamlLoadString(const char *, size_t); +int ConfYamlLoadString(const char *, size_t); void ConfYamlRegisterTests(void); #endif /* !__CONF_YAML_LOADER_H__ */ diff --git a/src/detect-engine-dcepayload.c b/src/detect-engine-dcepayload.c index 4d2392c888..4fefcf5996 100644 --- a/src/detect-engine-dcepayload.c +++ b/src/detect-engine-dcepayload.c @@ -83,6 +83,13 @@ static int DoInspectDcePayload(DetectEngineCtx *de_ctx, { SCEnter(); + det_ctx->inspection_recursion_counter++; + + if (det_ctx->inspection_recursion_counter == de_ctx->inspection_recursion_limit) { + det_ctx->discontinue_matching = 1; + SCReturnInt(0); + } + if (sm == NULL || stub_len == 0) { SCReturnInt(0); } @@ -425,6 +432,7 @@ int DetectEngineInspectDcePayload(DetectEngineCtx *de_ctx, det_ctx->payload_offset = 0; det_ctx->discontinue_matching = 0; + det_ctx->inspection_recursion_counter = 0; r = DoInspectDcePayload(de_ctx, det_ctx, s, s->dmatch, f, dce_stub_data, dce_stub_data_len, dcerpc_state); @@ -441,6 +449,7 @@ int DetectEngineInspectDcePayload(DetectEngineCtx *de_ctx, det_ctx->payload_offset = 0; det_ctx->discontinue_matching = 0; + det_ctx->inspection_recursion_counter = 0; r = DoInspectDcePayload(de_ctx, det_ctx, s, s->dmatch, f, dce_stub_data, dce_stub_data_len, dcerpc_state); diff --git a/src/detect-engine-payload.c b/src/detect-engine-payload.c index 5331aabd20..9b60053914 100644 --- a/src/detect-engine-payload.c +++ b/src/detect-engine-payload.c @@ -74,6 +74,13 @@ static int DoInspectPacketPayload(DetectEngineCtx *de_ctx, { SCEnter(); + det_ctx->inspection_recursion_counter++; + + if (det_ctx->inspection_recursion_counter == de_ctx->inspection_recursion_limit) { + det_ctx->discontinue_matching = 1; + SCReturnInt(0); + } + if (sm == NULL || payload_len == 0) { SCReturnInt(0); } @@ -368,6 +375,7 @@ int DetectEngineInspectPacketPayload(DetectEngineCtx *de_ctx, det_ctx->payload_offset = 0; det_ctx->discontinue_matching = 0; + det_ctx->inspection_recursion_counter = 0; r = DoInspectPacketPayload(de_ctx, det_ctx, s, s->pmatch, p, f, p->payload, p->payload_len); if (r == 1) { diff --git a/src/detect-engine-uri.c b/src/detect-engine-uri.c index 5a2754a50b..bfc2433b40 100644 --- a/src/detect-engine-uri.c +++ b/src/detect-engine-uri.c @@ -81,6 +81,13 @@ static int DoInspectPacketUri(DetectEngineCtx *de_ctx, { SCEnter(); + det_ctx->inspection_recursion_counter++; + + if (det_ctx->inspection_recursion_counter == de_ctx->inspection_recursion_limit) { + det_ctx->discontinue_matching = 1; + SCReturnInt(0); + } + if (sm == NULL) { SCReturnInt(0); } @@ -421,6 +428,7 @@ int DetectEngineInspectPacketUris(DetectEngineCtx *de_ctx, det_ctx->discontinue_matching = 0; det_ctx->payload_offset = 0; + det_ctx->inspection_recursion_counter = 0; /* Inspect all the uricontents fetched on each * transaction at the app layer */ diff --git a/src/detect-engine.c b/src/detect-engine.c index 8349e4fd39..29883eac57 100644 --- a/src/detect-engine.c +++ b/src/detect-engine.c @@ -26,6 +26,7 @@ #include "detect.h" #include "flow.h" #include "conf.h" +#include "conf-yaml-loader.h" #include "detect-parse.h" #include "detect-engine-sigorder.h" @@ -48,14 +49,23 @@ #include "util-hash.h" #include "util-byte.h" #include "util-debug.h" +#include "util-unittest.h" #include "util-var-name.h" #include "tm-modules.h" +#define DETECT_ENGINE_DEFAULT_INSPECTION_RECURSION_LIMIT 10000 + static uint8_t DetectEngineCtxLoadConf(DetectEngineCtx *); + DetectEngineCtx *DetectEngineCtxInit(void) { DetectEngineCtx *de_ctx; + ConfNode *seq_node = NULL; + ConfNode *insp_recursion_limit_node = NULL; + ConfNode *de_engine_node = NULL; + char *insp_recursion_limit = NULL; + de_ctx = SCMalloc(sizeof(DetectEngineCtx)); if (de_ctx == NULL) goto error; @@ -66,6 +76,39 @@ DetectEngineCtx *DetectEngineCtxInit(void) { SCLogDebug("ConfGetBool could not load the value."); } + de_engine_node = ConfGetNode("detect-engine"); + if (de_engine_node != NULL) { + TAILQ_FOREACH(seq_node, &de_engine_node->head, next) { + if (strcmp(seq_node->val, "inspection-recursion-limit") != 0) + continue; + + insp_recursion_limit_node = ConfNodeLookupChild(seq_node, seq_node->val); + if (insp_recursion_limit_node == NULL) { + SCLogError(SC_ERR_INVALID_YAML_CONF_ENTRY, "Error retrieving conf " + "entry for detect-engine:inspection-recursion-limit"); + break; + } + insp_recursion_limit = insp_recursion_limit_node->val; + SCLogDebug("Found detect-engine:inspection-recursion-limit - %s:%s", + insp_recursion_limit_node->name, insp_recursion_limit_node->val); + + break; + } + } + + if (insp_recursion_limit != NULL) { + de_ctx->inspection_recursion_limit = atoi(insp_recursion_limit); + } else { + de_ctx->inspection_recursion_limit = + DETECT_ENGINE_DEFAULT_INSPECTION_RECURSION_LIMIT; + } + + if (de_ctx->inspection_recursion_limit == 0) + de_ctx->inspection_recursion_limit = -1; + + SCLogDebug("de_ctx->inspection_recursion_limit: %d", + de_ctx->inspection_recursion_limit); + de_ctx->mpm_matcher = PatternMatchDefaultMatcher(); DetectEngineCtxLoadConf(de_ctx); @@ -441,3 +484,188 @@ void DetectEngineThreadCtxInfo(ThreadVars *t, DetectEngineThreadCtx *det_ctx) { PatternMatchThreadPrint(&det_ctx->mtcu, det_ctx->de_ctx->mpm_matcher); } +/*************************************Unittest*********************************/ + +#ifdef UNITTESTS + +static int DetectEngineInitYamlConf(char *conf) +{ + ConfCreateContextBackup(); + ConfInit(); + return ConfYamlLoadString(conf, strlen(conf)); +} + +static void DetectEngineDeInitYamlConf(void) +{ + ConfDeInit(); + ConfRestoreContextBackup(); + + return; +} + +static int DetectEngineTest01(void) +{ + char *conf = + "%YAML 1.1\n" + "---\n" + "detect-engine:\n" + " - profile: medium\n" + " - custom-values:\n" + " toclient_src_groups: 2\n" + " toclient_dst_groups: 2\n" + " toclient_sp_groups: 2\n" + " toclient_dp_groups: 3\n" + " toserver_src_groups: 2\n" + " toserver_dst_groups: 4\n" + " toserver_sp_groups: 2\n" + " toserver_dp_groups: 25\n" + " - inspection-recursion-limit: 0\n"; + + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if (DetectEngineInitYamlConf(conf) == -1) + return 0; + de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) + goto end; + + result = (de_ctx->inspection_recursion_limit == -1); + + end: + if (de_ctx != NULL) + DetectEngineCtxFree(de_ctx); + + DetectEngineDeInitYamlConf(); + + return result; +} + +static int DetectEngineTest02(void) +{ + char *conf = + "%YAML 1.1\n" + "---\n" + "detect-engine:\n" + " - profile: medium\n" + " - custom-values:\n" + " toclient_src_groups: 2\n" + " toclient_dst_groups: 2\n" + " toclient_sp_groups: 2\n" + " toclient_dp_groups: 3\n" + " toserver_src_groups: 2\n" + " toserver_dst_groups: 4\n" + " toserver_sp_groups: 2\n" + " toserver_dp_groups: 25\n" + " - inspection-recursion-limit:\n"; + + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if (DetectEngineInitYamlConf(conf) == -1) + return 0; + de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) + goto end; + + result = (de_ctx->inspection_recursion_limit == -1); + + end: + if (de_ctx != NULL) + DetectEngineCtxFree(de_ctx); + + DetectEngineDeInitYamlConf(); + + return result; +} + +static int DetectEngineTest03(void) +{ + char *conf = + "%YAML 1.1\n" + "---\n" + "detect-engine:\n" + " - profile: medium\n" + " - custom-values:\n" + " toclient_src_groups: 2\n" + " toclient_dst_groups: 2\n" + " toclient_sp_groups: 2\n" + " toclient_dp_groups: 3\n" + " toserver_src_groups: 2\n" + " toserver_dst_groups: 4\n" + " toserver_sp_groups: 2\n" + " toserver_dp_groups: 25\n"; + + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if (DetectEngineInitYamlConf(conf) == -1) + return 0; + de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) + goto end; + + result = (de_ctx->inspection_recursion_limit == + DETECT_ENGINE_DEFAULT_INSPECTION_RECURSION_LIMIT); + + end: + if (de_ctx != NULL) + DetectEngineCtxFree(de_ctx); + + DetectEngineDeInitYamlConf(); + + return result; +} + +static int DetectEngineTest04(void) +{ + char *conf = + "%YAML 1.1\n" + "---\n" + "detect-engine:\n" + " - profile: medium\n" + " - custom-values:\n" + " toclient_src_groups: 2\n" + " toclient_dst_groups: 2\n" + " toclient_sp_groups: 2\n" + " toclient_dp_groups: 3\n" + " toserver_src_groups: 2\n" + " toserver_dst_groups: 4\n" + " toserver_sp_groups: 2\n" + " toserver_dp_groups: 25\n" + " - inspection-recursion-limit: 10\n"; + + DetectEngineCtx *de_ctx = NULL; + int result = 0; + + if (DetectEngineInitYamlConf(conf) == -1) + return 0; + de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) + goto end; + + result = (de_ctx->inspection_recursion_limit == 10); + + end: + if (de_ctx != NULL) + DetectEngineCtxFree(de_ctx); + + DetectEngineDeInitYamlConf(); + + return result; +} + +#endif + +void DetectEngineRegisterTests() +{ + +#ifdef UNITTESTS + UtRegisterTest("DetectEngineTest01", DetectEngineTest01, 1); + UtRegisterTest("DetectEngineTest02", DetectEngineTest02, 1); + UtRegisterTest("DetectEngineTest03", DetectEngineTest03, 1); + UtRegisterTest("DetectEngineTest04", DetectEngineTest04, 1); +#endif + + return; +} diff --git a/src/detect-engine.h b/src/detect-engine.h index 44ebdf79f1..e59bfad187 100644 --- a/src/detect-engine.h +++ b/src/detect-engine.h @@ -37,6 +37,7 @@ TmEcode DetectEngineThreadCtxDeinit(ThreadVars *, void *); /* faster as a macro than a inline function on my box -- VJ */ #define DetectEngineGetMaxSigId(de_ctx) ((de_ctx)->signum) void DetectEngineResetMaxSigId(DetectEngineCtx *); +void DetectEngineRegisterTests(void); #endif /* __DETECT_ENGINE_H__ */ diff --git a/src/detect.h b/src/detect.h index caccc467c0..02b2d0071b 100644 --- a/src/detect.h +++ b/src/detect.h @@ -577,6 +577,9 @@ typedef struct DetectEngineCtx_ { * id sharing and id tracking. */ MpmPatternIdStore *mpm_pattern_id_store; + /* maximum recursion depth for content inspection */ + int inspection_recursion_limit; + /* array containing all sgh's in use so we can loop * through it in Stage4. */ struct SigGroupHead_ **sgh_array; @@ -635,6 +638,9 @@ typedef struct DetectionEngineThreadCtx_ { /* used to discontinue any more matching */ int discontinue_matching; + /* holds the current recursion depth on content inspection */ + int inspection_recursion_counter; + /* dce stub data */ uint8_t *dce_stub_data; /* dce stub data len */ diff --git a/src/suricata.c b/src/suricata.c index 43a393da38..86616190af 100644 --- a/src/suricata.c +++ b/src/suricata.c @@ -966,7 +966,7 @@ int main(int argc, char **argv) DeStateRegisterTests(); DetectRingBufferRegisterTests(); MemcmpRegisterTests(); - + DetectEngineRegisterTests(); if (list_unittests) { UtListTests(regex_arg); }