diff options
Diffstat (limited to '')
-rw-r--r-- | plugins/smartcard/gsd-smartcard-service.c | 849 |
1 files changed, 849 insertions, 0 deletions
diff --git a/plugins/smartcard/gsd-smartcard-service.c b/plugins/smartcard/gsd-smartcard-service.c new file mode 100644 index 0000000..4d529c3 --- /dev/null +++ b/plugins/smartcard/gsd-smartcard-service.c @@ -0,0 +1,849 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- + * + * Copyright (C) 2012 Red Hat, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <http://www.gnu.org/licenses/>. + * + * Authors: Ray Strode + */ + +#include "config.h" + +#include "gsd-smartcard-service.h" +#include "org.gnome.SettingsDaemon.Smartcard.h" +#include "gsd-smartcard-manager.h" +#include "gsd-smartcard-enum-types.h" +#include "gsd-smartcard-utils.h" + +#include <glib/gi18n.h> +#include <glib/gstdio.h> +#include <gio/gio.h> + +struct _GsdSmartcardService +{ + GsdSmartcardServiceManagerSkeleton parent; + + GDBusConnection *bus_connection; + GDBusObjectManagerServer *object_manager_server; + GsdSmartcardManager *smartcard_manager; + GCancellable *cancellable; + GHashTable *tokens; + + gboolean login_token_bound; + guint name_id; +}; + +#define GSD_DBUS_NAME "org.gnome.SettingsDaemon" +#define GSD_DBUS_PATH "/org/gnome/SettingsDaemon" +#define GSD_DBUS_BASE_INTERFACE "org.gnome.SettingsDaemon" + +#define GSD_SMARTCARD_DBUS_NAME GSD_DBUS_NAME ".Smartcard" +#define GSD_SMARTCARD_DBUS_PATH GSD_DBUS_PATH "/Smartcard" +#define GSD_SMARTCARD_MANAGER_DBUS_PATH GSD_SMARTCARD_DBUS_PATH "/Manager" +#define GSD_SMARTCARD_MANAGER_DRIVERS_DBUS_PATH GSD_SMARTCARD_MANAGER_DBUS_PATH "/Drivers" +#define GSD_SMARTCARD_MANAGER_TOKENS_DBUS_PATH GSD_SMARTCARD_MANAGER_DBUS_PATH "/Tokens" + +enum { + PROP_0, + PROP_MANAGER, + PROP_BUS_CONNECTION +}; + +static void gsd_smartcard_service_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *param_spec); +static void gsd_smartcard_service_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *param_spec); +static void async_initable_interface_init (GAsyncInitableIface *interface); +static void smartcard_service_manager_interface_init (GsdSmartcardServiceManagerIface *interface); + +G_LOCK_DEFINE_STATIC (gsd_smartcard_tokens); + +G_DEFINE_TYPE_WITH_CODE (GsdSmartcardService, + gsd_smartcard_service, + GSD_SMARTCARD_SERVICE_TYPE_MANAGER_SKELETON, + G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, + async_initable_interface_init) + G_IMPLEMENT_INTERFACE (GSD_SMARTCARD_SERVICE_TYPE_MANAGER, + smartcard_service_manager_interface_init)); + +static void +set_bus_connection (GsdSmartcardService *self, + GDBusConnection *connection) +{ + if (self->bus_connection != connection) { + g_clear_object (&self->bus_connection); + self->bus_connection = g_object_ref (connection); + g_object_notify (G_OBJECT (self), "bus-connection"); + } +} + +static void +register_object_manager (GsdSmartcardService *self) +{ + GsdSmartcardServiceObjectSkeleton *object; + + self->object_manager_server = g_dbus_object_manager_server_new (GSD_SMARTCARD_DBUS_PATH); + + object = gsd_smartcard_service_object_skeleton_new (GSD_SMARTCARD_MANAGER_DBUS_PATH); + gsd_smartcard_service_object_skeleton_set_manager (object, + GSD_SMARTCARD_SERVICE_MANAGER (self)); + + g_dbus_object_manager_server_export (self->object_manager_server, + G_DBUS_OBJECT_SKELETON (object)); + g_object_unref (object); + + g_dbus_object_manager_server_set_connection (self->object_manager_server, + self->bus_connection); +} + +static const char * +get_login_token_object_path (GsdSmartcardService *self) +{ + return GSD_SMARTCARD_MANAGER_TOKENS_DBUS_PATH "/login_token"; +} + +static void +register_login_token_alias (GsdSmartcardService *self) +{ + GDBusObjectSkeleton *object; + GDBusInterfaceSkeleton *interface; + const char *object_path; + const char *token_name; + + token_name = g_getenv ("PKCS11_LOGIN_TOKEN_NAME"); + + if (token_name == NULL) + return; + + object_path = get_login_token_object_path (self); + object = G_DBUS_OBJECT_SKELETON (gsd_smartcard_service_object_skeleton_new (object_path)); + interface = G_DBUS_INTERFACE_SKELETON (gsd_smartcard_service_token_skeleton_new ()); + + g_dbus_object_skeleton_add_interface (object, interface); + g_object_unref (interface); + + g_object_set (G_OBJECT (interface), + "name", token_name, + "used-to-login", TRUE, + "is-inserted", FALSE, + NULL); + + g_dbus_object_manager_server_export (self->object_manager_server, + object); + + G_LOCK (gsd_smartcard_tokens); + g_hash_table_insert (self->tokens, g_strdup (object_path), interface); + G_UNLOCK (gsd_smartcard_tokens); +} + +static void +on_bus_gotten (GObject *source_object, + GAsyncResult *result, + GTask *task) +{ + GsdSmartcardService *self; + GDBusConnection *connection; + GError *error = NULL; + + connection = g_bus_get_finish (result, &error); + if (connection == NULL) { + g_task_return_error (task, error); + goto out; + } + + g_debug ("taking name %s on session bus", GSD_SMARTCARD_DBUS_NAME); + + self = g_task_get_source_object (task); + + set_bus_connection (self, connection); + + register_object_manager (self); + self->name_id = g_bus_own_name_on_connection (connection, + GSD_SMARTCARD_DBUS_NAME, + G_BUS_NAME_OWNER_FLAGS_NONE, + NULL, + NULL, + NULL, + NULL); + + /* In case the login token is removed at start up, register an + * an alias interface that's always around + */ + register_login_token_alias (self); + g_task_return_boolean (task, TRUE); + +out: + g_object_unref (task); + return; +} + +static gboolean +gsd_smartcard_service_initable_init_finish (GAsyncInitable *initable, + GAsyncResult *result, + GError **error) +{ + GTask *task; + + task = G_TASK (result); + + return g_task_propagate_boolean (task, error); +} + +static void +gsd_smartcard_service_initable_init_async (GAsyncInitable *initable, + int io_priority, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GsdSmartcardService *self = GSD_SMARTCARD_SERVICE (initable); + GTask *task; + + task = g_task_new (G_OBJECT (self), cancellable, callback, user_data); + g_task_set_priority (task, io_priority); + + g_bus_get (G_BUS_TYPE_SESSION, cancellable, (GAsyncReadyCallback) on_bus_gotten, task); +} + +static void +async_initable_interface_init (GAsyncInitableIface *interface) +{ + interface->init_async = gsd_smartcard_service_initable_init_async; + interface->init_finish = gsd_smartcard_service_initable_init_finish; +} + +static char * +get_object_path_for_token (GsdSmartcardService *self, + PK11SlotInfo *card_slot) +{ + char *object_path; + char *escaped_library_path; + SECMODModule *driver; + CK_SLOT_ID slot_id; + + driver = PK11_GetModule (card_slot); + slot_id = PK11_GetSlotID (card_slot); + + escaped_library_path = gsd_smartcard_utils_escape_object_path (driver->dllName); + + object_path = g_strdup_printf ("%s/token_from_%s_slot_%lu", + GSD_SMARTCARD_MANAGER_TOKENS_DBUS_PATH, + escaped_library_path, + (gulong) slot_id); + g_free (escaped_library_path); + + return object_path; +} + +static gboolean +gsd_smartcard_service_handle_get_login_token (GsdSmartcardServiceManager *manager, + GDBusMethodInvocation *invocation) +{ + GsdSmartcardService *self = GSD_SMARTCARD_SERVICE (manager); + PK11SlotInfo *card_slot; + char *object_path; + + card_slot = gsd_smartcard_manager_get_login_token (self->smartcard_manager); + + if (card_slot == NULL) { + const char *login_token_object_path; + + /* If we know there's a login token but it was removed before the + * smartcard manager could examine it, just return the generic login + * token object path + */ + login_token_object_path = get_login_token_object_path (self); + + if (g_hash_table_contains (self->tokens, login_token_object_path)) { + gsd_smartcard_service_manager_complete_get_login_token (manager, + invocation, + login_token_object_path); + return TRUE; + } + + g_dbus_method_invocation_return_error (invocation, + GSD_SMARTCARD_MANAGER_ERROR, + GSD_SMARTCARD_MANAGER_ERROR_FINDING_SMARTCARD, + _("User was not logged in with smartcard.")); + + return TRUE; + } + + object_path = get_object_path_for_token (self, card_slot); + gsd_smartcard_service_manager_complete_get_login_token (manager, + invocation, + object_path); + g_free (object_path); + + return TRUE; +} + +static gboolean +gsd_smartcard_service_handle_get_inserted_tokens (GsdSmartcardServiceManager *manager, + GDBusMethodInvocation *invocation) +{ + GsdSmartcardService *self = GSD_SMARTCARD_SERVICE (manager); + GList *inserted_tokens, *node; + GPtrArray *object_paths; + + inserted_tokens = gsd_smartcard_manager_get_inserted_tokens (self->smartcard_manager, + NULL); + + object_paths = g_ptr_array_new (); + for (node = inserted_tokens; node != NULL; node = node->next) { + PK11SlotInfo *card_slot = node->data; + char *object_path; + + object_path = get_object_path_for_token (self, card_slot); + g_ptr_array_add (object_paths, object_path); + } + g_ptr_array_add (object_paths, NULL); + g_list_free (inserted_tokens); + + gsd_smartcard_service_manager_complete_get_inserted_tokens (manager, + invocation, + (const char * const *) object_paths->pdata); + + g_ptr_array_free (object_paths, TRUE); + + return TRUE; +} + +static void +smartcard_service_manager_interface_init (GsdSmartcardServiceManagerIface *interface) +{ + interface->handle_get_login_token = gsd_smartcard_service_handle_get_login_token; + interface->handle_get_inserted_tokens = gsd_smartcard_service_handle_get_inserted_tokens; +} + +static void +gsd_smartcard_service_init (GsdSmartcardService *self) +{ + self->tokens = g_hash_table_new_full (g_str_hash, + g_str_equal, + (GDestroyNotify) g_free, + NULL); +} + +static void +gsd_smartcard_service_dispose (GObject *object) +{ + GsdSmartcardService *self = GSD_SMARTCARD_SERVICE (object); + + g_clear_object (&self->bus_connection); + g_clear_object (&self->object_manager_server); + g_clear_object (&self->smartcard_manager); + + g_cancellable_cancel (self->cancellable); + g_clear_object (&self->cancellable); + g_clear_pointer (&self->tokens, g_hash_table_unref); + + G_OBJECT_CLASS (gsd_smartcard_service_parent_class)->dispose (object); +} + +static void +gsd_smartcard_service_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *param_spec) +{ + GsdSmartcardService *self = GSD_SMARTCARD_SERVICE (object); + + switch (property_id) { + case PROP_MANAGER: + self->smartcard_manager = g_value_dup_object (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, param_spec); + break; + } +} + +static void +gsd_smartcard_service_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *param_spec) +{ + GsdSmartcardService *self = GSD_SMARTCARD_SERVICE (object); + + switch (property_id) { + case PROP_MANAGER: + g_value_set_object (value, self->smartcard_manager); + break; + case PROP_BUS_CONNECTION: + g_value_set_object (value, self->bus_connection); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, param_spec); + break; + } +} + +static void +gsd_smartcard_service_class_init (GsdSmartcardServiceClass *service_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (service_class); + GParamSpec *param_spec; + + object_class->dispose = gsd_smartcard_service_dispose; + object_class->set_property = gsd_smartcard_service_set_property; + object_class->get_property = gsd_smartcard_service_get_property; + + param_spec = g_param_spec_object ("manager", + "Smartcard Manager", + "Smartcard Manager", + GSD_TYPE_SMARTCARD_MANAGER, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); + g_object_class_install_property (object_class, PROP_MANAGER, param_spec); + param_spec = g_param_spec_object ("bus-connection", + "Bus Connection", + "bus connection", + G_TYPE_DBUS_CONNECTION, + G_PARAM_READABLE); + g_object_class_install_property (object_class, PROP_BUS_CONNECTION, param_spec); +} + +static void +on_new_async_finished (GObject *source_object, + GAsyncResult *result, + GTask *task) +{ + GError *error = NULL; + GObject *object; + + object = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), + result, + &error); + + if (object == NULL) { + g_task_return_error (task, error); + goto out; + } + + g_assert (GSD_IS_SMARTCARD_SERVICE (object)); + + g_task_return_pointer (task, object, g_object_unref); +out: + g_object_unref (task); + return; +} + +void +gsd_smartcard_service_new_async (GsdSmartcardManager *manager, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GTask *task; + + task = g_task_new (NULL, cancellable, callback, user_data); + + g_async_initable_new_async (GSD_TYPE_SMARTCARD_SERVICE, + G_PRIORITY_DEFAULT, + cancellable, + (GAsyncReadyCallback) on_new_async_finished, + task, + "manager", manager, + NULL); +} + +GsdSmartcardService * +gsd_smartcard_service_new_finish (GAsyncResult *result, + GError **error) +{ + GTask *task; + GsdSmartcardService *self = NULL; + + task = G_TASK (result); + + self = g_task_propagate_pointer (task, error); + + if (self == NULL) + return self; + + return g_object_ref (self); +} + +static char * +get_object_path_for_driver (GsdSmartcardService *self, + SECMODModule *driver) +{ + char *object_path; + char *escaped_library_path; + + escaped_library_path = gsd_smartcard_utils_escape_object_path (driver->dllName); + + object_path = g_build_path ("/", + GSD_SMARTCARD_MANAGER_DRIVERS_DBUS_PATH, + escaped_library_path, NULL); + g_free (escaped_library_path); + + return object_path; +} + +void +gsd_smartcard_service_register_driver (GsdSmartcardService *self, + SECMODModule *driver) +{ + char *object_path; + GDBusObjectSkeleton *object; + GDBusInterfaceSkeleton *interface; + + object_path = get_object_path_for_driver (self, driver); + object = G_DBUS_OBJECT_SKELETON (gsd_smartcard_service_object_skeleton_new (object_path)); + g_free (object_path); + + interface = G_DBUS_INTERFACE_SKELETON (gsd_smartcard_service_driver_skeleton_new ()); + g_dbus_object_skeleton_add_interface (object, interface); + g_object_unref (interface); + + g_object_set (G_OBJECT (interface), + "library", driver->dllName, + "description", driver->commonName, + NULL); + g_dbus_object_manager_server_export (self->object_manager_server, + object); + g_object_unref (object); +} + +static void +synchronize_token_now (GsdSmartcardService *self, + PK11SlotInfo *card_slot) +{ + GDBusInterfaceSkeleton *interface; + char *object_path; + const char *token_name; + gboolean is_present, is_login_card; + + object_path = get_object_path_for_token (self, card_slot); + + G_LOCK (gsd_smartcard_tokens); + interface = g_hash_table_lookup (self->tokens, object_path); + g_free (object_path); + + if (interface == NULL) + goto out; + + token_name = PK11_GetTokenName (card_slot); + is_present = PK11_IsPresent (card_slot); + + if (g_strcmp0 (g_getenv ("PKCS11_LOGIN_TOKEN_NAME"), token_name) == 0) + is_login_card = TRUE; + else + is_login_card = FALSE; + + g_debug ("==============================="); + g_debug (" Token '%s'", token_name); + g_debug (" Inserted: %s", is_present? "yes" : "no"); + g_debug (" Previously used to login: %s", is_login_card? "yes" : "no"); + g_debug ("===============================\n"); + + if (!is_present && is_login_card) { + gboolean was_present; + + g_object_get (G_OBJECT (interface), + "is-inserted", &was_present, + NULL); + + if (was_present) + gsd_smartcard_manager_do_remove_action (self->smartcard_manager); + } + + g_object_set (G_OBJECT (interface), + "used-to-login", is_login_card, + "is-inserted", is_present, + NULL); + g_object_get (G_OBJECT (interface), + "used-to-login", &is_login_card, + "is-inserted", &is_present, + NULL); + + if (is_login_card && !self->login_token_bound) { + const char *login_token_path; + GDBusInterfaceSkeleton *login_token_interface; + + login_token_path = get_login_token_object_path (self); + login_token_interface = g_hash_table_lookup (self->tokens, login_token_path); + + if (login_token_interface != NULL) { + g_object_bind_property (interface, "driver", + login_token_interface, "driver", + G_BINDING_SYNC_CREATE); + g_object_bind_property (interface, "is-inserted", + login_token_interface, "is-inserted", + G_BINDING_SYNC_CREATE); + self->login_token_bound = TRUE; + } + } + +out: + G_UNLOCK (gsd_smartcard_tokens); +} + +typedef struct +{ + PK11SlotInfo *card_slot; + char *object_path; + GSource *main_thread_source; +} RegisterNewTokenOperation; + +static void +destroy_register_new_token_operation (RegisterNewTokenOperation *operation) +{ + g_clear_pointer (&operation->main_thread_source, + g_source_destroy); + PK11_FreeSlot (operation->card_slot); + g_free (operation->object_path); + g_free (operation); +} + +static gboolean +on_main_thread_to_register_new_token (GTask *task) +{ + GsdSmartcardService *self; + GDBusObjectSkeleton *object; + GDBusInterfaceSkeleton *interface; + RegisterNewTokenOperation *operation; + SECMODModule *driver; + char *driver_object_path; + const char *token_name; + + self = g_task_get_source_object (task); + + operation = g_task_get_task_data (task); + operation->main_thread_source = NULL; + + object = G_DBUS_OBJECT_SKELETON (gsd_smartcard_service_object_skeleton_new (operation->object_path)); + interface = G_DBUS_INTERFACE_SKELETON (gsd_smartcard_service_token_skeleton_new ()); + + g_dbus_object_skeleton_add_interface (object, interface); + g_object_unref (interface); + + driver = PK11_GetModule (operation->card_slot); + driver_object_path = get_object_path_for_driver (self, driver); + + token_name = PK11_GetTokenName (operation->card_slot); + + g_object_set (G_OBJECT (interface), + "driver", driver_object_path, + "name", token_name, + NULL); + g_free (driver_object_path); + + g_dbus_object_manager_server_export (self->object_manager_server, + object); + + G_LOCK (gsd_smartcard_tokens); + g_hash_table_insert (self->tokens, g_strdup (operation->object_path), interface); + G_UNLOCK (gsd_smartcard_tokens); + + g_task_return_boolean (task, TRUE); + g_object_unref (task); + + return G_SOURCE_REMOVE; +} + +static void +create_main_thread_source (GSourceFunc callback, + gpointer user_data, + GSource **source_out) +{ + GSource *source; + + source = g_idle_source_new (); + g_source_set_callback (source, callback, user_data, NULL); + + *source_out = source; + g_source_attach (source, NULL); + g_source_unref (source); +} + +static void +register_new_token_in_main_thread (GsdSmartcardService *self, + PK11SlotInfo *card_slot, + char *object_path, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + RegisterNewTokenOperation *operation; + GTask *task; + + operation = g_new0 (RegisterNewTokenOperation, 1); + operation->card_slot = PK11_ReferenceSlot (card_slot); + operation->object_path = g_strdup (object_path); + + task = g_task_new (self, cancellable, callback, user_data); + + g_task_set_task_data (task, + operation, + (GDestroyNotify) destroy_register_new_token_operation); + + create_main_thread_source ((GSourceFunc) on_main_thread_to_register_new_token, + task, + &operation->main_thread_source); +} + +static gboolean +register_new_token_in_main_thread_finish (GsdSmartcardService *self, + GAsyncResult *result, + GError **error) +{ + return g_task_propagate_boolean (G_TASK (result), error); +} + +static void +on_token_registered (GsdSmartcardService *self, + GAsyncResult *result, + PK11SlotInfo *card_slot) +{ + gboolean registered; + GError *error = NULL; + + registered = register_new_token_in_main_thread_finish (self, result, &error); + + if (!registered) { + g_debug ("Couldn't register token: %s", + error->message); + goto out; + } + + synchronize_token_now (self, card_slot); + +out: + PK11_FreeSlot (card_slot); +} + +typedef struct +{ + PK11SlotInfo *card_slot; + GSource *main_thread_source; +} SynchronizeTokenOperation; + +static void +destroy_synchronize_token_operation (SynchronizeTokenOperation *operation) +{ + g_clear_pointer (&operation->main_thread_source, + g_source_destroy); + PK11_FreeSlot (operation->card_slot); + g_free (operation); +} + +static gboolean +on_main_thread_to_synchronize_token (GTask *task) +{ + GsdSmartcardService *self; + SynchronizeTokenOperation *operation; + + self = g_task_get_source_object (task); + + operation = g_task_get_task_data (task); + operation->main_thread_source = NULL; + + synchronize_token_now (self, operation->card_slot); + + g_task_return_boolean (task, TRUE); + g_object_unref (task); + + return G_SOURCE_REMOVE; +} + +static gboolean +synchronize_token_in_main_thread_finish (GsdSmartcardService *self, + GAsyncResult *result, + GError **error) +{ + return g_task_propagate_boolean (G_TASK (result), error); +} + +static void +synchronize_token_in_main_thread (GsdSmartcardService *self, + PK11SlotInfo *card_slot, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + SynchronizeTokenOperation *operation; + GTask *task; + + operation = g_new0 (SynchronizeTokenOperation, 1); + operation->card_slot = PK11_ReferenceSlot (card_slot); + + task = g_task_new (self, cancellable, callback, user_data); + + g_task_set_task_data (task, + operation, + (GDestroyNotify) + destroy_synchronize_token_operation); + + create_main_thread_source ((GSourceFunc) + on_main_thread_to_synchronize_token, + task, + &operation->main_thread_source); +} + +static void +on_token_synchronized (GsdSmartcardService *self, + GAsyncResult *result, + PK11SlotInfo *card_slot) +{ + gboolean synchronized; + GError *error = NULL; + + synchronized = synchronize_token_in_main_thread_finish (self, result, &error); + + if (!synchronized) + g_debug ("Couldn't synchronize token: %s", error->message); + + PK11_FreeSlot (card_slot); +} + +void +gsd_smartcard_service_sync_token (GsdSmartcardService *self, + PK11SlotInfo *card_slot, + GCancellable *cancellable) +{ + char *object_path; + GDBusInterfaceSkeleton *interface; + + object_path = get_object_path_for_token (self, card_slot); + + G_LOCK (gsd_smartcard_tokens); + interface = g_hash_table_lookup (self->tokens, object_path); + G_UNLOCK (gsd_smartcard_tokens); + + if (interface == NULL) + register_new_token_in_main_thread (self, + card_slot, + object_path, + cancellable, + (GAsyncReadyCallback) + on_token_registered, + PK11_ReferenceSlot (card_slot)); + + else + synchronize_token_in_main_thread (self, + card_slot, + cancellable, + (GAsyncReadyCallback) + on_token_synchronized, + PK11_ReferenceSlot (card_slot)); + + g_free (object_path); +} |