From f70667fbf2e5adc465522d12147fc51694f21944 Mon Sep 17 00:00:00 2001 From: Stef Walter Date: Sat, 18 Dec 2010 11:59:11 -0600 Subject: [PATCH] [gck] Allow enumeration over slots as well as modules. Can now enumerate object over a list of slots, as well as a list of modules. --- docs/reference/gck/gck-sections.txt | 1 + gck/gck-enumerator.c | 116 ++++++++++++++++-------------------- gck/gck-modules.c | 2 +- gck/gck-slot.c | 19 ++++++ gck/gck.h | 4 ++ gck/tests/test-gck-enumerator.c | 38 +++++++++++- 6 files changed, 113 insertions(+), 67 deletions(-) diff --git a/docs/reference/gck/gck-sections.txt b/docs/reference/gck/gck-sections.txt index 1bad963..d567b8e 100644 --- a/docs/reference/gck/gck-sections.txt +++ b/docs/reference/gck/gck-sections.txt @@ -98,6 +98,7 @@ gck_slot_get_token_info gck_slot_get_mechanisms gck_slot_get_mechanism_info gck_slot_has_flags +gck_slots_enumerate_objects gck_slot_open_session gck_slot_open_session_full gck_slot_open_session_async diff --git a/gck/gck-enumerator.c b/gck/gck-enumerator.c index 781dd90..2e39497 100644 --- a/gck/gck-enumerator.c +++ b/gck/gck-enumerator.c @@ -62,15 +62,13 @@ struct _GckEnumeratorState { gboolean authenticate; gchar *password; - /* state_module */ - GckModule *module; - /* state_slots */ GList *slots; /* state_slot */ GckSlot *slot; GckTokenInfo *token_info; + CK_FUNCTION_LIST_PTR funcs; /* state_session */ GckSession *session; @@ -90,8 +88,7 @@ struct _GckEnumeratorPrivate { G_DEFINE_TYPE (GckEnumerator, gck_enumerator, G_TYPE_OBJECT); -static gpointer state_start (GckEnumeratorState *args, gboolean forward); -static gpointer state_module (GckEnumeratorState *args, gboolean forward); +static gpointer state_modules (GckEnumeratorState *args, gboolean forward); static gpointer state_slots (GckEnumeratorState *args, gboolean forward); static gpointer state_slot (GckEnumeratorState *args, gboolean forward); static gpointer state_session (GckEnumeratorState *args, gboolean forward); @@ -123,10 +120,7 @@ cleanup_state (GckEnumeratorState *args) g_assert (args); /* Have each state cleanup */ - rewind_state (args, state_start); - - /* state_module */ - g_assert (!args->module); + rewind_state (args, state_modules); /* state_slots */ g_assert (!args->slots); @@ -134,6 +128,7 @@ cleanup_state (GckEnumeratorState *args) /* state_slot */ g_assert (!args->slot); g_assert (!args->token_info); + g_assert (!args->funcs); /* state_session */ g_assert (!args->session); @@ -166,9 +161,11 @@ cleanup_state (GckEnumeratorState *args) } static gpointer -state_start (GckEnumeratorState *args, gboolean forward) +state_modules (GckEnumeratorState *args, gboolean forward) { - g_assert (args->module == NULL); + GckModule *module; + + g_assert (args->slots == NULL); if (forward) { @@ -177,40 +174,25 @@ state_start (GckEnumeratorState *args, gboolean forward) return NULL; /* Pop off the current module */ - args->module = args->modules->data; - g_assert (GCK_IS_MODULE (args->module)); + module = args->modules->data; + g_assert (GCK_IS_MODULE (module)); args->modules = g_list_delete_link (args->modules, args->modules); - return state_module; - } - /* Should never be asked to go backward from start state */ - g_assert_not_reached (); -} - -static gpointer -state_module (GckEnumeratorState *args, gboolean forward) -{ - g_assert (args->module); - g_assert (!args->slots); - - /* module to slots state */ - if (forward) { + args->slots = gck_module_get_slots (module, TRUE); + g_object_unref (module); - args->slots = gck_module_get_slots (args->module, TRUE); return state_slots; - - /* module to start state */ - } else { - g_object_unref (args->module); - args->module = NULL; - return state_start; } + + /* Should never be asked to go backward from start state */ + g_assert_not_reached (); } static gpointer state_slots (GckEnumeratorState *args, gboolean forward) { GckSlot *slot; + GckModule *module; GckTokenInfo *token_info; g_assert (args->slot == NULL); @@ -220,7 +202,7 @@ state_slots (GckEnumeratorState *args, gboolean forward) /* If there are no more slots go back to start state */ if (!args->slots) - return rewind_state (args, state_start); + return rewind_state (args, state_modules); /* Pop the next slot off the stack */ slot = args->slots->data; @@ -230,7 +212,7 @@ state_slots (GckEnumeratorState *args, gboolean forward) if (!token_info) { g_message ("couldn't get token info while enumerating"); g_object_unref (slot); - return rewind_state (args, state_start); + return rewind_state (args, state_modules); } /* Are we trying to match the slot? */ @@ -244,43 +226,44 @@ state_slots (GckEnumeratorState *args, gboolean forward) } } + module = gck_slot_get_module (slot); + args->funcs = gck_module_get_functions (module); + g_assert (args->funcs); + g_object_unref (module); + /* We have a slot */ args->slot = slot; args->token_info = token_info; return state_slot; - /* slots state to module state */ + /* slots state to modules state */ } else { gck_list_unref_free (args->slots); args->slots = NULL; - return state_module; + return state_modules; } } static gpointer state_slot (GckEnumeratorState *args, gboolean forward) { - CK_FUNCTION_LIST_PTR funcs; CK_SESSION_HANDLE session; CK_FLAGS flags; CK_RV rv; g_assert (args->slot); - g_assert (args->module); + g_assert (args->funcs); g_assert (args->session == NULL); /* slot to session state */ if (forward) { - funcs = gck_module_get_functions (args->module); - g_return_val_if_fail (funcs, NULL); - flags = CKF_SERIAL_SESSION; if ((args->session_options & GCK_SESSION_READ_WRITE) == GCK_SESSION_READ_WRITE) flags |= CKF_RW_SESSION; - rv = (funcs->C_OpenSession) (gck_slot_get_handle (args->slot), - flags, NULL, NULL, &session); + rv = (args->funcs->C_OpenSession) (gck_slot_get_handle (args->slot), + flags, NULL, NULL, &session); if (rv != CKR_OK) { g_message ("couldn't open session on module while enumerating objects: %s", @@ -295,6 +278,7 @@ state_slot (GckEnumeratorState *args, gboolean forward) } else { g_object_unref (args->slot); args->slot = NULL; + args->funcs = NULL; gck_token_info_free (args->token_info); args->token_info = NULL; @@ -306,13 +290,12 @@ state_slot (GckEnumeratorState *args, gboolean forward) static gpointer state_session (GckEnumeratorState *args, gboolean forward) { - CK_FUNCTION_LIST_PTR funcs; GckSessionInfo *sinfo; CK_ULONG n_pin; CK_RV rv; + g_assert (args->funcs); g_assert (args->session); - g_assert (args->module); g_assert (!args->want_password); g_assert (args->token_info); @@ -344,13 +327,10 @@ state_session (GckEnumeratorState *args, gboolean forward) gck_session_info_free (sinfo); - funcs = gck_module_get_functions (args->module); - g_return_val_if_fail (funcs, NULL); - /* Try to log in */ n_pin = args->password ? strlen (args->password) : 0; - rv = (funcs->C_Login) (gck_session_get_handle (args->session), CKU_USER, - (CK_BYTE_PTR)args->password, n_pin); + rv = (args->funcs->C_Login) (gck_session_get_handle (args->session), CKU_USER, + (CK_BYTE_PTR)args->password, n_pin); /* Authentication failed, ask for a password */ if (rv == CKR_PIN_INCORRECT) { @@ -375,7 +355,6 @@ state_session (GckEnumeratorState *args, gboolean forward) static gpointer state_authenticated (GckEnumeratorState *args, gboolean forward) { - CK_FUNCTION_LIST_PTR funcs; CK_OBJECT_HANDLE objects[128]; CK_SESSION_HANDLE session; CK_ATTRIBUTE_PTR attrs; @@ -391,6 +370,7 @@ state_authenticated (GckEnumeratorState *args, gboolean forward) g_assert (args->session); g_assert (!args->want_password); g_assert (args->want_objects); + g_assert (args->funcs); if (args->match_attrs) { attrs = _gck_attributes_commit_out (args->match_attrs, &n_attrs); @@ -399,18 +379,15 @@ state_authenticated (GckEnumeratorState *args, gboolean forward) n_attrs = 0; } - funcs = gck_module_get_functions (args->module); - g_return_val_if_fail (funcs, NULL); - session = gck_session_get_handle (args->session); g_return_val_if_fail (session, NULL); /* Get all the objects */ - rv = (funcs->C_FindObjectsInit) (session, attrs, n_attrs); + rv = (args->funcs->C_FindObjectsInit) (session, attrs, n_attrs); if (rv == CKR_OK) { for(;;) { - rv = (funcs->C_FindObjects) (session, objects, G_N_ELEMENTS (objects), &count); + rv = (args->funcs->C_FindObjects) (session, objects, G_N_ELEMENTS (objects), &count); if (rv != CKR_OK || count == 0) break; @@ -419,7 +396,7 @@ state_authenticated (GckEnumeratorState *args, gboolean forward) g_array_append_vals (args->objects, objects, count); } - (funcs->C_FindObjectsFinal) (session); + (args->funcs->C_FindObjectsFinal) (session); } return state_results; @@ -481,7 +458,6 @@ gck_enumerator_init (GckEnumerator *self) self->pv = G_TYPE_INSTANCE_GET_PRIVATE (self, GCK_TYPE_ENUMERATOR, GckEnumeratorPrivate); args = g_new0 (GckEnumeratorState, 1); - args->handler = state_start; g_atomic_pointer_set (&self->pv->state, args); } @@ -517,7 +493,8 @@ gck_enumerator_class_init (GckEnumeratorClass *klass) */ GckEnumerator* -_gck_enumerator_new (GList *modules, guint session_options, GckTokenInfo *match_token, GckAttributes *match_attrs) +_gck_enumerator_new (GList *modules_or_slots, guint session_options, + GckTokenInfo *match_token, GckAttributes *match_attrs) { GckEnumerator *self; GckEnumeratorState *state; @@ -526,7 +503,16 @@ _gck_enumerator_new (GList *modules, guint session_options, GckTokenInfo *match_ state = g_atomic_pointer_get (&self->pv->state); state->session_options = session_options; - state->modules = gck_list_ref_copy (modules); + + if (modules_or_slots && GCK_IS_SLOT (modules_or_slots->data)) { + state->slots = gck_list_ref_copy (modules_or_slots); + state->modules = NULL; + state->handler = state_slots; + } else { + state->modules = gck_list_ref_copy (modules_or_slots); + state->slots = NULL; + state->handler = state_modules; + } if (match_attrs) { state->match_attrs = gck_attributes_ref (match_attrs); @@ -569,20 +555,22 @@ static gboolean complete_enumerate_next (EnumerateNext *args, CK_RV result) { GckEnumeratorState *state; + GckModule *module; gboolean ret = TRUE; g_assert (args->state); state = args->state; if (state->want_password) { - g_assert (state->module); g_assert (state->slot); /* TODO: Should we be using secure memory here? */ g_free (state->password); state->password = NULL; - ret = _gck_module_fire_authenticate_slot (state->module, state->slot, NULL, &state->password); + module = gck_slot_get_module (state->slot); + ret = _gck_module_fire_authenticate_slot (module, state->slot, NULL, &state->password); + g_object_unref (module); /* If authenticate returns TRUE then call is not complete */ ret = !ret; diff --git a/gck/gck-modules.c b/gck/gck-modules.c index a5b0b46..59ae1c8 100644 --- a/gck/gck-modules.c +++ b/gck/gck-modules.c @@ -135,7 +135,7 @@ gck_modules_get_slots (GList *modules, gboolean token_present) } /** - * gck_module_enumerate_objects_full: + * gck_module_enumerate_objects: * @self: The module to enumerate objects. * @attrs: Attributes that the objects must have, or empty for all objects. * @session_flags: Flags for opening a session. diff --git a/gck/gck-slot.c b/gck/gck-slot.c index d8a4a4e..8698198 100644 --- a/gck/gck-slot.c +++ b/gck/gck-slot.c @@ -799,6 +799,25 @@ gck_slot_has_flags (GckSlot *self, gulong flags) return (info.flags & flags) != 0; } +/** + * gck_slots_enumerate_objects: + * @slots: a list of #GckSlot to enumerate objects on. + * @attrs: Attributes that the objects must have, or empty for all objects. + * @session_options: Options for opening a session. + * + * Setup an enumerator for listing matching objects on the slots. + * + * This call will not block but will return an enumerator immediately. + * + * Return value: a new enumerator + **/ +GckEnumerator* +gck_slots_enumerate_objects (GList *slots, GckAttributes *attrs, guint session_options) +{ + return _gck_enumerator_new (slots, session_options, NULL, attrs); +} + + #if UNIMPLEMENTED typedef struct InitToken { diff --git a/gck/gck.h b/gck/gck.h index c627e60..4a4a564 100644 --- a/gck/gck.h +++ b/gck/gck.h @@ -494,6 +494,10 @@ GckMechanismInfo* gck_slot_get_mechanism_info (GckSlot *self, gboolean gck_slot_has_flags (GckSlot *self, gulong flags); +GckEnumerator* gck_slots_enumerate_objects (GList *slots, + GckAttributes *attrs, + guint session_options); + #if UNIMPLEMENTED gboolean gck_slot_init_token (GckSlot *self, diff --git a/gck/tests/test-gck-enumerator.c b/gck/tests/test-gck-enumerator.c index 699b061..2d86563 100644 --- a/gck/tests/test-gck-enumerator.c +++ b/gck/tests/test-gck-enumerator.c @@ -7,23 +7,26 @@ #include "gck-private.h" static GList *modules = NULL; +static GckModule *module = NULL; TESTING_SETUP(enumerator) { - GckModule *module; GError *err = NULL; /* Successful load */ module = gck_module_initialize (".libs/libmock-test-module.so", NULL, 0, &err); SUCCESS_RES (module, err); - modules = g_list_append (NULL, module); + modules = g_list_append (NULL, g_object_ref (module)); } TESTING_TEARDOWN(enumerator) { gck_list_unref_free (modules); modules = NULL; + + g_object_unref (module); + module = NULL; } TESTING_TEST(enumerator_create) @@ -35,6 +38,18 @@ TESTING_TEST(enumerator_create) g_object_unref (en); } +TESTING_TEST(enumerator_create_slots) +{ + GckEnumerator *en; + GList *slots; + + slots = gck_module_get_slots (module, FALSE); + en = _gck_enumerator_new (slots, 0, NULL, NULL); + g_assert (GCK_IS_ENUMERATOR (en)); + g_object_unref (en); + gck_list_unref_free (slots); +} + TESTING_TEST(enumerator_next) { GError *error = NULL; @@ -51,6 +66,25 @@ TESTING_TEST(enumerator_next) g_object_unref (en); } +TESTING_TEST(enumerator_next_slots) +{ + GError *error = NULL; + GList *slots = NULL; + GckEnumerator *en; + GckObject *obj; + + slots = gck_module_get_slots (module, FALSE); + en = _gck_enumerator_new (slots, 0, NULL, NULL); + g_assert (GCK_IS_ENUMERATOR (en)); + + obj = gck_enumerator_next (en, NULL, &error); + g_assert (GCK_IS_OBJECT (obj)); + + g_object_unref (obj); + g_object_unref (en); + gck_list_unref_free (slots); +} + TESTING_TEST(enumerator_next_and_resume) { GError *error = NULL; -- 2.7.4