openssl: store the CA after first send (ClientHello)
move Curl_ssl_setup_x509_store() call after the first send (ClientHello) this gives time to parse CA anchors while waiting on the server reply Ref: #10389 Closes #10432
This commit is contained in:
parent
341280e161
commit
e8b00fcd6a
@ -294,6 +294,7 @@ struct ssl_backend_data {
|
|||||||
/* Set to true once a valid keylog entry has been created to avoid dupes. */
|
/* Set to true once a valid keylog entry has been created to avoid dupes. */
|
||||||
bool keylog_done;
|
bool keylog_done;
|
||||||
#endif
|
#endif
|
||||||
|
bool x509_store_setup; /* x509 store has been set up */
|
||||||
};
|
};
|
||||||
|
|
||||||
#if defined(HAVE_SSL_X509_STORE_SHARE)
|
#if defined(HAVE_SSL_X509_STORE_SHARE)
|
||||||
@ -747,6 +748,18 @@ static int bio_cf_in_read(BIO *bio, char *buf, int blen)
|
|||||||
if(CURLE_AGAIN == result)
|
if(CURLE_AGAIN == result)
|
||||||
BIO_set_retry_read(bio);
|
BIO_set_retry_read(bio);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Before returning server replies to the SSL instance, we need
|
||||||
|
* to have setup the x509 store or verification will fail. */
|
||||||
|
if(!connssl->backend->x509_store_setup) {
|
||||||
|
result = Curl_ssl_setup_x509_store(cf, data, connssl->backend->ctx);
|
||||||
|
if(result) {
|
||||||
|
connssl->backend->io_result = result;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
connssl->backend->x509_store_setup = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
return (int)nread;
|
return (int)nread;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -927,34 +940,6 @@ static char *ossl_strerror(unsigned long error, char *buf, size_t size)
|
|||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return an extra data index for the associated Curl_cfilter instance.
|
|
||||||
* This index can be used with SSL_get_ex_data() and SSL_set_ex_data().
|
|
||||||
*/
|
|
||||||
static int ossl_get_ssl_cf_index(void)
|
|
||||||
{
|
|
||||||
static int ssl_ex_data_cf_index = -1;
|
|
||||||
if(ssl_ex_data_cf_index < 0) {
|
|
||||||
ssl_ex_data_cf_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
|
|
||||||
}
|
|
||||||
return ssl_ex_data_cf_index;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool ossl_attach_cf(struct Curl_cfilter *cf)
|
|
||||||
{
|
|
||||||
struct ssl_connect_data *connssl = cf->ctx;
|
|
||||||
struct ssl_backend_data *backend = connssl->backend;
|
|
||||||
int cf_idx = ossl_get_ssl_cf_index();
|
|
||||||
|
|
||||||
DEBUGASSERT(backend);
|
|
||||||
|
|
||||||
/* If we don't have SSL context, do nothing. */
|
|
||||||
if(backend->handle && cf_idx >= 0) {
|
|
||||||
if(SSL_set_ex_data(backend->handle, cf_idx, cf))
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int passwd_callback(char *buf, int num, int encrypting,
|
static int passwd_callback(char *buf, int num, int encrypting,
|
||||||
void *global_passwd)
|
void *global_passwd)
|
||||||
{
|
{
|
||||||
@ -1755,10 +1740,6 @@ static int ossl_init(void)
|
|||||||
|
|
||||||
Curl_tls_keylog_open();
|
Curl_tls_keylog_open();
|
||||||
|
|
||||||
/* Initialize the extra data indexes */
|
|
||||||
if(ossl_get_ssl_cf_index() < 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1970,6 +1951,7 @@ static void ossl_close(struct Curl_cfilter *cf, struct Curl_easy *data)
|
|||||||
if(backend->ctx) {
|
if(backend->ctx) {
|
||||||
SSL_CTX_free(backend->ctx);
|
SSL_CTX_free(backend->ctx);
|
||||||
backend->ctx = NULL;
|
backend->ctx = NULL;
|
||||||
|
backend->x509_store_setup = FALSE;
|
||||||
}
|
}
|
||||||
if(backend->bio_method) {
|
if(backend->bio_method) {
|
||||||
bio_cf_method_free(backend->bio_method);
|
bio_cf_method_free(backend->bio_method);
|
||||||
@ -2646,19 +2628,14 @@ static void ossl_trace(int direction, int ssl_ver, int content_type,
|
|||||||
void *userp)
|
void *userp)
|
||||||
{
|
{
|
||||||
const char *verstr = "???";
|
const char *verstr = "???";
|
||||||
struct connectdata *conn = userp;
|
struct Curl_cfilter *cf = userp;
|
||||||
int cf_idx = ossl_get_ssl_cf_index();
|
|
||||||
struct Curl_easy *data = NULL;
|
struct Curl_easy *data = NULL;
|
||||||
struct Curl_cfilter *cf;
|
|
||||||
char unknown[32];
|
char unknown[32];
|
||||||
|
|
||||||
DEBUGASSERT(cf_idx >= 0);
|
if(!cf)
|
||||||
cf = (struct Curl_cfilter*) SSL_get_ex_data(ssl, cf_idx);
|
return;
|
||||||
DEBUGASSERT(cf);
|
|
||||||
data = CF_DATA_CURRENT(cf);
|
data = CF_DATA_CURRENT(cf);
|
||||||
|
if(!data || !data->set.fdebug || (direction && direction != 1))
|
||||||
if(!conn || !data || !data->set.fdebug
|
|
||||||
|| (direction != 0 && direction != 1))
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
switch(ssl_ver) {
|
switch(ssl_ver) {
|
||||||
@ -2951,13 +2928,10 @@ static int ossl_new_session_cb(SSL *ssl, SSL_SESSION *ssl_sessionid)
|
|||||||
struct Curl_easy *data;
|
struct Curl_easy *data;
|
||||||
struct Curl_cfilter *cf;
|
struct Curl_cfilter *cf;
|
||||||
const struct ssl_config_data *config;
|
const struct ssl_config_data *config;
|
||||||
int cf_idx = ossl_get_ssl_cf_index();
|
|
||||||
struct ssl_connect_data *connssl;
|
struct ssl_connect_data *connssl;
|
||||||
bool isproxy;
|
bool isproxy;
|
||||||
|
|
||||||
if(cf_idx < 0)
|
cf = (struct Curl_cfilter*) SSL_get_app_data(ssl);
|
||||||
return 0;
|
|
||||||
cf = (struct Curl_cfilter*) SSL_get_ex_data(ssl, cf_idx);
|
|
||||||
connssl = cf? cf->ctx : NULL;
|
connssl = cf? cf->ctx : NULL;
|
||||||
data = connssl? CF_DATA_CURRENT(cf) : NULL;
|
data = connssl? CF_DATA_CURRENT(cf) : NULL;
|
||||||
/* The sockindex has been stored as a pointer to an array element */
|
/* The sockindex has been stored as a pointer to an array element */
|
||||||
@ -3475,7 +3449,6 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf,
|
|||||||
struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
|
struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
|
||||||
struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
|
struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
|
||||||
BIO *bio;
|
BIO *bio;
|
||||||
int cf_idx = ossl_get_ssl_cf_index();
|
|
||||||
|
|
||||||
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
|
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
|
||||||
bool sni;
|
bool sni;
|
||||||
@ -3498,9 +3471,6 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf,
|
|||||||
DEBUGASSERT(ssl_connect_1 == connssl->connecting_state);
|
DEBUGASSERT(ssl_connect_1 == connssl->connecting_state);
|
||||||
DEBUGASSERT(backend);
|
DEBUGASSERT(backend);
|
||||||
|
|
||||||
if(cf_idx < 0)
|
|
||||||
return CURLE_FAILED_INIT;
|
|
||||||
|
|
||||||
/* Make funny stuff to get random input */
|
/* Make funny stuff to get random input */
|
||||||
result = ossl_seed(data);
|
result = ossl_seed(data);
|
||||||
if(result)
|
if(result)
|
||||||
@ -3558,7 +3528,7 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf,
|
|||||||
if(data->set.fdebug && data->set.verbose) {
|
if(data->set.fdebug && data->set.verbose) {
|
||||||
/* the SSL trace callback is only used for verbose logging */
|
/* the SSL trace callback is only used for verbose logging */
|
||||||
SSL_CTX_set_msg_callback(backend->ctx, ossl_trace);
|
SSL_CTX_set_msg_callback(backend->ctx, ossl_trace);
|
||||||
SSL_CTX_set_msg_callback_arg(backend->ctx, cf->conn);
|
SSL_CTX_set_msg_callback_arg(backend->ctx, cf);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -3746,10 +3716,6 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
result = Curl_ssl_setup_x509_store(cf, data, backend->ctx);
|
|
||||||
if(result)
|
|
||||||
return result;
|
|
||||||
|
|
||||||
/* OpenSSL always tries to verify the peer, this only says whether it should
|
/* OpenSSL always tries to verify the peer, this only says whether it should
|
||||||
* fail to connect if the verification fails, or if it should continue
|
* 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
|
* anyway. In the latter case the result of the verification is checked with
|
||||||
@ -3793,7 +3759,7 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf,
|
|||||||
return CURLE_OUT_OF_MEMORY;
|
return CURLE_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
SSL_set_ex_data(backend->handle, cf_idx, cf);
|
SSL_set_app_data(backend->handle, cf);
|
||||||
|
|
||||||
#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \
|
#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \
|
||||||
!defined(OPENSSL_NO_OCSP)
|
!defined(OPENSSL_NO_OCSP)
|
||||||
@ -3822,13 +3788,7 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(!ossl_attach_cf(cf)) {
|
SSL_set_app_data(backend->handle, cf);
|
||||||
/* Maybe the internal errors of SSL_get_ex_new_index or SSL_set_ex_data */
|
|
||||||
failf(data, "SSL: ossl_attach_cf failed: %s",
|
|
||||||
ossl_strerror(ERR_get_error(), error_buffer,
|
|
||||||
sizeof(error_buffer)));
|
|
||||||
return CURLE_SSL_CONNECT_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(ssl_config->primary.sessionid) {
|
if(ssl_config->primary.sessionid) {
|
||||||
Curl_ssl_sessionid_lock(data);
|
Curl_ssl_sessionid_lock(data);
|
||||||
@ -3887,6 +3847,16 @@ static CURLcode ossl_connect_step2(struct Curl_cfilter *cf,
|
|||||||
ERR_clear_error();
|
ERR_clear_error();
|
||||||
|
|
||||||
err = SSL_connect(backend->handle);
|
err = SSL_connect(backend->handle);
|
||||||
|
|
||||||
|
if(!backend->x509_store_setup) {
|
||||||
|
/* After having send off the ClientHello, we prepare the x509
|
||||||
|
* store to verify the coming certificate from the server */
|
||||||
|
CURLcode result = Curl_ssl_setup_x509_store(cf, data, backend->ctx);
|
||||||
|
if(result)
|
||||||
|
return result;
|
||||||
|
backend->x509_store_setup = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef HAVE_KEYLOG_CALLBACK
|
#ifndef HAVE_KEYLOG_CALLBACK
|
||||||
if(Curl_tls_keylog_enabled()) {
|
if(Curl_tls_keylog_enabled()) {
|
||||||
/* If key logging is enabled, wait for the handshake to complete and then
|
/* If key logging is enabled, wait for the handshake to complete and then
|
||||||
@ -4372,8 +4342,9 @@ static CURLcode ossl_connect_common(struct Curl_cfilter *cf,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* if ssl is expecting something, check if it's available. */
|
/* if ssl is expecting something, check if it's available. */
|
||||||
if(connssl->connecting_state == ssl_connect_2_reading ||
|
if(!nonblocking &&
|
||||||
connssl->connecting_state == ssl_connect_2_writing) {
|
(connssl->connecting_state == ssl_connect_2_reading ||
|
||||||
|
connssl->connecting_state == ssl_connect_2_writing)) {
|
||||||
|
|
||||||
curl_socket_t writefd = ssl_connect_2_writing ==
|
curl_socket_t writefd = ssl_connect_2_writing ==
|
||||||
connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
|
connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user