]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
vtls: only remember the expiry timestamp in session cache
authorStefan Eissing <stefan@eissing.org>
Mon, 30 Dec 2024 09:58:35 +0000 (10:58 +0100)
committerDaniel Stenberg <daniel@haxx.se>
Mon, 30 Dec 2024 15:14:52 +0000 (16:14 +0100)
Instead of receive and lifetime, keep only the eppch seconds when a
session expires.

Closes #15861

lib/vquic/curl_ngtcp2.c
lib/vtls/bearssl.c
lib/vtls/gtls.c
lib/vtls/gtls.h
lib/vtls/mbedtls.c
lib/vtls/openssl.c
lib/vtls/vtls_scache.c
lib/vtls/vtls_scache.h
lib/vtls/wolfssl.c
tests/http/test_08_caddy.py

index 0449acdab1adb2929705d752cc7debee9822745b..79535d6e0927ea16188eb7f3119fa40f081120a2 100644 (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:
index d3326bb45cf5e8d1d3c40df58519e330b1b36dee..c52f28d748c171dc51d166b5d2c5bd5cea832090 100644 (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);
index 879c6f3455c26e72d106f19f5dc4321e119a6235..b87da2c82db571826e2db376553480a9ae991d7f 100644 (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,
index a40e68097ca0d71084883fbcb2527494d7794c6b..a17dcd7adbbfd902d721282baa74f167fa3872a4 100644 (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);
index f2c7b6c2388a74927012e4269b74f1bb78b06c6a..c8b5af6ba5ca501863758da91d5f1fd4cb907b2f 100644 (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)
index a6549d272fa054c23bce16ac78c1c079967b8b84..f253674b2fd5893f50509d7f2adfb06662298194 100644 (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 */
index b06a4ca805399bb8be290e149044ebe1d825f9b7..2c661a61c1dce06e4dd634ceef85bb30f33673ac 100644 (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));
   }
index 33d426a38e7e8045d2a358df02daedbe53887237..14b011241f9b9e7187b9bbca1de3ed4de4c3de22 100644 (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);
index a17f1cfddeafdb5c9e354f971871128810650649..467de62a197d8bb62831bb268bcc920020105677 100644 (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 */
index 418eaae70f3642968cc15c9cd60b803aa9910be0..fdec2fdfa7097fe01458b76750397dcdde78c0c3 100644 (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