]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Merge pull request #2522 in SNORT/snort3 from ~OSERHIIE/snort3:custom_vars_wo_suffixe...
authorBhagya Tholpady (bbantwal) <bbantwal@cisco.com>
Tue, 27 Oct 2020 17:05:43 +0000 (17:05 +0000)
committerBhagya Tholpady (bbantwal) <bbantwal@cisco.com>
Tue, 27 Oct 2020 17:05:43 +0000 (17:05 +0000)
Squashed commit of the following:

commit 368ff259fb2f0e37e297dd82b46ce71a2bbfc1e2
Author: Oleksandr Serhiienko <oserhiie@cisco.com>
Date:   Thu Sep 24 19:48:37 2020 +0300

    ips: move IPS variables to sub-tables which designates type

        * main: snort supports ips.variables.nets/.paths/.ports tables to specify custom variables regardless suffixes (_PATH, _PORT, _NET and _SERVER)
        * lua: update default_variables with 'nets', 'paths' and 'ports' tables in snort_defaults.lua
        * managers, parser, ports: rid-off obsolete code for variables parsing relying on the suffixes
        * snort_module: remove support for -S option
        * tools: snort2lua converts custom variables into ips.variables.nets/.paths/.ports tables
        * doc: update upgrade/differences.txt

20 files changed:
doc/upgrade/differences.txt
lua/snort_defaults.lua
src/main/modules.cc
src/main/snort_config.cc
src/main/snort_config.h
src/main/snort_module.cc
src/managers/module_manager.cc
src/parser/parse_conf.cc
src/parser/parse_conf.h
src/parser/parse_rule.cc
src/parser/parser.cc
src/parser/vars.cc
src/parser/vars.h
src/ports/port_var_table.cc
src/ports/port_var_table.h
tools/snort2lua/data/data_types/dt_var.cc
tools/snort2lua/data/data_types/dt_var.h
tools/snort2lua/data/dt_data.cc
tools/snort2lua/data/dt_data.h
tools/snort2lua/keyword_states/kws_var.cc

index da955f8f45a84792650e01356798c743f028a980..ddafc21bdc0342bb8957bf94cb27a775629672f6 100644 (file)
@@ -141,8 +141,8 @@ Some things Snort++ can do today that Snort can not do as well:
 * 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
 
index 9fffe3b7a7bbba1c78b80e1b979f8625420146fc..9afdff06a26ebae9341a912c7c93814936d4b26b 100644 (file)
@@ -95,30 +95,34 @@ FILE_DATA_PORTS = HTTP_PORTS .. MAIL_PORTS
 ---------------------------------------------------------------------------
 
 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,
+    }
 }
 
 ---------------------------------------------------------------------------
index 62be9831f751289e90564195b67277c69b8fa68f..30687149428198a502221b0ba7c26a4d5a761fbe 100644 (file)
@@ -1168,14 +1168,14 @@ bool InspectionModule::set(const char*, Value& v, SnortConfig* sc)
 // 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" },
@@ -1183,6 +1183,20 @@ static const Parameter variable_params[] =
     { 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",
@@ -1238,19 +1252,8 @@ public:
     { 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)
 {
@@ -1297,8 +1300,15 @@ 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;
index aa4b9f2a8d7b81fa6e609efb0fc5d3799fdbde4f..163fd79bf031dfd5758b1a8f2a25ecbade7cd05f 100644 (file)
@@ -245,9 +245,6 @@ SnortConfig::~SnortConfig()
     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() !=
@@ -458,10 +455,6 @@ void SnortConfig::merge(SnortConfig* cmd_line)
         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];
index 3c8a85a782bdbce3d552e15f411ef3f1fe90703c..46b08714369df70d94a8af1ba5a7b769cb6b8e39 100644 (file)
@@ -157,7 +157,6 @@ struct RulePortTables;
 struct SFDAQConfig;
 struct SoRules;
 struct ThresholdConfig;
-struct VarNode;
 
 namespace snort
 {
@@ -393,7 +392,6 @@ public:
     XHash* rtn_hash_table = nullptr;
 
     PolicyMap* policy_map = nullptr;
-    VarNode* var_list = nullptr;
     std::string tweaks;
 
     DataBus* global_dbus = nullptr;
index 497fb306b2c012e490c1c1c87da8521f46a417d9..4ab163b630dbb40ffc3225051d08bcf48a5de19d 100644 (file)
@@ -267,9 +267,6 @@ static const Parameter s_params[] =
     { "-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" },
 
@@ -772,8 +769,6 @@ bool SnortModule::set(const char*, Value& v, SnortConfig* sc)
         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());
index e9d33e86082212d33fb428186a32a616915a1aa1..6c9175f97bb5a42027a99d9177fbf6148dd41cee 100644 (file)
@@ -44,7 +44,6 @@
 #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"
 
index af7f2a041cbd5247cae1fb6e222db9a94f4aac50..19f5540b7be38e59e9bc1e5f8214babb635fe6cd 100644 (file)
@@ -186,7 +186,7 @@ const char* get_config_file(const char* arg, std::string& file)
 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);
@@ -201,38 +201,18 @@ void parse_include(SnortConfig* sc, const char* arg)
     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:
@@ -250,7 +230,7 @@ void ParseIpVar(SnortConfig* sc, const char* var, const char* val)
             return;
 
         default:
-            ParseError("failed to parse the IP address: %s.", val);
+            ParseError("failed to parse the IP address: %s.", value);
             return;
         }
     }
index 065bab0c97342566f8cc2e175ea3fde45f458955..7f320f1b48352fcc811fcf3882836d1f6248cd85 100644 (file)
@@ -41,8 +41,7 @@ const char* get_config_file(const char* arg, std::string& file);
 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*);
index 2905fcfe0d302eede756f114e97f4c96a2411f9b..05aa3a8b62d9d3d81dfdd3da816724bb92ac44d8 100644 (file)
@@ -464,7 +464,7 @@ static PortObject* ParsePortListTcpUdpPort(
         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);
 
index 0d9138827c9d757c1d7cf1537babdf604050dea1..f469e4ab86c0c5bbac125d3dd0aece012befd4d1 100644 (file)
@@ -323,8 +323,6 @@ SnortConfig* ParseSnortConf(const SnortConfig* boot_conf, const char* fname, boo
     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();
 
@@ -341,14 +339,6 @@ SnortConfig* ParseSnortConf(const SnortConfig* boot_conf, const char* fname, boo
     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);
index 131a8f47a7368fea63fb92b45324dbed3b2c8463..0b6159e45e28e43ba1aa3612130c9c8bdfeea0d9 100644 (file)
 
 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();
@@ -145,12 +64,12 @@ int PortVarDefine(SnortConfig* sc, const char* name, const char* s)
     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,"^");
         }
     }
 
@@ -166,21 +85,8 @@ int PortVarDefine(SnortConfig* sc, const char* name, const char* s)
         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;
@@ -190,19 +96,6 @@ VarEntry* VarAlloc()
     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;
@@ -253,18 +146,6 @@ int VarIsIpAddr(vartable_t* ip_vartable, const char* value)
     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;
@@ -295,17 +176,6 @@ static int CheckBrackets(char* value)
     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;
@@ -338,25 +208,7 @@ int VarIsIpList(vartable_t* ip_vartable, const char* value)
     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;
@@ -364,13 +216,6 @@ void DisallowCrossTableDuplicateVars(
     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:
@@ -434,81 +279,17 @@ void DisallowCrossTableDuplicateVars(
     }
 }
 
-/****************************************************************************
- *
- * 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)
@@ -529,17 +310,17 @@ VarEntry* VarDefine(
         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);
 
@@ -550,11 +331,11 @@ VarEntry* VarDefine(
 
         p->id = dp->var_id++;
 
-        return p;
+        return;
     }
 
     /* See if an existing variable is being redefined */
