1
0
mirror of https://github.com/moparisthebest/curl synced 2024-12-22 08:08:50 -05:00

vtls: prepare the SSL backends for encapsulated private data

At the moment, cURL's SSL backend needs to be configured at build time.
As such, it is totally okay for them to hard-code their backend-specific
data in the ssl_connect_data struct.

In preparation for making the SSL backend a runtime option, let's make
the access of said private data a bit more abstract so that it can be
adjusted later in an easy manner.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
This commit is contained in:
Johannes Schindelin 2017-06-21 12:41:18 +02:00 committed by Daniel Stenberg
parent 20c6cf7e95
commit d65e6cc4fc
No known key found for this signature in database
GPG Key ID: 5CC908FDB71E12C2
10 changed files with 762 additions and 712 deletions

View File

@ -47,6 +47,8 @@
#include "curl_memory.h" #include "curl_memory.h"
#include "memdebug.h" #include "memdebug.h"
#define BACKEND connssl
static CURLcode map_error_to_curl(int axtls_err) static CURLcode map_error_to_curl(int axtls_err)
{ {
switch(axtls_err) { switch(axtls_err) {
@ -104,13 +106,13 @@ static Curl_send axtls_send;
static void free_ssl_structs(struct ssl_connect_data *connssl) static void free_ssl_structs(struct ssl_connect_data *connssl)
{ {
if(connssl->ssl) { if(BACKEND->ssl) {
ssl_free(connssl->ssl); ssl_free(BACKEND->ssl);
connssl->ssl = NULL; BACKEND->ssl = NULL;
} }
if(connssl->ssl_ctx) { if(BACKEND->ssl_ctx) {
ssl_ctx_free(connssl->ssl_ctx); ssl_ctx_free(BACKEND->ssl_ctx);
connssl->ssl_ctx = NULL; BACKEND->ssl_ctx = NULL;
} }
} }
@ -121,6 +123,7 @@ static void free_ssl_structs(struct ssl_connect_data *connssl)
*/ */
static CURLcode connect_prep(struct connectdata *conn, int sockindex) static CURLcode connect_prep(struct connectdata *conn, int sockindex)
{ {
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct Curl_easy *data = conn->data; struct Curl_easy *data = conn->data;
SSL_CTX *ssl_ctx; SSL_CTX *ssl_ctx;
SSL *ssl = NULL; SSL *ssl = NULL;
@ -135,7 +138,7 @@ static CURLcode connect_prep(struct connectdata *conn, int sockindex)
SSL_SERVER_VERIFY_LATER | SSL_SERVER_VERIFY_LATER |
SSL_CONNECT_IN_PARTS; 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 /* to make us tolerant against being called more than once for the
same connection */ same connection */
return CURLE_OK; return CURLE_OK;
@ -169,8 +172,8 @@ static CURLcode connect_prep(struct connectdata *conn, int sockindex)
return CURLE_SSL_CONNECT_ERROR; return CURLE_SSL_CONNECT_ERROR;
} }
conn->ssl[sockindex].ssl_ctx = ssl_ctx; BACKEND->ssl_ctx = ssl_ctx;
conn->ssl[sockindex].ssl = NULL; BACKEND->ssl = NULL;
/* Load the trusted CA cert bundle file */ /* Load the trusted CA cert bundle file */
if(SSL_CONN_CONFIG(CAfile)) { if(SSL_CONN_CONFIG(CAfile)) {
@ -265,7 +268,7 @@ static CURLcode connect_prep(struct connectdata *conn, int sockindex)
if(!ssl) if(!ssl)
ssl = ssl_client_new(ssl_ctx, conn->sock[sockindex], NULL, 0, NULL); ssl = ssl_client_new(ssl_ctx, conn->sock[sockindex], NULL, 0, NULL);
conn->ssl[sockindex].ssl = ssl; BACKEND->ssl = ssl;
return CURLE_OK; return CURLE_OK;
} }
@ -275,7 +278,7 @@ static void Curl_axtls_close(struct connectdata *conn, int sockindex)
infof(conn->data, " Curl_axtls_close\n"); infof(conn->data, " Curl_axtls_close\n");
/* line from openssl.c: (void)SSL_shutdown(connssl->ssl); /* line from openssl.c: (void)SSL_shutdown(BACKEND->ssl);
axTLS compat layer does nothing for SSL_shutdown */ axTLS compat layer does nothing for SSL_shutdown */
/* The following line is from openssl.c. There seems to be no axTLS /* The following line is from openssl.c. There seems to be no axTLS
@ -292,7 +295,8 @@ static void Curl_axtls_close(struct connectdata *conn, int sockindex)
static CURLcode connect_finish(struct connectdata *conn, int sockindex) static CURLcode connect_finish(struct connectdata *conn, int sockindex)
{ {
struct Curl_easy *data = conn->data; 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; const char *peer_CN;
uint32_t dns_altname_index; uint32_t dns_altname_index;
const char *dns_altname; const char *dns_altname;
@ -387,7 +391,7 @@ static CURLcode connect_finish(struct connectdata *conn, int sockindex)
} }
/* General housekeeping */ /* General housekeeping */
conn->ssl[sockindex].state = ssl_connection_complete; connssl->state = ssl_connection_complete;
conn->recv[sockindex] = axtls_recv; conn->recv[sockindex] = axtls_recv;
conn->send[sockindex] = axtls_send; conn->send[sockindex] = axtls_send;
@ -412,6 +416,7 @@ static CURLcode connect_finish(struct connectdata *conn, int sockindex)
static CURLcode Curl_axtls_connect_nonblocking(struct connectdata *conn, static CURLcode Curl_axtls_connect_nonblocking(struct connectdata *conn,
int sockindex, bool *done) int sockindex, bool *done)
{ {
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
CURLcode conn_step; CURLcode conn_step;
int ssl_fcn_return; int ssl_fcn_return;
int i; int i;
@ -419,23 +424,23 @@ static CURLcode Curl_axtls_connect_nonblocking(struct connectdata *conn,
*done = FALSE; *done = FALSE;
/* connectdata is calloc'd and connecting_state is only changed in this /* connectdata is calloc'd and connecting_state is only changed in this
function, so this is safe, as the state is effectively initialized. */ 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); conn_step = connect_prep(conn, sockindex);
if(conn_step != CURLE_OK) { if(conn_step != CURLE_OK) {
Curl_axtls_close(conn, sockindex); Curl_axtls_close(conn, sockindex);
return conn_step; 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. */ /* 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 /* 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 fact that axtls does not expose any knowledge about when work needs
to be performed. This can save ~25% of time on SSL handshakes. */ to be performed. This can save ~25% of time on SSL handshakes. */
for(i=0; i<5; i++) { for(i=0; i<5; i++) {
ssl_fcn_return = ssl_read(conn->ssl[sockindex].ssl, NULL); ssl_fcn_return = ssl_read(BACKEND->ssl, NULL);
if(ssl_fcn_return < 0) { if(ssl_fcn_return < 0) {
Curl_axtls_close(conn, sockindex); Curl_axtls_close(conn, sockindex);
ssl_display_error(ssl_fcn_return); /* goes to stdout. */ ssl_display_error(ssl_fcn_return); /* goes to stdout. */
@ -445,10 +450,10 @@ static CURLcode Curl_axtls_connect_nonblocking(struct connectdata *conn,
} }
} }
infof(conn->data, "handshake completed successfully\n"); 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); conn_step = connect_finish(conn, sockindex);
if(conn_step != CURLE_OK) { if(conn_step != CURLE_OK) {
Curl_axtls_close(conn, sockindex); Curl_axtls_close(conn, sockindex);
@ -456,15 +461,15 @@ static CURLcode Curl_axtls_connect_nonblocking(struct connectdata *conn,
} }
/* Reset connect state */ /* Reset connect state */
conn->ssl[sockindex].connecting_state = ssl_connect_1; connssl->connecting_state = ssl_connect_1;
*done = TRUE; *done = TRUE;
return CURLE_OK; return CURLE_OK;
} }
/* Unrecognized state. Things are very bad. */ /* Unrecognized state. Things are very bad. */
conn->ssl[sockindex].state = ssl_connection_none; connssl->state = ssl_connection_none;
conn->ssl[sockindex].connecting_state = ssl_connect_1; connssl->connecting_state = ssl_connect_1;
/* Return value perhaps not strictly correct, but distinguishes the issue.*/ /* Return value perhaps not strictly correct, but distinguishes the issue.*/
return CURLE_BAD_FUNCTION_ARGUMENT; return CURLE_BAD_FUNCTION_ARGUMENT;
} }
@ -479,7 +484,8 @@ static CURLcode Curl_axtls_connect(struct connectdata *conn, int sockindex)
struct Curl_easy *data = conn->data; struct Curl_easy *data = conn->data;
CURLcode conn_step = connect_prep(conn, sockindex); CURLcode conn_step = connect_prep(conn, sockindex);
int ssl_fcn_return; 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; long timeout_ms;
if(conn_step != CURLE_OK) { if(conn_step != CURLE_OK) {
@ -525,8 +531,9 @@ static ssize_t axtls_send(struct connectdata *conn,
size_t len, size_t len,
CURLcode *err) CURLcode *err)
{ {
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
/* ssl_write() returns 'int' while write() and send() returns 'size_t' */ /* 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"); infof(conn->data, " axtls_send\n");
@ -563,17 +570,17 @@ static int Curl_axtls_shutdown(struct connectdata *conn, int sockindex)
/* axTLS compat layer does nothing for SSL_shutdown, so we do nothing too /* axTLS compat layer does nothing for SSL_shutdown, so we do nothing too
if(data->set.ftp_ccc == CURLFTPSSL_CCC_ACTIVE) 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); int what = SOCKET_READABLE(conn->sock[sockindex], SSL_SHUTDOWN_TIMEOUT);
if(what > 0) { if(what > 0) {
/* Something to read, let's do it and hope that it is the close /* Something to read, let's do it and hope that it is the close
notify alert from the server. buf is managed internally by notify alert from the server. buf is managed internally by
axTLS and will be released upon calling ssl_free via axTLS and will be released upon calling ssl_free via
free_ssl_structs. */ free_ssl_structs. */
nread = (ssize_t)ssl_read(connssl->ssl, &buf); nread = (ssize_t)ssl_read(BACKEND->ssl, &buf);
if(nread < SSL_OK) { if(nread < SSL_OK) {
failf(data, "close notify alert not received during shutdown"); failf(data, "close notify alert not received during shutdown");
@ -609,7 +616,7 @@ static ssize_t axtls_recv(struct connectdata *conn, /* connection data */
*err = CURLE_OK; *err = CURLE_OK;
if(connssl) { if(connssl) {
ret = ssl_read(connssl->ssl, &read_buf); ret = ssl_read(BACKEND->ssl, &read_buf);
if(ret > SSL_OK) { if(ret > SSL_OK) {
/* ssl_read returns SSL_OK if there is more data to read, so if it is /* ssl_read returns SSL_OK if there is more data to read, so if it is
larger, then all data has been read already. */ larger, then all data has been read already. */
@ -644,7 +651,8 @@ static ssize_t axtls_recv(struct connectdata *conn, /* connection data */
*/ */
static 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].ssl, (void*)&buf, 1);
axTLS compat layer always returns the last argument, so connection is axTLS compat layer always returns the last argument, so connection is
always alive? */ always alive? */
@ -685,7 +693,7 @@ static void *Curl_axtls_get_internals(struct ssl_connect_data *connssl,
CURLINFO info UNUSED_PARAM) CURLINFO info UNUSED_PARAM)
{ {
(void)info; (void)info;
return connssl->ssl; return BACKEND->ssl;
} }
const struct Curl_ssl Curl_ssl_axtls = { const struct Curl_ssl Curl_ssl_axtls = {

View File

@ -122,6 +122,8 @@ and that's a problem since options.h hasn't been included yet. */
#endif #endif
#endif #endif
#define BACKEND connssl
static Curl_recv cyassl_recv; static Curl_recv cyassl_recv;
static Curl_send cyassl_send; static Curl_send cyassl_send;
@ -148,7 +150,7 @@ cyassl_connect_step1(struct connectdata *conn,
char error_buffer[CYASSL_MAX_ERROR_SZ]; char error_buffer[CYASSL_MAX_ERROR_SZ];
char *ciphers; char *ciphers;
struct Curl_easy *data = conn->data; 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; SSL_METHOD* req_method = NULL;
curl_socket_t sockfd = conn->sock[sockindex]; curl_socket_t sockfd = conn->sock[sockindex];
#ifdef HAVE_SNI #ifdef HAVE_SNI
@ -158,7 +160,7 @@ cyassl_connect_step1(struct connectdata *conn,
#define use_sni(x) Curl_nop_stmt #define use_sni(x) Curl_nop_stmt
#endif #endif
if(conssl->state == ssl_connection_complete) if(connssl->state == ssl_connection_complete)
return CURLE_OK; return CURLE_OK;
if(SSL_CONN_CONFIG(version_max) != CURL_SSLVERSION_MAX_NONE) { if(SSL_CONN_CONFIG(version_max) != CURL_SSLVERSION_MAX_NONE) {
@ -217,11 +219,11 @@ cyassl_connect_step1(struct connectdata *conn,
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
} }
if(conssl->ctx) if(BACKEND->ctx)
SSL_CTX_free(conssl->ctx); SSL_CTX_free(BACKEND->ctx);
conssl->ctx = SSL_CTX_new(req_method); BACKEND->ctx = SSL_CTX_new(req_method);
if(!conssl->ctx) { if(!BACKEND->ctx) {
failf(data, "SSL: couldn't create a context!"); failf(data, "SSL: couldn't create a context!");
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
} }
@ -237,9 +239,9 @@ cyassl_connect_step1(struct connectdata *conn,
version. We use wolfSSL_CTX_SetMinVersion and not CyaSSL_SetMinVersion version. We use wolfSSL_CTX_SetMinVersion and not CyaSSL_SetMinVersion
because only the former will work before the user's CTX callback is called. because only the former will work before the user's CTX callback is called.
*/ */
if((wolfSSL_CTX_SetMinVersion(conssl->ctx, WOLFSSL_TLSV1) != 1) && if((wolfSSL_CTX_SetMinVersion(BACKEND->ctx, WOLFSSL_TLSV1) != 1) &&
(wolfSSL_CTX_SetMinVersion(conssl->ctx, WOLFSSL_TLSV1_1) != 1) && (wolfSSL_CTX_SetMinVersion(BACKEND->ctx, WOLFSSL_TLSV1_1) != 1) &&
(wolfSSL_CTX_SetMinVersion(conssl->ctx, WOLFSSL_TLSV1_2) != 1)) { (wolfSSL_CTX_SetMinVersion(BACKEND->ctx, WOLFSSL_TLSV1_2) != 1)) {
failf(data, "SSL: couldn't set the minimum protocol version"); failf(data, "SSL: couldn't set the minimum protocol version");
return CURLE_SSL_CONNECT_ERROR; return CURLE_SSL_CONNECT_ERROR;
} }
@ -249,7 +251,7 @@ cyassl_connect_step1(struct connectdata *conn,
ciphers = SSL_CONN_CONFIG(cipher_list); ciphers = SSL_CONN_CONFIG(cipher_list);
if(ciphers) { 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); failf(data, "failed setting cipher list: %s", ciphers);
return CURLE_SSL_CIPHER; return CURLE_SSL_CIPHER;
} }
@ -259,7 +261,7 @@ cyassl_connect_step1(struct connectdata *conn,
#ifndef NO_FILESYSTEM #ifndef NO_FILESYSTEM
/* load trusted cacert */ /* load trusted cacert */
if(SSL_CONN_CONFIG(CAfile)) { 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(CAfile),
SSL_CONN_CONFIG(CApath))) { SSL_CONN_CONFIG(CApath))) {
if(SSL_CONN_CONFIG(verifypeer)) { if(SSL_CONN_CONFIG(verifypeer)) {
@ -296,7 +298,7 @@ cyassl_connect_step1(struct connectdata *conn,
if(SSL_SET_OPTION(cert) && SSL_SET_OPTION(key)) { if(SSL_SET_OPTION(cert) && SSL_SET_OPTION(key)) {
int file_type = do_file_type(SSL_SET_OPTION(cert_type)); 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) { file_type) != 1) {
failf(data, "unable to use client certificate (no key or wrong pass" failf(data, "unable to use client certificate (no key or wrong pass"
" phrase?)"); " phrase?)");
@ -304,7 +306,7 @@ cyassl_connect_step1(struct connectdata *conn,
} }
file_type = do_file_type(SSL_SET_OPTION(key_type)); 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) { file_type) != 1) {
failf(data, "unable to set private key"); failf(data, "unable to set private key");
return CURLE_SSL_CONNECT_ERROR; return CURLE_SSL_CONNECT_ERROR;
@ -316,7 +318,7 @@ cyassl_connect_step1(struct connectdata *conn,
* fail to connect if the verification fails, or if it should continue * fail to connect if the verification fails, or if it should continue
* anyway. In the latter case the result of the verification is checked with * anyway. In the latter case the result of the verification is checked with
* SSL_get_verify_result() below. */ * 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_CONN_CONFIG(verifypeer)?SSL_VERIFY_PEER:
SSL_VERIFY_NONE, SSL_VERIFY_NONE,
NULL); NULL);
@ -335,7 +337,7 @@ cyassl_connect_step1(struct connectdata *conn,
#ifdef ENABLE_IPV6 #ifdef ENABLE_IPV6
(0 == Curl_inet_pton(AF_INET6, hostname, &addr6)) && (0 == Curl_inet_pton(AF_INET6, hostname, &addr6)) &&
#endif #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)) { (unsigned short)hostname_len) != 1)) {
infof(data, "WARNING: failed to configure server name indication (SNI) " infof(data, "WARNING: failed to configure server name indication (SNI) "
"TLS extension\n"); "TLS extension\n");
@ -348,15 +350,15 @@ cyassl_connect_step1(struct connectdata *conn,
https://github.com/wolfSSL/wolfssl/issues/366 https://github.com/wolfSSL/wolfssl/issues/366
The supported curves below are those also supported by OpenSSL 1.0.2 and The supported curves below are those also supported by OpenSSL 1.0.2 and
in the same order. */ in the same order. */
CyaSSL_CTX_UseSupportedCurve(conssl->ctx, 0x17); /* secp256r1 */ CyaSSL_CTX_UseSupportedCurve(BACKEND->ctx, 0x17); /* secp256r1 */
CyaSSL_CTX_UseSupportedCurve(conssl->ctx, 0x19); /* secp521r1 */ CyaSSL_CTX_UseSupportedCurve(BACKEND->ctx, 0x19); /* secp521r1 */
CyaSSL_CTX_UseSupportedCurve(conssl->ctx, 0x18); /* secp384r1 */ CyaSSL_CTX_UseSupportedCurve(BACKEND->ctx, 0x18); /* secp384r1 */
#endif #endif
/* give application a chance to interfere with SSL set up. */ /* give application a chance to interfere with SSL set up. */
if(data->set.ssl.fsslctx) { if(data->set.ssl.fsslctx) {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
result = (*data->set.ssl.fsslctx)(data, conssl->ctx, result = (*data->set.ssl.fsslctx)(data, BACKEND->ctx,
data->set.ssl.fsslctxp); data->set.ssl.fsslctxp);
if(result) { if(result) {
failf(data, "error signaled by ssl ctx callback"); failf(data, "error signaled by ssl ctx callback");
@ -374,10 +376,10 @@ cyassl_connect_step1(struct connectdata *conn,
#endif #endif
/* Let's make an SSL structure */ /* Let's make an SSL structure */
if(conssl->handle) if(BACKEND->handle)
SSL_free(conssl->handle); SSL_free(BACKEND->handle);
conssl->handle = SSL_new(conssl->ctx); BACKEND->handle = SSL_new(BACKEND->ctx);
if(!conssl->handle) { if(!BACKEND->handle) {
failf(data, "SSL: couldn't create a context (handle)!"); failf(data, "SSL: couldn't create a context (handle)!");
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
} }
@ -400,7 +402,7 @@ cyassl_connect_step1(struct connectdata *conn,
strcpy(protocols + strlen(protocols), ALPN_HTTP_1_1); strcpy(protocols + strlen(protocols), ALPN_HTTP_1_1);
infof(data, "ALPN, offering %s\n", 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), (unsigned)strlen(protocols),
WOLFSSL_ALPN_CONTINUE_ON_MISMATCH) != SSL_SUCCESS) { WOLFSSL_ALPN_CONTINUE_ON_MISMATCH) != SSL_SUCCESS) {
failf(data, "SSL: failed setting ALPN protocols"); failf(data, "SSL: failed setting ALPN protocols");
@ -416,10 +418,10 @@ cyassl_connect_step1(struct connectdata *conn,
Curl_ssl_sessionid_lock(conn); Curl_ssl_sessionid_lock(conn);
if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL, sockindex)) { if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL, sockindex)) {
/* we got a session id, use it! */ /* 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); Curl_ssl_sessionid_unlock(conn);
failf(data, "SSL: SSL_set_session failed: %s", 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)); error_buffer));
return CURLE_SSL_CONNECT_ERROR; return CURLE_SSL_CONNECT_ERROR;
} }
@ -430,12 +432,12 @@ cyassl_connect_step1(struct connectdata *conn,
} }
/* pass the raw socket into the SSL layer */ /* 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"); failf(data, "SSL: SSL_set_fd failed");
return CURLE_SSL_CONNECT_ERROR; return CURLE_SSL_CONNECT_ERROR;
} }
conssl->connecting_state = ssl_connect_2; connssl->connecting_state = ssl_connect_2;
return CURLE_OK; return CURLE_OK;
} }
@ -446,7 +448,7 @@ cyassl_connect_step2(struct connectdata *conn,
{ {
int ret = -1; int ret = -1;
struct Curl_easy *data = conn->data; 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 : const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
conn->host.name; conn->host.name;
const char * const dispname = SSL_IS_PROXY() ? const char * const dispname = SSL_IS_PROXY() ?
@ -460,22 +462,22 @@ cyassl_connect_step2(struct connectdata *conn,
/* Enable RFC2818 checks */ /* Enable RFC2818 checks */
if(SSL_CONN_CONFIG(verifyhost)) { 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) if(ret == SSL_FAILURE)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
} }
ret = SSL_connect(conssl->handle); ret = SSL_connect(BACKEND->handle);
if(ret != 1) { if(ret != 1) {
char error_buffer[CYASSL_MAX_ERROR_SZ]; 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) { if(SSL_ERROR_WANT_READ == detail) {
conssl->connecting_state = ssl_connect_2_reading; connssl->connecting_state = ssl_connect_2_reading;
return CURLE_OK; return CURLE_OK;
} }
else if(SSL_ERROR_WANT_WRITE == detail) { else if(SSL_ERROR_WANT_WRITE == detail) {
conssl->connecting_state = ssl_connect_2_writing; connssl->connecting_state = ssl_connect_2_writing;
return CURLE_OK; return CURLE_OK;
} }
/* There is no easy way to override only the CN matching. /* There is no easy way to override only the CN matching.
@ -536,7 +538,7 @@ cyassl_connect_step2(struct connectdata *conn,
curl_asn1Element *pubkey; curl_asn1Element *pubkey;
CURLcode result; CURLcode result;
x509 = SSL_get_peer_certificate(conssl->handle); x509 = SSL_get_peer_certificate(BACKEND->handle);
if(!x509) { if(!x509) {
failf(data, "SSL: failed retrieving server certificate"); failf(data, "SSL: failed retrieving server certificate");
return CURLE_SSL_PINNEDPUBKEYNOTMATCH; return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
@ -578,7 +580,7 @@ cyassl_connect_step2(struct connectdata *conn,
char *protocol = NULL; char *protocol = NULL;
unsigned short protocol_len = 0; 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) { if(rc == SSL_SUCCESS) {
infof(data, "ALPN, server accepted to use %.*s\n", protocol_len, infof(data, "ALPN, server accepted to use %.*s\n", protocol_len,
@ -607,11 +609,11 @@ cyassl_connect_step2(struct connectdata *conn,
} }
#endif /* HAVE_ALPN */ #endif /* HAVE_ALPN */
conssl->connecting_state = ssl_connect_3; connssl->connecting_state = ssl_connect_3;
#if (LIBCYASSL_VERSION_HEX >= 0x03009010) #if (LIBCYASSL_VERSION_HEX >= 0x03009010)
infof(data, "SSL connection using %s / %s\n", infof(data, "SSL connection using %s / %s\n",
wolfSSL_get_version(conssl->handle), wolfSSL_get_version(BACKEND->handle),
wolfSSL_get_cipher_name(conssl->handle)); wolfSSL_get_cipher_name(BACKEND->handle));
#else #else
infof(data, "SSL connected\n"); infof(data, "SSL connected\n");
#endif #endif
@ -635,7 +637,7 @@ cyassl_connect_step3(struct connectdata *conn,
SSL_SESSION *our_ssl_sessionid; SSL_SESSION *our_ssl_sessionid;
void *old_ssl_sessionid = NULL; 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); Curl_ssl_sessionid_lock(conn);
incache = !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL, incache = !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL,
@ -672,12 +674,13 @@ static ssize_t cyassl_send(struct connectdata *conn,
size_t len, size_t len,
CURLcode *curlcode) CURLcode *curlcode)
{ {
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
char error_buffer[CYASSL_MAX_ERROR_SZ]; char error_buffer[CYASSL_MAX_ERROR_SZ];
int memlen = (len > (size_t)INT_MAX) ? INT_MAX : (int)len; 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) { if(rc < 0) {
int err = SSL_get_error(conn->ssl[sockindex].handle, rc); int err = SSL_get_error(BACKEND->handle, rc);
switch(err) { switch(err) {
case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_READ:
@ -698,16 +701,16 @@ static ssize_t cyassl_send(struct connectdata *conn,
static 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) { if(BACKEND->handle) {
(void)SSL_shutdown(conssl->handle); (void)SSL_shutdown(BACKEND->handle);
SSL_free(conssl->handle); SSL_free(BACKEND->handle);
conssl->handle = NULL; BACKEND->handle = NULL;
} }
if(conssl->ctx) { if(BACKEND->ctx) {
SSL_CTX_free(conssl->ctx); SSL_CTX_free(BACKEND->ctx);
conssl->ctx = NULL; BACKEND->ctx = NULL;
} }
} }
@ -717,12 +720,13 @@ static ssize_t cyassl_recv(struct connectdata *conn,
size_t buffersize, size_t buffersize,
CURLcode *curlcode) CURLcode *curlcode)
{ {
struct ssl_connect_data *connssl = &conn->ssl[num];
char error_buffer[CYASSL_MAX_ERROR_SZ]; char error_buffer[CYASSL_MAX_ERROR_SZ];
int buffsize = (buffersize > (size_t)INT_MAX) ? INT_MAX : (int)buffersize; 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) { if(nread < 0) {
int err = SSL_get_error(conn->ssl[num].handle, nread); int err = SSL_get_error(BACKEND->handle, nread);
switch(err) { switch(err) {
case SSL_ERROR_ZERO_RETURN: /* no more data */ case SSL_ERROR_ZERO_RETURN: /* no more data */
@ -774,8 +778,9 @@ static int Curl_cyassl_init(void)
static bool Curl_cyassl_data_pending(const struct connectdata* conn, static bool Curl_cyassl_data_pending(const struct connectdata* conn,
int connindex) int connindex)
{ {
if(conn->ssl[connindex].handle) /* SSL is in use */ const struct ssl_connect_data *connssl = &conn->ssl[connindex];
return (0 != SSL_pending(conn->ssl[connindex].handle)) ? TRUE : FALSE; if(BACKEND->handle) /* SSL is in use */
return (0 != SSL_pending(BACKEND->handle)) ? TRUE : FALSE;
else else
return FALSE; return FALSE;
} }
@ -790,9 +795,9 @@ static int Curl_cyassl_shutdown(struct connectdata *conn, int sockindex)
int retval = 0; int retval = 0;
struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_connect_data *connssl = &conn->ssl[sockindex];
if(connssl->handle) { if(BACKEND->handle) {
SSL_free(connssl->handle); SSL_free(BACKEND->handle);
connssl->handle = NULL; BACKEND->handle = NULL;
} }
return retval; return retval;
} }
@ -963,7 +968,7 @@ static void *Curl_cyassl_get_internals(struct ssl_connect_data *connssl,
CURLINFO info UNUSED_PARAM) CURLINFO info UNUSED_PARAM)
{ {
(void)info; (void)info;
return connssl->handle; return BACKEND->handle;
} }
const struct Curl_ssl Curl_ssl_cyassl = { const struct Curl_ssl Curl_ssl_cyassl = {

View File

@ -118,6 +118,8 @@
#define ioErr -36 #define ioErr -36
#define paramErr -50 #define paramErr -50
#define BACKEND connssl
/* pinned public key support tests */ /* pinned public key support tests */
/* version 1 supports macOS 10.12+ and iOS 10+ */ /* version 1 supports macOS 10.12+ and iOS 10+ */
@ -179,7 +181,7 @@ static OSStatus SocketRead(SSLConnectionRef connection,
UInt8 *currData = (UInt8 *)data; UInt8 *currData = (UInt8 *)data;
/*int sock = *(int *)connection;*/ /*int sock = *(int *)connection;*/
struct ssl_connect_data *connssl = (struct ssl_connect_data *)connection; struct ssl_connect_data *connssl = (struct ssl_connect_data *)connection;
int sock = connssl->ssl_sockfd; int sock = BACKEND->ssl_sockfd;
OSStatus rtn = noErr; OSStatus rtn = noErr;
size_t bytesRead; size_t bytesRead;
ssize_t rrtn; ssize_t rrtn;
@ -208,7 +210,7 @@ static OSStatus SocketRead(SSLConnectionRef connection,
break; break;
case EAGAIN: case EAGAIN:
rtn = errSSLWouldBlock; rtn = errSSLWouldBlock;
connssl->ssl_direction = false; BACKEND->ssl_direction = false;
break; break;
default: default:
rtn = ioErr; rtn = ioErr;
@ -239,7 +241,7 @@ static OSStatus SocketWrite(SSLConnectionRef connection,
size_t bytesSent = 0; size_t bytesSent = 0;
/*int sock = *(int *)connection;*/ /*int sock = *(int *)connection;*/
struct ssl_connect_data *connssl = (struct ssl_connect_data *)connection; struct ssl_connect_data *connssl = (struct ssl_connect_data *)connection;
int sock = connssl->ssl_sockfd; int sock = BACKEND->ssl_sockfd;
ssize_t length; ssize_t length;
size_t dataLen = *dataLength; size_t dataLen = *dataLength;
const UInt8 *dataPtr = (UInt8 *)data; const UInt8 *dataPtr = (UInt8 *)data;
@ -259,7 +261,7 @@ static OSStatus SocketWrite(SSLConnectionRef connection,
theErr = errno; theErr = errno;
if(theErr == EAGAIN) { if(theErr == EAGAIN) {
ortn = errSSLWouldBlock; ortn = errSSLWouldBlock;
connssl->ssl_direction = true; BACKEND->ssl_direction = true;
} }
else { else {
ortn = ioErr; ortn = ioErr;
@ -1193,30 +1195,30 @@ set_ssl_version_min_max(struct connectdata *conn, int sockindex)
return result; return result;
} }
(void)SSLSetProtocolVersionMin(connssl->ssl_ctx, darwin_ver_min); (void)SSLSetProtocolVersionMin(BACKEND->ssl_ctx, darwin_ver_min);
(void)SSLSetProtocolVersionMax(connssl->ssl_ctx, darwin_ver_max); (void)SSLSetProtocolVersionMax(BACKEND->ssl_ctx, darwin_ver_max);
return result; return result;
} }
else { else {
#if CURL_SUPPORT_MAC_10_8 #if CURL_SUPPORT_MAC_10_8
long i = ssl_version; long i = ssl_version;
(void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx,
kSSLProtocolAll, kSSLProtocolAll,
false); false);
for(; i <= (ssl_version_max >> 16); i++) { for(; i <= (ssl_version_max >> 16); i++) {
switch(i) { switch(i) {
case CURL_SSLVERSION_TLSv1_0: case CURL_SSLVERSION_TLSv1_0:
(void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx,
kTLSProtocol1, kTLSProtocol1,
true); true);
break; break;
case CURL_SSLVERSION_TLSv1_1: case CURL_SSLVERSION_TLSv1_1:
(void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx,
kTLSProtocol11, kTLSProtocol11,
true); true);
break; break;
case CURL_SSLVERSION_TLSv1_2: case CURL_SSLVERSION_TLSv1_2:
(void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx,
kTLSProtocol12, kTLSProtocol12,
true); true);
break; break;
@ -1262,10 +1264,10 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS #if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
if(SSLCreateContext != NULL) { /* use the newer API if avaialble */ if(SSLCreateContext != NULL) { /* use the newer API if avaialble */
if(connssl->ssl_ctx) if(BACKEND->ssl_ctx)
CFRelease(connssl->ssl_ctx); CFRelease(BACKEND->ssl_ctx);
connssl->ssl_ctx = SSLCreateContext(NULL, kSSLClientSide, kSSLStreamType); BACKEND->ssl_ctx = SSLCreateContext(NULL, kSSLClientSide, kSSLStreamType);
if(!connssl->ssl_ctx) { if(!BACKEND->ssl_ctx) {
failf(data, "SSL: couldn't create a context!"); failf(data, "SSL: couldn't create a context!");
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
} }
@ -1273,9 +1275,9 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
else { else {
/* The old ST API does not exist under iOS, so don't compile it: */ /* The old ST API does not exist under iOS, so don't compile it: */
#if CURL_SUPPORT_MAC_10_8 #if CURL_SUPPORT_MAC_10_8
if(connssl->ssl_ctx) if(BACKEND->ssl_ctx)
(void)SSLDisposeContext(connssl->ssl_ctx); (void)SSLDisposeContext(BACKEND->ssl_ctx);
err = SSLNewContext(false, &(connssl->ssl_ctx)); err = SSLNewContext(false, &(BACKEND->ssl_ctx));
if(err != noErr) { if(err != noErr) {
failf(data, "SSL: couldn't create a context: OSStatus %d", err); failf(data, "SSL: couldn't create a context: OSStatus %d", err);
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
@ -1283,15 +1285,15 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
#endif /* CURL_SUPPORT_MAC_10_8 */ #endif /* CURL_SUPPORT_MAC_10_8 */
} }
#else #else
if(connssl->ssl_ctx) if(BACKEND->ssl_ctx)
(void)SSLDisposeContext(connssl->ssl_ctx); (void)SSLDisposeContext(BACKEND->ssl_ctx);
err = SSLNewContext(false, &(connssl->ssl_ctx)); err = SSLNewContext(false, &(BACKEND->ssl_ctx));
if(err != noErr) { if(err != noErr) {
failf(data, "SSL: couldn't create a context: OSStatus %d", err); failf(data, "SSL: couldn't create a context: OSStatus %d", err);
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
} }
#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */ #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 */ /* check to see if we've been told to use an explicit SSL/TLS version */
#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS #if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
@ -1299,8 +1301,8 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
switch(conn->ssl_config.version) { switch(conn->ssl_config.version) {
case CURL_SSLVERSION_DEFAULT: case CURL_SSLVERSION_DEFAULT:
case CURL_SSLVERSION_TLSv1: case CURL_SSLVERSION_TLSv1:
(void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kTLSProtocol1); (void)SSLSetProtocolVersionMin(BACKEND->ssl_ctx, kTLSProtocol1);
(void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol12); (void)SSLSetProtocolVersionMax(BACKEND->ssl_ctx, kTLSProtocol12);
break; break;
case CURL_SSLVERSION_TLSv1_0: case CURL_SSLVERSION_TLSv1_0:
case CURL_SSLVERSION_TLSv1_1: case CURL_SSLVERSION_TLSv1_1:
@ -1313,20 +1315,20 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
break; break;
} }
case CURL_SSLVERSION_SSLv3: case CURL_SSLVERSION_SSLv3:
err = SSLSetProtocolVersionMin(connssl->ssl_ctx, kSSLProtocol3); err = SSLSetProtocolVersionMin(BACKEND->ssl_ctx, kSSLProtocol3);
if(err != noErr) { if(err != noErr) {
failf(data, "Your version of the OS does not support SSLv3"); failf(data, "Your version of the OS does not support SSLv3");
return CURLE_SSL_CONNECT_ERROR; return CURLE_SSL_CONNECT_ERROR;
} }
(void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kSSLProtocol3); (void)SSLSetProtocolVersionMax(BACKEND->ssl_ctx, kSSLProtocol3);
break; break;
case CURL_SSLVERSION_SSLv2: case CURL_SSLVERSION_SSLv2:
err = SSLSetProtocolVersionMin(connssl->ssl_ctx, kSSLProtocol2); err = SSLSetProtocolVersionMin(BACKEND->ssl_ctx, kSSLProtocol2);
if(err != noErr) { if(err != noErr) {
failf(data, "Your version of the OS does not support SSLv2"); failf(data, "Your version of the OS does not support SSLv2");
return CURLE_SSL_CONNECT_ERROR; return CURLE_SSL_CONNECT_ERROR;
} }
(void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kSSLProtocol2); (void)SSLSetProtocolVersionMax(BACKEND->ssl_ctx, kSSLProtocol2);
break; break;
default: default:
failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
@ -1335,19 +1337,19 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
} }
else { else {
#if CURL_SUPPORT_MAC_10_8 #if CURL_SUPPORT_MAC_10_8
(void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx,
kSSLProtocolAll, kSSLProtocolAll,
false); false);
switch(conn->ssl_config.version) { switch(conn->ssl_config.version) {
case CURL_SSLVERSION_DEFAULT: case CURL_SSLVERSION_DEFAULT:
case CURL_SSLVERSION_TLSv1: case CURL_SSLVERSION_TLSv1:
(void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx,
kTLSProtocol1, kTLSProtocol1,
true); true);
(void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx,
kTLSProtocol11, kTLSProtocol11,
true); true);
(void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx,
kTLSProtocol12, kTLSProtocol12,
true); true);
break; break;
@ -1362,7 +1364,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
break; break;
} }
case CURL_SSLVERSION_SSLv3: case CURL_SSLVERSION_SSLv3:
err = SSLSetProtocolVersionEnabled(connssl->ssl_ctx, err = SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx,
kSSLProtocol3, kSSLProtocol3,
true); true);
if(err != noErr) { if(err != noErr) {
@ -1371,7 +1373,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
} }
break; break;
case CURL_SSLVERSION_SSLv2: case CURL_SSLVERSION_SSLv2:
err = SSLSetProtocolVersionEnabled(connssl->ssl_ctx, err = SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx,
kSSLProtocol2, kSSLProtocol2,
true); true);
if(err != noErr) { if(err != noErr) {
@ -1391,12 +1393,12 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
" SSL/TLS version"); " SSL/TLS version");
return CURLE_SSL_CONNECT_ERROR; return CURLE_SSL_CONNECT_ERROR;
} }
(void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, kSSLProtocolAll, false); (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx, kSSLProtocolAll, false);
switch(conn->ssl_config.version) { switch(conn->ssl_config.version) {
case CURL_SSLVERSION_DEFAULT: case CURL_SSLVERSION_DEFAULT:
case CURL_SSLVERSION_TLSv1: case CURL_SSLVERSION_TLSv1:
case CURL_SSLVERSION_TLSv1_0: case CURL_SSLVERSION_TLSv1_0:
(void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx,
kTLSProtocol1, kTLSProtocol1,
true); true);
break; break;
@ -1410,7 +1412,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
failf(data, "Your version of the OS does not support TLSv1.3"); failf(data, "Your version of the OS does not support TLSv1.3");
return CURLE_SSL_CONNECT_ERROR; return CURLE_SSL_CONNECT_ERROR;
case CURL_SSLVERSION_SSLv2: case CURL_SSLVERSION_SSLv2:
err = SSLSetProtocolVersionEnabled(connssl->ssl_ctx, err = SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx,
kSSLProtocol2, kSSLProtocol2,
true); true);
if(err != noErr) { if(err != noErr) {
@ -1419,7 +1421,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
} }
break; break;
case CURL_SSLVERSION_SSLv3: case CURL_SSLVERSION_SSLv3:
err = SSLSetProtocolVersionEnabled(connssl->ssl_ctx, err = SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx,
kSSLProtocol3, kSSLProtocol3,
true); true);
if(err != noErr) { if(err != noErr) {
@ -1483,7 +1485,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
certs_c[0] = cert_and_key; certs_c[0] = cert_and_key;
certs = CFArrayCreate(NULL, (const void **)certs_c, 1L, certs = CFArrayCreate(NULL, (const void **)certs_c, 1L,
&kCFTypeArrayCallBacks); &kCFTypeArrayCallBacks);
err = SSLSetCertificate(connssl->ssl_ctx, certs); err = SSLSetCertificate(BACKEND->ssl_ctx, certs);
if(certs) if(certs)
CFRelease(certs); CFRelease(certs);
if(err != noErr) { if(err != noErr) {
@ -1546,7 +1548,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
if(SSLSetSessionOption != NULL) { if(SSLSetSessionOption != NULL) {
#endif /* CURL_BUILD_MAC */ #endif /* CURL_BUILD_MAC */
bool break_on_auth = !conn->ssl_config.verifypeer || ssl_cafile; bool break_on_auth = !conn->ssl_config.verifypeer || ssl_cafile;
err = SSLSetSessionOption(connssl->ssl_ctx, err = SSLSetSessionOption(BACKEND->ssl_ctx,
kSSLSessionOptionBreakOnServerAuth, kSSLSessionOptionBreakOnServerAuth,
break_on_auth); break_on_auth);
if(err != noErr) { if(err != noErr) {
@ -1556,7 +1558,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
} }
else { else {
#if CURL_SUPPORT_MAC_10_8 #if CURL_SUPPORT_MAC_10_8
err = SSLSetEnableCertVerify(connssl->ssl_ctx, err = SSLSetEnableCertVerify(BACKEND->ssl_ctx,
conn->ssl_config.verifypeer?true:false); conn->ssl_config.verifypeer?true:false);
if(err != noErr) { if(err != noErr) {
failf(data, "SSL: SSLSetEnableCertVerify() failed: OSStatus %d", err); failf(data, "SSL: SSLSetEnableCertVerify() failed: OSStatus %d", err);
@ -1565,7 +1567,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
#endif /* CURL_SUPPORT_MAC_10_8 */ #endif /* CURL_SUPPORT_MAC_10_8 */
} }
#else #else
err = SSLSetEnableCertVerify(connssl->ssl_ctx, err = SSLSetEnableCertVerify(BACKEND->ssl_ctx,
conn->ssl_config.verifypeer?true:false); conn->ssl_config.verifypeer?true:false);
if(err != noErr) { if(err != noErr) {
failf(data, "SSL: SSLSetEnableCertVerify() failed: OSStatus %d", err); failf(data, "SSL: SSLSetEnableCertVerify() failed: OSStatus %d", err);
@ -1586,7 +1588,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
* Both hostname check and SNI require SSLSetPeerDomainName(). * Both hostname check and SNI require SSLSetPeerDomainName().
* Also: the verifyhost setting influences SNI usage */ * Also: the verifyhost setting influences SNI usage */
if(conn->ssl_config.verifyhost) { if(conn->ssl_config.verifyhost) {
err = SSLSetPeerDomainName(connssl->ssl_ctx, hostname, err = SSLSetPeerDomainName(BACKEND->ssl_ctx, hostname,
strlen(hostname)); strlen(hostname));
if(err != noErr) { if(err != noErr) {
@ -1612,11 +1614,11 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
higher priority, but it's probably better that we not connect at all than 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 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.) */ 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)); all_ciphers = malloc(all_ciphers_count*sizeof(SSLCipherSuite));
allowed_ciphers = malloc(all_ciphers_count*sizeof(SSLCipherSuite)); allowed_ciphers = malloc(all_ciphers_count*sizeof(SSLCipherSuite));
if(all_ciphers && allowed_ciphers && if(all_ciphers && allowed_ciphers &&
SSLGetSupportedCiphers(connssl->ssl_ctx, all_ciphers, SSLGetSupportedCiphers(BACKEND->ssl_ctx, all_ciphers,
&all_ciphers_count) == noErr) { &all_ciphers_count) == noErr) {
for(i = 0UL ; i < all_ciphers_count ; i++) { for(i = 0UL ; i < all_ciphers_count ; i++) {
#if CURL_BUILD_MAC #if CURL_BUILD_MAC
@ -1698,7 +1700,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
break; break;
} }
} }
err = SSLSetEnabledCiphers(connssl->ssl_ctx, allowed_ciphers, err = SSLSetEnabledCiphers(BACKEND->ssl_ctx, allowed_ciphers,
allowed_ciphers_count); allowed_ciphers_count);
if(err != noErr) { if(err != noErr) {
failf(data, "SSL: SSLSetEnabledCiphers() failed: OSStatus %d", err); failf(data, "SSL: SSLSetEnabledCiphers() failed: OSStatus %d", err);
@ -1719,9 +1721,9 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
specifically doesn't want us doing that: */ specifically doesn't want us doing that: */
if(SSLSetSessionOption != NULL) { if(SSLSetSessionOption != NULL) {
/* TODO s/data->set.ssl.enable_beast/SSL_SET_OPTION(enable_beast)/g */ /* 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); !data->set.ssl.enable_beast);
SSLSetSessionOption(connssl->ssl_ctx, kSSLSessionOptionFalseStart, SSLSetSessionOption(BACKEND->ssl_ctx, kSSLSessionOptionFalseStart,
data->set.ssl.falsestart); /* false start support */ data->set.ssl.falsestart); /* false start support */
} }
#endif /* CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 */ #endif /* CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 */
@ -1735,7 +1737,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
if(!Curl_ssl_getsessionid(conn, (void **)&ssl_sessionid, if(!Curl_ssl_getsessionid(conn, (void **)&ssl_sessionid,
&ssl_sessionid_len, sockindex)) { &ssl_sessionid_len, sockindex)) {
/* we got a session id, use it! */ /* 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); Curl_ssl_sessionid_unlock(conn);
if(err != noErr) { if(err != noErr) {
failf(data, "SSL: SSLSetPeerID() failed: OSStatus %d", err); failf(data, "SSL: SSLSetPeerID() failed: OSStatus %d", err);
@ -1753,7 +1755,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
verifypeer, SSL_CONN_CONFIG(verifyhost), hostname, port); verifypeer, SSL_CONN_CONFIG(verifyhost), hostname, port);
ssl_sessionid_len = strlen(ssl_sessionid); 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) { if(err != noErr) {
Curl_ssl_sessionid_unlock(conn); Curl_ssl_sessionid_unlock(conn);
failf(data, "SSL: SSLSetPeerID() failed: OSStatus %d", err); failf(data, "SSL: SSLSetPeerID() failed: OSStatus %d", err);
@ -1770,7 +1772,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) { if(err != noErr) {
failf(data, "SSL: SSLSetIOFuncs() failed: OSStatus %d", err); failf(data, "SSL: SSLSetIOFuncs() failed: OSStatus %d", err);
return CURLE_SSL_CONNECT_ERROR; return CURLE_SSL_CONNECT_ERROR;
@ -1780,8 +1782,8 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
/* We need to store the FD in a constant memory address, because /* We need to store the FD in a constant memory address, because
* SSLSetConnection() will not copy that address. I've found that * SSLSetConnection() will not copy that address. I've found that
* conn->sock[sockindex] may change on its own. */ * conn->sock[sockindex] may change on its own. */
connssl->ssl_sockfd = sockfd; BACKEND->ssl_sockfd = sockfd;
err = SSLSetConnection(connssl->ssl_ctx, connssl); err = SSLSetConnection(BACKEND->ssl_ctx, connssl);
if(err != noErr) { if(err != noErr) {
failf(data, "SSL: SSLSetConnection() failed: %d", err); failf(data, "SSL: SSLSetConnection() failed: %d", err);
return CURLE_SSL_CONNECT_ERROR; return CURLE_SSL_CONNECT_ERROR;
@ -2189,12 +2191,12 @@ darwinssl_connect_step2(struct connectdata *conn, int sockindex)
|| ssl_connect_2_writing == connssl->connecting_state); || ssl_connect_2_writing == connssl->connecting_state);
/* Here goes nothing: */ /* Here goes nothing: */
err = SSLHandshake(connssl->ssl_ctx); err = SSLHandshake(BACKEND->ssl_ctx);
if(err != noErr) { if(err != noErr) {
switch(err) { switch(err) {
case errSSLWouldBlock: /* they're not done with us yet */ 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; ssl_connect_2_writing : ssl_connect_2_reading;
return CURLE_OK; return CURLE_OK;
@ -2203,7 +2205,7 @@ darwinssl_connect_step2(struct connectdata *conn, int sockindex)
case -9841: case -9841:
if(SSL_CONN_CONFIG(CAfile) && SSL_CONN_CONFIG(verifypeer)) { if(SSL_CONN_CONFIG(CAfile) && SSL_CONN_CONFIG(verifypeer)) {
int res = verify_cert(SSL_CONN_CONFIG(CAfile), data, int res = verify_cert(SSL_CONN_CONFIG(CAfile), data,
connssl->ssl_ctx); BACKEND->ssl_ctx);
if(res != CURLE_OK) if(res != CURLE_OK)
return res; return res;
} }
@ -2281,7 +2283,7 @@ darwinssl_connect_step2(struct connectdata *conn, int sockindex)
#ifdef DARWIN_SSL_PINNEDPUBKEY #ifdef DARWIN_SSL_PINNEDPUBKEY
if(data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]) { 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]); data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]);
if(result) { if(result) {
failf(data, "SSL: public key does not match pinned public key!"); failf(data, "SSL: public key does not match pinned public key!");
@ -2291,8 +2293,8 @@ darwinssl_connect_step2(struct connectdata *conn, int sockindex)
#endif /* DARWIN_SSL_PINNEDPUBKEY */ #endif /* DARWIN_SSL_PINNEDPUBKEY */
/* Informational message */ /* Informational message */
(void)SSLGetNegotiatedCipher(connssl->ssl_ctx, &cipher); (void)SSLGetNegotiatedCipher(BACKEND->ssl_ctx, &cipher);
(void)SSLGetNegotiatedProtocolVersion(connssl->ssl_ctx, &protocol); (void)SSLGetNegotiatedProtocolVersion(BACKEND->ssl_ctx, &protocol);
switch(protocol) { switch(protocol) {
case kSSLProtocol2: case kSSLProtocol2:
infof(data, "SSL 2.0 connection using %s\n", infof(data, "SSL 2.0 connection using %s\n",
@ -2339,13 +2341,13 @@ show_verbose_server_cert(struct connectdata *conn,
CFIndex i, count; CFIndex i, count;
SecTrustRef trust = NULL; SecTrustRef trust = NULL;
if(!connssl->ssl_ctx) if(!BACKEND->ssl_ctx)
return; return;
#if CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS #if CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS
#if CURL_BUILD_IOS #if CURL_BUILD_IOS
#pragma unused(server_certs) #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 /* For some reason, SSLCopyPeerTrust() can return noErr and yet return
a null trust, so be on guard for that: */ a null trust, so be on guard for that: */
if(err == noErr && trust) { if(err == noErr && trust) {
@ -2371,7 +2373,7 @@ show_verbose_server_cert(struct connectdata *conn,
Lion or later. */ Lion or later. */
if(SecTrustEvaluateAsync != NULL) { if(SecTrustEvaluateAsync != NULL) {
#pragma unused(server_certs) #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 /* For some reason, SSLCopyPeerTrust() can return noErr and yet return
a null trust, so be on guard for that: */ a null trust, so be on guard for that: */
if(err == noErr && trust) { if(err == noErr && trust) {
@ -2391,7 +2393,7 @@ show_verbose_server_cert(struct connectdata *conn,
} }
else { else {
#if CURL_SUPPORT_MAC_10_8 #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... */ /* Just in case SSLCopyPeerCertificates() returns null too... */
if(err == noErr && server_certs) { if(err == noErr && server_certs) {
count = CFArrayGetCount(server_certs); count = CFArrayGetCount(server_certs);
@ -2413,7 +2415,7 @@ show_verbose_server_cert(struct connectdata *conn,
#endif /* CURL_BUILD_IOS */ #endif /* CURL_BUILD_IOS */
#else #else
#pragma unused(trust) #pragma unused(trust)
err = SSLCopyPeerCertificates(connssl->ssl_ctx, &server_certs); err = SSLCopyPeerCertificates(BACKEND->ssl_ctx, &server_certs);
if(err == noErr) { if(err == noErr) {
count = CFArrayGetCount(server_certs); count = CFArrayGetCount(server_certs);
for(i = 0L ; i < count ; i++) { for(i = 0L ; i < count ; i++) {
@ -2593,21 +2595,21 @@ static void Curl_darwinssl_close(struct connectdata *conn, int sockindex)
{ {
struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_connect_data *connssl = &conn->ssl[sockindex];
if(connssl->ssl_ctx) { if(BACKEND->ssl_ctx) {
(void)SSLClose(connssl->ssl_ctx); (void)SSLClose(BACKEND->ssl_ctx);
#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS #if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
if(SSLCreateContext != NULL) if(SSLCreateContext != NULL)
CFRelease(connssl->ssl_ctx); CFRelease(BACKEND->ssl_ctx);
#if CURL_SUPPORT_MAC_10_8 #if CURL_SUPPORT_MAC_10_8
else else
(void)SSLDisposeContext(connssl->ssl_ctx); (void)SSLDisposeContext(BACKEND->ssl_ctx);
#endif /* CURL_SUPPORT_MAC_10_8 */ #endif /* CURL_SUPPORT_MAC_10_8 */
#else #else
(void)SSLDisposeContext(connssl->ssl_ctx); (void)SSLDisposeContext(BACKEND->ssl_ctx);
#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */ #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;
} }
static int Curl_darwinssl_shutdown(struct connectdata *conn, int sockindex) static int Curl_darwinssl_shutdown(struct connectdata *conn, int sockindex)
@ -2619,7 +2621,7 @@ static int Curl_darwinssl_shutdown(struct connectdata *conn, int sockindex)
int rc; int rc;
char buf[120]; char buf[120];
if(!connssl->ssl_ctx) if(!BACKEND->ssl_ctx)
return 0; return 0;
if(data->set.ftp_ccc != CURLFTPSSL_CCC_ACTIVE) if(data->set.ftp_ccc != CURLFTPSSL_CCC_ACTIVE)
@ -2693,8 +2695,8 @@ static int Curl_darwinssl_check_cxn(struct connectdata *conn)
OSStatus err; OSStatus err;
SSLSessionState state; SSLSessionState state;
if(connssl->ssl_ctx) { if(BACKEND->ssl_ctx) {
err = SSLGetSessionState(connssl->ssl_ctx, &state); err = SSLGetSessionState(BACKEND->ssl_ctx, &state);
if(err == noErr) if(err == noErr)
return state == kSSLConnected || state == kSSLHandshake; return state == kSSLConnected || state == kSSLHandshake;
return -1; return -1;
@ -2709,8 +2711,8 @@ static bool Curl_darwinssl_data_pending(const struct connectdata *conn,
OSStatus err; OSStatus err;
size_t buffer; size_t buffer;
if(connssl->ssl_ctx) { /* SSL is in use */ if(BACKEND->ssl_ctx) { /* SSL is in use */
err = SSLGetBufferedReadSize(connssl->ssl_ctx, &buffer); err = SSLGetBufferedReadSize(BACKEND->ssl_ctx, &buffer);
if(err == noErr) if(err == noErr)
return buffer > 0UL; return buffer > 0UL;
return false; return false;
@ -2791,15 +2793,15 @@ static ssize_t darwinssl_send(struct connectdata *conn,
over again with no new data until it quits returning errSSLWouldBlock. */ 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? */ /* 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: */ /* Write the buffered data: */
err = SSLWrite(connssl->ssl_ctx, NULL, 0UL, &processed); err = SSLWrite(BACKEND->ssl_ctx, NULL, 0UL, &processed);
switch(err) { switch(err) {
case noErr: case noErr:
/* processed is always going to be 0 because we didn't write to /* processed is always going to be 0 because we didn't write to
the buffer, so return how much was written to the socket */ the buffer, so return how much was written to the socket */
processed = connssl->ssl_write_buffered_length; processed = BACKEND->ssl_write_buffered_length;
connssl->ssl_write_buffered_length = 0UL; BACKEND->ssl_write_buffered_length = 0UL;
break; break;
case errSSLWouldBlock: /* argh, try again */ case errSSLWouldBlock: /* argh, try again */
*curlcode = CURLE_AGAIN; *curlcode = CURLE_AGAIN;
@ -2812,13 +2814,13 @@ static ssize_t darwinssl_send(struct connectdata *conn,
} }
else { else {
/* We've got new data to write: */ /* 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) { if(err != noErr) {
switch(err) { switch(err) {
case errSSLWouldBlock: case errSSLWouldBlock:
/* Data was buffered but not sent, we have to tell the caller /* Data was buffered but not sent, we have to tell the caller
to try sending again, and remember how much was buffered */ 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; *curlcode = CURLE_AGAIN;
return -1L; return -1L;
default: default:
@ -2840,7 +2842,7 @@ static ssize_t darwinssl_recv(struct connectdata *conn,
/*struct Curl_easy *data = conn->data;*/ /*struct Curl_easy *data = conn->data;*/
struct ssl_connect_data *connssl = &conn->ssl[num]; struct ssl_connect_data *connssl = &conn->ssl[num];
size_t processed = 0UL; 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) { if(err != noErr) {
switch(err) { switch(err) {
@ -2875,7 +2877,7 @@ static void *Curl_darwinssl_get_internals(struct ssl_connect_data *connssl,
CURLINFO info UNUSED_PARAM) CURLINFO info UNUSED_PARAM)
{ {
(void)info; (void)info;
return connssl->ssl_ctx; return BACKEND->ssl_ctx;
} }
const struct Curl_ssl Curl_ssl_darwinssl = { const struct Curl_ssl Curl_ssl_darwinssl = {

View File

@ -98,6 +98,7 @@
#define CURL_GSKPROTO_TLSV12_MASK (1 << CURL_GSKPROTO_TLSV12) #define CURL_GSKPROTO_TLSV12_MASK (1 << CURL_GSKPROTO_TLSV12)
#define CURL_GSKPROTO_LAST 5 #define CURL_GSKPROTO_LAST 5
#define BACKEND connssl
/* Supported ciphers. */ /* Supported ciphers. */
typedef struct { typedef struct {
@ -495,14 +496,14 @@ static void cancel_async_handshake(struct connectdata *conn, int sockindex)
Qso_OverlappedIO_t cstat; Qso_OverlappedIO_t cstat;
if(QsoCancelOperation(conn->sock[sockindex], 0) > 0) 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) static void close_async_handshake(struct ssl_connect_data *connssl)
{ {
QsoDestroyIOCompletionPort(connssl->iocport); QsoDestroyIOCompletionPort(BACKEND->iocport);
connssl->iocport = -1; BACKEND->iocport = -1;
} }
/* SSL over SSL /* SSL over SSL
@ -620,12 +621,12 @@ static int pipe_ssloverssl(struct connectdata *conn, int sockindex,
FD_ZERO(&fds_write); FD_ZERO(&fds_write);
n = -1; n = -1;
if(directions & SOS_READ) { if(directions & SOS_READ) {
FD_SET(connssl->remotefd, &fds_write); FD_SET(BACKEND->remotefd, &fds_write);
n = connssl->remotefd; n = BACKEND->remotefd;
} }
if(directions & SOS_WRITE) { if(directions & SOS_WRITE) {
FD_SET(connssl->remotefd, &fds_read); FD_SET(BACKEND->remotefd, &fds_read);
n = connssl->remotefd; n = BACKEND->remotefd;
FD_SET(conn->sock[sockindex], &fds_write); FD_SET(conn->sock[sockindex], &fds_write);
if(n < conn->sock[sockindex]) if(n < conn->sock[sockindex])
n = conn->sock[sockindex]; n = conn->sock[sockindex];
@ -634,14 +635,15 @@ static int pipe_ssloverssl(struct connectdata *conn, int sockindex,
if(i < 0) if(i < 0)
return -1; /* Select error. */ 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. */ /* Try getting data from HTTPS proxy and pipe it upstream. */
n = 0; n = 0;
i = gsk_secure_soc_read(connproxyssl->handle, buf, sizeof buf, &n); i = gsk_secure_soc_read(connproxyssl->handle,
buf, sizeof buf, &n);
switch(i) { switch(i) {
case GSK_OK: case GSK_OK:
if(n) { if(n) {
i = write(connssl->remotefd, buf, n); i = write(BACKEND->remotefd, buf, n);
if(i < 0) if(i < 0)
return -1; return -1;
ret = 1; ret = 1;
@ -655,10 +657,10 @@ 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)) { FD_ISSET(conn->sock[sockindex], &fds_write)) {
/* Pipe data to HTTPS proxy. */ /* Pipe data to HTTPS proxy. */
n = read(connssl->remotefd, buf, sizeof buf); n = read(BACKEND->remotefd, buf, sizeof buf);
if(n < 0) if(n < 0)
return -1; return -1;
if(n) { if(n) {
@ -676,23 +678,23 @@ static int pipe_ssloverssl(struct connectdata *conn, int sockindex,
static void close_one(struct ssl_connect_data *connssl, static void close_one(struct ssl_connect_data *connssl,
struct connectdata *conn, int sockindex) struct connectdata *conn, int sockindex)
{ {
if(connssl->handle) { if(BACKEND->handle) {
gskit_status(conn->data, gsk_secure_soc_close(&connssl->handle), gskit_status(conn->data, gsk_secure_soc_close(&BACKEND->handle),
"gsk_secure_soc_close()", 0); "gsk_secure_soc_close()", 0);
/* Last chance to drain output. */ /* Last chance to drain output. */
while(pipe_ssloverssl(conn, sockindex, SOS_WRITE) > 0) while(pipe_ssloverssl(conn, sockindex, SOS_WRITE) > 0)
; ;
connssl->handle = (gsk_handle) NULL; BACKEND->handle = (gsk_handle) NULL;
if(connssl->localfd >= 0) { if(BACKEND->localfd >= 0) {
close(connssl->localfd); close(BACKEND->localfd);
connssl->localfd = -1; BACKEND->localfd = -1;
} }
if(connssl->remotefd >= 0) { if(BACKEND->remotefd >= 0) {
close(connssl->remotefd); close(BACKEND->remotefd);
connssl->remotefd = -1; BACKEND->remotefd = -1;
} }
} }
if(connssl->iocport >= 0) if(BACKEND->iocport >= 0)
close_async_handshake(connssl); close_async_handshake(connssl);
} }
@ -700,13 +702,14 @@ static void close_one(struct ssl_connect_data *connssl,
static ssize_t gskit_send(struct connectdata *conn, int sockindex, static ssize_t gskit_send(struct connectdata *conn, int sockindex,
const void *mem, size_t len, CURLcode *curlcode) const void *mem, size_t len, CURLcode *curlcode)
{ {
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct Curl_easy *data = conn->data; struct Curl_easy *data = conn->data;
CURLcode cc = CURLE_SEND_ERROR; CURLcode cc = CURLE_SEND_ERROR;
int written; int written;
if(pipe_ssloverssl(conn, sockindex, SOS_WRITE) >= 0) { if(pipe_ssloverssl(conn, sockindex, SOS_WRITE) >= 0) {
cc = gskit_status(data, cc = gskit_status(data,
gsk_secure_soc_write(conn->ssl[sockindex].handle, gsk_secure_soc_write(BACKEND->handle,
(char *) mem, (int) len, &written), (char *) mem, (int) len, &written),
"gsk_secure_soc_write()", CURLE_SEND_ERROR); "gsk_secure_soc_write()", CURLE_SEND_ERROR);
if(cc == CURLE_OK) if(cc == CURLE_OK)
@ -724,6 +727,7 @@ static ssize_t gskit_send(struct connectdata *conn, int sockindex,
static ssize_t gskit_recv(struct connectdata *conn, int num, char *buf, static ssize_t gskit_recv(struct connectdata *conn, int num, char *buf,
size_t buffersize, CURLcode *curlcode) size_t buffersize, CURLcode *curlcode)
{ {
struct ssl_connect_data *connssl = &conn->ssl[num];
struct Curl_easy *data = conn->data; struct Curl_easy *data = conn->data;
int buffsize; int buffsize;
int nread; int nread;
@ -731,7 +735,7 @@ static ssize_t gskit_recv(struct connectdata *conn, int num, char *buf,
if(pipe_ssloverssl(conn, num, SOS_READ) >= 0) { if(pipe_ssloverssl(conn, num, SOS_READ) >= 0) {
buffsize = buffersize > (size_t) INT_MAX? INT_MAX: (int) buffersize; 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), buf, buffsize, &nread),
"gsk_secure_soc_read()", CURLE_RECV_ERROR); "gsk_secure_soc_read()", CURLE_RECV_ERROR);
} }
@ -806,10 +810,10 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
/* Create SSL environment, start (preferably asynchronous) handshake. */ /* Create SSL environment, start (preferably asynchronous) handshake. */
connssl->handle = (gsk_handle) NULL; BACKEND->handle = (gsk_handle) NULL;
connssl->iocport = -1; BACKEND->iocport = -1;
connssl->localfd = -1; BACKEND->localfd = -1;
connssl->remotefd = -1; BACKEND->remotefd = -1;
/* GSKit supports two ways of specifying an SSL context: either by /* GSKit supports two ways of specifying an SSL context: either by
* application identifier (that should have been defined at the system * application identifier (that should have been defined at the system
@ -842,7 +846,7 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
} }
/* Create secure session. */ /* 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_secure_soc_open()", CURLE_SSL_CONNECT_ERROR);
gsk_environment_close(&envir); gsk_environment_close(&envir);
if(result) if(result)
@ -852,18 +856,18 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
if(conn->proxy_ssl[sockindex].use) { if(conn->proxy_ssl[sockindex].use) {
if(inetsocketpair(sockpair)) if(inetsocketpair(sockpair))
return CURLE_SSL_CONNECT_ERROR; return CURLE_SSL_CONNECT_ERROR;
connssl->localfd = sockpair[0]; BACKEND->localfd = sockpair[0];
connssl->remotefd = sockpair[1]; BACKEND->remotefd = sockpair[1];
setsockopt(connssl->localfd, SOL_SOCKET, SO_RCVBUF, setsockopt(BACKEND->localfd, SOL_SOCKET, SO_RCVBUF,
(void *) sobufsize, sizeof sobufsize); (void *) sobufsize, sizeof sobufsize);
setsockopt(connssl->remotefd, SOL_SOCKET, SO_RCVBUF, setsockopt(BACKEND->remotefd, SOL_SOCKET, SO_RCVBUF,
(void *) sobufsize, sizeof sobufsize); (void *) sobufsize, sizeof sobufsize);
setsockopt(connssl->localfd, SOL_SOCKET, SO_SNDBUF, setsockopt(BACKEND->localfd, SOL_SOCKET, SO_SNDBUF,
(void *) sobufsize, sizeof sobufsize); (void *) sobufsize, sizeof sobufsize);
setsockopt(connssl->remotefd, SOL_SOCKET, SO_SNDBUF, setsockopt(BACKEND->remotefd, SOL_SOCKET, SO_SNDBUF,
(void *) sobufsize, sizeof sobufsize); (void *) sobufsize, sizeof sobufsize);
curlx_nonblock(connssl->localfd, TRUE); curlx_nonblock(BACKEND->localfd, TRUE);
curlx_nonblock(connssl->remotefd, TRUE); curlx_nonblock(BACKEND->remotefd, TRUE);
} }
/* Determine which SSL/TLS version should be enabled. */ /* Determine which SSL/TLS version should be enabled. */
@ -897,7 +901,7 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
/* Process SNI. Ignore if not supported (on OS400 < V7R1). */ /* Process SNI. Ignore if not supported (on OS400 < V7R1). */
if(sni) { if(sni) {
result = set_buffer(data, connssl->handle, result = set_buffer(data, BACKEND->handle,
GSK_SSL_EXTN_SERVERNAME_REQUEST, sni, TRUE); GSK_SSL_EXTN_SERVERNAME_REQUEST, sni, TRUE);
if(result == CURLE_UNSUPPORTED_PROTOCOL) if(result == CURLE_UNSUPPORTED_PROTOCOL)
result = CURLE_OK; result = CURLE_OK;
@ -911,34 +915,34 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
if(timeout < 0) if(timeout < 0)
result = CURLE_OPERATION_TIMEDOUT; result = CURLE_OPERATION_TIMEDOUT;
else else
result = set_numeric(data, connssl->handle, GSK_HANDSHAKE_TIMEOUT, result = set_numeric(data, BACKEND->handle, GSK_HANDSHAKE_TIMEOUT,
(timeout + 999) / 1000); (timeout + 999) / 1000);
} }
if(!result) 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) if(!result)
result = set_numeric(data, connssl->handle, GSK_FD, connssl->localfd >= 0? result = set_numeric(data, BACKEND->handle, GSK_FD, BACKEND->localfd >= 0?
connssl->localfd: conn->sock[sockindex]); BACKEND->localfd: conn->sock[sockindex]);
if(!result) if(!result)
result = set_ciphers(conn, connssl->handle, &protoflags); result = set_ciphers(conn, BACKEND->handle, &protoflags);
if(!protoflags) { if(!protoflags) {
failf(data, "No SSL protocol/cipher combination enabled"); failf(data, "No SSL protocol/cipher combination enabled");
result = CURLE_SSL_CIPHER; result = CURLE_SSL_CIPHER;
} }
if(!result) 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)? (protoflags & CURL_GSKPROTO_SSLV2_MASK)?
GSK_PROTOCOL_SSLV2_ON: GSK_PROTOCOL_SSLV2_OFF, FALSE); GSK_PROTOCOL_SSLV2_ON: GSK_PROTOCOL_SSLV2_OFF, FALSE);
if(!result) 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)? (protoflags & CURL_GSKPROTO_SSLV3_MASK)?
GSK_PROTOCOL_SSLV3_ON: GSK_PROTOCOL_SSLV3_OFF, FALSE); GSK_PROTOCOL_SSLV3_ON: GSK_PROTOCOL_SSLV3_OFF, FALSE);
if(!result) 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)? (protoflags & CURL_GSKPROTO_TLSV10_MASK)?
GSK_PROTOCOL_TLSV1_ON: GSK_PROTOCOL_TLSV1_OFF, FALSE); GSK_PROTOCOL_TLSV1_ON: GSK_PROTOCOL_TLSV1_OFF, FALSE);
if(!result) { 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)? (protoflags & CURL_GSKPROTO_TLSV11_MASK)?
GSK_TRUE: GSK_FALSE, TRUE); GSK_TRUE: GSK_FALSE, TRUE);
if(result == CURLE_UNSUPPORTED_PROTOCOL) { if(result == CURLE_UNSUPPORTED_PROTOCOL) {
@ -950,7 +954,7 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
} }
} }
if(!result) { 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)? (protoflags & CURL_GSKPROTO_TLSV12_MASK)?
GSK_TRUE: GSK_FALSE, TRUE); GSK_TRUE: GSK_FALSE, TRUE);
if(result == CURLE_UNSUPPORTED_PROTOCOL) { if(result == CURLE_UNSUPPORTED_PROTOCOL) {
@ -962,18 +966,18 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
} }
} }
if(!result) 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: verifypeer? GSK_SERVER_AUTH_FULL:
GSK_SERVER_AUTH_PASSTHRU, FALSE); GSK_SERVER_AUTH_PASSTHRU, FALSE);
if(!result) { if(!result) {
/* Start handshake. Try asynchronous first. */ /* Start handshake. Try asynchronous first. */
memset(&commarea, 0, sizeof commarea); memset(&commarea, 0, sizeof commarea);
connssl->iocport = QsoCreateIOCompletionPort(); BACKEND->iocport = QsoCreateIOCompletionPort();
if(connssl->iocport != -1) { if(BACKEND->iocport != -1) {
result = gskit_status(data, result = gskit_status(data,
gsk_secure_soc_startInit(connssl->handle, gsk_secure_soc_startInit(BACKEND->handle,
connssl->iocport, BACKEND->iocport,
&commarea), &commarea),
"gsk_secure_soc_startInit()", "gsk_secure_soc_startInit()",
CURLE_SSL_CONNECT_ERROR); CURLE_SSL_CONNECT_ERROR);
@ -993,7 +997,7 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
} }
else { else {
/* No more completion port available. Use synchronous IO. */ /* 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); "gsk_secure_soc_init()", CURLE_SSL_CONNECT_ERROR);
if(!result) { if(!result) {
connssl->connecting_state = ssl_connect_3; connssl->connecting_state = ssl_connect_3;
@ -1026,7 +1030,7 @@ static CURLcode gskit_connect_step2(struct connectdata *conn, int sockindex,
timeout_ms = 0; timeout_ms = 0;
stmv.tv_sec = timeout_ms / 1000; stmv.tv_sec = timeout_ms / 1000;
stmv.tv_usec = (timeout_ms - stmv.tv_sec * 1000) * 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. */ case 1: /* Operation complete. */
break; break;
case -1: /* An error occurred: handshake still in progress. */ case -1: /* An error occurred: handshake still in progress. */
@ -1075,7 +1079,7 @@ static CURLcode gskit_connect_step3(struct connectdata *conn, int sockindex)
/* SSL handshake done: gather certificate info and verify host. */ /* 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, GSK_PARTNER_CERT_INFO,
&cdev, &cdec), &cdev, &cdec),
"gsk_attribute_get_cert_info()", CURLE_SSL_CONNECT_ERROR) == "gsk_attribute_get_cert_info()", CURLE_SSL_CONNECT_ERROR) ==
@ -1260,7 +1264,7 @@ static int Curl_gskit_shutdown(struct connectdata *conn, int sockindex)
int rc; int rc;
char buf[120]; char buf[120];
if(!connssl->handle) if(!BACKEND->handle)
return 0; return 0;
if(data->set.ftp_ccc != CURLFTPSSL_CCC_ACTIVE) if(data->set.ftp_ccc != CURLFTPSSL_CCC_ACTIVE)
@ -1314,12 +1318,13 @@ static size_t Curl_gskit_version(char *buffer, size_t size)
static 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 err;
int errlen; int errlen;
/* The only thing that can be tested here is at the socket level. */ /* 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 */ return 0; /* connection has been closed */
err = 0; err = 0;
@ -1337,7 +1342,7 @@ static void *Curl_gskit_get_internals(struct ssl_connect_data *connssl,
CURLINFO info UNUSED_PARAM) CURLINFO info UNUSED_PARAM)
{ {
(void)info; (void)info;
return connssl->handle; return BACKEND->handle;
} }
const struct Curl_ssl Curl_ssl_gskit = { const struct Curl_ssl Curl_ssl_gskit = {

View File

@ -107,6 +107,8 @@ static bool gtls_inited = FALSE;
# include <gnutls/ocsp.h> # include <gnutls/ocsp.h>
#endif #endif
#define BACKEND connssl
/* /*
* Custom push and pull callback functions used by GNU TLS to read and write * 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() * to the socket. These functions are simple wrappers to send() and recv()
@ -276,7 +278,7 @@ static CURLcode handshake(struct connectdata *conn,
{ {
struct Curl_easy *data = conn->data; struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex]; 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]; curl_socket_t sockfd = conn->sock[sockindex];
time_t timeout_ms; time_t timeout_ms;
int rc; int rc;
@ -474,6 +476,7 @@ gtls_connect_step1(struct connectdata *conn,
int sockindex) int sockindex)
{ {
struct Curl_easy *data = conn->data; struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
unsigned int init_flags; unsigned int init_flags;
gnutls_session_t session; gnutls_session_t session;
int rc; int rc;
@ -509,7 +512,7 @@ gtls_connect_step1(struct connectdata *conn,
const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
conn->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 /* to make us tolerant against being called more than once for the
same connection */ same connection */
return CURLE_OK; return CURLE_OK;
@ -525,7 +528,7 @@ gtls_connect_step1(struct connectdata *conn,
sni = FALSE; /* SSLv3 has no SNI */ sni = FALSE; /* SSLv3 has no SNI */
/* allocate a cred struct */ /* 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) { if(rc != GNUTLS_E_SUCCESS) {
failf(data, "gnutls_cert_all_cred() failed: %s", gnutls_strerror(rc)); failf(data, "gnutls_cert_all_cred() failed: %s", gnutls_strerror(rc));
return CURLE_SSL_CONNECT_ERROR; return CURLE_SSL_CONNECT_ERROR;
@ -536,15 +539,14 @@ gtls_connect_step1(struct connectdata *conn,
infof(data, "Using TLS-SRP username: %s\n", SSL_SET_OPTION(username)); infof(data, "Using TLS-SRP username: %s\n", SSL_SET_OPTION(username));
rc = gnutls_srp_allocate_client_credentials( rc = gnutls_srp_allocate_client_credentials(
&conn->ssl[sockindex].srp_client_cred); &BACKEND->srp_client_cred);
if(rc != GNUTLS_E_SUCCESS) { if(rc != GNUTLS_E_SUCCESS) {
failf(data, "gnutls_srp_allocate_client_cred() failed: %s", failf(data, "gnutls_srp_allocate_client_cred() failed: %s",
gnutls_strerror(rc)); gnutls_strerror(rc));
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
} }
rc = gnutls_srp_set_client_credentials(conn->ssl[sockindex]. rc = gnutls_srp_set_client_credentials(BACKEND->srp_client_cred,
srp_client_cred,
SSL_SET_OPTION(username), SSL_SET_OPTION(username),
SSL_SET_OPTION(password)); SSL_SET_OPTION(password));
if(rc != GNUTLS_E_SUCCESS) { if(rc != GNUTLS_E_SUCCESS) {
@ -557,10 +559,10 @@ gtls_connect_step1(struct connectdata *conn,
if(SSL_CONN_CONFIG(CAfile)) { if(SSL_CONN_CONFIG(CAfile)) {
/* set the trusted CA cert bundle file */ /* 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); 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), SSL_CONN_CONFIG(CAfile),
GNUTLS_X509_FMT_PEM); GNUTLS_X509_FMT_PEM);
if(rc < 0) { if(rc < 0) {
@ -577,7 +579,7 @@ gtls_connect_step1(struct connectdata *conn,
#ifdef HAS_CAPATH #ifdef HAS_CAPATH
if(SSL_CONN_CONFIG(CApath)) { if(SSL_CONN_CONFIG(CApath)) {
/* set the trusted CA cert directory */ /* 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), SSL_CONN_CONFIG(CApath),
GNUTLS_X509_FMT_PEM); GNUTLS_X509_FMT_PEM);
if(rc < 0) { if(rc < 0) {
@ -596,13 +598,13 @@ gtls_connect_step1(struct connectdata *conn,
/* use system ca certificate store as fallback */ /* use system ca certificate store as fallback */
if(SSL_CONN_CONFIG(verifypeer) && if(SSL_CONN_CONFIG(verifypeer) &&
!(SSL_CONN_CONFIG(CAfile) || SSL_CONN_CONFIG(CApath))) { !(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 #endif
if(SSL_SET_OPTION(CRLfile)) { if(SSL_SET_OPTION(CRLfile)) {
/* set the CRL list file */ /* 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), SSL_SET_OPTION(CRLfile),
GNUTLS_X509_FMT_PEM); GNUTLS_X509_FMT_PEM);
if(rc < 0) { if(rc < 0) {
@ -623,14 +625,14 @@ gtls_connect_step1(struct connectdata *conn,
init_flags |= GNUTLS_NO_TICKETS; init_flags |= GNUTLS_NO_TICKETS;
#endif #endif
rc = gnutls_init(&conn->ssl[sockindex].session, init_flags); rc = gnutls_init(&BACKEND->session, init_flags);
if(rc != GNUTLS_E_SUCCESS) { if(rc != GNUTLS_E_SUCCESS) {
failf(data, "gnutls_init() failed: %d", rc); failf(data, "gnutls_init() failed: %d", rc);
return CURLE_SSL_CONNECT_ERROR; return CURLE_SSL_CONNECT_ERROR;
} }
/* convenient assign */ /* convenient assign */
session = conn->ssl[sockindex].session; session = BACKEND->session;
if((0 == Curl_inet_pton(AF_INET, hostname, &addr)) && if((0 == Curl_inet_pton(AF_INET, hostname, &addr)) &&
#ifdef ENABLE_IPV6 #ifdef ENABLE_IPV6
@ -787,7 +789,7 @@ gtls_connect_step1(struct connectdata *conn,
GNUTLS_PKCS_USE_PBES2_AES_128 | GNUTLS_PKCS_USE_PBES2_AES_192 | GNUTLS_PKCS_USE_PBES2_AES_128 | GNUTLS_PKCS_USE_PBES2_AES_192 |
GNUTLS_PKCS_USE_PBES2_AES_256; GNUTLS_PKCS_USE_PBES2_AES_256;
rc = gnutls_certificate_set_x509_key_file2( rc = gnutls_certificate_set_x509_key_file2(
conn->ssl[sockindex].cred, BACKEND->cred,
SSL_SET_OPTION(cert), SSL_SET_OPTION(cert),
SSL_SET_OPTION(key) ? SSL_SET_OPTION(key) ?
SSL_SET_OPTION(key) : SSL_SET_OPTION(cert), SSL_SET_OPTION(key) : SSL_SET_OPTION(cert),
@ -807,7 +809,7 @@ gtls_connect_step1(struct connectdata *conn,
} }
else { else {
if(gnutls_certificate_set_x509_key_file( if(gnutls_certificate_set_x509_key_file(
conn->ssl[sockindex].cred, BACKEND->cred,
SSL_SET_OPTION(cert), SSL_SET_OPTION(cert),
SSL_SET_OPTION(key) ? SSL_SET_OPTION(key) ?
SSL_SET_OPTION(key) : SSL_SET_OPTION(cert), SSL_SET_OPTION(key) : SSL_SET_OPTION(cert),
@ -823,7 +825,7 @@ gtls_connect_step1(struct connectdata *conn,
/* put the credentials to the current session */ /* put the credentials to the current session */
if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP) { if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP) {
rc = gnutls_credentials_set(session, GNUTLS_CRD_SRP, rc = gnutls_credentials_set(session, GNUTLS_CRD_SRP,
conn->ssl[sockindex].srp_client_cred); BACKEND->srp_client_cred);
if(rc != GNUTLS_E_SUCCESS) { if(rc != GNUTLS_E_SUCCESS) {
failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc)); failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc));
return CURLE_SSL_CONNECT_ERROR; return CURLE_SSL_CONNECT_ERROR;
@ -833,7 +835,7 @@ gtls_connect_step1(struct connectdata *conn,
#endif #endif
{ {
rc = gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, rc = gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE,
conn->ssl[sockindex].cred); BACKEND->cred);
if(rc != GNUTLS_E_SUCCESS) { if(rc != GNUTLS_E_SUCCESS) {
failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc)); failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc));
return CURLE_SSL_CONNECT_ERROR; return CURLE_SSL_CONNECT_ERROR;
@ -966,7 +968,8 @@ gtls_connect_step3(struct connectdata *conn,
time_t certclock; time_t certclock;
const char *ptr; const char *ptr;
struct Curl_easy *data = conn->data; 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; int rc;
#ifdef HAS_ALPN #ifdef HAS_ALPN
gnutls_datum_t proto; gnutls_datum_t proto;
@ -1516,13 +1519,15 @@ static CURLcode Curl_gtls_connect(struct connectdata *conn, int sockindex)
static bool Curl_gtls_data_pending(const struct connectdata *conn, static bool Curl_gtls_data_pending(const struct connectdata *conn,
int connindex) int connindex)
{ {
const struct ssl_connect_data *connssl = &conn->ssl[connindex];
bool res = FALSE; bool res = FALSE;
if(conn->ssl[connindex].session && if(BACKEND->session &&
0 != gnutls_record_check_pending(conn->ssl[connindex].session)) 0 != gnutls_record_check_pending(BACKEND->session))
res = TRUE; res = TRUE;
if(conn->proxy_ssl[connindex].session && connssl = &conn->proxy_ssl[connindex];
0 != gnutls_record_check_pending(conn->proxy_ssl[connindex].session)) if(BACKEND->session &&
0 != gnutls_record_check_pending(BACKEND->session))
res = TRUE; res = TRUE;
return res; return res;
@ -1534,7 +1539,8 @@ static ssize_t gtls_send(struct connectdata *conn,
size_t len, size_t len,
CURLcode *curlcode) 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) { if(rc < 0) {
*curlcode = (rc == GNUTLS_E_AGAIN) *curlcode = (rc == GNUTLS_E_AGAIN)
@ -1547,21 +1553,21 @@ static ssize_t gtls_send(struct connectdata *conn,
return rc; return rc;
} }
static void close_one(struct ssl_connect_data *ssl) static void close_one(struct ssl_connect_data *connssl)
{ {
if(ssl->session) { if(BACKEND->session) {
gnutls_bye(ssl->session, GNUTLS_SHUT_RDWR); gnutls_bye(BACKEND->session, GNUTLS_SHUT_RDWR);
gnutls_deinit(ssl->session); gnutls_deinit(BACKEND->session);
ssl->session = NULL; BACKEND->session = NULL;
} }
if(ssl->cred) { if(BACKEND->cred) {
gnutls_certificate_free_credentials(ssl->cred); gnutls_certificate_free_credentials(BACKEND->cred);
ssl->cred = NULL; BACKEND->cred = NULL;
} }
#ifdef USE_TLS_SRP #ifdef USE_TLS_SRP
if(ssl->srp_client_cred) { if(BACKEND->srp_client_cred) {
gnutls_srp_free_client_credentials(ssl->srp_client_cred); gnutls_srp_free_client_credentials(BACKEND->srp_client_cred);
ssl->srp_client_cred = NULL; BACKEND->srp_client_cred = NULL;
} }
#endif #endif
} }
@ -1578,6 +1584,7 @@ static void Curl_gtls_close(struct connectdata *conn, int sockindex)
*/ */
static 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; ssize_t result;
int retval = 0; int retval = 0;
struct Curl_easy *data = conn->data; struct Curl_easy *data = conn->data;
@ -1590,16 +1597,16 @@ static int Curl_gtls_shutdown(struct connectdata *conn, int sockindex)
we do not send one. Let's hope other servers do the same... */ we do not send one. Let's hope other servers do the same... */
if(data->set.ftp_ccc == CURLFTPSSL_CCC_ACTIVE) 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) { while(!done) {
int what = SOCKET_READABLE(conn->sock[sockindex], int what = SOCKET_READABLE(conn->sock[sockindex],
SSL_SHUTDOWN_TIMEOUT); SSL_SHUTDOWN_TIMEOUT);
if(what > 0) { if(what > 0) {
/* Something to read, let's do it and hope that it is the close /* Something to read, let's do it and hope that it is the close
notify alert from the server */ notify alert from the server */
result = gnutls_record_recv(conn->ssl[sockindex].session, result = gnutls_record_recv(BACKEND->session,
buf, sizeof(buf)); buf, sizeof(buf));
switch(result) { switch(result) {
case 0: case 0:
@ -1630,18 +1637,18 @@ static int Curl_gtls_shutdown(struct connectdata *conn, int sockindex)
done = 1; 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 #ifdef USE_TLS_SRP
if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP
&& SSL_SET_OPTION(username) != NULL) && 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 #endif
conn->ssl[sockindex].cred = NULL; BACKEND->cred = NULL;
conn->ssl[sockindex].session = NULL; BACKEND->session = NULL;
return retval; return retval;
} }
@ -1652,9 +1659,10 @@ static ssize_t gtls_recv(struct connectdata *conn, /* connection data */
size_t buffersize, /* max amount to read */ size_t buffersize, /* max amount to read */
CURLcode *curlcode) CURLcode *curlcode)
{ {
struct ssl_connect_data *connssl = &conn->ssl[num];
ssize_t ret; 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)) { if((ret == GNUTLS_E_AGAIN) || (ret == GNUTLS_E_INTERRUPTED)) {
*curlcode = CURLE_AGAIN; *curlcode = CURLE_AGAIN;
return -1; return -1;
@ -1786,7 +1794,7 @@ static void *Curl_gtls_get_internals(struct ssl_connect_data *connssl,
CURLINFO info UNUSED_PARAM) CURLINFO info UNUSED_PARAM)
{ {
(void)info; (void)info;
return connssl->session; return BACKEND->session;
} }
const struct Curl_ssl Curl_ssl_gnutls = { const struct Curl_ssl Curl_ssl_gnutls = {

View File

@ -61,6 +61,8 @@
#include "curl_memory.h" #include "curl_memory.h"
#include "memdebug.h" #include "memdebug.h"
#define BACKEND connssl
/* apply threading? */ /* apply threading? */
#if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32) #if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32)
#define THREADING_SUPPORT #define THREADING_SUPPORT
@ -214,9 +216,9 @@ set_ssl_version_min_max(struct connectdata *conn, int sockindex)
return result; 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_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); mbedtls_ver_max);
return result; return result;
@ -248,9 +250,9 @@ mbed_connect_step1(struct connectdata *conn,
#ifdef THREADING_SUPPORT #ifdef THREADING_SUPPORT
entropy_init_mutex(&ts_entropy); 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); &ts_entropy, NULL, 0);
if(ret) { if(ret) {
#ifdef MBEDTLS_ERROR_C #ifdef MBEDTLS_ERROR_C
@ -260,11 +262,11 @@ mbed_connect_step1(struct connectdata *conn,
-ret, errorbuf); -ret, errorbuf);
} }
#else #else
mbedtls_entropy_init(&connssl->entropy); mbedtls_entropy_init(&BACKEND->entropy);
mbedtls_ctr_drbg_init(&connssl->ctr_drbg); mbedtls_ctr_drbg_init(&BACKEND->ctr_drbg);
ret = mbedtls_ctr_drbg_seed(&connssl->ctr_drbg, mbedtls_entropy_func, ret = mbedtls_ctr_drbg_seed(&BACKEND->ctr_drbg, mbedtls_entropy_func,
&connssl->entropy, NULL, 0); &BACKEND->entropy, NULL, 0);
if(ret) { if(ret) {
#ifdef MBEDTLS_ERROR_C #ifdef MBEDTLS_ERROR_C
mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
@ -275,10 +277,10 @@ mbed_connect_step1(struct connectdata *conn,
#endif /* THREADING_SUPPORT */ #endif /* THREADING_SUPPORT */
/* Load the trusted CA */ /* Load the trusted CA */
mbedtls_x509_crt_init(&connssl->cacert); mbedtls_x509_crt_init(&BACKEND->cacert);
if(ssl_cafile) { 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) { if(ret<0) {
#ifdef MBEDTLS_ERROR_C #ifdef MBEDTLS_ERROR_C
@ -293,7 +295,7 @@ mbed_connect_step1(struct connectdata *conn,
} }
if(ssl_capath) { 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) { if(ret<0) {
#ifdef MBEDTLS_ERROR_C #ifdef MBEDTLS_ERROR_C
@ -308,10 +310,10 @@ mbed_connect_step1(struct connectdata *conn,
} }
/* Load the client certificate */ /* Load the client certificate */
mbedtls_x509_crt_init(&connssl->clicert); mbedtls_x509_crt_init(&BACKEND->clicert);
if(ssl_cert) { 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) { if(ret) {
#ifdef MBEDTLS_ERROR_C #ifdef MBEDTLS_ERROR_C
@ -325,12 +327,12 @@ mbed_connect_step1(struct connectdata *conn,
} }
/* Load the client private key */ /* Load the client private key */
mbedtls_pk_init(&connssl->pk); mbedtls_pk_init(&BACKEND->pk);
if(SSL_SET_OPTION(key)) { 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)); 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; ret = MBEDTLS_ERR_PK_TYPE_MISMATCH;
if(ret) { if(ret) {
@ -345,10 +347,10 @@ mbed_connect_step1(struct connectdata *conn,
} }
/* Load the CRL */ /* Load the CRL */
mbedtls_x509_crl_init(&connssl->crl); mbedtls_x509_crl_init(&BACKEND->crl);
if(ssl_crlfile) { 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) { if(ret) {
#ifdef MBEDTLS_ERROR_C #ifdef MBEDTLS_ERROR_C
@ -363,14 +365,14 @@ mbed_connect_step1(struct connectdata *conn,
infof(data, "mbedTLS: Connecting to %s:%d\n", hostname, port); 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); mbedtls_ssl_init(&BACKEND->ssl);
if(mbedtls_ssl_setup(&connssl->ssl, &connssl->config)) { if(mbedtls_ssl_setup(&BACKEND->ssl, &BACKEND->config)) {
failf(data, "mbedTLS: ssl_init failed"); failf(data, "mbedTLS: ssl_init failed");
return CURLE_SSL_CONNECT_ERROR; 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_IS_CLIENT,
MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_TRANSPORT_STREAM,
MBEDTLS_SSL_PRESET_DEFAULT); MBEDTLS_SSL_PRESET_DEFAULT);
@ -380,20 +382,20 @@ mbed_connect_step1(struct connectdata *conn,
} }
/* new profile with RSA min key len = 1024 ... */ /* 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); &mbedtls_x509_crt_profile_fr);
switch(SSL_CONN_CONFIG(version)) { switch(SSL_CONN_CONFIG(version)) {
case CURL_SSLVERSION_DEFAULT: case CURL_SSLVERSION_DEFAULT:
case CURL_SSLVERSION_TLSv1: 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); MBEDTLS_SSL_MINOR_VERSION_1);
infof(data, "mbedTLS: Set min SSL version to TLS 1.0\n"); infof(data, "mbedTLS: Set min SSL version to TLS 1.0\n");
break; break;
case CURL_SSLVERSION_SSLv3: 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_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); MBEDTLS_SSL_MINOR_VERSION_0);
infof(data, "mbedTLS: Set SSL version to SSLv3\n"); infof(data, "mbedTLS: Set SSL version to SSLv3\n");
break; break;
@ -412,25 +414,25 @@ mbed_connect_step1(struct connectdata *conn,
return CURLE_SSL_CONNECT_ERROR; 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, mbedtls_ssl_conf_rng(&BACKEND->config, mbedtls_ctr_drbg_random,
&connssl->ctr_drbg); &BACKEND->ctr_drbg);
mbedtls_ssl_set_bio(&connssl->ssl, &conn->sock[sockindex], mbedtls_ssl_set_bio(&BACKEND->ssl, &conn->sock[sockindex],
mbedtls_net_send, mbedtls_net_send,
mbedtls_net_recv, mbedtls_net_recv,
NULL /* rev_timeout() */); NULL /* rev_timeout() */);
mbedtls_ssl_conf_ciphersuites(&connssl->config, mbedtls_ssl_conf_ciphersuites(&BACKEND->config,
mbedtls_ssl_list_ciphersuites()); mbedtls_ssl_list_ciphersuites());
#if defined(MBEDTLS_SSL_RENEGOTIATION) #if defined(MBEDTLS_SSL_RENEGOTIATION)
mbedtls_ssl_conf_renegotiation(&connssl->config, mbedtls_ssl_conf_renegotiation(&BACKEND->config,
MBEDTLS_SSL_RENEGOTIATION_ENABLED); MBEDTLS_SSL_RENEGOTIATION_ENABLED);
#endif #endif
#if defined(MBEDTLS_SSL_SESSION_TICKETS) #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); MBEDTLS_SSL_SESSION_TICKETS_DISABLED);
#endif #endif
@ -440,7 +442,7 @@ mbed_connect_step1(struct connectdata *conn,
Curl_ssl_sessionid_lock(conn); Curl_ssl_sessionid_lock(conn);
if(!Curl_ssl_getsessionid(conn, &old_session, NULL, sockindex)) { 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) { if(ret) {
Curl_ssl_sessionid_unlock(conn); Curl_ssl_sessionid_unlock(conn);
failf(data, "mbedtls_ssl_set_session returned -0x%x", -ret); failf(data, "mbedtls_ssl_set_session returned -0x%x", -ret);
@ -451,15 +453,15 @@ mbed_connect_step1(struct connectdata *conn,
Curl_ssl_sessionid_unlock(conn); Curl_ssl_sessionid_unlock(conn);
} }
mbedtls_ssl_conf_ca_chain(&connssl->config, mbedtls_ssl_conf_ca_chain(&BACKEND->config,
&connssl->cacert, &BACKEND->cacert,
&connssl->crl); &BACKEND->crl);
if(SSL_SET_OPTION(key)) { if(SSL_SET_OPTION(key)) {
mbedtls_ssl_conf_own_cert(&connssl->config, mbedtls_ssl_conf_own_cert(&BACKEND->config,
&connssl->clicert, &connssl->pk); &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* /* 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 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. */ host specified as an IP address, this function must be used. */
@ -469,7 +471,7 @@ mbed_connect_step1(struct connectdata *conn,
#ifdef HAS_ALPN #ifdef HAS_ALPN
if(conn->bits.tls_enable_alpn) { if(conn->bits.tls_enable_alpn) {
const char **p = &connssl->protocols[0]; const char **p = &BACKEND->protocols[0];
#ifdef USE_NGHTTP2 #ifdef USE_NGHTTP2
if(data->set.httpversion >= CURL_HTTP_VERSION_2) if(data->set.httpversion >= CURL_HTTP_VERSION_2)
*p++ = NGHTTP2_PROTO_VERSION_ID; *p++ = NGHTTP2_PROTO_VERSION_ID;
@ -478,19 +480,19 @@ mbed_connect_step1(struct connectdata *conn,
*p = NULL; *p = NULL;
/* this function doesn't clone the protocols array, which is why we need /* this function doesn't clone the protocols array, which is why we need
to keep it around */ to keep it around */
if(mbedtls_ssl_conf_alpn_protocols(&connssl->config, if(mbedtls_ssl_conf_alpn_protocols(&BACKEND->config,
&connssl->protocols[0])) { &BACKEND->protocols[0])) {
failf(data, "Failed setting ALPN protocols"); failf(data, "Failed setting ALPN protocols");
return CURLE_SSL_CONNECT_ERROR; 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); infof(data, "ALPN, offering %s\n", *p);
} }
#endif #endif
#ifdef MBEDTLS_DEBUG #ifdef MBEDTLS_DEBUG
/* In order to make that work in mbedtls MBEDTLS_DEBUG_C must be defined. */ /* 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 /* - 0 No debug
* - 1 Error * - 1 Error
* - 2 State change * - 2 State change
@ -502,7 +504,7 @@ mbed_connect_step1(struct connectdata *conn,
/* give application a chance to interfere with mbedTLS set up. */ /* give application a chance to interfere with mbedTLS set up. */
if(data->set.ssl.fsslctx) { 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); data->set.ssl.fsslctxp);
if(ret) { if(ret) {
failf(data, "error signaled by ssl ctx callback"); failf(data, "error signaled by ssl ctx callback");
@ -537,7 +539,7 @@ mbed_connect_step2(struct connectdata *conn,
conn->recv[sockindex] = mbed_recv; conn->recv[sockindex] = mbed_recv;
conn->send[sockindex] = mbed_send; conn->send[sockindex] = mbed_send;
ret = mbedtls_ssl_handshake(&connssl->ssl); ret = mbedtls_ssl_handshake(&BACKEND->ssl);
if(ret == MBEDTLS_ERR_SSL_WANT_READ) { if(ret == MBEDTLS_ERR_SSL_WANT_READ) {
connssl->connecting_state = ssl_connect_2_reading; connssl->connecting_state = ssl_connect_2_reading;
@ -557,10 +559,10 @@ mbed_connect_step2(struct connectdata *conn,
} }
infof(data, "mbedTLS: Handshake complete, cipher is %s\n", 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 && SSL_CONN_CONFIG(verifypeer)) {
if(ret & MBEDTLS_X509_BADCERT_EXPIRED) if(ret & MBEDTLS_X509_BADCERT_EXPIRED)
@ -580,7 +582,7 @@ mbed_connect_step2(struct connectdata *conn,
return CURLE_PEER_FAILED_VERIFICATION; 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) { if(peercert && data->set.verbose) {
const size_t bufsize = 16384; const size_t bufsize = 16384;
@ -650,7 +652,7 @@ mbed_connect_step2(struct connectdata *conn,
#ifdef HAS_ALPN #ifdef HAS_ALPN
if(conn->bits.tls_enable_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) { if(next_protocol) {
infof(data, "ALPN, server accepted to use %s\n", next_protocol); infof(data, "ALPN, server accepted to use %s\n", next_protocol);
@ -700,7 +702,7 @@ mbed_connect_step3(struct connectdata *conn,
mbedtls_ssl_session_init(our_ssl_sessionid); 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) { if(ret) {
free(our_ssl_sessionid); free(our_ssl_sessionid);
failf(data, "mbedtls_ssl_get_session returned -0x%x", -ret); failf(data, "mbedtls_ssl_get_session returned -0x%x", -ret);
@ -730,9 +732,10 @@ static ssize_t mbed_send(struct connectdata *conn, int sockindex,
const void *mem, size_t len, const void *mem, size_t len,
CURLcode *curlcode) CURLcode *curlcode)
{ {
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
int ret = -1; int ret = -1;
ret = mbedtls_ssl_write(&conn->ssl[sockindex].ssl, ret = mbedtls_ssl_write(&BACKEND->ssl,
(unsigned char *)mem, len); (unsigned char *)mem, len);
if(ret < 0) { if(ret < 0) {
@ -751,15 +754,16 @@ static void Curl_mbedtls_close_all(struct Curl_easy *data)
static 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); struct ssl_connect_data *connssl = &conn->ssl[sockindex];
mbedtls_x509_crt_free(&conn->ssl[sockindex].clicert); mbedtls_pk_free(&BACKEND->pk);
mbedtls_x509_crt_free(&conn->ssl[sockindex].cacert); mbedtls_x509_crt_free(&BACKEND->clicert);
mbedtls_x509_crl_free(&conn->ssl[sockindex].crl); mbedtls_x509_crt_free(&BACKEND->cacert);
mbedtls_ssl_config_free(&conn->ssl[sockindex].config); mbedtls_x509_crl_free(&BACKEND->crl);
mbedtls_ssl_free(&conn->ssl[sockindex].ssl); mbedtls_ssl_config_free(&BACKEND->config);
mbedtls_ctr_drbg_free(&conn->ssl[sockindex].ctr_drbg); mbedtls_ssl_free(&BACKEND->ssl);
mbedtls_ctr_drbg_free(&BACKEND->ctr_drbg);
#ifndef THREADING_SUPPORT #ifndef THREADING_SUPPORT
mbedtls_entropy_free(&conn->ssl[sockindex].entropy); mbedtls_entropy_free(&BACKEND->entropy);
#endif /* THREADING_SUPPORT */ #endif /* THREADING_SUPPORT */
} }
@ -767,11 +771,12 @@ static ssize_t mbed_recv(struct connectdata *conn, int num,
char *buf, size_t buffersize, char *buf, size_t buffersize,
CURLcode *curlcode) CURLcode *curlcode)
{ {
struct ssl_connect_data *connssl = &conn->ssl[num];
int ret = -1; int ret = -1;
ssize_t len = -1; ssize_t len = -1;
memset(buf, 0, buffersize); 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); buffersize);
if(ret <= 0) { if(ret <= 0) {
@ -1001,7 +1006,8 @@ static void Curl_mbedtls_cleanup(void)
static bool Curl_mbedtls_data_pending(const struct connectdata *conn, static bool Curl_mbedtls_data_pending(const struct connectdata *conn,
int sockindex) 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, static void Curl_mbedtls_sha256sum(const unsigned char *input,
@ -1016,7 +1022,7 @@ static void *Curl_mbedtls_get_internals(struct ssl_connect_data *connssl,
CURLINFO info UNUSED_PARAM) CURLINFO info UNUSED_PARAM)
{ {
(void)info; (void)info;
return &connssl->ssl; return &BACKEND->ssl;
} }
const struct Curl_ssl Curl_ssl_mbedtls = { const struct Curl_ssl Curl_ssl_mbedtls = {

View File

@ -78,6 +78,8 @@
/* enough to fit the string "PEM Token #[0|1]" */ /* enough to fit the string "PEM Token #[0|1]" */
#define SLOTSIZE 13 #define SLOTSIZE 13
#define BACKEND connssl
static PRLock *nss_initlock = NULL; static PRLock *nss_initlock = NULL;
static PRLock *nss_crllock = NULL; static PRLock *nss_crllock = NULL;
static PRLock *nss_findslot_lock = NULL; static PRLock *nss_findslot_lock = NULL;
@ -396,7 +398,7 @@ static CURLcode insert_wrapped_ptr(struct curl_llist *list, void *ptr)
/* Call PK11_CreateGenericObject() with the given obj_class and filename. If /* 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 call succeeds, append the object handle to the list of objects so that
* the object can be destroyed in Curl_nss_close(). */ * 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, CK_OBJECT_CLASS obj_class,
const char *filename, bool cacert) const char *filename, bool cacert)
{ {
@ -435,14 +437,14 @@ static CURLcode nss_create_object(struct ssl_connect_data *ssl,
if(!obj) if(!obj)
return result; 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); PK11_DestroyGenericObject(obj);
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
} }
if(!cacert && CKO_CERTIFICATE == obj_class) if(!cacert && CKO_CERTIFICATE == obj_class)
/* store reference to a client certificate */ /* store reference to a client certificate */
ssl->obj_clicert = obj; BACKEND->obj_clicert = obj;
return CURLE_OK; return CURLE_OK;
} }
@ -1017,7 +1019,7 @@ static CURLcode cmp_peer_pubkey(struct ssl_connect_data *connssl,
const char *pinnedpubkey) const char *pinnedpubkey)
{ {
CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH; CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;
struct Curl_easy *data = connssl->data; struct Curl_easy *data = BACKEND->data;
CERTCertificate *cert; CERTCertificate *cert;
if(!pinnedpubkey) if(!pinnedpubkey)
@ -1025,7 +1027,7 @@ static CURLcode cmp_peer_pubkey(struct ssl_connect_data *connssl,
return CURLE_OK; return CURLE_OK;
/* get peer certificate */ /* get peer certificate */
cert = SSL_PeerCertificate(connssl->handle); cert = SSL_PeerCertificate(BACKEND->handle);
if(cert) { if(cert) {
/* extract public key from peer certificate */ /* extract public key from peer certificate */
SECKEYPublicKey *pubkey = CERT_ExtractPublicKey(cert); SECKEYPublicKey *pubkey = CERT_ExtractPublicKey(cert);
@ -1069,11 +1071,11 @@ static SECStatus SelectClientCert(void *arg, PRFileDesc *sock,
struct SECKEYPrivateKeyStr **pRetKey) struct SECKEYPrivateKeyStr **pRetKey)
{ {
struct ssl_connect_data *connssl = (struct ssl_connect_data *)arg; struct ssl_connect_data *connssl = (struct ssl_connect_data *)arg;
struct Curl_easy *data = connssl->data; struct Curl_easy *data = BACKEND->data;
const char *nickname = connssl->client_nickname; const char *nickname = BACKEND->client_nickname;
static const char pem_slotname[] = "PEM Token #1"; static const char pem_slotname[] = "PEM Token #1";
if(connssl->obj_clicert) { if(BACKEND->obj_clicert) {
/* use the cert/key provided by PEM reader */ /* use the cert/key provided by PEM reader */
SECItem cert_der = { 0, NULL, 0 }; SECItem cert_der = { 0, NULL, 0 };
void *proto_win = SSL_RevealPinArg(sock); void *proto_win = SSL_RevealPinArg(sock);
@ -1086,7 +1088,7 @@ static SECStatus SelectClientCert(void *arg, PRFileDesc *sock,
return SECFailure; 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) { &cert_der) != SECSuccess) {
failf(data, "NSS: CKA_VALUE not found in PK11 generic object"); failf(data, "NSS: CKA_VALUE not found in PK11 generic object");
PK11_FreeSlot(slot); PK11_FreeSlot(slot);
@ -1428,11 +1430,12 @@ static void Curl_nss_cleanup(void)
*/ */
static 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; int rc;
char buf; char buf;
rc = 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)); PR_SecondsToInterval(1));
if(rc > 0) if(rc > 0)
return 1; /* connection still in place */ return 1; /* connection still in place */
@ -1446,26 +1449,26 @@ static int Curl_nss_check_cxn(struct connectdata *conn)
static void nss_close(struct ssl_connect_data *connssl) static void nss_close(struct ssl_connect_data *connssl)
{ {
/* before the cleanup, check whether we are using a client certificate */ /* before the cleanup, check whether we are using a client certificate */
const bool client_cert = (connssl->client_nickname != NULL) const bool client_cert = (BACKEND->client_nickname != NULL)
|| (connssl->obj_clicert != NULL); || (BACKEND->obj_clicert != NULL);
free(connssl->client_nickname); free(BACKEND->client_nickname);
connssl->client_nickname = NULL; BACKEND->client_nickname = NULL;
/* destroy all NSS objects in order to avoid failure of NSS shutdown */ /* destroy all NSS objects in order to avoid failure of NSS shutdown */
Curl_llist_destroy(&connssl->obj_list, NULL); Curl_llist_destroy(&BACKEND->obj_list, NULL);
connssl->obj_clicert = NULL; BACKEND->obj_clicert = NULL;
if(connssl->handle) { if(BACKEND->handle) {
if(client_cert) if(client_cert)
/* A server might require different authentication based on the /* A server might require different authentication based on the
* particular path being requested by the client. To support this * particular path being requested by the client. To support this
* scenario, we must ensure that a connection will never reuse the * scenario, we must ensure that a connection will never reuse the
* authentication data from a previous connection. */ * authentication data from a previous connection. */
SSL_InvalidateSession(connssl->handle); SSL_InvalidateSession(BACKEND->handle);
PR_Close(connssl->handle); PR_Close(BACKEND->handle);
connssl->handle = NULL; BACKEND->handle = NULL;
} }
} }
@ -1477,16 +1480,17 @@ static void Curl_nss_close(struct connectdata *conn, int sockindex)
struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_connect_data *connssl_proxy = &conn->proxy_ssl[sockindex]; struct ssl_connect_data *connssl_proxy = &conn->proxy_ssl[sockindex];
if(connssl->handle || connssl_proxy->handle) { if(BACKEND->handle || connssl_proxy->handle) {
/* NSS closes the socket we previously handed to it, so we must mark it /* NSS closes the socket we previously handed to it, so we must mark it
as closed to avoid double close */ as closed to avoid double close */
fake_sclose(conn->sock[sockindex]); fake_sclose(conn->sock[sockindex]);
conn->sock[sockindex] = CURL_SOCKET_BAD; conn->sock[sockindex] = CURL_SOCKET_BAD;
} }
if(connssl->handle) if(BACKEND->handle)
/* nss_close(connssl) will transitively close also connssl_proxy->handle /* nss_close(connssl) will transitively close also
if both are used. Clear it to avoid a double close leading to crash. */ connssl_proxy->handle if both are used. Clear it to avoid
a double close leading to crash. */
connssl_proxy->handle = NULL; connssl_proxy->handle = NULL;
nss_close(connssl); nss_close(connssl);
@ -1731,7 +1735,7 @@ static CURLcode nss_fail_connect(struct ssl_connect_data *connssl,
} }
/* cleanup on connection failure */ /* cleanup on connection failure */
Curl_llist_destroy(&connssl->obj_list, NULL); Curl_llist_destroy(&BACKEND->obj_list, NULL);
return curlerr; return curlerr;
} }
@ -1745,7 +1749,7 @@ static CURLcode nss_set_blocking(struct ssl_connect_data *connssl,
sock_opt.option = PR_SockOpt_Nonblocking; sock_opt.option = PR_SockOpt_Nonblocking;
sock_opt.value.non_blocking = !blocking; 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 nss_fail_connect(connssl, data, CURLE_SSL_CONNECT_ERROR);
return CURLE_OK; return CURLE_OK;
@ -1769,10 +1773,10 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
SSL_LIBRARY_VERSION_TLS_1_0 /* max */ 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() */ /* 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. */ /* FIXME. NSS doesn't support multiple databases open at the same time. */
PR_Lock(nss_initlock); PR_Lock(nss_initlock);
@ -1881,7 +1885,7 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
char *nickname = dup_nickname(data, SSL_SET_OPTION(cert)); char *nickname = dup_nickname(data, SSL_SET_OPTION(cert));
if(nickname) { if(nickname) {
/* we are not going to use libnsspem.so to read the client cert */ /* we are not going to use libnsspem.so to read the client cert */
connssl->obj_clicert = NULL; BACKEND->obj_clicert = NULL;
} }
else { else {
CURLcode rv = cert_stuff(conn, sockindex, SSL_SET_OPTION(cert), CURLcode rv = cert_stuff(conn, sockindex, SSL_SET_OPTION(cert),
@ -1894,10 +1898,10 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
} }
/* store the nickname for SelectClientCert() called during handshake */ /* store the nickname for SelectClientCert() called during handshake */
connssl->client_nickname = nickname; BACKEND->client_nickname = nickname;
} }
else else
connssl->client_nickname = NULL; BACKEND->client_nickname = NULL;
if(SSL_GetClientAuthDataHook(model, SelectClientCert, if(SSL_GetClientAuthDataHook(model, SelectClientCert,
(void *)connssl) != SECSuccess) { (void *)connssl) != SECSuccess) {
@ -1938,8 +1942,8 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
} }
/* import our model socket onto the current I/O stack */ /* import our model socket onto the current I/O stack */
connssl->handle = SSL_ImportFD(model, nspr_io); BACKEND->handle = SSL_ImportFD(model, nspr_io);
if(!connssl->handle) { if(!BACKEND->handle) {
if(!second_layer) if(!second_layer)
PR_Close(nspr_io); PR_Close(nspr_io);
goto error; goto error;
@ -1950,36 +1954,36 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
/* This is the password associated with the cert that we're using */ /* This is the password associated with the cert that we're using */
if(SSL_SET_OPTION(key_passwd)) { 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 #ifdef SSL_ENABLE_OCSP_STAPLING
if(SSL_CONN_CONFIG(verifystatus)) { 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) != SECSuccess)
goto error; goto error;
} }
#endif #endif
#ifdef SSL_ENABLE_NPN #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) ? PR_TRUE : PR_FALSE) != SECSuccess)
goto error; goto error;
#endif #endif
#ifdef SSL_ENABLE_ALPN #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) ? PR_TRUE : PR_FALSE) != SECSuccess)
goto error; goto error;
#endif #endif
#if NSSVERNUM >= 0x030f04 /* 3.15.4 */ #if NSSVERNUM >= 0x030f04 /* 3.15.4 */
if(data->set.ssl.falsestart) { 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) != SECSuccess)
goto error; goto error;
if(SSL_SetCanFalseStartCallback(connssl->handle, CanFalseStartCallback, if(SSL_SetCanFalseStartCallback(BACKEND->handle, CanFalseStartCallback,
conn) != SECSuccess) conn) != SECSuccess)
goto error; goto error;
} }
@ -2003,24 +2007,24 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
memcpy(&protocols[cur], ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH); memcpy(&protocols[cur], ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH);
cur += 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; goto error;
} }
#endif #endif
/* Force handshake on next I/O */ /* Force handshake on next I/O */
if(SSL_ResetHandshake(connssl->handle, /* asServer */ PR_FALSE) if(SSL_ResetHandshake(BACKEND->handle, /* asServer */ PR_FALSE)
!= SECSuccess) != SECSuccess)
goto error; goto error;
/* propagate hostname to the TLS layer */ /* 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) conn->host.name) != SECSuccess)
goto error; goto error;
/* prevent NSS from re-using the session for a different hostname */ /* 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) conn->http_proxy.host.name : conn->host.name)
!= SECSuccess) != SECSuccess)
goto error; goto error;
@ -2057,7 +2061,7 @@ static CURLcode nss_do_connect(struct connectdata *conn, int sockindex)
/* Force the handshake now */ /* Force the handshake now */
timeout = PR_MillisecondsToInterval((PRUint32) time_left); 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) if(PR_GetError() == PR_WOULD_BLOCK_ERROR)
/* blocking direction is updated by nss_update_connecting_state() */ /* blocking direction is updated by nss_update_connecting_state() */
return CURLE_AGAIN; return CURLE_AGAIN;
@ -2068,7 +2072,7 @@ static CURLcode nss_do_connect(struct connectdata *conn, int sockindex)
goto error; goto error;
} }
result = display_conn_info(conn, connssl->handle); result = display_conn_info(conn, BACKEND->handle);
if(result) if(result)
goto error; goto error;
@ -2077,7 +2081,7 @@ static CURLcode nss_do_connect(struct connectdata *conn, int sockindex)
char *nickname = dup_nickname(data, SSL_SET_OPTION(issuercert)); char *nickname = dup_nickname(data, SSL_SET_OPTION(issuercert));
if(nickname) { if(nickname) {
/* we support only nicknames in case of issuercert for now */ /* 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); free(nickname);
} }
@ -2185,9 +2189,9 @@ static ssize_t nss_send(struct connectdata *conn, /* connection data */
/* The SelectClientCert() hook uses this for infof() and failf() but the /* The SelectClientCert() hook uses this for infof() and failf() but the
handle stored in nss_setup_connect() could have already been freed. */ handle stored in nss_setup_connect() could have already been freed. */
connssl->data = conn->data; BACKEND->data = conn->data;
rc = PR_Send(connssl->handle, mem, (int)len, 0, PR_INTERVAL_NO_WAIT); rc = PR_Send(BACKEND->handle, mem, (int)len, 0, PR_INTERVAL_NO_WAIT);
if(rc < 0) { if(rc < 0) {
PRInt32 err = PR_GetError(); PRInt32 err = PR_GetError();
if(err == PR_WOULD_BLOCK_ERROR) if(err == PR_WOULD_BLOCK_ERROR)
@ -2222,9 +2226,9 @@ static ssize_t nss_recv(struct connectdata *conn, /* connection data */
/* The SelectClientCert() hook uses this for infof() and failf() but the /* The SelectClientCert() hook uses this for infof() and failf() but the
handle stored in nss_setup_connect() could have already been freed. */ handle stored in nss_setup_connect() could have already been freed. */
connssl->data = conn->data; BACKEND->data = conn->data;
nread = PR_Recv(connssl->handle, buf, (int)buffersize, 0, nread = PR_Recv(BACKEND->handle, buf, (int)buffersize, 0,
PR_INTERVAL_NO_WAIT); PR_INTERVAL_NO_WAIT);
if(nread < 0) { if(nread < 0) {
/* failed SSL read */ /* failed SSL read */
@ -2327,7 +2331,7 @@ static void *Curl_nss_get_internals(struct ssl_connect_data *connssl,
CURLINFO info UNUSED_PARAM) CURLINFO info UNUSED_PARAM)
{ {
(void)info; (void)info;
return connssl->handle; return BACKEND->handle;
} }
const struct Curl_ssl Curl_ssl_nss = { const struct Curl_ssl Curl_ssl_nss = {

View File

@ -155,6 +155,8 @@ static unsigned long OpenSSL_version_num(void)
#define DEFAULT_CIPHER_SELECTION \ #define DEFAULT_CIPHER_SELECTION \
"ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH" "ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH"
#define BACKEND connssl
/* /*
* Number of bytes to read from the random number seed file. This must be * 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 * a finite value (because some entropy "files" like /dev/urandom have
@ -956,16 +958,16 @@ static struct curl_slist *Curl_ossl_engines_list(struct Curl_easy *data)
static void ossl_close(struct ssl_connect_data *connssl) static void ossl_close(struct ssl_connect_data *connssl)
{ {
if(connssl->handle) { if(BACKEND->handle) {
(void)SSL_shutdown(connssl->handle); (void)SSL_shutdown(BACKEND->handle);
SSL_set_connect_state(connssl->handle); SSL_set_connect_state(BACKEND->handle);
SSL_free(connssl->handle); SSL_free(BACKEND->handle);
connssl->handle = NULL; BACKEND->handle = NULL;
} }
if(connssl->ctx) { if(BACKEND->ctx) {
SSL_CTX_free(connssl->ctx); SSL_CTX_free(BACKEND->ctx);
connssl->ctx = NULL; BACKEND->ctx = NULL;
} }
} }
@ -1001,9 +1003,9 @@ static int Curl_ossl_shutdown(struct connectdata *conn, int sockindex)
we do not send one. Let's hope other servers do the same... */ we do not send one. Let's hope other servers do the same... */
if(data->set.ftp_ccc == CURLFTPSSL_CCC_ACTIVE) 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); buffsize = (int)sizeof(buf);
while(!done) { while(!done) {
int what = SOCKET_READABLE(conn->sock[sockindex], int what = SOCKET_READABLE(conn->sock[sockindex],
@ -1013,9 +1015,8 @@ static int Curl_ossl_shutdown(struct connectdata *conn, int sockindex)
/* Something to read, let's do it and hope that it is the close /* Something to read, let's do it and hope that it is the close
notify alert from the server */ notify alert from the server */
nread = (ssize_t)SSL_read(conn->ssl[sockindex].handle, buf, nread = (ssize_t)SSL_read(BACKEND->handle, buf, buffsize);
buffsize); err = SSL_get_error(BACKEND->handle, (int)nread);
err = SSL_get_error(conn->ssl[sockindex].handle, (int)nread);
switch(err) { switch(err) {
case SSL_ERROR_NONE: /* this is not an error */ case SSL_ERROR_NONE: /* this is not an error */
@ -1060,7 +1061,7 @@ static int Curl_ossl_shutdown(struct connectdata *conn, int sockindex)
if(data->set.verbose) { if(data->set.verbose) {
#ifdef HAVE_SSL_GET_SHUTDOWN #ifdef HAVE_SSL_GET_SHUTDOWN
switch(SSL_get_shutdown(connssl->handle)) { switch(SSL_get_shutdown(BACKEND->handle)) {
case SSL_SENT_SHUTDOWN: case SSL_SENT_SHUTDOWN:
infof(data, "SSL_get_shutdown() returned SSL_SENT_SHUTDOWN\n"); infof(data, "SSL_get_shutdown() returned SSL_SENT_SHUTDOWN\n");
break; break;
@ -1075,8 +1076,8 @@ static int Curl_ossl_shutdown(struct connectdata *conn, int sockindex)
#endif #endif
} }
SSL_free(connssl->handle); SSL_free(BACKEND->handle);
connssl->handle = NULL; BACKEND->handle = NULL;
} }
return retval; return retval;
} }
@ -1350,7 +1351,7 @@ static CURLcode verifystatus(struct connectdata *conn,
X509_STORE *st = NULL; X509_STORE *st = NULL;
STACK_OF(X509) *ch = 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) { if(!p) {
failf(data, "No OCSP response received"); failf(data, "No OCSP response received");
@ -1380,8 +1381,8 @@ static CURLcode verifystatus(struct connectdata *conn,
goto end; goto end;
} }
ch = SSL_get_peer_cert_chain(connssl->handle); ch = SSL_get_peer_cert_chain(BACKEND->handle);
st = SSL_CTX_get_cert_store(connssl->ctx); st = SSL_CTX_get_cert_store(BACKEND->ctx);
#if ((OPENSSL_VERSION_NUMBER <= 0x1000201fL) /* Fixed after 1.0.2a */ || \ #if ((OPENSSL_VERSION_NUMBER <= 0x1000201fL) /* Fixed after 1.0.2a */ || \
(defined(LIBRESSL_VERSION_NUMBER) && \ (defined(LIBRESSL_VERSION_NUMBER) && \
@ -1772,7 +1773,7 @@ set_ssl_version_min_max(long *ctx_options, struct connectdata *conn,
#ifdef TLS1_3_VERSION #ifdef TLS1_3_VERSION
{ {
struct ssl_connect_data *connssl = &conn->ssl[sockindex]; 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; *ctx_options |= SSL_OP_NO_TLSv1_2;
} }
#else #else
@ -1923,25 +1924,25 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
return CURLE_SSL_CONNECT_ERROR; return CURLE_SSL_CONNECT_ERROR;
} }
if(connssl->ctx) if(BACKEND->ctx)
SSL_CTX_free(connssl->ctx); SSL_CTX_free(BACKEND->ctx);
connssl->ctx = SSL_CTX_new(req_method); BACKEND->ctx = SSL_CTX_new(req_method);
if(!connssl->ctx) { if(!BACKEND->ctx) {
failf(data, "SSL: couldn't create a context: %s", failf(data, "SSL: couldn't create a context: %s",
ossl_strerror(ERR_peek_error(), error_buffer, sizeof(error_buffer))); ossl_strerror(ERR_peek_error(), error_buffer, sizeof(error_buffer)));
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
} }
#ifdef SSL_MODE_RELEASE_BUFFERS #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 #endif
#ifdef SSL_CTRL_SET_MSG_CALLBACK #ifdef SSL_CTRL_SET_MSG_CALLBACK
if(data->set.fdebug && data->set.verbose) { if(data->set.fdebug && data->set.verbose) {
/* the SSL trace callback is only used for verbose logging */ /* the SSL trace callback is only used for verbose logging */
SSL_CTX_set_msg_callback(connssl->ctx, ssl_tls_trace); SSL_CTX_set_msg_callback(BACKEND->ctx, ssl_tls_trace);
SSL_CTX_set_msg_callback_arg(connssl->ctx, conn); SSL_CTX_set_msg_callback_arg(BACKEND->ctx, conn);
} }
#endif #endif
@ -2058,11 +2059,11 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
return CURLE_SSL_CONNECT_ERROR; return CURLE_SSL_CONNECT_ERROR;
} }
SSL_CTX_set_options(connssl->ctx, ctx_options); SSL_CTX_set_options(BACKEND->ctx, ctx_options);
#ifdef HAS_NPN #ifdef HAS_NPN
if(conn->bits.tls_enable_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 #endif
#ifdef HAS_ALPN #ifdef HAS_ALPN
@ -2090,12 +2091,12 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
/* expects length prefixed preference ordered list of protocols in wire /* expects length prefixed preference ordered list of protocols in wire
* format * format
*/ */
SSL_CTX_set_alpn_protos(connssl->ctx, protocols, cur); SSL_CTX_set_alpn_protos(BACKEND->ctx, protocols, cur);
} }
#endif #endif
if(ssl_cert || ssl_cert_type) { 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), SSL_SET_OPTION(key_type),
SSL_SET_OPTION(key_passwd))) { SSL_SET_OPTION(key_passwd))) {
/* failf() is already done in cert_stuff() */ /* failf() is already done in cert_stuff() */
@ -2106,7 +2107,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
ciphers = SSL_CONN_CONFIG(cipher_list); ciphers = SSL_CONN_CONFIG(cipher_list);
if(!ciphers) if(!ciphers)
ciphers = (char *)DEFAULT_CIPHER_SELECTION; ciphers = (char *)DEFAULT_CIPHER_SELECTION;
if(!SSL_CTX_set_cipher_list(connssl->ctx, ciphers)) { if(!SSL_CTX_set_cipher_list(BACKEND->ctx, ciphers)) {
failf(data, "failed setting cipher list: %s", ciphers); failf(data, "failed setting cipher list: %s", ciphers);
return CURLE_SSL_CIPHER; return CURLE_SSL_CIPHER;
} }
@ -2118,18 +2119,18 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
infof(data, "Using TLS-SRP username: %s\n", ssl_username); 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"); failf(data, "Unable to set SRP user name");
return CURLE_BAD_FUNCTION_ARGUMENT; 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"); failf(data, "failed setting SRP password");
return CURLE_BAD_FUNCTION_ARGUMENT; return CURLE_BAD_FUNCTION_ARGUMENT;
} }
if(!SSL_CONN_CONFIG(cipher_list)) { if(!SSL_CONN_CONFIG(cipher_list)) {
infof(data, "Setting cipher list SRP\n"); 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"); failf(data, "failed setting SRP cipher list");
return CURLE_SSL_CIPHER; return CURLE_SSL_CIPHER;
} }
@ -2140,7 +2141,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
if(ssl_cafile || ssl_capath) { if(ssl_cafile || ssl_capath) {
/* tell SSL where to find CA certificates that are used to verify /* tell SSL where to find CA certificates that are used to verify
the servers certificate. */ 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) { if(verifypeer) {
/* Fail if we insist on successfully verifying the server. */ /* Fail if we insist on successfully verifying the server. */
failf(data, "error setting certificate verify locations:\n" failf(data, "error setting certificate verify locations:\n"
@ -2168,14 +2169,14 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
else if(verifypeer) { else if(verifypeer) {
/* verfying the peer without any CA certificates won't /* verfying the peer without any CA certificates won't
work so use openssl's built in default as fallback */ 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 #endif
if(ssl_crlfile) { if(ssl_crlfile) {
/* tell SSL where to find CRL file that is used to check certificate /* tell SSL where to find CRL file that is used to check certificate
* revocation */ * 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()); X509_LOOKUP_file());
if(!lookup || if(!lookup ||
(!X509_load_crl_file(lookup, ssl_crlfile, X509_FILETYPE_PEM)) ) { (!X509_load_crl_file(lookup, ssl_crlfile, X509_FILETYPE_PEM)) ) {
@ -2184,7 +2185,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
} }
/* Everything is fine. */ /* Everything is fine. */
infof(data, "successfully load CRL file:\n"); 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); X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
infof(data, " CRLfile: %s\n", ssl_crlfile); infof(data, " CRLfile: %s\n", ssl_crlfile);
@ -2199,7 +2200,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 defined(X509_V_FLAG_TRUSTED_FIRST) && !defined(X509_V_FLAG_NO_ALT_CHAINS)
if(verifypeer) { 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); X509_V_FLAG_TRUSTED_FIRST);
} }
#endif #endif
@ -2208,12 +2209,12 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
* fail to connect if the verification fails, or if it should continue * fail to connect if the verification fails, or if it should continue
* anyway. In the latter case the result of the verification is checked with * anyway. In the latter case the result of the verification is checked with
* SSL_get_verify_result() below. */ * 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); verifypeer ? SSL_VERIFY_PEER : SSL_VERIFY_NONE, NULL);
/* give application a chance to interfere with SSL set up. */ /* give application a chance to interfere with SSL set up. */
if(data->set.ssl.fsslctx) { 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); data->set.ssl.fsslctxp);
if(result) { if(result) {
failf(data, "error signaled by ssl ctx callback"); failf(data, "error signaled by ssl ctx callback");
@ -2222,10 +2223,10 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
} }
/* Lets make an SSL structure */ /* Lets make an SSL structure */
if(connssl->handle) if(BACKEND->handle)
SSL_free(connssl->handle); SSL_free(BACKEND->handle);
connssl->handle = SSL_new(connssl->ctx); BACKEND->handle = SSL_new(BACKEND->ctx);
if(!connssl->handle) { if(!BACKEND->handle) {
failf(data, "SSL: couldn't create a context (handle)!"); failf(data, "SSL: couldn't create a context (handle)!");
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
} }
@ -2233,19 +2234,19 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \ #if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \
!defined(OPENSSL_NO_OCSP) !defined(OPENSSL_NO_OCSP)
if(SSL_CONN_CONFIG(verifystatus)) 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 #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 #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
if((0 == Curl_inet_pton(AF_INET, hostname, &addr)) && if((0 == Curl_inet_pton(AF_INET, hostname, &addr)) &&
#ifdef ENABLE_IPV6 #ifdef ENABLE_IPV6
(0 == Curl_inet_pton(AF_INET6, hostname, &addr)) && (0 == Curl_inet_pton(AF_INET6, hostname, &addr)) &&
#endif #endif
sni && 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) " infof(data, "WARNING: failed to configure server name indication (SNI) "
"TLS extension\n"); "TLS extension\n");
#endif #endif
@ -2257,7 +2258,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
Curl_ssl_sessionid_lock(conn); Curl_ssl_sessionid_lock(conn);
if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL, sockindex)) { if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL, sockindex)) {
/* we got a session id, use it! */ /* 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); Curl_ssl_sessionid_unlock(conn);
failf(data, "SSL: SSL_set_session failed: %s", failf(data, "SSL: SSL_set_session failed: %s",
ossl_strerror(ERR_get_error(), error_buffer, ossl_strerror(ERR_get_error(), error_buffer,
@ -2272,13 +2273,14 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
if(conn->proxy_ssl[sockindex].use) { if(conn->proxy_ssl[sockindex].use) {
BIO *const bio = BIO_new(BIO_f_ssl()); BIO *const bio = BIO_new(BIO_f_ssl());
SSL *handle = conn->proxy_ssl[sockindex].handle;
DEBUGASSERT(ssl_connection_complete == conn->proxy_ssl[sockindex].state); DEBUGASSERT(ssl_connection_complete == conn->proxy_ssl[sockindex].state);
DEBUGASSERT(conn->proxy_ssl[sockindex].handle != NULL); DEBUGASSERT(BACKEND->handle != NULL);
DEBUGASSERT(bio != NULL); DEBUGASSERT(bio != NULL);
BIO_set_ssl(bio, conn->proxy_ssl[sockindex].handle, FALSE); BIO_set_ssl(bio, handle, FALSE);
SSL_set_bio(connssl->handle, bio, bio); SSL_set_bio(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 */ /* pass the raw socket into the SSL layers */
failf(data, "SSL: SSL_set_fd failed: %s", failf(data, "SSL: SSL_set_fd failed: %s",
ossl_strerror(ERR_get_error(), error_buffer, sizeof(error_buffer))); ossl_strerror(ERR_get_error(), error_buffer, sizeof(error_buffer)));
@ -2303,13 +2305,13 @@ static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex)
ERR_clear_error(); ERR_clear_error();
err = SSL_connect(connssl->handle); err = SSL_connect(BACKEND->handle);
/* 1 is fine /* 1 is fine
0 is "not successful but was shut down controlled" 0 is "not successful but was shut down controlled"
<0 is "handshake was not successful, because a fatal error occurred" */ <0 is "handshake was not successful, because a fatal error occurred" */
if(1 != err) { 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) { if(SSL_ERROR_WANT_READ == detail) {
connssl->connecting_state = ssl_connect_2_reading; connssl->connecting_state = ssl_connect_2_reading;
@ -2343,7 +2345,7 @@ static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex)
(reason == SSL_R_CERTIFICATE_VERIFY_FAILED)) { (reason == SSL_R_CERTIFICATE_VERIFY_FAILED)) {
result = CURLE_SSL_CACERT; result = CURLE_SSL_CACERT;
lerr = SSL_get_verify_result(connssl->handle); lerr = SSL_get_verify_result(BACKEND->handle);
if(lerr != X509_V_OK) { if(lerr != X509_V_OK) {
*certverifyresult = lerr; *certverifyresult = lerr;
snprintf(error_buffer, sizeof(error_buffer), snprintf(error_buffer, sizeof(error_buffer),
@ -2387,8 +2389,8 @@ static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex)
/* Informational message */ /* Informational message */
infof(data, "SSL connection using %s / %s\n", infof(data, "SSL connection using %s / %s\n",
get_ssl_version_txt(connssl->handle), get_ssl_version_txt(BACKEND->handle),
SSL_get_cipher(connssl->handle)); SSL_get_cipher(BACKEND->handle));
#ifdef HAS_ALPN #ifdef HAS_ALPN
/* Sets data and len to negotiated protocol, len is 0 if no protocol was /* Sets data and len to negotiated protocol, len is 0 if no protocol was
@ -2397,7 +2399,7 @@ static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex)
if(conn->bits.tls_enable_alpn) { if(conn->bits.tls_enable_alpn) {
const unsigned char *neg_protocol; const unsigned char *neg_protocol;
unsigned int len; unsigned int len;
SSL_get0_alpn_selected(connssl->handle, &neg_protocol, &len); SSL_get0_alpn_selected(BACKEND->handle, &neg_protocol, &len);
if(len != 0) { if(len != 0) {
infof(data, "ALPN, server accepted to use %.*s\n", len, neg_protocol); infof(data, "ALPN, server accepted to use %.*s\n", len, neg_protocol);
@ -2543,7 +2545,7 @@ static CURLcode get_cert_chain(struct connectdata *conn,
int numcerts; int numcerts;
BIO *mem; BIO *mem;
sk = SSL_get_peer_cert_chain(connssl->handle); sk = SSL_get_peer_cert_chain(BACKEND->handle);
if(!sk) { if(!sk) {
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
} }
@ -2833,8 +2835,8 @@ static CURLcode servercert(struct connectdata *conn,
/* we've been asked to gather certificate info! */ /* we've been asked to gather certificate info! */
(void)get_cert_chain(conn, connssl); (void)get_cert_chain(conn, connssl);
connssl->server_cert = SSL_get_peer_certificate(connssl->handle); BACKEND->server_cert = SSL_get_peer_certificate(BACKEND->handle);
if(!connssl->server_cert) { if(!BACKEND->server_cert) {
BIO_free(mem); BIO_free(mem);
if(!strict) if(!strict)
return CURLE_OK; return CURLE_OK;
@ -2845,16 +2847,16 @@ static CURLcode servercert(struct connectdata *conn,
infof(data, "%s certificate:\n", SSL_IS_PROXY() ? "Proxy" : "Server"); 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)); buffer, sizeof(buffer));
infof(data, " subject: %s\n", rc?"[NONE]":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); len = BIO_get_mem_data(mem, (char **) &ptr);
infof(data, " start date: %.*s\n", len, ptr); infof(data, " start date: %.*s\n", len, ptr);
rc = BIO_reset(mem); 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); len = BIO_get_mem_data(mem, (char **) &ptr);
infof(data, " expire date: %.*s\n", len, ptr); infof(data, " expire date: %.*s\n", len, ptr);
rc = BIO_reset(mem); rc = BIO_reset(mem);
@ -2862,15 +2864,15 @@ static CURLcode servercert(struct connectdata *conn,
BIO_free(mem); BIO_free(mem);
if(SSL_CONN_CONFIG(verifyhost)) { if(SSL_CONN_CONFIG(verifyhost)) {
result = verifyhost(conn, connssl->server_cert); result = verifyhost(conn, BACKEND->server_cert);
if(result) { if(result) {
X509_free(connssl->server_cert); X509_free(BACKEND->server_cert);
connssl->server_cert = NULL; BACKEND->server_cert = NULL;
return result; 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)); buffer, sizeof(buffer));
if(rc) { if(rc) {
if(strict) if(strict)
@ -2890,8 +2892,8 @@ static CURLcode servercert(struct connectdata *conn,
if(strict) if(strict)
failf(data, "SSL: Unable to open issuer cert (%s)", failf(data, "SSL: Unable to open issuer cert (%s)",
SSL_SET_OPTION(issuercert)); SSL_SET_OPTION(issuercert));
X509_free(connssl->server_cert); X509_free(BACKEND->server_cert);
connssl->server_cert = NULL; BACKEND->server_cert = NULL;
return CURLE_SSL_ISSUER_ERROR; return CURLE_SSL_ISSUER_ERROR;
} }
@ -2900,7 +2902,7 @@ static CURLcode servercert(struct connectdata *conn,
if(strict) if(strict)
failf(data, "SSL: Unable to read issuer cert (%s)", failf(data, "SSL: Unable to read issuer cert (%s)",
SSL_SET_OPTION(issuercert)); SSL_SET_OPTION(issuercert));
X509_free(connssl->server_cert); X509_free(BACKEND->server_cert);
X509_free(issuer); X509_free(issuer);
fclose(fp); fclose(fp);
return CURLE_SSL_ISSUER_ERROR; return CURLE_SSL_ISSUER_ERROR;
@ -2908,13 +2910,13 @@ static CURLcode servercert(struct connectdata *conn,
fclose(fp); 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) if(strict)
failf(data, "SSL: Certificate issuer check failed (%s)", failf(data, "SSL: Certificate issuer check failed (%s)",
SSL_SET_OPTION(issuercert)); SSL_SET_OPTION(issuercert));
X509_free(connssl->server_cert); X509_free(BACKEND->server_cert);
X509_free(issuer); X509_free(issuer);
connssl->server_cert = NULL; BACKEND->server_cert = NULL;
return CURLE_SSL_ISSUER_ERROR; return CURLE_SSL_ISSUER_ERROR;
} }
@ -2923,7 +2925,7 @@ static CURLcode servercert(struct connectdata *conn,
X509_free(issuer); 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(*certverifyresult != X509_V_OK) {
if(SSL_CONN_CONFIG(verifypeer)) { if(SSL_CONN_CONFIG(verifypeer)) {
@ -2948,8 +2950,8 @@ static CURLcode servercert(struct connectdata *conn,
if(SSL_CONN_CONFIG(verifystatus)) { if(SSL_CONN_CONFIG(verifystatus)) {
result = verifystatus(conn, connssl); result = verifystatus(conn, connssl);
if(result) { if(result) {
X509_free(connssl->server_cert); X509_free(BACKEND->server_cert);
connssl->server_cert = NULL; BACKEND->server_cert = NULL;
return result; return result;
} }
} }
@ -2962,13 +2964,13 @@ static CURLcode servercert(struct connectdata *conn,
ptr = SSL_IS_PROXY() ? data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] : ptr = SSL_IS_PROXY() ? data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]; data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
if(!result && ptr) { 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) if(result)
failf(data, "SSL: public key does not match pinned public key!"); failf(data, "SSL: public key does not match pinned public key!");
} }
X509_free(connssl->server_cert); X509_free(BACKEND->server_cert);
connssl->server_cert = NULL; BACKEND->server_cert = NULL;
connssl->connecting_state = ssl_connect_done; connssl->connecting_state = ssl_connect_done;
return result; return result;
@ -2987,7 +2989,7 @@ static CURLcode ossl_connect_step3(struct connectdata *conn, int sockindex)
SSL_SESSION *our_ssl_sessionid; SSL_SESSION *our_ssl_sessionid;
void *old_ssl_sessionid = NULL; 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 /* SSL_get1_session() will increment the reference count and the session
will stay in memory until explicitly freed with SSL_SESSION_free(3), will stay in memory until explicitly freed with SSL_SESSION_free(3),
@ -3176,11 +3178,11 @@ static CURLcode Curl_ossl_connect(struct connectdata *conn, int sockindex)
static bool Curl_ossl_data_pending(const struct connectdata *conn, static bool Curl_ossl_data_pending(const struct connectdata *conn,
int connindex) int connindex)
{ {
if(conn->ssl[connindex].handle) const struct ssl_connect_data *connssl = &conn->ssl[connindex];
if(BACKEND->handle)
/* SSL is in use */ /* SSL is in use */
return (0 != SSL_pending(conn->ssl[connindex].handle) || return (0 != SSL_pending(BACKEND->handle) ||
(conn->proxy_ssl[connindex].handle && (BACKEND->handle && 0 != SSL_pending(BACKEND->handle))) ?
0 != SSL_pending(conn->proxy_ssl[connindex].handle))) ?
TRUE : FALSE; TRUE : FALSE;
return FALSE; return FALSE;
} }
@ -3200,14 +3202,15 @@ static ssize_t ossl_send(struct connectdata *conn,
unsigned long sslerror; unsigned long sslerror;
int memlen; int memlen;
int rc; int rc;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
ERR_clear_error(); ERR_clear_error();
memlen = (len > (size_t)INT_MAX) ? INT_MAX : (int)len; 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) { if(rc <= 0) {
err = SSL_get_error(conn->ssl[sockindex].handle, rc); err = SSL_get_error(BACKEND->handle, rc);
switch(err) { switch(err) {
case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_READ:
@ -3261,14 +3264,15 @@ static ssize_t ossl_recv(struct connectdata *conn, /* connection data */
unsigned long sslerror; unsigned long sslerror;
ssize_t nread; ssize_t nread;
int buffsize; int buffsize;
struct ssl_connect_data *connssl = &conn->ssl[num];
ERR_clear_error(); ERR_clear_error();
buffsize = (buffersize > (size_t)INT_MAX) ? INT_MAX : (int)buffersize; 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) { if(nread <= 0) {
/* failed SSL_read */ /* 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) { switch(err) {
case SSL_ERROR_NONE: /* this is not an error */ case SSL_ERROR_NONE: /* this is not an error */
@ -3399,7 +3403,7 @@ static void *Curl_ossl_get_internals(struct ssl_connect_data *connssl,
{ {
/* Legacy: CURLINFO_TLS_SESSION must return an SSL_CTX pointer. */ /* Legacy: CURLINFO_TLS_SESSION must return an SSL_CTX pointer. */
return info == CURLINFO_TLS_SESSION ? return info == CURLINFO_TLS_SESSION ?
(void *)connssl->ctx : (void *)connssl->handle; (void *)BACKEND->ctx : (void *)BACKEND->handle;
} }
const struct Curl_ssl Curl_ssl_openssl = { const struct Curl_ssl Curl_ssl_openssl = {

View File

@ -70,6 +70,8 @@
#define PUB_DER_MAX_BYTES (RSA_PUB_DER_MAX_BYTES > ECP_PUB_DER_MAX_BYTES ? \ #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) RSA_PUB_DER_MAX_BYTES : ECP_PUB_DER_MAX_BYTES)
#define BACKEND connssl
/* apply threading? */ /* apply threading? */
#if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32) #if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32)
#define THREADING_SUPPORT #define THREADING_SUPPORT
@ -197,8 +199,8 @@ set_ssl_version_min_max(struct connectdata *conn, int sockindex)
return result; return result;
} }
ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3, ssl_min_ver); ssl_set_min_version(&BACKEND->ssl, SSL_MAJOR_VERSION_3, ssl_min_ver);
ssl_set_max_version(&connssl->ssl, SSL_MAJOR_VERSION_3, ssl_max_ver); ssl_set_max_version(&BACKEND->ssl, SSL_MAJOR_VERSION_3, ssl_max_ver);
return result; return result;
} }
@ -226,16 +228,16 @@ polarssl_connect_step1(struct connectdata *conn,
#ifdef THREADING_SUPPORT #ifdef THREADING_SUPPORT
entropy_init_mutex(&entropy); 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) { NULL, 0)) != 0) {
error_strerror(ret, errorbuf, sizeof(errorbuf)); error_strerror(ret, errorbuf, sizeof(errorbuf));
failf(data, "Failed - PolarSSL: ctr_drbg_init returned (-0x%04X) %s\n", failf(data, "Failed - PolarSSL: ctr_drbg_init returned (-0x%04X) %s\n",
-ret, errorbuf); -ret, errorbuf);
} }
#else #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) { NULL, 0)) != 0) {
error_strerror(ret, errorbuf, sizeof(errorbuf)); error_strerror(ret, errorbuf, sizeof(errorbuf));
failf(data, "Failed - PolarSSL: ctr_drbg_init returned (-0x%04X) %s\n", failf(data, "Failed - PolarSSL: ctr_drbg_init returned (-0x%04X) %s\n",
@ -244,10 +246,10 @@ polarssl_connect_step1(struct connectdata *conn,
#endif /* THREADING_SUPPORT */ #endif /* THREADING_SUPPORT */
/* Load the trusted CA */ /* Load the trusted CA */
memset(&connssl->cacert, 0, sizeof(x509_crt)); memset(&BACKEND->cacert, 0, sizeof(x509_crt));
if(SSL_CONN_CONFIG(CAfile)) { if(SSL_CONN_CONFIG(CAfile)) {
ret = x509_crt_parse_file(&connssl->cacert, ret = x509_crt_parse_file(&BACKEND->cacert,
SSL_CONN_CONFIG(CAfile)); SSL_CONN_CONFIG(CAfile));
if(ret<0) { if(ret<0) {
@ -261,7 +263,7 @@ polarssl_connect_step1(struct connectdata *conn,
} }
if(capath) { if(capath) {
ret = x509_crt_parse_path(&connssl->cacert, capath); ret = x509_crt_parse_path(&BACKEND->cacert, capath);
if(ret<0) { if(ret<0) {
error_strerror(ret, errorbuf, sizeof(errorbuf)); error_strerror(ret, errorbuf, sizeof(errorbuf));
@ -274,10 +276,10 @@ polarssl_connect_step1(struct connectdata *conn,
} }
/* Load the client certificate */ /* Load the client certificate */
memset(&connssl->clicert, 0, sizeof(x509_crt)); memset(&BACKEND->clicert, 0, sizeof(x509_crt));
if(SSL_SET_OPTION(cert)) { if(SSL_SET_OPTION(cert)) {
ret = x509_crt_parse_file(&connssl->clicert, ret = x509_crt_parse_file(&BACKEND->clicert,
SSL_SET_OPTION(cert)); SSL_SET_OPTION(cert));
if(ret) { if(ret) {
@ -298,9 +300,9 @@ polarssl_connect_step1(struct connectdata *conn,
if(ret == 0 && !pk_can_do(&pk, POLARSSL_PK_RSA)) if(ret == 0 && !pk_can_do(&pk, POLARSSL_PK_RSA))
ret = POLARSSL_ERR_PK_TYPE_MISMATCH; ret = POLARSSL_ERR_PK_TYPE_MISMATCH;
if(ret == 0) if(ret == 0)
rsa_copy(&connssl->rsa, pk_rsa(pk)); rsa_copy(&BACKEND->rsa, pk_rsa(pk));
else else
rsa_free(&connssl->rsa); rsa_free(&BACKEND->rsa);
pk_free(&pk); pk_free(&pk);
if(ret) { if(ret) {
@ -313,10 +315,10 @@ polarssl_connect_step1(struct connectdata *conn,
} }
/* Load the CRL */ /* Load the CRL */
memset(&connssl->crl, 0, sizeof(x509_crl)); memset(&BACKEND->crl, 0, sizeof(x509_crl));
if(SSL_SET_OPTION(CRLfile)) { if(SSL_SET_OPTION(CRLfile)) {
ret = x509_crl_parse_file(&connssl->crl, ret = x509_crl_parse_file(&BACKEND->crl,
SSL_SET_OPTION(CRLfile)); SSL_SET_OPTION(CRLfile));
if(ret) { if(ret) {
@ -330,7 +332,7 @@ polarssl_connect_step1(struct connectdata *conn,
infof(data, "PolarSSL: Connecting to %s:%d\n", hostname, port); 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"); failf(data, "PolarSSL: ssl_init failed");
return CURLE_SSL_CONNECT_ERROR; return CURLE_SSL_CONNECT_ERROR;
} }
@ -338,13 +340,13 @@ polarssl_connect_step1(struct connectdata *conn,
switch(SSL_CONN_CONFIG(version)) { switch(SSL_CONN_CONFIG(version)) {
case CURL_SSLVERSION_DEFAULT: case CURL_SSLVERSION_DEFAULT:
case CURL_SSLVERSION_TLSv1: 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); SSL_MINOR_VERSION_1);
break; break;
case CURL_SSLVERSION_SSLv3: 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_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); SSL_MINOR_VERSION_0);
infof(data, "PolarSSL: Forced min. SSL Version to be SSLv3\n"); infof(data, "PolarSSL: Forced min. SSL Version to be SSLv3\n");
break; break;
@ -363,16 +365,16 @@ polarssl_connect_step1(struct connectdata *conn,
return CURLE_SSL_CONNECT_ERROR; return CURLE_SSL_CONNECT_ERROR;
} }
ssl_set_endpoint(&connssl->ssl, SSL_IS_CLIENT); ssl_set_endpoint(&BACKEND->ssl, SSL_IS_CLIENT);
ssl_set_authmode(&connssl->ssl, SSL_VERIFY_OPTIONAL); ssl_set_authmode(&BACKEND->ssl, SSL_VERIFY_OPTIONAL);
ssl_set_rng(&connssl->ssl, ctr_drbg_random, ssl_set_rng(&BACKEND->ssl, ctr_drbg_random,
&connssl->ctr_drbg); &BACKEND->ctr_drbg);
ssl_set_bio(&connssl->ssl, ssl_set_bio(&BACKEND->ssl,
net_recv, &conn->sock[sockindex], net_recv, &conn->sock[sockindex],
net_send, &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! */ /* Check if there's a cached ID we can/should use here! */
if(SSL_SET_OPTION(primary.sessionid)) { if(SSL_SET_OPTION(primary.sessionid)) {
@ -380,7 +382,7 @@ polarssl_connect_step1(struct connectdata *conn,
Curl_ssl_sessionid_lock(conn); Curl_ssl_sessionid_lock(conn);
if(!Curl_ssl_getsessionid(conn, &old_session, NULL, sockindex)) { 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) { if(ret) {
Curl_ssl_sessionid_unlock(conn); Curl_ssl_sessionid_unlock(conn);
failf(data, "ssl_set_session returned -0x%x", -ret); failf(data, "ssl_set_session returned -0x%x", -ret);
@ -391,15 +393,15 @@ polarssl_connect_step1(struct connectdata *conn,
Curl_ssl_sessionid_unlock(conn); Curl_ssl_sessionid_unlock(conn);
} }
ssl_set_ca_chain(&connssl->ssl, ssl_set_ca_chain(&BACKEND->ssl,
&connssl->cacert, &BACKEND->cacert,
&connssl->crl, &BACKEND->crl,
hostname); hostname);
ssl_set_own_cert_rsa(&connssl->ssl, ssl_set_own_cert_rsa(&BACKEND->ssl,
&connssl->clicert, &connssl->rsa); &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 /* 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 to set in the SNI extension. So even if curl connects to a host
specified as an IP address, this function must be used. */ specified as an IP address, this function must be used. */
@ -424,12 +426,12 @@ polarssl_connect_step1(struct connectdata *conn,
protocols[cur] = NULL; protocols[cur] = NULL;
ssl_set_alpn_protocols(&connssl->ssl, protocols); ssl_set_alpn_protocols(&BACKEND->ssl, protocols);
} }
#endif #endif
#ifdef POLARSSL_DEBUG #ifdef POLARSSL_DEBUG
ssl_set_dbg(&connssl->ssl, polarssl_debug, data); ssl_set_dbg(&BACKEND->ssl, polarssl_debug, data);
#endif #endif
connssl->connecting_state = ssl_connect_2; connssl->connecting_state = ssl_connect_2;
@ -443,7 +445,7 @@ polarssl_connect_step2(struct connectdata *conn,
{ {
int ret; int ret;
struct Curl_easy *data = conn->data; struct Curl_easy *data = conn->data;
struct ssl_connect_data* connssl = &conn->ssl[sockindex]; struct ssl_connect_data* connssl = &BACKEND->ssl[sockindex];
char buffer[1024]; char buffer[1024];
const char * const pinnedpubkey = SSL_IS_PROXY() ? const char * const pinnedpubkey = SSL_IS_PROXY() ?
data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] : data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
@ -456,7 +458,7 @@ polarssl_connect_step2(struct connectdata *conn,
conn->recv[sockindex] = polarssl_recv; conn->recv[sockindex] = polarssl_recv;
conn->send[sockindex] = polarssl_send; conn->send[sockindex] = polarssl_send;
ret = ssl_handshake(&connssl->ssl); ret = ssl_handshake(&BACKEND->ssl);
switch(ret) { switch(ret) {
case 0: case 0:
@ -478,9 +480,9 @@ polarssl_connect_step2(struct connectdata *conn,
} }
infof(data, "PolarSSL: Handshake complete, cipher is %s\n", 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 && SSL_CONN_CONFIG(verifypeer)) {
if(ret & BADCERT_EXPIRED) if(ret & BADCERT_EXPIRED)
@ -500,12 +502,12 @@ polarssl_connect_step2(struct connectdata *conn,
return CURLE_PEER_FAILED_VERIFICATION; 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 */ /* If the session was resumed, there will be no peer certs */
memset(buffer, 0, sizeof(buffer)); memset(buffer, 0, sizeof(buffer));
if(x509_crt_info(buffer, sizeof(buffer), (char *)"* ", 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); infof(data, "Dumping cert info:\n%s\n", buffer);
} }
@ -517,7 +519,7 @@ polarssl_connect_step2(struct connectdata *conn,
unsigned char pubkey[PUB_DER_MAX_BYTES]; unsigned char pubkey[PUB_DER_MAX_BYTES];
const x509_crt *peercert; 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) { if(!peercert || !peercert->raw.p || !peercert->raw.len) {
failf(data, "Failed due to missing peer certificate"); failf(data, "Failed due to missing peer certificate");
@ -566,7 +568,7 @@ polarssl_connect_step2(struct connectdata *conn,
#ifdef HAS_ALPN #ifdef HAS_ALPN
if(conn->bits.tls_enable_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) { if(next_protocol != NULL) {
infof(data, "ALPN, server accepted to use %s\n", next_protocol); infof(data, "ALPN, server accepted to use %s\n", next_protocol);
@ -614,7 +616,7 @@ polarssl_connect_step3(struct connectdata *conn,
memset(our_ssl_sessionid, 0, sizeof(ssl_session)); 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) { if(ret) {
failf(data, "ssl_get_session returned -0x%x", -ret); failf(data, "ssl_get_session returned -0x%x", -ret);
return CURLE_SSL_CONNECT_ERROR; return CURLE_SSL_CONNECT_ERROR;
@ -645,9 +647,10 @@ static ssize_t polarssl_send(struct connectdata *conn,
size_t len, size_t len,
CURLcode *curlcode) CURLcode *curlcode)
{ {
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
int ret = -1; int ret = -1;
ret = ssl_write(&conn->ssl[sockindex].ssl, ret = ssl_write(&BACKEND->ssl,
(unsigned char *)mem, len); (unsigned char *)mem, len);
if(ret < 0) { if(ret < 0) {
@ -661,11 +664,12 @@ static ssize_t polarssl_send(struct connectdata *conn,
static 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); struct ssl_connect_data *connssl = &conn->sock[sockindex];
x509_crt_free(&conn->ssl[sockindex].clicert); rsa_free(&BACKEND->rsa);
x509_crt_free(&conn->ssl[sockindex].cacert); x509_crt_free(&BACKEND->clicert);
x509_crl_free(&conn->ssl[sockindex].crl); x509_crt_free(&BACKEND->cacert);
ssl_free(&conn->ssl[sockindex].ssl); x509_crl_free(&BACKEND->crl);
ssl_free(&BACKEND->ssl);
} }
static ssize_t polarssl_recv(struct connectdata *conn, static ssize_t polarssl_recv(struct connectdata *conn,
@ -674,11 +678,12 @@ static ssize_t polarssl_recv(struct connectdata *conn,
size_t buffersize, size_t buffersize,
CURLcode *curlcode) CURLcode *curlcode)
{ {
struct ssl_connect_data *connssl = &conn->ssl[num];
int ret = -1; int ret = -1;
ssize_t len = -1; ssize_t len = -1;
memset(buf, 0, buffersize); 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 <= 0) {
if(ret == POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY) if(ret == POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY)
@ -863,7 +868,8 @@ static void Curl_polarssl_cleanup(void)
static bool Curl_polarssl_data_pending(const struct connectdata *conn, static bool Curl_polarssl_data_pending(const struct connectdata *conn,
int sockindex) int sockindex)
{ {
return ssl_get_bytes_avail(&conn->ssl[sockindex].ssl) != 0; 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, static void Curl_polarssl_sha256sum(const unsigned char *input,
@ -878,7 +884,7 @@ static void *Curl_polarssl_get_internals(struct ssl_connect_data *connssl,
CURLINFO info UNUSED_PARAM) CURLINFO info UNUSED_PARAM)
{ {
(void)info; (void)info;
return &connssl->ssl; return &BACKEND->ssl;
} }
const struct Curl_ssl Curl_ssl_polarssl = { const struct Curl_ssl Curl_ssl_polarssl = {

View File

@ -127,6 +127,8 @@
* #define failf(x, y, ...) printf(y, __VA_ARGS__) * #define failf(x, y, ...) printf(y, __VA_ARGS__)
*/ */
#define BACKEND connssl
static Curl_recv schannel_recv; static Curl_recv schannel_recv;
static Curl_send schannel_send; static Curl_send schannel_send;
@ -224,33 +226,33 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
#ifdef HAS_ALPN #ifdef HAS_ALPN
/* ALPN is only supported on Windows 8.1 / Server 2012 R2 and above. /* 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. */ 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"), !GetProcAddress(GetModuleHandleA("ntdll"),
"wine_get_version") && "wine_get_version") &&
Curl_verify_windows_version(6, 3, PLATFORM_WINNT, Curl_verify_windows_version(6, 3, PLATFORM_WINNT,
VERSION_GREATER_THAN_EQUAL); VERSION_GREATER_THAN_EQUAL);
#else #else
connssl->use_alpn = false; BACKEND->use_alpn = false;
#endif #endif
connssl->cred = NULL; BACKEND->cred = NULL;
/* check for an existing re-usable credential handle */ /* check for an existing re-usable credential handle */
if(SSL_SET_OPTION(primary.sessionid)) { if(SSL_SET_OPTION(primary.sessionid)) {
Curl_ssl_sessionid_lock(conn); Curl_ssl_sessionid_lock(conn);
if(!Curl_ssl_getsessionid(conn, (void **)&old_cred, NULL, sockindex)) { 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"); infof(data, "schannel: re-using existing credential handle\n");
/* increment the reference counter of the credential/session handle */ /* increment the reference counter of the credential/session handle */
connssl->cred->refcount++; BACKEND->cred->refcount++;
infof(data, "schannel: incremented credential handle refcount = %d\n", infof(data, "schannel: incremented credential handle refcount = %d\n",
connssl->cred->refcount); BACKEND->cred->refcount);
} }
Curl_ssl_sessionid_unlock(conn); Curl_ssl_sessionid_unlock(conn);
} }
if(!connssl->cred) { if(!BACKEND->cred) {
/* setup Schannel API options */ /* setup Schannel API options */
memset(&schannel_cred, 0, sizeof(schannel_cred)); memset(&schannel_cred, 0, sizeof(schannel_cred));
schannel_cred.dwVersion = SCHANNEL_CRED_VERSION; schannel_cred.dwVersion = SCHANNEL_CRED_VERSION;
@ -320,14 +322,14 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
} }
/* allocate memory for the re-usable credential handle */ /* 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)); malloc(sizeof(struct curl_schannel_cred));
if(!connssl->cred) { if(!BACKEND->cred) {
failf(data, "schannel: unable to allocate memory"); failf(data, "schannel: unable to allocate memory");
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
} }
memset(connssl->cred, 0, sizeof(struct curl_schannel_cred)); memset(BACKEND->cred, 0, sizeof(struct curl_schannel_cred));
connssl->cred->refcount = 1; BACKEND->cred->refcount = 1;
/* https://msdn.microsoft.com/en-us/library/windows/desktop/aa374716.aspx /* https://msdn.microsoft.com/en-us/library/windows/desktop/aa374716.aspx
*/ */
@ -335,8 +337,8 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
s_pSecFn->AcquireCredentialsHandle(NULL, (TCHAR *)UNISP_NAME, s_pSecFn->AcquireCredentialsHandle(NULL, (TCHAR *)UNISP_NAME,
SECPKG_CRED_OUTBOUND, NULL, SECPKG_CRED_OUTBOUND, NULL,
&schannel_cred, NULL, NULL, &schannel_cred, NULL, NULL,
&connssl->cred->cred_handle, &BACKEND->cred->cred_handle,
&connssl->cred->time_stamp); &BACKEND->cred->time_stamp);
if(sspi_status != SEC_E_OK) { if(sspi_status != SEC_E_OK) {
if(sspi_status == SEC_E_WRONG_PRINCIPAL) if(sspi_status == SEC_E_WRONG_PRINCIPAL)
@ -345,7 +347,7 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
else else
failf(data, "schannel: AcquireCredentialsHandle failed: %s", failf(data, "schannel: AcquireCredentialsHandle failed: %s",
Curl_sspi_strerror(conn, sspi_status)); Curl_sspi_strerror(conn, sspi_status));
Curl_safefree(connssl->cred); Curl_safefree(BACKEND->cred);
return CURLE_SSL_CONNECT_ERROR; return CURLE_SSL_CONNECT_ERROR;
} }
} }
@ -360,7 +362,7 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
} }
#ifdef HAS_ALPN #ifdef HAS_ALPN
if(connssl->use_alpn) { if(BACKEND->use_alpn) {
int cur = 0; int cur = 0;
int list_start_index = 0; int list_start_index = 0;
unsigned int *extension_len = NULL; unsigned int *extension_len = NULL;
@ -418,18 +420,18 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
InitSecBufferDesc(&outbuf_desc, &outbuf, 1); InitSecBufferDesc(&outbuf_desc, &outbuf, 1);
/* setup request flags */ /* 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_CONFIDENTIALITY | ISC_REQ_ALLOCATE_MEMORY |
ISC_REQ_STREAM; ISC_REQ_STREAM;
/* allocate memory for the security context handle */ /* 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)); malloc(sizeof(struct curl_schannel_ctxt));
if(!connssl->ctxt) { if(!BACKEND->ctxt) {
failf(data, "schannel: unable to allocate memory"); failf(data, "schannel: unable to allocate memory");
return CURLE_OUT_OF_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); host_name = Curl_convert_UTF8_to_tchar(hostname);
if(!host_name) if(!host_name)
@ -443,10 +445,10 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
us problems with inbuf regardless. https://github.com/curl/curl/issues/983 us problems with inbuf regardless. https://github.com/curl/curl/issues/983
*/ */
sspi_status = s_pSecFn->InitializeSecurityContext( sspi_status = s_pSecFn->InitializeSecurityContext(
&connssl->cred->cred_handle, NULL, host_name, connssl->req_flags, 0, 0, &BACKEND->cred->cred_handle, NULL, host_name, BACKEND->req_flags, 0, 0,
(connssl->use_alpn ? &inbuf_desc : NULL), (BACKEND->use_alpn ? &inbuf_desc : NULL),
0, &connssl->ctxt->ctxt_handle, 0, &BACKEND->ctxt->ctxt_handle,
&outbuf_desc, &connssl->ret_flags, &connssl->ctxt->time_stamp); &outbuf_desc, &BACKEND->ret_flags, &BACKEND->ctxt->time_stamp);
Curl_unicodefree(host_name); Curl_unicodefree(host_name);
@ -457,7 +459,7 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
else else
failf(data, "schannel: initial InitializeSecurityContext failed: %s", failf(data, "schannel: initial InitializeSecurityContext failed: %s",
Curl_sspi_strerror(conn, sspi_status)); Curl_sspi_strerror(conn, sspi_status));
Curl_safefree(connssl->ctxt); Curl_safefree(BACKEND->ctxt);
return CURLE_SSL_CONNECT_ERROR; return CURLE_SSL_CONNECT_ERROR;
} }
@ -477,10 +479,10 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
infof(data, "schannel: sent initial handshake data: " infof(data, "schannel: sent initial handshake data: "
"sent %zd bytes\n", written); "sent %zd bytes\n", written);
connssl->recv_unrecoverable_err = CURLE_OK; BACKEND->recv_unrecoverable_err = CURLE_OK;
connssl->recv_sspi_close_notify = false; BACKEND->recv_sspi_close_notify = false;
connssl->recv_connection_closed = false; BACKEND->recv_connection_closed = false;
connssl->encdata_is_incomplete = false; BACKEND->encdata_is_incomplete = false;
/* continue to second handshake step */ /* continue to second handshake step */
connssl->connecting_state = ssl_connect_2; connssl->connecting_state = ssl_connect_2;
@ -513,39 +515,39 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
infof(data, "schannel: SSL/TLS connection with %s port %hu (step 2/3)\n", infof(data, "schannel: SSL/TLS connection with %s port %hu (step 2/3)\n",
hostname, conn->remote_port); hostname, conn->remote_port);
if(!connssl->cred || !connssl->ctxt) if(!BACKEND->cred || !BACKEND->ctxt)
return CURLE_SSL_CONNECT_ERROR; return CURLE_SSL_CONNECT_ERROR;
/* buffer to store previously received and decrypted data */ /* buffer to store previously received and decrypted data */
if(connssl->decdata_buffer == NULL) { if(BACKEND->decdata_buffer == NULL) {
connssl->decdata_offset = 0; BACKEND->decdata_offset = 0;
connssl->decdata_length = CURL_SCHANNEL_BUFFER_INIT_SIZE; BACKEND->decdata_length = CURL_SCHANNEL_BUFFER_INIT_SIZE;
connssl->decdata_buffer = malloc(connssl->decdata_length); BACKEND->decdata_buffer = malloc(BACKEND->decdata_length);
if(connssl->decdata_buffer == NULL) { if(BACKEND->decdata_buffer == NULL) {
failf(data, "schannel: unable to allocate memory"); failf(data, "schannel: unable to allocate memory");
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
} }
} }
/* buffer to store previously received and encrypted data */ /* buffer to store previously received and encrypted data */
if(connssl->encdata_buffer == NULL) { if(BACKEND->encdata_buffer == NULL) {
connssl->encdata_is_incomplete = false; BACKEND->encdata_is_incomplete = false;
connssl->encdata_offset = 0; BACKEND->encdata_offset = 0;
connssl->encdata_length = CURL_SCHANNEL_BUFFER_INIT_SIZE; BACKEND->encdata_length = CURL_SCHANNEL_BUFFER_INIT_SIZE;
connssl->encdata_buffer = malloc(connssl->encdata_length); BACKEND->encdata_buffer = malloc(BACKEND->encdata_length);
if(connssl->encdata_buffer == NULL) { if(BACKEND->encdata_buffer == NULL) {
failf(data, "schannel: unable to allocate memory"); failf(data, "schannel: unable to allocate memory");
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
} }
} }
/* if we need a bigger buffer to read a full message, increase buffer now */ /* 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) { CURL_SCHANNEL_BUFFER_FREE_SIZE) {
/* increase internal encrypted data buffer */ /* increase internal encrypted data buffer */
reallocated_length = connssl->encdata_offset + reallocated_length = BACKEND->encdata_offset +
CURL_SCHANNEL_BUFFER_FREE_SIZE; CURL_SCHANNEL_BUFFER_FREE_SIZE;
reallocated_buffer = realloc(connssl->encdata_buffer, reallocated_buffer = realloc(BACKEND->encdata_buffer,
reallocated_length); reallocated_length);
if(reallocated_buffer == NULL) { if(reallocated_buffer == NULL) {
@ -553,8 +555,8 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
} }
else { else {
connssl->encdata_buffer = reallocated_buffer; BACKEND->encdata_buffer = reallocated_buffer;
connssl->encdata_length = reallocated_length; BACKEND->encdata_length = reallocated_length;
} }
} }
@ -562,10 +564,10 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
if(doread) { if(doread) {
/* read encrypted handshake data from socket */ /* read encrypted handshake data from socket */
result = Curl_read_plain(conn->sock[sockindex], result = Curl_read_plain(conn->sock[sockindex],
(char *) (connssl->encdata_buffer + (char *) (BACKEND->encdata_buffer +
connssl->encdata_offset), BACKEND->encdata_offset),
connssl->encdata_length - BACKEND->encdata_length -
connssl->encdata_offset, BACKEND->encdata_offset,
&nread); &nread);
if(result == CURLE_AGAIN) { if(result == CURLE_AGAIN) {
if(connssl->connecting_state != ssl_connect_2_writing) if(connssl->connecting_state != ssl_connect_2_writing)
@ -581,17 +583,17 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
} }
/* increase encrypted data buffer offset */ /* increase encrypted data buffer offset */
connssl->encdata_offset += nread; BACKEND->encdata_offset += nread;
connssl->encdata_is_incomplete = false; BACKEND->encdata_is_incomplete = false;
infof(data, "schannel: encrypted data got %zd\n", nread); infof(data, "schannel: encrypted data got %zd\n", nread);
} }
infof(data, "schannel: encrypted data buffer: offset %zu length %zu\n", 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 */ /* setup input buffers */
InitSecBuffer(&inbuf[0], SECBUFFER_TOKEN, malloc(connssl->encdata_offset), InitSecBuffer(&inbuf[0], SECBUFFER_TOKEN, malloc(BACKEND->encdata_offset),
curlx_uztoul(connssl->encdata_offset)); curlx_uztoul(BACKEND->encdata_offset));
InitSecBuffer(&inbuf[1], SECBUFFER_EMPTY, NULL, 0); InitSecBuffer(&inbuf[1], SECBUFFER_EMPTY, NULL, 0);
InitSecBufferDesc(&inbuf_desc, inbuf, 2); InitSecBufferDesc(&inbuf_desc, inbuf, 2);
@ -607,8 +609,8 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
} }
/* copy received handshake data into input buffer */ /* copy received handshake data into input buffer */
memcpy(inbuf[0].pvBuffer, connssl->encdata_buffer, memcpy(inbuf[0].pvBuffer, BACKEND->encdata_buffer,
connssl->encdata_offset); BACKEND->encdata_offset);
host_name = Curl_convert_UTF8_to_tchar(hostname); host_name = Curl_convert_UTF8_to_tchar(hostname);
if(!host_name) if(!host_name)
@ -617,9 +619,9 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
/* https://msdn.microsoft.com/en-us/library/windows/desktop/aa375924.aspx /* https://msdn.microsoft.com/en-us/library/windows/desktop/aa375924.aspx
*/ */
sspi_status = s_pSecFn->InitializeSecurityContext( 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, 0, 0, &inbuf_desc, 0, NULL, host_name, BACKEND->req_flags, 0, 0, &inbuf_desc, 0, NULL,
&outbuf_desc, &connssl->ret_flags, &connssl->ctxt->time_stamp); &outbuf_desc, &BACKEND->ret_flags, &BACKEND->ctxt->time_stamp);
Curl_unicodefree(host_name); Curl_unicodefree(host_name);
@ -628,7 +630,7 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
/* check if the handshake was incomplete */ /* check if the handshake was incomplete */
if(sspi_status == SEC_E_INCOMPLETE_MESSAGE) { if(sspi_status == SEC_E_INCOMPLETE_MESSAGE) {
connssl->encdata_is_incomplete = true; BACKEND->encdata_is_incomplete = true;
connssl->connecting_state = ssl_connect_2_reading; connssl->connecting_state = ssl_connect_2_reading;
infof(data, "schannel: received incomplete message, need more data\n"); infof(data, "schannel: received incomplete message, need more data\n");
return CURLE_OK; return CURLE_OK;
@ -638,8 +640,8 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
the handshake without one. This will allow connections to servers which the handshake without one. This will allow connections to servers which
request a client certificate but do not require it. */ request a client certificate but do not require it. */
if(sspi_status == SEC_I_INCOMPLETE_CREDENTIALS && if(sspi_status == SEC_I_INCOMPLETE_CREDENTIALS &&
!(connssl->req_flags & ISC_REQ_USE_SUPPLIED_CREDS)) { !(BACKEND->req_flags & ISC_REQ_USE_SUPPLIED_CREDS)) {
connssl->req_flags |= ISC_REQ_USE_SUPPLIED_CREDS; BACKEND->req_flags |= ISC_REQ_USE_SUPPLIED_CREDS;
connssl->connecting_state = ssl_connect_2_writing; connssl->connecting_state = ssl_connect_2_writing;
infof(data, "schannel: a client certificate has been requested\n"); infof(data, "schannel: a client certificate has been requested\n");
return CURLE_OK; return CURLE_OK;
@ -697,11 +699,11 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
*/ */
/* check if the remaining data is less than the total amount /* check if the remaining data is less than the total amount
and therefore begins after the already processed data */ and therefore begins after the already processed data */
if(connssl->encdata_offset > inbuf[1].cbBuffer) { if(BACKEND->encdata_offset > inbuf[1].cbBuffer) {
memmove(connssl->encdata_buffer, memmove(BACKEND->encdata_buffer,
(connssl->encdata_buffer + connssl->encdata_offset) - (BACKEND->encdata_buffer + BACKEND->encdata_offset) -
inbuf[1].cbBuffer, inbuf[1].cbBuffer); 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) { if(sspi_status == SEC_I_CONTINUE_NEEDED) {
doread = FALSE; doread = FALSE;
continue; continue;
@ -709,7 +711,7 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
} }
} }
else { else {
connssl->encdata_offset = 0; BACKEND->encdata_offset = 0;
} }
break; break;
} }
@ -757,27 +759,27 @@ schannel_connect_step3(struct connectdata *conn, int sockindex)
infof(data, "schannel: SSL/TLS connection with %s port %hu (step 3/3)\n", infof(data, "schannel: SSL/TLS connection with %s port %hu (step 3/3)\n",
hostname, conn->remote_port); hostname, conn->remote_port);
if(!connssl->cred) if(!BACKEND->cred)
return CURLE_SSL_CONNECT_ERROR; return CURLE_SSL_CONNECT_ERROR;
/* check if the required context attributes are met */ /* check if the required context attributes are met */
if(connssl->ret_flags != connssl->req_flags) { if(BACKEND->ret_flags != BACKEND->req_flags) {
if(!(connssl->ret_flags & ISC_RET_SEQUENCE_DETECT)) if(!(BACKEND->ret_flags & ISC_RET_SEQUENCE_DETECT))
failf(data, "schannel: failed to setup sequence detection"); 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"); 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"); 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"); 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"); failf(data, "schannel: failed to setup stream orientation");
return CURLE_SSL_CONNECT_ERROR; return CURLE_SSL_CONNECT_ERROR;
} }
#ifdef HAS_ALPN #ifdef HAS_ALPN
if(connssl->use_alpn) { if(BACKEND->use_alpn) {
sspi_status = s_pSecFn->QueryContextAttributes(&connssl->ctxt->ctxt_handle, sspi_status = s_pSecFn->QueryContextAttributes(&BACKEND->ctxt->ctxt_handle,
SECPKG_ATTR_APPLICATION_PROTOCOL, &alpn_result); SECPKG_ATTR_APPLICATION_PROTOCOL, &alpn_result);
if(sspi_status != SEC_E_OK) { if(sspi_status != SEC_E_OK) {
@ -819,7 +821,7 @@ schannel_connect_step3(struct connectdata *conn, int sockindex)
incache = !(Curl_ssl_getsessionid(conn, (void **)&old_cred, NULL, incache = !(Curl_ssl_getsessionid(conn, (void **)&old_cred, NULL,
sockindex)); sockindex));
if(incache) { if(incache) {
if(old_cred != connssl->cred) { if(old_cred != BACKEND->cred) {
infof(data, "schannel: old credential handle is stale, removing\n"); infof(data, "schannel: old credential handle is stale, removing\n");
/* we're not taking old_cred ownership here, no refcount++ is needed */ /* we're not taking old_cred ownership here, no refcount++ is needed */
Curl_ssl_delsessionid(conn, (void *)old_cred); Curl_ssl_delsessionid(conn, (void *)old_cred);
@ -827,7 +829,7 @@ schannel_connect_step3(struct connectdata *conn, int sockindex)
} }
} }
if(!incache) { if(!incache) {
result = Curl_ssl_addsessionid(conn, (void *)connssl->cred, result = Curl_ssl_addsessionid(conn, (void *)BACKEND->cred,
sizeof(struct curl_schannel_cred), sizeof(struct curl_schannel_cred),
sockindex); sockindex);
if(result) { if(result) {
@ -837,7 +839,7 @@ schannel_connect_step3(struct connectdata *conn, int sockindex)
} }
else { else {
/* this cred session is now also referenced by sessionid cache */ /* 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"); infof(data, "schannel: stored credential handle in session cache\n");
} }
} }
@ -845,7 +847,7 @@ schannel_connect_step3(struct connectdata *conn, int sockindex)
} }
if(data->set.ssl.certinfo) { 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); SECPKG_ATTR_REMOTE_CERT_CONTEXT, &ccert_context);
if((sspi_status != SEC_E_OK) || (ccert_context == NULL)) { if((sspi_status != SEC_E_OK) || (ccert_context == NULL)) {
@ -999,11 +1001,11 @@ schannel_send(struct connectdata *conn, int sockindex,
CURLcode result; CURLcode result;
/* check if the maximum stream sizes were queried */ /* 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( sspi_status = s_pSecFn->QueryContextAttributes(
&connssl->ctxt->ctxt_handle, &BACKEND->ctxt->ctxt_handle,
SECPKG_ATTR_STREAM_SIZES, SECPKG_ATTR_STREAM_SIZES,
&connssl->stream_sizes); &BACKEND->stream_sizes);
if(sspi_status != SEC_E_OK) { if(sspi_status != SEC_E_OK) {
*err = CURLE_SEND_ERROR; *err = CURLE_SEND_ERROR;
return -1; return -1;
@ -1011,14 +1013,14 @@ schannel_send(struct connectdata *conn, int sockindex,
} }
/* check if the buffer is longer than the maximum message length */ /* check if the buffer is longer than the maximum message length */
if(len > connssl->stream_sizes.cbMaximumMessage) { if(len > BACKEND->stream_sizes.cbMaximumMessage) {
*err = CURLE_SEND_ERROR; *err = CURLE_SEND_ERROR;
return -1; return -1;
} }
/* calculate the complete message length and allocate a buffer for it */ /* calculate the complete message length and allocate a buffer for it */
data_len = connssl->stream_sizes.cbHeader + len + data_len = BACKEND->stream_sizes.cbHeader + len +
connssl->stream_sizes.cbTrailer; BACKEND->stream_sizes.cbTrailer;
data = (unsigned char *) malloc(data_len); data = (unsigned char *) malloc(data_len);
if(data == NULL) { if(data == NULL) {
*err = CURLE_OUT_OF_MEMORY; *err = CURLE_OUT_OF_MEMORY;
@ -1027,12 +1029,12 @@ schannel_send(struct connectdata *conn, int sockindex,
/* setup output buffers (header, data, trailer, empty) */ /* setup output buffers (header, data, trailer, empty) */
InitSecBuffer(&outbuf[0], SECBUFFER_STREAM_HEADER, InitSecBuffer(&outbuf[0], SECBUFFER_STREAM_HEADER,
data, connssl->stream_sizes.cbHeader); data, BACKEND->stream_sizes.cbHeader);
InitSecBuffer(&outbuf[1], SECBUFFER_DATA, 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, InitSecBuffer(&outbuf[2], SECBUFFER_STREAM_TRAILER,
data + connssl->stream_sizes.cbHeader + len, data + BACKEND->stream_sizes.cbHeader + len,
connssl->stream_sizes.cbTrailer); BACKEND->stream_sizes.cbTrailer);
InitSecBuffer(&outbuf[3], SECBUFFER_EMPTY, NULL, 0); InitSecBuffer(&outbuf[3], SECBUFFER_EMPTY, NULL, 0);
InitSecBufferDesc(&outbuf_desc, outbuf, 4); InitSecBufferDesc(&outbuf_desc, outbuf, 4);
@ -1040,7 +1042,7 @@ schannel_send(struct connectdata *conn, int sockindex,
memcpy(outbuf[1].pvBuffer, buf, len); memcpy(outbuf[1].pvBuffer, buf, len);
/* https://msdn.microsoft.com/en-us/library/windows/desktop/aa375390.aspx */ /* 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); &outbuf_desc, 0);
/* check if the message was encrypted */ /* check if the message was encrypted */
@ -1150,7 +1152,7 @@ schannel_recv(struct connectdata *conn, int sockindex,
size_t min_encdata_length = len + CURL_SCHANNEL_BUFFER_FREE_SIZE; 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. * 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 * Our priority is to always return as much decrypted data to the caller as
@ -1162,16 +1164,16 @@ schannel_recv(struct connectdata *conn, int sockindex,
infof(data, "schannel: client wants to read %zu bytes\n", len); infof(data, "schannel: client wants to read %zu bytes\n", len);
*err = CURLE_OK; *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"); infof(data, "schannel: enough decrypted data is already available\n");
goto cleanup; goto cleanup;
} }
else if(connssl->recv_unrecoverable_err) { else if(BACKEND->recv_unrecoverable_err) {
*err = connssl->recv_unrecoverable_err; *err = BACKEND->recv_unrecoverable_err;
infof(data, "schannel: an unrecoverable error occurred in a prior call\n"); infof(data, "schannel: an unrecoverable error occurred in a prior call\n");
goto cleanup; 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 */ /* once a server has indicated shutdown there is no more encrypted data */
infof(data, "schannel: server indicated shutdown in a prior call\n"); infof(data, "schannel: server indicated shutdown in a prior call\n");
goto cleanup; goto cleanup;
@ -1183,17 +1185,17 @@ schannel_recv(struct connectdata *conn, int sockindex,
*/ */
; /* do nothing */ ; /* 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 */ /* 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 || if(size < CURL_SCHANNEL_BUFFER_FREE_SIZE ||
connssl->encdata_length < min_encdata_length) { BACKEND->encdata_length < min_encdata_length) {
reallocated_length = connssl->encdata_offset + reallocated_length = BACKEND->encdata_offset +
CURL_SCHANNEL_BUFFER_FREE_SIZE; CURL_SCHANNEL_BUFFER_FREE_SIZE;
if(reallocated_length < min_encdata_length) { if(reallocated_length < min_encdata_length) {
reallocated_length = min_encdata_length; reallocated_length = min_encdata_length;
} }
reallocated_buffer = realloc(connssl->encdata_buffer, reallocated_buffer = realloc(BACKEND->encdata_buffer,
reallocated_length); reallocated_length);
if(reallocated_buffer == NULL) { if(reallocated_buffer == NULL) {
*err = CURLE_OUT_OF_MEMORY; *err = CURLE_OUT_OF_MEMORY;
@ -1201,20 +1203,20 @@ schannel_recv(struct connectdata *conn, int sockindex,
goto cleanup; goto cleanup;
} }
connssl->encdata_buffer = reallocated_buffer; BACKEND->encdata_buffer = reallocated_buffer;
connssl->encdata_length = reallocated_length; BACKEND->encdata_length = reallocated_length;
size = connssl->encdata_length - connssl->encdata_offset; size = BACKEND->encdata_length - BACKEND->encdata_offset;
infof(data, "schannel: encdata_buffer resized %zu\n", 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", 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 */ /* read encrypted data from socket */
*err = Curl_read_plain(conn->sock[sockindex], *err = Curl_read_plain(conn->sock[sockindex],
(char *)(connssl->encdata_buffer + (char *)(BACKEND->encdata_buffer +
connssl->encdata_offset), BACKEND->encdata_offset),
size, &nread); size, &nread);
if(*err) { if(*err) {
nread = -1; nread = -1;
@ -1226,26 +1228,26 @@ schannel_recv(struct connectdata *conn, int sockindex,
infof(data, "schannel: Curl_read_plain returned error %d\n", *err); infof(data, "schannel: Curl_read_plain returned error %d\n", *err);
} }
else if(nread == 0) { else if(nread == 0) {
connssl->recv_connection_closed = true; BACKEND->recv_connection_closed = true;
infof(data, "schannel: server closed the connection\n"); infof(data, "schannel: server closed the connection\n");
} }
else if(nread > 0) { else if(nread > 0) {
connssl->encdata_offset += (size_t)nread; BACKEND->encdata_offset += (size_t)nread;
connssl->encdata_is_incomplete = false; BACKEND->encdata_is_incomplete = false;
infof(data, "schannel: encrypted data got %zd\n", nread); infof(data, "schannel: encrypted data got %zd\n", nread);
} }
} }
infof(data, "schannel: encrypted data buffer: offset %zu length %zu\n", 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 */ /* decrypt loop */
while(connssl->encdata_offset > 0 && sspi_status == SEC_E_OK && while(BACKEND->encdata_offset > 0 && sspi_status == SEC_E_OK &&
(!len || connssl->decdata_offset < len || (!len || BACKEND->decdata_offset < len ||
connssl->recv_connection_closed)) { BACKEND->recv_connection_closed)) {
/* prepare data buffer for DecryptMessage call */ /* prepare data buffer for DecryptMessage call */
InitSecBuffer(&inbuf[0], SECBUFFER_DATA, connssl->encdata_buffer, InitSecBuffer(&inbuf[0], SECBUFFER_DATA, BACKEND->encdata_buffer,
curlx_uztoul(connssl->encdata_offset)); curlx_uztoul(BACKEND->encdata_offset));
/* we need 3 more empty input buffers for possible output */ /* we need 3 more empty input buffers for possible output */
InitSecBuffer(&inbuf[1], SECBUFFER_EMPTY, NULL, 0); InitSecBuffer(&inbuf[1], SECBUFFER_EMPTY, NULL, 0);
@ -1255,7 +1257,7 @@ schannel_recv(struct connectdata *conn, int sockindex,
/* https://msdn.microsoft.com/en-us/library/windows/desktop/aa375348.aspx /* 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); &inbuf_desc, 0, NULL);
/* check if everything went fine (server may want to renegotiate /* check if everything went fine (server may want to renegotiate
@ -1271,36 +1273,36 @@ schannel_recv(struct connectdata *conn, int sockindex,
/* increase buffer in order to fit the received amount of data */ /* increase buffer in order to fit the received amount of data */
size = inbuf[1].cbBuffer > CURL_SCHANNEL_BUFFER_FREE_SIZE ? size = inbuf[1].cbBuffer > CURL_SCHANNEL_BUFFER_FREE_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 || if(BACKEND->decdata_length - BACKEND->decdata_offset < size ||
connssl->decdata_length < len) { BACKEND->decdata_length < len) {
/* increase internal decrypted data buffer */ /* 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 */ /* make sure that the requested amount of data fits */
if(reallocated_length < len) { if(reallocated_length < len) {
reallocated_length = len; reallocated_length = len;
} }
reallocated_buffer = realloc(connssl->decdata_buffer, reallocated_buffer = realloc(BACKEND->decdata_buffer,
reallocated_length); reallocated_length);
if(reallocated_buffer == NULL) { if(reallocated_buffer == NULL) {
*err = CURLE_OUT_OF_MEMORY; *err = CURLE_OUT_OF_MEMORY;
failf(data, "schannel: unable to re-allocate memory"); failf(data, "schannel: unable to re-allocate memory");
goto cleanup; goto cleanup;
} }
connssl->decdata_buffer = reallocated_buffer; BACKEND->decdata_buffer = reallocated_buffer;
connssl->decdata_length = reallocated_length; BACKEND->decdata_length = reallocated_length;
} }
/* copy decrypted data to internal buffer */ /* copy decrypted data to internal buffer */
size = inbuf[1].cbBuffer; size = inbuf[1].cbBuffer;
if(size) { if(size) {
memcpy(connssl->decdata_buffer + connssl->decdata_offset, memcpy(BACKEND->decdata_buffer + BACKEND->decdata_offset,
inbuf[1].pvBuffer, size); 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 added: %zu\n", size);
infof(data, "schannel: decrypted data cached: offset %zu length %zu\n", 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 */ /* check for remaining encrypted data */
@ -1311,21 +1313,21 @@ schannel_recv(struct connectdata *conn, int sockindex,
/* check if the remaining data is less than the total amount /* check if the remaining data is less than the total amount
* and therefore begins after the already processed data * 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 /* move remaining encrypted data forward to the beginning of
buffer */ buffer */
memmove(connssl->encdata_buffer, memmove(BACKEND->encdata_buffer,
(connssl->encdata_buffer + connssl->encdata_offset) - (BACKEND->encdata_buffer + BACKEND->encdata_offset) -
inbuf[3].cbBuffer, inbuf[3].cbBuffer); 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", infof(data, "schannel: encrypted data cached: offset %zu length %zu\n",
connssl->encdata_offset, connssl->encdata_length); BACKEND->encdata_offset, BACKEND->encdata_length);
} }
else { else {
/* reset encrypted buffer offset, because there is no data remaining */ /* 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 */ /* check if server wants to renegotiate the connection context */
@ -1335,7 +1337,7 @@ schannel_recv(struct connectdata *conn, int sockindex,
infof(data, "schannel: can't renogotiate, an error is pending\n"); infof(data, "schannel: can't renogotiate, an error is pending\n");
goto cleanup; goto cleanup;
} }
if(connssl->encdata_offset) { if(BACKEND->encdata_offset) {
*err = CURLE_RECV_ERROR; *err = CURLE_RECV_ERROR;
infof(data, "schannel: can't renogotiate, " infof(data, "schannel: can't renogotiate, "
"encrypted data available\n"); "encrypted data available\n");
@ -1359,16 +1361,16 @@ schannel_recv(struct connectdata *conn, int sockindex,
else if(sspi_status == SEC_I_CONTEXT_EXPIRED) { else if(sspi_status == SEC_I_CONTEXT_EXPIRED) {
/* In Windows 2000 SEC_I_CONTEXT_EXPIRED (close_notify) is not /* In Windows 2000 SEC_I_CONTEXT_EXPIRED (close_notify) is not
returned so we have to work around that in cleanup. */ returned so we have to work around that in cleanup. */
connssl->recv_sspi_close_notify = true; BACKEND->recv_sspi_close_notify = true;
if(!connssl->recv_connection_closed) { if(!BACKEND->recv_connection_closed) {
connssl->recv_connection_closed = true; BACKEND->recv_connection_closed = true;
infof(data, "schannel: server closed the connection\n"); infof(data, "schannel: server closed the connection\n");
} }
goto cleanup; goto cleanup;
} }
} }
else if(sspi_status == SEC_E_INCOMPLETE_MESSAGE) { else if(sspi_status == SEC_E_INCOMPLETE_MESSAGE) {
connssl->encdata_is_incomplete = true; BACKEND->encdata_is_incomplete = true;
if(!*err) if(!*err)
*err = CURLE_AGAIN; *err = CURLE_AGAIN;
infof(data, "schannel: failed to decrypt data, need more data\n"); infof(data, "schannel: failed to decrypt data, need more data\n");
@ -1383,10 +1385,10 @@ schannel_recv(struct connectdata *conn, int sockindex,
} }
infof(data, "schannel: encrypted data buffer: offset %zu length %zu\n", 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", infof(data, "schannel: decrypted data buffer: offset %zu length %zu\n",
connssl->decdata_offset, connssl->decdata_length); BACKEND->decdata_offset, BACKEND->decdata_length);
cleanup: cleanup:
/* Warning- there is no guarantee the encdata state is valid at this point */ /* Warning- there is no guarantee the encdata state is valid at this point */
@ -1400,13 +1402,13 @@ cleanup:
return close_notify. In that case if the connection was closed we assume it 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. was graceful (close_notify) since there doesn't seem to be a way to tell.
*/ */
if(len && !connssl->decdata_offset && connssl->recv_connection_closed && if(len && !BACKEND->decdata_offset && BACKEND->recv_connection_closed &&
!connssl->recv_sspi_close_notify) { !BACKEND->recv_sspi_close_notify) {
bool isWin2k = Curl_verify_windows_version(5, 0, PLATFORM_WINNT, bool isWin2k = Curl_verify_windows_version(5, 0, PLATFORM_WINNT,
VERSION_EQUAL); VERSION_EQUAL);
if(isWin2k && sspi_status == SEC_E_OK) if(isWin2k && sspi_status == SEC_E_OK)
connssl->recv_sspi_close_notify = true; BACKEND->recv_sspi_close_notify = true;
else { else {
*err = CURLE_RECV_ERROR; *err = CURLE_RECV_ERROR;
infof(data, "schannel: server closed abruptly (missing close_notify)\n"); infof(data, "schannel: server closed abruptly (missing close_notify)\n");
@ -1415,23 +1417,23 @@ cleanup:
/* Any error other than CURLE_AGAIN is an unrecoverable error. */ /* Any error other than CURLE_AGAIN is an unrecoverable error. */
if(*err && *err != CURLE_AGAIN) 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) { if(size) {
memcpy(buf, connssl->decdata_buffer, size); memcpy(buf, BACKEND->decdata_buffer, size);
memmove(connssl->decdata_buffer, connssl->decdata_buffer + size, memmove(BACKEND->decdata_buffer, BACKEND->decdata_buffer + size,
connssl->decdata_offset - size); BACKEND->decdata_offset - size);
connssl->decdata_offset -= size; BACKEND->decdata_offset -= size;
infof(data, "schannel: decrypted data returned %zu\n", size); infof(data, "schannel: decrypted data returned %zu\n", size);
infof(data, "schannel: decrypted data buffer: offset %zu length %zu\n", 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; *err = CURLE_OK;
return (ssize_t)size; return (ssize_t)size;
} }
if(!*err && !connssl->recv_connection_closed) if(!*err && !BACKEND->recv_connection_closed)
*err = CURLE_AGAIN; *err = CURLE_AGAIN;
/* It's debatable what to return when !len. We could return whatever error we /* It's debatable what to return when !len. We could return whatever error we
@ -1469,8 +1471,8 @@ static bool Curl_schannel_data_pending(const struct connectdata *conn,
const struct ssl_connect_data *connssl = &conn->ssl[sockindex]; const struct ssl_connect_data *connssl = &conn->ssl[sockindex];
if(connssl->use) /* SSL/TLS is in use */ if(connssl->use) /* SSL/TLS is in use */
return (connssl->decdata_offset > 0 || return (BACKEND->decdata_offset > 0 ||
(connssl->encdata_offset > 0 && !connssl->encdata_is_incomplete)); (BACKEND->encdata_offset > 0 && !BACKEND->encdata_is_incomplete));
else else
return FALSE; return FALSE;
} }
@ -1507,7 +1509,7 @@ static int Curl_schannel_shutdown(struct connectdata *conn, int sockindex)
infof(data, "schannel: shutting down SSL/TLS connection with %s port %hu\n", infof(data, "schannel: shutting down SSL/TLS connection with %s port %hu\n",
hostname, conn->remote_port); hostname, conn->remote_port);
if(connssl->cred && connssl->ctxt) { if(BACKEND->cred && BACKEND->ctxt) {
SecBufferDesc BuffDesc; SecBufferDesc BuffDesc;
SecBuffer Buffer; SecBuffer Buffer;
SECURITY_STATUS sspi_status; SECURITY_STATUS sspi_status;
@ -1520,7 +1522,7 @@ static int Curl_schannel_shutdown(struct connectdata *conn, int sockindex)
InitSecBuffer(&Buffer, SECBUFFER_TOKEN, &dwshut, sizeof(dwshut)); InitSecBuffer(&Buffer, SECBUFFER_TOKEN, &dwshut, sizeof(dwshut));
InitSecBufferDesc(&BuffDesc, &Buffer, 1); InitSecBufferDesc(&BuffDesc, &Buffer, 1);
sspi_status = s_pSecFn->ApplyControlToken(&connssl->ctxt->ctxt_handle, sspi_status = s_pSecFn->ApplyControlToken(&BACKEND->ctxt->ctxt_handle,
&BuffDesc); &BuffDesc);
if(sspi_status != SEC_E_OK) if(sspi_status != SEC_E_OK)
@ -1536,18 +1538,18 @@ static int Curl_schannel_shutdown(struct connectdata *conn, int sockindex)
InitSecBufferDesc(&outbuf_desc, &outbuf, 1); InitSecBufferDesc(&outbuf_desc, &outbuf, 1);
sspi_status = s_pSecFn->InitializeSecurityContext( sspi_status = s_pSecFn->InitializeSecurityContext(
&connssl->cred->cred_handle, &BACKEND->cred->cred_handle,
&connssl->ctxt->ctxt_handle, &BACKEND->ctxt->ctxt_handle,
host_name, host_name,
connssl->req_flags, BACKEND->req_flags,
0, 0,
0, 0,
NULL, NULL,
0, 0,
&connssl->ctxt->ctxt_handle, &BACKEND->ctxt->ctxt_handle,
&outbuf_desc, &outbuf_desc,
&connssl->ret_flags, &BACKEND->ret_flags,
&connssl->ctxt->time_stamp); &BACKEND->ctxt->time_stamp);
Curl_unicodefree(host_name); Curl_unicodefree(host_name);
@ -1566,33 +1568,33 @@ static int Curl_schannel_shutdown(struct connectdata *conn, int sockindex)
} }
/* free SSPI Schannel API security context handle */ /* free SSPI Schannel API security context handle */
if(connssl->ctxt) { if(BACKEND->ctxt) {
infof(data, "schannel: clear security context handle\n"); infof(data, "schannel: clear security context handle\n");
s_pSecFn->DeleteSecurityContext(&connssl->ctxt->ctxt_handle); s_pSecFn->DeleteSecurityContext(&BACKEND->ctxt->ctxt_handle);
Curl_safefree(connssl->ctxt); Curl_safefree(BACKEND->ctxt);
} }
/* free SSPI Schannel API credential handle */ /* free SSPI Schannel API credential handle */
if(connssl->cred) { if(BACKEND->cred) {
Curl_ssl_sessionid_lock(conn); Curl_ssl_sessionid_lock(conn);
Curl_schannel_session_free(connssl->cred); Curl_schannel_session_free(BACKEND->cred);
Curl_ssl_sessionid_unlock(conn); Curl_ssl_sessionid_unlock(conn);
connssl->cred = NULL; BACKEND->cred = NULL;
} }
/* free internal buffer for received encrypted data */ /* free internal buffer for received encrypted data */
if(connssl->encdata_buffer != NULL) { if(BACKEND->encdata_buffer != NULL) {
Curl_safefree(connssl->encdata_buffer); Curl_safefree(BACKEND->encdata_buffer);
connssl->encdata_length = 0; BACKEND->encdata_length = 0;
connssl->encdata_offset = 0; BACKEND->encdata_offset = 0;
connssl->encdata_is_incomplete = false; BACKEND->encdata_is_incomplete = false;
} }
/* free internal buffer for received decrypted data */ /* free internal buffer for received decrypted data */
if(connssl->decdata_buffer != NULL) { if(BACKEND->decdata_buffer != NULL) {
Curl_safefree(connssl->decdata_buffer); Curl_safefree(BACKEND->decdata_buffer);
connssl->decdata_length = 0; BACKEND->decdata_length = 0;
connssl->decdata_offset = 0; BACKEND->decdata_offset = 0;
} }
return CURLE_OK; return CURLE_OK;
@ -1646,7 +1648,7 @@ static CURLcode verify_certificate(struct connectdata *conn, int sockindex)
conn->http_proxy.host.name : conn->http_proxy.host.name :
conn->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, SECPKG_ATTR_REMOTE_CERT_CONTEXT,
&pCertContextServer); &pCertContextServer);
@ -1777,7 +1779,7 @@ static void *Curl_schannel_get_internals(struct ssl_connect_data *connssl,
CURLINFO info UNUSED_PARAM) CURLINFO info UNUSED_PARAM)
{ {
(void)info; (void)info;
return &connssl->ctxt->ctxt_handle; return &BACKEND->ctxt->ctxt_handle;
} }
const struct Curl_ssl Curl_ssl_schannel = { const struct Curl_ssl Curl_ssl_schannel = {