[glib-networking] Use the GnuTLS system trust by default
- From: Michael Catanzaro <mcatanzaro src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib-networking] Use the GnuTLS system trust by default
- Date: Wed, 7 Mar 2018 02:08:03 +0000 (UTC)
commit f1c8feee014007cc913b71357acb609f8d1200df
Author: Michael Catanzaro <mcatanzaro igalia com>
Date: Thu Feb 8 22:02:06 2018 -0600
Use the GnuTLS system trust by default
Get rid of the ca_certificates_path build flag. The default GTlsDatabase
will now use the GnuTLS system trust. GTlsFileDatabase now builds its
internal hash tables by iterating its gnutls_x509_trust_list_t, rather
than by parsing its certificate file manually.
The find-ca-certificates script is removed, since it's no longer needed.
There are some potential compatibility risks here:
* The minimum required GnuTLS version is increased from 3.3.5 to 3.4.
* If GnuTLS is not configured with a system trust, all certificate
verification using the default GTlsDatabase will fail. I noticed that
GNOME's flatpak runtime does not configure a system trust, so this
breaks HTTPS there. This is sad for Epiphany Technology Preview, but
we should do this anyway, and separately fix the GNOME runtime.
* It was previously possible to configure glib-networking using
--without-ca-certificates to ensure the default GTlsDatabase is
empty (GNOME #727282). Apparently this was desirable on some embedded
systems, though I'm not sure why. Such configuration is still
possible by configuring GnuTLS with no system trust. Presumably,
anybody relying on this behavior will notice that the
--without-ca-certificates flag has disappeared during the build
system change and investigate, so this seems unproblematic.
* The default GTlsDatabase is a GTlsFileDatabase, but it might not
actually correspond to a file anymore. This will be fixed in the next
commit.
* If the anchors property of a GTlsFileDatabase is NULL, that
previously indicated an empty GTlsFileDatabase, but now indicates
that the system trust is used. This will also be fixed in the next
commit.
* Certificate handles created using the default GTlsDatabase will be
different before and after this commit. This seems unlikely to cause
problems in practice, since a quick Debian codesearch reveals zero
applications using our certificate handles. But, if an application
were to rely on handles generated by previous versions of
glib-networking being valid in the new version, it would break.
None of the above seem likely to cause practical issues, once
distributors ensure that GnuTLS is built properly, so I think we can
proceed.
https://bugzilla.gnome.org/show_bug.cgi?id=753260
find-ca-certificates | 20 ------
meson.build | 10 +---
meson_options.txt | 1 -
tls/gnutls/gtlsbackend-gnutls.c | 6 +--
tls/gnutls/gtlsfiledatabase-gnutls.c | 117 ++++++++++++++++++---------------
5 files changed, 66 insertions(+), 88 deletions(-)
---
diff --git a/meson.build b/meson.build
index cf6782c..ee2bd9d 100644
--- a/meson.build
+++ b/meson.build
@@ -62,14 +62,7 @@ if enable_gnome_proxy_support
endif
# *** Checks for GnuTLS ***
-gnutls_dep = dependency('gnutls', version: '>= 3.3.5', required: true)
-
-msg = 'location of system Certificate Authority list: '
-res = run_command(join_paths(meson.source_root(), 'find-ca-certificates'),
get_option('ca_certificates_path'))
-assert(res.returncode() == 0, msg + ' could not find any CA certificate store. Use
-Dca_certificates_path=PATH to set')
-ca_certificates_path = res.stdout().strip()
-message(msg + ca_certificates_path)
-config_h.set_quoted('GTLS_SYSTEM_CA_FILE', ca_certificates_path, description: 'The system CA list')
+gnutls_dep = dependency('gnutls', version: '>= 3.4', required: true)
# *** Checks for p11-kit ***
enable_pkcs11_support = get_option('pkcs11_support')
@@ -126,5 +119,4 @@ meson.add_install_script('meson_post_install.py', gio_module_dir)
output = '\n\n libproxy support: ' + enable_libproxy_support.to_string() + '\n'
output += ' GNOME proxy support: ' + enable_gnome_proxy_support.to_string() + '\n'
output += ' PKCS#11 support: ' + enable_pkcs11_support.to_string() + '\n'
-output += ' TLS CA file: ' + ca_certificates_path + '\n'
message(output)
diff --git a/meson_options.txt b/meson_options.txt
index 8cf58ed..1e04d19 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -1,6 +1,5 @@
option('libproxy_support', type: 'boolean', value: true, description: 'support for libproxy proxy
configration')
option('gnome_proxy_support', type: 'boolean', value: true, description: 'support for GNOME desktop proxy
configuration')
-option('ca_certificates_path', type: 'string', value: '', description: 'path to system Certificate Authority
list')
option('pkcs11_support', type: 'boolean', value: true, description: 'support for PKCS#11 using p11-kit')
option('installed_tests', type: 'boolean', value: false, description: 'enable installed tests')
option('static_modules', type: 'boolean', value: false, description: 'build static modules')
diff --git a/tls/gnutls/gtlsbackend-gnutls.c b/tls/gnutls/gtlsbackend-gnutls.c
index 0a6b5d4..97502d3 100644
--- a/tls/gnutls/gtlsbackend-gnutls.c
+++ b/tls/gnutls/gtlsbackend-gnutls.c
@@ -114,11 +114,7 @@ static GTlsDatabase*
g_tls_backend_gnutls_real_create_database (GTlsBackendGnutls *self,
GError **error)
{
- const gchar *anchor_file = NULL;
-#ifdef GTLS_SYSTEM_CA_FILE
- anchor_file = GTLS_SYSTEM_CA_FILE;
-#endif
- return g_tls_file_database_new (anchor_file, error);
+ return g_tls_file_database_new (NULL, error);
}
static void
diff --git a/tls/gnutls/gtlsfiledatabase-gnutls.c b/tls/gnutls/gtlsfiledatabase-gnutls.c
index 5a5c965..3fb7b4a 100644
--- a/tls/gnutls/gtlsfiledatabase-gnutls.c
+++ b/tls/gnutls/gtlsfiledatabase-gnutls.c
@@ -149,13 +149,24 @@ create_handle_for_certificate (const gchar *filename,
gchar *uri;
/*
- * Here we create a URI that looks like:
+ * Here we create a URI that looks like
*
file:///etc/ssl/certs/ca-certificates.crt#11b2641821252596420e468c275771f5e51022c121a17bd7a89a2f37b6336c8f
+ * or system-trust:#11b2641821252596420e468c275771f5e51022c121a17bd7a89a2f37b6336c8f.
+ *
+ * system-trust is a meaningless URI scheme; we just need some stable way to
+ * uniquely identify these certificates.
*/
- uri_part = g_filename_to_uri (filename, NULL, NULL);
- if (!uri_part)
- return NULL;
+ if (filename)
+ {
+ uri_part = g_filename_to_uri (filename, NULL, NULL);
+ if (!uri_part)
+ return NULL;
+ }
+ else
+ {
+ uri_part = g_strdup ("system-trust:");
+ }
bookmark = g_compute_checksum_for_bytes (G_CHECKSUM_SHA256, der);
uri = g_strconcat (uri_part, "#", bookmark, NULL);
@@ -189,40 +200,29 @@ create_handles_array_unlocked (const gchar *filename,
return handles;
}
-static gboolean
-load_anchor_file (const gchar *filename,
- GHashTable *subjects,
- GHashTable *issuers,
- GHashTable *complete,
- GError **error)
+static void
+initialize_tables (gnutls_x509_trust_list_t trust_list,
+ GHashTable *subjects,
+ GHashTable *issuers,
+ GHashTable *complete)
{
- GList *list, *l;
- gnutls_x509_crt_t cert;
+ gnutls_x509_trust_list_iter_t iter = NULL;
+ gnutls_x509_crt_t cert = NULL;
gnutls_datum_t dn;
- GBytes *der;
- GBytes *subject;
- GBytes *issuer;
+ GBytes *der = NULL;
+ GBytes *subject = NULL;
+ GBytes *issuer = NULL;
gint gerr;
- GError *my_error = NULL;
-
- list = g_tls_certificate_list_new_from_file (filename, &my_error);
- if (my_error)
- {
- g_propagate_error (error, my_error);
- return FALSE;
- }
- for (l = list; l; l = l->next)
+ while ((gerr = gnutls_x509_trust_list_iter_get_ca (trust_list, &iter, &cert)) == 0)
{
- cert = g_tls_certificate_gnutls_get_cert (l->data);
gerr = gnutls_x509_crt_get_raw_dn (cert, &dn);
if (gerr < 0)
{
g_warning ("failed to get subject of anchor certificate: %s",
gnutls_strerror (gerr));
- continue;
+ goto next;
}
-
subject = g_bytes_new_with_free_func (dn.data, dn.size, gnutls_free, dn.data);
gerr = gnutls_x509_crt_get_raw_issuer_dn (cert, &dn);
@@ -230,13 +230,18 @@ load_anchor_file (const gchar *filename,
{
g_warning ("failed to get issuer of anchor certificate: %s",
gnutls_strerror (gerr));
- continue;
+ goto next;
}
-
issuer = g_bytes_new_with_free_func (dn.data, dn.size, gnutls_free, dn.data);
- der = g_tls_certificate_gnutls_get_bytes (l->data);
- g_return_val_if_fail (der != NULL, FALSE);
+ gerr = gnutls_x509_crt_export2 (cert, GNUTLS_X509_FMT_DER, &dn);
+ if (gerr < 0)
+ {
+ g_warning ("failed to get certificate DER: %s",
+ gnutls_strerror (gerr));
+ goto next;
+ }
+ der = g_bytes_new_with_free_func (dn.data, dn.size, gnutls_free, dn.data);
/* Three different ways of looking up same certificate */
bytes_multi_table_insert (subjects, subject, der);
@@ -245,15 +250,12 @@ load_anchor_file (const gchar *filename,
g_hash_table_insert (complete, g_bytes_ref (der),
g_bytes_ref (der));
- g_bytes_unref (der);
- g_bytes_unref (subject);
- g_bytes_unref (issuer);
-
- g_object_unref (l->data);
+next:
+ g_clear_pointer (&der, g_bytes_unref);
+ g_clear_pointer (&subject, g_bytes_unref);
+ g_clear_pointer (&issuer, g_bytes_unref);
+ g_clear_pointer (&cert, gnutls_x509_crt_deinit);
}
- g_list_free (list);
-
- return TRUE;
}
@@ -267,11 +269,10 @@ g_tls_file_database_gnutls_finalize (GObject *object)
g_clear_pointer (&self->issuers, g_hash_table_destroy);
g_clear_pointer (&self->complete, g_hash_table_destroy);
g_clear_pointer (&self->handles, g_hash_table_destroy);
- if (self->anchor_filename)
- {
- g_free (self->anchor_filename);
- gnutls_x509_trust_list_deinit (self->trust_list, 1);
- }
+ g_clear_pointer (&self->anchor_filename, g_free);
+
+ gnutls_x509_trust_list_deinit (self->trust_list, 1);
+
g_mutex_clear (&self->mutex);
G_OBJECT_CLASS (g_tls_file_database_gnutls_parent_class)->finalize (object);
@@ -303,6 +304,7 @@ g_tls_file_database_gnutls_set_property (GObject *object,
{
GTlsFileDatabaseGnutls *self = G_TLS_FILE_DATABASE_GNUTLS (object);
const char *anchor_path;
+ int gerr;
switch (prop_id)
{
@@ -320,11 +322,24 @@ g_tls_file_database_gnutls_set_property (GObject *object,
g_free (self->anchor_filename);
gnutls_x509_trust_list_deinit (self->trust_list, 1);
}
+
self->anchor_filename = g_strdup (anchor_path);
gnutls_x509_trust_list_init (&self->trust_list, 0);
- gnutls_x509_trust_list_add_trust_file (self->trust_list,
- anchor_path, NULL,
- GNUTLS_X509_FMT_PEM, 0, 0);
+
+ if (self->anchor_filename)
+ {
+ gnutls_x509_trust_list_add_trust_file (self->trust_list,
+ anchor_path, NULL,
+ GNUTLS_X509_FMT_PEM, 0, 0);
+ }
+ else
+ {
+ gerr = gnutls_x509_trust_list_add_system_trust (self->trust_list, 0, 0);
+ if (gerr == GNUTLS_E_UNIMPLEMENTED_FEATURE)
+ g_warning ("Failed to load system trust store: gnutls_x509_trust_list_add_system_trust is not
implemented for this platform");
+ else if (gerr < 0)
+ g_warning ("Failed to load system trust store: %s", gnutls_strerror (gerr));
+ }
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -641,7 +656,7 @@ g_tls_file_database_gnutls_initable_init (GInitable *initable,
{
GTlsFileDatabaseGnutls *self = G_TLS_FILE_DATABASE_GNUTLS (initable);
GHashTable *subjects, *issuers, *complete;
- gboolean result;
+ gboolean result = TRUE;
if (g_cancellable_set_error_if_cancelled (cancellable, error))
return FALSE;
@@ -653,11 +668,7 @@ g_tls_file_database_gnutls_initable_init (GInitable *initable,
(GDestroyNotify)g_bytes_unref,
(GDestroyNotify)g_bytes_unref);
- if (self->anchor_filename)
- result = load_anchor_file (self->anchor_filename, subjects, issuers,
- complete, error);
- else
- result = TRUE;
+ initialize_tables (self->trust_list, subjects, issuers, complete);
if (g_cancellable_set_error_if_cancelled (cancellable, error))
result = FALSE;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]