sigmatch_table[DETECT_CONTENT].Setup = DetectContentSetup;
sigmatch_table[DETECT_CONTENT].Free = DetectContentFree;
sigmatch_table[DETECT_CONTENT].RegisterTests = DetectContentRegisterTests;
+ sigmatch_table[DETECT_CONTENT].flags = (SIGMATCH_QUOTES_MANDATORY|SIGMATCH_HANDLE_NEGATION);
}
/**
* \retval 0 ok
*/
int DetectContentDataParse(const char *keyword, const char *contentstr,
- uint8_t **pstr, uint16_t *plen, uint32_t *flags)
+ uint8_t **pstr, uint16_t *plen)
{
char *str = NULL;
- uint16_t len;
- uint16_t pos = 0;
- uint16_t slen = 0;
+ size_t slen = 0;
slen = strlen(contentstr);
if (slen == 0) {
return -1;
}
+ uint8_t buffer[slen + 1];
+ strlcpy((char *)&buffer, contentstr, slen + 1);
+ str = (char *)buffer;
- /* skip the first spaces */
- while (pos < slen && isspace((unsigned char)contentstr[pos]))
- pos++;
-
- if (contentstr[pos] == '!') {
- *flags = DETECT_CONTENT_NEGATED;
- pos++;
- } else
- *flags = 0;
-
- if (contentstr[pos] == '\"' && ((slen - pos) <= 1))
- goto error;
-
- if (!(contentstr[pos] == '\"' && contentstr[slen - 1] == '\"')) {
- SCLogError(SC_ERR_INVALID_SIGNATURE, "%s keyword arguments "
- "should be always enclosed in double quotes. Invalid "
- "content keyword passed in this rule - \"%s\"",
- keyword, contentstr);
- goto error;
- }
-
- if ((str = SCStrdup(contentstr + pos + 1)) == NULL)
- goto error;
- str[strlen(str) - 1] = '\0';
-
- len = strlen(str);
- if (len == 0)
- goto error;
-
- SCLogDebug("\"%s\", len %" PRIu32 "", str, len);
+ SCLogDebug("\"%s\", len %" PRIuMAX, str, (uintmax_t)slen);
//SCLogDebug("DetectContentParse: \"%s\", len %" PRIu32 "", str, len);
char converted = 0;
uint8_t binpos = 0;
uint16_t bin_count = 0;
- for (i = 0, x = 0; i < len; i++) {
+ for (i = 0, x = 0; i < slen; i++) {
// SCLogDebug("str[%02u]: %c", i, str[i]);
if (str[i] == '|') {
bin_count++;
}
if (converted) {
- len = x;
+ slen = x;
}
}
- *plen = len;
- *pstr = (uint8_t *)str;
- return 0;
+ if (slen) {
+ uint8_t *ptr = SCCalloc(1, slen);
+ if (ptr == NULL) {
+ return -1;
+ }
+ memcpy(ptr, str, slen);
+ *plen = (uint16_t)slen;
+ *pstr = ptr;
+ return 0;
+ }
error:
- if (str != NULL)
- SCFree(str);
return -1;
}
/**
* \initonly
*/
DetectContentData *DetectContentParse(SpmGlobalThreadCtx *spm_global_thread_ctx,
- char *contentstr)
+ const char *contentstr)
{
DetectContentData *cd = NULL;
uint8_t *content = NULL;
uint16_t len = 0;
- uint32_t flags = 0;
int ret;
- ret = DetectContentDataParse("content", contentstr, &content, &len, &flags);
+ ret = DetectContentDataParse("content", contentstr, &content, &len);
if (ret == -1) {
return NULL;
}
memset(cd, 0, sizeof(DetectContentData) + len);
- if (flags == DETECT_CONTENT_NEGATED)
- cd->flags |= DETECT_CONTENT_NEGATED;
-
cd->content = (uint8_t *)cd + sizeof(DetectContentData);
memcpy(cd->content, content, len);
cd->content_len = len;
}
DetectContentData *DetectContentParseEncloseQuotes(SpmGlobalThreadCtx *spm_global_thread_ctx,
- char *contentstr)
+ const char *contentstr)
{
- char str[strlen(contentstr) + 3]; // 2 for quotes, 1 for \0
-
- str[0] = '\"';
- memcpy(str + 1, contentstr, strlen(contentstr));
- str[strlen(contentstr) + 1] = '\"';
- str[strlen(contentstr) + 2] = '\0';
-
- return DetectContentParse(spm_global_thread_ctx, str);
+ return DetectContentParse(spm_global_thread_ctx, contentstr);
}
/**
cd = DetectContentParse(de_ctx->spm_global_thread_ctx, contentstr);
if (cd == NULL)
goto error;
+ if (s->init_data->negated == true) {
+ cd->flags |= DETECT_CONTENT_NEGATED;
+ }
+
DetectContentPrint(cd);
int sm_list = s->init_data->list;
{
int result = 1;
DetectContentData *cd = NULL;
- char *teststring = "\"abc\\:def\"";
- char *teststringparsed = "abc:def";
+ const char *teststring = "abc\\:def";
+ const char *teststringparsed = "abc:def";
uint16_t spm_matcher = SinglePatternMatchDefaultMatcher();
SpmGlobalThreadCtx *spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher);
{
int result = 1;
DetectContentData *cd = NULL;
- char *teststring = "\"abc\\;def\"";
- char *teststringparsed = "abc;def";
+ const char *teststring = "abc\\;def";
+ const char *teststringparsed = "abc;def";
uint16_t spm_matcher = SinglePatternMatchDefaultMatcher();
SpmGlobalThreadCtx *spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher);
{
int result = 1;
DetectContentData *cd = NULL;
- char *teststring = "\"abc\\\"def\"";
- char *teststringparsed = "abc\"def";
+ const char *teststring = "abc\\\"def";
+ const char *teststringparsed = "abc\"def";
uint16_t spm_matcher = SinglePatternMatchDefaultMatcher();
SpmGlobalThreadCtx *spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher);
{
int result = 1;
DetectContentData *cd = NULL;
- char *teststring = "\"abc\\\\def\"";
- char *teststringparsed = "abc\\def";
+ const char *teststring = "abc\\\\def";
+ const char *teststringparsed = "abc\\def";
uint16_t spm_matcher = SinglePatternMatchDefaultMatcher();
SpmGlobalThreadCtx *spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher);
{
int result = 1;
DetectContentData *cd = NULL;
- char *teststring = "\"abc\\def\"";
+ const char *teststring = "abc\\def";
uint16_t spm_matcher = SinglePatternMatchDefaultMatcher();
SpmGlobalThreadCtx *spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher);
{
int result = 1;
DetectContentData *cd = NULL;
- char *teststring = "\"a|42|c|44|e|46|\"";
- char *teststringparsed = "abcdef";
+ const char *teststring = "a|42|c|44|e|46|";
+ const char *teststringparsed = "abcdef";
uint16_t spm_matcher = SinglePatternMatchDefaultMatcher();
SpmGlobalThreadCtx *spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher);
{
int result = 1;
DetectContentData *cd = NULL;
- char *teststring = "\"\"";
+ const char *teststring = "";
uint16_t spm_matcher = SinglePatternMatchDefaultMatcher();
SpmGlobalThreadCtx *spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher);
{
int result = 1;
DetectContentData *cd = NULL;
- char *teststring = "\"\"";
+ const char *teststring = "";
uint16_t spm_matcher = SinglePatternMatchDefaultMatcher();
SpmGlobalThreadCtx *spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher);
static int DetectContentParseTest09(void)
{
- int result = 0;
- DetectContentData *cd = NULL;
- char *teststring = "!\"boo\"";
-
- uint16_t spm_matcher = SinglePatternMatchDefaultMatcher();
- SpmGlobalThreadCtx *spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher);
- FAIL_IF(spm_global_thread_ctx == NULL);
-
- cd = DetectContentParse(spm_global_thread_ctx, teststring);
- if (cd != NULL) {
- if (cd->flags & DETECT_CONTENT_NEGATED)
- result = 1;
-
- DetectContentFree(cd);
- }
- SpmDestroyGlobalThreadCtx(spm_global_thread_ctx);
- return result;
-}
-
-static int DetectContentParseTest10(void)
-{
- int result = 0;
- DetectContentData *cd = NULL;
- char *teststring = "!\"boo\"";
-
- uint16_t spm_matcher = SinglePatternMatchDefaultMatcher();
- SpmGlobalThreadCtx *spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher);
- FAIL_IF(spm_global_thread_ctx == NULL);
-
- cd = DetectContentParse(spm_global_thread_ctx, teststring);
- if (cd != NULL) {
- if (cd->flags & DETECT_CONTENT_NEGATED)
- result = 1;
-
- DetectContentFree(cd);
- }
- SpmDestroyGlobalThreadCtx(spm_global_thread_ctx);
- return result;
-}
-
-static int DetectContentParseNegTest11(void)
-{
- int result = 0;
- DetectContentData *cd = NULL;
- char *teststring = "\"boo\"";
-
- uint16_t spm_matcher = SinglePatternMatchDefaultMatcher();
- SpmGlobalThreadCtx *spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher);
- FAIL_IF(spm_global_thread_ctx == NULL);
-
- cd = DetectContentParse(spm_global_thread_ctx, teststring);
- if (cd != NULL) {
- if (!(cd->flags & DETECT_CONTENT_NEGATED))
- result = 1;
-
- DetectContentFree(cd);
- }
- SpmDestroyGlobalThreadCtx(spm_global_thread_ctx);
- return result;
-}
-
-static int DetectContentParseNegTest12(void)
-{
- int result = 0;
- DetectContentData *cd = NULL;
- char *teststring = "\"boo\"";
-
- uint16_t spm_matcher = SinglePatternMatchDefaultMatcher();
- SpmGlobalThreadCtx *spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher);
- FAIL_IF(spm_global_thread_ctx == NULL);
-
- cd = DetectContentParse(spm_global_thread_ctx, teststring);
- if (cd != NULL) {
- if (!(cd->flags & DETECT_CONTENT_NEGATED))
- result = 1;
-
- DetectContentFree(cd);
- }
- SpmDestroyGlobalThreadCtx(spm_global_thread_ctx);
- return result;
-}
-
-static int DetectContentParseNegTest13(void)
-{
- int result = 0;
- DetectContentData *cd = NULL;
- char *teststring = "!\"boo\"";
-
- uint16_t spm_matcher = SinglePatternMatchDefaultMatcher();
- SpmGlobalThreadCtx *spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher);
- FAIL_IF(spm_global_thread_ctx == NULL);
-
- cd = DetectContentParse(spm_global_thread_ctx, teststring);
- if (cd != NULL) {
- if (cd->flags & DETECT_CONTENT_NEGATED)
- result = 1;
-
- DetectContentFree(cd);
- }
- SpmDestroyGlobalThreadCtx(spm_global_thread_ctx);
- return result;
-}
-
-static int DetectContentParseNegTest14(void)
-{
- int result = 0;
DetectContentData *cd = NULL;
- char *teststring = " \"!boo\"";
+ const char *teststring = "boo";
uint16_t spm_matcher = SinglePatternMatchDefaultMatcher();
SpmGlobalThreadCtx *spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher);
FAIL_IF(spm_global_thread_ctx == NULL);
cd = DetectContentParse(spm_global_thread_ctx, teststring);
- if (cd != NULL) {
- if (!(cd->flags & DETECT_CONTENT_NEGATED))
- result = 1;
-
- DetectContentFree(cd);
- }
- SpmDestroyGlobalThreadCtx(spm_global_thread_ctx);
- return result;
-}
-
-static int DetectContentParseNegTest15(void)
-{
- int result = 0;
- DetectContentData *cd = NULL;
- char *teststring = " !\"boo\"";
-
- uint16_t spm_matcher = SinglePatternMatchDefaultMatcher();
- SpmGlobalThreadCtx *spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher);
- FAIL_IF(spm_global_thread_ctx == NULL);
-
- cd = DetectContentParse(spm_global_thread_ctx, teststring);
- if (cd != NULL) {
- if (cd->flags & DETECT_CONTENT_NEGATED)
- result = 1;
-
- DetectContentFree(cd);
- }
- SpmDestroyGlobalThreadCtx(spm_global_thread_ctx);
- return result;
-}
-
-static int DetectContentParseNegTest16(void)
-{
- int result = 0;
- DetectContentData *cd = NULL;
- char *teststring = " \"boo\"";
-
- uint16_t spm_matcher = SinglePatternMatchDefaultMatcher();
- SpmGlobalThreadCtx *spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher);
- FAIL_IF(spm_global_thread_ctx == NULL);
-
- cd = DetectContentParse(spm_global_thread_ctx, teststring);
- if (cd != NULL) {
- result = (cd->content_len == 3 && memcmp(cd->content,"boo",3) == 0);
- DetectContentFree(cd);
- }
+ FAIL_IF_NULL(cd);
+ DetectContentFree(cd);
SpmDestroyGlobalThreadCtx(spm_global_thread_ctx);
- return result;
+ PASS;
}
/**
s->alproto = ALPROTO_DCERPC;
- result &= (DetectContentSetup(de_ctx, s, "\"one\"") == 0);
+ result &= (DetectContentSetup(de_ctx, s, "one") == 0);
result &= (s->sm_lists[g_dce_stub_data_buffer_id] == NULL && s->sm_lists[DETECT_SM_LIST_PMATCH] != NULL);
SigFree(s);
if (s == NULL)
return 0;
- result &= (DetectContentSetup(de_ctx, s, "\"one\"") == 0);
+ result &= (DetectContentSetup(de_ctx, s, "one") == 0);
result &= (s->sm_lists[g_dce_stub_data_buffer_id] == NULL && s->sm_lists[DETECT_SM_LIST_PMATCH] != NULL);
end:
{
int result = 1;
DetectContentData *cd = NULL;
- int patlen = 257;
+ int patlen = 255;
char *teststring = SCMalloc(sizeof(char) * (patlen + 1));
if (unlikely(teststring == NULL))
return 0;
int idx = 0;
- teststring[idx++] = '\"';
- for (int i = 0; i < (patlen - 2); idx++, i++) {
+ for (int i = 0; i < patlen; idx++, i++) {
teststring[idx] = 'a';
}
- teststring[idx++] = '\"';
teststring[idx++] = '\0';
uint16_t spm_matcher = SinglePatternMatchDefaultMatcher();
{
int result = 1;
DetectContentData *cd = NULL;
- int patlen = 258;
+ int patlen = 256;
char *teststring = SCMalloc(sizeof(char) * (patlen + 1));
if (unlikely(teststring == NULL))
return 0;
int idx = 0;
- teststring[idx++] = '\"';
- for (int i = 0; i < (patlen - 2); idx++, i++) {
+ for (int i = 0; i < patlen; idx++, i++) {
teststring[idx] = 'a';
}
- teststring[idx++] = '\"';
teststring[idx++] = '\0';
uint16_t spm_matcher = SinglePatternMatchDefaultMatcher();
{
int result = 1;
DetectContentData *cd = NULL;
- int patlen = 260;
+ int patlen = 258;
char *teststring = SCMalloc(sizeof(char) * (patlen + 1));
if (unlikely(teststring == NULL))
return 0;
int idx = 0;
- teststring[idx++] = '\"';
teststring[idx++] = '|';
teststring[idx++] = '4';
teststring[idx++] = '6';
teststring[idx++] = '|';
- for (int i = 0; i < (patlen - 6); idx++, i++) {
+ for (int i = 0; i < (patlen - 4); idx++, i++) {
teststring[idx] = 'a';
}
- teststring[idx++] = '\"';
teststring[idx++] = '\0';
uint16_t spm_matcher = SinglePatternMatchDefaultMatcher();
{
int result = 1;
DetectContentData *cd = NULL;
- int patlen = 261;
+ int patlen = 259;
char *teststring = SCMalloc(sizeof(char) * (patlen + 1));
if (unlikely(teststring == NULL))
return 0;
int idx = 0;
- teststring[idx++] = '\"';
teststring[idx++] = '|';
teststring[idx++] = '4';
teststring[idx++] = '6';
teststring[idx++] = '|';
- for (int i = 0; i < (patlen - 6); idx++, i++) {
+ for (int i = 0; i < (patlen - 4); idx++, i++) {
teststring[idx] = 'a';
}
- teststring[idx++] = '\"';
teststring[idx++] = '\0';
uint16_t spm_matcher = SinglePatternMatchDefaultMatcher();
UtRegisterTest("DetectContentParseTest07", DetectContentParseTest07);
UtRegisterTest("DetectContentParseTest08", DetectContentParseTest08);
UtRegisterTest("DetectContentParseTest09", DetectContentParseTest09);
- UtRegisterTest("DetectContentParseTest10", DetectContentParseTest10);
- UtRegisterTest("DetectContentParseNegTest11", DetectContentParseNegTest11);
- UtRegisterTest("DetectContentParseNegTest12", DetectContentParseNegTest12);
- UtRegisterTest("DetectContentParseNegTest13", DetectContentParseNegTest13);
- UtRegisterTest("DetectContentParseNegTest14", DetectContentParseNegTest14);
- UtRegisterTest("DetectContentParseNegTest15", DetectContentParseNegTest15);
- UtRegisterTest("DetectContentParseNegTest16", DetectContentParseNegTest16);
UtRegisterTest("DetectContentParseTest17", DetectContentParseTest17);
UtRegisterTest("DetectContentParseTest18", DetectContentParseTest18);
UtRegisterTest("DetectContentParseTest19", DetectContentParseTest19);
void DetectContentRegister (void);
uint32_t DetectContentMaxId(DetectEngineCtx *);
DetectContentData *DetectContentParse(SpmGlobalThreadCtx *spm_global_thread_ctx,
- char *contentstr);
+ const char *contentstr);
int DetectContentDataParse(const char *keyword, const char *contentstr,
- uint8_t **pstr, uint16_t *plen, uint32_t *flags);
+ uint8_t **pstr, uint16_t *plen);
DetectContentData *DetectContentParseEncloseQuotes(SpmGlobalThreadCtx *spm_global_thread_ctx,
- char *contentstr);
+ const char *contentstr);
int DetectContentSetup(DetectEngineCtx *de_ctx, Signature *s, char *contentstr);
void DetectContentPrint(DetectContentData *);
sigmatch_table[DETECT_FILEEXT].Setup = DetectFileextSetup;
sigmatch_table[DETECT_FILEEXT].Free = DetectFileextFree;
sigmatch_table[DETECT_FILEEXT].RegisterTests = DetectFileextRegisterTests;
+ sigmatch_table[DETECT_FILEEXT].flags = SIGMATCH_QUOTES_OPTIONAL|SIGMATCH_HANDLE_NEGATION;
g_file_match_list_id = DetectBufferTypeRegister("files");
* \retval pointer to DetectFileextData on success
* \retval NULL on failure
*/
-static DetectFileextData *DetectFileextParse (char *str)
+static DetectFileextData *DetectFileextParse (const char *str, bool negate)
{
DetectFileextData *fileext = NULL;
memset(fileext, 0x00, sizeof(DetectFileextData));
- if (DetectContentDataParse("fileext", str, &fileext->ext, &fileext->len, &fileext->flags) == -1) {
+ if (DetectContentDataParse("fileext", str, &fileext->ext, &fileext->len) == -1) {
goto error;
}
uint16_t u;
for (u = 0; u < fileext->len; u++)
fileext->ext[u] = tolower(fileext->ext[u]);
+ if (negate) {
+ fileext->flags |= DETECT_CONTENT_NEGATED;
+ }
+
SCLogDebug("flags %02X", fileext->flags);
if (fileext->flags & DETECT_CONTENT_NEGATED) {
SCLogDebug("negated fileext");
DetectFileextData *fileext= NULL;
SigMatch *sm = NULL;
- fileext = DetectFileextParse(str);
+ fileext = DetectFileextParse(str, s->init_data->negated);
if (fileext == NULL)
goto error;
/**
* \test DetectFileextTestParse01
*/
-int DetectFileextTestParse01 (void)
+static int DetectFileextTestParse01 (void)
{
- DetectFileextData *dfd = DetectFileextParse("\"doc\"");
+ DetectFileextData *dfd = DetectFileextParse("doc", false);
if (dfd != NULL) {
DetectFileextFree(dfd);
return 1;
/**
* \test DetectFileextTestParse02
*/
-int DetectFileextTestParse02 (void)
+static int DetectFileextTestParse02 (void)
{
int result = 0;
- DetectFileextData *dfd = DetectFileextParse("\"tar.gz\"");
+ DetectFileextData *dfd = DetectFileextParse("tar.gz", false);
if (dfd != NULL) {
if (dfd->len == 6 && memcmp(dfd->ext, "tar.gz", 6) == 0) {
result = 1;
/**
* \test DetectFileextTestParse03
*/
-int DetectFileextTestParse03 (void)
+static int DetectFileextTestParse03 (void)
{
int result = 0;
- DetectFileextData *dfd = DetectFileextParse("\"pdf\"");
+ DetectFileextData *dfd = DetectFileextParse("pdf", false);
if (dfd != NULL) {
if (dfd->len == 3 && memcmp(dfd->ext, "pdf", 3) == 0) {
result = 1;
sigmatch_table[DETECT_FILEMAGIC].desc = "match on the information libmagic returns about a file";
sigmatch_table[DETECT_FILEMAGIC].url = "https://redmine.openinfosecfoundation.org/projects/suricata/wiki/File-keywords#filemagic";
sigmatch_table[DETECT_FILEMAGIC].Setup = DetectFilemagicSetupNoSupport;
+ sigmatch_table[DETECT_FILEMAGIC].flags = SIGMATCH_QUOTES_MANDATORY|SIGMATCH_HANDLE_NEGATION;
}
#else /* HAVE_MAGIC */
sigmatch_table[DETECT_FILEMAGIC].Setup = DetectFilemagicSetup;
sigmatch_table[DETECT_FILEMAGIC].Free = DetectFilemagicFree;
sigmatch_table[DETECT_FILEMAGIC].RegisterTests = DetectFilemagicRegisterTests;
+ sigmatch_table[DETECT_FILEMAGIC].flags = SIGMATCH_QUOTES_MANDATORY|SIGMATCH_HANDLE_NEGATION;
g_file_match_list_id = DetectBufferTypeRegister("files");
* \retval filemagic pointer to DetectFilemagicData on success
* \retval NULL on failure
*/
-static DetectFilemagicData *DetectFilemagicParse (char *str)
+static DetectFilemagicData *DetectFilemagicParse (const char *str, bool negate)
{
DetectFilemagicData *filemagic = NULL;
memset(filemagic, 0x00, sizeof(DetectFilemagicData));
- if (DetectContentDataParse ("filemagic", str, &filemagic->name, &filemagic->len, &filemagic->flags) == -1) {
+ if (DetectContentDataParse ("filemagic", str, &filemagic->name, &filemagic->len) == -1) {
goto error;
}
goto error;
}
+ if (negate) {
+ filemagic->flags |= DETECT_CONTENT_NEGATED;
+ }
+
SCLogDebug("flags %02X", filemagic->flags);
if (filemagic->flags & DETECT_CONTENT_NEGATED) {
SCLogDebug("negated filemagic");
DetectFilemagicData *filemagic = NULL;
SigMatch *sm = NULL;
- filemagic = DetectFilemagicParse(str);
+ filemagic = DetectFilemagicParse(str, s->init_data->negated);
if (filemagic == NULL)
goto error;
/**
* \test DetectFilemagicTestParse01
*/
-int DetectFilemagicTestParse01 (void)
+static int DetectFilemagicTestParse01 (void)
{
- DetectFilemagicData *dnd = DetectFilemagicParse("\"secret.pdf\"");
+ DetectFilemagicData *dnd = DetectFilemagicParse("secret.pdf", false);
if (dnd != NULL) {
DetectFilemagicFree(dnd);
return 1;
/**
* \test DetectFilemagicTestParse02
*/
-int DetectFilemagicTestParse02 (void)
+static int DetectFilemagicTestParse02 (void)
{
int result = 0;
- DetectFilemagicData *dnd = DetectFilemagicParse("\"backup.tar.gz\"");
+ DetectFilemagicData *dnd = DetectFilemagicParse("backup.tar.gz", false);
if (dnd != NULL) {
if (dnd->len == 13 && memcmp(dnd->name, "backup.tar.gz", 13) == 0) {
result = 1;
/**
* \test DetectFilemagicTestParse03
*/
-int DetectFilemagicTestParse03 (void)
+static int DetectFilemagicTestParse03 (void)
{
int result = 0;
- DetectFilemagicData *dnd = DetectFilemagicParse("\"cmd.exe\"");
+ DetectFilemagicData *dnd = DetectFilemagicParse("cmd.exe", false);
if (dnd != NULL) {
if (dnd->len == 7 && memcmp(dnd->name, "cmd.exe", 7) == 0) {
result = 1;
sigmatch_table[DETECT_FILENAME].Setup = DetectFilenameSetup;
sigmatch_table[DETECT_FILENAME].Free = DetectFilenameFree;
sigmatch_table[DETECT_FILENAME].RegisterTests = DetectFilenameRegisterTests;
+ sigmatch_table[DETECT_FILENAME].flags = SIGMATCH_QUOTES_OPTIONAL|SIGMATCH_HANDLE_NEGATION;
DetectAppLayerInspectEngineRegister("files",
ALPROTO_HTTP, SIG_FLAG_TOSERVER, HTP_REQUEST_BODY,
* \retval filename pointer to DetectFilenameData on success
* \retval NULL on failure
*/
-static DetectFilenameData *DetectFilenameParse (char *str)
+static DetectFilenameData *DetectFilenameParse (const char *str, bool negate)
{
DetectFilenameData *filename = NULL;
memset(filename, 0x00, sizeof(DetectFilenameData));
- if (DetectContentDataParse ("filename", str, &filename->name, &filename->len, &filename->flags) == -1) {
+ if (DetectContentDataParse ("filename", str, &filename->name, &filename->len) == -1) {
goto error;
}
goto error;
}
+ if (negate) {
+ filename->flags |= DETECT_CONTENT_NEGATED;
+ }
+
SCLogDebug("flags %02X", filename->flags);
if (filename->flags & DETECT_CONTENT_NEGATED) {
SCLogDebug("negated filename");
DetectFilenameData *filename = NULL;
SigMatch *sm = NULL;
- filename = DetectFilenameParse(str);
+ filename = DetectFilenameParse(str, s->init_data->negated);
if (filename == NULL)
goto error;
/**
* \test DetectFilenameTestParse01
*/
-int DetectFilenameTestParse01 (void)
+static int DetectFilenameTestParse01 (void)
{
- DetectFilenameData *dnd = DetectFilenameParse("\"secret.pdf\"");
+ DetectFilenameData *dnd = DetectFilenameParse("secret.pdf", false);
if (dnd != NULL) {
DetectFilenameFree(dnd);
return 1;
/**
* \test DetectFilenameTestParse02
*/
-int DetectFilenameTestParse02 (void)
+static int DetectFilenameTestParse02 (void)
{
int result = 0;
- DetectFilenameData *dnd = DetectFilenameParse("\"backup.tar.gz\"");
+ DetectFilenameData *dnd = DetectFilenameParse("backup.tar.gz", false);
if (dnd != NULL) {
if (dnd->len == 13 && memcmp(dnd->name, "backup.tar.gz", 13) == 0) {
result = 1;
/**
* \test DetectFilenameTestParse03
*/
-int DetectFilenameTestParse03 (void)
+static int DetectFilenameTestParse03 (void)
{
int result = 0;
- DetectFilenameData *dnd = DetectFilenameParse("\"cmd.exe\"");
+ DetectFilenameData *dnd = DetectFilenameParse("cmd.exe", false);
if (dnd != NULL) {
if (dnd->len == 7 && memcmp(dnd->name, "cmd.exe", 7) == 0) {
result = 1;
const char *str_ptr;
uint8_t *content = NULL;
uint16_t contentlen = 0;
- uint32_t contentflags = 0;
+ uint32_t contentflags = s->init_data->negated ? DETECT_CONTENT_NEGATED : 0;
ret = pcre_exec(parse_regex, parse_regex_study, rawstr, strlen(rawstr), 0, 0, ov, MAX_SUBSTRINGS);
if (ret != 3) {
}
varcontent = (char *)str_ptr;
- res = DetectContentDataParse("flowvar", varcontent, &content, &contentlen, &contentflags);
+ if (strlen(varcontent) >= 2) {
+ if (varcontent[0] == '"')
+ varcontent++;
+ if (varcontent[strlen(varcontent)-1] == '"')
+ varcontent[strlen(varcontent)-1] = '\0';
+ }
+ SCLogDebug("varcontent %s", varcontent);
+
+ res = DetectContentDataParse("flowvar", varcontent, &content, &contentlen);
if (res == -1)
goto error;
sigmatch_table[DETECT_MSG].Setup = DetectMsgSetup;
sigmatch_table[DETECT_MSG].Free = NULL;
sigmatch_table[DETECT_MSG].RegisterTests = DetectMsgRegisterTests;
+ sigmatch_table[DETECT_MSG].flags = SIGMATCH_QUOTES_MANDATORY;
}
static int DetectMsgSetup (DetectEngineCtx *de_ctx, Signature *s, char *msgstr)
{
- char *str = NULL;
- uint16_t len;
- uint16_t pos = 0;
- uint16_t slen = 0;
-
- slen = strlen(msgstr);
+ size_t slen = strlen(msgstr);
if (slen == 0)
- goto error;
-
- /* skip the first spaces */
- while (pos < slen && isspace((unsigned char)msgstr[pos]))
- pos++;
-
- /* Strip leading and trailing "s. */
- if (msgstr[pos] == '\"') {
- str = SCStrdup(msgstr + pos + 1);
- if (unlikely(str == NULL))
- goto error;
- if (strlen(str) && str[strlen(str) - 1] == '\"') {
- str[strlen(str)-1] = '\0';
- }
- } else {
- SCLogError(SC_ERR_INVALID_VALUE, "format error \'%s\'", msgstr);
- goto error;
- }
-
- len = strlen(str);
- if (len == 0)
- goto error;
+ return -1;
+ char input[slen + 1];
+ strlcpy(input, msgstr, slen + 1);
+ char *str = input;
char converted = 0;
{
uint8_t escape = 0;
/* it doesn't matter if we need to escape or not we remove the extra "\" to mimic snort */
- for (i = 0, x = 0; i < len; i++) {
+ for (i = 0, x = 0; i < slen; i++) {
//printf("str[%02u]: %c\n", i, str[i]);
if(!escape && str[i] == '\\') {
escape = 1;
#endif
if (converted) {
- len = x;
- str[len] = '\0';
+ slen = x;
+ str[slen] = '\0';
}
}
- s->msg = SCMalloc(len + 1);
+ s->msg = SCStrdup(str);
if (s->msg == NULL)
goto error;
-
- strlcpy(s->msg, str, len + 1);
-
- SCFree(str);
return 0;
error:
- SCFree(str);
return -1;
}
goto error;
}
}
+ s->init_data->negated = false;
/* Validate double quoting, trimming trailing white space along the way. */
if (strlen(optvalue) > 0) {
size_t ovlen = strlen(optvalue);
- if (ovlen && optvalue[0] == '"') {
+ char *ptr = optvalue;
+
+ /* skip leading whitespace */
+ while (ovlen > 0) {
+ if (!isblank(*ptr))
+ break;
+ ptr++;
+ ovlen--;
+ }
+ if (ovlen == 0) {
+ SCLogError(SC_ERR_INVALID_SIGNATURE, "invalid formatting or malformed option to %s keyword: \'%s\'",
+ optname, optstr);
+ goto error;
+ }
+
+ /* see if value is negated */
+ if ((st->flags & SIGMATCH_HANDLE_NEGATION) && *ptr == '!') {
+ s->init_data->negated = true;
+ ptr++;
+ ovlen--;
+ }
+ /* skip more whitespace */
+ while (ovlen > 0) {
+ if (!isblank(*ptr))
+ break;
+ ptr++;
+ ovlen--;
+ }
+ if (ovlen == 0) {
+ SCLogError(SC_ERR_INVALID_SIGNATURE, "invalid formatting or malformed option to %s keyword: \'%s\'",
+ optname, optstr);
+ goto error;
+ }
+ /* if quoting is mandatory, enforce it */
+ if (st->flags & SIGMATCH_QUOTES_MANDATORY && ovlen && *ptr != '"') {
+ SCLogError(SC_ERR_INVALID_SIGNATURE, "invalid formattingto %s keyword: "
+ "value must be double quoted \'%s\'", optname, optstr);
+ goto error;
+ }
+
+ if ((st->flags & (SIGMATCH_QUOTES_OPTIONAL|SIGMATCH_QUOTES_MANDATORY))
+ && ovlen && *ptr == '"')
+ {
for (; ovlen > 0; ovlen--) {
- if (isblank(optvalue[ovlen - 1])) {
- optvalue[ovlen - 1] = '\0';
+ if (isblank(ptr[ovlen - 1])) {
+ ptr[ovlen - 1] = '\0';
} else {
break;
}
}
- if (ovlen && optvalue[ovlen - 1] != '"') {
+ if (ovlen && ptr[ovlen - 1] != '"') {
SCLogError(SC_ERR_INVALID_SIGNATURE,
"bad option value formatting (possible missing semicolon) "
"for keyword %s: \'%s\'", optname, optvalue);
goto error;
}
+ if (ovlen > 1) {
+ /* strip leading " */
+ ptr++;
+ ovlen--;
+ ptr[ovlen - 1] = '\0';
+ ovlen--;
+ }
+ if (ovlen == 0) {
+ SCLogError(SC_ERR_INVALID_SIGNATURE,
+ "bad input "
+ "for keyword %s: \'%s\'", optname, optvalue);
+ goto error;
+ }
+ } else {
+ if (*ptr == '"') {
+ SCLogError(SC_ERR_INVALID_SIGNATURE, "quotes on %s keyword that doesn't support them: \'%s\'",
+ optname, optstr);
+ goto error;
+ }
+ }
+ /* setup may or may not add a new SigMatch to the list */
+ if (st->Setup(de_ctx, s, ptr) < 0) {
+ SCLogDebug("\"%s\" failed to setup", st->name);
+ goto error;
+ }
+ } else {
+ /* setup may or may not add a new SigMatch to the list */
+ if (st->Setup(de_ctx, s, NULL) < 0) {
+ SCLogDebug("\"%s\" failed to setup", st->name);
+ goto error;
}
}
-
- /* setup may or may not add a new SigMatch to the list */
- if (st->Setup(de_ctx, s, strlen(optvalue) ? optvalue : NULL) < 0) {
- SCLogDebug("\"%s\" failed to setup", st->name);
- goto error;
- }
+ s->init_data->negated = false;
if (ret == 4) {
return 1;
sigmatch_table[DETECT_PCRE].Setup = DetectPcreSetup;
sigmatch_table[DETECT_PCRE].Free = DetectPcreFree;
sigmatch_table[DETECT_PCRE].RegisterTests = DetectPcreRegisterTests;
+ sigmatch_table[DETECT_PCRE].flags = (SIGMATCH_QUOTES_OPTIONAL|SIGMATCH_HANDLE_NEGATION);
intmax_t val = 0;
return 0;
}
-static DetectPcreData *DetectPcreParse (DetectEngineCtx *de_ctx, char *regexstr, int *sm_list,
- char *capture_names, size_t capture_names_size)
+static DetectPcreData *DetectPcreParse (DetectEngineCtx *de_ctx, const char *regexstr, int *sm_list,
+ char *capture_names, size_t capture_names_size, bool negate)
{
int ec;
const char *eb;
int ret = 0, res = 0;
int ov[MAX_SUBSTRINGS];
int check_host_header = 0;
-
char op_str[64] = "";
- uint8_t negate = 0;
-
- while (*regexstr != '\0' && isspace((unsigned char)*regexstr)) {
- regexstr++;
- }
-
- if (*regexstr == '!') {
- negate = 1;
- regexstr++;
- }
int cut_capture = 0;
char *fcap = strstr(regexstr, "flow:");
/** \internal
* \brief check if we need to extract capture settings and set them up if needed
*/
-static int DetectPcreParseCapture(char *regexstr, DetectEngineCtx *de_ctx, DetectPcreData *pd,
+static int DetectPcreParseCapture(const char *regexstr, DetectEngineCtx *de_ctx, DetectPcreData *pd,
char *capture_names)
{
int ret = 0, res = 0;
int ov[MAX_SUBSTRINGS];
memset(&ov, 0, sizeof(ov));
char type_str[16] = "";
- char *orig_right_edge = regexstr + strlen(regexstr);
+ const char *orig_right_edge = regexstr + strlen(regexstr);
char *name_array[DETECT_PCRE_CAPTURE_MAX] = { NULL };
int name_idx = 0;
int capture_cnt = 0;
int parsed_sm_list = DETECT_SM_LIST_NOTSET;
char capture_names[1024] = "";
- pd = DetectPcreParse(de_ctx, regexstr, &parsed_sm_list, capture_names, sizeof(capture_names));
+ pd = DetectPcreParse(de_ctx, regexstr, &parsed_sm_list,
+ capture_names, sizeof(capture_names), s->init_data->negated);
if (pd == NULL)
goto error;
if (DetectPcreParseCapture(regexstr, de_ctx, pd, capture_names) < 0)
{
int result = 1;
DetectPcreData *pd = NULL;
- char *teststring = "/blah/7";
+ const char *teststring = "/blah/7";
int list = DETECT_SM_LIST_NOTSET;
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
FAIL_IF_NULL(de_ctx);
- pd = DetectPcreParse(de_ctx, teststring, &list, NULL, 0);
+ pd = DetectPcreParse(de_ctx, teststring, &list, NULL, 0, false);
FAIL_IF_NOT_NULL(pd);
DetectEngineCtxFree(de_ctx);
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
FAIL_IF_NULL(de_ctx);
- pd = DetectPcreParse(de_ctx, teststring, &list, NULL, 0);
+ pd = DetectPcreParse(de_ctx, teststring, &list, NULL, 0, false);
FAIL_IF_NOT_NULL(pd);
DetectEngineCtxFree(de_ctx);
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
FAIL_IF_NULL(de_ctx);
- pd = DetectPcreParse(de_ctx, teststring, &list, NULL, 0);
+ pd = DetectPcreParse(de_ctx, teststring, &list, NULL, 0, false);
FAIL_IF_NOT_NULL(pd);
DetectEngineCtxFree(de_ctx);
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
FAIL_IF_NULL(de_ctx);
- pd = DetectPcreParse(de_ctx, teststring, &list, NULL, 0);
+ pd = DetectPcreParse(de_ctx, teststring, &list, NULL, 0, false);
FAIL_IF_NULL(pd);
DetectPcreFree(pd);
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
FAIL_IF_NULL(de_ctx);
- pd = DetectPcreParse(de_ctx, teststring, &list, NULL, 0);
+ pd = DetectPcreParse(de_ctx, teststring, &list, NULL, 0, false);
FAIL_IF_NULL(pd);
DetectPcreFree(pd);
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
FAIL_IF_NULL(de_ctx);
- pd = DetectPcreParse(de_ctx, teststring, &list, NULL, 0);
+ pd = DetectPcreParse(de_ctx, teststring, &list, NULL, 0, false);
FAIL_IF_NULL(pd);
DetectPcreFree(pd);
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
FAIL_IF_NULL(de_ctx);
- pd = DetectPcreParse(de_ctx, teststring, &list, NULL, 0);
+ pd = DetectPcreParse(de_ctx, teststring, &list, NULL, 0, false);
FAIL_IF_NULL(pd);
DetectPcreFree(pd);
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
FAIL_IF_NULL(de_ctx);
- pd = DetectPcreParse(de_ctx, teststring, &list, NULL, 0);
+ pd = DetectPcreParse(de_ctx, teststring, &list, NULL, 0, false);
FAIL_IF_NULL(pd);
DetectPcreFree(pd);
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
FAIL_IF_NULL(de_ctx);
- pd = DetectPcreParse(de_ctx, teststring, &list, NULL, 0);
+ pd = DetectPcreParse(de_ctx, teststring, &list, NULL, 0, false);
FAIL_IF_NULL(pd);
DetectPcreFree(pd);
FAIL_IF(de_ctx == NULL);
- pd = DetectPcreParse(de_ctx, "/domain\\.com/W", &list, NULL, 0);
+ pd = DetectPcreParse(de_ctx, "/domain\\.com/W", &list, NULL, 0, false);
FAIL_IF(pd == NULL);
DetectPcreFree(pd);
list = DETECT_SM_LIST_NOTSET;
- pd = DetectPcreParse(de_ctx, "/dOmain\\.com/W", &list, NULL, 0);
+ pd = DetectPcreParse(de_ctx, "/dOmain\\.com/W", &list, NULL, 0, false);
FAIL_IF(pd != NULL);
/* Uppercase meta characters are valid. */
list = DETECT_SM_LIST_NOTSET;
- pd = DetectPcreParse(de_ctx, "/domain\\D+\\.com/W", &list, NULL, 0);
+ pd = DetectPcreParse(de_ctx, "/domain\\D+\\.com/W", &list, NULL, 0, false);
FAIL_IF(pd == NULL);
DetectPcreFree(pd);
/* This should not parse as the first \ escapes the second \, then
* we have a D. */
list = DETECT_SM_LIST_NOTSET;
- pd = DetectPcreParse(de_ctx, "/\\\\Ddomain\\.com/W", &list, NULL, 0);
+ pd = DetectPcreParse(de_ctx, "/\\\\Ddomain\\.com/W", &list, NULL, 0, false);
FAIL_IF(pd != NULL);
DetectEngineCtxFree(de_ctx);
sigmatch_table[DETECT_REPLACE].Setup = DetectReplaceSetup;
sigmatch_table[DETECT_REPLACE].Free = NULL;
sigmatch_table[DETECT_REPLACE].RegisterTests = DetectReplaceRegisterTests;
+ sigmatch_table[DETECT_REPLACE].flags = (SIGMATCH_QUOTES_MANDATORY|SIGMATCH_HANDLE_NEGATION);
}
int DetectReplaceSetup(DetectEngineCtx *de_ctx, Signature *s, char *replacestr)
{
uint8_t *content = NULL;
uint16_t len = 0;
- uint32_t flags = 0;
SigMatch *pm = NULL;
DetectContentData *ud = NULL;
- int ret = DetectContentDataParse("replace", replacestr, &content, &len, &flags);
- if (ret == -1)
- goto error;
-
- if (flags & DETECT_CONTENT_NEGATED) {
+ if (s->init_data->negated) {
SCLogError(SC_ERR_INVALID_VALUE, "Can't negate replacement string: %s",
replacestr);
goto error;
}
+ int ret = DetectContentDataParse("replace", replacestr, &content, &len);
+ if (ret == -1)
+ goto error;
+
switch (run_mode) {
case RUNMODE_NFQ:
case RUNMODE_IPFW:
sigmatch_table[DETECT_AL_SSH_PROTOVERSION].Setup = DetectSshVersionSetup;
sigmatch_table[DETECT_AL_SSH_PROTOVERSION].Free = DetectSshVersionFree;
sigmatch_table[DETECT_AL_SSH_PROTOVERSION].RegisterTests = DetectSshVersionRegisterTests;
+ sigmatch_table[DETECT_AL_SSH_PROTOVERSION].flags = SIGMATCH_QUOTES_OPTIONAL;
DetectSetupParseRegexes(PARSE_REGEX, &parse_regex, &parse_regex_study);
sigmatch_table[DETECT_AL_SSH_SOFTWAREVERSION].Setup = DetectSshSoftwareVersionSetup;
sigmatch_table[DETECT_AL_SSH_SOFTWAREVERSION].Free = DetectSshSoftwareVersionFree;
sigmatch_table[DETECT_AL_SSH_SOFTWAREVERSION].RegisterTests = DetectSshSoftwareVersionRegisterTests;
+ sigmatch_table[DETECT_AL_SSH_SOFTWAREVERSION].flags = SIGMATCH_QUOTES_OPTIONAL;
DetectSetupParseRegexes(PARSE_REGEX, &parse_regex, &parse_regex_study);
* \brief Regex for parsing "id" option, matching number or "number"
*/
-#define PARSE_REGEX "^\\s*(\\!*)\\s*([A-z0-9\\s\\-\\.=,\\*@]+|\"[A-z0-9\\s\\-\\.=,\\*@]+\")\\s*$"
-#define PARSE_REGEX_FINGERPRINT "^\\s*(\\!*)\\s*([A-z0-9\\:\\*]+|\"[A-z0-9\\:\\* ]+\")\\s*$"
+#define PARSE_REGEX "^([A-z0-9\\s\\-\\.=,\\*@]+|\"[A-z0-9\\s\\-\\.=,\\*@]+\")\\s*$"
+#define PARSE_REGEX_FINGERPRINT "^([A-z0-9\\:\\*]+|\"[A-z0-9\\:\\* ]+\")\\s*$"
static pcre *subject_parse_regex;
static pcre_extra *subject_parse_regex_study;
sigmatch_table[DETECT_AL_TLS_SUBJECT].Setup = DetectTlsSubjectSetup;
sigmatch_table[DETECT_AL_TLS_SUBJECT].Free = DetectTlsSubjectFree;
sigmatch_table[DETECT_AL_TLS_SUBJECT].RegisterTests = DetectTlsSubjectRegisterTests;
+ sigmatch_table[DETECT_AL_TLS_SUBJECT].flags = SIGMATCH_QUOTES_MANDATORY|SIGMATCH_HANDLE_NEGATION;
sigmatch_table[DETECT_AL_TLS_ISSUERDN].name = "tls.issuerdn";
sigmatch_table[DETECT_AL_TLS_ISSUERDN].desc = "match TLS/SSL certificate IssuerDN field";
sigmatch_table[DETECT_AL_TLS_ISSUERDN].Setup = DetectTlsIssuerDNSetup;
sigmatch_table[DETECT_AL_TLS_ISSUERDN].Free = DetectTlsIssuerDNFree;
sigmatch_table[DETECT_AL_TLS_ISSUERDN].RegisterTests = DetectTlsIssuerDNRegisterTests;
+ sigmatch_table[DETECT_AL_TLS_ISSUERDN].flags = SIGMATCH_QUOTES_MANDATORY|SIGMATCH_HANDLE_NEGATION;
sigmatch_table[DETECT_AL_TLS_FINGERPRINT].name = "tls.fingerprint";
sigmatch_table[DETECT_AL_TLS_FINGERPRINT].desc = "match TLS/SSL certificate SHA1 fingerprint";
sigmatch_table[DETECT_AL_TLS_FINGERPRINT].Setup = DetectTlsFingerprintSetup;
sigmatch_table[DETECT_AL_TLS_FINGERPRINT].Free = DetectTlsFingerprintFree;
sigmatch_table[DETECT_AL_TLS_FINGERPRINT].RegisterTests = NULL;
+ sigmatch_table[DETECT_AL_TLS_FINGERPRINT].flags = SIGMATCH_QUOTES_MANDATORY|SIGMATCH_HANDLE_NEGATION;
sigmatch_table[DETECT_AL_TLS_STORE].name = "tls_store";
sigmatch_table[DETECT_AL_TLS_STORE].alias = "tls.store";
* \retval id_d pointer to DetectTlsData on success
* \retval NULL on failure
*/
-static DetectTlsData *DetectTlsSubjectParse (char *str)
+static DetectTlsData *DetectTlsSubjectParse (const char *str, bool negate)
{
DetectTlsData *tls = NULL;
#define MAX_SUBSTRINGS 30
ret = pcre_exec(subject_parse_regex, subject_parse_regex_study, str, strlen(str), 0, 0,
ov, MAX_SUBSTRINGS);
- if (ret != 3) {
+ if (ret != 2) {
SCLogError(SC_ERR_PCRE_MATCH, "invalid tls.subject option");
goto error;
}
- res = pcre_get_substring((char *)str, ov, MAX_SUBSTRINGS, 1, &str_ptr);
- if (res < 0) {
- SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed");
- goto error;
- }
- if (str_ptr[0] == '!')
+ if (negate)
flag = DETECT_CONTENT_NEGATED;
- pcre_free_substring(str_ptr);
- res = pcre_get_substring((char *)str, ov, MAX_SUBSTRINGS, 2, &str_ptr);
+ res = pcre_get_substring((char *)str, ov, MAX_SUBSTRINGS, 1, &str_ptr);
if (res < 0) {
SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed");
goto error;
if (DetectSignatureSetAppProto(s, ALPROTO_TLS) != 0)
return -1;
- tls = DetectTlsSubjectParse(str);
+ tls = DetectTlsSubjectParse(str, s->init_data->negated);
if (tls == NULL)
goto error;
* \retval id_d pointer to DetectTlsData on success
* \retval NULL on failure
*/
-static DetectTlsData *DetectTlsIssuerDNParse(char *str)
+static DetectTlsData *DetectTlsIssuerDNParse(const char *str, bool negate)
{
DetectTlsData *tls = NULL;
#define MAX_SUBSTRINGS 30
ret = pcre_exec(issuerdn_parse_regex, issuerdn_parse_regex_study, str, strlen(str), 0, 0,
ov, MAX_SUBSTRINGS);
-
- if (ret != 3) {
+ if (ret != 2) {
SCLogError(SC_ERR_PCRE_MATCH, "invalid tls.issuerdn option");
goto error;
}
- res = pcre_get_substring((char *)str, ov, MAX_SUBSTRINGS, 1, &str_ptr);
- if (res < 0) {
- SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed");
- goto error;
- }
- if (str_ptr[0] == '!')
+ if (negate)
flag = DETECT_CONTENT_NEGATED;
- pcre_free_substring(str_ptr);
- res = pcre_get_substring((char *)str, ov, MAX_SUBSTRINGS, 2, &str_ptr);
+ res = pcre_get_substring((char *)str, ov, MAX_SUBSTRINGS, 1, &str_ptr);
if (res < 0) {
SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed");
goto error;
if (DetectSignatureSetAppProto(s, ALPROTO_TLS) != 0)
return -1;
- tls = DetectTlsIssuerDNParse(str);
+ tls = DetectTlsIssuerDNParse(str, s->init_data->negated);
if (tls == NULL)
goto error;
* \retval pointer to DetectTlsData on success
* \retval NULL on failure
*/
-static DetectTlsData *DetectTlsFingerprintParse (char *str)
+static DetectTlsData *DetectTlsFingerprintParse (const char *str, bool negate)
{
DetectTlsData *tls = NULL;
#define MAX_SUBSTRINGS 30
ret = pcre_exec(fingerprint_parse_regex, fingerprint_parse_regex_study, str, strlen(str), 0, 0,
ov, MAX_SUBSTRINGS);
-
- if (ret != 3) {
+ if (ret != 2) {
SCLogError(SC_ERR_PCRE_MATCH, "invalid tls.fingerprint option");
goto error;
}
- res = pcre_get_substring((char *)str, ov, MAX_SUBSTRINGS, 1, &str_ptr);
- if (res < 0) {
- SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed");
- goto error;
- }
- if (str_ptr[0] == '!')
+ if (negate)
flag = DETECT_CONTENT_NEGATED;
- pcre_free_substring(str_ptr);
- res = pcre_get_substring((char *)str, ov, MAX_SUBSTRINGS, 2, &str_ptr);
+ res = pcre_get_substring((char *)str, ov, MAX_SUBSTRINGS, 1, &str_ptr);
if (res < 0) {
SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed");
goto error;
if (DetectSignatureSetAppProto(s, ALPROTO_TLS) != 0)
return -1;
- tls = DetectTlsFingerprintParse(str);
+ tls = DetectTlsFingerprintParse(str, s->init_data->negated);
if (tls == NULL)
goto error;
sigmatch_table[DETECT_URICONTENT].Setup = DetectUricontentSetup;
sigmatch_table[DETECT_URICONTENT].Free = DetectUricontentFree;
sigmatch_table[DETECT_URICONTENT].RegisterTests = DetectUricontentRegisterTests;
+ sigmatch_table[DETECT_URICONTENT].flags = (SIGMATCH_QUOTES_MANDATORY|SIGMATCH_HANDLE_NEGATION);
g_http_uri_buffer_id = DetectBufferTypeRegister("http_uri");
}
/** Number of sigmatches. Used for assigning SigMatch::idx */
uint16_t sm_cnt;
+ /** option was prefixed with '!'. Only set for sigmatches that
+ * have the SIGMATCH_HANDLE_NEGATION flag set. */
+ bool negated;
+
/* used to hold flags that are used during init */
uint32_t init_flags;
/* coccinelle: SignatureInitData:init_flags:SIG_FLAG_INIT_ */
#define SIGMATCH_NOT_BUILT (1 << 3)
/** sigmatch may have options, so the parser should be ready to
* deal with both cases */
-#define SIGMATCH_OPTIONAL_OPT (1 << 4)
+#define SIGMATCH_OPTIONAL_OPT (1 << 4)
+/** input may be wrapped in double quotes. They will be stripped before
+ * input data is passed to keyword parser */
+#define SIGMATCH_QUOTES_OPTIONAL (1 << 5)
+/** input MUST be wrapped in double quotes. They will be stripped before
+ * input data is passed to keyword parser. Missing double quotes lead to
+ * error and signature invalidation. */
+#define SIGMATCH_QUOTES_MANDATORY (1 << 6)
+/** negation parsing is handled by the rule parser. Signature::init_data::negated
+ * will be set to true or false prior to calling the keyword parser. Exclamation
+ * mark is stripped from the input to the keyword parser. */
+#define SIGMATCH_HANDLE_NEGATION (1 << 7)
enum DetectEngineTenantSelectors
{