From: Tom Peters (thopeter) Date: Fri, 9 Sep 2022 20:17:33 +0000 (+0000) Subject: Pull request #3576: http_inspect: Investigate if we can refactor rule options using... X-Git-Tag: 3.1.42.0~17 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d97f26c30f0059b8fdbeaeb3a6c13317899060b9;p=thirdparty%2Fsnort3.git Pull request #3576: http_inspect: Investigate if we can refactor rule options using ranges/2 Merge in SNORT/snort3 from ~ADMAMOLE/snort3:derive_range_option to master Squashed commit of the following: commit ae50bb122b87ef5fc32bc06536f4d556ed082c78 Author: Adrian Mamolea Date: Tue Aug 16 14:41:45 2022 -0400 http_inspect: rework range rule options --- diff --git a/src/service_inspectors/http_inspect/ips_http_num_hdrs.cc b/src/service_inspectors/http_inspect/ips_http_num_hdrs.cc index 3b9d4f5ac..5d2632a46 100644 --- a/src/service_inspectors/http_inspect/ips_http_num_hdrs.cc +++ b/src/service_inspectors/http_inspect/ips_http_num_hdrs.cc @@ -41,28 +41,25 @@ using namespace snort; using namespace HttpCommon; using namespace HttpEnums; -THREAD_LOCAL std::array HttpNumHdrsRuleOptModule::http_num_hdrs_ps; - -static const char* num_range = "0:65535"; +// Base class for all range-based rule options modules +HttpRangeRuleOptModule::HttpRangeRuleOptModule(const char* key_, const char* help, + HTTP_RULE_OPT rule_opt_index_, const Parameter params[], ProfileStats& ps_) : + HttpRuleOptModule(key_, help, rule_opt_index_, CAT_NONE, params), ps(ps_) +{ + const Parameter& range_param = params[0]; + // enforce that "~range" is the first Parameter + assert(range_param.type == Parameter::PT_INTERVAL); + num_range = range_param.get_range(); +} -bool HttpNumHdrsRuleOptModule::begin(const char*, int, SnortConfig*) +bool HttpRangeRuleOptModule::begin(const char*, int, SnortConfig*) { HttpRuleOptModule::begin(nullptr, 0, nullptr); range.init(); - if (rule_opt_index == HTTP_RANGE_NUM_HDRS) - inspect_section = IS_FLEX_HEADER; - else if (rule_opt_index == HTTP_RANGE_NUM_COOKIES) - inspect_section = IS_HEADER; - else - { - inspect_section = IS_TRAILER; - is_trailer_opt = true; - } - return true; } -bool HttpNumHdrsRuleOptModule::set(const char*, Value& v, SnortConfig*) +bool HttpRangeRuleOptModule::set(const char*, Value& v, SnortConfig*) { if (v.is("~range")) return range.validate(v.get_string(), num_range); @@ -70,8 +67,8 @@ bool HttpNumHdrsRuleOptModule::set(const char*, Value& v, SnortConfig*) return HttpRuleOptModule::set(nullptr, v, nullptr); } - -uint32_t HttpNumHdrsIpsOption::hash() const +// Base class for all range-based rule options +uint32_t HttpRangeIpsOption::hash() const { uint32_t a = HttpIpsOption::hash(); uint32_t b = range.hash(); @@ -81,25 +78,23 @@ uint32_t HttpNumHdrsIpsOption::hash() const return c; } -bool HttpNumHdrsIpsOption::operator==(const IpsOption& ips) const +bool HttpRangeIpsOption::operator==(const IpsOption& ips) const { - const HttpNumHdrsIpsOption& hio = static_cast(ips); + const HttpRangeIpsOption& hio = static_cast(ips); return HttpIpsOption::operator==(ips) && range == hio.range; } -IpsOption::EvalStatus HttpNumHdrsIpsOption::eval(Cursor&, Packet* p) +IpsOption::EvalStatus HttpRangeIpsOption::eval(Cursor&, Packet* p) { - RuleProfile profile(HttpNumHdrsRuleOptModule::http_num_hdrs_ps[idx]); + RuleProfile profile(ps); const HttpInspect* const hi = eval_helper(p); if (hi == nullptr) return NO_MATCH; - const int32_t count = (idx == NUM_HDRS_PSI_COOKIES) ? - hi->http_get_num_cookies(p, buffer_info) : - hi->http_get_num_headers(p, buffer_info); - if (count != HttpCommon::STAT_NOT_PRESENT && range.eval(count)) + const int32_t count = get_num(hi, p); + if (count != STAT_NOT_PRESENT && range.eval(count)) return MATCH; return NO_MATCH; @@ -115,7 +110,7 @@ IpsOption::EvalStatus HttpNumHdrsIpsOption::eval(Cursor&, Packet* p) static const Parameter http_num_hdrs_params[] = { - { "~range", Parameter::PT_INTERVAL, num_range, nullptr, + { "~range", Parameter::PT_INTERVAL, "0:65535", nullptr, "check that number of headers of current buffer are in given range" }, { "request", Parameter::PT_IMPLIED, nullptr, nullptr, "match against the version from the request message even when examining the response" }, @@ -130,8 +125,8 @@ static const Parameter http_num_hdrs_params[] = static Module* num_hdrs_mod_ctor() { - return new HttpNumHdrsRuleOptModule(IPS_OPT, IPS_HELP, HTTP_RANGE_NUM_HDRS, CAT_NONE, - NUM_HDRS_PSI_HDRS, http_num_hdrs_params); + return new HttpNumRuleOptModule(IPS_OPT, IPS_HELP, + http_num_hdrs_params); } static const IpsApi num_headers_api = @@ -146,7 +141,7 @@ static const IpsApi num_headers_api = IPS_OPT, IPS_HELP, num_hdrs_mod_ctor, - HttpNumHdrsRuleOptModule::mod_dtor + HttpRangeRuleOptModule::mod_dtor }, OPT_TYPE_DETECTION, 0, PROTO_BIT__TCP, @@ -154,8 +149,8 @@ static const IpsApi num_headers_api = nullptr, nullptr, nullptr, - HttpNumHdrsIpsOption::opt_ctor, - HttpNumHdrsIpsOption::opt_dtor, + HttpNumIpsOption<&HttpInspect::http_get_num_headers>::opt_ctor, + HttpRangeIpsOption::opt_dtor, nullptr }; @@ -169,8 +164,8 @@ static const IpsApi num_headers_api = static Module* num_trailers_mod_ctor() { - return new HttpNumHdrsRuleOptModule(IPS_OPT, IPS_HELP, HTTP_RANGE_NUM_TRAILERS, CAT_NONE, - NUM_HDRS_PSI_TRAILERS, http_num_hdrs_params); + return new HttpNumRuleOptModule(IPS_OPT, IPS_HELP, + http_num_hdrs_params); } static const IpsApi num_trailers_api = @@ -185,7 +180,7 @@ static const IpsApi num_trailers_api = IPS_OPT, IPS_HELP, num_trailers_mod_ctor, - HttpNumHdrsRuleOptModule::mod_dtor + HttpRangeRuleOptModule::mod_dtor }, OPT_TYPE_DETECTION, 0, PROTO_BIT__TCP, @@ -193,8 +188,8 @@ static const IpsApi num_trailers_api = nullptr, nullptr, nullptr, - HttpNumHdrsIpsOption::opt_ctor, - HttpNumHdrsIpsOption::opt_dtor, + HttpNumIpsOption<&HttpInspect::http_get_num_headers>::opt_ctor, + HttpRangeIpsOption::opt_dtor, nullptr }; @@ -208,7 +203,7 @@ static const IpsApi num_trailers_api = static const Parameter http_num_cookies_params[] = { - { "~range", Parameter::PT_INTERVAL, num_range, nullptr, + { "~range", Parameter::PT_INTERVAL, "0:65535", nullptr, "check that number of cookies of current header are in given range" }, { "request", Parameter::PT_IMPLIED, nullptr, nullptr, "match against the version from the request message even when examining the response" }, @@ -217,8 +212,8 @@ static const Parameter http_num_cookies_params[] = static Module* num_cookies_mod_ctor() { - return new HttpNumHdrsRuleOptModule(IPS_OPT, IPS_HELP, HTTP_RANGE_NUM_COOKIES, CAT_NONE, - NUM_HDRS_PSI_COOKIES, http_num_cookies_params); + return new HttpNumRuleOptModule(IPS_OPT, IPS_HELP, + http_num_cookies_params); } static const IpsApi num_cookies_api = @@ -233,7 +228,7 @@ static const IpsApi num_cookies_api = IPS_OPT, IPS_HELP, num_cookies_mod_ctor, - HttpNumHdrsRuleOptModule::mod_dtor + HttpRangeRuleOptModule::mod_dtor }, OPT_TYPE_DETECTION, 0, PROTO_BIT__TCP, @@ -241,8 +236,8 @@ static const IpsApi num_cookies_api = nullptr, nullptr, nullptr, - HttpNumHdrsIpsOption::opt_ctor, - HttpNumHdrsIpsOption::opt_dtor, + HttpNumIpsOption<&HttpInspect::http_get_num_cookies>::opt_ctor, + HttpRangeIpsOption::opt_dtor, nullptr }; diff --git a/src/service_inspectors/http_inspect/ips_http_num_hdrs.h b/src/service_inspectors/http_inspect/ips_http_num_hdrs.h index 8272f1ffa..bc0e62712 100644 --- a/src/service_inspectors/http_inspect/ips_http_num_hdrs.h +++ b/src/service_inspectors/http_inspect/ips_http_num_hdrs.h @@ -29,49 +29,87 @@ #include "framework/range.h" #include "http_enum.h" +#include "http_inspect.h" #include "ips_http.h" -enum NumHdrsPsIdx { NUM_HDRS_PSI_HDRS, NUM_HDRS_PSI_TRAILERS, NUM_HDRS_PSI_COOKIES, NUM_HDRS_PSI_MAX }; - -class HttpNumHdrsRuleOptModule : public HttpRuleOptModule +// Base class for all range-based rule options modules +class HttpRangeRuleOptModule : public HttpRuleOptModule { public: - HttpNumHdrsRuleOptModule(const char* key_, const char* help, HttpEnums::HTTP_RULE_OPT rule_opt_index_, - snort::CursorActionType cat_, NumHdrsPsIdx idx_, const snort::Parameter params[]) - : HttpRuleOptModule(key_, help, rule_opt_index_, cat_, params), idx(idx_) {} + HttpRangeRuleOptModule(const char* key_, const char* help, HttpEnums::HTTP_RULE_OPT rule_opt_index_, + const snort::Parameter params[], snort::ProfileStats& ps_); + + snort::ProfileStats* get_profile() const override { return &ps; } - snort::ProfileStats* get_profile() const override - { return &http_num_hdrs_ps[idx]; } - static void mod_dtor(snort::Module* m) { delete m; } bool begin(const char*, int, snort::SnortConfig*) override; bool set(const char*, snort::Value&, snort::SnortConfig*) override; private: - friend class HttpNumHdrsIpsOption; - static THREAD_LOCAL std::array http_num_hdrs_ps; - const NumHdrsPsIdx idx; + snort::ProfileStats& ps; + + friend class HttpRangeIpsOption; + const char* num_range; snort::RangeCheck range; }; -class HttpNumHdrsIpsOption : public HttpIpsOption +// Base class for all range-based rule options +class HttpRangeIpsOption : public HttpIpsOption { public: - HttpNumHdrsIpsOption(const HttpNumHdrsRuleOptModule* cm) : - HttpIpsOption(cm), idx(cm->idx), range(cm->range) {} + HttpRangeIpsOption(const HttpRangeRuleOptModule* cm) : + HttpIpsOption(cm), ps(cm->ps), range(cm->range) { } EvalStatus eval(Cursor&, snort::Packet*) override; uint32_t hash() const override; bool operator==(const snort::IpsOption& ips) const override; - static IpsOption* opt_ctor(snort::Module* m, OptTreeNode*) - { return new HttpNumHdrsIpsOption((HttpNumHdrsRuleOptModule*)m); } - static void opt_dtor(snort::IpsOption* p) { delete p; } + virtual int32_t get_num(const HttpInspect* hi, snort::Packet* p) = 0; + private: - const NumHdrsPsIdx idx; + snort::ProfileStats& ps; const snort::RangeCheck range; }; +// Template class for range-based rule options module +template +class HttpNumRuleOptModule : public HttpRangeRuleOptModule +{ +public: + HttpNumRuleOptModule(const char* key_, const char* help, const snort::Parameter params[]) + : HttpRangeRuleOptModule(key_, help, OPT_IDX, params, ps) { } + + bool begin(const char*, int, snort::SnortConfig*) override + { + HttpRangeRuleOptModule::begin(nullptr, 0, nullptr); + inspect_section = SECTION; + if (inspect_section == HttpEnums::IS_TRAILER) + { + is_trailer_opt = true; + } + return true; + } + +private: + static THREAD_LOCAL snort::ProfileStats ps; +}; + +template +THREAD_LOCAL snort::ProfileStats HttpNumRuleOptModule::ps; + +// Template class for range-based rule options +template +class HttpNumIpsOption : public HttpRangeIpsOption +{ +public: + using HttpRangeIpsOption::HttpRangeIpsOption; + + static IpsOption* opt_ctor(snort::Module* m, OptTreeNode*) + { return new HttpNumIpsOption((const HttpRangeRuleOptModule*)m); } + + int32_t get_num(const HttpInspect* hi, snort::Packet* p) override + { return (hi->*FNC)(p, buffer_info); } +}; #endif