[gnome-keyring/dbus-api] [secret-store] Complete secret search functionality and tests.
- From: Stefan Walter <stefw src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [gnome-keyring/dbus-api] [secret-store] Complete secret search functionality and tests.
- Date: Sat, 26 Sep 2009 01:55:40 +0000 (UTC)
commit 34ca11c960f2271f98d6f57fc22d0535a692ddde
Author: Stef Walter <stef memberwebs com>
Date: Sat Sep 26 01:52:55 2009 +0000
[secret-store] Complete secret search functionality and tests.
Finish up the GckSecretSearch object and add tests for all
it's functionality.
pkcs11/secret-store/gck-secret-module.c | 2 +
pkcs11/secret-store/gck-secret-search.c | 362 ++++++++++++++++++--
pkcs11/secret-store/gck-secret-search.h | 22 +-
pkcs11/secret-store/tests/Makefile.am | 1 +
.../secret-store/tests/unit-test-secret-search.c | 354 +++++++++++++++++++
5 files changed, 708 insertions(+), 33 deletions(-)
---
diff --git a/pkcs11/secret-store/gck-secret-module.c b/pkcs11/secret-store/gck-secret-module.c
index de90199..c4edbf2 100644
--- a/pkcs11/secret-store/gck-secret-module.c
+++ b/pkcs11/secret-store/gck-secret-module.c
@@ -23,6 +23,7 @@
#include "gck-secret-collection.h"
#include "gck-secret-module.h"
+#include "gck-secret-search.h"
#include "gck-secret-store.h"
#include "gck/gck-file-tracker.h"
@@ -209,6 +210,7 @@ static void
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);
}
static void
diff --git a/pkcs11/secret-store/gck-secret-search.c b/pkcs11/secret-store/gck-secret-search.c
index a1995b9..27e1860 100644
--- a/pkcs11/secret-store/gck-secret-search.c
+++ b/pkcs11/secret-store/gck-secret-search.c
@@ -1,78 +1,340 @@
-/*
+/*
* gnome-keyring
- *
+ *
* Copyright (C) 2009 Stefan Walter
- *
- * This program is free software; you can redistribute it and/or modify
+ *
+ * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
- *
+ *
* This program 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
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
+ * 02111-1307, USA.
*/
#include "config.h"
+#include "gck-secret-collection.h"
#include "gck-secret-fields.h"
+#include "gck-secret-item.h"
#include "gck-secret-search.h"
+#include "gck/gck-attributes.h"
+#include "gck/gck-manager.h"
+#include "gck/gck-module.h"
+#include "gck/gck-session.h"
+#include "gck/gck-transaction.h"
+#include "gck/gck-util.h"
+
#include "pkcs11i.h"
#include <glib/gi18n.h>
enum {
PROP_0,
+ PROP_COLLECTION,
PROP_FIELDS
};
struct _GckSecretSearch {
GckObject parent;
+ GckSecretCollection *collection;
GHashTable *fields;
GList *managers;
- GList *objects;
+ GHashTable *handles;
};
G_DEFINE_TYPE (GckSecretSearch, gck_secret_search, GCK_TYPE_OBJECT);
/* -----------------------------------------------------------------------------
- * INTERNAL
+ * INTERNAL
*/
+static gboolean
+match_object_against_criteria (GckSecretSearch *self, GckObject *object)
+{
+ GckSecretCollection *collection;
+ GckSecretItem *item;
+ GHashTable *fields;
+
+ if (!GCK_IS_SECRET_ITEM (object))
+ return FALSE;
+
+ item = GCK_SECRET_ITEM (object);
+
+ /* Collection should match unless any collection allowed */
+ collection = gck_secret_item_get_collection (item);
+ if (self->collection && collection != self->collection)
+ return FALSE;
+
+ /* Fields should match using our special algorithm */
+ fields = gck_secret_item_get_fields (item);
+ return gck_secret_fields_match (fields, self->fields);
+}
+
+static void
+on_manager_added_object (GckManager *manager, GckObject *object, gpointer user_data)
+{
+ GckSecretSearch *self = user_data;
+ CK_OBJECT_HANDLE handle;
+
+ g_return_if_fail (GCK_IS_SECRET_SEARCH (self));
+
+ handle = gck_object_get_handle (object);
+ g_return_if_fail (handle);
+
+ g_return_if_fail (g_hash_table_lookup (self->handles, &handle) == NULL);
+
+ if (match_object_against_criteria (self, object)) {
+ g_hash_table_replace (self->handles, gck_util_ulong_alloc (handle), "unused");
+ gck_object_notify_attribute (GCK_OBJECT (self), CKA_G_MATCHED);
+ }
+}
+
+static void
+on_manager_removed_object (GckManager *manager, GckObject *object, gpointer user_data)
+{
+ GckSecretSearch *self = user_data;
+ CK_OBJECT_HANDLE handle;
+
+ g_return_if_fail (GCK_IS_SECRET_SEARCH (self));
+
+ handle = gck_object_get_handle (object);
+ g_return_if_fail (handle);
+
+ if (g_hash_table_lookup (self->handles, &handle) != NULL) {
+ g_hash_table_remove (self->handles, &handle);
+ gck_object_notify_attribute (GCK_OBJECT (self), CKA_G_MATCHED);
+ }
+}
+
static void
-manager_gone_away (gpointer user_data, GObject *where_the_object_was)
+on_manager_changed_object (GckManager *manager, GckObject *object,
+ CK_ATTRIBUTE_TYPE type, gpointer user_data)
+{
+ GckSecretSearch *self = user_data;
+ CK_OBJECT_HANDLE handle;
+
+ if (type != CKA_G_FIELDS)
+ return;
+
+ g_return_if_fail (GCK_IS_SECRET_SEARCH (self));
+
+ handle = gck_object_get_handle (object);
+ g_return_if_fail (handle);
+
+ /* Should we have this object? */
+ if (match_object_against_criteria (self, object)) {
+ if (g_hash_table_lookup (self->handles, &handle) == NULL) {
+ g_hash_table_replace (self->handles, gck_util_ulong_alloc (handle), "unused");
+ gck_object_notify_attribute (GCK_OBJECT (self), CKA_G_MATCHED);
+ }
+
+ /* Should we not have this object? */
+ } else {
+ if (g_hash_table_lookup (self->handles, &handle) != NULL) {
+ g_hash_table_remove (self->handles, &handle);
+ gck_object_notify_attribute (GCK_OBJECT (self), CKA_G_MATCHED);
+ }
+ }
+}
+
+static void
+on_manager_gone_away (gpointer user_data, GObject *where_the_object_was)
{
GckSecretSearch *self = GCK_SECRET_SEARCH (user_data);
GList *l;
-
+
g_return_if_fail (self);
-
+
l = g_list_find (self->managers, where_the_object_was);
g_return_if_fail (l != NULL);
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)
+{
+ GList *objects, *o;
+ GckManager *manager;
+ GList *l;
+
+ g_assert (!self->managers);
+ self->managers = managers;
+
+ for (l = self->managers; l; l = g_list_next (l)) {
+ manager = GCK_MANAGER (l->data);
+
+ /* 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);
+
+ /* 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
+factory_create_search (GckSession *session, GckTransaction *transaction,
+ CK_ATTRIBUTE_PTR attrs, CK_ULONG n_attrs, GckObject **result)
+{
+ GckSecretCollection *collection = NULL;
+ GckSecretSearch *search;
+ GList *managers = NULL;
+ CK_ATTRIBUTE *attr;
+ GHashTable *fields;
+ GckManager *manager;
+ GckModule *module;
+ CK_RV rv;
+
+ g_return_if_fail (GCK_IS_TRANSACTION (transaction));
+ g_return_if_fail (attrs || !n_attrs);
+ g_return_if_fail (result);
+
+ /* Find the fields being requested */
+ attr = gck_attributes_find (attrs, n_attrs, CKA_G_FIELDS);
+ if (attr == NULL) {
+ gck_transaction_fail (transaction, CKR_TEMPLATE_INCOMPLETE);
+ return;
+ }
+
+ /* Parse the fields, into our internal representation */
+ rv = gck_secret_fields_parse (attr, &fields);
+ gck_attribute_consume (attr);
+ if (rv != CKR_OK) {
+ gck_transaction_fail (transaction, rv);
+ return;
+ }
+
+ 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);
+
+ /* 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);
+ gck_attribute_consume (attr);
+ if (!collection) {
+ g_hash_table_unref (fields);
+ g_list_free (managers);
+ gck_transaction_fail (transaction, CKR_TEMPLATE_INCONSISTENT);
+ return;
+ }
+ }
+
+ search = g_object_new (GCK_TYPE_SECRET_SEARCH,
+ "module", module,
+ "manager", manager,
+ "fields", fields,
+ "collection", collection,
+ NULL);
+
+ populate_search_from_managers (search, managers);
+ *result = GCK_OBJECT (search);
+}
+
+static void
+add_each_handle_to_array (gpointer key, gpointer value, gpointer user_data)
+{
+ GArray *array = user_data;
+ CK_OBJECT_HANDLE *handle = key;
+ g_array_append_val (array, *handle);
+}
+
+static CK_RV
+attribute_set_handles (GHashTable *handles, CK_ATTRIBUTE_PTR attr)
+{
+ GArray *array;
+ CK_RV rv;
+
+ g_assert (handles);
+ g_assert (attr);
+
+ /* Want the length */
+ if (!attr->pValue) {
+ attr->ulValueLen = sizeof (CK_OBJECT_HANDLE) * g_hash_table_size (handles);
+ return CKR_OK;
+ }
+
+ /* Get the actual values */
+ array = g_array_new (FALSE, TRUE, sizeof (CK_OBJECT_HANDLE));
+ g_hash_table_foreach (handles, add_each_handle_to_array, array);
+ rv = gck_attribute_set_data (attr, array->data, array->len * sizeof (CK_OBJECT_HANDLE));
+ g_array_free (array, TRUE);
+ return rv;
+}
+
/* -----------------------------------------------------------------------------
- * OBJECT
+ * OBJECT
*/
static CK_RV
gck_secret_search_get_attribute (GckObject *base, GckSession *session, CK_ATTRIBUTE_PTR attr)
{
GckSecretSearch *self = GCK_SECRET_SEARCH (base);
-
+ const gchar *identifier;
+
switch (attr->type) {
+ case CKA_CLASS:
+ return gck_attribute_set_ulong (attr, CKO_G_SEARCH);
+ case CKA_MODIFIABLE:
+ return gck_attribute_set_bool (attr, CK_TRUE); /* TODO: This is needed for deleting? */
+ case CKA_G_COLLECTION:
+ if (!self->collection)
+ return gck_attribute_set_empty (attr);
+ identifier = gck_secret_object_get_identifier (GCK_SECRET_OBJECT (self->collection));
+ return gck_attribute_set_string (attr, identifier);
case CKA_G_FIELDS:
return gck_secret_fields_serialize (attr, self->fields);
+ case CKA_G_MATCHED:
+ return attribute_set_handles (self->handles, attr);
}
-
+
return GCK_OBJECT_CLASS (gck_secret_search_parent_class)->get_attribute (base, session, attr);
}
@@ -80,7 +342,7 @@ gck_secret_search_get_attribute (GckObject *base, GckSession *session, CK_ATTRIB
static void
gck_secret_search_init (GckSecretSearch *self)
{
-
+ self->handles = g_hash_table_new_full (gck_util_ulong_hash, gck_util_ulong_equal, gck_util_ulong_free, NULL);
}
static GObject*
@@ -88,18 +350,22 @@ gck_secret_search_constructor (GType type, guint n_props, GObjectConstructParam
{
GckSecretSearch *self = GCK_SECRET_SEARCH (G_OBJECT_CLASS (gck_secret_search_parent_class)->constructor(type, n_props, props));
g_return_val_if_fail (self, NULL);
-
+
g_return_val_if_fail (self->fields, NULL);
return G_OBJECT (self);
}
static void
-gck_secret_search_set_property (GObject *obj, guint prop_id, const GValue *value,
+gck_secret_search_set_property (GObject *obj, guint prop_id, const GValue *value,
GParamSpec *pspec)
{
GckSecretSearch *self = GCK_SECRET_SEARCH (obj);
switch (prop_id) {
+ case PROP_COLLECTION:
+ g_return_if_fail (!self->collection);
+ self->collection = g_value_dup_object (value);
+ break;
case PROP_FIELDS:
g_return_if_fail (!self->fields);
self->fields = g_value_dup_boxed (value);
@@ -112,11 +378,14 @@ gck_secret_search_set_property (GObject *obj, guint prop_id, const GValue *value
}
static void
-gck_secret_search_get_property (GObject *obj, guint prop_id, GValue *value,
+gck_secret_search_get_property (GObject *obj, guint prop_id, GValue *value,
GParamSpec *pspec)
{
GckSecretSearch *self = GCK_SECRET_SEARCH (obj);
switch (prop_id) {
+ case PROP_COLLECTION:
+ g_value_set_object (value, gck_secret_search_get_collection (self));
+ break;
case PROP_FIELDS:
g_return_if_fail (self->fields);
g_value_set_boxed (value, gck_secret_search_get_fields (self));
@@ -132,12 +401,20 @@ gck_secret_search_dispose (GObject *obj)
{
GckSecretSearch *self = GCK_SECRET_SEARCH (obj);
GList *l;
-
- for (l = self->managers; l; l = g_list_next (l))
- g_object_weak_unref (G_OBJECT (l->data), manager_gone_away, self);
+
+ for (l = self->managers; l; l = g_list_next (l)) {
+ g_signal_handlers_disconnect_by_func (l->data, on_manager_added_object, self);
+ g_signal_handlers_disconnect_by_func (l->data, on_manager_removed_object, self);
+ g_signal_handlers_disconnect_by_func (l->data, on_manager_changed_object, self);
+ g_object_weak_unref (G_OBJECT (l->data), on_manager_gone_away, self);
+ }
g_list_free (self->managers);
self->managers = NULL;
+ if (self->collection)
+ g_object_unref (self->collection);
+ self->collection = NULL;
+
G_OBJECT_CLASS (gck_secret_search_parent_class)->dispose (obj);
}
@@ -147,7 +424,7 @@ gck_secret_search_finalize (GObject *obj)
GckSecretSearch *self = GCK_SECRET_SEARCH (obj);
g_assert (!self->managers);
-
+
if (self->fields)
g_hash_table_destroy (self->fields);
self->fields = NULL;
@@ -160,9 +437,9 @@ gck_secret_search_class_init (GckSecretSearchClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GckObjectClass *gck_class = GCK_OBJECT_CLASS (klass);
-
+
gck_secret_search_parent_class = g_type_class_peek_parent (klass);
-
+
gobject_class->constructor = gck_secret_search_constructor;
gobject_class->dispose = gck_secret_search_dispose;
gobject_class->finalize = gck_secret_search_finalize;
@@ -170,15 +447,50 @@ gck_secret_search_class_init (GckSecretSearchClass *klass)
gobject_class->get_property = gck_secret_search_get_property;
gck_class->get_attribute = gck_secret_search_get_attribute;
+
+ g_object_class_install_property (gobject_class, PROP_COLLECTION,
+ g_param_spec_object ("collection", "Collection", "Item's Collection",
+ GCK_TYPE_SECRET_COLLECTION, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+ g_object_class_install_property (gobject_class, PROP_FIELDS,
+ g_param_spec_boxed ("fields", "Fields", "Item's fields",
+ GCK_BOXED_SECRET_FIELDS, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
}
/* -----------------------------------------------------------------------------
* PUBLIC
*/
+GckFactoryInfo*
+gck_secret_search_get_factory (void)
+{
+ static CK_OBJECT_CLASS klass = CKO_G_SEARCH;
+ static CK_BBOOL token = CK_FALSE;
+
+ static CK_ATTRIBUTE attributes[] = {
+ { CKA_CLASS, &klass, sizeof (klass) },
+ { CKA_TOKEN, &token, sizeof (token) },
+ };
+
+ static GckFactoryInfo factory = {
+ attributes,
+ G_N_ELEMENTS (attributes),
+ factory_create_search
+ };
+
+ return &factory;
+}
+
GHashTable*
gck_secret_search_get_fields (GckSecretSearch *self)
{
g_return_val_if_fail (GCK_IS_SECRET_SEARCH (self), NULL);
return self->fields;
}
+
+GckSecretCollection*
+gck_secret_search_get_collection (GckSecretSearch *self)
+{
+ g_return_val_if_fail (GCK_IS_SECRET_SEARCH (self), NULL);
+ return self->collection;
+}
diff --git a/pkcs11/secret-store/gck-secret-search.h b/pkcs11/secret-store/gck-secret-search.h
index b2d6a96..fa829cf 100644
--- a/pkcs11/secret-store/gck-secret-search.h
+++ b/pkcs11/secret-store/gck-secret-search.h
@@ -1,22 +1,22 @@
-/*
+/*
* gnome-keyring
- *
+ *
* Copyright (C) 2009 Stefan Walter
- *
- * This program is free software; you can redistribute it and/or modify
+ *
+ * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
- *
+ *
* This program 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
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
+ * 02111-1307, USA.
*/
#ifndef __GCK_SECRET_SEARCH_H__
@@ -28,6 +28,8 @@
#include <glib-object.h>
+#define GCK_FACTORY_SECRET_SEARCH (gck_secret_search_get_factory ())
+
#define GCK_TYPE_SECRET_SEARCH (gck_secret_search_get_type ())
#define GCK_SECRET_SEARCH(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCK_TYPE_SECRET_SEARCH, GckSecretSearch))
#define GCK_SECRET_SEARCH_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GCK_TYPE_SECRET_SEARCH, GckSecretSearchClass))
@@ -41,8 +43,12 @@ struct _GckSecretSearchClass {
GckObjectClass parent_class;
};
-GType gck_secret_search_get_type (void);
+GType gck_secret_search_get_type (void) G_GNUC_CONST;
+
+GckFactoryInfo* gck_secret_search_get_factory (void) G_GNUC_CONST;
GHashTable* gck_secret_search_get_fields (GckSecretSearch *self);
+GckSecretCollection* gck_secret_search_get_collection (GckSecretSearch *self);
+
#endif /* __GCK_SECRET_SEARCH_H__ */
diff --git a/pkcs11/secret-store/tests/Makefile.am b/pkcs11/secret-store/tests/Makefile.am
index a25dda0..ce80ed9 100644
--- a/pkcs11/secret-store/tests/Makefile.am
+++ b/pkcs11/secret-store/tests/Makefile.am
@@ -5,6 +5,7 @@ UNIT_AUTO = \
unit-test-secret-object.c \
unit-test-secret-collection.c \
unit-test-secret-item.c \
+ unit-test-secret-search.c \
unit-test-secret-textual.c \
unit-test-secret-binary.c \
test-secret-module.c test-secret-module.h
diff --git a/pkcs11/secret-store/tests/unit-test-secret-search.c b/pkcs11/secret-store/tests/unit-test-secret-search.c
new file mode 100644
index 0000000..9f91a2f
--- /dev/null
+++ b/pkcs11/secret-store/tests/unit-test-secret-search.c
@@ -0,0 +1,354 @@
+/* -*- 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-collection.h"
+#include "gck-secret-fields.h"
+#include "gck-secret-item.h"
+#include "gck-secret-search.h"
+
+#include "gck/gck-session.h"
+#include "gck/gck-transaction.h"
+
+#include "pkcs11/pkcs11i.h"
+
+#include <glib.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+static GckModule *module = NULL;
+static GckSession *session = NULL;
+static GckFactory factory = NULL;
+static GckSecretCollection *collection = NULL;
+static GckSecretItem *item = NULL;
+
+DEFINE_SETUP(secret_search)
+{
+ GHashTable *fields;
+
+ module = test_secret_module_initialize_and_enter ();
+ session = test_secret_module_open_session (TRUE);
+ factory = GCK_FACTORY_SECRET_SEARCH->factory;
+ g_assert (factory);
+
+ collection = g_object_new (GCK_TYPE_SECRET_COLLECTION,
+ "module", module,
+ "manager", gck_session_get_manager (session),
+ "identifier", "test-collection",
+ NULL);
+
+ /* Create an item */
+ item = gck_secret_collection_create_item (collection, "test-item");
+ fields = gck_secret_fields_new ();
+ gck_secret_fields_add (fields, "name1", "value1");
+ gck_secret_fields_add (fields, "name2", "value2");
+ gck_secret_item_set_fields (item, fields);
+ g_hash_table_unref (fields);
+
+ gck_object_expose (GCK_OBJECT (collection), TRUE);
+}
+
+DEFINE_TEARDOWN(secret_search)
+{
+ g_object_unref (collection);
+
+ test_secret_module_leave_and_finalize ();
+ module = NULL;
+ session = NULL;
+}
+
+DEFINE_TEST(create_search_incomplete)
+{
+ CK_ATTRIBUTE attrs[1];
+ GckObject *object = NULL;
+ CK_RV rv;
+
+ rv = gck_session_create_object_for_factory (session, factory, attrs, 0, &object);
+ g_assert (rv == CKR_TEMPLATE_INCOMPLETE);
+ g_assert (object == NULL);
+}
+
+DEFINE_TEST(create_search_bad_fields)
+{
+ CK_ATTRIBUTE attrs[] = {
+ { CKA_G_FIELDS, "bad-value", 9 },
+ };
+
+ GckObject *object = NULL;
+ CK_RV rv;
+
+ rv = gck_session_create_object_for_factory (session, factory, attrs, 1, &object);
+ g_assert (rv == CKR_ATTRIBUTE_VALUE_INVALID);
+ g_assert (object == NULL);
+}
+
+DEFINE_TEST(create_search)
+{
+ CK_ATTRIBUTE attrs[] = {
+ { CKA_G_FIELDS, "test\0value\0two\0value2", 22 },
+ };
+
+ GckSecretCollection *collection;
+ GckObject *object = NULL;
+ GHashTable *fields;
+ gpointer vdata;
+ gulong vulong;
+ gboolean vbool;
+ gsize vsize;
+ CK_RV rv;
+
+ rv = gck_session_create_object_for_factory (session, factory, attrs, 1, &object);
+ g_assert (rv == CKR_OK);
+ g_assert (object != NULL);
+ g_assert (GCK_IS_SECRET_SEARCH (object));
+
+ if (!gck_object_get_attribute_ulong (object, session, CKA_CLASS, &vulong))
+ g_assert_not_reached ();
+ g_assert (rv == CKR_OK);
+ g_assert (vulong == CKO_G_SEARCH);
+
+ if (!gck_object_get_attribute_boolean (object, session, CKA_MODIFIABLE, &vbool))
+ g_assert_not_reached ();
+ g_assert (rv == CKR_OK);
+ g_assert (vbool == CK_TRUE);
+
+ vdata = gck_object_get_attribute_data (object, session, CKA_G_FIELDS, &vsize);
+ g_assert (vdata);
+ g_assert (vsize == attrs[0].ulValueLen);
+ g_free (vdata);
+
+ vdata = gck_object_get_attribute_data (object, session, CKA_G_COLLECTION, &vsize);
+ g_assert (vdata);
+ g_assert (vsize == 0);
+ g_free (vdata);
+
+ /* No objects matched */
+ vdata = gck_object_get_attribute_data (object, session, CKA_G_MATCHED, &vsize);
+ g_assert (vdata);
+ g_assert (vsize == 0);
+ g_free (vdata);
+
+ /* Get the fields object and check */
+ fields = gck_secret_search_get_fields (GCK_SECRET_SEARCH (object));
+ g_assert (fields);
+ g_assert_cmpstr (gck_secret_fields_get (fields, "test"), ==, "value");
+
+ /* No collection */
+ collection = gck_secret_search_get_collection (GCK_SECRET_SEARCH (object));
+ g_assert (collection == NULL);
+}
+
+DEFINE_TEST(create_search_and_match)
+{
+ CK_ATTRIBUTE attrs[] = {
+ { CKA_G_FIELDS, "name1\0value1\0name2\0value2", 26 },
+ };
+
+ GckObject *object = NULL;
+ gpointer vdata;
+ gsize vsize;
+ CK_RV rv;
+
+ rv = gck_session_create_object_for_factory (session, factory, attrs, 1, &object);
+ g_assert (rv == CKR_OK);
+ g_assert (object != NULL);
+ g_assert (GCK_IS_SECRET_SEARCH (object));
+
+ /* One object matched */
+ vdata = gck_object_get_attribute_data (object, session, CKA_G_MATCHED, &vsize);
+ g_assert (vdata);
+ g_assert (vsize == sizeof (CK_OBJECT_HANDLE));
+ g_assert (*((CK_OBJECT_HANDLE_PTR)vdata) == gck_object_get_handle (GCK_OBJECT (item)));
+ g_free (vdata);
+}
+
+DEFINE_TEST(create_search_and_change_to_match)
+{
+ CK_ATTRIBUTE attrs[] = {
+ { CKA_G_FIELDS, "name1\0value1", 13 },
+ };
+
+ GckObject *object = NULL;
+ GHashTable *fields;
+ gpointer vdata;
+ gsize vsize;
+ CK_RV rv;
+
+ /* Make it not match */
+ fields = gck_secret_fields_new ();
+ gck_secret_item_set_fields (item, fields);
+ g_hash_table_unref (fields);
+
+ rv = gck_session_create_object_for_factory (session, factory, attrs, 1, &object);
+ g_assert (rv == CKR_OK);
+ g_assert (object != NULL);
+ g_assert (GCK_IS_SECRET_SEARCH (object));
+
+ /* Nothing matched */
+ vdata = gck_object_get_attribute_data (object, session, CKA_G_MATCHED, &vsize);
+ g_assert (vsize == 0);
+ g_free (vdata);
+
+ /* Make it match */
+ fields = gck_secret_fields_new ();
+ gck_secret_fields_add (fields, "name1", "value1");
+ gck_secret_fields_add (fields, "name2", "value2");
+ gck_secret_item_set_fields (item, fields);
+ g_hash_table_unref (fields);
+
+ /* One object matched */
+ vdata = gck_object_get_attribute_data (object, session, CKA_G_MATCHED, &vsize);
+ g_assert (vdata);
+ g_assert (vsize == sizeof (CK_OBJECT_HANDLE));
+ g_assert (*((CK_OBJECT_HANDLE_PTR)vdata) == gck_object_get_handle (GCK_OBJECT (item)));
+ g_free (vdata);
+}
+
+DEFINE_TEST(create_search_and_change_to_not_match)
+{
+ CK_ATTRIBUTE attrs[] = {
+ { CKA_G_FIELDS, "name1\0value1", 13 },
+ };
+
+ GckObject *object = NULL;
+ GHashTable *fields;
+ gpointer vdata;
+ gsize vsize;
+ CK_RV rv;
+
+ rv = gck_session_create_object_for_factory (session, factory, attrs, 1, &object);
+ g_assert (rv == CKR_OK);
+ g_assert (object != NULL);
+ g_assert (GCK_IS_SECRET_SEARCH (object));
+
+ /* One object matched */
+ vdata = gck_object_get_attribute_data (object, session, CKA_G_MATCHED, &vsize);
+ g_assert (vdata);
+ g_assert (vsize == sizeof (CK_OBJECT_HANDLE));
+ g_assert (*((CK_OBJECT_HANDLE_PTR)vdata) == gck_object_get_handle (GCK_OBJECT (item)));
+ g_free (vdata);
+
+ /* Make it not match */
+ fields = gck_secret_fields_new ();
+ gck_secret_item_set_fields (item, fields);
+ g_hash_table_unref (fields);
+
+ /* Nothing matched */
+ vdata = gck_object_get_attribute_data (object, session, CKA_G_MATCHED, &vsize);
+ g_assert (vsize == 0);
+ g_free (vdata);
+}
+
+DEFINE_TEST(create_search_for_bad_collection)
+{
+ CK_ATTRIBUTE attrs[] = {
+ { CKA_G_FIELDS, "name1\0value1", 13 },
+ { CKA_G_COLLECTION, "bad-collection", 14 },
+ };
+
+ GckObject *object = NULL;
+ CK_RV rv;
+
+ rv = gck_session_create_object_for_factory (session, factory, attrs, 2, &object);
+ g_assert (rv == CKR_TEMPLATE_INCONSISTENT);
+}
+
+DEFINE_TEST(create_search_for_collection)
+{
+ CK_ATTRIBUTE attrs[] = {
+ { CKA_G_FIELDS, "name1\0value1", 13 },
+ { CKA_G_COLLECTION, "test-collection", 15 },
+ };
+
+ GckObject *object = NULL;
+ gpointer vdata;
+ gsize vsize;
+ CK_RV rv;
+
+ rv = gck_session_create_object_for_factory (session, factory, attrs, 2, &object);
+ g_assert (rv == CKR_OK);
+ g_assert (object != NULL);
+ g_assert (GCK_IS_SECRET_SEARCH (object));
+
+ /* Should have the collection set properly */
+ vdata = gck_object_get_attribute_data (object, session, CKA_G_COLLECTION , &vsize);
+ g_assert (vdata);
+ g_assert (vsize == 15);
+ g_assert (memcmp (vdata, "test-collection", 15) == 0);
+ g_free (vdata);
+
+ /* One object matched */
+ vdata = gck_object_get_attribute_data (object, session, CKA_G_MATCHED, &vsize);
+ g_assert (vdata);
+ g_assert (vsize == sizeof (CK_OBJECT_HANDLE));
+ g_assert (*((CK_OBJECT_HANDLE_PTR)vdata) == gck_object_get_handle (GCK_OBJECT (item)));
+ g_free (vdata);
+}
+
+DEFINE_TEST(create_search_for_collection_no_match)
+{
+ CK_ATTRIBUTE attrs[] = {
+ { CKA_G_FIELDS, "test\0value", 11 },
+ { CKA_G_COLLECTION, "test-collection", 15 },
+ };
+
+ GckObject *object = NULL;
+ GckSecretCollection *ocoll;
+ GckSecretItem *oitem;
+ GHashTable *fields;
+ gpointer vdata;
+ gsize vsize;
+ CK_RV rv;
+
+ ocoll = g_object_new (GCK_TYPE_SECRET_COLLECTION,
+ "module", module,
+ "manager", gck_session_get_manager (session),
+ "identifier", "other-collection",
+ NULL);
+ oitem = gck_secret_collection_create_item (ocoll, "other-item");
+ gck_object_expose (GCK_OBJECT (ocoll), TRUE);
+
+ /* Make it match, but remember, wrong collection*/
+ fields = gck_secret_fields_new ();
+ gck_secret_fields_add (fields, "test", "value");
+ gck_secret_item_set_fields (oitem, fields);
+ g_hash_table_unref (fields);
+
+ rv = gck_session_create_object_for_factory (session, factory, attrs, 2, &object);
+ g_assert (rv == CKR_OK);
+ g_assert (object != NULL);
+ g_assert (GCK_IS_SECRET_SEARCH (object));
+
+ /* No objects matched */
+ vdata = gck_object_get_attribute_data (object, session, CKA_G_MATCHED, &vsize);
+ g_assert (vsize == 0);
+ g_free (vdata);
+
+ g_object_unref (ocoll);
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]