[gnome-keyring] [pkcs11] Rework how credentials, and auto-destruct work.
- From: Stefan Walter <stefw src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [gnome-keyring] [pkcs11] Rework how credentials, and auto-destruct work.
- Date: Mon, 1 Feb 2010 02:32:52 +0000 (UTC)
commit d6192caf4dad9a6166c7c6e248f3fb159f1d5ee1
Author: Stef Walter <stef memberwebs com>
Date: Sun Dec 20 17:19:38 2009 +0000
[pkcs11] Rework how credentials, and auto-destruct work.
Add the concept of a CKA_CREDENTIAL_TEMPLATE from which
credential objects for a given object take attributes.
Change around the various auto-destruct attributes.
daemon/ssh-agent/gkd-ssh-agent-ops.c | 18 +--
pkcs11/gck/gck-attributes.c | 42 +++++
pkcs11/gck/gck-attributes.h | 4 +
pkcs11/gck/gck-credential.c | 188 +++++++++++++------
pkcs11/gck/gck-credential.h | 21 ++-
pkcs11/gck/gck-object.c | 152 ++++++++++++----
pkcs11/gck/gck-object.h | 2 +
pkcs11/gck/gck-private-xsa-key.c | 19 +--
pkcs11/gck/gck-session.c | 59 +------
pkcs11/gck/gck-session.h | 11 +-
pkcs11/gck/gck-timer.c | 7 +-
pkcs11/gck/gck-timer.h | 2 +-
pkcs11/gck/tests/unit-test-credential.c | 67 +++-----
pkcs11/gck/tests/unit-test-object.c | 51 ++----
pkcs11/gck/tests/unit-test-timer.c | 47 ++---
pkcs11/pkcs11g.h | 15 --
pkcs11/pkcs11i.h | 22 +++
pkcs11/secret-store/gck-secret-binary.c | 17 +-
pkcs11/secret-store/gck-secret-collection.c | 107 ++++++++---
pkcs11/secret-store/gck-secret-collection.h | 10 +-
pkcs11/secret-store/gck-secret-item.c | 13 +-
pkcs11/secret-store/gck-secret-textual.c | 5 +-
.../tests/unit-test-secret-collection.c | 18 ++-
23 files changed, 521 insertions(+), 376 deletions(-)
---
diff --git a/daemon/ssh-agent/gkd-ssh-agent-ops.c b/daemon/ssh-agent/gkd-ssh-agent-ops.c
index 98567ae..07ae493 100644
--- a/daemon/ssh-agent/gkd-ssh-agent-ops.c
+++ b/daemon/ssh-agent/gkd-ssh-agent-ops.c
@@ -28,6 +28,7 @@
#include "pkcs11/pkcs11.h"
#include "pkcs11/pkcs11g.h"
+#include "pkcs11/pkcs11i.h"
#include "egg/egg-secure-memory.h"
@@ -545,12 +546,8 @@ static gboolean
load_contraints (EggBuffer *buffer, gsize offset, gsize *next_offset,
GP11Attributes *priv, GP11Attributes *pub)
{
- GTimeVal tv;
guchar constraint;
guint32 lifetime;
- time_t time;
- struct tm tm;
- gchar buf[20];
/*
* Constraints are a byte flag, and optional data depending
@@ -566,17 +563,8 @@ load_contraints (EggBuffer *buffer, gsize offset, gsize *next_offset,
if (!egg_buffer_get_uint32 (buffer, offset, &offset, &lifetime))
return FALSE;
- g_get_current_time (&tv);
- time = tv.tv_sec + lifetime;
-
- if (!gmtime_r (&time, &tm))
- g_return_val_if_reached (FALSE);
-
- if (!strftime(buf, sizeof (buf), "%Y%m%d%H%M%S00", &tm))
- g_return_val_if_reached (FALSE);
-
- gp11_attributes_add_data (pub, CKA_GNOME_AUTO_DESTRUCT, buf, 16);
- gp11_attributes_add_data (priv, CKA_GNOME_AUTO_DESTRUCT, buf, 16);
+ gp11_attributes_add_ulong (pub, CKA_G_DESTRUCT_AFTER, lifetime);
+ gp11_attributes_add_ulong (priv, CKA_G_DESTRUCT_AFTER, lifetime);
break;
case GKD_SSH_FLAG_CONSTRAIN_CONFIRM:
diff --git a/pkcs11/gck/gck-attributes.c b/pkcs11/gck/gck-attributes.c
index f68babf..62465cd 100644
--- a/pkcs11/gck/gck-attributes.c
+++ b/pkcs11/gck/gck-attributes.c
@@ -287,6 +287,48 @@ gck_attribute_set_mpi (CK_ATTRIBUTE_PTR attr, gcry_mpi_t mpi)
return CKR_OK;
}
+CK_RV
+gck_attribute_set_template (CK_ATTRIBUTE_PTR attr, CK_ATTRIBUTE_PTR template,
+ CK_ULONG n_template)
+{
+ CK_ATTRIBUTE_PTR array;
+ CK_RV rv;
+ gulong len;
+ gulong i;
+
+ g_assert (attr);
+ g_warn_if_fail ((attr->type & CKF_ARRAY_ATTRIBUTE) != 0);
+
+ len = sizeof (CK_ATTRIBUTE) * n_template;
+ if (!attr->pValue) {
+ attr->ulValueLen = len;
+ return CKR_OK;
+ } else if (len > attr->ulValueLen) {
+ attr->ulValueLen = (CK_ULONG)-1;
+ return CKR_BUFFER_TOO_SMALL;
+ }
+
+ attr->ulValueLen = len;
+ array = attr->pValue;
+ rv = CKR_OK;
+
+ /* Start working with individual elements */
+ for (i = 0; i < n_template; ++i) {
+ array[i].type = template[i].type;
+ if (!array[i].pValue) {
+ array[i].ulValueLen = template[i].ulValueLen;
+ } else if (array[i].ulValueLen < template[i].ulValueLen) {
+ array[i].ulValueLen = (CK_ULONG)-1;
+ rv = CKR_BUFFER_TOO_SMALL;
+ } else {
+ memcpy(array[i].pValue, template[i].pValue, template[i].ulValueLen);
+ array[i].ulValueLen = template[i].ulValueLen;
+ }
+ }
+
+ return CKR_OK;
+}
+
gboolean
gck_attribute_equal (gconstpointer v1, gconstpointer v2)
{
diff --git a/pkcs11/gck/gck-attributes.h b/pkcs11/gck/gck-attributes.h
index dc266bb..5e8bcb6 100644
--- a/pkcs11/gck/gck-attributes.h
+++ b/pkcs11/gck/gck-attributes.h
@@ -67,6 +67,10 @@ CK_RV gck_attribute_set_data (CK_ATTRI
CK_RV gck_attribute_set_mpi (CK_ATTRIBUTE_PTR attr,
gcry_mpi_t mpi);
+CK_RV gck_attribute_set_template (CK_ATTRIBUTE_PTR attr,
+ CK_ATTRIBUTE_PTR template,
+ CK_ULONG n_template);
+
guint gck_attribute_hash (gconstpointer v);
gboolean gck_attribute_equal (gconstpointer a,
diff --git a/pkcs11/gck/gck-credential.c b/pkcs11/gck/gck-credential.c
index d0e97ca..74ce3e6 100644
--- a/pkcs11/gck/gck-credential.c
+++ b/pkcs11/gck/gck-credential.c
@@ -28,13 +28,12 @@
#include "gck-transaction.h"
#include "pkcs11/pkcs11.h"
-#include "pkcs11/pkcs11g.h"
+#include "pkcs11/pkcs11i.h"
enum {
PROP_0,
PROP_OBJECT,
- PROP_SECRET,
- PROP_USES_REMAINING
+ PROP_SECRET
};
struct _GckCredentialPrivate {
@@ -42,13 +41,12 @@ struct _GckCredentialPrivate {
/* The object we authenticated */
GckObject *object;
- /* Optional secret and/or data */
+ /* Secret which created this credential */
GckSecret *secret;
- gpointer user_data;
- GDestroyNotify destroy;
- /* Can limit by number of uses remaining */
- gint uses_remaining;
+ /* Stored data */
+ GType user_type;
+ gpointer user_data;
};
G_DEFINE_TYPE (GckCredential, gck_credential, GCK_TYPE_OBJECT);
@@ -133,6 +131,21 @@ object_went_away (gpointer data, GObject *old_object)
self_destruct (self);
}
+static void
+clear_data (GckCredential *self)
+{
+ if (!self->pv->user_data)
+ return;
+ if (G_TYPE_IS_BOXED (self->pv->user_type))
+ g_boxed_free (self->pv->user_type, self->pv->user_data);
+ else if (G_TYPE_IS_OBJECT (self->pv->user_type))
+ g_object_unref (self->pv->user_data);
+ else
+ g_assert_not_reached ();
+ self->pv->user_data = NULL;
+ self->pv->user_type = 0;
+}
+
/* -----------------------------------------------------------------------------
* OBJECT
*/
@@ -155,12 +168,6 @@ gck_credential_real_get_attribute (GckObject *base, GckSession *session, CK_ATTR
handle = self->pv->object ? gck_object_get_handle (self->pv->object) : 0;
return gck_attribute_set_ulong (attr, handle);
- case CKA_G_USES_REMAINING:
- if (self->pv->uses_remaining < 0)
- return gck_attribute_set_ulong (attr, (CK_ULONG)-1);
- else
- return gck_attribute_set_ulong (attr, self->pv->uses_remaining);
-
case CKA_VALUE:
return CKR_ATTRIBUTE_SENSITIVE;
};
@@ -181,7 +188,6 @@ static void
gck_credential_init (GckCredential *self)
{
self->pv = G_TYPE_INSTANCE_GET_PRIVATE (self, GCK_TYPE_CREDENTIAL, GckCredentialPrivate);
- self->pv->uses_remaining = -1;
}
static void
@@ -193,14 +199,7 @@ gck_credential_dispose (GObject *obj)
g_object_weak_unref (G_OBJECT (self->pv->object), object_went_away, self);
self->pv->object = NULL;
- if (self->pv->secret)
- g_object_unref (self->pv->secret);
- self->pv->secret = NULL;
-
- if (self->pv->user_data && self->pv->destroy)
- (self->pv->destroy)(self->pv->user_data);
- self->pv->user_data = NULL;
- self->pv->destroy = NULL;
+ clear_data (self);
G_OBJECT_CLASS (gck_credential_parent_class)->dispose (obj);
}
@@ -211,9 +210,8 @@ gck_credential_finalize (GObject *obj)
GckCredential *self = GCK_CREDENTIAL (obj);
g_assert (!self->pv->object);
- g_assert (!self->pv->secret);
+ g_assert (!self->pv->user_type);
g_assert (!self->pv->user_data);
- g_assert (!self->pv->destroy);
G_OBJECT_CLASS (gck_credential_parent_class)->finalize (obj);
}
@@ -255,9 +253,6 @@ gck_credential_get_property (GObject *obj, guint prop_id, GValue *value,
case PROP_SECRET:
g_value_set_object (value, gck_credential_get_secret (self));
break;
- case PROP_USES_REMAINING:
- g_value_set_int (value, gck_credential_get_uses_remaining (self));
- break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
break;
@@ -288,10 +283,6 @@ gck_credential_class_init (GckCredentialClass *klass)
g_object_class_install_property (gobject_class, PROP_SECRET,
g_param_spec_object ("secret", "Secret", "Optiontal secret",
GCK_TYPE_SECRET, G_PARAM_READWRITE));
-
- g_object_class_install_property (gobject_class, PROP_USES_REMAINING,
- g_param_spec_int ("uses-remaining", "Uses Remaining", "Uses remaining",
- -1, G_MAXINT, -1, G_PARAM_READWRITE));
}
/* -----------------------------------------------------------------------------
@@ -410,47 +401,124 @@ gck_credential_get_object (GckCredential *self)
return self->pv->object;
}
-gint
-gck_credential_get_uses_remaining (GckCredential *self)
+gpointer
+gck_credential_peek_data (GckCredential *self, GType type)
{
- g_return_val_if_fail (GCK_IS_CREDENTIAL (self), 0);
- return self->pv->uses_remaining;
+ g_return_val_if_fail (GCK_IS_CREDENTIAL (self), NULL);
+ if (!self->pv->user_data)
+ return NULL;
+ g_return_val_if_fail (type == self->pv->user_type, NULL);
+ return self->pv->user_data;
}
-void
-gck_credential_set_uses_remaining (GckCredential *self, gint use_count)
+gpointer
+gck_credential_pop_data (GckCredential *self, GType type)
{
- g_return_if_fail (GCK_IS_CREDENTIAL (self));
- g_return_if_fail (use_count != 0);
+ gpointer data = NULL;
+ g_return_val_if_fail (GCK_IS_CREDENTIAL (self), NULL);
- self->pv->uses_remaining = use_count;
- g_object_notify (G_OBJECT (self), "uses-remaining");
+ if (self->pv->user_data) {
+ g_return_val_if_fail (type == self->pv->user_type, NULL);
+ if (G_TYPE_IS_BOXED (self->pv->user_type))
+ data = g_boxed_copy (self->pv->user_type, self->pv->user_data);
+ else if (G_TYPE_IS_OBJECT (self->pv->user_type))
+ data = g_object_ref (self->pv->user_data);
+ else
+ g_assert_not_reached ();
+ }
+
+ gck_object_mark_used (GCK_OBJECT (self));
+ return data;
}
void
-gck_credential_throw_away_one_use (GckCredential *self)
+gck_credential_set_data (GckCredential *self, GType type, gpointer data)
{
g_return_if_fail (GCK_IS_CREDENTIAL (self));
- if (self->pv->uses_remaining > 0)
- --(self->pv->uses_remaining);
- if (self->pv->uses_remaining == 0)
- self_destruct (self);
-}
-gpointer
-gck_credential_get_data (GckCredential *self)
-{
- g_return_val_if_fail (GCK_IS_CREDENTIAL (self), NULL);
- return self->pv->user_data;
+ if (data) {
+ g_return_if_fail (type);
+ g_return_if_fail (G_TYPE_IS_BOXED (type) || G_TYPE_IS_OBJECT (type));
+ }
+
+ clear_data (self);
+
+ if (data) {
+ self->pv->user_type = type;
+ if (G_TYPE_IS_BOXED (type))
+ self->pv->user_data = g_boxed_copy (type, data);
+ else if (G_TYPE_IS_OBJECT (type))
+ self->pv->user_data = g_object_ref (data);
+ else
+ g_assert_not_reached ();
+ }
}
-void
-gck_credential_set_data (GckCredential *self, gpointer data, GDestroyNotify destroy)
+gboolean
+gck_credential_for_each (GckSession *session, GckObject *object,
+ GckCredentialFunc func, gpointer user_data)
{
- g_return_if_fail (GCK_IS_CREDENTIAL (self));
+ CK_OBJECT_HANDLE handle;
+ CK_OBJECT_CLASS klass;
+ CK_ATTRIBUTE attrs[2];
+ GList *results, *l;
+ GckCredential *cred;
+ gboolean ret;
+
+ g_return_val_if_fail (GCK_IS_SESSION (session), FALSE);
+ g_return_val_if_fail (GCK_IS_OBJECT (object), FALSE);
+ g_return_val_if_fail (func, FALSE);
+
+ /* Do we have one right on the session */
+ cred = gck_session_get_credential (session);
+ if (cred && gck_credential_get_object (cred) == object) {
+ g_object_ref (cred);
+ ret = (func) (cred, object, user_data);
+ g_object_unref (cred);
+ if (ret)
+ return TRUE;
+ }
+
+ klass = CKO_G_CREDENTIAL;
+ attrs[0].type = CKA_CLASS;
+ attrs[0].pValue = &klass;
+ attrs[0].ulValueLen = sizeof (klass);
+
+ handle = gck_object_get_handle (object);
+ attrs[1].type = CKA_G_OBJECT;
+ attrs[1].pValue = &handle;
+ attrs[1].ulValueLen = sizeof (handle);
+
+ /* Find any on the session */
+ results = gck_manager_find_by_attributes (gck_session_get_manager (session),
+ attrs, G_N_ELEMENTS (attrs));
+
+ for (l = results; l; l = g_list_next (l)) {
+ g_object_ref (l->data);
+ ret = (func) (l->data, object, user_data);
+ g_object_unref (l->data);
+ if (ret)
+ break;
+ }
+
+ g_list_free (results);
+
+ if (l != NULL)
+ return TRUE;
+
+ /* Find any in the token */
+ results = gck_manager_find_by_attributes (gck_module_get_manager (gck_session_get_module (session)),
+ attrs, G_N_ELEMENTS (attrs));
+
+ for (l = results; l; l = g_list_next (l)) {
+ g_object_ref (l->data);
+ ret = (func) (l->data, object, user_data);
+ g_object_unref (l->data);
+ if (ret)
+ break;
+ }
+
+ g_list_free (results);
- if (self->pv->user_data && self->pv->destroy)
- (self->pv->destroy) (self->pv->user_data);
- self->pv->user_data = data;
- self->pv->destroy = destroy;
+ return (l != NULL);
}
diff --git a/pkcs11/gck/gck-credential.h b/pkcs11/gck/gck-credential.h
index c20e03e..01d5589 100644
--- a/pkcs11/gck/gck-credential.h
+++ b/pkcs11/gck/gck-credential.h
@@ -72,17 +72,24 @@ const gchar* gck_credential_get_password (GckCredential
GckObject* gck_credential_get_object (GckCredential *self);
-gpointer gck_credential_get_data (GckCredential *self);
+gpointer gck_credential_peek_data (GckCredential *self,
+ GType type);
+
+gpointer gck_credential_pop_data (GckCredential *self,
+ GType type);
void gck_credential_set_data (GckCredential *self,
- gpointer data,
- GDestroyNotify destroy);
+ GType type,
+ gpointer data);
-gint gck_credential_get_uses_remaining (GckCredential *self);
+typedef gboolean (*GckCredentialFunc) (GckCredential *cred,
+ GckObject *object,
+ gpointer user_data);
-void gck_credential_set_uses_remaining (GckCredential *self,
- gint use_count);
-void gck_credential_throw_away_one_use (GckCredential *self);
+gboolean gck_credential_for_each (GckSession *self,
+ GckObject *object,
+ GckCredentialFunc func,
+ gpointer user_data);
#endif /* __GCK_CREDENTIAL_H__ */
diff --git a/pkcs11/gck/gck-object.c b/pkcs11/gck/gck-object.c
index 2d28df3..0b2544f 100644
--- a/pkcs11/gck/gck-object.c
+++ b/pkcs11/gck/gck-object.c
@@ -23,8 +23,10 @@
#include "pkcs11/pkcs11.h"
#include "pkcs11/pkcs11g.h"
+#include "pkcs11/pkcs11i.h"
#include "gck-attributes.h"
+#include "gck-credential.h"
#include "gck-manager.h"
#include "gck-object.h"
#include "gck-transaction.h"
@@ -51,8 +53,12 @@ enum {
static guint signals[LAST_SIGNAL] = { 0 };
typedef struct _GckObjectTransient {
- GckTimer *timed_timer;
- glong timed_when;
+ GckTimer *timer;
+ gulong timed_after;
+ gulong timed_idle;
+ glong stamp_used;
+ glong stamp_created;
+ gulong uses_remaining;
} GckObjectTransient;
struct _GckObjectPrivate {
@@ -76,33 +82,62 @@ void _gck_manager_unregister_object (GckManager *self, GckObject *object);
*/
static void
-kaboom_callback (GckTimer *timer, gpointer user_data)
+self_destruct (GckObject *self)
{
- GckObject *self = user_data;
GckTransaction *transaction;
- GckObjectTransient *transient;
CK_RV rv;
- g_return_if_fail (GCK_IS_OBJECT (self));
- g_return_if_fail (self->pv->transient);
- transient = self->pv->transient;
-
- g_return_if_fail (timer == transient->timed_timer);
- transient->timed_timer = NULL;
-
- g_object_ref (self);
-
transaction = gck_transaction_new ();
- /* Off we go */
gck_object_destroy (self, transaction);
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);
+}
+
+static void
+timer_callback (GckTimer *timer, gpointer user_data)
+{
+ GckObject *self = user_data;
+ glong after, idle, offset;
+ GckObjectTransient *transient;
+ GTimeVal tv;
+
+ g_return_if_fail (GCK_IS_OBJECT (self));
+
+ g_object_ref (self);
+
+ g_return_if_fail (self->pv->transient);
+ transient = self->pv->transient;
+ g_return_if_fail (timer == transient->timer);
+ transient->timer = NULL;
+
+ g_get_current_time (&tv);
+ idle = after = G_MAXLONG;
+
+ /* Are we supposed to be destroyed after a certain time? */
+ if (transient->timed_after) {
+ g_return_if_fail (transient->stamp_created);
+ after = (transient->stamp_created + transient->timed_after) - tv.tv_sec;
+ }
+
+ /* Are we supposed to be destroyed after an idle time? */
+ if (transient->timed_idle) {
+ g_return_if_fail (transient->stamp_used);
+ idle = (transient->stamp_used + transient->timed_idle) - tv.tv_sec;
+ }
+
+ /* Okay, time to destroy? */
+ offset = MIN (after, idle);
+ if (offset <= 0)
+ self_destruct (self);
+
+ /* Setup the next timer */
+ else
+ transient->timer = gck_timer_start (self->pv->module, offset, timer_callback, self);
g_object_unref (self);
}
@@ -112,15 +147,19 @@ start_callback (GckTransaction *transaction, GObject *obj, gpointer user_data)
{
GckObject *self = GCK_OBJECT (obj);
GckObjectTransient *transient;
+ GTimeVal tv;
g_return_val_if_fail (GCK_IS_OBJECT (self), FALSE);
g_return_val_if_fail (self->pv->transient, FALSE);
transient = self->pv->transient;
+ g_return_val_if_fail (!transient->timer, FALSE);
- g_return_val_if_fail (!transient->timed_timer, FALSE);
- transient->timed_timer = gck_timer_start (self->pv->module, transient->timed_when,
- kaboom_callback, self);
+ g_get_current_time (&tv);
+ transient->stamp_created = tv.tv_sec;
+ transient->stamp_used = tv.tv_sec;
+ /* Start the timer going */
+ timer_callback (NULL, self);
return TRUE;
}
@@ -153,6 +192,15 @@ complete_expose (GckTransaction *transaction, GObject *obj, gpointer user_data)
return TRUE;
}
+static gboolean
+find_credential (GckCredential *cred, GckObject *object, gpointer user_data)
+{
+ CK_OBJECT_HANDLE *result = user_data;
+ g_return_val_if_fail (!*result, FALSE);
+ *result = gck_object_get_handle (GCK_OBJECT (cred));
+ return TRUE;
+}
+
/* -----------------------------------------------------------------------------
* OBJECT
*/
@@ -160,8 +208,9 @@ complete_expose (GckTransaction *transaction, GObject *obj, gpointer user_data)
static CK_RV
gck_object_real_get_attribute (GckObject *self, GckSession *session, CK_ATTRIBUTE* attr)
{
+ CK_OBJECT_HANDLE handle = 0;
CK_RV rv;
-
+
switch (attr->type)
{
case CKA_CLASS:
@@ -173,15 +222,24 @@ gck_object_real_get_attribute (GckObject *self, GckSession *session, CK_ATTRIBUT
return gck_attribute_set_bool (attr, FALSE);
case CKA_TOKEN:
return gck_attribute_set_bool (attr, gck_object_is_token (self));
+ case CKA_G_CREDENTIAL:
+ gck_credential_for_each (session, GCK_OBJECT (self), find_credential, &handle);
+ return gck_attribute_set_ulong (attr, handle);
case CKA_GNOME_UNIQUE:
if (self->pv->unique)
return gck_attribute_set_string (attr, self->pv->unique);
return CKR_ATTRIBUTE_TYPE_INVALID;
case CKA_GNOME_TRANSIENT:
return gck_attribute_set_bool (attr, self->pv->transient ? TRUE : FALSE);
- case CKA_GNOME_AUTO_DESTRUCT:
- return gck_attribute_set_time (attr, self->pv->transient ?
- self->pv->transient->timed_when : -1);
+ case CKA_G_DESTRUCT_AFTER:
+ return gck_attribute_set_ulong (attr, self->pv->transient ?
+ self->pv->transient->timed_after : 0);
+ case CKA_G_DESTRUCT_IDLE:
+ return gck_attribute_set_ulong (attr, self->pv->transient ?
+ self->pv->transient->timed_idle : 0);
+ case CKA_G_DESTRUCT_USES:
+ return gck_attribute_set_ulong (attr, self->pv->transient ?
+ self->pv->transient->uses_remaining : 0);
};
/* Give store a shot */
@@ -250,9 +308,9 @@ gck_object_real_create_attributes (GckObject *self, GckSession *session,
GckTransaction *transaction, CK_ATTRIBUTE *attrs, CK_ULONG n_attrs)
{
CK_ATTRIBUTE_PTR transient_attr;
- CK_ATTRIBUTE_PTR lifetime_attr;
gboolean transient = FALSE;
- glong lifetime = -1;
+ gulong after = 0;
+ gulong idle = 0;
CK_RV rv;
/* Parse the transient attribute */
@@ -267,15 +325,8 @@ gck_object_real_create_attributes (GckObject *self, GckSession *session,
}
/* Parse the auto destruct attribute */
- lifetime_attr = gck_attributes_find (attrs, n_attrs, CKA_GNOME_AUTO_DESTRUCT);
- if (lifetime_attr) {
- rv = gck_attribute_get_time (lifetime_attr, &lifetime);
- gck_attribute_consume (lifetime_attr);
- if (rv != CKR_OK) {
- gck_transaction_fail (transaction, rv);
- return;
- }
-
+ if (gck_attributes_find_ulong (attrs, n_attrs, CKA_G_DESTRUCT_AFTER, &after) ||
+ gck_attributes_find_ulong (attrs, n_attrs, CKA_G_DESTRUCT_IDLE, &idle)) {
/* Default for the transient attribute */
if (!transient_attr)
transient = TRUE;
@@ -283,10 +334,11 @@ gck_object_real_create_attributes (GckObject *self, GckSession *session,
if (transient) {
self->pv->transient = g_slice_new0 (GckObjectTransient);
- self->pv->transient->timed_when = lifetime;
+ self->pv->transient->timed_after = after;
+ self->pv->transient->timed_idle = idle;
}
- if (lifetime >= 0) {
+ if (after || idle) {
if (!self->pv->transient) {
gck_transaction_fail (transaction, CKR_TEMPLATE_INCONSISTENT);
return;
@@ -354,9 +406,9 @@ gck_object_dispose (GObject *obj)
if (self->pv->transient) {
transient = self->pv->transient;
- if (transient->timed_timer)
- gck_timer_cancel (transient->timed_timer);
- transient->timed_timer = NULL;
+ if (transient->timer)
+ gck_timer_cancel (transient->timer);
+ transient->timer = NULL;
}
G_OBJECT_CLASS (gck_object_parent_class)->dispose (obj);
@@ -663,6 +715,28 @@ gck_object_is_transient (GckObject *self)
return self->pv->transient ? TRUE : FALSE;
}
+void
+gck_object_mark_used (GckObject *self)
+{
+ GckObjectTransient *transient;
+ GTimeVal tv;
+
+ g_return_if_fail (GCK_IS_OBJECT (self));
+ transient = self->pv->transient;
+
+ if (transient) {
+ if (transient->timed_idle) {
+ g_get_current_time (&tv);
+ transient->stamp_used = tv.tv_sec;
+ }
+ if (transient->uses_remaining) {
+ --(transient->uses_remaining);
+ if (transient->uses_remaining == 0)
+ self_destruct (self);
+ }
+ }
+}
+
CK_RV
gck_object_unlock (GckObject *self, GckCredential *cred)
{
diff --git a/pkcs11/gck/gck-object.h b/pkcs11/gck/gck-object.h
index d9b28d1..149a51e 100644
--- a/pkcs11/gck/gck-object.h
+++ b/pkcs11/gck/gck-object.h
@@ -83,6 +83,8 @@ gboolean gck_object_is_token (GckObject *self);
gboolean gck_object_is_transient (GckObject *self);
+void gck_object_mark_used (GckObject *self);
+
CK_RV gck_object_unlock (GckObject *self,
GckCredential *cred);
diff --git a/pkcs11/gck/gck-private-xsa-key.c b/pkcs11/gck/gck-private-xsa-key.c
index f099d2c..5940309 100644
--- a/pkcs11/gck/gck-private-xsa-key.c
+++ b/pkcs11/gck/gck-private-xsa-key.c
@@ -176,12 +176,9 @@ acquire_from_credential (GckCredential *cred, GckObject *object, gpointer user_d
g_assert (!*result);
/* The sexp we stored on the credential */
- *result = gck_credential_get_data (cred);
- if (*result != NULL) {
- *result = gck_sexp_ref (*result);
- gck_credential_throw_away_one_use (cred);
+ *result = gck_credential_pop_data (cred, GCK_BOXED_SEXP);
+ if (*result != NULL)
return TRUE;
- }
return FALSE;
}
@@ -190,7 +187,7 @@ static gboolean
have_from_credential (GckCredential *cred, GckObject *object, gpointer unused)
{
/* The sexp we stored on the credential */
- return gck_credential_get_data (cred) ? TRUE : FALSE;
+ return gck_credential_peek_data (cred, GCK_BOXED_SEXP) ? TRUE : FALSE;
}
/* -----------------------------------------------------------------------------
@@ -245,7 +242,7 @@ gck_private_xsa_key_real_get_attribute (GckObject *base, GckSession *session, CK
case CKA_ALWAYS_AUTHENTICATE:
have = self->pv->sexp ? TRUE : FALSE;
if (!have && session)
- have = gck_session_for_each_credential (session, base, have_from_credential, NULL);
+ have = gck_credential_for_each (session, base, have_from_credential, NULL);
return gck_attribute_set_bool (attr, !have);
case CKA_MODULUS:
@@ -292,8 +289,8 @@ gck_private_xsa_key_real_acquire_crypto_sexp (GckSexpKey *base, GckSession *sess
/* Find an credential, with an unlocked copy */
else
- gck_session_for_each_credential (session, GCK_OBJECT (self),
- acquire_from_credential, &sexp);
+ gck_credential_for_each (session, GCK_OBJECT (self),
+ acquire_from_credential, &sexp);
return sexp;
}
@@ -368,9 +365,7 @@ gck_private_xsa_key_set_locked_private (GckPrivateXsaKey *self, GckCredential *c
g_return_if_fail (GCK_IS_PRIVATE_XSA_KEY (self));
g_return_if_fail (GCK_IS_CREDENTIAL (cred));
g_return_if_fail (gck_credential_get_object (cred) == GCK_OBJECT (self));
- if (sexp != NULL)
- gck_sexp_ref (sexp);
- gck_credential_set_data (cred, sexp, gck_sexp_unref);
+ gck_credential_set_data (cred, GCK_BOXED_SEXP, sexp);
}
GckSexp*
diff --git a/pkcs11/gck/gck-session.c b/pkcs11/gck/gck-session.c
index fee6766..8b280ec 100644
--- a/pkcs11/gck/gck-session.c
+++ b/pkcs11/gck/gck-session.c
@@ -756,62 +756,11 @@ gck_session_destroy_session_object (GckSession *self, GckTransaction *transactio
remove_object (self, transaction, obj);
}
-gboolean
-gck_session_for_each_credential (GckSession *self, GckObject *object,
- GckCredentialFunc func, gpointer user_data)
+GckCredential*
+gck_session_get_credential (GckSession *self)
{
- CK_OBJECT_HANDLE handle;
- CK_OBJECT_CLASS klass;
- CK_ATTRIBUTE attrs[2];
- GList *results, *l;
-
- g_return_val_if_fail (GCK_IS_SESSION (self), FALSE);
- g_return_val_if_fail (GCK_IS_OBJECT (object), FALSE);
- g_return_val_if_fail (func, FALSE);
-
- /* Do we have one right on the session */
- if (self->pv->credential != NULL &&
- gck_credential_get_object (self->pv->credential) == object) {
- if ((func) (self->pv->credential, object, user_data))
- return TRUE;
- }
-
- klass = CKO_G_CREDENTIAL;
- attrs[0].type = CKA_CLASS;
- attrs[0].pValue = &klass;
- attrs[0].ulValueLen = sizeof (klass);
-
- handle = gck_object_get_handle (object);
- attrs[1].type = CKA_G_OBJECT;
- attrs[1].pValue = &handle;
- attrs[1].ulValueLen = sizeof (handle);
-
- /* Find any on the session */
- results = gck_manager_find_by_attributes (self->pv->manager,
- attrs, G_N_ELEMENTS (attrs));
-
- for (l = results; l; l = g_list_next (l)) {
- if ((func) (l->data, object, user_data))
- break;
- }
-
- g_list_free (results);
-
- if (l != NULL)
- return TRUE;
-
- /* Find any in the token */
- results = gck_manager_find_by_attributes (gck_module_get_manager (self->pv->module),
- attrs, G_N_ELEMENTS (attrs));
-
- for (l = results; l; l = g_list_next (l)) {
- if ((func) (l->data, object, user_data))
- break;
- }
-
- g_list_free (results);
-
- return (l != NULL);
+ g_return_val_if_fail (GCK_IS_SESSION (self), NULL);
+ return self->pv->credential;
}
GckObject*
diff --git a/pkcs11/gck/gck-session.h b/pkcs11/gck/gck-session.h
index 348c312..290443d 100644
--- a/pkcs11/gck/gck-session.h
+++ b/pkcs11/gck/gck-session.h
@@ -52,10 +52,6 @@ struct _GckSessionClass {
#endif
};
-typedef gboolean (*GckCredentialFunc) (GckCredential *cred,
- GckObject *object,
- gpointer user_data);
-
GType gck_session_get_type (void);
GckSession* gck_session_for_session_object (GckObject *obj);
@@ -85,6 +81,8 @@ void gck_session_set_crypto_state (GckSess
gpointer state,
GDestroyNotify destroy);
+GckCredential* gck_session_get_credential (GckSession *self);
+
CK_RV gck_session_lookup_readable_object (GckSession *self,
CK_OBJECT_HANDLE handle,
GckObject **result);
@@ -105,11 +103,6 @@ void gck_session_destroy_session_object (GckSess
GckTransaction *transaction,
GckObject *obj);
-gboolean gck_session_for_each_credential (GckSession *self,
- GckObject *object,
- GckCredentialFunc func,
- gpointer user_data);
-
GckObject* gck_session_create_object_for_factory (GckSession *self,
GckFactory *factory,
GckTransaction *transaction,
diff --git a/pkcs11/gck/gck-timer.c b/pkcs11/gck/gck-timer.c
index 4776c3b..999670b 100644
--- a/pkcs11/gck/gck-timer.c
+++ b/pkcs11/gck/gck-timer.c
@@ -157,15 +157,18 @@ gck_timer_shutdown (void)
GMutex* _gck_module_get_scary_mutex_that_you_should_not_touch (GckModule *self);
GckTimer*
-gck_timer_start (GckModule *module, glong when, GckTimerFunc callback, gpointer user_data)
+gck_timer_start (GckModule *module, glong seconds, GckTimerFunc callback, gpointer user_data)
{
GckTimer *timer;
+ GTimeVal tv;
g_return_val_if_fail (callback, NULL);
g_return_val_if_fail (timer_queue, NULL);
+ g_get_current_time (&tv);
+
timer = g_slice_new (GckTimer);
- timer->when = when;
+ timer->when = seconds + tv.tv_sec;
timer->callback = callback;
timer->user_data = user_data;
diff --git a/pkcs11/gck/gck-timer.h b/pkcs11/gck/gck-timer.h
index 14fdf93..170db4e 100644
--- a/pkcs11/gck/gck-timer.h
+++ b/pkcs11/gck/gck-timer.h
@@ -30,7 +30,7 @@ typedef void (*GckTimerFunc) (GckTimer *timer,
gpointer user_data);
GckTimer* gck_timer_start (GckModule *module,
- glong when,
+ glong seconds,
GckTimerFunc func,
gpointer user_data);
diff --git a/pkcs11/gck/tests/unit-test-credential.c b/pkcs11/gck/tests/unit-test-credential.c
index 6601339..0e1d9ff 100644
--- a/pkcs11/gck/tests/unit-test-credential.c
+++ b/pkcs11/gck/tests/unit-test-credential.c
@@ -32,7 +32,7 @@
#include "gck/gck-session.h"
#include "gck/gck-module.h"
-#include "pkcs11g.h"
+#include "pkcs11i.h"
static GckModule *module = NULL;
static GckSession *session = NULL;
@@ -174,40 +174,6 @@ DEFINE_TEST(credential_get_attributes)
g_assert (rv == CKR_OK);
g_assert (check.ulValueLen == sizeof (value));
g_assert (value == locked);
-
- check.type = CKA_G_USES_REMAINING;
- check.pValue = &value;
- check.ulValueLen = sizeof (value);
-
- rv = gck_session_C_GetAttributeValue (session, handle, &check, 1);
- g_assert (rv == CKR_OK);
- g_assert (check.ulValueLen == sizeof (value));
- g_assert (value == (CK_ULONG)-1);
-}
-
-DEFINE_TEST(credential_uses_property)
-{
- GckCredential *auth;
- gint uses;
- CK_RV rv;
-
- rv = gck_credential_create (module, NULL, object, (guchar*)"mock", 4, &auth);
- g_assert (rv == CKR_OK);
- g_assert (auth);
-
- g_object_get (auth, "uses-remaining", &uses, NULL);
- g_assert (uses == -1);
-
- gck_credential_set_uses_remaining (auth, 5);
-
- uses = gck_credential_get_uses_remaining (auth);
- g_assert (uses == 5);
-
- gck_credential_throw_away_one_use (auth);
- uses = gck_credential_get_uses_remaining (auth);
- g_assert (uses == 4);
-
- g_object_unref (auth);
}
DEFINE_TEST(credential_object_property)
@@ -262,26 +228,43 @@ DEFINE_TEST(credential_login_property)
g_object_unref (cred);
}
+static GType
+boxed_string (void)
+{
+ static GType type = 0;
+ if (!type)
+ type = g_boxed_type_register_static ("TestBoxedString",
+ (GBoxedCopyFunc)g_strdup,
+ (GBoxedFreeFunc)g_free);
+ return type;
+}
+
DEFINE_TEST(credential_data)
{
GckCredential *cred;
+ GType type = boxed_string ();
+ gchar *check;
CK_RV rv;
rv = gck_credential_create (module, NULL, object, (guchar*)"mock", 4, &cred);
g_assert (rv == CKR_OK);
g_assert (cred);
- g_assert (gck_credential_get_data (cred) == NULL);
+ g_assert (gck_credential_peek_data (cred, type) == NULL);
+
+ gck_credential_set_data (cred, type, "one");
- gck_credential_set_data (cred, g_strdup ("one"), g_free);
+ check = gck_credential_pop_data (cred, type);
+ g_assert_cmpstr ("one", ==, check);
+ g_free (check);
- g_assert_cmpstr ("one", ==, gck_credential_get_data (cred));
+ g_assert_cmpstr ("one", ==, gck_credential_peek_data (cred, type));
- gck_credential_set_data (cred, g_strdup ("ONE"), g_free);
- g_assert_cmpstr ("ONE", ==, gck_credential_get_data (cred));
+ gck_credential_set_data (cred, type, "ONE");
+ g_assert_cmpstr ("ONE", ==, gck_credential_peek_data (cred, type));
- gck_credential_set_data (cred, NULL, NULL);
- g_assert (gck_credential_get_data (cred) == NULL);
+ gck_credential_set_data (cred, 0, NULL);
+ g_assert (gck_credential_peek_data (cred, 0) == NULL);
g_object_unref (cred);
}
diff --git a/pkcs11/gck/tests/unit-test-object.c b/pkcs11/gck/tests/unit-test-object.c
index ee1dea1..fd16dd0 100644
--- a/pkcs11/gck/tests/unit-test-object.c
+++ b/pkcs11/gck/tests/unit-test-object.c
@@ -30,7 +30,7 @@
#include "gck/gck-module.h"
#include "gck/gck-transaction.h"
-#include "pkcs11g.h"
+#include "pkcs11i.h"
static GckModule *module = NULL;
static GckSession *session = NULL;
@@ -157,12 +157,12 @@ DEFINE_TEST(object_create_auto_destruct)
CK_BBOOL token = CK_FALSE;
CK_OBJECT_CLASS klass = CKO_CERTIFICATE;
CK_CERTIFICATE_TYPE type = CKC_X_509;
- gchar lifetime[16];
- gchar check[16];
-
+ CK_ULONG lifetime = 2;
+ CK_ULONG check;
+
CK_ATTRIBUTE attrs[] = {
- { CKA_GNOME_AUTO_DESTRUCT, lifetime, sizeof (lifetime) },
- { CKA_TOKEN, &token, sizeof (token) },
+ { CKA_G_DESTRUCT_AFTER, &lifetime, sizeof (lifetime) },
+ { CKA_TOKEN, &token, sizeof (token) },
{ CKA_CLASS, &klass, sizeof (klass) },
{ CKA_CERTIFICATE_TYPE, &type, sizeof (type) },
{ CKA_VALUE, certificate_data, certificate_n_data },
@@ -171,19 +171,13 @@ DEFINE_TEST(object_create_auto_destruct)
CK_BBOOL transient;
CK_ATTRIBUTE lookups[] = {
- { CKA_GNOME_AUTO_DESTRUCT, check, sizeof (check) },
+ { CKA_G_DESTRUCT_AFTER, &check, sizeof (check) },
{ CKA_GNOME_TRANSIENT, &transient, sizeof (transient) }
};
CK_OBJECT_HANDLE handle;
- GTimeVal tv;
CK_RV rv;
-
- /* Fill in the special attribute */
- g_get_current_time (&tv);
- rv = gck_attribute_set_time (&attrs[0], tv.tv_sec + 2);
- g_assert (rv == CKR_OK);
-
+
rv = gck_session_C_CreateObject (session, attrs, G_N_ELEMENTS (attrs), &handle);
g_assert (rv == CKR_OK);
g_assert (handle != 0);
@@ -194,7 +188,7 @@ DEFINE_TEST(object_create_auto_destruct)
rv = gck_session_C_GetAttributeValue (session, handle, lookups, G_N_ELEMENTS (lookups));
g_assert (rv == CKR_OK);
g_assert (transient == TRUE);
- g_assert (memcmp (lifetime, check, 16) == 0);
+ g_assert (memcmp (&lifetime, &check, sizeof (lifetime)) == 0);
test_module_leave ();
test_mainloop_run (2200);
@@ -207,10 +201,11 @@ DEFINE_TEST(object_create_auto_destruct_not_transient)
{
CK_OBJECT_CLASS klass = CKO_CERTIFICATE;
CK_CERTIFICATE_TYPE type = CKC_X_509;
- CK_BBOOL transient = CK_FALSE;
-
+ CK_BBOOL transient = CK_FALSE;
+ CK_ULONG after = 1;
+
CK_ATTRIBUTE attrs[] = {
- { CKA_GNOME_AUTO_DESTRUCT, "1999010101010100", 16 },
+ { CKA_G_DESTRUCT_AFTER, &after, sizeof (after) },
{ CKA_GNOME_TRANSIENT, &transient, sizeof (transient) },
{ CKA_CLASS, &klass, sizeof (klass) },
{ CKA_CERTIFICATE_TYPE, &type, sizeof (type) },
@@ -225,26 +220,6 @@ DEFINE_TEST(object_create_auto_destruct_not_transient)
g_assert (rv == CKR_TEMPLATE_INCONSISTENT);
}
-DEFINE_TEST(object_create_auto_destruct_bad_value)
-{
- CK_OBJECT_CLASS klass = CKO_CERTIFICATE;
- CK_CERTIFICATE_TYPE type = CKC_X_509;
-
- CK_ATTRIBUTE attrs[] = {
- { CKA_GNOME_AUTO_DESTRUCT, "1999", 4 },
- { CKA_CLASS, &klass, sizeof (klass) },
- { CKA_CERTIFICATE_TYPE, &type, sizeof (type) },
- { CKA_VALUE, certificate_data, certificate_n_data },
- };
-
- CK_OBJECT_HANDLE handle;
- CK_RV rv;
-
- /* Can't have a non-transient object that auto-destructs */
- 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;
diff --git a/pkcs11/gck/tests/unit-test-timer.c b/pkcs11/gck/tests/unit-test-timer.c
index f9b42cf..ac50b62 100644
--- a/pkcs11/gck/tests/unit-test-timer.c
+++ b/pkcs11/gck/tests/unit-test-timer.c
@@ -55,12 +55,10 @@ timer_callback (GckTimer *timer, gpointer user_data)
DEFINE_TEST(timer_simple)
{
- GTimeVal tv;
GckTimer *timer;
-
- g_get_current_time (&tv);
- timer = gck_timer_start (module, tv.tv_sec + 2, timer_callback, &timer);
-
+
+ timer = gck_timer_start (module, 2, timer_callback, &timer);
+
test_module_leave ();
test_mainloop_run (2200);
test_module_enter ();
@@ -70,12 +68,10 @@ DEFINE_TEST(timer_simple)
DEFINE_TEST(timer_cancel)
{
- GTimeVal tv;
GckTimer *timer;
-
- g_get_current_time (&tv);
- timer = gck_timer_start (module, tv.tv_sec + 2, timer_callback, &timer);
-
+
+ timer = gck_timer_start (module, 2, timer_callback, &timer);
+
test_module_leave ();
test_mainloop_run (500);
test_module_enter ();
@@ -92,13 +88,11 @@ DEFINE_TEST(timer_cancel)
DEFINE_TEST(timer_immediate)
{
- GTimeVal tv;
GckTimer *timer;
-
+
/* Setup timer in the past, should execute as soon as possible */
- g_get_current_time (&tv);
- timer = gck_timer_start (module, tv.tv_sec - 5, timer_callback, &timer);
-
+ timer = gck_timer_start (module, -5, timer_callback, &timer);
+
/* Should not be called immediately */
g_assert (timer != NULL);
@@ -126,16 +120,13 @@ multiple_callback (GckTimer *timer, gpointer user_data)
DEFINE_TEST(timer_multiple)
{
- GTimeVal tv;
-
timer_check = 0;
- g_get_current_time (&tv);
-
+
/* Multiple timers, add out of order, should be called in order */
- gck_timer_start (module, tv.tv_sec + 1, multiple_callback, GINT_TO_POINTER (1));
- gck_timer_start (module, tv.tv_sec + 3, multiple_callback, GINT_TO_POINTER (3));
- gck_timer_start (module, tv.tv_sec + 2, multiple_callback, GINT_TO_POINTER (2));
- gck_timer_start (module, tv.tv_sec + 0, multiple_callback, GINT_TO_POINTER (0));
+ gck_timer_start (module, 1, multiple_callback, GINT_TO_POINTER (1));
+ gck_timer_start (module, 3, multiple_callback, GINT_TO_POINTER (3));
+ gck_timer_start (module, 2, multiple_callback, GINT_TO_POINTER (2));
+ gck_timer_start (module, 0, multiple_callback, GINT_TO_POINTER (0));
test_module_leave ();
test_mainloop_run (3500);
@@ -146,12 +137,8 @@ DEFINE_TEST(timer_multiple)
DEFINE_TEST(timer_outstanding)
{
- GTimeVal tv;
-
- g_get_current_time (&tv);
-
/* A timer that can't be called */
- gck_timer_start (module, tv.tv_sec + 5, timer_callback, NULL);
- gck_timer_start (module, tv.tv_sec + 10, timer_callback, NULL);
- gck_timer_start (module, tv.tv_sec + 1, timer_callback, NULL);
+ gck_timer_start (module, 5, timer_callback, NULL);
+ gck_timer_start (module, 10, timer_callback, NULL);
+ gck_timer_start (module, 1, timer_callback, NULL);
}
diff --git a/pkcs11/pkcs11g.h b/pkcs11/pkcs11g.h
index a84e7d9..f9f0ffc 100644
--- a/pkcs11/pkcs11g.h
+++ b/pkcs11/pkcs11g.h
@@ -90,23 +90,8 @@
#define CKA_GNOME_PURPOSE_TIME_STAMPING (CKA_GNOME + 109)
/* -------------------------------------------------------------------
- * AUTO-DESTRUCT
*/
-#define CKA_GNOME_AUTO_DESTRUCT (CKA_GNOME + 200)
-
#define CKA_GNOME_TRANSIENT (CKA_GNOME + 201)
-/* -------------------------------------------------------------------
- * CREDENTIAL
- */
-
-#define CKO_G_CREDENTIAL (CKO_GNOME + 100)
-
-#define CKA_G_OBJECT (CKA_GNOME + 202)
-
-#define CKA_G_USES_REMAINING (CKA_GNOME + 203)
-
-#define CKA_G_CREDENTIAL (CKA_GNOME + 204)
-
#endif /* PKCS11G_H */
diff --git a/pkcs11/pkcs11i.h b/pkcs11/pkcs11i.h
index a32e4f9..08337f1 100644
--- a/pkcs11/pkcs11i.h
+++ b/pkcs11/pkcs11i.h
@@ -95,4 +95,26 @@ typedef CK_G_APPLICATION* CK_G_APPLICATION_PTR;
#define CKK_G_NULL (CKK_GNOME + 100)
+/* -------------------------------------------------------------------
+ * AUTO DESTRUCT
+ */
+
+#define CKA_G_DESTRUCT_IDLE (CKA_GNOME + 190)
+
+#define CKA_G_DESTRUCT_AFTER (CKA_GNOME + 191)
+
+#define CKA_G_DESTRUCT_USES (CKA_GNOME + 192)
+
+/* -------------------------------------------------------------------
+ * CREDENTIAL
+ */
+
+#define CKO_G_CREDENTIAL (CKO_GNOME + 100)
+
+#define CKA_G_OBJECT (CKA_GNOME + 202)
+
+#define CKA_G_CREDENTIAL (CKA_GNOME + 204)
+
+#define CKA_G_CREDENTIAL_TEMPLATE (CKA_GNOME + 205)
+
#endif /* PKCS11I_H */
diff --git a/pkcs11/secret-store/gck-secret-binary.c b/pkcs11/secret-store/gck-secret-binary.c
index 6e68594..d8fa13f 100644
--- a/pkcs11/secret-store/gck-secret-binary.c
+++ b/pkcs11/secret-store/gck-secret-binary.c
@@ -587,19 +587,19 @@ gck_secret_binary_write (GckSecretCollection *collection, GckSecretData *sdata,
egg_buffer_append (&buffer, (guchar*)KEYRING_FILE_HEADER, KEYRING_FILE_HEADER_LEN);
egg_buffer_add_byte (&buffer, 0); /* Major version */
egg_buffer_add_byte (&buffer, 0); /* Minor version */
- egg_buffer_add_byte (&buffer, 0); /* crypto (0 == AEL) */
+ egg_buffer_add_byte (&buffer, 0); /* crypto (0 == AES) */
egg_buffer_add_byte (&buffer, 0); /* hash (0 == MD5) */
buffer_add_utf8_string (&buffer, gck_secret_object_get_label (obj));
buffer_add_time (&buffer, gck_secret_object_get_modified (obj));
buffer_add_time (&buffer, gck_secret_object_get_created (obj));
-
+
flags = 0;
- if (g_object_get_data (G_OBJECT (collection), "lock-on-idle"))
- flags |= 1;
+ lock_timeout = gck_secret_collection_get_lock_idle (collection);
+ if (lock_timeout)
+ flags |= LOCK_ON_IDLE_FLAG;
egg_buffer_add_uint32 (&buffer, flags);
-
- lock_timeout = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (collection), "lock-on-idle"));
+
egg_buffer_add_uint32 (&buffer, lock_timeout);
egg_buffer_add_uint32 (&buffer, hash_iterations);
egg_buffer_append (&buffer, salt, 8);
@@ -939,8 +939,9 @@ gck_secret_binary_read (GckSecretCollection *collection, GckSecretData *sdata,
gck_secret_object_set_label (obj, display_name);
gck_secret_object_set_modified (obj, mtime);
gck_secret_object_set_created (obj, ctime);
- g_object_set_data (G_OBJECT (collection), "lock-on-idle", GINT_TO_POINTER (!!(flags & LOCK_ON_IDLE_FLAG)));
- g_object_set_data (G_OBJECT (collection), "lock-timeout", GINT_TO_POINTER (lock_timeout));
+ if (!(flags & LOCK_ON_IDLE_FLAG))
+ lock_timeout = 0;
+ gck_secret_collection_set_lock_idle (collection, lock_timeout);
/* Build a Hash table where we can track ids we haven't yet seen */
checks = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
diff --git a/pkcs11/secret-store/gck-secret-collection.c b/pkcs11/secret-store/gck-secret-collection.c
index 23fc457..d418ab1 100644
--- a/pkcs11/secret-store/gck-secret-collection.c
+++ b/pkcs11/secret-store/gck-secret-collection.c
@@ -48,6 +48,11 @@ struct _GckSecretCollection {
GHashTable *items;
gchar *filename;
guint32 watermark;
+
+ /* Template for credential */
+ CK_ATTRIBUTE tp_attrs[2];
+ CK_ULONG tp_idle;
+ CK_BBOOL tp_token;
};
G_DEFINE_TYPE (GckSecretCollection, gck_secret_collection, GCK_TYPE_SECRET_OBJECT);
@@ -108,7 +113,7 @@ find_unlocked_credential (GckCredential *cred, GckObject *object, gpointer user_
g_return_val_if_fail (!*result, FALSE);
- if (gck_credential_get_data (cred)) {
+ if (gck_credential_peek_data (cred, GCK_TYPE_SECRET_DATA)) {
*result = gck_object_get_handle (GCK_OBJECT (cred));
return TRUE;
}
@@ -121,14 +126,12 @@ find_unlocked_secret_data (GckCredential *cred, GckObject *object, gpointer user
{
GckSecretCollection *self = GCK_SECRET_COLLECTION (object);
GckSecretData **result = user_data;
- GckSecretData *sdata;
g_return_val_if_fail (!*result, FALSE);
- sdata = gck_credential_get_data (cred);
- if (sdata) {
- g_return_val_if_fail (sdata == self->sdata, FALSE);
- *result = sdata;
+ *result = gck_credential_pop_data (cred, GCK_TYPE_SECRET_DATA);
+ if (*result) {
+ g_return_val_if_fail (*result == self->sdata, FALSE);
return TRUE;
}
@@ -292,9 +295,10 @@ factory_create_collection (GckSession *session, GckTransaction *transaction,
gck_credential_connect (cred, GCK_OBJECT (collection));
sdata = g_object_new (GCK_TYPE_SECRET_DATA, NULL);
- gck_credential_set_data (cred, sdata, g_object_unref);
+ gck_credential_set_data (cred, GCK_TYPE_SECRET_DATA, sdata);
gck_secret_data_set_master (sdata, gck_credential_get_secret (cred));
track_secret_data (collection, sdata);
+ g_object_unref (sdata);
gck_session_complete_object_creation (session, transaction, GCK_OBJECT (collection), attrs, n_attrs);
return GCK_OBJECT (collection);
@@ -335,7 +339,7 @@ change_master_password (GckSecretCollection *self, GckTransaction *transaction,
g_object_ref (previous);
gck_credential_connect (cred, GCK_OBJECT (self));
- gck_credential_set_data (cred, g_object_ref (self->sdata), g_object_unref);
+ gck_credential_set_data (cred, GCK_TYPE_SECRET_DATA, self->sdata);
gck_secret_data_set_master (self->sdata, gck_credential_get_secret (cred));
gck_transaction_add (transaction, self, complete_master_password, previous);
@@ -349,15 +353,12 @@ static CK_RV
gck_secret_collection_get_attribute (GckObject *base, GckSession *session, CK_ATTRIBUTE_PTR attr)
{
GckSecretCollection *self = GCK_SECRET_COLLECTION (base);
- CK_OBJECT_HANDLE handle = 0;
switch (attr->type) {
case CKA_CLASS:
return gck_attribute_set_ulong (attr, CKO_G_COLLECTION);
- case CKA_G_CREDENTIAL:
- gck_session_for_each_credential (session, GCK_OBJECT (self),
- find_unlocked_credential, &handle);
- return gck_attribute_set_ulong (attr, handle);
+ case CKA_G_CREDENTIAL_TEMPLATE:
+ return gck_attribute_set_template (attr, self->tp_attrs, G_N_ELEMENTS (self->tp_attrs));
}
return GCK_OBJECT_CLASS (gck_secret_collection_parent_class)->get_attribute (base, session, attr);
}
@@ -373,8 +374,8 @@ gck_secret_collection_set_attribute (GckObject *object, GckSession *session,
switch (attr->type) {
case CKA_G_CREDENTIAL:
- gck_session_for_each_credential (session, GCK_OBJECT (self),
- find_unlocked_credential, &handle);
+ gck_credential_for_each (session, GCK_OBJECT (self),
+ find_unlocked_credential, &handle);
if (handle == 0)
return gck_transaction_fail (transaction, CKR_USER_NOT_LOGGED_IN);
rv = gck_attribute_get_ulong (attr, &handle);
@@ -397,6 +398,7 @@ gck_secret_collection_real_unlock (GckObject *obj, GckCredential *cred)
GckDataResult res;
GckSecretData *sdata;
GckSecret *master;
+ CK_RV rv;
master = gck_credential_get_secret (cred);
@@ -406,7 +408,7 @@ gck_secret_collection_real_unlock (GckObject *obj, GckCredential *cred)
return CKR_PIN_INCORRECT;
/* Credential now tracks our secret data */
- gck_credential_set_data (cred, g_object_ref (self->sdata), g_object_unref);
+ gck_credential_set_data (cred, GCK_TYPE_SECRET_DATA, self->sdata);
return CKR_OK;
}
@@ -428,23 +430,27 @@ gck_secret_collection_real_unlock (GckObject *obj, GckCredential *cred)
switch (res) {
case GCK_DATA_SUCCESS:
- gck_credential_set_data (cred, sdata, g_object_unref);
+ gck_credential_set_data (cred, GCK_TYPE_SECRET_DATA, sdata);
track_secret_data (self, sdata);
- return CKR_OK;
+ rv = CKR_OK;
+ break;
case GCK_DATA_LOCKED:
- g_object_unref (sdata);
- return CKR_PIN_INCORRECT;
+ rv = CKR_PIN_INCORRECT;
+ break;
case GCK_DATA_UNRECOGNIZED:
- g_object_unref (sdata);
g_message ("unrecognized or invalid keyring: %s", self->filename);
- return CKR_FUNCTION_FAILED;
+ rv = CKR_FUNCTION_FAILED;
+ break;
case GCK_DATA_FAILURE:
- g_object_unref (sdata);
g_message ("failed to read or parse keyring: %s", self->filename);
- return CKR_GENERAL_ERROR;
+ rv = CKR_GENERAL_ERROR;
+ break;
default:
g_assert_not_reached ();
}
+
+ g_object_unref (sdata);
+ return rv;
}
static void
@@ -458,15 +464,24 @@ static gboolean
gck_secret_collection_real_is_locked (GckSecretObject *obj, GckSession *session)
{
GckSecretCollection *self = GCK_SECRET_COLLECTION (obj);
- return gck_secret_collection_unlocked_data (self, session) ? FALSE : TRUE;
+ return gck_secret_collection_unlocked_have (self, session);
}
static void
gck_secret_collection_init (GckSecretCollection *self)
{
self->items = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
-}
+ self->tp_token = CK_FALSE;
+ self->tp_attrs[0].type = CKA_TOKEN;
+ self->tp_attrs[0].pValue = &self->tp_token;
+ self->tp_attrs[0].ulValueLen = sizeof (self->tp_token);
+
+ self->tp_idle = 0;
+ self->tp_attrs[1].type = CKA_G_DESTRUCT_IDLE;
+ self->tp_attrs[1].pValue = &self->tp_idle;
+ self->tp_attrs[1].ulValueLen = sizeof (self->tp_idle);
+}
static void
gck_secret_collection_set_property (GObject *obj, guint prop_id, const GValue *value,
@@ -727,8 +742,26 @@ gck_secret_collection_destroy_item (GckSecretCollection *self, GckTransaction *t
remove_item (self, transaction, item);
}
+gboolean
+gck_secret_collection_unlocked_have (GckSecretCollection *self, GckSession *session)
+{
+ CK_OBJECT_HANDLE handle = 0;
+
+ g_return_val_if_fail (GCK_IS_SECRET_COLLECTION (self), FALSE);
+ g_return_val_if_fail (GCK_IS_SESSION (session), FALSE);
+
+ /*
+ * Look for credential objects that this session has access
+ * to, and use those to find the secret data. If a secret data is
+ * found, it should match the one we are tracking in self->sdata.
+ */
+
+ gck_credential_for_each (session, GCK_OBJECT (self), find_unlocked_credential, &handle);
+ return handle != 0;
+}
+
GckSecretData*
-gck_secret_collection_unlocked_data (GckSecretCollection *self, GckSession *session)
+gck_secret_collection_unlocked_use (GckSecretCollection *self, GckSession *session)
{
GckSecretData *sdata = NULL;
@@ -741,8 +774,8 @@ gck_secret_collection_unlocked_data (GckSecretCollection *self, GckSession *sess
* found, it should match the one we are tracking in self->sdata.
*/
- gck_session_for_each_credential (session, GCK_OBJECT (self),
- find_unlocked_secret_data, &sdata);
+ gck_credential_for_each (session, GCK_OBJECT (self),
+ find_unlocked_secret_data, &sdata);
return sdata;
}
@@ -827,3 +860,19 @@ gck_secret_collection_destroy (GckSecretCollection *self, GckTransaction *transa
if (self->filename)
gck_transaction_remove_file (transaction, self->filename);
}
+
+gint
+gck_secret_collection_get_lock_idle (GckSecretCollection *self)
+{
+ g_return_val_if_fail (GCK_IS_SECRET_COLLECTION (self), 0);
+ return (gint)self->tp_idle;
+}
+
+void
+gck_secret_collection_set_lock_idle (GckSecretCollection *self, gint lock_timeout)
+{
+ g_return_if_fail (GCK_IS_SECRET_COLLECTION (self));
+ if (lock_timeout < 0)
+ lock_timeout = 0;
+ self->tp_idle = (CK_ULONG)lock_timeout;
+}
diff --git a/pkcs11/secret-store/gck-secret-collection.h b/pkcs11/secret-store/gck-secret-collection.h
index 98d9cf5..e0a8e57 100644
--- a/pkcs11/secret-store/gck-secret-collection.h
+++ b/pkcs11/secret-store/gck-secret-collection.h
@@ -85,7 +85,15 @@ void gck_secret_collection_destroy_item (GckSecretCollection
void gck_secret_collection_unlocked_clear (GckSecretCollection *self);
-GckSecretData* gck_secret_collection_unlocked_data (GckSecretCollection *self,
+GckSecretData* gck_secret_collection_unlocked_use (GckSecretCollection *self,
GckSession *session);
+gboolean gck_secret_collection_unlocked_have (GckSecretCollection *self,
+ GckSession *session);
+
+gint gck_secret_collection_get_lock_idle (GckSecretCollection *self);
+
+void gck_secret_collection_set_lock_idle (GckSecretCollection *self,
+ gint lock_timeout);
+
#endif /* __GCK_SECRET_COLLECTION_H__ */
diff --git a/pkcs11/secret-store/gck-secret-item.c b/pkcs11/secret-store/gck-secret-item.c
index a6605d8..b0c5659 100644
--- a/pkcs11/secret-store/gck-secret-item.c
+++ b/pkcs11/secret-store/gck-secret-item.c
@@ -207,6 +207,7 @@ gck_secret_item_real_get_attribute (GckObject *base, GckSession *session, CK_ATT
const gchar *identifier;
const guchar *secret;
gsize n_secret = 0;
+ CK_RV rv;
g_return_val_if_fail (self->collection, CKR_GENERAL_ERROR);
@@ -215,12 +216,14 @@ gck_secret_item_real_get_attribute (GckObject *base, GckSession *session, CK_ATT
return gck_attribute_set_ulong (attr, CKO_SECRET_KEY);
case CKA_VALUE:
- sdata = gck_secret_collection_unlocked_data (self->collection, session);
+ sdata = gck_secret_collection_unlocked_use (self->collection, session);
if (sdata == NULL)
return CKR_USER_NOT_LOGGED_IN;
identifier = gck_secret_object_get_identifier (GCK_SECRET_OBJECT (self));
secret = gck_secret_data_get_raw (sdata, identifier, &n_secret);
- return gck_attribute_set_data (attr, secret, n_secret);
+ rv = gck_attribute_set_data (attr, secret, n_secret);
+ g_object_unref (sdata);
+ return rv;
case CKA_G_COLLECTION:
g_return_val_if_fail (self->collection, CKR_GENERAL_ERROR);
@@ -257,18 +260,20 @@ gck_secret_item_real_set_attribute (GckObject *base, GckSession *session,
}
/* Check that the object is not locked */
- sdata = gck_secret_collection_unlocked_data (self->collection, session);
- if (sdata == NULL) {
+ if (!gck_secret_collection_unlocked_have (self->collection, session)) {
gck_transaction_fail (transaction, CKR_USER_NOT_LOGGED_IN);
return;
}
switch (attr->type) {
case CKA_VALUE:
+ sdata = gck_secret_collection_unlocked_use (self->collection, session);
+ g_return_if_fail (sdata);
identifier = gck_secret_object_get_identifier (GCK_SECRET_OBJECT (self));
secret = gck_secret_new (attr->pValue, attr->ulValueLen);
gck_secret_data_set_transacted (sdata, transaction, identifier, secret);
g_object_unref (secret);
+ g_object_unref (sdata);
if (!gck_transaction_get_failed (transaction))
gck_transaction_add (transaction, self, complete_set_secret, NULL);
return;
diff --git a/pkcs11/secret-store/gck-secret-textual.c b/pkcs11/secret-store/gck-secret-textual.c
index 029e46a..6c4e7d1 100644
--- a/pkcs11/secret-store/gck-secret-textual.c
+++ b/pkcs11/secret-store/gck-secret-textual.c
@@ -390,7 +390,6 @@ gck_secret_textual_write (GckSecretCollection *collection, GckSecretData *sdata,
const gchar *value;
GKeyFile *file;
GError *err = NULL;
- gboolean idle_lock;
gint idle_timeout;
g_return_val_if_fail (GCK_IS_SECRET_COLLECTION (collection), GCK_DATA_FAILURE);
@@ -408,8 +407,8 @@ gck_secret_textual_write (GckSecretCollection *collection, GckSecretData *sdata,
key_file_set_uint64 (file, "keyring", "mtime", gck_secret_object_get_modified (obj));
/* Not currently used :( */
- idle_lock = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (collection), "lock-on-idle"));
- g_key_file_set_boolean (file, "keyring", "lock-on-idle", idle_lock);
+ idle_timeout = gck_secret_collection_get_lock_idle (collection);
+ g_key_file_set_boolean (file, "keyring", "lock-on-idle", idle_timeout > 0);
idle_timeout = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (collection), "lock-timeout"));
g_key_file_set_integer (file, "keyring", "lock-timeout", idle_timeout);
diff --git a/pkcs11/secret-store/tests/unit-test-secret-collection.c b/pkcs11/secret-store/tests/unit-test-secret-collection.c
index 9c8136c..0a77d28 100644
--- a/pkcs11/secret-store/tests/unit-test-secret-collection.c
+++ b/pkcs11/secret-store/tests/unit-test-secret-collection.c
@@ -115,9 +115,10 @@ DEFINE_TEST(secret_collection_unlocked_data)
g_object_unref (cred);
/* Collection should now be unlocked */
- sdata = gck_secret_collection_unlocked_data (collection, session);
+ sdata = gck_secret_collection_unlocked_use (collection, session);
g_assert (GCK_IS_SECRET_DATA (sdata));
g_assert (!gck_secret_object_is_locked (GCK_SECRET_OBJECT (collection), session));
+ g_object_unref (sdata);
}
DEFINE_TEST(secret_collection_get_filename)
@@ -177,9 +178,10 @@ DEFINE_TEST(secret_collection_load_unlock_plain)
gck_session_add_session_object (session, NULL, GCK_OBJECT (cred));
g_object_unref (cred);
- sdata = gck_secret_collection_unlocked_data (collection, session);
+ sdata = gck_secret_collection_unlocked_use (collection, session);
g_assert (sdata != NULL && GCK_IS_SECRET_DATA (sdata));
test_secret_collection_validate (collection, sdata);
+ g_object_unref (sdata);
}
DEFINE_TEST(secret_collection_load_unlock_encrypted)
@@ -205,9 +207,10 @@ DEFINE_TEST(secret_collection_load_unlock_encrypted)
gck_session_add_session_object (session, NULL, GCK_OBJECT (cred));
g_object_unref (cred);
- sdata = gck_secret_collection_unlocked_data (collection, session);
+ sdata = gck_secret_collection_unlocked_use (collection, session);
g_assert (sdata != NULL && GCK_IS_SECRET_DATA (sdata));
test_secret_collection_validate (collection, sdata);
+ g_object_unref (sdata);
}
DEFINE_TEST(secret_collection_load_unlock_bad_password)
@@ -249,9 +252,10 @@ DEFINE_TEST(secret_collection_unlock_without_load)
gck_session_add_session_object (session, NULL, GCK_OBJECT (cred));
g_object_unref (cred);
- sdata = gck_secret_collection_unlocked_data (collection, session);
+ sdata = gck_secret_collection_unlocked_use (collection, session);
g_assert (sdata != NULL && GCK_IS_SECRET_DATA (sdata));
test_secret_collection_validate (collection, sdata);
+ g_object_unref (sdata);
}
DEFINE_TEST(secret_collection_twice_unlock)
@@ -279,9 +283,10 @@ DEFINE_TEST(secret_collection_twice_unlock)
gck_session_add_session_object (session, NULL, GCK_OBJECT (cred));
g_object_unref (cred);
- sdata = gck_secret_collection_unlocked_data (collection, session);
+ sdata = gck_secret_collection_unlocked_use (collection, session);
g_assert (sdata != NULL && GCK_IS_SECRET_DATA (sdata));
test_secret_collection_validate (collection, sdata);
+ g_object_unref (sdata);
}
DEFINE_TEST(secret_collection_twice_unlock_bad_password)
@@ -307,9 +312,10 @@ DEFINE_TEST(secret_collection_twice_unlock_bad_password)
(guchar*)"wrong", 5, &cred);
g_assert (rv == CKR_PIN_INCORRECT);
- sdata = gck_secret_collection_unlocked_data (collection, session);
+ sdata = gck_secret_collection_unlocked_use (collection, session);
g_assert (sdata != NULL && GCK_IS_SECRET_DATA (sdata));
test_secret_collection_validate (collection, sdata);
+ g_object_unref (sdata);
}
DEFINE_TEST(secret_collection_memory_unlock)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]