Hello,
The following patch adds support for unlimited rule size and unlimited
`content' option size (was limited to 2Kb). Please disregard the previous
patch I've sent.
--
/Dmitry <[EMAIL PROTECTED]>
Index: detection-plugins/sp_pattern_match.c
===================================================================
--- detection-plugins/sp_pattern_match.c (revision 13692)
+++ detection-plugins/sp_pattern_match.c (revision 13697)
@@ -1264,16 +1264,15 @@
***************************************************************************/
static void ParsePattern(char *rule, OptTreeNode * otn, int type)
{
- unsigned char tmp_buf[2048];
+ unsigned char *pattern;
/* got enough ptrs for you? */
char *start_ptr;
char *end_ptr;
char *idx;
- char *dummy_idx;
- char *dummy_end;
+ char *pat_end;
char hex_buf[3];
- u_int dummy_size = 0;
+ u_int pat_size = 0;
int size;
int hexmode = 0;
int hexsize = 0;
@@ -1283,9 +1282,6 @@
int exception_flag = 0;
PatternMatchData *ds_idx;
- /* clear out the temp buffer */
- bzero(tmp_buf, 2048);
-
if(rule == NULL)
{
FatalError("%s(%d) => ParsePattern Got Null "
@@ -1338,9 +1334,17 @@
/* set all the pointers to the appropriate places... */
idx = start_ptr;
+ /* allocate memory for the resulting pattern */
+ pattern = malloc((size+1) * sizeof(char));
+ if(pattern == NULL)
+ {
+ FatalError("%s(%d) => could not allocate %d bytes of memory for "
+ "pattern\n", file_name, file_line, size * sizeof(char));
+ }
+ pattern[size] = 0;
+
/* set the indexes into the temp buffer */
- dummy_idx = tmp_buf;
- dummy_end = (dummy_idx + size);
+ pat_end = (pat_end + size);
/* why is this buffer so small? */
bzero(hex_buf, 3);
@@ -1388,8 +1392,8 @@
{
DEBUG_WRAP(DebugMessage(DEBUG_PARSER, "literal set,
Clearing\n"););
literal = 0;
- tmp_buf[dummy_size] = start_ptr[cnt];
- dummy_size++;
+ pattern[pat_size] = start_ptr[cnt];
+ pat_size++;
}
break;
@@ -1406,9 +1410,9 @@
else
{
DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH, "Clearing
literal\n"););
- tmp_buf[dummy_size] = start_ptr[cnt];
+ pattern[pat_size] = start_ptr[cnt];
literal = 0;
- dummy_size++;
+ pat_size++;
}
break;
@@ -1435,21 +1439,12 @@
hex_buf[1] = *idx;
pending--;
- if(dummy_idx < dummy_end)
- {
- tmp_buf[dummy_size] = (u_char)
- strtol(hex_buf, (char **) NULL, 16)&0xFF;
+ pattern[pat_size] = (u_char)
+ strtol(hex_buf, (char **) NULL, 16)&0xFF;
- dummy_size++;
- bzero(hex_buf, 3);
- memset(hex_buf, '0', 2);
- }
- else
- {
- FatalError("ParsePattern() dummy "
- "buffer overflow, make a smaller "
- "pattern please! (Max size = 2048)\n");
- }
+ pat_size++;
+ bzero(hex_buf, 3);
+ memset(hex_buf, '0', 2);
}
}
else
@@ -1469,16 +1464,8 @@
{
if(*idx >= 0x1F && *idx <= 0x7e)
{
- if(dummy_idx < dummy_end)
- {
- tmp_buf[dummy_size] = start_ptr[cnt];
- dummy_size++;
- }
- else
- {
- FatalError("%s(%d)=> ParsePattern() "
- "dummy buffer overflow!\n", file_name,
file_line);
- }
+ pattern[pat_size] = start_ptr[cnt];
+ pat_size++;
if(literal)
{
@@ -1489,8 +1476,8 @@
{
if(literal)
{
- tmp_buf[dummy_size] = start_ptr[cnt];
- dummy_size++;
+ pattern[pat_size] = start_ptr[cnt];
+ pat_size++;
DEBUG_WRAP(DebugMessage(DEBUG_PARSER, "Clearing
literal\n"););
literal = 0;
}
@@ -1506,7 +1493,6 @@
break;
}
- dummy_idx++;
idx++;
cnt++;
}
@@ -1528,15 +1514,22 @@
while(ds_idx->next != NULL)
ds_idx = ds_idx->next;
- if((ds_idx->pattern_buf = (char *) calloc(dummy_size+1, sizeof(char)))
- == NULL)
+ if(size == pat_size)
{
- FatalError("ParsePattern() pattern_buf malloc failed!\n");
+ ds_idx->pattern_buf = pattern;
}
+ else
+ {
+ if((ds_idx->pattern_buf = (char *) malloc((pat_size+1) * sizeof(char)))
+ == NULL)
+ {
+ FatalError("ParsePattern() pattern_buf malloc failed!\n");
+ }
+ memcpy(ds_idx->pattern_buf, pattern, pat_size+1);
+ free(pattern);
+ }
- memcpy(ds_idx->pattern_buf, tmp_buf, dummy_size);
-
- ds_idx->pattern_size = dummy_size;
+ ds_idx->pattern_size = pat_size;
ds_idx->search = uniSearch;
make_precomp(ds_idx);
Index: parser.c
===================================================================
--- parser.c (revision 13692)
+++ parser.c (revision 13697)
@@ -137,13 +137,9 @@
void ParseRulesFile(char *file, int inclevel)
{
FILE *thefp; /* file pointer for the rules file */
- char buf[STD_BUF]; /* file read buffer */
- char *index; /* buffer indexing pointer */
char *stored_file_name = file_name;
int stored_file_line = file_line;
- char *saved_line = NULL;
- int continuation = 0;
- char *new_line = NULL;
+ char *line;
struct stat file_stat; /* for include path testing */
if(inclevel == 0)
@@ -208,83 +204,14 @@
file_name);
}
- /* clear the line buffer */
- bzero((char *) buf, STD_BUF);
-
-
/* loop thru each file line and send it to the rule parser */
- while((fgets(buf, STD_BUF, thefp)) != NULL)
+ while((line = ReadLine(thefp)) != NULL)
{
- /*
- * inc the line counter so the error messages know which line to
- * bitch about
- */
- file_line++;
+ DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,
+ "[*] Processing rule: %s\n", line););
- index = buf;
-
-#ifdef DEBUG2
- LogMessage("Got line %s (%d): %s\n", file_name, file_line, buf);
-#endif
- /* advance through any whitespace at the beginning of the line */
- while(*index == ' ' || *index == '\t')
- index++;
-
- /* if it's not a comment or a <CR>, send it to the parser */
- if((*index != '#') && (*index != 0x0a) && (*index != ';') &&
- (index != NULL))
- {
- if(continuation == 1)
- {
- new_line = (char *) calloc((strlen(saved_line) + strlen(index)
- +1), sizeof(char));
- strncat(new_line, saved_line, strlen(saved_line));
- strncat(new_line, index, strlen(index));
- free(saved_line);
- saved_line = NULL;
- index = new_line;
-
- if(strlen(index) > PARSERULE_SIZE)
- {
- FatalError("Please don't try to overflow the parser, "
- "that's not very nice of you... (%d-byte "
- "limit on rule size)\n", PARSERULE_SIZE);
- }
-
- DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"concat rule: %s\n",
- new_line););
- }
-
- /* check for a '\' continuation character at the end of the line
- * if it's there we need to get the next line in the file
- */
- if(ContinuationCheck(index) == 0)
- {
- DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,
- "[*] Processing rule: %s\n", index););
-
- ParseRule(thefp, index, inclevel);
-
- if(new_line != NULL)
- {
- free(new_line);
- new_line = NULL;
- continuation = 0;
- }
- }
- else
- {
- /* save the current line */
- saved_line = strdup(index);
-
- /* set the flag to let us know the next line is
- * a continuation line
- */
- continuation = 1;
- }
- }
-
- bzero((char *) buf, STD_BUF);
+ ParseRule(thefp, line, inclevel);
+ free(line);
}
if(file_name)
@@ -323,36 +250,6 @@
return;
}
-
-
-int ContinuationCheck(char *rule)
-{
- char *idx; /* indexing var for moving around on the string */
-
- idx = rule + strlen(rule) - 1;
-
- DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"initial idx set to \'%c\'\n",
- *idx););
-
- while(isspace((int)*idx))
- {
- idx--;
- }
-
- if(*idx == '\\')
- {
- DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Got continuation char, "
- "clearing char and returning 1\n"););
-
- /* clear the '\' so there isn't a problem on the appended string */
- *idx = '\x0';
- return 1;
- }
-
- return 0;
-}
-
-
int CheckRule(char *str)
{
int len;
@@ -476,7 +373,7 @@
char **toks; /* dbl ptr for mSplit call, holds rule tokens */
int num_toks; /* holds number of tokens found by mSplit */
int rule_type; /* rule type enumeration variable */
- char rule[PARSERULE_SIZE];
+ char *rule;
int protocol = 0;
char *tmp;
RuleTreeNode proto_node;
@@ -485,11 +382,8 @@
/* chop off the <CR/LF> from the string */
strip(prule);
- /* expand all variables */
- bzero((void *)rule, sizeof(rule));
+ rule = ExpandVars(prule);
- strncpy(rule, ExpandVars(prule), PARSERULE_SIZE-1);
-
/* break out the tokens from the rule string */
toks = mSplit(rule, " ", 10, &num_toks, 0);
@@ -515,7 +409,7 @@
* any drop rules in the configuration file */
if (!InlineMode())
{
- return;
+ goto cleanup;
}
break;
@@ -526,7 +420,7 @@
* any sdrop rules in the configuration file */
if (!InlineMode())
{
- return;
+ goto cleanup;
}
break;
@@ -537,7 +431,7 @@
* any reject rules in the configuration file */
if (!InlineMode())
{
- return;
+ goto cleanup;
}
break;
#endif /* GIDS */
@@ -571,25 +465,25 @@
ParseRulesFile(tmp, inclevel + 1);
mSplitFree(&toks, num_toks);
- return;
+ goto cleanup;
case RULE_VAR:
DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Variable\n"););
VarDefine(toks[1], toks[2]);
mSplitFree(&toks, num_toks);
- return;
+ goto cleanup;
case RULE_PREPROCESS:
DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Preprocessor\n"););
ParsePreprocessor(rule);
mSplitFree(&toks, num_toks);
- return;
+ goto cleanup;
case RULE_OUTPUT:
DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Output Plugin\n"););
ParseOutputPlugin(rule);
mSplitFree(&toks, num_toks);
- return;
+ goto cleanup;
case RULE_ACTIVATE:
DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Activation rule\n"););
@@ -603,25 +497,25 @@
DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Rule file config\n"););
ParseConfig(rule);
mSplitFree(&toks, num_toks);
- return;
+ goto cleanup;
case RULE_DECLARE:
DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Rule type
declaration\n"););
ParseRuleTypeDeclaration(rule_file, rule);
mSplitFree(&toks, num_toks);
- return;
+ goto cleanup;
case RULE_THRESHOLD:
DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Threshold\n"););
ParseSFThreshold(rule_file, rule);
mSplitFree(&toks, num_toks);
- return;
+ goto cleanup;
case RULE_SUPPRESS:
DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Suppress\n"););
ParseSFSuppress(rule_file, rule);
mSplitFree(&toks, num_toks);
- return;
+ goto cleanup;
case RULE_UNKNOWN:
DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Unknown rule type,
might be declared\n"););
@@ -645,7 +539,7 @@
default:
DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Invalid input: %s\n",
prule););
mSplitFree(&toks, num_toks);
- return;
+ goto cleanup;
}
if(num_toks < 7)
@@ -661,7 +555,7 @@
" at the end of the line, make sure there are no\n"
" carriage returns before the end of this line)\n",
file_name, file_line);
- return;
+ goto cleanup;
}
if (rule_type == RULE_UNKNOWN)
@@ -833,6 +727,10 @@
mSplitFree(&toks, num_toks);
+cleanup:
+ if(rule != prule)
+ free(rule);
+
return;
}
@@ -2902,21 +2800,28 @@
***************************************************************************/
char *ExpandVars(char *string)
{
- static char estring[PARSERULE_SIZE];
+ char *line = NULL;
char rawvarname[128], varname[128], varaux[128], varbuffer[128],
varmodifier, *varcontents;
int varname_completed, c, i, j, iv, jv, l_string, name_only;
int quote_toggle = 0;
+ size_t line_len,
+ string_len;
if(!string || !*string || !strchr(string, '$'))
return(string);
- bzero((char *) estring, sizeof(estring));
+ string_len = strlen(string);
+ line_len = string_len + STD_BUF;
+ /* allocate more than the original string.
+ * on variable expansion, increase string_len and make sure that
+ * line_len is always more or equal string_len */
+ line = malloc(line_len + 1);
i = j = 0;
l_string = strlen(string);
DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES, "ExpandVars, Before: %s\n",
string););
- while(i < l_string && j < sizeof(estring) - 1)
+ while(i < l_string)
{
c = string[i++];
@@ -2924,116 +2829,119 @@
{
/* added checks to make sure that we are inside a quoted string
*/
- quote_toggle ^= 1;
+ quote_toggle = !quote_toggle;
+ line[j++] = c;
+ continue;
}
- if(c == '$' && !quote_toggle)
- {
- bzero((char *) rawvarname, sizeof(rawvarname));
- varname_completed = 0;
- name_only = 1;
- iv = i;
- jv = 0;
+ if(c != '$' || quote_toggle)
+ {
+ line[j++] = c;
+ continue;
+ }
- if(string[i] == '(')
- {
- name_only = 0;
- iv = i + 1;
- }
+ bzero((char *) rawvarname, sizeof(rawvarname));
+ varname_completed = 0;
+ name_only = 1;
+ iv = i;
+ jv = 0;
- while(!varname_completed
- && iv < l_string
- && jv < sizeof(rawvarname) - 1)
- {
- c = string[iv++];
+ if(string[i] == '(')
+ {
+ name_only = 0;
+ iv = i + 1;
+ }
- if((name_only && !(isalnum(c) || c == '_'))
- || (!name_only && c == ')'))
- {
- varname_completed = 1;
+ while(!varname_completed
+ && iv < l_string
+ && jv < sizeof(rawvarname) - 1)
+ {
+ c = string[iv++];
- if(name_only)
- iv--;
- }
- else
- {
- rawvarname[jv++] = c;
- }
- }
+ if((name_only && !(isalnum(c) || c == '_'))
+ || (!name_only && c == ')'))
+ {
+ varname_completed = 1;
- if(varname_completed || iv == l_string)
- {
- char *p;
+ if(name_only)
+ iv--;
+ }
+ else
+ {
+ rawvarname[jv++] = c;
+ }
+ }
- i = iv;
+ if(varname_completed || iv == l_string)
+ {
+ char *p;
- varcontents = NULL;
+ i = iv;
- bzero((char *) varname, sizeof(varname));
- bzero((char *) varaux, sizeof(varaux));
- varmodifier = ' ';
+ varcontents = NULL;
- if((p = strchr(rawvarname, ':')))
- {
- strncpy(varname, rawvarname, p - rawvarname);
+ bzero((char *) varname, sizeof(varname));
+ bzero((char *) varaux, sizeof(varaux));
+ varmodifier = ' ';
- if(strlen(p) >= 2)
- {
- varmodifier = *(p + 1);
- strcpy(varaux, p + 2);
- }
- }
- else
- strcpy(varname, rawvarname);
+ if((p = strchr(rawvarname, ':')))
+ {
+ strncpy(varname, rawvarname, p - rawvarname);
- bzero((char *) varbuffer, sizeof(varbuffer));
+ if(strlen(p) >= 2)
+ {
+ varmodifier = *(p + 1);
+ strcpy(varaux, p + 2);
+ }
+ }
+ else
+ strcpy(varname, rawvarname);
- varcontents = VarGet(varname);
+ bzero((char *) varbuffer, sizeof(varbuffer));
- switch(varmodifier)
- {
- case '-':
- if(!varcontents || !strlen(varcontents))
- varcontents = varaux;
- break;
+ varcontents = VarGet(varname);
- case '?':
- if(!varcontents || !strlen(varcontents))
- {
- ErrorMessage("%s(%d): ", file_name, file_line);
+ switch(varmodifier)
+ {
+ case '-':
+ if(!varcontents || !strlen(varcontents))
+ varcontents = varaux;
+ break;
- if(strlen(varaux))
- FatalError("%s\n", varaux);
- else
- FatalError("Undefined variable \"%s\"\n",
varname);
- }
- break;
- }
+ case '?':
+ if(!varcontents || !strlen(varcontents))
+ {
+ ErrorMessage("%s(%d): ", file_name, file_line);
- if(varcontents)
- {
- int l_varcontents = strlen(varcontents);
+ if(strlen(varaux))
+ FatalError("%s\n", varaux);
+ else
+ FatalError("Undefined variable \"%s\"\n", varname);
+ }
+ break;
+ }
- iv = 0;
+ if(varcontents)
+ {
+ int l_varcontents = strlen(varcontents);
+ string_len += l_varcontents;
- while(iv < l_varcontents && j < sizeof(estring) - 1)
- estring[j++] = varcontents[iv++];
- }
- }
- else
- {
- estring[j++] = '$';
- }
- }
- else
- {
- estring[j++] = c;
- }
+ if(string_len > line_len)
+ line = realloc(line, (line_len += STD_BUF) + 1);
+ memcpy(line + j, varcontents, l_varcontents);
+ j += l_varcontents;
+ }
+ }
+ else
+ {
+ line[j++] = '$';
+ }
}
- DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES, "ExpandVars, After: %s\n",
estring););
+ line[j] = 0;
+ DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES, "ExpandVars, After: %s\n",
line););
- return(estring);
+ return line;
}
@@ -4194,40 +4102,85 @@
return;
}
-/* adapted from ParseRuleFule in rules.c */
-char *ReadLine(FILE * file)
+char *ReadLine(FILE *in)
{
- char buf[STD_BUF];
- char *index;
+ size_t filledLen = 0,
+ len = 0,
+ lineSize = 0;
+ char *line = NULL,
+ *pos;
- bzero((char *) buf, STD_BUF);
-
- /*
- * Read a line from file and return it. Skip over lines beginning with #,
- * ;, or a newline
- */
- while((fgets(buf, STD_BUF, file)) != NULL)
+again:
+ for (;;)
{
- file_line++;
- index = buf;
+ /* allocate buffer */
+ if (len - filledLen < STD_BUF)
+ {
+ line = realloc(line, (len += STD_BUF) + 1);
+ if (len != STD_BUF)
+ line[len - 1] = 0;
+ else
+ *line = 0;
+ }
+ if (fgets(line + filledLen, len - filledLen + 1, in) == NULL ||
+ line[len - 1] == 0 || line[len - 1] == '\n')
+ {
+ /* no characters read? */
+ if (*line == 0)
+ {
+ free(line);
+ return NULL;
+ }
+
+ file_line++;
#ifdef DEBUG2
- LogMessage("Got line %s (%d): %s\n", file_name, file_line, buf);
+ LogMessage("Got line %s (%d): %s\n", file_name, file_line, line +
lineSize);
#endif
- /* if it's not a comment or a <CR>, we return it */
- if((*index != '#') && (*index != 0x0a) && (*index != ';')
- && (index != NULL))
- {
- /* advance through any whitespace at the beginning of ther line */
- while(isspace((int) *index))
- ++index;
- /* return a copy of the line */
- return strdup(index);
- }
+ /* if the line ends with a `\' */
+ pos = line + strlen(line) - 1;
+ if (*pos == '\\')
+ FatalError("Line %d ends with a `\', but no next line is "
+ "present\n", file_line);
+
+ for (; line + lineSize < pos && isspace((unsigned char) *pos);
pos--);
+
+ /* found non-space is backslash? */
+ if (*pos == '\\')
+ {
+ *(pos + 1) = 0;
+ filledLen = pos - line;
+ lineSize = filledLen;
+ continue;
+ }
+
+ break;
+ }
+
+
+ filledLen = len;
}
- return NULL;
+ /* find first non-space character */
+ for (pos = line; isspace((unsigned char) *pos); pos++);
+ /* is it a comment? */
+ if (*pos == '#' || *pos == ';' || *pos == 0)
+ {
+ lineSize = filledLen = 0;
+ *line = 0;
+ goto again;
+ }
+
+ /* strip whitespace at the beginning of the line if present */
+ if (line == pos)
+ return line;
+ else
+ {
+ char *copy = strdup(pos);
+ free(line);
+ return copy;
+ }
}
/*