[glib-networking/mcatanzaro/session-resumption: 17/17] Revert "gnutls: support TLS 1.3 session tickets client-side"
- From: Michael Catanzaro <mcatanzaro src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib-networking/mcatanzaro/session-resumption: 17/17] Revert "gnutls: support TLS 1.3 session tickets client-side"
- Date: Tue, 1 Oct 2019 23:06:09 +0000 (UTC)
commit 6cf4406257728a63feb0e16a1c1d6bbcda39042e
Author: Michael Catanzaro <mcatanzaro gnome org>
Date: Tue Oct 1 18:05:00 2019 -0500
Revert "gnutls: support TLS 1.3 session tickets client-side"
This reverts commit 1dfb04f1caa587a3000feda8c5eab369ab7f8a14.
tls/gnutls/gtlsbackend-gnutls.c | 85 +++++++++++++++--------
tls/gnutls/gtlsbackend-gnutls.h | 10 ++-
tls/gnutls/gtlsclientconnection-gnutls.c | 114 +++++++++++++++----------------
tls/gnutls/gtlsconnection-gnutls.c | 6 +-
tls/gnutls/gtlsconnection-gnutls.h | 2 +
5 files changed, 126 insertions(+), 91 deletions(-)
---
diff --git a/tls/gnutls/gtlsbackend-gnutls.c b/tls/gnutls/gtlsbackend-gnutls.c
index bd6863f..d0e5eaa 100644
--- a/tls/gnutls/gtlsbackend-gnutls.c
+++ b/tls/gnutls/gtlsbackend-gnutls.c
@@ -172,14 +172,15 @@ g_tls_backend_gnutls_interface_init (GTlsBackendInterface *iface)
*/
G_LOCK_DEFINE_STATIC (session_cache_lock);
-GHashTable *client_session_cache; /* (owned) GBytes -> (owned) GTlsBackendGnutlsCacheData */
+GHashTable *client_session_cache, *server_session_cache;
#define SESSION_CACHE_MAX_SIZE 50
#define SESSION_CACHE_MAX_AGE (60 * 60) /* one hour */
typedef struct {
- GQueue *session_tickets; /* (owned) GBytes */
- gint64 last_used;
+ GBytes *session_id;
+ GBytes *session_data;
+ time_t last_used;
} GTlsBackendGnutlsCacheData;
static void
@@ -188,7 +189,7 @@ session_cache_cleanup (GHashTable *cache)
GHashTableIter iter;
gpointer key, value;
GTlsBackendGnutlsCacheData *cache_data;
- gint64 expired = g_get_monotonic_time () - SESSION_CACHE_MAX_AGE;
+ time_t expired = time (NULL) - SESSION_CACHE_MAX_AGE;
g_hash_table_iter_init (&iter, cache);
while (g_hash_table_iter_next (&iter, &key, &value))
@@ -200,51 +201,84 @@ session_cache_cleanup (GHashTable *cache)
}
static void
-cache_data_free (GTlsBackendGnutlsCacheData *data)
+cache_data_free (gpointer data)
{
- g_queue_free_full (data->session_tickets, (GDestroyNotify)g_bytes_unref);
- g_free (data);
+ GTlsBackendGnutlsCacheData *cache_data = data;
+
+ g_bytes_unref (cache_data->session_id);
+ g_bytes_unref (cache_data->session_data);
+ g_free (cache_data);
}
static GHashTable *
-get_session_cache (gboolean create)
+get_session_cache (unsigned int type,
+ gboolean create)
{
- if (!client_session_cache && create)
+ GHashTable **cache_p;
+
+ cache_p = (type == GNUTLS_CLIENT) ? &client_session_cache : &server_session_cache;
+ if (!*cache_p && create)
{
- client_session_cache = g_hash_table_new_full (g_bytes_hash, g_bytes_equal,
- (GDestroyNotify)g_bytes_unref,
(GDestroyNotify)cache_data_free);
+ *cache_p = g_hash_table_new_full (g_bytes_hash, g_bytes_equal,
+ NULL, cache_data_free);
}
- return client_session_cache;
+ return *cache_p;
}
void
-g_tls_backend_gnutls_store_session_data (GBytes *session_id,
- GBytes *session_data)
+g_tls_backend_gnutls_store_session (unsigned int type,
+ GBytes *session_id,
+ GBytes *session_data)
{
GTlsBackendGnutlsCacheData *cache_data;
GHashTable *cache;
G_LOCK (session_cache_lock);
- cache = get_session_cache (TRUE);
+ cache = get_session_cache (type, TRUE);
cache_data = g_hash_table_lookup (cache, session_id);
- if (!cache_data)
+ if (cache_data)
+ {
+ if (!g_bytes_equal (cache_data->session_data, session_data))
+ {
+ g_bytes_unref (cache_data->session_data);
+ cache_data->session_data = g_bytes_ref (session_data);
+ }
+ }
+ else
{
if (g_hash_table_size (cache) >= SESSION_CACHE_MAX_SIZE)
session_cache_cleanup (cache);
cache_data = g_new (GTlsBackendGnutlsCacheData, 1);
- cache_data->session_tickets = g_queue_new ();
- g_hash_table_insert (cache, g_bytes_ref (session_id), cache_data);
+ cache_data->session_id = g_bytes_ref (session_id);
+ cache_data->session_data = g_bytes_ref (session_data);
+
+ g_hash_table_insert (cache, cache_data->session_id, cache_data);
}
- g_queue_push_tail (cache_data->session_tickets, g_bytes_ref (session_data));
- cache_data->last_used = g_get_monotonic_time ();
+ cache_data->last_used = time (NULL);
+
+ G_UNLOCK (session_cache_lock);
+}
+
+void
+g_tls_backend_gnutls_remove_session (unsigned int type,
+ GBytes *session_id)
+{
+ GHashTable *cache;
+
+ G_LOCK (session_cache_lock);
+
+ cache = get_session_cache (type, FALSE);
+ if (cache)
+ g_hash_table_remove (cache, session_id);
G_UNLOCK (session_cache_lock);
}
GBytes *
-g_tls_backend_gnutls_lookup_session_data (GBytes *session_id)
+g_tls_backend_gnutls_lookup_session (unsigned int type,
+ GBytes *session_id)
{
GTlsBackendGnutlsCacheData *cache_data;
GBytes *session_data = NULL;
@@ -252,17 +286,14 @@ g_tls_backend_gnutls_lookup_session_data (GBytes *session_id)
G_LOCK (session_cache_lock);
- cache = get_session_cache (FALSE);
+ cache = get_session_cache (type, FALSE);
if (cache)
{
cache_data = g_hash_table_lookup (cache, session_id);
if (cache_data)
{
- /* Note that session tickets should be used only once since TLS 1.3,
- * so we remove from the queue after retrieval. See RFC 8446 §C.4.
- */
- session_data = g_queue_pop_head (cache_data->session_tickets);
- cache_data->last_used = g_get_monotonic_time ();
+ cache_data->last_used = time (NULL);
+ session_data = g_bytes_ref (cache_data->session_data);
}
}
diff --git a/tls/gnutls/gtlsbackend-gnutls.h b/tls/gnutls/gtlsbackend-gnutls.h
index fb33361..7b92bf3 100644
--- a/tls/gnutls/gtlsbackend-gnutls.h
+++ b/tls/gnutls/gtlsbackend-gnutls.h
@@ -35,8 +35,12 @@ G_DECLARE_FINAL_TYPE (GTlsBackendGnutls, g_tls_backend_gnutls, G, TLS_BACKEND_GN
void g_tls_backend_gnutls_register (GIOModule *module);
-void g_tls_backend_gnutls_store_session_data (GBytes *session_id,
- GBytes *session_data);
-GBytes *g_tls_backend_gnutls_lookup_session_data (GBytes *session_id);
+void g_tls_backend_gnutls_store_session (unsigned int type,
+ GBytes *session_id,
+ GBytes *session_data);
+void g_tls_backend_gnutls_remove_session (unsigned int type,
+ GBytes *session_id);
+GBytes *g_tls_backend_gnutls_lookup_session (unsigned int type,
+ GBytes *session_id);
G_END_DECLS
diff --git a/tls/gnutls/gtlsclientconnection-gnutls.c b/tls/gnutls/gtlsclientconnection-gnutls.c
index 8061889..31104f1 100644
--- a/tls/gnutls/gtlsclientconnection-gnutls.c
+++ b/tls/gnutls/gtlsclientconnection-gnutls.c
@@ -52,15 +52,10 @@ struct _GTlsClientConnectionGnutls
GTlsCertificateFlags validation_flags;
GSocketConnectable *server_identity;
gboolean use_ssl3;
+ gboolean session_data_override;
- /* session_data is either the session ticket that was used to resume this
- * connection, or the most recent session ticket received from the server.
- * Because session ticket reuse is generally undesirable, it should only be
- * accessed if session_data_override is set.
- */
GBytes *session_id;
GBytes *session_data;
- gboolean session_data_override;
GPtrArray *accepted_cas;
gboolean accepted_cas_changed;
@@ -70,7 +65,7 @@ struct _GTlsClientConnectionGnutls
gnutls_privkey_t pkey;
};
-static void g_tls_client_connection_gnutls_initable_interface_init (GInitableIface *iface);
+static void g_tls_client_connection_gnutls_initable_interface_init (GInitableIface *iface);
static void g_tls_client_connection_gnutls_client_connection_interface_init (GTlsClientConnectionInterface
*iface);
static void g_tls_client_connection_gnutls_dtls_client_connection_interface_init
(GDtlsClientConnectionInterface *iface);
@@ -142,17 +137,12 @@ g_tls_client_connection_gnutls_compute_session_id (GTlsClientConnectionGnutls *g
if (g_test_initialized ())
return;
- /* Create a TLS "session ID." We base it on the IP address since
+ /* Create a TLS session ID. We base it on the IP address since
* different hosts serving the same hostname/service will probably
* not share the same session cache. We base it on the
* server-identity because at least some servers will fail (rather
* than just failing to resume the session) if we don't.
* (https://bugs.launchpad.net/bugs/823325)
- *
- * Note that our session IDs have no relation to TLS protocol
- * session IDs, e.g. as provided by gnutls_session_get_id2(). Unlike
- * our session IDs, actual TLS session IDs can no longer be used for
- * session resumption.
*/
g_object_get (G_OBJECT (gnutls), "base-io-stream", &base_conn, NULL);
if (G_IS_SOCKET_CONNECTION (base_conn))
@@ -201,32 +191,6 @@ g_tls_client_connection_gnutls_compute_session_id (GTlsClientConnectionGnutls *g
g_clear_object (&base_conn);
}
-static int
-handshake_thread_session_ticket_received_cb (gnutls_session_t session,
- guint htype,
- guint when,
- guint incoming,
- const gnutls_datum_t *msg)
-{
- GTlsClientConnectionGnutls *gnutls = G_TLS_CLIENT_CONNECTION_GNUTLS (gnutls_session_get_ptr (session));
- gnutls_datum_t session_datum;
-
- if (gnutls_session_get_data2 (session, &session_datum) == GNUTLS_E_SUCCESS)
- {
- g_clear_pointer (&gnutls->session_data, g_bytes_unref);
- gnutls->session_data = g_bytes_new_with_free_func (session_datum.data,
- session_datum.size,
- (GDestroyNotify)gnutls_free,
- session_datum.data);
-
- if (gnutls->session_id)
- g_tls_backend_gnutls_store_session_data (gnutls->session_id,
- gnutls->session_data);
- }
-
- return 0;
-}
-
static void
g_tls_client_connection_gnutls_finalize (GObject *object)
{
@@ -273,9 +237,6 @@ g_tls_client_connection_gnutls_initable_init (GInitable *initable,
g_free (normalized_hostname);
}
- gnutls_handshake_set_hook_function (session, GNUTLS_HANDSHAKE_NEW_SESSION_TICKET,
- GNUTLS_HOOK_POST, handshake_thread_session_ticket_received_cb);
-
return TRUE;
}
@@ -446,6 +407,21 @@ g_tls_client_connection_gnutls_handshake_thread_retrieve_function (gnutls_sessio
return 0;
}
+static void
+g_tls_client_connection_gnutls_clear_session_data (GTlsClientConnectionGnutls *gnutls)
+{
+ gnutls->session_data_override = FALSE;
+ g_clear_pointer (&gnutls->session_data, g_bytes_unref);
+ if (gnutls->session_id)
+ g_tls_backend_gnutls_remove_session (GNUTLS_CLIENT, gnutls->session_id);
+}
+
+static void
+g_tls_client_connection_gnutls_failed (GTlsConnectionGnutls *gnutls)
+{
+ g_tls_client_connection_gnutls_clear_session_data (G_TLS_CLIENT_CONNECTION_GNUTLS (gnutls));
+}
+
static void
g_tls_client_connection_gnutls_prepare_handshake (GTlsConnectionBase *tls,
gchar **advertised_protocols)
@@ -454,9 +430,9 @@ g_tls_client_connection_gnutls_prepare_handshake (GTlsConnectionBase *tls,
g_tls_client_connection_gnutls_compute_session_id (gnutls);
+ /* Try to get a cached session */
if (gnutls->session_data_override)
{
- g_assert (gnutls->session_data);
gnutls_session_set_data (g_tls_connection_gnutls_get_session (G_TLS_CONNECTION_GNUTLS (tls)),
g_bytes_get_data (gnutls->session_data, NULL),
g_bytes_get_size (gnutls->session_data));
@@ -465,14 +441,14 @@ g_tls_client_connection_gnutls_prepare_handshake (GTlsConnectionBase *tls,
{
GBytes *session_data;
- session_data = g_tls_backend_gnutls_lookup_session_data (gnutls->session_id);
+ session_data = g_tls_backend_gnutls_lookup_session (GNUTLS_CLIENT, gnutls->session_id);
if (session_data)
{
gnutls_session_set_data (g_tls_connection_gnutls_get_session (G_TLS_CONNECTION_GNUTLS (tls)),
g_bytes_get_data (session_data, NULL),
g_bytes_get_size (session_data));
g_clear_pointer (&gnutls->session_data, g_bytes_unref);
- gnutls->session_data = g_steal_pointer (&session_data);
+ gnutls->session_data = session_data;
}
}
@@ -486,6 +462,7 @@ g_tls_client_connection_gnutls_complete_handshake (GTlsConnectionBase *tls,
GError **error)
{
GTlsClientConnectionGnutls *gnutls = G_TLS_CLIENT_CONNECTION_GNUTLS (tls);
+ int resumed;
G_TLS_CONNECTION_BASE_CLASS (g_tls_client_connection_gnutls_parent_class)->complete_handshake (tls,
negotiated_protocol, error);
@@ -494,6 +471,28 @@ g_tls_client_connection_gnutls_complete_handshake (GTlsConnectionBase *tls,
*/
if (gnutls->accepted_cas_changed)
g_object_notify (G_OBJECT (gnutls), "accepted-cas");
+
+ resumed = gnutls_session_is_resumed (g_tls_connection_gnutls_get_session (G_TLS_CONNECTION_GNUTLS (tls)));
+ if (!resumed)
+ {
+ gnutls_datum_t session_datum;
+
+ g_tls_client_connection_gnutls_clear_session_data (G_TLS_CLIENT_CONNECTION_GNUTLS (tls));
+
+ if (gnutls_session_get_data2 (g_tls_connection_gnutls_get_session (G_TLS_CONNECTION_GNUTLS (tls)),
+ &session_datum) == 0)
+ {
+ gnutls->session_data = g_bytes_new_with_free_func (session_datum.data,
+ session_datum.size,
+ (GDestroyNotify)gnutls_free,
+ session_datum.data);
+
+ if (gnutls->session_id)
+ g_tls_backend_gnutls_store_session (GNUTLS_CLIENT,
+ gnutls->session_id,
+ gnutls->session_data);
+ }
+ }
}
static void
@@ -503,24 +502,16 @@ g_tls_client_connection_gnutls_copy_session_state (GTlsClientConnection *conn,
GTlsClientConnectionGnutls *gnutls = G_TLS_CLIENT_CONNECTION_GNUTLS (conn);
GTlsClientConnectionGnutls *gnutls_source = G_TLS_CLIENT_CONNECTION_GNUTLS (source);
- /* Precondition: source has handshaked, conn has not. */
- g_return_if_fail (!gnutls->session_id);
- g_return_if_fail (gnutls_source->session_id);
-
- /* Prefer to use a new session ticket, if possible. */
- gnutls->session_data = g_tls_backend_gnutls_lookup_session_data (gnutls_source->session_id);
-
- if (!gnutls->session_data && gnutls_source->session_data)
+ if (gnutls_source->session_data)
{
- /* If it's not possible, we'll try to reuse the old ticket, even though
- * this is a privacy risk since TLS 1.3. Applications should not use this
- * function unless they need us to try as hard as possible to resume a
- * session, even at the cost of privacy.
- */
+ gnutls->session_data_override = TRUE;
gnutls->session_data = g_bytes_ref (gnutls_source->session_data);
- }
- gnutls->session_data_override = !!gnutls->session_data;
+ if (gnutls->session_id)
+ g_tls_backend_gnutls_store_session (GNUTLS_CLIENT,
+ gnutls->session_id,
+ gnutls->session_data);
+ }
}
static void
@@ -528,6 +519,7 @@ g_tls_client_connection_gnutls_class_init (GTlsClientConnectionGnutlsClass *klas
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GTlsConnectionBaseClass *base_class = G_TLS_CONNECTION_BASE_CLASS (klass);
+ GTlsConnectionGnutlsClass *gnutls_class = G_TLS_CONNECTION_GNUTLS_CLASS (klass);
gobject_class->get_property = g_tls_client_connection_gnutls_get_property;
gobject_class->set_property = g_tls_client_connection_gnutls_set_property;
@@ -536,6 +528,8 @@ g_tls_client_connection_gnutls_class_init (GTlsClientConnectionGnutlsClass *klas
base_class->prepare_handshake = g_tls_client_connection_gnutls_prepare_handshake;
base_class->complete_handshake = g_tls_client_connection_gnutls_complete_handshake;
+ gnutls_class->failed = g_tls_client_connection_gnutls_failed;
+
g_object_class_override_property (gobject_class, PROP_VALIDATION_FLAGS, "validation-flags");
g_object_class_override_property (gobject_class, PROP_SERVER_IDENTITY, "server-identity");
g_object_class_override_property (gobject_class, PROP_USE_SSL3, "use-ssl3");
diff --git a/tls/gnutls/gtlsconnection-gnutls.c b/tls/gnutls/gtlsconnection-gnutls.c
index 51e8293..8f16523 100644
--- a/tls/gnutls/gtlsconnection-gnutls.c
+++ b/tls/gnutls/gtlsconnection-gnutls.c
@@ -478,7 +478,11 @@ end_gnutls_io (GTlsConnectionGnutls *gnutls,
#define END_GNUTLS_IO(gnutls, direction, ret, status, errmsg, err) \
status = end_gnutls_io (gnutls, direction, ret, err, errmsg); \
- } while (status == G_TLS_CONNECTION_BASE_TRY_AGAIN);
+ } while (status == G_TLS_CONNECTION_BASE_TRY_AGAIN); \
+ \
+ if (status == G_TLS_CONNECTION_BASE_ERROR && \
+ G_TLS_CONNECTION_GNUTLS_GET_CLASS (gnutls)-> failed) \
+ G_TLS_CONNECTION_GNUTLS_GET_CLASS (gnutls)->failed (gnutls);
static void
set_gnutls_error (GTlsConnectionGnutls *gnutls,
diff --git a/tls/gnutls/gtlsconnection-gnutls.h b/tls/gnutls/gtlsconnection-gnutls.h
index 55ae5ee..db3b726 100644
--- a/tls/gnutls/gtlsconnection-gnutls.h
+++ b/tls/gnutls/gtlsconnection-gnutls.h
@@ -39,6 +39,8 @@ G_DECLARE_DERIVABLE_TYPE (GTlsConnectionGnutls, g_tls_connection_gnutls, G, TLS_
struct _GTlsConnectionGnutlsClass
{
GTlsConnectionBaseClass parent_class;
+
+ void (*failed) (GTlsConnectionGnutls *tls);
};
gnutls_certificate_credentials_t g_tls_connection_gnutls_get_credentials (GTlsConnectionGnutls *connection);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]