From: Ron Dempster (rdempste) Date: Thu, 13 Jan 2022 14:29:13 +0000 (+0000) Subject: Pull request #3205: Move global inspectors and selectors to the policy map X-Git-Tag: 3.1.21.0~9 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e5ccb7285682df7b1f432833e6afdb74b98a710c;p=thirdparty%2Fsnort3.git Pull request #3205: Move global inspectors and selectors to the policy map Merge in SNORT/snort3 from ~RDEMPSTE/snort3:global to master Squashed commit of the following: commit 3e62d9c7bf8bfaddb89e9b9419efd08d78a9a7bb Author: Ron Dempster (rdempste) Date: Tue Dec 7 11:06:41 2021 -0500 policy: add a file_policy to the network policy and use it commit 0b136c2654fa7d4ffadcb5ad3b080e723bc43bc2 Author: Ron Dempster (rdempste) Date: Fri Dec 3 16:19:22 2021 -0500 main: move policy selector and flow tracking from snort config to policy map commit 69d9c2d07434a6ebe0968231f9ad503b43a0a1f4 Author: Ron Dempster (rdempste) Date: Fri Dec 3 16:18:11 2021 -0500 main: only add policies to the user policy map at the end of table processing commit 20377e6bd1f74bbe37c615ce4b4aacf3c401c8c7 Author: Ron Dempster (rdempste) Date: Fri Dec 3 16:16:04 2021 -0500 control: fix macro definitions --- diff --git a/lua/max_detect.lua b/lua/max_detect.lua index 19a8c5751..418f45519 100644 --- a/lua/max_detect.lua +++ b/lua/max_detect.lua @@ -6,9 +6,6 @@ arp_spoof = nil --- bug: false will limit http file_data -file_id.enable_signature = true - ftp_server.check_encrypted = true detection = diff --git a/lua/security.lua b/lua/security.lua index 3a046c44a..c2613d94f 100644 --- a/lua/security.lua +++ b/lua/security.lua @@ -5,9 +5,6 @@ arp_spoof = nil --- bug: false will limit http file_data -file_id.enable_signature = true - ftp_server.check_encrypted = true detection = diff --git a/lua/snort.lua b/lua/snort.lua index 7343bb0f7..3579a4d53 100644 --- a/lua/snort.lua +++ b/lua/snort.lua @@ -86,6 +86,7 @@ http2_inspect = { } -- see file_magic.lua for file id rules file_id = { file_rules = file_magic } +file_policy = { } -- the following require additional configuration to be fully effective: diff --git a/src/control/control.h b/src/control/control.h index d6f271774..b797e4834 100644 --- a/src/control/control.h +++ b/src/control/control.h @@ -80,7 +80,7 @@ private: time_t touched; }; -#define LogRespond(cn, ...) if (cn) cn->respond(__VA_ARGS__); else LogMessage(__VA_ARGS__) -#define LogfRespond(cn, fh, ...) if (cn) cn->respond(__VA_ARGS__); else LogMessage(fh, __VA_ARGS__) +#define LogRespond(cn, ...) do { if (cn) cn->respond(__VA_ARGS__); else LogMessage(__VA_ARGS__); } while(0) +#define LogfRespond(cn, fh, ...) do { if (cn) cn->respond(__VA_ARGS__); else LogMessage(fh, __VA_ARGS__); } while(0) #endif diff --git a/src/file_api/CMakeLists.txt b/src/file_api/CMakeLists.txt index 2eddff699..32fa5969d 100644 --- a/src/file_api/CMakeLists.txt +++ b/src/file_api/CMakeLists.txt @@ -7,7 +7,6 @@ set( FILE_API_INCLUDES file_identifier.h file_lib.h file_module.h - file_policy.h file_segment.h file_service.h ) @@ -16,6 +15,7 @@ add_library ( file_api OBJECT ${FILE_API_INCLUDES} circular_buffer.cc circular_buffer.h + file_api.cc file_capture.cc file_cache.cc file_cache.h @@ -27,7 +27,6 @@ add_library ( file_api OBJECT file_mempool.cc file_mempool.h file_module.cc - file_policy.cc file_segment.cc file_service.cc file_stats.cc diff --git a/src/file_api/file_api.cc b/src/file_api/file_api.cc new file mode 100644 index 000000000..b644a791d --- /dev/null +++ b/src/file_api/file_api.cc @@ -0,0 +1,43 @@ +//-------------------------------------------------------------------------- +// Copyright (C) 2021-2021 Cisco and/or its affiliates. All rights reserved. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License Version 2 as published +// by the Free Software Foundation. You may not use, modify or distribute +// this program under any other version of the GNU General Public License. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +//-------------------------------------------------------------------------- +// file_api.cc author Ron Dempster + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "file_api/file_api.h" + +using namespace snort; + +FilePolicyBase::FilePolicyBase() +{ ref_count = 1; } + +FilePolicyBase::~FilePolicyBase() +{ assert(!ref_count); } + +void FilePolicyBase::delete_file_policy(FilePolicyBase* policy) +{ + if (policy) + { + assert(policy->ref_count); + unsigned ref = --policy->ref_count; + if (!ref) + delete policy; + } +} diff --git a/src/file_api/file_api.h b/src/file_api/file_api.h index d7d1c87b7..991a0d924 100644 --- a/src/file_api/file_api.h +++ b/src/file_api/file_api.h @@ -26,6 +26,7 @@ // Currently, it provides three sets of APIs: file processing, MIME processing, // and configurations. +#include #include #include #include @@ -138,8 +139,8 @@ class SO_PUBLIC FilePolicyBase { public: - FilePolicyBase() = default; - virtual ~FilePolicyBase() = default; + FilePolicyBase(); + virtual ~FilePolicyBase(); // This is called when a new flow is queried for the first time // Check & update what file policy is enabled on this flow/file @@ -154,6 +155,14 @@ public: { return FILE_VERDICT_UNKNOWN; } virtual void log_file_action(Flow*, FileInfo*, FileAction) { } + + void add_ref() + { ++ref_count; } + + SO_PUBLIC static void delete_file_policy(FilePolicyBase*); + +private: + std::atomic_uint ref_count; }; inline void initFilePosition(FilePosition* position, uint64_t processed_size) diff --git a/src/file_api/file_config.cc b/src/file_api/file_config.cc index 81d5c869c..3170dc9fd 100644 --- a/src/file_api/file_config.cc +++ b/src/file_api/file_config.cc @@ -63,11 +63,6 @@ void FileConfig::process_file_rule(FileMagicRule& rule) fileIdentifier.insert_file_rule(rule); } -void FileConfig::process_file_policy_rule(FileRule& rule) -{ - filePolicy.insert_file_rule(rule); -} - const FileMagicRule* FileConfig::get_rule_from_id(uint32_t id) const { return fileIdentifier.get_rule_from_id(id); @@ -109,7 +104,7 @@ FileConfig* get_file_config(const SnortConfig* sc) if ( !sc ) sc = SnortConfig::get_conf(); - FileInspect* fi = (FileInspect*)InspectorManager::get_inspector(FILE_ID_NAME, true, sc); + FileInspect* fi = (FileInspect*)InspectorManager::get_file_inspector(sc); if (fi) return (fi->config); diff --git a/src/file_api/file_config.h b/src/file_api/file_config.h index 3e380da2d..bb3f4ca7d 100644 --- a/src/file_api/file_config.h +++ b/src/file_api/file_config.h @@ -25,7 +25,6 @@ // This provides the basic configuration for file processing #include "main/snort_config.h" #include "file_api/file_identifier.h" -#include "file_api/file_policy.h" #define DEFAULT_FILE_TYPE_DEPTH 1460 #define DEFAULT_FILE_SIGNATURE_DEPTH 10485760 /*10 Mbytes*/ @@ -49,11 +48,8 @@ public: void get_magic_rule_ids_from_type(const std::string&, const std::string&, snort::FileTypeBitSet&) const; void process_file_rule(FileMagicRule&); - void process_file_policy_rule(FileRule&); bool process_file_magic(FileMagicData&); uint32_t find_file_type_id(const uint8_t* buf, int len, uint64_t file_offset, void** context); - FilePolicy& get_file_policy() { return filePolicy; } - const FilePolicy& get_file_policy() const { return filePolicy; } std::string file_type_name(uint32_t id) const; int64_t file_type_depth = DEFAULT_FILE_TYPE_DEPTH; @@ -73,11 +69,9 @@ public: bool trace_type = false; bool trace_signature = false; bool trace_stream = false; - int64_t verdict_delay = 0; private: FileIdentifier fileIdentifier; - FilePolicy filePolicy; }; std::string file_type_name(uint32_t id); diff --git a/src/file_api/file_flows.cc b/src/file_api/file_flows.cc index e01bb21ca..ad4387df3 100644 --- a/src/file_api/file_flows.cc +++ b/src/file_api/file_flows.cc @@ -136,14 +136,13 @@ FileFlows* FileFlows::get_file_flows(Flow* flow, bool to_create) if (!to_create or fd) return fd; - FileInspect* fi = (FileInspect*)InspectorManager::get_inspector(FILE_ID_NAME, true); + FileInspect* fi = (FileInspect*)InspectorManager::get_file_inspector(); if (FileService::is_file_service_enabled() and fi) { fd = new FileFlows(flow, fi); flow->set_flow_data(fd); - if (fi->config) - fd->set_file_policy(&(fi->config->get_file_policy())); + fd->set_file_policy(get_network_policy()->get_base_file_policy()); } return fd; @@ -223,6 +222,8 @@ FileFlows::~FileFlows() { delete elem.second; } + + FilePolicyBase::delete_file_policy(file_policy); } FileContext* FileFlows::find_main_file_context(FilePosition pos, FileDirection dir, size_t index) @@ -297,7 +298,7 @@ FileContext* FileFlows::get_file_context( context = new FileContext; partially_processed_contexts[multi_file_processing_id] = context; FILE_DEBUG(file_trace, DEFAULT_TRACE_OPTION_ID, TRACE_DEBUG_LEVEL, GET_CURRENT_PACKET, - "get_file_context:creating new context\n"); + "get_file_context:creating new context\n"); if (partially_processed_contexts.size() > file_counts.max_concurrent_files_per_flow) file_counts.max_concurrent_files_per_flow = partially_processed_contexts.size(); } @@ -352,7 +353,7 @@ bool FileFlows::file_process(Packet* p, uint64_t file_id, const uint8_t* file_da if ((file_depth < 0) or (offset > (uint64_t)file_depth)) { FILE_DEBUG(file_trace , DEFAULT_TRACE_OPTION_ID, TRACE_ERROR_LEVEL, p, - "file depth less than zero or offset is more than file depth , returning\n"); + "file depth less than zero or offset is more than file depth , returning\n"); return false; } @@ -418,7 +419,7 @@ bool FileFlows::file_process(Packet* p, uint64_t file_id, const uint8_t* file_da } } - FILE_DEBUG(file_trace , DEFAULT_TRACE_OPTION_ID, TRACE_DEBUG_LEVEL, p, + FILE_DEBUG(file_trace , DEFAULT_TRACE_OPTION_ID, TRACE_DEBUG_LEVEL, p, "calling context process data_size %d, offset %lu, position %d\n", data_size, offset, position); continue_processing = context->process(p, file_data, data_size, offset, file_policy, position); @@ -539,18 +540,16 @@ bool FileInspect::configure(SnortConfig*) static void file_config_show(const FileConfig* fc) { - const FilePolicy& fp = fc->get_file_policy(); - - if ( ConfigLogger::log_flag("enable_type", fp.get_file_type()) ) + if ( ConfigLogger::log_flag("enable_type", FileService::is_file_type_id_enabled()) ) ConfigLogger::log_value("type_depth", fc->file_type_depth); - if ( ConfigLogger::log_flag("enable_signature", fp.get_file_signature()) ) + if ( ConfigLogger::log_flag("enable_signature", FileService::is_file_signature_enabled()) ) ConfigLogger::log_value("signature_depth", fc->file_signature_depth); if ( ConfigLogger::log_flag("block_timeout_lookup", fc->block_timeout_lookup) ) ConfigLogger::log_value("block_timeout", fc->file_block_timeout); - if ( ConfigLogger::log_flag("enable_capture", fp.get_file_capture()) ) + if ( ConfigLogger::log_flag("enable_capture", FileService::is_file_capture_enabled()) ) { ConfigLogger::log_value("capture_memcap", fc->capture_memcap); ConfigLogger::log_value("capture_max_size", fc->capture_max_size); @@ -566,7 +565,6 @@ static void file_config_show(const FileConfig* fc) ConfigLogger::log_flag("trace_type", fc->trace_type); ConfigLogger::log_flag("trace_signature", fc->trace_signature); ConfigLogger::log_flag("trace_stream", fc->trace_stream); - ConfigLogger::log_value("verdict_delay", fc->verdict_delay); } void FileInspect::show(const SnortConfig*) const @@ -615,7 +613,7 @@ static const InspectApi file_inspect_api = mod_ctor, mod_dtor }, - IT_PASSIVE, + IT_FILE, PROTO_BIT__NONE, nullptr, "file", diff --git a/src/file_api/file_flows.h b/src/file_api/file_flows.h index 6816453c1..3656749af 100644 --- a/src/file_api/file_flows.h +++ b/src/file_api/file_flows.h @@ -29,7 +29,6 @@ #include "file_api.h" #include "file_module.h" -#include "file_policy.h" #include @@ -103,7 +102,13 @@ public: static unsigned file_flow_data_id; - void set_file_policy(FilePolicyBase* fp) { file_policy = fp; } + void set_file_policy(FilePolicyBase* fp) + { + assert(fp); + FilePolicyBase::delete_file_policy(file_policy); + fp->add_ref(); + file_policy = fp; + } FilePolicyBase* get_file_policy() { return file_policy; } private: diff --git a/src/file_api/file_lib.cc b/src/file_api/file_lib.cc index 8e4604e07..5d31fba6b 100644 --- a/src/file_api/file_lib.cc +++ b/src/file_api/file_lib.cc @@ -308,7 +308,7 @@ FileContext::FileContext () file_signature_context = nullptr; file_capture = nullptr; file_segments = nullptr; - inspector = (FileInspect*)InspectorManager::acquire(FILE_ID_NAME, true); + inspector = (FileInspect*)InspectorManager::acquire_file_inspector(); config = inspector->config; } @@ -392,7 +392,7 @@ void FileContext::finish_signature_lookup(Packet* p, bool final_lookup, FilePoli if (get_file_sig_sha256()) { verdict = policy->signature_lookup(p, this); - FILE_DEBUG(file_trace, DEFAULT_TRACE_OPTION_ID, TRACE_DEBUG_LEVEL, + FILE_DEBUG(file_trace, DEFAULT_TRACE_OPTION_ID, TRACE_DEBUG_LEVEL, p, "finish signature lookup verdict %d\n", verdict); if ( verdict != FILE_VERDICT_UNKNOWN || final_lookup ) { @@ -543,7 +543,7 @@ bool FileContext::process(Packet* p, const uint8_t* file_data, int data_size, /* file signature calculation */ if (is_file_signature_enabled()) { - FILE_DEBUG(file_trace, DEFAULT_TRACE_OPTION_ID, TRACE_DEBUG_LEVEL, p, + FILE_DEBUG(file_trace, DEFAULT_TRACE_OPTION_ID, TRACE_DEBUG_LEVEL, p, "file signature is enabled\n"); if (!sha256) process_file_signature_sha256(file_data, data_size, position); @@ -639,13 +639,13 @@ void FileContext::process_file_signature_sha256(const uint8_t* file_data, int da { if ((int64_t)processed_bytes + data_size > config->file_signature_depth) { - FILE_DEBUG(file_trace, DEFAULT_TRACE_OPTION_ID, TRACE_INFO_LEVEL, GET_CURRENT_PACKET, + FILE_DEBUG(file_trace, DEFAULT_TRACE_OPTION_ID, TRACE_INFO_LEVEL, GET_CURRENT_PACKET, "process_file_signature_sha256:FILE_SIG_DEPTH_FAIL\n"); file_state.sig_state = FILE_SIG_DEPTH_FAIL; return; } - FILE_DEBUG(file_trace, DEFAULT_TRACE_OPTION_ID, TRACE_DEBUG_LEVEL, GET_CURRENT_PACKET, + FILE_DEBUG(file_trace, DEFAULT_TRACE_OPTION_ID, TRACE_DEBUG_LEVEL, GET_CURRENT_PACKET, "processing file signature position: %d sig state %d \n", position, file_state.sig_state); switch (position) { @@ -654,7 +654,7 @@ void FileContext::process_file_signature_sha256(const uint8_t* file_data, int da file_signature_context = snort_calloc(sizeof(SHA256_CTX)); SHA256_Init((SHA256_CTX*)file_signature_context); SHA256_Update((SHA256_CTX*)file_signature_context, file_data, data_size); - FILE_DEBUG(file_trace, DEFAULT_TRACE_OPTION_ID, TRACE_DEBUG_LEVEL, GET_CURRENT_PACKET, + FILE_DEBUG(file_trace, DEFAULT_TRACE_OPTION_ID, TRACE_DEBUG_LEVEL, GET_CURRENT_PACKET, "position is start of file\n"); if (file_state.sig_state == FILE_SIG_FLUSH) { @@ -671,7 +671,7 @@ void FileContext::process_file_signature_sha256(const uint8_t* file_data, int da if (!file_signature_context) return; SHA256_Update((SHA256_CTX*)file_signature_context, file_data, data_size); - FILE_DEBUG(file_trace, DEFAULT_TRACE_OPTION_ID, TRACE_DEBUG_LEVEL, GET_CURRENT_PACKET, + FILE_DEBUG(file_trace, DEFAULT_TRACE_OPTION_ID, TRACE_DEBUG_LEVEL, GET_CURRENT_PACKET, "position is middle of the file\n"); if (file_state.sig_state == FILE_SIG_FLUSH) { @@ -693,7 +693,7 @@ void FileContext::process_file_signature_sha256(const uint8_t* file_data, int da sha256 = new uint8_t[SHA256_HASH_SIZE]; SHA256_Final(sha256, (SHA256_CTX*)file_signature_context); file_state.sig_state = FILE_SIG_DONE; - FILE_DEBUG(file_trace, DEFAULT_TRACE_OPTION_ID, TRACE_DEBUG_LEVEL, GET_CURRENT_PACKET, + FILE_DEBUG(file_trace, DEFAULT_TRACE_OPTION_ID, TRACE_DEBUG_LEVEL, GET_CURRENT_PACKET, "position is end of the file\n"); break; @@ -705,7 +705,7 @@ void FileContext::process_file_signature_sha256(const uint8_t* file_data, int da sha256 = new uint8_t[SHA256_HASH_SIZE]; SHA256_Final(sha256, (SHA256_CTX*)file_signature_context); file_state.sig_state = FILE_SIG_DONE; - FILE_DEBUG(file_trace, DEFAULT_TRACE_OPTION_ID, TRACE_DEBUG_LEVEL, GET_CURRENT_PACKET, + FILE_DEBUG(file_trace, DEFAULT_TRACE_OPTION_ID, TRACE_DEBUG_LEVEL, GET_CURRENT_PACKET, "position is full file\n"); break; @@ -747,9 +747,9 @@ void FileContext::update_file_size(int data_size, FilePosition position) { processed_bytes += data_size; - FILE_DEBUG(file_trace, DEFAULT_TRACE_OPTION_ID, TRACE_DEBUG_LEVEL, - GET_CURRENT_PACKET, - "Updating file size of file_id %lu at position %d with processed_bytes %lu\n", + FILE_DEBUG(file_trace, DEFAULT_TRACE_OPTION_ID, TRACE_DEBUG_LEVEL, + GET_CURRENT_PACKET, + "Updating file size of file_id %lu at position %d with processed_bytes %lu\n", file_id, position, processed_bytes); if ((position == SNORT_FILE_END)or (position == SNORT_FILE_FULL)) { diff --git a/src/file_api/file_module.cc b/src/file_api/file_module.cc index 931578a9c..49bb22d1b 100644 --- a/src/file_api/file_module.cc +++ b/src/file_api/file_module.cc @@ -82,48 +82,6 @@ static const Parameter file_rule_params[] = { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr } }; -// File policy -static const Parameter file_when_params[] = -{ - // FIXIT-M when.policy_id should be an arbitrary string auto converted - // into index for binder matching and lookups - { "file_type_id", Parameter::PT_INT, "0:max32", "0", - "unique ID for file type in file magic rule" }, - - { "sha256", Parameter::PT_STRING, nullptr, nullptr, - "SHA 256" }, - - { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr } -}; - -static const Parameter file_use_params[] = -{ - { "verdict", Parameter::PT_ENUM, "unknown | log | stop | block | reset ", "unknown", - "what to do with matching traffic" }, - - { "enable_file_type", Parameter::PT_BOOL, nullptr, "false", - "true/false -> enable/disable file type identification" }, - - { "enable_file_signature", Parameter::PT_BOOL, nullptr, "false", - "true/false -> enable/disable file signature" }, - - { "enable_file_capture", Parameter::PT_BOOL, nullptr, "false", - "true/false -> enable/disable file capture" }, - - { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr } -}; - -static const Parameter file_policy_rule_params[] = -{ - { "when", Parameter::PT_TABLE, file_when_params, nullptr, - "match criteria" }, - - { "use", Parameter::PT_TABLE, file_use_params, nullptr, - "target configuration" }, - - { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr } -}; - static const Parameter file_id_params[] = { { "type_depth", Parameter::PT_INT, "0:max53", "1460", @@ -159,24 +117,12 @@ static const Parameter file_id_params[] = { "max_files_per_flow", Parameter::PT_INT, "1:max53", "128", "maximal number of files able to be concurrently processed per flow" }, - { "enable_type", Parameter::PT_BOOL, nullptr, "true", - "enable type ID" }, - - { "enable_signature", Parameter::PT_BOOL, nullptr, "false", - "enable signature calculation" }, - - { "enable_capture", Parameter::PT_BOOL, nullptr, "false", - "enable file capture" }, - { "show_data_depth", Parameter::PT_INT, "0:max53", "100", "print this many octets" }, { "file_rules", Parameter::PT_LIST, file_rule_params, nullptr, "list of file magic rules" }, - { "file_policy", Parameter::PT_LIST, file_policy_rule_params, nullptr, - "list of file rules" }, - { "trace_type", Parameter::PT_BOOL, nullptr, "false", "enable runtime dump of type info" }, @@ -186,9 +132,6 @@ static const Parameter file_id_params[] = { "trace_stream", Parameter::PT_BOOL, nullptr, "false", "enable runtime dump of file data" }, - { "verdict_delay", Parameter::PT_INT, "0:max53", "0", - "number of queries to return final verdict" }, - { "b64_decode_depth", Parameter::PT_INT, "-1:65535", "-1", "base64 decoding depth (-1 no limit)" }, @@ -271,8 +214,6 @@ bool FileIdModule::set(const char*, Value& v, SnortConfig*) if (!fc) fc = new FileConfig; - FilePolicy& fp = fc->get_file_policy(); - if ( v.is("type_depth") ) fc->file_type_depth = v.get_int64(); @@ -306,23 +247,6 @@ bool FileIdModule::set(const char*, Value& v, SnortConfig*) else if ( v.is("max_files_per_flow") ) fc->max_files_per_flow = v.get_uint64(); - else if ( v.is("enable_type") ) - { - fp.set_file_type(v.get_bool()); - } - else if ( v.is("enable_signature") ) - { - fp.set_file_signature(v.get_bool()); - } - else if ( v.is("enable_capture") ) - { - if (v.get_bool() and Snort::is_reloading() and !FileService::is_file_capture_enabled()) - { - ReloadError("Changing file_id.enable_capture requires a restart.\n"); - return false; - } - fp.set_file_capture(v.get_bool()); - } else if ( v.is("show_data_depth") ) fc->show_data_depth = v.get_int64(); @@ -335,11 +259,6 @@ bool FileIdModule::set(const char*, Value& v, SnortConfig*) else if ( v.is("trace_stream") ) fc->trace_stream = v.get_bool(); - else if ( v.is("verdict_delay") ) - { - fc->verdict_delay = v.get_int64(); - fp.set_verdict_delay(fc->verdict_delay); - } else if ( v.is("decompress_pdf") ) FileService::decode_conf.set_decompress_pdf(v.get_bool()); @@ -377,9 +296,6 @@ bool FileIdModule::set(const char*, Value& v, SnortConfig*) FileService::decode_conf.set_uu_depth(mime); } - else if ( v.is("file_rules") ) - return true; - else if ( v.is("rev") ) rule.rev = v.get_uint32(); @@ -408,53 +324,12 @@ bool FileIdModule::set(const char*, Value& v, SnortConfig*) else if ( v.is("version") ) rule.version = v.get_string(); - else if ( v.is("magic") ) - return true; - else if ( v.is("content") ) magic.content_str = v.get_string(); else if ( v.is("offset") ) magic.offset = v.get_uint32(); - else if ( v.is("file_policy") ) - return true; - - else if ( v.is("when") ) - return true; - - else if ( v.is("file_type_id") ) - file_rule.when.type_id = v.get_uint32(); - - else if ( v.is("sha256") ) - file_rule.when.sha256 = v.get_string(); - - else if ( v.is("use") ) - return true; - - else if ( v.is("verdict") ) - { - file_rule.use.verdict = (FileVerdict)v.get_uint8(); - if (file_rule.use.verdict == FileVerdict::FILE_VERDICT_REJECT) - need_active = true; - } - - else if ( v.is("enable_file_type") ) - file_rule.use.type_enabled = v.get_bool(); - - else if ( v.is("enable_file_signature") ) - file_rule.use.signature_enabled = v.get_bool(); - - else if ( v.is("enable_file_capture") ) - { - file_rule.use.capture_enabled = v.get_bool(); - if (file_rule.use.capture_enabled && Snort::is_reloading() - && !FileService::is_file_capture_enabled()) - { - ReloadError("Changing file_id.enable_file_capture requires a restart.\n"); - return false; - } - } return true; } @@ -471,10 +346,6 @@ bool FileIdModule::begin(const char* fqn, int idx, SnortConfig*) { magic.clear(); } - else if ( !strcmp(fqn, "file_id.file_policy") ) - { - file_rule.clear(); - } return true; } @@ -493,10 +364,6 @@ bool FileIdModule::end(const char* fqn, int idx, SnortConfig*) fc->process_file_magic(magic); rule.file_magics.emplace_back(magic); } - else if ( !strcmp(fqn, "file_id.file_policy") ) - { - fc->process_file_policy_rule(file_rule); - } return true; } @@ -504,12 +371,7 @@ bool FileIdModule::end(const char* fqn, int idx, SnortConfig*) void FileIdModule::load_config(FileConfig*& dst) { dst = fc; - - if (fc) - { - fc->get_file_policy().load(); - fc = nullptr; - } + fc = nullptr; } void FileIdModule::show_dynamic_stats() diff --git a/src/file_api/file_module.h b/src/file_api/file_module.h index b5d86d93b..000e37017 100644 --- a/src/file_api/file_module.h +++ b/src/file_api/file_module.h @@ -26,7 +26,6 @@ #include "file_config.h" #include "file_identifier.h" -#include "file_policy.h" #include "main/snort_debug.h" #include "utils/util.h" //------------------------------------------------------------------------- @@ -76,9 +75,7 @@ public: private: FileMagicRule rule; FileMagicData magic; - FileRule file_rule; FileConfig *fc = nullptr; - bool need_active = false; }; enum FileSid diff --git a/src/file_api/file_service.h b/src/file_api/file_service.h index 6ec083423..f96288002 100644 --- a/src/file_api/file_service.h +++ b/src/file_api/file_service.h @@ -24,7 +24,6 @@ // This provides a wrapper to start/stop file service -#include "file_api/file_policy.h" #include "main/snort_config.h" #include "main/snort_types.h" #include "mime/file_mime_config.h" diff --git a/src/framework/CMakeLists.txt b/src/framework/CMakeLists.txt index 6499cc522..a4afae34f 100644 --- a/src/framework/CMakeLists.txt +++ b/src/framework/CMakeLists.txt @@ -31,6 +31,7 @@ add_library ( framework OBJECT codec.cc cursor.cc data_bus.cc + file_policy.cc inspector.cc ips_option.cc packet_constraints.cc diff --git a/src/file_api/file_policy.cc b/src/framework/file_policy.cc similarity index 97% rename from src/file_api/file_policy.cc rename to src/framework/file_policy.cc index af81d0bba..cd8ca57aa 100644 --- a/src/file_api/file_policy.cc +++ b/src/framework/file_policy.cc @@ -22,14 +22,13 @@ #include "config.h" #endif -#include "file_policy.h" +#include "framework/file_policy.h" +#include "file_api/file_capture.h" +#include "file_api/file_lib.h" +#include "file_api/file_service.h" #include "hash/hashes.h" -#include "file_capture.h" -#include "file_lib.h" -#include "file_service.h" - using namespace snort; static FileRule emptyRule; diff --git a/src/file_api/file_policy.h b/src/framework/file_policy.h similarity index 98% rename from src/file_api/file_policy.h rename to src/framework/file_policy.h index a0c3164a8..d166505d4 100644 --- a/src/file_api/file_policy.h +++ b/src/framework/file_policy.h @@ -23,7 +23,7 @@ #include #include -#include "file_api.h" +#include "file_api/file_api.h" namespace snort { @@ -88,7 +88,6 @@ private: bool signature_enabled = false; bool capture_enabled = false; int64_t verdict_delay = 0; - }; #endif diff --git a/src/framework/inspector.cc b/src/framework/inspector.cc index 636a37330..ca8341e74 100644 --- a/src/framework/inspector.cc +++ b/src/framework/inspector.cc @@ -136,6 +136,7 @@ static const char* InspectorTypeNames[IT_MAX] = "service", "control", "probe", + "file", }; const char* InspectApi::get_type(InspectorType type) diff --git a/src/framework/inspector.h b/src/framework/inspector.h index bb88bad8d..0dc3804c3 100644 --- a/src/framework/inspector.h +++ b/src/framework/inspector.h @@ -194,6 +194,7 @@ enum InspectorType IT_SERVICE, // extract and analyze service PDUs (eg dce, http, ssl) IT_CONTROL, // process all packets before detection (eg appid) IT_PROBE, // process all packets after detection (eg perf_monitor, port_scan) + IT_FILE, // file identification inspector IT_MAX }; diff --git a/src/framework/module.cc b/src/framework/module.cc index 3c9f5adbd..a1b39f4a7 100644 --- a/src/framework/module.cc +++ b/src/framework/module.cc @@ -176,6 +176,7 @@ void Module::reset_stats() PegCount Module::get_global_count(const char* name) const { const PegInfo* infos = get_pegs(); + assert(infos); for ( unsigned i = 0; infos[i].name; i++ ) { diff --git a/src/framework/policy_selector.h b/src/framework/policy_selector.h index 1be0b480d..4f420a27a 100644 --- a/src/framework/policy_selector.h +++ b/src/framework/policy_selector.h @@ -79,7 +79,7 @@ public: if (ps) ps->get_api()->dtor(ps); } - const PolicySelectorApi* get_api() + const PolicySelectorApi* get_api() const { return api; } virtual bool select_default_policies(const _daq_pkt_hdr*, const SnortConfig*) = 0; virtual void show() const = 0; diff --git a/src/log/log.cc b/src/log/log.cc index c9d9b9b7d..e1a23f6d5 100644 --- a/src/log/log.cc +++ b/src/log/log.cc @@ -83,7 +83,8 @@ FILE* OpenAlertFile(const char* filearg) FatalError("OpenAlertFile() => fopen() alert file %s: %s\n", filename, get_error(errno)); } - setvbuf(file, (char*)nullptr, _IOLBF, (size_t)0); + else + setvbuf(file, (char*)nullptr, _IOLBF, (size_t)0); return file; } diff --git a/src/main/help.cc b/src/main/help.cc index 6b6975716..6497d3170 100644 --- a/src/main/help.cc +++ b/src/main/help.cc @@ -256,7 +256,7 @@ void config_markup(SnortConfig*, const char*) fprintf(stdout, "max31 = 2147483647\n"); fprintf(stdout, "max32 = 4294967295\n"); fprintf(stdout, "max53 = 9007199254740992\n"); - fprintf(stdout, "maxSZ = %zu\n", (sizeof(size_t) == 4) ? 4294967295 : 9007199254740992); + fprintf(stdout, "maxSZ = %lu\n", (sizeof(size_t) == 4) ? 4294967295LU : 9007199254740992LU); exit(0); } diff --git a/src/main/modules.cc b/src/main/modules.cc index cd5b9f039..dec205545 100644 --- a/src/main/modules.cc +++ b/src/main/modules.cc @@ -31,12 +31,14 @@ #include "detection/fp_config.h" #include "detection/rules.h" #include "detection/tag.h" +#include "file_api/file_service.h" #include "filters/detection_filter.h" #include "filters/rate_filter.h" #include "filters/sfrf.h" #include "filters/sfthd.h" #include "filters/sfthreshold.h" #include "flow/ha_module.h" +#include "framework/file_policy.h" #include "framework/module.h" #include "host_tracker/host_tracker_module.h" #include "host_tracker/host_cache_module.h" @@ -1051,6 +1053,7 @@ class NetworkModule : public Module public: NetworkModule() : Module("network", network_help, network_params) { } bool set(const char*, Value&, SnortConfig*) override; + bool end(const char*, int, SnortConfig*) override; Usage get_usage() const override { return CONTEXT; } @@ -1067,10 +1070,7 @@ bool NetworkModule::set(const char*, Value& v, SnortConfig* sc) ConfigChecksumMode(v.get_string()); else if ( v.is("id") ) - { p->user_policy_id = v.get_uint16(); - sc->policy_map->set_user_network(p); - } else if ( v.is("min_ttl") ) p->min_ttl = v.get_uint8(); @@ -1090,6 +1090,16 @@ bool NetworkModule::set(const char*, Value& v, SnortConfig* sc) return true; } +bool NetworkModule::end(const char*, int idx, SnortConfig* sc) +{ + if (!idx) + { + NetworkPolicy* p = get_network_policy(); + sc->policy_map->set_user_network(p); + } + return true; +} + //------------------------------------------------------------------------- // inspection policy module //------------------------------------------------------------------------- @@ -1122,6 +1132,7 @@ class InspectionModule : public Module public: InspectionModule() : Module("inspection", inspection_help, inspection_params) { } bool set(const char*, Value&, SnortConfig*) override; + bool end(const char*, int, SnortConfig*) override; Usage get_usage() const override { return INSPECT; } @@ -1132,10 +1143,7 @@ bool InspectionModule::set(const char*, Value& v, SnortConfig* sc) InspectionPolicy* p = get_inspection_policy(); if ( v.is("id") ) - { p->user_policy_id = v.get_uint16(); - sc->policy_map->set_user_inspection(p); - } #ifdef HAVE_UUID else if ( v.is("uuid") ) @@ -1164,13 +1172,18 @@ bool InspectionModule::set(const char*, Value& v, SnortConfig* sc) } else if ( v.is("max_aux_ip") ) - { sc->max_aux_ip = v.get_int16(); - return true; - } return true; } + +bool InspectionModule::end(const char*, int, SnortConfig* sc) +{ + InspectionPolicy* p = get_inspection_policy(); + sc->policy_map->set_user_inspection(p); + return true; +} + //------------------------------------------------------------------------- // Ips policy module //------------------------------------------------------------------------- @@ -1284,7 +1297,7 @@ private: bool IpsModule::matches(const char*, std::string&) { return true; } -bool IpsModule::set(const char* fqn, Value& v, SnortConfig* sc) +bool IpsModule::set(const char* fqn, Value& v, SnortConfig*) { IpsPolicy* p = get_ips_policy(); @@ -1298,10 +1311,7 @@ bool IpsModule::set(const char* fqn, Value& v, SnortConfig* sc) p->enable_builtin_rules = v.get_bool(); else if ( v.is("id") ) - { p->user_policy_id = v.get_uint16(); - sc->policy_map->set_user_ips(p); - } else if ( v.is("include") ) p->include = v.get_string(); @@ -1351,7 +1361,7 @@ bool IpsModule::set(const char* fqn, Value& v, SnortConfig* sc) return true; } -bool IpsModule::end(const char* fqn, int idx, SnortConfig*) +bool IpsModule::end(const char* fqn, int idx, SnortConfig* sc) { if ( idx and !strcmp(fqn, "ips.action_map") ) { @@ -1367,6 +1377,11 @@ bool IpsModule::end(const char* fqn, int idx, SnortConfig*) replace.clear(); with.clear(); } + else if (!idx and !strcmp(fqn, "ips")) + { + IpsPolicy* p = get_ips_policy(); + sc->policy_map->set_user_ips(p); + } return true; } @@ -1996,6 +2011,155 @@ bool HostsModule::end(const char* fqn, int idx, SnortConfig* sc) return true; } +//------------------------------------------------------------------------- +// File policy module +//------------------------------------------------------------------------- + +static const Parameter file_when_params[] = +{ + // FIXIT-M when.policy_id should be an arbitrary string auto converted + // into index for binder matching and lookups + { "file_type_id", Parameter::PT_INT, "0:max32", "0", + "unique ID for file type in file magic rule" }, + + { "sha256", Parameter::PT_STRING, nullptr, nullptr, + "SHA 256" }, + + { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr } +}; + +static const Parameter file_use_params[] = +{ + { "verdict", Parameter::PT_ENUM, "unknown | log | stop | block | reset ", "unknown", + "what to do with matching traffic" }, + + { "enable_file_type", Parameter::PT_BOOL, nullptr, "false", + "true/false -> enable/disable file type identification" }, + + { "enable_file_signature", Parameter::PT_BOOL, nullptr, "false", + "true/false -> enable/disable file signature" }, + + { "enable_file_capture", Parameter::PT_BOOL, nullptr, "false", + "true/false -> enable/disable file capture" }, + + { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr } +}; + +static const Parameter file_policy_rule_params[] = +{ + { "when", Parameter::PT_TABLE, file_when_params, nullptr, + "match criteria" }, + + { "use", Parameter::PT_TABLE, file_use_params, nullptr, + "target configuration" }, + + { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr } +}; + +static const Parameter file_policy_params[] = +{ + { "enable_type", Parameter::PT_BOOL, nullptr, "true", + "enable type ID" }, + + { "enable_signature", Parameter::PT_BOOL, nullptr, "false", + "enable signature calculation" }, + + { "enable_capture", Parameter::PT_BOOL, nullptr, "false", + "enable file capture" }, + + { "verdict_delay", Parameter::PT_INT, "0:max53", "0", + "number of queries to return final verdict" }, + + { "rules", Parameter::PT_LIST, file_policy_rule_params, nullptr, + "list of file rules" }, + + { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr } +}; + + +#define file_policy_help "configure file policy" + +class FilePolicyModule : public Module +{ +public: + FilePolicyModule() : Module("file_policy", file_policy_help, file_policy_params) + { } + bool begin(const char*, int, SnortConfig*) override; + bool set(const char*, Value&, SnortConfig*) override; + bool end(const char*, int, SnortConfig*) override; + +private: + FileRule file_rule; +}; + +bool FilePolicyModule::begin(const char* fqn, int idx, SnortConfig*) +{ + if (idx && !strcmp(fqn, "file_policy.rules")) + file_rule.clear(); + return true; +} + +bool FilePolicyModule::set(const char*, Value& v, SnortConfig*) +{ + FilePolicy* fp = get_network_policy()->get_file_policy(); + if ( v.is("file_type_id") ) + file_rule.when.type_id = v.get_uint32(); + + else if ( v.is("sha256") ) + file_rule.when.sha256 = v.get_string(); + + else if ( v.is("verdict") ) + file_rule.use.verdict = (FileVerdict)v.get_uint8(); + + else if ( v.is("enable_file_type") ) + file_rule.use.type_enabled = v.get_bool(); + + else if ( v.is("enable_file_signature") ) + file_rule.use.signature_enabled = v.get_bool(); + + else if ( v.is("enable_file_capture") ) + { + file_rule.use.capture_enabled = v.get_bool(); + if (file_rule.use.capture_enabled && Snort::is_reloading() + && !FileService::is_file_capture_enabled()) + { + ReloadError("Changing file_id.enable_file_capture requires a restart.\n"); + return false; + } + } + + else if ( v.is("enable_type") ) + fp->set_file_type(v.get_bool()); + + else if ( v.is("enable_signature") ) + fp->set_file_signature(v.get_bool()); + + else if ( v.is("enable_capture") ) + { + if (v.get_bool() and Snort::is_reloading() and !FileService::is_file_capture_enabled()) + { + ReloadError("Changing file_id.enable_capture requires a restart.\n"); + return false; + } + fp->set_file_capture(v.get_bool()); + } + + else if ( v.is("verdict_delay") ) + fp->set_verdict_delay(v.get_int64()); + + return true; +} + +bool FilePolicyModule::end(const char* fqn, int idx, SnortConfig*) +{ + if (!idx) + get_network_policy()->get_file_policy()->load(); + if (idx && !strcmp(fqn, "file_policy.rules")) + get_network_policy()->add_file_policy_rule(file_rule); + + return true; +} + //------------------------------------------------------------------------- // module manager stuff - move to framework/module_manager.cc //------------------------------------------------------------------------- @@ -2045,6 +2209,7 @@ void module_init() ModuleManager::add_module(new NetworkModule); ModuleManager::add_module(new InspectionModule); ModuleManager::add_module(new IpsModule); + ModuleManager::add_module(new FilePolicyModule); // these modules replace config and hosts.xml ModuleManager::add_module(new AttributeTableModule); diff --git a/src/main/policy.cc b/src/main/policy.cc index 8213f7e00..7680beea9 100644 --- a/src/main/policy.cc +++ b/src/main/policy.cc @@ -27,6 +27,7 @@ #include "actions/actions.h" #include "detection/detection_engine.h" +#include "framework/file_policy.h" #include "framework/policy_selector.h" #include "log/messages.h" #include "managers/inspector_manager.h" @@ -52,10 +53,14 @@ NetworkPolicy::NetworkPolicy(NetworkPolicy* other_network_policy, const char* ex { init(other_network_policy, exclude_name); } NetworkPolicy::~NetworkPolicy() -{ InspectorManager::delete_policy(this, cloned); } +{ + FilePolicyBase::delete_file_policy(file_policy); + InspectorManager::delete_policy(this, cloned); +} void NetworkPolicy::init(NetworkPolicy* other_network_policy, const char* exclude_name) { + file_policy = new FilePolicy; if (other_network_policy) { dbus.clone(other_network_policy->dbus, exclude_name); @@ -73,6 +78,14 @@ void NetworkPolicy::init(NetworkPolicy* other_network_policy, const char* exclud InspectorManager::new_policy(this, other_network_policy); } +FilePolicyBase* NetworkPolicy::get_base_file_policy() const +{ return file_policy; } +FilePolicy* NetworkPolicy::get_file_policy() const +{ return file_policy; } + +void NetworkPolicy::add_file_policy_rule(FileRule& file_rule) +{ file_policy->insert_file_rule(file_rule); } + //------------------------------------------------------------------------- // inspection policy //------------------------------------------------------------------------- @@ -167,6 +180,9 @@ PolicyMap::PolicyMap(PolicyMap* other_map, const char* exclude_name) clone(other_map, exclude_name); else { + file_id = InspectorManager::create_single_instance_inspector_policy(); + flow_tracking = InspectorManager::create_single_instance_inspector_policy(); + global_inspector_policy = InspectorManager::create_global_inspector_policy(); add_shell(new Shell(nullptr, true), true); empty_ips_policy = new IpsPolicy(ips_policy.size()); ips_policy.push_back(empty_ips_policy); @@ -208,8 +224,13 @@ PolicyMap::~PolicyMap() for ( auto p : network_policy ) delete p; + InspectorManager::destroy_single_instance_inspector(flow_tracking); + InspectorManager::destroy_single_instance_inspector(file_id); } + PolicySelector::free_policy_selector(selector); + InspectorManager::destroy_global_inspector_policy(global_inspector_policy, cloned); + shells.clear(); inspection_policy.clear(); ips_policy.clear(); @@ -219,6 +240,10 @@ PolicyMap::~PolicyMap() void PolicyMap::clone(PolicyMap *other_map, const char* exclude_name) { + global_inspector_policy = + InspectorManager::create_global_inspector_policy(other_map->global_inspector_policy); + file_id = other_map->file_id; + flow_tracking = other_map->flow_tracking; shells = other_map->shells; ips_policy = other_map->ips_policy; empty_ips_policy = other_map->empty_ips_policy; @@ -423,7 +448,8 @@ void set_default_policy(const SnortConfig* sc) void select_default_policy(const _daq_pkt_hdr* pkthdr, const SnortConfig* sc) { - if (!sc->global_selector || !sc->global_selector->select_default_policies(pkthdr, sc)) + PolicySelector* ps = sc->policy_map->get_policy_selector(); + if (!ps || !ps->select_default_policies(pkthdr, sc)) { set_network_policy(sc->policy_map->get_network_policy(0)); set_inspection_policy(sc->policy_map->get_inspection_policy(0)); diff --git a/src/main/policy.h b/src/main/policy.h index 38f4b0d20..1dbd08117 100644 --- a/src/main/policy.h +++ b/src/main/policy.h @@ -42,8 +42,10 @@ typedef unsigned char uuid_t[16]; namespace snort { +class FilePolicyBase; class GHash; class IpsAction; +class PolicySelector; struct SnortConfig; } @@ -87,6 +89,9 @@ enum DecodeEventFlag // Snort ac-split creates the nap (network analysis policy) // Snort++ breaks the nap into network and inspection +class FilePolicy; +class FileRule; + struct NetworkPolicy { public: @@ -94,6 +99,10 @@ public: NetworkPolicy(NetworkPolicy*, const char*); ~NetworkPolicy(); + void add_file_policy_rule(FileRule& file_rule); + snort::FilePolicyBase* get_base_file_policy() const; + FilePolicy* get_file_policy() const; + bool checksum_drops(uint16_t codec_cksum_err_flag) { return (checksum_drop & codec_cksum_err_flag) != 0; } @@ -109,6 +118,9 @@ public: bool icmp_checksums() { return (checksum_eval & CHECKSUM_FLAG__ICMP) != 0; } +protected: + FilePolicy* file_policy; + public: struct TrafficPolicy* traffic_policy; snort::DataBus dbus; @@ -221,6 +233,9 @@ struct PolicyTuple inspection(ins_pol), ips(ips_pol), network(net_pol) { } }; +struct GlobalInspectorPolicy; +class SingleInstanceInspectorPolicy; + class PolicyMap { public: @@ -290,6 +305,21 @@ public: void set_cloned(bool state) { cloned = state; } + snort::PolicySelector* get_policy_selector() const + { return selector; } + + void set_policy_selector(snort::PolicySelector* new_selector) + { selector = new_selector; } + + SingleInstanceInspectorPolicy* get_file_id() + { return file_id; } + + SingleInstanceInspectorPolicy* get_flow_tracking() + { return flow_tracking; } + + GlobalInspectorPolicy* get_global_inspector_policy() + { return global_inspector_policy; } + const Shell* get_shell_by_policy(unsigned id) const { auto it = std::find_if(std::begin(shell_map), std::end(shell_map), @@ -311,6 +341,11 @@ private: std::unordered_map user_inspection; std::unordered_map user_ips; + snort::PolicySelector* selector = nullptr; + SingleInstanceInspectorPolicy* file_id; + SingleInstanceInspectorPolicy* flow_tracking; + GlobalInspectorPolicy* global_inspector_policy; + bool cloned = false; }; diff --git a/src/main/snort_config.cc b/src/main/snort_config.cc index aab108c3a..5d379a669 100644 --- a/src/main/snort_config.cc +++ b/src/main/snort_config.cc @@ -275,8 +275,6 @@ SnortConfig::~SnortConfig() if ( plugins ) delete plugins; delete payload_injector_config; - InspectorManager::free_flow_tracking(flow_tracking); - PolicySelector::free_policy_selector(global_selector); clear_reload_resource_tuner_list(); trim_heap(); diff --git a/src/main/snort_config.h b/src/main/snort_config.h index 8e0bc59d7..ecacaa642 100644 --- a/src/main/snort_config.h +++ b/src/main/snort_config.h @@ -149,7 +149,6 @@ struct IpsActionsConfig; struct LatencyConfig; struct MemoryConfig; struct PayloadInjectorConfig; -struct PHInstance; struct Plugins; struct PORT_RULE_MAP; struct RateFilterConfig; @@ -163,7 +162,6 @@ struct ThresholdConfig; namespace snort { class GHash; -class PolicySelector; class ProtocolReference; class ThreadConfig; class XHash; @@ -394,10 +392,6 @@ public: PolicyMap* policy_map = nullptr; std::string tweaks; - PolicySelector* global_selector = nullptr; - PHInstance* flow_tracking = nullptr; - PHInstance* removed_flow_tracking = nullptr; - uint16_t tunnel_mask = 0; int16_t max_aux_ip = 16; diff --git a/src/managers/inspector_manager.cc b/src/managers/inspector_manager.cc index 7f03987d2..5eca04b48 100644 --- a/src/managers/inspector_manager.cc +++ b/src/managers/inspector_manager.cc @@ -137,6 +137,9 @@ struct PHInstance ReloadType get_reload_type() { return reload_type; } + + void tinit(); + void tterm(); }; PHInstance::PHInstance(PHClass& p, SnortConfig* sc, Module* mod) : pp_class(p) @@ -224,8 +227,56 @@ struct InspectorList virtual void handle_new_reenabled(SnortConfig*, bool, bool) = 0; virtual void vectorize(SnortConfig*) = 0; + + void tinit(); + void tterm(); + void tterm_removed(); + + void populate_removed(SnortConfig*, InspectorList*); + void clear_removed(); }; +void InspectorList::tinit() +{ + for ( auto* p : ilist ) + p->tinit(); +} + +void InspectorList::tterm() +{ + for ( auto* p : ilist ) + p->tterm(); +} + +void InspectorList::tterm_removed() +{ + for ( auto* p : removed_ilist ) + p->tterm(); +} + +static PHInstance* get_instance(InspectorList* il, const char* keyword); + +void InspectorList::populate_removed(SnortConfig* sc, InspectorList* old) +{ + for (auto it = old->ilist.begin(); it != old->ilist.end(); ++it) + { + PHInstance* instance = get_instance(this, (*it)->name.c_str()); + if (!instance) + { + removed_ilist.emplace_back(*it); + (*it)->handler->add_global_ref(); + (*it)->handler->tear_down(sc); + } + } +} + +void InspectorList::clear_removed() +{ + for ( auto* p : removed_ilist ) + p->handler->rem_global_ref(); + removed_ilist.clear(); +} + struct TrafficPolicy : public InspectorList { PHVector passive; @@ -266,8 +317,148 @@ void TrafficPolicy::vectorize(SnortConfig*) break; default: - ParseError("Network policy (context usage) does not handle %s inspector type\n", - InspectApi::get_type(p->pp_class.api.type)); + ParseError( + "Network policy (context usage) does not handle inspector %s with type %s\n", + p->pp_class.api.base.name, InspectApi::get_type(p->pp_class.api.type)); + break; + } + } +} + +class SingleInstanceInspectorPolicy +{ +public: + SingleInstanceInspectorPolicy() = default; + ~SingleInstanceInspectorPolicy(); + + bool get_new(SnortConfig*, Module*, PHClass&, PHInstance*&); + void populate_removed(SnortConfig*, SingleInstanceInspectorPolicy*); + void clear_removed(); + void configure(SnortConfig*); + void tinit(); + void tterm(); + void tterm_removed(); + void print_config(SnortConfig*, const char* title); + + PHInstance* instance = nullptr; + PHInstance* removed_instance = nullptr; +}; + +SingleInstanceInspectorPolicy::~SingleInstanceInspectorPolicy() +{ + if (instance) + { + if ( IT_PASSIVE == instance->handler->get_api()->type ) + s_trash2.emplace_back(instance->handler); + else + s_trash.emplace_back(instance->handler); + + delete instance; + } + assert(nullptr == removed_instance); +} + +bool SingleInstanceInspectorPolicy::get_new(SnortConfig*sc, Module* mod, PHClass& pc, + PHInstance*& ppi) +{ + if (instance) + return false; + ppi = new PHInstance(pc, sc, mod); + if ( ppi->handler ) + instance = ppi; + else + { + delete ppi; + ppi = nullptr; + } + return true; +} + +void SingleInstanceInspectorPolicy::populate_removed(SnortConfig* sc, + SingleInstanceInspectorPolicy* old) +{ + if (old->instance && !instance) + { + removed_instance = old->instance; + removed_instance->handler->add_global_ref(); + removed_instance->handler->tear_down(sc); + } +} + +void SingleInstanceInspectorPolicy::clear_removed() +{ + if (removed_instance) + { + removed_instance->handler->rem_global_ref(); + removed_instance = nullptr; + } +} + +void SingleInstanceInspectorPolicy::configure(SnortConfig* sc) +{ + if (instance) + instance->handler->configure(sc); +} + +void SingleInstanceInspectorPolicy::tinit() +{ + if (instance) + instance->tinit(); +} + +void SingleInstanceInspectorPolicy::tterm() +{ + if (instance) + instance->tterm(); +} + +void SingleInstanceInspectorPolicy::tterm_removed() +{ + if (removed_instance) + removed_instance->tterm(); +} + +void SingleInstanceInspectorPolicy::print_config(SnortConfig* sc, const char* title) +{ + if (instance) + { + LogLabel(title); + const std::string name = InspectorManager::generate_inspector_label(instance); + LogLabel(name.c_str()); + instance->handler->show(sc); + } +} + +struct GlobalInspectorPolicy : public InspectorList +{ + PHVector passive; + PHVector probe; + + void handle_new_reenabled(SnortConfig*, bool, bool) override + { } + void vectorize(SnortConfig*) override; +}; + +void GlobalInspectorPolicy::vectorize(SnortConfig*) +{ + passive.alloc(ilist.size()); + probe.alloc(ilist.size()); + for ( auto* p : ilist ) + { + switch ( p->pp_class.api.type ) + { + case IT_PASSIVE: + passive.add(p); + break; + + case IT_PROBE: + probe.add(p); + break; + + default: + ParseError( + "Global inspector policy (global usage) does not handle inspector %s with type %s\n", + p->pp_class.api.base.name, InspectApi::get_type(p->pp_class.api.type)); break; } } @@ -279,7 +470,6 @@ struct FrameworkPolicy : public InspectorList PHVector packet; PHVector network; PHVector service; - PHVector probe; Inspector* binder; Inspector* wizard; @@ -293,6 +483,7 @@ struct FrameworkPolicy : public InspectorList void vectorize(SnortConfig*) override; void add_inspector_to_cache(PHInstance*, SnortConfig*); void remove_inspector_from_cache(Inspector*); + bool delete_inspector(SnortConfig*, const char* iname); }; void FrameworkPolicy::add_inspector_to_cache(PHInstance* p, SnortConfig* sc) @@ -361,7 +552,6 @@ void FrameworkPolicy::vectorize(SnortConfig* sc) packet.alloc(ilist.size()); network.alloc(ilist.size()); service.alloc(ilist.size()); - probe.alloc(ilist.size()); for ( auto* p : ilist ) { @@ -393,17 +583,9 @@ void FrameworkPolicy::vectorize(SnortConfig* sc) wizard = p->handler; break; - case IT_PROBE: - { - // probes always run - // add them to default so they can be found on InspectorManager::probe - sc->policy_map->get_inspection_policy(0)->framework_policy->probe.add(p); - break; - } - default: - ParseError("Inspection policy does not handle %s inspector type\n", - InspectApi::get_type(p->pp_class.api.type)); + ParseError("Inspection policy does not handle inspector %s with type %s\n", + p->pp_class.api.base.name, InspectApi::get_type(p->pp_class.api.type)); break; } } @@ -414,10 +596,26 @@ void FrameworkPolicy::vectorize(SnortConfig* sc) for ( auto* p : ilist ) add_inspector_to_cache(p, sc); - if ( !binder and (sc->flow_tracking or wizard) ) + if ( !binder and (sc->policy_map->get_flow_tracking()->instance or wizard) ) instantiate_default_binder(sc, this); } +bool FrameworkPolicy::delete_inspector(SnortConfig* sc, const char* iname) +{ + std::vector::iterator old_it; + if ( get_instance(this, iname, old_it) ) + { + (*old_it)->set_reloaded(RELOAD_TYPE_DELETED); + remove_inspector_from_cache((*old_it)->handler); + ilist.erase(old_it); + std::vector::iterator bind_it; + if ( get_instance(this, bind_id, bind_it) ) + (*bind_it)->handler->remove_inspector_binding(sc, iname); + return true; + } + return false; +} + //------------------------------------------------------------------------- // global stuff //------------------------------------------------------------------------- @@ -531,8 +729,38 @@ void InspectorManager::empty_trash() // policy stuff //------------------------------------------------------------------------- -static bool get_instance( - InspectorList* il, const char* keyword, +SingleInstanceInspectorPolicy* InspectorManager::create_single_instance_inspector_policy() +{ return new SingleInstanceInspectorPolicy; } + +void InspectorManager::destroy_single_instance_inspector(SingleInstanceInspectorPolicy* p) +{ delete p; } + +GlobalInspectorPolicy* InspectorManager::create_global_inspector_policy(GlobalInspectorPolicy* other_pp) +{ + GlobalInspectorPolicy* pp = new GlobalInspectorPolicy; + + if ( other_pp ) + pp->ilist = other_pp->ilist; + + return pp; +} + +void InspectorManager::destroy_global_inspector_policy(GlobalInspectorPolicy* pp, bool cloned) +{ + for ( auto* p : pp->ilist ) + { + if ( cloned and !(p->is_reloaded()) ) + continue; + if ( IT_PASSIVE == p->handler->get_api()->type ) + s_trash2.emplace_back(p->handler); + else + s_trash.emplace_back(p->handler); + delete p; + } + delete pp; +} + +static bool get_instance(InspectorList* il, const char* keyword, std::vector::iterator& it) { for ( it = il->ilist.begin(); it != il->ilist.end(); ++it ) @@ -649,6 +877,9 @@ void InspectorManager::delete_policy(NetworkPolicy* pi, bool cloned) void InspectorManager::update_policy(SnortConfig* sc) { + GlobalInspectorPolicy* pp = sc->policy_map->get_global_inspector_policy(); + for ( auto* p : pp->ilist ) + p->set_reloaded(RELOAD_TYPE_NONE); InspectionPolicy* ip = sc->policy_map->get_inspection_policy(); for ( auto* p : ip->framework_policy->ilist ) p->set_reloaded(RELOAD_TYPE_NONE); @@ -669,55 +900,47 @@ Binder* InspectorManager::get_binder() void InspectorManager::clear_removed_inspectors(SnortConfig* sc) { - if (sc->removed_flow_tracking) - { - sc->removed_flow_tracking->handler->rem_global_ref(); - sc->removed_flow_tracking = nullptr; - } + SingleInstanceInspectorPolicy* fid = sc->policy_map->get_file_id(); + fid->clear_removed(); + SingleInstanceInspectorPolicy* ft = sc->policy_map->get_flow_tracking(); + ft->clear_removed(); + GlobalInspectorPolicy* pp = sc->policy_map->get_global_inspector_policy(); + pp->clear_removed(); TrafficPolicy* tp = sc->policy_map->get_network_policy()->traffic_policy; - for ( auto* p : tp->removed_ilist ) - p->handler->rem_global_ref(); - tp->removed_ilist.clear(); + tp->clear_removed(); FrameworkPolicy* fp = sc->policy_map->get_inspection_policy()->framework_policy; - for ( auto* p : fp->removed_ilist ) - p->handler->rem_global_ref(); - fp->removed_ilist.clear(); + fp->clear_removed(); } void InspectorManager::tear_down_removed_inspectors(const SnortConfig* old, SnortConfig* sc) { - if (old->flow_tracking && !sc->flow_tracking) - { - sc->removed_flow_tracking = old->flow_tracking; - sc->removed_flow_tracking->handler->add_global_ref(); - sc->removed_flow_tracking->handler->tear_down(sc); - } + SingleInstanceInspectorPolicy* old_fid = old->policy_map->get_file_id(); + SingleInstanceInspectorPolicy* fid = sc->policy_map->get_file_id(); + fid->populate_removed(sc, old_fid); + + SingleInstanceInspectorPolicy* old_ft = old->policy_map->get_flow_tracking(); + SingleInstanceInspectorPolicy* ft = sc->policy_map->get_flow_tracking(); + ft->populate_removed(sc, old_ft); + + GlobalInspectorPolicy* pp = sc->policy_map->get_global_inspector_policy(); + GlobalInspectorPolicy* old_pp = old->policy_map->get_global_inspector_policy(); + pp->populate_removed(sc, old_pp); TrafficPolicy* tp = get_default_network_policy(sc)->traffic_policy; TrafficPolicy* old_tp = get_default_network_policy(old)->traffic_policy; - for (auto it = old_tp->ilist.begin(); it != old_tp->ilist.end(); ++it) - { - PHInstance* instance = get_instance(tp, (*it)->name.c_str()); - if (!instance) - { - tp->removed_ilist.emplace_back(*it); - (*it)->handler->add_global_ref(); - (*it)->handler->tear_down(sc); - } - } + tp->populate_removed(sc, old_tp); FrameworkPolicy* fp = get_default_inspection_policy(sc)->framework_policy; FrameworkPolicy* old_fp = get_default_inspection_policy(old)->framework_policy; - for (auto it = old_fp->ilist.begin(); it != old_fp->ilist.end(); ++it) - { - PHInstance* instance = get_instance(fp, (*it)->name.c_str()); - if (!instance) - { - fp->removed_ilist.emplace_back(*it); - (*it)->handler->add_global_ref(); - (*it)->handler->tear_down(sc); - } - } + fp->populate_removed(sc, old_fp); +} + +Inspector* InspectorManager::get_file_inspector(const SnortConfig* sc) +{ + if ( !sc ) + sc = SnortConfig::get_conf(); + SingleInstanceInspectorPolicy* fid = sc->policy_map->get_file_id(); + return fid->instance ? fid->instance->handler : nullptr; } // FIXIT-P cache get_inspector() returns or provide indexed lookup @@ -726,10 +949,10 @@ Inspector* InspectorManager::get_inspector(const char* key, bool dflt_only, cons InspectionPolicy* pi; NetworkPolicy* ni; + if ( !sc ) + sc = SnortConfig::get_conf(); if ( dflt_only ) { - if ( !sc ) - sc = SnortConfig::get_conf(); pi = get_default_inspection_policy(sc); ni = get_default_network_policy(sc); } @@ -752,6 +975,20 @@ Inspector* InspectorManager::get_inspector(const char* key, bool dflt_only, cons if ( p ) return p->handler; } + + GlobalInspectorPolicy* pp = sc->policy_map->get_global_inspector_policy(); + PHInstance* p = get_instance(pp, key); + if ( p ) + return p->handler; + + SingleInstanceInspectorPolicy* ft = sc->policy_map->get_flow_tracking(); + if ( ft->instance && ft->instance->name == key ) + return ft->instance->handler; + + SingleInstanceInspectorPolicy* fid = sc->policy_map->get_file_id(); + if ( fid->instance && fid->instance->name == key ) + return fid->instance->handler; + return nullptr; } @@ -779,24 +1016,8 @@ Inspector* InspectorManager::get_service_inspector_by_id(const SnortProtocolId p bool InspectorManager::delete_inspector(SnortConfig* sc, const char* iname) { - bool ok = false; FrameworkPolicy* fp = sc->policy_map->get_inspection_policy()->framework_policy; - std::vector::iterator old_it; - - if ( get_instance(fp, iname, old_it) ) - { - (*old_it)->set_reloaded(RELOAD_TYPE_DELETED); - fp->remove_inspector_from_cache((*old_it)->handler); - fp->ilist.erase(old_it); - ok = true; - std::vector::iterator bind_it; - if ( get_instance(fp, bind_id, bind_it) ) - { - (*bind_it)->handler->remove_inspector_binding(sc, iname); - } - } - - return ok; + return fp->delete_inspector(sc, iname); } void InspectorManager::free_inspector(Inspector* p) @@ -804,16 +1025,6 @@ void InspectorManager::free_inspector(Inspector* p) p->get_api()->dtor(p); } -void InspectorManager::free_flow_tracking(PHInstance* pi) -{ - if (pi) - { - Inspector* i = pi->handler; - delete pi; - free_inspector(i); - } -} - InspectSsnFunc InspectorManager::get_session(uint16_t proto) { for ( auto* p : s_handlers ) @@ -880,6 +1091,26 @@ static PHGlobal& get_thread_local_plugin(const InspectApi& api) return s_tl_handlers->back(); } +void PHInstance::tinit() +{ + PHGlobal& phg = get_thread_local_plugin(pp_class.api); + if ( !phg.instance_initialized ) + { + handler->tinit(); + phg.instance_initialized = true; + } +} + +void PHInstance::tterm() +{ + PHGlobal& phg = get_thread_local_plugin(pp_class.api); + if ( phg.instance_initialized ) + { + handler->tterm(); + phg.instance_initialized = false; + } +} + void InspectorManager::thread_init(const SnortConfig* sc) { Inspector::slot = get_instance_id(); @@ -896,43 +1127,23 @@ void InspectorManager::thread_init(const SnortConfig* sc) // pin->tinit() only called for default policy set_default_policy(sc); - if (sc->flow_tracking) - { - PHGlobal& phg = get_thread_local_plugin(sc->flow_tracking->pp_class.api); - if ( !phg.instance_initialized ) - { - sc->flow_tracking->handler->tinit(); - phg.instance_initialized = true; - } - } + SingleInstanceInspectorPolicy* fid = sc->policy_map->get_file_id(); + fid->tinit(); + SingleInstanceInspectorPolicy* ft = sc->policy_map->get_flow_tracking(); + ft->tinit(); + + GlobalInspectorPolicy* pp = sc->policy_map->get_global_inspector_policy(); + pp->tinit(); InspectionPolicy* pi = get_inspection_policy(); if ( pi && pi->framework_policy ) - { - for ( auto* p : pi->framework_policy->ilist ) - { - PHGlobal& phg = get_thread_local_plugin(p->pp_class.api); - if ( !phg.instance_initialized ) - { - p->handler->tinit(); - phg.instance_initialized = true; - } - } - } + pi->framework_policy->tinit(); for ( unsigned i = 0; i < sc->policy_map->network_policy_count(); i++) { NetworkPolicy* npi = sc->policy_map->get_network_policy(i); set_network_policy(npi); - for ( auto* p : npi->traffic_policy->ilist ) - { - PHGlobal& phg = get_thread_local_plugin(p->pp_class.api); - if ( !phg.instance_initialized ) - { - p->handler->tinit(); - phg.instance_initialized = true; - } - } + npi->traffic_policy->tinit(); } } @@ -951,77 +1162,44 @@ void InspectorManager::thread_reinit(const SnortConfig* sc) } set_default_policy(sc); - if (sc->flow_tracking) - { - PHGlobal& phg = get_thread_local_plugin(sc->flow_tracking->pp_class.api); - if ( !phg.instance_initialized ) - { - if (phg.api.tinit) - sc->flow_tracking->handler->tinit(); - phg.instance_initialized = true; - } - } + SingleInstanceInspectorPolicy* fid = sc->policy_map->get_file_id(); + fid->tinit(); + SingleInstanceInspectorPolicy* ft = sc->policy_map->get_flow_tracking(); + ft->tinit(); + + GlobalInspectorPolicy* pp = sc->policy_map->get_global_inspector_policy(); + pp->tinit(); for ( unsigned i = 0; i < sc->policy_map->network_policy_count(); i++) { NetworkPolicy* npi = sc->policy_map->get_network_policy(i); set_network_policy(npi); - - for ( auto* p : npi->traffic_policy->ilist ) - { - PHGlobal& phg = get_thread_local_plugin(p->pp_class.api); - if ( !phg.instance_initialized ) - { - p->handler->tinit(); - phg.instance_initialized = true; - } - } + npi->traffic_policy->tinit(); // pin->tinit() only called for default policy InspectionPolicy* pi = get_default_inspection_policy(sc); if ( pi && pi->framework_policy ) - { - // Call pin->tinit() for anything that hasn't yet - for ( auto* p : pi->framework_policy->ilist ) - { - PHGlobal& phg = get_thread_local_plugin(p->pp_class.api); - if ( !phg.instance_initialized ) - { - p->handler->tinit(); - phg.instance_initialized = true; - } - } - } + pi->framework_policy->tinit(); } } void InspectorManager::thread_stop_removed(const SnortConfig* sc) { - if (sc->removed_flow_tracking) - { - PHGlobal& phg = get_thread_local_plugin(sc->removed_flow_tracking->pp_class.api); - if ( phg.instance_initialized ) - { - sc->removed_flow_tracking->handler->tterm(); - phg.instance_initialized = false; - } - } + SingleInstanceInspectorPolicy* fid = sc->policy_map->get_file_id(); + fid->tterm_removed(); + + SingleInstanceInspectorPolicy* ft = sc->policy_map->get_flow_tracking(); + ft->tterm_removed(); + + GlobalInspectorPolicy* pp = sc->policy_map->get_global_inspector_policy(); + pp->tterm_removed(); // pin->tinit() only called for default policy NetworkPolicy* npi = get_default_network_policy(sc); - if ( npi && npi->traffic_policy ) { // Call pin->tterm() for anything that has been initialized and removed - for ( auto* p : npi->traffic_policy->removed_ilist ) - { - PHGlobal& phg = get_thread_local_plugin(p->pp_class.api); - if ( phg.instance_initialized ) - { - p->handler->tterm(); - phg.instance_initialized = false; - } - } + npi->traffic_policy->tterm_removed(); } // pin->tinit() only called for default policy @@ -1030,15 +1208,7 @@ void InspectorManager::thread_stop_removed(const SnortConfig* sc) if ( pi && pi->framework_policy ) { // Call pin->tterm() for anything that has been initialized and removed - for ( auto* p : pi->framework_policy->removed_ilist ) - { - PHGlobal& phg = get_thread_local_plugin(p->pp_class.api); - if ( phg.instance_initialized ) - { - p->handler->tterm(); - phg.instance_initialized = false; - } - } + pi->framework_policy->tterm_removed(); } } @@ -1048,45 +1218,24 @@ void InspectorManager::thread_stop(const SnortConfig* sc) if ( !s_tl_handlers ) return; - // pin->tterm() only called for default policy set_default_policy(sc); - if (sc->flow_tracking) - { - PHGlobal& phg = get_thread_local_plugin(sc->flow_tracking->pp_class.api); - if ( phg.instance_initialized ) - { - sc->flow_tracking->handler->tterm(); - phg.instance_initialized = false; - } - } + SingleInstanceInspectorPolicy* fid = sc->policy_map->get_file_id(); + fid->tterm(); + SingleInstanceInspectorPolicy* ft = sc->policy_map->get_flow_tracking(); + ft->tterm(); + + GlobalInspectorPolicy* pp = sc->policy_map->get_global_inspector_policy(); + pp->tterm(); InspectionPolicy* pi = get_inspection_policy(); if ( pi && pi->framework_policy ) - { - for ( auto* p : pi->framework_policy->ilist ) - { - PHGlobal& phg = get_thread_local_plugin(p->pp_class.api); - if ( phg.instance_initialized ) - { - p->handler->tterm(); - phg.instance_initialized = false; - } - } - } + pi->framework_policy->tterm(); for ( unsigned i = 0; i < sc->policy_map->network_policy_count(); i++) { NetworkPolicy* npi = sc->policy_map->get_network_policy(i); set_network_policy(npi); - for ( auto* p : npi->traffic_policy->ilist ) - { - PHGlobal& phg = get_thread_local_plugin(p->pp_class.api); - if ( phg.instance_initialized ) - { - p->handler->tterm(); - phg.instance_initialized = false; - } - } + npi->traffic_policy->tterm(); } } @@ -1127,36 +1276,48 @@ void InspectorManager::instantiate( else { PHInstance* ppi; - if (Module::GLOBAL == mod->get_usage() && IT_STREAM == api->type) + if (Module::GLOBAL == mod->get_usage() && IT_FILE == api->type) { - assert(sc); - if (sc->flow_tracking) + SingleInstanceInspectorPolicy* fid = sc->policy_map->get_file_id(); + assert(fid); + if (!fid->get_new(sc, mod, *ppc, ppi)) { - ParseError("Only one flow tracking inspector may be instantiated\n"); + ParseError("Only one file identification inspector may be instantiated\n"); return; } - ppi = new PHInstance(*ppc, sc, mod); - if ( ppi->handler ) - sc->flow_tracking = ppi; - else + } + else if (Module::GLOBAL == mod->get_usage() && IT_STREAM == api->type) + { + SingleInstanceInspectorPolicy* ft = sc->policy_map->get_flow_tracking(); + assert(ft); + if (!ft->get_new(sc, mod, *ppc, ppi)) { - delete ppi; - ppi = nullptr; + ParseError("Only one flow tracking inspector may be instantiated\n"); + return; } } else { - InspectorList* il; - if (Module::CONTEXT == mod->get_usage()) - il = get_network_policy()->traffic_policy; - else - il = get_inspection_policy()->framework_policy; - assert(il); - if ( name ) keyword = name; - - ppi = get_new(ppc, il, keyword, mod, sc); + if (Module::GLOBAL == mod->get_usage() && IT_SERVICE != api->type) + { + GlobalInspectorPolicy* il = sc->policy_map->get_global_inspector_policy(); + assert(il); + ppi = get_new(ppc, il, keyword, mod, sc); + } + else if (Module::CONTEXT == mod->get_usage()) + { + TrafficPolicy* il = get_network_policy()->traffic_policy; + assert(il); + ppi = get_new(ppc, il, keyword, mod, sc); + } + else + { + FrameworkPolicy* il = get_inspection_policy()->framework_policy; + assert(il); + ppi = get_new(ppc, il, keyword, mod, sc); + } } if ( ppi ) @@ -1255,6 +1416,18 @@ static bool configure(SnortConfig* sc, InspectorList* il, bool cloned, bool& new return ok; } +Inspector* InspectorManager::acquire_file_inspector() +{ + Inspector* pi = get_file_inspector(); + + if ( !pi ) + FatalError("unconfigured file inspector\n"); + else + pi->add_global_ref(); + + return pi; +} + Inspector* InspectorManager::acquire(const char* key, bool dflt_only) { Inspector* pi = get_inspector(key, dflt_only); @@ -1297,8 +1470,14 @@ bool InspectorManager::configure(SnortConfig* sc, bool cloned) } ::set_network_policy(sc); - if (sc->flow_tracking) - ok = sc->flow_tracking->handler->configure(sc) && ok; + SingleInstanceInspectorPolicy* fid = sc->policy_map->get_file_id(); + fid->configure(sc); + + SingleInstanceInspectorPolicy* ft = sc->policy_map->get_flow_tracking(); + ft->configure(sc); + + GlobalInspectorPolicy* pp = sc->policy_map->get_global_inspector_policy(); + ok = ::configure(sc, pp, cloned, new_ins, reenabled_ins) && ok; ::set_inspection_policy(sc); for ( unsigned idx = 0; idx < sc->policy_map->inspection_policy_count(); ++idx ) @@ -1356,12 +1535,22 @@ void InspectorManager::sort_inspector_list(const InspectorList* il, void InspectorManager::print_config(SnortConfig* sc) { - if (sc->flow_tracking) + SingleInstanceInspectorPolicy* fid = sc->policy_map->get_file_id(); + fid->print_config(sc, "File Identification"); + SingleInstanceInspectorPolicy* ft = sc->policy_map->get_flow_tracking(); + ft->print_config(sc, "Flow Tracking"); + + GlobalInspectorPolicy* pp = sc->policy_map->get_global_inspector_policy(); + if (!pp->ilist.empty()) { - LogLabel("Flow Tracking"); - const std::string name = generate_inspector_label(sc->flow_tracking); - LogLabel(name.c_str()); - sc->flow_tracking->handler->show(sc); + LogLabel("Global Inspectors"); + std::map pp_sorted_ilist; + sort_inspector_list(pp, pp_sorted_ilist); + for ( const auto& p : pp_sorted_ilist ) + { + LogLabel(p.first.c_str()); + p.second->handler->show(sc); + } } const auto shell_number = sc->policy_map->shells_count(); @@ -1543,8 +1732,12 @@ void InspectorManager::internal_execute(Packet* p) } const SnortConfig* sc = p->context->conf; - if ( !p->has_paf_payload() && sc->flow_tracking ) - ::execute(p, &sc->flow_tracking, 1); + if ( !p->has_paf_payload() ) + { + SingleInstanceInspectorPolicy* ft = sc->policy_map->get_flow_tracking(); + if (ft->instance ) + ::execute(p, &ft->instance, 1); + } // must check between each ::execute() if ( p->disable_inspect ) @@ -1620,11 +1813,11 @@ void InspectorManager::internal_execute(Packet* p) void InspectorManager::probe(Packet* p) { - InspectionPolicy* policy = p->context->conf->policy_map->get_inspection_policy(0); - FrameworkPolicy* fp = policy->framework_policy; + GlobalInspectorPolicy* pp = p->context->conf->policy_map->get_global_inspector_policy(); + assert(pp); if ( !trace_enabled(snort_trace, TRACE_INSPECTOR_MANAGER, DEFAULT_TRACE_LOG_LEVEL, p) ) - ::execute(p, fp->probe.vec, fp->probe.num, true); + ::execute(p, pp->probe.vec, pp->probe.num, true); else { Stopwatch timer; @@ -1635,7 +1828,7 @@ void InspectorManager::probe(Packet* p) timer.start(); - ::execute(p, fp->probe.vec, fp->probe.num, true); + ::execute(p, pp->probe.vec, pp->probe.num, true); trace_ulogf(snort_trace, TRACE_INSPECTOR_MANAGER, p, "end inspection, %s, packet %" PRId64", context %" PRId64", total time: %" PRId64" usec\n", diff --git a/src/managers/inspector_manager.h b/src/managers/inspector_manager.h index 45b684a49..da76869a2 100644 --- a/src/managers/inspector_manager.h +++ b/src/managers/inspector_manager.h @@ -28,10 +28,12 @@ #include "framework/inspector.h" class Binder; +class SingleInstanceInspectorPolicy; struct InspectorList; struct InspectionPolicy; struct NetworkPolicy; struct PHInstance; +struct GlobalInspectorPolicy; namespace snort { @@ -67,9 +69,13 @@ public: static bool delete_inspector(SnortConfig*, const char* iname); static void free_inspector(Inspector*); - static void free_flow_tracking(PHInstance*); + static SingleInstanceInspectorPolicy* create_single_instance_inspector_policy(); + static void destroy_single_instance_inspector(SingleInstanceInspectorPolicy*); + static GlobalInspectorPolicy* create_global_inspector_policy(GlobalInspectorPolicy* = nullptr); + static void destroy_global_inspector_policy(GlobalInspectorPolicy*, bool cloned); static InspectSsnFunc get_session(uint16_t proto); + SO_PUBLIC static Inspector* get_file_inspector(const SnortConfig* = nullptr); SO_PUBLIC static Inspector* get_inspector( const char* key, bool dflt_only = false, const SnortConfig* = nullptr); @@ -78,6 +84,7 @@ public: SO_PUBLIC static Binder* get_binder(); + SO_PUBLIC static Inspector* acquire_file_inspector(); SO_PUBLIC static Inspector* acquire(const char* key, bool dflt_only = false); SO_PUBLIC static void release(Inspector*); diff --git a/src/managers/policy_selector_manager.cc b/src/managers/policy_selector_manager.cc index 45085e3af..27df15f01 100644 --- a/src/managers/policy_selector_manager.cc +++ b/src/managers/policy_selector_manager.cc @@ -61,25 +61,26 @@ void PolicySelectorManager::release_plugins() void PolicySelectorManager::instantiate(const PolicySelectorApi* api, Module* mod, SnortConfig* sc) { assert(sc); - if (sc->global_selector) + if (sc->policy_map->get_policy_selector()) { ParseError("Only one selector may be instantiated\n"); return; } assert(api); - sc->global_selector = api->ctor(mod); + sc->policy_map->set_policy_selector(api->ctor(mod)); } void PolicySelectorManager::print_config(const SnortConfig* sc) { assert(sc); - if (sc->global_selector) + const PolicySelector* ps = sc->policy_map->get_policy_selector(); + if (ps) { LogLabel("Policy Selector"); - std::string name = sc->global_selector->get_api()->base.name; + std::string name = ps->get_api()->base.name; name += ":"; LogLabel(name.c_str()); - sc->global_selector->show(); + ps->show(); } } diff --git a/src/network_inspectors/appid/appid_api.cc b/src/network_inspectors/appid/appid_api.cc index a6b93faa4..ae1c455e8 100644 --- a/src/network_inspectors/appid/appid_api.cc +++ b/src/network_inspectors/appid/appid_api.cc @@ -259,7 +259,7 @@ bool AppIdApi::is_inspection_needed(const Inspector& inspector) const return false; SnortProtocolId id = inspector.get_service(); - AppIdConfig& config = appid_inspector->get_ctxt().config; + const AppIdConfig& config = appid_inspector->get_ctxt().config; if (id == config.snort_proto_ids[PROTO_INDEX_HTTP2] or id == config.snort_proto_ids[PROTO_INDEX_SSH]) return true; diff --git a/src/service_inspectors/http2_inspect/http2_data_cutter.cc b/src/service_inspectors/http2_inspect/http2_data_cutter.cc index 800d01bce..b2033df98 100644 --- a/src/service_inspectors/http2_inspect/http2_data_cutter.cc +++ b/src/service_inspectors/http2_inspect/http2_data_cutter.cc @@ -91,7 +91,7 @@ StreamSplitter::Status Http2DataCutter::scan(const uint8_t* data, uint32_t lengt uint32_t* flush_offset, uint32_t& data_offset, uint8_t frame_flags) { Http2Stream* const stream = session_data->find_stream(session_data->current_stream[source_id]); - + if (!stream or !stream->is_open(source_id) or stream->is_discard_set(source_id)) return skip_over_frame(stream, length, flush_offset, data_offset, frame_flags); @@ -164,7 +164,7 @@ StreamSplitter::Status Http2DataCutter::scan(const uint8_t* data, uint32_t lengt // here assert(false); stream->set_state(source_id, STREAM_ERROR); - return skip_over_frame(stream, length, flush_offset, data_offset, frame_flags); + return skip_over_frame(stream, length, flush_offset, data_offset, frame_flags); } } @@ -193,7 +193,6 @@ StreamSplitter::Status Http2DataCutter::scan(const uint8_t* data, uint32_t lengt { session_data->stream_in_hi = session_data->current_stream[source_id]; session_data->hi_ss[source_id]->prep_partial_flush(session_data->flow, 0); - session_data->stream_in_hi = NO_STREAM_ID; } else { @@ -317,7 +316,7 @@ void Http2DataCutter::discarded_frame_cleanup(Http2Stream* const stream) frame_bytes_seen = 0; reassemble_data_bytes_read = 0; reassemble_state = GET_FRAME_HDR; - + if (!stream->is_end_stream_on_data_flush(source_id)) return; diff --git a/tools/snort2lua/config_states/config_file.cc b/tools/snort2lua/config_states/config_file.cc index 16d53eae1..61076238c 100644 --- a/tools/snort2lua/config_states/config_file.cc +++ b/tools/snort2lua/config_states/config_file.cc @@ -41,7 +41,6 @@ bool File::convert(std::istringstream& data_stream) std::string args; bool retval = true; - table_api.open_table("file_id"); while (util::get_string(data_stream, args, ",")) { std::istringstream arg_stream(args); @@ -53,61 +52,85 @@ bool File::convert(std::istringstream& data_stream) else if (keyword == "file_capture_memcap") { + table_api.open_table("file_id"); table_api.add_diff_option_comment("config file: file_capture_memcap", "capture_memcap"); tmpval = parse_int_option("capture_memcap", arg_stream, false); + table_api.close_table(); } else if (keyword == "file_capture_max") { + table_api.open_table("file_id"); table_api.add_diff_option_comment("config file: file_capture_max", "capture_max_size"); tmpval = parse_int_option("capture_max_size", arg_stream, false); + table_api.close_table(); } else if (keyword == "file_capture_min") { + table_api.open_table("file_id"); table_api.add_diff_option_comment("config file: file_capture_min", "capture_min_size"); tmpval = parse_int_option("capture_min_size", arg_stream, false); + table_api.close_table(); } else if (keyword == "file_capture_block_size") { + table_api.open_table("file_id"); table_api.add_diff_option_comment("config file: file_capture_block_size", "capture_block_size"); tmpval = parse_int_option("capture_block_size", arg_stream, false); + table_api.close_table(); } else if (keyword == "show_data_depth") + { + table_api.open_table("file_id"); tmpval = parse_int_option("show_data_depth", arg_stream, false); + table_api.close_table(); + } else if (keyword == "type_id") { + table_api.open_table("file_policy"); table_api.add_diff_option_comment("config file: type_id", "enable_type"); table_api.add_option("enable_type", true); + table_api.close_table(); } else if (keyword == "signature") { + table_api.open_table("file_policy"); table_api.add_diff_option_comment("config file: signature", "enable_signature"); table_api.add_option("enable_signature", true); + table_api.close_table(); } else if (keyword == "file_type_depth") { + table_api.open_table("file_id"); table_api.add_diff_option_comment("config file: file_type_depth", "type_depth"); tmpval = parse_int_option("type_depth", arg_stream, false); + table_api.close_table(); } else if (keyword == "file_signature_depth") { + table_api.open_table("file_id"); table_api.add_diff_option_comment("config file: file_signature_depth", "signature_depth"); tmpval = parse_int_option("signature_depth", arg_stream, false); + table_api.close_table(); } else if (keyword == "file_block_timeout") { + table_api.open_table("file_id"); table_api.add_diff_option_comment("config file: file_block_timeout", "block_timeout"); tmpval = parse_int_option("block_timeout", arg_stream, false); + table_api.close_table(); } else if (keyword == "file_lookup_timeout") { + table_api.open_table("file_id"); table_api.add_diff_option_comment("config file: file_lookup_timeout", "lookup_timeout"); tmpval = parse_int_option("lookup_timeout", arg_stream, false); + table_api.close_table(); } else tmpval = false; @@ -117,7 +140,9 @@ bool File::convert(std::istringstream& data_stream) } // Always add the file_rules option to reference the file magic rules. + table_api.open_table("file_id"); table_api.add_option("file_rules", "$file_magic"); + table_api.close_table(); return retval; }