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 2022/12/12 18:20:25 UTC

[trafficserver] branch 9.1.x updated: Validate request-target (#9100)

This is an automated email from the ASF dual-hosted git repository.

bcall pushed a commit to branch 9.1.x
in repository https://gitbox.apache.org/repos/asf/trafficserver.git


The following commit(s) were added to refs/heads/9.1.x by this push:
     new e7549cbe3 Validate request-target (#9100)
e7549cbe3 is described below

commit e7549cbe3860d3d4ecc0f0e898c2a095bd0f141f
Author: Masakazu Kitajo <ma...@apache.org>
AuthorDate: Wed Sep 21 08:04:47 2022 +0900

    Validate request-target (#9100)
    
    (cherry picked from commit 3b9cbf873a77bb7f9297f2b16496a290e0cf7de1)
---
 proxy/hdrs/HTTP.cc                 | 35 +++++++++++++++++++++++++++++++++++
 proxy/hdrs/HTTP.h                  |  1 +
 proxy/hdrs/unit_tests/test_Hdrs.cc |  4 +++-
 3 files changed, 39 insertions(+), 1 deletion(-)

diff --git a/proxy/hdrs/HTTP.cc b/proxy/hdrs/HTTP.cc
index 73cd16362..f3d4d469a 100644
--- a/proxy/hdrs/HTTP.cc
+++ b/proxy/hdrs/HTTP.cc
@@ -970,6 +970,9 @@ http_parser_parse_req(HTTPParser *parser, HdrHeap *heap, HTTPHdrImpl *hh, const
       ParseResult ret = mime_parser_parse(&parser->m_mime_parser, heap, hh->m_fields_impl, start, end, must_copy_strings, eof,
                                           false, max_hdr_field_size);
       // If we're done with the main parse do some validation
+      if (ret == PARSE_RESULT_DONE) {
+        ret = validate_hdr_request_target(HTTP_WKSIDX_GET, url);
+      }
       if (ret == PARSE_RESULT_DONE) {
         ret = validate_hdr_host(hh); // check HOST header
       }
@@ -1125,6 +1128,9 @@ http_parser_parse_req(HTTPParser *parser, HdrHeap *heap, HTTPHdrImpl *hh, const
   ParseResult ret = mime_parser_parse(&parser->m_mime_parser, heap, hh->m_fields_impl, start, end, must_copy_strings, eof, false,
                                       max_hdr_field_size);
   // If we're done with the main parse do some validation
+  if (ret == PARSE_RESULT_DONE) {
+    ret = validate_hdr_request_target(hh->u.req.m_method_wks_idx, hh->u.req.m_url_impl);
+  }
   if (ret == PARSE_RESULT_DONE) {
     ret = validate_hdr_host(hh); // check HOST header
   }
@@ -1134,6 +1140,35 @@ http_parser_parse_req(HTTPParser *parser, HdrHeap *heap, HTTPHdrImpl *hh, const
   return ret;
 }
 
+ParseResult
+validate_hdr_request_target(int method_wk_idx, URLImpl *url)
+{
+  ParseResult ret  = PARSE_RESULT_DONE;
+  int host_len     = url->m_len_host;
+  int path_len     = url->m_len_path;
+  const char *path = url->m_ptr_path;
+  int scheme_len   = url->m_len_scheme;
+
+  if (host_len == 0) {
+    if (path_len == 1 && path[0] == '*') { // asterisk-form
+      // Skip this check for now because URLImpl can't distinguish '*' and '/*'
+      // if (method_wk_idx != HTTP_WKSIDX_OPTIONS) {
+      //   ret = PARSE_RESULT_ERROR;
+      // }
+    } else { // origin-form
+      // Nothing to check here
+    }
+  } else if (scheme_len == 0 && host_len != 0) { // authority-form
+    if (method_wk_idx != HTTP_WKSIDX_CONNECT) {
+      ret = PARSE_RESULT_ERROR;
+    }
+  } else { // absolute-form
+    // Nothing to check here
+  }
+
+  return ret;
+}
+
 ParseResult
 validate_hdr_host(HTTPHdrImpl *hh)
 {
diff --git a/proxy/hdrs/HTTP.h b/proxy/hdrs/HTTP.h
index 83763c72d..a6738559b 100644
--- a/proxy/hdrs/HTTP.h
+++ b/proxy/hdrs/HTTP.h
@@ -441,6 +441,7 @@ void http_parser_clear(HTTPParser *parser);
 ParseResult http_parser_parse_req(HTTPParser *parser, HdrHeap *heap, HTTPHdrImpl *hh, const char **start, const char *end,
                                   bool must_copy_strings, bool eof, int strict_uri_parsing, size_t max_request_line_size,
                                   size_t max_hdr_field_size);
+ParseResult validate_hdr_request_target(int method_wks_idx, URLImpl *url);
 ParseResult validate_hdr_host(HTTPHdrImpl *hh);
 ParseResult validate_hdr_content_length(HdrHeap *heap, HTTPHdrImpl *hh);
 ParseResult http_parser_parse_resp(HTTPParser *parser, HdrHeap *heap, HTTPHdrImpl *hh, const char **start, const char *end,
diff --git a/proxy/hdrs/unit_tests/test_Hdrs.cc b/proxy/hdrs/unit_tests/test_Hdrs.cc
index e7314fee3..2aad37de2 100644
--- a/proxy/hdrs/unit_tests/test_Hdrs.cc
+++ b/proxy/hdrs/unit_tests/test_Hdrs.cc
@@ -45,7 +45,7 @@ TEST_CASE("HdrTestHttpParse", "[proxy][hdrtest]")
     int expected_result;
     int expected_bytes_consumed;
   };
-  static const std::array<Test, 21> tests = {{
+  static const std::array<Test, 23> tests = {{
     {"GET /index.html HTTP/1.0\r\n", PARSE_RESULT_DONE, 26},
     {"GET /index.html HTTP/1.0\r\n\r\n***BODY****", PARSE_RESULT_DONE, 28},
     {"GET /index.html HTTP/1.0\r\nUser-Agent: foobar\r\n\r\n***BODY****", PARSE_RESULT_DONE, 48},
@@ -66,6 +66,8 @@ TEST_CASE("HdrTestHttpParse", "[proxy][hdrtest]")
     {"GET /index.html HTTP/1.0\r\nUser-Agent: foobar\r\n", PARSE_RESULT_DONE, 46},
     {"GET /index.html HTTP/1.0\r\n", PARSE_RESULT_DONE, 26},
     {"GET /index.html hTTP/1.0\r\n", PARSE_RESULT_ERROR, 26},
+    {"CONNECT foo.example HTTP/1.1\r\n", PARSE_RESULT_DONE, 30},
+    {"GET foo.example HTTP/1.1\r\n", PARSE_RESULT_ERROR, 26},
     {"", PARSE_RESULT_ERROR, 0},
   }};