* IPS rules may also have a wild card parameter, which is indicated by a
*. Used for unquoted, comma-separated lists such as service and metadata.
* The snort module has command line options starting with a -.
-* $ denotes variable names, eg rule_state.$gid_sid which would be used
- like rule_state["1:23456"] = { }.
+* $ denotes variable names.
Some additional details to note:
return true;
}
-//-------------------------------------------------------------------------
-// rule_state module
-//-------------------------------------------------------------------------
-
-static const Parameter single_rule_state_params[] =
-{
- { "action", Parameter::PT_ENUM,
- "log | pass | alert | drop | block | reset", "alert",
- "apply action if rule matches or inherit from rule definition" },
-
- { "enable", Parameter::PT_ENUM, "no | yes | inherit", "inherit",
- "enable or disable rule in current ips policy or use default defined by ips policy" },
-
- { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
-};
-
-static const Parameter rule_state_params[] =
-{
- { "$gid_sid", Parameter::PT_LIST, single_rule_state_params, nullptr,
- "defines rule state parameters for gid:sid" },
-
- { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
-};
-
-#define rule_state_help \
- "enable/disable and set actions for specific IPS rules; " \
- "deprecated, use rule state stubs with enable instead"
-
-class RuleStateModule : public Module
-{
-public:
- RuleStateModule() : Module("rule_state", rule_state_help, rule_state_params, false) { }
-
- bool set(const char*, Value&, SnortConfig*) override;
- bool begin(const char*, int, SnortConfig*) override;
- bool end(const char*, int, SnortConfig*) override;
-
- bool matches(const char*, std::string&) override;
-
- Usage get_usage() const override
- { return DETECT; }
-
-private:
- RuleKey key;
- RuleState state;
-};
-
-bool RuleStateModule::matches(const char* param, std::string& name)
-{
- if ( strcmp(param, "$gid_sid") )
- return false;
-
- std::stringstream ss(name);
- char sep;
-
- ss >> key.gid >> sep >> key.sid;
-
- if ( key.gid and key.sid and sep == ':' )
- return true;
-
- return false;
-}
-
-bool RuleStateModule::set(const char* fqn, Value& v, SnortConfig*)
-{
- // the name itself is passed as the fqn when declaring rule_state = { }
- if ( !strcmp(fqn, "$gid_sid") )
- return true;
-
- if ( key.gid and key.sid )
- {
- if ( v.is("action") )
- {
- state.rule_action = v.get_string();
- state.action = snort::Actions::Type(v.get_uint8() + 1);
- }
-
- else if ( v.is("enable") )
- state.enable = IpsPolicy::Enable(v.get_uint8());
- }
- else
- return false;
-
- return true;
-}
-
-bool RuleStateModule::begin(const char*, int, SnortConfig* sc)
-{
- if ( !sc->rule_states )
- sc->rule_states = new RuleStateMap;
-
- else
- {
- key = { 0, 0, 0 };
- state.action = snort::Actions::Type::ALERT;
- state.enable = IpsPolicy::Enable::INHERIT_ENABLE;
- }
- return true;
-}
-
-bool RuleStateModule::end(const char* fqn, int, SnortConfig* sc)
-{
- if ( !strcmp(fqn, "rule_state") )
- return true;
-
- if ( !key.gid or !key.sid )
- return false;
-
- key.policy_id = snort::get_ips_policy()->policy_id;
- sc->rule_states->add(key, state);
-
- return true;
-}
-
//-------------------------------------------------------------------------
// hosts module
//-------------------------------------------------------------------------
ModuleManager::add_module(new ProcessModule);
ModuleManager::add_module(new ProfilerModule);
ModuleManager::add_module(new ReferencesModule);
- ModuleManager::add_module(new RuleStateModule);
ModuleManager::add_module(new SearchEngineModule);
ModuleManager::add_module(new SFDAQModule);
ModuleManager::add_module(new PayloadInjectorModule);
if ( !s_config_output || !s_current_node )
return;
- // lua interpreter does not call open_table for simple list items like (string) or
- // special rule_state list items
- // We have to add tree node for this item too
+ // lua interpreter does not call open_table for simple list items like (string)
+ // we have to add tree node for this item
if ( s_current_node->get_type() == Parameter::PT_LIST )
{
- auto node = s_current_node->get_node("");
- if ( !node || s_current_node->get_name().find(":") == std::string::npos )
- {
- node = new TreeConfigNode(s_current_node, "", Parameter::PT_TABLE);
- s_current_node->add_child_node(node);
- }
-
- node->add_child_node(new ValueConfigNode(node, value));
+ add_config_child_node("", Parameter::PT_TABLE);
+ s_current_node->add_child_node(new ValueConfigNode(s_current_node, value));
+ s_current_node = s_current_node->get_parent_node();
return;
}
profiler = { } -- don't activate
rate_filter = { } -- pure list
references = { } -- pure list
-rule_state = { } -- pure list
side_channel = { } -- leaks!
snort = { } -- command line only
suppress = { } -- pure list
class DataApi;
class RuleApi;
+class StateApi;
class TableApi;
class ConversionState
// FIXIT-L these should be removed and accessed through cv
data_api(c.get_data_api()),
table_api(c.get_table_api()),
- rule_api(c.get_rule_api())
+ rule_api(c.get_rule_api()),
+ state_api(c.get_state_api())
{ }
virtual ~ConversionState() = default;
virtual bool convert(std::istringstream& data)=0;
DataApi& data_api;
TableApi& table_api;
RuleApi& rule_api;
+ StateApi& state_api;
inline bool eat_option(std::istringstream& stream)
{
add_library( conversion_data OBJECT
dt_data.h
dt_data.cc
- dt_table_api.h
- dt_table_api.cc
dt_rule_api.h
dt_rule_api.cc
+ dt_state_api.h
+ dt_state_api.cc
+ dt_table_api.h
+ dt_table_api.cc
)
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2020-2020 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.
+//--------------------------------------------------------------------------
+// dt_state_api.cc author Serhii Vlasiuk <svlasiuk@cisco.com>
+
+#include "data/dt_state_api.h"
+
+#include "data/data_types/dt_rule.h"
+
+void StateApi::create_state()
+{
+ curr_state = new Rule();
+ states.push_back(curr_state);
+}
+
+void StateApi::clear()
+{
+ for (auto s : states)
+ delete s;
+
+ states.clear();
+}
+
+bool StateApi::empty() const
+{
+ return states.empty();
+}
+
+void StateApi::set_action(const std::string& action)
+{
+ if ( curr_state )
+ curr_state->add_hdr_data(action);
+}
+
+void StateApi::add_option(const std::string& name, const std::string& val)
+{
+ if ( curr_state )
+ curr_state->add_option(name, val);
+}
+
+void StateApi::add_comment(const std::string& comment)
+{
+ if ( curr_state )
+ curr_state->add_comment(comment);
+}
+
+void StateApi::print_states(std::ostream& out) const
+{
+ if ( states.empty() )
+ return;
+
+ out << "local_states =\n[[\n";
+
+ for (const auto r : states)
+ out << (*r) << "\n";
+
+ out << "]]\n\n";
+}
+
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2020-2020 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.
+//--------------------------------------------------------------------------
+// dt_state_api.h author Serhii Vlasiuk <svlasiuk@cisco.com>
+
+#ifndef DATA_DT_STATE_API_H
+#define DATA_DT_STATE_API_H
+
+#include <iostream>
+#include <vector>
+
+class Rule;
+
+class StateApi
+{
+public:
+ StateApi() = default;
+ ~StateApi() = default;
+
+ void create_state();
+ void clear();
+ bool empty() const;
+ void add_option(const std::string& keyword, const std::string& val);
+ void add_comment(const std::string& comment);
+ void set_action(const std::string& action);
+ void print_states(std::ostream& out) const;
+
+private:
+ std::vector<Rule*> states;
+ Rule* curr_state = nullptr;
+};
+
+#endif
+
{ "ips", true },
{ "network", true },
{ "normalizer", true },
- { "rule_state", true },
{ "stream_tcp", true },
{ "suppress", true },
};
out << "\n";
data_api.print_data(out);
+ if (!state_api.empty())
+ {
+ table_api.open_top_level_table("ips");
+ state_api.print_states(out);
+ state_api.clear();
+ table_api.add_option("states", "$local_states");
+ table_api.close_table();
+ }
+
if (!rule_api.empty())
{
data_api.print_local_variables(out);
#include "conversion_defines.h"
#include "data/dt_data.h"
#include "data/dt_rule_api.h"
+#include "data/dt_state_api.h"
#include "data/dt_table_api.h"
#include "helpers/util_binder.h"
inline RuleApi& get_rule_api()
{ return rule_api; }
+ inline StateApi& get_state_api()
+ { return state_api; }
+
bool added_ftp_data() const
{ return ftp_data_is_added; }
TableApi table_api;
RuleApi rule_api;
+
+ StateApi state_api;
+
std::vector<std::shared_ptr<Binder>> binders;
// the current parsing state.
table_api.open_table("detection");
table_api.add_option("global_rule_state", true);
table_api.close_table();
- table_api.open_table("rule_state");
- table_api.close_table();
}
string gid;
if ( retval )
{
- string key = gid + ":" + sid;
- table_api.open_associative_table("rule_state", key.c_str());
+ state_api.create_state();
+ state_api.add_option("gid", gid);
+ state_api.add_option("sid", sid);
if ( !enable.empty() )
{
- table_api.add_diff_option_comment("enabled/disabled", "enable");
- table_api.add_option("enable", enable);
+ state_api.add_option("enable", enable);
+ state_api.add_comment("option change: 'enabled/disabled' --> 'enable'");
}
if ( !action.empty() )
if ( action == "sdrop" )
{
action = "drop";
- table_api.add_diff_option_comment("sdrop", "drop");
+ state_api.add_comment("action change: 'sdrop' --> 'drop'");
}
- table_api.add_option("action", action);
+ state_api.set_action(action);
}
-
- table_api.close_table();
}
return retval;