diff options
author | dartraiden <wowemuh@gmail.com> | 2020-05-02 22:10:12 +0300 |
---|---|---|
committer | dartraiden <wowemuh@gmail.com> | 2020-05-02 22:10:12 +0300 |
commit | e963209266bbf3809cb8b44740de1b61e58f9ace (patch) | |
tree | 2ade22dff252aecfbd298b40e86b81182bba8dbc /libs/libcurl/src/vtls | |
parent | e59cb2e8ac2d6c21016f773f0f26148343a5839c (diff) |
libcurl: update to 7.70.0
Diffstat (limited to 'libs/libcurl/src/vtls')
-rw-r--r-- | libs/libcurl/src/vtls/bearssl.c | 100 | ||||
-rw-r--r-- | libs/libcurl/src/vtls/gskit.c | 5 | ||||
-rw-r--r-- | libs/libcurl/src/vtls/gtls.c | 500 | ||||
-rw-r--r-- | libs/libcurl/src/vtls/mbedtls.c | 145 | ||||
-rw-r--r-- | libs/libcurl/src/vtls/nss.c | 119 | ||||
-rw-r--r-- | libs/libcurl/src/vtls/openssl.c | 252 | ||||
-rw-r--r-- | libs/libcurl/src/vtls/schannel.c | 178 | ||||
-rw-r--r-- | libs/libcurl/src/vtls/schannel_verify.c | 9 | ||||
-rw-r--r-- | libs/libcurl/src/vtls/sectransp.c | 191 | ||||
-rw-r--r-- | libs/libcurl/src/vtls/vtls.c | 7 | ||||
-rw-r--r-- | libs/libcurl/src/vtls/wolfssl.c | 124 |
11 files changed, 803 insertions, 827 deletions
diff --git a/libs/libcurl/src/vtls/bearssl.c b/libs/libcurl/src/vtls/bearssl.c index 67f945831c..1a6530c81c 100644 --- a/libs/libcurl/src/vtls/bearssl.c +++ b/libs/libcurl/src/vtls/bearssl.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2019, Michael Forney, <mforney@mforney.org> + * Copyright (C) 2019 - 2020, Michael Forney, <mforney@mforney.org> * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -56,8 +56,6 @@ struct ssl_backend_data { size_t pending_write; }; -#define BACKEND connssl->backend - struct cafile_parser { CURLcode err; bool in_cert; @@ -300,6 +298,7 @@ static CURLcode bearssl_connect_step1(struct connectdata *conn, int sockindex) { struct Curl_easy *data = conn->data; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + struct ssl_backend_data *backend = connssl->backend; const char * const ssl_cafile = SSL_CONN_CONFIG(CAfile); const char *hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : conn->host.name; @@ -343,7 +342,7 @@ static CURLcode bearssl_connect_step1(struct connectdata *conn, int sockindex) } if(ssl_cafile) { - ret = load_cafile(ssl_cafile, &BACKEND->anchors, &BACKEND->anchors_len); + ret = load_cafile(ssl_cafile, &backend->anchors, &backend->anchors_len); if(ret != CURLE_OK) { if(verifypeer) { failf(data, "error setting certificate verify locations:\n" @@ -356,24 +355,24 @@ static CURLcode bearssl_connect_step1(struct connectdata *conn, int sockindex) } /* initialize SSL context */ - br_ssl_client_init_full(&BACKEND->ctx, &BACKEND->x509.minimal, - BACKEND->anchors, BACKEND->anchors_len); - br_ssl_engine_set_versions(&BACKEND->ctx.eng, version_min, version_max); - br_ssl_engine_set_buffer(&BACKEND->ctx.eng, BACKEND->buf, - sizeof(BACKEND->buf), 1); + br_ssl_client_init_full(&backend->ctx, &backend->x509.minimal, + backend->anchors, backend->anchors_len); + br_ssl_engine_set_versions(&backend->ctx.eng, version_min, version_max); + br_ssl_engine_set_buffer(&backend->ctx.eng, backend->buf, + sizeof(backend->buf), 1); /* initialize X.509 context */ - BACKEND->x509.vtable = &x509_vtable; - BACKEND->x509.verifypeer = verifypeer; - BACKEND->x509.verifyhost = verifyhost; - br_ssl_engine_set_x509(&BACKEND->ctx.eng, &BACKEND->x509.vtable); + backend->x509.vtable = &x509_vtable; + backend->x509.verifypeer = verifypeer; + backend->x509.verifyhost = verifyhost; + br_ssl_engine_set_x509(&backend->ctx.eng, &backend->x509.vtable); if(SSL_SET_OPTION(primary.sessionid)) { void *session; Curl_ssl_sessionid_lock(conn); if(!Curl_ssl_getsessionid(conn, &session, NULL, sockindex)) { - br_ssl_engine_set_session_parameters(&BACKEND->ctx.eng, session); + br_ssl_engine_set_session_parameters(&backend->ctx.eng, session); infof(data, "BearSSL: re-using session ID\n"); } Curl_ssl_sessionid_unlock(conn); @@ -389,16 +388,16 @@ static CURLcode bearssl_connect_step1(struct connectdata *conn, int sockindex) #ifdef USE_NGHTTP2 if(data->set.httpversion >= CURL_HTTP_VERSION_2 && (!SSL_IS_PROXY() || !conn->bits.tunnel_proxy)) { - BACKEND->protocols[cur++] = NGHTTP2_PROTO_VERSION_ID; + backend->protocols[cur++] = NGHTTP2_PROTO_VERSION_ID; infof(data, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID); } #endif - BACKEND->protocols[cur++] = ALPN_HTTP_1_1; + backend->protocols[cur++] = ALPN_HTTP_1_1; infof(data, "ALPN, offering %s\n", ALPN_HTTP_1_1); - br_ssl_engine_set_protocol_names(&BACKEND->ctx.eng, - BACKEND->protocols, cur); + br_ssl_engine_set_protocol_names(&backend->ctx.eng, + backend->protocols, cur); } if((1 == Curl_inet_pton(AF_INET, hostname, &addr)) @@ -414,9 +413,9 @@ static CURLcode bearssl_connect_step1(struct connectdata *conn, int sockindex) hostname = NULL; } - if(!br_ssl_client_reset(&BACKEND->ctx, hostname, 0)) + if(!br_ssl_client_reset(&backend->ctx, hostname, 0)) return CURLE_FAILED_INIT; - BACKEND->active = TRUE; + backend->active = TRUE; connssl->connecting_state = ssl_connect_2; @@ -428,6 +427,7 @@ static CURLcode bearssl_run_until(struct connectdata *conn, int sockindex, { struct Curl_easy *data = conn->data; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + struct ssl_backend_data *backend = connssl->backend; curl_socket_t sockfd = conn->sock[sockindex]; unsigned state; unsigned char *buf; @@ -436,9 +436,9 @@ static CURLcode bearssl_run_until(struct connectdata *conn, int sockindex, int err; for(;;) { - state = br_ssl_engine_current_state(&BACKEND->ctx.eng); + state = br_ssl_engine_current_state(&backend->ctx.eng); if(state & BR_SSL_CLOSED) { - err = br_ssl_engine_last_error(&BACKEND->ctx.eng); + err = br_ssl_engine_last_error(&backend->ctx.eng); switch(err) { case BR_ERR_OK: /* TLS close notify */ @@ -468,7 +468,7 @@ static CURLcode bearssl_run_until(struct connectdata *conn, int sockindex, if(state & target) return CURLE_OK; if(state & BR_SSL_SENDREC) { - buf = br_ssl_engine_sendrec_buf(&BACKEND->ctx.eng, &len); + buf = br_ssl_engine_sendrec_buf(&backend->ctx.eng, &len); ret = swrite(sockfd, buf, len); if(ret == -1) { if(SOCKERRNO == EAGAIN || SOCKERRNO == EWOULDBLOCK) { @@ -478,10 +478,10 @@ static CURLcode bearssl_run_until(struct connectdata *conn, int sockindex, } return CURLE_WRITE_ERROR; } - br_ssl_engine_sendrec_ack(&BACKEND->ctx.eng, ret); + br_ssl_engine_sendrec_ack(&backend->ctx.eng, ret); } else if(state & BR_SSL_RECVREC) { - buf = br_ssl_engine_recvrec_buf(&BACKEND->ctx.eng, &len); + buf = br_ssl_engine_recvrec_buf(&backend->ctx.eng, &len); ret = sread(sockfd, buf, len); if(ret == 0) { failf(data, "SSL: EOF without close notify"); @@ -495,7 +495,7 @@ static CURLcode bearssl_run_until(struct connectdata *conn, int sockindex, } return CURLE_READ_ERROR; } - br_ssl_engine_recvrec_ack(&BACKEND->ctx.eng, ret); + br_ssl_engine_recvrec_ack(&backend->ctx.eng, ret); } } } @@ -504,13 +504,14 @@ static CURLcode bearssl_connect_step2(struct connectdata *conn, int sockindex) { struct Curl_easy *data = conn->data; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + struct ssl_backend_data *backend = connssl->backend; CURLcode ret; ret = bearssl_run_until(conn, sockindex, BR_SSL_SENDAPP | BR_SSL_RECVAPP); if(ret == CURLE_AGAIN) return CURLE_OK; if(ret == CURLE_OK) { - if(br_ssl_engine_current_state(&BACKEND->ctx.eng) == BR_SSL_CLOSED) { + if(br_ssl_engine_current_state(&backend->ctx.eng) == BR_SSL_CLOSED) { failf(data, "SSL: connection closed during handshake"); return CURLE_SSL_CONNECT_ERROR; } @@ -523,6 +524,7 @@ static CURLcode bearssl_connect_step3(struct connectdata *conn, int sockindex) { struct Curl_easy *data = conn->data; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + struct ssl_backend_data *backend = connssl->backend; CURLcode ret; DEBUGASSERT(ssl_connect_3 == connssl->connecting_state); @@ -530,7 +532,7 @@ static CURLcode bearssl_connect_step3(struct connectdata *conn, int sockindex) if(conn->bits.tls_enable_alpn) { const char *protocol; - protocol = br_ssl_engine_get_selected_protocol(&BACKEND->ctx.eng); + protocol = br_ssl_engine_get_selected_protocol(&backend->ctx.eng); if(protocol) { infof(data, "ALPN, server accepted to use %s\n", protocol); @@ -558,7 +560,7 @@ static CURLcode bearssl_connect_step3(struct connectdata *conn, int sockindex) session = malloc(sizeof(*session)); if(!session) return CURLE_OUT_OF_MEMORY; - br_ssl_engine_get_session_parameters(&BACKEND->ctx.eng, session); + br_ssl_engine_get_session_parameters(&backend->ctx.eng, session); Curl_ssl_sessionid_lock(conn); incache = !(Curl_ssl_getsessionid(conn, &oldsession, NULL, sockindex)); if(incache) @@ -581,6 +583,7 @@ static ssize_t bearssl_send(struct connectdata *conn, int sockindex, { struct Curl_easy *data = conn->data; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + struct ssl_backend_data *backend = connssl->backend; unsigned char *app; size_t applen; @@ -588,23 +591,23 @@ static ssize_t bearssl_send(struct connectdata *conn, int sockindex, *err = bearssl_run_until(conn, sockindex, BR_SSL_SENDAPP); if (*err != CURLE_OK) return -1; - app = br_ssl_engine_sendapp_buf(&BACKEND->ctx.eng, &applen); + app = br_ssl_engine_sendapp_buf(&backend->ctx.eng, &applen); if(!app) { failf(data, "SSL: connection closed during write"); *err = CURLE_SEND_ERROR; return -1; } - if(BACKEND->pending_write) { - applen = BACKEND->pending_write; - BACKEND->pending_write = 0; + if(backend->pending_write) { + applen = backend->pending_write; + backend->pending_write = 0; return applen; } if(applen > len) applen = len; memcpy(app, buf, applen); - br_ssl_engine_sendapp_ack(&BACKEND->ctx.eng, applen); - br_ssl_engine_flush(&BACKEND->ctx.eng, 0); - BACKEND->pending_write = applen; + br_ssl_engine_sendapp_ack(&backend->ctx.eng, applen); + br_ssl_engine_flush(&backend->ctx.eng, 0); + backend->pending_write = applen; } } @@ -612,19 +615,20 @@ static ssize_t bearssl_recv(struct connectdata *conn, int sockindex, char *buf, size_t len, CURLcode *err) { struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + struct ssl_backend_data *backend = connssl->backend; unsigned char *app; size_t applen; *err = bearssl_run_until(conn, sockindex, BR_SSL_RECVAPP); if(*err != CURLE_OK) return -1; - app = br_ssl_engine_recvapp_buf(&BACKEND->ctx.eng, &applen); + app = br_ssl_engine_recvapp_buf(&backend->ctx.eng, &applen); if(!app) return 0; if(applen > len) applen = len; memcpy(buf, app, applen); - br_ssl_engine_recvapp_ack(&BACKEND->ctx.eng, applen); + br_ssl_engine_recvapp_ack(&backend->ctx.eng, applen); return applen; } @@ -739,8 +743,8 @@ static bool Curl_bearssl_data_pending(const struct connectdata *conn, int connindex) { const struct ssl_connect_data *connssl = &conn->ssl[connindex]; - - return br_ssl_engine_current_state(&BACKEND->ctx.eng) & BR_SSL_RECVAPP; + struct ssl_backend_data *backend = connssl->backend; + return br_ssl_engine_current_state(&backend->ctx.eng) & BR_SSL_RECVAPP; } static CURLcode Curl_bearssl_random(struct Curl_easy *data UNUSED_PARAM, @@ -786,21 +790,23 @@ static CURLcode Curl_bearssl_connect_nonblocking(struct connectdata *conn, static void *Curl_bearssl_get_internals(struct ssl_connect_data *connssl, CURLINFO info UNUSED_PARAM) { - return &BACKEND->ctx; + struct ssl_backend_data *backend = connssl->backend; + return &backend->ctx; } static void Curl_bearssl_close(struct connectdata *conn, int sockindex) { struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + struct ssl_backend_data *backend = connssl->backend; size_t i; - if(BACKEND->active) { - br_ssl_engine_close(&BACKEND->ctx.eng); + if(backend->active) { + br_ssl_engine_close(&backend->ctx.eng); (void)bearssl_run_until(conn, sockindex, BR_SSL_CLOSED); } - for(i = 0; i < BACKEND->anchors_len; ++i) - free(BACKEND->anchors[i].dn.data); - free(BACKEND->anchors); + for(i = 0; i < backend->anchors_len; ++i) + free(backend->anchors[i].dn.data); + free(backend->anchors); } static void Curl_bearssl_session_free(void *ptr) @@ -836,9 +842,7 @@ static CURLcode Curl_bearssl_sha256sum(const unsigned char *input, const struct Curl_ssl Curl_ssl_bearssl = { { CURLSSLBACKEND_BEARSSL, "bearssl" }, - 0, - sizeof(struct ssl_backend_data), Curl_none_init, diff --git a/libs/libcurl/src/vtls/gskit.c b/libs/libcurl/src/vtls/gskit.c index 32153dd071..b0864b5fad 100644 --- a/libs/libcurl/src/vtls/gskit.c +++ b/libs/libcurl/src/vtls/gskit.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2020, 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 @@ -524,7 +524,6 @@ static int pipe_ssloverssl(struct connectdata *conn, int sockindex, int m; int i; int ret = 0; - struct timeval tv = {0, 0}; char buf[CURL_MAX_WRITE_SIZE]; if(!connssl->use || !connproxyssl->use) @@ -544,7 +543,7 @@ static int pipe_ssloverssl(struct connectdata *conn, int sockindex, if(n < conn->sock[sockindex]) n = conn->sock[sockindex]; } - i = select(n + 1, &fds_read, &fds_write, NULL, &tv); + i = Curl_select(n + 1, &fds_read, &fds_write, NULL, 0); if(i < 0) return -1; /* Select error. */ diff --git a/libs/libcurl/src/vtls/gtls.c b/libs/libcurl/src/vtls/gtls.c index 5f740eeba1..4ed3ea5cfa 100644 --- a/libs/libcurl/src/vtls/gtls.c +++ b/libs/libcurl/src/vtls/gtls.c @@ -72,36 +72,11 @@ static void tls_log_func(int level, const char *str) #endif static bool gtls_inited = FALSE; -#if defined(GNUTLS_VERSION_NUMBER) -# if (GNUTLS_VERSION_NUMBER >= 0x020c00) -# undef gnutls_transport_set_lowat -# define gnutls_transport_set_lowat(A,B) Curl_nop_stmt -# define USE_GNUTLS_PRIORITY_SET_DIRECT 1 -# endif -# if (GNUTLS_VERSION_NUMBER >= 0x020c03) -# define GNUTLS_MAPS_WINSOCK_ERRORS 1 -# endif - -# if HAVE_GNUTLS_ALPN_SET_PROTOCOLS -# define HAS_ALPN -# endif - -# if HAVE_GNUTLS_OCSP_REQ_INIT -# define HAS_OCSP -# endif - -# if (GNUTLS_VERSION_NUMBER >= 0x030306) -# define HAS_CAPATH -# endif +#if !defined(GNUTLS_VERSION_NUMBER) || (GNUTLS_VERSION_NUMBER < 0x03010a) +#error "too old GnuTLS version" #endif -#if (GNUTLS_VERSION_NUMBER >= 0x030603) -#define HAS_TLS13 -#endif - -#ifdef HAS_OCSP # include <gnutls/ocsp.h> -#endif struct ssl_backend_data { gnutls_session_t session; @@ -111,58 +86,10 @@ struct ssl_backend_data { #endif }; -#define BACKEND connssl->backend - -/* - * Custom push and pull callback functions used by GNU TLS to read and write - * to the socket. These functions are simple wrappers to send() and recv() - * (although here using the sread/swrite macros as defined by - * curl_setup_once.h). - * We use custom functions rather than the GNU TLS defaults because it allows - * us to get specific about the fourth "flags" argument, and to use arbitrary - * private data with gnutls_transport_set_ptr if we wish. - * - * When these custom push and pull callbacks fail, GNU TLS checks its own - * session-specific error variable, and when not set also its own global - * errno variable, in order to take appropriate action. GNU TLS does not - * require that the transport is actually a socket. This implies that for - * Windows builds these callbacks should ideally set the session-specific - * error variable using function gnutls_transport_set_errno or as a last - * resort global errno variable using gnutls_transport_set_global_errno, - * with a transport agnostic error value. This implies that some winsock - * error translation must take place in these callbacks. - * - * Paragraph above applies to GNU TLS versions older than 2.12.3, since - * this version GNU TLS does its own internal winsock error translation - * using system_errno() function. - */ - -#if defined(USE_WINSOCK) && !defined(GNUTLS_MAPS_WINSOCK_ERRORS) -# define gtls_EINTR 4 -# define gtls_EIO 5 -# define gtls_EAGAIN 11 -static int gtls_mapped_sockerrno(void) -{ - switch(SOCKERRNO) { - case WSAEWOULDBLOCK: - return gtls_EAGAIN; - case WSAEINTR: - return gtls_EINTR; - default: - break; - } - return gtls_EIO; -} -#endif - static ssize_t Curl_gtls_push(void *s, const void *buf, size_t len) { curl_socket_t sock = *(curl_socket_t *)s; ssize_t ret = swrite(sock, buf, len); -#if defined(USE_WINSOCK) && !defined(GNUTLS_MAPS_WINSOCK_ERRORS) - if(ret < 0) - gnutls_transport_set_global_errno(gtls_mapped_sockerrno()); -#endif return ret; } @@ -170,10 +97,6 @@ static ssize_t Curl_gtls_pull(void *s, void *buf, size_t len) { curl_socket_t sock = *(curl_socket_t *)s; ssize_t ret = sread(sock, buf, len); -#if defined(USE_WINSOCK) && !defined(GNUTLS_MAPS_WINSOCK_ERRORS) - if(ret < 0) - gnutls_transport_set_global_errno(gtls_mapped_sockerrno()); -#endif return ret; } @@ -284,7 +207,8 @@ static CURLcode handshake(struct connectdata *conn, { struct Curl_easy *data = conn->data; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; - gnutls_session_t session = BACKEND->session; + struct ssl_backend_data *backend = connssl->backend; + gnutls_session_t session = backend->session; curl_socket_t sockfd = conn->sock[sockindex]; for(;;) { @@ -383,51 +307,6 @@ static gnutls_x509_crt_fmt_t do_file_type(const char *type) return -1; } -#ifndef USE_GNUTLS_PRIORITY_SET_DIRECT -static CURLcode -set_ssl_version_min_max(int *list, size_t list_size, struct connectdata *conn) -{ - struct Curl_easy *data = conn->data; - long ssl_version = SSL_CONN_CONFIG(version); - long ssl_version_max = SSL_CONN_CONFIG(version_max); - long i = ssl_version; - long protocol_priority_idx = 0; - - switch(ssl_version_max) { - case CURL_SSLVERSION_MAX_NONE: - case CURL_SSLVERSION_MAX_DEFAULT: -#ifdef HAS_TLS13 - ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_3; -#endif - ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2; - break; - } - - for(; i <= (ssl_version_max >> 16) && - protocol_priority_idx < list_size; ++i) { - switch(i) { - case CURL_SSLVERSION_TLSv1_0: - protocol_priority[protocol_priority_idx++] = GNUTLS_TLS1_0; - break; - case CURL_SSLVERSION_TLSv1_1: - protocol_priority[protocol_priority_idx++] = GNUTLS_TLS1_1; - break; - case CURL_SSLVERSION_TLSv1_2: - protocol_priority[protocol_priority_idx++] = GNUTLS_TLS1_2; - break; - case CURL_SSLVERSION_TLSv1_3: -#ifdef HAS_TLS13 - protocol_priority[protocol_priority_idx++] = GNUTLS_TLS1_3; - break; -#else - failf(data, "GnuTLS: TLS 1.3 is not yet supported"); - return CURLE_SSL_CONNECT_ERROR; -#endif - } - } - return CURLE_OK; -} -#else #define GNUTLS_CIPHERS "NORMAL:-ARCFOUR-128:-CTYPE-ALL:+CTYPE-X509" /* If GnuTLS was compiled without support for SRP it will error out if SRP is requested in the priority string, so treat it specially @@ -445,77 +324,59 @@ set_ssl_version_min_max(const char **prioritylist, struct connectdata *conn) ssl_version_max = CURL_SSLVERSION_MAX_DEFAULT; } switch(ssl_version | ssl_version_max) { - case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_0: - *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" - "+VERS-TLS1.0:" GNUTLS_SRP; - return CURLE_OK; - case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_1: - *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" - "+VERS-TLS1.0:+VERS-TLS1.1:" GNUTLS_SRP; - return CURLE_OK; - case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_2: - *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" - "+VERS-TLS1.0:+VERS-TLS1.1:+VERS-TLS1.2:" GNUTLS_SRP; - return CURLE_OK; - case CURL_SSLVERSION_TLSv1_1 | CURL_SSLVERSION_MAX_TLSv1_1: - *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" - "+VERS-TLS1.1:" GNUTLS_SRP; - return CURLE_OK; - case CURL_SSLVERSION_TLSv1_1 | CURL_SSLVERSION_MAX_TLSv1_2: - *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" - "+VERS-TLS1.1:+VERS-TLS1.2:" GNUTLS_SRP; - return CURLE_OK; - case CURL_SSLVERSION_TLSv1_2 | CURL_SSLVERSION_MAX_TLSv1_2: - *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" - "+VERS-TLS1.2:" GNUTLS_SRP; - return CURLE_OK; - case CURL_SSLVERSION_TLSv1_3 | CURL_SSLVERSION_MAX_TLSv1_3: -#ifdef HAS_TLS13 - *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" - "+VERS-TLS1.3:" GNUTLS_SRP; - return CURLE_OK; -#else - failf(data, "GnuTLS: TLS 1.3 is not yet supported"); - return CURLE_SSL_CONNECT_ERROR; -#endif - case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_DEFAULT: - *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" - "+VERS-TLS1.0:+VERS-TLS1.1:+VERS-TLS1.2:" -#ifdef HAS_TLS13 - "+VERS-TLS1.3:" -#endif - GNUTLS_SRP; - return CURLE_OK; - case CURL_SSLVERSION_TLSv1_1 | CURL_SSLVERSION_MAX_DEFAULT: - *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" - "+VERS-TLS1.1:+VERS-TLS1.2:" -#ifdef HAS_TLS13 - "+VERS-TLS1.3:" -#endif - GNUTLS_SRP; - return CURLE_OK; - case CURL_SSLVERSION_TLSv1_2 | CURL_SSLVERSION_MAX_DEFAULT: - *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" - "+VERS-TLS1.2:" -#ifdef HAS_TLS13 - "+VERS-TLS1.3:" -#endif - GNUTLS_SRP; - return CURLE_OK; - case CURL_SSLVERSION_TLSv1_3 | CURL_SSLVERSION_MAX_DEFAULT: - *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" - "+VERS-TLS1.2:" -#ifdef HAS_TLS13 - "+VERS-TLS1.3:" -#endif - GNUTLS_SRP; - return CURLE_OK; + case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_0: + *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" + "+VERS-TLS1.0"; + return CURLE_OK; + case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_1: + *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" + "+VERS-TLS1.0:+VERS-TLS1.1"; + return CURLE_OK; + case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_2: + *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" + "+VERS-TLS1.0:+VERS-TLS1.1:+VERS-TLS1.2"; + return CURLE_OK; + case CURL_SSLVERSION_TLSv1_1 | CURL_SSLVERSION_MAX_TLSv1_1: + *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" + "+VERS-TLS1.1"; + return CURLE_OK; + case CURL_SSLVERSION_TLSv1_1 | CURL_SSLVERSION_MAX_TLSv1_2: + *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" + "+VERS-TLS1.1:+VERS-TLS1.2"; + return CURLE_OK; + case CURL_SSLVERSION_TLSv1_2 | CURL_SSLVERSION_MAX_TLSv1_2: + *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" + "+VERS-TLS1.2"; + return CURLE_OK; + case CURL_SSLVERSION_TLSv1_3 | CURL_SSLVERSION_MAX_TLSv1_3: + *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" + "+VERS-TLS1.3"; + return CURLE_OK; + case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_DEFAULT: + *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" + "+VERS-TLS1.0:+VERS-TLS1.1:+VERS-TLS1.2" + ":+VERS-TLS1.3"; + return CURLE_OK; + case CURL_SSLVERSION_TLSv1_1 | CURL_SSLVERSION_MAX_DEFAULT: + *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" + "+VERS-TLS1.1:+VERS-TLS1.2" + ":+VERS-TLS1.3"; + return CURLE_OK; + case CURL_SSLVERSION_TLSv1_2 | CURL_SSLVERSION_MAX_DEFAULT: + *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" + "+VERS-TLS1.2" + ":+VERS-TLS1.3"; + return CURLE_OK; + case CURL_SSLVERSION_TLSv1_3 | CURL_SSLVERSION_MAX_DEFAULT: + *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" + "+VERS-TLS1.2" + ":+VERS-TLS1.3"; + return CURLE_OK; } failf(data, "GnuTLS: cannot set ssl protocol"); return CURLE_SSL_CONNECT_ERROR; } -#endif static CURLcode gtls_connect_step1(struct connectdata *conn, @@ -523,6 +384,7 @@ gtls_connect_step1(struct connectdata *conn, { struct Curl_easy *data = conn->data; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + struct ssl_backend_data *backend = connssl->backend; unsigned int init_flags; gnutls_session_t session; int rc; @@ -535,26 +397,8 @@ gtls_connect_step1(struct connectdata *conn, #else struct in_addr addr; #endif -#ifndef USE_GNUTLS_PRIORITY_SET_DIRECT - static const int cipher_priority[] = { - /* These two ciphers were added to GnuTLS as late as ver. 3.0.1, - but this code path is only ever used for ver. < 2.12.0. - GNUTLS_CIPHER_AES_128_GCM, - GNUTLS_CIPHER_AES_256_GCM, - */ - GNUTLS_CIPHER_AES_128_CBC, - GNUTLS_CIPHER_AES_256_CBC, - GNUTLS_CIPHER_CAMELLIA_128_CBC, - GNUTLS_CIPHER_CAMELLIA_256_CBC, - GNUTLS_CIPHER_3DES_CBC, - }; - static const int cert_type_priority[] = { GNUTLS_CRT_X509, 0 }; - int protocol_priority[] = { 0, 0, 0, 0 }; -#else const char *prioritylist; const char *err = NULL; -#endif - const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : conn->host.name; @@ -574,7 +418,7 @@ gtls_connect_step1(struct connectdata *conn, sni = FALSE; /* SSLv3 has no SNI */ /* allocate a cred struct */ - rc = gnutls_certificate_allocate_credentials(&BACKEND->cred); + rc = gnutls_certificate_allocate_credentials(&backend->cred); if(rc != GNUTLS_E_SUCCESS) { failf(data, "gnutls_cert_all_cred() failed: %s", gnutls_strerror(rc)); return CURLE_SSL_CONNECT_ERROR; @@ -585,14 +429,14 @@ gtls_connect_step1(struct connectdata *conn, infof(data, "Using TLS-SRP username: %s\n", SSL_SET_OPTION(username)); rc = gnutls_srp_allocate_client_credentials( - &BACKEND->srp_client_cred); + &backend->srp_client_cred); if(rc != GNUTLS_E_SUCCESS) { failf(data, "gnutls_srp_allocate_client_cred() failed: %s", gnutls_strerror(rc)); return CURLE_OUT_OF_MEMORY; } - rc = gnutls_srp_set_client_credentials(BACKEND->srp_client_cred, + rc = gnutls_srp_set_client_credentials(backend->srp_client_cred, SSL_SET_OPTION(username), SSL_SET_OPTION(password)); if(rc != GNUTLS_E_SUCCESS) { @@ -605,10 +449,10 @@ gtls_connect_step1(struct connectdata *conn, if(SSL_CONN_CONFIG(CAfile)) { /* set the trusted CA cert bundle file */ - gnutls_certificate_set_verify_flags(BACKEND->cred, + gnutls_certificate_set_verify_flags(backend->cred, GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT); - rc = gnutls_certificate_set_x509_trust_file(BACKEND->cred, + rc = gnutls_certificate_set_x509_trust_file(backend->cred, SSL_CONN_CONFIG(CAfile), GNUTLS_X509_FMT_PEM); if(rc < 0) { @@ -622,10 +466,9 @@ gtls_connect_step1(struct connectdata *conn, SSL_CONN_CONFIG(CAfile)); } -#ifdef HAS_CAPATH if(SSL_CONN_CONFIG(CApath)) { /* set the trusted CA cert directory */ - rc = gnutls_certificate_set_x509_trust_dir(BACKEND->cred, + rc = gnutls_certificate_set_x509_trust_dir(backend->cred, SSL_CONN_CONFIG(CApath), GNUTLS_X509_FMT_PEM); if(rc < 0) { @@ -638,19 +481,18 @@ gtls_connect_step1(struct connectdata *conn, infof(data, "found %d certificates in %s\n", rc, SSL_CONN_CONFIG(CApath)); } -#endif #ifdef CURL_CA_FALLBACK /* use system ca certificate store as fallback */ if(SSL_CONN_CONFIG(verifypeer) && !(SSL_CONN_CONFIG(CAfile) || SSL_CONN_CONFIG(CApath))) { - gnutls_certificate_set_x509_system_trust(BACKEND->cred); + gnutls_certificate_set_x509_system_trust(backend->cred); } #endif if(SSL_SET_OPTION(CRLfile)) { /* set the CRL list file */ - rc = gnutls_certificate_set_x509_crl_file(BACKEND->cred, + rc = gnutls_certificate_set_x509_crl_file(backend->cred, SSL_SET_OPTION(CRLfile), GNUTLS_X509_FMT_PEM); if(rc < 0) { @@ -675,14 +517,14 @@ gtls_connect_step1(struct connectdata *conn, init_flags |= GNUTLS_NO_TICKETS; #endif - rc = gnutls_init(&BACKEND->session, init_flags); + rc = gnutls_init(&backend->session, init_flags); if(rc != GNUTLS_E_SUCCESS) { failf(data, "gnutls_init() failed: %d", rc); return CURLE_SSL_CONNECT_ERROR; } /* convenient assign */ - session = BACKEND->session; + session = backend->session; if((0 == Curl_inet_pton(AF_INET, hostname, &addr)) && #ifdef ENABLE_IPV6 @@ -699,62 +541,6 @@ gtls_connect_step1(struct connectdata *conn, if(rc != GNUTLS_E_SUCCESS) return CURLE_SSL_CONNECT_ERROR; -#ifndef USE_GNUTLS_PRIORITY_SET_DIRECT - rc = gnutls_cipher_set_priority(session, cipher_priority); - if(rc != GNUTLS_E_SUCCESS) - return CURLE_SSL_CONNECT_ERROR; - - /* Sets the priority on the certificate types supported by gnutls. Priority - is higher for types specified before others. After specifying the types - you want, you must append a 0. */ - rc = gnutls_certificate_type_set_priority(session, cert_type_priority); - if(rc != GNUTLS_E_SUCCESS) - return CURLE_SSL_CONNECT_ERROR; - - if(SSL_CONN_CONFIG(cipher_list) != NULL) { - failf(data, "can't pass a custom cipher list to older GnuTLS" - " versions"); - return CURLE_SSL_CONNECT_ERROR; - } - - switch(SSL_CONN_CONFIG(version)) { - case CURL_SSLVERSION_SSLv3: - protocol_priority[0] = GNUTLS_SSL3; - break; - case CURL_SSLVERSION_DEFAULT: - case CURL_SSLVERSION_TLSv1: - protocol_priority[0] = GNUTLS_TLS1_0; - protocol_priority[1] = GNUTLS_TLS1_1; - protocol_priority[2] = GNUTLS_TLS1_2; -#ifdef HAS_TLS13 - protocol_priority[3] = GNUTLS_TLS1_3; -#endif - break; - case CURL_SSLVERSION_TLSv1_0: - case CURL_SSLVERSION_TLSv1_1: - case CURL_SSLVERSION_TLSv1_2: - case CURL_SSLVERSION_TLSv1_3: - { - CURLcode result = set_ssl_version_min_max(protocol_priority, - sizeof(protocol_priority)/sizeof(protocol_priority[0]), conn); - if(result != CURLE_OK) - return result; - break; - } - case CURL_SSLVERSION_SSLv2: - failf(data, "GnuTLS does not support SSLv2"); - return CURLE_SSL_CONNECT_ERROR; - default: - failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); - return CURLE_SSL_CONNECT_ERROR; - } - rc = gnutls_protocol_set_priority(session, protocol_priority); - if(rc != GNUTLS_E_SUCCESS) { - failf(data, "Did you pass a valid GnuTLS cipher list?"); - return CURLE_SSL_CONNECT_ERROR; - } - -#else /* Ensure +SRP comes at the *end* of all relevant strings so that it can be * removed if a run-time error indicates that SRP is not supported by this * GnuTLS version */ @@ -764,11 +550,11 @@ gtls_connect_step1(struct connectdata *conn, break; case CURL_SSLVERSION_DEFAULT: case CURL_SSLVERSION_TLSv1: - prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:" + prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0" #ifdef HAS_TLS13 - "+VERS-TLS1.3:" + ":+VERS-TLS1.3" #endif - GNUTLS_SRP; + ; break; case CURL_SSLVERSION_TLSv1_0: case CURL_SSLVERSION_TLSv1_1: @@ -787,32 +573,39 @@ gtls_connect_step1(struct connectdata *conn, failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); return CURLE_SSL_CONNECT_ERROR; } - rc = gnutls_priority_set_direct(session, prioritylist, &err); - if((rc == GNUTLS_E_INVALID_REQUEST) && err) { - if(!strcmp(err, GNUTLS_SRP)) { - /* This GnuTLS was probably compiled without support for SRP. - * Note that fact and try again without it. */ - int validprioritylen = curlx_uztosi(err - prioritylist); - char *prioritycopy = strdup(prioritylist); - if(!prioritycopy) - return CURLE_OUT_OF_MEMORY; +#ifdef USE_TLS_SRP + /* Only add SRP to the cipher list if SRP is requested. Otherwise + * GnuTLS will disable TLS 1.3 support. */ + if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP) { + size_t len = strlen(prioritylist); + + char *prioritysrp = malloc(len + sizeof(GNUTLS_SRP) + 1); + if(!prioritysrp) + return CURLE_OUT_OF_MEMORY; + strcpy(prioritysrp, prioritylist); + strcpy(prioritysrp + len, ":" GNUTLS_SRP); + + rc = gnutls_priority_set_direct(session, prioritysrp, &err); + free(prioritysrp); + + if((rc == GNUTLS_E_INVALID_REQUEST) && err) { infof(data, "This GnuTLS does not support SRP\n"); - if(validprioritylen) - /* Remove the :+SRP */ - prioritycopy[validprioritylen - 1] = 0; - rc = gnutls_priority_set_direct(session, prioritycopy, &err); - free(prioritycopy); } } + else { +#endif + rc = gnutls_priority_set_direct(session, prioritylist, &err); +#ifdef USE_TLS_SRP + } +#endif + if(rc != GNUTLS_E_SUCCESS) { failf(data, "Error %d setting GnuTLS cipher list starting with %s", rc, err); return CURLE_SSL_CONNECT_ERROR; } -#endif -#ifdef HAS_ALPN if(conn->bits.tls_enable_alpn) { int cur = 0; gnutls_datum_t protocols[2]; @@ -834,18 +627,16 @@ gtls_connect_step1(struct connectdata *conn, gnutls_alpn_set_protocols(session, protocols, cur, 0); } -#endif if(SSL_SET_OPTION(cert)) { if(SSL_SET_OPTION(key_passwd)) { -#if HAVE_GNUTLS_CERTIFICATE_SET_X509_KEY_FILE2 const unsigned int supported_key_encryption_algorithms = GNUTLS_PKCS_USE_PKCS12_3DES | GNUTLS_PKCS_USE_PKCS12_ARCFOUR | GNUTLS_PKCS_USE_PKCS12_RC2_40 | GNUTLS_PKCS_USE_PBES2_3DES | GNUTLS_PKCS_USE_PBES2_AES_128 | GNUTLS_PKCS_USE_PBES2_AES_192 | GNUTLS_PKCS_USE_PBES2_AES_256; rc = gnutls_certificate_set_x509_key_file2( - BACKEND->cred, + backend->cred, SSL_SET_OPTION(cert), SSL_SET_OPTION(key) ? SSL_SET_OPTION(key) : SSL_SET_OPTION(cert), @@ -858,14 +649,10 @@ gtls_connect_step1(struct connectdata *conn, gnutls_strerror(rc)); return CURLE_SSL_CONNECT_ERROR; } -#else - failf(data, "gnutls lacks support for encrypted key files"); - return CURLE_SSL_CONNECT_ERROR; -#endif } else { if(gnutls_certificate_set_x509_key_file( - BACKEND->cred, + backend->cred, SSL_SET_OPTION(cert), SSL_SET_OPTION(key) ? SSL_SET_OPTION(key) : SSL_SET_OPTION(cert), @@ -881,7 +668,7 @@ gtls_connect_step1(struct connectdata *conn, /* put the credentials to the current session */ if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP) { rc = gnutls_credentials_set(session, GNUTLS_CRD_SRP, - BACKEND->srp_client_cred); + backend->srp_client_cred); if(rc != GNUTLS_E_SUCCESS) { failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc)); return CURLE_SSL_CONNECT_ERROR; @@ -891,7 +678,7 @@ gtls_connect_step1(struct connectdata *conn, #endif { rc = gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, - BACKEND->cred); + backend->cred); if(rc != GNUTLS_E_SUCCESS) { failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc)); return CURLE_SSL_CONNECT_ERROR; @@ -917,10 +704,6 @@ gtls_connect_step1(struct connectdata *conn, gnutls_transport_set_push_function(session, gnutls_transport_push); gnutls_transport_set_pull_function(session, gnutls_transport_pull); - /* lowat must be set to zero when using custom push and pull functions. */ - gnutls_transport_set_lowat(session, 0); - -#ifdef HAS_OCSP if(SSL_CONN_CONFIG(verifystatus)) { rc = gnutls_ocsp_status_request_enable_client(session, NULL, 0, NULL); if(rc != GNUTLS_E_SUCCESS) { @@ -928,7 +711,6 @@ gtls_connect_step1(struct connectdata *conn, return CURLE_SSL_CONNECT_ERROR; } } -#endif /* This might be a reconnect, so we check for a session ID in the cache to speed up things */ @@ -1020,17 +802,17 @@ gtls_connect_step3(struct connectdata *conn, unsigned int verify_status = 0; gnutls_x509_crt_t x509_cert, x509_issuer; gnutls_datum_t issuerp; - char certbuf[256] = ""; /* big enough? */ + gnutls_datum_t certfields; + char certname[65] = ""; /* limited to 64 chars by ASN.1 */ size_t size; time_t certclock; const char *ptr; struct Curl_easy *data = conn->data; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; - gnutls_session_t session = BACKEND->session; + struct ssl_backend_data *backend = connssl->backend; + gnutls_session_t session = backend->session; int rc; -#ifdef HAS_ALPN gnutls_datum_t proto; -#endif CURLcode result = CURLE_OK; #ifndef CURL_DISABLE_VERBOSE_STRINGS unsigned int algo; @@ -1127,7 +909,6 @@ gtls_connect_step3(struct connectdata *conn, else infof(data, "\t server certificate verification SKIPPED\n"); -#ifdef HAS_OCSP if(SSL_CONN_CONFIG(verifystatus)) { if(gnutls_ocsp_status_request_is_checked(session, 0) == 0) { gnutls_datum_t status_request; @@ -1230,7 +1011,6 @@ gtls_connect_step3(struct connectdata *conn, } else infof(data, "\t server certificate status verification SKIPPED\n"); -#endif /* initialize an X.509 certificate structure. */ gnutls_x509_crt_init(&x509_cert); @@ -1257,11 +1037,11 @@ gtls_connect_step3(struct connectdata *conn, SSL_SET_OPTION(issuercert)?SSL_SET_OPTION(issuercert):"none"); } - size = sizeof(certbuf); + size = sizeof(certname); rc = gnutls_x509_crt_get_dn_by_oid(x509_cert, GNUTLS_OID_X520_COMMON_NAME, 0, /* the first and only one */ FALSE, - certbuf, + certname, &size); if(rc) { infof(data, "error fetching CN from cert:%s\n", @@ -1322,16 +1102,16 @@ gtls_connect_step3(struct connectdata *conn, if(SSL_CONN_CONFIG(verifyhost)) { failf(data, "SSL: certificate subject name (%s) does not match " - "target host name '%s'", certbuf, dispname); + "target host name '%s'", certname, dispname); gnutls_x509_crt_deinit(x509_cert); return CURLE_PEER_FAILED_VERIFICATION; } else infof(data, "\t common name: %s (does not match '%s')\n", - certbuf, dispname); + certname, dispname); } else - infof(data, "\t common name: %s (matched)\n", certbuf); + infof(data, "\t common name: %s (matched)\n", certname); /* Check for time-based validity */ certclock = gnutls_x509_crt_get_expiration_time(x509_cert); @@ -1416,9 +1196,10 @@ gtls_connect_step3(struct connectdata *conn, gnutls_x509_crt_get_version(x509_cert)); - size = sizeof(certbuf); - gnutls_x509_crt_get_dn(x509_cert, certbuf, &size); - infof(data, "\t subject: %s\n", certbuf); + rc = gnutls_x509_crt_get_dn2(x509_cert, &certfields); + if(rc != 0) + return CURLE_OUT_OF_MEMORY; + infof(data, "\t subject: %s\n", certfields.data); certclock = gnutls_x509_crt_get_activation_time(x509_cert); showtime(data, "start date", certclock); @@ -1426,14 +1207,14 @@ gtls_connect_step3(struct connectdata *conn, certclock = gnutls_x509_crt_get_expiration_time(x509_cert); showtime(data, "expire date", certclock); - size = sizeof(certbuf); - gnutls_x509_crt_get_issuer_dn(x509_cert, certbuf, &size); - infof(data, "\t issuer: %s\n", certbuf); + rc = gnutls_x509_crt_get_issuer_dn2(x509_cert, &certfields); + if(rc != 0) + return CURLE_OUT_OF_MEMORY; + infof(data, "\t issuer: %s\n", certfields.data); #endif gnutls_x509_crt_deinit(x509_cert); -#ifdef HAS_ALPN if(conn->bits.tls_enable_alpn) { rc = gnutls_alpn_get_selected_protocol(session, &proto); if(rc == 0) { @@ -1459,7 +1240,6 @@ gtls_connect_step3(struct connectdata *conn, Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ? BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE); } -#endif conn->ssl[sockindex].state = ssl_connection_complete; conn->recv[sockindex] = gtls_recv; @@ -1577,13 +1357,14 @@ static bool Curl_gtls_data_pending(const struct connectdata *conn, { const struct ssl_connect_data *connssl = &conn->ssl[connindex]; bool res = FALSE; - if(BACKEND->session && - 0 != gnutls_record_check_pending(BACKEND->session)) + struct ssl_backend_data *backend = connssl->backend; + if(backend->session && + 0 != gnutls_record_check_pending(backend->session)) res = TRUE; connssl = &conn->proxy_ssl[connindex]; - if(BACKEND->session && - 0 != gnutls_record_check_pending(BACKEND->session)) + if(backend->session && + 0 != gnutls_record_check_pending(backend->session)) res = TRUE; return res; @@ -1596,7 +1377,8 @@ static ssize_t gtls_send(struct connectdata *conn, CURLcode *curlcode) { struct ssl_connect_data *connssl = &conn->ssl[sockindex]; - ssize_t rc = gnutls_record_send(BACKEND->session, mem, len); + struct ssl_backend_data *backend = connssl->backend; + ssize_t rc = gnutls_record_send(backend->session, mem, len); if(rc < 0) { *curlcode = (rc == GNUTLS_E_AGAIN) @@ -1611,19 +1393,20 @@ static ssize_t gtls_send(struct connectdata *conn, static void close_one(struct ssl_connect_data *connssl) { - if(BACKEND->session) { - gnutls_bye(BACKEND->session, GNUTLS_SHUT_WR); - gnutls_deinit(BACKEND->session); - BACKEND->session = NULL; + struct ssl_backend_data *backend = connssl->backend; + if(backend->session) { + gnutls_bye(backend->session, GNUTLS_SHUT_WR); + gnutls_deinit(backend->session); + backend->session = NULL; } - if(BACKEND->cred) { - gnutls_certificate_free_credentials(BACKEND->cred); - BACKEND->cred = NULL; + if(backend->cred) { + gnutls_certificate_free_credentials(backend->cred); + backend->cred = NULL; } #ifdef USE_TLS_SRP - if(BACKEND->srp_client_cred) { - gnutls_srp_free_client_credentials(BACKEND->srp_client_cred); - BACKEND->srp_client_cred = NULL; + if(backend->srp_client_cred) { + gnutls_srp_free_client_credentials(backend->srp_client_cred); + backend->srp_client_cred = NULL; } #endif } @@ -1641,6 +1424,7 @@ static void Curl_gtls_close(struct connectdata *conn, int sockindex) static int Curl_gtls_shutdown(struct connectdata *conn, int sockindex) { struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + struct ssl_backend_data *backend = connssl->backend; int retval = 0; struct Curl_easy *data = conn->data; @@ -1651,10 +1435,10 @@ static int Curl_gtls_shutdown(struct connectdata *conn, int sockindex) we do not send one. Let's hope other servers do the same... */ if(data->set.ftp_ccc == CURLFTPSSL_CCC_ACTIVE) - gnutls_bye(BACKEND->session, GNUTLS_SHUT_WR); + gnutls_bye(backend->session, GNUTLS_SHUT_WR); #endif - if(BACKEND->session) { + if(backend->session) { ssize_t result; bool done = FALSE; char buf[120]; @@ -1665,7 +1449,7 @@ static int Curl_gtls_shutdown(struct connectdata *conn, int sockindex) if(what > 0) { /* Something to read, let's do it and hope that it is the close notify alert from the server */ - result = gnutls_record_recv(BACKEND->session, + result = gnutls_record_recv(backend->session, buf, sizeof(buf)); switch(result) { case 0: @@ -1695,18 +1479,18 @@ static int Curl_gtls_shutdown(struct connectdata *conn, int sockindex) done = TRUE; } } - gnutls_deinit(BACKEND->session); + gnutls_deinit(backend->session); } - gnutls_certificate_free_credentials(BACKEND->cred); + gnutls_certificate_free_credentials(backend->cred); #ifdef USE_TLS_SRP if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP && SSL_SET_OPTION(username) != NULL) - gnutls_srp_free_client_credentials(BACKEND->srp_client_cred); + gnutls_srp_free_client_credentials(backend->srp_client_cred); #endif - BACKEND->cred = NULL; - BACKEND->session = NULL; + backend->cred = NULL; + backend->session = NULL; return retval; } @@ -1718,9 +1502,10 @@ static ssize_t gtls_recv(struct connectdata *conn, /* connection data */ CURLcode *curlcode) { struct ssl_connect_data *connssl = &conn->ssl[num]; + struct ssl_backend_data *backend = connssl->backend; ssize_t ret; - ret = gnutls_record_recv(BACKEND->session, buf, buffersize); + ret = gnutls_record_recv(backend->session, buf, buffersize); if((ret == GNUTLS_E_AGAIN) || (ret == GNUTLS_E_INTERRUPTED)) { *curlcode = CURLE_AGAIN; return -1; @@ -1836,18 +1621,15 @@ static CURLcode Curl_gtls_sha256sum(const unsigned char *tmp, /* input */ static bool Curl_gtls_cert_status_request(void) { -#ifdef HAS_OCSP return TRUE; -#else - return FALSE; -#endif } static void *Curl_gtls_get_internals(struct ssl_connect_data *connssl, CURLINFO info UNUSED_PARAM) { + struct ssl_backend_data *backend = connssl->backend; (void)info; - return BACKEND->session; + return backend->session; } const struct Curl_ssl Curl_ssl_gnutls = { diff --git a/libs/libcurl/src/vtls/mbedtls.c b/libs/libcurl/src/vtls/mbedtls.c index f057315f30..cbf3d3dec9 100644 --- a/libs/libcurl/src/vtls/mbedtls.c +++ b/libs/libcurl/src/vtls/mbedtls.c @@ -75,8 +75,6 @@ struct ssl_backend_data { const char *protocols[3]; }; -#define BACKEND connssl->backend - /* apply threading? */ #if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32) #define THREADING_SUPPORT @@ -196,6 +194,7 @@ set_ssl_version_min_max(struct connectdata *conn, int sockindex) { struct Curl_easy *data = conn->data; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + struct ssl_backend_data *backend = connssl->backend; int mbedtls_ver_min = MBEDTLS_SSL_MINOR_VERSION_1; int mbedtls_ver_max = MBEDTLS_SSL_MINOR_VERSION_1; long ssl_version = SSL_CONN_CONFIG(version); @@ -227,9 +226,9 @@ set_ssl_version_min_max(struct connectdata *conn, int sockindex) return result; } - mbedtls_ssl_conf_min_version(&BACKEND->config, MBEDTLS_SSL_MAJOR_VERSION_3, + mbedtls_ssl_conf_min_version(&backend->config, MBEDTLS_SSL_MAJOR_VERSION_3, mbedtls_ver_min); - mbedtls_ssl_conf_max_version(&BACKEND->config, MBEDTLS_SSL_MAJOR_VERSION_3, + mbedtls_ssl_conf_max_version(&backend->config, MBEDTLS_SSL_MAJOR_VERSION_3, mbedtls_ver_max); return result; @@ -241,6 +240,7 @@ mbed_connect_step1(struct connectdata *conn, { struct Curl_easy *data = conn->data; struct ssl_connect_data* connssl = &conn->ssl[sockindex]; + struct ssl_backend_data *backend = connssl->backend; const char * const ssl_cafile = SSL_CONN_CONFIG(CAfile); const bool verifypeer = SSL_CONN_CONFIG(verifypeer); const char * const ssl_capath = SSL_CONN_CONFIG(CApath); @@ -261,9 +261,9 @@ mbed_connect_step1(struct connectdata *conn, #ifdef THREADING_SUPPORT entropy_init_mutex(&ts_entropy); - mbedtls_ctr_drbg_init(&BACKEND->ctr_drbg); + mbedtls_ctr_drbg_init(&backend->ctr_drbg); - ret = mbedtls_ctr_drbg_seed(&BACKEND->ctr_drbg, entropy_func_mutex, + ret = mbedtls_ctr_drbg_seed(&backend->ctr_drbg, entropy_func_mutex, &ts_entropy, NULL, 0); if(ret) { #ifdef MBEDTLS_ERROR_C @@ -273,11 +273,11 @@ mbed_connect_step1(struct connectdata *conn, -ret, errorbuf); } #else - mbedtls_entropy_init(&BACKEND->entropy); - mbedtls_ctr_drbg_init(&BACKEND->ctr_drbg); + mbedtls_entropy_init(&backend->entropy); + mbedtls_ctr_drbg_init(&backend->ctr_drbg); - ret = mbedtls_ctr_drbg_seed(&BACKEND->ctr_drbg, mbedtls_entropy_func, - &BACKEND->entropy, NULL, 0); + ret = mbedtls_ctr_drbg_seed(&backend->ctr_drbg, mbedtls_entropy_func, + &backend->entropy, NULL, 0); if(ret) { #ifdef MBEDTLS_ERROR_C mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); @@ -288,10 +288,10 @@ mbed_connect_step1(struct connectdata *conn, #endif /* THREADING_SUPPORT */ /* Load the trusted CA */ - mbedtls_x509_crt_init(&BACKEND->cacert); + mbedtls_x509_crt_init(&backend->cacert); if(ssl_cafile) { - ret = mbedtls_x509_crt_parse_file(&BACKEND->cacert, ssl_cafile); + ret = mbedtls_x509_crt_parse_file(&backend->cacert, ssl_cafile); if(ret<0) { #ifdef MBEDTLS_ERROR_C @@ -306,7 +306,7 @@ mbed_connect_step1(struct connectdata *conn, } if(ssl_capath) { - ret = mbedtls_x509_crt_parse_path(&BACKEND->cacert, ssl_capath); + ret = mbedtls_x509_crt_parse_path(&backend->cacert, ssl_capath); if(ret<0) { #ifdef MBEDTLS_ERROR_C @@ -321,10 +321,10 @@ mbed_connect_step1(struct connectdata *conn, } /* Load the client certificate */ - mbedtls_x509_crt_init(&BACKEND->clicert); + mbedtls_x509_crt_init(&backend->clicert); if(ssl_cert) { - ret = mbedtls_x509_crt_parse_file(&BACKEND->clicert, ssl_cert); + ret = mbedtls_x509_crt_parse_file(&backend->clicert, ssl_cert); if(ret) { #ifdef MBEDTLS_ERROR_C @@ -338,13 +338,13 @@ mbed_connect_step1(struct connectdata *conn, } /* Load the client private key */ - mbedtls_pk_init(&BACKEND->pk); + mbedtls_pk_init(&backend->pk); if(SSL_SET_OPTION(key)) { - ret = mbedtls_pk_parse_keyfile(&BACKEND->pk, SSL_SET_OPTION(key), + ret = mbedtls_pk_parse_keyfile(&backend->pk, SSL_SET_OPTION(key), SSL_SET_OPTION(key_passwd)); - if(ret == 0 && !(mbedtls_pk_can_do(&BACKEND->pk, MBEDTLS_PK_RSA) || - mbedtls_pk_can_do(&BACKEND->pk, MBEDTLS_PK_ECKEY))) + if(ret == 0 && !(mbedtls_pk_can_do(&backend->pk, MBEDTLS_PK_RSA) || + mbedtls_pk_can_do(&backend->pk, MBEDTLS_PK_ECKEY))) ret = MBEDTLS_ERR_PK_TYPE_MISMATCH; if(ret) { @@ -359,10 +359,10 @@ mbed_connect_step1(struct connectdata *conn, } /* Load the CRL */ - mbedtls_x509_crl_init(&BACKEND->crl); + mbedtls_x509_crl_init(&backend->crl); if(ssl_crlfile) { - ret = mbedtls_x509_crl_parse_file(&BACKEND->crl, ssl_crlfile); + ret = mbedtls_x509_crl_parse_file(&backend->crl, ssl_crlfile); if(ret) { #ifdef MBEDTLS_ERROR_C @@ -377,14 +377,14 @@ mbed_connect_step1(struct connectdata *conn, infof(data, "mbedTLS: Connecting to %s:%ld\n", hostname, port); - mbedtls_ssl_config_init(&BACKEND->config); + mbedtls_ssl_config_init(&backend->config); - mbedtls_ssl_init(&BACKEND->ssl); - if(mbedtls_ssl_setup(&BACKEND->ssl, &BACKEND->config)) { + mbedtls_ssl_init(&backend->ssl); + if(mbedtls_ssl_setup(&backend->ssl, &backend->config)) { failf(data, "mbedTLS: ssl_init failed"); return CURLE_SSL_CONNECT_ERROR; } - ret = mbedtls_ssl_config_defaults(&BACKEND->config, + ret = mbedtls_ssl_config_defaults(&backend->config, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT); @@ -394,20 +394,20 @@ mbed_connect_step1(struct connectdata *conn, } /* new profile with RSA min key len = 1024 ... */ - mbedtls_ssl_conf_cert_profile(&BACKEND->config, + mbedtls_ssl_conf_cert_profile(&backend->config, &mbedtls_x509_crt_profile_fr); switch(SSL_CONN_CONFIG(version)) { case CURL_SSLVERSION_DEFAULT: case CURL_SSLVERSION_TLSv1: - mbedtls_ssl_conf_min_version(&BACKEND->config, MBEDTLS_SSL_MAJOR_VERSION_3, + mbedtls_ssl_conf_min_version(&backend->config, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1); infof(data, "mbedTLS: Set min SSL version to TLS 1.0\n"); break; case CURL_SSLVERSION_SSLv3: - mbedtls_ssl_conf_min_version(&BACKEND->config, MBEDTLS_SSL_MAJOR_VERSION_3, + mbedtls_ssl_conf_min_version(&backend->config, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0); - mbedtls_ssl_conf_max_version(&BACKEND->config, MBEDTLS_SSL_MAJOR_VERSION_3, + mbedtls_ssl_conf_max_version(&backend->config, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0); infof(data, "mbedTLS: Set SSL version to SSLv3\n"); break; @@ -426,25 +426,25 @@ mbed_connect_step1(struct connectdata *conn, return CURLE_SSL_CONNECT_ERROR; } - mbedtls_ssl_conf_authmode(&BACKEND->config, MBEDTLS_SSL_VERIFY_OPTIONAL); + mbedtls_ssl_conf_authmode(&backend->config, MBEDTLS_SSL_VERIFY_OPTIONAL); - mbedtls_ssl_conf_rng(&BACKEND->config, mbedtls_ctr_drbg_random, - &BACKEND->ctr_drbg); - mbedtls_ssl_set_bio(&BACKEND->ssl, &conn->sock[sockindex], + mbedtls_ssl_conf_rng(&backend->config, mbedtls_ctr_drbg_random, + &backend->ctr_drbg); + mbedtls_ssl_set_bio(&backend->ssl, &conn->sock[sockindex], mbedtls_net_send, mbedtls_net_recv, NULL /* rev_timeout() */); - mbedtls_ssl_conf_ciphersuites(&BACKEND->config, + mbedtls_ssl_conf_ciphersuites(&backend->config, mbedtls_ssl_list_ciphersuites()); #if defined(MBEDTLS_SSL_RENEGOTIATION) - mbedtls_ssl_conf_renegotiation(&BACKEND->config, + mbedtls_ssl_conf_renegotiation(&backend->config, MBEDTLS_SSL_RENEGOTIATION_ENABLED); #endif #if defined(MBEDTLS_SSL_SESSION_TICKETS) - mbedtls_ssl_conf_session_tickets(&BACKEND->config, + mbedtls_ssl_conf_session_tickets(&backend->config, MBEDTLS_SSL_SESSION_TICKETS_DISABLED); #endif @@ -454,7 +454,7 @@ mbed_connect_step1(struct connectdata *conn, Curl_ssl_sessionid_lock(conn); if(!Curl_ssl_getsessionid(conn, &old_session, NULL, sockindex)) { - ret = mbedtls_ssl_set_session(&BACKEND->ssl, old_session); + ret = mbedtls_ssl_set_session(&backend->ssl, old_session); if(ret) { Curl_ssl_sessionid_unlock(conn); failf(data, "mbedtls_ssl_set_session returned -0x%x", -ret); @@ -465,15 +465,15 @@ mbed_connect_step1(struct connectdata *conn, Curl_ssl_sessionid_unlock(conn); } - mbedtls_ssl_conf_ca_chain(&BACKEND->config, - &BACKEND->cacert, - &BACKEND->crl); + mbedtls_ssl_conf_ca_chain(&backend->config, + &backend->cacert, + &backend->crl); if(SSL_SET_OPTION(key)) { - mbedtls_ssl_conf_own_cert(&BACKEND->config, - &BACKEND->clicert, &BACKEND->pk); + mbedtls_ssl_conf_own_cert(&backend->config, + &backend->clicert, &backend->pk); } - if(mbedtls_ssl_set_hostname(&BACKEND->ssl, hostname)) { + if(mbedtls_ssl_set_hostname(&backend->ssl, hostname)) { /* mbedtls_ssl_set_hostname() sets the name to use in CN/SAN checks *and* the name to set in the SNI extension. So even if curl connects to a host specified as an IP address, this function must be used. */ @@ -483,7 +483,7 @@ mbed_connect_step1(struct connectdata *conn, #ifdef HAS_ALPN if(conn->bits.tls_enable_alpn) { - const char **p = &BACKEND->protocols[0]; + const char **p = &backend->protocols[0]; #ifdef USE_NGHTTP2 if(data->set.httpversion >= CURL_HTTP_VERSION_2) *p++ = NGHTTP2_PROTO_VERSION_ID; @@ -492,19 +492,19 @@ mbed_connect_step1(struct connectdata *conn, *p = NULL; /* this function doesn't clone the protocols array, which is why we need to keep it around */ - if(mbedtls_ssl_conf_alpn_protocols(&BACKEND->config, - &BACKEND->protocols[0])) { + if(mbedtls_ssl_conf_alpn_protocols(&backend->config, + &backend->protocols[0])) { failf(data, "Failed setting ALPN protocols"); return CURLE_SSL_CONNECT_ERROR; } - for(p = &BACKEND->protocols[0]; *p; ++p) + for(p = &backend->protocols[0]; *p; ++p) infof(data, "ALPN, offering %s\n", *p); } #endif #ifdef MBEDTLS_DEBUG /* In order to make that work in mbedtls MBEDTLS_DEBUG_C must be defined. */ - mbedtls_ssl_conf_dbg(&BACKEND->config, mbed_debug, data); + mbedtls_ssl_conf_dbg(&backend->config, mbed_debug, data); /* - 0 No debug * - 1 Error * - 2 State change @@ -516,7 +516,7 @@ mbed_connect_step1(struct connectdata *conn, /* give application a chance to interfere with mbedTLS set up. */ if(data->set.ssl.fsslctx) { - ret = (*data->set.ssl.fsslctx)(data, &BACKEND->config, + ret = (*data->set.ssl.fsslctx)(data, &backend->config, data->set.ssl.fsslctxp); if(ret) { failf(data, "error signaled by ssl ctx callback"); @@ -536,15 +536,16 @@ mbed_connect_step2(struct connectdata *conn, int ret; struct Curl_easy *data = conn->data; struct ssl_connect_data* connssl = &conn->ssl[sockindex]; + struct ssl_backend_data *backend = connssl->backend; const mbedtls_x509_crt *peercert; const char * const pinnedpubkey = SSL_IS_PROXY() ? - data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] : - data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]; + data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] : + data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]; conn->recv[sockindex] = mbed_recv; conn->send[sockindex] = mbed_send; - ret = mbedtls_ssl_handshake(&BACKEND->ssl); + ret = mbedtls_ssl_handshake(&backend->ssl); if(ret == MBEDTLS_ERR_SSL_WANT_READ) { connssl->connecting_state = ssl_connect_2_reading; @@ -566,10 +567,10 @@ mbed_connect_step2(struct connectdata *conn, } infof(data, "mbedTLS: Handshake complete, cipher is %s\n", - mbedtls_ssl_get_ciphersuite(&BACKEND->ssl) + mbedtls_ssl_get_ciphersuite(&backend->ssl) ); - ret = mbedtls_ssl_get_verify_result(&BACKEND->ssl); + ret = mbedtls_ssl_get_verify_result(&backend->ssl); if(!SSL_CONN_CONFIG(verifyhost)) /* Ignore hostname errors if verifyhost is disabled */ @@ -594,7 +595,7 @@ mbed_connect_step2(struct connectdata *conn, return CURLE_PEER_FAILED_VERIFICATION; } - peercert = mbedtls_ssl_get_peer_cert(&BACKEND->ssl); + peercert = mbedtls_ssl_get_peer_cert(&backend->ssl); if(peercert && data->set.verbose) { const size_t bufsize = 16384; @@ -664,7 +665,7 @@ mbed_connect_step2(struct connectdata *conn, #ifdef HAS_ALPN if(conn->bits.tls_enable_alpn) { - const char *next_protocol = mbedtls_ssl_get_alpn_protocol(&BACKEND->ssl); + const char *next_protocol = mbedtls_ssl_get_alpn_protocol(&backend->ssl); if(next_protocol) { infof(data, "ALPN, server accepted to use %s\n", next_protocol); @@ -701,6 +702,7 @@ mbed_connect_step3(struct connectdata *conn, { CURLcode retcode = CURLE_OK; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + struct ssl_backend_data *backend = connssl->backend; struct Curl_easy *data = conn->data; DEBUGASSERT(ssl_connect_3 == connssl->connecting_state); @@ -716,7 +718,7 @@ mbed_connect_step3(struct connectdata *conn, mbedtls_ssl_session_init(our_ssl_sessionid); - ret = mbedtls_ssl_get_session(&BACKEND->ssl, our_ssl_sessionid); + ret = mbedtls_ssl_get_session(&backend->ssl, our_ssl_sessionid); if(ret) { if(ret != MBEDTLS_ERR_SSL_ALLOC_FAILED) mbedtls_ssl_session_free(our_ssl_sessionid); @@ -750,9 +752,10 @@ static ssize_t mbed_send(struct connectdata *conn, int sockindex, CURLcode *curlcode) { struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + struct ssl_backend_data *backend = connssl->backend; int ret = -1; - ret = mbedtls_ssl_write(&BACKEND->ssl, + ret = mbedtls_ssl_write(&backend->ssl, (unsigned char *)mem, len); if(ret < 0) { @@ -772,15 +775,16 @@ static void Curl_mbedtls_close_all(struct Curl_easy *data) static void Curl_mbedtls_close(struct connectdata *conn, int sockindex) { struct ssl_connect_data *connssl = &conn->ssl[sockindex]; - mbedtls_pk_free(&BACKEND->pk); - mbedtls_x509_crt_free(&BACKEND->clicert); - mbedtls_x509_crt_free(&BACKEND->cacert); - mbedtls_x509_crl_free(&BACKEND->crl); - mbedtls_ssl_config_free(&BACKEND->config); - mbedtls_ssl_free(&BACKEND->ssl); - mbedtls_ctr_drbg_free(&BACKEND->ctr_drbg); + struct ssl_backend_data *backend = connssl->backend; + mbedtls_pk_free(&backend->pk); + mbedtls_x509_crt_free(&backend->clicert); + mbedtls_x509_crt_free(&backend->cacert); + mbedtls_x509_crl_free(&backend->crl); + mbedtls_ssl_config_free(&backend->config); + mbedtls_ssl_free(&backend->ssl); + mbedtls_ctr_drbg_free(&backend->ctr_drbg); #ifndef THREADING_SUPPORT - mbedtls_entropy_free(&BACKEND->entropy); + mbedtls_entropy_free(&backend->entropy); #endif /* THREADING_SUPPORT */ } @@ -789,11 +793,12 @@ static ssize_t mbed_recv(struct connectdata *conn, int num, CURLcode *curlcode) { struct ssl_connect_data *connssl = &conn->ssl[num]; + struct ssl_backend_data *backend = connssl->backend; int ret = -1; ssize_t len = -1; memset(buf, 0, buffersize); - ret = mbedtls_ssl_read(&BACKEND->ssl, (unsigned char *)buf, + ret = mbedtls_ssl_read(&backend->ssl, (unsigned char *)buf, buffersize); if(ret <= 0) { @@ -1029,7 +1034,8 @@ static bool Curl_mbedtls_data_pending(const struct connectdata *conn, int sockindex) { const struct ssl_connect_data *connssl = &conn->ssl[sockindex]; - return mbedtls_ssl_get_bytes_avail(&BACKEND->ssl) != 0; + struct ssl_backend_data *backend = connssl->backend; + return mbedtls_ssl_get_bytes_avail(&backend->ssl) != 0; } static CURLcode Curl_mbedtls_sha256sum(const unsigned char *input, @@ -1051,8 +1057,9 @@ static CURLcode Curl_mbedtls_sha256sum(const unsigned char *input, static void *Curl_mbedtls_get_internals(struct ssl_connect_data *connssl, CURLINFO info UNUSED_PARAM) { + struct ssl_backend_data *backend = connssl->backend; (void)info; - return &BACKEND->ssl; + return &backend->ssl; } const struct Curl_ssl Curl_ssl_mbedtls = { diff --git a/libs/libcurl/src/vtls/nss.c b/libs/libcurl/src/vtls/nss.c index ef51b0d912..16ec409e92 100644 --- a/libs/libcurl/src/vtls/nss.c +++ b/libs/libcurl/src/vtls/nss.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2020, 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 @@ -87,8 +87,6 @@ struct ssl_backend_data { PK11GenericObject *obj_clicert; }; -#define BACKEND connssl->backend - static PRLock *nss_initlock = NULL; static PRLock *nss_crllock = NULL; static PRLock *nss_findslot_lock = NULL; @@ -462,6 +460,7 @@ static CURLcode nss_create_object(struct ssl_connect_data *connssl, const int slot_id = (cacert) ? 0 : 1; char *slot_name = aprintf("PEM Token #%d", slot_id); + struct ssl_backend_data *backend = connssl->backend; if(!slot_name) return CURLE_OUT_OF_MEMORY; @@ -495,14 +494,14 @@ static CURLcode nss_create_object(struct ssl_connect_data *connssl, if(!obj) return result; - if(insert_wrapped_ptr(&BACKEND->obj_list, obj) != CURLE_OK) { + if(insert_wrapped_ptr(&backend->obj_list, obj) != CURLE_OK) { PK11_DestroyGenericObject(obj); return CURLE_OUT_OF_MEMORY; } if(!cacert && CKO_CERTIFICATE == obj_class) /* store reference to a client certificate */ - BACKEND->obj_clicert = obj; + backend->obj_clicert = obj; return CURLE_OK; } @@ -1084,7 +1083,8 @@ static CURLcode cmp_peer_pubkey(struct ssl_connect_data *connssl, const char *pinnedpubkey) { CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH; - struct Curl_easy *data = BACKEND->data; + struct ssl_backend_data *backend = connssl->backend; + struct Curl_easy *data = backend->data; CERTCertificate *cert; if(!pinnedpubkey) @@ -1092,7 +1092,7 @@ static CURLcode cmp_peer_pubkey(struct ssl_connect_data *connssl, return CURLE_OK; /* get peer certificate */ - cert = SSL_PeerCertificate(BACKEND->handle); + cert = SSL_PeerCertificate(backend->handle); if(cert) { /* extract public key from peer certificate */ SECKEYPublicKey *pubkey = CERT_ExtractPublicKey(cert); @@ -1136,11 +1136,12 @@ static SECStatus SelectClientCert(void *arg, PRFileDesc *sock, struct SECKEYPrivateKeyStr **pRetKey) { struct ssl_connect_data *connssl = (struct ssl_connect_data *)arg; - struct Curl_easy *data = BACKEND->data; - const char *nickname = BACKEND->client_nickname; + struct ssl_backend_data *backend = connssl->backend; + struct Curl_easy *data = backend->data; + const char *nickname = backend->client_nickname; static const char pem_slotname[] = "PEM Token #1"; - if(BACKEND->obj_clicert) { + if(backend->obj_clicert) { /* use the cert/key provided by PEM reader */ SECItem cert_der = { 0, NULL, 0 }; void *proto_win = SSL_RevealPinArg(sock); @@ -1153,7 +1154,7 @@ static SECStatus SelectClientCert(void *arg, PRFileDesc *sock, return SECFailure; } - if(PK11_ReadRawAttribute(PK11_TypeGeneric, BACKEND->obj_clicert, CKA_VALUE, + if(PK11_ReadRawAttribute(PK11_TypeGeneric, backend->obj_clicert, CKA_VALUE, &cert_der) != SECSuccess) { failf(data, "NSS: CKA_VALUE not found in PK11 generic object"); PK11_FreeSlot(slot); @@ -1503,11 +1504,12 @@ static void Curl_nss_cleanup(void) static int Curl_nss_check_cxn(struct connectdata *conn) { struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET]; + struct ssl_backend_data *backend = connssl->backend; int rc; char buf; rc = - PR_Recv(BACKEND->handle, (void *)&buf, 1, PR_MSG_PEEK, + PR_Recv(backend->handle, (void *)&buf, 1, PR_MSG_PEEK, PR_SecondsToInterval(1)); if(rc > 0) return 1; /* connection still in place */ @@ -1521,26 +1523,27 @@ static int Curl_nss_check_cxn(struct connectdata *conn) static void nss_close(struct ssl_connect_data *connssl) { /* before the cleanup, check whether we are using a client certificate */ - const bool client_cert = (BACKEND->client_nickname != NULL) - || (BACKEND->obj_clicert != NULL); + struct ssl_backend_data *backend = connssl->backend; + const bool client_cert = (backend->client_nickname != NULL) + || (backend->obj_clicert != NULL); - free(BACKEND->client_nickname); - BACKEND->client_nickname = NULL; + free(backend->client_nickname); + backend->client_nickname = NULL; /* destroy all NSS objects in order to avoid failure of NSS shutdown */ - Curl_llist_destroy(&BACKEND->obj_list, NULL); - BACKEND->obj_clicert = NULL; + Curl_llist_destroy(&backend->obj_list, NULL); + backend->obj_clicert = NULL; - if(BACKEND->handle) { + if(backend->handle) { if(client_cert) /* A server might require different authentication based on the * particular path being requested by the client. To support this * scenario, we must ensure that a connection will never reuse the * authentication data from a previous connection. */ - SSL_InvalidateSession(BACKEND->handle); + SSL_InvalidateSession(backend->handle); - PR_Close(BACKEND->handle); - BACKEND->handle = NULL; + PR_Close(backend->handle); + backend->handle = NULL; } } @@ -1551,15 +1554,16 @@ static void Curl_nss_close(struct connectdata *conn, int sockindex) { struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_connect_data *connssl_proxy = &conn->proxy_ssl[sockindex]; + struct ssl_backend_data *backend = connssl->backend; - if(BACKEND->handle || connssl_proxy->backend->handle) { + if(backend->handle || connssl_proxy->backend->handle) { /* NSS closes the socket we previously handed to it, so we must mark it as closed to avoid double close */ fake_sclose(conn->sock[sockindex]); conn->sock[sockindex] = CURL_SOCKET_BAD; } - if(BACKEND->handle) + if(backend->handle) /* nss_close(connssl) will transitively close also connssl_proxy->backend->handle if both are used. Clear it to avoid a double close leading to crash. */ @@ -1773,6 +1777,7 @@ static CURLcode nss_fail_connect(struct ssl_connect_data *connssl, CURLcode curlerr) { PRErrorCode err = 0; + struct ssl_backend_data *backend = connssl->backend; if(is_nss_error(curlerr)) { /* read NSPR error code */ @@ -1788,7 +1793,7 @@ static CURLcode nss_fail_connect(struct ssl_connect_data *connssl, } /* cleanup on connection failure */ - Curl_llist_destroy(&BACKEND->obj_list, NULL); + Curl_llist_destroy(&backend->obj_list, NULL); return curlerr; } @@ -1799,10 +1804,11 @@ static CURLcode nss_set_blocking(struct ssl_connect_data *connssl, bool blocking) { static PRSocketOptionData sock_opt; + struct ssl_backend_data *backend = connssl->backend; sock_opt.option = PR_SockOpt_Nonblocking; sock_opt.value.non_blocking = !blocking; - if(PR_SetSocketOption(BACKEND->handle, &sock_opt) != PR_SUCCESS) + if(PR_SetSocketOption(backend->handle, &sock_opt) != PR_SUCCESS) return nss_fail_connect(connssl, data, CURLE_SSL_CONNECT_ERROR); return CURLE_OK; @@ -1818,6 +1824,7 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex) struct Curl_easy *data = conn->data; curl_socket_t sockfd = conn->sock[sockindex]; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + struct ssl_backend_data *backend = connssl->backend; CURLcode result; bool second_layer = FALSE; SSLVersionRange sslver_supported; @@ -1835,10 +1842,10 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex) #endif }; - BACKEND->data = data; + backend->data = data; /* list of all NSS objects we need to destroy in Curl_nss_close() */ - Curl_llist_init(&BACKEND->obj_list, nss_destroy_object); + Curl_llist_init(&backend->obj_list, nss_destroy_object); PR_Lock(nss_initlock); result = nss_init(conn->data); @@ -1960,7 +1967,7 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex) char *nickname = dup_nickname(data, SSL_SET_OPTION(cert)); if(nickname) { /* we are not going to use libnsspem.so to read the client cert */ - BACKEND->obj_clicert = NULL; + backend->obj_clicert = NULL; } else { CURLcode rv = cert_stuff(conn, sockindex, SSL_SET_OPTION(cert), @@ -1973,10 +1980,10 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex) } /* store the nickname for SelectClientCert() called during handshake */ - BACKEND->client_nickname = nickname; + backend->client_nickname = nickname; } else - BACKEND->client_nickname = NULL; + backend->client_nickname = NULL; if(SSL_GetClientAuthDataHook(model, SelectClientCert, (void *)connssl) != SECSuccess) { @@ -2017,8 +2024,8 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex) } /* import our model socket onto the current I/O stack */ - BACKEND->handle = SSL_ImportFD(model, nspr_io); - if(!BACKEND->handle) { + backend->handle = SSL_ImportFD(model, nspr_io); + if(!backend->handle) { if(!second_layer) PR_Close(nspr_io); goto error; @@ -2029,36 +2036,36 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex) /* This is the password associated with the cert that we're using */ if(SSL_SET_OPTION(key_passwd)) { - SSL_SetPKCS11PinArg(BACKEND->handle, SSL_SET_OPTION(key_passwd)); + SSL_SetPKCS11PinArg(backend->handle, SSL_SET_OPTION(key_passwd)); } #ifdef SSL_ENABLE_OCSP_STAPLING if(SSL_CONN_CONFIG(verifystatus)) { - if(SSL_OptionSet(BACKEND->handle, SSL_ENABLE_OCSP_STAPLING, PR_TRUE) + if(SSL_OptionSet(backend->handle, SSL_ENABLE_OCSP_STAPLING, PR_TRUE) != SECSuccess) goto error; } #endif #ifdef SSL_ENABLE_NPN - if(SSL_OptionSet(BACKEND->handle, SSL_ENABLE_NPN, conn->bits.tls_enable_npn + if(SSL_OptionSet(backend->handle, SSL_ENABLE_NPN, conn->bits.tls_enable_npn ? PR_TRUE : PR_FALSE) != SECSuccess) goto error; #endif #ifdef SSL_ENABLE_ALPN - if(SSL_OptionSet(BACKEND->handle, SSL_ENABLE_ALPN, conn->bits.tls_enable_alpn + if(SSL_OptionSet(backend->handle, SSL_ENABLE_ALPN, conn->bits.tls_enable_alpn ? PR_TRUE : PR_FALSE) != SECSuccess) goto error; #endif #if NSSVERNUM >= 0x030f04 /* 3.15.4 */ if(data->set.ssl.falsestart) { - if(SSL_OptionSet(BACKEND->handle, SSL_ENABLE_FALSE_START, PR_TRUE) + if(SSL_OptionSet(backend->handle, SSL_ENABLE_FALSE_START, PR_TRUE) != SECSuccess) goto error; - if(SSL_SetCanFalseStartCallback(BACKEND->handle, CanFalseStartCallback, + if(SSL_SetCanFalseStartCallback(backend->handle, CanFalseStartCallback, conn) != SECSuccess) goto error; } @@ -2082,24 +2089,24 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex) memcpy(&protocols[cur], ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH); cur += ALPN_HTTP_1_1_LENGTH; - if(SSL_SetNextProtoNego(BACKEND->handle, protocols, cur) != SECSuccess) + if(SSL_SetNextProtoNego(backend->handle, protocols, cur) != SECSuccess) goto error; } #endif /* Force handshake on next I/O */ - if(SSL_ResetHandshake(BACKEND->handle, /* asServer */ PR_FALSE) + if(SSL_ResetHandshake(backend->handle, /* asServer */ PR_FALSE) != SECSuccess) goto error; /* propagate hostname to the TLS layer */ - if(SSL_SetURL(BACKEND->handle, SSL_IS_PROXY() ? conn->http_proxy.host.name : + if(SSL_SetURL(backend->handle, SSL_IS_PROXY() ? conn->http_proxy.host.name : conn->host.name) != SECSuccess) goto error; /* prevent NSS from re-using the session for a different hostname */ - if(SSL_SetSockPeerID(BACKEND->handle, SSL_IS_PROXY() ? + if(SSL_SetSockPeerID(backend->handle, SSL_IS_PROXY() ? conn->http_proxy.host.name : conn->host.name) != SECSuccess) goto error; @@ -2116,6 +2123,7 @@ error: static CURLcode nss_do_connect(struct connectdata *conn, int sockindex) { struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + struct ssl_backend_data *backend = connssl->backend; struct Curl_easy *data = conn->data; CURLcode result = CURLE_SSL_CONNECT_ERROR; PRUint32 timeout; @@ -2136,7 +2144,7 @@ static CURLcode nss_do_connect(struct connectdata *conn, int sockindex) /* Force the handshake now */ timeout = PR_MillisecondsToInterval((PRUint32) time_left); - if(SSL_ForceHandshakeWithTimeout(BACKEND->handle, timeout) != SECSuccess) { + if(SSL_ForceHandshakeWithTimeout(backend->handle, timeout) != SECSuccess) { if(PR_GetError() == PR_WOULD_BLOCK_ERROR) /* blocking direction is updated by nss_update_connecting_state() */ return CURLE_AGAIN; @@ -2147,7 +2155,7 @@ static CURLcode nss_do_connect(struct connectdata *conn, int sockindex) goto error; } - result = display_conn_info(conn, BACKEND->handle); + result = display_conn_info(conn, backend->handle); if(result) goto error; @@ -2156,7 +2164,7 @@ static CURLcode nss_do_connect(struct connectdata *conn, int sockindex) char *nickname = dup_nickname(data, SSL_SET_OPTION(issuercert)); if(nickname) { /* we support only nicknames in case of issuercert for now */ - ret = check_issuer_cert(BACKEND->handle, nickname); + ret = check_issuer_cert(backend->handle, nickname); free(nickname); } @@ -2260,13 +2268,14 @@ static ssize_t nss_send(struct connectdata *conn, /* connection data */ CURLcode *curlcode) { struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + struct ssl_backend_data *backend = connssl->backend; ssize_t rc; /* The SelectClientCert() hook uses this for infof() and failf() but the handle stored in nss_setup_connect() could have already been freed. */ - BACKEND->data = conn->data; + backend->data = conn->data; - rc = PR_Send(BACKEND->handle, mem, (int)len, 0, PR_INTERVAL_NO_WAIT); + rc = PR_Send(backend->handle, mem, (int)len, 0, PR_INTERVAL_NO_WAIT); if(rc < 0) { PRInt32 err = PR_GetError(); if(err == PR_WOULD_BLOCK_ERROR) @@ -2297,13 +2306,14 @@ static ssize_t nss_recv(struct connectdata *conn, /* connection data */ CURLcode *curlcode) { struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + struct ssl_backend_data *backend = connssl->backend; ssize_t nread; /* The SelectClientCert() hook uses this for infof() and failf() but the handle stored in nss_setup_connect() could have already been freed. */ - BACKEND->data = conn->data; + backend->data = conn->data; - nread = PR_Recv(BACKEND->handle, buf, (int)buffersize, 0, + nread = PR_Recv(backend->handle, buf, (int)buffersize, 0, PR_INTERVAL_NO_WAIT); if(nread < 0) { /* failed SSL read */ @@ -2364,6 +2374,9 @@ static CURLcode Curl_nss_md5sum(unsigned char *tmp, /* input */ PK11Context *MD5pw = PK11_CreateDigestContext(SEC_OID_MD5); unsigned int MD5out; + if(!MD5pw) + return CURLE_NOT_BUILT_IN; + PK11_DigestOp(MD5pw, tmp, curlx_uztoui(tmplen)); PK11_DigestFinal(MD5pw, md5sum, &MD5out, curlx_uztoui(md5len)); PK11_DestroyContext(MD5pw, PR_TRUE); @@ -2379,6 +2392,9 @@ static CURLcode Curl_nss_sha256sum(const unsigned char *tmp, /* input */ PK11Context *SHA256pw = PK11_CreateDigestContext(SEC_OID_SHA256); unsigned int SHA256out; + if(!SHA256pw) + return CURLE_NOT_BUILT_IN; + PK11_DigestOp(SHA256pw, tmp, curlx_uztoui(tmplen)); PK11_DigestFinal(SHA256pw, sha256sum, &SHA256out, curlx_uztoui(sha256len)); PK11_DestroyContext(SHA256pw, PR_TRUE); @@ -2407,8 +2423,9 @@ static bool Curl_nss_false_start(void) static void *Curl_nss_get_internals(struct ssl_connect_data *connssl, CURLINFO info UNUSED_PARAM) { + struct ssl_backend_data *backend = connssl->backend; (void)info; - return BACKEND->handle; + return backend->handle; } const struct Curl_ssl Curl_ssl_nss = { diff --git a/libs/libcurl/src/vtls/openssl.c b/libs/libcurl/src/vtls/openssl.c index 1d09cadca8..176fa522a5 100644 --- a/libs/libcurl/src/vtls/openssl.c +++ b/libs/libcurl/src/vtls/openssl.c @@ -228,8 +228,6 @@ struct ssl_backend_data { #endif }; -#define BACKEND connssl->backend - /* * Number of bytes to read from the random number seed file. This must be * a finite value (because some entropy "files" like /dev/urandom have @@ -1269,19 +1267,19 @@ static struct curl_slist *Curl_ossl_engines_list(struct Curl_easy *data) return list; } - static void ossl_close(struct ssl_connect_data *connssl) { - if(BACKEND->handle) { - (void)SSL_shutdown(BACKEND->handle); - SSL_set_connect_state(BACKEND->handle); + struct ssl_backend_data *backend = connssl->backend; + if(backend->handle) { + (void)SSL_shutdown(backend->handle); + SSL_set_connect_state(backend->handle); - SSL_free(BACKEND->handle); - BACKEND->handle = NULL; + SSL_free(backend->handle); + backend->handle = NULL; } - if(BACKEND->ctx) { - SSL_CTX_free(BACKEND->ctx); - BACKEND->ctx = NULL; + if(backend->ctx) { + SSL_CTX_free(backend->ctx); + backend->ctx = NULL; } } @@ -1310,6 +1308,7 @@ static int Curl_ossl_shutdown(struct connectdata *conn, int sockindex) int buffsize; int err; bool done = FALSE; + struct ssl_backend_data *backend = connssl->backend; #ifndef CURL_DISABLE_FTP /* This has only been tested on the proftpd server, and the mod_tls code @@ -1318,10 +1317,10 @@ static int Curl_ossl_shutdown(struct connectdata *conn, int sockindex) we do not send one. Let's hope other servers do the same... */ if(data->set.ftp_ccc == CURLFTPSSL_CCC_ACTIVE) - (void)SSL_shutdown(BACKEND->handle); + (void)SSL_shutdown(backend->handle); #endif - if(BACKEND->handle) { + if(backend->handle) { buffsize = (int)sizeof(buf); while(!done) { int what = SOCKET_READABLE(conn->sock[sockindex], @@ -1331,8 +1330,8 @@ static int Curl_ossl_shutdown(struct connectdata *conn, int sockindex) /* Something to read, let's do it and hope that it is the close notify alert from the server */ - nread = (ssize_t)SSL_read(BACKEND->handle, buf, buffsize); - err = SSL_get_error(BACKEND->handle, (int)nread); + nread = (ssize_t)SSL_read(backend->handle, buf, buffsize); + err = SSL_get_error(backend->handle, (int)nread); switch(err) { case SSL_ERROR_NONE: /* this is not an error */ @@ -1377,7 +1376,7 @@ static int Curl_ossl_shutdown(struct connectdata *conn, int sockindex) if(data->set.verbose) { #ifdef HAVE_SSL_GET_SHUTDOWN - switch(SSL_get_shutdown(BACKEND->handle)) { + switch(SSL_get_shutdown(backend->handle)) { case SSL_SENT_SHUTDOWN: infof(data, "SSL_get_shutdown() returned SSL_SENT_SHUTDOWN\n"); break; @@ -1392,8 +1391,8 @@ static int Curl_ossl_shutdown(struct connectdata *conn, int sockindex) #endif } - SSL_free(BACKEND->handle); - BACKEND->handle = NULL; + SSL_free(backend->handle); + backend->handle = NULL; } return retval; } @@ -1712,13 +1711,13 @@ static CURLcode verifystatus(struct connectdata *conn, const unsigned char *p; CURLcode result = CURLE_OK; struct Curl_easy *data = conn->data; - OCSP_RESPONSE *rsp = NULL; OCSP_BASICRESP *br = NULL; X509_STORE *st = NULL; STACK_OF(X509) *ch = NULL; + struct ssl_backend_data *backend = connssl->backend; - long len = SSL_get_tlsext_status_ocsp_resp(BACKEND->handle, &status); + long len = SSL_get_tlsext_status_ocsp_resp(backend->handle, &status); if(!status) { failf(data, "No OCSP response received"); @@ -1748,8 +1747,8 @@ static CURLcode verifystatus(struct connectdata *conn, goto end; } - ch = SSL_get_peer_cert_chain(BACKEND->handle); - st = SSL_CTX_get_cert_store(BACKEND->ctx); + ch = SSL_get_peer_cert_chain(backend->handle); + st = SSL_CTX_get_cert_store(backend->ctx); #if ((OPENSSL_VERSION_NUMBER <= 0x1000201fL) /* Fixed after 1.0.2a */ || \ (defined(LIBRESSL_VERSION_NUMBER) && \ @@ -1825,7 +1824,8 @@ static CURLcode verifystatus(struct connectdata *conn, } end: - if(br) OCSP_BASICRESP_free(br); + if(br) + OCSP_BASICRESP_free(br); OCSP_RESPONSE_free(rsp); return result; @@ -2270,7 +2270,7 @@ set_ssl_version_min_max_legacy(ctx_option_t *ctx_options, #ifdef TLS1_3_VERSION { struct ssl_connect_data *connssl = &conn->ssl[sockindex]; - SSL_CTX_set_max_proto_version(BACKEND->ctx, TLS1_3_VERSION); + SSL_CTX_set_max_proto_version(backend->ctx, TLS1_3_VERSION); *ctx_options |= SSL_OP_NO_TLSv1_2; } #else @@ -2419,6 +2419,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) const bool verifypeer = SSL_CONN_CONFIG(verifypeer); const char * const ssl_crlfile = SSL_SET_OPTION(CRLfile); char error_buffer[256]; + struct ssl_backend_data *backend = connssl->backend; DEBUGASSERT(ssl_connect_1 == connssl->connecting_state); @@ -2477,25 +2478,25 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) return CURLE_SSL_CONNECT_ERROR; } - if(BACKEND->ctx) - SSL_CTX_free(BACKEND->ctx); - BACKEND->ctx = SSL_CTX_new(req_method); + if(backend->ctx) + SSL_CTX_free(backend->ctx); + backend->ctx = SSL_CTX_new(req_method); - if(!BACKEND->ctx) { + if(!backend->ctx) { failf(data, "SSL: couldn't create a context: %s", ossl_strerror(ERR_peek_error(), error_buffer, sizeof(error_buffer))); return CURLE_OUT_OF_MEMORY; } #ifdef SSL_MODE_RELEASE_BUFFERS - SSL_CTX_set_mode(BACKEND->ctx, SSL_MODE_RELEASE_BUFFERS); + SSL_CTX_set_mode(backend->ctx, SSL_MODE_RELEASE_BUFFERS); #endif #ifdef SSL_CTRL_SET_MSG_CALLBACK if(data->set.fdebug && data->set.verbose) { /* the SSL trace callback is only used for verbose logging */ - SSL_CTX_set_msg_callback(BACKEND->ctx, ssl_tls_trace); - SSL_CTX_set_msg_callback_arg(BACKEND->ctx, conn); + SSL_CTX_set_msg_callback(backend->ctx, ssl_tls_trace); + SSL_CTX_set_msg_callback_arg(backend->ctx, conn); } #endif @@ -2561,8 +2562,8 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) /* "--sslv2" option means SSLv2 only, disable all others */ case CURL_SSLVERSION_SSLv2: #if OPENSSL_VERSION_NUMBER >= 0x10100000L /* 1.1.0 */ - SSL_CTX_set_min_proto_version(BACKEND->ctx, SSL2_VERSION); - SSL_CTX_set_max_proto_version(BACKEND->ctx, SSL2_VERSION); + SSL_CTX_set_min_proto_version(backend->ctx, SSL2_VERSION); + SSL_CTX_set_max_proto_version(backend->ctx, SSL2_VERSION); #else ctx_options |= SSL_OP_NO_SSLv3; ctx_options |= SSL_OP_NO_TLSv1; @@ -2579,8 +2580,8 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) /* "--sslv3" option means SSLv3 only, disable all others */ case CURL_SSLVERSION_SSLv3: #if OPENSSL_VERSION_NUMBER >= 0x10100000L /* 1.1.0 */ - SSL_CTX_set_min_proto_version(BACKEND->ctx, SSL3_VERSION); - SSL_CTX_set_max_proto_version(BACKEND->ctx, SSL3_VERSION); + SSL_CTX_set_min_proto_version(backend->ctx, SSL3_VERSION); + SSL_CTX_set_max_proto_version(backend->ctx, SSL3_VERSION); #else ctx_options |= SSL_OP_NO_SSLv2; ctx_options |= SSL_OP_NO_TLSv1; @@ -2607,7 +2608,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) ctx_options |= SSL_OP_NO_SSLv3; #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) /* 1.1.0 */ - result = set_ssl_version_min_max(BACKEND->ctx, conn); + result = set_ssl_version_min_max(backend->ctx, conn); #else result = set_ssl_version_min_max_legacy(&ctx_options, conn, sockindex); #endif @@ -2620,11 +2621,11 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) return CURLE_SSL_CONNECT_ERROR; } - SSL_CTX_set_options(BACKEND->ctx, ctx_options); + SSL_CTX_set_options(backend->ctx, ctx_options); #ifdef HAS_NPN if(conn->bits.tls_enable_npn) - SSL_CTX_set_next_proto_select_cb(BACKEND->ctx, select_next_proto_cb, conn); + SSL_CTX_set_next_proto_select_cb(backend->ctx, select_next_proto_cb, conn); #endif #ifdef HAS_ALPN @@ -2652,12 +2653,12 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) /* expects length prefixed preference ordered list of protocols in wire * format */ - SSL_CTX_set_alpn_protos(BACKEND->ctx, protocols, cur); + SSL_CTX_set_alpn_protos(backend->ctx, protocols, cur); } #endif if(ssl_cert || ssl_cert_type) { - if(!cert_stuff(conn, BACKEND->ctx, ssl_cert, ssl_cert_type, + if(!cert_stuff(conn, backend->ctx, ssl_cert, ssl_cert_type, SSL_SET_OPTION(key), SSL_SET_OPTION(key_type), SSL_SET_OPTION(key_passwd))) { /* failf() is already done in cert_stuff() */ @@ -2669,7 +2670,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) if(!ciphers) ciphers = (char *)DEFAULT_CIPHER_SELECTION; if(ciphers) { - if(!SSL_CTX_set_cipher_list(BACKEND->ctx, ciphers)) { + if(!SSL_CTX_set_cipher_list(backend->ctx, ciphers)) { failf(data, "failed setting cipher list: %s", ciphers); return CURLE_SSL_CIPHER; } @@ -2680,7 +2681,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) { char *ciphers13 = SSL_CONN_CONFIG(cipher_list13); if(ciphers13) { - if(!SSL_CTX_set_ciphersuites(BACKEND->ctx, ciphers13)) { + if(!SSL_CTX_set_ciphersuites(backend->ctx, ciphers13)) { failf(data, "failed setting TLS 1.3 cipher suite: %s", ciphers13); return CURLE_SSL_CIPHER; } @@ -2691,7 +2692,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) #ifdef HAVE_SSL_CTX_SET_POST_HANDSHAKE_AUTH /* OpenSSL 1.1.1 requires clients to opt-in for PHA */ - SSL_CTX_set_post_handshake_auth(BACKEND->ctx, 1); + SSL_CTX_set_post_handshake_auth(backend->ctx, 1); #endif #ifdef USE_TLS_SRP @@ -2700,18 +2701,18 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) infof(data, "Using TLS-SRP username: %s\n", ssl_username); - if(!SSL_CTX_set_srp_username(BACKEND->ctx, 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_SET_OPTION(password))) { failf(data, "failed setting SRP password"); return CURLE_BAD_FUNCTION_ARGUMENT; } if(!SSL_CONN_CONFIG(cipher_list)) { infof(data, "Setting cipher list SRP\n"); - if(!SSL_CTX_set_cipher_list(BACKEND->ctx, "SRP")) { + if(!SSL_CTX_set_cipher_list(backend->ctx, "SRP")) { failf(data, "failed setting SRP cipher list"); return CURLE_SSL_CIPHER; } @@ -2719,10 +2720,37 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) } #endif +#if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3) + /* OpenSSL 3.0.0 has deprecated SSL_CTX_load_verify_locations */ + if(ssl_cafile) { + if(!SSL_CTX_load_verify_file(backend->ctx, ssl_cafile)) { + if(verifypeer) { + /* Fail if we insist on successfully verifying the server. */ + failf(data, "error setting certificate file: %s", ssl_cafile); + return CURLE_SSL_CACERT_BADFILE; + } + /* Continue with a warning if no certificate verification is required. */ + infof(data, "error setting certificate file, continuing anyway\n"); + } + infof(data, " CAfile: %s\n", ssl_cafile); + } + if(ssl_capath) { + if(!SSL_CTX_load_verify_dir(backend->ctx, ssl_capath)) { + if(verifypeer) { + /* Fail if we insist on successfully verifying the server. */ + failf(data, "error setting certificate path: %s", ssl_capath); + return CURLE_SSL_CACERT_BADFILE; + } + /* Continue with a warning if no certificate verification is required. */ + infof(data, "error setting certificate path, continuing anyway\n"); + } + infof(data, " CApath: %s\n", ssl_capath); + } +#else if(ssl_cafile || ssl_capath) { /* tell SSL where to find CA certificates that are used to verify the servers certificate. */ - if(!SSL_CTX_load_verify_locations(BACKEND->ctx, ssl_cafile, ssl_capath)) { + if(!SSL_CTX_load_verify_locations(backend->ctx, ssl_cafile, ssl_capath)) { if(verifypeer) { /* Fail if we insist on successfully verifying the server. */ failf(data, "error setting certificate verify locations:\n" @@ -2746,18 +2774,20 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) ssl_cafile ? ssl_cafile : "none", ssl_capath ? ssl_capath : "none"); } +#endif + #ifdef CURL_CA_FALLBACK else if(verifypeer) { /* verifying the peer without any CA certificates won't work so use openssl's built in default as fallback */ - SSL_CTX_set_default_verify_paths(BACKEND->ctx); + SSL_CTX_set_default_verify_paths(backend->ctx); } #endif if(ssl_crlfile) { /* tell SSL where to find CRL file that is used to check certificate * revocation */ - lookup = X509_STORE_add_lookup(SSL_CTX_get_cert_store(BACKEND->ctx), + lookup = X509_STORE_add_lookup(SSL_CTX_get_cert_store(backend->ctx), X509_LOOKUP_file()); if(!lookup || (!X509_load_crl_file(lookup, ssl_crlfile, X509_FILETYPE_PEM)) ) { @@ -2766,7 +2796,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) } /* Everything is fine. */ infof(data, "successfully load CRL file:\n"); - X509_STORE_set_flags(SSL_CTX_get_cert_store(BACKEND->ctx), + X509_STORE_set_flags(SSL_CTX_get_cert_store(backend->ctx), X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL); infof(data, " CRLfile: %s\n", ssl_crlfile); @@ -2781,7 +2811,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) https://rt.openssl.org/Ticket/Display.html?id=3621&user=guest&pass=guest */ #if defined(X509_V_FLAG_TRUSTED_FIRST) && !defined(X509_V_FLAG_NO_ALT_CHAINS) - X509_STORE_set_flags(SSL_CTX_get_cert_store(BACKEND->ctx), + X509_STORE_set_flags(SSL_CTX_get_cert_store(backend->ctx), X509_V_FLAG_TRUSTED_FIRST); #endif #ifdef X509_V_FLAG_PARTIAL_CHAIN @@ -2790,7 +2820,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) trust-anchors, in the same way as self-signed root CA certificates are. This allows users to verify servers using the intermediate cert only, instead of needing the whole chain. */ - X509_STORE_set_flags(SSL_CTX_get_cert_store(BACKEND->ctx), + X509_STORE_set_flags(SSL_CTX_get_cert_store(backend->ctx), X509_V_FLAG_PARTIAL_CHAIN); } #endif @@ -2800,13 +2830,13 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) * fail to connect if the verification fails, or if it should continue * anyway. In the latter case the result of the verification is checked with * SSL_get_verify_result() below. */ - SSL_CTX_set_verify(BACKEND->ctx, + SSL_CTX_set_verify(backend->ctx, verifypeer ? SSL_VERIFY_PEER : SSL_VERIFY_NONE, NULL); /* Enable logging of secrets to the file specified in env SSLKEYLOGFILE. */ #if defined(ENABLE_SSLKEYLOGFILE) && defined(HAVE_KEYLOG_CALLBACK) if(keylog_file_fp) { - SSL_CTX_set_keylog_callback(BACKEND->ctx, ossl_keylog_callback); + SSL_CTX_set_keylog_callback(backend->ctx, ossl_keylog_callback); } #endif @@ -2814,14 +2844,14 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) * callback. Use the "external storage" mode to avoid that OpenSSL creates * an internal session cache. */ - SSL_CTX_set_session_cache_mode(BACKEND->ctx, + SSL_CTX_set_session_cache_mode(backend->ctx, SSL_SESS_CACHE_CLIENT | SSL_SESS_CACHE_NO_INTERNAL); - SSL_CTX_sess_set_new_cb(BACKEND->ctx, ossl_new_session_cb); + SSL_CTX_sess_set_new_cb(backend->ctx, ossl_new_session_cb); /* give application a chance to interfere with SSL set up. */ if(data->set.ssl.fsslctx) { Curl_set_in_callback(data, true); - result = (*data->set.ssl.fsslctx)(data, BACKEND->ctx, + result = (*data->set.ssl.fsslctx)(data, backend->ctx, data->set.ssl.fsslctxp); Curl_set_in_callback(data, false); if(result) { @@ -2831,10 +2861,10 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) } /* Lets make an SSL structure */ - if(BACKEND->handle) - SSL_free(BACKEND->handle); - BACKEND->handle = SSL_new(BACKEND->ctx); - if(!BACKEND->handle) { + if(backend->handle) + SSL_free(backend->handle); + backend->handle = SSL_new(backend->ctx); + if(!backend->handle) { failf(data, "SSL: couldn't create a context (handle)!"); return CURLE_OUT_OF_MEMORY; } @@ -2842,23 +2872,23 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) #if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \ !defined(OPENSSL_NO_OCSP) if(SSL_CONN_CONFIG(verifystatus)) - SSL_set_tlsext_status_type(BACKEND->handle, TLSEXT_STATUSTYPE_ocsp); + SSL_set_tlsext_status_type(backend->handle, TLSEXT_STATUSTYPE_ocsp); #endif #if defined(OPENSSL_IS_BORINGSSL) && defined(ALLOW_RENEG) - SSL_set_renegotiate_mode(BACKEND->handle, ssl_renegotiate_freely); + SSL_set_renegotiate_mode(backend->handle, ssl_renegotiate_freely); #endif - SSL_set_connect_state(BACKEND->handle); + SSL_set_connect_state(backend->handle); - BACKEND->server_cert = 0x0; + backend->server_cert = 0x0; #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME if((0 == Curl_inet_pton(AF_INET, hostname, &addr)) && #ifdef ENABLE_IPV6 (0 == Curl_inet_pton(AF_INET6, hostname, &addr)) && #endif sni && - !SSL_set_tlsext_host_name(BACKEND->handle, hostname)) + !SSL_set_tlsext_host_name(backend->handle, hostname)) infof(data, "WARNING: failed to configure server name indication (SNI) " "TLS extension\n"); #endif @@ -2872,14 +2902,14 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) if(connectdata_idx >= 0 && sockindex_idx >= 0) { /* Store the data needed for the "new session" callback. * The sockindex is stored as a pointer to an array element. */ - SSL_set_ex_data(BACKEND->handle, connectdata_idx, conn); - SSL_set_ex_data(BACKEND->handle, sockindex_idx, conn->sock + sockindex); + SSL_set_ex_data(backend->handle, connectdata_idx, conn); + SSL_set_ex_data(backend->handle, sockindex_idx, conn->sock + sockindex); } Curl_ssl_sessionid_lock(conn); if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL, sockindex)) { /* we got a session id, use it! */ - if(!SSL_set_session(BACKEND->handle, ssl_sessionid)) { + if(!SSL_set_session(backend->handle, ssl_sessionid)) { Curl_ssl_sessionid_unlock(conn); failf(data, "SSL: SSL_set_session failed: %s", ossl_strerror(ERR_get_error(), error_buffer, @@ -2899,9 +2929,9 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) DEBUGASSERT(handle != NULL); DEBUGASSERT(bio != NULL); BIO_set_ssl(bio, handle, FALSE); - SSL_set_bio(BACKEND->handle, bio, bio); + SSL_set_bio(backend->handle, bio, bio); } - else if(!SSL_set_fd(BACKEND->handle, (int)sockfd)) { + else if(!SSL_set_fd(backend->handle, (int)sockfd)) { /* pass the raw socket into the SSL layers */ failf(data, "SSL: SSL_set_fd failed: %s", ossl_strerror(ERR_get_error(), error_buffer, sizeof(error_buffer))); @@ -2920,24 +2950,25 @@ static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex) struct ssl_connect_data *connssl = &conn->ssl[sockindex]; long * const certverifyresult = SSL_IS_PROXY() ? &data->set.proxy_ssl.certverifyresult : &data->set.ssl.certverifyresult; + struct ssl_backend_data *backend = connssl->backend; DEBUGASSERT(ssl_connect_2 == connssl->connecting_state || ssl_connect_2_reading == connssl->connecting_state || ssl_connect_2_writing == connssl->connecting_state); ERR_clear_error(); - err = SSL_connect(BACKEND->handle); + err = SSL_connect(backend->handle); /* If keylogging is enabled but the keylog callback is not supported then log secrets here, immediately after SSL_connect by using tap_ssl_key. */ #if defined(ENABLE_SSLKEYLOGFILE) && !defined(HAVE_KEYLOG_CALLBACK) - tap_ssl_key(BACKEND->handle, &BACKEND->tap_state); + tap_ssl_key(backend->handle, &backend->tap_state); #endif /* 1 is fine 0 is "not successful but was shut down controlled" <0 is "handshake was not successful, because a fatal error occurred" */ if(1 != err) { - int detail = SSL_get_error(BACKEND->handle, err); + int detail = SSL_get_error(backend->handle, err); if(SSL_ERROR_WANT_READ == detail) { connssl->connecting_state = ssl_connect_2_reading; @@ -2977,7 +3008,7 @@ static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex) (reason == SSL_R_CERTIFICATE_VERIFY_FAILED)) { result = CURLE_PEER_FAILED_VERIFICATION; - lerr = SSL_get_verify_result(BACKEND->handle); + lerr = SSL_get_verify_result(backend->handle); if(lerr != X509_V_OK) { *certverifyresult = lerr; msnprintf(error_buffer, sizeof(error_buffer), @@ -3026,8 +3057,8 @@ static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex) /* Informational message */ infof(data, "SSL connection using %s / %s\n", - get_ssl_version_txt(BACKEND->handle), - SSL_get_cipher(BACKEND->handle)); + get_ssl_version_txt(backend->handle), + SSL_get_cipher(backend->handle)); #ifdef HAS_ALPN /* Sets data and len to negotiated protocol, len is 0 if no protocol was @@ -3036,7 +3067,7 @@ static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex) if(conn->bits.tls_enable_alpn) { const unsigned char *neg_protocol; unsigned int len; - SSL_get0_alpn_selected(BACKEND->handle, &neg_protocol, &len); + SSL_get0_alpn_selected(backend->handle, &neg_protocol, &len); if(len != 0) { infof(data, "ALPN, server accepted to use %.*s\n", len, neg_protocol); @@ -3171,8 +3202,9 @@ static CURLcode get_cert_chain(struct connectdata *conn, struct Curl_easy *data = conn->data; numcert_t numcerts; BIO *mem; + struct ssl_backend_data *backend = connssl->backend; - sk = SSL_get_peer_cert_chain(BACKEND->handle); + sk = SSL_get_peer_cert_chain(backend->handle); if(!sk) { return CURLE_OUT_OF_MEMORY; } @@ -3458,13 +3490,14 @@ static CURLcode servercert(struct connectdata *conn, long * const certverifyresult = SSL_IS_PROXY() ? &data->set.proxy_ssl.certverifyresult : &data->set.ssl.certverifyresult; BIO *mem = BIO_new(BIO_s_mem()); + struct ssl_backend_data *backend = connssl->backend; if(data->set.ssl.certinfo) /* we've been asked to gather certificate info! */ (void)get_cert_chain(conn, connssl); - BACKEND->server_cert = SSL_get_peer_certificate(BACKEND->handle); - if(!BACKEND->server_cert) { + backend->server_cert = SSL_get_peer_certificate(backend->handle); + if(!backend->server_cert) { BIO_free(mem); if(!strict) return CURLE_OK; @@ -3475,19 +3508,19 @@ static CURLcode servercert(struct connectdata *conn, infof(data, "%s certificate:\n", SSL_IS_PROXY() ? "Proxy" : "Server"); - rc = x509_name_oneline(X509_get_subject_name(BACKEND->server_cert), + rc = x509_name_oneline(X509_get_subject_name(backend->server_cert), buffer, sizeof(buffer)); infof(data, " subject: %s\n", rc?"[NONE]":buffer); #ifndef CURL_DISABLE_VERBOSE_STRINGS { long len; - ASN1_TIME_print(mem, X509_get0_notBefore(BACKEND->server_cert)); + ASN1_TIME_print(mem, X509_get0_notBefore(backend->server_cert)); len = BIO_get_mem_data(mem, (char **) &ptr); infof(data, " start date: %.*s\n", len, ptr); (void)BIO_reset(mem); - ASN1_TIME_print(mem, X509_get0_notAfter(BACKEND->server_cert)); + ASN1_TIME_print(mem, X509_get0_notAfter(backend->server_cert)); len = BIO_get_mem_data(mem, (char **) &ptr); infof(data, " expire date: %.*s\n", len, ptr); (void)BIO_reset(mem); @@ -3497,15 +3530,15 @@ static CURLcode servercert(struct connectdata *conn, BIO_free(mem); if(SSL_CONN_CONFIG(verifyhost)) { - result = verifyhost(conn, BACKEND->server_cert); + result = verifyhost(conn, backend->server_cert); if(result) { - X509_free(BACKEND->server_cert); - BACKEND->server_cert = NULL; + X509_free(backend->server_cert); + backend->server_cert = NULL; return result; } } - rc = x509_name_oneline(X509_get_issuer_name(BACKEND->server_cert), + rc = x509_name_oneline(X509_get_issuer_name(backend->server_cert), buffer, sizeof(buffer)); if(rc) { if(strict) @@ -3527,8 +3560,8 @@ static CURLcode servercert(struct connectdata *conn, " error %s", ossl_strerror(ERR_get_error(), error_buffer, sizeof(error_buffer)) ); - X509_free(BACKEND->server_cert); - BACKEND->server_cert = NULL; + X509_free(backend->server_cert); + backend->server_cert = NULL; return CURLE_OUT_OF_MEMORY; } @@ -3537,8 +3570,8 @@ static CURLcode servercert(struct connectdata *conn, failf(data, "SSL: Unable to open issuer cert (%s)", SSL_SET_OPTION(issuercert)); BIO_free(fp); - X509_free(BACKEND->server_cert); - BACKEND->server_cert = NULL; + X509_free(backend->server_cert); + backend->server_cert = NULL; return CURLE_SSL_ISSUER_ERROR; } @@ -3549,19 +3582,19 @@ static CURLcode servercert(struct connectdata *conn, SSL_SET_OPTION(issuercert)); BIO_free(fp); X509_free(issuer); - X509_free(BACKEND->server_cert); - BACKEND->server_cert = NULL; + X509_free(backend->server_cert); + backend->server_cert = NULL; return CURLE_SSL_ISSUER_ERROR; } - if(X509_check_issued(issuer, BACKEND->server_cert) != X509_V_OK) { + if(X509_check_issued(issuer, backend->server_cert) != X509_V_OK) { if(strict) failf(data, "SSL: Certificate issuer check failed (%s)", SSL_SET_OPTION(issuercert)); BIO_free(fp); X509_free(issuer); - X509_free(BACKEND->server_cert); - BACKEND->server_cert = NULL; + X509_free(backend->server_cert); + backend->server_cert = NULL; return CURLE_SSL_ISSUER_ERROR; } @@ -3571,7 +3604,7 @@ static CURLcode servercert(struct connectdata *conn, X509_free(issuer); } - lerr = *certverifyresult = SSL_get_verify_result(BACKEND->handle); + lerr = *certverifyresult = SSL_get_verify_result(backend->handle); if(*certverifyresult != X509_V_OK) { if(SSL_CONN_CONFIG(verifypeer)) { @@ -3596,8 +3629,8 @@ static CURLcode servercert(struct connectdata *conn, if(SSL_CONN_CONFIG(verifystatus)) { result = verifystatus(conn, connssl); if(result) { - X509_free(BACKEND->server_cert); - BACKEND->server_cert = NULL; + X509_free(backend->server_cert); + backend->server_cert = NULL; return result; } } @@ -3610,13 +3643,13 @@ static CURLcode servercert(struct connectdata *conn, ptr = SSL_IS_PROXY() ? data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] : data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]; if(!result && ptr) { - result = pkp_pin_peer_pubkey(data, BACKEND->server_cert, ptr); + result = pkp_pin_peer_pubkey(data, backend->server_cert, ptr); if(result) failf(data, "SSL: public key does not match pinned public key!"); } - X509_free(BACKEND->server_cert); - BACKEND->server_cert = NULL; + X509_free(backend->server_cert); + backend->server_cert = NULL; connssl->connecting_state = ssl_connect_done; return result; @@ -3810,14 +3843,15 @@ static ssize_t ossl_send(struct connectdata *conn, int memlen; int rc; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + struct ssl_backend_data *backend = connssl->backend; ERR_clear_error(); memlen = (len > (size_t)INT_MAX) ? INT_MAX : (int)len; - rc = SSL_write(BACKEND->handle, mem, memlen); + rc = SSL_write(backend->handle, mem, memlen); if(rc <= 0) { - err = SSL_get_error(BACKEND->handle, rc); + err = SSL_get_error(backend->handle, rc); switch(err) { case SSL_ERROR_WANT_READ: @@ -3884,14 +3918,15 @@ static ssize_t ossl_recv(struct connectdata *conn, /* connection data */ ssize_t nread; int buffsize; struct ssl_connect_data *connssl = &conn->ssl[num]; + struct ssl_backend_data *backend = connssl->backend; ERR_clear_error(); buffsize = (buffersize > (size_t)INT_MAX) ? INT_MAX : (int)buffersize; - nread = (ssize_t)SSL_read(BACKEND->handle, buf, buffsize); + nread = (ssize_t)SSL_read(backend->handle, buf, buffsize); if(nread <= 0) { /* failed SSL_read */ - int err = SSL_get_error(BACKEND->handle, (int)nread); + int err = SSL_get_error(backend->handle, (int)nread); switch(err) { case SSL_ERROR_NONE: /* this is not an error */ @@ -4097,8 +4132,9 @@ static void *Curl_ossl_get_internals(struct ssl_connect_data *connssl, CURLINFO info) { /* Legacy: CURLINFO_TLS_SESSION must return an SSL_CTX pointer. */ + struct ssl_backend_data *backend = connssl->backend; return info == CURLINFO_TLS_SESSION ? - (void *)BACKEND->ctx : (void *)BACKEND->handle; + (void *)backend->ctx : (void *)backend->handle; } const struct Curl_ssl Curl_ssl_openssl = { diff --git a/libs/libcurl/src/vtls/schannel.c b/libs/libcurl/src/vtls/schannel.c index f665ee3404..49659bb7ab 100644 --- a/libs/libcurl/src/vtls/schannel.c +++ b/libs/libcurl/src/vtls/schannel.c @@ -520,8 +520,15 @@ schannel_connect_step1(struct connectdata *conn, int sockindex) DEBUGF(infof(data, "schannel: disabled server certificate revocation " "checks\n")); } + else if(data->set.ssl.revoke_best_effort) { + schannel_cred.dwFlags |= SCH_CRED_IGNORE_NO_REVOCATION_CHECK | + SCH_CRED_IGNORE_REVOCATION_OFFLINE | SCH_CRED_REVOCATION_CHECK_CHAIN; + + DEBUGF(infof(data, "schannel: ignore revocation offline errors")); + } else { schannel_cred.dwFlags |= SCH_CRED_REVOCATION_CHECK_CHAIN; + DEBUGF(infof(data, "schannel: checking server certificate revocation\n")); } @@ -578,11 +585,12 @@ schannel_connect_step1(struct connectdata *conn, int sockindex) /* client certificate */ if(data->set.ssl.cert) { DWORD cert_store_name; - TCHAR *cert_store_path; + TCHAR *cert_store_path = NULL; TCHAR *cert_thumbprint_str; CRYPT_HASH_BLOB cert_thumbprint; BYTE cert_thumbprint_data[CERT_THUMBPRINT_DATA_LEN]; HCERTSTORE cert_store; + FILE *fInCert = NULL; TCHAR *cert_path = Curl_convert_UTF8_to_tchar(data->set.ssl.cert); if(!cert_path) @@ -590,54 +598,143 @@ schannel_connect_step1(struct connectdata *conn, int sockindex) result = get_cert_location(cert_path, &cert_store_name, &cert_store_path, &cert_thumbprint_str); - if(result != CURLE_OK) { - failf(data, "schannel: Failed to get certificate location for %s", - cert_path); + if((result != CURLE_OK) && (data->set.ssl.cert[0]!='\0')) + fInCert = fopen(data->set.ssl.cert, "rb"); + + if((result != CURLE_OK) && (fInCert == NULL)) { + failf(data, "schannel: Failed to get certificate location" + " or file for %s", + data->set.ssl.cert); Curl_unicodefree(cert_path); return result; } - cert_store = - CertOpenStore(CURL_CERT_STORE_PROV_SYSTEM, 0, - (HCRYPTPROV)NULL, - CERT_STORE_OPEN_EXISTING_FLAG | cert_store_name, - cert_store_path); - if(!cert_store) { - failf(data, "schannel: Failed to open cert store %x %s, " - "last error is %x", - cert_store_name, cert_store_path, GetLastError()); - free(cert_store_path); + if(fInCert) { + /* Reading a .P12 or .pfx file, like the example at bottom of + https://social.msdn.microsoft.com/Forums/windowsdesktop/ + en-US/3e7bc95f-b21a-4bcd-bd2c-7f996718cae5 + */ + void *certdata = NULL; + long filesize = 0; + CRYPT_DATA_BLOB datablob; + WCHAR* pszPassword; + size_t pwd_len = 0; + int str_w_len = 0; + int continue_reading = fseek(fInCert, 0, SEEK_END) == 0; + if(continue_reading) + filesize = ftell(fInCert); + if(filesize < 0) + continue_reading = 0; + if(continue_reading) + continue_reading = fseek(fInCert, 0, SEEK_SET) == 0; + if(continue_reading) + certdata = malloc(((size_t)filesize) + 1); + if((certdata == NULL) || + ((int) fread(certdata, (size_t)filesize, 1, fInCert) != 1)) + continue_reading = 0; + fclose(fInCert); Curl_unicodefree(cert_path); - return CURLE_SSL_CERTPROBLEM; - } - free(cert_store_path); - cert_thumbprint.pbData = cert_thumbprint_data; - cert_thumbprint.cbData = CERT_THUMBPRINT_DATA_LEN; + if(!continue_reading) { + failf(data, "schannel: Failed to read cert file %s", + data->set.ssl.cert); + free(certdata); + return CURLE_SSL_CERTPROBLEM; + } - if(!CryptStringToBinary(cert_thumbprint_str, CERT_THUMBPRINT_STR_LEN, - CRYPT_STRING_HEX, - cert_thumbprint_data, &cert_thumbprint.cbData, - NULL, NULL)) { - Curl_unicodefree(cert_path); - return CURLE_SSL_CERTPROBLEM; - } + /* Convert key-pair data to the in-memory certificate store */ + datablob.pbData = (BYTE*)certdata; + datablob.cbData = (DWORD)filesize; + + if(data->set.ssl.key_passwd != NULL) + pwd_len = strlen(data->set.ssl.key_passwd); + pszPassword = (WCHAR*)malloc(sizeof(WCHAR)*(pwd_len + 1)); + if(pwd_len > 0) + str_w_len = + MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, + data->set.ssl.key_passwd, (int)pwd_len, + pszPassword, (int)(pwd_len + 1)); + + if((str_w_len >= 0) && (str_w_len <= (int)pwd_len)) + pszPassword[str_w_len] = 0; + else + pszPassword[0] = 0; + + cert_store = PFXImportCertStore(&datablob, pszPassword, 0); + free(pszPassword); + free(certdata); + if(cert_store == NULL) { + DWORD errorcode = GetLastError(); + if(errorcode == ERROR_INVALID_PASSWORD) + failf(data, "schannel: Failed to import cert file %s, " + "password is bad", data->set.ssl.cert); + else + failf(data, "schannel: Failed to import cert file %s, " + "last error is 0x%x", data->set.ssl.cert, errorcode); + return CURLE_SSL_CERTPROBLEM; + } - client_certs[0] = CertFindCertificateInStore( - cert_store, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, - CERT_FIND_HASH, &cert_thumbprint, NULL); + client_certs[0] = CertFindCertificateInStore( + cert_store, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, + CERT_FIND_ANY, NULL, NULL); - Curl_unicodefree(cert_path); + if(client_certs[0] == NULL) { + failf(data, "schannel: Failed to get certificate from file %s" + ", last error is 0x%x", + data->set.ssl.cert, GetLastError()); + CertCloseStore(cert_store, 0); + return CURLE_SSL_CERTPROBLEM; + } - if(client_certs[0]) { schannel_cred.cCreds = 1; schannel_cred.paCred = client_certs; } else { - /* CRYPT_E_NOT_FOUND / E_INVALIDARG */ - return CURLE_SSL_CERTPROBLEM; - } + cert_store = + CertOpenStore(CURL_CERT_STORE_PROV_SYSTEM, 0, + (HCRYPTPROV)NULL, + CERT_STORE_OPEN_EXISTING_FLAG | cert_store_name, + cert_store_path); + if(!cert_store) { + failf(data, "schannel: Failed to open cert store %x %s, " + "last error is 0x%x", + cert_store_name, cert_store_path, GetLastError()); + free(cert_store_path); + Curl_unicodefree(cert_path); + return CURLE_SSL_CERTPROBLEM; + } + free(cert_store_path); + + cert_thumbprint.pbData = cert_thumbprint_data; + cert_thumbprint.cbData = CERT_THUMBPRINT_DATA_LEN; + + if(!CryptStringToBinary(cert_thumbprint_str, + CERT_THUMBPRINT_STR_LEN, + CRYPT_STRING_HEX, + cert_thumbprint_data, + &cert_thumbprint.cbData, + NULL, NULL)) { + Curl_unicodefree(cert_path); + CertCloseStore(cert_store, 0); + return CURLE_SSL_CERTPROBLEM; + } + + client_certs[0] = CertFindCertificateInStore( + cert_store, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, + CERT_FIND_HASH, &cert_thumbprint, NULL); + + Curl_unicodefree(cert_path); + if(client_certs[0]) { + schannel_cred.cCreds = 1; + schannel_cred.paCred = client_certs; + } + else { + /* CRYPT_E_NOT_FOUND / E_INVALIDARG */ + CertCloseStore(cert_store, 0); + return CURLE_SSL_CERTPROBLEM; + } + } CertCloseStore(cert_store, 0); } #else @@ -1534,13 +1631,13 @@ schannel_send(struct connectdata *conn, int sockindex, /* send entire message or fail */ while(len > (size_t)written) { ssize_t this_write; - timediff_t timeleft; + timediff_t timeout_ms; int what; this_write = 0; - timeleft = Curl_timeleft(conn->data, NULL, FALSE); - if(timeleft < 0) { + timeout_ms = Curl_timeleft(conn->data, NULL, FALSE); + if(timeout_ms < 0) { /* we already got the timeout */ failf(conn->data, "schannel: timed out sending data " "(bytes sent: %zd)", written); @@ -1548,8 +1645,9 @@ schannel_send(struct connectdata *conn, int sockindex, written = -1; break; } - - what = SOCKET_WRITABLE(conn->sock[sockindex], timeleft); + if(!timeout_ms) + timeout_ms = TIMEDIFF_T_MAX; + what = SOCKET_WRITABLE(conn->sock[sockindex], timeout_ms); if(what < 0) { /* fatal error */ failf(conn->data, "select/poll on SSL socket, errno: %d", SOCKERRNO); @@ -2203,7 +2301,7 @@ static void Curl_schannel_checksum(const unsigned char *input, memset(checksum, 0, checksumlen); if(!CryptAcquireContext(&hProv, NULL, NULL, provType, - CRYPT_VERIFYCONTEXT)) + CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) return; /* failed */ do { diff --git a/libs/libcurl/src/vtls/schannel_verify.c b/libs/libcurl/src/vtls/schannel_verify.c index e75132cadd..3dbc11f056 100644 --- a/libs/libcurl/src/vtls/schannel_verify.c +++ b/libs/libcurl/src/vtls/schannel_verify.c @@ -636,6 +636,15 @@ CURLcode Curl_verify_certificate(struct connectdata *conn, int sockindex) CERT_SIMPLE_CHAIN *pSimpleChain = pChainContext->rgpChain[0]; DWORD dwTrustErrorMask = ~(DWORD)(CERT_TRUST_IS_NOT_TIME_NESTED); dwTrustErrorMask &= pSimpleChain->TrustStatus.dwErrorStatus; + + if(data->set.ssl.revoke_best_effort) { + /* Ignore errors when root certificates are missing the revocation + * list URL, or when the list could not be downloaded because the + * server is currently unreachable. */ + dwTrustErrorMask &= ~(DWORD)(CERT_TRUST_REVOCATION_STATUS_UNKNOWN | + CERT_TRUST_IS_OFFLINE_REVOCATION); + } + if(dwTrustErrorMask) { if(dwTrustErrorMask & CERT_TRUST_IS_REVOKED) failf(data, "schannel: CertGetCertificateChain trust error" diff --git a/libs/libcurl/src/vtls/sectransp.c b/libs/libcurl/src/vtls/sectransp.c index 7dd028fb7f..6b2d436fc0 100644 --- a/libs/libcurl/src/vtls/sectransp.c +++ b/libs/libcurl/src/vtls/sectransp.c @@ -138,8 +138,6 @@ struct ssl_backend_data { size_t ssl_write_buffered_length; }; -#define BACKEND connssl->backend - /* pinned public key support tests */ /* version 1 supports macOS 10.12+ and iOS 10+ */ @@ -201,7 +199,8 @@ static OSStatus SocketRead(SSLConnectionRef connection, UInt8 *currData = (UInt8 *)data; /*int sock = *(int *)connection;*/ struct ssl_connect_data *connssl = (struct ssl_connect_data *)connection; - int sock = BACKEND->ssl_sockfd; + struct ssl_backend_data *backend = connssl->backend; + int sock = backend->ssl_sockfd; OSStatus rtn = noErr; size_t bytesRead; ssize_t rrtn; @@ -230,7 +229,7 @@ static OSStatus SocketRead(SSLConnectionRef connection, break; case EAGAIN: rtn = errSSLWouldBlock; - BACKEND->ssl_direction = false; + backend->ssl_direction = false; break; default: rtn = ioErr; @@ -261,7 +260,8 @@ static OSStatus SocketWrite(SSLConnectionRef connection, size_t bytesSent = 0; /*int sock = *(int *)connection;*/ struct ssl_connect_data *connssl = (struct ssl_connect_data *)connection; - int sock = BACKEND->ssl_sockfd; + struct ssl_backend_data *backend = connssl->backend; + int sock = backend->ssl_sockfd; ssize_t length; size_t dataLen = *dataLength; const UInt8 *dataPtr = (UInt8 *)data; @@ -281,7 +281,7 @@ static OSStatus SocketWrite(SSLConnectionRef connection, theErr = errno; if(theErr == EAGAIN) { ortn = errSSLWouldBlock; - BACKEND->ssl_direction = true; + backend->ssl_direction = true; } else { ortn = ioErr; @@ -1276,6 +1276,7 @@ set_ssl_version_min_max(struct connectdata *conn, int sockindex) { struct Curl_easy *data = conn->data; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + struct ssl_backend_data *backend = connssl->backend; long ssl_version = SSL_CONN_CONFIG(version); long ssl_version_max = SSL_CONN_CONFIG(version_max); long max_supported_version_by_os; @@ -1326,30 +1327,30 @@ set_ssl_version_min_max(struct connectdata *conn, int sockindex) return result; } - (void)SSLSetProtocolVersionMin(BACKEND->ssl_ctx, darwin_ver_min); - (void)SSLSetProtocolVersionMax(BACKEND->ssl_ctx, darwin_ver_max); + (void)SSLSetProtocolVersionMin(backend->ssl_ctx, darwin_ver_min); + (void)SSLSetProtocolVersionMax(backend->ssl_ctx, darwin_ver_max); return result; } else { #if CURL_SUPPORT_MAC_10_8 long i = ssl_version; - (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx, + (void)SSLSetProtocolVersionEnabled(backend->ssl_ctx, kSSLProtocolAll, false); for(; i <= (ssl_version_max >> 16); i++) { switch(i) { case CURL_SSLVERSION_TLSv1_0: - (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx, + (void)SSLSetProtocolVersionEnabled(backend->ssl_ctx, kTLSProtocol1, true); break; case CURL_SSLVERSION_TLSv1_1: - (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx, + (void)SSLSetProtocolVersionEnabled(backend->ssl_ctx, kTLSProtocol11, true); break; case CURL_SSLVERSION_TLSv1_2: - (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx, + (void)SSLSetProtocolVersionEnabled(backend->ssl_ctx, kTLSProtocol12, true); break; @@ -1373,6 +1374,7 @@ static CURLcode sectransp_connect_step1(struct connectdata *conn, struct Curl_easy *data = conn->data; curl_socket_t sockfd = conn->sock[sockindex]; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + struct ssl_backend_data *backend = connssl->backend; const char * const ssl_cafile = SSL_CONN_CONFIG(CAfile); const bool verifypeer = SSL_CONN_CONFIG(verifypeer); char * const ssl_cert = SSL_SET_OPTION(cert); @@ -1395,10 +1397,10 @@ static CURLcode sectransp_connect_step1(struct connectdata *conn, #if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS if(SSLCreateContext != NULL) { /* use the newer API if available */ - if(BACKEND->ssl_ctx) - CFRelease(BACKEND->ssl_ctx); - BACKEND->ssl_ctx = SSLCreateContext(NULL, kSSLClientSide, kSSLStreamType); - if(!BACKEND->ssl_ctx) { + if(backend->ssl_ctx) + CFRelease(backend->ssl_ctx); + backend->ssl_ctx = SSLCreateContext(NULL, kSSLClientSide, kSSLStreamType); + if(!backend->ssl_ctx) { failf(data, "SSL: couldn't create a context!"); return CURLE_OUT_OF_MEMORY; } @@ -1406,9 +1408,9 @@ static CURLcode sectransp_connect_step1(struct connectdata *conn, else { /* The old ST API does not exist under iOS, so don't compile it: */ #if CURL_SUPPORT_MAC_10_8 - if(BACKEND->ssl_ctx) - (void)SSLDisposeContext(BACKEND->ssl_ctx); - err = SSLNewContext(false, &(BACKEND->ssl_ctx)); + if(backend->ssl_ctx) + (void)SSLDisposeContext(backend->ssl_ctx); + err = SSLNewContext(false, &(backend->ssl_ctx)); if(err != noErr) { failf(data, "SSL: couldn't create a context: OSStatus %d", err); return CURLE_OUT_OF_MEMORY; @@ -1416,31 +1418,31 @@ static CURLcode sectransp_connect_step1(struct connectdata *conn, #endif /* CURL_SUPPORT_MAC_10_8 */ } #else - if(BACKEND->ssl_ctx) - (void)SSLDisposeContext(BACKEND->ssl_ctx); - err = SSLNewContext(false, &(BACKEND->ssl_ctx)); + if(backend->ssl_ctx) + (void)SSLDisposeContext(backend->ssl_ctx); + err = SSLNewContext(false, &(backend->ssl_ctx)); if(err != noErr) { failf(data, "SSL: couldn't create a context: OSStatus %d", err); return CURLE_OUT_OF_MEMORY; } #endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */ - BACKEND->ssl_write_buffered_length = 0UL; /* reset buffered write length */ + backend->ssl_write_buffered_length = 0UL; /* reset buffered write length */ /* check to see if we've been told to use an explicit SSL/TLS version */ #if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS if(SSLSetProtocolVersionMax != NULL) { switch(conn->ssl_config.version) { case CURL_SSLVERSION_TLSv1: - (void)SSLSetProtocolVersionMin(BACKEND->ssl_ctx, kTLSProtocol1); + (void)SSLSetProtocolVersionMin(backend->ssl_ctx, kTLSProtocol1); #if (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1 if(__builtin_available(macOS 10.13, iOS 11.0, *)) { - (void)SSLSetProtocolVersionMax(BACKEND->ssl_ctx, kTLSProtocol13); + (void)SSLSetProtocolVersionMax(backend->ssl_ctx, kTLSProtocol13); } else { - (void)SSLSetProtocolVersionMax(BACKEND->ssl_ctx, kTLSProtocol12); + (void)SSLSetProtocolVersionMax(backend->ssl_ctx, kTLSProtocol12); } #else - (void)SSLSetProtocolVersionMax(BACKEND->ssl_ctx, kTLSProtocol12); + (void)SSLSetProtocolVersionMax(backend->ssl_ctx, kTLSProtocol12); #endif /* (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1 */ break; @@ -1456,20 +1458,20 @@ static CURLcode sectransp_connect_step1(struct connectdata *conn, break; } case CURL_SSLVERSION_SSLv3: - err = SSLSetProtocolVersionMin(BACKEND->ssl_ctx, kSSLProtocol3); + err = SSLSetProtocolVersionMin(backend->ssl_ctx, kSSLProtocol3); if(err != noErr) { failf(data, "Your version of the OS does not support SSLv3"); return CURLE_SSL_CONNECT_ERROR; } - (void)SSLSetProtocolVersionMax(BACKEND->ssl_ctx, kSSLProtocol3); + (void)SSLSetProtocolVersionMax(backend->ssl_ctx, kSSLProtocol3); break; case CURL_SSLVERSION_SSLv2: - err = SSLSetProtocolVersionMin(BACKEND->ssl_ctx, kSSLProtocol2); + err = SSLSetProtocolVersionMin(backend->ssl_ctx, kSSLProtocol2); if(err != noErr) { failf(data, "Your version of the OS does not support SSLv2"); return CURLE_SSL_CONNECT_ERROR; } - (void)SSLSetProtocolVersionMax(BACKEND->ssl_ctx, kSSLProtocol2); + (void)SSLSetProtocolVersionMax(backend->ssl_ctx, kSSLProtocol2); break; default: failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); @@ -1478,19 +1480,19 @@ static CURLcode sectransp_connect_step1(struct connectdata *conn, } else { #if CURL_SUPPORT_MAC_10_8 - (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx, + (void)SSLSetProtocolVersionEnabled(backend->ssl_ctx, kSSLProtocolAll, false); switch(conn->ssl_config.version) { case CURL_SSLVERSION_DEFAULT: case CURL_SSLVERSION_TLSv1: - (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx, + (void)SSLSetProtocolVersionEnabled(backend->ssl_ctx, kTLSProtocol1, true); - (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx, + (void)SSLSetProtocolVersionEnabled(backend->ssl_ctx, kTLSProtocol11, true); - (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx, + (void)SSLSetProtocolVersionEnabled(backend->ssl_ctx, kTLSProtocol12, true); break; @@ -1505,7 +1507,7 @@ static CURLcode sectransp_connect_step1(struct connectdata *conn, break; } case CURL_SSLVERSION_SSLv3: - err = SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx, + err = SSLSetProtocolVersionEnabled(backend->ssl_ctx, kSSLProtocol3, true); if(err != noErr) { @@ -1514,7 +1516,7 @@ static CURLcode sectransp_connect_step1(struct connectdata *conn, } break; case CURL_SSLVERSION_SSLv2: - err = SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx, + err = SSLSetProtocolVersionEnabled(backend->ssl_ctx, kSSLProtocol2, true); if(err != noErr) { @@ -1534,12 +1536,12 @@ static CURLcode sectransp_connect_step1(struct connectdata *conn, " SSL/TLS version"); return CURLE_SSL_CONNECT_ERROR; } - (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx, kSSLProtocolAll, false); + (void)SSLSetProtocolVersionEnabled(backend->ssl_ctx, kSSLProtocolAll, false); switch(conn->ssl_config.version) { case CURL_SSLVERSION_DEFAULT: case CURL_SSLVERSION_TLSv1: case CURL_SSLVERSION_TLSv1_0: - (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx, + (void)SSLSetProtocolVersionEnabled(backend->ssl_ctx, kTLSProtocol1, true); break; @@ -1553,7 +1555,7 @@ static CURLcode sectransp_connect_step1(struct connectdata *conn, failf(data, "Your version of the OS does not support TLSv1.3"); return CURLE_SSL_CONNECT_ERROR; case CURL_SSLVERSION_SSLv2: - err = SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx, + err = SSLSetProtocolVersionEnabled(backend->ssl_ctx, kSSLProtocol2, true); if(err != noErr) { @@ -1562,7 +1564,7 @@ static CURLcode sectransp_connect_step1(struct connectdata *conn, } break; case CURL_SSLVERSION_SSLv3: - err = SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx, + err = SSLSetProtocolVersionEnabled(backend->ssl_ctx, kSSLProtocol3, true); if(err != noErr) { @@ -1596,7 +1598,7 @@ static CURLcode sectransp_connect_step1(struct connectdata *conn, /* expects length prefixed preference ordered list of protocols in wire * format */ - err = SSLSetALPNProtocols(BACKEND->ssl_ctx, alpnArr); + err = SSLSetALPNProtocols(backend->ssl_ctx, alpnArr); if(err != noErr) infof(data, "WARNING: failed to set ALPN protocols; OSStatus %d\n", err); @@ -1657,7 +1659,7 @@ static CURLcode sectransp_connect_step1(struct connectdata *conn, certs_c[0] = cert_and_key; certs = CFArrayCreate(NULL, (const void **)certs_c, 1L, &kCFTypeArrayCallBacks); - err = SSLSetCertificate(BACKEND->ssl_ctx, certs); + err = SSLSetCertificate(backend->ssl_ctx, certs); if(certs) CFRelease(certs); if(err != noErr) { @@ -1720,7 +1722,7 @@ static CURLcode sectransp_connect_step1(struct connectdata *conn, if(SSLSetSessionOption != NULL) { #endif /* CURL_BUILD_MAC */ bool break_on_auth = !conn->ssl_config.verifypeer || ssl_cafile; - err = SSLSetSessionOption(BACKEND->ssl_ctx, + err = SSLSetSessionOption(backend->ssl_ctx, kSSLSessionOptionBreakOnServerAuth, break_on_auth); if(err != noErr) { @@ -1730,7 +1732,7 @@ static CURLcode sectransp_connect_step1(struct connectdata *conn, } else { #if CURL_SUPPORT_MAC_10_8 - err = SSLSetEnableCertVerify(BACKEND->ssl_ctx, + err = SSLSetEnableCertVerify(backend->ssl_ctx, conn->ssl_config.verifypeer?true:false); if(err != noErr) { failf(data, "SSL: SSLSetEnableCertVerify() failed: OSStatus %d", err); @@ -1739,7 +1741,7 @@ static CURLcode sectransp_connect_step1(struct connectdata *conn, #endif /* CURL_SUPPORT_MAC_10_8 */ } #else - err = SSLSetEnableCertVerify(BACKEND->ssl_ctx, + err = SSLSetEnableCertVerify(backend->ssl_ctx, conn->ssl_config.verifypeer?true:false); if(err != noErr) { failf(data, "SSL: SSLSetEnableCertVerify() failed: OSStatus %d", err); @@ -1760,7 +1762,7 @@ static CURLcode sectransp_connect_step1(struct connectdata *conn, * Both hostname check and SNI require SSLSetPeerDomainName(). * Also: the verifyhost setting influences SNI usage */ if(conn->ssl_config.verifyhost) { - err = SSLSetPeerDomainName(BACKEND->ssl_ctx, hostname, + err = SSLSetPeerDomainName(backend->ssl_ctx, hostname, strlen(hostname)); if(err != noErr) { @@ -1786,7 +1788,7 @@ static CURLcode sectransp_connect_step1(struct connectdata *conn, higher priority, but it's probably better that we not connect at all than to give the user a false sense of security if the server only supports insecure ciphers. (Note: We don't care about SSLv2-only ciphers.) */ - err = SSLGetNumberSupportedCiphers(BACKEND->ssl_ctx, &all_ciphers_count); + err = SSLGetNumberSupportedCiphers(backend->ssl_ctx, &all_ciphers_count); if(err != noErr) { failf(data, "SSL: SSLGetNumberSupportedCiphers() failed: OSStatus %d", err); @@ -1803,7 +1805,7 @@ static CURLcode sectransp_connect_step1(struct connectdata *conn, failf(data, "SSL: Failed to allocate memory for allowed ciphers"); return CURLE_OUT_OF_MEMORY; } - err = SSLGetSupportedCiphers(BACKEND->ssl_ctx, all_ciphers, + err = SSLGetSupportedCiphers(backend->ssl_ctx, all_ciphers, &all_ciphers_count); if(err != noErr) { Curl_safefree(all_ciphers); @@ -1890,7 +1892,7 @@ static CURLcode sectransp_connect_step1(struct connectdata *conn, break; } } - err = SSLSetEnabledCiphers(BACKEND->ssl_ctx, allowed_ciphers, + err = SSLSetEnabledCiphers(backend->ssl_ctx, allowed_ciphers, allowed_ciphers_count); Curl_safefree(all_ciphers); Curl_safefree(allowed_ciphers); @@ -1903,9 +1905,9 @@ static CURLcode sectransp_connect_step1(struct connectdata *conn, /* We want to enable 1/n-1 when using a CBC cipher unless the user specifically doesn't want us doing that: */ if(SSLSetSessionOption != NULL) { - SSLSetSessionOption(BACKEND->ssl_ctx, kSSLSessionOptionSendOneByteRecord, + SSLSetSessionOption(backend->ssl_ctx, kSSLSessionOptionSendOneByteRecord, !data->set.ssl.enable_beast); - SSLSetSessionOption(BACKEND->ssl_ctx, kSSLSessionOptionFalseStart, + SSLSetSessionOption(backend->ssl_ctx, kSSLSessionOptionFalseStart, data->set.ssl.falsestart); /* false start support */ } #endif /* CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 */ @@ -1919,7 +1921,7 @@ static CURLcode sectransp_connect_step1(struct connectdata *conn, if(!Curl_ssl_getsessionid(conn, (void **)&ssl_sessionid, &ssl_sessionid_len, sockindex)) { /* we got a session id, use it! */ - err = SSLSetPeerID(BACKEND->ssl_ctx, ssl_sessionid, ssl_sessionid_len); + err = SSLSetPeerID(backend->ssl_ctx, ssl_sessionid, ssl_sessionid_len); Curl_ssl_sessionid_unlock(conn); if(err != noErr) { failf(data, "SSL: SSLSetPeerID() failed: OSStatus %d", err); @@ -1937,7 +1939,7 @@ static CURLcode sectransp_connect_step1(struct connectdata *conn, verifypeer, SSL_CONN_CONFIG(verifyhost), hostname, port); ssl_sessionid_len = strlen(ssl_sessionid); - err = SSLSetPeerID(BACKEND->ssl_ctx, ssl_sessionid, ssl_sessionid_len); + err = SSLSetPeerID(backend->ssl_ctx, ssl_sessionid, ssl_sessionid_len); if(err != noErr) { Curl_ssl_sessionid_unlock(conn); failf(data, "SSL: SSLSetPeerID() failed: OSStatus %d", err); @@ -1954,7 +1956,7 @@ static CURLcode sectransp_connect_step1(struct connectdata *conn, } } - err = SSLSetIOFuncs(BACKEND->ssl_ctx, SocketRead, SocketWrite); + err = SSLSetIOFuncs(backend->ssl_ctx, SocketRead, SocketWrite); if(err != noErr) { failf(data, "SSL: SSLSetIOFuncs() failed: OSStatus %d", err); return CURLE_SSL_CONNECT_ERROR; @@ -1964,8 +1966,8 @@ static CURLcode sectransp_connect_step1(struct connectdata *conn, /* We need to store the FD in a constant memory address, because * SSLSetConnection() will not copy that address. I've found that * conn->sock[sockindex] may change on its own. */ - BACKEND->ssl_sockfd = sockfd; - err = SSLSetConnection(BACKEND->ssl_ctx, connssl); + backend->ssl_sockfd = sockfd; + err = SSLSetConnection(backend->ssl_ctx, connssl); if(err != noErr) { failf(data, "SSL: SSLSetConnection() failed: %d", err); return CURLE_SSL_CONNECT_ERROR; @@ -2346,6 +2348,7 @@ sectransp_connect_step2(struct connectdata *conn, int sockindex) { struct Curl_easy *data = conn->data; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + struct ssl_backend_data *backend = connssl->backend; OSStatus err; SSLCipherSuite cipher; SSLProtocol protocol = 0; @@ -2357,12 +2360,12 @@ sectransp_connect_step2(struct connectdata *conn, int sockindex) || ssl_connect_2_writing == connssl->connecting_state); /* Here goes nothing: */ - err = SSLHandshake(BACKEND->ssl_ctx); + err = SSLHandshake(backend->ssl_ctx); if(err != noErr) { switch(err) { case errSSLWouldBlock: /* they're not done with us yet */ - connssl->connecting_state = BACKEND->ssl_direction ? + connssl->connecting_state = backend->ssl_direction ? ssl_connect_2_writing : ssl_connect_2_reading; return CURLE_OK; @@ -2371,7 +2374,7 @@ sectransp_connect_step2(struct connectdata *conn, int sockindex) case -9841: if(SSL_CONN_CONFIG(CAfile) && SSL_CONN_CONFIG(verifypeer)) { CURLcode result = verify_cert(SSL_CONN_CONFIG(CAfile), data, - BACKEND->ssl_ctx); + backend->ssl_ctx); if(result) return result; } @@ -2580,7 +2583,7 @@ sectransp_connect_step2(struct connectdata *conn, int sockindex) #ifdef SECTRANSP_PINNEDPUBKEY if(data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]) { - CURLcode result = pkp_pin_peer_pubkey(data, BACKEND->ssl_ctx, + CURLcode result = pkp_pin_peer_pubkey(data, backend->ssl_ctx, data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]); if(result) { failf(data, "SSL: public key does not match pinned public key!"); @@ -2590,8 +2593,8 @@ sectransp_connect_step2(struct connectdata *conn, int sockindex) #endif /* SECTRANSP_PINNEDPUBKEY */ /* Informational message */ - (void)SSLGetNegotiatedCipher(BACKEND->ssl_ctx, &cipher); - (void)SSLGetNegotiatedProtocolVersion(BACKEND->ssl_ctx, &protocol); + (void)SSLGetNegotiatedCipher(backend->ssl_ctx, &cipher); + (void)SSLGetNegotiatedProtocolVersion(backend->ssl_ctx, &protocol); switch(protocol) { case kSSLProtocol2: infof(data, "SSL 2.0 connection using %s\n", @@ -2631,7 +2634,7 @@ sectransp_connect_step2(struct connectdata *conn, int sockindex) if(__builtin_available(macOS 10.13.4, iOS 11, tvOS 11, *)) { CFArrayRef alpnArr = NULL; CFStringRef chosenProtocol = NULL; - err = SSLCopyALPNProtocols(BACKEND->ssl_ctx, &alpnArr); + err = SSLCopyALPNProtocols(backend->ssl_ctx, &alpnArr); if(err == noErr && alpnArr && CFArrayGetCount(alpnArr) >= 1) chosenProtocol = CFArrayGetValueAtIndex(alpnArr, 0); @@ -2674,19 +2677,20 @@ show_verbose_server_cert(struct connectdata *conn, { struct Curl_easy *data = conn->data; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + struct ssl_backend_data *backend = connssl->backend; CFArrayRef server_certs = NULL; SecCertificateRef server_cert; OSStatus err; CFIndex i, count; SecTrustRef trust = NULL; - if(!BACKEND->ssl_ctx) + if(!backend->ssl_ctx) return; #if CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS #if CURL_BUILD_IOS #pragma unused(server_certs) - err = SSLCopyPeerTrust(BACKEND->ssl_ctx, &trust); + err = SSLCopyPeerTrust(backend->ssl_ctx, &trust); /* For some reason, SSLCopyPeerTrust() can return noErr and yet return a null trust, so be on guard for that: */ if(err == noErr && trust) { @@ -2712,7 +2716,7 @@ show_verbose_server_cert(struct connectdata *conn, Lion or later. */ if(SecTrustEvaluateAsync != NULL) { #pragma unused(server_certs) - err = SSLCopyPeerTrust(BACKEND->ssl_ctx, &trust); + err = SSLCopyPeerTrust(backend->ssl_ctx, &trust); /* For some reason, SSLCopyPeerTrust() can return noErr and yet return a null trust, so be on guard for that: */ if(err == noErr && trust) { @@ -2732,7 +2736,7 @@ show_verbose_server_cert(struct connectdata *conn, } else { #if CURL_SUPPORT_MAC_10_8 - err = SSLCopyPeerCertificates(BACKEND->ssl_ctx, &server_certs); + err = SSLCopyPeerCertificates(backend->ssl_ctx, &server_certs); /* Just in case SSLCopyPeerCertificates() returns null too... */ if(err == noErr && server_certs) { count = CFArrayGetCount(server_certs); @@ -2754,7 +2758,7 @@ show_verbose_server_cert(struct connectdata *conn, #endif /* CURL_BUILD_IOS */ #else #pragma unused(trust) - err = SSLCopyPeerCertificates(BACKEND->ssl_ctx, &server_certs); + err = SSLCopyPeerCertificates(backend->ssl_ctx, &server_certs); if(err == noErr) { count = CFArrayGetCount(server_certs); for(i = 0L ; i < count ; i++) { @@ -2933,34 +2937,36 @@ static CURLcode Curl_sectransp_connect(struct connectdata *conn, int sockindex) static void Curl_sectransp_close(struct connectdata *conn, int sockindex) { struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + struct ssl_backend_data *backend = connssl->backend; - if(BACKEND->ssl_ctx) { - (void)SSLClose(BACKEND->ssl_ctx); + if(backend->ssl_ctx) { + (void)SSLClose(backend->ssl_ctx); #if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS if(SSLCreateContext != NULL) - CFRelease(BACKEND->ssl_ctx); + CFRelease(backend->ssl_ctx); #if CURL_SUPPORT_MAC_10_8 else - (void)SSLDisposeContext(BACKEND->ssl_ctx); + (void)SSLDisposeContext(backend->ssl_ctx); #endif /* CURL_SUPPORT_MAC_10_8 */ #else - (void)SSLDisposeContext(BACKEND->ssl_ctx); + (void)SSLDisposeContext(backend->ssl_ctx); #endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */ - BACKEND->ssl_ctx = NULL; + backend->ssl_ctx = NULL; } - BACKEND->ssl_sockfd = 0; + backend->ssl_sockfd = 0; } static int Curl_sectransp_shutdown(struct connectdata *conn, int sockindex) { struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + struct ssl_backend_data *backend = connssl->backend; struct Curl_easy *data = conn->data; ssize_t nread; int what; int rc; char buf[120]; - if(!BACKEND->ssl_ctx) + if(!backend->ssl_ctx) return 0; #ifndef CURL_DISABLE_FTP @@ -3033,11 +3039,12 @@ static size_t Curl_sectransp_version(char *buffer, size_t size) static int Curl_sectransp_check_cxn(struct connectdata *conn) { struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET]; + struct ssl_backend_data *backend = connssl->backend; OSStatus err; SSLSessionState state; - if(BACKEND->ssl_ctx) { - err = SSLGetSessionState(BACKEND->ssl_ctx, &state); + if(backend->ssl_ctx) { + err = SSLGetSessionState(backend->ssl_ctx, &state); if(err == noErr) return state == kSSLConnected || state == kSSLHandshake; return -1; @@ -3049,11 +3056,12 @@ static bool Curl_sectransp_data_pending(const struct connectdata *conn, int connindex) { const struct ssl_connect_data *connssl = &conn->ssl[connindex]; + struct ssl_backend_data *backend = connssl->backend; OSStatus err; size_t buffer; - if(BACKEND->ssl_ctx) { /* SSL is in use */ - err = SSLGetBufferedReadSize(BACKEND->ssl_ctx, &buffer); + if(backend->ssl_ctx) { /* SSL is in use */ + err = SSLGetBufferedReadSize(backend->ssl_ctx, &buffer); if(err == noErr) return buffer > 0UL; return false; @@ -3119,6 +3127,7 @@ static ssize_t sectransp_send(struct connectdata *conn, { /*struct Curl_easy *data = conn->data;*/ struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + struct ssl_backend_data *backend = connssl->backend; size_t processed = 0UL; OSStatus err; @@ -3137,15 +3146,15 @@ static ssize_t sectransp_send(struct connectdata *conn, over again with no new data until it quits returning errSSLWouldBlock. */ /* Do we have buffered data to write from the last time we were called? */ - if(BACKEND->ssl_write_buffered_length) { + if(backend->ssl_write_buffered_length) { /* Write the buffered data: */ - err = SSLWrite(BACKEND->ssl_ctx, NULL, 0UL, &processed); + err = SSLWrite(backend->ssl_ctx, NULL, 0UL, &processed); switch(err) { case noErr: /* processed is always going to be 0 because we didn't write to the buffer, so return how much was written to the socket */ - processed = BACKEND->ssl_write_buffered_length; - BACKEND->ssl_write_buffered_length = 0UL; + processed = backend->ssl_write_buffered_length; + backend->ssl_write_buffered_length = 0UL; break; case errSSLWouldBlock: /* argh, try again */ *curlcode = CURLE_AGAIN; @@ -3158,13 +3167,13 @@ static ssize_t sectransp_send(struct connectdata *conn, } else { /* We've got new data to write: */ - err = SSLWrite(BACKEND->ssl_ctx, mem, len, &processed); + err = SSLWrite(backend->ssl_ctx, mem, len, &processed); if(err != noErr) { switch(err) { case errSSLWouldBlock: /* Data was buffered but not sent, we have to tell the caller to try sending again, and remember how much was buffered */ - BACKEND->ssl_write_buffered_length = len; + backend->ssl_write_buffered_length = len; *curlcode = CURLE_AGAIN; return -1L; default: @@ -3185,11 +3194,12 @@ static ssize_t sectransp_recv(struct connectdata *conn, { /*struct Curl_easy *data = conn->data;*/ struct ssl_connect_data *connssl = &conn->ssl[num]; + struct ssl_backend_data *backend = connssl->backend; size_t processed = 0UL; OSStatus err; again: - err = SSLRead(BACKEND->ssl_ctx, buf, buffersize, &processed); + err = SSLRead(backend->ssl_ctx, buf, buffersize, &processed); if(err != noErr) { switch(err) { @@ -3215,7 +3225,7 @@ static ssize_t sectransp_recv(struct connectdata *conn, case -9841: if(SSL_CONN_CONFIG(CAfile) && SSL_CONN_CONFIG(verifypeer)) { CURLcode result = verify_cert(SSL_CONN_CONFIG(CAfile), conn->data, - BACKEND->ssl_ctx); + backend->ssl_ctx); if(result) return result; } @@ -3233,8 +3243,9 @@ static ssize_t sectransp_recv(struct connectdata *conn, static void *Curl_sectransp_get_internals(struct ssl_connect_data *connssl, CURLINFO info UNUSED_PARAM) { + struct ssl_backend_data *backend = connssl->backend; (void)info; - return BACKEND->ssl_ctx; + return backend->ssl_ctx; } const struct Curl_ssl Curl_ssl_sectransp = { diff --git a/libs/libcurl/src/vtls/vtls.c b/libs/libcurl/src/vtls/vtls.c index dfefa1bd5e..f1b5252273 100644 --- a/libs/libcurl/src/vtls/vtls.c +++ b/libs/libcurl/src/vtls/vtls.c @@ -174,6 +174,9 @@ int Curl_ssl_init(void) return Curl_ssl->init(); } +#if defined(CURL_WITH_MULTI_SSL) +static const struct Curl_ssl Curl_ssl_multi; +#endif /* Global cleanup */ void Curl_ssl_cleanup(void) @@ -181,6 +184,9 @@ void Curl_ssl_cleanup(void) if(init_ssl) { /* only cleanup if we did a previous init */ Curl_ssl->cleanup(); +#if defined(CURL_WITH_MULTI_SSL) + Curl_ssl = &Curl_ssl_multi; +#endif init_ssl = FALSE; } } @@ -489,6 +495,7 @@ CURLcode Curl_ssl_addsessionid(struct connectdata *conn, store->scheme = conn->handler->scheme; if(!Curl_clone_primary_ssl_config(ssl_config, &store->ssl_config)) { + Curl_free_primary_ssl_config(&store->ssl_config); store->sessionid = NULL; /* let caller free sessionid */ free(clone_host); free(clone_conn_to_host); diff --git a/libs/libcurl/src/vtls/wolfssl.c b/libs/libcurl/src/vtls/wolfssl.c index 8c2d3f4a28..5040b05929 100644 --- a/libs/libcurl/src/vtls/wolfssl.c +++ b/libs/libcurl/src/vtls/wolfssl.c @@ -96,12 +96,9 @@ struct ssl_backend_data { SSL* handle; }; -#define BACKEND connssl->backend - static Curl_recv wolfssl_recv; static Curl_send wolfssl_send; - static int do_file_type(const char *type) { if(!type || !type[0]) @@ -124,6 +121,7 @@ wolfssl_connect_step1(struct connectdata *conn, char *ciphers; struct Curl_easy *data = conn->data; struct ssl_connect_data* connssl = &conn->ssl[sockindex]; + struct ssl_backend_data *backend = connssl->backend; SSL_METHOD* req_method = NULL; curl_socket_t sockfd = conn->sock[sockindex]; #ifdef HAVE_SNI @@ -203,11 +201,11 @@ wolfssl_connect_step1(struct connectdata *conn, return CURLE_OUT_OF_MEMORY; } - if(BACKEND->ctx) - SSL_CTX_free(BACKEND->ctx); - BACKEND->ctx = SSL_CTX_new(req_method); + if(backend->ctx) + SSL_CTX_free(backend->ctx); + backend->ctx = SSL_CTX_new(req_method); - if(!BACKEND->ctx) { + if(!backend->ctx) { failf(data, "SSL: couldn't create a context!"); return CURLE_OUT_OF_MEMORY; } @@ -222,11 +220,11 @@ wolfssl_connect_step1(struct connectdata *conn, * defaults to TLS 1.1) so we have this short circuit evaluation to find * the minimum supported TLS version. */ - if((wolfSSL_CTX_SetMinVersion(BACKEND->ctx, WOLFSSL_TLSV1) != 1) && - (wolfSSL_CTX_SetMinVersion(BACKEND->ctx, WOLFSSL_TLSV1_1) != 1) && - (wolfSSL_CTX_SetMinVersion(BACKEND->ctx, WOLFSSL_TLSV1_2) != 1) + if((wolfSSL_CTX_SetMinVersion(backend->ctx, WOLFSSL_TLSV1) != 1) && + (wolfSSL_CTX_SetMinVersion(backend->ctx, WOLFSSL_TLSV1_1) != 1) && + (wolfSSL_CTX_SetMinVersion(backend->ctx, WOLFSSL_TLSV1_2) != 1) #ifdef WOLFSSL_TLS13 - && (wolfSSL_CTX_SetMinVersion(BACKEND->ctx, WOLFSSL_TLSV1_3) != 1) + && (wolfSSL_CTX_SetMinVersion(backend->ctx, WOLFSSL_TLSV1_3) != 1) #endif ) { failf(data, "SSL: couldn't set the minimum protocol version"); @@ -238,7 +236,7 @@ wolfssl_connect_step1(struct connectdata *conn, ciphers = SSL_CONN_CONFIG(cipher_list); if(ciphers) { - if(!SSL_CTX_set_cipher_list(BACKEND->ctx, ciphers)) { + if(!SSL_CTX_set_cipher_list(backend->ctx, ciphers)) { failf(data, "failed setting cipher list: %s", ciphers); return CURLE_SSL_CIPHER; } @@ -248,7 +246,7 @@ wolfssl_connect_step1(struct connectdata *conn, #ifndef NO_FILESYSTEM /* load trusted cacert */ if(SSL_CONN_CONFIG(CAfile)) { - if(1 != SSL_CTX_load_verify_locations(BACKEND->ctx, + if(1 != SSL_CTX_load_verify_locations(backend->ctx, SSL_CONN_CONFIG(CAfile), SSL_CONN_CONFIG(CApath))) { if(SSL_CONN_CONFIG(verifypeer)) { @@ -285,7 +283,7 @@ wolfssl_connect_step1(struct connectdata *conn, if(SSL_SET_OPTION(cert) && SSL_SET_OPTION(key)) { int file_type = do_file_type(SSL_SET_OPTION(cert_type)); - if(SSL_CTX_use_certificate_file(BACKEND->ctx, SSL_SET_OPTION(cert), + if(SSL_CTX_use_certificate_file(backend->ctx, SSL_SET_OPTION(cert), file_type) != 1) { failf(data, "unable to use client certificate (no key or wrong pass" " phrase?)"); @@ -293,7 +291,7 @@ wolfssl_connect_step1(struct connectdata *conn, } file_type = do_file_type(SSL_SET_OPTION(key_type)); - if(SSL_CTX_use_PrivateKey_file(BACKEND->ctx, SSL_SET_OPTION(key), + if(SSL_CTX_use_PrivateKey_file(backend->ctx, SSL_SET_OPTION(key), file_type) != 1) { failf(data, "unable to set private key"); return CURLE_SSL_CONNECT_ERROR; @@ -305,7 +303,7 @@ wolfssl_connect_step1(struct connectdata *conn, * fail to connect if the verification fails, or if it should continue * anyway. In the latter case the result of the verification is checked with * SSL_get_verify_result() below. */ - SSL_CTX_set_verify(BACKEND->ctx, + SSL_CTX_set_verify(backend->ctx, SSL_CONN_CONFIG(verifypeer)?SSL_VERIFY_PEER: SSL_VERIFY_NONE, NULL); @@ -324,7 +322,7 @@ wolfssl_connect_step1(struct connectdata *conn, #ifdef ENABLE_IPV6 (0 == Curl_inet_pton(AF_INET6, hostname, &addr6)) && #endif - (wolfSSL_CTX_UseSNI(BACKEND->ctx, WOLFSSL_SNI_HOST_NAME, hostname, + (wolfSSL_CTX_UseSNI(backend->ctx, WOLFSSL_SNI_HOST_NAME, hostname, (unsigned short)hostname_len) != 1)) { infof(data, "WARNING: failed to configure server name indication (SNI) " "TLS extension\n"); @@ -334,7 +332,7 @@ wolfssl_connect_step1(struct connectdata *conn, /* give application a chance to interfere with SSL set up. */ if(data->set.ssl.fsslctx) { - CURLcode result = (*data->set.ssl.fsslctx)(data, BACKEND->ctx, + CURLcode result = (*data->set.ssl.fsslctx)(data, backend->ctx, data->set.ssl.fsslctxp); if(result) { failf(data, "error signaled by ssl ctx callback"); @@ -352,10 +350,10 @@ wolfssl_connect_step1(struct connectdata *conn, #endif /* Let's make an SSL structure */ - if(BACKEND->handle) - SSL_free(BACKEND->handle); - BACKEND->handle = SSL_new(BACKEND->ctx); - if(!BACKEND->handle) { + if(backend->handle) + SSL_free(backend->handle); + backend->handle = SSL_new(backend->ctx); + if(!backend->handle) { failf(data, "SSL: couldn't create a context (handle)!"); return CURLE_OUT_OF_MEMORY; } @@ -378,7 +376,7 @@ wolfssl_connect_step1(struct connectdata *conn, strcpy(protocols + strlen(protocols), ALPN_HTTP_1_1); infof(data, "ALPN, offering %s\n", ALPN_HTTP_1_1); - if(wolfSSL_UseALPN(BACKEND->handle, protocols, + if(wolfSSL_UseALPN(backend->handle, protocols, (unsigned)strlen(protocols), WOLFSSL_ALPN_CONTINUE_ON_MISMATCH) != SSL_SUCCESS) { failf(data, "SSL: failed setting ALPN protocols"); @@ -394,11 +392,11 @@ wolfssl_connect_step1(struct connectdata *conn, Curl_ssl_sessionid_lock(conn); if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL, sockindex)) { /* we got a session id, use it! */ - if(!SSL_set_session(BACKEND->handle, ssl_sessionid)) { + if(!SSL_set_session(backend->handle, ssl_sessionid)) { char error_buffer[WOLFSSL_MAX_ERROR_SZ]; Curl_ssl_sessionid_unlock(conn); failf(data, "SSL: SSL_set_session failed: %s", - ERR_error_string(SSL_get_error(BACKEND->handle, 0), + ERR_error_string(SSL_get_error(backend->handle, 0), error_buffer)); return CURLE_SSL_CONNECT_ERROR; } @@ -409,7 +407,7 @@ wolfssl_connect_step1(struct connectdata *conn, } /* pass the raw socket into the SSL layer */ - if(!SSL_set_fd(BACKEND->handle, (int)sockfd)) { + if(!SSL_set_fd(backend->handle, (int)sockfd)) { failf(data, "SSL: SSL_set_fd failed"); return CURLE_SSL_CONNECT_ERROR; } @@ -426,6 +424,7 @@ wolfssl_connect_step2(struct connectdata *conn, int ret = -1; struct Curl_easy *data = conn->data; struct ssl_connect_data* connssl = &conn->ssl[sockindex]; + struct ssl_backend_data *backend = connssl->backend; const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : conn->host.name; const char * const dispname = SSL_IS_PROXY() ? @@ -439,15 +438,15 @@ wolfssl_connect_step2(struct connectdata *conn, /* Enable RFC2818 checks */ if(SSL_CONN_CONFIG(verifyhost)) { - ret = wolfSSL_check_domain_name(BACKEND->handle, hostname); + ret = wolfSSL_check_domain_name(backend->handle, hostname); if(ret == SSL_FAILURE) return CURLE_OUT_OF_MEMORY; } - ret = SSL_connect(BACKEND->handle); + ret = SSL_connect(backend->handle); if(ret != 1) { char error_buffer[WOLFSSL_MAX_ERROR_SZ]; - int detail = SSL_get_error(BACKEND->handle, ret); + int detail = SSL_get_error(backend->handle, ret); if(SSL_ERROR_WANT_READ == detail) { connssl->connecting_state = ssl_connect_2_reading; @@ -516,7 +515,7 @@ wolfssl_connect_step2(struct connectdata *conn, curl_asn1Element *pubkey; CURLcode result; - x509 = SSL_get_peer_certificate(BACKEND->handle); + x509 = SSL_get_peer_certificate(backend->handle); if(!x509) { failf(data, "SSL: failed retrieving server certificate"); return CURLE_SSL_PINNEDPUBKEYNOTMATCH; @@ -558,7 +557,7 @@ wolfssl_connect_step2(struct connectdata *conn, char *protocol = NULL; unsigned short protocol_len = 0; - rc = wolfSSL_ALPN_GetProtocol(BACKEND->handle, &protocol, &protocol_len); + rc = wolfSSL_ALPN_GetProtocol(backend->handle, &protocol, &protocol_len); if(rc == SSL_SUCCESS) { infof(data, "ALPN, server accepted to use %.*s\n", protocol_len, @@ -592,8 +591,8 @@ wolfssl_connect_step2(struct connectdata *conn, connssl->connecting_state = ssl_connect_3; #if (LIBWOLFSSL_VERSION_HEX >= 0x03009010) infof(data, "SSL connection using %s / %s\n", - wolfSSL_get_version(BACKEND->handle), - wolfSSL_get_cipher_name(BACKEND->handle)); + wolfSSL_get_version(backend->handle), + wolfSSL_get_cipher_name(backend->handle)); #else infof(data, "SSL connected\n"); #endif @@ -609,6 +608,7 @@ wolfssl_connect_step3(struct connectdata *conn, CURLcode result = CURLE_OK; struct Curl_easy *data = conn->data; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + struct ssl_backend_data *backend = connssl->backend; DEBUGASSERT(ssl_connect_3 == connssl->connecting_state); @@ -617,7 +617,7 @@ wolfssl_connect_step3(struct connectdata *conn, SSL_SESSION *our_ssl_sessionid; void *old_ssl_sessionid = NULL; - our_ssl_sessionid = SSL_get_session(BACKEND->handle); + our_ssl_sessionid = SSL_get_session(backend->handle); Curl_ssl_sessionid_lock(conn); incache = !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL, @@ -655,12 +655,13 @@ static ssize_t wolfssl_send(struct connectdata *conn, CURLcode *curlcode) { struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + struct ssl_backend_data *backend = connssl->backend; char error_buffer[WOLFSSL_MAX_ERROR_SZ]; - int memlen = (len > (size_t)INT_MAX) ? INT_MAX : (int)len; - int rc = SSL_write(BACKEND->handle, mem, memlen); + int memlen = (len > (size_t)INT_MAX) ? INT_MAX : (int)len; + int rc = SSL_write(backend->handle, mem, memlen); if(rc < 0) { - int err = SSL_get_error(BACKEND->handle, rc); + int err = SSL_get_error(backend->handle, rc); switch(err) { case SSL_ERROR_WANT_READ: @@ -682,31 +683,33 @@ static ssize_t wolfssl_send(struct connectdata *conn, static void Curl_wolfssl_close(struct connectdata *conn, int sockindex) { struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + struct ssl_backend_data *backend = connssl->backend; - if(BACKEND->handle) { - (void)SSL_shutdown(BACKEND->handle); - SSL_free(BACKEND->handle); - BACKEND->handle = NULL; + if(backend->handle) { + (void)SSL_shutdown(backend->handle); + SSL_free(backend->handle); + backend->handle = NULL; } - if(BACKEND->ctx) { - SSL_CTX_free(BACKEND->ctx); - BACKEND->ctx = NULL; + if(backend->ctx) { + SSL_CTX_free(backend->ctx); + backend->ctx = NULL; } } static ssize_t wolfssl_recv(struct connectdata *conn, - int num, - char *buf, - size_t buffersize, - CURLcode *curlcode) + int num, + char *buf, + size_t buffersize, + CURLcode *curlcode) { struct ssl_connect_data *connssl = &conn->ssl[num]; + struct ssl_backend_data *backend = connssl->backend; char error_buffer[WOLFSSL_MAX_ERROR_SZ]; - int buffsize = (buffersize > (size_t)INT_MAX) ? INT_MAX : (int)buffersize; - int nread = SSL_read(BACKEND->handle, buf, buffsize); + int buffsize = (buffersize > (size_t)INT_MAX) ? INT_MAX : (int)buffersize; + int nread = SSL_read(backend->handle, buf, buffsize); if(nread < 0) { - int err = SSL_get_error(BACKEND->handle, nread); + int err = SSL_get_error(backend->handle, nread); switch(err) { case SSL_ERROR_ZERO_RETURN: /* no more data */ @@ -758,11 +761,12 @@ static void Curl_wolfssl_cleanup(void) static bool Curl_wolfssl_data_pending(const struct connectdata* conn, - int connindex) + int connindex) { const struct ssl_connect_data *connssl = &conn->ssl[connindex]; - if(BACKEND->handle) /* SSL is in use */ - return (0 != SSL_pending(BACKEND->handle)) ? TRUE : FALSE; + struct ssl_backend_data *backend = connssl->backend; + if(backend->handle) /* SSL is in use */ + return (0 != SSL_pending(backend->handle)) ? TRUE : FALSE; else return FALSE; } @@ -776,10 +780,11 @@ static int Curl_wolfssl_shutdown(struct connectdata *conn, int sockindex) { int retval = 0; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + struct ssl_backend_data *backend = connssl->backend; - if(BACKEND->handle) { - SSL_free(BACKEND->handle); - BACKEND->handle = NULL; + if(backend->handle) { + SSL_free(backend->handle); + backend->handle = NULL; } return retval; } @@ -950,10 +955,11 @@ static CURLcode Curl_wolfssl_sha256sum(const unsigned char *tmp, /* input */ } static void *Curl_wolfssl_get_internals(struct ssl_connect_data *connssl, - CURLINFO info UNUSED_PARAM) + CURLINFO info UNUSED_PARAM) { + struct ssl_backend_data *backend = connssl->backend; (void)info; - return BACKEND->handle; + return backend->handle; } const struct Curl_ssl Curl_ssl_wolfssl = { |