]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Pull request #3576: http_inspect: Investigate if we can refactor rule options using...
authorTom Peters (thopeter) <thopeter@cisco.com>
Fri, 9 Sep 2022 20:17:33 +0000 (20:17 +0000)
committerTom Peters (thopeter) <thopeter@cisco.com>
Fri, 9 Sep 2022 20:17:33 +0000 (20:17 +0000)
Merge in SNORT/snort3 from ~ADMAMOLE/snort3:derive_range_option to master

Squashed commit of the following:

commit ae50bb122b87ef5fc32bc06536f4d556ed082c78
Author: Adrian Mamolea <admamole@cisco.com>
Date:   Tue Aug 16 14:41:45 2022 -0400

    http_inspect: rework range rule options

src/service_inspectors/http_inspect/ips_http_num_hdrs.cc
src/service_inspectors/http_inspect/ips_http_num_hdrs.h

index 3b9d4f5ac339b41737d186d1a22f43ee042e9343..5d2632a4693e82ff825ba47aaaf78a731e235b85 100644 (file)
@@ -41,28 +41,25 @@ using namespace snort;
 using namespace HttpCommon;
 using namespace HttpEnums;
 
-THREAD_LOCAL std::array<ProfileStats, NUM_HDRS_PSI_MAX> 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<const HttpNumHdrsIpsOption&>(ips);
+    const HttpRangeIpsOption& hio = static_cast<const HttpRangeIpsOption&>(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<HTTP_RANGE_NUM_HDRS, IS_FLEX_HEADER>(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<HTTP_RANGE_NUM_TRAILERS, IS_TRAILER>(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<HTTP_RANGE_NUM_COOKIES, IS_HEADER>(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
 };
 
index 8272f1ffa5249e32fc63d6e4dd5911c83d95cea5..bc0e6271233fb589a6769a5f44dcaa20ee90145b 100644 (file)
 #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<snort::ProfileStats, NUM_HDRS_PSI_MAX> 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<HttpEnums::HTTP_RULE_OPT OPT_IDX, HttpEnums::InspectSection SECTION>
+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<HttpEnums::HTTP_RULE_OPT OPT_IDX, HttpEnums::InspectSection SECTION>
+THREAD_LOCAL snort::ProfileStats HttpNumRuleOptModule<OPT_IDX, SECTION>::ps;
+
+// Template class for range-based rule options
+template<int32_t (HttpInspect::* FNC)(snort::Packet*, const HttpBufferInfo&) const>
+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