]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Merge pull request #1206 in SNORT/snort3 from file_type_strings1 to master
authorHui Cao (huica) <huica@cisco.com>
Mon, 7 May 2018 13:07:50 +0000 (09:07 -0400)
committerHui Cao (huica) <huica@cisco.com>
Mon, 7 May 2018 13:07:50 +0000 (09:07 -0400)
Squashed commit of the following:

commit a7e1439ed447f31a501cf3342b4d8f6ce67e70b0
Author: Steve Chew <stechew@cisco.com>
Date:   Fri Apr 27 17:07:43 2018 -0400

    file_type: Require strings instead of integers for types. Handle versions.

src/file_api/file_api.h
src/file_api/file_config.cc
src/file_api/file_config.h
src/file_api/file_flows.cc
src/file_api/file_identifier.cc
src/file_api/file_identifier.h
src/ips_options/ips_file_type.cc

index 1978e43255d51f0a61d7f5151c22db832acfc71f..e74cb0f06053b036efcfe49098675b566a951425 100644 (file)
@@ -26,8 +26,9 @@
 // Currently, it provides three sets of APIs: file processing, MIME processing,
 // and configurations.
 
-#include <string>
+#include <bitset>
 #include <cstring>
+#include <string>
 
 #include "main/snort_types.h"
 
@@ -114,6 +115,9 @@ struct FileCaptureInfo;
 
 namespace snort
 {
+#define FILE_ID_MAX          1024
+typedef std::bitset<FILE_ID_MAX> FileTypeBitSet;
+
 class FileContext;
 class FileInfo;
 class Flow;
@@ -188,7 +192,9 @@ inline FileCharEncoding get_character_encoding(const char* file_name, size_t len
 }
 
 SO_PUBLIC uint64_t get_file_processed_size(Flow* flow);
-FilePosition get_file_position(Packet* pkt);
+SO_PUBLIC FilePosition get_file_position(Packet* pkt);
+SO_PUBLIC void get_magic_rule_ids_from_type(const std::string& type,
+    const std::string& version, FileTypeBitSet& ids_set);
 }
 #endif
 
index ae558092c067cf6bfb0501b530f9d607c31a6a36..f602b823923e6f551ce2225c05ced19ed78fd697 100644 (file)
@@ -71,6 +71,12 @@ FileMagicRule* FileConfig::get_rule_from_id(uint32_t id)
     return fileIdentifier.get_rule_from_id(id);
 }
 
+void FileConfig::get_magic_rule_ids_from_type(const std::string& type,
+    const std::string& version, snort::FileTypeBitSet& ids_set)
+{
+    return fileIdentifier.get_magic_rule_ids_from_type(type, version, ids_set);
+}
+
 std::string FileConfig::file_type_name(uint32_t id)
 {
     if (SNORT_FILE_TYPE_UNKNOWN == id)
@@ -105,3 +111,16 @@ FileConfig* get_file_config ()
     else
         return nullptr;
 }
