detect/content: implement endswith

pull/3182/head
Victor Julien 8 years ago
parent 07738af868
commit d588237235

@ -61,6 +61,7 @@ enum {
DETECT_PCRE,
DETECT_DEPTH,
DETECT_STARTS_WITH,
DETECT_ENDS_WITH,
DETECT_DISTANCE,
DETECT_WITHIN,
DETECT_OFFSET,

@ -59,6 +59,8 @@ int DetectIsdataatSetup (DetectEngineCtx *, Signature *, const char *);
void DetectIsdataatRegisterTests(void);
void DetectIsdataatFree(void *);
static int DetectEndsWithSetup (DetectEngineCtx *de_ctx, Signature *s, const char *nullstr);
/**
* \brief Registration function for isdataat: keyword
*/
@ -73,6 +75,12 @@ void DetectIsdataatRegister(void)
sigmatch_table[DETECT_ISDATAAT].Free = DetectIsdataatFree;
sigmatch_table[DETECT_ISDATAAT].RegisterTests = DetectIsdataatRegisterTests;
sigmatch_table[DETECT_ENDS_WITH].name = "endswith";
sigmatch_table[DETECT_ENDS_WITH].desc = "make sure the previous content matches exactly at the end of the buffer";
sigmatch_table[DETECT_ENDS_WITH].url = DOC_URL DOC_VERSION "/rules/payload-keywords.html#endswith";
sigmatch_table[DETECT_ENDS_WITH].Setup = DetectEndsWithSetup;
sigmatch_table[DETECT_ENDS_WITH].flags = SIGMATCH_NOOPT;
DetectSetupParseRegexes(PARSE_REGEX, &parse_regex, &parse_regex_study);
}
@ -299,6 +307,28 @@ void DetectIsdataatFree(void *ptr)
SCFree(idad);
}
static int DetectEndsWithSetup (DetectEngineCtx *de_ctx, Signature *s, const char *nullstr)
{
SigMatch *pm = NULL;
int ret = -1;
/* retrieve the sm to apply the depth against */
pm = DetectGetLastSMFromLists(s, DETECT_CONTENT, -1);
if (pm == NULL) {
SCLogError(SC_ERR_DEPTH_MISSING_CONTENT, "endswith needs a "
"preceding content option");
goto end;
}
/* verify other conditions. */
DetectContentData *cd = (DetectContentData *)pm->ctx;
cd->flags |= DETECT_CONTENT_ENDS_WITH;
ret = 0;
end:
return ret;
}
#ifdef UNITTESTS
static int g_dce_stub_data_buffer_id = 0;

@ -235,6 +235,34 @@ static int DetectEngineContentInspectionTest11(void) {
TEST_FOOTER;
}
/** \test endswith (isdataat) recursion logic
* based on DetectEngineContentInspectionTest06 */
static int DetectEngineContentInspectionTest12(void) {
TEST_HEADER;
// 6 steps: (1) a, (2) 1st b, (3) c not found, (4) 2nd b, (5) c found, endswith
TEST_RUN("ababc", 5, "content:\"a\"; content:\"b\"; distance:0; within:1; content:\"c\"; distance:0; within:1; endswith;", true, 5);
TEST_RUN("ababcabc", 8, "content:\"a\"; content:\"b\"; distance:0; within:1; content:\"c\"; distance:0; within:1; endswith;", true, 7);
TEST_RUN("abcXYZ", 6, "content:\"abc\"; content:\"XYZ\"; distance:0; within:3; endswith;", true, 2);
TEST_RUN("abcXYZ", 6, "content:\"XYZ\"; distance:3; within:3; endswith;", true, 1);
TEST_RUN("abcXYZ", 6, "content:\"cXY\"; distance:2; within:3; endswith;", false, 1);
TEST_RUN("xxxxxxxxxxxxxxxxxyYYYYYYYYYYYYYYYY", 34, "content:\"yYYYYYYYYYYYYYYYY\"; distance:9; within:29; endswith;", true, 1);
TEST_FOOTER;
}
static int DetectEngineContentInspectionTest13(void) {
TEST_HEADER;
TEST_RUN("ab", 2, "content:\"a\"; startswith; content:\"b\"; endswith;", true, 2);
TEST_RUN("ab", 2, "content:\"a\"; startswith; content:\"b\"; within:1; distance:0; endswith;", true, 2);
TEST_RUN("ab", 2, "content:\"ab\"; startswith; endswith;", true, 1);
TEST_RUN("ab", 2, "content:\"a\"; startswith; endswith;", false, 1);
TEST_RUN("ab", 2, "content:\"b\"; startswith;", false, 1);
TEST_RUN("ab", 2, "content:\"b\"; startswith; endswith;", false, 1);
TEST_FOOTER;
}
void DetectEngineContentInspectionRegisterTests(void)
{
UtRegisterTest("DetectEngineContentInspectionTest01",
@ -259,6 +287,10 @@ void DetectEngineContentInspectionRegisterTests(void)
DetectEngineContentInspectionTest10);
UtRegisterTest("DetectEngineContentInspectionTest11 startswith",
DetectEngineContentInspectionTest11);
UtRegisterTest("DetectEngineContentInspectionTest12 endswith",
DetectEngineContentInspectionTest12);
UtRegisterTest("DetectEngineContentInspectionTest13 mix startswith/endswith",
DetectEngineContentInspectionTest13);
}
#undef TEST_HEADER

Loading…
Cancel
Save