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

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