From: Mike Stepanek (mstepane) Date: Tue, 18 Feb 2020 15:27:42 +0000 (+0000) Subject: Merge pull request #2001 in SNORT/snort3 from ~KATHARVE/snort3:h2i_disable_detection... X-Git-Tag: 3.0.0-268~7 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=736ff5736ed8a746d6c6cb3802f921224948b1b2;p=thirdparty%2Fsnort3.git Merge pull request #2001 in SNORT/snort3 from ~KATHARVE/snort3:h2i_disable_detection to master Squashed commit of the following: commit 3f544dd8749a9ea7f25cdbafa29582b0396ade31 Author: Katura Harvey Date: Fri Feb 7 13:32:24 2020 -0500 http2_inspect: support disabling detection for uninteresting HTTP/2 frames http_inspect: when detection is disabled, disable all rules not just content rules --- diff --git a/src/detection/detection_engine.cc b/src/detection/detection_engine.cc index 25d13c2f4..18dd43897 100644 --- a/src/detection/detection_engine.cc +++ b/src/detection/detection_engine.cc @@ -324,7 +324,11 @@ void DetectionEngine::clear_replacement() } void DetectionEngine::disable_all(Packet* p) -{ p->context->active_rules = IpsContext::NONE; } +{ + p->context->active_rules = IpsContext::NONE; + trace_logf(detection, TRACE_PKT_DETECTION, + "Disabled all detect, packet %" PRIu64"\n", p->context->packet_number); +} bool DetectionEngine::all_disabled(Packet* p) { return p->context->active_rules == IpsContext::NONE; } diff --git a/src/service_inspectors/http2_inspect/http2_dummy_packet.h b/src/service_inspectors/http2_inspect/http2_dummy_packet.h new file mode 100644 index 000000000..1ab7e1676 --- /dev/null +++ b/src/service_inspectors/http2_inspect/http2_dummy_packet.h @@ -0,0 +1,43 @@ +//-------------------------------------------------------------------------- +// Copyright (C) 2020-2020 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. +//-------------------------------------------------------------------------- +// http2_dummy_packet.h author Katura Harvey + +/* + * The purpose of this Packet subclass is to enable H2I to take direction from http_inspect on + * whether or not to send a frame to detection. When http_inspect is processing normal HTTP/1.1 + * traffic it is dealing with a 'real' packet that has a context, the field on which disable_all() + * is called to disable detection on that packet. With HTTP/2 traffic, http_inspect is processing a + * dummy packet that H2I created, which does not contain a context object. Rather than create an + * entire new context object when we really only need a bool, http_inspect checks if the flow is + * HTTP/2 and sets a bool instead of calling it's usual disable_all(). H2I checks the bool and can + * then call disable_all() on the real packet. + */ + +#ifndef HTTP2_DUMMY_PACKET_H +#define HTTP2_DUMMY_PACKET_H + +#include "protocols/packet.h" + +class Http2DummyPacket : public snort::Packet +{ +public: + Http2DummyPacket() : snort::Packet(false) { } + bool is_detection_required() { return !disable_inspect; } +}; + +#endif diff --git a/src/service_inspectors/http2_inspect/http2_frame.h b/src/service_inspectors/http2_inspect/http2_frame.h index cd131e44c..861f43e96 100644 --- a/src/service_inspectors/http2_inspect/http2_frame.h +++ b/src/service_inspectors/http2_inspect/http2_frame.h @@ -43,6 +43,8 @@ public: virtual void clear() { } virtual const Field& get_buf(unsigned id); virtual uint32_t get_xtradata_mask() { return 0; } + virtual bool is_detection_required() const { return true; } + #ifdef REG_TEST virtual void print_frame(FILE* output); #endif diff --git a/src/service_inspectors/http2_inspect/http2_headers_frame.cc b/src/service_inspectors/http2_inspect/http2_headers_frame.cc index a771f3f77..07ab5632b 100644 --- a/src/service_inspectors/http2_inspect/http2_headers_frame.cc +++ b/src/service_inspectors/http2_inspect/http2_headers_frame.cc @@ -28,6 +28,7 @@ #include "service_inspectors/http_inspect/http_inspect.h" #include "service_inspectors/http_inspect/http_stream_splitter.h" +#include "http2_dummy_packet.h" #include "http2_enum.h" #include "http2_flow_data.h" #include "http2_hpack.h" @@ -79,7 +80,7 @@ Http2HeadersFrame::Http2HeadersFrame(const uint8_t* header_buffer, const int32_t session_data->stream_in_hi = session_data->current_stream[source_id]; { uint32_t flush_offset; - Packet dummy_pkt(false); + Http2DummyPacket dummy_pkt; dummy_pkt.flow = session_data->flow; const uint32_t unused = 0; const StreamSplitter::Status start_scan_result = @@ -103,7 +104,7 @@ Http2HeadersFrame::Http2HeadersFrame(const uint8_t* header_buffer, const int32_t // http_inspect eval() and clear() of start line { - Packet dummy_pkt(false); + Http2DummyPacket dummy_pkt; dummy_pkt.flow = session_data->flow; dummy_pkt.packet_flags = (source_id == SRC_CLIENT) ? PKT_FROM_CLIENT : PKT_FROM_SERVER; dummy_pkt.dsize = stream_buf.length; @@ -115,7 +116,7 @@ Http2HeadersFrame::Http2HeadersFrame(const uint8_t* header_buffer, const int32_t // http_inspect scan() of headers { uint32_t flush_offset; - Packet dummy_pkt(false); + Http2DummyPacket dummy_pkt; dummy_pkt.flow = session_data->flow; const uint32_t unused = 0; const StreamSplitter::Status header_scan_result = @@ -143,13 +144,14 @@ Http2HeadersFrame::Http2HeadersFrame(const uint8_t* header_buffer, const int32_t // http_inspect eval() of headers { - Packet dummy_pkt(false); + Http2DummyPacket dummy_pkt; dummy_pkt.flow = session_data->flow; dummy_pkt.packet_flags = (source_id == SRC_CLIENT) ? PKT_FROM_CLIENT : PKT_FROM_SERVER; dummy_pkt.dsize = stream_buf.length; dummy_pkt.data = stream_buf.data; dummy_pkt.xtradata_mask = 0; session_data->hi->eval(&dummy_pkt); + detection_required = dummy_pkt.is_detection_required(); xtradata_mask = dummy_pkt.xtradata_mask; } } diff --git a/src/service_inspectors/http2_inspect/http2_headers_frame.h b/src/service_inspectors/http2_inspect/http2_headers_frame.h index 9772b3aa6..27722facc 100644 --- a/src/service_inspectors/http2_inspect/http2_headers_frame.h +++ b/src/service_inspectors/http2_inspect/http2_headers_frame.h @@ -35,6 +35,7 @@ public: const Field& get_buf(unsigned id) override; uint32_t get_xtradata_mask() override { return xtradata_mask; } + bool is_detection_required() const override { return detection_required; } friend Http2Frame* Http2Frame::new_frame(const uint8_t*, const int32_t, const uint8_t*, const int32_t, Http2FlowData*, HttpCommon::SourceId); @@ -56,5 +57,6 @@ private: bool error_during_decode = false; bool hi_abort = false; uint32_t xtradata_mask = 0; + bool detection_required = false; }; #endif diff --git a/src/service_inspectors/http2_inspect/http2_inspect.cc b/src/service_inspectors/http2_inspect/http2_inspect.cc index 836d79365..77de26ffd 100644 --- a/src/service_inspectors/http2_inspect/http2_inspect.cc +++ b/src/service_inspectors/http2_inspect/http2_inspect.cc @@ -129,6 +129,8 @@ void Http2Inspect::eval(Packet* p) session_data->frame_header_size[source_id], session_data->frame_data[source_id], session_data->frame_data_size[source_id], source_id); + if (!stream->get_current_frame()->is_detection_required()) + DetectionEngine::disable_all(p); p->xtradata_mask |= stream->get_xtradata_mask(); // The current frame now owns these buffers, clear them from the flow data diff --git a/src/service_inspectors/http2_inspect/http2_settings_frame.h b/src/service_inspectors/http2_inspect/http2_settings_frame.h index 00e194d69..f78803819 100644 --- a/src/service_inspectors/http2_inspect/http2_settings_frame.h +++ b/src/service_inspectors/http2_inspect/http2_settings_frame.h @@ -31,6 +31,7 @@ class Http2SettingsFrame : public Http2Frame public: friend Http2Frame* Http2Frame::new_frame(const uint8_t*, const int32_t, const uint8_t*, const int32_t, Http2FlowData*, HttpCommon::SourceId); + bool is_detection_required() const override { return false; } #ifdef REG_TEST void print_frame(FILE* output) override; diff --git a/src/service_inspectors/http2_inspect/http2_stream.h b/src/service_inspectors/http2_inspect/http2_stream.h index 777b2e2b3..a267335b3 100644 --- a/src/service_inspectors/http2_inspect/http2_stream.h +++ b/src/service_inspectors/http2_inspect/http2_stream.h @@ -46,6 +46,7 @@ public: void set_hi_msg_section(HttpMsgSection* section) { hi_msg_section = section; } uint32_t get_xtradata_mask() { return (current_frame != nullptr) ? current_frame->get_xtradata_mask() : 0; } + Http2Frame *get_current_frame() { return current_frame; } #ifdef REG_TEST void print_frame(FILE* output); #endif diff --git a/src/service_inspectors/http_inspect/http_inspect.cc b/src/service_inspectors/http_inspect/http_inspect.cc index 7c555a7b0..39f522d86 100644 --- a/src/service_inspectors/http_inspect/http_inspect.cc +++ b/src/service_inspectors/http_inspect/http_inspect.cc @@ -27,6 +27,7 @@ #include "detection/detection_engine.h" #include "detection/detection_util.h" +#include "service_inspectors/http2_inspect/http2_dummy_packet.h" #include "service_inspectors/http2_inspect/http2_flow_data.h" #include "log/unified2.h" #include "protocols/packet.h" @@ -310,6 +311,18 @@ int HttpInspect::get_xtra_jsnorm(Flow* flow, uint8_t** buf, uint32_t* len, uint3 return 1; } +void HttpInspect::disable_detection(Packet* p) +{ + HttpFlowData* session_data = http_get_flow_data(p->flow); + if (session_data->for_http2) + p->disable_inspect = true; + else + { + assert(p->context); + DetectionEngine::disable_all(p); + } +} + HttpFlowData* HttpInspect::http_get_flow_data(const Flow* flow) { Http2FlowData* h2i_flow_data = nullptr; @@ -363,10 +376,7 @@ void HttpInspect::eval(Packet* p) const bool buf_owner = !session_data->partial_flush[source_id]; if (!process(p->data, p->dsize, p->flow, source_id, buf_owner)) - { - if (!session_data->for_http2) - DetectionEngine::disable_content(p); - } + disable_detection(p); #ifdef REG_TEST else diff --git a/src/service_inspectors/http_inspect/http_inspect.h b/src/service_inspectors/http_inspect/http_inspect.h index 40ebda7e0..77b024804 100644 --- a/src/service_inspectors/http_inspect/http_inspect.h +++ b/src/service_inspectors/http_inspect/http_inspect.h @@ -56,6 +56,7 @@ public: } static HttpEnums::InspectSection get_latest_is(const snort::Packet* p); static HttpCommon::SourceId get_latest_src(const snort::Packet* p); + void disable_detection(snort::Packet *p); // Callbacks that provide "extra data" static int get_xtra_trueip(snort::Flow*, uint8_t**, uint32_t*, uint32_t*);