From: Mike Stepanek (mstepane) Date: Tue, 5 May 2020 13:47:52 +0000 (+0000) Subject: Merge pull request #2192 in SNORT/snort3 from ~KATHARVE/snort3:h2i_concurrent_files... X-Git-Tag: 3.0.1-3~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f605a43fad9412b8cb19d0b68e867554aa415fc1;p=thirdparty%2Fsnort3.git Merge pull request #2192 in SNORT/snort3 from ~KATHARVE/snort3:h2i_concurrent_files to master Squashed commit of the following: commit fa388955bae45e95f80034a69f010a7fa9b5a84b Author: Katura Harvey Date: Thu Apr 30 09:21:22 2020 -0400 file_api: mark processing of file complete after type detection if signature not enabled commit 2aff0ce2b10432111d836a82537187e2676be998 Author: Katura Harvey Date: Thu Apr 30 09:20:06 2020 -0400 http2_inspect: add peg count to track max concurrent http2 file transfers --- diff --git a/src/file_api/file_lib.cc b/src/file_api/file_lib.cc index 20911bc8a..4b8514427 100644 --- a/src/file_api/file_lib.cc +++ b/src/file_api/file_lib.cc @@ -405,6 +405,7 @@ bool FileContext::process(Packet* p, const uint8_t* file_data, int data_size, if ((!is_file_type_enabled()) and (!is_file_signature_enabled())) { update_file_size(data_size, position); + processing_complete = true; if (PacketTracer::is_active()) PacketTracer::log("File: Type and Sig not enabled\n"); return false; diff --git a/src/mime/file_mime_process.cc b/src/mime/file_mime_process.cc index 4cfcc4603..8e028bfce 100644 --- a/src/mime/file_mime_process.cc +++ b/src/mime/file_mime_process.cc @@ -839,7 +839,7 @@ void MimeSession::mime_file_process(Packet* p, const uint8_t* data, int data_siz if(!file_flows) return; - if (continue_inspecting_file or position == SNORT_FILE_END) + if (continue_inspecting_file) { if (session_base_file_id) { diff --git a/src/service_inspectors/http2_inspect/http2_data_cutter.cc b/src/service_inspectors/http2_inspect/http2_data_cutter.cc index 5164c248c..9ddf91f78 100644 --- a/src/service_inspectors/http2_inspect/http2_data_cutter.cc +++ b/src/service_inspectors/http2_inspect/http2_data_cutter.cc @@ -327,8 +327,9 @@ void Http2DataCutter::finish_msg_body() 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); + Http2Stream* const stream = session_data->get_current_stream(source_id); + stream->get_hi_flow_data()->finish_h2_body(source_id); + stream->set_last_data_flush(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); diff --git a/src/service_inspectors/http2_inspect/http2_data_frame.cc b/src/service_inspectors/http2_inspect/http2_data_frame.cc index b3a18b8e6..06dd661ca 100644 --- a/src/service_inspectors/http2_inspect/http2_data_frame.cc +++ b/src/service_inspectors/http2_inspect/http2_data_frame.cc @@ -29,14 +29,17 @@ #include "http2_dummy_packet.h" #include "http2_flow_data.h" +#include "http2_module.h" using namespace HttpCommon; using namespace snort; +using namespace Http2Enums; Http2DataFrame::Http2DataFrame(const uint8_t* header_buffer, const int32_t header_len, const uint8_t* data_buffer, const int32_t data_len, Http2FlowData* session_data_, - HttpCommon::SourceId source_id_) : - Http2Frame(header_buffer, header_len, nullptr, 0, session_data_, source_id_) + HttpCommon::SourceId source_id_, Http2Stream* stream_) : + Http2Frame(header_buffer, header_len, nullptr, 0, session_data_, source_id_, stream_), + data_length(data_len) { if ((data_len != 0) || !session_data->flushing_data[source_id]) { @@ -65,3 +68,34 @@ void Http2DataFrame::clear() session_data->hi->clear(&dummy_pkt); } +void Http2DataFrame::update_stream_state() +{ + switch (stream->get_state(source_id)) + { + case STATE_OPEN: + if (data_length > 0) + { + session_data->concurrent_files += 1; + stream->set_state(source_id, STATE_OPEN_DATA); + if (session_data->concurrent_files > + Http2Module::get_peg_counts(PEG_MAX_CONCURRENT_FILES)) + { + Http2Module::increment_peg_counts(PEG_MAX_CONCURRENT_FILES); + } + } + if (stream->is_last_data_flush(source_id)) + stream->set_state(source_id, STATE_CLOSED); + break; + case STATE_OPEN_DATA: + if (stream->is_last_data_flush(source_id)) + { + assert(session_data->concurrent_files > 0); + session_data->concurrent_files -= 1; + stream->set_state(source_id, STATE_CLOSED); + } + break; + default: + // Stream state is idle or closed - this is caught in scan so should not get here + assert(false); + } +} diff --git a/src/service_inspectors/http2_inspect/http2_data_frame.h b/src/service_inspectors/http2_inspect/http2_data_frame.h index 08ff4cc4a..5ee0d9997 100644 --- a/src/service_inspectors/http2_inspect/http2_data_frame.h +++ b/src/service_inspectors/http2_inspect/http2_data_frame.h @@ -23,6 +23,7 @@ #include "http2_frame.h" class Http2Frame; +class Http2Stream; class Http2DataFrame : public Http2Frame { @@ -32,13 +33,16 @@ public: uint32_t get_xtradata_mask() override { return xtradata_mask; } bool is_detection_required() const override { return detection_required; } + void update_stream_state() override; friend Http2Frame* Http2Frame::new_frame(const uint8_t*, const int32_t, const uint8_t*, - const int32_t, Http2FlowData*, HttpCommon::SourceId); + const int32_t, Http2FlowData*, HttpCommon::SourceId, Http2Stream* stream); private: - Http2DataFrame(const uint8_t* header_buffer, const int32_t header_len,const uint8_t* data_buffer, const int32_t data_len, Http2FlowData* ssn_data, - HttpCommon::SourceId src_id); + Http2DataFrame(const uint8_t* header_buffer, const int32_t header_len, + const uint8_t* data_buffer, const int32_t data_len, Http2FlowData* ssn_data, + HttpCommon::SourceId src_id, Http2Stream* stream); + uint32_t data_length = 0; uint32_t xtradata_mask = 0; bool detection_required = false; }; diff --git a/src/service_inspectors/http2_inspect/http2_enum.h b/src/service_inspectors/http2_inspect/http2_enum.h index b042b3d24..0550c07a4 100644 --- a/src/service_inspectors/http2_inspect/http2_enum.h +++ b/src/service_inspectors/http2_inspect/http2_enum.h @@ -36,6 +36,8 @@ enum FrameType : uint8_t { FT_DATA=0, FT_HEADERS=1, FT_PRIORITY=2, FT_RST_STREAM FT_PUSH_PROMISE=5, FT_PING=6, FT_GOAWAY=7, FT_WINDOW_UPDATE=8, FT_CONTINUATION=9, FT__ABORT=254, FT__NONE=255 }; +enum StreamState { STATE_IDLE, STATE_OPEN, STATE_OPEN_DATA, STATE_CLOSED }; + // Message buffers available to clients // This enum must remain synchronized with Http2Api::classic_buffer_names[] enum HTTP2_BUFFER { HTTP2_BUFFER_FRAME_HEADER = 1, HTTP2_BUFFER_FRAME_DATA, @@ -44,7 +46,7 @@ enum HTTP2_BUFFER { HTTP2_BUFFER_FRAME_HEADER = 1, HTTP2_BUFFER_FRAME_DATA, // Peg counts // This enum must remain synchronized with Http2Module::peg_names[] in http2_tables.cc enum PEG_COUNT { PEG_FLOW = 0, PEG_CONCURRENT_SESSIONS, PEG_MAX_CONCURRENT_SESSIONS, - PEG_MAX_ENTRIES, PEG_COUNT__MAX }; + PEG_MAX_TABLE_ENTRIES, PEG_MAX_CONCURRENT_FILES, PEG_COUNT__MAX }; enum EventSid { @@ -100,6 +102,7 @@ enum Infraction INF_INVALID_STARTLINE = 25, INF_INVALID_HEADER = 26, INF_PADDING_LEN = 27, + INF_TRAILERS_AFTER_END_STREAM = 28, INF__MAX_VALUE }; diff --git a/src/service_inspectors/http2_inspect/http2_flow_data.h b/src/service_inspectors/http2_inspect/http2_flow_data.h index 79f6c32fc..46dd2b1fd 100644 --- a/src/service_inspectors/http2_inspect/http2_flow_data.h +++ b/src/service_inspectors/http2_inspect/http2_flow_data.h @@ -120,6 +120,7 @@ protected: Http2ConnectionSettings connection_settings[2]; Http2HpackDecoder hpack_decoder[2]; std::list streams; + uint32_t concurrent_files = 0; // Internal to scan() bool preface[2] = { true, false }; diff --git a/src/service_inspectors/http2_inspect/http2_frame.cc b/src/service_inspectors/http2_inspect/http2_frame.cc index f5a331e11..87fab4036 100644 --- a/src/service_inspectors/http2_inspect/http2_frame.cc +++ b/src/service_inspectors/http2_inspect/http2_frame.cc @@ -28,6 +28,7 @@ #include "http2_flow_data.h" #include "http2_headers_frame.h" #include "http2_settings_frame.h" +#include "http2_stream.h" #include "service_inspectors/http_inspect/http_field.h" using namespace HttpCommon; @@ -36,32 +37,33 @@ using namespace snort; Http2Frame::Http2Frame(const uint8_t* header_buffer, const int32_t header_len, const uint8_t* data_buffer, const int32_t data_len, Http2FlowData* session_data, - SourceId source_id) : session_data(session_data), source_id(source_id) + SourceId source_id, Http2Stream* stream_) : session_data(session_data), source_id(source_id), + stream(stream_) { if (header_len > 0) header.set(header_len, header_buffer, true); if (data_len > 0) - { data.set(data_len, data_buffer, true); - } } Http2Frame* Http2Frame::new_frame(const uint8_t* header, const int32_t header_len, - const uint8_t* data, const int32_t data_len, Http2FlowData* session_data, SourceId source_id) + const uint8_t* data, const int32_t data_len, Http2FlowData* session_data, SourceId source_id, + Http2Stream* stream) { // FIXIT-E call the appropriate frame subclass constructor based on the type switch(session_data->frame_type[source_id]) { case FT_HEADERS: return new Http2HeadersFrame(header, header_len, data, data_len, session_data, - source_id); + source_id, stream); case FT_SETTINGS: return new Http2SettingsFrame(header, header_len, data, data_len, session_data, - source_id); + source_id, stream); case FT_DATA: - return new Http2DataFrame(header, header_len, data, data_len, session_data, source_id); + return new Http2DataFrame(header, header_len, data, data_len, session_data, source_id, + stream); default: - return new Http2Frame(header, header_len, data, data_len, session_data, source_id); + return new Http2Frame(header, header_len, data, data_len, session_data, source_id, stream); } } diff --git a/src/service_inspectors/http2_inspect/http2_frame.h b/src/service_inspectors/http2_inspect/http2_frame.h index 861f43e96..9fe27e725 100644 --- a/src/service_inspectors/http2_inspect/http2_frame.h +++ b/src/service_inspectors/http2_inspect/http2_frame.h @@ -32,6 +32,7 @@ */ class Http2FlowData; +class Http2Stream; class Http2Frame { @@ -39,11 +40,12 @@ public: virtual ~Http2Frame() { } static Http2Frame* new_frame(const uint8_t* header_buffer, const int32_t header_len, const uint8_t* data_buffer, const int32_t data_len, Http2FlowData* session_data, - HttpCommon::SourceId source_id); + HttpCommon::SourceId source_id, Http2Stream* stream); 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; } + virtual void update_stream_state() { } #ifdef REG_TEST virtual void print_frame(FILE* output); @@ -52,7 +54,7 @@ public: protected: Http2Frame(const uint8_t* header_buffer, const int32_t header_len, const uint8_t* data_buffer, const int32_t data_len, Http2FlowData* session_data, - HttpCommon::SourceId source_id); + HttpCommon::SourceId source_id, Http2Stream* stream); uint8_t get_flags(); uint32_t get_stream_id(); @@ -60,6 +62,7 @@ protected: Field data; Http2FlowData* session_data; HttpCommon::SourceId source_id; + Http2Stream* stream; const static uint8_t flags_index = 4; const static uint8_t stream_id_index = 5; diff --git a/src/service_inspectors/http2_inspect/http2_headers_frame.cc b/src/service_inspectors/http2_inspect/http2_headers_frame.cc index 3ac0d0a11..07098c605 100644 --- a/src/service_inspectors/http2_inspect/http2_headers_frame.cc +++ b/src/service_inspectors/http2_inspect/http2_headers_frame.cc @@ -34,6 +34,7 @@ #include "http2_flow_data.h" #include "http2_hpack.h" #include "http2_start_line.h" +#include "http2_stream.h" using namespace snort; using namespace HttpCommon; @@ -41,12 +42,16 @@ using namespace Http2Enums; Http2HeadersFrame::Http2HeadersFrame(const uint8_t* header_buffer, const int32_t header_len, const uint8_t* data_buffer, const int32_t data_len, Http2FlowData* session_data_, - HttpCommon::SourceId source_id_) : - Http2Frame(header_buffer, header_len, data_buffer, data_len, session_data_, source_id_) + HttpCommon::SourceId source_id_, Http2Stream* stream_) : + Http2Frame(header_buffer, header_len, data_buffer, data_len, session_data_, source_id_, stream_) { - Http2Stream* const stream = session_data->find_stream(get_stream_id()); - if (get_flags() & END_STREAM) - stream->set_end_stream(source_id); + // FIXIT-E If the stream state is not IDLE, we've already received the headers. Trailers are + // not yet being processed + if (stream->get_state(source_id) >= STATE_OPEN) + { + trailer = true; + return; + } // No need to process an empty headers frame if (data.length() <= 0) @@ -203,10 +208,48 @@ const Field& Http2HeadersFrame::get_buf(unsigned id) } } +void Http2HeadersFrame::update_stream_state() +{ + switch (stream->get_state(source_id)) + { + case STATE_IDLE: + if (get_flags() & END_STREAM) + stream->set_state(source_id, STATE_CLOSED); + else + stream->set_state(source_id, STATE_OPEN); + break; + case STATE_OPEN: + // fallthrough + case STATE_OPEN_DATA: + if (get_flags() & END_STREAM) + { + if (stream->get_state(source_id) == STATE_OPEN_DATA) + session_data->concurrent_files -= 1; + stream->set_state(source_id, STATE_CLOSED); + } + else + { + // Headers frame without end_stream flag set after initial Headers frame + *session_data->infractions[source_id] += INF_FRAME_SEQUENCE; + session_data->events[source_id]->create_event(EVENT_FRAME_SEQUENCE); + } + break; + case STATE_CLOSED: + // Trailers in closed state + *session_data->infractions[source_id] += INF_TRAILERS_AFTER_END_STREAM; + session_data->events[source_id]->create_event(EVENT_FRAME_SEQUENCE); + break; + } +} + + #ifdef REG_TEST void Http2HeadersFrame::print_frame(FILE* output) { - fprintf(output, "\nHeaders frame\n"); + if (!trailer) + fprintf(output, "\nHeaders frame\n"); + else + fprintf(output, "Trailing Headers frame\n"); if (error_during_decode) fprintf(output, "Error decoding headers.\n"); if (start_line) diff --git a/src/service_inspectors/http2_inspect/http2_headers_frame.h b/src/service_inspectors/http2_inspect/http2_headers_frame.h index 43fce110a..99f7d7d35 100644 --- a/src/service_inspectors/http2_inspect/http2_headers_frame.h +++ b/src/service_inspectors/http2_inspect/http2_headers_frame.h @@ -26,6 +26,7 @@ class Field; class Http2HpackDecoder; class Http2StartLine; class Http2Frame; +class Http2Stream; class Http2HeadersFrame : public Http2Frame { @@ -36,9 +37,10 @@ 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; } + void update_stream_state() override; friend Http2Frame* Http2Frame::new_frame(const uint8_t*, const int32_t, const uint8_t*, - const int32_t, Http2FlowData*, HttpCommon::SourceId); + const int32_t, Http2FlowData*, HttpCommon::SourceId, Http2Stream* stream); #ifdef REG_TEST void print_frame(FILE* output) override; @@ -47,7 +49,7 @@ public: private: Http2HeadersFrame(const uint8_t* header_buffer, const int32_t header_len, const uint8_t* data_buffer, const int32_t data_len, Http2FlowData* ssn_data, - HttpCommon::SourceId src_id); + HttpCommon::SourceId src_id, Http2Stream* stream); Http2StartLine* start_line_generator = nullptr; uint8_t* decoded_headers = nullptr; // working buffer to store decoded headers @@ -58,5 +60,8 @@ private: bool hi_abort = false; uint32_t xtradata_mask = 0; bool detection_required = false; + + // FIXIT-E Process trailers + bool trailer = false; }; #endif diff --git a/src/service_inspectors/http2_inspect/http2_hpack_dynamic_table.cc b/src/service_inspectors/http2_inspect/http2_hpack_dynamic_table.cc index 3bb751800..f90d77a41 100644 --- a/src/service_inspectors/http2_inspect/http2_hpack_dynamic_table.cc +++ b/src/service_inspectors/http2_inspect/http2_hpack_dynamic_table.cc @@ -65,8 +65,8 @@ bool HpackDynamicTable::add_entry(const Field& name, const Field& value) circular_array[start] = new_entry; num_entries++; - if (num_entries > Http2Module::get_peg_counts(PEG_MAX_ENTRIES)) - Http2Module::increment_peg_counts(PEG_MAX_ENTRIES); + if (num_entries > Http2Module::get_peg_counts(PEG_MAX_TABLE_ENTRIES)) + Http2Module::increment_peg_counts(PEG_MAX_TABLE_ENTRIES); rfc_table_size += new_entry_size; return true; diff --git a/src/service_inspectors/http2_inspect/http2_settings_frame.cc b/src/service_inspectors/http2_inspect/http2_settings_frame.cc index 980a35c3b..943350c2d 100644 --- a/src/service_inspectors/http2_inspect/http2_settings_frame.cc +++ b/src/service_inspectors/http2_inspect/http2_settings_frame.cc @@ -48,8 +48,8 @@ static uint32_t get_parameter_value(const uint8_t* data_buffer) Http2SettingsFrame::Http2SettingsFrame(const uint8_t* header_buffer, const int32_t header_len, const uint8_t* data_buffer, const int32_t data_len, Http2FlowData* ssn_data, - HttpCommon::SourceId src_id) : Http2Frame(header_buffer, header_len, data_buffer, data_len, - ssn_data, src_id) + HttpCommon::SourceId src_id, Http2Stream* stream_) : Http2Frame(header_buffer, header_len, data_buffer, data_len, + ssn_data, src_id, stream_) { if (!sanity_check()) { diff --git a/src/service_inspectors/http2_inspect/http2_settings_frame.h b/src/service_inspectors/http2_inspect/http2_settings_frame.h index f78803819..ad910862e 100644 --- a/src/service_inspectors/http2_inspect/http2_settings_frame.h +++ b/src/service_inspectors/http2_inspect/http2_settings_frame.h @@ -30,7 +30,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); + const int32_t, Http2FlowData*, HttpCommon::SourceId, Http2Stream* stream); bool is_detection_required() const override { return false; } #ifdef REG_TEST @@ -40,7 +40,7 @@ public: private: Http2SettingsFrame(const uint8_t* header_buffer, const int32_t header_len, const uint8_t* data_buffer, const int32_t data_len, Http2FlowData* ssn_data, - HttpCommon::SourceId src_id); + HttpCommon::SourceId src_id, Http2Stream* stream); void parse_settings_frame(); bool sanity_check(); diff --git a/src/service_inspectors/http2_inspect/http2_stream.cc b/src/service_inspectors/http2_inspect/http2_stream.cc index ea96b2734..3e6c45378 100644 --- a/src/service_inspectors/http2_inspect/http2_stream.cc +++ b/src/service_inspectors/http2_inspect/http2_stream.cc @@ -21,6 +21,7 @@ #include "config.h" #endif +#include "http2_enum.h" #include "http2_stream.h" #include "service_inspectors/http_inspect/http_flow_data.h" @@ -28,6 +29,7 @@ #include "http2_data_cutter.h" using namespace HttpCommon; +using namespace Http2Enums; Http2Stream::Http2Stream(uint32_t stream_id_, Http2FlowData* session_data_) : stream_id(stream_id_), @@ -48,7 +50,8 @@ void Http2Stream::eval_frame(const uint8_t* header_buffer, int32_t header_len, { delete current_frame; current_frame = Http2Frame::new_frame(header_buffer, header_len, data_buffer, - data_len, session_data, source_id); + data_len, session_data, source_id, this); + current_frame->update_stream_state(); } void Http2Stream::clear_frame() @@ -80,3 +83,8 @@ Http2DataCutter* Http2Stream::get_data_cutter(HttpCommon::SourceId source_id) data_cutter[source_id] = new Http2DataCutter(session_data, source_id); return data_cutter[source_id]; } + +bool Http2Stream::is_open(HttpCommon::SourceId source_id) +{ + return (state[source_id] == STATE_OPEN) || (state[source_id] == STATE_OPEN_DATA); +} diff --git a/src/service_inspectors/http2_inspect/http2_stream.h b/src/service_inspectors/http2_inspect/http2_stream.h index 9189bad33..bbbf7f0cc 100644 --- a/src/service_inspectors/http2_inspect/http2_stream.h +++ b/src/service_inspectors/http2_inspect/http2_stream.h @@ -23,6 +23,7 @@ #include "service_inspectors/http_inspect/http_common.h" #include "service_inspectors/http_inspect/http_field.h" +#include "http2_enum.h" #include "http2_frame.h" class Http2DataCutter; @@ -53,9 +54,6 @@ public: void set_data_cutter(Http2DataCutter* cutter, HttpCommon::SourceId source_id) { data_cutter[source_id] = cutter; } - 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_partial_buf_pending(HttpCommon::SourceId source_id) { partial_buf_pending[source_id] = true; } void reset_partial_buf_pending(HttpCommon::SourceId source_id) @@ -63,6 +61,13 @@ public: bool is_partial_buf_pending(HttpCommon::SourceId source_id) { return partial_buf_pending[source_id]; } + void set_state(HttpCommon::SourceId source_id, Http2Enums::StreamState new_state) + { state[source_id] = new_state; } + Http2Enums::StreamState get_state(HttpCommon::SourceId source_id) { return state[source_id]; } + bool is_open(HttpCommon::SourceId source_id); + void set_last_data_flush(HttpCommon::SourceId source_id) { last_data_flush[source_id] = true; } + bool is_last_data_flush(HttpCommon::SourceId source_id) { return last_data_flush[source_id]; } + #ifdef REG_TEST void print_frame(FILE* output); #endif @@ -74,9 +79,9 @@ private: HttpFlowData* hi_flow_data = nullptr; HttpMsgSection* hi_msg_section = nullptr; Http2DataCutter* data_cutter[2] = { nullptr, nullptr}; - bool end_stream_set[2] = { false, false }; bool partial_buf_pending[2] = { false, false }; // used to indicate a partial buffer - // is pending from a previous partial flush + bool last_data_flush[2] = { false, false }; + Http2Enums::StreamState state[2] = { Http2Enums::STATE_IDLE, Http2Enums::STATE_IDLE }; }; #endif diff --git a/src/service_inspectors/http2_inspect/http2_stream_splitter_impl.cc b/src/service_inspectors/http2_inspect/http2_stream_splitter_impl.cc index 58aa1fdc8..685f192b6 100644 --- a/src/service_inspectors/http2_inspect/http2_stream_splitter_impl.cc +++ b/src/service_inspectors/http2_inspect/http2_stream_splitter_impl.cc @@ -70,10 +70,11 @@ StreamSplitter::Status Http2StreamSplitter::data_scan(Http2FlowData* session_dat { Http2Stream* const stream = session_data->find_stream(session_data->current_stream[source_id]); - if (!stream || stream->end_stream_is_set(source_id)) + if (!stream || !stream->is_open(source_id)) { *session_data->infractions[source_id] += INF_FRAME_SEQUENCE; session_data->events[source_id]->create_event(EVENT_FRAME_SEQUENCE); + // FIXIT-E We should not be aborting here return StreamSplitter::ABORT; } @@ -96,6 +97,7 @@ StreamSplitter::Status Http2StreamSplitter::data_scan(Http2FlowData* session_dat *session_data->infractions[source_id] += INF_FRAME_SEQUENCE; session_data->events[source_id]->create_event(EVENT_FRAME_SEQUENCE); + // FIXIT-E We should not be aborting here return StreamSplitter::ABORT; } @@ -129,15 +131,6 @@ StreamSplitter::Status Http2StreamSplitter::non_data_scan(Http2FlowData* session session_data->scan_remaining_frame_octets[source_id] = frame_length; session_data->total_bytes_in_split[source_id] += FRAME_HEADER_LENGTH + frame_length; - - // If the stream object exists and the end_stream flag is set, save that state in the - // stream object. If this is the first headers frame in the current stream, the stream - // object has not been created yet. The end_stream flag will be handled in the headers - // frame processing - Http2Stream* const stream = session_data->find_stream( - session_data->current_stream[source_id]); - if (stream and frame_flags & END_STREAM) - stream->set_end_stream(source_id); } // If we don't have the full frame, keep scanning @@ -193,8 +186,9 @@ StreamSplitter::Status Http2StreamSplitter::non_data_scan(Http2FlowData* session } // Flush pending data -void Http2StreamSplitter::partial_flush_data(Http2FlowData* session_data, HttpCommon::SourceId source_id, - uint32_t* flush_offset, uint32_t data_offset, uint32_t old_stream) +void Http2StreamSplitter::partial_flush_data(Http2FlowData* session_data, + HttpCommon::SourceId source_id, uint32_t* flush_offset, uint32_t data_offset, uint32_t + old_stream) { session_data->current_stream[source_id] = session_data->stream_in_hi = old_stream; session_data->frame_type[source_id] = FT_DATA; @@ -311,7 +305,8 @@ StreamSplitter::Status Http2StreamSplitter::implement_scan(Http2FlowData* sessio ((old_stream != session_data->current_stream[source_id] && type == FT_DATA) || type != FT_DATA)) { - partial_flush_data(session_data, source_id, flush_offset, data_offset, old_stream); + partial_flush_data(session_data, source_id, flush_offset, data_offset, + old_stream); return StreamSplitter::FLUSH; } diff --git a/src/service_inspectors/http2_inspect/http2_tables.cc b/src/service_inspectors/http2_inspect/http2_tables.cc index 76b8d5998..535f9345a 100644 --- a/src/service_inspectors/http2_inspect/http2_tables.cc +++ b/src/service_inspectors/http2_inspect/http2_tables.cc @@ -52,10 +52,12 @@ const RuleMap Http2Module::http2_events[] = const PegInfo Http2Module::peg_names[PEG_COUNT__MAX+1] = { - { CountType::SUM, "flows", "HTTP connections inspected" }, + { CountType::SUM, "flows", "HTTP/2 connections inspected" }, { CountType::NOW, "concurrent_sessions", "total concurrent HTTP/2 sessions" }, { CountType::MAX, "max_concurrent_sessions", "maximum concurrent HTTP/2 sessions" }, { CountType::MAX, "max_table_entries", "maximum entries in an HTTP/2 dynamic table" }, + { CountType::MAX, "max_concurrent_files", "maximum concurrent file transfers per HTTP/2 " + "connection" }, { CountType::END, nullptr, nullptr } }; diff --git a/src/service_inspectors/http_inspect/http_stream_splitter_finish.cc b/src/service_inspectors/http_inspect/http_stream_splitter_finish.cc index ade06bc9f..dba08efc6 100644 --- a/src/service_inspectors/http_inspect/http_stream_splitter_finish.cc +++ b/src/service_inspectors/http_inspect/http_stream_splitter_finish.cc @@ -161,10 +161,11 @@ bool HttpStreamSplitter::init_partial_flush(Flow* flow) { Profile profile(HttpModule::get_profile_stats()); - assert(source_id == SRC_SERVER); - HttpFlowData* session_data = HttpInspect::http_get_flow_data(flow); assert(session_data != nullptr); + + assert(session_data->for_http2 || source_id == SRC_SERVER); + assert((session_data->type_expected[source_id] == SEC_BODY_CL) || (session_data->type_expected[source_id] == SEC_BODY_OLD) || (session_data->type_expected[source_id] == SEC_BODY_CHUNK) ||