summaryrefslogtreecommitdiffstats
path: root/Utilities/cmcurl/lib/vtls
diff options
context:
space:
mode:
Diffstat (limited to 'Utilities/cmcurl/lib/vtls')
-rw-r--r--Utilities/cmcurl/lib/vtls/axtls.c190
-rw-r--r--Utilities/cmcurl/lib/vtls/axtls.h39
-rw-r--r--Utilities/cmcurl/lib/vtls/cyassl.c223
-rw-r--r--Utilities/cmcurl/lib/vtls/cyassl.h63
-rw-r--r--Utilities/cmcurl/lib/vtls/darwinssl.c469
-rw-r--r--Utilities/cmcurl/lib/vtls/darwinssl.h70
-rw-r--r--Utilities/cmcurl/lib/vtls/gskit.c191
-rw-r--r--Utilities/cmcurl/lib/vtls/gskit.h38
-rw-r--r--Utilities/cmcurl/lib/vtls/gtls.c233
-rw-r--r--Utilities/cmcurl/lib/vtls/gtls.h64
-rw-r--r--Utilities/cmcurl/lib/vtls/mbedtls.c237
-rw-r--r--Utilities/cmcurl/lib/vtls/mbedtls.h52
-rw-r--r--Utilities/cmcurl/lib/vtls/nss.c237
-rw-r--r--Utilities/cmcurl/lib/vtls/nssg.h71
-rw-r--r--Utilities/cmcurl/lib/vtls/openssl.c627
-rw-r--r--Utilities/cmcurl/lib/vtls/openssl.h91
-rw-r--r--Utilities/cmcurl/lib/vtls/polarssl.c198
-rw-r--r--Utilities/cmcurl/lib/vtls/polarssl.h52
-rw-r--r--Utilities/cmcurl/lib/vtls/polarssl_threadlock.c4
-rw-r--r--Utilities/cmcurl/lib/vtls/schannel.c532
-rw-r--r--Utilities/cmcurl/lib/vtls/schannel.h89
-rw-r--r--Utilities/cmcurl/lib/vtls/vtls.c501
-rw-r--r--Utilities/cmcurl/lib/vtls/vtls.h82
23 files changed, 2523 insertions, 1830 deletions
diff --git a/Utilities/cmcurl/lib/vtls/axtls.c b/Utilities/cmcurl/lib/vtls/axtls.c
index f0e3766..6b42708 100644
--- a/Utilities/cmcurl/lib/vtls/axtls.c
+++ b/Utilities/cmcurl/lib/vtls/axtls.c
@@ -47,21 +47,12 @@
#include "curl_memory.h"
#include "memdebug.h"
+struct ssl_backend_data {
+ SSL_CTX* ssl_ctx;
+ SSL* ssl;
+};
-/* Global axTLS init, called from Curl_ssl_init() */
-int Curl_axtls_init(void)
-{
-/* axTLS has no global init. Everything is done through SSL and SSL_CTX
- * structs stored in connectdata structure. Perhaps can move to axtls.h.
- */
- return 1;
-}
-
-int Curl_axtls_cleanup(void)
-{
- /* axTLS has no global cleanup. Perhaps can move this to axtls.h. */
- return 1;
-}
+#define BACKEND connssl->backend
static CURLcode map_error_to_curl(int axtls_err)
{
@@ -120,13 +111,13 @@ static Curl_send axtls_send;
static void free_ssl_structs(struct ssl_connect_data *connssl)
{
- if(connssl->ssl) {
- ssl_free(connssl->ssl);
- connssl->ssl = NULL;
+ if(BACKEND->ssl) {
+ ssl_free(BACKEND->ssl);
+ BACKEND->ssl = NULL;
}
- if(connssl->ssl_ctx) {
- ssl_ctx_free(connssl->ssl_ctx);
- connssl->ssl_ctx = NULL;
+ if(BACKEND->ssl_ctx) {
+ ssl_ctx_free(BACKEND->ssl_ctx);
+ BACKEND->ssl_ctx = NULL;
}
}
@@ -137,6 +128,7 @@ static void free_ssl_structs(struct ssl_connect_data *connssl)
*/
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;
@@ -151,7 +143,7 @@ static CURLcode connect_prep(struct connectdata *conn, int sockindex)
SSL_SERVER_VERIFY_LATER |
SSL_CONNECT_IN_PARTS;
- if(conn->ssl[sockindex].state == ssl_connection_complete)
+ if(connssl->state == ssl_connection_complete)
/* to make us tolerant against being called more than once for the
same connection */
return CURLE_OK;
@@ -185,8 +177,8 @@ static CURLcode connect_prep(struct connectdata *conn, int sockindex)
return CURLE_SSL_CONNECT_ERROR;
}
- conn->ssl[sockindex].ssl_ctx = ssl_ctx;
- conn->ssl[sockindex].ssl = NULL;
+ BACKEND->ssl_ctx = ssl_ctx;
+ BACKEND->ssl = NULL;
/* Load the trusted CA cert bundle file */
if(SSL_CONN_CONFIG(CAfile)) {
@@ -212,7 +204,7 @@ static CURLcode connect_prep(struct connectdata *conn, int sockindex)
/* Load client certificate */
if(SSL_SET_OPTION(cert)) {
- i=0;
+ 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],
@@ -236,7 +228,7 @@ static CURLcode connect_prep(struct connectdata *conn, int sockindex)
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;
+ 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],
@@ -281,10 +273,26 @@ static CURLcode connect_prep(struct connectdata *conn, int sockindex)
if(!ssl)
ssl = ssl_client_new(ssl_ctx, conn->sock[sockindex], NULL, 0, NULL);
- conn->ssl[sockindex].ssl = ssl;
+ 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.
@@ -292,7 +300,8 @@ static CURLcode connect_prep(struct connectdata *conn, int sockindex)
static CURLcode connect_finish(struct connectdata *conn, int sockindex)
{
struct Curl_easy *data = conn->data;
- SSL *ssl = conn->ssl[sockindex].ssl;
+ 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;
@@ -387,7 +396,7 @@ static CURLcode connect_finish(struct connectdata *conn, int sockindex)
}
/* General housekeeping */
- conn->ssl[sockindex].state = ssl_connection_complete;
+ connssl->state = ssl_connection_complete;
conn->recv[sockindex] = axtls_recv;
conn->send[sockindex] = axtls_send;
@@ -409,11 +418,10 @@ static CURLcode connect_finish(struct connectdata *conn, int sockindex)
* Use axTLS's non-blocking connection feature to open an SSL connection.
* This is called after a TCP connection is already established.
*/
-CURLcode Curl_axtls_connect_nonblocking(
- struct connectdata *conn,
- int sockindex,
- bool *done)
+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;
@@ -421,23 +429,23 @@ CURLcode Curl_axtls_connect_nonblocking(
*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(conn->ssl[sockindex].connecting_state == ssl_connect_1) {
+ 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;
}
- conn->ssl[sockindex].connecting_state = ssl_connect_2;
+ connssl->connecting_state = ssl_connect_2;
}
- if(conn->ssl[sockindex].connecting_state == ssl_connect_2) {
+ if(connssl->connecting_state == ssl_connect_2) {
/* Check to make sure handshake was ok. */
- if(ssl_handshake_status(conn->ssl[sockindex].ssl) != SSL_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(conn->ssl[sockindex].ssl, NULL);
+ 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. */
@@ -447,10 +455,10 @@ CURLcode Curl_axtls_connect_nonblocking(
}
}
infof(conn->data, "handshake completed successfully\n");
- conn->ssl[sockindex].connecting_state = ssl_connect_3;
+ connssl->connecting_state = ssl_connect_3;
}
- if(conn->ssl[sockindex].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);
@@ -458,15 +466,15 @@ CURLcode Curl_axtls_connect_nonblocking(
}
/* Reset connect state */
- conn->ssl[sockindex].connecting_state = ssl_connect_1;
+ connssl->connecting_state = ssl_connect_1;
*done = TRUE;
return CURLE_OK;
}
/* Unrecognized state. Things are very bad. */
- conn->ssl[sockindex].state = ssl_connection_none;
- conn->ssl[sockindex].connecting_state = ssl_connect_1;
+ 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;
}
@@ -476,15 +484,13 @@ CURLcode Curl_axtls_connect_nonblocking(
* This function is called after the TCP connect has completed. Setup the TLS
* layer and do all necessary magic for a blocking connect.
*/
-CURLcode
-Curl_axtls_connect(struct connectdata *conn,
- int sockindex)
-
+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;
- SSL *ssl = conn->ssl[sockindex].ssl;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ SSL *ssl = BACKEND->ssl;
long timeout_ms;
if(conn_step != CURLE_OK) {
@@ -530,8 +536,9 @@ static ssize_t axtls_send(struct connectdata *conn,
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(conn->ssl[sockindex].ssl, mem, (int)len);
+ int rc = ssl_write(BACKEND->ssl, mem, (int)len);
infof(conn->data, " axtls_send\n");
@@ -544,27 +551,11 @@ static ssize_t axtls_send(struct connectdata *conn,
return rc;
}
-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(connssl->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);
-}
-
/*
* This function is called to shut down the SSL layer but keep the
* socket open (CCC - Clear Command Channel)
*/
-int Curl_axtls_shutdown(struct connectdata *conn, int sockindex)
+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.
@@ -584,17 +575,17 @@ int Curl_axtls_shutdown(struct connectdata *conn, int sockindex)
/* axTLS compat layer does nothing for SSL_shutdown, so we do nothing too
if(data->set.ftp_ccc == CURLFTPSSL_CCC_ACTIVE)
- (void)SSL_shutdown(connssl->ssl);
+ (void)SSL_shutdown(BACKEND->ssl);
*/
- if(connssl->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(connssl->ssl, &buf);
+ nread = (ssize_t)ssl_read(BACKEND->ssl, &buf);
if(nread < SSL_OK) {
failf(data, "close notify alert not received during shutdown");
@@ -630,7 +621,7 @@ static ssize_t axtls_recv(struct connectdata *conn, /* connection data */
*err = CURLE_OK;
if(connssl) {
- ret = ssl_read(connssl->ssl, &read_buf);
+ 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. */
@@ -663,9 +654,10 @@ static ssize_t axtls_recv(struct connectdata *conn, /* connection data */
* 0 means the connection has been closed
* -1 means the connection status is unknown
*/
-int Curl_axtls_check_cxn(struct connectdata *conn)
+static int Curl_axtls_check_cxn(struct connectdata *conn)
{
- /* openssl.c line: rc = SSL_peek(conn->ssl[FIRSTSOCKET].ssl, (void*)&buf, 1);
+ /* 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? */
@@ -673,7 +665,7 @@ int Curl_axtls_check_cxn(struct connectdata *conn)
return 1; /* connection still in place */
}
-void Curl_axtls_session_free(void *ptr)
+static void Curl_axtls_session_free(void *ptr)
{
(void)ptr;
/* free the ID */
@@ -681,14 +673,13 @@ void Curl_axtls_session_free(void *ptr)
compatibility layer does nothing, so we do nothing too. */
}
-size_t Curl_axtls_version(char *buffer, size_t size)
+static size_t Curl_axtls_version(char *buffer, size_t size)
{
return snprintf(buffer, size, "axTLS/%s", ssl_version());
}
-CURLcode Curl_axtls_random(struct Curl_easy *data,
- unsigned char *entropy,
- size_t length)
+static CURLcode Curl_axtls_random(struct Curl_easy *data,
+ unsigned char *entropy, size_t length)
{
static bool ssl_seeded = FALSE;
(void)data;
@@ -703,4 +694,49 @@ CURLcode Curl_axtls_random(struct Curl_easy *data,
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, /* have_ca_path */
+ 0, /* have_certinfo */
+ 0, /* have_pinnedpubkey */
+ 0, /* have_ssl_ctx */
+ 0, /* support_https_proxy */
+
+ 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 */
+ 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
index 53797ea..3f1e129 100644
--- a/Utilities/cmcurl/lib/vtls/axtls.h
+++ b/Utilities/cmcurl/lib/vtls/axtls.h
@@ -27,44 +27,7 @@
#include "curl/curl.h"
#include "urldata.h"
-int Curl_axtls_init(void);
-int Curl_axtls_cleanup(void);
-CURLcode Curl_axtls_connect(struct connectdata *conn, int sockindex);
-CURLcode Curl_axtls_connect_nonblocking(
- struct connectdata *conn,
- int sockindex,
- bool *done);
-
- /* close a SSL connection */
-void Curl_axtls_close(struct connectdata *conn, int sockindex);
-
-void Curl_axtls_session_free(void *ptr);
-size_t Curl_axtls_version(char *buffer, size_t size);
-int Curl_axtls_shutdown(struct connectdata *conn, int sockindex);
-int Curl_axtls_check_cxn(struct connectdata *conn);
-CURLcode Curl_axtls_random(struct Curl_easy *data,
- unsigned char *entropy,
- size_t length);
-
-/* Set the API backend definition to axTLS */
-#define CURL_SSL_BACKEND CURLSSLBACKEND_AXTLS
-
-/* API setup for axTLS */
-#define curlssl_init Curl_axtls_init
-#define curlssl_cleanup Curl_axtls_cleanup
-#define curlssl_connect Curl_axtls_connect
-#define curlssl_connect_nonblocking Curl_axtls_connect_nonblocking
-#define curlssl_session_free(x) Curl_axtls_session_free(x)
-#define curlssl_close_all(x) ((void)x)
-#define curlssl_close Curl_axtls_close
-#define curlssl_shutdown(x,y) Curl_axtls_shutdown(x,y)
-#define curlssl_set_engine(x,y) ((void)x, (void)y, CURLE_NOT_BUILT_IN)
-#define curlssl_set_engine_default(x) ((void)x, CURLE_NOT_BUILT_IN)
-#define curlssl_engines_list(x) ((void)x, (struct curl_slist *)NULL)
-#define curlssl_version Curl_axtls_version
-#define curlssl_check_cxn(x) Curl_axtls_check_cxn(x)
-#define curlssl_data_pending(x,y) ((void)x, (void)y, 0)
-#define curlssl_random(x,y,z) Curl_axtls_random(x,y,z)
+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 01bfdab..ba5ee15 100644
--- a/Utilities/cmcurl/lib/vtls/cyassl.c
+++ b/Utilities/cmcurl/lib/vtls/cyassl.c
@@ -91,6 +91,7 @@ and that's a problem since options.h hasn't been included yet. */
#include "x509asn1.h"
#include "curl_printf.h"
+#include <cyassl/openssl/ssl.h>
#include <cyassl/ssl.h>
#ifdef HAVE_CYASSL_ERROR_SSL_H
#include <cyassl/error-ssl.h>
@@ -110,6 +111,25 @@ and that's a problem since options.h hasn't been included yet. */
#define CYASSL_MAX_ERROR_SZ 80
#endif
+/* KEEP_PEER_CERT is a product of the presence of build time symbol
+ OPENSSL_EXTRA without NO_CERTS, depending on the version. KEEP_PEER_CERT is
+ in wolfSSL's settings.h, and the latter two are build time symbols in
+ options.h. */
+#ifndef KEEP_PEER_CERT
+#if defined(HAVE_CYASSL_GET_PEER_CERTIFICATE) || \
+ defined(HAVE_WOLFSSL_GET_PEER_CERTIFICATE) || \
+ (defined(OPENSSL_EXTRA) && !defined(NO_CERTS))
+#define KEEP_PEER_CERT
+#endif
+#endif
+
+struct ssl_backend_data {
+ SSL_CTX* ctx;
+ SSL* handle;
+};
+
+#define BACKEND connssl->backend
+
static Curl_recv cyassl_recv;
static Curl_send cyassl_send;
@@ -136,7 +156,7 @@ cyassl_connect_step1(struct connectdata *conn,
char error_buffer[CYASSL_MAX_ERROR_SZ];
char *ciphers;
struct Curl_easy *data = conn->data;
- struct ssl_connect_data* conssl = &conn->ssl[sockindex];
+ struct ssl_connect_data* connssl = &conn->ssl[sockindex];
SSL_METHOD* req_method = NULL;
curl_socket_t sockfd = conn->sock[sockindex];
#ifdef HAVE_SNI
@@ -146,7 +166,7 @@ cyassl_connect_step1(struct connectdata *conn,
#define use_sni(x) Curl_nop_stmt
#endif
- if(conssl->state == ssl_connection_complete)
+ if(connssl->state == ssl_connection_complete)
return CURLE_OK;
if(SSL_CONN_CONFIG(version_max) != CURL_SSLVERSION_MAX_NONE) {
@@ -205,11 +225,11 @@ cyassl_connect_step1(struct connectdata *conn,
return CURLE_OUT_OF_MEMORY;
}
- if(conssl->ctx)
- SSL_CTX_free(conssl->ctx);
- conssl->ctx = SSL_CTX_new(req_method);
+ if(BACKEND->ctx)
+ SSL_CTX_free(BACKEND->ctx);
+ BACKEND->ctx = SSL_CTX_new(req_method);
- if(!conssl->ctx) {
+ if(!BACKEND->ctx) {
failf(data, "SSL: couldn't create a context!");
return CURLE_OUT_OF_MEMORY;
}
@@ -225,9 +245,9 @@ cyassl_connect_step1(struct connectdata *conn,
version. We use wolfSSL_CTX_SetMinVersion and not CyaSSL_SetMinVersion
because only the former will work before the user's CTX callback is called.
*/
- if((wolfSSL_CTX_SetMinVersion(conssl->ctx, WOLFSSL_TLSV1) != 1) &&
- (wolfSSL_CTX_SetMinVersion(conssl->ctx, WOLFSSL_TLSV1_1) != 1) &&
- (wolfSSL_CTX_SetMinVersion(conssl->ctx, WOLFSSL_TLSV1_2) != 1)) {
+ if((wolfSSL_CTX_SetMinVersion(BACKEND->ctx, WOLFSSL_TLSV1) != 1) &&
+ (wolfSSL_CTX_SetMinVersion(BACKEND->ctx, WOLFSSL_TLSV1_1) != 1) &&
+ (wolfSSL_CTX_SetMinVersion(BACKEND->ctx, WOLFSSL_TLSV1_2) != 1)) {
failf(data, "SSL: couldn't set the minimum protocol version");
return CURLE_SSL_CONNECT_ERROR;
}
@@ -237,7 +257,7 @@ cyassl_connect_step1(struct connectdata *conn,
ciphers = SSL_CONN_CONFIG(cipher_list);
if(ciphers) {
- if(!SSL_CTX_set_cipher_list(conssl->ctx, ciphers)) {
+ if(!SSL_CTX_set_cipher_list(BACKEND->ctx, ciphers)) {
failf(data, "failed setting cipher list: %s", ciphers);
return CURLE_SSL_CIPHER;
}
@@ -247,7 +267,7 @@ cyassl_connect_step1(struct connectdata *conn,
#ifndef NO_FILESYSTEM
/* load trusted cacert */
if(SSL_CONN_CONFIG(CAfile)) {
- if(1 != SSL_CTX_load_verify_locations(conssl->ctx,
+ if(1 != SSL_CTX_load_verify_locations(BACKEND->ctx,
SSL_CONN_CONFIG(CAfile),
SSL_CONN_CONFIG(CApath))) {
if(SSL_CONN_CONFIG(verifypeer)) {
@@ -284,7 +304,7 @@ cyassl_connect_step1(struct connectdata *conn,
if(SSL_SET_OPTION(cert) && SSL_SET_OPTION(key)) {
int file_type = do_file_type(SSL_SET_OPTION(cert_type));
- if(SSL_CTX_use_certificate_file(conssl->ctx, SSL_SET_OPTION(cert),
+ if(SSL_CTX_use_certificate_file(BACKEND->ctx, SSL_SET_OPTION(cert),
file_type) != 1) {
failf(data, "unable to use client certificate (no key or wrong pass"
" phrase?)");
@@ -292,7 +312,7 @@ cyassl_connect_step1(struct connectdata *conn,
}
file_type = do_file_type(SSL_SET_OPTION(key_type));
- if(SSL_CTX_use_PrivateKey_file(conssl->ctx, SSL_SET_OPTION(key),
+ if(SSL_CTX_use_PrivateKey_file(BACKEND->ctx, SSL_SET_OPTION(key),
file_type) != 1) {
failf(data, "unable to set private key");
return CURLE_SSL_CONNECT_ERROR;
@@ -304,7 +324,7 @@ cyassl_connect_step1(struct connectdata *conn,
* fail to connect if the verification fails, or if it should continue
* anyway. In the latter case the result of the verification is checked with
* SSL_get_verify_result() below. */
- SSL_CTX_set_verify(conssl->ctx,
+ SSL_CTX_set_verify(BACKEND->ctx,
SSL_CONN_CONFIG(verifypeer)?SSL_VERIFY_PEER:
SSL_VERIFY_NONE,
NULL);
@@ -323,7 +343,7 @@ cyassl_connect_step1(struct connectdata *conn,
#ifdef ENABLE_IPV6
(0 == Curl_inet_pton(AF_INET6, hostname, &addr6)) &&
#endif
- (CyaSSL_CTX_UseSNI(conssl->ctx, CYASSL_SNI_HOST_NAME, hostname,
+ (CyaSSL_CTX_UseSNI(BACKEND->ctx, CYASSL_SNI_HOST_NAME, hostname,
(unsigned short)hostname_len) != 1)) {
infof(data, "WARNING: failed to configure server name indication (SNI) "
"TLS extension\n");
@@ -336,15 +356,15 @@ cyassl_connect_step1(struct connectdata *conn,
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(conssl->ctx, 0x17); /* secp256r1 */
- CyaSSL_CTX_UseSupportedCurve(conssl->ctx, 0x19); /* secp521r1 */
- CyaSSL_CTX_UseSupportedCurve(conssl->ctx, 0x18); /* secp384r1 */
+ 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;
- result = (*data->set.ssl.fsslctx)(data, conssl->ctx,
+ result = (*data->set.ssl.fsslctx)(data, BACKEND->ctx,
data->set.ssl.fsslctxp);
if(result) {
failf(data, "error signaled by ssl ctx callback");
@@ -362,10 +382,10 @@ cyassl_connect_step1(struct connectdata *conn,
#endif
/* Let's make an SSL structure */
- if(conssl->handle)
- SSL_free(conssl->handle);
- conssl->handle = SSL_new(conssl->ctx);
- if(!conssl->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;
}
@@ -388,7 +408,7 @@ cyassl_connect_step1(struct connectdata *conn,
strcpy(protocols + strlen(protocols), ALPN_HTTP_1_1);
infof(data, "ALPN, offering %s\n", ALPN_HTTP_1_1);
- if(wolfSSL_UseALPN(conssl->handle, protocols,
+ if(wolfSSL_UseALPN(BACKEND->handle, protocols,
(unsigned)strlen(protocols),
WOLFSSL_ALPN_CONTINUE_ON_MISMATCH) != SSL_SUCCESS) {
failf(data, "SSL: failed setting ALPN protocols");
@@ -404,10 +424,10 @@ cyassl_connect_step1(struct connectdata *conn,
Curl_ssl_sessionid_lock(conn);
if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL, sockindex)) {
/* we got a session id, use it! */
- if(!SSL_set_session(conssl->handle, ssl_sessionid)) {
+ if(!SSL_set_session(BACKEND->handle, ssl_sessionid)) {
Curl_ssl_sessionid_unlock(conn);
failf(data, "SSL: SSL_set_session failed: %s",
- ERR_error_string(SSL_get_error(conssl->handle, 0),
+ ERR_error_string(SSL_get_error(BACKEND->handle, 0),
error_buffer));
return CURLE_SSL_CONNECT_ERROR;
}
@@ -418,12 +438,12 @@ cyassl_connect_step1(struct connectdata *conn,
}
/* pass the raw socket into the SSL layer */
- if(!SSL_set_fd(conssl->handle, (int)sockfd)) {
+ if(!SSL_set_fd(BACKEND->handle, (int)sockfd)) {
failf(data, "SSL: SSL_set_fd failed");
return CURLE_SSL_CONNECT_ERROR;
}
- conssl->connecting_state = ssl_connect_2;
+ connssl->connecting_state = ssl_connect_2;
return CURLE_OK;
}
@@ -434,7 +454,7 @@ cyassl_connect_step2(struct connectdata *conn,
{
int ret = -1;
struct Curl_easy *data = conn->data;
- struct ssl_connect_data* conssl = &conn->ssl[sockindex];
+ struct ssl_connect_data* connssl = &conn->ssl[sockindex];
const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
conn->host.name;
const char * const dispname = SSL_IS_PROXY() ?
@@ -448,22 +468,22 @@ cyassl_connect_step2(struct connectdata *conn,
/* Enable RFC2818 checks */
if(SSL_CONN_CONFIG(verifyhost)) {
- ret = CyaSSL_check_domain_name(conssl->handle, hostname);
+ ret = CyaSSL_check_domain_name(BACKEND->handle, hostname);
if(ret == SSL_FAILURE)
return CURLE_OUT_OF_MEMORY;
}
- ret = SSL_connect(conssl->handle);
+ ret = SSL_connect(BACKEND->handle);
if(ret != 1) {
char error_buffer[CYASSL_MAX_ERROR_SZ];
- int detail = SSL_get_error(conssl->handle, ret);
+ int detail = SSL_get_error(BACKEND->handle, ret);
if(SSL_ERROR_WANT_READ == detail) {
- conssl->connecting_state = ssl_connect_2_reading;
+ connssl->connecting_state = ssl_connect_2_reading;
return CURLE_OK;
}
else if(SSL_ERROR_WANT_WRITE == detail) {
- conssl->connecting_state = ssl_connect_2_writing;
+ connssl->connecting_state = ssl_connect_2_writing;
return CURLE_OK;
}
/* There is no easy way to override only the CN matching.
@@ -524,7 +544,7 @@ cyassl_connect_step2(struct connectdata *conn,
curl_asn1Element *pubkey;
CURLcode result;
- x509 = SSL_get_peer_certificate(conssl->handle);
+ x509 = SSL_get_peer_certificate(BACKEND->handle);
if(!x509) {
failf(data, "SSL: failed retrieving server certificate");
return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
@@ -566,7 +586,7 @@ cyassl_connect_step2(struct connectdata *conn,
char *protocol = NULL;
unsigned short protocol_len = 0;
- rc = wolfSSL_ALPN_GetProtocol(conssl->handle, &protocol, &protocol_len);
+ rc = wolfSSL_ALPN_GetProtocol(BACKEND->handle, &protocol, &protocol_len);
if(rc == SSL_SUCCESS) {
infof(data, "ALPN, server accepted to use %.*s\n", protocol_len,
@@ -595,11 +615,11 @@ cyassl_connect_step2(struct connectdata *conn,
}
#endif /* HAVE_ALPN */
- conssl->connecting_state = ssl_connect_3;
+ connssl->connecting_state = ssl_connect_3;
#if (LIBCYASSL_VERSION_HEX >= 0x03009010)
infof(data, "SSL connection using %s / %s\n",
- wolfSSL_get_version(conssl->handle),
- wolfSSL_get_cipher_name(conssl->handle));
+ wolfSSL_get_version(BACKEND->handle),
+ wolfSSL_get_cipher_name(BACKEND->handle));
#else
infof(data, "SSL connected\n");
#endif
@@ -623,7 +643,7 @@ cyassl_connect_step3(struct connectdata *conn,
SSL_SESSION *our_ssl_sessionid;
void *old_ssl_sessionid = NULL;
- our_ssl_sessionid = SSL_get_session(connssl->handle);
+ our_ssl_sessionid = SSL_get_session(BACKEND->handle);
Curl_ssl_sessionid_lock(conn);
incache = !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL,
@@ -660,12 +680,13 @@ static ssize_t cyassl_send(struct connectdata *conn,
size_t len,
CURLcode *curlcode)
{
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
char error_buffer[CYASSL_MAX_ERROR_SZ];
int memlen = (len > (size_t)INT_MAX) ? INT_MAX : (int)len;
- int rc = SSL_write(conn->ssl[sockindex].handle, mem, memlen);
+ int rc = SSL_write(BACKEND->handle, mem, memlen);
if(rc < 0) {
- int err = SSL_get_error(conn->ssl[sockindex].handle, rc);
+ int err = SSL_get_error(BACKEND->handle, rc);
switch(err) {
case SSL_ERROR_WANT_READ:
@@ -684,18 +705,18 @@ static ssize_t cyassl_send(struct connectdata *conn,
return rc;
}
-void Curl_cyassl_close(struct connectdata *conn, int sockindex)
+static void Curl_cyassl_close(struct connectdata *conn, int sockindex)
{
- struct ssl_connect_data *conssl = &conn->ssl[sockindex];
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- if(conssl->handle) {
- (void)SSL_shutdown(conssl->handle);
- SSL_free(conssl->handle);
- conssl->handle = NULL;
+ if(BACKEND->handle) {
+ (void)SSL_shutdown(BACKEND->handle);
+ SSL_free(BACKEND->handle);
+ BACKEND->handle = NULL;
}
- if(conssl->ctx) {
- SSL_CTX_free(conssl->ctx);
- conssl->ctx = NULL;
+ if(BACKEND->ctx) {
+ SSL_CTX_free(BACKEND->ctx);
+ BACKEND->ctx = NULL;
}
}
@@ -705,12 +726,13 @@ static ssize_t cyassl_recv(struct connectdata *conn,
size_t buffersize,
CURLcode *curlcode)
{
+ struct ssl_connect_data *connssl = &conn->ssl[num];
char error_buffer[CYASSL_MAX_ERROR_SZ];
int buffsize = (buffersize > (size_t)INT_MAX) ? INT_MAX : (int)buffersize;
- int nread = SSL_read(conn->ssl[num].handle, buf, buffsize);
+ int nread = SSL_read(BACKEND->handle, buf, buffsize);
if(nread < 0) {
- int err = SSL_get_error(conn->ssl[num].handle, nread);
+ int err = SSL_get_error(BACKEND->handle, nread);
switch(err) {
case SSL_ERROR_ZERO_RETURN: /* no more data */
@@ -732,14 +754,14 @@ static ssize_t cyassl_recv(struct connectdata *conn,
}
-void Curl_cyassl_session_free(void *ptr)
+static void Curl_cyassl_session_free(void *ptr)
{
(void)ptr;
/* CyaSSL reuses sessions on own, no free */
}
-size_t Curl_cyassl_version(char *buffer, size_t size)
+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());
@@ -753,16 +775,18 @@ size_t Curl_cyassl_version(char *buffer, size_t size)
}
-int Curl_cyassl_init(void)
+static int Curl_cyassl_init(void)
{
return (CyaSSL_Init() == SSL_SUCCESS);
}
-bool Curl_cyassl_data_pending(const struct connectdata* conn, int connindex)
+static bool Curl_cyassl_data_pending(const struct connectdata* conn,
+ int connindex)
{
- if(conn->ssl[connindex].handle) /* SSL is in use */
- return (0 != SSL_pending(conn->ssl[connindex].handle)) ? TRUE : FALSE;
+ const struct ssl_connect_data *connssl = &conn->ssl[connindex];
+ if(BACKEND->handle) /* SSL is in use */
+ return (0 != SSL_pending(BACKEND->handle)) ? TRUE : FALSE;
else
return FALSE;
}
@@ -772,14 +796,14 @@ bool Curl_cyassl_data_pending(const struct connectdata* conn, int connindex)
* This function is called to shut down the SSL layer but keep the
* socket open (CCC - Clear Command Channel)
*/
-int Curl_cyassl_shutdown(struct connectdata *conn, int sockindex)
+static int Curl_cyassl_shutdown(struct connectdata *conn, int sockindex)
{
int retval = 0;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- if(connssl->handle) {
- SSL_free(connssl->handle);
- connssl->handle = NULL;
+ if(BACKEND->handle) {
+ SSL_free(BACKEND->handle);
+ BACKEND->handle = NULL;
}
return retval;
}
@@ -804,7 +828,7 @@ cyassl_connect_common(struct connectdata *conn,
return CURLE_OK;
}
- if(ssl_connect_1==connssl->connecting_state) {
+ if(ssl_connect_1 == connssl->connecting_state) {
/* Find out how much more time we're allowed */
timeout_ms = Curl_timeleft(data, NULL, TRUE);
@@ -836,9 +860,9 @@ cyassl_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,
@@ -899,18 +923,14 @@ cyassl_connect_common(struct connectdata *conn,
}
-CURLcode
-Curl_cyassl_connect_nonblocking(struct connectdata *conn,
- int sockindex,
- bool *done)
+static CURLcode Curl_cyassl_connect_nonblocking(struct connectdata *conn,
+ int sockindex, bool *done)
{
return cyassl_connect_common(conn, sockindex, TRUE, done);
}
-CURLcode
-Curl_cyassl_connect(struct connectdata *conn,
- int sockindex)
+static CURLcode Curl_cyassl_connect(struct connectdata *conn, int sockindex)
{
CURLcode result;
bool done = FALSE;
@@ -924,9 +944,8 @@ Curl_cyassl_connect(struct connectdata *conn,
return CURLE_OK;
}
-CURLcode Curl_cyassl_random(struct Curl_easy *data,
- unsigned char *entropy,
- size_t length)
+static CURLcode Curl_cyassl_random(struct Curl_easy *data,
+ unsigned char *entropy, size_t length)
{
RNG rng;
(void)data;
@@ -939,10 +958,10 @@ CURLcode Curl_cyassl_random(struct Curl_easy *data,
return CURLE_OK;
}
-void Curl_cyassl_sha256sum(const unsigned char *tmp, /* input */
- size_t tmplen,
- unsigned char *sha256sum /* output */,
- size_t unused)
+static void Curl_cyassl_sha256sum(const unsigned char *tmp, /* input */
+ size_t tmplen,
+ unsigned char *sha256sum /* output */,
+ size_t unused)
{
Sha256 SHA256pw;
(void)unused;
@@ -951,4 +970,48 @@ void Curl_cyassl_sha256sum(const unsigned char *tmp, /* input */
Sha256Final(&SHA256pw, sha256sum);
}
+static void *Curl_cyassl_get_internals(struct ssl_connect_data *connssl,
+ CURLINFO info UNUSED_PARAM)
+{
+ (void)info;
+ return BACKEND->handle;
+}
+
+const struct Curl_ssl Curl_ssl_cyassl = {
+ { CURLSSLBACKEND_WOLFSSL, "WolfSSL" }, /* info */
+
+ 0, /* have_ca_path */
+ 0, /* have_certinfo */
+#ifdef KEEP_PEER_CERT
+ 1, /* have_pinnedpubkey */
+#else
+ 0, /* have_pinnedpubkey */
+#endif
+ 1, /* have_ssl_ctx */
+ 0, /* support_https_proxy */
+
+ sizeof(struct ssl_backend_data),
+
+ Curl_cyassl_init, /* init */
+ Curl_none_cleanup, /* cleanup */
+ Curl_cyassl_version, /* version */
+ Curl_none_check_cxn, /* check_cxn */
+ Curl_cyassl_shutdown, /* shutdown */
+ Curl_cyassl_data_pending, /* data_pending */
+ Curl_cyassl_random, /* random */
+ Curl_none_cert_status_request, /* cert_status_request */
+ Curl_cyassl_connect, /* connect */
+ Curl_cyassl_connect_nonblocking, /* connect_nonblocking */
+ Curl_cyassl_get_internals, /* get_internals */
+ Curl_cyassl_close, /* close */
+ Curl_none_close_all, /* close_all */
+ Curl_cyassl_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 */
+ Curl_cyassl_sha256sum /* sha256sum */
+};
+
#endif
diff --git a/Utilities/cmcurl/lib/vtls/cyassl.h b/Utilities/cmcurl/lib/vtls/cyassl.h
index f47719e..01e11cc 100644
--- a/Utilities/cmcurl/lib/vtls/cyassl.h
+++ b/Utilities/cmcurl/lib/vtls/cyassl.h
@@ -25,68 +25,7 @@
#ifdef USE_CYASSL
-/* KEEP_PEER_CERT is a product of the presence of build time symbol
- OPENSSL_EXTRA without NO_CERTS, depending on the version. KEEP_PEER_CERT is
- in wolfSSL's settings.h, and the latter two are build time symbols in
- options.h. */
-#ifndef KEEP_PEER_CERT
-#if defined(HAVE_CYASSL_GET_PEER_CERTIFICATE) || \
- defined(HAVE_WOLFSSL_GET_PEER_CERTIFICATE) || \
- (defined(OPENSSL_EXTRA) && !defined(NO_CERTS))
-#define KEEP_PEER_CERT
-#endif
-#endif
-
-CURLcode Curl_cyassl_connect(struct connectdata *conn, int sockindex);
-bool Curl_cyassl_data_pending(const struct connectdata* conn, int connindex);
-int Curl_cyassl_shutdown(struct connectdata* conn, int sockindex);
-
- /* close a SSL connection */
-void Curl_cyassl_close(struct connectdata *conn, int sockindex);
-
-void Curl_cyassl_session_free(void *ptr);
-size_t Curl_cyassl_version(char *buffer, size_t size);
-int Curl_cyassl_shutdown(struct connectdata *conn, int sockindex);
-int Curl_cyassl_init(void);
-CURLcode Curl_cyassl_connect_nonblocking(struct connectdata *conn,
- int sockindex,
- bool *done);
-CURLcode Curl_cyassl_random(struct Curl_easy *data,
- unsigned char *entropy,
- size_t length);
-void Curl_cyassl_sha256sum(const unsigned char *tmp, /* input */
- size_t tmplen,
- unsigned char *sha256sum, /* output */
- size_t unused);
-
-/* Set the API backend definition to CyaSSL */
-#define CURL_SSL_BACKEND CURLSSLBACKEND_CYASSL
-
-/* this backend supports CURLOPT_SSL_CTX_* */
-#define have_curlssl_ssl_ctx 1
-
-#ifdef KEEP_PEER_CERT
-/* this backend supports CURLOPT_PINNEDPUBLICKEY */
-#define have_curlssl_pinnedpubkey 1
-#endif
-
-/* API setup for CyaSSL */
-#define curlssl_init Curl_cyassl_init
-#define curlssl_cleanup() Curl_nop_stmt
-#define curlssl_connect Curl_cyassl_connect
-#define curlssl_connect_nonblocking Curl_cyassl_connect_nonblocking
-#define curlssl_session_free(x) Curl_cyassl_session_free(x)
-#define curlssl_close_all(x) ((void)x)
-#define curlssl_close Curl_cyassl_close
-#define curlssl_shutdown(x,y) Curl_cyassl_shutdown(x,y)
-#define curlssl_set_engine(x,y) ((void)x, (void)y, CURLE_NOT_BUILT_IN)
-#define curlssl_set_engine_default(x) ((void)x, CURLE_NOT_BUILT_IN)
-#define curlssl_engines_list(x) ((void)x, (struct curl_slist *)NULL)
-#define curlssl_version Curl_cyassl_version
-#define curlssl_check_cxn(x) ((void)x, -1)
-#define curlssl_data_pending(x,y) Curl_cyassl_data_pending(x,y)
-#define curlssl_random(x,y,z) Curl_cyassl_random(x,y,z)
-#define curlssl_sha256sum(a,b,c,d) Curl_cyassl_sha256sum(a,b,c,d)
+extern const struct Curl_ssl Curl_ssl_cyassl;
#endif /* USE_CYASSL */
#endif /* HEADER_CURL_CYASSL_H */
diff --git a/Utilities/cmcurl/lib/vtls/darwinssl.c b/Utilities/cmcurl/lib/vtls/darwinssl.c
index 0417665..a98f433 100644
--- a/Utilities/cmcurl/lib/vtls/darwinssl.c
+++ b/Utilities/cmcurl/lib/vtls/darwinssl.c
@@ -34,11 +34,18 @@
#ifdef USE_DARWINSSL
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wtautological-pointer-compare"
+#endif /* __clang__ */
+
#ifdef HAVE_LIMITS_H
#include <limits.h>
#endif
#include <Security/Security.h>
+/* For some reason, when building for iOS, the omnibus header above does
+ * not include SecureTransport.h as of iOS SDK 5.1. */
#include <Security/SecureTransport.h>
#include <CoreFoundation/CoreFoundation.h>
#include <CommonCrypto/CommonDigest.h>
@@ -113,6 +120,33 @@
#define ioErr -36
#define paramErr -50
+struct ssl_backend_data {
+ SSLContextRef ssl_ctx;
+ curl_socket_t ssl_sockfd;
+ bool ssl_direction; /* true if writing, false if reading */
+ size_t ssl_write_buffered_length;
+};
+
+#define BACKEND connssl->backend
+
+/* pinned public key support tests */
+
+/* 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
+#endif
+
+/* version 2 supports MacOSX 10.7+ */
+#if (!TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070)
+#define DARWIN_SSL_PINNEDPUBKEY_V2 1
+#endif
+
+#if defined(DARWIN_SSL_PINNEDPUBKEY_V1) || defined(DARWIN_SSL_PINNEDPUBKEY_V2)
+/* this backend supports CURLOPT_PINNEDPUBLICKEY */
+#define DARWIN_SSL_PINNEDPUBKEY 1
+#endif /* DARWIN_SSL_PINNEDPUBKEY */
+
#ifdef DARWIN_SSL_PINNEDPUBKEY
/* both new and old APIs return rsa keys missing the spki header (not DER) */
static const unsigned char rsa4096SpkiHeader[] = {
@@ -156,7 +190,7 @@ static OSStatus SocketRead(SSLConnectionRef connection,
UInt8 *currData = (UInt8 *)data;
/*int sock = *(int *)connection;*/
struct ssl_connect_data *connssl = (struct ssl_connect_data *)connection;
- int sock = connssl->ssl_sockfd;
+ int sock = BACKEND->ssl_sockfd;
OSStatus rtn = noErr;
size_t bytesRead;
ssize_t rrtn;
@@ -185,7 +219,7 @@ static OSStatus SocketRead(SSLConnectionRef connection,
break;
case EAGAIN:
rtn = errSSLWouldBlock;
- connssl->ssl_direction = false;
+ BACKEND->ssl_direction = false;
break;
default:
rtn = ioErr;
@@ -216,7 +250,7 @@ static OSStatus SocketWrite(SSLConnectionRef connection,
size_t bytesSent = 0;
/*int sock = *(int *)connection;*/
struct ssl_connect_data *connssl = (struct ssl_connect_data *)connection;
- int sock = connssl->ssl_sockfd;
+ int sock = BACKEND->ssl_sockfd;
ssize_t length;
size_t dataLen = *dataLength;
const UInt8 *dataPtr = (UInt8 *)data;
@@ -236,7 +270,7 @@ static OSStatus SocketWrite(SSLConnectionRef connection,
theErr = errno;
if(theErr == EAGAIN) {
ortn = errSSLWouldBlock;
- connssl->ssl_direction = true;
+ BACKEND->ssl_direction = true;
}
else {
ortn = ioErr;
@@ -844,7 +878,7 @@ CF_INLINE void GetDarwinVersionNumber(int *major, int *minor)
into a string. Some aren't available under iOS or newer cats. So here's
a unified function for getting a string describing the certificate that
ought to work in all cats starting with Leopard. */
-CF_INLINE CFStringRef CopyCertSubject(SecCertificateRef cert)
+CF_INLINE CFStringRef getsubject(SecCertificateRef cert)
{
CFStringRef server_cert_summary = CFSTR("(null)");
@@ -871,6 +905,54 @@ CF_INLINE CFStringRef CopyCertSubject(SecCertificateRef cert)
return server_cert_summary;
}
+static CURLcode CopyCertSubject(struct Curl_easy *data,
+ SecCertificateRef cert, char **certp)
+{
+ CFStringRef c = getsubject(cert);
+ CURLcode result = CURLE_OK;
+ const char *direct;
+ char *cbuf = NULL;
+ *certp = NULL;
+
+ if(!c) {
+ failf(data, "SSL: invalid CA certificate subject");
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ /* If the subject is already available as UTF-8 encoded (ie 'direct') then
+ use that, else convert it. */
+ direct = CFStringGetCStringPtr(c, kCFStringEncodingUTF8);
+ if(direct) {
+ *certp = strdup(direct);
+ if(!*certp) {
+ failf(data, "SSL: out of memory");
+ result = CURLE_OUT_OF_MEMORY;
+ }
+ }
+ else {
+ size_t cbuf_size = ((size_t)CFStringGetLength(c) * 4) + 1;
+ cbuf = calloc(cbuf_size, 1);
+ if(cbuf) {
+ if(!CFStringGetCString(c, cbuf, cbuf_size,
+ kCFStringEncodingUTF8)) {
+ failf(data, "SSL: invalid CA certificate subject");
+ result = CURLE_SSL_CACERT;
+ }
+ else
+ /* pass back the buffer */
+ *certp = cbuf;
+ }
+ else {
+ failf(data, "SSL: couldn't allocate %zu bytes of memory", cbuf_size);
+ result = CURLE_OUT_OF_MEMORY;
+ }
+ }
+ if(result)
+ free(cbuf);
+ CFRelease(c);
+ return result;
+}
+
#if CURL_SUPPORT_MAC_10_6
/* The SecKeychainSearch API was deprecated in Lion, and using it will raise
deprecation warnings, so let's not compile this unless it's necessary: */
@@ -963,7 +1045,7 @@ static OSStatus CopyIdentityWithLabel(char *label,
keys_list_count = CFArrayGetCount(keys_list);
*out_cert_and_key = NULL;
status = 1;
- for(i=0; i<keys_list_count; i++) {
+ for(i = 0; i<keys_list_count; i++) {
OSStatus err = noErr;
SecCertificateRef cert = NULL;
SecIdentityRef identity =
@@ -1075,7 +1157,8 @@ CF_INLINE bool is_file(const char *filename)
}
#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
-static CURLcode darwinssl_version_from_curl(long *darwinver, long ssl_version)
+static CURLcode darwinssl_version_from_curl(SSLProtocol *darwinver,
+ long ssl_version)
{
switch(ssl_version) {
case CURL_SSLVERSION_TLSv1_0:
@@ -1136,30 +1219,30 @@ set_ssl_version_min_max(struct connectdata *conn, int sockindex)
return result;
}
- (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, darwin_ver_min);
- (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, darwin_ver_max);
+ (void)SSLSetProtocolVersionMin(BACKEND->ssl_ctx, darwin_ver_min);
+ (void)SSLSetProtocolVersionMax(BACKEND->ssl_ctx, darwin_ver_max);
return result;
}
else {
#if CURL_SUPPORT_MAC_10_8
long i = ssl_version;
- (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+ (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx,
kSSLProtocolAll,
false);
for(; i <= (ssl_version_max >> 16); i++) {
switch(i) {
case CURL_SSLVERSION_TLSv1_0:
- (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+ (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx,
kTLSProtocol1,
true);
break;
case CURL_SSLVERSION_TLSv1_1:
- (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+ (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx,
kTLSProtocol11,
true);
break;
case CURL_SSLVERSION_TLSv1_2:
- (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+ (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx,
kTLSProtocol12,
true);
break;
@@ -1205,10 +1288,10 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
if(SSLCreateContext != NULL) { /* use the newer API if avaialble */
- if(connssl->ssl_ctx)
- CFRelease(connssl->ssl_ctx);
- connssl->ssl_ctx = SSLCreateContext(NULL, kSSLClientSide, kSSLStreamType);
- if(!connssl->ssl_ctx) {
+ if(BACKEND->ssl_ctx)
+ CFRelease(BACKEND->ssl_ctx);
+ BACKEND->ssl_ctx = SSLCreateContext(NULL, kSSLClientSide, kSSLStreamType);
+ if(!BACKEND->ssl_ctx) {
failf(data, "SSL: couldn't create a context!");
return CURLE_OUT_OF_MEMORY;
}
@@ -1216,9 +1299,9 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
else {
/* The old ST API does not exist under iOS, so don't compile it: */
#if CURL_SUPPORT_MAC_10_8
- if(connssl->ssl_ctx)
- (void)SSLDisposeContext(connssl->ssl_ctx);
- err = SSLNewContext(false, &(connssl->ssl_ctx));
+ if(BACKEND->ssl_ctx)
+ (void)SSLDisposeContext(BACKEND->ssl_ctx);
+ err = SSLNewContext(false, &(BACKEND->ssl_ctx));
if(err != noErr) {
failf(data, "SSL: couldn't create a context: OSStatus %d", err);
return CURLE_OUT_OF_MEMORY;
@@ -1226,15 +1309,15 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
#endif /* CURL_SUPPORT_MAC_10_8 */
}
#else
- if(connssl->ssl_ctx)
- (void)SSLDisposeContext(connssl->ssl_ctx);
- err = SSLNewContext(false, &(connssl->ssl_ctx));
+ if(BACKEND->ssl_ctx)
+ (void)SSLDisposeContext(BACKEND->ssl_ctx);
+ err = SSLNewContext(false, &(BACKEND->ssl_ctx));
if(err != noErr) {
failf(data, "SSL: couldn't create a context: OSStatus %d", err);
return CURLE_OUT_OF_MEMORY;
}
#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
- connssl->ssl_write_buffered_length = 0UL; /* reset buffered write length */
+ BACKEND->ssl_write_buffered_length = 0UL; /* reset buffered write length */
/* check to see if we've been told to use an explicit SSL/TLS version */
#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
@@ -1242,8 +1325,8 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
switch(conn->ssl_config.version) {
case CURL_SSLVERSION_DEFAULT:
case CURL_SSLVERSION_TLSv1:
- (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kTLSProtocol1);
- (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol12);
+ (void)SSLSetProtocolVersionMin(BACKEND->ssl_ctx, kTLSProtocol1);
+ (void)SSLSetProtocolVersionMax(BACKEND->ssl_ctx, kTLSProtocol12);
break;
case CURL_SSLVERSION_TLSv1_0:
case CURL_SSLVERSION_TLSv1_1:
@@ -1256,20 +1339,20 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
break;
}
case CURL_SSLVERSION_SSLv3:
- err = SSLSetProtocolVersionMin(connssl->ssl_ctx, kSSLProtocol3);
+ err = SSLSetProtocolVersionMin(BACKEND->ssl_ctx, kSSLProtocol3);
if(err != noErr) {
failf(data, "Your version of the OS does not support SSLv3");
return CURLE_SSL_CONNECT_ERROR;
}
- (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kSSLProtocol3);
+ (void)SSLSetProtocolVersionMax(BACKEND->ssl_ctx, kSSLProtocol3);
break;
case CURL_SSLVERSION_SSLv2:
- err = SSLSetProtocolVersionMin(connssl->ssl_ctx, kSSLProtocol2);
+ err = SSLSetProtocolVersionMin(BACKEND->ssl_ctx, kSSLProtocol2);
if(err != noErr) {
failf(data, "Your version of the OS does not support SSLv2");
return CURLE_SSL_CONNECT_ERROR;
}
- (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kSSLProtocol2);
+ (void)SSLSetProtocolVersionMax(BACKEND->ssl_ctx, kSSLProtocol2);
break;
default:
failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
@@ -1278,19 +1361,19 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
}
else {
#if CURL_SUPPORT_MAC_10_8
- (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+ (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx,
kSSLProtocolAll,
false);
switch(conn->ssl_config.version) {
case CURL_SSLVERSION_DEFAULT:
case CURL_SSLVERSION_TLSv1:
- (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+ (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx,
kTLSProtocol1,
true);
- (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+ (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx,
kTLSProtocol11,
true);
- (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+ (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx,
kTLSProtocol12,
true);
break;
@@ -1305,7 +1388,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
break;
}
case CURL_SSLVERSION_SSLv3:
- err = SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+ err = SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx,
kSSLProtocol3,
true);
if(err != noErr) {
@@ -1314,7 +1397,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
}
break;
case CURL_SSLVERSION_SSLv2:
- err = SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+ err = SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx,
kSSLProtocol2,
true);
if(err != noErr) {
@@ -1334,12 +1417,12 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
" SSL/TLS version");
return CURLE_SSL_CONNECT_ERROR;
}
- (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, kSSLProtocolAll, false);
+ (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx, kSSLProtocolAll, false);
switch(conn->ssl_config.version) {
case CURL_SSLVERSION_DEFAULT:
case CURL_SSLVERSION_TLSv1:
case CURL_SSLVERSION_TLSv1_0:
- (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+ (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx,
kTLSProtocol1,
true);
break;
@@ -1353,7 +1436,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
failf(data, "Your version of the OS does not support TLSv1.3");
return CURLE_SSL_CONNECT_ERROR;
case CURL_SSLVERSION_SSLv2:
- err = SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+ err = SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx,
kSSLProtocol2,
true);
if(err != noErr) {
@@ -1362,7 +1445,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
}
break;
case CURL_SSLVERSION_SSLv3:
- err = SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+ err = SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx,
kSSLProtocol3,
true);
if(err != noErr) {
@@ -1412,25 +1495,21 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
/* If we found one, print it out: */
err = SecIdentityCopyCertificate(cert_and_key, &cert);
if(err == noErr) {
- CFStringRef cert_summary = CopyCertSubject(cert);
- char cert_summary_c[128];
-
- if(cert_summary) {
- memset(cert_summary_c, 0, 128);
- if(CFStringGetCString(cert_summary,
- cert_summary_c,
- 128,
- kCFStringEncodingUTF8)) {
- infof(data, "Client certificate: %s\n", cert_summary_c);
- }
- CFRelease(cert_summary);
- CFRelease(cert);
+ char *certp;
+ CURLcode result = CopyCertSubject(data, cert, &certp);
+ if(!result) {
+ infof(data, "Client certificate: %s\n", certp);
+ free(certp);
}
+
+ CFRelease(cert);
+ if(result)
+ return result;
}
certs_c[0] = cert_and_key;
certs = CFArrayCreate(NULL, (const void **)certs_c, 1L,
&kCFTypeArrayCallBacks);
- err = SSLSetCertificate(connssl->ssl_ctx, certs);
+ err = SSLSetCertificate(BACKEND->ssl_ctx, certs);
if(certs)
CFRelease(certs);
if(err != noErr) {
@@ -1493,7 +1572,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
if(SSLSetSessionOption != NULL) {
#endif /* CURL_BUILD_MAC */
bool break_on_auth = !conn->ssl_config.verifypeer || ssl_cafile;
- err = SSLSetSessionOption(connssl->ssl_ctx,
+ err = SSLSetSessionOption(BACKEND->ssl_ctx,
kSSLSessionOptionBreakOnServerAuth,
break_on_auth);
if(err != noErr) {
@@ -1503,7 +1582,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
}
else {
#if CURL_SUPPORT_MAC_10_8
- err = SSLSetEnableCertVerify(connssl->ssl_ctx,
+ err = SSLSetEnableCertVerify(BACKEND->ssl_ctx,
conn->ssl_config.verifypeer?true:false);
if(err != noErr) {
failf(data, "SSL: SSLSetEnableCertVerify() failed: OSStatus %d", err);
@@ -1512,7 +1591,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
#endif /* CURL_SUPPORT_MAC_10_8 */
}
#else
- err = SSLSetEnableCertVerify(connssl->ssl_ctx,
+ err = SSLSetEnableCertVerify(BACKEND->ssl_ctx,
conn->ssl_config.verifypeer?true:false);
if(err != noErr) {
failf(data, "SSL: SSLSetEnableCertVerify() failed: OSStatus %d", err);
@@ -1533,7 +1612,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
* Both hostname check and SNI require SSLSetPeerDomainName().
* Also: the verifyhost setting influences SNI usage */
if(conn->ssl_config.verifyhost) {
- err = SSLSetPeerDomainName(connssl->ssl_ctx, hostname,
+ err = SSLSetPeerDomainName(BACKEND->ssl_ctx, hostname,
strlen(hostname));
if(err != noErr) {
@@ -1559,11 +1638,11 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
higher priority, but it's probably better that we not connect at all than
to give the user a false sense of security if the server only supports
insecure ciphers. (Note: We don't care about SSLv2-only ciphers.) */
- (void)SSLGetNumberSupportedCiphers(connssl->ssl_ctx, &all_ciphers_count);
+ (void)SSLGetNumberSupportedCiphers(BACKEND->ssl_ctx, &all_ciphers_count);
all_ciphers = malloc(all_ciphers_count*sizeof(SSLCipherSuite));
allowed_ciphers = malloc(all_ciphers_count*sizeof(SSLCipherSuite));
if(all_ciphers && allowed_ciphers &&
- SSLGetSupportedCiphers(connssl->ssl_ctx, all_ciphers,
+ SSLGetSupportedCiphers(BACKEND->ssl_ctx, all_ciphers,
&all_ciphers_count) == noErr) {
for(i = 0UL ; i < all_ciphers_count ; i++) {
#if CURL_BUILD_MAC
@@ -1645,7 +1724,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
break;
}
}
- err = SSLSetEnabledCiphers(connssl->ssl_ctx, allowed_ciphers,
+ err = SSLSetEnabledCiphers(BACKEND->ssl_ctx, allowed_ciphers,
allowed_ciphers_count);
if(err != noErr) {
failf(data, "SSL: SSLSetEnabledCiphers() failed: OSStatus %d", err);
@@ -1666,9 +1745,9 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
specifically doesn't want us doing that: */
if(SSLSetSessionOption != NULL) {
/* TODO s/data->set.ssl.enable_beast/SSL_SET_OPTION(enable_beast)/g */
- SSLSetSessionOption(connssl->ssl_ctx, kSSLSessionOptionSendOneByteRecord,
+ SSLSetSessionOption(BACKEND->ssl_ctx, kSSLSessionOptionSendOneByteRecord,
!data->set.ssl.enable_beast);
- SSLSetSessionOption(connssl->ssl_ctx, kSSLSessionOptionFalseStart,
+ SSLSetSessionOption(BACKEND->ssl_ctx, kSSLSessionOptionFalseStart,
data->set.ssl.falsestart); /* false start support */
}
#endif /* CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 */
@@ -1682,7 +1761,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
if(!Curl_ssl_getsessionid(conn, (void **)&ssl_sessionid,
&ssl_sessionid_len, sockindex)) {
/* we got a session id, use it! */
- err = SSLSetPeerID(connssl->ssl_ctx, ssl_sessionid, ssl_sessionid_len);
+ err = SSLSetPeerID(BACKEND->ssl_ctx, ssl_sessionid, ssl_sessionid_len);
Curl_ssl_sessionid_unlock(conn);
if(err != noErr) {
failf(data, "SSL: SSLSetPeerID() failed: OSStatus %d", err);
@@ -1700,7 +1779,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
verifypeer, SSL_CONN_CONFIG(verifyhost), hostname, port);
ssl_sessionid_len = strlen(ssl_sessionid);
- err = SSLSetPeerID(connssl->ssl_ctx, ssl_sessionid, ssl_sessionid_len);
+ err = SSLSetPeerID(BACKEND->ssl_ctx, ssl_sessionid, ssl_sessionid_len);
if(err != noErr) {
Curl_ssl_sessionid_unlock(conn);
failf(data, "SSL: SSLSetPeerID() failed: OSStatus %d", err);
@@ -1717,7 +1796,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
}
}
- err = SSLSetIOFuncs(connssl->ssl_ctx, SocketRead, SocketWrite);
+ err = SSLSetIOFuncs(BACKEND->ssl_ctx, SocketRead, SocketWrite);
if(err != noErr) {
failf(data, "SSL: SSLSetIOFuncs() failed: OSStatus %d", err);
return CURLE_SSL_CONNECT_ERROR;
@@ -1727,8 +1806,8 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
/* We need to store the FD in a constant memory address, because
* SSLSetConnection() will not copy that address. I've found that
* conn->sock[sockindex] may change on its own. */
- connssl->ssl_sockfd = sockfd;
- err = SSLSetConnection(connssl->ssl_ctx, connssl);
+ BACKEND->ssl_sockfd = sockfd;
+ err = SSLSetConnection(BACKEND->ssl_ctx, connssl);
if(err != noErr) {
failf(data, "SSL: SSLSetConnection() failed: %d", err);
return CURLE_SSL_CONNECT_ERROR;
@@ -1791,7 +1870,7 @@ static int read_cert(const char *file, unsigned char **out, size_t *outlen)
{
int fd;
ssize_t n, len = 0, cap = 512;
- unsigned char buf[cap], *data;
+ unsigned char buf[512], *data;
fd = open(file, 0);
if(fd < 0)
@@ -1869,6 +1948,8 @@ static int append_cert_to_array(struct Curl_easy *data,
CFMutableArrayRef array)
{
CFDataRef certdata = CFDataCreate(kCFAllocatorDefault, buf, buflen);
+ char *certp;
+ CURLcode result;
if(!certdata) {
failf(data, "SSL: failed to allocate array for CA certificate");
return CURLE_OUT_OF_MEMORY;
@@ -1883,25 +1964,10 @@ static int append_cert_to_array(struct Curl_easy *data,
}
/* Check if cacert is valid. */
- CFStringRef subject = CopyCertSubject(cacert);
- if(subject) {
- char subject_cbuf[128];
- memset(subject_cbuf, 0, 128);
- if(!CFStringGetCString(subject,
- subject_cbuf,
- 128,
- kCFStringEncodingUTF8)) {
- CFRelease(cacert);
- failf(data, "SSL: invalid CA certificate subject");
- return CURLE_SSL_CACERT;
- }
- CFRelease(subject);
- }
- else {
- CFRelease(cacert);
- failf(data, "SSL: invalid CA certificate");
- return CURLE_SSL_CACERT;
- }
+ result = CopyCertSubject(data, cacert, &certp);
+ if(result)
+ return result;
+ free(certp);
CFArrayAppendValue(array, cacert);
CFRelease(cacert);
@@ -2027,12 +2093,13 @@ static int verify_cert(const char *cafile, struct Curl_easy *data,
}
#ifdef DARWIN_SSL_PINNEDPUBKEY
-static CURLcode pkp_pin_peer_pubkey(struct SessionHandle *data,
+static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data,
SSLContextRef ctx,
const char *pinnedpubkey)
{ /* Scratch */
size_t pubkeylen, realpubkeylen, spkiHeaderLength = 24;
- unsigned char *pubkey = NULL, *realpubkey = NULL, *spkiHeader = NULL;
+ unsigned char *pubkey = NULL, *realpubkey = NULL;
+ const unsigned char *spkiHeader = NULL;
CFDataRef publicKeyBits = NULL;
/* Result is returned to caller */
@@ -2075,7 +2142,7 @@ static CURLcode pkp_pin_peer_pubkey(struct SessionHandle *data,
#endif /* DARWIN_SSL_PINNEDPUBKEY_V2 */
pubkeylen = CFDataGetLength(publicKeyBits);
- pubkey = CFDataGetBytePtr(publicKeyBits);
+ pubkey = (unsigned char *)CFDataGetBytePtr(publicKeyBits);
switch(pubkeylen) {
case 526:
@@ -2148,12 +2215,12 @@ darwinssl_connect_step2(struct connectdata *conn, int sockindex)
|| ssl_connect_2_writing == connssl->connecting_state);
/* Here goes nothing: */
- err = SSLHandshake(connssl->ssl_ctx);
+ err = SSLHandshake(BACKEND->ssl_ctx);
if(err != noErr) {
switch(err) {
case errSSLWouldBlock: /* they're not done with us yet */
- connssl->connecting_state = connssl->ssl_direction ?
+ connssl->connecting_state = BACKEND->ssl_direction ?
ssl_connect_2_writing : ssl_connect_2_reading;
return CURLE_OK;
@@ -2162,7 +2229,7 @@ darwinssl_connect_step2(struct connectdata *conn, int sockindex)
case -9841:
if(SSL_CONN_CONFIG(CAfile) && SSL_CONN_CONFIG(verifypeer)) {
int res = verify_cert(SSL_CONN_CONFIG(CAfile), data,
- connssl->ssl_ctx);
+ BACKEND->ssl_ctx);
if(res != CURLE_OK)
return res;
}
@@ -2240,7 +2307,7 @@ darwinssl_connect_step2(struct connectdata *conn, int sockindex)
#ifdef DARWIN_SSL_PINNEDPUBKEY
if(data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]) {
- CURLcode result = pkp_pin_peer_pubkey(data, connssl->ssl_ctx,
+ CURLcode result = pkp_pin_peer_pubkey(data, BACKEND->ssl_ctx,
data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]);
if(result) {
failf(data, "SSL: public key does not match pinned public key!");
@@ -2250,8 +2317,8 @@ darwinssl_connect_step2(struct connectdata *conn, int sockindex)
#endif /* DARWIN_SSL_PINNEDPUBKEY */
/* Informational message */
- (void)SSLGetNegotiatedCipher(connssl->ssl_ctx, &cipher);
- (void)SSLGetNegotiatedProtocolVersion(connssl->ssl_ctx, &protocol);
+ (void)SSLGetNegotiatedCipher(BACKEND->ssl_ctx, &cipher);
+ (void)SSLGetNegotiatedProtocolVersion(BACKEND->ssl_ctx, &protocol);
switch(protocol) {
case kSSLProtocol2:
infof(data, "SSL 2.0 connection using %s\n",
@@ -2292,36 +2359,32 @@ show_verbose_server_cert(struct connectdata *conn,
{
struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- CFStringRef server_cert_summary;
- char server_cert_summary_c[128];
CFArrayRef server_certs = NULL;
SecCertificateRef server_cert;
OSStatus err;
CFIndex i, count;
SecTrustRef trust = NULL;
- if(!connssl->ssl_ctx)
+ if(!BACKEND->ssl_ctx)
return;
#if CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS
#if CURL_BUILD_IOS
#pragma unused(server_certs)
- err = SSLCopyPeerTrust(connssl->ssl_ctx, &trust);
+ err = SSLCopyPeerTrust(BACKEND->ssl_ctx, &trust);
/* For some reason, SSLCopyPeerTrust() can return noErr and yet return
a null trust, so be on guard for that: */
if(err == noErr && trust) {
count = SecTrustGetCertificateCount(trust);
for(i = 0L ; i < count ; i++) {
+ CURLcode result;
+ char *certp;
server_cert = SecTrustGetCertificateAtIndex(trust, i);
- server_cert_summary = CopyCertSubject(server_cert);
- memset(server_cert_summary_c, 0, 128);
- if(CFStringGetCString(server_cert_summary,
- server_cert_summary_c,
- 128,
- kCFStringEncodingUTF8)) {
- infof(data, "Server certificate: %s\n", server_cert_summary_c);
+ result = CopyCertSubject(data, server_cert, &certp);
+ if(!result) {
+ infof(data, "Server certificate: %s\n", certp);
+ free(certp);
}
- CFRelease(server_cert_summary);
}
CFRelease(trust);
}
@@ -2334,45 +2397,40 @@ show_verbose_server_cert(struct connectdata *conn,
Lion or later. */
if(SecTrustEvaluateAsync != NULL) {
#pragma unused(server_certs)
- err = SSLCopyPeerTrust(connssl->ssl_ctx, &trust);
+ err = SSLCopyPeerTrust(BACKEND->ssl_ctx, &trust);
/* For some reason, SSLCopyPeerTrust() can return noErr and yet return
a null trust, so be on guard for that: */
if(err == noErr && trust) {
count = SecTrustGetCertificateCount(trust);
for(i = 0L ; i < count ; i++) {
+ char *certp;
+ CURLcode result;
server_cert = SecTrustGetCertificateAtIndex(trust, i);
- server_cert_summary = CopyCertSubject(server_cert);
- memset(server_cert_summary_c, 0, 128);
- if(CFStringGetCString(server_cert_summary,
- server_cert_summary_c,
- 128,
- kCFStringEncodingUTF8)) {
- infof(data, "Server certificate: %s\n", server_cert_summary_c);
+ result = CopyCertSubject(data, server_cert, &certp);
+ if(!result) {
+ infof(data, "Server certificate: %s\n", certp);
+ free(certp);
}
- CFRelease(server_cert_summary);
}
CFRelease(trust);
}
}
else {
#if CURL_SUPPORT_MAC_10_8
- err = SSLCopyPeerCertificates(connssl->ssl_ctx, &server_certs);
+ err = SSLCopyPeerCertificates(BACKEND->ssl_ctx, &server_certs);
/* Just in case SSLCopyPeerCertificates() returns null too... */
if(err == noErr && server_certs) {
count = CFArrayGetCount(server_certs);
for(i = 0L ; i < count ; i++) {
+ char *certp;
+ CURLcode result;
server_cert = (SecCertificateRef)CFArrayGetValueAtIndex(server_certs,
i);
-
- server_cert_summary = CopyCertSubject(server_cert);
- memset(server_cert_summary_c, 0, 128);
- if(CFStringGetCString(server_cert_summary,
- server_cert_summary_c,
- 128,
- kCFStringEncodingUTF8)) {
- infof(data, "Server certificate: %s\n", server_cert_summary_c);
+ result = CopyCertSubject(data, server_cert, &certp);
+ if(!result) {
+ infof(data, "Server certificate: %s\n", certp);
+ free(certp);
}
- CFRelease(server_cert_summary);
}
CFRelease(server_certs);
}
@@ -2381,20 +2439,18 @@ show_verbose_server_cert(struct connectdata *conn,
#endif /* CURL_BUILD_IOS */
#else
#pragma unused(trust)
- err = SSLCopyPeerCertificates(connssl->ssl_ctx, &server_certs);
+ err = SSLCopyPeerCertificates(BACKEND->ssl_ctx, &server_certs);
if(err == noErr) {
count = CFArrayGetCount(server_certs);
for(i = 0L ; i < count ; i++) {
+ CURLcode result;
+ char *certp;
server_cert = (SecCertificateRef)CFArrayGetValueAtIndex(server_certs, i);
- server_cert_summary = CopyCertSubject(server_cert);
- memset(server_cert_summary_c, 0, 128);
- if(CFStringGetCString(server_cert_summary,
- server_cert_summary_c,
- 128,
- kCFStringEncodingUTF8)) {
- infof(data, "Server certificate: %s\n", server_cert_summary_c);
+ result = CopyCertSubject(data, server_cert, &certp);
+ if(!result) {
+ infof(data, "Server certificate: %s\n", certp);
+ free(certp);
}
- CFRelease(server_cert_summary);
}
CFRelease(server_certs);
}
@@ -2443,7 +2499,7 @@ darwinssl_connect_common(struct connectdata *conn,
return CURLE_OK;
}
- if(ssl_connect_1==connssl->connecting_state) {
+ if(ssl_connect_1 == connssl->connecting_state) {
/* Find out how much more time we're allowed */
timeout_ms = Curl_timeleft(data, NULL, TRUE);
@@ -2538,17 +2594,13 @@ darwinssl_connect_common(struct connectdata *conn,
return CURLE_OK;
}
-CURLcode
-Curl_darwinssl_connect_nonblocking(struct connectdata *conn,
- int sockindex,
- bool *done)
+static CURLcode Curl_darwinssl_connect_nonblocking(struct connectdata *conn,
+ int sockindex, bool *done)
{
return darwinssl_connect_common(conn, sockindex, TRUE, done);
}
-CURLcode
-Curl_darwinssl_connect(struct connectdata *conn,
- int sockindex)
+static CURLcode Curl_darwinssl_connect(struct connectdata *conn, int sockindex)
{
CURLcode result;
bool done = FALSE;
@@ -2563,28 +2615,28 @@ Curl_darwinssl_connect(struct connectdata *conn,
return CURLE_OK;
}
-void Curl_darwinssl_close(struct connectdata *conn, int sockindex)
+static void Curl_darwinssl_close(struct connectdata *conn, int sockindex)
{
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- if(connssl->ssl_ctx) {
- (void)SSLClose(connssl->ssl_ctx);
+ if(BACKEND->ssl_ctx) {
+ (void)SSLClose(BACKEND->ssl_ctx);
#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
if(SSLCreateContext != NULL)
- CFRelease(connssl->ssl_ctx);
+ CFRelease(BACKEND->ssl_ctx);
#if CURL_SUPPORT_MAC_10_8
else
- (void)SSLDisposeContext(connssl->ssl_ctx);
+ (void)SSLDisposeContext(BACKEND->ssl_ctx);
#endif /* CURL_SUPPORT_MAC_10_8 */
#else
- (void)SSLDisposeContext(connssl->ssl_ctx);
+ (void)SSLDisposeContext(BACKEND->ssl_ctx);
#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
- connssl->ssl_ctx = NULL;
+ BACKEND->ssl_ctx = NULL;
}
- connssl->ssl_sockfd = 0;
+ BACKEND->ssl_sockfd = 0;
}
-int Curl_darwinssl_shutdown(struct connectdata *conn, int sockindex)
+static int Curl_darwinssl_shutdown(struct connectdata *conn, int sockindex)
{
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct Curl_easy *data = conn->data;
@@ -2593,7 +2645,7 @@ int Curl_darwinssl_shutdown(struct connectdata *conn, int sockindex)
int rc;
char buf[120];
- if(!connssl->ssl_ctx)
+ if(!BACKEND->ssl_ctx)
return 0;
if(data->set.ftp_ccc != CURLFTPSSL_CCC_ACTIVE)
@@ -2637,7 +2689,7 @@ int Curl_darwinssl_shutdown(struct connectdata *conn, int sockindex)
return rc;
}
-void Curl_darwinssl_session_free(void *ptr)
+static void Curl_darwinssl_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
@@ -2648,7 +2700,7 @@ void Curl_darwinssl_session_free(void *ptr)
Curl_safefree(ptr);
}
-size_t Curl_darwinssl_version(char *buffer, size_t size)
+static size_t Curl_darwinssl_version(char *buffer, size_t size)
{
return snprintf(buffer, size, "SecureTransport");
}
@@ -2661,14 +2713,14 @@ size_t Curl_darwinssl_version(char *buffer, size_t size)
* 0 means the connection has been closed
* -1 means the connection status is unknown
*/
-int Curl_darwinssl_check_cxn(struct connectdata *conn)
+static int Curl_darwinssl_check_cxn(struct connectdata *conn)
{
struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET];
OSStatus err;
SSLSessionState state;
- if(connssl->ssl_ctx) {
- err = SSLGetSessionState(connssl->ssl_ctx, &state);
+ if(BACKEND->ssl_ctx) {
+ err = SSLGetSessionState(BACKEND->ssl_ctx, &state);
if(err == noErr)
return state == kSSLConnected || state == kSSLHandshake;
return -1;
@@ -2676,15 +2728,15 @@ int Curl_darwinssl_check_cxn(struct connectdata *conn)
return 0;
}
-bool Curl_darwinssl_data_pending(const struct connectdata *conn,
- int connindex)
+static bool Curl_darwinssl_data_pending(const struct connectdata *conn,
+ int connindex)
{
const struct ssl_connect_data *connssl = &conn->ssl[connindex];
OSStatus err;
size_t buffer;
- if(connssl->ssl_ctx) { /* SSL is in use */
- err = SSLGetBufferedReadSize(connssl->ssl_ctx, &buffer);
+ if(BACKEND->ssl_ctx) { /* SSL is in use */
+ err = SSLGetBufferedReadSize(BACKEND->ssl_ctx, &buffer);
if(err == noErr)
return buffer > 0UL;
return false;
@@ -2693,14 +2745,16 @@ bool Curl_darwinssl_data_pending(const struct connectdata *conn,
return false;
}
-CURLcode Curl_darwinssl_random(unsigned char *entropy,
- size_t length)
+static CURLcode Curl_darwinssl_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
do this manually for the benefit of the older cats. */
size_t i;
u_int32_t random_number = 0;
+ (void)data;
+
for(i = 0 ; i < length ; i++) {
if(i % sizeof(u_int32_t) == 0)
random_number = arc4random();
@@ -2711,25 +2765,26 @@ CURLcode Curl_darwinssl_random(unsigned char *entropy,
return CURLE_OK;
}
-void Curl_darwinssl_md5sum(unsigned char *tmp, /* input */
- size_t tmplen,
- unsigned char *md5sum, /* output */
- size_t md5len)
+static CURLcode Curl_darwinssl_md5sum(unsigned char *tmp, /* input */
+ size_t tmplen,
+ unsigned char *md5sum, /* output */
+ size_t md5len)
{
(void)md5len;
(void)CC_MD5(tmp, (CC_LONG)tmplen, md5sum);
+ return CURLE_OK;
}
-void Curl_darwinssl_sha256sum(unsigned char *tmp, /* input */
- size_t tmplen,
- unsigned char *sha256sum, /* output */
- size_t sha256len)
+static void Curl_darwinssl_sha256sum(const unsigned char *tmp, /* input */
+ size_t tmplen,
+ unsigned char *sha256sum, /* output */
+ size_t sha256len)
{
- assert(sha256len >= SHA256_DIGEST_LENGTH);
+ assert(sha256len >= CURL_SHA256_DIGEST_LENGTH);
(void)CC_SHA256(tmp, (CC_LONG)tmplen, sha256sum);
}
-bool Curl_darwinssl_false_start(void)
+static bool Curl_darwinssl_false_start(void)
{
#if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7
if(SSLSetSessionOption != NULL)
@@ -2764,15 +2819,15 @@ static ssize_t darwinssl_send(struct connectdata *conn,
over again with no new data until it quits returning errSSLWouldBlock. */
/* Do we have buffered data to write from the last time we were called? */
- if(connssl->ssl_write_buffered_length) {
+ if(BACKEND->ssl_write_buffered_length) {
/* Write the buffered data: */
- err = SSLWrite(connssl->ssl_ctx, NULL, 0UL, &processed);
+ err = SSLWrite(BACKEND->ssl_ctx, NULL, 0UL, &processed);
switch(err) {
case noErr:
/* processed is always going to be 0 because we didn't write to
the buffer, so return how much was written to the socket */
- processed = connssl->ssl_write_buffered_length;
- connssl->ssl_write_buffered_length = 0UL;
+ processed = BACKEND->ssl_write_buffered_length;
+ BACKEND->ssl_write_buffered_length = 0UL;
break;
case errSSLWouldBlock: /* argh, try again */
*curlcode = CURLE_AGAIN;
@@ -2785,13 +2840,13 @@ static ssize_t darwinssl_send(struct connectdata *conn,
}
else {
/* We've got new data to write: */
- err = SSLWrite(connssl->ssl_ctx, mem, len, &processed);
+ err = SSLWrite(BACKEND->ssl_ctx, mem, len, &processed);
if(err != noErr) {
switch(err) {
case errSSLWouldBlock:
/* Data was buffered but not sent, we have to tell the caller
to try sending again, and remember how much was buffered */
- connssl->ssl_write_buffered_length = len;
+ BACKEND->ssl_write_buffered_length = len;
*curlcode = CURLE_AGAIN;
return -1L;
default:
@@ -2813,7 +2868,7 @@ static ssize_t darwinssl_recv(struct connectdata *conn,
/*struct Curl_easy *data = conn->data;*/
struct ssl_connect_data *connssl = &conn->ssl[num];
size_t processed = 0UL;
- OSStatus err = SSLRead(connssl->ssl_ctx, buf, buffersize, &processed);
+ OSStatus err = SSLRead(BACKEND->ssl_ctx, buf, buffersize, &processed);
if(err != noErr) {
switch(err) {
@@ -2844,4 +2899,52 @@ static ssize_t darwinssl_recv(struct connectdata *conn,
return (ssize_t)processed;
}
+static void *Curl_darwinssl_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 */
+
+ 0, /* have_ca_path */
+ 0, /* have_certinfo */
+#ifdef DARWIN_SSL_PINNEDPUBKEY
+ 1, /* have_pinnedpubkey */
+#else
+ 0, /* have_pinnedpubkey */
+#endif /* DARWIN_SSL_PINNEDPUBKEY */
+ 0, /* have_ssl_ctx */
+ 0, /* support_https_proxy */
+
+ 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_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 */
+ Curl_none_close_all, /* close_all */
+ Curl_darwinssl_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 */
+};
+
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+
#endif /* USE_DARWINSSL */
diff --git a/Utilities/cmcurl/lib/vtls/darwinssl.h b/Utilities/cmcurl/lib/vtls/darwinssl.h
index fd372ff..23c7f70 100644
--- a/Utilities/cmcurl/lib/vtls/darwinssl.h
+++ b/Utilities/cmcurl/lib/vtls/darwinssl.h
@@ -26,75 +26,7 @@
#ifdef USE_DARWINSSL
-CURLcode Curl_darwinssl_connect(struct connectdata *conn, int sockindex);
-
-CURLcode Curl_darwinssl_connect_nonblocking(struct connectdata *conn,
- int sockindex,
- bool *done);
-
-/* close a SSL connection */
-void Curl_darwinssl_close(struct connectdata *conn, int sockindex);
-
-void Curl_darwinssl_session_free(void *ptr);
-size_t Curl_darwinssl_version(char *buffer, size_t size);
-int Curl_darwinssl_shutdown(struct connectdata *conn, int sockindex);
-int Curl_darwinssl_check_cxn(struct connectdata *conn);
-bool Curl_darwinssl_data_pending(const struct connectdata *conn,
- int connindex);
-
-CURLcode Curl_darwinssl_random(unsigned char *entropy,
- size_t length);
-void Curl_darwinssl_md5sum(unsigned char *tmp, /* input */
- size_t tmplen,
- unsigned char *md5sum, /* output */
- size_t md5len);
-void Curl_darwinssl_sha256sum(unsigned char *tmp, /* input */
- size_t tmplen,
- unsigned char *sha256sum, /* output */
- size_t sha256len);
-bool Curl_darwinssl_false_start(void);
-
-/* Set the API backend definition to SecureTransport */
-#define CURL_SSL_BACKEND CURLSSLBACKEND_DARWINSSL
-
-/* pinned public key support tests */
-
-/* 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
-#endif
-
-/* version 2 supports MacOSX 10.7+ */
-#if (!TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070)
-#define DARWIN_SSL_PINNEDPUBKEY_V2 1
-#endif
-
-#if defined(DARWIN_SSL_PINNEDPUBKEY_V1) || defined(DARWIN_SSL_PINNEDPUBKEY_V2)
-/* this backend supports CURLOPT_PINNEDPUBLICKEY */
-#define DARWIN_SSL_PINNEDPUBKEY 1
-#define have_curlssl_pinnedpubkey 1
-#endif /* DARWIN_SSL_PINNEDPUBKEY */
-
-/* API setup for SecureTransport */
-#define curlssl_init() (1)
-#define curlssl_cleanup() Curl_nop_stmt
-#define curlssl_connect Curl_darwinssl_connect
-#define curlssl_connect_nonblocking Curl_darwinssl_connect_nonblocking
-#define curlssl_session_free(x) Curl_darwinssl_session_free(x)
-#define curlssl_close_all(x) ((void)x)
-#define curlssl_close Curl_darwinssl_close
-#define curlssl_shutdown(x,y) 0
-#define curlssl_set_engine(x,y) ((void)x, (void)y, CURLE_NOT_BUILT_IN)
-#define curlssl_set_engine_default(x) ((void)x, CURLE_NOT_BUILT_IN)
-#define curlssl_engines_list(x) ((void)x, (struct curl_slist *)NULL)
-#define curlssl_version Curl_darwinssl_version
-#define curlssl_check_cxn Curl_darwinssl_check_cxn
-#define curlssl_data_pending(x,y) Curl_darwinssl_data_pending(x, y)
-#define curlssl_random(x,y,z) ((void)x, Curl_darwinssl_random(y,z))
-#define curlssl_md5sum(a,b,c,d) Curl_darwinssl_md5sum(a,b,c,d)
-#define curlssl_sha256sum(a,b,c,d) Curl_darwinssl_sha256sum(a,b,c,d)
-#define curlssl_false_start() Curl_darwinssl_false_start()
+extern const struct Curl_ssl Curl_ssl_darwinssl;
#endif /* USE_DARWINSSL */
#endif /* HEADER_CURL_DARWINSSL_H */
diff --git a/Utilities/cmcurl/lib/vtls/gskit.c b/Utilities/cmcurl/lib/vtls/gskit.c
index bf75bdd..ba5faef 100644
--- a/Utilities/cmcurl/lib/vtls/gskit.c
+++ b/Utilities/cmcurl/lib/vtls/gskit.c
@@ -98,6 +98,14 @@
#define CURL_GSKPROTO_TLSV12_MASK (1 << CURL_GSKPROTO_TLSV12)
#define CURL_GSKPROTO_LAST 5
+struct ssl_backend_data {
+ gsk_handle handle;
+ int iocport;
+ int localfd;
+ int remotefd;
+};
+
+#define BACKEND connssl->backend
/* Supported ciphers. */
typedef struct {
@@ -427,7 +435,7 @@ static CURLcode set_ciphers(struct connectdata *conn,
}
-int Curl_gskit_init(void)
+static int Curl_gskit_init(void)
{
/* No initialisation needed. */
@@ -435,7 +443,7 @@ int Curl_gskit_init(void)
}
-void Curl_gskit_cleanup(void)
+static void Curl_gskit_cleanup(void)
{
/* Nothing to do. */
}
@@ -495,14 +503,14 @@ static void cancel_async_handshake(struct connectdata *conn, int sockindex)
Qso_OverlappedIO_t cstat;
if(QsoCancelOperation(conn->sock[sockindex], 0) > 0)
- QsoWaitForIOCompletion(connssl->iocport, &cstat, (struct timeval *) NULL);
+ QsoWaitForIOCompletion(BACKEND->iocport, &cstat, (struct timeval *) NULL);
}
static void close_async_handshake(struct ssl_connect_data *connssl)
{
- QsoDestroyIOCompletionPort(connssl->iocport);
- connssl->iocport = -1;
+ QsoDestroyIOCompletionPort(BACKEND->iocport);
+ BACKEND->iocport = -1;
}
/* SSL over SSL
@@ -620,12 +628,12 @@ static int pipe_ssloverssl(struct connectdata *conn, int sockindex,
FD_ZERO(&fds_write);
n = -1;
if(directions & SOS_READ) {
- FD_SET(connssl->remotefd, &fds_write);
- n = connssl->remotefd;
+ FD_SET(BACKEND->remotefd, &fds_write);
+ n = BACKEND->remotefd;
}
if(directions & SOS_WRITE) {
- FD_SET(connssl->remotefd, &fds_read);
- n = connssl->remotefd;
+ FD_SET(BACKEND->remotefd, &fds_read);
+ n = BACKEND->remotefd;
FD_SET(conn->sock[sockindex], &fds_write);
if(n < conn->sock[sockindex])
n = conn->sock[sockindex];
@@ -634,14 +642,15 @@ static int pipe_ssloverssl(struct connectdata *conn, int sockindex,
if(i < 0)
return -1; /* Select error. */
- if(FD_ISSET(connssl->remotefd, &fds_write)) {
+ if(FD_ISSET(BACKEND->remotefd, &fds_write)) {
/* Try getting data from HTTPS proxy and pipe it upstream. */
n = 0;
- i = gsk_secure_soc_read(connproxyssl->handle, buf, sizeof buf, &n);
+ i = gsk_secure_soc_read(connproxyssl->backend->handle,
+ buf, sizeof buf, &n);
switch(i) {
case GSK_OK:
if(n) {
- i = write(connssl->remotefd, buf, n);
+ i = write(BACKEND->remotefd, buf, n);
if(i < 0)
return -1;
ret = 1;
@@ -655,14 +664,14 @@ static int pipe_ssloverssl(struct connectdata *conn, int sockindex,
}
}
- if(FD_ISSET(connssl->remotefd, &fds_read) &&
+ if(FD_ISSET(BACKEND->remotefd, &fds_read) &&
FD_ISSET(conn->sock[sockindex], &fds_write)) {
/* Pipe data to HTTPS proxy. */
- n = read(connssl->remotefd, buf, sizeof buf);
+ n = read(BACKEND->remotefd, buf, sizeof buf);
if(n < 0)
return -1;
if(n) {
- i = gsk_secure_soc_write(connproxyssl->handle, buf, n, &m);
+ i = gsk_secure_soc_write(connproxyssl->backend->handle, buf, n, &m);
if(i != GSK_OK || n != m)
return -1;
ret = 1;
@@ -676,23 +685,23 @@ static int pipe_ssloverssl(struct connectdata *conn, int sockindex,
static void close_one(struct ssl_connect_data *connssl,
struct connectdata *conn, int sockindex)
{
- if(connssl->handle) {
- gskit_status(conn->data, gsk_secure_soc_close(&connssl->handle),
+ if(BACKEND->handle) {
+ gskit_status(conn->data, gsk_secure_soc_close(&BACKEND->handle),
"gsk_secure_soc_close()", 0);
/* Last chance to drain output. */
while(pipe_ssloverssl(conn, sockindex, SOS_WRITE) > 0)
;
- connssl->handle = (gsk_handle) NULL;
- if(connssl->localfd >= 0) {
- close(connssl->localfd);
- connssl->localfd = -1;
+ BACKEND->handle = (gsk_handle) NULL;
+ if(BACKEND->localfd >= 0) {
+ close(BACKEND->localfd);
+ BACKEND->localfd = -1;
}
- if(connssl->remotefd >= 0) {
- close(connssl->remotefd);
- connssl->remotefd = -1;
+ if(BACKEND->remotefd >= 0) {
+ close(BACKEND->remotefd);
+ BACKEND->remotefd = -1;
}
}
- if(connssl->iocport >= 0)
+ if(BACKEND->iocport >= 0)
close_async_handshake(connssl);
}
@@ -700,13 +709,14 @@ static void close_one(struct ssl_connect_data *connssl,
static ssize_t gskit_send(struct connectdata *conn, int sockindex,
const void *mem, size_t len, CURLcode *curlcode)
{
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct Curl_easy *data = conn->data;
CURLcode cc = CURLE_SEND_ERROR;
int written;
if(pipe_ssloverssl(conn, sockindex, SOS_WRITE) >= 0) {
cc = gskit_status(data,
- gsk_secure_soc_write(conn->ssl[sockindex].handle,
+ gsk_secure_soc_write(BACKEND->handle,
(char *) mem, (int) len, &written),
"gsk_secure_soc_write()", CURLE_SEND_ERROR);
if(cc == CURLE_OK)
@@ -724,6 +734,7 @@ static ssize_t gskit_send(struct connectdata *conn, int sockindex,
static ssize_t gskit_recv(struct connectdata *conn, int num, char *buf,
size_t buffersize, CURLcode *curlcode)
{
+ struct ssl_connect_data *connssl = &conn->ssl[num];
struct Curl_easy *data = conn->data;
int buffsize;
int nread;
@@ -731,7 +742,7 @@ static ssize_t gskit_recv(struct connectdata *conn, int num, char *buf,
if(pipe_ssloverssl(conn, num, SOS_READ) >= 0) {
buffsize = buffersize > (size_t) INT_MAX? INT_MAX: (int) buffersize;
- cc = gskit_status(data, gsk_secure_soc_read(conn->ssl[num].handle,
+ cc = gskit_status(data, gsk_secure_soc_read(BACKEND->handle,
buf, buffsize, &nread),
"gsk_secure_soc_read()", CURLE_RECV_ERROR);
}
@@ -806,10 +817,10 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
/* Create SSL environment, start (preferably asynchronous) handshake. */
- connssl->handle = (gsk_handle) NULL;
- connssl->iocport = -1;
- connssl->localfd = -1;
- connssl->remotefd = -1;
+ BACKEND->handle = (gsk_handle) NULL;
+ BACKEND->iocport = -1;
+ BACKEND->localfd = -1;
+ BACKEND->remotefd = -1;
/* GSKit supports two ways of specifying an SSL context: either by
* application identifier (that should have been defined at the system
@@ -842,7 +853,7 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
}
/* Create secure session. */
- result = gskit_status(data, gsk_secure_soc_open(envir, &connssl->handle),
+ result = gskit_status(data, gsk_secure_soc_open(envir, &BACKEND->handle),
"gsk_secure_soc_open()", CURLE_SSL_CONNECT_ERROR);
gsk_environment_close(&envir);
if(result)
@@ -852,18 +863,18 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
if(conn->proxy_ssl[sockindex].use) {
if(inetsocketpair(sockpair))
return CURLE_SSL_CONNECT_ERROR;
- connssl->localfd = sockpair[0];
- connssl->remotefd = sockpair[1];
- setsockopt(connssl->localfd, SOL_SOCKET, SO_RCVBUF,
+ BACKEND->localfd = sockpair[0];
+ BACKEND->remotefd = sockpair[1];
+ setsockopt(BACKEND->localfd, SOL_SOCKET, SO_RCVBUF,
(void *) sobufsize, sizeof sobufsize);
- setsockopt(connssl->remotefd, SOL_SOCKET, SO_RCVBUF,
+ setsockopt(BACKEND->remotefd, SOL_SOCKET, SO_RCVBUF,
(void *) sobufsize, sizeof sobufsize);
- setsockopt(connssl->localfd, SOL_SOCKET, SO_SNDBUF,
+ setsockopt(BACKEND->localfd, SOL_SOCKET, SO_SNDBUF,
(void *) sobufsize, sizeof sobufsize);
- setsockopt(connssl->remotefd, SOL_SOCKET, SO_SNDBUF,
+ setsockopt(BACKEND->remotefd, SOL_SOCKET, SO_SNDBUF,
(void *) sobufsize, sizeof sobufsize);
- curlx_nonblock(connssl->localfd, TRUE);
- curlx_nonblock(connssl->remotefd, TRUE);
+ curlx_nonblock(BACKEND->localfd, TRUE);
+ curlx_nonblock(BACKEND->remotefd, TRUE);
}
/* Determine which SSL/TLS version should be enabled. */
@@ -897,7 +908,7 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
/* Process SNI. Ignore if not supported (on OS400 < V7R1). */
if(sni) {
- result = set_buffer(data, connssl->handle,
+ result = set_buffer(data, BACKEND->handle,
GSK_SSL_EXTN_SERVERNAME_REQUEST, sni, TRUE);
if(result == CURLE_UNSUPPORTED_PROTOCOL)
result = CURLE_OK;
@@ -911,34 +922,34 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
if(timeout < 0)
result = CURLE_OPERATION_TIMEDOUT;
else
- result = set_numeric(data, connssl->handle, GSK_HANDSHAKE_TIMEOUT,
+ result = set_numeric(data, BACKEND->handle, GSK_HANDSHAKE_TIMEOUT,
(timeout + 999) / 1000);
}
if(!result)
- result = set_numeric(data, connssl->handle, GSK_OS400_READ_TIMEOUT, 1);
+ result = set_numeric(data, BACKEND->handle, GSK_OS400_READ_TIMEOUT, 1);
if(!result)
- result = set_numeric(data, connssl->handle, GSK_FD, connssl->localfd >= 0?
- connssl->localfd: conn->sock[sockindex]);
+ result = set_numeric(data, BACKEND->handle, GSK_FD, BACKEND->localfd >= 0?
+ BACKEND->localfd: conn->sock[sockindex]);
if(!result)
- result = set_ciphers(conn, connssl->handle, &protoflags);
+ result = set_ciphers(conn, BACKEND->handle, &protoflags);
if(!protoflags) {
failf(data, "No SSL protocol/cipher combination enabled");
result = CURLE_SSL_CIPHER;
}
if(!result)
- result = set_enum(data, connssl->handle, GSK_PROTOCOL_SSLV2,
+ result = set_enum(data, BACKEND->handle, GSK_PROTOCOL_SSLV2,
(protoflags & CURL_GSKPROTO_SSLV2_MASK)?
GSK_PROTOCOL_SSLV2_ON: GSK_PROTOCOL_SSLV2_OFF, FALSE);
if(!result)
- result = set_enum(data, connssl->handle, GSK_PROTOCOL_SSLV3,
+ result = set_enum(data, BACKEND->handle, GSK_PROTOCOL_SSLV3,
(protoflags & CURL_GSKPROTO_SSLV3_MASK)?
GSK_PROTOCOL_SSLV3_ON: GSK_PROTOCOL_SSLV3_OFF, FALSE);
if(!result)
- result = set_enum(data, connssl->handle, GSK_PROTOCOL_TLSV1,
+ result = set_enum(data, BACKEND->handle, GSK_PROTOCOL_TLSV1,
(protoflags & CURL_GSKPROTO_TLSV10_MASK)?
GSK_PROTOCOL_TLSV1_ON: GSK_PROTOCOL_TLSV1_OFF, FALSE);
if(!result) {
- result = set_enum(data, connssl->handle, GSK_PROTOCOL_TLSV11,
+ result = set_enum(data, BACKEND->handle, GSK_PROTOCOL_TLSV11,
(protoflags & CURL_GSKPROTO_TLSV11_MASK)?
GSK_TRUE: GSK_FALSE, TRUE);
if(result == CURLE_UNSUPPORTED_PROTOCOL) {
@@ -950,7 +961,7 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
}
}
if(!result) {
- result = set_enum(data, connssl->handle, GSK_PROTOCOL_TLSV12,
+ result = set_enum(data, BACKEND->handle, GSK_PROTOCOL_TLSV12,
(protoflags & CURL_GSKPROTO_TLSV12_MASK)?
GSK_TRUE: GSK_FALSE, TRUE);
if(result == CURLE_UNSUPPORTED_PROTOCOL) {
@@ -962,18 +973,18 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
}
}
if(!result)
- result = set_enum(data, connssl->handle, GSK_SERVER_AUTH_TYPE,
+ result = set_enum(data, BACKEND->handle, GSK_SERVER_AUTH_TYPE,
verifypeer? GSK_SERVER_AUTH_FULL:
GSK_SERVER_AUTH_PASSTHRU, FALSE);
if(!result) {
/* Start handshake. Try asynchronous first. */
memset(&commarea, 0, sizeof commarea);
- connssl->iocport = QsoCreateIOCompletionPort();
- if(connssl->iocport != -1) {
+ BACKEND->iocport = QsoCreateIOCompletionPort();
+ if(BACKEND->iocport != -1) {
result = gskit_status(data,
- gsk_secure_soc_startInit(connssl->handle,
- connssl->iocport,
+ gsk_secure_soc_startInit(BACKEND->handle,
+ BACKEND->iocport,
&commarea),
"gsk_secure_soc_startInit()",
CURLE_SSL_CONNECT_ERROR);
@@ -993,7 +1004,7 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
}
else {
/* No more completion port available. Use synchronous IO. */
- result = gskit_status(data, gsk_secure_soc_init(connssl->handle),
+ result = gskit_status(data, gsk_secure_soc_init(BACKEND->handle),
"gsk_secure_soc_init()", CURLE_SSL_CONNECT_ERROR);
if(!result) {
connssl->connecting_state = ssl_connect_3;
@@ -1026,7 +1037,7 @@ static CURLcode gskit_connect_step2(struct connectdata *conn, int sockindex,
timeout_ms = 0;
stmv.tv_sec = timeout_ms / 1000;
stmv.tv_usec = (timeout_ms - stmv.tv_sec * 1000) * 1000;
- switch(QsoWaitForIOCompletion(connssl->iocport, &cstat, &stmv)) {
+ switch(QsoWaitForIOCompletion(BACKEND->iocport, &cstat, &stmv)) {
case 1: /* Operation complete. */
break;
case -1: /* An error occurred: handshake still in progress. */
@@ -1075,7 +1086,7 @@ static CURLcode gskit_connect_step3(struct connectdata *conn, int sockindex)
/* SSL handshake done: gather certificate info and verify host. */
- if(gskit_status(data, gsk_attribute_get_cert_info(connssl->handle,
+ if(gskit_status(data, gsk_attribute_get_cert_info(BACKEND->handle,
GSK_PARTNER_CERT_INFO,
&cdev, &cdec),
"gsk_attribute_get_cert_info()", CURLE_SSL_CONNECT_ERROR) ==
@@ -1216,9 +1227,8 @@ static CURLcode gskit_connect_common(struct connectdata *conn, int sockindex,
}
-CURLcode Curl_gskit_connect_nonblocking(struct connectdata *conn,
- int sockindex,
- bool *done)
+static CURLcode Curl_gskit_connect_nonblocking(struct connectdata *conn,
+ int sockindex, bool *done)
{
CURLcode result;
@@ -1229,7 +1239,7 @@ CURLcode Curl_gskit_connect_nonblocking(struct connectdata *conn,
}
-CURLcode Curl_gskit_connect(struct connectdata *conn, int sockindex)
+static CURLcode Curl_gskit_connect(struct connectdata *conn, int sockindex)
{
CURLcode result;
bool done;
@@ -1245,14 +1255,14 @@ CURLcode Curl_gskit_connect(struct connectdata *conn, int sockindex)
}
-void Curl_gskit_close(struct connectdata *conn, int sockindex)
+static void Curl_gskit_close(struct connectdata *conn, int sockindex)
{
close_one(&conn->ssl[sockindex], conn, sockindex);
close_one(&conn->proxy_ssl[sockindex], conn, sockindex);
}
-int Curl_gskit_shutdown(struct connectdata *conn, int sockindex)
+static int Curl_gskit_shutdown(struct connectdata *conn, int sockindex)
{
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct Curl_easy *data = conn->data;
@@ -1261,7 +1271,7 @@ int Curl_gskit_shutdown(struct connectdata *conn, int sockindex)
int rc;
char buf[120];
- if(!connssl->handle)
+ if(!BACKEND->handle)
return 0;
if(data->set.ftp_ccc != CURLFTPSSL_CCC_ACTIVE)
@@ -1306,21 +1316,22 @@ int Curl_gskit_shutdown(struct connectdata *conn, int sockindex)
}
-size_t Curl_gskit_version(char *buffer, size_t size)
+static size_t Curl_gskit_version(char *buffer, size_t size)
{
strncpy(buffer, "GSKit", size);
return strlen(buffer);
}
-int Curl_gskit_check_cxn(struct connectdata *cxn)
+static int Curl_gskit_check_cxn(struct connectdata *cxn)
{
+ struct ssl_connect_data *connssl = &cxn->ssl[FIRSTSOCKET];
int err;
int errlen;
/* The only thing that can be tested here is at the socket level. */
- if(!cxn->ssl[FIRSTSOCKET].handle)
+ if(!BACKEND->handle)
return 0; /* connection has been closed */
err = 0;
@@ -1334,4 +1345,46 @@ int Curl_gskit_check_cxn(struct connectdata *cxn)
return -1; /* connection status unknown */
}
+static void *Curl_gskit_get_internals(struct ssl_connect_data *connssl,
+ CURLINFO info UNUSED_PARAM)
+{
+ (void)info;
+ return BACKEND->handle;
+}
+
+const struct Curl_ssl Curl_ssl_gskit = {
+ { CURLSSLBACKEND_GSKIT, "gskit" }, /* info */
+
+ 0, /* have_ca_path */
+ 1, /* have_certinfo */
+ 0, /* have_pinnedpubkey */
+ 0, /* have_ssl_ctx */
+ /* TODO: convert to 1 and fix test #1014 (if need) */
+ 0, /* support_https_proxy */
+
+ sizeof(struct ssl_backend_data),
+
+ Curl_gskit_init, /* init */
+ Curl_gskit_cleanup, /* cleanup */
+ Curl_gskit_version, /* version */
+ Curl_gskit_check_cxn, /* check_cxn */
+ Curl_gskit_shutdown, /* shutdown */
+ Curl_none_data_pending, /* data_pending */
+ Curl_none_random, /* random */
+ Curl_none_cert_status_request, /* cert_status_request */
+ Curl_gskit_connect, /* connect */
+ Curl_gskit_connect_nonblocking, /* connect_nonblocking */
+ Curl_gskit_get_internals, /* get_internals */
+ Curl_gskit_close, /* close */
+ Curl_none_close_all, /* close_all */
+ /* No session handling for GSKit */
+ Curl_none_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_GSKIT */
diff --git a/Utilities/cmcurl/lib/vtls/gskit.h b/Utilities/cmcurl/lib/vtls/gskit.h
index 2297592..466ee4d 100644
--- a/Utilities/cmcurl/lib/vtls/gskit.h
+++ b/Utilities/cmcurl/lib/vtls/gskit.h
@@ -30,44 +30,8 @@
#include "urldata.h"
#ifdef USE_GSKIT
-int Curl_gskit_init(void);
-void Curl_gskit_cleanup(void);
-CURLcode Curl_gskit_connect(struct connectdata *conn, int sockindex);
-CURLcode Curl_gskit_connect_nonblocking(struct connectdata *conn,
- int sockindex, bool *done);
-void Curl_gskit_close(struct connectdata *conn, int sockindex);
-int Curl_gskit_shutdown(struct connectdata *conn, int sockindex);
-size_t Curl_gskit_version(char *buffer, size_t size);
-int Curl_gskit_check_cxn(struct connectdata *cxn);
-
-/* Support HTTPS-proxy */
-/* TODO: add '#define HTTPS_PROXY_SUPPORT 1' and fix test #1014 (if need) */
-
-/* Set the API backend definition to GSKit */
-#define CURL_SSL_BACKEND CURLSSLBACKEND_GSKIT
-
-/* this backend supports CURLOPT_CERTINFO */
-#define have_curlssl_certinfo 1
-
-/* API setup for GSKit */
-#define curlssl_init Curl_gskit_init
-#define curlssl_cleanup Curl_gskit_cleanup
-#define curlssl_connect Curl_gskit_connect
-#define curlssl_connect_nonblocking Curl_gskit_connect_nonblocking
-
-/* No session handling for GSKit */
-#define curlssl_session_free(x) Curl_nop_stmt
-#define curlssl_close_all(x) ((void)x)
-#define curlssl_close Curl_gskit_close
-#define curlssl_shutdown(x,y) Curl_gskit_shutdown(x,y)
-#define curlssl_set_engine(x,y) CURLE_NOT_BUILT_IN
-#define curlssl_set_engine_default(x) CURLE_NOT_BUILT_IN
-#define curlssl_engines_list(x) NULL
-#define curlssl_version Curl_gskit_version
-#define curlssl_check_cxn(x) Curl_gskit_check_cxn(x)
-#define curlssl_data_pending(x,y) 0
-#define curlssl_random(x,y,z) (x=x, y=y, z=z, CURLE_NOT_BUILT_IN)
+extern const struct Curl_ssl Curl_ssl_gskit;
#endif /* USE_GSKIT */
diff --git a/Utilities/cmcurl/lib/vtls/gtls.c b/Utilities/cmcurl/lib/vtls/gtls.c
index 844be2d..a844915 100644
--- a/Utilities/cmcurl/lib/vtls/gtls.c
+++ b/Utilities/cmcurl/lib/vtls/gtls.c
@@ -60,15 +60,13 @@
/* The last #include file should be: */
#include "memdebug.h"
-/*
- Some hackish cast macros based on:
- https://developer.gnome.org/glib/unstable/glib-Type-Conversion-Macros.html
-*/
-#ifndef GNUTLS_POINTER_TO_INT_CAST
-#define GNUTLS_POINTER_TO_INT_CAST(p) ((int) (long) (p))
+#ifndef GNUTLS_POINTER_TO_SOCKET_CAST
+#define GNUTLS_POINTER_TO_SOCKET_CAST(p) \
+ ((curl_socket_t) ((char *)(p) - (char *)NULL))
#endif
-#ifndef GNUTLS_INT_TO_POINTER_CAST
-#define GNUTLS_INT_TO_POINTER_CAST(i) ((void *) (long) (i))
+#ifndef GNUTLS_SOCKET_TO_POINTER_CAST
+#define GNUTLS_SOCKET_TO_POINTER_CAST(s) \
+ ((void *) ((char *)NULL + (s)))
#endif
/* Enable GnuTLS debugging by defining GTLSDEBUG */
@@ -109,6 +107,16 @@ static bool gtls_inited = FALSE;
# include <gnutls/ocsp.h>
#endif
+struct ssl_backend_data {
+ gnutls_session_t session;
+ gnutls_certificate_credentials_t cred;
+#ifdef USE_TLS_SRP
+ gnutls_srp_client_credentials_t srp_client_cred;
+#endif
+};
+
+#define BACKEND connssl->backend
+
/*
* Custom push and pull callback functions used by GNU TLS to read and write
* to the socket. These functions are simple wrappers to send() and recv()
@@ -153,7 +161,7 @@ static int gtls_mapped_sockerrno(void)
static ssize_t Curl_gtls_push(void *s, const void *buf, size_t len)
{
- ssize_t ret = swrite(GNUTLS_POINTER_TO_INT_CAST(s), buf, len);
+ ssize_t ret = swrite(GNUTLS_POINTER_TO_SOCKET_CAST(s), buf, len);
#if defined(USE_WINSOCK) && !defined(GNUTLS_MAPS_WINSOCK_ERRORS)
if(ret < 0)
gnutls_transport_set_global_errno(gtls_mapped_sockerrno());
@@ -163,7 +171,7 @@ static ssize_t Curl_gtls_push(void *s, const void *buf, size_t len)
static ssize_t Curl_gtls_pull(void *s, void *buf, size_t len)
{
- ssize_t ret = sread(GNUTLS_POINTER_TO_INT_CAST(s), buf, len);
+ ssize_t ret = sread(GNUTLS_POINTER_TO_SOCKET_CAST(s), buf, len);
#if defined(USE_WINSOCK) && !defined(GNUTLS_MAPS_WINSOCK_ERRORS)
if(ret < 0)
gnutls_transport_set_global_errno(gtls_mapped_sockerrno());
@@ -188,7 +196,7 @@ static ssize_t Curl_gtls_pull_ssl(void *s, void *buf, size_t len)
* must only be called from within curl_global_init() to keep the thread
* situation under control!
*/
-int Curl_gtls_init(void)
+static int Curl_gtls_init(void)
{
int ret = 1;
if(!gtls_inited) {
@@ -202,13 +210,12 @@ int Curl_gtls_init(void)
return ret;
}
-int Curl_gtls_cleanup(void)
+static void Curl_gtls_cleanup(void)
{
if(gtls_inited) {
gnutls_global_deinit();
gtls_inited = FALSE;
}
- return 1;
}
#ifndef CURL_DISABLE_VERBOSE_STRINGS
@@ -279,7 +286,7 @@ static CURLcode handshake(struct connectdata *conn,
{
struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- gnutls_session_t session = conn->ssl[sockindex].session;
+ gnutls_session_t session = BACKEND->session;
curl_socket_t sockfd = conn->sock[sockindex];
time_t timeout_ms;
int rc;
@@ -299,9 +306,9 @@ static CURLcode handshake(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,
@@ -477,6 +484,7 @@ gtls_connect_step1(struct connectdata *conn,
int sockindex)
{
struct Curl_easy *data = conn->data;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
unsigned int init_flags;
gnutls_session_t session;
int rc;
@@ -512,7 +520,7 @@ gtls_connect_step1(struct connectdata *conn,
const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
conn->host.name;
- if(conn->ssl[sockindex].state == ssl_connection_complete)
+ if(connssl->state == ssl_connection_complete)
/* to make us tolerant against being called more than once for the
same connection */
return CURLE_OK;
@@ -528,7 +536,7 @@ gtls_connect_step1(struct connectdata *conn,
sni = FALSE; /* SSLv3 has no SNI */
/* allocate a cred struct */
- rc = gnutls_certificate_allocate_credentials(&conn->ssl[sockindex].cred);
+ rc = gnutls_certificate_allocate_credentials(&BACKEND->cred);
if(rc != GNUTLS_E_SUCCESS) {
failf(data, "gnutls_cert_all_cred() failed: %s", gnutls_strerror(rc));
return CURLE_SSL_CONNECT_ERROR;
@@ -539,15 +547,14 @@ gtls_connect_step1(struct connectdata *conn,
infof(data, "Using TLS-SRP username: %s\n", SSL_SET_OPTION(username));
rc = gnutls_srp_allocate_client_credentials(
- &conn->ssl[sockindex].srp_client_cred);
+ &BACKEND->srp_client_cred);
if(rc != GNUTLS_E_SUCCESS) {
failf(data, "gnutls_srp_allocate_client_cred() failed: %s",
gnutls_strerror(rc));
return CURLE_OUT_OF_MEMORY;
}
- rc = gnutls_srp_set_client_credentials(conn->ssl[sockindex].
- srp_client_cred,
+ rc = gnutls_srp_set_client_credentials(BACKEND->srp_client_cred,
SSL_SET_OPTION(username),
SSL_SET_OPTION(password));
if(rc != GNUTLS_E_SUCCESS) {
@@ -560,10 +567,10 @@ gtls_connect_step1(struct connectdata *conn,
if(SSL_CONN_CONFIG(CAfile)) {
/* set the trusted CA cert bundle file */
- gnutls_certificate_set_verify_flags(conn->ssl[sockindex].cred,
+ gnutls_certificate_set_verify_flags(BACKEND->cred,
GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT);
- rc = gnutls_certificate_set_x509_trust_file(conn->ssl[sockindex].cred,
+ rc = gnutls_certificate_set_x509_trust_file(BACKEND->cred,
SSL_CONN_CONFIG(CAfile),
GNUTLS_X509_FMT_PEM);
if(rc < 0) {
@@ -580,7 +587,7 @@ gtls_connect_step1(struct connectdata *conn,
#ifdef HAS_CAPATH
if(SSL_CONN_CONFIG(CApath)) {
/* set the trusted CA cert directory */
- rc = gnutls_certificate_set_x509_trust_dir(conn->ssl[sockindex].cred,
+ rc = gnutls_certificate_set_x509_trust_dir(BACKEND->cred,
SSL_CONN_CONFIG(CApath),
GNUTLS_X509_FMT_PEM);
if(rc < 0) {
@@ -599,13 +606,13 @@ gtls_connect_step1(struct connectdata *conn,
/* use system ca certificate store as fallback */
if(SSL_CONN_CONFIG(verifypeer) &&
!(SSL_CONN_CONFIG(CAfile) || SSL_CONN_CONFIG(CApath))) {
- gnutls_certificate_set_x509_system_trust(conn->ssl[sockindex].cred);
+ gnutls_certificate_set_x509_system_trust(BACKEND->cred);
}
#endif
if(SSL_SET_OPTION(CRLfile)) {
/* set the CRL list file */
- rc = gnutls_certificate_set_x509_crl_file(conn->ssl[sockindex].cred,
+ rc = gnutls_certificate_set_x509_crl_file(BACKEND->cred,
SSL_SET_OPTION(CRLfile),
GNUTLS_X509_FMT_PEM);
if(rc < 0) {
@@ -626,14 +633,14 @@ gtls_connect_step1(struct connectdata *conn,
init_flags |= GNUTLS_NO_TICKETS;
#endif
- rc = gnutls_init(&conn->ssl[sockindex].session, init_flags);
+ rc = gnutls_init(&BACKEND->session, init_flags);
if(rc != GNUTLS_E_SUCCESS) {
failf(data, "gnutls_init() failed: %d", rc);
return CURLE_SSL_CONNECT_ERROR;
}
/* convenient assign */
- session = conn->ssl[sockindex].session;
+ session = BACKEND->session;
if((0 == Curl_inet_pton(AF_INET, hostname, &addr)) &&
#ifdef ENABLE_IPV6
@@ -763,7 +770,8 @@ gtls_connect_step1(struct connectdata *conn,
gnutls_datum_t protocols[2];
#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].data = (unsigned char *)NGHTTP2_PROTO_VERSION_ID;
protocols[cur].size = NGHTTP2_PROTO_VERSION_ID_LEN;
cur++;
@@ -789,7 +797,7 @@ gtls_connect_step1(struct connectdata *conn,
GNUTLS_PKCS_USE_PBES2_AES_128 | GNUTLS_PKCS_USE_PBES2_AES_192 |
GNUTLS_PKCS_USE_PBES2_AES_256;
rc = gnutls_certificate_set_x509_key_file2(
- conn->ssl[sockindex].cred,
+ BACKEND->cred,
SSL_SET_OPTION(cert),
SSL_SET_OPTION(key) ?
SSL_SET_OPTION(key) : SSL_SET_OPTION(cert),
@@ -809,7 +817,7 @@ gtls_connect_step1(struct connectdata *conn,
}
else {
if(gnutls_certificate_set_x509_key_file(
- conn->ssl[sockindex].cred,
+ BACKEND->cred,
SSL_SET_OPTION(cert),
SSL_SET_OPTION(key) ?
SSL_SET_OPTION(key) : SSL_SET_OPTION(cert),
@@ -825,7 +833,7 @@ gtls_connect_step1(struct connectdata *conn,
/* put the credentials to the current session */
if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP) {
rc = gnutls_credentials_set(session, GNUTLS_CRD_SRP,
- conn->ssl[sockindex].srp_client_cred);
+ BACKEND->srp_client_cred);
if(rc != GNUTLS_E_SUCCESS) {
failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc));
return CURLE_SSL_CONNECT_ERROR;
@@ -835,7 +843,7 @@ gtls_connect_step1(struct connectdata *conn,
#endif
{
rc = gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE,
- conn->ssl[sockindex].cred);
+ BACKEND->cred);
if(rc != GNUTLS_E_SUCCESS) {
failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc));
return CURLE_SSL_CONNECT_ERROR;
@@ -843,13 +851,13 @@ gtls_connect_step1(struct connectdata *conn,
}
if(conn->proxy_ssl[sockindex].use) {
- transport_ptr = conn->proxy_ssl[sockindex].session;
+ transport_ptr = conn->proxy_ssl[sockindex].backend->session;
gnutls_transport_push = Curl_gtls_push_ssl;
gnutls_transport_pull = Curl_gtls_pull_ssl;
}
else {
/* file descriptor for the socket */
- transport_ptr = GNUTLS_INT_TO_POINTER_CAST(conn->sock[sockindex]);
+ transport_ptr = GNUTLS_SOCKET_TO_POINTER_CAST(conn->sock[sockindex]);
gnutls_transport_push = Curl_gtls_push;
gnutls_transport_pull = Curl_gtls_pull;
}
@@ -968,7 +976,8 @@ gtls_connect_step3(struct connectdata *conn,
time_t certclock;
const char *ptr;
struct Curl_easy *data = conn->data;
- gnutls_session_t session = conn->ssl[sockindex].session;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ gnutls_session_t session = BACKEND->session;
int rc;
#ifdef HAS_ALPN
gnutls_datum_t proto;
@@ -1199,7 +1208,7 @@ gtls_connect_step3(struct connectdata *conn,
SSL_SET_OPTION(issuercert)?SSL_SET_OPTION(issuercert):"none");
}
- size=sizeof(certbuf);
+ size = sizeof(certbuf);
rc = gnutls_x509_crt_get_dn_by_oid(x509_cert, GNUTLS_OID_X520_COMMON_NAME,
0, /* the first and only one */
FALSE,
@@ -1239,7 +1248,7 @@ gtls_connect_step3(struct connectdata *conn,
#endif
if(addrlen) {
- for(i=0; ; i++) {
+ for(i = 0; ; i++) {
certaddrlen = sizeof(certaddr);
ret = gnutls_x509_crt_get_subject_alt_name(x509_cert, i, certaddr,
&certaddrlen, NULL);
@@ -1472,7 +1481,7 @@ gtls_connect_common(struct connectdata *conn,
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
/* Initiate the connection, if not already done */
- if(ssl_connect_1==connssl->connecting_state) {
+ if(ssl_connect_1 == connssl->connecting_state) {
rc = gtls_connect_step1(conn, sockindex);
if(rc)
return rc;
@@ -1484,29 +1493,24 @@ gtls_connect_common(struct connectdata *conn,
return rc;
/* Finish connecting once the handshake is done */
- if(ssl_connect_1==connssl->connecting_state) {
+ if(ssl_connect_1 == connssl->connecting_state) {
rc = gtls_connect_step3(conn, sockindex);
if(rc)
return rc;
}
- *done = ssl_connect_1==connssl->connecting_state;
+ *done = ssl_connect_1 == connssl->connecting_state;
return CURLE_OK;
}
-CURLcode
-Curl_gtls_connect_nonblocking(struct connectdata *conn,
- int sockindex,
- bool *done)
+static CURLcode Curl_gtls_connect_nonblocking(struct connectdata *conn,
+ int sockindex, bool *done)
{
return gtls_connect_common(conn, sockindex, TRUE, done);
}
-CURLcode
-Curl_gtls_connect(struct connectdata *conn,
- int sockindex)
-
+static CURLcode Curl_gtls_connect(struct connectdata *conn, int sockindex)
{
CURLcode result;
bool done = FALSE;
@@ -1520,15 +1524,18 @@ Curl_gtls_connect(struct connectdata *conn,
return CURLE_OK;
}
-bool Curl_gtls_data_pending(const struct connectdata *conn, int connindex)
+static bool Curl_gtls_data_pending(const struct connectdata *conn,
+ int connindex)
{
+ const struct ssl_connect_data *connssl = &conn->ssl[connindex];
bool res = FALSE;
- if(conn->ssl[connindex].session &&
- 0 != gnutls_record_check_pending(conn->ssl[connindex].session))
+ if(BACKEND->session &&
+ 0 != gnutls_record_check_pending(BACKEND->session))
res = TRUE;
- if(conn->proxy_ssl[connindex].session &&
- 0 != gnutls_record_check_pending(conn->proxy_ssl[connindex].session))
+ connssl = &conn->proxy_ssl[connindex];
+ if(BACKEND->session &&
+ 0 != gnutls_record_check_pending(BACKEND->session))
res = TRUE;
return res;
@@ -1540,7 +1547,8 @@ static ssize_t gtls_send(struct connectdata *conn,
size_t len,
CURLcode *curlcode)
{
- ssize_t rc = gnutls_record_send(conn->ssl[sockindex].session, mem, len);
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ ssize_t rc = gnutls_record_send(BACKEND->session, mem, len);
if(rc < 0) {
*curlcode = (rc == GNUTLS_E_AGAIN)
@@ -1553,26 +1561,26 @@ static ssize_t gtls_send(struct connectdata *conn,
return rc;
}
-static void close_one(struct ssl_connect_data *ssl)
+static void close_one(struct ssl_connect_data *connssl)
{
- if(ssl->session) {
- gnutls_bye(ssl->session, GNUTLS_SHUT_RDWR);
- gnutls_deinit(ssl->session);
- ssl->session = NULL;
+ if(BACKEND->session) {
+ gnutls_bye(BACKEND->session, GNUTLS_SHUT_RDWR);
+ gnutls_deinit(BACKEND->session);
+ BACKEND->session = NULL;
}
- if(ssl->cred) {
- gnutls_certificate_free_credentials(ssl->cred);
- ssl->cred = NULL;
+ if(BACKEND->cred) {
+ gnutls_certificate_free_credentials(BACKEND->cred);
+ BACKEND->cred = NULL;
}
#ifdef USE_TLS_SRP
- if(ssl->srp_client_cred) {
- gnutls_srp_free_client_credentials(ssl->srp_client_cred);
- ssl->srp_client_cred = NULL;
+ if(BACKEND->srp_client_cred) {
+ gnutls_srp_free_client_credentials(BACKEND->srp_client_cred);
+ BACKEND->srp_client_cred = NULL;
}
#endif
}
-void Curl_gtls_close(struct connectdata *conn, int sockindex)
+static void Curl_gtls_close(struct connectdata *conn, int sockindex)
{
close_one(&conn->ssl[sockindex]);
close_one(&conn->proxy_ssl[sockindex]);
@@ -1582,8 +1590,9 @@ void Curl_gtls_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_gtls_shutdown(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;
@@ -1596,16 +1605,16 @@ int Curl_gtls_shutdown(struct connectdata *conn, int sockindex)
we do not send one. Let's hope other servers do the same... */
if(data->set.ftp_ccc == CURLFTPSSL_CCC_ACTIVE)
- gnutls_bye(conn->ssl[sockindex].session, GNUTLS_SHUT_WR);
+ gnutls_bye(BACKEND->session, GNUTLS_SHUT_WR);
- if(conn->ssl[sockindex].session) {
+ if(BACKEND->session) {
while(!done) {
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 */
- result = gnutls_record_recv(conn->ssl[sockindex].session,
+ result = gnutls_record_recv(BACKEND->session,
buf, sizeof(buf));
switch(result) {
case 0:
@@ -1636,18 +1645,18 @@ int Curl_gtls_shutdown(struct connectdata *conn, int sockindex)
done = 1;
}
}
- gnutls_deinit(conn->ssl[sockindex].session);
+ gnutls_deinit(BACKEND->session);
}
- gnutls_certificate_free_credentials(conn->ssl[sockindex].cred);
+ gnutls_certificate_free_credentials(BACKEND->cred);
#ifdef USE_TLS_SRP
if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP
&& SSL_SET_OPTION(username) != NULL)
- gnutls_srp_free_client_credentials(conn->ssl[sockindex].srp_client_cred);
+ gnutls_srp_free_client_credentials(BACKEND->srp_client_cred);
#endif
- conn->ssl[sockindex].cred = NULL;
- conn->ssl[sockindex].session = NULL;
+ BACKEND->cred = NULL;
+ BACKEND->session = NULL;
return retval;
}
@@ -1658,9 +1667,10 @@ static ssize_t gtls_recv(struct connectdata *conn, /* connection data */
size_t buffersize, /* max amount to read */
CURLcode *curlcode)
{
+ struct ssl_connect_data *connssl = &conn->ssl[num];
ssize_t ret;
- ret = gnutls_record_recv(conn->ssl[num].session, buf, buffersize);
+ ret = gnutls_record_recv(BACKEND->session, buf, buffersize);
if((ret == GNUTLS_E_AGAIN) || (ret == GNUTLS_E_INTERRUPTED)) {
*curlcode = CURLE_AGAIN;
return -1;
@@ -1680,6 +1690,7 @@ static ssize_t gtls_recv(struct connectdata *conn, /* connection data */
if(ret < 0) {
failf(conn->data, "GnuTLS recv error (%d): %s",
+
(int)ret, gnutls_strerror((int)ret));
*curlcode = CURLE_RECV_ERROR;
return -1;
@@ -1688,12 +1699,12 @@ static ssize_t gtls_recv(struct connectdata *conn, /* connection data */
return ret;
}
-void Curl_gtls_session_free(void *ptr)
+static void Curl_gtls_session_free(void *ptr)
{
free(ptr);
}
-size_t Curl_gtls_version(char *buffer, size_t size)
+static size_t Curl_gtls_version(char *buffer, size_t size)
{
return snprintf(buffer, size, "GnuTLS/%s", gnutls_check_version(NULL));
}
@@ -1723,9 +1734,8 @@ static int Curl_gtls_seed(struct Curl_easy *data)
#endif
/* data might be NULL! */
-CURLcode Curl_gtls_random(struct Curl_easy *data,
- unsigned char *entropy,
- size_t length)
+static CURLcode Curl_gtls_random(struct Curl_easy *data,
+ unsigned char *entropy, size_t length)
{
#if defined(USE_GNUTLS_NETTLE)
int rc;
@@ -1740,10 +1750,10 @@ CURLcode Curl_gtls_random(struct Curl_easy *data,
return CURLE_OK;
}
-void Curl_gtls_md5sum(unsigned char *tmp, /* input */
- size_t tmplen,
- unsigned char *md5sum, /* output */
- size_t md5len)
+static CURLcode Curl_gtls_md5sum(unsigned char *tmp, /* input */
+ size_t tmplen,
+ unsigned char *md5sum, /* output */
+ size_t md5len)
{
#if defined(USE_GNUTLS_NETTLE)
struct md5_ctx MD5pw;
@@ -1757,12 +1767,13 @@ void Curl_gtls_md5sum(unsigned char *tmp, /* input */
memcpy(md5sum, gcry_md_read(MD5pw, 0), md5len);
gcry_md_close(MD5pw);
#endif
+ return CURLE_OK;
}
-void Curl_gtls_sha256sum(const unsigned char *tmp, /* input */
- size_t tmplen,
- unsigned char *sha256sum, /* output */
- size_t sha256len)
+static void Curl_gtls_sha256sum(const unsigned char *tmp, /* input */
+ size_t tmplen,
+ unsigned char *sha256sum, /* output */
+ size_t sha256len)
{
#if defined(USE_GNUTLS_NETTLE)
struct sha256_ctx SHA256pw;
@@ -1778,7 +1789,7 @@ void Curl_gtls_sha256sum(const unsigned char *tmp, /* input */
#endif
}
-bool Curl_gtls_cert_status_request(void)
+static bool Curl_gtls_cert_status_request(void)
{
#ifdef HAS_OCSP
return TRUE;
@@ -1787,4 +1798,44 @@ bool Curl_gtls_cert_status_request(void)
#endif
}
+static void *Curl_gtls_get_internals(struct ssl_connect_data *connssl,
+ CURLINFO info UNUSED_PARAM)
+{
+ (void)info;
+ return BACKEND->session;
+}
+
+const struct Curl_ssl Curl_ssl_gnutls = {
+ { CURLSSLBACKEND_GNUTLS, "gnutls" }, /* info */
+
+ 1, /* have_ca_path */
+ 1, /* have_certinfo */
+ 1, /* have_pinnedpubkey */
+ 0, /* have_ssl_ctx */
+ 1, /* support_https_proxy */
+
+ sizeof(struct ssl_backend_data),
+
+ Curl_gtls_init, /* init */
+ Curl_gtls_cleanup, /* cleanup */
+ Curl_gtls_version, /* version */
+ Curl_none_check_cxn, /* check_cxn */
+ Curl_gtls_shutdown, /* shutdown */
+ Curl_gtls_data_pending, /* data_pending */
+ Curl_gtls_random, /* random */
+ Curl_gtls_cert_status_request, /* cert_status_request */
+ Curl_gtls_connect, /* connect */
+ Curl_gtls_connect_nonblocking, /* connect_nonblocking */
+ Curl_gtls_get_internals, /* get_internals */
+ Curl_gtls_close, /* close */
+ Curl_none_close_all, /* close_all */
+ Curl_gtls_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_gtls_md5sum, /* md5sum */
+ Curl_gtls_sha256sum /* sha256sum */
+};
+
#endif /* USE_GNUTLS */
diff --git a/Utilities/cmcurl/lib/vtls/gtls.h b/Utilities/cmcurl/lib/vtls/gtls.h
index 462c048..780fc10 100644
--- a/Utilities/cmcurl/lib/vtls/gtls.h
+++ b/Utilities/cmcurl/lib/vtls/gtls.h
@@ -28,69 +28,7 @@
#include "urldata.h"
-int Curl_gtls_init(void);
-int Curl_gtls_cleanup(void);
-CURLcode Curl_gtls_connect(struct connectdata *conn, int sockindex);
-CURLcode Curl_gtls_connect_nonblocking(struct connectdata *conn,
- int sockindex,
- bool *done);
-bool Curl_gtls_data_pending(const struct connectdata *conn,
- int connindex);
-
- /* close a SSL connection */
-void Curl_gtls_close(struct connectdata *conn, int sockindex);
-
-void Curl_gtls_session_free(void *ptr);
-size_t Curl_gtls_version(char *buffer, size_t size);
-int Curl_gtls_shutdown(struct connectdata *conn, int sockindex);
-CURLcode Curl_gtls_random(struct Curl_easy *data,
- unsigned char *entropy,
- size_t length);
-void Curl_gtls_md5sum(unsigned char *tmp, /* input */
- size_t tmplen,
- unsigned char *md5sum, /* output */
- size_t md5len);
-void Curl_gtls_sha256sum(const unsigned char *tmp, /* input */
- size_t tmplen,
- unsigned char *sha256sum, /* output */
- size_t sha256len);
-
-bool Curl_gtls_cert_status_request(void);
-
-/* Support HTTPS-proxy */
-#define HTTPS_PROXY_SUPPORT 1
-
-/* Set the API backend definition to GnuTLS */
-#define CURL_SSL_BACKEND CURLSSLBACKEND_GNUTLS
-
-/* this backend supports the CAPATH option */
-#define have_curlssl_ca_path 1
-
-/* this backend supports CURLOPT_CERTINFO */
-#define have_curlssl_certinfo 1
-
-/* this backend supports CURLOPT_PINNEDPUBLICKEY */
-#define have_curlssl_pinnedpubkey 1
-
-/* API setup for GnuTLS */
-#define curlssl_init Curl_gtls_init
-#define curlssl_cleanup Curl_gtls_cleanup
-#define curlssl_connect Curl_gtls_connect
-#define curlssl_connect_nonblocking Curl_gtls_connect_nonblocking
-#define curlssl_session_free(x) Curl_gtls_session_free(x)
-#define curlssl_close_all(x) ((void)x)
-#define curlssl_close Curl_gtls_close
-#define curlssl_shutdown(x,y) Curl_gtls_shutdown(x,y)
-#define curlssl_set_engine(x,y) ((void)x, (void)y, CURLE_NOT_BUILT_IN)
-#define curlssl_set_engine_default(x) ((void)x, CURLE_NOT_BUILT_IN)
-#define curlssl_engines_list(x) ((void)x, (struct curl_slist *)NULL)
-#define curlssl_version Curl_gtls_version
-#define curlssl_check_cxn(x) ((void)x, -1)
-#define curlssl_data_pending(x,y) Curl_gtls_data_pending(x,y)
-#define curlssl_random(x,y,z) Curl_gtls_random(x,y,z)
-#define curlssl_md5sum(a,b,c,d) Curl_gtls_md5sum(a,b,c,d)
-#define curlssl_sha256sum(a,b,c,d) Curl_gtls_sha256sum(a,b,c,d)
-#define curlssl_cert_status_request() Curl_gtls_cert_status_request()
+extern const struct Curl_ssl Curl_ssl_gnutls;
#endif /* USE_GNUTLS */
#endif /* HEADER_CURL_GTLS_H */
diff --git a/Utilities/cmcurl/lib/vtls/mbedtls.c b/Utilities/cmcurl/lib/vtls/mbedtls.c
index 037babe..ce1f8eb 100644
--- a/Utilities/cmcurl/lib/vtls/mbedtls.c
+++ b/Utilities/cmcurl/lib/vtls/mbedtls.c
@@ -61,6 +61,21 @@
#include "curl_memory.h"
#include "memdebug.h"
+struct ssl_backend_data {
+ mbedtls_ctr_drbg_context ctr_drbg;
+ mbedtls_entropy_context entropy;
+ mbedtls_ssl_context ssl;
+ int server_fd;
+ mbedtls_x509_crt cacert;
+ mbedtls_x509_crt clicert;
+ mbedtls_x509_crl crl;
+ mbedtls_pk_context pk;
+ mbedtls_ssl_config config;
+ const char *protocols[3];
+};
+
+#define BACKEND connssl->backend
+
/* apply threading? */
#if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32)
#define THREADING_SUPPORT
@@ -214,9 +229,9 @@ set_ssl_version_min_max(struct connectdata *conn, int sockindex)
return result;
}
- mbedtls_ssl_conf_min_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
+ mbedtls_ssl_conf_min_version(&BACKEND->config, MBEDTLS_SSL_MAJOR_VERSION_3,
mbedtls_ver_min);
- mbedtls_ssl_conf_max_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
+ mbedtls_ssl_conf_max_version(&BACKEND->config, MBEDTLS_SSL_MAJOR_VERSION_3,
mbedtls_ver_max);
return result;
@@ -238,7 +253,7 @@ mbed_connect_step1(struct connectdata *conn,
const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port;
int ret = -1;
char errorbuf[128];
- errorbuf[0]=0;
+ errorbuf[0] = 0;
/* mbedTLS only supports SSLv3 and TLSv1 */
if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv2) {
@@ -248,9 +263,9 @@ mbed_connect_step1(struct connectdata *conn,
#ifdef THREADING_SUPPORT
entropy_init_mutex(&ts_entropy);
- mbedtls_ctr_drbg_init(&connssl->ctr_drbg);
+ mbedtls_ctr_drbg_init(&BACKEND->ctr_drbg);
- ret = mbedtls_ctr_drbg_seed(&connssl->ctr_drbg, entropy_func_mutex,
+ ret = mbedtls_ctr_drbg_seed(&BACKEND->ctr_drbg, entropy_func_mutex,
&ts_entropy, NULL, 0);
if(ret) {
#ifdef MBEDTLS_ERROR_C
@@ -260,11 +275,11 @@ mbed_connect_step1(struct connectdata *conn,
-ret, errorbuf);
}
#else
- mbedtls_entropy_init(&connssl->entropy);
- mbedtls_ctr_drbg_init(&connssl->ctr_drbg);
+ mbedtls_entropy_init(&BACKEND->entropy);
+ mbedtls_ctr_drbg_init(&BACKEND->ctr_drbg);
- ret = mbedtls_ctr_drbg_seed(&connssl->ctr_drbg, mbedtls_entropy_func,
- &connssl->entropy, NULL, 0);
+ ret = mbedtls_ctr_drbg_seed(&BACKEND->ctr_drbg, mbedtls_entropy_func,
+ &BACKEND->entropy, NULL, 0);
if(ret) {
#ifdef MBEDTLS_ERROR_C
mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
@@ -275,10 +290,10 @@ mbed_connect_step1(struct connectdata *conn,
#endif /* THREADING_SUPPORT */
/* Load the trusted CA */
- mbedtls_x509_crt_init(&connssl->cacert);
+ mbedtls_x509_crt_init(&BACKEND->cacert);
if(ssl_cafile) {
- ret = mbedtls_x509_crt_parse_file(&connssl->cacert, ssl_cafile);
+ ret = mbedtls_x509_crt_parse_file(&BACKEND->cacert, ssl_cafile);
if(ret<0) {
#ifdef MBEDTLS_ERROR_C
@@ -293,7 +308,7 @@ mbed_connect_step1(struct connectdata *conn,
}
if(ssl_capath) {
- ret = mbedtls_x509_crt_parse_path(&connssl->cacert, ssl_capath);
+ ret = mbedtls_x509_crt_parse_path(&BACKEND->cacert, ssl_capath);
if(ret<0) {
#ifdef MBEDTLS_ERROR_C
@@ -308,10 +323,10 @@ mbed_connect_step1(struct connectdata *conn,
}
/* Load the client certificate */
- mbedtls_x509_crt_init(&connssl->clicert);
+ mbedtls_x509_crt_init(&BACKEND->clicert);
if(ssl_cert) {
- ret = mbedtls_x509_crt_parse_file(&connssl->clicert, ssl_cert);
+ ret = mbedtls_x509_crt_parse_file(&BACKEND->clicert, ssl_cert);
if(ret) {
#ifdef MBEDTLS_ERROR_C
@@ -325,12 +340,12 @@ mbed_connect_step1(struct connectdata *conn,
}
/* Load the client private key */
- mbedtls_pk_init(&connssl->pk);
+ mbedtls_pk_init(&BACKEND->pk);
if(SSL_SET_OPTION(key)) {
- ret = mbedtls_pk_parse_keyfile(&connssl->pk, SSL_SET_OPTION(key),
+ ret = mbedtls_pk_parse_keyfile(&BACKEND->pk, SSL_SET_OPTION(key),
SSL_SET_OPTION(key_passwd));
- if(ret == 0 && !mbedtls_pk_can_do(&connssl->pk, MBEDTLS_PK_RSA))
+ if(ret == 0 && !mbedtls_pk_can_do(&BACKEND->pk, MBEDTLS_PK_RSA))
ret = MBEDTLS_ERR_PK_TYPE_MISMATCH;
if(ret) {
@@ -345,10 +360,10 @@ mbed_connect_step1(struct connectdata *conn,
}
/* Load the CRL */
- mbedtls_x509_crl_init(&connssl->crl);
+ mbedtls_x509_crl_init(&BACKEND->crl);
if(ssl_crlfile) {
- ret = mbedtls_x509_crl_parse_file(&connssl->crl, ssl_crlfile);
+ ret = mbedtls_x509_crl_parse_file(&BACKEND->crl, ssl_crlfile);
if(ret) {
#ifdef MBEDTLS_ERROR_C
@@ -363,14 +378,14 @@ mbed_connect_step1(struct connectdata *conn,
infof(data, "mbedTLS: Connecting to %s:%d\n", hostname, port);
- mbedtls_ssl_config_init(&connssl->config);
+ mbedtls_ssl_config_init(&BACKEND->config);
- mbedtls_ssl_init(&connssl->ssl);
- if(mbedtls_ssl_setup(&connssl->ssl, &connssl->config)) {
+ mbedtls_ssl_init(&BACKEND->ssl);
+ if(mbedtls_ssl_setup(&BACKEND->ssl, &BACKEND->config)) {
failf(data, "mbedTLS: ssl_init failed");
return CURLE_SSL_CONNECT_ERROR;
}
- ret = mbedtls_ssl_config_defaults(&connssl->config,
+ ret = mbedtls_ssl_config_defaults(&BACKEND->config,
MBEDTLS_SSL_IS_CLIENT,
MBEDTLS_SSL_TRANSPORT_STREAM,
MBEDTLS_SSL_PRESET_DEFAULT);
@@ -380,20 +395,20 @@ mbed_connect_step1(struct connectdata *conn,
}
/* new profile with RSA min key len = 1024 ... */
- mbedtls_ssl_conf_cert_profile(&connssl->config,
+ mbedtls_ssl_conf_cert_profile(&BACKEND->config,
&mbedtls_x509_crt_profile_fr);
switch(SSL_CONN_CONFIG(version)) {
case CURL_SSLVERSION_DEFAULT:
case CURL_SSLVERSION_TLSv1:
- mbedtls_ssl_conf_min_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
+ mbedtls_ssl_conf_min_version(&BACKEND->config, MBEDTLS_SSL_MAJOR_VERSION_3,
MBEDTLS_SSL_MINOR_VERSION_1);
infof(data, "mbedTLS: Set min SSL version to TLS 1.0\n");
break;
case CURL_SSLVERSION_SSLv3:
- mbedtls_ssl_conf_min_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
+ mbedtls_ssl_conf_min_version(&BACKEND->config, MBEDTLS_SSL_MAJOR_VERSION_3,
MBEDTLS_SSL_MINOR_VERSION_0);
- mbedtls_ssl_conf_max_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
+ mbedtls_ssl_conf_max_version(&BACKEND->config, MBEDTLS_SSL_MAJOR_VERSION_3,
MBEDTLS_SSL_MINOR_VERSION_0);
infof(data, "mbedTLS: Set SSL version to SSLv3\n");
break;
@@ -412,25 +427,25 @@ mbed_connect_step1(struct connectdata *conn,
return CURLE_SSL_CONNECT_ERROR;
}
- mbedtls_ssl_conf_authmode(&connssl->config, MBEDTLS_SSL_VERIFY_OPTIONAL);
+ mbedtls_ssl_conf_authmode(&BACKEND->config, MBEDTLS_SSL_VERIFY_OPTIONAL);
- mbedtls_ssl_conf_rng(&connssl->config, mbedtls_ctr_drbg_random,
- &connssl->ctr_drbg);
- mbedtls_ssl_set_bio(&connssl->ssl, &conn->sock[sockindex],
+ mbedtls_ssl_conf_rng(&BACKEND->config, mbedtls_ctr_drbg_random,
+ &BACKEND->ctr_drbg);
+ mbedtls_ssl_set_bio(&BACKEND->ssl, &conn->sock[sockindex],
mbedtls_net_send,
mbedtls_net_recv,
NULL /* rev_timeout() */);
- mbedtls_ssl_conf_ciphersuites(&connssl->config,
+ mbedtls_ssl_conf_ciphersuites(&BACKEND->config,
mbedtls_ssl_list_ciphersuites());
#if defined(MBEDTLS_SSL_RENEGOTIATION)
- mbedtls_ssl_conf_renegotiation(&connssl->config,
+ mbedtls_ssl_conf_renegotiation(&BACKEND->config,
MBEDTLS_SSL_RENEGOTIATION_ENABLED);
#endif
#if defined(MBEDTLS_SSL_SESSION_TICKETS)
- mbedtls_ssl_conf_session_tickets(&connssl->config,
+ mbedtls_ssl_conf_session_tickets(&BACKEND->config,
MBEDTLS_SSL_SESSION_TICKETS_DISABLED);
#endif
@@ -440,7 +455,7 @@ mbed_connect_step1(struct connectdata *conn,
Curl_ssl_sessionid_lock(conn);
if(!Curl_ssl_getsessionid(conn, &old_session, NULL, sockindex)) {
- ret = mbedtls_ssl_set_session(&connssl->ssl, old_session);
+ ret = mbedtls_ssl_set_session(&BACKEND->ssl, old_session);
if(ret) {
Curl_ssl_sessionid_unlock(conn);
failf(data, "mbedtls_ssl_set_session returned -0x%x", -ret);
@@ -451,15 +466,15 @@ mbed_connect_step1(struct connectdata *conn,
Curl_ssl_sessionid_unlock(conn);
}
- mbedtls_ssl_conf_ca_chain(&connssl->config,
- &connssl->cacert,
- &connssl->crl);
+ mbedtls_ssl_conf_ca_chain(&BACKEND->config,
+ &BACKEND->cacert,
+ &BACKEND->crl);
if(SSL_SET_OPTION(key)) {
- mbedtls_ssl_conf_own_cert(&connssl->config,
- &connssl->clicert, &connssl->pk);
+ mbedtls_ssl_conf_own_cert(&BACKEND->config,
+ &BACKEND->clicert, &BACKEND->pk);
}
- if(mbedtls_ssl_set_hostname(&connssl->ssl, hostname)) {
+ if(mbedtls_ssl_set_hostname(&BACKEND->ssl, hostname)) {
/* mbedtls_ssl_set_hostname() sets the name to use in CN/SAN checks *and*
the name to set in the SNI extension. So even if curl connects to a
host specified as an IP address, this function must be used. */
@@ -469,7 +484,7 @@ mbed_connect_step1(struct connectdata *conn,
#ifdef HAS_ALPN
if(conn->bits.tls_enable_alpn) {
- const char **p = &connssl->protocols[0];
+ const char **p = &BACKEND->protocols[0];
#ifdef USE_NGHTTP2
if(data->set.httpversion >= CURL_HTTP_VERSION_2)
*p++ = NGHTTP2_PROTO_VERSION_ID;
@@ -478,19 +493,19 @@ mbed_connect_step1(struct connectdata *conn,
*p = NULL;
/* this function doesn't clone the protocols array, which is why we need
to keep it around */
- if(mbedtls_ssl_conf_alpn_protocols(&connssl->config,
- &connssl->protocols[0])) {
+ if(mbedtls_ssl_conf_alpn_protocols(&BACKEND->config,
+ &BACKEND->protocols[0])) {
failf(data, "Failed setting ALPN protocols");
return CURLE_SSL_CONNECT_ERROR;
}
- for(p = &connssl->protocols[0]; *p; ++p)
+ for(p = &BACKEND->protocols[0]; *p; ++p)
infof(data, "ALPN, offering %s\n", *p);
}
#endif
#ifdef MBEDTLS_DEBUG
/* In order to make that work in mbedtls MBEDTLS_DEBUG_C must be defined. */
- mbedtls_ssl_conf_dbg(&connssl->config, mbed_debug, data);
+ mbedtls_ssl_conf_dbg(&BACKEND->config, mbed_debug, data);
/* - 0 No debug
* - 1 Error
* - 2 State change
@@ -502,7 +517,7 @@ mbed_connect_step1(struct connectdata *conn,
/* give application a chance to interfere with mbedTLS set up. */
if(data->set.ssl.fsslctx) {
- ret = (*data->set.ssl.fsslctx)(data, &connssl->config,
+ ret = (*data->set.ssl.fsslctx)(data, &BACKEND->config,
data->set.ssl.fsslctxp);
if(ret) {
failf(data, "error signaled by ssl ctx callback");
@@ -537,7 +552,7 @@ mbed_connect_step2(struct connectdata *conn,
conn->recv[sockindex] = mbed_recv;
conn->send[sockindex] = mbed_send;
- ret = mbedtls_ssl_handshake(&connssl->ssl);
+ ret = mbedtls_ssl_handshake(&BACKEND->ssl);
if(ret == MBEDTLS_ERR_SSL_WANT_READ) {
connssl->connecting_state = ssl_connect_2_reading;
@@ -557,10 +572,10 @@ mbed_connect_step2(struct connectdata *conn,
}
infof(data, "mbedTLS: Handshake complete, cipher is %s\n",
- mbedtls_ssl_get_ciphersuite(&conn->ssl[sockindex].ssl)
+ mbedtls_ssl_get_ciphersuite(&BACKEND->ssl)
);
- ret = mbedtls_ssl_get_verify_result(&conn->ssl[sockindex].ssl);
+ ret = mbedtls_ssl_get_verify_result(&BACKEND->ssl);
if(ret && SSL_CONN_CONFIG(verifypeer)) {
if(ret & MBEDTLS_X509_BADCERT_EXPIRED)
@@ -580,7 +595,7 @@ mbed_connect_step2(struct connectdata *conn,
return CURLE_PEER_FAILED_VERIFICATION;
}
- peercert = mbedtls_ssl_get_peer_cert(&connssl->ssl);
+ peercert = mbedtls_ssl_get_peer_cert(&BACKEND->ssl);
if(peercert && data->set.verbose) {
const size_t bufsize = 16384;
@@ -650,7 +665,7 @@ mbed_connect_step2(struct connectdata *conn,
#ifdef HAS_ALPN
if(conn->bits.tls_enable_alpn) {
- next_protocol = mbedtls_ssl_get_alpn_protocol(&connssl->ssl);
+ next_protocol = mbedtls_ssl_get_alpn_protocol(&BACKEND->ssl);
if(next_protocol) {
infof(data, "ALPN, server accepted to use %s\n", next_protocol);
@@ -700,7 +715,7 @@ mbed_connect_step3(struct connectdata *conn,
mbedtls_ssl_session_init(our_ssl_sessionid);
- ret = mbedtls_ssl_get_session(&connssl->ssl, our_ssl_sessionid);
+ ret = mbedtls_ssl_get_session(&BACKEND->ssl, our_ssl_sessionid);
if(ret) {
free(our_ssl_sessionid);
failf(data, "mbedtls_ssl_get_session returned -0x%x", -ret);
@@ -730,9 +745,10 @@ static ssize_t mbed_send(struct connectdata *conn, int sockindex,
const void *mem, size_t len,
CURLcode *curlcode)
{
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
int ret = -1;
- ret = mbedtls_ssl_write(&conn->ssl[sockindex].ssl,
+ ret = mbedtls_ssl_write(&BACKEND->ssl,
(unsigned char *)mem, len);
if(ret < 0) {
@@ -744,22 +760,23 @@ static ssize_t mbed_send(struct connectdata *conn, int sockindex,
return ret;
}
-void Curl_mbedtls_close_all(struct Curl_easy *data)
+static void Curl_mbedtls_close_all(struct Curl_easy *data)
{
(void)data;
}
-void Curl_mbedtls_close(struct connectdata *conn, int sockindex)
+static void Curl_mbedtls_close(struct connectdata *conn, int sockindex)
{
- mbedtls_pk_free(&conn->ssl[sockindex].pk);
- mbedtls_x509_crt_free(&conn->ssl[sockindex].clicert);
- mbedtls_x509_crt_free(&conn->ssl[sockindex].cacert);
- mbedtls_x509_crl_free(&conn->ssl[sockindex].crl);
- mbedtls_ssl_config_free(&conn->ssl[sockindex].config);
- mbedtls_ssl_free(&conn->ssl[sockindex].ssl);
- mbedtls_ctr_drbg_free(&conn->ssl[sockindex].ctr_drbg);
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ mbedtls_pk_free(&BACKEND->pk);
+ mbedtls_x509_crt_free(&BACKEND->clicert);
+ mbedtls_x509_crt_free(&BACKEND->cacert);
+ mbedtls_x509_crl_free(&BACKEND->crl);
+ mbedtls_ssl_config_free(&BACKEND->config);
+ mbedtls_ssl_free(&BACKEND->ssl);
+ mbedtls_ctr_drbg_free(&BACKEND->ctr_drbg);
#ifndef THREADING_SUPPORT
- mbedtls_entropy_free(&conn->ssl[sockindex].entropy);
+ mbedtls_entropy_free(&BACKEND->entropy);
#endif /* THREADING_SUPPORT */
}
@@ -767,11 +784,12 @@ static ssize_t mbed_recv(struct connectdata *conn, int num,
char *buf, size_t buffersize,
CURLcode *curlcode)
{
+ struct ssl_connect_data *connssl = &conn->ssl[num];
int ret = -1;
ssize_t len = -1;
memset(buf, 0, buffersize);
- ret = mbedtls_ssl_read(&conn->ssl[num].ssl, (unsigned char *)buf,
+ ret = mbedtls_ssl_read(&BACKEND->ssl, (unsigned char *)buf,
buffersize);
if(ret <= 0) {
@@ -788,21 +806,21 @@ static ssize_t mbed_recv(struct connectdata *conn, int num,
return len;
}
-void Curl_mbedtls_session_free(void *ptr)
+static void Curl_mbedtls_session_free(void *ptr)
{
mbedtls_ssl_session_free(ptr);
free(ptr);
}
-size_t Curl_mbedtls_version(char *buffer, size_t size)
+static size_t Curl_mbedtls_version(char *buffer, size_t size)
{
unsigned int version = mbedtls_version_get_number();
return snprintf(buffer, size, "mbedTLS/%d.%d.%d", version>>24,
(version>>16)&0xff, (version>>8)&0xff);
}
-CURLcode Curl_mbedtls_random(struct Curl_easy *data, unsigned char *entropy,
- size_t length)
+static CURLcode Curl_mbedtls_random(struct Curl_easy *data,
+ unsigned char *entropy, size_t length)
{
#if defined(MBEDTLS_CTR_DRBG_C)
int ret = -1;
@@ -811,7 +829,7 @@ CURLcode Curl_mbedtls_random(struct Curl_easy *data, unsigned char *entropy,
mbedtls_ctr_drbg_context ctr_drbg;
mbedtls_entropy_init(&ctr_entropy);
mbedtls_ctr_drbg_init(&ctr_drbg);
- errorbuf[0]=0;
+ errorbuf[0] = 0;
ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func,
&ctr_entropy, NULL, 0);
@@ -869,7 +887,7 @@ mbed_connect_common(struct connectdata *conn,
return CURLE_OK;
}
- if(ssl_connect_1==connssl->connecting_state) {
+ if(ssl_connect_1 == connssl->connecting_state) {
/* Find out how much more time we're allowed */
timeout_ms = Curl_timeleft(data, NULL, TRUE);
@@ -900,9 +918,9 @@ mbed_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,
@@ -942,13 +960,13 @@ mbed_connect_common(struct connectdata *conn,
} /* repeat step2 until all transactions are done. */
- if(ssl_connect_3==connssl->connecting_state) {
+ if(ssl_connect_3 == connssl->connecting_state) {
retcode = mbed_connect_step3(conn, sockindex);
if(retcode)
return retcode;
}
- if(ssl_connect_done==connssl->connecting_state) {
+ if(ssl_connect_done == connssl->connecting_state) {
connssl->state = ssl_connection_complete;
conn->recv[sockindex] = mbed_recv;
conn->send[sockindex] = mbed_send;
@@ -963,18 +981,14 @@ mbed_connect_common(struct connectdata *conn,
return CURLE_OK;
}
-CURLcode
-Curl_mbedtls_connect_nonblocking(struct connectdata *conn,
- int sockindex,
- bool *done)
+static CURLcode Curl_mbedtls_connect_nonblocking(struct connectdata *conn,
+ int sockindex, bool *done)
{
return mbed_connect_common(conn, sockindex, TRUE, done);
}
-CURLcode
-Curl_mbedtls_connect(struct connectdata *conn,
- int sockindex)
+static CURLcode Curl_mbedtls_connect(struct connectdata *conn, int sockindex)
{
CURLcode retcode;
bool done = FALSE;
@@ -992,19 +1006,70 @@ Curl_mbedtls_connect(struct connectdata *conn,
* return 0 error initializing SSL
* return 1 SSL initialized successfully
*/
-int Curl_mbedtls_init(void)
+static int Curl_mbedtls_init(void)
{
return Curl_polarsslthreadlock_thread_setup();
}
-void Curl_mbedtls_cleanup(void)
+static void Curl_mbedtls_cleanup(void)
{
(void)Curl_polarsslthreadlock_thread_cleanup();
}
-int Curl_mbedtls_data_pending(const struct connectdata *conn, int sockindex)
+static bool Curl_mbedtls_data_pending(const struct connectdata *conn,
+ int sockindex)
{
- return mbedtls_ssl_get_bytes_avail(&conn->ssl[sockindex].ssl) != 0;
+ const struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ return mbedtls_ssl_get_bytes_avail(&BACKEND->ssl) != 0;
}
+static void Curl_mbedtls_sha256sum(const unsigned char *input,
+ size_t inputlen,
+ unsigned char *sha256sum,
+ size_t sha256len UNUSED_PARAM)
+{
+ (void)sha256len;
+ mbedtls_sha256(input, inputlen, sha256sum, 0);
+}
+
+static void *Curl_mbedtls_get_internals(struct ssl_connect_data *connssl,
+ CURLINFO info UNUSED_PARAM)
+{
+ (void)info;
+ return &BACKEND->ssl;
+}
+
+const struct Curl_ssl Curl_ssl_mbedtls = {
+ { CURLSSLBACKEND_MBEDTLS, "mbedtls" }, /* info */
+
+ 1, /* have_ca_path */
+ 0, /* have_certinfo */
+ 1, /* have_pinnedpubkey */
+ 1, /* have_ssl_ctx */
+ 0, /* support_https_proxy */
+
+ sizeof(struct ssl_backend_data),
+
+ Curl_mbedtls_init, /* init */
+ Curl_mbedtls_cleanup, /* cleanup */
+ Curl_mbedtls_version, /* version */
+ Curl_none_check_cxn, /* check_cxn */
+ Curl_none_shutdown, /* shutdown */
+ Curl_mbedtls_data_pending, /* data_pending */
+ Curl_mbedtls_random, /* random */
+ Curl_none_cert_status_request, /* cert_status_request */
+ Curl_mbedtls_connect, /* connect */
+ Curl_mbedtls_connect_nonblocking, /* connect_nonblocking */
+ Curl_mbedtls_get_internals, /* get_internals */
+ Curl_mbedtls_close, /* close */
+ Curl_mbedtls_close_all, /* close_all */
+ Curl_mbedtls_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 */
+ Curl_mbedtls_sha256sum /* sha256sum */
+};
+
#endif /* USE_MBEDTLS */
diff --git a/Utilities/cmcurl/lib/vtls/mbedtls.h b/Utilities/cmcurl/lib/vtls/mbedtls.h
index 71d17a4..4a93860 100644
--- a/Utilities/cmcurl/lib/vtls/mbedtls.h
+++ b/Utilities/cmcurl/lib/vtls/mbedtls.h
@@ -26,57 +26,7 @@
#ifdef USE_MBEDTLS
-#include <mbedtls/sha256.h>
-
-/* Called on first use mbedTLS, setup threading if supported */
-int Curl_mbedtls_init(void);
-void Curl_mbedtls_cleanup(void);
-int Curl_mbedtls_data_pending(const struct connectdata *conn, int sockindex);
-
-CURLcode Curl_mbedtls_connect(struct connectdata *conn, int sockindex);
-
-CURLcode Curl_mbedtls_connect_nonblocking(struct connectdata *conn,
- int sockindex,
- bool *done);
-
-/* tell mbedTLS to close down all open information regarding connections (and
- thus session ID caching etc) */
-void Curl_mbedtls_close_all(struct Curl_easy *data);
-
- /* close a SSL connection */
-void Curl_mbedtls_close(struct connectdata *conn, int sockindex);
-
-void Curl_mbedtls_session_free(void *ptr);
-size_t Curl_mbedtls_version(char *buffer, size_t size);
-int Curl_mbedtls_shutdown(struct connectdata *conn, int sockindex);
-
-CURLcode Curl_mbedtls_random(struct Curl_easy *data, unsigned char *entropy,
- size_t length);
-
-/* this backends supports CURLOPT_PINNEDPUBLICKEY */
-#define have_curlssl_pinnedpubkey 1
-
-/* this backend supports CURLOPT_SSL_CTX_* */
-#define have_curlssl_ssl_ctx 1
-
-/* API setup for mbedTLS */
-#define curlssl_init() Curl_mbedtls_init()
-#define curlssl_cleanup() Curl_mbedtls_cleanup()
-#define curlssl_connect Curl_mbedtls_connect
-#define curlssl_connect_nonblocking Curl_mbedtls_connect_nonblocking
-#define curlssl_session_free(x) Curl_mbedtls_session_free(x)
-#define curlssl_close_all Curl_mbedtls_close_all
-#define curlssl_close Curl_mbedtls_close
-#define curlssl_shutdown(x,y) 0
-#define curlssl_set_engine(x,y) (x=x, y=y, CURLE_NOT_BUILT_IN)
-#define curlssl_set_engine_default(x) (x=x, CURLE_NOT_BUILT_IN)
-#define curlssl_engines_list(x) (x=x, (struct curl_slist *)NULL)
-#define curlssl_version Curl_mbedtls_version
-#define curlssl_check_cxn(x) (x=x, -1)
-#define curlssl_data_pending(x,y) Curl_mbedtls_data_pending(x, y)
-#define CURL_SSL_BACKEND CURLSSLBACKEND_MBEDTLS
-#define curlssl_sha256sum(a,b,c,d) mbedtls_sha256(a,b,c,0)
-#define curlssl_random(x,y,z) Curl_mbedtls_random(x, y, z)
+extern const struct Curl_ssl Curl_ssl_mbedtls;
#endif /* USE_MBEDTLS */
#endif /* HEADER_CURL_MBEDTLS_H */
diff --git a/Utilities/cmcurl/lib/vtls/nss.c b/Utilities/cmcurl/lib/vtls/nss.c
index cd01389..c0b7e63 100644
--- a/Utilities/cmcurl/lib/vtls/nss.c
+++ b/Utilities/cmcurl/lib/vtls/nss.c
@@ -78,6 +78,16 @@
/* enough to fit the string "PEM Token #[0|1]" */
#define SLOTSIZE 13
+struct ssl_backend_data {
+ PRFileDesc *handle;
+ char *client_nickname;
+ struct Curl_easy *data;
+ struct curl_llist obj_list;
+ PK11GenericObject *obj_clicert;
+};
+
+#define BACKEND connssl->backend
+
static PRLock *nss_initlock = NULL;
static PRLock *nss_crllock = NULL;
static PRLock *nss_findslot_lock = NULL;
@@ -271,7 +281,7 @@ static SECStatus set_ciphers(struct Curl_easy *data, PRFileDesc * model,
found = PR_FALSE;
- for(i=0; i<NUM_OF_CIPHERS; i++) {
+ for(i = 0; i<NUM_OF_CIPHERS; i++) {
if(strcasecompare(cipher, cipherlist[i].name)) {
cipher_state[i] = PR_TRUE;
found = PR_TRUE;
@@ -290,7 +300,7 @@ static SECStatus set_ciphers(struct Curl_easy *data, PRFileDesc * model,
}
/* Finally actually enable the selected ciphers */
- for(i=0; i<NUM_OF_CIPHERS; i++) {
+ for(i = 0; i<NUM_OF_CIPHERS; i++) {
if(!cipher_state[i])
continue;
@@ -311,7 +321,7 @@ static bool any_cipher_enabled(void)
{
unsigned int i;
- for(i=0; i<NUM_OF_CIPHERS; i++) {
+ for(i = 0; i<NUM_OF_CIPHERS; i++) {
PRInt32 policy = 0;
SSL_CipherPolicyGet(cipherlist[i].num, &policy);
if(policy)
@@ -396,7 +406,7 @@ static CURLcode insert_wrapped_ptr(struct curl_llist *list, void *ptr)
/* Call PK11_CreateGenericObject() with the given obj_class and filename. If
* the call succeeds, append the object handle to the list of objects so that
* the object can be destroyed in Curl_nss_close(). */
-static CURLcode nss_create_object(struct ssl_connect_data *ssl,
+static CURLcode nss_create_object(struct ssl_connect_data *connssl,
CK_OBJECT_CLASS obj_class,
const char *filename, bool cacert)
{
@@ -435,14 +445,14 @@ static CURLcode nss_create_object(struct ssl_connect_data *ssl,
if(!obj)
return result;
- if(insert_wrapped_ptr(&ssl->obj_list, obj) != CURLE_OK) {
+ if(insert_wrapped_ptr(&BACKEND->obj_list, obj) != CURLE_OK) {
PK11_DestroyGenericObject(obj);
return CURLE_OUT_OF_MEMORY;
}
if(!cacert && CKO_CERTIFICATE == obj_class)
/* store reference to a client certificate */
- ssl->obj_clicert = obj;
+ BACKEND->obj_clicert = obj;
return CURLE_OK;
}
@@ -992,7 +1002,7 @@ static SECStatus check_issuer_cert(PRFileDesc *sock,
char *issuer_nickname)
{
CERTCertificate *cert, *cert_issuer, *issuer;
- SECStatus res=SECSuccess;
+ SECStatus res = SECSuccess;
void *proto_win = NULL;
cert = SSL_PeerCertificate(sock);
@@ -1004,7 +1014,7 @@ static SECStatus check_issuer_cert(PRFileDesc *sock,
if((!cert_issuer) || (!issuer))
res = SECFailure;
else if(SECITEM_CompareItem(&cert_issuer->derCert,
- &issuer->derCert)!=SECEqual)
+ &issuer->derCert) != SECEqual)
res = SECFailure;
CERT_DestroyCertificate(cert);
@@ -1017,7 +1027,7 @@ static CURLcode cmp_peer_pubkey(struct ssl_connect_data *connssl,
const char *pinnedpubkey)
{
CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;
- struct Curl_easy *data = connssl->data;
+ struct Curl_easy *data = BACKEND->data;
CERTCertificate *cert;
if(!pinnedpubkey)
@@ -1025,7 +1035,7 @@ static CURLcode cmp_peer_pubkey(struct ssl_connect_data *connssl,
return CURLE_OK;
/* get peer certificate */
- cert = SSL_PeerCertificate(connssl->handle);
+ cert = SSL_PeerCertificate(BACKEND->handle);
if(cert) {
/* extract public key from peer certificate */
SECKEYPublicKey *pubkey = CERT_ExtractPublicKey(cert);
@@ -1069,11 +1079,11 @@ static SECStatus SelectClientCert(void *arg, PRFileDesc *sock,
struct SECKEYPrivateKeyStr **pRetKey)
{
struct ssl_connect_data *connssl = (struct ssl_connect_data *)arg;
- struct Curl_easy *data = connssl->data;
- const char *nickname = connssl->client_nickname;
+ struct Curl_easy *data = BACKEND->data;
+ const char *nickname = BACKEND->client_nickname;
static const char pem_slotname[] = "PEM Token #1";
- if(connssl->obj_clicert) {
+ if(BACKEND->obj_clicert) {
/* use the cert/key provided by PEM reader */
SECItem cert_der = { 0, NULL, 0 };
void *proto_win = SSL_RevealPinArg(sock);
@@ -1086,7 +1096,7 @@ static SECStatus SelectClientCert(void *arg, PRFileDesc *sock,
return SECFailure;
}
- if(PK11_ReadRawAttribute(PK11_TypeGeneric, connssl->obj_clicert, CKA_VALUE,
+ if(PK11_ReadRawAttribute(PK11_TypeGeneric, BACKEND->obj_clicert, CKA_VALUE,
&cert_der) != SECSuccess) {
failf(data, "NSS: CKA_VALUE not found in PK11 generic object");
PK11_FreeSlot(slot);
@@ -1351,7 +1361,7 @@ static CURLcode nss_init(struct Curl_easy *data)
* @retval 0 error initializing SSL
* @retval 1 SSL initialized successfully
*/
-int Curl_nss_init(void)
+static int Curl_nss_init(void)
{
/* curl_global_init() is not thread-safe so this test is ok */
if(nss_initlock == NULL) {
@@ -1386,7 +1396,7 @@ CURLcode Curl_nss_force_init(struct Curl_easy *data)
}
/* Global cleanup */
-void Curl_nss_cleanup(void)
+static void Curl_nss_cleanup(void)
{
/* This function isn't required to be threadsafe and this is only done
* as a safety feature.
@@ -1426,14 +1436,14 @@ void Curl_nss_cleanup(void)
* 0 means the connection has been closed
* -1 means the connection status is unknown
*/
-int
-Curl_nss_check_cxn(struct connectdata *conn)
+static int Curl_nss_check_cxn(struct connectdata *conn)
{
+ struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET];
int rc;
char buf;
rc =
- PR_Recv(conn->ssl[FIRSTSOCKET].handle, (void *)&buf, 1, PR_MSG_PEEK,
+ PR_Recv(BACKEND->handle, (void *)&buf, 1, PR_MSG_PEEK,
PR_SecondsToInterval(1));
if(rc > 0)
return 1; /* connection still in place */
@@ -1447,48 +1457,49 @@ Curl_nss_check_cxn(struct connectdata *conn)
static void nss_close(struct ssl_connect_data *connssl)
{
/* before the cleanup, check whether we are using a client certificate */
- const bool client_cert = (connssl->client_nickname != NULL)
- || (connssl->obj_clicert != NULL);
+ const bool client_cert = (BACKEND->client_nickname != NULL)
+ || (BACKEND->obj_clicert != NULL);
- free(connssl->client_nickname);
- connssl->client_nickname = NULL;
+ free(BACKEND->client_nickname);
+ BACKEND->client_nickname = NULL;
/* destroy all NSS objects in order to avoid failure of NSS shutdown */
- Curl_llist_destroy(&connssl->obj_list, NULL);
- connssl->obj_clicert = NULL;
+ Curl_llist_destroy(&BACKEND->obj_list, NULL);
+ BACKEND->obj_clicert = NULL;
- if(connssl->handle) {
+ if(BACKEND->handle) {
if(client_cert)
/* A server might require different authentication based on the
* particular path being requested by the client. To support this
* scenario, we must ensure that a connection will never reuse the
* authentication data from a previous connection. */
- SSL_InvalidateSession(connssl->handle);
+ SSL_InvalidateSession(BACKEND->handle);
- PR_Close(connssl->handle);
- connssl->handle = NULL;
+ PR_Close(BACKEND->handle);
+ BACKEND->handle = NULL;
}
}
/*
* This function is called when an SSL connection is closed.
*/
-void Curl_nss_close(struct connectdata *conn, int sockindex)
+static void Curl_nss_close(struct connectdata *conn, int sockindex)
{
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_connect_data *connssl_proxy = &conn->proxy_ssl[sockindex];
- if(connssl->handle || connssl_proxy->handle) {
+ if(BACKEND->handle || connssl_proxy->backend->handle) {
/* NSS closes the socket we previously handed to it, so we must mark it
as closed to avoid double close */
fake_sclose(conn->sock[sockindex]);
conn->sock[sockindex] = CURL_SOCKET_BAD;
}
- if(connssl->handle)
- /* nss_close(connssl) will transitively close also connssl_proxy->handle
- if both are used. Clear it to avoid a double close leading to crash. */
- connssl_proxy->handle = NULL;
+ if(BACKEND->handle)
+ /* nss_close(connssl) will transitively close also
+ connssl_proxy->backend->handle if both are used. Clear it to avoid
+ a double close leading to crash. */
+ connssl_proxy->backend->handle = NULL;
nss_close(connssl);
nss_close(connssl_proxy);
@@ -1732,7 +1743,7 @@ static CURLcode nss_fail_connect(struct ssl_connect_data *connssl,
}
/* cleanup on connection failure */
- Curl_llist_destroy(&connssl->obj_list, NULL);
+ Curl_llist_destroy(&BACKEND->obj_list, NULL);
return curlerr;
}
@@ -1746,7 +1757,7 @@ static CURLcode nss_set_blocking(struct ssl_connect_data *connssl,
sock_opt.option = PR_SockOpt_Nonblocking;
sock_opt.value.non_blocking = !blocking;
- if(PR_SetSocketOption(connssl->handle, &sock_opt) != PR_SUCCESS)
+ if(PR_SetSocketOption(BACKEND->handle, &sock_opt) != PR_SUCCESS)
return nss_fail_connect(connssl, data, CURLE_SSL_CONNECT_ERROR);
return CURLE_OK;
@@ -1770,10 +1781,10 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
SSL_LIBRARY_VERSION_TLS_1_0 /* max */
};
- connssl->data = data;
+ BACKEND->data = data;
/* list of all NSS objects we need to destroy in Curl_nss_close() */
- Curl_llist_init(&connssl->obj_list, nss_destroy_object);
+ 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);
@@ -1882,7 +1893,7 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
char *nickname = dup_nickname(data, SSL_SET_OPTION(cert));
if(nickname) {
/* we are not going to use libnsspem.so to read the client cert */
- connssl->obj_clicert = NULL;
+ BACKEND->obj_clicert = NULL;
}
else {
CURLcode rv = cert_stuff(conn, sockindex, SSL_SET_OPTION(cert),
@@ -1895,10 +1906,10 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
}
/* store the nickname for SelectClientCert() called during handshake */
- connssl->client_nickname = nickname;
+ BACKEND->client_nickname = nickname;
}
else
- connssl->client_nickname = NULL;
+ BACKEND->client_nickname = NULL;
if(SSL_GetClientAuthDataHook(model, SelectClientCert,
(void *)connssl) != SECSuccess) {
@@ -1908,8 +1919,8 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
if(conn->proxy_ssl[sockindex].use) {
DEBUGASSERT(ssl_connection_complete == conn->proxy_ssl[sockindex].state);
- DEBUGASSERT(conn->proxy_ssl[sockindex].handle != NULL);
- nspr_io = conn->proxy_ssl[sockindex].handle;
+ DEBUGASSERT(conn->proxy_ssl[sockindex].backend->handle != NULL);
+ nspr_io = conn->proxy_ssl[sockindex].backend->handle;
second_layer = TRUE;
}
else {
@@ -1939,8 +1950,8 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
}
/* import our model socket onto the current I/O stack */
- connssl->handle = SSL_ImportFD(model, nspr_io);
- if(!connssl->handle) {
+ BACKEND->handle = SSL_ImportFD(model, nspr_io);
+ if(!BACKEND->handle) {
if(!second_layer)
PR_Close(nspr_io);
goto error;
@@ -1951,36 +1962,36 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
/* This is the password associated with the cert that we're using */
if(SSL_SET_OPTION(key_passwd)) {
- SSL_SetPKCS11PinArg(connssl->handle, SSL_SET_OPTION(key_passwd));
+ SSL_SetPKCS11PinArg(BACKEND->handle, SSL_SET_OPTION(key_passwd));
}
#ifdef SSL_ENABLE_OCSP_STAPLING
if(SSL_CONN_CONFIG(verifystatus)) {
- if(SSL_OptionSet(connssl->handle, SSL_ENABLE_OCSP_STAPLING, PR_TRUE)
+ if(SSL_OptionSet(BACKEND->handle, SSL_ENABLE_OCSP_STAPLING, PR_TRUE)
!= SECSuccess)
goto error;
}
#endif
#ifdef SSL_ENABLE_NPN
- if(SSL_OptionSet(connssl->handle, SSL_ENABLE_NPN, conn->bits.tls_enable_npn
+ if(SSL_OptionSet(BACKEND->handle, SSL_ENABLE_NPN, conn->bits.tls_enable_npn
? PR_TRUE : PR_FALSE) != SECSuccess)
goto error;
#endif
#ifdef SSL_ENABLE_ALPN
- if(SSL_OptionSet(connssl->handle, SSL_ENABLE_ALPN, conn->bits.tls_enable_alpn
+ if(SSL_OptionSet(BACKEND->handle, SSL_ENABLE_ALPN, conn->bits.tls_enable_alpn
? PR_TRUE : PR_FALSE) != SECSuccess)
goto error;
#endif
#if NSSVERNUM >= 0x030f04 /* 3.15.4 */
if(data->set.ssl.falsestart) {
- if(SSL_OptionSet(connssl->handle, SSL_ENABLE_FALSE_START, PR_TRUE)
+ if(SSL_OptionSet(BACKEND->handle, SSL_ENABLE_FALSE_START, PR_TRUE)
!= SECSuccess)
goto error;
- if(SSL_SetCanFalseStartCallback(connssl->handle, CanFalseStartCallback,
+ if(SSL_SetCanFalseStartCallback(BACKEND->handle, CanFalseStartCallback,
conn) != SECSuccess)
goto error;
}
@@ -1992,7 +2003,8 @@ static CURLcode nss_setup_connect(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,
NGHTTP2_PROTO_VERSION_ID_LEN);
@@ -2003,24 +2015,24 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
memcpy(&protocols[cur], ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH);
cur += ALPN_HTTP_1_1_LENGTH;
- if(SSL_SetNextProtoNego(connssl->handle, protocols, cur) != SECSuccess)
+ if(SSL_SetNextProtoNego(BACKEND->handle, protocols, cur) != SECSuccess)
goto error;
}
#endif
/* Force handshake on next I/O */
- if(SSL_ResetHandshake(connssl->handle, /* asServer */ PR_FALSE)
+ if(SSL_ResetHandshake(BACKEND->handle, /* asServer */ PR_FALSE)
!= SECSuccess)
goto error;
/* propagate hostname to the TLS layer */
- if(SSL_SetURL(connssl->handle, SSL_IS_PROXY() ? conn->http_proxy.host.name :
+ if(SSL_SetURL(BACKEND->handle, SSL_IS_PROXY() ? conn->http_proxy.host.name :
conn->host.name) != SECSuccess)
goto error;
/* prevent NSS from re-using the session for a different hostname */
- if(SSL_SetSockPeerID(connssl->handle, SSL_IS_PROXY() ?
+ if(SSL_SetSockPeerID(BACKEND->handle, SSL_IS_PROXY() ?
conn->http_proxy.host.name : conn->host.name)
!= SECSuccess)
goto error;
@@ -2057,7 +2069,7 @@ static CURLcode nss_do_connect(struct connectdata *conn, int sockindex)
/* Force the handshake now */
timeout = PR_MillisecondsToInterval((PRUint32) time_left);
- if(SSL_ForceHandshakeWithTimeout(connssl->handle, timeout) != SECSuccess) {
+ if(SSL_ForceHandshakeWithTimeout(BACKEND->handle, timeout) != SECSuccess) {
if(PR_GetError() == PR_WOULD_BLOCK_ERROR)
/* blocking direction is updated by nss_update_connecting_state() */
return CURLE_AGAIN;
@@ -2068,7 +2080,7 @@ static CURLcode nss_do_connect(struct connectdata *conn, int sockindex)
goto error;
}
- result = display_conn_info(conn, connssl->handle);
+ result = display_conn_info(conn, BACKEND->handle);
if(result)
goto error;
@@ -2077,7 +2089,7 @@ static CURLcode nss_do_connect(struct connectdata *conn, int sockindex)
char *nickname = dup_nickname(data, SSL_SET_OPTION(issuercert));
if(nickname) {
/* we support only nicknames in case of issuercert for now */
- ret = check_issuer_cert(connssl->handle, nickname);
+ ret = check_issuer_cert(BACKEND->handle, nickname);
free(nickname);
}
@@ -2163,13 +2175,13 @@ static CURLcode nss_connect_common(struct connectdata *conn, int sockindex,
return CURLE_OK;
}
-CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex)
+static CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex)
{
return nss_connect_common(conn, sockindex, /* blocking */ NULL);
}
-CURLcode Curl_nss_connect_nonblocking(struct connectdata *conn,
- int sockindex, bool *done)
+static CURLcode Curl_nss_connect_nonblocking(struct connectdata *conn,
+ int sockindex, bool *done)
{
return nss_connect_common(conn, sockindex, done);
}
@@ -2180,8 +2192,14 @@ static ssize_t nss_send(struct connectdata *conn, /* connection data */
size_t len, /* amount to write */
CURLcode *curlcode)
{
- ssize_t rc = PR_Send(conn->ssl[sockindex].handle, mem, (int)len, 0,
- PR_INTERVAL_NO_WAIT);
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ ssize_t rc;
+
+ /* The SelectClientCert() hook uses this for infof() and failf() but the
+ handle stored in nss_setup_connect() could have already been freed. */
+ BACKEND->data = conn->data;
+
+ rc = PR_Send(BACKEND->handle, mem, (int)len, 0, PR_INTERVAL_NO_WAIT);
if(rc < 0) {
PRInt32 err = PR_GetError();
if(err == PR_WOULD_BLOCK_ERROR)
@@ -2205,14 +2223,21 @@ static ssize_t nss_send(struct connectdata *conn, /* connection data */
return rc; /* number of bytes */
}
-static ssize_t nss_recv(struct connectdata * conn, /* connection data */
- int num, /* socketindex */
+static ssize_t nss_recv(struct connectdata *conn, /* connection data */
+ int sockindex, /* socketindex */
char *buf, /* store read data here */
size_t buffersize, /* max amount to read */
CURLcode *curlcode)
{
- ssize_t nread = PR_Recv(conn->ssl[num].handle, buf, (int)buffersize, 0,
- PR_INTERVAL_NO_WAIT);
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ ssize_t nread;
+
+ /* The SelectClientCert() hook uses this for infof() and failf() but the
+ handle stored in nss_setup_connect() could have already been freed. */
+ BACKEND->data = conn->data;
+
+ nread = PR_Recv(BACKEND->handle, buf, (int)buffersize, 0,
+ PR_INTERVAL_NO_WAIT);
if(nread < 0) {
/* failed SSL read */
PRInt32 err = PR_GetError();
@@ -2238,22 +2263,22 @@ static ssize_t nss_recv(struct connectdata * conn, /* connection data */
return nread;
}
-size_t Curl_nss_version(char *buffer, size_t size)
+static size_t Curl_nss_version(char *buffer, size_t size)
{
return snprintf(buffer, size, "NSS/%s", NSS_VERSION);
}
/* data might be NULL */
-int Curl_nss_seed(struct Curl_easy *data)
+static int Curl_nss_seed(struct Curl_easy *data)
{
/* make sure that NSS is initialized */
return !!Curl_nss_force_init(data);
}
/* data might be NULL */
-CURLcode Curl_nss_random(struct Curl_easy *data,
- unsigned char *entropy,
- size_t length)
+static CURLcode Curl_nss_random(struct Curl_easy *data,
+ unsigned char *entropy,
+ size_t length)
{
Curl_nss_seed(data); /* Initiate the seed if not already done */
@@ -2264,10 +2289,10 @@ CURLcode Curl_nss_random(struct Curl_easy *data,
return CURLE_OK;
}
-void Curl_nss_md5sum(unsigned char *tmp, /* input */
- size_t tmplen,
- unsigned char *md5sum, /* output */
- size_t md5len)
+static CURLcode Curl_nss_md5sum(unsigned char *tmp, /* input */
+ size_t tmplen,
+ unsigned char *md5sum, /* output */
+ size_t md5len)
{
PK11Context *MD5pw = PK11_CreateDigestContext(SEC_OID_MD5);
unsigned int MD5out;
@@ -2275,12 +2300,14 @@ void Curl_nss_md5sum(unsigned char *tmp, /* input */
PK11_DigestOp(MD5pw, tmp, curlx_uztoui(tmplen));
PK11_DigestFinal(MD5pw, md5sum, &MD5out, curlx_uztoui(md5len));
PK11_DestroyContext(MD5pw, PR_TRUE);
+
+ return CURLE_OK;
}
-void Curl_nss_sha256sum(const unsigned char *tmp, /* input */
- size_t tmplen,
- unsigned char *sha256sum, /* output */
- size_t sha256len)
+static void Curl_nss_sha256sum(const unsigned char *tmp, /* input */
+ size_t tmplen,
+ unsigned char *sha256sum, /* output */
+ size_t sha256len)
{
PK11Context *SHA256pw = PK11_CreateDigestContext(SEC_OID_SHA256);
unsigned int SHA256out;
@@ -2290,7 +2317,7 @@ void Curl_nss_sha256sum(const unsigned char *tmp, /* input */
PK11_DestroyContext(SHA256pw, PR_TRUE);
}
-bool Curl_nss_cert_status_request(void)
+static bool Curl_nss_cert_status_request(void)
{
#ifdef SSL_ENABLE_OCSP_STAPLING
return TRUE;
@@ -2299,7 +2326,7 @@ bool Curl_nss_cert_status_request(void)
#endif
}
-bool Curl_nss_false_start(void)
+static bool Curl_nss_false_start(void)
{
#if NSSVERNUM >= 0x030f04 /* 3.15.4 */
return TRUE;
@@ -2308,4 +2335,46 @@ bool Curl_nss_false_start(void)
#endif
}
+static void *Curl_nss_get_internals(struct ssl_connect_data *connssl,
+ CURLINFO info UNUSED_PARAM)
+{
+ (void)info;
+ return BACKEND->handle;
+}
+
+const struct Curl_ssl Curl_ssl_nss = {
+ { CURLSSLBACKEND_NSS, "nss" }, /* info */
+
+ 1, /* have_ca_path */
+ 1, /* have_certinfo */
+ 1, /* have_pinnedpubkey */
+ 0, /* have_ssl_ctx */
+ 1, /* support_https_proxy */
+
+ sizeof(struct ssl_backend_data),
+
+ Curl_nss_init, /* init */
+ Curl_nss_cleanup, /* cleanup */
+ Curl_nss_version, /* version */
+ Curl_nss_check_cxn, /* check_cxn */
+ /* NSS has no shutdown function provided and thus always fail */
+ Curl_none_shutdown, /* shutdown */
+ Curl_none_data_pending, /* data_pending */
+ Curl_nss_random, /* random */
+ Curl_nss_cert_status_request, /* cert_status_request */
+ Curl_nss_connect, /* connect */
+ Curl_nss_connect_nonblocking, /* connect_nonblocking */
+ Curl_nss_get_internals, /* get_internals */
+ Curl_nss_close, /* close */
+ Curl_none_close_all, /* close_all */
+ /* NSS has its own session ID cache */
+ Curl_none_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_nss_false_start, /* false_start */
+ Curl_nss_md5sum, /* md5sum */
+ Curl_nss_sha256sum /* sha256sum */
+};
+
#endif /* USE_NSS */
diff --git a/Utilities/cmcurl/lib/vtls/nssg.h b/Utilities/cmcurl/lib/vtls/nssg.h
index 8c46929..41e51b0 100644
--- a/Utilities/cmcurl/lib/vtls/nssg.h
+++ b/Utilities/cmcurl/lib/vtls/nssg.h
@@ -30,79 +30,10 @@
#include "urldata.h"
-CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex);
-CURLcode Curl_nss_connect_nonblocking(struct connectdata *conn,
- int sockindex,
- bool *done);
-/* close a SSL connection */
-void Curl_nss_close(struct connectdata *conn, int sockindex);
-
-int Curl_nss_init(void);
-void Curl_nss_cleanup(void);
-
-size_t Curl_nss_version(char *buffer, size_t size);
-int Curl_nss_check_cxn(struct connectdata *cxn);
-int Curl_nss_seed(struct Curl_easy *data);
-
/* initialize NSS library if not already */
CURLcode Curl_nss_force_init(struct Curl_easy *data);
-CURLcode Curl_nss_random(struct Curl_easy *data,
- unsigned char *entropy,
- size_t length);
-
-void Curl_nss_md5sum(unsigned char *tmp, /* input */
- size_t tmplen,
- unsigned char *md5sum, /* output */
- size_t md5len);
-
-void Curl_nss_sha256sum(const unsigned char *tmp, /* input */
- size_t tmplen,
- unsigned char *sha256sum, /* output */
- size_t sha256len);
-
-bool Curl_nss_cert_status_request(void);
-
-bool Curl_nss_false_start(void);
-
-/* Support HTTPS-proxy */
-#define HTTPS_PROXY_SUPPORT 1
-
-/* Set the API backend definition to NSS */
-#define CURL_SSL_BACKEND CURLSSLBACKEND_NSS
-
-/* this backend supports the CAPATH option */
-#define have_curlssl_ca_path 1
-
-/* this backend supports CURLOPT_CERTINFO */
-#define have_curlssl_certinfo 1
-
-/* this backends supports CURLOPT_PINNEDPUBLICKEY */
-#define have_curlssl_pinnedpubkey 1
-
-/* API setup for NSS */
-#define curlssl_init Curl_nss_init
-#define curlssl_cleanup Curl_nss_cleanup
-#define curlssl_connect Curl_nss_connect
-#define curlssl_connect_nonblocking Curl_nss_connect_nonblocking
-
-/* NSS has its own session ID cache */
-#define curlssl_session_free(x) Curl_nop_stmt
-#define curlssl_close_all(x) ((void)x)
-#define curlssl_close Curl_nss_close
-/* NSS has no shutdown function provided and thus always fail */
-#define curlssl_shutdown(x,y) ((void)x, (void)y, 1)
-#define curlssl_set_engine(x,y) ((void)x, (void)y, CURLE_NOT_BUILT_IN)
-#define curlssl_set_engine_default(x) ((void)x, CURLE_NOT_BUILT_IN)
-#define curlssl_engines_list(x) ((void)x, (struct curl_slist *)NULL)
-#define curlssl_version Curl_nss_version
-#define curlssl_check_cxn(x) Curl_nss_check_cxn(x)
-#define curlssl_data_pending(x,y) ((void)x, (void)y, 0)
-#define curlssl_random(x,y,z) Curl_nss_random(x,y,z)
-#define curlssl_md5sum(a,b,c,d) Curl_nss_md5sum(a,b,c,d)
-#define curlssl_sha256sum(a,b,c,d) Curl_nss_sha256sum(a,b,c,d)
-#define curlssl_cert_status_request() Curl_nss_cert_status_request()
-#define curlssl_false_start() Curl_nss_false_start()
+extern const struct Curl_ssl Curl_ssl_nss;
#endif /* USE_NSS */
#endif /* HEADER_CURL_NSSG_H */
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 */
diff --git a/Utilities/cmcurl/lib/vtls/openssl.h b/Utilities/cmcurl/lib/vtls/openssl.h
index b9648d5..114dc4b 100644
--- a/Utilities/cmcurl/lib/vtls/openssl.h
+++ b/Utilities/cmcurl/lib/vtls/openssl.h
@@ -31,96 +31,7 @@
#include "urldata.h"
-CURLcode Curl_ossl_connect(struct connectdata *conn, int sockindex);
-CURLcode Curl_ossl_connect_nonblocking(struct connectdata *conn,
- int sockindex,
- bool *done);
-
-/* close a SSL connection */
-void Curl_ossl_close(struct connectdata *conn, int sockindex);
-
-/* tell OpenSSL to close down all open information regarding connections (and
- thus session ID caching etc) */
-void Curl_ossl_close_all(struct Curl_easy *data);
-
-/* Sets an OpenSSL engine */
-CURLcode Curl_ossl_set_engine(struct Curl_easy *data, const char *engine);
-
-/* function provided for the generic SSL-layer, called when a session id
- should be freed */
-void Curl_ossl_session_free(void *ptr);
-
-/* Sets engine as default for all SSL operations */
-CURLcode Curl_ossl_set_engine_default(struct Curl_easy *data);
-
-/* Build list of OpenSSL engines */
-struct curl_slist *Curl_ossl_engines_list(struct Curl_easy *data);
-
-int Curl_ossl_init(void);
-void Curl_ossl_cleanup(void);
-
-size_t Curl_ossl_version(char *buffer, size_t size);
-int Curl_ossl_check_cxn(struct connectdata *cxn);
-int Curl_ossl_shutdown(struct connectdata *conn, int sockindex);
-bool Curl_ossl_data_pending(const struct connectdata *conn,
- int connindex);
-
-/* return 0 if a find random is filled in */
-CURLcode Curl_ossl_random(struct Curl_easy *data, unsigned char *entropy,
- size_t length);
-void Curl_ossl_md5sum(unsigned char *tmp, /* input */
- size_t tmplen,
- unsigned char *md5sum /* output */,
- size_t unused);
-void Curl_ossl_sha256sum(const unsigned char *tmp, /* input */
- size_t tmplen,
- unsigned char *sha256sum /* output */,
- size_t unused);
-
-bool Curl_ossl_cert_status_request(void);
-
-/* Support HTTPS-proxy */
-#define HTTPS_PROXY_SUPPORT 1
-
-/* Set the API backend definition to OpenSSL */
-#define CURL_SSL_BACKEND CURLSSLBACKEND_OPENSSL
-
-/* this backend supports the CAPATH option */
-#define have_curlssl_ca_path 1
-
-/* this backend supports CURLOPT_CERTINFO */
-#define have_curlssl_certinfo 1
-
-/* this backend supports CURLOPT_SSL_CTX_* */
-#define have_curlssl_ssl_ctx 1
-
-/* this backend supports CURLOPT_PINNEDPUBLICKEY */
-#define have_curlssl_pinnedpubkey 1
-
-/* API setup for OpenSSL */
-#define curlssl_init Curl_ossl_init
-#define curlssl_cleanup Curl_ossl_cleanup
-#define curlssl_connect Curl_ossl_connect
-#define curlssl_connect_nonblocking Curl_ossl_connect_nonblocking
-#define curlssl_session_free(x) Curl_ossl_session_free(x)
-#define curlssl_close_all Curl_ossl_close_all
-#define curlssl_close Curl_ossl_close
-#define curlssl_shutdown(x,y) Curl_ossl_shutdown(x,y)
-#define curlssl_set_engine(x,y) Curl_ossl_set_engine(x,y)
-#define curlssl_set_engine_default(x) Curl_ossl_set_engine_default(x)
-#define curlssl_engines_list(x) Curl_ossl_engines_list(x)
-#define curlssl_version Curl_ossl_version
-#define curlssl_check_cxn Curl_ossl_check_cxn
-#define curlssl_data_pending(x,y) Curl_ossl_data_pending(x,y)
-#define curlssl_random(x,y,z) Curl_ossl_random(x,y,z)
-#define curlssl_md5sum(a,b,c,d) Curl_ossl_md5sum(a,b,c,d)
-#if (OPENSSL_VERSION_NUMBER >= 0x0090800fL) && !defined(OPENSSL_NO_SHA256)
-#define curlssl_sha256sum(a,b,c,d) Curl_ossl_sha256sum(a,b,c,d)
-#endif
-#define curlssl_cert_status_request() Curl_ossl_cert_status_request()
-
-#define DEFAULT_CIPHER_SELECTION \
- "ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH"
+extern const struct Curl_ssl Curl_ssl_openssl;
#endif /* USE_OPENSSL */
#endif /* HEADER_CURL_SSLUSE_H */
diff --git a/Utilities/cmcurl/lib/vtls/polarssl.c b/Utilities/cmcurl/lib/vtls/polarssl.c
index 669091c..fc0644f 100644
--- a/Utilities/cmcurl/lib/vtls/polarssl.c
+++ b/Utilities/cmcurl/lib/vtls/polarssl.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2012 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2012 - 2017, 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
@@ -30,7 +30,6 @@
#include "curl_setup.h"
#ifdef USE_POLARSSL
-
#include <polarssl/net.h>
#include <polarssl/ssl.h>
#include <polarssl/certs.h>
@@ -70,6 +69,19 @@
#define PUB_DER_MAX_BYTES (RSA_PUB_DER_MAX_BYTES > ECP_PUB_DER_MAX_BYTES ? \
RSA_PUB_DER_MAX_BYTES : ECP_PUB_DER_MAX_BYTES)
+struct ssl_backend_data {
+ ctr_drbg_context ctr_drbg;
+ entropy_context entropy;
+ ssl_context ssl;
+ int server_fd;
+ x509_crt cacert;
+ x509_crt clicert;
+ x509_crl crl;
+ rsa_context rsa;
+};
+
+#define BACKEND connssl->backend
+
/* apply threading? */
#if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32)
#define THREADING_SUPPORT
@@ -197,8 +209,8 @@ set_ssl_version_min_max(struct connectdata *conn, int sockindex)
return result;
}
- ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3, ssl_min_ver);
- ssl_set_max_version(&connssl->ssl, SSL_MAJOR_VERSION_3, ssl_max_ver);
+ ssl_set_min_version(&BACKEND->ssl, SSL_MAJOR_VERSION_3, ssl_min_ver);
+ ssl_set_max_version(&BACKEND->ssl, SSL_MAJOR_VERSION_3, ssl_max_ver);
return result;
}
@@ -215,7 +227,7 @@ polarssl_connect_step1(struct connectdata *conn,
const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port;
int ret = -1;
char errorbuf[128];
- errorbuf[0]=0;
+ errorbuf[0] = 0;
/* PolarSSL only supports SSLv3 and TLSv1 */
if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv2) {
@@ -226,16 +238,16 @@ polarssl_connect_step1(struct connectdata *conn,
#ifdef THREADING_SUPPORT
entropy_init_mutex(&entropy);
- if((ret = ctr_drbg_init(&connssl->ctr_drbg, entropy_func_mutex, &entropy,
+ if((ret = ctr_drbg_init(&BACKEND->ctr_drbg, entropy_func_mutex, &entropy,
NULL, 0)) != 0) {
error_strerror(ret, errorbuf, sizeof(errorbuf));
failf(data, "Failed - PolarSSL: ctr_drbg_init returned (-0x%04X) %s\n",
-ret, errorbuf);
}
#else
- entropy_init(&connssl->entropy);
+ entropy_init(&BACKEND->entropy);
- if((ret = ctr_drbg_init(&connssl->ctr_drbg, entropy_func, &connssl->entropy,
+ if((ret = ctr_drbg_init(&BACKEND->ctr_drbg, entropy_func, &BACKEND->entropy,
NULL, 0)) != 0) {
error_strerror(ret, errorbuf, sizeof(errorbuf));
failf(data, "Failed - PolarSSL: ctr_drbg_init returned (-0x%04X) %s\n",
@@ -244,10 +256,10 @@ polarssl_connect_step1(struct connectdata *conn,
#endif /* THREADING_SUPPORT */
/* Load the trusted CA */
- memset(&connssl->cacert, 0, sizeof(x509_crt));
+ memset(&BACKEND->cacert, 0, sizeof(x509_crt));
if(SSL_CONN_CONFIG(CAfile)) {
- ret = x509_crt_parse_file(&connssl->cacert,
+ ret = x509_crt_parse_file(&BACKEND->cacert,
SSL_CONN_CONFIG(CAfile));
if(ret<0) {
@@ -261,7 +273,7 @@ polarssl_connect_step1(struct connectdata *conn,
}
if(capath) {
- ret = x509_crt_parse_path(&connssl->cacert, capath);
+ ret = x509_crt_parse_path(&BACKEND->cacert, capath);
if(ret<0) {
error_strerror(ret, errorbuf, sizeof(errorbuf));
@@ -274,10 +286,10 @@ polarssl_connect_step1(struct connectdata *conn,
}
/* Load the client certificate */
- memset(&connssl->clicert, 0, sizeof(x509_crt));
+ memset(&BACKEND->clicert, 0, sizeof(x509_crt));
if(SSL_SET_OPTION(cert)) {
- ret = x509_crt_parse_file(&connssl->clicert,
+ ret = x509_crt_parse_file(&BACKEND->clicert,
SSL_SET_OPTION(cert));
if(ret) {
@@ -298,9 +310,9 @@ polarssl_connect_step1(struct connectdata *conn,
if(ret == 0 && !pk_can_do(&pk, POLARSSL_PK_RSA))
ret = POLARSSL_ERR_PK_TYPE_MISMATCH;
if(ret == 0)
- rsa_copy(&connssl->rsa, pk_rsa(pk));
+ rsa_copy(&BACKEND->rsa, pk_rsa(pk));
else
- rsa_free(&connssl->rsa);
+ rsa_free(&BACKEND->rsa);
pk_free(&pk);
if(ret) {
@@ -313,10 +325,10 @@ polarssl_connect_step1(struct connectdata *conn,
}
/* Load the CRL */
- memset(&connssl->crl, 0, sizeof(x509_crl));
+ memset(&BACKEND->crl, 0, sizeof(x509_crl));
if(SSL_SET_OPTION(CRLfile)) {
- ret = x509_crl_parse_file(&connssl->crl,
+ ret = x509_crl_parse_file(&BACKEND->crl,
SSL_SET_OPTION(CRLfile));
if(ret) {
@@ -330,7 +342,7 @@ polarssl_connect_step1(struct connectdata *conn,
infof(data, "PolarSSL: Connecting to %s:%d\n", hostname, port);
- if(ssl_init(&connssl->ssl)) {
+ if(ssl_init(&BACKEND->ssl)) {
failf(data, "PolarSSL: ssl_init failed");
return CURLE_SSL_CONNECT_ERROR;
}
@@ -338,13 +350,13 @@ polarssl_connect_step1(struct connectdata *conn,
switch(SSL_CONN_CONFIG(version)) {
case CURL_SSLVERSION_DEFAULT:
case CURL_SSLVERSION_TLSv1:
- ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3,
+ ssl_set_min_version(&BACKEND->ssl, SSL_MAJOR_VERSION_3,
SSL_MINOR_VERSION_1);
break;
case CURL_SSLVERSION_SSLv3:
- ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3,
+ ssl_set_min_version(&BACKEND->ssl, SSL_MAJOR_VERSION_3,
SSL_MINOR_VERSION_0);
- ssl_set_max_version(&connssl->ssl, SSL_MAJOR_VERSION_3,
+ ssl_set_max_version(&BACKEND->ssl, SSL_MAJOR_VERSION_3,
SSL_MINOR_VERSION_0);
infof(data, "PolarSSL: Forced min. SSL Version to be SSLv3\n");
break;
@@ -363,16 +375,16 @@ polarssl_connect_step1(struct connectdata *conn,
return CURLE_SSL_CONNECT_ERROR;
}
- ssl_set_endpoint(&connssl->ssl, SSL_IS_CLIENT);
- ssl_set_authmode(&connssl->ssl, SSL_VERIFY_OPTIONAL);
+ ssl_set_endpoint(&BACKEND->ssl, SSL_IS_CLIENT);
+ ssl_set_authmode(&BACKEND->ssl, SSL_VERIFY_OPTIONAL);
- ssl_set_rng(&connssl->ssl, ctr_drbg_random,
- &connssl->ctr_drbg);
- ssl_set_bio(&connssl->ssl,
+ ssl_set_rng(&BACKEND->ssl, ctr_drbg_random,
+ &BACKEND->ctr_drbg);
+ ssl_set_bio(&BACKEND->ssl,
net_recv, &conn->sock[sockindex],
net_send, &conn->sock[sockindex]);
- ssl_set_ciphersuites(&connssl->ssl, ssl_list_ciphersuites());
+ ssl_set_ciphersuites(&BACKEND->ssl, ssl_list_ciphersuites());
/* Check if there's a cached ID we can/should use here! */
if(SSL_SET_OPTION(primary.sessionid)) {
@@ -380,7 +392,7 @@ polarssl_connect_step1(struct connectdata *conn,
Curl_ssl_sessionid_lock(conn);
if(!Curl_ssl_getsessionid(conn, &old_session, NULL, sockindex)) {
- ret = ssl_set_session(&connssl->ssl, old_session);
+ ret = ssl_set_session(&BACKEND->ssl, old_session);
if(ret) {
Curl_ssl_sessionid_unlock(conn);
failf(data, "ssl_set_session returned -0x%x", -ret);
@@ -391,15 +403,15 @@ polarssl_connect_step1(struct connectdata *conn,
Curl_ssl_sessionid_unlock(conn);
}
- ssl_set_ca_chain(&connssl->ssl,
- &connssl->cacert,
- &connssl->crl,
+ ssl_set_ca_chain(&BACKEND->ssl,
+ &BACKEND->cacert,
+ &BACKEND->crl,
hostname);
- ssl_set_own_cert_rsa(&connssl->ssl,
- &connssl->clicert, &connssl->rsa);
+ ssl_set_own_cert_rsa(&BACKEND->ssl,
+ &BACKEND->clicert, &BACKEND->rsa);
- if(ssl_set_hostname(&connssl->ssl, hostname)) {
+ if(ssl_set_hostname(&BACKEND->ssl, hostname)) {
/* ssl_set_hostname() sets the name to use in CN/SAN checks *and* the name
to set in the SNI extension. So even if curl connects to a host
specified as an IP address, this function must be used. */
@@ -424,12 +436,12 @@ polarssl_connect_step1(struct connectdata *conn,
protocols[cur] = NULL;
- ssl_set_alpn_protocols(&connssl->ssl, protocols);
+ ssl_set_alpn_protocols(&BACKEND->ssl, protocols);
}
#endif
#ifdef POLARSSL_DEBUG
- ssl_set_dbg(&connssl->ssl, polarssl_debug, data);
+ ssl_set_dbg(&BACKEND->ssl, polarssl_debug, data);
#endif
connssl->connecting_state = ssl_connect_2;
@@ -456,7 +468,7 @@ polarssl_connect_step2(struct connectdata *conn,
conn->recv[sockindex] = polarssl_recv;
conn->send[sockindex] = polarssl_send;
- ret = ssl_handshake(&connssl->ssl);
+ ret = ssl_handshake(&BACKEND->ssl);
switch(ret) {
case 0:
@@ -478,9 +490,9 @@ polarssl_connect_step2(struct connectdata *conn,
}
infof(data, "PolarSSL: Handshake complete, cipher is %s\n",
- ssl_get_ciphersuite(&conn->ssl[sockindex].ssl) );
+ ssl_get_ciphersuite(&BACKEND->ssl) );
- ret = ssl_get_verify_result(&conn->ssl[sockindex].ssl);
+ ret = ssl_get_verify_result(&BACKEND->ssl);
if(ret && SSL_CONN_CONFIG(verifypeer)) {
if(ret & BADCERT_EXPIRED)
@@ -500,12 +512,12 @@ polarssl_connect_step2(struct connectdata *conn,
return CURLE_PEER_FAILED_VERIFICATION;
}
- if(ssl_get_peer_cert(&(connssl->ssl))) {
+ if(ssl_get_peer_cert(&(BACKEND->ssl))) {
/* If the session was resumed, there will be no peer certs */
memset(buffer, 0, sizeof(buffer));
if(x509_crt_info(buffer, sizeof(buffer), (char *)"* ",
- ssl_get_peer_cert(&(connssl->ssl))) != -1)
+ ssl_get_peer_cert(&(BACKEND->ssl))) != -1)
infof(data, "Dumping cert info:\n%s\n", buffer);
}
@@ -517,7 +529,7 @@ polarssl_connect_step2(struct connectdata *conn,
unsigned char pubkey[PUB_DER_MAX_BYTES];
const x509_crt *peercert;
- peercert = ssl_get_peer_cert(&connssl->ssl);
+ peercert = ssl_get_peer_cert(&BACKEND->ssl);
if(!peercert || !peercert->raw.p || !peercert->raw.len) {
failf(data, "Failed due to missing peer certificate");
@@ -566,7 +578,7 @@ polarssl_connect_step2(struct connectdata *conn,
#ifdef HAS_ALPN
if(conn->bits.tls_enable_alpn) {
- const char *next_protocol = ssl_get_alpn_protocol(&connssl->ssl);
+ const char *next_protocol = ssl_get_alpn_protocol(&BACKEND->ssl);
if(next_protocol != NULL) {
infof(data, "ALPN, server accepted to use %s\n", next_protocol);
@@ -614,7 +626,7 @@ polarssl_connect_step3(struct connectdata *conn,
memset(our_ssl_sessionid, 0, sizeof(ssl_session));
- ret = ssl_get_session(&connssl->ssl, our_ssl_sessionid);
+ ret = ssl_get_session(&BACKEND->ssl, our_ssl_sessionid);
if(ret) {
failf(data, "ssl_get_session returned -0x%x", -ret);
return CURLE_SSL_CONNECT_ERROR;
@@ -645,9 +657,10 @@ static ssize_t polarssl_send(struct connectdata *conn,
size_t len,
CURLcode *curlcode)
{
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
int ret = -1;
- ret = ssl_write(&conn->ssl[sockindex].ssl,
+ ret = ssl_write(&BACKEND->ssl,
(unsigned char *)mem, len);
if(ret < 0) {
@@ -659,13 +672,14 @@ static ssize_t polarssl_send(struct connectdata *conn,
return ret;
}
-void Curl_polarssl_close(struct connectdata *conn, int sockindex)
+static void Curl_polarssl_close(struct connectdata *conn, int sockindex)
{
- rsa_free(&conn->ssl[sockindex].rsa);
- x509_crt_free(&conn->ssl[sockindex].clicert);
- x509_crt_free(&conn->ssl[sockindex].cacert);
- x509_crl_free(&conn->ssl[sockindex].crl);
- ssl_free(&conn->ssl[sockindex].ssl);
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ rsa_free(&BACKEND->rsa);
+ x509_crt_free(&BACKEND->clicert);
+ x509_crt_free(&BACKEND->cacert);
+ x509_crl_free(&BACKEND->crl);
+ ssl_free(&BACKEND->ssl);
}
static ssize_t polarssl_recv(struct connectdata *conn,
@@ -674,11 +688,12 @@ static ssize_t polarssl_recv(struct connectdata *conn,
size_t buffersize,
CURLcode *curlcode)
{
+ struct ssl_connect_data *connssl = &conn->ssl[num];
int ret = -1;
ssize_t len = -1;
memset(buf, 0, buffersize);
- ret = ssl_read(&conn->ssl[num].ssl, (unsigned char *)buf, buffersize);
+ ret = ssl_read(&BACKEND->ssl, (unsigned char *)buf, buffersize);
if(ret <= 0) {
if(ret == POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY)
@@ -694,7 +709,7 @@ static ssize_t polarssl_recv(struct connectdata *conn,
return len;
}
-void Curl_polarssl_session_free(void *ptr)
+static void Curl_polarssl_session_free(void *ptr)
{
ssl_session_free(ptr);
free(ptr);
@@ -703,7 +718,7 @@ void Curl_polarssl_session_free(void *ptr)
/* 1.3.10 was the first rebranded version. All new releases (in 1.3 branch and
higher) will be mbed TLS branded.. */
-size_t Curl_polarssl_version(char *buffer, size_t size)
+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",
@@ -762,9 +777,9 @@ polarssl_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,
@@ -825,18 +840,14 @@ polarssl_connect_common(struct connectdata *conn,
return CURLE_OK;
}
-CURLcode
-Curl_polarssl_connect_nonblocking(struct connectdata *conn,
- int sockindex,
- bool *done)
+static CURLcode Curl_polarssl_connect_nonblocking(struct connectdata *conn,
+ int sockindex, bool *done)
{
return polarssl_connect_common(conn, sockindex, TRUE, done);
}
-CURLcode
-Curl_polarssl_connect(struct connectdata *conn,
- int sockindex)
+static CURLcode Curl_polarssl_connect(struct connectdata *conn, int sockindex)
{
CURLcode result;
bool done = FALSE;
@@ -854,20 +865,73 @@ Curl_polarssl_connect(struct connectdata *conn,
* return 0 error initializing SSL
* return 1 SSL initialized successfully
*/
-int Curl_polarssl_init(void)
+static int Curl_polarssl_init(void)
{
return Curl_polarsslthreadlock_thread_setup();
}
-void Curl_polarssl_cleanup(void)
+static void Curl_polarssl_cleanup(void)
{
(void)Curl_polarsslthreadlock_thread_cleanup();
}
+static bool Curl_polarssl_data_pending(const struct connectdata *conn,
+ int sockindex)
+{
+ const struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ return ssl_get_bytes_avail(&BACKEND->ssl) != 0;
+}
+
+static void Curl_polarssl_sha256sum(const unsigned char *input,
+ size_t inputlen,
+ unsigned char *sha256sum,
+ size_t sha256len UNUSED_PARAM)
+{
+ (void)sha256len;
+ sha256(input, inputlen, sha256sum, 0);
+}
-int Curl_polarssl_data_pending(const struct connectdata *conn, int sockindex)
+static void *Curl_polarssl_get_internals(struct ssl_connect_data *connssl,
+ CURLINFO info UNUSED_PARAM)
{
- return ssl_get_bytes_avail(&conn->ssl[sockindex].ssl) != 0;
+ (void)info;
+ return &BACKEND->ssl;
}
+const struct Curl_ssl Curl_ssl_polarssl = {
+ { CURLSSLBACKEND_POLARSSL, "polarssl" }, /* info */
+
+ 1, /* have_ca_path */
+ 0, /* have_certinfo */
+ 1, /* have_pinnedpubkey */
+ 0, /* have_ssl_ctx */
+ 0, /* support_https_proxy */
+
+ sizeof(struct ssl_backend_data),
+
+ Curl_polarssl_init, /* init */
+ Curl_polarssl_cleanup, /* cleanup */
+ Curl_polarssl_version, /* version */
+ 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
+ */
+ Curl_none_random, /* random */
+ Curl_none_cert_status_request, /* cert_status_request */
+ Curl_polarssl_connect, /* connect */
+ Curl_polarssl_connect_nonblocking, /* connect_nonblocking */
+ Curl_polarssl_get_internals, /* get_internals */
+ Curl_polarssl_close, /* close */
+ Curl_none_close_all, /* close_all */
+ Curl_polarssl_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 */
+ Curl_polarssl_sha256sum /* sha256sum */
+};
+
#endif /* USE_POLARSSL */
diff --git a/Utilities/cmcurl/lib/vtls/polarssl.h b/Utilities/cmcurl/lib/vtls/polarssl.h
index 47af7b4..23c3636 100644
--- a/Utilities/cmcurl/lib/vtls/polarssl.h
+++ b/Utilities/cmcurl/lib/vtls/polarssl.h
@@ -26,57 +26,7 @@
#ifdef USE_POLARSSL
-#include <polarssl/sha256.h>
-
-/* Called on first use PolarSSL, setup threading if supported */
-int Curl_polarssl_init(void);
-void Curl_polarssl_cleanup(void);
-int Curl_polarssl_data_pending(const struct connectdata *conn, int sockindex);
-
-
-CURLcode Curl_polarssl_connect(struct connectdata *conn, int sockindex);
-
-CURLcode Curl_polarssl_connect_nonblocking(struct connectdata *conn,
- int sockindex,
- bool *done);
-
- /* close a SSL connection */
-void Curl_polarssl_close(struct connectdata *conn, int sockindex);
-
-void Curl_polarssl_session_free(void *ptr);
-size_t Curl_polarssl_version(char *buffer, size_t size);
-int Curl_polarssl_shutdown(struct connectdata *conn, int sockindex);
-
-/* Set the API backend definition to PolarSSL */
-#define CURL_SSL_BACKEND CURLSSLBACKEND_POLARSSL
-
-/* this backend supports the CAPATH option */
-#define have_curlssl_ca_path 1
-
-/* this backends supports CURLOPT_PINNEDPUBLICKEY */
-#define have_curlssl_pinnedpubkey 1
-
-/* API setup for PolarSSL */
-#define curlssl_init() Curl_polarssl_init()
-#define curlssl_cleanup() Curl_polarssl_cleanup()
-#define curlssl_connect Curl_polarssl_connect
-#define curlssl_connect_nonblocking Curl_polarssl_connect_nonblocking
-#define curlssl_session_free(x) Curl_polarssl_session_free(x)
-#define curlssl_close_all(x) ((void)x)
-#define curlssl_close Curl_polarssl_close
-#define curlssl_shutdown(x,y) 0
-#define curlssl_set_engine(x,y) ((void)x, (void)y, CURLE_NOT_BUILT_IN)
-#define curlssl_set_engine_default(x) ((void)x, CURLE_NOT_BUILT_IN)
-#define curlssl_engines_list(x) ((void)x, (struct curl_slist *)NULL)
-#define curlssl_version Curl_polarssl_version
-#define curlssl_check_cxn(x) ((void)x, -1)
-#define curlssl_data_pending(x,y) Curl_polarssl_data_pending(x, y)
-#define curlssl_sha256sum(a,b,c,d) sha256(a,b,c,0)
-
-/* This might cause libcurl to use a weeker random!
- TODO: implement proper use of Polarssl's CTR-DRBG or HMAC-DRBG and use that
-*/
-#define curlssl_random(x,y,z) ((void)x, (void)y, (void)z, CURLE_NOT_BUILT_IN)
+extern const struct Curl_ssl Curl_ssl_polarssl;
#endif /* USE_POLARSSL */
#endif /* HEADER_CURL_POLARSSL_H */
diff --git a/Utilities/cmcurl/lib/vtls/polarssl_threadlock.c b/Utilities/cmcurl/lib/vtls/polarssl_threadlock.c
index b1eb7b7..dd5fbd7 100644
--- a/Utilities/cmcurl/lib/vtls/polarssl_threadlock.c
+++ b/Utilities/cmcurl/lib/vtls/polarssl_threadlock.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2013-2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2013-2017, 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
@@ -114,7 +114,7 @@ int Curl_polarsslthreadlock_lock_function(int n)
}
#elif defined(HAVE_PROCESS_H)
if(n < NUMT) {
- ret = (WaitForSingleObject(mutex_buf[n], INFINITE)==WAIT_FAILED?1:0);
+ ret = (WaitForSingleObject(mutex_buf[n], INFINITE) == WAIT_FAILED?1:0);
if(ret) {
DEBUGF(fprintf(stderr,
"Error: polarsslthreadlock_lock_function failed\n"));
diff --git a/Utilities/cmcurl/lib/vtls/schannel.c b/Utilities/cmcurl/lib/vtls/schannel.c
index 9460301..9ca1431 100644
--- a/Utilities/cmcurl/lib/vtls/schannel.c
+++ b/Utilities/cmcurl/lib/vtls/schannel.c
@@ -46,6 +46,8 @@
# error "Can't compile SCHANNEL support without SSPI."
#endif
+#include <schnlsp.h>
+#include <schannel.h>
#include "curl_sspi.h"
#include "schannel.h"
#include "vtls.h"
@@ -74,11 +76,92 @@
# define HAS_ALPN 1
#endif
+#ifndef UNISP_NAME_A
+#define UNISP_NAME_A "Microsoft Unified Security Protocol Provider"
+#endif
+
+#ifndef UNISP_NAME_W
+#define UNISP_NAME_W L"Microsoft Unified Security Protocol Provider"
+#endif
+
+#ifndef UNISP_NAME
+#ifdef UNICODE
+#define UNISP_NAME UNISP_NAME_W
+#else
+#define UNISP_NAME UNISP_NAME_A
+#endif
+#endif
+
+#ifndef SP_PROT_SSL2_CLIENT
+#define SP_PROT_SSL2_CLIENT 0x00000008
+#endif
+
+#ifndef SP_PROT_SSL3_CLIENT
+#define SP_PROT_SSL3_CLIENT 0x00000008
+#endif
+
+#ifndef SP_PROT_TLS1_CLIENT
+#define SP_PROT_TLS1_CLIENT 0x00000080
+#endif
+
+#ifndef SP_PROT_TLS1_0_CLIENT
+#define SP_PROT_TLS1_0_CLIENT SP_PROT_TLS1_CLIENT
+#endif
+
+#ifndef SP_PROT_TLS1_1_CLIENT
+#define SP_PROT_TLS1_1_CLIENT 0x00000200
+#endif
+
+#ifndef SP_PROT_TLS1_2_CLIENT
+#define SP_PROT_TLS1_2_CLIENT 0x00000800
+#endif
+
+#ifndef SECBUFFER_ALERT
+#define SECBUFFER_ALERT 17
+#endif
+
+/* Both schannel buffer sizes must be > 0 */
+#define CURL_SCHANNEL_BUFFER_INIT_SIZE 4096
+#define CURL_SCHANNEL_BUFFER_FREE_SIZE 1024
+
/* Uncomment to force verbose output
* #define infof(x, y, ...) printf(y, __VA_ARGS__)
* #define failf(x, y, ...) printf(y, __VA_ARGS__)
*/
+/* Structs to store Schannel handles */
+struct curl_schannel_cred {
+ CredHandle cred_handle;
+ TimeStamp time_stamp;
+ int refcount;
+};
+
+struct curl_schannel_ctxt {
+ CtxtHandle ctxt_handle;
+ TimeStamp time_stamp;
+};
+
+struct ssl_backend_data {
+ struct curl_schannel_cred *cred;
+ struct curl_schannel_ctxt *ctxt;
+ SecPkgContext_StreamSizes stream_sizes;
+ size_t encdata_length, decdata_length;
+ size_t encdata_offset, decdata_offset;
+ unsigned char *encdata_buffer, *decdata_buffer;
+ /* encdata_is_incomplete: if encdata contains only a partial record that
+ can't be decrypted without another Curl_read_plain (that is, status is
+ SEC_E_INCOMPLETE_MESSAGE) then set this true. after Curl_read_plain writes
+ more bytes into encdata then set this back to false. */
+ bool encdata_is_incomplete;
+ unsigned long req_flags, ret_flags;
+ CURLcode recv_unrecoverable_err; /* schannel_recv had an unrecoverable err */
+ bool recv_sspi_close_notify; /* true if connection closed by close_notify */
+ bool recv_connection_closed; /* true if connection closed, regardless how */
+ bool use_alpn; /* true if ALPN is used for this connection */
+};
+
+#define BACKEND connssl->backend
+
static Curl_recv schannel_recv;
static Curl_send schannel_send;
@@ -176,33 +259,33 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
#ifdef HAS_ALPN
/* ALPN is only supported on Windows 8.1 / Server 2012 R2 and above.
Also it doesn't seem to be supported for Wine, see curl bug #983. */
- connssl->use_alpn = conn->bits.tls_enable_alpn &&
+ BACKEND->use_alpn = conn->bits.tls_enable_alpn &&
!GetProcAddress(GetModuleHandleA("ntdll"),
"wine_get_version") &&
Curl_verify_windows_version(6, 3, PLATFORM_WINNT,
VERSION_GREATER_THAN_EQUAL);
#else
- connssl->use_alpn = false;
+ BACKEND->use_alpn = false;
#endif
- connssl->cred = NULL;
+ BACKEND->cred = NULL;
/* check for an existing re-usable credential handle */
if(SSL_SET_OPTION(primary.sessionid)) {
Curl_ssl_sessionid_lock(conn);
if(!Curl_ssl_getsessionid(conn, (void **)&old_cred, NULL, sockindex)) {
- connssl->cred = old_cred;
+ BACKEND->cred = old_cred;
infof(data, "schannel: re-using existing credential handle\n");
/* increment the reference counter of the credential/session handle */
- connssl->cred->refcount++;
+ BACKEND->cred->refcount++;
infof(data, "schannel: incremented credential handle refcount = %d\n",
- connssl->cred->refcount);
+ BACKEND->cred->refcount);
}
Curl_ssl_sessionid_unlock(conn);
}
- if(!connssl->cred) {
+ if(!BACKEND->cred) {
/* setup Schannel API options */
memset(&schannel_cred, 0, sizeof(schannel_cred));
schannel_cred.dwVersion = SCHANNEL_CRED_VERSION;
@@ -272,14 +355,14 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
}
/* allocate memory for the re-usable credential handle */
- connssl->cred = (struct curl_schannel_cred *)
+ BACKEND->cred = (struct curl_schannel_cred *)
malloc(sizeof(struct curl_schannel_cred));
- if(!connssl->cred) {
+ if(!BACKEND->cred) {
failf(data, "schannel: unable to allocate memory");
return CURLE_OUT_OF_MEMORY;
}
- memset(connssl->cred, 0, sizeof(struct curl_schannel_cred));
- connssl->cred->refcount = 1;
+ memset(BACKEND->cred, 0, sizeof(struct curl_schannel_cred));
+ BACKEND->cred->refcount = 1;
/* https://msdn.microsoft.com/en-us/library/windows/desktop/aa374716.aspx
*/
@@ -287,8 +370,8 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
s_pSecFn->AcquireCredentialsHandle(NULL, (TCHAR *)UNISP_NAME,
SECPKG_CRED_OUTBOUND, NULL,
&schannel_cred, NULL, NULL,
- &connssl->cred->cred_handle,
- &connssl->cred->time_stamp);
+ &BACKEND->cred->cred_handle,
+ &BACKEND->cred->time_stamp);
if(sspi_status != SEC_E_OK) {
if(sspi_status == SEC_E_WRONG_PRINCIPAL)
@@ -297,7 +380,7 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
else
failf(data, "schannel: AcquireCredentialsHandle failed: %s",
Curl_sspi_strerror(conn, sspi_status));
- Curl_safefree(connssl->cred);
+ Curl_safefree(BACKEND->cred);
return CURLE_SSL_CONNECT_ERROR;
}
}
@@ -312,7 +395,7 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
}
#ifdef HAS_ALPN
- if(connssl->use_alpn) {
+ if(BACKEND->use_alpn) {
int cur = 0;
int list_start_index = 0;
unsigned int *extension_len = NULL;
@@ -370,18 +453,18 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
InitSecBufferDesc(&outbuf_desc, &outbuf, 1);
/* setup request flags */
- connssl->req_flags = ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT |
+ BACKEND->req_flags = ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT |
ISC_REQ_CONFIDENTIALITY | ISC_REQ_ALLOCATE_MEMORY |
ISC_REQ_STREAM;
/* allocate memory for the security context handle */
- connssl->ctxt = (struct curl_schannel_ctxt *)
+ BACKEND->ctxt = (struct curl_schannel_ctxt *)
malloc(sizeof(struct curl_schannel_ctxt));
- if(!connssl->ctxt) {
+ if(!BACKEND->ctxt) {
failf(data, "schannel: unable to allocate memory");
return CURLE_OUT_OF_MEMORY;
}
- memset(connssl->ctxt, 0, sizeof(struct curl_schannel_ctxt));
+ memset(BACKEND->ctxt, 0, sizeof(struct curl_schannel_ctxt));
host_name = Curl_convert_UTF8_to_tchar(hostname);
if(!host_name)
@@ -395,10 +478,10 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
us problems with inbuf regardless. https://github.com/curl/curl/issues/983
*/
sspi_status = s_pSecFn->InitializeSecurityContext(
- &connssl->cred->cred_handle, NULL, host_name, connssl->req_flags, 0, 0,
- (connssl->use_alpn ? &inbuf_desc : NULL),
- 0, &connssl->ctxt->ctxt_handle,
- &outbuf_desc, &connssl->ret_flags, &connssl->ctxt->time_stamp);
+ &BACKEND->cred->cred_handle, NULL, host_name, BACKEND->req_flags, 0, 0,
+ (BACKEND->use_alpn ? &inbuf_desc : NULL),
+ 0, &BACKEND->ctxt->ctxt_handle,
+ &outbuf_desc, &BACKEND->ret_flags, &BACKEND->ctxt->time_stamp);
Curl_unicodefree(host_name);
@@ -409,7 +492,7 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
else
failf(data, "schannel: initial InitializeSecurityContext failed: %s",
Curl_sspi_strerror(conn, sspi_status));
- Curl_safefree(connssl->ctxt);
+ Curl_safefree(BACKEND->ctxt);
return CURLE_SSL_CONNECT_ERROR;
}
@@ -429,10 +512,10 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
infof(data, "schannel: sent initial handshake data: "
"sent %zd bytes\n", written);
- connssl->recv_unrecoverable_err = CURLE_OK;
- connssl->recv_sspi_close_notify = false;
- connssl->recv_connection_closed = false;
- connssl->encdata_is_incomplete = false;
+ BACKEND->recv_unrecoverable_err = CURLE_OK;
+ BACKEND->recv_sspi_close_notify = false;
+ BACKEND->recv_connection_closed = false;
+ BACKEND->encdata_is_incomplete = false;
/* continue to second handshake step */
connssl->connecting_state = ssl_connect_2;
@@ -465,39 +548,39 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
infof(data, "schannel: SSL/TLS connection with %s port %hu (step 2/3)\n",
hostname, conn->remote_port);
- if(!connssl->cred || !connssl->ctxt)
+ if(!BACKEND->cred || !BACKEND->ctxt)
return CURLE_SSL_CONNECT_ERROR;
/* buffer to store previously received and decrypted data */
- if(connssl->decdata_buffer == NULL) {
- connssl->decdata_offset = 0;
- connssl->decdata_length = CURL_SCHANNEL_BUFFER_INIT_SIZE;
- connssl->decdata_buffer = malloc(connssl->decdata_length);
- if(connssl->decdata_buffer == NULL) {
+ if(BACKEND->decdata_buffer == NULL) {
+ BACKEND->decdata_offset = 0;
+ BACKEND->decdata_length = CURL_SCHANNEL_BUFFER_INIT_SIZE;
+ BACKEND->decdata_buffer = malloc(BACKEND->decdata_length);
+ if(BACKEND->decdata_buffer == NULL) {
failf(data, "schannel: unable to allocate memory");
return CURLE_OUT_OF_MEMORY;
}
}
/* buffer to store previously received and encrypted data */
- if(connssl->encdata_buffer == NULL) {
- connssl->encdata_is_incomplete = false;
- connssl->encdata_offset = 0;
- connssl->encdata_length = CURL_SCHANNEL_BUFFER_INIT_SIZE;
- connssl->encdata_buffer = malloc(connssl->encdata_length);
- if(connssl->encdata_buffer == NULL) {
+ if(BACKEND->encdata_buffer == NULL) {
+ BACKEND->encdata_is_incomplete = false;
+ BACKEND->encdata_offset = 0;
+ BACKEND->encdata_length = CURL_SCHANNEL_BUFFER_INIT_SIZE;
+ BACKEND->encdata_buffer = malloc(BACKEND->encdata_length);
+ if(BACKEND->encdata_buffer == NULL) {
failf(data, "schannel: unable to allocate memory");
return CURLE_OUT_OF_MEMORY;
}
}
/* if we need a bigger buffer to read a full message, increase buffer now */
- if(connssl->encdata_length - connssl->encdata_offset <
+ if(BACKEND->encdata_length - BACKEND->encdata_offset <
CURL_SCHANNEL_BUFFER_FREE_SIZE) {
/* increase internal encrypted data buffer */
- reallocated_length = connssl->encdata_offset +
+ reallocated_length = BACKEND->encdata_offset +
CURL_SCHANNEL_BUFFER_FREE_SIZE;
- reallocated_buffer = realloc(connssl->encdata_buffer,
+ reallocated_buffer = realloc(BACKEND->encdata_buffer,
reallocated_length);
if(reallocated_buffer == NULL) {
@@ -505,8 +588,8 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
return CURLE_OUT_OF_MEMORY;
}
else {
- connssl->encdata_buffer = reallocated_buffer;
- connssl->encdata_length = reallocated_length;
+ BACKEND->encdata_buffer = reallocated_buffer;
+ BACKEND->encdata_length = reallocated_length;
}
}
@@ -514,10 +597,10 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
if(doread) {
/* read encrypted handshake data from socket */
result = Curl_read_plain(conn->sock[sockindex],
- (char *) (connssl->encdata_buffer +
- connssl->encdata_offset),
- connssl->encdata_length -
- connssl->encdata_offset,
+ (char *) (BACKEND->encdata_buffer +
+ BACKEND->encdata_offset),
+ BACKEND->encdata_length -
+ BACKEND->encdata_offset,
&nread);
if(result == CURLE_AGAIN) {
if(connssl->connecting_state != ssl_connect_2_writing)
@@ -533,17 +616,17 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
}
/* increase encrypted data buffer offset */
- connssl->encdata_offset += nread;
- connssl->encdata_is_incomplete = false;
+ BACKEND->encdata_offset += nread;
+ BACKEND->encdata_is_incomplete = false;
infof(data, "schannel: encrypted data got %zd\n", nread);
}
infof(data, "schannel: encrypted data buffer: offset %zu length %zu\n",
- connssl->encdata_offset, connssl->encdata_length);
+ BACKEND->encdata_offset, BACKEND->encdata_length);
/* setup input buffers */
- InitSecBuffer(&inbuf[0], SECBUFFER_TOKEN, malloc(connssl->encdata_offset),
- curlx_uztoul(connssl->encdata_offset));
+ InitSecBuffer(&inbuf[0], SECBUFFER_TOKEN, malloc(BACKEND->encdata_offset),
+ curlx_uztoul(BACKEND->encdata_offset));
InitSecBuffer(&inbuf[1], SECBUFFER_EMPTY, NULL, 0);
InitSecBufferDesc(&inbuf_desc, inbuf, 2);
@@ -559,8 +642,8 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
}
/* copy received handshake data into input buffer */
- memcpy(inbuf[0].pvBuffer, connssl->encdata_buffer,
- connssl->encdata_offset);
+ memcpy(inbuf[0].pvBuffer, BACKEND->encdata_buffer,
+ BACKEND->encdata_offset);
host_name = Curl_convert_UTF8_to_tchar(hostname);
if(!host_name)
@@ -569,9 +652,9 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
/* https://msdn.microsoft.com/en-us/library/windows/desktop/aa375924.aspx
*/
sspi_status = s_pSecFn->InitializeSecurityContext(
- &connssl->cred->cred_handle, &connssl->ctxt->ctxt_handle,
- host_name, connssl->req_flags, 0, 0, &inbuf_desc, 0, NULL,
- &outbuf_desc, &connssl->ret_flags, &connssl->ctxt->time_stamp);
+ &BACKEND->cred->cred_handle, &BACKEND->ctxt->ctxt_handle,
+ host_name, BACKEND->req_flags, 0, 0, &inbuf_desc, 0, NULL,
+ &outbuf_desc, &BACKEND->ret_flags, &BACKEND->ctxt->time_stamp);
Curl_unicodefree(host_name);
@@ -580,7 +663,7 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
/* check if the handshake was incomplete */
if(sspi_status == SEC_E_INCOMPLETE_MESSAGE) {
- connssl->encdata_is_incomplete = true;
+ BACKEND->encdata_is_incomplete = true;
connssl->connecting_state = ssl_connect_2_reading;
infof(data, "schannel: received incomplete message, need more data\n");
return CURLE_OK;
@@ -590,8 +673,8 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
the handshake without one. This will allow connections to servers which
request a client certificate but do not require it. */
if(sspi_status == SEC_I_INCOMPLETE_CREDENTIALS &&
- !(connssl->req_flags & ISC_REQ_USE_SUPPLIED_CREDS)) {
- connssl->req_flags |= ISC_REQ_USE_SUPPLIED_CREDS;
+ !(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");
return CURLE_OK;
@@ -631,7 +714,7 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
failf(data, "schannel: next InitializeSecurityContext failed: %s",
Curl_sspi_strerror(conn, sspi_status));
return sspi_status == SEC_E_UNTRUSTED_ROOT ?
- CURLE_SSL_CACERT_BADFILE : CURLE_SSL_CONNECT_ERROR;
+ CURLE_SSL_CACERT : CURLE_SSL_CONNECT_ERROR;
}
/* check if there was additional remaining encrypted data */
@@ -649,11 +732,11 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
*/
/* check if the remaining data is less than the total amount
and therefore begins after the already processed data */
- if(connssl->encdata_offset > inbuf[1].cbBuffer) {
- memmove(connssl->encdata_buffer,
- (connssl->encdata_buffer + connssl->encdata_offset) -
+ if(BACKEND->encdata_offset > inbuf[1].cbBuffer) {
+ memmove(BACKEND->encdata_buffer,
+ (BACKEND->encdata_buffer + BACKEND->encdata_offset) -
inbuf[1].cbBuffer, inbuf[1].cbBuffer);
- connssl->encdata_offset = inbuf[1].cbBuffer;
+ BACKEND->encdata_offset = inbuf[1].cbBuffer;
if(sspi_status == SEC_I_CONTINUE_NEEDED) {
doread = FALSE;
continue;
@@ -661,7 +744,7 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
}
}
else {
- connssl->encdata_offset = 0;
+ BACKEND->encdata_offset = 0;
}
break;
}
@@ -709,27 +792,27 @@ schannel_connect_step3(struct connectdata *conn, int sockindex)
infof(data, "schannel: SSL/TLS connection with %s port %hu (step 3/3)\n",
hostname, conn->remote_port);
- if(!connssl->cred)
+ if(!BACKEND->cred)
return CURLE_SSL_CONNECT_ERROR;
/* check if the required context attributes are met */
- if(connssl->ret_flags != connssl->req_flags) {
- if(!(connssl->ret_flags & ISC_RET_SEQUENCE_DETECT))
+ if(BACKEND->ret_flags != BACKEND->req_flags) {
+ if(!(BACKEND->ret_flags & ISC_RET_SEQUENCE_DETECT))
failf(data, "schannel: failed to setup sequence detection");
- if(!(connssl->ret_flags & ISC_RET_REPLAY_DETECT))
+ if(!(BACKEND->ret_flags & ISC_RET_REPLAY_DETECT))
failf(data, "schannel: failed to setup replay detection");
- if(!(connssl->ret_flags & ISC_RET_CONFIDENTIALITY))
+ if(!(BACKEND->ret_flags & ISC_RET_CONFIDENTIALITY))
failf(data, "schannel: failed to setup confidentiality");
- if(!(connssl->ret_flags & ISC_RET_ALLOCATED_MEMORY))
+ if(!(BACKEND->ret_flags & ISC_RET_ALLOCATED_MEMORY))
failf(data, "schannel: failed to setup memory allocation");
- if(!(connssl->ret_flags & ISC_RET_STREAM))
+ if(!(BACKEND->ret_flags & ISC_RET_STREAM))
failf(data, "schannel: failed to setup stream orientation");
return CURLE_SSL_CONNECT_ERROR;
}
#ifdef HAS_ALPN
- if(connssl->use_alpn) {
- sspi_status = s_pSecFn->QueryContextAttributes(&connssl->ctxt->ctxt_handle,
+ if(BACKEND->use_alpn) {
+ sspi_status = s_pSecFn->QueryContextAttributes(&BACKEND->ctxt->ctxt_handle,
SECPKG_ATTR_APPLICATION_PROTOCOL, &alpn_result);
if(sspi_status != SEC_E_OK) {
@@ -771,7 +854,7 @@ schannel_connect_step3(struct connectdata *conn, int sockindex)
incache = !(Curl_ssl_getsessionid(conn, (void **)&old_cred, NULL,
sockindex));
if(incache) {
- if(old_cred != connssl->cred) {
+ if(old_cred != BACKEND->cred) {
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);
@@ -779,7 +862,7 @@ schannel_connect_step3(struct connectdata *conn, int sockindex)
}
}
if(!incache) {
- result = Curl_ssl_addsessionid(conn, (void *)connssl->cred,
+ result = Curl_ssl_addsessionid(conn, (void *)BACKEND->cred,
sizeof(struct curl_schannel_cred),
sockindex);
if(result) {
@@ -789,7 +872,7 @@ schannel_connect_step3(struct connectdata *conn, int sockindex)
}
else {
/* this cred session is now also referenced by sessionid cache */
- connssl->cred->refcount++;
+ BACKEND->cred->refcount++;
infof(data, "schannel: stored credential handle in session cache\n");
}
}
@@ -797,7 +880,7 @@ schannel_connect_step3(struct connectdata *conn, int sockindex)
}
if(data->set.ssl.certinfo) {
- sspi_status = s_pSecFn->QueryContextAttributes(&connssl->ctxt->ctxt_handle,
+ sspi_status = s_pSecFn->QueryContextAttributes(&BACKEND->ctxt->ctxt_handle,
SECPKG_ATTR_REMOTE_CERT_CONTEXT, &ccert_context);
if((sspi_status != SEC_E_OK) || (ccert_context == NULL)) {
@@ -951,11 +1034,11 @@ schannel_send(struct connectdata *conn, int sockindex,
CURLcode result;
/* check if the maximum stream sizes were queried */
- if(connssl->stream_sizes.cbMaximumMessage == 0) {
+ if(BACKEND->stream_sizes.cbMaximumMessage == 0) {
sspi_status = s_pSecFn->QueryContextAttributes(
- &connssl->ctxt->ctxt_handle,
+ &BACKEND->ctxt->ctxt_handle,
SECPKG_ATTR_STREAM_SIZES,
- &connssl->stream_sizes);
+ &BACKEND->stream_sizes);
if(sspi_status != SEC_E_OK) {
*err = CURLE_SEND_ERROR;
return -1;
@@ -963,14 +1046,13 @@ schannel_send(struct connectdata *conn, int sockindex,
}
/* check if the buffer is longer than the maximum message length */
- if(len > connssl->stream_sizes.cbMaximumMessage) {
- *err = CURLE_SEND_ERROR;
- return -1;
+ if(len > BACKEND->stream_sizes.cbMaximumMessage) {
+ len = BACKEND->stream_sizes.cbMaximumMessage;
}
/* calculate the complete message length and allocate a buffer for it */
- data_len = connssl->stream_sizes.cbHeader + len +
- connssl->stream_sizes.cbTrailer;
+ data_len = BACKEND->stream_sizes.cbHeader + len +
+ BACKEND->stream_sizes.cbTrailer;
data = (unsigned char *) malloc(data_len);
if(data == NULL) {
*err = CURLE_OUT_OF_MEMORY;
@@ -979,12 +1061,12 @@ schannel_send(struct connectdata *conn, int sockindex,
/* setup output buffers (header, data, trailer, empty) */
InitSecBuffer(&outbuf[0], SECBUFFER_STREAM_HEADER,
- data, connssl->stream_sizes.cbHeader);
+ data, BACKEND->stream_sizes.cbHeader);
InitSecBuffer(&outbuf[1], SECBUFFER_DATA,
- data + connssl->stream_sizes.cbHeader, curlx_uztoul(len));
+ data + BACKEND->stream_sizes.cbHeader, curlx_uztoul(len));
InitSecBuffer(&outbuf[2], SECBUFFER_STREAM_TRAILER,
- data + connssl->stream_sizes.cbHeader + len,
- connssl->stream_sizes.cbTrailer);
+ data + BACKEND->stream_sizes.cbHeader + len,
+ BACKEND->stream_sizes.cbTrailer);
InitSecBuffer(&outbuf[3], SECBUFFER_EMPTY, NULL, 0);
InitSecBufferDesc(&outbuf_desc, outbuf, 4);
@@ -992,7 +1074,7 @@ schannel_send(struct connectdata *conn, int sockindex,
memcpy(outbuf[1].pvBuffer, buf, len);
/* https://msdn.microsoft.com/en-us/library/windows/desktop/aa375390.aspx */
- sspi_status = s_pSecFn->EncryptMessage(&connssl->ctxt->ctxt_handle, 0,
+ sspi_status = s_pSecFn->EncryptMessage(&BACKEND->ctxt->ctxt_handle, 0,
&outbuf_desc, 0);
/* check if the message was encrypted */
@@ -1102,7 +1184,7 @@ schannel_recv(struct connectdata *conn, int sockindex,
size_t min_encdata_length = len + CURL_SCHANNEL_BUFFER_FREE_SIZE;
/****************************************************************************
- * Don't return or set connssl->recv_unrecoverable_err unless in the cleanup.
+ * Don't return or set BACKEND->recv_unrecoverable_err unless in the cleanup.
* The pattern for return error is set *err, optional infof, goto cleanup.
*
* Our priority is to always return as much decrypted data to the caller as
@@ -1114,16 +1196,16 @@ schannel_recv(struct connectdata *conn, int sockindex,
infof(data, "schannel: client wants to read %zu bytes\n", len);
*err = CURLE_OK;
- if(len && len <= connssl->decdata_offset) {
+ if(len && len <= BACKEND->decdata_offset) {
infof(data, "schannel: enough decrypted data is already available\n");
goto cleanup;
}
- else if(connssl->recv_unrecoverable_err) {
- *err = connssl->recv_unrecoverable_err;
+ else if(BACKEND->recv_unrecoverable_err) {
+ *err = BACKEND->recv_unrecoverable_err;
infof(data, "schannel: an unrecoverable error occurred in a prior call\n");
goto cleanup;
}
- else if(connssl->recv_sspi_close_notify) {
+ else if(BACKEND->recv_sspi_close_notify) {
/* once a server has indicated shutdown there is no more encrypted data */
infof(data, "schannel: server indicated shutdown in a prior call\n");
goto cleanup;
@@ -1135,17 +1217,17 @@ schannel_recv(struct connectdata *conn, int sockindex,
*/
; /* do nothing */
}
- else if(!connssl->recv_connection_closed) {
+ else if(!BACKEND->recv_connection_closed) {
/* increase enc buffer in order to fit the requested amount of data */
- size = connssl->encdata_length - connssl->encdata_offset;
+ size = BACKEND->encdata_length - BACKEND->encdata_offset;
if(size < CURL_SCHANNEL_BUFFER_FREE_SIZE ||
- connssl->encdata_length < min_encdata_length) {
- reallocated_length = connssl->encdata_offset +
+ BACKEND->encdata_length < min_encdata_length) {
+ reallocated_length = BACKEND->encdata_offset +
CURL_SCHANNEL_BUFFER_FREE_SIZE;
if(reallocated_length < min_encdata_length) {
reallocated_length = min_encdata_length;
}
- reallocated_buffer = realloc(connssl->encdata_buffer,
+ reallocated_buffer = realloc(BACKEND->encdata_buffer,
reallocated_length);
if(reallocated_buffer == NULL) {
*err = CURLE_OUT_OF_MEMORY;
@@ -1153,20 +1235,20 @@ schannel_recv(struct connectdata *conn, int sockindex,
goto cleanup;
}
- connssl->encdata_buffer = reallocated_buffer;
- connssl->encdata_length = reallocated_length;
- size = connssl->encdata_length - connssl->encdata_offset;
+ 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",
- connssl->encdata_length);
+ BACKEND->encdata_length);
}
infof(data, "schannel: encrypted data buffer: offset %zu length %zu\n",
- connssl->encdata_offset, connssl->encdata_length);
+ BACKEND->encdata_offset, BACKEND->encdata_length);
/* read encrypted data from socket */
*err = Curl_read_plain(conn->sock[sockindex],
- (char *)(connssl->encdata_buffer +
- connssl->encdata_offset),
+ (char *)(BACKEND->encdata_buffer +
+ BACKEND->encdata_offset),
size, &nread);
if(*err) {
nread = -1;
@@ -1178,26 +1260,26 @@ schannel_recv(struct connectdata *conn, int sockindex,
infof(data, "schannel: Curl_read_plain returned error %d\n", *err);
}
else if(nread == 0) {
- connssl->recv_connection_closed = true;
+ BACKEND->recv_connection_closed = true;
infof(data, "schannel: server closed the connection\n");
}
else if(nread > 0) {
- connssl->encdata_offset += (size_t)nread;
- connssl->encdata_is_incomplete = false;
+ BACKEND->encdata_offset += (size_t)nread;
+ BACKEND->encdata_is_incomplete = false;
infof(data, "schannel: encrypted data got %zd\n", nread);
}
}
infof(data, "schannel: encrypted data buffer: offset %zu length %zu\n",
- connssl->encdata_offset, connssl->encdata_length);
+ BACKEND->encdata_offset, BACKEND->encdata_length);
/* decrypt loop */
- while(connssl->encdata_offset > 0 && sspi_status == SEC_E_OK &&
- (!len || connssl->decdata_offset < len ||
- connssl->recv_connection_closed)) {
+ while(BACKEND->encdata_offset > 0 && sspi_status == SEC_E_OK &&
+ (!len || BACKEND->decdata_offset < len ||
+ BACKEND->recv_connection_closed)) {
/* prepare data buffer for DecryptMessage call */
- InitSecBuffer(&inbuf[0], SECBUFFER_DATA, connssl->encdata_buffer,
- curlx_uztoul(connssl->encdata_offset));
+ InitSecBuffer(&inbuf[0], SECBUFFER_DATA, BACKEND->encdata_buffer,
+ curlx_uztoul(BACKEND->encdata_offset));
/* we need 3 more empty input buffers for possible output */
InitSecBuffer(&inbuf[1], SECBUFFER_EMPTY, NULL, 0);
@@ -1207,7 +1289,7 @@ schannel_recv(struct connectdata *conn, int sockindex,
/* https://msdn.microsoft.com/en-us/library/windows/desktop/aa375348.aspx
*/
- sspi_status = s_pSecFn->DecryptMessage(&connssl->ctxt->ctxt_handle,
+ sspi_status = s_pSecFn->DecryptMessage(&BACKEND->ctxt->ctxt_handle,
&inbuf_desc, 0, NULL);
/* check if everything went fine (server may want to renegotiate
@@ -1223,36 +1305,36 @@ schannel_recv(struct connectdata *conn, int sockindex,
/* increase buffer in order to fit the received amount of data */
size = inbuf[1].cbBuffer > CURL_SCHANNEL_BUFFER_FREE_SIZE ?
inbuf[1].cbBuffer : CURL_SCHANNEL_BUFFER_FREE_SIZE;
- if(connssl->decdata_length - connssl->decdata_offset < size ||
- connssl->decdata_length < len) {
+ if(BACKEND->decdata_length - BACKEND->decdata_offset < size ||
+ BACKEND->decdata_length < len) {
/* increase internal decrypted data buffer */
- reallocated_length = connssl->decdata_offset + size;
+ reallocated_length = BACKEND->decdata_offset + size;
/* make sure that the requested amount of data fits */
if(reallocated_length < len) {
reallocated_length = len;
}
- reallocated_buffer = realloc(connssl->decdata_buffer,
+ reallocated_buffer = realloc(BACKEND->decdata_buffer,
reallocated_length);
if(reallocated_buffer == NULL) {
*err = CURLE_OUT_OF_MEMORY;
failf(data, "schannel: unable to re-allocate memory");
goto cleanup;
}
- connssl->decdata_buffer = reallocated_buffer;
- connssl->decdata_length = reallocated_length;
+ BACKEND->decdata_buffer = reallocated_buffer;
+ BACKEND->decdata_length = reallocated_length;
}
/* copy decrypted data to internal buffer */
size = inbuf[1].cbBuffer;
if(size) {
- memcpy(connssl->decdata_buffer + connssl->decdata_offset,
+ memcpy(BACKEND->decdata_buffer + BACKEND->decdata_offset,
inbuf[1].pvBuffer, size);
- connssl->decdata_offset += size;
+ BACKEND->decdata_offset += size;
}
infof(data, "schannel: decrypted data added: %zu\n", size);
infof(data, "schannel: decrypted data cached: offset %zu length %zu\n",
- connssl->decdata_offset, connssl->decdata_length);
+ BACKEND->decdata_offset, BACKEND->decdata_length);
}
/* check for remaining encrypted data */
@@ -1263,21 +1345,21 @@ schannel_recv(struct connectdata *conn, int sockindex,
/* check if the remaining data is less than the total amount
* and therefore begins after the already processed data
*/
- if(connssl->encdata_offset > inbuf[3].cbBuffer) {
+ if(BACKEND->encdata_offset > inbuf[3].cbBuffer) {
/* move remaining encrypted data forward to the beginning of
buffer */
- memmove(connssl->encdata_buffer,
- (connssl->encdata_buffer + connssl->encdata_offset) -
+ memmove(BACKEND->encdata_buffer,
+ (BACKEND->encdata_buffer + BACKEND->encdata_offset) -
inbuf[3].cbBuffer, inbuf[3].cbBuffer);
- connssl->encdata_offset = inbuf[3].cbBuffer;
+ BACKEND->encdata_offset = inbuf[3].cbBuffer;
}
infof(data, "schannel: encrypted data cached: offset %zu length %zu\n",
- connssl->encdata_offset, connssl->encdata_length);
+ BACKEND->encdata_offset, BACKEND->encdata_length);
}
else {
/* reset encrypted buffer offset, because there is no data remaining */
- connssl->encdata_offset = 0;
+ BACKEND->encdata_offset = 0;
}
/* check if server wants to renegotiate the connection context */
@@ -1287,7 +1369,7 @@ schannel_recv(struct connectdata *conn, int sockindex,
infof(data, "schannel: can't renogotiate, an error is pending\n");
goto cleanup;
}
- if(connssl->encdata_offset) {
+ if(BACKEND->encdata_offset) {
*err = CURLE_RECV_ERROR;
infof(data, "schannel: can't renogotiate, "
"encrypted data available\n");
@@ -1311,16 +1393,16 @@ schannel_recv(struct connectdata *conn, int sockindex,
else if(sspi_status == SEC_I_CONTEXT_EXPIRED) {
/* In Windows 2000 SEC_I_CONTEXT_EXPIRED (close_notify) is not
returned so we have to work around that in cleanup. */
- connssl->recv_sspi_close_notify = true;
- if(!connssl->recv_connection_closed) {
- connssl->recv_connection_closed = true;
+ BACKEND->recv_sspi_close_notify = true;
+ if(!BACKEND->recv_connection_closed) {
+ BACKEND->recv_connection_closed = true;
infof(data, "schannel: server closed the connection\n");
}
goto cleanup;
}
}
else if(sspi_status == SEC_E_INCOMPLETE_MESSAGE) {
- connssl->encdata_is_incomplete = true;
+ BACKEND->encdata_is_incomplete = true;
if(!*err)
*err = CURLE_AGAIN;
infof(data, "schannel: failed to decrypt data, need more data\n");
@@ -1335,10 +1417,10 @@ schannel_recv(struct connectdata *conn, int sockindex,
}
infof(data, "schannel: encrypted data buffer: offset %zu length %zu\n",
- connssl->encdata_offset, connssl->encdata_length);
+ BACKEND->encdata_offset, BACKEND->encdata_length);
infof(data, "schannel: decrypted data buffer: offset %zu length %zu\n",
- connssl->decdata_offset, connssl->decdata_length);
+ BACKEND->decdata_offset, BACKEND->decdata_length);
cleanup:
/* Warning- there is no guarantee the encdata state is valid at this point */
@@ -1352,13 +1434,13 @@ cleanup:
return close_notify. In that case if the connection was closed we assume it
was graceful (close_notify) since there doesn't seem to be a way to tell.
*/
- if(len && !connssl->decdata_offset && connssl->recv_connection_closed &&
- !connssl->recv_sspi_close_notify) {
+ if(len && !BACKEND->decdata_offset && BACKEND->recv_connection_closed &&
+ !BACKEND->recv_sspi_close_notify) {
bool isWin2k = Curl_verify_windows_version(5, 0, PLATFORM_WINNT,
VERSION_EQUAL);
if(isWin2k && sspi_status == SEC_E_OK)
- connssl->recv_sspi_close_notify = true;
+ BACKEND->recv_sspi_close_notify = true;
else {
*err = CURLE_RECV_ERROR;
infof(data, "schannel: server closed abruptly (missing close_notify)\n");
@@ -1367,23 +1449,23 @@ cleanup:
/* Any error other than CURLE_AGAIN is an unrecoverable error. */
if(*err && *err != CURLE_AGAIN)
- connssl->recv_unrecoverable_err = *err;
+ BACKEND->recv_unrecoverable_err = *err;
- size = len < connssl->decdata_offset ? len : connssl->decdata_offset;
+ size = len < BACKEND->decdata_offset ? len : BACKEND->decdata_offset;
if(size) {
- memcpy(buf, connssl->decdata_buffer, size);
- memmove(connssl->decdata_buffer, connssl->decdata_buffer + size,
- connssl->decdata_offset - size);
- connssl->decdata_offset -= size;
+ memcpy(buf, BACKEND->decdata_buffer, size);
+ 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",
- connssl->decdata_offset, connssl->decdata_length);
+ BACKEND->decdata_offset, BACKEND->decdata_length);
*err = CURLE_OK;
return (ssize_t)size;
}
- if(!*err && !connssl->recv_connection_closed)
+ if(!*err && !BACKEND->recv_connection_closed)
*err = CURLE_AGAIN;
/* It's debatable what to return when !len. We could return whatever error we
@@ -1395,15 +1477,13 @@ cleanup:
return *err ? -1 : 0;
}
-CURLcode
-Curl_schannel_connect_nonblocking(struct connectdata *conn, int sockindex,
- bool *done)
+static CURLcode Curl_schannel_connect_nonblocking(struct connectdata *conn,
+ int sockindex, bool *done)
{
return schannel_connect_common(conn, sockindex, TRUE, done);
}
-CURLcode
-Curl_schannel_connect(struct connectdata *conn, int sockindex)
+static CURLcode Curl_schannel_connect(struct connectdata *conn, int sockindex)
{
CURLcode result;
bool done = FALSE;
@@ -1417,25 +1497,38 @@ Curl_schannel_connect(struct connectdata *conn, int sockindex)
return CURLE_OK;
}
-bool Curl_schannel_data_pending(const struct connectdata *conn, int sockindex)
+static bool Curl_schannel_data_pending(const struct connectdata *conn,
+ int sockindex)
{
const struct ssl_connect_data *connssl = &conn->ssl[sockindex];
if(connssl->use) /* SSL/TLS is in use */
- return (connssl->decdata_offset > 0 ||
- (connssl->encdata_offset > 0 && !connssl->encdata_is_incomplete));
+ return (BACKEND->decdata_offset > 0 ||
+ (BACKEND->encdata_offset > 0 && !BACKEND->encdata_is_incomplete));
else
return FALSE;
}
-void Curl_schannel_close(struct connectdata *conn, int sockindex)
+static void Curl_schannel_close(struct connectdata *conn, int sockindex)
{
if(conn->ssl[sockindex].use)
/* if the SSL/TLS channel hasn't been shut down yet, do that now. */
Curl_ssl_shutdown(conn, sockindex);
}
-int Curl_schannel_shutdown(struct connectdata *conn, int sockindex)
+static void Curl_schannel_session_free(void *ptr)
+{
+ /* this is expected to be called under sessionid lock */
+ struct curl_schannel_cred *cred = ptr;
+
+ cred->refcount--;
+ if(cred->refcount == 0) {
+ s_pSecFn->FreeCredentialsHandle(&cred->cred_handle);
+ Curl_safefree(cred);
+ }
+}
+
+static int Curl_schannel_shutdown(struct connectdata *conn, int sockindex)
{
/* See https://msdn.microsoft.com/en-us/library/windows/desktop/aa380138.aspx
* Shutting Down an Schannel Connection
@@ -1448,7 +1541,7 @@ int Curl_schannel_shutdown(struct connectdata *conn, int sockindex)
infof(data, "schannel: shutting down SSL/TLS connection with %s port %hu\n",
hostname, conn->remote_port);
- if(connssl->cred && connssl->ctxt) {
+ if(BACKEND->cred && BACKEND->ctxt) {
SecBufferDesc BuffDesc;
SecBuffer Buffer;
SECURITY_STATUS sspi_status;
@@ -1461,7 +1554,7 @@ int Curl_schannel_shutdown(struct connectdata *conn, int sockindex)
InitSecBuffer(&Buffer, SECBUFFER_TOKEN, &dwshut, sizeof(dwshut));
InitSecBufferDesc(&BuffDesc, &Buffer, 1);
- sspi_status = s_pSecFn->ApplyControlToken(&connssl->ctxt->ctxt_handle,
+ sspi_status = s_pSecFn->ApplyControlToken(&BACKEND->ctxt->ctxt_handle,
&BuffDesc);
if(sspi_status != SEC_E_OK)
@@ -1477,18 +1570,18 @@ int Curl_schannel_shutdown(struct connectdata *conn, int sockindex)
InitSecBufferDesc(&outbuf_desc, &outbuf, 1);
sspi_status = s_pSecFn->InitializeSecurityContext(
- &connssl->cred->cred_handle,
- &connssl->ctxt->ctxt_handle,
+ &BACKEND->cred->cred_handle,
+ &BACKEND->ctxt->ctxt_handle,
host_name,
- connssl->req_flags,
+ BACKEND->req_flags,
0,
0,
NULL,
0,
- &connssl->ctxt->ctxt_handle,
+ &BACKEND->ctxt->ctxt_handle,
&outbuf_desc,
- &connssl->ret_flags,
- &connssl->ctxt->time_stamp);
+ &BACKEND->ret_flags,
+ &BACKEND->ctxt->time_stamp);
Curl_unicodefree(host_name);
@@ -1507,71 +1600,62 @@ int Curl_schannel_shutdown(struct connectdata *conn, int sockindex)
}
/* free SSPI Schannel API security context handle */
- if(connssl->ctxt) {
+ if(BACKEND->ctxt) {
infof(data, "schannel: clear security context handle\n");
- s_pSecFn->DeleteSecurityContext(&connssl->ctxt->ctxt_handle);
- Curl_safefree(connssl->ctxt);
+ s_pSecFn->DeleteSecurityContext(&BACKEND->ctxt->ctxt_handle);
+ Curl_safefree(BACKEND->ctxt);
}
/* free SSPI Schannel API credential handle */
- if(connssl->cred) {
+ if(BACKEND->cred) {
Curl_ssl_sessionid_lock(conn);
- Curl_schannel_session_free(connssl->cred);
+ Curl_schannel_session_free(BACKEND->cred);
Curl_ssl_sessionid_unlock(conn);
- connssl->cred = NULL;
+ BACKEND->cred = NULL;
}
/* free internal buffer for received encrypted data */
- if(connssl->encdata_buffer != NULL) {
- Curl_safefree(connssl->encdata_buffer);
- connssl->encdata_length = 0;
- connssl->encdata_offset = 0;
- connssl->encdata_is_incomplete = false;
+ if(BACKEND->encdata_buffer != NULL) {
+ Curl_safefree(BACKEND->encdata_buffer);
+ BACKEND->encdata_length = 0;
+ BACKEND->encdata_offset = 0;
+ BACKEND->encdata_is_incomplete = false;
}
/* free internal buffer for received decrypted data */
- if(connssl->decdata_buffer != NULL) {
- Curl_safefree(connssl->decdata_buffer);
- connssl->decdata_length = 0;
- connssl->decdata_offset = 0;
+ if(BACKEND->decdata_buffer != NULL) {
+ Curl_safefree(BACKEND->decdata_buffer);
+ BACKEND->decdata_length = 0;
+ BACKEND->decdata_offset = 0;
}
return CURLE_OK;
}
-void Curl_schannel_session_free(void *ptr)
-{
- /* this is expected to be called under sessionid lock */
- struct curl_schannel_cred *cred = ptr;
-
- cred->refcount--;
- if(cred->refcount == 0) {
- s_pSecFn->FreeCredentialsHandle(&cred->cred_handle);
- Curl_safefree(cred);
- }
-}
-
-int Curl_schannel_init(void)
+static int Curl_schannel_init(void)
{
return (Curl_sspi_global_init() == CURLE_OK ? 1 : 0);
}
-void Curl_schannel_cleanup(void)
+static void Curl_schannel_cleanup(void)
{
Curl_sspi_global_cleanup();
}
-size_t Curl_schannel_version(char *buffer, size_t size)
+static size_t Curl_schannel_version(char *buffer, size_t size)
{
size = snprintf(buffer, size, "WinSSL");
return size;
}
-CURLcode Curl_schannel_random(unsigned char *entropy, size_t length)
+static CURLcode Curl_schannel_random(struct Curl_easy *data UNUSED_PARAM,
+ unsigned char *entropy, size_t length)
{
HCRYPTPROV hCryptProv = 0;
+ (void)data;
+
if(!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL,
CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
return CURLE_FAILED_INIT;
@@ -1598,7 +1682,7 @@ static CURLcode verify_certificate(struct connectdata *conn, int sockindex)
conn->http_proxy.host.name :
conn->host.name;
- status = s_pSecFn->QueryContextAttributes(&connssl->ctxt->ctxt_handle,
+ status = s_pSecFn->QueryContextAttributes(&BACKEND->ctxt->ctxt_handle,
SECPKG_ATTR_REMOTE_CERT_CONTEXT,
&pCertContextServer);
@@ -1725,4 +1809,44 @@ static CURLcode verify_certificate(struct connectdata *conn, int sockindex)
}
#endif /* _WIN32_WCE */
+static void *Curl_schannel_get_internals(struct ssl_connect_data *connssl,
+ CURLINFO info UNUSED_PARAM)
+{
+ (void)info;
+ return &BACKEND->ctxt->ctxt_handle;
+}
+
+const struct Curl_ssl Curl_ssl_schannel = {
+ { CURLSSLBACKEND_SCHANNEL, "schannel" }, /* info */
+
+ 0, /* have_ca_path */
+ 1, /* have_certinfo */
+ 0, /* have_pinnedpubkey */
+ 0, /* have_ssl_ctx */
+ 0, /* support_https_proxy */
+
+ sizeof(struct ssl_backend_data),
+
+ Curl_schannel_init, /* init */
+ Curl_schannel_cleanup, /* cleanup */
+ Curl_schannel_version, /* version */
+ Curl_none_check_cxn, /* check_cxn */
+ Curl_schannel_shutdown, /* shutdown */
+ Curl_schannel_data_pending, /* data_pending */
+ Curl_schannel_random, /* random */
+ Curl_none_cert_status_request, /* cert_status_request */
+ Curl_schannel_connect, /* connect */
+ Curl_schannel_connect_nonblocking, /* connect_nonblocking */
+ Curl_schannel_get_internals, /* get_internals */
+ Curl_schannel_close, /* close */
+ Curl_none_close_all, /* close_all */
+ Curl_schannel_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_SCHANNEL */
diff --git a/Utilities/cmcurl/lib/vtls/schannel.h b/Utilities/cmcurl/lib/vtls/schannel.h
index 8627c63..932103d 100644
--- a/Utilities/cmcurl/lib/vtls/schannel.h
+++ b/Utilities/cmcurl/lib/vtls/schannel.h
@@ -28,94 +28,7 @@
#include "urldata.h"
-#ifndef UNISP_NAME_A
-#define UNISP_NAME_A "Microsoft Unified Security Protocol Provider"
-#endif
-
-#ifndef UNISP_NAME_W
-#define UNISP_NAME_W L"Microsoft Unified Security Protocol Provider"
-#endif
-
-#ifndef UNISP_NAME
-#ifdef UNICODE
-#define UNISP_NAME UNISP_NAME_W
-#else
-#define UNISP_NAME UNISP_NAME_A
-#endif
-#endif
-
-#ifndef SP_PROT_SSL2_CLIENT
-#define SP_PROT_SSL2_CLIENT 0x00000008
-#endif
-
-#ifndef SP_PROT_SSL3_CLIENT
-#define SP_PROT_SSL3_CLIENT 0x00000008
-#endif
-
-#ifndef SP_PROT_TLS1_CLIENT
-#define SP_PROT_TLS1_CLIENT 0x00000080
-#endif
-
-#ifndef SP_PROT_TLS1_0_CLIENT
-#define SP_PROT_TLS1_0_CLIENT SP_PROT_TLS1_CLIENT
-#endif
-
-#ifndef SP_PROT_TLS1_1_CLIENT
-#define SP_PROT_TLS1_1_CLIENT 0x00000200
-#endif
-
-#ifndef SP_PROT_TLS1_2_CLIENT
-#define SP_PROT_TLS1_2_CLIENT 0x00000800
-#endif
-
-#ifndef SECBUFFER_ALERT
-#define SECBUFFER_ALERT 17
-#endif
-
-/* Both schannel buffer sizes must be > 0 */
-#define CURL_SCHANNEL_BUFFER_INIT_SIZE 4096
-#define CURL_SCHANNEL_BUFFER_FREE_SIZE 1024
-
-
-CURLcode Curl_schannel_connect(struct connectdata *conn, int sockindex);
-
-CURLcode Curl_schannel_connect_nonblocking(struct connectdata *conn,
- int sockindex,
- bool *done);
-
-bool Curl_schannel_data_pending(const struct connectdata *conn, int sockindex);
-void Curl_schannel_close(struct connectdata *conn, int sockindex);
-int Curl_schannel_shutdown(struct connectdata *conn, int sockindex);
-void Curl_schannel_session_free(void *ptr);
-
-int Curl_schannel_init(void);
-void Curl_schannel_cleanup(void);
-size_t Curl_schannel_version(char *buffer, size_t size);
-
-CURLcode Curl_schannel_random(unsigned char *entropy, size_t length);
-
-/* Set the API backend definition to Schannel */
-#define CURL_SSL_BACKEND CURLSSLBACKEND_SCHANNEL
-
-/* this backend supports CURLOPT_CERTINFO */
-#define have_curlssl_certinfo 1
-
-/* API setup for Schannel */
-#define curlssl_init Curl_schannel_init
-#define curlssl_cleanup Curl_schannel_cleanup
-#define curlssl_connect Curl_schannel_connect
-#define curlssl_connect_nonblocking Curl_schannel_connect_nonblocking
-#define curlssl_session_free Curl_schannel_session_free
-#define curlssl_close_all(x) ((void)x)
-#define curlssl_close Curl_schannel_close
-#define curlssl_shutdown Curl_schannel_shutdown
-#define curlssl_set_engine(x,y) ((void)x, (void)y, CURLE_NOT_BUILT_IN)
-#define curlssl_set_engine_default(x) ((void)x, CURLE_NOT_BUILT_IN)
-#define curlssl_engines_list(x) ((void)x, (struct curl_slist *)NULL)
-#define curlssl_version Curl_schannel_version
-#define curlssl_check_cxn(x) ((void)x, -1)
-#define curlssl_data_pending Curl_schannel_data_pending
-#define curlssl_random(x,y,z) ((void)x, Curl_schannel_random(y,z))
+extern const struct Curl_ssl Curl_ssl_schannel;
#endif /* USE_SCHANNEL */
#endif /* HEADER_CURL_SCHANNEL_H */
diff --git a/Utilities/cmcurl/lib/vtls/vtls.c b/Utilities/cmcurl/lib/vtls/vtls.c
index d5d0971..bb8fda4 100644
--- a/Utilities/cmcurl/lib/vtls/vtls.c
+++ b/Utilities/cmcurl/lib/vtls/vtls.c
@@ -28,17 +28,9 @@
to any specific SSL-layer.
Curl_ssl_ - prefix for generic ones
- Curl_ossl_ - prefix for OpenSSL ones
- Curl_gtls_ - prefix for GnuTLS ones
- Curl_nss_ - prefix for NSS ones
- Curl_gskit_ - prefix for GSKit ones
- Curl_polarssl_ - prefix for PolarSSL ones
- Curl_cyassl_ - prefix for CyaSSL ones
- Curl_schannel_ - prefix for Schannel SSPI ones
- Curl_darwinssl_ - prefix for SecureTransport (Darwin) ones
-
- Note that this source code uses curlssl_* functions, and they are all
- defines/macros #defined by the lib-specific header files.
+
+ Note that this source code uses the functions of the configured SSL
+ backend via the global Curl_ssl instance.
"SSL/TLS Strong Encryption: An Introduction"
https://httpd.apache.org/docs/2.0/ssl/ssl_intro.html
@@ -98,9 +90,12 @@ Curl_ssl_config_matches(struct ssl_primary_config* data,
(data->version_max == needle->version_max) &&
(data->verifypeer == needle->verifypeer) &&
(data->verifyhost == needle->verifyhost) &&
+ (data->verifystatus == needle->verifystatus) &&
Curl_safe_strcasecompare(data->CApath, needle->CApath) &&
Curl_safe_strcasecompare(data->CAfile, needle->CAfile) &&
Curl_safe_strcasecompare(data->clientcert, needle->clientcert) &&
+ Curl_safe_strcasecompare(data->random_file, needle->random_file) &&
+ Curl_safe_strcasecompare(data->egdsocket, needle->egdsocket) &&
Curl_safe_strcasecompare(data->cipher_list, needle->cipher_list))
return TRUE;
@@ -111,42 +106,51 @@ bool
Curl_clone_primary_ssl_config(struct ssl_primary_config *source,
struct ssl_primary_config *dest)
{
- dest->verifyhost = source->verifyhost;
- dest->verifypeer = source->verifypeer;
dest->version = source->version;
dest->version_max = source->version_max;
+ dest->verifypeer = source->verifypeer;
+ dest->verifyhost = source->verifyhost;
+ dest->verifystatus = source->verifystatus;
+ dest->sessionid = source->sessionid;
- CLONE_STRING(CAfile);
CLONE_STRING(CApath);
- CLONE_STRING(cipher_list);
- CLONE_STRING(egdsocket);
- CLONE_STRING(random_file);
+ CLONE_STRING(CAfile);
CLONE_STRING(clientcert);
+ CLONE_STRING(random_file);
+ CLONE_STRING(egdsocket);
+ CLONE_STRING(cipher_list);
- /* Disable dest sessionid cache if a client cert is used, CVE-2016-5419. */
- dest->sessionid = (dest->clientcert ? false : source->sessionid);
return TRUE;
}
void Curl_free_primary_ssl_config(struct ssl_primary_config* sslc)
{
- Curl_safefree(sslc->CAfile);
Curl_safefree(sslc->CApath);
- Curl_safefree(sslc->cipher_list);
- Curl_safefree(sslc->egdsocket);
- Curl_safefree(sslc->random_file);
+ Curl_safefree(sslc->CAfile);
Curl_safefree(sslc->clientcert);
+ Curl_safefree(sslc->random_file);
+ Curl_safefree(sslc->egdsocket);
+ Curl_safefree(sslc->cipher_list);
}
+#ifdef USE_SSL
+static int multissl_init(const struct Curl_ssl *backend);
+#endif
+
int Curl_ssl_backend(void)
{
- return (int)CURL_SSL_BACKEND;
+#ifdef USE_SSL
+ multissl_init(NULL);
+ return Curl_ssl->info.id;
+#else
+ return (int)CURLSSLBACKEND_NONE;
+#endif
}
#ifdef USE_SSL
/* "global" init done? */
-static bool init_ssl=FALSE;
+static bool init_ssl = FALSE;
/**
* Global SSL init
@@ -161,7 +165,7 @@ int Curl_ssl_init(void)
return 1;
init_ssl = TRUE; /* never again */
- return curlssl_init();
+ return Curl_ssl->init();
}
@@ -170,7 +174,7 @@ void Curl_ssl_cleanup(void)
{
if(init_ssl) {
/* only cleanup if we did a previous init */
- curlssl_cleanup();
+ Curl_ssl->cleanup();
init_ssl = FALSE;
}
}
@@ -205,12 +209,20 @@ ssl_connect_init_proxy(struct connectdata *conn, int sockindex)
DEBUGASSERT(conn->bits.proxy_ssl_connected[sockindex]);
if(ssl_connection_complete == conn->ssl[sockindex].state &&
!conn->proxy_ssl[sockindex].use) {
-#if defined(HTTPS_PROXY_SUPPORT)
+ struct ssl_backend_data *pbdata;
+
+ if(!Curl_ssl->support_https_proxy)
+ return CURLE_NOT_BUILT_IN;
+
+ /* The pointers to the ssl backend data, which is opaque here, are swapped
+ rather than move the contents. */
+ pbdata = conn->proxy_ssl[sockindex].backend;
conn->proxy_ssl[sockindex] = conn->ssl[sockindex];
+
memset(&conn->ssl[sockindex], 0, sizeof(conn->ssl[sockindex]));
-#else
- return CURLE_NOT_BUILT_IN;
-#endif
+ memset(pbdata, 0, Curl_ssl->sizeof_ssl_backend_data);
+
+ conn->ssl[sockindex].backend = pbdata;
}
return CURLE_OK;
}
@@ -233,7 +245,7 @@ Curl_ssl_connect(struct connectdata *conn, int sockindex)
conn->ssl[sockindex].use = TRUE;
conn->ssl[sockindex].state = ssl_connection_negotiating;
- result = curlssl_connect(conn, sockindex);
+ result = Curl_ssl->connect(conn, sockindex);
if(!result)
Curl_pgrsTime(conn->data, TIMER_APPCONNECT); /* SSL is connected */
@@ -257,12 +269,7 @@ Curl_ssl_connect_nonblocking(struct connectdata *conn, int sockindex,
/* mark this is being ssl requested from here on. */
conn->ssl[sockindex].use = TRUE;
-#ifdef curlssl_connect_nonblocking
- result = curlssl_connect_nonblocking(conn, sockindex, done);
-#else
- *done = TRUE; /* fallback to BLOCKING */
- result = curlssl_connect(conn, sockindex);
-#endif /* non-blocking connect support */
+ result = Curl_ssl->connect_nonblocking(conn, sockindex, done);
if(!result && *done)
Curl_pgrsTime(conn->data, TIMER_APPCONNECT); /* SSL is connected */
return result;
@@ -361,7 +368,7 @@ void Curl_ssl_kill_session(struct curl_ssl_session *session)
/* defensive check */
/* free the ID the SSL-layer specific way */
- curlssl_session_free(session->sessionid);
+ Curl_ssl->session_free(session->sessionid);
session->sessionid = NULL;
session->age = 0; /* fresh */
@@ -379,7 +386,7 @@ void Curl_ssl_kill_session(struct curl_ssl_session *session)
void Curl_ssl_delsessionid(struct connectdata *conn, void *ssl_sessionid)
{
size_t i;
- struct Curl_easy *data=conn->data;
+ struct Curl_easy *data = conn->data;
for(i = 0; i < data->set.general_ssl.max_ssl_sessions; i++) {
struct curl_ssl_session *check = &data->state.session[i];
@@ -403,9 +410,9 @@ CURLcode Curl_ssl_addsessionid(struct connectdata *conn,
int sockindex)
{
size_t i;
- struct Curl_easy *data=conn->data; /* the mother of all structs */
+ struct Curl_easy *data = conn->data; /* the mother of all structs */
struct curl_ssl_session *store = &data->state.session[0];
- long oldest_age=data->state.session[0].age; /* zero if unused */
+ long oldest_age = data->state.session[0].age; /* zero if unused */
char *clone_host;
char *clone_conn_to_host;
int conn_to_port;
@@ -499,7 +506,7 @@ void Curl_ssl_close_all(struct Curl_easy *data)
Curl_safefree(data->state.session);
}
- curlssl_close_all(data);
+ Curl_ssl->close_all(data);
}
#if defined(USE_OPENSSL) || defined(USE_GNUTLS) || defined(USE_SCHANNEL) || \
@@ -542,12 +549,12 @@ int Curl_ssl_getsock(struct connectdata *conn,
void Curl_ssl_close(struct connectdata *conn, int sockindex)
{
DEBUGASSERT((sockindex <= 1) && (sockindex >= -1));
- curlssl_close(conn, sockindex);
+ Curl_ssl->close(conn, sockindex);
}
CURLcode Curl_ssl_shutdown(struct connectdata *conn, int sockindex)
{
- if(curlssl_shutdown(conn, sockindex))
+ if(Curl_ssl->shutdown(conn, sockindex))
return CURLE_SSL_SHUTDOWN_FAILED;
conn->ssl[sockindex].use = FALSE; /* get back to ordinary socket usage */
@@ -563,20 +570,20 @@ CURLcode Curl_ssl_shutdown(struct connectdata *conn, int sockindex)
*/
CURLcode Curl_ssl_set_engine(struct Curl_easy *data, const char *engine)
{
- return curlssl_set_engine(data, engine);
+ return Curl_ssl->set_engine(data, engine);
}
/* Selects the default SSL crypto engine
*/
CURLcode Curl_ssl_set_engine_default(struct Curl_easy *data)
{
- return curlssl_set_engine_default(data);
+ return Curl_ssl->set_engine_default(data);
}
/* Return list of OpenSSL crypto engine names. */
struct curl_slist *Curl_ssl_engines_list(struct Curl_easy *data)
{
- return curlssl_engines_list(data);
+ return Curl_ssl->engines_list(data);
}
/*
@@ -602,9 +609,15 @@ CURLcode Curl_ssl_initsessions(struct Curl_easy *data, size_t amount)
return CURLE_OK;
}
+static size_t Curl_multissl_version(char *buffer, size_t size);
+
size_t Curl_ssl_version(char *buffer, size_t size)
{
- return curlssl_version(buffer, size);
+#ifdef CURL_WITH_MULTI_SSL
+ return Curl_multissl_version(buffer, size);
+#else
+ return Curl_ssl->version(buffer, size);
+#endif
}
/*
@@ -617,13 +630,13 @@ size_t Curl_ssl_version(char *buffer, size_t size)
*/
int Curl_ssl_check_cxn(struct connectdata *conn)
{
- return curlssl_check_cxn(conn);
+ return Curl_ssl->check_cxn(conn);
}
bool Curl_ssl_data_pending(const struct connectdata *conn,
int connindex)
{
- return curlssl_data_pending(conn, connindex);
+ return Curl_ssl->data_pending(conn, connindex);
}
void Curl_ssl_free_certinfo(struct Curl_easy *data)
@@ -633,7 +646,7 @@ void Curl_ssl_free_certinfo(struct Curl_easy *data)
if(ci->num_of_certs) {
/* free all individual lists used */
- for(i=0; i<ci->num_of_certs; i++) {
+ for(i = 0; i<ci->num_of_certs; i++) {
curl_slist_free_all(ci->certinfo[i]);
ci->certinfo[i] = NULL;
}
@@ -687,7 +700,7 @@ CURLcode Curl_ssl_push_certinfo_len(struct Curl_easy *data,
snprintf(output, outlen, "%s:", label);
/* memcpy the value (it might not be zero terminated) */
- memcpy(&output[labellen+1], value, valuelen);
+ memcpy(&output[labellen + 1], value, valuelen);
/* zero terminate the output */
output[labellen + 1 + valuelen] = 0;
@@ -721,7 +734,7 @@ CURLcode Curl_ssl_random(struct Curl_easy *data,
unsigned char *entropy,
size_t length)
{
- return curlssl_random(data, entropy, length);
+ return Curl_ssl->random(data, entropy, length);
}
/*
@@ -796,12 +809,10 @@ CURLcode Curl_pin_peer_pubkey(struct Curl_easy *data,
size_t size, pem_len;
CURLcode pem_read;
CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;
-#ifdef curlssl_sha256sum
CURLcode encode;
size_t encodedlen, pinkeylen;
char *encoded, *pinkeycopy, *begin_pos, *end_pos;
unsigned char *sha256sumdigest = NULL;
-#endif
/* if a path wasn't specified, don't pin */
if(!pinnedpubkey)
@@ -811,15 +822,20 @@ 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) {
-#ifdef curlssl_sha256sum
+ if(!Curl_ssl->sha256sum) {
+ /* without sha256 support, this cannot match */
+ return result;
+ }
+
/* compute sha256sum of public key */
- sha256sumdigest = malloc(SHA256_DIGEST_LENGTH);
+ sha256sumdigest = malloc(CURL_SHA256_DIGEST_LENGTH);
if(!sha256sumdigest)
return CURLE_OUT_OF_MEMORY;
- curlssl_sha256sum(pubkey, pubkeylen,
- sha256sumdigest, SHA256_DIGEST_LENGTH);
+ Curl_ssl->sha256sum(pubkey, pubkeylen,
+ sha256sumdigest, CURL_SHA256_DIGEST_LENGTH);
encode = Curl_base64_encode(data, (char *)sha256sumdigest,
- SHA256_DIGEST_LENGTH, &encoded, &encodedlen);
+ CURL_SHA256_DIGEST_LENGTH, &encoded,
+ &encodedlen);
Curl_safefree(sha256sumdigest);
if(encode)
@@ -864,10 +880,6 @@ CURLcode Curl_pin_peer_pubkey(struct Curl_easy *data,
} while(end_pos && begin_pos);
Curl_safefree(encoded);
Curl_safefree(pinkeycopy);
-#else
- /* without sha256 support, this cannot match */
- (void)data;
-#endif
return result;
}
@@ -943,20 +955,7 @@ CURLcode Curl_ssl_md5sum(unsigned char *tmp, /* input */
unsigned char *md5sum, /* output */
size_t md5len)
{
-#ifdef curlssl_md5sum
- curlssl_md5sum(tmp, tmplen, md5sum, md5len);
-#else
- MD5_context *MD5pw;
-
- (void) md5len;
-
- MD5pw = Curl_MD5_init(Curl_DIGEST_MD5);
- if(!MD5pw)
- return CURLE_OUT_OF_MEMORY;
- Curl_MD5_update(MD5pw, tmp, curlx_uztoui(tmplen));
- Curl_MD5_final(MD5pw, md5sum);
-#endif
- return CURLE_OK;
+ return Curl_ssl->md5sum(tmp, tmplen, md5sum, md5len);
}
#endif
@@ -965,11 +964,7 @@ CURLcode Curl_ssl_md5sum(unsigned char *tmp, /* input */
*/
bool Curl_ssl_cert_status_request(void)
{
-#ifdef curlssl_cert_status_request
- return curlssl_cert_status_request();
-#else
- return FALSE;
-#endif
+ return Curl_ssl->cert_status_request();
}
/*
@@ -977,11 +972,341 @@ bool Curl_ssl_cert_status_request(void)
*/
bool Curl_ssl_false_start(void)
{
-#ifdef curlssl_false_start
- return curlssl_false_start();
-#else
+ return Curl_ssl->false_start();
+}
+
+/*
+ * Default implementations for unsupported functions.
+ */
+
+int Curl_none_init(void)
+{
+ return 1;
+}
+
+void Curl_none_cleanup(void)
+{ }
+
+int Curl_none_shutdown(struct connectdata *conn UNUSED_PARAM,
+ int sockindex UNUSED_PARAM)
+{
+ (void)conn;
+ (void)sockindex;
+ return 0;
+}
+
+int Curl_none_check_cxn(struct connectdata *conn UNUSED_PARAM)
+{
+ (void)conn;
+ return -1;
+}
+
+CURLcode Curl_none_random(struct Curl_easy *data UNUSED_PARAM,
+ unsigned char *entropy UNUSED_PARAM,
+ size_t length UNUSED_PARAM)
+{
+ (void)data;
+ (void)entropy;
+ (void)length;
+ return CURLE_NOT_BUILT_IN;
+}
+
+void Curl_none_close_all(struct Curl_easy *data UNUSED_PARAM)
+{
+ (void)data;
+}
+
+void Curl_none_session_free(void *ptr UNUSED_PARAM)
+{
+ (void)ptr;
+}
+
+bool Curl_none_data_pending(const struct connectdata *conn UNUSED_PARAM,
+ int connindex UNUSED_PARAM)
+{
+ (void)conn;
+ (void)connindex;
+ return 0;
+}
+
+bool Curl_none_cert_status_request(void)
+{
return FALSE;
+}
+
+CURLcode Curl_none_set_engine(struct Curl_easy *data UNUSED_PARAM,
+ const char *engine UNUSED_PARAM)
+{
+ (void)data;
+ (void)engine;
+ return CURLE_NOT_BUILT_IN;
+}
+
+CURLcode Curl_none_set_engine_default(struct Curl_easy *data UNUSED_PARAM)
+{
+ (void)data;
+ return CURLE_NOT_BUILT_IN;
+}
+
+struct curl_slist *Curl_none_engines_list(struct Curl_easy *data UNUSED_PARAM)
+{
+ (void)data;
+ return (struct curl_slist *)NULL;
+}
+
+bool Curl_none_false_start(void)
+{
+ return FALSE;
+}
+
+CURLcode Curl_none_md5sum(unsigned char *input, size_t inputlen,
+ unsigned char *md5sum, size_t md5len UNUSED_PARAM)
+{
+ MD5_context *MD5pw;
+
+ (void)md5len;
+
+ MD5pw = Curl_MD5_init(Curl_DIGEST_MD5);
+ if(!MD5pw)
+ return CURLE_OUT_OF_MEMORY;
+ Curl_MD5_update(MD5pw, input, curlx_uztoui(inputlen));
+ Curl_MD5_final(MD5pw, md5sum);
+ return CURLE_OK;
+}
+
+static int Curl_multissl_init(void)
+{
+ if(multissl_init(NULL))
+ return 1;
+ return Curl_ssl->init();
+}
+
+static CURLcode Curl_multissl_connect(struct connectdata *conn, int sockindex)
+{
+ if(multissl_init(NULL))
+ return CURLE_FAILED_INIT;
+ return Curl_ssl->connect(conn, sockindex);
+}
+
+static CURLcode Curl_multissl_connect_nonblocking(struct connectdata *conn,
+ int sockindex, bool *done)
+{
+ if(multissl_init(NULL))
+ return CURLE_FAILED_INIT;
+ return Curl_ssl->connect_nonblocking(conn, sockindex, done);
+}
+
+static void *Curl_multissl_get_internals(struct ssl_connect_data *connssl,
+ CURLINFO info)
+{
+ if(multissl_init(NULL))
+ return NULL;
+ return Curl_ssl->get_internals(connssl, info);
+}
+
+static void Curl_multissl_close(struct connectdata *conn, int sockindex)
+{
+ if(multissl_init(NULL))
+ return;
+ Curl_ssl->close(conn, sockindex);
+}
+
+static const struct Curl_ssl Curl_ssl_multi = {
+ { CURLSSLBACKEND_NONE, "multi" }, /* info */
+
+ 0, /* have_ca_path */
+ 0, /* have_certinfo */
+ 0, /* have_pinnedpubkey */
+ 0, /* have_ssl_ctx */
+ 0, /* support_https_proxy */
+
+ (size_t)-1, /* something insanely large to be on the safe side */
+
+ Curl_multissl_init, /* init */
+ Curl_none_cleanup, /* cleanup */
+ Curl_multissl_version, /* version */
+ Curl_none_check_cxn, /* check_cxn */
+ Curl_none_shutdown, /* shutdown */
+ Curl_none_data_pending, /* data_pending */
+ Curl_none_random, /* random */
+ Curl_none_cert_status_request, /* cert_status_request */
+ Curl_multissl_connect, /* connect */
+ Curl_multissl_connect_nonblocking, /* connect_nonblocking */
+ Curl_multissl_get_internals, /* get_internals */
+ Curl_multissl_close, /* close */
+ Curl_none_close_all, /* close_all */
+ Curl_none_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 */
+};
+
+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_GNUTLS)
+ &Curl_ssl_gnutls;
+#elif defined(USE_GSKIT)
+ &Curl_ssl_gskit;
+#elif defined(USE_MBEDTLS)
+ &Curl_ssl_mbedtls;
+#elif defined(USE_NSS)
+ &Curl_ssl_nss;
+#elif defined(USE_OPENSSL)
+ &Curl_ssl_openssl;
+#elif defined(USE_POLARSSL)
+ &Curl_ssl_polarssl;
+#elif defined(USE_SCHANNEL)
+ &Curl_ssl_schannel;
+#else
+#error "Missing struct Curl_ssl for selected SSL backend"
+#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,
+#endif
+#if defined(USE_GNUTLS)
+ &Curl_ssl_gnutls,
+#endif
+#if defined(USE_GSKIT)
+ &Curl_ssl_gskit,
+#endif
+#if defined(USE_MBEDTLS)
+ &Curl_ssl_mbedtls,
+#endif
+#if defined(USE_NSS)
+ &Curl_ssl_nss,
+#endif
+#if defined(USE_OPENSSL)
+ &Curl_ssl_openssl,
+#endif
+#if defined(USE_POLARSSL)
+ &Curl_ssl_polarssl,
+#endif
+#if defined(USE_SCHANNEL)
+ &Curl_ssl_schannel,
+#endif
+ NULL
+};
+
+static size_t Curl_multissl_version(char *buffer, size_t size)
+{
+ static const struct Curl_ssl *selected;
+ static char backends[200];
+ static size_t total;
+ const struct Curl_ssl *current;
+
+ current = Curl_ssl == &Curl_ssl_multi ? available_backends[0] : Curl_ssl;
+
+ if(current != selected) {
+ char *p = backends;
+ int i;
+
+ selected = current;
+
+ for(i = 0; available_backends[i]; i++) {
+ if(i)
+ *(p++) = ' ';
+ if(selected != available_backends[i])
+ *(p++) = '(';
+ p += available_backends[i]->version(p, backends + sizeof(backends) - p);
+ if(selected != available_backends[i])
+ *(p++) = ')';
+ }
+ *p = '\0';
+ total = p - backends;
+ }
+
+ if(size < total)
+ memcpy(buffer, backends, total + 1);
+ else {
+ memcpy(buffer, backends, size - 1);
+ buffer[size - 1] = '\0';
+ }
+
+ return total;
+}
+
+static int multissl_init(const struct Curl_ssl *backend)
+{
+ const char *env;
+ int i;
+
+ if(Curl_ssl != &Curl_ssl_multi)
+ return 1;
+
+ if(backend) {
+ Curl_ssl = backend;
+ return 0;
+ }
+
+ if(!available_backends[0])
+ return 1;
+
+ env = getenv("CURL_SSL_BACKEND");
+#ifdef CURL_DEFAULT_SSL_BACKEND
+ if(!env)
+ env = CURL_DEFAULT_SSL_BACKEND;
+#endif
+ if(env) {
+ for(i = 0; available_backends[i]; i++) {
+ if(strcasecompare(env, available_backends[i]->info.name)) {
+ Curl_ssl = available_backends[i];
+ return 0;
+ }
+ }
+ }
+
+ /* Fall back to first available backend */
+ Curl_ssl = available_backends[0];
+ return 0;
+}
+
+CURLsslset curl_global_sslset(curl_sslbackend id, const char *name,
+ const curl_ssl_backend ***avail)
+{
+ int i;
+
+ if(Curl_ssl != &Curl_ssl_multi)
+ return id == Curl_ssl->info.id ? CURLSSLSET_OK : CURLSSLSET_TOO_LATE;
+
+ for(i = 0; available_backends[i]; i++) {
+ if(available_backends[i]->info.id == id ||
+ (name && strcasecompare(available_backends[i]->info.name, name))) {
+ multissl_init(available_backends[i]);
+ return CURLSSLSET_OK;
+ }
+ }
+
+ if(avail)
+ *avail = (const curl_ssl_backend **)&available_backends;
+ return CURLSSLSET_UNKNOWN_BACKEND;
+}
+
+#else /* USE_SSL */
+CURLsslset curl_global_sslset(curl_sslbackend id, const char *name,
+ const curl_ssl_backend ***avail)
+{
+ (void)id;
+ (void)name;
+ (void)avail;
+ return CURLSSLSET_NO_BACKENDS;
}
-#endif /* USE_SSL */
+#endif /* !USE_SSL */
diff --git a/Utilities/cmcurl/lib/vtls/vtls.h b/Utilities/cmcurl/lib/vtls/vtls.h
index 2aabeda..f1a11ea 100644
--- a/Utilities/cmcurl/lib/vtls/vtls.h
+++ b/Utilities/cmcurl/lib/vtls/vtls.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 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
@@ -23,6 +23,80 @@
***************************************************************************/
#include "curl_setup.h"
+struct connectdata;
+struct ssl_connect_data;
+
+struct Curl_ssl {
+ /*
+ * This *must* be the first entry to allow returning the list of available
+ * backends in curl_global_sslset().
+ */
+ curl_ssl_backend info;
+
+ unsigned have_ca_path:1; /* supports CAPATH */
+ unsigned have_certinfo:1; /* supports CURLOPT_CERTINFO */
+ unsigned have_pinnedpubkey:1; /* supports CURLOPT_PINNEDPUBLICKEY */
+ unsigned have_ssl_ctx:1; /* supports CURLOPT_SSL_CTX_* */
+
+ unsigned support_https_proxy:1; /* supports access via HTTPS proxies */
+
+ size_t sizeof_ssl_backend_data;
+
+ int (*init)(void);
+ void (*cleanup)(void);
+
+ size_t (*version)(char *buffer, size_t size);
+ int (*check_cxn)(struct connectdata *cxn);
+ int (*shutdown)(struct connectdata *conn, int sockindex);
+ bool (*data_pending)(const struct connectdata *conn,
+ int connindex);
+
+ /* return 0 if a find random is filled in */
+ CURLcode (*random)(struct Curl_easy *data, unsigned char *entropy,
+ size_t length);
+ bool (*cert_status_request)(void);
+
+ CURLcode (*connect)(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);
+ void (*close)(struct connectdata *conn, int sockindex);
+ void (*close_all)(struct Curl_easy *data);
+ void (*session_free)(void *ptr);
+
+ CURLcode (*set_engine)(struct Curl_easy *data, const char *engine);
+ CURLcode (*set_engine_default)(struct Curl_easy *data);
+ struct curl_slist *(*engines_list)(struct Curl_easy *data);
+
+ bool (*false_start)(void);
+
+ CURLcode (*md5sum)(unsigned char *input, size_t inputlen,
+ unsigned char *md5sum, size_t md5sumlen);
+ void (*sha256sum)(const unsigned char *input, size_t inputlen,
+ unsigned char *sha256sum, size_t sha256sumlen);
+};
+
+#ifdef USE_SSL
+extern const struct Curl_ssl *Curl_ssl;
+#endif
+
+int Curl_none_init(void);
+void Curl_none_cleanup(void);
+int Curl_none_shutdown(struct connectdata *conn, int sockindex);
+int Curl_none_check_cxn(struct connectdata *conn);
+CURLcode Curl_none_random(struct Curl_easy *data, unsigned char *entropy,
+ size_t length);
+void Curl_none_close_all(struct Curl_easy *data);
+void Curl_none_session_free(void *ptr);
+bool Curl_none_data_pending(const struct connectdata *conn, int connindex);
+bool Curl_none_cert_status_request(void);
+CURLcode Curl_none_set_engine(struct Curl_easy *data, const char *engine);
+CURLcode Curl_none_set_engine_default(struct Curl_easy *data);
+struct curl_slist *Curl_none_engines_list(struct Curl_easy *data);
+bool Curl_none_false_start(void);
+CURLcode Curl_none_md5sum(unsigned char *input, size_t inputlen,
+ unsigned char *md5sum, size_t md5len);
+
#include "openssl.h" /* OpenSSL versions */
#include "gtls.h" /* GnuTLS versions */
#include "nssg.h" /* NSS versions */
@@ -42,8 +116,8 @@
#define MD5_DIGEST_LENGTH 16 /* fixed size */
#endif
-#ifndef SHA256_DIGEST_LENGTH
-#define SHA256_DIGEST_LENGTH 32 /* fixed size */
+#ifndef CURL_SHA256_DIGEST_LENGTH
+#define CURL_SHA256_DIGEST_LENGTH 32 /* fixed size */
#endif
/* see https://tools.ietf.org/html/draft-ietf-tls-applayerprotoneg-04 */
@@ -172,8 +246,6 @@ bool Curl_ssl_false_start(void);
#define SSL_SHUTDOWN_TIMEOUT 10000 /* ms */
#else
-/* Set the API backend definition to none */
-#define CURL_SSL_BACKEND CURLSSLBACKEND_NONE
/* When SSL support is not present, just define away these function calls */
#define Curl_ssl_init() 1