]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
detect-parse: improve common parser 2683/head
authorVictor Julien <victor@inliniac.net>
Mon, 1 May 2017 18:34:07 +0000 (20:34 +0200)
committerVictor Julien <victor@inliniac.net>
Tue, 2 May 2017 09:23:35 +0000 (11:23 +0200)
In preparation of turning input to keyword parsers to const add
options to the common rule parser to enforce and strip double
quotes and parse negation support.

At registration, the keyword can register 3 extra flags:

    SIGMATCH_QUOTES_MANDATORY: value to keyword must be quoted

    SIGMATCH_QUOTES_OPTIONAL: value to keyword may be quoted

    SIGMATCH_HANDLE_NEGATION: leading ! is parsed

In all cases leading spaces are removed. If the 'quote' flags are
set, the quotes are removed from the input as well.

15 files changed:
src/detect-content.c
src/detect-content.h
src/detect-fileext.c
src/detect-filemagic.c
src/detect-filename.c
src/detect-flowvar.c
src/detect-msg.c
src/detect-parse.c
src/detect-pcre.c
src/detect-replace.c
src/detect-ssh-proto-version.c
src/detect-ssh-software-version.c
src/detect-tls.c
src/detect-uricontent.c
src/detect.h

index 64904b0168f37541d66fe06623792e83f7e1f093..687360a622575669d61c0503eb33f66ed88d5ce1 100644 (file)
@@ -59,6 +59,7 @@ void DetectContentRegister (void)
     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);
 }
 
 /**
@@ -73,48 +74,20 @@ void DetectContentRegister (void)
  *  \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;
@@ -127,7 +100,7 @@ int DetectContentDataParse(const char *keyword, const char *contentstr,
         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++;
@@ -199,17 +172,22 @@ int DetectContentDataParse(const char *keyword, const char *contentstr,
         }
 
         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;
 }
 /**
@@ -217,15 +195,14 @@ error:
  * \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;
     }
@@ -238,9 +215,6 @@ DetectContentData *DetectContentParse(SpmGlobalThreadCtx *spm_global_thread_ctx,
 
     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;
@@ -265,16 +239,9 @@ DetectContentData *DetectContentParse(SpmGlobalThreadCtx *spm_global_thread_ctx,
 }
 
 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);
 }
 
 /**
@@ -381,6 +348,10 @@ int DetectContentSetup(DetectEngineCtx *de_ctx, Signature *s, char *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;
@@ -432,8 +403,8 @@ static int DetectContentParseTest01 (void)
 {
     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);
@@ -463,8 +434,8 @@ static int DetectContentParseTest02 (void)
 {
     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);
@@ -494,8 +465,8 @@ static int DetectContentParseTest03 (void)
 {
     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);
@@ -525,8 +496,8 @@ static int DetectContentParseTest04 (void)
 {
     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);
@@ -557,7 +528,7 @@ static int DetectContentParseTest05 (void)
 {
     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);
@@ -582,8 +553,8 @@ static int DetectContentParseTest06 (void)
 {
     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);
@@ -614,7 +585,7 @@ static int DetectContentParseTest07 (void)
 {
     int result = 1;
     DetectContentData *cd = NULL;
-    char *teststring = "\"\"";
+    const char *teststring = "";
 
     uint16_t spm_matcher = SinglePatternMatchDefaultMatcher();
     SpmGlobalThreadCtx *spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher);
@@ -637,7 +608,7 @@ static int DetectContentParseTest08 (void)
 {
     int result = 1;
     DetectContentData *cd = NULL;
-    char *teststring = "\"\"";
+    const char *teststring = "";
 
     uint16_t spm_matcher = SinglePatternMatchDefaultMatcher();
     SpmGlobalThreadCtx *spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher);
@@ -925,168 +896,18 @@ static int DetectContentLongPatternMatchTest11()
 
 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;
 }
 
 /**
@@ -1131,7 +952,7 @@ static int DetectContentParseTest18(void)
 
     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);
@@ -1140,7 +961,7 @@ static int DetectContentParseTest18(void)
     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:
@@ -2164,16 +1985,14 @@ static int DetectContentParseTest41(void)
 {
     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();
@@ -2199,16 +2018,14 @@ static int DetectContentParseTest42(void)
 {
     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();
@@ -2231,20 +2048,18 @@ static int DetectContentParseTest43(void)
 {
     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();
@@ -2270,20 +2085,18 @@ static int DetectContentParseTest44(void)
 {
     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();
@@ -2859,13 +2672,6 @@ static void DetectContentRegisterTests(void)
     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);
index 81bd2a1fa316d00846a8f10908ec5a6c6cb01289..fd217067746deda5c8ecb35dff9eb3e0dedc6802 100644 (file)
@@ -106,11 +106,11 @@ typedef struct DetectContentData_ {
 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 *);
index a052d97d752303e42082bbe31237f74392be866f..5483901c21c4ad769b8d9c208a89c90f2a5735e5 100644 (file)
@@ -70,6 +70,7 @@ void DetectFileextRegister(void)
     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");
 
@@ -139,7 +140,7 @@ static int DetectFileextMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx,
  * \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;
 
@@ -150,13 +151,17 @@ static DetectFileextData *DetectFileextParse (char *str)
 
     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");
@@ -198,7 +203,7 @@ static int DetectFileextSetup (DetectEngineCtx *de_ctx, Signature *s, char *str)
     DetectFileextData *fileext= NULL;
     SigMatch *sm = NULL;
 
-    fileext = DetectFileextParse(str);
+    fileext = DetectFileextParse(str, s->init_data->negated);
     if (fileext == NULL)
         goto error;
 
@@ -245,9 +250,9 @@ static void DetectFileextFree(void *ptr)
 /**
  * \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;
@@ -258,11 +263,11 @@ int DetectFileextTestParse01 (void)
 /**
  * \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;
@@ -277,11 +282,11 @@ int DetectFileextTestParse02 (void)
 /**
  * \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;
index 34f6c6fca0ced6c15e341583a3092e7252252ac9..eeb3805bfc3db7a839ca6c275b2d3b13f0d0b3b0 100644 (file)
@@ -71,6 +71,7 @@ void DetectFilemagicRegister(void)
     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 */
