[PATCH] Add back validatation that the scheme matches the wire protocol (#9007)
authorBrian Neradt <brian.neradt@gmail.com>
Tue, 9 Aug 2022 03:18:49 +0000 (22:18 -0500)
committerAbhijith PA <abhijith@debian.org>
Sat, 29 Oct 2022 12:33:47 +0000 (13:33 +0100)
This adds back in the scheme and wire protocol check (see #8465) along
with a configuration to be able to disable the check if the verification
is not desired.

Gbp-Pq: Name CVE-2021-37150.patch

doc/admin-guide/files/records.config.en.rst
mgmt/RecordsConfig.cc
proxy/http/HttpConfig.cc
proxy/http/HttpConfig.h
proxy/http/HttpSM.cc

index b799c24f9a98ff5e0a8bc6e4ec5da3cd8fd97e25..6398f5461cd7ad9acc9dbba83ccd8567f1dd99c6 100644 (file)
@@ -3413,6 +3413,29 @@ Client-Related Configuration
 
    Enables (``1``) or disables (``0``) TLSv1_1 in the ATS client context. If not specified, enabled by default
 
+.. ts:cv:: CONFIG proxy.config.ssl.client.scheme_proto_mismatch_policy INT 2
+   :overridable:
+
+   This option controls how |TS| behaves when the client side connection
+   protocol and the client request's scheme do not match. For example, if
+   enforcement is enabled by setting this value to ``2`` and the client
+   connection is a cleartext HTTP connection but the scheme of the URL is
+   ``https://``, then |TS| will emit a warning and return an immediate 400 HTTP
+   response without proxying the request to the origin.
+
+   The default value is ``2``, meaning that |TS| will enforce that the protocol
+   matches the scheme.
+
+   ===== ======================================================================
+   Value Description
+   ===== ======================================================================
+   ``0`` Disable verification that the protocol and scheme match.
+   ``1`` Check that the protocol and scheme match, but only emit a warning if
+         they do not.
+   ``2`` Check that the protocol and scheme match and, if they do not, emit a
+         warning and return an immediate HTTP 400 response.
+   ===== ======================================================================
+
 .. ts:cv:: CONFIG proxy.config.ssl.client.TLSv1_2 INT 1
 
    Enables (``1``) or disables (``0``) TLSv1_2 in the ATS client context. If not specified, enabled by default
index d96029678817c6dcf2d3b02ba9176415c6ed0720..084649deab3703813d30cbf18514ed3383220341 100644 (file)
@@ -1137,6 +1137,8 @@ static const RecordElement RecordsConfig[] =
   ,
   {RECT_CONFIG, "proxy.config.ssl.client.CA.cert.path", RECD_STRING, TS_BUILD_SYSCONFDIR, RECU_RESTART_TS, RR_NULL, RECC_NULL, nullptr, RECA_NULL}
   ,
+  {RECT_CONFIG, "proxy.config.ssl.client.scheme_proto_mismatch_policy", RECD_INT, "2", RECU_DYNAMIC, RR_NULL, RECC_NULL, nullptr, RECA_NULL}
+  ,
   {RECT_CONFIG, "proxy.config.ssl.session_cache", RECD_INT, "2", RECU_RESTART_TS, RR_NULL, RECC_NULL, nullptr, RECA_NULL}
   ,
   {RECT_CONFIG, "proxy.config.ssl.session_cache.size", RECD_INT, "102400", RECU_RESTART_TS, RR_NULL, RECC_NULL, nullptr, RECA_NULL}
index 9b98bba52c04038bfb7c77615cc72ab4aa2c528b..03de8af0803023b4eeb604a7fd52f858df849252 100644 (file)
@@ -1225,7 +1225,7 @@ HttpConfig::startup()
   HttpEstablishStaticConfigByte(c.redirection_host_no_port, "proxy.config.http.redirect_host_no_port");
   HttpEstablishStaticConfigLongLong(c.oride.number_of_redirections, "proxy.config.http.number_of_redirections");
   HttpEstablishStaticConfigLongLong(c.post_copy_size, "proxy.config.http.post_copy_size");
-
+  HttpEstablishStaticConfigByte(c.scheme_proto_mismatch_policy, "proxy.config.ssl.client.scheme_proto_mismatch_policy");
   http_config_cont->handleEvent(EVENT_NONE, nullptr);
 
   return;
@@ -1492,6 +1492,8 @@ HttpConfig::reconfigure()
   params->oride.client_cert_filename        = ats_strdup(m_master.oride.client_cert_filename);
   params->oride.client_cert_filepath        = ats_strdup(m_master.oride.client_cert_filepath);
 
+  params->scheme_proto_mismatch_policy = m_master.scheme_proto_mismatch_policy;
+
   params->negative_caching_list = m_master.negative_caching_list;
 
   m_id = configProcessor.set(m_id, params);
index 5b395a360c60de7bc50fa34c54a5137fb851e416..2c7c648a61fd55dba43d0a54926c5f99f79e7c8d 100644 (file)
@@ -873,6 +873,7 @@ public:
 
   MgmtInt body_factory_response_max_size = 8192;
 
+  MgmtByte scheme_proto_mismatch_policy = 2;
   // noncopyable
   /////////////////////////////////////
   // operator = and copy constructor //
index 9435cb1a532fa98eb2c348316a3c5691b2bb73f3..a4492fea6d576af9c64d195daf11f95dc5ab32d6 100644 (file)
@@ -727,17 +727,20 @@ HttpSM::state_read_client_request_header(int event, void *data)
   case PARSE_RESULT_DONE:
     SMDebug("http", "[%" PRId64 "] done parsing client request header", sm_id);
 
-    if (!is_internal) {
+        if (!is_internal && t_state.http_config_param->scheme_proto_mismatch_policy != 0) {
       auto scheme = t_state.hdr_info.client_request.url_get()->scheme_get_wksidx();
       if ((client_connection_is_ssl && (scheme == URL_WKSIDX_HTTP || scheme == URL_WKSIDX_WS)) ||
           (!client_connection_is_ssl && (scheme == URL_WKSIDX_HTTPS || scheme == URL_WKSIDX_WSS))) {
-        SMDebug("http", "scheme [%s] vs. protocol [%s] mismatch", hdrtoken_index_to_wks(scheme),
+        Warning("scheme [%s] vs. protocol [%s] mismatch", hdrtoken_index_to_wks(scheme),
                 client_connection_is_ssl ? "tls" : "plaintext");
-        t_state.http_return_code = HTTP_STATUS_BAD_REQUEST;
-        call_transact_and_set_next_state(HttpTransact::BadRequest);
-        break;
+        if (t_state.http_config_param->scheme_proto_mismatch_policy == 2) {
+          t_state.http_return_code = HTTP_STATUS_BAD_REQUEST;
+          call_transact_and_set_next_state(HttpTransact::BadRequest);
+          break;
+        }
       }
     }
+
     ua_txn->set_session_active();
 
     if (t_state.hdr_info.client_request.version_get() == HTTPVersion(1, 1) &&