From: Mike Stepanek (mstepane) Date: Tue, 18 Feb 2020 21:21:07 +0000 (+0000) Subject: Merge pull request #1961 in SNORT/snort3 from ~SMINUT/snort3:multiple_reject_take5... X-Git-Tag: 3.0.0-268~4 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3f82c249240f9f3acaed5a92cda9e6194294424d;p=thirdparty%2Fsnort3.git Merge pull request #1961 in SNORT/snort3 from ~SMINUT/snort3:multiple_reject_take5 to master Squashed commit of the following: commit d2f17bbd38c252525c3a36822d2e19c872dc4868 Author: Silviu Minut Date: Fri Jan 3 18:01:36 2020 -0500 main: make ips actions (reject, react, replace) configurable by ips policy and provide default reject to everything else that needs one. managers: take IpsAction out of ActionManager. actions: change ReactData from struct to class with proper constructor and destructor and enable default_react in active.cc. packet_io: introduce the BaseAction class for Active to work with, and take IpsAction out of Active. packet_io: allow ips reject to put both an RST and ICMP dest unreachable on the wire, if so configured, and make the active default reset action put a RST for tcp and ICMP for icmp. packet_io: add a version of Active::reset_session()that does not take a BaseAction as an input argument, but rather queues the default reset; similarly for set_delayed_action. actions: remove act_react.h, act_reject.h and act_replace.h. actions: get rid of Replace_ResetQueue() and Replace_QueueChange(). packet_io: rename ActiveAction to ActiveActionType and BaseAction to ActiveAction. --- diff --git a/src/actions/CMakeLists.txt b/src/actions/CMakeLists.txt index 9d805a580..f12a5a84e 100644 --- a/src/actions/CMakeLists.txt +++ b/src/actions/CMakeLists.txt @@ -8,7 +8,6 @@ set (IPS_ACTION_SOURCES ips_actions.cc ips_actions.h act_replace.cc - act_replace.h ) set( PLUGIN_LIST diff --git a/src/actions/act_react.cc b/src/actions/act_react.cc index 909f528aa..9605227ef 100644 --- a/src/actions/act_react.cc +++ b/src/actions/act_react.cc @@ -92,41 +92,81 @@ static THREAD_LOCAL ProfileStats reactPerfStats; "You are attempting to access a forbidden site.
" \ "Consult your system administrator for details." -struct ReactData + +class ReactData { - int rule_msg; // 1=>use rule msg; 0=>use DEFAULT_MSG +public: + + ReactData(bool rmsg, const char* page); + ~ReactData(); + + ssize_t get_buf_len() const { return buf_len; } + const char* get_resp_buf() const { return resp_buf; } + +private: + // FIXIT-M: make it do what it says, or delete it. + // int rule_msg; // 1=>use rule msg; 0=>use DEFAULT_MSG ssize_t buf_len; // length of response char* resp_buf; // response to send - char* resp_page; + const char* resp_page; }; -class ReactAction : public IpsAction + +class ReactAction : public snort::IpsAction { public: - ReactAction(ReactData* c) : IpsAction(s_name, ACT_PROXY) - { config = c; } - + ReactAction(ReactData* c); ~ReactAction() override; - void exec(Packet*) override; + void exec(snort::Packet*) override; private: - void send(Packet*); + void send(snort::Packet*); private: ReactData* config; }; +ReactData::ReactData(bool rmsg, const char* page) + : buf_len(0), resp_buf(nullptr), resp_page(page) +{ + int body_len, head_len, total_len; + char dummy; + + const char* head = DEFAULT_HTTP; + const char* body = resp_page ? resp_page : DEFAULT_HTML; + const char* msg = DEFAULT_MSG; + UNUSED(rmsg); + + body_len = snprintf(&dummy, 1, body, msg); + head_len = snprintf(&dummy, 1, head, body_len); + total_len = head_len + body_len + 1; + + resp_buf = (char*)snort_calloc(total_len); + + SnortSnprintf((char*)resp_buf, head_len+1, head, body_len); + SnortSnprintf((char*)resp_buf+head_len, body_len+1, body, msg); + + // set actual length + resp_buf[total_len-1] = '\0'; + buf_len = strlen(resp_buf); +} + +ReactData::~ReactData() +{ + if ( resp_buf ) + snort_free(resp_buf); +} + //------------------------------------------------------------------------- // class methods //------------------------------------------------------------------------- +ReactAction::ReactAction(ReactData* c) : IpsAction(s_name, ActionType::ACT_PROXY), config(c) {} + ReactAction::~ReactAction() { - if (config->resp_buf) - snort_free(config->resp_buf); - - snort_free(config); + delete config; } void ReactAction::exec(Packet* p) @@ -140,13 +180,13 @@ void ReactAction::exec(Packet* p) void ReactAction::send(Packet* p) { EncodeFlags df = (p->is_from_server()) ? ENC_FLAG_FWD : 0; - EncodeFlags sent = config->buf_len; + EncodeFlags sent = config->get_buf_len(); Active* act = p->active; if ( p->packet_flags & PKT_STREAM_EST ) { - act->send_data(p, df, (uint8_t*)config->resp_buf, config->buf_len); + act->send_data(p, df, (const uint8_t*)config->get_resp_buf(), sent); // act->send_data() sends a FIN, so need to bump seq by 1. sent++; } @@ -155,37 +195,6 @@ void ReactAction::send(Packet* p) act->send_reset(p, rf); } -//------------------------------------------------------------------------- -// implementation foo -//------------------------------------------------------------------------- - - -//-------------------------------------------------------------------- - -// format response buffer -static void react_config(ReactData* rd) -{ - int body_len, head_len, total_len; - char dummy; - - const char* head = DEFAULT_HTTP; - const char* body = rd->resp_page ? rd->resp_page : DEFAULT_HTML; - const char* msg = DEFAULT_MSG; - - body_len = snprintf(&dummy, 1, body, msg); - head_len = snprintf(&dummy, 1, head, body_len); - total_len = head_len + body_len + 1; - - rd->resp_buf = (char*)snort_calloc(total_len); - - SnortSnprintf((char*)rd->resp_buf, head_len+1, head, body_len); - SnortSnprintf((char*)rd->resp_buf+head_len, body_len+1, body, msg); - - // set actual length - rd->resp_buf[total_len-1] = '\0'; - rd->buf_len = strlen(rd->resp_buf); -} - //------------------------------------------------------------------------- // module //------------------------------------------------------------------------- @@ -204,8 +213,11 @@ static const Parameter s_params[] = class ReactModule : public Module { public: - ReactModule() : Module(s_name, s_help, s_params) { page = nullptr; } - ~ReactModule() override { if (page) snort_free(page); } + ReactModule() : Module(s_name, s_help, s_params), msg(false), page(nullptr) {} + ~ReactModule() override { + if (page) + snort_free(page); + } bool begin(const char*, int, SnortConfig*) override; bool set(const char*, Value&, SnortConfig*) override; @@ -314,12 +326,8 @@ static void mod_dtor(Module* m) static IpsAction* react_ctor(Module* p) { - ReactData* rd = (ReactData*)snort_calloc(sizeof(*rd)); - ReactModule* m = (ReactModule*)p; - rd->rule_msg = m->msg; - rd->resp_page = m->page; - react_config(rd); // FIXIT-L this must be done per response + ReactData* rd = new ReactData(m->msg, m->page); Active::set_enabled(); return new ReactAction(rd); diff --git a/src/actions/act_reject.cc b/src/actions/act_reject.cc index 0160291fc..082c166db 100644 --- a/src/actions/act_reject.cc +++ b/src/actions/act_reject.cc @@ -55,34 +55,33 @@ using namespace snort; -#define REJ_NONE 0x00 -#define REJ_RST_SRC 0x01 -#define REJ_RST_DST 0x02 -#define REJ_UNR_NET 0x04 -#define REJ_UNR_HOST 0x08 -#define REJ_UNR_PORT 0x10 -#define REJ_UNR_FWD 0x20 - -#define REJ_RST_BOTH (REJ_RST_SRC|REJ_RST_DST) -#define REJ_UNR_ALL (REJ_UNR_NET|REJ_UNR_HOST|REJ_UNR_PORT|REJ_UNR_FWD) - #define s_name "reject" #define s_help \ "terminate session with TCP reset or ICMP unreachable" -static THREAD_LOCAL ProfileStats rejPerfStats; +enum +{ + REJ_NONE = 0x00, + REJ_RST_SRC = 0x01, + REJ_RST_DST = 0x02, + REJ_UNR_NET = 0x04, + REJ_UNR_HOST = 0x08, + REJ_UNR_PORT = 0x10, + REJ_UNR_FWD = 0x20, + REJ_RST_BOTH = (REJ_RST_SRC | REJ_RST_DST), + REJ_UNR_ALL = (REJ_UNR_NET | REJ_UNR_HOST | REJ_UNR_PORT | REJ_UNR_FWD) +}; + +THREAD_LOCAL ProfileStats rejPerfStats; -class RejectAction : public IpsAction +class RejectAction : public snort::IpsAction { public: - RejectAction(uint32_t f) : IpsAction(s_name, ACT_RESET), mask(f) { } - - void exec(Packet*) override; + RejectAction(uint32_t f); + void exec(snort::Packet*) override; private: - void send(Packet*); - uint32_t mask; }; @@ -90,15 +89,19 @@ private: // class methods //------------------------------------------------------------------------- +RejectAction::RejectAction(uint32_t f) : IpsAction(s_name, ActionType::ACT_RESET), mask(f) +{ } + + void RejectAction::exec(Packet* p) { - Profile profile(rejPerfStats); - if ( !p->ptrs.ip_api.is_ip() ) return; Active* act = p->active; + Profile profile(rejPerfStats); + switch ( p->type() ) { case PktType::TCP: @@ -117,12 +120,6 @@ void RejectAction::exec(Packet* p) return; } - send(p); -} - -void RejectAction::send(Packet* p) -{ - Active* act = p->active; uint32_t flags = 0; if ( act->is_reset_candidate(p) ) diff --git a/src/actions/act_replace.cc b/src/actions/act_replace.cc index 5068d6a51..388ab381b 100644 --- a/src/actions/act_replace.cc +++ b/src/actions/act_replace.cc @@ -21,8 +21,6 @@ #include "config.h" #endif -#include "act_replace.h" - #include "detection/detection_engine.h" #include "framework/ips_action.h" #include "framework/module.h" @@ -40,16 +38,6 @@ using namespace snort; // queue foo //-------------------------------------------------------------------------- -void Replace_ResetQueue() -{ - DetectionEngine::clear_replacement(); -} - -void Replace_QueueChange(const std::string& s, unsigned off) -{ - DetectionEngine::add_replacement(s, off); -} - static inline void Replace_ApplyChange(Packet* p, std::string& data, unsigned offset) { uint8_t* start = const_cast(p->data) + offset; @@ -131,21 +119,20 @@ bool ReplaceModule::end(const char*, int, SnortConfig*) } //------------------------------------------------------------------------- - -class ReplaceAction : public IpsAction +class ReplaceAction : public snort::IpsAction { public: - ReplaceAction(ReplaceModule*); + ReplaceAction(bool disable_replace); - void exec(Packet*) override; + void exec(snort::Packet*) override; private: bool disable_replace = false; }; -ReplaceAction::ReplaceAction(ReplaceModule* m) : +ReplaceAction::ReplaceAction(bool dr) : IpsAction(s_name, ACT_RESET) { - disable_replace = m->disable_replace; + disable_replace = dr; Active::set_enabled(); } @@ -166,7 +153,7 @@ static void mod_dtor(Module* m) { delete m; } static IpsAction* rep_ctor(Module* m) -{ return new ReplaceAction((ReplaceModule*)m); } +{ return new ReplaceAction( ((ReplaceModule*)m)->disable_replace); } static void rep_dtor(IpsAction* p) { delete p; } diff --git a/src/actions/actions.cc b/src/actions/actions.cc index 8250bad16..357890890 100644 --- a/src/actions/actions.cc +++ b/src/actions/actions.cc @@ -25,6 +25,7 @@ #include "detection/detect.h" #include "detection/tag.h" #include "packet_io/active.h" +#include "packet_io/active_action.h" #include "parser/parser.h" #include "utils/stats.h" @@ -131,7 +132,7 @@ void Actions::execute(Actions::Type action, Packet* p, const OptTreeNode* otn, break; case Actions::RESET: - p->active->reset_session(p); + p->active->reset_session(p, get_ips_policy()->action[action]); alert(p, otn); SetTags(p, otn, event_id); break; @@ -154,7 +155,7 @@ void Actions::apply(Actions::Type action, Packet* p) break; case Actions::RESET: - p->active->reset_session(p); + p->active->reset_session(p, get_ips_policy()->action[action]); break; default: diff --git a/src/detection/detection_engine.cc b/src/detection/detection_engine.cc index 18dd43897..cb688e7fc 100644 --- a/src/detection/detection_engine.cc +++ b/src/detection/detection_engine.cc @@ -24,7 +24,6 @@ #include "detection_engine.h" -#include "actions/act_replace.h" #include "events/sfeventq.h" #include "filters/sfthreshold.h" #include "framework/endianness.h" @@ -146,7 +145,7 @@ Packet* DetectionEngine::get_encode_packet() Packet* DetectionEngine::set_next_packet(Packet* parent) { static THREAD_LOCAL Active shutdown_active; - static THREAD_LOCAL IpsAction* shutdown_action = nullptr; + static THREAD_LOCAL ActiveAction* shutdown_action = nullptr; wait_for_context(); IpsContext* c = Analyzer::get_switcher()->get_next(); @@ -698,3 +697,4 @@ void DetectionEngine::clear_events(Packet* p) SF_EVENTQ* pq = p->context->equeue; pc.log_limit += sfeventq_reset(pq); } + diff --git a/src/detection/fp_detect.cc b/src/detection/fp_detect.cc index 05cd9bf62..967ed95e6 100644 --- a/src/detection/fp_detect.cc +++ b/src/detection/fp_detect.cc @@ -54,6 +54,7 @@ #include "managers/action_manager.h" #include "packet_tracer/packet_tracer.h" #include "parser/parser.h" +#include "packet_io/active.h" #include "profiler/profiler_defs.h" #include "protocols/icmp4.h" #include "protocols/packet_manager.h" @@ -120,8 +121,13 @@ static inline void fpLogOther( otn_trigger_actions(otn, p); // rule actions are queued here (eg reject) - if ( rtn->listhead->action ) - ActionManager::queue(rtn->listhead->action, p); + if ( rtn->listhead->is_plugin_action ) + { + snort::Actions::Type idx = rtn->listhead->ruleListNode->mode; + ActiveAction * act = get_ips_policy()->action[idx]; + if ( act ) + Active::queue(act, p); + } } /* diff --git a/src/detection/rules.h b/src/detection/rules.h index c6659567a..b31436bf3 100644 --- a/src/detection/rules.h +++ b/src/detection/rules.h @@ -56,8 +56,8 @@ struct ListHead { OutputSet* LogList; OutputSet* AlertList; - snort::IpsAction* action; struct RuleListNode* ruleListNode; + bool is_plugin_action = false; }; // for top-level rule lists by type (alert, drop, etc.) diff --git a/src/file_api/file_cache.cc b/src/file_api/file_cache.cc index 48019fde5..1f435900a 100644 --- a/src/file_api/file_cache.cc +++ b/src/file_api/file_cache.cc @@ -271,9 +271,9 @@ bool FileCache::apply_verdict(Packet* p, FileContext* file_ctx, FileVerdict verd policy->log_file_action(flow, file_ctx, FILE_RESUME_LOG); return false; case FILE_VERDICT_BLOCK: - // can't block session inside a session - act->set_delayed_action(Active::ACT_BLOCK, true); - break; + // can't block session inside a session + act->set_delayed_action(Active::ACT_BLOCK, true); + break; case FILE_VERDICT_REJECT: // can't reset session inside a session diff --git a/src/file_api/file_module.cc b/src/file_api/file_module.cc index 8cf0296cb..4910e819b 100644 --- a/src/file_api/file_module.cc +++ b/src/file_api/file_module.cc @@ -32,6 +32,7 @@ #include "log/messages.h" #include "main/snort.h" #include "main/snort_config.h" +#include "packet_io/active.h" #include "file_service.h" #include "file_stats.h" @@ -369,7 +370,11 @@ bool FileIdModule::set(const char*, Value& v, SnortConfig*) 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(); @@ -433,6 +438,9 @@ bool FileIdModule::end(const char* fqn, int idx, SnortConfig*) fc->process_file_policy_rule(file_rule); } + if ( need_active ) + Active::set_enabled(); + return true; } @@ -451,3 +459,4 @@ void FileIdModule::show_dynamic_stats() { file_stats_print(); } + diff --git a/src/file_api/file_module.h b/src/file_api/file_module.h index 301d695a3..7f7bc48d9 100644 --- a/src/file_api/file_module.h +++ b/src/file_api/file_module.h @@ -66,6 +66,7 @@ private: FileMagicData magic; FileRule file_rule; FileConfig *fc = nullptr; + bool need_active = false; }; enum FileSid diff --git a/src/framework/ips_action.h b/src/framework/ips_action.h index c976db805..b9be2d6d1 100644 --- a/src/framework/ips_action.h +++ b/src/framework/ips_action.h @@ -28,6 +28,7 @@ #include "actions/actions.h" #include "framework/base_api.h" #include "main/snort_types.h" +#include "packet_io/active_action.h" // this is the current version of the api #define ACTAPI_VERSION ((BASE_API_VERSION << 16) | 0) @@ -41,33 +42,18 @@ namespace snort struct Packet; struct SnortConfig; -enum ActionType -{ - ACT_LOCAL, - ACT_MODIFY, - ACT_PROXY, - ACT_RESET, - ACT_REMOTE, - ACT_MAX -}; - -class SO_PUBLIC IpsAction +class SO_PUBLIC IpsAction : public ActiveAction { public: - virtual ~IpsAction() = default; - - virtual void exec(Packet*) = 0; - + virtual void exec(Packet*) override = 0; const char* get_name() const { return name; } - ActionType get_action() { return action; } protected: - IpsAction(const char* s, ActionType a) - { name = s; action = a; } + IpsAction(const char* s, ActionType a) : ActiveAction(a) + { name = s; } private: const char* name; - ActionType action; }; typedef void (* IpsActFunc)(); diff --git a/src/ips_options/ips_replace.cc b/src/ips_options/ips_replace.cc index 28861213d..8c10b64d9 100644 --- a/src/ips_options/ips_replace.cc +++ b/src/ips_options/ips_replace.cc @@ -22,7 +22,7 @@ #include "config.h" #endif -#include "actions/act_replace.h" +#include "detection/detection_engine.h" #include "detection/treenodes.h" #include "framework/cursor.h" #include "framework/ips_option.h" @@ -178,7 +178,7 @@ void ReplaceOption::action(Packet*) RuleProfile profile(replacePerfStats); if ( pending() ) - Replace_QueueChange(repl, (unsigned)pos()); + DetectionEngine::add_replacement(repl, (unsigned)pos()); } //------------------------------------------------------------------------- diff --git a/src/main/analyzer.cc b/src/main/analyzer.cc index 52c934349..26eb50b85 100644 --- a/src/main/analyzer.cc +++ b/src/main/analyzer.cc @@ -329,7 +329,7 @@ static DAQ_Verdict distill_verdict(Packet* p) */ void Analyzer::post_process_daq_pkt_msg(Packet* p) { - ActionManager::execute(p); + Active::execute(p); DAQ_Verdict verdict = MAX_DAQ_VERDICT; @@ -397,7 +397,7 @@ void Analyzer::process_daq_pkt_msg(DAQ_Msg_h msg, bool retry) DetectionEngine::reset(); sfthreshold_reset(); - ActionManager::reset_queue(p); + Active::clear_queue(p); p->daq_msg = msg; p->daq_instance = daq_instance; @@ -964,3 +964,4 @@ void Analyzer::rotate() { DataBus::publish(THREAD_ROTATE_EVENT, nullptr); } + diff --git a/src/main/policy.cc b/src/main/policy.cc index a8aecbe5c..cc65d39eb 100644 --- a/src/main/policy.cc +++ b/src/main/policy.cc @@ -23,6 +23,7 @@ #include "policy.h" +#include "actions/actions.h" #include "detection/detection_engine.h" #include "log/messages.h" #include "managers/inspector_manager.h" @@ -106,7 +107,7 @@ void InspectionPolicy::clone_dbus(SnortConfig* from, const char* exclude_module) // detection policy //------------------------------------------------------------------------- -IpsPolicy::IpsPolicy(PolicyId id) +IpsPolicy::IpsPolicy(PolicyId id) : action(Actions::Type::MAX, nullptr) { policy_id = id; user_policy_id = 0; @@ -296,6 +297,12 @@ InspectionPolicy* get_inspection_policy() IpsPolicy* get_ips_policy() { return s_detection_policy; } +IpsPolicy* get_ips_policy(SnortConfig* sc, unsigned i) +{ + return sc && i < sc->policy_map->ips_policy_count() ? + sc->policy_map->get_ips_policy(0) : nullptr; +} + InspectionPolicy* get_default_inspection_policy(SnortConfig* sc) { return sc->policy_map->get_inspection_policy(0); } @@ -391,3 +398,4 @@ bool only_ips_policy() bool only_network_policy() { return get_network_policy() && !get_ips_policy() && !get_inspection_policy(); } + diff --git a/src/main/policy.h b/src/main/policy.h index de51b437c..4821aa674 100644 --- a/src/main/policy.h +++ b/src/main/policy.h @@ -34,6 +34,7 @@ typedef unsigned char uuid_t[16]; #include #include +#include #include "framework/data_bus.h" @@ -41,6 +42,7 @@ namespace snort { class GHash; struct SnortConfig; +class ActiveAction; } struct PortTable; @@ -166,6 +168,10 @@ public: Enable default_rule_state = INHERIT_ENABLE; bool obfuscate_pii; + + // Holds plugin actions associated with this policy (e.g. reject, react, etc.) + // Indexed by Actions::Type. + std::vector action; }; //------------------------------------------------------------------------- @@ -272,6 +278,7 @@ namespace snort SO_PUBLIC NetworkPolicy* get_network_policy(); SO_PUBLIC InspectionPolicy* get_inspection_policy(); SO_PUBLIC IpsPolicy* get_ips_policy(); +SO_PUBLIC IpsPolicy* get_ips_policy(snort::SnortConfig*, unsigned i = 0); SO_PUBLIC InspectionPolicy* get_default_inspection_policy(snort::SnortConfig*); SO_PUBLIC void set_ips_policy(IpsPolicy* p); SO_PUBLIC void set_network_policy(NetworkPolicy* p); @@ -297,3 +304,4 @@ bool only_ips_policy(); bool only_network_policy(); #endif + diff --git a/src/managers/action_manager.cc b/src/managers/action_manager.cc index 78180bd9f..10d2e0e3a 100644 --- a/src/managers/action_manager.cc +++ b/src/managers/action_manager.cc @@ -25,7 +25,6 @@ #include -#include "actions/act_replace.h" #include "log/messages.h" #include "main/snort_config.h" #include "packet_io/active.h" @@ -163,9 +162,15 @@ void ActionManager::instantiate(const ActionApi* api, Module* mod, SnortConfig* if ( !sc->ips_actions_config->reject && !strcmp(act->get_name(), "reject") ) sc->ips_actions_config->reject = act; - ListHead* lh = CreateRuleType(sc, api->base.name, api->type); - assert(lh); - lh->action = act; + RuleListNode* rln = CreateRuleType(sc, api->base.name, api->type, true); + + // The plugin actions (e.g. reject, react, etc.) are per policy, per mode. + // At logging time, they have to be retrieved the way we store them here. + IpsPolicy* ips = get_ips_policy(); + snort::Actions::Type idx = rln->mode; + assert(ips->action[idx] == nullptr); + ips->action[idx] = act; + } } @@ -227,33 +232,6 @@ void ActionManager::thread_term(SnortConfig*) } } -void ActionManager::execute(Packet* p) -{ - if ( *p->action ) - { - (*p->action)->exec(p); - *p->action = nullptr; - } -} - -void ActionManager::queue(IpsAction* a, Packet* p) -{ - if ( !(*p->action) || a->get_action() > (*p->action)->get_action() ) - *p->action = a; -} - -void ActionManager::queue_reject(SnortConfig* sc, Packet* p) -{ - if ( sc->ips_actions_config->reject ) - queue(sc->ips_actions_config->reject, p); -} - -void ActionManager::reset_queue(Packet* p) -{ - *p->action = nullptr; - Replace_ResetQueue(); -} - #ifdef PIGLET //------------------------------------------------------------------------- @@ -282,5 +260,6 @@ IpsActionWrapper* ActionManager::instantiate(const char* name, Module* m) return new IpsActionWrapper(api, p); } + #endif diff --git a/src/managers/action_manager.h b/src/managers/action_manager.h index 1cea257f3..21ebce884 100644 --- a/src/managers/action_manager.h +++ b/src/managers/action_manager.h @@ -72,11 +72,6 @@ public: static void thread_reinit(snort::SnortConfig*); static void thread_term(snort::SnortConfig*); - static void reset_queue(snort::Packet*); - static void queue_reject(snort::SnortConfig*, snort::Packet*); - static void queue(snort::IpsAction*, snort::Packet*); - static void execute(snort::Packet*); - #ifdef PIGLET static IpsActionWrapper* instantiate(const char*, snort::Module*); #endif diff --git a/src/packet_io/CMakeLists.txt b/src/packet_io/CMakeLists.txt index 4c2807d9b..13689e82b 100644 --- a/src/packet_io/CMakeLists.txt +++ b/src/packet_io/CMakeLists.txt @@ -28,6 +28,7 @@ endif () add_library (packet_io OBJECT active.cc active.h + active_action.h sfdaq.cc sfdaq.h sfdaq_config.cc diff --git a/src/packet_io/active.cc b/src/packet_io/active.cc index 63922a104..0df08bdd6 100644 --- a/src/packet_io/active.cc +++ b/src/packet_io/active.cc @@ -24,10 +24,13 @@ #endif #include "active.h" +#include "active_action.h" +#include "detection/detection_engine.h" #include "log/messages.h" #include "main/snort_config.h" #include "managers/action_manager.h" +#include "profiler/profiler.h" #include "protocols/tcp.h" #include "pub_sub/active_events.h" #include "stream/stream.h" @@ -41,6 +44,17 @@ using namespace snort; #define MAX_ATTEMPTS 20 +class ResetAction : public snort::ActiveAction +{ +public: + ResetAction() : ActiveAction(ActionType::ACT_RESET) {} + + void exec(snort::Packet* p) override + { + p->active->kill_session(p, ENC_FLAG_FWD); + } +}; + const char* Active::act_str[Active::ACT_MAX][Active::AST_MAX] = { { "allow", "error", "error", "error" }, @@ -63,6 +77,8 @@ static THREAD_LOCAL eth_t* s_link = nullptr; static THREAD_LOCAL ip_t* s_ipnet = nullptr; static THREAD_LOCAL send_t s_send = SFDAQ::inject; +static ResetAction default_reset; + //-------------------------------------------------------------------- // helpers @@ -482,6 +498,11 @@ void Active::block_session(Packet* p, bool force) } void Active::reset_session(Packet* p, bool force) +{ + reset_session(p, &default_reset, force); +} + +void Active::reset_session(Packet* p, ActiveAction* reject, bool force) { update_status(p, force); active_action = ACT_RESET; @@ -491,7 +512,8 @@ void Active::reset_session(Packet* p, bool force) if ( enabled ) { - ActionManager::queue_reject(SnortConfig::get_conf(), p); + if (reject) + Active::queue(reject, p); if ( p->flow ) { @@ -503,9 +525,22 @@ void Active::reset_session(Packet* p, bool force) p->disable_inspect = true; } -void Active::set_delayed_action(ActiveAction action, bool force) +void Active::queue(ActiveAction* a, Packet* p) +{ + if ( !(*p->action) || a->get_action() > (*p->action)->get_action() ) + *p->action = a; +} + +void Active::set_delayed_action(ActiveActionType action, bool force) +{ + set_delayed_action(action, action == ACT_RESET ? &default_reset : nullptr, force); +} + +void Active::set_delayed_action(ActiveActionType action, ActiveAction* act, bool force) { delayed_active_action = action; + assert(delayed_reject == nullptr); + delayed_reject = act; if ( force ) active_status = AST_FORCE; @@ -526,7 +561,8 @@ void Active::apply_delayed_action(Packet* p) block_session(p, force); break; case ACT_RESET: - reset_session(p, force); + assert(delayed_reject); // resets must have been told which reject to use + reset_session(p, delayed_reject, force); break; case ACT_RETRY: if(!retry_packet(p)) @@ -539,6 +575,7 @@ void Active::apply_delayed_action(Packet* p) delayed_active_action = ACT_PASS; } + //-------------------------------------------------------------------- bool Active::open(const char* dev) @@ -582,4 +619,21 @@ void Active::reset() active_status = AST_ALLOW; active_action = ACT_PASS; delayed_active_action = ACT_PASS; + delayed_reject = nullptr; +} + +void Active::clear_queue(Packet* p) +{ + *p->action = nullptr; + DetectionEngine::clear_replacement(); } + +void Active::execute(Packet* p) +{ + if ( *p->action ) + { + (*p->action)->exec(p); + *p->action = nullptr; + } +} + diff --git a/src/packet_io/active.h b/src/packet_io/active.h index 89f2a7030..387b595f8 100644 --- a/src/packet_io/active.h +++ b/src/packet_io/active.h @@ -24,13 +24,13 @@ // manages packet processing verdicts returned to the DAQ. action (what to // do) is separate from status (whether we can actually do it or not). - #include "protocols/packet_manager.h" namespace snort { struct Packet; struct SnortConfig; +class ActiveAction; class SO_PUBLIC Active { @@ -44,10 +44,14 @@ public: enum ActiveStatus : uint8_t { AST_ALLOW, AST_CANT, AST_WOULD, AST_FORCE, AST_MAX }; - enum ActiveAction : uint8_t + // FIXIT-M: these are only used in set_delayed_action and + // apply_delayed_action, in a big switch(action). Do away with these and + // use the actual (Base)Action objects. + enum ActiveActionType : uint8_t { ACT_PASS, ACT_HOLD, ACT_RETRY, ACT_DROP, ACT_BLOCK, ACT_RESET, ACT_MAX }; public: + static void init(SnortConfig*); static bool thread_init(SnortConfig*); static void thread_term(); @@ -69,7 +73,7 @@ public: bool is_reset_candidate(const Packet*); bool is_unreachable_candidate(const Packet*); - ActiveAction get_action() const + ActiveActionType get_action() const { return active_action; } ActiveStatus get_status() const @@ -91,6 +95,11 @@ public: void allow_session(Packet*); void block_session(Packet*, bool force = false); void reset_session(Packet*, bool force = false); + void reset_session(Packet*, snort::ActiveAction* r, bool force = false); + + static void queue(snort::ActiveAction* a, snort::Packet* p); + static void clear_queue(snort::Packet*); + static void execute(Packet* p); void block_again() { active_action = ACT_BLOCK; } @@ -125,7 +134,8 @@ public: bool get_tunnel_bypass() const { return active_tunnel_bypass > 0; } - void set_delayed_action(ActiveAction, bool force = false); + void set_delayed_action(ActiveActionType, bool force = false); + void set_delayed_action(ActiveActionType, ActiveAction* act, bool force = false); void apply_delayed_action(Packet*); void reset(); @@ -139,11 +149,10 @@ private: void update_status(const Packet*, bool force = false); void daq_update_status(const Packet*); - void block_session(const Packet*, ActiveAction, bool force = false); + void block_session(const Packet*, ActiveActionType, bool force = false); void cant_drop(); - private: static const char* act_str[ACT_MAX][AST_MAX]; static bool enabled; @@ -156,8 +165,9 @@ private: // of these flags following all processing and the drop // or response may have been produced by a pseudopacket. ActiveStatus active_status; - ActiveAction active_action; - ActiveAction delayed_active_action; + ActiveActionType active_action; + ActiveActionType delayed_active_action; + ActiveAction* delayed_reject; // set with set_delayed_action() }; struct ActiveSuspendContext diff --git a/src/actions/act_replace.h b/src/packet_io/active_action.h similarity index 53% rename from src/actions/act_replace.h rename to src/packet_io/active_action.h index 6f739b4fc..1c2dc0955 100644 --- a/src/actions/act_replace.h +++ b/src/packet_io/active_action.h @@ -16,14 +16,48 @@ // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. //-------------------------------------------------------------------------- -#ifndef ACT_REPLACE_H -#define ACT_REPLACE_H +// active_action.h author Silviu Minut -#include +#ifndef ACTIVE_ACTION_H +#define ACTIVE_ACTION_H -// FIXIT-M these prevent dynamic ips replace option and action -void Replace_ResetQueue(); -void Replace_QueueChange(const std::string&, unsigned); +#include "main/snort_types.h" + +namespace snort +{ +struct Packet; + +enum ActionType +{ + ACT_LOCAL, + ACT_MODIFY, + ACT_PROXY, + ACT_RESET, + ACT_REMOTE, + ACT_MAX +}; + +// These are injection actions (e.g. send a RST packet, or respond to a query +// with an "Access denied" message). Instances of this class are queued into +// the packet at inspection / detection time and executed at the end by +// Analyzer. The pure virtual exec() method can call into Active methods for +// the low-level stuff. +class SO_PUBLIC ActiveAction +{ +public: + ActiveAction(ActionType a = ActionType::ACT_MAX) : action(a) {} + virtual ~ActiveAction() = default; + + virtual void exec(Packet*) = 0; + + ActionType get_action() const { return action; } + +protected: + ActionType action; + +}; + +} #endif diff --git a/src/parser/parser.cc b/src/parser/parser.cc index fe5860b61..8dd5ef27e 100644 --- a/src/parser/parser.cc +++ b/src/parser/parser.cc @@ -410,7 +410,7 @@ void ParseRules(SnortConfig* sc) * Returns: the ListHead for the rule type * ***************************************************************************/ -ListHead* CreateRuleType(SnortConfig* sc, const char* name, Actions::Type mode) +RuleListNode* CreateRuleType(SnortConfig* sc, const char* name, Actions::Type mode, bool is_plugin_action) { RuleListNode* node; unsigned evalIndex = 0; @@ -433,11 +433,10 @@ ListHead* CreateRuleType(SnortConfig* sc, const char* name, Actions::Type mode) do { - /* We do not allow multiple rules types with the same name. */ if (strcasecmp(tmp->name, name) == 0) { snort_free(node); - return nullptr; + return tmp; } evalIndex++; @@ -451,6 +450,7 @@ ListHead* CreateRuleType(SnortConfig* sc, const char* name, Actions::Type mode) node->RuleList = (ListHead*)snort_calloc(sizeof(ListHead)); node->RuleList->ruleListNode = node; + node->RuleList->is_plugin_action = is_plugin_action; node->mode = mode; node->name = snort_strdup(name); node->evalIndex = evalIndex; @@ -458,7 +458,7 @@ ListHead* CreateRuleType(SnortConfig* sc, const char* name, Actions::Type mode) sc->evalOrder[node->mode] = evalIndex; sc->num_rule_types++; - return node->RuleList; + return node; } void FreeRuleLists(SnortConfig* sc) diff --git a/src/parser/parser.h b/src/parser/parser.h index 6bd96c8b4..0978b884c 100644 --- a/src/parser/parser.h +++ b/src/parser/parser.h @@ -84,7 +84,8 @@ inline RuleTreeNode* getRuntimeRtnFromOtn(const struct OptTreeNode* otn) return getRtnFromOtn(otn); } -ListHead* CreateRuleType(snort::SnortConfig* sc, const char* name, snort::Actions::Type); +RuleListNode* CreateRuleType(snort::SnortConfig* sc, const char* name, + snort::Actions::Type, bool is_plugin_action = false); void FreeRuleTreeNode(RuleTreeNode*); void DestroyRuleTreeNode(RuleTreeNode*); diff --git a/src/protocols/packet.cc b/src/protocols/packet.cc index 546bf9ebe..1acc69da3 100644 --- a/src/protocols/packet.cc +++ b/src/protocols/packet.cc @@ -53,7 +53,7 @@ Packet::Packet(bool packet_data) obfuscator = nullptr; endianness = nullptr; - active_inst = new Active; + active_inst = new Active(); action_inst = nullptr; reset(); } diff --git a/src/protocols/packet.h b/src/protocols/packet.h index 12741ca46..e6c0265cf 100644 --- a/src/protocols/packet.h +++ b/src/protocols/packet.h @@ -33,7 +33,7 @@ namespace snort class Active; class Endianness; class Flow; -class IpsAction; +class ActiveAction; class IpsContext; class Obfuscator; class SFDAQInstance; @@ -137,8 +137,8 @@ struct SO_PUBLIC Packet IpsContext* context; Active* active; Active* active_inst; - IpsAction** action; - IpsAction* action_inst; + ActiveAction** action; + ActiveAction* action_inst; DAQ_Msg_h daq_msg; // DAQ message this packet came from SFDAQInstance* daq_instance; // DAQ instance the message came from @@ -385,3 +385,4 @@ inline uint64_t alignedNtohq(const uint64_t* ptr) } } #endif + diff --git a/src/pub_sub/active_events.h b/src/pub_sub/active_events.h index b09150632..425916393 100644 --- a/src/pub_sub/active_events.h +++ b/src/pub_sub/active_events.h @@ -34,22 +34,22 @@ class SO_PUBLIC ActiveEvent : public DataEvent { public: ActiveEvent - (const Active::ActiveAction current, const Active::ActiveAction previous, const Packet* p) + (const Active::ActiveActionType current, const Active::ActiveActionType previous, const Packet* p) : current_action(current), previous_action(previous), pkt(p) { } - Active::ActiveAction get_current_action() const + Active::ActiveActionType get_current_action() const { return current_action; } - Active::ActiveAction get_previous_action() const + Active::ActiveActionType get_previous_action() const { return previous_action; } const Packet* get_pkt() const { return pkt; } private: - const Active::ActiveAction current_action; - const Active::ActiveAction previous_action; + const Active::ActiveActionType current_action; + const Active::ActiveActionType previous_action; const Packet* pkt; }; } diff --git a/src/service_inspectors/smtp/smtp_module.cc b/src/service_inspectors/smtp/smtp_module.cc index af5416759..b9a5adce4 100644 --- a/src/service_inspectors/smtp/smtp_module.cc +++ b/src/service_inspectors/smtp/smtp_module.cc @@ -25,6 +25,7 @@ #include "smtp_module.h" #include "log/messages.h" +#include "packet_io/active.h" #include "utils/util.h" using namespace snort; @@ -329,7 +330,10 @@ bool SmtpModule::set(const char*, Value& v, SnortConfig*) } else if ( v.is("xlink2state") ) + { config->xlink2state = (XLINK2STATE)v.get_uint8(); + Active::set_enabled(); + } else return false;