From: Tom Peters (thopeter) Date: Tue, 30 Nov 2021 17:29:53 +0000 (+0000) Subject: Pull request #3176: US 684353: http_inspect: number of header lines rule option X-Git-Tag: 3.1.18.0~4 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4b32d7ed925c413812fdaa30549b1fef9bcc4e6e;p=thirdparty%2Fsnort3.git Pull request #3176: US 684353: http_inspect: number of header lines rule option Merge in SNORT/snort3 from ~MDAGON/snort3:hdrs_num2 to master Squashed commit of the following: commit 6e4ab5896b6911913dfff1a681516f90938f5326 Author: Maya Dagon Date: Tue Aug 3 15:55:26 2021 -0400 http_inspect: new rule options num_headers, num_trailers --- diff --git a/doc/user/http_inspect.txt b/doc/user/http_inspect.txt index 54a7150f9..c2d848c5c 100755 --- a/doc/user/http_inspect.txt +++ b/doc/user/http_inspect.txt @@ -667,6 +667,13 @@ The vba_data will contain the decompressed Visual Basic for Applications (vba) macro data embedded in MS office files. It requires decompress_zip and decompress_vba options enabled. +===== num_headers and num_trailers + +These rule options are used to check the number of headers and +trailers, respectively. Checks available: equal to "=" or just value, +not "!" or "!=", less than "<", greater than ">", less or equal to "<=", +less or greater than ">=", in range "<>", in range or equal to "<=>". + ==== Timing issues and combining rule options HTTP inspector is stateful. That means it is aware of a bigger picture than diff --git a/src/framework/range.cc b/src/framework/range.cc index 275a6221f..66d356b4b 100644 --- a/src/framework/range.cc +++ b/src/framework/range.cc @@ -28,6 +28,8 @@ #include #include +#include "hash/hash_key_operations.h" + using namespace snort; using namespace std; @@ -308,6 +310,16 @@ bool RangeCheck::validate(const char* s, const char* r) return true; } +uint32_t RangeCheck::hash() const +{ + uint32_t a = op; + uint32_t b = min; + uint32_t c = max; + mix(a,b,c); + finalize(a,b,c); + return a; +} + //-------------------------------------------------------------------------- // unit tests: EQ, NOT, LT, LE, GT, GE, LG, LEG //-------------------------------------------------------------------------- diff --git a/src/framework/range.h b/src/framework/range.h index 7f8324c19..4b53a1593 100644 --- a/src/framework/range.h +++ b/src/framework/range.h @@ -43,8 +43,6 @@ public: EQ, NOT, LT, LE, GT, GE, LG, LEG, MAX }; - // Warning: FragOffsetOption computes its hash function using all the data members of - // RangeCheck. Any change to the following may require changes in ips_fragoffset.cc. Op op = MAX; long min = 0; long max = 0; @@ -57,6 +55,7 @@ public: bool parse(const char* s); bool eval(long) const; bool validate(const char* s, const char* r); + uint32_t hash() const; }; } #endif diff --git a/src/ips_options/ips_ack.cc b/src/ips_options/ips_ack.cc index 3f4d92a07..dcf3df476 100644 --- a/src/ips_options/ips_ack.cc +++ b/src/ips_options/ips_ack.cc @@ -60,13 +60,11 @@ private: uint32_t TcpAckOption::hash() const { - uint32_t a = config.op; - uint32_t b = config.min; - uint32_t c = config.max; + uint32_t a = config.hash(); + uint32_t b = IpsOption::hash(); + uint32_t c = 0; mix(a,b,c); - a += IpsOption::hash(); - finalize(a,b,c); return c; } diff --git a/src/ips_options/ips_bufferlen.cc b/src/ips_options/ips_bufferlen.cc index 21ee5870d..d7bedd665 100644 --- a/src/ips_options/ips_bufferlen.cc +++ b/src/ips_options/ips_bufferlen.cc @@ -60,13 +60,11 @@ private: uint32_t LenOption::hash() const { - uint32_t a = config.op; - uint32_t b = config.min; - uint32_t c = config.max; + uint32_t a = config.hash(); + uint32_t b = IpsOption::hash(); + uint32_t c = 0; mix(a,b,c); - a += IpsOption::hash(); - finalize(a,b,c); return c; } diff --git a/src/ips_options/ips_dsize.cc b/src/ips_options/ips_dsize.cc index 2c59e3def..93b1151ed 100644 --- a/src/ips_options/ips_dsize.cc +++ b/src/ips_options/ips_dsize.cc @@ -57,13 +57,11 @@ private: uint32_t DsizeOption::hash() const { - uint32_t a = config.min; - uint32_t b = config.max; - uint32_t c = config.op; + uint32_t a = config.hash(); + uint32_t b = IpsOption::hash(); + uint32_t c = 0; mix(a,b,c); - a += IpsOption::hash(); - finalize(a,b,c); return c; } diff --git a/src/ips_options/ips_fragoffset.cc b/src/ips_options/ips_fragoffset.cc index fbae6b56f..7efcfcef6 100644 --- a/src/ips_options/ips_fragoffset.cc +++ b/src/ips_options/ips_fragoffset.cc @@ -56,13 +56,11 @@ private: uint32_t FragOffsetOption::hash() const { - uint32_t a = config.op; - uint32_t b = (uint32_t)config.min; - uint32_t c = (uint32_t)config.max; + uint32_t a = config.hash(); + uint32_t b = IpsOption::hash(); + uint32_t c = 0; mix(a,b,c); - a += IpsOption::hash(); - finalize(a,b,c); return c; } diff --git a/src/ips_options/ips_icmp_id.cc b/src/ips_options/ips_icmp_id.cc index 12f9d22bb..e89bde3ae 100644 --- a/src/ips_options/ips_icmp_id.cc +++ b/src/ips_options/ips_icmp_id.cc @@ -80,13 +80,11 @@ private: uint32_t IcmpIdOption::hash() const { - uint32_t a = config.op; - uint32_t b = config.min; - uint32_t c = config.max; + uint32_t a = config.hash(); + uint32_t b = IpsOption::hash(); + uint32_t c = 0; mix(a,b,c); - a += IpsOption::hash(); - finalize(a,b,c); return c; } diff --git a/src/ips_options/ips_icmp_seq.cc b/src/ips_options/ips_icmp_seq.cc index 147cbc2da..fff474c9c 100644 --- a/src/ips_options/ips_icmp_seq.cc +++ b/src/ips_options/ips_icmp_seq.cc @@ -80,13 +80,11 @@ private: uint32_t IcmpSeqOption::hash() const { - uint32_t a = config.op; - uint32_t b = config.min; - uint32_t c = config.max; + uint32_t a = config.hash(); + uint32_t b = IpsOption::hash(); + uint32_t c = 0; mix(a,b,c); - a += IpsOption::hash(); - finalize(a,b,c); return c; } diff --git a/src/ips_options/ips_icode.cc b/src/ips_options/ips_icode.cc index 947cab321..ddf2d94e7 100644 --- a/src/ips_options/ips_icode.cc +++ b/src/ips_options/ips_icode.cc @@ -57,13 +57,11 @@ private: uint32_t IcodeOption::hash() const { - uint32_t a = config.op; - uint32_t b = config.min; - uint32_t c = config.max; + uint32_t a = config.hash(); + uint32_t b = IpsOption::hash(); + uint32_t c = 0; mix(a,b,c); - a += IpsOption::hash(); - finalize(a,b,c); return c; } diff --git a/src/ips_options/ips_id.cc b/src/ips_options/ips_id.cc index b59cfd52c..b4f83a81a 100644 --- a/src/ips_options/ips_id.cc +++ b/src/ips_options/ips_id.cc @@ -56,13 +56,11 @@ private: uint32_t IpIdOption::hash() const { - uint32_t a = config.op; - uint32_t b = config.min; - uint32_t c = config.max; + uint32_t a = config.hash(); + uint32_t b = IpsOption::hash(); + uint32_t c = 0; mix(a,b,c); - a += IpsOption::hash(); - finalize(a,b,c); return c; } diff --git a/src/ips_options/ips_itype.cc b/src/ips_options/ips_itype.cc index 89b7040ce..9fc4de5f3 100644 --- a/src/ips_options/ips_itype.cc +++ b/src/ips_options/ips_itype.cc @@ -57,13 +57,11 @@ private: uint32_t IcmpTypeOption::hash() const { - uint32_t a = config.op; - uint32_t b = config.min; - uint32_t c = config.max; + uint32_t a = config.hash(); + uint32_t b = IpsOption::hash(); + uint32_t c = 0; mix(a,b,c); - a += IpsOption::hash(); - finalize(a,b,c); return c; } diff --git a/src/ips_options/ips_seq.cc b/src/ips_options/ips_seq.cc index 9376aa981..771e9c5e5 100644 --- a/src/ips_options/ips_seq.cc +++ b/src/ips_options/ips_seq.cc @@ -57,13 +57,11 @@ private: uint32_t TcpSeqOption::hash() const { - uint32_t a = config.op; - uint32_t b = config.min; - uint32_t c = config.max; + uint32_t a = config.hash(); + uint32_t b = IpsOption::hash(); + uint32_t c = 0; mix(a,b,c); - a += IpsOption::hash(); - finalize(a,b,c); return c; } diff --git a/src/ips_options/ips_tos.cc b/src/ips_options/ips_tos.cc index c8a7d6d7a..46b995c05 100644 --- a/src/ips_options/ips_tos.cc +++ b/src/ips_options/ips_tos.cc @@ -56,13 +56,11 @@ public: uint32_t IpTosOption::hash() const { - uint32_t a = config.op; - uint32_t b = config.min; - uint32_t c = config.max; + uint32_t a = config.hash(); + uint32_t b = IpsOption::hash(); + uint32_t c = 0; mix(a,b,c); - a += IpsOption::hash(); - finalize(a,b,c); return c; } diff --git a/src/ips_options/ips_ttl.cc b/src/ips_options/ips_ttl.cc index 2f1fddf5f..b88146999 100644 --- a/src/ips_options/ips_ttl.cc +++ b/src/ips_options/ips_ttl.cc @@ -56,12 +56,9 @@ private: uint32_t TtlOption::hash() const { - uint32_t a = config.op; - uint32_t b = config.min; - uint32_t c = config.max; - - mix(a,b,c); - a += IpsOption::hash(); + uint32_t a = config.hash(); + uint32_t b = IpsOption::hash(); + uint32_t c = 0; mix(a,b,c); finalize(a,b,c); diff --git a/src/ips_options/ips_window.cc b/src/ips_options/ips_window.cc index 0c57d8132..c176ac7aa 100644 --- a/src/ips_options/ips_window.cc +++ b/src/ips_options/ips_window.cc @@ -57,13 +57,11 @@ private: uint32_t TcpWinOption::hash() const { - uint32_t a = config.op; - uint32_t b = config.min; - uint32_t c = config.max; + uint32_t a = config.hash(); + uint32_t b = IpsOption::hash(); + uint32_t c = 0; mix(a,b,c); - a += IpsOption::hash(); - finalize(a,b,c); return c; } diff --git a/src/service_inspectors/cip/ips_cip_attribute.cc b/src/service_inspectors/cip/ips_cip_attribute.cc index a3bd448d6..a2e76ce1b 100644 --- a/src/service_inspectors/cip/ips_cip_attribute.cc +++ b/src/service_inspectors/cip/ips_cip_attribute.cc @@ -62,13 +62,11 @@ private: uint32_t CipAttributeOption::hash() const { - uint32_t a = cip_attr.op; - uint32_t b = cip_attr.min; - uint32_t c = cip_attr.max; + uint32_t a = cip_attr.hash(); + uint32_t b = IpsOption::hash(); + uint32_t c = 0; mix(a, b, c); - a += IpsOption::hash(); - finalize(a,b,c); return c; } diff --git a/src/service_inspectors/cip/ips_cip_class.cc b/src/service_inspectors/cip/ips_cip_class.cc index a0384593d..c57965e81 100644 --- a/src/service_inspectors/cip/ips_cip_class.cc +++ b/src/service_inspectors/cip/ips_cip_class.cc @@ -63,13 +63,11 @@ private: uint32_t CipClassOption::hash() const { - uint32_t a = cip_class.op; - uint32_t b = cip_class.min; - uint32_t c = cip_class.max; + uint32_t a = cip_class.hash(); + uint32_t b = IpsOption::hash(); + uint32_t c = 0; mix(a, b, c); - a += IpsOption::hash(); - finalize(a,b,c); return c; } diff --git a/src/service_inspectors/cip/ips_cip_connpathclass.cc b/src/service_inspectors/cip/ips_cip_connpathclass.cc index b1da5a545..a8feb6584 100644 --- a/src/service_inspectors/cip/ips_cip_connpathclass.cc +++ b/src/service_inspectors/cip/ips_cip_connpathclass.cc @@ -62,13 +62,11 @@ private: uint32_t CipConnpathclassOption::hash() const { - uint32_t a = cip_cpc.op; - uint32_t b = cip_cpc.min; - uint32_t c = cip_cpc.max; + uint32_t a = cip_cpc.hash(); + uint32_t b = IpsOption::hash(); + uint32_t c = 0; mix(a, b, c); - a += IpsOption::hash(); - finalize(a,b,c); return c; } diff --git a/src/service_inspectors/cip/ips_cip_enipcommand.cc b/src/service_inspectors/cip/ips_cip_enipcommand.cc index 467ee8c47..89420483d 100644 --- a/src/service_inspectors/cip/ips_cip_enipcommand.cc +++ b/src/service_inspectors/cip/ips_cip_enipcommand.cc @@ -62,13 +62,11 @@ private: uint32_t CipEnipCommandOption::hash() const { - uint32_t a = cip_enip_cmd.op; - uint32_t b = cip_enip_cmd.min; - uint32_t c = cip_enip_cmd.max; + uint32_t a = cip_enip_cmd.hash(); + uint32_t b = IpsOption::hash(); + uint32_t c = 0; mix(a, b, c); - a += IpsOption::hash(); - finalize(a,b,c); return c; } diff --git a/src/service_inspectors/cip/ips_cip_instance.cc b/src/service_inspectors/cip/ips_cip_instance.cc index 224a364d6..66538f1bd 100644 --- a/src/service_inspectors/cip/ips_cip_instance.cc +++ b/src/service_inspectors/cip/ips_cip_instance.cc @@ -62,13 +62,11 @@ private: uint32_t CipInstanceOption::hash() const { - uint32_t a = cip_inst.op; - uint32_t b = cip_inst.min; - uint32_t c = cip_inst.max; + uint32_t a = cip_inst.hash(); + uint32_t b = IpsOption::hash(); + uint32_t c = 0; mix(a, b, c); - a += IpsOption::hash(); - finalize(a,b,c); return c; } diff --git a/src/service_inspectors/cip/ips_cip_service.cc b/src/service_inspectors/cip/ips_cip_service.cc index 97af706ad..53cb5d214 100644 --- a/src/service_inspectors/cip/ips_cip_service.cc +++ b/src/service_inspectors/cip/ips_cip_service.cc @@ -62,13 +62,11 @@ private: uint32_t CipServiceOption::hash() const { - uint32_t a = cip_serv.op; - uint32_t b = cip_serv.min; - uint32_t c = cip_serv.max; + uint32_t a = cip_serv.hash(); + uint32_t b = IpsOption::hash(); + uint32_t c = 0; mix(a, b, c); - a += IpsOption::hash(); - finalize(a,b,c); return c; } diff --git a/src/service_inspectors/cip/ips_cip_status.cc b/src/service_inspectors/cip/ips_cip_status.cc index c4dcd021b..f11873dbd 100644 --- a/src/service_inspectors/cip/ips_cip_status.cc +++ b/src/service_inspectors/cip/ips_cip_status.cc @@ -62,13 +62,11 @@ private: uint32_t CipStatusOption::hash() const { - uint32_t a = cip_status.op; - uint32_t b = cip_status.min; - uint32_t c = cip_status.max; + uint32_t a = cip_status.hash(); + uint32_t b = IpsOption::hash(); + uint32_t c = 0; mix(a, b, c); - a += IpsOption::hash(); - finalize(a,b,c); return c; } diff --git a/src/service_inspectors/dce_rpc/ips_dce_iface.cc b/src/service_inspectors/dce_rpc/ips_dce_iface.cc index bd70959c9..fee3d4ba6 100644 --- a/src/service_inspectors/dce_rpc/ips_dce_iface.cc +++ b/src/service_inspectors/dce_rpc/ips_dce_iface.cc @@ -342,13 +342,11 @@ uint32_t Dce2IfaceOption::hash() const (uuid.node[3] << 16) | (uuid.node[4] << 8) | (uuid.node[5]); - b += version.max; - c += version.min; + b += version.hash(); + c += any_frag; mix(a, b, c); - a += version.op; - b += any_frag; c += IpsOption::hash(); finalize(a, b, c); diff --git a/src/service_inspectors/http_inspect/http_api.cc b/src/service_inspectors/http_inspect/http_api.cc index bf1d47f14..91c1327b9 100644 --- a/src/service_inspectors/http_inspect/http_api.cc +++ b/src/service_inspectors/http_inspect/http_api.cc @@ -104,6 +104,8 @@ extern const BaseApi* ips_http_client_body; extern const BaseApi* ips_http_cookie; extern const BaseApi* ips_http_header; extern const BaseApi* ips_http_method; +extern const BaseApi* ips_http_num_headers; +extern const BaseApi* ips_http_num_trailers; extern const BaseApi* ips_http_param; extern const BaseApi* ips_http_raw_body; extern const BaseApi* ips_http_raw_cookie; @@ -131,6 +133,8 @@ const BaseApi* sin_http[] = ips_http_cookie, ips_http_header, ips_http_method, + ips_http_num_headers, + ips_http_num_trailers, ips_http_param, ips_http_raw_body, ips_http_raw_cookie, diff --git a/src/service_inspectors/http_inspect/http_enum.h b/src/service_inspectors/http_inspect/http_enum.h index 9dfdf66eb..065339076 100755 --- a/src/service_inspectors/http_inspect/http_enum.h +++ b/src/service_inspectors/http_inspect/http_enum.h @@ -53,14 +53,16 @@ enum SectionType { SEC_DISCARD = -19, SEC_ABORT = -18, SEC__NOT_COMPUTE=-14, SEC enum DetectionStatus { DET_REACTIVATING = 1, DET_ON, DET_DEACTIVATING, DET_OFF }; -// Message buffers available to clients -// This enum must remain synchronized with HttpApi::classic_buffer_names[] -enum HTTP_BUFFER { HTTP_BUFFER_CLIENT_BODY = 1, HTTP_BUFFER_COOKIE, HTTP_BUFFER_HEADER, +// HTTP rule options. +// Lower portion is message buffers available to clients. +// That part must remain synchronized with HttpApi::classic_buffer_names[] +enum HTTP_RULE_OPT { HTTP_BUFFER_CLIENT_BODY = 1, HTTP_BUFFER_COOKIE, HTTP_BUFFER_HEADER, HTTP_BUFFER_METHOD, HTTP_BUFFER_PARAM, HTTP_BUFFER_RAW_BODY, HTTP_BUFFER_RAW_COOKIE, HTTP_BUFFER_RAW_HEADER, HTTP_BUFFER_RAW_REQUEST, HTTP_BUFFER_RAW_STATUS, HTTP_BUFFER_RAW_TRAILER, HTTP_BUFFER_RAW_URI, HTTP_BUFFER_STAT_CODE, HTTP_BUFFER_STAT_MSG, HTTP_BUFFER_TRAILER, HTTP_BUFFER_TRUE_IP, HTTP_BUFFER_URI, HTTP_BUFFER_VERSION, - BUFFER_JS_DATA, BUFFER_VBA_DATA, HTTP_BUFFER_MAX }; + BUFFER_JS_DATA, BUFFER_VBA_DATA , HTTP_BUFFER_MAX = BUFFER_VBA_DATA, + HTTP_RANGE_NUM_HDRS, HTTP_RANGE_NUM_TRAILERS, HTTP_MAX_RULE_OPTION }; // Peg counts // This enum must remain synchronized with HttpModule::peg_names[] in http_tables.cc diff --git a/src/service_inspectors/http_inspect/http_inspect.cc b/src/service_inspectors/http_inspect/http_inspect.cc index 57d805821..ddf444ca0 100755 --- a/src/service_inspectors/http_inspect/http_inspect.cc +++ b/src/service_inspectors/http_inspect/http_inspect.cc @@ -274,9 +274,9 @@ bool HttpInspect::get_buf(unsigned id, Packet* p, InspectionBuffer& b) } const Field& HttpInspect::http_get_buf(Cursor& c, Packet* p, - const HttpBufferInfo& buffer_info) + const HttpBufferInfo& buffer_info) const { - HttpMsgSection* current_section = HttpContextData::get_snapshot(p); + HttpMsgSection* const current_section = HttpContextData::get_snapshot(p); if (current_section == nullptr) return Field::FIELD_NULL; @@ -284,6 +284,17 @@ const Field& HttpInspect::http_get_buf(Cursor& c, Packet* p, return current_section->get_classic_buffer(c, buffer_info); } +int32_t HttpInspect::http_get_num_headers(Packet* p, + const HttpBufferInfo& buffer_info) const +{ + const HttpMsgSection* const current_section = HttpContextData::get_snapshot(p); + + if (current_section == nullptr) + return STAT_NOT_COMPUTE; + + return current_section->get_num_headers(buffer_info); +} + bool HttpInspect::get_fp_buf(InspectionBuffer::Type ibt, Packet* p, InspectionBuffer& b) { if (get_latest_is(p) == IS_NONE) diff --git a/src/service_inspectors/http_inspect/http_inspect.h b/src/service_inspectors/http_inspect/http_inspect.h index b61e742fe..49d508006 100644 --- a/src/service_inspectors/http_inspect/http_inspect.h +++ b/src/service_inspectors/http_inspect/http_inspect.h @@ -48,7 +48,8 @@ public: 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 HttpBufferInfo& buffer_info) const; + int32_t http_get_num_headers(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; diff --git a/src/service_inspectors/http_inspect/http_msg_head_shared.h b/src/service_inspectors/http_inspect/http_msg_head_shared.h index b51bd4d96..f0f791a68 100755 --- a/src/service_inspectors/http_inspect/http_msg_head_shared.h +++ b/src/service_inspectors/http_inspect/http_msg_head_shared.h @@ -59,7 +59,9 @@ public: uint64_t get_file_cache_index(); const Field& get_content_disposition_filename(); bool is_external_js(); + int32_t get_num_headers() const { return num_headers; } + static const int MAX_HEADERS = 200; // I'm an arbitrary number. FIXIT-RC protected: HttpMsgHeadShared(const uint8_t* buffer, const uint16_t buf_size, HttpFlowData* session_data_, HttpCommon::SourceId source_id_, bool buf_owner, snort::Flow* flow_, @@ -78,7 +80,6 @@ private: static const int MAX = HttpEnums::HEAD__MAX_VALUE + HttpEnums::MAX_CUSTOM_HEADERS; // All of these are indexed by the relative position of the header field in the message - static const int MAX_HEADERS = 200; // I'm an arbitrary number. FIXIT-RC static const int MAX_HEADER_LENGTH = 4096; // Based on max cookie size of some browsers void parse_header_block(); diff --git a/src/service_inspectors/http_inspect/http_msg_section.cc b/src/service_inspectors/http_inspect/http_msg_section.cc index e115e8409..6e16ae044 100644 --- a/src/service_inspectors/http_inspect/http_msg_section.cc +++ b/src/service_inspectors/http_inspect/http_msg_section.cc @@ -404,6 +404,20 @@ const Field& HttpMsgSection::get_classic_buffer(Cursor& c, const HttpBufferInfo& } } +int32_t HttpMsgSection::get_num_headers(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; + + const HttpMsgHeadShared* const head = (buf.type == HTTP_RANGE_NUM_TRAILERS) ? + (HttpMsgHeadShared*)trailer[buffer_side]: + (HttpMsgHeadShared*)header[buffer_side] ; + if (head == nullptr) + return HttpCommon::STAT_NOT_COMPUTE; + + return head->get_num_headers(); +} + void HttpMsgSection::get_related_sections() { // When a message section is created these relationships become fixed so we make copies for diff --git a/src/service_inspectors/http_inspect/http_msg_section.h b/src/service_inspectors/http_inspect/http_msg_section.h index 8f41965c9..eb5f53ace 100644 --- a/src/service_inspectors/http_inspect/http_msg_section.h +++ b/src/service_inspectors/http_inspect/http_msg_section.h @@ -80,6 +80,7 @@ public: bool is_clear() { return cleared; } uint64_t get_transaction_id() { return trans_num; } + int32_t get_num_headers(const HttpBufferInfo& buf) const; HttpMsgSection* next = nullptr; diff --git a/src/service_inspectors/http_inspect/ips_http.cc b/src/service_inspectors/http_inspect/ips_http.cc index 067d17209..5603318bf 100644 --- a/src/service_inspectors/http_inspect/ips_http.cc +++ b/src/service_inspectors/http_inspect/ips_http.cc @@ -41,14 +41,16 @@ using namespace snort; using namespace HttpCommon; using namespace HttpEnums; -THREAD_LOCAL std::array HttpCursorModule::http_ps; +THREAD_LOCAL std::array HttpRuleOptModule::http_ps; -bool HttpCursorModule::begin(const char*, int, SnortConfig*) +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 (buffer_index) + switch (rule_opt_index) { case HTTP_BUFFER_RAW_STATUS: case HTTP_BUFFER_STAT_CODE: @@ -66,6 +68,7 @@ bool HttpCursorModule::begin(const char*, int, SnortConfig*) case HTTP_BUFFER_TRUE_IP: case HTTP_BUFFER_URI: case HTTP_BUFFER_VERSION: + case HTTP_RANGE_NUM_HDRS: inspect_section = IS_FLEX_HEADER; break; case HTTP_BUFFER_CLIENT_BODY: @@ -75,6 +78,7 @@ bool HttpCursorModule::begin(const char*, int, SnortConfig*) break; case HTTP_BUFFER_RAW_TRAILER: case HTTP_BUFFER_TRAILER: + case HTTP_RANGE_NUM_TRAILERS: inspect_section = IS_TRAILER; break; default: @@ -83,7 +87,7 @@ bool HttpCursorModule::begin(const char*, int, SnortConfig*) return true; } -bool HttpCursorModule::set(const char*, Value& v, SnortConfig*) +bool HttpRuleOptModule::set(const char*, Value& v, SnortConfig*) { if (v.is("field")) { @@ -163,27 +167,31 @@ bool HttpCursorModule::set(const char*, Value& v, SnortConfig*) 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()); + } return true; } -bool HttpCursorModule::end(const char*, int, SnortConfig*) +bool HttpRuleOptModule::end(const char*, int, SnortConfig*) { // 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 (((buffer_index == HTTP_BUFFER_TRAILER) || (buffer_index == HTTP_BUFFER_RAW_TRAILER)) && + 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) && !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 (buffer_index == HTTP_BUFFER_PARAM && para_list.param.length() == 0) + if (rule_opt_index == HTTP_BUFFER_PARAM && para_list.param.length() == 0) ParseError("Specify parameter name"); return true; } -void HttpCursorModule::HttpRuleParaList::reset() +void HttpRuleOptModule::HttpRuleParaList::reset() { field.clear(); param.clear(); @@ -198,6 +206,7 @@ void HttpCursorModule::HttpRuleParaList::reset() path = false; query = false; fragment = false; + range.init(); } uint32_t HttpIpsOption::hash() const @@ -206,6 +215,7 @@ 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(); finalize(a,b,c); return c; } @@ -215,7 +225,8 @@ bool HttpIpsOption::operator==(const IpsOption& ips) const const HttpIpsOption& hio = static_cast(ips); return IpsOption::operator==(ips) && inspect_section == hio.inspect_section && - buffer_info == hio.buffer_info; + buffer_info == hio.buffer_info && + range == hio.range; } bool HttpIpsOption::retry(Cursor& current_cursor, const Cursor&) @@ -232,7 +243,7 @@ bool HttpIpsOption::retry(Cursor& current_cursor, const Cursor&) IpsOption::EvalStatus HttpIpsOption::eval(Cursor& c, Packet* p) { - RuleProfile profile(HttpCursorModule::http_ps[psi]); + RuleProfile profile(HttpRuleOptModule::http_ps[psi]); if (!p->flow || !p->flow->gadget || (HttpInspect::get_latest_is(p) == IS_NONE)) return NO_MATCH; @@ -248,17 +259,28 @@ IpsOption::EvalStatus HttpIpsOption::eval(Cursor& c, Packet* p) const Http2FlowData* const h2i_flow_data = (Http2FlowData*)p->flow->get_flow_data(Http2FlowData::inspector_id); - HttpInspect* const hi = (h2i_flow_data != nullptr) ? + const HttpInspect* const hi = (h2i_flow_data != nullptr) ? (HttpInspect*)(p->flow->assistant_gadget) : (HttpInspect*)(p->flow->gadget); - const Field& http_buffer = hi->http_get_buf(c, p, buffer_info); + 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; + if (http_buffer.length() <= 0) + return NO_MATCH; - c.set(key, http_buffer.start(), http_buffer.length()); + c.set(key, http_buffer.start(), http_buffer.length()); - return MATCH; + return MATCH; + } + 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; + } } //------------------------------------------------------------------------- @@ -272,7 +294,7 @@ IpsOption::EvalStatus HttpIpsOption::eval(Cursor& c, Packet* p) static Module* client_body_mod_ctor() { - return new HttpCursorModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_CLIENT_BODY, CAT_SET_BODY, + return new HttpRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_CLIENT_BODY, CAT_SET_BODY, PSI_CLIENT_BODY); } @@ -288,7 +310,7 @@ static const IpsApi client_body_api = IPS_OPT, IPS_HELP, client_body_mod_ctor, - HttpCursorModule::mod_dtor + HttpRuleOptModule::mod_dtor }, OPT_TYPE_DETECTION, 0, PROTO_BIT__TCP, @@ -325,7 +347,7 @@ static const Parameter http_cookie_params[] = static Module* cookie_mod_ctor() { - return new HttpCursorModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_COOKIE, CAT_SET_COOKIE, PSI_COOKIE, + return new HttpRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_COOKIE, CAT_SET_COOKIE, PSI_COOKIE, http_cookie_params); } @@ -341,7 +363,7 @@ static const IpsApi cookie_api = IPS_OPT, IPS_HELP, cookie_mod_ctor, - HttpCursorModule::mod_dtor + HttpRuleOptModule::mod_dtor }, OPT_TYPE_DETECTION, 0, PROTO_BIT__TCP, @@ -386,7 +408,7 @@ static const Parameter http_header_params[] = static Module* header_mod_ctor() { - return new HttpCursorModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_HEADER, CAT_SET_HEADER, + return new HttpRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_HEADER, CAT_SET_HEADER, PSI_HEADER, http_header_params); } @@ -402,7 +424,7 @@ static const IpsApi header_api = IPS_OPT, IPS_HELP, header_mod_ctor, - HttpCursorModule::mod_dtor + HttpRuleOptModule::mod_dtor }, OPT_TYPE_DETECTION, 0, PROTO_BIT__TCP, @@ -437,7 +459,7 @@ static const Parameter http_method_params[] = static Module* method_mod_ctor() { - return new HttpCursorModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_METHOD, CAT_SET_METHOD, PSI_METHOD, + return new HttpRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_METHOD, CAT_SET_METHOD, PSI_METHOD, http_method_params); } @@ -453,7 +475,7 @@ static const IpsApi method_api = IPS_OPT, IPS_HELP, method_mod_ctor, - HttpCursorModule::mod_dtor + HttpRuleOptModule::mod_dtor }, OPT_TYPE_DETECTION, 0, PROTO_BIT__TCP, @@ -486,7 +508,7 @@ static const Parameter http_param_params[] = static Module* param_mod_ctor() { - return new HttpCursorModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_PARAM, CAT_SET_OTHER, PSI_PARAM, + return new HttpRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_PARAM, CAT_SET_OTHER, PSI_PARAM, http_param_params); } @@ -502,7 +524,7 @@ static const IpsApi param_api = IPS_OPT, IPS_HELP, param_mod_ctor, - HttpCursorModule::mod_dtor + HttpRuleOptModule::mod_dtor }, OPT_TYPE_DETECTION, 0, PROTO_BIT__TCP, @@ -526,7 +548,7 @@ static const IpsApi param_api = static Module* raw_body_mod_ctor() { - return new HttpCursorModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_RAW_BODY, CAT_SET_OTHER, + return new HttpRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_RAW_BODY, CAT_SET_OTHER, PSI_RAW_BODY); } @@ -542,7 +564,7 @@ static const IpsApi raw_body_api = IPS_OPT, IPS_HELP, raw_body_mod_ctor, - HttpCursorModule::mod_dtor + HttpRuleOptModule::mod_dtor }, OPT_TYPE_DETECTION, 0, PROTO_BIT__TCP, @@ -579,7 +601,7 @@ static const Parameter http_raw_cookie_params[] = static Module* raw_cookie_mod_ctor() { - return new HttpCursorModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_RAW_COOKIE, CAT_SET_OTHER, + return new HttpRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_RAW_COOKIE, CAT_SET_OTHER, PSI_RAW_COOKIE, http_raw_cookie_params); } @@ -595,7 +617,7 @@ static const IpsApi raw_cookie_api = IPS_OPT, IPS_HELP, raw_cookie_mod_ctor, - HttpCursorModule::mod_dtor + HttpRuleOptModule::mod_dtor }, OPT_TYPE_DETECTION, 0, PROTO_BIT__TCP, @@ -634,7 +656,7 @@ static const Parameter http_raw_header_params[] = static Module* raw_header_mod_ctor() { - return new HttpCursorModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_RAW_HEADER, CAT_SET_RAW_HEADER, + return new HttpRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_RAW_HEADER, CAT_SET_RAW_HEADER, PSI_RAW_HEADER, http_raw_header_params); } @@ -650,7 +672,7 @@ static const IpsApi raw_header_api = IPS_OPT, IPS_HELP, raw_header_mod_ctor, - HttpCursorModule::mod_dtor + HttpRuleOptModule::mod_dtor }, OPT_TYPE_DETECTION, 0, PROTO_BIT__TCP, @@ -685,7 +707,7 @@ static const Parameter http_raw_request_params[] = static Module* raw_request_mod_ctor() { - return new HttpCursorModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_RAW_REQUEST, CAT_SET_OTHER, + return new HttpRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_RAW_REQUEST, CAT_SET_OTHER, PSI_RAW_REQUEST, http_raw_request_params); } @@ -701,7 +723,7 @@ static const IpsApi raw_request_api = IPS_OPT, IPS_HELP, raw_request_mod_ctor, - HttpCursorModule::mod_dtor + HttpRuleOptModule::mod_dtor }, OPT_TYPE_DETECTION, 0, PROTO_BIT__TCP, @@ -734,7 +756,7 @@ static const Parameter http_raw_status_params[] = static Module* raw_status_mod_ctor() { - return new HttpCursorModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_RAW_STATUS, CAT_SET_OTHER, + return new HttpRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_RAW_STATUS, CAT_SET_OTHER, PSI_RAW_STATUS, http_raw_status_params); } @@ -750,7 +772,7 @@ static const IpsApi raw_status_api = IPS_OPT, IPS_HELP, raw_status_mod_ctor, - HttpCursorModule::mod_dtor + HttpRuleOptModule::mod_dtor }, OPT_TYPE_DETECTION, 0, PROTO_BIT__TCP, @@ -788,7 +810,7 @@ static const Parameter http_raw_trailer_params[] = static Module* raw_trailer_mod_ctor() { - return new HttpCursorModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_RAW_TRAILER, CAT_SET_RAW_HEADER, + return new HttpRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_RAW_TRAILER, CAT_SET_RAW_HEADER, PSI_RAW_TRAILER, http_raw_trailer_params); } @@ -804,7 +826,7 @@ static const IpsApi raw_trailer_api = IPS_OPT, IPS_HELP, raw_trailer_mod_ctor, - HttpCursorModule::mod_dtor + HttpRuleOptModule::mod_dtor }, OPT_TYPE_DETECTION, 0, PROTO_BIT__TCP, @@ -851,7 +873,7 @@ static const Parameter http_raw_uri_params[] = static Module* raw_uri_mod_ctor() { - return new HttpCursorModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_RAW_URI, CAT_SET_RAW_KEY, + return new HttpRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_RAW_URI, CAT_SET_RAW_KEY, PSI_RAW_URI, http_raw_uri_params); } @@ -867,7 +889,7 @@ static const IpsApi raw_uri_api = IPS_OPT, IPS_HELP, raw_uri_mod_ctor, - HttpCursorModule::mod_dtor + HttpRuleOptModule::mod_dtor }, OPT_TYPE_DETECTION, 0, PROTO_BIT__TCP, @@ -900,7 +922,7 @@ static const Parameter http_stat_code_params[] = static Module* stat_code_mod_ctor() { - return new HttpCursorModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_STAT_CODE, CAT_SET_STAT_CODE, + return new HttpRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_STAT_CODE, CAT_SET_STAT_CODE, PSI_STAT_CODE, http_stat_code_params); } @@ -916,7 +938,7 @@ static const IpsApi stat_code_api = IPS_OPT, IPS_HELP, stat_code_mod_ctor, - HttpCursorModule::mod_dtor + HttpRuleOptModule::mod_dtor }, OPT_TYPE_DETECTION, 0, PROTO_BIT__TCP, @@ -949,7 +971,7 @@ static const Parameter http_stat_msg_params[] = static Module* stat_msg_mod_ctor() { - return new HttpCursorModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_STAT_MSG, CAT_SET_STAT_MSG, + return new HttpRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_STAT_MSG, CAT_SET_STAT_MSG, PSI_STAT_MSG, http_stat_msg_params); } @@ -965,7 +987,7 @@ static const IpsApi stat_msg_api = IPS_OPT, IPS_HELP, stat_msg_mod_ctor, - HttpCursorModule::mod_dtor + HttpRuleOptModule::mod_dtor }, OPT_TYPE_DETECTION, 0, PROTO_BIT__TCP, @@ -1002,7 +1024,7 @@ static const Parameter http_trailer_params[] = static Module* trailer_mod_ctor() { - return new HttpCursorModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_TRAILER, CAT_SET_HEADER, + return new HttpRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_TRAILER, CAT_SET_HEADER, PSI_TRAILER, http_trailer_params); } @@ -1018,7 +1040,7 @@ static const IpsApi trailer_api = IPS_OPT, IPS_HELP, trailer_mod_ctor, - HttpCursorModule::mod_dtor + HttpRuleOptModule::mod_dtor }, OPT_TYPE_DETECTION, 0, PROTO_BIT__TCP, @@ -1053,7 +1075,7 @@ static const Parameter http_true_ip_params[] = static Module* true_ip_mod_ctor() { - return new HttpCursorModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_TRUE_IP, CAT_SET_OTHER, + return new HttpRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_TRUE_IP, CAT_SET_OTHER, PSI_TRUE_IP, http_true_ip_params); } @@ -1069,7 +1091,7 @@ static const IpsApi true_ip_api = IPS_OPT, IPS_HELP, true_ip_mod_ctor, - HttpCursorModule::mod_dtor + HttpRuleOptModule::mod_dtor }, OPT_TYPE_DETECTION, 0, PROTO_BIT__TCP, @@ -1116,7 +1138,7 @@ static const Parameter http_uri_params[] = static Module* uri_mod_ctor() { - return new HttpCursorModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_URI, CAT_SET_KEY, PSI_URI, + return new HttpRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_URI, CAT_SET_KEY, PSI_URI, http_uri_params); } @@ -1132,7 +1154,7 @@ static const IpsApi uri_api = IPS_OPT, IPS_HELP, uri_mod_ctor, - HttpCursorModule::mod_dtor + HttpRuleOptModule::mod_dtor }, OPT_TYPE_DETECTION, 0, PROTO_BIT__TCP, @@ -1169,7 +1191,7 @@ static const Parameter http_version_params[] = static Module* version_mod_ctor() { - return new HttpCursorModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_VERSION, CAT_SET_OTHER, + return new HttpRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_VERSION, CAT_SET_OTHER, PSI_VERSION, http_version_params); } @@ -1185,7 +1207,7 @@ static const IpsApi version_api = IPS_OPT, IPS_HELP, version_mod_ctor, - HttpCursorModule::mod_dtor + HttpRuleOptModule::mod_dtor }, OPT_TYPE_DETECTION, 0, PROTO_BIT__TCP, @@ -1209,7 +1231,7 @@ static const IpsApi version_api = #define IPS_HELP "rule option to set detection cursor to normalized JavaScript data" static Module* js_data_mod_ctor() { - return new HttpCursorModule(IPS_OPT, IPS_HELP, BUFFER_JS_DATA, CAT_SET_JS_DATA, + return new HttpRuleOptModule(IPS_OPT, IPS_HELP, BUFFER_JS_DATA, CAT_SET_JS_DATA, PSI_JS_DATA); } @@ -1225,7 +1247,100 @@ static const IpsApi js_data_api = IPS_OPT, IPS_HELP, js_data_mod_ctor, - HttpCursorModule::mod_dtor + 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, @@ -1246,6 +1361,8 @@ 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; diff --git a/src/service_inspectors/http_inspect/ips_http.h b/src/service_inspectors/http_inspect/ips_http.h index c97b42506..46e30e16f 100644 --- a/src/service_inspectors/http_inspect/ips_http.h +++ b/src/service_inspectors/http_inspect/ips_http.h @@ -25,26 +25,30 @@ #include "profiler/profiler.h" #include "framework/ips_option.h" #include "framework/module.h" +#include "framework/range.h" #include "http_buffer_info.h" #include "http_enum.h" +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_MAX }; + PSI_TRUE_IP, PSI_URI, PSI_VERSION, PSI_JS_DATA, PSI_VBA_DATA, + PSI_RANGE_NUM_HDRS, PSI_RANGE_NUM_TRAILERS, PSI_MAX }; -class HttpCursorModule : public snort::Module +class HttpRuleOptModule : public snort::Module { public: - HttpCursorModule(const char* key_, const char* help, HttpEnums::HTTP_BUFFER buffer_index_, + 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_), buffer_index(buffer_index_), + : snort::Module(key_, help), key(key_), rule_opt_index(rule_opt_index_), cat(cat_), psi(psi_) {} - HttpCursorModule(const char* key_, const char* help, HttpEnums::HTTP_BUFFER buffer_index_, + 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_), buffer_index(buffer_index_), - cat(cat_), psi(psi_) {} + : 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]; } static void mod_dtor(snort::Module* m) { delete m; } bool begin(const char*, int, snort::SnortConfig*) override; @@ -74,12 +78,13 @@ private: bool path; bool query; bool fragment; + snort::RangeCheck range; void reset(); }; const char* const key; - const HttpEnums::HTTP_BUFFER buffer_index; + const HttpEnums::HTTP_RULE_OPT rule_opt_index; const snort::CursorActionType cat; const PsIdx psi; @@ -92,26 +97,28 @@ private: class HttpIpsOption : public snort::IpsOption { public: - HttpIpsOption(const HttpCursorModule* cm) : + 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->buffer_index, cm->sub_id, cm->form, - cm->para_list.param, cm->para_list.nocase) {} + buffer_info(cm->rule_opt_index, cm->sub_id, cm->form, + cm->para_list.param, cm->para_list.nocase), range(cm->para_list.range){} snort::CursorActionType get_cursor_type() const override { return cat; } EvalStatus eval(Cursor&, snort::Packet*) override; 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((HttpCursorModule*)m); } + { return new HttpIpsOption((HttpRuleOptModule*)m); } static void opt_dtor(snort::IpsOption* p) { delete 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; }; #endif diff --git a/src/stream/tcp/ips_stream_size.cc b/src/stream/tcp/ips_stream_size.cc index ce3cd5f5a..dff965734 100644 --- a/src/stream/tcp/ips_stream_size.cc +++ b/src/stream/tcp/ips_stream_size.cc @@ -64,18 +64,12 @@ private: uint32_t SizeOption::hash() const { - uint32_t a = ssod.op; - uint32_t b = ssod.min; - uint32_t c = ssod.max; - - mix(a,b,c); - - a = direction; - b += IpsOption::hash(); + uint32_t a = ssod.hash(); + uint32_t b = direction; + uint32_t c = IpsOption::hash(); mix(a,b,c); finalize(a,b,c); - return c; }