[gnome-keyring: 3/6] Add support for auto destructing session objects.
- From: Stefan Walter <stefw src gnome org>
- To: svn-commits-list gnome org
- Subject: [gnome-keyring: 3/6] Add support for auto destructing session objects.
- Date: Sat, 18 Jul 2009 18:36:00 +0000 (UTC)
commit ad2c0e75977c7a76c25ef27fb29b767d3c1e94ad
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]