From 907a16c832d9ce0ffa7e9b2297548063095a7242 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 9 May 2022 23:13:53 +0200 Subject: [PATCH] tls: check more TLS details for connection reuse CVE-2022-27782 Reported-by: Harry Sintonen Bug: https://curl.se/docs/CVE-2022-27782.html Closes #8825 Upstream-Status: Backport [https://github.com/curl/curl/commit/f18af4f874cecab82a9797e8c7541e0990c7a64c] Signed-off-by: Robert Joslyn --- lib/setopt.c | 29 +++++++++++++++++------------ lib/url.c | 17 ++++++++++------- lib/urldata.h | 13 +++++++------ lib/vtls/gtls.c | 30 ++++++++++++++++-------------- lib/vtls/mbedtls.c | 2 +- lib/vtls/nss.c | 6 +++--- lib/vtls/openssl.c | 10 +++++----- lib/vtls/vtls.c | 1 + 8 files changed, 60 insertions(+), 48 deletions(-) diff --git a/lib/setopt.c b/lib/setopt.c index 4648c87..bebb2e4 100644 --- a/lib/setopt.c +++ b/lib/setopt.c @@ -2130,6 +2130,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) case CURLOPT_SSL_OPTIONS: arg = va_arg(param, long); + data->set.ssl.primary.ssl_options = (unsigned char)(arg & 0xff); data->set.ssl.enable_beast = (bool)((arg&CURLSSLOPT_ALLOW_BEAST) ? TRUE : FALSE); data->set.ssl.no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE); @@ -2139,6 +2140,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) #ifndef CURL_DISABLE_PROXY case CURLOPT_PROXY_SSL_OPTIONS: arg = va_arg(param, long); + data->set.proxy_ssl.primary.ssl_options = (unsigned char)(arg & 0xff); data->set.proxy_ssl.enable_beast = (bool)((arg&CURLSSLOPT_ALLOW_BEAST) ? TRUE : FALSE); data->set.proxy_ssl.no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE); @@ -2541,44 +2543,47 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) case CURLOPT_TLSAUTH_USERNAME: result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_USERNAME_ORIG], va_arg(param, char *)); - if(data->set.str[STRING_TLSAUTH_USERNAME_ORIG] && !data->set.ssl.authtype) - data->set.ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */ + if(data->set.str[STRING_TLSAUTH_USERNAME_ORIG] && + !data->set.ssl.primary.authtype) + data->set.ssl.primary.authtype = CURL_TLSAUTH_SRP; /* default to SRP */ break; case CURLOPT_PROXY_TLSAUTH_USERNAME: result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_USERNAME_PROXY], va_arg(param, char *)); if(data->set.str[STRING_TLSAUTH_USERNAME_PROXY] && - !data->set.proxy_ssl.authtype) - data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */ + !data->set.proxy_ssl.primary.authtype) + data->set.proxy_ssl.primary.authtype = CURL_TLSAUTH_SRP; /* default to + SRP */ break; case CURLOPT_TLSAUTH_PASSWORD: result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD_ORIG], va_arg(param, char *)); - if(data->set.str[STRING_TLSAUTH_USERNAME_ORIG] && !data->set.ssl.authtype) - data->set.ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */ + if(data->set.str[STRING_TLSAUTH_USERNAME_ORIG] && + !data->set.ssl.primary.authtype) + data->set.ssl.primary.authtype = CURL_TLSAUTH_SRP; /* default to SRP */ break; case CURLOPT_PROXY_TLSAUTH_PASSWORD: result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD_PROXY], va_arg(param, char *)); if(data->set.str[STRING_TLSAUTH_USERNAME_PROXY] && - !data->set.proxy_ssl.authtype) - data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */ + !data->set.proxy_ssl.primary.authtype) + data->set.proxy_ssl.primary.authtype = CURL_TLSAUTH_SRP; /* default */ break; case CURLOPT_TLSAUTH_TYPE: argptr = va_arg(param, char *); if(!argptr || strncasecompare(argptr, "SRP", strlen("SRP"))) - data->set.ssl.authtype = CURL_TLSAUTH_SRP; + data->set.ssl.primary.authtype = CURL_TLSAUTH_SRP; else - data->set.ssl.authtype = CURL_TLSAUTH_NONE; + data->set.ssl.primary.authtype = CURL_TLSAUTH_NONE; break; case CURLOPT_PROXY_TLSAUTH_TYPE: argptr = va_arg(param, char *); if(!argptr || strncasecompare(argptr, "SRP", strlen("SRP"))) - data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP; + data->set.proxy_ssl.primary.authtype = CURL_TLSAUTH_SRP; else - data->set.proxy_ssl.authtype = CURL_TLSAUTH_NONE; + data->set.proxy_ssl.primary.authtype = CURL_TLSAUTH_NONE; break; #endif #ifdef USE_ARES diff --git a/lib/url.c b/lib/url.c index efa3dc7..6518be9 100644 --- a/lib/url.c +++ b/lib/url.c @@ -482,7 +482,7 @@ CURLcode Curl_init_userdefined(struct Curl_easy *data) set->ssl.primary.verifypeer = TRUE; set->ssl.primary.verifyhost = TRUE; #ifdef USE_TLS_SRP - set->ssl.authtype = CURL_TLSAUTH_NONE; + set->ssl.primary.authtype = CURL_TLSAUTH_NONE; #endif set->ssh_auth_types = CURLSSH_AUTH_DEFAULT; /* defaults to any auth type */ @@ -3594,8 +3594,9 @@ static CURLcode create_conn(struct Curl_easy *data, data->set.proxy_ssl.primary.pinned_key = data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY]; - data->set.ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE_ORIG]; - data->set.proxy_ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE_PROXY]; + data->set.ssl.primary.CRLfile = data->set.str[STRING_SSL_CRLFILE_ORIG]; + data->set.proxy_ssl.primary.CRLfile = + data->set.str[STRING_SSL_CRLFILE_PROXY]; data->set.ssl.cert = data->set.str[STRING_CERT_ORIG]; data->set.proxy_ssl.cert = data->set.str[STRING_CERT_PROXY]; data->set.ssl.cert_type = data->set.str[STRING_CERT_TYPE_ORIG]; @@ -3609,10 +3610,12 @@ static CURLcode create_conn(struct Curl_easy *data, data->set.ssl.primary.clientcert = data->set.str[STRING_CERT_ORIG]; data->set.proxy_ssl.primary.clientcert = data->set.str[STRING_CERT_PROXY]; #ifdef USE_TLS_SRP - data->set.ssl.username = data->set.str[STRING_TLSAUTH_USERNAME_ORIG]; - data->set.proxy_ssl.username = data->set.str[STRING_TLSAUTH_USERNAME_PROXY]; - data->set.ssl.password = data->set.str[STRING_TLSAUTH_PASSWORD_ORIG]; - data->set.proxy_ssl.password = data->set.str[STRING_TLSAUTH_PASSWORD_PROXY]; + data->set.ssl.primary.username = data->set.str[STRING_TLSAUTH_USERNAME_ORIG]; + data->set.proxy_ssl.primary.username = + data->set.str[STRING_TLSAUTH_USERNAME_PROXY]; + data->set.ssl.primary.password = data->set.str[STRING_TLSAUTH_PASSWORD_ORIG]; + data->set.proxy_ssl.primary.password = + data->set.str[STRING_TLSAUTH_PASSWORD_PROXY]; #endif if(!Curl_clone_primary_ssl_config(&data->set.ssl.primary, diff --git a/lib/urldata.h b/lib/urldata.h index ab1b267..ad0ef8f 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -231,6 +231,13 @@ struct ssl_primary_config { char *cipher_list; /* list of ciphers to use */ char *cipher_list13; /* list of TLS 1.3 cipher suites to use */ char *pinned_key; + char *CRLfile; /* CRL to check certificate revocation */ + #ifdef USE_TLS_SRP + char *username; /* TLS username (for, e.g., SRP) */ + char *password; /* TLS password (for, e.g., SRP) */ + enum CURL_TLSAUTH authtype; /* TLS authentication type (default SRP) */ + #endif + unsigned char ssl_options; /* the CURLOPT_SSL_OPTIONS bitmask */ 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 */ @@ -240,7 +247,6 @@ struct ssl_primary_config { struct ssl_config_data { struct ssl_primary_config primary; long certverifyresult; /* result from the certificate verification */ - char *CRLfile; /* CRL to check certificate revocation */ curl_ssl_ctx_callback fsslctx; /* function to initialize ssl ctx */ void *fsslctxp; /* parameter for call back */ char *cert; /* client certificate file name */ @@ -248,11 +254,6 @@ struct ssl_config_data { char *key; /* private key file name */ char *key_type; /* format for private key (default: PEM) */ char *key_passwd; /* plain text private key password */ -#ifdef USE_TLS_SRP - char *username; /* TLS username (for, e.g., SRP) */ - char *password; /* TLS password (for, e.g., SRP) */ - enum CURL_TLSAUTH authtype; /* TLS authentication type (default SRP) */ -#endif BIT(certinfo); /* gather lots of certificate info */ BIT(falsestart); BIT(enable_beast); /* allow this flaw for interoperability's sake*/ diff --git a/lib/vtls/gtls.c b/lib/vtls/gtls.c index 3d0758d..92c301c 100644 --- a/lib/vtls/gtls.c +++ b/lib/vtls/gtls.c @@ -581,9 +581,10 @@ gtls_connect_step1(struct connectdata *conn, } #ifdef USE_TLS_SRP - if((SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP) && + if((SSL_SET_OPTION(primary.authtype) == CURL_TLSAUTH_SRP) && Curl_allow_auth_to_host(data)) { - infof(data, "Using TLS-SRP username: %s\n", SSL_SET_OPTION(username)); + infof(data, "Using TLS-SRP username: %s\n", + SSL_SET_OPTION(primary.username)); rc = gnutls_srp_allocate_client_credentials(&BACKEND->srp_client_cred); if(rc != GNUTLS_E_SUCCESS) { @@ -593,8 +594,8 @@ gtls_connect_step1(struct connectdata *conn, } rc = gnutls_srp_set_client_credentials(BACKEND->srp_client_cred, - SSL_SET_OPTION(username), - SSL_SET_OPTION(password)); + SSL_SET_OPTION(primary.username), + SSL_SET_OPTION(primary.password)); if(rc != GNUTLS_E_SUCCESS) { failf(data, "gnutls_srp_set_client_cred() failed: %s", gnutls_strerror(rc)); @@ -648,19 +649,19 @@ gtls_connect_step1(struct connectdata *conn, } #endif - if(SSL_SET_OPTION(CRLfile)) { + if(SSL_SET_OPTION(primary.CRLfile)) { /* set the CRL list file */ rc = gnutls_certificate_set_x509_crl_file(BACKEND->cred, - SSL_SET_OPTION(CRLfile), + SSL_SET_OPTION(primary.CRLfile), GNUTLS_X509_FMT_PEM); if(rc < 0) { failf(data, "error reading crl file %s (%s)", - SSL_SET_OPTION(CRLfile), gnutls_strerror(rc)); + SSL_SET_OPTION(primary.CRLfile), gnutls_strerror(rc)); return CURLE_SSL_CRL_BADFILE; } else infof(data, "found %d CRL in %s\n", - rc, SSL_SET_OPTION(CRLfile)); + rc, SSL_SET_OPTION(primary.CRLfile)); } /* Initialize TLS session as a client */ @@ -879,7 +880,7 @@ gtls_connect_step1(struct connectdata *conn, #ifdef USE_TLS_SRP /* put the credentials to the current session */ - if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP) { + if(SSL_SET_OPTION(primary.authtype) == CURL_TLSAUTH_SRP) { rc = gnutls_credentials_set(session, GNUTLS_CRD_SRP, BACKEND->srp_client_cred); if(rc != GNUTLS_E_SUCCESS) { @@ -1061,8 +1062,8 @@ gtls_connect_step3(struct connectdata *conn, SSL_CONN_CONFIG(verifyhost) || SSL_CONN_CONFIG(issuercert)) { #ifdef USE_TLS_SRP - if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP - && SSL_SET_OPTION(username) != NULL + if(SSL_SET_OPTION(primary.authtype) == CURL_TLSAUTH_SRP + && SSL_SET_OPTION(primary.username) != NULL && !SSL_CONN_CONFIG(verifypeer) && gnutls_cipher_get(session)) { /* no peer cert, but auth is ok if we have SRP user and cipher and no @@ -1116,7 +1117,8 @@ gtls_connect_step3(struct connectdata *conn, failf(data, "server certificate verification failed. CAfile: %s " "CRLfile: %s", SSL_CONN_CONFIG(CAfile) ? SSL_CONN_CONFIG(CAfile): "none", - SSL_SET_OPTION(CRLfile)?SSL_SET_OPTION(CRLfile):"none"); + SSL_SET_OPTION(primary.CRLfile) ? + SSL_SET_OPTION(primary.CRLfile) : "none"); return CURLE_PEER_FAILED_VERIFICATION; } else @@ -1703,8 +1705,8 @@ static int Curl_gtls_shutdown(struct connectdata *conn, int sockindex) gnutls_certificate_free_credentials(BACKEND->cred); #ifdef USE_TLS_SRP - if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP - && SSL_SET_OPTION(username) != NULL) + if(SSL_SET_OPTION(primary.authtype) == CURL_TLSAUTH_SRP + && SSL_SET_OPTION(primary.username) != NULL) gnutls_srp_free_client_credentials(BACKEND->srp_client_cred); #endif diff --git a/lib/vtls/mbedtls.c b/lib/vtls/mbedtls.c index 19df847..62d2b00 100644 --- a/lib/vtls/mbedtls.c +++ b/lib/vtls/mbedtls.c @@ -245,7 +245,7 @@ mbed_connect_step1(struct connectdata *conn, const bool verifypeer = SSL_CONN_CONFIG(verifypeer); const char * const ssl_capath = SSL_CONN_CONFIG(CApath); char * const ssl_cert = SSL_SET_OPTION(cert); - const char * const ssl_crlfile = SSL_SET_OPTION(CRLfile); + const char * const ssl_crlfile = SSL_SET_OPTION(primary.CRLfile); const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : conn->host.name; const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port; diff --git a/lib/vtls/nss.c b/lib/vtls/nss.c index 86102f7..62fd7a2 100644 --- a/lib/vtls/nss.c +++ b/lib/vtls/nss.c @@ -1955,13 +1955,13 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex) } } - if(SSL_SET_OPTION(CRLfile)) { - const CURLcode rv = nss_load_crl(SSL_SET_OPTION(CRLfile)); + if(SSL_SET_OPTION(primary.CRLfile)) { + const CURLcode rv = nss_load_crl(SSL_SET_OPTION(primary.CRLfile)); if(rv) { result = rv; goto error; } - infof(data, " CRLfile: %s\n", SSL_SET_OPTION(CRLfile)); + infof(data, " CRLfile: %s\n", SSL_SET_OPTION(primary.CRLfile)); } if(SSL_SET_OPTION(cert)) { diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c index a14cecc..ec5a8f5 100644 --- a/lib/vtls/openssl.c +++ b/lib/vtls/openssl.c @@ -2454,14 +2454,14 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) &data->set.proxy_ssl.certverifyresult : &data->set.ssl.certverifyresult; const long int ssl_version = SSL_CONN_CONFIG(version); #ifdef USE_TLS_SRP - const enum CURL_TLSAUTH ssl_authtype = SSL_SET_OPTION(authtype); + const enum CURL_TLSAUTH ssl_authtype = SSL_SET_OPTION(primary.authtype); #endif char * const ssl_cert = SSL_SET_OPTION(cert); const char * const ssl_cert_type = SSL_SET_OPTION(cert_type); const char * const ssl_cafile = SSL_CONN_CONFIG(CAfile); const char * const ssl_capath = SSL_CONN_CONFIG(CApath); const bool verifypeer = SSL_CONN_CONFIG(verifypeer); - const char * const ssl_crlfile = SSL_SET_OPTION(CRLfile); + const char * const ssl_crlfile = SSL_SET_OPTION(primary.CRLfile); char error_buffer[256]; DEBUGASSERT(ssl_connect_1 == connssl->connecting_state); @@ -2741,15 +2741,15 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) #ifdef USE_TLS_SRP if((ssl_authtype == CURL_TLSAUTH_SRP) && Curl_allow_auth_to_host(data)) { - char * const ssl_username = SSL_SET_OPTION(username); - + char * const ssl_username = SSL_SET_OPTION(primary.username); + char * const ssl_password = SSL_SET_OPTION(primary.password); infof(data, "Using TLS-SRP username: %s\n", ssl_username); if(!SSL_CTX_set_srp_username(BACKEND->ctx, ssl_username)) { failf(data, "Unable to set SRP user name"); return CURLE_BAD_FUNCTION_ARGUMENT; } - if(!SSL_CTX_set_srp_password(BACKEND->ctx, SSL_SET_OPTION(password))) { + if(!SSL_CTX_set_srp_password(BACKEND->ctx, ssl_password)) { failf(data, "failed setting SRP password"); return CURLE_BAD_FUNCTION_ARGUMENT; } diff --git a/lib/vtls/vtls.c b/lib/vtls/vtls.c index e38f74e..e8cb70f 100644 --- a/lib/vtls/vtls.c +++ b/lib/vtls/vtls.c @@ -89,6 +89,7 @@ Curl_ssl_config_matches(struct ssl_primary_config* data, { 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) &&