This is an automated email from the ASF dual-hosted git repository.
sorber pushed a commit to branch 6.2.x
in repository https://gitbox.apache.org/repos/asf/trafficserver.git
The following commit(s) were added to refs/heads/6.2.x by this push:
new 5a55d02 Respond with 400 code when Content-Length headers mismatch,
remove duplicate copies of the Content-Length header with exactly same values,
and remove Content-Length headers if Transfer-Encoding header exists.
5a55d02 is described below
commit 5a55d02ca87789046b04ee90335e0aa0b4636307
Author: Bryan Call <[email protected]>
AuthorDate: Mon Mar 5 16:21:18 2018 -0800
Respond with 400 code when Content-Length headers mismatch, remove
duplicate copies of the Content-Length header with exactly same values,
and remove Content-Length headers if Transfer-Encoding header exists.
(cherry picked from commit 44af6e5ba6d323354da0dd00f35aa7920d477805)
Conflicts:
proxy/hdrs/HTTP.cc
proxy/hdrs/HTTP.h
tests/gold_tests/headers/syntax.test.py
---
proxy/hdrs/HTTP.cc | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++----
proxy/hdrs/HTTP.h | 1 +
2 files changed, 63 insertions(+), 4 deletions(-)
diff --git a/proxy/hdrs/HTTP.cc b/proxy/hdrs/HTTP.cc
index 2968b8b..f520836 100644
--- a/proxy/hdrs/HTTP.cc
+++ b/proxy/hdrs/HTTP.cc
@@ -950,8 +950,13 @@ http_parser_parse_req(HTTPParser *parser, HdrHeap *heap,
HTTPHdrImpl *hh, const
return PARSE_ERROR;
MIMEParseResult ret = mime_parser_parse(&parser->m_mime_parser, heap,
hh->m_fields_impl, start, end, must_copy_strings, eof);
- if (ret == PARSE_DONE)
- ret = validate_hdr_host(hh); // if we're done with the main parse,
check HOST.
+ // If we're done with the main parse do some validation
+ if (ret == PARSE_DONE) {
+ ret = validate_hdr_host(hh); // check HOST header
+ }
+ if (ret == PARSE_DONE) {
+ ret = validate_hdr_content_length(heap, hh);
+ }
return ret;
}
#endif
@@ -1095,8 +1100,13 @@ http_parser_parse_req(HTTPParser *parser, HdrHeap *heap,
HTTPHdrImpl *hh, const
parser->m_parsing_http = false;
MIMEParseResult ret = mime_parser_parse(&parser->m_mime_parser, heap,
hh->m_fields_impl, start, end, must_copy_strings, eof);
- if (ret == PARSE_DONE)
- ret = validate_hdr_host(hh); // if we're done with the main parse, check
HOST.
+ // If we're done with the main parse do some validation
+ if (ret == PARSE_DONE) {
+ ret = validate_hdr_host(hh); // check HOST header
+ }
+ if (ret == PARSE_DONE) {
+ ret = validate_hdr_content_length(heap, hh);
+ }
return ret;
}
@@ -1138,6 +1148,54 @@ validate_hdr_host(HTTPHdrImpl *hh)
return ret;
}
+MIMEParseResult
+validate_hdr_content_length(HdrHeap *heap, HTTPHdrImpl *hh)
+{
+ MIMEField *content_length_field = mime_hdr_field_find(hh->m_fields_impl,
MIME_FIELD_CONTENT_LENGTH, MIME_LEN_CONTENT_LENGTH);
+
+ if (content_length_field) {
+ // RFC 7230 section 3.3.3:
+ // If a message is received with both a Transfer-Encoding and a
+ // Content-Length header field, the Transfer-Encoding overrides
+ // the Content-Length
+ if (mime_hdr_field_find(hh->m_fields_impl, MIME_FIELD_TRANSFER_ENCODING,
MIME_LEN_TRANSFER_ENCODING) != nullptr) {
+ // Delete all Content-Length headers
+ Debug("http", "Transfer-Encoding header and Content-Length headers the
request, removing all Content-Length headers");
+ mime_hdr_field_delete(heap, hh->m_fields_impl, content_length_field);
+ return PARSE_DONE;
+ }
+
+ // RFC 7230 section 3.3.3:
+ // If a message is received without Transfer-Encoding and with
+ // either multiple Content-Length header fields having differing
+ // field-values or a single Content-Length header field having an
+ // invalid value, then the message framing is invalid and the
+ // recipient MUST treat it as an unrecoverable error. If this is a
+ // request message, the server MUST respond with a 400 (Bad Request)
+ // status code and then close the connection
+ int content_length_len = 0;
+ const char *content_length_val =
content_length_field->value_get(&content_length_len);
+
+ while (content_length_field->has_dups()) {
+ int content_length_len_2 = 0;
+ const char *content_length_val_2 =
content_length_field->m_next_dup->value_get(&content_length_len_2);
+
+ if ((content_length_len != content_length_len_2) ||
+ (memcmp(content_length_val, content_length_val_2,
content_length_len) != 0)) {
+ // Values are different, parse error
+ Debug("http", "Content-Length headers don't match, returning parse
error");
+ return PARSE_ERROR;
+ } else {
+ // Delete the duplicate since it has the same value
+ Debug("http", "Deleting duplicate Content-Length header");
+ mime_hdr_field_delete(heap, hh->m_fields_impl,
content_length_field->m_next_dup, false);
+ }
+ }
+ }
+
+ return PARSE_DONE;
+}
+
/*-------------------------------------------------------------------------
-------------------------------------------------------------------------*/
diff --git a/proxy/hdrs/HTTP.h b/proxy/hdrs/HTTP.h
index c230743..6e75c04 100644
--- a/proxy/hdrs/HTTP.h
+++ b/proxy/hdrs/HTTP.h
@@ -443,6 +443,7 @@ void http_parser_clear(HTTPParser *parser);
MIMEParseResult http_parser_parse_req(HTTPParser *parser, HdrHeap *heap,
HTTPHdrImpl *hh, const char **start, const char *end,
bool must_copy_strings, bool eof);
MIMEParseResult validate_hdr_host(HTTPHdrImpl *hh);
+MIMEParseResult validate_hdr_content_length(HdrHeap *heap, HTTPHdrImpl *hh);
MIMEParseResult http_parser_parse_resp(HTTPParser *parser, HdrHeap *heap,
HTTPHdrImpl *hh, const char **start, const char *end,
bool must_copy_strings, bool eof);