}
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; }
--- /dev/null
+//--------------------------------------------------------------------------
+// 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 <katharve@cisco.com>
+
+/*
+ * 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
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
#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"
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 =
// 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;
// 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 =
// 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;
}
}
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);
bool error_during_decode = false;
bool hi_abort = false;
uint32_t xtradata_mask = 0;
+ bool detection_required = false;
};
#endif
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
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;
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
#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"
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;
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
}
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*);