]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Pull request #3506: http_inspect directly calls detection
authorTom Peters (thopeter) <thopeter@cisco.com>
Fri, 22 Jul 2022 18:20:21 +0000 (18:20 +0000)
committerTom Peters (thopeter) <thopeter@cisco.com>
Fri, 22 Jul 2022 18:20:21 +0000 (18:20 +0000)
Merge in SNORT/snort3 from ~THOPETER/snort3:nhttp164 to master

Squashed commit of the following:

commit 0b70bc4f11ef4639ef8fa5cd33bcfd9b0d80b57d
Author: Tom Peters <thopeter@cisco.com>
Date:   Mon Jun 27 13:19:09 2022 -0400

    http_inspect: directly call detection

commit 792288626c150c068752c053d2de20d39845c74b
Author: Tom Peters <thopeter@cisco.com>
Date:   Tue Jul 5 16:15:35 2022 -0400

    http2_inspect: Interface to http_inspect now uses real reassembled packet

25 files changed:
src/service_inspectors/http2_inspect/http2_data_cutter.cc
src/service_inspectors/http2_inspect/http2_data_frame.cc
src/service_inspectors/http2_inspect/http2_data_frame.h
src/service_inspectors/http2_inspect/http2_dummy_packet.h [deleted file]
src/service_inspectors/http2_inspect/http2_frame.h
src/service_inspectors/http2_inspect/http2_headers_frame.cc
src/service_inspectors/http2_inspect/http2_headers_frame.h
src/service_inspectors/http2_inspect/http2_headers_frame_header.cc
src/service_inspectors/http2_inspect/http2_headers_frame_header.h
src/service_inspectors/http2_inspect/http2_headers_frame_trailer.cc
src/service_inspectors/http2_inspect/http2_headers_frame_trailer.h
src/service_inspectors/http2_inspect/http2_headers_frame_with_startline.cc
src/service_inspectors/http2_inspect/http2_headers_frame_with_startline.h
src/service_inspectors/http2_inspect/http2_inspect.cc
src/service_inspectors/http2_inspect/http2_push_promise_frame.cc
src/service_inspectors/http2_inspect/http2_push_promise_frame.h
src/service_inspectors/http2_inspect/http2_stream.cc
src/service_inspectors/http2_inspect/http2_stream.h
src/service_inspectors/http2_inspect/http2_utils.cc
src/service_inspectors/http_inspect/http_inspect.cc
src/service_inspectors/http_inspect/http_inspect.h
src/service_inspectors/http_inspect/http_msg_section.cc
src/service_inspectors/http_inspect/http_msg_section.h
src/service_inspectors/http_inspect/http_stream_splitter.h
src/service_inspectors/http_inspect/http_stream_splitter_scan.cc

index 89ff65ba27106d14dd1714154b62e0c4697e55e7..fc20430ce4afab4490551719e9a6cac1ff9a9ef9 100644 (file)
@@ -26,7 +26,6 @@
 #include "service_inspectors/http_inspect/http_flow_data.h"
 #include "service_inspectors/http_inspect/http_stream_splitter.h"
 
-#include "http2_dummy_packet.h"
 #include "http2_utils.h"
 
 using namespace snort;
