mirror of
https://github.com/curl/curl.git
synced 2026-08-01 07:58:10 +03:00
tls: fix incomplete mTLS config in conn reuse and session cache
cert_type, key, key_type, key_passwd and key_blob lived in ssl_config_data but not in ssl_primary_config, so they were invisible to match_ssl_primary_config() and to the TLS session cache peer key. Two easy handles sharing a connection pool could reuse each other's authenticated connections when they differed only on SSLKEY, SSLKEYTYPE, KEYPASSWD, SSLCERTTYPE or SSLKEYBLOB. The second handle would silently inherit the first handle's authenticated identity. Promote all five fields into ssl_primary_config so the conn-reuse predicate and session cache key cover the complete client credential set. Also replace the fixed ":CCERT" session cache marker with the actual clientcert path so sessions are not shared across different client certificates. Verified by test 3303 and 3304 Reported-By: Joshua Rogers (AISLE Research) Closes #21667
This commit is contained in:
parent
a4dca608e1
commit
7541ae569d
19 changed files with 512 additions and 81 deletions
|
|
@ -326,8 +326,8 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
|
|||
#ifdef LDAP_OPT_X_TLS
|
||||
if(conn->ssl_config.verifypeer) {
|
||||
/* OpenLDAP SDK supports BASE64 files. */
|
||||
if(data->set.ssl.cert_type &&
|
||||
!curl_strequal(data->set.ssl.cert_type, "PEM")) {
|
||||
if(data->set.ssl.primary.cert_type &&
|
||||
!curl_strequal(data->set.ssl.primary.cert_type, "PEM")) {
|
||||
failf(data, "LDAP local: ERROR OpenLDAP only supports PEM cert-type");
|
||||
result = CURLE_SSL_CERTPROBLEM;
|
||||
goto quit;
|
||||
|
|
|
|||
|
|
@ -150,9 +150,14 @@ struct ssl_primary_config {
|
|||
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) */
|
||||
|
|
@ -172,11 +177,6 @@ struct ssl_config_data {
|
|||
long certverifyresult; /* result from the certificate verification */
|
||||
curl_ssl_ctx_callback fsslctx; /* function to initialize ssl ctx */
|
||||
void *fsslctxp; /* parameter for call back */
|
||||
char *cert_type; /* format for certificate (default: PEM) */
|
||||
char *key; /* private key filename */
|
||||
struct curl_blob *key_blob;
|
||||
char *key_type; /* format for private key (default: PEM) */
|
||||
char *key_passwd; /* plain text private key password */
|
||||
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 */
|
||||
|
|
|
|||
|
|
@ -862,7 +862,7 @@ static int myssh_in_AUTH_PKEY_INIT(struct Curl_easy *data,
|
|||
/* Two choices, (1) private key was given on CMD,
|
||||
* (2) use the "default" keys. */
|
||||
if(data->set.str[STRING_SSH_PRIVATE_KEY]) {
|
||||
if(sshc->pubkey && !data->set.ssl.key_passwd) {
|
||||
if(sshc->pubkey && !data->set.ssl.primary.key_passwd) {
|
||||
rc = ssh_userauth_try_publickey(sshc->ssh_session, NULL, sshc->pubkey);
|
||||
if(rc == SSH_AUTH_AGAIN)
|
||||
return SSH_AGAIN;
|
||||
|
|
@ -875,7 +875,7 @@ static int myssh_in_AUTH_PKEY_INIT(struct Curl_easy *data,
|
|||
|
||||
rc = ssh_pki_import_privkey_file(data->
|
||||
set.str[STRING_SSH_PRIVATE_KEY],
|
||||
data->set.ssl.key_passwd, NULL,
|
||||
data->set.ssl.primary.key_passwd, NULL,
|
||||
NULL, &sshc->privkey);
|
||||
if(rc != SSH_OK) {
|
||||
failf(data, "Could not load private key file %s",
|
||||
|
|
@ -888,7 +888,7 @@ static int myssh_in_AUTH_PKEY_INIT(struct Curl_easy *data,
|
|||
}
|
||||
else {
|
||||
rc = ssh_userauth_publickey_auto(sshc->ssh_session, NULL,
|
||||
data->set.ssl.key_passwd);
|
||||
data->set.ssl.primary.key_passwd);
|
||||
if(rc == SSH_AUTH_AGAIN)
|
||||
return SSH_AGAIN;
|
||||
|
||||
|
|
|
|||
|
|
@ -1147,7 +1147,7 @@ static CURLcode ssh_state_pkey_init(struct Curl_easy *data,
|
|||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
sshc->passphrase = data->set.ssl.key_passwd;
|
||||
sshc->passphrase = data->set.ssl.primary.key_passwd;
|
||||
if(!sshc->passphrase)
|
||||
sshc->passphrase = "";
|
||||
|
||||
|
|
|
|||
|
|
@ -996,10 +996,11 @@ static CURLcode gtls_client_init(struct Curl_cfilter *cf,
|
|||
if(result)
|
||||
return result;
|
||||
}
|
||||
if(ssl_config->cert_type && curl_strequal(ssl_config->cert_type, "P12")) {
|
||||
if(ssl_config->primary.cert_type &&
|
||||
curl_strequal(ssl_config->primary.cert_type, "P12")) {
|
||||
rc = gnutls_certificate_set_x509_simple_pkcs12_file(
|
||||
gtls->shared_creds->creds, config->clientcert, GNUTLS_X509_FMT_DER,
|
||||
ssl_config->key_passwd ? ssl_config->key_passwd : "");
|
||||
ssl_config->primary.key_passwd ? ssl_config->primary.key_passwd : "");
|
||||
if(rc != GNUTLS_E_SUCCESS) {
|
||||
failf(data,
|
||||
"error reading X.509 potentially-encrypted key or certificate "
|
||||
|
|
@ -1017,14 +1018,15 @@ static CURLcode gtls_client_init(struct Curl_cfilter *cf,
|
|||
rc = gnutls_certificate_set_x509_key_file2(
|
||||
gtls->shared_creds->creds,
|
||||
config->clientcert,
|
||||
ssl_config->key ? ssl_config->key : config->clientcert,
|
||||
gnutls_do_file_type(ssl_config->cert_type),
|
||||
ssl_config->key_passwd,
|
||||
ssl_config->primary.key ? ssl_config->primary.key :
|
||||
config->clientcert,
|
||||
gnutls_do_file_type(ssl_config->primary.cert_type),
|
||||
ssl_config->primary.key_passwd,
|
||||
supported_key_encryption_algorithms);
|
||||
if(rc != GNUTLS_E_SUCCESS) {
|
||||
failf(data,
|
||||
"error reading X.509 %skey file: %s",
|
||||
ssl_config->key_passwd ? "potentially-encrypted " : "",
|
||||
ssl_config->primary.key_passwd ? "potentially-encrypted " : "",
|
||||
gnutls_strerror(rc));
|
||||
return CURLE_SSL_CONNECT_ERROR;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -486,7 +486,7 @@ static CURLcode mbed_load_cacert(struct Curl_cfilter *cf,
|
|||
const char * const ssl_capath = conn_config->CApath;
|
||||
#ifdef MBEDTLS_PEM_PARSE_C
|
||||
struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
|
||||
const char * const ssl_cert_type = ssl_config->cert_type;
|
||||
const char * const ssl_cert_type = ssl_config->primary.cert_type;
|
||||
#endif
|
||||
int ret = -1;
|
||||
char errorbuf[128];
|
||||
|
|
@ -581,7 +581,7 @@ static CURLcode mbed_load_clicert(struct Curl_cfilter *cf,
|
|||
char * const ssl_cert = ssl_config->primary.clientcert;
|
||||
const struct curl_blob *ssl_cert_blob = ssl_config->primary.cert_blob;
|
||||
#ifdef MBEDTLS_PEM_PARSE_C
|
||||
const char * const ssl_cert_type = ssl_config->cert_type;
|
||||
const char * const ssl_cert_type = ssl_config->primary.cert_type;
|
||||
#endif
|
||||
int ret = -1;
|
||||
char errorbuf[128];
|
||||
|
|
@ -662,12 +662,12 @@ static CURLcode mbed_load_privkey(struct Curl_cfilter *cf,
|
|||
|
||||
mbedtls_pk_init(&backend->pk);
|
||||
|
||||
if(ssl_config->key || ssl_config->key_blob) {
|
||||
if(ssl_config->key) {
|
||||
if(ssl_config->primary.key || ssl_config->primary.key_blob) {
|
||||
if(ssl_config->primary.key) {
|
||||
#ifdef MBEDTLS_FS_IO
|
||||
#if MBEDTLS_VERSION_NUMBER >= 0x04000000
|
||||
ret = mbedtls_pk_parse_keyfile(&backend->pk, ssl_config->key,
|
||||
ssl_config->key_passwd);
|
||||
ret = mbedtls_pk_parse_keyfile(&backend->pk, ssl_config->primary.key,
|
||||
ssl_config->primary.key_passwd);
|
||||
if(ret == 0 &&
|
||||
!(mbedtls_pk_can_do_psa(&backend->pk,
|
||||
PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH),
|
||||
|
|
@ -677,8 +677,8 @@ static CURLcode mbed_load_privkey(struct Curl_cfilter *cf,
|
|||
PSA_KEY_USAGE_SIGN_HASH)))
|
||||
ret = MBEDTLS_ERR_PK_TYPE_MISMATCH;
|
||||
#else
|
||||
ret = mbedtls_pk_parse_keyfile(&backend->pk, ssl_config->key,
|
||||
ssl_config->key_passwd,
|
||||
ret = mbedtls_pk_parse_keyfile(&backend->pk, ssl_config->primary.key,
|
||||
ssl_config->primary.key_passwd,
|
||||
mbedtls_ctr_drbg_random,
|
||||
&rng.drbg);
|
||||
if(ret == 0 && !(mbedtls_pk_can_do(&backend->pk, MBEDTLS_PK_RSA) ||
|
||||
|
|
@ -689,7 +689,7 @@ static CURLcode mbed_load_privkey(struct Curl_cfilter *cf,
|
|||
if(ret) {
|
||||
mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
|
||||
failf(data, "mbedTLS: error reading private key %s: (-0x%04X) %s",
|
||||
ssl_config->key, -ret, errorbuf);
|
||||
ssl_config->primary.key, -ret, errorbuf);
|
||||
return CURLE_SSL_CERTPROBLEM;
|
||||
}
|
||||
#else
|
||||
|
|
@ -698,8 +698,8 @@ static CURLcode mbed_load_privkey(struct Curl_cfilter *cf,
|
|||
#endif
|
||||
}
|
||||
else {
|
||||
const struct curl_blob *ssl_key_blob = ssl_config->key_blob;
|
||||
const char *passwd = ssl_config->key_passwd;
|
||||
const struct curl_blob *ssl_key_blob = ssl_config->primary.key_blob;
|
||||
const char *passwd = ssl_config->primary.key_passwd;
|
||||
/* Unfortunately, mbedtls_pk_parse_key() requires the data to be
|
||||
null-terminated if the data is PEM encoded (even when provided the
|
||||
exact length). */
|
||||
|
|
@ -933,7 +933,7 @@ static CURLcode mbed_configure_ssl(struct Curl_cfilter *cf,
|
|||
#endif
|
||||
);
|
||||
|
||||
if(ssl_config->key || ssl_config->key_blob) {
|
||||
if(ssl_config->primary.key || ssl_config->primary.key_blob) {
|
||||
mbedtls_ssl_conf_own_cert(&backend->config, &backend->clicert,
|
||||
&backend->pk);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3677,7 +3677,7 @@ CURLcode Curl_ossl_ctx_init(struct ossl_ctx *octx,
|
|||
struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, 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_cert_type = ssl_config->cert_type;
|
||||
const char * const ssl_cert_type = ssl_config->primary.cert_type;
|
||||
unsigned int ssl_version_min;
|
||||
char error_buffer[256];
|
||||
|
||||
|
|
@ -3841,8 +3841,9 @@ CURLcode Curl_ossl_ctx_init(struct ossl_ctx *octx,
|
|||
if(ssl_cert || ssl_cert_blob || ssl_cert_type) {
|
||||
result = client_cert(data, octx->ssl_ctx,
|
||||
ssl_cert, ssl_cert_blob, ssl_cert_type,
|
||||
ssl_config->key, ssl_config->key_blob,
|
||||
ssl_config->key_type, ssl_config->key_passwd);
|
||||
ssl_config->primary.key, ssl_config->primary.key_blob,
|
||||
ssl_config->primary.key_type,
|
||||
ssl_config->primary.key_passwd);
|
||||
if(result)
|
||||
/* failf() is already done in client_cert() */
|
||||
return result;
|
||||
|
|
|
|||
|
|
@ -845,14 +845,14 @@ init_config_builder_client_auth(struct Curl_easy *data,
|
|||
const struct rustls_certified_key *certified_key = NULL;
|
||||
CURLcode result = CURLE_OK;
|
||||
|
||||
if(conn_config->clientcert && !ssl_config->key) {
|
||||
if(conn_config->clientcert && !ssl_config->primary.key) {
|
||||
failf(data, "rustls: must provide key with certificate '%s'",
|
||||
conn_config->clientcert);
|
||||
return CURLE_SSL_CERTPROBLEM;
|
||||
}
|
||||
else if(!conn_config->clientcert && ssl_config->key) {
|
||||
else if(!conn_config->clientcert && ssl_config->primary.key) {
|
||||
failf(data, "rustls: must provide certificate with key '%s'",
|
||||
ssl_config->key);
|
||||
ssl_config->primary.key);
|
||||
return CURLE_SSL_CERTPROBLEM;
|
||||
}
|
||||
|
||||
|
|
@ -866,8 +866,9 @@ init_config_builder_client_auth(struct Curl_easy *data,
|
|||
goto cleanup;
|
||||
}
|
||||
|
||||
if(!read_file_into(ssl_config->key, &key_contents)) {
|
||||
failf(data, "rustls: failed to read key file: '%s'", ssl_config->key);
|
||||
if(!read_file_into(ssl_config->primary.key, &key_contents)) {
|
||||
failf(data, "rustls: failed to read key file: '%s'",
|
||||
ssl_config->primary.key);
|
||||
result = CURLE_SSL_CERTPROBLEM;
|
||||
goto cleanup;
|
||||
}
|
||||
|
|
@ -1066,7 +1067,7 @@ static CURLcode cr_init_backend(struct Curl_cfilter *cf,
|
|||
}
|
||||
}
|
||||
|
||||
if(conn_config->clientcert || ssl_config->key) {
|
||||
if(conn_config->clientcert || ssl_config->primary.key) {
|
||||
result = init_config_builder_client_auth(data,
|
||||
conn_config,
|
||||
ssl_config,
|
||||
|
|
|
|||
|
|
@ -415,8 +415,8 @@ static CURLcode get_client_cert(struct Curl_easy *data,
|
|||
}
|
||||
}
|
||||
|
||||
if((fInCert || blob) && data->set.ssl.cert_type &&
|
||||
!curl_strequal(data->set.ssl.cert_type, "P12")) {
|
||||
if((fInCert || blob) && data->set.ssl.primary.cert_type &&
|
||||
!curl_strequal(data->set.ssl.primary.cert_type, "P12")) {
|
||||
failf(data, "schannel: certificate format compatibility error "
|
||||
"for %s",
|
||||
blob ? "(memory blob)" : data->set.ssl.primary.clientcert);
|
||||
|
|
@ -466,15 +466,15 @@ static CURLcode get_client_cert(struct Curl_easy *data,
|
|||
datablob.pbData = (BYTE *)certdata;
|
||||
datablob.cbData = (DWORD)certsize;
|
||||
|
||||
if(data->set.ssl.key_passwd)
|
||||
pwd_len = strlen(data->set.ssl.key_passwd);
|
||||
if(data->set.ssl.primary.key_passwd)
|
||||
pwd_len = strlen(data->set.ssl.primary.key_passwd);
|
||||
pszPassword = (WCHAR *)curlx_malloc(sizeof(WCHAR) * (pwd_len + 1));
|
||||
if(pszPassword) {
|
||||
int str_w_len = 0;
|
||||
if(pwd_len > 0)
|
||||
str_w_len = MultiByteToWideChar(CP_UTF8,
|
||||
MB_ERR_INVALID_CHARS,
|
||||
data->set.ssl.key_passwd,
|
||||
data->set.ssl.primary.key_passwd,
|
||||
(int)pwd_len,
|
||||
pszPassword, (int)(pwd_len + 1));
|
||||
|
||||
|
|
|
|||
|
|
@ -205,6 +205,7 @@ static bool match_ssl_primary_config(struct Curl_easy *data,
|
|||
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) &&
|
||||
|
|
@ -218,7 +219,11 @@ static bool match_ssl_primary_config(struct Curl_easy *data,
|
|||
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_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;
|
||||
|
|
@ -253,6 +258,7 @@ static bool clone_ssl_primary_config(struct ssl_primary_config *source,
|
|||
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);
|
||||
|
|
@ -263,6 +269,10 @@ static bool clone_ssl_primary_config(struct ssl_primary_config *source,
|
|||
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);
|
||||
|
|
@ -283,9 +293,14 @@ static void free_primary_ssl_config(struct ssl_primary_config *sslc)
|
|||
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);
|
||||
|
|
@ -337,12 +352,12 @@ CURLcode Curl_ssl_easy_config_complete(struct Curl_easy *data)
|
|||
sslc->primary.username = data->set.str[STRING_TLSAUTH_USERNAME];
|
||||
sslc->primary.password = data->set.str[STRING_TLSAUTH_PASSWORD];
|
||||
#endif
|
||||
sslc->cert_type = data->set.str[STRING_CERT_TYPE];
|
||||
sslc->key = data->set.str[STRING_KEY];
|
||||
sslc->key_type = data->set.str[STRING_KEY_TYPE];
|
||||
sslc->key_passwd = data->set.str[STRING_KEY_PASSWD];
|
||||
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->key_blob = data->set.blobs[BLOB_KEY];
|
||||
sslc->primary.key_blob = data->set.blobs[BLOB_KEY];
|
||||
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
sslc = &data->set.proxy_ssl;
|
||||
|
|
@ -378,12 +393,12 @@ CURLcode Curl_ssl_easy_config_complete(struct Curl_easy *data)
|
|||
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->cert_type = data->set.str[STRING_CERT_TYPE_PROXY];
|
||||
sslc->key = data->set.str[STRING_KEY_PROXY];
|
||||
sslc->key_type = data->set.str[STRING_KEY_TYPE_PROXY];
|
||||
sslc->key_passwd = data->set.str[STRING_KEY_PASSWD_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->key_blob = data->set.blobs[BLOB_KEY_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];
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@
|
|||
struct Curl_ssl_scache_peer {
|
||||
char *ssl_peer_key; /* id for peer + relevant TLS configuration */
|
||||
char *clientcert;
|
||||
char *key_passwd;
|
||||
char *srp_username;
|
||||
char *srp_password;
|
||||
struct Curl_llist sessions;
|
||||
|
|
@ -123,6 +124,48 @@ out:
|
|||
return result;
|
||||
}
|
||||
|
||||
static CURLcode cf_ssl_peer_key_add_mtls(struct dynbuf *buf,
|
||||
struct ssl_primary_config *ssl,
|
||||
bool *is_local)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
if(ssl->clientcert && ssl->clientcert[0]) {
|
||||
result = cf_ssl_peer_key_add_path(buf, "CCERT", ssl->clientcert, is_local);
|
||||
if(result)
|
||||
goto out;
|
||||
}
|
||||
if(ssl->key && ssl->key[0]) {
|
||||
result = cf_ssl_peer_key_add_path(buf, "KEY", ssl->key, is_local);
|
||||
if(result)
|
||||
goto out;
|
||||
}
|
||||
if(ssl->key_blob) {
|
||||
result = cf_ssl_peer_key_add_hash(buf, "KEYBlob", ssl->key_blob);
|
||||
if(result)
|
||||
goto out;
|
||||
}
|
||||
if(ssl->cert_type && ssl->cert_type[0]) {
|
||||
size_t i;
|
||||
result = curlx_dyn_add(buf, ":CT-");
|
||||
for(i = 0; !result && ssl->cert_type[i]; i++) {
|
||||
char c = Curl_raw_toupper(ssl->cert_type[i]);
|
||||
result = curlx_dyn_addn(buf, &c, 1);
|
||||
}
|
||||
if(result)
|
||||
goto out;
|
||||
}
|
||||
if(ssl->key_type && ssl->key_type[0]) {
|
||||
size_t i;
|
||||
result = curlx_dyn_add(buf, ":KT-");
|
||||
for(i = 0; !result && ssl->key_type[i]; i++) {
|
||||
char c = Curl_raw_toupper(ssl->key_type[i]);
|
||||
result = curlx_dyn_addn(buf, &c, 1);
|
||||
}
|
||||
}
|
||||
out:
|
||||
return result;
|
||||
}
|
||||
|
||||
#define CURL_SSLS_LOCAL_SUFFIX ":L"
|
||||
#define CURL_SSLS_GLOBAL_SUFFIX ":G"
|
||||
|
||||
|
|
@ -134,12 +177,12 @@ static bool cf_ssl_peer_key_is_global(const char *peer_key)
|
|||
(peer_key[len - 2] == ':');
|
||||
}
|
||||
|
||||
CURLcode Curl_ssl_peer_key_make(struct Curl_cfilter *cf,
|
||||
const struct ssl_peer *peer,
|
||||
const char *tls_id,
|
||||
char **ppeer_key)
|
||||
CURLcode Curl_ssl_peer_key_build(struct ssl_primary_config *ssl,
|
||||
const struct ssl_peer *peer,
|
||||
const struct Curl_peer *via_peer,
|
||||
const char *tls_id,
|
||||
char **ppeer_key)
|
||||
{
|
||||
struct ssl_primary_config *ssl = Curl_ssl_cf_get_primary_config(cf);
|
||||
struct dynbuf buf;
|
||||
size_t key_len;
|
||||
bool is_local = FALSE;
|
||||
|
|
@ -188,10 +231,10 @@ CURLcode Curl_ssl_peer_key_make(struct Curl_cfilter *cf,
|
|||
goto out;
|
||||
}
|
||||
if(!ssl->verifypeer || !ssl->verifyhost) {
|
||||
if(cf->conn->via_peer) {
|
||||
if(via_peer) {
|
||||
result = curlx_dyn_addf(&buf, ":CHOST-%s:CPORT-%u",
|
||||
cf->conn->via_peer->hostname,
|
||||
cf->conn->via_peer->port);
|
||||
via_peer->hostname,
|
||||
via_peer->port);
|
||||
if(result)
|
||||
goto out;
|
||||
}
|
||||
|
|
@ -266,11 +309,9 @@ CURLcode Curl_ssl_peer_key_make(struct Curl_cfilter *cf,
|
|||
goto out;
|
||||
}
|
||||
|
||||
if(ssl->clientcert && ssl->clientcert[0]) {
|
||||
result = curlx_dyn_add(&buf, ":CCERT");
|
||||
if(result)
|
||||
goto out;
|
||||
}
|
||||
result = cf_ssl_peer_key_add_mtls(&buf, ssl, &is_local);
|
||||
if(result)
|
||||
goto out;
|
||||
#ifdef USE_TLS_SRP
|
||||
if(ssl->username || ssl->password) {
|
||||
result = curlx_dyn_add(&buf, ":SRP-AUTH");
|
||||
|
|
@ -301,6 +342,16 @@ out:
|
|||
return result;
|
||||
}
|
||||
|
||||
CURLcode Curl_ssl_peer_key_make(struct Curl_cfilter *cf,
|
||||
const struct ssl_peer *peer,
|
||||
const char *tls_id,
|
||||
char **ppeer_key)
|
||||
{
|
||||
struct ssl_primary_config *ssl = Curl_ssl_cf_get_primary_config(cf);
|
||||
return Curl_ssl_peer_key_build(ssl, peer, cf->conn->via_peer, tls_id,
|
||||
ppeer_key);
|
||||
}
|
||||
|
||||
struct Curl_ssl_scache {
|
||||
unsigned int magic;
|
||||
struct Curl_ssl_scache_peer *peers;
|
||||
|
|
@ -409,6 +460,7 @@ static void cf_ssl_scache_clear_peer(struct Curl_ssl_scache_peer *peer)
|
|||
}
|
||||
peer->sobj_free = NULL;
|
||||
curlx_safefree(peer->clientcert);
|
||||
curlx_safefree(peer->key_passwd);
|
||||
#ifdef USE_TLS_SRP
|
||||
curlx_safefree(peer->srp_username);
|
||||
curlx_safefree(peer->srp_password);
|
||||
|
|
@ -437,8 +489,8 @@ static void cf_ssl_cache_peer_update(struct Curl_ssl_scache_peer *peer)
|
|||
* - its peer key is not yet known, because sessions were
|
||||
* imported using only the salt+hmac
|
||||
* - the peer key is global, e.g. carrying no relative paths */
|
||||
peer->exportable = (!peer->clientcert && !peer->srp_username &&
|
||||
!peer->srp_password &&
|
||||
peer->exportable = (!peer->clientcert && !peer->key_passwd &&
|
||||
!peer->srp_username && !peer->srp_password &&
|
||||
(!peer->ssl_peer_key ||
|
||||
cf_ssl_peer_key_is_global(peer->ssl_peer_key)));
|
||||
}
|
||||
|
|
@ -447,6 +499,7 @@ static CURLcode
|
|||
cf_ssl_scache_peer_init(struct Curl_ssl_scache_peer *peer,
|
||||
const char *ssl_peer_key,
|
||||
const char *clientcert,
|
||||
const char *key_passwd,
|
||||
const char *srp_username,
|
||||
const char *srp_password,
|
||||
const unsigned char *salt,
|
||||
|
|
@ -475,6 +528,11 @@ cf_ssl_scache_peer_init(struct Curl_ssl_scache_peer *peer,
|
|||
if(!peer->clientcert)
|
||||
goto out;
|
||||
}
|
||||
if(key_passwd) {
|
||||
peer->key_passwd = curlx_strdup(key_passwd);
|
||||
if(!peer->key_passwd)
|
||||
goto out;
|
||||
}
|
||||
if(srp_username) {
|
||||
peer->srp_username = curlx_strdup(srp_username);
|
||||
if(!peer->srp_username)
|
||||
|
|
@ -616,7 +674,7 @@ static bool cf_ssl_scache_match_auth(struct Curl_ssl_scache_peer *peer,
|
|||
struct ssl_primary_config *conn_config)
|
||||
{
|
||||
if(!conn_config) {
|
||||
if(peer->clientcert)
|
||||
if(peer->clientcert || peer->key_passwd)
|
||||
return FALSE;
|
||||
#ifdef USE_TLS_SRP
|
||||
if(peer->srp_username || peer->srp_password)
|
||||
|
|
@ -626,6 +684,8 @@ static bool cf_ssl_scache_match_auth(struct Curl_ssl_scache_peer *peer,
|
|||
}
|
||||
else if(!Curl_safecmp(peer->clientcert, conn_config->clientcert))
|
||||
return FALSE;
|
||||
if(Curl_timestrcmp(peer->key_passwd, conn_config->key_passwd))
|
||||
return FALSE;
|
||||
#ifdef USE_TLS_SRP
|
||||
if(Curl_timestrcmp(peer->srp_username, conn_config->username) ||
|
||||
Curl_timestrcmp(peer->srp_password, conn_config->password))
|
||||
|
|
@ -754,6 +814,7 @@ static CURLcode cf_ssl_add_peer(struct Curl_easy *data,
|
|||
if(peer) {
|
||||
char buffer[64];
|
||||
const char *ccert = conn_config ? conn_config->clientcert : NULL;
|
||||
const char *kpasswd = conn_config ? conn_config->key_passwd : NULL;
|
||||
const char *username = NULL, *password = NULL;
|
||||
#ifdef USE_TLS_SRP
|
||||
username = conn_config ? conn_config->username : NULL;
|
||||
|
|
@ -765,7 +826,7 @@ static CURLcode cf_ssl_add_peer(struct Curl_easy *data,
|
|||
"cert-%p", conn_config->cert_blob->data);
|
||||
ccert = buffer; /* data is strduped by cf_ssl_scache_peer_init */
|
||||
}
|
||||
result = cf_ssl_scache_peer_init(peer, ssl_peer_key, ccert,
|
||||
result = cf_ssl_scache_peer_init(peer, ssl_peer_key, ccert, kpasswd,
|
||||
username, password, NULL, NULL);
|
||||
if(result)
|
||||
goto out;
|
||||
|
|
@ -1144,7 +1205,7 @@ CURLcode Curl_ssl_session_import(struct Curl_easy *data,
|
|||
if(!peer) {
|
||||
peer = cf_ssl_get_free_peer(scache);
|
||||
if(peer) {
|
||||
result = cf_ssl_scache_peer_init(peer, ssl_peer_key, NULL,
|
||||
result = cf_ssl_scache_peer_init(peer, ssl_peer_key, NULL, NULL,
|
||||
NULL, NULL, salt, hmac);
|
||||
if(result)
|
||||
goto out;
|
||||
|
|
|
|||
|
|
@ -66,6 +66,22 @@ CURLcode Curl_ssl_peer_key_make(struct Curl_cfilter *cf,
|
|||
const char *tls_id,
|
||||
char **ppeer_key);
|
||||
|
||||
/**
|
||||
* Like Curl_ssl_peer_key_make() but takes the primary config and peer
|
||||
* descriptors directly, without requiring a Curl_cfilter. Exposed for
|
||||
* unit testing.
|
||||
* @param ssl the primary SSL config to key on
|
||||
* @param peer the peer the filter wants to talk to
|
||||
* @param via_peer the connecting-through peer, or NULL
|
||||
* @param tls_id identifier of TLS implementation for sessions
|
||||
* @param ppeer_key on successful return, the key generated
|
||||
*/
|
||||
CURLcode Curl_ssl_peer_key_build(struct ssl_primary_config *ssl,
|
||||
const struct ssl_peer *peer,
|
||||
const struct Curl_peer *via_peer,
|
||||
const char *tls_id,
|
||||
char **ppeer_key);
|
||||
|
||||
/* Return if there is a session cache shall be used.
|
||||
* An ssl session might not be configured or not available for
|
||||
* "connect-only" transfers.
|
||||
|
|
|
|||
|
|
@ -920,10 +920,10 @@ static CURLcode wssl_client_cert(struct Curl_easy *data,
|
|||
#ifndef NO_FILESYSTEM
|
||||
if(ssl_config->primary.cert_blob || ssl_config->primary.clientcert) {
|
||||
const char *cert_file = ssl_config->primary.clientcert;
|
||||
const char *key_file = ssl_config->key;
|
||||
const char *key_file = ssl_config->primary.key;
|
||||
const struct curl_blob *cert_blob = ssl_config->primary.cert_blob;
|
||||
const struct curl_blob *key_blob = ssl_config->key_blob;
|
||||
int file_type = wssl_do_file_type(ssl_config->cert_type);
|
||||
const struct curl_blob *key_blob = ssl_config->primary.key_blob;
|
||||
int file_type = wssl_do_file_type(ssl_config->primary.cert_type);
|
||||
int rc;
|
||||
|
||||
switch(file_type) {
|
||||
|
|
@ -954,7 +954,7 @@ static CURLcode wssl_client_cert(struct Curl_easy *data,
|
|||
key_file = cert_file;
|
||||
}
|
||||
else
|
||||
file_type = wssl_do_file_type(ssl_config->key_type);
|
||||
file_type = wssl_do_file_type(ssl_config->primary.key_type);
|
||||
|
||||
rc = key_blob ?
|
||||
wolfSSL_CTX_use_PrivateKey_buffer(wctx->ssl_ctx, key_blob->data,
|
||||
|
|
@ -968,8 +968,8 @@ static CURLcode wssl_client_cert(struct Curl_easy *data,
|
|||
#else /* NO_FILESYSTEM */
|
||||
if(ssl_config->primary.cert_blob) {
|
||||
const struct curl_blob *cert_blob = ssl_config->primary.cert_blob;
|
||||
const struct curl_blob *key_blob = ssl_config->key_blob;
|
||||
int file_type = wssl_do_file_type(ssl_config->cert_type);
|
||||
const struct curl_blob *key_blob = ssl_config->primary.key_blob;
|
||||
int file_type = wssl_do_file_type(ssl_config->primary.cert_type);
|
||||
int rc;
|
||||
|
||||
switch(file_type) {
|
||||
|
|
@ -994,7 +994,7 @@ static CURLcode wssl_client_cert(struct Curl_easy *data,
|
|||
if(!key_blob)
|
||||
key_blob = cert_blob;
|
||||
else
|
||||
file_type = wssl_do_file_type(ssl_config->key_type);
|
||||
file_type = wssl_do_file_type(ssl_config->primary.key_type);
|
||||
|
||||
if(wolfSSL_CTX_use_PrivateKey_buffer(wctx->ssl_ctx, key_blob->data,
|
||||
(long)key_blob->len,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue