[gnome-keyring/dbus-api] Add support for auto destructing session objects.



commit 950a42ee6deec596e696636536abfcb06da49771
Author: Stef Walter <stef memberwebs com>
Date:   Sat Jul 18 18:31:48 2009 +0000

    Add support for auto destructing session objects.
    
    These destroy themselves after a certain amount of lifetime
    controlled by the CKA_GNOME_AUTO_DESTRUCT attribute.

 pkcs11/gck/gck-object.c  |  120 ++++++++++++++++++++++++++++++++++++++++++++++
 pkcs11/gck/gck-object.h  |    8 +++
 pkcs11/gck/gck-session.c |   32 ++++++++++++-
 pkcs11/gck/gck-session.h |    5 ++
 pkcs11/pkcs11g.h         |    6 ++
 5 files changed, 170 insertions(+), 1 deletions(-)
---
diff --git a/pkcs11/gck/gck-object.c b/pkcs11/gck/gck-object.c
index 51754a6..928638e 100644
--- a/pkcs11/gck/gck-object.c
+++ b/pkcs11/gck/gck-object.c
@@ -28,7 +28,9 @@
 #include "gck-manager.h"
 #include "gck-object.h"
 #include "gck-transaction.h"
+#include "gck-session.h"
 #include "gck-store.h"
