[gnome-settings-daemon] smartcard: support old card removal actions



commit 92460adeaaa9707958e972b9f6b2cfefe7a50f71
Author: Ray Strode <rstrode redhat com>
Date:   Mon Jul 29 00:02:04 2013 -0400

    smartcard: support old card removal actions
    
    The old smartcard plugin supported a feature where the screen
    would lock or the session would get logged out if a user
    yanked their login token.
    
    This commit adds that feature back.

 plugins/smartcard/gsd-smartcard-manager.c |  170 ++++++++++++++++++++++++++++-
 plugins/smartcard/gsd-smartcard-manager.h |    1 +
 plugins/smartcard/gsd-smartcard-service.c |   11 ++
 3 files changed, 181 insertions(+), 1 deletions(-)
---
diff --git a/plugins/smartcard/gsd-smartcard-manager.c b/plugins/smartcard/gsd-smartcard-manager.c
index 14c2f71..4ac31ae 100644
--- a/plugins/smartcard/gsd-smartcard-manager.c
+++ b/plugins/smartcard/gsd-smartcard-manager.c
@@ -31,6 +31,9 @@
 #include "gsd-smartcard-enum-types.h"
 #include "gsd-smartcard-utils.h"
 
+#include "org.gnome.ScreenSaver.h"
+#include "org.gnome.SessionManager.h"
+
 #include <prerror.h>
 #include <prinit.h>
 #include <nss.h>
@@ -40,6 +43,8 @@
 
 #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;
@@ -47,16 +52,22 @@ struct GsdSmartcardManagerPrivate
         GList *smartcards_watch_tasks;
         GCancellable *cancellable;
 
+        GsdSessionManager *session_manager;
+        GsdScreenSaver *screen_saver;
+
         GSettings *settings;
 
         guint32 nss_is_loaded : 1;
 };
 
 #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);
 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);
@@ -221,7 +232,6 @@ watch_one_event_from_driver (GsdSmartcardManager       *self,
                                       PK11_ReferenceSlot (card));
 
                 gsd_smartcard_service_sync_token (priv->service, card, cancellable);
-
         } else if (old_card == NULL) {
                 /* If the just removed smartcard is not known to us then
                  * ignore the removal event. NSS sends a synthentic removal
@@ -556,6 +566,7 @@ on_all_drivers_activated (GsdSmartcardManager *self,
 {
         GError *error = NULL;
         gboolean driver_activated;
+        PK11SlotInfo *login_token;
 
         driver_activated = activate_all_drivers_async_finish (self, result, &error);
 
@@ -564,6 +575,16 @@ on_all_drivers_activated (GsdSmartcardManager *self,
                 return;
         }
 
+        login_token = gsd_smartcard_manager_get_login_token (self);
+
+        if (login_token || g_getenv ("PKCS11_LOGIN_TOKEN_NAME") != NULL) {
+                /* The card used to log in was removed before login completed.
+                 * Do removal action immediately
+                 */
+                if (!login_token || !PK11_IsPresent (login_token))
+                        gsd_smartcard_manager_do_remove_action (self);
+        }
+
         g_task_return_boolean (task, TRUE);
 }
 
@@ -703,6 +724,153 @@ gsd_smartcard_manager_stop (GsdSmartcardManager *self)
 
         g_clear_object (&priv->settings);
         g_clear_object (&priv->cancellable);
