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