From: Russ Combs Date: Mon, 18 Aug 2014 22:01:06 +0000 (-0400) Subject: added act_replace X-Git-Tag: 3.0.0-233~1422^2~3 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=ee18ef80101fb0f7883caa145c8704fe896d2791;p=thirdparty%2Fsnort3.git added act_replace --- diff --git a/ChangeLog b/ChangeLog index 6f1681e25..3d36adb9a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -5,7 +5,8 @@ ips_replace -- stream workarounds for new packet / protocol foo and shutdown sequencing -- fixed end of rule parsing to not require ; and recognize incomplete rules --- fixed executing a command wile paused +-- fixed executing a command while paused +-- added act_replace 112 -- initial action plugin - reject diff --git a/src/actions/CMakeLists.txt b/src/actions/CMakeLists.txt index bc770823d..8bd7e8c0b 100644 --- a/src/actions/CMakeLists.txt +++ b/src/actions/CMakeLists.txt @@ -12,7 +12,8 @@ set (IPS_ACTION_SOURCES set( PLUGIN_LIST act_react.cc act_reject.cc - act_resp.cc + act_replace.cc + act_replace.h ) if (STATIC_IPS_ACTIONS) @@ -34,7 +35,7 @@ else (STATIC_IPS_ACTIONS) add_shared_library(act_react actions act_react.cc) add_shared_library(act_reject actions act_reject.cc) - add_shared_library(act_resp actions act_resp.cc) + add_shared_library(act_replace actions act_replace.cc act_replace.h) endif (STATIC_IPS_ACTIONS) diff --git a/src/actions/Makefile.am b/src/actions/Makefile.am index 7ac113bad..7a4a0bb25 100644 --- a/src/actions/Makefile.am +++ b/src/actions/Makefile.am @@ -10,7 +10,8 @@ actions.h plugin_list = \ act_react.cc \ act_reject.cc \ -act_resp.cc +act_replace.cc \ +act_replace.h libips_actions_a_SOURCES = \ actions.cc \ @@ -32,10 +33,10 @@ libact_reject_la_CXXFLAGS = $(AM_CXXFLAGS) -DBUILDING_SO libact_reject_la_LDFLAGS = -export-dynamic -shared libact_reject_la_SOURCES = act_reject.cc -actlib_LTLIBRARIES += libact_resp.la -libact_resp_la_CXXFLAGS = $(AM_CXXFLAGS) -DBUILDING_SO -libact_resp_la_LDFLAGS = -export-dynamic -shared -libact_resp_la_SOURCES = act_resp.cc +actlib_LTLIBRARIES += libact_replace.la +libact_replace_la_CXXFLAGS = $(AM_CXXFLAGS) -DBUILDING_SO +libact_replace_la_LDFLAGS = -export-dynamic -shared +libact_replace_la_SOURCES = act_replace.cc act_replace.h endif AM_CXXFLAGS = @AM_CXXFLAGS@ diff --git a/src/actions/act_react.cc b/src/actions/act_react.cc index 282b9504a..e4aa9d5d0 100644 --- a/src/actions/act_react.cc +++ b/src/actions/act_react.cc @@ -100,7 +100,6 @@ struct ReactData int rule_msg; // 1=>use rule msg; 0=>use DEFAULT_MSG ssize_t buf_len; // length of response char* resp_buf; // response to send - }; static char* s_page = NULL; @@ -108,19 +107,20 @@ static char* s_page = NULL; class ReactAction : public IpsAction { public: - ReactAction(ReactData* c) : IpsAction(s_name) + ReactAction(ReactData* c) : IpsAction(s_name, ACT_PROXY) { config = c; }; ~ReactAction(); void exec(Packet*); +private: + void send(Packet*); + private: ReactData* config; }; -static void React_Send(Packet*, void*); - //------------------------------------------------------------------------- // class methods //------------------------------------------------------------------------- @@ -144,12 +144,24 @@ void ReactAction::exec(Packet* p) MODULE_PROFILE_START(reactPerfStats); if ( Active_IsRSTCandidate(p) ) - Active_QueueResponse(React_Send, config); + send(p); Active_DropSession(); MODULE_PROFILE_END(reactPerfStats); } +void ReactAction::send (Packet* p) +{ + EncodeFlags df = (p->packet_flags & PKT_FROM_SERVER) ? ENC_FLAG_FWD : 0; + EncodeFlags rf = ENC_FLAG_SEQ | (ENC_FLAG_VAL & config->buf_len); + + Active_IgnoreSession(p); + + Active_SendData(p, df, (uint8_t*)config->resp_buf, config->buf_len); + Active_SendReset(p, rf); + Active_SendReset(p, ENC_FLAG_FWD); +} + //------------------------------------------------------------------------- // implementation foo //------------------------------------------------------------------------- @@ -211,23 +223,6 @@ static bool react_getpage (const char* file) //-------------------------------------------------------------------- -static void React_Send (Packet* p, void* pv) -{ - ReactData* rd = (ReactData*)pv; - EncodeFlags df = (p->packet_flags & PKT_FROM_SERVER) ? ENC_FLAG_FWD : 0; - EncodeFlags rf = ENC_FLAG_SEQ | (ENC_FLAG_VAL & rd->buf_len); - PROFILE_VARS; - - MODULE_PROFILE_START(reactPerfStats); - Active_IgnoreSession(p); - - Active_SendData(p, df, (uint8_t*)rd->resp_buf, rd->buf_len); - Active_SendReset(p, rf); - Active_SendReset(p, ENC_FLAG_FWD); - - MODULE_PROFILE_END(reactPerfStats); -} - // format response buffer static void react_config (ReactData* rd) { diff --git a/src/actions/act_reject.cc b/src/actions/act_reject.cc index 7db8c104c..d29c7a6c6 100644 --- a/src/actions/act_reject.cc +++ b/src/actions/act_reject.cc @@ -1,114 +1,255 @@ +/**************************************************************************** + * + * Copyright (C) 2014 Cisco and/or its affiliates. All rights reserved. + * Copyright (C) 2005-2013 Sourcefire, Inc. + * + * 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 + * + ****************************************************************************/ /* -** Copyright (C) 2014 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. -*/ -// act_reject.cc author Russ Combs + * Perform flexible response on packets matching conditions specified in Snort + * rules. + * + * Shutdown hostile network connections by injecting TCP resets or ICMP + * unreachable packets. + * + * flexresp3 is derived from flexresp and flexresp2. It includes all + * configuration options from those modules and has these differences: + * + * - injects packets with correct encapsulations (doesn't assume + * eth+ip+icmp/tcp). + * + * - uses the wire packet as a prototype, not the packet generating the alert + * (which may be reassembled or otherwise generated internally with only the + * headers required for logging). + * + * - queues the injection action so that it is taken only once after detection + * regardless of multiple resp3 rules firing. + * + * - uses the same encoding and injection mechanism as active_response and/or + * reject actions. + * + * - bypasses sequence strafing in inline mode. + */ + +// act_rej.cc author Russ Combs #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "snort_types.h" -#include "framework/ips_action.h" -#include "framework/module.h" +#include "snort_debug.h" #include "protocols/packet.h" +#include "profiler.h" #include "packet_io/active.h" -#include "snort_debug.h" #include "snort.h" +#include "util.h" +#include "framework/ips_action.h" +#include "framework/parameter.h" +#include "framework/module.h" + +#define REJ_RST_SND 0x01 +#define REJ_RST_RCV 0x02 +#define REJ_UNR_NET 0x04 +#define REJ_UNR_HOST 0x08 +#define REJ_UNR_PORT 0x10 + +#define REJ_RST (REJ_RST_SND|REJ_RST_RCV) +#define REJ_UNR (REJ_UNR_NET|REJ_UNR_HOST|REJ_UNR_PORT) static const char* s_name = "reject"; +static THREAD_LOCAL ProfileStats rejPerfStats; + +class RejectAction : public IpsAction +{ +public: + RejectAction(uint32_t f) : IpsAction(s_name, ACT_RESET) + { mask = f; }; + + void exec(Packet*); + +private: + void send(Packet*); + +private: + uint32_t mask; +}; + //------------------------------------------------------------------------- -// reject module +// class methods //------------------------------------------------------------------------- -static const Parameter reject_params[] = +void RejectAction::exec(Packet* p) { + PROFILE_VARS; + MODULE_PROFILE_START(rejPerfStats); + + send(p); + + MODULE_PROFILE_END(rejPerfStats); +} + +void RejectAction::send(Packet* p) +{ + uint32_t flags = 0; + + if ( Active_IsRSTCandidate(p) ) + flags |= (mask & REJ_RST); + + if ( Active_IsUNRCandidate(p) ) + flags |= (mask & REJ_UNR); + + if ( flags & REJ_RST_SND ) + Active_SendReset(p, 0); + + if ( flags & REJ_RST_RCV ) + Active_SendReset(p, ENC_FLAG_FWD); + + if ( flags & REJ_UNR_NET ) + Active_SendUnreach(p, ENC_UNR_NET); + + if ( flags & REJ_UNR_HOST ) + Active_SendUnreach(p, ENC_UNR_HOST); + + if ( flags & REJ_UNR_PORT ) + Active_SendUnreach(p, ENC_UNR_PORT); + + Active_IgnoreSession(p); +} + +//------------------------------------------------------------------------- +// module +//------------------------------------------------------------------------- + +static const Parameter rej_params[] = +{ + { "reset_source", Parameter::PT_STRING, nullptr, nullptr, + "reset sender" }, + + { "rst_snd", Parameter::PT_STRING, nullptr, nullptr, + "reset sender" }, + + { "reset_dest", Parameter::PT_STRING, nullptr, nullptr, + "reset receiver" }, + + { "rst_rcv", Parameter::PT_STRING, nullptr, nullptr, + "reset receiver" }, + + { "reset_both", Parameter::PT_STRING, nullptr, nullptr, + "reset both sender and receiver" }, + + { "rst_all", Parameter::PT_STRING, nullptr, nullptr, + "reset both sender and receiver" }, + + { "icmp_net", Parameter::PT_STRING, nullptr, nullptr, + "send icmp network unreachable to sender" }, + + { "icmp_host", Parameter::PT_STRING, nullptr, nullptr, + "send icmp host unreachable to sender" }, + + { "icmp_port", Parameter::PT_STRING, nullptr, nullptr, + "send icmp port unreachable to sender" }, + + { "icmp_all", Parameter::PT_STRING, nullptr, nullptr, + "send icmp net, host, and port unreachable to sender" }, + { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr } }; class RejectModule : public Module { public: - RejectModule() : Module(s_name, reject_params) { }; - bool set(const char*, Value&, SnortConfig*); + RejectModule() : Module(s_name, rej_params) { }; + bool begin(const char*, int, SnortConfig*); - bool end(const char*, int, SnortConfig*); + bool set(const char*, Value&, SnortConfig*); -public: -}; + ProfileStats* get_profile() const + { return &rejPerfStats; }; -bool RejectModule::set(const char*, Value&, SnortConfig*) -{ - return false; -} + uint32_t flags; +}; bool RejectModule::begin(const char*, int, SnortConfig*) { + flags = 0; return true; } -bool RejectModule::end(const char*, int, SnortConfig*) +bool RejectModule::set(const char*, Value& v, SnortConfig*) { - return true; -} + if ( v.is("reset_source") || v.is("rst_snd") ) + flags |= REJ_RST_SND; -//------------------------------------------------------------------------- + else if ( v.is("reset_dest") || v.is("rst_rcv") ) + flags |= REJ_RST_RCV; -class RejectAction : public IpsAction -{ -public: - RejectAction(RejectModule*); + else if ( v.is("reset_both") || v.is("rst_all") ) + flags |= (REJ_RST_RCV | REJ_RST_SND); - void exec(Packet*); + else if ( v.is("icmp_net") ) + flags |= REJ_UNR_NET; -private: - unsigned flags; -}; + else if ( v.is("icmp_host") ) + flags |= REJ_UNR_HOST; -RejectAction::RejectAction(RejectModule*) : - IpsAction(s_name) -{ - Active_SetEnabled(1); -} + else if ( v.is("icmp_port") ) + flags |= REJ_UNR_PORT; -void RejectAction::exec(Packet* p) -{ - if ( PacketIsRebuilt(p) ) - return; + else if ( v.is("icmp_all") ) + flags |= (REJ_UNR_NET | REJ_UNR_HOST | REJ_UNR_PORT); - Active_QueueReject(); + else + return false; + + return true; } +//------------------------------------------------------------------------- +// api methods //------------------------------------------------------------------------- static Module* mod_ctor() -{ return new RejectModule; } +{ + return new RejectModule; +} static void mod_dtor(Module* m) -{ delete m; } +{ + delete m; +} -static IpsAction* rej_ctor(Module* m) -{ return new RejectAction((RejectModule*)m); } +static IpsAction* rej_ctor(Module* p) +{ + RejectModule* m = (RejectModule*)p; + return new RejectAction(m->flags); +} static void rej_dtor(IpsAction* p) -{ delete p; } +{ + delete p; +} -static ActionApi rej_api +static void rej_ginit() +{ + Active_SetEnabled(1); +} + +static const ActionApi rej_api = { { PT_IPS_ACTION, @@ -119,7 +260,7 @@ static ActionApi rej_api mod_dtor }, RULE_TYPE__DROP, - nullptr, + rej_ginit, nullptr, nullptr, nullptr, diff --git a/src/actions/act_resp.cc b/src/actions/act_resp.cc deleted file mode 100644 index 13be4ac6d..000000000 --- a/src/actions/act_resp.cc +++ /dev/null @@ -1,295 +0,0 @@ -/**************************************************************************** - * - * Copyright (C) 2014 Cisco and/or its affiliates. All rights reserved. - * Copyright (C) 2005-2013 Sourcefire, Inc. - * - * 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 - * - ****************************************************************************/ -/* - * Perform flexible response on packets matching conditions specified in Snort - * rules. - * - * Shutdown hostile network connections by injecting TCP resets or ICMP - * unreachable packets. - * - * flexresp3 is derived from flexresp and flexresp2. It includes all - * configuration options from those modules and has these differences: - * - * - injects packets with correct encapsulations (doesn't assume - * eth+ip+icmp/tcp). - * - * - uses the wire packet as a prototype, not the packet generating the alert - * (which may be reassembled or otherwise generated internally with only the - * headers required for logging). - * - * - queues the injection action so that it is taken only once after detection - * regardless of multiple resp3 rules firing. - * - * - uses the same encoding and injection mechanism as active_response and/or - * reject actions. - * - * - bypasses sequence strafing in inline mode. - */ - -// act_resp.cc author Russ Combs - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "snort_types.h" -#include "snort_debug.h" -#include "protocols/packet.h" -#include "profiler.h" -#include "packet_io/active.h" -#include "snort.h" -#include "util.h" -#include "framework/ips_action.h" -#include "framework/parameter.h" -#include "framework/module.h" - -#define RESP_RST_SND 0x01 -#define RESP_RST_RCV 0x02 -#define RESP_UNR_NET 0x04 -#define RESP_UNR_HOST 0x08 -#define RESP_UNR_PORT 0x10 - -#define RESP_RST (RESP_RST_SND|RESP_RST_RCV) -#define RESP_UNR (RESP_UNR_NET|RESP_UNR_HOST|RESP_UNR_PORT) - -// FIXIT this should merge with or replace reject -static const char* s_name = "resp"; - -static THREAD_LOCAL ProfileStats resp3PerfStats; - -// instance data -struct Resp3_Data -{ - uint32_t mask; -}; - -class RespondAction : public IpsAction -{ -public: - RespondAction(uint32_t f) : IpsAction(s_name) - { config.mask = f; }; - - void exec(Packet*); - -private: - Resp3_Data config; -}; - -static void Resp3_Send(Packet*, void*); - -//------------------------------------------------------------------------- -// class methods -//------------------------------------------------------------------------- - -void RespondAction::exec(Packet*) -{ - PROFILE_VARS; - MODULE_PROFILE_START(resp3PerfStats); - - Active_QueueResponse(Resp3_Send, &config); - - MODULE_PROFILE_END(resp3PerfStats); -} - -//-------------------------------------------------------------------- -// core functions -//-------------------------------------------------------------------- - -static void Resp3_Send (Packet* p, void* pv) -{ - PROFILE_VARS; - MODULE_PROFILE_START(resp3PerfStats); - - Resp3_Data* rd = (Resp3_Data*)pv; - uint32_t flags = 0; - - if ( Active_IsRSTCandidate(p) ) - flags |= (rd->mask & RESP_RST); - - if ( Active_IsUNRCandidate(p) ) - flags |= (rd->mask & RESP_UNR); - - if ( flags & RESP_RST_SND ) - Active_SendReset(p, 0); - - if ( flags & RESP_RST_RCV ) - Active_SendReset(p, ENC_FLAG_FWD); - - if ( flags & RESP_UNR_NET ) - Active_SendUnreach(p, ENC_UNR_NET); - - if ( flags & RESP_UNR_HOST ) - Active_SendUnreach(p, ENC_UNR_HOST); - - if ( flags & RESP_UNR_PORT ) - Active_SendUnreach(p, ENC_UNR_PORT); - - Active_IgnoreSession(p); - MODULE_PROFILE_END(resp3PerfStats); -} - -//------------------------------------------------------------------------- -// module -//------------------------------------------------------------------------- - -static const Parameter resp_params[] = -{ - { "reset_source", Parameter::PT_STRING, nullptr, nullptr, - "reset sender" }, - - { "rst_snd", Parameter::PT_STRING, nullptr, nullptr, - "reset sender" }, - - { "reset_dest", Parameter::PT_STRING, nullptr, nullptr, - "reset receiver" }, - - { "rst_rcv", Parameter::PT_STRING, nullptr, nullptr, - "reset receiver" }, - - { "reset_both", Parameter::PT_STRING, nullptr, nullptr, - "reset both sender and receiver" }, - - { "rst_all", Parameter::PT_STRING, nullptr, nullptr, - "reset both sender and receiver" }, - - { "icmp_net", Parameter::PT_STRING, nullptr, nullptr, - "send icmp network unreachable to sender" }, - - { "icmp_host", Parameter::PT_STRING, nullptr, nullptr, - "send icmp host unreachable to sender" }, - - { "icmp_port", Parameter::PT_STRING, nullptr, nullptr, - "send icmp port unreachable to sender" }, - - { "icmp_all", Parameter::PT_STRING, nullptr, nullptr, - "send icmp net, host, and port unreachable to sender" }, - - { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr } -}; - -class RespModule : public Module -{ -public: - RespModule() : Module(s_name, resp_params) { }; - - bool begin(const char*, int, SnortConfig*); - bool set(const char*, Value&, SnortConfig*); - - ProfileStats* get_profile() const - { return &resp3PerfStats; }; - - uint32_t flags; -}; - -bool RespModule::begin(const char*, int, SnortConfig*) -{ - flags = 0; - return true; -} - -bool RespModule::set(const char*, Value& v, SnortConfig*) -{ - if ( v.is("reset_source") || v.is("rst_snd") ) - flags |= RESP_RST_SND; - - else if ( v.is("reset_dest") || v.is("rst_rcv") ) - flags |= RESP_RST_RCV; - - else if ( v.is("reset_both") || v.is("rst_all") ) - flags |= (RESP_RST_RCV | RESP_RST_SND); - - else if ( v.is("icmp_net") ) - flags |= RESP_UNR_NET; - - else if ( v.is("icmp_host") ) - flags |= RESP_UNR_HOST; - - else if ( v.is("icmp_port") ) - flags |= RESP_UNR_PORT; - - else if ( v.is("icmp_all") ) - flags |= (RESP_UNR_NET | RESP_UNR_HOST | RESP_UNR_PORT); - - else - return false; - - return true; -} - -//------------------------------------------------------------------------- -// api methods -//------------------------------------------------------------------------- - -static Module* mod_ctor() -{ - return new RespModule; -} - -static void mod_dtor(Module* m) -{ - delete m; -} - -static IpsAction* resp_ctor(Module* p) -{ - RespModule* m = (RespModule*)p; - return new RespondAction(m->flags); -} - -static void resp_dtor(IpsAction* p) -{ - delete p; -} - -static void resp_ginit() -{ - Active_SetEnabled(1); -} - -static const ActionApi resp_api = -{ - { - PT_IPS_ACTION, - s_name, - ACTAPI_PLUGIN_V0, - 0, - mod_ctor, - mod_dtor - }, - RULE_TYPE__DROP, - resp_ginit, - nullptr, - nullptr, - nullptr, - resp_ctor, - resp_dtor -}; - -#ifdef BUILDING_SO -SO_PUBLIC const BaseApi* snort_plugins[] = -{ - &resp_api.base, - nullptr -}; -#else -const BaseApi* act_resp = &resp_api.base; -#endif - diff --git a/src/actions/ips_actions.cc b/src/actions/ips_actions.cc index 75d7e5ecf..7e8e65241 100644 --- a/src/actions/ips_actions.cc +++ b/src/actions/ips_actions.cc @@ -27,7 +27,7 @@ #ifdef STATIC_IPS_ACTIONS extern const BaseApi* act_react; extern const BaseApi* act_reject; -extern const BaseApi* act_resp; +extern const BaseApi* act_replace; #endif const BaseApi* ips_actions[] = @@ -35,7 +35,7 @@ const BaseApi* ips_actions[] = #ifdef STATIC_IPS_ACTIONS act_react, act_reject, - act_resp, + act_replace, #endif nullptr, }; diff --git a/src/detection/detection_options.cc b/src/detection/detection_options.cc index 55f7666b7..1d73c7b8c 100644 --- a/src/detection/detection_options.cc +++ b/src/detection/detection_options.cc @@ -49,7 +49,6 @@ #include "ips_options/ips_flowbits.h" #include "ips_options/ips_content.h" #include "ips_options/ips_pcre.h" -#include "ips_options/ips_replace.h" #include "fpdetect.h" #include "ppm.h" #include "profiler.h" @@ -383,7 +382,7 @@ int detection_option_node_evaluate( detection_option_tree_node_t *node, detection_option_eval_data_t *eval_data, Cursor& orig_cursor) { - int i, result = 0; //, prior_result = 0; + int i, result = 0; int rval = DETECTION_OPTION_NO_MATCH; char tmp_noalert_flag = 0; Cursor cursor = orig_cursor; @@ -723,20 +722,6 @@ int detection_option_node_evaluate( // node->children[i]->result; } -#if 0 - // FIXIT replace is broken now :( - if (result - prior_result > 0 - && node->option_type == RULE_OPTION_TYPE_CONTENT - && Replace_OffsetStored(content_data) && ScInlineMode()) - { - // FIXIT queuing replacements here is premature - // should be done if / when rule actually fires - // and at that point, the change can be applied - Replace_QueueChange(content_data); - prior_result = result; - } -#endif - NODE_PROFILE_TMPSTART(node); if (rval == DETECTION_OPTION_NO_ALERT) diff --git a/src/detection/fpdetect.cc b/src/detection/fpdetect.cc index a9e49108d..60fb9e291 100644 --- a/src/detection/fpdetect.cc +++ b/src/detection/fpdetect.cc @@ -147,15 +147,15 @@ static inline void InitMatchInfo(OTNX_MATCH_DATA *o) static inline void fpLogOther ( Packet* p, RuleTreeNode* rtn, OptTreeNode* otn, int action) { - // FIXIT some or all of these can be migrated to user defined actions - otn_trigger_actions(otn, p); - if ( EventTrace_IsEnabled() ) EventTrace_Log(p, otn, action); - // user defined actions are done here + // rule option actions are queued here (eg replace) + otn_trigger_actions(otn, p); + + // rule actions are queued here (eg reject) if ( rtn->listhead->action ) - rtn->listhead->action->exec(p); + ActionManager::queue(rtn->listhead->action); } /* diff --git a/src/file_api/file_resume_block.cc b/src/file_api/file_resume_block.cc index 0e5cfc491..d233c01b9 100644 --- a/src/file_api/file_resume_block.cc +++ b/src/file_api/file_resume_block.cc @@ -35,6 +35,7 @@ #include "protocols/packet.h" #include "packet_io/active.h" #include "libs/file_sha256.h" +#include "managers/action_manager.h" /* The hash table of expected files */ static THREAD_LOCAL_TBD SFXHASH *fileHash = NULL; @@ -199,7 +200,7 @@ static inline File_Verdict checkVerdict(Packet *p, FileNode *node, SFXHASH_NODE { Active_ForceDropPacket(); Active_DropSession(); - Active_QueueReject(); + ActionManager::queue_reject(); if (log_file_action) { log_file_action(p->flow, FILE_RESUME_BLOCK); @@ -212,7 +213,7 @@ static inline File_Verdict checkVerdict(Packet *p, FileNode *node, SFXHASH_NODE Active_ForceDropPacket(); Active_DropSession(); if (FILE_VERDICT_REJECT == node->verdict) - Active_QueueReject(); + ActionManager::queue_reject(); if (log_file_action) { log_file_action(p->flow, FILE_RESUME_BLOCK); diff --git a/src/framework/ips_action.h b/src/framework/ips_action.h index 933cf5663..8dc556caa 100644 --- a/src/framework/ips_action.h +++ b/src/framework/ips_action.h @@ -38,6 +38,16 @@ struct Packet; // api for class //------------------------------------------------------------------------- +enum ActionType +{ + ACT_LOCAL, + ACT_MODIFY, + ACT_PROXY, + ACT_RESET, + ACT_REMOTE, + ACT_MAX +}; + struct SnortConfig; class IpsAction @@ -48,13 +58,15 @@ public: virtual void exec(Packet*) = 0; const char* get_name() const { return name; }; + ActionType get_action() { return action; } protected: - IpsAction(const char* s) - { name = s; }; + IpsAction(const char* s, ActionType a) + { name = s; action = a; }; 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 de4a57ad1..d1c4c86cd 100644 --- a/src/ips_options/ips_replace.cc +++ b/src/ips_options/ips_replace.cc @@ -19,8 +19,6 @@ ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#include "ips_replace.h" - #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -43,8 +41,7 @@ using namespace std; #include "framework/parameter.h" #include "framework/module.h" #include "detection/detection_defines.h" - -#define MAX_PATTERN_SIZE 2048 +#include "actions/act_replace.h" static void replace_parse(const char* args, string& s) { @@ -78,67 +75,6 @@ static bool replace_ok() return true; } -//-------------------------------------------------------------------------- -// queue foo -//-------------------------------------------------------------------------- - -struct Replacement -{ - string data; - int offset; -}; - -#define MAX_REPLACEMENTS 32 -static THREAD_LOCAL Replacement* rpl; -static THREAD_LOCAL int num_rpl = 0; - -void Replace_ResetQueue(void) -{ - num_rpl = 0; -} - -void Replace_QueueChange(string& s, int off) -{ - Replacement* r; - - if ( num_rpl == MAX_REPLACEMENTS ) - return; - - r = rpl + num_rpl++; - - r->data = s; - r->offset = off; -} - -static inline void Replace_ApplyChange(Packet *p, Replacement* r) -{ - uint8_t* start = (uint8_t*)p->data + r->offset; - const uint8_t* end = p->data + p->dsize; - unsigned len; - - if ( (start + r->data.size()) >= end ) - len = p->dsize - r->offset; - else - len = r->data.size(); - - memcpy(start, r->data.c_str(), len); -} - -// FIXIT this could be ContentOption::action() -// for a more general packet rewriting facility -void Replace_ModifyPacket(Packet *p) -{ - if ( num_rpl == 0 ) - return; - - for ( int n = 0; n < num_rpl; n++ ) - { - Replace_ApplyChange(p, rpl+n); - } - p->packet_flags |= PKT_MODIFIED; - num_rpl = 0; -} - //------------------------------------------------------------------------- // replace rule option //------------------------------------------------------------------------- @@ -231,25 +167,22 @@ int ReplaceOption::eval(Cursor& c, Packet* p) if ( !c.is("pkt_data") ) return DETECTION_OPTION_NO_MATCH; - if ( c.length() < repl.size() ) + if ( c.get_pos() < repl.size() ) return DETECTION_OPTION_NO_MATCH; - store(c.get_pos()); + store(c.get_pos() - repl.size()); MODULE_PROFILE_END(replacePerfStats); return DETECTION_OPTION_MATCH; } -// FIXIT this may need to be apply change here -// and queue change from some other point -// (almost certainly broke) void ReplaceOption::action(Packet*) { PROFILE_VARS; MODULE_PROFILE_START(replacePerfStats); if ( pending() ) - Replace_QueueChange(repl, pos()); + Replace_QueueChange(repl, (unsigned)pos()); MODULE_PROFILE_END(replacePerfStats); } @@ -260,8 +193,8 @@ void ReplaceOption::action(Packet*) static const Parameter repl_params[] = { - { "~mode", Parameter::PT_ENUM, "printable|binary|all", nullptr, - "output format" }, + { "~", Parameter::PT_STRING, nullptr, nullptr, + "byte code to replace with" }, { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr } }; @@ -288,7 +221,7 @@ bool ReplModule::begin(const char*, int, SnortConfig*) bool ReplModule::set(const char*, Value& v, SnortConfig*) { - if ( v.is("~mode") ) + if ( v.is("~") ) replace_parse(v.get_string(), data); else @@ -333,16 +266,6 @@ static void replace_dtor(IpsOption* p) delete p; } -static void replace_tinit(SnortConfig*) -{ - rpl = new Replacement[MAX_REPLACEMENTS]; -} - -static void replace_tterm(SnortConfig*) -{ - delete[] rpl; -} - static const IpsApi replace_api = { { @@ -357,8 +280,8 @@ static const IpsApi replace_api = 0, 0, nullptr, nullptr, - replace_tinit, - replace_tterm, + nullptr, + nullptr, replace_ctor, replace_dtor, nullptr diff --git a/src/ips_options/ips_replace.h b/src/ips_options/ips_replace.h deleted file mode 100644 index 045918dc3..000000000 --- a/src/ips_options/ips_replace.h +++ /dev/null @@ -1,36 +0,0 @@ -/* -** Copyright (C) 2014 Cisco and/or its affiliates. All rights reserved. -** Copyright (C) 2002-2013 Sourcefire, Inc. -** Copyright (C) 1998-2002 Martin Roesch -** -** 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. -*/ - -#ifndef REPLACE_H -#define REPLACE_H - -#include -#include "ips_content.h" -#include "main/thread.h" - -void PayloadReplaceInit(PatternMatchData*, char*, OptTreeNode*); - -void Replace_ResetQueue(void); -void Replace_QueueChange(PatternMatchData*); -void Replace_ModifyPacket(Packet*); - -#endif - diff --git a/src/main/snort.cc b/src/main/snort.cc index 6948a6aeb..462afb641 100644 --- a/src/main/snort.cc +++ b/src/main/snort.cc @@ -55,7 +55,6 @@ using namespace std; #include "helpers/process.h" #include "protocols/packet.h" -#include "managers/packet_manager.h" #include "packet_io/sfdaq.h" #include "packet_io/active.h" #include "rules.h" @@ -89,6 +88,7 @@ using namespace std; #include "managers/ips_manager.h" #include "managers/mpse_manager.h" #include "managers/packet_manager.h" +#include "managers/action_manager.h" #include "detection/sfrim.h" #include "ppm.h" #include "profiler.h" @@ -107,7 +107,7 @@ using namespace std; #include "target_based/sftarget_reader.h" #include "stream/stream_api.h" #include "stream/stream.h" -#include "ips_options/ips_replace.h" +#include "actions/act_replace.h" #ifdef INTEL_SOFT_CPM #include "search/intel_soft_cpm.h" @@ -285,6 +285,22 @@ static void register_profiles() // initialization //------------------------------------------------------------------------- +static void init_policy(SnortConfig* sc) +{ + PolicyMode pm; + + if ( sc->run_flags & RUN_FLAG__INLINE ) + pm = POLICY_MODE__INLINE; + + else if ( sc->run_flags & RUN_FLAG__INLINE_TEST ) + pm = POLICY_MODE__INLINE_TEST; + + else + pm = POLICY_MODE__PASSIVE; + + sc->get_ips_policy()->policy_mode = pm; +} + static void SnortInit(int argc, char **argv) { init_signals(); @@ -333,6 +349,7 @@ static void SnortInit(int argc, char **argv) * command line overriding config file. * Set the global snort_conf that will be used during run time */ snort_conf = MergeSnortConfs(snort_cmd_line_conf, sc); + init_policy(snort_conf); if ( snort_conf->output ) EventManager::instantiate(snort_conf->output, sc); @@ -617,6 +634,7 @@ static SnortConfig * get_reload_config(void) SnortConfig *sc = ParseSnortConf(snort_cmd_line_conf); sc = MergeSnortConfs(snort_cmd_line_conf, sc); + init_policy(sc); #ifdef PERF_PROFILING /* Parse profiling here because of file option and potential @@ -888,16 +906,14 @@ DAQ_Verdict packet_callback( MODULE_PROFILE_START(eventqPerfStats); SnortEventqReset(); - Replace_ResetQueue(); - Active_ResetQueue(); MODULE_PROFILE_END(eventqPerfStats); + ActionManager::reset_queue(); + verdict = ProcessPacket(&s_packet, pkthdr, pkt); - if ( Active_ResponseQueued() ) - { - Active_SendResponses(&s_packet); - } + ActionManager::execute(&s_packet); + if ( Active_PacketWasDropped() ) { if ( verdict == DAQ_VERDICT_PASS ) @@ -905,8 +921,6 @@ DAQ_Verdict packet_callback( } else { - Replace_ModifyPacket(&s_packet); - if ( s_packet.packet_flags & PKT_MODIFIED ) { // this packet was normalized and/or has replacements @@ -1003,6 +1017,7 @@ void snort_thread_init(const char* intf) EventManager::open_outputs(); IpsManager::setup_options(); + ActionManager::thread_init(snort_conf); InspectorManager::thread_init(snort_conf); } @@ -1013,6 +1028,7 @@ void snort_thread_term() #endif ModuleManager::accumulate(snort_conf); InspectorManager::thread_term(snort_conf); + ActionManager::thread_term(snort_conf); IpsManager::clear_options(); EventManager::close_outputs(); diff --git a/src/managers/action_manager.cc b/src/managers/action_manager.cc index e7c814b71..d5f93ea29 100644 --- a/src/managers/action_manager.cc +++ b/src/managers/action_manager.cc @@ -33,10 +33,14 @@ using namespace std; #include "search_engines/search_engines.h" #include "parser/parser.h" #include "log/messages.h" +#include "actions/act_replace.h" typedef list AList; static AList s_actors; +static IpsAction* s_reject = nullptr; +static THREAD_LOCAL IpsAction* s_action = nullptr; + //------------------------------------------------------------------------- // engine plugins //------------------------------------------------------------------------- @@ -78,12 +82,29 @@ void ActionManager::instantiate( if ( act ) { + if ( !s_reject && !strcmp(act->get_name(), "reject") ) + s_reject = act; + ListHead* lh = CreateRuleType(sc, api->base.name, api->type, 0, nullptr); assert(lh); lh->action = act; } } +void ActionManager::thread_init(SnortConfig*) +{ + for ( auto* p : s_actors ) + if ( p->tinit ) + p->tinit(); +} + +void ActionManager::thread_term(SnortConfig*) +{ + for ( auto* p : s_actors ) + if ( p->tterm ) + p->tterm(); +} + #if 0 static const ActionApi* get_api(const char* keyword) { @@ -95,6 +116,30 @@ static const ActionApi* get_api(const char* keyword) } #endif -void ActionManager::execute(Packet*) -{ } +void ActionManager::execute(Packet* p) +{ + if ( s_action ) + { + s_action->exec(p); + s_action = nullptr; + } +} + +void ActionManager::queue(IpsAction* a) +{ + if ( !s_action || a->get_action() > s_action->get_action() ) + s_action = a; +} + +void ActionManager::queue_reject() +{ + if ( s_reject ) + queue(s_reject); +} + +void ActionManager::reset_queue() +{ + s_action = nullptr; + Replace_ResetQueue(); +} diff --git a/src/managers/action_manager.h b/src/managers/action_manager.h index f8974abd2..738650bed 100644 --- a/src/managers/action_manager.h +++ b/src/managers/action_manager.h @@ -45,6 +45,13 @@ public: static RuleType get_action_type(const char*); static void instantiate(const ActionApi*, Module*, SnortConfig*); + + static void thread_init(SnortConfig*); + static void thread_term(SnortConfig*); + + static void reset_queue(); + static void queue_reject(); + static void queue(IpsAction*); static void execute(struct Packet*); }; diff --git a/src/packet_io/active.cc b/src/packet_io/active.cc index 68d400665..e46cf9df0 100644 --- a/src/packet_io/active.cc +++ b/src/packet_io/active.cc @@ -38,6 +38,7 @@ #include "stream/stream_api.h" #include "snort.h" +#include "managers/action_manager.h" #include "managers/packet_manager.h" #include "packet_io/sfdaq.h" @@ -56,9 +57,6 @@ THREAD_LOCAL int active_suspend = 0; THREAD_LOCAL int active_have_rsp = 0; -static THREAD_LOCAL void* s_rejData, *s_rspData; -static THREAD_LOCAL Active_ResponseFunc s_rejFunc = NULL, s_rspFunc = NULL; - static THREAD_LOCAL uint64_t s_injects = 0; typedef int (*send_t) ( @@ -83,73 +81,6 @@ static inline PROTO_ID GetInnerProto (const Packet* p) return ( p->layers[p->num_layers-1].proto ); } -//-------------------------------------------------------------------- -// this implementation ensures that flexible responses -// take precedence over active responses. - -int Active_QueueReject (void) -{ - if ( Active_Suspended() ) - return 0; - - if ( !s_rejFunc ) - { - s_rejFunc = (Active_ResponseFunc)Active_KillSession; - s_rejData = NULL; - active_have_rsp = 1; - } - return 0; -} - -int Active_QueueResponse (Active_ResponseFunc f, void* pv) -{ - if ( Active_Suspended() ) - return 0; - - if ( !s_rspFunc ) - { - s_rspFunc = f; - s_rspData = pv; - active_have_rsp = 1; - } - return 0; -} - -// helper function -static inline void Active_ClearQueue (void) -{ - s_rejFunc = s_rspFunc = NULL; - s_rejData = s_rspData = NULL; -} - -int Active_ResetQueue () -{ - Active_ClearQueue(); - return 0; -} - -int Active_SendResponses (Packet* p) -{ - if ( s_rspFunc ) - { - s_rspFunc(p, s_rspData); - } - else if ( s_rejFunc ) - { - s_rejFunc(p, s_rejData); - } - else - { - return 0; - } - if ( p->flow ) - { - stream.init_active_response(p, p->flow); - } - Active_ClearQueue(); - return 1; -} - //-------------------------------------------------------------------- void Active_KillSession (Packet* p, EncodeFlags* pf) @@ -435,7 +366,7 @@ static inline int _Active_DoReset(Packet *p) { case IPPROTO_TCP: if ( Active_IsRSTCandidate(p) ) - Active_QueueReject(); + ActionManager::queue_reject(); break; // FIXIT send unr to udp/icmp4/icmp6 only or for all non-tcp? @@ -443,7 +374,7 @@ static inline int _Active_DoReset(Packet *p) case IPPROTO_ICMP: case IPPROTO_ICMPV6: if ( Active_IsUNRCandidate(p) ) - Active_QueueReject(); + ActionManager::queue_reject(); break; } diff --git a/src/packet_io/active.h b/src/packet_io/active.h index 62b448b28..8ba4cb5ec 100644 --- a/src/packet_io/active.h +++ b/src/packet_io/active.h @@ -33,15 +33,6 @@ int Active_Init(SnortConfig*); int Active_Term(void); -typedef void (*Active_ResponseFunc)(Packet*, void* data); - -int Active_QueueReject(void); -int Active_QueueResponse(Active_ResponseFunc, void*); -int Active_ResetQueue(void); - -// this must be called on the wire packet and not a -// reassembled packet so that encoding is correct. -int Active_SendResponses(Packet*); uint64_t Active_GetInjects(void); // NULL flags implies ENC_FLAG_FWD diff --git a/src/parser/parser.cc b/src/parser/parser.cc index 598992b34..d1ec1909d 100644 --- a/src/parser/parser.cc +++ b/src/parser/parser.cc @@ -619,8 +619,6 @@ SnortConfig * ParseSnortConf(const SnortConfig* boot_conf) OtnInit(sc); - InitVarTables(sc->policy_map->ips_policy[0]); - sc->fast_pattern_config = FastPatternConfigNew(); sc->event_queue_config = EventQueueConfigNew(); sc->threshold_config = ThresholdConfigNew();