+        g_clear_object (&priv->session_manager);
+        g_clear_object (&priv->screen_saver);
+}
+
+static void
+on_got_screen_saver_to_lock_screen (GObject             *object,
+                                    GAsyncResult        *result,
+                                    GsdSmartcardManager *self)
+{
+        GsdSmartcardManagerPrivate *priv = self->priv;
+        GsdScreenSaver *screen_saver;
+        GError *error = NULL;
+
+        screen_saver = gsd_screen_saver_proxy_new_for_bus_finish (result, &error);
+
+        if (screen_saver == NULL) {
+                g_warning ("Couldn't find screen saver service to lock screen: %s",
+                           error->message);
+                g_error_free (error);
+                return;
+        }
+
+        if (priv->screen_saver != NULL)
+                g_object_unref (screen_saver);
+
+        priv->screen_saver = screen_saver;
+
+        lock_screen (self);
+}
+
+static void
+on_screen_locked (GsdScreenSaver      *screen_saver,
+                  GAsyncResult        *result,
+                  GsdSmartcardManager *self)
+{
+        gboolean is_locked;
+        GError *error = NULL;
+
+        is_locked = gsd_screen_saver_call_lock_finish (screen_saver, result, &error);
+
+        if (!is_locked) {
+                g_warning ("Couldn't lock screen: %s", error->message);
+                g_error_free (error);
+                return;
+        }
+}
+
+static void
+lock_screen (GsdSmartcardManager *self)
+{
+        GsdSmartcardManagerPrivate *priv = self->priv;
+
+        if (priv->screen_saver == NULL) {
+                gsd_screen_saver_proxy_new_for_bus (G_BUS_TYPE_SESSION,
+                                                    G_DBUS_PROXY_FLAGS_NONE,
+                                                    "org.gnome.ScreenSaver",
+                                                    "/org/gnome/ScreenSaver",
+                                                    priv->cancellable,
+                                                    (GAsyncReadyCallback) on_got_screen_saver_to_lock_screen,
+                                                    self);
+                return;
+        }
+
+        gsd_screen_saver_call_lock (priv->screen_saver,
+                                    priv->cancellable,
+                                    (GAsyncReadyCallback) on_screen_locked,
+                                    self);
+}
+
+static void
+on_got_session_manager_to_log_out (GObject             *object,
+                                   GAsyncResult        *result,
+                                   GsdSmartcardManager *self)
+{
+        GsdSmartcardManagerPrivate *priv = self->priv;
+        GsdSessionManager *session_manager;
+        GError *error = NULL;
+
+        session_manager = gsd_session_manager_proxy_new_for_bus_finish (result, &error);
+
+        if (session_manager == NULL) {
+                g_warning ("Couldn't find session manager service to log out: %s",
+                           error->message);
+                g_error_free (error);
+                return;
+        }
+
+        if (priv->session_manager != NULL)
+                g_object_unref (session_manager);
+
+        priv->session_manager = session_manager;
+
+        log_out (self);
+}
+
+static void
+on_logged_out (GsdSessionManager   *session_manager,
+               GAsyncResult        *result,
+               GsdSmartcardManager *self)
+{
+        gboolean is_logged_out;
+        GError *error = NULL;
+
+        is_logged_out = gsd_session_manager_call_logout_finish (session_manager, result, &error);
+
+        if (!is_logged_out) {
+                g_warning ("Couldn't log out: %s", error->message);
+                g_error_free (error);
+                return;
+        }
+}
+
+static void
+log_out (GsdSmartcardManager *self)
+{
+        GsdSmartcardManagerPrivate *priv = self->priv;
+
+        if (priv->session_manager == NULL) {
+                gsd_session_manager_proxy_new_for_bus (G_BUS_TYPE_SESSION,
+                                                       G_DBUS_PROXY_FLAGS_NONE,
+                                                       "org.gnome.SessionManager",
+                                                       "/org/gnome/SessionManager",
+                                                       priv->cancellable,
+                                                       (GAsyncReadyCallback) 
on_got_session_manager_to_log_out,
+                                                       self);
+                return;
+        }
+
+        gsd_session_manager_call_logout (priv->session_manager,
+                                         GSD_SESSION_MANAGER_LOGOUT_MODE_FORCE,
+                                         priv->cancellable,
+                                         (GAsyncReadyCallback) on_logged_out,
+                                         self);
+}
+
+void
+gsd_smartcard_manager_do_remove_action (GsdSmartcardManager *self)
+{
+        GsdSmartcardManagerPrivate *priv = self->priv;
+        char *remove_action;
+
+        remove_action = g_settings_get_string (priv->settings, KEY_REMOVE_ACTION);
+
+        if (strcmp (remove_action, "lock-screen") == 0)
+                lock_screen (self);
+        else if (strcmp (remove_action, "force-logout") == 0)
+                log_out (self);
 }
 
 static PK11SlotInfo *
diff --git a/plugins/smartcard/gsd-smartcard-manager.h b/plugins/smartcard/gsd-smartcard-manager.h
index 9d3a2ce..7876fc1 100644
--- a/plugins/smartcard/gsd-smartcard-manager.h
+++ b/plugins/smartcard/gsd-smartcard-manager.h
@@ -76,6 +76,7 @@ void                    gsd_smartcard_manager_stop        (GsdSmartcardManager
 PK11SlotInfo *          gsd_smartcard_manager_get_login_token (GsdSmartcardManager *manager);
 GList *                 gsd_smartcard_manager_get_inserted_tokens (GsdSmartcardManager *manager,
                                                                    gsize               *num_tokens);
+void                    gsd_smartcard_manager_do_remove_action (GsdSmartcardManager *manager);
 
 G_END_DECLS
 
diff --git a/plugins/smartcard/gsd-smartcard-service.c b/plugins/smartcard/gsd-smartcard-service.c
index 40350d0..cc20f4c 100644
--- a/plugins/smartcard/gsd-smartcard-service.c
+++ b/plugins/smartcard/gsd-smartcard-service.c
@@ -505,6 +505,17 @@ synchronize_token_now (GsdSmartcardService *self,
         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 (priv->smartcard_manager);
+        }
+
         g_object_set (G_OBJECT (interface),
                       "used-to-login", is_login_card,
                       "is-inserted", is_present,


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]