[gnome-keyring/dbus-api] [secret-store] Complete loading/unlocking code for GckSecretCollection.



commit 2798e6b63edc34419e0dd44f3ef6e72ab4996d13
Author: Stef Walter <stef memberwebs com>
Date:   Sat Aug 15 13:46:41 2009 +0000

    [secret-store] Complete loading/unlocking code for GckSecretCollection.
    
    Complete the loading and unlocking code for collections. Integrate loading
    properly into GckSecretModule.

 pkcs11/secret-store/gck-secret-binary.c            |   17 +-
 pkcs11/secret-store/gck-secret-collection.c        |  230 +++++++++++++++-----
 pkcs11/secret-store/gck-secret-collection.h        |    9 +
 pkcs11/secret-store/gck-secret-module.c            |   45 ++--
 pkcs11/secret-store/gck-secret-types.h             |    3 +
 .../secret-store/tests/unit-test-secret-binary.c   |   33 +++
 .../tests/unit-test-secret-collection.c            |  209 ++++++++++++++++++
 7 files changed, 471 insertions(+), 75 deletions(-)
---
diff --git a/pkcs11/secret-store/gck-secret-binary.c b/pkcs11/secret-store/gck-secret-binary.c
index e78c9d1..f21f236 100644
--- a/pkcs11/secret-store/gck-secret-binary.c
+++ b/pkcs11/secret-store/gck-secret-binary.c
@@ -375,18 +375,25 @@ static gboolean
 decrypt_buffer (EggBuffer *buffer, GckSecret *master,
 		guchar salt[8], int iterations)
 {
-	const gchar *password;
+	const gchar *password = NULL;
 	gcry_cipher_hd_t cih;
 	gcry_error_t gerr;
         guchar *key, *iv;
-        gsize n_password;
+        gsize n_password = 0;
 	size_t pos;
 
 	g_assert (buffer->len % 16 == 0);
 	g_assert (16 == gcry_cipher_get_algo_blklen (GCRY_CIPHER_AES128));
 	g_assert (16 == gcry_cipher_get_algo_keylen (GCRY_CIPHER_AES128));
 	
-	password = gck_secret_get_password (master, &n_password);
+	/* No password is set, try an null password */
+	if (master == NULL) {
+		password = NULL;
+		n_password = 0;
+	} else {
+		password = gck_secret_get_password (master, &n_password);
+	}
+
 	if (!egg_symkey_generate_simple (GCRY_CIPHER_AES128, GCRY_MD_SHA256, 
 	                                 password, n_password, salt, 8, iterations, &key, &iv))
 		return FALSE;
@@ -623,7 +630,10 @@ gck_secret_binary_write (GckSecretCollection *collection, GckSecretData *sdata,
 			     (guchar*)to_encrypt.buf + 16, to_encrypt.len - 16);
 	memcpy (to_encrypt.buf, digest, 16);
 	
+	/* If no master password is set, we shouldn't be writing binary... */
 	master = gck_secret_data_get_master (sdata);
+	g_return_val_if_fail (master, GCK_DATA_FAILURE);
+
 	if (!encrypt_buffer (&to_encrypt, master, salt, hash_iterations)) {
 		egg_buffer_uninit (&buffer);
 		egg_buffer_uninit (&to_encrypt);
@@ -911,7 +921,6 @@ gck_secret_binary_read (GckSecretCollection *collection, GckSecretData *sdata,
 
 	if (sdata != NULL) {
 		master = gck_secret_data_get_master (sdata);
-		g_return_val_if_fail (master, GCK_DATA_FAILURE);
 		if (!decrypt_buffer (&to_decrypt, master, salt, hash_iterations))
 			goto bail;
 		if (!verify_decrypted_buffer (&to_decrypt)) {
diff --git a/pkcs11/secret-store/gck-secret-collection.c b/pkcs11/secret-store/gck-secret-collection.c
index 90fdcfe..b4ab958 100644
--- a/pkcs11/secret-store/gck-secret-collection.c
+++ b/pkcs11/secret-store/gck-secret-collection.c
@@ -27,29 +27,57 @@
 #include "gck-secret-item.h"
 #include "gck-secret-textual.h"
 
+#include "gck/gck-authenticator.h"
+#include "gck/gck-secret.h"
 #include "gck/gck-session.h"
 
 #include <glib/gi18n.h>
 
+enum {
+	PROP_0,
+	PROP_FILENAME
+};
+
 struct _GckSecretCollection {
 	GckSecretObject parent;
-	GckSecretData *data;
+	GckSecretData *sdata;
 	GHashTable *items;
+	gchar *filename;
 };
 
 G_DEFINE_TYPE (GckSecretCollection, gck_secret_collection, GCK_TYPE_SECRET_OBJECT);
 
-#if 0
-static void gck_secret_collection_serializable (GckSerializableIface *iface);
-
-G_DEFINE_TYPE_EXTENDED (GckSecretCollection, gck_secret_collection, GCK_TYPE_SECRET_OBJECT, 0,
-               G_IMPLEMENT_INTERFACE (GCK_TYPE_SERIALIZABLE, gck_secret_collection_serializable));
-#endif
-
 /* -----------------------------------------------------------------------------
  * INTERNAL
  */
 
+static GckDataResult
+load_collection_and_secret_data (GckSecretCollection *self, GckSecretData *sdata,
+                                 const gchar *path)
+{
+	GckDataResult res;
+	GError *error = NULL;
+	guchar *data;
+	gsize n_data;
+
+	/* Read in the keyring */
+	if (!g_file_get_contents (path, (gchar**)&data, &n_data, &error)) {
+		g_message ("problem reading keyring: %s: %s",
+		           path, error && error->message ? error->message : "");
+		g_clear_error (&error);
+		return GCK_DATA_FAILURE;
+	}
+
+	/* Try to load from an encrypted file, and otherwise plain text */
+	res = gck_secret_binary_read (self, sdata, data, n_data);
+	if (res == GCK_DATA_UNRECOGNIZED)
+		res = gck_secret_textual_read (self, sdata, data, n_data);
+
+	g_free (data);
+
+	return res;
+}
+
 static gboolean
 find_unlocked_secret_data (GckAuthenticator *auth, GckObject *object, gpointer user_data)
 {
@@ -61,7 +89,7 @@ find_unlocked_secret_data (GckAuthenticator *auth, GckObject *object, gpointer u
 
 	sdata = g_object_get_data (G_OBJECT (auth), "collection-secret-data");
 	if (sdata) {
-		g_return_val_if_fail (sdata == self->data, FALSE);
+		g_return_val_if_fail (sdata == self->sdata, FALSE);
 		*result = sdata;
 		return TRUE;
 	}
@@ -74,13 +102,13 @@ track_secret_data (GckSecretCollection *self, GckSecretData *data)
 {
 	g_return_if_fail (GCK_IS_SECRET_COLLECTION (self));
 
-	if (self->data)
-		g_object_remove_weak_pointer (G_OBJECT (self->data),
-		                              (gpointer*)&(self->data));
-	self->data = data;
-	if (self->data)
-		g_object_add_weak_pointer (G_OBJECT (self->data),
-		                           (gpointer*)&self->data);
+	if (self->sdata)
+		g_object_remove_weak_pointer (G_OBJECT (self->sdata),
+		                              (gpointer*)&(self->sdata));
+	self->sdata = data;
+	if (self->sdata)
+		g_object_add_weak_pointer (G_OBJECT (self->sdata),
+		                           (gpointer*)&self->sdata);
 }
 
 static void
@@ -98,16 +126,58 @@ static CK_RV
 gck_secret_collection_real_unlock (GckObject *obj, GckAuthenticator *auth)
 {
 	GckSecretCollection *self = GCK_SECRET_COLLECTION (obj);
+	GckDataResult res;
 	GckSecretData *sdata;
+	GckSecret *master;
 
-	sdata = g_object_new (GCK_TYPE_SECRET_DATA, NULL);
+	master = gck_authenticator_get_login (auth);
+
+	/* Already unlocked, make sure pin matches */
+	if (self->sdata) {
+		if (!gck_secret_equal (gck_secret_data_get_master (self->sdata), master))
+			return CKR_PIN_INCORRECT;
 
-	/* TODO: Implement actual unlock work here */
+		/* Authenticator now tracks our secret data */
+		g_object_set_data_full (G_OBJECT (auth), "collection-secret-data",
+		                        g_object_ref (self->sdata), g_object_unref);
+		return CKR_OK;
+	}
 
-	g_object_set_data_full (G_OBJECT (auth), "collection-secret-data", sdata, g_object_unref);
-	track_secret_data (self, sdata);
+	/* New secret data object, setup master password */
+	sdata = g_object_new (GCK_TYPE_SECRET_DATA, NULL);
+	gck_secret_data_set_master (sdata, master);
+
+	/* Load the data from a file, and decrypt if necessary */
+	if (self->filename) {
+		res = load_collection_and_secret_data (self, sdata, self->filename);
+
+	/* No filename, password must be null */
+	} else {
+		if (gck_secret_equals (master, NULL, 0))
+			res = GCK_DATA_SUCCESS;
+		else
+			res = GCK_DATA_LOCKED;
+	}
 
-	return CKR_OK;
+	switch (res) {
+	case GCK_DATA_SUCCESS:
+		g_object_set_data_full (G_OBJECT (auth), "collection-secret-data", sdata, g_object_unref);
+		track_secret_data (self, sdata);
+		return CKR_OK;
+	case GCK_DATA_LOCKED:
+		g_object_unref (sdata);
+		return CKR_PIN_INCORRECT;
+	case GCK_DATA_UNRECOGNIZED:
+		g_object_unref (sdata);
+		g_message ("unrecognized or invalid keyring: %s", self->filename);
+		return CKR_FUNCTION_FAILED;
+	case GCK_DATA_FAILURE:
+		g_object_unref (sdata);
+		g_message ("failed to read or parse keyring: %s", self->filename);
+		return CKR_GENERAL_ERROR;
+	default:
+		g_assert_not_reached ();
+	}
 }
 
 static gboolean
@@ -123,6 +193,39 @@ gck_secret_collection_init (GckSecretCollection *self)
 	self->items = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
 }
 
+
+static void
+gck_secret_collection_set_property (GObject *obj, guint prop_id, const GValue *value,
+                                    GParamSpec *pspec)
+{
+	GckSecretCollection *self = GCK_SECRET_COLLECTION (obj);
+
+	switch (prop_id) {
+	case PROP_FILENAME:
+		gck_secret_collection_set_filename (self, g_value_get_string (value));
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+gck_secret_collection_get_property (GObject *obj, guint prop_id, GValue *value,
+                                    GParamSpec *pspec)
+{
+	GckSecretCollection *self = GCK_SECRET_COLLECTION (obj);
+
+	switch (prop_id) {
+	case PROP_FILENAME:
+		g_value_set_string (value, gck_secret_collection_get_filename (self));
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
+		break;
+	}
+}
+
 static void
 gck_secret_collection_dispose (GObject *obj)
 {
@@ -139,11 +242,14 @@ gck_secret_collection_finalize (GObject *obj)
 {
 	GckSecretCollection *self = GCK_SECRET_COLLECTION (obj);
 
-	g_assert (self->data == NULL);
+	g_assert (self->sdata == NULL);
 
 	g_hash_table_destroy (self->items);
 	self->items = NULL;
 
+	g_free (self->filename);
+	self->filename = NULL;
+
 	G_OBJECT_CLASS (gck_secret_collection_parent_class)->finalize (obj);
 }
 
@@ -156,33 +262,21 @@ gck_secret_collection_class_init (GckSecretCollectionClass *klass)
 
 	gck_secret_collection_parent_class = g_type_class_peek_parent (klass);
 
+	gobject_class->set_property = gck_secret_collection_set_property;
+	gobject_class->get_property = gck_secret_collection_get_property;
 	gobject_class->dispose = gck_secret_collection_dispose;
 	gobject_class->finalize = gck_secret_collection_finalize;
 
 	gck_class->unlock = gck_secret_collection_real_unlock;
 
 	secret_class->is_locked = gck_secret_collection_real_is_locked;
-}
-
-#if 0
-static gboolean
-gck_secret_collection_real_load (GckSerializable *base, GckSecret *login, const guchar *data, gsize n_data)
-{
-	GckSecretCollection *self = GCK_SECRET_COLLECTION (base);
-	GckDataResult res;
-
-	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);
-
-	res = gck_secret_binary_read (self, login, data, n_data);
-	if (res == GCK_DATA_UNRECOGNIZED)
-		res = gck_secret_textual_read (self, data, n_data);
 
-	/* TODO: This doesn't transfer knowledge of 'wrong password' back up */
-	return (res == GCK_DATA_SUCCESS);
+	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));
 }
 
+#if 0
 static gboolean
 gck_secret_collection_real_save (GckSerializable *base, GckSecret *login, guchar **data, gsize *n_data)
 {
@@ -194,10 +288,10 @@ gck_secret_collection_real_save (GckSerializable *base, GckSecret *login, guchar
 	g_return_val_if_fail (data, FALSE);
 	g_return_val_if_fail (n_data, FALSE);
 
-	if (!self->data)
+	if (!self->sdata)
 		g_return_val_if_reached (FALSE);
 
-	master = gck_secret_data_get_master (self->data);
+	master = gck_secret_data_get_master (self->sdata);
 	if (master == NULL)
 		res = gck_secret_textual_write (self, data, n_data);
 	else
@@ -207,19 +301,31 @@ gck_secret_collection_real_save (GckSerializable *base, GckSecret *login, guchar
 	return (res == GCK_DATA_SUCCESS);
 }
 
-static void
-gck_secret_collection_serializable (GckSerializableIface *iface)
-{
-	iface->extension = ".keyring";
-	iface->load = gck_secret_collection_real_load;
-	iface->save = gck_secret_collection_real_save;
-}
 #endif
 
 /* -----------------------------------------------------------------------------
  * PUBLIC
  */
 
+const gchar*
+gck_secret_collection_get_filename (GckSecretCollection *self)
+{
+	g_return_val_if_fail (GCK_IS_SECRET_COLLECTION (self), NULL);
+	return self->filename;
+}
+
+void
+gck_secret_collection_set_filename (GckSecretCollection *self, const gchar *filename)
+{
+	g_return_if_fail (GCK_IS_SECRET_COLLECTION (self));
+
+	if (self->filename == filename)
+		return;
+	g_free (self->filename);
+	self->filename = g_strdup (filename);
+	g_object_notify (G_OBJECT (self), "filename");
+}
+
 GList*
 gck_secret_collection_get_items (GckSecretCollection *self)
 {
@@ -282,7 +388,7 @@ gck_secret_collection_unlocked_data (GckSecretCollection *self, GckSession *sess
 	/*
 	 * Look for authenticator 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->data.
+	 * found, it should match the one we are tracking in self->sdata.
 	 */
 
 	gck_session_for_each_authenticator (session, GCK_OBJECT (self),
@@ -290,3 +396,27 @@ gck_secret_collection_unlocked_data (GckSecretCollection *self, GckSession *sess
 
 	return sdata;
 }
+
+void
+gck_secret_collection_unlocked_clear (GckSecretCollection *self)
+{
+	/*
+	 * TODO: This is a tough one to implement. I'm holding off and wondering
+	 * if we don't need it, perhaps? As it currently stands, what needs to happen
+	 * here is we need to find each and every authenticator that references the
+	 * secret data for this collection and completely delete those objects.
+	 */
+	g_warning ("Clearing of secret data needs implementing");
+	track_secret_data (self, NULL);
+}
+
+GckDataResult
+gck_secret_collection_load (GckSecretCollection *self)
+{
+	g_return_val_if_fail (GCK_IS_SECRET_COLLECTION (self), GCK_DATA_FAILURE);
+
+	if (!self->filename)
+		return GCK_DATA_SUCCESS;
+
+	return load_collection_and_secret_data (self, self->sdata, self->filename);
+}
diff --git a/pkcs11/secret-store/gck-secret-collection.h b/pkcs11/secret-store/gck-secret-collection.h
index 2bddd35..2f00cc9 100644
--- a/pkcs11/secret-store/gck-secret-collection.h
+++ b/pkcs11/secret-store/gck-secret-collection.h
@@ -41,6 +41,13 @@ struct _GckSecretCollectionClass {
 
 GType                gck_secret_collection_get_type        (void);
 
+GckDataResult        gck_secret_collection_load            (GckSecretCollection *self);
+
+const gchar*         gck_secret_collection_get_filename    (GckSecretCollection *self);
+
+void                 gck_secret_collection_set_filename    (GckSecretCollection *self,
+                                                            const gchar *filename);
+
 GList*               gck_secret_collection_get_items       (GckSecretCollection *self);
 
 GckSecretItem*       gck_secret_collection_get_item        (GckSecretCollection *self,
@@ -52,6 +59,8 @@ GckSecretItem*       gck_secret_collection_create_item     (GckSecretCollection
 void                 gck_secret_collection_remove_item     (GckSecretCollection *self,
                                                             GckSecretItem *item);
 
+void                 gck_secret_collection_unlocked_clear  (GckSecretCollection *self);
+
 GckSecretData*       gck_secret_collection_unlocked_data   (GckSecretCollection *self,
                                                             GckSession *session);
 
diff --git a/pkcs11/secret-store/gck-secret-module.c b/pkcs11/secret-store/gck-secret-module.c
index 1090d66..40cafae 100644
--- a/pkcs11/secret-store/gck-secret-module.c
+++ b/pkcs11/secret-store/gck-secret-module.c
@@ -26,7 +26,6 @@
 #include "gck-secret-store.h"
 
 #include "gck/gck-file-tracker.h"
-#include "gck/gck-serializable.h"
 
 #include <fcntl.h>
 #include <string.h>
@@ -84,55 +83,59 @@ GCK_DEFINE_MODULE (gck_secret_module, GCK_TYPE_SECRET_MODULE);
  */
 
 static void
-file_load (GckFileTracker *tracker, const gchar *path, GckSecretModule *self)
+on_file_load (GckFileTracker *tracker, const gchar *path, GckSecretModule *self)
 {
 	GckSecretCollection *collection;
-	GError *error = NULL;
 	GckManager *manager;
+	GckDataResult res;
 	gboolean created;
 	gchar *basename;
-	guchar *data;
-	gsize n_data;
 
 	manager = gck_module_get_manager (GCK_MODULE (self));
 	g_return_if_fail (manager);
 
-	/* Read in the keyring */
-	if (!g_file_get_contents (path, (gchar**)&data, &n_data, &error)) {
-		g_warning ("couldn't load keyring: %s: %s",
-		           path, error && error->message ? error->message : "");
-		return;
-	}
-
 	/* Do we have one for this path yet? */
 	basename = g_path_get_basename (path);
 	collection = g_hash_table_lookup (self->collections, basename);
 
 	if (collection == NULL) {
 		created = TRUE;
-		g_assert ("unimplemented");
-#if 0
 		collection = g_object_new (GCK_TYPE_SECRET_COLLECTION,
 		                           "module", self,
 		                           "identifier", basename,
+		                           "filename", path,
 		                           NULL);
-#endif
 	}
 
-	if (gck_serializable_load (GCK_SERIALIZABLE (collection), NULL, data, n_data)) {
+	res = gck_secret_collection_load (collection);
+
+	switch (res) {
+	case GCK_DATA_SUCCESS:
 		if (created) {
 			g_hash_table_replace (self->collections, basename, collection);
 			gck_manager_register_object (manager, GCK_OBJECT (collection));
 			basename = NULL;
 		}
+		break;
+	case GCK_DATA_LOCKED:
+		g_message ("master password for keyring changed without our knowledge: %s", path);
+		gck_secret_collection_unlocked_clear (collection);
+		break;
+	case GCK_DATA_UNRECOGNIZED:
+		g_message ("keyring was in an invalid or unrecognized format: %s", path);
+		break;
+	case GCK_DATA_FAILURE:
+		g_message ("failed to parse keyring: %s", path);
+		break;
+	default:
+		g_assert_not_reached ();
 	}
 
 	g_free (basename);
-	g_free (data);
 }
 
 static void
-file_remove (GckFileTracker *tracker, const gchar *path, GckSecretModule *self)
+on_file_remove (GckFileTracker *tracker, const gchar *path, GckSecretModule *self)
 {
 	gchar *basename;
 
@@ -194,9 +197,9 @@ gck_secret_module_constructor (GType type, guint n_props, GObjectConstructParam
 	}
 
 	self->tracker = gck_file_tracker_new (self->directory, "*.keyrings", NULL);
-	g_signal_connect (self->tracker, "file-added", G_CALLBACK (file_load), self);
-	g_signal_connect (self->tracker, "file-changed", G_CALLBACK (file_load), self);
-	g_signal_connect (self->tracker, "file-removed", G_CALLBACK (file_remove), self);
+	g_signal_connect (self->tracker, "file-added", G_CALLBACK (on_file_load), self);
+	g_signal_connect (self->tracker, "file-changed", G_CALLBACK (on_file_load), self);
+	g_signal_connect (self->tracker, "file-removed", G_CALLBACK (on_file_remove), self);
 
 	return G_OBJECT (self);
 }
diff --git a/pkcs11/secret-store/gck-secret-types.h b/pkcs11/secret-store/gck-secret-types.h
index 923cd7f..af64578 100644
--- a/pkcs11/secret-store/gck-secret-types.h
+++ b/pkcs11/secret-store/gck-secret-types.h
@@ -22,6 +22,9 @@
 #ifndef __GCK_SECRET_TYPES_H__
 #define __GCK_SECRET_TYPES_H__
 
+#include "gck/gck-types.h"
+#include "gck/gck-data-types.h"
+
 typedef struct _GckSecretCollection GckSecretCollection;
 typedef struct _GckSecretData GckSecretData;
 typedef struct _GckSecretItem GckSecretItem;
diff --git a/pkcs11/secret-store/tests/unit-test-secret-binary.c b/pkcs11/secret-store/tests/unit-test-secret-binary.c
index 7f92c5d..7393037 100644
--- a/pkcs11/secret-store/tests/unit-test-secret-binary.c
+++ b/pkcs11/secret-store/tests/unit-test-secret-binary.c
@@ -112,6 +112,39 @@ DEFINE_TEST(binary_read_wrong_format)
 	g_assert (res == GCK_DATA_UNRECOGNIZED);
 }
 
+DEFINE_TEST(binary_read_wrong_master)
+{
+	GckDataResult res;
+	GckSecret *master;
+	guchar *data;
+	gsize n_data;
+
+	master = gck_secret_new_from_password ("wrong");
+	gck_secret_data_set_master (sdata, master);
+	g_object_unref (master);
+
+	data = test_read_testdata ("encrypted.keyring", &n_data);
+	res = gck_secret_binary_read (collection, sdata, data, n_data);
+	g_free (data);
+
+	g_assert (res == GCK_DATA_LOCKED);
+}
+
+DEFINE_TEST(binary_read_sdata_but_no_master)
+{
+	GckDataResult res;
+	guchar *data;
+	gsize n_data;
+
+	gck_secret_data_set_master (sdata, NULL);
+
+	data = test_read_testdata ("encrypted.keyring", &n_data);
+	res = gck_secret_binary_read (collection, sdata, data, n_data);
+	g_free (data);
+
+	g_assert (res == GCK_DATA_LOCKED);
+}
+
 DEFINE_TEST(binary_write)
 {
 	GckDataResult res;
diff --git a/pkcs11/secret-store/tests/unit-test-secret-collection.c b/pkcs11/secret-store/tests/unit-test-secret-collection.c
index 7d1c8e4..747aedd 100644
--- a/pkcs11/secret-store/tests/unit-test-secret-collection.c
+++ b/pkcs11/secret-store/tests/unit-test-secret-collection.c
@@ -93,3 +93,212 @@ DEFINE_TEST(secret_collection_unlocked_data)
 	g_assert (GCK_IS_SECRET_DATA (sdata));
 	g_assert (!gck_secret_object_is_locked (GCK_SECRET_OBJECT (collection), session));
 }
+
+DEFINE_TEST(secret_collection_get_filename)
+{
+	GckSecretCollection *other;
+	const gchar *filename;
+
+	other = g_object_new (GCK_TYPE_SECRET_COLLECTION,
+	                      "module", module,
+	                      "identifier", "test",
+	                      "filename", "/tmp/filename.keyring",
+	                      NULL);
+
+	filename = gck_secret_collection_get_filename (other);
+	g_assert_cmpstr (filename, ==, "/tmp/filename.keyring");
+
+	g_object_unref (other);
+}
+
+DEFINE_TEST(secret_collection_set_filename)
+{
+	const gchar *filename;
+
+	gck_secret_collection_set_filename (collection, "/tmp/filename.keyring");
+
+	filename = gck_secret_collection_get_filename (collection);
+	g_assert_cmpstr (filename, ==, "/tmp/filename.keyring");
+}
+
+DEFINE_TEST(secret_collection_load_unlock_plain)
+{
+	GckAuthenticator *auth;
+	GckSecretData *sdata;
+	GckDataResult res;
+	gchar *filename;
+	CK_RV rv;
+
+	filename = g_build_filename (test_dir_testdata (), "plain.keyring", NULL);
+	gck_secret_collection_set_filename (collection, filename);
+	g_free (filename);
+
+	/* Load the data in the file */
+	res = gck_secret_collection_load (collection);
+	g_assert (res == GCK_DATA_SUCCESS);
+
+	/* Unlock the keyring, which should load again */
+	rv = gck_authenticator_create (GCK_OBJECT (collection), NULL, 0, &auth);
+	g_assert (rv == CKR_OK);
+	gck_session_add_session_object (session, NULL, GCK_OBJECT (auth));
+	g_object_unref (auth);
+
+	sdata = gck_secret_collection_unlocked_data (collection, session);
+	g_assert (sdata != NULL && GCK_IS_SECRET_DATA (sdata));
+	test_secret_collection_validate (collection, sdata);
+}
+
+DEFINE_TEST(secret_collection_load_unlock_encrypted)
+{
+	GckAuthenticator *auth;
+	GckSecretData *sdata;
+	GckDataResult res;
+	gchar *filename;
+	CK_RV rv;
+
+	filename = g_build_filename (test_dir_testdata (), "encrypted.keyring", NULL);
+	gck_secret_collection_set_filename (collection, filename);
+	g_free (filename);
+
+	/* Load the data in the file */
+	res = gck_secret_collection_load (collection);
+	g_assert (res == GCK_DATA_SUCCESS);
+
+	/* Unlock the keyring, which should load again */
+	rv = gck_authenticator_create (GCK_OBJECT (collection), (guchar*)"my-keyring-password", 19, &auth);
+	g_assert (rv == CKR_OK);
+	gck_session_add_session_object (session, NULL, GCK_OBJECT (auth));
+	g_object_unref (auth);
+
+	sdata = gck_secret_collection_unlocked_data (collection, session);
+	g_assert (sdata != NULL && GCK_IS_SECRET_DATA (sdata));
+	test_secret_collection_validate (collection, sdata);
+}
+
+DEFINE_TEST(secret_collection_load_unlock_bad_password)
+{
+	GckAuthenticator *auth;
+	GckDataResult res;
+	gchar *filename;
+	CK_RV rv;
+
+	filename = g_build_filename (test_dir_testdata (), "encrypted.keyring", NULL);
+	gck_secret_collection_set_filename (collection, filename);
+	g_free (filename);
+
+	/* Load the data in the file */
+	res = gck_secret_collection_load (collection);
+	g_assert (res == GCK_DATA_SUCCESS);
+
+	/* Unlock the keyring, which should load again */
+	rv = gck_authenticator_create (GCK_OBJECT (collection), (guchar*)"wrong", 5, &auth);
+	g_assert (rv == CKR_PIN_INCORRECT);
+}
+
+DEFINE_TEST(secret_collection_unlock_without_load)
+{
+	GckAuthenticator *auth;
+	GckSecretData *sdata;
+	gchar *filename;
+	CK_RV rv;
+
+	filename = g_build_filename (test_dir_testdata (), "encrypted.keyring", NULL);
+	gck_secret_collection_set_filename (collection, filename);
+	g_free (filename);
+
+	/* Unlock the keyring, which should load it */
+	rv = gck_authenticator_create (GCK_OBJECT (collection), (guchar*)"my-keyring-password", 19, &auth);
+	g_assert (rv == CKR_OK);
+	gck_session_add_session_object (session, NULL, GCK_OBJECT (auth));
+	g_object_unref (auth);
+
+	sdata = gck_secret_collection_unlocked_data (collection, session);
+	g_assert (sdata != NULL && GCK_IS_SECRET_DATA (sdata));
+	test_secret_collection_validate (collection, sdata);
+}
+
+DEFINE_TEST(secret_collection_twice_unlock)
+{
+	GckAuthenticator *auth;
+	GckSecretData *sdata;
+	gchar *filename;
+	CK_RV rv;
+
+	filename = g_build_filename (test_dir_testdata (), "encrypted.keyring", NULL);
+	gck_secret_collection_set_filename (collection, filename);
+	g_free (filename);
+
+	/* Unlock the keyring, which should load */
+	rv = gck_authenticator_create (GCK_OBJECT (collection), (guchar*)"my-keyring-password", 19, &auth);
+	g_assert (rv == CKR_OK);
+	gck_session_add_session_object (session, NULL, GCK_OBJECT (auth));
+	g_object_unref (auth);
+
+	/* Unlock the keyring again, which should not reload */
+	rv = gck_authenticator_create (GCK_OBJECT (collection), (guchar*)"my-keyring-password", 19, &auth);
+	g_assert (rv == CKR_OK);
+	gck_session_add_session_object (session, NULL, GCK_OBJECT (auth));
+	g_object_unref (auth);
+
+	sdata = gck_secret_collection_unlocked_data (collection, session);
+	g_assert (sdata != NULL && GCK_IS_SECRET_DATA (sdata));
+	test_secret_collection_validate (collection, sdata);
+}
+
+DEFINE_TEST(secret_collection_twice_unlock_bad_password)
+{
+	GckAuthenticator *auth;
+	GckSecretData *sdata;
+	gchar *filename;
+	CK_RV rv;
+
+	filename = g_build_filename (test_dir_testdata (), "encrypted.keyring", NULL);
+	gck_secret_collection_set_filename (collection, filename);
+	g_free (filename);
+
+	/* Unlock the keyring, which should load */
+	rv = gck_authenticator_create (GCK_OBJECT (collection), (guchar*)"my-keyring-password", 19, &auth);
+	g_assert (rv == CKR_OK);
+	gck_session_add_session_object (session, NULL, GCK_OBJECT (auth));
+	g_object_unref (auth);
+
+	/* Unlock the keyring again, wrong password */
+	rv = gck_authenticator_create (GCK_OBJECT (collection), (guchar*)"wrong", 5, &auth);
+	g_assert (rv == CKR_PIN_INCORRECT);
+
+	sdata = gck_secret_collection_unlocked_data (collection, session);
+	g_assert (sdata != NULL && GCK_IS_SECRET_DATA (sdata));
+	test_secret_collection_validate (collection, sdata);
+}
+
+DEFINE_TEST(secret_collection_memory_unlock)
+{
+	GckAuthenticator *auth;
+	GckDataResult res;
+	CK_RV rv;
+
+	/* Load the data in the file */
+	res = gck_secret_collection_load (collection);
+	g_assert (res == GCK_DATA_SUCCESS);
+
+	/* Unlock the keyring, which should load again */
+	rv = gck_authenticator_create (GCK_OBJECT (collection), NULL, 0, &auth);
+	g_assert (rv == CKR_OK);
+	gck_session_add_session_object (session, NULL, GCK_OBJECT (auth));
+	g_object_unref (auth);
+}
+
+DEFINE_TEST(secret_collection_memory_unlock_bad_password)
+{
+	GckAuthenticator *auth;
+	GckDataResult res;
+	CK_RV rv;
+
+	/* Load the data in the file */
+	res = gck_secret_collection_load (collection);
+	g_assert (res == GCK_DATA_SUCCESS);
+
+	/* Unlock the keyring, which should load again */
+	rv = gck_authenticator_create (GCK_OBJECT (collection), (guchar*)"wrong", 5, &auth);
+	g_assert (rv == CKR_PIN_INCORRECT);
+}



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