openssl: remove manual check for certificate expiration
[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
38 typedef struct
39 {
40   /*
41    * This class is protected by mutex because the default GTlsDatabase
42    * is a global singleton, accessible via the default GTlsBackend.
43    */
44   GMutex mutex;
45
46   /* read-only after construct */
47   gnutls_x509_trust_list_t trust_list;
48
49   /*
50    * These are hash tables of GBytes -> GPtrArray<GBytes>. The values of
51    * the ptr array are full DER encoded certificate values. The keys are byte
52    * arrays containing either subject DNs, issuer DNs, or full DER encoded certs
53    */
54   GHashTable *subjects;
55   GHashTable *issuers;
56
57   /*
58    * This is a table of GBytes -> GBytes. The values and keys are
59    * DER encoded certificate values.
60    */
61   GHashTable *complete;
62
63   /*
64    * This is a table of gchar * -> GPtrArray<GBytes>. The values of
65    * the ptr array are full DER encoded certificate values. The keys are the
66    * string handles. This array is populated on demand.
67    */
68   GHashTable *handles;
69 } GTlsDatabaseGnutlsPrivate;
70
71 static void g_tls_database_gnutls_initable_interface_init (GInitableIface *iface);
72
73 G_DEFINE_TYPE_WITH_CODE (GTlsDatabaseGnutls, g_tls_database_gnutls, G_TYPE_TLS_DATABASE,
74                          G_ADD_PRIVATE (GTlsDatabaseGnutls);
75                          G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
76                                                 g_tls_database_gnutls_initable_interface_init);
77                          );
78
79 static GHashTable *
80 bytes_multi_table_new (void)
81 {
82   return g_hash_table_new_full (g_bytes_hash, g_bytes_equal,
83                                 (GDestroyNotify)g_bytes_unref,
84                                 (GDestroyNotify)g_ptr_array_unref);
85 }
86
87 static void
88 bytes_multi_table_insert (GHashTable *table,
89                           GBytes     *key,
90                           GBytes     *value)
91 {
92   GPtrArray *multi;
93
94   multi = g_hash_table_lookup (table, key);
95   if (multi == NULL)
96     {
97       multi = g_ptr_array_new_with_free_func ((GDestroyNotify)g_bytes_unref);
98       g_hash_table_insert (table, g_bytes_ref (key), multi);
99     }
100   g_ptr_array_add (multi, g_bytes_ref (value));
101 }
102
103 static GBytes *
104 bytes_multi_table_lookup_ref_one (GHashTable *table,
105                                   GBytes     *key)
106 {
107   GPtrArray *multi;
108
109   multi = g_hash_table_lookup (table, key);
110   if (multi == NULL)
111     return NULL;
112
113   g_assert (multi->len > 0);
114   return g_bytes_ref (multi->pdata[0]);
115 }
116
117 static GList *
118 bytes_multi_table_lookup_ref_all (GHashTable *table,
119                                   GBytes     *key)
120 {
121   GPtrArray *multi;
122   GList *list = NULL;
123   guint i;
124
125   multi = g_hash_table_lookup (table, key);
126   if (multi == NULL)
127     return NULL;
128
129   for (i = 0; i < multi->len; i++)
130     list = g_list_prepend (list, g_bytes_ref (multi->pdata[i]));
131
132   return g_list_reverse (list);
133 }
134
135 static GHashTable *
136 create_handles_array_unlocked (GTlsDatabaseGnutls *self,
137                                GHashTable         *complete)
138 {
139   GHashTable *handles;
140   GHashTableIter iter;
141   GBytes *der;
142   gchar *handle;
143
144   handles = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
145                                    (GDestroyNotify)g_bytes_unref);
146
147   g_hash_table_iter_init (&iter, complete);
148   while (g_hash_table_iter_next (&iter, NULL, (gpointer *)&der))
149     {
150       g_assert (G_TLS_DATABASE_GNUTLS_GET_CLASS (self)->create_handle_for_certificate);
151       handle = G_TLS_DATABASE_GNUTLS_GET_CLASS (self)->create_handle_for_certificate (self, der);
152       if (handle != NULL)
153         g_hash_table_insert (handles, handle, g_bytes_ref (der));
154     }
155
156   return handles;
157 }
158
159 static void
160 initialize_tables (gnutls_x509_trust_list_t  trust_list,
161                    GHashTable               *subjects,
162                    GHashTable               *issuers,
163                    GHashTable               *complete)
164 {
165   gnutls_x509_trust_list_iter_t iter = NULL;
166   gnutls_x509_crt_t cert = NULL;
167   gnutls_datum_t dn;
168   GBytes *der = NULL;
169   GBytes *subject = NULL;
170   GBytes *issuer = NULL;
171   gint gerr;
172
173   while ((gerr = gnutls_x509_trust_list_iter_get_ca (trust_list, &iter, &cert)) == 0)
174     {
175       gerr = gnutls_x509_crt_get_raw_dn (cert, &dn);
176       if (gerr < 0)
177         {
178           g_warning ("failed to get subject of anchor certificate: %s",
179                      gnutls_strerror (gerr));
180           goto next;
181         }
182       subject = g_bytes_new_with_free_func (dn.data, dn.size, gnutls_free, dn.data);
183
184       gerr = gnutls_x509_crt_get_raw_issuer_dn (cert, &dn);
185       if (gerr < 0)
186         {
187           g_warning ("failed to get issuer of anchor certificate: %s",
188                      gnutls_strerror (gerr));
189           goto next;
190         }
191       issuer = g_bytes_new_with_free_func (dn.data, dn.size, gnutls_free, dn.data);
192
193       gerr = gnutls_x509_crt_export2 (cert, GNUTLS_X509_FMT_DER, &dn);
194       if (gerr < 0)
195         {
196           g_warning ("failed to get certificate DER: %s",
197                      gnutls_strerror (gerr));
198           goto next;
199         }
200       der = g_bytes_new_with_free_func (dn.data, dn.size, gnutls_free, dn.data);
201
202       /* Three different ways of looking up same certificate */
203       bytes_multi_table_insert (subjects, subject, der);
204       bytes_multi_table_insert (issuers, issuer, der);
205
206       g_hash_table_insert (complete, g_bytes_ref (der),
207                            g_bytes_ref (der));
208
209 next:
210       g_clear_pointer (&der, g_bytes_unref);
211       g_clear_pointer (&subject, g_bytes_unref);
212       g_clear_pointer (&issuer, g_bytes_unref);
213       g_clear_pointer (&cert, gnutls_x509_crt_deinit);
214     }
215 }
216
217 static void
218 g_tls_database_gnutls_finalize (GObject *object)
219 {
220   GTlsDatabaseGnutls *self = G_TLS_DATABASE_GNUTLS (object);
221   GTlsDatabaseGnutlsPrivate *priv = g_tls_database_gnutls_get_instance_private (self);
222
223   g_clear_pointer (&priv->subjects, g_hash_table_destroy);
224   g_clear_pointer (&priv->issuers, g_hash_table_destroy);
225   g_clear_pointer (&priv->complete, g_hash_table_destroy);
226   g_clear_pointer (&priv->handles, g_hash_table_destroy);
227
228   gnutls_x509_trust_list_deinit (priv->trust_list, 1);
229
230   g_mutex_clear (&priv->mutex);
231
232   G_OBJECT_CLASS (g_tls_database_gnutls_parent_class)->finalize (object);
233 }
234
235 static void
236 g_tls_database_gnutls_init (GTlsDatabaseGnutls *self)
237 {
238   GTlsDatabaseGnutlsPrivate *priv = g_tls_database_gnutls_get_instance_private (self);
239
240   g_mutex_init (&priv->mutex);
241 }
242
243 static gchar *
244 g_tls_database_gnutls_create_certificate_handle (GTlsDatabase    *database,
245                                                  GTlsCertificate *certificate)
246 {
247   GTlsDatabaseGnutls *self = G_TLS_DATABASE_GNUTLS (database);
248   GTlsDatabaseGnutlsPrivate *priv = g_tls_database_gnutls_get_instance_private (self);
249   GBytes *der;
250   gboolean contains;
251   gchar *handle = NULL;
252
253   der = g_tls_certificate_gnutls_get_bytes (G_TLS_CERTIFICATE_GNUTLS (certificate));
254   g_return_val_if_fail (der != NULL, FALSE);
255
256   g_mutex_lock (&priv->mutex);
257
258   /* At the same time look up whether this certificate is in list */
259   contains = g_hash_table_lookup (priv->complete, der) ? TRUE : FALSE;
260
261   g_mutex_unlock (&priv->mutex);
262
263   /* Certificate is in the database */
264   if (contains)
265     {
266       g_assert (G_TLS_DATABASE_GNUTLS_GET_CLASS (self)->create_handle_for_certificate);
267       handle = G_TLS_DATABASE_GNUTLS_GET_CLASS (self)->create_handle_for_certificate (self, der);
268     }
269
270   g_bytes_unref (der);
271   return handle;
272 }
273
274 static GTlsCertificate *
275 g_tls_database_gnutls_lookup_certificate_for_handle (GTlsDatabase             *database,
276                                                      const gchar              *handle,
277                                                      GTlsInteraction          *interaction,
278                                                      GTlsDatabaseLookupFlags   flags,
279                                                      GCancellable             *cancellable,
280                                                      GError                  **error)
281 {
282   GTlsDatabaseGnutls *self = G_TLS_DATABASE_GNUTLS (database);
283   GTlsDatabaseGnutlsPrivate *priv = g_tls_database_gnutls_get_instance_private (self);
284   GTlsCertificate *cert;
285   GBytes *der;
286   gnutls_datum_t datum;
287   gsize length;
288
289   if (g_cancellable_set_error_if_cancelled (cancellable, error))
290     return NULL;
291
292   if (!handle)
293     return NULL;
294
295   g_mutex_lock (&priv->mutex);
296
297   /* Create the handles table if not already done */
298   if (!priv->handles)
299     priv->handles = create_handles_array_unlocked (self, priv->complete);
300
301   der = g_hash_table_lookup (priv->handles, handle);
302   if (der != NULL)
303     g_bytes_ref (der);
304
305   g_mutex_unlock (&priv->mutex);
306
307   if (der == NULL)
308     return NULL;
309
310   datum.data = (unsigned char *)g_bytes_get_data (der, &length);
311   datum.size = length;
312
313   if (g_cancellable_set_error_if_cancelled (cancellable, error))
314     cert = NULL;
315   else
316     cert = g_tls_certificate_gnutls_new (&datum, NULL);
317
318   g_bytes_unref (der);
319   return cert;
320 }
321
322 static GTlsCertificate *
323 g_tls_database_gnutls_lookup_certificate_issuer (GTlsDatabase             *database,
324                                                  GTlsCertificate          *certificate,
325                                                  GTlsInteraction          *interaction,
326                                                  GTlsDatabaseLookupFlags   flags,
327                                                  GCancellable             *cancellable,
328                                                  GError                  **error)
329 {
330   GTlsDatabaseGnutls *self = G_TLS_DATABASE_GNUTLS (database);
331   GTlsDatabaseGnutlsPrivate *priv = g_tls_database_gnutls_get_instance_private (self);
332   gnutls_datum_t dn = { NULL, 0 };
333   GBytes *subject, *der;
334   gnutls_datum_t datum;
335   GTlsCertificate *issuer = NULL;
336   gnutls_x509_crt_t cert;
337   gsize length;
338   int gerr;
339
340   g_return_val_if_fail (G_IS_TLS_CERTIFICATE_GNUTLS (certificate), NULL);
341
342   if (g_cancellable_set_error_if_cancelled (cancellable, error))
343     return NULL;
344
345   if (flags & G_TLS_DATABASE_LOOKUP_KEYPAIR)
346     return NULL;
347
348   /* Dig out the issuer of this certificate */
349   cert = g_tls_certificate_gnutls_get_cert (G_TLS_CERTIFICATE_GNUTLS (certificate));
350   gerr = gnutls_x509_crt_get_raw_issuer_dn (cert, &dn);
351   if (gerr < 0)
352     {
353       g_warning ("failed to get issuer of certificate: %s", gnutls_strerror (gerr));
354       return NULL;
355     }
356
357   subject = g_bytes_new_with_free_func (dn.data, dn.size, gnutls_free, dn.data);
358
359   /* Find the full DER value of the certificate */
360   g_mutex_lock (&priv->mutex);
361   der = bytes_multi_table_lookup_ref_one (priv->subjects, subject);
362   g_mutex_unlock (&priv->mutex);
363
364   g_bytes_unref (subject);
365
366   if (g_cancellable_set_error_if_cancelled (cancellable, error))
367     {
368       issuer = NULL;
369     }
370   else if (der != NULL)
371     {
372       datum.data = (unsigned char *)g_bytes_get_data (der, &length);
373       datum.size = length;
374       issuer = g_tls_certificate_gnutls_new (&datum, NULL);
375     }
376
377   if (der != NULL)
378     g_bytes_unref (der);
379   return issuer;
380 }
381
382 static GList *
383 g_tls_database_gnutls_lookup_certificates_issued_by (GTlsDatabase             *database,
384                                                      GByteArray               *issuer_raw_dn,
385                                                      GTlsInteraction          *interaction,
386                                                      GTlsDatabaseLookupFlags   flags,
387                                                      GCancellable             *cancellable,
388                                                      GError                  **error)
389 {
390   GTlsDatabaseGnutls *self = G_TLS_DATABASE_GNUTLS (database);
391   GTlsDatabaseGnutlsPrivate *priv = g_tls_database_gnutls_get_instance_private (self);
392   GBytes *issuer;
393   gnutls_datum_t datum;
394   GList *issued = NULL;
395   GList *ders;
396   gsize length;
397   GList *l;
398
399   if (g_cancellable_set_error_if_cancelled (cancellable, error))
400     return NULL;
401
402   /* We don't have any private keys here */
403   if (flags & G_TLS_DATABASE_LOOKUP_KEYPAIR)
404     return NULL;
405
406   issuer = g_bytes_new_static (issuer_raw_dn->data, issuer_raw_dn->len);
407
408   /* Find the full DER value of the certificate */
409   g_mutex_lock (&priv->mutex);
410   ders = bytes_multi_table_lookup_ref_all (priv->issuers, issuer);
411   g_mutex_unlock (&priv->mutex);
412
413   g_bytes_unref (issuer);
414
415   for (l = ders; l != NULL; l = g_list_next (l))
416     {
417       if (g_cancellable_set_error_if_cancelled (cancellable, error))
418         {
419           g_list_free_full (issued, g_object_unref);
420           issued = NULL;
421           break;
422         }
423
424       datum.data = (unsigned char *)g_bytes_get_data (l->data, &length);
425       datum.size = length;
426       issued = g_list_prepend (issued, g_tls_certificate_gnutls_new (&datum, NULL));
427     }
428
429   g_list_free_full (ders, (GDestroyNotify)g_bytes_unref);
430   return issued;
431 }
432
433 static void
434 convert_certificate_chain_to_gnutls (GTlsCertificateGnutls  *chain,
435                                      gnutls_x509_crt_t     **gnutls_chain,
436                                      guint                  *gnutls_chain_length)
437 {
438   GTlsCertificate *cert;
439   guint i;
440
441   g_assert (gnutls_chain);
442   g_assert (gnutls_chain_length);
443
444   for (*gnutls_chain_length = 0, cert = G_TLS_CERTIFICATE (chain);
445        cert; cert = g_tls_certificate_get_issuer (cert))
446     ++(*gnutls_chain_length);
447
448   *gnutls_chain = g_new0 (gnutls_x509_crt_t, *gnutls_chain_length);
449
450   for (i = 0, cert = G_TLS_CERTIFICATE (chain);
451        cert; cert = g_tls_certificate_get_issuer (cert), ++i)
452     (*gnutls_chain)[i] = g_tls_certificate_gnutls_get_cert (G_TLS_CERTIFICATE_GNUTLS (cert));
453
454   g_assert (i == *gnutls_chain_length);
455 }
456
457 static GTlsCertificateFlags
458 g_tls_database_gnutls_verify_chain (GTlsDatabase             *database,
459                                     GTlsCertificate          *chain,
460                                     const gchar              *purpose,
461                                     GSocketConnectable       *identity,
462                                     GTlsInteraction          *interaction,
463                                     GTlsDatabaseVerifyFlags   flags,
464                                     GCancellable             *cancellable,
465                                     GError                  **error)
466 {
467   GTlsDatabaseGnutls *self = G_TLS_DATABASE_GNUTLS (database);
468   GTlsDatabaseGnutlsPrivate *priv = g_tls_database_gnutls_get_instance_private (self);
469   GTlsCertificateFlags result;
470   guint gnutls_result;
471   gnutls_x509_crt_t *certs;
472   guint certs_length;
473   const char *hostname = NULL;
474   char *free_hostname = NULL;
475   int gerr;
476
477   g_return_val_if_fail (G_IS_TLS_CERTIFICATE_GNUTLS (chain),
478                         G_TLS_CERTIFICATE_GENERIC_ERROR);
479   g_assert (purpose);
480
481   if (g_cancellable_set_error_if_cancelled (cancellable, error))
482     return G_TLS_CERTIFICATE_GENERIC_ERROR;
483
484   convert_certificate_chain_to_gnutls (G_TLS_CERTIFICATE_GNUTLS (chain),
485                                        &certs, &certs_length);
486   gerr = gnutls_x509_trust_list_verify_crt (priv->trust_list,
487                                             certs, certs_length,
488                                             0, &gnutls_result, NULL);
489
490   if (gerr != 0 || g_cancellable_set_error_if_cancelled (cancellable, error))
491     {
492       g_free (certs);
493       return G_TLS_CERTIFICATE_GENERIC_ERROR;
494     }
495
496   result = g_tls_certificate_gnutls_convert_flags (gnutls_result);
497
498   if (G_IS_NETWORK_ADDRESS (identity))
499     hostname = g_network_address_get_hostname (G_NETWORK_ADDRESS (identity));
500   else if (G_IS_NETWORK_SERVICE (identity))
501     hostname = g_network_service_get_domain (G_NETWORK_SERVICE (identity));
502   else if (G_IS_INET_SOCKET_ADDRESS (identity))
503     {
504       GInetAddress *addr;
505
506       addr = g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (identity));
507       hostname = free_hostname = g_inet_address_to_string (addr);
508     }
509   if (hostname)
510     {
511       if (!gnutls_x509_crt_check_hostname (certs[0], hostname))
512         result |= G_TLS_CERTIFICATE_BAD_IDENTITY;
513       g_free (free_hostname);
514     }
515
516   g_free (certs);
517   return result;
518 }
519
520 static gchar *
521 g_tls_database_gnutls_create_handle_for_certificate (GTlsDatabaseGnutls *self,
522                                                      GBytes             *der)
523 {
524   gchar *bookmark;
525   gchar *uri;
526
527   /*
528    * Here we create a URI that looks like
529    * system-trust:#11b2641821252596420e468c275771f5e51022c121a17bd7a89a2f37b6336c8f.
530    *
531    * system-trust is a meaningless URI scheme, and the handle does not
532    * even need to be a URI; this is just a nice stable way to uniquely
533    * identify a certificate.
534    */
535
536   bookmark = g_compute_checksum_for_bytes (G_CHECKSUM_SHA256, der);
537   uri = g_strconcat ("system-trust:#", bookmark, NULL);
538
539   g_free (bookmark);
540
541   return uri;
542 }
543
544 static gboolean
545 g_tls_database_gnutls_populate_trust_list (GTlsDatabaseGnutls        *self,
546                                            gnutls_x509_trust_list_t   trust_list,
547                                            GError                   **error)
548 {
549   int gerr = gnutls_x509_trust_list_add_system_trust (trust_list, 0, 0);
550   if (gerr == GNUTLS_E_UNIMPLEMENTED_FEATURE)
551     {
552       g_set_error_literal (error, G_TLS_ERROR, G_TLS_ERROR_MISC,
553                            _("Failed to load system trust store: GnuTLS was not configured with a system trust"));
554     }
555   else if (gerr < 0)
556     {
557       g_set_error (error, G_TLS_ERROR, G_TLS_ERROR_MISC,
558                    _("Failed to load system trust store: %s"),
559                    gnutls_strerror (gerr));
560     }
561   return gerr >= 0;
562 }
563
564 static void
565 g_tls_database_gnutls_class_init (GTlsDatabaseGnutlsClass *klass)
566 {
567   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
568   GTlsDatabaseClass *database_class = G_TLS_DATABASE_CLASS (klass);
569
570   gobject_class->finalize     = g_tls_database_gnutls_finalize;
571
572   database_class->create_certificate_handle = g_tls_database_gnutls_create_certificate_handle;
573   database_class->lookup_certificate_for_handle = g_tls_database_gnutls_lookup_certificate_for_handle;
574   database_class->lookup_certificate_issuer = g_tls_database_gnutls_lookup_certificate_issuer;
575   database_class->lookup_certificates_issued_by = g_tls_database_gnutls_lookup_certificates_issued_by;
576   database_class->verify_chain = g_tls_database_gnutls_verify_chain;
577
578   klass->create_handle_for_certificate = g_tls_database_gnutls_create_handle_for_certificate;
579   klass->populate_trust_list = g_tls_database_gnutls_populate_trust_list;
580 }
581
582 static gboolean
583 g_tls_database_gnutls_initable_init (GInitable     *initable,
584                                      GCancellable  *cancellable,
585                                      GError       **error)
586 {
587   GTlsDatabaseGnutls *self = G_TLS_DATABASE_GNUTLS (initable);
588   GTlsDatabaseGnutlsPrivate *priv = g_tls_database_gnutls_get_instance_private (self);
589   gnutls_x509_trust_list_t trust_list = NULL;
590   GHashTable *subjects = NULL;
591   GHashTable *issuers = NULL;
592   GHashTable *complete = NULL;
593   gboolean result = TRUE;
594
595   if (g_cancellable_set_error_if_cancelled (cancellable, error))
596     return FALSE;
597
598   gnutls_x509_trust_list_init (&trust_list, 0);
599
600   g_assert (G_TLS_DATABASE_GNUTLS_GET_CLASS (self)->populate_trust_list);
601   if (!G_TLS_DATABASE_GNUTLS_GET_CLASS (self)->populate_trust_list (self, trust_list, error))
602     {
603       result = FALSE;
604       goto out;
605     }
606
607   subjects = bytes_multi_table_new ();
608   issuers = bytes_multi_table_new ();
609
610   complete = g_hash_table_new_full (g_bytes_hash, g_bytes_equal,
611                                     (GDestroyNotify)g_bytes_unref,
612                                     (GDestroyNotify)g_bytes_unref);
613
614   initialize_tables (trust_list, subjects, issuers, complete);
615
616   if (g_cancellable_set_error_if_cancelled (cancellable, error))
617     result = FALSE;
618
619   if (result)
620     {
621       g_mutex_lock (&priv->mutex);
622       if (!priv->trust_list)
623         {
624           priv->trust_list = trust_list;
625           trust_list = NULL;
626         }
627       if (!priv->subjects)
628         {
629           priv->subjects = subjects;
630           subjects = NULL;
631         }
632       if (!priv->issuers)
633         {
634           priv->issuers = issuers;
635           issuers = NULL;
636         }
637       if (!priv->complete)
638         {
639           priv->complete = complete;
640           complete = NULL;
641         }
642       g_mutex_unlock (&priv->mutex);
643     }
644
645 out:
646   if (trust_list != NULL)
647     gnutls_x509_trust_list_deinit (trust_list, 1);
648   if (subjects != NULL)
649     g_hash_table_unref (subjects);
650   if (issuers != NULL)
651     g_hash_table_unref (issuers);
652   if (complete != NULL)
653     g_hash_table_unref (complete);
654   return result;
655 }
656
657 static void
658 g_tls_database_gnutls_initable_interface_init (GInitableIface *iface)
659 {
660   iface->init = g_tls_database_gnutls_initable_init;
661 }
662
663 GTlsDatabaseGnutls *
664 g_tls_database_gnutls_new (GError **error)
665 {
666   g_return_val_if_fail (!error || !*error, NULL);
667
668   return g_initable_new (G_TYPE_TLS_DATABASE_GNUTLS, NULL, error, NULL);
669 }