diff options
Diffstat (limited to 'Utilities/cmcurl/lib/vtls/openssl.c')
-rw-r--r-- | Utilities/cmcurl/lib/vtls/openssl.c | 627 |
1 files changed, 452 insertions, 175 deletions
diff --git a/Utilities/cmcurl/lib/vtls/openssl.c b/Utilities/cmcurl/lib/vtls/openssl.c index dbee369..4253160 100644 --- a/Utilities/cmcurl/lib/vtls/openssl.c +++ b/Utilities/cmcurl/lib/vtls/openssl.c @@ -51,8 +51,10 @@ #include "strcase.h" #include "hostcheck.h" #include "curl_printf.h" - #include <openssl/ssl.h> +#ifdef HAVE_OPENSSL_ENGINE_H +#include <openssl/engine.h> +#endif #include <openssl/rand.h> #include <openssl/x509v3.h> #ifndef OPENSSL_NO_DSA @@ -64,6 +66,8 @@ #include <openssl/conf.h> #include <openssl/bn.h> #include <openssl/rsa.h> +#include <openssl/bio.h> +#include <openssl/buffer.h> #ifdef HAVE_OPENSSL_PKCS12_H #include <openssl/pkcs12.h> @@ -111,7 +115,6 @@ #define HAVE_OPAQUE_EVP_PKEY 1 /* since 1.1.0 -pre3 */ #define HAVE_OPAQUE_RSA_DSA_DH 1 /* since 1.1.0 -pre5 */ #define CONST_EXTS const -#define CONST_ASN1_BIT_STRING const #define HAVE_ERR_REMOVE_THREAD_STATE_DEPRECATED 1 #else /* For OpenSSL before 1.1.0 */ @@ -119,7 +122,6 @@ #define X509_get0_notBefore(x) X509_get_notBefore(x) #define X509_get0_notAfter(x) X509_get_notAfter(x) #define CONST_EXTS /* nope */ -#define CONST_ASN1_BIT_STRING /* nope */ #ifdef LIBRESSL_VERSION_NUMBER static unsigned long OpenSSL_version_num(void) { @@ -146,6 +148,20 @@ static unsigned long OpenSSL_version_num(void) #define OPENSSL_load_builtin_modules(x) #endif +/* + * Whether SSL_CTX_set_keylog_callback is available. + * OpenSSL: supported since 1.1.1 https://github.com/openssl/openssl/pull/2287 + * BoringSSL: supported since d28f59c27bac (committed 2015-11-19), the + * BORINGSSL_201512 macro from 2016-01-21 should be close enough. + * LibreSSL: unsupported in at least 2.5.1 (explicitly check for it since it + * lies and pretends to be OpenSSL 2.0.0). + */ +#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && \ + !defined(LIBRESSL_VERSION_NUMBER)) || \ + defined(BORINGSSL_201512) +#define HAVE_KEYLOG_CALLBACK +#endif + #if defined(LIBRESSL_VERSION_NUMBER) #define OSSL_PACKAGE "LibreSSL" #elif defined(OPENSSL_IS_BORINGSSL) @@ -154,6 +170,38 @@ static unsigned long OpenSSL_version_num(void) #define OSSL_PACKAGE "OpenSSL" #endif +#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) +/* up2date versions of OpenSSL maintain the default reasonably secure without + * breaking compatibility, so it is better not to override the default by curl + */ +#define DEFAULT_CIPHER_SELECTION NULL +#else +/* ... but it is not the case with old versions of OpenSSL */ +#define DEFAULT_CIPHER_SELECTION \ + "ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH" +#endif + +#ifdef ENABLE_SSLKEYLOGFILE +typedef struct ssl_tap_state { + int master_key_length; + unsigned char master_key[SSL_MAX_MASTER_KEY_LENGTH]; + unsigned char client_random[SSL3_RANDOM_SIZE]; +} ssl_tap_state_t; +#endif /* ENABLE_SSLKEYLOGFILE */ + +struct ssl_backend_data { + /* these ones requires specific SSL-types */ + SSL_CTX* ctx; + SSL* handle; + X509* server_cert; +#ifdef ENABLE_SSLKEYLOGFILE + /* tap_state holds the last seen master key if we're logging them */ + ssl_tap_state_t tap_state; +#endif +}; + +#define BACKEND connssl->backend + /* * Number of bytes to read from the random number seed file. This must be * a finite value (because some entropy "files" like /dev/urandom have @@ -162,6 +210,112 @@ static unsigned long OpenSSL_version_num(void) */ #define RAND_LOAD_LENGTH 1024 +#ifdef ENABLE_SSLKEYLOGFILE +/* The fp for the open SSLKEYLOGFILE, or NULL if not open */ +static FILE *keylog_file_fp; + +#ifdef HAVE_KEYLOG_CALLBACK +static void ossl_keylog_callback(const SSL *ssl, const char *line) +{ + (void)ssl; + + /* Using fputs here instead of fprintf since libcurl's fprintf replacement + may not be thread-safe. */ + if(keylog_file_fp && line && *line) { + char stackbuf[256]; + char *buf; + size_t linelen = strlen(line); + + if(linelen <= sizeof(stackbuf) - 2) + buf = stackbuf; + else { + buf = malloc(linelen + 2); + if(!buf) + return; + } + strncpy(buf, line, linelen); + buf[linelen] = '\n'; + buf[linelen + 1] = '\0'; + + fputs(buf, keylog_file_fp); + if(buf != stackbuf) + free(buf); + } +} +#else +#define KEYLOG_PREFIX "CLIENT_RANDOM " +#define KEYLOG_PREFIX_LEN (sizeof(KEYLOG_PREFIX) - 1) +/* + * tap_ssl_key is called by libcurl to make the CLIENT_RANDOMs if the OpenSSL + * being used doesn't have native support for doing that. + */ +static void tap_ssl_key(const SSL *ssl, ssl_tap_state_t *state) +{ + const char *hex = "0123456789ABCDEF"; + int pos, i; + char line[KEYLOG_PREFIX_LEN + 2 * SSL3_RANDOM_SIZE + 1 + + 2 * SSL_MAX_MASTER_KEY_LENGTH + 1 + 1]; + const SSL_SESSION *session = SSL_get_session(ssl); + unsigned char client_random[SSL3_RANDOM_SIZE]; + unsigned char master_key[SSL_MAX_MASTER_KEY_LENGTH]; + int master_key_length = 0; + + if(!session || !keylog_file_fp) + return; + +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + /* ssl->s3 is not checked in openssl 1.1.0-pre6, but let's assume that + * we have a valid SSL context if we have a non-NULL session. */ + SSL_get_client_random(ssl, client_random, SSL3_RANDOM_SIZE); + master_key_length = + SSL_SESSION_get_master_key(session, master_key, SSL_MAX_MASTER_KEY_LENGTH); +#else + if(ssl->s3 && session->master_key_length > 0) { + master_key_length = session->master_key_length; + memcpy(master_key, session->master_key, session->master_key_length); + memcpy(client_random, ssl->s3->client_random, SSL3_RANDOM_SIZE); + } +#endif + + if(master_key_length <= 0) + return; + + /* Skip writing keys if there is no key or it did not change. */ + if(state->master_key_length == master_key_length && + !memcmp(state->master_key, master_key, master_key_length) && + !memcmp(state->client_random, client_random, SSL3_RANDOM_SIZE)) { + return; + } + + state->master_key_length = master_key_length; + memcpy(state->master_key, master_key, master_key_length); + memcpy(state->client_random, client_random, SSL3_RANDOM_SIZE); + + memcpy(line, KEYLOG_PREFIX, KEYLOG_PREFIX_LEN); + pos = KEYLOG_PREFIX_LEN; + + /* Client Random for SSLv3/TLS */ + for(i = 0; i < SSL3_RANDOM_SIZE; i++) { + line[pos++] = hex[client_random[i] >> 4]; + line[pos++] = hex[client_random[i] & 0xF]; + } + line[pos++] = ' '; + + /* Master Secret (size is at most SSL_MAX_MASTER_KEY_LENGTH) */ + for(i = 0; i < master_key_length; i++) { + line[pos++] = hex[master_key[i] >> 4]; + line[pos++] = hex[master_key[i] & 0xF]; + } + line[pos++] = '\n'; + line[pos] = '\0'; + + /* Using fputs here instead of fprintf since libcurl's fprintf replacement + may not be thread-safe. */ + fputs(line, keylog_file_fp); +} +#endif /* !HAVE_KEYLOG_CALLBACK */ +#endif /* ENABLE_SSLKEYLOGFILE */ + static const char *SSL_ERROR_to_str(int err) { switch(err) { @@ -216,7 +370,7 @@ static int passwd_callback(char *buf, int num, int encrypting, if(!encrypting) { int klen = curlx_uztosi(strlen((char *)global_passwd)); if(num > klen) { - memcpy(buf, global_passwd, klen+1); + memcpy(buf, global_passwd, klen + 1); return klen; } } @@ -236,7 +390,6 @@ static CURLcode Curl_ossl_seed(struct Curl_easy *data) /* we have the "SSL is seeded" boolean static to prevent multiple time-consuming seedings in vain */ static bool ssl_seeded = FALSE; - int nread=0; char fname[256]; if(ssl_seeded) @@ -256,12 +409,12 @@ static CURLcode Curl_ossl_seed(struct Curl_easy *data) #endif { /* let the option override the define */ - nread += RAND_load_file((data->set.str[STRING_SSL_RANDOM_FILE]? - data->set.str[STRING_SSL_RANDOM_FILE]: - RANDOM_FILE), - RAND_LOAD_LENGTH); + RAND_load_file((data->set.str[STRING_SSL_RANDOM_FILE]? + data->set.str[STRING_SSL_RANDOM_FILE]: + RANDOM_FILE), + RAND_LOAD_LENGTH); if(rand_enough()) - return nread; + return CURLE_OK; } #if defined(HAVE_RAND_EGD) @@ -279,35 +432,47 @@ static CURLcode Curl_ossl_seed(struct Curl_easy *data) int ret = RAND_egd(data->set.str[STRING_SSL_EGDSOCKET]? data->set.str[STRING_SSL_EGDSOCKET]:EGD_SOCKET); if(-1 != ret) { - nread += ret; if(rand_enough()) - return nread; + return CURLE_OK; } } #endif - /* If we get here, it means we need to seed the PRNG using a "silly" - approach! */ + /* fallback to a custom seeding of the PRNG using a hash based on a current + time */ do { unsigned char randb[64]; - int len = sizeof(randb); - if(!RAND_bytes(randb, len)) - break; - RAND_add(randb, len, (len >> 1)); + size_t len = sizeof(randb); + size_t i, i_max; + for(i = 0, i_max = len / sizeof(struct curltime); i < i_max; ++i) { + struct curltime tv = curlx_tvnow(); + Curl_wait_ms(1); + tv.tv_sec *= i + 1; + tv.tv_usec *= (unsigned int)i + 2; + tv.tv_sec ^= ((curlx_tvnow().tv_sec + curlx_tvnow().tv_usec) * + (i + 3)) << 8; + tv.tv_usec ^= (unsigned int) ((curlx_tvnow().tv_sec + + curlx_tvnow().tv_usec) * + (i + 4)) << 16; + memcpy(&randb[i * sizeof(struct curltime)], &tv, + sizeof(struct curltime)); + } + RAND_add(randb, (int)len, (double)len/2); } while(!rand_enough()); /* generates a default path for the random seed file */ - fname[0]=0; /* blank it first */ + fname[0] = 0; /* blank it first */ RAND_file_name(fname, sizeof(fname)); if(fname[0]) { /* we got a file name to try */ - nread += RAND_load_file(fname, RAND_LOAD_LENGTH); + RAND_load_file(fname, RAND_LOAD_LENGTH); if(rand_enough()) - return nread; + return CURLE_OK; } infof(data, "libcurl is now using a weak random seed!\n"); - return CURLE_SSL_CONNECT_ERROR; /* confusing error code */ + return (rand_enough() ? CURLE_OK : + CURLE_SSL_CONNECT_ERROR /* confusing error code */); } #ifndef SSL_FILETYPE_ENGINE @@ -384,6 +549,7 @@ int cert_stuff(struct connectdata *conn, { struct Curl_easy *data = conn->data; char error_buffer[256]; + bool check_privkey = TRUE; int file_type = do_file_type(cert_type); @@ -592,7 +758,7 @@ int cert_stuff(struct connectdata *conn, break; if(!key_file) /* cert & key can only be in PEM case in the same file */ - key_file=cert_file; + key_file = cert_file; /* FALLTHROUGH */ case SSL_FILETYPE_ASN1: if(SSL_CTX_use_PrivateKey_file(ctx, key_file, file_type) != 1) { @@ -655,13 +821,13 @@ int cert_stuff(struct connectdata *conn, return 0; } - ssl=SSL_new(ctx); + ssl = SSL_new(ctx); if(!ssl) { failf(data, "unable to create an SSL structure"); return 0; } - x509=SSL_get_certificate(ssl); + x509 = SSL_get_certificate(ssl); /* This version was provided by Evan Jordan and is supposed to not leak memory as the previous version: */ @@ -671,17 +837,32 @@ int cert_stuff(struct connectdata *conn, EVP_PKEY_free(pktmp); } +#ifndef OPENSSL_NO_RSA + { + /* If RSA is used, don't check the private key if its flags indicate + * it doesn't support it. */ + EVP_PKEY *priv_key = SSL_get_privatekey(ssl); + if(EVP_PKEY_id(priv_key) == EVP_PKEY_RSA) { + RSA *rsa = EVP_PKEY_get1_RSA(priv_key); + if(RSA_flags(rsa) & RSA_METHOD_FLAG_NO_CHECK) + check_privkey = FALSE; + RSA_free(rsa); /* Decrement reference count */ + } + } +#endif + SSL_free(ssl); /* If we are using DSA, we can copy the parameters from * the private key */ - - /* Now we know that a key and cert have been set against - * the SSL context */ - if(!SSL_CTX_check_private_key(ctx)) { - failf(data, "Private key does not match the certificate public key"); - return 0; + if(check_privkey == TRUE) { + /* Now we know that a key and cert have been set against + * the SSL context */ + if(!SSL_CTX_check_private_key(ctx)) { + failf(data, "Private key does not match the certificate public key"); + return 0; + } } } return 1; @@ -709,7 +890,7 @@ static int x509_name_oneline(X509_NAME *a, char *buf, size_t size) size--; /* don't overwrite the buffer end */ memcpy(buf, biomem->data, size); - buf[size]=0; + buf[size] = 0; BIO_free(bio_out); @@ -723,8 +904,12 @@ static int x509_name_oneline(X509_NAME *a, char *buf, size_t size) * @retval 0 error initializing SSL * @retval 1 SSL initialized successfully */ -int Curl_ossl_init(void) +static int Curl_ossl_init(void) { +#ifdef ENABLE_SSLKEYLOGFILE + const char *keylog_file_name; +#endif + OPENSSL_load_builtin_modules(); #ifdef HAVE_ENGINE_LOAD_BUILTIN_ENGINES @@ -761,11 +946,24 @@ int Curl_ossl_init(void) OpenSSL_add_all_algorithms(); #endif +#ifdef ENABLE_SSLKEYLOGFILE + keylog_file_name = curl_getenv("SSLKEYLOGFILE"); + if(keylog_file_name && !keylog_file_fp) { + keylog_file_fp = fopen(keylog_file_name, FOPEN_APPENDTEXT); + if(keylog_file_fp) { + if(setvbuf(keylog_file_fp, NULL, _IOLBF, 4096)) { + fclose(keylog_file_fp); + keylog_file_fp = NULL; + } + } + } +#endif + return 1; } /* Global cleanup */ -void Curl_ossl_cleanup(void) +static void Curl_ossl_cleanup(void) { #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && \ !defined(LIBRESSL_VERSION_NUMBER) @@ -797,6 +995,13 @@ void Curl_ossl_cleanup(void) SSL_COMP_free_compression_methods(); #endif #endif + +#ifdef ENABLE_SSLKEYLOGFILE + if(keylog_file_fp) { + fclose(keylog_file_fp); + keylog_file_fp = NULL; + } +#endif } /* @@ -807,7 +1012,7 @@ void Curl_ossl_cleanup(void) * 0 means the connection has been closed * -1 means the connection status is unknown */ -int Curl_ossl_check_cxn(struct connectdata *conn) +static int Curl_ossl_check_cxn(struct connectdata *conn) { /* SSL_peek takes data out of the raw recv buffer without peeking so we use recv MSG_PEEK instead. Bug #795 */ @@ -853,7 +1058,8 @@ int Curl_ossl_check_cxn(struct connectdata *conn) /* Selects an OpenSSL crypto engine */ -CURLcode Curl_ossl_set_engine(struct Curl_easy *data, const char *engine) +static CURLcode Curl_ossl_set_engine(struct Curl_easy *data, + const char *engine) { #if defined(USE_OPENSSL) && defined(HAVE_OPENSSL_ENGINE_H) ENGINE *e; @@ -898,7 +1104,7 @@ CURLcode Curl_ossl_set_engine(struct Curl_easy *data, const char *engine) /* Sets engine as default for all SSL operations */ -CURLcode Curl_ossl_set_engine_default(struct Curl_easy *data) +static CURLcode Curl_ossl_set_engine_default(struct Curl_easy *data) { #ifdef HAVE_OPENSSL_ENGINE_H if(data->state.engine) { @@ -920,7 +1126,7 @@ CURLcode Curl_ossl_set_engine_default(struct Curl_easy *data) /* Return list of OpenSSL crypto engine names. */ -struct curl_slist *Curl_ossl_engines_list(struct Curl_easy *data) +static struct curl_slist *Curl_ossl_engines_list(struct Curl_easy *data) { struct curl_slist *list = NULL; #if defined(USE_OPENSSL) && defined(HAVE_OPENSSL_ENGINE_H) @@ -943,23 +1149,23 @@ struct curl_slist *Curl_ossl_engines_list(struct Curl_easy *data) static void ossl_close(struct ssl_connect_data *connssl) { - if(connssl->handle) { - (void)SSL_shutdown(connssl->handle); - SSL_set_connect_state(connssl->handle); + if(BACKEND->handle) { + (void)SSL_shutdown(BACKEND->handle); + SSL_set_connect_state(BACKEND->handle); - SSL_free(connssl->handle); - connssl->handle = NULL; + SSL_free(BACKEND->handle); + BACKEND->handle = NULL; } - if(connssl->ctx) { - SSL_CTX_free(connssl->ctx); - connssl->ctx = NULL; + if(BACKEND->ctx) { + SSL_CTX_free(BACKEND->ctx); + BACKEND->ctx = NULL; } } /* * This function is called when an SSL connection is closed. */ -void Curl_ossl_close(struct connectdata *conn, int sockindex) +static void Curl_ossl_close(struct connectdata *conn, int sockindex) { ossl_close(&conn->ssl[sockindex]); ossl_close(&conn->proxy_ssl[sockindex]); @@ -969,7 +1175,7 @@ void Curl_ossl_close(struct connectdata *conn, int sockindex) * This function is called to shut down the SSL layer but keep the * socket open (CCC - Clear Command Channel) */ -int Curl_ossl_shutdown(struct connectdata *conn, int sockindex) +static int Curl_ossl_shutdown(struct connectdata *conn, int sockindex) { int retval = 0; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; @@ -988,9 +1194,9 @@ int Curl_ossl_shutdown(struct connectdata *conn, int sockindex) we do not send one. Let's hope other servers do the same... */ if(data->set.ftp_ccc == CURLFTPSSL_CCC_ACTIVE) - (void)SSL_shutdown(connssl->handle); + (void)SSL_shutdown(BACKEND->handle); - if(connssl->handle) { + if(BACKEND->handle) { buffsize = (int)sizeof(buf); while(!done) { int what = SOCKET_READABLE(conn->sock[sockindex], @@ -1000,9 +1206,8 @@ int Curl_ossl_shutdown(struct connectdata *conn, int sockindex) /* Something to read, let's do it and hope that it is the close notify alert from the server */ - nread = (ssize_t)SSL_read(conn->ssl[sockindex].handle, buf, - buffsize); - err = SSL_get_error(conn->ssl[sockindex].handle, (int)nread); + nread = (ssize_t)SSL_read(BACKEND->handle, buf, buffsize); + err = SSL_get_error(BACKEND->handle, (int)nread); switch(err) { case SSL_ERROR_NONE: /* this is not an error */ @@ -1047,7 +1252,7 @@ int Curl_ossl_shutdown(struct connectdata *conn, int sockindex) if(data->set.verbose) { #ifdef HAVE_SSL_GET_SHUTDOWN - switch(SSL_get_shutdown(connssl->handle)) { + switch(SSL_get_shutdown(BACKEND->handle)) { case SSL_SENT_SHUTDOWN: infof(data, "SSL_get_shutdown() returned SSL_SENT_SHUTDOWN\n"); break; @@ -1062,13 +1267,13 @@ int Curl_ossl_shutdown(struct connectdata *conn, int sockindex) #endif } - SSL_free(connssl->handle); - connssl->handle = NULL; + SSL_free(BACKEND->handle); + BACKEND->handle = NULL; } return retval; } -void Curl_ossl_session_free(void *ptr) +static void Curl_ossl_session_free(void *ptr) { /* free the ID */ SSL_SESSION_free(ptr); @@ -1078,7 +1283,7 @@ void Curl_ossl_session_free(void *ptr) * This function is called when the 'data' struct is going away. Close * down everything and free all resources! */ -void Curl_ossl_close_all(struct Curl_easy *data) +static void Curl_ossl_close_all(struct Curl_easy *data) { #ifdef HAVE_OPENSSL_ENGINE_H if(data->state.engine) { @@ -1170,7 +1375,7 @@ static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert) numalts = sk_GENERAL_NAME_num(altnames); /* loop through all alternatives - until a dnsmatch */ - for(i=0; (i < numalts) && !dnsmatched; i++) { + for(i = 0; (i < numalts) && !dnsmatched; i++) { /* get a handle to alternative name number i */ const GENERAL_NAME *check = sk_GENERAL_NAME_value(altnames, i); @@ -1239,7 +1444,7 @@ static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert) else { /* we have to look to the last occurrence of a commonName in the distinguished one to get the most significant one. */ - int j, i=-1; + int j, i = -1; /* The following is done because of a bug in 0.9.6b */ @@ -1248,14 +1453,14 @@ static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert) X509_NAME *name = X509_get_subject_name(server_cert); if(name) - while((j = X509_NAME_get_index_by_NID(name, NID_commonName, i))>=0) - i=j; + while((j = X509_NAME_get_index_by_NID(name, NID_commonName, i)) >= 0) + i = j; /* we have the name entry and we will now convert this to a string that we can use for comparison. Doing this we support BMPstring, UTF8 etc. */ - if(i>=0) { + if(i >= 0) { ASN1_STRING *tmp = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name, i)); @@ -1268,7 +1473,7 @@ static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert) if(ASN1_STRING_type(tmp) == V_ASN1_UTF8STRING) { j = ASN1_STRING_length(tmp); if(j >= 0) { - peer_CN = OPENSSL_malloc(j+1); + peer_CN = OPENSSL_malloc(j + 1); if(peer_CN) { memcpy(peer_CN, ASN1_STRING_get0_data(tmp), j); peer_CN[j] = '\0'; @@ -1291,7 +1496,8 @@ static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert) peer_CN = NULL; else { /* convert peer_CN from UTF8 */ - CURLcode rc = Curl_convert_from_utf8(data, peer_CN, strlen(peer_CN)); + CURLcode rc = Curl_convert_from_utf8(data, (char *)peer_CN, + strlen((char *)peer_CN)); /* Curl_convert_from_utf8 calls failf if unsuccessful */ if(rc) { OPENSSL_free(peer_CN); @@ -1337,7 +1543,7 @@ static CURLcode verifystatus(struct connectdata *conn, X509_STORE *st = NULL; STACK_OF(X509) *ch = NULL; - long len = SSL_get_tlsext_status_ocsp_resp(connssl->handle, &p); + long len = SSL_get_tlsext_status_ocsp_resp(BACKEND->handle, &p); if(!p) { failf(data, "No OCSP response received"); @@ -1367,8 +1573,8 @@ static CURLcode verifystatus(struct connectdata *conn, goto end; } - ch = SSL_get_peer_cert_chain(connssl->handle); - st = SSL_CTX_get_cert_store(connssl->ctx); + ch = SSL_get_peer_cert_chain(BACKEND->handle); + st = SSL_CTX_get_cert_store(BACKEND->ctx); #if ((OPENSSL_VERSION_NUMBER <= 0x1000201fL) /* Fixed after 1.0.2a */ || \ (defined(LIBRESSL_VERSION_NUMBER) && \ @@ -1759,7 +1965,7 @@ set_ssl_version_min_max(long *ctx_options, struct connectdata *conn, #ifdef TLS1_3_VERSION { struct ssl_connect_data *connssl = &conn->ssl[sockindex]; - SSL_CTX_set_max_proto_version(connssl->ctx, TLS1_3_VERSION); + SSL_CTX_set_max_proto_version(BACKEND->ctx, TLS1_3_VERSION); *ctx_options |= SSL_OP_NO_TLSv1_2; } #else @@ -1767,6 +1973,7 @@ set_ssl_version_min_max(long *ctx_options, struct connectdata *conn, failf(data, OSSL_PACKAGE " was built without TLS 1.3 support"); return CURLE_NOT_BUILT_IN; #endif + /* FALLTHROUGH */ case CURL_SSLVERSION_TLSv1_2: #if OPENSSL_VERSION_NUMBER >= 0x1000100FL *ctx_options |= SSL_OP_NO_TLSv1_1; @@ -1909,25 +2116,25 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) return CURLE_SSL_CONNECT_ERROR; } - if(connssl->ctx) - SSL_CTX_free(connssl->ctx); - connssl->ctx = SSL_CTX_new(req_method); + if(BACKEND->ctx) + SSL_CTX_free(BACKEND->ctx); + BACKEND->ctx = SSL_CTX_new(req_method); - if(!connssl->ctx) { + if(!BACKEND->ctx) { failf(data, "SSL: couldn't create a context: %s", ossl_strerror(ERR_peek_error(), error_buffer, sizeof(error_buffer))); return CURLE_OUT_OF_MEMORY; } #ifdef SSL_MODE_RELEASE_BUFFERS - SSL_CTX_set_mode(connssl->ctx, SSL_MODE_RELEASE_BUFFERS); + SSL_CTX_set_mode(BACKEND->ctx, SSL_MODE_RELEASE_BUFFERS); #endif #ifdef SSL_CTRL_SET_MSG_CALLBACK if(data->set.fdebug && data->set.verbose) { /* the SSL trace callback is only used for verbose logging */ - SSL_CTX_set_msg_callback(connssl->ctx, ssl_tls_trace); - SSL_CTX_set_msg_callback_arg(connssl->ctx, conn); + SSL_CTX_set_msg_callback(BACKEND->ctx, ssl_tls_trace); + SSL_CTX_set_msg_callback_arg(BACKEND->ctx, conn); } #endif @@ -2044,11 +2251,11 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) return CURLE_SSL_CONNECT_ERROR; } - SSL_CTX_set_options(connssl->ctx, ctx_options); + SSL_CTX_set_options(BACKEND->ctx, ctx_options); #ifdef HAS_NPN if(conn->bits.tls_enable_npn) - SSL_CTX_set_next_proto_select_cb(connssl->ctx, select_next_proto_cb, conn); + SSL_CTX_set_next_proto_select_cb(BACKEND->ctx, select_next_proto_cb, conn); #endif #ifdef HAS_ALPN @@ -2057,7 +2264,8 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) unsigned char protocols[128]; #ifdef USE_NGHTTP2 - if(data->set.httpversion >= CURL_HTTP_VERSION_2) { + if(data->set.httpversion >= CURL_HTTP_VERSION_2 && + (!SSL_IS_PROXY() || !conn->bits.tunnel_proxy)) { protocols[cur++] = NGHTTP2_PROTO_VERSION_ID_LEN; memcpy(&protocols[cur], NGHTTP2_PROTO_VERSION_ID, @@ -2075,12 +2283,12 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) /* expects length prefixed preference ordered list of protocols in wire * format */ - SSL_CTX_set_alpn_protos(connssl->ctx, protocols, cur); + SSL_CTX_set_alpn_protos(BACKEND->ctx, protocols, cur); } #endif if(ssl_cert || ssl_cert_type) { - if(!cert_stuff(conn, connssl->ctx, ssl_cert, ssl_cert_type, + if(!cert_stuff(conn, BACKEND->ctx, ssl_cert, ssl_cert_type, SSL_SET_OPTION(key), SSL_SET_OPTION(key_type), SSL_SET_OPTION(key_passwd))) { /* failf() is already done in cert_stuff() */ @@ -2091,11 +2299,13 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) ciphers = SSL_CONN_CONFIG(cipher_list); if(!ciphers) ciphers = (char *)DEFAULT_CIPHER_SELECTION; - if(!SSL_CTX_set_cipher_list(connssl->ctx, ciphers)) { - failf(data, "failed setting cipher list: %s", ciphers); - return CURLE_SSL_CIPHER; + if(ciphers) { + if(!SSL_CTX_set_cipher_list(BACKEND->ctx, ciphers)) { + failf(data, "failed setting cipher list: %s", ciphers); + return CURLE_SSL_CIPHER; + } + infof(data, "Cipher selection: %s\n", ciphers); } - infof(data, "Cipher selection: %s\n", ciphers); #ifdef USE_TLS_SRP if(ssl_authtype == CURL_TLSAUTH_SRP) { @@ -2103,18 +2313,18 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) infof(data, "Using TLS-SRP username: %s\n", ssl_username); - if(!SSL_CTX_set_srp_username(connssl->ctx, ssl_username)) { + if(!SSL_CTX_set_srp_username(BACKEND->ctx, ssl_username)) { failf(data, "Unable to set SRP user name"); return CURLE_BAD_FUNCTION_ARGUMENT; } - if(!SSL_CTX_set_srp_password(connssl->ctx, SSL_SET_OPTION(password))) { + if(!SSL_CTX_set_srp_password(BACKEND->ctx, SSL_SET_OPTION(password))) { failf(data, "failed setting SRP password"); return CURLE_BAD_FUNCTION_ARGUMENT; } if(!SSL_CONN_CONFIG(cipher_list)) { infof(data, "Setting cipher list SRP\n"); - if(!SSL_CTX_set_cipher_list(connssl->ctx, "SRP")) { + if(!SSL_CTX_set_cipher_list(BACKEND->ctx, "SRP")) { failf(data, "failed setting SRP cipher list"); return CURLE_SSL_CIPHER; } @@ -2125,7 +2335,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) if(ssl_cafile || ssl_capath) { /* tell SSL where to find CA certificates that are used to verify the servers certificate. */ - if(!SSL_CTX_load_verify_locations(connssl->ctx, ssl_cafile, ssl_capath)) { + if(!SSL_CTX_load_verify_locations(BACKEND->ctx, ssl_cafile, ssl_capath)) { if(verifypeer) { /* Fail if we insist on successfully verifying the server. */ failf(data, "error setting certificate verify locations:\n" @@ -2153,14 +2363,14 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) else if(verifypeer) { /* verfying the peer without any CA certificates won't work so use openssl's built in default as fallback */ - SSL_CTX_set_default_verify_paths(connssl->ctx); + SSL_CTX_set_default_verify_paths(BACKEND->ctx); } #endif if(ssl_crlfile) { /* tell SSL where to find CRL file that is used to check certificate * revocation */ - lookup=X509_STORE_add_lookup(SSL_CTX_get_cert_store(connssl->ctx), + lookup = X509_STORE_add_lookup(SSL_CTX_get_cert_store(BACKEND->ctx), X509_LOOKUP_file()); if(!lookup || (!X509_load_crl_file(lookup, ssl_crlfile, X509_FILETYPE_PEM)) ) { @@ -2169,7 +2379,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) } /* Everything is fine. */ infof(data, "successfully load CRL file:\n"); - X509_STORE_set_flags(SSL_CTX_get_cert_store(connssl->ctx), + X509_STORE_set_flags(SSL_CTX_get_cert_store(BACKEND->ctx), X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL); infof(data, " CRLfile: %s\n", ssl_crlfile); @@ -2184,7 +2394,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) */ #if defined(X509_V_FLAG_TRUSTED_FIRST) && !defined(X509_V_FLAG_NO_ALT_CHAINS) if(verifypeer) { - X509_STORE_set_flags(SSL_CTX_get_cert_store(connssl->ctx), + X509_STORE_set_flags(SSL_CTX_get_cert_store(BACKEND->ctx), X509_V_FLAG_TRUSTED_FIRST); } #endif @@ -2193,12 +2403,19 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) * fail to connect if the verification fails, or if it should continue * anyway. In the latter case the result of the verification is checked with * SSL_get_verify_result() below. */ - SSL_CTX_set_verify(connssl->ctx, + SSL_CTX_set_verify(BACKEND->ctx, verifypeer ? SSL_VERIFY_PEER : SSL_VERIFY_NONE, NULL); + /* Enable logging of secrets to the file specified in env SSLKEYLOGFILE. */ +#if defined(ENABLE_SSLKEYLOGFILE) && defined(HAVE_KEYLOG_CALLBACK) + if(keylog_file) { + SSL_CTX_set_keylog_callback(connssl->ctx, ossl_keylog_callback); + } +#endif + /* give application a chance to interfere with SSL set up. */ if(data->set.ssl.fsslctx) { - result = (*data->set.ssl.fsslctx)(data, connssl->ctx, + result = (*data->set.ssl.fsslctx)(data, BACKEND->ctx, data->set.ssl.fsslctxp); if(result) { failf(data, "error signaled by ssl ctx callback"); @@ -2207,10 +2424,10 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) } /* Lets make an SSL structure */ - if(connssl->handle) - SSL_free(connssl->handle); - connssl->handle = SSL_new(connssl->ctx); - if(!connssl->handle) { + if(BACKEND->handle) + SSL_free(BACKEND->handle); + BACKEND->handle = SSL_new(BACKEND->ctx); + if(!BACKEND->handle) { failf(data, "SSL: couldn't create a context (handle)!"); return CURLE_OUT_OF_MEMORY; } @@ -2218,19 +2435,19 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) #if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \ !defined(OPENSSL_NO_OCSP) if(SSL_CONN_CONFIG(verifystatus)) - SSL_set_tlsext_status_type(connssl->handle, TLSEXT_STATUSTYPE_ocsp); + SSL_set_tlsext_status_type(BACKEND->handle, TLSEXT_STATUSTYPE_ocsp); #endif - SSL_set_connect_state(connssl->handle); + SSL_set_connect_state(BACKEND->handle); - connssl->server_cert = 0x0; + BACKEND->server_cert = 0x0; #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME if((0 == Curl_inet_pton(AF_INET, hostname, &addr)) && #ifdef ENABLE_IPV6 (0 == Curl_inet_pton(AF_INET6, hostname, &addr)) && #endif sni && - !SSL_set_tlsext_host_name(connssl->handle, hostname)) + !SSL_set_tlsext_host_name(BACKEND->handle, hostname)) infof(data, "WARNING: failed to configure server name indication (SNI) " "TLS extension\n"); #endif @@ -2242,7 +2459,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) Curl_ssl_sessionid_lock(conn); if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL, sockindex)) { /* we got a session id, use it! */ - if(!SSL_set_session(connssl->handle, ssl_sessionid)) { + if(!SSL_set_session(BACKEND->handle, ssl_sessionid)) { Curl_ssl_sessionid_unlock(conn); failf(data, "SSL: SSL_set_session failed: %s", ossl_strerror(ERR_get_error(), error_buffer, @@ -2257,13 +2474,14 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) if(conn->proxy_ssl[sockindex].use) { BIO *const bio = BIO_new(BIO_f_ssl()); + SSL *handle = conn->proxy_ssl[sockindex].backend->handle; DEBUGASSERT(ssl_connection_complete == conn->proxy_ssl[sockindex].state); - DEBUGASSERT(conn->proxy_ssl[sockindex].handle != NULL); + DEBUGASSERT(handle != NULL); DEBUGASSERT(bio != NULL); - BIO_set_ssl(bio, conn->proxy_ssl[sockindex].handle, FALSE); - SSL_set_bio(connssl->handle, bio, bio); + BIO_set_ssl(bio, handle, FALSE); + SSL_set_bio(BACKEND->handle, bio, bio); } - else if(!SSL_set_fd(connssl->handle, (int)sockfd)) { + else if(!SSL_set_fd(BACKEND->handle, (int)sockfd)) { /* pass the raw socket into the SSL layers */ failf(data, "SSL: SSL_set_fd failed: %s", ossl_strerror(ERR_get_error(), error_buffer, sizeof(error_buffer))); @@ -2288,13 +2506,18 @@ static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex) ERR_clear_error(); - err = SSL_connect(connssl->handle); + err = SSL_connect(BACKEND->handle); + /* If keylogging is enabled but the keylog callback is not supported then log + secrets here, immediately after SSL_connect by using tap_ssl_key. */ +#if defined(ENABLE_SSLKEYLOGFILE) && !defined(HAVE_KEYLOG_CALLBACK) + tap_ssl_key(BACKEND->handle, &BACKEND->tap_state); +#endif /* 1 is fine 0 is "not successful but was shut down controlled" <0 is "handshake was not successful, because a fatal error occurred" */ if(1 != err) { - int detail = SSL_get_error(connssl->handle, err); + int detail = SSL_get_error(BACKEND->handle, err); if(SSL_ERROR_WANT_READ == detail) { connssl->connecting_state = ssl_connect_2_reading; @@ -2328,7 +2551,7 @@ static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex) (reason == SSL_R_CERTIFICATE_VERIFY_FAILED)) { result = CURLE_SSL_CACERT; - lerr = SSL_get_verify_result(connssl->handle); + lerr = SSL_get_verify_result(BACKEND->handle); if(lerr != X509_V_OK) { *certverifyresult = lerr; snprintf(error_buffer, sizeof(error_buffer), @@ -2372,8 +2595,8 @@ static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex) /* Informational message */ infof(data, "SSL connection using %s / %s\n", - get_ssl_version_txt(connssl->handle), - SSL_get_cipher(connssl->handle)); + get_ssl_version_txt(BACKEND->handle), + SSL_get_cipher(BACKEND->handle)); #ifdef HAS_ALPN /* Sets data and len to negotiated protocol, len is 0 if no protocol was @@ -2382,7 +2605,7 @@ static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex) if(conn->bits.tls_enable_alpn) { const unsigned char *neg_protocol; unsigned int len; - SSL_get0_alpn_selected(connssl->handle, &neg_protocol, &len); + SSL_get0_alpn_selected(BACKEND->handle, &neg_protocol, &len); if(len != 0) { infof(data, "ALPN, server accepted to use %.*s\n", len, neg_protocol); @@ -2427,7 +2650,7 @@ static int asn1_object_dump(ASN1_OBJECT *a, char *buf, size_t len) do { \ long info_len = BIO_get_mem_data(mem, &ptr); \ Curl_ssl_push_certinfo_len(data, _num, _label, ptr, info_len); \ - if(1!=BIO_reset(mem)) \ + if(1 != BIO_reset(mem)) \ break; \ } WHILE_FALSE @@ -2475,12 +2698,12 @@ static int X509V3_ext(struct Curl_easy *data, /* no extensions, bail out */ return 1; - for(i=0; i < (int)sk_X509_EXTENSION_num(exts); i++) { + for(i = 0; i < (int)sk_X509_EXTENSION_num(exts); i++) { ASN1_OBJECT *obj; X509_EXTENSION *ext = sk_X509_EXTENSION_value(exts, i); BUF_MEM *biomem; char buf[512]; - char *ptr=buf; + char *ptr = buf; char namebuf[128]; BIO *bio_out = BIO_new(BIO_s_mem()); @@ -2497,16 +2720,16 @@ static int X509V3_ext(struct Curl_easy *data, BIO_get_mem_ptr(bio_out, &biomem); for(j = 0; j < (size_t)biomem->length; j++) { - const char *sep=""; + const char *sep = ""; if(biomem->data[j] == '\n') { - sep=", "; + sep = ", "; j++; /* skip the newline */ }; 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 += snprintf(ptr, sizeof(buf)-(ptr-buf), "%s%c", sep, + biomem->data[j]); } Curl_ssl_push_certinfo(data, certnum, namebuf, buf); @@ -2528,7 +2751,7 @@ static CURLcode get_cert_chain(struct connectdata *conn, int numcerts; BIO *mem; - sk = SSL_get_peer_cert_chain(connssl->handle); + sk = SSL_get_peer_cert_chain(BACKEND->handle); if(!sk) { return CURLE_OUT_OF_MEMORY; } @@ -2545,10 +2768,10 @@ static CURLcode get_cert_chain(struct connectdata *conn, for(i = 0; i < numcerts; i++) { ASN1_INTEGER *num; X509 *x = sk_X509_value(sk, i); - EVP_PKEY *pubkey=NULL; + EVP_PKEY *pubkey = NULL; int j; char *ptr; - CONST_ASN1_BIT_STRING ASN1_BIT_STRING *psig = NULL; + const ASN1_BIT_STRING *psig = NULL; X509_NAME_print_ex(mem, X509_get_subject_name(x), 0, XN_FLAG_ONELINE); push_certinfo("Subject", i); @@ -2818,8 +3041,8 @@ static CURLcode servercert(struct connectdata *conn, /* we've been asked to gather certificate info! */ (void)get_cert_chain(conn, connssl); - connssl->server_cert = SSL_get_peer_certificate(connssl->handle); - if(!connssl->server_cert) { + BACKEND->server_cert = SSL_get_peer_certificate(BACKEND->handle); + if(!BACKEND->server_cert) { BIO_free(mem); if(!strict) return CURLE_OK; @@ -2830,16 +3053,16 @@ static CURLcode servercert(struct connectdata *conn, infof(data, "%s certificate:\n", SSL_IS_PROXY() ? "Proxy" : "Server"); - rc = x509_name_oneline(X509_get_subject_name(connssl->server_cert), + rc = x509_name_oneline(X509_get_subject_name(BACKEND->server_cert), buffer, sizeof(buffer)); infof(data, " subject: %s\n", rc?"[NONE]":buffer); - ASN1_TIME_print(mem, X509_get0_notBefore(connssl->server_cert)); + ASN1_TIME_print(mem, X509_get0_notBefore(BACKEND->server_cert)); len = BIO_get_mem_data(mem, (char **) &ptr); infof(data, " start date: %.*s\n", len, ptr); rc = BIO_reset(mem); - ASN1_TIME_print(mem, X509_get0_notAfter(connssl->server_cert)); + ASN1_TIME_print(mem, X509_get0_notAfter(BACKEND->server_cert)); len = BIO_get_mem_data(mem, (char **) &ptr); infof(data, " expire date: %.*s\n", len, ptr); rc = BIO_reset(mem); @@ -2847,15 +3070,15 @@ static CURLcode servercert(struct connectdata *conn, BIO_free(mem); if(SSL_CONN_CONFIG(verifyhost)) { - result = verifyhost(conn, connssl->server_cert); + result = verifyhost(conn, BACKEND->server_cert); if(result) { - X509_free(connssl->server_cert); - connssl->server_cert = NULL; + X509_free(BACKEND->server_cert); + BACKEND->server_cert = NULL; return result; } } - rc = x509_name_oneline(X509_get_issuer_name(connssl->server_cert), + rc = x509_name_oneline(X509_get_issuer_name(BACKEND->server_cert), buffer, sizeof(buffer)); if(rc) { if(strict) @@ -2875,8 +3098,8 @@ static CURLcode servercert(struct connectdata *conn, if(strict) failf(data, "SSL: Unable to open issuer cert (%s)", SSL_SET_OPTION(issuercert)); - X509_free(connssl->server_cert); - connssl->server_cert = NULL; + X509_free(BACKEND->server_cert); + BACKEND->server_cert = NULL; return CURLE_SSL_ISSUER_ERROR; } @@ -2885,7 +3108,7 @@ static CURLcode servercert(struct connectdata *conn, if(strict) failf(data, "SSL: Unable to read issuer cert (%s)", SSL_SET_OPTION(issuercert)); - X509_free(connssl->server_cert); + X509_free(BACKEND->server_cert); X509_free(issuer); fclose(fp); return CURLE_SSL_ISSUER_ERROR; @@ -2893,13 +3116,13 @@ static CURLcode servercert(struct connectdata *conn, fclose(fp); - if(X509_check_issued(issuer, connssl->server_cert) != X509_V_OK) { + if(X509_check_issued(issuer, BACKEND->server_cert) != X509_V_OK) { if(strict) failf(data, "SSL: Certificate issuer check failed (%s)", SSL_SET_OPTION(issuercert)); - X509_free(connssl->server_cert); + X509_free(BACKEND->server_cert); X509_free(issuer); - connssl->server_cert = NULL; + BACKEND->server_cert = NULL; return CURLE_SSL_ISSUER_ERROR; } @@ -2908,7 +3131,7 @@ static CURLcode servercert(struct connectdata *conn, X509_free(issuer); } - lerr = *certverifyresult = SSL_get_verify_result(connssl->handle); + lerr = *certverifyresult = SSL_get_verify_result(BACKEND->handle); if(*certverifyresult != X509_V_OK) { if(SSL_CONN_CONFIG(verifypeer)) { @@ -2933,8 +3156,8 @@ static CURLcode servercert(struct connectdata *conn, if(SSL_CONN_CONFIG(verifystatus)) { result = verifystatus(conn, connssl); if(result) { - X509_free(connssl->server_cert); - connssl->server_cert = NULL; + X509_free(BACKEND->server_cert); + BACKEND->server_cert = NULL; return result; } } @@ -2947,13 +3170,13 @@ static CURLcode servercert(struct connectdata *conn, ptr = SSL_IS_PROXY() ? data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] : data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]; if(!result && ptr) { - result = pkp_pin_peer_pubkey(data, connssl->server_cert, ptr); + result = pkp_pin_peer_pubkey(data, BACKEND->server_cert, ptr); if(result) failf(data, "SSL: public key does not match pinned public key!"); } - X509_free(connssl->server_cert); - connssl->server_cert = NULL; + X509_free(BACKEND->server_cert); + BACKEND->server_cert = NULL; connssl->connecting_state = ssl_connect_done; return result; @@ -2972,7 +3195,7 @@ static CURLcode ossl_connect_step3(struct connectdata *conn, int sockindex) SSL_SESSION *our_ssl_sessionid; void *old_ssl_sessionid = NULL; - our_ssl_sessionid = SSL_get1_session(connssl->handle); + 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), @@ -3077,9 +3300,9 @@ static CURLcode ossl_connect_common(struct connectdata *conn, if(connssl->connecting_state == ssl_connect_2_reading || connssl->connecting_state == ssl_connect_2_writing) { - curl_socket_t writefd = ssl_connect_2_writing== + curl_socket_t writefd = ssl_connect_2_writing == connssl->connecting_state?sockfd:CURL_SOCKET_BAD; - curl_socket_t readfd = ssl_connect_2_reading== + curl_socket_t readfd = ssl_connect_2_reading == connssl->connecting_state?sockfd:CURL_SOCKET_BAD; what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd, @@ -3137,14 +3360,14 @@ static CURLcode ossl_connect_common(struct connectdata *conn, return CURLE_OK; } -CURLcode Curl_ossl_connect_nonblocking(struct connectdata *conn, - int sockindex, - bool *done) +static CURLcode Curl_ossl_connect_nonblocking(struct connectdata *conn, + int sockindex, + bool *done) { return ossl_connect_common(conn, sockindex, TRUE, done); } -CURLcode Curl_ossl_connect(struct connectdata *conn, int sockindex) +static CURLcode Curl_ossl_connect(struct connectdata *conn, int sockindex) { CURLcode result; bool done = FALSE; @@ -3158,17 +3381,22 @@ CURLcode Curl_ossl_connect(struct connectdata *conn, int sockindex) return CURLE_OK; } -bool Curl_ossl_data_pending(const struct connectdata *conn, int connindex) +static bool Curl_ossl_data_pending(const struct connectdata *conn, + int connindex) { - if(conn->ssl[connindex].handle) + const struct ssl_connect_data *connssl = &conn->ssl[connindex]; + const struct ssl_connect_data *proxyssl = &conn->proxy_ssl[connindex]; + if(BACKEND->handle) /* SSL is in use */ - return (0 != SSL_pending(conn->ssl[connindex].handle) || - (conn->proxy_ssl[connindex].handle && - 0 != SSL_pending(conn->proxy_ssl[connindex].handle))) ? + return (0 != SSL_pending(BACKEND->handle) || + (proxyssl->backend->handle && + 0 != SSL_pending(proxyssl->backend->handle))) ? TRUE : FALSE; return FALSE; } +static size_t Curl_ossl_version(char *buffer, size_t size); + static ssize_t ossl_send(struct connectdata *conn, int sockindex, const void *mem, @@ -3182,14 +3410,15 @@ static ssize_t ossl_send(struct connectdata *conn, unsigned long sslerror; int memlen; int rc; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; ERR_clear_error(); memlen = (len > (size_t)INT_MAX) ? INT_MAX : (int)len; - rc = SSL_write(conn->ssl[sockindex].handle, mem, memlen); + rc = SSL_write(BACKEND->handle, mem, memlen); if(rc <= 0) { - err = SSL_get_error(conn->ssl[sockindex].handle, rc); + err = SSL_get_error(BACKEND->handle, rc); switch(err) { case SSL_ERROR_WANT_READ: @@ -3243,14 +3472,15 @@ static ssize_t ossl_recv(struct connectdata *conn, /* connection data */ unsigned long sslerror; ssize_t nread; int buffsize; + struct ssl_connect_data *connssl = &conn->ssl[num]; ERR_clear_error(); buffsize = (buffersize > (size_t)INT_MAX) ? INT_MAX : (int)buffersize; - nread = (ssize_t)SSL_read(conn->ssl[num].handle, buf, buffsize); + nread = (ssize_t)SSL_read(BACKEND->handle, buf, buffsize); if(nread <= 0) { /* failed SSL_read */ - int err = SSL_get_error(conn->ssl[num].handle, (int)nread); + int err = SSL_get_error(BACKEND->handle, (int)nread); switch(err) { case SSL_ERROR_NONE: /* this is not an error */ @@ -3282,7 +3512,7 @@ static ssize_t ossl_recv(struct connectdata *conn, /* connection data */ return nread; } -size_t Curl_ossl_version(char *buffer, size_t size) +static size_t Curl_ossl_version(char *buffer, size_t size) { #ifdef OPENSSL_IS_BORINGSSL return snprintf(buffer, size, OSSL_PACKAGE); @@ -3291,9 +3521,9 @@ size_t Curl_ossl_version(char *buffer, size_t size) unsigned long ssleay_value; sub[2]='\0'; sub[1]='\0'; - ssleay_value=OpenSSL_version_num(); + ssleay_value = OpenSSL_version_num(); if(ssleay_value < 0x906000) { - ssleay_value=SSLEAY_VERSION_NUMBER; + ssleay_value = SSLEAY_VERSION_NUMBER; sub[0]='\0'; } else { @@ -3322,8 +3552,8 @@ size_t Curl_ossl_version(char *buffer, size_t size) } /* can be called with data == NULL */ -CURLcode Curl_ossl_random(struct Curl_easy *data, unsigned char *entropy, - size_t length) +static CURLcode Curl_ossl_random(struct Curl_easy *data, + unsigned char *entropy, size_t length) { int rc; if(data) { @@ -3339,23 +3569,24 @@ CURLcode Curl_ossl_random(struct Curl_easy *data, unsigned char *entropy, return (rc == 1 ? CURLE_OK : CURLE_FAILED_INIT); } -void Curl_ossl_md5sum(unsigned char *tmp, /* input */ - size_t tmplen, - unsigned char *md5sum /* output */, - size_t unused) +static CURLcode Curl_ossl_md5sum(unsigned char *tmp, /* input */ + size_t tmplen, + unsigned char *md5sum /* output */, + size_t unused) { MD5_CTX MD5pw; (void)unused; MD5_Init(&MD5pw); MD5_Update(&MD5pw, tmp, tmplen); MD5_Final(md5sum, &MD5pw); + return CURLE_OK; } #if (OPENSSL_VERSION_NUMBER >= 0x0090800fL) && !defined(OPENSSL_NO_SHA256) -void Curl_ossl_sha256sum(const unsigned char *tmp, /* input */ - size_t tmplen, - unsigned char *sha256sum /* output */, - size_t unused) +static void Curl_ossl_sha256sum(const unsigned char *tmp, /* input */ + size_t tmplen, + unsigned char *sha256sum /* output */, + size_t unused) { SHA256_CTX SHA256pw; (void)unused; @@ -3365,7 +3596,7 @@ void Curl_ossl_sha256sum(const unsigned char *tmp, /* input */ } #endif -bool Curl_ossl_cert_status_request(void) +static bool Curl_ossl_cert_status_request(void) { #if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \ !defined(OPENSSL_NO_OCSP) @@ -3374,4 +3605,50 @@ bool Curl_ossl_cert_status_request(void) return FALSE; #endif } + +static void *Curl_ossl_get_internals(struct ssl_connect_data *connssl, + CURLINFO info) +{ + /* Legacy: CURLINFO_TLS_SESSION must return an SSL_CTX pointer. */ + return info == CURLINFO_TLS_SESSION ? + (void *)BACKEND->ctx : (void *)BACKEND->handle; +} + +const struct Curl_ssl Curl_ssl_openssl = { + { CURLSSLBACKEND_OPENSSL, "openssl" }, /* info */ + + 1, /* have_ca_path */ + 1, /* have_certinfo */ + 1, /* have_pinnedpubkey */ + 1, /* have_ssl_ctx */ + 1, /* support_https_proxy */ + + sizeof(struct ssl_backend_data), + + Curl_ossl_init, /* init */ + Curl_ossl_cleanup, /* cleanup */ + Curl_ossl_version, /* version */ + Curl_ossl_check_cxn, /* check_cxn */ + Curl_ossl_shutdown, /* shutdown */ + Curl_ossl_data_pending, /* data_pending */ + Curl_ossl_random, /* random */ + Curl_ossl_cert_status_request, /* cert_status_request */ + Curl_ossl_connect, /* connect */ + Curl_ossl_connect_nonblocking, /* connect_nonblocking */ + Curl_ossl_get_internals, /* get_internals */ + Curl_ossl_close, /* close */ + Curl_ossl_close_all, /* close_all */ + Curl_ossl_session_free, /* session_free */ + Curl_ossl_set_engine, /* set_engine */ + Curl_ossl_set_engine_default, /* set_engine_default */ + Curl_ossl_engines_list, /* engines_list */ + Curl_none_false_start, /* false_start */ + Curl_ossl_md5sum, /* md5sum */ +#if (OPENSSL_VERSION_NUMBER >= 0x0090800fL) && !defined(OPENSSL_NO_SHA256) + Curl_ossl_sha256sum /* sha256sum */ +#else + NULL /* sha256sum */ +#endif +}; + #endif /* USE_OPENSSL */ |