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

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

commit 7e0ba0658481151fd3e5cb045b3f3d35583ac83c
Author: xinli1 <xin...@linkedin.com>
AuthorDate: Tue Oct 22 10:04:52 2019 -0700

    set host name in TLS extension for SNI Host check in service side with sni 
policy verify_with_name_source.
    
    fix build error in autest
    
    update document
    
    fix wrong comment
    
    (cherry picked from commit 48771056f71f85a3ac6b01f1fa10a7172c4bdc04)
---
 doc/admin-guide/files/records.config.en.rst | 16 +++++++++++++++-
 iocore/net/I_NetVConnection.h               | 23 +++++++++++++++++++++++
 iocore/net/P_UnixNetVConnection.h           |  1 +
 iocore/net/SSLNetVConnection.cc             |  9 +++++----
 iocore/net/quic/QUICTLS_openssl.cc          |  3 ++-
 proxy/http/HttpSM.cc                        | 11 +++++++++++
 6 files changed, 57 insertions(+), 6 deletions(-)

diff --git a/doc/admin-guide/files/records.config.en.rst 
b/doc/admin-guide/files/records.config.en.rst
index d9999df..56a5645 100644
--- a/doc/admin-guide/files/records.config.en.rst
+++ b/doc/admin-guide/files/records.config.en.rst
@@ -3473,7 +3473,21 @@ Client-Related Configuration
 
    Indicate how the SNI value for the TLS connection to the origin is 
selected.  By default it is
    `host` which means the host header field value is used for the SNI.  If 
`remap` is specified, the
-   remapped origin name is used for the SNI value.
+   remapped origin name is used for the SNI value.  If 
`verify_with_name_source` is specified, the 
+   SNI will be the host header value and the name to check in the server 
certificate will be the 
+   remap header value.
+   We have two names that could be used in the transaction host header and the 
SNI value to the 
+   origin. These could be the host header from the client or the remap host 
name. Unless you have 
+   pristine host header enabled, these are likely the same values.
+   If sni_policy = host, both the sni and the host header to origin will be 
the same.
+   If sni_policy = remap, the sni value with be the remap host name and the 
host header will be the 
+   host header from the client.
+   In addition, We may want to set the SNI and host headers the same (makes 
some common web servers 
+   happy), but the certificate served by the origin may have a name that 
corresponds to the remap 
+   name. So instead of using the SNI name for the name check, we may want to 
use the remap name. 
+   So if sni_policy = verify_with_name_source, the sni will be the host header 
value and the name to 
+   check in the server certificate will be the remap header value.
+   
 
 .. ts:cv:: CONFIG proxy.config.ssl.client.TLSv1 INT 0
 
diff --git a/iocore/net/I_NetVConnection.h b/iocore/net/I_NetVConnection.h
index df0667f..bfe1137 100644
--- a/iocore/net/I_NetVConnection.h
+++ b/iocore/net/I_NetVConnection.h
@@ -192,6 +192,10 @@ struct NetVCOptions {
    */
   ats_scoped_str ssl_servername;
 
+  /** Server host name from client's request to use for SNI data on an 
outbound connection.
+   */
+  ats_scoped_str sni_hostname;
+
   /**
    * Client certificate to use in response to OS's certificate request
    */
@@ -259,6 +263,20 @@ struct NetVCOptions {
   }
 
   self &
+  set_sni_hostname(const char *name, size_t len)
+  {
+    IpEndpoint ip;
+
+    // Literal IPv4 and IPv6 addresses are not permitted in 
"HostName".(rfc6066#section-3)
+    if (name && len && ats_ip_pton(std::string_view(name, len), &ip) != 0) {
+      sni_hostname = ats_strndup(name, len);
+    } else {
+      sni_hostname = nullptr;
+    }
+    return *this;
+  }
+
+  self &
   operator=(self const &that)
   {
     if (&that != this) {
@@ -274,6 +292,7 @@ struct NetVCOptions {
        */
       sni_servername = nullptr; // release any current name.
       ssl_servername = nullptr;
+      sni_hostname   = nullptr;
       memcpy(static_cast<void *>(this), &that, sizeof(self));
       if (that.sni_servername) {
         sni_servername.release(); // otherwise we'll free the source string.
@@ -283,6 +302,10 @@ struct NetVCOptions {
         ssl_servername.release(); // otherwise we'll free the source string.
         this->ssl_servername = ats_strdup(that.ssl_servername);
       }
+      if (that.sni_hostname) {
+        sni_hostname.release(); // otherwise we'll free the source string.
+        this->sni_hostname = ats_strdup(that.sni_hostname);
+      }
     }
     return *this;
   }
diff --git a/iocore/net/P_UnixNetVConnection.h 
b/iocore/net/P_UnixNetVConnection.h
index 128f572..26d573d 100644
--- a/iocore/net/P_UnixNetVConnection.h
+++ b/iocore/net/P_UnixNetVConnection.h
@@ -68,6 +68,7 @@ NetVCOptions::reset()
 
   sni_servername              = nullptr;
   ssl_servername              = nullptr;
+  sni_hostname                = nullptr;
   ssl_client_cert_name        = nullptr;
   ssl_client_private_key_name = nullptr;
   ssl_client_ca_cert_name     = nullptr;
diff --git a/iocore/net/SSLNetVConnection.cc b/iocore/net/SSLNetVConnection.cc
index d5771f5..051c97a 100644
--- a/iocore/net/SSLNetVConnection.cc
+++ b/iocore/net/SSLNetVConnection.cc
@@ -1078,11 +1078,12 @@ SSLNetVConnection::sslStartHandShake(int event, int 
&err)
 
       SSL_set_verify(this->ssl, SSL_VERIFY_PEER, verify_callback);
 
-      if (this->options.sni_servername) {
-        if (SSL_set_tlsext_host_name(this->ssl, this->options.sni_servername)) 
{
-          Debug("ssl", "using SNI name '%s' for client handshake", 
this->options.sni_servername.get());
+      ats_scoped_str &tlsext_host_name = this->options.sni_hostname ? 
this->options.sni_hostname : this->options.sni_servername;
+      if (tlsext_host_name) {
+        if (SSL_set_tlsext_host_name(this->ssl, tlsext_host_name)) {
+          Debug("ssl", "using SNI name '%s' for client handshake", 
tlsext_host_name.get());
         } else {
-          Debug("ssl.error", "failed to set SNI name '%s' for client 
handshake", this->options.sni_servername.get());
+          Debug("ssl.error", "failed to set SNI name '%s' for client 
handshake", tlsext_host_name.get());
           SSL_INCREMENT_DYN_STAT(ssl_sni_name_set_failure);
         }
       }
diff --git a/iocore/net/quic/QUICTLS_openssl.cc 
b/iocore/net/quic/QUICTLS_openssl.cc
index 0eabec1..75e9842 100644
--- a/iocore/net/quic/QUICTLS_openssl.cc
+++ b/iocore/net/quic/QUICTLS_openssl.cc
@@ -405,7 +405,8 @@ QUICTLS::QUICTLS(QUICPacketProtectionKeyInfo &pp_key_info, 
SSL_CTX *ssl_ctx, Net
 
     SSL_set_alpn_protos(this->_ssl, reinterpret_cast<const unsigned char 
*>(netvc_options.alpn_protos.data()),
                         netvc_options.alpn_protos.size());
-    SSL_set_tlsext_host_name(this->_ssl, netvc_options.sni_servername.get());
+    const ats_scoped_str &tlsext_host_name = netvc_options.sni_hostname ? 
netvc_options.sni_hostname : netvc_options.sni_servername;
+    SSL_set_tlsext_host_name(this->_ssl, tlsext_host_name.get());
   } else {
     SSL_set_accept_state(this->_ssl);
   }
diff --git a/proxy/http/HttpSM.cc b/proxy/http/HttpSM.cc
index 45d3e5b..2450d2b 100644
--- a/proxy/http/HttpSM.cc
+++ b/proxy/http/HttpSM.cc
@@ -5007,6 +5007,17 @@ HttpSM::do_http_server_open(bool raw)
     if (t_state.txn_conf->ssl_client_sni_policy != nullptr && 
!strcmp(t_state.txn_conf->ssl_client_sni_policy, "remap")) {
       len = strlen(t_state.server_info.name);
       opt.set_sni_servername(t_state.server_info.name, len);
+    } else if (t_state.txn_conf->ssl_client_sni_policy != nullptr &&
+               !strcmp(t_state.txn_conf->ssl_client_sni_policy, 
"verify_with_name_source")) {
+      // the same with "remap" policy to set sni_servername
+      len = strlen(t_state.server_info.name);
+      opt.set_sni_servername(t_state.server_info.name, len);
+
+      // also set sni_hostname with host header from server request in this 
policy
+      const char *host = t_state.hdr_info.server_request.host_get(&len);
+      if (host && len > 0) {
+        opt.set_sni_hostname(host, len);
+      }
     } else { // Do the default of host header for SNI
       const char *host = t_state.hdr_info.server_request.host_get(&len);
       if (host && len > 0) {

Reply via email to