]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Merge pull request #2800 in SNORT/snort3 from ~BBANTWAL/snort3:ips_actions to master
authorMichael Altizer (mialtize) <mialtize@cisco.com>
Fri, 26 Mar 2021 19:20:37 +0000 (19:20 +0000)
committerMichael Altizer (mialtize) <mialtize@cisco.com>
Fri, 26 Mar 2021 19:20:37 +0000 (19:20 +0000)
Squashed commit of the following:

commit 9ea4a671998c7c5270d91ca26ee1cca8228030ff
Author: Bhagya Tholpady <bbantwal@cisco.com>
Date:   Fri Mar 26 12:08:39 2021 -0400

    actions: dynamically construct the default eval order for all the loaded ips actions

commit 39c59c2dd92c4ad3b1ed1d3ac4914c511b5a7edf
Author: Bhagya Tholpady <bbantwal@cisco.com>
Date:   Sun Mar 21 13:07:52 2021 -0400

    detection: Update the rtn's listHead to reflect the new action set in the rule state

commit 628648057da9d38fc7c212a209427623700efaa3
Author: Bhagya Tholpady <bbantwal@cisco.com>
Date:   Thu Mar 25 09:48:18 2021 -0400

    rate_filter: Get the available ips actions dynamically to configure the new_action

commit 15c13d82d360fc37aa83ebf30dea71b2877b5a14
Author: Bhagya Tholpady <bbantwal@cisco.com>
Date:   Wed Mar 17 12:13:06 2021 -0400

    snort_config: Remove is_active_enabled and set_active_enabled functions

commit fce81b9ed016b3aa118371fec104cc3d62c5109b
Author: Bhagya Tholpady <bbantwal@cisco.com>
Date:   Tue Mar 16 14:26:49 2021 -0400

    snort2lua: delete conversion of disable_replace option

commit 13ad5f9b33620576f11483058425fc8b43031acc
Author: Bhagya Tholpady <bbantwal@cisco.com>
Date:   Tue Mar 9 11:33:31 2021 -0500

    actions: Make all IPS actions pluggable

    * All actions, including the previously "built-in" actions, have been
    refactored into a set of equal IPS action plugins. Each IPS action has
    an immediate effect and may or may not contain an active response to be
    carried out as a delayed action.
    * The reset and reject IPS actions have been merged into a single
    reject IPS action. The reject IPS action can no longer be built as a
    dynamic plugin.
    * All IPS actions will be instantiated in a default state in each IPS
    policy where they have not been otherwise explicitly configured via a
    module.
    * The rewrite IPS action is no longer configurable and has lost its
    module. Its active response priority has been corrected to AP_MODIFY.
    * Rate filter thresholding has been corrected to apply to any IPS
    action that drops traffic.
    * Rule evaluation action ordering has been expanded to include all
    IPS actions, static and dynamic. Dynamic actions will currently default
    to the lowest priority.

57 files changed:
doc/user/active.txt
lua/snort.lua
src/actions/CMakeLists.txt
src/actions/act_alert.cc [new file with mode: 0644]
src/actions/act_block.cc [new file with mode: 0644]
src/actions/act_drop.cc [new file with mode: 0644]
src/actions/act_log.cc [new file with mode: 0644]
src/actions/act_pass.cc [new file with mode: 0644]
src/actions/act_react.cc
src/actions/act_reject.cc
src/actions/act_replace.cc
src/actions/actions.cc
src/actions/actions.h
src/actions/dev_notes.txt
src/actions/ips_actions.cc
src/detection/detection_engine.cc
src/detection/detection_engine.h
src/detection/detection_util.cc
src/detection/detection_util.h
src/detection/fp_detect.cc
src/detection/rules.cc
src/detection/rules.h
src/detection/signature.cc
src/detection/treenodes.h
src/events/event_queue.h
src/file_api/file_module.cc
src/filters/sfrf.cc
src/filters/sfrf.h
src/filters/sfrf_test.cc
src/framework/ips_action.h
src/main/modules.cc
src/main/policy.cc
src/main/policy.h
src/main/snort.cc
src/main/snort_config.cc
src/main/snort_config.h
src/managers/action_manager.cc
src/managers/action_manager.h
src/packet_io/active.cc
src/packet_io/active_action.h
src/parser/parse_conf.cc
src/parser/parse_conf.h
src/parser/parse_rule.cc
src/parser/parser.cc
src/parser/parser.h
src/payload_injector/test/payload_injector_test.cc
src/piglet_plugins/pp_inspector_iface.cc
src/piglet_plugins/pp_ips_action_iface.cc
src/service_inspectors/http2_inspect/test/http2_hpack_int_decode_test.cc
src/service_inspectors/http2_inspect/test/http2_hpack_string_decode_test.cc
src/service_inspectors/http_inspect/test/http_module_test.cc
src/service_inspectors/http_inspect/test/http_transaction_test.cc
src/service_inspectors/http_inspect/test/http_uri_norm_test.cc
src/service_inspectors/smtp/smtp_module.cc
tools/snort2lua/config_states/config_deleted.cc
tools/snort2lua/config_states/config_no_option.cc
tools/snort2lua/rule_states/rule_replace.cc

index 5ea2d0475dab36ecc6a5266c5b7c24ef49ac19b2..2acaf189b190260b1cc7644ae5054ef4d5f149f0 100644 (file)
@@ -24,7 +24,9 @@ plugins:
 
     react = { }
     reject = { }
-    rewrite = { }
+
+When these active responses are not configured the default configuration
+is used.
 
 Active responses will be performed for reject, react or rewrite IPS rule 
 actions, and response packets are encoded based on the triggering packet. 
@@ -164,7 +166,6 @@ option in the rules.
 
 For example:
 
-    rewrite = { }
     local_rules =
     [[
     rewrite tcp 10.1.1.87 any -> 10.1.1.0/24 80
@@ -183,12 +184,3 @@ For example:
 
 this rule replaces "index.php" with "indax.php", and rewrite action 
 updates that packet.
-
-to enable rewrite action:
-
-    rewrite = { }
-
-the replace operation can be disabled by changing the configuration:
-
-    rewrite = { disable_replace = true }
-
index dc9df2c8a9326edcb3115545d765eb2d0b70ac3f..e0b5a3d3d794c968f8729e323b514a67cb6850fc 100644 (file)
@@ -178,8 +178,6 @@ ips =
     variables = default_variables
 }
 
-rewrite = { }
-
 -- use these to configure additional rule actions
 -- react = { }
 -- reject = { }
index f12a5a84ead1dde6b6c04564865f6768e575b78e..acb3102ce3bd8746dc9502154338ffa532c1a578 100644 (file)
@@ -7,12 +7,17 @@ set (IPS_ACTION_SOURCES
     actions.cc
     ips_actions.cc
     ips_actions.h
+    act_alert.cc
+    act_block.cc
+    act_drop.cc
+    act_log.cc
+    act_pass.cc
+    act_reject.cc
     act_replace.cc
 )
 
 set( PLUGIN_LIST
     act_react.cc
-    act_reject.cc
     )
 
 if (STATIC_IPS_ACTIONS)
@@ -28,7 +33,6 @@ else (STATIC_IPS_ACTIONS)
     )
 
     add_dynamic_module(act_react ips_actions act_react.cc)
-    add_dynamic_module(act_reject ips_actions act_reject.cc)
 
 endif (STATIC_IPS_ACTIONS)
 
