[glib-networking/mcatanzaro/notify-accepted-cas: 3/3] Don't notify accepted-cas property on handshake thread



commit a5edbfce8e87f915679032782dcee85369e23a53
Author: Michael Catanzaro <mcatanzaro gnome org>
Date:   Fri Sep 20 12:51:42 2019 -0500

    Don't notify accepted-cas property on handshake thread
    
    This is wrong because application code could wind up running on our
    internal thread if it connects to the notify.
    
    Fixes #95

 tls/gnutls/gtlsclientconnection-gnutls.c   | 16 +++++++++++++---
 tls/openssl/gtlsclientconnection-openssl.c | 22 +++++++++++++++++++++-
 2 files changed, 34 insertions(+), 4 deletions(-)
---
diff --git a/tls/gnutls/gtlsclientconnection-gnutls.c b/tls/gnutls/gtlsclientconnection-gnutls.c
index 384df22..4e2f5b7 100644
--- a/tls/gnutls/gtlsclientconnection-gnutls.c
+++ b/tls/gnutls/gtlsclientconnection-gnutls.c
@@ -58,6 +58,7 @@ struct _GTlsClientConnectionGnutls
   GBytes *session_data;
 
   GPtrArray *accepted_cas;
+  gboolean accepted_cas_changed;
 
   gnutls_pcert_st *pcert;
   unsigned int pcert_length;
@@ -326,6 +327,7 @@ g_tls_client_connection_gnutls_retrieve_function (gnutls_session_t
   GTlsClientConnectionGnutls *gnutls = gnutls_transport_get_ptr (session);
   GTlsConnectionGnutls *conn = G_TLS_CONNECTION_GNUTLS (gnutls);
   GPtrArray *accepted_cas;
+  gboolean had_accepted_cas;
   GByteArray *dn;
   int i;
 
@@ -333,6 +335,8 @@ g_tls_client_connection_gnutls_retrieve_function (gnutls_session_t
    * the algorithms given in pk_algos.
    */
 
+  had_accepted_cas = gnutls->accepted_cas != NULL;
+
   accepted_cas = g_ptr_array_new_with_free_func ((GDestroyNotify)g_byte_array_unref);
   for (i = 0; i < nreqs; i++)
     {
@@ -344,7 +348,8 @@ g_tls_client_connection_gnutls_retrieve_function (gnutls_session_t
   if (gnutls->accepted_cas)
     g_ptr_array_unref (gnutls->accepted_cas);
   gnutls->accepted_cas = accepted_cas;
-  g_object_notify (G_OBJECT (gnutls), "accepted-cas");
+
+  gnutls->accepted_cas_changed = gnutls->accepted_cas || had_accepted_cas;
 
   clear_gnutls_certificate_copy (gnutls);
   g_tls_connection_gnutls_get_certificate (conn, pcert, pcert_length, pkey);
@@ -445,8 +450,13 @@ g_tls_client_connection_gnutls_complete_handshake (GTlsConnectionBase  *tls,
   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);
+  G_TLS_CONNECTION_BASE_CLASS (g_tls_client_connection_gnutls_parent_class)->complete_handshake (tls, 
negotiated_protocol, error);
+
+  /* It may have changed during the handshake, but we have to wait until here
+   * because we can't emit notifies on the handshake thread.
+   */
+  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)
diff --git a/tls/openssl/gtlsclientconnection-openssl.c b/tls/openssl/gtlsclientconnection-openssl.c
index 3926029..06fbd5d 100644
--- a/tls/openssl/gtlsclientconnection-openssl.c
+++ b/tls/openssl/gtlsclientconnection-openssl.c
@@ -52,6 +52,7 @@ struct _GTlsClientConnectionOpenssl
   GBytes *session_data;
 
   STACK_OF (X509_NAME) *ca_list;
+  gboolean ca_list_changed;
 
   SSL_SESSION *session;
   SSL *ssl;
@@ -235,6 +236,22 @@ g_tls_client_connection_openssl_constructed (GObject *object)
   G_OBJECT_CLASS (g_tls_client_connection_openssl_parent_class)->constructed (object);
 }
 
+static void
+g_tls_client_connection_openssl_complete_handshake (GTlsConnectionBase  *tls,
+                                                    gchar              **negotiated_protocol,
+                                                    GError             **error)
+{
+  GTlsClientConnectionOpenssl *client = G_TLS_CLIENT_CONNECTION_OPENSSL (tls);
+
+  G_TLS_CONNECTION_BASE_CLASS (g_tls_client_connection_openssl_parent_class)->complete_handshake (tls, 
negotiated_protocol, error);
+
+  /* It may have changed during the handshake, but we have to wait until here
+   * because we can't emit notifies on the handshake thread.
+   */
+  if (client->ca_list_changed)
+    g_object_notify (G_OBJECT (client), "accepted-cas");
+}
+
 static GTlsCertificateFlags
 verify_ocsp_response (GTlsClientConnectionOpenssl *openssl,
                       GTlsCertificate             *peer_certificate)
@@ -303,6 +320,7 @@ g_tls_client_connection_openssl_class_init (GTlsClientConnectionOpensslClass *kl
   gobject_class->set_property         = g_tls_client_connection_openssl_set_property;
   gobject_class->constructed          = g_tls_client_connection_openssl_constructed;
 
+  base_class->complete_handshake      = g_tls_client_connection_openssl_complete_handshake;
   base_class->verify_peer_certificate = g_tls_client_connection_openssl_verify_peer_certificate;
 
   openssl_class->get_ssl              = g_tls_client_connection_openssl_get_ssl;
@@ -341,12 +359,14 @@ retrieve_certificate (SSL       *ssl,
   GTlsClientConnectionOpenssl *client;
   GTlsConnectionBase *tls;
   GTlsCertificate *cert;
+  gboolean had_ca_list;
 
   client = SSL_get_ex_data (ssl, data_index);
   tls = G_TLS_CONNECTION_BASE (client);
 
+  had_ca_list = client->ca_list != NULL;
   client->ca_list = SSL_get_client_CA_list (client->ssl);
-  g_object_notify (G_OBJECT (client), "accepted-cas");
+  client->ca_list_changed = client->ca_list || had_ca_list;
 
   cert = g_tls_connection_get_certificate (G_TLS_CONNECTION (client));
   if (!cert)


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]