[gnome-keyring] Implement collection storing lock on idle, and unlock timeout
- From: Stefan Walter <stefw src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [gnome-keyring] Implement collection storing lock on idle, and unlock timeout
- Date: Mon, 1 Feb 2010 02:33:13 +0000 (UTC)
commit dbfc7003c830761722eea7831db6ddcf6680eb50
Author: Stef Walter <stef memberwebs com>
Date: Mon Feb 1 02:27:10 2010 +0000
Implement collection storing lock on idle, and unlock timeout
pkcs11/gck/gck-attributes.c | 114 ++++++++++++++++++++++++---
pkcs11/gck/gck-attributes.h | 22 +++++-
pkcs11/gck/tests/unit-test-attributes.c | 49 ++++++++++++
pkcs11/secret-store/gck-secret-binary.c | 23 ++++--
pkcs11/secret-store/gck-secret-collection.c | 69 ++++++++++++-----
pkcs11/secret-store/gck-secret-collection.h | 5 +
pkcs11/secret-store/gck-secret-textual.c | 17 +++--
7 files changed, 254 insertions(+), 45 deletions(-)
---
diff --git a/pkcs11/gck/gck-attributes.c b/pkcs11/gck/gck-attributes.c
index 62465cd..b2c7c53 100644
--- a/pkcs11/gck/gck-attributes.c
+++ b/pkcs11/gck/gck-attributes.c
@@ -162,6 +162,25 @@ gck_attribute_get_mpi (CK_ATTRIBUTE_PTR attr, gcry_mpi_t *value)
return CKR_OK;
}
+CK_RV
+gck_attribute_get_template (CK_ATTRIBUTE_PTR attr, GArray **template)
+{
+ CK_ULONG n_attrs;
+
+ g_return_val_if_fail (attr, CKR_GENERAL_ERROR);
+ g_return_val_if_fail (attr, CKR_GENERAL_ERROR);
+
+ /* Validate everything first */
+ if (attr->ulValueLen % sizeof (CK_ATTRIBUTE) != 0)
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+
+ n_attrs = attr->ulValueLen / sizeof (CK_ATTRIBUTE);
+ if (n_attrs != 0 && !attr->pValue)
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+
+ *template = gck_template_new (attr->pValue, n_attrs);
+ return CKR_OK;
+}
CK_RV
gck_attribute_set_empty (CK_ATTRIBUTE_PTR attr)
@@ -288,10 +307,10 @@ 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)
+gck_attribute_set_template (CK_ATTRIBUTE_PTR attr, GArray *template)
{
CK_ATTRIBUTE_PTR array;
+ CK_ATTRIBUTE_PTR at;
CK_RV rv;
gulong len;
gulong i;
@@ -299,7 +318,7 @@ gck_attribute_set_template (CK_ATTRIBUTE_PTR attr, CK_ATTRIBUTE_PTR template,
g_assert (attr);
g_warn_if_fail ((attr->type & CKF_ARRAY_ATTRIBUTE) != 0);
- len = sizeof (CK_ATTRIBUTE) * n_template;
+ len = sizeof (CK_ATTRIBUTE) * template->len;
if (!attr->pValue) {
attr->ulValueLen = len;
return CKR_OK;
@@ -313,20 +332,21 @@ gck_attribute_set_template (CK_ATTRIBUTE_PTR attr, CK_ATTRIBUTE_PTR template,
rv = CKR_OK;
/* Start working with individual elements */
- for (i = 0; i < n_template; ++i) {
- array[i].type = template[i].type;
+ for (i = 0; i < template->len; ++i) {
+ at = &g_array_index (template, CK_ATTRIBUTE, i);
+ array[i].type = at->type;
if (!array[i].pValue) {
- array[i].ulValueLen = template[i].ulValueLen;
- } else if (array[i].ulValueLen < template[i].ulValueLen) {
+ array[i].ulValueLen = at->ulValueLen;
+ } else if (array[i].ulValueLen < at->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;
+ memcpy(array[i].pValue, at->pValue, at->ulValueLen);
+ array[i].ulValueLen = at->ulValueLen;
}
}
- return CKR_OK;
+ return rv;
}
gboolean
@@ -519,3 +539,77 @@ gck_attributes_find_string (CK_ATTRIBUTE_PTR attrs, CK_ULONG n_attrs,
return gck_attribute_get_string (attr, value) == CKR_OK;
}
+
+GArray*
+gck_template_new (CK_ATTRIBUTE_PTR attrs, CK_ULONG n_attrs)
+{
+ GArray *template = g_array_new (FALSE, FALSE, sizeof (CK_ATTRIBUTE));
+ CK_ATTRIBUTE_PTR pat;
+ gulong i;
+
+ g_return_val_if_fail (attrs || !n_attrs, NULL);
+
+ g_array_append_vals (template, attrs, n_attrs);
+ for (i = 0; i < n_attrs; ++i) {
+ pat = &g_array_index (template, CK_ATTRIBUTE, i);
+ if (pat->pValue)
+ pat->pValue = g_memdup (pat->pValue, pat->ulValueLen);
+ }
+
+ return template;
+}
+
+void
+gck_template_set (GArray *template, CK_ATTRIBUTE_PTR attr)
+{
+ CK_ATTRIBUTE_PTR pat;
+ CK_ATTRIBUTE at;
+ guint i;
+
+ g_return_if_fail (template);
+ g_return_if_fail (attr);
+
+ pat = gck_attributes_find ((CK_ATTRIBUTE_PTR)template->data, template->len, attr->type);
+
+ /* Remove any previous value */
+ for (i = 0; i < template->len; ++i) {
+ if (g_array_index (template, CK_ATTRIBUTE, i).type == attr->type) {
+ g_free (g_array_index (template, CK_ATTRIBUTE, i).pValue);
+ g_array_remove_index_fast (template, i);
+ break;
+ }
+ }
+
+ /* Add a new attribute */
+ memcpy (&at, attr, sizeof (at));
+ if (at.pValue)
+ at.pValue = g_memdup (at.pValue, at.ulValueLen);
+ g_array_append_vals (template, &at, 1);
+}
+
+void
+gck_template_free (GArray *template)
+{
+ guint i;
+
+ if (!template)
+ return;
+
+ for (i = 0; i < template->len; ++i)
+ g_free (g_array_index (template, CK_ATTRIBUTE, i).pValue);
+ g_array_free (template, TRUE);
+}
+
+gboolean
+gck_template_find_boolean (GArray *template, CK_ATTRIBUTE_TYPE type, gboolean *value)
+{
+ g_return_val_if_fail (template, FALSE);
+ return gck_attributes_find_boolean ((CK_ATTRIBUTE_PTR)template->data, template->len, type, value);
+}
+
+gboolean
+gck_template_find_ulong (GArray *template, CK_ATTRIBUTE_TYPE type, gulong *value)
+{
+ g_return_val_if_fail (template, FALSE);
+ return gck_attributes_find_ulong ((CK_ATTRIBUTE_PTR)template->data, template->len, type, value);
+}
diff --git a/pkcs11/gck/gck-attributes.h b/pkcs11/gck/gck-attributes.h
index 5e8bcb6..e392eab 100644
--- a/pkcs11/gck/gck-attributes.h
+++ b/pkcs11/gck/gck-attributes.h
@@ -43,6 +43,9 @@ CK_RV gck_attribute_get_string (CK_ATTRI
CK_RV gck_attribute_get_mpi (CK_ATTRIBUTE_PTR attr,
gcry_mpi_t *value);
+CK_RV gck_attribute_get_template (CK_ATTRIBUTE_PTR attr,
+ GArray **template);
+
CK_RV gck_attribute_set_empty (CK_ATTRIBUTE_PTR attr);
CK_RV gck_attribute_set_bool (CK_ATTRIBUTE_PTR attr,
@@ -68,8 +71,7 @@ CK_RV gck_attribute_set_mpi (CK_ATTRI
gcry_mpi_t mpi);
CK_RV gck_attribute_set_template (CK_ATTRIBUTE_PTR attr,
- CK_ATTRIBUTE_PTR template,
- CK_ULONG n_template);
+ GArray *template);
guint gck_attribute_hash (gconstpointer v);
@@ -113,4 +115,20 @@ gboolean gck_attributes_find_string (CK_ATTRI
CK_ATTRIBUTE_TYPE type,
gchar **value);
+GArray* gck_template_new (CK_ATTRIBUTE_PTR attrs,
+ CK_ULONG n_attrs);
+
+void gck_template_set (GArray *template,
+ CK_ATTRIBUTE_PTR attr);
+
+void gck_template_free (GArray *template);
+
+gboolean gck_template_find_boolean (GArray *template,
+ CK_ATTRIBUTE_TYPE type,
+ gboolean *value);
+
+gboolean gck_template_find_ulong (GArray *template,
+ CK_ATTRIBUTE_TYPE type,
+ gulong *value);
+
#endif /* GCK_ATTRIBUTE_H_ */
diff --git a/pkcs11/gck/tests/unit-test-attributes.c b/pkcs11/gck/tests/unit-test-attributes.c
index b1d4903..ed9cbb0 100644
--- a/pkcs11/gck/tests/unit-test-attributes.c
+++ b/pkcs11/gck/tests/unit-test-attributes.c
@@ -728,3 +728,52 @@ DEFINE_TEST(attributes_consume)
g_free (attrs);
}
+
+DEFINE_TEST(template_new_free)
+{
+ GArray *template = gck_template_new (attr_template, G_N_ELEMENTS (attr_template));
+ g_assert (template);
+ gck_template_free (template);
+}
+
+DEFINE_TEST(template_find)
+{
+ GArray *template = gck_template_new (attr_template, G_N_ELEMENTS (attr_template));
+ gulong uvalue;
+ gboolean ret, bvalue;
+
+ ret = gck_template_find_ulong (template, CKA_CLASS, &uvalue);
+ g_assert (ret);
+ g_assert (uvalue == attr_template_klass);
+
+ ret = gck_template_find_boolean (template, CKA_TOKEN, &bvalue);
+ g_assert (ret);
+ g_assert (bvalue == attr_template_token);
+
+ /* An invalid attribute */
+ ret = gck_template_find_boolean (template, CKA_AC_ISSUER, &bvalue);
+ g_assert (!ret);
+
+ gck_template_free (template);
+}
+
+DEFINE_TEST(template_set_replace)
+{
+ GArray *template = gck_template_new (attr_template, G_N_ELEMENTS (attr_template));
+ CK_OBJECT_CLASS klass = CKO_HW_FEATURE;
+ CK_ATTRIBUTE attr = { CKA_CLASS, &klass, sizeof (klass) };
+ gulong uvalue;
+
+ if (!gck_template_find_ulong (template, CKA_CLASS, &uvalue))
+ g_assert_not_reached ();
+ g_assert (uvalue == attr_template_klass);
+
+ /* Replace a previous attribute */
+ gck_template_set (template, &attr);
+
+ if (!gck_template_find_ulong (template, CKA_CLASS, &uvalue))
+ g_assert_not_reached ();
+ g_assert (uvalue == CKO_HW_FEATURE);
+
+ gck_template_free (template);
+}
diff --git a/pkcs11/secret-store/gck-secret-binary.c b/pkcs11/secret-store/gck-secret-binary.c
index d8fa13f..99a0085 100644
--- a/pkcs11/secret-store/gck-secret-binary.c
+++ b/pkcs11/secret-store/gck-secret-binary.c
@@ -56,7 +56,10 @@
* DECLARATIONS
*/
-#define LOCK_ON_IDLE_FLAG (1<<0)
+enum {
+ LOCK_ON_IDLE_FLAG = 1 << 0,
+ LOCK_AFTER_FLAG = 1 << 1
+};
typedef struct {
/* unencrypted: */
@@ -568,7 +571,7 @@ gck_secret_binary_write (GckSecretCollection *collection, GckSecretData *sdata,
gint hash_iterations;
gint lock_timeout;
guchar salt[8];
- guint flags;
+ guint flags = 0;
int i;
g_return_val_if_fail (GCK_IS_SECRET_COLLECTION (collection), GCK_DATA_FAILURE);
@@ -594,10 +597,15 @@ gck_secret_binary_write (GckSecretCollection *collection, GckSecretData *sdata,
buffer_add_time (&buffer, gck_secret_object_get_modified (obj));
buffer_add_time (&buffer, gck_secret_object_get_created (obj));
- flags = 0;
lock_timeout = gck_secret_collection_get_lock_idle (collection);
- if (lock_timeout)
+ if (lock_timeout) {
flags |= LOCK_ON_IDLE_FLAG;
+ } else {
+ lock_timeout = gck_secret_collection_get_lock_after (collection);
+ if (lock_timeout)
+ flags |= LOCK_AFTER_FLAG;
+ }
+
egg_buffer_add_uint32 (&buffer, flags);
egg_buffer_add_uint32 (&buffer, lock_timeout);
@@ -939,9 +947,10 @@ 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);
- if (!(flags & LOCK_ON_IDLE_FLAG))
- lock_timeout = 0;
- gck_secret_collection_set_lock_idle (collection, lock_timeout);
+ if (flags & LOCK_ON_IDLE_FLAG)
+ gck_secret_collection_set_lock_idle (collection, lock_timeout);
+ else if (flags & LOCK_AFTER_FLAG)
+ gck_secret_collection_set_lock_after (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 07a3089..1769ea9 100644
--- a/pkcs11/secret-store/gck-secret-collection.c
+++ b/pkcs11/secret-store/gck-secret-collection.c
@@ -48,11 +48,7 @@ struct _GckSecretCollection {
GHashTable *items;
gchar *filename;
guint32 watermark;
-
- /* Template for credential */
- CK_ATTRIBUTE tp_attrs[2];
- CK_ULONG tp_idle;
- CK_BBOOL tp_token;
+ GArray *template;
};
G_DEFINE_TYPE (GckSecretCollection, gck_secret_collection, GCK_TYPE_SECRET_OBJECT);
@@ -358,7 +354,7 @@ gck_secret_collection_get_attribute (GckObject *base, GckSession *session, CK_AT
case CKA_CLASS:
return gck_attribute_set_ulong (attr, CKO_G_COLLECTION);
case CKA_G_CREDENTIAL_TEMPLATE:
- return gck_attribute_set_template (attr, self->tp_attrs, G_N_ELEMENTS (self->tp_attrs));
+ return gck_attribute_set_template (attr, self->template);
}
return GCK_OBJECT_CLASS (gck_secret_collection_parent_class)->get_attribute (base, session, attr);
}
@@ -370,6 +366,7 @@ gck_secret_collection_set_attribute (GckObject *object, GckSession *session,
GckSecretCollection *self = GCK_SECRET_COLLECTION (object);
CK_OBJECT_HANDLE handle = 0;
GckCredential *cred;
+ GArray *template;
CK_RV rv;
switch (attr->type) {
@@ -386,6 +383,13 @@ gck_secret_collection_set_attribute (GckObject *object, GckSession *session,
return gck_transaction_fail (transaction, CKR_ATTRIBUTE_VALUE_INVALID);
change_master_password (self, transaction, cred);
return;
+ case CKA_G_CREDENTIAL_TEMPLATE:
+ rv = gck_attribute_get_template (attr, &template);
+ if (rv != CKR_OK)
+ return gck_transaction_fail (transaction, rv);
+ gck_template_free (self->template);
+ self->template = template;
+ return;
};
return GCK_OBJECT_CLASS (gck_secret_collection_parent_class)->set_attribute (object, session, transaction, attr);
@@ -470,17 +474,17 @@ gck_secret_collection_real_is_locked (GckSecretObject *obj, GckSession *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);
+ CK_ULONG idle = 0;
+ CK_ULONG after = 0;
+ CK_BBOOL token = CK_TRUE;
+ CK_ATTRIBUTE attrs[] = {
+ { CKA_TOKEN, &token, sizeof (token) },
+ { CKA_G_DESTRUCT_IDLE, &idle, sizeof (idle) },
+ { CKA_G_DESTRUCT_AFTER, &after, sizeof (after) },
+ };
- 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);
+ self->items = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
+ self->template = gck_template_new (attrs, G_N_ELEMENTS (attrs));
}
static void
@@ -539,6 +543,9 @@ gck_secret_collection_finalize (GObject *obj)
g_free (self->filename);
self->filename = NULL;
+ gck_template_free (self->template);
+ self->template = NULL;
+
G_OBJECT_CLASS (gck_secret_collection_parent_class)->finalize (obj);
}
@@ -864,15 +871,37 @@ gck_secret_collection_destroy (GckSecretCollection *self, GckTransaction *transa
gint
gck_secret_collection_get_lock_idle (GckSecretCollection *self)
{
+ gulong value;
g_return_val_if_fail (GCK_IS_SECRET_COLLECTION (self), 0);
- return (gint)self->tp_idle;
+ if (!gck_template_find_ulong (self->template, CKA_G_DESTRUCT_IDLE, &value))
+ value = 0;
+ return (gint)value;
}
void
gck_secret_collection_set_lock_idle (GckSecretCollection *self, gint lock_timeout)
{
+ CK_ULONG value = (lock_timeout < 0) ? 0 : lock_timeout;
+ CK_ATTRIBUTE attr = { CKA_G_DESTRUCT_IDLE, &value, sizeof (value) };
+ g_return_if_fail (GCK_IS_SECRET_COLLECTION (self));
+ gck_template_set (self->template, &attr);
+}
+
+gint
+gck_secret_collection_get_lock_after (GckSecretCollection *self)
+{
+ gulong value;
+ g_return_val_if_fail (GCK_IS_SECRET_COLLECTION (self), 0);
+ if (!gck_template_find_ulong (self->template, CKA_G_DESTRUCT_AFTER, &value))
+ value = 0;
+ return (gint)value;
+}
+
+void
+gck_secret_collection_set_lock_after (GckSecretCollection *self, gint lock_timeout)
+{
+ CK_ULONG value = (lock_timeout < 0) ? 0 : lock_timeout;
+ CK_ATTRIBUTE attr = { CKA_G_DESTRUCT_AFTER, &value, sizeof (value) };
g_return_if_fail (GCK_IS_SECRET_COLLECTION (self));
- if (lock_timeout < 0)
- lock_timeout = 0;
- self->tp_idle = (CK_ULONG)lock_timeout;
+ gck_template_set (self->template, &attr);
}
diff --git a/pkcs11/secret-store/gck-secret-collection.h b/pkcs11/secret-store/gck-secret-collection.h
index e0a8e57..690a2f2 100644
--- a/pkcs11/secret-store/gck-secret-collection.h
+++ b/pkcs11/secret-store/gck-secret-collection.h
@@ -96,4 +96,9 @@ gint gck_secret_collection_get_lock_idle (GckSecretCollection
void gck_secret_collection_set_lock_idle (GckSecretCollection *self,
gint lock_timeout);
+gint gck_secret_collection_get_lock_after (GckSecretCollection *self);
+
+void gck_secret_collection_set_lock_after (GckSecretCollection *self,
+ gint lock_timeout);
+
#endif /* __GCK_SECRET_COLLECTION_H__ */
diff --git a/pkcs11/secret-store/gck-secret-textual.c b/pkcs11/secret-store/gck-secret-textual.c
index 6c4e7d1..2eaddd9 100644
--- a/pkcs11/secret-store/gck-secret-textual.c
+++ b/pkcs11/secret-store/gck-secret-textual.c
@@ -406,11 +406,14 @@ gck_secret_textual_write (GckSecretCollection *collection, GckSecretData *sdata,
key_file_set_uint64 (file, "keyring", "ctime", gck_secret_object_get_created (obj));
key_file_set_uint64 (file, "keyring", "mtime", gck_secret_object_get_modified (obj));
- /* Not currently used :( */
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);
+ if (idle_timeout)
+ g_key_file_set_integer (file, "keyring", "lock-timeout", idle_timeout);
+ idle_timeout = gck_secret_collection_get_lock_after (collection);
+ g_key_file_set_boolean (file, "keyring", "lock-after", idle_timeout > 0);
+ if (idle_timeout)
+ g_key_file_set_integer (file, "keyring", "lock-timeout", idle_timeout);
items = gck_secret_collection_get_items (collection);
for (l = items; l; l = g_list_next (l))
@@ -457,7 +460,6 @@ gck_secret_textual_read (GckSecretCollection *collection, GckSecretData *sdata,
gchar *start = NULL;
const gchar *identifier;
GHashTable *checks = NULL;
- gboolean lock_idle;
gint lock_timeout;
gchar *value;
guint64 num;
@@ -499,9 +501,12 @@ gck_secret_textual_read (GckSecretCollection *collection, GckSecretData *sdata,
gck_secret_object_set_modified (obj, num);
/* Not currently used :( */
- lock_idle = g_key_file_get_boolean (file, "keyring", "lock-on-idle", NULL);
- g_object_set_data (G_OBJECT (collection), "lock-on-idle", GINT_TO_POINTER (lock_idle));
lock_timeout = g_key_file_get_integer (file, "keyring", "lock-timeout", NULL);
+ if (g_key_file_get_boolean (file, "keyring", "lock-after", NULL))
+ gck_secret_collection_set_lock_idle (collection, lock_timeout);
+ else if (g_key_file_get_boolean (file, "keyring", "lock-on-idle", NULL))
+ gck_secret_collection_set_lock_idle (collection, lock_timeout);
+
g_object_set_data (G_OBJECT (collection), "lock-timeout", GINT_TO_POINTER (lock_timeout));
/* Build a Hash table where we can track ids we haven't yet seen */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]