TRUE : FALSE;
/* Update the current connection ssl_config. */
- if(data->conn) {
- data->conn->ssl_config.verifypeer =
- data->set.ssl.primary.verifypeer;
- }
+ Curl_ssl_conn_config_update(data, FALSE);
break;
#ifndef CURL_DISABLE_DOH
case CURLOPT_DOH_SSL_VERIFYPEER:
(0 != va_arg(param, long))?TRUE:FALSE;
/* Update the current connection proxy_ssl_config. */
- if(data->conn) {
- data->conn->proxy_ssl_config.verifypeer =
- data->set.proxy_ssl.primary.verifypeer;
- }
+ Curl_ssl_conn_config_update(data, TRUE);
break;
#endif
case CURLOPT_SSL_VERIFYHOST:
data->set.ssl.primary.verifyhost = (bool)((arg & 3) ? TRUE : FALSE);
/* Update the current connection ssl_config. */
- if(data->conn) {
- data->conn->ssl_config.verifyhost =
- data->set.ssl.primary.verifyhost;
- }
+ Curl_ssl_conn_config_update(data, FALSE);
break;
#ifndef CURL_DISABLE_DOH
case CURLOPT_DOH_SSL_VERIFYHOST:
/* Treat both 1 and 2 as TRUE */
data->set.proxy_ssl.primary.verifyhost = (bool)((arg & 3)?TRUE:FALSE);
-
/* Update the current connection proxy_ssl_config. */
- if(data->conn) {
- data->conn->proxy_ssl_config.verifyhost =
- data->set.proxy_ssl.primary.verifyhost;
- }
+ Curl_ssl_conn_config_update(data, TRUE);
break;
#endif
case CURLOPT_SSL_VERIFYSTATUS:
TRUE : FALSE;
/* Update the current connection ssl_config. */
- if(data->conn) {
- data->conn->ssl_config.verifystatus =
- data->set.ssl.primary.verifystatus;
- }
+ Curl_ssl_conn_config_update(data, FALSE);
break;
#ifndef CURL_DISABLE_DOH
case CURLOPT_DOH_SSL_VERIFYSTATUS:
Curl_mime_initpart(&set->mimepost);
- /*
- * libcurl 7.10 introduced SSL verification *by default*! This needs to be
- * switched off unless wanted.
- */
+ Curl_ssl_easy_config_init(data);
#ifndef CURL_DISABLE_DOH
set->doh_verifyhost = TRUE;
set->doh_verifypeer = TRUE;
#endif
- set->ssl.primary.verifypeer = TRUE;
- set->ssl.primary.verifyhost = TRUE;
#ifdef USE_SSH
/* defaults to any auth type */
set->ssh_auth_types = CURLSSH_AUTH_DEFAULT;
set->new_directory_perms = 0755; /* Default permissions */
#endif
- set->ssl.primary.sessionid = TRUE; /* session ID caching enabled by
- default */
-#ifndef CURL_DISABLE_PROXY
- set->proxy_ssl = set->ssl;
-#endif
set->new_file_perms = 0644; /* Default permissions */
set->allowed_protocols = (curl_prot_t) CURLPROTO_ALL;
Curl_safefree(conn->socks_proxy.passwd);
Curl_safefree(conn->http_proxy.host.rawalloc); /* http proxy name buffer */
Curl_safefree(conn->socks_proxy.host.rawalloc); /* socks proxy name buffer */
- Curl_free_primary_ssl_config(&conn->proxy_ssl_config);
#endif
Curl_safefree(conn->user);
Curl_safefree(conn->passwd);
Curl_safefree(conn->hostname_resolve);
Curl_safefree(conn->secondaryhostname);
Curl_safefree(conn->localdev);
- Curl_free_primary_ssl_config(&conn->ssl_config);
+ Curl_ssl_conn_config_cleanup(conn);
#ifdef USE_UNIX_SOCKETS
Curl_safefree(conn->unix_domain_socket);
continue;
else if(needle->handler->flags&PROTOPT_SSL) {
/* use double layer ssl */
- if(!Curl_ssl_config_matches(&needle->proxy_ssl_config,
- &check->proxy_ssl_config))
+ if(!Curl_ssl_conn_config_match(data, needle, check, TRUE))
continue;
}
- else if(!Curl_ssl_config_matches(&needle->ssl_config,
- &check->ssl_config))
+ else if(!Curl_ssl_conn_config_match(data, needle, check, FALSE))
continue;
}
}
if(needle->handler->flags & PROTOPT_SSL) {
/* This is a SSL connection so verify that we're using the same
SSL options as well */
- if(!Curl_ssl_config_matches(&needle->ssl_config,
- &check->ssl_config)) {
+ if(!Curl_ssl_conn_config_match(data, needle, check, FALSE)) {
DEBUGF(infof(data,
"Connection #%" CURL_FORMAT_CURL_OFF_T
" has different SSL parameters, can't reuse",
#ifndef CURL_DISABLE_FTP
conn->bits.ftp_use_epsv = data->set.ftp_use_epsv;
conn->bits.ftp_use_eprt = data->set.ftp_use_eprt;
-#endif
- conn->ssl_config.verifystatus = data->set.ssl.primary.verifystatus;
- conn->ssl_config.verifypeer = data->set.ssl.primary.verifypeer;
- conn->ssl_config.verifyhost = data->set.ssl.primary.verifyhost;
- conn->ssl_config.ssl_options = data->set.ssl.primary.ssl_options;
-#ifndef CURL_DISABLE_PROXY
- conn->proxy_ssl_config.verifystatus =
- data->set.proxy_ssl.primary.verifystatus;
- conn->proxy_ssl_config.verifypeer = data->set.proxy_ssl.primary.verifypeer;
- conn->proxy_ssl_config.verifyhost = data->set.proxy_ssl.primary.verifyhost;
- conn->proxy_ssl_config.ssl_options = data->set.proxy_ssl.primary.ssl_options;
#endif
conn->ip_version = data->set.ipver;
conn->connect_only = data->set.connect_only;
conn->send[SECONDARYSOCKET] = Curl_conn_send;
conn->bits.tcp_fastopen = data->set.tcp_fastopen;
- /* Get a cloned copy of the SSL config situation stored in the
- connection struct. But to get this going nicely, we must first make
- sure that the strings in the master copy are pointing to the correct
- strings in the session handle strings array!
-
- Keep in mind that the pointers in the master copy are pointing to strings
- that will be freed as part of the Curl_easy struct, but all cloned
- copies will be separately allocated.
- */
- 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.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];
-
-#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];
-#endif
- data->set.ssl.primary.CRLfile = data->set.str[STRING_SSL_CRLFILE];
- 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];
-#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];
-#ifndef CURL_DISABLE_PROXY
- 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
- data->set.ssl.key_blob = data->set.blobs[BLOB_KEY];
-
- if(!Curl_clone_primary_ssl_config(&data->set.ssl.primary,
- &conn->ssl_config)) {
- result = CURLE_OUT_OF_MEMORY;
- goto out;
- }
-
-#ifndef CURL_DISABLE_PROXY
- if(!Curl_clone_primary_ssl_config(&data->set.proxy_ssl.primary,
- &conn->proxy_ssl_config)) {
- result = CURLE_OUT_OF_MEMORY;
+ /* Init the SSL configuration for the connection from settings in data */
+ result = Curl_ssl_conn_config_init(data, conn);
+ if(result)
goto out;
- }
-#endif
prune_dead_connections(data);
#include "http1.h"
#include "curl_msh3.h"
#include "socketpair.h"
+#include "vtls/vtls.h"
#include "vquic/vquic.h"
/* The last 3 #include files should be in this order */
struct Curl_easy *data)
{
struct cf_msh3_ctx *ctx = cf->ctx;
- bool verify = !!cf->conn->ssl_config.verifypeer;
+ struct ssl_primary_config *conn_config;
MSH3_ADDR addr = {0};
CURLcode result;
+ bool verify;
+
+ conn_config = Curl_ssl_cf_get_primary_config(cf);
+ if(!conn_config)
+ return CURLE_FAILED_INIT;
+ verify = !!conn_config->verifypeer;
memcpy(&addr, &ctx->addr.sa_addr, ctx->addr.addrlen);
MSH3_SET_PORT(&addr, (uint16_t)cf->conn->remote_port);
- if(verify && (cf->conn->ssl_config.CAfile || cf->conn->ssl_config.CApath)) {
+ if(verify && (conn_config->CAfile || conn_config->CApath)) {
/* TODO: need a way to provide trust anchors to MSH3 */
#ifdef DEBUGBUILD
/* we need this for our test cases to run */
struct Curl_cfilter *cf, struct Curl_easy *data)
{
struct cf_ngtcp2_ctx *ctx = cf->ctx;
- struct connectdata *conn = cf->conn;
+ struct ssl_primary_config *conn_config;
CURLcode result = CURLE_FAILED_INIT;
- SSL_CTX *ssl_ctx = SSL_CTX_new(TLS_method());
+ SSL_CTX *ssl_ctx = SSL_CTX_new(TLS_method());
if(!ssl_ctx) {
result = CURLE_OUT_OF_MEMORY;
goto out;
}
+ conn_config = Curl_ssl_cf_get_primary_config(cf);
+ if(!conn_config) {
+ result = CURLE_FAILED_INIT;
+ goto out;
+ }
#if defined(OPENSSL_IS_BORINGSSL) || defined(OPENSSL_IS_AWSLC)
if(ngtcp2_crypto_boringssl_configure_client_context(ssl_ctx) != 0) {
SSL_CTX_set_default_verify_paths(ssl_ctx);
{
- const char *curves = conn->ssl_config.curves ?
- conn->ssl_config.curves : QUIC_GROUPS;
+ const char *curves = conn_config->curves ?
+ conn_config->curves : QUIC_GROUPS;
if(!SSL_CTX_set1_curves_list(ssl_ctx, curves)) {
failf(data, "failed setting curves list for QUIC: '%s'", curves);
return CURLE_SSL_CIPHER;
#ifndef OPENSSL_IS_BORINGSSL
{
- const char *ciphers13 = conn->ssl_config.cipher_list13 ?
- conn->ssl_config.cipher_list13 : QUIC_CIPHERS;
+ const char *ciphers13 = conn_config->cipher_list13 ?
+ conn_config->cipher_list13 : QUIC_CIPHERS;
if(SSL_CTX_set_ciphersuites(ssl_ctx, ciphers13) != 1) {
failf(data, "failed setting QUIC cipher suite: %s", ciphers13);
return CURLE_SSL_CIPHER;
* fail to connect if the verification fails, or if it should continue
* anyway. In the latter case the result of the verification is checked with
* SSL_get_verify_result() below. */
- SSL_CTX_set_verify(ssl_ctx, conn->ssl_config.verifypeer ?
+ SSL_CTX_set_verify(ssl_ctx, conn_config->verifypeer ?
SSL_VERIFY_PEER : SSL_VERIFY_NONE, NULL);
/* give application a chance to interfere with SSL set up. */
SSL_CTX *ssl_ctx = ctx->sslctx;
const struct ssl_config_data *ssl_config;
- ssl_config = Curl_ssl_get_config(data, FIRSTSOCKET);
+ ssl_config = Curl_ssl_cf_get_config(cf, data);
DEBUGASSERT(ssl_config);
if(ssl_config->primary.clientcert || ssl_config->primary.cert_blob
struct Curl_easy *data)
{
struct cf_ngtcp2_ctx *ctx = cf->ctx;
+ struct ssl_primary_config *conn_config;
CURLcode result;
gnutls_datum_t alpn[2];
/* this will need some attention when HTTPS proxy over QUIC get fixed */
long * const pverifyresult = &data->set.ssl.certverifyresult;
int rc;
+ conn_config = Curl_ssl_cf_get_primary_config(cf);
+ if(!conn_config)
+ return CURLE_FAILED_INIT;
+
DEBUGASSERT(ctx->gtls == NULL);
ctx->gtls = calloc(1, sizeof(*(ctx->gtls)));
if(!ctx->gtls)
return CURLE_OUT_OF_MEMORY;
- result = gtls_client_init(data, &cf->conn->ssl_config, &data->set.ssl,
+ result = gtls_client_init(data, conn_config, &data->set.ssl,
hostname, ctx->gtls, pverifyresult);
if(result)
return result;
static CURLcode quic_ssl_ctx(WOLFSSL_CTX **pssl_ctx,
struct Curl_cfilter *cf, struct Curl_easy *data)
{
- struct connectdata *conn = cf->conn;
CURLcode result = CURLE_FAILED_INIT;
- WOLFSSL_CTX *ssl_ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method());
+ struct ssl_primary_config *conn_config;
+ WOLFSSL_CTX *ssl_ctx = NULL;
+ conn_config = Curl_ssl_cf_get_primary_config(cf);
+ if(!conn_config) {
+ result = CURLE_FAILED_INIT;
+ goto out;
+ }
+
+ ssl_ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method());
if(!ssl_ctx) {
result = CURLE_OUT_OF_MEMORY;
goto out;
if(ngtcp2_crypto_wolfssl_configure_client_context(ssl_ctx) != 0) {
failf(data, "ngtcp2_crypto_wolfssl_configure_client_context failed");
+ result = CURLE_FAILED_INIT;
goto out;
}
wolfSSL_CTX_set_default_verify_paths(ssl_ctx);
- if(wolfSSL_CTX_set_cipher_list(ssl_ctx, conn->ssl_config.cipher_list13 ?
- conn->ssl_config.cipher_list13 :
+ if(wolfSSL_CTX_set_cipher_list(ssl_ctx, conn_config->cipher_list13 ?
+ conn_config->cipher_list13 :
QUIC_CIPHERS) != 1) {
char error_buffer[256];
ERR_error_string_n(ERR_get_error(), error_buffer, sizeof(error_buffer));
goto out;
}
- if(wolfSSL_CTX_set1_groups_list(ssl_ctx, conn->ssl_config.curves ?
- conn->ssl_config.curves :
+ if(wolfSSL_CTX_set1_groups_list(ssl_ctx, conn_config->curves ?
+ conn_config->curves :
(char *)QUIC_GROUPS) != 1) {
failf(data, "wolfSSL failed to set curves");
goto out;
#endif
}
- if(conn->ssl_config.verifypeer) {
- const char * const ssl_cafile = conn->ssl_config.CAfile;
- const char * const ssl_capath = conn->ssl_config.CApath;
+ if(conn_config->verifypeer) {
+ const char * const ssl_cafile = conn_config->CAfile;
+ const char * const ssl_capath = conn_config->CApath;
wolfSSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER, NULL);
if(ssl_cafile || ssl_capath) {
struct Curl_easy *data)
{
struct cf_ngtcp2_ctx *ctx = cf->ctx;
+ struct ssl_primary_config *conn_config;
CURLcode result = CURLE_OK;
const char *hostname, *disp_hostname;
int port;
char *snihost;
+ conn_config = Curl_ssl_cf_get_primary_config(cf);
+ if(!conn_config)
+ return CURLE_FAILED_INIT;
+
Curl_conn_get_host(data, cf->sockindex, &hostname, &disp_hostname, &port);
snihost = Curl_ssl_snihost(data, hostname, NULL);
if(!snihost)
cf->conn->httpversion = 30;
cf->conn->bundle->multiuse = BUNDLE_MULTIPLEX;
- if(cf->conn->ssl_config.verifyhost) {
+ if(conn_config->verifyhost) {
#ifdef USE_OPENSSL
X509 *server_cert;
server_cert = SSL_get_peer_certificate(ctx->ssl);
return result;
#elif defined(USE_GNUTLS)
result = Curl_gtls_verifyserver(data, ctx->gtls->session,
- &cf->conn->ssl_config, &data->set.ssl,
+ conn_config, &data->set.ssl,
hostname, disp_hostname,
data->set.str[STRING_SSL_PINNEDPUBLICKEY]);
if(result)
struct Curl_easy *data)
{
struct cf_quiche_ctx *ctx = cf->ctx;
+ struct ssl_primary_config *conn_config;
+
+ conn_config = Curl_ssl_cf_get_primary_config(cf);
+ if(!conn_config)
+ return CURLE_FAILED_INIT;
if(!ctx->x509_store_setup) {
- if(cf->conn->ssl_config.verifypeer) {
- const char * const ssl_cafile = cf->conn->ssl_config.CAfile;
- const char * const ssl_capath = cf->conn->ssl_config.CApath;
+ if(conn_config->verifypeer) {
+ const char * const ssl_cafile = conn_config->CAfile;
+ const char * const ssl_capath = conn_config->CApath;
if(ssl_cafile || ssl_capath) {
SSL_CTX_set_verify(ctx->sslctx, SSL_VERIFY_PEER, NULL);
/* tell OpenSSL where to find CA certificates that are used to verify
static CURLcode quic_ssl_setup(struct Curl_cfilter *cf, struct Curl_easy *data)
{
struct cf_quiche_ctx *ctx = cf->ctx;
+ struct ssl_primary_config *conn_config;
unsigned char checkip[16];
- struct connectdata *conn = data->conn;
- const char *curves = conn->ssl_config.curves;
+
+ conn_config = Curl_ssl_cf_get_primary_config(cf);
+ if(!conn_config)
+ return CURLE_FAILED_INIT;
DEBUGASSERT(!ctx->sslctx);
ctx->sslctx = SSL_CTX_new(TLS_method());
SSL_CTX_set_keylog_callback(ctx->sslctx, keylog_callback);
}
- if(curves && !SSL_CTX_set1_curves_list(ctx->sslctx, curves)) {
- failf(data, "failed setting curves list for QUIC: '%s'", curves);
+ if(conn_config->curves &&
+ !SSL_CTX_set1_curves_list(ctx->sslctx, conn_config->curves)) {
+ failf(data, "failed setting curves list for QUIC: '%s'",
+ conn_config->curves);
return CURLE_SSL_CIPHER;
}
struct Curl_easy *data)
{
struct cf_quiche_ctx *ctx = cf->ctx;
+ struct ssl_primary_config *conn_config;
CURLcode result = CURLE_OK;
+ conn_config = Curl_ssl_cf_get_primary_config(cf);
+ if(!conn_config)
+ return CURLE_FAILED_INIT;
+
cf->conn->bits.multiplex = TRUE; /* at least potentially multiplexed */
cf->conn->httpversion = 30;
cf->conn->bundle->multiuse = BUNDLE_MULTIPLEX;
- if(cf->conn->ssl_config.verifyhost) {
+ if(conn_config->verifyhost) {
X509 *server_cert;
server_cert = SSL_get_peer_certificate(ctx->ssl);
if(!server_cert) {
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;
#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 *conn,
+ struct connectdata *candidate,
+ bool proxy)
+{
+ if(proxy)
+ return match_ssl_primary_config(data, &conn->proxy_ssl_config,
+ &candidate->proxy_ssl_config);
+ return match_ssl_primary_config(data, &conn->ssl_config,
+ &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;
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);
#endif
}
+static CURLcode Curl_ssl_init_ssl_config(struct Curl_easy *data,
+ struct ssl_primary_config *config)
+{
+ 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];
+
+ if(!clone_ssl_primary_config(&data->set.ssl.primary, config))
+ return CURLE_OUT_OF_MEMORY;
+ return CURLE_OK;
+}
+
+#ifndef CURL_DISABLE_PROXY
+static CURLcode
+Curl_ssl_init_proxy_ssl_config(struct Curl_easy *data,
+ struct ssl_primary_config *config)
+{
+ 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
+
+ if(!clone_ssl_primary_config(&data->set.proxy_ssl.primary, config))
+ return CURLE_OUT_OF_MEMORY;
+ return CURLE_OK;
+}
+#endif /* !CURL_DISABLE_PROXY */
+
+CURLcode Curl_ssl_conn_config_init(struct Curl_easy *data,
+ struct connectdata *conn)
+{
+ CURLcode result;
+ /* Get a cloned copy of the SSL config situation for use in
+ * the connection. `data` might have a shorter lifetime than `conn`*/
+ result = Curl_ssl_init_ssl_config(data, &conn->ssl_config);
+ if(result)
+ goto out;
+#ifndef CURL_DISABLE_PROXY
+ result = Curl_ssl_init_proxy_ssl_config(data, &conn->proxy_ssl_config);
+#endif
+out:
+ return result;
+}
+
+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;
+ src = for_proxy? &data->set.proxy_ssl.primary : &data->set.ssl.primary;
+ dest = for_proxy? &data->conn->proxy_ssl_config : &data->conn->ssl_config;
+ 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
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 */
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);
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)
{
(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);
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);
#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)
{
#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)
{
#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 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 *conn,
+ 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);
+
#ifdef USE_SSL
int Curl_ssl_init(void);
void Curl_ssl_cleanup(void);
struct Curl_easy *data);
#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.
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;
#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 */
void Curl_ssl_adjust_pollset(struct Curl_cfilter *cf, struct Curl_easy *data,
struct easy_pollset *ps);
-/**
- * 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);
-
/**
* Get the SSL filter below the given one or NULL if there is none.
*/