[gnome-keyring/gck-work] [gck] Remove session pooling, and add concept of module list.
- From: Stefan Walter <stefw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-keyring/gck-work] [gck] Remove session pooling, and add concept of module list.
- Date: Sun, 1 Aug 2010 07:35:16 +0000 (UTC)
commit 28b92ce9b020dc3e1bb58eb07669f83d753c18dd
Author: Stef Walter <stef memberwebs com>
Date: Fri Jul 30 20:42:16 2010 +0200
[gck] Remove session pooling, and add concept of module list.
* Session pooling no langer necessary now that we track sessions
properly in GckObject. This was of dubious value anyway.
* Added concept of a module list.
.gitignore | 2 +-
gck/Makefile.am | 1 +
gck/gck-module.c | 477 +++---------------------------------------
gck/gck-modules.c | 221 +++++++++++++++++++
gck/gck-private.h | 8 -
gck/gck-session.c | 2 +-
gck/gck-slot.c | 44 ++---
gck/gck.h | 26 ++-
gck/tests/test-gck-crypto.c | 4 +-
gck/tests/test-gck-module.c | 9 +-
gck/tests/test-gck-session.c | 72 +------
11 files changed, 296 insertions(+), 570 deletions(-)
---
diff --git a/.gitignore b/.gitignore
index 1707eef..627c574 100644
--- a/.gitignore
+++ b/.gitignore
@@ -13,7 +13,7 @@
.anjuta*
*.tar.gz
.*project
-.settings
+.*settings
*.orig
*.stamp
.deps
diff --git a/gck/Makefile.am b/gck/Makefile.am
index 0173680..b6ed66d 100644
--- a/gck/Makefile.am
+++ b/gck/Makefile.am
@@ -21,6 +21,7 @@ libgck_la_SOURCES = \
gck-call.c \
gck-misc.c \
gck-module.c \
+ gck-modules.c \
gck-object.c \
gck-session.c \
gck-slot.c \
diff --git a/gck/gck-module.c b/gck/gck-module.c
index d194384..ef33b85 100644
--- a/gck/gck-module.c
+++ b/gck/gck-module.c
@@ -77,8 +77,7 @@ enum {
PROP_0,
PROP_PATH,
PROP_FUNCTIONS,
- PROP_POOL_SESSIONS,
- PROP_AUTO_AUTHENTICATE
+ PROP_OPTIONS
};
enum {
@@ -99,8 +98,7 @@ typedef struct _GckModulePrivate {
GckModuleData data;
GStaticMutex mutex;
gboolean finalized;
- GHashTable *open_sessions;
- gint auto_authenticate;
+ guint options;
} GckModulePrivate;
#define gck_module_GET_DATA(o) \
@@ -110,13 +108,6 @@ G_DEFINE_TYPE (GckModule, gck_module, G_TYPE_OBJECT);
static guint signals[LAST_SIGNAL] = { 0 };
-typedef struct _SessionPool {
- CK_SLOT_ID slot;
- CK_FUNCTION_LIST_PTR funcs;
- GArray *ro_sessions; /* array of CK_SESSION_HANDLE */
- GArray *rw_sessions; /* array of CK_SESSION_HANDLE */
-} SessionPool;
-
/* ----------------------------------------------------------------------------
* HELPERS
*/
@@ -164,20 +155,6 @@ unlock_mutex (void *mutex)
return CKR_OK;
}
-static void
-close_session (CK_FUNCTION_LIST_PTR funcs, CK_SESSION_HANDLE handle)
-{
- CK_RV rv;
-
- g_return_if_fail (funcs);
-
- rv = (funcs->C_CloseSession) (handle);
- if (rv != CKR_OK) {
- g_warning ("couldn't close session properly: %s",
- gck_message_from_rv (rv));
- }
-}
-
/* ----------------------------------------------------------------------------
* INTERNAL
*/
@@ -215,166 +192,6 @@ unlock_private (gpointer obj, GckModulePrivate *pv)
g_object_unref (self);
}
-static void
-free_session_pool (gpointer p)
-{
- SessionPool *pool = p;
- guint i;
-
- if (pool->ro_sessions) {
- for(i = 0; i < pool->ro_sessions->len; ++i)
- close_session (pool->funcs, g_array_index (pool->ro_sessions, CK_SESSION_HANDLE, i));
- g_array_free (pool->ro_sessions, TRUE);
- }
-
- if (pool->rw_sessions) {
- for(i = 0; i < pool->rw_sessions->len; ++i)
- close_session (pool->funcs, g_array_index (pool->rw_sessions, CK_SESSION_HANDLE, i));
- g_array_free (pool->rw_sessions, TRUE);
- }
-
- g_free (pool);
-}
-
-static gboolean
-push_session_table (GckModulePrivate *pv, CK_SLOT_ID slot, gulong flags, CK_SESSION_HANDLE handle)
-{
- SessionPool *pool;
- GArray *array;
-
- g_assert (handle);
-
- if (pv->open_sessions == NULL)
- return FALSE;
-
- pool = g_hash_table_lookup (pv->open_sessions, &slot);
- if (!pool) {
- pool = g_new0 (SessionPool, 1);
- pool->funcs = pv->data.funcs;
- g_hash_table_insert (pv->open_sessions, g_memdup (&slot, sizeof (slot)), pool);
- }
-
- if (flags & CKF_RW_SESSION) {
- if (!pool->rw_sessions)
- pool->rw_sessions = g_array_new (FALSE, TRUE, sizeof (CK_SESSION_HANDLE));
- array = pool->rw_sessions;
- } else {
- if (!pool->ro_sessions)
- pool->ro_sessions = g_array_new (FALSE, TRUE, sizeof (CK_SESSION_HANDLE));
- array = pool->ro_sessions;
- }
-
- g_array_append_val (array, handle);
- return TRUE;
-}
-
-static CK_SESSION_HANDLE
-pop_session_table (GckModulePrivate *pv, CK_SLOT_ID slot, gulong flags)
-{
- CK_SESSION_HANDLE result = 0;
- SessionPool *pool;
- GArray **array;
-
- g_return_val_if_fail (pv, 0);
-
- if (!pv->open_sessions)
- return 0;
-
- pool = g_hash_table_lookup (pv->open_sessions, &slot);
- if (pool == NULL)
- return 0;
-
- if (flags & CKF_RW_SESSION)
- array = &pool->rw_sessions;
- else
- array = &pool->ro_sessions;
-
- if (*array == NULL)
- return 0;
-
- g_assert ((*array)->len > 0);
- result = g_array_index (*array, CK_SESSION_HANDLE, (*array)->len - 1);
- g_assert (result != 0);
- g_array_remove_index_fast (*array, (*array)->len - 1);
-
- if (!(*array)->len) {
- g_array_free (*array, TRUE);
- *array = NULL;
- if (!pool->rw_sessions && !pool->ro_sessions)
- g_hash_table_remove (pv->open_sessions, &slot);
- }
-
- return result;
-}
-
-static void
-destroy_session_table (GckModulePrivate *pv)
-{
- if (pv->open_sessions)
- g_hash_table_unref (pv->open_sessions);
- pv->open_sessions = NULL;
-}
-
-static void
-create_session_table (GckModulePrivate *pv)
-{
- if (!pv->open_sessions)
- pv->open_sessions = g_hash_table_new_full (_gck_ulong_hash, _gck_ulong_equal, g_free, free_session_pool);
-}
-
-CK_SESSION_HANDLE
-_gck_module_pooled_session_handle (GckModule *self, CK_SLOT_ID slot, gulong flags)
-{
- GckModulePrivate *pv = lock_private (self);
- CK_SESSION_HANDLE handle;
-
- g_return_val_if_fail (GCK_IS_MODULE (self), 0);
-
- {
- handle = pop_session_table (pv, slot, flags);
- }
-
- unlock_private (self, pv);
-
- return handle;
-}
-
-gboolean
-_gck_module_pool_session_handle (GckSession *session, CK_SESSION_HANDLE handle, GckModule *self)
-{
- GckModuleData *data = gck_module_GET_DATA (self);
- GckModulePrivate *pv;
- CK_SESSION_INFO info;
- gboolean handled = FALSE;
- CK_RV rv;
-
- g_return_val_if_fail (GCK_IS_SESSION (session), FALSE);
- g_return_val_if_fail (GCK_IS_MODULE (self), FALSE);
-
- /* Get the session info so we know where to categorize this */
- rv = (data->funcs->C_GetSessionInfo) (handle, &info);
-
- if (rv == CKR_OK) {
-
- pv = lock_private (self);
-
- {
- /* Keep this one around for later use */
- handled = push_session_table (pv, info.slotID, info.flags, handle);
- }
-
- unlock_private (self, pv);
-
- } else {
-
- /* An already closed session, we don't want to bother with */
- if (rv == CKR_SESSION_CLOSED || rv == CKR_SESSION_HANDLE_INVALID)
- handled = TRUE;
- }
-
- return handled;
-}
-
gboolean
_gck_module_fire_authenticate_slot (GckModule *self, GckSlot *slot, gchar *label, gchar **password)
{
@@ -477,11 +294,8 @@ gck_module_get_property (GObject *obj, guint prop_id, GValue *value,
case PROP_FUNCTIONS:
g_value_set_pointer (value, gck_module_get_functions (self));
break;
- case PROP_AUTO_AUTHENTICATE:
- g_value_set_int (value, gck_module_get_auto_authenticate (self));
- break;
- case PROP_POOL_SESSIONS:
- g_value_set_boolean (value, gck_module_get_pool_sessions (self));
+ case PROP_OPTIONS:
+ g_value_set_uint (value, gck_module_get_options (self));
break;
}
}
@@ -503,11 +317,8 @@ gck_module_set_property (GObject *obj, guint prop_id, const GValue *value,
g_return_if_fail (!data->funcs);
data->funcs = g_value_get_pointer (value);
break;
- case PROP_AUTO_AUTHENTICATE:
- gck_module_set_auto_authenticate (self, g_value_get_int (value));
- break;
- case PROP_POOL_SESSIONS:
- gck_module_set_pool_sessions (self, g_value_get_boolean (value));
+ case PROP_OPTIONS:
+ gck_module_set_options (self, g_value_get_uint (value));
break;
}
}
@@ -521,8 +332,6 @@ gck_module_dispose (GObject *obj)
CK_RV rv;
{
- destroy_session_table (pv);
-
if (!pv->finalized && data->initialized && data->funcs) {
finalize = TRUE;
pv->finalized = TRUE;
@@ -549,8 +358,6 @@ gck_module_finalize (GObject *obj)
GckModulePrivate *pv = G_TYPE_INSTANCE_GET_PRIVATE (obj, GCK_TYPE_MODULE, GckModulePrivate);
GckModuleData *data = gck_module_GET_DATA (obj);
- g_assert (!pv->open_sessions);
-
data->funcs = NULL;
if (data->module) {
@@ -607,28 +414,16 @@ gck_module_class_init (GckModuleClass *klass)
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
/**
- * GckModule:auto-authenticate:
+ * GckModule:options:
*
- * Whether or not to automatically authenticate token objects that need
- * a C_Login call before they can be used.
+ * Various option flags related to authentication etc.
*
* The #GckModule::authenticate-object signal will be fired when an
* object needs to be authenticated.
*/
- g_object_class_install_property (gobject_class, PROP_AUTO_AUTHENTICATE,
- g_param_spec_int ("auto-authenticate", "Auto Authenticate", "Auto Login to Token when necessary",
- 0, G_MAXINT, 0, G_PARAM_READWRITE));
-
- /**
- * GckModule:pool-sessions:
- *
- * Whether or not to pool PKCS#11 sessions. When this is set, sessions
- * will be pooled and reused if their flags match when gck_slot_open_session()
- * is called.
- */
- g_object_class_install_property (gobject_class, PROP_POOL_SESSIONS,
- g_param_spec_boolean ("pool-sessions", "Pool Sessions", "Pool sessions?",
- FALSE, G_PARAM_READWRITE));
+ g_object_class_install_property (gobject_class, PROP_OPTIONS,
+ g_param_spec_uint ("options", "Options", "Module options",
+ 0, G_MAXUINT, 0, G_PARAM_READWRITE));
/**
* GckModule::authenticate-slot:
@@ -952,25 +747,23 @@ gck_module_get_functions (GckModule *self)
/**
- * gck_module_get_pool_sessions:
+ * gck_module_get_options:
* @self: The module to get setting from.
*
- * Get the reuse sessions setting. When this is set, sessions
- * will be pooled and reused if their flags match when
- * gck_slot_open_session() is called.
+ * Get the various module options, such as auto authenticate etc.
*
- * Return value: Whether reusing sessions or not.
+ * Return value: The module options.
**/
-gboolean
-gck_module_get_pool_sessions (GckModule *self)
+guint
+gck_module_get_options (GckModule *self)
{
GckModulePrivate *pv = lock_private (self);
- gboolean ret;
+ guint ret;
g_return_val_if_fail (pv, FALSE);
{
- ret = pv->open_sessions != NULL;
+ ret = pv->options;
}
unlock_private (self, pv);
@@ -979,253 +772,41 @@ gck_module_get_pool_sessions (GckModule *self)
}
/**
- * gck_module_set_pool_sessions:
+ * gck_module_set_options:
* @self: The module to set the setting on.
- * @pool: Whether to reuse sessions or not.
- *
- * When this is set, sessions will be pooled and reused
- * if their flags match when gck_slot_open_session() is called.
+ * @options: Authentication and other options..
**/
void
-gck_module_set_pool_sessions (GckModule *self, gboolean pool)
+gck_module_set_options (GckModule *self, guint options)
{
GckModulePrivate *pv = lock_private (self);
g_return_if_fail (pv);
{
- if (pool)
- create_session_table (pv);
- else
- destroy_session_table (pv);
- }
-
- unlock_private (self, pv);
- g_object_notify (G_OBJECT (self), "pool-sessions");
-}
-
-/**
- * gck_module_get_auto_authenticate:
- * @self: The module to get setting from.
- *
- * Get the auto login setting. When this is set, this slot
- * will emit the 'authenticate-slot' signal when a session
- * requires authentication, and the 'authenticate-object'
- * signal when an object requires authintication.
- *
- * Return value: Whether auto login or not.
- **/
-gint
-gck_module_get_auto_authenticate (GckModule *self)
-{
- GckModulePrivate *pv = lock_private (self);
- gint ret;
-
- g_return_val_if_fail (pv, FALSE);
-
- {
- ret = pv->auto_authenticate;
+ pv->options = options;
}
unlock_private (self, pv);
-
- return ret;
+ g_object_notify (G_OBJECT (self), "options");
}
/**
- * gck_module_set_auto_authenticate:
- * @self: The module to set the setting on.
- * @auto_authenticate: Whether auto login or not.
- *
- * When this is set, this slot
- * will emit the 'authenticate-slot' signal when a session
- * requires authentication, and the 'authenticate-object'
- * signal when an object requires authintication.
+ * gck_module_add_options:
+ * @self: The module to add the option on.
+ * @options: Authentication and other options..
**/
void
-gck_module_set_auto_authenticate (GckModule *self, gint auto_authenticate)
+gck_module_add_options (GckModule *self, guint options)
{
GckModulePrivate *pv = lock_private (self);
- /* HACK: Get needed fix around API freeze. */
- if (auto_authenticate == 1)
- auto_authenticate = GCK_AUTHENTICATE_TOKENS | GCK_AUTHENTICATE_OBJECTS;
-
g_return_if_fail (pv);
{
- pv->auto_authenticate = auto_authenticate;
+ pv->options |= options;
}
unlock_private (self, pv);
- g_object_notify (G_OBJECT (self), "auto-authenticate");
-}
-
-/**
- * gck_module_enumerate_objects:
- * @self: The module to enumerate objects.
- * @func: Function to call for each object.
- * @user_data: Data to pass to the function.
- * @...: The arguments must be triples of: attribute type, data type, value.
- *
- * Call a function for every matching object on the module. This call may
- * block for an indefinite period.
- *
- *
- * <para>The variable argument list should contain:
- * <variablelist>
- * <varlistentry>
- * <term>a)</term>
- * <listitem><para>The gulong attribute type (ie: CKA_LABEL). </para></listitem>
- * </varlistentry>
- * <varlistentry>
- * <term>b)</term>
- * <listitem><para>The attribute data type (one of GCK_BOOLEAN, GCK_ULONG,
- * GCK_STRING, GCK_DATE) orthe raw attribute value length.</para></listitem>
- * </varlistentry>
- * <varlistentry>
- * <term>c)</term>
- * <listitem><para>The attribute value, either a gboolean, gulong, gchar*, GDate* or
- * a pointer to a raw attribute value.</para></listitem>
- * </varlistentry>
- * </variablelist>
- * The variable argument list should be terminated with GCK_INVALID.</para>
- *
- * This function will open a session per slot. It's recommended that you
- * set the 'reuse-sessions' property on each slot if you'll be calling
- * it a lot.
- *
- * You can access the session in which the object was found, by using the
- * gck_object_get_session() function on the resulting objects.
- *
- * This function skips tokens that are not initialize, and makes a best effort to
- * find objects on valid tokens.
- *
- * The function can return FALSE to stop the enumeration.
- *
- * Return value: If FALSE then an error prevented all matching objects from being enumerated.
- **/
-gboolean
-gck_module_enumerate_objects (GckModule *self, GckObjectForeachFunc func,
- gpointer user_data, ...)
-{
- GckAttributes *attrs;
- GError *error = NULL;
- va_list va;
-
- va_start (va, user_data);
- attrs = gck_attributes_new_valist (g_realloc, va);
- va_end (va);
-
- gck_module_enumerate_objects_full (self, attrs, NULL, func, user_data, &error);
- gck_attributes_unref (attrs);
-
- if (error != NULL) {
- g_warning ("enumerating objects failed: %s", error->message);
- g_clear_error (&error);
- return FALSE;
- }
-
- return TRUE;
-}
-
-/**
- * gck_module_enumerate_objects_full:
- * @self: The module to enumerate objects.
- * @attrs: Attributes that the objects must have, or empty for all objects.
- * @cancellable: Optional cancellation object, or NULL.
- * @func: Function to call for each object.
- * @user_data: Data to pass to the function.
- * @error: Location to return error information.
- *
- * Call a function for every matching object on the module. This call may
- * block for an indefinite period.
- *
- * This function will open a session per slot. It's recommended that you
- * set the 'reuse-sessions' property on each slot if you'll be calling
- * it a lot.
- *
- * You can access the session in which the object was found, by using the
- * gck_object_get_session() function on the resulting objects.
- *
- * The function can return FALSE to stop the enumeration.
- *
- * Return value: If FALSE then an error prevented all matching objects from being enumerated.
- **/
-gboolean
-gck_module_enumerate_objects_full (GckModule *self, GckAttributes *attrs,
- GCancellable *cancellable, GckObjectForeachFunc func,
- gpointer user_data, GError **err)
-{
- gboolean stop = FALSE;
- gboolean ret = TRUE;
- GList *objects, *o;
- GList *slots, *l;
- GError *error = NULL;
- GckSession *session;
-
- g_return_val_if_fail (GCK_IS_MODULE (self), FALSE);
- g_return_val_if_fail (attrs, FALSE);
- g_return_val_if_fail (func, FALSE);
-
- gck_attributes_ref (attrs);
- slots = gck_module_get_slots (self, TRUE);
-
- for (l = slots; ret && !stop && l; l = g_list_next (l)) {
-
- /* TODO: We really should allow the caller to specify the flags, at least read-write */
- session = gck_slot_open_session (l->data, CKF_RW_SESSION | CKF_SERIAL_SESSION, &error);
- if (!session) {
- g_return_val_if_fail (error != NULL, FALSE);
-
- /* Ignore these errors when enumerating */
- if (g_error_matches (error, GCK_ERROR, CKR_USER_PIN_NOT_INITIALIZED)) {
- g_clear_error (&error);
-
- } else {
- ret = FALSE;
- g_propagate_error (err, error);
- error = NULL;
- }
- continue;
- }
-
- objects = gck_session_find_objects_full (session, attrs, cancellable, &error);
- if (error) {
- ret = FALSE;
- g_object_unref (session);
- g_propagate_error (err, error);
- error = NULL;
- continue;
- }
-
- for (o = objects; !stop && o; o = g_list_next (o)) {
- if (!(func)(o->data, user_data)) {
- stop = TRUE;
- break;
- }
- }
-
- g_object_unref (session);
- gck_list_unref_free (objects);
- }
-
- gck_list_unref_free (slots);
- gck_attributes_unref (attrs);
-
- return ret;
+ g_object_notify (G_OBJECT (self), "options");
}
-
-/**
- * GckObjectForeachFunc:
- * @object: The enumerated object.
- * @user_data: Data passed to enumerate function.
- *
- * This function is passed to gck_module_enumerate_objects() or a similar function.
- * It is called once for each object matched.
- *
- * The GckSession through which the object is accessible can be retrieved by calling
- * gck_object_get_session() on object.
- *
- * Returns: TRUE to continue enumerating, FALSE to stop.
- */
diff --git a/gck/gck-modules.c b/gck/gck-modules.c
new file mode 100644
index 0000000..ae70d6f
--- /dev/null
+++ b/gck/gck-modules.c
@@ -0,0 +1,221 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* gck-modules.c - the GObject PKCS#11 wrapper library
+
+ Copyright (C) 2008, 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 <nielsen memberwebs com>
+*/
+
+#include "config.h"
+
+#include "gck.h"
+#include "gck-private.h"
+#include "gck-marshal.h"
+
+#include <string.h>
+
+/**
+ * SECTION:gck-modules
+ * @title: GckModule lists
+ * @short_description: Dealing with lists of PKCS#11 modules.
+ *
+ * Xxxxx
+ */
+
+GList*
+gck_modules_get_slots (GList *modules, gboolean token_present)
+{
+ GList *result = NULL;
+ GList *m;
+
+ for (m = modules; m; m = g_list_next (m)) {
+ result = g_list_concat (result, gck_module_get_slots (m->data, token_present));
+ }
+
+ return result;
+}
+
+/**
+ * gck_modules_enumerate_objects:
+ * @modules: The modules on which to enumerate objects.
+ * @func: Function to call for each object.
+ * @user_data: Data to pass to the function.
+ * @...: The arguments must be triples of: attribute type, data type, value.
+ *
+ * Call a function for every matching object on the module. This call may
+ * block for an indefinite period.
+ *
+ * <para>The variable argument list should contain:
+ * <variablelist>
+ * <varlistentry>
+ * <term>a)</term>
+ * <listitem><para>The gulong attribute type (ie: CKA_LABEL). </para></listitem>
+ * </varlistentry>
+ * <varlistentry>
+ * <term>b)</term>
+ * <listitem><para>The attribute data type (one of GCK_BOOLEAN, GCK_ULONG,
+ * GCK_STRING, GCK_DATE) orthe raw attribute value length.</para></listitem>
+ * </varlistentry>
+ * <varlistentry>
+ * <term>c)</term>
+ * <listitem><para>The attribute value, either a gboolean, gulong, gchar*, GDate* or
+ * a pointer to a raw attribute value.</para></listitem>
+ * </varlistentry>
+ * </variablelist>
+ * The variable argument list should be terminated with GCK_INVALID.</para>
+ *
+ * This function will open a session per slot. It's recommended that you
+ * set the 'reuse-sessions' property on each slot if you'll be calling
+ * it a lot.
+ *
+ * You can access the session in which the object was found, by using the
+ * gck_object_get_session() function on the resulting objects.
+ *
+ * This function skips tokens that are not initialize, and makes a best effort to
+ * find objects on valid tokens.
+ *
+ * The function can return FALSE to stop the enumeration.
+ *
+ * Return value: If FALSE then an error prevented all matching objects from being enumerated.
+ **/
+gboolean
+gck_modules_enumerate_objects (GList *modules, GckObjectForeachFunc func,
+ gpointer user_data, ...)
+{
+ GckAttributes *attrs;
+ GError *error = NULL;
+ va_list va;
+
+ va_start (va, user_data);
+ attrs = gck_attributes_new_valist (g_realloc, va);
+ va_end (va);
+
+ gck_modules_enumerate_objects_full (modules, attrs, CKF_RW_SESSION, NULL, func, user_data, &error);
+ gck_attributes_unref (attrs);
+
+ if (error != NULL) {
+ g_warning ("enumerating objects failed: %s", error->message);
+ g_clear_error (&error);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/**
+ * gck_module_enumerate_objects_full:
+ * @self: The module to enumerate objects.
+ * @attrs: Attributes that the objects must have, or empty for all objects.
+ * @cancellable: Optional cancellation object, or NULL.
+ * @func: Function to call for each object.
+ * @user_data: Data to pass to the function.
+ * @error: Location to return error information.
+ *
+ * Call a function for every matching object on the module. This call may
+ * block for an indefinite period.
+ *
+ * This function will open a session per slot. It's recommended that you
+ * set the 'reuse-sessions' property on each slot if you'll be calling
+ * it a lot.
+ *
+ * You can access the session in which the object was found, by using the
+ * gck_object_get_session() function on the resulting objects.
+ *
+ * The function can return FALSE to stop the enumeration.
+ *
+ * Return value: If FALSE then an error prevented all matching objects from being enumerated.
+ **/
+gboolean
+gck_modules_enumerate_objects_full (GList *modules, GckAttributes *attrs, guint session_flags,
+ GCancellable *cancellable, GckObjectForeachFunc func,
+ gpointer user_data, GError **err)
+{
+ gboolean stop = FALSE;
+ gboolean ret = TRUE;
+ GList *objects, *o;
+ GList *slots, *l, *m;
+ GError *error = NULL;
+ GckSession *session;
+
+ g_return_val_if_fail (attrs, FALSE);
+ g_return_val_if_fail (func, FALSE);
+
+ gck_attributes_ref (attrs);
+
+ for (m = modules; ret && !stop && m; m = g_list_next (m)) {
+ slots = gck_module_get_slots (m->data, TRUE);
+
+ for (l = slots; ret && !stop && l; l = g_list_next (l)) {
+
+ session = gck_slot_open_session (l->data, session_flags, &error);
+ if (!session) {
+ g_return_val_if_fail (error != NULL, FALSE);
+
+ /* Ignore these errors when enumerating */
+ if (g_error_matches (error, GCK_ERROR, CKR_USER_PIN_NOT_INITIALIZED)) {
+ g_clear_error (&error);
+
+ } else {
+ ret = FALSE;
+ g_propagate_error (err, error);
+ error = NULL;
+ }
+ continue;
+ }
+
+ objects = gck_session_find_objects_full (session, attrs, cancellable, &error);
+ if (error) {
+ ret = FALSE;
+ g_object_unref (session);
+ g_propagate_error (err, error);
+ error = NULL;
+ continue;
+ }
+
+ for (o = objects; !stop && o; o = g_list_next (o)) {
+ if (!(func)(o->data, user_data)) {
+ stop = TRUE;
+ break;
+ }
+ }
+
+ g_object_unref (session);
+ gck_list_unref_free (objects);
+ }
+
+ gck_list_unref_free (slots);
+ }
+
+ gck_attributes_unref (attrs);
+
+ return ret;
+}
+
+/**
+ * GckObjectForeachFunc:
+ * @object: The enumerated object.
+ * @user_data: Data passed to enumerate function.
+ *
+ * This function is passed to gck_module_enumerate_objects() or a similar function.
+ * It is called once for each object matched.
+ *
+ * The GckSession through which the object is accessible can be retrieved by calling
+ * gck_object_get_session() on object.
+ *
+ * Returns: TRUE to continue enumerating, FALSE to stop.
+ */
diff --git a/gck/gck-private.h b/gck/gck-private.h
index f30f21c..5a337cf 100644
--- a/gck/gck-private.h
+++ b/gck/gck-private.h
@@ -72,14 +72,6 @@ gboolean _gck_module_fire_authenticate_object (GckModule *module,
gchar *label,
gchar **password);
-gboolean _gck_module_pool_session_handle (GckSession *session,
- CK_SESSION_HANDLE handle,
- GckModule *self);
-
-CK_SESSION_HANDLE _gck_module_pooled_session_handle (GckModule *module,
- CK_SLOT_ID slot,
- gulong flags);
-
/* ----------------------------------------------------------------------------
* SLOT
*/
diff --git a/gck/gck-session.c b/gck/gck-session.c
index 064a52d..73de8c8 100644
--- a/gck/gck-session.c
+++ b/gck/gck-session.c
@@ -2163,7 +2163,7 @@ authenticate_init (Authenticate *auth, GckSlot *slot, GckObject *object)
g_assert (GCK_IS_OBJECT (object));
module = gck_slot_get_module (slot);
- if (gck_module_get_auto_authenticate (module) & GCK_AUTHENTICATE_OBJECTS) {
+ if (gck_module_get_options (module) & GCK_AUTHENTICATE_OBJECTS) {
auth->state = AUTHENTICATE_CAN;
auth->protected_auth = gck_slot_has_flags (slot, CKF_PROTECTED_AUTHENTICATION_PATH);
auth->module = module;
diff --git a/gck/gck-slot.c b/gck/gck-slot.c
index e4092bf..6afe3f3 100644
--- a/gck/gck-slot.c
+++ b/gck/gck-slot.c
@@ -113,10 +113,6 @@ make_session_object (GckSlot *self, gulong flags, CK_SESSION_HANDLE handle)
session = gck_session_from_handle (self, handle);
g_return_val_if_fail (session != NULL, NULL);
- /* Session keeps a reference to module so this is safe */
- g_signal_connect (session, "discard-handle",
- G_CALLBACK (_gck_module_pool_session_handle), module);
-
g_object_unref (module);
return session;
@@ -937,9 +933,9 @@ GckSession*
gck_slot_open_session_full (GckSlot *self, gulong flags, gpointer app_data,
CK_NOTIFY notify, GCancellable *cancellable, GError **err)
{
+ OpenSession args = { GCK_ARGUMENTS_INIT, 0, };
GckSession *session = NULL;
GckModule *module = NULL;
- CK_SESSION_HANDLE handle;
CK_SLOT_ID slot_id;
flags |= CKF_SERIAL_SESSION;
@@ -949,25 +945,18 @@ gck_slot_open_session_full (GckSlot *self, gulong flags, gpointer app_data,
/* Try to use a cached session */
module = gck_slot_get_module (self);
slot_id = gck_slot_get_handle (self);
- handle = _gck_module_pooled_session_handle (module, slot_id, flags);
- if (handle != 0)
- session = make_session_object (self, flags, handle);
/* Open a new session */
- if (session == NULL) {
- OpenSession args = { GCK_ARGUMENTS_INIT, 0, };
-
- args.slot = self;
- args.flags = flags;
- args.app_data = app_data;
- args.notify = notify;
- args.password = NULL;
- args.auto_login = (gck_module_get_auto_authenticate (module) & GCK_AUTHENTICATE_TOKENS) ? TRUE : FALSE;
- args.session = 0;
-
- if (_gck_call_sync (self, perform_open_session, complete_open_session, &args, cancellable, err))
- session = make_session_object (self, flags, args.session);
- }
+ args.slot = self;
+ args.flags = flags;
+ args.app_data = app_data;
+ args.notify = notify;
+ args.password = NULL;
+ args.auto_login = (gck_module_get_options (module) & GCK_AUTHENTICATE_TOKENS) ? TRUE : FALSE;
+ args.session = 0;
+
+ if (_gck_call_sync (self, perform_open_session, complete_open_session, &args, cancellable, err))
+ session = make_session_object (self, flags, args.session);
g_object_unref (module);
g_object_unref (self);
@@ -996,7 +985,6 @@ gck_slot_open_session_async (GckSlot *self, gulong flags, gpointer app_data,
GAsyncReadyCallback callback, gpointer user_data)
{
GckModule *module = NULL;
- GckCall *call;
OpenSession *args;
CK_SLOT_ID slot_id;
@@ -1015,16 +1003,10 @@ gck_slot_open_session_async (GckSlot *self, gulong flags, gpointer app_data,
/* Try to use a cached session */
module = gck_slot_get_module (self);
slot_id = gck_slot_get_handle (self);
- args->session = _gck_module_pooled_session_handle (module, slot_id, flags);
- args->auto_login = (gck_module_get_auto_authenticate (module) & GCK_AUTHENTICATE_TOKENS) ? TRUE : FALSE;
+ args->auto_login = (gck_module_get_options (module) & GCK_AUTHENTICATE_TOKENS) ? TRUE : FALSE;
g_object_unref (module);
- call = _gck_call_async_ready (args, cancellable, callback, user_data);
- if (args->session)
- _gck_call_async_short (call, CKR_OK);
- else
- _gck_call_async_go (call);
-
+ _gck_call_async_ready_go (args, cancellable, callback, user_data);
g_object_unref (self);
}
diff --git a/gck/gck.h b/gck/gck.h
index 76905eb..bc53667 100644
--- a/gck/gck.h
+++ b/gck/gck.h
@@ -304,40 +304,44 @@ GckModuleInfo* gck_module_get_info (GckModule *self);
GList* gck_module_get_slots (GckModule *self,
gboolean token_present);
-gboolean gck_module_get_pool_sessions (GckModule *self);
+guint gck_module_get_options (GckModule *self);
-void gck_module_set_pool_sessions (GckModule *self,
- gboolean pool);
+void gck_module_set_options (GckModule *self,
+ guint options);
-gint gck_module_get_auto_authenticate (GckModule *self);
+void gck_module_add_options (GckModule *self,
+ guint options);
-void gck_module_set_auto_authenticate (GckModule *self,
- gint auto_authenticate);
+GList* gck_modules_get_slots (GList *modules,
+ gboolean token_present);
-gboolean gck_module_enumerate_objects (GckModule *self,
+gboolean gck_modules_enumerate_objects (GList *modules,
GckObjectForeachFunc func,
gpointer user_data,
...);
-gboolean gck_module_enumerate_objects_full (GckModule *self,
+gboolean gck_modules_enumerate_objects_full (GList *modules,
GckAttributes *attrs,
+ guint session_flags,
GCancellable *cancellable,
GckObjectForeachFunc func,
gpointer user_data,
GError **error);
#ifdef UNIMPLEMENTED
-void gck_module_enumerate_objects_async (GckModule *self,
+void gck_modules_enumerate_objects_async (GList *modules,
GckAttributes *attrs,
+ guint session_flags,
+ GckObjectForeachFunc func,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
-GckObject* gck_module_enumerate_objects_next (GckModule *self,
+GckObject* gck_modules_enumerate_objects_next (GList *modules,
GAsyncResult *res,
GError **error);
-void gck_module_enumerate_objects_finish (GckModule *self,
+void gck_modules_enumerate_objects_finish (GList *modules,
GAsyncResult *res,
GError **error);
#endif
diff --git a/gck/tests/test-gck-crypto.c b/gck/tests/test-gck-crypto.c
index 0bb5c9c..9e6018c 100644
--- a/gck/tests/test-gck-crypto.c
+++ b/gck/tests/test-gck-crypto.c
@@ -253,7 +253,7 @@ DEFINE_TEST(sign)
mech = gck_mechanism_new_with_param (CKM_PREFIX, "my-prefix:", 10);
/* Enable auto-login on this session, see previous test */
- gck_module_set_auto_authenticate (module, TRUE);
+ gck_module_set_options (module, GCK_AUTHENTICATE_OBJECTS);
g_signal_connect (module, "authenticate-object", G_CALLBACK (authenticate_object), NULL);
/* Find the right key */
@@ -303,7 +303,7 @@ DEFINE_TEST(verify)
mech = gck_mechanism_new_with_param (CKM_PREFIX, "my-prefix:", 10);
/* Enable auto-login on this session, shouldn't be needed */
- gck_module_set_auto_authenticate (module, TRUE);
+ gck_module_set_options (module, GCK_AUTHENTICATE_OBJECTS);
g_signal_connect (module, "authenticate-object", G_CALLBACK (authenticate_object), NULL);
/* Find the right key */
diff --git a/gck/tests/test-gck-module.c b/gck/tests/test-gck-module.c
index 122d2d6..6a3ebf9 100644
--- a/gck/tests/test-gck-module.c
+++ b/gck/tests/test-gck-module.c
@@ -126,9 +126,12 @@ DEFINE_TEST(module_enumerate)
GckSession *session;
GckAttributes *attrs;
gboolean ret;
+ GList *modules;
+
+ modules = g_list_prepend (NULL, g_object_ref (module));
attrs = gck_attributes_new ();
- ret = gck_module_enumerate_objects_full (module, attrs, NULL, for_first_object, "first", NULL);
+ ret = gck_modules_enumerate_objects_full (modules, attrs, 0, NULL, for_first_object, "first", NULL);
g_assert (ret);
g_assert_cmpint (n_objects, ==, 1);
g_assert (GCK_IS_OBJECT (last_object));
@@ -142,7 +145,7 @@ DEFINE_TEST(module_enumerate)
last_object = NULL;
n_objects = 0;
- ret = gck_module_enumerate_objects (module, for_each_object, "blah",
+ ret = gck_modules_enumerate_objects (modules, for_each_object, "blah",
CKA_CLASS, GCK_ULONG, CKO_PRIVATE_KEY,
GCK_INVALID);
g_assert (ret);
@@ -156,4 +159,6 @@ DEFINE_TEST(module_enumerate)
g_object_unref (last_object);
last_object = NULL;
n_objects = 0;
+
+ gck_list_unref_free (modules);
}
diff --git a/gck/tests/test-gck-session.c b/gck/tests/test-gck-session.c
index ff98a0a..ed00f32 100644
--- a/gck/tests/test-gck-session.c
+++ b/gck/tests/test-gck-session.c
@@ -101,66 +101,6 @@ DEFINE_TEST(open_close_session)
g_object_unref (sess);
}
-DEFINE_TEST(open_reused)
-{
- CK_OBJECT_HANDLE handle;
- GckSession *sess, *sess2;
- GAsyncResult *result = NULL;
- GError *err = NULL;
- gboolean value;
-
- g_assert (gck_module_get_pool_sessions (module) == FALSE);
- gck_module_set_pool_sessions (module, TRUE);
- g_assert (gck_module_get_pool_sessions (module) == TRUE);
- g_object_get (module, "pool-sessions", &value, NULL);
- g_assert (value == TRUE);
-
- sess = gck_slot_open_session (slot, 0, &err);
- SUCCESS_RES (sess, err);
- if (!sess) return;
-
- /* Make note of the handle we saw */
- handle = gck_session_get_handle (sess);
- g_object_unref (sess);
-
- /* Open again, and see if the same handle */
- sess = gck_slot_open_session (slot, 0, &err);
- SUCCESS_RES (sess, err);
- if (!sess) return;
- g_assert (handle == gck_session_get_handle (sess));
- g_object_unref (sess);
-
- /* Test opening async */
- gck_slot_open_session_async (slot, 0, NULL, NULL, NULL, fetch_async_result, &result);
- testing_wait_until (500);
- g_assert (result != NULL);
- sess = gck_slot_open_session_finish (slot, result, &err);
- SUCCESS_RES (sess, err);
- if (!sess) return;
- g_assert (handle == gck_session_get_handle (sess));
- g_object_unref (result);
- g_object_unref (sess);
-
- /* Test opening with different flags, a different session should be returned */
- sess = gck_slot_open_session (slot, CKF_RW_SESSION, &err);
- SUCCESS_RES (sess, err);
- if (!sess) return;
- g_assert (handle != gck_session_get_handle (sess));
-
- /* Now open a second session, with same flags, shouldn't return the same */
- sess2 = gck_slot_open_session (slot, CKF_RW_SESSION, &err);
- SUCCESS_RES (sess2, err);
- if (!sess2) return;
- g_assert (gck_session_get_handle (sess) != gck_session_get_handle (sess2));
-
- g_object_set (module, "pool-sessions", FALSE, NULL);
- g_assert (gck_module_get_pool_sessions (module) == FALSE);
-
- g_object_unref (sess);
- g_object_unref (sess2);
-}
-
-
DEFINE_TEST(init_set_pin)
{
GAsyncResult *result = NULL;
@@ -274,10 +214,10 @@ DEFINE_TEST(auto_login)
g_clear_error (&err);
/* Setup for auto login */
- g_assert (gck_module_get_auto_authenticate (module) == 0);
- gck_module_set_auto_authenticate (module, TRUE);
- g_assert (gck_module_get_auto_authenticate (module) == (GCK_AUTHENTICATE_TOKENS | GCK_AUTHENTICATE_OBJECTS));
- g_object_get (module, "auto-authenticate", &value, NULL);
+ g_assert (gck_module_get_options (module) == 0);
+ gck_module_set_options (module, GCK_AUTHENTICATE_TOKENS | GCK_AUTHENTICATE_OBJECTS);
+ g_assert (gck_module_get_options (module) == (GCK_AUTHENTICATE_TOKENS | GCK_AUTHENTICATE_OBJECTS));
+ g_object_get (module, "options", &value, NULL);
g_assert (value == (GCK_AUTHENTICATE_TOKENS | GCK_AUTHENTICATE_OBJECTS));
g_signal_connect (module, "authenticate-slot", G_CALLBACK (authenticate_token), GUINT_TO_POINTER (35));
@@ -318,6 +258,6 @@ DEFINE_TEST(auto_login)
ret = gck_session_logout (session, &err);
SUCCESS_RES (ret, err);
- g_object_set (module, "auto-authenticate", FALSE, NULL);
- g_assert (gck_module_get_auto_authenticate (module) == FALSE);
+ g_object_set (module, "options", 0, NULL);
+ g_assert_cmpuint (gck_module_get_options (module), ==, 0);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]