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 2015/11/14 22:03:02 UTC
trafficserver git commit: TS-4019: Validate header names and values
before passing to FetchSM
Repository: trafficserver
Updated Branches:
refs/heads/master 7dbb358c9 -> fe2de1a3d
TS-4019: Validate header names and values before passing to FetchSM
This closes #334
Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo
Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/fe2de1a3
Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/fe2de1a3
Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/fe2de1a3
Branch: refs/heads/master
Commit: fe2de1a3d552c09409bfc328a2dfe6a4f1691930
Parents: 7dbb358
Author: Masakazu Kitajo <mk...@yahoo-corp.jp>
Authored: Sat Nov 14 13:02:33 2015 -0800
Committer: Bryan Call <bc...@apache.org>
Committed: Sat Nov 14 13:02:33 2015 -0800
----------------------------------------------------------------------
proxy/hdrs/MIME.h | 37 ++++++++++++++++++++++++++++++++
proxy/http2/HTTP2.cc | 16 ++++++++++----
proxy/http2/Http2ConnectionState.cc | 4 +++-
proxy/http2/Http2Stream.cc | 7 ++++--
proxy/http2/Http2Stream.h | 2 +-
5 files changed, 58 insertions(+), 8 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/fe2de1a3/proxy/hdrs/MIME.h
----------------------------------------------------------------------
diff --git a/proxy/hdrs/MIME.h b/proxy/hdrs/MIME.h
index 903bfc3..f882df1 100644
--- a/proxy/hdrs/MIME.h
+++ b/proxy/hdrs/MIME.h
@@ -29,6 +29,7 @@
#include "ts/ink_assert.h"
#include "ts/ink_apidefs.h"
#include "ts/ink_string++.h"
+#include "ts/ParseRules.h"
#include "HdrHeap.h"
#include "HdrToken.h"
@@ -164,6 +165,7 @@ struct MIMEField {
int value_get_comma_list(StrList *list) const;
void name_set(HdrHeap *heap, MIMEHdrImpl *mh, const char *name, int length);
+ bool name_is_valid() const;
void value_set(HdrHeap *heap, MIMEHdrImpl *mh, const char *value, int length);
void value_set_int(HdrHeap *heap, MIMEHdrImpl *mh, int32_t value);
@@ -175,6 +177,7 @@ struct MIMEField {
// Other separators (e.g. ';' in Set-cookie/Cookie) are also possible
void value_append(HdrHeap *heap, MIMEHdrImpl *mh, const char *value, int length, bool prepend_comma = false,
const char separator = ',');
+ bool value_is_valid() const;
int has_dups() const;
};
@@ -765,6 +768,23 @@ MIMEField::name_set(HdrHeap *heap, MIMEHdrImpl *mh, const char *name, int length
/*-------------------------------------------------------------------------
-------------------------------------------------------------------------*/
+inline bool
+MIMEField::name_is_valid() const
+{
+ const char *name;
+ int length;
+
+ for (name = name_get(&length); length > 0; length--) {
+ if (ParseRules::is_control(name[length - 1])) {
+ return false;
+ }
+ }
+ return true;
+}
+
+/*-------------------------------------------------------------------------
+ -------------------------------------------------------------------------*/
+
inline const char *
MIMEField::value_get(int *length) const
{
@@ -852,6 +872,23 @@ MIMEField::value_append(HdrHeap *heap, MIMEHdrImpl *mh, const char *value, int l
mime_field_value_append(heap, mh, this, value, length, prepend_comma, separator);
}
+/*-------------------------------------------------------------------------
+ -------------------------------------------------------------------------*/
+
+inline bool
+MIMEField::value_is_valid() const
+{
+ const char *value;
+ int length;
+
+ for (value = value_get(&length); length > 0; length--) {
+ if (ParseRules::is_control(value[length - 1])) {
+ return false;
+ }
+ }
+ return true;
+}
+
inline int
MIMEField::has_dups() const
{
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/fe2de1a3/proxy/http2/HTTP2.cc
----------------------------------------------------------------------
diff --git a/proxy/http2/HTTP2.cc b/proxy/http2/HTTP2.cc
index 16a72fa..7789e90 100644
--- a/proxy/http2/HTTP2.cc
+++ b/proxy/http2/HTTP2.cc
@@ -405,19 +405,19 @@ convert_from_2_to_1_1_header(HTTPHdr *headers)
int scheme_len, authority_len, path_len, method_len;
// Get values of :scheme, :authority and :path to assemble requested URL
- if ((field = headers->field_find(HPACK_VALUE_SCHEME, HPACK_LEN_SCHEME)) != NULL) {
+ if ((field = headers->field_find(HPACK_VALUE_SCHEME, HPACK_LEN_SCHEME)) != NULL && field->value_is_valid()) {
scheme = field->value_get(&scheme_len);
} else {
return PARSE_ERROR;
}
- if ((field = headers->field_find(HPACK_VALUE_AUTHORITY, HPACK_LEN_AUTHORITY)) != NULL) {
+ if ((field = headers->field_find(HPACK_VALUE_AUTHORITY, HPACK_LEN_AUTHORITY)) != NULL && field->value_is_valid()) {
authority = field->value_get(&authority_len);
} else {
return PARSE_ERROR;
}
- if ((field = headers->field_find(HPACK_VALUE_PATH, HPACK_LEN_PATH)) != NULL) {
+ if ((field = headers->field_find(HPACK_VALUE_PATH, HPACK_LEN_PATH)) != NULL && field->value_is_valid()) {
path = field->value_get(&path_len);
} else {
return PARSE_ERROR;
@@ -437,7 +437,7 @@ convert_from_2_to_1_1_header(HTTPHdr *headers)
arena.str_free(url);
// Get value of :method
- if ((field = headers->field_find(HPACK_VALUE_METHOD, HPACK_LEN_METHOD)) != NULL) {
+ if ((field = headers->field_find(HPACK_VALUE_METHOD, HPACK_LEN_METHOD)) != NULL && field->value_is_valid()) {
method = field->value_get(&method_len);
int method_wks_idx = hdrtoken_tokenize(method, method_len);
@@ -476,6 +476,14 @@ convert_from_2_to_1_1_header(HTTPHdr *headers)
headers->field_delete(HPACK_VALUE_STATUS, HPACK_LEN_STATUS);
}
+ // Check validity of all names and values
+ MIMEFieldIter iter;
+ for (const MIMEField *field = headers->iter_get_first(&iter); field != NULL; field = headers->iter_get_next(&iter)) {
+ if (!field->name_is_valid() || !field->value_is_valid()) {
+ return PARSE_ERROR;
+ }
+ }
+
return PARSE_DONE;
}
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/fe2de1a3/proxy/http2/Http2ConnectionState.cc
----------------------------------------------------------------------
diff --git a/proxy/http2/Http2ConnectionState.cc b/proxy/http2/Http2ConnectionState.cc
index 39d21f6..0f950e7 100644
--- a/proxy/http2/Http2ConnectionState.cc
+++ b/proxy/http2/Http2ConnectionState.cc
@@ -259,7 +259,9 @@ rcv_headers_frame(Http2ClientSession &cs, Http2ConnectionState &cstate, const Ht
return Http2Error(HTTP2_ERROR_CLASS_STREAM, HTTP2_ERROR_PROTOCOL_ERROR);
}
- stream->init_fetcher(cstate);
+ if (!stream->init_fetcher(cstate)) {
+ return Http2Error(HTTP2_ERROR_CLASS_STREAM, HTTP2_ERROR_PROTOCOL_ERROR);
+ }
} else {
// NOTE: Expect CONTINUATION Frame. Do NOT change state of stream or decode
// Header Blocks.
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/fe2de1a3/proxy/http2/Http2Stream.cc
----------------------------------------------------------------------
diff --git a/proxy/http2/Http2Stream.cc b/proxy/http2/Http2Stream.cc
index 2ea7020..30c175f 100644
--- a/proxy/http2/Http2Stream.cc
+++ b/proxy/http2/Http2Stream.cc
@@ -28,13 +28,15 @@
// Currently use only HTTP/1.1 for requesting to origin server
const static char *HTTP2_FETCHING_HTTP_VERSION = "HTTP/1.1";
-void
+bool
Http2Stream::init_fetcher(Http2ConnectionState &cstate)
{
extern ClassAllocator<FetchSM> FetchSMAllocator;
// Convert header to HTTP/1.1 format
- convert_from_2_to_1_1_header(&_req_header);
+ if (convert_from_2_to_1_1_header(&_req_header) == PARSE_ERROR) {
+ return false;
+ }
// Get null-terminated URL and method
Arena arena;
@@ -61,6 +63,7 @@ Http2Stream::init_fetcher(Http2ConnectionState &cstate)
_fetch_sm->ext_set_user_data(this);
_fetch_sm->ext_launch();
+ return true;
}
void
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/fe2de1a3/proxy/http2/Http2Stream.h
----------------------------------------------------------------------
diff --git a/proxy/http2/Http2Stream.h b/proxy/http2/Http2Stream.h
index f47f096..c96c434 100644
--- a/proxy/http2/Http2Stream.h
+++ b/proxy/http2/Http2Stream.h
@@ -61,7 +61,7 @@ public:
}
// Operate FetchSM
- void init_fetcher(Http2ConnectionState &cstate);
+ bool init_fetcher(Http2ConnectionState &cstate);
void set_body_to_fetcher(const void *data, size_t len);
FetchSM *
get_fetcher()