You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
339 lines
12 KiB
339 lines
12 KiB
From 0665bd86221d3c9012f0391d8e4939a2d12b6417 Mon Sep 17 00:00:00 2001 |
|
From: Ray Strode <rstrode@redhat.com> |
|
Date: Fri, 9 Feb 2018 16:39:12 -0500 |
|
Subject: [PATCH 1/2] smartcard: Wait until smartcards are inspected before |
|
locking screen |
|
|
|
There's a race condition in the code where we check if the screen should |
|
be locked (because the smartcard is removed) before we necessarly check |
|
the smartcard's insertion status. |
|
|
|
This commit fixes the race by iterating through all smartcards at |
|
startup and checking their status explicitly. |
|
--- |
|
plugins/smartcard/gsd-smartcard-manager.c | 61 ++++++++++++++++++----- |
|
1 file changed, 49 insertions(+), 12 deletions(-) |
|
|
|
diff --git a/plugins/smartcard/gsd-smartcard-manager.c b/plugins/smartcard/gsd-smartcard-manager.c |
|
index a6245425..94ffdd90 100644 |
|
--- a/plugins/smartcard/gsd-smartcard-manager.c |
|
+++ b/plugins/smartcard/gsd-smartcard-manager.c |
|
@@ -37,64 +37,73 @@ |
|
#include <secmod.h> |
|
#include <secerr.h> |
|
|
|
#define GSD_SMARTCARD_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_SMARTCARD_MANAGER, GsdSmartcardManagerPrivate)) |
|
|
|
#define GSD_SESSION_MANAGER_LOGOUT_MODE_FORCE 2 |
|
|
|
struct GsdSmartcardManagerPrivate |
|
{ |
|
guint start_idle_id; |
|
GsdSmartcardService *service; |
|
GList *smartcards_watch_tasks; |
|
GCancellable *cancellable; |
|
|
|
GsdSessionManager *session_manager; |
|
GsdScreenSaver *screen_saver; |
|
|
|
GSettings *settings; |
|
|
|
NSSInitContext *nss_context; |
|
}; |
|
|
|
#define CONF_SCHEMA "org.gnome.settings-daemon.peripherals.smartcard" |
|
#define KEY_REMOVE_ACTION "removal-action" |
|
|
|
static void gsd_smartcard_manager_class_init (GsdSmartcardManagerClass *klass); |
|
static void gsd_smartcard_manager_init (GsdSmartcardManager *self); |
|
static void gsd_smartcard_manager_finalize (GObject *object); |
|
static void lock_screen (GsdSmartcardManager *self); |
|
static void log_out (GsdSmartcardManager *self); |
|
+static void on_smartcards_from_driver_watched (GsdSmartcardManager *self, |
|
+ GAsyncResult *result, |
|
+ GTask *task); |
|
G_DEFINE_TYPE (GsdSmartcardManager, gsd_smartcard_manager, G_TYPE_OBJECT) |
|
G_DEFINE_QUARK (gsd-smartcard-manager-error, gsd_smartcard_manager_error) |
|
G_LOCK_DEFINE_STATIC (gsd_smartcards_watch_tasks); |
|
|
|
+typedef struct { |
|
+ SECMODModule *driver; |
|
+ guint idle_id; |
|
+ GError *error; |
|
+} DriverRegistrationOperation; |
|
+ |
|
static gpointer manager_object = NULL; |
|
|
|
static void |
|
gsd_smartcard_manager_class_init (GsdSmartcardManagerClass *klass) |
|
{ |
|
GObjectClass *object_class = G_OBJECT_CLASS (klass); |
|
|
|
object_class->finalize = gsd_smartcard_manager_finalize; |
|
|
|
gsd_smartcard_utils_register_error_domain (GSD_SMARTCARD_MANAGER_ERROR, |
|
GSD_TYPE_SMARTCARD_MANAGER_ERROR); |
|
g_type_class_add_private (klass, sizeof (GsdSmartcardManagerPrivate)); |
|
} |
|
|
|
static void |
|
gsd_smartcard_manager_init (GsdSmartcardManager *self) |
|
{ |
|
self->priv = GSD_SMARTCARD_MANAGER_GET_PRIVATE (self); |
|
} |
|
|
|
static void |
|
load_nss (GsdSmartcardManager *self) |
|
{ |
|
GsdSmartcardManagerPrivate *priv = self->priv; |
|
NSSInitContext *context = NULL; |
|
|
|
/* The first field in the NSSInitParameters structure |
|
* is the size of the structure. NSS requires this, so |
|
* that it can change the size of the structure in future |
|
* versions of NSS in a detectable way |
|
@@ -291,135 +300,168 @@ watch_smartcards_from_driver (GTask *task, |
|
break; |
|
} |
|
|
|
if (!watch_succeeded) { |
|
g_task_return_error (task, error); |
|
break; |
|
} |
|
} |
|
} |
|
|
|
static void |
|
destroy_watch_smartcards_operation (WatchSmartcardsOperation *operation) |
|
{ |
|
SECMOD_DestroyModule (operation->driver); |
|
g_hash_table_unref (operation->smartcards); |
|
g_free (operation); |
|
} |
|
|
|
static void |
|
on_smartcards_watch_task_destroyed (GsdSmartcardManager *self, |
|
GTask *freed_task) |
|
{ |
|
GsdSmartcardManagerPrivate *priv = self->priv; |
|
|
|
G_LOCK (gsd_smartcards_watch_tasks); |
|
priv->smartcards_watch_tasks = g_list_remove (priv->smartcards_watch_tasks, |
|
freed_task); |
|
G_UNLOCK (gsd_smartcards_watch_tasks); |
|
} |
|
|
|
+static void |
|
+sync_initial_tokens_from_driver (GsdSmartcardManager *self, |
|
+ SECMODModule *driver, |
|
+ GHashTable *smartcards, |
|
+ GCancellable *cancellable) |
|
+{ |
|
+ GsdSmartcardManagerPrivate *priv = self->priv; |
|
+ int i; |
|
+ |
|
+ for (i = 0; i < driver->slotCount; i++) { |
|
+ PK11SlotInfo *card; |
|
+ |
|
+ card = driver->slots[i]; |
|
+ |
|
+ if (PK11_IsPresent (card)) { |
|
+ CK_SLOT_ID slot_id; |
|
+ slot_id = PK11_GetSlotID (card); |
|
+ |
|
+ g_debug ("Detected smartcard in slot %d at start up", (int) slot_id); |
|
+ |
|
+ g_hash_table_replace (smartcards, |
|
+ GINT_TO_POINTER ((int) slot_id), |
|
+ PK11_ReferenceSlot (card)); |
|
+ gsd_smartcard_service_sync_token (priv->service, card, cancellable); |
|
+ } |
|
+ } |
|
+} |
|
+ |
|
static void |
|
watch_smartcards_from_driver_async (GsdSmartcardManager *self, |
|
SECMODModule *driver, |
|
GCancellable *cancellable, |
|
GAsyncReadyCallback callback, |
|
gpointer user_data) |
|
{ |
|
GsdSmartcardManagerPrivate *priv = self->priv; |
|
GTask *task; |
|
WatchSmartcardsOperation *operation; |
|
|
|
operation = g_new0 (WatchSmartcardsOperation, 1); |
|
operation->driver = SECMOD_ReferenceModule (driver); |
|
operation->smartcards = g_hash_table_new_full (g_direct_hash, |
|
g_direct_equal, |
|
NULL, |
|
(GDestroyNotify) PK11_FreeSlot); |
|
|
|
task = g_task_new (self, cancellable, callback, user_data); |
|
|
|
g_task_set_task_data (task, |
|
operation, |
|
(GDestroyNotify) destroy_watch_smartcards_operation); |
|
|
|
G_LOCK (gsd_smartcards_watch_tasks); |
|
priv->smartcards_watch_tasks = g_list_prepend (priv->smartcards_watch_tasks, |
|
task); |
|
g_object_weak_ref (G_OBJECT (task), |
|
(GWeakNotify) on_smartcards_watch_task_destroyed, |
|
self); |
|
G_UNLOCK (gsd_smartcards_watch_tasks); |
|
|
|
+ sync_initial_tokens_from_driver (self, driver, operation->smartcards, cancellable); |
|
+ |
|
g_task_run_in_thread (task, (GTaskThreadFunc) watch_smartcards_from_driver); |
|
} |
|
|
|
static gboolean |
|
register_driver_finish (GsdSmartcardManager *self, |
|
GAsyncResult *result, |
|
GError **error) |
|
{ |
|
return g_task_propagate_boolean (G_TASK (result), error); |
|
} |
|
|
|
static void |
|
on_driver_registered (GsdSmartcardManager *self, |
|
GAsyncResult *result, |
|
GTask *task) |
|
{ |
|
GError *error = NULL; |
|
+ DriverRegistrationOperation *operation; |
|
+ GsdSmartcardManagerPrivate *priv = self->priv; |
|
+ |
|
+ operation = g_task_get_task_data (G_TASK (result)); |
|
|
|
if (!register_driver_finish (self, result, &error)) { |
|
g_task_return_error (task, error); |
|
g_object_unref (task); |
|
return; |
|
} |
|
|
|
- g_task_return_boolean (task, TRUE); |
|
+ watch_smartcards_from_driver_async (self, |
|
+ operation->driver, |
|
+ priv->cancellable, |
|
+ (GAsyncReadyCallback) on_smartcards_from_driver_watched, |
|
+ task); |
|
|
|
+ g_task_return_boolean (task, TRUE); |
|
g_object_unref (task); |
|
} |
|
|
|
static void |
|
on_smartcards_from_driver_watched (GsdSmartcardManager *self, |
|
GAsyncResult *result, |
|
GTask *task) |
|
{ |
|
g_debug ("Done watching smartcards from driver"); |
|
} |
|
|
|
-typedef struct { |
|
- SECMODModule *driver; |
|
- guint idle_id; |
|
- GError *error; |
|
-} DriverRegistrationOperation; |
|
- |
|
static void |
|
destroy_driver_registration_operation (DriverRegistrationOperation *operation) |
|
{ |
|
SECMOD_DestroyModule (operation->driver); |
|
g_free (operation); |
|
} |
|
|
|
static gboolean |
|
on_task_thread_to_complete_driver_registration (GTask *task) |
|
{ |
|
DriverRegistrationOperation *operation; |
|
operation = g_task_get_task_data (task); |
|
|
|
if (operation->error != NULL) |
|
g_task_return_error (task, operation->error); |
|
else |
|
g_task_return_boolean (task, TRUE); |
|
|
|
return G_SOURCE_REMOVE; |
|
} |
|
|
|
static gboolean |
|
on_main_thread_to_register_driver (GTask *task) |
|
{ |
|
GsdSmartcardManager *self; |
|
GsdSmartcardManagerPrivate *priv; |
|
DriverRegistrationOperation *operation; |
|
GSource *source; |
|
|
|
self = g_task_get_source_object (task); |
|
@@ -450,65 +492,60 @@ register_driver (GsdSmartcardManager *self, |
|
|
|
task = g_task_new (self, cancellable, callback, user_data); |
|
operation = g_new0 (DriverRegistrationOperation, 1); |
|
operation->driver = SECMOD_ReferenceModule (driver); |
|
g_task_set_task_data (task, |
|
operation, |
|
(GDestroyNotify) destroy_driver_registration_operation); |
|
|
|
operation->idle_id = g_idle_add ((GSourceFunc) on_main_thread_to_register_driver, task); |
|
g_source_set_name_by_id (operation->idle_id, "[gnome-settings-daemon] on_main_thread_to_register_driver"); |
|
} |
|
|
|
static void |
|
activate_driver (GsdSmartcardManager *self, |
|
SECMODModule *driver, |
|
GCancellable *cancellable, |
|
GAsyncReadyCallback callback, |
|
gpointer user_data) |
|
{ |
|
GTask *task; |
|
|
|
g_debug ("Activating driver '%s'", driver->commonName); |
|
|
|
task = g_task_new (self, cancellable, callback, user_data); |
|
|
|
register_driver (self, |
|
driver, |
|
cancellable, |
|
(GAsyncReadyCallback) on_driver_registered, |
|
task); |
|
- watch_smartcards_from_driver_async (self, |
|
- driver, |
|
- cancellable, |
|
- (GAsyncReadyCallback) on_smartcards_from_driver_watched, |
|
- task); |
|
} |
|
|
|
typedef struct |
|
{ |
|
int pending_drivers_count; |
|
int activated_drivers_count; |
|
} ActivateAllDriversOperation; |
|
|
|
static gboolean |
|
activate_driver_async_finish (GsdSmartcardManager *self, |
|
GAsyncResult *result, |
|
GError **error) |
|
{ |
|
return g_task_propagate_boolean (G_TASK (result), error); |
|
} |
|
|
|
static void |
|
try_to_complete_all_drivers_activation (GTask *task) |
|
{ |
|
ActivateAllDriversOperation *operation; |
|
|
|
operation = g_task_get_task_data (task); |
|
|
|
if (operation->pending_drivers_count > 0) |
|
return; |
|
|
|
if (operation->activated_drivers_count > 0) |
|
g_task_return_boolean (task, TRUE); |
|
else |
|
g_task_return_new_error (task, GSD_SMARTCARD_MANAGER_ERROR, |
|
-- |
|
2.17.0 |
|
|
|
|