* stream5_tcp: prune_log_max deleted; to be replaced with histogram
* stream5_tcp: max_active_responses, min_response_seconds moved to
active.max_responses, min_interval
-* ips policies support snort variables (_PATH, _PORT, _NET, _SERVER),
- ips = { variables = { var1 = expr1, var2 = expr2, ... } }
+* ips policies support snort variables configured based on type,
+ ips = { variables = { nets = { var1 = expr1, ... }, paths = { var2 = expr2, ... }, ports = { var3 = expr3, ... } } }
=== Rules
---------------------------------------------------------------------------
default_variables = {
- RULE_PATH = RULE_PATH,
- BUILTIN_RULE_PATH = BUILTIN_RULE_PATH,
- PLUGIN_RULE_PATH = PLUGIN_RULE_PATH,
- WHITE_LIST_PATH = WHITE_LIST_PATH,
- BLACK_LIST_PATH = BLACK_LIST_PATH,
-
- HOME_NET = HOME_NET,
- EXTERNAL_NET = EXTERNAL_NET,
- DNS_SERVERS = DNS_SERVERS,
- FTP_SERVERS = FTP_SERVERS,
- HTTP_SERVERS = HTTP_SERVERS,
- SIP_SERVERS = SIP_SERVERS,
- SMTP_SERVERS = SMTP_SERVERS,
- SQL_SERVERS = SQL_SERVERS,
- SSH_SERVERS = SSH_SERVERS,
- TELNET_SERVERS = TELNET_SERVERS,
-
- FTP_PORTS = FTP_PORTS,
- HTTP_PORTS = HTTP_PORTS,
- MAIL_PORTS = MAIL_PORTS,
- ORACLE_PORTS = ORACLE_PORTS,
- SIP_PORTS = SIP_PORTS,
- SSH_PORTS = SSH_PORTS,
- FILE_DATA_PORTS = FILE_DATA_PORTS,
+ nets = {
+ HOME_NET = HOME_NET,
+ EXTERNAL_NET = EXTERNAL_NET,
+ DNS_SERVERS = DNS_SERVERS,
+ FTP_SERVERS = FTP_SERVERS,
+ HTTP_SERVERS = HTTP_SERVERS,
+ SIP_SERVERS = SIP_SERVERS,
+ SMTP_SERVERS = SMTP_SERVERS,
+ SQL_SERVERS = SQL_SERVERS,
+ SSH_SERVERS = SSH_SERVERS,
+ TELNET_SERVERS = TELNET_SERVERS,
+ },
+ paths = {
+ RULE_PATH = RULE_PATH,
+ BUILTIN_RULE_PATH = BUILTIN_RULE_PATH,
+ PLUGIN_RULE_PATH = PLUGIN_RULE_PATH,
+ WHITE_LIST_PATH = WHITE_LIST_PATH,
+ BLACK_LIST_PATH = BLACK_LIST_PATH,
+ },
+ ports = {
+ FTP_PORTS = FTP_PORTS,
+ HTTP_PORTS = HTTP_PORTS,
+ MAIL_PORTS = MAIL_PORTS,
+ ORACLE_PORTS = ORACLE_PORTS,
+ SIP_PORTS = SIP_PORTS,
+ SSH_PORTS = SSH_PORTS,
+ FILE_DATA_PORTS = FILE_DATA_PORTS,
+ }
}
---------------------------------------------------------------------------
// Ips policy module
//-------------------------------------------------------------------------
-static void set_var(SnortConfig* sc, const char* fqn, Value& v)
+static const char* get_var_name(const char* fqn)
{
const char* ptr = strrchr(fqn, '.');
assert(ptr);
- SetVar(sc, ptr + 1, v.get_string());
+ return ptr + 1;
}
-static const Parameter variable_params[] =
+static const Parameter var_params[] =
{
{ "$var" , Parameter::PT_STRING, nullptr, nullptr,
"IPS policy variable" },
{ nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
};
+static const Parameter variable_params[] =
+{
+ { "nets" , Parameter::PT_TABLE, var_params, nullptr,
+ "net variables" },
+
+ { "paths" , Parameter::PT_TABLE, var_params, nullptr,
+ "path variables" },
+
+ { "ports" , Parameter::PT_TABLE, var_params, nullptr,
+ "port variables" },
+
+ { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
+};
+
static const Parameter ips_params[] =
{
{ "default_rule_state", Parameter::PT_ENUM, "no | yes | inherit", "inherit",
{ return DETECT; }
};
-bool IpsModule::matches(const char* param, std::string& name)
-{
- if ( strcmp(param, "$var") )
- return false;
-
- if ( name.find("_PATH") != string::npos or
- name.find("_PORT") != string::npos or
- name.find("_NET") != string::npos or
- name.find("_SERVER") != string::npos )
- return true;
-
- return false;
-}
+bool IpsModule::matches(const char*, std::string&)
+{ return true; }
bool IpsModule::set(const char* fqn, Value& v, SnortConfig* sc)
{
}
#endif
- else if ( strstr(fqn, "variables") )
- set_var(sc, fqn, v);
+ // FIXIT-M should only need one table with dynamically typed vars
+ else if ( strstr(fqn, "variables.nets.") )
+ ParseIpVar(get_var_name(fqn), v.get_string());
+
+ else if ( strstr(fqn, "variables.paths.") )
+ ParsePathVar(get_var_name(fqn), v.get_string());
+
+ else if ( strstr(fqn, "variables.ports.") )
+ ParsePortVar(get_var_name(fqn), v.get_string());
else
return false;
if (eth_dst )
snort_free(eth_dst);
- if ( var_list )
- FreeVarList(var_list);
-
if ( fast_pattern_config &&
(!snort_conf || this == snort_conf ||
(fast_pattern_config->get_search_api() !=
remote_control_socket = cmd_line->remote_control_socket;
#endif
- // config file vars are stored differently
- // FIXIT-M should cmd_line use the same var list / table?
- var_list = nullptr;
-
assert(!state);
num_slots = offload_threads + ThreadConfig::get_instance_max();
state = new std::vector<void*>[num_slots];
struct SFDAQConfig;
struct SoRules;
struct ThresholdConfig;
-struct VarNode;
namespace snort
{
XHash* rtn_hash_table = nullptr;
PolicyMap* policy_map = nullptr;
- VarNode* var_list = nullptr;
std::string tweaks;
DataBus* global_dbus = nullptr;
{ "-r", Parameter::PT_STRING, nullptr, nullptr,
"<pcap>... (same as --pcap-list)" },
- { "-S", Parameter::PT_STRING, nullptr, nullptr,
- "<x=v> set config variable x equal to value v" },
-
{ "-s", Parameter::PT_INT, "68:65535", "1518",
"<snap> (same as --snaplen); default is 1518" },
sc->run_flags |= RUN_FLAG__READ;
Trough::add_source(Trough::SOURCE_LIST, v.get_string());
}
- else if ( v.is("-S") )
- config_set_var(sc, v.get_string());
else if ( v.is("-s") or v.is("--snaplen") )
sc->daq_config->set_mru_size(v.get_uint16());
#include "main/snort_config.h"
#include "parser/parse_conf.h"
#include "parser/parser.h"
-#include "parser/vars.h"
#include "profiler/profiler.h"
#include "utils/util.h"
void parse_include(SnortConfig* sc, const char* arg)
{
assert(arg);
- arg = ExpandVars(sc, arg);
+ arg = ExpandVars(arg);
std::string file = !rules_file_depth ? get_ips_policy()->includer : get_parse_file();
const char* code = get_config_file(arg, file);
pop_parse_location();
}
-// FIXIT-M should only need one table with dynamically typed vars
-//
-// FIXIT-M this is a hack to tell vars by naming convention; with one table
-// this is obviated but if multiple tables are kept might want to change
-// these to a module with parameters
-void SetVar(snort::SnortConfig* sc, const char* name, const char* value)
-{
- if ( strstr(name, "_PATH") )
- AddVarToTable(sc, name, value);
-
- else if ( strstr(name, "_PORT") )
- PortVarDefine(sc, name, value);
-
- else if ( strstr(name, "_NET") )
- ParseIpVar(sc, name, value);
-
- else if ( strstr(name, "_SERVER") )
- ParseIpVar(sc, name, value);
-}
-
-void ParseIpVar(SnortConfig* sc, const char* var, const char* val)
+void ParseIpVar(const char* var, const char* value)
{
int ret;
IpsPolicy* p = get_ips_policy(); // FIXIT-M double check, see below
- DisallowCrossTableDuplicateVars(sc, var, VAR_TYPE__IPVAR);
+ DisallowCrossTableDuplicateVars(var, VAR_TYPE__IPVAR);
- if ((ret = sfvt_define(p->ip_vartable, var, val)) != SFIP_SUCCESS)
+ if ((ret = sfvt_define(p->ip_vartable, var, value)) != SFIP_SUCCESS)
{
switch (ret)
{
case SFIP_ARG_ERR:
- ParseError("the following is not allowed: %s.", val);
+ ParseError("the following is not allowed: %s.", value);
return;
case SFIP_DUPLICATE:
return;
default:
- ParseError("failed to parse the IP address: %s.", val);
+ ParseError("failed to parse the IP address: %s.", value);
return;
}
}
void parse_rules_file(snort::SnortConfig*, const char* fname);
void parse_rules_string(snort::SnortConfig*, const char* str);
-void SetVar(snort::SnortConfig*, const char* name, const char* value);
-void ParseIpVar(snort::SnortConfig*, const char* name, const char* s);
+void ParseIpVar(const char* name, const char* value);
void parse_include(snort::SnortConfig*, const char*);
void add_service_to_otn(snort::SnortConfig*, OptTreeNode*, const char*);
const char* name = port_str + 1;
/* look it up in the port var table */
- portobject = PortVarTableFind(pvt, name);
+ portobject = PortVarTableFind(pvt, name, true);
if ( !portobject )
ParseAbort("***PortVar Lookup failed on '%s'.", port_str);
sc->tweaks = boot_conf->tweaks;
sc->dump_config_type = boot_conf->dump_config_type;
- VarNode* tmp = boot_conf->var_list;
-
if ( !fname )
fname = get_snort_conf();
sc->rate_filter_config = RateFilter_ConfigNew();
sc->detection_filter_config = DetectionFilterConfigNew();
- /* Add command line defined variables - duplicates will already
- * have been resolved */
- while (tmp != nullptr)
- {
- AddVarToTable(sc, tmp->name, tmp->value);
- tmp = tmp->next;
- }
-
// get overrides from cmd line
Shell* sh = boot_conf->policy_map->get_shell();
sc->policy_map->get_shell()->set_overrides(sh);
using namespace snort;
-//-------------------------------------------------------------------------
-// var node stuff
-//-------------------------------------------------------------------------
-
-void config_set_var(SnortConfig* sc, const char* val)
-{
- {
- const char* equal_ptr = strchr(val, '=');
- VarNode* node;
-
- if (equal_ptr == nullptr)
- {
- ParseError("Format for command line variable definitions "
- "is:\n -S var=value\n");
- return;
- }
-
- /* Save these and parse when snort conf is parsed so
- * they can be added to the snort conf configuration */
- node = (VarNode*)snort_calloc(sizeof(VarNode));
-
- /* Make sure it's not already in the list */
- if (sc->var_list != nullptr)
- {
- VarNode* tmp = sc->var_list;
-
- while (tmp != nullptr)
- {
- if (strncasecmp(tmp->name, val, equal_ptr - val) == 0)
- {
- ParseError("Duplicate variable name: %s.", tmp->name);
- snort_free(node);
- return;
- }
- tmp = tmp->next;
- }
- }
-
- node->name = snort_strndup(val, equal_ptr - val);
- node->value = snort_strdup(equal_ptr + 1);
- node->line = snort_strdup(val);
- node->next = sc->var_list;
- sc->var_list = node;
-
- /* Put line in a parser parsable form - we know the
- * equals is already there */
- *strchr(node->line, '=') = ' ';
- }
-}
-
-void FreeVarList(VarNode* head)
-{
- while (head != nullptr)
- {
- VarNode* tmp = head;
-
- head = head->next;
-
- if (tmp->name != nullptr)
- snort_free(tmp->name);
-
- if (tmp->value != nullptr)
- snort_free(tmp->value);
-
- if (tmp->line != nullptr)
- snort_free(tmp->line);
-
- snort_free(tmp);
- }
-}
-
//-------------------------------------------------------------------------
// var table stuff
//-------------------------------------------------------------------------
-/*
- * PortVarDefine
- *
- * name - portlist name, i.e. http, smtp, ...
- * s - port number, port range, or a list of numbers/ranges in brackets
- *
- * examples:
- * portvar http [80,8080,8138,8700:8800,!8711]
- * portvar http $http_basic
- */
-int PortVarDefine(SnortConfig* sc, const char* name, const char* s)
+void ParsePortVar(const char* name, const char* value)
{
PortObject* po;
POParser pop;
int rstat;
PortVarTable* portVarTable = get_ips_policy()->portVarTable;
- DisallowCrossTableDuplicateVars(sc, name, VAR_TYPE__PORTVAR);
+ DisallowCrossTableDuplicateVars(name, VAR_TYPE__PORTVAR);
- if ( SnortStrcasestr(s,strlen(s),"any") ) /* this allows 'any' or '[any]' */
+ if ( SnortStrcasestr(value,strlen(value),"any") ) /* this allows 'any' or '[any]' */
{
- if (strstr(s,"!"))
+ if (strstr(value,"!"))
{
- ParseError("illegal use of negation and 'any': %s.", s);
+ ParseError("illegal use of negation and 'any': %s.", value);
}
po = PortObjectNew();
else
{
/* Parse the Port List info into a PortObject */
- po = PortObjectParseString(portVarTable, &pop, name, s, 0);
+ po = PortObjectParseString(portVarTable, &pop, name, value, 0);
if (!po)
{
const char* errstr = PortObjectParseError(&pop);
ParseAbort("PortVar Parse error: (pos=%d,error=%s)\n>>%s\n>>%*s.",
- pop.pos,errstr,s,pop.pos,"^");
+ pop.pos,errstr,value,pop.pos,"^");
}
}
ParseWarning(WARN_VARS, "PortVar '%s', already defined.", po->name);
PortObjectFree(po);
}
-
- return 0;
}
-/****************************************************************************
- *
- * Function: VarAlloc()
- *
- * Purpose: allocates memory for a variable
- *
- * Arguments: none
- *
- * Returns: pointer to new VarEntry
- *
- ***************************************************************************/
VarEntry* VarAlloc()
{
VarEntry* pve;
return( pve);
}
-/****************************************************************************
- *
- * Function: VarIsIpAddr(char *, char *)
- *
- * Purpose: Checks if a var is an IP address. Necessary since moving forward
- * we want all IP addresses handled by the IP variable table.
- * If a list is given, this checks each value.
- *
- * Arguments: value => the string to check
- *
- * Returns: 1 if IP address, 0 otherwise
- *
- ***************************************************************************/
int VarIsIpAddr(vartable_t* ip_vartable, const char* value)
{
const char* tmp;
return 0;
}
-/****************************************************************************
- *
- * Function: CheckBrackets(char *)
- *
- * Purpose: Check that the brackets match up in a string that
- * represents a list.
- *
- * Arguments: value => the string to check
- *
- * Returns: 1 if the brackets match correctly, 0 otherwise
- *
- ***************************************************************************/
static int CheckBrackets(char* value)
{
int num_brackets = 0;
return 1;
}
-/****************************************************************************
- *
- * Function: VarIsIpList(vartable_t *, char*)
- *
- * Purpose: Checks if a var is a list of IP addresses.
- *
- * Arguments: value => the string to check
- *
- * Returns: 1 if each item is an IP address, 0 otherwise
- *
- ***************************************************************************/
int VarIsIpList(vartable_t* ip_vartable, const char* value)
{
char* copy, * item;
return item_is_ip;
}
-/****************************************************************************
- *
- * Function: DisallowCrossTableDuplicateVars(char *, int)
- *
- * Purpose: ParseErrors if the a variable name is redefined across variable
- * types. Enforcing this mutual exclusion prevents the
- * catastrophe where the variable lookup fall-through (see VarSearch)
- * finds an unintended variable from the wrong table. Note: VarSearch
- * is only necessary for ExpandVars.
- *
- * Arguments: name => The name of the variable
- * var_type => The type of the variable that is about to be defined.
- * The corresponding variable table will not be searched.
- *
- * Returns: void function
- *
- ***************************************************************************/
-void DisallowCrossTableDuplicateVars(
- SnortConfig*, const char* name, VarType var_type)
+void DisallowCrossTableDuplicateVars(const char* name, VarType var_type)
{
IpsPolicy* dp = get_ips_policy();
VarEntry* var_table = dp->var_table;
vartable_t* ip_vartable = dp->ip_vartable;
VarEntry* p = var_table;
- /* If this is a faked Portvar, treat as a portvar */
- if ((var_type == VAR_TYPE__DEFAULT) &&
- (strstr(name, "_PORT") || strstr(name, "PORT_")))
- {
- var_type = VAR_TYPE__PORTVAR;
- }
-
switch (var_type)
{
case VAR_TYPE__DEFAULT:
}
}
-/****************************************************************************
- *
- * Function: VarDefine(char *, char *)
- *
- * Purpose: define the contents of a variable
- *
- * Arguments: name => the name of the variable
- * value => the contents of the variable
- *
- * Returns: void function
- *
- ***************************************************************************/
-VarEntry* VarDefine(
- SnortConfig* sc, const char* name, const char* value)
+void ParsePathVar(const char* name, const char* value)
{
- IpsPolicy* dp = get_ips_policy();
- VarEntry* var_table = dp->var_table;
- vartable_t* ip_vartable = dp->ip_vartable;
- VarEntry* p;
- uint32_t var_id = 0;
-
if (value == nullptr)
{
ParseAbort("bad value in variable definition. Make sure you don't "
"have a '$' in the var name.");
}
- if (VarIsIpList(ip_vartable, value))
- {
- SfIpRet ret;
-
- if (ip_vartable == nullptr)
- return nullptr;
-
- /* Verify a variable by this name is not already used as either a
- * portvar or regular var. Enforcing this mutual exclusion prevents the
- * catastrophe where the variable lookup fall-through (see VarSearch)
- * finds an unintended variable from the wrong table. Note: VarSearch
- * is only necessary for ExpandVars. */
- DisallowCrossTableDuplicateVars(sc, name, VAR_TYPE__IPVAR);
-
- if ((ret = sfvt_define(ip_vartable, name, value)) != SFIP_SUCCESS)
- {
- switch (ret)
- {
- case SFIP_ARG_ERR:
- ParseAbort("the following is not allowed: %s.", value);
-
- case SFIP_DUPLICATE:
- ParseWarning(WARN_VARS, "Var '%s' redefined.", name);
- break;
-
- case SFIP_CONFLICT:
- ParseAbort("negated IP ranges that are more general than "
- "non-negated ranges are not allowed. Consider "
- "inverting the logic in %s.", name);
-
- case SFIP_NOT_ANY:
- ParseAbort("!any is not allowed in %s", name);
-
- default:
- ParseAbort("failed to parse the IP address: %s.", value);
- }
- }
- return nullptr;
- }
- /* Check if this is a variable that stores an IP */
- else if (*value == '$')
- {
- if ( sfvt_lookup_var(ip_vartable, value) )
- {
- sfvt_define(ip_vartable, name, value);
- return nullptr;
- }
- }
+ IpsPolicy* dp = get_ips_policy();
+ VarEntry* var_table = dp->var_table;
+ uint32_t var_id = 0;
/* Check to see if this variable is just being aliased */
if (var_table != nullptr)
while (tmp != var_table);
}
- value = ExpandVars(sc, value);
+ value = ExpandVars(value);
if (!value)
{
ParseAbort("could not expand var('%s').", name);
}
- DisallowCrossTableDuplicateVars(sc, name, VAR_TYPE__DEFAULT);
+ DisallowCrossTableDuplicateVars(name, VAR_TYPE__DEFAULT);
if (var_table == nullptr)
{
- p = VarAlloc();
+ VarEntry* p = VarAlloc();
p->name = snort_strdup(name);
p->value = snort_strdup(value);
p->id = dp->var_id++;
- return p;
+ return;
}
/* See if an existing variable is being redefined */
- p = var_table;
+ VarEntry* p = var_table;
do
{
p->value = snort_strdup(value);
ParseWarning(WARN_VARS, "Var '%s' redefined\n", p->name);
- return p;
+ return;
}
p = p->next;
else
p->id = var_id;
- return p;
+ return;
}
void DeleteVars(VarEntry* var_table)
}
}
-const char* VarSearch(SnortConfig* sc, const char* name)
+const char* VarSearch(const char* name)
{
IpsPolicy* dp = get_ips_policy();
VarEntry* var_table = dp->var_table;
sfip_var_t* ipvar;
if ((ipvar = sfvt_lookup_var(ip_vartable, name)) != nullptr)
- return ExpandVars(sc, ipvar->value);
+ return ExpandVars(ipvar->value);
if (PortVarTableFind(portVarTable, name))
return name;
// The expanded string. Note that the string is returned in a
// static variable and most likely needs to be string dup'ed.
-const char* ExpandVars(SnortConfig* sc, const char* string)
+const char* ExpandVars(const char* string)
{
static char estring[ 65536 ]; // FIXIT-L convert this foo to a std::string
memset((char*)varbuffer, 0, sizeof(varbuffer));
- varcontents = VarSearch(sc, varname);
+ varcontents = VarSearch(varname);
switch (varmodifier)
{
return estring;
}
-void AddVarToTable(SnortConfig* sc, const char* name, const char* value)
-{
- //TODO: snort.cfg and rules should use PortVar instead ...this allows compatibility for now.
- if (strstr(name, "_PORT") || strstr(name, "PORT_"))
- {
- PortVarDefine(sc, name, value);
- }
- else
- {
- VarDefine(sc, name, value);
- }
-}
-
-//--------------------------------------------------------------------------
-// unit tests
-//--------------------------------------------------------------------------
-
-#ifdef UNIT_TEST
-// FIXIT-L these var tests are inadequate
-
-TEST_CASE("config_set_var-success", "[vars]")
-{
- SnortConfig sc;
- sc.var_list = nullptr;
- config_set_var(&sc, "A=B");
-
- REQUIRE(sc.var_list->name[0] == 'A');
- REQUIRE(sc.var_list->value[0] == 'B');
-}
-
-TEST_CASE("config_set_var-existing-success", "[vars]")
-{
- SnortConfig sc;
-
- config_set_var(&sc, "C=D");
- config_set_var(&sc, "A=B");
-
- REQUIRE(sc.var_list->name[0] == 'A');
- REQUIRE(sc.var_list->value[0] == 'B');
-}
-
-// FIXIT-L missing CHECKs / REQUIREs
-TEST_CASE("config_set_var-duplicate-error", "[vars]")
-{
- SnortConfig sc;
- config_set_var(&sc, "A=B");
-}
-
-TEST_CASE("config_set_var-no_equals_sign-error", "[vars]")
-{
- SnortConfig sc;
- config_set_var(&sc, "A");
-}
-
-#endif
-
struct SnortConfig;
}
-//-------------------------------------------------------------------------
-// var node stuff
-//-------------------------------------------------------------------------
-
-struct VarNode
-{
- char* name;
- char* value;
- char* line;
- VarNode* next;
-};
-
-void config_set_var(snort::SnortConfig*, const char*);
-void FreeVarList(VarNode*);
-
//-------------------------------------------------------------------------
// var table stuff
//-------------------------------------------------------------------------
VarEntry* next;
};
-VarEntry* VarDefine(snort::SnortConfig*, const char* name, const char* value);
-int PortVarDefine(snort::SnortConfig*, const char* name, const char* s);
+void ParsePathVar(const char* name, const char* value);
+void ParsePortVar(const char* name, const char* value);
VarEntry* VarAlloc();
void DeleteVars(VarEntry* var_table);
-void AddVarToTable(snort::SnortConfig*, const char*, const char*);
enum VarType
{
int VarIsIpAddr(vartable_t* ip_vartable, const char* value);
int VarIsIpList(vartable_t* ip_vartable, const char* value);
-void DisallowCrossTableDuplicateVars(snort::SnortConfig*, const char* name, VarType var_type);
+void DisallowCrossTableDuplicateVars(const char* name, VarType var_type);
-const char* VarSearch(snort::SnortConfig*, const char* name);
-const char* ExpandVars(snort::SnortConfig*, const char* string);
+const char* VarSearch(const char* name);
+const char* ExpandVars(const char* string);
#endif
return -1;
}
-PortObject* PortVarTableFind(PortVarTable* h, const char* name)
+PortObject* PortVarTableFind(PortVarTable* h, const char* name, bool add_if_not_found)
{
if (!h || !name)
return nullptr;
PortObject* po = (PortObject*)h->find(name);
- if ( !po and SnortConfig::get_conf()->dump_rule_info() and strstr(name, "PORT") )
+ if ( !po and SnortConfig::get_conf()->dump_rule_info() and add_if_not_found )
{
po = PortObjectNew();
po->name = snort_strdup(name);
PortVarTable* PortVarTableCreate();
int PortVarTableFree(PortVarTable* pvt);
int PortVarTableAdd(PortVarTable* pvt, PortObject* po);
-PortObject* PortVarTableFind(PortVarTable* pvt, const char* name);
+PortObject* PortVarTableFind(PortVarTable* pvt, const char* name, bool add_if_not_found = false);
#endif
std::ostream& operator<<(std::ostream& out, const Variable& var)
{
- std::string whitespace;
+ std::string whitespace =
+ ( var.print_whitespace && var.depth ) ? std::string(var.depth * 4, ' ') : "";
+
bool first_var = true;
std::size_t count = 0;
- for (int i = 0; i < var.depth; i++)
- whitespace += " ";
-
- out << (var.print_whitespace ? whitespace : "") << var.name << " = ";
+ if ( !var.comment.empty() )
+ out << whitespace << "-- " << var.comment << "\n";
- if ( var.print_whitespace )
- count += whitespace.size();
+ out << whitespace << var.name << " = ";
+ count += whitespace.size();
count += var.name.size() + 3;
if ( var.print_whitespace )
Variable(const std::string& name, int depth = 0);
virtual ~Variable();
- inline const std::string& get_name() { return name; }
+ inline const std::string& get_name() const { return name; }
std::string get_value(DataApi*);
bool add_value(std::string);
void set_value(const std::string&, bool quoted);
+ void set_comment(const std::string& c)
+ { comment = c; }
void set_print_whitespace(bool w)
{ print_whitespace = w; }
std::vector<VarData*> vars;
std::string name;
+ std::string comment;
int depth;
bool print_whitespace = true;
static const std::size_t max_line_length = 77; // leave room for additional text
std::string DataApi::translate_variable(const std::string& var_name)
{
- for (auto v : vars)
- if (var_name == v->get_name())
- return v->get_value(this);
+ auto v = find_var(var_name);
+ if ( v != vars.end() )
+ return (*v)->get_value(this);
return std::string();
}
return error_string;
}
+var_it DataApi::find_var(const std::string& name) const
+{
+ return std::find_if(vars.begin(), vars.end(),
+ [&](const Variable* v){ return v->get_name() == name; });
+}
+
void DataApi::error(const std::string& error)
{
errors->add_text(error);
errors->add_text("^^^^ unknown_syntax=" + unknown_option);
}
-static bool is_local_variable(const std::string& name)
+void DataApi::set_variable(const std::string& name, const std::string& value, bool quoted)
{
- return name.find("_PATH") != std::string::npos
- || name.find("_PORT") != std::string::npos
- || name.find("_NET") != std::string::npos
- || name.find("_SERVER") != std::string::npos;
+ Variable* var = new Variable(name);
+ vars.push_back(var);
+ var->set_value(value, quoted);
}
-void DataApi::set_variable(const std::string& name, const std::string& value, bool quoted)
+bool DataApi::add_net_variable(const std::string& name, const std::string& value)
{
- if (is_local_variable(name))
- local_vars.push_back(name);
+ auto v = find_var(name);
+ if ( v != vars.end() )
+ return (*v)->add_value(value);
+
+ net_vars.push_back(name);
Variable* var = new Variable(name);
vars.push_back(var);
- var->set_value(value, quoted);
+ return var->add_value(value);
}
-bool DataApi::add_variable(const std::string& name, const std::string& value)
+bool DataApi::add_path_variable(const std::string& name, const std::string& value)
{
- for (auto v : vars)
- if (name == v->get_name())
- return v->add_value(value);
+ auto v = find_var(name);
+ if ( v != vars.end() )
+ return (*v)->add_value(value);
+
+ Variable* var = new Variable(name);
+
+ // Since a user may specify an IP address, port or path variable with 'var' and it's valid for
+ // Snort2 we attempt to detect type based on the suffix
+ if ( name.find("PORT_") != std::string::npos || name.find("_PORT") != std::string::npos )
+ {
+ var->set_comment("treated as portvar");
+ port_vars.push_back(name);
+ }
+ else if ( name.find("NET_") != std::string::npos || name.find("_NET") != std::string::npos
+ || name.find("SERVER_") != std::string::npos || name.find("_SERVER") != std::string::npos )
+ {
+ var->set_comment("treated as ipvar");
+ net_vars.push_back(name);
+ }
+ else if ( name.find("PATH_") != std::string::npos || name.find("_PATH") != std::string::npos )
+ {
+ var->set_comment("treated as path var");
+ path_vars.push_back(name);
+ }
+ else
+ var->set_comment("treated as global var");
- if (is_local_variable(name))
- local_vars.push_back(name);
+ vars.push_back(var);
+ return var->add_value(value);
+}
+
+bool DataApi::add_port_variable(const std::string& name, const std::string& value)
+{
+ auto v = find_var(name);
+ if ( v != vars.end() )
+ return (*v)->add_value(value);
+
+ port_vars.push_back(name);
Variable* var = new Variable(name);
vars.push_back(var);
out << (*unsupported) << "\n";
}
+static void print_vars(std::ostream& out, const std::string& name,
+ const std::vector<std::string>& vars)
+{
+ if ( vars.empty() )
+ return;
+
+ out << " " << name << " =\n {\n";
+ for ( const auto& v : vars )
+ out << " " << v << " = " << v << ",\n";
+ out << " },\n";
+}
+
void DataApi::print_local_variables(std::ostream& out) const
{
- if (local_vars.empty())
+ if ( !has_local_vars() )
return;
out << "local_variables =\n{\n";
- for (const auto& v : local_vars)
- out << " " << v << " = " << v << ",\n";
+ print_vars(out, "nets", net_vars);
+ print_vars(out, "paths", path_vars);
+ print_vars(out, "ports", port_vars);
out << "}\n\n";
}
class Comments;
class DataApi;
+using var_it = std::vector<Variable*>::const_iterator;
+
class DataApi
{
public:
{ return vars.empty() && includes.empty(); }
bool has_local_vars() const
- { return !local_vars.empty(); }
+ { return !net_vars.empty() or !path_vars.empty() or !port_vars.empty(); }
// functions specifically useful when parsing includes.
// allows for easy swapping of data. These two functions
// add a variable to this file
void set_variable(const std::string& name, const std::string& value, bool quoted);
- bool add_variable(const std::string& name, const std::string& value);
+ bool add_net_variable(const std::string& name, const std::string& value);
+ bool add_path_variable(const std::string& name, const std::string& value);
+ bool add_port_variable(const std::string& name, const std::string& value);
// add a Snort style include file
bool add_include_file(const std::string& name);
// add a 'comment' to the Lua file. should ONLY be used when
void set_current_line(unsigned line)
{ current_line = line; }
+private:
+ std::string get_file_line();
+ var_it find_var(const std::string& name) const;
+
private:
enum class PrintMode
{
std::vector<Variable*> vars;
std::vector<Include*> includes;
- std::vector<std::string> local_vars;
+ std::vector<std::string> net_vars;
+ std::vector<std::string> path_vars;
+ std::vector<std::string> port_vars;
Comments* comments;
Comments* errors;
Comments* unsupported;
bool curr_data_bad = false; // keep track whether current 'conversion' is already bad
const std::string* current_file = nullptr;
unsigned current_line = 0;
-
- std::string get_file_line();
};
#endif
#include "helpers/converter.h"
#include "helpers/s2l_util.h"
-namespace keywords
-{
-namespace
-{
-class Var : public ConversionState
-{
-public:
- Var(Converter& c) : ConversionState(c) { }
- bool convert(std::istringstream& data) override;
-};
-} // namespace
-
-bool Var::convert(std::istringstream& data_stream)
+static bool var_convert(std::istringstream& data_stream, DataApi& data_api,
+ bool (*add_var)(const std::string&, const std::string&, DataApi&))
{
std::string ports; // cv.print_line(data_stream);
std::string keyword;
util::split(ports, ',', port_list);
for (const std::string& elem : port_list)
- retval = data_api.add_variable(keyword, elem) && retval;
+ retval = add_var(keyword, elem, data_api) && retval;
return retval;
}
else
{
- return data_api.add_variable(keyword, ports);
+ return add_var(keyword, ports, data_api);
}
}
+namespace keywords
+{
+namespace
+{
+class NetVar : public ConversionState
+{
+public:
+ NetVar(Converter& c) : ConversionState(c) { }
+ bool convert(std::istringstream& data_stream) override
+ {
+ return var_convert(data_stream, data_api,
+ [](const std::string& name, const std::string& net, DataApi& d_api)
+ { return d_api.add_net_variable(name, net); });
+ }
+};
+
+class PathVar : public ConversionState
+{
+public:
+ PathVar(Converter& c) : ConversionState(c) { }
+ bool convert(std::istringstream& data_stream) override
+ {
+ return var_convert(data_stream, data_api,
+ [](const std::string& name, const std::string& path, DataApi& d_api)
+ { return d_api.add_path_variable(name, path); });
+ }
+};
+
+class PortVar : public ConversionState
+{
+public:
+ PortVar(Converter& c) : ConversionState(c) { }
+ bool convert(std::istringstream& data_stream) override
+ {
+ return var_convert(data_stream, data_api,
+ [](const std::string& name, const std::string& port, DataApi& d_api)
+ { return d_api.add_port_variable(name, port); });
+ }
+};
+} // namespace
+
/**************************
******* A P I ***********
**************************/
-static ConversionState* ctor(Converter& c)
-{ return new Var(c); }
+static ConversionState* ctor_net_var(Converter& c)
+{ return new NetVar(c); }
+
+static ConversionState* ctor_path_var(Converter& c)
+{ return new PathVar(c); }
+
+static ConversionState* ctor_port_var(Converter& c)
+{ return new PortVar(c); }
static const ConvertMap keyword_portvar =
{
"portvar",
- ctor,
+ ctor_port_var,
};
static const ConvertMap keyword_ipvar =
{
"ipvar",
- ctor,
+ ctor_net_var,
};
static const ConvertMap keyword_var =
{
"var",
- ctor,
+ ctor_path_var,
};
const ConvertMap* portvar_map = &keyword_portvar;