1 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
3 * GIO - GLib Input, Output and Streaming Library
5 * Copyright 2010 Collabora, Ltd
6 * Copyright 2018 Igalia S.L.
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.
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.
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/>.
22 * In addition, when the library is used with OpenSSL, a special
23 * exception applies. Refer to the LICENSE_EXCEPTION file for details.
25 * Author: Stef Walter <stefw@collabora.co.uk>
30 #include "gtlsdatabase-gnutls.h"
33 #include <glib/gi18n-lib.h>
34 #include <gnutls/x509.h>
36 #include "gtlscertificate-gnutls.h"
41 * This class is protected by mutex because the default GTlsDatabase
42 * is a global singleton, accessible via the default GTlsBackend.
46 /* read-only after construct */
47 gnutls_x509_trust_list_t trust_list;
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
58 * This is a table of GBytes -> GBytes. The values and keys are
59 * DER encoded certificate values.
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.
69 } GTlsDatabaseGnutlsPrivate;
71 static void g_tls_database_gnutls_initable_interface_init (GInitableIface *iface);
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);
80 bytes_multi_table_new (void)
82 return g_hash_table_new_full (g_bytes_hash, g_bytes_equal,
83 (GDestroyNotify)g_bytes_unref,
84 (GDestroyNotify)g_ptr_array_unref);
88 bytes_multi_table_insert (GHashTable *table,
94 multi = g_hash_table_lookup (table, key);
97 multi = g_ptr_array_new_with_free_func ((GDestroyNotify)g_bytes_unref);
98 g_hash_table_insert (table, g_bytes_ref (key), multi);
100 g_ptr_array_add (multi, g_bytes_ref (value));
104 bytes_multi_table_lookup_ref_one (GHashTable *table,
109 multi = g_hash_table_lookup (table, key);
113 g_assert (multi->len > 0);
114 return g_bytes_ref (multi->pdata[0]);
118 bytes_multi_table_lookup_ref_all (GHashTable *table,
125 multi = g_hash_table_lookup (table, key);
129 for (i = 0; i < multi->len; i++)
130 list = g_list_prepend (list, g_bytes_ref (multi->pdata[i]));
132 return g_list_reverse (list);
136 create_handles_array_unlocked (GTlsDatabaseGnutls *self,
137 GHashTable *complete)
144 handles = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
145 (GDestroyNotify)g_bytes_unref);
147 g_hash_table_iter_init (&iter, complete);
148 while (g_hash_table_iter_next (&iter, NULL, (gpointer *)&der))
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);
153 g_hash_table_insert (handles, handle, g_bytes_ref (der));
160 initialize_tables (gnutls_x509_trust_list_t trust_list,
161 GHashTable *subjects,
163 GHashTable *complete)
165 gnutls_x509_trust_list_iter_t iter = NULL;
166 gnutls_x509_crt_t cert = NULL;
169 GBytes *subject = NULL;
170 GBytes *issuer = NULL;
173 while ((gerr = gnutls_x509_trust_list_iter_get_ca (trust_list, &iter, &cert)) == 0)
175 gerr = gnutls_x509_crt_get_raw_dn (cert, &dn);
178 g_warning ("failed to get subject of anchor certificate: %s",
179 gnutls_strerror (gerr));
182 subject = g_bytes_new_with_free_func (dn.data, dn.size, gnutls_free, dn.data);
184 gerr = gnutls_x509_crt_get_raw_issuer_dn (cert, &dn);
187 g_warning ("failed to get issuer of anchor certificate: %s",
188 gnutls_strerror (gerr));
191 issuer = g_bytes_new_with_free_func (dn.data, dn.size, gnutls_free, dn.data);
193 gerr = gnutls_x509_crt_export2 (cert, GNUTLS_X509_FMT_DER, &dn);
196 g_warning ("failed to get certificate DER: %s",
197 gnutls_strerror (gerr));
200 der = g_bytes_new_with_free_func (dn.data, dn.size, gnutls_free, dn.data);
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);
206 g_hash_table_insert (complete, g_bytes_ref (der),
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);
218 g_tls_database_gnutls_finalize (GObject *object)
220 GTlsDatabaseGnutls *self = G_TLS_DATABASE_GNUTLS (object);
221 GTlsDatabaseGnutlsPrivate *priv = g_tls_database_gnutls_get_instance_private (self);
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);
228 gnutls_x509_trust_list_deinit (priv->trust_list, 1);
230 g_mutex_clear (&priv->mutex);
232 G_OBJECT_CLASS (g_tls_database_gnutls_parent_class)->finalize (object);
236 g_tls_database_gnutls_init (GTlsDatabaseGnutls *self)
238 GTlsDatabaseGnutlsPrivate *priv = g_tls_database_gnutls_get_instance_private (self);
240 g_mutex_init (&priv->mutex);
244 g_tls_database_gnutls_create_certificate_handle (GTlsDatabase *database,
245 GTlsCertificate *certificate)
247 GTlsDatabaseGnutls *self = G_TLS_DATABASE_GNUTLS (database);
248 GTlsDatabaseGnutlsPrivate *priv = g_tls_database_gnutls_get_instance_private (self);
251 gchar *handle = NULL;
253 der = g_tls_certificate_gnutls_get_bytes (G_TLS_CERTIFICATE_GNUTLS (certificate));
254 g_return_val_if_fail (der != NULL, FALSE);
256 g_mutex_lock (&priv->mutex);
258 /* At the same time look up whether this certificate is in list */
259 contains = g_hash_table_lookup (priv->complete, der) ? TRUE : FALSE;
261 g_mutex_unlock (&priv->mutex);
263 /* Certificate is in the database */
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);
274 static GTlsCertificate *
275 g_tls_database_gnutls_lookup_certificate_for_handle (GTlsDatabase *database,
277 GTlsInteraction *interaction,
278 GTlsDatabaseLookupFlags flags,
279 GCancellable *cancellable,
282 GTlsDatabaseGnutls *self = G_TLS_DATABASE_GNUTLS (database);
283 GTlsDatabaseGnutlsPrivate *priv = g_tls_database_gnutls_get_instance_private (self);
284 GTlsCertificate *cert;
286 gnutls_datum_t datum;
289 if (g_cancellable_set_error_if_cancelled (cancellable, error))
295 g_mutex_lock (&priv->mutex);
297 /* Create the handles table if not already done */
299 priv->handles = create_handles_array_unlocked (self, priv->complete);
301 der = g_hash_table_lookup (priv->handles, handle);
305 g_mutex_unlock (&priv->mutex);
310 datum.data = (unsigned char *)g_bytes_get_data (der, &length);
313 if (g_cancellable_set_error_if_cancelled (cancellable, error))
316 cert = g_tls_certificate_gnutls_new (&datum, NULL);
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,
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;
340 g_return_val_if_fail (G_IS_TLS_CERTIFICATE_GNUTLS (certificate), NULL);
342 if (g_cancellable_set_error_if_cancelled (cancellable, error))
345 if (flags & G_TLS_DATABASE_LOOKUP_KEYPAIR)
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);
353 g_warning ("failed to get issuer of certificate: %s", gnutls_strerror (gerr));
357 subject = g_bytes_new_with_free_func (dn.data, dn.size, gnutls_free, dn.data);
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);
364 g_bytes_unref (subject);
366 if (g_cancellable_set_error_if_cancelled (cancellable, error))
370 else if (der != NULL)
372 datum.data = (unsigned char *)g_bytes_get_data (der, &length);
374 issuer = g_tls_certificate_gnutls_new (&datum, NULL);
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,
390 GTlsDatabaseGnutls *self = G_TLS_DATABASE_GNUTLS (database);
391 GTlsDatabaseGnutlsPrivate *priv = g_tls_database_gnutls_get_instance_private (self);
393 gnutls_datum_t datum;
394 GList *issued = NULL;
399 if (g_cancellable_set_error_if_cancelled (cancellable, error))
402 /* We don't have any private keys here */
403 if (flags & G_TLS_DATABASE_LOOKUP_KEYPAIR)
406 issuer = g_bytes_new_static (issuer_raw_dn->data, issuer_raw_dn->len);
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);
413 g_bytes_unref (issuer);
415 for (l = ders; l != NULL; l = g_list_next (l))
417 if (g_cancellable_set_error_if_cancelled (cancellable, error))
419 g_list_free_full (issued, g_object_unref);
424 datum.data = (unsigned char *)g_bytes_get_data (l->data, &length);
426 issued = g_list_prepend (issued, g_tls_certificate_gnutls_new (&datum, NULL));
429 g_list_free_full (ders, (GDestroyNotify)g_bytes_unref);
434 convert_certificate_chain_to_gnutls (GTlsCertificateGnutls *chain,
435 gnutls_x509_crt_t **gnutls_chain,
436 guint *gnutls_chain_length)
438 GTlsCertificate *cert;
441 g_assert (gnutls_chain);
442 g_assert (gnutls_chain_length);
444 for (*gnutls_chain_length = 0, cert = G_TLS_CERTIFICATE (chain);
445 cert; cert = g_tls_certificate_get_issuer (cert))
446 ++(*gnutls_chain_length);
448 *gnutls_chain = g_new0 (gnutls_x509_crt_t, *gnutls_chain_length);
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));
454 g_assert (i == *gnutls_chain_length);
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,
467 GTlsDatabaseGnutls *self = G_TLS_DATABASE_GNUTLS (database);
468 GTlsDatabaseGnutlsPrivate *priv = g_tls_database_gnutls_get_instance_private (self);
469 GTlsCertificateFlags result;
471 gnutls_x509_crt_t *certs;
473 const char *hostname = NULL;
474 char *free_hostname = NULL;
477 g_return_val_if_fail (G_IS_TLS_CERTIFICATE_GNUTLS (chain),
478 G_TLS_CERTIFICATE_GENERIC_ERROR);
481 if (g_cancellable_set_error_if_cancelled (cancellable, error))
482 return G_TLS_CERTIFICATE_GENERIC_ERROR;
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,
488 0, &gnutls_result, NULL);
490 if (gerr != 0 || g_cancellable_set_error_if_cancelled (cancellable, error))
493 return G_TLS_CERTIFICATE_GENERIC_ERROR;
496 result = g_tls_certificate_gnutls_convert_flags (gnutls_result);
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))
506 addr = g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (identity));
507 hostname = free_hostname = g_inet_address_to_string (addr);
511 if (!gnutls_x509_crt_check_hostname (certs[0], hostname))
512 result |= G_TLS_CERTIFICATE_BAD_IDENTITY;
513 g_free (free_hostname);
521 g_tls_database_gnutls_create_handle_for_certificate (GTlsDatabaseGnutls *self,
528 * Here we create a URI that looks like
529 * system-trust:#11b2641821252596420e468c275771f5e51022c121a17bd7a89a2f37b6336c8f.
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.
536 bookmark = g_compute_checksum_for_bytes (G_CHECKSUM_SHA256, der);
537 uri = g_strconcat ("system-trust:#", bookmark, NULL);
545 g_tls_database_gnutls_populate_trust_list (GTlsDatabaseGnutls *self,
546 gnutls_x509_trust_list_t trust_list,
549 int gerr = gnutls_x509_trust_list_add_system_trust (trust_list, 0, 0);
550 if (gerr == GNUTLS_E_UNIMPLEMENTED_FEATURE)
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"));
557 g_set_error (error, G_TLS_ERROR, G_TLS_ERROR_MISC,
558 _("Failed to load system trust store: %s"),
559 gnutls_strerror (gerr));
565 g_tls_database_gnutls_class_init (GTlsDatabaseGnutlsClass *klass)
567 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
568 GTlsDatabaseClass *database_class = G_TLS_DATABASE_CLASS (klass);
570 gobject_class->finalize = g_tls_database_gnutls_finalize;
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;
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;
583 g_tls_database_gnutls_initable_init (GInitable *initable,
584 GCancellable *cancellable,
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;
595 if (g_cancellable_set_error_if_cancelled (cancellable, error))
598 gnutls_x509_trust_list_init (&trust_list, 0);
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))
607 subjects = bytes_multi_table_new ();
608 issuers = bytes_multi_table_new ();
610 complete = g_hash_table_new_full (g_bytes_hash, g_bytes_equal,
611 (GDestroyNotify)g_bytes_unref,
612 (GDestroyNotify)g_bytes_unref);
614 initialize_tables (trust_list, subjects, issuers, complete);
616 if (g_cancellable_set_error_if_cancelled (cancellable, error))
621 g_mutex_lock (&priv->mutex);
622 if (!priv->trust_list)
624 priv->trust_list = trust_list;
629 priv->subjects = subjects;
634 priv->issuers = issuers;
639 priv->complete = complete;
642 g_mutex_unlock (&priv->mutex);
646 if (trust_list != NULL)
647 gnutls_x509_trust_list_deinit (trust_list, 1);
648 if (subjects != NULL)
649 g_hash_table_unref (subjects);
651 g_hash_table_unref (issuers);
652 if (complete != NULL)
653 g_hash_table_unref (complete);
658 g_tls_database_gnutls_initable_interface_init (GInitableIface *iface)
660 iface->init = g_tls_database_gnutls_initable_init;
664 g_tls_database_gnutls_new (GError **error)
666 g_return_val_if_fail (!error || !*error, NULL);
668 return g_initable_new (G_TYPE_TLS_DATABASE_GNUTLS, NULL, error, NULL);