From: Hui Cao (huica) Date: Mon, 7 May 2018 13:07:50 +0000 (-0400) Subject: Merge pull request #1206 in SNORT/snort3 from file_type_strings1 to master X-Git-Tag: 3.0.0-245~18 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=8197df559ed7b0f2be68b32df9ba9b89a5fc23f2;p=thirdparty%2Fsnort3.git Merge pull request #1206 in SNORT/snort3 from file_type_strings1 to master Squashed commit of the following: commit a7e1439ed447f31a501cf3342b4d8f6ce67e70b0 Author: Steve Chew Date: Fri Apr 27 17:07:43 2018 -0400 file_type: Require strings instead of integers for types. Handle versions. --- diff --git a/src/file_api/file_api.h b/src/file_api/file_api.h index 1978e4325..e74cb0f06 100644 --- a/src/file_api/file_api.h +++ b/src/file_api/file_api.h @@ -26,8 +26,9 @@ // Currently, it provides three sets of APIs: file processing, MIME processing, // and configurations. -#include +#include #include +#include #include "main/snort_types.h" @@ -114,6 +115,9 @@ struct FileCaptureInfo; namespace snort { +#define FILE_ID_MAX 1024 +typedef std::bitset 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 diff --git a/src/file_api/file_config.cc b/src/file_api/file_config.cc index ae558092c..f602b8239 100644 --- a/src/file_api/file_config.cc +++ b/src/file_api/file_config.cc @@ -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(); + } +} + diff --git a/src/file_api/file_config.h b/src/file_api/file_config.h index 3976acf2c..fec378cee 100644 --- a/src/file_api/file_config.h +++ b/src/file_api/file_config.h @@ -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&); diff --git a/src/file_api/file_flows.cc b/src/file_api/file_flows.cc index 6f8a8ddc4..ef7817ac2 100644 --- a/src/file_api/file_flows.cc +++ b/src/file_api/file_flows.cc @@ -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); diff --git a/src/file_api/file_identifier.cc b/src/file_api/file_identifier.cc index 4f149f798..833bdddc3 100644 --- a/src/file_api/file_identifier.cc +++ b/src/file_api/file_identifier.cc @@ -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 //-------------------------------------------------------------------------- diff --git a/src/file_api/file_identifier.h b/src/file_api/file_identifier.h index a583c4290..fe7152f38 100644 --- a/src/file_api/file_identifier.h +++ b/src/file_api/file_identifier.h @@ -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(); diff --git a/src/ips_options/ips_file_type.cc b/src/ips_options/ips_file_type.cc index c699f37f7..a3dcbc779 100644 --- a/src/ips_options/ips_file_type.cc +++ b/src/ips_options/ips_file_type.cc @@ -22,19 +22,16 @@ #include "config.h" #endif -#include - #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 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; }