From: Stefan Walter Date: Sat, 27 Dec 2008 18:29:23 +0000 (+0000) Subject: Add basic thread-safety. X-Git-Tag: split~388 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=ba78c4d9ad389bb42608935d1bd79e0039960154;p=platform%2Fupstream%2Fgcr.git Add basic thread-safety. * gp11/gp11.h: * gp11/gp11-call.c: * gp11/gp11-marshal.list: * gp11/gp11-misc.c: * gp11/gp11-module.c: * gp11/gp11-object.c: * gp11/gp11-session.c: * gp11/gp11-slot.c: * gp11/tests/unit-test-gp11-module.c: * gp11/tests/unit-test-gp11-object.c: * gp11/tests/unit-test-gp11-session.c: Add basic thread-safety. svn path=/trunk/; revision=1411 --- diff --git a/gp11/gp11-call.c b/gp11/gp11-call.c index c9c1ea6..0cf8bcd 100644 --- a/gp11/gp11-call.c +++ b/gp11/gp11-call.c @@ -33,6 +33,7 @@ static gpointer _gp11_call_parent_class = NULL; struct _GP11Call { GObject parent; + GP11Module *module; /* For making the call */ GP11CallFunc func; @@ -131,6 +132,8 @@ process_async_call (gpointer data, GP11CallClass *klass) static void process_result (GP11Call *call, gpointer unused) { + GP11Slot *slot; + /* Double check a few things */ g_assert (GP11_IS_CALL (call)); @@ -147,8 +150,10 @@ process_result (GP11Call *call, gpointer unused) if (call->rv == CKR_USER_NOT_LOGGED_IN && GP11_IS_SESSION (call->object)) { g_free (call->password); call->password = NULL; - call->do_login = _gp11_slot_token_authentication (GP11_SESSION (call->object)->slot, - &call->password); + slot = gp11_session_get_slot (GP11_SESSION (call->object)); + g_assert (GP11_IS_SLOT (slot)); + call->do_login = _gp11_slot_token_authentication (slot, &call->password); + g_object_unref (slot); } /* If we're supposed to do a login, then queue this call again */ @@ -239,6 +244,10 @@ _gp11_call_finalize (GObject *obj) { GP11Call *call = GP11_CALL (obj); + if (call->module) + g_object_unref (call->module); + call->module = NULL; + if (call->object) g_object_unref (call->object); call->object = NULL; @@ -395,6 +404,7 @@ _gp11_call_sync (gpointer object, gpointer func, gpointer data, GP11Arguments *args = (GP11Arguments*)data; gchar *password = NULL; GP11Module *module = NULL; + GP11Slot *slot; CK_ULONG pin_len; CK_RV rv; @@ -405,8 +415,9 @@ _gp11_call_sync (gpointer object, gpointer func, gpointer data, g_object_get (object, "module", &module, "handle", &args->handle, NULL); g_assert (GP11_IS_MODULE (module)); - args->pkcs11 = module->funcs; - g_object_unref (module); + /* We now hold a reference to module until below */ + args->pkcs11 = gp11_module_get_function_list (module); + g_assert (args->pkcs11); rv = perform_call ((GP11CallFunc)func, cancellable, args); @@ -417,14 +428,15 @@ _gp11_call_sync (gpointer object, gpointer func, gpointer data, if (rv == CKR_USER_NOT_LOGGED_IN && GP11_IS_SESSION (object)) { do { - if (!_gp11_slot_token_authentication (GP11_SESSION (object)->slot, - &password)) { + slot = gp11_session_get_slot (GP11_SESSION (object)); + if (!_gp11_slot_token_authentication (slot, &password)) { rv = CKR_USER_NOT_LOGGED_IN; } else { pin_len = password ? strlen (password) : 0; rv = (args->pkcs11->C_Login) (args->handle, CKU_USER, (CK_UTF8CHAR_PTR)password, pin_len); } + g_object_unref (slot); } while (rv == CKR_PIN_INCORRECT); /* If we logged in successfully then try again */ @@ -432,6 +444,8 @@ _gp11_call_sync (gpointer object, gpointer func, gpointer data, rv = perform_call ((GP11CallFunc)func, cancellable, args); } + g_object_unref (module); + if (rv == CKR_OK) return TRUE; @@ -477,15 +491,18 @@ _gp11_call_async_prep (gpointer object, gpointer cb_object, gpointer func, void _gp11_call_async_object (GP11Call *call, gpointer object) { - GP11Module *module; - g_assert (GP11_IS_CALL (call)); g_assert (call->args); - g_object_get (object, "module", &module, "handle", &call->args->handle, NULL); - g_assert (GP11_IS_MODULE (module)); - call->args->pkcs11 = module->funcs; - g_object_unref (module); + if (call->module) + g_object_unref (call->module); + call->module = NULL; + + g_object_get (object, "module", &call->module, "handle", &call->args->handle, NULL); + g_assert (GP11_IS_MODULE (call->module)); + call->args->pkcs11 = gp11_module_get_function_list (call->module); + + /* We now hold a reference on module until finalize */ } GP11Call* diff --git a/gp11/gp11-marshal.list b/gp11/gp11-marshal.list index 7e7cf5d..aaf14e7 100644 --- a/gp11/gp11-marshal.list +++ b/gp11/gp11-marshal.list @@ -1,2 +1,3 @@ BOOLEAN:POINTER BOOLEAN:OBJECT,POINTER +BOOLEAN:ULONG diff --git a/gp11/gp11-misc.c b/gp11/gp11-misc.c index 0d1c10e..1501757 100644 --- a/gp11/gp11-misc.c +++ b/gp11/gp11-misc.c @@ -38,8 +38,13 @@ GQuark gp11_get_error_quark (void) { static GQuark domain = 0; - if (domain == 0) + static volatile gsize quark_inited = 0; + + if (g_once_init_enter (&quark_inited)) { domain = g_quark_from_static_string ("gp11-error"); + g_once_init_leave (&quark_inited, 1); + } + return domain; } diff --git a/gp11/gp11-module.c b/gp11/gp11-module.c index b43c444..de5fa4a 100644 --- a/gp11/gp11-module.c +++ b/gp11/gp11-module.c @@ -27,18 +27,35 @@ #include +/* + * MT safe + * + * The only thing that can change after object initialization in + * a GP11Module is the finalized flag, which can be set + * to 1 in dispose. + */ + enum { PROP_0, - PROP_MODULE_PATH + PROP_PATH, + PROP_FUNCTION_LIST }; -typedef struct _GP11ModulePrivate { +typedef struct _GP11ModuleData { GModule *module; + gchar *path; + gint finalized; + CK_FUNCTION_LIST_PTR funcs; CK_C_INITIALIZE_ARGS init_args; +} GP11ModuleData; + +typedef struct _GP11ModulePrivate { + GP11ModuleData data; + /* Add future mutex and non-MT-safe data here */ } GP11ModulePrivate; -#define GP11_MODULE_GET_PRIVATE(o) \ - (G_TYPE_INSTANCE_GET_PRIVATE((o), GP11_TYPE_MODULE, GP11ModulePrivate)) +#define GP11_MODULE_GET_DATA(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE((o), GP11_TYPE_MODULE, GP11ModuleData)) G_DEFINE_TYPE (GP11Module, gp11_module, G_TYPE_OBJECT); @@ -94,7 +111,7 @@ unlock_mutex (void *mutex) */ static void -gp11_module_init (GP11Module *module) +gp11_module_init (GP11Module *self) { } @@ -103,11 +120,14 @@ static void gp11_module_get_property (GObject *obj, guint prop_id, GValue *value, GParamSpec *pspec) { - GP11Module *module = GP11_MODULE (obj); + GP11Module *self = GP11_MODULE (obj); switch (prop_id) { - case PROP_MODULE_PATH: - g_value_set_string (value, module->path); + case PROP_PATH: + g_value_set_string (value, gp11_module_get_path (self)); + break; + case PROP_FUNCTION_LIST: + g_value_set_pointer (value, gp11_module_get_function_list (self)); break; } } @@ -116,14 +136,14 @@ static void gp11_module_set_property (GObject *obj, guint prop_id, const GValue *value, GParamSpec *pspec) { - GP11ModulePrivate *pv = GP11_MODULE_GET_PRIVATE (obj); - GP11Module *module = GP11_MODULE (obj); + GP11ModuleData *data = GP11_MODULE_GET_DATA (obj); + /* Only allowed during initialization */ switch (prop_id) { - case PROP_MODULE_PATH: - g_return_if_fail (!pv->module); - module->path = g_value_dup_string (value); - g_return_if_fail (module->path); + case PROP_PATH: + g_return_if_fail (!data->path); + data->path = g_value_dup_string (value); + g_return_if_fail (data->path); break; } } @@ -131,36 +151,39 @@ gp11_module_set_property (GObject *obj, guint prop_id, const GValue *value, static void gp11_module_dispose (GObject *obj) { - GP11Module *module = GP11_MODULE (obj); + GP11ModuleData *data = GP11_MODULE_GET_DATA (obj); + gint finalized = g_atomic_int_get (&data->finalized); CK_RV rv; - if (module->funcs) { - rv = (module->funcs->C_Finalize) (NULL); + /* Must be careful when accessing funcs */ + if (data->funcs && !finalized && + g_atomic_int_compare_and_exchange (&data->finalized, finalized, 1)) { + rv = (data->funcs->C_Finalize) (NULL); if (rv != CKR_OK) { g_warning ("C_Finalize on module '%s' failed: %s", - module->path, gp11_message_from_rv (rv)); + data->path, gp11_message_from_rv (rv)); } - module->funcs = NULL; } + + G_OBJECT_CLASS (gp11_module_parent_class)->dispose (obj); } static void gp11_module_finalize (GObject *obj) { - GP11ModulePrivate *pv = GP11_MODULE_GET_PRIVATE (obj); - GP11Module *module = GP11_MODULE (obj); + GP11ModuleData *data = GP11_MODULE_GET_DATA (obj); - g_assert (module->funcs == NULL); + data->funcs = NULL; - if (pv->module) { - if (!g_module_close (pv->module)) + if (data->module) { + if (!g_module_close (data->module)) g_warning ("failed to close the pkcs11 module: %s", g_module_error ()); - pv->module = NULL; + data->module = NULL; } - g_free (module->path); - module->path = NULL; + g_free (data->path); + data->path = NULL; G_OBJECT_CLASS (gp11_module_parent_class)->finalize (obj); } @@ -177,10 +200,14 @@ gp11_module_class_init (GP11ModuleClass *klass) gobject_class->dispose = gp11_module_dispose; gobject_class->finalize = gp11_module_finalize; - g_object_class_install_property (gobject_class, PROP_MODULE_PATH, - g_param_spec_string ("module-path", "Module Path", "Path to the PKCS11 Module", + g_object_class_install_property (gobject_class, PROP_PATH, + g_param_spec_string ("path", "Module Path", "Path to the PKCS11 Module", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + g_object_class_install_property (gobject_class, PROP_FUNCTION_LIST, + g_param_spec_pointer ("function-list", "Function List", "PKCS11 Function List", + G_PARAM_READABLE)); + g_type_class_add_private (gobject_class, sizeof (GP11ModulePrivate)); } @@ -218,19 +245,19 @@ GP11Module* gp11_module_initialize (const gchar *path, gpointer reserved, GError **err) { CK_C_GetFunctionList get_function_list; - GP11ModulePrivate *pv; + GP11ModuleData *data; GP11Module *mod; CK_RV rv; g_return_val_if_fail (path != NULL, NULL); g_return_val_if_fail (!err || !*err, NULL); - mod = g_object_new (GP11_TYPE_MODULE, "module-path", path, NULL); - pv = GP11_MODULE_GET_PRIVATE (mod); + mod = g_object_new (GP11_TYPE_MODULE, "path", path, NULL); + data = GP11_MODULE_GET_DATA (mod); /* Load the actual module */ - pv->module = g_module_open (path, 0); - if (!pv->module) { + data->module = g_module_open (path, 0); + if (!data->module) { g_set_error (err, GP11_ERROR, (int)CKR_GP11_MODULE_PROBLEM, "Error loading pkcs11 module: %s", g_module_error ()); g_object_unref (mod); @@ -238,7 +265,7 @@ gp11_module_initialize (const gchar *path, gpointer reserved, GError **err) } /* Get the entry point */ - if (!g_module_symbol (pv->module, "C_GetFunctionList", (void**)&get_function_list)) { + if (!g_module_symbol (data->module, "C_GetFunctionList", (void**)&get_function_list)) { g_set_error (err, GP11_ERROR, (int)CKR_GP11_MODULE_PROBLEM, "Invalid pkcs11 module: %s", g_module_error ()); g_object_unref (mod); @@ -246,7 +273,7 @@ gp11_module_initialize (const gchar *path, gpointer reserved, GError **err) } /* Get the function list */ - rv = (get_function_list) (&mod->funcs); + rv = (get_function_list) (&data->funcs); if (rv != CKR_OK) { g_set_error (err, GP11_ERROR, rv, "Couldn't get pkcs11 function list: %s", gp11_message_from_rv (rv)); @@ -254,26 +281,16 @@ gp11_module_initialize (const gchar *path, gpointer reserved, GError **err) return NULL; } - /* Make sure we have a compatible version */ - if (mod->funcs->version.major != CRYPTOKI_VERSION_MAJOR) { - g_set_error (err, GP11_ERROR, (int)CKR_GP11_MODULE_PROBLEM, - "Incompatible version of pkcs11 module: %d.%d", - (int)mod->funcs->version.major, - (int)mod->funcs->version.minor); - g_object_unref (mod); - return NULL; - } - - memset (&pv->init_args, 0, sizeof (pv->init_args)); - pv->init_args.flags = CKF_OS_LOCKING_OK; - pv->init_args.CreateMutex = create_mutex; - pv->init_args.DestroyMutex = destroy_mutex; - pv->init_args.LockMutex = lock_mutex; - pv->init_args.UnlockMutex = unlock_mutex; - pv->init_args.pReserved = reserved; + memset (&data->init_args, 0, sizeof (data->init_args)); + data->init_args.flags = CKF_OS_LOCKING_OK; + data->init_args.CreateMutex = create_mutex; + data->init_args.DestroyMutex = destroy_mutex; + data->init_args.LockMutex = lock_mutex; + data->init_args.UnlockMutex = unlock_mutex; + data->init_args.pReserved = reserved; /* Now initialize the module */ - rv = (mod->funcs->C_Initialize) (&pv->init_args); + rv = (data->funcs->C_Initialize) (&data->init_args); if (rv != CKR_OK) { g_set_error (err, GP11_ERROR, rv, "Couldn't initialize module: %s", gp11_message_from_rv (rv)); @@ -286,24 +303,25 @@ gp11_module_initialize (const gchar *path, gpointer reserved, GError **err) /** * gp11_module_get_info: - * @module: The module to get info for. + * @self: The module to get info for. * * Get the info about a PKCS#11 module. * * Return value: The module info. Release this with gp11_module_info_free(). **/ GP11ModuleInfo* -gp11_module_get_info (GP11Module *module) +gp11_module_get_info (GP11Module *self) { + GP11ModuleData *data = GP11_MODULE_GET_DATA (self); GP11ModuleInfo *modinfo; CK_INFO info; CK_RV rv; - g_return_val_if_fail (GP11_IS_MODULE (module), NULL); - g_return_val_if_fail (module->funcs, NULL); + g_return_val_if_fail (GP11_IS_MODULE (self), NULL); + g_return_val_if_fail (data->funcs, NULL); memset (&info, 0, sizeof (info)); - rv = (module->funcs->C_GetInfo (&info)); + rv = (data->funcs->C_GetInfo (&info)); if (rv != CKR_OK) { g_warning ("couldn't get module info: %s", gp11_message_from_rv (rv)); return NULL; @@ -325,7 +343,7 @@ gp11_module_get_info (GP11Module *module) /** * gp11_module_get_slots: - * @module: The module for which to get the slots. + * @self: The module for which to get the slots. * @token_present: Whether to limit only to slots with a token present. * * Get the GP11Slot objects for a given module. @@ -333,17 +351,18 @@ gp11_module_get_info (GP11Module *module) * Return value: The possibly empty list of slots. Release this with gp11_list_unref_free(). */ GList* -gp11_module_get_slots (GP11Module *module, gboolean token_present) +gp11_module_get_slots (GP11Module *self, gboolean token_present) { + GP11ModuleData *data = GP11_MODULE_GET_DATA (self); CK_SLOT_ID_PTR slot_list; CK_ULONG count, i; GList *result; CK_RV rv; - g_return_val_if_fail (GP11_IS_MODULE (module), NULL); - g_return_val_if_fail (module->funcs, NULL); + g_return_val_if_fail (GP11_IS_MODULE (self), NULL); + g_return_val_if_fail (data->funcs, NULL); - rv = (module->funcs->C_GetSlotList) (token_present ? CK_TRUE : CK_FALSE, NULL, &count); + rv = (data->funcs->C_GetSlotList) (token_present ? CK_TRUE : CK_FALSE, NULL, &count); if (rv != CKR_OK) { g_warning ("couldn't get slot count: %s", gp11_message_from_rv (rv)); return NULL; @@ -353,7 +372,7 @@ gp11_module_get_slots (GP11Module *module, gboolean token_present) return NULL; slot_list = g_new (CK_SLOT_ID, count); - rv = (module->funcs->C_GetSlotList) (token_present ? CK_TRUE : CK_FALSE, slot_list, &count); + rv = (data->funcs->C_GetSlotList) (token_present ? CK_TRUE : CK_FALSE, slot_list, &count); if (rv != CKR_OK) { g_warning ("couldn't get slot list: %s", gp11_message_from_rv (rv)); g_free (slot_list); @@ -362,13 +381,44 @@ gp11_module_get_slots (GP11Module *module, gboolean token_present) result = NULL; for (i = 0; i < count; ++i) { - /* TODO: Should we be looking these up somewhere? */ result = g_list_prepend (result, g_object_new (GP11_TYPE_SLOT, "handle", slot_list[i], - "module", module, NULL)); + "module", self, NULL)); } g_free (slot_list); return g_list_reverse (result); } +/** + * gp11_module_get_path: + * @self: The module for which to get the path. + * + * Get the file path of this module. This may not be an absolute path, and + * usually reflects the path passed to gp11_module_initialize(). + * + * Return value: The path, do not modify or free this value. + **/ +const gchar* +gp11_module_get_path (GP11Module *self) +{ + GP11ModuleData *data = GP11_MODULE_GET_DATA (self); + g_return_val_if_fail (GP11_IS_MODULE (self), NULL); + return data->path; +} + +/** + * gp11_module_get_function_list: + * @self: The module for which to get the function list. + * + * Get the PKCS#11 function list for the module. + * + * Return value: The function list, do not modify this structure. + **/ +CK_FUNCTION_LIST_PTR +gp11_module_get_function_list (GP11Module *self) +{ + GP11ModuleData *data = GP11_MODULE_GET_DATA (self); + g_return_val_if_fail (GP11_IS_MODULE (self), NULL); + return data->funcs; +} diff --git a/gp11/gp11-object.c b/gp11/gp11-object.c index b7fb1a9..5230b6c 100644 --- a/gp11/gp11-object.c +++ b/gp11/gp11-object.c @@ -28,6 +28,12 @@ #include +/* + * MT safe -- Nothing in GP11ObjectData changes between + * init and finalize. All GP11ObjectPrivate access between init + * and finalize is locked. + */ + enum { PROP_0, PROP_MODULE, @@ -36,6 +42,21 @@ enum { PROP_SESSION }; +typedef struct _GP11ObjectData { + GP11Module *module; + GP11Slot *slot; + CK_OBJECT_HANDLE handle; +} GP11ObjectData; + +typedef struct _GP11ObjectPrivate { + GP11ObjectData data; + GStaticMutex mutex; + GP11Session *session; +} GP11ObjectPrivate; + +#define GP11_OBJECT_GET_DATA(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE((o), GP11_TYPE_OBJECT, GP11ObjectData)) + G_DEFINE_TYPE (GP11Object, gp11_object, G_TYPE_OBJECT); /* ---------------------------------------------------------------------------- @@ -80,26 +101,37 @@ opened_session (GObject *obj, GAsyncResult *result, gpointer user_data) } static void -require_session_async (GP11Object *object, GP11Call *call, +require_session_async (GP11Object *self, GP11Call *call, gulong flags, GCancellable *cancellable) { - g_assert (GP11_IS_OBJECT (object)); + GP11ObjectData *data = GP11_OBJECT_GET_DATA (self); + GP11Session *session; + + g_assert (GP11_IS_OBJECT (self)); + + session = gp11_object_get_session (self); + if (session) { + run_call_with_session (call, session); + g_object_unref (session); + } else { + gp11_slot_open_session_async (data->slot, flags, cancellable, opened_session, call); + } - if (object->session) - run_call_with_session (call, object->session); - else - gp11_slot_open_session_async (object->slot, flags, cancellable, opened_session, call); } static GP11Session* -require_session_sync (GP11Object *object, gulong flags, GError **err) +require_session_sync (GP11Object *self, gulong flags, GError **err) { - g_assert (GP11_IS_OBJECT (object)); + GP11ObjectData *data = GP11_OBJECT_GET_DATA (self); + GP11Session *session; - if (object->session) - return g_object_ref (object->session); + g_assert (GP11_IS_OBJECT (self)); - return gp11_slot_open_session (object->slot, flags, err); + session = gp11_object_get_session (self); + if (session) + return session; + + return gp11_slot_open_session (data->slot, flags, err); } /* ---------------------------------------------------------------------------- @@ -107,29 +139,30 @@ require_session_sync (GP11Object *object, gulong flags, GError **err) */ static void -gp11_object_init (GP11Object *object) +gp11_object_init (GP11Object *self) { - + GP11ObjectPrivate *pv = (G_TYPE_INSTANCE_GET_PRIVATE(self, GP11_TYPE_OBJECT, GP11ObjectPrivate)); + g_static_mutex_init (&pv->mutex); } static void gp11_object_get_property (GObject *obj, guint prop_id, GValue *value, - GParamSpec *pspec) + GParamSpec *pspec) { - GP11Object *object = GP11_OBJECT (obj); + GP11Object *self = GP11_OBJECT (obj); switch (prop_id) { case PROP_MODULE: - g_value_set_object (value, object->module); + g_value_take_object (value, gp11_object_get_module (self)); break; case PROP_SLOT: - g_value_set_object (value, object->slot); + g_value_take_object (value, gp11_object_get_slot (self)); break; case PROP_SESSION: - g_value_set_object (value, object->session); + g_value_take_object (value, gp11_object_get_session (self)); break; case PROP_HANDLE: - g_value_set_uint (value, object->handle); + g_value_set_ulong (value, gp11_object_get_handle (self)); break; } } @@ -138,61 +171,55 @@ static void gp11_object_set_property (GObject *obj, guint prop_id, const GValue *value, GParamSpec *pspec) { - GP11Object *object = GP11_OBJECT (obj); + GP11ObjectData *data = GP11_OBJECT_GET_DATA (obj); + GP11Object *self = GP11_OBJECT (obj); + + /* The sets to data below are only allowed during construction */ switch (prop_id) { case PROP_MODULE: - g_return_if_fail (!object->module); - object->module = g_value_get_object (value); - g_return_if_fail (object->module); - g_object_ref (object->module); + g_return_if_fail (!data->module); + data->module = g_value_get_object (value); + g_return_if_fail (data->module); + g_object_ref (data->module); break; case PROP_SLOT: - g_return_if_fail (!object->slot); - object->slot = g_value_get_object (value); - g_return_if_fail (object->slot); - g_object_ref (object->slot); + g_return_if_fail (!data->slot); + data->slot = g_value_get_object (value); + g_return_if_fail (data->slot); + g_object_ref (data->slot); break; case PROP_SESSION: - gp11_object_set_session (object, g_value_get_object (value)); + gp11_object_set_session (self, g_value_get_object (value)); break; case PROP_HANDLE: - g_return_if_fail (!object->handle); - object->handle = g_value_get_uint (value); + g_return_if_fail (!data->handle); + data->handle = g_value_get_ulong (value); break; } } static void -gp11_object_dispose (GObject *obj) +gp11_object_finalize (GObject *obj) { - GP11Object *object = GP11_OBJECT (obj); - - if (object->slot) - g_object_unref (object->slot); - object->slot = NULL; - - if (object->module) - g_object_unref (object->module); - object->module = NULL; + GP11ObjectPrivate *pv = (G_TYPE_INSTANCE_GET_PRIVATE(obj, GP11_TYPE_OBJECT, GP11ObjectPrivate)); + GP11ObjectData *data = GP11_OBJECT_GET_DATA (obj); - if (object->session) - g_object_unref (object->session); - object->session = NULL; + if (data->slot) + g_object_unref (data->slot); + data->slot = NULL; - G_OBJECT_CLASS (gp11_object_parent_class)->dispose (obj); -} + if (data->module) + g_object_unref (data->module); + data->module = NULL; -static void -gp11_object_finalize (GObject *obj) -{ - GP11Object *object = GP11_OBJECT (obj); + if (pv->session) + g_object_unref (pv->session); + pv->session = NULL; - g_assert (object->slot == NULL); - g_assert (object->module == NULL); - g_assert (object->session == NULL); + data->handle = 0; - object->handle = 0; + g_static_mutex_free (&pv->mutex); G_OBJECT_CLASS (gp11_object_parent_class)->finalize (obj); } @@ -206,7 +233,6 @@ gp11_object_class_init (GP11ObjectClass *klass) gobject_class->get_property = gp11_object_get_property; gobject_class->set_property = gp11_object_set_property; - gobject_class->dispose = gp11_object_dispose; gobject_class->finalize = gp11_object_finalize; g_object_class_install_property (gobject_class, PROP_MODULE, @@ -218,12 +244,14 @@ gp11_object_class_init (GP11ObjectClass *klass) GP11_TYPE_SLOT, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property (gobject_class, PROP_HANDLE, - g_param_spec_uint ("handle", "Object Handle", "PKCS11 Object Handle", - 0, G_MAXUINT, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + g_param_spec_ulong ("handle", "Object Handle", "PKCS11 Object Handle", + 0, G_MAXULONG, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property (gobject_class, PROP_SESSION, g_param_spec_object ("session", "session", "PKCS11 Session to make calls on", GP11_TYPE_SESSION, G_PARAM_READWRITE)); + + g_type_class_add_private (klass, sizeof (GP11ObjectPrivate)); } /* ---------------------------------------------------------------------------- @@ -243,8 +271,16 @@ gp11_object_class_init (GP11ObjectClass *klass) GP11Object* gp11_object_from_handle (GP11Slot *slot, CK_OBJECT_HANDLE handle) { + GP11Module *module = NULL; + GP11Object *object; + g_return_val_if_fail (GP11_IS_SLOT (slot), NULL); - return g_object_new (GP11_TYPE_OBJECT, "module", slot->module, "handle", handle, "slot", slot, NULL); + + module = gp11_slot_get_module (slot); + object = g_object_new (GP11_TYPE_OBJECT, "module", module, "handle", handle, "slot", slot, NULL); + g_object_unref (module); + + return object; } /** @@ -277,22 +313,57 @@ gp11_objects_from_handle_array (GP11Slot *slot, const GP11Attribute *attr) /** * gp11_object_get_handle: - * @object: The object. + * @self: The object. * * Get the raw PKCS#11 handle of a GP11Object. * * Return value: The raw object handle. **/ CK_OBJECT_HANDLE -gp11_object_get_handle (GP11Object *object) +gp11_object_get_handle (GP11Object *self) +{ + GP11ObjectData *data = GP11_OBJECT_GET_DATA (self); + g_return_val_if_fail (GP11_IS_OBJECT (self), (CK_OBJECT_HANDLE)-1); + return data->handle; +} + +/** + * gp11_object_get_module: + * @self: The object. + * + * Get the PKCS#11 module to which this object belongs. + * + * Return value: The module, which should be unreffed after use. + **/ +GP11Module* +gp11_object_get_module (GP11Object *self) +{ + GP11ObjectData *data = GP11_OBJECT_GET_DATA (self); + g_return_val_if_fail (GP11_IS_OBJECT (self), NULL); + g_return_val_if_fail (GP11_IS_MODULE (data->module), NULL); + return g_object_ref (data->module); +} + +/** + * gp11_object_get_slot: + * @self: The object. + * + * Get the PKCS#11 slot to which this object belongs. + * + * Return value: The slot, which should be unreffed after use. + **/ +GP11Slot* +gp11_object_get_slot (GP11Object *self) { - g_return_val_if_fail (GP11_IS_OBJECT (object), (CK_OBJECT_HANDLE)-1); - return object->handle; + GP11ObjectData *data = GP11_OBJECT_GET_DATA (self); + g_return_val_if_fail (GP11_IS_OBJECT (self), NULL); + g_return_val_if_fail (GP11_IS_SLOT (data->slot), NULL); + return g_object_ref (data->slot); } /** * gp11_object_get_session: - * @object: The object + * @self: The object * * Get the PKCS#11 session assigned to make calls on when operating * on this object. @@ -301,18 +372,30 @@ gp11_object_get_handle (GP11Object *object) * object. By default an object will open and close sessions * appropriate for its calls. * - * Return value: The assigned session. + * Return value: The assigned session, which must be unreffed after use. **/ GP11Session* -gp11_object_get_session (GP11Object *object) +gp11_object_get_session (GP11Object *self) { - g_return_val_if_fail (GP11_IS_OBJECT (object), NULL); - return object->session; + GP11ObjectPrivate *pv = (G_TYPE_INSTANCE_GET_PRIVATE (self, GP11_TYPE_OBJECT, GP11ObjectPrivate)); + GP11Session *session; + + g_return_val_if_fail (GP11_IS_OBJECT (self), NULL); + + g_static_mutex_lock (&pv->mutex); + + { + session = pv->session ? g_object_ref (pv->session) : NULL; + } + + g_static_mutex_unlock (&pv->mutex); + + return session; } /** - * gp11_object_get_session: - * @object: The object + * gp11_object_set_session: + * @self: The object * @session: The assigned session * * Set the PKCS#11 session assigned to make calls on when operating @@ -326,14 +409,23 @@ gp11_object_get_session (GP11Object *object) * that modify the state of the object will probably fail. **/ void -gp11_object_set_session (GP11Object *object, GP11Session *session) +gp11_object_set_session (GP11Object *self, GP11Session *session) { - g_return_if_fail (GP11_IS_OBJECT (object)); - if (session) - g_object_ref (session); - if (object->session) - g_object_unref (object->session); - object->session = session; + GP11ObjectPrivate *pv = (G_TYPE_INSTANCE_GET_PRIVATE (self, GP11_TYPE_OBJECT, GP11ObjectPrivate)); + + g_return_if_fail (GP11_IS_OBJECT (self)); + + g_static_mutex_lock (&pv->mutex); + + { + if (session) + g_object_ref (session); + if (pv->session) + g_object_unref (pv->session); + pv->session = session; + } + + g_static_mutex_unlock (&pv->mutex); } /* DESTROY */ @@ -351,7 +443,7 @@ perform_destroy (Destroy *args) /** * gp11_object_destroy: - * @object: The object to destroy. + * @self: The object to destroy. * @err: A location to return an error. * * Destroy a PKCS#11 object, deleting it from storage or the session. @@ -360,14 +452,14 @@ perform_destroy (Destroy *args) * Return value: Whether the call was successful or not. **/ gboolean -gp11_object_destroy (GP11Object *object, GError **err) +gp11_object_destroy (GP11Object *self, GError **err) { - return gp11_object_destroy_full (object, NULL, err); + return gp11_object_destroy_full (self, NULL, err); } /** * gp11_object_destroy_full: - * @object: The object to destroy. + * @self: The object to destroy. * @cancellable: Optional cancellable object, or NULL to ignore. * @err: A location to return an error. * @@ -377,18 +469,19 @@ gp11_object_destroy (GP11Object *object, GError **err) * Return value: Whether the call was successful or not. **/ gboolean -gp11_object_destroy_full (GP11Object *object, GCancellable *cancellable, GError **err) +gp11_object_destroy_full (GP11Object *self, GCancellable *cancellable, GError **err) { + GP11ObjectData *data = GP11_OBJECT_GET_DATA (self); Destroy args = { GP11_ARGUMENTS_INIT, 0 }; GP11Session *session; gboolean ret = FALSE; - g_return_val_if_fail (GP11_IS_OBJECT (object), FALSE); - g_return_val_if_fail (GP11_IS_SLOT (object->slot), FALSE); + g_return_val_if_fail (GP11_IS_OBJECT (self), FALSE); + g_return_val_if_fail (GP11_IS_SLOT (data->slot), FALSE); - args.object = object->handle; + args.object = data->handle; - session = require_session_sync (object, CKF_RW_SESSION, err); + session = require_session_sync (self, CKF_RW_SESSION, err); if (session) ret = _gp11_call_sync (session, perform_destroy, &args, cancellable, err); g_object_unref (session); @@ -397,7 +490,7 @@ gp11_object_destroy_full (GP11Object *object, GCancellable *cancellable, GError /** * gp11_object_destroy_async: - * @object: The object to destroy. + * @self: The object to destroy. * @cancellable: Optional cancellable object, or NULL to ignore. * @callback: Callback which is called when operation completes. * @user_data: Data to pass to the callback. @@ -406,25 +499,26 @@ gp11_object_destroy_full (GP11Object *object, GCancellable *cancellable, GError * This call will return immediately and complete asynchronously. **/ void -gp11_object_destroy_async (GP11Object *object, GCancellable *cancellable, +gp11_object_destroy_async (GP11Object *self, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { + GP11ObjectData *data = GP11_OBJECT_GET_DATA (self); Destroy* args; GP11Call *call; - g_return_if_fail (GP11_IS_OBJECT (object)); - g_return_if_fail (GP11_IS_SLOT (object->slot)); + g_return_if_fail (GP11_IS_OBJECT (self)); + g_return_if_fail (GP11_IS_SLOT (data->slot)); - args = _gp11_call_async_prep (NULL, object, perform_destroy, sizeof (*args), NULL); - args->object = object->handle; + args = _gp11_call_async_prep (data->slot, self, perform_destroy, sizeof (*args), NULL); + args->object = data->handle; call = _gp11_call_async_ready (args, cancellable, callback, user_data); - require_session_async (object, call, CKF_RW_SESSION, cancellable); + require_session_async (self, call, CKF_RW_SESSION, cancellable); } /** * gp11_object_destroy_finish: - * @object: The object being destroyed. + * @self: The object being destroyed. * @result: The result of the destory operation passed to the callback. * @err: A location to store an error. * @@ -434,7 +528,7 @@ gp11_object_destroy_async (GP11Object *object, GCancellable *cancellable, * Return value: Whether the object was destroyed successfully or not. */ gboolean -gp11_object_destroy_finish (GP11Object *object, GAsyncResult *result, GError **err) +gp11_object_destroy_finish (GP11Object *self, GAsyncResult *result, GError **err) { return _gp11_call_basic_finish (result, err); } @@ -462,7 +556,7 @@ perform_set_attributes (SetAttributes *args) /** * gp11_object_set: - * @object: The object to set attributes on. + * @self: The object to set attributes on. * @err: A location to return an error. * ...: The attributes to set. * @@ -493,7 +587,7 @@ perform_set_attributes (SetAttributes *args) * Return value: Whether the call was successful or not. **/ gboolean -gp11_object_set (GP11Object *object, GError **err, ...) +gp11_object_set (GP11Object *self, GError **err, ...) { GP11Attributes *attrs; va_list va; @@ -503,7 +597,7 @@ gp11_object_set (GP11Object *object, GError **err, ...) attrs = gp11_attributes_new_valist (va); va_end (va); - rv = gp11_object_set_full (object, attrs, NULL, err); + rv = gp11_object_set_full (self, attrs, NULL, err); gp11_attributes_unref (attrs); return rv; @@ -511,7 +605,7 @@ gp11_object_set (GP11Object *object, GError **err, ...) /** * gp11_object_set_full: - * @object: The object to set attributes on. + * @self: The object to set attributes on. * @attrs: The attributes to set on the object. * @cancellable: Optional cancellable object, or NULL to ignore. * @err: A location to return an error. @@ -521,20 +615,21 @@ gp11_object_set (GP11Object *object, GError **err, ...) * Return value: Whether the call was successful or not. **/ gboolean -gp11_object_set_full (GP11Object *object, GP11Attributes *attrs, +gp11_object_set_full (GP11Object *self, GP11Attributes *attrs, GCancellable *cancellable, GError **err) { + GP11ObjectData *data = GP11_OBJECT_GET_DATA (self); SetAttributes args; GP11Session *session; gboolean ret = FALSE; - g_return_val_if_fail (GP11_IS_OBJECT (object), FALSE); + g_return_val_if_fail (GP11_IS_OBJECT (self), FALSE); memset (&args, 0, sizeof (args)); args.attrs = attrs; - args.object = object->handle; + args.object = data->handle; - session = require_session_sync (object, CKF_RW_SESSION, err); + session = require_session_sync (self, CKF_RW_SESSION, err); if (session) ret = _gp11_call_sync (session, perform_set_attributes, &args, cancellable, err); g_object_unref (session); @@ -543,7 +638,7 @@ gp11_object_set_full (GP11Object *object, GP11Attributes *attrs, /** * gp11_object_set_async: - * @object: The object to set attributes on. + * @self: The object to set attributes on. * @attrs: The attributes to set on the object. * @cancellable: Optional cancellable object, or NULL to ignore. * @callback: Callback which is called when operation completes. @@ -553,27 +648,28 @@ gp11_object_set_full (GP11Object *object, GP11Attributes *attrs, * immediately and completes asynchronously. **/ void -gp11_object_set_async (GP11Object *object, GP11Attributes *attrs, GCancellable *cancellable, +gp11_object_set_async (GP11Object *self, GP11Attributes *attrs, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { + GP11ObjectData *data = GP11_OBJECT_GET_DATA (self); SetAttributes *args; GP11Call *call; - g_return_if_fail (GP11_IS_OBJECT (object)); + g_return_if_fail (GP11_IS_OBJECT (self)); - args = _gp11_call_async_prep (object->slot, object, perform_set_attributes, + args = _gp11_call_async_prep (data->slot, self, perform_set_attributes, sizeof (*args), free_set_attributes); args->attrs = attrs; gp11_attributes_ref (attrs); - args->object = object->handle; + args->object = data->handle; call = _gp11_call_async_ready (args, cancellable, callback, user_data); - require_session_async (object, call, CKF_RW_SESSION, cancellable); + require_session_async (self, call, CKF_RW_SESSION, cancellable); } /** * gp11_object_set_finish: - * @object: The object to set attributes on. + * @self: The object to set attributes on. * @result: The result of the destory operation passed to the callback. * @err: A location to store an error. * @@ -583,7 +679,7 @@ gp11_object_set_async (GP11Object *object, GP11Attributes *attrs, GCancellable * * Return value: Whether the attributes were successfully set on the object or not. */ gboolean -gp11_object_set_finish (GP11Object *object, GAsyncResult *result, GError **err) +gp11_object_set_finish (GP11Object *self, GAsyncResult *result, GError **err) { return _gp11_call_basic_finish (result, err); } @@ -682,7 +778,7 @@ perform_get_attributes (GetAttributes *args) /** * gp11_object_get: - * @object: The object to get attributes from. + * @self: The object to get attributes from. * @err: A location to store an error. * ...: The attribute types to get. * @@ -695,7 +791,7 @@ perform_get_attributes (GetAttributes *args) * Return value: The resulting PKCS#11 attributes, or NULL if an error occurred. **/ GP11Attributes* -gp11_object_get (GP11Object *object, GError **err, ...) +gp11_object_get (GP11Object *self, GError **err, ...) { GP11Attributes *result; GArray *array; @@ -712,14 +808,14 @@ gp11_object_get (GP11Object *object, GError **err, ...) } va_end (va); - result = gp11_object_get_full (object, (gulong*)array->data, array->len, NULL, err); + result = gp11_object_get_full (self, (gulong*)array->data, array->len, NULL, err); g_array_free (array, TRUE); return result; } /** * gp11_object_get: - * @object: The object to get attributes from. + * @self: The object to get attributes from. * @attr_types: The attributes to get. * @n_attr_types: The number of attributes to get. * @cancellable: Optional cancellation object, or NULL. @@ -734,22 +830,23 @@ gp11_object_get (GP11Object *object, GError **err, ...) * Return value: The resulting PKCS#11 attributes, or NULL if an error occurred. **/ GP11Attributes* -gp11_object_get_full (GP11Object *object, const gulong *attr_types, gsize n_attr_types, +gp11_object_get_full (GP11Object *self, const gulong *attr_types, gsize n_attr_types, GCancellable *cancellable, GError **err) { + GP11ObjectData *data = GP11_OBJECT_GET_DATA (self); GetAttributes args; GP11Session *session; - g_return_val_if_fail (GP11_IS_OBJECT (object), FALSE); + g_return_val_if_fail (GP11_IS_OBJECT (self), FALSE); - session = require_session_sync (object, 0, err); + session = require_session_sync (self, 0, err); if (!session) return NULL; memset (&args, 0, sizeof (args)); args.attr_types = (gulong*)attr_types; args.n_attr_types = n_attr_types; - args.object = object->handle; + args.object = data->handle; if (!_gp11_call_sync (session, perform_get_attributes, &args, cancellable, err)) { gp11_attributes_unref (args.results); @@ -763,7 +860,7 @@ gp11_object_get_full (GP11Object *object, const gulong *attr_types, gsize n_attr /** * gp11_object_get_async: - * @object: The object to get attributes from. + * @self: The object to get attributes from. * @attr_types: The attributes to get. * @n_attr_types: The number of attributes to get. * @cancellable: Optional cancellation object, or NULL. @@ -774,28 +871,29 @@ gp11_object_get_full (GP11Object *object, const gulong *attr_types, gsize n_attr * immediately and completes asynchronously. **/ void -gp11_object_get_async (GP11Object *object, const gulong *attr_types, gsize n_attr_types, +gp11_object_get_async (GP11Object *self, const gulong *attr_types, gsize n_attr_types, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { + GP11ObjectData *data = GP11_OBJECT_GET_DATA (self); GetAttributes *args; GP11Call *call; - g_return_if_fail (GP11_IS_OBJECT (object)); + g_return_if_fail (GP11_IS_OBJECT (self)); - args = _gp11_call_async_prep (object->session, object, perform_get_attributes, + args = _gp11_call_async_prep (data->slot, self, perform_get_attributes, sizeof (*args), free_get_attributes); args->n_attr_types = n_attr_types; if (n_attr_types) args->attr_types = g_memdup (attr_types, sizeof (gulong) * n_attr_types); - args->object = object->handle; + args->object = data->handle; call = _gp11_call_async_ready (args, cancellable, callback, user_data); - require_session_async (object, call, 0, cancellable); + require_session_async (self, call, 0, cancellable); } /** * gp11_object_get_finish: - * @object: The object to get attributes from. + * @self: The object to get attributes from. * @result: The result passed to the callback. * @err: A location to store an error. * @@ -808,7 +906,7 @@ gp11_object_get_async (GP11Object *object, const gulong *attr_types, gsize n_att * Return value: The resulting PKCS#11 attributes, or NULL if an error occurred. **/ GP11Attributes* -gp11_object_get_finish (GP11Object *object, GAsyncResult *result, GError **err) +gp11_object_get_finish (GP11Object *self, GAsyncResult *result, GError **err) { GP11Attributes *results; GetAttributes *args; @@ -826,7 +924,7 @@ gp11_object_get_finish (GP11Object *object, GAsyncResult *result, GError **err) /** * gp11_object_get_one: - * @object: The object to get an attribute from. + * @self: The object to get an attribute from. * @attr_type: The attribute to get. * @err: A location to store an error. * @@ -836,14 +934,14 @@ gp11_object_get_finish (GP11Object *object, GAsyncResult *result, GError **err) * Return value: The resulting PKCS#11 attribute, or NULL if an error occurred. **/ GP11Attribute* -gp11_object_get_one (GP11Object *object, gulong attr_type, GError **err) +gp11_object_get_one (GP11Object *self, gulong attr_type, GError **err) { - return gp11_object_get_one_full (object, attr_type, NULL, err); + return gp11_object_get_one_full (self, attr_type, NULL, err); } /** * gp11_object_get_one_full: - * @object: The object to get an attribute from. + * @self: The object to get an attribute from. * @attr_type: The attribute to get. * @cancellable: Optional cancellation object, or NULL. * @err: A location to store an error. @@ -854,13 +952,13 @@ gp11_object_get_one (GP11Object *object, gulong attr_type, GError **err) * Return value: The resulting PKCS#11 attribute, or NULL if an error occurred. **/ GP11Attribute* -gp11_object_get_one_full (GP11Object *object, gulong attr_type, +gp11_object_get_one_full (GP11Object *self, gulong attr_type, GCancellable *cancellable, GError **err) { GP11Attributes *attrs; GP11Attribute *attr; - attrs = gp11_object_get_full (object, &attr_type, 1, cancellable, err); + attrs = gp11_object_get_full (self, &attr_type, 1, cancellable, err); if (!attrs || !gp11_attributes_count (attrs)) return NULL; @@ -873,7 +971,7 @@ gp11_object_get_one_full (GP11Object *object, gulong attr_type, /** * gp11_object_get_one_async: - * @object: The object to get an attribute from. + * @self: The object to get an attribute from. * @attr_type: The attribute to get. * @cancellable: Optional cancellation object, or NULL. * @callback: Called when the operation completes. @@ -883,15 +981,15 @@ gp11_object_get_one_full (GP11Object *object, gulong attr_type, * return immediately and complete asynchronously. **/ void -gp11_object_get_one_async (GP11Object *object, gulong attr_type, GCancellable *cancellable, +gp11_object_get_one_async (GP11Object *self, gulong attr_type, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { - gp11_object_get_async (object, &attr_type, 1, cancellable, callback, user_data); + gp11_object_get_async (self, &attr_type, 1, cancellable, callback, user_data); } /** * gp11_object_get_one_finish: - * @object: The object to get an attribute from. + * @self: The object to get an attribute from. * @result: The result passed to the callback. * @err: A location to store an error. * @@ -902,12 +1000,12 @@ gp11_object_get_one_async (GP11Object *object, gulong attr_type, GCancellable *c **/ GP11Attribute* -gp11_object_get_one_finish (GP11Object *object, GAsyncResult *result, GError **err) +gp11_object_get_one_finish (GP11Object *self, GAsyncResult *result, GError **err) { GP11Attributes *attrs; GP11Attribute *attr; - attrs = gp11_object_get_finish (object, result, err); + attrs = gp11_object_get_finish (self, result, err); if (!attrs) return NULL; diff --git a/gp11/gp11-session.c b/gp11/gp11-session.c index 10495d6..6c7a758 100644 --- a/gp11/gp11-session.c +++ b/gp11/gp11-session.c @@ -24,6 +24,7 @@ #include "config.h" #include "gp11.h" +#include "gp11-marshal.h" #include "gp11-private.h" #include @@ -40,6 +41,21 @@ enum { PROP_SLOT }; +typedef struct _GP11SessionData { + GP11Slot *slot; + GP11Module *module; + CK_SESSION_HANDLE handle; + gint discarded; +} GP11SessionData; + +typedef struct _GP11SessionPrivate { + GP11SessionData data; + /* Add mutex and future MT-unsafe members here */ +} GP11SessionPrivate; + +#define GP11_SESSION_GET_DATA(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE((o), GP11_TYPE_SESSION, GP11SessionData)) + G_DEFINE_TYPE (GP11Session, gp11_session, G_TYPE_OBJECT); static guint signals[LAST_SIGNAL] = { 0 }; @@ -48,8 +64,33 @@ static guint signals[LAST_SIGNAL] = { 0 }; * OBJECT */ +static gboolean +gp11_session_real_discard_handle (GP11Session *self, CK_OBJECT_HANDLE handle) +{ + GP11SessionData *data = GP11_SESSION_GET_DATA (self); + CK_FUNCTION_LIST_PTR funcs; + CK_RV rv; + + /* The default functionality, close the handle */ + + g_return_val_if_fail (data->module, FALSE); + g_object_ref (data->module); + + funcs = gp11_module_get_function_list (data->module); + g_return_val_if_fail (funcs, FALSE); + + rv = (funcs->C_CloseSession) (handle); + if (rv != CKR_OK) { + g_warning ("couldn't close session properly: %s", + gp11_message_from_rv (rv)); + } + + g_object_unref (data->module); + return TRUE; +} + static void -gp11_session_init (GP11Session *session) +gp11_session_init (GP11Session *self) { } @@ -58,41 +99,43 @@ static void gp11_session_get_property (GObject *obj, guint prop_id, GValue *value, GParamSpec *pspec) { - GP11Session *session = GP11_SESSION (obj); + GP11Session *self = GP11_SESSION (obj); switch (prop_id) { case PROP_MODULE: - g_value_set_object (value, session->module); + g_value_take_object (value, gp11_session_get_module (self)); break; case PROP_HANDLE: - g_value_set_uint (value, session->handle); + g_value_set_ulong (value, gp11_session_get_handle (self)); break; case PROP_SLOT: - g_value_set_object(value, session->slot); + g_value_take_object (value, gp11_session_get_slot (self)); break; } } static void gp11_session_set_property (GObject *obj, guint prop_id, const GValue *value, - GParamSpec *pspec) + GParamSpec *pspec) { - GP11Session *session = GP11_SESSION (obj); + GP11SessionData *data = GP11_SESSION_GET_DATA (obj); + + /* Only valid calls are from constructor */ switch (prop_id) { case PROP_MODULE: - g_return_if_fail (!session->module); - session->module = g_value_dup_object (value); - g_return_if_fail (session->module); + g_return_if_fail (!data->module); + data->module = g_value_dup_object (value); + g_return_if_fail (data->module); break; case PROP_HANDLE: - g_return_if_fail (!session->handle); - session->handle = g_value_get_uint (value); + g_return_if_fail (!data->handle); + data->handle = g_value_get_ulong (value); break; case PROP_SLOT: - g_return_if_fail (!session->slot); - session->slot = g_value_dup_object (value); - g_return_if_fail (session->slot); + g_return_if_fail (!data->slot); + data->slot = g_value_dup_object (value); + g_return_if_fail (data->slot); break; } } @@ -100,35 +143,25 @@ gp11_session_set_property (GObject *obj, guint prop_id, const GValue *value, static void gp11_session_dispose (GObject *obj) { - GP11Session *session = GP11_SESSION (obj); - CK_RV rv; + GP11SessionData *data = GP11_SESSION_GET_DATA (obj); + GP11Session *self = GP11_SESSION (obj); + gboolean handled; + gint discarded; - g_return_if_fail (GP11_IS_SESSION (session)); - - /* - * Let the world know that we're discarding the session - * handle. This allows session reuse to work. - */ - if (session->handle) - g_signal_emit_by_name (session, "discard-handle"); - - if (session->handle) { - g_return_if_fail (session->module && session->module->funcs); - rv = (session->module->funcs->C_CloseSession) (session->handle); - if (rv != CKR_OK) { - g_warning ("couldn't close session properly: %s", - gp11_message_from_rv (rv)); - } - session->handle = 0; - } + g_return_if_fail (GP11_IS_SESSION (self)); - if (session->slot) - g_object_unref (session->slot); - session->slot = NULL; + discarded = g_atomic_int_get (&data->discarded); + if (!discarded && g_atomic_int_compare_and_exchange (&data->discarded, discarded, 1)) { - if (session->module) - g_object_unref (session->module); - session->module = NULL; + /* + * Let the world know that we're discarding the session + * handle. This allows session reuse to work. + */ + + g_signal_emit_by_name (self, "discard-handle", data->handle, &handled); + g_return_if_fail (handled); + + } G_OBJECT_CLASS (gp11_session_parent_class)->dispose (obj); } @@ -136,15 +169,21 @@ gp11_session_dispose (GObject *obj) static void gp11_session_finalize (GObject *obj) { - GP11Session *session = GP11_SESSION (obj); + GP11SessionData *data = GP11_SESSION_GET_DATA (obj); + + g_assert (data->discarded != 0); - g_assert (session->module == NULL); - g_assert (session->handle == 0); + if (data->slot) + g_object_unref (data->slot); + data->slot = NULL; + + if (data->module) + g_object_unref (data->module); + data->module = NULL; G_OBJECT_CLASS (gp11_session_parent_class)->finalize (obj); } - static void gp11_session_class_init (GP11SessionClass *klass) { @@ -156,22 +195,26 @@ gp11_session_class_init (GP11SessionClass *klass) gobject_class->dispose = gp11_session_dispose; gobject_class->finalize = gp11_session_finalize; + klass->discard_handle = gp11_session_real_discard_handle; + g_object_class_install_property (gobject_class, PROP_MODULE, g_param_spec_object ("module", "Module", "PKCS11 Module", GP11_TYPE_MODULE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property (gobject_class, PROP_HANDLE, - g_param_spec_uint ("handle", "Session Handle", "PKCS11 Session Handle", - 0, G_MAXUINT, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + g_param_spec_ulong ("handle", "Session Handle", "PKCS11 Session Handle", + 0, G_MAXULONG, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property (gobject_class, PROP_SLOT, g_param_spec_object ("slot", "Slot that this session uses", "PKCS11 Slot", GP11_TYPE_SLOT, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); signals[DISCARD_HANDLE] = g_signal_new ("discard-handle", GP11_TYPE_SESSION, - G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GP11SessionClass, discard_handle), - NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GP11SessionClass, discard_handle), + g_signal_accumulator_true_handled, NULL, + _gp11_marshal_BOOLEAN__ULONG, G_TYPE_BOOLEAN, 1, G_TYPE_ULONG); + g_type_class_add_private (klass, sizeof (GP11SessionPrivate)); } /* ---------------------------------------------------------------------------- @@ -206,29 +249,72 @@ gp11_session_info_free (GP11SessionInfo *session_info) GP11Session* gp11_session_from_handle (GP11Slot *slot, CK_SESSION_HANDLE handle) { + GP11Module *module; + GP11Session *session; + g_return_val_if_fail (GP11_IS_SLOT (slot), NULL); - return g_object_new (GP11_TYPE_SESSION, "module", slot->module, - "handle", handle, "slot", slot, NULL); + + module = gp11_slot_get_module (slot); + session = g_object_new (GP11_TYPE_SESSION, "module", module, + "handle", handle, "slot", slot, NULL); + g_object_unref (module); + + return session; } /** * gp11_session_get_handle: - * @session: The session object. + * @self: The session object. * * Get the raw PKCS#11 session handle from a GP11Session object. * * Return value: The raw session handle. **/ CK_SESSION_HANDLE -gp11_session_get_handle (GP11Session *session) +gp11_session_get_handle (GP11Session *self) { - g_return_val_if_fail (GP11_IS_SESSION (session), (CK_SESSION_HANDLE)-1); - return session->handle; + GP11SessionData *data = GP11_SESSION_GET_DATA (self); + g_return_val_if_fail (GP11_IS_SESSION (self), (CK_SESSION_HANDLE)-1); + return data->handle; +} + +/** + * gp11_session_get_module: + * @self: The session object. + * + * Get the PKCS#11 module to which this session belongs. + * + * Return value: The module, which should be unreffed after use. + **/ +GP11Module* +gp11_session_get_module (GP11Session *self) +{ + GP11SessionData *data = GP11_SESSION_GET_DATA (self); + g_return_val_if_fail (GP11_IS_SESSION (self), NULL); + g_return_val_if_fail (GP11_IS_MODULE (data->module), NULL); + return g_object_ref (data->module); +} + +/** + * gp11_session_get_slot: + * @self: The session object. + * + * Get the PKCS#11 slot to which this session belongs. + * + * Return value: The slot, which should be unreffed after use. + **/ +GP11Slot* +gp11_session_get_slot (GP11Session *self) +{ + GP11SessionData *data = GP11_SESSION_GET_DATA (self); + g_return_val_if_fail (GP11_IS_SESSION (self), NULL); + g_return_val_if_fail (GP11_IS_SLOT (data->slot), NULL); + return g_object_ref (data->slot); } /** * gp11_session_get_info: - * @session: The session object. + * @self: The session object. * * Get information about the session. * @@ -236,18 +322,27 @@ gp11_session_get_handle (GP11Session *session) * when done. **/ GP11SessionInfo* -gp11_session_get_info (GP11Session *session) +gp11_session_get_info (GP11Session *self) { + GP11SessionData *data = GP11_SESSION_GET_DATA (self); GP11SessionInfo *sessioninfo; + CK_FUNCTION_LIST_PTR funcs; CK_SESSION_INFO info; CK_RV rv; - g_return_val_if_fail (GP11_IS_SESSION (session), NULL); - g_return_val_if_fail (GP11_IS_MODULE (session->module), NULL); - g_return_val_if_fail (session->module->funcs, NULL); + g_return_val_if_fail (GP11_IS_SESSION (self), NULL); + g_return_val_if_fail (GP11_IS_MODULE (data->module), NULL); + + g_object_ref (data->module); + + funcs = gp11_module_get_function_list (data->module); + g_return_val_if_fail (funcs, NULL); memset (&info, 0, sizeof (info)); - rv = (session->module->funcs->C_GetSessionInfo) (session->handle, &info); + rv = (funcs->C_GetSessionInfo) (data->handle, &info); + + g_object_unref (data->module); + if (rv != CKR_OK) { g_warning ("couldn't get session info: %s", gp11_message_from_rv (rv)); return NULL; @@ -289,7 +384,7 @@ perform_login (Login *args) /** * gp11_session_login: - * @session: Log into this session. + * @self: Log into this session. * @user_type: The type of login user. * @pin: The user's PIN, or NULL for protected authentication path. * @n_pin: The length of the PIN. @@ -301,15 +396,15 @@ perform_login (Login *args) * Return value: Whether successful or not. **/ gboolean -gp11_session_login (GP11Session *session, gulong user_type, const guchar *pin, +gp11_session_login (GP11Session *self, gulong user_type, const guchar *pin, gsize n_pin, GError **err) { - return gp11_session_login_full (session, user_type, pin, n_pin, NULL, err); + return gp11_session_login_full (self, user_type, pin, n_pin, NULL, err); } /** * gp11_session_login_full: - * @session: Log into this session. + * @self: Log into this session. * @user_type: The type of login user. * @pin: The user's PIN, or NULL for protected authentication path. * @n_pin: The length of the PIN. @@ -322,17 +417,17 @@ gp11_session_login (GP11Session *session, gulong user_type, const guchar *pin, * Return value: Whether successful or not. **/ gboolean -gp11_session_login_full (GP11Session *session, gulong user_type, const guchar *pin, +gp11_session_login_full (GP11Session *self, gulong user_type, const guchar *pin, gsize n_pin, GCancellable *cancellable, GError **err) { Login args = { GP11_ARGUMENTS_INIT, user_type, (guchar*)pin, n_pin }; - return _gp11_call_sync (session, perform_login, &args, cancellable, err); + return _gp11_call_sync (self, perform_login, &args, cancellable, err); } /** * gp11_session_login_async: - * @session: Log into this session. + * @self: Log into this session. * @user_type: The type of login user. * @pin: The user's PIN, or NULL for protected authentication path. * @n_pin: The length of the PIN. @@ -344,11 +439,11 @@ gp11_session_login_full (GP11Session *session, gulong user_type, const guchar *p * immediately and completes asynchronously. **/ void -gp11_session_login_async (GP11Session *session, gulong user_type, const guchar *pin, +gp11_session_login_async (GP11Session *self, gulong user_type, const guchar *pin, gsize n_pin, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { - Login* args = _gp11_call_async_prep (session, session, perform_login, sizeof (*args), free_login); + Login* args = _gp11_call_async_prep (self, self, perform_login, sizeof (*args), free_login); args->user_type = user_type; args->pin = pin && n_pin ? g_memdup (pin, n_pin) : NULL; @@ -360,7 +455,7 @@ gp11_session_login_async (GP11Session *session, gulong user_type, const guchar * /** * gp11_session_login_finish: - * @session: The session logged into. + * @self: The session logged into. * @result: The result passed to the callback. * @err: A location to return an error. * @@ -369,7 +464,7 @@ gp11_session_login_async (GP11Session *session, gulong user_type, const guchar * * Return value: Whether the operation was successful or not. **/ gboolean -gp11_session_login_finish (GP11Session *session, GAsyncResult *result, GError **err) +gp11_session_login_finish (GP11Session *self, GAsyncResult *result, GError **err) { return _gp11_call_basic_finish (result, err); } @@ -387,7 +482,7 @@ perform_logout (GP11Arguments *args) /** * gp11_session_logout: - * @session: Logout of this session. + * @self: Logout of this session. * @err: A location to return an error. * * Log out of the session. This call may block for an indefinite period. @@ -395,14 +490,14 @@ perform_logout (GP11Arguments *args) * Return value: Whether the logout was successful or not. **/ gboolean -gp11_session_logout (GP11Session *session, GError **err) +gp11_session_logout (GP11Session *self, GError **err) { - return gp11_session_logout_full (session, NULL, err); + return gp11_session_logout_full (self, NULL, err); } /** * gp11_session_logout_full: - * @session: Logout of this session. + * @self: Logout of this session. * @cancellable: Optional cancellation object, or NULL. * @err: A location to return an error. * @@ -411,15 +506,15 @@ gp11_session_logout (GP11Session *session, GError **err) * Return value: Whether the logout was successful or not. **/ gboolean -gp11_session_logout_full (GP11Session *session, GCancellable *cancellable, GError **err) +gp11_session_logout_full (GP11Session *self, GCancellable *cancellable, GError **err) { GP11Arguments args = GP11_ARGUMENTS_INIT; - return _gp11_call_sync (session, perform_logout, &args, cancellable, err); + return _gp11_call_sync (self, perform_logout, &args, cancellable, err); } /** * gp11_session_logout_async: - * @session: Logout of this session. + * @self: Logout of this session. * @cancellable: Optional cancellation object, or NULL. * @callback: Called when the operation completes. * @user_data: Data to pass to the callback. @@ -428,16 +523,16 @@ gp11_session_logout_full (GP11Session *session, GCancellable *cancellable, GErro * asynchronously. **/ void -gp11_session_logout_async (GP11Session *session, GCancellable *cancellable, +gp11_session_logout_async (GP11Session *self, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { - GP11Arguments *args = _gp11_call_async_prep (session, session, perform_logout, 0, NULL); + GP11Arguments *args = _gp11_call_async_prep (self, self, perform_logout, 0, NULL); _gp11_call_async_ready_go (args, cancellable, callback, user_data); } /** * gp11_session_logout_finish: - * @session: Logout of this session. + * @self: Logout of this session. * @result: The result passed to the callback. * @err: A location to return an error. * @@ -446,7 +541,7 @@ gp11_session_logout_async (GP11Session *session, GCancellable *cancellable, * Return value: Whether the logout was successful or not. **/ gboolean -gp11_session_logout_finish (GP11Session *session, GAsyncResult *result, GError **err) +gp11_session_logout_finish (GP11Session *self, GAsyncResult *result, GError **err) { return _gp11_call_basic_finish (result, err); } @@ -480,7 +575,7 @@ perform_create_object (CreateObject *args) /** * gp11_session_create_object: - * @session: The session to create the object on. + * @self: The session to create the object on. * @err: A location to store an error. * ...: The attributes to create the new object with. * @@ -512,7 +607,7 @@ perform_create_object (CreateObject *args) * Return value: The newly created object, or NULL if an error occurred. **/ GP11Object* -gp11_session_create_object (GP11Session *session, GError **err, ...) +gp11_session_create_object (GP11Session *self, GError **err, ...) { GP11Attributes *attrs; GP11Object *object; @@ -522,14 +617,14 @@ gp11_session_create_object (GP11Session *session, GError **err, ...) attrs = gp11_attributes_new_valist (va); va_end (va); - object = gp11_session_create_object_full (session, attrs, NULL, err); + object = gp11_session_create_object_full (self, attrs, NULL, err); gp11_attributes_unref (attrs); return object; } /** * gp11_session_create_object_full: - * @session: The session to create the object on. + * @self: The session to create the object on. * @attrs: The attributes to create the object with. * @cancellable: Optional cancellation object, or NULL. * @err: A location to return an error, or NULL. @@ -540,18 +635,19 @@ gp11_session_create_object (GP11Session *session, GError **err, ...) * Return value: The newly created object or NULL if an error occurred. **/ GP11Object* -gp11_session_create_object_full (GP11Session *session, GP11Attributes *attrs, +gp11_session_create_object_full (GP11Session *self, GP11Attributes *attrs, GCancellable *cancellable, GError **err) { + GP11SessionData *data = GP11_SESSION_GET_DATA (self); CreateObject args = { GP11_ARGUMENTS_INIT, attrs, 0 }; - if (!_gp11_call_sync (session, perform_create_object, &args, cancellable, err)) + if (!_gp11_call_sync (self, perform_create_object, &args, cancellable, err)) return NULL; - return gp11_object_from_handle (session->slot, args.object); + return gp11_object_from_handle (data->slot, args.object); } /** * gp11_session_create_object_async: - * @session: The session to create the object on. + * @self: The session to create the object on. * @attrs: The attributes to create the object with. * @cancellable: Optional cancellation object or NULL. * @callback: Called when the operation completes. @@ -561,11 +657,11 @@ gp11_session_create_object_full (GP11Session *session, GP11Attributes *attrs, * and complete asynchronously. **/ void -gp11_session_create_object_async (GP11Session *session, GP11Attributes *attrs, +gp11_session_create_object_async (GP11Session *self, GP11Attributes *attrs, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { - CreateObject *args = _gp11_call_async_prep (session, session, perform_create_object, + CreateObject *args = _gp11_call_async_prep (self, self, perform_create_object, sizeof (*args), free_create_object); args->attrs = attrs; gp11_attributes_ref (attrs); @@ -574,7 +670,7 @@ gp11_session_create_object_async (GP11Session *session, GP11Attributes *attrs, /** * gp11_session_create_object_finish: - * @session: The session to create the object on. + * @self: The session to create the object on. * @result: The result passed to the callback. * @err: A location to return an error, or NULL. * @@ -583,14 +679,15 @@ gp11_session_create_object_async (GP11Session *session, GP11Attributes *attrs, * Return value: The newly created object or NULL if an error occurred. **/ GP11Object* -gp11_session_create_object_finish (GP11Session *session, GAsyncResult *result, GError **err) +gp11_session_create_object_finish (GP11Session *self, GAsyncResult *result, GError **err) { + GP11SessionData *data = GP11_SESSION_GET_DATA (self); CreateObject *args; if (!_gp11_call_basic_finish (result, err)) return NULL; args = _gp11_call_arguments (result, CreateObject); - return gp11_object_from_handle (session->slot, args->object); + return gp11_object_from_handle (data->slot, args->object); } @@ -666,14 +763,15 @@ perform_find_objects (FindObjects *args) } static GList* -objlist_from_handles (GP11Session *session, CK_OBJECT_HANDLE_PTR objects, +objlist_from_handles (GP11Session *self, CK_OBJECT_HANDLE_PTR objects, CK_ULONG n_objects) { + GP11SessionData *data = GP11_SESSION_GET_DATA (self); GList *results = NULL; while (n_objects > 0) { results = g_list_prepend (results, - gp11_object_from_handle (session->slot, objects[--n_objects])); + gp11_object_from_handle (data->slot, objects[--n_objects])); } return g_list_reverse (results); @@ -681,7 +779,7 @@ objlist_from_handles (GP11Session *session, CK_OBJECT_HANDLE_PTR objects, /** * gp11_session_find_objects: - * @session: The session to find objects on. + * @self: The session to find objects on. * @err: A location to return an error or NULL. * ...: The attributes to match. * @@ -712,7 +810,7 @@ objlist_from_handles (GP11Session *session, CK_OBJECT_HANDLE_PTR objects, * Return value: A list of the matching objects, which may be empty. **/ GList* -gp11_session_find_objects (GP11Session *session, GError **err, ...) +gp11_session_find_objects (GP11Session *self, GError **err, ...) { GP11Attributes *attrs; GList *results; @@ -722,14 +820,14 @@ gp11_session_find_objects (GP11Session *session, GError **err, ...) attrs = gp11_attributes_new_valist (va); va_end (va); - results = gp11_session_find_objects_full (session, attrs, NULL, err); + results = gp11_session_find_objects_full (self, attrs, NULL, err); gp11_attributes_unref (attrs); return results; } /** * gp11_session_find_objects_full: - * @session: The session to find objects on. + * @self: The session to find objects on. * @attrs: The attributes to match. * @cancellable: Optional cancellation object or NULL. * @err: A location to return an error or NULL. @@ -740,21 +838,21 @@ gp11_session_find_objects (GP11Session *session, GError **err, ...) * Return value: A list of the matching objects, which may be empty. **/ GList* -gp11_session_find_objects_full (GP11Session *session, GP11Attributes *attrs, +gp11_session_find_objects_full (GP11Session *self, GP11Attributes *attrs, GCancellable *cancellable, GError **err) { FindObjects args = { GP11_ARGUMENTS_INIT, attrs, NULL, 0 }; GList *results = NULL; - if (_gp11_call_sync (session, perform_find_objects, &args, cancellable, err)) - results = objlist_from_handles (session, args.objects, args.n_objects); + if (_gp11_call_sync (self, perform_find_objects, &args, cancellable, err)) + results = objlist_from_handles (self, args.objects, args.n_objects); g_free (args.objects); return results; } /** * gp11_session_find_objects_async: - * @session: The session to find objects on. + * @self: The session to find objects on. * @attrs: The attributes to match. * @cancellable: Optional cancellation object or NULL. * @callback: Called when the operation completes. @@ -764,11 +862,11 @@ gp11_session_find_objects_full (GP11Session *session, GP11Attributes *attrs, * return immediately and complete asynchronously. **/ void -gp11_session_find_objects_async (GP11Session *session, GP11Attributes *attrs, +gp11_session_find_objects_async (GP11Session *self, GP11Attributes *attrs, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { - FindObjects *args = _gp11_call_async_prep (session, session, perform_find_objects, + FindObjects *args = _gp11_call_async_prep (self, self, perform_find_objects, sizeof (*args), free_find_objects); args->attrs = attrs; gp11_attributes_ref (attrs); @@ -777,7 +875,7 @@ gp11_session_find_objects_async (GP11Session *session, GP11Attributes *attrs, /** * gp11_session_find_objects_finish: - * @session: The session to find objects on. + * @self: The session to find objects on. * @result: The attributes to match. * @err: A location to return an error. * @@ -786,14 +884,14 @@ gp11_session_find_objects_async (GP11Session *session, GP11Attributes *attrs, * Return value: A list of the matching objects, which may be empty. **/ GList* -gp11_session_find_objects_finish (GP11Session *session, GAsyncResult *result, GError **err) +gp11_session_find_objects_finish (GP11Session *self, GAsyncResult *result, GError **err) { FindObjects *args; if (!_gp11_call_basic_finish (result, err)) return NULL; args = _gp11_call_arguments (result, FindObjects); - return objlist_from_handles (session, args->objects, args->n_objects); + return objlist_from_handles (self, args->objects, args->n_objects); } @@ -855,7 +953,7 @@ perform_crypt (Crypt *args) } static guchar* -crypt_sync (GP11Session *session, GP11Object *key, GP11Mechanism *mech_args, const guchar *input, +crypt_sync (GP11Session *self, GP11Object *key, GP11Mechanism *mech_args, const guchar *input, gsize n_input, gsize *n_result, GCancellable *cancellable, GError **err, CK_C_EncryptInit init_func, CK_C_Encrypt complete_func) { @@ -881,7 +979,7 @@ crypt_sync (GP11Session *session, GP11Object *key, GP11Mechanism *mech_args, con args.init_func = init_func; args.complete_func = complete_func; - if (!_gp11_call_sync (session, perform_crypt, &args, cancellable, err)) { + if (!_gp11_call_sync (self, perform_crypt, &args, cancellable, err)) { g_free (args.result); return NULL; } @@ -890,11 +988,11 @@ crypt_sync (GP11Session *session, GP11Object *key, GP11Mechanism *mech_args, con } static void -crypt_async (GP11Session *session, GP11Object *key, GP11Mechanism *mech_args, const guchar *input, +crypt_async (GP11Session *self, GP11Object *key, GP11Mechanism *mech_args, const guchar *input, gsize n_input, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data, CK_C_EncryptInit init_func, CK_C_Encrypt complete_func) { - Crypt *args = _gp11_call_async_prep (session, session, perform_crypt, sizeof (*args), free_crypt); + Crypt *args = _gp11_call_async_prep (self, self, perform_crypt, sizeof (*args), free_crypt); g_return_if_fail (GP11_IS_OBJECT (key)); g_return_if_fail (mech_args); @@ -919,12 +1017,12 @@ crypt_async (GP11Session *session, GP11Object *key, GP11Mechanism *mech_args, co } static guchar* -crypt_finish (GP11Session *session, GAsyncResult *result, gsize *n_result, GError **err) +crypt_finish (GP11Session *self, GAsyncResult *result, gsize *n_result, GError **err) { Crypt *args; guchar *res; - if (!_gp11_call_basic_finish (session, result, err)) + if (!_gp11_call_basic_finish (self, result, err)) return NULL; args = _gp11_call_arguments (result, Crypt); @@ -938,25 +1036,25 @@ crypt_finish (GP11Session *session, GAsyncResult *result, gsize *n_result, GErro } guchar* -gp11_session_encrypt (GP11Session *session, GP11Object *key, gulong mech, const guchar *input, +gp11_session_encrypt (GP11Session *self, GP11Object *key, gulong mech, const guchar *input, gsize n_input, gsize *n_result, GError **err) { GP11Mechanism mech_args = { mech, NULL, 0 }; - return gp11_session_encrypt_full (session, key, &mech_args, input, n_input, n_result, NULL, err); + return gp11_session_encrypt_full (self, key, &mech_args, input, n_input, n_result, NULL, err); } guchar* -gp11_session_encrypt_full (GP11Session *session, GP11Object *key, GP11Mechanism *mech_args, +gp11_session_encrypt_full (GP11Session *self, GP11Object *key, GP11Mechanism *mech_args, const guchar *input, gsize n_input, gsize *n_result, GCancellable *cancellable, GError **err) { GP11Module *module = NULL; guchar *ret; - g_object_get (session, "module", &module, NULL); + g_object_get (self, "module", &module, NULL); g_return_val_if_fail (module != NULL, NULL); - ret = crypt_sync (session, key, mech_args, input, n_input, n_result, cancellable, err, + ret = crypt_sync (self, key, mech_args, input, n_input, n_result, cancellable, err, module->funcs->C_EncryptInit, module->funcs->C_Encrypt); g_object_unref (module); @@ -964,117 +1062,117 @@ gp11_session_encrypt_full (GP11Session *session, GP11Object *key, GP11Mechanism } void -gp11_session_encrypt_async (GP11Session *session, GP11Object *key, GP11Mechanism *mech_args, +gp11_session_encrypt_async (GP11Session *self, GP11Object *key, GP11Mechanism *mech_args, const guchar *input, gsize n_input, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { GP11Module *module = NULL; - g_object_get (session, "module", &module, NULL); + g_object_get (self, "module", &module, NULL); g_return_if_fail (module != NULL); - crypt_async (session, key, mech_args, input, n_input, cancellable, callback, user_data, + crypt_async (self, key, mech_args, input, n_input, cancellable, callback, user_data, module->funcs->C_EncryptInit, module->funcs->C_Encrypt); g_object_unref (module); } guchar* -gp11_session_encrypt_finish (GP11Session *session, GAsyncResult *result, gsize *n_result, +gp11_session_encrypt_finish (GP11Session *self, GAsyncResult *result, gsize *n_result, GError **err) { - return crypt_finish (session, result, n_result, err); + return crypt_finish (self, result, n_result, err); } guchar* -gp11_session_decrypt (GP11Session *session, GP11Object *key, gulong mech_type, const guchar *input, +gp11_session_decrypt (GP11Session *self, GP11Object *key, gulong mech_type, const guchar *input, gsize n_input, gsize *n_result, GError **err) { GP11Mechanism mech_args = { mech_type, NULL, 0 }; - return gp11_session_decrypt_full (session, key, &mech_args, input, n_input, n_result, NULL, err); + return gp11_session_decrypt_full (self, key, &mech_args, input, n_input, n_result, NULL, err); } guchar* -gp11_session_decrypt_full (GP11Session *session, GP11Object *key, GP11Mechanism *mech_args, +gp11_session_decrypt_full (GP11Session *self, GP11Object *key, GP11Mechanism *mech_args, const guchar *input, gsize n_input, gsize *n_result, GCancellable *cancellable, GError **err) { GP11Module *module = NULL; guchar *ret; - g_object_get (session, "module", &module, NULL); + g_object_get (self, "module", &module, NULL); g_return_val_if_fail (module != NULL, NULL); - ret = crypt_sync (session, key, mech_args, input, n_input, n_result, cancellable, err, + ret = crypt_sync (self, key, mech_args, input, n_input, n_result, cancellable, err, module->funcs->C_DecryptInit, module->funcs->C_Decrypt); g_object_unref (module); return ret; } void -gp11_session_decrypt_async (GP11Session *session, GP11Object *key, GP11Mechanism *mech_args, +gp11_session_decrypt_async (GP11Session *self, GP11Object *key, GP11Mechanism *mech_args, const guchar *input, gsize n_input, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { GP11Module *module = NULL; - g_object_get (session, "module", &module, NULL); + g_object_get (self, "module", &module, NULL); g_return_if_fail (module != NULL); - crypt_async (session, key, mech_args, input, n_input, cancellable, callback, user_data, + crypt_async (self, key, mech_args, input, n_input, cancellable, callback, user_data, module->funcs->C_DecryptInit, module->funcs->C_Decrypt); g_object_unref (module); } guchar* -gp11_session_decrypt_finish (GP11Session *session, GAsyncResult *result, +gp11_session_decrypt_finish (GP11Session *self, GAsyncResult *result, gsize *n_result, GError **err) { - return crypt_finish (session, result, n_result, err); + return crypt_finish (self, result, n_result, err); } guchar* -gp11_session_sign (GP11Session *session, GP11Object *key, gulong mech_type, const guchar *input, +gp11_session_sign (GP11Session *self, GP11Object *key, gulong mech_type, const guchar *input, gsize n_input, gsize *n_result, GError **err) { GP11Mechanism mech_args = { mech_type, NULL, 0 }; - return gp11_session_sign_full (session, key, &mech_args, input, n_input, n_result, NULL, err); + return gp11_session_sign_full (self, key, &mech_args, input, n_input, n_result, NULL, err); } guchar* -gp11_session_sign_full (GP11Session *session, GP11Object *key, GP11Mechanism *mech_args, +gp11_session_sign_full (GP11Session *self, GP11Object *key, GP11Mechanism *mech_args, const guchar *input, gsize n_input, gsize *n_result, GCancellable *cancellable, GError **err) { GP11Module *module = NULL; guchar *ret; - g_object_get (session, "module", &module, NULL); + g_object_get (self, "module", &module, NULL); g_return_val_if_fail (module != NULL, NULL); - return crypt_sync (session, key, mech_args, input, n_input, n_result, cancellable, err, + return crypt_sync (self, key, mech_args, input, n_input, n_result, cancellable, err, module->funcs->C_SignInit, module->funcs->C_Sign); g_object_unref (module); return ret; } void -gp11_session_sign_async (GP11Session *session, GP11Object *key, GP11Mechanism *mech_args, +gp11_session_sign_async (GP11Session *self, GP11Object *key, GP11Mechanism *mech_args, const guchar *input, gsize n_input, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { GP11Module *module = NULL; - g_object_get (session, "module", &module, NULL); + g_object_get (self, "module", &module, NULL); g_return_if_fail (module != NULL); - crypt_async (session, key, mech_args, input, n_input, cancellable, callback, user_data, + crypt_async (self, key, mech_args, input, n_input, cancellable, callback, user_data, module->funcs->C_SignInit, module->funcs->C_Sign); g_object_unref (module); } guchar* -gp11_session_sign_finish (GP11Session *session, GAsyncResult *result, +gp11_session_sign_finish (GP11Session *self, GAsyncResult *result, gsize *n_result, GError **err) { - return crypt_finish (session, result, n_result, err); + return crypt_finish (self, result, n_result, err); } @@ -1115,16 +1213,16 @@ perform_verify (Verify *args) } gboolean -gp11_session_verify (GP11Session *session, GP11Object *key, gulong mech_type, const guchar *input, +gp11_session_verify (GP11Session *self, GP11Object *key, gulong mech_type, const guchar *input, gsize n_input, const guchar *signature, gsize n_signature, GError **err) { GP11Mechanism mech_args = { mech_type, NULL, 0 }; - return gp11_session_verify_full (session, key, &mech_args, input, n_input, + return gp11_session_verify_full (self, key, &mech_args, input, n_input, signature, n_signature, NULL, err); } gboolean -gp11_session_verify_full (GP11Session *session, GP11Object *key, GP11Mechanism *mech_args, +gp11_session_verify_full (GP11Session *self, GP11Object *key, GP11Mechanism *mech_args, const guchar *input, gsize n_input, const guchar *signature, gsize n_signature, GCancellable *cancellable, GError **err) { @@ -1147,16 +1245,16 @@ gp11_session_verify_full (GP11Session *session, GP11Object *key, GP11Mechanism * args.signature = (guchar*)signature; args.n_signature = n_signature; - return _gp11_call_sync (session, perform_verify, &args, cancellable, err); + return _gp11_call_sync (self, perform_verify, &args, cancellable, err); } void -gp11_session_verify_async (GP11Session *session, GP11Object *key, GP11Mechanism *mech_args, +gp11_session_verify_async (GP11Session *self, GP11Object *key, GP11Mechanism *mech_args, const guchar *input, gsize n_input, const guchar *signature, gsize n_signature, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { - Verify *args = _gp11_call_async_prep (session, session, perform_verify, sizeof (*args), free_verify); + Verify *args = _gp11_call_async_prep (self, self, perform_verify, sizeof (*args), free_verify); g_return_if_fail (GP11_IS_OBJECT (key)); g_return_if_fail (mech_args); @@ -1178,9 +1276,9 @@ gp11_session_verify_async (GP11Session *session, GP11Object *key, GP11Mechanism } gboolean -gp11_session_verify_finish (GP11Session *session, GAsyncResult *result, GError **err) +gp11_session_verify_finish (GP11Session *self, GAsyncResult *result, GError **err) { - return _gp11_call_basic_finish (session, result, err); + return _gp11_call_basic_finish (self, result, err); } #endif /* UNTESTED */ diff --git a/gp11/gp11-slot.c b/gp11/gp11-slot.c index cb50c05..5072abe 100644 --- a/gp11/gp11-slot.c +++ b/gp11/gp11-slot.c @@ -46,7 +46,14 @@ enum { LAST_SIGNAL }; +typedef struct _GP11SlotData { + GP11Module *module; + CK_SLOT_ID handle; +} GP11SlotData; + typedef struct _GP11SlotPrivate { + GP11SlotData data; + GStaticMutex mutex; gboolean auto_login; GHashTable *open_sessions; GP11TokenInfo *token_info; @@ -54,8 +61,8 @@ typedef struct _GP11SlotPrivate { G_DEFINE_TYPE (GP11Slot, gp11_slot, G_TYPE_OBJECT); -#define GP11_SLOT_GET_PRIVATE(o) \ - (G_TYPE_INSTANCE_GET_PRIVATE((o), GP11_TYPE_SLOT, GP11SlotPrivate)) +#define GP11_SLOT_GET_DATA(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE((o), GP11_TYPE_SLOT, GP11SlotData)) typedef struct _SessionPool { gulong flags; @@ -102,211 +109,215 @@ timegm(struct tm *t) * HELPERS */ +static guint +ulong_hash (gconstpointer v) +{ + const signed char *p = v; + guint32 i, h = *p; + + for(i = 0; i < sizeof (gulong); ++i) + h = (h << 5) - h + *(p++); + + return h; +} + +static gboolean +ulong_equal (gconstpointer v1, gconstpointer v2) +{ + return *((const gulong*)v1) == *((const gulong*)v2); +} + static void close_session (GP11Module *module, CK_SESSION_HANDLE handle) { + CK_FUNCTION_LIST_PTR funcs; CK_RV rv; g_return_if_fail (GP11_IS_MODULE (module)); - g_return_if_fail (module->funcs); - rv = (module->funcs->C_CloseSession) (handle); + + g_object_ref (module); + + funcs = gp11_module_get_function_list (module); + g_return_if_fail (funcs); + + rv = (funcs->C_CloseSession) (handle); if (rv != CKR_OK) { g_warning ("couldn't close session properly: %s", gp11_message_from_rv (rv)); } + + g_object_unref (module); } -static void -free_session_pool (gpointer p) +static GP11SlotPrivate* +lock_private (gpointer obj) { - SessionPool *pool = p; - guint i; + GP11SlotPrivate *pv; + GP11Slot *self; - for(i = 0; i < pool->sessions->len; ++i) - close_session (pool->module, g_array_index(pool->sessions, CK_SESSION_HANDLE, i)); - g_array_free(pool->sessions, TRUE); - g_free (pool); -} + g_assert (GP11_IS_SLOT (obj)); + self = GP11_SLOT (obj); -#ifdef UNUSED + g_object_ref (self); -static void -foreach_count_sessions (gpointer key, gpointer value, gpointer user_data) -{ - SessionPool *pool = value; - guint *result = user_data; - *result += pool->sessions->len; + pv = G_TYPE_INSTANCE_GET_PRIVATE (self, GP11_TYPE_SLOT, GP11SlotPrivate); + g_static_mutex_lock (&pv->mutex); + + return pv; } -static guint -count_session_table (GP11Slot *slot, guint flags) +static void +unlock_private (gpointer obj, GP11SlotPrivate *pv) { - GP11SlotPrivate *pv = GP11_SLOT_GET_PRIVATE (slot); - guint result = 0; + GP11Slot *self; - if (!pv->open_sessions) - return 0; + g_assert (pv); + g_assert (GP11_IS_SLOT (obj)); - g_hash_table_foreach (pv->open_sessions, foreach_count_sessions, &result); - return result; -} + self = GP11_SLOT (obj); + + g_assert (G_TYPE_INSTANCE_GET_PRIVATE (self, GP11_TYPE_SLOT, GP11SlotPrivate) == pv); -#endif /* UNUSED */ + g_static_mutex_unlock (&pv->mutex); + g_object_unref (self); +} static void -push_session_table (GP11Slot *slot, gulong flags, CK_SESSION_HANDLE handle) +free_session_pool (gpointer p) { - GP11SlotPrivate *pv = GP11_SLOT_GET_PRIVATE (slot); - SessionPool *pool; + SessionPool *pool = p; + guint i; - if (!pv->open_sessions) { - close_session (slot->module, handle); - return; - } + for(i = 0; i < pool->sessions->len; ++i) + close_session (pool->module, g_array_index(pool->sessions, CK_SESSION_HANDLE, i)); + g_array_free(pool->sessions, TRUE); + g_free (pool); +} + +static gboolean +push_session_table (GP11SlotPrivate *pv, gulong flags, CK_SESSION_HANDLE handle) +{ + SessionPool *pool; g_assert (handle); - g_assert (GP11_IS_MODULE (slot->module)); + g_assert (GP11_IS_MODULE (pv->data.module)); + + if (pv->open_sessions == NULL) + return FALSE; pool = g_hash_table_lookup (pv->open_sessions, &flags); if (!pool) { pool = g_new0 (SessionPool, 1); pool->flags = flags; - pool->module = slot->module; /* weak ref */ + pool->module = pv->data.module; /* weak ref */ pool->sessions = g_array_new (FALSE, TRUE, sizeof (CK_SESSION_HANDLE)); g_hash_table_insert (pv->open_sessions, g_memdup (&flags, sizeof (flags)), pool); } g_assert (pool->flags == flags); g_array_append_val (pool->sessions, handle); + return TRUE; } static CK_SESSION_HANDLE -pop_session_table (GP11Slot *slot, gulong flags) +pop_session_table (GP11SlotPrivate *pv, gulong flags) { - GP11SlotPrivate *pv = GP11_SLOT_GET_PRIVATE (slot); - CK_SESSION_HANDLE result; + CK_SESSION_HANDLE result = 0; SessionPool *pool; - if (!pv->open_sessions) - return 0; + g_return_val_if_fail (pv, 0); - g_assert (GP11_IS_MODULE (slot->module)); - pool = g_hash_table_lookup (pv->open_sessions, &flags); - if (!pool) - return 0; + g_assert (GP11_IS_MODULE (pv->data.module)); - g_assert (pool->sessions->len > 0); - result = g_array_index (pool->sessions, CK_SESSION_HANDLE, pool->sessions->len - 1); - g_assert (result != 0); - g_array_remove_index_fast (pool->sessions, pool->sessions->len - 1); - if (!pool->sessions->len) - g_hash_table_remove(pv->open_sessions, &flags); + if (pv->open_sessions) { + pool = g_hash_table_lookup (pv->open_sessions, &flags); + if (pool) { + g_assert (pool->sessions->len > 0); + result = g_array_index (pool->sessions, CK_SESSION_HANDLE, pool->sessions->len - 1); + g_assert (result != 0); + g_array_remove_index_fast (pool->sessions, pool->sessions->len - 1); + if (!pool->sessions->len) + g_hash_table_remove(pv->open_sessions, &flags); + } + } return result; } static void -destroy_session_table (GP11Slot *slot) +destroy_session_table (GP11SlotPrivate *pv) { - GP11SlotPrivate *pv = GP11_SLOT_GET_PRIVATE (slot); if (pv->open_sessions) g_hash_table_unref (pv->open_sessions); pv->open_sessions = NULL; } -static guint -ulong_hash (gconstpointer v) -{ - // TODO: I'm sure there's a better gulong hash - const signed char *p = v; - guint32 i, h = *p; - - for(i = 0; i < sizeof (gulong); ++i) - h = (h << 5) - h + *(p++); - - return h; -} - -static gboolean -ulong_equal (gconstpointer v1, gconstpointer v2) -{ - return *((const gulong*)v1) == *((const gulong*)v2); -} - static void -create_session_table (GP11Slot *slot) +create_session_table (GP11SlotPrivate *pv) { - GP11SlotPrivate *pv = GP11_SLOT_GET_PRIVATE (slot); if (!pv->open_sessions) pv->open_sessions = g_hash_table_new_full (ulong_hash, ulong_equal, g_free, free_session_pool); } -static void -reuse_session_handle (GP11Session *session, GP11Slot *slot) +static gboolean +reuse_session_handle (GP11Session *session, CK_SESSION_HANDLE handle, GP11Slot *self) { + GP11SlotData *data = GP11_SLOT_GET_DATA (self); + GP11SlotPrivate *pv; + CK_FUNCTION_LIST_PTR funcs; CK_SESSION_INFO info; - gulong *flags; + gboolean handled = FALSE; CK_RV rv; - g_return_if_fail (GP11_IS_SESSION (session)); - g_return_if_fail (GP11_IS_SLOT (slot)); - g_return_if_fail (GP11_IS_MODULE (slot->module)); - g_return_if_fail (session->handle != 0); + g_return_val_if_fail (GP11_IS_SESSION (session), FALSE); + g_return_val_if_fail (GP11_IS_SLOT (self), FALSE); + + funcs = gp11_module_get_function_list (data->module); + g_return_val_if_fail (funcs, FALSE); /* Get the session info so we know where to categorize this */ - rv = (slot->module->funcs->C_GetSessionInfo) (session->handle, &info); + rv = (funcs->C_GetSessionInfo) (handle, &info); - /* An already closed session, we don't want to bother with */ - if (rv == CKR_SESSION_CLOSED || rv == CKR_SESSION_HANDLE_INVALID) { - session->handle = 0; - return; - } + if (rv == CKR_OK) { - /* A strange session, let it go to be closed somewhere else */ - if (rv != CKR_OK) - return; + /* Keep this one around for later use */ + pv = lock_private (self); - /* - * Get the flags that this session was opened with originally, and - * check them against the session's current flags. If they're no - * longer present, then don't reuse this session. - */ - flags = g_object_get_data (G_OBJECT (session), "gp11-open-session-flags"); - g_return_if_fail (flags); - if ((*flags & info.flags) != *flags) - return; + { + handled = push_session_table (pv, info.flags, handle); + } + + unlock_private (self, pv); + + } else { - /* Keep this one around for later use */ - push_session_table (slot, *flags, session->handle); - session->handle = 0; + /* 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; } static GP11Session* -make_session_object (GP11Slot *slot, gulong flags, CK_SESSION_HANDLE handle) +make_session_object (GP11Slot *self, gulong flags, CK_SESSION_HANDLE handle) { GP11Session *session; g_return_val_if_fail (handle != 0, NULL); - session = gp11_session_from_handle (slot, handle); - g_return_val_if_fail (session != NULL, NULL); - /* Session keeps a reference to us, so this is safe */ - g_signal_connect (session, "discard-handle", G_CALLBACK (reuse_session_handle), slot); + g_object_ref (self); - /* Mark the flags on the session for later looking up */ - g_object_set_data_full (G_OBJECT (session), "gp11-open-session-flags", - g_memdup (&flags, sizeof (flags)), g_free); + session = gp11_session_from_handle (self, handle); + g_return_val_if_fail (session != NULL, NULL); - return session; -} + /* Session keeps a reference to us, so this is safe */ + g_signal_connect (session, "discard-handle", G_CALLBACK (reuse_session_handle), self); -static void -ensure_token_info (GP11Slot *slot) -{ - GP11SlotPrivate *pv = GP11_SLOT_GET_PRIVATE (slot); - if (!pv->token_info) - pv->token_info = gp11_slot_get_token_info (slot); + g_object_unref (self); + + return session; } /* ---------------------------------------------------------------------------- @@ -314,30 +325,30 @@ ensure_token_info (GP11Slot *slot) */ static void -gp11_slot_init (GP11Slot *slot) +gp11_slot_init (GP11Slot *self) { - + GP11SlotPrivate *pv = G_TYPE_INSTANCE_GET_PRIVATE (self, GP11_TYPE_SLOT, GP11SlotPrivate); + g_static_mutex_init (&pv->mutex); } static void gp11_slot_get_property (GObject *obj, guint prop_id, GValue *value, GParamSpec *pspec) { - GP11SlotPrivate *pv = GP11_SLOT_GET_PRIVATE (obj); - GP11Slot *slot = GP11_SLOT (obj); + GP11Slot *self = GP11_SLOT (obj); switch (prop_id) { case PROP_MODULE: - g_value_set_object (value, slot->module); + g_value_take_object (value, gp11_slot_get_module (self)); break; case PROP_HANDLE: - g_value_set_uint (value, slot->handle); + g_value_set_ulong (value, gp11_slot_get_handle (self)); break; case PROP_AUTO_LOGIN: - g_value_set_boolean (value, pv->auto_login); + g_value_set_boolean (value, gp11_slot_get_auto_login (self)); break; case PROP_REUSE_SESSIONS: - g_value_set_boolean (value, pv->open_sessions != NULL); + g_value_set_boolean (value, gp11_slot_get_reuse_sessions (self)); break; } } @@ -346,28 +357,27 @@ static void gp11_slot_set_property (GObject *obj, guint prop_id, const GValue *value, GParamSpec *pspec) { - GP11SlotPrivate *pv = GP11_SLOT_GET_PRIVATE (obj); - GP11Slot *slot = GP11_SLOT (obj); + GP11SlotData *data = GP11_SLOT_GET_DATA (obj); + GP11Slot *self = GP11_SLOT (obj); + + /* All writes to data members below, happen only during construct phase */ switch (prop_id) { case PROP_MODULE: - g_return_if_fail (!slot->module); - slot->module = g_value_get_object (value); - g_return_if_fail (slot->module); - g_object_ref (slot->module); + g_assert (!data->module); + data->module = g_value_get_object (value); + g_assert (data->module); + g_object_ref (data->module); break; case PROP_HANDLE: - g_return_if_fail (!slot->handle); - slot->handle = g_value_get_uint (value); + g_assert (!data->handle); + data->handle = g_value_get_ulong (value); break; case PROP_AUTO_LOGIN: - pv->auto_login = g_value_get_boolean (value); + gp11_slot_set_auto_login (self, g_value_get_boolean (value)); break; case PROP_REUSE_SESSIONS: - if (g_value_get_boolean (value)) - create_session_table (slot); - else - destroy_session_table (slot); + gp11_slot_set_reuse_sessions (self, g_value_get_boolean (value)); break; } } @@ -375,14 +385,14 @@ gp11_slot_set_property (GObject *obj, guint prop_id, const GValue *value, static void gp11_slot_dispose (GObject *obj) { - GP11Slot *slot = GP11_SLOT (obj); + GP11SlotPrivate *pv = lock_private (obj); - /* Need to do this before the module goes away */ - destroy_session_table (slot); + { + /* Need to do this before the module goes away */ + destroy_session_table (pv); + } - if (slot->module) - g_object_unref (slot->module); - slot->module = NULL; + unlock_private (obj, pv); G_OBJECT_CLASS (gp11_slot_parent_class)->dispose (obj); } @@ -390,10 +400,22 @@ gp11_slot_dispose (GObject *obj) static void gp11_slot_finalize (GObject *obj) { - GP11Slot *slot = GP11_SLOT (obj); + GP11SlotPrivate *pv = G_TYPE_INSTANCE_GET_PRIVATE (obj, GP11_TYPE_SLOT, GP11SlotPrivate); + GP11SlotData *data = GP11_SLOT_GET_DATA (obj); + + data->handle = 0; + + g_assert (!pv->open_sessions); - g_assert (slot->module == NULL); - slot->handle = 0; + if (data->module) + g_object_unref (data->module); + data->module = NULL; + + if (pv->token_info) + gp11_token_info_free (pv->token_info); + pv->token_info = NULL; + + g_static_mutex_free (&pv->mutex); G_OBJECT_CLASS (gp11_slot_parent_class)->finalize (obj); } @@ -415,8 +437,8 @@ gp11_slot_class_init (GP11SlotClass *klass) GP11_TYPE_MODULE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property (gobject_class, PROP_HANDLE, - g_param_spec_uint ("handle", "Handle", "PKCS11 Slot ID", - 0, G_MAXUINT, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + g_param_spec_ulong ("handle", "Handle", "PKCS11 Slot ID", + 0, G_MAXULONG, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property (gobject_class, PROP_AUTO_LOGIN, g_param_spec_boolean ("auto-login", "Auto Login", "Auto Login to Token when necessary", @@ -439,29 +461,41 @@ gp11_slot_class_init (GP11SlotClass *klass) */ gboolean -_gp11_slot_token_authentication (GP11Slot *slot, gchar **password) +_gp11_slot_token_authentication (GP11Slot *self, gchar **password) { - GP11SlotPrivate *pv = GP11_SLOT_GET_PRIVATE (slot); + GP11SlotPrivate *pv = lock_private (self); + gboolean emit_signal = FALSE; gboolean ret = FALSE; - g_return_val_if_fail (GP11_IS_SLOT (slot), FALSE); + g_return_val_if_fail (GP11_IS_SLOT (self), FALSE); g_return_val_if_fail (password, FALSE); - if (!pv->auto_login) - return FALSE; - - /* - * If it's a protected authentication path style token, then - * we don't prompt here, the hardware/software is expected - * to prompt the user in some other way. - */ - ensure_token_info (slot); - if (pv->token_info && (pv->token_info->flags & CKF_PROTECTED_AUTHENTICATION_PATH)) { - *password = NULL; - return TRUE; + { + if (pv->auto_login) { + + /* + * If it's a protected authentication path style token, then + * we don't prompt here, the hardware/software is expected + * to prompt the user in some other way. + */ + + if (!pv->token_info) + pv->token_info = gp11_slot_get_token_info (self); + + if (pv->token_info && (pv->token_info->flags & CKF_PROTECTED_AUTHENTICATION_PATH)) { + *password = NULL; + ret = TRUE; + } else { + emit_signal = TRUE; + } + } } - g_signal_emit (slot, signals[AUTHENTICATE_TOKEN], 0, password, &ret); + unlock_private (self, pv); + + if (emit_signal) + g_signal_emit (self, signals[AUTHENTICATE_TOKEN], 0, password, &ret); + return ret; } @@ -519,22 +553,40 @@ gp11_mechanism_info_free (GP11MechanismInfo *mech_info) /** * gp11_slot_get_handle: - * @slot: The slot to get the handle of. + * @self: The slot to get the handle of. * * Get the raw PKCS#11 handle of a slot. * * Return value: The raw handle. **/ CK_SLOT_ID -gp11_slot_get_handle (GP11Slot *slot) +gp11_slot_get_handle (GP11Slot *self) +{ + GP11SlotData *data = GP11_SLOT_GET_DATA (self); + g_return_val_if_fail (GP11_IS_SLOT (self), (CK_SLOT_ID)-1); + return data->handle; +} + +/** + * gp11_slot_get_module: + * @self: The slot to get the module for. + * + * Get the module that this slot is on. + * + * Return value: The module, you must unreference this after you're done with it. + */ +GP11Module* +gp11_slot_get_module (GP11Slot *self) { - g_return_val_if_fail (GP11_IS_SLOT (slot), (CK_SLOT_ID)-1); - return slot->handle; + GP11SlotData *data = GP11_SLOT_GET_DATA (self); + g_return_val_if_fail (GP11_IS_SLOT (self), NULL); + g_return_val_if_fail (GP11_IS_MODULE (data->module), NULL); + return g_object_ref (data->module); } /** * gp11_slot_get_reuse_sessions: - * @slot: The slot to get setting from. + * @self: The slot to get setting from. * * Get the reuse sessions setting. When this is set, sessions * will be pooled and reused if their flags match when @@ -543,30 +595,51 @@ gp11_slot_get_handle (GP11Slot *slot) * Return value: Whether reusing sessions or not. **/ gboolean -gp11_slot_get_reuse_sessions (GP11Slot *slot) +gp11_slot_get_reuse_sessions (GP11Slot *self) { - gboolean reuse = FALSE; - g_object_get (slot, "reuse-sessions", &reuse, NULL); - return reuse; + GP11SlotPrivate *pv = lock_private (self); + gboolean ret; + + g_return_val_if_fail (pv, FALSE); + + { + ret = pv->open_sessions != NULL; + } + + unlock_private (self, pv); + + return ret; } /** * gp11_slot_set_reuse_sessions: - * @slot: The slot to set the setting on. + * @self: The slot to set the setting on. * @reuse: Whether to reuse sessions or not. * * When this is set, sessions will be pooled and reused * if their flags match when gp11_slot_open_session() is called. **/ void -gp11_slot_set_reuse_sessions (GP11Slot *slot, gboolean reuse) +gp11_slot_set_reuse_sessions (GP11Slot *self, gboolean reuse) { - g_object_set (slot, "reuse-sessions", reuse, NULL); + GP11SlotPrivate *pv = lock_private (self); + + g_return_if_fail (pv); + + { + if (reuse) + create_session_table (pv); + else + destroy_session_table (pv); + } + + unlock_private (self, pv); + g_object_notify (G_OBJECT (self), "reuse-sessions"); } /** * gp11_slot_get_auto_login: - * @slot: The slot to get setting from. + * @self: The slot to get setting from. * * Get the auto login setting. When this is set, this slot * will emit the 'authenticate-token' signal when a session @@ -575,16 +648,25 @@ gp11_slot_set_reuse_sessions (GP11Slot *slot, gboolean reuse) * Return value: Whether auto login or not. **/ gboolean -gp11_slot_get_auto_login (GP11Slot *slot) +gp11_slot_get_auto_login (GP11Slot *self) { - gboolean auto_login = FALSE; - g_object_get (slot, "auto-login", &auto_login, NULL); - return auto_login; + GP11SlotPrivate *pv = lock_private (self); + gboolean ret; + + g_return_val_if_fail (pv, FALSE); + + { + ret = pv->auto_login; + } + + unlock_private (self, pv); + + return ret; } /** * gp11_slot_set_auto_login: - * @slot: The slot to set the setting on. + * @self: The slot to set the setting on. * @auto_login: Whether auto login or not. * * When this is set, this slot @@ -592,14 +674,23 @@ gp11_slot_get_auto_login (GP11Slot *slot) * requires authentication. **/ void -gp11_slot_set_auto_login (GP11Slot *slot, gboolean auto_login) +gp11_slot_set_auto_login (GP11Slot *self, gboolean auto_login) { - g_object_set (slot, "auto-login", auto_login, NULL); + GP11SlotPrivate *pv = lock_private (self); + + g_return_if_fail (pv); + + { + pv->auto_login = auto_login; + } + + unlock_private (self, pv); + g_object_notify (G_OBJECT (self), "auto-login"); } /** * gp11_slot_get_info: - * @slot: The slot to get info for. + * @self: The slot to get info for. * * Get the information for this slot. * @@ -607,18 +698,28 @@ gp11_slot_set_auto_login (GP11Slot *slot, gboolean auto_login) * to release it. **/ GP11SlotInfo* -gp11_slot_get_info (GP11Slot *slot) +gp11_slot_get_info (GP11Slot *self) { + CK_SLOT_ID handle = (CK_SLOT_ID)-1; + GP11Module *module = NULL; + CK_FUNCTION_LIST_PTR funcs; GP11SlotInfo *slotinfo; CK_SLOT_INFO info; CK_RV rv; - g_return_val_if_fail (GP11_IS_SLOT (slot), NULL); - g_return_val_if_fail (GP11_IS_MODULE (slot->module), NULL); - g_return_val_if_fail (slot->module->funcs, NULL); + g_return_val_if_fail (GP11_IS_SLOT (self), NULL); + + g_object_get (self, "module", &module, "handle", &handle, NULL); + g_return_val_if_fail (GP11_IS_MODULE (module), NULL); + + funcs = gp11_module_get_function_list (module); + g_return_val_if_fail (funcs, NULL); memset (&info, 0, sizeof (info)); - rv = (slot->module->funcs->C_GetSlotInfo) (slot->handle, &info); + rv = (funcs->C_GetSlotInfo) (handle, &info); + + g_object_unref (module); + if (rv != CKR_OK) { g_warning ("couldn't get slot info: %s", gp11_message_from_rv (rv)); return NULL; @@ -640,7 +741,7 @@ gp11_slot_get_info (GP11Slot *slot) /** * gp11_slot_get_token_info: - * @slot: The slot to get info for. + * @self: The slot to get info for. * * Get the token information for this slot. * @@ -648,20 +749,30 @@ gp11_slot_get_info (GP11Slot *slot) * to release it. **/ GP11TokenInfo* -gp11_slot_get_token_info (GP11Slot *slot) +gp11_slot_get_token_info (GP11Slot *self) { + CK_SLOT_ID handle = (CK_SLOT_ID)-1; + CK_FUNCTION_LIST_PTR funcs; + GP11Module *module = NULL; GP11TokenInfo *tokeninfo; CK_TOKEN_INFO info; gchar *string; struct tm tm; CK_RV rv; - g_return_val_if_fail (GP11_IS_SLOT (slot), NULL); - g_return_val_if_fail (GP11_IS_MODULE (slot->module), NULL); - g_return_val_if_fail (slot->module->funcs, NULL); + g_return_val_if_fail (GP11_IS_SLOT (self), NULL); + + g_object_get (self, "module", &module, "handle", &handle, NULL); + g_return_val_if_fail (GP11_IS_MODULE (module), NULL); + + funcs = gp11_module_get_function_list (module); + g_return_val_if_fail (funcs, NULL); memset (&info, 0, sizeof (info)); - rv = (slot->module->funcs->C_GetTokenInfo) (slot->handle, &info); + rv = (funcs->C_GetTokenInfo) (handle, &info); + + g_object_unref (module); + if (rv != CKR_OK) { g_warning ("couldn't get slot info: %s", gp11_message_from_rv (rv)); return NULL; @@ -706,7 +817,7 @@ gp11_slot_get_token_info (GP11Slot *slot) /** * gp11_slot_get_mechanisms: - * @slot: The slot to get mechanisms for. + * @self: The slot to get mechanisms for. * * Get the available mechanisms for this slot. * @@ -714,33 +825,42 @@ gp11_slot_get_token_info (GP11Slot *slot) * gp11_mechanisms_free() when done with this. **/ GP11Mechanisms* -gp11_slot_get_mechanisms (GP11Slot *slot) +gp11_slot_get_mechanisms (GP11Slot *self) { + CK_SLOT_ID handle = (CK_SLOT_ID)-1; + CK_FUNCTION_LIST_PTR funcs; + GP11Module *module = NULL; CK_MECHANISM_TYPE_PTR mech_list; CK_ULONG count, i; GP11Mechanisms *result; CK_RV rv; - g_return_val_if_fail (GP11_IS_SLOT (slot), NULL); - g_return_val_if_fail (GP11_IS_MODULE (slot->module), NULL); - g_return_val_if_fail (slot->module->funcs, NULL); + g_return_val_if_fail (GP11_IS_SLOT (self), NULL); + + g_object_get (self, "module", &module, "handle", &handle, NULL); + g_return_val_if_fail (GP11_IS_MODULE (module), NULL); - rv = (slot->module->funcs->C_GetMechanismList) (slot->handle, NULL, &count); + funcs = gp11_module_get_function_list (module); + g_return_val_if_fail (funcs, NULL); + + rv = (funcs->C_GetMechanismList) (handle, NULL, &count); if (rv != CKR_OK) { g_warning ("couldn't get mechanism count: %s", gp11_message_from_rv (rv)); - return NULL; + count = 0; + } else { + mech_list = g_new (CK_MECHANISM_TYPE, count); + rv = (funcs->C_GetMechanismList) (handle, mech_list, &count); + if (rv != CKR_OK) { + g_warning ("couldn't get mechanism list: %s", gp11_message_from_rv (rv)); + g_free (mech_list); + count = 0; + } } - if (!count) - return NULL; + g_object_unref (module); - mech_list = g_new (CK_MECHANISM_TYPE, count); - rv = (slot->module->funcs->C_GetMechanismList) (slot->handle, mech_list, &count); - if (rv != CKR_OK) { - g_warning ("couldn't get mechanism list: %s", gp11_message_from_rv (rv)); - g_free (mech_list); + if (!count) return NULL; - } result = g_array_new (FALSE, TRUE, sizeof (CK_MECHANISM_TYPE)); for (i = 0; i < count; ++i) @@ -753,7 +873,7 @@ gp11_slot_get_mechanisms (GP11Slot *slot) /** * gp11_slot_get_mechanism_info: - * @slot: The slot to get mechanism info from. + * @self: The slot to get mechanism info from. * @mech_type: The mechanisms type to get info for. * * Get information for the specified mechanism. @@ -762,19 +882,29 @@ gp11_slot_get_mechanisms (GP11Slot *slot) * gp11_mechanism_info_free() when done with it. **/ GP11MechanismInfo* -gp11_slot_get_mechanism_info (GP11Slot *slot, gulong mech_type) +gp11_slot_get_mechanism_info (GP11Slot *self, gulong mech_type) { + CK_SLOT_ID handle = (CK_SLOT_ID)-1; + CK_FUNCTION_LIST_PTR funcs; GP11MechanismInfo *mechinfo; + GP11Module *module = NULL; CK_MECHANISM_INFO info; struct tm; CK_RV rv; - g_return_val_if_fail (GP11_IS_SLOT (slot), NULL); - g_return_val_if_fail (GP11_IS_MODULE (slot->module), NULL); - g_return_val_if_fail (slot->module->funcs, NULL); + g_return_val_if_fail (GP11_IS_SLOT (self), NULL); + + g_object_get (self, "module", &module, "handle", &handle, NULL); + g_return_val_if_fail (GP11_IS_MODULE (module), NULL); + + funcs = gp11_module_get_function_list (module); + g_return_val_if_fail (funcs, NULL); memset (&info, 0, sizeof (info)); - rv = (slot->module->funcs->C_GetMechanismInfo) (slot->handle, mech_type, &info); + rv = (funcs->C_GetMechanismInfo) (handle, mech_type, &info); + + g_object_unref (module); + if (rv != CKR_OK) { g_warning ("couldn't get mechanism info: %s", gp11_message_from_rv (rv)); return NULL; @@ -806,20 +936,20 @@ perform_init_token (InitToken *args) } gboolean -gp11_slot_init_token (GP11Slot *slot, const guchar *pin, gsize length, +gp11_slot_init_token (GP11Slot *self, const guchar *pin, gsize length, const gchar *label, GCancellable *cancellable, GError **err) { InitToken args = { GP11_ARGUMENTS_INIT, pin, length, label }; - return _gp11_call_sync (slot, perform_init_token, &args, err); + return _gp11_call_sync (self, perform_init_token, &args, err); } void -gp11_slot_init_token_async (GP11Slot *slot, const guchar *pin, gsize length, +gp11_slot_init_token_async (GP11Slot *self, const guchar *pin, gsize length, const gchar *label, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { - InitToken* args = _gp11_call_async_prep (slot, slot, perform_init_token, + InitToken* args = _gp11_call_async_prep (self, self, perform_init_token, sizeof (*args)); args->pin = pin; @@ -830,9 +960,9 @@ gp11_slot_init_token_async (GP11Slot *slot, const guchar *pin, gsize length, } gboolean -gp11_slot_init_token_finish (GP11Slot *slot, GAsyncResult *result, GError **err) +gp11_slot_init_token_finish (GP11Slot *self, GAsyncResult *result, GError **err) { - return _gp11_call_basic_finish (slot, result, err); + return _gp11_call_basic_finish (self, result, err); } #endif /* UNIMPLEMENTED */ @@ -853,7 +983,7 @@ perform_open_session (OpenSession *args) /** * gp11_slot_open_session: - * @slot: The slot ot open a session on. + * @self: The slot ot open a session on. * @flags: The flags to open a session with. * @err: A location to return an error, or NULL. * @@ -865,14 +995,14 @@ perform_open_session (OpenSession *args) * Return value: A new session or NULL if an error occurs. **/ GP11Session* -gp11_slot_open_session (GP11Slot *slot, gulong flags, GError **err) +gp11_slot_open_session (GP11Slot *self, gulong flags, GError **err) { - return gp11_slot_open_session_full (slot, flags, NULL, err); + return gp11_slot_open_session_full (self, flags, NULL, err); } /** * gp11_slot_open_session_full: - * @slot: The slot to open a session on. + * @self: The slot to open a session on. * @flags: The flags to open a session with. * @cancellable: Optional cancellation object, or NULL. * @err: A location to return an error, or NULL. @@ -885,26 +1015,42 @@ gp11_slot_open_session (GP11Slot *slot, gulong flags, GError **err) * Return value: A new session or NULL if an error occurs. **/ GP11Session* -gp11_slot_open_session_full (GP11Slot *slot, gulong flags, GCancellable *cancellable, GError **err) +gp11_slot_open_session_full (GP11Slot *self, gulong flags, GCancellable *cancellable, GError **err) { - OpenSession args = { GP11_ARGUMENTS_INIT, flags, 0 }; + GP11SlotPrivate *pv; + GP11Session *session = NULL; CK_SESSION_HANDLE handle; - /* Try to use a cached session */ - handle = pop_session_table (slot, flags); - if (handle != 0) - return make_session_object (slot, flags, handle); + flags |= CKF_SERIAL_SESSION; + + g_object_ref (self); + + pv = lock_private (self); + + { + /* Try to use a cached session */ + handle = pop_session_table (pv, flags); + if (handle != 0) + session = make_session_object (self, flags, handle); + } + + unlock_private (self, pv); /* Open a new session */ - if (!_gp11_call_sync (slot, perform_open_session, &args, cancellable, err)) - return FALSE; + if (session == NULL) { + OpenSession args = { GP11_ARGUMENTS_INIT, flags, 0 }; + if (_gp11_call_sync (self, perform_open_session, &args, cancellable, err)) + session = make_session_object (self, flags, args.session); + } + + g_object_unref (self); - return make_session_object (slot, flags, args.session); + return session; } /** * gp11_slot_open_session_async: - * @slot: The slot to open a session on. + * @self: The slot to open a session on. * @flags: The flags to open a session with. * @cancellable: Optional cancellation object, or NULL. * @callback: Called when the operation completes. @@ -916,27 +1062,41 @@ gp11_slot_open_session_full (GP11Slot *slot, gulong flags, GCancellable *cancell * This call will return immediately and complete asynchronously. **/ void -gp11_slot_open_session_async (GP11Slot *slot, gulong flags, GCancellable *cancellable, +gp11_slot_open_session_async (GP11Slot *self, gulong flags, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { + GP11SlotPrivate *pv; GP11Call *call; - OpenSession *args = _gp11_call_async_prep (slot, slot, perform_open_session, - sizeof (*args), NULL); + OpenSession *args; + + flags |= CKF_SERIAL_SESSION; + + g_object_ref (self); + + args = _gp11_call_async_prep (self, self, perform_open_session, sizeof (*args), NULL); + + pv = lock_private (self); - /* Try to use a cached session */ - args->session = pop_session_table (slot, flags); - args->flags = flags; + { + /* Try to use a cached session */ + args->session = pop_session_table (pv, flags); + args->flags = flags; + } + + unlock_private (self, pv); call = _gp11_call_async_ready (args, cancellable, callback, user_data); if (args->session) _gp11_call_async_short (call, CKR_OK); else _gp11_call_async_go (call); + + g_object_unref (self); } /** * gp11_slot_open_session_finish: - * @slot: The slot to open a session on. + * @self: The slot to open a session on. * @result: The result passed to the callback. * @err: A location to return an error or NULL. * @@ -946,13 +1106,22 @@ gp11_slot_open_session_async (GP11Slot *slot, gulong flags, GCancellable *cancel * Return value: The new session or NULL if an error occurs. */ GP11Session* -gp11_slot_open_session_finish (GP11Slot *slot, GAsyncResult *result, GError **err) +gp11_slot_open_session_finish (GP11Slot *self, GAsyncResult *result, GError **err) { - OpenSession *args; + GP11Session *session = NULL; - if (!_gp11_call_basic_finish (result, err)) - return NULL; + g_object_ref (self); - args = _gp11_call_arguments (result, OpenSession); - return make_session_object (slot, args->flags, args->session); + { + OpenSession *args; + + if (_gp11_call_basic_finish (result, err)) { + args = _gp11_call_arguments (result, OpenSession); + session = make_session_object (self, args->flags, args->session); + } + } + + g_object_unref (self); + + return session; } diff --git a/gp11/gp11.h b/gp11/gp11.h index 50bf817..097274c 100644 --- a/gp11/gp11.h +++ b/gp11/gp11.h @@ -243,25 +243,28 @@ typedef struct _GP11ModuleClass GP11ModuleClass; struct _GP11Module { GObject parent; - - gchar *path; - CK_FUNCTION_LIST_PTR funcs; + gpointer reserved[4]; }; struct _GP11ModuleClass { GObjectClass parent; + gpointer reserved[8]; }; -GType gp11_module_get_type (void) G_GNUC_CONST; +GType gp11_module_get_type (void) G_GNUC_CONST; -GP11Module* gp11_module_initialize (const gchar *path, - gpointer reserved, - GError **err); +GP11Module* gp11_module_initialize (const gchar *path, + gpointer reserved, + GError **err); + +const gchar* gp11_module_get_path (GP11Module *module); + +CK_FUNCTION_LIST_PTR gp11_module_get_function_list (GP11Module *module); -GP11ModuleInfo* gp11_module_get_info (GP11Module *module); +GP11ModuleInfo* gp11_module_get_info (GP11Module *module); -GList* gp11_module_get_slots (GP11Module *module, - gboolean token_present); +GList* gp11_module_get_slots (GP11Module *module, + gboolean token_present); enum { GP11_IS_STRING = -1, @@ -338,9 +341,7 @@ typedef struct _GP11SlotClass GP11SlotClass; struct _GP11Slot { GObject parent; - - GP11Module *module; - CK_SLOT_ID handle; + gpointer reserved[4]; }; struct _GP11SlotClass { @@ -355,10 +356,13 @@ struct _GP11SlotClass { void (*slot_event) (GP11Slot *slot); #endif + gpointer reserved[10]; }; GType gp11_slot_get_type (void) G_GNUC_CONST; +GP11Module* gp11_slot_get_module (GP11Slot *slot); + CK_SLOT_ID gp11_slot_get_handle (GP11Slot *slot); gboolean gp11_slot_get_reuse_sessions (GP11Slot *slot); @@ -447,24 +451,26 @@ typedef struct _GP11SessionClass GP11SessionClass; struct _GP11Session { GObject parent; - - GP11Slot *slot; - GP11Module *module; - CK_SESSION_HANDLE handle; }; struct _GP11SessionClass { GObjectClass parent; - void (*discard_handle) (GP11Session *session); + gboolean (*discard_handle) (GP11Session *session, CK_SESSION_HANDLE handle); }; GType gp11_session_get_type (void) G_GNUC_CONST; GP11Session* gp11_session_from_handle (GP11Slot *slot, CK_SESSION_HANDLE handle); +GP11Module* gp11_session_get_module (GP11Session *self); + +GP11Slot* gp11_session_get_slot (GP11Session *self); + CK_SESSION_HANDLE gp11_session_get_handle (GP11Session *session); +CK_SESSION_HANDLE gp11_session_steal_handle (GP11Session *session); + GP11SessionInfo* gp11_session_get_info (GP11Session *session); #if UNIMPLEMENTED @@ -1195,11 +1201,6 @@ typedef struct _GP11ObjectClass GP11ObjectClass; struct _GP11Object { GObject parent; - - GP11Module *module; - GP11Slot *slot; - GP11Session *session; - CK_OBJECT_HANDLE handle; }; struct _GP11ObjectClass { @@ -1214,6 +1215,10 @@ GP11Object* gp11_object_from_handle (GP11Slot *slot, GList* gp11_objects_from_handle_array (GP11Slot *slot, const GP11Attribute *attr); +GP11Module* gp11_object_get_module (GP11Object *self); + +GP11Slot* gp11_object_get_slot (GP11Object *object); + CK_OBJECT_HANDLE gp11_object_get_handle (GP11Object *object); GP11Session* gp11_object_get_session (GP11Object *object); diff --git a/gp11/tests/unit-test-gp11-module.c b/gp11/tests/unit-test-gp11-module.c index c0dc4c0..e5f1d1c 100644 --- a/gp11/tests/unit-test-gp11-module.c +++ b/gp11/tests/unit-test-gp11-module.c @@ -40,7 +40,7 @@ DEFINE_TEST(module_props) { gchar *path; - g_object_get (module, "module-path", &path, NULL); + g_object_get (module, "path", &path, NULL); g_assert (path != NULL && "no module-path"); g_assert (strcmp (".libs/libgp11-test-module.so", path) == 0 && "module path wrong"); g_free (path); diff --git a/gp11/tests/unit-test-gp11-object.c b/gp11/tests/unit-test-gp11-object.c index 31e9c6e..9445633 100644 --- a/gp11/tests/unit-test-gp11-object.c +++ b/gp11/tests/unit-test-gp11-object.c @@ -33,7 +33,7 @@ DEFINE_SETUP(prep_object) SUCCESS_RES(session, err); /* Our module always exports a token object with this */ - object = gp11_object_from_handle (session->slot, 2); + object = gp11_object_from_handle (slot, 2); g_assert (object != NULL); } @@ -47,12 +47,12 @@ DEFINE_TEARDOWN(prep_object) DEFINE_TEST(object_props) { - GP11Slot *slot; + GP11Slot *sl; GP11Module *mod; CK_OBJECT_HANDLE handle; - g_object_get (object, "slot", &slot, "module", &mod, "handle", &handle, NULL); - g_assert (slot == session->slot); - g_object_unref (slot); + g_object_get (object, "slot", &sl, "module", &mod, "handle", &handle, NULL); + g_assert (slot == sl); + g_object_unref (sl); g_assert (module == mod); g_object_unref (mod); g_assert (handle == 2); @@ -84,7 +84,7 @@ DEFINE_TEST(create_object) g_assert (GP11_IS_OBJECT (object)); if (object) { - last_handle = object->handle; + last_handle = gp11_object_get_handle (object); g_object_unref (object); } @@ -100,8 +100,8 @@ DEFINE_TEST(create_object) SUCCESS_RES (object, err); if (object) { - g_assert (last_handle != object->handle); - last_handle = object->handle; + g_assert (last_handle != gp11_object_get_handle (object)); + last_handle = gp11_object_get_handle (object); g_object_unref (object); } @@ -380,7 +380,9 @@ DEFINE_TEST(explicit_sessions) /* Set an explicit session */ gp11_object_set_session (object, session); - g_assert (gp11_object_get_session (object) == session); + sess = gp11_object_get_session (object); + g_assert (sess == session); + g_object_unref (sess); g_object_get (object, "session", &sess, NULL); g_assert (sess == session); g_object_unref (sess); @@ -415,4 +417,11 @@ DEFINE_TEST(explicit_sessions) g_assert (gp11_object_get_session (object) == NULL); g_object_get (object, "session", &sess, NULL); g_assert (sess == NULL); + + /* Test property settor */ + g_object_set (object, "session", session, NULL); + sess = gp11_object_get_session (object); + g_assert (sess == session); + gp11_object_set_session (object, NULL); + g_object_unref (sess); } diff --git a/gp11/tests/unit-test-gp11-session.c b/gp11/tests/unit-test-gp11-session.c index 1274b76..ed6e189 100644 --- a/gp11/tests/unit-test-gp11-session.c +++ b/gp11/tests/unit-test-gp11-session.c @@ -42,14 +42,17 @@ DEFINE_TEARDOWN(load_session) DEFINE_TEST(session_props) { GP11Module *mod; + GP11Slot *sl; guint handle; - g_object_get (session, "module", &mod, "handle", &handle, NULL); + g_object_get (session, "module", &mod, "handle", &handle, "slot", &sl, NULL); g_assert (mod == module); + g_assert (sl == slot); g_object_unref (mod); + g_object_unref (sl); g_assert (handle != 0); - g_assert (session->handle == handle); + g_assert (gp11_session_get_handle (session) == handle); } DEFINE_TEST(session_info) @@ -59,7 +62,7 @@ DEFINE_TEST(session_info) info = gp11_session_get_info (session); g_assert (info != NULL && "no session info"); - g_assert (info->slot_id == slot->handle); + g_assert (info->slot_id == gp11_slot_get_handle (slot)); g_assert ((info->flags & CKF_SERIAL_SESSION) == CKF_SERIAL_SESSION); g_assert (info->device_error == 1414); gp11_session_info_free (info); @@ -103,24 +106,27 @@ DEFINE_TEST(open_reused) GP11Session *sess, *sess2; GAsyncResult *result = NULL; GError *err = NULL; + gboolean value; g_assert (gp11_slot_get_reuse_sessions (slot) == FALSE); gp11_slot_set_reuse_sessions (slot, TRUE); g_assert (gp11_slot_get_reuse_sessions (slot) == TRUE); + g_object_get (slot, "reuse-sessions", &value, NULL); + g_assert (value == TRUE); sess = gp11_slot_open_session (slot, 0, &err); SUCCESS_RES (sess, err); if (!sess) return; /* Make note of the handle we saw */ - handle = sess->handle; + handle = gp11_session_get_handle (sess); g_object_unref (sess); /* Open again, and see if the same handle */ sess = gp11_slot_open_session (slot, 0, &err); SUCCESS_RES (sess, err); if (!sess) return; - g_assert (handle == sess->handle); + g_assert (handle == gp11_session_get_handle (sess)); g_object_unref (sess); /* Test opening async */ @@ -130,7 +136,7 @@ DEFINE_TEST(open_reused) sess = gp11_slot_open_session_finish (slot, result, &err); SUCCESS_RES (sess, err); if (!sess) return; - g_assert (handle == sess->handle); + g_assert (handle == gp11_session_get_handle (sess)); g_object_unref (result); g_object_unref (sess); @@ -138,13 +144,16 @@ DEFINE_TEST(open_reused) sess = gp11_slot_open_session (slot, CKF_RW_SESSION, &err); SUCCESS_RES (sess, err); if (!sess) return; - g_assert (handle != sess->handle); + g_assert (handle != gp11_session_get_handle (sess)); /* Now open a second session, with same flags, shouldn't return the same */ sess2 = gp11_slot_open_session (slot, CKF_RW_SESSION, &err); SUCCESS_RES (sess2, err); if (!sess2) return; - g_assert (sess->handle != sess2->handle); + g_assert (gp11_session_get_handle (sess) != gp11_session_get_handle (sess2)); + + g_object_set (slot, "reuse-sessions", FALSE, NULL); + g_assert (gp11_slot_get_reuse_sessions (slot) == FALSE); g_object_unref (sess); g_object_unref (sess2); @@ -214,6 +223,7 @@ DEFINE_TEST(auto_login) GError *err = NULL; GP11Attributes *attrs; gboolean ret; + gboolean value; attrs = gp11_attributes_newv (CKA_CLASS, GP11_ULONG, CKO_DATA, CKA_LABEL, GP11_STRING, "TEST OBJECT", @@ -230,6 +240,8 @@ DEFINE_TEST(auto_login) g_assert (gp11_slot_get_auto_login (slot) == FALSE); gp11_slot_set_auto_login (slot, TRUE); g_assert (gp11_slot_get_auto_login (slot) == TRUE); + g_object_get (slot, "auto-login", &value, NULL); + g_assert (value == TRUE); g_signal_connect (slot, "authenticate-token", G_CALLBACK (authenticate_token), GUINT_TO_POINTER (35)); @@ -254,4 +266,7 @@ DEFINE_TEST(auto_login) /* We should now be logged in, try to log out */ ret = gp11_session_logout (session, &err); SUCCESS_RES (ret, err); + + g_object_set (slot, "auto-login", FALSE, NULL); + g_assert (gp11_slot_get_auto_login (slot) == FALSE); }