[gnome-keyring/dbus-api] [secret-store] Complete basic GckSecretCollection, and test.



commit ae1a21d1c358a58b4609011ddf2975d8062e5bf1
Author: Stef Walter <stef memberwebs com>
Date:   Tue Aug 11 03:49:42 2009 +0000

    [secret-store] Complete basic GckSecretCollection, and test.
    
    Complete all basic methods for GckSecretCollection and add unit tests.
    No actual parsing of keyrings is hooked in yet.

 pkcs11/secret-store/gck-secret-binary.c            |    1 -
 pkcs11/secret-store/gck-secret-collection.c        |  199 ++++++++++++--------
 pkcs11/secret-store/gck-secret-collection.h        |   14 +--
 pkcs11/secret-store/gck-secret-textual.c           |    1 -
 pkcs11/secret-store/tests/Makefile.am              |    1 +
 .../tests/unit-test-secret-collection.c            |   95 ++++++++++
 6 files changed, 223 insertions(+), 88 deletions(-)
---
diff --git a/pkcs11/secret-store/gck-secret-binary.c b/pkcs11/secret-store/gck-secret-binary.c
index d07a418..a17927c 100644
--- a/pkcs11/secret-store/gck-secret-binary.c
+++ b/pkcs11/secret-store/gck-secret-binary.c
@@ -571,7 +571,6 @@ gck_secret_binary_write (GckSecretCollection *collection, GckSecret *master,
 
 	/* In case the world changes on us... */
 	g_return_val_if_fail (gcry_md_get_algo_dlen (GCRY_MD_MD5) == sizeof (digest), GCK_DATA_FAILURE);
-	g_return_val_if_fail (gck_secret_collection_get_state (collection) == GCK_SECRET_COMPLETE, GCK_DATA_FAILURE);
 	
 	egg_buffer_init_full (&buffer, 256, g_realloc);
 	obj = GCK_SECRET_OBJECT (collection);
diff --git a/pkcs11/secret-store/gck-secret-collection.c b/pkcs11/secret-store/gck-secret-collection.c
index f88877d..90fdcfe 100644
--- a/pkcs11/secret-store/gck-secret-collection.c
+++ b/pkcs11/secret-store/gck-secret-collection.c
@@ -24,95 +24,103 @@
 #include "gck-secret-binary.h"
 #include "gck-secret-collection.h"
 #include "gck-secret-data.h"
+#include "gck-secret-item.h"
 #include "gck-secret-textual.h"
 
-#include "egg/egg-buffer.h"
-
-#include "gck/gck-serializable.h"
+#include "gck/gck-session.h"
 
 #include <glib/gi18n.h>
 
-enum {
-	PROP_0,
-	PROP_DATA
-};
-
 struct _GckSecretCollection {
 	GckSecretObject parent;
 	GckSecretData *data;
-	GList *items;
+	GHashTable *items;
 };
 
+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 gboolean
+find_unlocked_secret_data (GckAuthenticator *auth, GckObject *object, gpointer user_data)
+{
+	GckSecretCollection *self = GCK_SECRET_COLLECTION (object);
+	GckSecretData **result = user_data;
+	GckSecretData *sdata;
 
+	g_return_val_if_fail (!*result, FALSE);
 
-/* -----------------------------------------------------------------------------
- * OBJECT
- */
-
-static CK_RV
-gck_secret_collection_get_attribute (GckObject *base, GckSession *session, CK_ATTRIBUTE_PTR attr)
-{
-#if 0
-	GckSecretCollection *self = GCK_SECRET_COLLECTION (base);
-	
-	switch (attr->type) {
+	sdata = g_object_get_data (G_OBJECT (auth), "collection-secret-data");
+	if (sdata) {
+		g_return_val_if_fail (sdata == self->data, FALSE);
+		*result = sdata;
+		return TRUE;
 	}
-#endif	
-	return GCK_OBJECT_CLASS (gck_secret_collection_parent_class)->get_attribute (base, session, attr);
+
+	return FALSE;
 }
 
 static void
-gck_secret_collection_init (GckSecretCollection *self)
+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);
+}
+
+static void
+each_value_to_list (gpointer key, gpointer value, gpointer user_data)
+{
+	GList **list = user_data;
+	*list = g_list_prepend (*list, value);
 }
 
-static GObject*
-gck_secret_collection_constructor (GType type, guint n_props, GObjectConstructParam *props)
+/* -----------------------------------------------------------------------------
+ * OBJECT
+ */
+
+static CK_RV
+gck_secret_collection_real_unlock (GckObject *obj, GckAuthenticator *auth)
 {
-	GckSecretCollection *self = GCK_SECRET_COLLECTION (G_OBJECT_CLASS (gck_secret_collection_parent_class)->constructor(type, n_props, props));
-	g_return_val_if_fail (self, NULL);
+	GckSecretCollection *self = GCK_SECRET_COLLECTION (obj);
+	GckSecretData *sdata;
+
+	sdata = g_object_new (GCK_TYPE_SECRET_DATA, NULL);
+
+	/* TODO: Implement actual unlock work here */
 
-	return G_OBJECT (self);
+	g_object_set_data_full (G_OBJECT (auth), "collection-secret-data", sdata, g_object_unref);
+	track_secret_data (self, sdata);
+
+	return CKR_OK;
 }
 
-static void
-gck_secret_collection_set_property (GObject *obj, guint prop_id, const GValue *value, 
-                                    GParamSpec *pspec)
+static gboolean
+gck_secret_collection_real_is_locked (GckSecretObject *obj, GckSession *session)
 {
 	GckSecretCollection *self = GCK_SECRET_COLLECTION (obj);
-	switch (prop_id) {
-	case PROP_DATA:
-		gck_secret_collection_set_data (self, g_value_get_object (value));
-		break;
-	default:
-		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
-		break;
-	}
+	return gck_secret_collection_unlocked_data (self, session) ? FALSE : TRUE;
 }
 
 static void
-gck_secret_collection_get_property (GObject *obj, guint prop_id, GValue *value, 
-                                    GParamSpec *pspec)
+gck_secret_collection_init (GckSecretCollection *self)
 {
-	GckSecretCollection *self = GCK_SECRET_COLLECTION (obj);
-	switch (prop_id) {
-	case PROP_DATA:
-		g_value_set_object (value, gck_secret_collection_get_data (self));
-		break;
-	default:
-		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
-		break;
-	}
+	self->items = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
 }
 
 static void
@@ -120,7 +128,8 @@ gck_secret_collection_dispose (GObject *obj)
 {
 	GckSecretCollection *self = GCK_SECRET_COLLECTION (obj);
 
-	gck_secret_collection_set_data (self, NULL);
+	track_secret_data (self, NULL);
+	g_hash_table_remove_all (self->items);
 
 	G_OBJECT_CLASS (gck_secret_collection_parent_class)->dispose (obj);
 }
@@ -132,6 +141,9 @@ gck_secret_collection_finalize (GObject *obj)
 
 	g_assert (self->data == NULL);
 
+	g_hash_table_destroy (self->items);
+	self->items = NULL;
+
 	G_OBJECT_CLASS (gck_secret_collection_parent_class)->finalize (obj);
 }
 
