(vba) macro data embedded in MS office files. It requires decompress_zip
and decompress_vba options enabled.
-===== num_headers and num_trailers
+===== http_num_headers and http_num_trailers
These rule options are used to check the number of headers and
trailers, respectively. Checks available: equal to "=" or just value,
http_event.h
http_js_norm.cc
http_js_norm.h
+ ips_http_buffer.cc
+ ips_http_buffer.h
+ ips_http_num_hdrs.cc
+ ips_http_num_hdrs.h
+ ips_http_param.cc
+ ips_http_param.h
+ ips_http_version.cc
+ ips_http_version.h
)
#if (STATIC_INSPECTORS)
Then we return to #1 as the next chunk begins. In particular extra separators beyond the two
expected are attributed to the beginning of the next chunk.
+Rule options:
+
+HttpIpsOption is the base class for http rule options. It supports the commonly used parameters:
+field, request, with_body, with_header and with_trailer. HttpBufferIpsOption is a rule option that
+sets a buffer. It implements most of the rule options.
+
Test tool usage instructions:
The HI test tool consists of two features. test_output provides extensive information about the
uint32_t c = sub_id & 0xFFFFFFFF;
uint32_t d = form >> 32;
uint32_t e = form & 0xFFFFFFFF;
- uint32_t f = 0;
mix(a,b,c);
- if (param)
- f = param->is_nocase() ? 1 : 0;
- mix(d,e,f);
- mix(a,c,f);
- if (param)
- mix_str(a,c,f,param->c_str(),param->length());
- finalize(a,c,f);
- return f;
+ mix(d,e,a);
+ finalize(d,e,a);
+ return d;
}
bool HttpBufferInfo::operator==(const HttpBufferInfo& rhs) const
{
- bool param_match = false;
-
- if (param && rhs.param)
- {
- HttpParam& lhs_param = *param;
- HttpParam& rhs_param = *rhs.param;
-
- param_match = (lhs_param == rhs_param);
- }
- else if (!param && !rhs.param)
- {
- param_match = true;
- }
-
- return type == rhs.type &&
- sub_id == rhs.sub_id &&
- form == rhs.form &&
- param_match;
+ return (type == rhs.type &&
+ sub_id == rhs.sub_id &&
+ form == rhs.form);
}
#ifndef HTTP_BUFFER_INFO_H
#define HTTP_BUFFER_INFO_H
-#include <string>
-
-#include "http_enum.h"
-#include "http_param.h"
-
class HttpBufferInfo
{
public:
HttpBufferInfo(unsigned type_, uint64_t sub_id_ = 0, uint64_t form_ = 0)
: type(type_), sub_id(sub_id_), form(form_) {}
- HttpBufferInfo(unsigned type_, uint64_t sub_id_, uint64_t form_,
- const std::string& param_str, bool nocase)
- : type(type_), sub_id(sub_id_), form(form_)
- {
- if (param_str.length() > 0)
- param = new HttpParam(param_str, nocase);
- }
-
- ~HttpBufferInfo()
- { delete param; }
-
uint32_t hash() const;
bool operator==(const HttpBufferInfo& rhs) const;
public:
- unsigned type;
- uint64_t sub_id;
- uint64_t form;
- HttpParam* param = nullptr;
+ const unsigned type;
+ const uint64_t sub_id;
+ const uint64_t form;
};
#endif
#include "http_msg_request.h"
#include "http_msg_status.h"
#include "http_msg_trailer.h"
+#include "http_param.h"
#include "http_test_manager.h"
using namespace snort;
bool HttpInspect::get_buf(unsigned id, Packet* p, InspectionBuffer& b)
{
- Cursor c;
HttpBufferInfo buffer_info(id);
- const Field& http_buffer = http_get_buf(c, p, buffer_info);
+ const Field& http_buffer = http_get_buf(p, buffer_info);
if (http_buffer.length() <= 0)
return false;
return true;
}
-const Field& HttpInspect::http_get_buf(Cursor& c, Packet* p,
- const HttpBufferInfo& buffer_info) const
+const Field& HttpInspect::http_get_buf(Packet* p, const HttpBufferInfo& buffer_info) const
+{
+ HttpMsgSection* const current_section = HttpContextData::get_snapshot(p);
+
+ if (current_section == nullptr)
+ return Field::FIELD_NULL;
+
+ return current_section->get_classic_buffer(buffer_info);
+}
+
+const Field& HttpInspect::http_get_param_buf(Cursor& c, Packet* p,
+ const HttpParam& param) const
{
HttpMsgSection* const current_section = HttpContextData::get_snapshot(p);
if (current_section == nullptr)
return Field::FIELD_NULL;
- return current_section->get_classic_buffer(c, buffer_info);
+ return current_section->get_param_buffer(c, param);
}
int32_t HttpInspect::http_get_num_headers(Packet* p,
return current_section->get_num_headers(buffer_info);
}
-VersionId HttpInspect::http_get_version_id(Packet* p) const
+VersionId HttpInspect::http_get_version_id(Packet* p,
+ const HttpBufferInfo& buffer_info) const
{
const HttpMsgSection* const current_section = HttpContextData::get_snapshot(p);
if (current_section == nullptr)
return VERS__NOT_PRESENT;
- return current_section->get_version_id();
+ return current_section->get_version_id(buffer_info);
}
bool HttpInspect::get_fp_buf(InspectionBuffer::Type ibt, Packet* p, InspectionBuffer& b)
#include "http_stream_splitter.h"
class HttpApi;
+class HttpParam;
class HttpInspect : public snort::Inspector
{
bool get_buf(snort::InspectionBuffer::Type ibt, snort::Packet* p,
snort::InspectionBuffer& b) override;
bool get_buf(unsigned id, snort::Packet* p, snort::InspectionBuffer& b) override;
- const Field& http_get_buf(Cursor& c, snort::Packet* p,
- const HttpBufferInfo& buffer_info) const;
+ const Field& http_get_buf(snort::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;
- HttpEnums::VersionId http_get_version_id(snort::Packet* p) const;
+ HttpEnums::VersionId http_get_version_id(snort::Packet* p,
+ const HttpBufferInfo& buffer_info) const;
bool get_fp_buf(snort::InspectionBuffer::Type ibt, snort::Packet* p,
snort::InspectionBuffer& b) override;
bool configure(snort::SnortConfig*) override;
const Field& HttpMsgSection::get_classic_buffer(unsigned id, uint64_t sub_id, uint64_t form)
{
- Cursor c;
HttpBufferInfo buffer_info(id, sub_id, form);
- return get_classic_buffer(c, buffer_info);
+ return get_classic_buffer(buffer_info);
}
-const Field& HttpMsgSection::get_classic_buffer(Cursor& c, const HttpBufferInfo& buf)
+const Field& HttpMsgSection::get_classic_buffer(const HttpBufferInfo& buf)
{
// buffer_side replaces source_id for buffers that support the request option
const SourceId buffer_side = (buf.form & FORM_REQUEST) ? SRC_CLIENT : source_id;
{
return (request != nullptr) ? request->get_method() : Field::FIELD_NULL;
}
- case HTTP_BUFFER_PARAM:
- {
- if (buf.param == nullptr || request == nullptr)
- return Field::FIELD_NULL;
-
- HttpUri* query = request->get_http_uri();
- HttpMsgBody* body = (source_id == SRC_CLIENT) ? get_body() : nullptr;
-
- if (query == nullptr && body == nullptr)
- return Field::FIELD_NULL;
-
- const HttpParaList::UriParam& uri_config = params->uri_param;
-
- ParameterMap& query_params = request->get_query_params();
- ParameterMap& body_params = request->get_body_params();
-
- // cache lookup
- HttpParam& param = *buf.param;
- ParameterData& query_data = query_params[param.str_upper()];
- ParameterData& body_data = body_params[param.str_upper()];
-
- if (!query_data.parsed && query != nullptr)
- {
- // query has not been parsed for this parameter
- const Field& rq = query->get_query();
- const Field& nq = query->get_norm_query();
-
- if (rq.length() > 0 && nq.length() > 0)
- {
- HttpQueryParser parser(rq.start(), rq.length(),
- nq.start(), nq.length(), uri_config,
- session_data, source_id);
-
- parser.parse(param, query_data);
- query_data.parsed = true;
- }
- }
-
- if (!body_data.parsed && body != nullptr)
- {
- // body has not been parsed for this parameter
- const Field& rb = body->get_detect_data();
- const Field& nb = body->get_classic_client_body();
-
- if (rb.length() > 0 && nb.length() > 0 && body->is_first())
- {
- HttpQueryParser parser(rb.start(), rb.length(),
- nb.start(), nb.length(), uri_config,
- session_data, source_id);
-
- parser.parse(param, body_data);
- body_data.parsed = true;
- }
- }
-
- KeyValueVec& query_kv = query_data.kv_vec;
- KeyValueVec& body_kv = body_data.kv_vec;
-
- unsigned num_query_params = query_kv.size();
- unsigned num_body_params = body_kv.size();
-
- if (num_query_params == 0 && num_body_params == 0)
- return Field::FIELD_NULL;
-
- // get data stored on the cursor
- HttpCursorData* cd = (HttpCursorData*)c.get_data(HttpCursorData::id);
-
- if (!cd)
- {
- cd = new HttpCursorData();
- c.set_data(cd);
- }
-
- // save the parameter count on the cursor
- cd->num_query_params = num_query_params;
- cd->num_body_params = num_body_params;
-
- unsigned& query_index = cd->query_index;
- unsigned& body_index = cd->body_index;
-
- while (query_index < num_query_params)
- {
- KeyValue* fields = query_kv[query_index];
-
- Field& key = fields->key;
- Field& value = fields->value;
-
- ++query_index;
-
- if (param.is_nocase())
- return value;
-
- if (!memcmp(key.start(), param.c_str(), key.length()))
- return value;
- }
-
- while (body_index < num_body_params)
- {
- KeyValue* fields = body_kv[body_index];
-
- Field& key = fields->key;
- Field& value = fields->value;
-
- ++body_index;
-
- if (param.is_nocase())
- return value;
-
- if (!memcmp(key.start(), param.c_str(), key.length()))
- return value;
- }
-
- return Field::FIELD_NULL;
- }
case HTTP_BUFFER_RAW_BODY:
{
return (get_body() != nullptr) ? get_body()->msg_text : Field::FIELD_NULL;
}
}
+const Field& HttpMsgSection::get_param_buffer(Cursor& c, const HttpParam& param)
+{
+ if (request == nullptr)
+ return Field::FIELD_NULL;
+
+ HttpUri* query = request->get_http_uri();
+ HttpMsgBody* body = (source_id == SRC_CLIENT) ? get_body() : nullptr;
+
+ if (query == nullptr && body == nullptr)
+ return Field::FIELD_NULL;
+
+ const HttpParaList::UriParam& uri_config = params->uri_param;
+
+ ParameterMap& query_params = request->get_query_params();
+ ParameterMap& body_params = request->get_body_params();
+
+ // cache lookup
+ ParameterData& query_data = query_params[param.str_upper()];
+ ParameterData& body_data = body_params[param.str_upper()];
+
+ if (!query_data.parsed && query != nullptr)
+ {
+ // query has not been parsed for this parameter
+ const Field& rq = query->get_query();
+ const Field& nq = query->get_norm_query();
+
+ if (rq.length() > 0 && nq.length() > 0)
+ {
+ HttpQueryParser parser(rq.start(), rq.length(),
+ nq.start(), nq.length(), uri_config,
+ session_data, source_id);
+
+ parser.parse(param, query_data);
+ query_data.parsed = true;
+ }
+ }
+
+ if (!body_data.parsed && body != nullptr)
+ {
+ // body has not been parsed for this parameter
+ const Field& rb = body->get_detect_data();
+ const Field& nb = body->get_classic_client_body();
+
+ if (rb.length() > 0 && nb.length() > 0 && body->is_first())
+ {
+ HttpQueryParser parser(rb.start(), rb.length(),
+ nb.start(), nb.length(), uri_config,
+ session_data, source_id);
+
+ parser.parse(param, body_data);
+ body_data.parsed = true;
+ }
+ }
+
+ KeyValueVec& query_kv = query_data.kv_vec;
+ KeyValueVec& body_kv = body_data.kv_vec;
+
+ unsigned num_query_params = query_kv.size();
+ unsigned num_body_params = body_kv.size();
+
+ if (num_query_params == 0 && num_body_params == 0)
+ return Field::FIELD_NULL;
+
+ // get data stored on the cursor
+ HttpCursorData* cd = (HttpCursorData*)c.get_data(HttpCursorData::id);
+
+ if (!cd)
+ {
+ cd = new HttpCursorData();
+ c.set_data(cd);
+ }
+
+ // save the parameter count on the cursor
+ cd->num_query_params = num_query_params;
+ cd->num_body_params = num_body_params;
+
+ unsigned& query_index = cd->query_index;
+ unsigned& body_index = cd->body_index;
+
+ while (query_index < num_query_params)
+ {
+ KeyValue* fields = query_kv[query_index];
+
+ Field& key = fields->key;
+ Field& value = fields->value;
+
+ ++query_index;
+
+ if (param.is_nocase())
+ return value;
+
+ if (!memcmp(key.start(), param.c_str(), key.length()))
+ return value;
+ }
+
+ while (body_index < num_body_params)
+ {
+ KeyValue* fields = body_kv[body_index];
+
+ Field& key = fields->key;
+ Field& value = fields->value;
+
+ ++body_index;
+
+ if (param.is_nocase())
+ return value;
+
+ if (!memcmp(key.start(), param.c_str(), key.length()))
+ return value;
+ }
+
+ return Field::FIELD_NULL;
+}
+
int32_t HttpMsgSection::get_num_headers(const HttpBufferInfo& buf) const
{
// buffer_side replaces source_id for buffers that support the request option
return head->get_num_headers();
}
+VersionId HttpMsgSection::get_version_id(const HttpBufferInfo& buf) const
+{
+ // buffer_side replaces source_id for buffers that support the request option
+ const SourceId buffer_side = (buf.form & FORM_REQUEST) ? SRC_CLIENT : source_id;
+ HttpMsgStart* start = (buffer_side == SRC_CLIENT) ?
+ (HttpMsgStart*)request : (HttpMsgStart*)status;
+
+ return (start != nullptr) ? start->get_version_id() : VERS__NOT_PRESENT;
+}
+
void HttpMsgSection::get_related_sections()
{
// When a message section is created these relationships become fixed so we make copies for
#include "http_field.h"
#include "http_flow_data.h"
#include "http_module.h"
+#include "http_param.h"
#include "http_transaction.h"
//-------------------------------------------------------------------------
virtual void update_flow() = 0;
const Field& get_classic_buffer(unsigned id, uint64_t sub_id, uint64_t form);
- const Field& get_classic_buffer(Cursor& c, const HttpBufferInfo& buf);
+ const Field& get_classic_buffer(const HttpBufferInfo& buf);
+ const Field& get_param_buffer(Cursor& c, const HttpParam& param);
HttpEnums::MethodId get_method_id() const { return method_id; }
uint64_t get_transaction_id() { return trans_num; }
int32_t get_num_headers(const HttpBufferInfo& buf) const;
- HttpEnums::VersionId get_version_id() const { return version_id; }
+ HttpEnums::VersionId get_version_id(const HttpBufferInfo& buf) const;
HttpMsgSection* next = nullptr;
void analyze() override;
bool detection_required() const override { return false; }
const Field& get_version() const { return version; }
+ HttpEnums::VersionId get_version_id() const { return version_id; }
protected:
HttpMsgStart(const uint8_t* buffer, const uint16_t buf_size, HttpFlowData* session_data_,
#include "http_flow_data.h"
#include "http_inspect.h"
#include "http_msg_head_shared.h"
-#include "http_param.h"
using namespace snort;
using namespace HttpCommon;
using namespace HttpEnums;
-THREAD_LOCAL std::array<ProfileStats, PSI_MAX> HttpRuleOptModule::http_ps;
-
-const std::string hdrs_num_range = "0:" + std::to_string(HttpMsgHeadShared::MAX_HEADERS);
bool HttpRuleOptModule::begin(const char*, int, SnortConfig*)
{
para_list.reset();
sub_id = 0;
form = 0;
- switch (rule_opt_index)
- {
- case HTTP_BUFFER_RAW_STATUS:
- case HTTP_BUFFER_STAT_CODE:
- case HTTP_BUFFER_STAT_MSG:
- inspect_section = IS_HEADER;
- break;
- case HTTP_BUFFER_COOKIE:
- case HTTP_BUFFER_HEADER:
- case HTTP_BUFFER_METHOD:
- case HTTP_BUFFER_PARAM:
- case HTTP_BUFFER_RAW_COOKIE:
- case HTTP_BUFFER_RAW_HEADER:
- case HTTP_BUFFER_RAW_REQUEST:
- case HTTP_BUFFER_RAW_URI:
- case HTTP_BUFFER_TRUE_IP:
- case HTTP_BUFFER_URI:
- case HTTP_BUFFER_VERSION:
- case HTTP_RANGE_NUM_HDRS:
- case HTTP_VERSION_MATCH:
- inspect_section = IS_FLEX_HEADER;
- break;
- case HTTP_BUFFER_CLIENT_BODY:
- case HTTP_BUFFER_RAW_BODY:
- case BUFFER_JS_DATA:
- inspect_section = IS_BODY;
- break;
- case HTTP_BUFFER_RAW_TRAILER:
- case HTTP_BUFFER_TRAILER:
- case HTTP_RANGE_NUM_TRAILERS:
- inspect_section = IS_TRAILER;
- break;
- default:
- assert(false);
- }
- return true;
-}
-
-static const std::map <std::string, VersionId> VersionStrToEnum =
-{
- { "malformed", VERS__PROBLEMATIC },
- { "other", VERS__OTHER },
- { "1.0", VERS_1_0 },
- { "1.1", VERS_1_1 },
- { "2.0", VERS_2_0 },
- { "0.9", VERS_0_9 }
-};
-
-bool HttpRuleOptModule::parse_version_list(Value& v)
-{
- v.set_first_token();
- std::string tok;
-
- while ( v.get_next_token(tok) )
- {
- if (tok[0] == '"')
- tok.erase(0, 1);
-
- if (tok.length() == 0)
- continue;
-
- if (tok[tok.length()-1] == '"')
- tok.erase(tok.length()-1, 1);
-
- auto iter = VersionStrToEnum.find(tok);
- if (iter == VersionStrToEnum.end())
- {
- ParseError("Unrecognized version %s\n", tok.c_str());
- return false;
- }
-
- para_list.version_flags[iter->second - VERS__MIN] = true;
- }
+ is_trailer_opt = false;
return true;
}
if (sub_id == STAT_OTHER)
ParseError("Unrecognized header field name");
}
- else if (v.is("~param"))
- {
- std::string bc = v.get_string();
- bool negated = false;
- if (!parse_byte_code(bc.c_str(), negated, para_list.param) or negated)
- ParseError("Invalid http_param");
- }
- else if (v.is("nocase"))
- {
- para_list.nocase = true;
- }
else if (v.is("request"))
{
para_list.request = true;
para_list.with_trailer = true;
inspect_section = IS_TRAILER;
}
- else if (v.is("scheme"))
- {
- para_list.scheme = true;
- sub_id = UC_SCHEME;
- }
- else if (v.is("host"))
- {
- para_list.host = true;
- sub_id = UC_HOST;
- }
- else if (v.is("port"))
- {
- para_list.port = true;
- sub_id = UC_PORT;
- }
- else if (v.is("path"))
- {
- para_list.path = true;
- sub_id = UC_PATH;
- }
- else if (v.is("query"))
- {
- para_list.query = true;
- sub_id = UC_QUERY;
- }
- else if (v.is("fragment"))
- {
- para_list.fragment = true;
- sub_id = UC_FRAGMENT;
- }
- else if (v.is("~range"))
- {
- return para_list.range.validate(v.get_string(), hdrs_num_range.c_str());
- }
- else if (v.is("~version_list"))
- {
- return parse_version_list(v);
- }
return true;
}
// Check for option conflicts
if (para_list.with_header + para_list.with_body + para_list.with_trailer > 1)
ParseError("Only specify one with_ option. Use the one that happens last.");
- if (((rule_opt_index == HTTP_BUFFER_TRAILER) || (rule_opt_index == HTTP_BUFFER_RAW_TRAILER) || (rule_opt_index == HTTP_RANGE_NUM_TRAILERS)) &&
- (para_list.with_header || para_list.with_body) &&
+ if ( is_trailer_opt && (para_list.with_header || para_list.with_body) &&
!para_list.request)
ParseError("Trailers with with_ option must also specify request");
- if (para_list.scheme + para_list.host + para_list.port + para_list.path + para_list.query +
- para_list.fragment > 1)
- ParseError("Only specify one part of the URI");
- if (rule_opt_index == HTTP_BUFFER_PARAM && para_list.param.length() == 0)
- ParseError("Specify parameter name");
return true;
}
void HttpRuleOptModule::HttpRuleParaList::reset()
{
field.clear();
- param.clear();
- nocase = false;
request = false;
with_header = false;
with_body = false;
with_trailer = false;
- scheme = false;
- host = false;
- port = false;
- path = false;
- query = false;
- fragment = false;
- range.init();
- version_flags = 0;
}
uint32_t HttpIpsOption::hash() const
uint32_t b = (uint32_t)inspect_section;
uint32_t c = buffer_info.hash();
mix(a,b,c);
- a += range.hash();
- b += (uint32_t)version_flags.to_ulong();
finalize(a,b,c);
return c;
}
const HttpIpsOption& hio = static_cast<const HttpIpsOption&>(ips);
return IpsOption::operator==(ips) &&
inspect_section == hio.inspect_section &&
- buffer_info == hio.buffer_info &&
- range == hio.range &&
- version_flags == hio.version_flags;
-}
-
-bool HttpIpsOption::retry(Cursor& current_cursor, const Cursor&)
-{
- if (buffer_info.type == HTTP_BUFFER_PARAM)
- {
- HttpCursorData* cd = (HttpCursorData*)current_cursor.get_data(HttpCursorData::id);
-
- if (cd)
- return cd->retry();
- }
- return false;
-}
-
-IpsOption::EvalStatus HttpIpsOption::eval_version_match(Packet* p, const HttpInspect* hi)
-{
- const VersionId version = hi->http_get_version_id(p);
-
- if (version_flags[version - HttpEnums::VERS__MIN])
- return MATCH;
-
- return NO_MATCH;
+ buffer_info == hio.buffer_info;
}
-IpsOption::EvalStatus HttpIpsOption::eval(Cursor& c, Packet* p)
+// Verify inspect_section matches. If it does get inspector pointer.
+HttpInspect const* HttpIpsOption::eval_helper(Packet* p)
{
- RuleProfile profile(HttpRuleOptModule::http_ps[psi]);
-
if (!p->flow || !p->flow->gadget || (HttpInspect::get_latest_is(p) == IS_NONE))
- return NO_MATCH;
+ return nullptr;
const bool section_match =
(HttpInspect::get_latest_is(p) == inspect_section) ||
((HttpInspect::get_latest_is(p) == IS_FIRST_BODY) && (inspect_section == IS_BODY)) ||
((HttpInspect::get_latest_src(p) == SRC_CLIENT) && (inspect_section == IS_FLEX_HEADER));
if (!section_match)
- return NO_MATCH;
+ return nullptr;
const Http2FlowData* const h2i_flow_data =
(Http2FlowData*)p->flow->get_flow_data(Http2FlowData::inspector_id);
const HttpInspect* const hi = (h2i_flow_data != nullptr) ?
(HttpInspect*)(p->flow->assistant_gadget) : (HttpInspect*)(p->flow->gadget);
- if (buffer_info.type <= HTTP__BUFFER_MAX)
- {
- const Field& http_buffer = hi->http_get_buf(c, p, buffer_info);
-
- if (http_buffer.length() <= 0)
- return NO_MATCH;
-
- c.set(key, http_buffer.start(), http_buffer.length());
-
- return MATCH;
- }
- else if (buffer_info.type == HTTP_VERSION_MATCH)
- {
- return eval_version_match(p, hi);
- }
- else
- {
- const int32_t num_lines = hi->http_get_num_headers(p, buffer_info);
- if (num_lines != HttpCommon::STAT_NOT_PRESENT && range.eval(num_lines))
- return MATCH;
-
- return NO_MATCH;
- }
-}
-
-//-------------------------------------------------------------------------
-// http_client_body
-//-------------------------------------------------------------------------
-
-#undef IPS_OPT
-#define IPS_OPT "http_client_body"
-#undef IPS_HELP
-#define IPS_HELP "rule option to set the detection cursor to the request body"
-
-static Module* client_body_mod_ctor()
-{
- return new HttpRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_CLIENT_BODY, CAT_SET_BODY,
- PSI_CLIENT_BODY);
-}
-
-static const IpsApi client_body_api =
-{
- {
- PT_IPS_OPTION,
- sizeof(IpsApi),
- IPSAPI_VERSION,
- 1,
- API_RESERVED,
- API_OPTIONS,
- IPS_OPT,
- IPS_HELP,
- client_body_mod_ctor,
- HttpRuleOptModule::mod_dtor
- },
- OPT_TYPE_DETECTION,
- 0, PROTO_BIT__TCP,
- nullptr,
- nullptr,
- nullptr,
- nullptr,
- HttpIpsOption::opt_ctor,
- HttpIpsOption::opt_dtor,
- nullptr
-};
-
-//-------------------------------------------------------------------------
-// http_cookie
-//-------------------------------------------------------------------------
-
-static const Parameter http_cookie_params[] =
-{
- { "request", Parameter::PT_IMPLIED, nullptr, nullptr,
- "match against the cookie from the request message even when examining the response" },
- { "with_header", Parameter::PT_IMPLIED, nullptr, nullptr,
- "this rule is limited to examining HTTP message headers" },
- { "with_body", Parameter::PT_IMPLIED, nullptr, nullptr,
- "parts of this rule examine HTTP message body" },
- { "with_trailer", Parameter::PT_IMPLIED, nullptr, nullptr,
- "parts of this rule examine HTTP message trailers" },
- { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
-};
-
-#undef IPS_OPT
-#define IPS_OPT "http_cookie"
-#undef IPS_HELP
-#define IPS_HELP "rule option to set the detection cursor to the HTTP cookie"
-
-static Module* cookie_mod_ctor()
-{
- return new HttpRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_COOKIE, CAT_SET_COOKIE, PSI_COOKIE,
- http_cookie_params);
-}
-
-static const IpsApi cookie_api =
-{
- {
- PT_IPS_OPTION,
- sizeof(IpsApi),
- IPSAPI_VERSION,
- 1,
- API_RESERVED,
- API_OPTIONS,
- IPS_OPT,
- IPS_HELP,
- cookie_mod_ctor,
- HttpRuleOptModule::mod_dtor
- },
- OPT_TYPE_DETECTION,
- 0, PROTO_BIT__TCP,
- nullptr,
- nullptr,
- nullptr,
- nullptr,
- HttpIpsOption::opt_ctor,
- HttpIpsOption::opt_dtor,
- nullptr
-};
-
-//-------------------------------------------------------------------------
-// http_header
-//-------------------------------------------------------------------------
-
-// FIXIT-M add match_unknown option to look at HEAD__UNKNOWN.
-
-// FIXIT-M if http_header is the fast pattern buffer and the content to be
-// matched appears in the normalized field but not in the raw field
-// detection will fail.
-
-static const Parameter http_header_params[] =
-{
- { "field", Parameter::PT_STRING, nullptr, nullptr,
- "restrict to given header. Header name is case insensitive." },
- { "request", Parameter::PT_IMPLIED, nullptr, nullptr,
- "match against the headers from the request message even when examining the response" },
- { "with_header", Parameter::PT_IMPLIED, nullptr, nullptr,
- "this rule is limited to examining HTTP message headers" },
- { "with_body", Parameter::PT_IMPLIED, nullptr, nullptr,
- "parts of this rule examine HTTP message body" },
- { "with_trailer", Parameter::PT_IMPLIED, nullptr, nullptr,
- "parts of this rule examine HTTP message trailers" },
- { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
-};
-
-#undef IPS_OPT
-#define IPS_OPT "http_header"
-#undef IPS_HELP
-#define IPS_HELP "rule option to set the detection cursor to the normalized headers"
-
-static Module* header_mod_ctor()
-{
- return new HttpRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_HEADER, CAT_SET_HEADER,
- PSI_HEADER, http_header_params);
-}
-
-static const IpsApi header_api =
-{
- {
- PT_IPS_OPTION,
- sizeof(IpsApi),
- IPSAPI_VERSION,
- 1,
- API_RESERVED,
- API_OPTIONS,
- IPS_OPT,
- IPS_HELP,
- header_mod_ctor,
- HttpRuleOptModule::mod_dtor
- },
- OPT_TYPE_DETECTION,
- 0, PROTO_BIT__TCP,
- nullptr,
- nullptr,
- nullptr,
- nullptr,
- HttpIpsOption::opt_ctor,
- HttpIpsOption::opt_dtor,
- nullptr
-};
-
-//-------------------------------------------------------------------------
-// http_method
-//-------------------------------------------------------------------------
-
-static const Parameter http_method_params[] =
-{
- { "with_header", Parameter::PT_IMPLIED, nullptr, nullptr,
- "this rule is limited to examining HTTP message headers" },
- { "with_body", Parameter::PT_IMPLIED, nullptr, nullptr,
- "parts of this rule examine HTTP message body" },
- { "with_trailer", Parameter::PT_IMPLIED, nullptr, nullptr,
- "parts of this rule examine HTTP message trailers" },
- { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
-};
-
-#undef IPS_OPT
-#define IPS_OPT "http_method"
-#undef IPS_HELP
-#define IPS_HELP "rule option to set the detection cursor to the HTTP request method"
-
-static Module* method_mod_ctor()
-{
- return new HttpRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_METHOD, CAT_SET_METHOD, PSI_METHOD,
- http_method_params);
-}
-
-static const IpsApi method_api =
-{
- {
- PT_IPS_OPTION,
- sizeof(IpsApi),
- IPSAPI_VERSION,
- 1,
- API_RESERVED,
- API_OPTIONS,
- IPS_OPT,
- IPS_HELP,
- method_mod_ctor,
- HttpRuleOptModule::mod_dtor
- },
- OPT_TYPE_DETECTION,
- 0, PROTO_BIT__TCP,
- nullptr,
- nullptr,
- nullptr,
- nullptr,
- HttpIpsOption::opt_ctor,
- HttpIpsOption::opt_dtor,
- nullptr
-};
-
-//-------------------------------------------------------------------------
-// http_param
-//-------------------------------------------------------------------------
-
-static const Parameter http_param_params[] =
-{
- { "~param", Parameter::PT_STRING, nullptr, nullptr,
- "parameter to match" },
- { "nocase", Parameter::PT_IMPLIED, nullptr, nullptr,
- "case insensitive match" },
- { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
-};
-
-#undef IPS_OPT
-#define IPS_OPT "http_param"
-#undef IPS_HELP
-#define IPS_HELP "rule option to set the detection cursor to the value of the specified HTTP parameter key which may be in the query or body"
-
-static Module* param_mod_ctor()
-{
- return new HttpRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_PARAM, CAT_SET_OTHER, PSI_PARAM,
- http_param_params);
-}
-
-static const IpsApi param_api =
-{
- {
- PT_IPS_OPTION,
- sizeof(IpsApi),
- IPSAPI_VERSION,
- 1,
- API_RESERVED,
- API_OPTIONS,
- IPS_OPT,
- IPS_HELP,
- param_mod_ctor,
- HttpRuleOptModule::mod_dtor
- },
- OPT_TYPE_DETECTION,
- 0, PROTO_BIT__TCP,
- nullptr,
- nullptr,
- nullptr,
- nullptr,
- HttpIpsOption::opt_ctor,
- HttpIpsOption::opt_dtor,
- nullptr
-};
-
-//-------------------------------------------------------------------------
-// http_raw_body
-//-------------------------------------------------------------------------
-
-#undef IPS_OPT
-#define IPS_OPT "http_raw_body"
-#undef IPS_HELP
-#define IPS_HELP "rule option to set the detection cursor to the unnormalized message body"
-
-static Module* raw_body_mod_ctor()
-{
- return new HttpRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_RAW_BODY, CAT_SET_OTHER,
- PSI_RAW_BODY);
-}
-
-static const IpsApi raw_body_api =
-{
- {
- PT_IPS_OPTION,
- sizeof(IpsApi),
- IPSAPI_VERSION,
- 1,
- API_RESERVED,
- API_OPTIONS,
- IPS_OPT,
- IPS_HELP,
- raw_body_mod_ctor,
- HttpRuleOptModule::mod_dtor
- },
- OPT_TYPE_DETECTION,
- 0, PROTO_BIT__TCP,
- nullptr,
- nullptr,
- nullptr,
- nullptr,
- HttpIpsOption::opt_ctor,
- HttpIpsOption::opt_dtor,
- nullptr
-};
-
-//-------------------------------------------------------------------------
-// http_raw_cookie
-//-------------------------------------------------------------------------
-
-static const Parameter http_raw_cookie_params[] =
-{
- { "request", Parameter::PT_IMPLIED, nullptr, nullptr,
- "match against the cookie from the request message even when examining the response" },
- { "with_header", Parameter::PT_IMPLIED, nullptr, nullptr,
- "this rule is limited to examining HTTP message headers" },
- { "with_body", Parameter::PT_IMPLIED, nullptr, nullptr,
- "parts of this rule examine HTTP message body" },
- { "with_trailer", Parameter::PT_IMPLIED, nullptr, nullptr,
- "parts of this rule examine HTTP message trailers" },
- { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
-};
-
-#undef IPS_OPT
-#define IPS_OPT "http_raw_cookie"
-#undef IPS_HELP
-#define IPS_HELP "rule option to set the detection cursor to the unnormalized cookie"
-
-static Module* raw_cookie_mod_ctor()
-{
- return new HttpRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_RAW_COOKIE, CAT_SET_OTHER,
- PSI_RAW_COOKIE, http_raw_cookie_params);
-}
-
-static const IpsApi raw_cookie_api =
-{
- {
- PT_IPS_OPTION,
- sizeof(IpsApi),
- IPSAPI_VERSION,
- 1,
- API_RESERVED,
- API_OPTIONS,
- IPS_OPT,
- IPS_HELP,
- raw_cookie_mod_ctor,
- HttpRuleOptModule::mod_dtor
- },
- OPT_TYPE_DETECTION,
- 0, PROTO_BIT__TCP,
- nullptr,
- nullptr,
- nullptr,
- nullptr,
- HttpIpsOption::opt_ctor,
- HttpIpsOption::opt_dtor,
- nullptr
-};
-
-//-------------------------------------------------------------------------
-// http_raw_header
-//-------------------------------------------------------------------------
-
-static const Parameter http_raw_header_params[] =
-{
- { "field", Parameter::PT_STRING, nullptr, nullptr,
- "restrict to given header. Header name is case insensitive." },
- { "request", Parameter::PT_IMPLIED, nullptr, nullptr,
- "match against the headers from the request message even when examining the response" },
- { "with_header", Parameter::PT_IMPLIED, nullptr, nullptr,
- "this rule is limited to examining HTTP message headers" },
- { "with_body", Parameter::PT_IMPLIED, nullptr, nullptr,
- "parts of this rule examine HTTP message body" },
- { "with_trailer", Parameter::PT_IMPLIED, nullptr, nullptr,
- "parts of this rule examine HTTP message trailers" },
- { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
-};
-
-#undef IPS_OPT
-#define IPS_OPT "http_raw_header"
-#undef IPS_HELP
-#define IPS_HELP "rule option to set the detection cursor to the unnormalized headers"
-
-static Module* raw_header_mod_ctor()
-{
- return new HttpRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_RAW_HEADER, CAT_SET_RAW_HEADER,
- PSI_RAW_HEADER, http_raw_header_params);
+ return hi;
}
-static const IpsApi raw_header_api =
-{
- {
- PT_IPS_OPTION,
- sizeof(IpsApi),
- IPSAPI_VERSION,
- 1,
- API_RESERVED,
- API_OPTIONS,
- IPS_OPT,
- IPS_HELP,
- raw_header_mod_ctor,
- HttpRuleOptModule::mod_dtor
- },
- OPT_TYPE_DETECTION,
- 0, PROTO_BIT__TCP,
- nullptr,
- nullptr,
- nullptr,
- nullptr,
- HttpIpsOption::opt_ctor,
- HttpIpsOption::opt_dtor,
- nullptr
-};
-
-//-------------------------------------------------------------------------
-// http_raw_request
-//-------------------------------------------------------------------------
-
-static const Parameter http_raw_request_params[] =
-{
- { "with_header", Parameter::PT_IMPLIED, nullptr, nullptr,
- "this rule is limited to examining HTTP message headers" },
- { "with_body", Parameter::PT_IMPLIED, nullptr, nullptr,
- "parts of this rule examine HTTP message body" },
- { "with_trailer", Parameter::PT_IMPLIED, nullptr, nullptr,
- "parts of this rule examine HTTP message trailers" },
- { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
-};
-
-#undef IPS_OPT
-#define IPS_OPT "http_raw_request"
-#undef IPS_HELP
-#define IPS_HELP "rule option to set the detection cursor to the unnormalized request line"
-
-static Module* raw_request_mod_ctor()
-{
- return new HttpRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_RAW_REQUEST, CAT_SET_OTHER,
- PSI_RAW_REQUEST, http_raw_request_params);
-}
-
-static const IpsApi raw_request_api =
-{
- {
- PT_IPS_OPTION,
- sizeof(IpsApi),
- IPSAPI_VERSION,
- 1,
- API_RESERVED,
- API_OPTIONS,
- IPS_OPT,
- IPS_HELP,
- raw_request_mod_ctor,
- HttpRuleOptModule::mod_dtor
- },
- OPT_TYPE_DETECTION,
- 0, PROTO_BIT__TCP,
- nullptr,
- nullptr,
- nullptr,
- nullptr,
- HttpIpsOption::opt_ctor,
- HttpIpsOption::opt_dtor,
- nullptr
-};
-
-//-------------------------------------------------------------------------
-// http_raw_status
-//-------------------------------------------------------------------------
-
-static const Parameter http_raw_status_params[] =
-{
- { "with_body", Parameter::PT_IMPLIED, nullptr, nullptr,
- "parts of this rule examine HTTP message body" },
- { "with_trailer", Parameter::PT_IMPLIED, nullptr, nullptr,
- "parts of this rule examine HTTP message trailers" },
- { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
-};
-
-#undef IPS_OPT
-#define IPS_OPT "http_raw_status"
-#undef IPS_HELP
-#define IPS_HELP "rule option to set the detection cursor to the unnormalized status line"
-
-static Module* raw_status_mod_ctor()
-{
- return new HttpRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_RAW_STATUS, CAT_SET_OTHER,
- PSI_RAW_STATUS, http_raw_status_params);
-}
-
-static const IpsApi raw_status_api =
-{
- {
- PT_IPS_OPTION,
- sizeof(IpsApi),
- IPSAPI_VERSION,
- 1,
- API_RESERVED,
- API_OPTIONS,
- IPS_OPT,
- IPS_HELP,
- raw_status_mod_ctor,
- HttpRuleOptModule::mod_dtor
- },
- OPT_TYPE_DETECTION,
- 0, PROTO_BIT__TCP,
- nullptr,
- nullptr,
- nullptr,
- nullptr,
- HttpIpsOption::opt_ctor,
- HttpIpsOption::opt_dtor,
- nullptr
-};
-
-//-------------------------------------------------------------------------
-// http_raw_trailer
-//-------------------------------------------------------------------------
-
-static const Parameter http_raw_trailer_params[] =
-{
- { "field", Parameter::PT_STRING, nullptr, nullptr,
- "restrict to given trailer. Trailer name is case insensitive." },
- { "request", Parameter::PT_IMPLIED, nullptr, nullptr,
- "match against the trailers from the request message even when examining the response" },
- { "with_header", Parameter::PT_IMPLIED, nullptr, nullptr,
- "parts of this rule examine HTTP response message headers (must be combined with request)"
- },
- { "with_body", Parameter::PT_IMPLIED, nullptr, nullptr,
- "parts of this rule examine HTTP response message body (must be combined with request)" },
- { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
-};
-
-#undef IPS_OPT
-#define IPS_OPT "http_raw_trailer"
-#undef IPS_HELP
-#define IPS_HELP "rule option to set the detection cursor to the unnormalized trailers"
-
-static Module* raw_trailer_mod_ctor()
-{
- return new HttpRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_RAW_TRAILER, CAT_SET_RAW_HEADER,
- PSI_RAW_TRAILER, http_raw_trailer_params);
-}
-
-static const IpsApi raw_trailer_api =
-{
- {
- PT_IPS_OPTION,
- sizeof(IpsApi),
- IPSAPI_VERSION,
- 1,
- API_RESERVED,
- API_OPTIONS,
- IPS_OPT,
- IPS_HELP,
- raw_trailer_mod_ctor,
- HttpRuleOptModule::mod_dtor
- },
- OPT_TYPE_DETECTION,
- 0, PROTO_BIT__TCP,
- nullptr,
- nullptr,
- nullptr,
- nullptr,
- HttpIpsOption::opt_ctor,
- HttpIpsOption::opt_dtor,
- nullptr
-};
-
-//-------------------------------------------------------------------------
-// http_raw_uri
-//-------------------------------------------------------------------------
-
-static const Parameter http_raw_uri_params[] =
-{
- { "with_header", Parameter::PT_IMPLIED, nullptr, nullptr,
- "this rule is limited to examining HTTP message headers" },
- { "with_body", Parameter::PT_IMPLIED, nullptr, nullptr,
- "parts of this rule examine HTTP message body" },
- { "with_trailer", Parameter::PT_IMPLIED, nullptr, nullptr,
- "parts of this rule examine HTTP message trailers" },
- { "scheme", Parameter::PT_IMPLIED, nullptr, nullptr,
- "match against scheme section of URI only" },
- { "host", Parameter::PT_IMPLIED, nullptr, nullptr,
- "match against host section of URI only" },
- { "port", Parameter::PT_IMPLIED, nullptr, nullptr,
- "match against port section of URI only" },
- { "path", Parameter::PT_IMPLIED, nullptr, nullptr,
- "match against path section of URI only" },
- { "query", Parameter::PT_IMPLIED, nullptr, nullptr,
- "match against query section of URI only" },
- { "fragment", Parameter::PT_IMPLIED, nullptr, nullptr,
- "match against fragment section of URI only" },
- { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
-};
-
-#undef IPS_OPT
-#define IPS_OPT "http_raw_uri"
-#undef IPS_HELP
-#define IPS_HELP "rule option to set the detection cursor to the unnormalized URI"
-
-static Module* raw_uri_mod_ctor()
-{
- return new HttpRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_RAW_URI, CAT_SET_RAW_KEY,
- PSI_RAW_URI, http_raw_uri_params);
-}
-
-static const IpsApi raw_uri_api =
-{
- {
- PT_IPS_OPTION,
- sizeof(IpsApi),
- IPSAPI_VERSION,
- 1,
- API_RESERVED,
- API_OPTIONS,
- IPS_OPT,
- IPS_HELP,
- raw_uri_mod_ctor,
- HttpRuleOptModule::mod_dtor
- },
- OPT_TYPE_DETECTION,
- 0, PROTO_BIT__TCP,
- nullptr,
- nullptr,
- nullptr,
- nullptr,
- HttpIpsOption::opt_ctor,
- HttpIpsOption::opt_dtor,
- nullptr
-};
-
-//-------------------------------------------------------------------------
-// http_stat_code
-//-------------------------------------------------------------------------
-
-static const Parameter http_stat_code_params[] =
-{
- { "with_body", Parameter::PT_IMPLIED, nullptr, nullptr,
- "parts of this rule examine HTTP message body" },
- { "with_trailer", Parameter::PT_IMPLIED, nullptr, nullptr,
- "parts of this rule examine HTTP message trailers" },
- { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
-};
-
-#undef IPS_OPT
-#define IPS_OPT "http_stat_code"
-#undef IPS_HELP
-#define IPS_HELP "rule option to set the detection cursor to the HTTP status code"
-
-static Module* stat_code_mod_ctor()
-{
- return new HttpRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_STAT_CODE, CAT_SET_STAT_CODE,
- PSI_STAT_CODE, http_stat_code_params);
-}
-
-static const IpsApi stat_code_api =
-{
- {
- PT_IPS_OPTION,
- sizeof(IpsApi),
- IPSAPI_VERSION,
- 1,
- API_RESERVED,
- API_OPTIONS,
- IPS_OPT,
- IPS_HELP,
- stat_code_mod_ctor,
- HttpRuleOptModule::mod_dtor
- },
- OPT_TYPE_DETECTION,
- 0, PROTO_BIT__TCP,
- nullptr,
- nullptr,
- nullptr,
- nullptr,
- HttpIpsOption::opt_ctor,
- HttpIpsOption::opt_dtor,
- nullptr
-};
-
-//-------------------------------------------------------------------------
-// http_stat_msg
-//-------------------------------------------------------------------------
-
-static const Parameter http_stat_msg_params[] =
-{
- { "with_body", Parameter::PT_IMPLIED, nullptr, nullptr,
- "parts of this rule examine HTTP message body" },
- { "with_trailer", Parameter::PT_IMPLIED, nullptr, nullptr,
- "parts of this rule examine HTTP message trailers" },
- { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
-};
-
-#undef IPS_OPT
-#define IPS_OPT "http_stat_msg"
-#undef IPS_HELP
-#define IPS_HELP "rule option to set the detection cursor to the HTTP status message"
-
-static Module* stat_msg_mod_ctor()
-{
- return new HttpRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_STAT_MSG, CAT_SET_STAT_MSG,
- PSI_STAT_MSG, http_stat_msg_params);
-}
-
-static const IpsApi stat_msg_api =
-{
- {
- PT_IPS_OPTION,
- sizeof(IpsApi),
- IPSAPI_VERSION,
- 1,
- API_RESERVED,
- API_OPTIONS,
- IPS_OPT,
- IPS_HELP,
- stat_msg_mod_ctor,
- HttpRuleOptModule::mod_dtor
- },
- OPT_TYPE_DETECTION,
- 0, PROTO_BIT__TCP,
- nullptr,
- nullptr,
- nullptr,
- nullptr,
- HttpIpsOption::opt_ctor,
- HttpIpsOption::opt_dtor,
- nullptr
-};
-
-//-------------------------------------------------------------------------
-// http_trailer
-//-------------------------------------------------------------------------
-
-static const Parameter http_trailer_params[] =
-{
- { "field", Parameter::PT_STRING, nullptr, nullptr, "restrict to given trailer" },
- { "request", Parameter::PT_IMPLIED, nullptr, nullptr,
- "match against the trailers from the request message even when examining the response" },
- { "with_header", Parameter::PT_IMPLIED, nullptr, nullptr,
- "parts of this rule examine HTTP response message headers (must be combined with request)"
- },
- { "with_body", Parameter::PT_IMPLIED, nullptr, nullptr,
- "parts of this rule examine HTTP message body (must be combined with request)" },
- { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
-};
-
-#undef IPS_OPT
-#define IPS_OPT "http_trailer"
-#undef IPS_HELP
-#define IPS_HELP "rule option to set the detection cursor to the normalized trailers"
-
-static Module* trailer_mod_ctor()
-{
- return new HttpRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_TRAILER, CAT_SET_HEADER,
- PSI_TRAILER, http_trailer_params);
-}
-
-static const IpsApi trailer_api =
-{
- {
- PT_IPS_OPTION,
- sizeof(IpsApi),
- IPSAPI_VERSION,
- 1,
- API_RESERVED,
- API_OPTIONS,
- IPS_OPT,
- IPS_HELP,
- trailer_mod_ctor,
- HttpRuleOptModule::mod_dtor
- },
- OPT_TYPE_DETECTION,
- 0, PROTO_BIT__TCP,
- nullptr,
- nullptr,
- nullptr,
- nullptr,
- HttpIpsOption::opt_ctor,
- HttpIpsOption::opt_dtor,
- nullptr
-};
-
-//-------------------------------------------------------------------------
-// http_true_ip
-//-------------------------------------------------------------------------
-
-static const Parameter http_true_ip_params[] =
-{
- { "with_header", Parameter::PT_IMPLIED, nullptr, nullptr,
- "this rule is limited to examining HTTP message headers" },
- { "with_body", Parameter::PT_IMPLIED, nullptr, nullptr,
- "parts of this rule examine HTTP message body" },
- { "with_trailer", Parameter::PT_IMPLIED, nullptr, nullptr,
- "parts of this rule examine HTTP message trailers" },
- { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
-};
-
-#undef IPS_OPT
-#define IPS_OPT "http_true_ip"
-#undef IPS_HELP
-#define IPS_HELP "rule option to set the detection cursor to the final client IP address"
-
-static Module* true_ip_mod_ctor()
-{
- return new HttpRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_TRUE_IP, CAT_SET_OTHER,
- PSI_TRUE_IP, http_true_ip_params);
-}
-
-static const IpsApi true_ip_api =
-{
- {
- PT_IPS_OPTION,
- sizeof(IpsApi),
- IPSAPI_VERSION,
- 1,
- API_RESERVED,
- API_OPTIONS,
- IPS_OPT,
- IPS_HELP,
- true_ip_mod_ctor,
- HttpRuleOptModule::mod_dtor
- },
- OPT_TYPE_DETECTION,
- 0, PROTO_BIT__TCP,
- nullptr,
- nullptr,
- nullptr,
- nullptr,
- HttpIpsOption::opt_ctor,
- HttpIpsOption::opt_dtor,
- nullptr
-};
-
-//-------------------------------------------------------------------------
-// http_uri
-//-------------------------------------------------------------------------
-
-static const Parameter http_uri_params[] =
-{
- { "with_header", Parameter::PT_IMPLIED, nullptr, nullptr,
- "this rule is limited to examining HTTP message headers" },
- { "with_body", Parameter::PT_IMPLIED, nullptr, nullptr,
- "parts of this rule examine HTTP message body" },
- { "with_trailer", Parameter::PT_IMPLIED, nullptr, nullptr,
- "parts of this rule examine HTTP message trailers" },
- { "scheme", Parameter::PT_IMPLIED, nullptr, nullptr,
- "match against scheme section of URI only" },
- { "host", Parameter::PT_IMPLIED, nullptr, nullptr,
- "match against host section of URI only" },
- { "port", Parameter::PT_IMPLIED, nullptr, nullptr,
- "match against port section of URI only" },
- { "path", Parameter::PT_IMPLIED, nullptr, nullptr,
- "match against path section of URI only" },
- { "query", Parameter::PT_IMPLIED, nullptr, nullptr,
- "match against query section of URI only" },
- { "fragment", Parameter::PT_IMPLIED, nullptr, nullptr,
- "match against fragment section of URI only" },
- { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
-};
-
-#undef IPS_OPT
-#define IPS_OPT "http_uri"
-#undef IPS_HELP
-#define IPS_HELP "rule option to set the detection cursor to the normalized URI buffer"
-
-static Module* uri_mod_ctor()
-{
- return new HttpRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_URI, CAT_SET_KEY, PSI_URI,
- http_uri_params);
-}
-
-static const IpsApi uri_api =
-{
- {
- PT_IPS_OPTION,
- sizeof(IpsApi),
- IPSAPI_VERSION,
- 1,
- API_RESERVED,
- API_OPTIONS,
- IPS_OPT,
- IPS_HELP,
- uri_mod_ctor,
- HttpRuleOptModule::mod_dtor
- },
- OPT_TYPE_DETECTION,
- 0, PROTO_BIT__TCP,
- nullptr,
- nullptr,
- nullptr,
- nullptr,
- HttpIpsOption::opt_ctor,
- HttpIpsOption::opt_dtor,
- nullptr
-};
-
-//-------------------------------------------------------------------------
-// http_version
-//-------------------------------------------------------------------------
-
-static const Parameter http_version_params[] =
-{
- { "request", Parameter::PT_IMPLIED, nullptr, nullptr,
- "match against the version from the request message even when examining the response" },
- { "with_header", Parameter::PT_IMPLIED, nullptr, nullptr,
- "this rule is limited to examining HTTP message headers" },
- { "with_body", Parameter::PT_IMPLIED, nullptr, nullptr,
- "parts of this rule examine HTTP message body" },
- { "with_trailer", Parameter::PT_IMPLIED, nullptr, nullptr,
- "parts of this rule examine HTTP message trailers" },
- { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
-};
-
-#undef IPS_OPT
-#define IPS_OPT "http_version"
-#undef IPS_HELP
-#define IPS_HELP "rule option to set the detection cursor to the version buffer"
-
-static Module* version_mod_ctor()
-{
- return new HttpRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_VERSION, CAT_SET_OTHER,
- PSI_VERSION, http_version_params);
-}
-
-static const IpsApi version_api =
-{
- {
- PT_IPS_OPTION,
- sizeof(IpsApi),
- IPSAPI_VERSION,
- 1,
- API_RESERVED,
- API_OPTIONS,
- IPS_OPT,
- IPS_HELP,
- version_mod_ctor,
- HttpRuleOptModule::mod_dtor
- },
- OPT_TYPE_DETECTION,
- 0, PROTO_BIT__TCP,
- nullptr,
- nullptr,
- nullptr,
- nullptr,
- HttpIpsOption::opt_ctor,
- HttpIpsOption::opt_dtor,
- nullptr
-};
-
-//-------------------------------------------------------------------------
-// js_data
-//-------------------------------------------------------------------------
-//
-
-#undef IPS_OPT
-#define IPS_OPT "js_data"
-#undef IPS_HELP
-#define IPS_HELP "rule option to set detection cursor to normalized JavaScript data"
-static Module* js_data_mod_ctor()
-{
- return new HttpRuleOptModule(IPS_OPT, IPS_HELP, BUFFER_JS_DATA, CAT_SET_JS_DATA,
- PSI_JS_DATA);
-}
-
-static const IpsApi js_data_api =
-{
- {
- PT_IPS_OPTION,
- sizeof(IpsApi),
- IPSAPI_VERSION,
- 1,
- API_RESERVED,
- API_OPTIONS,
- IPS_OPT,
- IPS_HELP,
- js_data_mod_ctor,
- HttpRuleOptModule::mod_dtor
- },
- OPT_TYPE_DETECTION,
- 0, PROTO_BIT__TCP,
- nullptr,
- nullptr,
- nullptr,
- nullptr,
- HttpIpsOption::opt_ctor,
- HttpIpsOption::opt_dtor,
- nullptr
-};
-
-//-------------------------------------------------------------------------
-// num_header_lines
-//-------------------------------------------------------------------------
-#undef IPS_OPT
-#define IPS_OPT "num_headers"
-#undef IPS_HELP
-#define IPS_HELP "rule option to perform range check on number of headers"
-
-static const Parameter http_num_hdrs_params[] =
-{
- { "~range", Parameter::PT_INTERVAL, hdrs_num_range.c_str(), 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" },
- { "with_header", Parameter::PT_IMPLIED, nullptr, nullptr,
- "this rule is limited to examining HTTP message headers" },
- { "with_body", Parameter::PT_IMPLIED, nullptr, nullptr,
- "parts of this rule examine HTTP message body" },
- { "with_trailer", Parameter::PT_IMPLIED, nullptr, nullptr,
- "parts of this rule examine HTTP message trailers" },
- { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
-};
-
-static Module* num_hdrs_mod_ctor()
-{
- return new HttpRuleOptModule(IPS_OPT, IPS_HELP, HTTP_RANGE_NUM_HDRS, CAT_SET_OTHER,
- PSI_RANGE_NUM_HDRS, http_num_hdrs_params);
-}
-
-static const IpsApi num_headers_api =
-{
- {
- PT_IPS_OPTION,
- sizeof(IpsApi),
- IPSAPI_VERSION,
- 1,
- API_RESERVED,
- API_OPTIONS,
- IPS_OPT,
- IPS_HELP,
- num_hdrs_mod_ctor,
- HttpRuleOptModule::mod_dtor
- },
- OPT_TYPE_DETECTION,
- 0, PROTO_BIT__TCP,
- nullptr,
- nullptr,
- nullptr,
- nullptr,
- HttpIpsOption::opt_ctor,
- HttpIpsOption::opt_dtor,
- nullptr
-};
-
-//-------------------------------------------------------------------------
-// num_trailer_lines
-//-------------------------------------------------------------------------
-#undef IPS_OPT
-#define IPS_OPT "num_trailers"
-#undef IPS_HELP
-#define IPS_HELP "rule option to perform range check on number of trailers"
-
-static Module* num_trailers_mod_ctor()
-{
- return new HttpRuleOptModule(IPS_OPT, IPS_HELP, HTTP_RANGE_NUM_TRAILERS, CAT_SET_OTHER,
- PSI_RANGE_NUM_TRAILERS, http_num_hdrs_params);
-}
-
-static const IpsApi num_trailers_api =
-{
- {
- PT_IPS_OPTION,
- sizeof(IpsApi),
- IPSAPI_VERSION,
- 1,
- API_RESERVED,
- API_OPTIONS,
- IPS_OPT,
- IPS_HELP,
- num_trailers_mod_ctor,
- HttpRuleOptModule::mod_dtor
- },
- OPT_TYPE_DETECTION,
- 0, PROTO_BIT__TCP,
- nullptr,
- nullptr,
- nullptr,
- nullptr,
- HttpIpsOption::opt_ctor,
- HttpIpsOption::opt_dtor,
- nullptr
-};
-
-//-------------------------------------------------------------------------
-// http_version_match
-//-------------------------------------------------------------------------
-#undef IPS_OPT
-#define IPS_OPT "http_version_match"
-#undef IPS_HELP
-#define IPS_HELP "rule option to match version to listed values"
-
-static const Parameter version_match_params[] =
-{
- { "~version_list", Parameter::PT_STRING, nullptr, nullptr,
- "space-separated list of versions to match" },
- { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
-};
-
-static Module* version_match_mod_ctor()
-{
- return new HttpRuleOptModule(IPS_OPT, IPS_HELP, HTTP_VERSION_MATCH, CAT_SET_OTHER,
- PSI_VERSION_MATCH, version_match_params);
-}
-
-static const IpsApi version_match_api =
-{
- {
- PT_IPS_OPTION,
- sizeof(IpsApi),
- IPSAPI_VERSION,
- 1,
- API_RESERVED,
- API_OPTIONS,
- IPS_OPT,
- IPS_HELP,
- version_match_mod_ctor,
- HttpRuleOptModule::mod_dtor
- },
- OPT_TYPE_DETECTION,
- 0, PROTO_BIT__TCP,
- nullptr,
- nullptr,
- nullptr,
- nullptr,
- HttpIpsOption::opt_ctor,
- HttpIpsOption::opt_dtor,
- nullptr
-};
-
-//-------------------------------------------------------------------------
-// plugins
-//-------------------------------------------------------------------------
-
-const BaseApi* ips_http_client_body = &client_body_api.base;
-const BaseApi* ips_http_cookie = &cookie_api.base;
-const BaseApi* ips_http_header = &header_api.base;
-const BaseApi* ips_http_method = &method_api.base;
-const BaseApi* ips_http_num_headers = &num_headers_api.base;
-const BaseApi* ips_http_num_trailers = &num_trailers_api.base;
-const BaseApi* ips_http_param = ¶m_api.base;
-const BaseApi* ips_http_raw_body = &raw_body_api.base;
-const BaseApi* ips_http_raw_cookie = &raw_cookie_api.base;
-const BaseApi* ips_http_raw_header = &raw_header_api.base;
-const BaseApi* ips_http_raw_request = &raw_request_api.base;
-const BaseApi* ips_http_raw_status = &raw_status_api.base;
-const BaseApi* ips_http_raw_trailer = &raw_trailer_api.base;
-const BaseApi* ips_http_raw_uri = &raw_uri_api.base;
-const BaseApi* ips_http_stat_code = &stat_code_api.base;
-const BaseApi* ips_http_stat_msg = &stat_msg_api.base;
-const BaseApi* ips_http_trailer = &trailer_api.base;
-const BaseApi* ips_http_true_ip = &true_ip_api.base;
-const BaseApi* ips_http_uri = &uri_api.base;
-const BaseApi* ips_http_version = &version_api.base;
-const BaseApi* ips_http_version_match = &version_match_api.base;
-const BaseApi* ips_js_data = &js_data_api.base;
class HttpInspect;
-enum PsIdx { PSI_CLIENT_BODY, PSI_COOKIE, PSI_HEADER, PSI_METHOD, PSI_PARAM,
- PSI_RAW_BODY, PSI_RAW_COOKIE, PSI_RAW_HEADER, PSI_RAW_REQUEST, PSI_RAW_STATUS,
- PSI_RAW_TRAILER, PSI_RAW_URI, PSI_STAT_CODE, PSI_STAT_MSG, PSI_TRAILER,
- PSI_TRUE_IP, PSI_URI, PSI_VERSION, PSI_JS_DATA, PSI_VBA_DATA,
- PSI_RANGE_NUM_HDRS, PSI_RANGE_NUM_TRAILERS, PSI_VERSION_MATCH, PSI_MAX };
-
class HttpRuleOptModule : public snort::Module
{
public:
HttpRuleOptModule(const char* key_, const char* help, HttpEnums::HTTP_RULE_OPT rule_opt_index_,
- snort::CursorActionType cat_, PsIdx psi_)
- : snort::Module(key_, help), key(key_), rule_opt_index(rule_opt_index_),
- cat(cat_), psi(psi_) {}
+ snort::CursorActionType cat_)
+ : snort::Module(key_, help), rule_opt_index(rule_opt_index_), key(key_),
+ cat(cat_) {}
HttpRuleOptModule(const char* key_, const char* help, HttpEnums::HTTP_RULE_OPT rule_opt_index_,
- snort::CursorActionType cat_, PsIdx psi_, const snort::Parameter params[])
- : snort::Module(key_, help, params), key(key_), rule_opt_index(rule_opt_index_),
- cat(cat_), psi(psi_) {}
- snort::ProfileStats* get_profile() const override { return &http_ps[psi]; }
+ snort::CursorActionType cat_, const snort::Parameter params[])
+ : snort::Module(key_, help, params), rule_opt_index(rule_opt_index_),
+ key(key_), cat(cat_) {}
+ snort::ProfileStats* get_profile() const = 0;
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;
Usage get_usage() const override
{ return DETECT; }
+protected:
+ HttpEnums::InspectSection inspect_section;
+ const HttpEnums::HTTP_RULE_OPT rule_opt_index;
+ const char* const key;
+ uint64_t sub_id;
+ bool is_trailer_opt; // used by ::end for with_* validation
+
private:
friend class HttpIpsOption;
- static THREAD_LOCAL std::array<snort::ProfileStats, PsIdx::PSI_MAX> http_ps;
- static const int version_size = HttpEnums::VERS__MAX - HttpEnums::VERS__MIN + 1;
struct HttpRuleParaList
{
public:
std::string field; // provide buffer containing specific header field
- std::string param; // provide buffer containing specific parameter
- bool nocase; // case insensitive match
bool request; // provide buffer from request not response
bool with_header; // provide buffer with a later section than it appears in
bool with_body;
bool with_trailer;
- bool scheme; // provide buffer with one of the six URI subcomponents
- bool host;
- bool port;
- bool path;
- bool query;
- bool fragment;
- snort::RangeCheck range;
- std::bitset<version_size> version_flags;
void reset();
};
- const char* const key;
- const HttpEnums::HTTP_RULE_OPT rule_opt_index;
const snort::CursorActionType cat;
- const PsIdx psi;
-
HttpRuleParaList para_list;
- HttpEnums::InspectSection inspect_section;
- uint64_t sub_id;
uint64_t form;
-
- bool parse_version_list(snort::Value& v);
};
class HttpIpsOption : public snort::IpsOption
{
public:
- HttpIpsOption(const HttpRuleOptModule* cm) :
- snort::IpsOption(cm->key, RULE_OPTION_TYPE_BUFFER_SET),
- key(cm->key), cat(cm->cat), psi(cm->psi),
- inspect_section(cm->inspect_section),
- buffer_info(cm->rule_opt_index, cm->sub_id, cm->form,
- cm->para_list.param, cm->para_list.nocase), range(cm->para_list.range),
- version_flags(cm->para_list.version_flags){}
+ HttpIpsOption(const HttpRuleOptModule* cm, option_type_t type) :
+ snort::IpsOption(cm->key, type),
+ buffer_info(cm->rule_opt_index, cm->sub_id, cm->form),
+ cat(cm->cat), inspect_section(cm->inspect_section) {}
snort::CursorActionType get_cursor_type() const override { return cat; }
- EvalStatus eval(Cursor&, snort::Packet*) override;
+ EvalStatus eval(Cursor&, snort::Packet*) = 0;
uint32_t hash() const override;
bool operator==(const snort::IpsOption& ips) const override;
- bool retry(Cursor&, const Cursor&) override;
- static IpsOption* opt_ctor(snort::Module* m, OptTreeNode*)
- { return new HttpIpsOption((HttpRuleOptModule*)m); }
- static void opt_dtor(snort::IpsOption* p) { delete p; }
+
+protected:
+ const HttpBufferInfo buffer_info;
+
+ HttpInspect const* eval_helper(snort::Packet* p);
private:
- const char* const key;
const snort::CursorActionType cat;
- const PsIdx psi;
const HttpEnums::InspectSection inspect_section;
- HttpBufferInfo buffer_info;
- const snort::RangeCheck range;
- const std::bitset<HttpRuleOptModule::version_size> version_flags;
-
- IpsOption::EvalStatus eval_version_match(snort::Packet* p, const HttpInspect* hi);
};
#endif
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2022-2022 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation. You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//--------------------------------------------------------------------------
+// ips_http_buffer.cc author Maya Dagon <mdagon@cisco.com>
+// Refactored from ips_http.cc author Tom Peters <thopeter@cisco.com>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "ips_http_buffer.h"
+
+#include "framework/cursor.h"
+#include "hash/hash_key_operations.h"
+#include "log/messages.h"
+#include "parser/parse_utils.h"
+#include "protocols/packet.h"
+
+#include "http_common.h"
+#include "http_enum.h"
+#include "http_inspect.h"
+
+using namespace snort;
+using namespace HttpCommon;
+using namespace HttpEnums;
+
+THREAD_LOCAL std::array<ProfileStats, BUFFER_PSI_MAX> HttpBufferRuleOptModule::http_buffer_ps;
+
+bool HttpBufferRuleOptModule::begin(const char*, int, SnortConfig*)
+{
+ HttpRuleOptModule::begin(nullptr, 0, nullptr);
+ scheme = false;
+ host = false;
+ port = false;
+ path = false;
+ query = false;
+ fragment = false;
+
+ switch (rule_opt_index)
+ {
+ case HTTP_BUFFER_RAW_STATUS:
+ case HTTP_BUFFER_STAT_CODE:
+ case HTTP_BUFFER_STAT_MSG:
+ inspect_section = IS_HEADER;
+ break;
+ case HTTP_BUFFER_COOKIE:
+ case HTTP_BUFFER_HEADER:
+ case HTTP_BUFFER_METHOD:
+ case HTTP_BUFFER_RAW_COOKIE:
+ case HTTP_BUFFER_RAW_HEADER:
+ case HTTP_BUFFER_RAW_REQUEST:
+ case HTTP_BUFFER_RAW_URI:
+ case HTTP_BUFFER_TRUE_IP:
+ case HTTP_BUFFER_URI:
+ case HTTP_BUFFER_VERSION:
+ inspect_section = IS_FLEX_HEADER;
+ break;
+ case HTTP_BUFFER_CLIENT_BODY:
+ case HTTP_BUFFER_RAW_BODY:
+ case BUFFER_JS_DATA:
+ inspect_section = IS_BODY;
+ break;
+ case HTTP_BUFFER_RAW_TRAILER:
+ case HTTP_BUFFER_TRAILER:
+ inspect_section = IS_TRAILER;
+ is_trailer_opt = true;
+ break;
+ default:
+ assert(false);
+ }
+ return true;
+}
+
+
+bool HttpBufferRuleOptModule::set(const char*, Value& v, SnortConfig*)
+{
+ if (v.is("scheme"))
+ {
+ scheme = true;
+ sub_id = UC_SCHEME;
+ }
+ else if (v.is("host"))
+ {
+ host = true;
+ sub_id = UC_HOST;
+ }
+ else if (v.is("port"))
+ {
+ port = true;
+ sub_id = UC_PORT;
+ }
+ else if (v.is("path"))
+ {
+ path = true;
+ sub_id = UC_PATH;
+ }
+ else if (v.is("query"))
+ {
+ query = true;
+ sub_id = UC_QUERY;
+ }
+ else if (v.is("fragment"))
+ {
+ fragment = true;
+ sub_id = UC_FRAGMENT;
+ }
+ else
+ HttpRuleOptModule::set(nullptr, v, nullptr);
+
+ return true;
+}
+
+
+bool HttpBufferRuleOptModule::end(const char*, int, SnortConfig*)
+{
+ // Check for option conflicts
+ if (scheme + host + port + path + query + fragment > 1)
+ ParseError("Only specify one part of the URI");
+ return HttpRuleOptModule::end(nullptr, 0, nullptr);
+}
+
+
+IpsOption::EvalStatus HttpBufferIpsOption::eval(Cursor& c, Packet* p)
+{
+ RuleProfile profile(HttpBufferRuleOptModule::http_buffer_ps[idx]);
+
+ const HttpInspect* const hi = eval_helper(p);
+ if (hi == nullptr)
+ return NO_MATCH;
+
+ const Field& http_buffer = hi->http_get_buf(p, buffer_info);
+ if (http_buffer.length() <= 0)
+ return NO_MATCH;
+
+ c.set(key, http_buffer.start(), http_buffer.length());
+
+ return MATCH;
+}
+
+
+//-------------------------------------------------------------------------
+// http_client_body
+//-------------------------------------------------------------------------
+
+#undef IPS_OPT
+#define IPS_OPT "http_client_body"
+#undef IPS_HELP
+#define IPS_HELP "rule option to set the detection cursor to the request body"
+
+static Module* client_body_mod_ctor()
+{
+ return new HttpBufferRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_CLIENT_BODY, CAT_SET_BODY,
+ BUFFER_PSI_CLIENT_BODY);
+}
+
+static const IpsApi client_body_api =
+{
+ {
+ PT_IPS_OPTION,
+ sizeof(IpsApi),
+ IPSAPI_VERSION,
+ 1,
+ API_RESERVED,
+ API_OPTIONS,
+ IPS_OPT,
+ IPS_HELP,
+ client_body_mod_ctor,
+ HttpBufferRuleOptModule::mod_dtor
+ },
+ OPT_TYPE_DETECTION,
+ 0, PROTO_BIT__TCP,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ HttpBufferIpsOption::opt_ctor,
+ HttpBufferIpsOption::opt_dtor,
+ nullptr
+};
+
+//-------------------------------------------------------------------------
+// http_cookie
+//-------------------------------------------------------------------------
+
+static const Parameter http_cookie_params[] =
+{
+ { "request", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "match against the cookie from the request message even when examining the response" },
+ { "with_header", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "this rule is limited to examining HTTP message headers" },
+ { "with_body", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "parts of this rule examine HTTP message body" },
+ { "with_trailer", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "parts of this rule examine HTTP message trailers" },
+ { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
+};
+
+#undef IPS_OPT
+#define IPS_OPT "http_cookie"
+#undef IPS_HELP
+#define IPS_HELP "rule option to set the detection cursor to the HTTP cookie"
+
+static Module* cookie_mod_ctor()
+{
+ return new HttpBufferRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_COOKIE, CAT_SET_COOKIE, BUFFER_PSI_COOKIE,
+ http_cookie_params);
+}
+
+static const IpsApi cookie_api =
+{
+ {
+ PT_IPS_OPTION,
+ sizeof(IpsApi),
+ IPSAPI_VERSION,
+ 1,
+ API_RESERVED,
+ API_OPTIONS,
+ IPS_OPT,
+ IPS_HELP,
+ cookie_mod_ctor,
+ HttpBufferRuleOptModule::mod_dtor
+ },
+ OPT_TYPE_DETECTION,
+ 0, PROTO_BIT__TCP,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ HttpBufferIpsOption::opt_ctor,
+ HttpBufferIpsOption::opt_dtor,
+ nullptr
+};
+
+//-------------------------------------------------------------------------
+// http_header
+//-------------------------------------------------------------------------
+
+// FIXIT-M add match_unknown option to look at HEAD__UNKNOWN.
+
+// FIXIT-M if http_header is the fast pattern buffer and the content to be
+// matched appears in the normalized field but not in the raw field
+// detection will fail.
+
+static const Parameter http_header_params[] =
+{
+ { "field", Parameter::PT_STRING, nullptr, nullptr,
+ "restrict to given header. Header name is case insensitive." },
+ { "request", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "match against the headers from the request message even when examining the response" },
+ { "with_header", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "this rule is limited to examining HTTP message headers" },
+ { "with_body", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "parts of this rule examine HTTP message body" },
+ { "with_trailer", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "parts of this rule examine HTTP message trailers" },
+ { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
+};
+
+#undef IPS_OPT
+#define IPS_OPT "http_header"
+#undef IPS_HELP
+#define IPS_HELP "rule option to set the detection cursor to the normalized headers"
+
+static Module* header_mod_ctor()
+{
+ return new HttpBufferRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_HEADER, CAT_SET_HEADER,
+ BUFFER_PSI_HEADER, http_header_params);
+}
+
+static const IpsApi header_api =
+{
+ {
+ PT_IPS_OPTION,
+ sizeof(IpsApi),
+ IPSAPI_VERSION,
+ 1,
+ API_RESERVED,
+ API_OPTIONS,
+ IPS_OPT,
+ IPS_HELP,
+ header_mod_ctor,
+ HttpBufferRuleOptModule::mod_dtor
+ },
+ OPT_TYPE_DETECTION,
+ 0, PROTO_BIT__TCP,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ HttpBufferIpsOption::opt_ctor,
+ HttpBufferIpsOption::opt_dtor,
+ nullptr
+};
+
+//-------------------------------------------------------------------------
+// http_method
+//-------------------------------------------------------------------------
+
+static const Parameter http_method_params[] =
+{
+ { "with_header", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "this rule is limited to examining HTTP message headers" },
+ { "with_body", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "parts of this rule examine HTTP message body" },
+ { "with_trailer", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "parts of this rule examine HTTP message trailers" },
+ { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
+};
+
+#undef IPS_OPT
+#define IPS_OPT "http_method"
+#undef IPS_HELP
+#define IPS_HELP "rule option to set the detection cursor to the HTTP request method"
+
+static Module* method_mod_ctor()
+{
+ return new HttpBufferRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_METHOD, CAT_SET_METHOD, BUFFER_PSI_METHOD,
+ http_method_params);
+}
+
+static const IpsApi method_api =
+{
+ {
+ PT_IPS_OPTION,
+ sizeof(IpsApi),
+ IPSAPI_VERSION,
+ 1,
+ API_RESERVED,
+ API_OPTIONS,
+ IPS_OPT,
+ IPS_HELP,
+ method_mod_ctor,
+ HttpBufferRuleOptModule::mod_dtor
+ },
+ OPT_TYPE_DETECTION,
+ 0, PROTO_BIT__TCP,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ HttpBufferIpsOption::opt_ctor,
+ HttpBufferIpsOption::opt_dtor,
+ nullptr
+};
+
+//-------------------------------------------------------------------------
+// http_raw_body
+//-------------------------------------------------------------------------
+
+#undef IPS_OPT
+#define IPS_OPT "http_raw_body"
+#undef IPS_HELP
+#define IPS_HELP "rule option to set the detection cursor to the unnormalized message body"
+
+static Module* raw_body_mod_ctor()
+{
+ return new HttpBufferRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_RAW_BODY, CAT_SET_OTHER,
+ BUFFER_PSI_RAW_BODY);
+}
+
+static const IpsApi raw_body_api =
+{
+ {
+ PT_IPS_OPTION,
+ sizeof(IpsApi),
+ IPSAPI_VERSION,
+ 1,
+ API_RESERVED,
+ API_OPTIONS,
+ IPS_OPT,
+ IPS_HELP,
+ raw_body_mod_ctor,
+ HttpBufferRuleOptModule::mod_dtor
+ },
+ OPT_TYPE_DETECTION,
+ 0, PROTO_BIT__TCP,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ HttpBufferIpsOption::opt_ctor,
+ HttpBufferIpsOption::opt_dtor,
+ nullptr
+};
+
+//-------------------------------------------------------------------------
+// http_raw_cookie
+//-------------------------------------------------------------------------
+
+static const Parameter http_raw_cookie_params[] =
+{
+ { "request", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "match against the cookie from the request message even when examining the response" },
+ { "with_header", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "this rule is limited to examining HTTP message headers" },
+ { "with_body", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "parts of this rule examine HTTP message body" },
+ { "with_trailer", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "parts of this rule examine HTTP message trailers" },
+ { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
+};
+
+#undef IPS_OPT
+#define IPS_OPT "http_raw_cookie"
+#undef IPS_HELP
+#define IPS_HELP "rule option to set the detection cursor to the unnormalized cookie"
+
+static Module* raw_cookie_mod_ctor()
+{
+ return new HttpBufferRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_RAW_COOKIE, CAT_SET_OTHER,
+ BUFFER_PSI_RAW_COOKIE, http_raw_cookie_params);
+}
+
+static const IpsApi raw_cookie_api =
+{
+ {
+ PT_IPS_OPTION,
+ sizeof(IpsApi),
+ IPSAPI_VERSION,
+ 1,
+ API_RESERVED,
+ API_OPTIONS,
+ IPS_OPT,
+ IPS_HELP,
+ raw_cookie_mod_ctor,
+ HttpBufferRuleOptModule::mod_dtor
+ },
+ OPT_TYPE_DETECTION,
+ 0, PROTO_BIT__TCP,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ HttpBufferIpsOption::opt_ctor,
+ HttpBufferIpsOption::opt_dtor,
+ nullptr
+};
+
+//-------------------------------------------------------------------------
+// http_raw_header
+//-------------------------------------------------------------------------
+
+static const Parameter http_raw_header_params[] =
+{
+ { "field", Parameter::PT_STRING, nullptr, nullptr,
+ "restrict to given header. Header name is case insensitive." },
+ { "request", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "match against the headers from the request message even when examining the response" },
+ { "with_header", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "this rule is limited to examining HTTP message headers" },
+ { "with_body", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "parts of this rule examine HTTP message body" },
+ { "with_trailer", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "parts of this rule examine HTTP message trailers" },
+ { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
+};
+
+#undef IPS_OPT
+#define IPS_OPT "http_raw_header"
+#undef IPS_HELP
+#define IPS_HELP "rule option to set the detection cursor to the unnormalized headers"
+
+static Module* raw_header_mod_ctor()
+{
+ return new HttpBufferRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_RAW_HEADER, CAT_SET_RAW_HEADER,
+ BUFFER_PSI_RAW_HEADER, http_raw_header_params);
+}
+
+static const IpsApi raw_header_api =
+{
+ {
+ PT_IPS_OPTION,
+ sizeof(IpsApi),
+ IPSAPI_VERSION,
+ 1,
+ API_RESERVED,
+ API_OPTIONS,
+ IPS_OPT,
+ IPS_HELP,
+ raw_header_mod_ctor,
+ HttpBufferRuleOptModule::mod_dtor
+ },
+ OPT_TYPE_DETECTION,
+ 0, PROTO_BIT__TCP,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ HttpBufferIpsOption::opt_ctor,
+ HttpBufferIpsOption::opt_dtor,
+ nullptr
+};
+
+//-------------------------------------------------------------------------
+// http_raw_request
+//-------------------------------------------------------------------------
+
+static const Parameter http_raw_request_params[] =
+{
+ { "with_header", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "this rule is limited to examining HTTP message headers" },
+ { "with_body", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "parts of this rule examine HTTP message body" },
+ { "with_trailer", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "parts of this rule examine HTTP message trailers" },
+ { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
+};
+
+#undef IPS_OPT
+#define IPS_OPT "http_raw_request"
+#undef IPS_HELP
+#define IPS_HELP "rule option to set the detection cursor to the unnormalized request line"
+
+static Module* raw_request_mod_ctor()
+{
+ return new HttpBufferRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_RAW_REQUEST, CAT_SET_OTHER,
+ BUFFER_PSI_RAW_REQUEST, http_raw_request_params);
+}
+
+static const IpsApi raw_request_api =
+{
+ {
+ PT_IPS_OPTION,
+ sizeof(IpsApi),
+ IPSAPI_VERSION,
+ 1,
+ API_RESERVED,
+ API_OPTIONS,
+ IPS_OPT,
+ IPS_HELP,
+ raw_request_mod_ctor,
+ HttpBufferRuleOptModule::mod_dtor
+ },
+ OPT_TYPE_DETECTION,
+ 0, PROTO_BIT__TCP,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ HttpBufferIpsOption::opt_ctor,
+ HttpBufferIpsOption::opt_dtor,
+ nullptr
+};
+
+//-------------------------------------------------------------------------
+// http_raw_status
+//-------------------------------------------------------------------------
+
+static const Parameter http_raw_status_params[] =
+{
+ { "with_body", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "parts of this rule examine HTTP message body" },
+ { "with_trailer", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "parts of this rule examine HTTP message trailers" },
+ { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
+};
+
+#undef IPS_OPT
+#define IPS_OPT "http_raw_status"
+#undef IPS_HELP
+#define IPS_HELP "rule option to set the detection cursor to the unnormalized status line"
+
+static Module* raw_status_mod_ctor()
+{
+ return new HttpBufferRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_RAW_STATUS, CAT_SET_OTHER,
+ BUFFER_PSI_RAW_STATUS, http_raw_status_params);
+}
+
+static const IpsApi raw_status_api =
+{
+ {
+ PT_IPS_OPTION,
+ sizeof(IpsApi),
+ IPSAPI_VERSION,
+ 1,
+ API_RESERVED,
+ API_OPTIONS,
+ IPS_OPT,
+ IPS_HELP,
+ raw_status_mod_ctor,
+ HttpBufferRuleOptModule::mod_dtor
+ },
+ OPT_TYPE_DETECTION,
+ 0, PROTO_BIT__TCP,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ HttpBufferIpsOption::opt_ctor,
+ HttpBufferIpsOption::opt_dtor,
+ nullptr
+};
+
+//-------------------------------------------------------------------------
+// http_raw_trailer
+//-------------------------------------------------------------------------
+
+static const Parameter http_raw_trailer_params[] =
+{
+ { "field", Parameter::PT_STRING, nullptr, nullptr,
+ "restrict to given trailer. Trailer name is case insensitive." },
+ { "request", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "match against the trailers from the request message even when examining the response" },
+ { "with_header", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "parts of this rule examine HTTP response message headers (must be combined with request)"
+ },
+ { "with_body", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "parts of this rule examine HTTP response message body (must be combined with request)" },
+ { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
+};
+
+#undef IPS_OPT
+#define IPS_OPT "http_raw_trailer"
+#undef IPS_HELP
+#define IPS_HELP "rule option to set the detection cursor to the unnormalized trailers"
+
+static Module* raw_trailer_mod_ctor()
+{
+ return new HttpBufferRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_RAW_TRAILER, CAT_SET_RAW_HEADER,
+ BUFFER_PSI_RAW_TRAILER, http_raw_trailer_params);
+}
+
+static const IpsApi raw_trailer_api =
+{
+ {
+ PT_IPS_OPTION,
+ sizeof(IpsApi),
+ IPSAPI_VERSION,
+ 1,
+ API_RESERVED,
+ API_OPTIONS,
+ IPS_OPT,
+ IPS_HELP,
+ raw_trailer_mod_ctor,
+ HttpBufferRuleOptModule::mod_dtor
+ },
+ OPT_TYPE_DETECTION,
+ 0, PROTO_BIT__TCP,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ HttpBufferIpsOption::opt_ctor,
+ HttpBufferIpsOption::opt_dtor,
+ nullptr
+};
+
+//-------------------------------------------------------------------------
+// http_raw_uri
+//-------------------------------------------------------------------------
+
+static const Parameter http_raw_uri_params[] =
+{
+ { "with_header", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "this rule is limited to examining HTTP message headers" },
+ { "with_body", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "parts of this rule examine HTTP message body" },
+ { "with_trailer", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "parts of this rule examine HTTP message trailers" },
+ { "scheme", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "match against scheme section of URI only" },
+ { "host", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "match against host section of URI only" },
+ { "port", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "match against port section of URI only" },
+ { "path", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "match against path section of URI only" },
+ { "query", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "match against query section of URI only" },
+ { "fragment", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "match against fragment section of URI only" },
+ { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
+};
+
+#undef IPS_OPT
+#define IPS_OPT "http_raw_uri"
+#undef IPS_HELP
+#define IPS_HELP "rule option to set the detection cursor to the unnormalized URI"
+
+static Module* raw_uri_mod_ctor()
+{
+ return new HttpBufferRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_RAW_URI, CAT_SET_RAW_KEY,
+ BUFFER_PSI_RAW_URI, http_raw_uri_params);
+}
+
+static const IpsApi raw_uri_api =
+{
+ {
+ PT_IPS_OPTION,
+ sizeof(IpsApi),
+ IPSAPI_VERSION,
+ 1,
+ API_RESERVED,
+ API_OPTIONS,
+ IPS_OPT,
+ IPS_HELP,
+ raw_uri_mod_ctor,
+ HttpBufferRuleOptModule::mod_dtor
+ },
+ OPT_TYPE_DETECTION,
+ 0, PROTO_BIT__TCP,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ HttpBufferIpsOption::opt_ctor,
+ HttpBufferIpsOption::opt_dtor,
+ nullptr
+};
+
+//-------------------------------------------------------------------------
+// http_stat_code
+//-------------------------------------------------------------------------
+
+static const Parameter http_stat_code_params[] =
+{
+ { "with_body", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "parts of this rule examine HTTP message body" },
+ { "with_trailer", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "parts of this rule examine HTTP message trailers" },
+ { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
+};
+
+#undef IPS_OPT
+#define IPS_OPT "http_stat_code"
+#undef IPS_HELP
+#define IPS_HELP "rule option to set the detection cursor to the HTTP status code"
+
+static Module* stat_code_mod_ctor()
+{
+ return new HttpBufferRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_STAT_CODE, CAT_SET_STAT_CODE,
+ BUFFER_PSI_STAT_CODE, http_stat_code_params);
+}
+
+static const IpsApi stat_code_api =
+{
+ {
+ PT_IPS_OPTION,
+ sizeof(IpsApi),
+ IPSAPI_VERSION,
+ 1,
+ API_RESERVED,
+ API_OPTIONS,
+ IPS_OPT,
+ IPS_HELP,
+ stat_code_mod_ctor,
+ HttpBufferRuleOptModule::mod_dtor
+ },
+ OPT_TYPE_DETECTION,
+ 0, PROTO_BIT__TCP,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ HttpBufferIpsOption::opt_ctor,
+ HttpBufferIpsOption::opt_dtor,
+ nullptr
+};
+
+//-------------------------------------------------------------------------
+// http_stat_msg
+//-------------------------------------------------------------------------
+
+static const Parameter http_stat_msg_params[] =
+{
+ { "with_body", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "parts of this rule examine HTTP message body" },
+ { "with_trailer", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "parts of this rule examine HTTP message trailers" },
+ { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
+};
+
+#undef IPS_OPT
+#define IPS_OPT "http_stat_msg"
+#undef IPS_HELP
+#define IPS_HELP "rule option to set the detection cursor to the HTTP status message"
+
+static Module* stat_msg_mod_ctor()
+{
+ return new HttpBufferRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_STAT_MSG, CAT_SET_STAT_MSG,
+ BUFFER_PSI_STAT_MSG, http_stat_msg_params);
+}
+
+static const IpsApi stat_msg_api =
+{
+ {
+ PT_IPS_OPTION,
+ sizeof(IpsApi),
+ IPSAPI_VERSION,
+ 1,
+ API_RESERVED,
+ API_OPTIONS,
+ IPS_OPT,
+ IPS_HELP,
+ stat_msg_mod_ctor,
+ HttpBufferRuleOptModule::mod_dtor
+ },
+ OPT_TYPE_DETECTION,
+ 0, PROTO_BIT__TCP,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ HttpBufferIpsOption::opt_ctor,
+ HttpBufferIpsOption::opt_dtor,
+ nullptr
+};
+
+//-------------------------------------------------------------------------
+// http_trailer
+//-------------------------------------------------------------------------
+
+static const Parameter http_trailer_params[] =
+{
+ { "field", Parameter::PT_STRING, nullptr, nullptr, "restrict to given trailer" },
+ { "request", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "match against the trailers from the request message even when examining the response" },
+ { "with_header", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "parts of this rule examine HTTP response message headers (must be combined with request)"
+ },
+ { "with_body", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "parts of this rule examine HTTP message body (must be combined with request)" },
+ { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
+};
+
+#undef IPS_OPT
+#define IPS_OPT "http_trailer"
+#undef IPS_HELP
+#define IPS_HELP "rule option to set the detection cursor to the normalized trailers"
+
+static Module* trailer_mod_ctor()
+{
+ return new HttpBufferRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_TRAILER, CAT_SET_HEADER,
+ BUFFER_PSI_TRAILER, http_trailer_params);
+}
+
+static const IpsApi trailer_api =
+{
+ {
+ PT_IPS_OPTION,
+ sizeof(IpsApi),
+ IPSAPI_VERSION,
+ 1,
+ API_RESERVED,
+ API_OPTIONS,
+ IPS_OPT,
+ IPS_HELP,
+ trailer_mod_ctor,
+ HttpBufferRuleOptModule::mod_dtor
+ },
+ OPT_TYPE_DETECTION,
+ 0, PROTO_BIT__TCP,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ HttpBufferIpsOption::opt_ctor,
+ HttpBufferIpsOption::opt_dtor,
+ nullptr
+};
+
+//-------------------------------------------------------------------------
+// http_true_ip
+//-------------------------------------------------------------------------
+
+static const Parameter http_true_ip_params[] =
+{
+ { "with_header", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "this rule is limited to examining HTTP message headers" },
+ { "with_body", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "parts of this rule examine HTTP message body" },
+ { "with_trailer", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "parts of this rule examine HTTP message trailers" },
+ { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
+};
+
+#undef IPS_OPT
+#define IPS_OPT "http_true_ip"
+#undef IPS_HELP
+#define IPS_HELP "rule option to set the detection cursor to the final client IP address"
+
+static Module* true_ip_mod_ctor()
+{
+ return new HttpBufferRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_TRUE_IP, CAT_SET_OTHER,
+ BUFFER_PSI_TRUE_IP, http_true_ip_params);
+}
+
+static const IpsApi true_ip_api =
+{
+ {
+ PT_IPS_OPTION,
+ sizeof(IpsApi),
+ IPSAPI_VERSION,
+ 1,
+ API_RESERVED,
+ API_OPTIONS,
+ IPS_OPT,
+ IPS_HELP,
+ true_ip_mod_ctor,
+ HttpBufferRuleOptModule::mod_dtor
+ },
+ OPT_TYPE_DETECTION,
+ 0, PROTO_BIT__TCP,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ HttpBufferIpsOption::opt_ctor,
+ HttpBufferIpsOption::opt_dtor,
+ nullptr
+};
+
+//-------------------------------------------------------------------------
+// http_uri
+//-------------------------------------------------------------------------
+
+static const Parameter http_uri_params[] =
+{
+ { "with_header", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "this rule is limited to examining HTTP message headers" },
+ { "with_body", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "parts of this rule examine HTTP message body" },
+ { "with_trailer", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "parts of this rule examine HTTP message trailers" },
+ { "scheme", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "match against scheme section of URI only" },
+ { "host", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "match against host section of URI only" },
+ { "port", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "match against port section of URI only" },
+ { "path", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "match against path section of URI only" },
+ { "query", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "match against query section of URI only" },
+ { "fragment", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "match against fragment section of URI only" },
+ { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
+};
+
+#undef IPS_OPT
+#define IPS_OPT "http_uri"
+#undef IPS_HELP
+#define IPS_HELP "rule option to set the detection cursor to the normalized URI buffer"
+
+static Module* uri_mod_ctor()
+{
+ return new HttpBufferRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_URI, CAT_SET_KEY, BUFFER_PSI_URI,
+ http_uri_params);
+}
+
+static const IpsApi uri_api =
+{
+ {
+ PT_IPS_OPTION,
+ sizeof(IpsApi),
+ IPSAPI_VERSION,
+ 1,
+ API_RESERVED,
+ API_OPTIONS,
+ IPS_OPT,
+ IPS_HELP,
+ uri_mod_ctor,
+ HttpBufferRuleOptModule::mod_dtor
+ },
+ OPT_TYPE_DETECTION,
+ 0, PROTO_BIT__TCP,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ HttpBufferIpsOption::opt_ctor,
+ HttpBufferIpsOption::opt_dtor,
+ nullptr
+};
+
+//-------------------------------------------------------------------------
+// http_version
+//-------------------------------------------------------------------------
+
+static const Parameter http_version_params[] =
+{
+ { "request", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "match against the version from the request message even when examining the response" },
+ { "with_header", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "this rule is limited to examining HTTP message headers" },
+ { "with_body", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "parts of this rule examine HTTP message body" },
+ { "with_trailer", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "parts of this rule examine HTTP message trailers" },
+ { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
+};
+
+#undef IPS_OPT
+#define IPS_OPT "http_version"
+#undef IPS_HELP
+#define IPS_HELP "rule option to set the detection cursor to the version buffer"
+
+static Module* version_mod_ctor()
+{
+ return new HttpBufferRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_VERSION, CAT_SET_OTHER,
+ BUFFER_PSI_VERSION, http_version_params);
+}
+
+static const IpsApi version_api =
+{
+ {
+ PT_IPS_OPTION,
+ sizeof(IpsApi),
+ IPSAPI_VERSION,
+ 1,
+ API_RESERVED,
+ API_OPTIONS,
+ IPS_OPT,
+ IPS_HELP,
+ version_mod_ctor,
+ HttpBufferRuleOptModule::mod_dtor
+ },
+ OPT_TYPE_DETECTION,
+ 0, PROTO_BIT__TCP,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ HttpBufferIpsOption::opt_ctor,
+ HttpBufferIpsOption::opt_dtor,
+ nullptr
+};
+
+//-------------------------------------------------------------------------
+// js_data
+//-------------------------------------------------------------------------
+//
+
+#undef IPS_OPT
+#define IPS_OPT "js_data"
+#undef IPS_HELP
+#define IPS_HELP "rule option to set detection cursor to normalized JavaScript data"
+static Module* js_data_mod_ctor()
+{
+ return new HttpBufferRuleOptModule(IPS_OPT, IPS_HELP, BUFFER_JS_DATA, CAT_SET_JS_DATA,
+ BUFFER_PSI_JS_DATA);
+}
+
+static const IpsApi js_data_api =
+{
+ {
+ PT_IPS_OPTION,
+ sizeof(IpsApi),
+ IPSAPI_VERSION,
+ 1,
+ API_RESERVED,
+ API_OPTIONS,
+ IPS_OPT,
+ IPS_HELP,
+ js_data_mod_ctor,
+ HttpBufferRuleOptModule::mod_dtor
+ },
+ OPT_TYPE_DETECTION,
+ 0, PROTO_BIT__TCP,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ HttpBufferIpsOption::opt_ctor,
+ HttpBufferIpsOption::opt_dtor,
+ nullptr
+};
+
+//-------------------------------------------------------------------------
+// plugins
+//-------------------------------------------------------------------------
+
+const BaseApi* ips_http_client_body = &client_body_api.base;
+const BaseApi* ips_http_cookie = &cookie_api.base;
+const BaseApi* ips_http_header = &header_api.base;
+const BaseApi* ips_http_method = &method_api.base;
+const BaseApi* ips_http_raw_body = &raw_body_api.base;
+const BaseApi* ips_http_raw_cookie = &raw_cookie_api.base;
+const BaseApi* ips_http_raw_header = &raw_header_api.base;
+const BaseApi* ips_http_raw_request = &raw_request_api.base;
+const BaseApi* ips_http_raw_status = &raw_status_api.base;
+const BaseApi* ips_http_raw_trailer = &raw_trailer_api.base;
+const BaseApi* ips_http_raw_uri = &raw_uri_api.base;
+const BaseApi* ips_http_stat_code = &stat_code_api.base;
+const BaseApi* ips_http_stat_msg = &stat_msg_api.base;
+const BaseApi* ips_http_trailer = &trailer_api.base;
+const BaseApi* ips_http_true_ip = &true_ip_api.base;
+const BaseApi* ips_http_uri = &uri_api.base;
+const BaseApi* ips_http_version = &version_api.base;
+const BaseApi* ips_js_data = &js_data_api.base;
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2022-2022 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation. You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//--------------------------------------------------------------------------
+// ips_http_buffer.h author Maya Dagon <mdagon@cisco.com>
+// Refactored from ips_http.h author Tom Peters <thopeter@cisco.com>
+
+#ifndef IPS_HTTP_BUFFER_H
+#define IPS_HTTP_BUFFER_H
+
+#include <array>
+
+#include "profiler/profiler.h"
+#include "framework/ips_option.h"
+#include "framework/module.h"
+
+#include "ips_http.h"
+
+enum BufferPsIdx { BUFFER_PSI_CLIENT_BODY, BUFFER_PSI_COOKIE, BUFFER_PSI_HEADER, BUFFER_PSI_METHOD,
+ BUFFER_PSI_RAW_BODY, BUFFER_PSI_RAW_COOKIE, BUFFER_PSI_RAW_HEADER, BUFFER_PSI_RAW_REQUEST,
+ BUFFER_PSI_RAW_STATUS, BUFFER_PSI_RAW_TRAILER, BUFFER_PSI_RAW_URI, BUFFER_PSI_STAT_CODE,
+ BUFFER_PSI_STAT_MSG, BUFFER_PSI_TRAILER, BUFFER_PSI_TRUE_IP, BUFFER_PSI_URI, BUFFER_PSI_VERSION,
+ BUFFER_PSI_JS_DATA, BUFFER_PSI_VBA_DATA, BUFFER_PSI_MAX };
+
+class HttpBufferRuleOptModule : public HttpRuleOptModule
+{
+public:
+ HttpBufferRuleOptModule(const char* key_, const char* help, HttpEnums::HTTP_RULE_OPT rule_opt_index_,
+ snort::CursorActionType cat_, BufferPsIdx idx_)
+ : HttpRuleOptModule(key_, help, rule_opt_index_, cat_), idx(idx_) {}
+ HttpBufferRuleOptModule(const char* key_, const char* help, HttpEnums::HTTP_RULE_OPT rule_opt_index_,
+ snort::CursorActionType cat_, BufferPsIdx idx_, const snort::Parameter params[])
+ : HttpRuleOptModule(key_, help, rule_opt_index_, cat_, params), idx(idx_) {}
+ snort::ProfileStats* get_profile() const override { return &http_buffer_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;
+ bool end(const char*, int, snort::SnortConfig*) override;
+
+private:
+ friend class HttpBufferIpsOption;
+ static THREAD_LOCAL std::array<snort::ProfileStats, BUFFER_PSI_MAX> http_buffer_ps;
+ const BufferPsIdx idx;
+
+ // URI related params. These affect the sub_id while parsed.
+ // These values are saved to alert on conflicts, only used by ::end
+ bool scheme;
+ bool host;
+ bool port;
+ bool path;
+ bool query;
+ bool fragment;
+};
+
+class HttpBufferIpsOption : public HttpIpsOption
+{
+public:
+ HttpBufferIpsOption(const HttpBufferRuleOptModule* cm) :
+ HttpIpsOption(cm, RULE_OPTION_TYPE_BUFFER_SET), idx(cm->idx),
+ key(cm->key) {}
+ EvalStatus eval(Cursor&, snort::Packet*) override;
+
+ static IpsOption* opt_ctor(snort::Module* m, OptTreeNode*)
+ { return new HttpBufferIpsOption((HttpBufferRuleOptModule*)m); }
+
+ static void opt_dtor(snort::IpsOption* p) { delete p; }
+
+private:
+ const BufferPsIdx idx;
+ const char* const key;
+};
+
+#endif
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2022-2022 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation. You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//--------------------------------------------------------------------------
+// ips_http_num_hdrs.cc author Maya Dagon <mdagon@cisco.com>
+// Refactored from ips_http.cc author Tom Peters <thopeter@cisco.com>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "ips_http_num_hdrs.h"
+
+#include "framework/cursor.h"
+#include "hash/hash_key_operations.h"
+#include "log/messages.h"
+#include "parser/parse_utils.h"
+#include "protocols/packet.h"
+#include "service_inspectors/http2_inspect/http2_flow_data.h"
+
+#include "http_common.h"
+#include "http_enum.h"
+#include "http_flow_data.h"
+#include "http_inspect.h"
+#include "http_msg_head_shared.h"
+
+using namespace snort;
+using namespace HttpCommon;
+using namespace HttpEnums;
+
+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);
+
+bool HttpNumHdrsRuleOptModule::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
+ {
+ inspect_section = IS_TRAILER;
+ is_trailer_opt = true;
+ }
+
+ return true;
+}
+
+bool HttpNumHdrsRuleOptModule::set(const char*, Value& v, SnortConfig*)
+{
+ if (v.is("~range"))
+ return range.validate(v.get_string(), hdrs_num_range.c_str());
+
+ return HttpRuleOptModule::set(nullptr, v, nullptr);
+}
+
+
+uint32_t HttpNumHdrsIpsOption::hash() const
+{
+ uint32_t a = HttpIpsOption::hash();
+ uint32_t b = range.hash();
+ uint32_t c = 0;
+ mix(a,b,c);
+ finalize(a,b,c);
+ return c;
+}
+
+bool HttpNumHdrsIpsOption::operator==(const IpsOption& ips) const
+{
+ const HttpNumHdrsIpsOption& hio = static_cast<const HttpNumHdrsIpsOption&>(ips);
+ return HttpIpsOption::operator==(static_cast<const HttpIpsOption&>(ips)) &&
+ range == hio.range;
+}
+
+IpsOption::EvalStatus HttpNumHdrsIpsOption::eval(Cursor&, Packet* p)
+{
+ RuleProfile profile(HttpNumHdrsRuleOptModule::http_num_hdrs_ps[idx]);
+
+ const HttpInspect* const hi = eval_helper(p);
+ 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))
+ return MATCH;
+
+ return NO_MATCH;
+}
+
+//-------------------------------------------------------------------------
+// num_header_lines
+//-------------------------------------------------------------------------
+#undef IPS_OPT
+#define IPS_OPT "http_num_headers"
+#undef IPS_HELP
+#define IPS_HELP "rule option to perform range check on number of headers"
+
+static const Parameter http_num_hdrs_params[] =
+{
+ { "~range", Parameter::PT_INTERVAL, hdrs_num_range.c_str(), 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" },
+ { "with_header", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "this rule is limited to examining HTTP message headers" },
+ { "with_body", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "parts of this rule examine HTTP message body" },
+ { "with_trailer", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "parts of this rule examine HTTP message trailers" },
+ { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
+};
+
+static Module* num_hdrs_mod_ctor()
+{
+ return new HttpNumHdrsRuleOptModule(IPS_OPT, IPS_HELP, HTTP_RANGE_NUM_HDRS, CAT_SET_OTHER,
+ NUM_HDRS_PSI_HDRS, http_num_hdrs_params);
+}
+
+static const IpsApi num_headers_api =
+{
+ {
+ PT_IPS_OPTION,
+ sizeof(IpsApi),
+ IPSAPI_VERSION,
+ 1,
+ API_RESERVED,
+ API_OPTIONS,
+ IPS_OPT,
+ IPS_HELP,
+ num_hdrs_mod_ctor,
+ HttpNumHdrsRuleOptModule::mod_dtor
+ },
+ OPT_TYPE_DETECTION,
+ 0, PROTO_BIT__TCP,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ HttpNumHdrsIpsOption::opt_ctor,
+ HttpNumHdrsIpsOption::opt_dtor,
+ nullptr
+};
+
+//-------------------------------------------------------------------------
+// num_trailer_lines
+//-------------------------------------------------------------------------
+#undef IPS_OPT
+#define IPS_OPT "http_num_trailers"
+#undef IPS_HELP
+#define IPS_HELP "rule option to perform range check on number of trailers"
+
+static Module* num_trailers_mod_ctor()
+{
+ return new HttpNumHdrsRuleOptModule(IPS_OPT, IPS_HELP, HTTP_RANGE_NUM_TRAILERS, CAT_SET_OTHER,
+ NUM_HDRS_PSI_TRAILERS, http_num_hdrs_params);
+}
+
+static const IpsApi num_trailers_api =
+{
+ {
+ PT_IPS_OPTION,
+ sizeof(IpsApi),
+ IPSAPI_VERSION,
+ 1,
+ API_RESERVED,
+ API_OPTIONS,
+ IPS_OPT,
+ IPS_HELP,
+ num_trailers_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;
+
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2022-2022 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation. You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//--------------------------------------------------------------------------
+// ips_http_num_hdrs.h author Maya Dagon <mdagon@cisco.com>
+// Refactored from ips_http.h author Tom Peters <thopeter@cisco.com>
+
+#ifndef IPS_HTTP_NUM_HDRS_H
+#define IPS_HTTP_NUM_HDRS_H
+
+#include <array>
+
+#include "profiler/profiler.h"
+#include "framework/ips_option.h"
+#include "framework/module.h"
+#include "framework/range.h"
+
+#include "http_enum.h"
+#include "ips_http.h"
+
+enum NumHdrsPsIdx { NUM_HDRS_PSI_HDRS, NUM_HDRS_PSI_TRAILERS, NUM_HDRS_PSI_MAX };
+
+class HttpNumHdrsRuleOptModule : 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_) {}
+
+ 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::RangeCheck range;
+};
+
+class HttpNumHdrsIpsOption : public HttpIpsOption
+{
+public:
+ HttpNumHdrsIpsOption(const HttpNumHdrsRuleOptModule* cm) :
+ HttpIpsOption(cm, RULE_OPTION_TYPE_OTHER), idx(cm->idx), 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; }
+
+private:
+ const NumHdrsPsIdx idx;
+ const snort::RangeCheck range;
+};
+
+#endif
+
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2022-2022 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation. You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//--------------------------------------------------------------------------
+// ips_http_param.cc author Maya Dagon <mdagon@cisco.com>
+// Refactored from ips_http.cc author Tom Peters <thopeter@cisco.com>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "ips_http_param.h"
+
+#include "framework/cursor.h"
+#include "hash/hash_key_operations.h"
+#include "log/messages.h"
+#include "parser/parse_utils.h"
+#include "protocols/packet.h"
+
+#include "http_common.h"
+#include "http_enum.h"
+#include "http_inspect.h"
+#include "http_param.h"
+
+using namespace snort;
+using namespace HttpCommon;
+using namespace HttpEnums;
+
+THREAD_LOCAL ProfileStats HttpParamRuleOptModule::http_param_ps;
+
+bool HttpParamRuleOptModule::begin(const char*, int, SnortConfig*)
+{
+ HttpRuleOptModule::begin(nullptr, 0, nullptr);
+ param.clear();
+ nocase = false;
+ inspect_section = IS_FLEX_HEADER;
+ return true;
+}
+
+bool HttpParamRuleOptModule::set(const char*, Value& v, SnortConfig*)
+{
+ if (v.is("~param"))
+ {
+ std::string bc = v.get_string();
+ bool negated = false;
+ if (!parse_byte_code(bc.c_str(), negated, param) or negated)
+ ParseError("Invalid http_param");
+ }
+ else if (v.is("nocase"))
+ {
+ nocase = true;
+ }
+ return true;
+}
+
+uint32_t HttpParamIpsOption::hash() const
+{
+ uint32_t a = HttpIpsOption::hash();
+ uint32_t b = http_param.is_nocase() ? 1 : 0;
+ uint32_t c = 0;
+ mix_str(a,b,c,http_param.c_str(),http_param.length());
+ finalize(a,b,c);
+ return a;
+}
+
+bool HttpParamRuleOptModule::end(const char*, int, SnortConfig*)
+{
+ if (param.length() == 0)
+ ParseError("Specify parameter name");
+ return true;
+}
+
+bool HttpParamIpsOption::operator==(const IpsOption& ips) const
+{
+ const HttpParamIpsOption& hio = static_cast<const HttpParamIpsOption&>(ips);
+
+ return HttpIpsOption::operator==(static_cast<const HttpIpsOption&>(ips)) &&
+ http_param == hio.http_param;
+}
+
+bool HttpParamIpsOption::retry(Cursor& current_cursor, const Cursor&)
+{
+ HttpCursorData* cd = (HttpCursorData*)current_cursor.get_data(HttpCursorData::id);
+
+ if (cd)
+ return cd->retry();
+
+ return false;
+}
+
+IpsOption::EvalStatus HttpParamIpsOption::eval(Cursor& c, Packet* p)
+{
+ RuleProfile profile(HttpParamRuleOptModule::http_param_ps);
+
+ const HttpInspect* const hi = eval_helper(p);
+ if (hi == nullptr)
+ return NO_MATCH;
+
+ const Field& http_buffer = hi->http_get_param_buf(c, p, http_param);
+ if (http_buffer.length() <= 0)
+ return NO_MATCH;
+
+ c.set(key, http_buffer.start(), http_buffer.length());
+
+ return MATCH;
+}
+
+//-------------------------------------------------------------------------
+// http_param
+//-------------------------------------------------------------------------
+
+static const Parameter http_param_params[] =
+{
+ { "~param", Parameter::PT_STRING, nullptr, nullptr,
+ "parameter to match" },
+ { "nocase", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "case insensitive match" },
+ { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
+};
+
+#undef IPS_OPT
+#define IPS_OPT "http_param"
+#undef IPS_HELP
+#define IPS_HELP "rule option to set the detection cursor to the value of the specified HTTP parameter key which may be in the query or body"
+
+static Module* param_mod_ctor()
+{
+ return new HttpParamRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_PARAM, CAT_SET_OTHER,
+ http_param_params);
+}
+
+static const IpsApi param_api =
+{
+ {
+ PT_IPS_OPTION,
+ sizeof(IpsApi),
+ IPSAPI_VERSION,
+ 1,
+ API_RESERVED,
+ API_OPTIONS,
+ IPS_OPT,
+ IPS_HELP,
+ param_mod_ctor,
+ HttpParamRuleOptModule::mod_dtor
+ },
+ OPT_TYPE_DETECTION,
+ 0, PROTO_BIT__TCP,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ HttpParamIpsOption::opt_ctor,
+ HttpParamIpsOption::opt_dtor,
+ nullptr
+};
+
+//-------------------------------------------------------------------------
+// plugins
+//-------------------------------------------------------------------------
+
+const BaseApi* ips_http_param = ¶m_api.base;
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2022-2022 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation. You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//--------------------------------------------------------------------------
+// ips_http_param.h author Maya Dagon <mdagon@cisco.com>
+// Refactored from ips_http.h author Tom Peters <thopeter@cisco.com>
+
+#ifndef IPS_HTTP_PARAM_H
+#define IPS_HTTP_PARAM_H
+
+#include "profiler/profiler.h"
+#include "framework/ips_option.h"
+#include "framework/module.h"
+
+#include "http_param.h"
+#include "ips_http.h"
+
+
+class HttpParamRuleOptModule : public HttpRuleOptModule
+{
+public:
+ HttpParamRuleOptModule(const char* key_, const char* help, HttpEnums::HTTP_RULE_OPT rule_opt_index_,
+ snort::CursorActionType cat_, const snort::Parameter params[])
+ : HttpRuleOptModule(key_, help, rule_opt_index_, cat_, params) {}
+ snort::ProfileStats* get_profile() const override { return &http_param_ps; }
+ 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;
+ bool end(const char*, int, snort::SnortConfig*) override;
+
+private:
+ friend class HttpParamIpsOption;
+ static THREAD_LOCAL snort::ProfileStats http_param_ps;
+
+ std::string param; // provide buffer containing specific parameter
+ bool nocase; // case insensitive match
+};
+
+class HttpParamIpsOption : public HttpIpsOption
+{
+public:
+ HttpParamIpsOption(const HttpParamRuleOptModule* cm) :
+ HttpIpsOption(cm, RULE_OPTION_TYPE_BUFFER_SET),
+ key(cm->key), http_param(cm->param, cm->nocase) {}
+ 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 HttpParamIpsOption((HttpParamRuleOptModule*)m); }
+
+ static void opt_dtor(snort::IpsOption* p) { delete p; }
+ bool retry(Cursor& , const Cursor&) override;
+
+private:
+ const char* const key;
+ const HttpParam http_param;
+};
+
+#endif
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2022-2022 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation. You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//--------------------------------------------------------------------------
+// ips_http_version.cc author Maya Dagon <mdagon@cisco.com>
+// Refactored from ips_http.cc author Tom Peters <thopeter@cisco.com>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "ips_http_version.h"
+
+#include "framework/cursor.h"
+#include "hash/hash_key_operations.h"
+#include "log/messages.h"
+#include "parser/parse_utils.h"
+#include "protocols/packet.h"
+
+#include "http_common.h"
+#include "http_enum.h"
+#include "http_inspect.h"
+
+using namespace snort;
+using namespace HttpCommon;
+using namespace HttpEnums;
+
+THREAD_LOCAL ProfileStats HttpVersionRuleOptModule::http_version_ps;
+
+bool HttpVersionRuleOptModule::begin(const char*, int, SnortConfig*)
+{
+ HttpRuleOptModule::begin(nullptr, 0, nullptr);
+ inspect_section = IS_FLEX_HEADER;
+ version_flags = 0;
+ return true;
+}
+
+static const std::map <std::string, VersionId> VersionStrToEnum =
+{
+ { "malformed", VERS__PROBLEMATIC },
+ { "other", VERS__OTHER },
+ { "1.0", VERS_1_0 },
+ { "1.1", VERS_1_1 },
+ { "2.0", VERS_2_0 },
+ { "0.9", VERS_0_9 }
+};
+
+bool HttpVersionRuleOptModule::parse_version_list(Value& v)
+{
+ v.set_first_token();
+ std::string tok;
+
+ while ( v.get_next_token(tok) )
+ {
+ if (tok[0] == '"')
+ tok.erase(0, 1);
+
+ if (tok.length() == 0)
+ continue;
+
+ if (tok[tok.length()-1] == '"')
+ tok.erase(tok.length()-1, 1);
+
+ auto iter = VersionStrToEnum.find(tok);
+ if (iter == VersionStrToEnum.end())
+ {
+ ParseError("Unrecognized version %s\n", tok.c_str());
+ return false;
+ }
+
+ version_flags[iter->second - VERS__MIN] = true;
+ }
+ return true;
+}
+
+bool HttpVersionRuleOptModule::set(const char*, Value& v, SnortConfig*)
+{
+ if (v.is("~version_list"))
+ {
+ return parse_version_list(v);
+ }
+ return HttpRuleOptModule::set(nullptr, v, nullptr);
+}
+
+uint32_t HttpVersionIpsOption::hash() const
+{
+ uint32_t a = HttpIpsOption::hash();
+ uint32_t b = (uint32_t)version_flags.to_ulong();
+ uint32_t c = 0;
+ mix(a,b,c);
+ finalize(a,b,c);
+ return c;
+}
+
+bool HttpVersionIpsOption::operator==(const IpsOption& ips) const
+{
+ const HttpVersionIpsOption& hio = static_cast<const HttpVersionIpsOption&>(ips);
+ return HttpIpsOption::operator==(static_cast<const HttpIpsOption&>(ips)) &&
+ version_flags == hio.version_flags;
+}
+
+IpsOption::EvalStatus HttpVersionIpsOption::eval(Cursor&, Packet* p)
+{
+ RuleProfile profile(HttpVersionRuleOptModule::http_version_ps);
+
+ const HttpInspect* const hi = eval_helper(p);
+ if (hi == nullptr)
+ return NO_MATCH;
+
+ const VersionId version = hi->http_get_version_id(p, buffer_info);
+
+ if (version_flags[version - HttpEnums::VERS__MIN])
+ return MATCH;
+
+ return NO_MATCH;
+}
+
+//-------------------------------------------------------------------------
+// http_version_match
+//-------------------------------------------------------------------------
+#undef IPS_OPT
+#define IPS_OPT "http_version_match"
+#undef IPS_HELP
+#define IPS_HELP "rule option to match version to listed values"
+
+static const Parameter version_match_params[] =
+{
+ { "~version_list", Parameter::PT_STRING, nullptr, nullptr,
+ "space-separated list of versions to match" },
+ { "request", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "match against the version from the request message even when examining the response" },
+ { "with_header", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "this rule is limited to examining HTTP message headers" },
+ { "with_body", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "parts of this rule examine HTTP message body" },
+ { "with_trailer", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "parts of this rule examine HTTP message trailers" },
+ { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
+};
+
+static Module* version_match_mod_ctor()
+{
+ return new HttpVersionRuleOptModule(IPS_OPT, IPS_HELP, HTTP_VERSION_MATCH, CAT_SET_OTHER,
+ version_match_params);
+}
+
+static const IpsApi version_match_api =
+{
+ {
+ PT_IPS_OPTION,
+ sizeof(IpsApi),
+ IPSAPI_VERSION,
+ 1,
+ API_RESERVED,
+ API_OPTIONS,
+ IPS_OPT,
+ IPS_HELP,
+ version_match_mod_ctor,
+ HttpVersionRuleOptModule::mod_dtor
+ },
+ OPT_TYPE_DETECTION,
+ 0, PROTO_BIT__TCP,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ HttpVersionIpsOption::opt_ctor,
+ HttpVersionIpsOption::opt_dtor,
+ nullptr
+};
+
+//-------------------------------------------------------------------------
+// plugins
+//-------------------------------------------------------------------------
+const BaseApi* ips_http_version_match = &version_match_api.base;
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2022-2022 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation. You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//--------------------------------------------------------------------------
+// ips_http_version.h author Maya Dagon <mdagon@cisco.com>
+// Refactored from ips_http.h author Tom Peters <thopeter@cisco.com>
+
+#ifndef IPS_HTTP_VERSION_H
+#define IPS_HTTP_VERSION_H
+
+#include "profiler/profiler.h"
+#include "framework/ips_option.h"
+#include "framework/module.h"
+
+#include "http_enum.h"
+#include "ips_http.h"
+
+class HttpVersionRuleOptModule : public HttpRuleOptModule
+{
+public:
+ HttpVersionRuleOptModule(const char* key_, const char* help, HttpEnums::HTTP_RULE_OPT rule_opt_index_,
+ snort::CursorActionType cat_, const snort::Parameter params[])
+ : HttpRuleOptModule(key_, help, rule_opt_index_, cat_, params){}
+ snort::ProfileStats* get_profile() const override { return &http_version_ps; }
+ 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 HttpVersionIpsOption;
+ static THREAD_LOCAL snort::ProfileStats http_version_ps;
+ static const int version_size = HttpEnums::VERS__MAX - HttpEnums::VERS__MIN + 1;
+
+ std::bitset<version_size> version_flags;
+
+ bool parse_version_list(snort::Value& v);
+};
+
+class HttpVersionIpsOption : public HttpIpsOption
+{
+public:
+ HttpVersionIpsOption(const HttpVersionRuleOptModule* cm) :
+ HttpIpsOption(cm, RULE_OPTION_TYPE_OTHER), version_flags(cm->version_flags) {}
+ 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 HttpVersionIpsOption((HttpVersionRuleOptModule*)m); }
+
+ static void opt_dtor(snort::IpsOption* p) { delete p; }
+
+private:
+ const std::bitset<HttpVersionRuleOptModule::version_size> version_flags;
+};
+
+#endif