diff --git a/src/actions/act_alert.cc b/src/actions/act_alert.cc
new file mode 100644 (file)
index 0000000..a2b4e9e
--- /dev/null
@@ -0,0 +1,88 @@
+//--------------------------------------------------------------------------
+// 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.
+//--------------------------------------------------------------------------
+// act_alert.cc author Bhagya Tholpady <bbantwal@cisco.com>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "framework/ips_action.h"
+#include "framework/module.h"
+#include "protocols/packet.h"
+
+#include "actions.h"
+
+using namespace snort;
+
+#define s_name "alert"
+
+#define s_help \
+    "generate alert on the current packet"
+
+//-------------------------------------------------------------------------
+class AlertAction : public IpsAction
+{
+public:
+    AlertAction() : IpsAction(s_name, nullptr) { }
+
+    void exec(Packet*, const OptTreeNode* otn) override;
+};
+
+void AlertAction::exec(Packet* p, const OptTreeNode* otn)
+{
+    if ( otn )
+        Actions::alert(p, otn);
+}
+
+//-------------------------------------------------------------------------
+
+static IpsAction* alert_ctor(Module*)
+{ return new AlertAction; }
+
+static void alert_dtor(IpsAction* p)
+{ delete p; }
+
+static ActionApi alert_api
+{
+    {
+        PT_IPS_ACTION,
+        sizeof(ActionApi),
+        ACTAPI_VERSION,
+        0,
+        API_RESERVED,
+        API_OPTIONS,
+        s_name,
+        s_help,
+        nullptr,  // mod_ctor
+        nullptr,  // mod_dtor
+    },
+    IpsAction::IAP_ALERT,
+    nullptr,
+    nullptr,
+    nullptr,
+    nullptr,
+    alert_ctor,
+    alert_dtor
+};
+
+const BaseApi* act_alert[] =
+{
+    &alert_api.base,
+    nullptr
+};
+
diff --git a/src/actions/act_block.cc b/src/actions/act_block.cc
new file mode 100644 (file)
index 0000000..7a910c3
--- /dev/null
@@ -0,0 +1,92 @@
+//--------------------------------------------------------------------------
+// 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.
+//--------------------------------------------------------------------------
+// act_block.cc author Bhagya Tholpady <bbantwal@cisco.com>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "framework/ips_action.h"
+#include "framework/module.h"
+#include "packet_io/active.h"
+#include "protocols/packet.h"
+
+#include "actions.h"
+
+using namespace snort;
+
+#define s_name "block"
+
+#define s_help \
+    "block current packet and all the subsequent packets in this flow"
+
+//-------------------------------------------------------------------------
+class BlockAction : public IpsAction
+{
+public:
+    BlockAction() : IpsAction(s_name, nullptr) { }
+
+    void exec(Packet*, const OptTreeNode* otn) override;
+    bool drops_traffic() override { return true; }
+};
+
+void BlockAction::exec(Packet* p, const OptTreeNode* otn)
+{
+    p->active->block_session(p);
+    p->active->set_drop_reason("ips");
+    if ( otn )
+        Actions::alert(p, otn);
+}
+
+//-------------------------------------------------------------------------
+
+static IpsAction* block_ctor(Module*)
+{ return new BlockAction; }
+
+static void block_dtor(IpsAction* p)
+{ delete p; }
+
+static ActionApi block_api
+{
+    {
+        PT_IPS_ACTION,
+        sizeof(ActionApi),
+        ACTAPI_VERSION,
+        0,
+        API_RESERVED,
+        API_OPTIONS,
+        s_name,
+        s_help,
+        nullptr,  // mod_ctor
+        nullptr,  // mod_dtor
+    },
+    IpsAction::IAP_BLOCK,
+    nullptr,
+    nullptr,
+    nullptr,
+    nullptr,
+    block_ctor,
+    block_dtor
+};
+
+const BaseApi* act_block[] =
+{
+    &block_api.base,
+    nullptr
+};
+
diff --git a/src/actions/act_drop.cc b/src/actions/act_drop.cc
new file mode 100644 (file)
index 0000000..4447204
--- /dev/null
@@ -0,0 +1,92 @@
+//--------------------------------------------------------------------------
+// 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.
+//--------------------------------------------------------------------------
+// act_drop.cc author Bhagya Tholpady <bbantwal@cisco.com>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "framework/ips_action.h"
+#include "framework/module.h"
+#include "packet_io/active.h"
+#include "protocols/packet.h"
+
+#include "actions.h"
+
+using namespace snort;
+
+#define s_name "drop"
+
+#define s_help \
+    "drop the current packet"
+
+//-------------------------------------------------------------------------
+class DropAction : public IpsAction
+{
+public:
+    DropAction() : IpsAction(s_name, nullptr) { }
+
+    void exec(Packet*, const OptTreeNode* otn) override;
+    bool drops_traffic() override { return true; }
+};
+
+void DropAction::exec(Packet* p, const OptTreeNode* otn)
+{
+    p->active->drop_packet(p);
+    p->active->set_drop_reason("ips");
+    if ( otn )
+        Actions::alert(p, otn);
+}
+
+//-------------------------------------------------------------------------
+
+static IpsAction* drop_ctor(Module*)
+{ return new DropAction; }
+
+static void drop_dtor(IpsAction* p)
+{ delete p; }
+
+static ActionApi drop_api
+{
+    {
+        PT_IPS_ACTION,
+        sizeof(ActionApi),
+        ACTAPI_VERSION,
+        0,
+        API_RESERVED,
+        API_OPTIONS,
+        s_name,
+        s_help,
+        nullptr,  // mod_ctor
+        nullptr,  // mod_dtor
+    },
+    IpsAction::IAP_DROP,
+    nullptr,
+    nullptr,
+    nullptr,
+    nullptr,
+    drop_ctor,
+    drop_dtor
+};
+
+const BaseApi* act_drop[] =
+{
+    &drop_api.base,
+    nullptr
+};
+
diff --git a/src/actions/act_log.cc b/src/actions/act_log.cc
new file mode 100644 (file)
index 0000000..b230d66
--- /dev/null
@@ -0,0 +1,88 @@
+//--------------------------------------------------------------------------
+// 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.
+//--------------------------------------------------------------------------
+// act_log.cc author Bhagya Tholpady <bbantwal@cisco.com>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "framework/ips_action.h"
+#include "framework/module.h"
+#include "protocols/packet.h"
+
+#include "actions.h"
+
+using namespace snort;
+
+#define s_name "log"
+
+#define s_help \
+    "log the current packet"
+
+//-------------------------------------------------------------------------
+class LogAction : public IpsAction
+{
+public:
+    LogAction() : IpsAction(s_name, nullptr) { }
+
+    void exec(Packet*, const OptTreeNode* otn) override;
+};
+
+void LogAction::exec(Packet* p, const OptTreeNode* otn)
+{
+    if ( otn )
+        Actions::log(p, otn);
+}
+
+//-------------------------------------------------------------------------
+
+static IpsAction* log_ctor(Module*)
+{ return new LogAction; }
+
+static void log_dtor(IpsAction* p)
+{ delete p; }
+
+static ActionApi log_api
+{
+    {
+        PT_IPS_ACTION,
+        sizeof(ActionApi),
+        ACTAPI_VERSION,
+        0,
+        API_RESERVED,
+        API_OPTIONS,
+        s_name,
+        s_help,
+        nullptr,  // mod_ctor
+        nullptr,  // mod_dtor
+    },
+    IpsAction::IAP_LOG,
+    nullptr,
+    nullptr,
+    nullptr,
+    nullptr,
+    log_ctor,
+    log_dtor
+};
+
+const BaseApi* act_log[] =
+{
+    &log_api.base,
+    nullptr
+};
+
diff --git a/src/actions/act_pass.cc b/src/actions/act_pass.cc
new file mode 100644 (file)
index 0000000..6a86561
--- /dev/null
@@ -0,0 +1,91 @@
+//--------------------------------------------------------------------------
+// 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.
+//--------------------------------------------------------------------------
+// act_pass.cc author Bhagya Tholpady <bbantwal@cisco.com>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "framework/ips_action.h"
+#include "framework/module.h"
+#include "protocols/packet.h"
+
+#include "actions.h"
+
+using namespace snort;
+
+#define s_name "pass"
+
+#define s_help \
+    "mark the current packet as passed"
+
+//-------------------------------------------------------------------------
+class PassAction : public IpsAction
+{
+public:
+    PassAction() : IpsAction(s_name, nullptr) { }
+
+    void exec(Packet*, const OptTreeNode*) override;
+};
+
+void PassAction::exec(Packet* p, const OptTreeNode* otn)
+{
+    if ( otn )
+    {
+        Actions::pass();
+        p->packet_flags |= PKT_PASS_RULE;
+    }
+}
+
+//-------------------------------------------------------------------------
+
+static IpsAction* pass_ctor(Module*)
+{ return new PassAction; }
+
+static void pass_dtor(IpsAction* p)
+{ delete p; }
+
+static ActionApi pass_api
+{
+    {
+        PT_IPS_ACTION,
+        sizeof(ActionApi),
+        ACTAPI_VERSION,
+        0,
+        API_RESERVED,
+        API_OPTIONS,
+        s_name,
+        s_help,
+        nullptr,  // mod_ctor
+        nullptr,  // mod_dtor
+    },
+    IpsAction::IAP_PASS,
+    nullptr,
+    nullptr,
+    nullptr,
+    nullptr,
+    pass_ctor,
+    pass_dtor
+};
+
+const BaseApi* act_pass[] =
+{
+    &pass_api.base,
+    nullptr
+};
+
index 2a12018a9a588c66e55eb6590caeb9cd281f50ca..64c862ec20e2bc3b3e0ae4534f270863d595c187 100644 (file)
@@ -61,6 +61,8 @@
 #include "utils/util.h"
 #include "utils/util_cstring.h"
 
+#include "actions.h"
+
 using namespace snort;
 using namespace HttpCommon;
 using namespace Http2Enums;
@@ -93,7 +95,7 @@ static THREAD_LOCAL ProfileStats reactPerfStats;
     "</body>\r\n" \
     "</html>\r\n"
 
-THREAD_LOCAL const snort::Trace* react_trace = nullptr;
+THREAD_LOCAL const Trace* react_trace = nullptr;
 
 class ReactData
 {
@@ -127,57 +129,90 @@ private:
     std::string resp_buf;      // response to send
 };
 
-class ReactAction : public snort::IpsAction
+//-------------------------------------------------------------------------
+// active action
+//-------------------------------------------------------------------------
+
+class ReactActiveAction : public ActiveAction
 {
 public:
-    ReactAction(ReactData* c)
-        : IpsAction(s_name, ActionType::ACT_PROXY), config(c)
+    ReactActiveAction(ReactData* c)
+        : ActiveAction( ActionPriority::AP_PROXY ), config(c)
     { }
 
-    ~ReactAction() override
-    { delete config; }
+    void delayed_exec(Packet* p) override;
 
-    void exec(snort::Packet* p) override
-    {
-        Profile profile(reactPerfStats);
+private:
+    void send(Packet* p);
+    ReactData* config;
+};
 
-        if ( p->active->is_reset_candidate(p) )
-            send(p);
-    }
+void ReactActiveAction::delayed_exec(Packet* p)
+{
+    Profile profile(reactPerfStats);
 
-private:
-    void send(snort::Packet* p)
+    if ( p->active->is_reset_candidate(p) )
+        send(p);
+}
+
+void ReactActiveAction::send(Packet* p)
+{
+    InjectionControl control;
+    control.http_page = (const uint8_t*)config->get_resp_buf();
+    control.http_page_len = config->get_buf_len();
+    if (p->flow && p->flow->gadget &&
+        (strcmp(p->flow->gadget->get_name(), "http2_inspect") == 0))
     {
-        InjectionControl control;
-        control.http_page = (const uint8_t*)config->get_resp_buf();
-        control.http_page_len = config->get_buf_len();
-        if (p->flow && p->flow->gadget &&
-            (strcmp(p->flow->gadget->get_name(), "http2_inspect") == 0))
+        Http2FlowData* const session_data =
+            (Http2FlowData*)p->flow->get_flow_data(Http2FlowData::inspector_id);
+        assert(session_data != nullptr);
+        const SourceId source_id = p->is_from_client() ? SRC_CLIENT : SRC_SERVER;
+        if (session_data != nullptr)
         {
-            Http2FlowData* const session_data =
-                (Http2FlowData*)p->flow->get_flow_data(Http2FlowData::inspector_id);
-            assert(session_data != nullptr);
-            const SourceId source_id = p->is_from_client() ? SRC_CLIENT : SRC_SERVER;
-            if (session_data != nullptr)
-            {
-                control.stream_id = session_data->get_current_stream_id(source_id);
-                assert(control.stream_id != NO_STREAM_ID);
-            }
+            control.stream_id = session_data->get_current_stream_id(source_id);
+            assert(control.stream_id != NO_STREAM_ID);
         }
-        InjectionReturnStatus status = PayloadInjector::inject_http_payload(p, control);
+    }
+    InjectionReturnStatus status = PayloadInjector::inject_http_payload(p, control);
 #ifdef DEBUG_MSGS
-        if (status != INJECTION_SUCCESS)
-            debug_logf(react_trace, p, "Injection error: %s\n",
-                PayloadInjector::get_err_string(status));
+    if (status != INJECTION_SUCCESS)
+        debug_logf(react_trace, p, "Injection error: %s\n",
+            PayloadInjector::get_err_string(status));
 #else
-        UNUSED(status);
+    UNUSED(status);
 #endif
-    }
+}
+
+//-------------------------------------------------------------------------
+// ips action
+//-------------------------------------------------------------------------
+
+class ReactAction : public IpsAction
+{
+public:
+    ReactAction(ReactData* c)
+        : IpsAction(s_name, &react_act_action), config(c), react_act_action(c)
+    { }
+
+    ~ReactAction() override
+    { delete config; }
+
+    void exec(Packet*, const OptTreeNode* otn) override;
+    bool drops_traffic() override { return true; }
 
 private:
     ReactData* config;
+    ReactActiveAction react_act_action;
 };
 
+void ReactAction::exec(Packet* p, const OptTreeNode* otn)
+{
+    p->active->drop_packet(p);
+    p->active->set_drop_reason("ips");
+    if ( otn )
+        Actions::alert(p, otn);
+}
+
 //-------------------------------------------------------------------------
 // module
 //-------------------------------------------------------------------------
@@ -205,19 +240,19 @@ public:
     Usage get_usage() const override
     { return DETECT; }
 
-    void set_trace(const snort::Trace* trace) const override
+    void set_trace(const Trace* trace) const override
     { react_trace = trace; }
 
-    const snort::TraceOption* get_trace_options() const override
+    const TraceOption* get_trace_options() const override
     {
         static const TraceOption react_trace_options(nullptr, 0, nullptr);
         return &react_trace_options;
     }
 
-public:
-    std::string page;
+    std::string get_data();
 
 private:
+    std::string page;
     bool getpage(const char* file);
 };
 
@@ -234,10 +269,9 @@ bool ReactModule::getpage(const char* file)
     return true;
 }
 
-bool ReactModule::begin(const char*, int, SnortConfig* sc)
+bool ReactModule::begin(const char*, int, SnortConfig*)
 {
     page.clear();
-    sc->set_active_enabled();
     return true;
 }
 
@@ -249,6 +283,13 @@ bool ReactModule::set(const char*, Value& v, SnortConfig*)
     return true;
 }
 
+std::string ReactModule::get_data()
+{
+    std::string tmp = page;
+    page.clear();
+    return tmp;
+}
+
 //-------------------------------------------------------------------------
 // api methods
 //-------------------------------------------------------------------------
@@ -261,10 +302,14 @@ static void mod_dtor(Module* m)
 
 static IpsAction* react_ctor(Module* p)
 {
-    ReactModule* m = (ReactModule*)p;
-    ReactData* rd = new ReactData(m->page);
+    std::string react_page;
+    if ( p )
+    {
+        ReactModule* m = (ReactModule*)p;
+        react_page = m->get_data();
+    }
 
-    return new ReactAction(rd);
+    return new ReactAction(new ReactData(react_page));
 }
 
 static void react_dtor(IpsAction* p)
