[gnome-keyring/dbus-api] [secret-store] Complete basic GckSecretCollection, and test.
- From: Stefan Walter <stefw src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [gnome-keyring/dbus-api] [secret-store] Complete basic GckSecretCollection, and test.
- Date: Tue, 11 Aug 2009 03:50:56 +0000 (UTC)
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]