Родитель
49573bc187
Коммит
3210101088
|
@ -1068,7 +1068,7 @@ static void cf_h1_proxy_close(struct Curl_cfilter *cf,
|
|||
|
||||
struct Curl_cftype Curl_cft_h1_proxy = {
|
||||
"H1-PROXY",
|
||||
CF_TYPE_IP_CONNECT,
|
||||
CF_TYPE_IP_CONNECT|CF_TYPE_PROXY,
|
||||
0,
|
||||
cf_h1_proxy_destroy,
|
||||
cf_h1_proxy_connect,
|
||||
|
|
|
@ -1532,7 +1532,7 @@ static bool cf_h2_proxy_is_alive(struct Curl_cfilter *cf,
|
|||
|
||||
struct Curl_cftype Curl_cft_h2_proxy = {
|
||||
"H2-PROXY",
|
||||
CF_TYPE_IP_CONNECT,
|
||||
CF_TYPE_IP_CONNECT|CF_TYPE_PROXY,
|
||||
CURL_LOG_LVL_NONE,
|
||||
cf_h2_proxy_destroy,
|
||||
cf_h2_proxy_connect,
|
||||
|
|
|
@ -189,7 +189,7 @@ static void cf_haproxy_adjust_pollset(struct Curl_cfilter *cf,
|
|||
|
||||
struct Curl_cftype Curl_cft_haproxy = {
|
||||
"HAPROXY",
|
||||
0,
|
||||
CF_TYPE_PROXY,
|
||||
0,
|
||||
cf_haproxy_destroy,
|
||||
cf_haproxy_connect,
|
||||
|
|
|
@ -178,10 +178,12 @@ typedef CURLcode Curl_cft_query(struct Curl_cfilter *cf,
|
|||
* connection, etc.
|
||||
* CF_TYPE_SSL: provide SSL/TLS
|
||||
* CF_TYPE_MULTIPLEX: provides multiplexing of easy handles
|
||||
* CF_TYPE_PROXY provides proxying
|
||||
*/
|
||||
#define CF_TYPE_IP_CONNECT (1 << 0)
|
||||
#define CF_TYPE_SSL (1 << 1)
|
||||
#define CF_TYPE_MULTIPLEX (1 << 2)
|
||||
#define CF_TYPE_PROXY (1 << 3)
|
||||
|
||||
/* A connection filter type, e.g. specific implementation. */
|
||||
struct Curl_cftype {
|
||||
|
|
|
@ -293,7 +293,7 @@ static void http_proxy_cf_close(struct Curl_cfilter *cf,
|
|||
|
||||
struct Curl_cftype Curl_cft_http_proxy = {
|
||||
"HTTP-PROXY",
|
||||
CF_TYPE_IP_CONNECT,
|
||||
CF_TYPE_IP_CONNECT|CF_TYPE_PROXY,
|
||||
0,
|
||||
http_proxy_cf_destroy,
|
||||
http_proxy_cf_connect,
|
||||
|
|
|
@ -1244,7 +1244,7 @@ static void socks_cf_get_host(struct Curl_cfilter *cf,
|
|||
|
||||
struct Curl_cftype Curl_cft_socks_proxy = {
|
||||
"SOCKS-PROXYY",
|
||||
CF_TYPE_IP_CONNECT,
|
||||
CF_TYPE_IP_CONNECT|CF_TYPE_PROXY,
|
||||
0,
|
||||
socks_proxy_cf_destroy,
|
||||
socks_proxy_cf_connect,
|
||||
|
|
|
@ -279,6 +279,8 @@ struct ssl_peer {
|
|||
char *dispname; /* display version of hostname */
|
||||
char *sni; /* SNI version of hostname or NULL if not usable */
|
||||
ssl_peer_type type; /* type of the peer information */
|
||||
int port; /* port we are talking to */
|
||||
int transport; /* TCP or QUIC */
|
||||
};
|
||||
|
||||
struct ssl_primary_config {
|
||||
|
@ -344,6 +346,7 @@ struct Curl_ssl_session {
|
|||
long age; /* just a number, the higher the more recent */
|
||||
int remote_port; /* remote port */
|
||||
int conn_to_port; /* remote port for the connection (may be -1) */
|
||||
int transport; /* TCP or QUIC */
|
||||
struct ssl_primary_config ssl_config; /* setup for this session */
|
||||
};
|
||||
|
||||
|
|
|
@ -113,7 +113,7 @@ void Curl_ngtcp2_ver(char *p, size_t len)
|
|||
struct cf_ngtcp2_ctx {
|
||||
struct cf_quic_ctx q;
|
||||
struct ssl_peer peer;
|
||||
struct quic_tls_ctx tls;
|
||||
struct curl_tls_ctx tls;
|
||||
ngtcp2_path connected_path;
|
||||
ngtcp2_conn *qconn;
|
||||
ngtcp2_cid dcid;
|
||||
|
@ -1909,25 +1909,60 @@ static void cf_ngtcp2_destroy(struct Curl_cfilter *cf, struct Curl_easy *data)
|
|||
(void)save;
|
||||
}
|
||||
|
||||
static CURLcode tls_ctx_setup(struct quic_tls_ctx *ctx,
|
||||
struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data)
|
||||
#ifdef USE_OPENSSL
|
||||
/* The "new session" callback must return zero if the session can be removed
|
||||
* or non-zero if the session has been put into the session cache.
|
||||
*/
|
||||
static int ossl_new_session_cb(SSL *ssl, SSL_SESSION *ssl_sessionid)
|
||||
{
|
||||
struct Curl_cfilter *cf;
|
||||
struct cf_ngtcp2_ctx *ctx;
|
||||
struct Curl_easy *data;
|
||||
ngtcp2_crypto_conn_ref *cref;
|
||||
|
||||
cref = (ngtcp2_crypto_conn_ref *)SSL_get_app_data(ssl);
|
||||
cf = cref? cref->user_data : NULL;
|
||||
ctx = cf? cf->ctx : NULL;
|
||||
data = cf? CF_DATA_CURRENT(cf) : NULL;
|
||||
if(cf && data && ctx) {
|
||||
CURLcode result = Curl_ossl_add_session(cf, data, &ctx->peer,
|
||||
ssl_sessionid);
|
||||
return result? 0 : 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif /* USE_OPENSSL */
|
||||
|
||||
static CURLcode tls_ctx_setup(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
void *user_data)
|
||||
{
|
||||
struct curl_tls_ctx *ctx = user_data;
|
||||
(void)cf;
|
||||
#ifdef USE_OPENSSL
|
||||
#if defined(OPENSSL_IS_BORINGSSL) || defined(OPENSSL_IS_AWSLC)
|
||||
if(ngtcp2_crypto_boringssl_configure_client_context(ctx->ssl_ctx) != 0) {
|
||||
if(ngtcp2_crypto_boringssl_configure_client_context(ctx->ossl.ssl_ctx)
|
||||
!= 0) {
|
||||
failf(data, "ngtcp2_crypto_boringssl_configure_client_context failed");
|
||||
return CURLE_FAILED_INIT;
|
||||
}
|
||||
#else
|
||||
if(ngtcp2_crypto_quictls_configure_client_context(ctx->ssl_ctx) != 0) {
|
||||
if(ngtcp2_crypto_quictls_configure_client_context(ctx->ossl.ssl_ctx) != 0) {
|
||||
failf(data, "ngtcp2_crypto_quictls_configure_client_context failed");
|
||||
return CURLE_FAILED_INIT;
|
||||
}
|
||||
#endif /* !OPENSSL_IS_BORINGSSL && !OPENSSL_IS_AWSLC */
|
||||
/* Enable the session cache because it's a prerequisite for the
|
||||
* "new session" callback. Use the "external storage" mode to prevent
|
||||
* OpenSSL from creating an internal session cache.
|
||||
*/
|
||||
SSL_CTX_set_session_cache_mode(ctx->ossl.ssl_ctx,
|
||||
SSL_SESS_CACHE_CLIENT |
|
||||
SSL_SESS_CACHE_NO_INTERNAL);
|
||||
SSL_CTX_sess_set_new_cb(ctx->ossl.ssl_ctx, ossl_new_session_cb);
|
||||
|
||||
#elif defined(USE_GNUTLS)
|
||||
if(ngtcp2_crypto_gnutls_configure_client_session(ctx->gtls->session) != 0) {
|
||||
if(ngtcp2_crypto_gnutls_configure_client_session(ctx->gtls.session) != 0) {
|
||||
failf(data, "ngtcp2_crypto_gnutls_configure_client_session failed");
|
||||
return CURLE_FAILED_INIT;
|
||||
}
|
||||
|
@ -1960,17 +1995,21 @@ static CURLcode cf_connect_start(struct Curl_cfilter *cf,
|
|||
Curl_bufcp_init(&ctx->stream_bufcp, H3_STREAM_CHUNK_SIZE,
|
||||
H3_STREAM_POOL_SPARES);
|
||||
|
||||
result = Curl_ssl_peer_init(&ctx->peer, cf);
|
||||
result = Curl_ssl_peer_init(&ctx->peer, cf, TRNSPRT_QUIC);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
#define H3_ALPN "\x2h3\x5h3-29"
|
||||
result = Curl_vquic_tls_init(&ctx->tls, cf, data, &ctx->peer,
|
||||
H3_ALPN, sizeof(H3_ALPN) - 1,
|
||||
tls_ctx_setup, &ctx->conn_ref);
|
||||
tls_ctx_setup, &ctx->tls, &ctx->conn_ref);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
#ifdef USE_OPENSSL
|
||||
SSL_set_quic_use_legacy_codepoint(ctx->tls.ossl.ssl, 0);
|
||||
#endif
|
||||
|
||||
ctx->dcid.datalen = NGTCP2_MAX_CIDLEN;
|
||||
result = Curl_rand(data, ctx->dcid.data, NGTCP2_MAX_CIDLEN);
|
||||
if(result)
|
||||
|
@ -2012,8 +2051,10 @@ static CURLcode cf_connect_start(struct Curl_cfilter *cf,
|
|||
if(rc)
|
||||
return CURLE_QUIC_CONNECT_ERROR;
|
||||
|
||||
#ifdef USE_GNUTLS
|
||||
ngtcp2_conn_set_tls_native_handle(ctx->qconn, ctx->tls.gtls->session);
|
||||
#ifdef USE_OPENSSL
|
||||
ngtcp2_conn_set_tls_native_handle(ctx->qconn, ctx->tls.ossl.ssl);
|
||||
#elif defined(USE_GNUTLS)
|
||||
ngtcp2_conn_set_tls_native_handle(ctx->qconn, ctx->tls.gtls.session);
|
||||
#else
|
||||
ngtcp2_conn_set_tls_native_handle(ctx->qconn, ctx->tls.ssl);
|
||||
#endif
|
||||
|
|
|
@ -281,7 +281,7 @@ static void cf_osslq_h3conn_cleanup(struct cf_osslq_h3conn *h3)
|
|||
struct cf_osslq_ctx {
|
||||
struct cf_quic_ctx q;
|
||||
struct ssl_peer peer;
|
||||
struct quic_tls_ctx tls;
|
||||
struct curl_tls_ctx tls;
|
||||
struct cf_call_data call_data;
|
||||
struct cf_osslq_h3conn h3;
|
||||
struct curltime started_at; /* time the current attempt started */
|
||||
|
@ -318,7 +318,7 @@ static void cf_osslq_close(struct Curl_cfilter *cf, struct Curl_easy *data)
|
|||
struct cf_call_data save;
|
||||
|
||||
CF_DATA_SAVE(save, cf, data);
|
||||
if(ctx && ctx->tls.ssl) {
|
||||
if(ctx && ctx->tls.ossl.ssl) {
|
||||
/* TODO: send connection close */
|
||||
CURL_TRC_CF(data, cf, "cf_osslq_close()");
|
||||
cf_osslq_ctx_clear(ctx);
|
||||
|
@ -403,7 +403,7 @@ static CURLcode cf_osslq_ssl_err(struct Curl_cfilter *cf,
|
|||
(reason == SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED))) {
|
||||
result = CURLE_PEER_FAILED_VERIFICATION;
|
||||
|
||||
lerr = SSL_get_verify_result(ctx->tls.ssl);
|
||||
lerr = SSL_get_verify_result(ctx->tls.ossl.ssl);
|
||||
if(lerr != X509_V_OK) {
|
||||
ssl_config->certverifyresult = lerr;
|
||||
msnprintf(ebuf, sizeof(ebuf),
|
||||
|
@ -1047,14 +1047,14 @@ static CURLcode cf_osslq_ctx_start(struct Curl_cfilter *cf,
|
|||
|
||||
Curl_bufcp_init(&ctx->stream_bufcp, H3_STREAM_CHUNK_SIZE,
|
||||
H3_STREAM_POOL_SPARES);
|
||||
result = Curl_ssl_peer_init(&ctx->peer, cf);
|
||||
result = Curl_ssl_peer_init(&ctx->peer, cf, TRNSPRT_QUIC);
|
||||
if(result)
|
||||
goto out;
|
||||
|
||||
#define H3_ALPN "\x2h3"
|
||||
result = Curl_vquic_tls_init(&ctx->tls, cf, data, &ctx->peer,
|
||||
H3_ALPN, sizeof(H3_ALPN) - 1,
|
||||
NULL, NULL);
|
||||
NULL, NULL, NULL);
|
||||
if(result)
|
||||
goto out;
|
||||
|
||||
|
@ -1098,12 +1098,12 @@ static CURLcode cf_osslq_ctx_start(struct Curl_cfilter *cf,
|
|||
goto out;
|
||||
}
|
||||
|
||||
if(!SSL_set1_initial_peer_addr(ctx->tls.ssl, baddr)) {
|
||||
if(!SSL_set1_initial_peer_addr(ctx->tls.ossl.ssl, baddr)) {
|
||||
failf(data, "failed to set the initial peer address");
|
||||
result = CURLE_FAILED_INIT;
|
||||
goto out;
|
||||
}
|
||||
if(!SSL_set_blocking_mode(ctx->tls.ssl, 0)) {
|
||||
if(!SSL_set_blocking_mode(ctx->tls.ossl.ssl, 0)) {
|
||||
failf(data, "failed to turn off blocking mode");
|
||||
result = CURLE_FAILED_INIT;
|
||||
goto out;
|
||||
|
@ -1111,7 +1111,8 @@ static CURLcode cf_osslq_ctx_start(struct Curl_cfilter *cf,
|
|||
|
||||
#ifdef SSL_VALUE_QUIC_IDLE_TIMEOUT
|
||||
/* Added in OpenSSL v3.3.x */
|
||||
if(!SSL_set_feature_request_uint(ctx->tls.ssl, SSL_VALUE_QUIC_IDLE_TIMEOUT,
|
||||
if(!SSL_set_feature_request_uint(ctx->tls.ossl.ssl,
|
||||
SSL_VALUE_QUIC_IDLE_TIMEOUT,
|
||||
CURL_QUIC_MAX_IDLE_MS)) {
|
||||
CURL_TRC_CF(data, cf, "error setting idle timeout, ");
|
||||
result = CURLE_FAILED_INIT;
|
||||
|
@ -1119,13 +1120,13 @@ static CURLcode cf_osslq_ctx_start(struct Curl_cfilter *cf,
|
|||
}
|
||||
#endif
|
||||
|
||||
SSL_set_bio(ctx->tls.ssl, bio, bio);
|
||||
SSL_set_bio(ctx->tls.ossl.ssl, bio, bio);
|
||||
bio = NULL;
|
||||
SSL_set_connect_state(ctx->tls.ssl);
|
||||
SSL_set_incoming_stream_policy(ctx->tls.ssl,
|
||||
SSL_set_connect_state(ctx->tls.ossl.ssl);
|
||||
SSL_set_incoming_stream_policy(ctx->tls.ossl.ssl,
|
||||
SSL_INCOMING_STREAM_POLICY_ACCEPT, 0);
|
||||
/* setup the H3 things on top of the QUIC connection */
|
||||
result = cf_osslq_h3conn_init(ctx, ctx->tls.ssl, cf);
|
||||
result = cf_osslq_h3conn_init(ctx, ctx->tls.ossl.ssl, cf);
|
||||
|
||||
out:
|
||||
if(bio)
|
||||
|
@ -1288,22 +1289,23 @@ static CURLcode cf_progress_ingress(struct Curl_cfilter *cf,
|
|||
struct cf_osslq_ctx *ctx = cf->ctx;
|
||||
CURLcode result = CURLE_OK;
|
||||
|
||||
if(!ctx->tls.ssl)
|
||||
if(!ctx->tls.ossl.ssl)
|
||||
goto out;
|
||||
|
||||
ERR_clear_error();
|
||||
|
||||
/* 1. Check for new incoming streams */
|
||||
while(1) {
|
||||
SSL *snew = SSL_accept_stream(ctx->tls.ssl, SSL_ACCEPT_STREAM_NO_BLOCK);
|
||||
SSL *snew = SSL_accept_stream(ctx->tls.ossl.ssl,
|
||||
SSL_ACCEPT_STREAM_NO_BLOCK);
|
||||
if(!snew)
|
||||
break;
|
||||
|
||||
(void)cf_osslq_h3conn_add_stream(&ctx->h3, snew, cf, data);
|
||||
}
|
||||
|
||||
if(!SSL_handle_events(ctx->tls.ssl)) {
|
||||
int detail = SSL_get_error(ctx->tls.ssl, 0);
|
||||
if(!SSL_handle_events(ctx->tls.ossl.ssl)) {
|
||||
int detail = SSL_get_error(ctx->tls.ossl.ssl, 0);
|
||||
result = cf_osslq_ssl_err(cf, data, detail, CURLE_RECV_ERROR);
|
||||
}
|
||||
|
||||
|
@ -1370,7 +1372,7 @@ static CURLcode h3_send_streams(struct Curl_cfilter *cf,
|
|||
struct cf_osslq_ctx *ctx = cf->ctx;
|
||||
CURLcode result = CURLE_OK;
|
||||
|
||||
if(!ctx->tls.ssl || !ctx->h3.conn)
|
||||
if(!ctx->tls.ossl.ssl || !ctx->h3.conn)
|
||||
goto out;
|
||||
|
||||
for(;;) {
|
||||
|
@ -1493,7 +1495,7 @@ static CURLcode cf_progress_egress(struct Curl_cfilter *cf,
|
|||
struct cf_osslq_ctx *ctx = cf->ctx;
|
||||
CURLcode result = CURLE_OK;
|
||||
|
||||
if(!ctx->tls.ssl)
|
||||
if(!ctx->tls.ossl.ssl)
|
||||
goto out;
|
||||
|
||||
ERR_clear_error();
|
||||
|
@ -1501,8 +1503,8 @@ static CURLcode cf_progress_egress(struct Curl_cfilter *cf,
|
|||
if(result)
|
||||
goto out;
|
||||
|
||||
if(!SSL_handle_events(ctx->tls.ssl)) {
|
||||
int detail = SSL_get_error(ctx->tls.ssl, 0);
|
||||
if(!SSL_handle_events(ctx->tls.ossl.ssl)) {
|
||||
int detail = SSL_get_error(ctx->tls.ossl.ssl, 0);
|
||||
result = cf_osslq_ssl_err(cf, data, detail, CURLE_SEND_ERROR);
|
||||
}
|
||||
|
||||
|
@ -1522,8 +1524,8 @@ static CURLcode check_and_set_expiry(struct Curl_cfilter *cf,
|
|||
timediff_t timeoutms;
|
||||
int is_infinite = TRUE;
|
||||
|
||||
if(ctx->tls.ssl &&
|
||||
SSL_get_event_timeout(ctx->tls.ssl, &tv, &is_infinite) &&
|
||||
if(ctx->tls.ossl.ssl &&
|
||||
SSL_get_event_timeout(ctx->tls.ossl.ssl, &tv, &is_infinite) &&
|
||||
!is_infinite) {
|
||||
timeoutms = curlx_tvtoms(&tv);
|
||||
/* QUIC want to be called again latest at the returned timeout */
|
||||
|
@ -1534,7 +1536,7 @@ static CURLcode check_and_set_expiry(struct Curl_cfilter *cf,
|
|||
result = cf_progress_egress(cf, data);
|
||||
if(result)
|
||||
goto out;
|
||||
if(SSL_get_event_timeout(ctx->tls.ssl, &tv, &is_infinite)) {
|
||||
if(SSL_get_event_timeout(ctx->tls.ossl.ssl, &tv, &is_infinite)) {
|
||||
timeoutms = curlx_tvtoms(&tv);
|
||||
}
|
||||
}
|
||||
|
@ -1579,7 +1581,7 @@ static CURLcode cf_osslq_connect(struct Curl_cfilter *cf,
|
|||
goto out;
|
||||
}
|
||||
|
||||
if(!ctx->tls.ssl) {
|
||||
if(!ctx->tls.ossl.ssl) {
|
||||
ctx->started_at = now;
|
||||
result = cf_osslq_ctx_start(cf, data);
|
||||
if(result)
|
||||
|
@ -1595,7 +1597,7 @@ static CURLcode cf_osslq_connect(struct Curl_cfilter *cf,
|
|||
}
|
||||
|
||||
ERR_clear_error();
|
||||
err = SSL_do_handshake(ctx->tls.ssl);
|
||||
err = SSL_do_handshake(ctx->tls.ossl.ssl);
|
||||
|
||||
if(err == 1) {
|
||||
/* connected */
|
||||
|
@ -1613,7 +1615,7 @@ static CURLcode cf_osslq_connect(struct Curl_cfilter *cf,
|
|||
}
|
||||
}
|
||||
else {
|
||||
int detail = SSL_get_error(ctx->tls.ssl, err);
|
||||
int detail = SSL_get_error(ctx->tls.ossl.ssl, err);
|
||||
switch(detail) {
|
||||
case SSL_ERROR_WANT_READ:
|
||||
ctx->q.last_io = now;
|
||||
|
@ -1644,7 +1646,8 @@ static CURLcode cf_osslq_connect(struct Curl_cfilter *cf,
|
|||
}
|
||||
|
||||
out:
|
||||
if(result == CURLE_RECV_ERROR && ctx->tls.ssl && ctx->protocol_shutdown) {
|
||||
if(result == CURLE_RECV_ERROR && ctx->tls.ossl.ssl &&
|
||||
ctx->protocol_shutdown) {
|
||||
/* When a QUIC server instance is shutting down, it may send us a
|
||||
* CONNECTION_CLOSE right away. Our connection then enters the DRAINING
|
||||
* state. The CONNECT may work in the near future again. Indicate
|
||||
|
@ -1732,7 +1735,7 @@ static ssize_t h3_stream_open(struct Curl_cfilter *cf,
|
|||
}
|
||||
|
||||
DEBUGASSERT(stream->s.id == -1);
|
||||
*err = cf_osslq_stream_open(&stream->s, ctx->tls.ssl, 0,
|
||||
*err = cf_osslq_stream_open(&stream->s, ctx->tls.ossl.ssl, 0,
|
||||
&ctx->stream_bufcp, data);
|
||||
if(*err) {
|
||||
failf(data, "can't get bidi streams");
|
||||
|
@ -1810,7 +1813,7 @@ static ssize_t cf_osslq_send(struct Curl_cfilter *cf, struct Curl_easy *data,
|
|||
|
||||
CF_DATA_SAVE(save, cf, data);
|
||||
DEBUGASSERT(cf->connected);
|
||||
DEBUGASSERT(ctx->tls.ssl);
|
||||
DEBUGASSERT(ctx->tls.ossl.ssl);
|
||||
DEBUGASSERT(ctx->h3.conn);
|
||||
*err = CURLE_OK;
|
||||
|
||||
|
@ -1952,7 +1955,7 @@ static ssize_t cf_osslq_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
|
|||
CF_DATA_SAVE(save, cf, data);
|
||||
DEBUGASSERT(cf->connected);
|
||||
DEBUGASSERT(ctx);
|
||||
DEBUGASSERT(ctx->tls.ssl);
|
||||
DEBUGASSERT(ctx->tls.ossl.ssl);
|
||||
DEBUGASSERT(ctx->h3.conn);
|
||||
*err = CURLE_OK;
|
||||
|
||||
|
@ -2088,7 +2091,7 @@ static bool cf_osslq_conn_is_alive(struct Curl_cfilter *cf,
|
|||
|
||||
CF_DATA_SAVE(save, cf, data);
|
||||
*input_pending = FALSE;
|
||||
if(!ctx->tls.ssl)
|
||||
if(!ctx->tls.ossl.ssl)
|
||||
goto out;
|
||||
|
||||
#ifdef SSL_VALUE_QUIC_IDLE_TIMEOUT
|
||||
|
@ -2096,7 +2099,8 @@ static bool cf_osslq_conn_is_alive(struct Curl_cfilter *cf,
|
|||
{
|
||||
timediff_t idletime;
|
||||
uint64_t idle_ms = ctx->max_idle_ms;
|
||||
if(!SSL_get_value_uint(ctx->tls.ssl, SSL_VALUE_CLASS_FEATURE_NEGOTIATED,
|
||||
if(!SSL_get_value_uint(ctx->tls.ossl.ssl,
|
||||
SSL_VALUE_CLASS_FEATURE_NEGOTIATED,
|
||||
SSL_VALUE_QUIC_IDLE_TIMEOUT, &idle_ms)) {
|
||||
CURL_TRC_CF(data, cf, "error getting negotiated idle timeout, "
|
||||
"assume connection is dead.");
|
||||
|
@ -2136,15 +2140,15 @@ static void cf_osslq_adjust_pollset(struct Curl_cfilter *cf,
|
|||
{
|
||||
struct cf_osslq_ctx *ctx = cf->ctx;
|
||||
|
||||
if(!ctx->tls.ssl) {
|
||||
if(!ctx->tls.ossl.ssl) {
|
||||
/* NOP */
|
||||
}
|
||||
else if(!cf->connected) {
|
||||
/* during handshake, transfer has not started yet. we always
|
||||
* add our socket for polling if SSL wants to send/recv */
|
||||
Curl_pollset_set(data, ps, ctx->q.sockfd,
|
||||
SSL_net_read_desired(ctx->tls.ssl),
|
||||
SSL_net_write_desired(ctx->tls.ssl));
|
||||
SSL_net_read_desired(ctx->tls.ossl.ssl),
|
||||
SSL_net_write_desired(ctx->tls.ossl.ssl));
|
||||
}
|
||||
else {
|
||||
/* once connected, we only modify the socket if it is present.
|
||||
|
@ -2153,8 +2157,8 @@ static void cf_osslq_adjust_pollset(struct Curl_cfilter *cf,
|
|||
Curl_pollset_check(data, ps, ctx->q.sockfd, &want_recv, &want_send);
|
||||
if(want_recv || want_send) {
|
||||
Curl_pollset_set(data, ps, ctx->q.sockfd,
|
||||
SSL_net_read_desired(ctx->tls.ssl),
|
||||
SSL_net_write_desired(ctx->tls.ssl));
|
||||
SSL_net_read_desired(ctx->tls.ossl.ssl),
|
||||
SSL_net_write_desired(ctx->tls.ossl.ssl));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2170,7 +2174,7 @@ static CURLcode cf_osslq_query(struct Curl_cfilter *cf,
|
|||
#ifdef SSL_VALUE_QUIC_STREAM_BIDI_LOCAL_AVAIL
|
||||
/* Added in OpenSSL v3.3.x */
|
||||
uint64_t v;
|
||||
if(!SSL_get_value_uint(ctx->tls.ssl, SSL_VALUE_CLASS_GENERIC,
|
||||
if(!SSL_get_value_uint(ctx->tls.ossl.ssl, SSL_VALUE_CLASS_GENERIC,
|
||||
SSL_VALUE_QUIC_STREAM_BIDI_LOCAL_AVAIL, &v)) {
|
||||
CURL_TRC_CF(data, cf, "error getting available local bidi streams");
|
||||
return CURLE_HTTP3;
|
||||
|
|
|
@ -88,7 +88,7 @@ void Curl_quiche_ver(char *p, size_t len)
|
|||
struct cf_quiche_ctx {
|
||||
struct cf_quic_ctx q;
|
||||
struct ssl_peer peer;
|
||||
struct quic_tls_ctx tls;
|
||||
struct curl_tls_ctx tls;
|
||||
quiche_conn *qconn;
|
||||
quiche_config *cfg;
|
||||
quiche_h3_conn *h3c;
|
||||
|
@ -123,8 +123,8 @@ static void cf_quiche_ctx_clear(struct cf_quiche_ctx *ctx)
|
|||
quiche_conn_free(ctx->qconn);
|
||||
if(ctx->cfg)
|
||||
quiche_config_free(ctx->cfg);
|
||||
/* quiche just freed ctx->tls.ssl */
|
||||
ctx->tls.ssl = NULL;
|
||||
/* quiche just freed it */
|
||||
ctx->tls.ossl.ssl = NULL;
|
||||
Curl_vquic_tls_cleanup(&ctx->tls);
|
||||
Curl_ssl_peer_cleanup(&ctx->peer);
|
||||
vquic_ctx_free(&ctx->q);
|
||||
|
@ -565,7 +565,7 @@ static CURLcode recv_pkt(const unsigned char *pkt, size_t pktlen,
|
|||
return CURLE_OK;
|
||||
}
|
||||
else if(QUICHE_ERR_TLS_FAIL == nread) {
|
||||
long verify_ok = SSL_get_verify_result(ctx->tls.ssl);
|
||||
long verify_ok = SSL_get_verify_result(ctx->tls.ossl.ssl);
|
||||
if(verify_ok != X509_V_OK) {
|
||||
failf(r->data, "SSL certificate problem: %s",
|
||||
X509_verify_cert_error_string(verify_ok));
|
||||
|
@ -1202,7 +1202,7 @@ static CURLcode cf_connect_start(struct Curl_cfilter *cf,
|
|||
if(result)
|
||||
return result;
|
||||
|
||||
result = Curl_ssl_peer_init(&ctx->peer, cf);
|
||||
result = Curl_ssl_peer_init(&ctx->peer, cf, TRNSPRT_QUIC);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
|
@ -1237,7 +1237,7 @@ static CURLcode cf_connect_start(struct Curl_cfilter *cf,
|
|||
result = Curl_vquic_tls_init(&ctx->tls, cf, data, &ctx->peer,
|
||||
QUICHE_H3_APPLICATION_PROTOCOL,
|
||||
sizeof(QUICHE_H3_APPLICATION_PROTOCOL) - 1,
|
||||
NULL, cf);
|
||||
NULL, NULL, cf);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
|
@ -1257,7 +1257,7 @@ static CURLcode cf_connect_start(struct Curl_cfilter *cf,
|
|||
(struct sockaddr *)&ctx->q.local_addr,
|
||||
ctx->q.local_addrlen,
|
||||
&sockaddr->sa_addr, sockaddr->addrlen,
|
||||
ctx->cfg, ctx->tls.ssl, false);
|
||||
ctx->cfg, ctx->tls.ossl.ssl, false);
|
||||
if(!ctx->qconn) {
|
||||
failf(data, "can't create quiche connection");
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
|
|
@ -61,277 +61,12 @@
|
|||
#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
|
||||
#endif
|
||||
|
||||
#ifdef USE_OPENSSL
|
||||
#define QUIC_CIPHERS \
|
||||
"TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_" \
|
||||
"POLY1305_SHA256:TLS_AES_128_CCM_SHA256"
|
||||
#define QUIC_GROUPS "P-256:X25519:P-384:P-521"
|
||||
#elif defined(USE_GNUTLS)
|
||||
#define QUIC_PRIORITY \
|
||||
"NORMAL:-VERS-ALL:+VERS-TLS1.3:-CIPHER-ALL:+AES-128-GCM:+AES-256-GCM:" \
|
||||
"+CHACHA20-POLY1305:+AES-128-CCM:-GROUP-ALL:+GROUP-SECP256R1:" \
|
||||
"+GROUP-X25519:+GROUP-SECP384R1:+GROUP-SECP521R1:" \
|
||||
"%DISABLE_TLS13_COMPAT_MODE"
|
||||
#elif defined(USE_WOLFSSL)
|
||||
#if defined(USE_WOLFSSL)
|
||||
|
||||
#define QUIC_CIPHERS \
|
||||
"TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_" \
|
||||
"POLY1305_SHA256:TLS_AES_128_CCM_SHA256"
|
||||
#define QUIC_GROUPS "P-256:P-384:P-521"
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef USE_OPENSSL
|
||||
|
||||
static void keylog_callback(const SSL *ssl, const char *line)
|
||||
{
|
||||
(void)ssl;
|
||||
Curl_tls_keylog_write_line(line);
|
||||
}
|
||||
|
||||
static CURLcode curl_ossl_init_ctx(struct quic_tls_ctx *ctx,
|
||||
struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
Curl_vquic_tls_ctx_setup *ctx_setup)
|
||||
{
|
||||
struct ssl_primary_config *conn_config;
|
||||
CURLcode result = CURLE_FAILED_INIT;
|
||||
|
||||
DEBUGASSERT(!ctx->ssl_ctx);
|
||||
#ifdef USE_OPENSSL_QUIC
|
||||
ctx->ssl_ctx = SSL_CTX_new(OSSL_QUIC_client_method());
|
||||
#else
|
||||
ctx->ssl_ctx = SSL_CTX_new(TLS_method());
|
||||
#endif
|
||||
if(!ctx->ssl_ctx) {
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
goto out;
|
||||
}
|
||||
conn_config = Curl_ssl_cf_get_primary_config(cf);
|
||||
if(!conn_config) {
|
||||
result = CURLE_FAILED_INIT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if(ctx_setup) {
|
||||
result = ctx_setup(ctx, cf, data);
|
||||
if(result)
|
||||
goto out;
|
||||
}
|
||||
|
||||
SSL_CTX_set_default_verify_paths(ctx->ssl_ctx);
|
||||
|
||||
{
|
||||
const char *curves = conn_config->curves ?
|
||||
conn_config->curves : QUIC_GROUPS;
|
||||
if(!SSL_CTX_set1_curves_list(ctx->ssl_ctx, curves)) {
|
||||
failf(data, "failed setting curves list for QUIC: '%s'", curves);
|
||||
return CURLE_SSL_CIPHER;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_IS_BORINGSSL
|
||||
{
|
||||
const char *ciphers13 = conn_config->cipher_list13 ?
|
||||
conn_config->cipher_list13 : QUIC_CIPHERS;
|
||||
if(SSL_CTX_set_ciphersuites(ctx->ssl_ctx, ciphers13) != 1) {
|
||||
failf(data, "failed setting QUIC cipher suite: %s", ciphers13);
|
||||
return CURLE_SSL_CIPHER;
|
||||
}
|
||||
infof(data, "QUIC cipher selection: %s", ciphers13);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Open the file if a TLS or QUIC backend has not done this before. */
|
||||
Curl_tls_keylog_open();
|
||||
if(Curl_tls_keylog_enabled()) {
|
||||
SSL_CTX_set_keylog_callback(ctx->ssl_ctx, keylog_callback);
|
||||
}
|
||||
|
||||
/* 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
|
||||
* SSL_get_verify_result() below. */
|
||||
SSL_CTX_set_verify(ctx->ssl_ctx, conn_config->verifypeer ?
|
||||
SSL_VERIFY_PEER : SSL_VERIFY_NONE, NULL);
|
||||
|
||||
/* give application a chance to interfere with SSL set up. */
|
||||
if(data->set.ssl.fsslctx) {
|
||||
/* When a user callback is installed to modify the SSL_CTX,
|
||||
* we need to do the full initialization before calling it.
|
||||
* See: #11800 */
|
||||
if(!ctx->x509_store_setup) {
|
||||
result = Curl_ssl_setup_x509_store(cf, data, ctx->ssl_ctx);
|
||||
if(result)
|
||||
goto out;
|
||||
ctx->x509_store_setup = TRUE;
|
||||
}
|
||||
Curl_set_in_callback(data, true);
|
||||
result = (*data->set.ssl.fsslctx)(data, ctx->ssl_ctx,
|
||||
data->set.ssl.fsslctxp);
|
||||
Curl_set_in_callback(data, false);
|
||||
if(result) {
|
||||
failf(data, "error signaled by ssl ctx callback");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
result = CURLE_OK;
|
||||
|
||||
out:
|
||||
if(result && ctx->ssl_ctx) {
|
||||
SSL_CTX_free(ctx->ssl_ctx);
|
||||
ctx->ssl_ctx = NULL;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static CURLcode curl_ossl_set_client_cert(struct quic_tls_ctx *ctx,
|
||||
struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data)
|
||||
{
|
||||
SSL_CTX *ssl_ctx = ctx->ssl_ctx;
|
||||
const struct ssl_config_data *ssl_config;
|
||||
|
||||
ssl_config = Curl_ssl_cf_get_config(cf, data);
|
||||
DEBUGASSERT(ssl_config);
|
||||
|
||||
if(ssl_config->primary.clientcert ||
|
||||
ssl_config->primary.cert_blob ||
|
||||
ssl_config->cert_type) {
|
||||
return Curl_ossl_set_client_cert(
|
||||
data, ssl_ctx, ssl_config->primary.clientcert,
|
||||
ssl_config->primary.cert_blob, ssl_config->cert_type,
|
||||
ssl_config->key, ssl_config->key_blob,
|
||||
ssl_config->key_type, ssl_config->key_passwd);
|
||||
}
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
/** SSL callbacks ***/
|
||||
|
||||
static CURLcode curl_ossl_init_ssl(struct quic_tls_ctx *ctx,
|
||||
struct Curl_easy *data,
|
||||
struct ssl_peer *peer,
|
||||
const char *alpn, size_t alpn_len,
|
||||
void *user_data)
|
||||
{
|
||||
DEBUGASSERT(!ctx->ssl);
|
||||
ctx->ssl = SSL_new(ctx->ssl_ctx);
|
||||
|
||||
SSL_set_app_data(ctx->ssl, user_data);
|
||||
SSL_set_connect_state(ctx->ssl);
|
||||
#ifndef USE_OPENSSL_QUIC
|
||||
SSL_set_quic_use_legacy_codepoint(ctx->ssl, 0);
|
||||
#endif
|
||||
|
||||
if(alpn)
|
||||
SSL_set_alpn_protos(ctx->ssl, (const uint8_t *)alpn, (int)alpn_len);
|
||||
|
||||
if(peer->sni) {
|
||||
if(!SSL_set_tlsext_host_name(ctx->ssl, peer->sni)) {
|
||||
failf(data, "Failed set SNI");
|
||||
SSL_free(ctx->ssl);
|
||||
ctx->ssl = NULL;
|
||||
return CURLE_QUIC_CONNECT_ERROR;
|
||||
}
|
||||
}
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
#elif defined(USE_GNUTLS)
|
||||
static int keylog_callback(gnutls_session_t session, const char *label,
|
||||
const gnutls_datum_t *secret)
|
||||
{
|
||||
gnutls_datum_t crandom;
|
||||
gnutls_datum_t srandom;
|
||||
|
||||
gnutls_session_get_random(session, &crandom, &srandom);
|
||||
if(crandom.size != 32) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
Curl_tls_keylog_write(label, crandom.data, secret->data, secret->size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static CURLcode curl_gtls_init_ctx(struct quic_tls_ctx *ctx,
|
||||
struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
struct ssl_peer *peer,
|
||||
const char *alpn, size_t alpn_len,
|
||||
Curl_vquic_tls_ctx_setup *ctx_setup,
|
||||
void *user_data)
|
||||
{
|
||||
struct ssl_primary_config *conn_config;
|
||||
CURLcode result;
|
||||
gnutls_datum_t alpns[5];
|
||||
/* this will need some attention when HTTPS proxy over QUIC get fixed */
|
||||
long * const pverifyresult = &data->set.ssl.certverifyresult;
|
||||
int rc;
|
||||
|
||||
conn_config = Curl_ssl_cf_get_primary_config(cf);
|
||||
if(!conn_config)
|
||||
return CURLE_FAILED_INIT;
|
||||
|
||||
DEBUGASSERT(ctx->gtls == NULL);
|
||||
ctx->gtls = calloc(1, sizeof(*(ctx->gtls)));
|
||||
if(!ctx->gtls)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
result = gtls_client_init(data, conn_config, &data->set.ssl,
|
||||
peer, ctx->gtls, pverifyresult);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
gnutls_session_set_ptr(ctx->gtls->session, user_data);
|
||||
|
||||
if(ctx_setup) {
|
||||
result = ctx_setup(ctx, cf, data);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
|
||||
rc = gnutls_priority_set_direct(ctx->gtls->session, QUIC_PRIORITY, NULL);
|
||||
if(rc < 0) {
|
||||
CURL_TRC_CF(data, cf, "gnutls_priority_set_direct failed: %s\n",
|
||||
gnutls_strerror(rc));
|
||||
return CURLE_QUIC_CONNECT_ERROR;
|
||||
}
|
||||
|
||||
/* Open the file if a TLS or QUIC backend has not done this before. */
|
||||
Curl_tls_keylog_open();
|
||||
if(Curl_tls_keylog_enabled()) {
|
||||
gnutls_session_set_keylog_function(ctx->gtls->session, keylog_callback);
|
||||
}
|
||||
|
||||
/* convert the ALPN string from our arguments to a list of strings
|
||||
* that gnutls wants and will convert internally back to this very
|
||||
* string for sending to the server. nice. */
|
||||
if(alpn) {
|
||||
size_t i, alen = alpn_len;
|
||||
unsigned char *s = (unsigned char *)alpn;
|
||||
unsigned char slen;
|
||||
for(i = 0; (i < ARRAYSIZE(alpns)) && alen; ++i) {
|
||||
slen = s[0];
|
||||
if(slen >= alen)
|
||||
return CURLE_FAILED_INIT;
|
||||
alpns[i].data = s + 1;
|
||||
alpns[i].size = slen;
|
||||
s += slen + 1;
|
||||
alen -= (size_t)slen + 1;
|
||||
}
|
||||
if(alen) /* not all alpn chars used, wrong format or too many */
|
||||
return CURLE_FAILED_INIT;
|
||||
if(i) {
|
||||
gnutls_alpn_set_protocols(ctx->gtls->session,
|
||||
alpns, (unsigned int)i,
|
||||
GNUTLS_ALPN_MANDATORY);
|
||||
}
|
||||
}
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
#elif defined(USE_WOLFSSL)
|
||||
|
||||
#if defined(HAVE_SECRET_CALLBACK)
|
||||
static void keylog_callback(const WOLFSSL *ssl, const char *line)
|
||||
|
@ -341,10 +76,11 @@ static void keylog_callback(const WOLFSSL *ssl, const char *line)
|
|||
}
|
||||
#endif
|
||||
|
||||
static CURLcode curl_wssl_init_ctx(struct quic_tls_ctx *ctx,
|
||||
static CURLcode curl_wssl_init_ctx(struct curl_tls_ctx *ctx,
|
||||
struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
Curl_vquic_tls_ctx_setup *ctx_setup)
|
||||
Curl_vquic_tls_ctx_setup *cb_setup,
|
||||
void *cb_user_data)
|
||||
{
|
||||
struct ssl_primary_config *conn_config;
|
||||
CURLcode result = CURLE_FAILED_INIT;
|
||||
|
@ -361,8 +97,8 @@ static CURLcode curl_wssl_init_ctx(struct quic_tls_ctx *ctx,
|
|||
goto out;
|
||||
}
|
||||
|
||||
if(ctx_setup) {
|
||||
result = ctx_setup(ctx, cf, data);
|
||||
if(cb_setup) {
|
||||
result = cb_setup(cf, data, cb_user_data);
|
||||
if(result)
|
||||
goto out;
|
||||
}
|
||||
|
@ -458,7 +194,7 @@ out:
|
|||
|
||||
/** SSL callbacks ***/
|
||||
|
||||
static CURLcode curl_wssl_init_ssl(struct quic_tls_ctx *ctx,
|
||||
static CURLcode curl_wssl_init_ssl(struct curl_tls_ctx *ctx,
|
||||
struct Curl_easy *data,
|
||||
struct ssl_peer *peer,
|
||||
const char *alpn, size_t alpn_len,
|
||||
|
@ -486,57 +222,50 @@ static CURLcode curl_wssl_init_ssl(struct quic_tls_ctx *ctx,
|
|||
}
|
||||
#endif /* defined(USE_WOLFSSL) */
|
||||
|
||||
CURLcode Curl_vquic_tls_init(struct quic_tls_ctx *ctx,
|
||||
CURLcode Curl_vquic_tls_init(struct curl_tls_ctx *ctx,
|
||||
struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
struct ssl_peer *peer,
|
||||
const char *alpn, size_t alpn_len,
|
||||
Curl_vquic_tls_ctx_setup *ctx_setup,
|
||||
void *user_data)
|
||||
Curl_vquic_tls_ctx_setup *cb_setup,
|
||||
void *cb_user_data, void *ssl_user_data)
|
||||
{
|
||||
CURLcode result;
|
||||
|
||||
#ifdef USE_OPENSSL
|
||||
result = curl_ossl_init_ctx(ctx, cf, data, ctx_setup);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
result = curl_ossl_set_client_cert(ctx, cf, data);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
return curl_ossl_init_ssl(ctx, data, peer, alpn, alpn_len, user_data);
|
||||
(void)result;
|
||||
return Curl_ossl_ctx_init(&ctx->ossl, cf, data, peer, TRNSPRT_QUIC,
|
||||
(const unsigned char *)alpn, alpn_len,
|
||||
cb_setup, cb_user_data, NULL, ssl_user_data);
|
||||
#elif defined(USE_GNUTLS)
|
||||
(void)result;
|
||||
return curl_gtls_init_ctx(ctx, cf, data, peer, alpn, alpn_len,
|
||||
ctx_setup, user_data);
|
||||
return Curl_gtls_ctx_init(&ctx->gtls, cf, data, peer,
|
||||
(const unsigned char *)alpn, alpn_len,
|
||||
cb_setup, cb_user_data, ssl_user_data);
|
||||
#elif defined(USE_WOLFSSL)
|
||||
result = curl_wssl_init_ctx(ctx, cf, data, ctx_setup);
|
||||
result = curl_wssl_init_ctx(ctx, cf, data, cb_setup, cb_user_data);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
return curl_wssl_init_ssl(ctx, data, peer, alpn, alpn_len, user_data);
|
||||
return curl_wssl_init_ssl(ctx, data, peer, alpn, alpn_len, ssl_user_data);
|
||||
#else
|
||||
#error "no TLS lib in used, should not happen"
|
||||
return CURLE_FAILED_INIT;
|
||||
#endif
|
||||
}
|
||||
|
||||
void Curl_vquic_tls_cleanup(struct quic_tls_ctx *ctx)
|
||||
void Curl_vquic_tls_cleanup(struct curl_tls_ctx *ctx)
|
||||
{
|
||||
#ifdef USE_OPENSSL
|
||||
if(ctx->ssl)
|
||||
SSL_free(ctx->ssl);
|
||||
if(ctx->ssl_ctx)
|
||||
SSL_CTX_free(ctx->ssl_ctx);
|
||||
if(ctx->ossl.ssl)
|
||||
SSL_free(ctx->ossl.ssl);
|
||||
if(ctx->ossl.ssl_ctx)
|
||||
SSL_CTX_free(ctx->ossl.ssl_ctx);
|
||||
#elif defined(USE_GNUTLS)
|
||||
if(ctx->gtls) {
|
||||
if(ctx->gtls->cred)
|
||||
gnutls_certificate_free_credentials(ctx->gtls->cred);
|
||||
if(ctx->gtls->session)
|
||||
gnutls_deinit(ctx->gtls->session);
|
||||
free(ctx->gtls);
|
||||
}
|
||||
if(ctx->gtls.cred)
|
||||
gnutls_certificate_free_credentials(ctx->gtls.cred);
|
||||
if(ctx->gtls.session)
|
||||
gnutls_deinit(ctx->gtls.session);
|
||||
#elif defined(USE_WOLFSSL)
|
||||
if(ctx->ssl)
|
||||
wolfSSL_free(ctx->ssl);
|
||||
|
@ -546,16 +275,16 @@ void Curl_vquic_tls_cleanup(struct quic_tls_ctx *ctx)
|
|||
memset(ctx, 0, sizeof(*ctx));
|
||||
}
|
||||
|
||||
CURLcode Curl_vquic_tls_before_recv(struct quic_tls_ctx *ctx,
|
||||
CURLcode Curl_vquic_tls_before_recv(struct curl_tls_ctx *ctx,
|
||||
struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data)
|
||||
{
|
||||
#ifdef USE_OPENSSL
|
||||
if(!ctx->x509_store_setup) {
|
||||
CURLcode result = Curl_ssl_setup_x509_store(cf, data, ctx->ssl_ctx);
|
||||
if(!ctx->ossl.x509_store_setup) {
|
||||
CURLcode result = Curl_ssl_setup_x509_store(cf, data, ctx->ossl.ssl_ctx);
|
||||
if(result)
|
||||
return result;
|
||||
ctx->x509_store_setup = TRUE;
|
||||
ctx->ossl.x509_store_setup = TRUE;
|
||||
}
|
||||
#else
|
||||
(void)ctx; (void)cf; (void)data;
|
||||
|
@ -563,7 +292,7 @@ CURLcode Curl_vquic_tls_before_recv(struct quic_tls_ctx *ctx,
|
|||
return CURLE_OK;
|
||||
}
|
||||
|
||||
CURLcode Curl_vquic_tls_verify_peer(struct quic_tls_ctx *ctx,
|
||||
CURLcode Curl_vquic_tls_verify_peer(struct curl_tls_ctx *ctx,
|
||||
struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
struct ssl_peer *peer)
|
||||
|
@ -575,36 +304,24 @@ CURLcode Curl_vquic_tls_verify_peer(struct quic_tls_ctx *ctx,
|
|||
if(!conn_config)
|
||||
return CURLE_FAILED_INIT;
|
||||
|
||||
if(conn_config->verifyhost) {
|
||||
#ifdef USE_OPENSSL
|
||||
X509 *server_cert;
|
||||
server_cert = SSL_get1_peer_certificate(ctx->ssl);
|
||||
if(!server_cert) {
|
||||
return CURLE_PEER_FAILED_VERIFICATION;
|
||||
}
|
||||
result = Curl_ossl_verifyhost(data, cf->conn, peer, server_cert);
|
||||
X509_free(server_cert);
|
||||
if(result)
|
||||
return result;
|
||||
(void)conn_config;
|
||||
result = Curl_oss_check_peer_cert(cf, data, &ctx->ossl, peer);
|
||||
#elif defined(USE_GNUTLS)
|
||||
result = Curl_gtls_verifyserver(data, ctx->gtls->session,
|
||||
if(conn_config->verifyhost) {
|
||||
result = Curl_gtls_verifyserver(data, ctx->gtls.session,
|
||||
conn_config, &data->set.ssl, peer,
|
||||
data->set.str[STRING_SSL_PINNEDPUBLICKEY]);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
#elif defined(USE_WOLFSSL)
|
||||
(void)data;
|
||||
if(conn_config->verifyhost) {
|
||||
if(!peer->sni ||
|
||||
wolfSSL_check_domain_name(ctx->ssl, peer->sni) == SSL_FAILURE)
|
||||
return CURLE_PEER_FAILED_VERIFICATION;
|
||||
#endif
|
||||
infof(data, "Verified certificate just fine");
|
||||
}
|
||||
else
|
||||
infof(data, "Skipped certificate verification");
|
||||
#ifdef USE_OPENSSL
|
||||
if(data->set.ssl.certinfo)
|
||||
/* asked to gather certificate info */
|
||||
(void)Curl_ossl_certchain(data, ctx->ssl);
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -26,21 +26,20 @@
|
|||
|
||||
#include "curl_setup.h"
|
||||
#include "bufq.h"
|
||||
#include "vtls/openssl.h"
|
||||
|
||||
#if defined(ENABLE_QUIC) && \
|
||||
(defined(USE_OPENSSL) || defined(USE_GNUTLS) || defined(USE_WOLFSSL))
|
||||
|
||||
struct quic_tls_ctx {
|
||||
struct curl_tls_ctx {
|
||||
#ifdef USE_OPENSSL
|
||||
SSL_CTX *ssl_ctx;
|
||||
SSL *ssl;
|
||||
struct ossl_ctx ossl;
|
||||
#elif defined(USE_GNUTLS)
|
||||
struct gtls_instance *gtls;
|
||||
struct gtls_ctx gtls;
|
||||
#elif defined(USE_WOLFSSL)
|
||||
WOLFSSL_CTX *ssl_ctx;
|
||||
WOLFSSL *ssl;
|
||||
#endif
|
||||
BIT(x509_store_setup); /* if x509 store has been set up */
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -50,9 +49,9 @@ struct quic_tls_ctx {
|
|||
* - openssl/wolfssl: SSL_CTX* has just been created
|
||||
* - gnutls: gtls_client_init() has run
|
||||
*/
|
||||
typedef CURLcode Curl_vquic_tls_ctx_setup(struct quic_tls_ctx *ctx,
|
||||
struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data);
|
||||
typedef CURLcode Curl_vquic_tls_ctx_setup(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
void *cb_user_data);
|
||||
|
||||
/**
|
||||
* Initialize the QUIC TLS instances based of the SSL configurations
|
||||
|
@ -64,23 +63,25 @@ typedef CURLcode Curl_vquic_tls_ctx_setup(struct quic_tls_ctx *ctx,
|
|||
* @param alpn the ALPN string in protocol format ((len+bytes+)+),
|
||||
* may be NULL
|
||||
* @param alpn_len the overall number of bytes in `alpn`
|
||||
* @param ctx_setup optional callback for very early TLS config
|
||||
* @param user_data optional pointer to set in TLS application context
|
||||
* @param cb_setup optional callback for very early TLS config
|
||||
± @param cb_user_data user_data param for callback
|
||||
* @param ssl_user_data optional pointer to set in TLS application context
|
||||
*/
|
||||
CURLcode Curl_vquic_tls_init(struct quic_tls_ctx *ctx,
|
||||
CURLcode Curl_vquic_tls_init(struct curl_tls_ctx *ctx,
|
||||
struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
struct ssl_peer *peer,
|
||||
const char *alpn, size_t alpn_len,
|
||||
Curl_vquic_tls_ctx_setup *ctx_setup,
|
||||
void *user_data);
|
||||
Curl_vquic_tls_ctx_setup *cb_setup,
|
||||
void *cb_user_data,
|
||||
void *ssl_user_data);
|
||||
|
||||
/**
|
||||
* Cleanup all data that has been initialized.
|
||||
*/
|
||||
void Curl_vquic_tls_cleanup(struct quic_tls_ctx *ctx);
|
||||
void Curl_vquic_tls_cleanup(struct curl_tls_ctx *ctx);
|
||||
|
||||
CURLcode Curl_vquic_tls_before_recv(struct quic_tls_ctx *ctx,
|
||||
CURLcode Curl_vquic_tls_before_recv(struct curl_tls_ctx *ctx,
|
||||
struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data);
|
||||
|
||||
|
@ -88,7 +89,7 @@ CURLcode Curl_vquic_tls_before_recv(struct quic_tls_ctx *ctx,
|
|||
* After the QUIC basic handshake has been, verify that the peer
|
||||
* (and its certificate) fulfill our requirements.
|
||||
*/
|
||||
CURLcode Curl_vquic_tls_verify_peer(struct quic_tls_ctx *ctx,
|
||||
CURLcode Curl_vquic_tls_verify_peer(struct curl_tls_ctx *ctx,
|
||||
struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
struct ssl_peer *peer);
|
||||
|
|
|
@ -686,7 +686,7 @@ static CURLcode bearssl_connect_step1(struct Curl_cfilter *cf,
|
|||
|
||||
CURL_TRC_CF(data, cf, "connect_step1, check session cache");
|
||||
Curl_ssl_sessionid_lock(data);
|
||||
if(!Curl_ssl_getsessionid(cf, data, &session, NULL)) {
|
||||
if(!Curl_ssl_getsessionid(cf, data, &connssl->peer, &session, NULL)) {
|
||||
br_ssl_engine_set_session_parameters(&backend->ctx.eng, session);
|
||||
session_set = 1;
|
||||
infof(data, "BearSSL: reusing session ID");
|
||||
|
@ -905,10 +905,11 @@ static CURLcode bearssl_connect_step3(struct Curl_cfilter *cf,
|
|||
return CURLE_OUT_OF_MEMORY;
|
||||
br_ssl_engine_get_session_parameters(&backend->ctx.eng, session);
|
||||
Curl_ssl_sessionid_lock(data);
|
||||
incache = !(Curl_ssl_getsessionid(cf, data, &oldsession, NULL));
|
||||
incache = !(Curl_ssl_getsessionid(cf, data, &connssl->peer,
|
||||
&oldsession, NULL));
|
||||
if(incache)
|
||||
Curl_ssl_delsessionid(data, oldsession);
|
||||
ret = Curl_ssl_addsessionid(cf, data, session, 0, &added);
|
||||
ret = Curl_ssl_addsessionid(cf, data, &connssl->peer, session, 0, &added);
|
||||
Curl_ssl_sessionid_unlock(data);
|
||||
if(!added)
|
||||
free(session);
|
||||
|
|
171
lib/vtls/gtls.c
171
lib/vtls/gtls.c
|
@ -43,6 +43,7 @@
|
|||
#include "urldata.h"
|
||||
#include "sendf.h"
|
||||
#include "inet_pton.h"
|
||||
#include "keylog.h"
|
||||
#include "gtls.h"
|
||||
#include "vtls.h"
|
||||
#include "vtls_int.h"
|
||||
|
@ -59,6 +60,16 @@
|
|||
/* The last #include file should be: */
|
||||
#include "memdebug.h"
|
||||
|
||||
#ifndef ARRAYSIZE
|
||||
#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
|
||||
#endif
|
||||
|
||||
#define QUIC_PRIORITY \
|
||||
"NORMAL:-VERS-ALL:+VERS-TLS1.3:-CIPHER-ALL:+AES-128-GCM:+AES-256-GCM:" \
|
||||
"+CHACHA20-POLY1305:+AES-128-CCM:-GROUP-ALL:+GROUP-SECP256R1:" \
|
||||
"+GROUP-X25519:+GROUP-SECP384R1:+GROUP-SECP521R1:" \
|
||||
"%DISABLE_TLS13_COMPAT_MODE"
|
||||
|
||||
/* Enable GnuTLS debugging by defining GTLSDEBUG */
|
||||
/*#define GTLSDEBUG */
|
||||
|
||||
|
@ -77,7 +88,7 @@ static bool gtls_inited = FALSE;
|
|||
# include <gnutls/ocsp.h>
|
||||
|
||||
struct gtls_ssl_backend_data {
|
||||
struct gtls_instance gtls;
|
||||
struct gtls_ctx gtls;
|
||||
};
|
||||
|
||||
static ssize_t gtls_push(void *s, const void *buf, size_t blen)
|
||||
|
@ -330,6 +341,7 @@ static gnutls_x509_crt_fmt_t do_file_type(const char *type)
|
|||
|
||||
static CURLcode
|
||||
set_ssl_version_min_max(struct Curl_easy *data,
|
||||
struct ssl_peer *peer,
|
||||
struct ssl_primary_config *conn_config,
|
||||
const char **prioritylist,
|
||||
const char *tls13support)
|
||||
|
@ -337,6 +349,16 @@ set_ssl_version_min_max(struct Curl_easy *data,
|
|||
long ssl_version = conn_config->version;
|
||||
long ssl_version_max = conn_config->version_max;
|
||||
|
||||
if(peer->transport == TRNSPRT_QUIC) {
|
||||
if((ssl_version != CURL_SSLVERSION_DEFAULT) &&
|
||||
(ssl_version < CURL_SSLVERSION_TLSv1_3)) {
|
||||
failf(data, "QUIC needs at least TLS version 1.3");
|
||||
return CURLE_SSL_CONNECT_ERROR;
|
||||
}
|
||||
*prioritylist = QUIC_PRIORITY;
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
if((ssl_version == CURL_SSLVERSION_DEFAULT) ||
|
||||
(ssl_version == CURL_SSLVERSION_TLSv1))
|
||||
ssl_version = CURL_SSLVERSION_TLSv1_0;
|
||||
|
@ -401,12 +423,12 @@ set_ssl_version_min_max(struct Curl_easy *data,
|
|||
return CURLE_SSL_CONNECT_ERROR;
|
||||
}
|
||||
|
||||
CURLcode gtls_client_init(struct Curl_easy *data,
|
||||
struct ssl_primary_config *config,
|
||||
struct ssl_config_data *ssl_config,
|
||||
struct ssl_peer *peer,
|
||||
struct gtls_instance *gtls,
|
||||
long *pverifyresult)
|
||||
static CURLcode gtls_client_init(struct Curl_easy *data,
|
||||
struct ssl_primary_config *config,
|
||||
struct ssl_config_data *ssl_config,
|
||||
struct ssl_peer *peer,
|
||||
struct gtls_ctx *gtls,
|
||||
long *pverifyresult)
|
||||
{
|
||||
unsigned int init_flags;
|
||||
int rc;
|
||||
|
@ -578,7 +600,8 @@ CURLcode gtls_client_init(struct Curl_easy *data,
|
|||
}
|
||||
|
||||
/* At this point we know we have a supported TLS version, so set it */
|
||||
result = set_ssl_version_min_max(data, config, &prioritylist, tls13support);
|
||||
result = set_ssl_version_min_max(data, peer,
|
||||
config, &prioritylist, tls13support);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
|
@ -677,46 +700,81 @@ CURLcode gtls_client_init(struct Curl_easy *data,
|
|||
return CURLE_OK;
|
||||
}
|
||||
|
||||
static CURLcode
|
||||
gtls_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
|
||||
static int keylog_callback(gnutls_session_t session, const char *label,
|
||||
const gnutls_datum_t *secret)
|
||||
{
|
||||
gnutls_datum_t crandom;
|
||||
gnutls_datum_t srandom;
|
||||
|
||||
gnutls_session_get_random(session, &crandom, &srandom);
|
||||
if(crandom.size != 32) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
Curl_tls_keylog_write(label, crandom.data, secret->data, secret->size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
CURLcode Curl_gtls_ctx_init(struct gtls_ctx *gctx,
|
||||
struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
struct ssl_peer *peer,
|
||||
const unsigned char *alpn, size_t alpn_len,
|
||||
Curl_gtls_ctx_setup_cb *cb_setup,
|
||||
void *cb_user_data,
|
||||
void *ssl_user_data)
|
||||
{
|
||||
struct ssl_connect_data *connssl = cf->ctx;
|
||||
struct gtls_ssl_backend_data *backend =
|
||||
(struct gtls_ssl_backend_data *)connssl->backend;
|
||||
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);
|
||||
long * const pverifyresult = &ssl_config->certverifyresult;
|
||||
CURLcode result;
|
||||
|
||||
DEBUGASSERT(backend);
|
||||
DEBUGASSERT(gctx);
|
||||
|
||||
if(connssl->state == ssl_connection_complete)
|
||||
/* to make us tolerant against being called more than once for the
|
||||
same connection */
|
||||
return CURLE_OK;
|
||||
|
||||
result = gtls_client_init(data, conn_config, ssl_config,
|
||||
&connssl->peer,
|
||||
&backend->gtls, pverifyresult);
|
||||
result = gtls_client_init(data, conn_config, ssl_config, peer,
|
||||
gctx, pverifyresult);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
if(connssl->alpn) {
|
||||
struct alpn_proto_buf proto;
|
||||
gnutls_datum_t alpn[ALPN_ENTRIES_MAX];
|
||||
size_t i;
|
||||
gnutls_session_set_ptr(gctx->session, ssl_user_data);
|
||||
|
||||
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]);
|
||||
if(cb_setup) {
|
||||
result = cb_setup(cf, data, cb_user_data);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Open the file if a TLS or QUIC backend has not done this before. */
|
||||
Curl_tls_keylog_open();
|
||||
if(Curl_tls_keylog_enabled()) {
|
||||
gnutls_session_set_keylog_function(gctx->session, keylog_callback);
|
||||
}
|
||||
|
||||
/* convert the ALPN string from our arguments to a list of strings
|
||||
* that gnutls wants and will convert internally back to this very
|
||||
* string for sending to the server. nice. */
|
||||
if(alpn) {
|
||||
gnutls_datum_t alpns[5];
|
||||
size_t i, alen = alpn_len;
|
||||
unsigned char *s = (unsigned char *)alpn;
|
||||
unsigned char slen;
|
||||
for(i = 0; (i < ARRAYSIZE(alpns)) && alen; ++i) {
|
||||
slen = s[0];
|
||||
if(slen >= alen)
|
||||
return CURLE_FAILED_INIT;
|
||||
alpns[i].data = s + 1;
|
||||
alpns[i].size = slen;
|
||||
s += slen + 1;
|
||||
alen -= (size_t)slen + 1;
|
||||
}
|
||||
if(gnutls_alpn_set_protocols(backend->gtls.session, alpn,
|
||||
(unsigned)connssl->alpn->count, 0)) {
|
||||
if(alen) /* not all alpn chars used, wrong format or too many */
|
||||
return CURLE_FAILED_INIT;
|
||||
if(i && gnutls_alpn_set_protocols(gctx->session,
|
||||
alpns, (unsigned int)i,
|
||||
GNUTLS_ALPN_MANDATORY)) {
|
||||
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
|
||||
|
@ -726,16 +784,49 @@ gtls_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
|
|||
size_t ssl_idsize;
|
||||
|
||||
Curl_ssl_sessionid_lock(data);
|
||||
if(!Curl_ssl_getsessionid(cf, data, &ssl_sessionid, &ssl_idsize)) {
|
||||
if(!Curl_ssl_getsessionid(cf, data, peer, &ssl_sessionid, &ssl_idsize)) {
|
||||
/* we got a session id, use it! */
|
||||
gnutls_session_set_data(backend->gtls.session,
|
||||
ssl_sessionid, ssl_idsize);
|
||||
gnutls_session_set_data(gctx->session, ssl_sessionid, ssl_idsize);
|
||||
|
||||
/* Informational message */
|
||||
infof(data, "SSL reusing session ID");
|
||||
}
|
||||
Curl_ssl_sessionid_unlock(data);
|
||||
}
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
static CURLcode
|
||||
gtls_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
|
||||
{
|
||||
struct ssl_connect_data *connssl = cf->ctx;
|
||||
struct gtls_ssl_backend_data *backend =
|
||||
(struct gtls_ssl_backend_data *)connssl->backend;
|
||||
struct alpn_proto_buf proto;
|
||||
CURLcode result;
|
||||
|
||||
DEBUGASSERT(backend);
|
||||
DEBUGASSERT(ssl_connect_1 == connssl->connecting_state);
|
||||
|
||||
if(connssl->state == ssl_connection_complete)
|
||||
/* to make us tolerant against being called more than once for the
|
||||
same connection */
|
||||
return CURLE_OK;
|
||||
|
||||
memset(&proto, 0, sizeof(proto));
|
||||
if(connssl->alpn) {
|
||||
result = Curl_alpn_to_proto_buf(&proto, connssl->alpn);
|
||||
if(result) {
|
||||
failf(data, "Error determining ALPN");
|
||||
return CURLE_SSL_CONNECT_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
result = Curl_gtls_ctx_init(&backend->gtls, cf, data, &connssl->peer,
|
||||
proto.data, proto.len, NULL, NULL, cf);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
|
||||
/* register callback functions and handle to send and receive data. */
|
||||
gnutls_transport_set_ptr(backend->gtls.session, cf);
|
||||
|
@ -1291,7 +1382,8 @@ static CURLcode gtls_verifyserver(struct Curl_cfilter *cf,
|
|||
gnutls_session_get_data(session, connect_sessionid, &connect_idsize);
|
||||
|
||||
Curl_ssl_sessionid_lock(data);
|
||||
incache = !(Curl_ssl_getsessionid(cf, data, &ssl_sessionid, NULL));
|
||||
incache = !(Curl_ssl_getsessionid(cf, data, &connssl->peer,
|
||||
&ssl_sessionid, NULL));
|
||||
if(incache) {
|
||||
/* there was one before in the cache, so instead of risking that the
|
||||
previous one was rejected, we just kill that and store the new */
|
||||
|
@ -1299,8 +1391,9 @@ static CURLcode gtls_verifyserver(struct Curl_cfilter *cf,
|
|||
}
|
||||
|
||||
/* store this session id */
|
||||
result = Curl_ssl_addsessionid(cf, data, connect_sessionid,
|
||||
connect_idsize, &added);
|
||||
result = Curl_ssl_addsessionid(cf, data, &connssl->peer,
|
||||
connect_sessionid, connect_idsize,
|
||||
&added);
|
||||
Curl_ssl_sessionid_unlock(data);
|
||||
if(!added)
|
||||
free(connect_sessionid);
|
||||
|
|
|
@ -45,7 +45,7 @@ struct ssl_primary_config;
|
|||
struct ssl_config_data;
|
||||
struct ssl_peer;
|
||||
|
||||
struct gtls_instance {
|
||||
struct gtls_ctx {
|
||||
gnutls_session_t session;
|
||||
gnutls_certificate_credentials_t cred;
|
||||
#ifdef USE_GNUTLS_SRP
|
||||
|
@ -53,13 +53,18 @@ struct gtls_instance {
|
|||
#endif
|
||||
};
|
||||
|
||||
CURLcode
|
||||
gtls_client_init(struct Curl_easy *data,
|
||||
struct ssl_primary_config *config,
|
||||
struct ssl_config_data *ssl_config,
|
||||
struct ssl_peer *peer,
|
||||
struct gtls_instance *gtls,
|
||||
long *pverifyresult);
|
||||
typedef CURLcode Curl_gtls_ctx_setup_cb(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
void *user_data);
|
||||
|
||||
CURLcode Curl_gtls_ctx_init(struct gtls_ctx *gctx,
|
||||
struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
struct ssl_peer *peer,
|
||||
const unsigned char *alpn, size_t alpn_len,
|
||||
Curl_gtls_ctx_setup_cb *cb_setup,
|
||||
void *cb_user_data,
|
||||
void *ssl_user_data);
|
||||
|
||||
CURLcode
|
||||
Curl_gtls_verifyserver(struct Curl_easy *data,
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "curl_setup.h"
|
||||
|
||||
#if defined(USE_OPENSSL) || \
|
||||
defined(USE_GNUTLS) || \
|
||||
defined(USE_WOLFSSL) || \
|
||||
(defined(USE_NGTCP2) && defined(USE_NGHTTP3)) || \
|
||||
defined(USE_QUICHE)
|
||||
|
|
|
@ -589,7 +589,7 @@ mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
|
|||
}
|
||||
#endif
|
||||
|
||||
infof(data, "mbedTLS: Connecting to %s:%d", hostname, connssl->port);
|
||||
infof(data, "mbedTLS: Connecting to %s:%d", hostname, connssl->peer.port);
|
||||
|
||||
mbedtls_ssl_config_init(&backend->config);
|
||||
ret = mbedtls_ssl_config_defaults(&backend->config,
|
||||
|
@ -667,7 +667,7 @@ mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
|
|||
void *old_session = NULL;
|
||||
|
||||
Curl_ssl_sessionid_lock(data);
|
||||
if(!Curl_ssl_getsessionid(cf, data, &old_session, NULL)) {
|
||||
if(!Curl_ssl_getsessionid(cf, data, &connssl->peer, &old_session, NULL)) {
|
||||
ret = mbedtls_ssl_set_session(&backend->ssl, old_session);
|
||||
if(ret) {
|
||||
Curl_ssl_sessionid_unlock(data);
|
||||
|
@ -955,11 +955,12 @@ mbed_connect_step3(struct Curl_cfilter *cf, struct Curl_easy *data)
|
|||
|
||||
/* If there's already a matching session in the cache, delete it */
|
||||
Curl_ssl_sessionid_lock(data);
|
||||
if(!Curl_ssl_getsessionid(cf, data, &old_ssl_sessionid, NULL))
|
||||
if(!Curl_ssl_getsessionid(cf, data, &connssl->peer,
|
||||
&old_ssl_sessionid, NULL))
|
||||
Curl_ssl_delsessionid(data, old_ssl_sessionid);
|
||||
|
||||
retcode = Curl_ssl_addsessionid(cf, data, our_ssl_sessionid,
|
||||
0, &added);
|
||||
retcode = Curl_ssl_addsessionid(cf, data, &connssl->peer,
|
||||
our_ssl_sessionid, 0, &added);
|
||||
Curl_ssl_sessionid_unlock(data);
|
||||
if(!added) {
|
||||
mbedtls_ssl_session_free(our_ssl_sessionid);
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -36,6 +36,39 @@
|
|||
|
||||
#include "urldata.h"
|
||||
|
||||
/* Struct to hold a Curl OpenSSL instance */
|
||||
struct ossl_ctx {
|
||||
/* these ones requires specific SSL-types */
|
||||
SSL_CTX* ssl_ctx;
|
||||
SSL* ssl;
|
||||
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. */
|
||||
BIT(keylog_done);
|
||||
#endif
|
||||
BIT(x509_store_setup); /* x509 store has been set up */
|
||||
BIT(reused_session); /* session-ID was reused for this */
|
||||
};
|
||||
|
||||
typedef CURLcode Curl_ossl_ctx_setup_cb(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
void *user_data);
|
||||
|
||||
typedef int Curl_ossl_new_session_cb(SSL *ssl, SSL_SESSION *ssl_sessionid);
|
||||
|
||||
CURLcode Curl_ossl_ctx_init(struct ossl_ctx *octx,
|
||||
struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
struct ssl_peer *peer,
|
||||
int transport, /* TCP or QUIC */
|
||||
const unsigned char *alpn, size_t alpn_len,
|
||||
Curl_ossl_ctx_setup_cb *cb_setup,
|
||||
void *cb_user_data,
|
||||
Curl_ossl_new_session_cb *cb_new_session,
|
||||
void *ssl_user_data);
|
||||
|
||||
#if (OPENSSL_VERSION_NUMBER < 0x30000000L)
|
||||
#define SSL_get1_peer_certificate SSL_get_peer_certificate
|
||||
#endif
|
||||
|
@ -66,5 +99,23 @@ CURLcode Curl_ossl_ctx_configure(struct Curl_cfilter *cf,
|
|||
struct Curl_easy *data,
|
||||
SSL_CTX *ssl_ctx);
|
||||
|
||||
/*
|
||||
* Add a new session to the cache.
|
||||
*/
|
||||
CURLcode Curl_ossl_add_session(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
const struct ssl_peer *peer,
|
||||
SSL_SESSION *ssl_sessionid);
|
||||
|
||||
/*
|
||||
* Get the server cert, verify it and show it, etc., only call failf() if
|
||||
* ssl config verifypeer or -host is set. Otherwise all this is for
|
||||
* informational purposes only!
|
||||
*/
|
||||
CURLcode Curl_oss_check_peer_cert(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
struct ossl_ctx *octx,
|
||||
struct ssl_peer *peer);
|
||||
|
||||
#endif /* USE_OPENSSL */
|
||||
#endif /* HEADER_CURL_SSLUSE_H */
|
||||
|
|
|
@ -1071,7 +1071,7 @@ schannel_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
|
|||
DEBUGASSERT(backend);
|
||||
DEBUGF(infof(data,
|
||||
"schannel: SSL/TLS connection with %s port %d (step 1/3)",
|
||||
connssl->peer.hostname, connssl->port));
|
||||
connssl->peer.hostname, connssl->peer.port));
|
||||
|
||||
if(curlx_verify_windows_version(5, 1, 0, PLATFORM_WINNT,
|
||||
VERSION_LESS_THAN_EQUAL)) {
|
||||
|
@ -1129,7 +1129,8 @@ schannel_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
|
|||
/* check for an existing reusable credential handle */
|
||||
if(ssl_config->primary.sessionid) {
|
||||
Curl_ssl_sessionid_lock(data);
|
||||
if(!Curl_ssl_getsessionid(cf, data, (void **)&old_cred, NULL)) {
|
||||
if(!Curl_ssl_getsessionid(cf, data, &connssl->peer,
|
||||
(void **)&old_cred, NULL)) {
|
||||
backend->cred = old_cred;
|
||||
DEBUGF(infof(data, "schannel: reusing existing credential handle"));
|
||||
|
||||
|
@ -1335,7 +1336,7 @@ schannel_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data)
|
|||
|
||||
DEBUGF(infof(data,
|
||||
"schannel: SSL/TLS connection with %s port %d (step 2/3)",
|
||||
connssl->peer.hostname, connssl->port));
|
||||
connssl->peer.hostname, connssl->peer.port));
|
||||
|
||||
if(!backend->cred || !backend->ctxt)
|
||||
return CURLE_SSL_CONNECT_ERROR;
|
||||
|
@ -1693,7 +1694,7 @@ schannel_connect_step3(struct Curl_cfilter *cf, struct Curl_easy *data)
|
|||
|
||||
DEBUGF(infof(data,
|
||||
"schannel: SSL/TLS connection with %s port %d (step 3/3)",
|
||||
connssl->peer.hostname, connssl->port));
|
||||
connssl->peer.hostname, connssl->peer.port));
|
||||
|
||||
if(!backend->cred)
|
||||
return CURLE_SSL_CONNECT_ERROR;
|
||||
|
@ -1755,7 +1756,8 @@ schannel_connect_step3(struct Curl_cfilter *cf, struct Curl_easy *data)
|
|||
struct Curl_schannel_cred *old_cred = NULL;
|
||||
|
||||
Curl_ssl_sessionid_lock(data);
|
||||
incache = !(Curl_ssl_getsessionid(cf, data, (void **)&old_cred, NULL));
|
||||
incache = !(Curl_ssl_getsessionid(cf, data, &connssl->peer,
|
||||
(void **)&old_cred, NULL));
|
||||
if(incache) {
|
||||
if(old_cred != backend->cred) {
|
||||
DEBUGF(infof(data,
|
||||
|
@ -1766,7 +1768,7 @@ schannel_connect_step3(struct Curl_cfilter *cf, struct Curl_easy *data)
|
|||
}
|
||||
}
|
||||
if(!incache) {
|
||||
result = Curl_ssl_addsessionid(cf, data, backend->cred,
|
||||
result = Curl_ssl_addsessionid(cf, data, &connssl->peer, backend->cred,
|
||||
sizeof(struct Curl_schannel_cred),
|
||||
&added);
|
||||
if(result) {
|
||||
|
@ -2493,7 +2495,7 @@ static int schannel_shutdown(struct Curl_cfilter *cf,
|
|||
|
||||
if(backend->ctxt) {
|
||||
infof(data, "schannel: shutting down SSL/TLS connection with %s port %d",
|
||||
connssl->peer.hostname, connssl->port);
|
||||
connssl->peer.hostname, connssl->peer.port);
|
||||
}
|
||||
|
||||
if(backend->cred && backend->ctxt) {
|
||||
|
|
|
@ -2047,8 +2047,8 @@ static CURLcode sectransp_connect_step1(struct Curl_cfilter *cf,
|
|||
size_t ssl_sessionid_len;
|
||||
|
||||
Curl_ssl_sessionid_lock(data);
|
||||
if(!Curl_ssl_getsessionid(cf, data, (void **)&ssl_sessionid,
|
||||
&ssl_sessionid_len)) {
|
||||
if(!Curl_ssl_getsessionid(cf, data, &connssl->peer,
|
||||
(void **)&ssl_sessionid, &ssl_sessionid_len)) {
|
||||
/* we got a session id, use it! */
|
||||
err = SSLSetPeerID(backend->ssl_ctx, ssl_sessionid, ssl_sessionid_len);
|
||||
Curl_ssl_sessionid_unlock(data);
|
||||
|
@ -2067,7 +2067,7 @@ static CURLcode sectransp_connect_step1(struct Curl_cfilter *cf,
|
|||
aprintf("%s:%d:%d:%s:%d",
|
||||
ssl_cafile ? ssl_cafile : "(blob memory)",
|
||||
verifypeer, conn_config->verifyhost, connssl->peer.hostname,
|
||||
connssl->port);
|
||||
connssl->peer.port);
|
||||
ssl_sessionid_len = strlen(ssl_sessionid);
|
||||
|
||||
err = SSLSetPeerID(backend->ssl_ctx, ssl_sessionid, ssl_sessionid_len);
|
||||
|
@ -2077,7 +2077,7 @@ static CURLcode sectransp_connect_step1(struct Curl_cfilter *cf,
|
|||
return CURLE_SSL_CONNECT_ERROR;
|
||||
}
|
||||
|
||||
result = Curl_ssl_addsessionid(cf, data, ssl_sessionid,
|
||||
result = Curl_ssl_addsessionid(cf, data, &connssl->peer, ssl_sessionid,
|
||||
ssl_sessionid_len, NULL);
|
||||
Curl_ssl_sessionid_unlock(data);
|
||||
if(result) {
|
||||
|
|
|
@ -534,10 +534,10 @@ void Curl_ssl_sessionid_unlock(struct Curl_easy *data)
|
|||
*/
|
||||
bool Curl_ssl_getsessionid(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
const struct ssl_peer *peer,
|
||||
void **ssl_sessionid,
|
||||
size_t *idsize) /* set 0 if unknown */
|
||||
{
|
||||
struct ssl_connect_data *connssl = cf->ctx;
|
||||
struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
|
||||
struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
|
||||
struct Curl_ssl_session *check;
|
||||
|
@ -567,14 +567,15 @@ bool Curl_ssl_getsessionid(struct Curl_cfilter *cf,
|
|||
if(!check->sessionid)
|
||||
/* not session ID means blank entry */
|
||||
continue;
|
||||
if(strcasecompare(connssl->peer.hostname, check->name) &&
|
||||
if(strcasecompare(peer->hostname, check->name) &&
|
||||
((!cf->conn->bits.conn_to_host && !check->conn_to_host) ||
|
||||
(cf->conn->bits.conn_to_host && check->conn_to_host &&
|
||||
strcasecompare(cf->conn->conn_to_host.name, check->conn_to_host))) &&
|
||||
((!cf->conn->bits.conn_to_port && check->conn_to_port == -1) ||
|
||||
(cf->conn->bits.conn_to_port && check->conn_to_port != -1 &&
|
||||
cf->conn->conn_to_port == check->conn_to_port)) &&
|
||||
(connssl->port == check->remote_port) &&
|
||||
(peer->port == check->remote_port) &&
|
||||
(peer->transport == check->transport) &&
|
||||
strcasecompare(cf->conn->handler->scheme, check->scheme) &&
|
||||
match_ssl_primary_config(data, conn_config, &check->ssl_config)) {
|
||||
/* yes, we have a session ID! */
|
||||
|
@ -591,8 +592,7 @@ bool Curl_ssl_getsessionid(struct Curl_cfilter *cf,
|
|||
DEBUGF(infof(data, "%s Session ID in cache for %s %s://%s:%d",
|
||||
no_match? "Didn't find": "Found",
|
||||
Curl_ssl_cf_is_proxy(cf) ? "proxy" : "host",
|
||||
cf->conn->handler->scheme, connssl->peer.hostname,
|
||||
connssl->port));
|
||||
cf->conn->handler->scheme, peer->hostname, peer->port));
|
||||
return no_match;
|
||||
}
|
||||
|
||||
|
@ -642,11 +642,11 @@ void Curl_ssl_delsessionid(struct Curl_easy *data, void *ssl_sessionid)
|
|||
*/
|
||||
CURLcode Curl_ssl_addsessionid(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
const struct ssl_peer *peer,
|
||||
void *ssl_sessionid,
|
||||
size_t idsize,
|
||||
bool *added)
|
||||
{
|
||||
struct ssl_connect_data *connssl = cf->ctx;
|
||||
struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
|
||||
struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
|
||||
size_t i;
|
||||
|
@ -668,7 +668,7 @@ CURLcode Curl_ssl_addsessionid(struct Curl_cfilter *cf,
|
|||
(void)ssl_config;
|
||||
DEBUGASSERT(ssl_config->primary.sessionid);
|
||||
|
||||
clone_host = strdup(connssl->peer.hostname);
|
||||
clone_host = strdup(peer->hostname);
|
||||
if(!clone_host)
|
||||
return CURLE_OUT_OF_MEMORY; /* bail out */
|
||||
|
||||
|
@ -723,8 +723,9 @@ CURLcode Curl_ssl_addsessionid(struct Curl_cfilter *cf,
|
|||
store->conn_to_host = clone_conn_to_host; /* clone connect to host name */
|
||||
store->conn_to_port = conn_to_port; /* connect to port number */
|
||||
/* port number */
|
||||
store->remote_port = connssl->port;
|
||||
store->remote_port = peer->port;
|
||||
store->scheme = cf->conn->handler->scheme;
|
||||
store->transport = peer->transport;
|
||||
|
||||
if(!clone_ssl_primary_config(conn_config, &store->ssl_config)) {
|
||||
Curl_free_primary_ssl_config(&store->ssl_config);
|
||||
|
@ -1549,9 +1550,9 @@ static ssl_peer_type get_peer_type(const char *hostname)
|
|||
return CURL_SSL_PEER_DNS;
|
||||
}
|
||||
|
||||
CURLcode Curl_ssl_peer_init(struct ssl_peer *peer, struct Curl_cfilter *cf)
|
||||
CURLcode Curl_ssl_peer_init(struct ssl_peer *peer, struct Curl_cfilter *cf,
|
||||
int transport)
|
||||
{
|
||||
struct ssl_connect_data *connssl = cf->ctx;
|
||||
const char *ehostname, *edispname;
|
||||
int eport;
|
||||
|
||||
|
@ -1614,7 +1615,8 @@ CURLcode Curl_ssl_peer_init(struct ssl_peer *peer, struct Curl_cfilter *cf)
|
|||
}
|
||||
|
||||
}
|
||||
connssl->port = eport;
|
||||
peer->port = eport;
|
||||
peer->transport = transport;
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
|
@ -1667,7 +1669,7 @@ static CURLcode ssl_cf_connect(struct Curl_cfilter *cf,
|
|||
goto out;
|
||||
|
||||
*done = FALSE;
|
||||
result = Curl_ssl_peer_init(&connssl->peer, cf);
|
||||
result = Curl_ssl_peer_init(&connssl->peer, cf, TRNSPRT_TCP);
|
||||
if(result)
|
||||
goto out;
|
||||
|
||||
|
@ -1857,7 +1859,7 @@ struct Curl_cftype Curl_cft_ssl = {
|
|||
|
||||
struct Curl_cftype Curl_cft_ssl_proxy = {
|
||||
"SSL-PROXY",
|
||||
CF_TYPE_SSL,
|
||||
CF_TYPE_SSL|CF_TYPE_PROXY,
|
||||
CURL_LOG_LVL_NONE,
|
||||
ssl_cf_destroy,
|
||||
ssl_cf_connect,
|
||||
|
@ -2033,12 +2035,7 @@ CURLcode Curl_ssl_cfilter_remove(struct Curl_easy *data,
|
|||
|
||||
bool Curl_ssl_cf_is_proxy(struct Curl_cfilter *cf)
|
||||
{
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
return (cf->cft == &Curl_cft_ssl_proxy);
|
||||
#else
|
||||
(void)cf;
|
||||
return FALSE;
|
||||
#endif
|
||||
return (cf->cft->flags & CF_TYPE_SSL) && (cf->cft->flags & CF_TYPE_PROXY);
|
||||
}
|
||||
|
||||
struct ssl_config_data *
|
||||
|
|
|
@ -107,7 +107,8 @@ void Curl_ssl_conn_config_update(struct Curl_easy *data, bool for_proxy);
|
|||
/**
|
||||
* Init SSL peer information for filter. Can be called repeatedly.
|
||||
*/
|
||||
CURLcode Curl_ssl_peer_init(struct ssl_peer *peer, struct Curl_cfilter *cf);
|
||||
CURLcode Curl_ssl_peer_init(struct ssl_peer *peer,
|
||||
struct Curl_cfilter *cf, int transport);
|
||||
/**
|
||||
* Free all allocated data and reset peer information.
|
||||
*/
|
||||
|
|
|
@ -73,9 +73,7 @@ struct ssl_connect_data {
|
|||
void *backend; /* vtls backend specific props */
|
||||
struct cf_call_data call_data; /* data handle used in current call */
|
||||
struct curltime handshake_done; /* time when handshake finished */
|
||||
int port; /* remote port at origin */
|
||||
BIT(use_alpn); /* if ALPN shall be used in handshake */
|
||||
BIT(reused_session); /* session-ID was reused for this */
|
||||
BIT(peer_closed); /* peer has closed connection */
|
||||
};
|
||||
|
||||
|
@ -181,6 +179,7 @@ bool Curl_ssl_cf_is_proxy(struct Curl_cfilter *cf);
|
|||
*/
|
||||
bool Curl_ssl_getsessionid(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
const struct ssl_peer *peer,
|
||||
void **ssl_sessionid,
|
||||
size_t *idsize); /* set 0 if unknown */
|
||||
/* add a new session ID
|
||||
|
@ -190,6 +189,7 @@ bool Curl_ssl_getsessionid(struct Curl_cfilter *cf,
|
|||
*/
|
||||
CURLcode Curl_ssl_addsessionid(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
const struct ssl_peer *peer,
|
||||
void *ssl_sessionid,
|
||||
size_t idsize,
|
||||
bool *added);
|
||||
|
|
|
@ -409,11 +409,11 @@ wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
|
|||
#if defined(WOLFSSL_ALLOW_TLSV10) && !defined(NO_OLD_TLS)
|
||||
req_method = TLSv1_client_method();
|
||||
use_sni(TRUE);
|
||||
break;
|
||||
#else
|
||||
failf(data, "wolfSSL does not support TLS 1.0");
|
||||
return CURLE_NOT_BUILT_IN;
|
||||
#endif
|
||||
break;
|
||||
case CURL_SSLVERSION_TLSv1_1:
|
||||
#ifndef NO_OLD_TLS
|
||||
req_method = TLSv1_1_client_method();
|
||||
|
@ -481,6 +481,7 @@ wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
|
|||
return CURLE_SSL_CONNECT_ERROR;
|
||||
}
|
||||
#endif
|
||||
FALLTHROUGH();
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -711,7 +712,8 @@ wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
|
|||
void *ssl_sessionid = NULL;
|
||||
|
||||
Curl_ssl_sessionid_lock(data);
|
||||
if(!Curl_ssl_getsessionid(cf, data, &ssl_sessionid, NULL)) {
|
||||
if(!Curl_ssl_getsessionid(cf, data, &connssl->peer,
|
||||
&ssl_sessionid, NULL)) {
|
||||
/* we got a session id, use it! */
|
||||
if(!SSL_set_session(backend->handle, ssl_sessionid)) {
|
||||
Curl_ssl_delsessionid(data, ssl_sessionid);
|
||||
|
@ -968,7 +970,8 @@ wolfssl_connect_step3(struct Curl_cfilter *cf, struct Curl_easy *data)
|
|||
|
||||
if(our_ssl_sessionid) {
|
||||
Curl_ssl_sessionid_lock(data);
|
||||
incache = !(Curl_ssl_getsessionid(cf, data, &old_ssl_sessionid, NULL));
|
||||
incache = !(Curl_ssl_getsessionid(cf, data, &connssl->peer,
|
||||
&old_ssl_sessionid, NULL));
|
||||
if(incache) {
|
||||
if(old_ssl_sessionid != our_ssl_sessionid) {
|
||||
infof(data, "old SSL session ID is stale, removing");
|
||||
|
@ -978,7 +981,8 @@ wolfssl_connect_step3(struct Curl_cfilter *cf, struct Curl_easy *data)
|
|||
}
|
||||
|
||||
if(!incache) {
|
||||
result = Curl_ssl_addsessionid(cf, data, our_ssl_sessionid, 0, NULL);
|
||||
result = Curl_ssl_addsessionid(cf, data, &connssl->peer,
|
||||
our_ssl_sessionid, 0, NULL);
|
||||
if(result) {
|
||||
Curl_ssl_sessionid_unlock(data);
|
||||
wolfSSL_SESSION_free(our_ssl_sessionid);
|
||||
|
|
|
@ -142,7 +142,8 @@ static size_t write_cb(char *ptr, size_t size, size_t nmemb, void *opaque)
|
|||
}
|
||||
|
||||
static void add_transfer(CURLM *multi, CURLSH *share,
|
||||
struct curl_slist *resolve, const char *url)
|
||||
struct curl_slist *resolve,
|
||||
const char *url, int http_version)
|
||||
{
|
||||
CURL *easy;
|
||||
CURLMcode mc;
|
||||
|
@ -159,7 +160,7 @@ static void add_transfer(CURLM *multi, CURLSH *share,
|
|||
curl_easy_setopt(easy, CURLOPT_NOSIGNAL, 1L);
|
||||
curl_easy_setopt(easy, CURLOPT_AUTOREFERER, 1L);
|
||||
curl_easy_setopt(easy, CURLOPT_FAILONERROR, 1L);
|
||||
curl_easy_setopt(easy, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
|
||||
curl_easy_setopt(easy, CURLOPT_HTTP_VERSION, http_version);
|
||||
curl_easy_setopt(easy, CURLOPT_WRITEFUNCTION, write_cb);
|
||||
curl_easy_setopt(easy, CURLOPT_WRITEDATA, NULL);
|
||||
curl_easy_setopt(easy, CURLOPT_HTTPGET, 1L);
|
||||
|
@ -190,13 +191,19 @@ int main(int argc, char *argv[])
|
|||
int msgs_in_queue;
|
||||
int add_more, waits, ongoing = 0;
|
||||
char *host, *port;
|
||||
int http_version = CURL_HTTP_VERSION_1_1;
|
||||
|
||||
if(argc != 2) {
|
||||
fprintf(stderr, "%s URL\n", argv[0]);
|
||||
if(argc != 3) {
|
||||
fprintf(stderr, "%s proto URL\n", argv[0]);
|
||||
exit(2);
|
||||
}
|
||||
|
||||
url = argv[1];
|
||||
if(!strcmp("h2", argv[1]))
|
||||
http_version = CURL_HTTP_VERSION_2;
|
||||
else if(!strcmp("h3", argv[1]))
|
||||
http_version = CURL_HTTP_VERSION_3ONLY;
|
||||
|
||||
url = argv[2];
|
||||
cu = curl_url();
|
||||
if(!cu) {
|
||||
fprintf(stderr, "out of memory\n");
|
||||
|
@ -234,7 +241,7 @@ int main(int argc, char *argv[])
|
|||
curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_SSL_SESSION);
|
||||
|
||||
|
||||
add_transfer(multi, share, &resolve, url);
|
||||
add_transfer(multi, share, &resolve, url, http_version);
|
||||
++ongoing;
|
||||
add_more = 6;
|
||||
waits = 3;
|
||||
|
@ -260,7 +267,7 @@ int main(int argc, char *argv[])
|
|||
}
|
||||
else {
|
||||
while(add_more) {
|
||||
add_transfer(multi, share, &resolve, url);
|
||||
add_transfer(multi, share, &resolve, url, http_version);
|
||||
++ongoing;
|
||||
--add_more;
|
||||
}
|
||||
|
|
|
@ -434,13 +434,14 @@ class TestDownload:
|
|||
assert r.exit_code == 0, f'{client.dump_logs()}'
|
||||
|
||||
# Special client that tests TLS session reuse in parallel transfers
|
||||
def test_02_26_session_shared_reuse(self, env: Env, httpd, repeat):
|
||||
curl = CurlClient(env=env)
|
||||
url = f'https://{env.domain1}:{env.https_port}/data-100k'
|
||||
# TODO: just uses a single connection for h2/h3. Not sure how to prevent that
|
||||
@pytest.mark.parametrize("proto", ['http/1.1', 'h2', 'h3'])
|
||||
def test_02_26_session_shared_reuse(self, env: Env, proto, httpd, nghttpx, repeat):
|
||||
url = f'https://{env.authority_for(env.domain1, proto)}/data-100k'
|
||||
client = LocalClient(name='tls-session-reuse', env=env)
|
||||
if not client.exists():
|
||||
pytest.skip(f'example client not built: {client.name}')
|
||||
r = client.run(args=[url])
|
||||
r = client.run(args=[proto, url])
|
||||
r.check_exit_code(0)
|
||||
|
||||
# test on paused transfers, based on issue #11982
|
||||
|
|
Загрузка…
Ссылка в новой задаче