]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Pull request #3996: parser: add file_id rule syntax evaluation
authorAnna Norokh -X (anorokh - SOFTSERVE INC at Cisco) <anorokh@cisco.com>
Wed, 20 Sep 2023 13:01:26 +0000 (13:01 +0000)
committerOleksii Shumeiko -X (oshumeik - SOFTSERVE INC at Cisco) <oshumeik@cisco.com>
Wed, 20 Sep 2023 13:01:26 +0000 (13:01 +0000)
Merge in SNORT/snort3 from ~ANOROKH/snort3:contentless_file_id to master

Squashed commit of the following:

commit 62f56f702475340468f31ab8a7f1a0fcbdc3c943
Author: Anna Norokh <anorokh@cisco.com>
Date:   Wed Sep 13 11:03:31 2023 +0300

    parser: add file_id rule syntax evaluation

      * drop ParseError in case of file_id rule without file_meta,
        fast-pattern(content,regex) or file_data option;
      * update file_id docs;
      * detection: replace rtn hard check with assert

doc/user/concepts.txt
doc/user/file_processing.txt
src/detection/fp_detect.cc
src/file_api/dev_notes.txt
src/parser/parse_rule.cc

index 358b2540f6edbe2e5afca94cbe7a740bb172c8a8..e4448878665c1a7bc4af23b13add541cad99d4f8 100644 (file)
@@ -267,7 +267,7 @@ Fast patterns are content strings that have the fast_pattern option or
 which have been selected by Snort automatically to be used as a fast
 pattern.  Snort will by default choose the longest pattern in the rule
 since that is likely to be most unique.  That is not always the case so add
-fast_pattern to the appropriate content option for best performance.  The
+fast_pattern to the appropriate content or regex option for best performance.  The
 ideal fast pattern is one which, if found, is very likely to result in a
 rule match.  Fast patterns that match frequently for unrelated traffic will
 cause Snort to work hard with little to show for it.
index 08754aca66735e82eed75825bb7304a7171b23ee..6c7f65eadecc1a5c268def8dfde8e1ae3a77f5df 100644 (file)
@@ -59,19 +59,19 @@ There are 3 steps to enable file processing:
 ==== Pre-packaged File Magic Rules
 
 A set of file magic rules is packaged with Snort. They can be located at
-"lua/file_magic.lua". To use this feature, it is recommended that these
+"lua/file_magic.rules". To use this feature, it is recommended that these
 pre-packaged rules are used; doing so requires that you include
 the file in your Snort configuration as such (already in snort.lua):
 
-    dofile('magic.lua')
+    file_id = { rules_file = 'file_magic.rules' }
 
 Example:
 
-   { type = "GIF", id = 62, category = "Graphics", rev = 1,
-     magic = { { content = "| 47 49 46 38 37 61 |",offset = 0 } } },
+    file_id (msg:"GIF"; file_meta:type GIF, id 62, category "Graphics"; 
+      file_data; content:"| 47 49 46 38 37 61 |", depth 6, offset 0; gid:4; sid:56; rev:1;)
 
-   { type = "GIF", id = 63, category = "Graphics", rev = 1,
-     magic = { { content = "| 47 49 46 38 39 61 |",offset = 0 } } },
+    file_id (msg:"GIF"; file_meta:type GIF, id 63, category 'Graphics";
+      file_data; content:"| 47 49 46 38 39 61 |", depth 6, offset 0; gid:4; sid:57; rev:1;)
 
 The previous two rules define GIF format, because two file magics are
 different. File magics are specified by content and offset, which look
@@ -79,6 +79,9 @@ at content at particular file offset to identify the file type. In this
 case, two magics look at the beginning of the file. You can use character
 if it is printable or hex value in between "|".
 
+Note that `file_meta` and a fast-pattern option (content, regex) are required 
+for each file_id rule.
+
 ==== File Policy
 
 You can enabled file type, file signature, or file capture by configuring