@@ -140,22 +152,19 @@ gck_secret_collection_class_init (GckSecretCollectionClass *klass)
 {
 	GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 	GckObjectClass *gck_class = GCK_OBJECT_CLASS (klass);
-	
+	GckSecretObjectClass *secret_class = GCK_SECRET_OBJECT_CLASS (klass);
+
 	gck_secret_collection_parent_class = g_type_class_peek_parent (klass);
-	
-	gobject_class->constructor = gck_secret_collection_constructor;
+
 	gobject_class->dispose = gck_secret_collection_dispose;
 	gobject_class->finalize = gck_secret_collection_finalize;
-	gobject_class->set_property = gck_secret_collection_set_property;
-	gobject_class->get_property = gck_secret_collection_get_property;
 
-	gck_class->get_attribute = gck_secret_collection_get_attribute;
+	gck_class->unlock = gck_secret_collection_real_unlock;
 
-	g_object_class_install_property (gobject_class, PROP_DATA,
-	           g_param_spec_object ("data", "Data", "Secret Item Data",
-	                                GCK_TYPE_SECRET_DATA, G_PARAM_READWRITE));
+	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)
 {
@@ -205,7 +214,7 @@ gck_secret_collection_serializable (GckSerializableIface *iface)
 	iface->load = gck_secret_collection_real_load;
 	iface->save = gck_secret_collection_real_save;
 }
