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:
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);
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)
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` */
{
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,
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);
#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)
}
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 */
}
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);
}
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)
{
}
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;
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,
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");
}
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;
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));
}
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 */
* @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);
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);
}
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 */
@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