[gnome-keyring/dbus-api] [gck] Make exposing pkcs11 object part of transaction.



commit 3599153c060ec3fa864ef8bf5779b40416976cef
Author: Stef Walter <stef memberwebs com>
Date:   Sat Nov 7 22:42:44 2009 +0000

    [gck] Make exposing pkcs11 object part of transaction.
    
    When a transaction fails, and an object was exposed (ie: made
    available through PKCS#11) we should revert the exposure.

 pkcs11/gck/gck-object.c             |   35 +++++++++++++++++++++
 pkcs11/gck/gck-object.h             |    6 ++++
 pkcs11/gck/gck-session.c            |    4 +-
 pkcs11/gck/tests/test-module.c      |   29 ++++++++++++++++++
 pkcs11/gck/tests/test-module.h      |    2 +
 pkcs11/gck/tests/unit-test-object.c |   57 +++++++++++++++++++++++++++++++++++
 6 files changed, 131 insertions(+), 2 deletions(-)
---
diff --git a/pkcs11/gck/gck-object.c b/pkcs11/gck/gck-object.c
index 5b0dba6..b9bcc1c 100644
--- a/pkcs11/gck/gck-object.c
+++ b/pkcs11/gck/gck-object.c
@@ -140,6 +140,18 @@ complete_destroy (GckTransaction *transaction, GObject *unused, gpointer user_da
 	return TRUE;
 }
 
+static gboolean
+complete_expose (GckTransaction *transaction, GObject *obj, gpointer user_data)
+{
+	GckObject *self = GCK_OBJECT (obj);
+	gboolean expose = GPOINTER_TO_UINT (user_data);
+
+	if (gck_transaction_get_failed (transaction))
+		gck_object_expose (self, !expose);
+
+	return TRUE;
+}
+
 /* -----------------------------------------------------------------------------
  * OBJECT 
  */
@@ -755,6 +767,13 @@ gck_object_destroy (GckObject *self, GckTransaction *transaction)
 	g_object_unref (self);
 }
 
+gboolean
+gck_object_is_exposed (GckObject *self)
+{
+	g_return_val_if_fail (GCK_IS_OBJECT (self), FALSE);
+	return self->pv->exposed;
+}
+
 void
 gck_object_expose (GckObject *self, gboolean expose)
 {
@@ -766,3 +785,19 @@ gck_object_expose (GckObject *self, gboolean expose)
 	if (self->pv->exposed != expose)
 		g_signal_emit (self, signals[EXPOSE_OBJECT], 0, expose);
 }
