This is an automated email from the ASF dual-hosted git repository.
eze pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git
The following commit(s) were added to refs/heads/master by this push:
new dc1a7e3c6f Reject reserved h2 to h3 frame types (#10113)
dc1a7e3c6f is described below
commit dc1a7e3c6f89a3b897054516ec63505fb8c84f9a
Author: Evan Zelkowitz <[email protected]>
AuthorDate: Fri Jul 28 14:38:00 2023 -0600
Reject reserved h2 to h3 frame types (#10113)
---
proxy/http3/Http3DebugNames.cc | 6 ++
proxy/http3/Http3ProtocolEnforcer.cc | 11 ++-
proxy/http3/test/test_Http3FrameDispatcher.cc | 130 ++++++++++++++++++++------
3 files changed, 120 insertions(+), 27 deletions(-)
diff --git a/proxy/http3/Http3DebugNames.cc b/proxy/http3/Http3DebugNames.cc
index 9e3fbf9640..321c33b328 100644
--- a/proxy/http3/Http3DebugNames.cc
+++ b/proxy/http3/Http3DebugNames.cc
@@ -44,6 +44,12 @@ Http3DebugNames::frame_type(Http3FrameType type)
return "GOAWAY";
case Http3FrameType::DUPLICATE_PUSH_ID:
return "DUPLICATE_PUSH_ID";
+ case Http3FrameType::X_RESERVED_1:
+ return "X_RESERVED_1";
+ case Http3FrameType::X_RESERVED_2:
+ return "X_RESERVED_2";
+ case Http3FrameType::X_RESERVED_3:
+ return "X_RESERVED_3";
case Http3FrameType::UNKNOWN:
default:
return "UNKNOWN";
diff --git a/proxy/http3/Http3ProtocolEnforcer.cc
b/proxy/http3/Http3ProtocolEnforcer.cc
index 9a90cda451..b2b64daad6 100644
--- a/proxy/http3/Http3ProtocolEnforcer.cc
+++ b/proxy/http3/Http3ProtocolEnforcer.cc
@@ -46,11 +46,20 @@ Http3ProtocolEnforcer::handle_frame(std::shared_ptr<const
Http3Frame> frame, int
} else if (frame_seq != 0 && f_type == Http3FrameType::SETTINGS) {
error =
std::make_unique<Http3ConnectionError>(Http3ErrorCode::H3_FRAME_UNEXPECTED,
"only one SETTINGS frame
is allowed per the control stream");
- } else if (f_type == Http3FrameType::DATA || f_type ==
Http3FrameType::HEADERS) {
+ } else if (f_type == Http3FrameType::DATA || f_type ==
Http3FrameType::HEADERS || f_type == Http3FrameType::X_RESERVED_1 ||
+ f_type == Http3FrameType::X_RESERVED_2 || f_type ==
Http3FrameType::X_RESERVED_3) {
std::string error_msg = Http3DebugNames::frame_type(f_type);
error_msg.append(" frame is not allowed on control stream");
error =
std::make_unique<Http3ConnectionError>(Http3ErrorCode::H3_FRAME_UNEXPECTED,
error_msg.c_str());
}
+ } else {
+ if (f_type == Http3FrameType::X_RESERVED_1 || f_type ==
Http3FrameType::X_RESERVED_2 ||
+ f_type == Http3FrameType::X_RESERVED_3) {
+ std::string error_msg = Http3DebugNames::frame_type(f_type);
+ error_msg.append(" frame is not allowed on any stream");
+ error =
std::make_unique<Http3ConnectionError>(Http3ErrorCode::H3_FRAME_UNEXPECTED,
error_msg.c_str());
+ }
}
+
return error;
}
diff --git a/proxy/http3/test/test_Http3FrameDispatcher.cc
b/proxy/http3/test/test_Http3FrameDispatcher.cc
index 8ba980e202..0987e4e8dd 100644
--- a/proxy/http3/test/test_Http3FrameDispatcher.cc
+++ b/proxy/http3/test/test_Http3FrameDispatcher.cc
@@ -29,32 +29,37 @@
TEST_CASE("Http3FrameHandler dispatch", "[http3]")
{
- uint8_t input[] = {// 1st frame (HEADERS)
- 0x01, 0x04, 0x11, 0x22, 0x33, 0x44,
- // 2nd frame (DATA)
- 0x00, 0x04, 0xaa, 0xbb, 0xcc, 0xdd,
- // 3rd frame (incomplete)
- 0xff};
-
- Http3FrameDispatcher http3FrameDispatcher;
- Http3MockFrameHandler handler;
- http3FrameDispatcher.add_handler(&handler);
-
- MIOBuffer *buf = new_MIOBuffer(BUFFER_SIZE_INDEX_512);
- IOBufferReader *reader = buf->alloc_reader();
- uint64_t nread = 0;
- Http3ErrorUPtr error = Http3ErrorUPtr(new Http3NoError());
-
- buf->write(input, sizeof(input));
-
- // Initial state
- CHECK(handler.total_frame_received == 0);
- CHECK(nread == 0);
-
- error = http3FrameDispatcher.on_read_ready(0, Http3StreamType::UNKNOWN,
*reader, nread);
- CHECK(error->app_error_code == Http3ErrorCode::H3_NO_ERROR);
- CHECK(handler.total_frame_received == 1);
- CHECK(nread == 12);
+ SECTION("Test good case")
+ {
+ uint8_t input[] = {// 1st frame (HEADERS)
+ 0x01, 0x04, 0x11, 0x22, 0x33, 0x44,
+ // 2nd frame (DATA)
+ 0x00, 0x04, 0xaa, 0xbb, 0xcc, 0xdd,
+ // 3rd frame (incomplete)
+ 0xff};
+
+ Http3FrameDispatcher http3FrameDispatcher;
+ Http3MockFrameHandler handler;
+ Http3ProtocolEnforcer enforcer;
+ http3FrameDispatcher.add_handler(&handler);
+ http3FrameDispatcher.add_handler(&enforcer);
+
+ MIOBuffer *buf = new_MIOBuffer(BUFFER_SIZE_INDEX_512);
+ IOBufferReader *reader = buf->alloc_reader();
+ uint64_t nread = 0;
+ Http3ErrorUPtr error = Http3ErrorUPtr(new Http3NoError());
+
+ buf->write(input, sizeof(input));
+
+ // Initial state
+ CHECK(handler.total_frame_received == 0);
+ CHECK(nread == 0);
+
+ error = http3FrameDispatcher.on_read_ready(0, Http3StreamType::UNKNOWN,
*reader, nread);
+ CHECK(error->app_error_code == Http3ErrorCode::H3_NO_ERROR);
+ CHECK(handler.total_frame_received == 1);
+ CHECK(nread == 12);
+ }
}
TEST_CASE("control stream tests", "[http3]")
@@ -219,6 +224,44 @@ TEST_CASE("control stream tests", "[http3]")
CHECK(handler.total_frame_received == 1);
CHECK(nread == sizeof(input));
}
+
+ SECTION("RESERVED frame is not allowed on control stream")
+ {
+ uint8_t input[] = {0x04, // Type
+ 0x08, // Length
+ 0x06, // Identifier
+ 0x44, 0x00, // Value
+ 0x09, // Identifier
+ 0x0f, // Value
+ 0x4a, 0x0a, // Identifier
+ 0x00, // Value
+ 0x06, // Type
+ 0x04, // Length
+ 0x11, 0x22, 0x33, 0x44};
+
+ Http3FrameDispatcher http3FrameDispatcher;
+ Http3ProtocolEnforcer enforcer;
+ Http3MockFrameHandler handler;
+
+ http3FrameDispatcher.add_handler(&enforcer);
+ http3FrameDispatcher.add_handler(&handler);
+
+ MIOBuffer *buf = new_MIOBuffer(BUFFER_SIZE_INDEX_512);
+ IOBufferReader *reader = buf->alloc_reader();
+ uint64_t nread = 0;
+ Http3ErrorUPtr error = Http3ErrorUPtr(new Http3NoError());
+
+ buf->write(input, sizeof(input));
+
+ // Initial state
+ CHECK(handler.total_frame_received == 0);
+ CHECK(nread == 0);
+
+ error = http3FrameDispatcher.on_read_ready(0, Http3StreamType::CONTROL,
*reader, nread);
+ CHECK(error->app_error_code == Http3ErrorCode::H3_FRAME_UNEXPECTED);
+ CHECK(handler.total_frame_received == 1);
+ CHECK(nread == sizeof(input));
+ }
}
TEST_CASE("ignore unknown frames", "[http3]")
@@ -244,3 +287,38 @@ TEST_CASE("ignore unknown frames", "[http3]")
CHECK(nread == 0);
}
}
+
+TEST_CASE("Reserved frame type not allowed", "[http3]")
+{
+ SECTION("Reject reserved frame type in non control stream")
+ {
+ uint8_t input[] = {// 1st frame (HEADERS)
+ 0x01, 0x04, 0x11, 0x22, 0x33, 0x44,
+ // 2nd frame (DATA)
+ 0x06, 0x04, 0xaa, 0xbb, 0xcc, 0xdd,
+ // 3rd frame (incomplete)
+ 0xff};
+
+ Http3FrameDispatcher http3FrameDispatcher;
+ Http3MockFrameHandler handler;
+ Http3ProtocolEnforcer enforcer;
+ http3FrameDispatcher.add_handler(&handler);
+ http3FrameDispatcher.add_handler(&enforcer);
+
+ MIOBuffer *buf = new_MIOBuffer(BUFFER_SIZE_INDEX_512);
+ IOBufferReader *reader = buf->alloc_reader();
+ uint64_t nread = 0;
+ Http3ErrorUPtr error = Http3ErrorUPtr(new Http3NoError());
+
+ buf->write(input, sizeof(input));
+
+ // Initial state
+ CHECK(handler.total_frame_received == 0);
+ CHECK(nread == 0);
+
+ error = http3FrameDispatcher.on_read_ready(0, Http3StreamType::UNKNOWN,
*reader, nread);
+ CHECK(error->app_error_code == Http3ErrorCode::H3_FRAME_UNEXPECTED);
+ CHECK(handler.total_frame_received == 0);
+ CHECK(nread == 12);
+ }
+}