You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
suricata/src/detect-fast-pattern.c

1159 lines
44 KiB
C

/* Copyright (C) 2007-2021 Open Information Security Foundation
*
* You can copy, redistribute or modify this Program under the terms of
* the GNU General Public License version 2 as published by the Free
* Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* version 2 along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
/**
* \file
*
* \author Anoop Saldanha <anoopsaldanha@gmail.com>
*
* Implements the fast_pattern keyword
*/
#include "suricata-common.h"
#include "detect.h"
#include "flow.h"
#include "detect-content.h"
#include "detect-parse.h"
#include "detect-engine.h"
#include "detect-engine-mpm.h"
#include "detect-engine-build.h"
#include "detect-fast-pattern.h"
#include "util-error.h"
#include "util-byte.h"
#include "util-debug.h"
#include "util-unittest.h"
#include "util-unittest-helper.h"
#define PARSE_REGEX "^(\\s*only\\s*)|\\s*([0-9]+)\\s*,\\s*([0-9]+)\\s*$"
static DetectParseRegex parse_regex;
static int DetectFastPatternSetup(DetectEngineCtx *, Signature *, const char *);
#ifdef UNITTESTS
static void DetectFastPatternRegisterTests(void);
#endif
/* holds the list of sm match lists that need to be searched for a keyword
* that has fp support */
static SCFPSupportSMList *g_fp_support_smlist_list = NULL;
/**
* \brief Checks if a particular buffer is in the list
* of lists that need to be searched for a keyword that has fp support.
*
* \param list_id The list id.
*
* \retval 1 If supported.
* \retval 0 If not.
*/
int FastPatternSupportEnabledForSigMatchList(const DetectEngineCtx *de_ctx,
const int list_id)
{
if (de_ctx->fp_support_smlist_list == NULL) {
return 0;
}
if (list_id == DETECT_SM_LIST_PMATCH)
return 1;
return DetectEngineBufferTypeSupportsMpmGetById(de_ctx, list_id);
}
static void Add(SCFPSupportSMList **list, const int list_id, const int priority)
{
SCFPSupportSMList *ip = NULL;
/* insertion point - ip */
for (SCFPSupportSMList *tmp = *list; tmp != NULL; tmp = tmp->next) {
if (list_id == tmp->list_id) {
SCLogDebug("SM list already registered.");
return;
}
/* We need a strict check to be sure that the current list
* was not already registered
* and other lists with the same priority hide it.
*/
if (priority < tmp->priority)
break;
ip = tmp;
}
if (*list == NULL) {
SCFPSupportSMList *new = SCMalloc(sizeof(SCFPSupportSMList));
if (unlikely(new == NULL))
exit(EXIT_FAILURE);
memset(new, 0, sizeof(SCFPSupportSMList));
new->list_id = list_id;
new->priority = priority;
*list = new;
return;
}
SCFPSupportSMList *new = SCMalloc(sizeof(SCFPSupportSMList));
if (unlikely(new == NULL))
exit(EXIT_FAILURE);
memset(new, 0, sizeof(SCFPSupportSMList));
new->list_id = list_id;
new->priority = priority;
if (ip == NULL) {
new->next = *list;
*list = new;
} else {
new->next = ip->next;
ip->next = new;
}
return;
}
/**
* \brief Lets one add a sm list id to be searched for potential fp supported
* keywords later.
*
* \param list_id SM list id.
* \param priority Priority for this list.
*/
void SupportFastPatternForSigMatchList(int list_id, int priority)
{
Add(&g_fp_support_smlist_list, list_id, priority);
}
void DetectEngineRegisterFastPatternForId(DetectEngineCtx *de_ctx, int list_id, int priority)
{
Add(&de_ctx->fp_support_smlist_list, list_id, priority);
}
/**
* \brief Registers the keywords(SMs) that should be given fp support.
*/
void SupportFastPatternForSigMatchTypes(void)
{
SupportFastPatternForSigMatchList(DETECT_SM_LIST_PMATCH, 3);
/* other types are handled by DetectMpmAppLayerRegister() */
}
void DetectEngineInitializeFastPatternList(DetectEngineCtx *de_ctx)
{
SCFPSupportSMList *last = NULL;
for (SCFPSupportSMList *tmp = g_fp_support_smlist_list; tmp != NULL; tmp = tmp->next) {
SCFPSupportSMList *n = SCCalloc(1, sizeof(*n));
if (n == NULL) {
FatalError("out of memory: %s", strerror(errno));
}
n->list_id = tmp->list_id;
n->priority = tmp->priority;
// append
if (de_ctx->fp_support_smlist_list == NULL) {
last = de_ctx->fp_support_smlist_list = n;
} else {
BUG_ON(last == NULL);
last->next = n;
last = n;
}
}
}
void DetectEngineFreeFastPatternList(DetectEngineCtx *de_ctx)
{
for (SCFPSupportSMList *tmp = de_ctx->fp_support_smlist_list; tmp != NULL;) {
SCFPSupportSMList *next = tmp->next;
SCFree(tmp);
tmp = next;
}
de_ctx->fp_support_smlist_list = NULL;
}
/**
* \brief Registration function for fast_pattern keyword
*/
void DetectFastPatternRegister(void)
{
sigmatch_table[DETECT_FAST_PATTERN].name = "fast_pattern";
sigmatch_table[DETECT_FAST_PATTERN].desc = "force using preceding content in the multi pattern matcher";
sigmatch_table[DETECT_FAST_PATTERN].url = "/rules/prefilter-keywords.html#fast-pattern";
sigmatch_table[DETECT_FAST_PATTERN].Match = NULL;
sigmatch_table[DETECT_FAST_PATTERN].Setup = DetectFastPatternSetup;
sigmatch_table[DETECT_FAST_PATTERN].Free = NULL;
#ifdef UNITTESTS
sigmatch_table[DETECT_FAST_PATTERN].RegisterTests = DetectFastPatternRegisterTests;
#endif
sigmatch_table[DETECT_FAST_PATTERN].flags |= SIGMATCH_OPTIONAL_OPT;
DetectSetupParseRegexes(PARSE_REGEX, &parse_regex);
}
/**
* \brief Configures the previous content context for a fast_pattern modifier
* keyword used in the rule.
*
* \param de_ctx Pointer to the Detection Engine Context.
* \param s Pointer to the Signature to which the current keyword belongs.
* \param arg May hold an argument
*
* \retval 0 On success.
* \retval -1 On failure.
*/
static int DetectFastPatternSetup(DetectEngineCtx *de_ctx, Signature *s, const char *arg)
{
int ret = 0, res = 0;
size_t pcre2len;
char arg_substr[128] = "";
DetectContentData *cd = NULL;
SigMatch *pm1 = DetectGetLastSMFromMpmLists(de_ctx, s);
SigMatch *pm2 = DetectGetLastSMFromLists(s, DETECT_CONTENT, -1);
if (pm1 == NULL && pm2 == NULL) {
SCLogError("fast_pattern found inside "
"the rule, without a content context. Please use a "
"content based keyword before using fast_pattern");
return -1;
}
SigMatch *pm = NULL;
if (pm1 && pm2) {
if (pm1->idx > pm2->idx)
pm = pm1;
else
pm = pm2;
} else if (pm1 && !pm2) {
pm = pm1;
} else {
pm = pm2;
}
cd = (DetectContentData *)pm->ctx;
if ((cd->flags & DETECT_CONTENT_NEGATED) &&
((cd->flags & DETECT_CONTENT_DISTANCE) ||
(cd->flags & DETECT_CONTENT_WITHIN) ||
(cd->flags & DETECT_CONTENT_OFFSET) ||
(cd->flags & DETECT_CONTENT_DEPTH))) {
/* we can't have any of these if we are having "only" */
SCLogError("fast_pattern; cannot be "
"used with negated content, along with relative modifiers");
goto error;
}
if (arg == NULL|| strcmp(arg, "") == 0) {
if (cd->flags & DETECT_CONTENT_FAST_PATTERN) {
SCLogError("can't use multiple fast_pattern "
"options for the same content");
goto error;
}
else { /*allow only one content to have fast_pattern modifier*/
for (uint32_t list_id = 0; list_id < DETECT_SM_LIST_MAX; list_id++) {
SigMatch *sm = NULL;
for (sm = s->init_data->smlists[list_id]; sm != NULL; sm = sm->next) {
if (sm->type == DETECT_CONTENT) {
DetectContentData *tmp_cd = (DetectContentData *)sm->ctx;
if (tmp_cd->flags & DETECT_CONTENT_FAST_PATTERN) {
SCLogError("fast_pattern "
"can be used on only one content in a rule");
goto error;
}
}
}
}
}
cd->flags |= DETECT_CONTENT_FAST_PATTERN;
return 0;
}
/* Execute the regex and populate args with captures. */
ret = DetectParsePcreExec(&parse_regex, arg, 0, 0);
/* fast pattern only */
if (ret == 2) {
if ((cd->flags & DETECT_CONTENT_NEGATED) ||
(cd->flags & DETECT_CONTENT_DISTANCE) ||
(cd->flags & DETECT_CONTENT_WITHIN) ||
(cd->flags & DETECT_CONTENT_OFFSET) ||
(cd->flags & DETECT_CONTENT_DEPTH)) {
/* we can't have any of these if we are having "only" */
SCLogError("fast_pattern: only; cannot be "
"used with negated content or with any of the relative "
"modifiers like distance, within, offset, depth");
goto error;
}
cd->flags |= DETECT_CONTENT_FAST_PATTERN_ONLY;
/* fast pattern chop */
} else if (ret == 4) {
pcre2len = sizeof(arg_substr);
res = pcre2_substring_copy_bynumber(
parse_regex.match, 2, (PCRE2_UCHAR8 *)arg_substr, &pcre2len);
if (res < 0) {
SCLogError("pcre2_substring_copy_bynumber failed "
"for fast_pattern offset");
goto error;
}
uint16_t offset;
if (StringParseUint16(&offset, 10, 0,
(const char *)arg_substr) < 0) {
SCLogError("Invalid fast pattern offset:"
" \"%s\"",
arg_substr);
goto error;
}
pcre2len = sizeof(arg_substr);
res = pcre2_substring_copy_bynumber(
parse_regex.match, 3, (PCRE2_UCHAR8 *)arg_substr, &pcre2len);
if (res < 0) {
SCLogError("pcre2_substring_copy_bynumber failed "
"for fast_pattern offset");
goto error;
}
uint16_t length;
if (StringParseUint16(&length, 10, 0,
(const char *)arg_substr) < 0) {
SCLogError("Invalid value for fast "
"pattern: \"%s\"",
arg_substr);
goto error;
}
// Avoiding integer overflow
if (offset > (65535 - length)) {
SCLogError("Fast pattern (length + offset) "
"exceeds limit pattern length limit");
goto error;
}
if (offset + length > cd->content_len) {
SCLogError("Fast pattern (length + "
"offset (%u)) exceeds pattern length (%u)",
offset + length, cd->content_len);
goto error;
}
cd->fp_chop_offset = offset;
cd->fp_chop_len = length;
cd->flags |= DETECT_CONTENT_FAST_PATTERN_CHOP;
} else {
SCLogError("parse error, ret %" PRId32 ", string %s", ret, arg);
goto error;
}
cd->flags |= DETECT_CONTENT_FAST_PATTERN;
return 0;
error:
return -1;
}
/*----------------------------------Unittests---------------------------------*/
#ifdef UNITTESTS
#include "detect-engine-alert.h"
static SigMatch *GetMatches(Signature *s, const int list)
{
SigMatch *sm = DetectBufferGetFirstSigMatch(s, list);
if (sm == NULL && list < DETECT_SM_LIST_MAX) {
sm = s->init_data->smlists[list];
}
return sm;
}
static int DetectFastPatternStickySingle(const char *sticky, const int list)
{
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
FAIL_IF_NULL(de_ctx);
char string[1024];
snprintf(string, sizeof(string),
"alert tcp any any -> any any "
"(%s%scontent:\"one\"; fast_pattern; sid:1;)",
sticky ? sticky : "", sticky ? "; " : " ");
Signature *s = DetectEngineAppendSig(de_ctx, string);
FAIL_IF_NULL(s);
SigMatch *sm = GetMatches(s, list);
FAIL_IF_NULL(sm);
FAIL_IF_NOT(sm->type == DETECT_CONTENT);
DetectContentData *cd = (DetectContentData *)sm->ctx;
FAIL_IF_NOT(DETECT_CONTENT_IS_SINGLE(cd));
FAIL_IF_NOT((cd->flags & DETECT_CONTENT_FAST_PATTERN) == DETECT_CONTENT_FAST_PATTERN);
DetectEngineCtxFree(de_ctx);
PASS;
}
static int DetectFastPatternModifierSingle(const char *sticky, const int list)
{
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
FAIL_IF_NULL(de_ctx);
char string[1024];
snprintf(string, sizeof(string),
"alert tcp any any -> any any "
"(content:\"one\"; %s%sfast_pattern; sid:1;)",
sticky ? sticky : "", sticky ? "; " : " ");
Signature *s = DetectEngineAppendSig(de_ctx, string);
FAIL_IF_NULL(s);
SigMatch *sm = GetMatches(s, list);
FAIL_IF_NULL(sm);
FAIL_IF_NOT(sm->type == DETECT_CONTENT);
DetectContentData *cd = (DetectContentData *)sm->ctx;
FAIL_IF_NOT(DETECT_CONTENT_IS_SINGLE(cd));
FAIL_IF_NOT((cd->flags & DETECT_CONTENT_FAST_PATTERN) == DETECT_CONTENT_FAST_PATTERN);
DetectEngineCtxFree(de_ctx);
PASS;
}
static int DetectFastPatternStickySingleNoFP(const char *sticky, const int list)
{
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
FAIL_IF_NULL(de_ctx);
char string[1024];
snprintf(string, sizeof(string),
"alert tcp any any -> any any "
"(%s%scontent:\"one\"; sid:1;)",
sticky ? sticky : "", sticky ? "; " : " ");
Signature *s = DetectEngineAppendSig(de_ctx, string);
FAIL_IF_NULL(s);
SigMatch *sm = GetMatches(s, list);
FAIL_IF_NULL(sm);
FAIL_IF_NOT(sm->type == DETECT_CONTENT);
DetectContentData *cd = (DetectContentData *)sm->ctx;
FAIL_IF_NOT(DETECT_CONTENT_IS_SINGLE(cd));
FAIL_IF_NOT((cd->flags & DETECT_CONTENT_FAST_PATTERN) == 0);
DetectEngineCtxFree(de_ctx);
PASS;
}
static int DetectFastPatternModifierSingleNoFP(const char *sticky, const int list)
{
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
FAIL_IF_NULL(de_ctx);
char string[1024];
snprintf(string, sizeof(string),
"alert tcp any any -> any any "
"(content:\"one\"; %s%ssid:1;)",
sticky ? sticky : "", sticky ? "; " : " ");
Signature *s = DetectEngineAppendSig(de_ctx, string);
FAIL_IF_NULL(s);
SigMatch *sm = GetMatches(s, list);
FAIL_IF_NULL(sm);
FAIL_IF_NOT(sm->type == DETECT_CONTENT);
DetectContentData *cd = (DetectContentData *)sm->ctx;
FAIL_IF_NOT(DETECT_CONTENT_IS_SINGLE(cd));
FAIL_IF_NOT((cd->flags & DETECT_CONTENT_FAST_PATTERN) == 0);
DetectEngineCtxFree(de_ctx);
PASS;
}
static int DetectFastPatternStickySingleBadArg(const char *sticky)
{
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
FAIL_IF_NULL(de_ctx);
char string[1024];
/* bogus argument to fast_pattern */
snprintf(string, sizeof(string),
"alert tcp any any -> any any "
"(%s%scontent:\"one\"; fast_pattern:boo; sid:1;)",
sticky ? sticky : "", sticky ? "; " : " ");
Signature *s = DetectEngineAppendSig(de_ctx, string);
FAIL_IF_NOT_NULL(s);
/* fast_pattern only with distance */
snprintf(string, sizeof(string),
"alert tcp any any -> any any "
"(%s%scontent:\"one\"; fast_pattern:only; content:\"two\"; distance:10; sid:1;)",
sticky ? sticky : "", sticky ? "; " : " ");
s = DetectEngineAppendSig(de_ctx, string);
FAIL_IF_NOT_NULL(s);
/* fast_pattern only with distance */
snprintf(string, sizeof(string),
"alert tcp any any -> any any "
"(%s%scontent:\"one\"; content:\"two\"; fast_pattern:only; distance:10; sid:1;)",
sticky ? sticky : "", sticky ? "; " : " ");
s = DetectEngineAppendSig(de_ctx, string);
FAIL_IF_NOT_NULL(s);
/* fast_pattern only with distance */
snprintf(string, sizeof(string),
"alert tcp any any -> any any "
"(%s%scontent:\"one\"; content:\"two\"; distance:10; fast_pattern:only; sid:1;)",
sticky ? sticky : "", sticky ? "; " : " ");
s = DetectEngineAppendSig(de_ctx, string);
FAIL_IF_NOT_NULL(s);
/* fast_pattern chop with invalid values */
snprintf(string, sizeof(string),
"alert tcp any any -> any any "
"(%s%scontent:\"one\"; fast_pattern:5,6; sid:1;)",
sticky ? sticky : "", sticky ? "; " : " ");
s = DetectEngineAppendSig(de_ctx, string);
FAIL_IF_NOT_NULL(s);
DetectEngineCtxFree(de_ctx);
PASS;
}
static int DetectFastPatternModifierBadRules(const char *sticky)
{
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
FAIL_IF_NULL(de_ctx);
char string[1024];
/* bogus argument to fast_pattern */
snprintf(string, sizeof(string),
"alert tcp any any -> any any "
"(content:\"one\"; %s%sfast_pattern:boo; sid:1;)",
sticky ? sticky : "", sticky ? "; " : " ");
Signature *s = DetectEngineAppendSig(de_ctx, string);
FAIL_IF_NOT_NULL(s);
/* fast_pattern only with distance */
snprintf(string, sizeof(string),
"alert tcp any any -> any any "
"(content:\"one\"; %s%sfast_pattern:only; content:\"two\"; %s%sdistance:10; sid:1;)",
sticky ? sticky : "", sticky ? "; " : " ", sticky ? sticky : "", sticky ? "; " : " ");
s = DetectEngineAppendSig(de_ctx, string);
FAIL_IF_NOT_NULL(s);
#if 0 // TODO bug?
/* fast_pattern only with distance */
snprintf(string, sizeof(string), "alert tcp any any -> any any "
"(content:\"one\"; %s%s content:\"two\"; %s%sdistance:10; fast_pattern:only; sid:1;)",
sticky ? sticky : "", sticky ? "; " : " ", sticky ? sticky : "", sticky ? "; " : " ");
s = DetectEngineAppendSig(de_ctx, string);
FAIL_IF_NOT_NULL(s);
#endif
/* fast_pattern only with within */
snprintf(string, sizeof(string),
"alert tcp any any -> any any "
"(content:\"one\"; %s%sfast_pattern:only; content:\"two\"; %s%swithin:10; sid:1;)",
sticky ? sticky : "", sticky ? "; " : " ", sticky ? sticky : "", sticky ? "; " : " ");
s = DetectEngineAppendSig(de_ctx, string);
FAIL_IF_NOT_NULL(s);
/* fast_pattern only with within */
snprintf(string, sizeof(string),
"alert tcp any any -> any any "
"(content:\"one\"; %s%s content:\"two\"; %s%swithin:10; fast_pattern:only; sid:1;)",
sticky ? sticky : "", sticky ? "; " : " ", sticky ? sticky : "", sticky ? "; " : " ");
s = DetectEngineAppendSig(de_ctx, string);
FAIL_IF_NOT_NULL(s);
/* fast_pattern only with offset */
snprintf(string, sizeof(string),
"alert tcp any any -> any any "
"(content:\"one\"; %s%sfast_pattern:only; offset:10; sid:1;)",
sticky ? sticky : "", sticky ? "; " : " ");
s = DetectEngineAppendSig(de_ctx, string);
FAIL_IF_NOT_NULL(s);
/* fast_pattern only with offset */
snprintf(string, sizeof(string),
"alert tcp any any -> any any "
"(content:\"one\"; %s%s offset:10; fast_pattern:only; sid:1;)",
sticky ? sticky : "", sticky ? "; " : " ");
s = DetectEngineAppendSig(de_ctx, string);
FAIL_IF_NOT_NULL(s);
/* fast_pattern only with depth */
snprintf(string, sizeof(string),
"alert tcp any any -> any any "
"(content:\"one\"; %s%sfast_pattern:only; depth:10; sid:1;)",
sticky ? sticky : "", sticky ? "; " : " ");
s = DetectEngineAppendSig(de_ctx, string);
FAIL_IF_NOT_NULL(s);
/* fast_pattern only with depth */
snprintf(string, sizeof(string),
"alert tcp any any -> any any "
"(content:\"one\"; %s%s depth:10; fast_pattern:only; sid:1;)",
sticky ? sticky : "", sticky ? "; " : " ");
s = DetectEngineAppendSig(de_ctx, string);
FAIL_IF_NOT_NULL(s);
/* fast_pattern only negate */
snprintf(string, sizeof(string),
"alert tcp any any -> any any "
"(content:\"one\"; %s%s content:!\"two\"; %s%sfast_pattern:only; sid:1;)",
sticky ? sticky : "", sticky ? "; " : " ", sticky ? sticky : "", sticky ? "; " : " ");
s = DetectEngineAppendSig(de_ctx, string);
FAIL_IF_NOT_NULL(s);
/* fast_pattern chop with invalid values */
snprintf(string, sizeof(string),
"alert tcp any any -> any any "
"(content:\"one\"; %s%sfast_pattern:5,6; sid:1;)",
sticky ? sticky : "", sticky ? "; " : " ");
s = DetectEngineAppendSig(de_ctx, string);
FAIL_IF_NOT_NULL(s);
/* fast_pattern chop with invalid values */
snprintf(string, sizeof(string),
"alert tcp any any -> any any "
"(content:\"one\"; %s%sfast_pattern:65977,2; sid:1;)",
sticky ? sticky : "", sticky ? "; " : " ");
s = DetectEngineAppendSig(de_ctx, string);
FAIL_IF_NOT_NULL(s);
/* fast_pattern chop with invalid values */
snprintf(string, sizeof(string),
"alert tcp any any -> any any "
"(content:\"one\"; %s%sfast_pattern:2,65977; sid:1;)",
sticky ? sticky : "", sticky ? "; " : " ");
s = DetectEngineAppendSig(de_ctx, string);
FAIL_IF_NOT_NULL(s);
/* fast_pattern chop with invalid values */
snprintf(string, sizeof(string),
"alert tcp any any -> any any "
"(content:\"one\"; %s%sfast_pattern:2,65534; sid:1;)",
sticky ? sticky : "", sticky ? "; " : " ");
s = DetectEngineAppendSig(de_ctx, string);
FAIL_IF_NOT_NULL(s);
/* fast_pattern chop with invalid values */
snprintf(string, sizeof(string),
"alert tcp any any -> any any "
"(content:\"one\"; %s%sfast_pattern:65534,2; sid:1;)",
sticky ? sticky : "", sticky ? "; " : " ");
s = DetectEngineAppendSig(de_ctx, string);
FAIL_IF_NOT_NULL(s);
/* negated fast_pattern with distance */
snprintf(string, sizeof(string),
"alert tcp any any -> any any "
"(content:\"one\"; %s%scontent:!\"two\"; fast_pattern:1,2; %s%sdistance:10; sid:1;)",
sticky ? sticky : "", sticky ? "; " : " ", sticky ? sticky : "", sticky ? "; " : " ");
s = DetectEngineAppendSig(de_ctx, string);
FAIL_IF_NOT_NULL(s);
/* negated fast_pattern with within */
snprintf(string, sizeof(string),
"alert tcp any any -> any any "
"(content:\"one\"; %s%scontent:!\"two\"; fast_pattern:1,2; %s%swithin:10; sid:1;)",
sticky ? sticky : "", sticky ? "; " : " ", sticky ? sticky : "", sticky ? "; " : " ");
s = DetectEngineAppendSig(de_ctx, string);
FAIL_IF_NOT_NULL(s);
/* negated fast_pattern with depth */
snprintf(string, sizeof(string),
"alert tcp any any -> any any "
"(content:\"one\"; %s%scontent:!\"two\"; fast_pattern:1,2; %s%sdepth:10; sid:1;)",
sticky ? sticky : "", sticky ? "; " : " ", sticky ? sticky : "", sticky ? "; " : " ");
s = DetectEngineAppendSig(de_ctx, string);
FAIL_IF_NOT_NULL(s);
/* negated fast_pattern with offset */
snprintf(string, sizeof(string),
"alert tcp any any -> any any "
"(content:\"one\"; %s%scontent:!\"two\"; fast_pattern:1,2; %s%soffset:10; sid:1;)",
sticky ? sticky : "", sticky ? "; " : " ", sticky ? sticky : "", sticky ? "; " : " ");
s = DetectEngineAppendSig(de_ctx, string);
FAIL_IF_NOT_NULL(s);
DetectEngineCtxFree(de_ctx);
PASS;
}
static int DetectFastPatternStickySingleFPOnly(const char *sticky, const int list)
{
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
FAIL_IF_NULL(de_ctx);
char string[1024];
snprintf(string, sizeof(string),
"alert tcp any any -> any any "
"(%s%scontent:\"one\"; fast_pattern:only; sid:1;)",
sticky ? sticky : "", sticky ? "; " : " ");
Signature *s = DetectEngineAppendSig(de_ctx, string);
FAIL_IF_NULL(s);
SigMatch *sm = GetMatches(s, list);
FAIL_IF_NULL(sm);
FAIL_IF_NOT(sm->type == DETECT_CONTENT);
DetectContentData *cd = (DetectContentData *)sm->ctx;
FAIL_IF_NOT(DETECT_CONTENT_IS_SINGLE(cd));
FAIL_IF_NOT((cd->flags & (DETECT_CONTENT_FAST_PATTERN | DETECT_CONTENT_FAST_PATTERN_ONLY)) ==
(DETECT_CONTENT_FAST_PATTERN | DETECT_CONTENT_FAST_PATTERN_ONLY));
DetectEngineCtxFree(de_ctx);
PASS;
}
static int DetectFastPatternModifierFPOnly(const char *sticky, const int list)
{
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
FAIL_IF_NULL(de_ctx);
char string[1024];
snprintf(string, sizeof(string),
"alert tcp any any -> any any "
"(content:\"one\"; %s%sfast_pattern:only; sid:1;)",
sticky ? sticky : "", sticky ? "; " : " ");
Signature *s = DetectEngineAppendSig(de_ctx, string);
FAIL_IF_NULL(s);
SigMatch *sm = GetMatches(s, list);
FAIL_IF_NULL(sm);
FAIL_IF_NOT(sm->type == DETECT_CONTENT);
DetectContentData *cd = (DetectContentData *)sm->ctx;
FAIL_IF_NOT(DETECT_CONTENT_IS_SINGLE(cd));
FAIL_IF_NOT((cd->flags & (DETECT_CONTENT_FAST_PATTERN | DETECT_CONTENT_FAST_PATTERN_ONLY)) ==
(DETECT_CONTENT_FAST_PATTERN | DETECT_CONTENT_FAST_PATTERN_ONLY));
snprintf(string, sizeof(string),
"alert tcp any any -> any any "
"(content:\"one\"; %s%scontent:\"two\"; %s%sfast_pattern:only; sid:2;)",
sticky ? sticky : "", sticky ? "; " : " ", sticky ? sticky : "", sticky ? "; " : " ");
s = DetectEngineAppendSig(de_ctx, string);
FAIL_IF_NULL(s);
sm = GetMatches(s, list);
FAIL_IF_NULL(sm);
FAIL_IF_NULL(sm->next);
FAIL_IF_NOT(sm->type == DETECT_CONTENT);
cd = (DetectContentData *)sm->ctx;
FAIL_IF_NOT(DETECT_CONTENT_IS_SINGLE(cd));
FAIL_IF_NOT(
(cd->flags & (DETECT_CONTENT_FAST_PATTERN | DETECT_CONTENT_FAST_PATTERN_ONLY)) == 0);
sm = sm->next;
FAIL_IF_NOT(sm->type == DETECT_CONTENT);
cd = (DetectContentData *)sm->ctx;
FAIL_IF_NOT(DETECT_CONTENT_IS_SINGLE(cd));
FAIL_IF_NOT((cd->flags & (DETECT_CONTENT_FAST_PATTERN | DETECT_CONTENT_FAST_PATTERN_ONLY)) ==
(DETECT_CONTENT_FAST_PATTERN | DETECT_CONTENT_FAST_PATTERN_ONLY));
snprintf(string, sizeof(string),
"alert tcp any any -> any any "
"(content:\"one\"; %s%scontent:\"two\"; distance:10; %s%scontent:\"three\"; "
"%s%sfast_pattern:only; sid:3;)",
sticky ? sticky : "", sticky ? "; " : " ", sticky ? sticky : "", sticky ? "; " : " ",
sticky ? sticky : "", sticky ? "; " : " ");
s = DetectEngineAppendSig(de_ctx, string);
FAIL_IF_NULL(s);
sm = GetMatches(s, list);
FAIL_IF_NULL(sm);
FAIL_IF_NULL(sm->next);
FAIL_IF_NOT(sm->type == DETECT_CONTENT);
cd = (DetectContentData *)sm->ctx;
FAIL_IF(DETECT_CONTENT_IS_SINGLE(cd));
FAIL_IF_NOT(
(cd->flags & (DETECT_CONTENT_FAST_PATTERN | DETECT_CONTENT_FAST_PATTERN_ONLY)) == 0);
sm = sm->next;
FAIL_IF_NULL(sm->next);
FAIL_IF_NOT(sm->type == DETECT_CONTENT);
cd = (DetectContentData *)sm->ctx;
FAIL_IF(DETECT_CONTENT_IS_SINGLE(cd));
FAIL_IF_NOT(
(cd->flags & (DETECT_CONTENT_FAST_PATTERN | DETECT_CONTENT_FAST_PATTERN_ONLY)) == 0);
sm = sm->next;
FAIL_IF_NOT_NULL(sm->next);
FAIL_IF_NOT(sm->type == DETECT_CONTENT);
cd = (DetectContentData *)sm->ctx;
FAIL_IF_NOT(DETECT_CONTENT_IS_SINGLE(cd));
FAIL_IF_NOT((cd->flags & (DETECT_CONTENT_FAST_PATTERN | DETECT_CONTENT_FAST_PATTERN_ONLY)) ==
(DETECT_CONTENT_FAST_PATTERN | DETECT_CONTENT_FAST_PATTERN_ONLY));
snprintf(string, sizeof(string),
"alert tcp any any -> any any "
"(content:\"one\"; %s%scontent:\"two\"; within:10; %s%scontent:\"three\"; "
"%s%sfast_pattern:only; sid:4;)",
sticky ? sticky : "", sticky ? "; " : " ", sticky ? sticky : "", sticky ? "; " : " ",
sticky ? sticky : "", sticky ? "; " : " ");
s = DetectEngineAppendSig(de_ctx, string);
FAIL_IF_NULL(s);
sm = GetMatches(s, list);
FAIL_IF_NULL(sm);
FAIL_IF_NULL(sm->next);
FAIL_IF_NOT(sm->type == DETECT_CONTENT);
cd = (DetectContentData *)sm->ctx;
FAIL_IF(DETECT_CONTENT_IS_SINGLE(cd));
FAIL_IF_NOT(
(cd->flags & (DETECT_CONTENT_FAST_PATTERN | DETECT_CONTENT_FAST_PATTERN_ONLY)) == 0);
sm = sm->next;
FAIL_IF_NULL(sm->next);
FAIL_IF_NOT(sm->type == DETECT_CONTENT);
cd = (DetectContentData *)sm->ctx;
FAIL_IF(DETECT_CONTENT_IS_SINGLE(cd));
FAIL_IF_NOT(
(cd->flags & (DETECT_CONTENT_FAST_PATTERN | DETECT_CONTENT_FAST_PATTERN_ONLY)) == 0);
sm = sm->next;
FAIL_IF_NOT_NULL(sm->next);
FAIL_IF_NOT(sm->type == DETECT_CONTENT);
cd = (DetectContentData *)sm->ctx;
FAIL_IF_NOT(DETECT_CONTENT_IS_SINGLE(cd));
FAIL_IF_NOT((cd->flags & (DETECT_CONTENT_FAST_PATTERN | DETECT_CONTENT_FAST_PATTERN_ONLY)) ==
(DETECT_CONTENT_FAST_PATTERN | DETECT_CONTENT_FAST_PATTERN_ONLY));
snprintf(string, sizeof(string),
"alert tcp any any -> any any "
"(content:\"one\"; %s%scontent:\"two\"; offset:10; %s%scontent:\"three\"; "
"%s%sfast_pattern:only; sid:5;)",
sticky ? sticky : "", sticky ? "; " : " ", sticky ? sticky : "", sticky ? "; " : " ",
sticky ? sticky : "", sticky ? "; " : " ");
s = DetectEngineAppendSig(de_ctx, string);
FAIL_IF_NULL(s);
sm = GetMatches(s, list);
FAIL_IF_NULL(sm);
FAIL_IF_NULL(sm->next);
FAIL_IF_NOT(sm->type == DETECT_CONTENT);
cd = (DetectContentData *)sm->ctx;
FAIL_IF_NOT(DETECT_CONTENT_IS_SINGLE(cd));
FAIL_IF_NOT(
(cd->flags & (DETECT_CONTENT_FAST_PATTERN | DETECT_CONTENT_FAST_PATTERN_ONLY)) == 0);
sm = sm->next;
FAIL_IF_NULL(sm->next);
FAIL_IF_NOT(sm->type == DETECT_CONTENT);
cd = (DetectContentData *)sm->ctx;
FAIL_IF(DETECT_CONTENT_IS_SINGLE(cd));
FAIL_IF_NOT(
(cd->flags & (DETECT_CONTENT_FAST_PATTERN | DETECT_CONTENT_FAST_PATTERN_ONLY)) == 0);
sm = sm->next;
FAIL_IF_NOT_NULL(sm->next);
FAIL_IF_NOT(sm->type == DETECT_CONTENT);
cd = (DetectContentData *)sm->ctx;
FAIL_IF_NOT(DETECT_CONTENT_IS_SINGLE(cd));
FAIL_IF_NOT((cd->flags & (DETECT_CONTENT_FAST_PATTERN | DETECT_CONTENT_FAST_PATTERN_ONLY)) ==
(DETECT_CONTENT_FAST_PATTERN | DETECT_CONTENT_FAST_PATTERN_ONLY));
snprintf(string, sizeof(string),
"alert tcp any any -> any any "
"(content:\"one\"; %s%scontent:\"two\"; depth:10; %s%scontent:\"three\"; "
"%s%sfast_pattern:only; sid:6;)",
sticky ? sticky : "", sticky ? "; " : " ", sticky ? sticky : "", sticky ? "; " : " ",
sticky ? sticky : "", sticky ? "; " : " ");
s = DetectEngineAppendSig(de_ctx, string);
FAIL_IF_NULL(s);
sm = GetMatches(s, list);
FAIL_IF_NULL(sm);
FAIL_IF_NULL(sm->next);
FAIL_IF_NOT(sm->type == DETECT_CONTENT);
cd = (DetectContentData *)sm->ctx;
FAIL_IF_NOT(DETECT_CONTENT_IS_SINGLE(cd));
FAIL_IF_NOT(
(cd->flags & (DETECT_CONTENT_FAST_PATTERN | DETECT_CONTENT_FAST_PATTERN_ONLY)) == 0);
sm = sm->next;
FAIL_IF_NULL(sm->next);
FAIL_IF_NOT(sm->type == DETECT_CONTENT);
cd = (DetectContentData *)sm->ctx;
FAIL_IF(DETECT_CONTENT_IS_SINGLE(cd));
FAIL_IF_NOT(
(cd->flags & (DETECT_CONTENT_FAST_PATTERN | DETECT_CONTENT_FAST_PATTERN_ONLY)) == 0);
sm = sm->next;
FAIL_IF_NOT_NULL(sm->next);
FAIL_IF_NOT(sm->type == DETECT_CONTENT);
cd = (DetectContentData *)sm->ctx;
FAIL_IF_NOT(DETECT_CONTENT_IS_SINGLE(cd));
FAIL_IF_NOT((cd->flags & (DETECT_CONTENT_FAST_PATTERN | DETECT_CONTENT_FAST_PATTERN_ONLY)) ==
(DETECT_CONTENT_FAST_PATTERN | DETECT_CONTENT_FAST_PATTERN_ONLY));
snprintf(string, sizeof(string),
"alert tcp any any -> any any "
"(content:!\"one\"; %s%sfast_pattern; content:\"two\"; depth:10; %s%ssid:7;)",
sticky ? sticky : "", sticky ? "; " : " ", sticky ? sticky : "", sticky ? "; " : " ");
s = DetectEngineAppendSig(de_ctx, string);
FAIL_IF_NULL(s);
sm = GetMatches(s, list);
FAIL_IF_NULL(sm);
FAIL_IF_NULL(sm->next);
FAIL_IF_NOT(sm->type == DETECT_CONTENT);
cd = (DetectContentData *)sm->ctx;
FAIL_IF_NOT(DETECT_CONTENT_IS_SINGLE(cd));
FAIL_IF_NOT((cd->flags & (DETECT_CONTENT_FAST_PATTERN | DETECT_CONTENT_FAST_PATTERN_ONLY |
DETECT_CONTENT_NEGATED)) ==
(DETECT_CONTENT_FAST_PATTERN | DETECT_CONTENT_NEGATED));
sm = sm->next;
FAIL_IF_NOT_NULL(sm->next);
FAIL_IF_NOT(sm->type == DETECT_CONTENT);
cd = (DetectContentData *)sm->ctx;
FAIL_IF(DETECT_CONTENT_IS_SINGLE(cd));
FAIL_IF_NOT(
(cd->flags & (DETECT_CONTENT_FAST_PATTERN | DETECT_CONTENT_FAST_PATTERN_ONLY)) == 0);
DetectEngineCtxFree(de_ctx);
PASS;
}
static int DetectFastPatternStickyFPChop(const char *sticky, const int list)
{
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
FAIL_IF_NULL(de_ctx);
char string[1024];
snprintf(string, sizeof(string),
"alert tcp any any -> any any "
"(%s%scontent:\"onetwothree\"; fast_pattern:3,4; sid:1;)",
sticky ? sticky : "", sticky ? "; " : " ");
Signature *s = DetectEngineAppendSig(de_ctx, string);
FAIL_IF_NULL(s);
SigMatch *sm = GetMatches(s, list);
FAIL_IF_NULL(sm);
FAIL_IF_NOT(sm->type == DETECT_CONTENT);
DetectContentData *cd = (DetectContentData *)sm->ctx;
FAIL_IF_NOT(DETECT_CONTENT_IS_SINGLE(cd));
FAIL_IF_NOT((cd->flags & (DETECT_CONTENT_FAST_PATTERN | DETECT_CONTENT_FAST_PATTERN_CHOP |
DETECT_CONTENT_FAST_PATTERN_ONLY)) ==
(DETECT_CONTENT_FAST_PATTERN | DETECT_CONTENT_FAST_PATTERN_CHOP));
FAIL_IF_NOT(cd->fp_chop_offset == 3);
FAIL_IF_NOT(cd->fp_chop_len == 4);
snprintf(string, sizeof(string),
"alert tcp any any -> any any "
"(%s%scontent:\"onetwothree\"; fast_pattern:3,4; content:\"xyz\"; distance:10; sid:2;)",
sticky ? sticky : "", sticky ? "; " : " ");
s = DetectEngineAppendSig(de_ctx, string);
FAIL_IF_NULL(s);
sm = GetMatches(s, list);
FAIL_IF_NULL(sm);
FAIL_IF_NOT(sm->type == DETECT_CONTENT);
cd = (DetectContentData *)sm->ctx;
FAIL_IF(DETECT_CONTENT_IS_SINGLE(cd));
FAIL_IF_NOT((cd->flags & (DETECT_CONTENT_FAST_PATTERN | DETECT_CONTENT_FAST_PATTERN_CHOP |
DETECT_CONTENT_FAST_PATTERN_ONLY)) ==
(DETECT_CONTENT_FAST_PATTERN | DETECT_CONTENT_FAST_PATTERN_CHOP));
FAIL_IF_NOT(cd->fp_chop_offset == 3);
FAIL_IF_NOT(cd->fp_chop_len == 4);
DetectEngineCtxFree(de_ctx);
PASS;
}
static int DetectFastPatternModifierFPChop(const char *sticky, const int list)
{
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
FAIL_IF_NULL(de_ctx);
char string[1024];
snprintf(string, sizeof(string),
"alert tcp any any -> any any "
"(content:\"onetwothree\"; %s%sfast_pattern:3,4; sid:1;)",
sticky ? sticky : "", sticky ? "; " : " ");
Signature *s = DetectEngineAppendSig(de_ctx, string);
FAIL_IF_NULL(s);
SigMatch *sm = GetMatches(s, list);
FAIL_IF_NULL(sm);
FAIL_IF_NOT(sm->type == DETECT_CONTENT);
DetectContentData *cd = (DetectContentData *)sm->ctx;
FAIL_IF_NOT(DETECT_CONTENT_IS_SINGLE(cd));
FAIL_IF_NOT((cd->flags & (DETECT_CONTENT_FAST_PATTERN | DETECT_CONTENT_FAST_PATTERN_CHOP |
DETECT_CONTENT_FAST_PATTERN_ONLY)) ==
(DETECT_CONTENT_FAST_PATTERN | DETECT_CONTENT_FAST_PATTERN_CHOP));
FAIL_IF_NOT(cd->fp_chop_offset == 3);
FAIL_IF_NOT(cd->fp_chop_len == 4);
snprintf(string, sizeof(string),
"alert tcp any any -> any any "
"(content:!\"onetwothree\"; %s%sfast_pattern:3,4; sid:2;)",
sticky ? sticky : "", sticky ? "; " : " ");
s = DetectEngineAppendSig(de_ctx, string);
FAIL_IF_NULL(s);
sm = GetMatches(s, list);
FAIL_IF_NULL(sm);
FAIL_IF_NOT(sm->type == DETECT_CONTENT);
cd = (DetectContentData *)sm->ctx;
FAIL_IF_NOT(DETECT_CONTENT_IS_SINGLE(cd));
FAIL_IF_NOT((cd->flags & (DETECT_CONTENT_NEGATED | DETECT_CONTENT_FAST_PATTERN |
DETECT_CONTENT_FAST_PATTERN_CHOP |
DETECT_CONTENT_FAST_PATTERN_ONLY)) ==
(DETECT_CONTENT_NEGATED | DETECT_CONTENT_FAST_PATTERN |
DETECT_CONTENT_FAST_PATTERN_CHOP));
FAIL_IF_NOT(cd->fp_chop_offset == 3);
FAIL_IF_NOT(cd->fp_chop_len == 4);
DetectEngineCtxFree(de_ctx);
PASS;
}
/**
* \test Checks if a fast_pattern is registered in a Signature
*/
static int DetectFastPatternTest01(void)
{
FAIL_IF_NOT(DetectFastPatternStickySingle(NULL, DETECT_SM_LIST_PMATCH));
FAIL_IF_NOT(DetectFastPatternModifierSingle(NULL, DETECT_SM_LIST_PMATCH));
FAIL_IF_NOT(DetectFastPatternStickySingleNoFP(NULL, DETECT_SM_LIST_PMATCH));
FAIL_IF_NOT(DetectFastPatternModifierSingleNoFP(NULL, DETECT_SM_LIST_PMATCH));
FAIL_IF_NOT(DetectFastPatternStickySingleBadArg(NULL));
FAIL_IF_NOT(DetectFastPatternModifierBadRules(NULL));
FAIL_IF_NOT(DetectFastPatternStickySingleFPOnly(NULL, DETECT_SM_LIST_PMATCH));
FAIL_IF_NOT(DetectFastPatternModifierFPOnly(NULL, DETECT_SM_LIST_PMATCH));
FAIL_IF_NOT(DetectFastPatternStickyFPChop(NULL, DETECT_SM_LIST_PMATCH));
FAIL_IF_NOT(DetectFastPatternModifierFPChop(NULL, DETECT_SM_LIST_PMATCH));
struct {
const char *buffer_name;
const char *sb_name;
const char *mod_name;
} keywords[] = {
{ "file_data", "file.data", NULL },
{ "http_uri", "http.uri", "http_uri" },
{ "http_raw_uri", "http.uri.raw", "http_raw_uri" },
{ "http_user_agent", "http.user_agent", "http_user_agent" },
{ "http_header", "http.header", "http_header" },
// http_raw_header requires sigs to have a direction
//{ "http_raw_header", "http.header.raw", "http_raw_header" },
{ "http_method", "http.method", "http_method" },
{ "http_cookie", "http.cookie", "http_cookie" },
{ "http_host", "http.host", "http_host" },
{ "http_raw_host", "http.host.raw", "http_raw_host" },
{ "http_stat_code", "http.stat_code", "http_stat_code" },
{ "http_stat_msg", "http.stat_msg", "http_stat_msg" },
{ "http_client_body", "http.request_body", "http_client_body" },
{ NULL, NULL, NULL },
};
for (int i = 0; keywords[i].buffer_name != NULL; i++) {
const int list_id = DetectBufferTypeGetByName(keywords[i].buffer_name);
FAIL_IF(list_id == -1);
const char *k = keywords[i].sb_name;
if (k) {
FAIL_IF_NOT(DetectFastPatternStickySingle(k, list_id));
FAIL_IF_NOT(DetectFastPatternStickySingleNoFP(k, list_id));
FAIL_IF_NOT(DetectFastPatternStickySingleBadArg(k));
FAIL_IF_NOT(DetectFastPatternStickySingleFPOnly(k, list_id));
FAIL_IF_NOT(DetectFastPatternStickyFPChop(k, list_id));
}
k = keywords[i].mod_name;
if (k) {
FAIL_IF_NOT(DetectFastPatternModifierSingle(k, list_id));
FAIL_IF_NOT(DetectFastPatternModifierSingleNoFP(k, list_id));
FAIL_IF_NOT(DetectFastPatternModifierBadRules(k));
FAIL_IF_NOT(DetectFastPatternModifierFPOnly(k, list_id));
FAIL_IF_NOT(DetectFastPatternModifierFPChop(k, list_id));
}
}
PASS;
}
/**
* \test Checks to make sure that other sigs work that should when fast_pattern is inspecting on the
* same payload
*
*/
static int DetectFastPatternTest14(void)
{
uint8_t *buf = (uint8_t *)"Dummy is our name. Oh yes. From right here "
"right now, all the way to hangover. right. strings5_imp now here "
"comes our dark knight strings_string5. Yes here is our dark knight";
uint16_t buflen = strlen((char *)buf);
ThreadVars th_v;
DetectEngineThreadCtx *det_ctx = NULL;
memset(&th_v, 0, sizeof(th_v));
Packet *p = UTHBuildPacket(buf, buflen, IPPROTO_TCP);
FAIL_IF_NULL(p);
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
FAIL_IF_NULL(de_ctx);
de_ctx->flags |= DE_QUIET;
FlowInitConfig(FLOW_QUIET);
Signature *s = DetectEngineAppendSig(de_ctx,
"alert tcp any any -> any any "
"(msg:\"fast_pattern test\"; content:\"strings_string5\"; content:\"knight\"; "
"fast_pattern; sid:1;)");
FAIL_IF_NULL(s);
s = DetectEngineAppendSig(de_ctx,
"alert tcp any any -> any any "
"(msg:\"test different content\"; content:\"Dummy is our name\"; sid:2;)");
FAIL_IF_NULL(s);
SigGroupBuild(de_ctx);
DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
FAIL_IF_NOT(PacketAlertCheck(p, 1));
FAIL_IF_NOT(PacketAlertCheck(p, 2));
UTHFreePackets(&p, 1);
DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
DetectEngineCtxFree(de_ctx);
FlowShutdown();
PASS;
}
/**
* Unittest to check
* - if we assign different content_ids to duplicate patterns, but one of the
* patterns has a fast_pattern chop set.
* - if 2 unique patterns get unique ids.
* - if 2 duplicate patterns, with no chop set get unique ids.
*/
static int DetectFastPatternTest671(void)
{
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
FAIL_IF_NULL(de_ctx);
de_ctx->flags |= DE_QUIET;
Signature *s[6];
s[0] = DetectEngineAppendSig(
de_ctx, "alert tcp any any -> any any (content:\"onetwothreefour\"; sid:1;)");
FAIL_IF_NULL(s[0]);
s[1] = DetectEngineAppendSig(
de_ctx, "alert tcp any any -> any any (content:\"onetwothreefour\"; sid:2;)");
FAIL_IF_NULL(s[1]);
s[2] = DetectEngineAppendSig(
de_ctx, "alert tcp any any -> any any (content:\"uniquepattern\"; sid:3;)");
FAIL_IF_NULL(s[2]);
s[3] = DetectEngineAppendSig(de_ctx,
"alert tcp any any -> any any (content:\"onetwothreefour\"; fast_pattern:3,5; sid:4;)");
FAIL_IF_NULL(s[3]);
s[4] = DetectEngineAppendSig(
de_ctx, "alert tcp any any -> any any (content:\"twoth\"; sid:5;)");
FAIL_IF_NULL(s[4]);
s[5] = DetectEngineAppendSig(de_ctx,
"alert tcp any any -> any any (content:\"onetwothreefour\"; fast_pattern:0,15; "
"sid:6;)");
FAIL_IF_NULL(s[5]);
SigGroupBuild(de_ctx);
SigMatchData *smd = s[0]->sm_arrays[DETECT_SM_LIST_PMATCH];
DetectContentData *cd = (DetectContentData *)smd->ctx;
FAIL_IF(cd->id != 0);
smd = s[1]->sm_arrays[DETECT_SM_LIST_PMATCH];
cd = (DetectContentData *)smd->ctx;
FAIL_IF(cd->id != 0);
smd = s[2]->sm_arrays[DETECT_SM_LIST_PMATCH];
cd = (DetectContentData *)smd->ctx;
FAIL_IF(cd->id != 2);
smd = s[3]->sm_arrays[DETECT_SM_LIST_PMATCH];
cd = (DetectContentData *)smd->ctx;
FAIL_IF(cd->id != 1);
smd = s[4]->sm_arrays[DETECT_SM_LIST_PMATCH];
cd = (DetectContentData *)smd->ctx;
FAIL_IF(cd->id != 1);
smd = s[5]->sm_arrays[DETECT_SM_LIST_PMATCH];
cd = (DetectContentData *)smd->ctx;
FAIL_IF(cd->id != 0);
DetectEngineCtxFree(de_ctx);
PASS;
}
static int DetectFastPatternPrefilter(void)
{
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
FAIL_IF_NULL(de_ctx);
const char *string = "alert tcp any any -> any any "
"(content:\"one\"; prefilter; sid:1;)";
Signature *s = DetectEngineAppendSig(de_ctx, string);
FAIL_IF_NULL(s);
SigMatch *sm = s->init_data->smlists[DETECT_SM_LIST_PMATCH];
FAIL_IF_NULL(sm);
FAIL_IF_NOT(sm->type == DETECT_CONTENT);
DetectContentData *cd = (DetectContentData *)sm->ctx;
FAIL_IF_NOT(DETECT_CONTENT_IS_SINGLE(cd));
FAIL_IF_NOT((cd->flags & DETECT_CONTENT_FAST_PATTERN) == DETECT_CONTENT_FAST_PATTERN);
DetectEngineCtxFree(de_ctx);
PASS;
}
static void DetectFastPatternRegisterTests(void)
{
UtRegisterTest("DetectFastPatternTest01", DetectFastPatternTest01);
UtRegisterTest("DetectFastPatternTest14", DetectFastPatternTest14);
/* Unittest to check
* - if we assign different content_ids to duplicate patterns, but one of the
* patterns has a fast_pattern chop set.
* - if 2 unique patterns get unique ids.
* - if 2 duplicate patterns, with no chop set get unique ids.
*/
UtRegisterTest("DetectFastPatternTest671", DetectFastPatternTest671);
UtRegisterTest("DetectFastPatternPrefilter", DetectFastPatternPrefilter);
}
#endif