-    p = var_table;
+    VarEntry* p = var_table;
 
     do
     {
@@ -565,7 +346,7 @@ VarEntry* VarDefine(
 
             p->value = snort_strdup(value);
             ParseWarning(WARN_VARS, "Var '%s' redefined\n", p->name);
-            return p;
+            return;
         }
 
         p = p->next;
@@ -585,7 +366,7 @@ VarEntry* VarDefine(
     else
         p->id = var_id;
 
-    return p;
+    return;
 }
 
 void DeleteVars(VarEntry* var_table)
@@ -610,7 +391,7 @@ 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;
@@ -619,7 +400,7 @@ const char* VarSearch(SnortConfig* sc, const char* name)
     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;
@@ -641,7 +422,7 @@ const char* VarSearch(SnortConfig* sc, const char* 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
 
@@ -727,7 +508,7 @@ const char* ExpandVars(SnortConfig* sc, const char* string)
 
                 memset((char*)varbuffer, 0, sizeof(varbuffer));
 
-                varcontents = VarSearch(sc, varname);
+                varcontents = VarSearch(varname);
 
                 switch (varmodifier)
                 {
@@ -773,59 +554,3 @@ const char* ExpandVars(SnortConfig* sc, const char* string)
     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
-
index 2d125c35cd1621e3be1c53ee861021ddd2c0ee0d..4b733f0cca8545981fcc63b3483b54a8c3fc2a40 100644 (file)
@@ -29,21 +29,6 @@ namespace snort
 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
 //-------------------------------------------------------------------------
@@ -61,12 +46,11 @@ struct VarEntry
     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
 {
@@ -77,10 +61,10 @@ 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
 
index 06dffaa3b97b350d79de841ed8375256222f2cf7..848ccf5890d4d557176d5648da28ebc2c81ba1ba 100644 (file)
@@ -86,14 +86,14 @@ int PortVarTableAdd(PortVarTable* h, PortObject* po)
     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);
index 7babca35d6bdd1d24e85adce3eb9480946951ee8..a2acc1d80a100d3a682f0af71cbd8ed69b1a6dd8 100644 (file)
@@ -41,7 +41,7 @@ typedef snort::GHash PortVarTable;
 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
 
index ee880bbfc5d8b6389860608ab5875faad758f49a..129d29c71a019aba608c3477e5f5c50f4365a9de 100644 (file)
@@ -140,18 +140,18 @@ static inline void print_newline(std::ostream& out,
 
 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 )
index 6c05f3e846ec7029d4cc777ebad6602a44d9ca01..0915cf7b748ccea2f00c388a0f6d26544c809a8b 100644 (file)
@@ -32,10 +32,12 @@ public:
     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; }
@@ -53,6 +55,7 @@ private:
 
     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
index 6818eef6571f6bc7f3ef85c0febc472ffa293417..0a33a6bb29f1ddcf7ee103d0461100cca29b9d08 100644 (file)
@@ -60,9 +60,9 @@ DataApi::~DataApi()
 
 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();
 }
@@ -242,6 +242,12 @@ std::string DataApi::get_file_line()
     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);
@@ -263,32 +269,66 @@ void DataApi::failed_conversion(const std::istringstream& stream, const std::str
         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);
@@ -355,14 +395,27 @@ void DataApi::print_unsupported(std::ostream& out) const
         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";
 }
 
index a6f3a2b0f224f67e7fa5d4e42f65b485c54c9c19..ca938185135dbd36b881779dd1459b1a940aba96 100644 (file)
@@ -50,6 +50,8 @@ class Variable;
 class Comments;
 class DataApi;
 
+using var_it = std::vector<Variable*>::const_iterator;
+
 class DataApi
 {
 public:
@@ -95,7 +97,7 @@ 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
@@ -109,7 +111,9 @@ public:
 
     // 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
@@ -130,6 +134,10 @@ public:
     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
     {
@@ -145,7 +153,9 @@ private:
 
     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;
@@ -153,8 +163,6 @@ private:
     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
index 54f4acb88d529a5dc83ea36ec01e26a7ba2f0ea6..ca7b1e76543c9e98e3a53111433ef67db07b6090 100644 (file)
 #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;
@@ -68,39 +57,86 @@ bool Var::convert(std::istringstream& data_stream)
         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;