From: Stefan Eissing Date: Mon, 30 Dec 2024 09:58:35 +0000 (+0100) Subject: vtls: only remember the expiry timestamp in session cache X-Git-Tag: curl-8_12_0~242 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=8a66c11a298c691d3613ef648f0fd0c968f20c0d;p=thirdparty%2Fcurl.git vtls: only remember the expiry timestamp in session cache Instead of receive and lifetime, keep only the eppch seconds when a session expires. Closes #15861 --- diff --git a/lib/vquic/curl_ngtcp2.c b/lib/vquic/curl_ngtcp2.c index 0449acdab1..79535d6e09 100644 --- a/lib/vquic/curl_ngtcp2.c +++ b/lib/vquic/curl_ngtcp2.c @@ -2232,7 +2232,7 @@ static int quic_gtls_handshake_cb(gnutls_session_t session, unsigned int htype, quic_tp_len = (size_t)tplen; } (void)Curl_gtls_cache_session(cf, data, ctx->peer.scache_key, - session, -1, "h3", quic_tp, quic_tp_len); + session, 0, "h3", quic_tp, quic_tp_len); break; } default: diff --git a/lib/vtls/bearssl.c b/lib/vtls/bearssl.c index d3326bb45c..c52f28d748 100644 --- a/lib/vtls/bearssl.c +++ b/lib/vtls/bearssl.c @@ -836,7 +836,7 @@ static CURLcode bearssl_connect_step3(struct Curl_cfilter *cf, ret = Curl_ssl_session_create((unsigned char *)session, sizeof(*session), (int)session->version, connssl->negotiated.alpn, - 0, -1, 0, &sc_session); + 0, 0, &sc_session); if(!ret) { ret = Curl_ssl_scache_put(cf, data, connssl->peer.scache_key, sc_session); diff --git a/lib/vtls/gtls.c b/lib/vtls/gtls.c index 879c6f3455..b87da2c82d 100644 --- a/lib/vtls/gtls.c +++ b/lib/vtls/gtls.c @@ -720,7 +720,7 @@ CURLcode Curl_gtls_cache_session(struct Curl_cfilter *cf, struct Curl_easy *data, const char *ssl_peer_key, gnutls_session_t session, - int lifetime_secs, + curl_off_t valid_until, const char *alpn, unsigned char *quic_tp, size_t quic_tp_len) @@ -765,7 +765,7 @@ CURLcode Curl_gtls_cache_session(struct Curl_cfilter *cf, result = Curl_ssl_session_create2(sdata, sdata_len, Curl_glts_get_ietf_proto(session), - alpn, 0, lifetime_secs, earlydata_max, + alpn, valid_until, earlydata_max, qtp_clone, quic_tp_len, &sc_session); /* call took ownership of `sdata` and `qtp_clone` */ @@ -800,8 +800,8 @@ static CURLcode cf_gtls_update_session_id(struct Curl_cfilter *cf, { struct ssl_connect_data *connssl = cf->ctx; return Curl_gtls_cache_session(cf, data, connssl->peer.scache_key, - session, -1, - connssl->negotiated.alpn, NULL, 0); + session, 0, connssl->negotiated.alpn, + NULL, 0); } static int gtls_handshake_cb(gnutls_session_t session, unsigned int htype, diff --git a/lib/vtls/gtls.h b/lib/vtls/gtls.h index a40e68097c..a17dcd7adb 100644 --- a/lib/vtls/gtls.h +++ b/lib/vtls/gtls.h @@ -110,7 +110,7 @@ CURLcode Curl_gtls_cache_session(struct Curl_cfilter *cf, struct Curl_easy *data, const char *ssl_peer_key, gnutls_session_t session, - int lifetime_secs, + curl_off_t valid_until, const char *alpn, unsigned char *quic_tp, size_t quic_tp_len); diff --git a/lib/vtls/mbedtls.c b/lib/vtls/mbedtls.c index f2c7b6c238..c8b5af6ba5 100644 --- a/lib/vtls/mbedtls.c +++ b/lib/vtls/mbedtls.c @@ -1173,7 +1173,7 @@ mbed_new_session(struct Curl_cfilter *cf, struct Curl_easy *data) #endif result = Curl_ssl_session_create(sdata, slen, ietf_tls_id, - connssl->negotiated.alpn, 0, -1, 0, + connssl->negotiated.alpn, 0, 0, &sc_session); sdata = NULL; /* call took ownership */ if(!result) diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c index a6549d272f..f253674b2f 100644 --- a/lib/vtls/openssl.c +++ b/lib/vtls/openssl.c @@ -2902,7 +2902,8 @@ CURLcode Curl_ossl_add_session(struct Curl_cfilter *cf, } result = Curl_ssl_session_create(der_session_buf, der_session_size, - ietf_tls_id, alpn, 0, + ietf_tls_id, alpn, + (curl_off_t)time(NULL) + SSL_SESSION_get_timeout(session), 0, &sc_session); der_session_buf = NULL; /* took ownership of sdata */ diff --git a/lib/vtls/vtls_scache.c b/lib/vtls/vtls_scache.c index b06a4ca805..2c661a61c1 100644 --- a/lib/vtls/vtls_scache.c +++ b/lib/vtls/vtls_scache.c @@ -109,8 +109,7 @@ static void cf_ssl_scache_clear_session(struct Curl_ssl_session *s) } s->quic_tp_len = 0; s->ietf_tls_id = 0; - s->time_received = 0; - s->lifetime_secs = 0; + s->valid_until = 0; Curl_safefree(s->alpn); } @@ -124,20 +123,18 @@ static void cf_ssl_scache_sesssion_ldestroy(void *udata, void *s) CURLcode Curl_ssl_session_create(unsigned char *sdata, size_t sdata_len, int ietf_tls_id, const char *alpn, - curl_off_t time_received, long lifetime_secs, - size_t earlydata_max, + curl_off_t valid_until, size_t earlydata_max, struct Curl_ssl_session **psession) { return Curl_ssl_session_create2(sdata, sdata_len, ietf_tls_id, alpn, - time_received, lifetime_secs, - earlydata_max, NULL, 0, psession); + valid_until, earlydata_max, + NULL, 0, psession); } CURLcode Curl_ssl_session_create2(unsigned char *sdata, size_t sdata_len, int ietf_tls_id, const char *alpn, - curl_off_t time_received, long lifetime_secs, - size_t earlydata_max, + curl_off_t valid_until, size_t earlydata_max, unsigned char *quic_tp, size_t quic_tp_len, struct Curl_ssl_session **psession) { @@ -157,16 +154,7 @@ Curl_ssl_session_create2(unsigned char *sdata, size_t sdata_len, } s->ietf_tls_id = ietf_tls_id; - s->time_received = time_received; - if(lifetime_secs < 0) - lifetime_secs = -1; /* unknown */ - else if((s->ietf_tls_id == CURL_IETF_PROTO_TLS1_3) && - (lifetime_secs > CURL_SCACHE_MAX_13_LIFETIME_SEC)) - lifetime_secs = CURL_SCACHE_MAX_13_LIFETIME_SEC; - else if(lifetime_secs > CURL_SCACHE_MAX_12_LIFETIME_SEC) - lifetime_secs = CURL_SCACHE_MAX_12_LIFETIME_SEC; - - s->lifetime_secs = (int)lifetime_secs; + s->valid_until = valid_until; s->earlydata_max = earlydata_max; s->sdata = sdata; s->sdata_len = sdata_len; @@ -272,8 +260,7 @@ static void cf_scache_session_remove(struct Curl_ssl_scache_peer *peer, static bool cf_scache_session_expired(struct Curl_ssl_session *s, curl_off_t now) { - return (s->lifetime_secs > 0 && - (s->time_received + s->lifetime_secs) < now); + return (s->valid_until > 0) && (s->valid_until < now); } static void cf_scache_peer_remove_expired(struct Curl_ssl_scache_peer *peer, @@ -715,16 +702,21 @@ static CURLcode cf_scache_peer_add_session(struct Curl_cfilter *cf, struct Curl_ssl_scache_peer *peer = NULL; CURLcode result = CURLE_OUT_OF_MEMORY; curl_off_t now = (curl_off_t)time(NULL); + curl_off_t max_lifetime; if(!scache || !scache->peer_count) { Curl_ssl_session_destroy(s); return CURLE_OK; } - if(!s->time_received) - s->time_received = now; - if(s->lifetime_secs < 0) - s->lifetime_secs = scache->default_lifetime_secs; + if(s->valid_until <= 0) + s->valid_until = now + scache->default_lifetime_secs; + + max_lifetime = (s->ietf_tls_id == CURL_IETF_PROTO_TLS1_3) ? + CURL_SCACHE_MAX_13_LIFETIME_SEC : + CURL_SCACHE_MAX_12_LIFETIME_SEC; + if(s->valid_until > (now + max_lifetime)) + s->valid_until = now + max_lifetime; if(cf_scache_session_expired(s, now)) { CURL_TRC_CF(data, cf, "[SCACHE] add, session already expired"); @@ -761,9 +753,9 @@ out: } else CURL_TRC_CF(data, cf, "[SCACHE] added session for %s [proto=0x%x, " - "lifetime=%d, alpn=%s, earlydata=%zu, quic_tp=%s], " - "peer has %zu sessions now", - ssl_peer_key, s->ietf_tls_id, s->lifetime_secs, s->alpn, + "valid_secs=%" FMT_OFF_T ", alpn=%s, earlydata=%zu, " + "quic_tp=%s], peer has %zu sessions now", + ssl_peer_key, s->ietf_tls_id, s->valid_until - now, s->alpn, s->earlydata_max, s->quic_tp ? "yes" : "no", Curl_llist_count(&peer->sessions)); return result; @@ -826,9 +818,8 @@ CURLcode Curl_ssl_scache_take(struct Curl_cfilter *cf, if(s) { *ps = s; CURL_TRC_CF(data, cf, "[SCACHE] took session for %s [proto=0x%x, " - "lifetime=%d, alpn=%s, earlydata=%zu, quic_tp=%s], " - "%zu sessions remain", - ssl_peer_key, s->ietf_tls_id, s->lifetime_secs, s->alpn, + "alpn=%s, earlydata=%zu, quic_tp=%s], %zu sessions remain", + ssl_peer_key, s->ietf_tls_id, s->alpn, s->earlydata_max, s->quic_tp ? "yes" : "no", Curl_llist_count(&peer->sessions)); } diff --git a/lib/vtls/vtls_scache.h b/lib/vtls/vtls_scache.h index 33d426a38e..14b011241f 100644 --- a/lib/vtls/vtls_scache.h +++ b/lib/vtls/vtls_scache.h @@ -118,8 +118,7 @@ CURLcode Curl_ssl_scache_add_obj(struct Curl_cfilter *cf, struct Curl_ssl_session { const unsigned char *sdata; /* session ticket data, plain bytes */ size_t sdata_len; /* number of bytes in sdata */ - curl_off_t time_received; /* seconds since EPOCH ticket was received */ - int lifetime_secs; /* ticket lifetime (-1 unknown) */ + curl_off_t valid_until; /* seconds since EPOCH until ticket expires */ int ietf_tls_id; /* TLS protocol identifier negotiated */ char *alpn; /* APLN TLS negotiated protocol string */ size_t earlydata_max; /* max 0-RTT data supported by peer */ @@ -134,17 +133,14 @@ struct Curl_ssl_session { * @param sdata_len amount of session data bytes * @param ietf_tls_id IETF protocol version, e.g. 0x304 for TLSv1.3 * @param alpn ALPN protocol selected or NULL - * @param time_received seconds since EPOCH session was received, pass 0 - * to have the value set to time of call - * @param lifetime_secs seconds of announced lifetime, <0 if unknown. - * values longer than 1 week will be capped as - * required by RFC 8446 + * @param valid_until seconds since EPOCH when session expires, pass 0 + * in case this is not known. * @param psession on return the scached session instance created */ CURLcode Curl_ssl_session_create(unsigned char *sdata, size_t sdata_len, int ietf_tls_id, const char *alpn, - curl_off_t time_received, long lifetime_secs, + curl_off_t valid_until, size_t earlydata_max, struct Curl_ssl_session **psession); @@ -153,7 +149,7 @@ Curl_ssl_session_create(unsigned char *sdata, size_t sdata_len, CURLcode Curl_ssl_session_create2(unsigned char *sdata, size_t sdata_len, int ietf_tls_id, const char *alpn, - curl_off_t time_received, long lifetime_secs, + curl_off_t valid_until, size_t earlydata_max, unsigned char *quic_tp, size_t quic_tp_len, struct Curl_ssl_session **psession); diff --git a/lib/vtls/wolfssl.c b/lib/vtls/wolfssl.c index a17f1cfdde..467de62a19 100644 --- a/lib/vtls/wolfssl.c +++ b/lib/vtls/wolfssl.c @@ -431,7 +431,8 @@ CURLcode Curl_wssl_cache_session(struct Curl_cfilter *cf, } result = Curl_ssl_session_create(sdata, sdata_len, - ietf_tls_id, alpn, 0, + ietf_tls_id, alpn, + (curl_off_t)time(NULL) + wolfSSL_SESSION_get_timeout(session), 0, &sc_session); sdata = NULL; /* took ownership of sdata */ diff --git a/tests/http/test_08_caddy.py b/tests/http/test_08_caddy.py index 418eaae70f..fdec2fdfa7 100644 --- a/tests/http/test_08_caddy.py +++ b/tests/http/test_08_caddy.py @@ -212,6 +212,8 @@ class TestCaddy: @pytest.mark.parametrize("proto", ['http/1.1', 'h2', 'h3']) def test_08_08_earlydata(self, env: Env, httpd, caddy, proto): + if not env.curl_uses_lib('gnutls'): + pytest.skip('TLS earlydata only implemented in GnuTLS') if proto == 'h3' and not env.have_h3(): pytest.skip("h3 not supported") count = 2