diff options
author | Brad King <brad.king@kitware.com> | 2019-05-22 18:15:06 (GMT) |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2019-05-22 18:15:06 (GMT) |
commit | a39138ef9a7f3e3ec94ae4fd99602ca711bbcf5f (patch) | |
tree | a4d546a554025fb11ec6cc32e7491b150cde35f3 /Utilities/cmcurl/lib/vtls | |
parent | 2de8af0121c3ca64dcb82a1220d2ba255aab3553 (diff) | |
parent | b26487c663ec29d972fd61adc2b14ac5880b78c7 (diff) | |
download | CMake-a39138ef9a7f3e3ec94ae4fd99602ca711bbcf5f.zip CMake-a39138ef9a7f3e3ec94ae4fd99602ca711bbcf5f.tar.gz CMake-a39138ef9a7f3e3ec94ae4fd99602ca711bbcf5f.tar.bz2 |
Merge branch 'upstream-curl' into update-curl
* upstream-curl:
curl 2019-05-22 (885ce314)
Diffstat (limited to 'Utilities/cmcurl/lib/vtls')
19 files changed, 809 insertions, 1334 deletions
diff --git a/Utilities/cmcurl/lib/vtls/axtls.c b/Utilities/cmcurl/lib/vtls/axtls.c deleted file mode 100644 index b262392..0000000 --- a/Utilities/cmcurl/lib/vtls/axtls.c +++ /dev/null @@ -1,741 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 2010, DirecTV, Contact: Eric Hu, <ehu@directv.com>. - * Copyright (C) 2010 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at https://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ - -/* - * Source file for all axTLS-specific code for the TLS/SSL layer. No code - * but vtls.c should ever call or use these functions. - */ - -#include "curl_setup.h" - -#ifdef USE_AXTLS - -#error axTLS support has been disabled in curl due to doubts about quality, -#error user dedication and a lack of use/testing. We urge users to consider -#error using a more established TLS backend instead. - -#include <axTLS/config.h> -#include <axTLS/ssl.h> -#include "axtls.h" - -#include "sendf.h" -#include "inet_pton.h" -#include "vtls.h" -#include "parsedate.h" -#include "connect.h" /* for the connect timeout */ -#include "select.h" -#include "curl_printf.h" -#include "hostcheck.h" -#include <unistd.h> - -/* The last #include files should be: */ -#include "curl_memory.h" -#include "memdebug.h" - -struct ssl_backend_data { - SSL_CTX* ssl_ctx; - SSL* ssl; -}; - -#define BACKEND connssl->backend - -static CURLcode map_error_to_curl(int axtls_err) -{ - switch(axtls_err) { - case SSL_ERROR_NOT_SUPPORTED: - case SSL_ERROR_INVALID_VERSION: - case -70: /* protocol version alert from server */ - return CURLE_UNSUPPORTED_PROTOCOL; - break; - case SSL_ERROR_NO_CIPHER: - return CURLE_SSL_CIPHER; - break; - case SSL_ERROR_BAD_CERTIFICATE: /* this may be bad server cert too */ - case SSL_ERROR_NO_CERT_DEFINED: - case -42: /* bad certificate alert from server */ - case -43: /* unsupported cert alert from server */ - case -44: /* cert revoked alert from server */ - case -45: /* cert expired alert from server */ - case -46: /* cert unknown alert from server */ - return CURLE_SSL_CERTPROBLEM; - break; - case SSL_X509_ERROR(X509_NOT_OK): - case SSL_X509_ERROR(X509_VFY_ERROR_NO_TRUSTED_CERT): - case SSL_X509_ERROR(X509_VFY_ERROR_BAD_SIGNATURE): - case SSL_X509_ERROR(X509_VFY_ERROR_NOT_YET_VALID): - case SSL_X509_ERROR(X509_VFY_ERROR_EXPIRED): - case SSL_X509_ERROR(X509_VFY_ERROR_SELF_SIGNED): - case SSL_X509_ERROR(X509_VFY_ERROR_INVALID_CHAIN): - case SSL_X509_ERROR(X509_VFY_ERROR_UNSUPPORTED_DIGEST): - case SSL_X509_ERROR(X509_INVALID_PRIV_KEY): - return CURLE_PEER_FAILED_VERIFICATION; - break; - case -48: /* unknown ca alert from server */ - return CURLE_SSL_CACERT; - break; - case -49: /* access denied alert from server */ - return CURLE_REMOTE_ACCESS_DENIED; - break; - case SSL_ERROR_CONN_LOST: - case SSL_ERROR_SOCK_SETUP_FAILURE: - case SSL_ERROR_INVALID_HANDSHAKE: - case SSL_ERROR_INVALID_PROT_MSG: - case SSL_ERROR_INVALID_HMAC: - case SSL_ERROR_INVALID_SESSION: - case SSL_ERROR_INVALID_KEY: /* it's too bad this doesn't map better */ - case SSL_ERROR_FINISHED_INVALID: - case SSL_ERROR_NO_CLIENT_RENOG: - default: - return CURLE_SSL_CONNECT_ERROR; - break; - } -} - -static Curl_recv axtls_recv; -static Curl_send axtls_send; - -static void free_ssl_structs(struct ssl_connect_data *connssl) -{ - if(BACKEND->ssl) { - ssl_free(BACKEND->ssl); - BACKEND->ssl = NULL; - } - if(BACKEND->ssl_ctx) { - ssl_ctx_free(BACKEND->ssl_ctx); - BACKEND->ssl_ctx = NULL; - } -} - -/* - * For both blocking and non-blocking connects, this function sets up the - * ssl context and state. This function is called after the TCP connect - * has completed. - */ -static CURLcode connect_prep(struct connectdata *conn, int sockindex) -{ - struct ssl_connect_data *connssl = &conn->ssl[sockindex]; - struct Curl_easy *data = conn->data; - SSL_CTX *ssl_ctx; - SSL *ssl = NULL; - int cert_types[] = {SSL_OBJ_X509_CERT, SSL_OBJ_PKCS12, 0}; - int key_types[] = {SSL_OBJ_RSA_KEY, SSL_OBJ_PKCS8, SSL_OBJ_PKCS12, 0}; - int i, ssl_fcn_return; - - /* Assuming users will not compile in custom key/cert to axTLS. - * Also, even for blocking connects, use axTLS non-blocking feature. - */ - uint32_t client_option = SSL_NO_DEFAULT_KEY | - SSL_SERVER_VERIFY_LATER | - SSL_CONNECT_IN_PARTS; - - if(connssl->state == ssl_connection_complete) - /* to make us tolerant against being called more than once for the - same connection */ - return CURLE_OK; - - if(SSL_CONN_CONFIG(version_max) != CURL_SSLVERSION_MAX_NONE) { - failf(data, "axtls does not support CURL_SSLVERSION_MAX"); - return CURLE_SSL_CONNECT_ERROR; - } - - - /* axTLS only supports TLSv1 */ - /* check to see if we've been told to use an explicit SSL/TLS version */ - switch(SSL_CONN_CONFIG(version)) { - case CURL_SSLVERSION_DEFAULT: - case CURL_SSLVERSION_TLSv1: - break; - default: - failf(data, "axTLS only supports TLS 1.0 and 1.1, " - "and it cannot be specified which one to use"); - return CURLE_SSL_CONNECT_ERROR; - } - -#ifdef AXTLSDEBUG - client_option |= SSL_DISPLAY_STATES | SSL_DISPLAY_RSA | SSL_DISPLAY_CERTS; -#endif /* AXTLSDEBUG */ - - /* Allocate an SSL_CTX struct */ - ssl_ctx = ssl_ctx_new(client_option, SSL_DEFAULT_CLNT_SESS); - if(ssl_ctx == NULL) { - failf(data, "unable to create client SSL context"); - return CURLE_SSL_CONNECT_ERROR; - } - - BACKEND->ssl_ctx = ssl_ctx; - BACKEND->ssl = NULL; - - /* Load the trusted CA cert bundle file */ - if(SSL_CONN_CONFIG(CAfile)) { - if(ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CACERT, - SSL_CONN_CONFIG(CAfile), NULL) != SSL_OK) { - infof(data, "error reading ca cert file %s \n", - SSL_CONN_CONFIG(CAfile)); - if(SSL_CONN_CONFIG(verifypeer)) { - return CURLE_SSL_CACERT_BADFILE; - } - } - else - infof(data, "found certificates in %s\n", SSL_CONN_CONFIG(CAfile)); - } - - /* gtls.c tasks we're skipping for now: - * 1) certificate revocation list checking - * 2) dns name assignment to host - * 3) set protocol priority. axTLS is TLSv1 only, so can probably ignore - * 4) set certificate priority. axTLS ignores type and sends certs in - * order added. can probably ignore this. - */ - - /* Load client certificate */ - if(SSL_SET_OPTION(cert)) { - i = 0; - /* Instead of trying to analyze cert type here, let axTLS try them all. */ - while(cert_types[i] != 0) { - ssl_fcn_return = ssl_obj_load(ssl_ctx, cert_types[i], - SSL_SET_OPTION(cert), NULL); - if(ssl_fcn_return == SSL_OK) { - infof(data, "successfully read cert file %s \n", - SSL_SET_OPTION(cert)); - break; - } - i++; - } - /* Tried all cert types, none worked. */ - if(cert_types[i] == 0) { - failf(data, "%s is not x509 or pkcs12 format", - SSL_SET_OPTION(cert)); - return CURLE_SSL_CERTPROBLEM; - } - } - - /* Load client key. - If a pkcs12 file successfully loaded a cert, then there's nothing to do - because the key has already been loaded. */ - if(SSL_SET_OPTION(key) && cert_types[i] != SSL_OBJ_PKCS12) { - i = 0; - /* Instead of trying to analyze key type here, let axTLS try them all. */ - while(key_types[i] != 0) { - ssl_fcn_return = ssl_obj_load(ssl_ctx, key_types[i], - SSL_SET_OPTION(key), NULL); - if(ssl_fcn_return == SSL_OK) { - infof(data, "successfully read key file %s \n", - SSL_SET_OPTION(key)); - break; - } - i++; - } - /* Tried all key types, none worked. */ - if(key_types[i] == 0) { - failf(data, "Failure: %s is not a supported key file", - SSL_SET_OPTION(key)); - return CURLE_SSL_CONNECT_ERROR; - } - } - - /* gtls.c does more here that is being left out for now - * 1) set session credentials. can probably ignore since axtls puts this - * info in the ssl_ctx struct - * 2) setting up callbacks. these seem gnutls specific - */ - - if(SSL_SET_OPTION(primary.sessionid)) { - const uint8_t *ssl_sessionid; - size_t ssl_idsize; - - /* In axTLS, handshaking happens inside ssl_client_new. */ - Curl_ssl_sessionid_lock(conn); - if(!Curl_ssl_getsessionid(conn, (void **) &ssl_sessionid, &ssl_idsize, - sockindex)) { - /* we got a session id, use it! */ - infof(data, "SSL re-using session ID\n"); - ssl = ssl_client_new(ssl_ctx, conn->sock[sockindex], - ssl_sessionid, (uint8_t)ssl_idsize, NULL); - } - Curl_ssl_sessionid_unlock(conn); - } - - if(!ssl) - ssl = ssl_client_new(ssl_ctx, conn->sock[sockindex], NULL, 0, NULL); - - BACKEND->ssl = ssl; - return CURLE_OK; -} - -static void Curl_axtls_close(struct connectdata *conn, int sockindex) -{ - struct ssl_connect_data *connssl = &conn->ssl[sockindex]; - - infof(conn->data, " Curl_axtls_close\n"); - - /* line from openssl.c: (void)SSL_shutdown(BACKEND->ssl); - axTLS compat layer does nothing for SSL_shutdown */ - - /* The following line is from openssl.c. There seems to be no axTLS - equivalent. ssl_free and ssl_ctx_free close things. - SSL_set_connect_state(connssl->handle); */ - - free_ssl_structs(connssl); -} - -/* - * For both blocking and non-blocking connects, this function finalizes the - * SSL connection. - */ -static CURLcode connect_finish(struct connectdata *conn, int sockindex) -{ - struct Curl_easy *data = conn->data; - struct ssl_connect_data *connssl = &conn->ssl[sockindex]; - SSL *ssl = BACKEND->ssl; - const char *peer_CN; - uint32_t dns_altname_index; - const char *dns_altname; - int8_t found_subject_alt_names = 0; - int8_t found_subject_alt_name_matching_conn = 0; - const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : - conn->host.name; - const char * const dispname = SSL_IS_PROXY() ? - conn->http_proxy.host.dispname : conn->host.dispname; - - /* Here, gtls.c gets the peer certificates and fails out depending on - * settings in "data." axTLS api doesn't have get cert chain fcn, so omit? - */ - - /* Verify server's certificate */ - if(SSL_CONN_CONFIG(verifypeer)) { - if(ssl_verify_cert(ssl) != SSL_OK) { - Curl_axtls_close(conn, sockindex); - failf(data, "server cert verify failed"); - return CURLE_PEER_FAILED_VERIFICATION; - } - } - else - infof(data, "\t server certificate verification SKIPPED\n"); - - /* Here, gtls.c does issuer verification. axTLS has no straightforward - * equivalent, so omitting for now.*/ - - /* Here, gtls.c does the following - * 1) x509 hostname checking per RFC2818. axTLS doesn't support this, but - * it seems useful. This is now implemented, by Oscar Koeroo - * 2) checks cert validity based on time. axTLS does this in ssl_verify_cert - * 3) displays a bunch of cert information. axTLS doesn't support most of - * this, but a couple fields are available. - */ - - /* There is no (DNS) Altnames count in the version 1.4.8 API. There is a - risk of an inifite loop */ - for(dns_altname_index = 0; ; dns_altname_index++) { - dns_altname = ssl_get_cert_subject_alt_dnsname(ssl, dns_altname_index); - if(dns_altname == NULL) { - break; - } - found_subject_alt_names = 1; - - infof(data, "\tComparing subject alt name DNS with hostname: %s <-> %s\n", - dns_altname, hostname); - if(Curl_cert_hostcheck(dns_altname, hostname)) { - found_subject_alt_name_matching_conn = 1; - break; - } - } - - /* RFC2818 checks */ - if(found_subject_alt_names && !found_subject_alt_name_matching_conn) { - if(SSL_CONN_CONFIG(verifyhost)) { - /* Break connection ! */ - Curl_axtls_close(conn, sockindex); - failf(data, "\tsubjectAltName(s) do not match %s\n", dispname); - return CURLE_PEER_FAILED_VERIFICATION; - } - else - infof(data, "\tsubjectAltName(s) do not match %s\n", dispname); - } - else if(found_subject_alt_names == 0) { - /* Per RFC2818, when no Subject Alt Names were available, examine the peer - CN as a legacy fallback */ - peer_CN = ssl_get_cert_dn(ssl, SSL_X509_CERT_COMMON_NAME); - if(peer_CN == NULL) { - if(SSL_CONN_CONFIG(verifyhost)) { - Curl_axtls_close(conn, sockindex); - failf(data, "unable to obtain common name from peer certificate"); - return CURLE_PEER_FAILED_VERIFICATION; - } - else - infof(data, "unable to obtain common name from peer certificate"); - } - else { - if(!Curl_cert_hostcheck((const char *)peer_CN, hostname)) { - if(SSL_CONN_CONFIG(verifyhost)) { - /* Break connection ! */ - Curl_axtls_close(conn, sockindex); - failf(data, "\tcommon name \"%s\" does not match \"%s\"\n", - peer_CN, dispname); - return CURLE_PEER_FAILED_VERIFICATION; - } - else - infof(data, "\tcommon name \"%s\" does not match \"%s\"\n", - peer_CN, dispname); - } - } - } - - /* General housekeeping */ - connssl->state = ssl_connection_complete; - conn->recv[sockindex] = axtls_recv; - conn->send[sockindex] = axtls_send; - - /* Put our freshly minted SSL session in cache */ - if(SSL_SET_OPTION(primary.sessionid)) { - const uint8_t *ssl_sessionid = ssl_get_session_id(ssl); - size_t ssl_idsize = ssl_get_session_id_size(ssl); - Curl_ssl_sessionid_lock(conn); - if(Curl_ssl_addsessionid(conn, (void *) ssl_sessionid, ssl_idsize, - sockindex) != CURLE_OK) - infof(data, "failed to add session to cache\n"); - Curl_ssl_sessionid_unlock(conn); - } - - return CURLE_OK; -} - -/* - * Use axTLS's non-blocking connection feature to open an SSL connection. - * This is called after a TCP connection is already established. - */ -static CURLcode Curl_axtls_connect_nonblocking(struct connectdata *conn, - int sockindex, bool *done) -{ - struct ssl_connect_data *connssl = &conn->ssl[sockindex]; - CURLcode conn_step; - int ssl_fcn_return; - int i; - - *done = FALSE; - /* connectdata is calloc'd and connecting_state is only changed in this - function, so this is safe, as the state is effectively initialized. */ - if(connssl->connecting_state == ssl_connect_1) { - conn_step = connect_prep(conn, sockindex); - if(conn_step != CURLE_OK) { - Curl_axtls_close(conn, sockindex); - return conn_step; - } - connssl->connecting_state = ssl_connect_2; - } - - if(connssl->connecting_state == ssl_connect_2) { - /* Check to make sure handshake was ok. */ - if(ssl_handshake_status(BACKEND->ssl) != SSL_OK) { - /* Loop to perform more work in between sleeps. This is work around the - fact that axtls does not expose any knowledge about when work needs - to be performed. This can save ~25% of time on SSL handshakes. */ - for(i = 0; i<5; i++) { - ssl_fcn_return = ssl_read(BACKEND->ssl, NULL); - if(ssl_fcn_return < 0) { - Curl_axtls_close(conn, sockindex); - ssl_display_error(ssl_fcn_return); /* goes to stdout. */ - return map_error_to_curl(ssl_fcn_return); - } - return CURLE_OK; - } - } - infof(conn->data, "handshake completed successfully\n"); - connssl->connecting_state = ssl_connect_3; - } - - if(connssl->connecting_state == ssl_connect_3) { - conn_step = connect_finish(conn, sockindex); - if(conn_step != CURLE_OK) { - Curl_axtls_close(conn, sockindex); - return conn_step; - } - - /* Reset connect state */ - connssl->connecting_state = ssl_connect_1; - - *done = TRUE; - return CURLE_OK; - } - - /* Unrecognized state. Things are very bad. */ - connssl->state = ssl_connection_none; - connssl->connecting_state = ssl_connect_1; - /* Return value perhaps not strictly correct, but distinguishes the issue.*/ - return CURLE_BAD_FUNCTION_ARGUMENT; -} - - -/* - * This function is called after the TCP connect has completed. Setup the TLS - * layer and do all necessary magic for a blocking connect. - */ -static CURLcode Curl_axtls_connect(struct connectdata *conn, int sockindex) -{ - struct Curl_easy *data = conn->data; - CURLcode conn_step = connect_prep(conn, sockindex); - int ssl_fcn_return; - struct ssl_connect_data *connssl = &conn->ssl[sockindex]; - SSL *ssl = BACKEND->ssl; - long timeout_ms; - - if(conn_step != CURLE_OK) { - Curl_axtls_close(conn, sockindex); - return conn_step; - } - - /* Check to make sure handshake was ok. */ - while(ssl_handshake_status(ssl) != SSL_OK) { - /* check allowed time left */ - timeout_ms = Curl_timeleft(data, NULL, TRUE); - - if(timeout_ms < 0) { - /* no need to continue if time already is up */ - failf(data, "SSL connection timeout"); - return CURLE_OPERATION_TIMEDOUT; - } - - ssl_fcn_return = ssl_read(ssl, NULL); - if(ssl_fcn_return < 0) { - Curl_axtls_close(conn, sockindex); - ssl_display_error(ssl_fcn_return); /* goes to stdout. */ - return map_error_to_curl(ssl_fcn_return); - } - /* TODO: avoid polling */ - Curl_wait_ms(10); - } - infof(conn->data, "handshake completed successfully\n"); - - conn_step = connect_finish(conn, sockindex); - if(conn_step != CURLE_OK) { - Curl_axtls_close(conn, sockindex); - return conn_step; - } - - return CURLE_OK; -} - -/* return number of sent (non-SSL) bytes */ -static ssize_t axtls_send(struct connectdata *conn, - int sockindex, - const void *mem, - size_t len, - CURLcode *err) -{ - struct ssl_connect_data *connssl = &conn->ssl[sockindex]; - /* ssl_write() returns 'int' while write() and send() returns 'size_t' */ - int rc = ssl_write(BACKEND->ssl, mem, (int)len); - - infof(conn->data, " axtls_send\n"); - - if(rc < 0) { - *err = map_error_to_curl(rc); - rc = -1; /* generic error code for send failure */ - } - - *err = CURLE_OK; - return rc; -} - -/* - * This function is called to shut down the SSL layer but keep the - * socket open (CCC - Clear Command Channel) - */ -static int Curl_axtls_shutdown(struct connectdata *conn, int sockindex) -{ - /* Outline taken from openssl.c since functions are in axTLS compat layer. - axTLS's error set is much smaller, so a lot of error-handling was removed. - */ - int retval = 0; - struct ssl_connect_data *connssl = &conn->ssl[sockindex]; - struct Curl_easy *data = conn->data; - uint8_t *buf; - ssize_t nread; - - infof(conn->data, " Curl_axtls_shutdown\n"); - - /* This has only been tested on the proftpd server, and the mod_tls code - sends a close notify alert without waiting for a close notify alert in - response. Thus we wait for a close notify alert from the server, but - we do not send one. Let's hope other servers do the same... */ - - /* axTLS compat layer does nothing for SSL_shutdown, so we do nothing too - if(data->set.ftp_ccc == CURLFTPSSL_CCC_ACTIVE) - (void)SSL_shutdown(BACKEND->ssl); - */ - - if(BACKEND->ssl) { - int what = SOCKET_READABLE(conn->sock[sockindex], SSL_SHUTDOWN_TIMEOUT); - if(what > 0) { - /* Something to read, let's do it and hope that it is the close - notify alert from the server. buf is managed internally by - axTLS and will be released upon calling ssl_free via - free_ssl_structs. */ - nread = (ssize_t)ssl_read(BACKEND->ssl, &buf); - - if(nread < SSL_OK) { - failf(data, "close notify alert not received during shutdown"); - retval = -1; - } - } - else if(0 == what) { - /* timeout */ - failf(data, "SSL shutdown timeout"); - } - else { - /* anything that gets here is fatally bad */ - failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); - retval = -1; - } - - free_ssl_structs(connssl); - } - return retval; -} - -static ssize_t axtls_recv(struct connectdata *conn, /* connection data */ - int num, /* socketindex */ - char *buf, /* store read data here */ - size_t buffersize, /* max amount to read */ - CURLcode *err) -{ - struct ssl_connect_data *connssl = &conn->ssl[num]; - ssize_t ret = 0; - uint8_t *read_buf; - - infof(conn->data, " axtls_recv\n"); - - *err = CURLE_OK; - if(connssl) { - ret = ssl_read(BACKEND->ssl, &read_buf); - if(ret > SSL_OK) { - /* ssl_read returns SSL_OK if there is more data to read, so if it is - larger, then all data has been read already. */ - memcpy(buf, read_buf, - (size_t)ret > buffersize ? buffersize : (size_t)ret); - } - else if(ret == SSL_OK) { - /* more data to be read, signal caller to call again */ - *err = CURLE_AGAIN; - ret = -1; - } - else if(ret == -3) { - /* With patched axTLS, SSL_CLOSE_NOTIFY=-3. Hard-coding until axTLS - team approves proposed fix. */ - Curl_axtls_close(conn, num); - } - else { - failf(conn->data, "axTLS recv error (%d)", ret); - *err = map_error_to_curl((int) ret); - ret = -1; - } - } - - return ret; -} - -/* - * Return codes: - * 1 means the connection is still in place - * 0 means the connection has been closed - * -1 means the connection status is unknown - */ -static int Curl_axtls_check_cxn(struct connectdata *conn) -{ - /* openssl.c line: - rc = SSL_peek(conn->ssl[FIRSTSOCKET].backend->ssl, (void*)&buf, 1); - axTLS compat layer always returns the last argument, so connection is - always alive? */ - - infof(conn->data, " Curl_axtls_check_cxn\n"); - return 1; /* connection still in place */ -} - -static void Curl_axtls_session_free(void *ptr) -{ - (void)ptr; - /* free the ID */ - /* both openssl.c and gtls.c do something here, but axTLS's OpenSSL - compatibility layer does nothing, so we do nothing too. */ -} - -static size_t Curl_axtls_version(char *buffer, size_t size) -{ - return snprintf(buffer, size, "axTLS/%s", ssl_version()); -} - -static CURLcode Curl_axtls_random(struct Curl_easy *data, - unsigned char *entropy, size_t length) -{ - static bool ssl_seeded = FALSE; - (void)data; - if(!ssl_seeded) { - ssl_seeded = TRUE; - /* Initialize the seed if not already done. This call is not exactly thread - * safe (and neither is the ssl_seeded check), but the worst effect of a - * race condition is that some global resources will leak. */ - RNG_initialize(); - } - get_random((int)length, entropy); - return CURLE_OK; -} - -static void *Curl_axtls_get_internals(struct ssl_connect_data *connssl, - CURLINFO info UNUSED_PARAM) -{ - (void)info; - return BACKEND->ssl; -} - -const struct Curl_ssl Curl_ssl_axtls = { - { CURLSSLBACKEND_AXTLS, "axtls" }, /* info */ - 0, /* no fancy stuff */ - sizeof(struct ssl_backend_data), - - /* - * axTLS has no global init. Everything is done through SSL and SSL_CTX - * structs stored in connectdata structure. - */ - Curl_none_init, /* init */ - /* axTLS has no global cleanup. */ - Curl_none_cleanup, /* cleanup */ - Curl_axtls_version, /* version */ - Curl_axtls_check_cxn, /* check_cxn */ - Curl_axtls_shutdown, /* shutdown */ - Curl_none_data_pending, /* data_pending */ - Curl_axtls_random, /* random */ - Curl_none_cert_status_request, /* cert_status_request */ - Curl_axtls_connect, /* connect */ - Curl_axtls_connect_nonblocking, /* connect_nonblocking */ - Curl_axtls_get_internals, /* get_internals */ - Curl_axtls_close, /* close_one */ - Curl_none_close_all, /* close_all */ - Curl_axtls_session_free, /* session_free */ - Curl_none_set_engine, /* set_engine */ - Curl_none_set_engine_default, /* set_engine_default */ - Curl_none_engines_list, /* engines_list */ - Curl_none_false_start, /* false_start */ - Curl_none_md5sum, /* md5sum */ - NULL /* sha256sum */ -}; - -#endif /* USE_AXTLS */ diff --git a/Utilities/cmcurl/lib/vtls/axtls.h b/Utilities/cmcurl/lib/vtls/axtls.h deleted file mode 100644 index cb81872..0000000 --- a/Utilities/cmcurl/lib/vtls/axtls.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef HEADER_CURL_AXTLS_H -#define HEADER_CURL_AXTLS_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 2010, DirecTV, Contact: Eric Hu <ehu@directv.com> - * Copyright (C) 2010 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at https://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ - -#ifdef USE_AXTLS -#include "curl/curl.h" -#include "urldata.h" - -extern const struct Curl_ssl Curl_ssl_axtls; - -#endif /* USE_AXTLS */ -#endif /* HEADER_CURL_AXTLS_H */ diff --git a/Utilities/cmcurl/lib/vtls/cyassl.c b/Utilities/cmcurl/lib/vtls/cyassl.c index e10398a..44a2bdd 100644 --- a/Utilities/cmcurl/lib/vtls/cyassl.c +++ b/Utilities/cmcurl/lib/vtls/cyassl.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2019, 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 @@ -67,15 +67,6 @@ and that's a problem since options.h hasn't been included yet. */ #endif #endif -/* HAVE_SUPPORTED_CURVES is wolfSSL's build time symbol for enabling the ECC - supported curve extension in options.h. Note ECC is enabled separately. */ -#ifndef HAVE_SUPPORTED_CURVES -#if defined(HAVE_CYASSL_CTX_USESUPPORTEDCURVE) || \ - defined(HAVE_WOLFSSL_CTX_USESUPPORTEDCURVE) -#define HAVE_SUPPORTED_CURVES -#endif -#endif - #include <limits.h> #include "urldata.h" @@ -88,6 +79,7 @@ and that's a problem since options.h hasn't been included yet. */ #include "strcase.h" #include "x509asn1.h" #include "curl_printf.h" +#include "multiif.h" #include <cyassl/openssl/ssl.h> #include <cyassl/ssl.h> @@ -151,7 +143,6 @@ static CURLcode cyassl_connect_step1(struct connectdata *conn, int sockindex) { - char error_buffer[CYASSL_MAX_ERROR_SZ]; char *ciphers; struct Curl_easy *data = conn->data; struct ssl_connect_data* connssl = &conn->ssl[sockindex]; @@ -364,16 +355,6 @@ cyassl_connect_step1(struct connectdata *conn, } #endif -#ifdef HAVE_SUPPORTED_CURVES - /* CyaSSL/wolfSSL does not send the supported ECC curves ext automatically: - https://github.com/wolfSSL/wolfssl/issues/366 - The supported curves below are those also supported by OpenSSL 1.0.2 and - in the same order. */ - CyaSSL_CTX_UseSupportedCurve(BACKEND->ctx, 0x17); /* secp256r1 */ - CyaSSL_CTX_UseSupportedCurve(BACKEND->ctx, 0x19); /* secp521r1 */ - CyaSSL_CTX_UseSupportedCurve(BACKEND->ctx, 0x18); /* secp384r1 */ -#endif - /* give application a chance to interfere with SSL set up. */ if(data->set.ssl.fsslctx) { CURLcode result = CURLE_OK; @@ -438,6 +419,7 @@ cyassl_connect_step1(struct connectdata *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)) { + char error_buffer[CYASSL_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), @@ -618,6 +600,8 @@ cyassl_connect_step2(struct connectdata *conn, else infof(data, "ALPN, unrecognized protocol %.*s\n", protocol_len, protocol); + Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ? + BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE); } else if(rc == SSL_ALPN_NOT_FOUND) infof(data, "ALPN, server did not agree to a protocol\n"); @@ -777,13 +761,13 @@ static void Curl_cyassl_session_free(void *ptr) static size_t Curl_cyassl_version(char *buffer, size_t size) { #if LIBCYASSL_VERSION_HEX >= 0x03006000 - return snprintf(buffer, size, "wolfSSL/%s", wolfSSL_lib_version()); + return msnprintf(buffer, size, "wolfSSL/%s", wolfSSL_lib_version()); #elif defined(WOLFSSL_VERSION) - return snprintf(buffer, size, "wolfSSL/%s", WOLFSSL_VERSION); + return msnprintf(buffer, size, "wolfSSL/%s", WOLFSSL_VERSION); #elif defined(CYASSL_VERSION) - return snprintf(buffer, size, "CyaSSL/%s", CYASSL_VERSION); + return msnprintf(buffer, size, "CyaSSL/%s", CYASSL_VERSION); #else - return snprintf(buffer, size, "CyaSSL/%s", "<1.8.8"); + return msnprintf(buffer, size, "CyaSSL/%s", "<1.8.8"); #endif } @@ -794,6 +778,12 @@ static int Curl_cyassl_init(void) } +static void Curl_cyassl_cleanup(void) +{ + CyaSSL_Cleanup(); +} + + static bool Curl_cyassl_data_pending(const struct connectdata* conn, int connindex) { @@ -1004,7 +994,7 @@ const struct Curl_ssl Curl_ssl_cyassl = { sizeof(struct ssl_backend_data), Curl_cyassl_init, /* init */ - Curl_none_cleanup, /* cleanup */ + Curl_cyassl_cleanup, /* cleanup */ Curl_cyassl_version, /* version */ Curl_none_check_cxn, /* check_cxn */ Curl_cyassl_shutdown, /* shutdown */ diff --git a/Utilities/cmcurl/lib/vtls/gskit.c b/Utilities/cmcurl/lib/vtls/gskit.c index 8d1b3d6..b93ff5d 100644 --- a/Utilities/cmcurl/lib/vtls/gskit.c +++ b/Utilities/cmcurl/lib/vtls/gskit.c @@ -734,12 +734,11 @@ static ssize_t gskit_recv(struct connectdata *conn, int num, char *buf, { struct ssl_connect_data *connssl = &conn->ssl[num]; struct Curl_easy *data = conn->data; - int buffsize; int nread; CURLcode cc = CURLE_RECV_ERROR; if(pipe_ssloverssl(conn, num, SOS_READ) >= 0) { - buffsize = buffersize > (size_t) INT_MAX? INT_MAX: (int) buffersize; + int buffsize = buffersize > (size_t) INT_MAX? INT_MAX: (int) buffersize; cc = gskit_status(data, gsk_secure_soc_read(BACKEND->handle, buf, buffsize, &nread), "gsk_secure_soc_read()", CURLE_RECV_ERROR); @@ -806,7 +805,6 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex) conn->host.name; const char *sni; unsigned int protoflags = 0; - long timeout; Qso_OverlappedIO_t commarea; int sockpair[2]; static const int sobufsize = CURL_MAX_WRITE_SIZE; @@ -914,7 +912,7 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex) if(!result) { /* Compute the handshake timeout. Since GSKit granularity is 1 second, we round up the required value. */ - timeout = Curl_timeleft(data, NULL, TRUE); + long timeout = Curl_timeleft(data, NULL, TRUE); if(timeout < 0) result = CURLE_OPERATION_TIMEDOUT; else @@ -1021,14 +1019,13 @@ static CURLcode gskit_connect_step2(struct connectdata *conn, int sockindex, struct Curl_easy *data = conn->data; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; Qso_OverlappedIO_t cstat; - long timeout_ms; struct timeval stmv; CURLcode result; /* Poll or wait for end of SSL asynchronous handshake. */ for(;;) { - timeout_ms = nonblocking? 0: Curl_timeleft(data, NULL, TRUE); + long timeout_ms = nonblocking? 0: Curl_timeleft(data, NULL, TRUE); if(timeout_ms < 0) timeout_ms = 0; stmv.tv_sec = timeout_ms / 1000; @@ -1077,7 +1074,6 @@ static CURLcode gskit_connect_step3(struct connectdata *conn, int sockindex) const char *cert = (const char *) NULL; const char *certend; const char *ptr; - int i; CURLcode result; /* SSL handshake done: gather certificate info and verify host. */ @@ -1087,6 +1083,8 @@ static CURLcode gskit_connect_step3(struct connectdata *conn, int sockindex) &cdev, &cdec), "gsk_attribute_get_cert_info()", CURLE_SSL_CONNECT_ERROR) == CURLE_OK) { + int i; + infof(data, "Server certificate:\n"); p = cdev; for(i = 0; i++ < cdec; p++) @@ -1160,7 +1158,6 @@ static CURLcode gskit_connect_common(struct connectdata *conn, int sockindex, struct Curl_easy *data = conn->data; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; long timeout_ms; - Qso_OverlappedIO_t cstat; CURLcode result = CURLE_OK; *done = connssl->state == ssl_connection_complete; @@ -1262,7 +1259,6 @@ static int Curl_gskit_shutdown(struct connectdata *conn, int sockindex) { struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct Curl_easy *data = conn->data; - ssize_t nread; int what; int rc; char buf[120]; @@ -1270,8 +1266,10 @@ static int Curl_gskit_shutdown(struct connectdata *conn, int sockindex) if(!BACKEND->handle) return 0; +#ifndef CURL_DISABLE_FTP if(data->set.ftp_ccc != CURLFTPSSL_CCC_ACTIVE) return 0; +#endif close_one(connssl, conn, sockindex); rc = 0; @@ -1279,6 +1277,8 @@ static int Curl_gskit_shutdown(struct connectdata *conn, int sockindex) SSL_SHUTDOWN_TIMEOUT); for(;;) { + ssize_t nread; + if(what < 0) { /* anything that gets here is fatally bad */ failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); @@ -1314,7 +1314,7 @@ static int Curl_gskit_shutdown(struct connectdata *conn, int sockindex) static size_t Curl_gskit_version(char *buffer, size_t size) { - return snprintf(buffer, size, "GSKit"); + return msnprintf(buffer, size, "GSKit"); } diff --git a/Utilities/cmcurl/lib/vtls/gtls.c b/Utilities/cmcurl/lib/vtls/gtls.c index 37662a7..8693cdc 100644 --- a/Utilities/cmcurl/lib/vtls/gtls.c +++ b/Utilities/cmcurl/lib/vtls/gtls.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2019, 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 @@ -55,6 +55,7 @@ #include "strcase.h" #include "warnless.h" #include "x509asn1.h" +#include "multiif.h" #include "curl_printf.h" #include "curl_memory.h" /* The last #include file should be: */ @@ -227,17 +228,17 @@ static void showtime(struct Curl_easy *data, if(result) return; - snprintf(str, - sizeof(str), - "\t %s: %s, %02d %s %4d %02d:%02d:%02d GMT", - text, - Curl_wkday[tm->tm_wday?tm->tm_wday-1:6], - tm->tm_mday, - Curl_month[tm->tm_mon], - tm->tm_year + 1900, - tm->tm_hour, - tm->tm_min, - tm->tm_sec); + msnprintf(str, + sizeof(str), + "\t %s: %s, %02d %s %4d %02d:%02d:%02d GMT", + text, + Curl_wkday[tm->tm_wday?tm->tm_wday-1:6], + tm->tm_mday, + Curl_month[tm->tm_mon], + tm->tm_year + 1900, + tm->tm_hour, + tm->tm_min, + tm->tm_sec); infof(data, "%s\n", str); } #endif @@ -285,11 +286,11 @@ static CURLcode handshake(struct connectdata *conn, struct ssl_connect_data *connssl = &conn->ssl[sockindex]; gnutls_session_t session = BACKEND->session; curl_socket_t sockfd = conn->sock[sockindex]; - time_t timeout_ms; - int rc; - int what; for(;;) { + time_t timeout_ms; + int rc; + /* check allowed time left */ timeout_ms = Curl_timeleft(data, NULL, duringconnect); @@ -302,7 +303,7 @@ static CURLcode handshake(struct connectdata *conn, /* if ssl is expecting something, check if it's available. */ if(connssl->connecting_state == ssl_connect_2_reading || connssl->connecting_state == ssl_connect_2_writing) { - + int what; curl_socket_t writefd = ssl_connect_2_writing == connssl->connecting_state?sockfd:CURL_SOCKET_BAD; curl_socket_t readfd = ssl_connect_2_reading == @@ -956,7 +957,6 @@ static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data, gnutls_pubkey_t key = NULL; /* Result is returned to caller */ - int ret = 0; CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH; /* if a path wasn't specified, don't pin */ @@ -967,6 +967,8 @@ static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data, return result; do { + int ret; + /* Begin Gyrations to get the public key */ gnutls_pubkey_init(&key); @@ -1110,7 +1112,7 @@ gtls_connect_step3(struct connectdata *conn, "CRLfile: %s", SSL_CONN_CONFIG(CAfile) ? SSL_CONN_CONFIG(CAfile): "none", SSL_SET_OPTION(CRLfile)?SSL_SET_OPTION(CRLfile):"none"); - return CURLE_SSL_CACERT; + return CURLE_PEER_FAILED_VERIFICATION; } else infof(data, "\t server certificate verification FAILED\n"); @@ -1278,10 +1280,7 @@ gtls_connect_step3(struct connectdata *conn, #define use_addr in_addr #endif unsigned char addrbuf[sizeof(struct use_addr)]; - unsigned char certaddr[sizeof(struct use_addr)]; - size_t addrlen = 0, certaddrlen; - int i; - int ret = 0; + size_t addrlen = 0; if(Curl_inet_pton(AF_INET, hostname, addrbuf) > 0) addrlen = 4; @@ -1291,10 +1290,13 @@ gtls_connect_step3(struct connectdata *conn, #endif if(addrlen) { + unsigned char certaddr[sizeof(struct use_addr)]; + int i; + for(i = 0; ; i++) { - certaddrlen = sizeof(certaddr); - ret = gnutls_x509_crt_get_subject_alt_name(x509_cert, i, certaddr, - &certaddrlen, NULL); + size_t certaddrlen = sizeof(certaddr); + int ret = gnutls_x509_crt_get_subject_alt_name(x509_cert, i, certaddr, + &certaddrlen, NULL); /* If this happens, it wasn't an IP address. */ if(ret == GNUTLS_E_SHORT_MEMORY_BUFFER) continue; @@ -1423,11 +1425,6 @@ gtls_connect_step3(struct connectdata *conn, size = sizeof(certbuf); gnutls_x509_crt_get_issuer_dn(x509_cert, certbuf, &size); infof(data, "\t issuer: %s\n", certbuf); - - /* compression algorithm (if any) */ - ptr = gnutls_compression_get_name(gnutls_compression_get(session)); - /* the *_get_name() says "NULL" if GNUTLS_COMP_NULL is returned */ - infof(data, "\t compression: %s\n", ptr); #endif gnutls_x509_crt_deinit(x509_cert); @@ -1454,6 +1451,9 @@ gtls_connect_step3(struct connectdata *conn, } else infof(data, "ALPN, server did not agree to a protocol\n"); + + Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ? + BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE); } #endif @@ -1466,8 +1466,6 @@ gtls_connect_step3(struct connectdata *conn, already got it from the cache and asked to use it in the connection, it might've been rejected and then a new one is in use now and we need to detect that. */ - bool incache; - void *ssl_sessionid; void *connect_sessionid; size_t connect_idsize = 0; @@ -1476,6 +1474,9 @@ gtls_connect_step3(struct connectdata *conn, connect_sessionid = malloc(connect_idsize); /* get a buffer for it */ if(connect_sessionid) { + bool incache; + void *ssl_sessionid; + /* extract session ID to the allocated buffer */ gnutls_session_get_data(session, connect_sessionid, &connect_idsize); @@ -1636,12 +1637,10 @@ 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]; - ssize_t result; int retval = 0; struct Curl_easy *data = conn->data; - bool done = FALSE; - char buf[120]; +#ifndef CURL_DISABLE_FTP /* This has only been tested on the proftpd server, and the mod_tls code sends a close notify alert without waiting for a close notify alert in response. Thus we wait for a close notify alert from the server, but @@ -1649,8 +1648,13 @@ static int Curl_gtls_shutdown(struct connectdata *conn, int sockindex) if(data->set.ftp_ccc == CURLFTPSSL_CCC_ACTIVE) gnutls_bye(BACKEND->session, GNUTLS_SHUT_WR); +#endif if(BACKEND->session) { + ssize_t result; + bool done = FALSE; + char buf[120]; + while(!done) { int what = SOCKET_READABLE(conn->sock[sockindex], SSL_SHUTDOWN_TIMEOUT); @@ -1748,7 +1752,7 @@ static void Curl_gtls_session_free(void *ptr) static size_t Curl_gtls_version(char *buffer, size_t size) { - return snprintf(buffer, size, "GnuTLS/%s", gnutls_check_version(NULL)); + return msnprintf(buffer, size, "GnuTLS/%s", gnutls_check_version(NULL)); } #ifndef USE_GNUTLS_NETTLE @@ -1763,12 +1767,6 @@ static int Curl_gtls_seed(struct Curl_easy *data) if(!ssl_seeded || data->set.str[STRING_SSL_RANDOM_FILE] || data->set.str[STRING_SSL_EGDSOCKET]) { - - /* TODO: to a good job seeding the RNG - This may involve the gcry_control function and these options: - GCRYCTL_SET_RANDOM_SEED_FILE - GCRYCTL_SET_RNDEGD_SOCKET - */ ssl_seeded = TRUE; } return 0; diff --git a/Utilities/cmcurl/lib/vtls/mbedtls.c b/Utilities/cmcurl/lib/vtls/mbedtls.c index c5ed887..63d1f4c 100644 --- a/Utilities/cmcurl/lib/vtls/mbedtls.c +++ b/Utilities/cmcurl/lib/vtls/mbedtls.c @@ -6,7 +6,7 @@ * \___|\___/|_| \_\_____| * * Copyright (C) 2010 - 2011, Hoi-Ho Chan, <hoiho.chan@gmail.com> - * Copyright (C) 2012 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 2012 - 2019, 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 @@ -54,6 +54,7 @@ #include "parsedate.h" #include "connect.h" /* for the connect timeout */ #include "select.h" +#include "multiif.h" #include "polarssl_threadlock.h" /* The last 3 #include files should be in this order */ @@ -342,7 +343,8 @@ mbed_connect_step1(struct connectdata *conn, if(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)) + 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) { @@ -373,7 +375,7 @@ mbed_connect_step1(struct connectdata *conn, } } - infof(data, "mbedTLS: Connecting to %s:%d\n", hostname, port); + infof(data, "mbedTLS: Connecting to %s:%ld\n", hostname, port); mbedtls_ssl_config_init(&BACKEND->config); @@ -539,13 +541,6 @@ mbed_connect_step2(struct connectdata *conn, data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] : data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]; -#ifdef HAS_ALPN - const char *next_protocol; -#endif - - char errorbuf[128]; - errorbuf[0] = 0; - conn->recv[sockindex] = mbed_recv; conn->send[sockindex] = mbed_send; @@ -560,6 +555,8 @@ mbed_connect_step2(struct connectdata *conn, return CURLE_OK; } else if(ret) { + char errorbuf[128]; + errorbuf[0] = 0; #ifdef MBEDTLS_ERROR_C mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); #endif /* MBEDTLS_ERROR_C */ @@ -574,19 +571,21 @@ mbed_connect_step2(struct connectdata *conn, ret = mbedtls_ssl_get_verify_result(&BACKEND->ssl); + if(!SSL_CONN_CONFIG(verifyhost)) + /* Ignore hostname errors if verifyhost is disabled */ + ret &= ~MBEDTLS_X509_BADCERT_CN_MISMATCH; + if(ret && SSL_CONN_CONFIG(verifypeer)) { if(ret & MBEDTLS_X509_BADCERT_EXPIRED) failf(data, "Cert verify failed: BADCERT_EXPIRED"); - if(ret & MBEDTLS_X509_BADCERT_REVOKED) { + else if(ret & MBEDTLS_X509_BADCERT_REVOKED) failf(data, "Cert verify failed: BADCERT_REVOKED"); - return CURLE_SSL_CACERT; - } - if(ret & MBEDTLS_X509_BADCERT_CN_MISMATCH) + else if(ret & MBEDTLS_X509_BADCERT_CN_MISMATCH) failf(data, "Cert verify failed: BADCERT_CN_MISMATCH"); - if(ret & MBEDTLS_X509_BADCERT_NOT_TRUSTED) + else if(ret & MBEDTLS_X509_BADCERT_NOT_TRUSTED) failf(data, "Cert verify failed: BADCERT_NOT_TRUSTED"); return CURLE_PEER_FAILED_VERIFICATION; @@ -662,7 +661,7 @@ mbed_connect_step2(struct connectdata *conn, #ifdef HAS_ALPN if(conn->bits.tls_enable_alpn) { - 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); @@ -682,6 +681,8 @@ mbed_connect_step2(struct connectdata *conn, else { infof(data, "ALPN, server did not agree to a protocol\n"); } + Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ? + BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE); } #endif @@ -714,6 +715,8 @@ mbed_connect_step3(struct connectdata *conn, 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); free(our_ssl_sessionid); failf(data, "mbedtls_ssl_get_session returned -0x%x", -ret); return CURLE_SSL_CONNECT_ERROR; @@ -727,6 +730,7 @@ mbed_connect_step3(struct connectdata *conn, retcode = Curl_ssl_addsessionid(conn, our_ssl_sessionid, 0, sockindex); Curl_ssl_sessionid_unlock(conn); if(retcode) { + mbedtls_ssl_session_free(our_ssl_sessionid); free(our_ssl_sessionid); failf(data, "failed to store ssl session"); return retcode; @@ -811,9 +815,14 @@ static void Curl_mbedtls_session_free(void *ptr) static size_t Curl_mbedtls_version(char *buffer, size_t size) { +#ifdef MBEDTLS_VERSION_C + /* if mbedtls_version_get_number() is available it is better */ unsigned int version = mbedtls_version_get_number(); - return snprintf(buffer, size, "mbedTLS/%u.%u.%u", version>>24, - (version>>16)&0xff, (version>>8)&0xff); + return msnprintf(buffer, size, "mbedTLS/%u.%u.%u", version>>24, + (version>>16)&0xff, (version>>8)&0xff); +#else + return msnprintf(buffer, size, "mbedTLS/%s", MBEDTLS_VERSION_STRING); +#endif } static CURLcode Curl_mbedtls_random(struct Curl_easy *data, diff --git a/Utilities/cmcurl/lib/vtls/mesalink.c b/Utilities/cmcurl/lib/vtls/mesalink.c index 6a2b67e..718c282 100644 --- a/Utilities/cmcurl/lib/vtls/mesalink.c +++ b/Utilities/cmcurl/lib/vtls/mesalink.c @@ -5,8 +5,8 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2017-2018, Yiming Jing, <jingyiming@baidu.com> - * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 2017 - 2018, Yiming Jing, <jingyiming@baidu.com> + * Copyright (C) 1998 - 2018, 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 @@ -268,7 +268,7 @@ mesalink_connect_step2(struct connectdata *conn, int sockindex) char error_buffer[MESALINK_MAX_ERROR_SZ]; int detail = SSL_get_error(BACKEND->handle, ret); - if(SSL_ERROR_WANT_CONNECT == detail) { + if(SSL_ERROR_WANT_CONNECT == detail || SSL_ERROR_WANT_READ == detail) { connssl->connecting_state = ssl_connect_2_reading; return CURLE_OK; } @@ -424,7 +424,7 @@ mesalink_recv(struct connectdata *conn, int num, char *buf, size_t buffersize, static size_t Curl_mesalink_version(char *buffer, size_t size) { - return snprintf(buffer, size, "MesaLink/%s", MESALINK_VERSION_STRING); + return msnprintf(buffer, size, "MesaLink/%s", MESALINK_VERSION_STRING); } static int diff --git a/Utilities/cmcurl/lib/vtls/nss.c b/Utilities/cmcurl/lib/vtls/nss.c index a3d3e58..491def1 100644 --- a/Utilities/cmcurl/lib/vtls/nss.c +++ b/Utilities/cmcurl/lib/vtls/nss.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2019, 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 @@ -38,6 +38,7 @@ #include "select.h" #include "vtls.h" #include "llist.h" +#include "multiif.h" #include "curl_printf.h" #include "nssg.h" #include <nspr.h> @@ -246,6 +247,32 @@ static void nss_print_error_message(struct Curl_easy *data, PRUint32 err) failf(data, "%s", PR_ErrorToString(err, PR_LANGUAGE_I_DEFAULT)); } +static char *nss_sslver_to_name(PRUint16 nssver) +{ + switch(nssver) { + case SSL_LIBRARY_VERSION_2: + return strdup("SSLv2"); + case SSL_LIBRARY_VERSION_3_0: + return strdup("SSLv3"); + case SSL_LIBRARY_VERSION_TLS_1_0: + return strdup("TLSv1.0"); +#ifdef SSL_LIBRARY_VERSION_TLS_1_1 + case SSL_LIBRARY_VERSION_TLS_1_1: + return strdup("TLSv1.1"); +#endif +#ifdef SSL_LIBRARY_VERSION_TLS_1_2 + case SSL_LIBRARY_VERSION_TLS_1_2: + return strdup("TLSv1.2"); +#endif +#ifdef SSL_LIBRARY_VERSION_TLS_1_3 + case SSL_LIBRARY_VERSION_TLS_1_3: + return strdup("TLSv1.3"); +#endif + default: + return curl_maprintf("0x%04x", nssver); + } +} + static SECStatus set_ciphers(struct Curl_easy *data, PRFileDesc * model, char *cipher_list) { @@ -351,7 +378,7 @@ static int is_file(const char *filename) return 0; if(stat(filename, &st) == 0) - if(S_ISREG(st.st_mode)) + if(S_ISREG(st.st_mode) || S_ISFIFO(st.st_mode) || S_ISCHR(st.st_mode)) return 1; return 0; @@ -817,6 +844,8 @@ static void HandshakeCallback(PRFileDesc *sock, void *arg) !memcmp(ALPN_HTTP_1_1, buf, ALPN_HTTP_1_1_LENGTH)) { conn->negnpn = CURL_HTTP_VERSION_1_1; } + Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ? + BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE); } } @@ -1279,6 +1308,8 @@ static void nss_unload_module(SECMODModule **pmod) static CURLcode nss_init_core(struct Curl_easy *data, const char *cert_dir) { NSSInitParameters initparams; + PRErrorCode err; + const char *err_name; if(nss_context != NULL) return CURLE_OK; @@ -1299,7 +1330,9 @@ static CURLcode nss_init_core(struct Curl_easy *data, const char *cert_dir) if(nss_context != NULL) return CURLE_OK; - infof(data, "Unable to initialize NSS database\n"); + err = PR_GetError(); + err_name = nss_error_to_name(err); + infof(data, "Unable to initialize NSS database: %d (%s)\n", err, err_name); } infof(data, "Initializing NSS with certpath: none\n"); @@ -1309,7 +1342,9 @@ static CURLcode nss_init_core(struct Curl_easy *data, const char *cert_dir) if(nss_context != NULL) return CURLE_OK; - infof(data, "Unable to initialize NSS\n"); + err = PR_GetError(); + err_name = nss_error_to_name(err); + failf(data, "Unable to initialize NSS: %d (%s)", err, err_name); return CURLE_SSL_CACERT_BADFILE; } @@ -1638,17 +1673,6 @@ static CURLcode nss_load_ca_certificates(struct connectdata *conn, static CURLcode nss_sslver_from_curl(PRUint16 *nssver, long version) { switch(version) { - case CURL_SSLVERSION_TLSv1: - /* TODO: set sslver->max to SSL_LIBRARY_VERSION_TLS_1_3 once stable */ -#ifdef SSL_LIBRARY_VERSION_TLS_1_2 - *nssver = SSL_LIBRARY_VERSION_TLS_1_2; -#elif defined SSL_LIBRARY_VERSION_TLS_1_1 - *nssver = SSL_LIBRARY_VERSION_TLS_1_1; -#else - *nssver = SSL_LIBRARY_VERSION_TLS_1_0; -#endif - return CURLE_OK; - case CURL_SSLVERSION_SSLv2: *nssver = SSL_LIBRARY_VERSION_2; return CURLE_OK; @@ -1709,10 +1733,8 @@ static CURLcode nss_init_sslver(SSLVersionRange *sslver, } switch(min) { - case CURL_SSLVERSION_DEFAULT: - break; case CURL_SSLVERSION_TLSv1: - sslver->min = SSL_LIBRARY_VERSION_TLS_1_0; + case CURL_SSLVERSION_DEFAULT: break; default: result = nss_sslver_from_curl(&sslver->min, min); @@ -1789,10 +1811,19 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex) struct ssl_connect_data *connssl = &conn->ssl[sockindex]; CURLcode result; bool second_layer = FALSE; + SSLVersionRange sslver_supported; SSLVersionRange sslver = { SSL_LIBRARY_VERSION_TLS_1_0, /* min */ - SSL_LIBRARY_VERSION_TLS_1_0 /* max */ +#ifdef SSL_LIBRARY_VERSION_TLS_1_3 + SSL_LIBRARY_VERSION_TLS_1_3 /* max */ +#elif defined SSL_LIBRARY_VERSION_TLS_1_2 + SSL_LIBRARY_VERSION_TLS_1_2 +#elif defined SSL_LIBRARY_VERSION_TLS_1_1 + SSL_LIBRARY_VERSION_TLS_1_1 +#else + SSL_LIBRARY_VERSION_TLS_1_0 +#endif }; BACKEND->data = data; @@ -1800,7 +1831,6 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex) /* list of all NSS objects we need to destroy in Curl_nss_close() */ Curl_llist_init(&BACKEND->obj_list, nss_destroy_object); - /* FIXME. NSS doesn't support multiple databases open at the same time. */ PR_Lock(nss_initlock); result = nss_init(conn->data); if(result) { @@ -1841,6 +1871,20 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex) /* enable/disable the requested SSL version(s) */ if(nss_init_sslver(&sslver, data, conn) != CURLE_OK) goto error; + if(SSL_VersionRangeGetSupported(ssl_variant_stream, + &sslver_supported) != SECSuccess) + goto error; + if(sslver_supported.max < sslver.max && sslver_supported.max >= sslver.min) { + char *sslver_req_str, *sslver_supp_str; + sslver_req_str = nss_sslver_to_name(sslver.max); + sslver_supp_str = nss_sslver_to_name(sslver_supported.max); + if(sslver_req_str && sslver_supp_str) + infof(data, "Falling back from %s to max supported SSL version (%s)\n", + sslver_req_str, sslver_supp_str); + free(sslver_req_str); + free(sslver_supp_str); + sslver.max = sslver_supported.max; + } if(SSL_VersionRangeSet(model, &sslver) != SECSuccess) goto error; @@ -2090,7 +2134,7 @@ static CURLcode nss_do_connect(struct connectdata *conn, int sockindex) else if(*certverifyresult == SSL_ERROR_BAD_CERT_DOMAIN) result = CURLE_PEER_FAILED_VERIFICATION; else if(*certverifyresult != 0) - result = CURLE_SSL_CACERT; + result = CURLE_PEER_FAILED_VERIFICATION; goto error; } @@ -2164,7 +2208,7 @@ static CURLcode nss_connect_common(struct connectdata *conn, int sockindex, if(!blocking) /* CURLE_AGAIN in non-blocking mode is not an error */ return CURLE_OK; - /* fall through */ + /* FALLTHROUGH */ default: return result; } @@ -2279,7 +2323,7 @@ static ssize_t nss_recv(struct connectdata *conn, /* connection data */ static size_t Curl_nss_version(char *buffer, size_t size) { - return snprintf(buffer, size, "NSS/%s", NSS_VERSION); + return msnprintf(buffer, size, "NSS/%s", NSS_VERSION); } /* data might be NULL */ diff --git a/Utilities/cmcurl/lib/vtls/openssl.c b/Utilities/cmcurl/lib/vtls/openssl.c index 4c5e8c1..85e9be6 100644 --- a/Utilities/cmcurl/lib/vtls/openssl.c +++ b/Utilities/cmcurl/lib/vtls/openssl.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2019, 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 @@ -48,6 +48,7 @@ #include "vtls.h" #include "strcase.h" #include "hostcheck.h" +#include "multiif.h" #include "curl_printf.h" #include <openssl/ssl.h> #include <openssl/rand.h> @@ -65,11 +66,15 @@ #include <openssl/buffer.h> #include <openssl/pkcs12.h> +#ifdef USE_AMISSL +#include "amigaos.h" +#endif + #if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_OCSP) #include <openssl/ocsp.h> #endif -#if (OPENSSL_VERSION_NUMBER >= 0x0090800fL) && /* 0.9.8 or later */ \ +#if (OPENSSL_VERSION_NUMBER >= 0x0090700fL) && /* 0.9.7 or later */ \ !defined(OPENSSL_NO_ENGINE) #define USE_OPENSSL_ENGINE #include <openssl/engine.h> @@ -82,6 +87,13 @@ #include "curl_memory.h" #include "memdebug.h" +/* Uncomment the ALLOW_RENEG line to a real #define if you want to allow TLS + renegotiations when built with BoringSSL. Renegotiating is non-compliant + with HTTP/2 and "an extremely dangerous protocol feature". Beware. + +#define ALLOW_RENEG 1 + */ + #ifndef OPENSSL_VERSION_NUMBER #error "OPENSSL_VERSION_NUMBER not defined" #endif @@ -384,6 +396,31 @@ static char *ossl_strerror(unsigned long error, char *buf, size_t size) return buf; } +/* Return an extra data index for the connection data. + * This index can be used with SSL_get_ex_data() and SSL_set_ex_data(). + */ +static int ossl_get_ssl_conn_index(void) +{ + static int ssl_ex_data_conn_index = -1; + if(ssl_ex_data_conn_index < 0) { + ssl_ex_data_conn_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL); + } + return ssl_ex_data_conn_index; +} + +/* Return an extra data index for the sockindex. + * This index can be used with SSL_get_ex_data() and SSL_set_ex_data(). + */ +static int ossl_get_ssl_sockindex_index(void) +{ + static int ssl_ex_data_sockindex_index = -1; + if(ssl_ex_data_sockindex_index < 0) { + ssl_ex_data_sockindex_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, + NULL); + } + return ssl_ex_data_sockindex_index; +} + static int passwd_callback(char *buf, int num, int encrypting, void *global_passwd) { @@ -788,8 +825,11 @@ int cert_stuff(struct connectdata *conn, fail: EVP_PKEY_free(pri); X509_free(x509); +#ifdef USE_AMISSL + sk_X509_pop_free(ca, Curl_amiga_X509_free); +#else sk_X509_pop_free(ca, X509_free); - +#endif if(!cert_done) return 0; /* failure! */ break; @@ -799,15 +839,15 @@ int cert_stuff(struct connectdata *conn, return 0; } - file_type = do_file_type(key_type); + if(!key_file) + key_file = cert_file; + else + file_type = do_file_type(key_type); switch(file_type) { case SSL_FILETYPE_PEM: if(cert_done) break; - if(!key_file) - /* cert & key can only be in PEM case in the same file */ - key_file = cert_file; /* FALLTHROUGH */ case SSL_FILETYPE_ASN1: if(SSL_CTX_use_PrivateKey_file(ctx, key_file, file_type) != 1) { @@ -1035,6 +1075,10 @@ static int Curl_ossl_init(void) } #endif + /* Initialize the extra data indexes */ + if(ossl_get_ssl_conn_index() < 0 || ossl_get_ssl_sockindex_index() < 0) + return 0; + return 1; } @@ -1049,7 +1093,7 @@ static void Curl_ossl_cleanup(void) /* Free ciphers and digests lists */ EVP_cleanup(); -#ifdef HAVE_ENGINE_CLEANUP +#ifdef USE_OPENSSL_ENGINE /* Free engine list */ ENGINE_cleanup(); #endif @@ -1264,6 +1308,7 @@ static int Curl_ossl_shutdown(struct connectdata *conn, int sockindex) int err; bool done = FALSE; +#ifndef CURL_DISABLE_FTP /* This has only been tested on the proftpd server, and the mod_tls code sends a close notify alert without waiting for a close notify alert in response. Thus we wait for a close notify alert from the server, but @@ -1271,6 +1316,7 @@ static int Curl_ossl_shutdown(struct connectdata *conn, int sockindex) if(data->set.ftp_ccc == CURLFTPSSL_CCC_ACTIVE) (void)SSL_shutdown(BACKEND->handle); +#endif if(BACKEND->handle) { buffsize = (int)sizeof(buf); @@ -1656,6 +1702,7 @@ static CURLcode verifystatus(struct connectdata *conn, struct ssl_connect_data *connssl) { int i, ocsp_status; + unsigned char *status; const unsigned char *p; CURLcode result = CURLE_OK; struct Curl_easy *data = conn->data; @@ -1665,14 +1712,14 @@ static CURLcode verifystatus(struct connectdata *conn, X509_STORE *st = NULL; STACK_OF(X509) *ch = NULL; - long len = SSL_get_tlsext_status_ocsp_resp(BACKEND->handle, &p); + long len = SSL_get_tlsext_status_ocsp_resp(BACKEND->handle, &status); - if(!p) { + if(!status) { failf(data, "No OCSP response received"); result = CURLE_SSL_INVALIDCERTSTATUS; goto end; } - + p = status; rsp = d2i_OCSP_RESPONSE(NULL, &p, len); if(!rsp) { failf(data, "Invalid OCSP response"); @@ -1867,15 +1914,8 @@ static const char *ssl_msg_type(int ssl_ver, int msg) return "Unknown"; } -static const char *tls_rt_type(int type, const void *buf, size_t buflen) +static const char *tls_rt_type(int type) { - (void)buf; - (void)buflen; -#ifdef SSL3_RT_INNER_CONTENT_TYPE - if(type == SSL3_RT_INNER_CONTENT_TYPE && buf && buflen >= 1) - type = *(unsigned char *)buf; -#endif - switch(type) { #ifdef SSL3_RT_HEADER case SSL3_RT_HEADER: @@ -1945,12 +1985,20 @@ static void ssl_tls_trace(int direction, int ssl_ver, int content_type, case 0: break; default: - snprintf(unknown, sizeof(unknown), "(%x)", ssl_ver); + msnprintf(unknown, sizeof(unknown), "(%x)", ssl_ver); verstr = unknown; break; } - if(ssl_ver) { + /* Log progress for interesting records only (like Handshake or Alert), skip + * all raw record headers (content_type == SSL3_RT_HEADER or ssl_ver == 0). + * For TLS 1.3, skip notification of the decrypted inner Content Type. + */ + if(ssl_ver +#ifdef SSL3_RT_INNER_CONTENT_TYPE + && content_type != SSL3_RT_INNER_CONTENT_TYPE +#endif + ) { const char *msg_name, *tls_rt_name; char ssl_buf[1024]; int msg_type, txt_len; @@ -1964,17 +2012,10 @@ static void ssl_tls_trace(int direction, int ssl_ver, int content_type, * is at 'buf[0]'. */ if(ssl_ver == SSL3_VERSION_MAJOR && content_type) - tls_rt_name = tls_rt_type(content_type, buf, len); + tls_rt_name = tls_rt_type(content_type); else tls_rt_name = ""; -#ifdef SSL3_RT_INNER_CONTENT_TYPE - if(content_type == SSL3_RT_INNER_CONTENT_TYPE) { - msg_type = 0; - msg_name = "[no content]"; - } - else -#endif if(content_type == SSL3_RT_CHANGE_CIPHER_SPEC) { msg_type = *(char *)buf; msg_name = "Change cipher spec"; @@ -1988,9 +2029,9 @@ static void ssl_tls_trace(int direction, int ssl_ver, int content_type, msg_name = ssl_msg_type(ssl_ver, msg_type); } - txt_len = snprintf(ssl_buf, sizeof(ssl_buf), "%s (%s), %s, %s (%d):\n", - verstr, direction?"OUT":"IN", - tls_rt_name, msg_name, msg_type); + txt_len = msnprintf(ssl_buf, sizeof(ssl_buf), "%s (%s), %s, %s (%d):\n", + verstr, direction?"OUT":"IN", + tls_rt_name, msg_name, msg_type); if(0 <= txt_len && (unsigned)txt_len < sizeof(ssl_buf)) { Curl_debug(data, CURLINFO_TEXT, ssl_buf, (size_t)txt_len); } @@ -2137,6 +2178,7 @@ set_ssl_version_min_max(long *ctx_options, struct connectdata *conn, } #else (void)sockindex; + (void)ctx_options; failf(data, OSSL_PACKAGE " was built without TLS 1.3 support"); return CURLE_NOT_BUILT_IN; #endif @@ -2189,6 +2231,62 @@ set_ssl_version_min_max(long *ctx_options, struct connectdata *conn, return CURLE_OK; } +/* The "new session" callback must return zero if the session can be removed + * or non-zero if the session has been put into the session cache. + */ +static int ossl_new_session_cb(SSL *ssl, SSL_SESSION *ssl_sessionid) +{ + int res = 0; + struct connectdata *conn; + struct Curl_easy *data; + int sockindex; + curl_socket_t *sockindex_ptr; + int connectdata_idx = ossl_get_ssl_conn_index(); + int sockindex_idx = ossl_get_ssl_sockindex_index(); + + if(connectdata_idx < 0 || sockindex_idx < 0) + return 0; + + conn = (struct connectdata*) SSL_get_ex_data(ssl, connectdata_idx); + if(!conn) + return 0; + + data = conn->data; + + /* The sockindex has been stored as a pointer to an array element */ + sockindex_ptr = (curl_socket_t*) SSL_get_ex_data(ssl, sockindex_idx); + sockindex = (int)(sockindex_ptr - conn->sock); + + if(SSL_SET_OPTION(primary.sessionid)) { + bool incache; + void *old_ssl_sessionid = NULL; + + Curl_ssl_sessionid_lock(conn); + incache = !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL, + sockindex)); + if(incache) { + if(old_ssl_sessionid != ssl_sessionid) { + infof(data, "old SSL session ID is stale, removing\n"); + Curl_ssl_delsessionid(conn, old_ssl_sessionid); + incache = FALSE; + } + } + + if(!incache) { + if(!Curl_ssl_addsessionid(conn, ssl_sessionid, + 0 /* unknown size */, sockindex)) { + /* the session has been put into the session cache */ + res = 1; + } + else + failf(data, "failed to store ssl session"); + } + Curl_ssl_sessionid_unlock(conn); + } + + return res; +} + static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) { CURLcode result = CURLE_OK; @@ -2585,6 +2683,14 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) } #endif + /* Enable the session cache because it's a prerequisite for the "new session" + * callback. Use the "external storage" mode to avoid that OpenSSL creates + * an internal session cache. + */ + 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); + /* give application a chance to interfere with SSL set up. */ if(data->set.ssl.fsslctx) { result = (*data->set.ssl.fsslctx)(data, BACKEND->ctx, @@ -2610,6 +2716,10 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) 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); +#endif + SSL_set_connect_state(BACKEND->handle); BACKEND->server_cert = 0x0; @@ -2627,6 +2737,15 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) /* Check if there's a cached ID we can/should use here! */ if(SSL_SET_OPTION(primary.sessionid)) { void *ssl_sessionid = NULL; + int connectdata_idx = ossl_get_ssl_conn_index(); + int sockindex_idx = ossl_get_ssl_sockindex_index(); + + 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); + } Curl_ssl_sessionid_lock(conn); if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL, sockindex)) { @@ -2699,6 +2818,12 @@ static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex) connssl->connecting_state = ssl_connect_2_writing; return CURLE_OK; } +#ifdef SSL_ERROR_WANT_ASYNC + if(SSL_ERROR_WANT_ASYNC == detail) { + connssl->connecting_state = ssl_connect_2; + return CURLE_OK; + } +#endif else { /* untreated error */ unsigned long errdetail; @@ -2721,14 +2846,14 @@ static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex) if((lib == ERR_LIB_SSL) && (reason == SSL_R_CERTIFICATE_VERIFY_FAILED)) { - result = CURLE_SSL_CACERT; + result = CURLE_PEER_FAILED_VERIFICATION; lerr = SSL_get_verify_result(BACKEND->handle); if(lerr != X509_V_OK) { *certverifyresult = lerr; - snprintf(error_buffer, sizeof(error_buffer), - "SSL certificate problem: %s", - X509_verify_cert_error_string(lerr)); + msnprintf(error_buffer, sizeof(error_buffer), + "SSL certificate problem: %s", + X509_verify_cert_error_string(lerr)); } else /* strcpy() is fine here as long as the string fits within @@ -2795,6 +2920,9 @@ static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex) } else infof(data, "ALPN, server did not agree to a protocol\n"); + + Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ? + BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE); } #endif @@ -2839,7 +2967,7 @@ static void pubkey_show(struct Curl_easy *data, char *ptr; char namebuf[32]; - snprintf(namebuf, sizeof(namebuf), "%s(%s)", type, name); + msnprintf(namebuf, sizeof(namebuf), "%s(%s)", type, name); if(bn) BN_print(mem, bn); @@ -2900,8 +3028,8 @@ static int X509V3_ext(struct Curl_easy *data, while((j<(size_t)biomem->length) && (biomem->data[j] == ' ')) j++; if(j<(size_t)biomem->length) - ptr += snprintf(ptr, sizeof(buf)-(ptr-buf), "%s%c", sep, - biomem->data[j]); + ptr += msnprintf(ptr, sizeof(buf)-(ptr-buf), "%s%c", sep, + biomem->data[j]); } Curl_ssl_push_certinfo(data, certnum, namebuf, buf); @@ -3101,11 +3229,6 @@ static CURLcode get_cert_chain(struct connectdata *conn, #endif break; } -#if 0 - case EVP_PKEY_EC: /* symbol not present in OpenSSL 0.9.6 */ - /* left TODO */ - break; -#endif } EVP_PKEY_free(pubkey); } @@ -3214,20 +3337,8 @@ static CURLcode servercert(struct connectdata *conn, /* we've been asked to gather certificate info! */ (void)get_cert_chain(conn, connssl); - fp = BIO_new(BIO_s_file()); - if(fp == NULL) { - failf(data, - "BIO_new return NULL, " OSSL_PACKAGE - " error %s", - ossl_strerror(ERR_get_error(), error_buffer, - sizeof(error_buffer)) ); - BIO_free(mem); - return CURLE_OUT_OF_MEMORY; - } - BACKEND->server_cert = SSL_get_peer_certificate(BACKEND->handle); if(!BACKEND->server_cert) { - BIO_free(fp); BIO_free(mem); if(!strict) return CURLE_OK; @@ -3262,7 +3373,6 @@ static CURLcode servercert(struct connectdata *conn, if(SSL_CONN_CONFIG(verifyhost)) { result = verifyhost(conn, BACKEND->server_cert); if(result) { - BIO_free(fp); X509_free(BACKEND->server_cert); BACKEND->server_cert = NULL; return result; @@ -3284,6 +3394,18 @@ static CURLcode servercert(struct connectdata *conn, /* e.g. match issuer name with provided issuer certificate */ if(SSL_SET_OPTION(issuercert)) { + fp = BIO_new(BIO_s_file()); + if(fp == NULL) { + failf(data, + "BIO_new return NULL, " OSSL_PACKAGE + " error %s", + ossl_strerror(ERR_get_error(), error_buffer, + sizeof(error_buffer)) ); + X509_free(BACKEND->server_cert); + BACKEND->server_cert = NULL; + return CURLE_OUT_OF_MEMORY; + } + if(BIO_read_filename(fp, SSL_SET_OPTION(issuercert)) <= 0) { if(strict) failf(data, "SSL: Unable to open issuer cert (%s)", @@ -3319,6 +3441,7 @@ static CURLcode servercert(struct connectdata *conn, infof(data, " SSL certificate issuer check ok (%s)\n", SSL_SET_OPTION(issuercert)); + BIO_free(fp); X509_free(issuer); } @@ -3347,7 +3470,6 @@ static CURLcode servercert(struct connectdata *conn, if(SSL_CONN_CONFIG(verifystatus)) { result = verifystatus(conn, connssl); if(result) { - BIO_free(fp); X509_free(BACKEND->server_cert); BACKEND->server_cert = NULL; return result; @@ -3367,7 +3489,6 @@ static CURLcode servercert(struct connectdata *conn, failf(data, "SSL: public key does not match pinned public key!"); } - BIO_free(fp); X509_free(BACKEND->server_cert); BACKEND->server_cert = NULL; connssl->connecting_state = ssl_connect_done; @@ -3378,52 +3499,10 @@ static CURLcode servercert(struct connectdata *conn, static CURLcode ossl_connect_step3(struct connectdata *conn, int sockindex) { CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; DEBUGASSERT(ssl_connect_3 == connssl->connecting_state); - if(SSL_SET_OPTION(primary.sessionid)) { - bool incache; - SSL_SESSION *our_ssl_sessionid; - void *old_ssl_sessionid = NULL; - - our_ssl_sessionid = SSL_get1_session(BACKEND->handle); - - /* SSL_get1_session() will increment the reference count and the session - will stay in memory until explicitly freed with SSL_SESSION_free(3), - regardless of its state. */ - - Curl_ssl_sessionid_lock(conn); - incache = !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL, - sockindex)); - if(incache) { - if(old_ssl_sessionid != our_ssl_sessionid) { - infof(data, "old SSL session ID is stale, removing\n"); - Curl_ssl_delsessionid(conn, old_ssl_sessionid); - incache = FALSE; - } - } - - if(!incache) { - result = Curl_ssl_addsessionid(conn, our_ssl_sessionid, - 0 /* unknown size */, sockindex); - if(result) { - Curl_ssl_sessionid_unlock(conn); - failf(data, "failed to store ssl session"); - return result; - } - } - else { - /* Session was incache, so refcount already incremented earlier. - * Avoid further increments with each SSL_get1_session() call. - * This does not free the session as refcount remains > 0 - */ - SSL_SESSION_free(our_ssl_sessionid); - } - Curl_ssl_sessionid_unlock(conn); - } - /* * We check certificates to authenticate the server; otherwise we risk * man-in-the-middle attack; NEVERTHELESS, if we're told explicitly not to @@ -3678,7 +3757,10 @@ static ssize_t ossl_recv(struct connectdata *conn, /* connection data */ switch(err) { case SSL_ERROR_NONE: /* this is not an error */ + break; case SSL_ERROR_ZERO_RETURN: /* no more data */ + /* close_notify alert */ + connclose(conn, "TLS close_notify"); break; case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: @@ -3709,8 +3791,13 @@ static ssize_t ossl_recv(struct connectdata *conn, /* connection data */ static size_t Curl_ossl_version(char *buffer, size_t size) { #ifdef OPENSSL_IS_BORINGSSL - return snprintf(buffer, size, OSSL_PACKAGE); -#else /* OPENSSL_IS_BORINGSSL */ + return msnprintf(buffer, size, OSSL_PACKAGE); +#elif defined(HAVE_OPENSSL_VERSION) && defined(OPENSSL_VERSION_STRING) + return msnprintf(buffer, size, "%s/%s", + OSSL_PACKAGE, OpenSSL_version(OPENSSL_VERSION_STRING)); +#else + /* not BoringSSL and not using OpenSSL_version */ + char sub[3]; unsigned long ssleay_value; sub[2]='\0'; @@ -3736,12 +3823,16 @@ static size_t Curl_ossl_version(char *buffer, size_t size) sub[0]='\0'; } - return snprintf(buffer, size, "%s/%lx.%lx.%lx%s", - OSSL_PACKAGE, - (ssleay_value>>28)&0xf, - (ssleay_value>>20)&0xff, - (ssleay_value>>12)&0xff, - sub); + return msnprintf(buffer, size, "%s/%lx.%lx.%lx%s" +#ifdef OPENSSL_FIPS + "-fips" +#endif + , + OSSL_PACKAGE, + (ssleay_value>>28)&0xf, + (ssleay_value>>20)&0xff, + (ssleay_value>>12)&0xff, + sub); #endif /* OPENSSL_IS_BORINGSSL */ } diff --git a/Utilities/cmcurl/lib/vtls/polarssl.c b/Utilities/cmcurl/lib/vtls/polarssl.c index 27af0cc..7ea26b4 100644 --- a/Utilities/cmcurl/lib/vtls/polarssl.c +++ b/Utilities/cmcurl/lib/vtls/polarssl.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2012 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 2012 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 2010 - 2011, Hoi-Ho Chan, <hoiho.chan@gmail.com> * * This software is licensed as described in the file COPYING, which @@ -55,6 +55,7 @@ #include "select.h" #include "strcase.h" #include "polarssl_threadlock.h" +#include "multiif.h" #include "curl_printf.h" #include "curl_memory.h" /* The last #include file should be: */ @@ -497,7 +498,7 @@ polarssl_connect_step2(struct connectdata *conn, if(ret & BADCERT_REVOKED) { failf(data, "Cert verify failed: BADCERT_REVOKED"); - return CURLE_SSL_CACERT; + return CURLE_PEER_FAILED_VERIFICATION; } if(ret & BADCERT_CN_MISMATCH) @@ -593,6 +594,8 @@ polarssl_connect_step2(struct connectdata *conn, } else infof(data, "ALPN, server did not agree to a protocol\n"); + Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ? + BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE); } #endif @@ -716,9 +719,9 @@ static void Curl_polarssl_session_free(void *ptr) static size_t Curl_polarssl_version(char *buffer, size_t size) { unsigned int version = version_get_number(); - return snprintf(buffer, size, "%s/%d.%d.%d", - version >= 0x01030A00?"mbedTLS":"PolarSSL", - version>>24, (version>>16)&0xff, (version>>8)&0xff); + return msnprintf(buffer, size, "%s/%d.%d.%d", + version >= 0x01030A00?"mbedTLS":"PolarSSL", + version>>24, (version>>16)&0xff, (version>>8)&0xff); } static CURLcode @@ -908,9 +911,7 @@ const struct Curl_ssl Curl_ssl_polarssl = { Curl_none_check_cxn, /* check_cxn */ Curl_none_shutdown, /* shutdown */ Curl_polarssl_data_pending, /* data_pending */ - /* This might cause libcurl to use a weeker random! - * TODO: use Polarssl's CTR-DRBG or HMAC-DRBG - */ + /* This might cause libcurl to use a weeker random! */ Curl_none_random, /* random */ Curl_none_cert_status_request, /* cert_status_request */ Curl_polarssl_connect, /* connect */ diff --git a/Utilities/cmcurl/lib/vtls/polarssl_threadlock.c b/Utilities/cmcurl/lib/vtls/polarssl_threadlock.c index dd5fbd7..27c94b1 100644 --- a/Utilities/cmcurl/lib/vtls/polarssl_threadlock.c +++ b/Utilities/cmcurl/lib/vtls/polarssl_threadlock.c @@ -23,16 +23,15 @@ #include "curl_setup.h" #if (defined(USE_POLARSSL) || defined(USE_MBEDTLS)) && \ - (defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32)) - -#if defined(USE_THREADS_POSIX) -# ifdef HAVE_PTHREAD_H -# include <pthread.h> -# endif -#elif defined(USE_THREADS_WIN32) -# ifdef HAVE_PROCESS_H -# include <process.h> -# endif + ((defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H)) || \ + (defined(USE_THREADS_WIN32) && defined(HAVE_PROCESS_H))) + +#if defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H) +# include <pthread.h> +# define POLARSSL_MUTEX_T pthread_mutex_t +#elif defined(USE_THREADS_WIN32) && defined(HAVE_PROCESS_H) +# include <process.h> +# define POLARSSL_MUTEX_T HANDLE #endif #include "polarssl_threadlock.h" @@ -50,25 +49,23 @@ static POLARSSL_MUTEX_T *mutex_buf = NULL; int Curl_polarsslthreadlock_thread_setup(void) { int i; - int ret; mutex_buf = calloc(NUMT * sizeof(POLARSSL_MUTEX_T), 1); if(!mutex_buf) return 0; /* error, no number of threads defined */ -#ifdef HAVE_PTHREAD_H for(i = 0; i < NUMT; i++) { + int ret; +#if defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H) ret = pthread_mutex_init(&mutex_buf[i], NULL); if(ret) return 0; /* pthread_mutex_init failed */ - } -#elif defined(HAVE_PROCESS_H) - for(i = 0; i < NUMT; i++) { +#elif defined(USE_THREADS_WIN32) && defined(HAVE_PROCESS_H) mutex_buf[i] = CreateMutex(0, FALSE, 0); if(mutex_buf[i] == 0) return 0; /* CreateMutex failed */ +#endif /* USE_THREADS_POSIX && HAVE_PTHREAD_H */ } -#endif /* HAVE_PTHREAD_H */ return 1; /* OK */ } @@ -76,24 +73,22 @@ int Curl_polarsslthreadlock_thread_setup(void) int Curl_polarsslthreadlock_thread_cleanup(void) { int i; - int ret; if(!mutex_buf) return 0; /* error, no threads locks defined */ -#ifdef HAVE_PTHREAD_H for(i = 0; i < NUMT; i++) { + int ret; +#if defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H) ret = pthread_mutex_destroy(&mutex_buf[i]); if(ret) return 0; /* pthread_mutex_destroy failed */ - } -#elif defined(HAVE_PROCESS_H) - for(i = 0; i < NUMT; i++) { +#elif defined(USE_THREADS_WIN32) && defined(HAVE_PROCESS_H) ret = CloseHandle(mutex_buf[i]); if(!ret) return 0; /* CloseHandle failed */ +#endif /* USE_THREADS_POSIX && HAVE_PTHREAD_H */ } -#endif /* HAVE_PTHREAD_H */ free(mutex_buf); mutex_buf = NULL; @@ -102,51 +97,47 @@ int Curl_polarsslthreadlock_thread_cleanup(void) int Curl_polarsslthreadlock_lock_function(int n) { - int ret; -#ifdef HAVE_PTHREAD_H if(n < NUMT) { + int ret; +#if defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H) ret = pthread_mutex_lock(&mutex_buf[n]); if(ret) { DEBUGF(fprintf(stderr, "Error: polarsslthreadlock_lock_function failed\n")); return 0; /* pthread_mutex_lock failed */ } - } -#elif defined(HAVE_PROCESS_H) - if(n < NUMT) { +#elif defined(USE_THREADS_WIN32) && defined(HAVE_PROCESS_H) ret = (WaitForSingleObject(mutex_buf[n], INFINITE) == WAIT_FAILED?1:0); if(ret) { DEBUGF(fprintf(stderr, "Error: polarsslthreadlock_lock_function failed\n")); return 0; /* pthread_mutex_lock failed */ } +#endif /* USE_THREADS_POSIX && HAVE_PTHREAD_H */ } -#endif /* HAVE_PTHREAD_H */ return 1; /* OK */ } int Curl_polarsslthreadlock_unlock_function(int n) { - int ret; -#ifdef HAVE_PTHREAD_H if(n < NUMT) { + int ret; +#if defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H) ret = pthread_mutex_unlock(&mutex_buf[n]); if(ret) { DEBUGF(fprintf(stderr, "Error: polarsslthreadlock_unlock_function failed\n")); return 0; /* pthread_mutex_unlock failed */ } - } -#elif defined(HAVE_PROCESS_H) - if(n < NUMT) { +#elif defined(USE_THREADS_WIN32) && defined(HAVE_PROCESS_H) ret = ReleaseMutex(mutex_buf[n]); if(!ret) { DEBUGF(fprintf(stderr, "Error: polarsslthreadlock_unlock_function failed\n")); return 0; /* pthread_mutex_lock failed */ } +#endif /* USE_THREADS_POSIX && HAVE_PTHREAD_H */ } -#endif /* HAVE_PTHREAD_H */ return 1; /* OK */ } diff --git a/Utilities/cmcurl/lib/vtls/polarssl_threadlock.h b/Utilities/cmcurl/lib/vtls/polarssl_threadlock.h index dda5359..1226475 100644 --- a/Utilities/cmcurl/lib/vtls/polarssl_threadlock.h +++ b/Utilities/cmcurl/lib/vtls/polarssl_threadlock.h @@ -26,13 +26,8 @@ #if (defined USE_POLARSSL) || (defined USE_MBEDTLS) -#if defined(USE_THREADS_POSIX) -# define POLARSSL_MUTEX_T pthread_mutex_t -#elif defined(USE_THREADS_WIN32) -# define POLARSSL_MUTEX_T HANDLE -#endif - -#if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32) +#if (defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H)) || \ + (defined(USE_THREADS_WIN32) && defined(HAVE_PROCESS_H)) int Curl_polarsslthreadlock_thread_setup(void); int Curl_polarsslthreadlock_thread_cleanup(void); diff --git a/Utilities/cmcurl/lib/vtls/schannel.c b/Utilities/cmcurl/lib/vtls/schannel.c index e442692..0f6f734 100644 --- a/Utilities/cmcurl/lib/vtls/schannel.c +++ b/Utilities/cmcurl/lib/vtls/schannel.c @@ -7,7 +7,7 @@ * * Copyright (C) 2012 - 2016, Marc Hoersken, <info@marc-hoersken.de> * Copyright (C) 2012, Mark Salisbury, <mark.salisbury@hp.com> - * Copyright (C) 2012 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 2012 - 2019, 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 @@ -23,9 +23,8 @@ ***************************************************************************/ /* - * Source file for all SChannel-specific code for the TLS/SSL layer. No code + * Source file for all Schannel-specific code for the TLS/SSL layer. No code * but vtls.c should ever call or use these functions. - * */ /* @@ -59,6 +58,7 @@ #include "warnless.h" #include "x509asn1.h" #include "curl_printf.h" +#include "multiif.h" #include "system_win32.h" /* The last #include file should be: */ @@ -196,7 +196,7 @@ set_ssl_version_min_max(SCHANNEL_CRED *schannel_cred, struct connectdata *conn) schannel_cred->grbitEnabledProtocols |= SP_PROT_TLS1_2_CLIENT; break; case CURL_SSLVERSION_TLSv1_3: - failf(data, "Schannel: TLS 1.3 is not yet supported"); + failf(data, "schannel: TLS 1.3 is not yet supported"); return CURLE_SSL_CONNECT_ERROR; } } @@ -325,6 +325,9 @@ get_alg_id_by_name(char *name) #ifdef CALG_ECDSA CIPHEROPTION(CALG_ECDSA); #endif +#ifdef CALG_ECDH_EPHEM + CIPHEROPTION(CALG_ECDH_EPHEM); +#endif return 0; } @@ -357,6 +360,7 @@ get_cert_location(TCHAR *path, DWORD *store_name, TCHAR **store_path, TCHAR **thumbprint) { TCHAR *sep; + TCHAR *store_path_start; size_t store_name_len; sep = _tcschr(path, TEXT('\\')); @@ -387,13 +391,17 @@ get_cert_location(TCHAR *path, DWORD *store_name, TCHAR **store_path, else return CURLE_SSL_CERTPROBLEM; - *store_path = sep + 1; + store_path_start = sep + 1; - sep = _tcschr(*store_path, TEXT('\\')); + sep = _tcschr(store_path_start, TEXT('\\')); if(sep == NULL) return CURLE_SSL_CERTPROBLEM; - *sep = 0; + *sep = TEXT('\0'); + *store_path = _tcsdup(store_path_start); + *sep = TEXT('\\'); + if(*store_path == NULL) + return CURLE_OUT_OF_MEMORY; *thumbprint = sep + 1; if(_tcslen(*thumbprint) != CERT_THUMBPRINT_STR_LEN) @@ -429,14 +437,15 @@ schannel_connect_step1(struct connectdata *conn, int sockindex) char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : conn->host.name; - infof(data, "schannel: SSL/TLS connection with %s port %hu (step 1/3)\n", - hostname, conn->remote_port); + DEBUGF(infof(data, + "schannel: SSL/TLS connection with %s port %hu (step 1/3)\n", + hostname, conn->remote_port)); if(Curl_verify_windows_version(5, 1, PLATFORM_WINNT, VERSION_LESS_THAN_EQUAL)) { - /* SChannel in Windows XP (OS version 5.1) uses legacy handshakes and + /* Schannel in Windows XP (OS version 5.1) uses legacy handshakes and algorithms that may not be supported by all servers. */ - infof(data, "schannel: WinSSL version is old and may not be able to " + infof(data, "schannel: Windows version is old and may not be able to " "connect to some servers due to lack of SNI, algorithms, etc.\n"); } @@ -490,12 +499,13 @@ schannel_connect_step1(struct connectdata *conn, int sockindex) Curl_ssl_sessionid_lock(conn); if(!Curl_ssl_getsessionid(conn, (void **)&old_cred, NULL, sockindex)) { BACKEND->cred = old_cred; - infof(data, "schannel: re-using existing credential handle\n"); + DEBUGF(infof(data, "schannel: re-using existing credential handle\n")); /* increment the reference counter of the credential/session handle */ BACKEND->cred->refcount++; - infof(data, "schannel: incremented credential handle refcount = %d\n", - BACKEND->cred->refcount); + DEBUGF(infof(data, + "schannel: incremented credential handle refcount = %d\n", + BACKEND->cred->refcount)); } Curl_ssl_sessionid_unlock(conn); } @@ -513,31 +523,32 @@ schannel_connect_step1(struct connectdata *conn, int sockindex) #endif schannel_cred.dwFlags = SCH_CRED_AUTO_CRED_VALIDATION; - /* TODO s/data->set.ssl.no_revoke/SSL_SET_OPTION(no_revoke)/g */ if(data->set.ssl.no_revoke) { schannel_cred.dwFlags |= SCH_CRED_IGNORE_NO_REVOCATION_CHECK | SCH_CRED_IGNORE_REVOCATION_OFFLINE; - infof(data, "schannel: disabled server certificate revocation " - "checks\n"); + DEBUGF(infof(data, "schannel: disabled server certificate revocation " + "checks\n")); } else { schannel_cred.dwFlags |= SCH_CRED_REVOCATION_CHECK_CHAIN; - infof(data, "schannel: checking server certificate revocation\n"); + DEBUGF(infof(data, + "schannel: checking server certificate revocation\n")); } } else { schannel_cred.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION | SCH_CRED_IGNORE_NO_REVOCATION_CHECK | SCH_CRED_IGNORE_REVOCATION_OFFLINE; - infof(data, "schannel: disabled server certificate revocation checks\n"); + DEBUGF(infof(data, + "schannel: disabled server cert revocation checks\n")); } if(!conn->ssl_config.verifyhost) { schannel_cred.dwFlags |= SCH_CRED_NO_SERVERNAME_CHECK; - infof(data, "schannel: verifyhost setting prevents Schannel from " - "comparing the supplied target name with the subject " - "names in server certificates.\n"); + DEBUGF(infof(data, "schannel: verifyhost setting prevents Schannel from " + "comparing the supplied target name with the subject " + "names in server certificates.\n")); } switch(conn->ssl_config.version) { @@ -609,9 +620,11 @@ schannel_connect_step1(struct connectdata *conn, int sockindex) 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); 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; @@ -674,8 +687,9 @@ schannel_connect_step1(struct connectdata *conn, int sockindex) CertFreeCertificateContext(client_certs[0]); if(sspi_status != SEC_E_OK) { + char buffer[STRERROR_LEN]; failf(data, "schannel: AcquireCredentialsHandle failed: %s", - Curl_sspi_strerror(conn, sspi_status)); + Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); Curl_safefree(BACKEND->cred); switch(sspi_status) { case SEC_E_INSUFFICIENT_MEMORY: @@ -790,15 +804,16 @@ schannel_connect_step1(struct connectdata *conn, int sockindex) Curl_unicodefree(host_name); if(sspi_status != SEC_I_CONTINUE_NEEDED) { + char buffer[STRERROR_LEN]; Curl_safefree(BACKEND->ctxt); switch(sspi_status) { case SEC_E_INSUFFICIENT_MEMORY: failf(data, "schannel: initial InitializeSecurityContext failed: %s", - Curl_sspi_strerror(conn, sspi_status)); + Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); return CURLE_OUT_OF_MEMORY; case SEC_E_WRONG_PRINCIPAL: failf(data, "schannel: SNI or certificate check failed: %s", - Curl_sspi_strerror(conn, sspi_status)); + Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); return CURLE_PEER_FAILED_VERIFICATION; /* case SEC_E_INVALID_HANDLE: @@ -813,13 +828,13 @@ schannel_connect_step1(struct connectdata *conn, int sockindex) */ default: failf(data, "schannel: initial InitializeSecurityContext failed: %s", - Curl_sspi_strerror(conn, sspi_status)); + Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); return CURLE_SSL_CONNECT_ERROR; } } - infof(data, "schannel: sending initial handshake data: " - "sending %lu bytes...\n", outbuf.cbBuffer); + DEBUGF(infof(data, "schannel: sending initial handshake data: " + "sending %lu bytes...\n", outbuf.cbBuffer)); /* send initial handshake data which is now stored in output buffer */ result = Curl_write_plain(conn, conn->sock[sockindex], outbuf.pvBuffer, @@ -831,8 +846,8 @@ schannel_connect_step1(struct connectdata *conn, int sockindex) return CURLE_SSL_CONNECT_ERROR; } - infof(data, "schannel: sent initial handshake data: " - "sent %zd bytes\n", written); + DEBUGF(infof(data, "schannel: sent initial handshake data: " + "sent %zd bytes\n", written)); BACKEND->recv_unrecoverable_err = CURLE_OK; BACKEND->recv_sspi_close_notify = false; @@ -853,13 +868,11 @@ schannel_connect_step2(struct connectdata *conn, int sockindex) struct Curl_easy *data = conn->data; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; unsigned char *reallocated_buffer; - size_t reallocated_length; SecBuffer outbuf[3]; SecBufferDesc outbuf_desc; SecBuffer inbuf[2]; SecBufferDesc inbuf_desc; SECURITY_STATUS sspi_status = SEC_E_OK; - TCHAR *host_name; CURLcode result; bool doread; char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : @@ -868,8 +881,9 @@ schannel_connect_step2(struct connectdata *conn, int sockindex) doread = (connssl->connecting_state != ssl_connect_2_writing) ? TRUE : FALSE; - infof(data, "schannel: SSL/TLS connection with %s port %hu (step 2/3)\n", - hostname, conn->remote_port); + DEBUGF(infof(data, + "schannel: SSL/TLS connection with %s port %hu (step 2/3)\n", + hostname, conn->remote_port)); if(!BACKEND->cred || !BACKEND->ctxt) return CURLE_SSL_CONNECT_ERROR; @@ -901,7 +915,7 @@ schannel_connect_step2(struct connectdata *conn, int sockindex) if(BACKEND->encdata_length - BACKEND->encdata_offset < CURL_SCHANNEL_BUFFER_FREE_SIZE) { /* increase internal encrypted data buffer */ - reallocated_length = BACKEND->encdata_offset + + size_t reallocated_length = BACKEND->encdata_offset + CURL_SCHANNEL_BUFFER_FREE_SIZE; reallocated_buffer = realloc(BACKEND->encdata_buffer, reallocated_length); @@ -917,6 +931,7 @@ schannel_connect_step2(struct connectdata *conn, int sockindex) } for(;;) { + TCHAR *host_name; if(doread) { /* read encrypted handshake data from socket */ result = Curl_read_plain(conn->sock[sockindex], @@ -928,8 +943,8 @@ schannel_connect_step2(struct connectdata *conn, int sockindex) if(result == CURLE_AGAIN) { if(connssl->connecting_state != ssl_connect_2_writing) connssl->connecting_state = ssl_connect_2_reading; - infof(data, "schannel: failed to receive handshake, " - "need more data\n"); + DEBUGF(infof(data, "schannel: failed to receive handshake, " + "need more data\n")); return CURLE_OK; } else if((result != CURLE_OK) || (nread == 0)) { @@ -941,11 +956,12 @@ schannel_connect_step2(struct connectdata *conn, int sockindex) /* increase encrypted data buffer offset */ BACKEND->encdata_offset += nread; BACKEND->encdata_is_incomplete = false; - infof(data, "schannel: encrypted data got %zd\n", nread); + DEBUGF(infof(data, "schannel: encrypted data got %zd\n", nread)); } - infof(data, "schannel: encrypted data buffer: offset %zu length %zu\n", - BACKEND->encdata_offset, BACKEND->encdata_length); + DEBUGF(infof(data, + "schannel: encrypted data buffer: offset %zu length %zu\n", + BACKEND->encdata_offset, BACKEND->encdata_length)); /* setup input buffers */ InitSecBuffer(&inbuf[0], SECBUFFER_TOKEN, malloc(BACKEND->encdata_offset), @@ -988,7 +1004,8 @@ schannel_connect_step2(struct connectdata *conn, int sockindex) if(sspi_status == SEC_E_INCOMPLETE_MESSAGE) { BACKEND->encdata_is_incomplete = true; connssl->connecting_state = ssl_connect_2_reading; - infof(data, "schannel: received incomplete message, need more data\n"); + DEBUGF(infof(data, + "schannel: received incomplete message, need more data\n")); return CURLE_OK; } @@ -999,7 +1016,8 @@ schannel_connect_step2(struct connectdata *conn, int sockindex) !(BACKEND->req_flags & ISC_REQ_USE_SUPPLIED_CREDS)) { BACKEND->req_flags |= ISC_REQ_USE_SUPPLIED_CREDS; connssl->connecting_state = ssl_connect_2_writing; - infof(data, "schannel: a client certificate has been requested\n"); + DEBUGF(infof(data, + "schannel: a client certificate has been requested\n")); return CURLE_OK; } @@ -1008,8 +1026,8 @@ schannel_connect_step2(struct connectdata *conn, int sockindex) for(i = 0; i < 3; i++) { /* search for handshake tokens that need to be send */ if(outbuf[i].BufferType == SECBUFFER_TOKEN && outbuf[i].cbBuffer > 0) { - infof(data, "schannel: sending next handshake data: " - "sending %lu bytes...\n", outbuf[i].cbBuffer); + DEBUGF(infof(data, "schannel: sending next handshake data: " + "sending %lu bytes...\n", outbuf[i].cbBuffer)); /* send handshake token to server */ result = Curl_write_plain(conn, conn->sock[sockindex], @@ -1030,14 +1048,15 @@ schannel_connect_step2(struct connectdata *conn, int sockindex) } } else { + char buffer[STRERROR_LEN]; switch(sspi_status) { case SEC_E_INSUFFICIENT_MEMORY: failf(data, "schannel: next InitializeSecurityContext failed: %s", - Curl_sspi_strerror(conn, sspi_status)); + Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); return CURLE_OUT_OF_MEMORY; case SEC_E_WRONG_PRINCIPAL: failf(data, "schannel: SNI or certificate check failed: %s", - Curl_sspi_strerror(conn, sspi_status)); + Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); return CURLE_PEER_FAILED_VERIFICATION; /* case SEC_E_INVALID_HANDLE: @@ -1052,14 +1071,15 @@ schannel_connect_step2(struct connectdata *conn, int sockindex) */ default: failf(data, "schannel: next InitializeSecurityContext failed: %s", - Curl_sspi_strerror(conn, sspi_status)); + Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); return CURLE_SSL_CONNECT_ERROR; } } /* check if there was additional remaining encrypted data */ if(inbuf[1].BufferType == SECBUFFER_EXTRA && inbuf[1].cbBuffer > 0) { - infof(data, "schannel: encrypted data length: %lu\n", inbuf[1].cbBuffer); + DEBUGF(infof(data, "schannel: encrypted data length: %lu\n", + inbuf[1].cbBuffer)); /* There are two cases where we could be getting extra data here: 1) If we're renegotiating a connection and the handshake is already @@ -1098,7 +1118,7 @@ schannel_connect_step2(struct connectdata *conn, int sockindex) /* check if the handshake is complete */ if(sspi_status == SEC_E_OK) { connssl->connecting_state = ssl_connect_3; - infof(data, "schannel: SSL/TLS handshake complete\n"); + DEBUGF(infof(data, "schannel: SSL/TLS handshake complete\n")); } pubkey_ptr = SSL_IS_PROXY() ? @@ -1114,13 +1134,68 @@ schannel_connect_step2(struct connectdata *conn, int sockindex) #ifdef HAS_MANUAL_VERIFY_API if(conn->ssl_config.verifypeer && BACKEND->use_manual_cred_validation) { - return verify_certificate(conn, sockindex); + return Curl_verify_certificate(conn, sockindex); } #endif return CURLE_OK; } +static bool +valid_cert_encoding(const CERT_CONTEXT *cert_context) +{ + return (cert_context != NULL) && + ((cert_context->dwCertEncodingType & X509_ASN_ENCODING) != 0) && + (cert_context->pbCertEncoded != NULL) && + (cert_context->cbCertEncoded > 0); +} + +typedef bool(*Read_crt_func)(const CERT_CONTEXT *ccert_context, void *arg); + +static void +traverse_cert_store(const CERT_CONTEXT *context, Read_crt_func func, + void *arg) +{ + const CERT_CONTEXT *current_context = NULL; + bool should_continue = true; + while(should_continue && + (current_context = CertEnumCertificatesInStore( + context->hCertStore, + current_context)) != NULL) + should_continue = func(current_context, arg); + + if(current_context) + CertFreeCertificateContext(current_context); +} + +static bool +cert_counter_callback(const CERT_CONTEXT *ccert_context, void *certs_count) +{ + if(valid_cert_encoding(ccert_context)) + (*(int *)certs_count)++; + return true; +} + +struct Adder_args +{ + struct connectdata *conn; + CURLcode result; + int idx; +}; + +static bool +add_cert_to_certinfo(const CERT_CONTEXT *ccert_context, void *raw_arg) +{ + struct Adder_args *args = (struct Adder_args*)raw_arg; + args->result = CURLE_OK; + if(valid_cert_encoding(ccert_context)) { + const char *beg = (const char *) ccert_context->pbCertEncoded; + const char *end = beg + ccert_context->cbCertEncoded; + args->result = Curl_extract_certinfo(args->conn, (args->idx)++, beg, end); + } + return args->result == CURLE_OK; +} + static CURLcode schannel_connect_step3(struct connectdata *conn, int sockindex) { @@ -1129,7 +1204,7 @@ schannel_connect_step3(struct connectdata *conn, int sockindex) struct ssl_connect_data *connssl = &conn->ssl[sockindex]; SECURITY_STATUS sspi_status = SEC_E_OK; CERT_CONTEXT *ccert_context = NULL; -#ifndef CURL_DISABLE_VERBOSE_STRINGS +#ifdef DEBUGBUILD const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : conn->host.name; #endif @@ -1139,8 +1214,9 @@ schannel_connect_step3(struct connectdata *conn, int sockindex) DEBUGASSERT(ssl_connect_3 == connssl->connecting_state); - infof(data, "schannel: SSL/TLS connection with %s port %hu (step 3/3)\n", - hostname, conn->remote_port); + DEBUGF(infof(data, + "schannel: SSL/TLS connection with %s port %hu (step 3/3)\n", + hostname, conn->remote_port)); if(!BACKEND->cred) return CURLE_SSL_CONNECT_ERROR; @@ -1192,6 +1268,8 @@ schannel_connect_step3(struct connectdata *conn, int sockindex) } else infof(data, "ALPN, server did not agree to a protocol\n"); + Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ? + BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE); } #endif @@ -1205,7 +1283,8 @@ schannel_connect_step3(struct connectdata *conn, int sockindex) sockindex)); if(incache) { if(old_cred != BACKEND->cred) { - infof(data, "schannel: old credential handle is stale, removing\n"); + DEBUGF(infof(data, + "schannel: old credential handle is stale, removing\n")); /* we're not taking old_cred ownership here, no refcount++ is needed */ Curl_ssl_delsessionid(conn, (void *)old_cred); incache = FALSE; @@ -1223,13 +1302,15 @@ schannel_connect_step3(struct connectdata *conn, int sockindex) else { /* this cred session is now also referenced by sessionid cache */ BACKEND->cred->refcount++; - infof(data, "schannel: stored credential handle in session cache\n"); + DEBUGF(infof(data, + "schannel: stored credential handle in session cache\n")); } } Curl_ssl_sessionid_unlock(conn); } if(data->set.ssl.certinfo) { + int certs_count = 0; sspi_status = s_pSecFn->QueryContextAttributes(&BACKEND->ctxt->ctxt_handle, SECPKG_ATTR_REMOTE_CERT_CONTEXT, &ccert_context); @@ -1238,15 +1319,15 @@ schannel_connect_step3(struct connectdata *conn, int sockindex) return CURLE_PEER_FAILED_VERIFICATION; } - result = Curl_ssl_init_certinfo(data, 1); - if(!result) { - if(((ccert_context->dwCertEncodingType & X509_ASN_ENCODING) != 0) && - (ccert_context->cbCertEncoded > 0)) { + traverse_cert_store(ccert_context, cert_counter_callback, &certs_count); - const char *beg = (const char *) ccert_context->pbCertEncoded; - const char *end = beg + ccert_context->cbCertEncoded; - result = Curl_extract_certinfo(conn, 0, beg, end); - } + result = Curl_ssl_init_certinfo(data, certs_count); + if(!result) { + struct Adder_args args; + args.conn = conn; + args.idx = 0; + traverse_cert_store(ccert_context, add_cert_to_certinfo, &args); + result = args.result; } CertFreeCertificateContext(ccert_context); if(result) @@ -1359,6 +1440,16 @@ schannel_connect_common(struct connectdata *conn, int sockindex, connssl->state = ssl_connection_complete; conn->recv[sockindex] = schannel_recv; conn->send[sockindex] = schannel_send; + +#ifdef SECPKG_ATTR_ENDPOINT_BINDINGS + /* When SSPI is used in combination with Schannel + * we need the Schannel context to create the Schannel + * binding to pass the IIS extended protection checks. + * Available on Windows 7 or later. + */ + conn->sslContext = &BACKEND->ctxt->ctxt_handle; +#endif + *done = TRUE; } else @@ -1543,7 +1634,7 @@ schannel_recv(struct connectdata *conn, int sockindex, * handled in the cleanup. */ - infof(data, "schannel: client wants to read %zu bytes\n", len); + DEBUGF(infof(data, "schannel: client wants to read %zu bytes\n", len)); *err = CURLE_OK; if(len && len <= BACKEND->decdata_offset) { @@ -1588,12 +1679,13 @@ schannel_recv(struct connectdata *conn, int sockindex, BACKEND->encdata_buffer = reallocated_buffer; BACKEND->encdata_length = reallocated_length; size = BACKEND->encdata_length - BACKEND->encdata_offset; - infof(data, "schannel: encdata_buffer resized %zu\n", - BACKEND->encdata_length); + DEBUGF(infof(data, "schannel: encdata_buffer resized %zu\n", + BACKEND->encdata_length)); } - infof(data, "schannel: encrypted data buffer: offset %zu length %zu\n", - BACKEND->encdata_offset, BACKEND->encdata_length); + DEBUGF(infof(data, + "schannel: encrypted data buffer: offset %zu length %zu\n", + BACKEND->encdata_offset, BACKEND->encdata_length)); /* read encrypted data from socket */ *err = Curl_read_plain(conn->sock[sockindex], @@ -1603,7 +1695,8 @@ schannel_recv(struct connectdata *conn, int sockindex, if(*err) { nread = -1; if(*err == CURLE_AGAIN) - infof(data, "schannel: Curl_read_plain returned CURLE_AGAIN\n"); + DEBUGF(infof(data, + "schannel: Curl_read_plain returned CURLE_AGAIN\n")); else if(*err == CURLE_RECV_ERROR) infof(data, "schannel: Curl_read_plain returned CURLE_RECV_ERROR\n"); else @@ -1611,17 +1704,18 @@ schannel_recv(struct connectdata *conn, int sockindex, } else if(nread == 0) { BACKEND->recv_connection_closed = true; - infof(data, "schannel: server closed the connection\n"); + DEBUGF(infof(data, "schannel: server closed the connection\n")); } else if(nread > 0) { BACKEND->encdata_offset += (size_t)nread; BACKEND->encdata_is_incomplete = false; - infof(data, "schannel: encrypted data got %zd\n", nread); + DEBUGF(infof(data, "schannel: encrypted data got %zd\n", nread)); } } - infof(data, "schannel: encrypted data buffer: offset %zu length %zu\n", - BACKEND->encdata_offset, BACKEND->encdata_length); + DEBUGF(infof(data, + "schannel: encrypted data buffer: offset %zu length %zu\n", + BACKEND->encdata_offset, BACKEND->encdata_length)); /* decrypt loop */ while(BACKEND->encdata_offset > 0 && sspi_status == SEC_E_OK && @@ -1649,8 +1743,8 @@ schannel_recv(struct connectdata *conn, int sockindex, /* check for successfully decrypted data, even before actual renegotiation or shutdown of the connection context */ if(inbuf[1].BufferType == SECBUFFER_DATA) { - infof(data, "schannel: decrypted data length: %lu\n", - inbuf[1].cbBuffer); + DEBUGF(infof(data, "schannel: decrypted data length: %lu\n", + inbuf[1].cbBuffer)); /* increase buffer in order to fit the received amount of data */ size = inbuf[1].cbBuffer > CURL_SCHANNEL_BUFFER_FREE_SIZE ? @@ -1682,15 +1776,16 @@ schannel_recv(struct connectdata *conn, int sockindex, BACKEND->decdata_offset += size; } - infof(data, "schannel: decrypted data added: %zu\n", size); - infof(data, "schannel: decrypted data cached: offset %zu length %zu\n", - BACKEND->decdata_offset, BACKEND->decdata_length); + DEBUGF(infof(data, "schannel: decrypted data added: %zu\n", size)); + DEBUGF(infof(data, + "schannel: decrypted cached: offset %zu length %zu\n", + BACKEND->decdata_offset, BACKEND->decdata_length)); } /* check for remaining encrypted data */ if(inbuf[3].BufferType == SECBUFFER_EXTRA && inbuf[3].cbBuffer > 0) { - infof(data, "schannel: encrypted data length: %lu\n", - inbuf[3].cbBuffer); + DEBUGF(infof(data, "schannel: encrypted data length: %lu\n", + inbuf[3].cbBuffer)); /* check if the remaining data is less than the total amount * and therefore begins after the already processed data @@ -1704,8 +1799,9 @@ schannel_recv(struct connectdata *conn, int sockindex, BACKEND->encdata_offset = inbuf[3].cbBuffer; } - infof(data, "schannel: encrypted data cached: offset %zu length %zu\n", - BACKEND->encdata_offset, BACKEND->encdata_length); + DEBUGF(infof(data, + "schannel: encrypted cached: offset %zu length %zu\n", + BACKEND->encdata_offset, BACKEND->encdata_length)); } else { /* reset encrypted buffer offset, because there is no data remaining */ @@ -1759,22 +1855,25 @@ schannel_recv(struct connectdata *conn, int sockindex, goto cleanup; } else { + char buffer[STRERROR_LEN]; *err = CURLE_RECV_ERROR; infof(data, "schannel: failed to read data from server: %s\n", - Curl_sspi_strerror(conn, sspi_status)); + Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); goto cleanup; } } - infof(data, "schannel: encrypted data buffer: offset %zu length %zu\n", - BACKEND->encdata_offset, BACKEND->encdata_length); + DEBUGF(infof(data, + "schannel: encrypted data buffer: offset %zu length %zu\n", + BACKEND->encdata_offset, BACKEND->encdata_length)); - infof(data, "schannel: decrypted data buffer: offset %zu length %zu\n", - BACKEND->decdata_offset, BACKEND->decdata_length); + DEBUGF(infof(data, + "schannel: decrypted data buffer: offset %zu length %zu\n", + BACKEND->decdata_offset, BACKEND->decdata_length)); cleanup: /* Warning- there is no guarantee the encdata state is valid at this point */ - infof(data, "schannel: schannel_recv cleanup\n"); + DEBUGF(infof(data, "schannel: schannel_recv cleanup\n")); /* Error if the connection has closed without a close_notify. Behavior here is a matter of debate. We don't want to be vulnerable to a @@ -1807,10 +1906,10 @@ cleanup: memmove(BACKEND->decdata_buffer, BACKEND->decdata_buffer + size, BACKEND->decdata_offset - size); BACKEND->decdata_offset -= size; - - infof(data, "schannel: decrypted data returned %zu\n", size); - infof(data, "schannel: decrypted data buffer: offset %zu length %zu\n", - BACKEND->decdata_offset, BACKEND->decdata_length); + DEBUGF(infof(data, "schannel: decrypted data returned %zu\n", size)); + DEBUGF(infof(data, + "schannel: decrypted data buffer: offset %zu length %zu\n", + BACKEND->decdata_offset, BACKEND->decdata_length)); *err = CURLE_OK; return (ssize_t)size; } @@ -1888,6 +1987,8 @@ static int Curl_schannel_shutdown(struct connectdata *conn, int sockindex) char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : conn->host.name; + DEBUGASSERT(data); + infof(data, "schannel: shutting down SSL/TLS connection with %s port %hu\n", hostname, conn->remote_port); @@ -1907,9 +2008,11 @@ static int Curl_schannel_shutdown(struct connectdata *conn, int sockindex) sspi_status = s_pSecFn->ApplyControlToken(&BACKEND->ctxt->ctxt_handle, &BuffDesc); - if(sspi_status != SEC_E_OK) + if(sspi_status != SEC_E_OK) { + char buffer[STRERROR_LEN]; failf(data, "schannel: ApplyControlToken failure: %s", - Curl_sspi_strerror(conn, sspi_status)); + Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); + } host_name = Curl_convert_UTF8_to_tchar(hostname); if(!host_name) @@ -1951,13 +2054,18 @@ static int Curl_schannel_shutdown(struct connectdata *conn, int sockindex) /* free SSPI Schannel API security context handle */ if(BACKEND->ctxt) { - infof(data, "schannel: clear security context handle\n"); + DEBUGF(infof(data, "schannel: clear security context handle\n")); s_pSecFn->DeleteSecurityContext(&BACKEND->ctxt->ctxt_handle); Curl_safefree(BACKEND->ctxt); } /* free SSPI Schannel API credential handle */ if(BACKEND->cred) { + /* + * When this function is called from Curl_schannel_close() the connection + * might not have an associated transfer so the check for conn->data is + * necessary. + */ Curl_ssl_sessionid_lock(conn); Curl_schannel_session_free(BACKEND->cred); Curl_ssl_sessionid_unlock(conn); @@ -1994,7 +2102,7 @@ static void Curl_schannel_cleanup(void) static size_t Curl_schannel_version(char *buffer, size_t size) { - size = snprintf(buffer, size, "WinSSL"); + size = msnprintf(buffer, size, "Schannel"); return size; } @@ -2022,14 +2130,9 @@ static CURLcode Curl_schannel_random(struct Curl_easy *data UNUSED_PARAM, static CURLcode pkp_pin_peer_pubkey(struct connectdata *conn, int sockindex, const char *pinnedpubkey) { - SECURITY_STATUS status; struct Curl_easy *data = conn->data; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; CERT_CONTEXT *pCertContextServer = NULL; - const char *x509_der; - DWORD x509_der_len; - curl_X509certificate x509_parsed; - curl_asn1Element *pubkey; /* Result is returned to caller */ CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH; @@ -2039,13 +2142,21 @@ static CURLcode pkp_pin_peer_pubkey(struct connectdata *conn, int sockindex, return CURLE_OK; do { - status = s_pSecFn->QueryContextAttributes(&BACKEND->ctxt->ctxt_handle, - SECPKG_ATTR_REMOTE_CERT_CONTEXT, - &pCertContextServer); + SECURITY_STATUS sspi_status; + const char *x509_der; + DWORD x509_der_len; + curl_X509certificate x509_parsed; + curl_asn1Element *pubkey; - if((status != SEC_E_OK) || (pCertContextServer == NULL)) { + sspi_status = + s_pSecFn->QueryContextAttributes(&BACKEND->ctxt->ctxt_handle, + SECPKG_ATTR_REMOTE_CERT_CONTEXT, + &pCertContextServer); + + if((sspi_status != SEC_E_OK) || (pCertContextServer == NULL)) { + char buffer[STRERROR_LEN]; failf(data, "schannel: Failed to read remote certificate context: %s", - Curl_sspi_strerror(conn, status)); + Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); break; /* failed */ } @@ -2082,11 +2193,11 @@ static CURLcode pkp_pin_peer_pubkey(struct connectdata *conn, int sockindex, } static void Curl_schannel_checksum(const unsigned char *input, - size_t inputlen, - unsigned char *checksum, - size_t checksumlen, - DWORD provType, - const unsigned int algId) + size_t inputlen, + unsigned char *checksum, + size_t checksumlen, + DWORD provType, + const unsigned int algId) { HCRYPTPROV hProv = 0; HCRYPTHASH hHash = 0; @@ -2136,9 +2247,9 @@ static CURLcode Curl_schannel_md5sum(unsigned char *input, unsigned char *md5sum, size_t md5len) { - Curl_schannel_checksum(input, inputlen, md5sum, md5len, - PROV_RSA_FULL, CALG_MD5); - return CURLE_OK; + Curl_schannel_checksum(input, inputlen, md5sum, md5len, + PROV_RSA_FULL, CALG_MD5); + return CURLE_OK; } static CURLcode Curl_schannel_sha256sum(const unsigned char *input, @@ -2146,9 +2257,9 @@ static CURLcode Curl_schannel_sha256sum(const unsigned char *input, unsigned char *sha256sum, size_t sha256len) { - Curl_schannel_checksum(input, inputlen, sha256sum, sha256len, - PROV_RSA_AES, CALG_SHA_256); - return CURLE_OK; + Curl_schannel_checksum(input, inputlen, sha256sum, sha256len, + PROV_RSA_AES, CALG_SHA_256); + return CURLE_OK; } static void *Curl_schannel_get_internals(struct ssl_connect_data *connssl, diff --git a/Utilities/cmcurl/lib/vtls/schannel.h b/Utilities/cmcurl/lib/vtls/schannel.h index e491bd4..ee8d7d4 100644 --- a/Utilities/cmcurl/lib/vtls/schannel.h +++ b/Utilities/cmcurl/lib/vtls/schannel.h @@ -8,7 +8,7 @@ * \___|\___/|_| \_\_____| * * Copyright (C) 2012, Marc Hoersken, <info@marc-hoersken.de>, et al. - * Copyright (C) 2012 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 2012 - 2018, 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 @@ -53,7 +53,7 @@ extern const struct Curl_ssl Curl_ssl_schannel; -CURLcode verify_certificate(struct connectdata *conn, int sockindex); +CURLcode Curl_verify_certificate(struct connectdata *conn, int sockindex); /* structs to expose only in schannel.c and schannel_verify.c */ #ifdef EXPOSE_SCHANNEL_INTERNAL_STRUCTS diff --git a/Utilities/cmcurl/lib/vtls/schannel_verify.c b/Utilities/cmcurl/lib/vtls/schannel_verify.c index 2516f56..5a09e96 100644 --- a/Utilities/cmcurl/lib/vtls/schannel_verify.c +++ b/Utilities/cmcurl/lib/vtls/schannel_verify.c @@ -7,7 +7,7 @@ * * Copyright (C) 2012 - 2016, Marc Hoersken, <info@marc-hoersken.de> * Copyright (C) 2012, Mark Salisbury, <mark.salisbury@hp.com> - * Copyright (C) 2012 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 2012 - 2019, 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 @@ -23,7 +23,7 @@ ***************************************************************************/ /* - * Source file for SChannel-specific certificate verification. This code should + * Source file for Schannel-specific certificate verification. This code should * only be invoked by code in schannel.c. */ @@ -87,18 +87,19 @@ static CURLcode add_certs_to_store(HCERTSTORE trust_store, LARGE_INTEGER file_size; char *ca_file_buffer = NULL; char *current_ca_file_ptr = NULL; - const TCHAR *ca_file_tstr = NULL; + TCHAR *ca_file_tstr = NULL; size_t ca_file_bufsize = 0; DWORD total_bytes_read = 0; bool more_certs = 0; int num_certs = 0; size_t END_CERT_LEN; - ca_file_tstr = Curl_convert_UTF8_to_tchar(ca_file); + ca_file_tstr = Curl_convert_UTF8_to_tchar((char *)ca_file); if(!ca_file_tstr) { + char buffer[STRERROR_LEN]; failf(data, "schannel: invalid path name for CA file '%s': %s", - ca_file, Curl_strerror(conn, GetLastError())); + ca_file, Curl_strerror(GetLastError(), buffer, sizeof(buffer))); result = CURLE_SSL_CACERT_BADFILE; goto cleanup; } @@ -116,17 +117,19 @@ static CURLcode add_certs_to_store(HCERTSTORE trust_store, FILE_ATTRIBUTE_NORMAL, NULL); if(ca_file_handle == INVALID_HANDLE_VALUE) { + char buffer[STRERROR_LEN]; failf(data, "schannel: failed to open CA file '%s': %s", - ca_file, Curl_strerror(conn, GetLastError())); + ca_file, Curl_strerror(GetLastError(), buffer, sizeof(buffer))); result = CURLE_SSL_CACERT_BADFILE; goto cleanup; } if(!GetFileSizeEx(ca_file_handle, &file_size)) { + char buffer[STRERROR_LEN]; failf(data, "schannel: failed to determine size of CA file '%s': %s", - ca_file, Curl_strerror(conn, GetLastError())); + ca_file, Curl_strerror(GetLastError(), buffer, sizeof(buffer))); result = CURLE_SSL_CACERT_BADFILE; goto cleanup; } @@ -153,10 +156,10 @@ static CURLcode add_certs_to_store(HCERTSTORE trust_store, if(!ReadFile(ca_file_handle, ca_file_buffer + total_bytes_read, bytes_to_read, &bytes_read, NULL)) { - + char buffer[STRERROR_LEN]; failf(data, "schannel: failed to read from CA file '%s': %s", - ca_file, Curl_strerror(conn, GetLastError())); + ca_file, Curl_strerror(GetLastError(), buffer, sizeof(buffer))); result = CURLE_SSL_CACERT_BADFILE; goto cleanup; } @@ -215,11 +218,12 @@ static CURLcode add_certs_to_store(HCERTSTORE trust_store, NULL, NULL, (const void **)&cert_context)) { - + char buffer[STRERROR_LEN]; failf(data, "schannel: failed to extract certificate from CA file " "'%s': %s", - ca_file, Curl_strerror(conn, GetLastError())); + ca_file, + Curl_strerror(GetLastError(), buffer, sizeof(buffer))); result = CURLE_SSL_CACERT_BADFILE; more_certs = 0; } @@ -243,10 +247,12 @@ static CURLcode add_certs_to_store(HCERTSTORE trust_store, NULL); CertFreeCertificateContext(cert_context); if(!add_cert_result) { + char buffer[STRERROR_LEN]; failf(data, "schannel: failed to add certificate from CA file '%s' " "to certificate store: %s", - ca_file, Curl_strerror(conn, GetLastError())); + ca_file, + Curl_strerror(GetLastError(), buffer, sizeof(buffer))); result = CURLE_SSL_CACERT_BADFILE; more_certs = 0; } @@ -406,9 +412,9 @@ cleanup: return result; } -CURLcode verify_certificate(struct connectdata *conn, int sockindex) +CURLcode Curl_verify_certificate(struct connectdata *conn, int sockindex) { - SECURITY_STATUS status; + SECURITY_STATUS sspi_status; struct Curl_easy *data = conn->data; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; CURLcode result = CURLE_OK; @@ -420,13 +426,15 @@ CURLcode verify_certificate(struct connectdata *conn, int sockindex) conn->http_proxy.host.name : conn->host.name; - status = s_pSecFn->QueryContextAttributes(&BACKEND->ctxt->ctxt_handle, - SECPKG_ATTR_REMOTE_CERT_CONTEXT, - &pCertContextServer); + sspi_status = + s_pSecFn->QueryContextAttributes(&BACKEND->ctxt->ctxt_handle, + SECPKG_ATTR_REMOTE_CERT_CONTEXT, + &pCertContextServer); - if((status != SEC_E_OK) || (pCertContextServer == NULL)) { + if((sspi_status != SEC_E_OK) || (pCertContextServer == NULL)) { + char buffer[STRERROR_LEN]; failf(data, "schannel: Failed to read remote certificate context: %s", - Curl_sspi_strerror(conn, status)); + Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); result = CURLE_PEER_FAILED_VERIFICATION; } @@ -450,8 +458,9 @@ CURLcode verify_certificate(struct connectdata *conn, int sockindex) CERT_STORE_CREATE_NEW_FLAG, NULL); if(!trust_store) { + char buffer[STRERROR_LEN]; failf(data, "schannel: failed to create certificate store: %s", - Curl_strerror(conn, GetLastError())); + Curl_strerror(GetLastError(), buffer, sizeof(buffer))); result = CURLE_SSL_CACERT_BADFILE; } else { @@ -477,9 +486,10 @@ CURLcode verify_certificate(struct connectdata *conn, int sockindex) CertCreateCertificateChainEngine( (CERT_CHAIN_ENGINE_CONFIG *)&engine_config, &cert_chain_engine); if(!create_engine_result) { + char buffer[STRERROR_LEN]; failf(data, "schannel: failed to create certificate chain engine: %s", - Curl_strerror(conn, GetLastError())); + Curl_strerror(GetLastError(), buffer, sizeof(buffer))); result = CURLE_SSL_CACERT_BADFILE; } } @@ -500,8 +510,9 @@ CURLcode verify_certificate(struct connectdata *conn, int sockindex) CERT_CHAIN_REVOCATION_CHECK_CHAIN), NULL, &pChainContext)) { + char buffer[STRERROR_LEN]; failf(data, "schannel: CertGetCertificateChain failed: %s", - Curl_sspi_strerror(conn, GetLastError())); + Curl_strerror(GetLastError(), buffer, sizeof(buffer))); pChainContext = NULL; result = CURLE_PEER_FAILED_VERIFICATION; } diff --git a/Utilities/cmcurl/lib/vtls/darwinssl.c b/Utilities/cmcurl/lib/vtls/sectransp.c index e8116b8..2fdf662 100644 --- a/Utilities/cmcurl/lib/vtls/darwinssl.c +++ b/Utilities/cmcurl/lib/vtls/sectransp.c @@ -6,7 +6,7 @@ * \___|\___/|_| \_\_____| * * Copyright (C) 2012 - 2017, Nick Zitzmann, <nickzman@gmail.com>. - * Copyright (C) 2012 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 2012 - 2019, 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 @@ -31,8 +31,9 @@ #include "urldata.h" /* for the Curl_easy definition */ #include "curl_base64.h" #include "strtok.h" +#include "multiif.h" -#ifdef USE_DARWINSSL +#ifdef USE_SECTRANSP #ifdef __clang__ #pragma clang diagnostic push @@ -59,7 +60,7 @@ #if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) #if MAC_OS_X_VERSION_MAX_ALLOWED < 1050 -#error "The darwinssl back-end requires Leopard or later." +#error "The Secure Transport back-end requires Leopard or later." #endif /* MAC_OS_X_VERSION_MAX_ALLOWED < 1050 */ #define CURL_BUILD_IOS 0 @@ -105,7 +106,7 @@ #define CURL_SUPPORT_MAC_10_9 0 #else -#error "The darwinssl back-end requires iOS or OS X." +#error "The Secure Transport back-end requires iOS or macOS." #endif /* (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) */ #if CURL_BUILD_MAC @@ -118,7 +119,7 @@ #include "connect.h" #include "select.h" #include "vtls.h" -#include "darwinssl.h" +#include "sectransp.h" #include "curl_printf.h" #include "strdup.h" @@ -144,20 +145,20 @@ struct ssl_backend_data { /* version 1 supports macOS 10.12+ and iOS 10+ */ #if ((TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MIN_REQUIRED >= 100000) || \ (!TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200)) -#define DARWIN_SSL_PINNEDPUBKEY_V1 1 +#define SECTRANSP_PINNEDPUBKEY_V1 1 #endif /* version 2 supports MacOSX 10.7+ */ #if (!TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070) -#define DARWIN_SSL_PINNEDPUBKEY_V2 1 +#define SECTRANSP_PINNEDPUBKEY_V2 1 #endif -#if defined(DARWIN_SSL_PINNEDPUBKEY_V1) || defined(DARWIN_SSL_PINNEDPUBKEY_V2) +#if defined(SECTRANSP_PINNEDPUBKEY_V1) || defined(SECTRANSP_PINNEDPUBKEY_V2) /* this backend supports CURLOPT_PINNEDPUBLICKEY */ -#define DARWIN_SSL_PINNEDPUBKEY 1 -#endif /* DARWIN_SSL_PINNEDPUBKEY */ +#define SECTRANSP_PINNEDPUBKEY 1 +#endif /* SECTRANSP_PINNEDPUBKEY */ -#ifdef DARWIN_SSL_PINNEDPUBKEY +#ifdef SECTRANSP_PINNEDPUBKEY /* both new and old APIs return rsa keys missing the spki header (not DER) */ static const unsigned char rsa4096SpkiHeader[] = { 0x30, 0x82, 0x02, 0x22, 0x30, 0x0d, @@ -170,7 +171,7 @@ static const unsigned char rsa2048SpkiHeader[] = { 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00}; -#ifdef DARWIN_SSL_PINNEDPUBKEY_V1 +#ifdef SECTRANSP_PINNEDPUBKEY_V1 /* the *new* version doesn't return DER encoded ecdsa certs like the old... */ static const unsigned char ecDsaSecp256r1SpkiHeader[] = { 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, @@ -184,8 +185,8 @@ static const unsigned char ecDsaSecp384r1SpkiHeader[] = { 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x22, 0x03, 0x62, 0x00}; -#endif /* DARWIN_SSL_PINNEDPUBKEY_V1 */ -#endif /* DARWIN_SSL_PINNEDPUBKEY */ +#endif /* SECTRANSP_PINNEDPUBKEY_V1 */ +#endif /* SECTRANSP_PINNEDPUBKEY */ /* The following two functions were ripped from Apple sample code, * with some modifications: */ @@ -950,7 +951,7 @@ static CURLcode CopyCertSubject(struct Curl_easy *data, if(!c) { failf(data, "SSL: invalid CA certificate subject"); - return CURLE_SSL_CACERT; + return CURLE_PEER_FAILED_VERIFICATION; } /* If the subject is already available as UTF-8 encoded (ie 'direct') then @@ -970,7 +971,7 @@ static CURLcode CopyCertSubject(struct Curl_easy *data, if(!CFStringGetCString(c, cbuf, cbuf_size, kCFStringEncodingUTF8)) { failf(data, "SSL: invalid CA certificate subject"); - result = CURLE_SSL_CACERT; + result = CURLE_PEER_FAILED_VERIFICATION; } else /* pass back the buffer */ @@ -1242,7 +1243,7 @@ CF_INLINE bool is_file(const char *filename) } #if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS -static CURLcode darwinssl_version_from_curl(SSLProtocol *darwinver, +static CURLcode sectransp_version_from_curl(SSLProtocol *darwinver, long ssl_version) { switch(ssl_version) { @@ -1298,7 +1299,6 @@ set_ssl_version_min_max(struct connectdata *conn, int sockindex) case CURL_SSLVERSION_DEFAULT: case CURL_SSLVERSION_TLSv1: ssl_version = CURL_SSLVERSION_TLSv1_0; - ssl_version_max = max_supported_version_by_os; break; } @@ -1313,13 +1313,13 @@ set_ssl_version_min_max(struct connectdata *conn, int sockindex) if(SSLSetProtocolVersionMax != NULL) { SSLProtocol darwin_ver_min = kTLSProtocol1; SSLProtocol darwin_ver_max = kTLSProtocol1; - CURLcode result = darwinssl_version_from_curl(&darwin_ver_min, + CURLcode result = sectransp_version_from_curl(&darwin_ver_min, ssl_version); if(result) { failf(data, "unsupported min version passed via CURLOPT_SSLVERSION"); return result; } - result = darwinssl_version_from_curl(&darwin_ver_max, + result = sectransp_version_from_curl(&darwin_ver_max, ssl_version_max >> 16); if(result) { failf(data, "unsupported max version passed via CURLOPT_SSLVERSION"); @@ -1362,12 +1362,12 @@ set_ssl_version_min_max(struct connectdata *conn, int sockindex) #endif /* CURL_SUPPORT_MAC_10_8 */ } #endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */ - failf(data, "DarwinSSL: cannot set SSL protocol"); + failf(data, "Secure Transport: cannot set SSL protocol"); return CURLE_SSL_CONNECT_ERROR; } -static CURLcode darwinssl_connect_step1(struct connectdata *conn, +static CURLcode sectransp_connect_step1(struct connectdata *conn, int sockindex) { struct Curl_easy *data = conn->data; @@ -1430,7 +1430,6 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn, #if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS if(SSLSetProtocolVersionMax != NULL) { switch(conn->ssl_config.version) { - case CURL_SSLVERSION_DEFAULT: case CURL_SSLVERSION_TLSv1: (void)SSLSetProtocolVersionMin(BACKEND->ssl_ctx, kTLSProtocol1); #if (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1 @@ -1445,6 +1444,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn, #endif /* (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1 */ break; + case CURL_SSLVERSION_DEFAULT: case CURL_SSLVERSION_TLSv1_0: case CURL_SSLVERSION_TLSv1_1: case CURL_SSLVERSION_TLSv1_2: @@ -1578,7 +1578,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn, #if (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1 if(conn->bits.tls_enable_alpn) { - if(__builtin_available(macOS 10.13.4, iOS 11, *)) { + if(__builtin_available(macOS 10.13.4, iOS 11, tvOS 11, *)) { CFMutableArrayRef alpnArr = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); @@ -1649,7 +1649,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn, } CFRelease(cert); - if(result == CURLE_SSL_CACERT) + if(result == CURLE_PEER_FAILED_VERIFICATION) return CURLE_SSL_CERTPROBLEM; if(result) return result; @@ -1903,7 +1903,6 @@ static CURLcode darwinssl_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) { - /* TODO s/data->set.ssl.enable_beast/SSL_SET_OPTION(enable_beast)/g */ SSLSetSessionOption(BACKEND->ssl_ctx, kSSLSessionOptionSendOneByteRecord, !data->set.ssl.enable_beast); SSLSetSessionOption(BACKEND->ssl_ctx, kSSLSessionOptionFalseStart, @@ -2235,7 +2234,7 @@ static int verify_cert(const char *cafile, struct Curl_easy *data, } } -#ifdef DARWIN_SSL_PINNEDPUBKEY +#ifdef SECTRANSP_PINNEDPUBKEY static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data, SSLContextRef ctx, const char *pinnedpubkey) @@ -2267,14 +2266,14 @@ static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data, if(keyRef == NULL) break; -#ifdef DARWIN_SSL_PINNEDPUBKEY_V1 +#ifdef SECTRANSP_PINNEDPUBKEY_V1 publicKeyBits = SecKeyCopyExternalRepresentation(keyRef, NULL); CFRelease(keyRef); if(publicKeyBits == NULL) break; -#elif DARWIN_SSL_PINNEDPUBKEY_V2 +#elif SECTRANSP_PINNEDPUBKEY_V2 OSStatus success = SecItemExport(keyRef, kSecFormatOpenSSL, 0, NULL, &publicKeyBits); @@ -2282,7 +2281,7 @@ static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data, if(success != errSecSuccess || publicKeyBits == NULL) break; -#endif /* DARWIN_SSL_PINNEDPUBKEY_V2 */ +#endif /* SECTRANSP_PINNEDPUBKEY_V2 */ pubkeylen = CFDataGetLength(publicKeyBits); pubkey = (unsigned char *)CFDataGetBytePtr(publicKeyBits); @@ -2296,7 +2295,7 @@ static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data, /* 2048 bit RSA pubkeylen == 270 */ spkiHeader = rsa2048SpkiHeader; break; -#ifdef DARWIN_SSL_PINNEDPUBKEY_V1 +#ifdef SECTRANSP_PINNEDPUBKEY_V1 case 65: /* ecDSA secp256r1 pubkeylen == 65 */ spkiHeader = ecDsaSecp256r1SpkiHeader; @@ -2309,7 +2308,7 @@ static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data, break; default: infof(data, "SSL: unhandled public key length: %d\n", pubkeylen); -#elif DARWIN_SSL_PINNEDPUBKEY_V2 +#elif SECTRANSP_PINNEDPUBKEY_V2 default: /* ecDSA secp256r1 pubkeylen == 91 header already included? * ecDSA secp384r1 header already included too @@ -2317,7 +2316,7 @@ static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data, */ result = Curl_pin_peer_pubkey(data, pinnedpubkey, pubkey, pubkeylen); -#endif /* DARWIN_SSL_PINNEDPUBKEY_V2 */ +#endif /* SECTRANSP_PINNEDPUBKEY_V2 */ continue; /* break from loop */ } @@ -2340,10 +2339,10 @@ static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data, return result; } -#endif /* DARWIN_SSL_PINNEDPUBKEY */ +#endif /* SECTRANSP_PINNEDPUBKEY */ static CURLcode -darwinssl_connect_step2(struct connectdata *conn, int sockindex) +sectransp_connect_step2(struct connectdata *conn, int sockindex) { struct Curl_easy *data = conn->data; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; @@ -2377,7 +2376,7 @@ darwinssl_connect_step2(struct connectdata *conn, int sockindex) return res; } /* the documentation says we need to call SSLHandshake() again */ - return darwinssl_connect_step2(conn, sockindex); + return sectransp_connect_step2(conn, sockindex); /* Problem with encrypt / decrypt */ case errSSLPeerDecodeError: @@ -2429,37 +2428,37 @@ darwinssl_connect_step2(struct connectdata *conn, int sockindex) /* These are all certificate problems with the server: */ case errSSLXCertChainInvalid: failf(data, "SSL certificate problem: Invalid certificate chain"); - return CURLE_SSL_CACERT; + return CURLE_PEER_FAILED_VERIFICATION; case errSSLUnknownRootCert: failf(data, "SSL certificate problem: Untrusted root certificate"); - return CURLE_SSL_CACERT; + return CURLE_PEER_FAILED_VERIFICATION; case errSSLNoRootCert: failf(data, "SSL certificate problem: No root certificate"); - return CURLE_SSL_CACERT; + return CURLE_PEER_FAILED_VERIFICATION; case errSSLCertNotYetValid: failf(data, "SSL certificate problem: The certificate chain had a " "certificate that is not yet valid"); - return CURLE_SSL_CACERT; + return CURLE_PEER_FAILED_VERIFICATION; case errSSLCertExpired: case errSSLPeerCertExpired: failf(data, "SSL certificate problem: Certificate chain had an " "expired certificate"); - return CURLE_SSL_CACERT; + return CURLE_PEER_FAILED_VERIFICATION; case errSSLBadCert: case errSSLPeerBadCert: failf(data, "SSL certificate problem: Couldn't understand the server " "certificate format"); - return CURLE_SSL_CACERT; + return CURLE_PEER_FAILED_VERIFICATION; case errSSLPeerUnsupportedCert: failf(data, "SSL certificate problem: An unsupported certificate " "format was encountered"); - return CURLE_SSL_CACERT; + return CURLE_PEER_FAILED_VERIFICATION; case errSSLPeerCertRevoked: failf(data, "SSL certificate problem: The certificate was revoked"); - return CURLE_SSL_CACERT; + return CURLE_PEER_FAILED_VERIFICATION; case errSSLPeerCertUnknown: failf(data, "SSL certificate problem: The certificate is unknown"); - return CURLE_SSL_CACERT; + return CURLE_PEER_FAILED_VERIFICATION; /* These are all certificate problems with the client: */ case errSecAuthFailed: @@ -2579,7 +2578,7 @@ darwinssl_connect_step2(struct connectdata *conn, int sockindex) /* we have been connected fine, we're not waiting for anything else. */ connssl->connecting_state = ssl_connect_3; -#ifdef DARWIN_SSL_PINNEDPUBKEY +#ifdef SECTRANSP_PINNEDPUBKEY if(data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]) { CURLcode result = pkp_pin_peer_pubkey(data, BACKEND->ssl_ctx, data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]); @@ -2588,7 +2587,7 @@ darwinssl_connect_step2(struct connectdata *conn, int sockindex) return result; } } -#endif /* DARWIN_SSL_PINNEDPUBKEY */ +#endif /* SECTRANSP_PINNEDPUBKEY */ /* Informational message */ (void)SSLGetNegotiatedCipher(BACKEND->ssl_ctx, &cipher); @@ -2629,7 +2628,7 @@ darwinssl_connect_step2(struct connectdata *conn, int sockindex) #if(CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1 if(conn->bits.tls_enable_alpn) { - if(__builtin_available(macOS 10.13.4, iOS 11, *)) { + if(__builtin_available(macOS 10.13.4, iOS 11, tvOS 11, *)) { CFArrayRef alpnArr = NULL; CFStringRef chosenProtocol = NULL; err = SSLCopyALPNProtocols(BACKEND->ssl_ctx, &alpnArr); @@ -2652,6 +2651,9 @@ darwinssl_connect_step2(struct connectdata *conn, int sockindex) else infof(data, "ALPN, server did not agree to a protocol\n"); + Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ? + BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE); + /* chosenProtocol is a reference to the string within alpnArr and doesn't need to be freed separately */ if(alpnArr) @@ -2772,7 +2774,7 @@ show_verbose_server_cert(struct connectdata *conn, #endif /* !CURL_DISABLE_VERBOSE_STRINGS */ static CURLcode -darwinssl_connect_step3(struct connectdata *conn, +sectransp_connect_step3(struct connectdata *conn, int sockindex) { struct Curl_easy *data = conn->data; @@ -2790,11 +2792,11 @@ darwinssl_connect_step3(struct connectdata *conn, return CURLE_OK; } -static Curl_recv darwinssl_recv; -static Curl_send darwinssl_send; +static Curl_recv sectransp_recv; +static Curl_send sectransp_send; static CURLcode -darwinssl_connect_common(struct connectdata *conn, +sectransp_connect_common(struct connectdata *conn, int sockindex, bool nonblocking, bool *done) @@ -2822,7 +2824,7 @@ darwinssl_connect_common(struct connectdata *conn, return CURLE_OPERATION_TIMEDOUT; } - result = darwinssl_connect_step1(conn, sockindex); + result = sectransp_connect_step1(conn, sockindex); if(result) return result; } @@ -2876,7 +2878,7 @@ darwinssl_connect_common(struct connectdata *conn, * before step2 has completed while ensuring that a client using select() * or epoll() will always have a valid fdset to wait on. */ - result = darwinssl_connect_step2(conn, sockindex); + result = sectransp_connect_step2(conn, sockindex); if(result || (nonblocking && (ssl_connect_2 == connssl->connecting_state || ssl_connect_2_reading == connssl->connecting_state || @@ -2887,15 +2889,15 @@ darwinssl_connect_common(struct connectdata *conn, if(ssl_connect_3 == connssl->connecting_state) { - result = darwinssl_connect_step3(conn, sockindex); + result = sectransp_connect_step3(conn, sockindex); if(result) return result; } if(ssl_connect_done == connssl->connecting_state) { connssl->state = ssl_connection_complete; - conn->recv[sockindex] = darwinssl_recv; - conn->send[sockindex] = darwinssl_send; + conn->recv[sockindex] = sectransp_recv; + conn->send[sockindex] = sectransp_send; *done = TRUE; } else @@ -2907,18 +2909,18 @@ darwinssl_connect_common(struct connectdata *conn, return CURLE_OK; } -static CURLcode Curl_darwinssl_connect_nonblocking(struct connectdata *conn, +static CURLcode Curl_sectransp_connect_nonblocking(struct connectdata *conn, int sockindex, bool *done) { - return darwinssl_connect_common(conn, sockindex, TRUE, done); + return sectransp_connect_common(conn, sockindex, TRUE, done); } -static CURLcode Curl_darwinssl_connect(struct connectdata *conn, int sockindex) +static CURLcode Curl_sectransp_connect(struct connectdata *conn, int sockindex) { CURLcode result; bool done = FALSE; - result = darwinssl_connect_common(conn, sockindex, FALSE, &done); + result = sectransp_connect_common(conn, sockindex, FALSE, &done); if(result) return result; @@ -2928,7 +2930,7 @@ static CURLcode Curl_darwinssl_connect(struct connectdata *conn, int sockindex) return CURLE_OK; } -static void Curl_darwinssl_close(struct connectdata *conn, int sockindex) +static void Curl_sectransp_close(struct connectdata *conn, int sockindex) { struct ssl_connect_data *connssl = &conn->ssl[sockindex]; @@ -2949,7 +2951,7 @@ static void Curl_darwinssl_close(struct connectdata *conn, int sockindex) BACKEND->ssl_sockfd = 0; } -static int Curl_darwinssl_shutdown(struct connectdata *conn, int sockindex) +static int Curl_sectransp_shutdown(struct connectdata *conn, int sockindex) { struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct Curl_easy *data = conn->data; @@ -2961,10 +2963,12 @@ static int Curl_darwinssl_shutdown(struct connectdata *conn, int sockindex) if(!BACKEND->ssl_ctx) return 0; +#ifndef CURL_DISABLE_FTP if(data->set.ftp_ccc != CURLFTPSSL_CCC_ACTIVE) return 0; +#endif - Curl_darwinssl_close(conn, sockindex); + Curl_sectransp_close(conn, sockindex); rc = 0; @@ -3002,20 +3006,20 @@ static int Curl_darwinssl_shutdown(struct connectdata *conn, int sockindex) return rc; } -static void Curl_darwinssl_session_free(void *ptr) +static void Curl_sectransp_session_free(void *ptr) { /* ST, as of iOS 5 and Mountain Lion, has no public method of deleting a cached session ID inside the Security framework. There is a private function that does this, but I don't want to have to explain to you why I got your application rejected from the App Store due to the use of a private API, so the best we can do is free up our own char array that we - created way back in darwinssl_connect_step1... */ + created way back in sectransp_connect_step1... */ Curl_safefree(ptr); } -static size_t Curl_darwinssl_version(char *buffer, size_t size) +static size_t Curl_sectransp_version(char *buffer, size_t size) { - return snprintf(buffer, size, "SecureTransport"); + return msnprintf(buffer, size, "SecureTransport"); } /* @@ -3026,7 +3030,7 @@ static size_t Curl_darwinssl_version(char *buffer, size_t size) * 0 means the connection has been closed * -1 means the connection status is unknown */ -static int Curl_darwinssl_check_cxn(struct connectdata *conn) +static int Curl_sectransp_check_cxn(struct connectdata *conn) { struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET]; OSStatus err; @@ -3041,7 +3045,7 @@ static int Curl_darwinssl_check_cxn(struct connectdata *conn) return 0; } -static bool Curl_darwinssl_data_pending(const struct connectdata *conn, +static bool Curl_sectransp_data_pending(const struct connectdata *conn, int connindex) { const struct ssl_connect_data *connssl = &conn->ssl[connindex]; @@ -3058,7 +3062,7 @@ static bool Curl_darwinssl_data_pending(const struct connectdata *conn, return false; } -static CURLcode Curl_darwinssl_random(struct Curl_easy *data UNUSED_PARAM, +static CURLcode Curl_sectransp_random(struct Curl_easy *data UNUSED_PARAM, unsigned char *entropy, size_t length) { /* arc4random_buf() isn't available on cats older than Lion, so let's @@ -3078,7 +3082,7 @@ static CURLcode Curl_darwinssl_random(struct Curl_easy *data UNUSED_PARAM, return CURLE_OK; } -static CURLcode Curl_darwinssl_md5sum(unsigned char *tmp, /* input */ +static CURLcode Curl_sectransp_md5sum(unsigned char *tmp, /* input */ size_t tmplen, unsigned char *md5sum, /* output */ size_t md5len) @@ -3088,7 +3092,7 @@ static CURLcode Curl_darwinssl_md5sum(unsigned char *tmp, /* input */ return CURLE_OK; } -static CURLcode Curl_darwinssl_sha256sum(const unsigned char *tmp, /* input */ +static CURLcode Curl_sectransp_sha256sum(const unsigned char *tmp, /* input */ size_t tmplen, unsigned char *sha256sum, /* output */ size_t sha256len) @@ -3098,7 +3102,7 @@ static CURLcode Curl_darwinssl_sha256sum(const unsigned char *tmp, /* input */ return CURLE_OK; } -static bool Curl_darwinssl_false_start(void) +static bool Curl_sectransp_false_start(void) { #if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 if(SSLSetSessionOption != NULL) @@ -3107,7 +3111,7 @@ static bool Curl_darwinssl_false_start(void) return FALSE; } -static ssize_t darwinssl_send(struct connectdata *conn, +static ssize_t sectransp_send(struct connectdata *conn, int sockindex, const void *mem, size_t len, @@ -3173,7 +3177,7 @@ static ssize_t darwinssl_send(struct connectdata *conn, return (ssize_t)processed; } -static ssize_t darwinssl_recv(struct connectdata *conn, +static ssize_t sectransp_recv(struct connectdata *conn, int num, char *buf, size_t buffersize, @@ -3213,48 +3217,48 @@ static ssize_t darwinssl_recv(struct connectdata *conn, return (ssize_t)processed; } -static void *Curl_darwinssl_get_internals(struct ssl_connect_data *connssl, +static void *Curl_sectransp_get_internals(struct ssl_connect_data *connssl, CURLINFO info UNUSED_PARAM) { (void)info; return BACKEND->ssl_ctx; } -const struct Curl_ssl Curl_ssl_darwinssl = { - { CURLSSLBACKEND_DARWINSSL, "darwinssl" }, /* info */ +const struct Curl_ssl Curl_ssl_sectransp = { + { CURLSSLBACKEND_SECURETRANSPORT, "secure-transport" }, /* info */ -#ifdef DARWIN_SSL_PINNEDPUBKEY +#ifdef SECTRANSP_PINNEDPUBKEY SSLSUPP_PINNEDPUBKEY, #else 0, -#endif /* DARWIN_SSL_PINNEDPUBKEY */ +#endif /* SECTRANSP_PINNEDPUBKEY */ sizeof(struct ssl_backend_data), Curl_none_init, /* init */ Curl_none_cleanup, /* cleanup */ - Curl_darwinssl_version, /* version */ - Curl_darwinssl_check_cxn, /* check_cxn */ - Curl_darwinssl_shutdown, /* shutdown */ - Curl_darwinssl_data_pending, /* data_pending */ - Curl_darwinssl_random, /* random */ + Curl_sectransp_version, /* version */ + Curl_sectransp_check_cxn, /* check_cxn */ + Curl_sectransp_shutdown, /* shutdown */ + Curl_sectransp_data_pending, /* data_pending */ + Curl_sectransp_random, /* random */ Curl_none_cert_status_request, /* cert_status_request */ - Curl_darwinssl_connect, /* connect */ - Curl_darwinssl_connect_nonblocking, /* connect_nonblocking */ - Curl_darwinssl_get_internals, /* get_internals */ - Curl_darwinssl_close, /* close_one */ + Curl_sectransp_connect, /* connect */ + Curl_sectransp_connect_nonblocking, /* connect_nonblocking */ + Curl_sectransp_get_internals, /* get_internals */ + Curl_sectransp_close, /* close_one */ Curl_none_close_all, /* close_all */ - Curl_darwinssl_session_free, /* session_free */ + Curl_sectransp_session_free, /* session_free */ Curl_none_set_engine, /* set_engine */ Curl_none_set_engine_default, /* set_engine_default */ Curl_none_engines_list, /* engines_list */ - Curl_darwinssl_false_start, /* false_start */ - Curl_darwinssl_md5sum, /* md5sum */ - Curl_darwinssl_sha256sum /* sha256sum */ + Curl_sectransp_false_start, /* false_start */ + Curl_sectransp_md5sum, /* md5sum */ + Curl_sectransp_sha256sum /* sha256sum */ }; #ifdef __clang__ #pragma clang diagnostic pop #endif -#endif /* USE_DARWINSSL */ +#endif /* USE_SECTRANSP */ diff --git a/Utilities/cmcurl/lib/vtls/darwinssl.h b/Utilities/cmcurl/lib/vtls/sectransp.h index 23c7f70..5cec797 100644 --- a/Utilities/cmcurl/lib/vtls/darwinssl.h +++ b/Utilities/cmcurl/lib/vtls/sectransp.h @@ -1,5 +1,5 @@ -#ifndef HEADER_CURL_DARWINSSL_H -#define HEADER_CURL_DARWINSSL_H +#ifndef HEADER_CURL_SECTRANSP_H +#define HEADER_CURL_SECTRANSP_H /*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | @@ -8,7 +8,7 @@ * \___|\___/|_| \_\_____| * * Copyright (C) 2012 - 2014, Nick Zitzmann, <nickzman@gmail.com>. - * Copyright (C) 2012 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 2012 - 2019, 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 @@ -24,9 +24,9 @@ ***************************************************************************/ #include "curl_setup.h" -#ifdef USE_DARWINSSL +#ifdef USE_SECTRANSP -extern const struct Curl_ssl Curl_ssl_darwinssl; +extern const struct Curl_ssl Curl_ssl_sectransp; -#endif /* USE_DARWINSSL */ -#endif /* HEADER_CURL_DARWINSSL_H */ +#endif /* USE_SECTRANSP */ +#endif /* HEADER_CURL_SECTRANSP_H */ diff --git a/Utilities/cmcurl/lib/vtls/vtls.c b/Utilities/cmcurl/lib/vtls/vtls.c index 6af39fe..a7452dc 100644 --- a/Utilities/cmcurl/lib/vtls/vtls.c +++ b/Utilities/cmcurl/lib/vtls/vtls.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2019, 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 @@ -248,7 +248,7 @@ Curl_ssl_connect(struct connectdata *conn, int sockindex) conn->ssl[sockindex].use = TRUE; conn->ssl[sockindex].state = ssl_connection_negotiating; - result = Curl_ssl->connect(conn, sockindex); + result = Curl_ssl->connect_blocking(conn, sockindex); if(!result) Curl_pgrsTime(conn->data, TIMER_APPCONNECT); /* SSL is connected */ @@ -498,9 +498,9 @@ CURLcode Curl_ssl_addsessionid(struct connectdata *conn, void Curl_ssl_close_all(struct Curl_easy *data) { - size_t i; /* kill the session ID cache if not shared */ if(data->state.session && !SSLSESSION_SHARED(data)) { + size_t i; for(i = 0; i < data->set.general_ssl.max_ssl_sessions; i++) /* the single-killer function handles empty table slots */ Curl_ssl_kill_session(&data->state.session[i]); @@ -513,7 +513,7 @@ void Curl_ssl_close_all(struct Curl_easy *data) } #if defined(USE_OPENSSL) || defined(USE_GNUTLS) || defined(USE_SCHANNEL) || \ - defined(USE_DARWINSSL) || defined(USE_POLARSSL) || defined(USE_NSS) || \ + defined(USE_SECTRANSP) || defined(USE_POLARSSL) || defined(USE_NSS) || \ defined(USE_MBEDTLS) || defined(USE_CYASSL) int Curl_ssl_getsock(struct connectdata *conn, curl_socket_t *socks, int numsocks) @@ -546,7 +546,7 @@ int Curl_ssl_getsock(struct connectdata *conn, (void)numsocks; return GETSOCK_BLANK; } -/* USE_OPENSSL || USE_GNUTLS || USE_SCHANNEL || USE_DARWINSSL || USE_NSS */ +/* USE_OPENSSL || USE_GNUTLS || USE_SCHANNEL || USE_SECTRANSP || USE_NSS */ #endif void Curl_ssl_close(struct connectdata *conn, int sockindex) @@ -557,7 +557,7 @@ void Curl_ssl_close(struct connectdata *conn, int sockindex) CURLcode Curl_ssl_shutdown(struct connectdata *conn, int sockindex) { - if(Curl_ssl->shutdown(conn, sockindex)) + if(Curl_ssl->shut_down(conn, sockindex)) return CURLE_SSL_SHUTDOWN_FAILED; conn->ssl[sockindex].use = FALSE; /* get back to ordinary socket usage */ @@ -644,11 +644,11 @@ bool Curl_ssl_data_pending(const struct connectdata *conn, void Curl_ssl_free_certinfo(struct Curl_easy *data) { - int i; struct curl_certinfo *ci = &data->info.certs; if(ci->num_of_certs) { /* free all individual lists used */ + int i; for(i = 0; i<ci->num_of_certs; i++) { curl_slist_free_all(ci->certinfo[i]); ci->certinfo[i] = NULL; @@ -700,7 +700,7 @@ CURLcode Curl_ssl_push_certinfo_len(struct Curl_easy *data, return CURLE_OUT_OF_MEMORY; /* sprintf the label and colon */ - snprintf(output, outlen, "%s:", label); + msnprintf(output, outlen, "%s:", label); /* memcpy the value (it might not be zero terminated) */ memcpy(&output[labellen + 1], value, valuelen); @@ -808,14 +808,7 @@ CURLcode Curl_pin_peer_pubkey(struct Curl_easy *data, { FILE *fp; unsigned char *buf = NULL, *pem_ptr = NULL; - long filesize; - size_t size, pem_len; - CURLcode pem_read; CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH; - CURLcode encode; - size_t encodedlen, pinkeylen; - char *encoded, *pinkeycopy, *begin_pos, *end_pos; - unsigned char *sha256sumdigest = NULL; /* if a path wasn't specified, don't pin */ if(!pinnedpubkey) @@ -825,6 +818,11 @@ CURLcode Curl_pin_peer_pubkey(struct Curl_easy *data, /* only do this if pinnedpubkey starts with "sha256//", length 8 */ if(strncmp(pinnedpubkey, "sha256//", 8) == 0) { + CURLcode encode; + size_t encodedlen, pinkeylen; + char *encoded, *pinkeycopy, *begin_pos, *end_pos; + unsigned char *sha256sumdigest; + if(!Curl_ssl->sha256sum) { /* without sha256 support, this cannot match */ return result; @@ -895,6 +893,10 @@ CURLcode Curl_pin_peer_pubkey(struct Curl_easy *data, return result; do { + long filesize; + size_t size, pem_len; + CURLcode pem_read; + /* Determine the file's size */ if(fseek(fp, 0, SEEK_END)) break; @@ -1114,7 +1116,7 @@ static CURLcode Curl_multissl_connect(struct connectdata *conn, int sockindex) { if(multissl_init(NULL)) return CURLE_FAILED_INIT; - return Curl_ssl->connect(conn, sockindex); + return Curl_ssl->connect_blocking(conn, sockindex); } static CURLcode Curl_multissl_connect_nonblocking(struct connectdata *conn, @@ -1170,12 +1172,10 @@ static const struct Curl_ssl Curl_ssl_multi = { const struct Curl_ssl *Curl_ssl = #if defined(CURL_WITH_MULTI_SSL) &Curl_ssl_multi; -#elif defined(USE_AXTLS) - &Curl_ssl_axtls; #elif defined(USE_CYASSL) &Curl_ssl_cyassl; -#elif defined(USE_DARWINSSL) - &Curl_ssl_darwinssl; +#elif defined(USE_SECTRANSP) + &Curl_ssl_sectransp; #elif defined(USE_GNUTLS) &Curl_ssl_gnutls; #elif defined(USE_GSKIT) @@ -1197,14 +1197,11 @@ const struct Curl_ssl *Curl_ssl = #endif static const struct Curl_ssl *available_backends[] = { -#if defined(USE_AXTLS) - &Curl_ssl_axtls, -#endif #if defined(USE_CYASSL) &Curl_ssl_cyassl, #endif -#if defined(USE_DARWINSSL) - &Curl_ssl_darwinssl, +#if defined(USE_SECTRANSP) + &Curl_ssl_sectransp, #endif #if defined(USE_GNUTLS) &Curl_ssl_gnutls, @@ -1244,16 +1241,17 @@ static size_t Curl_multissl_version(char *buffer, size_t size) if(current != selected) { char *p = backends; + char *end = backends + sizeof(backends); int i; selected = current; - for(i = 0; available_backends[i]; i++) { + for(i = 0; available_backends[i] && p < (end - 4); i++) { if(i) *(p++) = ' '; if(selected != available_backends[i]) *(p++) = '('; - p += available_backends[i]->version(p, backends + sizeof(backends) - p); + p += available_backends[i]->version(p, end - p - 2); if(selected != available_backends[i]) *(p++) = ')'; } @@ -1261,21 +1259,20 @@ static size_t Curl_multissl_version(char *buffer, size_t size) total = p - backends; } - if(size < total) + if(size > total) memcpy(buffer, backends, total + 1); else { memcpy(buffer, backends, size - 1); buffer[size - 1] = '\0'; } - return total; + return CURLMIN(size - 1, total); } static int multissl_init(const struct Curl_ssl *backend) { const char *env; char *env_tmp; - int i; if(Curl_ssl != &Curl_ssl_multi) return 1; @@ -1294,6 +1291,7 @@ static int multissl_init(const struct Curl_ssl *backend) env = CURL_DEFAULT_SSL_BACKEND; #endif if(env) { + int i; for(i = 0; available_backends[i]; i++) { if(strcasecompare(env, available_backends[i]->info.name)) { Curl_ssl = available_backends[i]; @@ -1318,7 +1316,14 @@ CURLsslset curl_global_sslset(curl_sslbackend id, const char *name, *avail = (const curl_ssl_backend **)&available_backends; if(Curl_ssl != &Curl_ssl_multi) - return id == Curl_ssl->info.id ? CURLSSLSET_OK : CURLSSLSET_TOO_LATE; + return id == Curl_ssl->info.id || + (name && strcasecompare(name, Curl_ssl->info.name)) ? + CURLSSLSET_OK : +#if defined(CURL_WITH_MULTI_SSL) + CURLSSLSET_TOO_LATE; +#else + CURLSSLSET_UNKNOWN_BACKEND; +#endif for(i = 0; available_backends[i]; i++) { if(available_backends[i]->info.id == id || diff --git a/Utilities/cmcurl/lib/vtls/vtls.h b/Utilities/cmcurl/lib/vtls/vtls.h index 5cd1160..2a87ca1 100644 --- a/Utilities/cmcurl/lib/vtls/vtls.h +++ b/Utilities/cmcurl/lib/vtls/vtls.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2019, 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 @@ -47,7 +47,7 @@ struct Curl_ssl { size_t (*version)(char *buffer, size_t size); int (*check_cxn)(struct connectdata *cxn); - int (*shutdown)(struct connectdata *conn, int sockindex); + int (*shut_down)(struct connectdata *conn, int sockindex); bool (*data_pending)(const struct connectdata *conn, int connindex); @@ -56,7 +56,7 @@ struct Curl_ssl { size_t length); bool (*cert_status_request)(void); - CURLcode (*connect)(struct connectdata *conn, int sockindex); + CURLcode (*connect_blocking)(struct connectdata *conn, int sockindex); CURLcode (*connect_nonblocking)(struct connectdata *conn, int sockindex, bool *done); void *(*get_internals)(struct ssl_connect_data *connssl, CURLINFO info); @@ -103,10 +103,9 @@ CURLcode Curl_none_md5sum(unsigned char *input, size_t inputlen, #include "nssg.h" /* NSS versions */ #include "gskit.h" /* Global Secure ToolKit versions */ #include "polarssl.h" /* PolarSSL versions */ -#include "axtls.h" /* axTLS versions */ #include "cyassl.h" /* CyaSSL versions */ #include "schannel.h" /* Schannel SSPI version */ -#include "darwinssl.h" /* SecureTransport (Darwin) version */ +#include "sectransp.h" /* SecureTransport (Darwin) version */ #include "mbedtls.h" /* mbedTLS versions */ #include "mesalink.h" /* MesaLink versions */ |