+
+namespace snort
+{
+    void get_magic_rule_ids_from_type(const std::string& type, const std::string& version, snort::FileTypeBitSet& ids_set)
+    {
+        FileConfig* conf = get_file_config();
+        if(conf)
+            conf->get_magic_rule_ids_from_type(type, version, ids_set);
+        else
+            ids_set.reset();
+    }
+}
+
index 3976acf2c311132de08c1e1f2b221422caf5583d..fec378ceeb8d2719ac52f94d7796c9e7db82b0a0 100644 (file)
@@ -45,6 +45,8 @@ class FileConfig
 {
 public:
     FileMagicRule* get_rule_from_id(uint32_t);
+    void get_magic_rule_ids_from_type(const std::string&, const std::string&,
+        snort::FileTypeBitSet&);
     void process_file_rule(FileMagicRule&);
     void process_file_policy_rule(FileRule&);
     bool process_file_magic(FileMagicData&);
index 6f8a8ddc4c9a3891a99a9c7f0e9c45977f309999..ef7817ac249118eb904ca0786f189ef6552dd399 100644 (file)
@@ -43,6 +43,26 @@ using namespace snort;
 unsigned FileFlows::file_flow_data_id = 0;
 static THREAD_LOCAL uint32_t max_file_id = 0;
 
+namespace snort
+{
+    FilePosition get_file_position(Packet* pkt)
+    {
+        FilePosition position = SNORT_FILE_POSITION_UNKNOWN;
+        Packet* p = (Packet*)pkt;
+
+        if (p->is_full_pdu())
+            position = SNORT_FILE_FULL;
+        else if (p->is_pdu_start())
+            position = SNORT_FILE_START;
+        else if (p->packet_flags & PKT_PDU_TAIL)
+            position = SNORT_FILE_END;
+        else if (get_file_processed_size(p->flow))
+            position = SNORT_FILE_MIDDLE;
+
+        return position;
+    }
+}
+
 void FileFlows::handle_retransmit (Packet*)
 {
     if (file_policy == nullptr)
@@ -245,25 +265,7 @@ void FileFlows::add_pending_file(uint64_t file_id)
 {
     current_file_id = pending_file_id = file_id;
 }
-namespace snort
-{
-FilePosition get_file_position(Packet* pkt)
-{
-    FilePosition position = SNORT_FILE_POSITION_UNKNOWN;
-    Packet* p = (Packet*)pkt;
-
-    if (p->is_full_pdu())
-        position = SNORT_FILE_FULL;
-    else if (p->is_pdu_start())
-        position = SNORT_FILE_START;
-    else if (p->packet_flags & PKT_PDU_TAIL)
-        position = SNORT_FILE_END;
-    else if (get_file_processed_size(p->flow))
-        position = SNORT_FILE_MIDDLE;
-
-    return position;
-}
-}
+
 FileInspect::FileInspect(FileIdModule* fm)
 {
     fm->load_config(config);
index 4f149f798a1727c92712c1c75a3cd624f9fb1e52..833bdddc34b24f616a0e56ee10b5a0619a547921 100644 (file)
@@ -290,9 +290,9 @@ void FileIdentifier::insert_file_rule(FileMagicRule& rule)
         init_merge_hash();
     }
 
-    if (rule.id > FILE_ID_MAX)
+    if (rule.id >= FILE_ID_MAX)
     {
-        ParseError("file type: rule id %u larger than %d", rule.id, FILE_ID_MAX);
+        ParseError("file type: rule id %u exceeds max id of %d", rule.id, FILE_ID_MAX-1);
         return;
     }
 
@@ -371,6 +371,23 @@ FileMagicRule* FileIdentifier::get_rule_from_id(uint32_t id)
         return nullptr;
 }
 
+void FileIdentifier::get_magic_rule_ids_from_type(const std::string& type,
+    const std::string& version, snort::FileTypeBitSet& ids_set)
+{
+    ids_set.reset();
+
+    for(uint32_t i; i < FILE_ID_MAX; i++)
+    {
+        if(type == file_magic_rules[i].type)
+        {
+            if(version.empty() or version == file_magic_rules[i].version)
+            {
+                ids_set.set(file_magic_rules[i].id);
+            }
+        }
+    }
+}
+
 //--------------------------------------------------------------------------
 // unit tests
 //--------------------------------------------------------------------------
index a583c42904fb1a1091c083ba712179ebf274c0b5..fe7152f38ac1f476600288e9749e000878c23650 100644 (file)
@@ -33,8 +33,6 @@
 
 #include "file_lib.h"
 
-#define FILE_ID_MAX          1024
-
 #define MAX_BRANCH (UINT8_MAX + 1)
 
 enum IdNodeState
@@ -91,6 +89,7 @@ public:
     void insert_file_rule(FileMagicRule& rule);
     uint32_t find_file_type_id(const uint8_t* buf, int len, uint64_t offset, void** context);
     FileMagicRule* get_rule_from_id(uint32_t);
+    void get_magic_rule_ids_from_type(const std::string&, const std::string&, snort::FileTypeBitSet&);
 
 private:
     void init_merge_hash();
index c699f37f78b0ce76e591803cb0097d17420dc24c..a3dcbc779fee0e88ee8c01022115b3bb51af37a7 100644 (file)
 #include "config.h"
 #endif
 
-#include <bitset>
-
 #include "framework/ips_option.h"
 #include "framework/module.h"
 #include "file_api/file_flows.h"
 #include "file_api/file_identifier.h"
+#include "log/messages.h"
 #include "profiler/profiler.h"
 #include "protocols/packet.h"
 
 using namespace snort;
 
-typedef std::bitset<FILE_ID_MAX> TypeBitSet;
-
 #define s_name "file_type"
 
 static THREAD_LOCAL ProfileStats fileTypePerfStats;
@@ -42,21 +39,21 @@ static THREAD_LOCAL ProfileStats fileTypePerfStats;
 class FileTypeOption : public IpsOption
 {
 public:
-    FileTypeOption(TypeBitSet &);
+    FileTypeOption(FileTypeBitSet&);
 
     CursorActionType get_cursor_type() const override
     { return CAT_NONE; }
 
     EvalStatus eval(Cursor&, Packet*) override;
 
-    TypeBitSet types;
+    FileTypeBitSet types;
 };
 
 //-------------------------------------------------------------------------
 // class methods
 //-------------------------------------------------------------------------
 
-FileTypeOption::FileTypeOption(TypeBitSet& t) : IpsOption(s_name)
+FileTypeOption::FileTypeOption(FileTypeBitSet& t) : IpsOption(s_name)
 {
     types = t;
 }
@@ -110,8 +107,6 @@ public:
     bool begin(const char*, int, SnortConfig*) override;
     bool set(const char*, Value&, SnortConfig*) override;
 
-    bool set_types(long);
-
     ProfileStats* get_profile() const override
     { return &fileTypePerfStats; }
 
@@ -119,7 +114,10 @@ public:
     { return DETECT; }
 
 public:
-    TypeBitSet types;
+    FileTypeBitSet types;
+
+private:
+    bool parse_type_and_version(std::string& token);
 };
 
 bool FileTypeModule::begin(const char*, int, SnortConfig*)