@@ -94,6 +95,7 @@ void DetectFilemagicRegister(void)
     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");
 
@@ -239,7 +241,7 @@ static int DetectFilemagicMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx,
  * \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;
 
@@ -250,7 +252,7 @@ static DetectFilemagicData *DetectFilemagicParse (char *str)
 
     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;
     }
 
@@ -259,6 +261,10 @@ static DetectFilemagicData *DetectFilemagicParse (char *str)
         goto error;
     }
 
+    if (negate) {
+        filemagic->flags |= DETECT_CONTENT_NEGATED;
+    }
+
     SCLogDebug("flags %02X", filemagic->flags);
     if (filemagic->flags & DETECT_CONTENT_NEGATED) {
         SCLogDebug("negated filemagic");
@@ -361,7 +367,7 @@ static int DetectFilemagicSetup (DetectEngineCtx *de_ctx, Signature *s, char *st
     DetectFilemagicData *filemagic = NULL;
     SigMatch *sm = NULL;
 
-    filemagic = DetectFilemagicParse(str);
+    filemagic = DetectFilemagicParse(str, s->init_data->negated);
     if (filemagic == NULL)
         goto error;
 
@@ -416,9 +422,9 @@ static void DetectFilemagicFree(void *ptr)
 /**
  * \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;
@@ -429,11 +435,11 @@ int DetectFilemagicTestParse01 (void)
 /**
  * \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;
@@ -448,11 +454,11 @@ int DetectFilemagicTestParse02 (void)
 /**
  * \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;
index d7ccde6201220892cd68bc6dfda4731041a1b475..840df3a31fdf883dbb3438a0ff3574b598c2a009 100644 (file)
@@ -71,6 +71,7 @@ void DetectFilenameRegister(void)
     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,
@@ -155,7 +156,7 @@ static int DetectFilenameMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx,
  * \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;
 
@@ -166,7 +167,7 @@ static DetectFilenameData *DetectFilenameParse (char *str)
 
     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;
     }
 
@@ -175,6 +176,10 @@ static DetectFilenameData *DetectFilenameParse (char *str)
         goto error;
     }
 
+    if (negate) {
+        filename->flags |= DETECT_CONTENT_NEGATED;
+    }
+
     SCLogDebug("flags %02X", filename->flags);
     if (filename->flags & DETECT_CONTENT_NEGATED) {
         SCLogDebug("negated filename");
@@ -215,7 +220,7 @@ static int DetectFilenameSetup (DetectEngineCtx *de_ctx, Signature *s, char *str
     DetectFilenameData *filename = NULL;
     SigMatch *sm = NULL;
 
-    filename = DetectFilenameParse(str);
+    filename = DetectFilenameParse(str, s->init_data->negated);
     if (filename == NULL)
         goto error;
 
@@ -264,9 +269,9 @@ static void DetectFilenameFree(void *ptr)
 /**
  * \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;
@@ -277,11 +282,11 @@ int DetectFilenameTestParse01 (void)
 /**
  * \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;
@@ -296,11 +301,11 @@ int DetectFilenameTestParse02 (void)
 /**
  * \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;
index bd7ff4038cf68c94ef8ba8f9f8cbd86050cdb362..e7f13b6fdff82f96fc6739084a2267c57bff4788 100644 (file)
@@ -125,7 +125,7 @@ static int DetectFlowvarSetup (DetectEngineCtx *de_ctx, Signature *s, char *raws
     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) {
@@ -147,7 +147,15 @@ static int DetectFlowvarSetup (DetectEngineCtx *de_ctx, Signature *s, char *raws
     }
     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;
 
index 314a2f21b5f2d3e74e58b0ee49c349e4a4305cf2..fb3d2411075b302bd06d23561c3e9a92fadd6aa3 100644 (file)
@@ -45,40 +45,18 @@ void DetectMsgRegister (void)
     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;
 
     {
@@ -86,7 +64,7 @@ static int DetectMsgSetup (DetectEngineCtx *de_ctx, Signature *s, char *msgstr)
         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;
@@ -119,22 +97,17 @@ static int DetectMsgSetup (DetectEngineCtx *de_ctx, Signature *s, char *msgstr)
 #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;
 }
 
index f2d34f36a6dde0e475923f102b81a0ac2fef95a8..6239d5d92c69ef0d1bcc709a7b55cd1e269179cf 100644 (file)
@@ -679,32 +679,100 @@ static int SigParseOptions(DetectEngineCtx *de_ctx, Signature *s, char *optstr,
             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;
index 3d9f4b76f209b5e91d9189f5a3a743bbe27af461..95fce0e8e692559ec306b408552ea4da70428bdc 100644 (file)
@@ -92,6 +92,7 @@ void DetectPcreRegister (void)
     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;
 
@@ -306,8 +307,8 @@ static int DetectPcreHasUpperCase(const char *re)
     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;
@@ -319,18 +320,7 @@ static DetectPcreData *DetectPcreParse (DetectEngineCtx *de_ctx, char *regexstr,
     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:");
@@ -670,14 +660,14 @@ error:
 /** \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;
@@ -811,7 +801,8 @@ static int DetectPcreSetup (DetectEngineCtx *de_ctx, Signature *s, char *regexst
     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)
@@ -906,12 +897,12 @@ static int DetectPcreParseTest01 (void)
 {
     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);
@@ -930,7 +921,7 @@ static int DetectPcreParseTest02 (void)
     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);
@@ -949,7 +940,7 @@ static int DetectPcreParseTest03 (void)
     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);
@@ -968,7 +959,7 @@ static int DetectPcreParseTest04 (void)
     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);
@@ -988,7 +979,7 @@ static int DetectPcreParseTest05 (void)
     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);
@@ -1008,7 +999,7 @@ static int DetectPcreParseTest06 (void)
     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);
@@ -1028,7 +1019,7 @@ static int DetectPcreParseTest07 (void)
     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);
@@ -1048,7 +1039,7 @@ static int DetectPcreParseTest08 (void)
     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);
@@ -1068,7 +1059,7 @@ static int DetectPcreParseTest09 (void)
     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);
@@ -3400,24 +3391,24 @@ static int DetectPcreParseHttpHost(void)
 
     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);
index 17f05615058804c57d23ae8a5c2831bca5431878..e4392f3d644e957b8196e36d370e76da1236522d 100644 (file)
@@ -69,26 +69,26 @@ void DetectReplaceRegister (void)
     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:
index 0099eabdf12e1f88da4411e057b37cf1ef840abb..26ec15113a7f3d565806e925690035de12007c11 100644 (file)
@@ -80,6 +80,7 @@ void DetectSshVersionRegister(void)
     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);
 
index 85d5769271767af4c0c3ef56461f3ef87328d86d..cd1dbfe5dc5dfdfe36d8231e3c1a05f20508bcba 100644 (file)
@@ -94,6 +94,7 @@ void DetectSshSoftwareVersionRegister(void)
     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);
 
index 222e4f9335e048dd418822a94f308bccdab0812e..7e2b2a46bf5bbb0f595f28a68330739a43fdd3a4 100644 (file)
@@ -64,8 +64,8 @@
  * \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;
@@ -122,6 +122,7 @@ void DetectTlsRegister (void)
     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";
@@ -130,6 +131,7 @@ void DetectTlsRegister (void)
     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";
@@ -138,6 +140,7 @@ void DetectTlsRegister (void)
     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";
@@ -228,7 +231,7 @@ static int DetectTlsSubjectMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx,
  * \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
@@ -242,21 +245,15 @@ static DetectTlsData *DetectTlsSubjectParse (char *str)
     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;
@@ -322,7 +319,7 @@ static int DetectTlsSubjectSetup (DetectEngineCtx *de_ctx, Signature *s, char *s
     if (DetectSignatureSetAppProto(s, ALPROTO_TLS) != 0)
         return -1;
 
-    tls = DetectTlsSubjectParse(str);
+    tls = DetectTlsSubjectParse(str, s->init_data->negated);
     if (tls == NULL)
         goto error;
 
@@ -434,7 +431,7 @@ static int DetectTlsIssuerDNMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx
  * \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
@@ -447,22 +444,15 @@ static DetectTlsData *DetectTlsIssuerDNParse(char *str)
 
     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;
@@ -529,7 +519,7 @@ static int DetectTlsIssuerDNSetup (DetectEngineCtx *de_ctx, Signature *s, char *
     if (DetectSignatureSetAppProto(s, ALPROTO_TLS) != 0)
         return -1;
 
-    tls = DetectTlsIssuerDNParse(str);
+    tls = DetectTlsIssuerDNParse(str, s->init_data->negated);
     if (tls == NULL)
         goto error;
 
@@ -574,7 +564,7 @@ static void DetectTlsIssuerDNFree(void *ptr)
  * \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
@@ -587,22 +577,15 @@ static DetectTlsData *DetectTlsFingerprintParse (char *str)
 
     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;
@@ -726,7 +709,7 @@ static int DetectTlsFingerprintSetup (DetectEngineCtx *de_ctx, Signature *s, cha
     if (DetectSignatureSetAppProto(s, ALPROTO_TLS) != 0)
         return -1;
 
-    tls = DetectTlsFingerprintParse(str);
+    tls = DetectTlsFingerprintParse(str, s->init_data->negated);
     if (tls == NULL)
         goto error;
 
index c4518a6515ece9de5468022e424af0574a7e64be..6da1b6a565661c81d8f962c855faa6bbd9cd895c 100644 (file)
@@ -73,6 +73,7 @@ void DetectUricontentRegister (void)
     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");
 }
index 7752d229a8c68c2eafdf45a81909325f524c5313..8f68e22b074f72cd0ae445e0f1715cbdc76db784 100644 (file)
@@ -360,6 +360,10 @@ typedef struct SignatureInitData_ {
     /** 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_ */
@@ -1108,7 +1112,18 @@ typedef struct SigGroupHead_ {
 #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
 {