[gnome-keyring/trust-store] [xdg-store] Complete work on adding and removing assertions.



commit 004c9b1d97a6f4e1257f39811af6a406c9fcaaba
Author: Stef Walter <stefw collabora co uk>
Date:   Wed Nov 24 23:02:28 2010 +0000

    [xdg-store] Complete work on adding and removing assertions.
    
     * Support for adding and removing assertions.
     * Various other small fixes.

 pkcs11/xdg-store/gkm-xdg-assertion.c     |   52 ++++++--
 pkcs11/xdg-store/gkm-xdg-assertion.h     |    6 +-
 pkcs11/xdg-store/gkm-xdg-module.c        |   88 ++++++++++--
 pkcs11/xdg-store/gkm-xdg-trust.c         |  216 ++++++++++++++++++++++++++----
 pkcs11/xdg-store/gkm-xdg-trust.h         |   14 ++-
 pkcs11/xdg-store/tests/test-xdg-module.c |   67 +++++++++-
 6 files changed, 386 insertions(+), 57 deletions(-)
---
diff --git a/pkcs11/xdg-store/gkm-xdg-assertion.c b/pkcs11/xdg-store/gkm-xdg-assertion.c
index db9f3b4..55f5229 100644
--- a/pkcs11/xdg-store/gkm-xdg-assertion.c
+++ b/pkcs11/xdg-store/gkm-xdg-assertion.c
@@ -24,6 +24,7 @@
 #include "gkm-xdg-assertion.h"
 #include "gkm-xdg-trust.h"
 
+#include "gkm/gkm-assertion.h"
 #include "gkm/gkm-attributes.h"
 #include "gkm/gkm-object.h"
 #include "gkm/gkm-session.h"
@@ -36,7 +37,7 @@
 
 #include <glib/gi18n.h>
 
-G_DEFINE_TYPE (GkmXdgAssertion, gkm_xdg_assertion, GKM_TYPE_OBJECT);
+G_DEFINE_TYPE (GkmXdgAssertion, gkm_xdg_assertion, GKM_TYPE_ASSERTION);
 
 /* -----------------------------------------------------------------------------
  * QUARKS
@@ -46,7 +47,7 @@ G_DEFINE_TYPE (GkmXdgAssertion, gkm_xdg_assertion, GKM_TYPE_OBJECT);
  * INTERNAL
  */
 
-static GkmTrust*
+static GkmXdgTrust*
 lookup_or_create_trust_object (GkmSession *session, GkmManager *manager,
                                GkmTransaction *transaction, CK_ASSERTION_TYPE type,
                                CK_ATTRIBUTE_PTR attrs, CK_ULONG n_attrs, gboolean *created)
@@ -56,7 +57,7 @@ lookup_or_create_trust_object (GkmSession *session, GkmManager *manager,
 	CK_OBJECT_CLASS klass;
 	CK_ULONG n_lookups;
 	GList *objects;
-	GkmTrust *trust;
+	GkmXdgTrust *trust;
 	GkmModule *module;
 
 	klass = CKO_NETSCAPE_TRUST;
@@ -102,8 +103,8 @@ lookup_or_create_trust_object (GkmSession *session, GkmManager *manager,
 
 	/* Found a matching trust object for this assertion */
 	if (objects) {
-		g_return_val_if_fail (GKM_IS_TRUST (objects->data), NULL);
-		trust = GKM_TRUST (objects->data);
+		g_return_val_if_fail (GKM_XDG_IS_TRUST (objects->data), NULL);
+		trust = GKM_XDG_TRUST (objects->data);
 		g_list_free (objects);
 
 	/* Create a trust object for this assertion */
@@ -130,11 +131,13 @@ factory_create_assertion (GkmSession *session, GkmTransaction *transaction,
                           CK_ATTRIBUTE_PTR attrs, CK_ULONG n_attrs)
 {
 	GkmAssertion *assertion;
+	GkmAssertion *previous;
 	CK_ASSERTION_TYPE type;
 	GkmManager *manager;
 	gboolean created = FALSE;
-	GkmTrust *trust;
+	GkmXdgTrust *trust;
 	gchar *purpose;
+	gchar *peer;
 
 	g_return_val_if_fail (attrs || !n_attrs, NULL);
 
@@ -148,6 +151,9 @@ factory_create_assertion (GkmSession *session, GkmTransaction *transaction,
 		return NULL;
 	}
 
+	if (!gkm_attributes_find_string (attrs, n_attrs, CKA_G_PEER, &peer))
+		peer = NULL;
+
 	/* Try to find or create an appropriate trust object for this assertion */
 	manager = gkm_manager_for_template (attrs, n_attrs, session);
 	trust = lookup_or_create_trust_object (session, manager, transaction,
@@ -157,17 +163,39 @@ factory_create_assertion (GkmSession *session, GkmTransaction *transaction,
 	if (trust == NULL) {
 		g_return_val_if_fail (gkm_transaction_get_failed (transaction), NULL);
 		g_free (purpose);
+		g_free (peer);
 		return NULL;
 	}
 
-	assertion = g_object_new (GKM_XDG_TYPE_ASSERTION, "trust", trust,
-	                          "type", type, "purpose", purpose, NULL);
+	assertion = g_object_new (GKM_XDG_TYPE_ASSERTION,
+	                          "module", gkm_object_get_module (GKM_OBJECT (trust)),
+	                          "manager", gkm_object_get_manager (GKM_OBJECT (manager)),
+	                          "trust", trust,
+	                          "type", type,
+	                          "purpose", purpose,
+	                          "peer", peer,
+	                          NULL);
 
-	gkm_attributes_consume (attrs, n_attrs, CKA_G_ASSERTION_TYPE, CKA_G_PURPOSE, G_MAXULONG);
-	gkm_session_complete_object_creation (session, transaction, GKM_OBJECT (assertion),
-	                                      TRUE, attrs, n_attrs);
+	/* Add the assertion to the trust object */
+	if (!gkm_transaction_get_failed (transaction)) {
+		previous = gkm_xdg_trust_add_assertion (trust, GKM_ASSERTION (assertion), transaction);
+		if (previous == NULL) {
+			gkm_transaction_fail (transaction, CKR_GENERAL_ERROR);
+
+		/* If trust refused to add this object, return whatever we did add */
+		} else if (previous != assertion) {
+			g_object_unref (assertion);
+			assertion = g_object_ref (previous);
+		}
+	}
+
+	if (!gkm_transaction_get_failed (transaction)) {
+		gkm_attributes_consume (attrs, n_attrs, CKA_G_ASSERTION_TYPE, CKA_G_PURPOSE, G_MAXULONG);
+		gkm_session_complete_object_creation (session, transaction, GKM_OBJECT (assertion),
+		                                      TRUE, attrs, n_attrs);
+	}
 
-	return GKM_OBJECT (trust);
+	return GKM_OBJECT (assertion);
 }
 
 /* -----------------------------------------------------------------------------
diff --git a/pkcs11/xdg-store/gkm-xdg-assertion.h b/pkcs11/xdg-store/gkm-xdg-assertion.h
index 75bc073..7b70561 100644
--- a/pkcs11/xdg-store/gkm-xdg-assertion.h
+++ b/pkcs11/xdg-store/gkm-xdg-assertion.h
@@ -25,7 +25,7 @@
 
 #include <glib-object.h>
 
-#include "gkm/gkm-object.h"
+#include "gkm/gkm-assertion.h"
 
 #define GKM_XDG_FACTORY_ASSERTION            (gkm_xdg_assertion_get_factory ())
 #define GKM_XDG_TYPE_ASSERTION               (gkm_xdg_assertion_get_type ())
@@ -40,12 +40,12 @@ typedef struct _GkmXdgAssertionClass GkmXdgAssertionClass;
 typedef struct _GkmXdgAssertionPrivate GkmXdgAssertionPrivate;
 
 struct _GkmXdgAssertion {
-	GkmObject parent;
+	GkmAssertion parent;
 	GkmXdgAssertionPrivate *pv;
 };
 
 struct _GkmXdgAssertionClass {
-	GkmObjectClass parent_class;
+	GkmAssertionClass parent_class;
 };
 
 GType                 gkm_xdg_assertion_get_type               (void);
diff --git a/pkcs11/xdg-store/gkm-xdg-module.c b/pkcs11/xdg-store/gkm-xdg-module.c
index f6d20f4..bae8abd 100644
--- a/pkcs11/xdg-store/gkm-xdg-module.c
+++ b/pkcs11/xdg-store/gkm-xdg-module.c
@@ -86,6 +86,12 @@ G_DEFINE_TYPE (GkmXdgModule, gkm_xdg_module, GKM_TYPE_MODULE);
 
 GkmModule*  _gkm_xdg_store_get_module_for_testing (void);
 
+/* Forward declarations */
+static void  remove_object_from_module (GkmXdgModule *self, GkmObject *object,
+                                        const gchar *filename, GkmTransaction *transaction);
+static void  add_object_to_module (GkmXdgModule *self, GkmObject *object,
+                                   const gchar *filename, GkmTransaction *transaction);
+
 /* -----------------------------------------------------------------------------
  * ACTUAL PKCS#11 Module Implementation
  */
@@ -122,8 +128,27 @@ lookup_filename_for_object (GkmObject *object)
 	return g_object_get_data (G_OBJECT (object), "xdg-module-filename");
 }
 
+static gboolean
+complete_add_object (GkmTransaction *transaction, GObject *module, gpointer user_data)
+{
+	GkmXdgModule *self = GKM_XDG_MODULE (module);
+	GkmObject *object = GKM_OBJECT (user_data);
+	const gchar *filename;
+
+	/* If the transaction failed, revert it */
+	if (gkm_transaction_get_failed (transaction)) {
+		filename = g_object_get_data (G_OBJECT (object), "xdg-module-filename");
+		g_return_val_if_fail (filename, FALSE);
+		remove_object_from_module (self, object, filename, NULL);
+	}
+
+	g_object_unref (object);
+	return TRUE;
+}
+
 static void
-add_object_to_module (GkmXdgModule *self, GkmObject *object, const gchar *filename)
+add_object_to_module (GkmXdgModule *self, GkmObject *object,
+                      const gchar *filename, GkmTransaction *transaction)
 {
 	g_assert (!g_hash_table_lookup (self->objects_by_path, filename));
 	g_hash_table_insert (self->objects_by_path, g_strdup (filename), g_object_ref (object));
@@ -133,13 +158,38 @@ add_object_to_module (GkmXdgModule *self, GkmObject *object, const gchar *filena
 	                        g_strdup (filename), g_free);
 
 	gkm_object_expose (object, TRUE);
+
+	if (transaction != NULL)
+		gkm_transaction_add (transaction, self, complete_add_object, g_object_ref (object));
+}
+
+static gboolean
+complete_remove_object (GkmTransaction *transaction, GObject *module, gpointer user_data)
+{
+	GkmXdgModule *self = GKM_XDG_MODULE (module);
+	GkmObject *object = GKM_OBJECT (user_data);
+	const gchar *filename;
+
+	/* If the transaction failed, revert it */
+	if (gkm_transaction_get_failed (transaction)) {
+		filename = g_object_get_data (G_OBJECT (object), "xdg-module-filename");
+		g_return_val_if_fail (filename, FALSE);
+		add_object_to_module (self, object, filename, NULL);
+	}
+
+	g_object_unref (object);
+	return TRUE;
 }
 
 static void
-remove_object_from_module (GkmXdgModule *self, GkmObject *object, const gchar *filename)
+remove_object_from_module (GkmXdgModule *self, GkmObject *object,
+                           const gchar *filename, GkmTransaction *transaction)
 {
 	gkm_object_expose (object, FALSE);
 
+	if (transaction != NULL)
+		gkm_transaction_add (transaction, self, complete_remove_object, g_object_ref (object));
+
 	g_assert (g_hash_table_lookup (self->objects_by_path, filename) == object);
 	g_hash_table_remove (self->objects_by_path, filename);
 }
@@ -195,14 +245,14 @@ file_load (GkmFileTracker *tracker, const gchar *path, GkmXdgModule *self)
 	/* And load the data into it */
 	} else if (gkm_serializable_load (GKM_SERIALIZABLE (object), NULL, data, n_data)) {
 		if (added)
-			add_object_to_module (self, object, path);
+			add_object_to_module (self, object, path, NULL);
 		gkm_object_expose (object, TRUE);
 
 	} else {
 		g_message ("failed to load file in user store: %s", path);
 		if (!added) {
 			gkm_object_expose (object, FALSE);
-			remove_object_from_module (self, object, path);
+			remove_object_from_module (self, object, path, NULL);
 		}
 	}
 
@@ -219,7 +269,7 @@ file_remove (GkmFileTracker *tracker, const gchar *path, GkmXdgModule *self)
 
 	object = g_hash_table_lookup (self->objects_by_path, path);
 	if (object != NULL)
-		remove_object_from_module (self, object, path);
+		remove_object_from_module (self, object, path, NULL);
 }
 
 static gchar*
@@ -353,7 +403,7 @@ gkm_xdg_module_real_add_token_object (GkmModule *module, GkmTransaction *transac
 	actual = gkm_transaction_unique_file (transaction, self->directory, basename);
 	if (!gkm_transaction_get_failed (transaction)) {
 		filename = g_build_filename (self->directory, actual, NULL);
-		add_object_to_module (self, object, filename);
+		add_object_to_module (self, object, filename, transaction);
 		g_free (filename);
 	}
 
@@ -404,16 +454,28 @@ gkm_xdg_module_real_remove_token_object (GkmModule *module, GkmTransaction *tran
 {
 	GkmXdgModule *self = GKM_XDG_MODULE (module);
 	const gchar *filename;
+	GkmXdgTrust *trust;
 
-	/* XXXX; need to implement for assertions */
-	g_assert_not_reached ();
+	/* Always serialize the trust object for each assertion */
+	if (GKM_XDG_IS_ASSERTION (object)) {
+		trust = GKM_XDG_TRUST (gkm_assertion_get_trust_object (GKM_ASSERTION (object)));
+		gkm_xdg_trust_remove_assertion (trust, GKM_ASSERTION (object), transaction);
+
+		/* Remove the trust object if it has no assertions */
+		if (!gkm_xdg_trust_have_assertion (trust))
+			object = GKM_OBJECT (trust);
+		else
+			object = NULL;
+	}
 
-	filename = lookup_filename_for_object (object);
-	g_return_if_fail (filename != NULL);
-	g_return_if_fail (g_hash_table_lookup (self->objects_by_path, filename) == object);
+	if (object && !gkm_transaction_get_failed (transaction)) {
+		filename = lookup_filename_for_object (object);
+		g_return_if_fail (filename != NULL);
+		g_return_if_fail (g_hash_table_lookup (self->objects_by_path, filename) == object);
 
-	gkm_transaction_remove_file (transaction, filename);
-	g_hash_table_remove (self->objects_by_path, filename);
+		gkm_transaction_remove_file (transaction, filename);
+		remove_object_from_module (self, object, filename, transaction);
+	}
 }
 
 static GObject*
diff --git a/pkcs11/xdg-store/gkm-xdg-trust.c b/pkcs11/xdg-store/gkm-xdg-trust.c
index 10a947a..20a4e30 100644
--- a/pkcs11/xdg-store/gkm-xdg-trust.c
+++ b/pkcs11/xdg-store/gkm-xdg-trust.c
@@ -71,6 +71,15 @@ static void gkm_xdg_trust_serializable (GkmSerializableIface *iface);
 G_DEFINE_TYPE_EXTENDED (GkmXdgTrust, gkm_xdg_trust, GKM_TYPE_TRUST, 0,
                         G_IMPLEMENT_INTERFACE (GKM_TYPE_SERIALIZABLE, gkm_xdg_trust_serializable));
 
+static GQuark QDATA_ASSERTION_KEY = 0;
+
+/* Forward declarations */
+static void add_assertion_to_trust (GkmXdgTrust *self, GkmAssertion *assertion,
+                                    GkmTransaction *transaction);
+
+static void remove_assertion_from_trust (GkmXdgTrust *self, GkmAssertion *assertion,
+                                         GkmTransaction *transaction);
+
 /* -----------------------------------------------------------------------------
  * QUARKS
  */
@@ -273,17 +282,20 @@ parse_netscape_trust (NetscapeFlags *netscape, GQuark level, const gchar *purpos
 }
 
 static void
-dispose_each_assertion (gpointer key, gpointer value, gpointer user_data)
+check_and_unref_assertion (gpointer data)
 {
-	g_assert (GKM_IS_ASSERTION (value));
-	g_object_run_dispose (G_OBJECT (value));
+	g_assert (GKM_IS_ASSERTION (data));
+	g_assert (g_object_get_qdata (data, QDATA_ASSERTION_KEY) != NULL);
+	g_object_run_dispose (data);
+	g_object_unref (data);
 }
 
 static GHashTable*
 create_assertions (void)
 {
 	return g_hash_table_new_full (egg_byte_array_hash, egg_byte_array_equal,
-	                              (GDestroyNotify)g_byte_array_unref, gkm_util_dispose_unref);
+	                              (GDestroyNotify)g_byte_array_unref,
+	                              check_and_unref_assertion);
 }
 
 static GkmAssertion*
@@ -328,6 +340,82 @@ create_assertion (GkmXdgTrust *self, GNode *asn, NetscapeFlags *netscape)
 	return assertion;
 }
 
+static void
+stash_assertion_key (GkmAssertion *assertion, GByteArray *key)
+{
+	g_assert (g_object_get_qdata (G_OBJECT (assertion), QDATA_ASSERTION_KEY) == NULL);
+	g_object_set_qdata_full (G_OBJECT (assertion), QDATA_ASSERTION_KEY,
+	                         g_byte_array_ref (key), (GDestroyNotify)g_byte_array_unref);
+}
+
+static GByteArray*
+lookup_assertion_key (GkmAssertion *assertion)
+{
+	return g_object_get_qdata (G_OBJECT (assertion), QDATA_ASSERTION_KEY);
+}
+
+static gboolean
+complete_add_assertion (GkmTransaction *transaction, GObject *object, gpointer user_data)
+{
+	GkmAssertion *assertion = GKM_ASSERTION (user_data);
+	GkmXdgTrust *self = GKM_XDG_TRUST (object);
+
+	if (gkm_transaction_get_failed (transaction))
+		remove_assertion_from_trust (self, assertion, NULL);
+	else
+		g_object_run_dispose (G_OBJECT (object));
+
+	g_object_unref (assertion);
+	return TRUE;
+}
+
+static void
+add_assertion_to_trust (GkmXdgTrust *self, GkmAssertion *assertion,
+                        GkmTransaction *transaction)
+{
+	GByteArray *key;
+
+	key = lookup_assertion_key (assertion);
+	g_assert (key);
+
+	g_hash_table_insert (self->pv->assertions, g_byte_array_ref (key), assertion);
+	gkm_object_expose (GKM_OBJECT (assertion), gkm_object_is_exposed (GKM_OBJECT (self)));
+
+	if (transaction != NULL)
+		gkm_transaction_add (transaction, self, complete_add_assertion, g_object_ref (assertion));
+}
+
+static gboolean
+complete_remove_assertion (GkmTransaction *transaction, GObject *object, gpointer user_data)
+{
+	GkmXdgTrust *self = GKM_XDG_TRUST (object);
+	GkmAssertion *assertion = GKM_ASSERTION (user_data);
+
+	if (gkm_transaction_get_failed (transaction))
+		add_assertion_to_trust (self, assertion, NULL);
+
+	g_object_unref (assertion);
+	return TRUE;
+}
+
+static void
+remove_assertion_from_trust (GkmXdgTrust *self, GkmAssertion *assertion,
+                             GkmTransaction *transaction)
+{
+	GByteArray *key;
+
+	key = lookup_assertion_key (assertion);
+	g_assert (key);
+
+	if (transaction != NULL)
+		gkm_transaction_add (transaction, self, complete_remove_assertion, g_object_ref (assertion));
+
+	gkm_object_expose (GKM_OBJECT (assertion), FALSE);
+
+	if (!g_hash_table_remove (self->pv->assertions, key))
+		g_return_if_reached ();
+}
+
 static gboolean
 load_assertions (GkmXdgTrust *self, GNode *asn)
 {
@@ -369,6 +457,7 @@ load_assertions (GkmXdgTrust *self, GNode *asn)
 		/* Create a new assertion */
 		} else {
 			assertion = create_assertion (self, node, &netscape);
+			stash_assertion_key (assertion, key);
 		}
 
 		if (assertion)
@@ -377,7 +466,7 @@ load_assertions (GkmXdgTrust *self, GNode *asn)
 	}
 
 	/* Override the stored assertions and netscape trust */
-	g_hash_table_foreach (self->pv->assertions, dispose_each_assertion, NULL);
+	g_hash_table_remove_all (self->pv->assertions);
 	g_hash_table_unref (self->pv->assertions);
 	self->pv->assertions = assertions;
 	memcpy (&self->pv->netscape, &netscape, sizeof (netscape));
@@ -386,15 +475,33 @@ load_assertions (GkmXdgTrust *self, GNode *asn)
 }
 
 static gboolean
+save_assertion (GNode *asn, GkmAssertion *assertion)
+{
+	const gchar *purpose;
+	const gchar *peer;
+	GQuark level;
+
+	level = assertion_type_to_level_enum (gkm_assertion_get_trust_type (assertion));
+	purpose = gkm_assertion_get_purpose (assertion);
+	peer = gkm_assertion_get_peer (assertion);
+
+	if (!egg_asn1x_set_oid_as_string (egg_asn1x_node (asn, "purpose", NULL), purpose) ||
+	    !egg_asn1x_set_enumerated (egg_asn1x_node (asn, "level", NULL), level))
+		g_return_val_if_reached (FALSE);
+
+	if (peer && !egg_asn1x_set_string_as_utf8 (egg_asn1x_node (asn, "peer", NULL),
+	                                           g_strdup (peer), g_free))
+		g_return_val_if_reached (FALSE);
+
+	return TRUE;
+}
+
+static gboolean
 save_assertions (GkmXdgTrust *self, GNode *asn)
 {
-	GkmAssertion *assertion;
 	GHashTableIter iter;
 	GNode *pair, *node;
-	const gchar *purpose;
-	const gchar *peer;
 	gpointer value;
-	GQuark level;
 
 	g_assert (GKM_XDG_IS_TRUST (self));
 	g_assert (asn);
@@ -404,21 +511,9 @@ save_assertions (GkmXdgTrust *self, GNode *asn)
 
 	g_hash_table_iter_init (&iter, self->pv->assertions);
 	while (g_hash_table_iter_next (&iter, NULL, &value)) {
-		assertion = GKM_ASSERTION (value);
-		level = assertion_type_to_level_enum (gkm_assertion_get_trust_type (assertion));
-		purpose = gkm_assertion_get_purpose (assertion);
-		peer = gkm_assertion_get_peer (assertion);
-
 		pair = egg_asn1x_append (node);
 		g_return_val_if_fail (pair, FALSE);
-
-		egg_asn1x_set_oid_as_string (egg_asn1x_node (pair, "purpose", NULL), purpose);
-		egg_asn1x_set_enumerated (egg_asn1x_node (pair, "level", NULL), level);
-
-		if (peer) {
-			egg_asn1x_set_string_as_utf8 (egg_asn1x_node (pair, "peer", NULL),
-			                              g_strdup (peer), g_free);
-		}
+		save_assertion (pair, GKM_ASSERTION (value));
 	}
 
 	return TRUE;
@@ -559,6 +654,7 @@ gkm_xdg_trust_class_init (GkmXdgTrustClass *klass)
 	gobject_class->finalize = gkm_xdg_trust_finalize;
 	gkm_class->get_attribute = gkm_xdg_trust_get_attribute;
 
+	QDATA_ASSERTION_KEY = g_quark_from_static_string ("gkm-xdg-trust-assertion-key");
 	g_type_class_add_private (klass, sizeof (GkmXdgTrustPrivate));
 
 	init_quarks ();
@@ -647,7 +743,7 @@ gkm_xdg_trust_serializable (GkmSerializableIface *iface)
  * PUBLIC
  */
 
-GkmTrust*
+GkmXdgTrust*
 gkm_xdg_trust_create_for_assertion (GkmModule *module, GkmManager *manager,
                                     GkmTransaction *transaction,
                                     CK_ATTRIBUTE_PTR attrs, CK_ULONG n_attrs)
@@ -699,5 +795,77 @@ gkm_xdg_trust_create_for_assertion (GkmModule *module, GkmManager *manager,
 	gkm_attributes_consume (attrs, n_attrs, CKA_G_CERTIFICATE_VALUE, CKA_ISSUER,
 	                        CKA_SERIAL_NUMBER, G_MAXULONG);
 
-	return GKM_TRUST (trust);
+	return trust;
+}
+
+GkmAssertion*
+gkm_xdg_trust_add_assertion (GkmXdgTrust *self, GkmAssertion *assertion,
+                             GkmTransaction *transaction)
+{
+	GkmAssertion *previous;
+	GByteArray *key;
+	GNode *asn;
+	gpointer data;
+	gsize n_data;
+
+	g_return_val_if_fail (GKM_XDG_IS_TRUST (self), NULL);
+	g_return_val_if_fail (GKM_IS_ASSERTION (assertion), NULL);
+	g_return_val_if_fail (!transaction || GKM_IS_TRANSACTION (transaction), NULL);
+
+	/* Build up a key if we don't have one */
+	key = lookup_assertion_key (assertion);
+	if (key == NULL) {
+		asn = egg_asn1x_create (xdg_asn1_tab, "TrustAssertion");
+		g_return_val_if_fail (asn, NULL);
+
+		if (!save_assertion (asn, assertion))
+			g_return_val_if_reached (NULL);
+
+		data = egg_asn1x_encode (asn, NULL, &n_data);
+		g_return_val_if_fail (data, NULL);
+
+		key = g_byte_array_new ();
+		g_byte_array_append (key, data, n_data);
+		stash_assertion_key (assertion, key);
+		g_byte_array_unref (key);
+
+		g_free (data);
+		egg_asn1x_destroy (asn);
+
+	/* Already has a key, check if we alraedy have the assertion */
+	} else {
+		previous = g_hash_table_lookup (self->pv->assertions, key);
+
+		/* Just return previous assertion, don't add */
+		if (previous != NULL)
+			return previous;
+	}
+
+	add_assertion_to_trust (self, assertion, transaction);
+	return assertion;
+}
+
+void
+gkm_xdg_trust_remove_assertion (GkmXdgTrust *self, GkmAssertion *assertion,
+                                GkmTransaction *transaction)
+{
+	GByteArray *key;
+
+	g_return_if_fail (GKM_XDG_IS_TRUST (self));
+	g_return_if_fail (GKM_IS_ASSERTION (assertion));
+	g_return_if_fail (!transaction || GKM_IS_TRANSACTION (transaction));
+
+	key = lookup_assertion_key (assertion);
+	g_return_if_fail (key);
+
+	/* Assertion needs to be from this trust object */
+	g_return_if_fail (g_hash_table_lookup (self->pv->assertions, key) != assertion);
+	remove_assertion_from_trust (self, assertion, transaction);
+}
+
+gboolean
+gkm_xdg_trust_have_assertion (GkmXdgTrust *self)
+{
+	g_return_val_if_fail (GKM_XDG_IS_TRUST (self), FALSE);
+	return g_hash_table_size (self->pv->assertions);
 }
diff --git a/pkcs11/xdg-store/gkm-xdg-trust.h b/pkcs11/xdg-store/gkm-xdg-trust.h
index 2e22218..88bc872 100644
--- a/pkcs11/xdg-store/gkm-xdg-trust.h
+++ b/pkcs11/xdg-store/gkm-xdg-trust.h
@@ -50,14 +50,20 @@ struct _GkmXdgTrustClass {
 
 GType                 gkm_xdg_trust_get_type               (void);
 
-GkmTrust*             gkm_xdg_trust_create_for_assertion   (GkmModule *module,
+GkmXdgTrust*          gkm_xdg_trust_create_for_assertion   (GkmModule *module,
                                                             GkmManager *manager,
                                                             GkmTransaction *transaction,
                                                             CK_ATTRIBUTE_PTR attrs,
                                                             CK_ULONG n_attrs);
 
-GkmAssertion*         gkm_xdg_trust_add_assertion          (GkmTrust *trust,
-                                                            GkmTrustLevel level,
-                                                            const char *purpose);
+GkmAssertion*         gkm_xdg_trust_add_assertion          (GkmXdgTrust *trust,
+                                                            GkmAssertion *assertion,
+                                                            GkmTransaction *transaction);
+
+void                  gkm_xdg_trust_remove_assertion       (GkmXdgTrust *trust,
+                                                            GkmAssertion *assertion,
+                                                            GkmTransaction *transaction);
+
+gboolean              gkm_xdg_trust_have_assertion         (GkmXdgTrust *trust);
 
 #endif /* __GKM_XDG_TRUST_H__ */
diff --git a/pkcs11/xdg-store/tests/test-xdg-module.c b/pkcs11/xdg-store/tests/test-xdg-module.c
index cc26566..a3cd72d 100644
--- a/pkcs11/xdg-store/tests/test-xdg-module.c
+++ b/pkcs11/xdg-store/tests/test-xdg-module.c
@@ -134,6 +134,7 @@ test_xdg_module_open_session (gboolean writable)
 
 static GkmModule *module = NULL;
 static GkmSession *session = NULL;
+static CK_SLOT_ID slot_id = 0;
 
 TESTING_EXTERNAL(xdg_module)
 {
@@ -143,13 +144,19 @@ TESTING_EXTERNAL(xdg_module)
 
 TESTING_SETUP(xdg_module_setup)
 {
+	CK_SESSION_INFO info;
 	CK_RV rv;
 
 	module = test_xdg_module_initialize_and_enter ();
 	session = test_xdg_module_open_session (TRUE);
 
 	rv = gkm_module_C_Login (module, gkm_session_get_handle (session), CKU_USER, NULL, 0);
-	g_assert (rv == CKR_OK);
+	gkm_assert_cmprv (rv, ==, CKR_OK);
+
+	rv = gkm_session_C_GetSessionInfo (session, &info);
+	gkm_assert_cmprv (rv, ==, CKR_OK);
+
+	slot_id = info.slotID;
 }
 
 TESTING_TEARDOWN(xdg_module_teardown)
@@ -275,3 +282,61 @@ TESTING_TEST (xdg_create_and_add_object)
 	gkm_assert_cmprv (rv, ==, CKR_OK);
 	gkm_assert_cmpulong (object, !=, 0);
 }
+
+TESTING_TEST (xdg_destroy_object)
+{
+	CK_OBJECT_HANDLE object = 0;
+	CK_CERTIFICATE_TYPE ctype = CKC_X_509;
+	CK_ULONG n_objects = 0;
+	CK_BBOOL tval = CK_TRUE;
+	CK_RV rv;
+
+	CK_ATTRIBUTE attrs[] = {
+		{ CKA_CERTIFICATE_TYPE, &ctype, sizeof (ctype) },
+		{ CKA_TOKEN, &tval, sizeof (tval) }
+	};
+
+	rv = gkm_session_C_FindObjectsInit (session, attrs, G_N_ELEMENTS (attrs));
+	gkm_assert_cmprv (rv, ==, CKR_OK);
+	rv = gkm_session_C_FindObjects (session, &object, 1, &n_objects);
+	gkm_assert_cmprv (rv, ==, CKR_OK);
+	gkm_assert_cmpulong (n_objects, ==, 1);
+	rv = gkm_session_C_FindObjectsFinal (session);
+	gkm_assert_cmprv (rv, ==, CKR_OK);
+
+	/* Destroy this object, which should be stored on the disk */
+	rv = gkm_session_C_DestroyObject (session, object);
+	gkm_assert_cmprv (rv, ==, CKR_OK);
+
+	/* Make sure it's really gone */
+	rv = gkm_session_C_DestroyObject (session, object);
+	gkm_assert_cmprv (rv, ==, CKR_OBJECT_HANDLE_INVALID);
+}
+
+TESTING_TEST (xdg_get_slot_info)
+{
+	CK_SLOT_INFO info;
+	const gchar *str;
+	CK_RV rv;
+
+	rv = gkm_module_C_GetSlotInfo (module, slot_id, &info);
+	gkm_assert_cmprv (rv, ==, CKR_OK);
+
+	str = g_strstr_len ((gchar*)info.slotDescription, sizeof (info.slotDescription),
+	                    "User Key Storage");
+	g_assert (str != NULL);
+}
+
+TESTING_TEST (xdg_get_token_info)
+{
+	CK_TOKEN_INFO info;
+	const gchar *str;
+	CK_RV rv;
+
+	rv = gkm_module_C_GetTokenInfo (module, slot_id, &info);
+	gkm_assert_cmprv (rv, ==, CKR_OK);
+
+	str = g_strstr_len ((gchar*)info.label, sizeof (info.label),
+	                    "User Key Storage");
+	g_assert (str != NULL);
+}



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]