mirror of
https://github.com/curl/curl.git
synced 2025-04-18 16:30:45 +08:00
bearssl: handshake fix, provide proper get_select_socks() implementation
- bring bearssl handshake times down from +200ms down to other TLS backends - vtls: improve generic get_select_socks() implementation - tests: provide Apache with a suitable ssl session cache Closes #11675
This commit is contained in:
parent
57e81ff3db
commit
1bccee76c8
@ -587,6 +587,7 @@ static CURLcode bearssl_connect_step1(struct Curl_cfilter *cf,
|
||||
const bool verifyhost = conn_config->verifyhost;
|
||||
CURLcode ret;
|
||||
unsigned version_min, version_max;
|
||||
int session_set = 0;
|
||||
#ifdef ENABLE_IPV6
|
||||
struct in6_addr addr;
|
||||
#else
|
||||
@ -594,6 +595,7 @@ static CURLcode bearssl_connect_step1(struct Curl_cfilter *cf,
|
||||
#endif
|
||||
|
||||
DEBUGASSERT(backend);
|
||||
CURL_TRC_CF(data, cf, "connect_step1");
|
||||
|
||||
switch(conn_config->version) {
|
||||
case CURL_SSLVERSION_SSLv2:
|
||||
@ -631,6 +633,7 @@ static CURLcode bearssl_connect_step1(struct Curl_cfilter *cf,
|
||||
source.data = ca_info_blob->data;
|
||||
source.len = ca_info_blob->len;
|
||||
|
||||
CURL_TRC_CF(data, cf, "connect_step1, load ca_info_blob");
|
||||
ret = load_cafile(&source, &backend->anchors, &backend->anchors_len);
|
||||
if(ret != CURLE_OK) {
|
||||
failf(data, "error importing CA certificate blob");
|
||||
@ -644,6 +647,7 @@ static CURLcode bearssl_connect_step1(struct Curl_cfilter *cf,
|
||||
source.data = ssl_cafile;
|
||||
source.len = 0;
|
||||
|
||||
CURL_TRC_CF(data, cf, "connect_step1, load cafile");
|
||||
ret = load_cafile(&source, &backend->anchors, &backend->anchors_len);
|
||||
if(ret != CURLE_OK) {
|
||||
failf(data, "error setting certificate verify locations."
|
||||
@ -663,6 +667,7 @@ static CURLcode bearssl_connect_step1(struct Curl_cfilter *cf,
|
||||
if(conn_config->cipher_list) {
|
||||
/* Override the ciphers as specified. For the default cipher list see the
|
||||
BearSSL source code of br_ssl_client_init_full() */
|
||||
CURL_TRC_CF(data, cf, "connect_step1, set ciphers");
|
||||
ret = bearssl_set_selected_ciphers(data, &backend->ctx.eng,
|
||||
conn_config->cipher_list);
|
||||
if(ret)
|
||||
@ -678,9 +683,11 @@ static CURLcode bearssl_connect_step1(struct Curl_cfilter *cf,
|
||||
if(ssl_config->primary.sessionid) {
|
||||
void *session;
|
||||
|
||||
CURL_TRC_CF(data, cf, "connect_step1, check session cache");
|
||||
Curl_ssl_sessionid_lock(data);
|
||||
if(!Curl_ssl_getsessionid(cf, data, &session, NULL)) {
|
||||
br_ssl_engine_set_session_parameters(&backend->ctx.eng, session);
|
||||
session_set = 1;
|
||||
infof(data, "BearSSL: re-using session ID");
|
||||
}
|
||||
Curl_ssl_sessionid_unlock(data);
|
||||
@ -718,6 +725,7 @@ static CURLcode bearssl_connect_step1(struct Curl_cfilter *cf,
|
||||
return CURLE_SSL_CONNECT_ERROR;
|
||||
}
|
||||
hostname = snihost;
|
||||
CURL_TRC_CF(data, cf, "connect_step1, SNI set");
|
||||
}
|
||||
|
||||
/* give application a chance to interfere with SSL set up. */
|
||||
@ -732,7 +740,7 @@ static CURLcode bearssl_connect_step1(struct Curl_cfilter *cf,
|
||||
}
|
||||
}
|
||||
|
||||
if(!br_ssl_client_reset(&backend->ctx, hostname, 1))
|
||||
if(!br_ssl_client_reset(&backend->ctx, hostname, session_set))
|
||||
return CURLE_FAILED_INIT;
|
||||
backend->active = TRUE;
|
||||
|
||||
@ -741,6 +749,28 @@ static CURLcode bearssl_connect_step1(struct Curl_cfilter *cf,
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
static int bearssl_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);
|
||||
|
||||
if(sock == CURL_SOCKET_BAD)
|
||||
return GETSOCK_BLANK;
|
||||
else {
|
||||
struct bearssl_ssl_backend_data *backend =
|
||||
(struct bearssl_ssl_backend_data *)connssl->backend;
|
||||
unsigned state = br_ssl_engine_current_state(&backend->ctx.eng);
|
||||
if(state & BR_SSL_SENDREC) {
|
||||
socks[0] = sock;
|
||||
return GETSOCK_WRITESOCK(0);
|
||||
}
|
||||
}
|
||||
socks[0] = sock;
|
||||
return GETSOCK_READSOCK(0);
|
||||
}
|
||||
|
||||
static CURLcode bearssl_run_until(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
unsigned target)
|
||||
@ -792,6 +822,7 @@ static CURLcode bearssl_run_until(struct Curl_cfilter *cf,
|
||||
if(state & BR_SSL_SENDREC) {
|
||||
buf = br_ssl_engine_sendrec_buf(&backend->ctx.eng, &len);
|
||||
ret = Curl_conn_cf_send(cf->next, data, (char *)buf, len, &result);
|
||||
CURL_TRC_CF(data, cf, "ssl_send(len=%zu) -> %zd, %d", len, ret, result);
|
||||
if(ret <= 0) {
|
||||
return result;
|
||||
}
|
||||
@ -800,6 +831,7 @@ static CURLcode bearssl_run_until(struct Curl_cfilter *cf,
|
||||
else if(state & BR_SSL_RECVREC) {
|
||||
buf = br_ssl_engine_recvrec_buf(&backend->ctx.eng, &len);
|
||||
ret = Curl_conn_cf_recv(cf->next, data, (char *)buf, len, &result);
|
||||
CURL_TRC_CF(data, cf, "ssl_recv(len=%zu) -> %zd, %d", len, ret, result);
|
||||
if(ret == 0) {
|
||||
failf(data, "SSL: EOF without close notify");
|
||||
return CURLE_READ_ERROR;
|
||||
@ -821,16 +853,26 @@ static CURLcode bearssl_connect_step2(struct Curl_cfilter *cf,
|
||||
CURLcode ret;
|
||||
|
||||
DEBUGASSERT(backend);
|
||||
CURL_TRC_CF(data, cf, "connect_step2");
|
||||
|
||||
ret = bearssl_run_until(cf, data, BR_SSL_SENDAPP | BR_SSL_RECVAPP);
|
||||
if(ret == CURLE_AGAIN)
|
||||
return CURLE_OK;
|
||||
if(ret == CURLE_OK) {
|
||||
unsigned int tver;
|
||||
if(br_ssl_engine_current_state(&backend->ctx.eng) == BR_SSL_CLOSED) {
|
||||
failf(data, "SSL: connection closed during handshake");
|
||||
return CURLE_SSL_CONNECT_ERROR;
|
||||
}
|
||||
connssl->connecting_state = ssl_connect_3;
|
||||
/* Informational message */
|
||||
tver = br_ssl_engine_get_version(&backend->ctx.eng);
|
||||
if(tver == 0x0303)
|
||||
infof(data, "SSL connection using TLSv1.2");
|
||||
else if(tver == 0x0304)
|
||||
infof(data, "SSL connection using TLSv1.3");
|
||||
else
|
||||
infof(data, "SSL connection using TLS 0x%x", tver);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@ -846,6 +888,7 @@ static CURLcode bearssl_connect_step3(struct Curl_cfilter *cf,
|
||||
|
||||
DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
|
||||
DEBUGASSERT(backend);
|
||||
CURL_TRC_CF(data, cf, "connect_step3");
|
||||
|
||||
if(connssl->alpn) {
|
||||
const char *proto;
|
||||
@ -954,8 +997,10 @@ static CURLcode bearssl_connect_common(struct Curl_cfilter *cf,
|
||||
timediff_t timeout_ms;
|
||||
int what;
|
||||
|
||||
CURL_TRC_CF(data, cf, "connect_common(blocking=%d)", !nonblocking);
|
||||
/* check if the connection has already been established */
|
||||
if(ssl_connection_complete == connssl->state) {
|
||||
CURL_TRC_CF(data, cf, "connect_common, connected");
|
||||
*done = TRUE;
|
||||
return CURLE_OK;
|
||||
}
|
||||
@ -987,8 +1032,10 @@ static CURLcode bearssl_connect_common(struct Curl_cfilter *cf,
|
||||
curl_socket_t readfd = ssl_connect_2_reading ==
|
||||
connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
|
||||
|
||||
CURL_TRC_CF(data, cf, "connect_common, check socket");
|
||||
what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
|
||||
nonblocking?0:timeout_ms);
|
||||
CURL_TRC_CF(data, cf, "connect_common, check socket -> %d", what);
|
||||
if(what < 0) {
|
||||
/* fatal error */
|
||||
failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
|
||||
@ -1163,7 +1210,7 @@ const struct Curl_ssl Curl_ssl_bearssl = {
|
||||
Curl_none_cert_status_request, /* cert_status_request */
|
||||
bearssl_connect, /* connect */
|
||||
bearssl_connect_nonblocking, /* connect_nonblocking */
|
||||
Curl_ssl_get_select_socks, /* getsock */
|
||||
bearssl_get_select_socks, /* getsock */
|
||||
bearssl_get_internals, /* get_internals */
|
||||
bearssl_close, /* close_one */
|
||||
Curl_none_close_all, /* close_all */
|
||||
|
@ -635,19 +635,16 @@ int Curl_ssl_get_select_socks(struct Curl_cfilter *cf, struct Curl_easy *data,
|
||||
struct ssl_connect_data *connssl = cf->ctx;
|
||||
curl_socket_t sock = Curl_conn_cf_get_socket(cf->next, data);
|
||||
|
||||
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);
|
||||
}
|
||||
if(sock == CURL_SOCKET_BAD)
|
||||
return GETSOCK_BLANK;
|
||||
|
||||
if(connssl->connecting_state == ssl_connect_2_writing) {
|
||||
/* we are only interested in writing */
|
||||
socks[0] = sock;
|
||||
return GETSOCK_WRITESOCK(0);
|
||||
}
|
||||
return GETSOCK_BLANK;
|
||||
socks[0] = sock;
|
||||
return GETSOCK_READSOCK(0);
|
||||
}
|
||||
|
||||
/* Selects an SSL crypto engine
|
||||
@ -1512,6 +1509,7 @@ static CURLcode ssl_cf_connect(struct Curl_cfilter *cf,
|
||||
}
|
||||
|
||||
CF_DATA_SAVE(save, cf, data);
|
||||
CURL_TRC_CF(data, cf, "cf_connect()");
|
||||
(void)connssl;
|
||||
DEBUGASSERT(data->conn);
|
||||
DEBUGASSERT(data->conn == cf->conn);
|
||||
@ -1541,6 +1539,7 @@ static CURLcode ssl_cf_connect(struct Curl_cfilter *cf,
|
||||
DEBUGASSERT(connssl->state == ssl_connection_complete);
|
||||
}
|
||||
out:
|
||||
CURL_TRC_CF(data, cf, "cf_connect() -> %d, done=%d", result, *done);
|
||||
CF_DATA_RESTORE(cf, save);
|
||||
return result;
|
||||
}
|
||||
@ -1601,12 +1600,17 @@ static int ssl_cf_get_select_socks(struct Curl_cfilter *cf,
|
||||
curl_socket_t *socks)
|
||||
{
|
||||
struct cf_call_data save;
|
||||
int result;
|
||||
int fds = GETSOCK_BLANK;
|
||||
|
||||
CF_DATA_SAVE(save, cf, data);
|
||||
result = Curl_ssl->get_select_socks(cf, data, socks);
|
||||
CF_DATA_RESTORE(cf, save);
|
||||
return result;
|
||||
if(!cf->next->connected) {
|
||||
fds = cf->next->cft->get_select_socks(cf->next, data, socks);
|
||||
}
|
||||
else if(!cf->connected) {
|
||||
CF_DATA_SAVE(save, cf, data);
|
||||
fds = Curl_ssl->get_select_socks(cf, data, socks);
|
||||
CF_DATA_RESTORE(cf, save);
|
||||
}
|
||||
return fds;
|
||||
}
|
||||
|
||||
static CURLcode ssl_cf_cntrl(struct Curl_cfilter *cf,
|
||||
|
@ -48,6 +48,7 @@ class Httpd:
|
||||
'authz_user', 'authz_core', 'authz_host',
|
||||
'auth_basic', 'auth_digest',
|
||||
'env', 'filter', 'headers', 'mime',
|
||||
'socache_shmcb',
|
||||
'rewrite', 'http2', 'ssl', 'proxy', 'proxy_http', 'proxy_connect',
|
||||
'mpm_event',
|
||||
]
|
||||
@ -251,6 +252,7 @@ class Httpd:
|
||||
f'Listen {self.env.proxy_port}',
|
||||
f'Listen {self.env.proxys_port}',
|
||||
f'TypesConfig "{self._conf_dir}/mime.types',
|
||||
f'SSLSessionCache "shmcb:ssl_gcache_data(32000)"',
|
||||
]
|
||||
if 'base' in self._extra_configs:
|
||||
conf.extend(self._extra_configs['base'])
|
||||
|
Loading…
x
Reference in New Issue
Block a user