@@ -284,7 +329,7 @@ static const ActionApi react_api =
         mod_ctor,
         mod_dtor
     },
-    Actions::DROP,
+    IpsAction::IpsActionPriority(IpsAction::IAP_DROP + 1),
     nullptr,  // pinit
     nullptr,  // pterm
     nullptr,  // tinit
index f9eb2e3155f1fa93b87a770eeff95c0337f6fbed..69a56087b48c0e9c78a827e1e29f347d44ac06b4 100644 (file)
@@ -54,6 +54,8 @@
 #include "packet_io/active.h"
 #include "profiler/profiler.h"
 
+#include "actions.h"
+
 using namespace snort;
 
 #define s_name "reject"
@@ -76,25 +78,21 @@ enum
 
 THREAD_LOCAL ProfileStats rejPerfStats;
 
-class RejectAction : public snort::IpsAction
+//-------------------------------------------------------------------------
+// active action
+//-------------------------------------------------------------------------
+
+class RejectActiveAction : public ActiveAction
 {
 public:
-    RejectAction(uint32_t f);
-    void exec(snort::Packet*) override;
+    RejectActiveAction(uint32_t f) : ActiveAction (ActionPriority::AP_RESET) , mask(f) { }
+    void delayed_exec(Packet*) override;
 
 private:
     uint32_t mask;
 };
 
-//-------------------------------------------------------------------------
-// class methods
-//-------------------------------------------------------------------------
-
-RejectAction::RejectAction(uint32_t f) : IpsAction(s_name, ActionType::ACT_RESET), mask(f)
-{ }
-
-
-void RejectAction::exec(Packet* p)
+void RejectActiveAction::delayed_exec(Packet* p)
 {
     if ( !p->ptrs.ip_api.is_ip() )
         return;
@@ -148,6 +146,35 @@ void RejectAction::exec(Packet* p)
         act->send_unreach(p, UnreachResponse::PORT);
 }
 
+//-------------------------------------------------------------------------
+// ips action
+//-------------------------------------------------------------------------
+
+class RejectAction : public IpsAction
+{
+public:
+    RejectAction(uint32_t f = REJ_RST_BOTH);
+
+    void exec(Packet*, const OptTreeNode* otn) override;
+
+private:
+    RejectActiveAction rej_act_action;
+};
+
+//-------------------------------------------------------------------------
+// class methods
+//-------------------------------------------------------------------------
+
+RejectAction::RejectAction(uint32_t f) : IpsAction(s_name, &rej_act_action) , rej_act_action(f)
+{ }
+
+void RejectAction::exec(Packet* p, const OptTreeNode* otn)
+{
+    p->active->reset_session(p, get_active_action());
+    if ( otn )
+        Actions::alert(p, otn);
+}
+
 //-------------------------------------------------------------------------
 // module
 //-------------------------------------------------------------------------
@@ -177,14 +204,15 @@ public:
     Usage get_usage() const override
     { return DETECT; }
 
-public:
+    uint32_t get_data();
+
+private:
     uint32_t flags;
 };
 
-bool RejectModule::begin(const char*, int, SnortConfig* sc)
+bool RejectModule::begin(const char*, int, SnortConfig*)
 {
     flags = 0;
-    sc->set_active_enabled();
     return true;
 }
 
@@ -226,6 +254,11 @@ bool RejectModule::set(const char*, Value& v, SnortConfig*)
     return true;
 }
 
+uint32_t RejectModule::get_data()
+{
+    return flags;
+}
+
 //-------------------------------------------------------------------------
 // api methods
 //-------------------------------------------------------------------------
@@ -242,8 +275,13 @@ static void mod_dtor(Module* m)
 
 static IpsAction* rej_ctor(Module* p)
 {
-    RejectModule* m = (RejectModule*)p;
-    return new RejectAction(m->flags);
+    if ( p )
+    {
+        RejectModule* m = (RejectModule*)p;
+        return new RejectAction(m->get_data());
+    }
+    else
+        return new RejectAction();
 }
 
 static void rej_dtor(IpsAction* p)
@@ -265,7 +303,7 @@ static const ActionApi rej_api =
         mod_ctor,
         mod_dtor
     },
-    Actions::RESET,
+    IpsAction::IAP_REJECT,
     nullptr,
     nullptr,
     nullptr,
@@ -274,11 +312,7 @@ static const ActionApi rej_api =
     rej_dtor
 };
 
-#ifdef BUILDING_SO
-SO_PUBLIC const BaseApi* snort_plugins[] =
-#else
 const BaseApi* act_reject[] =
-#endif
 {
     &rej_api.base,
     nullptr
index 1ad01da12986db1038157862fce89f599c3b3c54..05f1feddd96bc88fa490b829556fef4a3d8994a4 100644 (file)
 #include "detection/detection_engine.h"
 #include "framework/ips_action.h"
 #include "framework/module.h"
-#include "main/snort_config.h"
 #include "packet_io/active.h"
 #include "protocols/packet.h"
 
+#include "actions.h"
+
 using namespace snort;
 
 #define s_name "rewrite"
@@ -72,83 +73,46 @@ static void Replace_ModifyPacket(Packet* p)
 }
 
 //-------------------------------------------------------------------------
-// replace module
+// active action
 //-------------------------------------------------------------------------
-
-static const Parameter s_params[] =
-{
-    { "disable_replace", Parameter::PT_BOOL, nullptr, "false",
-      "disable replace of packet contents with rewrite rules" },
-
-    { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
-};
-
-class ReplaceModule : public Module
+class ReplaceActiveAction : public ActiveAction
 {
 public:
-    ReplaceModule() : Module(s_name, s_help, s_params) { }
-    bool set(const char*, Value&, SnortConfig*) override;
-    bool begin(const char*, int, SnortConfig*) override;
-
-    Usage get_usage() const override
-    { return DETECT; }
-
-public:
-    bool disable_replace;
+    ReplaceActiveAction() : ActiveAction(ActionPriority::AP_MODIFY) { }
+    void delayed_exec(Packet*) override;
 };
 
-bool ReplaceModule::set(const char*, Value& v, SnortConfig*)
+void ReplaceActiveAction::delayed_exec(Packet* p)
 {
-    if ( v.is("disable_replace") )
-        disable_replace = v.get_bool();
-    else
-        return false;
-
-    return true;
-}
+    if ( p->is_rebuilt() )
+        return;
 
-bool ReplaceModule::begin(const char*, int, SnortConfig* sc)
-{
-    disable_replace = false;
-    sc->set_active_enabled();
-    return true;
+    Replace_ModifyPacket(p);
 }
 
 //-------------------------------------------------------------------------
-class ReplaceAction : public snort::IpsAction
+// ips action
+//-------------------------------------------------------------------------
+class ReplaceAction : public IpsAction
 {
 public:
-    ReplaceAction(bool disable_replace);
+    ReplaceAction() : IpsAction(s_name, &rep_act_action) { }
+
+    void exec(Packet*, const OptTreeNode* otn) override;
 
-    void exec(snort::Packet*) override;
 private:
-    bool disable_replace = false;
+    ReplaceActiveAction rep_act_action;
 };
 
-ReplaceAction::ReplaceAction(bool dr) :
-    IpsAction(s_name, ACT_RESET)
+void ReplaceAction::exec(Packet* p, const OptTreeNode* otn)
 {
-    disable_replace = dr;
-}
-
-void ReplaceAction::exec(Packet* p)
-{
-    if ( p->is_rebuilt() || disable_replace )
-        return;
-
-    Replace_ModifyPacket(p);
+    Actions::alert(p, otn);
 }
 
 //-------------------------------------------------------------------------
 
-static Module* mod_ctor()
-{ return new ReplaceModule; }
-
-static void mod_dtor(Module* m)
-{ delete m; }
-
-static IpsAction* rep_ctor(Module* m)
-{ return new ReplaceAction( ((ReplaceModule*)m)->disable_replace); }
+static IpsAction* rep_ctor(Module*)
+{ return new ReplaceAction; }
 
 static void rep_dtor(IpsAction* p)
 { delete p; }
@@ -164,10 +128,10 @@ static ActionApi rep_api
         API_OPTIONS,
         s_name,
         s_help,
-        mod_ctor,
-        mod_dtor
+        nullptr,  // mod_ctor
+        nullptr,  // mod_dtor
     },
-    Actions::ALERT,
+    IpsAction::IAP_REWRITE,
     nullptr,
     nullptr,
     nullptr,
@@ -176,11 +140,7 @@ static ActionApi rep_api
     rep_dtor
 };
 
-#ifdef BUILDING_SO
-SO_PUBLIC const BaseApi* snort_plugins[] =
-#else
 const BaseApi* act_replace[] =
