You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by bc...@apache.org on 2016/10/28 15:49:05 UTC
[trafficserver] 01/02: TS-5019: Add total header length checks in
HPACK
This is an automated email from the ASF dual-hosted git repository.
bcall pushed a commit to branch 7.0.x
in repository https://git-dual.apache.org/repos/asf/trafficserver.git
commit 19969fe4acc2fcd52b8e9728e0df96d871b47358
Author: Masaori Koshiba <ma...@apache.org>
AuthorDate: Fri Oct 28 08:18:58 2016 +0900
TS-5019: Add total header length checks in HPACK
(cherry picked from commit a5c11a863d961099af500649c4669fb711d48991)
---
proxy/http2/HPACK.cc | 16 +++++++++++++++-
proxy/http2/HPACK.h | 6 ++++--
proxy/http2/HTTP2.cc | 5 ++++-
proxy/http2/Http2ConnectionState.cc | 4 ++++
proxy/http2/Http2Stream.cc | 7 +++++++
proxy/http2/Http2Stream.h | 8 +-------
proxy/http2/RegressionHPACK.cc | 3 ++-
proxy/http2/test_HPACK.cc | 8 +++++---
8 files changed, 42 insertions(+), 15 deletions(-)
diff --git a/proxy/http2/HPACK.cc b/proxy/http2/HPACK.cc
index 9947170..68ec9f0 100644
--- a/proxy/http2/HPACK.cc
+++ b/proxy/http2/HPACK.cc
@@ -851,7 +851,8 @@ update_dynamic_table_size(const uint8_t *buf_start, const uint8_t *buf_end, Hpac
}
int64_t
-hpack_decode_header_block(HpackIndexingTable &indexing_table, HTTPHdr *hdr, const uint8_t *in_buf, const size_t in_buf_len)
+hpack_decode_header_block(HpackIndexingTable &indexing_table, HTTPHdr *hdr, const uint8_t *in_buf, const size_t in_buf_len,
+ uint32_t max_header_size)
{
const uint8_t *cursor = in_buf;
const uint8_t *const in_buf_end = in_buf + in_buf_len;
@@ -859,6 +860,7 @@ hpack_decode_header_block(HpackIndexingTable &indexing_table, HTTPHdr *hdr, cons
HTTPHdrImpl *hh = hdr->m_http;
bool header_field_started = false;
bool has_http2_violation = false;
+ uint32_t total_header_size = 0;
while (cursor < in_buf_end) {
int64_t read_bytes = 0;
@@ -902,6 +904,18 @@ hpack_decode_header_block(HpackIndexingTable &indexing_table, HTTPHdr *hdr, cons
cursor += read_bytes;
continue;
}
+
+ int name_len = 0;
+ int value_len = 0;
+
+ field->name_get(&name_len);
+ field->value_get(&value_len);
+ total_header_size += name_len + value_len;
+
+ if (total_header_size > max_header_size) {
+ return HPACK_ERROR_SIZE_EXCEEDED_ERROR;
+ }
+
// Store to HdrHeap
mime_hdr_field_attach(hh->m_fields_impl, field, 1, NULL);
}
diff --git a/proxy/http2/HPACK.h b/proxy/http2/HPACK.h
index cf57f7d..e0c60f9 100644
--- a/proxy/http2/HPACK.h
+++ b/proxy/http2/HPACK.h
@@ -30,7 +30,8 @@
#include "HTTP.h"
// It means that any header field can be compressed/decompressed by ATS
-const static int HPACK_ERROR_COMPRESSION_ERROR = -1;
+const static int HPACK_ERROR_COMPRESSION_ERROR = -1;
+const static int HPACK_ERROR_SIZE_EXCEEDED_ERROR = -2;
enum HpackFieldType {
HPACK_FIELD_INDEX, // [RFC 7541] 6.1. Indexed Header Field Representation
@@ -170,7 +171,8 @@ int64_t update_dynamic_table_size(const uint8_t *buf_start, const uint8_t *buf_e
// High level interfaces
typedef HpackIndexingTable HpackHandle;
-int64_t hpack_decode_header_block(HpackHandle &handle, HTTPHdr *hdr, const uint8_t *in_buf, const size_t in_buf_len);
+int64_t hpack_decode_header_block(HpackHandle &handle, HTTPHdr *hdr, const uint8_t *in_buf, const size_t in_buf_len,
+ uint32_t max_header_size);
int64_t hpack_encode_header_block(HpackHandle &handle, uint8_t *out_buf, const size_t out_buf_len, HTTPHdr *hdr);
#endif /* __HPACK_H__ */
diff --git a/proxy/http2/HTTP2.cc b/proxy/http2/HTTP2.cc
index f26354f..ac134ef 100644
--- a/proxy/http2/HTTP2.cc
+++ b/proxy/http2/HTTP2.cc
@@ -621,12 +621,15 @@ http2_decode_header_blocks(HTTPHdr *hdr, const uint8_t *buf_start, const uint32_
const char *value;
int len;
bool is_trailing_header = trailing_header;
- int64_t result = hpack_decode_header_block(handle, hdr, buf_start, buf_len);
+ int64_t result = hpack_decode_header_block(handle, hdr, buf_start, buf_len, Http2::max_request_header_size);
if (result < 0) {
if (result == HPACK_ERROR_COMPRESSION_ERROR) {
return HTTP2_ERROR_COMPRESSION_ERROR;
+ } else if (result == HPACK_ERROR_SIZE_EXCEEDED_ERROR) {
+ return HTTP2_ERROR_ENHANCE_YOUR_CALM;
}
+
return HTTP2_ERROR_PROTOCOL_ERROR;
}
if (len_read) {
diff --git a/proxy/http2/Http2ConnectionState.cc b/proxy/http2/Http2ConnectionState.cc
index c14ebf3..f6a7668 100644
--- a/proxy/http2/Http2ConnectionState.cc
+++ b/proxy/http2/Http2ConnectionState.cc
@@ -302,6 +302,8 @@ rcv_headers_frame(Http2ConnectionState &cstate, const Http2Frame &frame)
if (result != HTTP2_ERROR_NO_ERROR) {
if (result == HTTP2_ERROR_COMPRESSION_ERROR) {
return Http2Error(HTTP2_ERROR_CLASS_CONNECTION, HTTP2_ERROR_COMPRESSION_ERROR);
+ } else if (result == HTTP2_ERROR_ENHANCE_YOUR_CALM) {
+ return Http2Error(HTTP2_ERROR_CLASS_CONNECTION, HTTP2_ERROR_ENHANCE_YOUR_CALM);
} else {
return Http2Error(HTTP2_ERROR_CLASS_STREAM, HTTP2_ERROR_PROTOCOL_ERROR);
}
@@ -734,6 +736,8 @@ rcv_continuation_frame(Http2ConnectionState &cstate, const Http2Frame &frame)
if (result != HTTP2_ERROR_NO_ERROR) {
if (result == HTTP2_ERROR_COMPRESSION_ERROR) {
return Http2Error(HTTP2_ERROR_CLASS_CONNECTION, HTTP2_ERROR_COMPRESSION_ERROR);
+ } else if (result == HTTP2_ERROR_ENHANCE_YOUR_CALM) {
+ return Http2Error(HTTP2_ERROR_CLASS_CONNECTION, HTTP2_ERROR_ENHANCE_YOUR_CALM);
} else {
return Http2Error(HTTP2_ERROR_CLASS_STREAM, HTTP2_ERROR_PROTOCOL_ERROR);
}
diff --git a/proxy/http2/Http2Stream.cc b/proxy/http2/Http2Stream.cc
index 4d3a07b..a4896b3 100644
--- a/proxy/http2/Http2Stream.cc
+++ b/proxy/http2/Http2Stream.cc
@@ -135,6 +135,13 @@ Http2Stream::main_event_handler(int event, void *edata)
return 0;
}
+Http2ErrorCode
+Http2Stream::decode_header_blocks(HpackHandle &hpack_handle)
+{
+ return http2_decode_header_blocks(&_req_header, (const uint8_t *)header_blocks, header_blocks_length, NULL, hpack_handle,
+ trailing_header);
+}
+
void
Http2Stream::send_request(Http2ConnectionState &cstate)
{
diff --git a/proxy/http2/Http2Stream.h b/proxy/http2/Http2Stream.h
index 924275e..121b91d 100644
--- a/proxy/http2/Http2Stream.h
+++ b/proxy/http2/Http2Stream.h
@@ -149,13 +149,6 @@ public:
return trailing_header;
}
- Http2ErrorCode
- decode_header_blocks(HpackHandle &hpack_handle)
- {
- return http2_decode_header_blocks(&_req_header, (const uint8_t *)header_blocks, header_blocks_length, NULL, hpack_handle,
- trailing_header);
- }
-
void
set_request_headers(HTTPHdr &h2_headers)
{
@@ -176,6 +169,7 @@ public:
return content_length == 0 || content_length == data_length;
}
+ Http2ErrorCode decode_header_blocks(HpackHandle &hpack_handle);
void send_request(Http2ConnectionState &cstate);
VIO *do_io_read(Continuation *c, int64_t nbytes, MIOBuffer *buf);
VIO *do_io_write(Continuation *c, int64_t nbytes, IOBufferReader *abuffer, bool owner = false);
diff --git a/proxy/http2/RegressionHPACK.cc b/proxy/http2/RegressionHPACK.cc
index 09ad109..94fdde3 100644
--- a/proxy/http2/RegressionHPACK.cc
+++ b/proxy/http2/RegressionHPACK.cc
@@ -29,6 +29,7 @@
const static int DYNAMIC_TABLE_SIZE_FOR_REGRESSION_TEST = 256;
const static int BUFSIZE_FOR_REGRESSION_TEST = 128;
const static int MAX_TEST_FIELD_NUM = 8;
+const static int MAX_REQUEST_HEADER_SIZE = 131072;
/***********************************************************************************
* *
@@ -564,7 +565,7 @@ REGRESSION_TEST(HPACK_Decode)(RegressionTest *t, int, int *pstatus)
headers->create(HTTP_TYPE_REQUEST);
hpack_decode_header_block(indexing_table, headers, encoded_field_request_test_case[i].encoded_field,
- encoded_field_request_test_case[i].encoded_field_len);
+ encoded_field_request_test_case[i].encoded_field_len, MAX_REQUEST_HEADER_SIZE);
for (unsigned int j = 0; j < sizeof(raw_field_request_test_case[i]) / sizeof(raw_field_request_test_case[i][0]); j++) {
const char *expected_name = raw_field_request_test_case[i][j].raw_name;
diff --git a/proxy/http2/test_HPACK.cc b/proxy/http2/test_HPACK.cc
index 44efca3..8750d7c 100644
--- a/proxy/http2/test_HPACK.cc
+++ b/proxy/http2/test_HPACK.cc
@@ -32,6 +32,8 @@
#include "ts/ink_args.h"
#include "ts/TestBox.h"
+const static int MAX_REQUEST_HEADER_SIZE = 131072;
+
using namespace std;
AppVersionInfo appVersionInfo;
@@ -195,7 +197,7 @@ test_decoding(const string filename)
case 'w':
parse_line(line, 6, name, value);
unpacked_len = unpack(value, unpacked);
- hpack_decode_header_block(indexing_table, &decoded, unpacked, unpacked_len);
+ hpack_decode_header_block(indexing_table, &decoded, unpacked, unpacked_len, MAX_REQUEST_HEADER_SIZE);
break;
}
break;
@@ -250,7 +252,7 @@ test_encoding(const string filename_in, const string filename_out)
result = seqnum;
break;
}
- hpack_decode_header_block(indexing_table_for_decoding, &decoded, encoded, written);
+ hpack_decode_header_block(indexing_table_for_decoding, &decoded, encoded, written, MAX_REQUEST_HEADER_SIZE);
if (compare_header_fields(&decoded, &original) != 0) {
result = seqnum;
break;
@@ -295,7 +297,7 @@ test_encoding(const string filename_in, const string filename_out)
result = seqnum;
return result;
}
- hpack_decode_header_block(indexing_table_for_decoding, &decoded, encoded, written);
+ hpack_decode_header_block(indexing_table_for_decoding, &decoded, encoded, written, MAX_REQUEST_HEADER_SIZE);
if (compare_header_fields(&decoded, &original) != 0) {
result = seqnum;
return result;
--
To stop receiving notification emails like this one, please contact
"commits@trafficserver.apache.org" <co...@trafficserver.apache.org>.