Blame SOURCES/0001-smartcard-Wait-until-smartcards-are-inspected-before.patch

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