]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
updated fast_pattern* syntax
authorRuss Combs <rucombs@cisco.com>
Thu, 19 Jun 2014 18:22:04 +0000 (14:22 -0400)
committerRuss Combs <rucombs@cisco.com>
Thu, 19 Jun 2014 18:22:04 +0000 (14:22 -0400)
src/ips_options/ips_content.cc

index 9b4ee7762efde965e6a26ba9efbf0f462e5e3d57..573b51dd019ee90823884f619b0d2bc59247836d 100644 (file)
@@ -236,9 +236,10 @@ static void update_pmd(PatternMatchData* pmd)
         pmd->last_check = (PmdLastCheck*)SnortAlloc(get_instance_max() * sizeof(*pmd->last_check));
 }
 
-static int HasFastPattern(OptTreeNode *otn, int list_type)
+static int FastPatterns(OptTreeNode *otn, int list_type)
 {
     OptFpList* fpl = otn ? otn->opt_func : nullptr;
+    int c = 0;
 
     while ( fpl )
     {
@@ -248,11 +249,11 @@ static int HasFastPattern(OptTreeNode *otn, int list_type)
             PatternMatchData* pmd = opt->get_data();
 
             if ( pmd->fp )
-                return 1;
+                c++;
         }
         fpl = fpl->next;
     }
-    return 0;
+    return c;
 }
 
 static int32_t ParseInt(const char* data, const char* tag)
@@ -274,11 +275,8 @@ static int32_t ParseInt(const char* data, const char* tag)
     return value;
 }
 
-// FIXIT the following comment is no longer true;
-/* Since each content modifier can be parsed as a rule option, do this check
- * after parsing the entire rule in FinalizeContentUniqueness() */
 static void ValidateContent(
-    SnortConfig*, PatternMatchData *pmd, int)
+    SnortConfig*, PatternMatchData *pmd, OptTreeNode* otn)
 {
     if (pmd == NULL)
         return;
@@ -308,6 +306,9 @@ static void ValidateContent(
                 ParseError("Fast pattern only contents cannot be negated.");
         }
     }
+
+    if ( FastPatterns(otn, RULE_OPTION_TYPE_CONTENT) > 1 )
+        ParseError("Only one content per rule may be used for fast pattern matching.");
 }
 
 static void make_precomp(PatternMatchData * idx)
@@ -717,82 +718,68 @@ static void PayloadSearchNocase(
 }
 
 static void PayloadSearchFastPattern(
-    PatternMatchData* pmd, char *data, OptTreeNode *otn)
+    PatternMatchData* pmd, char *data, OptTreeNode*)
 {
-    /* There can only be one fast pattern content in the rule, whether
-     * normal, http or other */
-    if (pmd->fp)
-    {
-        ParseError("Cannot set fast_pattern modifier more than once "
-                "for the same \"content\".");
-    }
+    if ( data )
+        ParseError("'fast_pattern' does not take an argument");
 
-    if (HasFastPattern(otn, RULE_OPTION_TYPE_CONTENT))
-        ParseError("Can only use the fast_pattern modifier once in a rule.");
+    pmd->fp = 1;
+}
+
+static void PayloadSearchFastPatternOnly(
+    PatternMatchData* pmd, char *data, OptTreeNode*)
+{
+    if ( data )
+        ParseError("'fast_pattern_only' does not take an argument");
 
     pmd->fp = 1;
+    pmd->fp_only = 1;
+}
 
