← Commit list

065b149df0

Stefan Eissing
Stefan Eissing
2026-01-27
SUCCESS Duration: 304s

Subject

OpenSSL: check reuse of sessions for verify status

Binary

No binary (build failed)

Architecture & Compiler Flags

Architecture: x86_64-linux-gnu Compiler: gcc (Ubuntu 11.4.0-1ubuntu1~22.04.3) 11.4.0

—

Build Log

(log yok)

Commit Diff GitHub →

lib/vtls/gtls.c+0 -2
@@ -1572,8 +1572,6 @@ static CURLcode glts_apple_verify(struct Curl_cfilter *cf,
result = Curl_vtls_apple_verify(cf, data, peer, chain->num_certs,
gtls_chain_get_der, chain, NULL, 0);
*pverified = !result;
- if(*pverified)
- infof(data, " SSL certificate verified by Apple SecTrust.");
return result;
}
#endif /* USE_APPLE_SECTRUST */
lib/vtls/openssl.c+41 -23
@@ -3371,32 +3371,42 @@ ossl_init_session_and_alpns(struct ossl_ctx *octx,
sizeof(error_buffer)));
}
else {
- infof(data, "SSL reusing session with ALPN '%s'",
- scs->alpn ? scs->alpn : "-");
- octx->reused_session = TRUE;
+ if(conn_cfg->verifypeer &&
+ (SSL_get_verify_result(octx->ssl) != X509_V_OK)) {
+ /* Session was from unverified connection, cannot reuse here */
+ SSL_set_session(octx->ssl, NULL);
+ infof(data, "SSL session not peer verified, not reusing");
+ }
+ else {
+ infof(data, "SSL reusing session with ALPN '%s'",
+ scs->alpn ? scs->alpn : "-");
+ octx->reused_session = TRUE;
+ infof(data, "SSL verify result: %lx",
+ SSL_get_verify_result(octx->ssl));
#ifdef HAVE_OPENSSL_EARLYDATA
- if(ssl_config->earlydata && scs->alpn &&
- SSL_SESSION_get_max_early_data(ssl_session) &&
- !cf->conn->connect_only &&
- (SSL_version(octx->ssl) == TLS1_3_VERSION)) {
- bool do_early_data = FALSE;
- if(sess_reuse_cb) {
- result = sess_reuse_cb(cf, data, &alpns, scs, &do_early_data);
- if(result) {
- SSL_SESSION_free(ssl_session);
- return result;
+ if(ssl_config->earlydata && scs->alpn &&
+ SSL_SESSION_get_max_early_data(ssl_session) &&
+ !cf->conn->connect_only &&
+ (SSL_version(octx->ssl) == TLS1_3_VERSION)) {
+ bool do_early_data = FALSE;
+ if(sess_reuse_cb) {
+ result = sess_reuse_cb(cf, data, &alpns, scs, &do_early_data);
+ if(result) {
+ SSL_SESSION_free(ssl_session);
+ return result;
+ }
+ }
+ if(do_early_data) {
+ /* We only try the ALPN protocol the session used before,
+ * otherwise we might send early data for the wrong protocol */
+ Curl_alpn_restrict_to(&alpns, scs->alpn);
}
}
- if(do_early_data) {
- /* We only try the ALPN protocol the session used before,
- * otherwise we might send early data for the wrong protocol */
- Curl_alpn_restrict_to(&alpns, scs->alpn);
- }
- }
#else
- (void)ssl_config;
- (void)sess_reuse_cb;
+ (void)ssl_config;
+ (void)sess_reuse_cb;
#endif
+ }
}
SSL_SESSION_free(ssl_session);
}
@@ -4681,8 +4691,15 @@ static CURLcode ossl_apple_verify(struct Curl_cfilter *cf,
if(!chain.num_certs &&
(conn_config->verifypeer || conn_config->verifyhost)) {
- failf(data, "SSL: could not get peer certificate");
- result = CURLE_PEER_FAILED_VERIFICATION;
+ if(!octx->reused_session) {
+ failf(data, "SSL: could not get peer certificate chain");
+ result = CURLE_PEER_FAILED_VERIFICATION;
+ }
+ else {
+ /* when session was reused, there is no peer cert chain */
+ *pverified = FALSE;
+ return CURLE_OK;
+ }
}
else {
#ifdef HAVE_BORINGSSL_LIKE
@@ -4758,6 +4775,7 @@ CURLcode Curl_ossl_check_peer_cert(struct Curl_cfilter *cf,
ossl_verify = SSL_get_verify_result(octx->ssl);
ssl_config->certverifyresult = ossl_verify;
+ infof(data, "OpenSSL verify result: %lx", ossl_verify);
verified = (ossl_verify == X509_V_OK);
if(verified)
tests/http/test_02_download.py+14 -4
@@ -286,7 +286,8 @@ class TestDownload:
if not client.exists():
pytest.skip(f'example client not built: {client.name}')
r = client.run(args=[
- '-n', f'{count}', '-P', f'{pause_offset}', '-V', proto, url
+ '-n', f'{count}', '-P', f'{pause_offset}',
+ '-C', env.ca.cert_file, '-V', proto, url
])
r.check_exit_code(0)
srcfile = os.path.join(httpd.docs_dir, docname)
@@ -305,7 +306,8 @@ class TestDownload:
pytest.skip(f'example client not built: {client.name}')
r = client.run(args=[
'-n', f'{count}', '-m', f'{max_parallel}',
- '-P', f'{pause_offset}', '-V', proto, url
+ '-P', f'{pause_offset}', '-C', env.ca.cert_file,
+ '-V', proto, url
])
r.check_exit_code(0)
srcfile = os.path.join(httpd.docs_dir, docname)
@@ -329,6 +331,7 @@ class TestDownload:
pytest.skip(f'example client not built: {client.name}')
r = client.run(args=[
'-n', f'{count}', '-m', f'{max_parallel}', '-a',
+ '-C', env.ca.cert_file,
'-P', f'{pause_offset}', '-V', proto, url
])
r.check_exit_code(0)
@@ -354,6 +357,7 @@ class TestDownload:
pytest.skip(f'example client not built: {client.name}')
r = client.run(args=[
'-n', f'{count}', '-m', f'{max_parallel}', '-a',
+ '-C', env.ca.cert_file,
'-A', f'{abort_offset}', '-V', proto, url
])
r.check_exit_code(42) # CURLE_ABORTED_BY_CALLBACK
@@ -379,6 +383,7 @@ class TestDownload:
pytest.skip(f'example client not built: {client.name}')
r = client.run(args=[
'-n', f'{count}', '-m', f'{max_parallel}', '-a',
+ '-C', env.ca.cert_file,
'-F', f'{fail_offset}', '-V', proto, url
])
r.check_exit_code(23) # CURLE_WRITE_ERROR
@@ -487,7 +492,8 @@ class TestDownload:
if not client.exists():
pytest.skip(f'example client not built: {client.name}')
r = client.run(args=[
- '-n', f'{count}', '-P', f'{pause_offset}', '-V', proto, url
+ '-n', f'{count}', '-P', f'{pause_offset}',
+ '-C', env.ca.cert_file, '-V', proto, url
])
r.check_exit_code(0)
srcfile = os.path.join(httpd.docs_dir, docname)
@@ -549,6 +555,7 @@ class TestDownload:
pytest.skip(f'example client not built: {client.name}')
r = client.run(args=[
'-n', f'{count}',
+ '-C', env.ca.cert_file,
'-e', # use TLS earlydata
'-f', # forbid reuse of connections
'-r', f'{env.domain1}:{port}:127.0.0.1',
@@ -596,6 +603,7 @@ class TestDownload:
r = client.run(args=[
'-n', f'{count}',
'-m', f'{max_parallel}',
+ '-C', env.ca.cert_file,
'-x', # always use a fresh connection
'-M', str(max_host_conns), # limit conns per host
'-r', f'{env.domain1}:{port}:127.0.0.1',
@@ -634,6 +642,7 @@ class TestDownload:
r = client.run(args=[
'-n', f'{count}',
'-m', f'{max_parallel}',
+ '-C', env.ca.cert_file,
'-x', # always use a fresh connection
'-T', str(max_total_conns), # limit total connections
'-r', f'{env.domain1}:{port}:127.0.0.1',
@@ -673,7 +682,8 @@ class TestDownload:
pytest.skip(f'example client not built: {client.name}')
r = client.run(args=[
'-n', f'{count}', '-m', f'{count}',
- '-P', f'{pause_offset}', '-V', proto, url
+ '-P', f'{pause_offset}', '-C', env.ca.cert_file,
+ '-V', proto, url
])
r.check_exit_code(0)
tests/http/test_08_caddy.py+1 -0
@@ -184,6 +184,7 @@ class TestCaddy:
pytest.skip(f'example client not built: {client.name}')
r = client.run(args=[
'-n', f'{count}',
+ '-C', env.ca.cert_file,
'-e', # use TLS earlydata
'-f', # forbid reuse of connections
'-r', f'{env.domain1}:{caddy.port}:127.0.0.1',
tests/http/test_17_ssl_use.py+2 -1
@@ -382,7 +382,7 @@ class TestSSLUse:
if not env.have_h3():
pytest.skip("h3 not supported")
if not env.curl_uses_lib('quictls') and \
- not (env.curl_uses_lib('openssl') and env.curl_uses_lib('ngtcp2')) and \
+ not env.curl_uses_lib('openssl') and \
not env.curl_uses_lib('gnutls') and \
not env.curl_uses_lib('wolfssl'):
pytest.skip("QUIC session reuse not implemented")
@@ -395,6 +395,7 @@ class TestSSLUse:
r = client.run(args=[
'-n', f'{count}',
'-f', # forbid reuse of connections
+ '-C', env.ca.cert_file,
'-r', f'{env.domain1}:{env.port_for("h3")}:127.0.0.1',
'-V', 'h3', url
])
tests/http/test_19_shutdown.py+3 -1
@@ -123,7 +123,8 @@ class TestShutdown:
if not client.exists():
pytest.skip(f'example client not built: {client.name}')
r = client.run(args=[
- '-n', f'{count}', '-f', '-V', proto, url
+ '-n', f'{count}', '-f', '-C', env.ca.cert_file,
+ '-V', proto, url
])
r.check_exit_code(0)
shutdowns = [line for line in r.trace_lines
@@ -199,6 +200,7 @@ class TestShutdown:
pytest.skip(f'example client not built: {client.name}')
r = client.run(args=[
'-n', f'{count}', # that many transfers
+ '-C', env.ca.cert_file,
'-f', # forbid conn reuse
'-m', '10', # max parallel
'-T', '5', # max total conns at a time
tests/libtest/cli_hx_download.c+12 -6
@@ -211,13 +211,13 @@ static int my_progress_d_cb(void *userdata,
static int setup_hx_download(CURL *curl, const char *url, struct transfer_d *t,
long http_version, struct curl_slist *host,
CURLSH *share, int use_earlydata,
- int fresh_connect)
+ int fresh_connect, char *cafile)
{
curl_easy_setopt(curl, CURLOPT_SHARE, share);
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, http_version);
- curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
- curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
+ if(cafile)
+ curl_easy_setopt(curl, CURLOPT_CAINFO, cafile);
curl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, "");
curl_easy_setopt(curl, CURLOPT_BUFFERSIZE, (long)(128 * 1024));
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, my_write_d_cb);
@@ -292,11 +292,12 @@ static CURLcode test_cli_hx_download(const char *URL)
size_t max_host_conns = 0;
size_t max_total_conns = 0;
int fresh_connect = 0;
+ char *cafile = NULL;
CURLcode result = CURLE_OK;
(void)URL;
- while((ch = cgetopt(test_argc, test_argv, "aefhm:n:xA:F:M:P:r:T:V:"))
+ while((ch = cgetopt(test_argc, test_argv, "aefhm:n:xA:C:F:M:P:r:T:V:"))
!= -1) {
const char *opt = coptarg;
curl_off_t num;
@@ -329,6 +330,10 @@ static CURLcode test_cli_hx_download(const char *URL)
if(!curlx_str_number(&opt, &num, LONG_MAX))
abort_offset = (size_t)num;
break;
+ case 'C':
+ curlx_free(cafile);
+ cafile = curlx_strdup(coptarg);
+ break;
case 'F':
if(!curlx_str_number(&opt, &num, LONG_MAX))
fail_offset = (size_t)num;
@@ -432,7 +437,7 @@ static CURLcode test_cli_hx_download(const char *URL)
t->curl = curl_easy_init();
if(!t->curl ||
setup_hx_download(t->curl, url, t, http_version, host, share,
- use_earlydata, fresh_connect)) {
+ use_earlydata, fresh_connect, cafile)) {
curl_mfprintf(stderr, "[t-%zu] FAILED setup\n", i);
result = (CURLcode)1;
goto cleanup;
@@ -515,7 +520,7 @@ static CURLcode test_cli_hx_download(const char *URL)
t->curl = curl_easy_init();
if(!t->curl ||
setup_hx_download(t->curl, url, t, http_version, host, share,
- use_earlydata, fresh_connect)) {
+ use_earlydata, fresh_connect, cafile)) {
curl_mfprintf(stderr, "[t-%zu] FAILED setup\n", i);
result = (CURLcode)1;
goto cleanup;
@@ -566,6 +571,7 @@ cleanup:
optcleanup:
curlx_free(resolve);
+ curlx_free(cafile);
return result;
}