-#endif
 {
     &rep_api.base,
     nullptr
index 2f28c9aea087dc83f21f8a520d06bfe8ef34e514..a8c6852676aeee0da966190a3a201010e22b7291 100644 (file)
 #include "actions.h"
 
 #include "detection/detect.h"
-#include "detection/tag.h"
-#include "packet_io/active.h"
-#include "packet_io/active_action.h"
+#include "managers/action_manager.h"
 #include "parser/parser.h"
 #include "utils/stats.h"
 
 using namespace snort;
 
-static void pass()
+void Actions::pass()
 {
     pc.pass_pkts++;
 }
 
-static void log(Packet* p, const OptTreeNode* otn)
+void Actions::log(Packet* p, const OptTreeNode* otn)
 {
     RuleTreeNode* rtn = getRuntimeRtnFromOtn(otn);
     CallLogFuncs(p, otn, rtn->listhead);
 }
 
-static void alert(Packet* p, const OptTreeNode* otn)
+void Actions::alert(Packet* p, const OptTreeNode* otn)
 {
     RuleTreeNode* rtn = getRuntimeRtnFromOtn(otn);
 
@@ -60,108 +58,30 @@ static void alert(Packet* p, const OptTreeNode* otn)
     CallLogFuncs(p, otn, rtn->listhead);
 }
 
-static const char* const type[Actions::MAX] =
+std::string Actions::get_string(Actions::Type action)
 {
-    "none", "log", "pass", "alert", "drop", "block", "reset"
-};
-
-const char* Actions::get_string(Actions::Type action)
-{
-    if ( action < Actions::MAX )
-        return type[action];
-
-    return "ERROR";
+    return ActionManager::get_action_string(action);
 }
 
 Actions::Type Actions::get_type(const char* s)
 {
-    if ( !s )
-        return Actions::NONE;
-
-    else if ( !strcasecmp(s, Actions::get_string(Actions::LOG)) )
-        return Actions::LOG;
-
-    else if ( !strcasecmp(s, Actions::get_string(Actions::PASS)) )
-        return Actions::PASS;
-
-    else if ( !strcasecmp(s, Actions::get_string(Actions::ALERT)) )
-        return Actions::ALERT;
-
-    else if ( !strcasecmp(s, Actions::get_string(Actions::DROP)) )
-        return Actions::DROP;
-
-    else if ( !strcasecmp(s, Actions::get_string(Actions::BLOCK)) )
-        return Actions::BLOCK;
-
-    else if ( !strcasecmp(s, Actions::get_string(Actions::RESET)) )
-        return Actions::RESET;
-
-    return Actions::NONE;
+    return ActionManager::get_action_type(s);
 }
 
-void Actions::execute(Actions::Type action, Packet* p, const OptTreeNode* otn,
-    uint16_t event_id)
+Actions::Type Actions::get_max_types()
 {
-    switch (action)
-    {
-    case Actions::PASS:
-        pass();
-        SetTags(p, otn, event_id);
-        break;
-
-    case Actions::ALERT:
-        alert(p, otn);
-        SetTags(p, otn, event_id);
-        break;
-
-    case Actions::LOG:
-        log(p, otn);
-        SetTags(p, otn, event_id);
-        break;
-
-    case Actions::DROP:
-        p->active->drop_packet(p);
-        p->active->set_drop_reason("ips");
-        alert(p, otn);
-        SetTags(p, otn, event_id);
-        break;
-
-    case Actions::BLOCK:
-        p->active->block_session(p);
-        p->active->set_drop_reason("ips");
-        alert(p, otn);
-        SetTags(p, otn, event_id);
-        break;
-
-    case Actions::RESET:
-        p->active->reset_session(p, get_ips_policy()->action[action]);
-        alert(p, otn);
-        SetTags(p, otn, event_id);
-        break;
-
-    default:
-        break;
-    }
+    return ActionManager::get_max_action_types();
 }
 
-void Actions::apply(Actions::Type action, Packet* p)
+bool Actions::is_valid_action(Actions::Type action)
 {
-    switch ( action )
-    {
-    case Actions::DROP:
-        p->active->drop_packet(p);
-        break;
-
-    case Actions::BLOCK:
-        p->active->block_session(p);
-        break;
-
-    case Actions::RESET:
-        p->active->reset_session(p, get_ips_policy()->action[action]);
-        break;
+    if ( action < get_max_types() )
+        return true;
 
-    default:
-        break;
-    }
+    return false;
 }
 
+std::string Actions::get_default_priorities(bool alert_before_pass)
+{
+    return ActionManager::get_action_priorities(alert_before_pass);
+}
index e3badba00cf4cec9d122ab9ec35bbc1d5543bc63..be6ac3eea3343b019217652da965cc61704d2dbf 100644 (file)
@@ -22,6 +22,7 @@
 // Define action types and provide hooks to apply a given action to a packet
 
 #include <cstdint>
+#include <string>
 
 #include "main/snort_types.h"
 
@@ -30,25 +31,22 @@ struct OptTreeNode;
 namespace snort
 {
 struct Packet;
+}
 
 class SO_PUBLIC Actions
 {
 public:
-    // FIXIT-L if Type is changed, RateFilterModule and type in actions.cc must be updated
-    enum Type : uint8_t
-    { NONE = 0, LOG, PASS, ALERT, DROP, BLOCK, RESET, MAX };
-
-    static const char* get_string(Type);
+    using Type = uint8_t;
+public:
+    static std::string get_string(Type);
     static Type get_type(const char*);
+    static Type get_max_types();
+    static bool is_valid_action(Type);
+    static std::string get_default_priorities(bool alert_before_pass = false);
 
-    static void execute(Type, struct Packet*, const struct OptTreeNode*,
-        uint16_t event_id);
-
-    static void apply(Type, struct Packet*);
-
-    static inline bool is_pass(Type a)
-    { return ( a == PASS ); }
+    static void pass();
+    static void log(snort::Packet*, const OptTreeNode*);
+    static void alert(snort::Packet*, const OptTreeNode*);
 };
-}
 #endif
 
index 90b114dd76f28f627fb83c99c6647397510389ab..a8f7026bc4820748af6b9d4178529940d0debbc2 100644 (file)
@@ -1,31 +1,34 @@
-IPS actions allow you to execute custom responses to events.
-Unlike loggers, these are invoked before thresholding and can be used to
-control external agents (including loggers).
+IPS actions allow you to execute custom responses to events. Unlike loggers,
+these are invoked before thresholding and can be used to control external agents
+(including loggers).
 
 IPS rules have an associated type that determines what kind of action they
 trigger. The rule types defined in this module are:
 
-* log
-* pass
-* alert
-* drop
-* block
-* reset
-
-There is also a "none" rule type, which is a no-op.
+* log pass alert drop block
 
 It also defines 3 active responses:
-* react
-* reject
-* rewrite
+* react reject rewrite
+
+Reject performs active response to shutdown hostile network session by injecting
+TCP resets (TCP connections) or ICMP unreachable packets.
+
+React sends an HTML page to the client, a RST to the server and blocks the flow.
+It is using payload_injector utilty. payload_injector should be configured when
+react is used.
+
+Rewrite enables overwrite packet contents based on "replace" option in the
+rules.
 
-Reject performs active response to shutdown hostile network 
-session by injecting TCP resets (TCP connections) or ICMP unreachable 
-packets.
+Ips actions are all pluggable and implemented as subclasses of IpsAction action.
+Each ips action instance has an instance of the active action that is used to
+perform the active response.
 
-React sends an HTML page to the client, a RST to the server
-and blocks the flow. It is using payload_injector utilty.
-payload_injector should be configured when react is used.
+IpsAction::exec represents the action taken by the ips actions after rule
+evaluation during packet processing. This may include logging, alerting  marking
+the packet as passed, etc. IpsActions::exec when called without the otn will do
+the active action such as drop/block/reset without alerting/logging or marking
+the packet as passed.
 
-Rewrite enables overwrite packet contents based on "replace" 
-option in the rules.
+ActiveAction::delayed_exec is called during the post processing of a packet to
+send active responses.
index 0e4a13c21c2e2afd7fb9096b1beaa07a1f42811c..90e2d4aeac2bf53e57fd2c8762fe9f9704690e03 100644 (file)
@@ -29,16 +29,26 @@ using namespace snort;
 
 #ifdef STATIC_IPS_ACTIONS
 extern const BaseApi* act_react[];
-extern const BaseApi* act_reject[];
 #endif
+extern const BaseApi* act_alert[];
+extern const BaseApi* act_block[];
+extern const BaseApi* act_drop[];
+extern const BaseApi* act_log[];
+extern const BaseApi* act_pass[];
+extern const BaseApi* act_reject[];
 extern const BaseApi* act_replace[];
 
 void load_actions()
 {
 #ifdef STATIC_IPS_ACTIONS
     PluginManager::load_plugins(act_react);
-    PluginManager::load_plugins(act_reject);
 #endif
+    PluginManager::load_plugins(act_alert);
+    PluginManager::load_plugins(act_block);
+    PluginManager::load_plugins(act_drop);
+    PluginManager::load_plugins(act_log);
+    PluginManager::load_plugins(act_pass);
+    PluginManager::load_plugins(act_reject);
     PluginManager::load_plugins(act_replace);
 }
 
index 13094254d1cf3f36010776fa3e53249731d39d57..f708dbb8fa0b122640f98b330a2122fd55cd1ad7 100644 (file)
@@ -649,7 +649,7 @@ int DetectionEngine::queue_event(const OptTreeNode* otn)
     return 0;
 }
 
-int DetectionEngine::queue_event(unsigned gid, unsigned sid, Actions::Type type)
+int DetectionEngine::queue_event(unsigned gid, unsigned sid)
 {
     OptTreeNode* otn = GetOTN(gid, sid);
 
@@ -664,7 +664,6 @@ int DetectionEngine::queue_event(unsigned gid, unsigned sid, Actions::Type type)
 
     en->otn = otn;
     en->rtn = nullptr;  // lookup later after ips policy selection
-    en->type = type;
 
     if ( sfeventq_add(pq, en) )
         return -1;
index aa77a2471852916f0e2f9cb672c996a81aba13cf..919d4a952c024b206a5b0388da7c60e9eeb28750 100644 (file)
@@ -25,7 +25,6 @@
 // packet (PDU), first call set_next_packet().  If rebuild is successful,
 // then instantiate a new DetectionEngine to detect that packet.
 
-#include "actions/actions.h"
 #include "detection/detection_util.h"
 #include "detection/ips_context.h"
 #include "main/snort_types.h"
@@ -87,7 +86,7 @@ public:
     static bool inspect(Packet*);
 
     static int queue_event(const struct OptTreeNode*);
-    static int queue_event(unsigned gid, unsigned sid, Actions::Type = Actions::NONE);
+    static int queue_event(unsigned gid, unsigned sid);
 
     static void disable_all(Packet*);
     static bool all_disabled(Packet*);
index 8cd9f3ef2410322c4df6ec591eb884ad1a3523ee..a8be6e1440dc946500ccd294126b347a15c5ad0d 100644 (file)
@@ -24,6 +24,7 @@
 
 #include "detection_util.h"
 
+#include "actions/actions.h"
 #include "events/event.h"
 #include "log/text_log.h"
 #include "protocols/packet.h"
@@ -74,16 +75,16 @@ static void LogBuffer(const char* s, const uint8_t* p, unsigned n)
     }
 }
 
-void EventTrace_Log(const Packet* p, const OptTreeNode* otn, int action)
+void EventTrace_Log(const Packet* p, const OptTreeNode* otn, Actions::Type action)
 {
-    const char* acts = Actions::get_string((Actions::Type)action);
+    std::string acts = Actions::get_string(action);
 
     if ( !tlog )
         return;
 
     TextLog_Print(tlog,
         "\nEvt=%u, Gid=%u, Sid=%u, Rev=%u, Act=%s\n",
-        event_id, otn->sigInfo.gid, otn->sigInfo.sid, otn->sigInfo.rev, acts);
+        event_id, otn->sigInfo.gid, otn->sigInfo.sid, otn->sigInfo.rev, acts.c_str());
 
     TextLog_Print(tlog,
         "Pkt=" STDu64 ", Sec=%lu.%6lu, Len=%u, Cap=%u\n",
index 123492e0ec2cf83e5f5f54dd0815dc17930b1cd7..13484f87714ffb3a227b0f73dbecb403c8705d39 100644 (file)
@@ -24,6 +24,7 @@
 // this is a legacy junk-drawer file that needs to be refactored
 // it provides file and alt data and event trace foo.
 
+#include "actions/actions.h"
 #include "main/snort_config.h"
 
 #define DECODE_BLEN 65535
@@ -44,7 +45,7 @@ struct DataBuffer
 void EventTrace_Init();
 void EventTrace_Term();
 
-void EventTrace_Log(const snort::Packet*, const OptTreeNode*, int action);
+void EventTrace_Log(const snort::Packet*, const OptTreeNode*, Actions::Type action);
 
 inline int EventTrace_IsEnabled(const snort::SnortConfig* sc)
 {
index cc1c72252e7098ef4a3e63892a6d1cfdbd227178..a3ba32a02991246d6fb024949440770467695ac1 100644 (file)
@@ -41,6 +41,7 @@
 
 #include <vector>
 
+#include "actions/actions.h"
 #include "events/event.h"
 #include "filters/rate_filter.h"
 #include "filters/sfthreshold.h"
@@ -107,29 +108,26 @@ static inline void init_match_info(const IpsContext* c)
 // called by fpLogEvent(), which does the filtering etc.
 // this handles the non-rule-actions (responses).
 static inline void fpLogOther(
-    Packet* p, const RuleTreeNode* rtn, const OptTreeNode* otn, int action)
+    Packet* p, const RuleTreeNode* rtn, const OptTreeNode* otn, Actions::Type action)
 {
     if ( EventTrace_IsEnabled(p->context->conf) )
         EventTrace_Log(p, otn, action);
 
     if ( PacketTracer::is_active() )
     {
+        std::string act = Actions::get_string(action);
         PacketTracer::log("Event: %u:%u:%u, Action %s\n",
             otn->sigInfo.gid, otn->sigInfo.sid,
-            otn->sigInfo.rev, Actions::get_string((Actions::Type)action));
+            otn->sigInfo.rev, act.c_str());
     }
 
     // rule option actions are queued here (eg replace)
     otn_trigger_actions(otn, p);
 
-    // rule actions are queued here (eg reject)
-    if ( rtn->listhead->is_plugin_action )
-    {
-        Actions::Type idx = rtn->listhead->ruleListNode->mode;
-        ActiveAction * act = get_ips_policy()->action[idx];
-        if ( act )
-            Active::queue(act, p);
-    }
+    IpsAction* act = get_ips_policy()->action[rtn->action];
+    ActiveAction* active_act = act->get_active_action();
+    if ( active_act )
+        Active::queue(act->get_active_action(), p);
 }
 
 /*
@@ -143,9 +141,6 @@ int fpLogEvent(const RuleTreeNode* rtn, const OptTreeNode* otn, Packet* p)
     int action = -1, rateAction = -1;
     int override, filterEvent = 0;
 
-    if ( Actions::is_pass(rtn->action) )
-        p->packet_flags |= PKT_PASS_RULE;
-
     if ( otn->stateless() )
     {
         /* Stateless rule, set the stateless bit */