-
+#endif
 
 /* -----------------------------------------------------------------------------
  * PUBLIC
@@ -214,28 +223,70 @@ gck_secret_collection_serializable (GckSerializableIface *iface)
 GList*
 gck_secret_collection_get_items (GckSecretCollection *self)
 {
+	GList *items = NULL;
 	g_return_val_if_fail (GCK_IS_SECRET_COLLECTION (self), NULL);
-	return g_list_copy (self->items);
+	g_hash_table_foreach (self->items, each_value_to_list, &items);
+	return items;
 }
 
-GckSecretData*
-gck_secret_collection_get_data (GckSecretCollection *self)
+GckSecretItem*
+gck_secret_collection_get_item (GckSecretCollection *self, const gchar *identifier)
 {
 	g_return_val_if_fail (GCK_IS_SECRET_COLLECTION (self), NULL);
-	return self->data;
+	g_return_val_if_fail (identifier, NULL);
+	return g_hash_table_lookup (self->items, identifier);
+}
+
+GckSecretItem*
+gck_secret_collection_create_item (GckSecretCollection *self, const gchar *identifier)
+{
+	GckSecretItem *item;
+
+	g_return_val_if_fail (GCK_IS_SECRET_COLLECTION (self), NULL);
+	g_return_val_if_fail (identifier, NULL);
+	g_return_val_if_fail (!g_hash_table_lookup (self->items, identifier), NULL);
+
+	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_hash_table_replace (self->items, g_strdup (identifier), item);
+	return item;
 }
 
 void
-gck_secret_collection_set_data (GckSecretCollection *self, GckSecretData *data)
+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));
 
-	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);
-	g_object_notify (G_OBJECT (self), "data");
+	identifier = gck_secret_object_get_identifier (GCK_SECRET_OBJECT (item));
+	g_return_if_fail (identifier);
+
+	g_hash_table_remove (self->items, identifier);
+}
+
+GckSecretData*
+gck_secret_collection_unlocked_data (GckSecretCollection *self, GckSession *session)
+{
+	GckSecretData *sdata = NULL;
+
+	g_return_val_if_fail (GCK_IS_SECRET_COLLECTION (self), NULL);
+	g_return_val_if_fail (GCK_IS_SESSION (session), NULL);
+
+	/*
+	 * 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.
+	 */
+
+	gck_session_for_each_authenticator (session, GCK_OBJECT (self),
+	                                    find_unlocked_secret_data, &sdata);
+
+	return sdata;
 }
diff --git a/pkcs11/secret-store/gck-secret-collection.h b/pkcs11/secret-store/gck-secret-collection.h
index b453c33..2bddd35 100644
--- a/pkcs11/secret-store/gck-secret-collection.h
+++ b/pkcs11/secret-store/gck-secret-collection.h
@@ -39,16 +39,8 @@ struct _GckSecretCollectionClass {
 	GckSecretObjectClass parent_class;
 };
 
-typedef enum _GckSecretState {
-	GCK_SECRET_EMPTY = 0,
-	GCK_SECRET_PARTIAL = 1,
-	GCK_SECRET_COMPLETE = 2
-} GckSecretState;
-
 GType                gck_secret_collection_get_type        (void);
 
