You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by zw...@apache.org on 2022/12/14 23:27:50 UTC

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

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

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


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

commit 6fb210ff76f5ea746e74375f1880dac830fedfa1
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                 | 37 +++++++++++++++++++++++++++++++++++++
 proxy/hdrs/HTTP.h                  |  1 +
 proxy/hdrs/unit_tests/test_Hdrs.cc |  4 +++-
 3 files changed, 41 insertions(+), 1 deletion(-)

diff --git a/proxy/hdrs/HTTP.cc b/proxy/hdrs/HTTP.cc
index 4e17d542f..ccaf8ca42 100644
--- a/proxy/hdrs/HTTP.cc
+++ b/proxy/hdrs/HTTP.cc
@@ -974,6 +974,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
       }
@@ -1129,6 +1132,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
   }
@@ -1138,6 +1144,37 @@ 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->get_host(&host_len);
+  int path_len;
+  const char *path = url->get_path(&path_len);
+  int scheme_len;
+  url->get_scheme(&scheme_len);
+
+  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 6d01fb2e1..710fbaf00 100644
--- a/proxy/hdrs/HTTP.h
+++ b/proxy/hdrs/HTTP.h
@@ -445,6 +445,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 73022bf62..30b9b198e 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},
   }};