]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Merge pull request #2329 in SNORT/snort3 from ~OSHUMEIK/snort3:policy_custom_variable...
authorBhagya Tholpady (bbantwal) <bbantwal@cisco.com>
Tue, 28 Jul 2020 15:43:37 +0000 (15:43 +0000)
committerBhagya Tholpady (bbantwal) <bbantwal@cisco.com>
Tue, 28 Jul 2020 15:43:37 +0000 (15:43 +0000)
Squashed commit of the following:

commit a0f0b195faee442a2ee63fec1e8bdf20e1b29966
Author: Oleksii Khomiakovskyi <okhomiak@cisco.com>
Date:   Mon Jul 6 17:23:23 2020 +0300

    ips: add support for variables with each ips policy

    Custom variables are for rules only.
    Snort2lua creates custom variables for each ips entry.

12 files changed:
doc/upgrade/differences.txt
lua/snort_defaults.lua
src/main/modules.cc
src/managers/module_manager.cc
src/parser/parse_conf.cc
src/parser/parse_conf.h
src/parser/parse_ip.cc
src/parser/vars.cc
src/sfip/sf_ipvar.cc
tools/snort2lua/data/dt_data.cc
tools/snort2lua/data/dt_data.h
tools/snort2lua/helpers/converter.cc

index c148e7f66f0e11e9dcda1846fb4a86168642264f..f267f771ea0ed85447361ee62220862ca95ee1f4 100644 (file)
@@ -141,6 +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, ... } }
 
 === Rules
 
index 5a41e12ac4dbf872466c1eba0dff743f939185c1..f956986991b98ad5e40e8705e75e95072f9d71f5 100644 (file)
@@ -34,7 +34,7 @@ BLACK_LIST_PATH = '../lists'
 -- default networks
 ---------------------------------------------------------------------------
 
--- List of DNS servers on your network 
+-- List of DNS servers on your network
 DNS_SERVERS = HOME_NET
 
 -- List of ftp servers on your network
@@ -49,7 +49,7 @@ SIP_SERVERS = HOME_NET
 -- List of SMTP servers on your network
 SMTP_SERVERS = HOME_NET
 
--- List of sql servers on your network 
+-- List of sql servers on your network
 SQL_SERVERS = HOME_NET
 
 -- List of ssh servers on your network
@@ -72,7 +72,7 @@ HTTP_PORTS =
     3702 4343 4848 5250 6988 7000 7001 7144 7145 7510 7777 7779 8000 8008
     8014 8028 8080 8085 8088 8090 8118 8123 8180 8181 8243 8280 8300 8800
     8888 8899 9000 9060 9080 9090 9091 9443 9999 11371 34443 34444 41080
-    50002 55555 
+    50002 55555
 ]]
 
 -- List of ports you run mail servers on
@@ -90,6 +90,37 @@ SSH_PORTS = ' 22'
 -- List of ports for file inspection
 FILE_DATA_PORTS = HTTP_PORTS .. MAIL_PORTS
 
+---------------------------------------------------------------------------
+-- default variables
+---------------------------------------------------------------------------
+
+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,
+}
+
 ---------------------------------------------------------------------------
 -- default ftp server
 ---------------------------------------------------------------------------
@@ -104,7 +135,7 @@ ftp_default_cmds =
     XSEM XSEN XSHA1 XSHA256
 ]]
 
-ftp_default_data_chan_cmds = 
+ftp_default_data_chan_cmds =
 [[
     PORT PASV LPRT LPSV EPRT EPSV
 ]]
@@ -114,28 +145,28 @@ ftp_default_data_xfer_cmds =
     RETR STOR STOU APPE LIST NLST
 ]]
 
-ftp_default_file_put_cmds = 
+ftp_default_file_put_cmds =
 [[
     STOR STOU
 ]]
 
-ftp_default_file_get_cmds = 
+ftp_default_file_get_cmds =
 [[
     RETR
 ]]
 