-GckSecretState       gck_secret_collection_get_state       (GckSecretCollection *self);
-
 GList*               gck_secret_collection_get_items       (GckSecretCollection *self);
 
 GckSecretItem*       gck_secret_collection_get_item        (GckSecretCollection *self,
@@ -60,9 +52,7 @@ GckSecretItem*       gck_secret_collection_create_item     (GckSecretCollection
 void                 gck_secret_collection_remove_item     (GckSecretCollection *self,
                                                             GckSecretItem *item);
 
-GckSecretData*       gck_secret_collection_get_data        (GckSecretCollection *self);
-
-void                 gck_secret_collection_set_data        (GckSecretCollection *self,
-                                                            GckSecretData *data);
+GckSecretData*       gck_secret_collection_unlocked_data   (GckSecretCollection *self,
+                                                            GckSession *session);
 
 #endif /* __GCK_SECRET_COLLECTION_H__ */
diff --git a/pkcs11/secret-store/gck-secret-textual.c b/pkcs11/secret-store/gck-secret-textual.c
index 4b91e5f..b22defa 100644
--- a/pkcs11/secret-store/gck-secret-textual.c
+++ b/pkcs11/secret-store/gck-secret-textual.c
@@ -413,7 +413,6 @@ gck_secret_textual_write (GckSecretCollection *collection, guchar **result, gsiz
 	gint idle_timeout;
 	
 	obj = GCK_SECRET_OBJECT (collection);
-	g_return_val_if_fail (!gck_secret_collection_get_state (collection) == GCK_SECRET_COMPLETE, FALSE);
 
 	file = g_key_file_new ();
 	
diff --git a/pkcs11/secret-store/tests/Makefile.am b/pkcs11/secret-store/tests/Makefile.am
index 18a90e3..ed75635 100644
--- a/pkcs11/secret-store/tests/Makefile.am
+++ b/pkcs11/secret-store/tests/Makefile.am
@@ -1,4 +1,5 @@
 UNIT_AUTO = \
+	unit-test-secret-collection.c \
 	unit-test-secret-compat.c \
 	unit-test-secret-data.c \
 	unit-test-secret-object.c \
diff --git a/pkcs11/secret-store/tests/unit-test-secret-collection.c b/pkcs11/secret-store/tests/unit-test-secret-collection.c
new file mode 100644
index 0000000..7d1c8e4
--- /dev/null
+++ b/pkcs11/secret-store/tests/unit-test-secret-collection.c
@@ -0,0 +1,95 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* unit-test-secret-collection.c: Test the collection keyring
+
+   Copyright (C) 2009 Stefan Walter
+
+   The Gnome Keyring Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The Gnome Keyring Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the Gnome Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.
+
+   Author: Stef Walter <stef memberwebs com>
+*/
+
+#include "config.h"
+
+#include "run-auto-test.h"
+#include "test-secret-module.h"
+
+#include "gck-secret-data.h"
+#include "gck-secret-collection.h"
+
+#include "gck/gck-authenticator.h"
+#include "gck/gck-session.h"
+
+#include <glib.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+static GckModule *module = NULL;
+static GckSession *session = NULL;
+static GckSecretCollection *collection = NULL;
+
+DEFINE_SETUP(secret_collection)
+{
+	module = test_secret_module_initialize_and_enter ();
+	session = test_secret_module_open_session (TRUE);
+
+	collection = g_object_new (GCK_TYPE_SECRET_COLLECTION,
+	                           "module", module,
+	                           "identifier", "test",
+	                           NULL);
+
+	g_assert (GCK_IS_SECRET_COLLECTION (collection));
+}
+
+DEFINE_TEARDOWN(secret_collection)
+{
+	if (collection)
+		g_object_unref (collection);
+	collection = NULL;
+
+	test_secret_module_leave_and_finalize ();
+	module = NULL;
+	session = NULL;
+
+}
+
+DEFINE_TEST(secret_collection_is_locked)
+{
+	gboolean locked;
+
+	/* By default is locked */
+	locked = gck_secret_object_is_locked (GCK_SECRET_OBJECT (collection), session);
+	g_assert (locked == TRUE);
+}
+
+DEFINE_TEST(secret_collection_unlocked_data)
+{
+	GckAuthenticator *auth;
+	GckSecretData *sdata;
+	CK_RV rv;
+
+	/* Create authenticator, which unlocks collection */
+	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);
+
+	/* Collection should now be unlocked */
+	sdata = gck_secret_collection_unlocked_data (collection, session);
+	g_assert (GCK_IS_SECRET_DATA (sdata));
+	g_assert (!gck_secret_object_is_locked (GCK_SECRET_OBJECT (collection), session));
+}



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