@@ -131,17 +130,14 @@ StreamSplitter::Status Http2DataCutter::scan(const uint8_t* data, uint32_t lengt
     if (cur_data > 0)
     {
         uint32_t http_flush_offset = 0;
-        Http2DummyPacket dummy_pkt;
-        dummy_pkt.flow = session_data->flow;
-        uint32_t unused = 0;
         session_data->stream_in_hi = session_data->current_stream[source_id];
         if ((data_bytes_read == data_len) && (frame_flags & FLAG_END_STREAM))
         {
             HttpFlowData* const hi_flow = stream->get_hi_flow_data();
             hi_flow->set_h2_body_state(source_id, H2_BODY_LAST_SEG);
         }
-        scan_result = session_data->hi_ss[source_id]->scan(&dummy_pkt, data + cur_data_offset,
-            cur_data, unused, &http_flush_offset);
+        scan_result = session_data->hi_ss[source_id]->scan(session_data->flow, data + cur_data_offset, cur_data,
+            &http_flush_offset);
         session_data->stream_in_hi = NO_STREAM_ID;
         switch (scan_result)
         {
index 57b55fe57f38fefdd04318d1ce34072cbb9c52dc..fa90b80a0926720d79d23f9b0c2affe9ab253b19 100644 (file)
@@ -27,7 +27,6 @@
 #include "service_inspectors/http_inspect/http_inspect.h"
 #include "service_inspectors/http_inspect/http_stream_splitter.h"
 
-#include "http2_dummy_packet.h"
 #include "http2_flow_data.h"
 #include "http2_module.h"
 
@@ -48,25 +47,15 @@ bool Http2DataFrame::valid_sequence(Http2Enums::StreamState state)
     return (state == Http2Enums::STREAM_EXPECT_BODY) || (state == Http2Enums::STREAM_BODY);
 }
 
-void Http2DataFrame::analyze_http1()
+void Http2DataFrame::analyze_http1(Packet* p)
 {
-    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 = data_length;
-    dummy_pkt.data = data_buffer;
-    dummy_pkt.xtradata_mask = 0;
     // FIXIT-E no checks here
-    session_data->hi->eval(&dummy_pkt);
-    detection_required = dummy_pkt.is_detection_required();
-    xtradata_mask = dummy_pkt.xtradata_mask;
+    session_data->hi->eval(p, source_id, data_buffer, data_length);
 }
 
-void Http2DataFrame::clear()
+void Http2DataFrame::clear(Packet* p)
 {
-    Http2DummyPacket dummy_pkt;
-    dummy_pkt.flow = session_data->flow;
-    session_data->hi->clear(&dummy_pkt);
+    session_data->hi->clear(p);
 }
 
 void Http2DataFrame::update_stream_state()
index c4dfd24c4e9a82d723b5aec3cf682ad08e0939e3..345e77eab4f351f5d65f7a0d96e84da8473ebf68 100644 (file)
@@ -30,11 +30,10 @@ class Http2DataFrame : public Http2Frame
 public:
     ~Http2DataFrame() override = default;
     bool valid_sequence(Http2Enums::StreamState state) override;
-    void analyze_http1() override;
-    void clear() override;
+    void analyze_http1(snort::Packet*) override;
+    void clear(snort::Packet*) override;
 
-    uint32_t get_xtradata_mask() override { return xtradata_mask; }
-    bool is_detection_required() const override { return detection_required; }
+    bool is_detection_required() const override { return false; }
     void update_stream_state() override;
 
     friend Http2Frame* Http2Frame::new_frame(const uint8_t*, const uint32_t, const uint8_t*,
@@ -52,7 +51,5 @@ private:
 
     const uint32_t data_length;
     const uint8_t* const data_buffer;
-    uint32_t xtradata_mask = 0;
-    bool detection_required = false;
 };
 #endif
diff --git a/src/service_inspectors/http2_inspect/http2_dummy_packet.h b/src/service_inspectors/http2_inspect/http2_dummy_packet.h
deleted file mode 100644 (file)
index cafe3b0..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-//--------------------------------------------------------------------------
-// Copyright (C) 2020-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.
-//--------------------------------------------------------------------------
-// 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
index 7b4c601684ff37d0ea8919775429e6cd8154eb58..38991a07cfbac2a9c882548f40ff46196949a957 100644 (file)
@@ -20,6 +20,7 @@
 #ifndef HTTP2_FRAME_H
 #define HTTP2_FRAME_H
 
+#include "protocols/packet.h"
 #include "service_inspectors/http_inspect/http_common.h"
 #include "service_inspectors/http_inspect/http_field.h"
 
@@ -44,10 +45,9 @@ public:
         const uint8_t* data_buffer, const uint32_t data_len, Http2FlowData* session_data,
         HttpCommon::SourceId source_id, Http2Stream* stream);
     virtual bool valid_sequence(Http2Enums::StreamState) { return true; }
-    virtual void analyze_http1() { }
-    virtual void clear() { }
+    virtual void analyze_http1(snort::Packet*) { }
+    virtual void clear(snort::Packet*) { }
     virtual const Field& get_buf(unsigned id);
-    virtual uint32_t get_xtradata_mask() { return 0; }
     virtual bool is_detection_required() const { return true; }
     virtual void update_stream_state() { }
 
index 239e44633fec9f72c0ac9215d5dddfc2f25e4c45..bbcac25672910569198d2209ca4eb69fa78b18fd 100644 (file)
@@ -28,7 +28,6 @@
 #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"
@@ -57,13 +56,11 @@ bool Http2HeadersFrame::in_error_state() const
     return stream->get_state(source_id) == STREAM_ERROR;
 }
 
-void Http2HeadersFrame::clear()
+void Http2HeadersFrame::clear(Packet* p)
 {
     if (session_data->abort_flow[source_id] || in_error_state())
         return;
-    Packet dummy_pkt(false);
-    dummy_pkt.flow = session_data->flow;
-    session_data->hi->clear(&dummy_pkt);
+    session_data->hi->clear(p);
 }
 
 bool Http2HeadersFrame::decode_headers(Http2StartLine* start_line_generator, bool trailers)
@@ -87,7 +84,7 @@ bool Http2HeadersFrame::decode_headers(Http2StartLine* start_line_generator, boo
     return true;
 }
 
