detect-flow: no_frag and only_frag keyword support

Support flow:no_frag and flow:only_frag keywords from Snort.
pull/2364/head
Jason Ish 9 years ago committed by Victor Julien
parent f81619a13e
commit 8f56c23468

@ -76,11 +76,26 @@ void DetectFlowRegister (void)
DetectSetupParseRegexes(PARSE_REGEX, &parse_regex, &parse_regex_study);
}
static inline int FlowMatch(const uint8_t pflowflags, const uint16_t tflags,
const uint8_t dflags, const uint8_t match_cnt)
/**
* \param pflags packet flags (p->flags)
* \param pflowflags packet flow flags (p->flowflags)
* \param tflags detection flags (det_ctx->flags)
* \param dflags detect flow flags
* \param match_cnt number of matches to trigger
*/
static inline int FlowMatch(const uint32_t pflags, const uint8_t pflowflags,
const uint16_t tflags, const uint16_t dflags, const uint8_t match_cnt)
{
uint8_t cnt = 0;
if ((dflags & DETECT_FLOW_FLAG_NO_FRAG) &&
(!(pflags & PKT_REBUILT_FRAGMENT))) {
cnt++;
} else if ((dflags & DETECT_FLOW_FLAG_ONLY_FRAG) &&
(pflags & PKT_REBUILT_FRAGMENT)) {
cnt++;
}
if ((dflags & DETECT_FLOW_FLAG_TOSERVER) && (pflowflags & FLOW_PKT_TOSERVER)) {
cnt++;
} else if ((dflags & DETECT_FLOW_FLAG_TOCLIENT) && (pflowflags & FLOW_PKT_TOCLIENT)) {
@ -135,7 +150,7 @@ int DetectFlowMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx, Packet *p, S
const DetectFlowData *fd = (const DetectFlowData *)ctx;
int ret = FlowMatch(p->flowflags, det_ctx->flags, fd->flags, fd->match_cnt);;
int ret = FlowMatch(p->flags, p->flowflags, det_ctx->flags, fd->flags, fd->match_cnt);;
SCLogDebug("returning %" PRId32 " fd->match_cnt %" PRId32 " fd->flags 0x%02X p->flowflags 0x%02X",
ret, fd->match_cnt, fd->flags, p->flowflags);
SCReturnInt(ret);
@ -263,6 +278,24 @@ DetectFlowData *DetectFlowParse (char *flowstr)
goto error;
}
fd->flags |= DETECT_FLOW_FLAG_NOSTREAM;
} else if (strcasecmp(args[i], "no_frag") == 0) {
if (fd->flags & DETECT_FLOW_FLAG_NO_FRAG) {
SCLogError(SC_ERR_FLAGS_MODIFIER, "cannot set no_frag flag is already set");
goto error;
} else if (fd->flags & DETECT_FLOW_FLAG_ONLY_FRAG) {
SCLogError(SC_ERR_FLAGS_MODIFIER, "cannot set no_frag flag, only_frag already set");
goto error;
}
fd->flags |= DETECT_FLOW_FLAG_NO_FRAG;
} else if (strcasecmp(args[i], "only_frag") == 0) {
if (fd->flags & DETECT_FLOW_FLAG_ONLY_FRAG) {
SCLogError(SC_ERR_FLAGS_MODIFIER, "cannot set only_frag flag is already set");
goto error;
} else if (fd->flags & DETECT_FLOW_FLAG_NO_FRAG) {
SCLogError(SC_ERR_FLAGS_MODIFIER, "cannot set only_frag flag, no_frag already set");
goto error;
}
fd->flags |= DETECT_FLOW_FLAG_ONLY_FRAG;
} else {
SCLogError(SC_ERR_INVALID_VALUE, "invalid flow option \"%s\"", args[i]);
goto error;
@ -365,7 +398,7 @@ PrefilterPacketFlowMatch(DetectEngineThreadCtx *det_ctx, Packet *p, const void *
if (PrefilterPacketHeaderExtraMatch(ctx, p) == FALSE)
return;
if (FlowMatch(p->flowflags, det_ctx->flags, ctx->v1.u8[0], ctx->v1.u8[1]))
if (FlowMatch(p->flags, p->flowflags, det_ctx->flags, ctx->v1.u8[0], ctx->v1.u8[1]))
{
PrefilterAddSids(&det_ctx->pmq, ctx->sigs_array, ctx->sigs_cnt);
}
@ -926,6 +959,75 @@ static int DetectFlowTestParseNotEstablished(void)
PASS;
}
/**
* \test Test parsing of the "no_frag" flow argument.
*/
static int DetectFlowTestParseNoFrag(void)
{
DetectFlowData *fd = NULL;
fd = DetectFlowParse("no_frag");
FAIL_IF_NULL(fd);
FAIL_IF_NOT(fd->flags & DETECT_FLOW_FLAG_NO_FRAG);
DetectFlowFree(fd);
PASS;
}
/**
* \test Test parsing of the "only_frag" flow argument.
*/
static int DetectFlowTestParseOnlyFrag(void)
{
DetectFlowData *fd = NULL;
fd = DetectFlowParse("only_frag");
FAIL_IF_NULL(fd);
FAIL_IF_NOT(fd->flags & DETECT_FLOW_FLAG_ONLY_FRAG);
DetectFlowFree(fd);
PASS;
}
/**
* \test Test that parsing of only_frag and no_frag together fails.
*/
static int DetectFlowTestParseNoFragOnlyFrag(void)
{
DetectFlowData *fd = NULL;
fd = DetectFlowParse("no_frag,only_frag");
FAIL_IF_NOT_NULL(fd);
PASS;
}
/**
* \test Test no_frag matching.
*/
static int DetectFlowTestNoFragMatch(void)
{
uint32_t pflags = 0;
DetectFlowData *fd = DetectFlowParse("no_frag");
FAIL_IF_NULL(fd);
FAIL_IF_NOT(fd->flags & DETECT_FLOW_FLAG_NO_FRAG);
FAIL_IF_NOT(fd->match_cnt == 1);
FAIL_IF_NOT(FlowMatch(pflags, 0, 0, fd->flags, fd->match_cnt));
pflags |= PKT_REBUILT_FRAGMENT;
FAIL_IF(FlowMatch(pflags, 0, 0, fd->flags, fd->match_cnt));
PASS;
}
/**
* \test Test only_frag matching.
*/
static int DetectFlowTestOnlyFragMatch(void)
{
uint32_t pflags = 0;
DetectFlowData *fd = DetectFlowParse("only_frag");
FAIL_IF_NULL(fd);
FAIL_IF_NOT(fd->flags & DETECT_FLOW_FLAG_ONLY_FRAG);
FAIL_IF_NOT(fd->match_cnt == 1);
FAIL_IF(FlowMatch(pflags, 0, 0, fd->flags, fd->match_cnt));
pflags |= PKT_REBUILT_FRAGMENT;
FAIL_IF_NOT(FlowMatch(pflags, 0, 0, fd->flags, fd->match_cnt));
PASS;
}
#endif /* UNITTESTS */
/**
@ -970,6 +1072,13 @@ void DetectFlowRegisterTests(void)
UtRegisterTest("DetectFlowTestParse21", DetectFlowTestParse21);
UtRegisterTest("DetectFlowTestParseNotEstablished",
DetectFlowTestParseNotEstablished);
UtRegisterTest("DetectFlowTestParseNoFrag", DetectFlowTestParseNoFrag);
UtRegisterTest("DetectFlowTestParseOnlyFrag",
DetectFlowTestParseOnlyFrag);
UtRegisterTest("DetectFlowTestParseNoFragOnlyFrag",
DetectFlowTestParseNoFragOnlyFrag);
UtRegisterTest("DetectFlowTestNoFragMatch", DetectFlowTestNoFragMatch);
UtRegisterTest("DetectFlowTestOnlyFragMatch", DetectFlowTestOnlyFragMatch);
UtRegisterTest("DetectFlowSigTest01", DetectFlowSigTest01);
#endif /* UNITTESTS */

@ -24,17 +24,19 @@
#ifndef __DETECT_FLOW_H__
#define __DETECT_FLOW_H__
#define DETECT_FLOW_FLAG_TOSERVER 0x01
#define DETECT_FLOW_FLAG_TOCLIENT 0x02
#define DETECT_FLOW_FLAG_ESTABLISHED 0x04
#define DETECT_FLOW_FLAG_NOT_ESTABLISHED 0x08
#define DETECT_FLOW_FLAG_STATELESS 0x10
#define DETECT_FLOW_FLAG_ONLYSTREAM 0x20
#define DETECT_FLOW_FLAG_NOSTREAM 0x40
#define DETECT_FLOW_FLAG_TOSERVER BIT_U16(0)
#define DETECT_FLOW_FLAG_TOCLIENT BIT_U16(1)
#define DETECT_FLOW_FLAG_ESTABLISHED BIT_U16(2)
#define DETECT_FLOW_FLAG_NOT_ESTABLISHED BIT_U16(3)
#define DETECT_FLOW_FLAG_STATELESS BIT_U16(4)
#define DETECT_FLOW_FLAG_ONLYSTREAM BIT_U16(5)
#define DETECT_FLOW_FLAG_NOSTREAM BIT_U16(6)
#define DETECT_FLOW_FLAG_NO_FRAG BIT_U16(7)
#define DETECT_FLOW_FLAG_ONLY_FRAG BIT_U16(8)
typedef struct DetectFlowData_ {
uint8_t flags; /* flags to match */
uint8_t match_cnt; /* number of matches we need */
uint16_t flags; /* flags to match */
uint8_t match_cnt; /* number of matches we need */
} DetectFlowData;
/* prototypes */

Loading…
Cancel
Save