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);
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();
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;
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" },
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 =
IPS_OPT,
IPS_HELP,
num_hdrs_mod_ctor,
- HttpNumHdrsRuleOptModule::mod_dtor
+ HttpRangeRuleOptModule::mod_dtor
},
OPT_TYPE_DETECTION,
0, PROTO_BIT__TCP,
nullptr,
nullptr,
nullptr,
- HttpNumHdrsIpsOption::opt_ctor,
- HttpNumHdrsIpsOption::opt_dtor,
+ HttpNumIpsOption<&HttpInspect::http_get_num_headers>::opt_ctor,
+ HttpRangeIpsOption::opt_dtor,
nullptr
};
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 =
IPS_OPT,
IPS_HELP,
num_trailers_mod_ctor,
- HttpNumHdrsRuleOptModule::mod_dtor
+ HttpRangeRuleOptModule::mod_dtor
},
OPT_TYPE_DETECTION,
0, PROTO_BIT__TCP,
nullptr,
nullptr,
nullptr,
- HttpNumHdrsIpsOption::opt_ctor,
- HttpNumHdrsIpsOption::opt_dtor,
+ HttpNumIpsOption<&HttpInspect::http_get_num_headers>::opt_ctor,
+ HttpRangeIpsOption::opt_dtor,
nullptr
};
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" },
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 =
IPS_OPT,
IPS_HELP,
num_cookies_mod_ctor,
- HttpNumHdrsRuleOptModule::mod_dtor
+ HttpRangeRuleOptModule::mod_dtor
},
OPT_TYPE_DETECTION,
0, PROTO_BIT__TCP,
nullptr,
nullptr,
nullptr,
- HttpNumHdrsIpsOption::opt_ctor,
- HttpNumHdrsIpsOption::opt_dtor,
+ HttpNumIpsOption<&HttpInspect::http_get_num_cookies>::opt_ctor,
+ HttpRangeIpsOption::opt_dtor,
nullptr
};
#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