-ftp_default_login_cmds = 
+ftp_default_login_cmds =
 [[
     USER PASS
 ]]
 
-ftp_default_encr_cmds = 
+ftp_default_encr_cmds =
 [[
     AUTH
 ]]
 
-ftp_format_commands = 
-[[ 
+ftp_format_commands =
+[[
     ACCT ADAT ALLO APPE AUTH CEL CLNT CMD CONF CWD DELE ENC EPRT EPSV ESTP
     HELP LANG LIST LPRT MACB MAIL MDTM MIC MKD MLSD MLST MODE NLST OPTS
     PASS PBSZ PORT PROT REST RETR RMD RNFR RNTO SDUP SITE SIZE SMNT STAT
@@ -358,7 +389,7 @@ default_wizard =
     },
     hexes =
     {
-        { service = 'dnp3', proto = 'tcp', client_first = true, 
+        { service = 'dnp3', proto = 'tcp', client_first = true,
           to_server = { '|05 64|' }, to_client = { '|05 64|' } },
 
         { service = 'http2', proto = 'tcp', client_first = true,
@@ -1157,6 +1188,7 @@ default_whitelist =
     ip_med_sweep ip_med_dist ip_hi_proto ip_hi_decoy ip_hi_sweep
     ip_hi_dist icmp_low_sweep icmp_med_sweep icmp_hi_sweep
     default_hi_port_scan default_med_port_scan default_low_port_scan
+    default_variables
 ]]
 
 snort_whitelist_append(default_whitelist)
index b6732286734b3dcea994ebed63dae8c45c404c0a..4a463d4e6253d487d44b61d373b4f8a521d9279b 100644 (file)
@@ -51,6 +51,7 @@
 #include "parser/parse_conf.h"
 #include "parser/parse_ip.h"
 #include "parser/parser.h"
+#include "parser/vars.h"
 #include "payload_injector/payload_injector_module.h"
 #include "profiler/profiler.h"
 #include "search_engines/pat_stats.h"
@@ -1167,6 +1168,21 @@ bool InspectionModule::set(const char*, Value& v, SnortConfig* sc)
 // Ips policy module
 //-------------------------------------------------------------------------
 
+static void set_var(SnortConfig* sc, const char* fqn, Value& v)
+{
+    const char* ptr = strrchr(fqn, '.');
+    assert(ptr);
+    SetVar(sc, ptr + 1, v.get_string());
+}
+
+static const Parameter variable_params[] =
+{
+    { "$var" , Parameter::PT_STRING, nullptr, nullptr,
+      "IPS policy variable" },
+
+    { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
+};
+
 static const Parameter ips_params[] =
 {
     { "default_rule_state", Parameter::PT_ENUM, "no | yes | inherit", "inherit",
@@ -1202,6 +1218,9 @@ static const Parameter ips_params[] =
       "IPS policy uuid" },
 #endif
 
+    { "variables", Parameter::PT_TABLE, variable_params, nullptr,
+      "defines IPS policy variables" },
+
     { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
 };
 
@@ -1213,12 +1232,27 @@ class IpsModule : public Module
 public:
     IpsModule() : Module("ips", ips_help, ips_params) { }
     bool set(const char*, Value&, SnortConfig*) override;
+    bool matches(const char*, std::string&) override;
 
     Usage get_usage() const override
     { return DETECT; }
 };
 
-bool IpsModule::set(const char*, Value& v, SnortConfig* sc)
+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::set(const char* fqn, Value& v, SnortConfig* sc)
 {
     IpsPolicy* p = get_ips_policy();
 
@@ -1263,6 +1297,9 @@ bool IpsModule::set(const char*, Value& v, SnortConfig* sc)
     }
 #endif
 
+    else if ( strstr(fqn, "variables") )
+        set_var(sc, fqn, v);
+
     else
         return false;
 
index 93d63a800b25d27af705d7f397869cc3c4a29661..fb937126998d39c55854e24e2a076c72a0194497 100644 (file)
@@ -188,19 +188,6 @@ static void set_top(string& fqn)
         fqn.erase(pos);
 }
 
-static void trace(const char* s, const char* fqn, Value& v)
-{
-#if 1
-    if ( s )
-        return;
-#endif
-
-    if ( v.get_type() == Value::VT_STR )
-        printf("%s: %s = '%s'\n", s, fqn, v.get_string());
-    else
-        printf("%s: %s = " STDi64 "\n", s, fqn, v.get_int64());
-}
-
 static ModHook* get_hook(const char* s)
 {
     auto mh = s_modules.find(s);
@@ -407,54 +394,6 @@ static const Parameter* get_params(
     return get_params(new_fqn, m, p, idx);
 }
 
-// FIXIT-M vars may have been defined on command line. that mechanism will
-// be replaced with pulling a Lua chunk from the command line and stuffing
-// into L before setting configs; that will overwrite
-//
-// 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
-//
-// FIXIT-L presently no way to catch errors like EXTERNAL_NET = not HOME_NET
-// which becomes a bool var and is ignored.
-static bool set_var(const char* fqn, Value& val)
-{
-    if ( val.get_type() != Value::VT_STR )
-        return false;
-
-    if ( get_ips_policy() == nullptr )
-        return true;
-
-    trace("var", fqn, val);
-    const char* s = val.get_string();
-
-    if ( strstr(fqn, "PATH") )
-        AddVarToTable(s_config, fqn, s);
-
-    else if ( strstr(fqn, "PORT") )
-        PortVarDefine(s_config, fqn, s);
-
-    else if ( strstr(fqn, "NET") || strstr(fqn, "SERVER") )
-        ParseIpVar(s_config, fqn, s);
-
-    return true;
-}
-
-static bool set_param(Module* mod, const char* fqn, Value& val)
-{
-    if ( !mod->verified_set(fqn, val, s_config) )
-    {
-        ParseError("%s is invalid", fqn);
-        ++s_errors;
-    }
-
-    trace("par", fqn, val);
-    return true;
-}
-
 static bool ignored(const char* fqn)
 {
     static const char* ignore = nullptr;
@@ -481,6 +420,41 @@ static bool ignored(const char* fqn)
     return true;
 }
 
+// FIXIT-M vars may have been defined on command line. that mechanism will
+// be replaced with pulling a Lua chunk from the command line and stuffing
+// into L before setting configs; that will overwrite
+//
+// FIXIT-L presently no way to catch errors like EXTERNAL_NET = not HOME_NET
+// which becomes a bool var and is ignored.
+static bool set_var(const char* fqn, Value& v)
+{
+    bool to_be_set = v.get_type() == Value::VT_STR;
+
+    if ( to_be_set )
+    {
+        if ( get_ips_policy() != nullptr )
+            SetVar(s_config, fqn, v.get_string());
+    }
+    else
+    {
+        if ( !ignored(fqn) )
+            ParseWarning(WARN_SYMBOLS, "unknown symbol %s", fqn);
+    }
+
+    return to_be_set;
+}
+
+static bool set_param(Module* mod, const char* fqn, Value& val)
+{
+    if ( !mod->verified_set(fqn, val, s_config) )
+    {
+        ParseError("%s is invalid", fqn);
+        ++s_errors;
+    }
+
+    return true;
+}
+
 static bool set_value(const char* fqn, Value& v)
 {
     string t = fqn;
@@ -493,13 +467,7 @@ static bool set_value(const char* fqn, Value& v)
     Module* mod = ModuleManager::get_module(key.c_str());
 
     if ( !mod )
-    {
-        bool found = set_var(fqn, v);
-
-        if ( !found && !ignored(fqn) )
-            ParseWarning(WARN_SYMBOLS, "unknown symbol %s", fqn);
-        return found;
-    }
+        return set_var(fqn, v);
 
     const Parameter* p;
     auto a = s_pmap.find(t);
index 134619305936bd853ad5bd3357defb36f7750c38..af7f2a041cbd5247cae1fb6e222db9a94f4aac50 100644 (file)
@@ -201,6 +201,26 @@ 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)
 {
     int ret;
index 9e7e10df2b07672126b4cb5b0550ea25fd39f190..065bab0c97342566f8cc2e175ea3fde45f458955 100644 (file)
@@ -41,6 +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 parse_include(snort::SnortConfig*, const char*);
 
index 674dc5c7d591a20f417b9d75865e479d83f1d1ef..73a92be8c25acfb61b0928265c13204dc97d5ccb 100644 (file)
@@ -34,14 +34,10 @@ sfip_var_t* sfip_var_from_string(const char* addr, const char* caller)
 {
     sfip_var_t* ret;
     int ret_code;
-    vartable_t* ip_vartable = nullptr;
-
-    if (get_ips_policy())
-        ip_vartable = get_ips_policy()->ip_vartable;
 
     ret = (sfip_var_t*)snort_calloc(sizeof(sfip_var_t));
 
-    if ((ret_code = sfvt_add_to_var(ip_vartable, ret, addr)) != SFIP_SUCCESS)
+    if ((ret_code = sfvt_add_to_var(nullptr, ret, addr)) != SFIP_SUCCESS)
     {
         if (ret_code == SFIP_LOOKUP_FAILURE)
         {
index 5e7f67b6a1f15164300fdc045068b79c94d640d2..131a8f47a7368fea63fb92b45324dbed3b2c8463 100644 (file)
@@ -159,18 +159,14 @@ int PortVarDefine(SnortConfig* sc, const char* name, const char* s)
     if ( rstat < 0 )
     {
         ParseError("PortVarTableAdd failed with '%s', exiting.", po->name);
+        PortObjectFree(po);
     }
     else if ( rstat > 0 )
     {
         ParseWarning(WARN_VARS, "PortVar '%s', already defined.", po->name);
+        PortObjectFree(po);
     }
 
-#if 0
-    LogMessage("PortVar '%s' defined : ",po->name);
-    PortObjectPrintPortsRaw(po);
-    LogMessage("\n");
-#endif
-
     return 0;
 }
 
@@ -589,30 +585,6 @@ VarEntry* VarDefine(
     else
         p->id = var_id;
 
-#if 0
-    vlen = strlen(value);
-    LogMessage("Var '%s' defined, value len = %d chars", p->name, vlen);
-
-    if ( vlen < 64 )
-    {
-        LogMessage(", value = %s\n", value);
-    }
-    else
-    {
-        LogMessage("\n");
-        n = 128;
-        s = value;
-        while (vlen)
-        {
-            if ( n > vlen )
-                n = vlen;
-            LogMessage("   %.*s\n", n, s);
-            s    += n;
-            vlen -= n;
-        }
-    }
-#endif
-
     return p;
 }
 
index 187bf62e20051a6f6c5d05ba16e95d1675c6ee79..c52b7fbb9bb6806767ebeaa3cf248d84c0994f83 100644 (file)
@@ -1340,6 +1340,55 @@ TEST_CASE("SfIpVarListMerge", "[SfIpVar]")
 
         sfvt_free_table(table);
     }
+
+    SECTION("merge without table")
+    {
+        SfIp* ip;
+
+        var2 = (sfip_var_t*)snort_calloc(sizeof(sfip_var_t));
+        table = sfvt_alloc_table();
+
+        // 'foo' variable
+        CHECK(sfvt_add_str(table, "foo 1.0.0.1", &var1) == SFIP_SUCCESS);
+
+        // no table used
+        CHECK(sfvt_add_to_var(nullptr, var2, "1.0.0.2") == SFIP_SUCCESS);
+        CHECK(sfvt_add_to_var(nullptr, var2, "$foo") == SFIP_LOOKUP_UNAVAILABLE);
+        CHECK(sfvt_add_to_var(nullptr, var2, "$moo") == SFIP_LOOKUP_UNAVAILABLE);
+
+        print_var_list(var2->head);
+        CHECK(!strcmp("1.0.0.2", sfipvar_test_buff));
+
+        ip = (SfIp *)snort_alloc(sizeof(SfIp));
+        CHECK(ip->set("1.0.0.1") == SFIP_SUCCESS);
+        CHECK((sfvar_ip_in(var2, ip) == false));
+        snort_free(ip);
+
+        ip = (SfIp *)snort_alloc(sizeof(SfIp));
+        CHECK(ip->set("1.0.0.2") == SFIP_SUCCESS);
+        CHECK((sfvar_ip_in(var2, ip) == true));
+        snort_free(ip);
+
+        // using table
+        CHECK(sfvt_add_to_var(table, var2, "$foo") == SFIP_SUCCESS);
+        CHECK(sfvt_add_to_var(table, var2, "$moo") == SFIP_LOOKUP_FAILURE);
+
+        print_var_list(var2->head);
+        CHECK(!strcmp("1.0.0.1,1.0.0.2", sfipvar_test_buff));
+
+        ip = (SfIp *)snort_alloc(sizeof(SfIp));
+        CHECK(ip->set("1.0.0.1") == SFIP_SUCCESS);
+        CHECK((sfvar_ip_in(var2, ip) == true));
+        snort_free(ip);
+
+        ip = (SfIp *)snort_alloc(sizeof(SfIp));
+        CHECK(ip->set("1.0.0.2") == SFIP_SUCCESS);
+        CHECK((sfvar_ip_in(var2, ip) == true));
+        snort_free(ip);
+
+        sfvar_free(var2);
+        sfvt_free_table(table);
+    }
 }
 
 TEST_CASE("SfIpVarCopyAddCompare", "[SfIpVar]")
index 17673972c376814a4846577eea513a4437e435e9..6818eef6571f6bc7f3ef85c0febc472ffa293417 100644 (file)
@@ -263,8 +263,19 @@ 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)
+{
+    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;
+}
+
 void DataApi::set_variable(const std::string& name, const std::string& value, bool quoted)
 {
+    if (is_local_variable(name))
+        local_vars.push_back(name);
+
     Variable* var = new Variable(name);
     vars.push_back(var);
     var->set_value(value, quoted);
@@ -276,6 +287,9 @@ bool DataApi::add_variable(const std::string& name, const std::string& value)
         if (name == v->get_name())
             return v->add_value(value);
 
+    if (is_local_variable(name))
+        local_vars.push_back(name);
+
     Variable* var = new Variable(name);
     vars.push_back(var);
     return var->add_value(value);
@@ -311,7 +325,7 @@ void DataApi::add_comment(const std::string& c)
 void DataApi::add_unsupported_comment(const std::string& c)
 { unsupported->add_text(c); }
 
-void DataApi::print_errors(std::ostream& out)
+void DataApi::print_errors(std::ostream& out) const
 {
     if (is_default_mode() &&
         !errors->empty())
@@ -320,7 +334,7 @@ void DataApi::print_errors(std::ostream& out)
     }
 }
 
-void DataApi::print_data(std::ostream& out)
+void DataApi::print_data(std::ostream& out) const
 {
     for (Variable* v : vars)
         out << (*v) << "\n\n";
@@ -329,18 +343,29 @@ void DataApi::print_data(std::ostream& out)
         out << (*i) << "\n\n";
 }
 
-void DataApi::print_comments(std::ostream& out)
+void DataApi::print_comments(std::ostream& out) const
 {
     if (is_default_mode() && !comments->empty())
         out << (*comments) << "\n";
 }
 
-void DataApi::print_unsupported(std::ostream& out)
+void DataApi::print_unsupported(std::ostream& out) const
 {
     if (is_default_mode() && !unsupported->empty())
         out << (*unsupported) << "\n";
 }
 
+void DataApi::print_local_variables(std::ostream& out) const
+{
+    if (local_vars.empty())
+        return;
+
+    out << "local_variables =\n{\n";
+    for (const auto& v : local_vars)
+        out << "    " << v << " = " << v << ",\n";
+    out << "}\n\n";
+}
+
 void DataApi::swap_conf_data(std::vector<Variable*>& new_vars,
     std::vector<Include*>& new_includes,
     Comments*& new_comments, Comments*& new_unsupported)
index 3d774d65f19cc691d4ab53dd448896c912084fc7..a6f3a2b0f224f67e7fa5d4e42f65b485c54c9c19 100644 (file)
@@ -81,10 +81,11 @@ public:
     void reset_state();
 
     // Output Functions
-    void print_errors(std::ostream&);
-    void print_data(std::ostream&);
-    void print_comments(std::ostream& out);
-    void print_unsupported(std::ostream& out);
+    void print_errors(std::ostream&) const;
+    void print_data(std::ostream&) const;
+    void print_comments(std::ostream& out) const;
+    void print_unsupported(std::ostream& out) const;
+    void print_local_variables(std::ostream&) const;
 
     // have there been any failed conversion?
     bool failed_conversions() const;
@@ -93,6 +94,9 @@ public:
     bool empty() const
     { return vars.empty() && includes.empty(); }
 
+    bool has_local_vars() const
+    { return !local_vars.empty(); }
+
     // functions specifically useful when parsing includes.
     // allows for easy swapping of data.  These two functions
     // swap data which will be printed in 'print_rules()' and
@@ -141,6 +145,7 @@ private:
 
     std::vector<Variable*> vars;
     std::vector<Include*> includes;
+    std::vector<std::string> local_vars;
     Comments* comments;
     Comments* errors;
     Comments* unsupported;
index c0b05934b7a1ef10b5c08c1ff6a0bb616336bb47..c34b2132f3e8d45824405212294d6ff218bcfacb 100644 (file)
 #include "helpers/converter.h"
 #include "conversion_state.h"
 #include "data/data_types/dt_comment.h"
+#include "data/data_types/dt_include.h"
 #include "data/data_types/dt_rule.h"
 #include "data/data_types/dt_table.h"
+#include "data/data_types/dt_var.h"
 #include "helpers/s2l_util.h"
 #include "helpers/util_binder.h"
 #include "init_state.h"
@@ -173,12 +175,18 @@ int Converter::parse_include_file(const std::string& input_file)
             rule_api.include_rule_file(input_file + ".rules");
     }
 
+    for (auto v : vars)
+        delete v;
+
     for (auto r : rules)
         delete r;
 
     for (auto t : tables)
         delete t;
 
+    for (auto i : includes)
+        delete i;
+
     return rc;
 }
 
@@ -518,13 +526,16 @@ int Converter::convert(
 
         if (!rule_api.empty())
         {
+            data_api.print_local_variables(out);
+
             if (rule_file.empty() || rule_file == output_file)
             {
                 rule_api.print_rules(out, false);
 
-                std::string s = std::string("$local_rules");
                 table_api.open_top_level_table("ips");
-                table_api.add_option("rules", s);
+                table_api.add_option("rules", "$local_rules");
+                if (data_api.has_local_vars())
+                    table_api.add_option("variables", "$local_variables");
                 table_api.close_table();
             }
             else
@@ -536,6 +547,8 @@ int Converter::convert(
 
                 table_api.open_top_level_table("ips");
                 table_api.add_option("include", rule_file);
+                if (data_api.has_local_vars())
+                    table_api.add_option("variables", "$local_variables");
                 table_api.close_table();
             }
         }