@@ -166,16 +161,17 @@ int fpLogEvent(const RuleTreeNode* rtn, const OptTreeNode* otn, Packet* p)
     {
         // We still want to drop packets that are drop rules.
         // We just don't want to see the alert.
-        Actions::apply(rtn->action, p);
+        IpsAction * act = get_ips_policy()->action[rtn->action];
+        act->exec(p);
         fpLogOther(p, rtn, otn, rtn->action);
         return 1;
     }
 
     // perform rate filtering tests - impacts action taken
     rateAction = RateFilter_Test(otn, p);
-    override = ( rateAction >= Actions::MAX );
+    override = ( rateAction >= Actions::get_max_types() );
     if ( override )
-        rateAction -= Actions::MAX;
+        rateAction -= Actions::get_max_types();
 
     // internal events are no-ops
     if ( (rateAction < 0) && EventIsInternal(otn->sigInfo.gid) )
@@ -209,7 +205,8 @@ int fpLogEvent(const RuleTreeNode* rtn, const OptTreeNode* otn, Packet* p)
         **  If InlineMode is on, then we still want to drop packets
         **  that are drop rules.  We just don't want to see the alert.
         */
-        Actions::apply((Actions::Type)action, p);
+        IpsAction * act = get_ips_policy()->action[action];
+        act->exec(p);
         fpLogOther(p, rtn, otn, action);
         pc.event_limit++;
         return 1;
@@ -222,7 +219,7 @@ int fpLogEvent(const RuleTreeNode* rtn, const OptTreeNode* otn, Packet* p)
     const SnortConfig* sc = p->context->conf;
 
     if ( (p->packet_flags & PKT_PASS_RULE) &&
-        (sc->get_eval_index(rtn->action) > sc->get_eval_index(Actions::PASS)) )
+        (sc->get_eval_index(rtn->action) > sc->get_eval_index(Actions::get_type("pass"))) )
     {
         fpLogOther(p, rtn, otn, rtn->action);
         return 1;
@@ -231,7 +228,11 @@ int fpLogEvent(const RuleTreeNode* rtn, const OptTreeNode* otn, Packet* p)
     otn->state[get_instance_id()].alerts++;
 
     event_id++;
-    Actions::execute((Actions::Type)action, p, otn, event_id);
+
+    IpsAction * act = get_ips_policy()->action[action];
+    act->exec(p, otn);
+    SetTags(p, otn, event_id);
+
     fpLogOther(p, rtn, otn, action);
 
     return 0;
@@ -639,7 +640,7 @@ static inline int fpFinalSelectEvent(OtnxMatchData* omd, Packet* p)
                 const OptTreeNode* otn = omd->matchInfo[i].MatchArray[j];
                 RuleTreeNode* rtn = getRtnFromOtn(otn);
 
-                if ( otn && rtn && Actions::is_pass(rtn->action) )
+                if ( otn && rtn && ( p->packet_flags & PKT_PASS_RULE ) )
                 {
                     /* Already acted on rules, so just don't act on anymore */
                     if ( tcnt > 0 )
@@ -680,11 +681,8 @@ static inline int fpFinalSelectEvent(OtnxMatchData* omd, Packet* p)
                 }
 
                 /* only log/count one pass */
-                if ( otn && rtn && Actions::is_pass(rtn->action) )
-                {
-                    p->packet_flags |= PKT_PASS_RULE;
+                if ( otn && rtn && ( p->packet_flags & PKT_PASS_RULE ) )
                     return 1;
-                }
             }
         }
     }
index 6c09fcf67c698c96aca29e9fccf9080fbc906545..c45122a4e6462bca54132bba24f2fb2e85837b83 100644 (file)
@@ -101,7 +101,8 @@ void RuleStateMap::apply(
         policy->rules_shared++;
 
     RuleTreeNode* t_rtn = dup_rtn(sc, otn, b_rtn, policy);
-    update_rtn(t_rtn, s);
+    update_rtn(sc, t_rtn, s);
+
     addRtnToOtn(sc, otn, t_rtn, ips_num);
 }
 
@@ -156,7 +157,7 @@ RuleTreeNode* RuleStateMap::dup_rtn(
     return ret;
 }
 
-void RuleStateMap::update_rtn(RuleTreeNode* rtn, const RuleState& s)
+void RuleStateMap::update_rtn(SnortConfig* sc, RuleTreeNode* rtn, const RuleState& s)
 {
     switch ( s.enable )
     {
@@ -164,6 +165,12 @@ void RuleStateMap::update_rtn(RuleTreeNode* rtn, const RuleState& s)
     case IpsPolicy::ENABLED: rtn->set_enabled(); break;
     case IpsPolicy::INHERIT_ENABLE: break;
     }
+
+    ListHead* new_listhead = get_rule_list(sc, s.rule_action.c_str());
+
+    if ( new_listhead and ( rtn->listhead != new_listhead ) )
+        rtn->listhead = new_listhead;
+
     rtn->action = s.action;
 
     if ( rtn->header )
index 69b0629ca89ed08b85ff8da9a6f7e1663b7f89d3..0905f6cac0ae1caaedb75bbb4e57e2ab15dc42b4 100644 (file)
@@ -58,14 +58,13 @@ struct ListHead
     OutputSet* LogList;
     OutputSet* AlertList;
     struct RuleListNode* ruleListNode;
-    bool is_plugin_action = false;
 };
 
 // for top-level rule lists by type (alert, drop, etc.)
 struct RuleListNode
 {
     ListHead* RuleList;   /* The rule list associated with this node */
-    snort::Actions::Type mode;        /* the rule mode */
+    Actions::Type mode;        /* the rule mode */
     unsigned evalIndex;        /* eval index for this rule set */
     char* name;           /* name of this rule list */
     RuleListNode* next;   /* the next RuleListNode */
@@ -83,7 +82,7 @@ struct RuleKey
 struct RuleState
 {
     std::string rule_action;
-    snort::Actions::Type action;
+    uint8_t action;
     IpsPolicy::Enable enable;
 };
 
@@ -97,7 +96,7 @@ public:
 
 private:
     RuleTreeNode* dup_rtn(snort::SnortConfig*, OptTreeNode*, RuleTreeNode*, IpsPolicy*);
-    void update_rtn(RuleTreeNode*, const RuleState&);
+    void update_rtn(snort::SnortConfig*, RuleTreeNode*, const RuleState&);
     void apply(snort::SnortConfig*, OptTreeNode*, unsigned ips_num, const RuleState&);
 
 private:
index 978672e6b622f360c5176009f85bb5c853072012..b106f250425911b823b08902d3153c7aa5b6c332 100644 (file)
@@ -28,6 +28,7 @@
 
 #include "signature.h"
 
+#include "actions/actions.h"
 #include "framework/decode_data.h"
 #include "hash/hash_defs.h"
 #include "hash/ghash.h"
@@ -476,10 +477,10 @@ void dump_rule_state(const SnortConfig* sc)
             auto pid = snort::get_ips_policy(sc, i)->user_policy_id;
             json.put("policy", pid);
 
-            const char* s = Actions::get_string(rtn->action);
-            json.put("action", s);
+            std::string action = Actions::get_string(rtn->action);
+            json.put("action", action.c_str());
 
-            s = rtn->enabled() ? "enabled" : "disabled";
+            const char* s = rtn->enabled() ? "enabled" : "disabled";
             json.put("state", s);
 
             json.close();
index f7f90927ff03aa7d27c7b1e0986cbca7d690ecf2..1a268f80be54f1ab72c27862201f23feaee76f09 100644 (file)
@@ -133,7 +133,7 @@ struct RuleTreeNode
     // Multiple OTNs can reference this RTN with the same policy.
     unsigned int otnRefCount = 0; // FIXIT-L shared_ptr?
 
-    snort::Actions::Type action = snort::Actions::Type::NONE;
+    Actions::Type action = 0;
 
     uint8_t flags = 0;
 
index c1d74b5874502f6af784a991f1f78047f7c876d6..97b722c5599b0bb164c3ea78129ac44260bd91d7 100644 (file)
@@ -20,7 +20,6 @@
 #ifndef EVENT_QUEUE_H
 #define EVENT_QUEUE_H
 
-#include "actions/actions.h"
 #include "main/snort_types.h"
 
 #define SNORT_EVENTQ_PRIORITY    1
@@ -38,7 +37,6 @@ struct EventNode
 {
     const struct OptTreeNode* otn;
     const struct RuleTreeNode* rtn;
-    snort::Actions::Type type;
 };
 
 EventQueueConfig* EventQueueConfigNew();
index fa5e1606bd4acc725de0e64015363d1a1272af7e..7fcd4f4a8cbc6e8b4a51930b1c67fde9b10dc28c 100644 (file)
@@ -464,14 +464,10 @@ bool FileIdModule::begin(const char* fqn, int idx, SnortConfig*)
     return true;
 }
 