@@ -129,16 +127,6 @@ bool FileTypeModule::begin(const char*, int, SnortConfig*)
     return true;
 }
 
-bool FileTypeModule::set_types(long t)
-{
-    if ( t < 0 or t > FILE_ID_MAX )
-        return false;
-
-    types.set((uint32_t)t);
-
-    return true;
-}
-
 bool FileTypeModule::set(const char*, Value& v, SnortConfig*)
 {
     if ( !v.is("~") )
@@ -149,22 +137,76 @@ bool FileTypeModule::set(const char*, Value& v, SnortConfig*)
 
     while ( v.get_next_token(tok) )
     {
-        long n;
-
         if ( tok[0] == '"' )
             tok.erase(0, 1);
 
         if ( tok[tok.length()-1] == '"' )
             tok.erase(tok.length()-1, 1);
 
-        if ( v.strtol(n, tok) )
+        if (! parse_type_and_version(tok) )
+            return false;
+    }
+    return true;
+}
+
+// Parse a file_type token and add the rule ID associated with the type
+// into the set of file types to match.
+//
+// The file_type token can have the following format where TYPENAME and
+// VER? are strings:
+//
+// TYPENAME     -- Type by itself will match all versions of that type.
+// TYPENAME,VER1 -- Match type and version
+// TYPENAME,VER1,VER2,... -- Match type and any of the specified versions.
+//
+//    Multiple types are separated by spaces:
+// TYPE1,VER1 TYPE2 TYPE3,VER1,VER2 -- Match any of these types
+//
+bool FileTypeModule::parse_type_and_version(std::string& token)
+{
+    std::istringstream stream(token);
+    std::string type_name;
+    std::string version;
+    FileTypeBitSet ids_set;
+
+    if(!std::getline(stream, type_name, ','))
+        return false;
+
+    if(!std::getline(stream, version, ','))
+    {
+        // Match all versions of this type.
+        get_magic_rule_ids_from_type(type_name, "", ids_set);
+        if(ids_set.none())
         {
-            if ( !set_types(n) )
-                return false;
+            ParseError("Invalid file_type type '%s'. Not found in file_rules.", type_name.c_str());
+            return false;
         }
-        else
+
+        types |= ids_set;
+        return true;
+    }
+
+    get_magic_rule_ids_from_type(type_name, version, ids_set);
+    if(ids_set.none())
+    {
+        ParseError("Invalid file_type type '%s' or version '%s'. Not found in file_rules.", type_name.c_str(), version.c_str());
+        return false;
+    }
+
+    types |= ids_set;
+
+    while(std::getline(stream, version, ','))
+    {
+        get_magic_rule_ids_from_type(type_name, version, ids_set);
+        if(ids_set.none())
+        {
+            ParseError("Invalid file_type type '%s' or version '%s'. Not found in file_rules.", type_name.c_str(), version.c_str());
             return false;
+        }
+
+        types |= ids_set;
     }
+
     return true;
 }