From c8bd489aa19525b4379a4b6c02b6ae06c7bb4e21 Mon Sep 17 00:00:00 2001 From: Victor Julien Date: Fri, 3 Nov 2017 12:29:49 +0100 Subject: [PATCH] detect: set implied flow direction based on keywords --- src/detect-flow.c | 31 ++++++++++++++++++++++++++++ src/detect-flow.h | 2 ++ src/detect-parse.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 83 insertions(+) diff --git a/src/detect-flow.c b/src/detect-flow.c index 06992d48a4..88490285ae 100644 --- a/src/detect-flow.c +++ b/src/detect-flow.c @@ -316,6 +316,37 @@ error: } +int DetectFlowSetupImplicit(Signature *s, uint32_t flags) +{ +#define SIG_FLAG_BOTH (SIG_FLAG_TOSERVER|SIG_FLAG_TOCLIENT) + BUG_ON(flags == 0); + BUG_ON(flags & ~SIG_FLAG_BOTH); + BUG_ON((flags & SIG_FLAG_BOTH) == SIG_FLAG_BOTH); + + SCLogDebug("want %08x", flags & SIG_FLAG_BOTH); + SCLogDebug("have %08x", s->flags & SIG_FLAG_BOTH); + + if (flags & SIG_FLAG_TOSERVER) { + if ((s->flags & SIG_FLAG_BOTH) == SIG_FLAG_BOTH) { + /* both is set if we just have 'flow:established' */ + s->flags &= ~SIG_FLAG_TOCLIENT; + } else if (s->flags & SIG_FLAG_TOCLIENT) { + return -1; + } + s->flags |= SIG_FLAG_TOSERVER; + } else { + if ((s->flags & SIG_FLAG_BOTH) == SIG_FLAG_BOTH) { + /* both is set if we just have 'flow:established' */ + s->flags &= ~SIG_FLAG_TOSERVER; + } else if (s->flags & SIG_FLAG_TOSERVER) { + return -1; + } + s->flags |= SIG_FLAG_TOCLIENT; + } + return 0; +#undef SIG_FLAG_BOTH +} + /** * \brief this function is used to add the parsed flowdata into the current signature * diff --git a/src/detect-flow.h b/src/detect-flow.h index dc050b40d9..0fee4bf8c1 100644 --- a/src/detect-flow.h +++ b/src/detect-flow.h @@ -39,6 +39,8 @@ typedef struct DetectFlowData_ { uint8_t match_cnt; /* number of matches we need */ } DetectFlowData; +int DetectFlowSetupImplicit(Signature *s, uint32_t flags); + /* prototypes */ void DetectFlowRegister (void); diff --git a/src/detect-parse.c b/src/detect-parse.c index 5b3cd3243b..bd7fd1e2d4 100644 --- a/src/detect-parse.c +++ b/src/detect-parse.c @@ -1553,15 +1553,65 @@ static int SigValidate(DetectEngineCtx *de_ctx, Signature *s) SCReturnInt(0); } + struct BufferVsDir { + int ts; + int tc; + } bufdir[nlists]; + memset(&bufdir, 0, nlists * sizeof(struct BufferVsDir)); + int x; for (x = 0; x < nlists; x++) { if (s->init_data->smlists[x]) { + const DetectEngineAppInspectionEngine *app = de_ctx->app_inspect_engines; + for ( ; app != NULL; app = app->next) { + if (app->sm_list == x && s->alproto == app->alproto) { + SCLogDebug("engine %s dir %d alproto %d", + DetectBufferTypeGetNameById(de_ctx, app->sm_list), + app->dir, app->alproto); + + bufdir[x].ts += (app->dir == 0); + bufdir[x].tc += (app->dir == 1); + } + } + if (DetectBufferRunValidateCallback(de_ctx, x, s, &de_ctx->sigerror) == FALSE) { SCReturnInt(0); } } } + int ts_excl = 0; + int tc_excl = 0; + int dir_amb = 0; + for (x = 0; x < nlists; x++) { + if (bufdir[x].ts == 0 && bufdir[x].tc == 0) + continue; + ts_excl += (bufdir[x].ts > 0 && bufdir[x].tc == 0); + tc_excl += (bufdir[x].ts == 0 && bufdir[x].tc > 0); + dir_amb += (bufdir[x].ts > 0 && bufdir[x].tc > 0); + + SCLogDebug("%s/%d: %d/%d", DetectBufferTypeGetNameById(de_ctx, x), + x, bufdir[x].ts, bufdir[x].tc); + } + if (ts_excl && tc_excl) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "rule %u mixes keywords with conflicting directions", s->id); + SCReturnInt(0); + } else if (ts_excl) { + SCLogDebug("%u: implied rule direction is toserver", s->id); + if (DetectFlowSetupImplicit(s, SIG_FLAG_TOSERVER) < 0) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "rule %u mixes keywords with conflicting directions", s->id); + SCReturnInt(0); + } + } else if (tc_excl) { + SCLogDebug("%u: implied rule direction is toclient", s->id); + if (DetectFlowSetupImplicit(s, SIG_FLAG_TOCLIENT) < 0) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "rule %u mixes keywords with conflicting directions", s->id); + SCReturnInt(0); + } + } else if (dir_amb) { + SCLogDebug("%u: rule direction cannot be deduced from keywords", s->id); + } + if ((s->flags & SIG_FLAG_REQUIRE_PACKET) && (s->flags & SIG_FLAG_REQUIRE_STREAM)) { SCLogError(SC_ERR_INVALID_SIGNATURE, "can't mix packet keywords with " -- 2.47.2