From: Mike Stepanek (mstepane) Date: Mon, 26 Oct 2020 15:45:07 +0000 (+0000) Subject: Merge pull request #2571 in SNORT/snort3 from ~MDAGON/snort3:react2 to master X-Git-Tag: 3.0.3-4~6 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=15b876c37984bbaa1a77c25b324d3febfcd45f54;p=thirdparty%2Fsnort3.git Merge pull request #2571 in SNORT/snort3 from ~MDAGON/snort3:react2 to master Squashed commit of the following: commit 83f8deb2a7dd18a555f348ae36cf4ee81da612fe Author: mdagon Date: Mon Sep 28 14:15:25 2020 -0400 actions: react supports HTTP/2 --- diff --git a/src/actions/act_react.cc b/src/actions/act_react.cc index 98f6f8513..dbc05ebd5 100644 --- a/src/actions/act_react.cc +++ b/src/actions/act_react.cc @@ -57,10 +57,13 @@ #include "payload_injector/payload_injector_module.h" #include "profiler/profiler.h" #include "protocols/packet.h" +#include "service_inspectors/http2_inspect/http2_flow_data.h" #include "utils/util.h" #include "utils/util_cstring.h" using namespace snort; +using namespace HttpCommon; +using namespace Http2Enums; #define s_name "react" @@ -100,7 +103,7 @@ public: { if ( page.empty()) { - resp_buf = DEFAULT_HTTP + std::to_string(sizeof(DEFAULT_HTML)); + resp_buf = DEFAULT_HTTP + std::to_string(strlen(DEFAULT_HTML)); resp_buf.append("\r\n\r\n"); resp_buf.append(DEFAULT_HTML); } @@ -148,6 +151,19 @@ private: InjectionControl control; control.http_page = (const uint8_t*)config->get_resp_buf(); control.http_page_len = config->get_buf_len(); + if (p->flow && p->flow->gadget && + (strcmp(p->flow->gadget->get_name(), "http2_inspect") == 0)) + { + Http2FlowData* const session_data = + (Http2FlowData*)p->flow->get_flow_data(Http2FlowData::inspector_id); + assert(session_data != nullptr); + const SourceId source_id = p->is_from_client() ? SRC_CLIENT : SRC_SERVER; + if (session_data != nullptr) + { + control.stream_id = session_data->get_current_stream_id(source_id); + assert(control.stream_id != NO_STREAM_ID); + } + } InjectionReturnStatus status = PayloadInjectorModule::inject_http_payload(p, control); #ifdef DEBUG_MSGS if (status != INJECTION_SUCCESS) diff --git a/src/payload_injector/payload_injector_module.cc b/src/payload_injector/payload_injector_module.cc index 5df57a9b0..b33a69075 100644 --- a/src/payload_injector/payload_injector_module.cc +++ b/src/payload_injector/payload_injector_module.cc @@ -60,7 +60,8 @@ static const std::map InjectionErrorToStrin { ERR_TRANSLATED_HDRS_SIZE, "HTTP/2 translated header size is bigger than expected. Update max size." }, { ERR_HTTP2_BODY_SIZE, "HTTP/2 body is > 16k. Currently not supported." }, - { ERR_HTTP2_EVEN_STREAM_ID, "HTTP/2 - injection to server initiated stream" } + { ERR_HTTP2_EVEN_STREAM_ID, "HTTP/2 - injection to server initiated stream" }, + { ERR_PKT_FROM_SERVER, "Packet is from server" } }; bool PayloadInjectorModule::configured = false; @@ -135,25 +136,30 @@ InjectionReturnStatus PayloadInjectorModule::inject_http_payload(Packet* p, if (configured) { - EncodeFlags df = (p->packet_flags & PKT_FROM_SERVER) ? ENC_FLAG_FWD : 0; - df |= ENC_FLAG_RST_SRVR; // Send RST to server. - - if (p->packet_flags & PKT_STREAM_EST) + if (p->packet_flags & PKT_FROM_SERVER) + status = ERR_PKT_FROM_SERVER; + else { - if (!p->flow) - status = ERR_UNIDENTIFIED_PROTOCOL; - else if (!p->flow->gadget || strcmp(p->flow->gadget->get_name(),"http_inspect") == 0) + EncodeFlags df = ENC_FLAG_RST_SRVR; // Send RST to server. + + if (p->packet_flags & PKT_STREAM_EST) { - payload_injector_stats.http_injects++; - p->active->send_data(p, df, control.http_page, control.http_page_len); + if (!p->flow) + status = ERR_UNIDENTIFIED_PROTOCOL; + else if (!p->flow->gadget || strcmp(p->flow->gadget->get_name(),"http_inspect") == + 0) + { + payload_injector_stats.http_injects++; + p->active->send_data(p, df, control.http_page, control.http_page_len); + } + else if (strcmp(p->flow->gadget->get_name(),"http2_inspect") == 0) + status = inject_http2_payload(p, control, df); + else + status = ERR_UNIDENTIFIED_PROTOCOL; } - else if (strcmp(p->flow->gadget->get_name(),"http2_inspect") == 0) - status = inject_http2_payload(p, control, df); else - status = ERR_UNIDENTIFIED_PROTOCOL; + status = ERR_STREAM_NOT_ESTABLISHED; } - else - status = ERR_STREAM_NOT_ESTABLISHED; } else status = ERR_INJECTOR_NOT_CONFIGURED; diff --git a/src/payload_injector/payload_injector_module.h b/src/payload_injector/payload_injector_module.h index 069ff2d04..466319213 100644 --- a/src/payload_injector/payload_injector_module.h +++ b/src/payload_injector/payload_injector_module.h @@ -50,7 +50,8 @@ enum InjectionReturnStatus : int8_t ERR_HTTP2_MID_FRAME = -6, ERR_TRANSLATED_HDRS_SIZE = -7, ERR_HTTP2_BODY_SIZE = -8, - ERR_HTTP2_EVEN_STREAM_ID = -9 + ERR_HTTP2_EVEN_STREAM_ID = -9, + ERR_PKT_FROM_SERVER = -10, // Update InjectionErrorToString when adding/removing error codes }; diff --git a/src/payload_injector/test/payload_injector_test.cc b/src/payload_injector/test/payload_injector_test.cc index 322399aaa..12a8abebe 100644 --- a/src/payload_injector/test/payload_injector_test.cc +++ b/src/payload_injector/test/payload_injector_test.cc @@ -318,6 +318,19 @@ TEST(payload_injector_test, http2_continuation_expected) delete flow.gadget; } +TEST(payload_injector_test, http2_pkt_from_srvr) +{ + mod.set_configured(true); + Packet p(false); + p.packet_flags = PKT_FROM_SERVER; + flow.gadget = new MockInspector(); + p.flow = &flow; + InjectionReturnStatus status = mod.inject_http_payload(&p, control); + CHECK(status == ERR_PKT_FROM_SERVER); + CHECK(flow.flow_state == Flow::FlowState::BLOCK); + delete flow.gadget; +} + TEST_GROUP(payload_injector_translate_err_test) { PayloadInjectorModule mod; diff --git a/src/service_inspectors/http2_inspect/http2_flow_data.h b/src/service_inspectors/http2_inspect/http2_flow_data.h index b38e354d1..a8c75daca 100644 --- a/src/service_inspectors/http2_inspect/http2_flow_data.h +++ b/src/service_inspectors/http2_inspect/http2_flow_data.h @@ -47,7 +47,7 @@ class HttpMsgSection; class HttpInspect; class HttpStreamSplitter; -class Http2FlowData : public snort::FlowData +class SO_PUBLIC Http2FlowData : public snort::FlowData { public: Http2FlowData(snort::Flow* flow_);