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
set( PLUGIN_LIST
act_react.cc
act_reject.cc
- act_resp.cc
+ act_replace.cc
+ act_replace.h
)
if (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)
plugin_list = \
act_react.cc \
act_reject.cc \
-act_resp.cc
+act_replace.cc \
+act_replace.h
libips_actions_a_SOURCES = \
actions.cc \
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@
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;
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
//-------------------------------------------------------------------------
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
//-------------------------------------------------------------------------
//--------------------------------------------------------------------
-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)
{
+/****************************************************************************
+ *
+ * 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 <rucombs@cisco.com>
+ * 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 <rucombs@cisco.com>
#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,
mod_dtor
},
RULE_TYPE__DROP,
- nullptr,
+ rej_ginit,
nullptr,
nullptr,
nullptr,
+++ /dev/null
-/****************************************************************************
- *
- * 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 <rucombs@cisco.com>
-
-#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
-
#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[] =
#ifdef STATIC_IPS_ACTIONS
act_react,
act_reject,
- act_resp,
+ act_replace,
#endif
nullptr,
};
#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"
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;
// 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)
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);
}
/*
#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;
{
Active_ForceDropPacket();
Active_DropSession();
- Active_QueueReject();
+ ActionManager::queue_reject();
if (log_file_action)
{
log_file_action(p->flow, FILE_RESUME_BLOCK);
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);
// api for class
//-------------------------------------------------------------------------
+enum ActionType
+{
+ ACT_LOCAL,
+ ACT_MODIFY,
+ ACT_PROXY,
+ ACT_RESET,
+ ACT_REMOTE,
+ ACT_MAX
+};
+
struct SnortConfig;
class IpsAction
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)();
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-#include "ips_replace.h"
-
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#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)
{
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
//-------------------------------------------------------------------------
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);
}
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 }
};
bool ReplModule::set(const char*, Value& v, SnortConfig*)
{
- if ( v.is("~mode") )
+ if ( v.is("~") )
replace_parse(v.get_string(), data);
else
delete p;
}
-static void replace_tinit(SnortConfig*)
-{
- rpl = new Replacement[MAX_REPLACEMENTS];
-}
-
-static void replace_tterm(SnortConfig*)
-{
- delete[] rpl;
-}
-
static const IpsApi replace_api =
{
{
0, 0,
nullptr,
nullptr,
- replace_tinit,
- replace_tterm,
+ nullptr,
+ nullptr,
replace_ctor,
replace_dtor,
nullptr
+++ /dev/null
-/*
-** Copyright (C) 2014 Cisco and/or its affiliates. All rights reserved.
-** Copyright (C) 2002-2013 Sourcefire, Inc.
-** Copyright (C) 1998-2002 Martin Roesch <roesch@sourcefire.com>
-**
-** 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 <assert.h>
-#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
-
#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"
#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"
#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"
// 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();
* 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);
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
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 )
}
else
{
- Replace_ModifyPacket(&s_packet);
-
if ( s_packet.packet_flags & PKT_MODIFIED )
{
// this packet was normalized and/or has replacements
EventManager::open_outputs();
IpsManager::setup_options();
+ ActionManager::thread_init(snort_conf);
InspectorManager::thread_init(snort_conf);
}
#endif
ModuleManager::accumulate(snort_conf);
InspectorManager::thread_term(snort_conf);
+ ActionManager::thread_term(snort_conf);
IpsManager::clear_options();
EventManager::close_outputs();
#include "search_engines/search_engines.h"
#include "parser/parser.h"
#include "log/messages.h"
+#include "actions/act_replace.h"
typedef list<const ActionApi*> AList;
static AList s_actors;
+static IpsAction* s_reject = nullptr;
+static THREAD_LOCAL IpsAction* s_action = nullptr;
+
//-------------------------------------------------------------------------
// engine plugins
//-------------------------------------------------------------------------
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)
{
}
#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();
+}
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*);
};
#include "stream/stream_api.h"
#include "snort.h"
+#include "managers/action_manager.h"
#include "managers/packet_manager.h"
#include "packet_io/sfdaq.h"
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) (
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)
{
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?
case IPPROTO_ICMP:
case IPPROTO_ICMPV6:
if ( Active_IsUNRCandidate(p) )
- Active_QueueReject();
+ ActionManager::queue_reject();
break;
}
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
OtnInit(sc);
- InitVarTables(sc->policy_map->ips_policy[0]);
-
sc->fast_pattern_config = FastPatternConfigNew();
sc->event_queue_config = EventQueueConfigNew();
sc->threshold_config = ThresholdConfigNew();