mirror of
https://github.com/curl/curl.git
synced 2026-07-24 13:57:16 +03:00
vtls_config: adjust to origin
When a transfer goes against another origin than the initial one, do not add the following to the ssl configuration: client cert, client key, srp user/pass, pinned key. Closes #21695
This commit is contained in:
parent
4beffe7737
commit
d3391229b0
8 changed files with 550 additions and 421 deletions
|
|
@ -96,6 +96,7 @@ LIB_VTLS_CFILES = \
|
|||
vtls/schannel.c \
|
||||
vtls/schannel_verify.c \
|
||||
vtls/vtls.c \
|
||||
vtls/vtls_config.c \
|
||||
vtls/vtls_scache.c \
|
||||
vtls/vtls_spack.c \
|
||||
vtls/wolfssl.c \
|
||||
|
|
@ -113,6 +114,7 @@ LIB_VTLS_HFILES = \
|
|||
vtls/schannel.h \
|
||||
vtls/schannel_int.h \
|
||||
vtls/vtls.h \
|
||||
vtls/vtls_config.h \
|
||||
vtls/vtls_int.h \
|
||||
vtls/vtls_scache.h \
|
||||
vtls/vtls_spack.h \
|
||||
|
|
|
|||
|
|
@ -300,6 +300,10 @@ CURLcode Curl_close(struct Curl_easy **datap)
|
|||
Curl_netrc_cleanup(&data->state.netrc);
|
||||
#ifndef CURL_DISABLE_DIGEST_AUTH
|
||||
curlx_free(data->state.envproxy);
|
||||
#endif
|
||||
Curl_ssl_config_cleanup(&data->set.ssl.primary);
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
Curl_ssl_config_cleanup(&data->set.proxy_ssl.primary);
|
||||
#endif
|
||||
curlx_free(data);
|
||||
return CURLE_OK;
|
||||
|
|
@ -355,7 +359,9 @@ void Curl_init_userdefined(struct Curl_easy *data)
|
|||
|
||||
set->httpauth = CURLAUTH_BASIC; /* defaults to basic */
|
||||
|
||||
Curl_ssl_config_init(&data->set.ssl.primary);
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
Curl_ssl_config_init(&data->set.proxy_ssl.primary);
|
||||
set->proxyport = 0;
|
||||
set->proxytype = CURLPROXY_HTTP; /* defaults to HTTP proxy */
|
||||
set->proxyauth = CURLAUTH_BASIC; /* defaults to basic */
|
||||
|
|
@ -363,7 +369,6 @@ void Curl_init_userdefined(struct Curl_easy *data)
|
|||
set->socks5auth = CURLAUTH_BASIC | CURLAUTH_GSSAPI;
|
||||
#endif
|
||||
|
||||
Curl_ssl_easy_config_init(data);
|
||||
#ifndef CURL_DISABLE_DOH
|
||||
set->doh_verifyhost = TRUE;
|
||||
set->doh_verifypeer = TRUE;
|
||||
|
|
@ -2782,7 +2787,7 @@ static CURLcode url_find_or_create_conn(struct Curl_easy *data)
|
|||
#endif
|
||||
|
||||
/* Complete the easy's SSL configuration for connection cache matching */
|
||||
result = Curl_ssl_easy_config_complete(data);
|
||||
result = Curl_ssl_easy_config_complete(data, needle->origin);
|
||||
if(result)
|
||||
goto out;
|
||||
|
||||
|
|
|
|||
|
|
@ -69,6 +69,7 @@
|
|||
#include "request.h"
|
||||
#include "ratelimit.h"
|
||||
#include "netrc.h"
|
||||
#include "vtls/vtls_config.h"
|
||||
|
||||
/* On error return, the value of `pnwritten` has no meaning */
|
||||
typedef CURLcode (Curl_send)(struct Curl_easy *data, /* transfer */
|
||||
|
|
@ -140,62 +141,6 @@ typedef CURLcode (Curl_recv)(struct Curl_easy *data, /* transfer */
|
|||
((x) && ((x)->magic == CURLEASY_MAGIC_NUMBER))
|
||||
#endif
|
||||
|
||||
struct ssl_primary_config {
|
||||
char *CApath; /* certificate directory (does not work on Windows) */
|
||||
char *CAfile; /* certificate to verify peer against */
|
||||
char *issuercert; /* optional issuer certificate filename */
|
||||
char *clientcert;
|
||||
char *cipher_list; /* list of ciphers to use */
|
||||
char *cipher_list13; /* list of TLS 1.3 cipher suites to use */
|
||||
char *signature_algorithms; /* list of signature algorithms to use */
|
||||
char *pinned_key;
|
||||
char *CRLfile; /* CRL to check certificate revocation */
|
||||
char *cert_type; /* format for certificate (default: PEM) */
|
||||
char *key; /* private key filename */
|
||||
char *key_type; /* format for private key (default: PEM) */
|
||||
char *key_passwd; /* plain text private key password */
|
||||
struct curl_blob *cert_blob;
|
||||
struct curl_blob *ca_info_blob;
|
||||
struct curl_blob *issuercert_blob;
|
||||
struct curl_blob *key_blob;
|
||||
#ifdef USE_TLS_SRP
|
||||
char *username; /* TLS username (for, e.g., SRP) */
|
||||
char *password; /* TLS password (for, e.g., SRP) */
|
||||
#endif
|
||||
char *curves; /* list of curves to use */
|
||||
uint32_t version_max; /* max supported version the client wants to use */
|
||||
uint8_t ssl_options; /* the CURLOPT_SSL_OPTIONS bitmask */
|
||||
uint8_t version; /* what version the client wants to use */
|
||||
BIT(verifypeer); /* set TRUE if this is desired */
|
||||
BIT(verifyhost); /* set TRUE if CN/SAN must match hostname */
|
||||
BIT(verifystatus); /* set TRUE if certificate status must be checked */
|
||||
BIT(cache_session); /* cache session or not */
|
||||
};
|
||||
|
||||
struct ssl_config_data {
|
||||
struct ssl_primary_config primary;
|
||||
long certverifyresult; /* result from the certificate verification */
|
||||
curl_ssl_ctx_callback fsslctx; /* function to initialize SSL ctx */
|
||||
void *fsslctxp; /* parameter for call back */
|
||||
BIT(certinfo); /* gather lots of certificate info */
|
||||
BIT(earlydata); /* use TLS 1.3 early data */
|
||||
BIT(enable_beast); /* allow this flaw for interoperability's sake */
|
||||
BIT(no_revoke); /* disable SSL certificate revocation checks */
|
||||
BIT(no_partialchain); /* do not accept partial certificate chains */
|
||||
BIT(revoke_best_effort); /* ignore SSL revocation offline/missing revocation
|
||||
list errors */
|
||||
BIT(native_ca_store); /* use the native CA store of operating system */
|
||||
BIT(auto_client_cert); /* automatically locate and use a client
|
||||
certificate for authentication (Schannel) */
|
||||
BIT(custom_cafile); /* application has set custom CA file */
|
||||
BIT(custom_capath); /* application has set custom CA path */
|
||||
BIT(custom_cablob); /* application has set custom CA blob */
|
||||
};
|
||||
|
||||
struct ssl_general_config {
|
||||
int ca_cache_timeout; /* Certificate store cache timeout (seconds) */
|
||||
};
|
||||
|
||||
#ifdef USE_WINDOWS_SSPI
|
||||
#include "curl_sspi.h"
|
||||
#endif
|
||||
|
|
|
|||
325
lib/vtls/vtls.c
325
lib/vtls/vtls.c
|
|
@ -78,57 +78,6 @@
|
|||
#include <Security/Security.h>
|
||||
#endif
|
||||
|
||||
|
||||
#define CLONE_STRING(var) \
|
||||
do { \
|
||||
if(source->var) { \
|
||||
dest->var = curlx_strdup(source->var); \
|
||||
if(!dest->var) \
|
||||
return FALSE; \
|
||||
} \
|
||||
else \
|
||||
dest->var = NULL; \
|
||||
} while(0)
|
||||
|
||||
#define CLONE_BLOB(var) \
|
||||
do { \
|
||||
if(blobdup(&dest->var, source->var)) \
|
||||
return FALSE; \
|
||||
} while(0)
|
||||
|
||||
static CURLcode blobdup(struct curl_blob **dest, struct curl_blob *src)
|
||||
{
|
||||
DEBUGASSERT(dest);
|
||||
DEBUGASSERT(!*dest);
|
||||
if(src) {
|
||||
/* only if there is data to dupe! */
|
||||
struct curl_blob *d;
|
||||
d = curlx_malloc(sizeof(struct curl_blob) + src->len);
|
||||
if(!d)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
d->len = src->len;
|
||||
/* Always duplicate because the connection may survive longer than the
|
||||
handle that passed in the blob. */
|
||||
d->flags = CURL_BLOB_COPY;
|
||||
d->data = (void *)((char *)d + sizeof(struct curl_blob));
|
||||
memcpy(d->data, src->data, src->len);
|
||||
*dest = d;
|
||||
}
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
/* returns TRUE if the blobs are identical */
|
||||
static bool blobcmp(struct curl_blob *first, struct curl_blob *second)
|
||||
{
|
||||
if(!first && !second) /* both are NULL */
|
||||
return TRUE;
|
||||
if(!first || !second) /* one is NULL */
|
||||
return FALSE;
|
||||
if(first->len != second->len) /* different sizes */
|
||||
return FALSE;
|
||||
return !memcmp(first->data, second->data, first->len); /* same data */
|
||||
}
|
||||
|
||||
#ifdef USE_SSL
|
||||
#if !defined(CURL_DISABLE_HTTP) || !defined(CURL_DISABLE_PROXY)
|
||||
static const struct alpn_spec ALPN_SPEC_H11 = {
|
||||
|
|
@ -177,280 +126,6 @@ static const struct alpn_spec *alpn_get_spec(http_majors wanted,
|
|||
#endif /* !CURL_DISABLE_HTTP || !CURL_DISABLE_PROXY */
|
||||
#endif /* USE_SSL */
|
||||
|
||||
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.cache_session = TRUE; /* 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) &&
|
||||
blobcmp(c1->key_blob, c2->key_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(c1->username, c2->username) &&
|
||||
!Curl_timestrcmp(c1->password, c2->password) &&
|
||||
#endif
|
||||
curl_strequal(c1->cipher_list, c2->cipher_list) &&
|
||||
curl_strequal(c1->cipher_list13, c2->cipher_list13) &&
|
||||
curl_strequal(c1->curves, c2->curves) &&
|
||||
curl_strequal(c1->signature_algorithms, c2->signature_algorithms) &&
|
||||
Curl_safecmp(c1->CRLfile, c2->CRLfile) &&
|
||||
Curl_safecmp(c1->pinned_key, c2->pinned_key) &&
|
||||
curl_strequal(c1->cert_type, c2->cert_type) &&
|
||||
Curl_safecmp(c1->key, c2->key) &&
|
||||
curl_strequal(c1->key_type, c2->key_type) &&
|
||||
!Curl_timestrcmp(c1->key_passwd, c2->key_passwd))
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
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;
|
||||
dest->verifypeer = source->verifypeer;
|
||||
dest->verifyhost = source->verifyhost;
|
||||
dest->verifystatus = source->verifystatus;
|
||||
dest->cache_session = source->cache_session;
|
||||
dest->ssl_options = source->ssl_options;
|
||||
|
||||
CLONE_BLOB(cert_blob);
|
||||
CLONE_BLOB(ca_info_blob);
|
||||
CLONE_BLOB(issuercert_blob);
|
||||
CLONE_BLOB(key_blob);
|
||||
CLONE_STRING(CApath);
|
||||
CLONE_STRING(CAfile);
|
||||
CLONE_STRING(issuercert);
|
||||
CLONE_STRING(clientcert);
|
||||
CLONE_STRING(cipher_list);
|
||||
CLONE_STRING(cipher_list13);
|
||||
CLONE_STRING(pinned_key);
|
||||
CLONE_STRING(curves);
|
||||
CLONE_STRING(signature_algorithms);
|
||||
CLONE_STRING(CRLfile);
|
||||
CLONE_STRING(cert_type);
|
||||
CLONE_STRING(key);
|
||||
CLONE_STRING(key_type);
|
||||
CLONE_STRING(key_passwd);
|
||||
#ifdef USE_TLS_SRP
|
||||
CLONE_STRING(username);
|
||||
CLONE_STRING(password);
|
||||
#endif
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void free_primary_ssl_config(struct ssl_primary_config *sslc)
|
||||
{
|
||||
curlx_safefree(sslc->CApath);
|
||||
curlx_safefree(sslc->CAfile);
|
||||
curlx_safefree(sslc->issuercert);
|
||||
curlx_safefree(sslc->clientcert);
|
||||
curlx_safefree(sslc->cipher_list);
|
||||
curlx_safefree(sslc->cipher_list13);
|
||||
curlx_safefree(sslc->pinned_key);
|
||||
curlx_safefree(sslc->cert_blob);
|
||||
curlx_safefree(sslc->ca_info_blob);
|
||||
curlx_safefree(sslc->issuercert_blob);
|
||||
curlx_safefree(sslc->key_blob);
|
||||
curlx_safefree(sslc->curves);
|
||||
curlx_safefree(sslc->signature_algorithms);
|
||||
curlx_safefree(sslc->CRLfile);
|
||||
curlx_safefree(sslc->cert_type);
|
||||
curlx_safefree(sslc->key);
|
||||
curlx_safefree(sslc->key_type);
|
||||
curlx_safefree(sslc->key_passwd);
|
||||
#ifdef USE_TLS_SRP
|
||||
curlx_safefree(sslc->username);
|
||||
curlx_safefree(sslc->password);
|
||||
#endif
|
||||
}
|
||||
|
||||
CURLcode Curl_ssl_easy_config_complete(struct Curl_easy *data)
|
||||
{
|
||||
struct ssl_config_data *sslc = &data->set.ssl;
|
||||
#if defined(CURL_CA_PATH) || defined(CURL_CA_BUNDLE)
|
||||
struct UserDefined *set = &data->set;
|
||||
CURLcode result;
|
||||
#endif
|
||||
|
||||
if(Curl_ssl_backend() != CURLSSLBACKEND_SCHANNEL) {
|
||||
#if defined(USE_APPLE_SECTRUST) || defined(CURL_CA_NATIVE)
|
||||
if(!sslc->custom_capath && !sslc->custom_cafile && !sslc->custom_cablob)
|
||||
sslc->native_ca_store = TRUE;
|
||||
#endif
|
||||
#ifdef CURL_CA_PATH
|
||||
if(!sslc->custom_capath && !set->str[STRING_SSL_CAPATH]) {
|
||||
result = Curl_setstropt(&set->str[STRING_SSL_CAPATH], CURL_CA_PATH);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
#ifdef CURL_CA_BUNDLE
|
||||
if(!sslc->custom_cafile && !set->str[STRING_SSL_CAFILE]) {
|
||||
result = Curl_setstropt(&set->str[STRING_SSL_CAFILE], CURL_CA_BUNDLE);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
sslc->primary.CAfile = data->set.str[STRING_SSL_CAFILE];
|
||||
sslc->primary.CRLfile = data->set.str[STRING_SSL_CRLFILE];
|
||||
sslc->primary.CApath = data->set.str[STRING_SSL_CAPATH];
|
||||
sslc->primary.issuercert = data->set.str[STRING_SSL_ISSUERCERT];
|
||||
sslc->primary.issuercert_blob = data->set.blobs[BLOB_SSL_ISSUERCERT];
|
||||
sslc->primary.cipher_list = data->set.str[STRING_SSL_CIPHER_LIST];
|
||||
sslc->primary.cipher_list13 = data->set.str[STRING_SSL_CIPHER13_LIST];
|
||||
sslc->primary.signature_algorithms =
|
||||
data->set.str[STRING_SSL_SIGNATURE_ALGORITHMS];
|
||||
sslc->primary.pinned_key = data->set.str[STRING_SSL_PINNEDPUBLICKEY];
|
||||
sslc->primary.cert_blob = data->set.blobs[BLOB_CERT];
|
||||
sslc->primary.ca_info_blob = data->set.blobs[BLOB_CAINFO];
|
||||
sslc->primary.curves = data->set.str[STRING_SSL_EC_CURVES];
|
||||
#ifdef USE_TLS_SRP
|
||||
sslc->primary.username = data->set.str[STRING_TLSAUTH_USERNAME];
|
||||
sslc->primary.password = data->set.str[STRING_TLSAUTH_PASSWORD];
|
||||
#endif
|
||||
sslc->primary.cert_type = data->set.str[STRING_CERT_TYPE];
|
||||
sslc->primary.key = data->set.str[STRING_KEY];
|
||||
sslc->primary.key_type = data->set.str[STRING_KEY_TYPE];
|
||||
sslc->primary.key_passwd = data->set.str[STRING_KEY_PASSWD];
|
||||
sslc->primary.clientcert = data->set.str[STRING_CERT];
|
||||
sslc->primary.key_blob = data->set.blobs[BLOB_KEY];
|
||||
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
sslc = &data->set.proxy_ssl;
|
||||
if(Curl_ssl_backend() != CURLSSLBACKEND_SCHANNEL) {
|
||||
#if defined(USE_APPLE_SECTRUST) || defined(CURL_CA_NATIVE)
|
||||
if(!sslc->custom_capath && !sslc->custom_cafile && !sslc->custom_cablob)
|
||||
sslc->native_ca_store = TRUE;
|
||||
#endif
|
||||
#ifdef CURL_CA_PATH
|
||||
if(!sslc->custom_capath && !set->str[STRING_SSL_CAPATH_PROXY]) {
|
||||
result = Curl_setstropt(&set->str[STRING_SSL_CAPATH_PROXY],
|
||||
CURL_CA_PATH);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
#ifdef CURL_CA_BUNDLE
|
||||
if(!sslc->custom_cafile && !set->str[STRING_SSL_CAFILE_PROXY]) {
|
||||
result = Curl_setstropt(&set->str[STRING_SSL_CAFILE_PROXY],
|
||||
CURL_CA_BUNDLE);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
sslc->primary.CAfile = data->set.str[STRING_SSL_CAFILE_PROXY];
|
||||
sslc->primary.CApath = data->set.str[STRING_SSL_CAPATH_PROXY];
|
||||
sslc->primary.cipher_list = data->set.str[STRING_SSL_CIPHER_LIST_PROXY];
|
||||
sslc->primary.cipher_list13 = data->set.str[STRING_SSL_CIPHER13_LIST_PROXY];
|
||||
sslc->primary.pinned_key = data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY];
|
||||
sslc->primary.cert_blob = data->set.blobs[BLOB_CERT_PROXY];
|
||||
sslc->primary.ca_info_blob = data->set.blobs[BLOB_CAINFO_PROXY];
|
||||
sslc->primary.issuercert = data->set.str[STRING_SSL_ISSUERCERT_PROXY];
|
||||
sslc->primary.issuercert_blob = data->set.blobs[BLOB_SSL_ISSUERCERT_PROXY];
|
||||
sslc->primary.CRLfile = data->set.str[STRING_SSL_CRLFILE_PROXY];
|
||||
sslc->primary.cert_type = data->set.str[STRING_CERT_TYPE_PROXY];
|
||||
sslc->primary.key = data->set.str[STRING_KEY_PROXY];
|
||||
sslc->primary.key_type = data->set.str[STRING_KEY_TYPE_PROXY];
|
||||
sslc->primary.key_passwd = data->set.str[STRING_KEY_PASSWD_PROXY];
|
||||
sslc->primary.clientcert = data->set.str[STRING_CERT_PROXY];
|
||||
sslc->primary.key_blob = data->set.blobs[BLOB_KEY_PROXY];
|
||||
#ifdef USE_TLS_SRP
|
||||
sslc->primary.username = data->set.str[STRING_TLSAUTH_USERNAME_PROXY];
|
||||
sslc->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 easy 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)
|
||||
{
|
||||
free_primary_ssl_config(&conn->ssl_config);
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
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
|
||||
|
|
|
|||
|
|
@ -103,43 +103,6 @@ CURLsslset Curl_init_sslset_nolock(curl_sslbackend id, const char *name,
|
|||
|
||||
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 `data` 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. Works 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.
|
||||
*/
|
||||
|
|
|
|||
399
lib/vtls/vtls_config.c
Normal file
399
lib/vtls/vtls_config.c
Normal file
|
|
@ -0,0 +1,399 @@
|
|||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
* are also available at https://curl.se/docs/copyright.html.
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of the Software, and permit persons to whom the Software is
|
||||
* furnished to do so, under the terms of the COPYING file.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
* SPDX-License-Identifier: curl
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
/* This file is for implementing all "generic" SSL functions that all libcurl
|
||||
internals should use. It is then responsible for calling the proper
|
||||
"backend" function.
|
||||
|
||||
SSL-functions in libcurl should call functions in this source file, and not
|
||||
to any specific SSL-layer.
|
||||
|
||||
Curl_ssl_ - prefix for generic ones
|
||||
|
||||
Note that this source code uses the functions of the configured SSL
|
||||
backend via the global Curl_ssl instance.
|
||||
|
||||
"SSL/TLS Strong Encryption: An Introduction"
|
||||
https://httpd.apache.org/docs/2.0/ssl/ssl_intro.html
|
||||
*/
|
||||
|
||||
#include "curl_setup.h"
|
||||
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#include "urldata.h"
|
||||
#include "setopt.h"
|
||||
#include "strcase.h"
|
||||
#include "vtls/vtls.h"
|
||||
#include "vtls/vtls_config.h"
|
||||
|
||||
|
||||
#define CLONE_STRING(var) \
|
||||
do { \
|
||||
if(source->var) { \
|
||||
dest->var = curlx_strdup(source->var); \
|
||||
if(!dest->var) \
|
||||
return FALSE; \
|
||||
} \
|
||||
else \
|
||||
dest->var = NULL; \
|
||||
} while(0)
|
||||
|
||||
#define CLONE_BLOB(var) \
|
||||
do { \
|
||||
if(blobdup(&dest->var, source->var)) \
|
||||
return FALSE; \
|
||||
} while(0)
|
||||
|
||||
static CURLcode blobdup(struct curl_blob **dest, struct curl_blob *src)
|
||||
{
|
||||
DEBUGASSERT(dest);
|
||||
DEBUGASSERT(!*dest);
|
||||
if(src) {
|
||||
/* only if there is data to dupe! */
|
||||
struct curl_blob *d;
|
||||
d = curlx_malloc(sizeof(struct curl_blob) + src->len);
|
||||
if(!d)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
d->len = src->len;
|
||||
/* Always duplicate because the connection may survive longer than the
|
||||
handle that passed in the blob. */
|
||||
d->flags = CURL_BLOB_COPY;
|
||||
d->data = (void *)((char *)d + sizeof(struct curl_blob));
|
||||
memcpy(d->data, src->data, src->len);
|
||||
*dest = d;
|
||||
}
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
/* returns TRUE if the blobs are identical */
|
||||
static bool blobcmp(struct curl_blob *first, struct curl_blob *second)
|
||||
{
|
||||
if(!first && !second) /* both are NULL */
|
||||
return TRUE;
|
||||
if(!first || !second) /* one is NULL */
|
||||
return FALSE;
|
||||
if(first->len != second->len) /* different sizes */
|
||||
return FALSE;
|
||||
return !memcmp(first->data, second->data, first->len); /* same data */
|
||||
}
|
||||
|
||||
void Curl_ssl_config_init(struct ssl_primary_config *sslc)
|
||||
{
|
||||
/*
|
||||
* libcurl 7.10 introduced SSL verification *by default*! This needs to be
|
||||
* switched off unless wanted.
|
||||
*/
|
||||
sslc->verifypeer = TRUE;
|
||||
sslc->verifyhost = TRUE;
|
||||
sslc->cache_session = TRUE; /* caching by default */
|
||||
}
|
||||
|
||||
void Curl_ssl_config_cleanup(struct ssl_primary_config *sslc)
|
||||
{
|
||||
if(sslc->deep_copy) {
|
||||
curlx_safefree(sslc->CApath);
|
||||
curlx_safefree(sslc->CAfile);
|
||||
curlx_safefree(sslc->issuercert);
|
||||
curlx_safefree(sslc->clientcert);
|
||||
curlx_safefree(sslc->cipher_list);
|
||||
curlx_safefree(sslc->cipher_list13);
|
||||
curlx_safefree(sslc->pinned_key);
|
||||
curlx_safefree(sslc->cert_blob);
|
||||
curlx_safefree(sslc->ca_info_blob);
|
||||
curlx_safefree(sslc->issuercert_blob);
|
||||
curlx_safefree(sslc->key_blob);
|
||||
curlx_safefree(sslc->curves);
|
||||
curlx_safefree(sslc->signature_algorithms);
|
||||
curlx_safefree(sslc->CRLfile);
|
||||
curlx_safefree(sslc->cert_type);
|
||||
curlx_safefree(sslc->key);
|
||||
curlx_safefree(sslc->key_type);
|
||||
curlx_safefree(sslc->key_passwd);
|
||||
#ifdef USE_TLS_SRP
|
||||
curlx_safefree(sslc->username);
|
||||
curlx_safefree(sslc->password);
|
||||
#endif
|
||||
sslc->deep_copy = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
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) &&
|
||||
blobcmp(c1->key_blob, c2->key_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(c1->username, c2->username) &&
|
||||
!Curl_timestrcmp(c1->password, c2->password) &&
|
||||
#endif
|
||||
curl_strequal(c1->cipher_list, c2->cipher_list) &&
|
||||
curl_strequal(c1->cipher_list13, c2->cipher_list13) &&
|
||||
curl_strequal(c1->curves, c2->curves) &&
|
||||
curl_strequal(c1->signature_algorithms, c2->signature_algorithms) &&
|
||||
Curl_safecmp(c1->CRLfile, c2->CRLfile) &&
|
||||
Curl_safecmp(c1->pinned_key, c2->pinned_key) &&
|
||||
curl_strequal(c1->cert_type, c2->cert_type) &&
|
||||
Curl_safecmp(c1->key, c2->key) &&
|
||||
curl_strequal(c1->key_type, c2->key_type) &&
|
||||
!Curl_timestrcmp(c1->key_passwd, c2->key_passwd))
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
DEBUGASSERT(!dest->deep_copy);
|
||||
dest->deep_copy = TRUE;
|
||||
dest->version = source->version;
|
||||
dest->version_max = source->version_max;
|
||||
dest->verifypeer = source->verifypeer;
|
||||
dest->verifyhost = source->verifyhost;
|
||||
dest->verifystatus = source->verifystatus;
|
||||
dest->cache_session = source->cache_session;
|
||||
dest->ssl_options = source->ssl_options;
|
||||
|
||||
CLONE_BLOB(cert_blob);
|
||||
CLONE_BLOB(ca_info_blob);
|
||||
CLONE_BLOB(issuercert_blob);
|
||||
CLONE_STRING(CApath);
|
||||
CLONE_STRING(CAfile);
|
||||
CLONE_STRING(issuercert);
|
||||
CLONE_STRING(cipher_list);
|
||||
CLONE_STRING(cipher_list13);
|
||||
CLONE_STRING(pinned_key);
|
||||
CLONE_STRING(curves);
|
||||
CLONE_STRING(signature_algorithms);
|
||||
CLONE_STRING(CRLfile);
|
||||
/* SSL credentials: client certificate, SRP auth */
|
||||
CLONE_STRING(clientcert);
|
||||
CLONE_STRING(cert_type);
|
||||
CLONE_STRING(key);
|
||||
CLONE_STRING(key_type);
|
||||
CLONE_STRING(key_passwd);
|
||||
CLONE_BLOB(key_blob);
|
||||
#ifdef USE_TLS_SRP
|
||||
CLONE_STRING(username);
|
||||
CLONE_STRING(password);
|
||||
#endif
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
CURLcode Curl_ssl_easy_config_complete(struct Curl_easy *data,
|
||||
struct Curl_peer *origin)
|
||||
{
|
||||
struct ssl_config_data *sslc = &data->set.ssl;
|
||||
#if defined(CURL_CA_PATH) || defined(CURL_CA_BUNDLE)
|
||||
struct UserDefined *set = &data->set;
|
||||
CURLcode result;
|
||||
#endif
|
||||
|
||||
if(Curl_ssl_backend() != CURLSSLBACKEND_SCHANNEL) {
|
||||
#if defined(USE_APPLE_SECTRUST) || defined(CURL_CA_NATIVE)
|
||||
if(!sslc->custom_capath && !sslc->custom_cafile && !sslc->custom_cablob)
|
||||
sslc->native_ca_store = TRUE;
|
||||
#endif
|
||||
#ifdef CURL_CA_PATH
|
||||
if(!sslc->custom_capath && !set->str[STRING_SSL_CAPATH]) {
|
||||
result = Curl_setstropt(&set->str[STRING_SSL_CAPATH], CURL_CA_PATH);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
#ifdef CURL_CA_BUNDLE
|
||||
if(!sslc->custom_cafile && !set->str[STRING_SSL_CAFILE]) {
|
||||
result = Curl_setstropt(&set->str[STRING_SSL_CAFILE], CURL_CA_BUNDLE);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
sslc->primary.CAfile = data->set.str[STRING_SSL_CAFILE];
|
||||
sslc->primary.CRLfile = data->set.str[STRING_SSL_CRLFILE];
|
||||
sslc->primary.CApath = data->set.str[STRING_SSL_CAPATH];
|
||||
sslc->primary.cipher_list = data->set.str[STRING_SSL_CIPHER_LIST];
|
||||
sslc->primary.cipher_list13 = data->set.str[STRING_SSL_CIPHER13_LIST];
|
||||
sslc->primary.signature_algorithms =
|
||||
data->set.str[STRING_SSL_SIGNATURE_ALGORITHMS];
|
||||
sslc->primary.ca_info_blob = data->set.blobs[BLOB_CAINFO];
|
||||
sslc->primary.curves = data->set.str[STRING_SSL_EC_CURVES];
|
||||
/* Maybe these should not be used for another origin. But for
|
||||
* backwards compatibility, keep them in. */
|
||||
sslc->primary.issuercert = data->set.str[STRING_SSL_ISSUERCERT];
|
||||
sslc->primary.issuercert_blob = data->set.blobs[BLOB_SSL_ISSUERCERT];
|
||||
|
||||
if(Curl_peer_equal(data->state.initial_origin, origin)) {
|
||||
sslc->primary.pinned_key = data->set.str[STRING_SSL_PINNEDPUBLICKEY];
|
||||
sslc->primary.cert_blob = data->set.blobs[BLOB_CERT];
|
||||
sslc->primary.cert_type = data->set.str[STRING_CERT_TYPE];
|
||||
sslc->primary.key = data->set.str[STRING_KEY];
|
||||
sslc->primary.key_type = data->set.str[STRING_KEY_TYPE];
|
||||
sslc->primary.key_passwd = data->set.str[STRING_KEY_PASSWD];
|
||||
sslc->primary.clientcert = data->set.str[STRING_CERT];
|
||||
sslc->primary.key_blob = data->set.blobs[BLOB_KEY];
|
||||
#ifdef USE_TLS_SRP
|
||||
sslc->primary.username = data->set.str[STRING_TLSAUTH_USERNAME];
|
||||
sslc->primary.password = data->set.str[STRING_TLSAUTH_PASSWORD];
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
sslc->primary.pinned_key = NULL;
|
||||
sslc->primary.cert_blob = NULL;
|
||||
sslc->primary.cert_type = NULL;
|
||||
sslc->primary.key = NULL;
|
||||
sslc->primary.key_type = NULL;
|
||||
sslc->primary.key_passwd = NULL;
|
||||
sslc->primary.clientcert = NULL;
|
||||
sslc->primary.key_blob = NULL;
|
||||
#ifdef USE_TLS_SRP
|
||||
sslc->primary.username = NULL;
|
||||
sslc->primary.password = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
sslc = &data->set.proxy_ssl;
|
||||
if(Curl_ssl_backend() != CURLSSLBACKEND_SCHANNEL) {
|
||||
#if defined(USE_APPLE_SECTRUST) || defined(CURL_CA_NATIVE)
|
||||
if(!sslc->custom_capath && !sslc->custom_cafile && !sslc->custom_cablob)
|
||||
sslc->native_ca_store = TRUE;
|
||||
#endif
|
||||
#ifdef CURL_CA_PATH
|
||||
if(!sslc->custom_capath && !set->str[STRING_SSL_CAPATH_PROXY]) {
|
||||
result = Curl_setstropt(&set->str[STRING_SSL_CAPATH_PROXY],
|
||||
CURL_CA_PATH);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
#ifdef CURL_CA_BUNDLE
|
||||
if(!sslc->custom_cafile && !set->str[STRING_SSL_CAFILE_PROXY]) {
|
||||
result = Curl_setstropt(&set->str[STRING_SSL_CAFILE_PROXY],
|
||||
CURL_CA_BUNDLE);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
sslc->primary.CAfile = data->set.str[STRING_SSL_CAFILE_PROXY];
|
||||
sslc->primary.CApath = data->set.str[STRING_SSL_CAPATH_PROXY];
|
||||
sslc->primary.cipher_list = data->set.str[STRING_SSL_CIPHER_LIST_PROXY];
|
||||
sslc->primary.cipher_list13 = data->set.str[STRING_SSL_CIPHER13_LIST_PROXY];
|
||||
sslc->primary.pinned_key = data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY];
|
||||
sslc->primary.cert_blob = data->set.blobs[BLOB_CERT_PROXY];
|
||||
sslc->primary.ca_info_blob = data->set.blobs[BLOB_CAINFO_PROXY];
|
||||
sslc->primary.issuercert = data->set.str[STRING_SSL_ISSUERCERT_PROXY];
|
||||
sslc->primary.issuercert_blob = data->set.blobs[BLOB_SSL_ISSUERCERT_PROXY];
|
||||
sslc->primary.CRLfile = data->set.str[STRING_SSL_CRLFILE_PROXY];
|
||||
sslc->primary.cert_type = data->set.str[STRING_CERT_TYPE_PROXY];
|
||||
sslc->primary.key = data->set.str[STRING_KEY_PROXY];
|
||||
sslc->primary.key_type = data->set.str[STRING_KEY_TYPE_PROXY];
|
||||
sslc->primary.key_passwd = data->set.str[STRING_KEY_PASSWD_PROXY];
|
||||
sslc->primary.clientcert = data->set.str[STRING_CERT_PROXY];
|
||||
sslc->primary.key_blob = data->set.blobs[BLOB_KEY_PROXY];
|
||||
#ifdef USE_TLS_SRP
|
||||
sslc->primary.username = data->set.str[STRING_TLSAUTH_USERNAME_PROXY];
|
||||
sslc->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 easy 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_ssl_config_cleanup(&conn->ssl_config);
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
Curl_ssl_config_cleanup(&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;
|
||||
}
|
||||
}
|
||||
125
lib/vtls/vtls_config.h
Normal file
125
lib/vtls/vtls_config.h
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
#ifndef HEADER_CURL_VTLS_CONFIG_H
|
||||
#define HEADER_CURL_VTLS_CONFIG_H
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
* are also available at https://curl.se/docs/copyright.html.
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of the Software, and permit persons to whom the Software is
|
||||
* furnished to do so, under the terms of the COPYING file.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
* SPDX-License-Identifier: curl
|
||||
*
|
||||
***************************************************************************/
|
||||
#include "curl_setup.h"
|
||||
|
||||
struct Curl_easy;
|
||||
struct connectdata;
|
||||
struct Curl_peer;
|
||||
|
||||
struct ssl_primary_config {
|
||||
char *CApath; /* certificate directory (does not work on Windows) */
|
||||
char *CAfile; /* certificate to verify peer against */
|
||||
char *issuercert; /* optional issuer certificate filename */
|
||||
char *clientcert;
|
||||
char *cipher_list; /* list of ciphers to use */
|
||||
char *cipher_list13; /* list of TLS 1.3 cipher suites to use */
|
||||
char *signature_algorithms; /* list of signature algorithms to use */
|
||||
char *pinned_key;
|
||||
char *CRLfile; /* CRL to check certificate revocation */
|
||||
char *cert_type; /* format for certificate (default: PEM) */
|
||||
char *key; /* private key filename */
|
||||
char *key_type; /* format for private key (default: PEM) */
|
||||
char *key_passwd; /* plain text private key password */
|
||||
struct curl_blob *cert_blob;
|
||||
struct curl_blob *ca_info_blob;
|
||||
struct curl_blob *issuercert_blob;
|
||||
struct curl_blob *key_blob;
|
||||
#ifdef USE_TLS_SRP
|
||||
char *username; /* TLS username (for, e.g., SRP) */
|
||||
char *password; /* TLS password (for, e.g., SRP) */
|
||||
#endif
|
||||
char *curves; /* list of curves to use */
|
||||
uint32_t version_max; /* max supported version the client wants to use */
|
||||
uint8_t ssl_options; /* the CURLOPT_SSL_OPTIONS bitmask */
|
||||
uint8_t version; /* what version the client wants to use */
|
||||
BIT(verifypeer); /* set TRUE if this is desired */
|
||||
BIT(verifyhost); /* set TRUE if CN/SAN must match hostname */
|
||||
BIT(verifystatus); /* set TRUE if certificate status must be checked */
|
||||
BIT(cache_session); /* cache session or not */
|
||||
BIT(deep_copy); /* members are deep copies, eg. owned here */
|
||||
};
|
||||
|
||||
struct ssl_config_data {
|
||||
struct ssl_primary_config primary;
|
||||
long certverifyresult; /* result from the certificate verification */
|
||||
curl_ssl_ctx_callback fsslctx; /* function to initialize SSL ctx */
|
||||
void *fsslctxp; /* parameter for call back */
|
||||
BIT(certinfo); /* gather lots of certificate info */
|
||||
BIT(earlydata); /* use TLS 1.3 early data */
|
||||
BIT(enable_beast); /* allow this flaw for interoperability's sake */
|
||||
BIT(no_revoke); /* disable SSL certificate revocation checks */
|
||||
BIT(no_partialchain); /* do not accept partial certificate chains */
|
||||
BIT(revoke_best_effort); /* ignore SSL revocation offline/missing revocation
|
||||
list errors */
|
||||
BIT(native_ca_store); /* use the native CA store of operating system */
|
||||
BIT(auto_client_cert); /* automatically locate and use a client
|
||||
certificate for authentication (Schannel) */
|
||||
BIT(custom_cafile); /* application has set custom CA file */
|
||||
BIT(custom_capath); /* application has set custom CA path */
|
||||
BIT(custom_cablob); /* application has set custom CA blob */
|
||||
};
|
||||
|
||||
struct ssl_general_config {
|
||||
int ca_cache_timeout; /* Certificate store cache timeout (seconds) */
|
||||
};
|
||||
|
||||
void Curl_ssl_config_init(struct ssl_primary_config *sslc);
|
||||
void Curl_ssl_config_cleanup(struct ssl_primary_config *sslc);
|
||||
|
||||
/**
|
||||
* Init the `data->set.ssl` and `data->set.proxy_ssl` for
|
||||
* connection matching use.
|
||||
*/
|
||||
CURLcode Curl_ssl_easy_config_complete(struct Curl_easy *data,
|
||||
struct Curl_peer *origin);
|
||||
|
||||
/**
|
||||
* 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 `data` 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. Works for `verifypeer`,
|
||||
* `verifyhost` and `verifystatus`. */
|
||||
void Curl_ssl_conn_config_update(struct Curl_easy *data, bool for_proxy);
|
||||
|
||||
#endif /* HEADER_CURL_VTLS_CONFIG_H */
|
||||
|
|
@ -41,6 +41,8 @@ static CURLcode test_unit3303(const char *arg)
|
|||
static char alt_key[] = "other.key";
|
||||
static char alt_ktype[] = "DER";
|
||||
static char alt_ctype[] = "P12";
|
||||
struct Curl_peer *origin = NULL;
|
||||
CURLcode result;
|
||||
|
||||
curl_global_init(CURL_GLOBAL_ALL);
|
||||
curl = curl_easy_init();
|
||||
|
|
@ -49,13 +51,24 @@ static CURLcode test_unit3303(const char *arg)
|
|||
goto unit_test_abort;
|
||||
}
|
||||
|
||||
result = Curl_peer_create((struct Curl_easy *)curl,
|
||||
&Curl_scheme_https,
|
||||
"test.curl.se", 1234, &origin);
|
||||
if(result) {
|
||||
curl_easy_cleanup(curl);
|
||||
curl_global_cleanup();
|
||||
goto unit_test_abort;
|
||||
}
|
||||
Curl_peer_link(&((struct Curl_easy *)curl)->state.initial_origin, origin);
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_SSLCERT, "client.pem");
|
||||
curl_easy_setopt(curl, CURLOPT_SSLKEY, "client.key");
|
||||
curl_easy_setopt(curl, CURLOPT_KEYPASSWD, "secret");
|
||||
curl_easy_setopt(curl, CURLOPT_SSLCERTTYPE, "PEM");
|
||||
curl_easy_setopt(curl, CURLOPT_SSLKEYTYPE, "PEM");
|
||||
|
||||
if(Curl_ssl_easy_config_complete((struct Curl_easy *)curl)) {
|
||||
if(Curl_ssl_easy_config_complete((struct Curl_easy *)curl, origin)) {
|
||||
Curl_peer_unlink(&origin);
|
||||
curl_easy_cleanup(curl);
|
||||
curl_global_cleanup();
|
||||
goto unit_test_abort;
|
||||
|
|
@ -66,6 +79,7 @@ static CURLcode test_unit3303(const char *arg)
|
|||
if(conn)
|
||||
Curl_ssl_conn_config_cleanup(conn);
|
||||
curlx_free(conn);
|
||||
Curl_peer_unlink(&origin);
|
||||
curl_easy_cleanup(curl);
|
||||
curl_global_cleanup();
|
||||
goto unit_test_abort;
|
||||
|
|
@ -118,6 +132,7 @@ static CURLcode test_unit3303(const char *arg)
|
|||
Curl_ssl_conn_config_cleanup(conn);
|
||||
curlx_free(conn);
|
||||
curl_easy_cleanup(curl);
|
||||
Curl_peer_unlink(&origin);
|
||||
curl_global_cleanup();
|
||||
#endif /* USE_SSL */
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue