[gnome-keyring/trust-store: 7/7] [gcr] Implement gcr_trust_xxx() functions.
- From: Stefan Walter <stefw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-keyring/trust-store: 7/7] [gcr] Implement gcr_trust_xxx() functions.
- Date: Sat, 18 Sep 2010 17:27:41 +0000 (UTC)
commit 62f95ff4566d353d8bc94e10c40d39cf5c095c7c
Author: Stef Walter <stef memberwebs com>
Date: Sat Sep 18 17:20:23 2010 +0000
[gcr] Implement gcr_trust_xxx() functions.
For looking up certificate trust exceptions and trust roots.
We do not do trust chains or verification. We provide access to trust
storage.
gcr/Makefile.am | 2 +
gcr/gcr-internal.h | 12 +
gcr/gcr-library.c | 55 +++++
gcr/gcr-trust.c | 579 ++++++++++++++++++++++++++++++++++++++++++++++++
gcr/gcr-trust.h | 93 ++++++++
gcr/gcr-types.h | 4 +
gcr/gcr.h | 2 +
gcr/gkm-test.c | 60 +++++
gcr/gkm-test.h | 62 +++++
gcr/tests/Makefile.am | 1 +
gcr/tests/test-trust.c | 238 ++++++++++++++++++++
po/POTFILES.in | 1 +
12 files changed, 1109 insertions(+), 0 deletions(-)
---
diff --git a/gcr/Makefile.am b/gcr/Makefile.am
index b1dcc9f..80492ab 100644
--- a/gcr/Makefile.am
+++ b/gcr/Makefile.am
@@ -22,6 +22,7 @@ inc_HEADERS = \
gcr-importer.h \
gcr-parser.h \
gcr-simple-certificate.h \
+ gcr-trust.h \
gcr-types.h \
gcr-unlock-options.h \
gcr-unlock-options-widget.h
@@ -53,6 +54,7 @@ libgcr GCR_VERSION_SUFFIX@_la_SOURCES = \
gcr-library.c \
gcr-parser.c gcr-parser.h \
gcr-simple-certificate.c gcr-simple-certificate.h \
+ gcr-trust.c gcr-trust.h \
gcr-types.h \
gcr-unlock-options.h \
gcr-unlock-options-widget.c gcr-unlock-options-widget.h \
diff --git a/gcr/gcr-internal.h b/gcr/gcr-internal.h
index a4630ab..ff036ec 100644
--- a/gcr/gcr-internal.h
+++ b/gcr/gcr-internal.h
@@ -5,8 +5,20 @@
#include <glib.h>
+#include <gck/gck.h>
+
void _gcr_initialize (void);
GList* _gcr_get_pkcs11_modules (void);
+GckSlot* _gcr_slot_for_storing_trust (GError **error);
+
+#ifdef WITH_TESTS
+
+void _gcr_set_test_pkcs11_modules (GList *modules);
+
+void _gcr_set_test_trust_slot (const gchar *uri);
+
+#endif
+
#endif /* GCR_INTERNAL_H_ */
diff --git a/gcr/gcr-library.c b/gcr/gcr-library.c
index 4317426..54557c0 100644
--- a/gcr/gcr-library.c
+++ b/gcr/gcr-library.c
@@ -33,7 +33,10 @@
#include <gcrypt.h>
+#include <glib/gi18n-lib.h>
+
static GList *all_modules = NULL;
+static const gchar *trust_slot_uri = "pkcs11:manufacturer=Gnome%20Keyring;serial=1:XDG:DEFAULT";
GQuark
gcr_data_error_get_domain (void)
@@ -44,6 +47,15 @@ gcr_data_error_get_domain (void)
return domain;
}
+GQuark
+gcr_error_get_domain (void)
+{
+ static GQuark domain = 0;
+ if (domain == 0)
+ domain = g_quark_from_static_string ("gcr-error");
+ return domain;
+}
+
/* -----------------------------------------------------------------------------
* MEMORY
*/
@@ -129,3 +141,46 @@ _gcr_get_pkcs11_modules (void)
{
return all_modules;
}
+
+GckSlot*
+_gcr_slot_for_storing_trust (GError **error)
+{
+ GList *modules;
+ GckSlot *slot;
+
+ modules = _gcr_get_pkcs11_modules ();
+
+ /*
+ * TODO: We need a better way to figure this out as far as
+ * being able to store trust. But for now just hard code in
+ * gnome-keyring.
+ */
+
+ slot = gck_modules_token_for_uri (modules, trust_slot_uri, error);
+ if (!slot) {
+ if (error && !*error) {
+ g_set_error (error, GCR_ERROR, /* TODO: */ 0,
+ _("Unable to find a place to store trust choices."));
+ }
+ }
+
+ return slot;
+}
+
+#ifdef WITH_TESTS
+
+void
+_gcr_set_test_pkcs11_modules (GList *modules)
+{
+ modules = gck_list_ref_copy (modules);
+ gck_list_unref_free (all_modules);
+ all_modules = modules;
+}
+
+void
+_gcr_set_test_trust_slot (const gchar *uri)
+{
+ trust_slot_uri = uri;
+}
+
+#endif /* WITH_TESTS */
diff --git a/gcr/gcr-trust.c b/gcr/gcr-trust.c
new file mode 100644
index 0000000..947fb71
--- /dev/null
+++ b/gcr/gcr-trust.c
@@ -0,0 +1,579 @@
+/*
+ * gnome-keyring
+ *
+ * Copyright (C) 2010 Stefan Walter
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include "gcr.h"
+#include "gcr-types.h"
+#include "gcr-internal.h"
+#include "gcr-trust.h"
+
+#include <gck/gck.h>
+
+#include <pkcs11/pkcs11n.h>
+
+/* ----------------------------------------------------------------------------------
+ * HELPERS
+ */
+
+typedef struct _GcrTrustOperation {
+ GckEnumerator *en;
+ GckAttributes *attrs;
+ GcrPurpose purpose;
+ GcrTrust trust;
+} GcrTrustOperation;
+
+static CK_ATTRIBUTE_TYPE
+attribute_type_for_purpose (GcrPurpose purpose)
+{
+ switch (purpose) {
+ case GCR_PURPOSE_SERVER_AUTH:
+ return CKA_TRUST_SERVER_AUTH;
+ case GCR_PURPOSE_CLIENT_AUTH:
+ return CKA_TRUST_CLIENT_AUTH;
+ case GCR_PURPOSE_CODE_SIGNING:
+ return CKA_TRUST_CODE_SIGNING;
+ case GCR_PURPOSE_EMAIL:
+ return CKA_TRUST_EMAIL_PROTECTION;
+ case GCR_PURPOSE_TIME_STAMPING:
+ return CKA_TRUST_TIME_STAMPING;
+ case GCR_PURPOSE_IPSEC_ENDPOINT:
+ return CKA_TRUST_IPSEC_END_SYSTEM;
+ case GCR_PURPOSE_IPSEC_TUNNEL:
+ return CKA_TRUST_IPSEC_TUNNEL;
+ case GCR_PURPOSE_IPSEC_USER:
+ return CKA_TRUST_IPSEC_USER;
+ case GCR_PURPOSE_IKE_INTERMEDIATE:
+ g_return_val_if_reached ((CK_ULONG)-1);
+ default:
+ g_return_val_if_reached ((CK_ULONG)-1);
+ };
+}
+
+static void
+trust_operation_free (gpointer data)
+{
+ GcrTrustOperation *op = data;
+ g_assert (data);
+
+ /* No reference held */
+ g_assert (GCK_IS_ENUMERATOR (op->en));
+ op->en = NULL;
+
+ g_assert (op->attrs);
+ gck_attributes_unref (op->attrs);
+ op->attrs = NULL;
+
+ g_slice_free (GcrTrustOperation, op);
+}
+
+static void
+trust_operation_init (GckEnumerator *en, GckAttributes *attrs,
+ GcrPurpose purpose, GcrTrust trust)
+{
+ GcrTrustOperation *op;
+
+ g_assert (GCK_IS_ENUMERATOR (en));
+ g_assert (!g_object_get_data (G_OBJECT (en), "trust-operation"));
+ g_assert (attrs);
+
+ op = g_slice_new0 (GcrTrustOperation);
+ op->purpose = purpose;
+ op->trust = trust;
+ op->attrs = gck_attributes_ref (attrs);
+
+ /* No reference held, GckEnumerator owns */
+ op->en = en;
+ g_object_set_data_full (G_OBJECT (en), "trust-operation", op, trust_operation_free);
+}
+
+static GcrTrustOperation*
+trust_operation_get (GckEnumerator *en)
+{
+ GcrTrustOperation *op = g_object_get_data (G_OBJECT (en), "trust-operation");
+ g_assert (op);
+ g_assert (op->en == en);
+ return op;
+}
+
+static GckAttributes*
+prepare_trust_attrs (GcrCertificate *cert)
+{
+ GckAttributes *attrs;
+ gpointer data;
+ gsize n_data;
+
+ attrs = gck_attributes_new ();
+ gck_attributes_add_ulong (attrs, CKA_CLASS, CKO_NETSCAPE_TRUST);
+
+ data = gcr_certificate_get_issuer_raw (cert, &n_data);
+ g_return_val_if_fail (data, NULL);
+ gck_attributes_add_data (attrs, CKA_ISSUER, data, n_data);
+ g_free (data);
+
+ data = gcr_certificate_get_serial_number (cert, &n_data);
+ g_return_val_if_fail (data, NULL);
+ gck_attributes_add_data (attrs, CKA_SERIAL_NUMBER, data, n_data);
+ g_free (data);
+
+ data = gcr_certificate_get_fingerprint (cert, G_CHECKSUM_SHA1, &n_data);
+ g_return_val_if_fail (data, NULL);
+ gck_attributes_add_data (attrs, CKA_CERT_SHA1_HASH, data, n_data);
+ g_free (data);
+
+ return attrs;
+}
+
+/* ----------------------------------------------------------------------------------
+ * GET CERTIFICATE EXCEPTION
+ */
+
+static GckEnumerator*
+prepare_get_certificate_exception (GcrCertificate *cert, GcrPurpose purpose)
+{
+ GckAttributes *attrs;
+ GckEnumerator *en;
+ GList *modules;
+
+ modules = _gcr_get_pkcs11_modules ();
+
+ attrs = prepare_trust_attrs (cert);
+ g_return_val_if_fail (attrs, NULL);
+
+ /*
+ * TODO: We need to be able to sort the modules by preference
+ * on which sources of trust storage we want to read over which
+ * others.
+ */
+
+ en = gck_modules_enumerate_objects (modules, attrs, 0);
+ trust_operation_init (en, attrs, purpose, GCR_TRUST_UNKNOWN);
+ gck_attributes_unref (attrs);
+
+ return en;
+}
+
+static GcrTrust
+perform_get_certificate_exception (GckEnumerator *en, GCancellable *cancel, GError **error)
+{
+ CK_ATTRIBUTE_TYPE type;
+ GcrTrustOperation *op;
+ GckObject *object;
+ gpointer data;
+ gsize n_data;
+ gulong value;
+
+ op = trust_operation_get (en);
+
+ g_assert (op != NULL);
+ g_assert (op->trust == GCR_TRUST_UNKNOWN);
+
+ type = attribute_type_for_purpose (op->purpose);
+
+ while (op->trust == GCR_TRUST_UNKNOWN) {
+ object = gck_enumerator_next (en, cancel, error);
+ if (!object)
+ break;
+
+ data = gck_object_get_data (object, type, &n_data, error);
+
+ g_object_unref (object);
+
+ if (!data)
+ break;
+
+ if (!gck_value_to_ulong (data, n_data, &value)) {
+ g_message ("an invalid sized value was received for trust attribute");
+ value = CKT_NETSCAPE_TRUST_UNKNOWN;
+ }
+
+ if (value == CKT_NETSCAPE_TRUSTED)
+ op->trust = GCR_TRUST_TRUSTED;
+ else if (value == CKT_NETSCAPE_UNTRUSTED)
+ op->trust = GCR_TRUST_UNTRUSTED;
+
+ g_free (data);
+ }
+
+ return op->trust;
+}
+
+GcrTrust
+gcr_trust_get_certificate_exception (GcrCertificate *cert, GcrPurpose purpose,
+ GCancellable *cancel, GError **error)
+{
+ GckEnumerator *en;
+ GcrTrust trust;
+
+ en = prepare_get_certificate_exception (cert, purpose);
+ g_return_val_if_fail (en, GCR_TRUST_UNKNOWN);
+
+ trust = perform_get_certificate_exception (en, cancel, error);
+
+ g_object_unref (en);
+
+ return trust;
+}
+
+static void
+thread_get_certificate_exception (GSimpleAsyncResult *res, GObject *object, GCancellable *cancel)
+{
+ GError *error = NULL;
+
+ perform_get_certificate_exception (GCK_ENUMERATOR (object), cancel, &error);
+
+ if (error != NULL) {
+ g_simple_async_result_set_from_error (res, error);
+ g_clear_error (&error);
+ }
+}
+
+void
+gcr_trust_get_certificate_exception_async (GcrCertificate *cert, GcrPurpose purpose,
+ GCancellable *cancel, GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *async;
+ GckEnumerator *en;
+
+ en = prepare_get_certificate_exception (cert, purpose);
+ g_return_if_fail (en);
+
+ async = g_simple_async_result_new (G_OBJECT (en), callback, user_data,
+ gcr_trust_get_certificate_exception_async);
+
+ g_simple_async_result_run_in_thread (async, thread_get_certificate_exception,
+ G_PRIORITY_DEFAULT, cancel);
+
+ g_object_unref (async);
+ g_object_unref (en);
+}
+
+GcrTrust
+gcr_trust_get_certificate_exception_finish (GAsyncResult *res, GError **error)
+{
+ GcrTrustOperation *op;
+ GObject *object;
+
+ object = g_async_result_get_source_object (res);
+ g_return_val_if_fail (g_simple_async_result_is_valid (res, object,
+ gcr_trust_get_certificate_exception_async), GCR_TRUST_UNKNOWN);
+
+ if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error))
+ return GCR_TRUST_UNKNOWN;
+
+ op = trust_operation_get (GCK_ENUMERATOR (object));
+ return op->trust;
+}
+
+/* ----------------------------------------------------------------------------------
+ * SET CERTIFICATE EXCEPTION
+ */
+
+static GckEnumerator*
+prepare_set_certificate_exception (GcrCertificate *cert, GcrPurpose purpose, GcrTrust trust)
+{
+ GckAttributes *attrs;
+ GckEnumerator *en;
+ GList *modules;
+
+ modules = _gcr_get_pkcs11_modules ();
+
+ attrs = prepare_trust_attrs (cert);
+ g_return_val_if_fail (attrs, NULL);
+
+ gck_attributes_add_boolean (attrs, CKA_MODIFIABLE, TRUE);
+ gck_attributes_add_boolean (attrs, CKA_TOKEN, TRUE);
+
+ /*
+ * TODO: We need to be able to sort the modules by preference
+ * on which sources of trust storage we want to read over which
+ * others.
+ */
+
+ en = gck_modules_enumerate_objects (modules, attrs, CKF_RW_SESSION);
+ trust_operation_init (en, attrs, purpose, trust);
+ gck_attributes_unref (attrs);
+
+ return en;
+}
+
+static gboolean
+perform_set_certificate_exception (GckEnumerator *en, GCancellable *cancel, GError **error)
+{
+ CK_ATTRIBUTE_TYPE type;
+ GcrTrustOperation *op;
+ GckAttributes *attrs;
+ gboolean ret = FALSE;
+ GError *lerr = NULL;
+ GckObject *object;
+ GckSession *session;
+ gulong value;
+ GckSlot *slot;
+
+ op = trust_operation_get (en);
+ g_assert (op != NULL);
+
+ /* We need an error below */
+ if (error && !*error)
+ *error = lerr;
+
+ switch (op->trust) {
+ case GCR_TRUST_UNKNOWN:
+ value = CKT_NETSCAPE_TRUST_UNKNOWN;
+ break;
+ case GCR_TRUST_UNTRUSTED:
+ value = CKT_NETSCAPE_UNTRUSTED;
+ break;
+ case GCR_TRUST_TRUSTED:
+ value = CKT_NETSCAPE_TRUSTED;
+ break;
+ }
+
+ type = attribute_type_for_purpose (op->purpose);
+ attrs = gck_attributes_new ();
+
+ object = gck_enumerator_next (en, cancel, error);
+
+ /* Only set this one attribute */
+ if (object) {
+
+ gck_attributes_add_ulong (attrs, type, value);
+ ret = gck_object_set (object, attrs, cancel, error);
+
+ /* Use all trust attributes to create trust object */
+ } else if (!*error) {
+
+ gck_attributes_add_all (attrs, op->attrs);
+ gck_attributes_add_ulong (attrs, type, value);
+
+ /* Find an appropriate token */
+ slot = _gcr_slot_for_storing_trust (error);
+ if (slot != NULL) {
+ session = gck_slot_open_session (slot, CKF_RW_SESSION, error);
+ if (session != NULL) {
+
+ object = gck_session_create_object (session, attrs, cancel, error);
+ if (object != NULL) {
+ g_object_unref (object);
+ ret = TRUE;
+ }
+
+ g_object_unref (session);
+ }
+
+ }
+
+ g_object_unref (slot);
+ }
+
+ gck_attributes_unref (attrs);
+
+ /* Our own local error pointer */
+ g_clear_error (&lerr);
+
+ return ret;
+}
+
+gboolean
+gcr_trust_set_certificate_exception (GcrCertificate *cert, GcrPurpose purpose, GcrTrust trust,
+ GCancellable *cancel, GError **error)
+{
+ GckEnumerator *en;
+ gboolean ret;
+
+ en = prepare_set_certificate_exception (cert, purpose, trust);
+ g_return_val_if_fail (en, FALSE);
+
+ ret = perform_set_certificate_exception (en, cancel, error);
+
+ g_object_unref (en);
+
+ return ret;
+}
+
+static void
+thread_set_certificate_exception (GSimpleAsyncResult *res, GObject *object, GCancellable *cancel)
+{
+ GError *error = NULL;
+
+ perform_set_certificate_exception (GCK_ENUMERATOR (object), cancel, &error);
+
+ if (error != NULL) {
+ g_simple_async_result_set_from_error (res, error);
+ g_clear_error (&error);
+ }
+}
+
+void
+gcr_trust_set_certificate_exception_async (GcrCertificate *cert, GcrPurpose purpose,
+ GcrTrust trust, GCancellable *cancel,
+ GAsyncReadyCallback callback, gpointer user_data)
+{
+ GSimpleAsyncResult *async;
+ GckEnumerator *en;
+
+ en = prepare_set_certificate_exception (cert, purpose, trust);
+ g_return_if_fail (en);
+
+ async = g_simple_async_result_new (G_OBJECT (en), callback, user_data,
+ gcr_trust_set_certificate_exception_async);
+
+ g_simple_async_result_run_in_thread (async, thread_set_certificate_exception,
+ G_PRIORITY_DEFAULT, cancel);
+
+ g_object_unref (async);
+ g_object_unref (en);
+}
+
+gboolean
+gcr_trust_set_certificate_exception_finish (GAsyncResult *res, GError **error)
+{
+ GObject *object;
+
+ object = g_async_result_get_source_object (res);
+ g_return_val_if_fail (g_simple_async_result_is_valid (res, object,
+ gcr_trust_set_certificate_exception_async), FALSE);
+
+ if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error))
+ return FALSE;
+
+ return TRUE;
+}
+
+/* ----------------------------------------------------------------------------------
+ * CERTIFICATE ROOT
+ */
+
+static GckEnumerator*
+prepare_is_certificate_root (GcrCertificate *cert, GcrPurpose purpose)
+{
+ GckAttributes *attrs;
+ GckEnumerator *en;
+ GList *modules;
+
+ modules = _gcr_get_pkcs11_modules ();
+
+ attrs = prepare_trust_attrs (cert);
+ g_return_val_if_fail (attrs, NULL);
+
+ gck_attributes_add_ulong (attrs, attribute_type_for_purpose (purpose),
+ CKT_NETSCAPE_TRUSTED_DELEGATOR);
+
+ /*
+ * TODO: We need to be able to sort the modules by preference
+ * on which sources of trust storage we want to read over which
+ * others.
+ */
+
+ en = gck_modules_enumerate_objects (modules, attrs, CKF_RW_SESSION);
+ trust_operation_init (en, attrs, purpose, GCR_TRUST_UNKNOWN);
+ gck_attributes_unref (attrs);
+
+ return en;
+}
+
+static gboolean
+perform_is_certificate_root (GckEnumerator *en, GCancellable *cancel, GError **error)
+{
+ GcrTrustOperation *op;
+ GckObject *object;
+
+ op = trust_operation_get (en);
+ g_assert (op != NULL);
+
+ object = gck_enumerator_next (en, cancel, error);
+ if (object != NULL) {
+ op->trust = GCR_TRUST_TRUSTED;
+ g_object_unref (object);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+gboolean
+gcr_trust_is_certificate_root (GcrCertificate *cert, GcrPurpose purpose,
+ GCancellable *cancel, GError **error)
+{
+ GckEnumerator *en;
+ gboolean ret;
+
+ en = prepare_is_certificate_root (cert, purpose);
+ g_return_val_if_fail (en, FALSE);
+
+ ret = perform_is_certificate_root (en, cancel, error);
+
+ g_object_unref (en);
+
+ return ret;
+}
+
+static void
+thread_is_certificate_root (GSimpleAsyncResult *res, GObject *object, GCancellable *cancel)
+{
+ GError *error = NULL;
+
+ perform_is_certificate_root (GCK_ENUMERATOR (object), cancel, &error);
+
+ if (error != NULL) {
+ g_simple_async_result_set_from_error (res, error);
+ g_clear_error (&error);
+ }
+}
+
+void
+gcr_trust_is_certificate_root_async (GcrCertificate *cert, GcrPurpose purpose,
+ GCancellable *cancel, GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *async;
+ GckEnumerator *en;
+
+ en = prepare_is_certificate_root (cert, purpose);
+ g_return_if_fail (en);
+
+ async = g_simple_async_result_new (G_OBJECT (en), callback, user_data,
+ gcr_trust_is_certificate_root_async);
+
+ g_simple_async_result_run_in_thread (async, thread_is_certificate_root,
+ G_PRIORITY_DEFAULT, cancel);
+
+ g_object_unref (async);
+ g_object_unref (en);
+}
+
+gboolean
+gcr_trust_is_certificate_root_finish (GAsyncResult *res, GError **error)
+{
+ GcrTrustOperation *op;
+ GObject *object;
+
+ object = g_async_result_get_source_object (res);
+ g_return_val_if_fail (g_simple_async_result_is_valid (res, object,
+ gcr_trust_is_certificate_root_async), FALSE);
+
+ if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error))
+ return FALSE;
+
+ op = trust_operation_get (GCK_ENUMERATOR (object));
+ return op->trust == GCR_TRUST_TRUSTED;
+}
diff --git a/gcr/gcr-trust.h b/gcr/gcr-trust.h
new file mode 100644
index 0000000..89902fa
--- /dev/null
+++ b/gcr/gcr-trust.h
@@ -0,0 +1,93 @@
+/*
+ * gnome-keyring
+ *
+ * Copyright (C) 2010 Stefan Walter
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef __GCR_TRUST_H__
+#define __GCR_TRUST_H__
+
+#include "gcr-types.h"
+
+G_BEGIN_DECLS
+
+typedef enum _GcrTrust {
+ GCR_TRUST_UNTRUSTED = -1,
+ GCR_TRUST_UNKNOWN = 0,
+ GCR_TRUST_TRUSTED,
+} GcrTrust;
+
+typedef enum _GcrPurpose {
+ GCR_PURPOSE_SERVER_AUTH = 1,
+ GCR_PURPOSE_CLIENT_AUTH,
+ GCR_PURPOSE_CODE_SIGNING,
+ GCR_PURPOSE_EMAIL,
+ GCR_PURPOSE_TIME_STAMPING,
+ GCR_PURPOSE_IPSEC_ENDPOINT,
+ GCR_PURPOSE_IPSEC_TUNNEL,
+ GCR_PURPOSE_IPSEC_USER,
+ GCR_PURPOSE_IKE_INTERMEDIATE,
+} GcrPurpose;
+
+GcrTrust gcr_trust_get_certificate_exception (GcrCertificate *cert,
+ GcrPurpose purpose,
+ GCancellable *cancel,
+ GError **error);
+
+void gcr_trust_get_certificate_exception_async (GcrCertificate *cert,
+ GcrPurpose purpose,
+ GCancellable *cancel,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+GcrTrust gcr_trust_get_certificate_exception_finish (GAsyncResult *res,
+ GError **error);
+
+gboolean gcr_trust_set_certificate_exception (GcrCertificate *cert,
+ GcrPurpose purpose,
+ GcrTrust trust,
+ GCancellable *cancel,
+ GError **error);
+
+void gcr_trust_set_certificate_exception_async (GcrCertificate *cert,
+ GcrPurpose purpose,
+ GcrTrust trust,
+ GCancellable *cancel,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean gcr_trust_set_certificate_exception_finish (GAsyncResult *res,
+ GError **error);
+
+gboolean gcr_trust_is_certificate_root (GcrCertificate *cert,
+ GcrPurpose purpose,
+ GCancellable *cancel,
+ GError **error);
+
+void gcr_trust_is_certificate_root_async (GcrCertificate *cert,
+ GcrPurpose purpose,
+ GCancellable *cancel,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean gcr_trust_is_certificate_root_finish (GAsyncResult *res,
+ GError **error);
+
+G_END_DECLS
+
+#endif /* __GCR_TOKEN_MANAGER_H__ */
diff --git a/gcr/gcr-types.h b/gcr/gcr-types.h
index 3051ff5..6d7decc 100644
--- a/gcr/gcr-types.h
+++ b/gcr/gcr-types.h
@@ -20,6 +20,10 @@ enum {
GCR_ERROR_LOCKED = 3
};
+#define GCR_ERROR (gcr_error_get_domain ())
+
+GQuark gcr_error_get_domain (void) G_GNUC_CONST;
+
enum {
GCR_FORMAT_INVALID = 0,
diff --git a/gcr/gcr.h b/gcr/gcr.h
index 49efed3..c150a34 100644
--- a/gcr/gcr.h
+++ b/gcr/gcr.h
@@ -29,6 +29,8 @@
#include "gcr-certificate-details-widget.h"
#include "gcr-importer.h"
#include "gcr-parser.h"
+#include "gcr-simple-certificate.h"
+#include "gcr-trust.h"
#include "gcr-types.h"
#endif /* __GCR_H__ */
diff --git a/gcr/gkm-test.c b/gcr/gkm-test.c
new file mode 100644
index 0000000..3e268ac
--- /dev/null
+++ b/gcr/gkm-test.c
@@ -0,0 +1,60 @@
+/*
+ * gnome-keyring
+ *
+ * Copyright (C) 2010 Stefan Walter
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include "gkm-attributes.h"
+#include "gkm-test.h"
+#include "gkm-util.h"
+
+#include "pkcs11/pkcs11.h"
+#include "pkcs11/pkcs11i.h"
+
+#include <glib.h>
+
+#include <string.h>
+
+void
+gkm_assertion_message_cmprv (const gchar *domain, const gchar *file, gint line,
+ const gchar *func, const gchar *expr,
+ CK_RV arg1, const gchar *cmp, CK_RV arg2)
+{
+ gchar *a1, *a2, *s;
+ a1 = gkm_util_rv_to_string (arg1);
+ a2 = gkm_util_rv_to_string (arg2);
+ s = g_strdup_printf ("assertion failed (%s): (%s %s %s)", expr, a1, cmp, a2);
+ g_free (a1);
+ g_free (a2);
+ g_assertion_message (domain, file, line, func, s);
+ g_free (s);
+}
+
+void
+gkm_assertion_message_cmpulong (const gchar *domain, const gchar *file, gint line,
+ const gchar *func, const gchar *expr,
+ CK_ULONG arg1, const gchar *cmp, CK_ULONG arg2)
+{
+ char *s = NULL;
+ s = g_strdup_printf ("assertion failed (%s): (0x%08llx %s 0x%08llx)", expr,
+ (long long unsigned)arg1, cmp, (long long unsigned)arg2);
+ g_assertion_message (domain, file, line, func, s);
+ g_free (s);
+}
diff --git a/gcr/gkm-test.h b/gcr/gkm-test.h
new file mode 100644
index 0000000..97cc078
--- /dev/null
+++ b/gcr/gkm-test.h
@@ -0,0 +1,62 @@
+/*
+ * gnome-keyring
+ *
+ * Copyright (C) 2010 Stefan Walter
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include <glib.h>
+
+#include "pkcs11/pkcs11.h"
+#include "pkcs11/pkcs11i.h"
+
+#ifndef GKM_TEST_H
+#define GKM_TEST_H
+
+#define gkm_assert_cmprv(v1, cmp, v2) \
+ do { CK_RV __v1 = (v1), __v2 = (v2); \
+ if (__v1 cmp __v2) ; else \
+ gkm_assertion_message_cmprv (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \
+ #v1 " " #cmp " " #v2, __v1, #cmp, __v2); \
+ } while (0)
+
+#define gkm_assert_cmpulong(v1, cmp, v2) \
+ do { CK_RV __v1 = (v1), __v2 = (v2); \
+ if (__v1 cmp __v2) ; else \
+ gkm_assertion_message_cmpulong (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \
+ #v1 " " #cmp " " #v2, __v1, #cmp, __v2); \
+ } while (0)
+
+void gkm_assertion_message_cmprv (const gchar *domain,
+ const gchar *file,
+ int line,
+ const gchar *func,
+ const gchar *expr,
+ CK_RV arg1,
+ const gchar *cmp,
+ CK_RV arg2);
+
+void gkm_assertion_message_cmpulong (const gchar *domain,
+ const gchar *file,
+ gint line,
+ const gchar *func,
+ const gchar *expr,
+ CK_ULONG arg1,
+ const gchar *cmp,
+ CK_ULONG arg2);
+
+#endif /* GKM_TEST_H */
diff --git a/gcr/tests/Makefile.am b/gcr/tests/Makefile.am
index 22295ad..d6d1839 100644
--- a/gcr/tests/Makefile.am
+++ b/gcr/tests/Makefile.am
@@ -2,6 +2,7 @@
# Test files should be listed in order they need to run
TESTING_FILES = \
unit-test-certificate.c \
+ test-trust.c \
unit-test-parser.c
TESTING_LIBS = \
diff --git a/gcr/tests/test-trust.c b/gcr/tests/test-trust.c
new file mode 100644
index 0000000..f97f009
--- /dev/null
+++ b/gcr/tests/test-trust.c
@@ -0,0 +1,238 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/*
+ Copyright (C) 2010 Stefan Walter
+
+ The Gnome Keyring Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The Gnome Keyring Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the Gnome Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Author: Stef Walter <stef memberwebs com>
+*/
+
+#include "config.h"
+
+#include "test-suite.h"
+
+#include "gcr.h"
+#include "gcr/gcr-internal.h"
+
+#include "gck/gck-mock.h"
+#include "gck/gck-test.h"
+
+#include "pkcs11/pkcs11n.h"
+
+#include <glib.h>
+
+static CK_FUNCTION_LIST_PTR funcs;
+static GList *modules = NULL;
+static GcrCertificate *certificate = NULL;
+
+DEFINE_SETUP (trust_setup)
+{
+ GckModule *module;
+ guchar *contents;
+ gsize len;
+ CK_RV rv;
+
+ contents = testing_data_read ("der-certificate.crt", &len);
+ g_assert (contents);
+
+ certificate = gcr_simple_certificate_new (contents, len);
+
+ rv = gck_mock_C_GetFunctionList (&funcs);
+ gck_assert_cmprv (rv, ==, CKR_OK);
+
+ /* Open a session */
+ rv = (funcs->C_Initialize) (NULL);
+ gck_assert_cmprv (rv, ==, CKR_OK);
+
+ g_assert (!modules);
+ module = gck_module_new (funcs, 0);
+ modules = g_list_prepend (modules, module);
+
+ _gcr_set_test_pkcs11_modules (modules);
+ _gcr_set_test_trust_slot (GCK_MOCK_SLOT_ONE_URI);
+}
+
+DEFINE_TEARDOWN (trust_setup)
+{
+ CK_RV rv;
+
+ g_object_unref (certificate);
+ certificate = NULL;
+
+ g_assert (funcs);
+ rv = (funcs->C_Finalize) (NULL);
+ gck_assert_cmprv (rv, ==, CKR_OK);
+
+ gck_list_unref_free (modules);
+ modules = NULL;
+}
+
+DEFINE_TEST (trust_get_exception_none)
+{
+ GError *error = NULL;
+ GcrTrust trust;
+
+ trust = gcr_trust_get_certificate_exception (certificate, GCR_PURPOSE_EMAIL, NULL, &error);
+ g_assert_cmpint (trust, ==, GCR_TRUST_UNKNOWN);
+ g_assert (error == NULL);
+}
+
+DEFINE_TEST (trust_set_and_get_exception)
+{
+ GError *error = NULL;
+ GcrTrust trust;
+ gboolean ret;
+
+ trust = gcr_trust_get_certificate_exception (certificate, GCR_PURPOSE_EMAIL, NULL, &error);
+ g_assert_cmpint (trust, ==, GCR_TRUST_UNKNOWN);
+ g_assert (error == NULL);
+
+ ret = gcr_trust_set_certificate_exception (certificate, GCR_PURPOSE_EMAIL,
+ GCR_TRUST_TRUSTED, NULL, &error);
+ g_assert (ret == TRUE);
+ g_assert (error == NULL);
+
+ trust = gcr_trust_get_certificate_exception (certificate, GCR_PURPOSE_EMAIL, NULL, &error);
+ g_assert_cmpint (trust, ==, GCR_TRUST_TRUSTED);
+ g_assert (error == NULL);
+}
+
+DEFINE_TEST (trust_set_and_override_exception)
+{
+ GError *error = NULL;
+ GcrTrust trust;
+ gboolean ret;
+
+ ret = gcr_trust_set_certificate_exception (certificate, GCR_PURPOSE_EMAIL,
+ GCR_TRUST_TRUSTED, NULL, &error);
+ g_assert (ret == TRUE);
+ g_assert (error == NULL);
+
+ trust = gcr_trust_get_certificate_exception (certificate, GCR_PURPOSE_EMAIL, NULL, &error);
+ g_assert_cmpint (trust, ==, GCR_TRUST_TRUSTED);
+ g_assert (error == NULL);
+
+ ret = gcr_trust_set_certificate_exception (certificate, GCR_PURPOSE_EMAIL,
+ GCR_TRUST_UNTRUSTED, NULL, &error);
+ g_assert (ret == TRUE);
+ g_assert (error == NULL);
+
+ trust = gcr_trust_get_certificate_exception (certificate, GCR_PURPOSE_EMAIL, NULL, &error);
+ g_assert_cmpint (trust, ==, GCR_TRUST_UNTRUSTED);
+ g_assert (error == NULL);
+}
+
+static void
+fetch_async_result (GObject *source, GAsyncResult *result, gpointer user_data)
+{
+ *((GAsyncResult**)user_data) = result;
+ g_object_ref (result);
+ testing_wait_stop ();
+}
+
+DEFINE_TEST (trust_set_and_get_exception_async)
+{
+ GAsyncResult *result = NULL;
+ GError *error = NULL;
+ GcrTrust trust;
+ gboolean ret;
+
+ gcr_trust_get_certificate_exception_async (certificate, GCR_PURPOSE_EMAIL, NULL, fetch_async_result, &result);
+ testing_wait_until (500);
+ g_assert (result);
+ trust = gcr_trust_get_certificate_exception_finish (result, &error);
+ g_assert (trust == GCR_TRUST_UNKNOWN);
+ g_assert (error == NULL);
+ g_object_unref (result);
+ result = NULL;
+
+ gcr_trust_set_certificate_exception_async (certificate, GCR_PURPOSE_EMAIL, GCR_TRUST_TRUSTED,
+ NULL, fetch_async_result, &result);
+ testing_wait_until (500);
+ g_assert (result);
+ ret = gcr_trust_set_certificate_exception_finish (result, &error);
+ g_assert (ret == TRUE);
+ g_assert (error == NULL);
+ g_object_unref (result);
+ result = NULL;
+
+ gcr_trust_get_certificate_exception_async (certificate, GCR_PURPOSE_EMAIL, NULL, fetch_async_result, &result);
+ testing_wait_until (500);
+ g_assert (result);
+ trust = gcr_trust_get_certificate_exception_finish (result, &error);
+ g_assert (trust == GCR_TRUST_TRUSTED);
+ g_assert (error == NULL);
+ g_object_unref (result);
+ result = NULL;
+}
+
+DEFINE_TEST (trust_is_certificate_root_not)
+{
+ GError *error = NULL;
+ gboolean ret;
+
+ ret = gcr_trust_is_certificate_root (certificate, GCR_PURPOSE_CLIENT_AUTH, NULL, &error);
+ g_assert (ret == FALSE);
+ g_assert (error == NULL);
+}
+
+DEFINE_TEST (trust_is_certificate_root_yes)
+{
+ GError *error = NULL;
+ GckAttributes *attrs;
+ gpointer data;
+ gsize n_data;
+ gboolean ret;
+
+ /* Create a certificate root trust */
+ attrs = gck_attributes_new ();
+ data = gcr_certificate_get_issuer_raw (certificate, &n_data);
+ g_assert (data && n_data);
+ gck_attributes_add_data (attrs, CKA_ISSUER, data, n_data);
+ g_free (data);
+ data = gcr_certificate_get_serial_number (certificate, &n_data);
+ g_assert (data && n_data);
+ gck_attributes_add_data (attrs, CKA_SERIAL_NUMBER, data, n_data);
+ g_free (data);
+ data = gcr_certificate_get_fingerprint (certificate, G_CHECKSUM_SHA1, &n_data);
+ g_assert (data);
+ gck_attributes_add_data (attrs, CKA_CERT_SHA1_HASH, data, n_data);
+ g_free (data);
+ gck_attributes_add_ulong (attrs, CKA_CLASS, CKO_NETSCAPE_TRUST);
+ gck_attributes_add_ulong (attrs, CKA_TRUST_CLIENT_AUTH, CKT_NETSCAPE_TRUSTED_DELEGATOR);
+ gck_mock_module_take_object (attrs);
+
+ ret = gcr_trust_is_certificate_root (certificate, GCR_PURPOSE_CLIENT_AUTH, NULL, &error);
+ g_assert (ret == TRUE);
+ g_assert (error == NULL);
+}
+
+DEFINE_TEST (trust_is_certificate_root_async)
+{
+ GAsyncResult *result = NULL;
+ GError *error = NULL;
+ gboolean ret;
+
+ gcr_trust_is_certificate_root_async (certificate, GCR_PURPOSE_CLIENT_AUTH, NULL, fetch_async_result, &result);
+ testing_wait_until (500);
+ g_assert (result);
+
+ ret = gcr_trust_is_certificate_root_finish (result, &error);
+ g_assert (ret == FALSE);
+ g_assert (error == NULL);
+
+ g_object_unref (result);
+}
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 5fbcfda..8dcd2e5 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -18,6 +18,7 @@ gcr/gcr-certificate-details-widget.c
[type: gettext/glade]gcr/gcr-import-dialog.ui
[type: gettext/glade]gcr/gcr-unlock-options-widget.ui
gcr/gcr-importer.c
+gcr/gcr-library.c
gcr/gcr-parser.c
gp11/gp11-misc.c
gck/gck-uri.c
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]