[glib-networking] Use gnutls_certificate_set_retrieve_function2()



commit c158d7f51284a6f5ac50f0b02a833893b69509fa
Author: Michael Catanzaro <mcatanzaro igalia com>
Date:   Mon Feb 26 13:18:41 2018 -0600

    Use gnutls_certificate_set_retrieve_function2()
    
    The GnuTLS manual says this is significantly more efficient than using
    gnutls_certificate_set_retrieve_function(). It certainly is a bit safer.
    It's easy to forget to initialize a member of the gnutls_retr2_st, but
    harder to forget about function parameters.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=793712

 tls/gnutls/gtlscertificate-gnutls-pkcs11.c |   28 ++++++++-----
 tls/gnutls/gtlscertificate-gnutls.c        |   59 +++++++++++++++++++---------
 tls/gnutls/gtlscertificate-gnutls.h        |   13 ++++--
 tls/gnutls/gtlsclientconnection-gnutls.c   |   47 +++++++++++-----------
 tls/gnutls/gtlsconnection-gnutls.c         |   22 +++++++---
 tls/gnutls/gtlsconnection-gnutls.h         |    5 ++-
 tls/gnutls/gtlsserverconnection-gnutls.c   |   33 +++++++++-------
 7 files changed, 128 insertions(+), 79 deletions(-)
---
diff --git a/tls/gnutls/gtlscertificate-gnutls-pkcs11.c b/tls/gnutls/gtlscertificate-gnutls-pkcs11.c
index ae02982..58c7e4f 100644
--- a/tls/gnutls/gtlscertificate-gnutls-pkcs11.c
+++ b/tls/gnutls/gtlscertificate-gnutls-pkcs11.c
@@ -115,31 +115,37 @@ g_tls_certificate_gnutls_pkcs11_init (GTlsCertificateGnutlsPkcs11 *self)
 static void
 g_tls_certificate_gnutls_pkcs11_copy (GTlsCertificateGnutls    *gnutls,
                                       const gchar              *interaction_id,
-                                      gnutls_retr2_st          *st)
+                                      gnutls_pcert_st         **pcert,
+                                      unsigned int             *pcert_length,
+                                      gnutls_privkey_t         *pkey)
 {
   GTlsCertificateGnutlsPkcs11 *self = G_TLS_CERTIFICATE_GNUTLS_PKCS11 (gnutls);
   gchar *uri;
 
-  st->key.x509 = NULL;
-
   /* Let the base class copy certificate in */
   G_TLS_CERTIFICATE_GNUTLS_CLASS (g_tls_certificate_gnutls_pkcs11_parent_class)->copy (gnutls,
                                                                                        interaction_id,
-                                                                                       st);
-
-  /* This is the allocation behavior we expect from base class */
-  g_assert (st->deinit_all);
+                                                                                       pcert,
+                                                                                       pcert_length,
+                                                                                       pkey);
 
   /* If the base class somehow put a key in, then respect that */
-  if (st->key.x509 == NULL)
+  if (*pkey == NULL)
     {
       uri = g_tls_certificate_gnutls_pkcs11_build_private_key_uri (self, interaction_id);
       if (uri != NULL)
         {
-          gnutls_pkcs11_privkey_init (&st->key.pkcs11);
-          gnutls_pkcs11_privkey_import_url (st->key.pkcs11, uri, GNUTLS_PKCS11_URL_GENERIC);
-          st->key_type = GNUTLS_PRIVKEY_PKCS11;
+          gnutls_pkcs11_privkey_t pkcs11_privkey;
+          gnutls_privkey_t privkey;
+
+          gnutls_pkcs11_privkey_init (&pkcs11_privkey);
+          gnutls_pkcs11_privkey_import_url (pkcs11_privkey, uri, GNUTLS_PKCS11_URL_GENERIC);
           g_free (uri);
+
+          gnutls_privkey_init (&privkey);
+          gnutls_privkey_import_pkcs11 (privkey, pkcs11_privkey, GNUTLS_PRIVKEY_IMPORT_COPY);
+          *pkey = privkey;
+          gnutls_pkcs11_privkey_deinit (pkcs11_privkey);
         }
     }
 }
diff --git a/tls/gnutls/gtlscertificate-gnutls.c b/tls/gnutls/gtlscertificate-gnutls.c
index 95b8093..d5545b3 100644
--- a/tls/gnutls/gtlscertificate-gnutls.c
+++ b/tls/gnutls/gtlscertificate-gnutls.c
@@ -389,11 +389,11 @@ g_tls_certificate_gnutls_verify (GTlsCertificate     *cert,
 static void
 g_tls_certificate_gnutls_real_copy (GTlsCertificateGnutls    *gnutls,
                                     const gchar              *interaction_id,
-                                    gnutls_retr2_st          *st)
+                                    gnutls_pcert_st         **pcert,
+                                    unsigned int             *pcert_length,
+                                    gnutls_privkey_t         *pkey)
 {
   GTlsCertificateGnutls *chain;
-  gnutls_x509_crt_t cert;
-  gnutls_datum_t data;
   guint num_certs = 0;
   size_t size = 0;
   int status;
@@ -409,15 +409,18 @@ g_tls_certificate_gnutls_real_copy (GTlsCertificateGnutls    *gnutls,
       chain = priv->issuer;
     }
 
-  st->ncerts = 0;
-  st->cert_type = GNUTLS_CRT_X509;
-  st->cert.x509 = gnutls_malloc (sizeof (gnutls_x509_crt_t) * num_certs);
+  *pcert_length = 0;
+  *pcert = gnutls_malloc (sizeof (gnutls_pcert_st) * num_certs);
+  if (*pcert == NULL)
+    g_error ("%s: out of memory", __FUNCTION__);
 
   /* Now do the actual copy of the whole chain. */
   chain = gnutls;
   while (chain != NULL)
     {
       GTlsCertificateGnutlsPrivate *priv = g_tls_certificate_gnutls_get_instance_private (chain);
+      gnutls_x509_crt_t cert;
+      gnutls_datum_t data;
 
       gnutls_x509_crt_export (priv->cert, GNUTLS_X509_FMT_DER,
                               NULL, &size);
@@ -431,8 +434,9 @@ g_tls_certificate_gnutls_real_copy (GTlsCertificateGnutls    *gnutls,
       g_warn_if_fail (status == 0);
       g_free (data.data);
 
-      st->cert.x509[st->ncerts] = cert;
-      st->ncerts++;
+      gnutls_pcert_import_x509 (*pcert + *pcert_length, cert, 0);
+      gnutls_x509_crt_deinit (cert);
+      (*pcert_length)++;
 
       chain = priv->issuer;
     }
@@ -442,14 +446,22 @@ g_tls_certificate_gnutls_real_copy (GTlsCertificateGnutls    *gnutls,
 
       if (priv->key != NULL)
         {
-          gnutls_x509_privkey_init (&st->key.x509);
-          gnutls_x509_privkey_cpy (st->key.x509, priv->key);
-        }
+          gnutls_x509_privkey_t x509_privkey;
+          gnutls_privkey_t privkey;
 
-      st->key_type = GNUTLS_PRIVKEY_X509;
-    }
+          gnutls_x509_privkey_init (&x509_privkey);
+          gnutls_x509_privkey_cpy (x509_privkey, priv->key);
 
-  st->deinit_all = TRUE;
+          gnutls_privkey_init (&privkey);
+          gnutls_privkey_import_x509 (privkey, x509_privkey, GNUTLS_PRIVKEY_IMPORT_COPY);
+          *pkey = privkey;
+          gnutls_x509_privkey_deinit (x509_privkey);
+        }
+      else
+        {
+          *pkey = NULL;
+        }
+    }
 }
 
 static void
@@ -524,14 +536,23 @@ g_tls_certificate_gnutls_has_key (GTlsCertificateGnutls *gnutls)
 }
 
 void
-g_tls_certificate_gnutls_copy  (GTlsCertificateGnutls *gnutls,
-                                const gchar           *interaction_id,
-                                gnutls_retr2_st       *st)
+g_tls_certificate_gnutls_copy  (GTlsCertificateGnutls  *gnutls,
+                                const gchar            *interaction_id,
+                                gnutls_pcert_st       **pcert,
+                                unsigned int           *pcert_length,
+                                gnutls_privkey_t       *pkey)
 {
   g_return_if_fail (G_IS_TLS_CERTIFICATE_GNUTLS (gnutls));
-  g_return_if_fail (st != NULL);
+  g_return_if_fail (pcert != NULL);
+  g_return_if_fail (pcert_length != NULL);
+  g_return_if_fail (pkey != NULL);
   g_return_if_fail (G_TLS_CERTIFICATE_GNUTLS_GET_CLASS (gnutls)->copy);
-  G_TLS_CERTIFICATE_GNUTLS_GET_CLASS (gnutls)->copy (gnutls, interaction_id, st);
+
+  G_TLS_CERTIFICATE_GNUTLS_GET_CLASS (gnutls)->copy (gnutls,
+                                                     interaction_id,
+                                                     pcert,
+                                                     pcert_length,
+                                                     pkey);
 }
 
 static const struct {
diff --git a/tls/gnutls/gtlscertificate-gnutls.h b/tls/gnutls/gtlscertificate-gnutls.h
index a6450ec..569b3db 100644
--- a/tls/gnutls/gtlscertificate-gnutls.h
+++ b/tls/gnutls/gtlscertificate-gnutls.h
@@ -26,6 +26,7 @@
 #define __G_TLS_CERTIFICATE_GNUTLS_H__
 
 #include <gio/gio.h>
+#include <gnutls/abstract.h>
 #include <gnutls/gnutls.h>
 
 G_BEGIN_DECLS
@@ -40,7 +41,9 @@ struct _GTlsCertificateGnutlsClass
 
   void              (*copy)               (GTlsCertificateGnutls    *gnutls,
                                            const gchar              *interaction_id,
-                                           gnutls_retr2_st          *st);
+                                           gnutls_pcert_st         **pcert,
+                                           unsigned int             *pcert_length,
+                                           gnutls_privkey_t         *pkey);
 };
 
 GTlsCertificate *            g_tls_certificate_gnutls_new             (const gnutls_datum_t  *datum,
@@ -54,9 +57,11 @@ void                         g_tls_certificate_gnutls_set_data        (GTlsCerti
 const gnutls_x509_crt_t      g_tls_certificate_gnutls_get_cert        (GTlsCertificateGnutls *gnutls);
 gboolean                     g_tls_certificate_gnutls_has_key         (GTlsCertificateGnutls *gnutls);
 
-void                         g_tls_certificate_gnutls_copy            (GTlsCertificateGnutls *gnutls,
-                                                                       const gchar           *interaction_id,
-                                                                       gnutls_retr2_st       *st);
+void                         g_tls_certificate_gnutls_copy            (GTlsCertificateGnutls  *gnutls,
+                                                                       const gchar            
*interaction_id,
+                                                                       gnutls_pcert_st       **pcert,
+                                                                       unsigned int           *pcert_length,
+                                                                       gnutls_privkey_t       *pkey);
 
 GTlsCertificateFlags         g_tls_certificate_gnutls_verify_identity (GTlsCertificateGnutls *gnutls,
                                                                        GSocketConnectable    *identity);
diff --git a/tls/gnutls/gtlsclientconnection-gnutls.c b/tls/gnutls/gtlsclientconnection-gnutls.c
index f0fa94e..a32ea43 100644
--- a/tls/gnutls/gtlsclientconnection-gnutls.c
+++ b/tls/gnutls/gtlsclientconnection-gnutls.c
@@ -66,12 +66,14 @@ static void     g_tls_client_connection_gnutls_initable_interface_init (GInitabl
 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);
 
-static int g_tls_client_connection_gnutls_retrieve_function (gnutls_session_t             session,
-                                                             const gnutls_datum_t        *req_ca_rdn,
-                                                             int                          nreqs,
-                                                             const gnutls_pk_algorithm_t *pk_algos,
-                                                             int                          pk_algos_length,
-                                                             gnutls_retr2_st             *st);
+static int g_tls_client_connection_gnutls_retrieve_function (gnutls_session_t              session,
+                                                             const gnutls_datum_t         *req_ca_rdn,
+                                                             int                           nreqs,
+                                                             const gnutls_pk_algorithm_t  *pk_algos,
+                                                             int                           pk_algos_length,
+                                                             gnutls_pcert_st             **pcert,
+                                                             unsigned int                 *pcert_length,
+                                                             gnutls_privkey_t             *pkey);
 
 static GInitableIface *g_tls_client_connection_gnutls_parent_initable_iface;
 
@@ -90,7 +92,7 @@ g_tls_client_connection_gnutls_init (GTlsClientConnectionGnutls *gnutls)
   gnutls_certificate_credentials_t creds;
 
   creds = g_tls_connection_gnutls_get_credentials (G_TLS_CONNECTION_GNUTLS (gnutls));
-  gnutls_certificate_set_retrieve_function (creds, g_tls_client_connection_gnutls_retrieve_function);
+  gnutls_certificate_set_retrieve_function2 (creds, g_tls_client_connection_gnutls_retrieve_function);
 }
 
 static const gchar *
@@ -291,12 +293,14 @@ g_tls_client_connection_gnutls_set_property (GObject      *object,
 }
 
 static int
-g_tls_client_connection_gnutls_retrieve_function (gnutls_session_t             session,
-                                                  const gnutls_datum_t        *req_ca_rdn,
-                                                  int                          nreqs,
-                                                  const gnutls_pk_algorithm_t *pk_algos,
-                                                  int                          pk_algos_length,
-                                                  gnutls_retr2_st             *st)
+g_tls_client_connection_gnutls_retrieve_function (gnutls_session_t              session,
+                                                  const gnutls_datum_t         *req_ca_rdn,
+                                                  int                           nreqs,
+                                                  const gnutls_pk_algorithm_t  *pk_algos,
+                                                  int                           pk_algos_length,
+                                                  gnutls_pcert_st             **pcert,
+                                                  unsigned int                 *pcert_length,
+                                                  gnutls_privkey_t             *pkey)
 {
   GTlsClientConnectionGnutls *gnutls = gnutls_transport_get_ptr (session);
   GTlsConnectionGnutls *conn = G_TLS_CONNECTION_GNUTLS (gnutls);
@@ -321,15 +325,15 @@ g_tls_client_connection_gnutls_retrieve_function (gnutls_session_t             s
   gnutls->accepted_cas = accepted_cas;
   g_object_notify (G_OBJECT (gnutls), "accepted-cas");
 
-  g_tls_connection_gnutls_get_certificate (conn, st);
+  g_tls_connection_gnutls_get_certificate (conn, pcert, pcert_length, pkey);
 
-  if (st->ncerts == 0)
+  if (*pcert_length == 0)
     {
       g_clear_error (&gnutls->cert_error);
       if (g_tls_connection_gnutls_request_certificate (conn, &gnutls->cert_error))
-        g_tls_connection_gnutls_get_certificate (conn, st);
+        g_tls_connection_gnutls_get_certificate (conn, pcert, pcert_length, pkey);
 
-      if (st->ncerts == 0)
+      if (*pcert_length == 0)
         {
           /* If there is still no client certificate, this connection will
            * probably fail, but no reason to give up: let's try anyway.
@@ -339,13 +343,10 @@ g_tls_client_connection_gnutls_retrieve_function (gnutls_session_t             s
         }
     }
 
-  g_assert (st->key_type == GNUTLS_PRIVKEY_X509 ||
-            st->key_type == GNUTLS_PRIVKEY_PKCS11);
-  if ((st->key_type == GNUTLS_PRIVKEY_X509 && st->key.x509 == NULL) ||
-      (st->key_type == GNUTLS_PRIVKEY_PKCS11 && st->key.pkcs11 == NULL))
+  if (*pkey == NULL)
     {
-      /* No private key. GnuTLS expects it to be non-null if ncerts is nonzero,
-       * so we have to abort now.
+      /* No private key. GnuTLS expects it to be non-null if pcert_length is
+       * nonzero, so we have to abort now.
        */
       gnutls->requested_cert_missing = TRUE;
       return -1;
diff --git a/tls/gnutls/gtlsconnection-gnutls.c b/tls/gnutls/gtlsconnection-gnutls.c
index 6aa17bc..ce89dfb 100644
--- a/tls/gnutls/gtlsconnection-gnutls.c
+++ b/tls/gnutls/gtlsconnection-gnutls.c
@@ -652,20 +652,28 @@ g_tls_connection_gnutls_get_session (GTlsConnectionGnutls *gnutls)
 }
 
 void
-g_tls_connection_gnutls_get_certificate (GTlsConnectionGnutls *gnutls,
-                                         gnutls_retr2_st      *st)
+g_tls_connection_gnutls_get_certificate (GTlsConnectionGnutls  *gnutls,
+                                         gnutls_pcert_st      **pcert,
+                                         unsigned int          *pcert_length,
+                                         gnutls_privkey_t      *pkey)
 {
   GTlsConnectionGnutlsPrivate *priv = g_tls_connection_gnutls_get_instance_private (gnutls);
   GTlsCertificate *cert;
 
-  st->cert_type = GNUTLS_CRT_X509;
-  st->ncerts = 0;
-
   cert = g_tls_connection_get_certificate (G_TLS_CONNECTION (gnutls));
 
   if (cert)
-    g_tls_certificate_gnutls_copy (G_TLS_CERTIFICATE_GNUTLS (cert),
-                                   priv->interaction_id, st);
+    {
+      g_tls_certificate_gnutls_copy (G_TLS_CERTIFICATE_GNUTLS (cert),
+                                     priv->interaction_id,
+                                     pcert, pcert_length, pkey);
+    }
+  else
+    {
+      *pcert = NULL;
+      *pcert_length = 0;
+      *pkey = NULL;
+    }
 }
 
 typedef enum {
diff --git a/tls/gnutls/gtlsconnection-gnutls.h b/tls/gnutls/gtlsconnection-gnutls.h
index 4c623c2..71c69cd 100644
--- a/tls/gnutls/gtlsconnection-gnutls.h
+++ b/tls/gnutls/gtlsconnection-gnutls.h
@@ -26,6 +26,7 @@
 #define __G_TLS_CONNECTION_GNUTLS_H__
 
 #include <gio/gio.h>
+#include <gnutls/abstract.h>
 #include <gnutls/gnutls.h>
 
 G_BEGIN_DECLS
@@ -49,7 +50,9 @@ gnutls_certificate_credentials_t g_tls_connection_gnutls_get_credentials (GTlsCo
 gnutls_session_t                 g_tls_connection_gnutls_get_session     (GTlsConnectionGnutls *connection);
 
 void     g_tls_connection_gnutls_get_certificate     (GTlsConnectionGnutls  *gnutls,
-                                                      gnutls_retr2_st       *st);
+                                                      gnutls_pcert_st      **pcert,
+                                                      unsigned int          *pcert_length,
+                                                      gnutls_privkey_t      *pkey);
 
 gboolean g_tls_connection_gnutls_request_certificate (GTlsConnectionGnutls  *gnutls,
                                                       GError               **error);
diff --git a/tls/gnutls/gtlsserverconnection-gnutls.c b/tls/gnutls/gtlsserverconnection-gnutls.c
index 8e323b3..7c38b87 100644
--- a/tls/gnutls/gtlsserverconnection-gnutls.c
+++ b/tls/gnutls/gtlsserverconnection-gnutls.c
@@ -51,12 +51,14 @@ static void     g_tls_server_connection_gnutls_initable_interface_init (GInitabl
 
 static void g_tls_server_connection_gnutls_server_connection_interface_init (GTlsServerConnectionInterface 
*iface);
 
-static int g_tls_server_connection_gnutls_retrieve_function (gnutls_session_t             session,
-                                                             const gnutls_datum_t        *req_ca_rdn,
-                                                             int                          nreqs,
-                                                             const gnutls_pk_algorithm_t *pk_algos,
-                                                             int                          pk_algos_length,
-                                                             gnutls_retr2_st             *st);
+static int g_tls_server_connection_gnutls_retrieve_function (gnutls_session_t              session,
+                                                             const gnutls_datum_t         *req_ca_rdn,
+                                                             int                           nreqs,
+                                                             const gnutls_pk_algorithm_t  *pk_algos,
+                                                             int                           pk_algos_length,
+                                                             gnutls_pcert_st             **pcert,
+                                                             unsigned int                 *pcert_length,
+                                                             gnutls_privkey_t             *pkey);
 
 static int            g_tls_server_connection_gnutls_db_store    (void            *user_data,
                                                                   gnutls_datum_t   key,
@@ -83,7 +85,7 @@ g_tls_server_connection_gnutls_init (GTlsServerConnectionGnutls *gnutls)
   gnutls_certificate_credentials_t creds;
 
   creds = g_tls_connection_gnutls_get_credentials (G_TLS_CONNECTION_GNUTLS (gnutls));
-  gnutls_certificate_set_retrieve_function (creds, g_tls_server_connection_gnutls_retrieve_function);
+  gnutls_certificate_set_retrieve_function2 (creds, g_tls_server_connection_gnutls_retrieve_function);
 }
 
 static gboolean
@@ -154,14 +156,17 @@ g_tls_server_connection_gnutls_set_property (GObject      *object,
 }
 
 static int
-g_tls_server_connection_gnutls_retrieve_function (gnutls_session_t             session,
-                                                  const gnutls_datum_t        *req_ca_rdn,
-                                                  int                          nreqs,
-                                                  const gnutls_pk_algorithm_t *pk_algos,
-                                                  int                          pk_algos_length,
-                                                  gnutls_retr2_st             *st)
+g_tls_server_connection_gnutls_retrieve_function (gnutls_session_t              session,
+                                                  const gnutls_datum_t         *req_ca_rdn,
+                                                  int                           nreqs,
+                                                  const gnutls_pk_algorithm_t  *pk_algos,
+                                                  int                           pk_algos_length,
+                                                  gnutls_pcert_st             **pcert,
+                                                  unsigned int                 *pcert_length,
+                                                  gnutls_privkey_t             *pkey)
 {
-  g_tls_connection_gnutls_get_certificate (gnutls_transport_get_ptr (session), st);
+  g_tls_connection_gnutls_get_certificate (gnutls_transport_get_ptr (session),
+                                           pcert, pcert_length, pkey);
   return 0;
 }
 


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