aboutsummaryrefslogtreecommitdiffstats
path: root/lib/vtls/vtls.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/vtls/vtls.c')
-rw-r--r--lib/vtls/vtls.c513
1 files changed, 426 insertions, 87 deletions
diff --git a/lib/vtls/vtls.c b/lib/vtls/vtls.c
index d5d0971c..56e63177 100644
--- a/lib/vtls/vtls.c
+++ b/lib/vtls/vtls.c
@@ -28,17 +28,9 @@
to any specific SSL-layer.
Curl_ssl_ - prefix for generic ones
- Curl_ossl_ - prefix for OpenSSL ones
- Curl_gtls_ - prefix for GnuTLS ones
- Curl_nss_ - prefix for NSS ones
- Curl_gskit_ - prefix for GSKit ones
- Curl_polarssl_ - prefix for PolarSSL ones
- Curl_cyassl_ - prefix for CyaSSL ones
- Curl_schannel_ - prefix for Schannel SSPI ones
- Curl_darwinssl_ - prefix for SecureTransport (Darwin) ones
-
- Note that this source code uses curlssl_* functions, and they are all
- defines/macros #defined by the lib-specific header files.
+
+ Note that this source code uses the functions of the configured SSL
+ backend via the global Curl_ssl instance.
"SSL/TLS Strong Encryption: An Introduction"
https://httpd.apache.org/docs/2.0/ssl/ssl_intro.html
@@ -98,9 +90,12 @@ Curl_ssl_config_matches(struct ssl_primary_config* data,
(data->version_max == needle->version_max) &&
(data->verifypeer == needle->verifypeer) &&
(data->verifyhost == needle->verifyhost) &&
+ (data->verifystatus == needle->verifystatus) &&
Curl_safe_strcasecompare(data->CApath, needle->CApath) &&
Curl_safe_strcasecompare(data->CAfile, needle->CAfile) &&
Curl_safe_strcasecompare(data->clientcert, needle->clientcert) &&
+ Curl_safe_strcasecompare(data->random_file, needle->random_file) &&
+ Curl_safe_strcasecompare(data->egdsocket, needle->egdsocket) &&
Curl_safe_strcasecompare(data->cipher_list, needle->cipher_list))
return TRUE;
@@ -111,42 +106,51 @@ bool
Curl_clone_primary_ssl_config(struct ssl_primary_config *source,
struct ssl_primary_config *dest)
{
- dest->verifyhost = source->verifyhost;
- dest->verifypeer = source->verifypeer;
dest->version = source->version;
dest->version_max = source->version_max;
+ dest->verifypeer = source->verifypeer;
+ dest->verifyhost = source->verifyhost;
+ dest->verifystatus = source->verifystatus;
+ dest->sessionid = source->sessionid;
- CLONE_STRING(CAfile);
CLONE_STRING(CApath);
- CLONE_STRING(cipher_list);
- CLONE_STRING(egdsocket);
- CLONE_STRING(random_file);
+ CLONE_STRING(CAfile);
CLONE_STRING(clientcert);
+ CLONE_STRING(random_file);
+ CLONE_STRING(egdsocket);
+ CLONE_STRING(cipher_list);
- /* Disable dest sessionid cache if a client cert is used, CVE-2016-5419. */
- dest->sessionid = (dest->clientcert ? false : source->sessionid);
return TRUE;
}
void Curl_free_primary_ssl_config(struct ssl_primary_config* sslc)
{
- Curl_safefree(sslc->CAfile);
Curl_safefree(sslc->CApath);
- Curl_safefree(sslc->cipher_list);
- Curl_safefree(sslc->egdsocket);
- Curl_safefree(sslc->random_file);
+ Curl_safefree(sslc->CAfile);
Curl_safefree(sslc->clientcert);
+ Curl_safefree(sslc->random_file);
+ Curl_safefree(sslc->egdsocket);
+ Curl_safefree(sslc->cipher_list);
}
+#ifdef USE_SSL
+static int multissl_init(const struct Curl_ssl *backend);
+#endif
+
int Curl_ssl_backend(void)
{
- return (int)CURL_SSL_BACKEND;
+#ifdef USE_SSL
+ multissl_init(NULL);
+ return Curl_ssl->info.id;
+#else
+ return (int)CURLSSLBACKEND_NONE;
+#endif
}
#ifdef USE_SSL
/* "global" init done? */
-static bool init_ssl=FALSE;
+static bool init_ssl = FALSE;
/**
* Global SSL init
@@ -161,7 +165,7 @@ int Curl_ssl_init(void)
return 1;
init_ssl = TRUE; /* never again */
- return curlssl_init();
+ return Curl_ssl->init();
}
@@ -170,7 +174,7 @@ void Curl_ssl_cleanup(void)
{
if(init_ssl) {
/* only cleanup if we did a previous init */
- curlssl_cleanup();
+ Curl_ssl->cleanup();
init_ssl = FALSE;
}
}
@@ -205,12 +209,20 @@ ssl_connect_init_proxy(struct connectdata *conn, int sockindex)
DEBUGASSERT(conn->bits.proxy_ssl_connected[sockindex]);
if(ssl_connection_complete == conn->ssl[sockindex].state &&
!conn->proxy_ssl[sockindex].use) {
-#if defined(HTTPS_PROXY_SUPPORT)
+ struct ssl_backend_data *pbdata;
+
+ if(!Curl_ssl->support_https_proxy)
+ return CURLE_NOT_BUILT_IN;
+
+ /* The pointers to the ssl backend data, which is opaque here, are swapped
+ rather than move the contents. */
+ pbdata = conn->proxy_ssl[sockindex].backend;
conn->proxy_ssl[sockindex] = conn->ssl[sockindex];
+
memset(&conn->ssl[sockindex], 0, sizeof(conn->ssl[sockindex]));
-#else
- return CURLE_NOT_BUILT_IN;
-#endif
+ memset(pbdata, 0, Curl_ssl->sizeof_ssl_backend_data);
+
+ conn->ssl[sockindex].backend = pbdata;
}
return CURLE_OK;
}
@@ -233,7 +245,7 @@ Curl_ssl_connect(struct connectdata *conn, int sockindex)
conn->ssl[sockindex].use = TRUE;
conn->ssl[sockindex].state = ssl_connection_negotiating;
- result = curlssl_connect(conn, sockindex);
+ result = Curl_ssl->connect(conn, sockindex);
if(!result)
Curl_pgrsTime(conn->data, TIMER_APPCONNECT); /* SSL is connected */
@@ -257,12 +269,7 @@ Curl_ssl_connect_nonblocking(struct connectdata *conn, int sockindex,
/* mark this is being ssl requested from here on. */
conn->ssl[sockindex].use = TRUE;
-#ifdef curlssl_connect_nonblocking
- result = curlssl_connect_nonblocking(conn, sockindex, done);
-#else
- *done = TRUE; /* fallback to BLOCKING */
- result = curlssl_connect(conn, sockindex);
-#endif /* non-blocking connect support */
+ result = Curl_ssl->connect_nonblocking(conn, sockindex, done);
if(!result && *done)
Curl_pgrsTime(conn->data, TIMER_APPCONNECT); /* SSL is connected */
return result;
@@ -361,7 +368,7 @@ void Curl_ssl_kill_session(struct curl_ssl_session *session)
/* defensive check */
/* free the ID the SSL-layer specific way */
- curlssl_session_free(session->sessionid);
+ Curl_ssl->session_free(session->sessionid);
session->sessionid = NULL;
session->age = 0; /* fresh */
@@ -379,7 +386,7 @@ void Curl_ssl_kill_session(struct curl_ssl_session *session)
void Curl_ssl_delsessionid(struct connectdata *conn, void *ssl_sessionid)
{
size_t i;
- struct Curl_easy *data=conn->data;
+ struct Curl_easy *data = conn->data;
for(i = 0; i < data->set.general_ssl.max_ssl_sessions; i++) {
struct curl_ssl_session *check = &data->state.session[i];
@@ -403,9 +410,9 @@ CURLcode Curl_ssl_addsessionid(struct connectdata *conn,
int sockindex)
{
size_t i;
- struct Curl_easy *data=conn->data; /* the mother of all structs */
+ struct Curl_easy *data = conn->data; /* the mother of all structs */
struct curl_ssl_session *store = &data->state.session[0];
- long oldest_age=data->state.session[0].age; /* zero if unused */
+ long oldest_age = data->state.session[0].age; /* zero if unused */
char *clone_host;
char *clone_conn_to_host;
int conn_to_port;
@@ -499,7 +506,7 @@ void Curl_ssl_close_all(struct Curl_easy *data)
Curl_safefree(data->state.session);
}
- curlssl_close_all(data);
+ Curl_ssl->close_all(data);
}
#if defined(USE_OPENSSL) || defined(USE_GNUTLS) || defined(USE_SCHANNEL) || \
@@ -542,12 +549,12 @@ int Curl_ssl_getsock(struct connectdata *conn,
void Curl_ssl_close(struct connectdata *conn, int sockindex)
{
DEBUGASSERT((sockindex <= 1) && (sockindex >= -1));
- curlssl_close(conn, sockindex);
+ Curl_ssl->close_one(conn, sockindex);
}
CURLcode Curl_ssl_shutdown(struct connectdata *conn, int sockindex)
{
- if(curlssl_shutdown(conn, sockindex))
+ if(Curl_ssl->shutdown(conn, sockindex))
return CURLE_SSL_SHUTDOWN_FAILED;
conn->ssl[sockindex].use = FALSE; /* get back to ordinary socket usage */
@@ -563,20 +570,20 @@ CURLcode Curl_ssl_shutdown(struct connectdata *conn, int sockindex)
*/
CURLcode Curl_ssl_set_engine(struct Curl_easy *data, const char *engine)
{
- return curlssl_set_engine(data, engine);
+ return Curl_ssl->set_engine(data, engine);
}
/* Selects the default SSL crypto engine
*/
CURLcode Curl_ssl_set_engine_default(struct Curl_easy *data)
{
- return curlssl_set_engine_default(data);
+ return Curl_ssl->set_engine_default(data);
}
/* Return list of OpenSSL crypto engine names. */
struct curl_slist *Curl_ssl_engines_list(struct Curl_easy *data)
{
- return curlssl_engines_list(data);
+ return Curl_ssl->engines_list(data);
}
/*
@@ -602,9 +609,15 @@ CURLcode Curl_ssl_initsessions(struct Curl_easy *data, size_t amount)
return CURLE_OK;
}
+static size_t Curl_multissl_version(char *buffer, size_t size);
+
size_t Curl_ssl_version(char *buffer, size_t size)
{
- return curlssl_version(buffer, size);
+#ifdef CURL_WITH_MULTI_SSL
+ return Curl_multissl_version(buffer, size);
+#else
+ return Curl_ssl->version(buffer, size);
+#endif
}
/*
@@ -617,13 +630,13 @@ size_t Curl_ssl_version(char *buffer, size_t size)
*/
int Curl_ssl_check_cxn(struct connectdata *conn)
{
- return curlssl_check_cxn(conn);
+ return Curl_ssl->check_cxn(conn);
}
bool Curl_ssl_data_pending(const struct connectdata *conn,
int connindex)
{
- return curlssl_data_pending(conn, connindex);
+ return Curl_ssl->data_pending(conn, connindex);
}
void Curl_ssl_free_certinfo(struct Curl_easy *data)
@@ -633,7 +646,7 @@ void Curl_ssl_free_certinfo(struct Curl_easy *data)
if(ci->num_of_certs) {
/* free all individual lists used */
- for(i=0; i<ci->num_of_certs; i++) {
+ for(i = 0; i<ci->num_of_certs; i++) {
curl_slist_free_all(ci->certinfo[i]);
ci->certinfo[i] = NULL;
}
@@ -687,7 +700,7 @@ CURLcode Curl_ssl_push_certinfo_len(struct Curl_easy *data,
snprintf(output, outlen, "%s:", label);
/* memcpy the value (it might not be zero terminated) */
- memcpy(&output[labellen+1], value, valuelen);
+ memcpy(&output[labellen + 1], value, valuelen);
/* zero terminate the output */
output[labellen + 1 + valuelen] = 0;
@@ -721,7 +734,7 @@ CURLcode Curl_ssl_random(struct Curl_easy *data,
unsigned char *entropy,
size_t length)
{
- return curlssl_random(data, entropy, length);
+ return Curl_ssl->random(data, entropy, length);
}
/*
@@ -796,12 +809,10 @@ CURLcode Curl_pin_peer_pubkey(struct Curl_easy *data,
size_t size, pem_len;
CURLcode pem_read;
CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;
-#ifdef curlssl_sha256sum
CURLcode encode;
size_t encodedlen, pinkeylen;
char *encoded, *pinkeycopy, *begin_pos, *end_pos;
unsigned char *sha256sumdigest = NULL;
-#endif
/* if a path wasn't specified, don't pin */
if(!pinnedpubkey)
@@ -811,15 +822,20 @@ CURLcode Curl_pin_peer_pubkey(struct Curl_easy *data,
/* only do this if pinnedpubkey starts with "sha256//", length 8 */
if(strncmp(pinnedpubkey, "sha256//", 8) == 0) {
-#ifdef curlssl_sha256sum
+ if(!Curl_ssl->sha256sum) {
+ /* without sha256 support, this cannot match */
+ return result;
+ }
+
/* compute sha256sum of public key */
- sha256sumdigest = malloc(SHA256_DIGEST_LENGTH);
+ sha256sumdigest = malloc(CURL_SHA256_DIGEST_LENGTH);
if(!sha256sumdigest)
return CURLE_OUT_OF_MEMORY;
- curlssl_sha256sum(pubkey, pubkeylen,
- sha256sumdigest, SHA256_DIGEST_LENGTH);
+ Curl_ssl->sha256sum(pubkey, pubkeylen,
+ sha256sumdigest, CURL_SHA256_DIGEST_LENGTH);
encode = Curl_base64_encode(data, (char *)sha256sumdigest,
- SHA256_DIGEST_LENGTH, &encoded, &encodedlen);
+ CURL_SHA256_DIGEST_LENGTH, &encoded,
+ &encodedlen);
Curl_safefree(sha256sumdigest);
if(encode)
@@ -864,10 +880,6 @@ CURLcode Curl_pin_peer_pubkey(struct Curl_easy *data,
} while(end_pos && begin_pos);
Curl_safefree(encoded);
Curl_safefree(pinkeycopy);
-#else
- /* without sha256 support, this cannot match */
- (void)data;
-#endif
return result;
}
@@ -943,45 +955,372 @@ CURLcode Curl_ssl_md5sum(unsigned char *tmp, /* input */
unsigned char *md5sum, /* output */
size_t md5len)
{
-#ifdef curlssl_md5sum
- curlssl_md5sum(tmp, tmplen, md5sum, md5len);
-#else
+ return Curl_ssl->md5sum(tmp, tmplen, md5sum, md5len);
+}
+#endif
+
+/*
+ * Check whether the SSL backend supports the status_request extension.
+ */
+bool Curl_ssl_cert_status_request(void)
+{
+ return Curl_ssl->cert_status_request();
+}
+
+/*
+ * Check whether the SSL backend supports false start.
+ */
+bool Curl_ssl_false_start(void)
+{
+ return Curl_ssl->false_start();
+}
+
+/*
+ * Default implementations for unsupported functions.
+ */
+
+int Curl_none_init(void)
+{
+ return 1;
+}
+
+void Curl_none_cleanup(void)
+{ }
+
+int Curl_none_shutdown(struct connectdata *conn UNUSED_PARAM,
+ int sockindex UNUSED_PARAM)
+{
+ (void)conn;
+ (void)sockindex;
+ return 0;
+}
+
+int Curl_none_check_cxn(struct connectdata *conn UNUSED_PARAM)
+{
+ (void)conn;
+ return -1;
+}
+
+CURLcode Curl_none_random(struct Curl_easy *data UNUSED_PARAM,
+ unsigned char *entropy UNUSED_PARAM,
+ size_t length UNUSED_PARAM)
+{
+ (void)data;
+ (void)entropy;
+ (void)length;
+ return CURLE_NOT_BUILT_IN;
+}
+
+void Curl_none_close_all(struct Curl_easy *data UNUSED_PARAM)
+{
+ (void)data;
+}
+
+void Curl_none_session_free(void *ptr UNUSED_PARAM)
+{
+ (void)ptr;
+}
+
+bool Curl_none_data_pending(const struct connectdata *conn UNUSED_PARAM,
+ int connindex UNUSED_PARAM)
+{
+ (void)conn;
+ (void)connindex;
+ return 0;
+}
+
+bool Curl_none_cert_status_request(void)
+{
+ return FALSE;
+}
+
+CURLcode Curl_none_set_engine(struct Curl_easy *data UNUSED_PARAM,
+ const char *engine UNUSED_PARAM)
+{
+ (void)data;
+ (void)engine;
+ return CURLE_NOT_BUILT_IN;
+}
+
+CURLcode Curl_none_set_engine_default(struct Curl_easy *data UNUSED_PARAM)
+{
+ (void)data;
+ return CURLE_NOT_BUILT_IN;
+}
+
+struct curl_slist *Curl_none_engines_list(struct Curl_easy *data UNUSED_PARAM)
+{
+ (void)data;
+ return (struct curl_slist *)NULL;
+}
+
+bool Curl_none_false_start(void)
+{
+ return FALSE;
+}
+
+#ifndef CURL_DISABLE_CRYPTO_AUTH
+CURLcode Curl_none_md5sum(unsigned char *input, size_t inputlen,
+ unsigned char *md5sum, size_t md5len UNUSED_PARAM)
+{
MD5_context *MD5pw;
- (void) md5len;
+ (void)md5len;
MD5pw = Curl_MD5_init(Curl_DIGEST_MD5);
if(!MD5pw)
return CURLE_OUT_OF_MEMORY;
- Curl_MD5_update(MD5pw, tmp, curlx_uztoui(tmplen));
+ Curl_MD5_update(MD5pw, input, curlx_uztoui(inputlen));
Curl_MD5_final(MD5pw, md5sum);
-#endif
return CURLE_OK;
}
+#else
+CURLcode Curl_none_md5sum(unsigned char *input UNUSED_PARAM,
+ size_t inputlen UNUSED_PARAM,
+ unsigned char *md5sum UNUSED_PARAM,
+ size_t md5len UNUSED_PARAM)
+{
+ (void)input;
+ (void)inputlen;
+ (void)md5sum;
+ (void)md5len;
+ return CURLE_NOT_BUILT_IN;
+}
#endif
-/*
- * Check whether the SSL backend supports the status_request extension.
- */
-bool Curl_ssl_cert_status_request(void)
+static int Curl_multissl_init(void)
+{
+ if(multissl_init(NULL))
+ return 1;
+ return Curl_ssl->init();
+}
+
+static CURLcode Curl_multissl_connect(struct connectdata *conn, int sockindex)
+{
+ if(multissl_init(NULL))
+ return CURLE_FAILED_INIT;
+ return Curl_ssl->connect(conn, sockindex);
+}
+
+static CURLcode Curl_multissl_connect_nonblocking(struct connectdata *conn,
+ int sockindex, bool *done)
{
-#ifdef curlssl_cert_status_request
- return curlssl_cert_status_request();
+ if(multissl_init(NULL))
+ return CURLE_FAILED_INIT;
+ return Curl_ssl->connect_nonblocking(conn, sockindex, done);
+}
+
+static void *Curl_multissl_get_internals(struct ssl_connect_data *connssl,
+ CURLINFO info)
+{
+ if(multissl_init(NULL))
+ return NULL;
+ return Curl_ssl->get_internals(connssl, info);
+}
+
+static void Curl_multissl_close(struct connectdata *conn, int sockindex)
+{
+ if(multissl_init(NULL))
+ return;
+ Curl_ssl->close_one(conn, sockindex);
+}
+
+static const struct Curl_ssl Curl_ssl_multi = {
+ { CURLSSLBACKEND_NONE, "multi" }, /* info */
+
+ 0, /* have_ca_path */
+ 0, /* have_certinfo */
+ 0, /* have_pinnedpubkey */
+ 0, /* have_ssl_ctx */
+ 0, /* support_https_proxy */
+
+ (size_t)-1, /* something insanely large to be on the safe side */
+
+ Curl_multissl_init, /* init */
+ Curl_none_cleanup, /* cleanup */
+ Curl_multissl_version, /* version */
+ Curl_none_check_cxn, /* check_cxn */
+ Curl_none_shutdown, /* shutdown */
+ Curl_none_data_pending, /* data_pending */
+ Curl_none_random, /* random */
+ Curl_none_cert_status_request, /* cert_status_request */
+ Curl_multissl_connect, /* connect */
+ Curl_multissl_connect_nonblocking, /* connect_nonblocking */
+ Curl_multissl_get_internals, /* get_internals */
+ Curl_multissl_close, /* close_one */
+ Curl_none_close_all, /* close_all */
+ Curl_none_session_free, /* session_free */
+ Curl_none_set_engine, /* set_engine */
+ Curl_none_set_engine_default, /* set_engine_default */
+ Curl_none_engines_list, /* engines_list */
+ Curl_none_false_start, /* false_start */
+ Curl_none_md5sum, /* md5sum */
+ NULL /* sha256sum */
+};
+
+const struct Curl_ssl *Curl_ssl =
+#if defined(CURL_WITH_MULTI_SSL)
+ &Curl_ssl_multi;
+#elif defined(USE_AXTLS)
+ &Curl_ssl_axtls;
+#elif defined(USE_CYASSL)
+ &Curl_ssl_cyassl;
+#elif defined(USE_DARWINSSL)
+ &Curl_ssl_darwinssl;
+#elif defined(USE_GNUTLS)
+ &Curl_ssl_gnutls;
+#elif defined(USE_GSKIT)
+ &Curl_ssl_gskit;
+#elif defined(USE_MBEDTLS)
+ &Curl_ssl_mbedtls;
+#elif defined(USE_NSS)
+ &Curl_ssl_nss;
+#elif defined(USE_OPENSSL)
+ &Curl_ssl_openssl;
+#elif defined(USE_POLARSSL)
+ &Curl_ssl_polarssl;
+#elif defined(USE_SCHANNEL)
+ &Curl_ssl_schannel;
#else
- return FALSE;
+#error "Missing struct Curl_ssl for selected SSL backend"
+#endif
+
+static const struct Curl_ssl *available_backends[] = {
+#if defined(USE_AXTLS)
+ &Curl_ssl_axtls,
+#endif
+#if defined(USE_CYASSL)
+ &Curl_ssl_cyassl,
+#endif
+#if defined(USE_DARWINSSL)
+ &Curl_ssl_darwinssl,
#endif
+#if defined(USE_GNUTLS)
+ &Curl_ssl_gnutls,
+#endif
+#if defined(USE_GSKIT)
+ &Curl_ssl_gskit,
+#endif
+#if defined(USE_MBEDTLS)
+ &Curl_ssl_mbedtls,
+#endif
+#if defined(USE_NSS)
+ &Curl_ssl_nss,
+#endif
+#if defined(USE_OPENSSL)
+ &Curl_ssl_openssl,
+#endif
+#if defined(USE_POLARSSL)
+ &Curl_ssl_polarssl,
+#endif
+#if defined(USE_SCHANNEL)
+ &Curl_ssl_schannel,
+#endif
+ NULL
+};
+
+static size_t Curl_multissl_version(char *buffer, size_t size)
+{
+ static const struct Curl_ssl *selected;
+ static char backends[200];
+ static size_t total;
+ const struct Curl_ssl *current;
+
+ current = Curl_ssl == &Curl_ssl_multi ? available_backends[0] : Curl_ssl;
+
+ if(current != selected) {
+ char *p = backends;
+ int i;
+
+ selected = current;
+
+ for(i = 0; available_backends[i]; i++) {
+ if(i)
+ *(p++) = ' ';
+ if(selected != available_backends[i])
+ *(p++) = '(';
+ p += available_backends[i]->version(p, backends + sizeof(backends) - p);
+ if(selected != available_backends[i])
+ *(p++) = ')';
+ }
+ *p = '\0';
+ total = p - backends;
+ }
+
+ if(size < total)
+ memcpy(buffer, backends, total + 1);
+ else {
+ memcpy(buffer, backends, size - 1);
+ buffer[size - 1] = '\0';
+ }
+
+ return total;
}
-/*
- * Check whether the SSL backend supports false start.
- */
-bool Curl_ssl_false_start(void)
+static int multissl_init(const struct Curl_ssl *backend)
{
-#ifdef curlssl_false_start
- return curlssl_false_start();
-#else
- return FALSE;
+ const char *env;
+ int i;
+
+ if(Curl_ssl != &Curl_ssl_multi)
+ return 1;
+
+ if(backend) {
+ Curl_ssl = backend;
+ return 0;
+ }
+
+ if(!available_backends[0])
+ return 1;
+
+ env = getenv("CURL_SSL_BACKEND");
+#ifdef CURL_DEFAULT_SSL_BACKEND
+ if(!env)
+ env = CURL_DEFAULT_SSL_BACKEND;
#endif
+ if(env) {
+ for(i = 0; available_backends[i]; i++) {
+ if(strcasecompare(env, available_backends[i]->info.name)) {
+ Curl_ssl = available_backends[i];
+ return 0;
+ }
+ }
+ }
+
+ /* Fall back to first available backend */
+ Curl_ssl = available_backends[0];
+ return 0;
+}
+
+CURLsslset curl_global_sslset(curl_sslbackend id, const char *name,
+ const curl_ssl_backend ***avail)
+{
+ int i;
+
+ if(Curl_ssl != &Curl_ssl_multi)
+ return id == Curl_ssl->info.id ? CURLSSLSET_OK : CURLSSLSET_TOO_LATE;
+
+ for(i = 0; available_backends[i]; i++) {
+ if(available_backends[i]->info.id == id ||
+ (name && strcasecompare(available_backends[i]->info.name, name))) {
+ multissl_init(available_backends[i]);
+ return CURLSSLSET_OK;
+ }
+ }
+
+ if(avail)
+ *avail = (const curl_ssl_backend **)&available_backends;
+ return CURLSSLSET_UNKNOWN_BACKEND;
+}
+
+#else /* USE_SSL */
+CURLsslset curl_global_sslset(curl_sslbackend id, const char *name,
+ const curl_ssl_backend ***avail)
+{
+ (void)id;
+ (void)name;
+ (void)avail;
+ return CURLSSLSET_NO_BACKENDS;
}
-#endif /* USE_SSL */
+#endif /* !USE_SSL */