[gnome-keyring/dbus-api] [secret-store] Implement creation and deletion of collection.
- From: Stefan Walter <stefw src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [gnome-keyring/dbus-api] [secret-store] Implement creation and deletion of collection.
- Date: Sun, 8 Nov 2009 02:06:39 +0000 (UTC)
commit 9c2e4fc16101db49fe9e4cd4e76562383174edcf
Author: Stef Walter <stef memberwebs com>
Date: Sun Nov 8 02:03:52 2009 +0000
[secret-store] Implement creation and deletion of collection.
Implement creation, storing and removal of token collections and
items. Creating a collection with a master password is not yet
supported.
pkcs11/secret-store/gck-secret-binary.c | 2 +-
pkcs11/secret-store/gck-secret-collection.c | 330 ++++++++++++++++++--
pkcs11/secret-store/gck-secret-collection.h | 26 ++-
pkcs11/secret-store/gck-secret-item.c | 58 ++++
pkcs11/secret-store/gck-secret-item.h | 4 +
pkcs11/secret-store/gck-secret-module.c | 211 ++++++++++++-
pkcs11/secret-store/gck-secret-object.c | 67 ++++-
pkcs11/secret-store/gck-secret-object.h | 8 +-
pkcs11/secret-store/gck-secret-search.c | 84 ++----
pkcs11/secret-store/gck-secret-textual.c | 9 +-
pkcs11/secret-store/tests/test-secret-module.c | 47 +++-
.../tests/unit-test-secret-collection.c | 208 ++++++++++++
pkcs11/secret-store/tests/unit-test-secret-item.c | 116 ++++++-
.../secret-store/tests/unit-test-secret-search.c | 4 +-
14 files changed, 1025 insertions(+), 149 deletions(-)
---
diff --git a/pkcs11/secret-store/gck-secret-binary.c b/pkcs11/secret-store/gck-secret-binary.c
index f21f236..bf4474e 100644
--- a/pkcs11/secret-store/gck-secret-binary.c
+++ b/pkcs11/secret-store/gck-secret-binary.c
@@ -956,7 +956,7 @@ gck_secret_binary_read (GckSecretCollection *collection, GckSecretData *sdata,
item = gck_secret_collection_get_item (collection, items[i].identifier);
if (item == NULL)
- item = gck_secret_collection_create_item (collection, items[i].identifier);
+ item = gck_secret_collection_new_item (collection, items[i].identifier);
setup_item_from_info (item, sdata, &items[i]);
}
diff --git a/pkcs11/secret-store/gck-secret-collection.c b/pkcs11/secret-store/gck-secret-collection.c
index cb78d97..363f727 100644
--- a/pkcs11/secret-store/gck-secret-collection.c
+++ b/pkcs11/secret-store/gck-secret-collection.c
@@ -31,6 +31,7 @@
#include "gck/gck-authenticator.h"
#include "gck/gck-secret.h"
#include "gck/gck-session.h"
+#include "gck/gck-transaction.h"
#include <glib/gi18n.h>
@@ -46,10 +47,15 @@ struct _GckSecretCollection {
GckSecretData *sdata;
GHashTable *items;
gchar *filename;
+ guint32 watermark;
};
G_DEFINE_TYPE (GckSecretCollection, gck_secret_collection, GCK_TYPE_SECRET_OBJECT);
+/* Forward declarations */
+static void add_item (GckSecretCollection *, GckTransaction *, GckSecretItem *);
+static void remove_item (GckSecretCollection *, GckTransaction *, GckSecretItem *);
+
/* -----------------------------------------------------------------------------
* INTERNAL
*/
@@ -128,6 +134,141 @@ expose_each_item (gpointer key, gpointer value, gpointer user_data)
gck_object_expose (value, expose);
}
+static gboolean
+complete_add (GckTransaction *transaction, GckSecretCollection *self, GckSecretItem *item)
+{
+ if (gck_transaction_get_failed (transaction))
+ remove_item (self, NULL, item);
+ g_object_unref (item);
+ return TRUE;
+}
+
+static void
+add_item (GckSecretCollection *self, GckTransaction *transaction, GckSecretItem *item)
+{
+ const gchar *identifier;
+ guint32 number;
+
+ g_assert (GCK_IS_SECRET_COLLECTION (self));
+ g_assert (GCK_IS_SECRET_ITEM (item));
+
+ identifier = gck_secret_object_get_identifier (GCK_SECRET_OBJECT (item));
+ g_return_if_fail (identifier);
+
+ /* Make note of the highest numeric identifier, for later use */
+ number = strtoul (identifier, NULL, 10);
+ if (number > self->watermark)
+ self->watermark = number;
+
+ g_hash_table_replace (self->items, g_strdup (identifier), g_object_ref (item));
+
+ if (gck_object_is_exposed (GCK_OBJECT (self)))
+ gck_object_expose_full (GCK_OBJECT (item), transaction, TRUE);
+ if (transaction)
+ gck_transaction_add (transaction, self, (GckTransactionFunc)complete_add,
+ g_object_ref (item));
+
+}
+
+static gboolean
+complete_remove (GckTransaction *transaction, GckSecretCollection *self, GckSecretItem *item)
+{
+ if (gck_transaction_get_failed (transaction))
+ add_item (self, NULL, item);
+ g_object_unref (item);
+ return TRUE;
+}
+
+static void
+remove_item (GckSecretCollection *self, GckTransaction *transaction, GckSecretItem *item)
+{
+ const gchar *identifier;
+
+ g_assert (GCK_IS_SECRET_COLLECTION (self));
+ g_assert (GCK_IS_SECRET_ITEM (item));
+
+ identifier = gck_secret_object_get_identifier (GCK_SECRET_OBJECT (item));
+ g_return_if_fail (identifier);
+
+ g_object_ref (item);
+
+ g_hash_table_remove (self->items, identifier);
+
+ gck_object_expose_full (GCK_OBJECT (item), transaction, FALSE);
+ if (transaction)
+ gck_transaction_add (transaction, self, (GckTransactionFunc)complete_remove,
+ g_object_ref (item));
+
+ g_object_unref (item);
+}
+
+static void
+factory_create_collection (GckSession *session, GckTransaction *transaction,
+ CK_ATTRIBUTE_PTR attrs, CK_ULONG n_attrs, GckObject **result)
+{
+ GckSecretCollection *collection = NULL;
+ CK_ATTRIBUTE *attr;
+ GckManager *manager;
+ gchar *identifier = NULL;
+ gchar *label = NULL;
+ gboolean is_token;
+ GckAuthenticator *auth;
+ CK_RV rv;
+
+ g_return_if_fail (GCK_IS_TRANSACTION (transaction));
+ g_return_if_fail (attrs || !n_attrs);
+ g_return_if_fail (result);
+
+ if (!gck_attributes_find_boolean (attrs, n_attrs, CKA_TOKEN, &is_token))
+ is_token = FALSE;
+ if (is_token)
+ manager = gck_module_get_manager (gck_session_get_module (session));
+ else
+ manager = gck_session_get_manager (session);
+
+ /* See if a collection attribute was specified, not present means all collections */
+ attr = gck_attributes_find (attrs, n_attrs, CKA_LABEL);
+ if (attr != NULL) {
+ rv = gck_attribute_get_string (attr, &label);
+ if (rv != CKR_OK)
+ return gck_transaction_fail (transaction, rv);
+ identifier = g_utf8_strdown (label, -1);
+ g_strdelimit (identifier, ":/\\<>|\t\n\r\v ", '_');
+ gck_attribute_consume (attr);
+ }
+
+ if (!identifier || !identifier[0]) {
+ g_free (identifier);
+ identifier = g_strdup ("unnamed");
+ }
+
+ collection = g_object_new (GCK_TYPE_SECRET_COLLECTION,
+ "module", gck_session_get_module (session),
+ "identifier", identifier,
+ "manager", manager,
+ "label", label,
+ NULL);
+
+ g_free (identifier);
+ g_free (label);
+
+ /*
+ * HACK: We are expected to have an unlocked collection. This is
+ * currently a chicken and egg problem, as there's no way to set
+ * credentials. Actually currently there's no way to set credentials.
+ */
+ rv = gck_authenticator_create (GCK_OBJECT (collection), gck_session_get_manager (session),
+ NULL, 0, &auth);
+ if (rv != CKR_OK) {
+ gck_transaction_fail (transaction, rv);
+ g_object_unref (collection);
+ } else {
+ gck_session_add_session_object (session, transaction, GCK_OBJECT (auth));
+ *result = GCK_OBJECT (collection);
+ g_object_unref (auth);
+ }
+}
+
/* -----------------------------------------------------------------------------
* OBJECT
*/
@@ -304,39 +445,32 @@ gck_secret_collection_class_init (GckSecretCollectionClass *klass)
g_object_class_install_property (gobject_class, PROP_FILENAME,
g_param_spec_string ("filename", "Filename", "Collection filename (without path)",
NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+ gck_secret_object_class_unique_identifiers (secret_class);
}
-#if 0
-static gboolean
-gck_secret_collection_real_save (GckSerializable *base, GckSecret *login, guchar **data, gsize *n_data)
-{
- GckSecretCollection *self = GCK_SECRET_COLLECTION (base);
- GckSecret *master;
- GckDataResult res;
+/* -----------------------------------------------------------------------------
+ * PUBLIC
+ */
- g_return_val_if_fail (GCK_IS_SECRET_COLLECTION (self), FALSE);
- g_return_val_if_fail (data, FALSE);
- g_return_val_if_fail (n_data, FALSE);
+GckFactory*
+gck_secret_collection_get_factory (void)
+{
+ static CK_OBJECT_CLASS klass = CKO_G_COLLECTION;
- if (!self->sdata)
- g_return_val_if_reached (FALSE);
+ static CK_ATTRIBUTE attributes[] = {
+ { CKA_CLASS, &klass, sizeof (klass) },
+ };
- master = gck_secret_data_get_master (self->sdata);
- if (master == NULL)
- res = gck_secret_textual_write (self, data, n_data);
- else
- res = gck_secret_binary_write (self, master, data, n_data);
+ static GckFactory factory = {
+ attributes,
+ G_N_ELEMENTS (attributes),
+ factory_create_collection
+ };
- /* TODO: This doesn't transfer knowledge of 'no password' back up */
- return (res == GCK_DATA_SUCCESS);
+ return &factory;
}
-#endif
-
-/* -----------------------------------------------------------------------------
- * PUBLIC
- */
-
const gchar*
gck_secret_collection_get_filename (GckSecretCollection *self)
{
@@ -373,8 +507,51 @@ gck_secret_collection_get_item (GckSecretCollection *self, const gchar *identifi
return g_hash_table_lookup (self->items, identifier);
}
+gboolean
+gck_secret_collection_has_item (GckSecretCollection *self, GckSecretItem *item)
+{
+ const gchar *identifier;
+
+ g_return_val_if_fail (GCK_IS_SECRET_COLLECTION (self), FALSE);
+ g_return_val_if_fail (GCK_IS_SECRET_ITEM (item), FALSE);
+
+ identifier = gck_secret_object_get_identifier (GCK_SECRET_OBJECT (item));
+ return g_hash_table_lookup (self->items, identifier) == item;
+}
+
+GckSecretCollection*
+gck_secret_collection_find (CK_ATTRIBUTE_PTR attr, ...)
+{
+ CK_OBJECT_CLASS klass = CKO_G_COLLECTION;
+ GckSecretCollection *result = NULL;
+ GckManager *manager;
+ CK_ATTRIBUTE attrs[2];
+ GList *objects;
+ va_list va;
+
+ g_assert (attr);
+
+ attrs[0].type = CKA_CLASS;
+ attrs[0].ulValueLen = sizeof (klass);
+ attrs[0].pValue = &klass;
+ attrs[1].type = CKA_ID;
+ attrs[1].ulValueLen = attr->ulValueLen;
+ attrs[1].pValue = attr->pValue;
+
+ va_start (va, attr);
+ while (!result && (manager = va_arg (va, GckManager*)) != NULL) {
+ objects = gck_manager_find_by_attributes (manager, attrs, 2);
+ if (objects && GCK_IS_SECRET_COLLECTION (objects->data))
+ result = objects->data;
+ g_list_free (objects);
+ }
+ va_end (va);
+
+ return result;
+}
+
GckSecretItem*
-gck_secret_collection_create_item (GckSecretCollection *self, const gchar *identifier)
+gck_secret_collection_new_item (GckSecretCollection *self, const gchar *identifier)
{
GckSecretItem *item;
@@ -389,22 +566,59 @@ gck_secret_collection_create_item (GckSecretCollection *self, const gchar *ident
"identifier", identifier,
NULL);
- g_hash_table_replace (self->items, g_strdup (identifier), item);
+ add_item (self, NULL, item);
+ g_object_unref (item);
+ return item;
+}
+
+GckSecretItem*
+gck_secret_collection_create_item (GckSecretCollection *self, GckTransaction *transaction)
+{
+ GckSecretItem *item;
+ gchar *identifier = NULL;
+
+ g_return_val_if_fail (GCK_IS_SECRET_COLLECTION (self), NULL);
+ g_return_val_if_fail (transaction, NULL);
+ g_return_val_if_fail (!gck_transaction_get_failed (transaction), NULL);
+
+ do {
+ g_free (identifier);
+ identifier = g_strdup_printf ("%d", ++(self->watermark));
+ } while (g_hash_table_lookup (self->items, identifier));
+
+ item = g_object_new (GCK_TYPE_SECRET_ITEM,
+ "module", gck_object_get_module (GCK_OBJECT (self)),
+ "manager", gck_object_get_manager (GCK_OBJECT (self)),
+ "collection", self,
+ "identifier", identifier,
+ NULL);
+
+ g_free (identifier);
+ add_item (self, transaction, item);
+ g_object_unref (item);
return item;
}
void
gck_secret_collection_remove_item (GckSecretCollection *self, GckSecretItem *item)
{
- const gchar *identifier;
-
g_return_if_fail (GCK_IS_SECRET_COLLECTION (self));
g_return_if_fail (GCK_IS_SECRET_ITEM (item));
+ g_return_if_fail (gck_secret_collection_has_item (self, item));
- identifier = gck_secret_object_get_identifier (GCK_SECRET_OBJECT (item));
- g_return_if_fail (identifier);
+ remove_item (self, NULL, item);
+}
- g_hash_table_remove (self->items, identifier);
+void
+gck_secret_collection_destroy_item (GckSecretCollection *self, GckTransaction *transaction,
+ GckSecretItem *item)
+{
+ g_return_if_fail (GCK_IS_SECRET_COLLECTION (self));
+ g_return_if_fail (GCK_IS_TRANSACTION (transaction));
+ g_return_if_fail (GCK_IS_SECRET_ITEM (item));
+ g_return_if_fail (gck_secret_collection_has_item (self, item));
+
+ remove_item (self, transaction, item);
}
GckSecretData*
@@ -450,3 +664,55 @@ gck_secret_collection_load (GckSecretCollection *self)
return load_collection_and_secret_data (self, self->sdata, self->filename);
}
+
+void
+gck_secret_collection_save (GckSecretCollection *self, GckTransaction *transaction)
+{
+ GckSecret *master;
+ GckDataResult res;
+ guchar *data;
+ gsize n_data;
+
+ g_return_if_fail (GCK_IS_SECRET_COLLECTION (self));
+ g_return_if_fail (GCK_IS_TRANSACTION (transaction));
+ g_return_if_fail (!gck_transaction_get_failed (transaction));
+
+ if (!self->sdata)
+ g_return_if_reached ();
+
+ master = gck_secret_data_get_master (self->sdata);
+ if (master == NULL || gck_secret_equals (master, NULL, 0))
+ res = gck_secret_textual_write (self, self->sdata, &data, &n_data);
+ else
+ res = gck_secret_binary_write (self, self->sdata, &data, &n_data);
+
+ switch (res) {
+ case GCK_DATA_FAILURE:
+ case GCK_DATA_UNRECOGNIZED:
+ g_warning ("couldn't prepare to write out keyring: %s", self->filename);
+ gck_transaction_fail (transaction, CKR_GENERAL_ERROR);
+ break;
+ case GCK_DATA_LOCKED:
+ g_warning ("locked error while writing out keyring: %s", self->filename);
+ gck_transaction_fail (transaction, CKR_GENERAL_ERROR);
+ break;
+ case GCK_DATA_SUCCESS:
+ gck_transaction_write_file (transaction, self->filename, data, n_data);
+ g_free (data);
+ break;
+ default:
+ g_assert_not_reached ();
+ };
+}
+
+void
+gck_secret_collection_destroy (GckSecretCollection *self, GckTransaction *transaction)
+{
+ g_return_if_fail (GCK_IS_SECRET_COLLECTION (self));
+ g_return_if_fail (GCK_IS_TRANSACTION (transaction));
+ g_return_if_fail (!gck_transaction_get_failed (transaction));
+
+ gck_object_expose_full (GCK_OBJECT (self), transaction, FALSE);
+ if (self->filename)
+ gck_transaction_remove_file (transaction, self->filename);
+}
diff --git a/pkcs11/secret-store/gck-secret-collection.h b/pkcs11/secret-store/gck-secret-collection.h
index 2f00cc9..98d9cf5 100644
--- a/pkcs11/secret-store/gck-secret-collection.h
+++ b/pkcs11/secret-store/gck-secret-collection.h
@@ -26,6 +26,8 @@
#include "gck-secret-object.h"
+#define GCK_FACTORY_SECRET_COLLECTION (gck_secret_collection_get_factory ())
+
#define GCK_TYPE_SECRET_COLLECTION (gck_secret_collection_get_type ())
#define GCK_SECRET_COLLECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCK_TYPE_SECRET_COLLECTION, GckSecretCollection))
#define GCK_SECRET_COLLECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GCK_TYPE_SECRET_COLLECTION, GckSecretCollectionClass))
@@ -37,12 +39,24 @@ typedef struct _GckSecretCollectionClass GckSecretCollectionClass;
struct _GckSecretCollectionClass {
GckSecretObjectClass parent_class;
+ GHashTable *identifiers;
};
GType gck_secret_collection_get_type (void);
+GckFactory* gck_secret_collection_get_factory (void) G_GNUC_CONST;
+
+GckSecretCollection* gck_secret_collection_find (CK_ATTRIBUTE_PTR attr,
+ ...) G_GNUC_NULL_TERMINATED;
+
GckDataResult gck_secret_collection_load (GckSecretCollection *self);
+void gck_secret_collection_save (GckSecretCollection *self,
+ GckTransaction *transaction);
+
+void gck_secret_collection_destroy (GckSecretCollection *self,
+ GckTransaction *transaction);
+
const gchar* gck_secret_collection_get_filename (GckSecretCollection *self);
void gck_secret_collection_set_filename (GckSecretCollection *self,
@@ -53,12 +67,22 @@ GList* gck_secret_collection_get_items (GckSecretCollection
GckSecretItem* gck_secret_collection_get_item (GckSecretCollection *self,
const gchar *identifier);
-GckSecretItem* gck_secret_collection_create_item (GckSecretCollection *self,
+gboolean gck_secret_collection_has_item (GckSecretCollection *self,
+ GckSecretItem *item);
+
+GckSecretItem* gck_secret_collection_new_item (GckSecretCollection *self,
const gchar *identifier);
void gck_secret_collection_remove_item (GckSecretCollection *self,
GckSecretItem *item);
+GckSecretItem* gck_secret_collection_create_item (GckSecretCollection *self,
+ GckTransaction *transaction);
+
+void gck_secret_collection_destroy_item (GckSecretCollection *self,
+ GckTransaction *transaction,
+ GckSecretItem *item);
+
void gck_secret_collection_unlocked_clear (GckSecretCollection *self);
GckSecretData* gck_secret_collection_unlocked_data (GckSecretCollection *self,
diff --git a/pkcs11/secret-store/gck-secret-item.c b/pkcs11/secret-store/gck-secret-item.c
index a40e8c4..558a5ff 100644
--- a/pkcs11/secret-store/gck-secret-item.c
+++ b/pkcs11/secret-store/gck-secret-item.c
@@ -26,7 +26,9 @@
#include "gck-secret-item.h"
#include "gck/gck-attributes.h"
+#include "gck/gck-module.h"
#include "gck/gck-secret.h"
+#include "gck/gck-session.h"
#include "gck/gck-transaction.h"
#include "pkcs11/pkcs11i.h"
@@ -95,6 +97,44 @@ begin_set_fields (GckSecretItem *self, GckTransaction *transaction, GHashTable *
self->fields = fields;
}
+static void
+factory_create_item (GckSession *session, GckTransaction *transaction,
+ CK_ATTRIBUTE_PTR attrs, CK_ULONG n_attrs, GckObject **result)
+{
+ GckSecretCollection *collection = NULL;
+ GckSecretItem *item;
+ GckManager *manager;
+ CK_ATTRIBUTE *attr;
+ gboolean is_token;
+
+ g_return_if_fail (GCK_IS_TRANSACTION (transaction));
+ g_return_if_fail (attrs || !n_attrs);
+ g_return_if_fail (result);
+
+ if (!gck_attributes_find_boolean (attrs, n_attrs, CKA_TOKEN, &is_token))
+ is_token = FALSE;
+
+ /* See if a collection attribute was specified */
+ attr = gck_attributes_find (attrs, n_attrs, CKA_G_COLLECTION);
+ if (attr != NULL) {
+ gck_attribute_consume (attr);
+ if (is_token)
+ manager = gck_module_get_manager (gck_session_get_module (session));
+ else
+ manager = gck_session_get_manager (session);
+ collection = gck_secret_collection_find (attr, manager, NULL);
+ }
+
+ if (!collection)
+ return gck_transaction_fail (transaction, CKR_TEMPLATE_INCOMPLETE);
+
+ /* The collection owns the item */
+ item = gck_secret_collection_create_item (collection, transaction);
+
+ /* All the other fields are set later ... */
+ *result = g_object_ref (item);
+}
+
/* -----------------------------------------------------------------------------
* OBJECT
*/
@@ -309,6 +349,24 @@ gck_secret_item_class_init (GckSecretItemClass *klass)
* PUBLIC
*/
+GckFactory*
+gck_secret_item_get_factory (void)
+{
+ static CK_OBJECT_CLASS klass = CKO_SECRET_KEY;
+
+ static CK_ATTRIBUTE attributes[] = {
+ { CKA_CLASS, &klass, sizeof (klass) },
+ };
+
+ static GckFactory factory = {
+ attributes,
+ G_N_ELEMENTS (attributes),
+ factory_create_item
+ };
+
+ return &factory;
+}
+
GckSecretCollection*
gck_secret_item_get_collection (GckSecretItem *self)
{
diff --git a/pkcs11/secret-store/gck-secret-item.h b/pkcs11/secret-store/gck-secret-item.h
index fd3344f..f992cc9 100644
--- a/pkcs11/secret-store/gck-secret-item.h
+++ b/pkcs11/secret-store/gck-secret-item.h
@@ -27,6 +27,8 @@
#include "gck-secret-object.h"
#include "gck-secret-collection.h"
+#define GCK_FACTORY_SECRET_ITEM (gck_secret_item_get_factory ())
+
#define GCK_TYPE_SECRET_ITEM (gck_secret_item_get_type ())
#define GCK_SECRET_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCK_TYPE_SECRET_ITEM, GckSecretItem))
#define GCK_SECRET_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GCK_TYPE_SECRET_ITEM, GckSecretItemClass))
@@ -42,6 +44,8 @@ struct _GckSecretItemClass {
GType gck_secret_item_get_type (void);
+GckFactory* gck_secret_item_get_factory (void) G_GNUC_CONST;
+
GckSecretCollection* gck_secret_item_get_collection (GckSecretItem *self);
GHashTable* gck_secret_item_get_fields (GckSecretItem *self);
diff --git a/pkcs11/secret-store/gck-secret-module.c b/pkcs11/secret-store/gck-secret-module.c
index a986bbf..fdf2178 100644
--- a/pkcs11/secret-store/gck-secret-module.c
+++ b/pkcs11/secret-store/gck-secret-module.c
@@ -22,12 +22,17 @@
#include "config.h"
#include "gck-secret-collection.h"
+#include "gck-secret-item.h"
#include "gck-secret-module.h"
#include "gck-secret-search.h"
#include "gck-secret-store.h"
#include "gck/gck-file-tracker.h"
+#include "gck/gck-transaction.h"
+#include <glib/gstdio.h>
+
+#include <errno.h>
#include <fcntl.h>
#include <string.h>
@@ -71,6 +76,10 @@ G_DEFINE_TYPE (GckSecretModule, gck_secret_module, GCK_TYPE_MODULE);
GckModule* _gck_secret_store_get_module_for_testing (void);
+/* Forward declarations */
+static void add_collection (GckSecretModule *, GckTransaction *, GckSecretCollection *);
+static void remove_collection (GckSecretModule *, GckTransaction *, GckSecretCollection *);
+
/* -----------------------------------------------------------------------------
* ACTUAL PKCS#11 Module Implementation
*/
@@ -83,6 +92,107 @@ GCK_DEFINE_MODULE (gck_secret_module, GCK_TYPE_SECRET_MODULE);
* INTERNAL
*/
+static gboolean
+complete_add (GckTransaction *transaction, GObject *obj, gpointer user_data)
+{
+ GckSecretCollection *collection = GCK_SECRET_COLLECTION (user_data);
+ if (gck_transaction_get_failed (transaction))
+ remove_collection (GCK_SECRET_MODULE (obj), NULL, collection);
+ g_object_unref (collection);
+ return TRUE;
+}
+
+static void
+add_collection (GckSecretModule *self, GckTransaction *transaction, GckSecretCollection *collection)
+{
+ const gchar *identifier;
+
+ g_assert (GCK_IS_SECRET_MODULE(self));
+ g_assert (GCK_IS_SECRET_COLLECTION (collection));
+
+ identifier = gck_secret_object_get_identifier (GCK_SECRET_OBJECT (collection));
+ g_return_if_fail (identifier);
+
+ g_hash_table_replace (self->collections, g_strdup (identifier), g_object_ref (collection));
+
+ gck_object_expose_full (GCK_OBJECT (collection), transaction, TRUE);
+ if (transaction)
+ gck_transaction_add (transaction, self, complete_add, g_object_ref (collection));
+}
+
+static gboolean
+complete_remove (GckTransaction *transaction, GObject *obj, gpointer user_data)
+{
+ GckSecretCollection *collection = GCK_SECRET_COLLECTION (user_data);
+ if (gck_transaction_get_failed (transaction))
+ add_collection (GCK_SECRET_MODULE (obj), NULL, collection);
+ g_object_unref (collection);
+ return TRUE;
+}
+
+static void
+remove_collection (GckSecretModule *self, GckTransaction *transaction, GckSecretCollection *collection)
+{
+ const gchar *identifier;
+
+ g_assert (GCK_IS_SECRET_MODULE (self));
+ g_assert (GCK_IS_SECRET_COLLECTION (collection));
+
+ identifier = gck_secret_object_get_identifier (GCK_SECRET_OBJECT (collection));
+ g_return_if_fail (identifier);
+
+ g_hash_table_remove (self->collections, identifier);
+
+ gck_object_expose_full (GCK_OBJECT (collection), transaction, FALSE);
+ if (transaction)
+ gck_transaction_add (transaction, self, complete_remove, g_object_ref (collection));
+}
+
+static gchar*
+identifier_from_filename (GckSecretModule *self, const gchar *filename)
+{
+ gchar *identifier;
+
+ /* Do we have one for this path yet? */
+ identifier = g_path_get_basename (filename);
+
+ /* Remove the keyring suffix */
+ if (g_str_has_suffix (identifier, ".keyring"))
+ identifier[strlen(identifier) - 8] = 0;
+
+ return identifier;
+}
+
+static gchar*
+identifier_to_new_filename (GckSecretModule *self, const gchar *identifier)
+{
+ gchar *filename;
+ gint i;
+ int fd;
+
+ for (i = 0; i < G_MAXINT; ++i) {
+ if (i == 0)
+ filename = g_strdup_printf ("%s/%s.keyring", self->directory, identifier);
+ else
+ filename = g_strdup_printf ("%s/%s_%d.keyring", self->directory, identifier, i);
+
+ /* Try to create the file, and check that it doesn't exist */
+ fd = g_open (filename, O_RDONLY | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
+ if (fd == -1) {
+ if (errno != EEXIST)
+ break;
+ } else {
+ close (fd);
+ break;
+ }
+
+ g_free (filename);
+ }
+
+ return filename;
+}
+
+
static void
on_file_load (GckFileTracker *tracker, const gchar *path, GckSecretModule *self)
{
@@ -90,20 +200,20 @@ on_file_load (GckFileTracker *tracker, const gchar *path, GckSecretModule *self)
GckManager *manager;
GckDataResult res;
gboolean created;
- gchar *basename;
+ gchar *identifier;
manager = gck_module_get_manager (GCK_MODULE (self));
g_return_if_fail (manager);
/* Do we have one for this path yet? */
- basename = g_path_get_basename (path);
- collection = g_hash_table_lookup (self->collections, basename);
+ identifier = identifier_from_filename (self, path);
+ collection = g_hash_table_lookup (self->collections, path);
if (collection == NULL) {
created = TRUE;
collection = g_object_new (GCK_TYPE_SECRET_COLLECTION,
"module", self,
- "identifier", basename,
+ "identifier", identifier,
"filename", path,
"manager", manager,
NULL);
@@ -113,11 +223,8 @@ on_file_load (GckFileTracker *tracker, const gchar *path, GckSecretModule *self)
switch (res) {
case GCK_DATA_SUCCESS:
- if (created) {
- g_hash_table_replace (self->collections, basename, collection);
- gck_object_expose (GCK_OBJECT (collection), TRUE);
- basename = NULL;
- }
+ if (created)
+ add_collection (self, NULL, collection);
break;
case GCK_DATA_LOCKED:
g_message ("master password for keyring changed without our knowledge: %s", path);
@@ -133,21 +240,21 @@ on_file_load (GckFileTracker *tracker, const gchar *path, GckSecretModule *self)
g_assert_not_reached ();
}
- g_free (basename);
+ g_object_unref (collection);
+ g_free (identifier);
}
static void
on_file_remove (GckFileTracker *tracker, const gchar *path, GckSecretModule *self)
{
- gchar *basename;
+ GckSecretCollection *collection;
g_return_if_fail (path);
g_return_if_fail (GCK_IS_SECRET_MODULE (self));
- basename = g_path_get_basename (path);
- if (!g_hash_table_remove (self->collections, basename))
- g_return_if_reached ();
- g_free (basename);
+ collection = g_hash_table_lookup (self->collections, path);
+ if (collection)
+ remove_collection (self, NULL, collection);
}
/* -----------------------------------------------------------------------------
@@ -185,6 +292,74 @@ gck_secret_module_real_refresh_token (GckModule *base)
return CKR_OK;
}
+static void
+gck_secret_module_real_store_object (GckModule *module, GckTransaction *transaction,
+ GckObject *object)
+{
+ GckSecretModule *self = GCK_SECRET_MODULE (module);
+ GckSecretCollection *collection = NULL;
+ const gchar *identifier;
+ gchar *filename;
+
+ /* Adding an item */
+ if (GCK_IS_SECRET_ITEM (object)) {
+ collection = gck_secret_item_get_collection (GCK_SECRET_ITEM (object));
+ g_return_if_fail (GCK_IS_SECRET_COLLECTION (collection));
+
+ /* Adding a collection */
+ } else if (GCK_IS_SECRET_COLLECTION (object)) {
+ collection = GCK_SECRET_COLLECTION (object);
+ }
+
+ /* No other kind of token object */
+ if (collection == NULL) {
+ g_warning ("can't store object of type '%s' on secret token", G_OBJECT_TYPE_NAME (object));
+ gck_transaction_fail (transaction, CKR_GENERAL_ERROR);
+ return;
+ }
+
+ /* Setup a filename for this collection */
+ if (!gck_secret_collection_get_filename (collection)) {
+ identifier = gck_secret_object_get_identifier (GCK_SECRET_OBJECT (collection));
+ filename = identifier_to_new_filename (self, identifier);
+ gck_secret_collection_set_filename (collection, filename);
+ g_free (filename);
+ }
+
+ gck_secret_collection_save (collection, transaction);
+ if (!gck_transaction_get_failed (transaction))
+ add_collection (self, transaction, collection);
+}
+
+static void
+gck_secret_module_real_remove_object (GckModule *module, GckTransaction *transaction,
+ GckObject *object)
+{
+ GckSecretModule *self = GCK_SECRET_MODULE (module);
+ GckSecretCollection *collection;
+
+ /* Removing an item */
+ if (GCK_IS_SECRET_ITEM (object)) {
+ collection = gck_secret_item_get_collection (GCK_SECRET_ITEM (object));
+ g_return_if_fail (GCK_IS_SECRET_COLLECTION (collection));
+ gck_secret_collection_destroy_item (collection, transaction, GCK_SECRET_ITEM (object));
+ if (!gck_transaction_get_failed (transaction))
+ gck_secret_collection_save (collection, transaction);
+
+ /* Removing a collection */
+ } else if (GCK_IS_SECRET_COLLECTION (object)) {
+ collection = GCK_SECRET_COLLECTION (object);
+ gck_secret_collection_destroy (collection, transaction);
+ if (!gck_transaction_get_failed (transaction))
+ remove_collection (self, transaction, collection);
+
+ /* No other token objects */
+ } else {
+ gck_transaction_fail (transaction, CKR_FUNCTION_NOT_SUPPORTED);
+ g_return_if_reached ();
+ }
+}
+
static GObject*
gck_secret_module_constructor (GType type, guint n_props, GObjectConstructParam *props)
{
@@ -211,6 +386,8 @@ gck_secret_module_init (GckSecretModule *self)
{
self->collections = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
gck_module_register_factory (GCK_MODULE (self), GCK_FACTORY_SECRET_SEARCH);
+ gck_module_register_factory (GCK_MODULE (self), GCK_FACTORY_SECRET_ITEM);
+ gck_module_register_factory (GCK_MODULE (self), GCK_FACTORY_SECRET_COLLECTION);
}
static void
@@ -252,11 +429,13 @@ gck_secret_module_class_init (GckSecretModuleClass *klass)
gobject_class->constructor = gck_secret_module_constructor;
gobject_class->dispose = gck_secret_module_dispose;
gobject_class->finalize = gck_secret_module_finalize;
-
+
module_class->get_slot_info = gck_secret_module_real_get_slot_info;
module_class->get_token_info = gck_secret_module_real_get_token_info;
module_class->parse_argument = gck_secret_module_real_parse_argument;
module_class->refresh_token = gck_secret_module_real_refresh_token;
+ module_class->remove_token_object = gck_secret_module_real_remove_object;
+ module_class->store_token_object = gck_secret_module_real_store_object;
}
/* ---------------------------------------------------------------------------------------
diff --git a/pkcs11/secret-store/gck-secret-object.c b/pkcs11/secret-store/gck-secret-object.c
index 9ca01a9..39783e9 100644
--- a/pkcs11/secret-store/gck-secret-object.c
+++ b/pkcs11/secret-store/gck-secret-object.c
@@ -81,6 +81,45 @@ begin_set_label (GckSecretObject *self, GckTransaction *transaction, gchar *labe
self->pv->label = label;
}
+static gchar*
+register_identifier (GckSecretObjectClass *klass, const gchar *identifier)
+{
+ gchar *result;
+ gint i;
+
+ g_assert (klass);
+ g_assert (identifier);
+
+ if (!klass->identifiers)
+ return g_strdup (identifier);
+
+ for (i = 0; i < G_MAXINT; ++i) {
+ if (i == 0)
+ result = g_strdup (identifier);
+ else
+ result = g_strdup_printf ("%s_%d", identifier, i);
+ if (g_hash_table_lookup (klass->identifiers, result)) {
+ g_free (result);
+ } else {
+ g_hash_table_insert (klass->identifiers, result, result);
+ return result;
+ }
+ }
+
+ g_assert_not_reached ();
+}
+
+static void
+unregister_identifier (GckSecretObjectClass *klass, gchar *identifier)
+{
+ g_assert (klass);
+ g_assert (identifier);
+
+ if (klass->identifiers)
+ g_hash_table_remove (klass->identifiers, identifier);
+ g_free (identifier);
+}
+
/* -----------------------------------------------------------------------------
* OBJECT
*/
@@ -168,16 +207,19 @@ static void
gck_secret_object_set_property (GObject *obj, guint prop_id, const GValue *value,
GParamSpec *pspec)
{
+ GckSecretObjectClass *klass = GCK_SECRET_OBJECT_GET_CLASS (obj);
GckSecretObject *self = GCK_SECRET_OBJECT (obj);
-
+ const gchar *identifier;
+
switch (prop_id) {
case PROP_LABEL:
gck_secret_object_set_label (self, g_value_get_string (value));
break;
case PROP_IDENTIFIER:
g_return_if_fail (!self->pv->identifier);
- self->pv->identifier = g_value_dup_string (value);
- g_return_if_fail (self->pv->identifier);
+ identifier = g_value_get_string (value);
+ g_return_if_fail (identifier);
+ self->pv->identifier = register_identifier (klass, identifier);
break;
case PROP_CREATED:
gck_secret_object_set_created (self, g_value_get_long (value));
@@ -217,18 +259,13 @@ gck_secret_object_get_property (GObject *obj, guint prop_id, GValue *value,
}
static void
-gck_secret_object_dispose (GObject *obj)
-{
- /* GckSecretObject *self = GCK_SECRET_OBJECT (obj); */
- G_OBJECT_CLASS (gck_secret_object_parent_class)->dispose (obj);
-}
-
-static void
gck_secret_object_finalize (GObject *obj)
{
+ GckSecretObjectClass *klass = GCK_SECRET_OBJECT_GET_CLASS (obj);
GckSecretObject *self = GCK_SECRET_OBJECT (obj);
- g_free (self->pv->identifier);
+ if (self->pv->identifier)
+ unregister_identifier (klass, self->pv->identifier);
self->pv->identifier = NULL;
g_free (self->pv->label);
@@ -250,7 +287,6 @@ gck_secret_object_class_init (GckSecretObjectClass *klass)
g_type_class_add_private (klass, sizeof (GckSecretObjectPrivate));
gobject_class->constructor = gck_secret_object_constructor;
- gobject_class->dispose = gck_secret_object_dispose;
gobject_class->finalize = gck_secret_object_finalize;
gobject_class->set_property = gck_secret_object_set_property;
gobject_class->get_property = gck_secret_object_get_property;
@@ -281,6 +317,13 @@ gck_secret_object_class_init (GckSecretObjectClass *klass)
* PUBLIC
*/
+void
+gck_secret_object_class_unique_identifiers (GckSecretObjectClass *klass)
+{
+ if (!klass->identifiers)
+ klass->identifiers = g_hash_table_new (g_str_hash, g_str_equal);
+}
+
const gchar*
gck_secret_object_get_identifier (GckSecretObject *self)
{
diff --git a/pkcs11/secret-store/gck-secret-object.h b/pkcs11/secret-store/gck-secret-object.h
index 106961e..b2b905f 100644
--- a/pkcs11/secret-store/gck-secret-object.h
+++ b/pkcs11/secret-store/gck-secret-object.h
@@ -44,8 +44,10 @@ struct _GckSecretObject {
};
struct _GckSecretObjectClass {
GckObjectClass parent_class;
-
+ GHashTable *identifiers;
+
gboolean (*is_locked) (GckSecretObject *self, GckSession *session);
+
};
GType gck_secret_object_get_type (void);
@@ -72,4 +74,8 @@ void gck_secret_object_was_modified (GckSecretObject *self);
gboolean gck_secret_object_is_locked (GckSecretObject *self,
GckSession *session);
+void gck_secret_object_class_unique_identifiers (GckSecretObjectClass *klass);
+
+gchar* gck_secret_object_anonymous_identifier (void);
+
#endif /* __GCK_SECRET_OBJECT_H__ */
diff --git a/pkcs11/secret-store/gck-secret-search.c b/pkcs11/secret-store/gck-secret-search.c
index 4fe7563..d177520 100644
--- a/pkcs11/secret-store/gck-secret-search.c
+++ b/pkcs11/secret-store/gck-secret-search.c
@@ -159,63 +159,26 @@ on_manager_gone_away (gpointer user_data, GObject *where_the_object_was)
self->managers = g_list_delete_link (self->managers, l);
}
-static GckSecretCollection*
-find_collection_in_managers (GList *managers, CK_ATTRIBUTE_PTR attr)
-{
- CK_OBJECT_CLASS klass = CKO_G_COLLECTION;
- GckSecretCollection *result = NULL;
- CK_ATTRIBUTE attrs[2];
- GList *objects, *l;
-
- g_assert (attr);
-
- attrs[0].type = CKA_CLASS;
- attrs[0].ulValueLen = sizeof (klass);
- attrs[0].pValue = &klass;
- attrs[1].type = CKA_ID;
- attrs[1].ulValueLen = attr->ulValueLen;
- attrs[1].pValue = attr->pValue;
-
- for (l = managers; !result && l; l = g_list_next (l)) {
- objects = gck_manager_find_by_attributes (l->data, attrs, 2);
- if (objects && GCK_IS_SECRET_COLLECTION (objects->data))
- result = objects->data;
- g_list_free (objects);
- }
-
- return result;
-}
-
static void
-populate_search_from_managers (GckSecretSearch *self, GList *managers)
+populate_search_from_manager (GckSecretSearch *self, GckManager *manager)
{
GList *objects, *o;
- GckManager *manager;
- GList *l;
- g_assert (!self->managers);
- self->managers = managers;
-
- /* Load any new items or collections */
- gck_module_refresh_token (gck_object_get_module (GCK_OBJECT (self)));
-
- for (l = self->managers; l; l = g_list_next (l)) {
- manager = GCK_MANAGER (l->data);
+ self->managers = g_list_append (self->managers, manager);
- /* Add in all the objects */
- objects = gck_manager_find_by_class (manager, CKO_SECRET_KEY);
- for (o = objects; o; o = g_list_next (o))
- on_manager_added_object (manager, o->data, self);
- g_list_free (objects);
+ /* Add in all the objects */
+ objects = gck_manager_find_by_class (manager, CKO_SECRET_KEY);
+ for (o = objects; o; o = g_list_next (o))
+ on_manager_added_object (manager, o->data, self);
+ g_list_free (objects);
- /* Track this manager */
- g_object_weak_ref (G_OBJECT (manager), on_manager_gone_away, self);
+ /* Track this manager */
+ g_object_weak_ref (G_OBJECT (manager), on_manager_gone_away, self);
- /* Watch for further events of objects */
- g_signal_connect (manager, "object-added", G_CALLBACK (on_manager_added_object), self);
- g_signal_connect (manager, "object-removed", G_CALLBACK (on_manager_removed_object), self);
- g_signal_connect (manager, "attribute-changed", G_CALLBACK (on_manager_changed_object), self);
- }
+ /* Watch for further events of objects */
+ g_signal_connect (manager, "object-added", G_CALLBACK (on_manager_added_object), self);
+ g_signal_connect (manager, "object-removed", G_CALLBACK (on_manager_removed_object), self);
+ g_signal_connect (manager, "attribute-changed", G_CALLBACK (on_manager_changed_object), self);
}
static void
@@ -223,11 +186,10 @@ factory_create_search (GckSession *session, GckTransaction *transaction,
CK_ATTRIBUTE_PTR attrs, CK_ULONG n_attrs, GckObject **result)
{
GckSecretCollection *collection = NULL;
+ GckManager *s_manager, *m_manager;
GckSecretSearch *search;
- GList *managers = NULL;
CK_ATTRIBUTE *attr;
GHashTable *fields;
- GckManager *manager;
GckModule *module;
CK_RV rv;
@@ -250,21 +212,17 @@ factory_create_search (GckSession *session, GckTransaction *transaction,
return;
}
- manager = gck_session_get_manager (session);
+ s_manager = gck_session_get_manager (session);
module = gck_session_get_module (session);
-
- /* The managers we're going to be searching */
- managers = g_list_prepend (managers, gck_module_get_manager (module));
- managers = g_list_prepend (managers, manager);
+ m_manager = gck_module_get_manager (module);
/* See if a collection attribute was specified, not present means all collections */
attr = gck_attributes_find (attrs, n_attrs, CKA_G_COLLECTION);
if (attr) {
- collection = find_collection_in_managers (managers, attr);
+ collection = gck_secret_collection_find (attr, s_manager, m_manager, NULL);
gck_attribute_consume (attr);
if (!collection) {
g_hash_table_unref (fields);
- g_list_free (managers);
gck_transaction_fail (transaction, CKR_TEMPLATE_INCONSISTENT);
return;
}
@@ -272,12 +230,16 @@ factory_create_search (GckSession *session, GckTransaction *transaction,
search = g_object_new (GCK_TYPE_SECRET_SEARCH,
"module", module,
- "manager", manager,
+ "manager", s_manager,
"fields", fields,
"collection", collection,
NULL);
- populate_search_from_managers (search, managers);
+ /* Load any new items or collections */
+ gck_module_refresh_token (module);
+
+ populate_search_from_manager (search, s_manager);
+ populate_search_from_manager (search, m_manager);
*result = GCK_OBJECT (search);
}
diff --git a/pkcs11/secret-store/gck-secret-textual.c b/pkcs11/secret-store/gck-secret-textual.c
index 51b24c9..087a4af 100644
--- a/pkcs11/secret-store/gck-secret-textual.c
+++ b/pkcs11/secret-store/gck-secret-textual.c
@@ -478,7 +478,12 @@ gck_secret_textual_read (GckSecretCollection *collection, GckSecretData *sdata,
file = g_key_file_new ();
obj = GCK_SECRET_OBJECT (collection);
-
+
+ if (!n_data) {
+ res = GCK_DATA_UNRECOGNIZED;
+ goto done;
+ }
+
if (!g_key_file_load_from_data (file, (const gchar*)data, n_data, G_KEY_FILE_NONE, &err)) {
if (g_error_matches (err, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_PARSE))
res = GCK_DATA_UNRECOGNIZED;
@@ -529,7 +534,7 @@ gck_secret_textual_read (GckSecretCollection *collection, GckSecretData *sdata,
item = gck_secret_collection_get_item (collection, identifier);
if (item == NULL)
- item = gck_secret_collection_create_item (collection, identifier);
+ item = gck_secret_collection_new_item (collection, identifier);
parse_item (file, item, sdata, (const gchar**)groups);
}
diff --git a/pkcs11/secret-store/tests/test-secret-module.c b/pkcs11/secret-store/tests/test-secret-module.c
index 93b0f6b..36462de 100644
--- a/pkcs11/secret-store/tests/test-secret-module.c
+++ b/pkcs11/secret-store/tests/test-secret-module.c
@@ -23,6 +23,7 @@
#include "config.h"
#include "test-secret-module.h"
+#include "run-auto-test.h"
#include "gck/gck-secret.h"
#include "gck/gck-module.h"
@@ -34,20 +35,53 @@
#include "gck-secret-object.h"
#include "gck-secret-store.h"
+#include <string.h>
+
static GMutex *mutex = NULL;
GckModule* _gck_secret_store_get_module_for_testing (void);
GMutex* _gck_module_get_scary_mutex_that_you_should_not_touch (GckModule *module);
+static void
+copy_scratch_file (const gchar *basename)
+{
+ gchar *filename;
+ gchar *data;
+ gsize n_data;
+
+ filename = test_data_filename (basename);
+ if (!g_file_get_contents (filename, &data, &n_data, NULL))
+ g_return_if_reached ();
+ g_free (filename);
+
+ filename = test_scratch_filename (basename);
+ if (!g_file_set_contents (filename, data, n_data, NULL))
+ g_return_if_reached ();
+ g_free (filename);
+ g_free (data);
+}
+
GckModule*
test_secret_module_initialize_and_enter (void)
{
CK_FUNCTION_LIST_PTR funcs;
+ CK_C_INITIALIZE_ARGS args;
GckModule *module;
+ gchar *string;
CK_RV rv;
+ /* Setup test directory to work in */
+ memset (&args, 0, sizeof (args));
+ string = g_strdup_printf ("directory='%s'", test_scratch_directory ());
+ args.pReserved = string;
+ args.flags = CKF_OS_LOCKING_OK;
+
+ /* Copy files from test-data to scratch */
+ copy_scratch_file ("encrypted.keyring");
+ copy_scratch_file ("plain.keyring");
+
funcs = gck_secret_store_get_functions ();
- rv = (funcs->C_Initialize) (NULL);
+ rv = (funcs->C_Initialize) (&args);
g_return_val_if_fail (rv == CKR_OK, NULL);
module = _gck_secret_store_get_module_for_testing ();
@@ -56,6 +90,8 @@ test_secret_module_initialize_and_enter (void)
mutex = _gck_module_get_scary_mutex_that_you_should_not_touch (module);
test_secret_module_enter ();
+ g_free (string);
+
return module;
}
@@ -104,6 +140,9 @@ test_secret_module_open_session (gboolean writable)
rv = gck_module_C_OpenSession (module, 1, flags, NULL, NULL, &handle);
g_assert (rv == CKR_OK);
+ rv = gck_module_C_Login (module, handle, CKU_USER, NULL, 0);
+ g_assert (rv == CKR_OK);
+
session = gck_module_lookup_session (module, handle);
g_assert (session);
@@ -215,7 +254,7 @@ test_secret_collection_populate (GckSecretCollection *collection, GckSecretData
GHashTable *fields;
GckSecret *secret;
- item = gck_secret_collection_create_item (collection, "4");
+ item = gck_secret_collection_new_item (collection, "4");
gck_secret_object_set_label (GCK_SECRET_OBJECT (item), "Noises");
secret = gck_secret_new_from_password ("4's secret");
gck_secret_data_set_secret (sdata, "4", secret);
@@ -225,7 +264,7 @@ test_secret_collection_populate (GckSecretCollection *collection, GckSecretData
gck_secret_fields_add (fields, "pig", "grunt");
gck_secret_fields_add_compat_uint32 (fields, "how-many", 292929);
- item = gck_secret_collection_create_item (collection, "5");
+ item = gck_secret_collection_new_item (collection, "5");
gck_secret_object_set_label (GCK_SECRET_OBJECT (item), "Colors");
secret = gck_secret_new_from_password ("5's secret");
gck_secret_data_set_secret (sdata, "5", secret);
@@ -235,7 +274,7 @@ test_secret_collection_populate (GckSecretCollection *collection, GckSecretData
gck_secret_fields_add (fields, "piglet", "pink");
gck_secret_fields_add_compat_uint32 (fields, "number", 8);
- item = gck_secret_collection_create_item (collection, "6");
+ item = gck_secret_collection_new_item (collection, "6");
gck_secret_object_set_label (GCK_SECRET_OBJECT (item), "Binary Secret");
secret = gck_secret_new ((guchar*)"binary\0secret", 13);
gck_secret_data_set_secret (sdata, "6", secret);
diff --git a/pkcs11/secret-store/tests/unit-test-secret-collection.c b/pkcs11/secret-store/tests/unit-test-secret-collection.c
index 854ee90..9182c07 100644
--- a/pkcs11/secret-store/tests/unit-test-secret-collection.c
+++ b/pkcs11/secret-store/tests/unit-test-secret-collection.c
@@ -28,9 +28,11 @@
#include "gck-secret-data.h"
#include "gck-secret-collection.h"
+#include "gck-secret-item.h"
#include "gck/gck-authenticator.h"
#include "gck/gck-session.h"
+#include "gck/gck-transaction.h"
#include "pkcs11/pkcs11i.h"
@@ -123,6 +125,14 @@ DEFINE_TEST(secret_collection_set_filename)
g_assert_cmpstr (filename, ==, "/tmp/filename.keyring");
}
+DEFINE_TEST(secret_collection_has_item)
+{
+ GckSecretItem *item;
+
+ item = gck_secret_collection_new_item (collection, "testo");
+ g_assert (gck_secret_collection_has_item (collection, item));
+}
+
DEFINE_TEST(secret_collection_load_unlock_plain)
{
GckAuthenticator *auth;
@@ -313,3 +323,201 @@ DEFINE_TEST(secret_collection_memory_unlock_bad_password)
(guchar*)"wrong", 5, &auth);
g_assert (rv == CKR_PIN_INCORRECT);
}
+
+DEFINE_TEST(secret_collection_factory)
+{
+ CK_OBJECT_CLASS klass = CKO_G_COLLECTION;
+ GckObject *object;
+ CK_RV rv;
+
+ CK_ATTRIBUTE attrs[] = {
+ { CKA_CLASS, &klass, sizeof (klass) },
+ { CKA_LABEL, "blah", 4 },
+ };
+
+ rv = gck_session_create_object_for_factory (session, GCK_FACTORY_SECRET_COLLECTION,
+ attrs, G_N_ELEMENTS (attrs), &object);
+ g_assert (rv == CKR_OK);
+ g_assert (GCK_IS_SECRET_COLLECTION (object));
+
+ g_assert_cmpstr (gck_secret_object_get_label (GCK_SECRET_OBJECT (object)), ==, "blah");
+}
+
+DEFINE_TEST(secret_collection_factory_unnamed)
+{
+ CK_OBJECT_CLASS klass = CKO_G_COLLECTION;
+ const gchar *identifier;
+ GckObject *object;
+ CK_RV rv;
+
+ CK_ATTRIBUTE attrs[] = {
+ { CKA_CLASS, &klass, sizeof (klass) },
+ };
+
+ rv = gck_session_create_object_for_factory (session, GCK_FACTORY_SECRET_COLLECTION,
+ attrs, G_N_ELEMENTS (attrs), &object);
+ g_assert (rv == CKR_OK);
+ g_assert (GCK_IS_SECRET_COLLECTION (object));
+
+ identifier = gck_secret_object_get_identifier (GCK_SECRET_OBJECT (object));
+ g_assert_cmpstr (identifier, !=, "");
+}
+
+DEFINE_TEST(secret_collection_factory_token)
+{
+ CK_OBJECT_CLASS klass = CKO_G_COLLECTION;
+ const gchar *identifier;
+ GckObject *object;
+ CK_BBOOL token = CK_TRUE;
+ CK_RV rv;
+
+ CK_ATTRIBUTE attrs[] = {
+ { CKA_CLASS, &klass, sizeof (klass) },
+ { CKA_TOKEN, &token, sizeof (token) },
+ { CKA_LABEL, "blah", 4 },
+ };
+
+ rv = gck_session_create_object_for_factory (session, GCK_FACTORY_SECRET_COLLECTION,
+ attrs, G_N_ELEMENTS (attrs), &object);
+ g_assert (rv == CKR_OK);
+ g_assert (GCK_IS_SECRET_COLLECTION (object));
+
+ identifier = gck_secret_object_get_identifier (GCK_SECRET_OBJECT (object));
+ g_assert (strstr (identifier, "blah"));
+}
+
+DEFINE_TEST(secret_collection_factory_duplicate)
+{
+ CK_OBJECT_CLASS klass = CKO_G_COLLECTION;
+ const gchar *identifier1, *identifier2;
+ GckObject *object;
+ CK_RV rv;
+
+ CK_ATTRIBUTE attrs[] = {
+ { CKA_CLASS, &klass, sizeof (klass) },
+ { CKA_LABEL, "blah", 4 },
+ };
+
+ rv = gck_session_create_object_for_factory (session, GCK_FACTORY_SECRET_COLLECTION,
+ attrs, G_N_ELEMENTS (attrs), &object);
+ g_assert (rv == CKR_OK);
+ g_assert (GCK_IS_SECRET_COLLECTION (object));
+
+ identifier1 = gck_secret_object_get_identifier (GCK_SECRET_OBJECT (object));
+ g_assert (strstr (identifier1, "blah"));
+
+ rv = gck_session_create_object_for_factory (session, GCK_FACTORY_SECRET_COLLECTION,
+ attrs, G_N_ELEMENTS (attrs), &object);
+ g_assert (rv == CKR_OK);
+ g_assert (GCK_IS_SECRET_COLLECTION (object));
+
+ identifier2 = gck_secret_object_get_identifier (GCK_SECRET_OBJECT (object));
+ g_assert (strstr (identifier2, "blah"));
+
+ g_assert_cmpstr (identifier1, !=, identifier2);
+}
+
+DEFINE_TEST(secret_collection_factory_item)
+{
+ CK_OBJECT_CLASS c_klass = CKO_G_COLLECTION;
+ CK_OBJECT_CLASS i_klass = CKO_SECRET_KEY;
+ const gchar *identifier;
+ GckObject *object;
+ CK_BBOOL token = CK_TRUE;
+ CK_RV rv;
+
+ CK_ATTRIBUTE c_attrs[] = {
+ { CKA_CLASS, &c_klass, sizeof (c_klass) },
+ { CKA_TOKEN, &token, sizeof (token) },
+ { CKA_LABEL, "three", 5 },
+ };
+
+ CK_ATTRIBUTE i_attrs[] = {
+ { CKA_G_COLLECTION, NULL, 0 }, /* Filled below */
+ { CKA_CLASS, &i_klass, sizeof (i_klass) },
+ { CKA_TOKEN, &token, sizeof (token) },
+ { CKA_LABEL, "Item", 4 },
+ };
+
+ rv = gck_session_create_object_for_factory (session, GCK_FACTORY_SECRET_COLLECTION,
+ c_attrs, G_N_ELEMENTS (c_attrs), &object);
+ g_assert (rv == CKR_OK);
+ g_assert (GCK_IS_SECRET_COLLECTION (object));
+
+ identifier = gck_secret_object_get_identifier (GCK_SECRET_OBJECT (object));
+ i_attrs[0].pValue = (gpointer)identifier;
+ i_attrs[0].ulValueLen = strlen (identifier);
+ rv = gck_session_create_object_for_factory (session, GCK_FACTORY_SECRET_ITEM,
+ i_attrs, G_N_ELEMENTS (i_attrs), &object);
+ g_assert (rv == CKR_OK);
+ g_assert (GCK_IS_SECRET_ITEM (object));
+}
+
+DEFINE_TEST(secret_collection_token_remove)
+{
+ CK_OBJECT_CLASS klass = CKO_G_COLLECTION;
+ GckTransaction *transaction;
+ GckObject *object;
+ CK_BBOOL token = CK_TRUE;
+ CK_RV rv;
+
+ CK_ATTRIBUTE attrs[] = {
+ { CKA_CLASS, &klass, sizeof (klass) },
+ { CKA_TOKEN, &token, sizeof (token) },
+ { CKA_LABEL, "blah", 4 },
+ };
+
+ rv = gck_session_create_object_for_factory (session, GCK_FACTORY_SECRET_COLLECTION,
+ attrs, G_N_ELEMENTS (attrs), &object);
+ g_assert (rv == CKR_OK);
+ g_assert (GCK_IS_SECRET_COLLECTION (object));
+
+ transaction = gck_transaction_new ();
+ gck_module_remove_token_object (module, transaction, object);
+ g_assert (!gck_transaction_get_failed (transaction));
+ gck_transaction_complete (transaction);
+ g_object_unref (transaction);
+}
+
+DEFINE_TEST(secret_collection_token_item_remove)
+{
+ CK_OBJECT_CLASS c_klass = CKO_G_COLLECTION;
+ CK_OBJECT_CLASS i_klass = CKO_SECRET_KEY;
+ GckTransaction *transaction;
+ const gchar *identifier;
+ GckObject *object;
+ CK_BBOOL token = CK_TRUE;
+ CK_RV rv;
+
+ CK_ATTRIBUTE c_attrs[] = {
+ { CKA_CLASS, &c_klass, sizeof (c_klass) },
+ { CKA_TOKEN, &token, sizeof (token) },
+ { CKA_LABEL, "three", 5 },
+ };
+
+ CK_ATTRIBUTE i_attrs[] = {
+ { CKA_G_COLLECTION, NULL, 0 }, /* Filled below */
+ { CKA_CLASS, &i_klass, sizeof (i_klass) },
+ { CKA_TOKEN, &token, sizeof (token) },
+ { CKA_LABEL, "Item", 4 },
+ };
+
+ rv = gck_session_create_object_for_factory (session, GCK_FACTORY_SECRET_COLLECTION,
+ c_attrs, G_N_ELEMENTS (c_attrs), &object);
+ g_assert (rv == CKR_OK);
+ g_assert (GCK_IS_SECRET_COLLECTION (object));
+
+ identifier = gck_secret_object_get_identifier (GCK_SECRET_OBJECT (object));
+ i_attrs[0].pValue = (gpointer)identifier;
+ i_attrs[0].ulValueLen = strlen (identifier);
+ rv = gck_session_create_object_for_factory (session, GCK_FACTORY_SECRET_ITEM,
+ i_attrs, G_N_ELEMENTS (i_attrs), &object);
+ g_assert (rv == CKR_OK);
+ g_assert (GCK_IS_SECRET_ITEM (object));
+
+ transaction = gck_transaction_new ();
+ gck_module_remove_token_object (module, transaction, object);
+ g_assert (!gck_transaction_get_failed (transaction));
+ gck_transaction_complete (transaction);
+ g_object_unref (transaction);
+}
diff --git a/pkcs11/secret-store/tests/unit-test-secret-item.c b/pkcs11/secret-store/tests/unit-test-secret-item.c
index c77a75d..fb5eb9b 100644
--- a/pkcs11/secret-store/tests/unit-test-secret-item.c
+++ b/pkcs11/secret-store/tests/unit-test-secret-item.c
@@ -85,20 +85,102 @@ unlock_collection(void)
g_object_unref (auth);
}
-DEFINE_TEST(secret_item_create)
+DEFINE_TEST(secret_item_new)
{
GckSecretItem *item;
- item = gck_secret_collection_create_item (collection, "the-identifier");
+ item = gck_secret_collection_new_item (collection, "the-identifier");
g_assert (GCK_IS_SECRET_ITEM (item));
g_assert_cmpstr (gck_secret_object_get_identifier (GCK_SECRET_OBJECT (item)), ==, "the-identifier");
}
+DEFINE_TEST(secret_item_create)
+{
+ GckTransaction *transaction;
+ GckSecretItem *item;
+
+ transaction = gck_transaction_new ();
+ item = gck_secret_collection_create_item (collection, transaction);
+ g_assert (GCK_IS_SECRET_ITEM (item));
+ g_object_ref (item);
+ g_assert (gck_secret_collection_has_item (collection, item));
+
+ gck_transaction_complete (transaction);
+ g_object_unref (transaction);
+
+ /* Should still be there */
+ g_assert (gck_secret_collection_has_item (collection, item));
+ g_object_unref (item);
+}
+
+DEFINE_TEST(secret_item_create_failed)
+{
+ GckTransaction *transaction;
+ GckSecretItem *item;
+
+ transaction = gck_transaction_new ();
+ item = gck_secret_collection_create_item (collection, transaction);
+ g_assert (GCK_IS_SECRET_ITEM (item));
+ g_object_ref (item);
+ g_assert (gck_secret_collection_has_item (collection, item));
+
+ gck_transaction_fail (transaction, CKR_GENERAL_ERROR);
+ gck_transaction_complete (transaction);
+ g_object_unref (transaction);
+
+ /* Should no longer be there */
+ g_assert (!gck_secret_collection_has_item (collection, item));
+ g_object_unref (item);
+}
+
+DEFINE_TEST(secret_item_destroy)
+{
+ GckTransaction *transaction;
+ GckSecretItem *item;
+
+ item = gck_secret_collection_new_item (collection, "the-identifier");
+ g_assert (gck_secret_collection_has_item (collection, item));
+ g_object_ref (item);
+
+ transaction = gck_transaction_new ();
+ gck_secret_collection_destroy_item (collection, transaction, item);
+ g_assert (!gck_secret_collection_has_item (collection, item));
+
+ gck_transaction_complete (transaction);
+ g_object_unref (transaction);
+
+ /* Should not be there */
+ g_assert (!gck_secret_collection_has_item (collection, item));
+ g_object_unref (item);
+}
+
+DEFINE_TEST(secret_item_destroy_failed)
+{
+ GckTransaction *transaction;
+ GckSecretItem *item;
+
+ item = gck_secret_collection_new_item (collection, "the-identifier");
+ g_assert (gck_secret_collection_has_item (collection, item));
+ g_object_ref (item);
+
+ transaction = gck_transaction_new ();
+ gck_secret_collection_destroy_item (collection, transaction, item);
+ g_assert (!gck_secret_collection_has_item (collection, item));
+
+ gck_transaction_fail (transaction, CKR_GENERAL_ERROR);
+ gck_transaction_complete (transaction);
+ g_object_unref (transaction);
+
+ /* Should be there */
+ g_assert (gck_secret_collection_has_item (collection, item));
+ g_object_unref (item);
+}
+
DEFINE_TEST(secret_item_collection_get)
{
GckSecretItem *item, *check;
- item = gck_secret_collection_create_item (collection, "the-identifier");
+ item = gck_secret_collection_new_item (collection, "the-identifier");
g_assert (GCK_IS_SECRET_ITEM (item));
check = gck_secret_collection_get_item (collection, "the-identifier");
@@ -110,9 +192,9 @@ DEFINE_TEST(secret_item_collection_items)
GList *l, *items;
const gchar *identifier;
- gck_secret_collection_create_item (collection, "one-identifier");
- gck_secret_collection_create_item (collection, "two-identifier");
- gck_secret_collection_create_item (collection, "three-identifier");
+ gck_secret_collection_new_item (collection, "one-identifier");
+ gck_secret_collection_new_item (collection, "two-identifier");
+ gck_secret_collection_new_item (collection, "three-identifier");
items = gck_secret_collection_get_items (collection);
g_assert_cmpuint (g_list_length (items), ==, 3);
@@ -131,7 +213,7 @@ DEFINE_TEST(secret_item_collection_remove)
{
GckSecretItem *item;
- item = gck_secret_collection_create_item (collection, "the-identifier");
+ item = gck_secret_collection_new_item (collection, "the-identifier");
g_assert (gck_secret_collection_get_item (collection, "the-identifier") == item);
gck_secret_collection_remove_item (collection, item);
@@ -142,7 +224,7 @@ DEFINE_TEST(secret_item_is_locked)
{
GckSecretItem *item;
- item = gck_secret_collection_create_item (collection, "the-identifier");
+ item = gck_secret_collection_new_item (collection, "the-identifier");
g_assert (gck_secret_object_is_locked (GCK_SECRET_OBJECT (item), session) ==
gck_secret_object_is_locked (GCK_SECRET_OBJECT (collection), session));
@@ -154,14 +236,14 @@ DEFINE_TEST(secret_item_is_locked)
DEFINE_TEST(secret_item_get_collection)
{
GckSecretItem *item;
- item = gck_secret_collection_create_item (collection, "the-identifier");
+ item = gck_secret_collection_new_item (collection, "the-identifier");
g_assert (gck_secret_item_get_collection (item) == collection);
}
DEFINE_TEST(secret_item_tracks_collection)
{
GckSecretItem *item;
- item = gck_secret_collection_create_item (collection, "the-identifier");
+ item = gck_secret_collection_new_item (collection, "the-identifier");
g_object_ref (item);
unlock_collection();
@@ -185,7 +267,7 @@ DEFINE_TEST(secret_item_get_set_fields)
GHashTable *check;
GckSecretItem *item;
- item = gck_secret_collection_create_item (collection, "the-identifier");
+ item = gck_secret_collection_new_item (collection, "the-identifier");
gck_secret_item_set_fields (item, fields);
gck_secret_item_set_fields (item, fields);
@@ -202,7 +284,7 @@ DEFINE_TEST(secret_item_collection_attr)
GckSecretItem *item;
CK_RV rv;
- item = gck_secret_collection_create_item (collection, "the-identifier");
+ item = gck_secret_collection_new_item (collection, "the-identifier");
rv = gck_object_get_attribute (GCK_OBJECT (item), session, &check);
g_assert (rv == CKR_OK);
g_assert (check.ulValueLen == 4);
@@ -220,7 +302,7 @@ DEFINE_TEST(secret_item_secret_attr)
unlock_collection ();
- item = gck_secret_collection_create_item (collection, "the-identifier");
+ item = gck_secret_collection_new_item (collection, "the-identifier");
gck_object_set_attribute (GCK_OBJECT (item), session, transaction, &attr);
g_assert (gck_transaction_get_failed (transaction) == FALSE);
gck_transaction_complete (transaction);
@@ -243,7 +325,7 @@ DEFINE_TEST(secret_item_secret_attr_locked)
GckSecretItem *item;
CK_RV rv;
- item = gck_secret_collection_create_item (collection, "the-identifier");
+ item = gck_secret_collection_new_item (collection, "the-identifier");
gck_object_set_attribute (GCK_OBJECT (item), session, transaction, &attr);
g_assert (gck_transaction_get_failed (transaction) == TRUE);
gck_transaction_complete (transaction);
@@ -268,7 +350,7 @@ DEFINE_TEST(secret_item_fields_attr)
unlock_collection ();
- item = gck_secret_collection_create_item (collection, "the-identifier");
+ item = gck_secret_collection_new_item (collection, "the-identifier");
gck_object_set_attribute (GCK_OBJECT (item), session, transaction, &attr);
g_assert (gck_transaction_get_failed (transaction) == FALSE);
gck_transaction_complete (transaction);
@@ -295,7 +377,7 @@ DEFINE_TEST(secret_item_fields_attr_locked)
CK_ATTRIBUTE attr = { CKA_G_FIELDS, "name1\0value1\0name2\0value2", 26 };
GckSecretItem *item;
- item = gck_secret_collection_create_item (collection, "the-identifier");
+ item = gck_secret_collection_new_item (collection, "the-identifier");
gck_object_set_attribute (GCK_OBJECT (item), session, transaction, &attr);
g_assert (gck_transaction_get_failed (transaction) == TRUE);
gck_transaction_complete (transaction);
@@ -316,7 +398,7 @@ DEFINE_TEST(secret_item_fields_attr_reverts)
unlock_collection ();
- item = gck_secret_collection_create_item (collection, "the-identifier");
+ item = gck_secret_collection_new_item (collection, "the-identifier");
/* Set the old value like so */
fields = gck_secret_fields_new ();
diff --git a/pkcs11/secret-store/tests/unit-test-secret-search.c b/pkcs11/secret-store/tests/unit-test-secret-search.c
index 2aafcb5..8a51591 100644
--- a/pkcs11/secret-store/tests/unit-test-secret-search.c
+++ b/pkcs11/secret-store/tests/unit-test-secret-search.c
@@ -64,7 +64,7 @@ DEFINE_SETUP(secret_search)
NULL);
/* Create an item */
- item = gck_secret_collection_create_item (collection, "test-item");
+ item = gck_secret_collection_new_item (collection, "test-item");
fields = gck_secret_fields_new ();
gck_secret_fields_add (fields, "name1", "value1");
gck_secret_fields_add (fields, "name2", "value2");
@@ -331,7 +331,7 @@ DEFINE_TEST(create_search_for_collection_no_match)
"manager", gck_session_get_manager (session),
"identifier", "other-collection",
NULL);
- oitem = gck_secret_collection_create_item (ocoll, "other-item");
+ oitem = gck_secret_collection_new_item (ocoll, "other-item");
gck_object_expose (GCK_OBJECT (ocoll), TRUE);
/* Make it match, but remember, wrong collection*/
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]