summaryrefslogtreecommitdiff
path: root/Utilities/cmcurl/lib/vtls
diff options
context:
space:
mode:
Diffstat (limited to 'Utilities/cmcurl/lib/vtls')
-rw-r--r--Utilities/cmcurl/lib/vtls/bearssl.c59
-rw-r--r--Utilities/cmcurl/lib/vtls/bearssl.h2
-rw-r--r--Utilities/cmcurl/lib/vtls/gskit.c14
-rw-r--r--Utilities/cmcurl/lib/vtls/gskit.h2
-rw-r--r--Utilities/cmcurl/lib/vtls/gtls.c85
-rw-r--r--Utilities/cmcurl/lib/vtls/gtls.h2
-rw-r--r--Utilities/cmcurl/lib/vtls/hostcheck.c2
-rw-r--r--Utilities/cmcurl/lib/vtls/hostcheck.h2
-rw-r--r--Utilities/cmcurl/lib/vtls/keylog.c2
-rw-r--r--Utilities/cmcurl/lib/vtls/keylog.h2
-rw-r--r--Utilities/cmcurl/lib/vtls/mbedtls.c64
-rw-r--r--Utilities/cmcurl/lib/vtls/mbedtls.h4
-rw-r--r--Utilities/cmcurl/lib/vtls/mbedtls_threadlock.c4
-rw-r--r--Utilities/cmcurl/lib/vtls/mbedtls_threadlock.h4
-rw-r--r--Utilities/cmcurl/lib/vtls/nss.c70
-rw-r--r--Utilities/cmcurl/lib/vtls/nssg.h2
-rw-r--r--Utilities/cmcurl/lib/vtls/openssl.c795
-rw-r--r--Utilities/cmcurl/lib/vtls/openssl.h11
-rw-r--r--Utilities/cmcurl/lib/vtls/rustls.c105
-rw-r--r--Utilities/cmcurl/lib/vtls/rustls.h2
-rw-r--r--Utilities/cmcurl/lib/vtls/schannel.c67
-rw-r--r--Utilities/cmcurl/lib/vtls/schannel.h8
-rw-r--r--Utilities/cmcurl/lib/vtls/schannel_verify.c6
-rw-r--r--Utilities/cmcurl/lib/vtls/sectransp.c94
-rw-r--r--Utilities/cmcurl/lib/vtls/sectransp.h4
-rw-r--r--Utilities/cmcurl/lib/vtls/vtls.c478
-rw-r--r--Utilities/cmcurl/lib/vtls/vtls.h59
-rw-r--r--Utilities/cmcurl/lib/vtls/vtls_int.h18
-rw-r--r--Utilities/cmcurl/lib/vtls/wolfssl.c77
-rw-r--r--Utilities/cmcurl/lib/vtls/wolfssl.h2
-rw-r--r--Utilities/cmcurl/lib/vtls/x509asn1.c25
-rw-r--r--Utilities/cmcurl/lib/vtls/x509asn1.h2
32 files changed, 1021 insertions, 1052 deletions
diff --git a/Utilities/cmcurl/lib/vtls/bearssl.c b/Utilities/cmcurl/lib/vtls/bearssl.c
index d9c0ce0eed..7e3eb79ce8 100644
--- a/Utilities/cmcurl/lib/vtls/bearssl.c
+++ b/Utilities/cmcurl/lib/vtls/bearssl.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2019 - 2022, Michael Forney, <mforney@mforney.org>
+ * Copyright (C) Michael Forney, <mforney@mforney.org>
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -58,7 +58,7 @@ struct ssl_backend_data {
unsigned char buf[BR_SSL_BUFSIZE_BIDI];
br_x509_trust_anchor *anchors;
size_t anchors_len;
- const char *protocols[2];
+ const char *protocols[ALPN_ENTRIES_MAX];
/* SSL client context is active */
bool active;
/* size of pending write, yet to be flushed */
@@ -691,29 +691,17 @@ static CURLcode bearssl_connect_step1(struct Curl_cfilter *cf,
Curl_ssl_sessionid_unlock(data);
}
- if(cf->conn->bits.tls_enable_alpn) {
- int cur = 0;
-
- /* NOTE: when adding more protocols here, increase the size of the
- * protocols array in `struct ssl_backend_data`.
- */
+ if(connssl->alpn) {
+ struct alpn_proto_buf proto;
+ size_t i;
-#ifdef USE_HTTP2
- if(data->state.httpwant >= CURL_HTTP_VERSION_2
-#ifndef CURL_DISABLE_PROXY
- && (!Curl_ssl_cf_is_proxy(cf) || !cf->conn->bits.tunnel_proxy)
-#endif
- ) {
- backend->protocols[cur++] = ALPN_H2;
- infof(data, VTLS_INFOF_ALPN_OFFER_1STR, ALPN_H2);
+ for(i = 0; i < connssl->alpn->count; ++i) {
+ backend->protocols[i] = connssl->alpn->entries[i];
}
-#endif
-
- backend->protocols[cur++] = ALPN_HTTP_1_1;
- infof(data, VTLS_INFOF_ALPN_OFFER_1STR, ALPN_HTTP_1_1);
-
- br_ssl_engine_set_protocol_names(&backend->ctx.eng,
- backend->protocols, cur);
+ br_ssl_engine_set_protocol_names(&backend->ctx.eng, backend->protocols,
+ connssl->alpn->count);
+ Curl_alpn_to_proto_str(&proto, connssl->alpn);
+ infof(data, VTLS_INFOF_ALPN_OFFER_1STR, proto.data);
}
if((1 == Curl_inet_pton(AF_INET, hostname, &addr))
@@ -862,26 +850,11 @@ static CURLcode bearssl_connect_step3(struct Curl_cfilter *cf,
DEBUGASSERT(backend);
if(cf->conn->bits.tls_enable_alpn) {
- const char *protocol;
-
- protocol = br_ssl_engine_get_selected_protocol(&backend->ctx.eng);
- if(protocol) {
- infof(data, VTLS_INFOF_ALPN_ACCEPTED_1STR, protocol);
+ const char *proto;
-#ifdef USE_HTTP2
- if(!strcmp(protocol, ALPN_H2))
- cf->conn->alpn = CURL_HTTP_VERSION_2;
- else
-#endif
- if(!strcmp(protocol, ALPN_HTTP_1_1))
- cf->conn->alpn = CURL_HTTP_VERSION_1_1;
- else
- infof(data, "ALPN, unrecognized protocol %s", protocol);
- Curl_multiuse_state(data, cf->conn->alpn == CURL_HTTP_VERSION_2 ?
- BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
- }
- else
- infof(data, VTLS_INFOF_NO_ALPN);
+ proto = br_ssl_engine_get_selected_protocol(&backend->ctx.eng);
+ Curl_alpn_set_negotiated(cf, data, (const unsigned char *)proto,
+ proto? strlen(proto) : 0);
}
if(ssl_config->primary.sessionid) {
@@ -977,7 +950,7 @@ static CURLcode bearssl_connect_common(struct Curl_cfilter *cf,
{
CURLcode ret;
struct ssl_connect_data *connssl = cf->ctx;
- curl_socket_t sockfd = cf->conn->sock[cf->sockindex];
+ curl_socket_t sockfd = Curl_conn_cf_get_socket(cf, data);
timediff_t timeout_ms;
int what;
diff --git a/Utilities/cmcurl/lib/vtls/bearssl.h b/Utilities/cmcurl/lib/vtls/bearssl.h
index 5125359961..b3651b092c 100644
--- a/Utilities/cmcurl/lib/vtls/bearssl.h
+++ b/Utilities/cmcurl/lib/vtls/bearssl.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2019 - 2022, Michael Forney, <mforney@mforney.org>
+ * Copyright (C) Michael Forney, <mforney@mforney.org>
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/Utilities/cmcurl/lib/vtls/gskit.c b/Utilities/cmcurl/lib/vtls/gskit.c
index 2074dcaa48..59fd27ce4e 100644
--- a/Utilities/cmcurl/lib/vtls/gskit.c
+++ b/Utilities/cmcurl/lib/vtls/gskit.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -499,7 +499,7 @@ static void cancel_async_handshake(struct Curl_cfilter *cf,
(void)data;
DEBUGASSERT(BACKEND);
- if(QsoCancelOperation(cf->conn->sock[cf->sockindex], 0) > 0)
+ if(QsoCancelOperation(Curl_conn_cf_get_socket(cf, data), 0) > 0)
QsoWaitForIOCompletion(BACKEND->iocport, &cstat, (struct timeval *) NULL);
}
@@ -532,7 +532,7 @@ static int pipe_ssloverssl(struct Curl_cfilter *cf, int directions)
DEBUGASSERT(connssl_next->backend);
n = 1;
fds[0].fd = BACKEND->remotefd;
- fds[1].fd = cf->conn->sock[cf->sockindex];
+ fds[1].fd = Curl_conn_cf_get_socket(cf, data);
if(directions & SOS_READ) {
fds[0].events |= POLLOUT;
@@ -847,7 +847,7 @@ static CURLcode gskit_connect_step1(struct Curl_cfilter *cf,
result = set_numeric(data, BACKEND->handle, GSK_OS400_READ_TIMEOUT, 1);
if(!result)
result = set_numeric(data, BACKEND->handle, GSK_FD, BACKEND->localfd >= 0?
- BACKEND->localfd: cf->conn->sock[cf->sockindex]);
+ BACKEND->localfd: Curl_conn_cf_get_socket(cf, data));
if(!result)
result = set_ciphers(cf, data, BACKEND->handle, &protoflags);
if(!protoflags) {
@@ -1208,7 +1208,7 @@ static int gskit_shutdown(struct Curl_cfilter *cf,
close_one(cf, data);
rc = 0;
- what = SOCKET_READABLE(cf->conn->sock[cf->sockindex],
+ what = SOCKET_READABLE(Curl_conn_cf_get_socket(cf, data),
SSL_SHUTDOWN_TIMEOUT);
while(loop--) {
@@ -1230,7 +1230,7 @@ static int gskit_shutdown(struct Curl_cfilter *cf,
notify alert from the server. No way to gsk_secure_soc_read() now, so
use read(). */
- nread = read(cf->conn->sock[cf->sockindex], buf, sizeof(buf));
+ nread = read(Curl_conn_cf_get_socket(cf, data), buf, sizeof(buf));
if(nread < 0) {
char buffer[STRERROR_LEN];
@@ -1241,7 +1241,7 @@ static int gskit_shutdown(struct Curl_cfilter *cf,
if(nread <= 0)
break;
- what = SOCKET_READABLE(cf->conn->sock[cf->sockindex], 0);
+ what = SOCKET_READABLE(Curl_conn_cf_get_socket(cf, data), 0);
}
return rc;
diff --git a/Utilities/cmcurl/lib/vtls/gskit.h b/Utilities/cmcurl/lib/vtls/gskit.h
index cf923f6b85..c71e6a0117 100644
--- a/Utilities/cmcurl/lib/vtls/gskit.h
+++ b/Utilities/cmcurl/lib/vtls/gskit.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/Utilities/cmcurl/lib/vtls/gtls.c b/Utilities/cmcurl/lib/vtls/gtls.c
index 104dce6093..07dfaa437c 100644
--- a/Utilities/cmcurl/lib/vtls/gtls.c
+++ b/Utilities/cmcurl/lib/vtls/gtls.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -84,7 +84,7 @@ static ssize_t gtls_push(void *s, const void *buf, size_t blen)
{
struct Curl_cfilter *cf = s;
struct ssl_connect_data *connssl = cf->ctx;
- struct Curl_easy *data = connssl->call_data;
+ struct Curl_easy *data = CF_DATA_CURRENT(cf);
ssize_t nwritten;
CURLcode result;
@@ -102,7 +102,7 @@ static ssize_t gtls_pull(void *s, void *buf, size_t blen)
{
struct Curl_cfilter *cf = s;
struct ssl_connect_data *connssl = cf->ctx;
- struct Curl_easy *data = connssl->call_data;
+ struct Curl_easy *data = CF_DATA_CURRENT(cf);
ssize_t nread;
CURLcode result;
@@ -214,7 +214,7 @@ static CURLcode handshake(struct Curl_cfilter *cf,
struct ssl_connect_data *connssl = cf->ctx;
struct ssl_backend_data *backend = connssl->backend;
gnutls_session_t session;
- curl_socket_t sockfd = cf->conn->sock[cf->sockindex];
+ curl_socket_t sockfd = Curl_conn_cf_get_socket(cf, data);
DEBUGASSERT(backend);
session = backend->gtls.session;
@@ -434,12 +434,10 @@ CURLcode gtls_client_init(struct Curl_easy *data,
}
#ifdef USE_GNUTLS_SRP
- if((config->authtype == CURL_TLSAUTH_SRP) &&
- Curl_auth_allowed_to_host(data)) {
+ if(config->username && Curl_auth_allowed_to_host(data)) {
infof(data, "Using TLS-SRP username: %s", config->username);
- rc = gnutls_srp_allocate_client_credentials(
- &gtls->srp_client_cred);
+ rc = gnutls_srp_allocate_client_credentials(&gtls->srp_client_cred);
if(rc != GNUTLS_E_SUCCESS) {
failf(data, "gnutls_srp_allocate_client_cred() failed: %s",
gnutls_strerror(rc));
@@ -581,7 +579,7 @@ CURLcode gtls_client_init(struct Curl_easy *data,
#ifdef USE_GNUTLS_SRP
/* Only add SRP to the cipher list if SRP is requested. Otherwise
* GnuTLS will disable TLS 1.3 support. */
- if(config->authtype == CURL_TLSAUTH_SRP) {
+ if(config->username) {
size_t len = strlen(prioritylist);
char *prioritysrp = malloc(len + sizeof(GNUTLS_SRP) + 1);
@@ -646,7 +644,7 @@ CURLcode gtls_client_init(struct Curl_easy *data,
#ifdef USE_GNUTLS_SRP
/* put the credentials to the current session */
- if(config->authtype == CURL_TLSAUTH_SRP) {
+ if(config->username) {
rc = gnutls_credentials_set(gtls->session, GNUTLS_CRD_SRP,
gtls->srp_client_cred);
if(rc != GNUTLS_E_SUCCESS) {
@@ -700,32 +698,22 @@ gtls_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
if(result)
return result;
- if(cf->conn->bits.tls_enable_alpn) {
- int cur = 0;
- gnutls_datum_t protocols[2];
+ if(connssl->alpn) {
+ struct alpn_proto_buf proto;
+ gnutls_datum_t alpn[ALPN_ENTRIES_MAX];
+ size_t i;
-#ifdef USE_HTTP2
- if(data->state.httpwant >= CURL_HTTP_VERSION_2
-#ifndef CURL_DISABLE_PROXY
- && (!Curl_ssl_cf_is_proxy(cf) || !cf->conn->bits.tunnel_proxy)
-#endif
- ) {
- protocols[cur].data = (unsigned char *)ALPN_H2;
- protocols[cur].size = ALPN_H2_LENGTH;
- cur++;
- infof(data, VTLS_INFOF_ALPN_OFFER_1STR, ALPN_H2);
+ for(i = 0; i < connssl->alpn->count; ++i) {
+ alpn[i].data = (unsigned char *)connssl->alpn->entries[i];
+ alpn[i].size = (unsigned)strlen(connssl->alpn->entries[i]);
}
-#endif
-
- protocols[cur].data = (unsigned char *)ALPN_HTTP_1_1;
- protocols[cur].size = ALPN_HTTP_1_1_LENGTH;
- cur++;
- infof(data, VTLS_INFOF_ALPN_OFFER_1STR, ALPN_HTTP_1_1);
-
- if(gnutls_alpn_set_protocols(backend->gtls.session, protocols, cur, 0)) {
+ if(gnutls_alpn_set_protocols(backend->gtls.session, alpn,
+ (unsigned)connssl->alpn->count, 0)) {
failf(data, "failed setting ALPN");
return CURLE_SSL_CONNECT_ERROR;
}
+ Curl_alpn_to_proto_str(&proto, connssl->alpn);
+ infof(data, VTLS_INFOF_ALPN_OFFER_1STR, proto.data);
}
/* This might be a reconnect, so we check for a session ID in the cache
@@ -860,10 +848,8 @@ Curl_gtls_verifyserver(struct Curl_easy *data,
config->verifyhost ||
config->issuercert) {
#ifdef USE_GNUTLS_SRP
- if(ssl_config->primary.authtype == CURL_TLSAUTH_SRP
- && ssl_config->primary.username
- && !config->verifypeer
- && gnutls_cipher_get(session)) {
+ if(ssl_config->primary.username && !config->verifypeer &&
+ gnutls_cipher_get(session)) {
/* no peer cert, but auth is ok if we have SRP user and cipher and no
peer verify */
}
@@ -1271,28 +1257,10 @@ static CURLcode gtls_verifyserver(struct Curl_cfilter *cf,
int rc;
rc = gnutls_alpn_get_selected_protocol(session, &proto);
- if(rc == 0) {
- infof(data, VTLS_INFOF_ALPN_ACCEPTED_LEN_1STR, proto.size,
- proto.data);
-
-#ifdef USE_HTTP2
- if(proto.size == ALPN_H2_LENGTH &&
- !memcmp(ALPN_H2, proto.data,
- ALPN_H2_LENGTH)) {
- cf->conn->alpn = CURL_HTTP_VERSION_2;
- }
- else
-#endif
- if(proto.size == ALPN_HTTP_1_1_LENGTH &&
- !memcmp(ALPN_HTTP_1_1, proto.data, ALPN_HTTP_1_1_LENGTH)) {
- cf->conn->alpn = CURL_HTTP_VERSION_1_1;
- }
- }
+ if(rc == 0)
+ Curl_alpn_set_negotiated(cf, data, proto.data, proto.size);
else
- infof(data, VTLS_INFOF_NO_ALPN);
-
- Curl_multiuse_state(data, cf->conn->alpn == CURL_HTTP_VERSION_2 ?
- BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
+ Curl_alpn_set_negotiated(cf, data, NULL, 0);
}
if(ssl_config->primary.sessionid) {
@@ -1516,7 +1484,7 @@ static int gtls_shutdown(struct Curl_cfilter *cf,
char buf[120];
while(!done) {
- int what = SOCKET_READABLE(cf->conn->sock[cf->sockindex],
+ int what = SOCKET_READABLE(Curl_conn_cf_get_socket(cf, data),
SSL_SHUTDOWN_TIMEOUT);
if(what > 0) {
/* Something to read, let's do it and hope that it is the close
@@ -1556,8 +1524,7 @@ static int gtls_shutdown(struct Curl_cfilter *cf,
gnutls_certificate_free_credentials(backend->gtls.cred);
#ifdef USE_GNUTLS_SRP
- if(ssl_config->primary.authtype == CURL_TLSAUTH_SRP
- && ssl_config->primary.username != NULL)
+ if(ssl_config->primary.username)
gnutls_srp_free_client_credentials(backend->gtls.srp_client_cred);
#endif
diff --git a/Utilities/cmcurl/lib/vtls/gtls.h b/Utilities/cmcurl/lib/vtls/gtls.h
index 49c1c47637..ac141e1c61 100644
--- a/Utilities/cmcurl/lib/vtls/gtls.h
+++ b/Utilities/cmcurl/lib/vtls/gtls.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/Utilities/cmcurl/lib/vtls/hostcheck.c b/Utilities/cmcurl/lib/vtls/hostcheck.c
index 2a648f20a9..e827dc58f3 100644
--- a/Utilities/cmcurl/lib/vtls/hostcheck.c
+++ b/Utilities/cmcurl/lib/vtls/hostcheck.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/Utilities/cmcurl/lib/vtls/hostcheck.h b/Utilities/cmcurl/lib/vtls/hostcheck.h
index d3c4eab56d..22a1ac2e56 100644
--- a/Utilities/cmcurl/lib/vtls/hostcheck.h
+++ b/Utilities/cmcurl/lib/vtls/hostcheck.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/Utilities/cmcurl/lib/vtls/keylog.c b/Utilities/cmcurl/lib/vtls/keylog.c
index 1952a690ca..d37bb183e7 100644
--- a/Utilities/cmcurl/lib/vtls/keylog.c
+++ b/Utilities/cmcurl/lib/vtls/keylog.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/Utilities/cmcurl/lib/vtls/keylog.h b/Utilities/cmcurl/lib/vtls/keylog.h
index 5d3c675b3e..eff5bf38f3 100644
--- a/Utilities/cmcurl/lib/vtls/keylog.h
+++ b/Utilities/cmcurl/lib/vtls/keylog.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/Utilities/cmcurl/lib/vtls/mbedtls.c b/Utilities/cmcurl/lib/vtls/mbedtls.c
index 0b81662b93..7f0f4e3668 100644
--- a/Utilities/cmcurl/lib/vtls/mbedtls.c
+++ b/Utilities/cmcurl/lib/vtls/mbedtls.c
@@ -5,8 +5,8 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2012 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
- * Copyright (C) 2010 - 2011, Hoi-Ho Chan, <hoiho.chan@gmail.com>
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Hoi-Ho Chan, <hoiho.chan@gmail.com>
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -159,15 +159,14 @@ static void mbed_debug(void *context, int level, const char *f_name,
static int bio_cf_write(void *bio, const unsigned char *buf, size_t blen)
{
struct Curl_cfilter *cf = bio;
- struct ssl_connect_data *connssl = cf->ctx;
- struct Curl_easy *data = connssl->call_data;
+ struct Curl_easy *data = CF_DATA_CURRENT(cf);
ssize_t nwritten;
CURLcode result;
DEBUGASSERT(data);
nwritten = Curl_conn_cf_send(cf->next, data, (char *)buf, blen, &result);
- /* DEBUGF(infof(data, CFMSG(cf, "bio_cf_out_write(len=%d) -> %d, err=%d"),
- blen, (int)nwritten, result)); */
+ DEBUGF(LOG_CF(data, cf, "bio_cf_out_write(len=%zu) -> %zd, err=%d",
+ blen, nwritten, result));
if(nwritten < 0 && CURLE_AGAIN == result) {
nwritten = MBEDTLS_ERR_SSL_WANT_WRITE;
}
@@ -177,8 +176,7 @@ static int bio_cf_write(void *bio, const unsigned char *buf, size_t blen)
static int bio_cf_read(void *bio, unsigned char *buf, size_t blen)
{
struct Curl_cfilter *cf = bio;
- struct ssl_connect_data *connssl = cf->ctx;
- struct Curl_easy *data = connssl->call_data;
+ struct Curl_easy *data = CF_DATA_CURRENT(cf);
ssize_t nread;
CURLcode result;
@@ -188,8 +186,8 @@ static int bio_cf_read(void *bio, unsigned char *buf, size_t blen)
return 0;
nread = Curl_conn_cf_recv(cf->next, data, (char *)buf, blen, &result);
- /* DEBUGF(infof(data, CFMSG(cf, "bio_cf_in_read(len=%d) -> %d, err=%d"),
- blen, (int)nread, result)); */
+ DEBUGF(LOG_CF(data, cf, "bio_cf_in_read(len=%zu) -> %zd, err=%d",
+ blen, nread, result));
if(nread < 0 && CURLE_AGAIN == result) {
nread = MBEDTLS_ERR_SSL_WANT_READ;
}
@@ -648,14 +646,13 @@ mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
}
#ifdef HAS_ALPN
- if(cf->conn->bits.tls_enable_alpn) {
- const char **p = &backend->protocols[0];
-#ifdef USE_HTTP2
- if(data->state.httpwant >= CURL_HTTP_VERSION_2)
- *p++ = ALPN_H2;
-#endif
- *p++ = ALPN_HTTP_1_1;
- *p = NULL;
+ if(connssl->alpn) {
+ struct alpn_proto_buf proto;
+ size_t i;
+
+ for(i = 0; i < connssl->alpn->count; ++i) {
+ backend->protocols[i] = connssl->alpn->entries[i];
+ }
/* this function doesn't clone the protocols array, which is why we need
to keep it around */
if(mbedtls_ssl_conf_alpn_protocols(&backend->config,
@@ -663,8 +660,8 @@ mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
failf(data, "Failed setting ALPN protocols");
return CURLE_SSL_CONNECT_ERROR;
}
- for(p = &backend->protocols[0]; *p; ++p)
- infof(data, VTLS_INFOF_ALPN_OFFER_1STR, *p);
+ Curl_alpn_to_proto_str(&proto, connssl->alpn);
+ infof(data, VTLS_INFOF_ALPN_OFFER_1STR, proto.data);
}
#endif
@@ -844,28 +841,11 @@ mbed_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data)
}
#ifdef HAS_ALPN
- if(cf->conn->bits.tls_enable_alpn) {
- const char *next_protocol = mbedtls_ssl_get_alpn_protocol(&backend->ssl);
+ if(connssl->alpn) {
+ const char *proto = mbedtls_ssl_get_alpn_protocol(&backend->ssl);
- if(next_protocol) {
- infof(data, VTLS_INFOF_ALPN_ACCEPTED_1STR, next_protocol);
-#ifdef USE_HTTP2
- if(!strncmp(next_protocol, ALPN_H2, ALPN_H2_LENGTH) &&
- !next_protocol[ALPN_H2_LENGTH]) {
- cf->conn->alpn = CURL_HTTP_VERSION_2;
- }
- else
-#endif
- if(!strncmp(next_protocol, ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH) &&
- !next_protocol[ALPN_HTTP_1_1_LENGTH]) {
- cf->conn->alpn = CURL_HTTP_VERSION_1_1;
- }
- }
- else {
- infof(data, VTLS_INFOF_NO_ALPN);
- }
- Curl_multiuse_state(data, cf->conn->alpn == CURL_HTTP_VERSION_2 ?
- BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
+ Curl_alpn_set_negotiated(cf, data, (const unsigned char *)proto,
+ proto? strlen(proto) : 0);
}
#endif
@@ -1081,7 +1061,7 @@ mbed_connect_common(struct Curl_cfilter *cf, struct Curl_easy *data,
{
CURLcode retcode;
struct ssl_connect_data *connssl = cf->ctx;
- curl_socket_t sockfd = cf->conn->sock[cf->sockindex];
+ curl_socket_t sockfd = Curl_conn_cf_get_socket(cf, data);
timediff_t timeout_ms;
int what;
diff --git a/Utilities/cmcurl/lib/vtls/mbedtls.h b/Utilities/cmcurl/lib/vtls/mbedtls.h
index ec3b43bf9c..d8a0a06eb6 100644
--- a/Utilities/cmcurl/lib/vtls/mbedtls.h
+++ b/Utilities/cmcurl/lib/vtls/mbedtls.h
@@ -7,8 +7,8 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2012 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
- * Copyright (C) 2010, Hoi-Ho Chan, <hoiho.chan@gmail.com>
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Hoi-Ho Chan, <hoiho.chan@gmail.com>
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/Utilities/cmcurl/lib/vtls/mbedtls_threadlock.c b/Utilities/cmcurl/lib/vtls/mbedtls_threadlock.c
index 7d019ede53..bcb7106a63 100644
--- a/Utilities/cmcurl/lib/vtls/mbedtls_threadlock.c
+++ b/Utilities/cmcurl/lib/vtls/mbedtls_threadlock.c
@@ -5,8 +5,8 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2013 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
- * Copyright (C) 2010, 2011, Hoi-Ho Chan, <hoiho.chan@gmail.com>
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Hoi-Ho Chan, <hoiho.chan@gmail.com>
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/Utilities/cmcurl/lib/vtls/mbedtls_threadlock.h b/Utilities/cmcurl/lib/vtls/mbedtls_threadlock.h
index 22e8725ab0..2b0bd41c8b 100644
--- a/Utilities/cmcurl/lib/vtls/mbedtls_threadlock.h
+++ b/Utilities/cmcurl/lib/vtls/mbedtls_threadlock.h
@@ -7,8 +7,8 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2013 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
- * Copyright (C) 2010, Hoi-Ho Chan, <hoiho.chan@gmail.com>
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Hoi-Ho Chan, <hoiho.chan@gmail.com>
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/Utilities/cmcurl/lib/vtls/nss.c b/Utilities/cmcurl/lib/vtls/nss.c
index 03694d22ba..774cbdd7ba 100644
--- a/Utilities/cmcurl/lib/vtls/nss.c
+++ b/Utilities/cmcurl/lib/vtls/nss.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -873,11 +873,11 @@ static void HandshakeCallback(PRFileDesc *sock, void *arg)
#endif
case SSL_NEXT_PROTO_NO_SUPPORT:
case SSL_NEXT_PROTO_NO_OVERLAP:
- infof(data, VTLS_INFOF_NO_ALPN);
+ Curl_alpn_set_negotiated(cf, data, NULL, 0);
return;
#ifdef SSL_ENABLE_ALPN
case SSL_NEXT_PROTO_SELECTED:
- infof(data, VTLS_INFOF_ALPN_ACCEPTED_LEN_1STR, buflen, buf);
+ Curl_alpn_set_negotiated(cf, data, buf, buflen);
break;
#endif
default:
@@ -885,25 +885,6 @@ static void HandshakeCallback(PRFileDesc *sock, void *arg)
break;
}
-#ifdef USE_HTTP2
- if(buflen == ALPN_H2_LENGTH &&
- !memcmp(ALPN_H2, buf, ALPN_H2_LENGTH)) {
- cf->conn->alpn = CURL_HTTP_VERSION_2;
- }
- else
-#endif
- if(buflen == ALPN_HTTP_1_1_LENGTH &&
- !memcmp(ALPN_HTTP_1_1, buf, ALPN_HTTP_1_1_LENGTH)) {
- cf->conn->alpn = CURL_HTTP_VERSION_1_1;
- }
-
- /* This callback might get called when PR_Recv() is used within
- * close_one() during a connection shutdown. At that point there might not
- * be any "bundle" associated with the connection anymore.
- */
- if(conn->bundle)
- Curl_multiuse_state(data, cf->conn->alpn == CURL_HTTP_VERSION_2 ?
- BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
}
}
@@ -1897,7 +1878,7 @@ static CURLcode nss_setup_connect(struct Curl_cfilter *cf,
PRFileDesc *nspr_io_stub = NULL;
PRBool ssl_no_cache;
PRBool ssl_cbc_random_iv;
- curl_socket_t sockfd = cf->conn->sock[cf->sockindex];
+ curl_socket_t sockfd = Curl_conn_cf_get_socket(cf, data);
struct ssl_connect_data *connssl = cf->ctx;
struct ssl_backend_data *backend = connssl->backend;
struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
@@ -2163,27 +2144,17 @@ static CURLcode nss_setup_connect(struct Curl_cfilter *cf,
#endif
#if defined(SSL_ENABLE_ALPN)
- if(cf->conn->bits.tls_enable_alpn) {
- int cur = 0;
- unsigned char protocols[128];
-
-#ifdef USE_HTTP2
- if(data->state.httpwant >= CURL_HTTP_VERSION_2
-#ifndef CURL_DISABLE_PROXY
- && (!Curl_ssl_cf_is_proxy(cf) || !cf->conn->bits.tunnel_proxy)
-#endif
- ) {
- protocols[cur++] = ALPN_H2_LENGTH;
- memcpy(&protocols[cur], ALPN_H2, ALPN_H2_LENGTH);
- cur += ALPN_H2_LENGTH;
- }
-#endif
- protocols[cur++] = ALPN_HTTP_1_1_LENGTH;
- memcpy(&protocols[cur], ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH);
- cur += ALPN_HTTP_1_1_LENGTH;
+ if(connssl->alpn) {
+ struct alpn_proto_buf proto;
- if(SSL_SetNextProtoNego(backend->handle, protocols, cur) != SECSuccess)
+ result = Curl_alpn_to_proto_buf(&proto, connssl->alpn);
+ if(result || SSL_SetNextProtoNego(backend->handle, proto.data, proto.len)
+ != SECSuccess) {
+ failf(data, "Error setting ALPN");
goto error;
+ }
+ Curl_alpn_to_proto_str(&proto, connssl->alpn);
+ infof(data, VTLS_INFOF_ALPN_OFFER_1STR, proto.data);
}
#endif
@@ -2393,6 +2364,19 @@ static ssize_t nss_send(struct Curl_cfilter *cf,
return rc; /* number of bytes */
}
+static bool
+nss_data_pending(struct Curl_cfilter *cf, const struct Curl_easy *data)
+{
+ struct ssl_connect_data *connssl = cf->ctx;
+ PRFileDesc *fd = connssl->backend->handle->lower;
+ char buf;
+
+ (void) data;
+
+ /* Returns true in case of error to force reading. */
+ return PR_Recv(fd, (void *) &buf, 1, PR_MSG_PEEK, PR_INTERVAL_NO_WAIT) != 0;
+}
+
static ssize_t nss_recv(struct Curl_cfilter *cf,
struct Curl_easy *data, /* transfer */
char *buf, /* store read data here */
@@ -2543,7 +2527,7 @@ const struct Curl_ssl Curl_ssl_nss = {
nss_check_cxn, /* check_cxn */
/* NSS has no shutdown function provided and thus always fail */
Curl_none_shutdown, /* shutdown */
- Curl_none_data_pending, /* data_pending */
+ nss_data_pending, /* data_pending */
nss_random, /* random */
nss_cert_status_request, /* cert_status_request */
nss_connect, /* connect */
diff --git a/Utilities/cmcurl/lib/vtls/nssg.h b/Utilities/cmcurl/lib/vtls/nssg.h
index 454a38f1fb..ad7eef5801 100644
--- a/Utilities/cmcurl/lib/vtls/nssg.h
+++ b/Utilities/cmcurl/lib/vtls/nssg.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/Utilities/cmcurl/lib/vtls/openssl.c b/Utilities/cmcurl/lib/vtls/openssl.c
index c5085be3c3..e3a50bd6ef 100644
--- a/Utilities/cmcurl/lib/vtls/openssl.c
+++ b/Utilities/cmcurl/lib/vtls/openssl.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -96,6 +96,7 @@
#include "curl_memory.h"
#include "memdebug.h"
+
/* Uncomment the ALLOW_RENEG line to a real #define if you want to allow TLS
renegotiations when built with BoringSSL. Renegotiating is non-compliant
with HTTP/2 and "an extremely dangerous protocol feature". Beware.
@@ -262,6 +263,12 @@
#define HAVE_OPENSSL_VERSION
#endif
+#ifdef OPENSSL_IS_BORINGSSL
+typedef uint32_t sslerr_t;
+#else
+typedef unsigned long sslerr_t;
+#endif
+
/*
* Whether the OpenSSL version has the API needed to support sharing an
* X509_STORE between connections. The API is:
@@ -285,17 +292,17 @@
#endif /* !LIBRESSL_VERSION_NUMBER */
struct ssl_backend_data {
- struct Curl_easy *logger; /* transfer handle to pass trace logs to, only
- using sockindex 0 */
/* these ones requires specific SSL-types */
SSL_CTX* ctx;
SSL* handle;
X509* server_cert;
+ BIO_METHOD *bio_method;
CURLcode io_result; /* result of last BIO cfilter operation */
#ifndef HAVE_KEYLOG_CALLBACK
/* Set to true once a valid keylog entry has been created to avoid dupes. */
bool keylog_done;
#endif
+ bool x509_store_setup; /* x509 store has been set up */
};
#if defined(HAVE_SSL_X509_STORE_SHARE)
@@ -710,14 +717,14 @@ static int bio_cf_out_write(BIO *bio, const char *buf, int blen)
{
struct Curl_cfilter *cf = BIO_get_data(bio);
struct ssl_connect_data *connssl = cf->ctx;
- struct Curl_easy *data = connssl->call_data;
+ struct Curl_easy *data = CF_DATA_CURRENT(cf);
ssize_t nwritten;
CURLcode result = CURLE_SEND_ERROR;
DEBUGASSERT(data);
nwritten = Curl_conn_cf_send(cf->next, data, buf, blen, &result);
- /* DEBUGF(infof(data, CFMSG(cf, "bio_cf_out_write(len=%d) -> %d, err=%d"),
- blen, (int)nwritten, result)); */
+ DEBUGF(LOG_CF(data, cf, "bio_cf_out_write(len=%d) -> %d, err=%d",
+ blen, (int)nwritten, result));
BIO_clear_retry_flags(bio);
connssl->backend->io_result = result;
if(nwritten < 0) {
@@ -731,7 +738,7 @@ static int bio_cf_in_read(BIO *bio, char *buf, int blen)
{
struct Curl_cfilter *cf = BIO_get_data(bio);
struct ssl_connect_data *connssl = cf->ctx;
- struct Curl_easy *data = connssl->call_data;
+ struct Curl_easy *data = CF_DATA_CURRENT(cf);
ssize_t nread;
CURLcode result = CURLE_RECV_ERROR;
@@ -741,64 +748,75 @@ static int bio_cf_in_read(BIO *bio, char *buf, int blen)
return 0;
nread = Curl_conn_cf_recv(cf->next, data, buf, blen, &result);
- /* DEBUGF(infof(data, CFMSG(cf, "bio_cf_in_read(len=%d) -> %d, err=%d"),
- blen, (int)nread, result)); */
+ DEBUGF(LOG_CF(data, cf, "bio_cf_in_read(len=%d) -> %d, err=%d",
+ blen, (int)nread, result));
BIO_clear_retry_flags(bio);
connssl->backend->io_result = result;
if(nread < 0) {
if(CURLE_AGAIN == result)
BIO_set_retry_read(bio);
}
+
+ /* Before returning server replies to the SSL instance, we need
+ * to have setup the x509 store or verification will fail. */
+ if(!connssl->backend->x509_store_setup) {
+ result = Curl_ssl_setup_x509_store(cf, data, connssl->backend->ctx);
+ if(result) {
+ connssl->backend->io_result = result;
+ return -1;
+ }
+ connssl->backend->x509_store_setup = TRUE;
+ }
+
return (int)nread;
}
-static BIO_METHOD *bio_cf_method = NULL;
-
#if USE_PRE_1_1_API
static BIO_METHOD bio_cf_meth_1_0 = {
- BIO_TYPE_MEM,
- "OpenSSL CF BIO",
- bio_cf_out_write,
- bio_cf_in_read,
- NULL, /* puts is never called */
- NULL, /* gets is never called */
- bio_cf_ctrl,
- bio_cf_create,
- bio_cf_destroy,
- NULL
+ BIO_TYPE_MEM,
+ "OpenSSL CF BIO",
+ bio_cf_out_write,
+ bio_cf_in_read,
+ NULL, /* puts is never called */
+ NULL, /* gets is never called */
+ bio_cf_ctrl,
+ bio_cf_create,
+ bio_cf_destroy,
+ NULL
};
-static void bio_cf_init_methods(void)
+static BIO_METHOD *bio_cf_method_create(void)
{
- bio_cf_method = &bio_cf_meth_1_0;
+ return &bio_cf_meth_1_0;
}
-#define bio_cf_free_methods() Curl_nop_stmt
+#define bio_cf_method_free(m) Curl_nop_stmt
#else
-static void bio_cf_init_methods(void)
+static BIO_METHOD *bio_cf_method_create(void)
{
- bio_cf_method = BIO_meth_new(BIO_TYPE_MEM, "OpenSSL CF BIO");
- BIO_meth_set_write(bio_cf_method, &bio_cf_out_write);
- BIO_meth_set_read(bio_cf_method, &bio_cf_in_read);
- BIO_meth_set_ctrl(bio_cf_method, &bio_cf_ctrl);
- BIO_meth_set_create(bio_cf_method, &bio_cf_create);
- BIO_meth_set_destroy(bio_cf_method, &bio_cf_destroy);
+ BIO_METHOD *m = BIO_meth_new(BIO_TYPE_MEM, "OpenSSL CF BIO");
+ if(m) {
+ BIO_meth_set_write(m, &bio_cf_out_write);
+ BIO_meth_set_read(m, &bio_cf_in_read);
+ BIO_meth_set_ctrl(m, &bio_cf_ctrl);
+ BIO_meth_set_create(m, &bio_cf_create);
+ BIO_meth_set_destroy(m, &bio_cf_destroy);
+ }
+ return m;
}
-static void bio_cf_free_methods(void)
+static void bio_cf_method_free(BIO_METHOD *m)
{
- BIO_meth_free(bio_cf_method);
+ if(m)
+ BIO_meth_free(m);
}
#endif
-static bool ossl_attach_data(struct Curl_cfilter *cf,
- struct Curl_easy *data);
-
/*
* 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
@@ -930,54 +948,6 @@ static char *ossl_strerror(unsigned long error, char *buf, size_t size)
return buf;
}
-/* Return an extra data index for the transfer data.
- * This index can be used with SSL_get_ex_data() and SSL_set_ex_data().
- */
-static int ossl_get_ssl_data_index(void)
-{
- static int ssl_ex_data_data_index = -1;
- if(ssl_ex_data_data_index < 0) {
- ssl_ex_data_data_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
- }
- return ssl_ex_data_data_index;
-}
-
-/* Return an extra data index for the associated Curl_cfilter instance.
- * This index can be used with SSL_get_ex_data() and SSL_set_ex_data().
- */
-static int ossl_get_ssl_cf_index(void)
-{
- static int ssl_ex_data_cf_index = -1;
- if(ssl_ex_data_cf_index < 0) {
- ssl_ex_data_cf_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
- }
- return ssl_ex_data_cf_index;
-}
-
-/* Return an extra data index for the sockindex.
- * This index can be used with SSL_get_ex_data() and SSL_set_ex_data().
- */
-static int ossl_get_ssl_sockindex_index(void)
-{
- static int sockindex_index = -1;
- if(sockindex_index < 0) {
- sockindex_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
- }
- return sockindex_index;
-}
-
-/* Return an extra data index for proxy boolean.
- * This index can be used with SSL_get_ex_data() and SSL_set_ex_data().
- */
-static int ossl_get_proxy_index(void)
-{
- static int proxy_index = -1;
- if(proxy_index < 0) {
- proxy_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
- }
- return proxy_index;
-}
-
static int passwd_callback(char *buf, int num, int encrypting,
void *global_passwd)
{
@@ -1254,7 +1224,7 @@ SSL_CTX_use_certificate_chain_blob(SSL_CTX *ctx, const struct curl_blob *blob,
if(ret) {
X509 *ca;
- unsigned long err;
+ sslerr_t err;
if(!SSL_CTX_clear_chain_certs(ctx)) {
ret = 0;
@@ -1776,14 +1746,8 @@ static int ossl_init(void)
OpenSSL_add_all_algorithms();
#endif
- bio_cf_init_methods();
Curl_tls_keylog_open();
- /* Initialize the extra data indexes */
- if(ossl_get_ssl_data_index() < 0 || ossl_get_ssl_cf_index() < 0 ||
- ossl_get_ssl_sockindex_index() < 0 || ossl_get_proxy_index() < 0)
- return 0;
-
return 1;
}
@@ -1822,7 +1786,6 @@ static void ossl_cleanup(void)
#endif
Curl_tls_keylog_close();
- bio_cf_free_methods();
}
/*
@@ -1840,7 +1803,10 @@ static int ossl_check_cxn(struct Curl_cfilter *cf, struct Curl_easy *data)
#ifdef MSG_PEEK
char buf;
ssize_t nread;
- nread = recv((RECV_TYPE_ARG1)cf->conn->sock[cf->sockindex],
+ curl_socket_t sock = Curl_conn_cf_get_socket(cf, data);
+ if(sock == CURL_SOCKET_BAD)
+ return 0; /* no socket, consider closed */
+ nread = recv((RECV_TYPE_ARG1)sock,
(RECV_TYPE_ARG2)&buf, (RECV_TYPE_ARG3)1,
(RECV_TYPE_ARG4)MSG_PEEK);
if(nread == 0)
@@ -1968,19 +1934,15 @@ static struct curl_slist *ossl_engines_list(struct Curl_easy *data)
return list;
}
-#define set_logger(connssl, data) \
- connssl->backend->logger = data
-
static void ossl_close(struct Curl_cfilter *cf, struct Curl_easy *data)
{
struct ssl_connect_data *connssl = cf->ctx;
struct ssl_backend_data *backend = connssl->backend;
+ (void)data;
DEBUGASSERT(backend);
if(backend->handle) {
- set_logger(connssl, data);
-
if(cf->next && cf->next->connected) {
char buf[32];
/* Maybe the server has already sent a close notify alert.
@@ -1997,6 +1959,11 @@ static void ossl_close(struct Curl_cfilter *cf, struct Curl_easy *data)
if(backend->ctx) {
SSL_CTX_free(backend->ctx);
backend->ctx = NULL;
+ backend->x509_store_setup = FALSE;
+ }
+ if(backend->bio_method) {
+ bio_cf_method_free(backend->bio_method);
+ backend->bio_method = NULL;
}
}
@@ -2034,7 +2001,7 @@ static int ossl_shutdown(struct Curl_cfilter *cf,
if(backend->handle) {
buffsize = (int)sizeof(buf);
while(!done && loop--) {
- int what = SOCKET_READABLE(cf->conn->sock[cf->sockindex],
+ int what = SOCKET_READABLE(Curl_conn_cf_get_socket(cf, data),
SSL_SHUTDOWN_TIMEOUT);
if(what > 0) {
ERR_clear_error();
@@ -2163,6 +2130,22 @@ static bool subj_alt_hostcheck(struct Curl_easy *data,
return FALSE;
}
+static CURLcode
+ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn,
+ X509 *server_cert, const char *hostname,
+ const char *dispname);
+
+CURLcode Curl_ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn,
+ X509 *server_cert)
+{
+ const char *hostname, *dispname;
+ int port;
+
+ (void)conn;
+ Curl_conn_get_host(data, FIRSTSOCKET, &hostname, &dispname, &port);
+ return ossl_verifyhost(data, conn, server_cert, hostname, dispname);
+}
+
/* Quote from RFC2818 section 3.1 "Server Identity"
If a subjectAltName extension of type dNSName is present, that MUST
@@ -2185,8 +2168,10 @@ static bool subj_alt_hostcheck(struct Curl_easy *data,
This function is now used from ngtcp2 (QUIC) as well.
*/
-CURLcode Curl_ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn,
- X509 *server_cert)
+static CURLcode
+ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn,
+ X509 *server_cert, const char *hostname,
+ const char *dispname)
{
bool matched = FALSE;
int target = GEN_DNS; /* target type, GEN_DNS or GEN_IPADD */
@@ -2200,12 +2185,9 @@ CURLcode Curl_ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn,
CURLcode result = CURLE_OK;
bool dNSName = FALSE; /* if a dNSName field exists in the cert */
bool iPAddress = FALSE; /* if a iPAddress field exists in the cert */
- const char *hostname, *dispname;
- int port;
size_t hostlen;
(void)conn;
- Curl_conn_get_host(data, FIRSTSOCKET, &hostname, &dispname, &port);
hostlen = strlen(hostname);
#ifndef ENABLE_IPV6
@@ -2668,24 +2650,15 @@ static void ossl_trace(int direction, int ssl_ver, int content_type,
const void *buf, size_t len, SSL *ssl,
void *userp)
{
- char unknown[32];
- const char *verstr = NULL;
- struct connectdata *conn = userp;
- int cf_idx = ossl_get_ssl_cf_index();
- struct ssl_connect_data *connssl;
+ const char *verstr = "???";
+ struct Curl_cfilter *cf = userp;
struct Curl_easy *data = NULL;
- struct Curl_cfilter *cf;
-
- DEBUGASSERT(cf_idx >= 0);
- cf = (struct Curl_cfilter*) SSL_get_ex_data(ssl, cf_idx);
- DEBUGASSERT(cf);
- connssl = cf->ctx;
- DEBUGASSERT(connssl);
- DEBUGASSERT(connssl->backend);
- data = connssl->backend->logger;
+ char unknown[32];
- if(!conn || !data || !data->set.fdebug ||
- (direction != 0 && direction != 1))
+ if(!cf)
+ return;
+ data = CF_DATA_CURRENT(cf);
+ if(!data || !data->set.fdebug || (direction && direction != 1))
return;
switch(ssl_ver) {
@@ -2730,6 +2703,9 @@ static void ossl_trace(int direction, int ssl_ver, int content_type,
* For TLS 1.3, skip notification of the decrypted inner Content-Type.
*/
if(ssl_ver
+#ifdef SSL3_RT_HEADER
+ && content_type != SSL3_RT_HEADER
+#endif
#ifdef SSL3_RT_INNER_CONTENT_TYPE
&& content_type != SSL3_RT_INNER_CONTENT_TYPE
#endif
@@ -2765,7 +2741,7 @@ static void ossl_trace(int direction, int ssl_ver, int content_type,
}
txt_len = msnprintf(ssl_buf, sizeof(ssl_buf),
- CFMSG(cf, "%s (%s), %s, %s (%d):\n"),
+ "%s (%s), %s, %s (%d):\n",
verstr, direction?"OUT":"IN",
tls_rt_name, msg_name, msg_type);
if(0 <= txt_len && (unsigned)txt_len < sizeof(ssl_buf)) {
@@ -2983,21 +2959,14 @@ static int ossl_new_session_cb(SSL *ssl, SSL_SESSION *ssl_sessionid)
struct Curl_easy *data;
struct Curl_cfilter *cf;
const struct ssl_config_data *config;
- curl_socket_t *sockindex_ptr;
- int data_idx = ossl_get_ssl_data_index();
- int cf_idx = ossl_get_ssl_cf_index();
- int sockindex_idx = ossl_get_ssl_sockindex_index();
- int proxy_idx = ossl_get_proxy_index();
+ struct ssl_connect_data *connssl;
bool isproxy;
- if(data_idx < 0 || cf_idx < 0 || sockindex_idx < 0 || proxy_idx < 0)
- return 0;
-
- cf = (struct Curl_cfilter*) SSL_get_ex_data(ssl, cf_idx);
- data = (struct Curl_easy *) SSL_get_ex_data(ssl, data_idx);
+ cf = (struct Curl_cfilter*) SSL_get_app_data(ssl);
+ connssl = cf? cf->ctx : NULL;
+ data = connssl? CF_DATA_CURRENT(cf) : NULL;
/* The sockindex has been stored as a pointer to an array element */
- sockindex_ptr = (curl_socket_t*) SSL_get_ex_data(ssl, sockindex_idx);
- if(!cf || !data || !sockindex_ptr)
+ if(!cf || !data)
return 0;
isproxy = Curl_ssl_cf_is_proxy(cf);
@@ -3091,7 +3060,7 @@ static CURLcode load_cacert_from_memory(X509_STORE *store,
BIO_free(cbio);
/* if we didn't end up importing anything, treat that as an error */
- return (count > 0 ? CURLE_OK : CURLE_SSL_CACERT_BADFILE);
+ return (count > 0) ? CURLE_OK : CURLE_SSL_CACERT_BADFILE;
}
static CURLcode populate_x509_store(struct Curl_cfilter *cf,
@@ -3110,206 +3079,219 @@ static CURLcode populate_x509_store(struct Curl_cfilter *cf,
const char * const ssl_crlfile = ssl_config->primary.CRLfile;
const bool verifypeer = conn_config->verifypeer;
bool imported_native_ca = false;
+ bool imported_ca_info_blob = false;
if(!store)
return CURLE_OUT_OF_MEMORY;
+ if(verifypeer) {
#if defined(USE_WIN32_CRYPTO)
- /* Import certificates from the Windows root certificate store if requested.
- https://stackoverflow.com/questions/9507184/
- https://github.com/d3x0r/SACK/blob/master/src/netlib/ssl_layer.c#L1037
- https://datatracker.ietf.org/doc/html/rfc5280 */
- if((conn_config->verifypeer || conn_config->verifyhost) &&
- (ssl_config->native_ca_store)) {
- HCERTSTORE hStore = CertOpenSystemStore(0, TEXT("ROOT"));
-
- if(hStore) {
- PCCERT_CONTEXT pContext = NULL;
- /* The array of enhanced key usage OIDs will vary per certificate and is
- declared outside of the loop so that rather than malloc/free each
- iteration we can grow it with realloc, when necessary. */
- CERT_ENHKEY_USAGE *enhkey_usage = NULL;
- DWORD enhkey_usage_size = 0;
-
- /* This loop makes a best effort to import all valid certificates from
- the MS root store. If a certificate cannot be imported it is skipped.
- 'result' is used to store only hard-fail conditions (such as out of
- memory) that cause an early break. */
- result = CURLE_OK;
- for(;;) {
- X509 *x509;
- FILETIME now;
- BYTE key_usage[2];
- DWORD req_size;
- const unsigned char *encoded_cert;
+ /* Import certificates from the Windows root certificate store if
+ requested.
+ https://stackoverflow.com/questions/9507184/
+ https://github.com/d3x0r/SACK/blob/master/src/netlib/ssl_layer.c#L1037
+ https://datatracker.ietf.org/doc/html/rfc5280 */
+ if(ssl_config->native_ca_store) {
+ HCERTSTORE hStore = CertOpenSystemStore(0, TEXT("ROOT"));
+
+ if(hStore) {
+ PCCERT_CONTEXT pContext = NULL;
+ /* The array of enhanced key usage OIDs will vary per certificate and
+ is declared outside of the loop so that rather than malloc/free each
+ iteration we can grow it with realloc, when necessary. */
+ CERT_ENHKEY_USAGE *enhkey_usage = NULL;
+ DWORD enhkey_usage_size = 0;
+
+ /* This loop makes a best effort to import all valid certificates from
+ the MS root store. If a certificate cannot be imported it is
+ skipped. 'result' is used to store only hard-fail conditions (such
+ as out of memory) that cause an early break. */
+ result = CURLE_OK;
+ for(;;) {
+ X509 *x509;
+ FILETIME now;
+ BYTE key_usage[2];
+ DWORD req_size;
+ const unsigned char *encoded_cert;
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
- char cert_name[256];
+ char cert_name[256];
#endif
- pContext = CertEnumCertificatesInStore(hStore, pContext);
- if(!pContext)
- break;
+ pContext = CertEnumCertificatesInStore(hStore, pContext);
+ if(!pContext)
+ break;
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
- if(!CertGetNameStringA(pContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0,
- NULL, cert_name, sizeof(cert_name))) {
- strcpy(cert_name, "Unknown");
- }
- infof(data, "SSL: Checking cert \"%s\"", cert_name);
+ if(!CertGetNameStringA(pContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0,
+ NULL, cert_name, sizeof(cert_name))) {
+ strcpy(cert_name, "Unknown");
+ }
+ infof(data, "SSL: Checking cert \"%s\"", cert_name);
#endif
+ encoded_cert = (const unsigned char *)pContext->pbCertEncoded;
+ if(!encoded_cert)
+ continue;
- encoded_cert = (const unsigned char *)pContext->pbCertEncoded;
- if(!encoded_cert)
- continue;
-
- GetSystemTimeAsFileTime(&now);
- if(CompareFileTime(&pContext->pCertInfo->NotBefore, &now) > 0 ||
- CompareFileTime(&now, &pContext->pCertInfo->NotAfter) > 0)
- continue;
-
- /* If key usage exists check for signing attribute */
- if(CertGetIntendedKeyUsage(pContext->dwCertEncodingType,
- pContext->pCertInfo,
- key_usage, sizeof(key_usage))) {
- if(!(key_usage[0] & CERT_KEY_CERT_SIGN_KEY_USAGE))
+ GetSystemTimeAsFileTime(&now);
+ if(CompareFileTime(&pContext->pCertInfo->NotBefore, &now) > 0 ||
+ CompareFileTime(&now, &pContext->pCertInfo->NotAfter) > 0)
continue;
- }
- else if(GetLastError())
- continue;
-
- /* If enhanced key usage exists check for server auth attribute.
- *
- * Note "In a Microsoft environment, a certificate might also have EKU
- * extended properties that specify valid uses for the certificate."
- * The call below checks both, and behavior varies depending on what is
- * found. For more details see CertGetEnhancedKeyUsage doc.
- */
- if(CertGetEnhancedKeyUsage(pContext, 0, NULL, &req_size)) {
- if(req_size && req_size > enhkey_usage_size) {
- void *tmp = realloc(enhkey_usage, req_size);
-
- if(!tmp) {
- failf(data, "SSL: Out of memory allocating for OID list");
- result = CURLE_OUT_OF_MEMORY;
- break;
- }
- enhkey_usage = (CERT_ENHKEY_USAGE *)tmp;
- enhkey_usage_size = req_size;
+ /* If key usage exists check for signing attribute */
+ if(CertGetIntendedKeyUsage(pContext->dwCertEncodingType,
+ pContext->pCertInfo,
+ key_usage, sizeof(key_usage))) {
+ if(!(key_usage[0] & CERT_KEY_CERT_SIGN_KEY_USAGE))
+ continue;
}
+ else if(GetLastError())
+ continue;
- if(CertGetEnhancedKeyUsage(pContext, 0, enhkey_usage, &req_size)) {
- if(!enhkey_usage->cUsageIdentifier) {
- /* "If GetLastError returns CRYPT_E_NOT_FOUND, the certificate is
- good for all uses. If it returns zero, the certificate has no
- valid uses." */
- if((HRESULT)GetLastError() != CRYPT_E_NOT_FOUND)
- continue;
+ /* If enhanced key usage exists check for server auth attribute.
+ *
+ * Note "In a Microsoft environment, a certificate might also have
+ * EKU extended properties that specify valid uses for the
+ * certificate." The call below checks both, and behavior varies
+ * depending on what is found. For more details see
+ * CertGetEnhancedKeyUsage doc.
+ */
+ if(CertGetEnhancedKeyUsage(pContext, 0, NULL, &req_size)) {
+ if(req_size && req_size > enhkey_usage_size) {
+ void *tmp = realloc(enhkey_usage, req_size);
+
+ if(!tmp) {
+ failf(data, "SSL: Out of memory allocating for OID list");
+ result = CURLE_OUT_OF_MEMORY;
+ break;
+ }
+
+ enhkey_usage = (CERT_ENHKEY_USAGE *)tmp;
+ enhkey_usage_size = req_size;
}
- else {
- DWORD i;
- bool found = false;
-
- for(i = 0; i < enhkey_usage->cUsageIdentifier; ++i) {
- if(!strcmp("1.3.6.1.5.5.7.3.1" /* OID server auth */,
- enhkey_usage->rgpszUsageIdentifier[i])) {
- found = true;
- break;
- }
+
+ if(CertGetEnhancedKeyUsage(pContext, 0, enhkey_usage, &req_size)) {
+ if(!enhkey_usage->cUsageIdentifier) {
+ /* "If GetLastError returns CRYPT_E_NOT_FOUND, the certificate
+ is good for all uses. If it returns zero, the certificate
+ has no valid uses." */
+ if((HRESULT)GetLastError() != CRYPT_E_NOT_FOUND)
+ continue;
}
+ else {
+ DWORD i;
+ bool found = false;
+
+ for(i = 0; i < enhkey_usage->cUsageIdentifier; ++i) {
+ if(!strcmp("1.3.6.1.5.5.7.3.1" /* OID server auth */,
+ enhkey_usage->rgpszUsageIdentifier[i])) {
+ found = true;
+ break;
+ }
+ }
- if(!found)
- continue;
+ if(!found)
+ continue;
+ }
}
+ else
+ continue;
}
else
continue;
- }
- else
- continue;
- x509 = d2i_X509(NULL, &encoded_cert, pContext->cbCertEncoded);
- if(!x509)
- continue;
+ x509 = d2i_X509(NULL, &encoded_cert, pContext->cbCertEncoded);
+ if(!x509)
+ continue;
- /* Try to import the certificate. This may fail for legitimate reasons
- such as duplicate certificate, which is allowed by MS but not
- OpenSSL. */
- if(X509_STORE_add_cert(store, x509) == 1) {
+ /* Try to import the certificate. This may fail for legitimate
+ reasons such as duplicate certificate, which is allowed by MS but
+ not OpenSSL. */
+ if(X509_STORE_add_cert(store, x509) == 1) {
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
- infof(data, "SSL: Imported cert \"%s\"", cert_name);
+ infof(data, "SSL: Imported cert \"%s\"", cert_name);
#endif
- imported_native_ca = true;
+ imported_native_ca = true;
+ }
+ X509_free(x509);
}
- X509_free(x509);
- }
- free(enhkey_usage);
- CertFreeCertificateContext(pContext);
- CertCloseStore(hStore, 0);
+ free(enhkey_usage);
+ CertFreeCertificateContext(pContext);
+ CertCloseStore(hStore, 0);
- if(result)
- return result;
+ if(result)
+ return result;
+ }
+ if(imported_native_ca)
+ infof(data, "successfully imported Windows CA store");
+ else
+ infof(data, "error importing Windows CA store, continuing anyway");
}
- if(imported_native_ca)
- infof(data, "successfully imported Windows CA store");
- else
- infof(data, "error importing Windows CA store, continuing anyway");
- }
#endif
-
- if(ca_info_blob) {
- result = load_cacert_from_memory(store, ca_info_blob);
- if(result) {
- if(result == CURLE_OUT_OF_MEMORY ||
- (verifypeer && !imported_native_ca)) {
+ if(ca_info_blob) {
+ result = load_cacert_from_memory(store, ca_info_blob);
+ if(result) {
failf(data, "error importing CA certificate blob");
return result;
}
- /* Only warn if no certificate verification is required. */
- infof(data, "error importing CA certificate blob, continuing anyway");
+ else {
+ imported_ca_info_blob = true;
+ infof(data, "successfully imported CA certificate blob");
+ }
}
- }
- if(verifypeer && !imported_native_ca && (ssl_cafile || ssl_capath)) {
+ if(ssl_cafile || ssl_capath) {
#if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3)
- /* OpenSSL 3.0.0 has deprecated SSL_CTX_load_verify_locations */
- if(ssl_cafile &&
- !X509_STORE_load_file(store, ssl_cafile)) {
- /* Fail if we insist on successfully verifying the server. */
- failf(data, "error setting certificate file: %s", ssl_cafile);
- return CURLE_SSL_CACERT_BADFILE;
- }
- if(ssl_capath &&
- !X509_STORE_load_path(store, ssl_capath)) {
- /* Fail if we insist on successfully verifying the server. */
- failf(data, "error setting certificate path: %s", ssl_capath);
- return CURLE_SSL_CACERT_BADFILE;
- }
+ /* OpenSSL 3.0.0 has deprecated SSL_CTX_load_verify_locations */
+ if(ssl_cafile && !X509_STORE_load_file(store, ssl_cafile)) {
+ if(!imported_native_ca && !imported_ca_info_blob) {
+ /* Fail if we insist on successfully verifying the server. */
+ failf(data, "error setting certificate file: %s", ssl_cafile);
+ return CURLE_SSL_CACERT_BADFILE;
+ }
+ else
+ infof(data, "error setting certificate file, continuing anyway");
+ }
+ if(ssl_capath && !X509_STORE_load_path(store, ssl_capath)) {
+ if(!imported_native_ca && !imported_ca_info_blob) {
+ /* Fail if we insist on successfully verifying the server. */
+ failf(data, "error setting certificate path: %s", ssl_capath);
+ return CURLE_SSL_CACERT_BADFILE;
+ }
+ else
+ infof(data, "error setting certificate path, continuing anyway");
+ }
#else
- /* tell OpenSSL where to find CA certificates that are used to verify the
- server's certificate. */
- if(!X509_STORE_load_locations(store, ssl_cafile, ssl_capath)) {
- /* Fail if we insist on successfully verifying the server. */
- failf(data, "error setting certificate verify locations:"
- " CAfile: %s CApath: %s",
- ssl_cafile ? ssl_cafile : "none",
- ssl_capath ? ssl_capath : "none");
- return CURLE_SSL_CACERT_BADFILE;
- }
+ /* tell OpenSSL where to find CA certificates that are used to verify the
+ server's certificate. */
+ if(!X509_STORE_load_locations(store, ssl_cafile, ssl_capath)) {
+ if(!imported_native_ca && !imported_ca_info_blob) {
+ /* Fail if we insist on successfully verifying the server. */
+ failf(data, "error setting certificate verify locations:"
+ " CAfile: %s CApath: %s",
+ ssl_cafile ? ssl_cafile : "none",
+ ssl_capath ? ssl_capath : "none");
+ return CURLE_SSL_CACERT_BADFILE;
+ }
+ else {
+ infof(data, "error setting certificate verify locations,"
+ " continuing anyway");
+ }
+ }
#endif
- infof(data, " CAfile: %s", ssl_cafile ? ssl_cafile : "none");
- infof(data, " CApath: %s", ssl_capath ? ssl_capath : "none");
- }
+ infof(data, " CAfile: %s", ssl_cafile ? ssl_cafile : "none");
+ infof(data, " CApath: %s", ssl_capath ? ssl_capath : "none");
+ }
#ifdef CURL_CA_FALLBACK
- if(verifypeer &&
- !ca_info_blob && !ssl_cafile && !ssl_capath && !imported_native_ca) {
- /* verifying the peer without any CA certificates won't
- work so use openssl's built-in default as fallback */
- X509_STORE_set_default_paths(store);
- }
+ if(!ssl_cafile && !ssl_capath &&
+ !imported_native_ca && !imported_ca_info_blob) {
+ /* verifying the peer without any CA certificates won't
+ work so use openssl's built-in default as fallback */
+ X509_STORE_set_default_paths(store);
+ }
#endif
+ }
if(ssl_crlfile) {
/* tell OpenSSL where to find CRL file that is used to check certificate
@@ -3440,9 +3422,9 @@ static void set_cached_x509_store(struct Curl_cfilter *cf,
}
}
-static CURLcode set_up_x509_store(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- struct ssl_backend_data *backend)
+CURLcode Curl_ssl_setup_x509_store(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ SSL_CTX *ssl_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);
@@ -3462,10 +3444,10 @@ static CURLcode set_up_x509_store(struct Curl_cfilter *cf,
cached_store = get_cached_x509_store(cf, data);
if(cached_store && cache_criteria_met && X509_STORE_up_ref(cached_store)) {
- SSL_CTX_set_cert_store(backend->ctx, cached_store);
+ SSL_CTX_set_cert_store(ssl_ctx, cached_store);
}
else {
- X509_STORE *store = SSL_CTX_get_cert_store(backend->ctx);
+ X509_STORE *store = SSL_CTX_get_cert_store(ssl_ctx);
result = populate_x509_store(cf, data, store);
if(result == CURLE_OK && cache_criteria_met) {
@@ -3476,11 +3458,11 @@ static CURLcode set_up_x509_store(struct Curl_cfilter *cf,
return result;
}
#else /* HAVE_SSL_X509_STORE_SHARE */
-static CURLcode set_up_x509_store(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- struct ssl_backend_data *backend)
+CURLcode Curl_ssl_setup_x509_store(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ SSL_CTX *ssl_ctx)
{
- X509_STORE *store = SSL_CTX_get_cert_store(backend->ctx);
+ X509_STORE *store = SSL_CTX_get_cert_store(ssl_ctx);
return populate_x509_store(cf, data, store);
}
@@ -3510,9 +3492,6 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf,
#endif
#endif
const long int ssl_version = conn_config->version;
-#ifdef USE_OPENSSL_SRP
- const enum CURL_TLSAUTH ssl_authtype = ssl_config->primary.authtype;
-#endif
char * const ssl_cert = ssl_config->primary.clientcert;
const struct curl_blob *ssl_cert_blob = ssl_config->primary.cert_blob;
const char * const ssl_cert_type = ssl_config->cert_type;
@@ -3580,8 +3559,7 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf,
if(data->set.fdebug && data->set.verbose) {
/* the SSL trace callback is only used for verbose logging */
SSL_CTX_set_msg_callback(backend->ctx, ossl_trace);
- SSL_CTX_set_msg_callback_arg(backend->ctx, cf->conn);
- set_logger(connssl, data);
+ SSL_CTX_set_msg_callback_arg(backend->ctx, cf);
}
#endif
@@ -3677,36 +3655,17 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf,
SSL_CTX_set_options(backend->ctx, ctx_options);
#ifdef HAS_ALPN
- if(cf->conn->bits.tls_enable_alpn) {
- int cur = 0;
- unsigned char protocols[128];
-
-#ifdef USE_HTTP2
- if(data->state.httpwant >= CURL_HTTP_VERSION_2
-#ifndef CURL_DISABLE_PROXY
- && (!Curl_ssl_cf_is_proxy(cf) || !cf->conn->bits.tunnel_proxy)
-#endif
- ) {
- protocols[cur++] = ALPN_H2_LENGTH;
-
- memcpy(&protocols[cur], ALPN_H2, ALPN_H2_LENGTH);
- cur += ALPN_H2_LENGTH;
- infof(data, VTLS_INFOF_ALPN_OFFER_1STR, ALPN_H2);
- }
-#endif
-
- protocols[cur++] = ALPN_HTTP_1_1_LENGTH;
- memcpy(&protocols[cur], ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH);
- cur += ALPN_HTTP_1_1_LENGTH;
- infof(data, VTLS_INFOF_ALPN_OFFER_1STR, ALPN_HTTP_1_1);
+ if(connssl->alpn) {
+ struct alpn_proto_buf proto;
- /* expects length prefixed preference ordered list of protocols in wire
- * format
- */
- if(SSL_CTX_set_alpn_protos(backend->ctx, protocols, cur)) {
+ result = Curl_alpn_to_proto_buf(&proto, connssl->alpn);
+ if(result ||
+ SSL_CTX_set_alpn_protos(backend->ctx, proto.data, proto.len)) {
failf(data, "Error setting ALPN");
return CURLE_SSL_CONNECT_ERROR;
}
+ Curl_alpn_to_proto_str(&proto, connssl->alpn);
+ infof(data, VTLS_INFOF_ALPN_OFFER_1STR, proto.data);
}
#endif
@@ -3764,8 +3723,7 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf,
#endif
#ifdef USE_OPENSSL_SRP
- if((ssl_authtype == CURL_TLSAUTH_SRP) &&
- Curl_auth_allowed_to_host(data)) {
+ if(ssl_config->primary.username && Curl_auth_allowed_to_host(data)) {
char * const ssl_username = ssl_config->primary.username;
char * const ssl_password = ssl_config->primary.password;
infof(data, "Using TLS-SRP username: %s", ssl_username);
@@ -3789,10 +3747,6 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf,
}
#endif
- result = set_up_x509_store(cf, data, backend);
- if(result)
- return result;
-
/* OpenSSL always tries to verify the peer, this only says whether it should
* 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
@@ -3836,6 +3790,8 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf,
return CURLE_OUT_OF_MEMORY;
}
+ SSL_set_app_data(backend->handle, cf);
+
#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \
!defined(OPENSSL_NO_OCSP)
if(conn_config->verifystatus)
@@ -3863,13 +3819,7 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf,
}
#endif
- if(!ossl_attach_data(cf, data)) {
- /* Maybe the internal errors of SSL_get_ex_new_index or SSL_set_ex_data */
- failf(data, "SSL: ossl_attach_data failed: %s",
- ossl_strerror(ERR_get_error(), error_buffer,
- sizeof(error_buffer)));
- return CURLE_SSL_CONNECT_ERROR;
- }
+ SSL_set_app_data(backend->handle, cf);
if(ssl_config->primary.sessionid) {
Curl_ssl_sessionid_lock(data);
@@ -3888,13 +3838,26 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf,
Curl_ssl_sessionid_unlock(data);
}
- bio = BIO_new(bio_cf_method);
+ backend->bio_method = bio_cf_method_create();
+ if(!backend->bio_method)
+ return CURLE_OUT_OF_MEMORY;
+ bio = BIO_new(backend->bio_method);
if(!bio)
return CURLE_OUT_OF_MEMORY;
BIO_set_data(bio, cf);
+#ifdef HAVE_SSL_SET0_WBIO
+ /* with OpenSSL v1.1.1 we get an alternative to SSL_set_bio() that works
+ * without backward compat quirks. Every call takes one reference, so we
+ * up it and pass. SSL* then owns it and will free.
+ * We check on the function in configure, since libressl and friends
+ * each have their own versions to add support for this. */
+ BIO_up_ref(bio);
+ SSL_set0_rbio(backend->handle, bio);
+ SSL_set0_wbio(backend->handle, bio);
+#else
SSL_set_bio(backend->handle, bio, bio);
-
+#endif
connssl->connecting_state = ssl_connect_2;
return CURLE_OK;
@@ -3915,6 +3878,16 @@ static CURLcode ossl_connect_step2(struct Curl_cfilter *cf,
ERR_clear_error();
err = SSL_connect(backend->handle);
+
+ if(!backend->x509_store_setup) {
+ /* After having send off the ClientHello, we prepare the x509
+ * store to verify the coming certificate from the server */
+ CURLcode result = Curl_ssl_setup_x509_store(cf, data, backend->ctx);
+ if(result)
+ return result;
+ backend->x509_store_setup = TRUE;
+ }
+
#ifndef HAVE_KEYLOG_CALLBACK
if(Curl_tls_keylog_enabled()) {
/* If key logging is enabled, wait for the handshake to complete and then
@@ -3949,7 +3922,7 @@ static CURLcode ossl_connect_step2(struct Curl_cfilter *cf,
}
else {
/* untreated error */
- unsigned long errdetail;
+ sslerr_t errdetail;
char error_buffer[256]="";
CURLcode result;
long lerr;
@@ -4043,26 +4016,8 @@ static CURLcode ossl_connect_step2(struct Curl_cfilter *cf,
const unsigned char *neg_protocol;
unsigned int len;
SSL_get0_alpn_selected(backend->handle, &neg_protocol, &len);
- if(len) {
- infof(data, VTLS_INFOF_ALPN_ACCEPTED_LEN_1STR, len, neg_protocol);
-
-#ifdef USE_HTTP2
- if(len == ALPN_H2_LENGTH &&
- !memcmp(ALPN_H2, neg_protocol, len)) {
- cf->conn->alpn = CURL_HTTP_VERSION_2;
- }
- else
-#endif
- if(len == ALPN_HTTP_1_1_LENGTH &&
- !memcmp(ALPN_HTTP_1_1, neg_protocol, ALPN_HTTP_1_1_LENGTH)) {
- cf->conn->alpn = CURL_HTTP_VERSION_1_1;
- }
- }
- else
- infof(data, VTLS_INFOF_NO_ALPN);
- Curl_multiuse_state(data, cf->conn->alpn == CURL_HTTP_VERSION_2 ?
- BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
+ return Curl_alpn_set_negotiated(cf, data, neg_protocol, len);
}
#endif
@@ -4205,7 +4160,8 @@ static CURLcode servercert(struct Curl_cfilter *cf,
BIO_free(mem);
if(conn_config->verifyhost) {
- result = Curl_ossl_verifyhost(data, conn, backend->server_cert);
+ result = ossl_verifyhost(data, conn, backend->server_cert,
+ connssl->hostname, connssl->dispname);
if(result) {
X509_free(backend->server_cert);
backend->server_cert = NULL;
@@ -4379,7 +4335,7 @@ static CURLcode ossl_connect_common(struct Curl_cfilter *cf,
{
CURLcode result = CURLE_OK;
struct ssl_connect_data *connssl = cf->ctx;
- curl_socket_t sockfd = cf->conn->sock[cf->sockindex];
+ curl_socket_t sockfd = Curl_conn_cf_get_socket(cf, data);
int what;
/* check if the connection has already been established */
@@ -4418,8 +4374,9 @@ static CURLcode ossl_connect_common(struct Curl_cfilter *cf,
}
/* if ssl is expecting something, check if it's available. */
- if(connssl->connecting_state == ssl_connect_2_reading ||
- connssl->connecting_state == ssl_connect_2_writing) {
+ if(!nonblocking &&
+ (connssl->connecting_state == ssl_connect_2_reading ||
+ connssl->connecting_state == ssl_connect_2_writing)) {
curl_socket_t writefd = ssl_connect_2_writing ==
connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
@@ -4427,7 +4384,7 @@ static CURLcode ossl_connect_common(struct Curl_cfilter *cf,
connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
- nonblocking?0:timeout_ms);
+ timeout_ms);
if(what < 0) {
/* fatal error */
failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
@@ -4435,11 +4392,6 @@ static CURLcode ossl_connect_common(struct Curl_cfilter *cf,
goto out;
}
if(0 == what) {
- if(nonblocking) {
- *done = FALSE;
- result = CURLE_OK;
- goto out;
- }
/* timeout */
failf(data, "SSL connection timeout");
result = CURLE_OPERATION_TIMEDOUT;
@@ -4527,7 +4479,7 @@ static ssize_t ossl_send(struct Curl_cfilter *cf,
'size_t' */
int err;
char error_buffer[256];
- unsigned long sslerror;
+ sslerr_t sslerror;
int memlen;
int rc;
struct ssl_connect_data *connssl = cf->ctx;
@@ -4539,7 +4491,6 @@ static ssize_t ossl_send(struct Curl_cfilter *cf,
ERR_clear_error();
memlen = (len > (size_t)INT_MAX) ? INT_MAX : (int)len;
- set_logger(connssl, data);
rc = SSL_write(backend->handle, mem, memlen);
if(rc <= 0) {
@@ -4636,7 +4587,6 @@ static ssize_t ossl_recv(struct Curl_cfilter *cf,
ERR_clear_error();
buffsize = (buffersize > (size_t)INT_MAX) ? INT_MAX : (int)buffersize;
- set_logger(connssl, data);
nread = (ssize_t)SSL_read(backend->handle, buf, buffsize);
if(nread <= 0) {
@@ -4854,89 +4804,6 @@ static void *ossl_get_internals(struct ssl_connect_data *connssl,
(void *)backend->ctx : (void *)backend->handle;
}
-static bool ossl_attach_data(struct Curl_cfilter *cf,
- struct Curl_easy *data)
-{
- struct ssl_connect_data *connssl = cf->ctx;
- struct ssl_backend_data *backend = connssl->backend;
- const struct ssl_config_data *config;
-
- DEBUGASSERT(backend);
-
- /* If we don't have SSL context, do nothing. */
- if(!backend->handle)
- return FALSE;
-
- config = Curl_ssl_cf_get_config(cf, data);
- if(config->primary.sessionid) {
- int data_idx = ossl_get_ssl_data_index();
- int cf_idx = ossl_get_ssl_cf_index();
- int sockindex_idx = ossl_get_ssl_sockindex_index();
- int proxy_idx = ossl_get_proxy_index();
-
- if(data_idx >= 0 && cf_idx >= 0 && sockindex_idx >= 0 &&
- proxy_idx >= 0) {
- int data_status, cf_status, sockindex_status, proxy_status;
-
- /* Store the data needed for the "new session" callback.
- * The sockindex is stored as a pointer to an array element. */
- data_status = SSL_set_ex_data(backend->handle, data_idx, data);
- cf_status = SSL_set_ex_data(backend->handle, cf_idx, cf);
- sockindex_status = SSL_set_ex_data(backend->handle, sockindex_idx,
- cf->conn->sock + cf->sockindex);
-#ifndef CURL_DISABLE_PROXY
- proxy_status = SSL_set_ex_data(backend->handle, proxy_idx,
- Curl_ssl_cf_is_proxy(cf)?
- (void *) 1 : NULL);
-#else
- proxy_status = SSL_set_ex_data(backend->handle, proxy_idx, NULL);
-#endif
- if(data_status && cf_status && sockindex_status && proxy_status)
- return TRUE;
- }
- return FALSE;
- }
- return TRUE;
-}
-
-/*
- * Starting with TLS 1.3, the ossl_new_session_cb callback gets called after
- * the handshake. If the transfer that sets up the callback gets killed before
- * this callback arrives, we must make sure to properly clear the data to
- * avoid UAF problems. A future optimization could be to instead store another
- * transfer that might still be using the same connection.
- */
-
-static void ossl_detach_data(struct Curl_cfilter *cf,
- struct Curl_easy *data)
-{
- struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
- struct ssl_connect_data *connssl = cf->ctx;
- struct ssl_backend_data *backend = connssl->backend;
- DEBUGASSERT(backend);
-
- /* If we don't have SSL context, do nothing. */
- if(!backend->handle)
- return;
-
- if(ssl_config->primary.sessionid) {
- int data_idx = ossl_get_ssl_data_index();
- int cf_idx = ossl_get_ssl_cf_index();
- int sockindex_idx = ossl_get_ssl_sockindex_index();
- int proxy_idx = ossl_get_proxy_index();
-
- if(data_idx >= 0 && cf_idx >= 0 && sockindex_idx >= 0 &&
- proxy_idx >= 0) {
- /* Disable references to data in "new session" callback to avoid
- * accessing a stale pointer. */
- SSL_set_ex_data(backend->handle, data_idx, NULL);
- SSL_set_ex_data(backend->handle, cf_idx, NULL);
- SSL_set_ex_data(backend->handle, sockindex_idx, NULL);
- SSL_set_ex_data(backend->handle, proxy_idx, NULL);
- }
- }
-}
-
static void ossl_free_multi_ssl_backend_data(
struct multi_ssl_backend_data *mbackend)
{
@@ -4990,8 +4857,8 @@ const struct Curl_ssl Curl_ssl_openssl = {
#else
NULL, /* sha256sum */
#endif
- ossl_attach_data, /* use of data in this connection */
- ossl_detach_data, /* remote of data from this connection */
+ NULL, /* use of data in this connection */
+ NULL, /* remote of data from this connection */
ossl_free_multi_ssl_backend_data, /* free_multi_ssl_backend_data */
ossl_recv, /* recv decrypted data */
ossl_send, /* send data to encrypt */
diff --git a/Utilities/cmcurl/lib/vtls/openssl.h b/Utilities/cmcurl/lib/vtls/openssl.h
index 9df4ecddba..950faab889 100644
--- a/Utilities/cmcurl/lib/vtls/openssl.h
+++ b/Utilities/cmcurl/lib/vtls/openssl.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -56,5 +56,14 @@ CURLcode Curl_ossl_set_client_cert(struct Curl_easy *data,
CURLcode Curl_ossl_certchain(struct Curl_easy *data, SSL *ssl);
+/**
+ * Setup the OpenSSL X509_STORE in `ssl_ctx` for the cfilter `cf` and
+ * easy handle `data`. Will allow reuse of a shared cache if suitable
+ * and configured.
+ */
+CURLcode Curl_ssl_setup_x509_store(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ SSL_CTX *ssl_ctx);
+
#endif /* USE_OPENSSL */
#endif /* HEADER_CURL_SSLUSE_H */
diff --git a/Utilities/cmcurl/lib/vtls/rustls.c b/Utilities/cmcurl/lib/vtls/rustls.c
index 27f4ec8d8c..003533dbb9 100644
--- a/Utilities/cmcurl/lib/vtls/rustls.c
+++ b/Utilities/cmcurl/lib/vtls/rustls.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2020 - 2022, Jacob Hoffman-Andrews,
+ * Copyright (C) Jacob Hoffman-Andrews,
* <github@hoffman-andrews.com>
*
* This software is licensed as described in the file COPYING, which
@@ -150,6 +150,7 @@ cr_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
size_t plain_bytes_copied = 0;
rustls_result rresult = 0;
char errorbuf[255];
+ size_t errorlen;
rustls_io_result io_error;
DEBUGASSERT(backend);
@@ -161,7 +162,7 @@ cr_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
io_error = rustls_connection_read_tls(rconn, read_cb, &io_ctx,
&tls_bytes_read);
if(io_error == EAGAIN || io_error == EWOULDBLOCK) {
- infof(data, CFMSG(cf, "cr_recv: EAGAIN or EWOULDBLOCK"));
+ DEBUGF(LOG_CF(data, cf, "cr_recv: EAGAIN or EWOULDBLOCK"));
}
else if(io_error) {
char buffer[STRERROR_LEN];
@@ -171,12 +172,13 @@ cr_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
return -1;
}
- infof(data, CFMSG(cf, "cr_recv: read %ld TLS bytes"), tls_bytes_read);
+ DEBUGF(LOG_CF(data, cf, "cr_recv: read %ld TLS bytes", tls_bytes_read));
rresult = rustls_connection_process_new_packets(rconn);
if(rresult != RUSTLS_RESULT_OK) {
- rustls_error(rresult, errorbuf, sizeof(errorbuf), &n);
- failf(data, "%.*s", n, errorbuf);
+ rustls_error(rresult, errorbuf, sizeof(errorbuf), &errorlen);
+ failf(data, "rustls_connection_process_new_packets: %.*s",
+ errorlen, errorbuf);
*err = map_error(rresult);
return -1;
}
@@ -189,14 +191,21 @@ cr_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
plainlen - plain_bytes_copied,
&n);
if(rresult == RUSTLS_RESULT_PLAINTEXT_EMPTY) {
- infof(data, CFMSG(cf, "cr_recv: got PLAINTEXT_EMPTY. "
- "will try again later."));
+ DEBUGF(LOG_CF(data, cf, "cr_recv: got PLAINTEXT_EMPTY. "
+ "will try again later."));
backend->data_pending = FALSE;
break;
}
+ else if(rresult == RUSTLS_RESULT_UNEXPECTED_EOF) {
+ failf(data, "rustls: peer closed TCP connection "
+ "without first closing TLS connection");
+ *err = CURLE_READ_ERROR;
+ return -1;
+ }
else if(rresult != RUSTLS_RESULT_OK) {
/* n always equals 0 in this case, don't need to check it */
- failf(data, "error in rustls_connection_read: %d", rresult);
+ rustls_error(rresult, errorbuf, sizeof(errorbuf), &errorlen);
+ failf(data, "rustls_connection_read: %.*s", errorlen, errorbuf);
*err = CURLE_READ_ERROR;
return -1;
}
@@ -207,7 +216,7 @@ cr_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
break;
}
else {
- infof(data, CFMSG(cf, "cr_recv: got %ld plain bytes"), n);
+ DEBUGF(LOG_CF(data, cf, "cr_recv: got %ld plain bytes", n));
plain_bytes_copied += n;
}
}
@@ -254,22 +263,25 @@ cr_send(struct Curl_cfilter *cf, struct Curl_easy *data,
size_t tlswritten_total = 0;
rustls_result rresult;
rustls_io_result io_error;
+ char errorbuf[256];
+ size_t errorlen;
DEBUGASSERT(backend);
rconn = backend->conn;
- infof(data, CFMSG(cf, "cr_send: %ld plain bytes"), plainlen);
+ DEBUGF(LOG_CF(data, cf, "cr_send: %ld plain bytes", plainlen));
if(plainlen > 0) {
rresult = rustls_connection_write(rconn, plainbuf, plainlen,
&plainwritten);
if(rresult != RUSTLS_RESULT_OK) {
- failf(data, "error in rustls_connection_write");
+ rustls_error(rresult, errorbuf, sizeof(errorbuf), &errorlen);
+ failf(data, "rustls_connection_write: %.*s", errorlen, errorbuf);
*err = CURLE_WRITE_ERROR;
return -1;
}
else if(plainwritten == 0) {
- failf(data, "EOF in rustls_connection_write");
+ failf(data, "rustls_connection_write: EOF");
*err = CURLE_WRITE_ERROR;
return -1;
}
@@ -282,8 +294,8 @@ cr_send(struct Curl_cfilter *cf, struct Curl_easy *data,
io_error = rustls_connection_write_tls(rconn, write_cb, &io_ctx,
&tlswritten);
if(io_error == EAGAIN || io_error == EWOULDBLOCK) {
- infof(data, CFMSG(cf, "cr_send: EAGAIN after %ld bytes"),
- tlswritten_total);
+ DEBUGF(LOG_CF(data, cf, "cr_send: EAGAIN after %zu bytes",
+ tlswritten_total));
*err = CURLE_AGAIN;
return -1;
}
@@ -299,7 +311,7 @@ cr_send(struct Curl_cfilter *cf, struct Curl_easy *data,
*err = CURLE_WRITE_ERROR;
return -1;
}
- infof(data, CFMSG(cf, "cr_send: wrote %ld TLS bytes"), tlswritten);
+ DEBUGF(LOG_CF(data, cf, "cr_send: wrote %zu TLS bytes", tlswritten));
tlswritten_total += tlswritten;
}
@@ -349,22 +361,25 @@ cr_init_backend(struct Curl_cfilter *cf, struct Curl_easy *data,
char errorbuf[256];
size_t errorlen;
int result;
- rustls_slice_bytes alpn[2] = {
- { (const uint8_t *)ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH },
- { (const uint8_t *)ALPN_H2, ALPN_H2_LENGTH },
- };
DEBUGASSERT(backend);
rconn = backend->conn;
config_builder = rustls_client_config_builder_new();
-#ifdef USE_HTTP2
- infof(data, VTLS_INFOF_ALPN_OFFER_1STR, ALPN_H2);
- rustls_client_config_builder_set_alpn_protocols(config_builder, alpn, 2);
-#else
- rustls_client_config_builder_set_alpn_protocols(config_builder, alpn, 1);
-#endif
- infof(data, VTLS_INFOF_ALPN_OFFER_1STR, ALPN_HTTP_1_1);
+ if(connssl->alpn) {
+ struct alpn_proto_buf proto;
+ rustls_slice_bytes alpn[ALPN_ENTRIES_MAX];
+ size_t i;
+
+ for(i = 0; i < connssl->alpn->count; ++i) {
+ alpn[i].data = (const uint8_t *)connssl->alpn->entries[i];
+ alpn[i].len = strlen(connssl->alpn->entries[i]);
+ }
+ rustls_client_config_builder_set_alpn_protocols(config_builder, alpn,
+ connssl->alpn->count);
+ Curl_alpn_to_proto_str(&proto, connssl->alpn);
+ infof(data, VTLS_INFOF_ALPN_OFFER_1STR, proto.data);
+ }
if(!verifypeer) {
rustls_client_config_builder_dangerous_set_certificate_verifier(
config_builder, cr_verify_none);
@@ -384,7 +399,7 @@ cr_init_backend(struct Curl_cfilter *cf, struct Curl_easy *data,
result = rustls_root_cert_store_add_pem(roots, ca_info_blob->data,
ca_info_blob->len, verifypeer);
if(result != RUSTLS_RESULT_OK) {
- failf(data, "failed to parse trusted certificates from blob");
+ failf(data, "rustls: failed to parse trusted certificates from blob");
rustls_root_cert_store_free(roots);
rustls_client_config_free(
rustls_client_config_builder_build(config_builder));
@@ -394,7 +409,7 @@ cr_init_backend(struct Curl_cfilter *cf, struct Curl_easy *data,
result = rustls_client_config_builder_use_roots(config_builder, roots);
rustls_root_cert_store_free(roots);
if(result != RUSTLS_RESULT_OK) {
- failf(data, "failed to load trusted certificates");
+ failf(data, "rustls: failed to load trusted certificates");
rustls_client_config_free(
rustls_client_config_builder_build(config_builder));
return CURLE_SSL_CACERT_BADFILE;
@@ -404,7 +419,7 @@ cr_init_backend(struct Curl_cfilter *cf, struct Curl_easy *data,
result = rustls_client_config_builder_load_roots_from_file(
config_builder, ssl_cafile);
if(result != RUSTLS_RESULT_OK) {
- failf(data, "failed to load trusted certificates");
+ failf(data, "rustls: failed to load trusted certificates");
rustls_client_config_free(
rustls_client_config_builder_build(config_builder));
return CURLE_SSL_CACERT_BADFILE;
@@ -416,7 +431,7 @@ cr_init_backend(struct Curl_cfilter *cf, struct Curl_easy *data,
{
char *snihost = Curl_ssl_snihost(data, hostname, NULL);
if(!snihost) {
- failf(data, "Failed to set SNI");
+ failf(data, "rustls: failed to get SNI");
return CURLE_SSL_CONNECT_ERROR;
}
result = rustls_client_connection_new(backend->config, snihost, &rconn);
@@ -439,29 +454,7 @@ cr_set_negotiated_alpn(struct Curl_cfilter *cf, struct Curl_easy *data,
size_t len = 0;
rustls_connection_get_alpn_protocol(rconn, &protocol, &len);
- if(!protocol) {
- infof(data, VTLS_INFOF_NO_ALPN);
- return;
- }
-
-#ifdef USE_HTTP2
- if(len == ALPN_H2_LENGTH && 0 == memcmp(ALPN_H2, protocol, len)) {
- infof(data, VTLS_INFOF_ALPN_ACCEPTED_1STR, ALPN_H2);
- cf->conn->alpn = CURL_HTTP_VERSION_2;
- }
- else
-#endif
- if(len == ALPN_HTTP_1_1_LENGTH &&
- 0 == memcmp(ALPN_HTTP_1_1, protocol, len)) {
- infof(data, VTLS_INFOF_ALPN_ACCEPTED_1STR, ALPN_HTTP_1_1);
- cf->conn->alpn = CURL_HTTP_VERSION_1_1;
- }
- else {
- infof(data, "ALPN, negotiated an unrecognized protocol");
- }
-
- Curl_multiuse_state(data, cf->conn->alpn == CURL_HTTP_VERSION_2 ?
- BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
+ Curl_alpn_set_negotiated(cf, data, protocol, len);
}
static CURLcode
@@ -469,7 +462,7 @@ cr_connect_nonblocking(struct Curl_cfilter *cf,
struct Curl_easy *data, bool *done)
{
struct ssl_connect_data *const connssl = cf->ctx;
- curl_socket_t sockfd = cf->conn->sock[cf->sockindex];
+ curl_socket_t sockfd = Curl_conn_cf_get_socket(cf, data);
struct ssl_backend_data *const backend = connssl->backend;
struct rustls_connection *rconn = NULL;
CURLcode tmperr = CURLE_OK;
@@ -573,7 +566,7 @@ cr_get_select_socks(struct Curl_cfilter *cf, struct Curl_easy *data,
curl_socket_t *socks)
{
struct ssl_connect_data *const connssl = cf->ctx;
- curl_socket_t sockfd = cf->conn->sock[cf->sockindex];
+ curl_socket_t sockfd = Curl_conn_cf_get_socket(cf, data);
struct ssl_backend_data *const backend = connssl->backend;
struct rustls_connection *rconn = NULL;
@@ -616,7 +609,7 @@ cr_close(struct Curl_cfilter *cf, struct Curl_easy *data)
rustls_connection_send_close_notify(backend->conn);
n = cr_send(cf, data, NULL, 0, &tmperr);
if(n < 0) {
- failf(data, "error sending close notify: %d", tmperr);
+ failf(data, "rustls: error sending close_notify: %d", tmperr);
}
rustls_connection_free(backend->conn);
diff --git a/Utilities/cmcurl/lib/vtls/rustls.h b/Utilities/cmcurl/lib/vtls/rustls.h
index 6b393dd639..bfbe23de3e 100644
--- a/Utilities/cmcurl/lib/vtls/rustls.h
+++ b/Utilities/cmcurl/lib/vtls/rustls.h
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2020 - 2022, Jacob Hoffman-Andrews,
+ * Copyright (C) Jacob Hoffman-Andrews,
* <github@hoffman-andrews.com>
*
* This software is licensed as described in the file COPYING, which
diff --git a/Utilities/cmcurl/lib/vtls/schannel.c b/Utilities/cmcurl/lib/vtls/schannel.c
index 7eab9542af..452fa409a5 100644
--- a/Utilities/cmcurl/lib/vtls/schannel.c
+++ b/Utilities/cmcurl/lib/vtls/schannel.c
@@ -5,9 +5,9 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2012 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
- * Copyright (C) 2012 - 2016, Marc Hoersken, <info@marc-hoersken.de>
- * Copyright (C) 2012, Mark Salisbury, <mark.salisbury@hp.com>
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Marc Hoersken, <info@marc-hoersken.de>
+ * Copyright (C) Mark Salisbury, <mark.salisbury@hp.com>
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -1105,7 +1105,7 @@ schannel_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
#ifdef HAS_ALPN
/* ALPN is only supported on Windows 8.1 / Server 2012 R2 and above.
Also it doesn't seem to be supported for Wine, see curl bug #983. */
- backend->use_alpn = cf->conn->bits.tls_enable_alpn &&
+ backend->use_alpn = connssl->alpn &&
!GetProcAddress(GetModuleHandle(TEXT("ntdll")),
"wine_get_version") &&
curlx_verify_windows_version(6, 3, 0, PLATFORM_WINNT,
@@ -1196,6 +1196,7 @@ schannel_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
int list_start_index = 0;
unsigned int *extension_len = NULL;
unsigned short* list_len = NULL;
+ struct alpn_proto_buf proto;
/* The first four bytes will be an unsigned int indicating number
of bytes of data in the rest of the buffer. */
@@ -1215,25 +1216,22 @@ schannel_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
list_start_index = cur;
-#ifdef USE_HTTP2
- if(data->state.httpwant >= CURL_HTTP_VERSION_2) {
- alpn_buffer[cur++] = ALPN_H2_LENGTH;
- memcpy(&alpn_buffer[cur], ALPN_H2, ALPN_H2_LENGTH);
- cur += ALPN_H2_LENGTH;
- infof(data, VTLS_INFOF_ALPN_OFFER_1STR, ALPN_H2);
+ result = Curl_alpn_to_proto_buf(&proto, connssl->alpn);
+ if(result) {
+ failf(data, "Error setting ALPN");
+ return CURLE_SSL_CONNECT_ERROR;
}
-#endif
-
- alpn_buffer[cur++] = ALPN_HTTP_1_1_LENGTH;
- memcpy(&alpn_buffer[cur], ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH);
- cur += ALPN_HTTP_1_1_LENGTH;
- infof(data, VTLS_INFOF_ALPN_OFFER_1STR, ALPN_HTTP_1_1);
+ memcpy(&alpn_buffer[cur], proto.data, proto.len);
+ cur += proto.len;
*list_len = curlx_uitous(cur - list_start_index);
*extension_len = *list_len + sizeof(unsigned int) + sizeof(unsigned short);
InitSecBuffer(&inbuf, SECBUFFER_APPLICATION_PROTOCOLS, alpn_buffer, cur);
InitSecBufferDesc(&inbuf_desc, &inbuf, 1);
+
+ Curl_alpn_to_proto_str(&proto, connssl->alpn);
+ infof(data, VTLS_INFOF_ALPN_OFFER_1STR, proto.data);
}
else {
InitSecBuffer(&inbuf, SECBUFFER_EMPTY, NULL, 0);
@@ -1727,40 +1725,23 @@ schannel_connect_step3(struct Curl_cfilter *cf, struct Curl_easy *data)
if(alpn_result.ProtoNegoStatus ==
SecApplicationProtocolNegotiationStatus_Success) {
- unsigned char alpn = 0;
-
- infof(data, VTLS_INFOF_ALPN_ACCEPTED_LEN_1STR,
- alpn_result.ProtocolIdSize, alpn_result.ProtocolId);
+ unsigned char prev_alpn = cf->conn->alpn;
-#ifdef USE_HTTP2
- if(alpn_result.ProtocolIdSize == ALPN_H2_LENGTH &&
- !memcmp(ALPN_H2, alpn_result.ProtocolId, ALPN_H2_LENGTH)) {
- alpn = CURL_HTTP_VERSION_2;
- }
- else
-#endif
- if(alpn_result.ProtocolIdSize == ALPN_HTTP_1_1_LENGTH &&
- !memcmp(ALPN_HTTP_1_1, alpn_result.ProtocolId,
- ALPN_HTTP_1_1_LENGTH)) {
- alpn = CURL_HTTP_VERSION_1_1;
- }
+ Curl_alpn_set_negotiated(cf, data, alpn_result.ProtocolId,
+ alpn_result.ProtocolIdSize);
if(backend->recv_renegotiating) {
- if(alpn != cf->conn->alpn) {
+ if(prev_alpn != cf->conn->alpn &&
+ prev_alpn != CURL_HTTP_VERSION_NONE) {
+ /* Renegotiation selected a different protocol now, we cannot
+ * deal with this */
failf(data, "schannel: server selected an ALPN protocol too late");
return CURLE_SSL_CONNECT_ERROR;
}
}
- else
- cf->conn->alpn = alpn;
}
else {
if(!backend->recv_renegotiating)
- infof(data, VTLS_INFOF_NO_ALPN);
- }
-
- if(!backend->recv_renegotiating) {
- Curl_multiuse_state(data, cf->conn->alpn == CURL_HTTP_VERSION_2 ?
- BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
+ Curl_alpn_set_negotiated(cf, data, NULL, 0);
}
}
#endif
@@ -1841,7 +1822,7 @@ schannel_connect_common(struct Curl_cfilter *cf,
{
CURLcode result;
struct ssl_connect_data *connssl = cf->ctx;
- curl_socket_t sockfd = cf->conn->sock[cf->sockindex];
+ curl_socket_t sockfd = Curl_conn_cf_get_socket(cf, data);
timediff_t timeout_ms;
int what;
@@ -2056,7 +2037,7 @@ schannel_send(struct Curl_cfilter *cf, struct Curl_easy *data,
}
else if(!timeout_ms)
timeout_ms = TIMEDIFF_T_MAX;
- what = SOCKET_WRITABLE(cf->conn->sock[cf->sockindex], timeout_ms);
+ what = SOCKET_WRITABLE(Curl_conn_cf_get_socket(cf, data), timeout_ms);
if(what < 0) {
/* fatal error */
failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
diff --git a/Utilities/cmcurl/lib/vtls/schannel.h b/Utilities/cmcurl/lib/vtls/schannel.h
index 6d4235a96c..7fae39fa0a 100644
--- a/Utilities/cmcurl/lib/vtls/schannel.h
+++ b/Utilities/cmcurl/lib/vtls/schannel.h
@@ -7,8 +7,8 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2012, Marc Hoersken, <info@marc-hoersken.de>, et al.
- * Copyright (C) 2012 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Marc Hoersken, <info@marc-hoersken.de>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -179,8 +179,8 @@ struct ssl_backend_data {
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
+ can't be decrypted without another recv() (that is, status is
+ SEC_E_INCOMPLETE_MESSAGE) then set this true. after an recv() adds
more bytes into encdata then set this back to false. */
bool encdata_is_incomplete;
unsigned long req_flags, ret_flags;
diff --git a/Utilities/cmcurl/lib/vtls/schannel_verify.c b/Utilities/cmcurl/lib/vtls/schannel_verify.c
index e4992162e6..d75ee8dfe7 100644
--- a/Utilities/cmcurl/lib/vtls/schannel_verify.c
+++ b/Utilities/cmcurl/lib/vtls/schannel_verify.c
@@ -5,9 +5,9 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2012 - 2016, Marc Hoersken, <info@marc-hoersken.de>
- * Copyright (C) 2012, Mark Salisbury, <mark.salisbury@hp.com>
- * Copyright (C) 2012 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Marc Hoersken, <info@marc-hoersken.de>
+ * Copyright (C) Mark Salisbury, <mark.salisbury@hp.com>
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/Utilities/cmcurl/lib/vtls/sectransp.c b/Utilities/cmcurl/lib/vtls/sectransp.c
index d903c53d10..2e98169e26 100644
--- a/Utilities/cmcurl/lib/vtls/sectransp.c
+++ b/Utilities/cmcurl/lib/vtls/sectransp.c
@@ -5,8 +5,8 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2012 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
- * Copyright (C) 2012 - 2017, Nick Zitzmann, <nickzman@gmail.com>.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Nick Zitzmann, <nickzman@gmail.com>.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -137,14 +137,6 @@
#include "memdebug.h"
-#define DEBUG_CF 0
-
-#if DEBUG_CF
-#define CF_DEBUGF(x) x
-#else
-#define CF_DEBUGF(x) do { } while(0)
-#endif
-
/* From MacTypes.h (which we can't include because it isn't present in iOS: */
#define ioErr -36
#define paramErr -50
@@ -840,15 +832,15 @@ static OSStatus bio_cf_in_read(SSLConnectionRef connection,
struct Curl_cfilter *cf = (struct Curl_cfilter *)connection;
struct ssl_connect_data *connssl = cf->ctx;
struct ssl_backend_data *backend = connssl->backend;
- struct Curl_easy *data = connssl->call_data;
+ struct Curl_easy *data = CF_DATA_CURRENT(cf);
ssize_t nread;
CURLcode result;
OSStatus rtn = noErr;
DEBUGASSERT(data);
nread = Curl_conn_cf_recv(cf->next, data, buf, *dataLength, &result);
- CF_DEBUGF(infof(data, CFMSG(cf, "bio_read(len=%zu) -> %zd, result=%d"),
- *dataLength, nread, result));
+ DEBUGF(LOG_CF(data, cf, "bio_read(len=%zu) -> %zd, result=%d",
+ *dataLength, nread, result));
if(nread < 0) {
switch(result) {
case CURLE_OK:
@@ -876,15 +868,15 @@ static OSStatus bio_cf_out_write(SSLConnectionRef connection,
struct Curl_cfilter *cf = (struct Curl_cfilter *)connection;
struct ssl_connect_data *connssl = cf->ctx;
struct ssl_backend_data *backend = connssl->backend;
- struct Curl_easy *data = connssl->call_data;
+ struct Curl_easy *data = CF_DATA_CURRENT(cf);
ssize_t nwritten;
CURLcode result;
OSStatus rtn = noErr;
DEBUGASSERT(data);
nwritten = Curl_conn_cf_send(cf->next, data, buf, *dataLength, &result);
- CF_DEBUGF(infof(data, CFMSG(cf, "bio_send(len=%zu) -> %zd, result=%d"),
- *dataLength, nwritten, result));
+ DEBUGF(LOG_CF(data, cf, "bio_send(len=%zu) -> %zd, result=%d",
+ *dataLength, nwritten, result));
if(nwritten <= 0) {
if(result == CURLE_AGAIN) {
rtn = errSSLWouldBlock;
@@ -1644,7 +1636,6 @@ static CURLcode sectransp_connect_step1(struct Curl_cfilter *cf,
const bool verifypeer = conn_config->verifypeer;
char * const ssl_cert = ssl_config->primary.clientcert;
const struct curl_blob *ssl_cert_blob = ssl_config->primary.cert_blob;
- bool isproxy = Curl_ssl_cf_is_proxy(cf);
#ifdef ENABLE_IPV6
struct in6_addr addr;
#else
@@ -1657,7 +1648,7 @@ static CURLcode sectransp_connect_step1(struct Curl_cfilter *cf,
DEBUGASSERT(backend);
- CF_DEBUGF(infof(data, CFMSG(cf, "connect_step1")));
+ DEBUGF(LOG_CF(data, cf, "connect_step1"));
GetDarwinVersionNumber(&darwinver_maj, &darwinver_min);
#endif /* CURL_BUILD_MAC */
@@ -1805,33 +1796,28 @@ static CURLcode sectransp_connect_step1(struct Curl_cfilter *cf,
#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
#if (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1
- if(cf->conn->bits.tls_enable_alpn) {
+ if(connssl->alpn) {
if(__builtin_available(macOS 10.13.4, iOS 11, tvOS 11, *)) {
+ struct alpn_proto_buf proto;
+ size_t i;
+ CFStringRef cstr;
CFMutableArrayRef alpnArr = CFArrayCreateMutable(NULL, 0,
&kCFTypeArrayCallBacks);
-
-#ifdef USE_HTTP2
- if(data->state.httpwant >= CURL_HTTP_VERSION_2
-#ifndef CURL_DISABLE_PROXY
- && (!isproxy || !cf->conn->bits.tunnel_proxy)
-#endif
- ) {
- CFArrayAppendValue(alpnArr, CFSTR(ALPN_H2));
- infof(data, VTLS_INFOF_ALPN_OFFER_1STR, ALPN_H2);
+ for(i = 0; i < connssl->alpn->count; ++i) {
+ cstr = CFStringCreateWithCString(NULL, connssl->alpn->entries[i],
+ kCFStringEncodingUTF8);
+ if(!cstr)
+ return CURLE_OUT_OF_MEMORY;
+ CFArrayAppendValue(alpnArr, cstr);
+ CFRelease(cstr);
}
-#endif
-
- CFArrayAppendValue(alpnArr, CFSTR(ALPN_HTTP_1_1));
- infof(data, VTLS_INFOF_ALPN_OFFER_1STR, ALPN_HTTP_1_1);
-
- /* expects length prefixed preference ordered list of protocols in wire
- * format
- */
err = SSLSetALPNProtocols(backend->ssl_ctx, alpnArr);
if(err != noErr)
infof(data, "WARNING: failed to set ALPN protocols; OSStatus %d",
err);
CFRelease(alpnArr);
+ Curl_alpn_to_proto_str(&proto, connssl->alpn);
+ infof(data, VTLS_INFOF_ALPN_OFFER_1STR, proto.data);
}
}
#endif
@@ -2302,7 +2288,7 @@ static CURLcode verify_cert_buf(struct Curl_cfilter *cf,
/* This is not a PEM file, probably a certificate in DER format. */
rc = append_cert_to_array(data, certbuf, buflen, array);
if(rc != CURLE_OK) {
- CF_DEBUGF(infof(data, CFMSG(cf, "append_cert for CA failed")));
+ DEBUGF(LOG_CF(data, cf, "append_cert for CA failed"));
result = rc;
goto out;
}
@@ -2316,7 +2302,7 @@ static CURLcode verify_cert_buf(struct Curl_cfilter *cf,
rc = append_cert_to_array(data, der, derlen, array);
free(der);
if(rc != CURLE_OK) {
- CF_DEBUGF(infof(data, CFMSG(cf, "append_cert for CA failed")));
+ DEBUGF(LOG_CF(data, cf, "append_cert for CA failed"));
result = rc;
goto out;
}
@@ -2332,7 +2318,7 @@ static CURLcode verify_cert_buf(struct Curl_cfilter *cf,
goto out;
}
- CF_DEBUGF(infof(data, CFMSG(cf, "setting %d trust anchors"), n));
+ DEBUGF(LOG_CF(data, cf, "setting %d trust anchors", n));
ret = SecTrustSetAnchorCertificates(trust, array);
if(ret != noErr) {
failf(data, "SecTrustSetAnchorCertificates() returned error %d", ret);
@@ -2354,11 +2340,11 @@ static CURLcode verify_cert_buf(struct Curl_cfilter *cf,
switch(trust_eval) {
case kSecTrustResultUnspecified:
/* what does this really mean? */
- CF_DEBUGF(infof(data, CFMSG(cf, "trust result: Unspecified")));
+ DEBUGF(LOG_CF(data, cf, "trust result: Unspecified"));
result = CURLE_OK;
goto out;
case kSecTrustResultProceed:
- CF_DEBUGF(infof(data, CFMSG(cf, "trust result: Proceed")));
+ DEBUGF(LOG_CF(data, cf, "trust result: Proceed"));
result = CURLE_OK;
goto out;
@@ -2391,7 +2377,7 @@ static CURLcode verify_cert(struct Curl_cfilter *cf,
size_t buflen;
if(ca_info_blob) {
- CF_DEBUGF(infof(data, CFMSG(cf, "verify_peer, CA from config blob")));
+ DEBUGF(LOG_CF(data, cf, "verify_peer, CA from config blob"));
certbuf = (unsigned char *)malloc(ca_info_blob->len + 1);
if(!certbuf) {
return CURLE_OUT_OF_MEMORY;
@@ -2401,8 +2387,7 @@ static CURLcode verify_cert(struct Curl_cfilter *cf,
certbuf[ca_info_blob->len]='\0';
}
else if(cafile) {
- CF_DEBUGF(infof(data, CFMSG(cf, "verify_peer, CA from file '%s'"),
- cafile));
+ DEBUGF(LOG_CF(data, cf, "verify_peer, CA from file '%s'", cafile));
if(read_cert(cafile, &certbuf, &buflen) < 0) {
failf(data, "SSL: failed to read or invalid CA certificate");
return CURLE_SSL_CACERT_BADFILE;
@@ -2538,7 +2523,7 @@ static CURLcode sectransp_connect_step2(struct Curl_cfilter *cf,
|| ssl_connect_2_reading == connssl->connecting_state
|| ssl_connect_2_writing == connssl->connecting_state);
DEBUGASSERT(backend);
- CF_DEBUGF(infof(data, CFMSG(cf, "connect_step2")));
+ DEBUGF(LOG_CF(data, cf, "connect_step2"));
/* Here goes nothing: */
check_handshake:
@@ -3003,7 +2988,7 @@ static CURLcode sectransp_connect_step3(struct Curl_cfilter *cf,
{
struct ssl_connect_data *connssl = cf->ctx;
- CF_DEBUGF(infof(data, CFMSG(cf, "connect_step3")));
+ DEBUGF(LOG_CF(data, cf, "connect_step3"));
/* There is no step 3!
* Well, okay, let's collect server certificates, and if verbose mode is on,
* let's print the details of the server certificates. */
@@ -3022,7 +3007,7 @@ sectransp_connect_common(struct Curl_cfilter *cf, struct Curl_easy *data,
{
CURLcode result;
struct ssl_connect_data *connssl = cf->ctx;
- curl_socket_t sockfd = cf->conn->sock[cf->sockindex];
+ curl_socket_t sockfd = Curl_conn_cf_get_socket(cf, data);
int what;
/* check if the connection has already been established */
@@ -3112,7 +3097,7 @@ sectransp_connect_common(struct Curl_cfilter *cf, struct Curl_easy *data,
}
if(ssl_connect_done == connssl->connecting_state) {
- CF_DEBUGF(infof(data, CFMSG(cf, "connected")));
+ DEBUGF(LOG_CF(data, cf, "connected"));
connssl->state = ssl_connection_complete;
*done = TRUE;
}
@@ -3158,7 +3143,7 @@ static void sectransp_close(struct Curl_cfilter *cf, struct Curl_easy *data)
DEBUGASSERT(backend);
if(backend->ssl_ctx) {
- CF_DEBUGF(infof(data, CFMSG(cf, "close")));
+ DEBUGF(LOG_CF(data, cf, "close"));
(void)SSLClose(backend->ssl_ctx);
#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
if(SSLCreateContext)
@@ -3200,9 +3185,10 @@ static int sectransp_shutdown(struct Curl_cfilter *cf,
rc = 0;
- what = SOCKET_READABLE(cf->conn->sock[cf->sockindex], SSL_SHUTDOWN_TIMEOUT);
+ what = SOCKET_READABLE(Curl_conn_cf_get_socket(cf, data),
+ SSL_SHUTDOWN_TIMEOUT);
- CF_DEBUGF(infof(data, CFMSG(cf, "shutdown")));
+ DEBUGF(LOG_CF(data, cf, "shutdown"));
while(loop--) {
if(what < 0) {
/* anything that gets here is fatally bad */
@@ -3229,7 +3215,7 @@ static int sectransp_shutdown(struct Curl_cfilter *cf,
if(nread <= 0)
break;
- what = SOCKET_READABLE(cf->conn->sock[cf->sockindex], 0);
+ what = SOCKET_READABLE(Curl_conn_cf_get_socket(cf, data), 0);
}
return rc;
@@ -3271,7 +3257,7 @@ static int sectransp_check_cxn(struct Curl_cfilter *cf,
DEBUGASSERT(backend);
if(backend->ssl_ctx) {
- CF_DEBUGF(infof(data, CFMSG(cf, "check connection")));
+ DEBUGF(LOG_CF(data, cf, "check connection"));
err = SSLGetSessionState(backend->ssl_ctx, &state);
if(err == noErr)
return state == kSSLConnected || state == kSSLHandshake;
@@ -3292,7 +3278,7 @@ static bool sectransp_data_pending(struct Curl_cfilter *cf,
DEBUGASSERT(backend);
if(backend->ssl_ctx) { /* SSL is in use */
- CF_DEBUGF(infof(data, CFMSG(cf, "data_pending")));
+ DEBUGF(LOG_CF((struct Curl_easy *)data, cf, "data_pending"));
err = SSLGetBufferedReadSize(backend->ssl_ctx, &buffer);
if(err == noErr)
return buffer > 0UL;
diff --git a/Utilities/cmcurl/lib/vtls/sectransp.h b/Utilities/cmcurl/lib/vtls/sectransp.h
index 2d53b7c480..0f1085ad91 100644
--- a/Utilities/cmcurl/lib/vtls/sectransp.h
+++ b/Utilities/cmcurl/lib/vtls/sectransp.h
@@ -7,8 +7,8 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2012 - 2014, Nick Zitzmann, <nickzman@gmail.com>.
- * Copyright (C) 2012 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Nick Zitzmann, <nickzman@gmail.com>.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/Utilities/cmcurl/lib/vtls/vtls.c b/Utilities/cmcurl/lib/vtls/vtls.c
index 873ee6bac7..15f6844c7b 100644
--- a/Utilities/cmcurl/lib/vtls/vtls.c
+++ b/Utilities/cmcurl/lib/vtls/vtls.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -73,6 +73,7 @@
#include "curl_memory.h"
#include "memdebug.h"
+
/* convenience macro to check if this handle is using a shared SSL session */
#define SSLSESSION_SHARED(data) (data->share && \
(data->share->specifier & \
@@ -150,7 +151,6 @@ Curl_ssl_config_matches(struct ssl_primary_config *data,
#ifdef USE_TLS_SRP
!Curl_timestrcmp(data->username, needle->username) &&
!Curl_timestrcmp(data->password, needle->password) &&
- (data->authtype == needle->authtype) &&
#endif
strcasecompare(data->cipher_list, needle->cipher_list) &&
strcasecompare(data->cipher_list13, needle->cipher_list13) &&
@@ -173,9 +173,6 @@ Curl_clone_primary_ssl_config(struct ssl_primary_config *source,
dest->verifystatus = source->verifystatus;
dest->sessionid = source->sessionid;
dest->ssl_options = source->ssl_options;
-#ifdef USE_TLS_SRP
- dest->authtype = source->authtype;
-#endif
CLONE_BLOB(cert_blob);
CLONE_BLOB(ca_info_blob);
@@ -272,8 +269,8 @@ void Curl_ssl_cleanup(void)
static bool ssl_prefs_check(struct Curl_easy *data)
{
/* check for CURLOPT_SSLVERSION invalid parameter value */
- const long sslver = data->set.ssl.primary.version;
- if((sslver < 0) || (sslver >= CURL_SSLVERSION_LAST)) {
+ const unsigned char sslver = data->set.ssl.primary.version;
+ if(sslver >= CURL_SSLVERSION_LAST) {
failf(data, "Unrecognized parameter value passed via CURLOPT_SSLVERSION");
return FALSE;
}
@@ -293,7 +290,8 @@ static bool ssl_prefs_check(struct Curl_easy *data)
return TRUE;
}
-static struct ssl_connect_data *cf_ctx_new(struct Curl_easy *data)
+static struct ssl_connect_data *cf_ctx_new(struct Curl_easy *data,
+ const struct alpn_spec *alpn)
{
struct ssl_connect_data *ctx;
@@ -302,6 +300,7 @@ static struct ssl_connect_data *cf_ctx_new(struct Curl_easy *data)
if(!ctx)
return NULL;
+ ctx->alpn = alpn;
ctx->backend = calloc(1, Curl_ssl->sizeof_ssl_backend_data);
if(!ctx->backend) {
free(ctx);
@@ -318,13 +317,6 @@ static void cf_ctx_free(struct ssl_connect_data *ctx)
}
}
-static void cf_ctx_set_data(struct Curl_cfilter *cf,
- struct Curl_easy *data)
-{
- if(cf->ctx)
- ((struct ssl_connect_data *)cf->ctx)->call_data = data;
-}
-
static CURLcode ssl_connect(struct Curl_cfilter *cf, struct Curl_easy *data)
{
struct ssl_connect_data *connssl = cf->ctx;
@@ -339,7 +331,6 @@ static CURLcode ssl_connect(struct Curl_cfilter *cf, struct Curl_easy *data)
result = Curl_ssl->connect_blocking(cf, data);
if(!result) {
- Curl_pgrsTime(data, TIMER_APPCONNECT); /* SSL is connected */
DEBUGASSERT(connssl->state == ssl_connection_complete);
}
@@ -615,19 +606,20 @@ int Curl_ssl_get_select_socks(struct Curl_cfilter *cf, struct Curl_easy *data,
curl_socket_t *socks)
{
struct ssl_connect_data *connssl = cf->ctx;
+ curl_socket_t sock = Curl_conn_cf_get_socket(cf->next, data);
- (void)data;
- if(connssl->connecting_state == ssl_connect_2_writing) {
- /* write mode */
- socks[0] = cf->conn->sock[FIRSTSOCKET];
- return GETSOCK_WRITESOCK(0);
- }
- if(connssl->connecting_state == ssl_connect_2_reading) {
- /* read mode */
- socks[0] = cf->conn->sock[FIRSTSOCKET];
- return GETSOCK_READSOCK(0);
+ if(sock != CURL_SOCKET_BAD) {
+ if(connssl->connecting_state == ssl_connect_2_writing) {
+ /* write mode */
+ socks[0] = sock;
+ return GETSOCK_WRITESOCK(0);
+ }
+ if(connssl->connecting_state == ssl_connect_2_reading) {
+ /* read mode */
+ socks[0] = sock;
+ return GETSOCK_READSOCK(0);
+ }
}
-
return GETSOCK_BLANK;
}
@@ -685,20 +677,6 @@ void Curl_ssl_version(char *buffer, size_t size)
#endif
}
-/*
- * This function tries to determine connection status.
- *
- * Return codes:
- * 1 means the connection is still in place
- * 0 means the connection has been closed
- * -1 means the connection status is unknown
- */
-int Curl_ssl_check_cxn(struct Curl_easy *data, struct connectdata *conn)
-{
- 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)
{
struct curl_certinfo *ci = &data->info.certs;
@@ -1430,53 +1408,80 @@ CURLsslset Curl_init_sslset_nolock(curl_sslbackend id, const char *name,
#ifdef USE_SSL
+static void free_hostname(struct ssl_connect_data *connssl)
+{
+ if(connssl->dispname != connssl->hostname)
+ free(connssl->dispname);
+ free(connssl->hostname);
+ connssl->hostname = connssl->dispname = NULL;
+}
+
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;
+ free_hostname(connssl);
}
cf->connected = FALSE;
}
-static void reinit_hostname(struct Curl_cfilter *cf)
+static CURLcode reinit_hostname(struct Curl_cfilter *cf)
{
struct ssl_connect_data *connssl = cf->ctx;
+ const char *ehostname, *edispname;
+ int eport;
+ /* We need the hostname for SNI negotiation. Once handshaked, this
+ * remains the SNI hostname for the TLS connection. But when the
+ * connection is reused, the settings in cf->conn might change.
+ * So we keep a copy of the hostname we use for SNI.
+ */
#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;
+ ehostname = cf->conn->http_proxy.host.name;
+ edispname = cf->conn->http_proxy.host.dispname;
+ eport = 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;
+ ehostname = cf->conn->host.name;
+ edispname = cf->conn->host.dispname;
+ eport = cf->conn->remote_port;
+ }
+
+ /* change if ehostname changed */
+ if(ehostname && (!connssl->hostname
+ || strcmp(ehostname, connssl->hostname))) {
+ free_hostname(connssl);
+ connssl->hostname = strdup(ehostname);
+ if(!connssl->hostname) {
+ free_hostname(connssl);
+ return CURLE_OUT_OF_MEMORY;
}
+ if(!edispname || !strcmp(ehostname, edispname))
+ connssl->dispname = connssl->hostname;
else {
- connssl->hostname = cf->conn->host.name;
- connssl->dispname = cf->conn->host.dispname;
- connssl->port = cf->conn->remote_port;
+ connssl->dispname = strdup(edispname);
+ if(!connssl->dispname) {
+ free_hostname(connssl);
+ return CURLE_OUT_OF_MEMORY;
+ }
}
}
- DEBUGASSERT(connssl->hostname);
+ connssl->port = eport;
+ return CURLE_OK;
}
static void ssl_cf_destroy(struct Curl_cfilter *cf, struct Curl_easy *data)
{
- cf_ctx_set_data(cf, data);
+ struct cf_call_data save;
+
+ CF_DATA_SAVE(save, cf, data);
cf_close(cf, data);
+ CF_DATA_RESTORE(cf, save);
cf_ctx_free(cf->ctx);
cf->ctx = NULL;
}
@@ -1484,10 +1489,12 @@ static void ssl_cf_destroy(struct Curl_cfilter *cf, struct Curl_easy *data)
static void ssl_cf_close(struct Curl_cfilter *cf,
struct Curl_easy *data)
{
- cf_ctx_set_data(cf, data);
+ struct cf_call_data save;
+
+ CF_DATA_SAVE(save, cf, data);
cf_close(cf, data);
cf->next->cft->close(cf->next, data);
- cf_ctx_set_data(cf, NULL);
+ CF_DATA_RESTORE(cf, save);
}
static CURLcode ssl_cf_connect(struct Curl_cfilter *cf,
@@ -1495,6 +1502,7 @@ static CURLcode ssl_cf_connect(struct Curl_cfilter *cf,
bool blocking, bool *done)
{
struct ssl_connect_data *connssl = cf->ctx;
+ struct cf_call_data save;
CURLcode result;
if(cf->connected) {
@@ -1502,7 +1510,7 @@ static CURLcode ssl_cf_connect(struct Curl_cfilter *cf,
return CURLE_OK;
}
- cf_ctx_set_data(cf, data);
+ CF_DATA_SAVE(save, cf, data);
(void)connssl;
DEBUGASSERT(data->conn);
DEBUGASSERT(data->conn == cf->conn);
@@ -1513,10 +1521,10 @@ static CURLcode ssl_cf_connect(struct Curl_cfilter *cf,
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;
+ result = reinit_hostname(cf);
+ if(result)
+ goto out;
if(blocking) {
result = ssl_connect(cf, data);
@@ -1528,26 +1536,26 @@ static CURLcode ssl_cf_connect(struct Curl_cfilter *cf,
if(!result && *done) {
cf->connected = TRUE;
- if(cf->sockindex == FIRSTSOCKET && !Curl_ssl_cf_is_proxy(cf))
- Curl_pgrsTime(data, TIMER_APPCONNECT); /* SSL is connected */
+ connssl->handshake_done = Curl_now();
DEBUGASSERT(connssl->state == ssl_connection_complete);
}
out:
- cf_ctx_set_data(cf, NULL);
+ CF_DATA_RESTORE(cf, save);
return result;
}
static bool ssl_cf_data_pending(struct Curl_cfilter *cf,
const struct Curl_easy *data)
{
+ struct cf_call_data save;
bool result;
- cf_ctx_set_data(cf, (struct Curl_easy *)data);
- if(cf->ctx && Curl_ssl->data_pending(cf, data))
+ CF_DATA_SAVE(save, cf, data);
+ if(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);
+ CF_DATA_RESTORE(cf, save);
return result;
}
@@ -1555,12 +1563,13 @@ static ssize_t ssl_cf_send(struct Curl_cfilter *cf,
struct Curl_easy *data, const void *buf, size_t len,
CURLcode *err)
{
+ struct cf_call_data save;
ssize_t nwritten;
+ CF_DATA_SAVE(save, cf, data);
*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);
+ CF_DATA_RESTORE(cf, save);
return nwritten;
}
@@ -1568,12 +1577,13 @@ static ssize_t ssl_cf_recv(struct Curl_cfilter *cf,
struct Curl_easy *data, char *buf, size_t len,
CURLcode *err)
{
+ struct cf_call_data save;
ssize_t nread;
+ CF_DATA_SAVE(save, cf, data);
*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);
+ CF_DATA_RESTORE(cf, save);
return nread;
}
@@ -1581,39 +1591,72 @@ static int ssl_cf_get_select_socks(struct Curl_cfilter *cf,
struct Curl_easy *data,
curl_socket_t *socks)
{
+ struct cf_call_data save;
int result;
- cf_ctx_set_data(cf, data);
+ CF_DATA_SAVE(save, cf, data);
result = Curl_ssl->get_select_socks(cf, data, socks);
- cf_ctx_set_data(cf, NULL);
+ CF_DATA_RESTORE(cf, save);
return result;
}
-static void ssl_cf_attach_data(struct Curl_cfilter *cf,
- struct Curl_easy *data)
+static CURLcode ssl_cf_cntrl(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ int event, int arg1, void *arg2)
{
- if(Curl_ssl->attach_data) {
- cf_ctx_set_data(cf, data);
- Curl_ssl->attach_data(cf, data);
- cf_ctx_set_data(cf, NULL);
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct cf_call_data save;
+
+ (void)arg1;
+ (void)arg2;
+ switch(event) {
+ case CF_CTRL_CONN_REPORT_STATS:
+ if(cf->sockindex == FIRSTSOCKET && !Curl_ssl_cf_is_proxy(cf))
+ Curl_pgrsTimeWas(data, TIMER_APPCONNECT, connssl->handshake_done);
+ break;
+ case CF_CTRL_DATA_ATTACH:
+ if(Curl_ssl->attach_data) {
+ CF_DATA_SAVE(save, cf, data);
+ Curl_ssl->attach_data(cf, data);
+ CF_DATA_RESTORE(cf, save);
+ }
+ break;
+ case CF_CTRL_DATA_DETACH:
+ if(Curl_ssl->detach_data) {
+ CF_DATA_SAVE(save, cf, data);
+ Curl_ssl->detach_data(cf, data);
+ CF_DATA_RESTORE(cf, save);
+ }
+ break;
+ default:
+ break;
}
+ return CURLE_OK;
}
-static void ssl_cf_detach_data(struct Curl_cfilter *cf,
- struct Curl_easy *data)
+static bool cf_ssl_is_alive(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);
- }
+ struct cf_call_data save;
+ bool result;
+ /*
+ * This function tries to determine connection status.
+ *
+ * Return codes:
+ * 1 means the connection is still in place
+ * 0 means the connection has been closed
+ * -1 means the connection status is unknown
+ */
+ CF_DATA_SAVE(save, cf, data);
+ result = Curl_ssl->check_cxn(cf, data) != 0;
+ CF_DATA_RESTORE(cf, save);
+ return result;
}
-static const struct Curl_cftype cft_ssl = {
+struct Curl_cftype Curl_cft_ssl = {
"SSL",
CF_TYPE_SSL,
+ CURL_LOG_DEFAULT,
ssl_cf_destroy,
- Curl_cf_def_setup,
ssl_cf_connect,
ssl_cf_close,
Curl_cf_def_get_host,
@@ -1621,15 +1664,17 @@ static const struct Curl_cftype cft_ssl = {
ssl_cf_data_pending,
ssl_cf_send,
ssl_cf_recv,
- ssl_cf_attach_data,
- ssl_cf_detach_data,
+ ssl_cf_cntrl,
+ cf_ssl_is_alive,
+ Curl_cf_def_conn_keep_alive,
+ Curl_cf_def_query,
};
-static const struct Curl_cftype cft_ssl_proxy = {
+struct Curl_cftype Curl_cft_ssl_proxy = {
"SSL-PROXY",
CF_TYPE_SSL,
+ CURL_LOG_DEFAULT,
ssl_cf_destroy,
- Curl_cf_def_setup,
ssl_cf_connect,
ssl_cf_close,
Curl_cf_def_get_host,
@@ -1637,65 +1682,107 @@ static const struct Curl_cftype cft_ssl_proxy = {
ssl_cf_data_pending,
ssl_cf_send,
ssl_cf_recv,
- ssl_cf_attach_data,
- ssl_cf_detach_data,
+ ssl_cf_cntrl,
+ cf_ssl_is_alive,
+ Curl_cf_def_conn_keep_alive,
+ Curl_cf_def_query,
};
-CURLcode Curl_ssl_cfilter_add(struct Curl_easy *data,
- struct connectdata *conn,
- int sockindex)
+static CURLcode cf_ssl_create(struct Curl_cfilter **pcf,
+ struct Curl_easy *data,
+ struct connectdata *conn)
{
- struct Curl_cfilter *cf;
+ struct Curl_cfilter *cf = NULL;
struct ssl_connect_data *ctx;
CURLcode result;
DEBUGASSERT(data->conn);
- ctx = cf_ctx_new(data);
+
+ ctx = cf_ctx_new(data, Curl_alpn_get_spec(data, conn));
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;
+ result = Curl_cf_create(&cf, &Curl_cft_ssl, ctx);
out:
if(result)
cf_ctx_free(ctx);
+ *pcf = result? NULL : cf;
return result;
}
-#ifndef CURL_DISABLE_PROXY
-CURLcode Curl_ssl_cfilter_proxy_add(struct Curl_easy *data,
- struct connectdata *conn,
- int sockindex)
+CURLcode Curl_ssl_cfilter_add(struct Curl_easy *data,
+ struct connectdata *conn,
+ int sockindex)
{
struct Curl_cfilter *cf;
+ CURLcode result;
+
+ result = cf_ssl_create(&cf, data, conn);
+ if(!result)
+ Curl_conn_cf_add(data, conn, sockindex, cf);
+ return result;
+}
+
+CURLcode Curl_cf_ssl_insert_after(struct Curl_cfilter *cf_at,
+ struct Curl_easy *data)
+{
+ struct Curl_cfilter *cf;
+ CURLcode result;
+
+ result = cf_ssl_create(&cf, data, cf_at->conn);
+ if(!result)
+ Curl_conn_cf_insert_after(cf_at, cf);
+ return result;
+}
+
+#ifndef CURL_DISABLE_PROXY
+static CURLcode cf_ssl_proxy_create(struct Curl_cfilter **pcf,
+ struct Curl_easy *data,
+ struct connectdata *conn)
+{
+ struct Curl_cfilter *cf = NULL;
struct ssl_connect_data *ctx;
CURLcode result;
- ctx = cf_ctx_new(data);
+ ctx = cf_ctx_new(data, Curl_alpn_get_proxy_spec(data, conn));
if(!ctx) {
result = CURLE_OUT_OF_MEMORY;
goto out;
}
+ result = Curl_cf_create(&cf, &Curl_cft_ssl_proxy, ctx);
- result = Curl_cf_create(&cf, &cft_ssl_proxy, ctx);
+out:
if(result)
- goto out;
+ cf_ctx_free(ctx);
+ *pcf = result? NULL : cf;
+ return result;
+}
- Curl_conn_cf_add(data, conn, sockindex, cf);
+CURLcode Curl_ssl_cfilter_proxy_add(struct Curl_easy *data,
+ struct connectdata *conn,
+ int sockindex)
+{
+ struct Curl_cfilter *cf;
+ CURLcode result;
- result = CURLE_OK;
+ result = cf_ssl_proxy_create(&cf, data, conn);
+ if(!result)
+ Curl_conn_cf_add(data, conn, sockindex, cf);
+ return result;
+}
-out:
- if(result)
- cf_ctx_free(ctx);
+CURLcode Curl_cf_ssl_proxy_insert_after(struct Curl_cfilter *cf_at,
+ struct Curl_easy *data)
+{
+ struct Curl_cfilter *cf;
+ CURLcode result;
+
+ result = cf_ssl_proxy_create(&cf, data, cf_at->conn);
+ if(!result)
+ Curl_conn_cf_insert_after(cf_at, cf);
return result;
}
@@ -1717,9 +1804,10 @@ void *Curl_ssl_get_internals(struct Curl_easy *data, int sockindex,
/* 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);
+ struct cf_call_data save;
+ CF_DATA_SAVE(save, cf, data);
result = Curl_ssl->get_internals(cf->ctx, info);
- cf_ctx_set_data(cf, NULL);
+ CF_DATA_RESTORE(cf, save);
}
}
return result;
@@ -1733,7 +1821,7 @@ CURLcode Curl_ssl_cfilter_remove(struct Curl_easy *data,
(void)data;
for(; cf; cf = cf->next) {
- if(cf->cft == &cft_ssl) {
+ if(cf->cft == &Curl_cft_ssl) {
if(Curl_ssl->shut_down(cf, data))
result = CURLE_SSL_SHUTDOWN_FAILED;
Curl_conn_cf_discard(cf, data);
@@ -1749,7 +1837,7 @@ static struct Curl_cfilter *get_ssl_cf_engaged(struct connectdata *conn,
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) {
+ if(cf->cft == &Curl_cft_ssl || cf->cft == &Curl_cft_ssl_proxy) {
lowest_ssl_cf = cf;
if(cf->connected || (cf->next && cf->next->connected)) {
/* connected or about to start */
@@ -1762,7 +1850,7 @@ static struct Curl_cfilter *get_ssl_cf_engaged(struct connectdata *conn,
bool Curl_ssl_cf_is_proxy(struct Curl_cfilter *cf)
{
- return (cf->cft == &cft_ssl_proxy);
+ return (cf->cft == &Curl_cft_ssl_proxy);
}
struct ssl_config_data *
@@ -1814,10 +1902,142 @@ Curl_ssl_get_primary_config(struct Curl_easy *data,
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)
+ if(cf->cft == &Curl_cft_ssl || cf->cft == &Curl_cft_ssl_proxy)
return cf;
}
return NULL;
}
+static const struct alpn_spec ALPN_SPEC_H10 = {
+ { ALPN_HTTP_1_0 }, 1
+};
+static const struct alpn_spec ALPN_SPEC_H11 = {
+ { ALPN_HTTP_1_1 }, 1
+};
+#ifdef USE_HTTP2
+static const struct alpn_spec ALPN_SPEC_H2_H11 = {
+ { ALPN_H2, ALPN_HTTP_1_1 }, 2
+};
+#endif
+
+const struct alpn_spec *
+Curl_alpn_get_spec(struct Curl_easy *data, struct connectdata *conn)
+{
+ if(!conn->bits.tls_enable_alpn)
+ return NULL;
+ if(data->state.httpwant == CURL_HTTP_VERSION_1_0)
+ return &ALPN_SPEC_H10;
+#ifdef USE_HTTP2
+ if(data->state.httpwant >= CURL_HTTP_VERSION_2)
+ return &ALPN_SPEC_H2_H11;
+#endif
+ return &ALPN_SPEC_H11;
+}
+
+const struct alpn_spec *
+Curl_alpn_get_proxy_spec(struct Curl_easy *data, struct connectdata *conn)
+{
+ if(!conn->bits.tls_enable_alpn)
+ return NULL;
+ if(data->state.httpwant == CURL_HTTP_VERSION_1_0)
+ return &ALPN_SPEC_H10;
+ return &ALPN_SPEC_H11;
+}
+
+CURLcode Curl_alpn_to_proto_buf(struct alpn_proto_buf *buf,
+ const struct alpn_spec *spec)
+{
+ size_t i, len;
+ int off = 0;
+ unsigned char blen;
+
+ memset(buf, 0, sizeof(*buf));
+ for(i = 0; spec && i < spec->count; ++i) {
+ len = strlen(spec->entries[i]);
+ if(len >= ALPN_NAME_MAX)
+ return CURLE_FAILED_INIT;
+ blen = (unsigned char)len;
+ if(off + blen + 1 >= (int)sizeof(buf->data))
+ return CURLE_FAILED_INIT;
+ buf->data[off++] = blen;
+ memcpy(buf->data + off, spec->entries[i], blen);
+ off += blen;
+ }
+ buf->len = off;
+ return CURLE_OK;
+}
+
+CURLcode Curl_alpn_to_proto_str(struct alpn_proto_buf *buf,
+ const struct alpn_spec *spec)
+{
+ size_t i, len;
+ size_t off = 0;
+
+ memset(buf, 0, sizeof(*buf));
+ for(i = 0; spec && i < spec->count; ++i) {
+ len = strlen(spec->entries[i]);
+ if(len >= ALPN_NAME_MAX)
+ return CURLE_FAILED_INIT;
+ if(off + len + 2 >= (int)sizeof(buf->data))
+ return CURLE_FAILED_INIT;
+ if(off)
+ buf->data[off++] = ',';
+ memcpy(buf->data + off, spec->entries[i], len);
+ off += len;
+ }
+ buf->data[off] = '\0';
+ buf->len = (int)off;
+ return CURLE_OK;
+}
+
+CURLcode Curl_alpn_set_negotiated(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ const unsigned char *proto,
+ size_t proto_len)
+{
+ int can_multi = 0;
+
+ if(proto && proto_len) {
+ if(proto_len == ALPN_HTTP_1_1_LENGTH &&
+ !memcmp(ALPN_HTTP_1_1, proto, ALPN_HTTP_1_1_LENGTH)) {
+ cf->conn->alpn = CURL_HTTP_VERSION_1_1;
+ }
+ else if(proto_len == ALPN_HTTP_1_0_LENGTH &&
+ !memcmp(ALPN_HTTP_1_0, proto, ALPN_HTTP_1_0_LENGTH)) {
+ cf->conn->alpn = CURL_HTTP_VERSION_1_0;
+ }
+#ifdef USE_HTTP2
+ else if(proto_len == ALPN_H2_LENGTH &&
+ !memcmp(ALPN_H2, proto, ALPN_H2_LENGTH)) {
+ cf->conn->alpn = CURL_HTTP_VERSION_2;
+ can_multi = 1;
+ }
+#endif
+#ifdef USE_HTTP3
+ else if(proto_len == ALPN_H3_LENGTH &&
+ !memcmp(ALPN_H3, proto, ALPN_H3_LENGTH)) {
+ cf->conn->alpn = CURL_HTTP_VERSION_3;
+ can_multi = 1;
+ }
+#endif
+ else {
+ cf->conn->alpn = CURL_HTTP_VERSION_NONE;
+ failf(data, "unsupported ALPN protocol: '%.*s'", (int)proto_len, proto);
+ /* TODO: do we want to fail this? Previous code just ignored it and
+ * some vtls backends even ignore the return code of this function. */
+ /* return CURLE_NOT_BUILT_IN; */
+ goto out;
+ }
+ infof(data, VTLS_INFOF_ALPN_ACCEPTED_LEN_1STR, (int)proto_len, proto);
+ }
+ else {
+ cf->conn->alpn = CURL_HTTP_VERSION_NONE;
+ infof(data, VTLS_INFOF_NO_ALPN);
+ }
+
+out:
+ Curl_multiuse_state(data, can_multi? BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
+ return CURLE_OK;
+}
+
#endif /* USE_SSL */
diff --git a/Utilities/cmcurl/lib/vtls/vtls.h b/Utilities/cmcurl/lib/vtls/vtls.h
index 5ad64fcf60..0d9e74a699 100644
--- a/Utilities/cmcurl/lib/vtls/vtls.h
+++ b/Utilities/cmcurl/lib/vtls/vtls.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -27,7 +27,6 @@
struct connectdata;
struct ssl_config_data;
-struct ssl_connect_data;
struct ssl_primary_config;
struct Curl_ssl_session;
@@ -53,6 +52,7 @@ struct Curl_ssl_session;
/* Curl_multi SSL backend-specific data; declared differently by each SSL
backend */
struct multi_ssl_backend_data;
+struct Curl_cfilter;
CURLsslset Curl_init_sslset_nolock(curl_sslbackend id, const char *name,
const curl_ssl_backend ***avail);
@@ -68,8 +68,53 @@ CURLsslset Curl_init_sslset_nolock(curl_sslbackend id, const char *name,
/* see https://www.iana.org/assignments/tls-extensiontype-values/ */
#define ALPN_HTTP_1_1_LENGTH 8
#define ALPN_HTTP_1_1 "http/1.1"
+#define ALPN_HTTP_1_0_LENGTH 8
+#define ALPN_HTTP_1_0 "http/1.0"
#define ALPN_H2_LENGTH 2
#define ALPN_H2 "h2"
+#define ALPN_H3_LENGTH 2
+#define ALPN_H3 "h3"
+
+/* conservative sizes on the ALPN entries and count we are handling,
+ * we can increase these if we ever feel the need or have to accommodate
+ * ALPN strings from the "outside". */
+#define ALPN_NAME_MAX 10
+#define ALPN_ENTRIES_MAX 3
+#define ALPN_PROTO_BUF_MAX (ALPN_ENTRIES_MAX * (ALPN_NAME_MAX + 1))
+
+struct alpn_spec {
+ const char entries[ALPN_ENTRIES_MAX][ALPN_NAME_MAX];
+ size_t count; /* number of entries */
+};
+
+struct alpn_proto_buf {
+ unsigned char data[ALPN_PROTO_BUF_MAX];
+ int len;
+};
+
+CURLcode Curl_alpn_to_proto_buf(struct alpn_proto_buf *buf,
+ const struct alpn_spec *spec);
+CURLcode Curl_alpn_to_proto_str(struct alpn_proto_buf *buf,
+ const struct alpn_spec *spec);
+
+CURLcode Curl_alpn_set_negotiated(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ const unsigned char *proto,
+ size_t proto_len);
+
+/**
+ * Get the ALPN specification to use for talking to remote host.
+ * May return NULL if ALPN is disabled on the connection.
+ */
+const struct alpn_spec *
+Curl_alpn_get_spec(struct Curl_easy *data, struct connectdata *conn);
+
+/**
+ * Get the ALPN specification to use for talking to the proxy.
+ * May return NULL if ALPN is disabled on the connection.
+ */
+const struct alpn_spec *
+Curl_alpn_get_proxy_spec(struct Curl_easy *data, struct connectdata *conn);
char *Curl_ssl_snihost(struct Curl_easy *data, const char *host, size_t *olen);
@@ -95,7 +140,6 @@ struct curl_slist *Curl_ssl_engines_list(struct Curl_easy *data);
/* init the SSL session ID cache */
CURLcode Curl_ssl_initsessions(struct Curl_easy *, size_t);
void Curl_ssl_version(char *buffer, size_t size);
-int Curl_ssl_check_cxn(struct Curl_easy *data, struct connectdata *conn);
/* Certificate information list handling. */
@@ -156,6 +200,9 @@ CURLcode Curl_ssl_cfilter_add(struct Curl_easy *data,
struct connectdata *conn,
int sockindex);
+CURLcode Curl_cf_ssl_insert_after(struct Curl_cfilter *cf_at,
+ struct Curl_easy *data);
+
CURLcode Curl_ssl_cfilter_remove(struct Curl_easy *data,
int sockindex);
@@ -163,6 +210,8 @@ CURLcode Curl_ssl_cfilter_remove(struct Curl_easy *data,
CURLcode Curl_ssl_cfilter_proxy_add(struct Curl_easy *data,
struct connectdata *conn,
int sockindex);
+CURLcode Curl_cf_ssl_proxy_insert_after(struct Curl_cfilter *cf_at,
+ struct Curl_easy *data);
#endif /* !CURL_DISABLE_PROXY */
/**
@@ -208,6 +257,9 @@ bool Curl_ssl_supports(struct Curl_easy *data, int ssl_option);
void *Curl_ssl_get_internals(struct Curl_easy *data, int sockindex,
CURLINFO info, int n);
+extern struct Curl_cftype Curl_cft_ssl;
+extern struct Curl_cftype Curl_cft_ssl_proxy;
+
#else /* if not USE_SSL */
/* When SSL support is not present, just define away these function calls */
@@ -218,7 +270,6 @@ void *Curl_ssl_get_internals(struct Curl_easy *data, int sockindex,
#define Curl_ssl_set_engine_default(x) CURLE_NOT_BUILT_IN
#define Curl_ssl_engines_list(x) NULL
#define Curl_ssl_initsessions(x,y) CURLE_OK
-#define Curl_ssl_check_cxn(d,x) 0
#define Curl_ssl_free_certinfo(x) Curl_nop_stmt
#define Curl_ssl_kill_session(x) Curl_nop_stmt
#define Curl_ssl_random(x,y,z) ((void)x, CURLE_NOT_BUILT_IN)
diff --git a/Utilities/cmcurl/lib/vtls/vtls_int.h b/Utilities/cmcurl/lib/vtls/vtls_int.h
index 6710a2b559..a20ca7db7f 100644
--- a/Utilities/cmcurl/lib/vtls/vtls_int.h
+++ b/Utilities/cmcurl/lib/vtls/vtls_int.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -33,18 +33,20 @@
struct ssl_connect_data {
ssl_connection_state state;
ssl_connect_state connecting_state;
- const char *hostname; /* hostnaem for verification */
- const char *dispname; /* display version of hostname */
+ char *hostname; /* hostname for verification */
+ char *dispname; /* display version of hostname */
int port; /* remote port at origin */
+ const struct alpn_spec *alpn; /* ALPN to use or NULL for none */
struct ssl_backend_data *backend; /* vtls backend specific props */
- struct Curl_easy *call_data; /* data handle used in current call,
- * same as parameter passed, but available
- * here for backend internal callbacks
- * that need it. NULLed after at the
- * end of each vtls filter invcocation. */
+ struct cf_call_data call_data; /* data handle used in current call */
+ struct curltime handshake_done; /* time when handshake finished */
};
+#define CF_CTX_CALL_DATA(cf) \
+ ((struct ssl_connect_data *)(cf)->ctx)->call_data
+
+
/* Definitions for SSL Implementations */
struct Curl_ssl {
diff --git a/Utilities/cmcurl/lib/vtls/wolfssl.c b/Utilities/cmcurl/lib/vtls/wolfssl.c
index 7cc4774e83..2e57899324 100644
--- a/Utilities/cmcurl/lib/vtls/wolfssl.c
+++ b/Utilities/cmcurl/lib/vtls/wolfssl.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -218,29 +218,9 @@ static const struct group_name_map gnm[] = {
{ WOLFSSL_KYBER_LEVEL1, "KYBER_LEVEL1" },
{ WOLFSSL_KYBER_LEVEL3, "KYBER_LEVEL3" },
{ WOLFSSL_KYBER_LEVEL5, "KYBER_LEVEL5" },
- { WOLFSSL_NTRU_HPS_LEVEL1, "NTRU_HPS_LEVEL1" },
- { WOLFSSL_NTRU_HPS_LEVEL3, "NTRU_HPS_LEVEL3" },
- { WOLFSSL_NTRU_HPS_LEVEL5, "NTRU_HPS_LEVEL5" },
- { WOLFSSL_NTRU_HRSS_LEVEL3, "NTRU_HRSS_LEVEL3" },
- { WOLFSSL_SABER_LEVEL1, "SABER_LEVEL1" },
- { WOLFSSL_SABER_LEVEL3, "SABER_LEVEL3" },
- { WOLFSSL_SABER_LEVEL5, "SABER_LEVEL5" },
- { WOLFSSL_KYBER_90S_LEVEL1, "KYBER_90S_LEVEL1" },
- { WOLFSSL_KYBER_90S_LEVEL3, "KYBER_90S_LEVEL3" },
- { WOLFSSL_KYBER_90S_LEVEL5, "KYBER_90S_LEVEL5" },
- { WOLFSSL_P256_NTRU_HPS_LEVEL1, "P256_NTRU_HPS_LEVEL1" },
- { WOLFSSL_P384_NTRU_HPS_LEVEL3, "P384_NTRU_HPS_LEVEL3" },
- { WOLFSSL_P521_NTRU_HPS_LEVEL5, "P521_NTRU_HPS_LEVEL5" },
- { WOLFSSL_P384_NTRU_HRSS_LEVEL3, "P384_NTRU_HRSS_LEVEL3" },
- { WOLFSSL_P256_SABER_LEVEL1, "P256_SABER_LEVEL1" },
- { WOLFSSL_P384_SABER_LEVEL3, "P384_SABER_LEVEL3" },
- { WOLFSSL_P521_SABER_LEVEL5, "P521_SABER_LEVEL5" },
{ WOLFSSL_P256_KYBER_LEVEL1, "P256_KYBER_LEVEL1" },
{ WOLFSSL_P384_KYBER_LEVEL3, "P384_KYBER_LEVEL3" },
{ WOLFSSL_P521_KYBER_LEVEL5, "P521_KYBER_LEVEL5" },
- { WOLFSSL_P256_KYBER_90S_LEVEL1, "P256_KYBER_90S_LEVEL1" },
- { WOLFSSL_P384_KYBER_90S_LEVEL3, "P384_KYBER_90S_LEVEL3" },
- { WOLFSSL_P521_KYBER_90S_LEVEL5, "P521_KYBER_90S_LEVEL5" },
{ 0, NULL }
};
#endif
@@ -299,8 +279,7 @@ static long bio_cf_ctrl(WOLFSSL_BIO *bio, int cmd, long num, void *ptr)
static int bio_cf_out_write(WOLFSSL_BIO *bio, const char *buf, int blen)
{
struct Curl_cfilter *cf = wolfSSL_BIO_get_data(bio);
- struct ssl_connect_data *connssl = cf->ctx;
- struct Curl_easy *data = connssl->call_data;
+ struct Curl_easy *data = CF_DATA_CURRENT(cf);
ssize_t nwritten;
CURLcode result = CURLE_OK;
@@ -315,8 +294,7 @@ static int bio_cf_out_write(WOLFSSL_BIO *bio, const char *buf, int blen)
static int bio_cf_in_read(WOLFSSL_BIO *bio, char *buf, int blen)
{
struct Curl_cfilter *cf = wolfSSL_BIO_get_data(bio);
- struct ssl_connect_data *connssl = cf->ctx;
- struct Curl_easy *data = connssl->call_data;
+ struct Curl_easy *data = CF_DATA_CURRENT(cf);
ssize_t nread;
CURLcode result = CURLE_OK;
@@ -633,29 +611,18 @@ wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
#endif
#ifdef HAVE_ALPN
- if(cf->conn->bits.tls_enable_alpn) {
- char protocols[128];
- *protocols = '\0';
-
- /* wolfSSL's ALPN protocol name list format is a comma separated string of
- protocols in descending order of preference, eg: "h2,http/1.1" */
-
-#ifdef USE_HTTP2
- if(data->state.httpwant >= CURL_HTTP_VERSION_2) {
- strcpy(protocols + strlen(protocols), ALPN_H2 ",");
- infof(data, VTLS_INFOF_ALPN_OFFER_1STR, ALPN_H2);
- }
-#endif
-
- strcpy(protocols + strlen(protocols), ALPN_HTTP_1_1);
- infof(data, VTLS_INFOF_ALPN_OFFER_1STR, ALPN_HTTP_1_1);
+ if(connssl->alpn) {
+ struct alpn_proto_buf proto;
+ CURLcode result;
- if(wolfSSL_UseALPN(backend->handle, protocols,
- (unsigned)strlen(protocols),
+ result = Curl_alpn_to_proto_str(&proto, connssl->alpn);
+ if(result ||
+ wolfSSL_UseALPN(backend->handle, (char *)proto.data, proto.len,
WOLFSSL_ALPN_CONTINUE_ON_MISMATCH) != SSL_SUCCESS) {
failf(data, "SSL: failed setting ALPN protocols");
return CURLE_SSL_CONNECT_ERROR;
}
+ infof(data, VTLS_INFOF_ALPN_OFFER_1STR, proto.data);
}
#endif /* HAVE_ALPN */
@@ -707,7 +674,7 @@ wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
}
#else /* USE_BIO_CHAIN */
/* pass the raw socket into the SSL layer */
- if(!SSL_set_fd(backend->handle, (int)cf->conn->sock[cf->sockindex])) {
+ if(!SSL_set_fd(backend->handle, (int)Curl_conn_cf_get_socket(cf, data))) {
failf(data, "SSL: SSL_set_fd failed");
return CURLE_SSL_CONNECT_ERROR;
}
@@ -883,25 +850,11 @@ wolfssl_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data)
rc = wolfSSL_ALPN_GetProtocol(backend->handle, &protocol, &protocol_len);
if(rc == SSL_SUCCESS) {
- infof(data, VTLS_INFOF_ALPN_ACCEPTED_LEN_1STR, protocol_len, protocol);
-
- if(protocol_len == ALPN_HTTP_1_1_LENGTH &&
- !memcmp(protocol, ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH))
- cf->conn->alpn = CURL_HTTP_VERSION_1_1;
-#ifdef USE_HTTP2
- else if(data->state.httpwant >= CURL_HTTP_VERSION_2 &&
- protocol_len == ALPN_H2_LENGTH &&
- !memcmp(protocol, ALPN_H2, ALPN_H2_LENGTH))
- cf->conn->alpn = CURL_HTTP_VERSION_2;
-#endif
- else
- infof(data, "ALPN, unrecognized protocol %.*s", protocol_len,
- protocol);
- Curl_multiuse_state(data, cf->conn->alpn == CURL_HTTP_VERSION_2 ?
- BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
+ Curl_alpn_set_negotiated(cf, data, (const unsigned char *)protocol,
+ protocol_len);
}
else if(rc == SSL_ALPN_NOT_FOUND)
- infof(data, VTLS_INFOF_NO_ALPN);
+ Curl_alpn_set_negotiated(cf, data, NULL, 0);
else {
failf(data, "ALPN, failure getting protocol, error %d", rc);
return CURLE_SSL_CONNECT_ERROR;
@@ -1166,7 +1119,7 @@ wolfssl_connect_common(struct Curl_cfilter *cf,
{
CURLcode result;
struct ssl_connect_data *connssl = cf->ctx;
- curl_socket_t sockfd = cf->conn->sock[cf->sockindex];
+ curl_socket_t sockfd = Curl_conn_cf_get_socket(cf, data);
int what;
/* check if the connection has already been established */
diff --git a/Utilities/cmcurl/lib/vtls/wolfssl.h b/Utilities/cmcurl/lib/vtls/wolfssl.h
index b2e7c3fde2..a5ed848099 100644
--- a/Utilities/cmcurl/lib/vtls/wolfssl.h
+++ b/Utilities/cmcurl/lib/vtls/wolfssl.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/Utilities/cmcurl/lib/vtls/x509asn1.c b/Utilities/cmcurl/lib/vtls/x509asn1.c
index 4c1c9a8b79..39e4fb33bc 100644
--- a/Utilities/cmcurl/lib/vtls/x509asn1.c
+++ b/Utilities/cmcurl/lib/vtls/x509asn1.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -48,6 +48,7 @@
#include "curl_ctype.h"
#include "hostcheck.h"
#include "vtls/vtls.h"
+#include "vtls/vtls_int.h"
#include "sendf.h"
#include "inet_pton.h"
#include "curl_base64.h"
@@ -1313,7 +1314,8 @@ CURLcode Curl_verifyhost(struct Curl_cfilter *cf,
/* Get the server IP address. */
#ifdef ENABLE_IPV6
- if(conn->bits.ipv6_ip && Curl_inet_pton(AF_INET6, connssl->hostname, &addr))
+ if(cf->conn->bits.ipv6_ip &&
+ Curl_inet_pton(AF_INET6, connssl->hostname, &addr))
addrlen = sizeof(struct in6_addr);
else
#endif
@@ -1348,19 +1350,18 @@ CURLcode Curl_verifyhost(struct Curl_cfilter *cf,
break;
switch(name.tag) {
case 2: /* DNS name. */
- matched = 0;
len = utf8asn1str(&dnsname, CURL_ASN1_IA5_STRING,
name.beg, name.end);
- if(len > 0) {
- if(size_t)len == strlen(dnsname)
- matched = Curl_cert_hostcheck(dnsname, (size_t)len,
- connssl->hostname, hostlen);
- free(dnsname);
- }
+ if(len > 0 && (size_t)len == strlen(dnsname))
+ matched = Curl_cert_hostcheck(dnsname, (size_t)len,
+ connssl->hostname, hostlen);
+ else
+ matched = 0;
+ free(dnsname);
break;
case 7: /* IP address. */
- matched = (name.end - name.beg) == addrlen &&
+ matched = (size_t)(name.end - name.beg) == addrlen &&
!memcmp(&addr, name.beg, addrlen);
break;
}
@@ -1406,8 +1407,10 @@ CURLcode Curl_verifyhost(struct Curl_cfilter *cf,
failf(data, "SSL: unable to obtain common name from peer certificate");
else {
len = utf8asn1str(&dnsname, elem.tag, elem.beg, elem.end);
- if(len < 0)
+ if(len < 0) {
+ free(dnsname);
return CURLE_OUT_OF_MEMORY;
+ }
if(strlen(dnsname) != (size_t) len) /* Nul byte in string ? */
failf(data, "SSL: illegal cert name field");
else if(Curl_cert_hostcheck((const char *) dnsname,
diff --git a/Utilities/cmcurl/lib/vtls/x509asn1.h b/Utilities/cmcurl/lib/vtls/x509asn1.h
index eb8e9597cb..5496de40e4 100644
--- a/Utilities/cmcurl/lib/vtls/x509asn1.h
+++ b/Utilities/cmcurl/lib/vtls/x509asn1.h
@@ -8,7 +8,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms