Migrate to openssl 3
[platform/upstream/glib-networking.git] / tls / gnutls / gtlsdatabase-gnutls.c
1 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /*
3  * GIO - GLib Input, Output and Streaming Library
4  *
5  * Copyright 2010 Collabora, Ltd
6  * Copyright 2018 Igalia S.L.
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General
19  * Public License along with this library; if not, see
20  * <http://www.gnu.org/licenses/>.
21  *
22  * In addition, when the library is used with OpenSSL, a special
23  * exception applies. Refer to the LICENSE_EXCEPTION file for details.
24  *
25  * Author: Stef Walter <stefw@collabora.co.uk>
26  */
27
28 #include "config.h"
29
30 #include "gtlsdatabase-gnutls.h"
31
32 #include <gio/gio.h>
33 #include <glib/gi18n-lib.h>
34 #include <gnutls/x509.h>
35
36 #include "gtlscertificate-gnutls.h"
37 #include "gtlshttp.h"
38 #include "gtlsgnutls-version.h"
39
40 typedef struct
41 {
42   /*
43    * This class is protected by mutex because the default GTlsDatabase
44    * is a global singleton, accessible via the default GTlsBackend.
45    */
46   GMutex mutex;
47
48   /* Read-only after construct, but still has to be protected by the mutex. */
49   gnutls_x509_trust_list_t trust_list;
50
51   /*
52    * These are hash tables of GBytes -> GPtrArray<GBytes>. The values of
53    * the ptr array are full DER encoded certificate values. The keys are byte
54    * arrays containing either subject DNs, issuer DNs, or full DER encoded certs
55    */
56   GHashTable *subjects;
57   GHashTable *issuers;
58
59   /*
60    * This is a table of GBytes -> GBytes. The values and keys are
61    * DER encoded certificate values.
62    */
63   GHashTable *complete;
64
65   /*
66    * This is a table of gchar * -> GPtrArray<GBytes>. The values of
67    * the ptr array are full DER encoded certificate values. The keys are the
68    * string handles. This array is populated on demand.
69    */
70   GHashTable *handles;
71 } GTlsDatabaseGnutlsPrivate;
72
73 static void g_tls_database_gnutls_initable_interface_init (GInitableIface *iface);
74
75 G_DEFINE_TYPE_WITH_CODE (GTlsDatabaseGnutls, g_tls_database_gnutls, G_TYPE_TLS_DATABASE,
76                          G_ADD_PRIVATE (GTlsDatabaseGnutls);
77                          G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
78                                                 g_tls_database_gnutls_initable_interface_init);
79                          );
80
81 static GHashTable *
82 bytes_multi_table_new (void)
83 {
84   return g_hash_table_new_full (g_bytes_hash, g_bytes_equal,
85                                 (GDestroyNotify)g_bytes_unref,
86                                 (GDestroyNotify)g_ptr_array_unref);
87 }
88
89 static void
90 bytes_multi_table_insert (GHashTable *table,
91                           GBytes     *key,
92                           GBytes     *value)
93 {
94   GPtrArray *multi;
95
96   multi = g_hash_table_lookup (table, key);
97   if (!multi)
98     {
99       multi = g_ptr_array_new_with_free_func ((GDestroyNotify)g_bytes_unref);
100       g_hash_table_insert (table, g_bytes_ref (key), multi);
101     }
102   g_ptr_array_add (multi, g_bytes_ref (value));
103 }
104
105 static GBytes *
106 bytes_multi_table_lookup_ref_one (GHashTable *table,
107                                   GBytes     *key)
108 {
109   GPtrArray *multi;
110
111   multi = g_hash_table_lookup (table, key);
112   if (!multi)
113     return NULL;
114
115   g_assert (multi->len > 0);
116   return g_bytes_ref (multi->pdata[0]);
117 }
118
119 static GList *
120 bytes_multi_table_lookup_ref_all (GHashTable *table,
121                                   GBytes     *key)
122 {
123   GPtrArray *multi;
124   GList *list = NULL;
125   guint i;
126
127   multi = g_hash_table_lookup (table, key);
128   if (!multi)
129     return NULL;
130
131   for (i = 0; i < multi->len; i++)
132     list = g_list_prepend (list, g_bytes_ref (multi->pdata[i]));
133
134   return g_list_reverse (list);
135 }
136
137 static GHashTable *
138 create_handles_array_unlocked (GTlsDatabaseGnutls *self,
139                                GHashTable         *complete)
140 {
141   GHashTable *handles;
142   GHashTableIter iter;
143   GBytes *der;
144   gchar *handle;
145
146   handles = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
147                                    (GDestroyNotify)g_bytes_unref);
148
149   g_hash_table_iter_init (&iter, complete);
150   while (g_hash_table_iter_next (&iter, NULL, (gpointer *)&der))
151     {
152       g_assert (G_TLS_DATABASE_GNUTLS_GET_CLASS (self)->create_handle_for_certificate);
153       handle = G_TLS_DATABASE_GNUTLS_GET_CLASS (self)->create_handle_for_certificate (self, der);
154       if (handle)
155         g_hash_table_insert (handles, handle, g_bytes_ref (der));
156     }
157
158   return handles;
159 }
160
161 static void
162 initialize_tables (gnutls_x509_trust_list_t  trust_list,
163                    GHashTable               *subjects,
164                    GHashTable               *issuers,
165                    GHashTable               *complete)
166 {
167   gnutls_x509_trust_list_iter_t iter = NULL;
168   gnutls_x509_crt_t cert = NULL;
169   gnutls_datum_t dn;
170   GBytes *der = NULL;
171   GBytes *subject = NULL;
172   GBytes *issuer = NULL;
173   gint gerr;
174
175   while (gnutls_x509_trust_list_iter_get_ca (trust_list, &iter, &cert) == 0)
176     {
177       gerr = gnutls_x509_crt_get_raw_dn (cert, &dn);
178       if (gerr < 0)
179         {
180           g_warning ("failed to get subject of anchor certificate: %s",
181                      gnutls_strerror (gerr));
182           goto next;
183         }
184       subject = g_bytes_new_with_free_func (dn.data, dn.size, gnutls_free, dn.data);
185
186       gerr = gnutls_x509_crt_get_raw_issuer_dn (cert, &dn);
187       if (gerr < 0)
188         {
189           g_warning ("failed to get issuer of anchor certificate: %s",
190                      gnutls_strerror (gerr));
191           goto next;
192         }
193       issuer = g_bytes_new_with_free_func (dn.data, dn.size, gnutls_free, dn.data);
194
195       gerr = gnutls_x509_crt_export2 (cert, GNUTLS_X509_FMT_DER, &dn);
196       if (gerr < 0)
197         {
198           g_warning ("failed to get certificate DER: %s",
199                      gnutls_strerror (gerr));
200           goto next;
201         }
202       der = g_bytes_new_with_free_func (dn.data, dn.size, gnutls_free, dn.data);
203
204       /* Three different ways of looking up same certificate */
205       bytes_multi_table_insert (subjects, subject, der);
206       bytes_multi_table_insert (issuers, issuer, der);
207
208       g_hash_table_insert (complete, g_bytes_ref (der),
209                            g_bytes_ref (der));
210
211 next:
212       g_clear_pointer (&der, g_bytes_unref);
213       g_clear_pointer (&subject, g_bytes_unref);
214       g_clear_pointer (&issuer, g_bytes_unref);
215       g_clear_pointer (&cert, gnutls_x509_crt_deinit);
216     }
217 }
218
219 static void
220 g_tls_database_gnutls_finalize (GObject *object)
221 {
222   GTlsDatabaseGnutls *self = G_TLS_DATABASE_GNUTLS (object);
223   GTlsDatabaseGnutlsPrivate *priv = g_tls_database_gnutls_get_instance_private (self);
224
225   g_clear_pointer (&priv->subjects, g_hash_table_destroy);
226   g_clear_pointer (&priv->issuers, g_hash_table_destroy);
227   g_clear_pointer (&priv->complete, g_hash_table_destroy);
228   g_clear_pointer (&priv->handles, g_hash_table_destroy);
229
230   gnutls_x509_trust_list_deinit (priv->trust_list, 1);
231
232   g_mutex_clear (&priv->mutex);
233
234   G_OBJECT_CLASS (g_tls_database_gnutls_parent_class)->finalize (object);
235 }
236
237 static void
238 g_tls_database_gnutls_init (GTlsDatabaseGnutls *self)
239 {
240   GTlsDatabaseGnutlsPrivate *priv = g_tls_database_gnutls_get_instance_private (self);
241
242   g_mutex_init (&priv->mutex);
243 }
244
245 static gchar *
246 g_tls_database_gnutls_create_certificate_handle (GTlsDatabase    *database,
247                                                  GTlsCertificate *certificate)
248 {
249   GTlsDatabaseGnutls *self = G_TLS_DATABASE_GNUTLS (database);
250   GTlsDatabaseGnutlsPrivate *priv = g_tls_database_gnutls_get_instance_private (self);
251   GBytes *der;
252   gboolean contains;
253   gchar *handle = NULL;
254
255   der = g_tls_certificate_gnutls_get_bytes (G_TLS_CERTIFICATE_GNUTLS (certificate));
256   g_return_val_if_fail (der, FALSE);
257
258   g_mutex_lock (&priv->mutex);
259
260   /* At the same time look up whether this certificate is in list */
261   contains = g_hash_table_lookup (priv->complete, der) ? TRUE : FALSE;
262
263   g_mutex_unlock (&priv->mutex);
264
265   /* Certificate is in the database */
266   if (contains)
267     {
268       g_assert (G_TLS_DATABASE_GNUTLS_GET_CLASS (self)->create_handle_for_certificate);
269       handle = G_TLS_DATABASE_GNUTLS_GET_CLASS (self)->create_handle_for_certificate (self, der);
270     }
271
272   g_bytes_unref (der);
273   return handle;
274 }
275
276 static GTlsCertificate *
277 g_tls_database_gnutls_lookup_certificate_for_handle (GTlsDatabase             *database,
278                                                      const gchar              *handle,
279                                                      GTlsInteraction          *interaction,
280                                                      GTlsDatabaseLookupFlags   flags,
281                                                      GCancellable             *cancellable,
282                                                      GError                  **error)
283 {
284   GTlsDatabaseGnutls *self = G_TLS_DATABASE_GNUTLS (database);
285   GTlsDatabaseGnutlsPrivate *priv = g_tls_database_gnutls_get_instance_private (self);
286   GTlsCertificate *cert;
287   GBytes *der;
288   gnutls_datum_t datum;
289   gsize length;
290
291   if (g_cancellable_set_error_if_cancelled (cancellable, error))
292     return NULL;
293
294   if (!handle)
295     return NULL;
296
297   g_mutex_lock (&priv->mutex);
298
299   /* Create the handles table if not already done */
300   if (!priv->handles)
301     priv->handles = create_handles_array_unlocked (self, priv->complete);
302
303   der = g_hash_table_lookup (priv->handles, handle);
304   if (der)
305     g_bytes_ref (der);
306
307   g_mutex_unlock (&priv->mutex);
308
309   if (!der)
310     return NULL;
311
312   datum.data = (unsigned char *)g_bytes_get_data (der, &length);
313   datum.size = length;
314
315   if (g_cancellable_set_error_if_cancelled (cancellable, error))
316     cert = NULL;
317   else
318     cert = g_tls_certificate_gnutls_new (&datum, NULL);
319
320   g_bytes_unref (der);
321   return cert;
322 }
323
324 static GTlsCertificate *
325 g_tls_database_gnutls_lookup_certificate_issuer (GTlsDatabase             *database,
326                                                  GTlsCertificate          *certificate,
327                                                  GTlsInteraction          *interaction,
328                                                  GTlsDatabaseLookupFlags   flags,
329                                                  GCancellable             *cancellable,
330                                                  GError                  **error)
331 {
332   GTlsDatabaseGnutls *self = G_TLS_DATABASE_GNUTLS (database);
333   GTlsDatabaseGnutlsPrivate *priv = g_tls_database_gnutls_get_instance_private (self);
334   gnutls_datum_t dn = { NULL, 0 };
335   GBytes *subject, *der;
336   gnutls_datum_t datum;
337   GTlsCertificate *issuer = NULL;
338   gnutls_x509_crt_t cert;
339   gsize length;
340   int gerr;
341
342   g_return_val_if_fail (G_IS_TLS_CERTIFICATE_GNUTLS (certificate), NULL);
343
344   if (g_cancellable_set_error_if_cancelled (cancellable, error))
345     return NULL;
346
347   if (flags & G_TLS_DATABASE_LOOKUP_KEYPAIR)
348     return NULL;
349
350   /* Dig out the issuer of this certificate */
351   cert = g_tls_certificate_gnutls_get_cert (G_TLS_CERTIFICATE_GNUTLS (certificate));
352   gerr = gnutls_x509_crt_get_raw_issuer_dn (cert, &dn);
353   if (gerr < 0)
354     {
355       g_warning ("failed to get issuer of certificate: %s", gnutls_strerror (gerr));
356       return NULL;
357     }
358
359   subject = g_bytes_new_with_free_func (dn.data, dn.size, gnutls_free, dn.data);
360
361   /* Find the full DER value of the certificate */
362   g_mutex_lock (&priv->mutex);
363   der = bytes_multi_table_lookup_ref_one (priv->subjects, subject);
364   g_mutex_unlock (&priv->mutex);
365
366   g_bytes_unref (subject);
367
368   if (g_cancellable_set_error_if_cancelled (cancellable, error))
369     {
370       issuer = NULL;
371     }
372   else if (der)
373     {
374       datum.data = (unsigned char *)g_bytes_get_data (der, &length);
375       datum.size = length;
376       issuer = g_tls_certificate_gnutls_new (&datum, NULL);
377     }
378
379   if (der)
380     g_bytes_unref (der);
381   return issuer;
382 }
383
384 static GList *
385 g_tls_database_gnutls_lookup_certificates_issued_by (GTlsDatabase             *database,
386                                                      GByteArray               *issuer_raw_dn,
387                                                      GTlsInteraction          *interaction,
388                                                      GTlsDatabaseLookupFlags   flags,
389                                                      GCancellable             *cancellable,
390                                                      GError                  **error)
391 {
392   GTlsDatabaseGnutls *self = G_TLS_DATABASE_GNUTLS (database);
393   GTlsDatabaseGnutlsPrivate *priv = g_tls_database_gnutls_get_instance_private (self);
394   GBytes *issuer;
395   gnutls_datum_t datum;
396   GList *issued = NULL;
397   GList *ders;
398   gsize length;
399   GList *l;
400
401   if (g_cancellable_set_error_if_cancelled (cancellable, error))
402     return NULL;
403
404   /* We don't have any private keys here */
405   if (flags & G_TLS_DATABASE_LOOKUP_KEYPAIR)
406     return NULL;
407
408   issuer = g_bytes_new_static (issuer_raw_dn->data, issuer_raw_dn->len);
409
410   /* Find the full DER value of the certificate */
411   g_mutex_lock (&priv->mutex);
412   ders = bytes_multi_table_lookup_ref_all (priv->issuers, issuer);
413   g_mutex_unlock (&priv->mutex);
414
415   g_bytes_unref (issuer);
416
417   for (l = ders; l; l = g_list_next (l))
418     {
419       if (g_cancellable_set_error_if_cancelled (cancellable, error))
420         {
421           g_list_free_full (issued, g_object_unref);
422           issued = NULL;
423           break;
424         }
425
426       datum.data = (unsigned char *)g_bytes_get_data (l->data, &length);
427       datum.size = length;
428       issued = g_list_prepend (issued, g_tls_certificate_gnutls_new (&datum, NULL));
429     }
430
431   g_list_free_full (ders, (GDestroyNotify)g_bytes_unref);
432   return issued;
433 }
434
435 typedef struct {
436   gnutls_x509_crt_t *chain;
437   guint              length;
438 } CertificateChain;
439
440 static CertificateChain *
441 certificate_chain_new (void)
442 {
443   return g_new0 (CertificateChain, 1);
444 }
445
446 static void
447 certificate_chain_free (CertificateChain *chain)
448 {
449   g_free (chain->chain);
450   g_free (chain);
451 }
452
453 static CertificateChain *
454 convert_certificate_chain_to_gnutls (GTlsCertificateGnutls *chain)
455 {
456   GTlsCertificate *cert;
457   CertificateChain *gnutls_chain;
458   guint i = 0;
459
460   gnutls_chain = certificate_chain_new ();
461
462   for (cert = G_TLS_CERTIFICATE (chain); cert; cert = g_tls_certificate_get_issuer (cert))
463     gnutls_chain->length++;
464
465   gnutls_chain->chain = g_new (gnutls_x509_crt_t, gnutls_chain->length);
466
467   for (cert = G_TLS_CERTIFICATE (chain); cert; cert = g_tls_certificate_get_issuer (cert), i++)
468     gnutls_chain->chain[i] = g_tls_certificate_gnutls_get_cert (G_TLS_CERTIFICATE_GNUTLS (cert));
469
470   g_assert (i == gnutls_chain->length);
471
472   return gnutls_chain;
473 }
474
475 static GTlsCertificateFlags
476 g_tls_database_gnutls_verify_chain (GTlsDatabase             *database,
477                                     GTlsCertificate          *chain,
478                                     const gchar              *purpose,
479                                     GSocketConnectable       *identity,
480                                     GTlsInteraction          *interaction,
481                                     GTlsDatabaseVerifyFlags   flags,
482                                     GCancellable             *cancellable,
483                                     GError                  **error)
484 {
485   GTlsDatabaseGnutls *self = G_TLS_DATABASE_GNUTLS (database);
486   GTlsDatabaseGnutlsPrivate *priv = g_tls_database_gnutls_get_instance_private (self);
487   GTlsCertificateFlags result;
488   guint gnutls_result;
489   CertificateChain *gnutls_chain;
490   int gerr;
491
492   g_return_val_if_fail (G_IS_TLS_CERTIFICATE_GNUTLS (chain),
493                         G_TLS_CERTIFICATE_GENERIC_ERROR);
494   g_assert (purpose);
495
496   if (g_cancellable_set_error_if_cancelled (cancellable, error))
497     return G_TLS_CERTIFICATE_GENERIC_ERROR;
498
499   g_mutex_lock (&priv->mutex);
500   gnutls_chain = convert_certificate_chain_to_gnutls (G_TLS_CERTIFICATE_GNUTLS (chain));
501   gerr = gnutls_x509_trust_list_verify_crt (priv->trust_list,
502                                             gnutls_chain->chain, gnutls_chain->length,
503                                             0, &gnutls_result, NULL);
504   g_mutex_unlock (&priv->mutex);
505
506   if (gerr != 0 || g_cancellable_set_error_if_cancelled (cancellable, error))
507     {
508       certificate_chain_free (gnutls_chain);
509       return G_TLS_CERTIFICATE_GENERIC_ERROR;
510     }
511
512   result = g_tls_certificate_gnutls_convert_flags (gnutls_result);
513
514   if (identity)
515     result |= g_tls_certificate_gnutls_verify_identity (G_TLS_CERTIFICATE_GNUTLS (chain),
516                                                         identity,
517                                                         error);
518
519   certificate_chain_free (gnutls_chain);
520   return result;
521 }
522
523 static gchar *
524 g_tls_database_gnutls_create_handle_for_certificate (GTlsDatabaseGnutls *self,
525                                                      GBytes             *der)
526 {
527   gchar *bookmark;
528   gchar *uri;
529
530   /*
531    * Here we create a URI that looks like
532    * system-trust:#11b2641821252596420e468c275771f5e51022c121a17bd7a89a2f37b6336c8f.
533    *
534    * system-trust is a meaningless URI scheme, and the handle does not
535    * even need to be a URI; this is just a nice stable way to uniquely
536    * identify a certificate.
537    */
538
539   bookmark = g_compute_checksum_for_bytes (G_CHECKSUM_SHA256, der);
540   uri = g_strconcat ("system-trust:#", bookmark, NULL);
541
542   g_free (bookmark);
543
544   return uri;
545 }
546
547 static gboolean
548 g_tls_database_gnutls_populate_trust_list (GTlsDatabaseGnutls        *self,
549                                            gnutls_x509_trust_list_t   trust_list,
550                                            GError                   **error)
551 {
552   int gerr = gnutls_x509_trust_list_add_system_trust (trust_list, 0, 0);
553   if (gerr == GNUTLS_E_UNIMPLEMENTED_FEATURE)
554     {
555       g_set_error_literal (error, G_TLS_ERROR, G_TLS_ERROR_MISC,
556                            _("Failed to load system trust store: GnuTLS was not configured with a system trust"));
557     }
558   else if (gerr < 0)
559     {
560       g_set_error (error, G_TLS_ERROR, G_TLS_ERROR_MISC,
561                    _("Failed to load system trust store: %s"),
562                    gnutls_strerror (gerr));
563     }
564   return gerr >= 0;
565 }
566
567 static gnutls_x509_trust_list_t
568 create_trust_list (GTlsDatabaseGnutls  *self,
569                    GError             **error)
570 {
571   GTlsDatabaseGnutlsClass *database_class = G_TLS_DATABASE_GNUTLS_GET_CLASS (self);
572   gnutls_x509_trust_list_t trust_list;
573   int ret;
574
575   ret = gnutls_x509_trust_list_init (&trust_list, 0);
576   if (ret != 0)
577     {
578       g_set_error (error, G_TLS_ERROR, G_TLS_ERROR_MISC, "Failed to initialize trust list: %s", gnutls_strerror (ret));
579       return NULL;
580     }
581
582   g_assert (database_class->populate_trust_list);
583   if (!database_class->populate_trust_list (self, trust_list, error))
584     {
585       gnutls_x509_trust_list_deinit (trust_list, TRUE);
586       return NULL;
587     }
588
589   return trust_list;
590 }
591
592 gnutls_certificate_credentials_t
593 g_tls_database_gnutls_get_credentials (GTlsDatabaseGnutls  *self,
594                                        GError             **error)
595 {
596   gnutls_certificate_credentials_t credentials;
597   gnutls_x509_trust_list_t trust_list = NULL;
598   int ret;
599
600   ret = gnutls_certificate_allocate_credentials (&credentials);
601   if (ret != 0)
602     {
603       g_set_error (error, G_TLS_ERROR, G_TLS_ERROR_MISC, "Failed to allocate credentials: %s", gnutls_strerror (ret));
604       return NULL;
605     }
606
607   trust_list = create_trust_list (self, error);
608   if (!trust_list)
609     {
610       gnutls_certificate_free_credentials (credentials);
611       return NULL;
612     }
613
614   gnutls_certificate_set_trust_list (credentials, trust_list, 0);
615   return credentials;
616 }
617
618 static void
619 g_tls_database_gnutls_class_init (GTlsDatabaseGnutlsClass *klass)
620 {
621   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
622   GTlsDatabaseClass *database_class = G_TLS_DATABASE_CLASS (klass);
623
624   gobject_class->finalize     = g_tls_database_gnutls_finalize;
625
626   database_class->create_certificate_handle = g_tls_database_gnutls_create_certificate_handle;
627   database_class->lookup_certificate_for_handle = g_tls_database_gnutls_lookup_certificate_for_handle;
628   database_class->lookup_certificate_issuer = g_tls_database_gnutls_lookup_certificate_issuer;
629   database_class->lookup_certificates_issued_by = g_tls_database_gnutls_lookup_certificates_issued_by;
630   database_class->verify_chain = g_tls_database_gnutls_verify_chain;
631
632   klass->create_handle_for_certificate = g_tls_database_gnutls_create_handle_for_certificate;
633   klass->populate_trust_list = g_tls_database_gnutls_populate_trust_list;
634 }
635
636 static gboolean
637 g_tls_database_gnutls_initable_init (GInitable     *initable,
638                                      GCancellable  *cancellable,
639                                      GError       **error)
640 {
641   GTlsDatabaseGnutls *self = G_TLS_DATABASE_GNUTLS (initable);
642   GTlsDatabaseGnutlsPrivate *priv = g_tls_database_gnutls_get_instance_private (self);
643   gnutls_x509_trust_list_t trust_list = NULL;
644   GHashTable *subjects = NULL;
645   GHashTable *issuers = NULL;
646   GHashTable *complete = NULL;
647   gboolean result = TRUE;
648
649   if (g_cancellable_set_error_if_cancelled (cancellable, error))
650     return FALSE;
651
652   trust_list = create_trust_list (self, error);
653   if (!trust_list)
654     return FALSE;
655
656   subjects = bytes_multi_table_new ();
657   issuers = bytes_multi_table_new ();
658
659   complete = g_hash_table_new_full (g_bytes_hash, g_bytes_equal,
660                                     (GDestroyNotify)g_bytes_unref,
661                                     (GDestroyNotify)g_bytes_unref);
662
663   initialize_tables (trust_list, subjects, issuers, complete);
664
665   if (g_cancellable_set_error_if_cancelled (cancellable, error))
666     result = FALSE;
667
668   if (result)
669     {
670       g_mutex_lock (&priv->mutex);
671       if (!priv->trust_list)
672         {
673           priv->trust_list = trust_list;
674           trust_list = NULL;
675         }
676       if (!priv->subjects)
677         {
678           priv->subjects = subjects;
679           subjects = NULL;
680         }
681       if (!priv->issuers)
682         {
683           priv->issuers = issuers;
684           issuers = NULL;
685         }
686       if (!priv->complete)
687         {
688           priv->complete = complete;
689           complete = NULL;
690         }
691       g_mutex_unlock (&priv->mutex);
692     }
693
694   if (trust_list)
695     gnutls_x509_trust_list_deinit (trust_list, 1);
696   if (subjects)
697     g_hash_table_unref (subjects);
698   if (issuers)
699     g_hash_table_unref (issuers);
700   if (complete)
701     g_hash_table_unref (complete);
702   return result;
703 }
704
705 static void
706 g_tls_database_gnutls_initable_interface_init (GInitableIface *iface)
707 {
708   iface->init = g_tls_database_gnutls_initable_init;
709 }
710
711 GTlsDatabaseGnutls *
712 g_tls_database_gnutls_new (GError **error)
713 {
714   g_return_val_if_fail (!error || !*error, NULL);
715
716   return g_initable_new (G_TYPE_TLS_DATABASE_GNUTLS, NULL, error, NULL);
717 }