[glib-networking/mcatanzaro/tls-thread: 22/26] progress



commit 3800a80c68f827942cc9aaa769e666a34f9042a0
Author: Michael Catanzaro <mcatanzaro gnome org>
Date:   Tue Dec 24 12:36:23 2019 -0600

    progress

 tls/base/gtlsconnection-base.c           |  8 +---
 tls/base/gtlsoperationsthread-base.c     | 47 +++++++--------------
 tls/base/gtlsoperationsthread-base.h     |  9 ++--
 tls/gnutls/gtlsoperationsthread-gnutls.c | 71 +++++++++++++++++++-------------
 4 files changed, 65 insertions(+), 70 deletions(-)
---
diff --git a/tls/base/gtlsconnection-base.c b/tls/base/gtlsconnection-base.c
index 4391625..a770db1 100644
--- a/tls/base/gtlsconnection-base.c
+++ b/tls/base/gtlsconnection-base.c
@@ -238,9 +238,6 @@ g_tls_connection_base_initable_init (GInitable    *initable,
   if (!priv->thread)
     return FALSE;
 
-  if (priv->certificate)
-    g_tls_operations_thread_base_set_own_certificate (priv->thread, priv->certificate);
-
   if (priv->interaction)
     g_tls_operations_thread_base_set_interaction (priv->thread, priv->interaction);
 
@@ -440,10 +437,6 @@ g_tls_connection_base_set_property (GObject      *object,
       if (priv->certificate)
         g_object_unref (priv->certificate);
       priv->certificate = g_value_dup_object (value);
-
-      if (priv->thread)
-        g_tls_operations_thread_base_set_own_certificate (priv->thread,
-                                                          priv->certificate);
       break;
 
     case PROP_INTERACTION:
@@ -1416,6 +1409,7 @@ handshake (GTlsConnectionBase  *tls,
   priv->started_handshake = TRUE;
 
   g_tls_operations_thread_base_handshake (priv->thread,
+                                          priv->certificate,
                                           (const gchar **)priv->advertised_protocols,
                                           auth_mode,
                                           timeout,
diff --git a/tls/base/gtlsoperationsthread-base.c b/tls/base/gtlsoperationsthread-base.c
index 46ead3b..0eecf58 100644
--- a/tls/base/gtlsoperationsthread-base.c
+++ b/tls/base/gtlsoperationsthread-base.c
@@ -81,13 +81,12 @@ typedef struct {
    * instead return data from the op thread to the calling thread using the op
    * struct.
    *
-   * TODO: some of this could move into the op struct?
+   * FIXME: what of this can move into the op struct?
    */
   GMutex mutex;
-  gchar *own_certificate_pem;
   GTlsInteraction *interaction;
   GError *interaction_error;
-  gboolean missing_requested_client_certificate;
+  gboolean missing_requested_client_certificate; /* FIXME: out parameter of handshake op? */
 } GTlsOperationsThreadBasePrivate;
 
 typedef enum {
@@ -112,6 +111,7 @@ struct _HandshakeContext
 
 typedef struct {
   HandshakeContext *context;
+  GTlsCertificate *own_certificate;
   gchar **advertised_protocols;
   GTlsAuthenticationMode auth_mode;
   gchar *negotiated_protocol;
@@ -182,33 +182,6 @@ g_tls_operations_thread_base_get_connection (GTlsOperationsThreadBase *self)
   return priv->connection;
 }
 
-void
-g_tls_operations_thread_base_set_own_certificate (GTlsOperationsThreadBase *self,
-                                                  GTlsCertificate          *cert)
-{
-  GTlsOperationsThreadBasePrivate *priv = g_tls_operations_thread_base_get_instance_private (self);
-
-  g_mutex_lock (&priv->mutex);
-  g_clear_pointer (&priv->own_certificate_pem, g_free);
-  g_object_get (cert,
-                "certificate-pem", &priv->own_certificate_pem,
-                NULL);
-  g_mutex_unlock (&priv->mutex);
-}
-
-gchar *
-g_tls_operations_thread_base_get_own_certificate_pem (GTlsOperationsThreadBase *self)
-{
-  GTlsOperationsThreadBasePrivate *priv = g_tls_operations_thread_base_get_instance_private (self);
-  gchar *copy;
-
-  g_mutex_lock (&priv->mutex);
-  copy = g_strdup (priv->own_certificate_pem);
-  g_mutex_unlock (&priv->mutex);
-
-  return copy;
-}
-
 void
 g_tls_operations_thread_base_set_interaction (GTlsOperationsThreadBase *self,
                                               GTlsInteraction          *interaction)
@@ -314,6 +287,7 @@ handshake_context_free (HandshakeContext *context)
 
 static HandshakeData *
 handshake_data_new (HandshakeContext        *context,
+                    GTlsCertificate         *own_certificate,
                     const gchar            **advertised_protocols,
                     GTlsAuthenticationMode   mode)
 {
@@ -321,6 +295,7 @@ handshake_data_new (HandshakeContext        *context,
 
   data = g_new0 (HandshakeData, 1);
   data->context = context;
+  data->own_certificate = own_certificate ? g_object_ref (own_certificate) : NULL;
   data->advertised_protocols = g_strdupv ((gchar **)advertised_protocols);
   data->auth_mode = mode;
 
@@ -332,6 +307,7 @@ handshake_data_free (HandshakeData *data)
 {
   g_strfreev (data->advertised_protocols);
 
+  g_clear_object (&data->own_certificate);
   g_clear_object (&data->peer_certificate);
 
   g_assert (!data->accepted_cas);
@@ -381,6 +357,7 @@ g_tls_thread_set_server_identity_operation_new (GTlsOperationsThreadBase *thread
 static GTlsThreadOperation *
 g_tls_thread_handshake_operation_new (GTlsOperationsThreadBase  *thread,
                                       HandshakeContext          *context,
+                                      GTlsCertificate           *own_certificate,
                                       GTlsConnectionBase        *connection,
                                       const gchar              **advertised_protocols,
                                       GTlsAuthenticationMode     auth_mode,
@@ -398,6 +375,7 @@ g_tls_thread_handshake_operation_new (GTlsOperationsThreadBase  *thread,
   op->cancellable = cancellable;
 
   op->handshake_data = handshake_data_new (context,
+                                           own_certificate,
                                            advertised_protocols,
                                            auth_mode);
 
@@ -719,6 +697,7 @@ g_tls_operations_thread_base_verify_certificate (GTlsOperationsThreadBase *self,
 
 GTlsConnectionBaseStatus
 g_tls_operations_thread_base_handshake (GTlsOperationsThreadBase   *self,
+                                        GTlsCertificate            *own_certificate,
                                         const gchar               **advertised_protocols,
                                         GTlsAuthenticationMode      auth_mode,
                                         gint64                      timeout,
@@ -733,6 +712,7 @@ g_tls_operations_thread_base_handshake (GTlsOperationsThreadBase   *self,
   GTlsOperationsThreadBasePrivate *priv = g_tls_operations_thread_base_get_instance_private (self);
   GTlsConnectionBaseStatus status;
   GTlsThreadOperation *op;
+  GTlsCertificate *copied_cert;
   HandshakeContext *context;
 
   g_assert (!g_main_context_is_owner (priv->op_thread_context));
@@ -744,8 +724,12 @@ g_tls_operations_thread_base_handshake (GTlsOperationsThreadBase   *self,
   context = handshake_context_new (verify_callback,
                                    user_data);
 
+  copied_cert = G_TLS_OPERATIONS_THREAD_BASE_GET_CLASS (self)->copy_certificate (self,
+                                                                                 own_certificate);
+
   op = g_tls_thread_handshake_operation_new (self,
                                              context,
+                                             copied_cert,
                                              priv->connection,
                                              advertised_protocols,
                                              auth_mode,
@@ -762,6 +746,7 @@ g_tls_operations_thread_base_handshake (GTlsOperationsThreadBase   *self,
 
   handshake_context_free (context);
   g_tls_thread_operation_free (op);
+  g_object_unref (copied_cert);
 
   return status;
 }
@@ -1216,6 +1201,7 @@ process_op (GAsyncQueue         *queue,
     case G_TLS_THREAD_OP_HANDSHAKE:
       op->result = base_class->handshake_fn (op->thread,
                                              op->handshake_data->context,
+                                             op->handshake_data->own_certificate,
                                              (const gchar **)op->handshake_data->advertised_protocols,
                                              op->handshake_data->auth_mode,
                                              op->timeout,
@@ -1430,7 +1416,6 @@ g_tls_operations_thread_base_finalize (GObject *object)
 
   g_mutex_clear (&priv->mutex);
 
-  g_clear_pointer (&priv->own_certificate_pem, g_free);
   g_clear_object (&priv->interaction);
   g_clear_error (&priv->interaction_error);
 
diff --git a/tls/base/gtlsoperationsthread-base.h b/tls/base/gtlsoperationsthread-base.h
index 3ecd5fd..7d390fa 100644
--- a/tls/base/gtlsoperationsthread-base.h
+++ b/tls/base/gtlsoperationsthread-base.h
@@ -40,6 +40,9 @@ struct _GTlsOperationsThreadBaseClass
 {
   GObjectClass parent_class;
 
+  GTlsCertificate            *(*copy_certificate)           (GTlsOperationsThreadBase  *self,
+                                                             GTlsCertificate           *cert);
+
   void                        (*copy_client_session_state)  (GTlsOperationsThreadBase  *self,
                                                              GTlsOperationsThreadBase  *source);
 
@@ -48,6 +51,7 @@ struct _GTlsOperationsThreadBaseClass
 
   GTlsConnectionBaseStatus    (*handshake_fn)               (GTlsOperationsThreadBase  *self,
                                                              HandshakeContext          *context,
+                                                             GTlsCertificate           *own_certificate,
                                                              const gchar              **advertised_protocols,
                                                              GTlsAuthenticationMode     auth_mode,
                                                              gint64                     timeout,
@@ -98,10 +102,6 @@ typedef void     (*GTlsSessionResumedFunc)    (GTlsOperationsThreadBase *thread,
 /* FIXME: remove!!! */
 GTlsConnectionBase       *g_tls_operations_thread_base_get_connection            (GTlsOperationsThreadBase   
*self);
 
-void                      g_tls_operations_thread_base_set_own_certificate       (GTlsOperationsThreadBase   
*self,
-                                                                                  GTlsCertificate            
*cert);
-gchar                    *g_tls_operations_thread_base_get_own_certificate_pem   (GTlsOperationsThreadBase   
*self);
-
 void                      g_tls_operations_thread_base_set_interaction           (GTlsOperationsThreadBase   
*self,
                                                                                   GTlsInteraction            
*interaction);
 GTlsInteraction          *g_tls_operations_thread_base_ref_interaction           (GTlsOperationsThreadBase   
*self);
@@ -126,6 +126,7 @@ void                      g_tls_operations_thread_base_set_server_identity
                                                                                   const gchar                
*server_identity);
 
 GTlsConnectionBaseStatus  g_tls_operations_thread_base_handshake                 (GTlsOperationsThreadBase   
*self,
+                                                                                  GTlsCertificate            
*own_certificate,
                                                                                   const gchar               
**advertised_protocols,
                                                                                   GTlsAuthenticationMode     
 auth_mode,
                                                                                   gint64                     
 timeout,
diff --git a/tls/gnutls/gtlsoperationsthread-gnutls.c b/tls/gnutls/gtlsoperationsthread-gnutls.c
index 39185eb..319498a 100644
--- a/tls/gnutls/gtlsoperationsthread-gnutls.c
+++ b/tls/gnutls/gtlsoperationsthread-gnutls.c
@@ -63,15 +63,17 @@ struct _GTlsOperationsThreadGnutls {
   gboolean                 handshaking;
   gboolean                 ever_handshaked;
 
+  /* Valid only during current operation */
+  GTlsCertificate         *own_certificate;
+  GTlsCertificate         *peer_certificate;
   GCancellable            *op_cancellable;
   GError                  *op_error;
 
+  /* Certificate internals, must be kept alive here. */
   gnutls_pcert_st         *pcert;
   unsigned int             pcert_length;
   gnutls_privkey_t         pkey;
 
-  GTlsCertificate         *peer_certificate;
-
   GList                   *accepted_cas;
 
   gchar                   *server_identity;
@@ -319,6 +321,17 @@ initialize_gnutls_priority (void)
     g_warning ("Failed to set GnuTLS session priority with error beginning at %s: %s", error_pos, 
gnutls_strerror (ret));
 }
 
+static GTlsCertificate *
+g_tls_operations_thread_gnutls_copy_certificate (GTlsOperationsThreadBase *base,
+                                                 GTlsCertificate          *cert)
+{
+  /* FIXME: need a real copy to avoid sharing the certificate across threads.
+   * Copy must copy private key. Must copy ENTIRE CHAIN including issuers.
+   */
+
+  return cert ? g_object_ref (cert) : NULL;
+}
+
 static void
 g_tls_operations_thread_gnutls_copy_client_session_state (GTlsOperationsThreadBase *base,
                                                           GTlsOperationsThreadBase *base_source)
@@ -465,7 +478,6 @@ compute_session_id (GTlsOperationsThreadGnutls *self)
           const gchar *server_hostname;
           gchar *addrstr;
           gchar *session_id;
-          gchar *pem;
           gchar *cert_hash = NULL;
 
           iaddr = g_inet_socket_address_get_address (isaddr);
@@ -478,11 +490,17 @@ compute_session_id (GTlsOperationsThreadGnutls *self)
            * that different connections to the same server can use different
            * certificates.
            */
-          pem = g_tls_operations_thread_base_get_own_certificate_pem (G_TLS_OPERATIONS_THREAD_BASE (self));
-          if (pem)
+          if (self->own_certificate)
             {
-              cert_hash = g_compute_checksum_for_string (G_CHECKSUM_SHA256, pem, -1);
-              g_free (pem);
+              GByteArray *der = NULL;
+              g_object_get (self->own_certificate,
+                            "certificate", &der,
+                            NULL);
+              if (der)
+                {
+                  cert_hash = g_compute_checksum_for_data (G_CHECKSUM_SHA256, der->data, der->len);
+                  g_byte_array_unref (der);
+                }
             }
 
           session_id = g_strdup_printf ("%s/%s/%d/%s", addrstr,
@@ -569,6 +587,7 @@ get_peer_certificate (GTlsOperationsThreadGnutls *self)
 static GTlsConnectionBaseStatus
 g_tls_operations_thread_gnutls_handshake (GTlsOperationsThreadBase  *base,
                                           HandshakeContext          *context,
+                                          GTlsCertificate           *own_certificate,
                                           const gchar              **advertised_protocols,
                                           GTlsAuthenticationMode     auth_mode,
                                           gint64                     timeout,
@@ -583,7 +602,7 @@ g_tls_operations_thread_gnutls_handshake (GTlsOperationsThreadBase  *base,
   gnutls_datum_t protocol;
   int ret;
 
-  g_clear_object (&self->peer_certificate);
+  self->own_certificate = g_steal_pointer (&own_certificate);
 
   if (!self->ever_handshaked)
     set_handshake_priority (self);
@@ -626,6 +645,8 @@ g_tls_operations_thread_gnutls_handshake (GTlsOperationsThreadBase  *base,
   self->handshaking = FALSE;
   self->ever_handshaked = TRUE;
 
+  g_clear_object (&self->own_certificate);
+
   if (gnutls_alpn_get_selected_protocol (self->session, &protocol) == 0 && protocol.size > 0)
     *negotiated_protocol = g_strndup ((gchar *)protocol.data, protocol.size);
   else
@@ -1209,7 +1230,7 @@ pin_request_cb (void         *userdata,
 }
 
 static void
-clear_gnutls_certificate_copy (GTlsOperationsThreadGnutls *self)
+clear_own_certificate_internals (GTlsOperationsThreadGnutls *self)
 {
   g_tls_certificate_gnutls_copy_free (self->pcert, self->pcert_length, self->pkey);
 
@@ -1219,28 +1240,20 @@ clear_gnutls_certificate_copy (GTlsOperationsThreadGnutls *self)
 }
 
 static void
-get_own_certificate (GTlsOperationsThreadGnutls  *self,
-                     gnutls_pcert_st            **pcert,
-                     unsigned int                *pcert_length,
-                     gnutls_privkey_t            *pkey)
+get_gnutls_certificate_internals (GTlsOperationsThreadGnutls  *self,
+                                  gnutls_pcert_st            **pcert,
+                                  unsigned int                *pcert_length,
+                                  gnutls_privkey_t            *pkey)
 {
-  char *pem;
-  GTlsCertificate *cert = NULL;
-
-  pem = g_tls_operations_thread_base_get_own_certificate_pem (G_TLS_OPERATIONS_THREAD_BASE (self));
-  if (pem)
-    {
-      cert = g_tls_certificate_new_from_pem (pem, -1, NULL);
-      g_free (pem);
-    }
+  clear_own_certificate_internals (self);
 
-  if (cert)
+  if (self->own_certificate)
     {
       gnutls_privkey_t privkey;
       gnutls_privkey_init (&privkey);
       gnutls_privkey_set_pin_function (privkey, pin_request_cb, self);
 
-      g_tls_certificate_gnutls_copy (G_TLS_CERTIFICATE_GNUTLS (cert),
+      g_tls_certificate_gnutls_copy (G_TLS_CERTIFICATE_GNUTLS (self->own_certificate),
                                      self->interaction_id,
                                      pcert, pcert_length, &privkey);
       *pkey = privkey;
@@ -1289,8 +1302,8 @@ retrieve_certificate_cb (gnutls_session_t              session,
       self->accepted_cas = g_list_reverse (self->accepted_cas);
     }
 
-  clear_gnutls_certificate_copy (self);
-  get_own_certificate (self, pcert, pcert_length, pkey);
+  clear_own_certificate_internals (self);
+  get_gnutls_certificate_internals (self, pcert, pcert_length, pkey);
 
   if (is_client (self))
     {
@@ -1300,7 +1313,7 @@ retrieve_certificate_cb (gnutls_session_t              session,
 
           if (g_tls_operations_thread_base_request_certificate (G_TLS_OPERATIONS_THREAD_BASE (self),
                                                                 self->op_cancellable))
-            get_own_certificate (self, pcert, pcert_length, pkey);
+            get_gnutls_certificate_internals (self, pcert, pcert_length, pkey);
 
           if (*pcert_length == 0)
             {
@@ -1437,7 +1450,7 @@ g_tls_operations_thread_gnutls_finalize (GObject *object)
   g_clear_object (&self->base_iostream);
   g_clear_object (&self->base_socket);
 
-  clear_gnutls_certificate_copy (self);
+  clear_own_certificate_internals (self);
 
   if (self->accepted_cas)
     {
@@ -1446,6 +1459,7 @@ g_tls_operations_thread_gnutls_finalize (GObject *object)
     }
 
   g_assert (!self->peer_certificate);
+  g_assert (!self->own_certificate);
 
   g_assert (!self->op_cancellable);
   g_assert (!self->op_error);
@@ -1538,6 +1552,7 @@ g_tls_operations_thread_gnutls_class_init (GTlsOperationsThreadGnutlsClass *klas
   gobject_class->get_property  = g_tls_operations_thread_gnutls_get_property;
   gobject_class->set_property  = g_tls_operations_thread_gnutls_set_property;
 
+  base_class->copy_certificate          = g_tls_operations_thread_gnutls_copy_certificate;
   base_class->copy_client_session_state = g_tls_operations_thread_gnutls_copy_client_session_state;
   base_class->set_server_identity       = g_tls_operations_thread_gnutls_set_server_identity;
   base_class->handshake_fn              = g_tls_operations_thread_gnutls_handshake;


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