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);
 

Reply via email to