index 5069726a25d519c81711e3f4614f901085318b08..694a85a5b3dde34c52b923e10c54c928af593edb 100644 (file)
@@ -274,7 +274,6 @@ int fpLogEvent(const RuleTreeNode* rtn, const OptTreeNode* otn, Packet* p)
 **    OptTreeNode        * - the otn to add.
 **
 **  FORMAL OUTPUTS
-**    int - 2 No rule tree node found for given policy ID.
 **    int - 1 max_events variable hit.
 **    int - 0 successful.
 **
@@ -282,8 +281,7 @@ int fpLogEvent(const RuleTreeNode* rtn, const OptTreeNode* otn, Packet* p)
 int fpAddMatch(OtnxMatchData* omd, const OptTreeNode* otn)
 {
     RuleTreeNode* rtn = getRtnFromOtn(otn);
-    if ( not rtn )
-        return 2;
+    assert(rtn);
 
     unsigned evalIndex = rtn->listhead->ruleListNode->evalIndex;
 
index c2867273b96610614d9b14d9cd1981b5ea4b6a74..f4b4bf5746dae4faea93febbe805ef07dda3b6ff 100644 (file)
@@ -16,3 +16,4 @@ threads to improve performance when multiple disks are used.
 * File libraries: provides file type identification and file signature
 calculation
 
+* file_id: file rules must contain `file_meta` and at least one fast-pattern option.
index d6e8eae7d121b8062a941ff86adf3e97bb8b73da..7ee3a256b1635b1bcc698759dee82062736a311a 100644 (file)
@@ -94,6 +94,8 @@ static std::string s_type;
 static std::string s_body;
 
 static bool action_file_id = false;
+static bool fp_file_id = false;
+static bool only_file_data = true;
 static bool strict_rtn_reduction = false;
 
 struct SoRule
@@ -1014,7 +1016,17 @@ void parse_rule_opt_end(SnortConfig* sc, const char* key, OptTreeNode* otn)
     CursorActionType cat = ips ? ips->get_cursor_type() : CAT_NONE;
 
     if ( cat > CAT_ADJUST )
+    {
         buf_is_set = true;
+        if ( action_file_id and strcmp(ips->get_name(), "file_data") )
+            only_file_data = false;
+    }
+
+    if ( ips and action_file_id )
+    {
+        if ( !strcmp(ips->get_name(), "content") or !strcmp(ips->get_name(), "regex") )
+            fp_file_id = true;
+    }
 
     if ( type != OPT_TYPE_META )
         otn->num_detection_opts++;
@@ -1157,6 +1169,28 @@ void parse_rule_close(SnortConfig* sc, RuleTreeNode& rtn, OptTreeNode* otn)
         return;
     }
 
+    if ( action_file_id )
+    {
+        if ( !otn->sigInfo.file_id )
+            ParseError("file_id rule %u:%u:%u requires file_meta option", otn->sigInfo.gid,
+                otn->sigInfo.sid, otn->sigInfo.rev);
+
+        if ( !fp_file_id )
+            ParseError("file_id rule %u:%u:%u requires a fast-pattern option",
+                otn->sigInfo.gid, otn->sigInfo.sid, otn->sigInfo.rev);
+
+        if ( buf_is_set and !only_file_data )
+            ParseError("file_id rule %u:%u:%u disallows IPS buffers that are not file_data",
+                otn->sigInfo.gid, otn->sigInfo.sid, otn->sigInfo.rev);
+
+        if ( !buf_is_set )
+            ParseError("file_id rule %u:%u:%u requires file_data option",
+                otn->sigInfo.gid, otn->sigInfo.sid, otn->sigInfo.rev);
+
+        only_file_data = true;
+        fp_file_id = false;
+    }
+
     RuleTreeNode* tmp = s_so_rule ? s_so_rule->rtn : &rtn;
     RuleTreeNode* new_rtn = transfer_rtn(tmp);
     addRtnToOtn(sc, otn, new_rtn);