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
This commit is contained in:
Stefan Eissing 2024-12-30 10:58:35 +01:00 committed by Daniel Stenberg
parent c2d37463b9
commit 8a66c11a29
No known key found for this signature in database
GPG Key ID: 5CC908FDB71E12C2
10 changed files with 40 additions and 49 deletions

View File

@ -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:

View File

@ -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);

View File

@ -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,

View File

@ -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);

View File

@ -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)

View File

@ -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 */

View File

@ -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));
}

View File

@ -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);

View File

@ -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 */

View File

@ -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