*/
static struct connectdata *allocate_conn(struct Curl_easy *data)
{
- struct connectdata *conn = calloc(1, sizeof(struct connectdata));
+#ifdef USE_SSL
+#define SSL_EXTRA + 4 * Curl_ssl->sizeof_ssl_backend_data - sizeof(long long)
+#else
+#define SSL_EXTRA 0
+#endif
+ struct connectdata *conn = calloc(1, sizeof(struct connectdata) + SSL_EXTRA);
if(!conn)
return NULL;
conn->ip_version = data->set.ipver;
+#ifdef USE_SSL
+ /*
+ * To save on malloc()s, the SSL backend-specific data has been allocated
+ * at the end of the connectdata struct.
+ */
+ {
+ char *p = (char *)&conn->align_data__do_not_use;
+ conn->ssl[0].backend = (struct ssl_backend_data *)p;
+ conn->ssl[1].backend =
+ (struct ssl_backend_data *)(p + Curl_ssl->sizeof_ssl_backend_data);
+ conn->proxy_ssl[0].backend =
+ (struct ssl_backend_data *)(p + Curl_ssl->sizeof_ssl_backend_data * 2);
+ conn->proxy_ssl[1].backend =
+ (struct ssl_backend_data *)(p + Curl_ssl->sizeof_ssl_backend_data * 3);
+ }
+#endif
+
#if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) && \
defined(NTLM_WB_ENABLED)
conn->ntlm_auth_hlpr_socket = CURL_SOCKET_BAD;
#include "cookie.h"
#include "formdata.h"
-#ifdef USE_OPENSSL
-#include <openssl/ssl.h>
-#ifdef HAVE_OPENSSL_ENGINE_H
-#include <openssl/engine.h>
-#endif
-#endif /* USE_OPENSSL */
-
-#ifdef USE_GNUTLS
-#include <gnutls/gnutls.h>
-#endif
-
-#ifdef USE_MBEDTLS
-
-#include <mbedtls/ssl.h>
-#include <mbedtls/version.h>
-#include <mbedtls/entropy.h>
-#include <mbedtls/ctr_drbg.h>
-
-#elif defined USE_POLARSSL
-
-#include <polarssl/ssl.h>
-#include <polarssl/version.h>
-#include <polarssl/entropy.h>
-#include <polarssl/ctr_drbg.h>
-
-#endif /* USE_POLARSSL */
-
-#ifdef USE_CYASSL
-#undef OCSP_REQUEST /* avoid cyassl/openssl/ssl.h clash with wincrypt.h */
-#undef OCSP_RESPONSE /* avoid cyassl/openssl/ssl.h clash with wincrypt.h */
-#include <cyassl/openssl/ssl.h>
-#endif
-
-#ifdef USE_NSS
-#include <nspr.h>
-#include <pk11pub.h>
-#endif
-
-#ifdef USE_GSKIT
-#include <gskssl.h>
-#endif
-
-#ifdef USE_AXTLS
-#include <axTLS/config.h>
-#include <axTLS/ssl.h>
-#undef malloc
-#undef calloc
-#undef realloc
-#endif /* USE_AXTLS */
-
-#if defined(USE_SCHANNEL) || defined(USE_WINDOWS_SSPI)
-#include "curl_sspi.h"
-#endif
-#ifdef USE_SCHANNEL
-#include <schnlsp.h>
-#include <schannel.h>
-#endif
-
-#ifdef USE_DARWINSSL
-#include <Security/Security.h>
-/* For some reason, when building for iOS, the omnibus header above does
- * not include SecureTransport.h as of iOS SDK 5.1. */
-#include <Security/SecureTransport.h>
-#endif
-
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
};
#endif
-#ifdef USE_SCHANNEL
-/* Structs to store Schannel handles */
-struct curl_schannel_cred {
- CredHandle cred_handle;
- TimeStamp time_stamp;
- int refcount;
-};
-
-struct curl_schannel_ctxt {
- CtxtHandle ctxt_handle;
- TimeStamp time_stamp;
-};
-#endif
-
/* enum for the nonblocking SSL connection state machine */
typedef enum {
ssl_connect_1,
ssl_connection_complete
} ssl_connection_state;
+/* SSL backend-specific data; declared differently by each SSL backend */
+struct ssl_backend_data;
+
/* struct for data related to each SSL connection */
struct ssl_connect_data {
/* Use ssl encrypted communications TRUE/FALSE, not necessarily using it atm
bool use;
ssl_connection_state state;
ssl_connect_state connecting_state;
-#if defined(USE_OPENSSL)
- /* these ones requires specific SSL-types */
- SSL_CTX* ctx;
- SSL* handle;
- X509* server_cert;
-#elif defined(USE_GNUTLS)
- gnutls_session_t session;
- gnutls_certificate_credentials_t cred;
-#ifdef USE_TLS_SRP
- gnutls_srp_client_credentials_t srp_client_cred;
-#endif
-#elif defined(USE_MBEDTLS)
- mbedtls_ctr_drbg_context ctr_drbg;
- mbedtls_entropy_context entropy;
- mbedtls_ssl_context ssl;
- int server_fd;
- mbedtls_x509_crt cacert;
- mbedtls_x509_crt clicert;
- mbedtls_x509_crl crl;
- mbedtls_pk_context pk;
- mbedtls_ssl_config config;
- const char *protocols[3];
-#elif defined(USE_POLARSSL)
- ctr_drbg_context ctr_drbg;
- entropy_context entropy;
- ssl_context ssl;
- int server_fd;
- x509_crt cacert;
- x509_crt clicert;
- x509_crl crl;
- rsa_context rsa;
-#elif defined(USE_CYASSL)
- SSL_CTX* ctx;
- SSL* handle;
-#elif defined(USE_NSS)
- PRFileDesc *handle;
- char *client_nickname;
- struct Curl_easy *data;
- struct curl_llist obj_list;
- PK11GenericObject *obj_clicert;
-#elif defined(USE_GSKIT)
- gsk_handle handle;
- int iocport;
- int localfd;
- int remotefd;
-#elif defined(USE_AXTLS)
- SSL_CTX* ssl_ctx;
- SSL* ssl;
-#elif defined(USE_SCHANNEL)
- struct curl_schannel_cred *cred;
- struct curl_schannel_ctxt *ctxt;
- SecPkgContext_StreamSizes stream_sizes;
- size_t encdata_length, decdata_length;
- size_t encdata_offset, decdata_offset;
- unsigned char *encdata_buffer, *decdata_buffer;
- /* encdata_is_incomplete: if encdata contains only a partial record that
- can't be decrypted without another Curl_read_plain (that is, status is
- SEC_E_INCOMPLETE_MESSAGE) then set this true. after Curl_read_plain writes
- more bytes into encdata then set this back to false. */
- bool encdata_is_incomplete;
- unsigned long req_flags, ret_flags;
- CURLcode recv_unrecoverable_err; /* schannel_recv had an unrecoverable err */
- bool recv_sspi_close_notify; /* true if connection closed by close_notify */
- bool recv_connection_closed; /* true if connection closed, regardless how */
- bool use_alpn; /* true if ALPN is used for this connection */
-#elif defined(USE_DARWINSSL)
- SSLContextRef ssl_ctx;
- curl_socket_t ssl_sockfd;
- bool ssl_direction; /* true if writing, false if reading */
- size_t ssl_write_buffered_length;
-#elif defined(USE_SSL)
-#error "SSL backend specific information missing from ssl_connect_data"
+#if defined(USE_SSL)
+ struct ssl_backend_data *backend;
#endif
};
char *unix_domain_socket;
bool abstract_unix_socket;
#endif
+
+#ifdef USE_SSL
+ /*
+ * To avoid multiple malloc() calls, the ssl_connect_data structures
+ * associated with a connectdata struct are allocated in the same block
+ * as the latter. This field forces alignment to an 8-byte boundary so
+ * that this all works.
+ */
+ long long *align_data__do_not_use;
+#endif
};
/* The end of connectdata. */
ares_channel f.e. */
#if defined(USE_OPENSSL) && defined(HAVE_OPENSSL_ENGINE_H)
- ENGINE *engine;
+ /* void instead of ENGINE to avoid bleeding OpenSSL into this header */
+ void *engine;
#endif /* USE_OPENSSL */
struct curltime expiretime; /* set this with Curl_expire() only */
struct Curl_tree timenode; /* for the splay stuff */
#include "curl_memory.h"
#include "memdebug.h"
-#define BACKEND connssl
+struct ssl_backend_data {
+ SSL_CTX* ssl_ctx;
+ SSL* ssl;
+};
+
+#define BACKEND connssl->backend
static CURLcode map_error_to_curl(int axtls_err)
{
static int Curl_axtls_check_cxn(struct connectdata *conn)
{
/* openssl.c line:
- rc = SSL_peek(conn->ssl[FIRSTSOCKET].ssl, (void*)&buf, 1);
+ rc = SSL_peek(conn->ssl[FIRSTSOCKET].backend->ssl, (void*)&buf, 1);
axTLS compat layer always returns the last argument, so connection is
always alive? */
0, /* have_ssl_ctx */
0, /* support_https_proxy */
+ sizeof(struct ssl_backend_data),
+
/*
* axTLS has no global init. Everything is done through SSL and SSL_CTX
* structs stored in connectdata structure.
#include "x509asn1.h"
#include "curl_printf.h"
+#include <cyassl/openssl/ssl.h>
#include <cyassl/ssl.h>
#ifdef HAVE_CYASSL_ERROR_SSL_H
#include <cyassl/error-ssl.h>
#endif
#endif
-#define BACKEND connssl
+struct ssl_backend_data {
+ SSL_CTX* ctx;
+ SSL* handle;
+};
+
+#define BACKEND connssl->backend
static Curl_recv cyassl_recv;
static Curl_send cyassl_send;
1, /* have_ssl_ctx */
0, /* support_https_proxy */
+ sizeof(struct ssl_backend_data),
+
Curl_cyassl_init, /* init */
Curl_none_cleanup, /* cleanup */
Curl_cyassl_version, /* version */
#endif
#include <Security/Security.h>
+/* For some reason, when building for iOS, the omnibus header above does
+ * not include SecureTransport.h as of iOS SDK 5.1. */
#include <Security/SecureTransport.h>
#include <CoreFoundation/CoreFoundation.h>
#include <CommonCrypto/CommonDigest.h>
#define ioErr -36
#define paramErr -50
-#define BACKEND connssl
+struct ssl_backend_data {
+ SSLContextRef ssl_ctx;
+ curl_socket_t ssl_sockfd;
+ bool ssl_direction; /* true if writing, false if reading */
+ size_t ssl_write_buffered_length;
+};
+
+#define BACKEND connssl->backend
/* pinned public key support tests */
0, /* have_ssl_ctx */
0, /* support_https_proxy */
+ sizeof(struct ssl_backend_data),
+
Curl_none_init, /* init */
Curl_none_cleanup, /* cleanup */
Curl_darwinssl_version, /* version */
#define CURL_GSKPROTO_TLSV12_MASK (1 << CURL_GSKPROTO_TLSV12)
#define CURL_GSKPROTO_LAST 5
-#define BACKEND connssl
+struct ssl_backend_data {
+ gsk_handle handle;
+ int iocport;
+ int localfd;
+ int remotefd;
+};
+
+#define BACKEND connssl->backend
/* Supported ciphers. */
typedef struct {
if(FD_ISSET(BACKEND->remotefd, &fds_write)) {
/* Try getting data from HTTPS proxy and pipe it upstream. */
n = 0;
- i = gsk_secure_soc_read(connproxyssl->handle,
+ i = gsk_secure_soc_read(connproxyssl->backend->handle,
buf, sizeof buf, &n);
switch(i) {
case GSK_OK:
if(n < 0)
return -1;
if(n) {
- i = gsk_secure_soc_write(connproxyssl->handle, buf, n, &m);
+ i = gsk_secure_soc_write(connproxyssl->backend->handle, buf, n, &m);
if(i != GSK_OK || n != m)
return -1;
ret = 1;
/* TODO: convert to 1 and fix test #1014 (if need) */
0, /* support_https_proxy */
+ sizeof(struct ssl_backend_data),
Curl_gskit_init, /* init */
Curl_gskit_cleanup, /* cleanup */
# include <gnutls/ocsp.h>
#endif
-#define BACKEND connssl
+struct ssl_backend_data {
+ gnutls_session_t session;
+ gnutls_certificate_credentials_t cred;
+#ifdef USE_TLS_SRP
+ gnutls_srp_client_credentials_t srp_client_cred;
+#endif
+};
+
+#define BACKEND connssl->backend
/*
* Custom push and pull callback functions used by GNU TLS to read and write
}
if(conn->proxy_ssl[sockindex].use) {
- transport_ptr = conn->proxy_ssl[sockindex].session;
+ transport_ptr = conn->proxy_ssl[sockindex].backend->session;
gnutls_transport_push = Curl_gtls_push_ssl;
gnutls_transport_pull = Curl_gtls_pull_ssl;
}
0, /* have_ssl_ctx */
1, /* support_https_proxy */
+ sizeof(struct ssl_backend_data),
+
Curl_gtls_init, /* init */
Curl_gtls_cleanup, /* cleanup */
Curl_gtls_version, /* version */
#include "curl_memory.h"
#include "memdebug.h"
-#define BACKEND connssl
+struct ssl_backend_data {
+ mbedtls_ctr_drbg_context ctr_drbg;
+ mbedtls_entropy_context entropy;
+ mbedtls_ssl_context ssl;
+ int server_fd;
+ mbedtls_x509_crt cacert;
+ mbedtls_x509_crt clicert;
+ mbedtls_x509_crl crl;
+ mbedtls_pk_context pk;
+ mbedtls_ssl_config config;
+ const char *protocols[3];
+};
+
+#define BACKEND connssl->backend
/* apply threading? */
#if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32)
1, /* have_ssl_ctx */
0, /* support_https_proxy */
+ sizeof(struct ssl_backend_data),
+
Curl_mbedtls_init, /* init */
Curl_mbedtls_cleanup, /* cleanup */
Curl_mbedtls_version, /* version */
/* enough to fit the string "PEM Token #[0|1]" */
#define SLOTSIZE 13
-#define BACKEND connssl
+struct ssl_backend_data {
+ PRFileDesc *handle;
+ char *client_nickname;
+ struct Curl_easy *data;
+ struct curl_llist obj_list;
+ PK11GenericObject *obj_clicert;
+};
+
+#define BACKEND connssl->backend
static PRLock *nss_initlock = NULL;
static PRLock *nss_crllock = NULL;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_connect_data *connssl_proxy = &conn->proxy_ssl[sockindex];
- if(BACKEND->handle || connssl_proxy->handle) {
+ if(BACKEND->handle || connssl_proxy->backend->handle) {
/* NSS closes the socket we previously handed to it, so we must mark it
as closed to avoid double close */
fake_sclose(conn->sock[sockindex]);
if(BACKEND->handle)
/* nss_close(connssl) will transitively close also
- connssl_proxy->handle if both are used. Clear it to avoid
+ connssl_proxy->backend->handle if both are used. Clear it to avoid
a double close leading to crash. */
- connssl_proxy->handle = NULL;
+ connssl_proxy->backend->handle = NULL;
nss_close(connssl);
nss_close(connssl_proxy);
if(conn->proxy_ssl[sockindex].use) {
DEBUGASSERT(ssl_connection_complete == conn->proxy_ssl[sockindex].state);
- DEBUGASSERT(conn->proxy_ssl[sockindex].handle != NULL);
- nspr_io = conn->proxy_ssl[sockindex].handle;
+ DEBUGASSERT(conn->proxy_ssl[sockindex].backend->handle != NULL);
+ nspr_io = conn->proxy_ssl[sockindex].backend->handle;
second_layer = TRUE;
}
else {
0, /* have_ssl_ctx */
1, /* support_https_proxy */
+ sizeof(struct ssl_backend_data),
+
Curl_nss_init, /* init */
Curl_nss_cleanup, /* cleanup */
Curl_nss_version, /* version */
#include "strcase.h"
#include "hostcheck.h"
#include "curl_printf.h"
-
#include <openssl/ssl.h>
+#ifdef HAVE_OPENSSL_ENGINE_H
+#include <openssl/engine.h>
+#endif
#include <openssl/rand.h>
#include <openssl/x509v3.h>
#ifndef OPENSSL_NO_DSA
#define DEFAULT_CIPHER_SELECTION \
"ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH"
-#define BACKEND connssl
+struct ssl_backend_data {
+ /* these ones requires specific SSL-types */
+ SSL_CTX* ctx;
+ SSL* handle;
+ X509* server_cert;
+};
+
+#define BACKEND connssl->backend
/*
* Number of bytes to read from the random number seed file. This must be
if(conn->proxy_ssl[sockindex].use) {
BIO *const bio = BIO_new(BIO_f_ssl());
- SSL *handle = conn->proxy_ssl[sockindex].handle;
+ SSL *handle = conn->proxy_ssl[sockindex].backend->handle;
DEBUGASSERT(ssl_connection_complete == conn->proxy_ssl[sockindex].state);
DEBUGASSERT(BACKEND->handle != NULL);
DEBUGASSERT(bio != NULL);
1, /* have_ssl_ctx */
1, /* support_https_proxy */
+ sizeof(struct ssl_backend_data),
+
Curl_ossl_init, /* init */
Curl_ossl_cleanup, /* cleanup */
Curl_ossl_version, /* version */
#ifdef USE_POLARSSL
+#elif defined USE_POLARSSL
+
#include <polarssl/net.h>
#include <polarssl/ssl.h>
#include <polarssl/certs.h>
#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)
-#define BACKEND connssl
+struct ssl_backend_data {
+ ctr_drbg_context ctr_drbg;
+ entropy_context entropy;
+ ssl_context ssl;
+ int server_fd;
+ x509_crt cacert;
+ x509_crt clicert;
+ x509_crl crl;
+ rsa_context rsa;
+};
+
+#define BACKEND connssl->backend
/* apply threading? */
#if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32)
0, /* have_ssl_ctx */
0, /* support_https_proxy */
+ sizeof(struct ssl_backend_data),
+
Curl_polarssl_init, /* init */
Curl_polarssl_cleanup, /* cleanup */
Curl_polarssl_version, /* version */
# error "Can't compile SCHANNEL support without SSPI."
#endif
+#include <schnlsp.h>
+#include <schannel.h>
#include "curl_sspi.h"
#include "schannel.h"
#include "vtls.h"
* #define failf(x, y, ...) printf(y, __VA_ARGS__)
*/
-#define BACKEND connssl
+/* Structs to store Schannel handles */
+struct curl_schannel_cred {
+ CredHandle cred_handle;
+ TimeStamp time_stamp;
+ int refcount;
+};
+
+struct curl_schannel_ctxt {
+ CtxtHandle ctxt_handle;
+ TimeStamp time_stamp;
+};
+
+struct ssl_backend_data {
+ struct curl_schannel_cred *cred;
+ struct curl_schannel_ctxt *ctxt;
+ SecPkgContext_StreamSizes stream_sizes;
+ size_t encdata_length, decdata_length;
+ size_t encdata_offset, decdata_offset;
+ unsigned char *encdata_buffer, *decdata_buffer;
+ /* encdata_is_incomplete: if encdata contains only a partial record that
+ can't be decrypted without another Curl_read_plain (that is, status is
+ SEC_E_INCOMPLETE_MESSAGE) then set this true. after Curl_read_plain writes
+ more bytes into encdata then set this back to false. */
+ bool encdata_is_incomplete;
+ unsigned long req_flags, ret_flags;
+ CURLcode recv_unrecoverable_err; /* schannel_recv had an unrecoverable err */
+ bool recv_sspi_close_notify; /* true if connection closed by close_notify */
+ bool recv_connection_closed; /* true if connection closed, regardless how */
+ bool use_alpn; /* true if ALPN is used for this connection */
+};
+
+#define BACKEND connssl->backend
static Curl_recv schannel_recv;
static Curl_send schannel_send;
0, /* have_ssl_ctx */
0, /* support_https_proxy */
+ sizeof(struct ssl_backend_data),
+
Curl_schannel_init, /* init */
Curl_schannel_cleanup, /* cleanup */
Curl_schannel_version, /* version */
unsigned support_https_proxy:1; /* supports access via HTTPS proxies */
+ size_t sizeof_ssl_backend_data;
+
int (*init)(void);
void (*cleanup)(void);