-void Http2HeadersFrame::process_decoded_headers(HttpFlowData* http_flow, SourceId hi_source_id)
+void Http2HeadersFrame::process_decoded_headers(HttpFlowData* http_flow, SourceId hi_source_id, Packet* p)
 {
     if (session_data->abort_flow[source_id] or http1_header.length() < 0)
         return;
@@ -110,12 +107,9 @@ void Http2HeadersFrame::process_decoded_headers(HttpFlowData* http_flow, SourceI
     if (http1_header.length() > 0)
     {
         uint32_t flush_offset;
-        Http2DummyPacket dummy_pkt;
-        dummy_pkt.flow = session_data->flow;
-        const uint32_t unused = 0;
         const StreamSplitter::Status header_scan_result =
-            session_data->hi_ss[hi_source_id]->scan(&dummy_pkt, http1_header.start(),
-            http1_header.length(), unused, &flush_offset);
+            session_data->hi_ss[hi_source_id]->scan(session_data->flow, http1_header.start(), http1_header.length(),
+            &flush_offset);
         assert((session_data->is_processing_partial_header() and
                 (header_scan_result == StreamSplitter::SEARCH)) or
             ((!session_data->is_processing_partial_header() and
@@ -145,20 +139,13 @@ void Http2HeadersFrame::process_decoded_headers(HttpFlowData* http_flow, SourceI
 
     // http_inspect eval() of headers
     {
-        Http2DummyPacket dummy_pkt;
-        dummy_pkt.flow = session_data->flow;
-        dummy_pkt.packet_flags = (hi_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);
+        session_data->hi->eval(p, hi_source_id, stream_buf.data, stream_buf.length);
+
         if (http_flow->get_type_expected(hi_source_id) == SEC_ABORT)
         {
             assert(session_data->is_processing_partial_header());
             stream->set_state(hi_source_id, STREAM_ERROR);
         }
-        detection_required = dummy_pkt.is_detection_required();
-        xtradata_mask = dummy_pkt.xtradata_mask;
     }
 }
 
index 9e3ea126255f95da71e2a992d16404a1e7f2481b..22451b8723394dd1e446fd39b60a6ad1b0859b9e 100644 (file)
@@ -32,11 +32,10 @@ class HttpFlowData;
 class Http2HeadersFrame : public Http2Frame
 {
 public:
-    void clear() override;
+    void clear(snort::Packet*) override;
 
     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; }
+    bool is_detection_required() const override { return false; }
 
 #ifdef REG_TEST
     void print_frame(FILE* output) override;
@@ -47,13 +46,11 @@ protected:
         const uint8_t* data_buffer, const uint32_t data_len, Http2FlowData* ssn_data,
         HttpCommon::SourceId src_id, Http2Stream* stream);
     bool decode_headers(Http2StartLine* start_line_generator, bool trailers);
-    void process_decoded_headers(HttpFlowData* http_flow, HttpCommon::SourceId hi_source_id);
+    void process_decoded_headers(HttpFlowData* http_flow, HttpCommon::SourceId hi_source_id, snort::Packet* p);
     uint8_t get_flags_mask() const override;
     virtual bool in_error_state() const;
 
     Field http1_header;                 // finalized headers to be passed to http_inspect
-    uint32_t xtradata_mask = 0;
-    bool detection_required = false;
     Http2HpackDecoder* hpack_decoder;
     uint8_t hpack_headers_offset = 0;
 };
index 41b823084416cb51393cc536ff5be0e1cc94db05..deff6a11351b5bc3e90f4014558d3168710f2804 100644 (file)
@@ -64,17 +64,17 @@ bool Http2HeadersFrameHeader::valid_sequence(Http2Enums::StreamState state)
     return (state == Http2Enums::STREAM_EXPECT_HEADERS);
 }
 
-void Http2HeadersFrameHeader::analyze_http1()
+void Http2HeadersFrameHeader::analyze_http1(Packet* p)
 {
     HttpFlowData* http_flow;
-    if (!process_start_line(http_flow, source_id))
+    if (!process_start_line(http_flow, source_id, p))
         return;
 
     // if END_STREAM flag set on headers, tell http_inspect not to expect a message body
     if (get_flags() & FLAG_END_STREAM)
         stream->get_hi_flow_data()->finish_h2_body(source_id, H2_BODY_NO_BODY, false);
 
-    process_decoded_headers(http_flow, source_id);
+    process_decoded_headers(http_flow, source_id, p);
 }
 
 void Http2HeadersFrameHeader::update_stream_state()
index 144ffe675173b98b430154931802ec748afb4e9e..88f61a3f8466dbc3b7a9f35190ae2d9968e6aba1 100644 (file)
@@ -32,7 +32,7 @@ public:
         const uint32_t, Http2FlowData*, HttpCommon::SourceId, Http2Stream* stream);
 
     bool valid_sequence(Http2Enums::StreamState state) override;
-    void analyze_http1() override;
+    void analyze_http1(snort::Packet*) override;
     void update_stream_state() override;
 
 #ifdef REG_TEST
index 7925e9861f8388f2cf983f740dce0cc6927af704..365f6d2f3ea865d7de021ad8605274ac904acd13 100644 (file)
@@ -28,7 +28,6 @@
 #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"
@@ -65,7 +64,7 @@ bool Http2HeadersFrameTrailer::valid_sequence(Http2Enums::StreamState state)
     return false;
 }
 
-void Http2HeadersFrameTrailer::analyze_http1()
+void Http2HeadersFrameTrailer::analyze_http1(Packet* p)
 {
     HttpFlowData* const http_flow = stream->get_hi_flow_data();
     assert(http_flow);
@@ -86,19 +85,14 @@ void Http2HeadersFrameTrailer::analyze_http1()
 
         if (stream_buf.data != nullptr)
         {
-            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;
-            session_data->hi->eval(&dummy_pkt);
+            session_data->hi->eval(p, source_id, stream_buf.data, stream_buf.length);
             assert (!valid_headers || http_flow->get_type_expected(source_id) == SEC_TRAILER);
             if (http_flow->get_type_expected(source_id) == SEC_ABORT)
             {
                 stream->set_state(source_id, STREAM_ERROR);
                 return;
             }
-            session_data->hi->clear(&dummy_pkt);
+            session_data->hi->clear(p);
         }
     }
 
@@ -108,7 +102,7 @@ void Http2HeadersFrameTrailer::analyze_http1()
         return;
     }
 
