extern const BaseApi* ips_http_header;
extern const BaseApi* ips_http_header_test;
extern const BaseApi* ips_http_method;
+extern const BaseApi* ips_http_num_cookies;
extern const BaseApi* ips_http_num_headers;
extern const BaseApi* ips_http_num_trailers;
extern const BaseApi* ips_http_param;
ips_http_header,
ips_http_header_test,
ips_http_method,
+ ips_http_num_cookies,
ips_http_num_headers,
ips_http_num_trailers,
ips_http_param,
HTTP_BUFFER_TRAILER, HTTP_BUFFER_TRUE_IP, HTTP_BUFFER_URI, HTTP_BUFFER_VERSION,
BUFFER_JS_DATA, BUFFER_VBA_DATA , HTTP__BUFFER_MAX = BUFFER_VBA_DATA,
HTTP_RANGE_NUM_HDRS, HTTP_RANGE_NUM_TRAILERS, HTTP_VERSION_MATCH,
- HTTP_HEADER_TEST, HTTP_TRAILER_TEST, HTTP__MAX_RULE_OPTION };
+ HTTP_HEADER_TEST, HTTP_TRAILER_TEST, HTTP_RANGE_NUM_COOKIES, HTTP__MAX_RULE_OPTION };
// Peg counts
// This enum must remain synchronized with HttpModule::peg_names[] in http_tables.cc
const HttpMsgSection* const current_section = HttpContextData::get_snapshot(p);
if (current_section == nullptr)
- return STAT_NOT_COMPUTE;
+ return STAT_NOT_PRESENT;
return current_section->get_num_headers(buffer_info);
}
+int32_t HttpInspect::http_get_num_cookies(Packet* p,
+ const HttpBufferInfo& buffer_info) const
+{
+ const HttpMsgSection* const current_section = HttpContextData::get_snapshot(p);
+
+ if (current_section == nullptr)
+ return STAT_NOT_PRESENT;
+
+ return current_section->get_num_cookies(buffer_info);
+}
+
VersionId HttpInspect::http_get_version_id(Packet* p,
const HttpBufferInfo& buffer_info) const
{
const Field& http_get_param_buf(Cursor& c, snort::Packet* p,
const HttpParam& param) const;
int32_t http_get_num_headers(snort::Packet* p, const HttpBufferInfo& buffer_info) const;
+ int32_t http_get_num_cookies(snort::Packet* p, const HttpBufferInfo& buffer_info) const;
HttpEnums::VersionId http_get_version_id(snort::Packet* p,
const HttpBufferInfo& buffer_info) const;
HttpCommon::SectionType get_type_expected(snort::Flow* flow, HttpCommon::SourceId source_id) const override;
// Do a case insensitive search for "boundary=" in a Field
static bool boundary_present(const Field& field);
+ Field* header_line = nullptr;
+ HttpEnums::HeaderId* header_name_id = nullptr;
+ int32_t num_headers = HttpCommon::STAT_NOT_COMPUTE;
+
#ifdef REG_TEST
void print_headers(FILE* output);
#endif
Field classic_raw_header; // raw headers with cookies spliced out
Field classic_norm_header; // URI normalization applied
Field classic_norm_cookie; // URI normalization applied to concatenated cookie values
- Field* header_line = nullptr;
Field* header_name = nullptr;
- HttpEnums::HeaderId* header_name_id = nullptr;
Field* header_value = nullptr;
NormalizedHeader* get_header_node(HttpEnums::HeaderId k) const;
NormalizedHeader* norm_heads = nullptr;
- int32_t num_headers = HttpCommon::STAT_NOT_COMPUTE;
std::bitset<MAX> headers_present = 0;
void extract_filename_from_content_disposition();
return true_ip_addr;
}
+int32_t HttpMsgHeader::get_num_cookies()
+{
+ if (num_cookies != STAT_NOT_COMPUTE)
+ return num_cookies;
+
+ num_cookies = 0;
+ for (int j=0; j < num_headers; j++)
+ {
+ if (header_name_id[j] == HEAD_SET_COOKIE)
+ num_cookies++;
+ else if (header_name_id[j] == HEAD_COOKIE)
+ {
+ const uint8_t* lim = header_line[j].start() + header_line[j].length();
+ for (const uint8_t* p = header_line[j].start(); p < lim; p++)
+ if (*p == ';')
+ num_cookies++;
+ num_cookies++;
+ }
+ }
+
+ return num_cookies;
+}
+
void HttpMsgHeader::gen_events()
{
if ((get_header_count(HEAD_CONTENT_LENGTH) > 0) &&
void publish() override;
const Field& get_true_ip();
const Field& get_true_ip_addr();
+ int32_t get_num_cookies();
// The multi_file_processing_id is unique for each file transferred within a single connection
// and is used by file processing to store partially processed file contexts in the flow data.
Field true_ip;
Field true_ip_addr;
+ int32_t num_cookies = HttpCommon::STAT_NOT_COMPUTE;
uint64_t multi_file_processing_id = 0;
(HttpMsgHeadShared*)trailer[buffer_side]:
(HttpMsgHeadShared*)header[buffer_side] ;
if (head == nullptr)
- return HttpCommon::STAT_NOT_COMPUTE;
+ return HttpCommon::STAT_NO_SOURCE;
return head->get_num_headers();
}
+int32_t HttpMsgSection::get_num_cookies(const HttpBufferInfo& buf) const
+{
+ // buffer_side replaces source_id for rule options that support the request option
+ const SourceId buffer_side = (buf.form & FORM_REQUEST) ? SRC_CLIENT : source_id;
+
+ HttpMsgHeader* head = header[buffer_side];
+ if (head == nullptr)
+ return HttpCommon::STAT_NO_SOURCE;
+
+ return head->get_num_cookies();
+}
+
VersionId HttpMsgSection::get_version_id(const HttpBufferInfo& buf) const
{
// buffer_side replaces source_id for buffers that support the request option
uint64_t get_transaction_id() { return trans_num; }
int32_t get_num_headers(const HttpBufferInfo& buf) const;
+ int32_t get_num_cookies(const HttpBufferInfo& buf) const;
HttpEnums::VersionId get_version_id(const HttpBufferInfo& buf) const;
HttpMsgSection* next = nullptr;
THREAD_LOCAL std::array<ProfileStats, NUM_HDRS_PSI_MAX> HttpNumHdrsRuleOptModule::http_num_hdrs_ps;
-const std::string hdrs_num_range = "0:" + std::to_string(HttpMsgHeadShared::MAX_HEADERS);
+static const char* num_range = "0:65535";
bool HttpNumHdrsRuleOptModule::begin(const char*, int, SnortConfig*)
{
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;
bool HttpNumHdrsRuleOptModule::set(const char*, Value& v, SnortConfig*)
{
if (v.is("~range"))
- return range.validate(v.get_string(), hdrs_num_range.c_str());
-
+ return range.validate(v.get_string(), num_range);
+
return HttpRuleOptModule::set(nullptr, v, nullptr);
}
if (hi == nullptr)
return NO_MATCH;
- const int32_t num_lines = hi->http_get_num_headers(p, buffer_info);
- if (num_lines != HttpCommon::STAT_NOT_PRESENT && range.eval(num_lines))
+ 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))
return MATCH;
return NO_MATCH;
static const Parameter http_num_hdrs_params[] =
{
- { "~range", Parameter::PT_INTERVAL, hdrs_num_range.c_str(), nullptr,
+ { "~range", Parameter::PT_INTERVAL, num_range, 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" },
nullptr
};
+//-------------------------------------------------------------------------
+// num_cookies
+//-------------------------------------------------------------------------
+#undef IPS_OPT
+#define IPS_OPT "http_num_cookies"
+#undef IPS_HELP
+#define IPS_HELP "rule option to perform range check on number of cookies"
+
+static const Parameter http_num_cookies_params[] =
+{
+ { "~range", Parameter::PT_INTERVAL, num_range, 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" },
+ { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
+};
+
+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);
+}
+
+static const IpsApi num_cookies_api =
+{
+ {
+ PT_IPS_OPTION,
+ sizeof(IpsApi),
+ IPSAPI_VERSION,
+ 1,
+ API_RESERVED,
+ API_OPTIONS,
+ IPS_OPT,
+ IPS_HELP,
+ num_cookies_mod_ctor,
+ HttpNumHdrsRuleOptModule::mod_dtor
+ },
+ OPT_TYPE_DETECTION,
+ 0, PROTO_BIT__TCP,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ HttpNumHdrsIpsOption::opt_ctor,
+ HttpNumHdrsIpsOption::opt_dtor,
+ nullptr
+};
+
//-------------------------------------------------------------------------
// plugins
//-------------------------------------------------------------------------
const BaseApi* ips_http_num_headers = &num_headers_api.base;
const BaseApi* ips_http_num_trailers = &num_trailers_api.base;
-
+const BaseApi* ips_http_num_cookies = &num_cookies_api.base;
#include "http_enum.h"
#include "ips_http.h"
-enum NumHdrsPsIdx { NUM_HDRS_PSI_HDRS, NUM_HDRS_PSI_TRAILERS, NUM_HDRS_PSI_MAX };
+enum NumHdrsPsIdx { NUM_HDRS_PSI_HDRS, NUM_HDRS_PSI_TRAILERS, NUM_HDRS_PSI_COOKIES, NUM_HDRS_PSI_MAX };
class HttpNumHdrsRuleOptModule : public HttpRuleOptModule
{