Before 6.0.6 if hex content was incomplete, Suricata didn't error out.
With 6.0.6 incomplete hex was detected and errored on which is a
breaking change in a release branch. Instead, only emit a warning
unless strict content checking has been requested.
To enable strict behaviour on incomplete content hex in a rule,
"--strict-rule-keywords=content" can be used on the command line.
Issue: #5546
* Simple content match part of the detection engine.
*/
+#include "detect-engine-register.h"
#include "suricata-common.h"
#include "decode.h"
#include "detect.h"
* \retval -1 error
* \retval 0 ok
*/
-int DetectContentDataParse(const char *keyword, const char *contentstr,
- uint8_t **pstr, uint16_t *plen)
+int DetectContentDataParse(
+ const char *keyword, const char *contentstr, uint8_t **pstr, uint16_t *plen, bool *warning)
{
char *str = NULL;
size_t slen = 0;
bin_count++;
if (bin) {
if (binpos > 0) {
- SCLogError(SC_ERR_INVALID_SIGNATURE,
- "Incomplete hex code in content - %s. Invalidating signature.",
- contentstr);
+ if (SigMatchStrictEnabled(DETECT_CONTENT)) {
+ SCLogError(SC_ERR_INVALID_SIGNATURE,
+ "Incomplete hex code in content - %s. Invalidating signature.",
+ contentstr);
+ } else {
+ SCLogWarning(SC_ERR_INVALID_SIGNATURE,
+ "Incomplete hex code in content - %s. Invalidating signature. "
+ "This will become an error in Suricata 7.0.",
+ contentstr);
+ /* Prior to 6.0.6, incomplete hex was silently
+ ignored. With 6.0.6 this turned into an
+ error with -T. For 6.0.7, make the error
+ non-fatal unless strict content parsing is
+ enabled. */
+ if (warning != NULL) {
+ *warning = true;
+ }
+ }
goto error;
}
bin = 0;
error:
return -1;
}
+
/**
* \brief DetectContentParse
* \initonly
*/
-DetectContentData *DetectContentParse(SpmGlobalThreadCtx *spm_global_thread_ctx,
- const char *contentstr)
+DetectContentData *DetectContentParse(
+ SpmGlobalThreadCtx *spm_global_thread_ctx, const char *contentstr, bool *warning)
{
DetectContentData *cd = NULL;
uint8_t *content = NULL;
uint16_t len = 0;
int ret;
- ret = DetectContentDataParse("content", contentstr, &content, &len);
- if (ret == -1) {
+ ret = DetectContentDataParse("content", contentstr, &content, &len, warning);
+ if (ret < 0) {
return NULL;
}
DetectContentData *DetectContentParseEncloseQuotes(SpmGlobalThreadCtx *spm_global_thread_ctx,
const char *contentstr)
{
- return DetectContentParse(spm_global_thread_ctx, contentstr);
+ return DetectContentParse(spm_global_thread_ctx, contentstr, NULL);
}
/**
{
DetectContentData *cd = NULL;
SigMatch *sm = NULL;
+ bool warning = false;
- cd = DetectContentParse(de_ctx->spm_global_thread_ctx, contentstr);
+ cd = DetectContentParse(de_ctx->spm_global_thread_ctx, contentstr, &warning);
if (cd == NULL)
goto error;
if (s->init_data->negated == true) {
error:
DetectContentFree(de_ctx, cd);
- return -1;
+ return warning ? -4 : -1;
}
/**
SpmGlobalThreadCtx *spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher);
FAIL_IF(spm_global_thread_ctx == NULL);
- cd = DetectContentParse(spm_global_thread_ctx, teststring);
+ cd = DetectContentParse(spm_global_thread_ctx, teststring, NULL);
if (cd != NULL) {
if (memcmp(cd->content, teststringparsed, strlen(teststringparsed)) != 0) {
SCLogDebug("expected %s got ", teststringparsed);
SpmGlobalThreadCtx *spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher);
FAIL_IF(spm_global_thread_ctx == NULL);
- cd = DetectContentParse(spm_global_thread_ctx, teststring);
+ cd = DetectContentParse(spm_global_thread_ctx, teststring, NULL);
if (cd != NULL) {
if (memcmp(cd->content, teststringparsed, strlen(teststringparsed)) != 0) {
SCLogDebug("expected %s got ", teststringparsed);
SpmGlobalThreadCtx *spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher);
FAIL_IF(spm_global_thread_ctx == NULL);
- cd = DetectContentParse(spm_global_thread_ctx, teststring);
+ cd = DetectContentParse(spm_global_thread_ctx, teststring, NULL);
if (cd != NULL) {
if (memcmp(cd->content, teststringparsed, strlen(teststringparsed)) != 0) {
SCLogDebug("expected %s got ", teststringparsed);
SpmGlobalThreadCtx *spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher);
FAIL_IF(spm_global_thread_ctx == NULL);
- cd = DetectContentParse(spm_global_thread_ctx, teststring);
+ cd = DetectContentParse(spm_global_thread_ctx, teststring, NULL);
if (cd != NULL) {
uint16_t len = (cd->content_len > strlen(teststringparsed));
if (memcmp(cd->content, teststringparsed, len) != 0) {
SpmGlobalThreadCtx *spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher);
FAIL_IF(spm_global_thread_ctx == NULL);
- cd = DetectContentParse(spm_global_thread_ctx, teststring);
+ cd = DetectContentParse(spm_global_thread_ctx, teststring, NULL);
if (cd != NULL) {
SCLogDebug("expected NULL got ");
PrintRawUriFp(stdout,cd->content,cd->content_len);
SpmGlobalThreadCtx *spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher);
FAIL_IF(spm_global_thread_ctx == NULL);
- cd = DetectContentParse(spm_global_thread_ctx, teststring);
+ cd = DetectContentParse(spm_global_thread_ctx, teststring, NULL);
if (cd != NULL) {
uint16_t len = (cd->content_len > strlen(teststringparsed));
if (memcmp(cd->content, teststringparsed, len) != 0) {
SpmGlobalThreadCtx *spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher);
FAIL_IF(spm_global_thread_ctx == NULL);
- cd = DetectContentParse(spm_global_thread_ctx, teststring);
+ cd = DetectContentParse(spm_global_thread_ctx, teststring, NULL);
if (cd != NULL) {
SCLogDebug("expected NULL got %p: ", cd);
result = 0;
SpmGlobalThreadCtx *spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher);
FAIL_IF(spm_global_thread_ctx == NULL);
- cd = DetectContentParse(spm_global_thread_ctx, teststring);
+ cd = DetectContentParse(spm_global_thread_ctx, teststring, NULL);
if (cd != NULL) {
SCLogDebug("expected NULL got %p: ", cd);
result = 0;
SpmGlobalThreadCtx *spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher);
FAIL_IF(spm_global_thread_ctx == NULL);
- cd = DetectContentParse(spm_global_thread_ctx, teststring);
+ cd = DetectContentParse(spm_global_thread_ctx, teststring, NULL);
FAIL_IF_NULL(cd);
DetectContentFree(NULL, cd);
SpmDestroyGlobalThreadCtx(spm_global_thread_ctx);
SpmGlobalThreadCtx *spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher);
FAIL_IF(spm_global_thread_ctx == NULL);
- cd = DetectContentParse(spm_global_thread_ctx, teststring);
+ cd = DetectContentParse(spm_global_thread_ctx, teststring, NULL);
if (cd == NULL) {
SCLogDebug("expected not NULL");
result = 0;
SpmGlobalThreadCtx *spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher);
FAIL_IF(spm_global_thread_ctx == NULL);
- cd = DetectContentParse(spm_global_thread_ctx, teststring);
+ cd = DetectContentParse(spm_global_thread_ctx, teststring, NULL);
if (cd == NULL) {
SCLogDebug("expected not NULL");
result = 0;
SpmGlobalThreadCtx *spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher);
FAIL_IF(spm_global_thread_ctx == NULL);
- cd = DetectContentParse(spm_global_thread_ctx, teststring);
+ cd = DetectContentParse(spm_global_thread_ctx, teststring, NULL);
if (cd == NULL) {
SCLogDebug("expected not NULL");
result = 0;
SpmGlobalThreadCtx *spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher);
FAIL_IF(spm_global_thread_ctx == NULL);
- cd = DetectContentParse(spm_global_thread_ctx, teststring);
+ cd = DetectContentParse(spm_global_thread_ctx, teststring, NULL);
if (cd == NULL) {
SCLogDebug("expected not NULL");
result = 0;
/* prototypes */
void DetectContentRegister (void);
uint32_t DetectContentMaxId(DetectEngineCtx *);
-DetectContentData *DetectContentParse(SpmGlobalThreadCtx *spm_global_thread_ctx,
- const char *contentstr);
-int DetectContentDataParse(const char *keyword, const char *contentstr,
- uint8_t **pstr, uint16_t *plen);
+DetectContentData *DetectContentParse(
+ SpmGlobalThreadCtx *spm_global_thread_ctx, const char *contentstr, bool *warning);
+int DetectContentDataParse(
+ const char *keyword, const char *contentstr, uint8_t **pstr, uint16_t *plen, bool *warning);
DetectContentData *DetectContentParseEncloseQuotes(SpmGlobalThreadCtx *spm_global_thread_ctx,
const char *contentstr);
* \retval pointer to DetectFileextData on success
* \retval NULL on failure
*/
-static DetectFileextData *DetectFileextParse (DetectEngineCtx *de_ctx, const char *str, bool negate)
+static DetectFileextData *DetectFileextParse(
+ DetectEngineCtx *de_ctx, const char *str, bool negate, bool *warning)
{
DetectFileextData *fileext = NULL;
memset(fileext, 0x00, sizeof(DetectFileextData));
- if (DetectContentDataParse("fileext", str, &fileext->ext, &fileext->len) == -1) {
+ if (DetectContentDataParse("fileext", str, &fileext->ext, &fileext->len, warning) == -1) {
goto error;
}
uint16_t u;
{
DetectFileextData *fileext= NULL;
SigMatch *sm = NULL;
+ bool warning = false;
- fileext = DetectFileextParse(de_ctx, str, s->init_data->negated);
+ fileext = DetectFileextParse(de_ctx, str, s->init_data->negated, &warning);
if (fileext == NULL)
goto error;
DetectFileextFree(de_ctx, fileext);
if (sm != NULL)
SCFree(sm);
- return -1;
-
+ return warning ? -4 : -1;
}
/**
*/
static int DetectFileextTestParse01 (void)
{
- DetectFileextData *dfd = DetectFileextParse(NULL, "doc", false);
+ DetectFileextData *dfd = DetectFileextParse(NULL, "doc", false, NULL);
if (dfd != NULL) {
DetectFileextFree(NULL, dfd);
return 1;
{
int result = 0;
- DetectFileextData *dfd = DetectFileextParse(NULL, "tar.gz", false);
+ DetectFileextData *dfd = DetectFileextParse(NULL, "tar.gz", false, NULL);
if (dfd != NULL) {
if (dfd->len == 6 && memcmp(dfd->ext, "tar.gz", 6) == 0) {
result = 1;
{
int result = 0;
- DetectFileextData *dfd = DetectFileextParse(NULL, "pdf", false);
+ DetectFileextData *dfd = DetectFileextParse(NULL, "pdf", false, NULL);
if (dfd != NULL) {
if (dfd->len == 3 && memcmp(dfd->ext, "pdf", 3) == 0) {
result = 1;
* \retval filemagic pointer to DetectFilemagicData on success
* \retval NULL on failure
*/
-static DetectFilemagicData *DetectFilemagicParse (DetectEngineCtx *de_ctx, const char *str, bool negate)
+static DetectFilemagicData *DetectFilemagicParse(
+ DetectEngineCtx *de_ctx, const char *str, bool negate, bool *warning)
{
DetectFilemagicData *filemagic = NULL;
memset(filemagic, 0x00, sizeof(DetectFilemagicData));
- if (DetectContentDataParse ("filemagic", str, &filemagic->name, &filemagic->len) == -1) {
+ if (DetectContentDataParse("filemagic", str, &filemagic->name, &filemagic->len, warning) ==
+ -1) {
goto error;
}
static int DetectFilemagicSetup (DetectEngineCtx *de_ctx, Signature *s, const char *str)
{
SigMatch *sm = NULL;
+ bool warning = false;
- DetectFilemagicData *filemagic = DetectFilemagicParse(de_ctx, str, s->init_data->negated);
+ DetectFilemagicData *filemagic =
+ DetectFilemagicParse(de_ctx, str, s->init_data->negated, &warning);
if (filemagic == NULL)
- return -1;
+ return warning ? -4 : -1;
g_magic_thread_ctx_id = DetectRegisterThreadCtxFuncs(de_ctx, "filemagic",
DetectFilemagicThreadInit, (void *)filemagic, DetectFilemagicThreadFree, 1);
*/
static int DetectFilemagicTestParse01 (void)
{
- DetectFilemagicData *dnd = DetectFilemagicParse(NULL, "secret.pdf", false);
+ DetectFilemagicData *dnd = DetectFilemagicParse(NULL, "secret.pdf", false, NULL);
if (dnd != NULL) {
DetectFilemagicFree(NULL, dnd);
return 1;
{
int result = 0;
- DetectFilemagicData *dnd = DetectFilemagicParse(NULL, "backup.tar.gz", false);
+ DetectFilemagicData *dnd = DetectFilemagicParse(NULL, "backup.tar.gz", false, NULL);
if (dnd != NULL) {
if (dnd->len == 13 && memcmp(dnd->name, "backup.tar.gz", 13) == 0) {
result = 1;
{
int result = 0;
- DetectFilemagicData *dnd = DetectFilemagicParse(NULL, "cmd.exe", false);
+ DetectFilemagicData *dnd = DetectFilemagicParse(NULL, "cmd.exe", false, NULL);
if (dnd != NULL) {
if (dnd->len == 7 && memcmp(dnd->name, "cmd.exe", 7) == 0) {
result = 1;
* \retval filename pointer to DetectFilenameData on success
* \retval NULL on failure
*/
-static DetectFilenameData *DetectFilenameParse (DetectEngineCtx *de_ctx, const char *str, bool negate)
+static DetectFilenameData *DetectFilenameParse(
+ DetectEngineCtx *de_ctx, const char *str, bool negate, bool *warning)
{
DetectFilenameData *filename = NULL;
memset(filename, 0x00, sizeof(DetectFilenameData));
- if (DetectContentDataParse ("filename", str, &filename->name, &filename->len) == -1) {
+ if (DetectContentDataParse("filename", str, &filename->name, &filename->len, warning) == -1) {
goto error;
}
{
DetectFilenameData *filename = NULL;
SigMatch *sm = NULL;
+ bool warning = false;
- filename = DetectFilenameParse(de_ctx, str, s->init_data->negated);
+ filename = DetectFilenameParse(de_ctx, str, s->init_data->negated, &warning);
if (filename == NULL)
goto error;
DetectFilenameFree(de_ctx, filename);
if (sm != NULL)
SCFree(sm);
- return -1;
+ return warning ? -4 : -1;
}
/**
*/
static int DetectFilenameTestParse01 (void)
{
- DetectFilenameData *dnd = DetectFilenameParse(NULL, "secret.pdf", false);
+ DetectFilenameData *dnd = DetectFilenameParse(NULL, "secret.pdf", false, NULL);
if (dnd != NULL) {
DetectFilenameFree(NULL, dnd);
return 1;
{
int result = 0;
- DetectFilenameData *dnd = DetectFilenameParse(NULL, "backup.tar.gz", false);
+ DetectFilenameData *dnd = DetectFilenameParse(NULL, "backup.tar.gz", false, NULL);
if (dnd != NULL) {
if (dnd->len == 13 && memcmp(dnd->name, "backup.tar.gz", 13) == 0) {
result = 1;
{
int result = 0;
- DetectFilenameData *dnd = DetectFilenameParse(NULL, "cmd.exe", false);
+ DetectFilenameData *dnd = DetectFilenameParse(NULL, "cmd.exe", false, NULL);
if (dnd != NULL) {
if (dnd->len == 7 && memcmp(dnd->name, "cmd.exe", 7) == 0) {
result = 1;
uint8_t *content = NULL;
uint16_t contentlen = 0;
uint32_t contentflags = s->init_data->negated ? DETECT_CONTENT_NEGATED : 0;
+ bool warning = false;
ret = DetectParsePcreExec(&parse_regex, rawstr, 0, 0, ov, MAX_SUBSTRINGS);
if (ret != 3) {
}
SCLogDebug("varcontent %s", &varcontent[varcontent_index]);
- res = DetectContentDataParse("flowvar", &varcontent[varcontent_index], &content, &contentlen);
+ res = DetectContentDataParse(
+ "flowvar", &varcontent[varcontent_index], &content, &contentlen, &warning);
if (res == -1)
goto error;
SCFree(sm);
if (content != NULL)
SCFree(content);
- return -1;
+ return warning ? -4 : -1;
}
/** \brief Store flowvar in det_ctx so we can exec it post-match */
if (ret == -4) {
de_ctx->sigerror_ok = true;
goto error;
- }
- else if (ret == -3) {
+ } else if (ret == -3) {
de_ctx->sigerror_silent = true;
de_ctx->sigerror_ok = true;
goto error;
- }
- else if (ret == -2) {
+ } else if (ret == -2) {
de_ctx->sigerror_silent = true;
goto error;
} else if (ret < 0) {
parse_content = varcontent;
}
- ret = DetectContentDataParse("pktvar", parse_content, &content, &len);
+ ret = DetectContentDataParse("pktvar", parse_content, &content, &len, NULL);
if (ret == -1 || content == NULL) {
pcre_free(varname);
pcre_free(varcontent);
{
uint8_t *content = NULL;
uint16_t len = 0;
+ bool warning = false;
if (s->init_data->negated) {
SCLogError(SC_ERR_INVALID_VALUE, "Can't negate replacement string: %s",
return 0;
}
- int ret = DetectContentDataParse("replace", replacestr, &content, &len);
+ int ret = DetectContentDataParse("replace", replacestr, &content, &len, &warning);
if (ret == -1)
- return -1;
+ return warning ? -4 : -1;
/* add to the latest "content" keyword from pmatch */
const SigMatch *pm = DetectGetLastSMByListId(s, DETECT_SM_LIST_PMATCH,