]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
vtls: pass on the right SNI name
authorDaniel Stenberg <daniel@haxx.se>
Sat, 22 Jan 2022 22:44:00 +0000 (23:44 +0100)
committerDaniel Stenberg <daniel@haxx.se>
Thu, 27 Jan 2022 07:36:10 +0000 (08:36 +0100)
The TLS backends convert the host name to SNI name and need to use that.
This involves cutting off any trailing dot and lowercasing.

Co-authored-by: Jay Satiro
Closes #8320

13 files changed:
lib/vtls/bearssl.c
lib/vtls/gskit.c
lib/vtls/gtls.c
lib/vtls/mbedtls.c
lib/vtls/nss.c
lib/vtls/openssl.c
lib/vtls/rustls.c
lib/vtls/schannel.c
lib/vtls/schannel.h
lib/vtls/sectransp.c
lib/vtls/vtls.c
lib/vtls/vtls.h
lib/vtls/wolfssl.c

index 9b772d064d75848f8f56e0821d3d33e61eb5e92b..bac6b39314d643eb4f7f355ed2d74c858a0a7055 100644 (file)
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 2019 - 2021, Michael Forney, <mforney@mforney.org>
+ * Copyright (C) 2019 - 2022, Michael Forney, <mforney@mforney.org>
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -465,6 +465,14 @@ static CURLcode bearssl_connect_step1(struct Curl_easy *data,
     }
     hostname = NULL;
   }
+  else {
+    char *snihost = Curl_ssl_snihost(data, hostname, NULL);
+    if(!snihost) {
+      failf(data, "Failed to set SNI");
+      return CURLE_SSL_CONNECT_ERROR;
+    }
+    hostname = snihost;
+  }
 
   if(!br_ssl_client_reset(&backend->ctx, hostname, 0))
     return CURLE_FAILED_INIT;
index e451f6aebebbf22e4f95a6ac981ed51ab66b3b51..223ca611014f4fc2524e71fbd083515854243806 100644 (file)
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -830,8 +830,13 @@ static CURLcode gskit_connect_step1(struct Curl_easy *data,
 
   /* Process SNI. Ignore if not supported (on OS400 < V7R1). */
   if(sni) {
+    char *snihost = Curl_ssl_snihost(data, sni, NULL);
+    if(!snihost) {
+      failf(data, "Failed to set SNI");
+      return CURLE_SSL_CONNECT_ERROR;
+    }
     result = set_buffer(data, BACKEND->handle,
-                        GSK_SSL_EXTN_SERVERNAME_REQUEST, sni, TRUE);
+                        GSK_SSL_EXTN_SERVERNAME_REQUEST, snihost, TRUE);
     if(result == CURLE_UNSUPPORTED_PROTOCOL)
       result = CURLE_OK;
   }
index 18864aa4b285566a4fee3db9034b239ad27edbb8..f9ef4d12b484449ed20a9d429f68802bb9ec79b2 100644 (file)
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -542,11 +542,15 @@ gtls_connect_step1(struct Curl_easy *data,
 #ifdef ENABLE_IPV6
      (0 == Curl_inet_pton(AF_INET6, hostname, &addr)) &&
 #endif
-     sni &&
-     (gnutls_server_name_set(session, GNUTLS_NAME_DNS, hostname,
-                             strlen(hostname)) < 0))
-    infof(data, "WARNING: failed to configure server name indication (SNI) "
-          "TLS extension");
+     sni) {
+    size_t snilen;
+    char *snihost = Curl_ssl_snihost(data, hostname, &snilen);
+    if(!snihost || gnutls_server_name_set(session, GNUTLS_NAME_DNS, snihost,
+                                          snilen) < 0) {
+      failf(data, "Failed to set SNI");
+      return CURLE_SSL_CONNECT_ERROR;
+    }
+  }
 
   /* Use default priorities */
   rc = gnutls_set_default_priority(session);
index 4dd7efa2b2c361ff9d80a4205318009bce2e104b..dc08032dd4d77784035e09fcfa1b68d98abc5d2d 100644 (file)
@@ -561,12 +561,15 @@ mbed_connect_step1(struct Curl_easy *data, struct connectdata *conn,
     mbedtls_ssl_conf_own_cert(&backend->config,
                               &backend->clicert, &backend->pk);
   }
-  if(mbedtls_ssl_set_hostname(&backend->ssl, hostname)) {
-    /* mbedtls_ssl_set_hostname() sets the name to use in CN/SAN checks *and*
-       the name to set in the SNI extension. So even if curl connects to a
-       host specified as an IP address, this function must be used. */
-    failf(data, "couldn't set hostname in mbedTLS");
-    return CURLE_SSL_CONNECT_ERROR;
+  {
+    char *snihost = Curl_ssl_snihost(data, hostname, NULL);
+    if(!snihost || mbedtls_ssl_set_hostname(&backend->ssl, snihost)) {
+      /* mbedtls_ssl_set_hostname() sets the name to use in CN/SAN checks and
+         the name to set in the SNI extension. So even if curl connects to a
+         host specified as an IP address, this function must be used. */
+      failf(data, "Failed to set SNI");
+      return CURLE_SSL_CONNECT_ERROR;
+    }
   }
 
 #ifdef HAS_ALPN
index 2b44f0512658c37c0c108f77347531f92fdebbe2..9e301437b6f6ce3b18fdbb31b644faa988e583ef 100644 (file)
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -1865,7 +1865,6 @@ static CURLcode nss_setup_connect(struct Curl_easy *data,
   CURLcode result;
   bool second_layer = FALSE;
   SSLVersionRange sslver_supported;
-
   SSLVersionRange sslver = {
     SSL_LIBRARY_VERSION_TLS_1_0,  /* min */
 #ifdef SSL_LIBRARY_VERSION_TLS_1_3
@@ -1878,6 +1877,11 @@ static CURLcode nss_setup_connect(struct Curl_easy *data,
     SSL_LIBRARY_VERSION_TLS_1_0
 #endif
   };
+  char *snihost = Curl_ssl_snihost(data, SSL_HOST_NAME(), NULL);
+  if(!snihost) {
+    failf(data, "Failed to set SNI");
+    return CURLE_SSL_CONNECT_ERROR;
+  }
 
   backend->data = data;
 
@@ -2140,11 +2144,11 @@ static CURLcode nss_setup_connect(struct Curl_easy *data,
     goto error;
 
   /* propagate hostname to the TLS layer */
-  if(SSL_SetURL(backend->handle, SSL_HOST_NAME()) != SECSuccess)
+  if(SSL_SetURL(backend->handle, snihost) != SECSuccess)
     goto error;
 
   /* prevent NSS from re-using the session for a different hostname */
-  if(SSL_SetSockPeerID(backend->handle, SSL_HOST_NAME()) != SECSuccess)
+  if(SSL_SetSockPeerID(backend->handle, snihost) != SECSuccess)
     goto error;
 
   return CURLE_OK;
index 5e8a657165ad5877f998cc8350ee146c920dd694..d6f814bc80a9d9572ea340848e01263b7cd3bc83 100644 (file)
@@ -3244,21 +3244,11 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data,
      (0 == Curl_inet_pton(AF_INET6, hostname, &addr)) &&
 #endif
      sni) {
-    size_t nlen = strlen(hostname);
-    if((long)nlen >= data->set.buffer_size)
-      /* this is seriously messed up */
+    char *snihost = Curl_ssl_snihost(data, hostname, NULL);
+    if(!snihost || !SSL_set_tlsext_host_name(backend->handle, snihost)) {
+      failf(data, "Failed set SNI");
       return CURLE_SSL_CONNECT_ERROR;
-
-    /* RFC 6066 section 3 says the SNI field is case insensitive, but browsers
-       send the data lowercase and subsequently there are now numerous servers
-       out there that don't work unless the name is lowercased */
-    Curl_strntolower(data->state.buffer, hostname, nlen);
-    data->state.buffer[nlen] = 0;
-    DEBUGASSERT(nlen);
-    DEBUGASSERT(data->state.buffer[nlen-1] != '.');
-    if(!SSL_set_tlsext_host_name(backend->handle, data->state.buffer))
-      infof(data, "WARNING: failed to configure server name indication (SNI) "
-            "TLS extension");
+    }
   }
 #endif
 
index 51230b196705aa9df3a9142ce5553310ad23fdb9..1c4cb19104dfe59e5e1c66af0c4f963d26882f8b 100644 (file)
@@ -368,7 +368,14 @@ cr_init_backend(struct Curl_easy *data, struct connectdata *conn,
 
   backend->config = rustls_client_config_builder_build(config_builder);
   DEBUGASSERT(rconn == NULL);
-  result = rustls_client_connection_new(backend->config, hostname, &rconn);
+  {
+    char *snihost = Curl_ssl_snihost(data, hostname, NULL);
+    if(!snihost) {
+      failf(data, "Failed to set SNI");
+      return CURLE_SSL_CONNECT_ERROR;
+    }
+    result = rustls_client_connection_new(backend->config, snihost, &rconn);
+  }
   if(result != RUSTLS_RESULT_OK) {
     rustls_error(result, errorbuf, sizeof(errorbuf), &errorlen);
     failf(data, "rustls_client_connection_new: %.*s", errorlen, errorbuf);
index 0a8e60610d8f88d16b5fd5a91884ae034cb16909..983ed540d42062605cde9ffe67d7377c58de0174 100644 (file)
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 2012 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2012 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
  * Copyright (C) 2012 - 2016, Marc Hoersken, <info@marc-hoersken.de>
  * Copyright (C) 2012, Mark Salisbury, <mark.salisbury@hp.com>
  *
@@ -765,7 +765,6 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn,
 #ifdef ENABLE_IPV6
   struct in6_addr addr6;
 #endif
-  TCHAR *host_name;
   CURLcode result;
   char * const hostname = SSL_HOST_NAME();
   struct ssl_backend_data *backend = connssl->backend;
@@ -846,10 +845,21 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn,
   }
 
   if(!backend->cred) {
+    char *snihost;
     result = schannel_acquire_credential_handle(data, conn, sockindex);
     if(result != CURLE_OK) {
       return result;
     }
+    /* A hostname associated with the credential is needed by
+       InitializeSecurityContext for SNI and other reasons. */
+    snihost = Curl_ssl_snihost(data, SSL_HOST_NAME(), NULL);
+    if(!snihost) {
+      failf(data, "Failed to set SNI");
+      return CURLE_SSL_CONNECT_ERROR;
+    }
+    backend->cred->sni_hostname = curlx_convert_UTF8_to_tchar(snihost);
+    if(!backend->cred->sni_hostname)
+      return CURLE_OUT_OF_MEMORY;
   }
 
   /* Warn if SNI is disabled due to use of an IP address */
@@ -936,10 +946,6 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn,
     return CURLE_OUT_OF_MEMORY;
   }
 
-  host_name = curlx_convert_UTF8_to_tchar(hostname);
-  if(!host_name)
-    return CURLE_OUT_OF_MEMORY;
-
   /* Schannel InitializeSecurityContext:
      https://msdn.microsoft.com/en-us/library/windows/desktop/aa375924.aspx
 
@@ -948,13 +954,12 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn,
      us problems with inbuf regardless. https://github.com/curl/curl/issues/983
   */
   sspi_status = s_pSecFn->InitializeSecurityContext(
-    &backend->cred->cred_handle, NULL, host_name, backend->req_flags, 0, 0,
+    &backend->cred->cred_handle, NULL, backend->cred->sni_hostname,
+    backend->req_flags, 0, 0,
     (backend->use_alpn ? &inbuf_desc : NULL),
     0, &backend->ctxt->ctxt_handle,
     &outbuf_desc, &backend->ret_flags, &backend->ctxt->time_stamp);
 
-  curlx_unicodefree(host_name);
-
   if(sspi_status != SEC_I_CONTINUE_NEEDED) {
     char buffer[STRERROR_LEN];
     Curl_safefree(backend->ctxt);
@@ -1027,16 +1032,11 @@ schannel_connect_step2(struct Curl_easy *data, struct connectdata *conn,
   SECURITY_STATUS sspi_status = SEC_E_OK;
   CURLcode result;
   bool doread;
-  char * const hostname = SSL_HOST_NAME();
   const char *pubkey_ptr;
   struct ssl_backend_data *backend = connssl->backend;
 
   doread = (connssl->connecting_state != ssl_connect_2_writing) ? TRUE : FALSE;
 
-  DEBUGF(infof(data,
-               "schannel: SSL/TLS connection with %s port %hu (step 2/3)",
-               hostname, conn->remote_port));
-
   if(!backend->cred || !backend->ctxt)
     return CURLE_SSL_CONNECT_ERROR;
 
@@ -1083,7 +1083,6 @@ schannel_connect_step2(struct Curl_easy *data, struct connectdata *conn,
   }
 
   for(;;) {
-    TCHAR *host_name;
     if(doread) {
       /* read encrypted handshake data from socket */
       result = Curl_read_plain(conn->sock[sockindex],
@@ -1136,17 +1135,12 @@ schannel_connect_step2(struct Curl_easy *data, struct connectdata *conn,
     memcpy(inbuf[0].pvBuffer, backend->encdata_buffer,
            backend->encdata_offset);
 
-    host_name = curlx_convert_UTF8_to_tchar(hostname);
-    if(!host_name)
-      return CURLE_OUT_OF_MEMORY;
-
     sspi_status = s_pSecFn->InitializeSecurityContext(
       &backend->cred->cred_handle, &backend->ctxt->ctxt_handle,
-      host_name, backend->req_flags, 0, 0, &inbuf_desc, 0, NULL,
+      backend->cred->sni_hostname, backend->req_flags,
+      0, 0, &inbuf_desc, 0, NULL,
       &outbuf_desc, &backend->ret_flags, &backend->ctxt->time_stamp);
 
-    curlx_unicodefree(host_name);
-
     /* free buffer for received handshake data */
     Curl_safefree(inbuf[0].pvBuffer);
 
@@ -2138,6 +2132,7 @@ static void schannel_session_free(void *ptr)
     cred->refcount--;
     if(cred->refcount == 0) {
       s_pSecFn->FreeCredentialsHandle(&cred->cred_handle);
+      curlx_unicodefree(cred->sni_hostname);
       Curl_safefree(cred);
     }
   }
@@ -2170,7 +2165,6 @@ static int schannel_shutdown(struct Curl_easy *data, struct connectdata *conn,
     SecBuffer outbuf;
     SecBufferDesc outbuf_desc;
     CURLcode result;
-    TCHAR *host_name;
     DWORD dwshut = SCHANNEL_SHUTDOWN;
 
     InitSecBuffer(&Buffer, SECBUFFER_TOKEN, &dwshut, sizeof(dwshut));
@@ -2185,10 +2179,6 @@ static int schannel_shutdown(struct Curl_easy *data, struct connectdata *conn,
             Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer)));
     }
 
-    host_name = curlx_convert_UTF8_to_tchar(hostname);
-    if(!host_name)
-      return CURLE_OUT_OF_MEMORY;
-
     /* setup output buffer */
     InitSecBuffer(&outbuf, SECBUFFER_EMPTY, NULL, 0);
     InitSecBufferDesc(&outbuf_desc, &outbuf, 1);
@@ -2196,7 +2186,7 @@ static int schannel_shutdown(struct Curl_easy *data, struct connectdata *conn,
     sspi_status = s_pSecFn->InitializeSecurityContext(
       &backend->cred->cred_handle,
       &backend->ctxt->ctxt_handle,
-      host_name,
+      backend->cred->sni_hostname,
       backend->req_flags,
       0,
       0,
@@ -2207,8 +2197,6 @@ static int schannel_shutdown(struct Curl_easy *data, struct connectdata *conn,
       &backend->ret_flags,
       &backend->ctxt->time_stamp);
 
-    curlx_unicodefree(host_name);
-
     if((sspi_status == SEC_E_OK) || (sspi_status == SEC_I_CONTEXT_EXPIRED)) {
       /* send close message which is in output buffer */
       ssize_t written;
index 77853aa30f96d22923f1d91e1731a3bd851998f6..c412ea4d02acd1d90d31606803cb87633f4ce1ec 100644 (file)
@@ -8,7 +8,7 @@
  *                             \___|\___/|_| \_\_____|
  *
  * Copyright (C) 2012, Marc Hoersken, <info@marc-hoersken.de>, et al.
- * Copyright (C) 2012 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2012 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -76,6 +76,7 @@ CURLcode Curl_verify_certificate(struct Curl_easy *data,
 struct Curl_schannel_cred {
   CredHandle cred_handle;
   TimeStamp time_stamp;
+  TCHAR *sni_hostname;
   int refcount;
 };
 
index f7a20b20b123e1824ff07c18ff44673f1b980070..059756eb69bd0ab1fd3135d84725fdc9d0880e6c 100644 (file)
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 2012 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2012 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
  * Copyright (C) 2012 - 2017, Nick Zitzmann, <nickzman@gmail.com>.
  *
  * This software is licensed as described in the file COPYING, which
@@ -2028,8 +2028,13 @@ static CURLcode sectransp_connect_step1(struct Curl_easy *data,
    * Both hostname check and SNI require SSLSetPeerDomainName().
    * Also: the verifyhost setting influences SNI usage */
   if(conn->ssl_config.verifyhost) {
-    err = SSLSetPeerDomainName(backend->ssl_ctx, hostname,
-    strlen(hostname));
+    size_t snilen;
+    char *snihost = Curl_ssl_snihost(data, hostname, &snilen);
+    if(!snihost) {
+      failf(data, "Failed to set SNI");
+      return CURLE_SSL_CONNECT_ERROR;
+    }
+    err = SSLSetPeerDomainName(backend->ssl_ctx, snihost, snilen);
 
     if(err != noErr) {
       infof(data, "WARNING: SSL: SSLSetPeerDomainName() failed: OSStatus %d",
index b606c622baff6b13a0de23739cd96f146cbf7d3c..b3bd87303ff14bf10343663c37dbfaf6b0c993be 100644 (file)
@@ -871,6 +871,32 @@ CURLcode Curl_ssl_random(struct Curl_easy *data,
   return Curl_ssl->random(data, entropy, length);
 }
 
+/*
+ * Curl_ssl_snihost() converts the input host name to a suitable SNI name put
+ * in data->state.buffer. Returns a pointer to the name (or NULL if a problem)
+ * and stores the new length in 'olen'.
+ *
+ * SNI fields must not have any trailing dot and while RFC 6066 section 3 says
+ * the SNI field is case insensitive, browsers always send the data lowercase
+ * and subsequently there are numerous servers out there that don't work
+ * unless the name is lowercased.
+ */
+
+char *Curl_ssl_snihost(struct Curl_easy *data, const char *host, size_t *olen)
+{
+  size_t len = strlen(host);
+  if(len && (host[len-1] == '.'))
+    len--;
+  if((long)len >= data->set.buffer_size)
+    return NULL;
+
+  Curl_strntolower(data->state.buffer, host, len);
+  data->state.buffer[len] = 0;
+  if(olen)
+    *olen = len;
+  return data->state.buffer;
+}
+
 /*
  * Public key pem to der conversion
  */
index fe5fc20e3cfb89044dd4be7cd65c43a23560d922..af3b8d3c94fc135fc435787b2c52b5e601cb8138 100644 (file)
@@ -172,6 +172,7 @@ bool Curl_ssl_tls13_ciphersuites(void);
   data->set.str[STRING_SSL_PINNEDPUBLICKEY]
 #endif
 
+char *Curl_ssl_snihost(struct Curl_easy *data, const char *host, size_t *olen);
 bool Curl_ssl_config_matches(struct ssl_primary_config *data,
                              struct ssl_primary_config *needle);
 bool Curl_clone_primary_ssl_config(struct ssl_primary_config *source,
index 8c5b9157b858b68cae2cd4986a99255fb5c6d1af..314279dd13ab9c3ce97bdf6cc5015bcb26affb44 100644 (file)
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -462,12 +462,17 @@ wolfssl_connect_step1(struct Curl_easy *data, struct connectdata *conn,
     if((hostname_len < USHRT_MAX) &&
        (0 == Curl_inet_pton(AF_INET, hostname, &addr4)) &&
 #ifdef ENABLE_IPV6
-       (0 == Curl_inet_pton(AF_INET6, hostname, &addr6)) &&
+       (0 == Curl_inet_pton(AF_INET6, hostname, &addr6))
 #endif
-       (wolfSSL_CTX_UseSNI(backend->ctx, WOLFSSL_SNI_HOST_NAME, hostname,
-                          (unsigned short)hostname_len) != 1)) {
-      infof(data, "WARNING: failed to configure server name indication (SNI) "
-            "TLS extension");
+      ) {
+      size_t snilen;
+      char *snihost = Curl_ssl_snihost(data, hostname, &snilen);
+      if(!snihost ||
+         wolfSSL_CTX_UseSNI(backend->ctx, WOLFSSL_SNI_HOST_NAME, snihost,
+                            (unsigned short)snilen) != 1) {
+        failf(data, "Failed to set SNI");
+        return CURLE_SSL_CONNECT_ERROR;
+      }
     }
   }
 #endif
@@ -590,7 +595,6 @@ wolfssl_connect_step2(struct Curl_easy *data, struct connectdata *conn,
   int ret = -1;
   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
   struct ssl_backend_data *backend = connssl->backend;
-  const char * const hostname = SSL_HOST_NAME();
   const char * const dispname = SSL_HOST_DISPNAME();
   const char * const pinnedpubkey = SSL_PINNED_PUB_KEY();
 
@@ -601,9 +605,10 @@ wolfssl_connect_step2(struct Curl_easy *data, struct connectdata *conn,
 
   /* Enable RFC2818 checks */
   if(SSL_CONN_CONFIG(verifyhost)) {
-    ret = wolfSSL_check_domain_name(backend->handle, hostname);
-    if(ret == SSL_FAILURE)
-      return CURLE_OUT_OF_MEMORY;
+    char *snihost = Curl_ssl_snihost(data, SSL_HOST_NAME(), NULL);
+    if(!snihost ||
+       (wolfSSL_check_domain_name(backend->handle, snihost) == SSL_FAILURE))
+      return CURLE_SSL_CONNECT_ERROR;
   }
 
   ret = SSL_connect(backend->handle);