summaryrefslogtreecommitdiff
path: root/libs/libcurl/src/vtls
diff options
context:
space:
mode:
authordartraiden <wowemuh@gmail.com>2023-12-10 18:22:53 +0300
committerdartraiden <wowemuh@gmail.com>2023-12-10 18:25:13 +0300
commit2ae0fc7299825cc561197d3f23c90e52ae8db58b (patch)
tree95fa8e7eb16cdff25b74d2d0ec033e667d4fd2c5 /libs/libcurl/src/vtls
parent76646f7a6d85fd5cdef2a610e0711bf4a9d8fdf3 (diff)
libcurl: update to 8.5.0
Diffstat (limited to 'libs/libcurl/src/vtls')
-rw-r--r--libs/libcurl/src/vtls/bearssl.c54
-rw-r--r--libs/libcurl/src/vtls/gtls.c121
-rw-r--r--libs/libcurl/src/vtls/gtls.h6
-rw-r--r--libs/libcurl/src/vtls/keylog.c9
-rw-r--r--libs/libcurl/src/vtls/mbedtls.c10
-rw-r--r--libs/libcurl/src/vtls/mbedtls_threadlock.c2
-rw-r--r--libs/libcurl/src/vtls/openssl.c526
-rw-r--r--libs/libcurl/src/vtls/openssl.h21
-rw-r--r--libs/libcurl/src/vtls/rustls.c117
-rw-r--r--libs/libcurl/src/vtls/schannel.c174
-rw-r--r--libs/libcurl/src/vtls/schannel_int.h17
-rw-r--r--libs/libcurl/src/vtls/schannel_verify.c64
-rw-r--r--libs/libcurl/src/vtls/sectransp.c40
-rw-r--r--libs/libcurl/src/vtls/vtls.c419
-rw-r--r--libs/libcurl/src/vtls/vtls.h80
-rw-r--r--libs/libcurl/src/vtls/vtls_int.h40
-rw-r--r--libs/libcurl/src/vtls/wolfssl.c37
-rw-r--r--libs/libcurl/src/vtls/x509asn1.c10
18 files changed, 1058 insertions, 689 deletions
diff --git a/libs/libcurl/src/vtls/bearssl.c b/libs/libcurl/src/vtls/bearssl.c
index 33f566931c..3bda30328c 100644
--- a/libs/libcurl/src/vtls/bearssl.c
+++ b/libs/libcurl/src/vtls/bearssl.c
@@ -582,17 +582,12 @@ static CURLcode bearssl_connect_step1(struct Curl_cfilter *cf,
const char * const ssl_cafile =
/* CURLOPT_CAINFO_BLOB overrides CURLOPT_CAINFO */
(ca_info_blob ? NULL : conn_config->CAfile);
- const char *hostname = connssl->hostname;
+ const char *hostname = connssl->peer.hostname;
const bool verifypeer = conn_config->verifypeer;
const bool verifyhost = conn_config->verifyhost;
CURLcode ret;
unsigned version_min, version_max;
int session_set = 0;
-#ifdef ENABLE_IPV6
- struct in6_addr addr;
-#else
- struct in_addr addr;
-#endif
DEBUGASSERT(backend);
CURL_TRC_CF(data, cf, "connect_step1");
@@ -706,11 +701,7 @@ static CURLcode bearssl_connect_step1(struct Curl_cfilter *cf,
infof(data, VTLS_INFOF_ALPN_OFFER_1STR, proto.data);
}
- if((1 == Curl_inet_pton(AF_INET, hostname, &addr))
-#ifdef ENABLE_IPV6
- || (1 == Curl_inet_pton(AF_INET6, hostname, &addr))
-#endif
- ) {
+ if(connssl->peer.is_ip_address) {
if(verifyhost) {
failf(data, "BearSSL: "
"host verification of IP address is not supported");
@@ -719,12 +710,11 @@ static CURLcode bearssl_connect_step1(struct Curl_cfilter *cf,
hostname = NULL;
}
else {
- char *snihost = Curl_ssl_snihost(data, hostname, NULL);
- if(!snihost) {
+ if(!connssl->peer.sni) {
failf(data, "Failed to set SNI");
return CURLE_SSL_CONNECT_ERROR;
}
- hostname = snihost;
+ hostname = connssl->peer.sni;
CURL_TRC_CF(data, cf, "connect_step1, SNI set");
}
@@ -749,26 +739,26 @@ static CURLcode bearssl_connect_step1(struct Curl_cfilter *cf,
return CURLE_OK;
}
-static int bearssl_get_select_socks(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- curl_socket_t *socks)
+static void bearssl_adjust_pollset(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct easy_pollset *ps)
{
- struct ssl_connect_data *connssl = cf->ctx;
- curl_socket_t sock = Curl_conn_cf_get_socket(cf->next, data);
-
- if(sock == CURL_SOCKET_BAD)
- return GETSOCK_BLANK;
- else {
- struct bearssl_ssl_backend_data *backend =
- (struct bearssl_ssl_backend_data *)connssl->backend;
- unsigned state = br_ssl_engine_current_state(&backend->ctx.eng);
- if(state & BR_SSL_SENDREC) {
- socks[0] = sock;
- return GETSOCK_WRITESOCK(0);
+ if(!cf->connected) {
+ curl_socket_t sock = Curl_conn_cf_get_socket(cf->next, data);
+ if(sock != CURL_SOCKET_BAD) {
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct bearssl_ssl_backend_data *backend =
+ (struct bearssl_ssl_backend_data *)connssl->backend;
+ unsigned state = br_ssl_engine_current_state(&backend->ctx.eng);
+
+ if(state & BR_SSL_SENDREC) {
+ Curl_pollset_set_out_only(data, ps, sock);
+ }
+ else {
+ Curl_pollset_set_in_only(data, ps, sock);
+ }
}
}
- socks[0] = sock;
- return GETSOCK_READSOCK(0);
}
static CURLcode bearssl_run_until(struct Curl_cfilter *cf,
@@ -1210,7 +1200,7 @@ const struct Curl_ssl Curl_ssl_bearssl = {
Curl_none_cert_status_request, /* cert_status_request */
bearssl_connect, /* connect */
bearssl_connect_nonblocking, /* connect_nonblocking */
- bearssl_get_select_socks, /* getsock */
+ bearssl_adjust_pollset, /* adjust_pollset */
bearssl_get_internals, /* get_internals */
bearssl_close, /* close_one */
Curl_none_close_all, /* close_all */
diff --git a/libs/libcurl/src/vtls/gtls.c b/libs/libcurl/src/vtls/gtls.c
index cc30cb0f55..bd78eb5030 100644
--- a/libs/libcurl/src/vtls/gtls.c
+++ b/libs/libcurl/src/vtls/gtls.c
@@ -402,18 +402,13 @@ set_ssl_version_min_max(struct Curl_easy *data,
CURLcode gtls_client_init(struct Curl_easy *data,
struct ssl_primary_config *config,
struct ssl_config_data *ssl_config,
- const char *hostname,
+ struct ssl_peer *peer,
struct gtls_instance *gtls,
long *pverifyresult)
{
unsigned int init_flags;
int rc;
bool sni = TRUE; /* default is SNI enabled */
-#ifdef ENABLE_IPV6
- struct in6_addr addr;
-#else
- struct in_addr addr;
-#endif
const char *prioritylist;
const char *err = NULL;
const char *tls13support;
@@ -460,50 +455,60 @@ CURLcode gtls_client_init(struct Curl_easy *data,
}
#endif
- if(config->CAfile) {
- /* set the trusted CA cert bundle file */
- gnutls_certificate_set_verify_flags(gtls->cred,
- GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT);
+ if(config->verifypeer) {
+ bool imported_native_ca = false;
- rc = gnutls_certificate_set_x509_trust_file(gtls->cred,
- config->CAfile,
- GNUTLS_X509_FMT_PEM);
- if(rc < 0) {
- infof(data, "error reading ca cert file %s (%s)",
- config->CAfile, gnutls_strerror(rc));
- if(config->verifypeer) {
- *pverifyresult = rc;
- return CURLE_SSL_CACERT_BADFILE;
+ if(ssl_config->native_ca_store) {
+ rc = gnutls_certificate_set_x509_system_trust(gtls->cred);
+ if(rc < 0)
+ infof(data, "error reading native ca store (%s), continuing anyway",
+ gnutls_strerror(rc));
+ else {
+ infof(data, "found %d certificates in native ca store", rc);
+ if(rc > 0)
+ imported_native_ca = true;
}
}
- else
- infof(data, "found %d certificates in %s", rc, config->CAfile);
- }
- if(config->CApath) {
- /* set the trusted CA cert directory */
- rc = gnutls_certificate_set_x509_trust_dir(gtls->cred,
- config->CApath,
- GNUTLS_X509_FMT_PEM);
- if(rc < 0) {
- infof(data, "error reading ca cert file %s (%s)",
- config->CApath, gnutls_strerror(rc));
- if(config->verifypeer) {
- *pverifyresult = rc;
- return CURLE_SSL_CACERT_BADFILE;
+ if(config->CAfile) {
+ /* set the trusted CA cert bundle file */
+ gnutls_certificate_set_verify_flags(gtls->cred,
+ GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT);
+
+ rc = gnutls_certificate_set_x509_trust_file(gtls->cred,
+ config->CAfile,
+ GNUTLS_X509_FMT_PEM);
+ if(rc < 0) {
+ infof(data, "error reading ca cert file %s (%s)%s",
+ config->CAfile, gnutls_strerror(rc),
+ (imported_native_ca ? ", continuing anyway" : ""));
+ if(!imported_native_ca) {
+ *pverifyresult = rc;
+ return CURLE_SSL_CACERT_BADFILE;
+ }
}
+ else
+ infof(data, "found %d certificates in %s", rc, config->CAfile);
}
- else
- infof(data, "found %d certificates in %s", rc, config->CApath);
- }
-#ifdef CURL_CA_FALLBACK
- /* use system ca certificate store as fallback */
- if(config->verifypeer && !(config->CAfile || config->CApath)) {
- /* this ignores errors on purpose */
- gnutls_certificate_set_x509_system_trust(gtls->cred);
+ if(config->CApath) {
+ /* set the trusted CA cert directory */
+ rc = gnutls_certificate_set_x509_trust_dir(gtls->cred,
+ config->CApath,
+ GNUTLS_X509_FMT_PEM);
+ if(rc < 0) {
+ infof(data, "error reading ca cert file %s (%s)%s",
+ config->CApath, gnutls_strerror(rc),
+ (imported_native_ca ? ", continuing anyway" : ""));
+ if(!imported_native_ca) {
+ *pverifyresult = rc;
+ return CURLE_SSL_CACERT_BADFILE;
+ }
+ }
+ else
+ infof(data, "found %d certificates in %s", rc, config->CApath);
+ }
}
-#endif
if(config->CRLfile) {
/* set the CRL list file */
@@ -537,15 +542,9 @@ CURLcode gtls_client_init(struct Curl_easy *data,
return CURLE_SSL_CONNECT_ERROR;
}
- if((0 == Curl_inet_pton(AF_INET, hostname, &addr)) &&
-#ifdef ENABLE_IPV6
- (0 == Curl_inet_pton(AF_INET6, hostname, &addr)) &&
-#endif
- sni) {
- size_t snilen;
- char *snihost = Curl_ssl_snihost(data, hostname, &snilen);
- if(!snihost || gnutls_server_name_set(gtls->session, GNUTLS_NAME_DNS,
- snihost, snilen) < 0) {
+ if(sni && peer->sni) {
+ if(gnutls_server_name_set(gtls->session, GNUTLS_NAME_DNS,
+ peer->sni, strlen(peer->sni)) < 0) {
failf(data, "Failed to set SNI");
return CURLE_SSL_CONNECT_ERROR;
}
@@ -699,7 +698,7 @@ gtls_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
return CURLE_OK;
result = gtls_client_init(data, conn_config, ssl_config,
- connssl->hostname,
+ &connssl->peer,
&backend->gtls, pverifyresult);
if(result)
return result;
@@ -811,8 +810,7 @@ Curl_gtls_verifyserver(struct Curl_easy *data,
gnutls_session_t session,
struct ssl_primary_config *config,
struct ssl_config_data *ssl_config,
- const char *hostname,
- const char *dispname,
+ struct ssl_peer *peer,
const char *pinned_key)
{
unsigned int cert_list_size;
@@ -1068,7 +1066,7 @@ Curl_gtls_verifyserver(struct Curl_easy *data,
in RFC2818 (HTTPS), which takes into account wildcards, and the subject
alternative name PKIX extension. Returns non zero on success, and zero on
failure. */
- rc = gnutls_x509_crt_check_hostname(x509_cert, hostname);
+ rc = gnutls_x509_crt_check_hostname(x509_cert, peer->hostname);
#if GNUTLS_VERSION_NUMBER < 0x030306
/* Before 3.3.6, gnutls_x509_crt_check_hostname() didn't check IP
addresses. */
@@ -1081,10 +1079,10 @@ Curl_gtls_verifyserver(struct Curl_easy *data,
unsigned char addrbuf[sizeof(struct use_addr)];
size_t addrlen = 0;
- if(Curl_inet_pton(AF_INET, hostname, addrbuf) > 0)
+ if(Curl_inet_pton(AF_INET, peer->hostname, addrbuf) > 0)
addrlen = 4;
#ifdef ENABLE_IPV6
- else if(Curl_inet_pton(AF_INET6, hostname, addrbuf) > 0)
+ else if(Curl_inet_pton(AF_INET6, peer->hostname, addrbuf) > 0)
addrlen = 16;
#endif
@@ -1114,13 +1112,13 @@ Curl_gtls_verifyserver(struct Curl_easy *data,
if(!rc) {
if(config->verifyhost) {
failf(data, "SSL: certificate subject name (%s) does not match "
- "target host name '%s'", certname, dispname);
+ "target host name '%s'", certname, peer->dispname);
gnutls_x509_crt_deinit(x509_cert);
return CURLE_PEER_FAILED_VERIFICATION;
}
else
infof(data, " common name: %s (does not match '%s')",
- certname, dispname);
+ certname, peer->dispname);
}
else
infof(data, " common name: %s (matched)", certname);
@@ -1253,8 +1251,7 @@ static CURLcode gtls_verifyserver(struct Curl_cfilter *cf,
CURLcode result;
result = Curl_gtls_verifyserver(data, session, conn_config, ssl_config,
- connssl->hostname, connssl->dispname,
- pinned_key);
+ &connssl->peer, pinned_key);
if(result)
goto out;
@@ -1662,7 +1659,7 @@ const struct Curl_ssl Curl_ssl_gnutls = {
gtls_cert_status_request, /* cert_status_request */
gtls_connect, /* connect */
gtls_connect_nonblocking, /* connect_nonblocking */
- Curl_ssl_get_select_socks, /* getsock */
+ Curl_ssl_adjust_pollset, /* adjust_pollset */
gtls_get_internals, /* get_internals */
gtls_close, /* close_one */
Curl_none_close_all, /* close_all */
diff --git a/libs/libcurl/src/vtls/gtls.h b/libs/libcurl/src/vtls/gtls.h
index 64f13b3b2a..998957e689 100644
--- a/libs/libcurl/src/vtls/gtls.h
+++ b/libs/libcurl/src/vtls/gtls.h
@@ -43,6 +43,7 @@ struct Curl_easy;
struct Curl_cfilter;
struct ssl_primary_config;
struct ssl_config_data;
+struct ssl_peer;
struct gtls_instance {
gnutls_session_t session;
@@ -56,7 +57,7 @@ CURLcode
gtls_client_init(struct Curl_easy *data,
struct ssl_primary_config *config,
struct ssl_config_data *ssl_config,
- const char *hostname,
+ struct ssl_peer *peer,
struct gtls_instance *gtls,
long *pverifyresult);
@@ -65,8 +66,7 @@ Curl_gtls_verifyserver(struct Curl_easy *data,
gnutls_session_t session,
struct ssl_primary_config *config,
struct ssl_config_data *ssl_config,
- const char *hostname,
- const char *dispname,
+ struct ssl_peer *peer,
const char *pinned_key);
extern const struct Curl_ssl Curl_ssl_gnutls;
diff --git a/libs/libcurl/src/vtls/keylog.c b/libs/libcurl/src/vtls/keylog.c
index dfa033d154..4a1f8ce74b 100644
--- a/libs/libcurl/src/vtls/keylog.c
+++ b/libs/libcurl/src/vtls/keylog.c
@@ -23,6 +23,11 @@
***************************************************************************/
#include "curl_setup.h"
+#if defined(USE_OPENSSL) || \
+ defined(USE_WOLFSSL) || \
+ (defined(USE_NGTCP2) && defined(USE_NGHTTP3)) || \
+ defined(USE_QUICHE)
+
#include "keylog.h"
#include <curl/curl.h>
@@ -55,7 +60,7 @@ Curl_tls_keylog_open(void)
if(keylog_file_name) {
keylog_file_fp = fopen(keylog_file_name, FOPEN_APPENDTEXT);
if(keylog_file_fp) {
-#ifdef WIN32
+#ifdef _WIN32
if(setvbuf(keylog_file_fp, NULL, _IONBF, 0))
#else
if(setvbuf(keylog_file_fp, NULL, _IOLBF, 4096))
@@ -157,3 +162,5 @@ Curl_tls_keylog_write(const char *label,
fputs(line, keylog_file_fp);
return true;
}
+
+#endif /* TLS or QUIC backend */
diff --git a/libs/libcurl/src/vtls/mbedtls.c b/libs/libcurl/src/vtls/mbedtls.c
index 496cac0ab4..292c933291 100644
--- a/libs/libcurl/src/vtls/mbedtls.c
+++ b/libs/libcurl/src/vtls/mbedtls.c
@@ -322,7 +322,7 @@ mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
char * const ssl_cert = ssl_config->primary.clientcert;
const struct curl_blob *ssl_cert_blob = ssl_config->primary.cert_blob;
const char * const ssl_crlfile = ssl_config->primary.CRLfile;
- const char *hostname = connssl->hostname;
+ const char *hostname = connssl->peer.hostname;
int ret = -1;
char errorbuf[128];
@@ -639,9 +639,9 @@ mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
mbedtls_ssl_conf_own_cert(&backend->config,
&backend->clicert, &backend->pk);
}
- {
- char *snihost = Curl_ssl_snihost(data, hostname, NULL);
- if(!snihost || mbedtls_ssl_set_hostname(&backend->ssl, snihost)) {
+
+ if(connssl->peer.sni) {
+ if(mbedtls_ssl_set_hostname(&backend->ssl, connssl->peer.sni)) {
/* 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. */
@@ -1274,7 +1274,7 @@ const struct Curl_ssl Curl_ssl_mbedtls = {
Curl_none_cert_status_request, /* cert_status_request */
mbedtls_connect, /* connect */
mbedtls_connect_nonblocking, /* connect_nonblocking */
- Curl_ssl_get_select_socks, /* getsock */
+ Curl_ssl_adjust_pollset, /* adjust_pollset */
mbedtls_get_internals, /* get_internals */
mbedtls_close, /* close_one */
mbedtls_close_all, /* close_all */
diff --git a/libs/libcurl/src/vtls/mbedtls_threadlock.c b/libs/libcurl/src/vtls/mbedtls_threadlock.c
index 935d0e1d66..757d19f003 100644
--- a/libs/libcurl/src/vtls/mbedtls_threadlock.c
+++ b/libs/libcurl/src/vtls/mbedtls_threadlock.c
@@ -51,7 +51,7 @@ int Curl_mbedtlsthreadlock_thread_setup(void)
{
int i;
- mutex_buf = calloc(NUMT * sizeof(MBEDTLS_MUTEX_T), 1);
+ mutex_buf = calloc(1, NUMT * sizeof(MBEDTLS_MUTEX_T));
if(!mutex_buf)
return 0; /* error, no number of threads defined */
diff --git a/libs/libcurl/src/vtls/openssl.c b/libs/libcurl/src/vtls/openssl.c
index b2f201ef13..fcc4e4eb0b 100644
--- a/libs/libcurl/src/vtls/openssl.c
+++ b/libs/libcurl/src/vtls/openssl.c
@@ -79,6 +79,8 @@
#include <openssl/bio.h>
#include <openssl/buffer.h>
#include <openssl/pkcs12.h>
+#include <openssl/tls1.h>
+#include <openssl/evp.h>
#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_OCSP)
#include <openssl/ocsp.h>
@@ -96,6 +98,9 @@
#include "curl_memory.h"
#include "memdebug.h"
+#ifndef ARRAYSIZE
+#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
+#endif
/* Uncomment the ALLOW_RENEG line to a real #define if you want to allow TLS
renegotiations when built with BoringSSL. Renegotiating is non-compliant
@@ -173,8 +178,6 @@
#if (OPENSSL_VERSION_NUMBER >= 0x30000000L)
#define HAVE_EVP_PKEY_GET_PARAMS 1
-#else
-#define SSL_get1_peer_certificate SSL_get_peer_certificate
#endif
#ifdef HAVE_EVP_PKEY_GET_PARAMS
@@ -235,7 +238,11 @@
#elif defined(OPENSSL_IS_AWSLC)
#define OSSL_PACKAGE "AWS-LC"
#else
-#define OSSL_PACKAGE "OpenSSL"
+# if defined(USE_NGTCP2) && defined(USE_NGHTTP3)
+# define OSSL_PACKAGE "quictls"
+# else
+# define OSSL_PACKAGE "OpenSSL"
+#endif
#endif
#if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
@@ -538,9 +545,9 @@ CURLcode Curl_ossl_certchain(struct Curl_easy *data, SSL *ssl)
#else
RSA_get0_key(rsa, &n, &e, NULL);
#endif /* HAVE_EVP_PKEY_GET_PARAMS */
- BIO_printf(mem, "%d", BN_num_bits(n));
+ BIO_printf(mem, "%d", n ? BN_num_bits(n) : 0);
#else
- BIO_printf(mem, "%d", BN_num_bits(rsa->n));
+ BIO_printf(mem, "%d", rsa->n ? BN_num_bits(rsa->n) : 0);
#endif /* HAVE_OPAQUE_RSA_DSA_DH */
push_certinfo("RSA Public Key", i);
print_pubkey_BN(rsa, n, i);
@@ -2098,22 +2105,6 @@ static bool subj_alt_hostcheck(struct Curl_easy *data,
return FALSE;
}
-static CURLcode
-ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn,
- X509 *server_cert, const char *hostname,
- const char *dispname);
-
-CURLcode Curl_ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn,
- X509 *server_cert)
-{
- const char *hostname, *dispname;
- int port;
-
- (void)conn;
- Curl_conn_get_host(data, FIRSTSOCKET, &hostname, &dispname, &port);
- return ossl_verifyhost(data, conn, server_cert, hostname, dispname);
-}
-
/* Quote from RFC2818 section 3.1 "Server Identity"
If a subjectAltName extension of type dNSName is present, that MUST
@@ -2136,10 +2127,8 @@ CURLcode Curl_ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn,
This function is now used from ngtcp2 (QUIC) as well.
*/
-static CURLcode
-ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn,
- X509 *server_cert, const char *hostname,
- const char *dispname)
+CURLcode Curl_ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn,
+ struct ssl_peer *peer, X509 *server_cert)
{
bool matched = FALSE;
int target = GEN_DNS; /* target type, GEN_DNS or GEN_IPADD */
@@ -2156,25 +2145,21 @@ ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn,
size_t hostlen;
(void)conn;
- hostlen = strlen(hostname);
-
-#ifndef ENABLE_IPV6
- /* Silence compiler warnings for unused params */
- (void) conn;
-#endif
-
+ hostlen = strlen(peer->hostname);
+ if(peer->is_ip_address) {
#ifdef ENABLE_IPV6
- if(conn->bits.ipv6_ip &&
- Curl_inet_pton(AF_INET6, hostname, &addr)) {
- target = GEN_IPADD;
- addrlen = sizeof(struct in6_addr);
- }
- else
-#endif
- if(Curl_inet_pton(AF_INET, hostname, &addr)) {
+ if(conn->bits.ipv6_ip &&
+ Curl_inet_pton(AF_INET6, peer->hostname, &addr)) {
target = GEN_IPADD;
- addrlen = sizeof(struct in_addr);
+ addrlen = sizeof(struct in6_addr);
}
+ else
+#endif
+ if(Curl_inet_pton(AF_INET, peer->hostname, &addr)) {
+ target = GEN_IPADD;
+ addrlen = sizeof(struct in_addr);
+ }
+ }
/* get a "list" of alternative names */
altnames = X509_get_ext_d2i(server_cert, NID_subject_alt_name, NULL, NULL);
@@ -2224,9 +2209,9 @@ ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn,
if((altlen == strlen(altptr)) &&
/* if this isn't true, there was an embedded zero in the name
string and we cannot match it. */
- subj_alt_hostcheck(data,
- altptr,
- altlen, hostname, hostlen, dispname)) {
+ subj_alt_hostcheck(data, altptr, altlen,
+ peer->hostname, hostlen,
+ peer->dispname)) {
dnsmatched = TRUE;
}
break;
@@ -2238,7 +2223,7 @@ ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn,
ipmatched = TRUE;
infof(data,
" subjectAltName: host \"%s\" matched cert's IP address!",
- dispname);
+ peer->dispname);
}
break;
}
@@ -2254,9 +2239,9 @@ ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn,
/* an alternative name matched */
;
else if(dNSName || iPAddress) {
- infof(data, " subjectAltName does not match %s", dispname);
+ infof(data, " subjectAltName does not match %s", peer->dispname);
failf(data, "SSL: no alternative certificate subject name matches "
- "target host name '%s'", dispname);
+ "target host name '%s'", peer->dispname);
result = CURLE_PEER_FAILED_VERIFICATION;
}
else {
@@ -2320,9 +2305,9 @@ ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn,
result = CURLE_PEER_FAILED_VERIFICATION;
}
else if(!Curl_cert_hostcheck((const char *)peer_CN,
- peerlen, hostname, hostlen)) {
+ peerlen, peer->hostname, hostlen)) {
failf(data, "SSL: certificate subject name '%s' does not match "
- "target host name '%s'", peer_CN, dispname);
+ "target host name '%s'", peer_CN, peer->dispname);
result = CURLE_PEER_FAILED_VERIFICATION;
}
else {
@@ -2731,12 +2716,6 @@ static void ossl_trace(int direction, int ssl_ver, int content_type,
#ifdef USE_OPENSSL
/* ====================================================== */
-#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
-# define use_sni(x) sni = (x)
-#else
-# define use_sni(x) Curl_nop_stmt
-#endif
-
/* Check for OpenSSL 1.0.2 which has ALPN support. */
#undef HAS_ALPN
#if OPENSSL_VERSION_NUMBER >= 0x10002000L \
@@ -3032,6 +3011,151 @@ static CURLcode load_cacert_from_memory(X509_STORE *store,
return (count > 0) ? CURLE_OK : CURLE_SSL_CACERT_BADFILE;
}
+#if defined(USE_WIN32_CRYPTO)
+static CURLcode import_windows_cert_store(struct Curl_easy *data,
+ const char *name,
+ X509_STORE *store,
+ bool *imported)
+{
+ CURLcode result = CURLE_OK;
+ HCERTSTORE hStore;
+
+ *imported = false;
+
+ hStore = CertOpenSystemStoreA(0, name);
+ if(hStore) {
+ PCCERT_CONTEXT pContext = NULL;
+ /* The array of enhanced key usage OIDs will vary per certificate and
+ is declared outside of the loop so that rather than malloc/free each
+ iteration we can grow it with realloc, when necessary. */
+ CERT_ENHKEY_USAGE *enhkey_usage = NULL;
+ DWORD enhkey_usage_size = 0;
+
+ /* This loop makes a best effort to import all valid certificates from
+ the MS root store. If a certificate cannot be imported it is
+ skipped. 'result' is used to store only hard-fail conditions (such
+ as out of memory) that cause an early break. */
+ result = CURLE_OK;
+ for(;;) {
+ X509 *x509;
+ FILETIME now;
+ BYTE key_usage[2];
+ DWORD req_size;
+ const unsigned char *encoded_cert;
+#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
+ char cert_name[256];
+#endif
+
+ pContext = CertEnumCertificatesInStore(hStore, pContext);
+ if(!pContext)
+ break;
+
+#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
+ if(!CertGetNameStringA(pContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0,
+ NULL, cert_name, sizeof(cert_name))) {
+ strcpy(cert_name, "Unknown");
+ }
+ infof(data, "SSL: Checking cert \"%s\"", cert_name);
+#endif
+ encoded_cert = (const unsigned char *)pContext->pbCertEncoded;
+ if(!encoded_cert)
+ continue;
+
+ GetSystemTimeAsFileTime(&now);
+ if(CompareFileTime(&pContext->pCertInfo->NotBefore, &now) > 0 ||
+ CompareFileTime(&now, &pContext->pCertInfo->NotAfter) > 0)
+ continue;
+
+ /* If key usage exists check for signing attribute */
+ if(CertGetIntendedKeyUsage(pContext->dwCertEncodingType,
+ pContext->pCertInfo,
+ key_usage, sizeof(key_usage))) {
+ if(!(key_usage[0] & CERT_KEY_CERT_SIGN_KEY_USAGE))
+ continue;
+ }
+ else if(GetLastError())
+ continue;
+
+ /* If enhanced key usage exists check for server auth attribute.
+ *
+ * Note "In a Microsoft environment, a certificate might also have
+ * EKU extended properties that specify valid uses for the
+ * certificate." The call below checks both, and behavior varies
+ * depending on what is found. For more details see
+ * CertGetEnhancedKeyUsage doc.
+ */
+ if(CertGetEnhancedKeyUsage(pContext, 0, NULL, &req_size)) {
+ if(req_size && req_size > enhkey_usage_size) {
+ void *tmp = realloc(enhkey_usage, req_size);
+
+ if(!tmp) {
+ failf(data, "SSL: Out of memory allocating for OID list");
+ result = CURLE_OUT_OF_MEMORY;
+ break;
+ }
+
+ enhkey_usage = (CERT_ENHKEY_USAGE *)tmp;
+ enhkey_usage_size = req_size;
+ }
+
+ if(CertGetEnhancedKeyUsage(pContext, 0, enhkey_usage, &req_size)) {
+ if(!enhkey_usage->cUsageIdentifier) {
+ /* "If GetLastError returns CRYPT_E_NOT_FOUND, the certificate
+ is good for all uses. If it returns zero, the certificate
+ has no valid uses." */
+ if((HRESULT)GetLastError() != CRYPT_E_NOT_FOUND)
+ continue;
+ }
+ else {
+ DWORD i;
+ bool found = false;
+
+ for(i = 0; i < enhkey_usage->cUsageIdentifier; ++i) {
+ if(!strcmp("1.3.6.1.5.5.7.3.1" /* OID server auth */,
+ enhkey_usage->rgpszUsageIdentifier[i])) {
+ found = true;
+ break;
+ }
+ }
+
+ if(!found)
+ continue;
+ }
+ }
+ else
+ continue;
+ }
+ else
+ continue;
+
+ x509 = d2i_X509(NULL, &encoded_cert, pContext->cbCertEncoded);
+ if(!x509)
+ continue;
+
+ /* Try to import the certificate. This may fail for legitimate
+ reasons such as duplicate certificate, which is allowed by MS but
+ not OpenSSL. */
+ if(X509_STORE_add_cert(store, x509) == 1) {
+#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
+ infof(data, "SSL: Imported cert \"%s\"", cert_name);
+#endif
+ *imported = true;
+ }
+ X509_free(x509);
+ }
+
+ free(enhkey_usage);
+ CertFreeCertificateContext(pContext);
+ CertCloseStore(hStore, 0);
+
+ if(result)
+ return result;
+ }
+
+ return result;
+}
+#endif
+
static CURLcode populate_x509_store(struct Curl_cfilter *cf,
struct Curl_easy *data,
X509_STORE *store)
@@ -3061,140 +3185,25 @@ static CURLcode populate_x509_store(struct Curl_cfilter *cf,
https://github.com/d3x0r/SACK/blob/master/src/netlib/ssl_layer.c#L1037
https://datatracker.ietf.org/doc/html/rfc5280 */
if(ssl_config->native_ca_store) {
- HCERTSTORE hStore = CertOpenSystemStore(0, TEXT("ROOT"));
-
- if(hStore) {
- PCCERT_CONTEXT pContext = NULL;
- /* The array of enhanced key usage OIDs will vary per certificate and
- is declared outside of the loop so that rather than malloc/free each
- iteration we can grow it with realloc, when necessary. */
- CERT_ENHKEY_USAGE *enhkey_usage = NULL;
- DWORD enhkey_usage_size = 0;
-
- /* This loop makes a best effort to import all valid certificates from
- the MS root store. If a certificate cannot be imported it is
- skipped. 'result' is used to store only hard-fail conditions (such
- as out of memory) that cause an early break. */
- result = CURLE_OK;
- for(;;) {
- X509 *x509;
- FILETIME now;
- BYTE key_usage[2];
- DWORD req_size;
- const unsigned char *encoded_cert;
-#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
- char cert_name[256];
-#endif
-
- pContext = CertEnumCertificatesInStore(hStore, pContext);
- if(!pContext)
- break;
-
-#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
- if(!CertGetNameStringA(pContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0,
- NULL, cert_name, sizeof(cert_name))) {
- strcpy(cert_name, "Unknown");
- }
- infof(data, "SSL: Checking cert \"%s\"", cert_name);
-#endif
- encoded_cert = (const unsigned char *)pContext->pbCertEncoded;
- if(!encoded_cert)
- continue;
-
- GetSystemTimeAsFileTime(&now);
- if(CompareFileTime(&pContext->pCertInfo->NotBefore, &now) > 0 ||
- CompareFileTime(&now, &pContext->pCertInfo->NotAfter) > 0)
- continue;
-
- /* If key usage exists check for signing attribute */
- if(CertGetIntendedKeyUsage(pContext->dwCertEncodingType,
- pContext->pCertInfo,
- key_usage, sizeof(key_usage))) {
- if(!(key_usage[0] & CERT_KEY_CERT_SIGN_KEY_USAGE))
- continue;
- }
- else if(GetLastError())
- continue;
-
- /* If enhanced key usage exists check for server auth attribute.
- *
- * Note "In a Microsoft environment, a certificate might also have
- * EKU extended properties that specify valid uses for the
- * certificate." The call below checks both, and behavior varies
- * depending on what is found. For more details see
- * CertGetEnhancedKeyUsage doc.
- */
- if(CertGetEnhancedKeyUsage(pContext, 0, NULL, &req_size)) {
- if(req_size && req_size > enhkey_usage_size) {
- void *tmp = realloc(enhkey_usage, req_size);
-
- if(!tmp) {
- failf(data, "SSL: Out of memory allocating for OID list");
- result = CURLE_OUT_OF_MEMORY;
- break;
- }
-
- enhkey_usage = (CERT_ENHKEY_USAGE *)tmp;
- enhkey_usage_size = req_size;
- }
-
- if(CertGetEnhancedKeyUsage(pContext, 0, enhkey_usage, &req_size)) {
- if(!enhkey_usage->cUsageIdentifier) {
- /* "If GetLastError returns CRYPT_E_NOT_FOUND, the certificate
- is good for all uses. If it returns zero, the certificate
- has no valid uses." */
- if((HRESULT)GetLastError() != CRYPT_E_NOT_FOUND)
- continue;
- }
- else {
- DWORD i;
- bool found = false;
-
- for(i = 0; i < enhkey_usage->cUsageIdentifier; ++i) {
- if(!strcmp("1.3.6.1.5.5.7.3.1" /* OID server auth */,
- enhkey_usage->rgpszUsageIdentifier[i])) {
- found = true;
- break;
- }
- }
-
- if(!found)
- continue;
- }
- }
- else
- continue;
- }
- else
- continue;
-
- x509 = d2i_X509(NULL, &encoded_cert, pContext->cbCertEncoded);
- if(!x509)
- continue;
-
- /* Try to import the certificate. This may fail for legitimate
- reasons such as duplicate certificate, which is allowed by MS but
- not OpenSSL. */
- if(X509_STORE_add_cert(store, x509) == 1) {
-#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
- infof(data, "SSL: Imported cert \"%s\"", cert_name);
-#endif
- imported_native_ca = true;
- }
- X509_free(x509);
- }
-
- free(enhkey_usage);
- CertFreeCertificateContext(pContext);
- CertCloseStore(hStore, 0);
-
+ const char *storeNames[] = {
+ "ROOT", /* Trusted Root Certification Authorities */
+ "CA" /* Intermediate Certification Authorities */
+ };
+ size_t i;
+ for(i = 0; i < ARRAYSIZE(storeNames); ++i) {
+ bool imported = false;
+ result = import_windows_cert_store(data, storeNames[i], store,
+ &imported);
if(result)
return result;
+ if(imported) {
+ infof(data, "successfully imported Windows %s store", storeNames[i]);
+ imported_native_ca = true;
+ }
+ else
+ infof(data, "error importing Windows %s store, continuing anyway",
+ storeNames[i]);
}
- if(imported_native_ca)
- infof(data, "successfully imported Windows CA store");
- else
- infof(data, "error importing Windows CA store, continuing anyway");
}
#endif
if(ca_info_blob) {
@@ -3210,7 +3219,7 @@ static CURLcode populate_x509_store(struct Curl_cfilter *cf,
}
if(ssl_cafile || ssl_capath) {
-#if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3)
+#if (OPENSSL_VERSION_NUMBER >= 0x30000000L)
/* OpenSSL 3.0.0 has deprecated SSL_CTX_load_verify_locations */
if(ssl_cafile && !X509_STORE_load_file(store, ssl_cafile)) {
if(!imported_native_ca && !imported_ca_info_blob) {
@@ -3339,6 +3348,7 @@ static X509_STORE *get_cached_x509_store(struct Curl_cfilter *cf,
struct Curl_multi *multi = data->multi_easy ? data->multi_easy : data->multi;
X509_STORE *store = NULL;
+ DEBUGASSERT(multi);
if(multi &&
multi->ssl_backend_data &&
multi->ssl_backend_data->store &&
@@ -3358,6 +3368,7 @@ static void set_cached_x509_store(struct Curl_cfilter *cf,
struct Curl_multi *multi = data->multi_easy ? data->multi_easy : data->multi;
struct multi_ssl_backend_data *mbackend;
+ DEBUGASSERT(multi);
if(!multi)
return;
@@ -3449,17 +3460,6 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf,
struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
BIO *bio;
-
-#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
- bool sni;
- const char *hostname = connssl->hostname;
-
-#ifdef ENABLE_IPV6
- struct in6_addr addr;
-#else
- struct in_addr addr;
-#endif
-#endif
const long int ssl_version = conn_config->version;
char * const ssl_cert = ssl_config->primary.clientcert;
const struct curl_blob *ssl_cert_blob = ssl_config->primary.cert_blob;
@@ -3494,7 +3494,6 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf,
#else
req_method = SSLv23_client_method();
#endif
- use_sni(TRUE);
break;
case CURL_SSLVERSION_SSLv2:
failf(data, "No SSLv2 support");
@@ -3787,13 +3786,8 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf,
backend->server_cert = 0x0;
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
- if((0 == Curl_inet_pton(AF_INET, hostname, &addr)) &&
-#ifdef ENABLE_IPV6
- (0 == Curl_inet_pton(AF_INET6, hostname, &addr)) &&
-#endif
- sni) {
- char *snihost = Curl_ssl_snihost(data, hostname, NULL);
- if(!snihost || !SSL_set_tlsext_host_name(backend->handle, snihost)) {
+ if(connssl->peer.sni) {
+ if(!SSL_set_tlsext_host_name(backend->handle, connssl->peer.sni)) {
failf(data, "Failed set SNI");
return CURLE_SSL_CONNECT_ERROR;
}
@@ -3802,6 +3796,7 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf,
SSL_set_app_data(backend->handle, cf);
+ connssl->reused_session = FALSE;
if(ssl_config->primary.sessionid) {
Curl_ssl_sessionid_lock(data);
if(!Curl_ssl_getsessionid(cf, data, &ssl_sessionid, NULL)) {
@@ -3815,6 +3810,7 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf,
}
/* Informational message */
infof(data, "SSL reusing session ID");
+ connssl->reused_session = TRUE;
}
Curl_ssl_sessionid_unlock(data);
}
@@ -3975,7 +3971,7 @@ static CURLcode ossl_connect_step2(struct Curl_cfilter *cf,
Curl_strerror(sockerr, extramsg, sizeof(extramsg));
failf(data, OSSL_PACKAGE " SSL_connect: %s in connection to %s:%d ",
extramsg[0] ? extramsg : SSL_ERROR_to_str(detail),
- connssl->hostname, connssl->port);
+ connssl->peer.hostname, connssl->port);
return result;
}
@@ -3986,13 +3982,28 @@ static CURLcode ossl_connect_step2(struct Curl_cfilter *cf,
}
}
else {
+ int psigtype_nid = NID_undef;
+ const char *negotiated_group_name = NULL;
+
/* we connected fine, we're not waiting for anything else. */
connssl->connecting_state = ssl_connect_3;
+#if (OPENSSL_VERSION_NUMBER >= 0x30000000L)
+ SSL_get_peer_signature_type_nid(backend->handle, &psigtype_nid);
+#if (OPENSSL_VERSION_NUMBER >= 0x30200000L)
+ negotiated_group_name = SSL_get0_group_name(backend->handle);
+#else
+ negotiated_group_name =
+ OBJ_nid2sn(SSL_get_negotiated_group(backend->handle) & 0x0000FFFF);
+#endif
+#endif
+
/* Informational message */
- infof(data, "SSL connection using %s / %s",
+ infof(data, "SSL connection using %s / %s / %s / %s",
SSL_get_version(backend->handle),
- SSL_get_cipher(backend->handle));
+ SSL_get_cipher(backend->handle),
+ negotiated_group_name? negotiated_group_name : "[blank]",
+ OBJ_nid2sn(psigtype_nid));
#ifdef HAS_ALPN
/* Sets data and len to negotiated protocol, len is 0 if no protocol was
@@ -4069,6 +4080,75 @@ static CURLcode ossl_pkp_pin_peer_pubkey(struct Curl_easy *data, X509* cert,
return result;
}
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && \
+ !(defined(LIBRESSL_VERSION_NUMBER) && \
+ LIBRESSL_VERSION_NUMBER < 0x3060000fL) && \
+ !defined(OPENSSL_IS_BORINGSSL) && \
+ !defined(OPENSSL_IS_AWSLC) && \
+ !defined(CURL_DISABLE_VERBOSE_STRINGS)
+static void infof_certstack(struct Curl_easy *data, const SSL *ssl)
+{
+ STACK_OF(X509) *certstack;
+ long verify_result;
+ int num_cert_levels;
+ int cert_level;
+
+ verify_result = SSL_get_verify_result(ssl);
+ if(verify_result != X509_V_OK)
+ certstack = SSL_get_peer_cert_chain(ssl);
+ else
+ certstack = SSL_get0_verified_chain(ssl);
+ num_cert_levels = sk_X509_num(certstack);
+
+ for(cert_level = 0; cert_level < num_cert_levels; cert_level++) {
+ char cert_algorithm[80] = "";
+ char group_name_final[80] = "";
+ const X509_ALGOR *palg_cert = NULL;
+ const ASN1_OBJECT *paobj_cert = NULL;
+ X509 *current_cert;
+ EVP_PKEY *current_pkey;
+ int key_bits;
+ int key_sec_bits;
+ int get_group_name;
+ const char *type_name;
+
+ current_cert = sk_X509_value(certstack, cert_level);
+
+ X509_get0_signature(NULL, &palg_cert, current_cert);
+ X509_ALGOR_get0(&paobj_cert, NULL, NULL, palg_cert);
+ OBJ_obj2txt(cert_algorithm, sizeof(cert_algorithm), paobj_cert, 0);
+
+ current_pkey = X509_get0_pubkey(current_cert);
+ key_bits = EVP_PKEY_bits(current_pkey);
+#if (OPENSSL_VERSION_NUMBER < 0x30000000L)
+#define EVP_PKEY_get_security_bits EVP_PKEY_security_bits
+#endif
+ key_sec_bits = EVP_PKEY_get_security_bits(current_pkey);
+#if (OPENSSL_VERSION_NUMBER >= 0x30000000L)
+ {
+ char group_name[80] = "";
+ get_group_name = EVP_PKEY_get_group_name(current_pkey, group_name,
+ sizeof(group_name), NULL);
+ msnprintf(group_name_final, sizeof(group_name_final), "/%s", group_name);
+ }
+ type_name = EVP_PKEY_get0_type_name(current_pkey);
+#else
+ get_group_name = 0;
+ type_name = NULL;
+#endif
+
+ infof(data,
+ " Certificate level %d: "
+ "Public key type %s%s (%d/%d Bits/secBits), signed using %s",
+ cert_level, type_name ? type_name : "?",
+ get_group_name == 0 ? "" : group_name_final,
+ key_bits, key_sec_bits, cert_algorithm);
+ }
+}
+#else
+#define infof_certstack(data, ssl)
+#endif
+
/*
* Get the server cert, verify it and show it, etc., only call failf() if the
* 'strict' argument is TRUE as otherwise all this is for informational
@@ -4147,8 +4227,8 @@ static CURLcode servercert(struct Curl_cfilter *cf,
BIO_free(mem);
if(conn_config->verifyhost) {
- result = ossl_verifyhost(data, conn, backend->server_cert,
- connssl->hostname, connssl->dispname);
+ result = Curl_ossl_verifyhost(data, conn, &connssl->peer,
+ backend->server_cert);
if(result) {
X509_free(backend->server_cert);
backend->server_cert = NULL;
@@ -4258,9 +4338,12 @@ static CURLcode servercert(struct Curl_cfilter *cf,
infof(data, " SSL certificate verify ok.");
}
+ infof_certstack(data, backend->handle);
+
#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \
!defined(OPENSSL_NO_OCSP)
- if(conn_config->verifystatus) {
+ if(conn_config->verifystatus && !connssl->reused_session) {
+ /* don't do this after Session ID reuse */
result = verifystatus(cf, data);
if(result) {
X509_free(backend->server_cert);
@@ -4522,22 +4605,9 @@ static ssize_t ossl_send(struct Curl_cfilter *cf,
case SSL_ERROR_SSL: {
/* A failure in the SSL library occurred, usually a protocol error.
The OpenSSL error queue contains more information on the error. */
- struct Curl_cfilter *cf_ssl_next = Curl_ssl_cf_get_ssl(cf->next);
- struct ssl_connect_data *connssl_next = cf_ssl_next?
- cf_ssl_next->ctx : NULL;
sslerror = ERR_get_error();
- if(ERR_GET_LIB(sslerror) == ERR_LIB_SSL &&
- ERR_GET_REASON(sslerror) == SSL_R_BIO_NOT_SET &&
- connssl->state == ssl_connection_complete &&
- (connssl_next && connssl_next->state == ssl_connection_complete)
- ) {
- char ver[120];
- (void)ossl_version(ver, sizeof(ver));
- failf(data, "Error: %s does not support double SSL tunneling.", ver);
- }
- else
- failf(data, "SSL_write() error: %s",
- ossl_strerror(sslerror, error_buffer, sizeof(error_buffer)));
+ failf(data, "SSL_write() error: %s",
+ ossl_strerror(sslerror, error_buffer, sizeof(error_buffer)));
*curlcode = CURLE_SEND_ERROR;
rc = -1;
goto out;
@@ -4842,7 +4912,7 @@ const struct Curl_ssl Curl_ssl_openssl = {
ossl_cert_status_request, /* cert_status_request */
ossl_connect, /* connect */
ossl_connect_nonblocking, /* connect_nonblocking */
- Curl_ssl_get_select_socks,/* getsock */
+ Curl_ssl_adjust_pollset, /* adjust_pollset */
ossl_get_internals, /* get_internals */
ossl_close, /* close_one */
ossl_close_all, /* close_all */
diff --git a/libs/libcurl/src/vtls/openssl.h b/libs/libcurl/src/vtls/openssl.h
index b88b83febe..df36a831b1 100644
--- a/libs/libcurl/src/vtls/openssl.h
+++ b/libs/libcurl/src/vtls/openssl.h
@@ -31,24 +31,21 @@
* This header should only be needed to get included by vtls.c, openssl.c
* and ngtcp2.c
*/
+#include <openssl/ossl_typ.h>
#include <openssl/ssl.h>
#include "urldata.h"
-/*
- * In an effort to avoid using 'X509 *' here, we instead use the struct
- * x509_st version of the type so that we can forward-declare it here without
- * having to include <openssl/x509v3.h>. Including that header causes name
- * conflicts when libcurl is built with both Schannel and OpenSSL support.
- */
-struct x509_st;
+#if (OPENSSL_VERSION_NUMBER < 0x30000000L)
+#define SSL_get1_peer_certificate SSL_get_peer_certificate
+#endif
+
CURLcode Curl_ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn,
- struct x509_st *server_cert);
+ struct ssl_peer *peer, X509 *server_cert);
extern const struct Curl_ssl Curl_ssl_openssl;
-struct ssl_ctx_st;
CURLcode Curl_ossl_set_client_cert(struct Curl_easy *data,
- struct ssl_ctx_st *ctx, char *cert_file,
+ SSL_CTX *ctx, char *cert_file,
const struct curl_blob *cert_blob,
const char *cert_type, char *key_file,
const struct curl_blob *key_blob,
@@ -65,5 +62,9 @@ CURLcode Curl_ssl_setup_x509_store(struct Curl_cfilter *cf,
struct Curl_easy *data,
SSL_CTX *ssl_ctx);
+CURLcode Curl_ossl_ctx_configure(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ SSL_CTX *ssl_ctx);
+
#endif /* USE_OPENSSL */
#endif /* HEADER_CURL_SSLUSE_H */
diff --git a/libs/libcurl/src/vtls/rustls.c b/libs/libcurl/src/vtls/rustls.c
index 989954bf46..d30325d098 100644
--- a/libs/libcurl/src/vtls/rustls.c
+++ b/libs/libcurl/src/vtls/rustls.c
@@ -39,6 +39,7 @@
#include "select.h"
#include "strerror.h"
#include "multiif.h"
+#include "connect.h" /* for the connect timeout */
struct rustls_ssl_backend_data
{
@@ -75,14 +76,6 @@ cr_data_pending(struct Curl_cfilter *cf, const struct Curl_easy *data)
return backend->data_pending;
}
-static CURLcode
-cr_connect(struct Curl_cfilter *cf UNUSED_PARAM,
- struct Curl_easy *data UNUSED_PARAM)
-{
- infof(data, "rustls_connect: unimplemented");
- return CURLE_SSL_CONNECT_ERROR;
-}
-
struct io_ctx {
struct Curl_cfilter *cf;
struct Curl_easy *data;
@@ -386,7 +379,7 @@ cr_init_backend(struct Curl_cfilter *cf, struct Curl_easy *data,
/* CURLOPT_CAINFO_BLOB overrides CURLOPT_CAINFO */
(ca_info_blob ? NULL : conn_config->CAfile);
const bool verifypeer = conn_config->verifypeer;
- const char *hostname = connssl->hostname;
+ const char *hostname = connssl->peer.hostname;
char errorbuf[256];
size_t errorlen;
int result;
@@ -458,12 +451,11 @@ cr_init_backend(struct Curl_cfilter *cf, struct Curl_easy *data,
backend->config = rustls_client_config_builder_build(config_builder);
DEBUGASSERT(rconn == NULL);
{
- char *snihost = Curl_ssl_snihost(data, hostname, NULL);
- if(!snihost) {
- failf(data, "rustls: failed to get SNI");
- return CURLE_SSL_CONNECT_ERROR;
- }
- result = rustls_client_connection_new(backend->config, snihost, &rconn);
+ /* rustls claims to manage ip address hostnames as well here. So,
+ * if we have an SNI, we use it, otherwise we pass the hostname */
+ char *server = connssl->peer.sni?
+ connssl->peer.sni : connssl->peer.hostname;
+ result = rustls_client_connection_new(backend->config, server, &rconn);
}
if(result != RUSTLS_RESULT_OK) {
rustls_error(result, errorbuf, sizeof(errorbuf), &errorlen);
@@ -486,9 +478,20 @@ cr_set_negotiated_alpn(struct Curl_cfilter *cf, struct Curl_easy *data,
Curl_alpn_set_negotiated(cf, data, protocol, len);
}
+/* Given an established network connection, do a TLS handshake.
+ *
+ * If `blocking` is true, this function will block until the handshake is
+ * complete. Otherwise it will return as soon as I/O would block.
+ *
+ * For the non-blocking I/O case, this function will set `*done` to true
+ * once the handshake is complete. This function never reads the value of
+ * `*done*`.
+ */
static CURLcode
-cr_connect_nonblocking(struct Curl_cfilter *cf,
- struct Curl_easy *data, bool *done)
+cr_connect_common(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ bool blocking,
+ bool *done)
{
struct ssl_connect_data *const connssl = cf->ctx;
curl_socket_t sockfd = Curl_conn_cf_get_socket(cf, data);
@@ -502,6 +505,8 @@ cr_connect_nonblocking(struct Curl_cfilter *cf,
bool wants_write;
curl_socket_t writefd;
curl_socket_t readfd;
+ timediff_t timeout_ms;
+ timediff_t socket_check_timeout;
DEBUGASSERT(backend);
@@ -539,12 +544,29 @@ cr_connect_nonblocking(struct Curl_cfilter *cf,
writefd = wants_write?sockfd:CURL_SOCKET_BAD;
readfd = wants_read?sockfd:CURL_SOCKET_BAD;
- what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd, 0);
+ /* check allowed time left */
+ timeout_ms = Curl_timeleft(data, NULL, TRUE);
+
+ if(timeout_ms < 0) {
+ /* no need to continue if time already is up */
+ failf(data, "rustls: operation timed out before socket check");
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+
+ socket_check_timeout = blocking?timeout_ms:0;
+
+ what = Curl_socket_check(
+ readfd, CURL_SOCKET_BAD, writefd, socket_check_timeout);
if(what < 0) {
/* fatal error */
failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
return CURLE_SSL_CONNECT_ERROR;
}
+ if(blocking && 0 == what) {
+ failf(data, "rustls connection timeout after %d ms",
+ socket_check_timeout);
+ return CURLE_OPERATION_TIMEDOUT;
+ }
if(0 == what) {
infof(data, "Curl_socket_check: %s would block",
wants_read&&wants_write ? "writing and reading" :
@@ -589,32 +611,43 @@ cr_connect_nonblocking(struct Curl_cfilter *cf,
DEBUGASSERT(false);
}
-/* returns a bitmap of flags for this connection's first socket indicating
- whether we want to read or write */
-static int
-cr_get_select_socks(struct Curl_cfilter *cf, struct Curl_easy *data,
- curl_socket_t *socks)
+static CURLcode
+cr_connect_nonblocking(struct Curl_cfilter *cf,
+ struct Curl_easy *data, bool *done)
{
- struct ssl_connect_data *const connssl = cf->ctx;
- curl_socket_t sockfd = Curl_conn_cf_get_socket(cf, data);
- struct rustls_ssl_backend_data *const backend =
- (struct rustls_ssl_backend_data *)connssl->backend;
- struct rustls_connection *rconn = NULL;
+ return cr_connect_common(cf, data, false, done);
+}
- (void)data;
- DEBUGASSERT(backend);
- rconn = backend->conn;
+static CURLcode
+cr_connect_blocking(struct Curl_cfilter *cf UNUSED_PARAM,
+ struct Curl_easy *data UNUSED_PARAM)
+{
+ bool done; /* unused */
+ return cr_connect_common(cf, data, true, &done);
+}
- if(rustls_connection_wants_write(rconn)) {
- socks[0] = sockfd;
- return GETSOCK_WRITESOCK(0);
- }
- if(rustls_connection_wants_read(rconn)) {
- socks[0] = sockfd;
- return GETSOCK_READSOCK(0);
+static void cr_adjust_pollset(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct easy_pollset *ps)
+{
+ if(!cf->connected) {
+ curl_socket_t sock = Curl_conn_cf_get_socket(cf->next, data);
+ struct ssl_connect_data *const connssl = cf->ctx;
+ struct rustls_ssl_backend_data *const backend =
+ (struct rustls_ssl_backend_data *)connssl->backend;
+ struct rustls_connection *rconn = NULL;
+
+ (void)data;
+ DEBUGASSERT(backend);
+ rconn = backend->conn;
+
+ if(rustls_connection_wants_write(rconn)) {
+ Curl_pollset_add_out(data, ps, sock);
+ }
+ if(rustls_connection_wants_read(rconn)) {
+ Curl_pollset_add_in(data, ps, sock);
+ }
}
-
- return GETSOCK_BLANK;
}
static void *
@@ -675,9 +708,9 @@ const struct Curl_ssl Curl_ssl_rustls = {
cr_data_pending, /* data_pending */
Curl_none_random, /* random */
Curl_none_cert_status_request, /* cert_status_request */
- cr_connect, /* connect */
+ cr_connect_blocking, /* connect */
cr_connect_nonblocking, /* connect_nonblocking */
- cr_get_select_socks, /* get_select_socks */
+ cr_adjust_pollset, /* adjust_pollset */
cr_get_internals, /* get_internals */
cr_close, /* close_one */
Curl_none_close_all, /* close_all */
diff --git a/libs/libcurl/src/vtls/schannel.c b/libs/libcurl/src/vtls/schannel.c
index 77ab43a9bf..c04f968f29 100644
--- a/libs/libcurl/src/vtls/schannel.c
+++ b/libs/libcurl/src/vtls/schannel.c
@@ -1063,17 +1063,12 @@ schannel_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
#endif
SECURITY_STATUS sspi_status = SEC_E_OK;
struct Curl_schannel_cred *old_cred = NULL;
- struct in_addr addr;
-#ifdef ENABLE_IPV6
- struct in6_addr addr6;
-#endif
CURLcode result;
- const char *hostname = connssl->hostname;
DEBUGASSERT(backend);
DEBUGF(infof(data,
"schannel: SSL/TLS connection with %s port %d (step 1/3)",
- hostname, connssl->port));
+ connssl->peer.hostname, connssl->port));
if(curlx_verify_windows_version(5, 1, 0, PLATFORM_WINNT,
VERSION_LESS_THAN_EQUAL)) {
@@ -1154,22 +1149,14 @@ schannel_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
/* A hostname associated with the credential is needed by
InitializeSecurityContext for SNI and other reasons. */
- snihost = Curl_ssl_snihost(data, hostname, NULL);
- if(!snihost) {
- failf(data, "Failed to set SNI");
- return CURLE_SSL_CONNECT_ERROR;
- }
+ snihost = connssl->peer.sni? connssl->peer.sni : connssl->peer.hostname;
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 */
- if(Curl_inet_pton(AF_INET, hostname, &addr)
-#ifdef ENABLE_IPV6
- || Curl_inet_pton(AF_INET6, hostname, &addr6)
-#endif
- ) {
+ if(connssl->peer.is_ip_address) {
infof(data, "schannel: using IP address, SNI is not supported by OS.");
}
@@ -1346,7 +1333,7 @@ schannel_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data)
DEBUGF(infof(data,
"schannel: SSL/TLS connection with %s port %d (step 2/3)",
- connssl->hostname, connssl->port));
+ connssl->peer.hostname, connssl->port));
if(!backend->cred || !backend->ctxt)
return CURLE_SSL_CONNECT_ERROR;
@@ -1700,7 +1687,7 @@ schannel_connect_step3(struct Curl_cfilter *cf, struct Curl_easy *data)
DEBUGF(infof(data,
"schannel: SSL/TLS connection with %s port %d (step 3/3)",
- connssl->hostname, connssl->port));
+ connssl->peer.hostname, connssl->port));
if(!backend->cred)
return CURLE_SSL_CONNECT_ERROR;
@@ -2498,7 +2485,7 @@ static int schannel_shutdown(struct Curl_cfilter *cf,
if(backend->ctxt) {
infof(data, "schannel: shutting down SSL/TLS connection with %s port %d",
- connssl->hostname, connssl->port);
+ connssl->peer.hostname, connssl->port);
}
if(backend->cred && backend->ctxt) {
@@ -2754,6 +2741,151 @@ static void *schannel_get_internals(struct ssl_connect_data *connssl,
return &backend->ctxt->ctxt_handle;
}
+HCERTSTORE Curl_schannel_get_cached_cert_store(struct Curl_cfilter *cf,
+ const struct Curl_easy *data)
+{
+ struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
+ struct Curl_multi *multi = data->multi_easy ? data->multi_easy : data->multi;
+ const struct curl_blob *ca_info_blob = conn_config->ca_info_blob;
+ struct schannel_multi_ssl_backend_data *mbackend;
+ const struct ssl_general_config *cfg = &data->set.general_ssl;
+ timediff_t timeout_ms;
+ timediff_t elapsed_ms;
+ struct curltime now;
+ unsigned char info_blob_digest[CURL_SHA256_DIGEST_LENGTH];
+
+ DEBUGASSERT(multi);
+
+ if(!multi || !multi->ssl_backend_data) {
+ return NULL;
+ }
+
+ mbackend = (struct schannel_multi_ssl_backend_data *)multi->ssl_backend_data;
+ if(!mbackend->cert_store) {
+ return NULL;
+ }
+
+ /* zero ca_cache_timeout completely disables caching */
+ if(!cfg->ca_cache_timeout) {
+ return NULL;
+ }
+
+ /* check for cache timeout by using the cached_x509_store_expired timediff
+ calculation pattern from openssl.c.
+ negative timeout means retain forever. */
+ timeout_ms = cfg->ca_cache_timeout * (timediff_t)1000;
+ if(timeout_ms >= 0) {
+ now = Curl_now();
+ elapsed_ms = Curl_timediff(now, mbackend->time);
+ if(elapsed_ms >= timeout_ms) {
+ return NULL;
+ }
+ }
+
+ if(ca_info_blob) {
+ if(!mbackend->CAinfo_blob_digest) {
+ return NULL;
+ }
+ if(mbackend->CAinfo_blob_size != ca_info_blob->len) {
+ return NULL;
+ }
+ schannel_sha256sum((const unsigned char *)ca_info_blob->data,
+ ca_info_blob->len,
+ info_blob_digest,
+ CURL_SHA256_DIGEST_LENGTH);
+ if(memcmp(mbackend->CAinfo_blob_digest,
+ info_blob_digest,
+ CURL_SHA256_DIGEST_LENGTH)) {
+ return NULL;
+ }
+ }
+ else {
+ if(!conn_config->CAfile || !mbackend->CAfile ||
+ strcmp(mbackend->CAfile, conn_config->CAfile)) {
+ return NULL;
+ }
+ }
+
+ return mbackend->cert_store;
+}
+
+bool Curl_schannel_set_cached_cert_store(struct Curl_cfilter *cf,
+ const struct Curl_easy *data,
+ HCERTSTORE cert_store)
+{
+ struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
+ struct Curl_multi *multi = data->multi_easy ? data->multi_easy : data->multi;
+ const struct curl_blob *ca_info_blob = conn_config->ca_info_blob;
+ struct schannel_multi_ssl_backend_data *mbackend;
+ unsigned char *CAinfo_blob_digest = NULL;
+ size_t CAinfo_blob_size = 0;
+ char *CAfile = NULL;
+
+ DEBUGASSERT(multi);
+
+ if(!multi) {
+ return false;
+ }
+
+ if(!multi->ssl_backend_data) {
+ multi->ssl_backend_data =
+ calloc(1, sizeof(struct schannel_multi_ssl_backend_data));
+ if(!multi->ssl_backend_data) {
+ return false;
+ }
+ }
+
+ mbackend = (struct schannel_multi_ssl_backend_data *)multi->ssl_backend_data;
+
+
+ if(ca_info_blob) {
+ CAinfo_blob_digest = malloc(CURL_SHA256_DIGEST_LENGTH);
+ if(!CAinfo_blob_digest) {
+ return false;
+ }
+ schannel_sha256sum((const unsigned char *)ca_info_blob->data,
+ ca_info_blob->len,
+ CAinfo_blob_digest,
+ CURL_SHA256_DIGEST_LENGTH);
+ CAinfo_blob_size = ca_info_blob->len;
+ }
+ else {
+ if(conn_config->CAfile) {
+ CAfile = strdup(conn_config->CAfile);
+ if(!CAfile) {
+ return false;
+ }
+ }
+ }
+
+ /* free old cache data */
+ if(mbackend->cert_store) {
+ CertCloseStore(mbackend->cert_store, 0);
+ }
+ free(mbackend->CAinfo_blob_digest);
+ free(mbackend->CAfile);
+
+ mbackend->time = Curl_now();
+ mbackend->cert_store = cert_store;
+ mbackend->CAinfo_blob_digest = CAinfo_blob_digest;
+ mbackend->CAinfo_blob_size = CAinfo_blob_size;
+ mbackend->CAfile = CAfile;
+ return true;
+}
+
+static void schannel_free_multi_ssl_backend_data(
+ struct multi_ssl_backend_data *msbd)
+{
+ struct schannel_multi_ssl_backend_data *mbackend =
+ (struct schannel_multi_ssl_backend_data*)msbd;
+ if(mbackend->cert_store) {
+ CertCloseStore(mbackend->cert_store, 0);
+ }
+ free(mbackend->CAinfo_blob_digest);
+ free(mbackend->CAfile);
+ free(mbackend);
+}
+
const struct Curl_ssl Curl_ssl_schannel = {
{ CURLSSLBACKEND_SCHANNEL, "schannel" }, /* info */
@@ -2777,7 +2909,7 @@ const struct Curl_ssl Curl_ssl_schannel = {
Curl_none_cert_status_request, /* cert_status_request */
schannel_connect, /* connect */
schannel_connect_nonblocking, /* connect_nonblocking */
- Curl_ssl_get_select_socks, /* getsock */
+ Curl_ssl_adjust_pollset, /* adjust_pollset */
schannel_get_internals, /* get_internals */
schannel_close, /* close_one */
Curl_none_close_all, /* close_all */
@@ -2789,7 +2921,7 @@ const struct Curl_ssl Curl_ssl_schannel = {
schannel_sha256sum, /* sha256sum */
NULL, /* associate_connection */
NULL, /* disassociate_connection */
- NULL, /* free_multi_ssl_backend_data */
+ schannel_free_multi_ssl_backend_data, /* free_multi_ssl_backend_data */
schannel_recv, /* recv decrypted data */
schannel_send, /* send data to encrypt */
};
diff --git a/libs/libcurl/src/vtls/schannel_int.h b/libs/libcurl/src/vtls/schannel_int.h
index 17a94d6e85..c460be63aa 100644
--- a/libs/libcurl/src/vtls/schannel_int.h
+++ b/libs/libcurl/src/vtls/schannel_int.h
@@ -149,5 +149,22 @@ struct schannel_ssl_backend_data {
#endif
};
+struct schannel_multi_ssl_backend_data {
+ unsigned char *CAinfo_blob_digest; /* CA info blob digest */
+ size_t CAinfo_blob_size; /* CA info blob size */
+ char *CAfile; /* CAfile path used to generate
+ certificate store */
+ HCERTSTORE cert_store; /* cached certificate store or
+ NULL if none */
+ struct curltime time; /* when the cached store was created */
+};
+
+HCERTSTORE Curl_schannel_get_cached_cert_store(struct Curl_cfilter *cf,
+ const struct Curl_easy *data);
+
+bool Curl_schannel_set_cached_cert_store(struct Curl_cfilter *cf,
+ const struct Curl_easy *data,
+ HCERTSTORE cert_store);
+
#endif /* USE_SCHANNEL */
#endif /* HEADER_CURL_SCHANNEL_INT_H */
diff --git a/libs/libcurl/src/vtls/schannel_verify.c b/libs/libcurl/src/vtls/schannel_verify.c
index 35ce35b789..0c9c00c16a 100644
--- a/libs/libcurl/src/vtls/schannel_verify.c
+++ b/libs/libcurl/src/vtls/schannel_verify.c
@@ -470,7 +470,7 @@ CURLcode Curl_verify_host(struct Curl_cfilter *cf,
CERT_CONTEXT *pCertContextServer = NULL;
TCHAR *cert_hostname_buff = NULL;
size_t cert_hostname_buff_index = 0;
- const char *conn_hostname = connssl->hostname;
+ const char *conn_hostname = connssl->peer.hostname;
size_t hostlen = strlen(conn_hostname);
DWORD len = 0;
DWORD actual_len = 0;
@@ -600,6 +600,7 @@ CURLcode Curl_verify_certificate(struct Curl_cfilter *cf,
const CERT_CHAIN_CONTEXT *pChainContext = NULL;
HCERTCHAINENGINE cert_chain_engine = NULL;
HCERTSTORE trust_store = NULL;
+ HCERTSTORE own_trust_store = NULL;
DEBUGASSERT(BACKEND);
@@ -630,31 +631,46 @@ CURLcode Curl_verify_certificate(struct Curl_cfilter *cf,
result = CURLE_SSL_CACERT_BADFILE;
}
else {
- /* Open the certificate store */
- trust_store = CertOpenStore(CERT_STORE_PROV_MEMORY,
- 0,
- (HCRYPTPROV)NULL,
- CERT_STORE_CREATE_NEW_FLAG,
- NULL);
- if(!trust_store) {
- char buffer[STRERROR_LEN];
- failf(data, "schannel: failed to create certificate store: %s",
- Curl_winapi_strerror(GetLastError(), buffer, sizeof(buffer)));
- result = CURLE_SSL_CACERT_BADFILE;
+ /* try cache */
+ trust_store = Curl_schannel_get_cached_cert_store(cf, data);
+
+ if(trust_store) {
+ infof(data, "schannel: reusing certificate store from cache");
}
else {
- const struct curl_blob *ca_info_blob = conn_config->ca_info_blob;
- if(ca_info_blob) {
- result = add_certs_data_to_store(trust_store,
- (const char *)ca_info_blob->data,
- ca_info_blob->len,
- "(memory blob)",
- data);
+ /* Open the certificate store */
+ trust_store = CertOpenStore(CERT_STORE_PROV_MEMORY,
+ 0,
+ (HCRYPTPROV)NULL,
+ CERT_STORE_CREATE_NEW_FLAG,
+ NULL);
+ if(!trust_store) {
+ char buffer[STRERROR_LEN];
+ failf(data, "schannel: failed to create certificate store: %s",
+ Curl_winapi_strerror(GetLastError(), buffer, sizeof(buffer)));
+ result = CURLE_SSL_CACERT_BADFILE;
}
else {
- result = add_certs_file_to_store(trust_store,
- conn_config->CAfile,
- data);
+ const struct curl_blob *ca_info_blob = conn_config->ca_info_blob;
+ own_trust_store = trust_store;
+
+ if(ca_info_blob) {
+ result = add_certs_data_to_store(trust_store,
+ (const char *)ca_info_blob->data,
+ ca_info_blob->len,
+ "(memory blob)",
+ data);
+ }
+ else {
+ result = add_certs_file_to_store(trust_store,
+ conn_config->CAfile,
+ data);
+ }
+ if(result == CURLE_OK) {
+ if(Curl_schannel_set_cached_cert_store(cf, data, trust_store)) {
+ own_trust_store = NULL;
+ }
+ }
}
}
}
@@ -754,8 +770,8 @@ CURLcode Curl_verify_certificate(struct Curl_cfilter *cf,
CertFreeCertificateChainEngine(cert_chain_engine);
}
- if(trust_store) {
- CertCloseStore(trust_store, 0);
+ if(own_trust_store) {
+ CertCloseStore(own_trust_store, 0);
}
if(pChainContext)
diff --git a/libs/libcurl/src/vtls/sectransp.c b/libs/libcurl/src/vtls/sectransp.c
index d941119de9..26b673016e 100644
--- a/libs/libcurl/src/vtls/sectransp.c
+++ b/libs/libcurl/src/vtls/sectransp.c
@@ -46,8 +46,10 @@
#endif /* __clang__ */
#ifdef __GNUC__
+#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Waddress"
#pragma GCC diagnostic ignored "-Wundef"
+#pragma GCC diagnostic ignored "-Wunreachable-code"
#endif
#include <limits.h>
@@ -1013,7 +1015,7 @@ static CURLcode CopyCertSubject(struct Curl_easy *data,
}
else {
size_t cbuf_size = ((size_t)CFStringGetLength(c) * 4) + 1;
- cbuf = calloc(cbuf_size, 1);
+ cbuf = calloc(1, cbuf_size);
if(cbuf) {
if(!CFStringGetCString(c, cbuf, cbuf_size,
kCFStringEncodingUTF8)) {
@@ -1651,11 +1653,6 @@ static CURLcode sectransp_connect_step1(struct Curl_cfilter *cf,
const bool verifypeer = conn_config->verifypeer;
char * const ssl_cert = ssl_config->primary.clientcert;
const struct curl_blob *ssl_cert_blob = ssl_config->primary.cert_blob;
-#ifdef ENABLE_IPV6
- struct in6_addr addr;
-#else
- struct in_addr addr;
-#endif /* ENABLE_IPV6 */
char *ciphers;
OSStatus err = noErr;
#if CURL_BUILD_MAC
@@ -2003,13 +2000,9 @@ static CURLcode sectransp_connect_step1(struct Curl_cfilter *cf,
* Both hostname check and SNI require SSLSetPeerDomainName().
* Also: the verifyhost setting influences SNI usage */
if(conn_config->verifyhost) {
- size_t snilen;
- char *snihost = Curl_ssl_snihost(data, connssl->hostname, &snilen);
- if(!snihost) {
- failf(data, "Failed to set SNI");
- return CURLE_SSL_CONNECT_ERROR;
- }
- err = SSLSetPeerDomainName(backend->ssl_ctx, snihost, snilen);
+ char *server = connssl->peer.sni?
+ connssl->peer.sni : connssl->peer.hostname;
+ err = SSLSetPeerDomainName(backend->ssl_ctx, server, strlen(server));
if(err != noErr) {
failf(data, "SSL: SSLSetPeerDomainName() failed: OSStatus %d",
@@ -2017,11 +2010,7 @@ static CURLcode sectransp_connect_step1(struct Curl_cfilter *cf,
return CURLE_SSL_CONNECT_ERROR;
}
- if((Curl_inet_pton(AF_INET, connssl->hostname, &addr))
- #ifdef ENABLE_IPV6
- || (Curl_inet_pton(AF_INET6, connssl->hostname, &addr))
- #endif
- ) {
+ if(connssl->peer.is_ip_address) {
infof(data, "WARNING: using IP address, SNI is being disabled by "
"the OS.");
}
@@ -2079,7 +2068,7 @@ static CURLcode sectransp_connect_step1(struct Curl_cfilter *cf,
ssl_sessionid =
aprintf("%s:%d:%d:%s:%d",
ssl_cafile ? ssl_cafile : "(blob memory)",
- verifypeer, conn_config->verifyhost, connssl->hostname,
+ verifypeer, conn_config->verifyhost, connssl->peer.hostname,
connssl->port);
ssl_sessionid_len = strlen(ssl_sessionid);
@@ -2665,7 +2654,7 @@ check_handshake:
host name: */
case errSSLHostNameMismatch:
failf(data, "SSL certificate peer verification failed, the "
- "certificate did not match \"%s\"\n", connssl->dispname);
+ "certificate did not match \"%s\"\n", connssl->peer.dispname);
return CURLE_PEER_FAILED_VERIFICATION;
/* Problem with SSL / TLS negotiation */
@@ -2757,7 +2746,7 @@ check_handshake:
default:
/* May also return codes listed in Security Framework Result Codes */
failf(data, "Unknown SSL protocol error in connection to %s:%d",
- connssl->hostname, err);
+ connssl->peer.hostname, err);
break;
}
return CURLE_SSL_CONNECT_ERROR;
@@ -3415,7 +3404,6 @@ again:
}
*curlcode = CURLE_AGAIN;
return -1L;
- break;
/* errSSLClosedGraceful - server gracefully shut down the SSL session
errSSLClosedNoNotify - server hung up on us instead of sending a
@@ -3425,7 +3413,6 @@ again:
case errSSLClosedNoNotify:
*curlcode = CURLE_OK;
return 0;
- break;
/* The below is errSSLPeerAuthCompleted; it's not defined in
Leopard's headers */
@@ -3445,7 +3432,6 @@ again:
failf(data, "SSLRead() return error %d", err);
*curlcode = CURLE_RECV_ERROR;
return -1L;
- break;
}
}
return (ssize_t)processed;
@@ -3483,7 +3469,7 @@ const struct Curl_ssl Curl_ssl_sectransp = {
Curl_none_cert_status_request, /* cert_status_request */
sectransp_connect, /* connect */
sectransp_connect_nonblocking, /* connect_nonblocking */
- Curl_ssl_get_select_socks, /* getsock */
+ Curl_ssl_adjust_pollset, /* adjust_pollset */
sectransp_get_internals, /* get_internals */
sectransp_close, /* close_one */
Curl_none_close_all, /* close_all */
@@ -3500,6 +3486,10 @@ const struct Curl_ssl Curl_ssl_sectransp = {
sectransp_send, /* send data to encrypt */
};
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
+
#ifdef __clang__
#pragma clang diagnostic pop
#endif
diff --git a/libs/libcurl/src/vtls/vtls.c b/libs/libcurl/src/vtls/vtls.c
index 6a45ccb6d8..f37907c494 100644
--- a/libs/libcurl/src/vtls/vtls.c
+++ b/libs/libcurl/src/vtls/vtls.c
@@ -67,6 +67,7 @@
#include "warnless.h"
#include "curl_base64.h"
#include "curl_printf.h"
+#include "inet_pton.h"
#include "strdup.h"
/* The last #include files should be: */
@@ -131,9 +132,6 @@ static bool blobcmp(struct curl_blob *first, struct curl_blob *second)
}
#ifdef USE_SSL
-static const struct alpn_spec ALPN_SPEC_H10 = {
- { ALPN_HTTP_1_0 }, 1
-};
static const struct alpn_spec ALPN_SPEC_H11 = {
{ ALPN_HTTP_1_1 }, 1
};
@@ -147,51 +145,83 @@ static const struct alpn_spec *alpn_get_spec(int httpwant, bool use_alpn)
{
if(!use_alpn)
return NULL;
- if(httpwant == CURL_HTTP_VERSION_1_0)
- return &ALPN_SPEC_H10;
#ifdef USE_HTTP2
if(httpwant >= CURL_HTTP_VERSION_2)
return &ALPN_SPEC_H2_H11;
+#else
+ (void)httpwant;
#endif
+ /* Use the ALPN protocol "http/1.1" for HTTP/1.x.
+ Avoid "http/1.0" because some servers don't support it. */
return &ALPN_SPEC_H11;
}
#endif /* USE_SSL */
-bool
-Curl_ssl_config_matches(struct ssl_primary_config *data,
- struct ssl_primary_config *needle)
-{
- if((data->version == needle->version) &&
- (data->version_max == needle->version_max) &&
- (data->ssl_options == needle->ssl_options) &&
- (data->verifypeer == needle->verifypeer) &&
- (data->verifyhost == needle->verifyhost) &&
- (data->verifystatus == needle->verifystatus) &&
- blobcmp(data->cert_blob, needle->cert_blob) &&
- blobcmp(data->ca_info_blob, needle->ca_info_blob) &&
- blobcmp(data->issuercert_blob, needle->issuercert_blob) &&
- Curl_safecmp(data->CApath, needle->CApath) &&
- Curl_safecmp(data->CAfile, needle->CAfile) &&
- Curl_safecmp(data->issuercert, needle->issuercert) &&
- Curl_safecmp(data->clientcert, needle->clientcert) &&
+void Curl_ssl_easy_config_init(struct Curl_easy *data)
+{
+ /*
+ * libcurl 7.10 introduced SSL verification *by default*! This needs to be
+ * switched off unless wanted.
+ */
+ data->set.ssl.primary.verifypeer = TRUE;
+ data->set.ssl.primary.verifyhost = TRUE;
+ data->set.ssl.primary.sessionid = TRUE; /* session ID caching by default */
+#ifndef CURL_DISABLE_PROXY
+ data->set.proxy_ssl = data->set.ssl;
+#endif
+}
+
+static bool
+match_ssl_primary_config(struct Curl_easy *data,
+ struct ssl_primary_config *c1,
+ struct ssl_primary_config *c2)
+{
+ (void)data;
+ if((c1->version == c2->version) &&
+ (c1->version_max == c2->version_max) &&
+ (c1->ssl_options == c2->ssl_options) &&
+ (c1->verifypeer == c2->verifypeer) &&
+ (c1->verifyhost == c2->verifyhost) &&
+ (c1->verifystatus == c2->verifystatus) &&
+ blobcmp(c1->cert_blob, c2->cert_blob) &&
+ blobcmp(c1->ca_info_blob, c2->ca_info_blob) &&
+ blobcmp(c1->issuercert_blob, c2->issuercert_blob) &&
+ Curl_safecmp(c1->CApath, c2->CApath) &&
+ Curl_safecmp(c1->CAfile, c2->CAfile) &&
+ Curl_safecmp(c1->issuercert, c2->issuercert) &&
+ Curl_safecmp(c1->clientcert, c2->clientcert) &&
#ifdef USE_TLS_SRP
- !Curl_timestrcmp(data->username, needle->username) &&
- !Curl_timestrcmp(data->password, needle->password) &&
+ !Curl_timestrcmp(c1->username, c2->username) &&
+ !Curl_timestrcmp(c1->password, c2->password) &&
#endif
- strcasecompare(data->cipher_list, needle->cipher_list) &&
- strcasecompare(data->cipher_list13, needle->cipher_list13) &&
- strcasecompare(data->curves, needle->curves) &&
- strcasecompare(data->CRLfile, needle->CRLfile) &&
- strcasecompare(data->pinned_key, needle->pinned_key))
+ strcasecompare(c1->cipher_list, c2->cipher_list) &&
+ strcasecompare(c1->cipher_list13, c2->cipher_list13) &&
+ strcasecompare(c1->curves, c2->curves) &&
+ strcasecompare(c1->CRLfile, c2->CRLfile) &&
+ strcasecompare(c1->pinned_key, c2->pinned_key))
return TRUE;
return FALSE;
}
-bool
-Curl_clone_primary_ssl_config(struct ssl_primary_config *source,
- struct ssl_primary_config *dest)
+bool Curl_ssl_conn_config_match(struct Curl_easy *data,
+ struct connectdata *candidate,
+ bool proxy)
+{
+#ifndef CURL_DISABLE_PROXY
+ if(proxy)
+ return match_ssl_primary_config(data, &data->set.proxy_ssl.primary,
+ &candidate->proxy_ssl_config);
+#else
+ (void)proxy;
+#endif
+ return match_ssl_primary_config(data, &data->set.ssl.primary,
+ &candidate->ssl_config);
+}
+
+static bool clone_ssl_primary_config(struct ssl_primary_config *source,
+ struct ssl_primary_config *dest)
{
dest->version = source->version;
dest->version_max = source->version_max;
@@ -221,7 +251,7 @@ Curl_clone_primary_ssl_config(struct ssl_primary_config *source,
return TRUE;
}
-void Curl_free_primary_ssl_config(struct ssl_primary_config *sslc)
+static void Curl_free_primary_ssl_config(struct ssl_primary_config *sslc)
{
Curl_safefree(sslc->CApath);
Curl_safefree(sslc->CAfile);
@@ -241,6 +271,111 @@ void Curl_free_primary_ssl_config(struct ssl_primary_config *sslc)
#endif
}
+CURLcode Curl_ssl_easy_config_complete(struct Curl_easy *data)
+{
+ data->set.ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH];
+ data->set.ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE];
+ data->set.ssl.primary.CRLfile = data->set.str[STRING_SSL_CRLFILE];
+ data->set.ssl.primary.issuercert = data->set.str[STRING_SSL_ISSUERCERT];
+ data->set.ssl.primary.issuercert_blob = data->set.blobs[BLOB_SSL_ISSUERCERT];
+ data->set.ssl.primary.cipher_list =
+ data->set.str[STRING_SSL_CIPHER_LIST];
+ data->set.ssl.primary.cipher_list13 =
+ data->set.str[STRING_SSL_CIPHER13_LIST];
+ data->set.ssl.primary.pinned_key =
+ data->set.str[STRING_SSL_PINNEDPUBLICKEY];
+ data->set.ssl.primary.cert_blob = data->set.blobs[BLOB_CERT];
+ data->set.ssl.primary.ca_info_blob = data->set.blobs[BLOB_CAINFO];
+ data->set.ssl.primary.curves = data->set.str[STRING_SSL_EC_CURVES];
+#ifdef USE_TLS_SRP
+ data->set.ssl.primary.username = data->set.str[STRING_TLSAUTH_USERNAME];
+ data->set.ssl.primary.password = data->set.str[STRING_TLSAUTH_PASSWORD];
+#endif
+ data->set.ssl.cert_type = data->set.str[STRING_CERT_TYPE];
+ data->set.ssl.key = data->set.str[STRING_KEY];
+ data->set.ssl.key_type = data->set.str[STRING_KEY_TYPE];
+ data->set.ssl.key_passwd = data->set.str[STRING_KEY_PASSWD];
+ data->set.ssl.primary.clientcert = data->set.str[STRING_CERT];
+ data->set.ssl.key_blob = data->set.blobs[BLOB_KEY];
+
+#ifndef CURL_DISABLE_PROXY
+ data->set.proxy_ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH_PROXY];
+ data->set.proxy_ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE_PROXY];
+ data->set.proxy_ssl.primary.cipher_list =
+ data->set.str[STRING_SSL_CIPHER_LIST_PROXY];
+ data->set.proxy_ssl.primary.cipher_list13 =
+ data->set.str[STRING_SSL_CIPHER13_LIST_PROXY];
+ data->set.proxy_ssl.primary.pinned_key =
+ data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY];
+ data->set.proxy_ssl.primary.cert_blob = data->set.blobs[BLOB_CERT_PROXY];
+ data->set.proxy_ssl.primary.ca_info_blob =
+ data->set.blobs[BLOB_CAINFO_PROXY];
+ data->set.proxy_ssl.primary.issuercert =
+ data->set.str[STRING_SSL_ISSUERCERT_PROXY];
+ data->set.proxy_ssl.primary.issuercert_blob =
+ data->set.blobs[BLOB_SSL_ISSUERCERT_PROXY];
+ data->set.proxy_ssl.primary.CRLfile =
+ data->set.str[STRING_SSL_CRLFILE_PROXY];
+ data->set.proxy_ssl.cert_type = data->set.str[STRING_CERT_TYPE_PROXY];
+ data->set.proxy_ssl.key = data->set.str[STRING_KEY_PROXY];
+ data->set.proxy_ssl.key_type = data->set.str[STRING_KEY_TYPE_PROXY];
+ data->set.proxy_ssl.key_passwd = data->set.str[STRING_KEY_PASSWD_PROXY];
+ data->set.proxy_ssl.primary.clientcert = data->set.str[STRING_CERT_PROXY];
+ data->set.proxy_ssl.key_blob = data->set.blobs[BLOB_KEY_PROXY];
+#ifdef USE_TLS_SRP
+ data->set.proxy_ssl.primary.username =
+ data->set.str[STRING_TLSAUTH_USERNAME_PROXY];
+ data->set.proxy_ssl.primary.password =
+ data->set.str[STRING_TLSAUTH_PASSWORD_PROXY];
+#endif
+#endif /* CURL_DISABLE_PROXY */
+
+ return CURLE_OK;
+}
+
+CURLcode Curl_ssl_conn_config_init(struct Curl_easy *data,
+ struct connectdata *conn)
+{
+ /* Clone "primary" SSL configurations from the esay handle to
+ * the connection. They are used for connection cache matching and
+ * probably outlive the easy handle */
+ if(!clone_ssl_primary_config(&data->set.ssl.primary, &conn->ssl_config))
+ return CURLE_OUT_OF_MEMORY;
+#ifndef CURL_DISABLE_PROXY
+ if(!clone_ssl_primary_config(&data->set.proxy_ssl.primary,
+ &conn->proxy_ssl_config))
+ return CURLE_OUT_OF_MEMORY;
+#endif
+ return CURLE_OK;
+}
+
+void Curl_ssl_conn_config_cleanup(struct connectdata *conn)
+{
+ Curl_free_primary_ssl_config(&conn->ssl_config);
+#ifndef CURL_DISABLE_PROXY
+ Curl_free_primary_ssl_config(&conn->proxy_ssl_config);
+#endif
+}
+
+void Curl_ssl_conn_config_update(struct Curl_easy *data, bool for_proxy)
+{
+ /* May be called on an easy that has no connection yet */
+ if(data->conn) {
+ struct ssl_primary_config *src, *dest;
+#ifndef CURL_DISABLE_PROXY
+ src = for_proxy? &data->set.proxy_ssl.primary : &data->set.ssl.primary;
+ dest = for_proxy? &data->conn->proxy_ssl_config : &data->conn->ssl_config;
+#else
+ (void)for_proxy;
+ src = &data->set.ssl.primary;
+ dest = &data->conn->ssl_config;
+#endif
+ dest->verifyhost = src->verifyhost;
+ dest->verifypeer = src->verifypeer;
+ dest->verifystatus = src->verifystatus;
+ }
+}
+
#ifdef USE_SSL
static int multissl_setup(const struct Curl_ssl *backend);
#endif
@@ -432,7 +567,7 @@ bool Curl_ssl_getsessionid(struct Curl_cfilter *cf,
if(!check->sessionid)
/* not session ID means blank entry */
continue;
- if(strcasecompare(connssl->hostname, check->name) &&
+ if(strcasecompare(connssl->peer.hostname, check->name) &&
((!cf->conn->bits.conn_to_host && !check->conn_to_host) ||
(cf->conn->bits.conn_to_host && check->conn_to_host &&
strcasecompare(cf->conn->conn_to_host.name, check->conn_to_host))) &&
@@ -441,7 +576,7 @@ bool Curl_ssl_getsessionid(struct Curl_cfilter *cf,
cf->conn->conn_to_port == check->conn_to_port)) &&
(connssl->port == check->remote_port) &&
strcasecompare(cf->conn->handler->scheme, check->scheme) &&
- Curl_ssl_config_matches(conn_config, &check->ssl_config)) {
+ match_ssl_primary_config(data, conn_config, &check->ssl_config)) {
/* yes, we have a session ID! */
(*general_age)++; /* increase general age */
check->age = *general_age; /* set this as used in this age */
@@ -456,7 +591,8 @@ bool Curl_ssl_getsessionid(struct Curl_cfilter *cf,
DEBUGF(infof(data, "%s Session ID in cache for %s %s://%s:%d",
no_match? "Didn't find": "Found",
Curl_ssl_cf_is_proxy(cf) ? "proxy" : "host",
- cf->conn->handler->scheme, connssl->hostname, connssl->port));
+ cf->conn->handler->scheme, connssl->peer.hostname,
+ connssl->port));
return no_match;
}
@@ -532,7 +668,7 @@ CURLcode Curl_ssl_addsessionid(struct Curl_cfilter *cf,
(void)ssl_config;
DEBUGASSERT(ssl_config->primary.sessionid);
- clone_host = strdup(connssl->hostname);
+ clone_host = strdup(connssl->peer.hostname);
if(!clone_host)
return CURLE_OUT_OF_MEMORY; /* bail out */
@@ -590,7 +726,7 @@ CURLcode Curl_ssl_addsessionid(struct Curl_cfilter *cf,
store->remote_port = connssl->port;
store->scheme = cf->conn->handler->scheme;
- if(!Curl_clone_primary_ssl_config(conn_config, &store->ssl_config)) {
+ if(!clone_ssl_primary_config(conn_config, &store->ssl_config)) {
Curl_free_primary_ssl_config(&store->ssl_config);
store->sessionid = NULL; /* let caller free sessionid */
free(clone_host);
@@ -629,22 +765,21 @@ void Curl_ssl_close_all(struct Curl_easy *data)
Curl_ssl->close_all(data);
}
-int Curl_ssl_get_select_socks(struct Curl_cfilter *cf, struct Curl_easy *data,
- curl_socket_t *socks)
+void Curl_ssl_adjust_pollset(struct Curl_cfilter *cf, struct Curl_easy *data,
+ struct easy_pollset *ps)
{
- struct ssl_connect_data *connssl = cf->ctx;
- curl_socket_t sock = Curl_conn_cf_get_socket(cf->next, data);
-
- if(sock == CURL_SOCKET_BAD)
- return GETSOCK_BLANK;
-
- if(connssl->connecting_state == ssl_connect_2_writing) {
- /* we are only interested in writing */
- socks[0] = sock;
- return GETSOCK_WRITESOCK(0);
+ if(!cf->connected) {
+ struct ssl_connect_data *connssl = cf->ctx;
+ curl_socket_t sock = Curl_conn_cf_get_socket(cf->next, data);
+ if(sock != CURL_SOCKET_BAD) {
+ if(connssl->connecting_state == ssl_connect_2_writing) {
+ Curl_pollset_set_out_only(data, ps, sock);
+ }
+ else {
+ Curl_pollset_set_in_only(data, ps, sock);
+ }
+ }
}
- socks[0] = sock;
- return GETSOCK_READSOCK(0);
}
/* Selects an SSL crypto engine
@@ -786,32 +921,6 @@ CURLcode Curl_ssl_random(struct Curl_easy *data,
}
/*
- * 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(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
*/
@@ -1156,13 +1265,13 @@ static CURLcode multissl_connect_nonblocking(struct Curl_cfilter *cf,
return Curl_ssl->connect_nonblocking(cf, data, done);
}
-static int multissl_get_select_socks(struct Curl_cfilter *cf,
+static void multissl_adjust_pollset(struct Curl_cfilter *cf,
struct Curl_easy *data,
- curl_socket_t *socks)
+ struct easy_pollset *ps)
{
if(multissl_setup(NULL))
- return 0;
- return Curl_ssl->get_select_socks(cf, data, socks);
+ return;
+ Curl_ssl->adjust_pollset(cf, data, ps);
}
static void *multissl_get_internals(struct ssl_connect_data *connssl,
@@ -1214,7 +1323,7 @@ static const struct Curl_ssl Curl_ssl_multi = {
Curl_none_cert_status_request, /* cert_status_request */
multissl_connect, /* connect */
multissl_connect_nonblocking, /* connect_nonblocking */
- multissl_get_select_socks, /* getsock */
+ multissl_adjust_pollset, /* adjust_pollset */
multissl_get_internals, /* get_internals */
multissl_close, /* close_one */
Curl_none_close_all, /* close_all */
@@ -1409,12 +1518,14 @@ CURLsslset Curl_init_sslset_nolock(curl_sslbackend id, const char *name,
#ifdef USE_SSL
-static void free_hostname(struct ssl_connect_data *connssl)
+void Curl_ssl_peer_cleanup(struct ssl_peer *peer)
{
- if(connssl->dispname != connssl->hostname)
- free(connssl->dispname);
- free(connssl->hostname);
- connssl->hostname = connssl->dispname = NULL;
+ if(peer->dispname != peer->hostname)
+ free(peer->dispname);
+ free(peer->sni);
+ free(peer->hostname);
+ peer->hostname = peer->sni = peer->dispname = NULL;
+ peer->is_ip_address = FALSE;
}
static void cf_close(struct Curl_cfilter *cf, struct Curl_easy *data)
@@ -1423,12 +1534,26 @@ static void cf_close(struct Curl_cfilter *cf, struct Curl_easy *data)
if(connssl) {
Curl_ssl->close(cf, data);
connssl->state = ssl_connection_none;
- free_hostname(connssl);
+ Curl_ssl_peer_cleanup(&connssl->peer);
}
cf->connected = FALSE;
}
-static CURLcode reinit_hostname(struct Curl_cfilter *cf)
+static int is_ip_address(const char *hostname)
+{
+#ifdef ENABLE_IPV6
+ struct in6_addr addr;
+#else
+ struct in_addr addr;
+#endif
+ return (hostname && hostname[0] && (Curl_inet_pton(AF_INET, hostname, &addr)
+#ifdef ENABLE_IPV6
+ || Curl_inet_pton(AF_INET6, hostname, &addr)
+#endif
+ ));
+}
+
+CURLcode Curl_ssl_peer_init(struct ssl_peer *peer, struct Curl_cfilter *cf)
{
struct ssl_connect_data *connssl = cf->ctx;
const char *ehostname, *edispname;
@@ -1454,23 +1579,43 @@ static CURLcode reinit_hostname(struct Curl_cfilter *cf)
}
/* change if ehostname changed */
- if(ehostname && (!connssl->hostname
- || strcmp(ehostname, connssl->hostname))) {
- free_hostname(connssl);
- connssl->hostname = strdup(ehostname);
- if(!connssl->hostname) {
- free_hostname(connssl);
+ if(ehostname && (!peer->hostname
+ || strcmp(ehostname, peer->hostname))) {
+ Curl_ssl_peer_cleanup(peer);
+ peer->hostname = strdup(ehostname);
+ if(!peer->hostname) {
+ Curl_ssl_peer_cleanup(peer);
return CURLE_OUT_OF_MEMORY;
}
if(!edispname || !strcmp(ehostname, edispname))
- connssl->dispname = connssl->hostname;
+ peer->dispname = peer->hostname;
else {
- connssl->dispname = strdup(edispname);
- if(!connssl->dispname) {
- free_hostname(connssl);
+ peer->dispname = strdup(edispname);
+ if(!peer->dispname) {
+ Curl_ssl_peer_cleanup(peer);
return CURLE_OUT_OF_MEMORY;
}
}
+
+ peer->sni = NULL;
+ peer->is_ip_address = is_ip_address(peer->hostname)? TRUE : FALSE;
+ if(peer->hostname[0] && !peer->is_ip_address) {
+ /* not an IP address, normalize according to RCC 6066 ch. 3,
+ * max len of SNI is 2^16-1, no trailing dot */
+ size_t len = strlen(peer->hostname);
+ if(len && (peer->hostname[len-1] == '.'))
+ len--;
+ if(len < USHRT_MAX) {
+ peer->sni = calloc(1, len + 1);
+ if(!peer->sni) {
+ Curl_ssl_peer_cleanup(peer);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ Curl_strntolower(peer->sni, peer->hostname, len);
+ peer->sni[len] = 0;
+ }
+ }
+
}
connssl->port = eport;
return CURLE_OK;
@@ -1525,7 +1670,7 @@ static CURLcode ssl_cf_connect(struct Curl_cfilter *cf,
goto out;
*done = FALSE;
- result = reinit_hostname(cf);
+ result = Curl_ssl_peer_init(&connssl->peer, cf);
if(result)
goto out;
@@ -1599,22 +1744,17 @@ static ssize_t ssl_cf_recv(struct Curl_cfilter *cf,
return nread;
}
-static int ssl_cf_get_select_socks(struct Curl_cfilter *cf,
+static void ssl_cf_adjust_pollset(struct Curl_cfilter *cf,
struct Curl_easy *data,
- curl_socket_t *socks)
+ struct easy_pollset *ps)
{
struct cf_call_data save;
- int fds = GETSOCK_BLANK;
- if(!cf->next->connected) {
- fds = cf->next->cft->get_select_socks(cf->next, data, socks);
- }
- else if(!cf->connected) {
+ if(!cf->connected) {
CF_DATA_SAVE(save, cf, data);
- fds = Curl_ssl->get_select_socks(cf, data, socks);
+ Curl_ssl->adjust_pollset(cf, data, ps);
CF_DATA_RESTORE(cf, save);
}
- return fds;
}
static CURLcode ssl_cf_cntrl(struct Curl_cfilter *cf,
@@ -1705,7 +1845,7 @@ struct Curl_cftype Curl_cft_ssl = {
ssl_cf_connect,
ssl_cf_close,
Curl_cf_def_get_host,
- ssl_cf_get_select_socks,
+ ssl_cf_adjust_pollset,
ssl_cf_data_pending,
ssl_cf_send,
ssl_cf_recv,
@@ -1723,7 +1863,7 @@ struct Curl_cftype Curl_cft_ssl_proxy = {
ssl_cf_connect,
ssl_cf_close,
Curl_cf_def_get_host,
- ssl_cf_get_select_socks,
+ ssl_cf_adjust_pollset,
ssl_cf_data_pending,
ssl_cf_send,
ssl_cf_recv,
@@ -1837,6 +1977,16 @@ bool Curl_ssl_supports(struct Curl_easy *data, int option)
return (Curl_ssl->supports & option)? TRUE : FALSE;
}
+static struct Curl_cfilter *get_ssl_filter(struct Curl_cfilter *cf)
+{
+ for(; cf; cf = cf->next) {
+ if(cf->cft == &Curl_cft_ssl || cf->cft == &Curl_cft_ssl_proxy)
+ return cf;
+ }
+ return NULL;
+}
+
+
void *Curl_ssl_get_internals(struct Curl_easy *data, int sockindex,
CURLINFO info, int n)
{
@@ -1844,8 +1994,8 @@ void *Curl_ssl_get_internals(struct Curl_easy *data, int sockindex,
(void)n;
if(data->conn) {
struct Curl_cfilter *cf;
- /* get first filter in chain, if any is present */
- cf = Curl_ssl_cf_get_ssl(data->conn->cfilter[sockindex]);
+ /* get first SSL filter in chain, if any is present */
+ cf = get_ssl_filter(data->conn->cfilter[sockindex]);
if(cf) {
struct cf_call_data save;
CF_DATA_SAVE(save, cf, data);
@@ -1875,23 +2025,6 @@ CURLcode Curl_ssl_cfilter_remove(struct Curl_easy *data,
return result;
}
-static struct Curl_cfilter *get_ssl_cf_engaged(struct connectdata *conn,
- int sockindex)
-{
- struct Curl_cfilter *cf, *lowest_ssl_cf = NULL;
-
- for(cf = conn->cfilter[sockindex]; cf; cf = cf->next) {
- if(cf->cft == &Curl_cft_ssl || cf->cft == &Curl_cft_ssl_proxy) {
- lowest_ssl_cf = cf;
- if(cf->connected || (cf->next && cf->next->connected)) {
- /* connected or about to start */
- return cf;
- }
- }
- }
- return lowest_ssl_cf;
-}
-
bool Curl_ssl_cf_is_proxy(struct Curl_cfilter *cf)
{
return (cf->cft == &Curl_cft_ssl_proxy);
@@ -1908,17 +2041,6 @@ Curl_ssl_cf_get_config(struct Curl_cfilter *cf, struct Curl_easy *data)
#endif
}
-struct ssl_config_data *
-Curl_ssl_get_config(struct Curl_easy *data, int sockindex)
-{
- struct Curl_cfilter *cf;
-
- (void)data;
- DEBUGASSERT(data->conn);
- cf = get_ssl_cf_engaged(data->conn, sockindex);
- return cf? Curl_ssl_cf_get_config(cf, data) : &data->set.ssl;
-}
-
struct ssl_primary_config *
Curl_ssl_cf_get_primary_config(struct Curl_cfilter *cf)
{
@@ -1930,15 +2052,6 @@ Curl_ssl_cf_get_primary_config(struct Curl_cfilter *cf)
#endif
}
-struct Curl_cfilter *Curl_ssl_cf_get_ssl(struct Curl_cfilter *cf)
-{
- for(; cf; cf = cf->next) {
- if(cf->cft == &Curl_cft_ssl || cf->cft == &Curl_cft_ssl_proxy)
- return cf;
- }
- return NULL;
-}
-
CURLcode Curl_alpn_to_proto_buf(struct alpn_proto_buf *buf,
const struct alpn_spec *spec)
{
@@ -2005,10 +2118,6 @@ CURLcode Curl_alpn_set_negotiated(struct Curl_cfilter *cf,
!memcmp(ALPN_HTTP_1_1, proto, ALPN_HTTP_1_1_LENGTH)) {
*palpn = CURL_HTTP_VERSION_1_1;
}
- else if(proto_len == ALPN_HTTP_1_0_LENGTH &&
- !memcmp(ALPN_HTTP_1_0, proto, ALPN_HTTP_1_0_LENGTH)) {
- *palpn = CURL_HTTP_VERSION_1_0;
- }
#ifdef USE_HTTP2
else if(proto_len == ALPN_H2_LENGTH &&
!memcmp(ALPN_H2, proto, ALPN_H2_LENGTH)) {
diff --git a/libs/libcurl/src/vtls/vtls.h b/libs/libcurl/src/vtls/vtls.h
index 2ec6162296..111d17f32c 100644
--- a/libs/libcurl/src/vtls/vtls.h
+++ b/libs/libcurl/src/vtls/vtls.h
@@ -65,15 +65,54 @@ CURLsslset Curl_init_sslset_nolock(curl_sslbackend id, const char *name,
#define CURL_SHA256_DIGEST_LENGTH 32 /* fixed size */
#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,
- struct ssl_primary_config *dest);
-void Curl_free_primary_ssl_config(struct ssl_primary_config *sslc);
-
curl_sslbackend Curl_ssl_backend(void);
+/**
+ * Init ssl config for a new easy handle.
+ */
+void Curl_ssl_easy_config_init(struct Curl_easy *data);
+
+/**
+ * Init the `data->set.ssl` and `data->set.proxy_ssl` for
+ * connection matching use.
+ */
+CURLcode Curl_ssl_easy_config_complete(struct Curl_easy *data);
+
+/**
+ * Init SSL configs (main + proxy) for a new connection from the easy handle.
+ */
+CURLcode Curl_ssl_conn_config_init(struct Curl_easy *data,
+ struct connectdata *conn);
+
+/**
+ * Free allocated resources in SSL configs (main + proxy) for
+ * the given connection.
+ */
+void Curl_ssl_conn_config_cleanup(struct connectdata *conn);
+
+/**
+ * Return TRUE iff SSL configuration from `conn` is functionally the
+ * same as the one on `candidate`.
+ * @param proxy match the proxy SSL config or the main one
+ */
+bool Curl_ssl_conn_config_match(struct Curl_easy *data,
+ struct connectdata *candidate,
+ bool proxy);
+
+/* Update certain connection SSL config flags after they have
+ * been changed on the easy handle. Will work for `verifypeer`,
+ * `verifyhost` and `verifystatus`. */
+void Curl_ssl_conn_config_update(struct Curl_easy *data, bool for_proxy);
+
+/**
+ * Init SSL peer information for filter. Can be called repeatedly.
+ */
+CURLcode Curl_ssl_peer_init(struct ssl_peer *peer, struct Curl_cfilter *cf);
+/**
+ * Free all allocated data and reset peer information.
+ */
+void Curl_ssl_peer_cleanup(struct ssl_peer *peer);
+
#ifdef USE_SSL
int Curl_ssl_init(void);
void Curl_ssl_cleanup(void);
@@ -160,18 +199,6 @@ CURLcode Curl_cf_ssl_proxy_insert_after(struct Curl_cfilter *cf_at,
#endif /* !CURL_DISABLE_PROXY */
/**
- * Get the SSL configuration that is used on the connection.
- * This returns NULL if no SSL is configured.
- * Otherwise it returns the config of the first (highest) one that is
- * either connected, in handshake or about to start
- * (e.g. all filters below it are connected). If SSL filters are present,
- * but neither can start operating, return the config of the lowest one
- * that will first come into effect when connecting.
- */
-struct ssl_config_data *Curl_ssl_get_config(struct Curl_easy *data,
- int sockindex);
-
-/**
* True iff the underlying SSL implementation supports the option.
* Option is one of the defined SSLSUPP_* values.
* `data` maybe NULL for the features of the default implementation.
@@ -188,6 +215,18 @@ bool Curl_ssl_supports(struct Curl_easy *data, int ssl_option);
void *Curl_ssl_get_internals(struct Curl_easy *data, int sockindex,
CURLINFO info, int n);
+/**
+ * Get the ssl_config_data in `data` that is relevant for cfilter `cf`.
+ */
+struct ssl_config_data *Curl_ssl_cf_get_config(struct Curl_cfilter *cf,
+ struct Curl_easy *data);
+
+/**
+ * Get the primary config relevant for the filter from its connection.
+ */
+struct ssl_primary_config *
+ Curl_ssl_cf_get_primary_config(struct Curl_cfilter *cf);
+
extern struct Curl_cftype Curl_cft_ssl;
extern struct Curl_cftype Curl_cft_ssl_proxy;
@@ -209,8 +248,9 @@ extern struct Curl_cftype Curl_cft_ssl_proxy;
#define Curl_ssl_get_internals(a,b,c,d) NULL
#define Curl_ssl_supports(a,b) FALSE
#define Curl_ssl_cfilter_add(a,b,c) CURLE_NOT_BUILT_IN
-#define Curl_ssl_get_config(a,b) NULL
#define Curl_ssl_cfilter_remove(a,b) CURLE_OK
+#define Curl_ssl_cf_get_config(a,b) NULL
+#define Curl_ssl_cf_get_primary_config(a) NULL
#endif
#endif /* HEADER_CURL_VTLS_H */
diff --git a/libs/libcurl/src/vtls/vtls_int.h b/libs/libcurl/src/vtls/vtls_int.h
index 7a78a56cc7..858a0de8e7 100644
--- a/libs/libcurl/src/vtls/vtls_int.h
+++ b/libs/libcurl/src/vtls/vtls_int.h
@@ -32,8 +32,6 @@
/* see https://www.iana.org/assignments/tls-extensiontype-values/ */
#define ALPN_HTTP_1_1_LENGTH 8
#define ALPN_HTTP_1_1 "http/1.1"
-#define ALPN_HTTP_1_0_LENGTH 8
-#define ALPN_HTTP_1_0 "http/1.0"
#define ALPN_H2_LENGTH 2
#define ALPN_H2 "h2"
#define ALPN_H3_LENGTH 2
@@ -70,14 +68,14 @@ CURLcode Curl_alpn_set_negotiated(struct Curl_cfilter *cf,
struct ssl_connect_data {
ssl_connection_state state;
ssl_connect_state connecting_state;
- char *hostname; /* hostname for verification */
- char *dispname; /* display version of hostname */
+ struct ssl_peer peer;
const struct alpn_spec *alpn; /* ALPN to use or NULL for none */
void *backend; /* vtls backend specific props */
struct cf_call_data call_data; /* data handle used in current call */
struct curltime handshake_done; /* time when handshake finished */
int port; /* remote port at origin */
BIT(use_alpn); /* if ALPN shall be used in handshake */
+ BIT(reused_session); /* session-ID was reused for this */
};
@@ -118,14 +116,11 @@ struct Curl_ssl {
struct Curl_easy *data,
bool *done);
- /* If the SSL backend wants to read or write on this connection during a
- handshake, set socks[0] to the connection's FIRSTSOCKET, and return
- a bitmap indicating read or write with GETSOCK_WRITESOCK(0) or
- GETSOCK_READSOCK(0). Otherwise return GETSOCK_BLANK.
- Mandatory. */
- int (*get_select_socks)(struct Curl_cfilter *cf, struct Curl_easy *data,
- curl_socket_t *socks);
-
+ /* During handshake, adjust the pollset to include the socket
+ * for POLLOUT or POLLIN as needed.
+ * Mandatory. */
+ void (*adjust_pollset)(struct Curl_cfilter *cf, struct Curl_easy *data,
+ struct easy_pollset *ps);
void *(*get_internals)(struct ssl_connect_data *connssl, CURLINFO info);
void (*close)(struct Curl_cfilter *cf, struct Curl_easy *data);
void (*close_all)(struct Curl_easy *data);
@@ -169,25 +164,8 @@ CURLcode Curl_none_set_engine(struct Curl_easy *data, const char *engine);
CURLcode Curl_none_set_engine_default(struct Curl_easy *data);
struct curl_slist *Curl_none_engines_list(struct Curl_easy *data);
bool Curl_none_false_start(void);
-int Curl_ssl_get_select_socks(struct Curl_cfilter *cf, struct Curl_easy *data,
- curl_socket_t *socks);
-
-/**
- * Get the ssl_config_data in `data` that is relevant for cfilter `cf`.
- */
-struct ssl_config_data *Curl_ssl_cf_get_config(struct Curl_cfilter *cf,
- struct Curl_easy *data);
-
-/**
- * Get the primary config relevant for the filter from its connection.
- */
-struct ssl_primary_config *
- Curl_ssl_cf_get_primary_config(struct Curl_cfilter *cf);
-
-/**
- * Get the first SSL filter in the chain starting with `cf`, or NULL.
- */
-struct Curl_cfilter *Curl_ssl_cf_get_ssl(struct Curl_cfilter *cf);
+void Curl_ssl_adjust_pollset(struct Curl_cfilter *cf, struct Curl_easy *data,
+ struct easy_pollset *ps);
/**
* Get the SSL filter below the given one or NULL if there is none.
diff --git a/libs/libcurl/src/vtls/wolfssl.c b/libs/libcurl/src/vtls/wolfssl.c
index fad1f7a88e..32681520a0 100644
--- a/libs/libcurl/src/vtls/wolfssl.c
+++ b/libs/libcurl/src/vtls/wolfssl.c
@@ -480,6 +480,7 @@ wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
return CURLE_SSL_CONNECT_ERROR;
}
#endif
+ default:
break;
}
@@ -513,7 +514,7 @@ wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
}
}
-#ifndef NO_FILESYSTEM
+#if !defined(NO_FILESYSTEM) && defined(WOLFSSL_SYS_CA_CERTS)
/* load native CA certificates */
if(ssl_config->native_ca_store) {
if(wolfSSL_CTX_load_system_CA_certs(backend->ctx) != WOLFSSL_SUCCESS) {
@@ -608,24 +609,12 @@ wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
SSL_VERIFY_NONE, NULL);
#ifdef HAVE_SNI
- if(sni) {
- struct in_addr addr4;
-#ifdef ENABLE_IPV6
- struct in6_addr addr6;
-#endif
- size_t hostname_len = strlen(connssl->hostname);
-
- if((hostname_len < USHRT_MAX) &&
- !Curl_inet_pton(AF_INET, connssl->hostname, &addr4)
-#ifdef ENABLE_IPV6
- && !Curl_inet_pton(AF_INET6, connssl->hostname, &addr6)
-#endif
- ) {
- size_t snilen;
- char *snihost = Curl_ssl_snihost(data, connssl->hostname, &snilen);
- if(!snihost ||
- wolfSSL_CTX_UseSNI(backend->ctx, WOLFSSL_SNI_HOST_NAME, snihost,
- (unsigned short)snilen) != 1) {
+ if(sni && connssl->peer.sni) {
+ size_t sni_len = strlen(connssl->peer.sni);
+ if((sni_len < USHRT_MAX)) {
+ if(wolfSSL_CTX_UseSNI(backend->ctx, WOLFSSL_SNI_HOST_NAME,
+ connssl->peer.sni,
+ (unsigned short)sni_len) != 1) {
failf(data, "Failed to set SNI");
return CURLE_SSL_CONNECT_ERROR;
}
@@ -763,9 +752,9 @@ wolfssl_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data)
/* Enable RFC2818 checks */
if(conn_config->verifyhost) {
- char *snihost = Curl_ssl_snihost(data, connssl->hostname, NULL);
- if(!snihost ||
- (wolfSSL_check_domain_name(backend->handle, snihost) == SSL_FAILURE))
+ char *snihost = connssl->peer.sni?
+ connssl->peer.sni : connssl->peer.hostname;
+ if(wolfSSL_check_domain_name(backend->handle, snihost) == SSL_FAILURE)
return CURLE_SSL_CONNECT_ERROR;
}
@@ -813,7 +802,7 @@ wolfssl_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data)
else if(DOMAIN_NAME_MISMATCH == detail) {
#if 1
failf(data, " subject alt name(s) or common name do not match \"%s\"",
- connssl->dispname);
+ connssl->peer.dispname);
return CURLE_PEER_FAILED_VERIFICATION;
#else
/* When the wolfssl_check_domain_name() is used and you desire to
@@ -1398,7 +1387,7 @@ const struct Curl_ssl Curl_ssl_wolfssl = {
Curl_none_cert_status_request, /* cert_status_request */
wolfssl_connect, /* connect */
wolfssl_connect_nonblocking, /* connect_nonblocking */
- Curl_ssl_get_select_socks, /* getsock */
+ Curl_ssl_adjust_pollset, /* adjust_pollset */
wolfssl_get_internals, /* get_internals */
wolfssl_close, /* close_one */
Curl_none_close_all, /* close_all */
diff --git a/libs/libcurl/src/vtls/x509asn1.c b/libs/libcurl/src/vtls/x509asn1.c
index a695922816..0ce971c7ba 100644
--- a/libs/libcurl/src/vtls/x509asn1.c
+++ b/libs/libcurl/src/vtls/x509asn1.c
@@ -1317,16 +1317,16 @@ CURLcode Curl_verifyhost(struct Curl_cfilter *cf,
if(Curl_parseX509(&cert, beg, end))
return CURLE_PEER_FAILED_VERIFICATION;
- hostlen = strlen(connssl->hostname);
+ hostlen = strlen(connssl->peer.hostname);
/* Get the server IP address. */
#ifdef ENABLE_IPV6
if(cf->conn->bits.ipv6_ip &&
- Curl_inet_pton(AF_INET6, connssl->hostname, &addr))
+ Curl_inet_pton(AF_INET6, connssl->peer.hostname, &addr))
addrlen = sizeof(struct in6_addr);
else
#endif
- if(Curl_inet_pton(AF_INET, connssl->hostname, &addr))
+ if(Curl_inet_pton(AF_INET, connssl->peer.hostname, &addr))
addrlen = sizeof(struct in_addr);
/* Process extensions. */
@@ -1361,7 +1361,7 @@ CURLcode Curl_verifyhost(struct Curl_cfilter *cf,
name.beg, name.end);
if(len > 0 && (size_t)len == strlen(dnsname))
matched = Curl_cert_hostcheck(dnsname, (size_t)len,
- connssl->hostname, hostlen);
+ connssl->peer.hostname, hostlen);
else
matched = 0;
free(dnsname);
@@ -1421,7 +1421,7 @@ CURLcode Curl_verifyhost(struct Curl_cfilter *cf,
if(strlen(dnsname) != (size_t) len) /* Nul byte in string ? */
failf(data, "SSL: illegal cert name field");
else if(Curl_cert_hostcheck((const char *) dnsname,
- len, connssl->hostname, hostlen)) {
+ len, connssl->peer.hostname, hostlen)) {
infof(data, " common name: %s (matched)", dnsname);
free(dnsname);
return CURLE_OK;