[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: On packages depending on up-to-date data (was Re: Snort: Mass Bug Closing)



On Tue, Aug 26, 2003 at 12:24:11AM +0200, Sander Smeenk wrote:
> > Really, the way to fix this package X needs data Y to be up-to-date is to:
> > a) separate data from the package (Nessus plugins are available in the 
> > 'nessus-plugins' package and can be updated separately, for example)
> 
> snort has that. snort-rules-default is the default set of rules found on
> snort.org for the release that is in debian, almost always updated when a 
> new debian-release of the package is done. People can start packaging
> their own rulesets, maybe even local rulesets or something.

Sure, I'm not saying that snort does not have it. I'm just saying that 
maybe you should consider upgrading the one in stable. The differences in 
format are known and you should be able to find a way to convert older 
rules set. 

> 
> > b) provide some way to retrieve new data (signatures, attacks, whatever)
> > either: downloading them from the main site directly (as
> > nessus-update-plugins does) or providing backported packages (and have them
> > included in stable revisiones.
> 
> This problem only exists for snort packages that aren't going to be
> updated, like the ones that reach stable. The unstable package is up to
> date enough to have all correct rules, imho.

You can convince the stable release manager to put a new 
snort-rules-default package into sarge, for example, 6 months after it is 
released. It's easier to do that than to try to push a new upstream version 
into sarge, and you will be providing the new rules users might want.

In any case, I was thinking on the lines of a separate (not packaged) 
method to download rules directly from snort.org. Please take a look at the 
'nessus-update-plugins' to see what I mean.

> The other thing is, snort.org's people quickly start to drop old rule
> formats when newer formats are used.  Should I be the one that has to
> convert every rule back to the old format to have stable users of snort
> safe and sound? It'll take alot of time. And I believe it is not always
> scriptable.

You are, after all, the snort package maintainer. If you don't want to do 
this you can try to find people who might volunteer to do the work for 
stable and provide a new snort-rules-default package for stable maybe 
converting some of the new rules which are no longer valid. Granted, some 
information might be lost in the conversion and some rules might not be 
converted, but still, better than no updates.

> So, although it sounds nice to have scripts to update rulefiles, I don't
> really see it happening, because of the problems amentioned above.

If no one works to see that happen it will never be.

> 
> > c) have a way to determine properly when new data needs a new engine and 
> > won't work with older versions and warn the user about it. This means that 
> > the engine needs to be programmed beforehand to understand a given dataset 
> > version and complain when the dataset is of a newer (and potentially 
> > worthless) version.
> 
> Well. Snort just fails to start if it can't parse the rule files. And
> usually that is with every major upstream release. :(

[Short version: see the patch below.]

[Long version: follows]
That's obviously, suboptimal, snort should be able to determine in some way
from a rules file if the format is a version it knows or it isn't. C'mon
version headers are not unheard of, just take a look at the header of any
HTML file in www.debian.org, it will tell you precisely which DTD to use to
be able to "understand" it. 

It wouldn't be so difficult [1] to have snort analyse the rules file before
including and determine if its rules can, or cannot, be added. Of course,
that would be mean improving the way rules files are parsed currently.

There is currently no distinction between snort's configuration and the
rules files themselves (pv.config_file in snort.c) but if they were
separated the ParseRulesFile in snort's parser.c could be rewritten to
verify the call to ParseRule and not proceed if there is an indication that
the rules belong to a new version. 

The adjointed patch (probably very ugly, untested and maybe broken) 
provides that functionality. If the snort parser encounters a place of the 
file which has 'version X' with X > SNORT_MAJOR_VERSION then it will not go 
on reading the rest of the rules file. That way you can have rules in one 
file which are read by older snort versions and rules that cannot (maybe 
because the Parser has been enhanced to included new formats).

Regards

Javi
--- parser.c.old	2003-08-26 01:04:50.000000000 +0200
+++ parser.c	2003-08-26 01:20:40.000000000 +0200
@@ -55,6 +55,8 @@
 #include "threshold.h"
 
 #include "snort.h"
+#define SNORT_MAJOR_VERSION 2
+/* SNORT_VERSION should probably be defined in the snort generic headers */
 
 ListHead Alert;         /* Alert Block Header */
 ListHead Log;           /* Log Block Header */
@@ -128,6 +130,7 @@
     int stored_file_line = file_line;
     char *saved_line = NULL;
     int continuation = 0;
+    int continueread = 1;
     char *new_line = NULL;
     struct stat file_stat; /* for include path testing */
 
@@ -198,7 +201,7 @@
 
 
     /* loop thru each file line and send it to the rule parser */
-    while((fgets(buf, STD_BUF, thefp)) != NULL)
+    while( continueread >0 && (fgets(buf, STD_BUF, thefp)) != NULL)
     {
         /*
          * inc the line counter so the error messages know which line to
@@ -248,7 +251,7 @@
                 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,
                             "[*] Processing rule: %s\n", index););
 
-                ParseRule(thefp, index, inclevel);
+                continueread = ParseRule(thefp, index, inclevel);
 
                 if(new_line != NULL)
                 {
@@ -454,14 +457,16 @@
  * Arguments: rule => rule string
  *            inclevel => nr of stacked "include"s
  *
- * Returns: void function
+ * Returns: integer, if greater than 0 the processor will keep reading
+ *          the rules file otherwise it will stop
  *
  ***************************************************************************/
-void ParseRule(FILE *rule_file, char *prule, int inclevel)
+int ParseRule(FILE *rule_file, char *prule, int inclevel)
 {
     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 */
+    int version;        /* version of the rules below */ 
     char rule[PARSERULE_SIZE];
     int protocol = 0;
     char *tmp;
@@ -493,6 +498,19 @@
     /* handle non-rule entries */
     switch(rule_type)
     {
+        case RULE_VERSION:
+            DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Version\n"););
+	    version = strtol(toks[1], NULL, 10);
+	    if ( errno == ERANGE || errno == EINVAL ) {
+                    FatalError("%s(%d) => Version is not a number %s\n", 
+                               file_name, file_line, toks[1]);
+	    }
+	    if ( version > SNORT_MAJOR_VERSION ) {
+                    ErrorMessage("%s(%d) => Version %s not supported, rules file will not be read any longer\n", file_name, file_line, toks[1]);
+		  return 0;
+	    }
+	    return 1 ;
+
         case RULE_PASS:
             DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Pass\n"););
             break;
@@ -522,22 +540,22 @@
 
             ParseRulesFile(tmp, inclevel + 1);
 
-            return;
+            return 1;
 
         case RULE_VAR:
             DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Variable\n"););
             VarDefine(toks[1], toks[2]);
-            return;
+            return 1;
 
         case RULE_PREPROCESS:
             DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Preprocessor\n"););
             ParsePreprocessor(rule);
-            return;
+            return 1;
 
         case RULE_OUTPUT:
             DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Output Plugin\n"););
             ParseOutputPlugin(rule);
-            return;
+            return 1;
 
         case RULE_ACTIVATE:
             DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Activation rule\n"););
@@ -550,21 +568,21 @@
         case RULE_CONFIG:
             DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Rule file config\n"););
             ParseConfig(rule);
-            return;
+            return 1;
 
         case RULE_DECLARE:
             DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Rule type declaration\n"););
             ParseRuleTypeDeclaration(rule_file, rule);
-            return;
+            return 1;
 
         case RULE_UNKNOWN:
             DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Unknown rule type, might be declared\n"););
             ParseDeclaredRuleType(rule);
-            return;
+            return 1;
 
         default:
             DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Invalid input: %s\n", prule););
-            return;
+            return 1;
     }
 
     if(num_toks < 7)
@@ -580,7 +598,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;
+        return 1;
     }
 
 
@@ -713,7 +731,7 @@
         free(toks[i]);
     }
 
-    return;
+    return 1;
 }
 
 /****************************************************************************
@@ -1772,6 +1790,9 @@
         FatalError("%s(%d) => Unknown rule type (%s)\n", file_name, file_line, func);
     }
     
+    if(!strcasecmp(func, "version"))
+        return RULE_VERSION;
+
     if(!strcasecmp(func, "log"))
         return RULE_LOG;
 
53a54
> #define RULE_VERSION     12

Attachment: pgprMn5pQtcFq.pgp
Description: PGP signature


Reply to: