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 )
{
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)
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;
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)
}
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;
}
//-------------------------------------------------------------------------
{
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);
}
free(data_dup);
- ValidateContent(sc, pmd, RULE_OPTION_TYPE_CONTENT);
+ ValidateContent(sc, pmd, otn);
return new ContentOption(pmd, "content");
}