-bool FileIdModule::end(const char* fqn, int idx, SnortConfig* sc)
+bool FileIdModule::end(const char* fqn, int idx, SnortConfig*)
 {
     if (!idx)
-    {
-        if ( need_active )
-            sc->set_active_enabled();
         return true;
-    }
 
     if ( !strcmp(fqn, "file_id.file_rules") )
     {
index 6e47a7ef50157c25550254b87f546f70e132e89d..0ff10ac5e769cce3593b2830a38cbc245786d77d 100644 (file)
@@ -28,6 +28,7 @@
 
 #include "main/thread.h"
 #include "detection/rules.h"
+#include "framework/ips_action.h"
 #include "hash/ghash.h"
 #include "hash/hash_defs.h"
 #include "hash/xhash.h"
@@ -402,9 +403,13 @@ static int SFRF_TestObject(
     // but the decrement will never come so we "fix" it here
     // if the count were not incremented in such cases, the
     // threshold would never be exceeded.
-    if ( !cfgNode->seconds && dynNode->count > cfgNode->count )
-        if ( cfgNode->newAction == Actions::DROP )
+    if ( !cfgNode->seconds && (dynNode->count > cfgNode->count)
+      && Actions::is_valid_action(cfgNode->newAction) )
+    {
+        IpsAction* act = get_ips_policy()->action[cfgNode->newAction];
+        if ( act->drops_traffic() )
             dynNode->count--;
+    }
 
 #ifdef SFRF_DEBUG
     printf("--SFRF_DEBUG: %d-%u-%u: %u Packet IP %s, op: %d, count %u, action %d\n",
@@ -742,7 +747,7 @@ static int _checkThreshold(
     fflush(stdout);
 #endif
 
-    return Actions::MAX + cfgNode->newAction;
+    return Actions::get_max_types() + cfgNode->newAction;
 }
 
 static void _updateDependentThresholds(
index e58aa33b0f18728c7cbc8f12437476e1e4a5796d..d28887fd8b84a850e572a67c8e812ddebc055f40 100644 (file)
@@ -95,7 +95,7 @@ struct tSFRFConfigNode
     unsigned seconds;
 
     // Action that replaces original rule action on reaching threshold
-    snort::Actions::Type newAction;
+    Actions::Type newAction;
 
     // Threshold action duration in seconds before reverting to original rule action
     unsigned timeout;
index ccc8c27b9f5cf50422fb8bd3df03dca479bd1b39..43028a25355f8feb82b63ee3aed0bc4bf30e4fd5 100644 (file)
@@ -952,8 +952,8 @@ static int EventTest(EventData* p)
     status = SFRF_TestThreshold(
         rfc, p->gid, p->sid, &sip, &dip, curtime, op);
 
-    if ( status >= Actions::MAX )
-        status -= Actions::MAX;
+    if ( status >= Actions::get_max_types() )
+        status -= Actions::get_max_types();
 
     return status;
 }
index 3338589e1da2004f40ee020fb3a28c4e17d9a7af..c69e6c54e517cf20171d8b96150b81951f2974ca 100644 (file)
 // These can be used to execute external controls like updating an external
 // firewall.
 
-#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)
+#define ACTAPI_VERSION ((BASE_API_VERSION << 16) | 1)
 
 //-------------------------------------------------------------------------
 // api for class
 //-------------------------------------------------------------------------
 
+struct OptTreeNode;
 namespace snort
 {
 struct Packet;
 
-class SO_PUBLIC IpsAction : public ActiveAction
+class SO_PUBLIC IpsAction
 {
 public:
-    void exec(Packet*) override = 0;
+    enum IpsActionPriority : uint16_t
+    {
+        IAP_LOG = 10,
+        IAP_ALERT = 20,
+        IAP_REWRITE = 30,
+        IAP_DROP = 40,
+        IAP_BLOCK = 50,
+        IAP_REJECT = 60,
+        IAP_PASS = 70,
+        IAP_MAX = IAP_PASS
+    };
+
+public:
+    virtual ~IpsAction() = default;
     const char* get_name() const { return name; }
+    ActiveAction* get_active_action() const { return active_action; }
+
+    virtual void exec(Packet*, const OptTreeNode* otn = nullptr) = 0;
+    virtual bool drops_traffic() { return false; }
 
 protected:
-    IpsAction(const char* s, ActionType a) : ActiveAction(a)
-    { name = s; }
+    IpsAction(const char* s, ActiveAction* a)
+    {
+        active_action = a;
+        name = s;
+    }
 
 private:
     const char* name;
+    ActiveAction* active_action;
 };
 
 typedef void (* IpsActFunc)();
@@ -62,7 +83,8 @@ typedef void (* ActDelFunc)(IpsAction*);
 struct ActionApi
 {
     BaseApi base;
-    Actions::Type type;
+
+    IpsAction::IpsActionPriority priority;
 
     IpsActFunc pinit;
     IpsActFunc pterm;
index db0f0c82e173630b505bc8a5ac4e6e6874e087e0..7739c139bb3ead2cd49052c16f8fc22e48cccba4 100644 (file)
@@ -611,7 +611,6 @@ bool ReferencesModule::set(const char*, Value& v, SnortConfig*)
 //-------------------------------------------------------------------------
 // alerts module
 //-------------------------------------------------------------------------
-
 static const Parameter alerts_params[] =
 {
     { "alert_with_interface_name", Parameter::PT_BOOL, nullptr, "false",
@@ -626,7 +625,7 @@ static const Parameter alerts_params[] =
     { "log_references", Parameter::PT_BOOL, nullptr, "false",
       "include rule references in alert info (full only)" },
 
-    { "order", Parameter::PT_STRING, nullptr, "pass reset block drop alert log",
+    { "order", Parameter::PT_STRING, nullptr, nullptr,
       "change the order of rule action application" },
 
     { "rate_filter_memcap", Parameter::PT_INT, "0:max32", "1048576",
@@ -873,13 +872,8 @@ bool ActiveModule::set(const char*, Value& v, SnortConfig* sc)
         sc->set_dst_mac(v.get_string());
 
     else if ( v.is("max_responses") )
-    {
         sc->max_responses = v.get_uint8();
 
-        if ( sc->max_responses )
-            sc->set_active_enabled();
-    }
-
     else if ( v.is("min_interval") )
         sc->min_interval = v.get_uint8();
 
@@ -1711,6 +1705,9 @@ bool EventFilterModule::end(const char*, int idx, SnortConfig* sc)
 // rate_filter module
 //-------------------------------------------------------------------------
 
+function<const char*()> get_action_types = []()
+{ return PluginManager::get_available_plugins(PT_IPS_ACTION); };
+
 static const Parameter rate_filter_params[] =
 {
     { "gid", Parameter::PT_INT, "0:max32", "1",
@@ -1728,10 +1725,7 @@ static const Parameter rate_filter_params[] =
     { "seconds", Parameter::PT_INT, "0:max32", "1",
       "count interval" },
 
-    { "new_action", Parameter::PT_ENUM,
-      // FIXIT-L new_action options must match Actions::Type and
-      // should include pluggable actions as well
-      "log | pass | alert | drop | block | reset", "alert",
+    { "new_action", Parameter::PT_DYNAMIC, (void*)&get_action_types, "alert",
       "take this action on future hits until timeout" },
 
     { "timeout", Parameter::PT_INT, "0:max32", "1",
@@ -1811,7 +1805,13 @@ bool RateFilterModule::set(const char*, Value& v, SnortConfig*)
         thdx.applyTo = sfip_var_from_string(v.get_string(), "rate_filter");
 
     else if ( v.is("new_action") )
-        thdx.newAction = (Actions::Type)(v.get_uint8() + 1);
+    {
+        thdx.newAction = Actions::get_type(v.get_string());
+
+        if ( !Actions::is_valid_action(thdx.newAction) )
+            ParseError("unknown new_action type rate_filter configuration %s",
+                    v.get_string());
+    }
 
     else
         return false;
index 19df09fc7fb0a582c56ddf6323645f64a0973e3a..9842b0c4b504efb47c4bf3270e3a3095fb7a874a 100644 (file)
@@ -107,7 +107,7 @@ void InspectionPolicy::configure()
 // detection policy
 //-------------------------------------------------------------------------
 
-IpsPolicy::IpsPolicy(PolicyId id) : action(Actions::Type::MAX, nullptr)
+IpsPolicy::IpsPolicy(PolicyId id) : action(Actions::get_max_types(), nullptr)
 {
     policy_id = id;
     user_policy_id = 0;
index 89681ad719388aea743c1c4ebf955ba8c93707e4..7ed98958034e17ef0f9f154585d97c99571a0fdc 100644 (file)
@@ -43,7 +43,7 @@ namespace snort
 {
 class GHash;
 struct SnortConfig;
-class ActiveAction;
+class IpsAction;
 }
 
 struct PortTable;
@@ -184,9 +184,8 @@ public:
 
     bool obfuscate_pii;
 
-    // Holds plugin actions associated with this policy (e.g. reject, react, etc.)
-    // Indexed by Actions::Type.
-    std::vector<snort::ActiveAction*> action;
+    // Holds all plugin actions associated with this policy
+    std::vector<snort::IpsAction*> action;
 };
 
 //-------------------------------------------------------------------------
index 679aa4ec735f574cbffdb4343e9263964cc99e2e..93002e791f42647defafa9ea6e39410fc853cda8 100644 (file)
@@ -182,7 +182,7 @@ void Snort::init(int argc, char** argv)
     ModuleManager::reset_stats(sc);
 
     if (sc->alert_before_pass())
-        sc->rule_order = "reset block drop alert pass log";
+        sc->rule_order = Actions::get_default_priorities(true);
 
     sc->setup();
 
index d0e6a76d25cedbc12d076ca686042dba4bc7b121..fc51f6ed553ec447aac4ab88dc429a0d472eceeb 100644 (file)
@@ -27,6 +27,7 @@
 #include <pwd.h>
 #include <syslog.h>
 
+#include "actions/ips_actions.h"
 #include "detection/detect.h"
 #include "detection/detection_engine.h"
 #include "detection/fp_config.h"
@@ -178,7 +179,6 @@ void SnortConfig::init(const SnortConfig* const other_conf, ProtocolReference* p
         thread_config = new ThreadConfig();
         global_dbus = new DataBus();
 
-        memset(evalOrder, 0, sizeof(evalOrder));
         proto_ref = new ProtocolReference(protocol_reference);
         so_rules = new SoRules;
         trace_config = new TraceConfig;
@@ -271,6 +271,7 @@ SnortConfig::~SnortConfig()
     delete memory;
     delete daq_config;
     delete proto_ref;
+    delete[] evalOrder;
     delete so_rules;
     if ( plugins )
         delete plugins;
@@ -290,6 +291,10 @@ void SnortConfig::setup()
 
     init_policies(this);
     ParseRules(this);
+
+    // Allocate evalOrder before calling the OrderRuleLists
+    evalOrder = new int[Actions::get_max_types()]();
+
     OrderRuleLists(this);
 
     if ( rule_states )
index 24a2a9e70b1f1405fe0ca21783ac1929d0a08492..94c753ec95c1d0def6643917098d6bd568a153c6 100644 (file)
@@ -29,6 +29,7 @@
 #include <unordered_map>
 #include <vector>
 
+#include "actions/actions.h"
 #include "events/event_queue.h"
 #include "framework/bits.h"
 #include "helpers/scratch_allocator.h"
@@ -356,7 +357,7 @@ public:
 
     unsigned num_rule_types = 0;
     RuleListNode* rule_lists = nullptr;
-    int evalOrder[Actions::MAX + 1];
+    int* evalOrder = nullptr;
 
     IpsActionsConfig* ips_actions_config = nullptr;
     FrameworkConfig* framework_config = nullptr;
@@ -427,7 +428,6 @@ public:
 
     DumpConfigType dump_config_type = DUMP_CONFIG_NONE;
 private:
-    bool active_enabled = false;
     std::list<ReloadResourceTuner*> reload_tuners;
 
 public:
@@ -604,13 +604,6 @@ public:
     bool assure_established() const
     { return run_flags & RUN_FLAG__ASSURE_EST; }
 
-    // active stuff
-    void set_active_enabled()
-    { active_enabled = true; }
-
-    bool is_active_enabled() const
-    { return active_enabled; }
-
     // other stuff
     uint8_t min_ttl() const
     { return get_network_policy()->min_ttl; }
index 1d7401a83c0686c9c02097ea7fb4faae773466eb..6c8470428fea5d1d7468433b6610999d7abced04 100644 (file)
@@ -27,6 +27,8 @@
 
 #include "log/messages.h"
 #include "main/snort_config.h"
+#include "managers/module_manager.h"
+#include "managers/plugin_manager.h"
 #include "packet_io/active.h"
 #include "parser/parser.h"
 
@@ -57,8 +59,13 @@ struct IpsActionsConfig
 };
 
 using ACList = vector<ActionClass>;
+using ACTypeList = unordered_map<string, Actions::Type>;
+using ACPriorityList = map<IpsAction::IpsActionPriority, string, std::greater<int>>;
 
 static ACList s_actors;
+static ACTypeList s_act_types;
+static ACPriorityList s_act_priorities;
+static Actions::Type s_act_index = 0;
 
 static THREAD_LOCAL ACList* s_tl_actors = nullptr;
 
@@ -70,16 +77,67 @@ static THREAD_LOCAL ACList* s_tl_actors = nullptr;
 void ActionManager::add_plugin(const ActionApi* api)
 {
     s_actors.emplace_back(api);
+    s_act_types.emplace(api->base.name, s_act_index++);
+    s_act_priorities.emplace(api->priority, api->base.name);
+}
+
+std::string ActionManager::get_action_string(Actions::Type action)
+{
+    if ( action < s_act_index )
+    {
+        for ( const auto& type : s_act_types )
+        {
+            if ( type.second == action )
+                return type.first;
+        }
+    }
+
+    return "ERROR";
 }
 
 Actions::Type ActionManager::get_action_type(const char* s)
 {
-    for ( auto& p : s_actors )
+    auto type = s_act_types.find(s);
+
+    if (type != s_act_types.end())
+        return type->second;
+
+    return get_max_action_types();
+}
+
+Actions::Type ActionManager::get_max_action_types()
+{
+    return s_act_index;
+}
+
+std::string ActionManager::get_action_priorities(bool alert_before_pass)
+{
+    std::string priorities;
+
+    for (auto iter = s_act_priorities.begin(); iter != s_act_priorities.end(); )
     {
-        if ( !strcmp(p.api->base.name, s) )
-            return p.api->type;
+        if ( alert_before_pass )
+        {
+            if ( iter->second == "pass" )
+            {
+                iter++;
+                continue;
+            }
+            else if ( iter->second == "alert" )
+            {
+                priorities += "alert pass ";
+                iter++;
+                continue;
+            }
+        }
+
+        priorities += iter->second;
+
+        if ( ++iter != s_act_priorities.end() )
+            priorities += " ";
     }
-    return Actions::NONE;
+
+    return priorities;
 }
 
 void ActionManager::dump_plugins()
@@ -144,26 +202,49 @@ void ActionManager::delete_config(SnortConfig* sc)
     sc->ips_actions_config = nullptr;
 }
 
-void ActionManager::instantiate(const ActionApi* api, Module* mod, SnortConfig* sc)
+void ActionManager::instantiate(const ActionApi* api, Module* mod, SnortConfig* sc, IpsPolicy* ips)
 {
     ActionClass* cls = get_action_class(api, sc->ips_actions_config);
+
     assert(cls != nullptr);
 
     IpsAction* act = cls->api->ctor(mod);
 
     if ( act )
     {
-        // Add this instance to the list of those created for this config
-        sc->ips_actions_config->clist.emplace_back(*cls, act);
 
-        RuleListNode* rln = CreateRuleType(sc, api->base.name, api->type, true);
+        RuleListNode* rln = CreateRuleType(sc, api->base.name, get_action_type(api->base.name));
 
         // 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();
+        if ( !ips )
+            ips = get_ips_policy();
+
         Actions::Type idx = rln->mode;
-        assert(ips->action[idx] == nullptr);
-        ips->action[idx] = act;
+        if (ips->action[idx] == nullptr)
+        {
+            ips->action[idx] = act;
+            // Add this instance to the list of those created for this config
+            sc->ips_actions_config->clist.emplace_back(*cls, act);
+        }
+        else
+        {
+            cls->api->dtor(act);
+        }
+    }
+}
+
+void ActionManager::initialize_policies(SnortConfig* sc)
+{
+    for (unsigned i = 0; i < sc->policy_map->ips_policy_count(); i++)
+    {
+        auto policy = sc->policy_map->get_ips_policy(i);
+
+        if ( !policy )
+            continue;
+
+        for ( auto actor : s_actors )
+            ActionManager::instantiate(actor.api, nullptr, sc, policy);
     }
 }
 
index bfb95fad5b90591283d1dd61027670c4883d13d3..b3dd0c93114f2e1db22a377737a47b840bf5bc78 100644 (file)
@@ -36,6 +36,8 @@ struct SnortConfig;
 struct Packet;
 }
 
+struct IpsPolicy;
+
 //-------------------------------------------------------------------------
 
 #ifdef PIGLET
@@ -63,10 +65,16 @@ public:
     static void dump_plugins();
 
     static void new_config(snort::SnortConfig*);
-    static snort::Actions::Type get_action_type(const char*);
     static void delete_config(snort::SnortConfig*);
 
-    static void instantiate(const snort::ActionApi*, snort::Module*, snort::SnortConfig*);
+    static void instantiate(const snort::ActionApi*, snort::Module*,
+            snort::SnortConfig*, IpsPolicy* ips = nullptr );
+    static void initialize_policies(snort::SnortConfig*);
+
+    static std::string get_action_string(Actions::Type);
+    static Actions::Type get_action_type(const char*);
+    static Actions::Type get_max_action_types(void);
+    static std::string get_action_priorities(bool);
 
     static void thread_init(const snort::SnortConfig*);
     static void thread_reinit(const snort::SnortConfig*);
index 4165775a5dd3b35f29966aabacd6fcea76542b78..313b6a4d76530f1df8b731043654a29fc37fdecb 100644 (file)
@@ -47,9 +47,9 @@ using namespace snort;
 class ResetAction : public snort::ActiveAction
 {
 public:
-    ResetAction() : ActiveAction(ActionType::ACT_RESET) { }
+    ResetAction() : ActiveAction(ActionPriority::AP_RESET) { }
 
-    void exec(snort::Packet* p) override
+    void delayed_exec(snort::Packet* p) override
     {
         p->active->kill_session(p, ENC_FLAG_FWD);
     }
@@ -183,10 +183,10 @@ bool Active::thread_init(const SnortConfig* sc)
     if ( s_attempts > MAX_ATTEMPTS )
         s_attempts = MAX_ATTEMPTS;
 
-    if ( sc->is_active_enabled() && !s_attempts )
+    if ( !s_attempts )
         s_attempts = 1;
 
-    if ( sc->is_active_enabled() && (!SFDAQ::can_inject() || !sc->respond_device.empty()) )
+    if ( !SFDAQ::can_inject() || !sc->respond_device.empty() )
     {
         if ( sc->read_mode() ||
             !open(sc->respond_device.empty() ? nullptr : sc->respond_device.c_str()) )
@@ -695,16 +695,13 @@ void Active::reset_session(Packet* p, ActiveAction* reject, bool force)
     if ( force or (p->context->conf->inline_mode() and SFDAQ::forwarding_packet(p->pkth)))
         Stream::drop_flow(p);
 
-    if ( p->context->conf->is_active_enabled() )
-    {
-        if (reject)
-            Active::queue(reject, p);
+    if (reject)
+        Active::queue(reject, p);
 
-        if ( p->flow )
-        {
-            Stream::init_active_response(p, p->flow);
-            p->flow->set_state(Flow::FlowState::RESET);
-        }
+    if ( p->flow )
+    {
+        Stream::init_active_response(p, p->flow);
+        p->flow->set_state(Flow::FlowState::RESET);
     }
 
     p->disable_inspect = true;
@@ -818,7 +815,7 @@ void Active::execute(Packet* p)
 {
     if ( *p->action )
     {
-        (*p->action)->exec(p);
+        (*p->action)->delayed_exec(p);
         *p->action = nullptr;
     }
 
index 88f5ff0001e817c97e7401d8a6dda555884e2fb1..485d976bbf48b302109d2ca63882f859a4f8b2b3 100644 (file)
@@ -27,14 +27,14 @@ namespace snort
 {
 struct Packet;
 
-enum ActionType
+enum ActionPriority
 {
-    ACT_LOCAL,
-    ACT_MODIFY,
-    ACT_PROXY,
-    ACT_RESET,
-    ACT_REMOTE,
-    ACT_MAX
+    AP_LOCAL,
+    AP_MODIFY,
+    AP_PROXY,
+    AP_RESET,
+    AP_REMOTE,
+    AP_MAX
 };
 
 // These are injection actions (e.g. send a RST packet, or respond to a query
@@ -45,15 +45,15 @@ enum ActionType
 class SO_PUBLIC ActiveAction
 {
 public:
-    ActiveAction(ActionType a = ActionType::ACT_MAX) : action(a) {}
+    ActiveAction(ActionPriority a = ActionPriority::AP_MAX) : action(a) {}
     virtual ~ActiveAction() = default;
 
-    virtual void exec(Packet*) = 0;
+    virtual void delayed_exec(Packet* ) { }
 
-    ActionType get_action() const { return action; }
+    ActionPriority get_action() const { return action; }
 
 protected:
-    ActionType action;
+    ActionPriority action;
 
 };
 
index e646c9b68c8df0745a0bebbe8a47da59a1e6bfe7..ce60702b170170ee4376ad84b342d8c82e9187ac 100644 (file)
 #include <sys/stat.h>
 #include <unistd.h>
 
+#include <cassert>
 #include <climits>
 #include <fstream>
 #include <stack>
 
 #include "log/messages.h"
 #include "main/snort_config.h"
-#include "managers/action_manager.h"
 #include "managers/module_manager.h"
 #include "sfip/sf_vartable.h"
 #include "target_based/snort_protocols.h"
@@ -265,30 +265,6 @@ void add_service_to_otn(SnortConfig* sc, OptTreeNode* otn, const char* svc_name)
     otn->sigInfo.services.emplace_back(si);
 }
 
-Actions::Type get_rule_type(const char* s)
-{
-    Actions::Type rt = Actions::get_type(s);
-
-    if ( rt == Actions::NONE )
-        rt = ActionManager::get_action_type(s);
-
-    switch ( rt )
-    {
-    case Actions::DROP:
-    case Actions::BLOCK:
-    case Actions::RESET:
-        return rt;
-
-    case Actions::NONE:
-        ParseError("unknown rule type '%s'", s);
-        break;
-
-    default:
-        break;
-    }
-    return rt;
-}
-
 ListHead* get_rule_list(SnortConfig* sc, const char* s)
 {
     const RuleListNode* p = sc->rule_lists;
index 7f320f1b48352fcc811fcf3882836d1f6248cd85..3baa5d1c69c5f2dc513fdd7c545c86d4f5d52568 100644 (file)
@@ -46,7 +46,6 @@ void parse_include(snort::SnortConfig*, const char*);
 
 void add_service_to_otn(snort::SnortConfig*, OptTreeNode*, const char*);
 
-snort::Actions::Type get_rule_type(const char*);
 ListHead* get_rule_list(snort::SnortConfig*, const char*);
 
 #endif
index 7069343a900b248b8b40c9a2dc7aa280d08df12c..d287a563eae61b60f98d802d38069488a66e3ae0 100644 (file)
@@ -23,6 +23,7 @@
 
 #include "parse_rule.h"
 
+#include "actions/actions.h"
 #include "detection/detect.h"
 #include "detection/fp_config.h"
 #include "detection/fp_utils.h"
@@ -955,13 +956,17 @@ void parse_rule_type(SnortConfig* sc, const char* s, RuleTreeNode& rtn)
     if ( s_so_rule )
         return;
 
-    rtn.action = get_rule_type(s);
+    assert(s);
 
-    if ( rtn.action == Actions::NONE )
+    rtn.action = Actions::get_type(s);
+
+    if ( !Actions::is_valid_action(rtn.action) )
     {
         s_ignore = true;
+        ParseError("unknown rule action '%s'", s);
         return;
     }
+
     if ( sc->dump_rule_meta() )
         rtn.header = new RuleHeader(s);
 
@@ -972,11 +977,9 @@ void parse_rule_type(SnortConfig* sc, const char* s, RuleTreeNode& rtn)
         CreateRuleType(sc, s, rtn.action);
         rtn.listhead = get_rule_list(sc, s);
     }
+
     if ( sc->get_default_rule_state() )
         rtn.set_enabled();
-
-    if ( !rtn.listhead )
-        ParseError("unconfigured rule action '%s'", s);
 }
 
 void parse_rule_proto(SnortConfig* sc, const char* s, RuleTreeNode& rtn, bool elided)
index 71c5ea18bef75b54aa03855695b7d21058a22fc0..e9b0b1ee0352c876bf8bb90dc6103666610a9934 100644 (file)
@@ -45,6 +45,7 @@
 #include "main/modules.h"
 #include "main/shell.h"
 #include "main/snort_config.h"
+#include "managers/action_manager.h"
 #include "managers/event_manager.h"
 #include "managers/module_manager.h"
 #include "ports/port_object.h"
@@ -289,6 +290,7 @@ static bool parse_file(SnortConfig* sc, Shell* sh, bool is_fatal, bool is_root)
         return false;
 
     bool success = sh->configure(sc, is_fatal, is_root);
+
     return success;
 }
 
@@ -379,6 +381,8 @@ SnortConfig* ParseSnortConf(const SnortConfig* cmd_line_conf, const char* fname,
     // Merge in any overrides from the command line
     sc->merge(cmd_line_conf);
 
+    ActionManager::initialize_policies(sc);
+
     return sc;
 }
 
@@ -551,10 +555,9 @@ void ShowPolicyStats(const SnortConfig* sc)
  * Returns: the ListHead for the rule type
  *
  ***************************************************************************/
-RuleListNode* CreateRuleType(SnortConfig* sc, const char* name, Actions::Type mode, bool is_plugin_action)
+RuleListNode* CreateRuleType(SnortConfig* sc, const char* name, Actions::Type mode)
 {
     RuleListNode* node;
-    unsigned evalIndex = 0;
 
     if (sc == nullptr)
         return nullptr;
@@ -580,7 +583,6 @@ RuleListNode* CreateRuleType(SnortConfig* sc, const char* name, Actions::Type mo
                 return tmp;
             }
 
-            evalIndex++;
             last = tmp;
             tmp = tmp->next;
         }
@@ -591,12 +593,9 @@ RuleListNode* CreateRuleType(SnortConfig* sc, const char* name, Actions::Type mo
 
     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;
 
-    sc->evalOrder[node->mode] =  evalIndex;
     sc->num_rule_types++;
 
     return node;
@@ -629,10 +628,14 @@ void OrderRuleLists(SnortConfig* sc)
 {
     int evalIndex = 0;
     RuleListNode* ordered_list = nullptr;
+    std::string default_priorities;
 
     const char* order = sc->rule_order.c_str();
     if ( !*order )
-        order = "pass drop alert log";  // FIXIT-M apply builtin module defaults
+    {
+        default_priorities = Actions::get_default_priorities();  // FIXIT-M apply builtin module defaults
+        order = default_priorities.c_str();
+    }
 
     std::stringstream ss(order);
     std::string tok;
@@ -670,7 +673,7 @@ void OrderRuleLists(SnortConfig* sc)
         RuleListNode* node = sc->rule_lists;
         sc->rule_lists = node->next;
         ordered_list = addNodeToOrderedList(ordered_list, node, evalIndex++);
-        sc->evalOrder[node->mode] =  evalIndex;
+        sc->evalOrder[node->mode] = evalIndex;
     }
 
     sc->rule_lists = ordered_list;
index 5b4821c91b6303933a16913921e85c2fea856882..79be6d14c297a4c011ed74fd28c4ed6a4b03f693 100644 (file)
@@ -86,8 +86,7 @@ inline RuleTreeNode* getRuntimeRtnFromOtn(const struct OptTreeNode* otn)
     return getRtnFromOtn(otn);
 }
 
-RuleListNode* CreateRuleType(snort::SnortConfig* sc, const char* name,
-    snort::Actions::Type, bool is_plugin_action = false);
+RuleListNode* CreateRuleType(snort::SnortConfig* sc, const char* name, Actions::Type action_type);
 
 void FreeRuleTreeNode(RuleTreeNode*);
 void DestroyRuleTreeNode(RuleTreeNode*);
index 01f5ec80aeee7922010920a0f7b3f3629416d033..c6646506b12d368c5a2254f168307b9429153cc9 100644 (file)
@@ -81,7 +81,7 @@ static void set_not_configured() { conf.payload_injector_config = nullptr; }
 static void set_configured() { conf.payload_injector_config = &pi_conf; }
 
 Packet::~Packet() = default;
-int DetectionEngine::queue_event(unsigned int, unsigned int, snort::Actions::Type) { return 0; }
+int DetectionEngine::queue_event(unsigned int, unsigned int) { return 0; }
 FlowData::~FlowData() = default;
 FlowData::FlowData(unsigned int, snort::Inspector*) { }
 
index d3475d0fc9420039054f7f5b2250af1844031f0d..c1e9b1a1320a7f338004bb26ef074bcdb56f7933 100644 (file)
@@ -36,7 +36,7 @@ using namespace snort;
 // FIXIT-M needs to be updated for addition of get_fp_buf()
 template<typename T>
 static inline bool get_buf(
-    Inspector& i, T v, Packet& p, std::string& rb)
+    Inspector& i, T v, snort::Packet& p, std::string& rb)
 {
     struct InspectionBuffer ib;
     bool result = i.get_buf(v, &p, ib);
index 52df4a8c145e9df128d6419f8405f04be111df89..0e18f597890262b516d6fd6621d874ce678b9f75 100644 (file)
@@ -38,7 +38,7 @@ static const luaL_Reg methods[] =
             auto& p = PacketIface.get(L);
             auto& self = IpsActionIface.get(L);
 
-            self.exec(&p);
+            self.exec(&p, nullptr);
 
             return 0;
         }
index 8eec00d41eb9ecff32a23953cb3c90db5ffb9b00..7680e31973febdd3adc036927c73b8cc83b13e9a 100644 (file)
@@ -32,7 +32,7 @@
 namespace snort
 {
 // Stubs whose sole purpose is to make the test code link
-int DetectionEngine::queue_event(unsigned int, unsigned int, Actions::Type) { return 0; }
+int DetectionEngine::queue_event(unsigned int, unsigned int) { return 0; }
 }
 
 using namespace Http2Enums;
index 6e69ae2c0b6a3ceb4a9fd59f7901d7f3544a8a98..2baf159a2862c7f5916c3295d92d12e5024d960c 100644 (file)
@@ -35,7 +35,7 @@
 namespace snort
 {
 // Stubs whose sole purpose is to make the test code link
-int DetectionEngine::queue_event(unsigned int, unsigned int, Actions::Type) { return 0; }
+int DetectionEngine::queue_event(unsigned int, unsigned int) { return 0; }
 }
 
 using namespace Http2Enums;
index ec5d19029afc6a283245b0f1eb1472fd8a855f30..47f3676b0c3ffcb720f2d8ce28094cdf693fa031 100755 (executable)
@@ -48,7 +48,7 @@ void Value::get_bits(std::bitset<256ul>&) const {}
 void Value::set_first_token() {}
 bool Value::get_next_token(std::string& ) { return false; }
 
-int DetectionEngine::queue_event(unsigned int, unsigned int, Actions::Type) { return 0; }
+int DetectionEngine::queue_event(unsigned int, unsigned int) { return 0; }
 LiteralSearch::Handle* LiteralSearch::setup() { return nullptr; }
 void LiteralSearch::cleanup(LiteralSearch::Handle*) {}
 LiteralSearch* LiteralSearch::instantiate(LiteralSearch::Handle*, const uint8_t*, unsigned, bool,
index fd88bb2206e091c51b80c5de10f7ec8877e6601d..f1c68448eaaf647af53c7ff51b1da53410071cea 100644 (file)
@@ -43,7 +43,7 @@ namespace snort
 unsigned FlowData::flow_data_id = 0;
 FlowData::FlowData(unsigned, Inspector*) {}
 FlowData::~FlowData() = default;
-int DetectionEngine::queue_event(unsigned int, unsigned int, Actions::Type) { return 0; }
+int DetectionEngine::queue_event(unsigned int, unsigned int) { return 0; }
 fd_status_t File_Decomp_StopFree(fd_session_t*) { return File_Decomp_OK; }
 uint32_t str_to_hash(const uint8_t *, size_t) { return 0; }
 void FlowData::update_allocations(size_t) {}
index 83a2041effb6c2205ae66e38a95fbf78d8537a82..5621c58af20378677fbfe7048a7af87bd46f5947 100755 (executable)
@@ -43,7 +43,7 @@ void ParseError(const char*, ...) {}
 void Value::get_bits(std::bitset<256ul>&) const {}
 void Value::set_first_token() {}
 bool Value::get_next_token(std::string& ) { return false; }
-int DetectionEngine::queue_event(unsigned int, unsigned int, Actions::Type) { return 0; }
+int DetectionEngine::queue_event(unsigned int, unsigned int) { return 0; }
 LiteralSearch::Handle* LiteralSearch::setup() { return nullptr; }
 void LiteralSearch::cleanup(LiteralSearch::Handle*) {}
 LiteralSearch* LiteralSearch::instantiate(LiteralSearch::Handle*, const uint8_t*, unsigned, bool,
index 69040795774ca08b2d50c32d0cf49648e169699d..4b0c0c1df1a1e846cfce7f25fbc9e2af2b847047 100644 (file)
@@ -364,11 +364,8 @@ bool SmtpModule::begin(const char*, int, SnortConfig*)
     return true;
 }
 
-bool SmtpModule::end(const char* fqn, int idx, SnortConfig* sc)
+bool SmtpModule::end(const char* fqn, int idx, SnortConfig*)
 {
-    if ( !strcmp(fqn, "smtp") and config->xlink2state )
-        sc->set_active_enabled();
-
     if ( !idx )
         return true;
 
index 2ca66c57951e1642f037857b9595d9fff44d4332..9d2da5e4aa98f2c044218c3f7ef566c974e297a7 100644 (file)
@@ -134,6 +134,20 @@ static const ConvertMap disable_ipopt_drops_api =
 
 const ConvertMap* disable_ipopt_drops_map = &disable_ipopt_drops_api;
 
+/*************************************************
+ ****************  disable_replace ***************
+ *************************************************/
+
+static const std::string disable_replace = "disable_replace";
+static const ConvertMap disable_replace_api =
+{
+    disable_replace,
+    deleted_ctor<& disable_replace>,
+};
+
+const ConvertMap* disable_replace_map = &disable_replace_api;
+
+
 /*************************************************
  ************  disable_tcpopt_alerts  ************
  *************************************************/
index e73dd1aec71e13de7c9a5515ccfcafbfdbd45e65..8383ca11f2a1f97b80e6073b895c4483c1d36ebe 100644 (file)
@@ -110,7 +110,6 @@ static const std::string ips = "ips";
 static const std::string packets = "packets";
 static const std::string process = "process";
 static const std::string output = "output";
-static const std::string rewrite = "rewrite";
 
 /*************************************************
  **********  addressspace_agnostic  **********
@@ -181,19 +180,6 @@ static const ConvertMap dirty_pig_api =
 
 const ConvertMap* dirty_pig_map = &dirty_pig_api;
 
-/*************************************************
- *****  disable rewrite rules with replace *******
- *************************************************/
-
-static const std::string disable_replace = "disable_replace";
-static const ConvertMap disable_replace_api =
-{
-    disable_replace,
-    config_true_no_opt_ctor<& disable_replace, & rewrite>,
-};
-
-const ConvertMap* disable_replace_map = &disable_replace_api;
-
 /*************************************************
  ***************  dump_chars_only  ***************
  *************************************************/
index 261f55569a7f0995c47536c575217fa4ff911638..91759d6ec2cba0e70eab844b00c5c6140ad7076b 100644 (file)
@@ -74,10 +74,6 @@ static ConversionState* ctor(Converter& c)
         "Changing ruletype '" + old_action + "' to 'rewrite' "
         "because the rule has 'replace' option.");
 
-    // include a rewrite plugin
-    c.get_table_api().open_table("rewrite");
-    c.get_table_api().close_table();
-
     // update the rule type
     c.get_rule_api().update_rule_action("rewrite");