-    process_decoded_headers(http_flow, source_id);
+    process_decoded_headers(http_flow, source_id, p);
 }
 
 void Http2HeadersFrameTrailer::update_stream_state()
index 046a60e457fbfb0c33f7853674d9189ecc1f723d..87970b9aa539a79fb8b56b64a0715d2f410c4657 100644 (file)
@@ -30,7 +30,7 @@ public:
         const uint32_t, Http2FlowData*, HttpCommon::SourceId, Http2Stream* stream);
 
     bool valid_sequence(Http2Enums::StreamState state) override;
-    void analyze_http1() override;
+    void analyze_http1(snort::Packet*) override;
     void update_stream_state() override;
 
 #ifdef REG_TEST
index 057ed1031f33bc72ce4087e160ee035ad0d0d344..8ab841ea9a8108ada2da4296d828911182960694 100644 (file)
@@ -28,7 +28,6 @@
 #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"
@@ -47,8 +46,7 @@ Http2HeadersFrameWithStartline::~Http2HeadersFrameWithStartline()
     delete start_line_generator;
 }
 
-bool Http2HeadersFrameWithStartline::process_start_line(HttpFlowData*& http_flow,
-    SourceId hi_source_id)
+bool Http2HeadersFrameWithStartline::process_start_line(HttpFlowData*& http_flow, SourceId hi_source_id, Packet* p)
 {
     if (session_data->abort_flow[source_id])
         return false;
@@ -56,12 +54,9 @@ bool Http2HeadersFrameWithStartline::process_start_line(HttpFlowData*& http_flow
     // http_inspect scan() of start line
     {
         uint32_t flush_offset;
-        Http2DummyPacket dummy_pkt;
-        dummy_pkt.flow = session_data->flow;
-        const uint32_t unused = 0;
         const StreamSplitter::Status start_scan_result =
-            session_data->hi_ss[hi_source_id]->scan(&dummy_pkt, start_line.start(),
-                start_line.length(), unused, &flush_offset);
+            session_data->hi_ss[hi_source_id]->scan(session_data->flow, start_line.start(), start_line.length(),
+            &flush_offset);
         if (start_scan_result != StreamSplitter::FLUSH)
         {
             stream->set_state(hi_source_id, STREAM_ERROR);
@@ -86,18 +81,13 @@ bool Http2HeadersFrameWithStartline::process_start_line(HttpFlowData*& http_flow
     assert(http_flow);
     // http_inspect eval() and clear() of start line
     {
-        Http2DummyPacket dummy_pkt;
-        dummy_pkt.flow = session_data->flow;
-        dummy_pkt.packet_flags = (hi_source_id == SRC_CLIENT) ? PKT_FROM_CLIENT : PKT_FROM_SERVER;
-        dummy_pkt.dsize = stream_buf.length;
-        dummy_pkt.data = stream_buf.data;
-        session_data->hi->eval(&dummy_pkt);
+        session_data->hi->eval(p, hi_source_id, stream_buf.data, stream_buf.length);
         if (http_flow->get_type_expected(hi_source_id) != SEC_HEADER)
         {
             stream->set_state(hi_source_id, STREAM_ERROR);
             return false;
         }
-        session_data->hi->clear(&dummy_pkt);
+        session_data->hi->clear(p);
     }
     return true;
 }
index 07528b04bdfe4cf8fe196a0ac8c4ebe3a28b8e4d..fb02dd3eb115ae20522797a77610d26aa0fc2c20 100644 (file)
@@ -46,7 +46,7 @@ protected:
         HttpCommon::SourceId src_id, Http2Stream* stream_) :
         Http2HeadersFrame(header_buffer, header_len, data_buffer, data_len, ssn_data, src_id,
             stream_) { }
-    bool process_start_line(HttpFlowData*& http_flow, HttpCommon::SourceId hi_source_id);
+    bool process_start_line(HttpFlowData*& http_flow, HttpCommon::SourceId hi_source_id, snort::Packet* p);
     bool are_pseudo_headers_complete();
 
     Http2StartLine* start_line_generator = nullptr;
index 6243ad9f30891929c84c4156e0f175cd233672f7..86556d4a947b8b71241ed9774776d5592f6432db 100644 (file)
@@ -83,7 +83,7 @@ bool Http2Inspect::get_buf(unsigned id, Packet* p, InspectionBuffer& b)
 
     // Otherwise we can return buffers for raw packets because frame header is available before
     // frame is reassembled.
-    if (!session_data->frame_in_detection)
+    if (session_data->stream_in_hi == Http2Enums::NO_STREAM_ID)
         return false;
 
     Http2Stream* const stream = session_data->find_processing_stream();
@@ -151,11 +151,10 @@ void Http2Inspect::eval(Packet* p)
     uint8_t* const frame_header_copy = new uint8_t[FRAME_HEADER_LENGTH];
     memcpy(frame_header_copy, session_data->lead_frame_header[source_id], FRAME_HEADER_LENGTH);
     stream->eval_frame(frame_header_copy, FRAME_HEADER_LENGTH,
-        session_data->frame_data[source_id], session_data->frame_data_size[source_id], source_id);
+        session_data->frame_data[source_id], session_data->frame_data_size[source_id], source_id, p);
 
     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
     session_data->frame_data[source_id] = nullptr;
@@ -199,7 +198,7 @@ void Http2Inspect::clear(Packet* p)
 
     Http2Stream* stream = session_data->find_processing_stream();
     assert(stream != nullptr);
-    stream->clear_frame();
+    stream->clear_frame(p);
     if (session_data->delete_stream)
         session_data->delete_processing_stream();
     session_data->stream_in_hi = NO_STREAM_ID;
index 2083985cf0d027db3da30eceecd1ae7848acc5b0..c21899b3c0925d2ab3b31b4d96100ac1f176679e 100644 (file)
@@ -100,7 +100,7 @@ bool Http2PushPromiseFrame::valid_sequence(Http2Enums::StreamState)
     return true;
 }
 
-void Http2PushPromiseFrame::analyze_http1()
+void Http2PushPromiseFrame::analyze_http1(Packet* p)
 {
     if (!start_line_generator->generate_start_line(start_line, are_pseudo_headers_complete()))
     {
@@ -111,14 +111,14 @@ void Http2PushPromiseFrame::analyze_http1()
     }
 
     HttpFlowData* http_flow;
-    if (!process_start_line(http_flow, SRC_CLIENT))
+    if (!process_start_line(http_flow, SRC_CLIENT, p))
         return;
 
     // Push promise cannot have a message body
     // FIXIT-E handle bad request lines and cases where a message body is implied
     stream->get_hi_flow_data()->finish_h2_body(SRC_CLIENT, H2_BODY_NO_BODY, false);
 
-    process_decoded_headers(http_flow, SRC_CLIENT);
+    process_decoded_headers(http_flow, SRC_CLIENT, p);
 }
 
 void Http2PushPromiseFrame::update_stream_state()
index 8a2e7da93c57353582d462b8fb36dca4ff67c5f8..2c56f2974136008e747ab00eb6575ce2649c9a4f 100644 (file)
@@ -41,7 +41,7 @@ class Http2PushPromiseFrame : public Http2HeadersFrameWithStartline
 {
 public:
     bool valid_sequence(Http2Enums::StreamState state) override;
-    void analyze_http1() override;
+    void analyze_http1(snort::Packet*) override;
     void update_stream_state() override;
     static uint32_t get_promised_stream_id(Http2EventGen* const events,
         Http2Infractions* const infractions, const uint8_t* data_buffer, uint32_t data_len);
index cdbdbcf6fc619701717d32abe9b96cdfd6c1ec04..aea2b4b5479f4e2383a6377289d6e1823aba7425 100644 (file)
@@ -28,9 +28,9 @@
 #include "service_inspectors/http_inspect/http_stream_splitter.h"
 
 #include "http2_data_cutter.h"
-#include "http2_dummy_packet.h"
 #include "http2_flow_data.h"
 
+using namespace snort;
 using namespace HttpCommon;
 using namespace Http2Enums;
 
@@ -47,7 +47,7 @@ Http2Stream::~Http2Stream()
 }
 
 void Http2Stream::eval_frame(const uint8_t* header_buffer, uint32_t header_len,
-    const uint8_t* data_buffer, uint32_t data_len, SourceId source_id)
+    const uint8_t* data_buffer, uint32_t data_len, SourceId source_id, Packet* p)
 {
     assert(current_frame == nullptr);
     current_frame = Http2Frame::new_frame(header_buffer, header_len, data_buffer,
@@ -56,7 +56,7 @@ void Http2Stream::eval_frame(const uint8_t* header_buffer, uint32_t header_len,
     {
         if (current_frame->valid_sequence(state[source_id]))
         {
-            current_frame->analyze_http1();
+            current_frame->analyze_http1(p);
             current_frame->update_stream_state();
         }
         else
@@ -80,10 +80,10 @@ void Http2Stream::check_and_cleanup_completed()
     }
 }
 
-void Http2Stream::clear_frame()
+void Http2Stream::clear_frame(Packet* p)
 {
     assert(current_frame != nullptr);
-    current_frame->clear();
+    current_frame->clear(p);
     delete current_frame;
     current_frame = nullptr;
 
@@ -130,17 +130,14 @@ void Http2Stream::finish_msg_body(HttpCommon::SourceId source_id, bool expect_tr
     bool clear_partial_buffer)
 {
     uint32_t http_flush_offset = 0;
-    Http2DummyPacket dummy_pkt;
-    dummy_pkt.flow = session_data->flow;
     const H2BodyState body_state = expect_trailers ?
         H2_BODY_COMPLETE_EXPECT_TRAILERS : H2_BODY_COMPLETE;
     get_hi_flow_data()->finish_h2_body(source_id, body_state, clear_partial_buffer);
     if (clear_partial_buffer)
     {
-        uint32_t unused = 0;
-        const snort::StreamSplitter::Status scan_result = session_data->hi_ss[source_id]->scan(
-            &dummy_pkt, nullptr, 0, unused, &http_flush_offset);
-        assert(scan_result == snort::StreamSplitter::FLUSH);
+        const StreamSplitter::Status scan_result = session_data->hi_ss[source_id]->scan(
+            session_data->flow, nullptr, 0, &http_flush_offset);
+        assert(scan_result == StreamSplitter::FLUSH);
         UNUSED(scan_result);
     }
 }
index efea49d933924550a227680078687e49318e5a59..d9071b8a718102aa51a86ee40cb1b119864d3ceb 100644 (file)
@@ -38,14 +38,12 @@ public:
     ~Http2Stream();
     uint32_t get_stream_id() const { return stream_id; }
     void eval_frame(const uint8_t* header_buffer, uint32_t header_len, const uint8_t* data_buffer,
-        uint32_t data_len, HttpCommon::SourceId source_id);
+        uint32_t data_len, HttpCommon::SourceId source_id, snort::Packet* p);
     void check_and_cleanup_completed();
-    void clear_frame();
+    void clear_frame(snort::Packet* p);
     const Field& get_buf(unsigned id);
     HttpFlowData* get_hi_flow_data() const { return hi_flow_data; }
     void set_hi_flow_data(HttpFlowData* flow_data);
-    uint32_t get_xtradata_mask() { return (current_frame != nullptr) ?
-        current_frame->get_xtradata_mask() : 0; }
     Http2Frame *get_current_frame() { return current_frame; }
 
     void set_state(HttpCommon::SourceId source_id, Http2Enums::StreamState new_state);
index bc414e592fb019da6221a60f59a31d513b46684e..cdec8eeb04209d63f72a06be0d2310dc1b61411a 100644 (file)
@@ -25,7 +25,6 @@
 
 #include <cassert>
 
-#include "http2_dummy_packet.h"
 #include "http2_enum.h"
 
 using namespace Http2Enums;
index 60048cdb54d1ee2b1ed36631eedd39132f39ef6f..805fb54a1a97c4fb72b6dceeeaa692c3c1ad30f1 100755 (executable)
@@ -29,7 +29,6 @@
 
 #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"
@@ -489,9 +488,7 @@ int HttpInspect::get_xtra_jsnorm(Flow* flow, uint8_t** buf, uint32_t* len, uint3
 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
+    if (!session_data->for_http2)
     {
         assert(p->context);
         DetectionEngine::disable_all(p);
@@ -525,9 +522,14 @@ void HttpInspect::http_set_flow_data(Flow* flow, HttpFlowData* flow_data)
 
 void HttpInspect::eval(Packet* p)
 {
-    Profile profile(HttpModule::get_profile_stats());
-
     const SourceId source_id = p->is_from_client() ? SRC_CLIENT : SRC_SERVER;
+    eval(p, source_id, p->data, p->dsize);
+    return;
+}
+
+void HttpInspect::eval(Packet* p, SourceId source_id, const uint8_t* data, uint16_t dsize)
+{
+    Profile profile(HttpModule::get_profile_stats());
 
     HttpFlowData* session_data = http_get_flow_data(p->flow);
     if (session_data == nullptr)
@@ -540,17 +542,17 @@ void HttpInspect::eval(Packet* p)
     // use due to calls to HttpInspect::eval on the raw stream_user packet
     if ((session_data->section_type[source_id] == SEC__NOT_COMPUTE) ||
         (session_data->type_expected[source_id] == SEC_ABORT)       ||
-        (session_data->octets_reassembled[source_id] != p->dsize))
+        (session_data->octets_reassembled[source_id] != dsize))
     {
         //assert(session_data->type_expected[source_id] != SEC_ABORT);
         //assert(session_data->section_type[source_id] != SEC__NOT_COMPUTE);
-        //assert(session_data->octets_reassembled[source_id] == p->dsize);
+        //assert(session_data->octets_reassembled[source_id] == dsize);
         session_data->type_expected[source_id] = SEC_ABORT;
         return;
     }
 
     if (!session_data->for_http2)
-        HttpModule::increment_peg_counts(PEG_TOTAL_BYTES, p->dsize);
+        HttpModule::increment_peg_counts(PEG_TOTAL_BYTES, dsize);
 
     session_data->octets_reassembled[source_id] = STAT_NOT_PRESENT;
 
@@ -562,26 +564,18 @@ void HttpInspect::eval(Packet* p)
     }
 
     // Limit alt_dsize of message body sections to request/response depth
+    // p->dsize is not a typo. The actual value on the reassembled packet is what matters for this purpose.
     if ((session_data->detect_depth_remaining[source_id] > 0) &&
         (session_data->detect_depth_remaining[source_id] < p->dsize))
     {
         p->set_detect_limit(session_data->detect_depth_remaining[source_id]);
     }
 
-    if (!process(p->data, p->dsize, p->flow, source_id, true))
-        disable_detection(p);
+    process(data, dsize, p->flow, source_id, true, p);
 
-#ifdef REG_TEST
-    else
-    {
-        if (HttpTestManager::use_test_output(HttpTestManager::IN_HTTP))
-        {
-            fprintf(HttpTestManager::get_output_file(), "Sent to detection %hu octets\n\n",
-                p->dsize);
-            fflush(HttpTestManager::get_output_file());
-        }
-    }
-#endif
+    // Detection was done in process()
+    if (!session_data->for_http2)
+        disable_detection(p);
 
     // If current transaction is complete then we are done with it. This is strictly a memory
     // optimization not necessary for correct operation.
@@ -600,8 +594,8 @@ void HttpInspect::eval(Packet* p)
     SetExtraData(p, xtra_jsnorm_id);
 }
 
-bool HttpInspect::process(const uint8_t* data, const uint16_t dsize, Flow* const flow,
-    SourceId source_id, bool buf_owner) const
+void HttpInspect::process(const uint8_t* data, const uint16_t dsize, Flow* const flow, SourceId source_id,
+    bool buf_owner, Packet* p) const
 {
     HttpMsgSection* current_section;
     HttpFlowData* session_data = http_get_flow_data(flow);
@@ -651,7 +645,7 @@ bool HttpInspect::process(const uint8_t* data, const uint16_t dsize, Flow* const
         {
             delete[] data;
         }
-        return false;
+        return;
     }
 
     current_section->analyze();
@@ -675,7 +669,17 @@ bool HttpInspect::process(const uint8_t* data, const uint16_t dsize, Flow* const
 #endif
 
     current_section->publish();
-    return current_section->detection_required();
+    if (current_section->run_detection(p))
+    {
+#ifdef REG_TEST
+        if (HttpTestManager::use_test_output(HttpTestManager::IN_HTTP))
+        {
+            fprintf(HttpTestManager::get_output_file(), "Sent to detection %hu octets\n\n",
+                dsize);
+            fflush(HttpTestManager::get_output_file());
+        }
+#endif
+    }
 }
 
 void HttpInspect::clear(Packet* p)
index 0865fe96d6ba3e9be8b6e5cd215c1033ccb583c3..f247a068236d0b2bbcc241c8385dfdf09c1e26ff 100644 (file)
@@ -63,6 +63,7 @@ public:
     bool configure(snort::SnortConfig*) override;
     void show(const snort::SnortConfig*) const override;
     void eval(snort::Packet* p) override;
+    void eval(snort::Packet* p, HttpCommon::SourceId source_id, const uint8_t* data, uint16_t dsize);
     void clear(snort::Packet* p) override;
 
     HttpStreamSplitter* get_splitter(bool is_client_to_server) override
@@ -90,8 +91,8 @@ private:
 
     HttpStreamSplitter splitter[2] = { { true, this }, { false, this } };
 
-    bool process(const uint8_t* data, const uint16_t dsize, snort::Flow* const flow,
-        HttpCommon::SourceId source_id_, bool buf_owner) const;
+    void process(const uint8_t* data, const uint16_t dsize, snort::Flow* const flow,
+        HttpCommon::SourceId source_id_, bool buf_owner, snort::Packet* p) const;
     static HttpFlowData* http_get_flow_data(const snort::Flow* flow);
     static void http_set_flow_data(snort::Flow* flow, HttpFlowData* flow_data);
 
index 9743732afed4c71288d096feda94bb7d26c44ac0..73acad3cecaf18c3464fd1d3bf7f6b02ac346c30 100644 (file)
@@ -131,6 +131,14 @@ void HttpMsgSection::update_depth() const
     }
 }
 
+bool HttpMsgSection::run_detection(snort::Packet* p)
+{
+    if ((p == nullptr) || !detection_required())
+        return false;
+    DetectionEngine::detect(p);
+    return true;
+}
+
 const Field& HttpMsgSection::classic_normalize(const Field& raw, Field& norm,
     bool do_path, const HttpParaList::UriParam& uri_param)
 {
index 5c59d32d4b2239726f70f04d46777e6053ef7750..8b1a6fcdd73d9831f60bd65e30726ca9388f3476 100644 (file)
@@ -22,6 +22,7 @@
 
 #include "detection/detection_util.h"
 #include "framework/cursor.h"
+#include "protocols/packet.h"
 
 #include "http_buffer_info.h"
 #include "http_common.h"
@@ -67,6 +68,12 @@ public:
     // Manages the splitter and communication between message sections
     virtual void update_flow() = 0;
 
+    // Publish an inspection event for other modules to consume
+    virtual void publish() {}
+
+    // Call the detection engine to inspect the current packet
+    bool run_detection(snort::Packet* p);
+
     const Field& get_classic_buffer(unsigned id, uint64_t sub_id, uint64_t form);
     const Field& get_classic_buffer(const HttpBufferInfo& buf);
     const Field& get_param_buffer(Cursor& c, const HttpParam& param);
@@ -75,9 +82,6 @@ public:
 
     int32_t get_status_code_num() const { return status_code_num; }
 
-    // Publish an inspection event for other modules to consume.
-    virtual void publish() { }
-
     void clear();
     bool is_clear() { return cleared; }
 
index e64bde15291e04c26c721a3a96c0e3e455156f2b..ffa690d1b5325ec6d2e781dcc08ee9d5e3de1aff 100644 (file)
@@ -39,6 +39,7 @@ public:
         source_id(is_client_to_server ? HttpCommon::SRC_CLIENT : HttpCommon::SRC_SERVER) {}
     Status scan(snort::Packet* pkt, const uint8_t* data, uint32_t length, uint32_t not_used,
         uint32_t* flush_offset) override;
+    Status scan(snort::Flow* flow, const uint8_t* data, uint32_t length, uint32_t* flush_offset);
     const snort::StreamBuffer reassemble(snort::Flow* flow, unsigned total, unsigned, const
         uint8_t* data, unsigned len, uint32_t flags, unsigned& copied) override;
     bool finish(snort::Flow* flow) override;
index 3209cfaed80bb98799cb2a0b0911384d0a98d582..71116ea9fddbf412123c5dbfca041ebb4f18d3d1 100644 (file)
@@ -24,6 +24,7 @@
 #include "http_stream_splitter.h"
 
 #include "packet_io/active.h"
+#include "protocols/packet.h"
 
 #include "http_common.h"
 #include "http_cutter.h"
@@ -128,9 +129,13 @@ StreamSplitter::Status HttpStreamSplitter::status_value(StreamSplitter::Status r
 StreamSplitter::Status HttpStreamSplitter::scan(Packet* pkt, const uint8_t* data, uint32_t length,
     uint32_t, uint32_t* flush_offset)
 {
-    Profile profile(HttpModule::get_profile_stats());
+    return scan(pkt->flow, data, length, flush_offset);
+}
 
-    Flow* const flow = pkt->flow;
+StreamSplitter::Status HttpStreamSplitter::scan(Flow* flow, const uint8_t* data, uint32_t length,
+    uint32_t* flush_offset)
+{
+    Profile profile(HttpModule::get_profile_stats());
 
     // This is the session state information we share with HttpInspect and store with stream. A
     // session is defined by a TCP connection. Since scan() is the first to see a new TCP
@@ -231,7 +236,7 @@ StreamSplitter::Status HttpStreamSplitter::scan(Packet* pkt, const uint8_t* data
         session_data->status_code_num = 200;
         HttpModule::increment_peg_counts(PEG_RESPONSE);
         prepare_flush(session_data, nullptr, SEC_HEADER, 0, 0, 0, false, 0, 0);
-        my_inspector->process((const uint8_t*)"", 0, flow, SRC_SERVER, false);
+        my_inspector->process((const uint8_t*)"", 0, flow, SRC_SERVER, false, nullptr);
         session_data->transaction[SRC_SERVER]->clear_section();
     }