-    if (data != NULL)
-    {
-        const char *error_str = "Rule option \"fast_pattern\": Invalid parameter: "
-            "\"%s\".  Valid parameters are: \"only\" | <offset>,<length>.  "
-            "Offset and length must be integers less than 65536, offset cannot "
-            "be negative, length must be positive and (offset + length) must "
-            "evaluate to less than or equal to the actual pattern length.  "
-            "Pattern length: %u";
-
-        if (isdigit((int)*data))
-        {
-            /* Specifying offset and length of pattern to use for
-             * fast pattern matcher */
+static void PayloadSearchFastPatternOffset(
+    PatternMatchData* pmd, char *data, OptTreeNode*)
+{
+    if (data == NULL)
+        ParseError("Missing argument to 'fast_pattern_offset' option");
 
-            long int offset, length;
-            char *endptr;
-            char **toks;
-            int num_toks;
+    long offset = ParseInt(data, "fast_pattern_offset");
 
-            toks = mSplit(data, " ", 0, &num_toks, 0);
-            if (num_toks != 2)
-            {
-                mSplitFree(&toks, num_toks);
-                ParseError(error_str, data, pmd->pattern_size);
-            }
+    static const char* error_str = 
+        "fast_pattern_offset must be non-negative and fast_pattern_offset + "
+        "fast_pattern_length must be less than or equal to the actual pattern "
+        "length which is %u.";
 
-            offset = SnortStrtol(toks[0], &endptr, 0);
-            if ((errno == ERANGE) || (*endptr != '\0')
-                    || (offset < 0) || (offset > UINT16_MAX))
-            {
-                mSplitFree(&toks, num_toks);
-                ParseError(error_str, data, pmd->pattern_size);
-            }
+    if ( (offset < 0) || (offset > UINT16_MAX))
+        ParseError(error_str, data, pmd->pattern_size);
 
-            length = SnortStrtol(toks[1], &endptr, 0);
-            if ((errno == ERANGE) || (*endptr != '\0')
-                    || (length <= 0) || (length > UINT16_MAX))
-            {
-                mSplitFree(&toks, num_toks);
-                ParseError(error_str, data, pmd->pattern_size);
-            }
+    if ((int)pmd->pattern_size < (offset + pmd->fp_length))
+        ParseError(error_str, data, pmd->pattern_size);
 
-            mSplitFree(&toks, num_toks);
+    pmd->fp_offset = offset;
+    pmd->fp = 1;
+}
 
-            if ((int)pmd->pattern_size < (offset + length))
-                ParseError(error_str, data, pmd->pattern_size);
+static void PayloadSearchFastPatternLength(
+    PatternMatchData* pmd, char *data, OptTreeNode*)
+{
+    if (data == NULL)
+        ParseError("Missing argument to 'fast_pattern_length' option");
 
-            pmd->fp_offset = (uint16_t)offset;
-            pmd->fp_length = (uint16_t)length;
-        }
-        else
-        {
-            /* Specifies that this content should only be used for
-             * fast pattern matching */
+    long length = ParseInt(data, "fast_pattern_length");
 
-            if (strcasecmp(data, PM_FP_ONLY) != 0)
-                ParseError(error_str, data, pmd->pattern_size);
+    const char* error_str = 
+        "fast_pattern_length must be positive and fast_pattern_offset + "
+        "fast_pattern_length must be less than or equal to the actual pattern "
+        "length which is %u.";
 
-            pmd->fp_only = 1;
-        }
-    }
+    if ( (length < 0) || (length > UINT16_MAX))
+        ParseError(error_str, data, pmd->pattern_size);
+
+    if ((int)pmd->pattern_size < (pmd->fp_offset + length))
+        ParseError(error_str, data, pmd->pattern_size);
+
+    pmd->fp_length = length;
+    pmd->fp = 1;
 }
 
 //-------------------------------------------------------------------------
@@ -1139,6 +1126,18 @@ static IpsOption* content_ctor(
         {
             PayloadSearchFastPattern(pmd, opt1, otn);
         }
+        else if (!strcasecmp(opts[0], "fast_pattern_only"))
+        {
+            PayloadSearchFastPatternOnly(pmd, opt1, otn);
+        }
+        else if (!strcasecmp(opts[0], "fast_pattern_offset"))
+        {
+            PayloadSearchFastPatternOffset(pmd, opt1, otn);
+        }
+        else if (!strcasecmp(opts[0], "fast_pattern_length"))
+        {
+            PayloadSearchFastPatternLength(pmd, opt1, otn);
+        }
         else if (!strcasecmp(opts[0], "distance"))
         {
             PayloadSearchDistance(pmd, opt1, otn);
@@ -1155,7 +1154,7 @@ static IpsOption* content_ctor(
     }
 
     free(data_dup);
-    ValidateContent(sc, pmd, RULE_OPTION_TYPE_CONTENT);
+    ValidateContent(sc, pmd, otn);
 
     return new ContentOption(pmd, "content");
 }