+
+void
+gck_object_expose_full (GckObject *self, GckTransaction *transaction, gboolean expose)
+{
+	if (!expose && !self)
+		return;
+
+	g_return_if_fail (GCK_IS_OBJECT (self));
+	g_return_if_fail (!transaction || !gck_transaction_get_failed (transaction));
+
+	if (self->pv->exposed != expose) {
+		if (transaction)
+			gck_transaction_add (transaction, self, complete_expose, GUINT_TO_POINTER (expose));
+		gck_object_expose (self, expose);
+	}
+}
diff --git a/pkcs11/gck/gck-object.h b/pkcs11/gck/gck-object.h
index 53c9b64..29988e1 100644
--- a/pkcs11/gck/gck-object.h
+++ b/pkcs11/gck/gck-object.h
@@ -87,9 +87,15 @@ CK_RV                  gck_object_unlock                 (GckObject *self,
 void                   gck_object_destroy                (GckObject *self,
                                                           GckTransaction *transaction);
 
+gboolean               gck_object_is_exposed             (GckObject *self);
+
 void                   gck_object_expose                 (GckObject *self,
                                                           gboolean expose);
 
+void                   gck_object_expose_full            (GckObject *self,
+                                                          GckTransaction *transaction,
+                                                          gboolean expose);
+
 gboolean               gck_object_match                  (GckObject *self,
                                                           GckSession *session,
                                                           CK_ATTRIBUTE_PTR attr);
diff --git a/pkcs11/gck/gck-session.c b/pkcs11/gck/gck-session.c
index afe3c12..7a37f55 100644
--- a/pkcs11/gck/gck-session.c
+++ b/pkcs11/gck/gck-session.c
@@ -316,7 +316,7 @@ remove_object (GckSession *self, GckTransaction *transaction, GckObject *object)
 	
 	g_object_ref (object);
 	
-	gck_object_expose (object, FALSE);
+	gck_object_expose_full (object, transaction, FALSE);
 	if (!g_hash_table_remove (self->pv->objects, object))
 		g_return_if_reached ();
 	g_object_set (object, "store", NULL, NULL);
@@ -351,7 +351,7 @@ add_object (GckSession *self, GckTransaction *transaction, GckObject *object)
 	g_hash_table_insert (self->pv->objects, object, g_object_ref (object));
 	g_object_set_data (G_OBJECT (object), "owned-by-session", self);
 	g_object_set (object, "store", self->pv->store, NULL);
-	gck_object_expose (object, TRUE);
+	gck_object_expose_full (object, transaction, TRUE);
 
 	if (transaction)
 		gck_transaction_add (transaction, self, (GckTransactionFunc)complete_add, 
diff --git a/pkcs11/gck/tests/test-module.c b/pkcs11/gck/tests/test-module.c
index e36071d..1cd7f82 100644
--- a/pkcs11/gck/tests/test-module.c
+++ b/pkcs11/gck/tests/test-module.c
@@ -23,11 +23,14 @@
 
 #include "config.h"
 #include "test-module.h"
+#include "run-auto-test.h"
 
 /* Include all the module entry points */
 #include "gck/gck-module-ep.h"
 GCK_DEFINE_MODULE (test_module, GCK_TYPE_MODULE);
 
+#include "gck/gck-certificate.h"
+
 GckModule*
 test_module_initialize_and_enter (void)
 {
@@ -84,3 +87,29 @@ test_module_open_session (gboolean writable)
 
 	return session;
 }
+
+GckObject*
+test_module_object_new (GckSession *session)
+{
+	GckObject *object;
+
+	CK_BBOOL token = CK_FALSE;
+	CK_OBJECT_CLASS klass = CKO_CERTIFICATE;
+	CK_CERTIFICATE_TYPE type = CKC_X_509;
+
+	gsize n_data;
+	guchar *data = test_read_testdata ("test-certificate-1.der", &n_data);
+
+	CK_ATTRIBUTE attrs[] = {
+		{ CKA_TOKEN, &token, sizeof (token) },
+		{ CKA_CLASS, &klass, sizeof (klass) },
+		{ CKA_CERTIFICATE_TYPE, &type, sizeof (type) },
+		{ CKA_VALUE, data, n_data },
+	};
+
+	if (gck_session_create_object_for_factory (session, GCK_FACTORY_CERTIFICATE->factory,
+	                                           attrs, G_N_ELEMENTS (attrs), &object) == CKR_OK)
+		return object;
+
+	return NULL;
+}
diff --git a/pkcs11/gck/tests/test-module.h b/pkcs11/gck/tests/test-module.h
index 631dd5b..32fece1 100644
--- a/pkcs11/gck/tests/test-module.h
+++ b/pkcs11/gck/tests/test-module.h
@@ -40,4 +40,6 @@ void                   test_module_leave_and_finalize       (void);
 
 GckSession*            test_module_open_session             (gboolean writable);
 
+GckObject*             test_module_object_new               (GckSession *session);
+
 #endif /* TESTMODULE_H_ */
diff --git a/pkcs11/gck/tests/unit-test-object.c b/pkcs11/gck/tests/unit-test-object.c
index 3cb323a..54e3f29 100644
--- a/pkcs11/gck/tests/unit-test-object.c
+++ b/pkcs11/gck/tests/unit-test-object.c
@@ -28,6 +28,7 @@
 #include "gck/gck-object.h"
 #include "gck/gck-session.h"
 #include "gck/gck-module.h"
+#include "gck/gck-transaction.h"
 
 #include "pkcs11g.h"
 
@@ -243,3 +244,59 @@ DEFINE_TEST(object_create_auto_destruct_bad_value)
 	rv = gck_session_C_CreateObject (session, attrs, G_N_ELEMENTS (attrs), &handle);
 	g_assert (rv == CKR_ATTRIBUTE_VALUE_INVALID);
 }
+
+DEFINE_TEST(object_expose)
+{
+	CK_OBJECT_HANDLE handle;
+	GckManager *manager;
+	GckObject *check, *object;
+
+	manager = gck_session_get_manager (session);
+	object = test_module_object_new (session);
+
+	handle = gck_object_get_handle (object);
+	gck_object_expose (object, TRUE);
+
+	/* Now it should have a handle, and be visible */
+	check = gck_manager_find_by_handle (manager, handle);
+	g_assert (check == object);
+
+	gck_object_expose (object, FALSE);
+
+	/* Now should be invisible */
+	check = gck_manager_find_by_handle (manager, handle);
+	g_assert (check == NULL);
+}
+
+DEFINE_TEST(object_expose_transaction)
+{
+	CK_OBJECT_HANDLE handle;
+	GckManager *manager;
+	GckObject *check, *object;
+	GckTransaction *transaction;
+
+	manager = gck_session_get_manager (session);
+	object = test_module_object_new (session);
+
+	handle = gck_object_get_handle (object);
+	transaction = gck_transaction_new ();
+
+	/* Should be hidden */
+	gck_object_expose (object, FALSE);
+	check = gck_manager_find_by_handle (manager, handle);
+	g_assert (check == NULL);
+
+	/* Now it should have a handle, and be visible */
+	gck_object_expose_full (object, transaction, TRUE);
+	check = gck_manager_find_by_handle (manager, handle);
+	g_assert (check == object);
+
+	gck_transaction_fail (transaction, CKR_GENERAL_ERROR);
+	gck_transaction_complete (transaction);
+
+	/* Now should be invisible */
+	check = gck_manager_find_by_handle (manager, handle);
+	g_assert (check == NULL);
+
+	g_object_unref (transaction);
+}



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