+#include "gck-timer.h"
 #include "gck-util.h"
 
 enum {
@@ -47,12 +49,18 @@ enum {
 
 static guint signals[LAST_SIGNAL] = { 0 };
 
+typedef struct _GckObjectLifetime {
+	GckTimer *timed_timer;
+	glong timed_when;
+} GckObjectLifetime;
+
 struct _GckObjectPrivate {
 	CK_OBJECT_HANDLE handle;
 	GckManager *manager;
 	GckStore *store;
 	gchar *unique;
 	gboolean permanent;
+	GckObjectLifetime *lifetime;
 };
 
 G_DEFINE_TYPE (GckObject, gck_object, G_TYPE_OBJECT);
@@ -61,6 +69,60 @@ G_DEFINE_TYPE (GckObject, gck_object, G_TYPE_OBJECT);
  * INTERNAL 
  */
 
+static void
+kaboom_callback (GckTimer *timer, gpointer user_data)
+{
+	GckObject *self = user_data;
+	GckTransaction *transaction;
+	GckObjectLifetime *lifetime;
+	GckSession *session;
+	CK_RV rv;
+
+	g_return_if_fail (GCK_IS_OBJECT (self));
+	g_return_if_fail (self->pv->lifetime);
+	lifetime = self->pv->lifetime;
+
+	g_return_if_fail (timer == lifetime->timed_timer);
+	lifetime->timed_timer = NULL;
+
+	g_object_ref (self);
+
+	transaction = gck_transaction_new ();
+
+	session = gck_session_for_session_object (self);
+	g_return_if_fail (session);
+	gck_session_destroy_session_object (session, transaction, GCK_OBJECT (self));
+
+	gck_transaction_complete (transaction);
+	rv = gck_transaction_get_result (transaction);
+	g_object_unref (transaction);
+
+	if (rv != CKR_OK)
+		g_warning ("Unexpected failure to auto destruct object (code: %lu)", (gulong)rv);
+
+	g_object_run_dispose (G_OBJECT (self));
+	g_object_unref (self);
+}
+
+static gboolean
+start_callback (GckTransaction *transaction, GObject *obj, gpointer user_data)
+{
+	GckObject *self = GCK_OBJECT (obj);
+	GckObjectLifetime *lifetime;
+	GckSession *session = user_data;
+
+	g_return_val_if_fail (GCK_IS_OBJECT (self), FALSE);
+	g_return_val_if_fail (GCK_IS_SESSION (session), FALSE);
+	g_return_val_if_fail (self->pv->lifetime, FALSE);
+	lifetime = self->pv->lifetime;
+
+	g_return_val_if_fail (!lifetime->timed_timer, FALSE);
+	lifetime->timed_timer = gck_timer_start (gck_session_get_module (session), 
+	                                         lifetime->timed_when, kaboom_callback, self);
+
+	return TRUE;
+}
+
 /* -----------------------------------------------------------------------------
  * OBJECT 
  */
@@ -85,6 +147,9 @@ gck_object_real_get_attribute (GckObject *self, CK_ATTRIBUTE* attr)
 		if (self->pv->unique)
 			return gck_attribute_set_string (attr, self->pv->unique);
 		return CKR_ATTRIBUTE_TYPE_INVALID;
+	case CKA_GNOME_AUTO_DESTRUCT:
+		return gck_attribute_set_time (attr, self->pv->lifetime ?
+		                                     self->pv->lifetime->timed_when : -1);
 	};
 
 	/* Give store a shot */
@@ -136,6 +201,31 @@ gck_object_real_set_attribute (GckObject *self, GckTransaction* transaction, CK_
 	gck_transaction_fail (transaction, CKR_ATTRIBUTE_TYPE_INVALID);
 }
 
+static void
+gck_object_real_create_attribute (GckObject *self, GckTransaction *transaction, 
+	                          CK_ATTRIBUTE *attr, GckSession *session)
+{
+	CK_RV rv;
+
+	switch (attr->type) {
+	case CKA_GNOME_AUTO_DESTRUCT:
+		if (!self->pv->lifetime)
+			self->pv->lifetime = g_slice_new0 (GckObjectLifetime);
+		rv = gck_attribute_get_time (attr, &self->pv->lifetime->timed_when);
+		gck_attribute_consume (attr);
+		if (rv == CKR_OK) {
+			/* Must be a session object for an auto destruct */
+			if (self->pv->lifetime->timed_when >= 0 && self->pv->permanent)
+				rv = CKR_TEMPLATE_INCONSISTENT;
+			else
+				gck_transaction_add (transaction, self, start_callback, session);
+		}
+		if (rv != CKR_OK)
+			gck_transaction_fail (transaction, rv);
+		return;
+	};
+}
+
 static CK_RV
 gck_object_real_unlock (GckObject *self, CK_UTF8CHAR_PTR pin, CK_ULONG n_pin)
 {
@@ -174,6 +264,7 @@ static void
 gck_object_dispose (GObject *obj)
 {
 	GckObject *self = GCK_OBJECT (obj);
+	GckObjectLifetime *lifetime;
 	
 	if (self->pv->manager)
 		gck_manager_unregister_object (self->pv->manager, self);
@@ -181,6 +272,16 @@ gck_object_dispose (GObject *obj)
 	
 	g_object_set (self, "store", NULL, NULL);
 	g_assert (self->pv->store == NULL);
+
+	if (self->pv->lifetime) {
+		lifetime = self->pv->lifetime;
+		if (lifetime->timed_timer)
+			gck_timer_cancel (lifetime->timed_timer);
+		lifetime->timed_timer = NULL;
+
+		g_slice_free (GckObjectLifetime, lifetime);
+		self->pv->lifetime = NULL;
+	}
     
 	G_OBJECT_CLASS (gck_object_parent_class)->dispose (obj);
 }
@@ -193,6 +294,8 @@ gck_object_finalize (GObject *obj)
 	g_assert (self->pv->manager == NULL);
 	g_free (self->pv->unique);
 
+	g_assert (self->pv->lifetime == NULL);
+
 	G_OBJECT_CLASS (gck_object_parent_class)->finalize (obj);
 }
 
@@ -295,6 +398,7 @@ gck_object_class_init (GckObjectClass *klass)
 	klass->unlock = gck_object_real_unlock;
 	klass->get_attribute = gck_object_real_get_attribute;
 	klass->set_attribute = gck_object_real_set_attribute;
+	klass->create_attribute = gck_object_real_create_attribute;
 	
 	g_object_class_install_property (gobject_class, PROP_HANDLE,
 	           g_param_spec_ulong ("handle", "Handle", "Object handle",
@@ -365,6 +469,22 @@ gck_object_set_attribute (GckObject *self, GckTransaction *transaction,
 }
 
 void
+gck_object_create_attribute (GckObject *self, GckTransaction *transaction,
+                             CK_ATTRIBUTE_PTR attr, GckSession *session)
+{
+	g_return_if_fail (GCK_IS_OBJECT (self));
+	g_return_if_fail (GCK_IS_TRANSACTION (transaction));
+	g_return_if_fail (!gck_transaction_get_failed (transaction));
+	g_return_if_fail (GCK_IS_SESSION (session));
+	g_return_if_fail (attr);
+
+	g_assert (GCK_OBJECT_GET_CLASS (self)->create_attribute);
+
+	/* Check that the value will actually change */
+	GCK_OBJECT_GET_CLASS (self)->create_attribute (self, transaction, attr, session);
+}
+
+void
 gck_object_notify_attribute  (GckObject *self, CK_ATTRIBUTE_TYPE attr_type)
 {
 	g_return_if_fail (GCK_IS_OBJECT (self));
diff --git a/pkcs11/gck/gck-object.h b/pkcs11/gck/gck-object.h
index cb5b12d..a1129c8 100644
--- a/pkcs11/gck/gck-object.h
+++ b/pkcs11/gck/gck-object.h
@@ -56,6 +56,9 @@ struct _GckObjectClass {
 	
 	void (*set_attribute) (GckObject *object, GckTransaction *transaction, CK_ATTRIBUTE *attr);
 	
+	void (*create_attribute) (GckObject *object, GckTransaction *transaction, 
+	                          CK_ATTRIBUTE *attr, GckSession *session);
+
 	CK_RV (*unlock) (GckObject *self, CK_UTF8CHAR_PTR pin, CK_ULONG n_pin);
 };
 
@@ -88,6 +91,11 @@ void                   gck_object_set_attribute          (GckObject *self,
                                                           GckTransaction *transaction,
                                                           CK_ATTRIBUTE_PTR attr);
 
+void                   gck_object_create_attribute       (GckObject *self,
+                                                          GckTransaction *transaction,
+                                                          CK_ATTRIBUTE_PTR attr,
+                                                          GckSession *session);
+
 void                   gck_object_notify_attribute       (GckObject *self,
                                                           CK_ATTRIBUTE_TYPE attr_type);
 
diff --git a/pkcs11/gck/gck-session.c b/pkcs11/gck/gck-session.c
index 3b0744e..a8055d4 100644
--- a/pkcs11/gck/gck-session.c
+++ b/pkcs11/gck/gck-session.c
@@ -558,6 +558,13 @@ gck_session_class_init (GckSessionClass *klass)
  * PUBLIC 
  */
 
+GckSession*
+gck_session_for_session_object (GckObject *obj)
+{
+	g_return_val_if_fail (GCK_IS_OBJECT (obj), NULL);
+	return GCK_SESSION (g_object_get_data (G_OBJECT (obj), "owned-by-session"));
+}
+
 CK_SESSION_HANDLE
 gck_session_get_handle (GckSession *self)
 {
@@ -654,6 +661,18 @@ gck_session_login_context_specific (GckSession *self, CK_UTF8CHAR_PTR pin, CK_UL
 	return gck_object_unlock (object, pin, n_pin);
 }
 
+void
+gck_session_destroy_session_object (GckSession *self, GckTransaction *transaction,
+                                    GckObject *obj)
+{
+	g_return_if_fail (GCK_IS_SESSION (self));
+	g_return_if_fail (gck_session_for_session_object (obj) == self);
+	g_return_if_fail (GCK_IS_TRANSACTION (transaction));
+	g_return_if_fail (!gck_transaction_get_failed (transaction));
+
+	remove_object (self, transaction, obj);
+}
+
 /* -----------------------------------------------------------------------------
  * PKCS#11
  */
@@ -772,6 +791,17 @@ gck_session_C_CreateObject (GckSession* self, CK_ATTRIBUTE_PTR template,
 		}
 	}
 	
+	if (!gck_transaction_get_failed (transaction)) {
+		g_object_set (object, "permanent", is_token, NULL);
+		gck_attributes_consume (attrs, n_attrs, CKA_TOKEN, G_MAXULONG);
+	}
+
+	/* Give the object a chance to create additional attributes */
+	for (i = 0; i < n_attrs && !gck_transaction_get_failed (transaction); ++i) {
+		if (!gck_attribute_consumed (&attrs[i]))
+			gck_object_create_attribute (object, transaction, &attrs[i], self);
+	}
+
 	/* Find somewhere to store the object */
 	if (!gck_transaction_get_failed (transaction)) {
 		if (is_token) 
@@ -885,7 +915,7 @@ gck_session_C_DestroyObject (GckSession* self, CK_OBJECT_HANDLE handle)
 	transaction = gck_transaction_new ();
 
 	/* Lookup the actual session that owns this object, if no session, then a token object */
-	session = g_object_get_data (G_OBJECT (object), "owned-by-session");
+	session = gck_session_for_session_object (object);
 	if (session != NULL)
 		remove_object (session, transaction, object);
 	else
diff --git a/pkcs11/gck/gck-session.h b/pkcs11/gck/gck-session.h
index 6a1b327..815e62c 100644
--- a/pkcs11/gck/gck-session.h
+++ b/pkcs11/gck/gck-session.h
@@ -59,6 +59,8 @@ GckSession*              gck_session_new                                (GckModu
                                                                          CK_SLOT_ID slot_id,
                                                                          CK_FLAGS flags);
 
+GckSession*              gck_session_for_session_object                 (GckObject *obj);
+
 CK_SESSION_HANDLE        gck_session_get_handle                         (GckSession *self);
 
 CK_SLOT_ID               gck_session_get_slot_id                        (GckSession *self);
@@ -86,6 +88,9 @@ CK_RV                    gck_session_login_context_specific             (GckSess
                                                                          CK_UTF8CHAR_PTR pin,
                                                                          CK_ULONG n_pin);
 
+void                     gck_session_destroy_session_object             (GckSession *self,
+                                                                         GckTransaction *transaction,
+                                                                         GckObject *obj);
 
 
 
diff --git a/pkcs11/pkcs11g.h b/pkcs11/pkcs11g.h
index 2651ef5..d2ac6d9 100644
--- a/pkcs11/pkcs11g.h
+++ b/pkcs11/pkcs11g.h
@@ -97,4 +97,10 @@
 #define CKA_GNOME_PURPOSE_IPSEC_USER             (CKA_GNOME + 108)
 #define CKA_GNOME_PURPOSE_TIME_STAMPING          (CKA_GNOME + 109)
 
+/* -------------------------------------------------------------------
+ * AUTO-DESTRUCT
+ */
+
+#define CKA_GNOME_AUTO_DESTRUCT                  (CKO_GNOME + 200)
+
 #endif /* PKCS11G_H */



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