summaryrefslogtreecommitdiff
path: root/Utilities/cmcurl/lib/vtls/vtls.c
diff options
context:
space:
mode:
Diffstat (limited to 'Utilities/cmcurl/lib/vtls/vtls.c')
-rw-r--r--Utilities/cmcurl/lib/vtls/vtls.c753
1 files changed, 538 insertions, 215 deletions
diff --git a/Utilities/cmcurl/lib/vtls/vtls.c b/Utilities/cmcurl/lib/vtls/vtls.c
index 9dee5aa3b3..873ee6bac7 100644
--- a/Utilities/cmcurl/lib/vtls/vtls.c
+++ b/Utilities/cmcurl/lib/vtls/vtls.c
@@ -51,8 +51,10 @@
#endif
#include "urldata.h"
+#include "cfilters.h"
#include "vtls.h" /* generic SSL protos etc */
+#include "vtls_int.h"
#include "slist.h"
#include "sendf.h"
#include "strcase.h"
@@ -150,11 +152,11 @@ Curl_ssl_config_matches(struct ssl_primary_config *data,
!Curl_timestrcmp(data->password, needle->password) &&
(data->authtype == needle->authtype) &&
#endif
- Curl_safe_strcasecompare(data->cipher_list, needle->cipher_list) &&
- Curl_safe_strcasecompare(data->cipher_list13, needle->cipher_list13) &&
- Curl_safe_strcasecompare(data->curves, needle->curves) &&
- Curl_safe_strcasecompare(data->CRLfile, needle->CRLfile) &&
- Curl_safe_strcasecompare(data->pinned_key, needle->pinned_key))
+ strcasecompare(data->cipher_list, needle->cipher_list) &&
+ strcasecompare(data->cipher_list13, needle->cipher_list13) &&
+ strcasecompare(data->curves, needle->curves) &&
+ strcasecompare(data->CRLfile, needle->CRLfile) &&
+ strcasecompare(data->pinned_key, needle->pinned_key))
return TRUE;
return FALSE;
@@ -291,89 +293,68 @@ static bool ssl_prefs_check(struct Curl_easy *data)
return TRUE;
}
-#ifndef CURL_DISABLE_PROXY
-static CURLcode
-ssl_connect_init_proxy(struct connectdata *conn, int sockindex)
+static struct ssl_connect_data *cf_ctx_new(struct Curl_easy *data)
{
- DEBUGASSERT(conn->bits.proxy_ssl_connected[sockindex]);
- if(ssl_connection_complete == conn->ssl[sockindex].state &&
- !conn->proxy_ssl[sockindex].use) {
- struct ssl_backend_data *pbdata;
-
- if(!(Curl_ssl->supports & SSLSUPP_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];
+ struct ssl_connect_data *ctx;
- DEBUGASSERT(pbdata != NULL);
+ (void)data;
+ ctx = calloc(1, sizeof(*ctx));
+ if(!ctx)
+ return NULL;
- memset(&conn->ssl[sockindex], 0, sizeof(conn->ssl[sockindex]));
- memset(pbdata, 0, Curl_ssl->sizeof_ssl_backend_data);
+ ctx->backend = calloc(1, Curl_ssl->sizeof_ssl_backend_data);
+ if(!ctx->backend) {
+ free(ctx);
+ return NULL;
+ }
+ return ctx;
+}
- conn->ssl[sockindex].backend = pbdata;
+static void cf_ctx_free(struct ssl_connect_data *ctx)
+{
+ if(ctx) {
+ free(ctx->backend);
+ free(ctx);
}
- return CURLE_OK;
}
-#endif
-CURLcode
-Curl_ssl_connect(struct Curl_easy *data, struct connectdata *conn,
- int sockindex)
+static void cf_ctx_set_data(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
{
- CURLcode result;
+ if(cf->ctx)
+ ((struct ssl_connect_data *)cf->ctx)->call_data = data;
+}
-#ifndef CURL_DISABLE_PROXY
- if(conn->bits.proxy_ssl_connected[sockindex]) {
- result = ssl_connect_init_proxy(conn, sockindex);
- if(result)
- return result;
- }
-#endif
+static CURLcode ssl_connect(struct Curl_cfilter *cf, struct Curl_easy *data)
+{
+ struct ssl_connect_data *connssl = cf->ctx;
+ CURLcode result;
if(!ssl_prefs_check(data))
return CURLE_SSL_CONNECT_ERROR;
/* mark this is being ssl-enabled from here on. */
- conn->ssl[sockindex].use = TRUE;
- conn->ssl[sockindex].state = ssl_connection_negotiating;
+ connssl->state = ssl_connection_negotiating;
- result = Curl_ssl->connect_blocking(data, conn, sockindex);
+ result = Curl_ssl->connect_blocking(cf, data);
- if(!result)
+ if(!result) {
Curl_pgrsTime(data, TIMER_APPCONNECT); /* SSL is connected */
- else
- conn->ssl[sockindex].use = FALSE;
+ DEBUGASSERT(connssl->state == ssl_connection_complete);
+ }
return result;
}
-CURLcode
-Curl_ssl_connect_nonblocking(struct Curl_easy *data, struct connectdata *conn,
- bool isproxy, int sockindex, bool *done)
+static CURLcode
+ssl_connect_nonblocking(struct Curl_cfilter *cf, struct Curl_easy *data,
+ bool *done)
{
- CURLcode result;
-
-#ifndef CURL_DISABLE_PROXY
- if(conn->bits.proxy_ssl_connected[sockindex]) {
- result = ssl_connect_init_proxy(conn, sockindex);
- if(result)
- return result;
- }
-#endif
if(!ssl_prefs_check(data))
return CURLE_SSL_CONNECT_ERROR;
/* mark this is being ssl requested from here on. */
- conn->ssl[sockindex].use = TRUE;
- result = Curl_ssl->connect_nonblocking(data, conn, sockindex, done);
- if(result)
- conn->ssl[sockindex].use = FALSE;
- else if(*done && !isproxy)
- Curl_pgrsTime(data, TIMER_APPCONNECT); /* SSL is connected */
- return result;
+ return Curl_ssl->connect_nonblocking(cf, data, done);
}
/*
@@ -398,42 +379,26 @@ void Curl_ssl_sessionid_unlock(struct Curl_easy *data)
* Check if there's a session ID for the given connection in the cache, and if
* there's one suitable, it is provided. Returns TRUE when no entry matched.
*/
-bool Curl_ssl_getsessionid(struct Curl_easy *data,
- struct connectdata *conn,
- const bool isProxy,
+bool Curl_ssl_getsessionid(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
void **ssl_sessionid,
- size_t *idsize, /* set 0 if unknown */
- int sockindex)
+ size_t *idsize) /* set 0 if unknown */
{
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
+ struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
struct Curl_ssl_session *check;
size_t i;
long *general_age;
bool no_match = TRUE;
-#ifndef CURL_DISABLE_PROXY
- struct ssl_primary_config * const ssl_config = isProxy ?
- &conn->proxy_ssl_config :
- &conn->ssl_config;
- const char * const name = isProxy ?
- conn->http_proxy.host.name : conn->host.name;
- int port = isProxy ? (int)conn->port : conn->remote_port;
-#else
- /* no proxy support */
- struct ssl_primary_config * const ssl_config = &conn->ssl_config;
- const char * const name = conn->host.name;
- int port = conn->remote_port;
-#endif
- (void)sockindex;
*ssl_sessionid = NULL;
-
-#ifdef CURL_DISABLE_PROXY
- if(isProxy)
+ if(!ssl_config)
return TRUE;
-#endif
- DEBUGASSERT(SSL_SET_OPTION(primary.sessionid));
+ DEBUGASSERT(ssl_config->primary.sessionid);
- if(!SSL_SET_OPTION(primary.sessionid) || !data->state.session)
+ if(!ssl_config->primary.sessionid || !data->state.session)
/* session ID re-use is disabled or the session cache has not been
setup */
return TRUE;
@@ -449,16 +414,16 @@ bool Curl_ssl_getsessionid(struct Curl_easy *data,
if(!check->sessionid)
/* not session ID means blank entry */
continue;
- if(strcasecompare(name, check->name) &&
- ((!conn->bits.conn_to_host && !check->conn_to_host) ||
- (conn->bits.conn_to_host && check->conn_to_host &&
- strcasecompare(conn->conn_to_host.name, check->conn_to_host))) &&
- ((!conn->bits.conn_to_port && check->conn_to_port == -1) ||
- (conn->bits.conn_to_port && check->conn_to_port != -1 &&
- conn->conn_to_port == check->conn_to_port)) &&
- (port == check->remote_port) &&
- strcasecompare(conn->handler->scheme, check->scheme) &&
- Curl_ssl_config_matches(ssl_config, &check->ssl_config)) {
+ if(strcasecompare(connssl->hostname, check->name) &&
+ ((!cf->conn->bits.conn_to_host && !check->conn_to_host) ||
+ (cf->conn->bits.conn_to_host && check->conn_to_host &&
+ strcasecompare(cf->conn->conn_to_host.name, check->conn_to_host))) &&
+ ((!cf->conn->bits.conn_to_port && check->conn_to_port == -1) ||
+ (cf->conn->bits.conn_to_port && check->conn_to_port != -1 &&
+ cf->conn->conn_to_port == check->conn_to_port)) &&
+ (connssl->port == check->remote_port) &&
+ strcasecompare(cf->conn->handler->scheme, check->scheme) &&
+ Curl_ssl_config_matches(conn_config, &check->ssl_config)) {
/* yes, we have a session ID! */
(*general_age)++; /* increase general age */
check->age = *general_age; /* set this as used in this age */
@@ -470,10 +435,10 @@ bool Curl_ssl_getsessionid(struct Curl_easy *data,
}
}
- DEBUGF(infof(data, "%s Session ID in cache for %s %s://%s:%d",
+ DEBUGF(infof(data, DMSG(data, "%s Session ID in cache for %s %s://%s:%d"),
no_match? "Didn't find": "Found",
- isProxy ? "proxy" : "host",
- conn->handler->scheme, name, port));
+ Curl_ssl_cf_is_proxy(cf) ? "proxy" : "host",
+ cf->conn->handler->scheme, connssl->hostname, connssl->port));
return no_match;
}
@@ -521,14 +486,15 @@ void Curl_ssl_delsessionid(struct Curl_easy *data, void *ssl_sessionid)
* layer. Curl_XXXX_session_free() will be called to free/kill the session ID
* later on.
*/
-CURLcode Curl_ssl_addsessionid(struct Curl_easy *data,
- struct connectdata *conn,
- const bool isProxy,
+CURLcode Curl_ssl_addsessionid(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
void *ssl_sessionid,
size_t idsize,
- int sockindex,
bool *added)
{
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
+ struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
size_t i;
struct Curl_ssl_session *store;
long oldest_age;
@@ -536,17 +502,6 @@ CURLcode Curl_ssl_addsessionid(struct Curl_easy *data,
char *clone_conn_to_host;
int conn_to_port;
long *general_age;
-#ifndef CURL_DISABLE_PROXY
- struct ssl_primary_config * const ssl_config = isProxy ?
- &conn->proxy_ssl_config :
- &conn->ssl_config;
- const char *hostname = isProxy ? conn->http_proxy.host.name :
- conn->host.name;
-#else
- struct ssl_primary_config * const ssl_config = &conn->ssl_config;
- const char *hostname = conn->host.name;
-#endif
- (void)sockindex;
if(added)
*added = FALSE;
@@ -556,14 +511,15 @@ CURLcode Curl_ssl_addsessionid(struct Curl_easy *data,
store = &data->state.session[0];
oldest_age = data->state.session[0].age; /* zero if unused */
- DEBUGASSERT(SSL_SET_OPTION(primary.sessionid));
+ (void)ssl_config;
+ DEBUGASSERT(ssl_config->primary.sessionid);
- clone_host = strdup(hostname);
+ clone_host = strdup(connssl->hostname);
if(!clone_host)
return CURLE_OUT_OF_MEMORY; /* bail out */
- if(conn->bits.conn_to_host) {
- clone_conn_to_host = strdup(conn->conn_to_host.name);
+ if(cf->conn->bits.conn_to_host) {
+ clone_conn_to_host = strdup(cf->conn->conn_to_host.name);
if(!clone_conn_to_host) {
free(clone_host);
return CURLE_OUT_OF_MEMORY; /* bail out */
@@ -572,8 +528,8 @@ CURLcode Curl_ssl_addsessionid(struct Curl_easy *data,
else
clone_conn_to_host = NULL;
- if(conn->bits.conn_to_port)
- conn_to_port = conn->conn_to_port;
+ if(cf->conn->bits.conn_to_port)
+ conn_to_port = cf->conn->conn_to_port;
else
conn_to_port = -1;
@@ -613,10 +569,10 @@ CURLcode Curl_ssl_addsessionid(struct Curl_easy *data,
store->conn_to_host = clone_conn_to_host; /* clone connect to host name */
store->conn_to_port = conn_to_port; /* connect to port number */
/* port number */
- store->remote_port = isProxy ? (int)conn->port : conn->remote_port;
- store->scheme = conn->handler->scheme;
+ store->remote_port = connssl->port;
+ store->scheme = cf->conn->handler->scheme;
- if(!Curl_clone_primary_ssl_config(ssl_config, &store->ssl_config)) {
+ if(!Curl_clone_primary_ssl_config(conn_config, &store->ssl_config)) {
Curl_free_primary_ssl_config(&store->ssl_config);
store->sessionid = NULL; /* let caller free sessionid */
free(clone_host);
@@ -627,32 +583,16 @@ CURLcode Curl_ssl_addsessionid(struct Curl_easy *data,
if(added)
*added = TRUE;
- DEBUGF(infof(data, "Added Session ID to cache for %s://%s:%d [%s]",
- store->scheme, store->name, store->remote_port,
- isProxy ? "PROXY" : "server"));
+ DEBUGF(infof(data, DMSG(data, "Added Session ID to cache for %s://%s:%d"
+ " [%s]"), store->scheme, store->name, store->remote_port,
+ Curl_ssl_cf_is_proxy(cf) ? "PROXY" : "server"));
return CURLE_OK;
}
-void Curl_ssl_associate_conn(struct Curl_easy *data,
- struct connectdata *conn)
+void Curl_free_multi_ssl_backend_data(struct multi_ssl_backend_data *mbackend)
{
- if(Curl_ssl->associate_connection) {
- Curl_ssl->associate_connection(data, conn, FIRSTSOCKET);
- if((conn->sock[SECONDARYSOCKET] != CURL_SOCKET_BAD) &&
- conn->bits.sock_accepted)
- Curl_ssl->associate_connection(data, conn, SECONDARYSOCKET);
- }
-}
-
-void Curl_ssl_detach_conn(struct Curl_easy *data,
- struct connectdata *conn)
-{
- if(Curl_ssl->disassociate_connection) {
- Curl_ssl->disassociate_connection(data, FIRSTSOCKET);
- if((conn->sock[SECONDARYSOCKET] != CURL_SOCKET_BAD) &&
- conn->bits.sock_accepted)
- Curl_ssl->disassociate_connection(data, SECONDARYSOCKET);
- }
+ if(Curl_ssl->free_multi_ssl_backend_data && mbackend)
+ Curl_ssl->free_multi_ssl_backend_data(mbackend);
}
void Curl_ssl_close_all(struct Curl_easy *data)
@@ -671,47 +611,26 @@ void Curl_ssl_close_all(struct Curl_easy *data)
Curl_ssl->close_all(data);
}
-int Curl_ssl_getsock(struct connectdata *conn, curl_socket_t *socks)
+int Curl_ssl_get_select_socks(struct Curl_cfilter *cf, struct Curl_easy *data,
+ curl_socket_t *socks)
{
- struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET];
+ struct ssl_connect_data *connssl = cf->ctx;
+ (void)data;
if(connssl->connecting_state == ssl_connect_2_writing) {
/* write mode */
- socks[0] = conn->sock[FIRSTSOCKET];
+ socks[0] = cf->conn->sock[FIRSTSOCKET];
return GETSOCK_WRITESOCK(0);
}
if(connssl->connecting_state == ssl_connect_2_reading) {
/* read mode */
- socks[0] = conn->sock[FIRSTSOCKET];
+ socks[0] = cf->conn->sock[FIRSTSOCKET];
return GETSOCK_READSOCK(0);
}
return GETSOCK_BLANK;
}
-void Curl_ssl_close(struct Curl_easy *data, struct connectdata *conn,
- int sockindex)
-{
- DEBUGASSERT((sockindex <= 1) && (sockindex >= -1));
- Curl_ssl->close_one(data, conn, sockindex);
- conn->ssl[sockindex].state = ssl_connection_none;
-}
-
-CURLcode Curl_ssl_shutdown(struct Curl_easy *data, struct connectdata *conn,
- int sockindex)
-{
- if(Curl_ssl->shut_down(data, conn, sockindex))
- return CURLE_SSL_SHUTDOWN_FAILED;
-
- conn->ssl[sockindex].use = FALSE; /* get back to ordinary socket usage */
- conn->ssl[sockindex].state = ssl_connection_none;
-
- conn->recv[sockindex] = Curl_recv_plain;
- conn->send[sockindex] = Curl_send_plain;
-
- return CURLE_OK;
-}
-
/* Selects an SSL crypto engine
*/
CURLcode Curl_ssl_set_engine(struct Curl_easy *data, const char *engine)
@@ -774,15 +693,10 @@ void Curl_ssl_version(char *buffer, size_t size)
* 0 means the connection has been closed
* -1 means the connection status is unknown
*/
-int Curl_ssl_check_cxn(struct connectdata *conn)
+int Curl_ssl_check_cxn(struct Curl_easy *data, struct connectdata *conn)
{
- return Curl_ssl->check_cxn(conn);
-}
-
-bool Curl_ssl_data_pending(const struct connectdata *conn,
- int connindex)
-{
- return Curl_ssl->data_pending(conn, connindex);
+ struct Curl_cfilter *cf = Curl_ssl_cf_get_ssl(conn->cfilter[FIRSTSOCKET]);
+ return cf? Curl_ssl->check_cxn(cf, data) : -1;
}
void Curl_ssl_free_certinfo(struct Curl_easy *data)
@@ -1138,20 +1052,13 @@ bool Curl_ssl_cert_status_request(void)
/*
* Check whether the SSL backend supports false start.
*/
-bool Curl_ssl_false_start(void)
+bool Curl_ssl_false_start(struct Curl_easy *data)
{
+ (void)data;
return Curl_ssl->false_start();
}
/*
- * Check whether the SSL backend supports setting TLS 1.3 cipher suites
- */
-bool Curl_ssl_tls13_ciphersuites(void)
-{
- return Curl_ssl->supports & SSLSUPP_TLS13_CIPHERSUITES;
-}
-
-/*
* Default implementations for unsupported functions.
*/
@@ -1163,19 +1070,18 @@ int Curl_none_init(void)
void Curl_none_cleanup(void)
{ }
-int Curl_none_shutdown(struct Curl_easy *data UNUSED_PARAM,
- struct connectdata *conn UNUSED_PARAM,
- int sockindex UNUSED_PARAM)
+int Curl_none_shutdown(struct Curl_cfilter *cf UNUSED_PARAM,
+ struct Curl_easy *data UNUSED_PARAM)
{
(void)data;
- (void)conn;
- (void)sockindex;
+ (void)cf;
return 0;
}
-int Curl_none_check_cxn(struct connectdata *conn UNUSED_PARAM)
+int Curl_none_check_cxn(struct Curl_cfilter *cf, struct Curl_easy *data)
{
- (void)conn;
+ (void)cf;
+ (void)data;
return -1;
}
@@ -1199,11 +1105,11 @@ 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)
+bool Curl_none_data_pending(struct Curl_cfilter *cf UNUSED_PARAM,
+ const struct Curl_easy *data UNUSED_PARAM)
{
- (void)conn;
- (void)connindex;
+ (void)cf;
+ (void)data;
return 0;
}
@@ -1244,28 +1150,30 @@ static int multissl_init(void)
return Curl_ssl->init();
}
-static CURLcode multissl_connect(struct Curl_easy *data,
- struct connectdata *conn, int sockindex)
+static CURLcode multissl_connect(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
{
if(multissl_setup(NULL))
return CURLE_FAILED_INIT;
- return Curl_ssl->connect_blocking(data, conn, sockindex);
+ return Curl_ssl->connect_blocking(cf, data);
}
-static CURLcode multissl_connect_nonblocking(struct Curl_easy *data,
- struct connectdata *conn,
- int sockindex, bool *done)
+static CURLcode multissl_connect_nonblocking(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ bool *done)
{
if(multissl_setup(NULL))
return CURLE_FAILED_INIT;
- return Curl_ssl->connect_nonblocking(data, conn, sockindex, done);
+ return Curl_ssl->connect_nonblocking(cf, data, done);
}
-static int multissl_getsock(struct connectdata *conn, curl_socket_t *socks)
+static int multissl_get_select_socks(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ curl_socket_t *socks)
{
if(multissl_setup(NULL))
return 0;
- return Curl_ssl->getsock(conn, socks);
+ return Curl_ssl->get_select_socks(cf, data, socks);
}
static void *multissl_get_internals(struct ssl_connect_data *connssl,
@@ -1276,12 +1184,30 @@ static void *multissl_get_internals(struct ssl_connect_data *connssl,
return Curl_ssl->get_internals(connssl, info);
}
-static void multissl_close(struct Curl_easy *data, struct connectdata *conn,
- int sockindex)
+static void multissl_close(struct Curl_cfilter *cf, struct Curl_easy *data)
{
if(multissl_setup(NULL))
return;
- Curl_ssl->close_one(data, conn, sockindex);
+ Curl_ssl->close(cf, data);
+}
+
+static ssize_t multissl_recv_plain(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ char *buf, size_t len, CURLcode *code)
+{
+ if(multissl_setup(NULL))
+ return CURLE_FAILED_INIT;
+ return Curl_ssl->recv_plain(cf, data, buf, len, code);
+}
+
+static ssize_t multissl_send_plain(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ const void *mem, size_t len,
+ CURLcode *code)
+{
+ if(multissl_setup(NULL))
+ return CURLE_FAILED_INIT;
+ return Curl_ssl->send_plain(cf, data, mem, len, code);
}
static const struct Curl_ssl Curl_ssl_multi = {
@@ -1299,7 +1225,7 @@ static const struct Curl_ssl Curl_ssl_multi = {
Curl_none_cert_status_request, /* cert_status_request */
multissl_connect, /* connect */
multissl_connect_nonblocking, /* connect_nonblocking */
- multissl_getsock, /* getsock */
+ multissl_get_select_socks, /* getsock */
multissl_get_internals, /* get_internals */
multissl_close, /* close_one */
Curl_none_close_all, /* close_all */
@@ -1310,7 +1236,10 @@ static const struct Curl_ssl Curl_ssl_multi = {
Curl_none_false_start, /* false_start */
NULL, /* sha256sum */
NULL, /* associate_connection */
- NULL /* disassociate_connection */
+ NULL, /* disassociate_connection */
+ NULL, /* free_multi_ssl_backend_data */
+ multissl_recv_plain, /* recv decrypted data */
+ multissl_send_plain, /* send data to encrypt */
};
const struct Curl_ssl *Curl_ssl =
@@ -1498,3 +1427,397 @@ CURLsslset Curl_init_sslset_nolock(curl_sslbackend id, const char *name,
}
#endif /* !USE_SSL */
+
+#ifdef USE_SSL
+
+static void cf_close(struct Curl_cfilter *cf, struct Curl_easy *data)
+{
+ struct ssl_connect_data *connssl = cf->ctx;
+ /* TODO: close_one closes BOTH conn->ssl AND conn->proxy_ssl for this
+ * sockindex (if in use). Gladly, it is safe to call more than once. */
+ if(connssl) {
+ Curl_ssl->close(cf, data);
+ connssl->state = ssl_connection_none;
+ }
+ cf->connected = FALSE;
+}
+
+static void reinit_hostname(struct Curl_cfilter *cf)
+{
+ struct ssl_connect_data *connssl = cf->ctx;
+
+#ifndef CURL_DISABLE_PROXY
+ if(Curl_ssl_cf_is_proxy(cf)) {
+ /* TODO: there is not definition for a proxy setup on a secondary conn */
+ connssl->hostname = cf->conn->http_proxy.host.name;
+ connssl->dispname = cf->conn->http_proxy.host.dispname;
+ connssl->port = cf->conn->http_proxy.port;
+ }
+ else
+#endif
+ {
+ /* TODO: secondaryhostname is set to the IP address we connect to
+ * in the FTP handler, it is assumed that host verification uses the
+ * hostname from FIRSTSOCKET */
+ if(cf->sockindex == SECONDARYSOCKET && 0) {
+ connssl->hostname = cf->conn->secondaryhostname;
+ connssl->dispname = connssl->hostname;
+ connssl->port = cf->conn->secondary_port;
+ }
+ else {
+ connssl->hostname = cf->conn->host.name;
+ connssl->dispname = cf->conn->host.dispname;
+ connssl->port = cf->conn->remote_port;
+ }
+ }
+ DEBUGASSERT(connssl->hostname);
+}
+
+static void ssl_cf_destroy(struct Curl_cfilter *cf, struct Curl_easy *data)
+{
+ cf_ctx_set_data(cf, data);
+ cf_close(cf, data);
+ cf_ctx_free(cf->ctx);
+ cf->ctx = NULL;
+}
+
+static void ssl_cf_close(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ cf_ctx_set_data(cf, data);
+ cf_close(cf, data);
+ cf->next->cft->close(cf->next, data);
+ cf_ctx_set_data(cf, NULL);
+}
+
+static CURLcode ssl_cf_connect(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ bool blocking, bool *done)
+{
+ struct ssl_connect_data *connssl = cf->ctx;
+ CURLcode result;
+
+ if(cf->connected) {
+ *done = TRUE;
+ return CURLE_OK;
+ }
+
+ cf_ctx_set_data(cf, data);
+ (void)connssl;
+ DEBUGASSERT(data->conn);
+ DEBUGASSERT(data->conn == cf->conn);
+ DEBUGASSERT(connssl);
+ DEBUGASSERT(cf->conn->host.name);
+
+ result = cf->next->cft->connect(cf->next, data, blocking, done);
+ if(result || !*done)
+ goto out;
+
+ /* TODO: right now we do not fully control when hostname is set,
+ * assign it on each connect call. */
+ reinit_hostname(cf);
+ *done = FALSE;
+
+ if(blocking) {
+ result = ssl_connect(cf, data);
+ *done = (result == CURLE_OK);
+ }
+ else {
+ result = ssl_connect_nonblocking(cf, data, done);
+ }
+
+ if(!result && *done) {
+ cf->connected = TRUE;
+ if(cf->sockindex == FIRSTSOCKET && !Curl_ssl_cf_is_proxy(cf))
+ Curl_pgrsTime(data, TIMER_APPCONNECT); /* SSL is connected */
+ DEBUGASSERT(connssl->state == ssl_connection_complete);
+ }
+out:
+ cf_ctx_set_data(cf, NULL);
+ return result;
+}
+
+static bool ssl_cf_data_pending(struct Curl_cfilter *cf,
+ const struct Curl_easy *data)
+{
+ bool result;
+
+ cf_ctx_set_data(cf, (struct Curl_easy *)data);
+ if(cf->ctx && Curl_ssl->data_pending(cf, data))
+ result = TRUE;
+ else
+ result = cf->next->cft->has_data_pending(cf->next, data);
+ cf_ctx_set_data(cf, NULL);
+ return result;
+}
+
+static ssize_t ssl_cf_send(struct Curl_cfilter *cf,
+ struct Curl_easy *data, const void *buf, size_t len,
+ CURLcode *err)
+{
+ ssize_t nwritten;
+
+ *err = CURLE_OK;
+ cf_ctx_set_data(cf, data);
+ nwritten = Curl_ssl->send_plain(cf, data, buf, len, err);
+ cf_ctx_set_data(cf, NULL);
+ return nwritten;
+}
+
+static ssize_t ssl_cf_recv(struct Curl_cfilter *cf,
+ struct Curl_easy *data, char *buf, size_t len,
+ CURLcode *err)
+{
+ ssize_t nread;
+
+ *err = CURLE_OK;
+ cf_ctx_set_data(cf, data);
+ nread = Curl_ssl->recv_plain(cf, data, buf, len, err);
+ cf_ctx_set_data(cf, NULL);
+ return nread;
+}
+
+static int ssl_cf_get_select_socks(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ curl_socket_t *socks)
+{
+ int result;
+
+ cf_ctx_set_data(cf, data);
+ result = Curl_ssl->get_select_socks(cf, data, socks);
+ cf_ctx_set_data(cf, NULL);
+ return result;
+}
+
+static void ssl_cf_attach_data(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ if(Curl_ssl->attach_data) {
+ cf_ctx_set_data(cf, data);
+ Curl_ssl->attach_data(cf, data);
+ cf_ctx_set_data(cf, NULL);
+ }
+}
+
+static void ssl_cf_detach_data(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ if(Curl_ssl->detach_data) {
+ cf_ctx_set_data(cf, data);
+ Curl_ssl->detach_data(cf, data);
+ cf_ctx_set_data(cf, NULL);
+ }
+}
+
+static const struct Curl_cftype cft_ssl = {
+ "SSL",
+ CF_TYPE_SSL,
+ ssl_cf_destroy,
+ Curl_cf_def_setup,
+ ssl_cf_connect,
+ ssl_cf_close,
+ Curl_cf_def_get_host,
+ ssl_cf_get_select_socks,
+ ssl_cf_data_pending,
+ ssl_cf_send,
+ ssl_cf_recv,
+ ssl_cf_attach_data,
+ ssl_cf_detach_data,
+};
+
+static const struct Curl_cftype cft_ssl_proxy = {
+ "SSL-PROXY",
+ CF_TYPE_SSL,
+ ssl_cf_destroy,
+ Curl_cf_def_setup,
+ ssl_cf_connect,
+ ssl_cf_close,
+ Curl_cf_def_get_host,
+ ssl_cf_get_select_socks,
+ ssl_cf_data_pending,
+ ssl_cf_send,
+ ssl_cf_recv,
+ ssl_cf_attach_data,
+ ssl_cf_detach_data,
+};
+
+CURLcode Curl_ssl_cfilter_add(struct Curl_easy *data,
+ struct connectdata *conn,
+ int sockindex)
+{
+ struct Curl_cfilter *cf;
+ struct ssl_connect_data *ctx;
+ CURLcode result;
+
+ DEBUGASSERT(data->conn);
+ ctx = cf_ctx_new(data);
+ if(!ctx) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
+ }
+
+ result = Curl_cf_create(&cf, &cft_ssl, ctx);
+ if(result)
+ goto out;
+
+ Curl_conn_cf_add(data, conn, sockindex, cf);
+
+ result = CURLE_OK;
+
+out:
+ if(result)
+ cf_ctx_free(ctx);
+ return result;
+}
+
+#ifndef CURL_DISABLE_PROXY
+CURLcode Curl_ssl_cfilter_proxy_add(struct Curl_easy *data,
+ struct connectdata *conn,
+ int sockindex)
+{
+ struct Curl_cfilter *cf;
+ struct ssl_connect_data *ctx;
+ CURLcode result;
+
+ ctx = cf_ctx_new(data);
+ if(!ctx) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
+ }
+
+ result = Curl_cf_create(&cf, &cft_ssl_proxy, ctx);
+ if(result)
+ goto out;
+
+ Curl_conn_cf_add(data, conn, sockindex, cf);
+
+ result = CURLE_OK;
+
+out:
+ if(result)
+ cf_ctx_free(ctx);
+ return result;
+}
+
+#endif /* !CURL_DISABLE_PROXY */
+
+bool Curl_ssl_supports(struct Curl_easy *data, int option)
+{
+ (void)data;
+ return (Curl_ssl->supports & option)? TRUE : FALSE;
+}
+
+void *Curl_ssl_get_internals(struct Curl_easy *data, int sockindex,
+ CURLINFO info, int n)
+{
+ void *result = NULL;
+ (void)n;
+ if(data->conn) {
+ struct Curl_cfilter *cf;
+ /* get first filter in chain, if any is present */
+ cf = Curl_ssl_cf_get_ssl(data->conn->cfilter[sockindex]);
+ if(cf) {
+ cf_ctx_set_data(cf, data);
+ result = Curl_ssl->get_internals(cf->ctx, info);
+ cf_ctx_set_data(cf, NULL);
+ }
+ }
+ return result;
+}
+
+CURLcode Curl_ssl_cfilter_remove(struct Curl_easy *data,
+ int sockindex)
+{
+ struct Curl_cfilter *cf = data->conn? data->conn->cfilter[sockindex] : NULL;
+ CURLcode result = CURLE_OK;
+
+ (void)data;
+ for(; cf; cf = cf->next) {
+ if(cf->cft == &cft_ssl) {
+ if(Curl_ssl->shut_down(cf, data))
+ result = CURLE_SSL_SHUTDOWN_FAILED;
+ Curl_conn_cf_discard(cf, data);
+ break;
+ }
+ }
+ return result;
+}
+
+static struct Curl_cfilter *get_ssl_cf_engaged(struct connectdata *conn,
+ int sockindex)
+{
+ struct Curl_cfilter *cf, *lowest_ssl_cf = NULL;
+
+ for(cf = conn->cfilter[sockindex]; cf; cf = cf->next) {
+ if(cf->cft == &cft_ssl || cf->cft == &cft_ssl_proxy) {
+ lowest_ssl_cf = cf;
+ if(cf->connected || (cf->next && cf->next->connected)) {
+ /* connected or about to start */
+ return cf;
+ }
+ }
+ }
+ return lowest_ssl_cf;
+}
+
+bool Curl_ssl_cf_is_proxy(struct Curl_cfilter *cf)
+{
+ return (cf->cft == &cft_ssl_proxy);
+}
+
+struct ssl_config_data *
+Curl_ssl_cf_get_config(struct Curl_cfilter *cf, struct Curl_easy *data)
+{
+#ifdef CURL_DISABLE_PROXY
+ (void)cf;
+ return &data->set.ssl;
+#else
+ return Curl_ssl_cf_is_proxy(cf)? &data->set.proxy_ssl : &data->set.ssl;
+#endif
+}
+
+struct ssl_config_data *
+Curl_ssl_get_config(struct Curl_easy *data, int sockindex)
+{
+ struct Curl_cfilter *cf;
+
+ (void)data;
+ DEBUGASSERT(data->conn);
+ cf = get_ssl_cf_engaged(data->conn, sockindex);
+ return cf? Curl_ssl_cf_get_config(cf, data) : &data->set.ssl;
+}
+
+struct ssl_primary_config *
+Curl_ssl_cf_get_primary_config(struct Curl_cfilter *cf)
+{
+#ifdef CURL_DISABLE_PROXY
+ return &cf->conn->ssl_config;
+#else
+ return Curl_ssl_cf_is_proxy(cf)?
+ &cf->conn->proxy_ssl_config : &cf->conn->ssl_config;
+#endif
+}
+
+struct ssl_primary_config *
+Curl_ssl_get_primary_config(struct Curl_easy *data,
+ struct connectdata *conn,
+ int sockindex)
+{
+ struct Curl_cfilter *cf;
+
+ (void)data;
+ DEBUGASSERT(conn);
+ cf = get_ssl_cf_engaged(conn, sockindex);
+ return cf? Curl_ssl_cf_get_primary_config(cf) : NULL;
+}
+
+struct Curl_cfilter *Curl_ssl_cf_get_ssl(struct Curl_cfilter *cf)
+{
+ for(; cf; cf = cf->next) {
+ if(cf->cft == &cft_ssl || cf->cft == &cft_ssl_proxy)
+ return cf;
+ }
+ return NULL;
+}
+
+#endif /* USE_SSL */