From: Tom Peters (thopeter) Date: Thu, 31 Jan 2019 18:43:36 +0000 (-0500) Subject: Merge pull request #1497 in SNORT/snort3 from ~MIREDDEN/snort3:fix_sticky_buffer_dupl... X-Git-Tag: 3.0.0-251~57 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3bdea79c7115d206b0f5041eb6a0cc337c28253c;p=thirdparty%2Fsnort3.git Merge pull request #1497 in SNORT/snort3 from ~MIREDDEN/snort3:fix_sticky_buffer_duplicates to master Squashed commit of the following: commit 91637b20ce8f365061a607e9233b1a239629fc72 Author: Mike Redden Date: Mon Jan 28 17:10:32 2019 -0500 snort2lua: fix sticky buffer duplication --- diff --git a/tools/snort2lua/data/data_types/dt_rule.cc b/tools/snort2lua/data/data_types/dt_rule.cc index 9c6c28ae6..f47fe1133 100644 --- a/tools/snort2lua/data/data_types/dt_rule.cc +++ b/tools/snort2lua/data/data_types/dt_rule.cc @@ -116,20 +116,27 @@ void Rule::add_suboption(const std::string& keyword, const std::string& val) void Rule::set_curr_options_buffer(const std::string& new_buffer, bool add_option) { - /* set the buffer if - * 1) No buffer has been set and this is not the default "pkt_data" buffer - * 2) The sticky buffer is set and is not equal to the new buffer - */ - if ( (sticky_buffer.empty() && new_buffer != "pkt_data") || - (!sticky_buffer.empty() && sticky_buffer != new_buffer) ) + if (new_buffer == "pkt_data") { - RuleOption* new_opt = new RuleOption(new_buffer); - if ( add_option ) - options.push_back(new_opt); - else - options.insert(options.end() - 1, new_opt); - sticky_buffer = new_buffer; + if (sticky_buffer.empty()) + { + sticky_buffer = "pkt_data"; + return; + } + + if (sticky_buffer == "pkt_data") + { + return; + } } + + RuleOption* new_opt = new RuleOption(new_buffer); + if ( add_option ) + options.push_back(new_opt); + else + options.insert(options.end() - 1, new_opt); + + sticky_buffer = new_buffer; } std::ostream& operator<<(std::ostream& out, const Rule& rule) @@ -181,23 +188,28 @@ void Rule::resolve_pcre_buffer_options() { std::string curr_sticky_buffer = ""; const std::string service = get_option("service"); - bool service_sip = (service.find("sip") != std::string::npos); - bool no_service_http = (service.find("http") == std::string::npos); + const bool service_sip = (service.find("sip") != std::string::npos); + const bool no_service_http = (service.find("http") == std::string::npos); std::string new_buffer; std::vector::iterator iter = options.begin(); + std::vector::iterator next_opt_iter; while (iter != options.end()) { std::string name = (*iter)->get_name(); - if (name == "pcre_P_option_body" || name == "pcre_H_option_header") + if (name == "pcre_P_option_body" || + name == "pcre_P_option_body_rel" || + name == "pcre_H_option_header" || + name == "pcre_H_option_header_rel") { delete(*iter); iter = options.erase(iter); if (service_sip) { - if (name == "pcre_P_option_body") + if (name == "pcre_P_option_body" || + name == "pcre_P_option_body_rel") { new_buffer = "sip_body"; } @@ -208,7 +220,8 @@ void Rule::resolve_pcre_buffer_options() } else { - if (name == "pcre_P_option_body") + if (name == "pcre_P_option_body" || + name == "pcre_P_option_body_rel") { if (no_service_http) { @@ -226,7 +239,11 @@ void Rule::resolve_pcre_buffer_options() } } - if (curr_sticky_buffer != new_buffer) + /* Add sticky buffer option if not equal to current, + * or if the pcre option is not relative */ + if (curr_sticky_buffer != new_buffer || + (name != "pcre_P_option_body_rel" && + name != "pcre_H_option_header_rel")) { curr_sticky_buffer = new_buffer; RuleOption* new_opt = new RuleOption(new_buffer); @@ -239,6 +256,14 @@ void Rule::resolve_pcre_buffer_options() name == "dce_stub_data" || name == "dnp3_data" || name == "modbus_data" || + name == "sip_header" || + name == "sip_body") + { + curr_sticky_buffer = name; + ++iter; + } + else if (name == "http_header" || + name == "http_client_body" || name == "http_cookie" || name == "http_method" || name == "http_raw_cookie" || @@ -247,19 +272,26 @@ void Rule::resolve_pcre_buffer_options() name == "http_stat_code" || name == "http_stat_msg" || name == "http_uri") - { - curr_sticky_buffer = name; - ++iter; - } - else if (name == "http_header" || - name == "http_client_body" || - name == "sip_header" || - name == "sip_body") { if (curr_sticky_buffer == name) { - delete(*iter); - iter = options.erase(iter); + next_opt_iter = std::next(iter, 1); + if (next_opt_iter != options.end()) + { + if ((*next_opt_iter)->is_relative_content()) + { + delete(*iter); + iter = options.erase(iter); + } + else + { + ++iter; + } + } + else + { + ++iter; + } } else { diff --git a/tools/snort2lua/data/data_types/dt_rule_option.cc b/tools/snort2lua/data/data_types/dt_rule_option.cc index a4d6f5d73..af01e1e33 100644 --- a/tools/snort2lua/data/data_types/dt_rule_option.cc +++ b/tools/snort2lua/data/data_types/dt_rule_option.cc @@ -51,6 +51,21 @@ bool RuleOption::add_suboption(const std::string& subopt_name, return true; } +bool RuleOption::is_relative_content() +{ + if (get_name() == "content") + { + for (auto rso : sub_options) + { + const std::string subopt_name = rso->get_name(); + if (subopt_name == "within" || subopt_name == "distance") + return true; + } + } + + return false; +} + std::ostream& operator<<(std::ostream& out, const RuleOption& opt) { bool first_print = true; diff --git a/tools/snort2lua/data/data_types/dt_rule_option.h b/tools/snort2lua/data/data_types/dt_rule_option.h index 8d9dc83d8..a2ffa8190 100644 --- a/tools/snort2lua/data/data_types/dt_rule_option.h +++ b/tools/snort2lua/data/data_types/dt_rule_option.h @@ -35,11 +35,13 @@ public: inline const std::string& get_name() { return name; } inline const std::string& get_value() { return value; } - inline void update_value(std::string& new_value) { value = new_value;} + inline void update_value(std::string& new_value) { value = new_value; } bool add_suboption(const std::string& name); bool add_suboption(const std::string& name, const std::string& val); + bool is_relative_content(); + // overloading operators friend std::ostream& operator<<(std::ostream&, const RuleOption&); diff --git a/tools/snort2lua/data/data_types/dt_rule_suboption.h b/tools/snort2lua/data/data_types/dt_rule_suboption.h index e40d85602..53c13649e 100644 --- a/tools/snort2lua/data/data_types/dt_rule_suboption.h +++ b/tools/snort2lua/data/data_types/dt_rule_suboption.h @@ -31,6 +31,8 @@ public: RuleSubOption(const std::string& name, const std::string& val); virtual ~RuleSubOption() = default; + inline const std::string& get_name() { return name; } + // overloading operators friend std::ostream& operator<<(std::ostream&, const RuleSubOption&); diff --git a/tools/snort2lua/rule_states/rule_pcre.cc b/tools/snort2lua/rule_states/rule_pcre.cc index 0ff7c6c63..c3e79ffa1 100644 --- a/tools/snort2lua/rule_states/rule_pcre.cc +++ b/tools/snort2lua/rule_states/rule_pcre.cc @@ -141,8 +141,15 @@ bool Pcre::convert(std::istringstream& data_stream) rule_api.add_option("pcre", pattern + new_opts); - if ( !relative ) - rule_api.set_curr_options_buffer(buffer); + if ( relative ) + { + if (buffer == "pcre_P_option_body") + buffer = "pcre_P_option_body_rel"; + else if (buffer == "pcre_H_option_header") + buffer = "pcre_H_option_header_rel"; + } + + rule_api.set_curr_options_buffer(buffer); return set_next_rule_state(data_stream); }