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;
+    }
 }
 
 /*

Reply via email to