← Commit list

75c2c881af

Stefan Eissing
Stefan Eissing
2026-07-01
SUCCESS Duration: 212s

Subject

openssl+sectrust: fix session reuse

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/vquic/cf-ngtcp2-cmn.c+2 -2
@@ -649,8 +649,8 @@ static int quic_ossl_new_session_cb(SSL *ssl, SSL_SESSION *ssl_sessionid)
quic_tp_len = (size_t)tplen;
}
#endif
- Curl_ossl_add_session(cf, data, ctx->ssl_peer.scache_key, ssl_sessionid,
- SSL_version(ssl), "h3", quic_tp, quic_tp_len);
+ Curl_ossl_add_session(cf, data, &ctx->tls.ossl, ctx->ssl_peer.scache_key,
+ ssl_sessionid, "h3", quic_tp, quic_tp_len);
}
return 0;
}
lib/vtls/openssl.c+32 -21
@@ -2632,9 +2632,9 @@ static CURLcode ossl_set_ssl_version_min_max(struct Curl_cfilter *cf,
CURLcode Curl_ossl_add_session(struct Curl_cfilter *cf,
struct Curl_easy *data,
+ struct ossl_ctx *octx,
const char *ssl_peer_key,
SSL_SESSION *session,
- int ietf_tls_id,
const char *alpn,
unsigned char *quic_tp,
size_t quic_tp_len)
@@ -2651,6 +2651,7 @@ CURLcode Curl_ossl_add_session(struct Curl_cfilter *cf,
size_t der_session_size;
unsigned char *der_session_ptr;
size_t earlydata_max = 0;
+ int ietf_tls_id = SSL_version(octx->ssl);
der_session_size = i2d_SSL_SESSION(session, NULL);
if(der_session_size == 0) {
@@ -2688,6 +2689,9 @@ CURLcode Curl_ossl_add_session(struct Curl_cfilter *cf,
earlydata_max, qtp_clone, quic_tp_len,
&sc_session);
der_session_buf = NULL; /* took ownership of sdata */
+#ifdef USE_APPLE_SECTRUST
+ sc_session->sectrust_verified = octx->sectrust_verified;
+#endif
if(!result) {
result = Curl_ssl_scache_put(cf, data, ssl_peer_key, sc_session);
/* took ownership of `sc_session` */
@@ -2708,8 +2712,9 @@ static int ossl_new_session_cb(SSL *ssl, SSL_SESSION *ssl_sessionid)
if(cf) {
struct Curl_easy *data = CF_DATA_CURRENT(cf);
struct ssl_connect_data *connssl = cf->ctx;
- Curl_ossl_add_session(cf, data, connssl->peer.scache_key, ssl_sessionid,
- SSL_version(ssl), connssl->negotiated.alpn, NULL, 0);
+ struct ossl_ctx *octx = (struct ossl_ctx *)connssl->backend;
+ Curl_ossl_add_session(cf, data, octx, connssl->peer.scache_key,
+ ssl_sessionid, connssl->negotiated.alpn, NULL, 0);
}
return 0;
}
@@ -3353,7 +3358,12 @@ static CURLcode ossl_init_session_and_alpns(
}
else {
if(conn_cfg->verifypeer &&
- (SSL_get_verify_result(octx->ssl) != X509_V_OK)) {
+ (SSL_get_verify_result(octx->ssl) != X509_V_OK)
+#ifdef USE_APPLE_SECTRUST
+ /* if sectrust is used and verified the session before */
+ && (!ssl_config->native_ca_store || !scs->sectrust_verified)
+#endif
+ ) {
/* Session was from unverified connection, cannot reuse here */
SSL_set_session(octx->ssl, NULL);
infof(data, "SSL session not peer verified, not reusing");
@@ -3362,6 +3372,9 @@ static CURLcode ossl_init_session_and_alpns(
infof(data, "SSL reusing session with ALPN '%s'",
scs->alpn ? scs->alpn : "-");
octx->reused_session = TRUE;
+#ifdef USE_APPLE_SECTRUST
+ octx->sectrust_session = scs->sectrust_verified;
+#endif
infof(data, "SSL verify result: %lx",
(unsigned long)SSL_get_verify_result(octx->ssl));
#ifdef HAVE_OPENSSL_EARLYDATA
@@ -4671,13 +4684,13 @@ static CURLcode ossl_chain_get_der(struct Curl_cfilter *cf,
static CURLcode ossl_apple_verify(struct Curl_cfilter *cf,
struct Curl_easy *data,
struct ossl_ctx *octx,
- struct ssl_peer *peer,
- bool *pverified)
+ struct ssl_peer *peer)
{
struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
struct ossl_certs_ctx chain;
CURLcode result;
+ octx->sectrust_verified = FALSE;
memset(&chain, 0, sizeof(chain));
chain.sk = SSL_get_peer_cert_chain(octx->ssl);
chain.num_certs = chain.sk ? sk_X509_num(chain.sk) : 0;
@@ -4689,8 +4702,11 @@ static CURLcode ossl_apple_verify(struct Curl_cfilter *cf,
result = CURLE_PEER_FAILED_VERIFICATION;
}
else {
- /* when session was reused, there is no peer cert chain */
- *pverified = FALSE;
+ /* When session was reused, there is no peer cert chain.
+ * We trust it if it came from a SecTrust verified TLS. */
+ CURL_TRC_CF(data, cf, "session reused, sectrust_session=%d",
+ octx->sectrust_session);
+ octx->sectrust_verified = (bool)octx->sectrust_session;
return CURLE_OK;
}
}
@@ -4717,12 +4733,12 @@ static CURLcode ossl_apple_verify(struct Curl_cfilter *cf,
if(!result && ocsp_missing && conn_config->verifystatus &&
!octx->reused_session) {
/* verified, but OCSP stapling is required and server sent none */
- *pverified = TRUE;
+ octx->sectrust_verified = TRUE;
failf(data, "No OCSP response received");
return CURLE_SSL_INVALIDCERTSTATUS;
}
}
- *pverified = !result;
+ octx->sectrust_verified = !result;
return result;
}
#endif /* USE_APPLE_SECTRUST */
@@ -4739,9 +4755,6 @@ CURLcode Curl_ossl_check_peer_cert(struct Curl_cfilter *cf,
long ossl_verify;
X509 *server_cert;
bool verified = FALSE;
-#if !defined(OPENSSL_NO_OCSP) && defined(USE_APPLE_SECTRUST)
- bool sectrust_verified = FALSE;
-#endif
if(data->set.ssl.certinfo && !octx->reused_session) {
/* asked to gather certificate info. Reused sessions do not have cert
@@ -4789,15 +4802,13 @@ CURLcode Curl_ossl_check_peer_cert(struct Curl_cfilter *cf,
/* we verify using Apple SecTrust *unless* OpenSSL already verified.
* This may happen if the application intercepted the OpenSSL callback
* and installed its own. */
- result = ossl_apple_verify(cf, data, octx, peer, &verified);
+ result = ossl_apple_verify(cf, data, octx, peer);
if(result && (result != CURLE_PEER_FAILED_VERIFICATION))
goto out; /* unexpected error */
- if(verified) {
+ if(octx->sectrust_verified) {
infof(data, "SSL certificate verified via Apple SecTrust.");
ssl_config->certverifyresult = X509_V_OK;
-#ifndef OPENSSL_NO_OCSP
- sectrust_verified = TRUE;
-#endif
+ verified = TRUE;
}
}
#endif
@@ -4816,9 +4827,9 @@ CURLcode Curl_ossl_check_peer_cert(struct Curl_cfilter *cf,
#ifndef OPENSSL_NO_OCSP
if(conn_config->verifystatus &&
#ifdef USE_APPLE_SECTRUST
- !sectrust_verified && /* already verified via apple sectrust, cannot
- * verifystate via OpenSSL in that case as it
- * does not have the trust anchors */
+ !octx->sectrust_verified && /* already verified via sectrust, cannot
+ * verifystate via OpenSSL in that case as it
+ * does not have the trust anchors */
#endif
!octx->reused_session) {
/* do not do this after Session ID reuse */
lib/vtls/openssl.h+5 -1
@@ -129,6 +129,10 @@ struct ossl_ctx {
BIT(x509_store_setup); /* x509 store has been set up */
BIT(store_is_empty); /* no certs/paths/blobs in x509 store */
BIT(reused_session); /* session-ID was reused for this */
+#ifdef USE_APPLE_SECTRUST
+ BIT(sectrust_verified); /* peer was verified by sectrust */
+ BIT(sectrust_session); /* session from sectrust verified peer */
+#endif
};
size_t Curl_ossl_version(char *buffer, size_t size);
@@ -182,9 +186,9 @@ CURLcode Curl_ossl_ctx_configure(struct Curl_cfilter *cf,
*/
CURLcode Curl_ossl_add_session(struct Curl_cfilter *cf,
struct Curl_easy *data,
+ struct ossl_ctx *octx,
const char *ssl_peer_key,
SSL_SESSION *session,
- int ietf_tls_id,
const char *alpn,
unsigned char *quic_tp,
size_t quic_tp_len);
lib/vtls/vtls_scache.h+1 -0
@@ -131,6 +131,7 @@ struct Curl_ssl_session {
const unsigned char *quic_tp; /* Optional QUIC transport param bytes */
size_t quic_tp_len; /* number of bytes in quic_tp */
struct Curl_llist_node list; /* internal storage handling */
+ BIT(sectrust_verified); /* session comes from sectrust verified TLS */
};
/* Create a `session` instance. Does NOT need locking.
lib/vtls/vtls_spack.c+7 -0
@@ -38,6 +38,7 @@
#define CURL_SPACK_ALPN 0x05
#define CURL_SPACK_EARLYDATA 0x06
#define CURL_SPACK_QUICTP 0x07
+#define CURL_SPACK_SECTRUST 0x08
static CURLcode spack_enc8(struct dynbuf *buf, uint8_t b)
{
@@ -218,6 +219,9 @@ CURLcode Curl_ssl_session_pack(struct Curl_easy *data,
if(!result)
result = spack_enc32(buf, (uint32_t)s->earlydata_max);
}
+ if(!result && s->sectrust_verified) {
+ result = spack_enc8(buf, CURL_SPACK_SECTRUST);
+ }
if(!result && s->quic_tp && s->quic_tp_len) {
result = spack_enc8(buf, CURL_SPACK_QUICTP);
if(!result)
@@ -303,6 +307,9 @@ CURLcode Curl_ssl_session_unpack(struct Curl_easy *data,
goto out;
s->valid_until = (curl_off_t)val64;
break;
+ case CURL_SPACK_SECTRUST:
+ s->sectrust_verified = TRUE;
+ break;
default: /* unknown tag */
result = CURLE_READ_ERROR;
goto out;