]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Merge pull request #2123 in SNORT/snort3 from ~MDAGON/snort3:pt5 to master
authorMike Stepanek (mstepane) <mstepane@cisco.com>
Mon, 6 Apr 2020 12:46:05 +0000 (12:46 +0000)
committerMike Stepanek (mstepane) <mstepane@cisco.com>
Mon, 6 Apr 2020 12:46:05 +0000 (12:46 +0000)
Squashed commit of the following:

commit 8bd4bd1239e961dba3287e9ec05fff34990ceb8c
Author: mdagon <mdagon@cisco.com>
Date:   Wed Mar 25 16:19:22 2020 -0400

    http2_inspect: flush pending data when a non-data frame is received

src/service_inspectors/http2_inspect/http2_data_cutter.cc
src/service_inspectors/http2_inspect/http2_flow_data.h
src/service_inspectors/http2_inspect/http2_stream.h
src/service_inspectors/http2_inspect/http2_stream_splitter.h
src/service_inspectors/http2_inspect/http2_stream_splitter_impl.cc
src/service_inspectors/http2_inspect/http2_tables.cc
src/service_inspectors/http2_inspect/http2_utils.cc
src/service_inspectors/http2_inspect/http2_utils.h

index c98bc7d6a14ecb743d301ca4a3fcfd3cacb8c63b..6cbba9668aa2d13f0a88fcf11379fe27c65343f4 100644 (file)
@@ -115,13 +115,13 @@ bool Http2DataCutter::http2_scan(const uint8_t* data, uint32_t length,
 StreamSplitter::Status Http2DataCutter::http_scan(const uint8_t* data, uint32_t* flush_offset)
 {
     StreamSplitter::Status scan_result = StreamSplitter::SEARCH;
-    uint32_t http_flush_offset = 0;
-    Http2DummyPacket dummy_pkt;
-    dummy_pkt.flow = session_data->flow;
-    uint32_t unused = 0;
 
     if (cur_data || leftover_bytes)
     {
+        uint32_t http_flush_offset = 0;
+        Http2DummyPacket dummy_pkt;
+        dummy_pkt.flow = session_data->flow;
+        uint32_t unused = 0;
         scan_result = session_data->hi_ss[source_id]->scan(&dummy_pkt, data + cur_data_offset,
             cur_data + leftover_bytes, unused, &http_flush_offset);
 
@@ -153,11 +153,8 @@ StreamSplitter::Status Http2DataCutter::http_scan(const uint8_t* data, uint32_t*
 
             if (frame_flags & END_STREAM)
             {
-                session_data->get_current_stream(source_id)->get_hi_flow_data()->
-                    finish_h2_body(source_id);
-                scan_result = session_data->hi_ss[source_id]->scan(&dummy_pkt, nullptr, 0, unused,
-                    &http_flush_offset);
-                assert(scan_result == StreamSplitter::FLUSH);
+                finish_msg_body(session_data, source_id);
+                return StreamSplitter::FLUSH;
             }
             else
                 session_data->data_processing[source_id] = true;
index d5767775855fafc85220bc5d55619bac2a52257b..79f6c32fcca8190e001ec4901b349fe3514acda4 100644 (file)
@@ -73,16 +73,7 @@ public:
     friend class Http2StatusLine;
     friend class Http2Stream;
     friend class Http2StreamSplitter;
-    friend snort::StreamSplitter::Status data_scan(Http2FlowData* session_data, const
-        uint8_t* data, uint32_t length, uint32_t* flush_offset, HttpCommon::SourceId source_id,
-        uint32_t frame_length, uint8_t frame_flags, uint32_t& data_offset);
-    friend const snort::StreamBuffer implement_reassemble(Http2FlowData*, unsigned, unsigned,
-        const uint8_t*, unsigned, uint32_t, HttpCommon::SourceId);
-    friend snort::StreamSplitter::Status implement_scan(Http2FlowData*, const uint8_t*, uint32_t,
-        uint32_t*, HttpCommon::SourceId);
-    friend snort::StreamSplitter::Status non_data_scan(Http2FlowData* session_data,
-        uint32_t length, uint32_t* flush_offset, HttpCommon::SourceId source_id,
-        uint32_t frame_length, uint8_t type, uint8_t frame_flags, uint32_t& data_offset);
+    friend void finish_msg_body(Http2FlowData* session_data, HttpCommon::SourceId source_id);
 
     size_t size_of() override
     { return sizeof(*this); }
@@ -143,7 +134,11 @@ protected:
     bool payload_discard[2] = { false, false };
     uint32_t num_frame_headers[2] = { 0, 0 };
     uint32_t total_bytes_in_split[2] = { 0, 0 };
-    uint32_t octets_before_first_header[2] = { 0, 0 };
+    bool use_leftover_hdr[2] = { false, false };
+    uint8_t leftover_hdr[2][Http2Enums::FRAME_HEADER_LENGTH];
+
+    // Used by scan, reassemble
+    bool flushing_data[2] = { false, false };
 
     // Used by scan, reassemble and eval to communicate
     uint8_t frame_type[2] = { Http2Enums::FT__NONE, Http2Enums::FT__NONE };
index e026ae97cd1a4b898888111a7d00c6a7769dc923..3d635f3d3482f53b70d9ff2c1ae83e7b5c8186fe 100644 (file)
@@ -55,6 +55,8 @@ public:
 
     void set_end_stream(HttpCommon::SourceId source_id) { end_stream_set[source_id] = true; }
     bool end_stream_is_set(HttpCommon::SourceId source_id) { return end_stream_set[source_id]; }
+    void set_abort_on_data(HttpCommon::SourceId source_id) { abort_on_data[source_id] = true; }
+    bool abort_on_data_is_set(HttpCommon::SourceId source_id) { return abort_on_data[source_id]; }
 #ifdef REG_TEST
     void print_frame(FILE* output);
 #endif
@@ -67,6 +69,7 @@ private:
     HttpMsgSection* hi_msg_section = nullptr;
     Http2DataCutter* data_cutter[2] = { nullptr, nullptr};
     bool end_stream_set[2] = { false, false };
+    bool abort_on_data[2] = { false, false};
 };
 
 #endif
index 1b7d13af482b28463f239a9d819e3ff82f0cd7a6..d001e1bc31b539cf620c0f2387ec7599ff80455c 100644 (file)
@@ -48,17 +48,23 @@ public:
 
 private:
     const HttpCommon::SourceId source_id;
-};
-
-snort::StreamSplitter::Status implement_scan(Http2FlowData* session_data, const uint8_t* data,
-    uint32_t length, uint32_t* flush_offset, HttpCommon::SourceId source_id);
-const snort::StreamBuffer implement_reassemble(Http2FlowData* session_data, unsigned total,
-    unsigned offset, const uint8_t* data, unsigned len, uint32_t flags,
-    HttpCommon::SourceId source_id);
 
-enum ValidationResult { V_GOOD, V_BAD, V_TBD };
+    static StreamSplitter::Status data_scan(Http2FlowData* session_data, const uint8_t* data,
+        uint32_t length, uint32_t* flush_offset, HttpCommon::SourceId source_id,
+        uint32_t frame_length, uint8_t frame_flags, uint32_t& data_offset);
+    static void flush_data(Http2FlowData* session_data, HttpCommon::SourceId source_id,
+        uint32_t* flush_offset, uint32_t old_stream);
+    static StreamSplitter::Status non_data_scan(Http2FlowData* session_data,
+        uint32_t length, uint32_t* flush_offset, HttpCommon::SourceId source_id,
+        uint32_t frame_length, uint8_t type, uint8_t frame_flags, uint32_t& data_offset);
+    static snort::StreamSplitter::Status implement_scan(Http2FlowData* session_data, const uint8_t* data,
+        uint32_t length, uint32_t* flush_offset, HttpCommon::SourceId source_id);
+    static const snort::StreamBuffer implement_reassemble(Http2FlowData* session_data, unsigned total,
+        unsigned offset, const uint8_t* data, unsigned len, uint32_t flags,
+        HttpCommon::SourceId source_id);
+    static bool read_frame_hdr(Http2FlowData* session_data, const uint8_t* data,
+        uint32_t length, HttpCommon::SourceId source_id, uint32_t& data_offset);
+};
 
-ValidationResult validate_preface(const uint8_t* data, const uint32_t length,
-    const uint32_t octets_seen);
 
 #endif
index 16f7a064a68a6634c52c158e19de33407bc1dcd5..d515988dfabe9e2db441a40f325cafda71787d82 100644 (file)
@@ -39,11 +39,39 @@ using namespace snort;
 using namespace HttpCommon;
 using namespace Http2Enums;
 
-StreamSplitter::Status data_scan(Http2FlowData* session_data, const uint8_t* data,
-    uint32_t length, uint32_t* flush_offset, HttpCommon::SourceId source_id,
-    uint32_t frame_length, uint8_t frame_flags, uint32_t& data_offset)
+enum ValidationResult { V_GOOD, V_BAD, V_TBD };
+
+static ValidationResult validate_preface(const uint8_t* data, const uint32_t length,
+    const uint32_t octets_seen)
+{
+    const uint32_t preface_length = 24;
+
+    static const uint8_t connection_prefix[] = { 'P', 'R', 'I', ' ', '*', ' ', 'H', 'T', 'T', 'P',
+        '/', '2', '.', '0', '\r', '\n', '\r', '\n', 'S', 'M', '\r', '\n', '\r', '\n' };
+
+    assert(octets_seen < preface_length);
+
+    const uint32_t count = (octets_seen + length) < preface_length ? length :
+        (preface_length - octets_seen);
+
+    if (memcmp(data, connection_prefix + octets_seen, count))
+        return V_BAD;
+
+    if ((octets_seen + length) < preface_length)
+        return V_TBD;
+
+    return V_GOOD;
+}
+
+StreamSplitter::Status Http2StreamSplitter::data_scan(Http2FlowData* session_data,
+    const uint8_t* data, uint32_t length, uint32_t* flush_offset,
+    HttpCommon::SourceId source_id, uint32_t frame_length, uint8_t frame_flags,
+    uint32_t& data_offset)
 {
     Http2Stream* const stream = session_data->find_stream(session_data->current_stream[source_id]);
+    if (stream && stream->abort_on_data_is_set(source_id))
+        return StreamSplitter::ABORT;
+
     HttpFlowData* http_flow = nullptr;
     if (stream)
         http_flow = (HttpFlowData*)stream->get_hi_flow_data();
@@ -63,14 +91,10 @@ StreamSplitter::Status data_scan(Http2FlowData* session_data, const uint8_t* dat
     return data_cutter->scan(data, length, flush_offset, data_offset, frame_length, frame_flags);
 }
 
-StreamSplitter::Status non_data_scan(Http2FlowData* session_data,
+StreamSplitter::Status Http2StreamSplitter::non_data_scan(Http2FlowData* session_data,
     uint32_t length, uint32_t* flush_offset, HttpCommon::SourceId source_id,
     uint32_t frame_length, uint8_t type, uint8_t frame_flags, uint32_t& data_offset)
 {
-    // FIXIT-E - temporary. Will force data frame flush instead
-    if (session_data->data_processing[source_id])
-        return StreamSplitter::ABORT;
-
     // Compute frame section length once per frame
     if (session_data->scan_remaining_frame_octets[source_id] == 0)
     {
@@ -152,7 +176,62 @@ StreamSplitter::Status non_data_scan(Http2FlowData* session_data,
     return status;
 }
 
-StreamSplitter::Status implement_scan(Http2FlowData* session_data, const uint8_t* data,
+// Flush pending data. Save current non-data header for the next scan/reassemble.
+void Http2StreamSplitter::flush_data(Http2FlowData* session_data, HttpCommon::SourceId source_id,
+    uint32_t* flush_offset, uint32_t old_stream)
+{
+    session_data->current_stream[source_id] = old_stream;
+    session_data->frame_type[source_id] = FT_DATA;
+    finish_msg_body(session_data, source_id);
+    *flush_offset = FRAME_HEADER_LENGTH;
+    session_data->flushing_data[source_id] = true;
+    memcpy(session_data->leftover_hdr[source_id],
+        session_data->scan_frame_header[source_id], FRAME_HEADER_LENGTH);
+    session_data->num_frame_headers[source_id] -= 1;
+    Http2Stream* const stream = session_data->find_stream(
+        session_data->current_stream[source_id]);
+    stream->set_abort_on_data(source_id);
+}
+
+bool Http2StreamSplitter::read_frame_hdr(Http2FlowData* session_data, const uint8_t* data,
+    uint32_t length, HttpCommon::SourceId source_id, uint32_t& data_offset)
+{
+    if (!session_data->flushing_data[source_id])
+    {
+        // Frame with header
+        if (session_data->scan_octets_seen[source_id] == 0)
+        {
+            // Scanning a new frame
+            session_data->num_frame_headers[source_id] += 1;
+        }
+
+        // The first nine bytes are the frame header. But all nine might not all be
+        // present in the first TCP segment we receive.
+        const uint32_t remaining_header = FRAME_HEADER_LENGTH -
+            session_data->scan_octets_seen[source_id];
+        const uint32_t remaining_header_in_data = remaining_header > length - data_offset ?
+            length - data_offset : remaining_header;
+        memcpy(session_data->scan_frame_header[source_id] +
+            session_data->scan_octets_seen[source_id], data + data_offset,
+            remaining_header_in_data);
+        session_data->scan_octets_seen[source_id] += remaining_header_in_data;
+        data_offset += remaining_header_in_data;
+
+        if (session_data->scan_octets_seen[source_id] < FRAME_HEADER_LENGTH)
+            return false;
+    }
+    else
+    {
+        // Just finished flushing data. Use saved header.
+        session_data->num_frame_headers[source_id] = 1;
+        session_data->flushing_data[source_id] = false;
+        session_data->use_leftover_hdr[source_id] = true;
+    }
+
+    return true;
+}
+
+StreamSplitter::Status Http2StreamSplitter::implement_scan(Http2FlowData* session_data, const uint8_t* data,
     uint32_t length, uint32_t* flush_offset, HttpCommon::SourceId source_id)
 {
     StreamSplitter::Status status = StreamSplitter::FLUSH;
@@ -180,10 +259,9 @@ StreamSplitter::Status implement_scan(Http2FlowData* session_data, const uint8_t
     {
         *flush_offset = 0;
         uint32_t data_offset = 0;
-        session_data->octets_before_first_header[source_id] = 0;
 
-        // If there is a header frame followed by a continuation frame in the same tcp segment or
-        // several data frames need to process multiple frames in a single scan
+        // Need to process multiple frames in a single scan() if a single TCP segment has
+        // 1) multiple header and continuation frames or 2) multiple data frames.
         do
         {
             if (session_data->mid_data_frame[source_id])
@@ -196,27 +274,7 @@ StreamSplitter::Status implement_scan(Http2FlowData* session_data, const uint8_t
             }
             else
             {
-                // Frame with header
-                if (session_data->scan_octets_seen[source_id] == 0)
-                {
-                    // Scanning a new frame
-                    session_data->num_frame_headers[source_id] += 1;
-                }
-
-                // The first nine bytes are the frame header. But all nine might not all be present
-                // in
-                // the first TCP segment we receive.
-                const uint32_t remaining_header = FRAME_HEADER_LENGTH -
-                    session_data->scan_octets_seen[source_id];
-                const uint32_t remaining_header_in_data = remaining_header > length - data_offset ?
-                    length - data_offset : remaining_header;
-                memcpy(session_data->scan_frame_header[source_id] +
-                    session_data->scan_octets_seen[source_id], data + data_offset,
-                    remaining_header_in_data);
-                session_data->scan_octets_seen[source_id] += remaining_header_in_data;
-                data_offset += remaining_header_in_data;
-
-                if (session_data->scan_octets_seen[source_id] < FRAME_HEADER_LENGTH)
+                if (!read_frame_hdr(session_data, data, length, source_id, data_offset))
                     return StreamSplitter::SEARCH;
 
                 // We have the full frame header, compute some variables
@@ -226,9 +284,23 @@ StreamSplitter::Status implement_scan(Http2FlowData* session_data, const uint8_t
                     session_data->scan_frame_header[source_id]);
                 const uint8_t frame_flags = get_frame_flags(session_data->
                     scan_frame_header[source_id]);
+                const uint32_t old_stream = session_data->current_stream[source_id];
                 session_data->current_stream[source_id] =
                     get_stream_id(session_data->scan_frame_header[source_id]);
 
+                if ((old_stream != session_data->current_stream[source_id]) &&
+                    session_data->data_processing[source_id] && type == FT_DATA)
+                {
+                    // FIXIT-E split by stream multiplexing not supported yet
+                    return StreamSplitter::ABORT;
+                }
+
+                if (session_data->data_processing[source_id] && type != FT_DATA)
+                {
+                    flush_data(session_data, source_id, flush_offset, old_stream);
+                    return StreamSplitter::FLUSH;
+                }
+
                 if (type == FT_DATA)
                     status = data_scan(session_data, data, length, flush_offset, source_id,
                         frame_length, frame_flags, data_offset);
@@ -245,7 +317,7 @@ StreamSplitter::Status implement_scan(Http2FlowData* session_data, const uint8_t
 
 // FIXIT-M If there are any errors in header decoding, this currently tells stream not to send
 // headers to detection. This behavior may need to be changed.
-const StreamBuffer implement_reassemble(Http2FlowData* session_data, unsigned total,
+const StreamBuffer Http2StreamSplitter::implement_reassemble(Http2FlowData* session_data, unsigned total,
     unsigned offset, const uint8_t* data, unsigned len, uint32_t flags,
     HttpCommon::SourceId source_id)
 {
@@ -268,33 +340,39 @@ const StreamBuffer implement_reassemble(Http2FlowData* session_data, unsigned to
 
     if (session_data->frame_type[source_id] == FT_DATA)
     {
-        Http2Stream* const stream = session_data->find_stream(
-            session_data->current_stream[source_id]);
-        Http2DataCutter* data_cutter = stream->get_data_cutter(source_id);
-        StreamBuffer http_frame_buf = data_cutter->reassemble(data, len);
-        if (http_frame_buf.data)
+        if (session_data->flushing_data[source_id] && (flags & PKT_PDU_TAIL))
+            len -= FRAME_HEADER_LENGTH;
+
+        if (len != 0)
         {
-            session_data->frame_data[source_id] = const_cast<uint8_t*>(http_frame_buf.data);
-            session_data->frame_data_size[source_id] = http_frame_buf.length;
+            Http2Stream* const stream = session_data->find_stream(
+                session_data->current_stream[source_id]);
+            Http2DataCutter* data_cutter = stream->get_data_cutter(source_id);
+            StreamBuffer http_frame_buf = data_cutter->reassemble(data, len);
+            if (http_frame_buf.data)
+            {
+                session_data->frame_data[source_id] = const_cast<uint8_t*>(http_frame_buf.data);
+                session_data->frame_data_size[source_id] = http_frame_buf.length;
+            }
         }
     }
     else
     {
-        assert(total >= FRAME_HEADER_LENGTH);
         uint32_t data_offset = 0;
 
         if (offset == 0)
         {
             // This is the first reassemble() for this frame - allocate data buffer
-            session_data->frame_data_size[source_id]= total -
-                session_data->frame_header_size[source_id];
+            session_data->frame_data_size[source_id] = total;
+            if (!session_data->use_leftover_hdr[source_id])
+                session_data->frame_data_size[source_id] -=
+                    session_data->frame_header_size[source_id];
             if (session_data->frame_data_size[source_id] > 0)
                 session_data->frame_data[source_id] = new uint8_t[
                     session_data->frame_data_size[source_id]];
 
             session_data->frame_data_offset[source_id] = 0;
-            session_data->remaining_frame_octets[source_id] =
-                session_data->octets_before_first_header[source_id];
+            session_data->remaining_frame_octets[source_id] = 0;
             session_data->padding_octets_in_frame[source_id] = 0;
         }
 
@@ -315,8 +393,7 @@ const StreamBuffer implement_reassemble(Http2FlowData* session_data, unsigned to
             }
 
             // Copy data into the frame buffer until we run out of data or reach the end of the
-            // current
-            // frame's data
+            // current frame's data
             const uint32_t remaining_frame_payload =
                 session_data->remaining_frame_octets[source_id] -
                 session_data->padding_octets_in_frame[source_id];
@@ -346,26 +423,36 @@ const StreamBuffer implement_reassemble(Http2FlowData* session_data, unsigned to
                 break;
 
             // Copy headers
-            const uint32_t remaining_frame_header =  FRAME_HEADER_LENGTH -
-                (session_data->frame_header_offset[source_id] % FRAME_HEADER_LENGTH);
-            octets_to_copy = remaining_frame_header > len - data_offset ? len - data_offset :
-                remaining_frame_header;
-            memcpy(session_data->frame_header[source_id] +
-                session_data->frame_header_offset[source_id],
-                data + data_offset, octets_to_copy);
-            session_data->frame_header_offset[source_id] += octets_to_copy;
-            data_offset += octets_to_copy;
+            if (session_data->use_leftover_hdr[source_id])
+            {
+                memcpy(session_data->frame_header[source_id],
+                    session_data->leftover_hdr[source_id], FRAME_HEADER_LENGTH);
+                session_data->frame_header_offset[source_id] += FRAME_HEADER_LENGTH;
+                session_data->use_leftover_hdr[source_id] = false;
+            }
+            else
+            {
+                const uint32_t remaining_frame_header =  FRAME_HEADER_LENGTH -
+                    (session_data->frame_header_offset[source_id] % FRAME_HEADER_LENGTH);
+                octets_to_copy = remaining_frame_header > len - data_offset ? len - data_offset :
+                    remaining_frame_header;
+                memcpy(session_data->frame_header[source_id] +
+                    session_data->frame_header_offset[source_id],
+                    data + data_offset, octets_to_copy);
+                session_data->frame_header_offset[source_id] += octets_to_copy;
+                data_offset += octets_to_copy;
 
-            if (session_data->frame_header_offset[source_id] % FRAME_HEADER_LENGTH != 0)
-                break;
+                if (session_data->frame_header_offset[source_id] % FRAME_HEADER_LENGTH != 0)
+                    break;
+            }
 
             // If we just finished copying a header, parse and update frame variables
             session_data->remaining_frame_octets[source_id] =
                 get_frame_length(session_data->frame_header[source_id] +
                 session_data->frame_header_offset[source_id] - FRAME_HEADER_LENGTH);
 
-            uint8_t frame_flags = get_frame_flags(session_data->
-                scan_frame_header[source_id]);
+            uint8_t frame_flags = get_frame_flags(session_data->frame_header[source_id] +
+                session_data->frame_header_offset[source_id] - FRAME_HEADER_LENGTH);
             if (frame_flags & PADDED)
                 session_data->get_padding_len[source_id] = true;
         }
@@ -373,6 +460,7 @@ const StreamBuffer implement_reassemble(Http2FlowData* session_data, unsigned to
         session_data->frame_type[source_id] = get_frame_type(
             session_data->frame_header[source_id]);
     }
+
     if (flags & PKT_PDU_TAIL)
     {
         session_data->total_bytes_in_split[source_id] = 0;
@@ -387,25 +475,3 @@ const StreamBuffer implement_reassemble(Http2FlowData* session_data, unsigned to
     return frame_buf;
 }
 
-ValidationResult validate_preface(const uint8_t* data, const uint32_t length,
-    const uint32_t octets_seen)
-{
-    const uint32_t preface_length = 24;
-
-    static const uint8_t connection_prefix[] = { 'P', 'R', 'I', ' ', '*', ' ', 'H', 'T', 'T', 'P',
-        '/', '2', '.', '0', '\r', '\n', '\r', '\n', 'S', 'M', '\r', '\n', '\r', '\n' };
-
-    assert(octets_seen < preface_length);
-
-    const uint32_t count = (octets_seen + length) < preface_length ? length :
-        (preface_length - octets_seen);
-
-    if (memcmp(data, connection_prefix + octets_seen, count))
-        return V_BAD;
-
-    if ((octets_seen + length) < preface_length)
-        return V_TBD;
-
-    return V_GOOD;
-}
-
index b558c107cb8d6905dc88c1ebd01133c48a71f3c4..76b8d5998bdeaa751a7e8dcbd94d1d3b11489f3a 100644 (file)
@@ -40,7 +40,7 @@ const RuleMap Http2Module::http2_events[] =
     { EVENT_PREFACE_MATCH_FAILURE, "HTTP/2 connection preface does not match" },
     { EVENT_REQUEST_WITHOUT_REQUIRED_FIELD, "HTTP/2 request missing required header field" },
     { EVENT_RESPONSE_WITHOUT_STATUS, "HTTP/2 response has no status code" },
-    { EVENT_INVALID_HEADER, "invalid HTTP/2 header field" },
+    { EVENT_INVALID_HEADER, "HTTP/2 invalid header field" },
     { EVENT_SETTINGS_FRAME_ERROR, "error in HTTP/2 settings frame" },
     { EVENT_SETTINGS_FRAME_UNKN_PARAM, "unknown parameter in HTTP/2 settings frame" },
     { EVENT_FRAME_SEQUENCE, "invalid HTTP/2 frame sequence" },
index 620803cb0ba483fd242008863d9a29b595cb0c4e..eb603bb472b7438c95f5dc5c6a2a88c34770f707 100644 (file)
 
 #include <cassert>
 
+#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_enum.h"
 
 using namespace Http2Enums;
@@ -58,3 +62,19 @@ uint8_t get_stream_id(const uint8_t* frame_header_buffer)
            (frame_header_buffer[stream_id_index + 2] << 8) +
            frame_header_buffer[stream_id_index + 3];
 }
+
+void finish_msg_body(Http2FlowData* session_data, HttpCommon::SourceId source_id)
+{
+    uint32_t http_flush_offset = 0;
+    Http2DummyPacket dummy_pkt;
+    dummy_pkt.flow = session_data->flow;
+    uint32_t unused = 0;
+    session_data->get_current_stream(source_id)->get_hi_flow_data()->
+        finish_h2_body(source_id);
+    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);
+    UNUSED(scan_result);
+    session_data->data_processing[source_id] = false;
+}
+
index 6a88f1e905768b3757f73627d249d6c1feaa618a..3954f69fdb808ae0bc02ef5ca2d5493b3a67ebf2 100644 (file)
@@ -25,6 +25,9 @@
 #endif
 
 #include "main/snort_types.h"
+#include "service_inspectors/http_inspect/http_common.h"
+
+#include "http2_flow_data.h"
 
 // Frame header parsing utils.
 // Assumption is that if input isn't null, it contains full frame header
@@ -34,4 +37,7 @@ uint8_t get_frame_type(const uint8_t* frame_header_buffer);
 uint8_t get_frame_flags(const uint8_t* frame_header_buffer);
 uint8_t get_stream_id(const uint8_t* frame_header_buffer);
 
+
+void finish_msg_body(Http2FlowData* session_data, HttpCommon::SourceId source_id);
+
 #endif