From: Mike Stepanek (mstepane) Date: Tue, 3 Mar 2020 19:51:34 +0000 (+0000) Subject: Merge pull request #2019 in SNORT/snort3 from ~MDAGON/snort3:data_frame to master X-Git-Tag: 3.0.0-269~19 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=45f5a67521b8178a6c1817ddc76d2950d213ed47;p=thirdparty%2Fsnort3.git Merge pull request #2019 in SNORT/snort3 from ~MDAGON/snort3:data_frame to master Squashed commit of the following: commit 00768b50e95acb2349676661affb73b40f2a53b1 Author: mdagon Date: Fri Jan 31 11:49:38 2020 -0500 http2_inspect: send data frames to http - full frames only in a single flush --- diff --git a/doc/http2_inspect.txt b/doc/http2_inspect.txt index 6db65d6a2..85577ee4e 100644 --- a/doc/http2_inspect.txt +++ b/doc/http2_inspect.txt @@ -7,13 +7,11 @@ You can configure it by adding: to your snort.lua configuration file. Everything has a beginning and for http2_inspect this is the beginning of -the beginning. Most of the protocol including HPACK decompression is not -implemented yet. +the beginning. Currently http2_inspect will divide an HTTP/2 connection into individual -frames and make them available for detection. Two new rule options are -available for looking at HTTP/2 frames: http2_frame_header provides the -9-octet frame header and http2_frame_data provides the frame content. +frames. Two new rule options are available for looking at HTTP/2 frames: +http2_frame_header provides the 9-octet frame header. alert tcp any any -> any any (msg:"Frame type"; flow:established, to_client; http2_frame_header; content:"|06|", offset 3, depth 1; @@ -21,22 +19,6 @@ available for looking at HTTP/2 frames: http2_frame_header provides the This will match if the Type byte of the frame header is 6 (PING). - alert tcp any any -> any any ( msg:"Content of HTTP/2 frame"; - flow:established, to_client; http2_frame_data; content:"peppermint"; - sid:2; rev:1; ) - -This will look for peppermint in the frame data but not the frame header. - -These can be combined: - - alert tcp any any -> any any ( msg:"Search in message bodies"; - flow:established, to_client; - http2_frame_header; content:"|00|", offset 3, depth 1; - http2_frame_data; content:"MaLwArE"; sid:3; rev:1; ) - -Frame type 0 is DATA which carries the HTTP message body. This rule will -search for MaLwArE inside an HTTP message body. - To smooth the transition to inspecting HTTP/2, rules that specify service:http will be treated as if they also specify service:http2. Thus: @@ -61,7 +43,6 @@ large numbers of existing rules. New rules should explicitly specify "service http,http2;" if that is the desired behavior. Eventually support for http implies http2 may be deprecated and removed. -In the future, http2_inspect will support HPACK header decompression and -be fully integrated with http_inspect to provide full inspection of the -individual HTTP/1.1 streams. +In the future, http2_inspect will be fully integrated with http_inspect to +provide full inspection of the individual HTTP/1.1 streams. diff --git a/src/service_inspectors/http2_inspect/CMakeLists.txt b/src/service_inspectors/http2_inspect/CMakeLists.txt index 3d11259a0..4e8177303 100644 --- a/src/service_inspectors/http2_inspect/CMakeLists.txt +++ b/src/service_inspectors/http2_inspect/CMakeLists.txt @@ -2,6 +2,10 @@ set (FILE_LIST http2_api.cc http2_api.h + http2_data_frame.cc + http2_data_frame.h + http2_data_cutter.cc + http2_data_cutter.h http2_enum.h http2_flow_data.cc http2_flow_data.h diff --git a/src/service_inspectors/http2_inspect/http2_api.cc b/src/service_inspectors/http2_inspect/http2_api.cc index fd733aed0..e0478b185 100644 --- a/src/service_inspectors/http2_inspect/http2_api.cc +++ b/src/service_inspectors/http2_inspect/http2_api.cc @@ -73,7 +73,6 @@ const InspectApi Http2Api::http2_api = }; extern const BaseApi* ips_http2_frame_header; -extern const BaseApi* ips_http2_frame_data; extern const BaseApi* ips_http2_decoded_header; #ifdef BUILDING_SO @@ -84,7 +83,6 @@ const BaseApi* sin_http2[] = { &Http2Api::http2_api.base, ips_http2_frame_header, - ips_http2_frame_data, ips_http2_decoded_header, nullptr }; diff --git a/src/service_inspectors/http2_inspect/http2_data_cutter.cc b/src/service_inspectors/http2_inspect/http2_data_cutter.cc new file mode 100644 index 000000000..b18f77177 --- /dev/null +++ b/src/service_inspectors/http2_inspect/http2_data_cutter.cc @@ -0,0 +1,290 @@ +//-------------------------------------------------------------------------- +// 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_data_cutter.cc author Maya Dagon + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "http2_data_cutter.h" + +#include "service_inspectors/http_inspect/http_flow_data.h" +#include "service_inspectors/http_inspect/http_stream_splitter.h" + +#include "http2_dummy_packet.h" + +using namespace snort; +using namespace HttpCommon; +using namespace Http2Enums; + +static std::string create_chunk_hdr(uint32_t len) +{ + std::stringstream stream; + stream<infractions[source_id] += INF_PADDING_LEN; + session_data->events[source_id]->create_event(EVENT_PADDING_LEN); + return false; + } + // FIXIT temporary - till multiple data frames sent to http + if (data_len == (padding_len + 1)) + return false; + data_len -= (padding_len + 1); + data_state = DATA; + cur_pos++; + cur_data_offset++; + break; + case DATA: + { + const uint32_t missing = data_len - data_bytes_read; + cur_data = ((length - cur_pos) >= missing) ? + missing : (length - cur_pos); + data_bytes_read += cur_data; + cur_pos += cur_data; + if (data_bytes_read == data_len) + data_state = padding_len ? PADDING : FULL_FRAME; + break; + } + case PADDING: + { + const uint32_t missing = padding_len - padding_read; + cur_padding = ((length - cur_pos) >= missing) ? + missing : (length - cur_pos); + cur_pos += cur_padding; + padding_read += cur_padding; + if (padding_read == padding_len) + data_state = FULL_FRAME; + break; + } + default: + break; + } + } + + frame_bytes_seen += cur_pos; + session_data->scan_remaining_frame_octets[source_id] = frame_length - frame_bytes_seen; + *flush_offset += cur_pos; + + return true; +} + +// Call http scan. Wrap data with chunk header and end of chunk. +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; + + // first phase supports only flush of full packet + switch (http_state) + { + case NONE_SENT: + { + if (cur_data) + { + std::string chunk_hdr = create_chunk_hdr(data_len); + scan_result = session_data->hi_ss[source_id]->scan(&dummy_pkt, + (const unsigned char*)chunk_hdr.c_str(), + chunk_hdr.length(), unused, &http_flush_offset); + bytes_sent_http += chunk_hdr.length(); + http_state = HEADER_SENT; + if (scan_result != StreamSplitter::SEARCH) + return StreamSplitter::ABORT; + } + } // fallthrough + case HEADER_SENT: + { + if (cur_data) + { + scan_result = session_data->hi_ss[source_id]->scan(&dummy_pkt, data + cur_data_offset, + cur_data, unused, &http_flush_offset); + bytes_sent_http += cur_data; + + if (scan_result != StreamSplitter::SEARCH) + return StreamSplitter::ABORT; + } + if (data_state == FULL_FRAME) + { + scan_result = session_data->hi_ss[source_id]->scan(&dummy_pkt, (const unsigned + char*)"\r\n0\r\n", + 5, unused, &http_flush_offset); + bytes_sent_http +=5; + assert(scan_result == StreamSplitter::FLUSH); + + session_data->scan_octets_seen[source_id] = 0; + session_data->scan_remaining_frame_octets[source_id] = 0; + } + } + } + + if (scan_result != StreamSplitter::FLUSH) + *flush_offset = 0; + + return scan_result; +} + +StreamSplitter::Status Http2DataCutter::scan(const uint8_t* data, uint32_t length, + uint32_t* flush_offset) +{ + if (!http2_scan(data, length, flush_offset)) + return StreamSplitter::ABORT; + + return Http2DataCutter::http_scan(data, flush_offset); +} + +const StreamBuffer Http2DataCutter::reassemble(unsigned total, unsigned offset, const + uint8_t* data, unsigned len) +{ + StreamBuffer frame_buf { nullptr, 0 }; + + if (offset == 0) + { + padding_read = data_bytes_read = hdr_bytes_read = 0; + } + cur_data = cur_padding = cur_data_offset = 0; + + unsigned cur_pos = 0; + while (cur_pos < len) + { + switch (reassemble_state) + { + case SKIP_FRAME_HDR: + { + if (hdr_bytes_read == 0) + { + session_data->frame_header[source_id] = new uint8_t[FRAME_HEADER_LENGTH]; + session_data->frame_header_size[source_id] = FRAME_HEADER_LENGTH; + } + const uint32_t missing = FRAME_HEADER_LENGTH - hdr_bytes_read; + const uint32_t cur_frame = ((len - cur_pos) < missing) ? (len - cur_pos) : missing; + memcpy(session_data->frame_header[source_id] + hdr_bytes_read, data + cur_pos, + cur_frame); + hdr_bytes_read += cur_frame; + cur_pos += cur_frame; + if (hdr_bytes_read == FRAME_HEADER_LENGTH) + { + cur_data_offset = cur_pos; + reassemble_state = (padding_len) ? SKIP_PADDING_LEN : SEND_CHUNK_HDR; + } + + break; + } + case SKIP_PADDING_LEN: + cur_pos++; + cur_data_offset++; + reassemble_state = SEND_CHUNK_HDR; + break; + case SEND_CHUNK_HDR: + { + std::string chunk_hdr = create_chunk_hdr(data_len); + unsigned copied; + session_data->hi_ss[source_id]->reassemble(session_data->flow, + bytes_sent_http, 0, (const uint8_t*)chunk_hdr.c_str(), chunk_hdr.length(), 0, + copied); + assert(copied == (unsigned)chunk_hdr.length()); + reassemble_state = SEND_DATA; + } // fallthrough + case SEND_DATA: + { + const uint32_t missing = data_len - data_bytes_read; + cur_data = ((len - cur_pos) >= missing) ? missing : (len - cur_pos); + data_bytes_read += cur_data; + cur_pos += cur_data; + + unsigned copied; + frame_buf = session_data->hi_ss[source_id]->reassemble(session_data->flow, + bytes_sent_http, 0, data + cur_data_offset, cur_data, + 0, copied); + assert(copied == (unsigned)cur_data); + + if (data_bytes_read == data_len) + reassemble_state = (padding_len) ? SKIP_PADDING : SEND_CRLF; + + break; + } + case SKIP_PADDING: + { + const uint32_t missing = padding_len - padding_read; + cur_padding = ((len - cur_pos) >= missing) ? + missing : (len - cur_pos); + cur_pos += cur_padding; + padding_read += cur_padding; + if (padding_read == padding_len) + reassemble_state = SEND_CRLF; + break; + } + + default: + break; + } + } + + if (len + offset == total) + assert(reassemble_state == SEND_CRLF); + + if (reassemble_state == SEND_CRLF) + { + unsigned copied; + frame_buf = session_data->hi_ss[source_id]->reassemble(session_data->flow, + bytes_sent_http, 0,(const unsigned char*)"\r\n0\r\n", 5, PKT_PDU_TAIL, copied); + assert(copied == 5); + + assert(frame_buf.data != nullptr); + session_data->frame_data[source_id] = const_cast (frame_buf.data); + session_data->frame_data_size[source_id] = frame_buf.length; + } + + return frame_buf; +} + diff --git a/src/service_inspectors/http2_inspect/http2_data_cutter.h b/src/service_inspectors/http2_inspect/http2_data_cutter.h new file mode 100644 index 000000000..8755a1993 --- /dev/null +++ b/src/service_inspectors/http2_inspect/http2_data_cutter.h @@ -0,0 +1,81 @@ +//-------------------------------------------------------------------------- +// 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_data_cutter.h author Maya Dagon + +#ifndef HTTP2_DATA_CUTTER_H +#define HTTP2_DATA_CUTTER_H + +#include "service_inspectors/http_inspect/http_common.h" +#include "stream/stream_splitter.h" + +#include "http2_enum.h" +#include "http2_flow_data.h" + +class Http2DataCutter +{ +public: + Http2DataCutter(Http2FlowData* flow_data, uint32_t len, HttpCommon::SourceId + src_id, bool is_padded); + snort::StreamSplitter::Status scan(const uint8_t* data, uint32_t length, + uint32_t* flush_offset); + const snort::StreamBuffer reassemble(unsigned total, unsigned offset, const uint8_t* data, + unsigned len); + +private: + + Http2FlowData* const session_data; + const HttpCommon::SourceId source_id; + + // total per frame + const uint32_t frame_length; + uint32_t data_len; + uint32_t padding_len = 0; + // accumulating + uint32_t frame_bytes_seen = 0; + uint32_t bytes_sent_http = 0; + uint32_t hdr_bytes_read = 0; + uint32_t data_bytes_read = 0; + uint32_t padding_read = 0; + // per call + uint32_t cur_data; + uint32_t cur_padding; + uint32_t cur_data_offset; + + // + // State machines + // + + // data scan + enum DataState { PADDING_LENGTH, DATA, PADDING, FULL_FRAME }; + enum DataState data_state; + + // http scan + enum HttpScanState { NONE_SENT, HEADER_SENT }; + enum HttpScanState http_state = NONE_SENT; + + // reassemble + enum ReassembleState { SKIP_FRAME_HDR, SKIP_PADDING_LEN, SEND_CHUNK_HDR, SEND_DATA, + SKIP_PADDING, SEND_CRLF }; + enum ReassembleState reassemble_state = SKIP_FRAME_HDR; + + bool http2_scan(const uint8_t* data, uint32_t length, uint32_t* flush_offset); + snort::StreamSplitter::Status http_scan(const uint8_t* data, uint32_t* flush_offset); +}; + +#endif + diff --git a/src/service_inspectors/http2_inspect/http2_data_frame.cc b/src/service_inspectors/http2_inspect/http2_data_frame.cc new file mode 100644 index 000000000..01a6c96f6 --- /dev/null +++ b/src/service_inspectors/http2_inspect/http2_data_frame.cc @@ -0,0 +1,58 @@ +//-------------------------------------------------------------------------- +// 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_data_frame.cc author Maya Dagon + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "http2_data_frame.h" + +#include "protocols/packet.h" +#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" + +using namespace HttpCommon; +using namespace snort; + +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_) +{ + 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_len; + dummy_pkt.data = data_buffer; + dummy_pkt.xtradata_mask = 0; + session_data->hi->eval(&dummy_pkt); + detection_required = dummy_pkt.is_detection_required(); + xtradata_mask = dummy_pkt.xtradata_mask; +} + +void Http2DataFrame::clear() +{ + Http2DummyPacket dummy_pkt; + dummy_pkt.flow = session_data->flow; + session_data->hi->clear(&dummy_pkt); +} + diff --git a/src/service_inspectors/http2_inspect/http2_data_frame.h b/src/service_inspectors/http2_inspect/http2_data_frame.h new file mode 100644 index 000000000..904f5aafa --- /dev/null +++ b/src/service_inspectors/http2_inspect/http2_data_frame.h @@ -0,0 +1,45 @@ +//-------------------------------------------------------------------------- +// 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_data_frame.h author Maya Dagon + +#ifndef HTTP2_DATA_FRAME_H +#define HTTP2_DATA_FRAME_H + +#include "http2_frame.h" + +class Http2Frame; + +class Http2DataFrame : public Http2Frame +{ +public: + ~Http2DataFrame() override {} + void clear() 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); + +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); + uint32_t xtradata_mask = 0; + bool detection_required = false; +}; +#endif diff --git a/src/service_inspectors/http2_inspect/http2_enum.h b/src/service_inspectors/http2_inspect/http2_enum.h index fdab3edbf..b042b3d24 100644 --- a/src/service_inspectors/http2_inspect/http2_enum.h +++ b/src/service_inspectors/http2_inspect/http2_enum.h @@ -64,6 +64,7 @@ enum EventSid EVENT_FRAME_SEQUENCE = 13, EVENT_DYNAMIC_TABLE_OVERFLOW = 14, EVENT_INVALID_STARTLINE = 15, + EVENT_PADDING_LEN = 16, EVENT__MAX_VALUE }; @@ -98,6 +99,7 @@ enum Infraction INF_TOO_MANY_TABLE_SIZE_UPDATES = 24, INF_INVALID_STARTLINE = 25, INF_INVALID_HEADER = 26, + INF_PADDING_LEN = 27, INF__MAX_VALUE }; diff --git a/src/service_inspectors/http2_inspect/http2_flow_data.cc b/src/service_inspectors/http2_inspect/http2_flow_data.cc index 51d5e362e..9627846eb 100644 --- a/src/service_inspectors/http2_inspect/http2_flow_data.cc +++ b/src/service_inspectors/http2_inspect/http2_flow_data.cc @@ -87,6 +87,8 @@ Http2FlowData::~Http2FlowData() delete infractions[k]; delete events[k]; delete hi_ss[k]; + delete[] frame_data[k]; + delete[] frame_header[k]; } } diff --git a/src/service_inspectors/http2_inspect/http2_flow_data.h b/src/service_inspectors/http2_inspect/http2_flow_data.h index 51891d6cd..ae7c8b3ce 100644 --- a/src/service_inspectors/http2_inspect/http2_flow_data.h +++ b/src/service_inspectors/http2_inspect/http2_flow_data.h @@ -62,6 +62,8 @@ public: void set_hi_msg_section(HttpMsgSection* section); friend class Http2Frame; + friend class Http2DataFrame; + friend class Http2DataCutter; friend class Http2HeadersFrame; friend class Http2Hpack; friend class Http2Inspect; @@ -71,6 +73,8 @@ 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, bool is_padded); 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, diff --git a/src/service_inspectors/http2_inspect/http2_frame.cc b/src/service_inspectors/http2_inspect/http2_frame.cc index 78837dd56..1b34537d3 100644 --- a/src/service_inspectors/http2_inspect/http2_frame.cc +++ b/src/service_inspectors/http2_inspect/http2_frame.cc @@ -23,6 +23,7 @@ #include "http2_frame.h" +#include "http2_data_frame.h" #include "http2_enum.h" #include "http2_flow_data.h" #include "http2_headers_frame.h" @@ -57,6 +58,8 @@ Http2Frame* Http2Frame::new_frame(const uint8_t* header, const int32_t header_le case FT_SETTINGS: return new Http2SettingsFrame(header, header_len, data, data_len, session_data, source_id); + case FT_DATA: + return new Http2DataFrame(header, header_len, data, data_len, session_data, source_id); default: return new Http2Frame(header, header_len, data, data_len, session_data, source_id); } diff --git a/src/service_inspectors/http2_inspect/http2_headers_frame.cc b/src/service_inspectors/http2_inspect/http2_headers_frame.cc index 87f84af67..46254299d 100644 --- a/src/service_inspectors/http2_inspect/http2_headers_frame.cc +++ b/src/service_inspectors/http2_inspect/http2_headers_frame.cc @@ -74,7 +74,7 @@ Http2HeadersFrame::Http2HeadersFrame(const uint8_t* header_buffer, const int32_t start_line = hpack_decoder.get_start_line(); http1_header = hpack_decoder.get_decoded_headers(decoded_headers); - if ((error_during_decode) || (session_data->hi_ss[source_id] == nullptr)) + if (error_during_decode) return; // http_inspect scan() of start line @@ -181,7 +181,7 @@ Http2HeadersFrame::~Http2HeadersFrame() void Http2HeadersFrame::clear() { - if (error_during_decode || hi_abort || (session_data->hi == nullptr)) + if (error_during_decode || hi_abort) return; Packet dummy_pkt(false); dummy_pkt.flow = session_data->flow; diff --git a/src/service_inspectors/http2_inspect/http2_inspect.cc b/src/service_inspectors/http2_inspect/http2_inspect.cc index 77de26ffd..e0e4b49ec 100644 --- a/src/service_inspectors/http2_inspect/http2_inspect.cc +++ b/src/service_inspectors/http2_inspect/http2_inspect.cc @@ -120,7 +120,7 @@ void Http2Inspect::eval(Packet* p) // FIXIT-H Workaround for unexpected eval() calls // Avoid eval if scan/reassemble aborts - if (session_data->frame_type[source_id] == FT__NONE) + if (session_data->frame_type[source_id] == FT__ABORT) return; Http2Stream* stream = session_data->get_current_stream(source_id); diff --git a/src/service_inspectors/http2_inspect/http2_stream.cc b/src/service_inspectors/http2_inspect/http2_stream.cc index dffdb222c..bd212718f 100644 --- a/src/service_inspectors/http2_inspect/http2_stream.cc +++ b/src/service_inspectors/http2_inspect/http2_stream.cc @@ -25,6 +25,8 @@ #include "service_inspectors/http_inspect/http_flow_data.h" +#include "http2_data_cutter.h" + using namespace HttpCommon; Http2Stream::Http2Stream(uint32_t stream_id_, Http2FlowData* session_data_) : @@ -37,6 +39,8 @@ Http2Stream::~Http2Stream() { delete current_frame; delete hi_flow_data; + delete data_cutter[SRC_CLIENT]; + delete data_cutter[SRC_SERVER]; } void Http2Stream::eval_frame(const uint8_t* header_buffer, int32_t header_len, @@ -70,3 +74,9 @@ void Http2Stream::print_frame(FILE* output) } #endif +Http2DataCutter* Http2Stream::get_data_cutter(HttpCommon::SourceId source_id, uint32_t len, bool is_padded) +{ + if (!data_cutter[source_id]) + data_cutter[source_id] = new Http2DataCutter(session_data, len, source_id, is_padded); + return data_cutter[source_id]; +} diff --git a/src/service_inspectors/http2_inspect/http2_stream.h b/src/service_inspectors/http2_inspect/http2_stream.h index a267335b3..408d6c2f9 100644 --- a/src/service_inspectors/http2_inspect/http2_stream.h +++ b/src/service_inspectors/http2_inspect/http2_stream.h @@ -25,8 +25,9 @@ #include "http2_frame.h" -class HttpFlowData; +class Http2DataCutter; class Http2FlowData; +class HttpFlowData; class HttpMsgSection; class Http2Stream @@ -47,6 +48,11 @@ public: uint32_t get_xtradata_mask() { return (current_frame != nullptr) ? current_frame->get_xtradata_mask() : 0; } Http2Frame *get_current_frame() { return current_frame; } + Http2DataCutter* get_data_cutter(HttpCommon::SourceId source_id, uint32_t len=0, bool is_padded=false); + void set_data_cutter(Http2DataCutter* cutter, HttpCommon::SourceId source_id) { data_cutter[source_id] = cutter; } + bool get_abort_data_processing(HttpCommon::SourceId source_id) const { return abort_data_processing[source_id]; } + void set_abort_data_processing(HttpCommon::SourceId source_id) { abort_data_processing[source_id] = true; } + #ifdef REG_TEST void print_frame(FILE* output); #endif @@ -57,6 +63,8 @@ private: Http2Frame* current_frame = nullptr; HttpFlowData* hi_flow_data = nullptr; HttpMsgSection* hi_msg_section = nullptr; + Http2DataCutter* data_cutter[2] = { nullptr, nullptr}; + bool abort_data_processing[2] = {false, false}; }; #endif diff --git a/src/service_inspectors/http2_inspect/http2_stream_splitter.cc b/src/service_inspectors/http2_inspect/http2_stream_splitter.cc index bdf286fff..0d9c71afe 100644 --- a/src/service_inspectors/http2_inspect/http2_stream_splitter.cc +++ b/src/service_inspectors/http2_inspect/http2_stream_splitter.cc @@ -58,14 +58,7 @@ StreamSplitter::Status Http2StreamSplitter::scan(Packet* pkt, const uint8_t* dat pkt->flow->set_flow_data(session_data = new Http2FlowData(pkt->flow)); Http2Module::increment_peg_counts(PEG_FLOW); } - - // General mechanism to abort using scan - if (session_data->frame_type[source_id] == FT__ABORT) - { - session_data->frame_type[source_id] = FT__NONE; - return HttpStreamSplitter::status_value(StreamSplitter::ABORT, true); - } - + #ifdef REG_TEST uint32_t dummy_flush_offset; @@ -95,9 +88,16 @@ StreamSplitter::Status Http2StreamSplitter::scan(Packet* pkt, const uint8_t* dat } #endif + // General mechanism to abort using scan + if (session_data->frame_type[source_id] == FT__ABORT) + return HttpStreamSplitter::status_value(StreamSplitter::ABORT, true); + const StreamSplitter::Status ret_val = implement_scan(session_data, data, length, flush_offset, source_id); + if (ret_val == StreamSplitter::ABORT) + session_data->frame_type[source_id] = FT__ABORT; + #ifdef REG_TEST if (HttpTestManager::use_test_input(HttpTestManager::IN_HTTP2)) if (ret_val == StreamSplitter::FLUSH) 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 6eb937cc4..100d779dd 100644 --- a/src/service_inspectors/http2_inspect/http2_stream_splitter_impl.cc +++ b/src/service_inspectors/http2_inspect/http2_stream_splitter_impl.cc @@ -27,9 +27,11 @@ #include "service_inspectors/http_inspect/http_common.h" #include "service_inspectors/http_inspect/http_flow_data.h" +#include "service_inspectors/http_inspect/http_stream_splitter.h" #include "service_inspectors/http_inspect/http_test_input.h" #include "service_inspectors/http_inspect/http_test_manager.h" +#include "http2_data_cutter.h" #include "http2_flow_data.h" using namespace snort; @@ -48,7 +50,7 @@ static uint8_t get_frame_type(const uint8_t* frame_buffer) return frame_buffer[frame_type_index]; // If there was no frame header, this must be a piece of a long data frame else - return FT_DATA; + return FT_DATA; } static uint8_t get_frame_flags(const uint8_t* frame_buffer) @@ -65,9 +67,38 @@ static uint8_t get_stream_id(const uint8_t* frame_buffer) const uint8_t stream_id_index = 5; assert(frame_buffer != nullptr); return ((frame_buffer[stream_id_index] & 0x7f) << 24) + - (frame_buffer[stream_id_index + 1] << 16) + - (frame_buffer[stream_id_index + 2] << 8) + - frame_buffer[stream_id_index + 3]; + (frame_buffer[stream_id_index + 1] << 16) + + (frame_buffer[stream_id_index + 2] << 8) + + frame_buffer[stream_id_index + 3]; +} + +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, bool is_padded) +{ + Http2Stream* const stream = session_data->find_stream(session_data->current_stream[source_id]); + HttpFlowData* http_flow = nullptr; + if (stream) + { + http_flow = (HttpFlowData*)stream->get_hi_flow_data(); + // temporary, till more than 1 data frame sent to http inspect is supported + if (stream->get_abort_data_processing(source_id)) + return StreamSplitter::ABORT; + } + + if (!stream || !http_flow || (frame_length > 0 and + (http_flow->get_type_expected(source_id) != HttpEnums::SEC_BODY_CHUNK))) + { + *session_data->infractions[source_id] += INF_FRAME_SEQUENCE; + session_data->events[source_id]->create_event(EVENT_FRAME_SEQUENCE); + return StreamSplitter::ABORT; + } + + if (frame_length == 0 or frame_length > MAX_OCTETS) + return StreamSplitter::ABORT; + + Http2DataCutter* data_cutter = stream->get_data_cutter(source_id, frame_length, is_padded); + return data_cutter->scan(data, length, flush_offset); } StreamSplitter::Status implement_scan(Http2FlowData* session_data, const uint8_t* data, @@ -80,14 +111,14 @@ StreamSplitter::Status implement_scan(Http2FlowData* session_data, const uint8_t // Verify preface is correct, else generate loss of sync event and abort switch (validate_preface(data, length, session_data->scan_octets_seen[source_id])) { - case V_GOOD: - break; - case V_BAD: - session_data->events[source_id]->create_event(EVENT_PREFACE_MATCH_FAILURE); - return StreamSplitter::ABORT; - case V_TBD: - session_data->scan_octets_seen[source_id] += length; - return StreamSplitter::SEARCH; + case V_GOOD: + break; + case V_BAD: + session_data->events[source_id]->create_event(EVENT_PREFACE_MATCH_FAILURE); + return StreamSplitter::ABORT; + case V_TBD: + session_data->scan_octets_seen[source_id] += length; + return StreamSplitter::SEARCH; } *flush_offset = 24 - session_data->scan_octets_seen[source_id]; @@ -107,8 +138,8 @@ StreamSplitter::Status implement_scan(Http2FlowData* session_data, const uint8_t if (session_data->leftover_data[source_id] > DATA_SECTION_SIZE) session_data->scan_remaining_frame_octets[source_id] = DATA_SECTION_SIZE; else - session_data->scan_remaining_frame_octets[source_id] = - session_data->leftover_data[source_id]; + session_data->scan_remaining_frame_octets[source_id] = + session_data->leftover_data[source_id]; session_data->total_bytes_in_split[source_id] = 0; } @@ -165,25 +196,16 @@ StreamSplitter::Status implement_scan(Http2FlowData* session_data, const uint8_t // We have the full frame header, compute some variables const uint32_t frame_length = get_frame_length(session_data-> scan_frame_header[source_id]); - const uint8_t type = get_frame_type(session_data->scan_frame_header[source_id]); + const uint8_t type = session_data->frame_type[source_id] = get_frame_type( + session_data->scan_frame_header[source_id]); + uint8_t frame_flags = get_frame_flags(session_data-> + scan_frame_header[source_id]); session_data->current_stream[source_id] = get_stream_id(session_data->scan_frame_header[source_id]); if (type == FT_DATA) - { - Http2Stream* const stream = session_data->find_stream(session_data->current_stream[source_id]); - HttpFlowData* http_flow = nullptr; - if (stream) - http_flow = (HttpFlowData*)stream->get_hi_flow_data(); - - if (!stream || !http_flow || (frame_length > 0 and - (http_flow->get_type_expected(source_id) != HttpEnums::SEC_BODY_CHUNK))) - { - *session_data->infractions[source_id] += INF_FRAME_SEQUENCE; - session_data->events[source_id]->create_event(EVENT_FRAME_SEQUENCE); - status = StreamSplitter::ABORT; - } - } + return data_scan(session_data, data, length, flush_offset, source_id, + frame_length, ((frame_flags & PADDED) !=0)); // Compute frame section length once per frame if (session_data->scan_remaining_frame_octets[source_id] == 0) @@ -195,14 +217,8 @@ StreamSplitter::Status implement_scan(Http2FlowData* session_data, const uint8_t status = StreamSplitter::ABORT; break; } - if ((type == FT_DATA) && (frame_length > DATA_SECTION_SIZE)) - { - // Break up long data frames into pieces for detection - session_data->scan_remaining_frame_octets[source_id] = DATA_SECTION_SIZE; - session_data->total_bytes_in_split[source_id] = DATA_SECTION_SIZE + - FRAME_HEADER_LENGTH; - } - else if (frame_length + FRAME_HEADER_LENGTH > MAX_OCTETS) + + if (frame_length + FRAME_HEADER_LENGTH > MAX_OCTETS) { // FIXIT-M long non-data frame needs to be supported status = StreamSplitter::ABORT; @@ -225,51 +241,49 @@ StreamSplitter::Status implement_scan(Http2FlowData* session_data, const uint8_t } // Have the full frame - uint8_t frame_flags = get_frame_flags(session_data->scan_frame_header[source_id]); - switch(type) + switch (type) { - case FT_HEADERS: + case FT_HEADERS: + if (!(frame_flags & END_HEADERS)) + { + session_data->continuation_expected[source_id] = true; + status = StreamSplitter::SEARCH; + } + break; + case FT_CONTINUATION: + if (session_data->continuation_expected[source_id]) + { if (!(frame_flags & END_HEADERS)) - { - session_data->continuation_expected[source_id] = true; status = StreamSplitter::SEARCH; - } - break; - case FT_CONTINUATION: - if (session_data->continuation_expected[source_id]) - { - if (!(frame_flags & END_HEADERS)) - status = StreamSplitter::SEARCH; - else - { - // continuation frame ending headers - status = StreamSplitter::FLUSH; - session_data->continuation_expected[source_id] = false; - } - } else { - // FIXIT-M CONTINUATION frames can also follow PUSH_PROMISE frames, which - // are not currently supported - *session_data->infractions[source_id] += INF_UNEXPECTED_CONTINUATION; - session_data->events[source_id]->create_event( - EVENT_UNEXPECTED_CONTINUATION); - status = StreamSplitter::ABORT; + // continuation frame ending headers + status = StreamSplitter::FLUSH; + session_data->continuation_expected[source_id] = false; } - break; - case FT_DATA: - session_data->leftover_data[source_id] = frame_length - - (session_data->total_bytes_in_split[source_id] - FRAME_HEADER_LENGTH); - break; + } + else + { + // FIXIT-M CONTINUATION frames can also follow PUSH_PROMISE frames, which + // are not currently supported + *session_data->infractions[source_id] += INF_UNEXPECTED_CONTINUATION; + session_data->events[source_id]->create_event( + EVENT_UNEXPECTED_CONTINUATION); + status = StreamSplitter::ABORT; + } + break; + default: + break; } data_offset += session_data->scan_remaining_frame_octets[source_id]; *flush_offset = data_offset; session_data->scan_octets_seen[source_id] = 0; session_data->scan_remaining_frame_octets[source_id] = 0; - - } while (status == StreamSplitter::SEARCH && data_offset < length); + } + while (status == StreamSplitter::SEARCH && data_offset < length); } + return status; } @@ -282,103 +296,125 @@ const StreamBuffer implement_reassemble(Http2FlowData* session_data, unsigned to assert(offset+len <= total); assert(total >= FRAME_HEADER_LENGTH); assert(total <= MAX_OCTETS); - assert(total == session_data->total_bytes_in_split[source_id]); StreamBuffer frame_buf { nullptr, 0 }; - uint32_t data_offset = 0; - - if (offset == 0) + if (session_data->frame_type[source_id] == FT_DATA) { - // This is the first reassemble() for this frame and we need to allocate some buffers - session_data->frame_header_size[source_id] = FRAME_HEADER_LENGTH * - session_data->num_frame_headers[source_id]; - if (session_data->frame_header_size[source_id] > 0) - session_data->frame_header[source_id] = new uint8_t[ - session_data->frame_header_size[source_id]]; - - session_data->frame_data_size[source_id]= total - - 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_header_offset[source_id] = 0; - 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->padding_octets_in_frame[source_id] = 0; + 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(total, offset, data, len); + if (http_frame_buf.data) + { + delete data_cutter; + stream->set_data_cutter(nullptr, source_id); + stream->set_abort_data_processing(source_id); + session_data->frame_data[source_id] = const_cast(http_frame_buf.data); + session_data->frame_data_size[source_id] = http_frame_buf.length; + } } - - do + else { - uint32_t octets_to_copy; - - // Read the padding length if necessary - if (session_data->get_padding_len[source_id]) + uint32_t data_offset = 0; + + if (offset == 0) { - session_data->get_padding_len[source_id] = false; - session_data->padding_octets_in_frame[source_id] = *(data + data_offset); - data_offset += 1; - session_data->remaining_frame_octets[source_id] -= 1; - // Subtract the padding and padding length from the frame data size - session_data->frame_data_size[source_id] -= - (session_data->padding_octets_in_frame[source_id] + 1); + // This is the first reassemble() for this frame and we need to allocate some buffers + session_data->frame_header_size[source_id] = FRAME_HEADER_LENGTH * + session_data->num_frame_headers[source_id]; + if (session_data->frame_header_size[source_id] > 0) + session_data->frame_header[source_id] = new uint8_t[ + session_data->frame_header_size[source_id]]; + + session_data->frame_data_size[source_id]= total - + 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_header_offset[source_id] = 0; + 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->padding_octets_in_frame[source_id] = 0; } - // Copy data into the frame buffer until we run out of data or reach the end of the 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]; - octets_to_copy = remaining_frame_payload > len - data_offset ? len - data_offset : - remaining_frame_payload; - if (octets_to_copy > 0) + do { - memcpy(session_data->frame_data[source_id] + session_data->frame_data_offset[source_id], - data + data_offset, octets_to_copy); - } - session_data->frame_data_offset[source_id] += octets_to_copy; - session_data->remaining_frame_octets[source_id] -= octets_to_copy; - data_offset += octets_to_copy; + uint32_t octets_to_copy; - if (data_offset == len) - break; + // Read the padding length if necessary + if (session_data->get_padding_len[source_id]) + { + session_data->get_padding_len[source_id] = false; + session_data->padding_octets_in_frame[source_id] = *(data + data_offset); + data_offset += 1; + session_data->remaining_frame_octets[source_id] -= 1; + // Subtract the padding and padding length from the frame data size + session_data->frame_data_size[source_id] -= + (session_data->padding_octets_in_frame[source_id] + 1); + } - // Skip over any padding - uint32_t padding_bytes_to_skip = session_data->padding_octets_in_frame[source_id] > - len - data_offset ? len - data_offset : - session_data->padding_octets_in_frame[source_id]; - session_data->remaining_frame_octets[source_id] -= padding_bytes_to_skip; - data_offset += padding_bytes_to_skip; + // Copy data into the frame buffer until we run out of data or reach the end of the + // 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]; + octets_to_copy = remaining_frame_payload > len - data_offset ? len - data_offset : + remaining_frame_payload; + if (octets_to_copy > 0) + { + memcpy(session_data->frame_data[source_id] + + session_data->frame_data_offset[source_id], + data + data_offset, octets_to_copy); + } + session_data->frame_data_offset[source_id] += octets_to_copy; + session_data->remaining_frame_octets[source_id] -= octets_to_copy; + data_offset += octets_to_copy; - if (data_offset == len) - break; + if (data_offset == len) + 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->frame_header_offset[source_id] % FRAME_HEADER_LENGTH != 0) - break; + // Skip over any padding + uint32_t padding_bytes_to_skip = session_data->padding_octets_in_frame[source_id] > + len - data_offset ? len - data_offset : + session_data->padding_octets_in_frame[source_id]; + session_data->remaining_frame_octets[source_id] -= padding_bytes_to_skip; + data_offset += padding_bytes_to_skip; - // 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); + if (data_offset == len) + break; - 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; - } while (data_offset < len); + // 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->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]); + if (frame_flags & PADDED) + session_data->get_padding_len[source_id] = true; + } + while (data_offset < len); + 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; @@ -389,7 +425,6 @@ const StreamBuffer implement_reassemble(Http2FlowData* session_data, unsigned to // create pkt_data buffer frame_buf.data = (const uint8_t*)""; } - session_data->frame_type[source_id] = get_frame_type(session_data->frame_header[source_id]); return frame_buf; } @@ -399,8 +434,8 @@ ValidationResult validate_preface(const uint8_t* data, const uint32_t length, { 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'}; + 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); @@ -415,3 +450,4 @@ ValidationResult validate_preface(const uint8_t* data, const uint32_t length, return V_GOOD; } + diff --git a/src/service_inspectors/http2_inspect/http2_tables.cc b/src/service_inspectors/http2_inspect/http2_tables.cc index 71557351e..b558c107c 100644 --- a/src/service_inspectors/http2_inspect/http2_tables.cc +++ b/src/service_inspectors/http2_inspect/http2_tables.cc @@ -46,6 +46,7 @@ const RuleMap Http2Module::http2_events[] = { EVENT_FRAME_SEQUENCE, "invalid HTTP/2 frame sequence" }, { EVENT_DYNAMIC_TABLE_OVERFLOW, "HTTP/2 dynamic table size limit exceeded" }, { EVENT_INVALID_STARTLINE, "invalid HTTP/2 start line" }, + { EVENT_PADDING_LEN, "HTTP/2 padding length is bigger than frame data size" }, { 0, nullptr } }; diff --git a/src/service_inspectors/http2_inspect/ips_http2.cc b/src/service_inspectors/http2_inspect/ips_http2.cc index 957ac9343..8eef40b38 100644 --- a/src/service_inspectors/http2_inspect/ips_http2.cc +++ b/src/service_inspectors/http2_inspect/ips_http2.cc @@ -81,46 +81,6 @@ IpsOption::EvalStatus Http2IpsOption::eval(Cursor& c, Packet* p) return MATCH; } -//------------------------------------------------------------------------- -// http2_frame_data -//------------------------------------------------------------------------- - -#undef IPS_OPT -#define IPS_OPT "http2_frame_data" -#undef IPS_HELP -#define IPS_HELP "rule option to set detection cursor to the HTTP/2 frame body" - -static Module* frame_data_mod_ctor() -{ - return new Http2CursorModule(IPS_OPT, IPS_HELP, HTTP2_BUFFER_FRAME_DATA, CAT_SET_OTHER, - PSI_FRAME_DATA); -} - -static const IpsApi frame_data_api = -{ - { - PT_IPS_OPTION, - sizeof(IpsApi), - IPSAPI_VERSION, - 1, - API_RESERVED, - API_OPTIONS, - IPS_OPT, - IPS_HELP, - frame_data_mod_ctor, - Http2CursorModule::mod_dtor - }, - OPT_TYPE_DETECTION, - 0, PROTO_BIT__TCP, - nullptr, - nullptr, - nullptr, - nullptr, - Http2IpsOption::opt_ctor, - Http2IpsOption::opt_dtor, - nullptr -}; - //------------------------------------------------------------------------- // http2_frame_header //------------------------------------------------------------------------- @@ -205,7 +165,6 @@ static const IpsApi decoded_header_api = // plugins //------------------------------------------------------------------------- -const BaseApi* ips_http2_frame_data = &frame_data_api.base; const BaseApi* ips_http2_frame_header = &frame_header_api.base; const BaseApi* ips_http2_decoded_header = &decoded_header_api.base;