[glib-networking/tls-database] gnutls: Supply GTlsDatabase in backend, and use for cert verification.
- From: Stefan Walter <stefw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib-networking/tls-database] gnutls: Supply GTlsDatabase in backend, and use for cert verification.
- Date: Tue, 28 Dec 2010 10:39:04 +0000 (UTC)
commit 033e8dfcc6ce428f80ee2972efa80b22931f8ece
Author: Stef Walter <stefw collabora co uk>
Date: Tue Dec 28 04:37:16 2010 -0600
gnutls: Supply GTlsDatabase in backend, and use for cert verification.
* Replace the certificate verification with GTlsDatabase
* Implement the necessary bits to expose the gnutls file database
via GTlsBackend.
* Update GTlsFileDatabaseGnutls to match GTlsFileDatabase changes.
* GTlsFileDatabaseGnutls no longer assumes that GHashTable has
thread-safe lookups.
tls/gnutls/gtlsbackend-gnutls.c | 124 ++++++++++++++---------------
tls/gnutls/gtlsbackend-gnutls.h | 10 +--
tls/gnutls/gtlsclientconnection-gnutls.c | 23 +++++-
tls/gnutls/gtlsconnection-gnutls.c | 46 +++--------
tls/gnutls/gtlsfiledatabase-gnutls.c | 127 ++++++++++++++---------------
tls/gnutls/gtlsserverconnection-gnutls.c | 25 ++++++-
6 files changed, 181 insertions(+), 174 deletions(-)
---
diff --git a/tls/gnutls/gtlsbackend-gnutls.c b/tls/gnutls/gtlsbackend-gnutls.c
index da15b01..5028bdb 100644
--- a/tls/gnutls/gtlsbackend-gnutls.c
+++ b/tls/gnutls/gtlsbackend-gnutls.c
@@ -32,8 +32,15 @@
#include "gtlsbackend-gnutls.h"
#include "gtlscertificate-gnutls.h"
#include "gtlsclientconnection-gnutls.h"
+#include "gtlsfiledatabase-gnutls.h"
#include "gtlsserverconnection-gnutls.h"
+struct _GTlsBackendGnutlsPrivate
+{
+ GMutex *mutex;
+ GTlsDatabase *default_database;
+};
+
static void g_tls_backend_gnutls_interface_init (GTlsBackendInterface *iface);
G_DEFINE_DYNAMIC_TYPE_EXTENDED (GTlsBackendGnutls, g_tls_backend_gnutls, G_TYPE_OBJECT, 0,
@@ -120,95 +127,80 @@ g_tls_backend_gnutls_init (GTlsBackendGnutls *backend)
* g_io_modules_scan_all_in_directory()).
*/
g_once (&gnutls_inited, gtls_gnutls_init, NULL);
+
+ backend->priv = G_TYPE_INSTANCE_GET_PRIVATE (backend, G_TYPE_TLS_BACKEND_GNUTLS, GTlsBackendGnutlsPrivate);
+ backend->priv->mutex = g_mutex_new ();
}
static void
-g_tls_backend_gnutls_class_init (GTlsBackendGnutlsClass *backend_class)
+g_tls_backend_gnutls_finalize (GObject *object)
{
+ GTlsBackendGnutls *backend = G_TLS_BACKEND_GNUTLS (object);
+
+ if (backend->priv->default_database)
+ g_object_unref (backend->priv->default_database);
+ g_mutex_free (backend->priv->mutex);
+
+ G_OBJECT_CLASS (g_tls_backend_gnutls_parent_class)->finalize (object);
}
static void
-g_tls_backend_gnutls_class_finalize (GTlsBackendGnutlsClass *backend_class)
+g_tls_backend_gnutls_class_init (GTlsBackendGnutlsClass *backend_class)
{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (backend_class);
+ gobject_class->finalize = g_tls_backend_gnutls_finalize;
+ g_type_class_add_private (backend_class, sizeof (GTlsBackendGnutlsPrivate));
}
static void
-g_tls_backend_gnutls_interface_init (GTlsBackendInterface *iface)
+g_tls_backend_gnutls_class_finalize (GTlsBackendGnutlsClass *backend_class)
{
- iface->get_certificate_type = g_tls_certificate_gnutls_get_type;
- iface->get_client_connection_type = g_tls_client_connection_gnutls_get_type;
- iface->get_server_connection_type = g_tls_server_connection_gnutls_get_type;
}
-#ifdef GTLS_SYSTEM_CA_FILE
-/* Parsing the system CA list takes a noticeable amount of time.
- * So we only do it once, and only when we actually need to see it.
- */
-static const GList *
-get_ca_lists (gnutls_x509_crt_t **cas,
- int *num_cas)
+static GTlsDatabase*
+g_tls_backend_gnutls_get_default_database (GTlsBackend *backend)
{
- static gnutls_x509_crt_t *ca_list_gnutls;
- static int ca_list_length;
- static GList *ca_list;
+ GTlsBackendGnutls *self = G_TLS_BACKEND_GNUTLS (backend);
+ const gchar *anchor_file = NULL;
+ GTlsDatabase *result;
+ GError *error = NULL;
- if (g_once_init_enter ((volatile gsize *)&ca_list_gnutls))
- {
- GError *error = NULL;
- gnutls_x509_crt_t *x509_crts;
- GList *c;
- int i;
+ g_mutex_lock (self->priv->mutex);
- ca_list = g_tls_certificate_list_new_from_file (GTLS_SYSTEM_CA_FILE, &error);
+ if (self->priv->default_database)
+ {
+ result = g_object_ref (self->priv->default_database);
+ }
+ else
+ {
+#ifdef GTLS_SYSTEM_CA_FILE
+ anchor_file = GTLS_SYSTEM_CA_FILE;
+#endif
+ result = g_tls_file_database_new (anchor_file, &error);
if (error)
- {
- g_warning ("Failed to read system CA file %s: %s.",
- GTLS_SYSTEM_CA_FILE, error->message);
- g_error_free (error);
- /* Note that this is not a security problem, since if
- * G_TLS_VALIDATE_CA is set, then this just means validation
- * will always fail, and if it isn't set, then it doesn't
- * matter that we couldn't read the CAs.
- */
- }
-
- ca_list_length = g_list_length (ca_list);
- x509_crts = g_new (gnutls_x509_crt_t, ca_list_length);
- for (c = ca_list, i = 0; c; c = c->next, i++)
- x509_crts[i] = g_tls_certificate_gnutls_get_cert (c->data);
-
- g_once_init_leave ((volatile gsize *)&ca_list_gnutls, GPOINTER_TO_SIZE (x509_crts));
+ {
+ g_warning ("couldn't load TLS file database: %s",
+ error->message);
+ g_clear_error (&error);
+ }
+ else
+ {
+ self->priv->default_database = g_object_ref (result);
+ }
}
- if (cas)
- *cas = ca_list_gnutls;
- if (num_cas)
- *num_cas = ca_list_length;
-
- return ca_list;
-}
-#endif
+ g_mutex_unlock (self->priv->mutex);
-const GList *
-g_tls_backend_gnutls_get_system_ca_list_gtls (void)
-{
-#ifdef GTLS_SYSTEM_CA_FILE
- return get_ca_lists (NULL, NULL);
-#else
- return NULL;
-#endif
+ return result;
}
-
-void
-g_tls_backend_gnutls_get_system_ca_list_gnutls (gnutls_x509_crt_t **cas,
- int *num_cas)
+static void
+g_tls_backend_gnutls_interface_init (GTlsBackendInterface *iface)
{
-#ifdef GTLS_SYSTEM_CA_FILE
- get_ca_lists (cas, num_cas);
-#else
- *cas = NULL;
- *num_cas = 0;
-#endif
+ iface->get_certificate_type = g_tls_certificate_gnutls_get_type;
+ iface->get_client_connection_type = g_tls_client_connection_gnutls_get_type;
+ iface->get_server_connection_type = g_tls_server_connection_gnutls_get_type;
+ iface->get_file_database_type = g_tls_file_database_gnutls_get_type;
+ iface->get_default_database = g_tls_backend_gnutls_get_default_database;
}
/* Session cache support; all the details are sort of arbitrary. Note
diff --git a/tls/gnutls/gtlsbackend-gnutls.h b/tls/gnutls/gtlsbackend-gnutls.h
index 97ebd90..6ab0344 100644
--- a/tls/gnutls/gtlsbackend-gnutls.h
+++ b/tls/gnutls/gtlsbackend-gnutls.h
@@ -25,8 +25,9 @@ G_BEGIN_DECLS
#define G_IS_TLS_BACKEND_GNUTLS_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class), G_TYPE_TLS_BACKEND_GNUTLS))
#define G_TLS_BACKEND_GNUTLS_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), G_TYPE_TLS_BACKEND_GNUTLS, GTlsBackendGnutlsClass))
-typedef struct _GTlsBackendGnutlsClass GTlsBackendGnutlsClass;
-typedef struct _GTlsBackendGnutls GTlsBackendGnutls;
+typedef struct _GTlsBackendGnutls GTlsBackendGnutls;
+typedef struct _GTlsBackendGnutlsClass GTlsBackendGnutlsClass;
+typedef struct _GTlsBackendGnutlsPrivate GTlsBackendGnutlsPrivate;
struct _GTlsBackendGnutlsClass
{
@@ -36,15 +37,12 @@ struct _GTlsBackendGnutlsClass
struct _GTlsBackendGnutls
{
GObject parent_instance;
+ GTlsBackendGnutlsPrivate *priv;
};
GType g_tls_backend_gnutls_get_type (void) G_GNUC_CONST;
void g_tls_backend_gnutls_register (GIOModule *module);
-const GList *g_tls_backend_gnutls_get_system_ca_list_gtls (void) G_GNUC_CONST;
-void g_tls_backend_gnutls_get_system_ca_list_gnutls (gnutls_x509_crt_t **cas,
- int *num_cas);
-
void g_tls_backend_gnutls_cache_session_data (const gchar *session_id,
guchar *session_data,
gsize session_data_length);
diff --git a/tls/gnutls/gtlsclientconnection-gnutls.c b/tls/gnutls/gtlsclientconnection-gnutls.c
index 888f7e7..c67286b 100644
--- a/tls/gnutls/gtlsclientconnection-gnutls.c
+++ b/tls/gnutls/gtlsclientconnection-gnutls.c
@@ -316,12 +316,29 @@ g_tls_client_connection_gnutls_verify_peer (GTlsConnectionGnutls *conn_gnutls,
GTlsCertificateFlags *errors)
{
GTlsClientConnectionGnutls *gnutls = G_TLS_CLIENT_CONNECTION_GNUTLS (conn_gnutls);
+ GTlsDatabase *database;
gboolean accepted;
+ GError *error = NULL;
- if (gnutls->priv->server_identity)
+ database = g_tls_connection_get_database (G_TLS_CONNECTION (conn_gnutls));
+ if (database == NULL)
+ {
+ *errors |= G_TLS_CERTIFICATE_UNKNOWN_CA;
+ *errors |= g_tls_certificate_verify (peer_certificate, gnutls->priv->server_identity, NULL);
+ }
+ else
{
- *errors |= g_tls_certificate_gnutls_verify_identity (G_TLS_CERTIFICATE_GNUTLS (peer_certificate),
- gnutls->priv->server_identity);
+ *errors |= g_tls_database_verify_chain (database, peer_certificate,
+ G_TLS_DATABASE_PURPOSE_SERVER_AUTH,
+ gnutls->priv->server_identity,
+ G_TLS_DATABASE_VERIFY_NONE,
+ NULL, &error);
+ if (error)
+ {
+ g_warning ("failure verifying certificate chain: %s",
+ error->message);
+ g_clear_error (&error);
+ }
}
if (*errors & gnutls->priv->validation_flags)
diff --git a/tls/gnutls/gtlsconnection-gnutls.c b/tls/gnutls/gtlsconnection-gnutls.c
index c0fb898..2937996 100644
--- a/tls/gnutls/gtlsconnection-gnutls.c
+++ b/tls/gnutls/gtlsconnection-gnutls.c
@@ -98,7 +98,7 @@ enum
PROP_BASE_IO_STREAM,
PROP_REQUIRE_CLOSE_NOTIFY,
PROP_REHANDSHAKE_MODE,
- PROP_USE_SYSTEM_CERTDB,
+ PROP_DATABASE,
PROP_CERTIFICATE,
PROP_PEER_CERTIFICATE,
PROP_PEER_CERTIFICATE_ERRORS
@@ -110,7 +110,6 @@ struct _GTlsConnectionGnutlsPrivate
GPollableInputStream *base_istream;
GPollableOutputStream *base_ostream;
- GList *ca_list;
gnutls_certificate_credentials creds;
gnutls_session session;
@@ -118,7 +117,7 @@ struct _GTlsConnectionGnutlsPrivate
GTlsCertificateFlags peer_certificate_errors;
gboolean require_close_notify;
GTlsRehandshakeMode rehandshake_mode;
- gboolean use_system_certdb;
+ GTlsDatabase *database;
gboolean need_handshake, handshaking, ever_handshaked;
gboolean closing;
@@ -157,7 +156,7 @@ g_tls_connection_gnutls_class_init (GTlsConnectionGnutlsClass *klass)
g_object_class_override_property (gobject_class, PROP_BASE_IO_STREAM, "base-io-stream");
g_object_class_override_property (gobject_class, PROP_REQUIRE_CLOSE_NOTIFY, "require-close-notify");
g_object_class_override_property (gobject_class, PROP_REHANDSHAKE_MODE, "rehandshake-mode");
- g_object_class_override_property (gobject_class, PROP_USE_SYSTEM_CERTDB, "use-system-certdb");
+ g_object_class_override_property (gobject_class, PROP_DATABASE, "database");
g_object_class_override_property (gobject_class, PROP_CERTIFICATE, "certificate");
g_object_class_override_property (gobject_class, PROP_PEER_CERTIFICATE, "peer-certificate");
g_object_class_override_property (gobject_class, PROP_PEER_CERTIFICATE_ERRORS, "peer-certificate-errors");
@@ -172,6 +171,8 @@ g_tls_connection_gnutls_initable_iface_init (GInitableIface *iface)
static void
g_tls_connection_gnutls_init (GTlsConnectionGnutls *gnutls)
{
+ GTlsBackend *backend;
+
gnutls->priv = G_TYPE_INSTANCE_GET_PRIVATE (gnutls, G_TYPE_TLS_CONNECTION_GNUTLS, GTlsConnectionGnutlsPrivate);
gnutls_certificate_allocate_credentials (&gnutls->priv->creds);
@@ -179,6 +180,9 @@ g_tls_connection_gnutls_init (GTlsConnectionGnutls *gnutls)
GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT);
gnutls->priv->need_handshake = TRUE;
+
+ backend = g_tls_backend_get_default ();
+ gnutls->priv->database = g_tls_backend_get_default_database (backend);
}
static gnutls_priority_t priorities[2][2];
@@ -274,6 +278,8 @@ g_tls_connection_gnutls_finalize (GObject *object)
if (connection->priv->creds)
gnutls_certificate_free_credentials (connection->priv->creds);
+ if (connection->priv->database)
+ g_object_unref (connection->priv->database);
if (connection->priv->certificate)
g_object_unref (connection->priv->certificate);
if (connection->priv->peer_certificate)
@@ -307,8 +313,8 @@ g_tls_connection_gnutls_get_property (GObject *object,
g_value_set_enum (value, gnutls->priv->rehandshake_mode);
break;
- case PROP_USE_SYSTEM_CERTDB:
- g_value_set_boolean (value, gnutls->priv->use_system_certdb);
+ case PROP_DATABASE:
+ g_value_set_object (value, gnutls->priv->database);
break;
case PROP_CERTIFICATE:
@@ -370,18 +376,8 @@ g_tls_connection_gnutls_set_property (GObject *object,
gnutls->priv->rehandshake_mode = g_value_get_enum (value);
break;
- case PROP_USE_SYSTEM_CERTDB:
- gnutls->priv->use_system_certdb = g_value_get_boolean (value);
-
- gnutls_certificate_free_cas (gnutls->priv->creds);
- if (gnutls->priv->use_system_certdb)
- {
- gnutls_x509_crt_t *cas;
- int num_cas;
-
- g_tls_backend_gnutls_get_system_ca_list_gnutls (&cas, &num_cas);
- gnutls_certificate_set_x509_trust (gnutls->priv->creds, cas, num_cas);
- }
+ case PROP_DATABASE:
+ gnutls->priv->database = g_value_dup_object (value);
break;
case PROP_CERTIFICATE:
@@ -855,20 +851,6 @@ handshake_internal (GTlsConnectionGnutls *gnutls,
if (peer_certificate)
{
- int status;
-
- status = gnutls_certificate_verify_peers (gnutls->priv->session);
- peer_certificate_errors = g_tls_certificate_gnutls_convert_flags (status);
- if (peer_certificate_errors)
- {
- /* gnutls_certificate_verify_peers() bails out on the first
- * error, which may be G_TLS_CERTIFICATE_UNKNOWN_CA, but the
- * caller may be planning to check that part themselves. So
- * call g_tls_certificate_verify() to get any other errors.
- */
- peer_certificate_errors |= g_tls_certificate_verify (peer_certificate, NULL, NULL);
- }
-
if (!G_TLS_CONNECTION_GNUTLS_GET_CLASS (gnutls)->verify_peer (gnutls, peer_certificate, &peer_certificate_errors))
{
g_object_unref (peer_certificate);
diff --git a/tls/gnutls/gtlsfiledatabase-gnutls.c b/tls/gnutls/gtlsfiledatabase-gnutls.c
index 4917867..34cfe31 100644
--- a/tls/gnutls/gtlsfiledatabase-gnutls.c
+++ b/tls/gnutls/gtlsfiledatabase-gnutls.c
@@ -28,13 +28,21 @@
#include <glib/gi18n-lib.h>
#include <gnutls/x509.h>
-G_DEFINE_TYPE (GTlsFileDatabaseGnutls, g_tls_file_database_gnutls,
- G_TYPE_TLS_DATABASE_GNUTLS);
+static void g_tls_file_database_gnutls_file_database_interface_init (GTlsFileDatabaseInterface *iface);
+
+static void g_tls_file_database_gnutls_initable_interface_init (GInitableIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (GTlsFileDatabaseGnutls, g_tls_file_database_gnutls, G_TYPE_TLS_DATABASE_GNUTLS,
+ G_IMPLEMENT_INTERFACE (G_TYPE_TLS_FILE_DATABASE,
+ g_tls_file_database_gnutls_file_database_interface_init);
+ G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
+ g_tls_file_database_gnutls_initable_interface_init);
+);
enum
{
PROP_0,
- PROP_ANCHOR_FILENAME,
+ PROP_ANCHOR_FILE,
};
struct _GTlsFileDatabaseGnutlsPrivate
@@ -43,7 +51,7 @@ struct _GTlsFileDatabaseGnutlsPrivate
gchar *anchor_filename;
/* protected by mutex */
- GStaticMutex mutex;
+ GMutex *mutex;
GHashTable *anchors;
};
@@ -142,48 +150,6 @@ load_anchor_file (const gchar *filename,
return TRUE;
}
-static GHashTable*
-ensure_and_ref_anchors (GTlsFileDatabaseGnutls *self)
-{
- GHashTable *anchors;
- GError *error = NULL;
-
- g_static_mutex_lock (&self->priv->mutex);
-
- if (self->priv->anchors)
- {
- anchors = g_hash_table_ref (self->priv->anchors);
- }
- else
- {
- anchors = g_hash_table_new_full (byte_array_hash, byte_array_equal,
- (GDestroyNotify)g_byte_array_unref,
- (GDestroyNotify)g_byte_array_unref);
-
- if (load_anchor_file (self->priv->anchor_filename, anchors, &error))
- {
- self->priv->anchors = g_hash_table_ref (anchors);
- }
- else
- {
- /*
- * Note that this is not a security problem, since if
- * G_TLS_VALIDATE_CA is set, then this just means validation
- * will always fail, and if it isn't set, then it doesn't
- * matter that we couldn't read the CAs.
- */
- g_warning ("couldn't load certificate anchor file: %s: %s",
- self->priv->anchor_filename,
- error && error->message ? error->message : "");
- }
- }
-
- g_static_mutex_unlock (&self->priv->mutex);
-
- /* We always return one, even if it's just empty */
- return anchors;
-}
-
static void
g_tls_file_database_gnutls_finalize (GObject *object)
{
@@ -195,7 +161,7 @@ g_tls_file_database_gnutls_finalize (GObject *object)
g_free (self->priv->anchor_filename);
self->priv->anchor_filename = NULL;
- g_static_mutex_free (&self->priv->mutex);
+ g_mutex_free (self->priv->mutex);
G_OBJECT_CLASS (g_tls_file_database_gnutls_parent_class)->finalize (object);
}
@@ -210,7 +176,7 @@ g_tls_file_database_gnutls_get_property (GObject *object,
switch (prop_id)
{
- case PROP_ANCHOR_FILENAME:
+ case PROP_ANCHOR_FILE:
g_value_set_string (value, self->priv->anchor_filename);
break;
default:
@@ -228,7 +194,7 @@ g_tls_file_database_gnutls_set_property (GObject *object,
switch (prop_id)
{
- case PROP_ANCHOR_FILENAME:
+ case PROP_ANCHOR_FILE:
self->priv->anchor_filename = g_value_dup_string (value);
break;
default:
@@ -242,7 +208,7 @@ g_tls_file_database_gnutls_init (GTlsFileDatabaseGnutls *self)
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
G_TYPE_TLS_FILE_DATABASE_GNUTLS,
GTlsFileDatabaseGnutlsPrivate);
- g_static_mutex_init (&self->priv->mutex);
+ self->priv->mutex = g_mutex_new ();
}
static gboolean
@@ -257,7 +223,6 @@ g_tls_file_database_gnutls_lookup_assertion (GTlsDatabaseGnutls *databa
GTlsFileDatabaseGnutls *self = G_TLS_FILE_DATABASE_GNUTLS (database);
GByteArray *der = NULL;
gboolean contains;
- GHashTable *anchors;
g_return_val_if_fail (G_IS_TLS_CERTIFICATE_GNUTLS (certificate), FALSE);
g_return_val_if_fail (purpose, FALSE);
@@ -276,10 +241,11 @@ g_tls_file_database_gnutls_lookup_assertion (GTlsDatabaseGnutls *databa
g_object_get (certificate, "certificate", &der, NULL);
g_return_val_if_fail (der, FALSE);
- anchors = ensure_and_ref_anchors (self);
- contains = g_hash_table_lookup (anchors, der) ? TRUE : FALSE;
+ g_mutex_lock (self->priv->mutex);
+ contains = g_hash_table_lookup (self->priv->anchors, der) ? TRUE : FALSE;
+ g_mutex_unlock (self->priv->mutex);
+
g_byte_array_unref (der);
- g_hash_table_unref (anchors);
/* All certificates in our file are anchored certificates */
return contains;
@@ -294,7 +260,6 @@ g_tls_file_database_gnutls_lookup_issuer (GTlsDatabase *database,
GTlsFileDatabaseGnutls *self = G_TLS_FILE_DATABASE_GNUTLS (database);
gnutls_datum_t dn = { NULL, 0 };
GByteArray *subject, *der;
- GHashTable *anchors;
gnutls_datum_t datum;
GTlsCertificate *issuer = NULL;
gnutls_x509_crt_t cert;
@@ -317,8 +282,9 @@ g_tls_file_database_gnutls_lookup_issuer (GTlsDatabase *database,
gnutls_free (dn.data);
/* Find the full DER value of the certificate */
- anchors = ensure_and_ref_anchors (self);
- der = g_hash_table_lookup (anchors, subject);
+ g_mutex_lock (self->priv->mutex);
+ der = g_hash_table_lookup (self->priv->anchors, subject);
+ g_mutex_unlock (self->priv->mutex);
g_byte_array_unref (subject);
@@ -329,7 +295,6 @@ g_tls_file_database_gnutls_lookup_issuer (GTlsDatabase *database,
issuer = g_tls_certificate_gnutls_new (&datum, NULL);
}
- g_hash_table_unref (anchors);
return issuer;
}
@@ -349,12 +314,42 @@ g_tls_file_database_gnutls_class_init (GTlsFileDatabaseGnutlsClass *klass)
database_class->lookup_issuer = g_tls_file_database_gnutls_lookup_issuer;
gnutls_class->lookup_assertion = g_tls_file_database_gnutls_lookup_assertion;
- g_object_class_install_property (gobject_class, PROP_ANCHOR_FILENAME,
- g_param_spec_string ("anchor-filename",
- N_("Anchor Filename"),
- N_("Path to system certificate anchor file"),
- NULL,
- G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT |
- G_PARAM_STATIC_STRINGS));
+ g_object_class_override_property (gobject_class, PROP_ANCHOR_FILE, "anchor-file");
+}
+
+static void
+g_tls_file_database_gnutls_file_database_interface_init (GTlsFileDatabaseInterface *iface)
+{
+
+}
+
+static gboolean
+g_tls_file_database_gnutls_initable_init (GInitable *initable,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GTlsFileDatabaseGnutls *self = G_TLS_FILE_DATABASE_GNUTLS (initable);
+ GHashTable *anchors;
+
+ anchors = g_hash_table_new_full (byte_array_hash, byte_array_equal,
+ (GDestroyNotify)g_byte_array_unref,
+ (GDestroyNotify)g_byte_array_unref);
+
+ if (!load_anchor_file (self->priv->anchor_filename, anchors, error))
+ {
+ g_hash_table_unref (anchors);
+ return FALSE;
+ }
+
+ g_mutex_lock (self->priv->mutex);
+ g_assert (!self->priv->anchors);
+ self->priv->anchors = anchors;
+ g_mutex_unlock (self->priv->mutex);
+ return TRUE;
+}
+
+static void
+g_tls_file_database_gnutls_initable_interface_init (GInitableIface *iface)
+{
+ iface->init = g_tls_file_database_gnutls_initable_init;
}
diff --git a/tls/gnutls/gtlsserverconnection-gnutls.c b/tls/gnutls/gtlsserverconnection-gnutls.c
index e374b63..2223277 100644
--- a/tls/gnutls/gtlsserverconnection-gnutls.c
+++ b/tls/gnutls/gtlsserverconnection-gnutls.c
@@ -174,8 +174,31 @@ g_tls_server_connection_gnutls_verify_peer (GTlsConnectionGnutls *gnutls,
GTlsCertificate *peer_certificate,
GTlsCertificateFlags *errors)
{
+ GTlsDatabase *database;
+ GError *error = NULL;
+
+ database = g_tls_connection_get_database (G_TLS_CONNECTION (gnutls));
+ if (database == NULL)
+ {
+ *errors |= G_TLS_CERTIFICATE_UNKNOWN_CA;
+ *errors |= g_tls_certificate_verify (peer_certificate, NULL, NULL);
+ }
+ else
+ {
+ *errors |= g_tls_database_verify_chain (database, peer_certificate,
+ G_TLS_DATABASE_PURPOSE_CLIENT_AUTH,
+ NULL, G_TLS_DATABASE_VERIFY_NONE,
+ NULL, &error);
+ if (error)
+ {
+ g_warning ("failure verifying certificate chain: %s",
+ error->message);
+ g_clear_error (&error);
+ }
+ }
+
return g_tls_connection_emit_accept_certificate (G_TLS_CONNECTION (gnutls),
- peer_certificate, *errors);
+ peer_certificate, *errors);
}
static void
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]