Blob Blame History Raw
From 92b5f8d3ca7b83fa5f10c16b8e876cfde23e4377 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Tue, 28 May 2013 09:20:57 -0400
Subject: [PATCH 1/11] smartcard: drop old implementation

It's going to be substantially rewritten, so drop the old
code to avoid a confusing diff when the new stuff lands.

https://bugzilla.gnome.org/show_bug.cgi?id=704890
---
 plugins/smartcard/Makefile.am             |   75 --
 plugins/smartcard/gsd-smartcard-manager.c | 1519 -----------------------------
 plugins/smartcard/gsd-smartcard-manager.h |   88 --
 plugins/smartcard/gsd-smartcard-plugin.c  |  337 -------
 plugins/smartcard/gsd-smartcard-plugin.h  |   59 --
 plugins/smartcard/gsd-smartcard.c         |  556 -----------
 plugins/smartcard/gsd-smartcard.h         |   94 --
 plugins/smartcard/test-smartcard.c        |    7 -
 8 files changed, 2735 deletions(-)
 delete mode 100644 plugins/smartcard/Makefile.am
 delete mode 100644 plugins/smartcard/gsd-smartcard-manager.c
 delete mode 100644 plugins/smartcard/gsd-smartcard-manager.h
 delete mode 100644 plugins/smartcard/gsd-smartcard-plugin.c
 delete mode 100644 plugins/smartcard/gsd-smartcard-plugin.h
 delete mode 100644 plugins/smartcard/gsd-smartcard.c
 delete mode 100644 plugins/smartcard/gsd-smartcard.h
 delete mode 100644 plugins/smartcard/test-smartcard.c

diff --git a/plugins/smartcard/Makefile.am b/plugins/smartcard/Makefile.am
deleted file mode 100644
index e2a0add..0000000
--- a/plugins/smartcard/Makefile.am
+++ /dev/null
@@ -1,75 +0,0 @@
-plugin_name = smartcard
-
-libexec_PROGRAMS = gsd-test-smartcard
-
-gsd_test_smartcard_SOURCES =	\
-	gsd-smartcard-manager.h	\
-	gsd-smartcard-manager.c	\
-	gsd-smartcard.h         \
-	gsd-smartcard.c         \
-	test-smartcard.c
-
-gsd_test_smartcard_CFLAGS =					\
-	-I$(top_srcdir)/gnome-settings-daemon			\
-	-I$(top_srcdir)/plugins/common				\
-	-DSYSCONFDIR=\""$(sysconfdir)"\" \
-	-DLIBDIR=\""$(libdir)"\" \
-	-DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\"	\
-	$(NSS_CFLAGS)						\
-	$(PLUGIN_CFLAGS)					\
-	$(SETTINGS_PLUGIN_CFLAGS)				\
-	$(AM_CFLAGS)
-
-gsd_test_smartcard_LDADD =					\
-	$(top_builddir)/gnome-settings-daemon/libgsd.la		\
-	$(top_builddir)/plugins/common/libcommon.la		\
-	$(NSS_LIBS)						\
-	$(SETTINGS_PLUGIN_LIBS)
-
-plugin_LTLIBRARIES = \
-	libsmartcard.la
-
-libsmartcard_la_SOURCES = \
-	gsd-smartcard-plugin.h  \
-	gsd-smartcard-plugin.c  \
-	gsd-smartcard.h         \
-	gsd-smartcard.c         \
-	gsd-smartcard-manager.h \
-	gsd-smartcard-manager.c
-
-libsmartcard_la_CPPFLAGS = \
-	-I$(top_srcdir)/gnome-settings-daemon \
-	-DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \
-	-DSYSCONFDIR=\""$(sysconfdir)"\" \
-	-DLIBDIR=\""$(libdir)"\" \
-	-DGSD_SMARTCARD_MANAGER_NSS_DB=\""$(NSS_DATABASE)"\" \
-	$(AM_CPPFLAGS)
-
-libsmartcard_la_CFLAGS = \
-	$(PLUGIN_CFLAGS)	\
-	$(SETTINGS_PLUGIN_CFLAGS) \
-	$(NSS_CFLAGS)	\
-	$(AM_CFLAGS)
-
-libsmartcard_la_LDFLAGS = \
-	$(GSD_PLUGIN_LDFLAGS)
-
-libsmartcard_la_LIBADD = \
-	$(SETTINGS_PLUGIN_LIBS)	\
-	$(NSS_LIBS)
-
-@GSD_INTLTOOL_PLUGIN_RULE@
-
-plugin_in_files = \
-	smartcard.gnome-settings-plugin.in
-
-plugin_DATA = $(plugin_in_files:.gnome-settings-plugin.in=.gnome-settings-plugin)
-
-EXTRA_DIST = \
-	$(plugin_in_files)
-
-CLEANFILES = \
-	$(plugin_DATA)
-
-DISTCLEANFILES = \
-	$(plugin_DATA)
diff --git a/plugins/smartcard/gsd-smartcard-manager.c b/plugins/smartcard/gsd-smartcard-manager.c
deleted file mode 100644
index 3acef0e..0000000
--- a/plugins/smartcard/gsd-smartcard-manager.c
+++ /dev/null
@@ -1,1519 +0,0 @@
-/* gsd-smartcard-manager.c - object for monitoring smartcard insertion and
- *                           removal events
- *
- * Copyright (C) 2006, 2009 Red Hat, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- *
- * Written By: Ray Strode
- */
-#include "config.h"
-
-#include "gsd-smartcard-manager.h"
-
-#define SMARTCARD_ENABLE_INTERNAL_API
-#include "gsd-smartcard.h"
-
-#include <dirent.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <poll.h>
-#include <signal.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/resource.h>
-#include <sys/time.h>
-#include <sys/wait.h>
-#include <unistd.h>
-
-#include <glib.h>
-#include <glib/gi18n.h>
-
-#include <prerror.h>
-#include <prinit.h>
-#include <nss.h>
-#include <pk11func.h>
-#include <secmod.h>
-#include <secerr.h>
-
-#ifndef GSD_SMARTCARD_MANAGER_DRIVER
-#define GSD_SMARTCARD_MANAGER_DRIVER LIBDIR"/pkcs11/libcoolkeypk11.so"
-#endif
-
-#ifndef GSD_SMARTCARD_MANAGER_NSS_DB
-#define GSD_SMARTCARD_MANAGER_NSS_DB SYSCONFDIR"/pki/nssdb"
-#endif
-
-#ifndef GSD_MAX_OPEN_FILE_DESCRIPTORS
-#define GSD_MAX_OPEN_FILE_DESCRIPTORS 1024
-#endif
-
-#ifndef GSD_OPEN_FILE_DESCRIPTORS_DIR
-#define GSD_OPEN_FILE_DESCRIPTORS_DIR "/proc/self/fd"
-#endif
-
-typedef enum _GsdSmartcardManagerState GsdSmartcardManagerState;
-typedef struct _GsdSmartcardManagerWorker GsdSmartcardManagerWorker;
-
-enum _GsdSmartcardManagerState {
-        GSD_SMARTCARD_MANAGER_STATE_STOPPED = 0,
-        GSD_SMARTCARD_MANAGER_STATE_STARTING,
-        GSD_SMARTCARD_MANAGER_STATE_STARTED,
-        GSD_SMARTCARD_MANAGER_STATE_STOPPING,
-};
-
-struct _GsdSmartcardManagerPrivate {
-        GsdSmartcardManagerState state;
-        GList        *modules;
-        char        *module_path;
-
-        GList        *workers;
-
-        GPid smartcard_event_watcher_pid;
-        GHashTable *smartcards;
-
-        guint poll_timeout_id;
-
-        guint32 is_unstoppable : 1;
-        guint32 nss_is_loaded : 1;
-};
-
-struct _GsdSmartcardManagerWorker {
-        GsdSmartcardManager *manager;
-        int manager_fd;
-
-        GThread      *thread;
-        SECMODModule *module;
-        GHashTable *smartcards;
-        int fd;
-        GSource *event_source;
-
-        guint32 nss_is_loaded : 1;
-};
-
-static void gsd_smartcard_manager_finalize (GObject *object);
-static void gsd_smartcard_manager_class_install_signals (GsdSmartcardManagerClass *service_class);
-static void gsd_smartcard_manager_class_install_properties (GsdSmartcardManagerClass *service_class);
-static void gsd_smartcard_manager_set_property (GObject       *object,
-                                                guint          prop_id,
-                                                const GValue  *value,
-                                                GParamSpec    *pspec);
-static void gsd_smartcard_manager_get_property (GObject    *object,
-                                                guint       prop_id,
-                                                GValue     *value,
-                                                GParamSpec *pspec);
-static void gsd_smartcard_manager_set_module_path (GsdSmartcardManager *manager,
-                                                   const char          *module_path);
-static void gsd_smartcard_manager_card_removed_handler (GsdSmartcardManager *manager,
-                                                        GsdSmartcard        *card);
-static void gsd_smartcard_manager_card_inserted_handler (GsdSmartcardManager *manager_class,
-                                                         GsdSmartcard        *card);
-static gboolean gsd_smartcard_manager_stop_now (GsdSmartcardManager *manager);
-static void gsd_smartcard_manager_queue_stop (GsdSmartcardManager *manager);
-
-static GsdSmartcardManagerWorker *gsd_smartcard_manager_create_worker (GsdSmartcardManager  *manager,
-                                                                       SECMODModule         *module);
-
-static GsdSmartcardManagerWorker * gsd_smartcard_manager_worker_new (GsdSmartcardManager *manager,
-                                                                     int                  worker_fd,
-                                                                     int                  manager_fd,
-                                                                     SECMODModule        *module);
-static void gsd_smartcard_manager_worker_free (GsdSmartcardManagerWorker *worker);
-static gboolean open_pipe (int *write_fd, int *read_fd);
-static gboolean read_bytes (int fd, gpointer bytes, gsize num_bytes);
-static gboolean write_bytes (int fd, gconstpointer bytes, gsize num_bytes);
-static GsdSmartcard *read_smartcard (int fd, SECMODModule *module);
-static gboolean write_smartcard (int fd, GsdSmartcard *card);
-
-enum {
-        PROP_0 = 0,
-        PROP_MODULE_PATH,
-        NUMBER_OF_PROPERTIES
-};
-
-enum {
-        SMARTCARD_INSERTED = 0,
-        SMARTCARD_REMOVED,
-        ERROR,
-        NUMBER_OF_SIGNALS
-};
-
-static guint gsd_smartcard_manager_signals[NUMBER_OF_SIGNALS];
-
-G_DEFINE_TYPE (GsdSmartcardManager,
-               gsd_smartcard_manager,
-               G_TYPE_OBJECT);
-
-static void
-gsd_smartcard_manager_class_init (GsdSmartcardManagerClass *manager_class)
-{
-        GObjectClass *gobject_class;
-
-        gobject_class = G_OBJECT_CLASS (manager_class);
-
-        gobject_class->finalize = gsd_smartcard_manager_finalize;
-
-        gsd_smartcard_manager_class_install_signals (manager_class);
-        gsd_smartcard_manager_class_install_properties (manager_class);
-
-        g_type_class_add_private (manager_class,
-                                  sizeof (GsdSmartcardManagerPrivate));
-}
-
-static void
-gsd_smartcard_manager_class_install_properties (GsdSmartcardManagerClass *card_class)
-{
-        GObjectClass *object_class;
-        GParamSpec *param_spec;
-
-        object_class = G_OBJECT_CLASS (card_class);
-        object_class->set_property = gsd_smartcard_manager_set_property;
-        object_class->get_property = gsd_smartcard_manager_get_property;
-
-        param_spec = g_param_spec_string ("module-path", "Module Path",
-                                          "path to smartcard PKCS #11 driver",
-                                          NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
-        g_object_class_install_property (object_class, PROP_MODULE_PATH, param_spec);
-}
-
-static void
-gsd_smartcard_manager_set_property (GObject       *object,
-                                    guint          prop_id,
-                                    const GValue  *value,
-                                    GParamSpec    *pspec)
-{
-        GsdSmartcardManager *manager = GSD_SMARTCARD_MANAGER (object);
-
-        switch (prop_id) {
-                case PROP_MODULE_PATH:
-                        gsd_smartcard_manager_set_module_path (manager,
-                                                                   g_value_get_string (value));
-                        break;
-
-                default:
-                        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-                        break;
-        }
-}
-
-static void
-gsd_smartcard_manager_get_property (GObject    *object,
-                                    guint       prop_id,
-                                    GValue     *value,
-                                    GParamSpec *pspec)
-{
-        GsdSmartcardManager *manager = GSD_SMARTCARD_MANAGER (object);
-        char *module_path;
-
-        switch (prop_id) {
-                case PROP_MODULE_PATH:
-                        module_path = gsd_smartcard_manager_get_module_path (manager);
-                        g_value_set_string (value, module_path);
-                        g_free (module_path);
-                        break;
-
-                default:
-                        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-                        break;
-        }
-}
-
-char *
-gsd_smartcard_manager_get_module_path (GsdSmartcardManager *manager)
-{
-        return manager->priv->module_path;
-}
-
-static void
-gsd_smartcard_manager_set_module_path (GsdSmartcardManager *manager,
-                                       const char          *module_path)
-{
-        if ((manager->priv->module_path == NULL) && (module_path == NULL)) {
-                return;
-        }
-
-        if (((manager->priv->module_path == NULL) ||
-         (module_path == NULL) ||
-         (strcmp (manager->priv->module_path, module_path) != 0))) {
-                g_free (manager->priv->module_path);
-                manager->priv->module_path = g_strdup (module_path);
-                g_object_notify (G_OBJECT (manager), "module-path");
-        }
-}
-
-static void
-gsd_smartcard_manager_card_removed_handler (GsdSmartcardManager *manager,
-                                            GsdSmartcard        *card)
-{
-        g_debug ("informing smartcard of its removal");
-        _gsd_smartcard_set_state (card, GSD_SMARTCARD_STATE_REMOVED);
-        g_debug ("done");
-}
-
-static void
-gsd_smartcard_manager_card_inserted_handler (GsdSmartcardManager *manager,
-                                             GsdSmartcard        *card)
-{
-        g_debug ("informing smartcard of its insertion");
-
-        _gsd_smartcard_set_state (card, GSD_SMARTCARD_STATE_INSERTED);
-        g_debug ("done");
-
-}
-
-static void
-gsd_smartcard_manager_class_install_signals (GsdSmartcardManagerClass *manager_class)
-{
-        GObjectClass *object_class;
-
-        object_class = G_OBJECT_CLASS (manager_class);
-
-        gsd_smartcard_manager_signals[SMARTCARD_INSERTED] =
-                g_signal_new ("smartcard-inserted",
-                              G_OBJECT_CLASS_TYPE (object_class),
-                              G_SIGNAL_RUN_FIRST,
-                              G_STRUCT_OFFSET (GsdSmartcardManagerClass,
-                                               smartcard_inserted),
-                              NULL, NULL, g_cclosure_marshal_VOID__POINTER,
-                              G_TYPE_NONE, 1, G_TYPE_POINTER);
-        manager_class->smartcard_inserted = gsd_smartcard_manager_card_inserted_handler;
-
-        gsd_smartcard_manager_signals[SMARTCARD_REMOVED] =
-                g_signal_new ("smartcard-removed",
-                              G_OBJECT_CLASS_TYPE (object_class),
-                              G_SIGNAL_RUN_FIRST,
-                              G_STRUCT_OFFSET (GsdSmartcardManagerClass,
-                                               smartcard_removed),
-                              NULL, NULL, g_cclosure_marshal_VOID__POINTER,
-                              G_TYPE_NONE, 1, G_TYPE_POINTER);
-        manager_class->smartcard_removed = gsd_smartcard_manager_card_removed_handler;
-
-        gsd_smartcard_manager_signals[ERROR] =
-                g_signal_new ("error",
-                              G_OBJECT_CLASS_TYPE (object_class),
-                              G_SIGNAL_RUN_LAST,
-                              G_STRUCT_OFFSET (GsdSmartcardManagerClass, error),
-                              NULL, NULL, g_cclosure_marshal_VOID__POINTER,
-                              G_TYPE_NONE, 1, G_TYPE_POINTER);
-        manager_class->error = NULL;
-}
-
-static gboolean
-slot_id_equal (CK_SLOT_ID *slot_id_1,
-               CK_SLOT_ID *slot_id_2)
-{
-        g_assert (slot_id_1 != NULL);
-        g_assert (slot_id_2 != NULL);
-
-        return *slot_id_1 == *slot_id_2;
-}
-
-static gboolean
-slot_id_hash (CK_SLOT_ID *slot_id)
-{
-        guint32 upper_bits, lower_bits;
-        int temp;
-
-        if (sizeof (CK_SLOT_ID) == sizeof (int)) {
-                return g_int_hash (slot_id);
-        }
-
-        upper_bits = ((*slot_id) >> 31) - 1;
-        lower_bits = (*slot_id) & 0xffffffff;
-
-        /* The upper bits are almost certainly always zero,
-         * so let's degenerate to g_int_hash for the
-         * (very) common case
-         */
-        temp = lower_bits + upper_bits;
-        return upper_bits + g_int_hash (&temp);
-}
-
-static void
-gsd_smartcard_manager_init (GsdSmartcardManager *manager)
-{
-        g_debug ("initializing smartcard manager");
-
-        manager->priv = G_TYPE_INSTANCE_GET_PRIVATE (manager,
-                                                     GSD_TYPE_SMARTCARD_MANAGER,
-                                                     GsdSmartcardManagerPrivate);
-        manager->priv->poll_timeout_id = 0;
-        manager->priv->is_unstoppable = FALSE;
-
-        manager->priv->smartcards =
-                g_hash_table_new_full (g_str_hash,
-                                       g_str_equal,
-                                       (GDestroyNotify) g_free,
-                                       (GDestroyNotify) g_object_unref);
-}
-
-static void
-gsd_smartcard_manager_finalize (GObject *object)
-{
-        GsdSmartcardManager *manager;
-        GObjectClass *gobject_class;
-
-        manager = GSD_SMARTCARD_MANAGER (object);
-        gobject_class =
-                G_OBJECT_CLASS (gsd_smartcard_manager_parent_class);
-
-        gsd_smartcard_manager_stop_now (manager);
-
-        g_hash_table_destroy (manager->priv->smartcards);
-        manager->priv->smartcards = NULL;
-
-        gobject_class->finalize (object);
-}
-
-GQuark
-gsd_smartcard_manager_error_quark (void)
-{
-        static GQuark error_quark = 0;
-
-        if (error_quark == 0) {
-                error_quark = g_quark_from_static_string ("gsd-smartcard-manager-error-quark");
-        }
-
-        return error_quark;
-}
-
-GsdSmartcardManager *
-gsd_smartcard_manager_new_default (void)
-{
-  return gsd_smartcard_manager_new (NULL);
-}
-
-GsdSmartcardManager *
-gsd_smartcard_manager_new (const char *module_path)
-{
-        GsdSmartcardManager *instance;
-
-        instance = GSD_SMARTCARD_MANAGER (g_object_new (GSD_TYPE_SMARTCARD_MANAGER,
-                                                        "module-path", module_path,
-                                                        NULL));
-
-        return instance;
-}
-
-static void
-gsd_smartcard_manager_emit_error (GsdSmartcardManager *manager,
-                                  GError              *error)
-{
-        manager->priv->is_unstoppable = TRUE;
-        g_signal_emit (manager, gsd_smartcard_manager_signals[ERROR], 0,
-                       error);
-        manager->priv->is_unstoppable = FALSE;
-}
-
-static void
-gsd_smartcard_manager_emit_smartcard_inserted (GsdSmartcardManager *manager,
-                                               GsdSmartcard        *card)
-{
-        manager->priv->is_unstoppable = TRUE;
-        g_signal_emit (manager, gsd_smartcard_manager_signals[SMARTCARD_INSERTED], 0,
-                       card);
-        manager->priv->is_unstoppable = FALSE;
-}
-
-static void
-gsd_smartcard_manager_emit_smartcard_removed (GsdSmartcardManager *manager,
-                                              GsdSmartcard        *card)
-{
-        manager->priv->is_unstoppable = TRUE;
-        g_signal_emit (manager, gsd_smartcard_manager_signals[SMARTCARD_REMOVED], 0,
-                       card);
-        manager->priv->is_unstoppable = FALSE;
-}
-
-static gboolean
-gsd_smartcard_manager_check_for_and_process_events (GIOChannel          *io_channel,
-                                                    GIOCondition         condition,
-                                                    GsdSmartcardManagerWorker *worker)
-{
-        GsdSmartcard *card;
-        GsdSmartcardManager *manager;
-        gboolean should_stop;
-        guchar event_type;
-        char *card_name;
-        int fd;
-
-        manager = worker->manager;
-
-        g_debug ("event!");
-        card = NULL;
-        should_stop = (condition & G_IO_HUP) || (condition & G_IO_ERR);
-
-        if (should_stop) {
-                g_debug ("received %s on event socket, stopping "
-                          "manager...",
-                          (condition & G_IO_HUP) && (condition & G_IO_ERR)?
-                          "error and hangup" :
-                          (condition & G_IO_HUP)?
-                          "hangup" : "error");
-        }
-
-        if (!(condition & G_IO_IN)) {
-                g_debug ("nevermind outta here!");
-                goto out;
-        }
-
-        fd = g_io_channel_unix_get_fd (io_channel);
-
-        event_type = '\0';
-        if (!read_bytes (fd, &event_type, 1)) {
-                g_debug ("could not read event type, stopping");
-                should_stop = TRUE;
-                goto out;
-        }
-
-        card = read_smartcard (fd, worker->module);
-
-        if (card == NULL) {
-                g_debug ("could not read card, stopping");
-                should_stop = TRUE;
-                goto out;
-        }
-
-        card_name = gsd_smartcard_get_name (card);
-        g_debug ("card '%s' had event %c", card_name, event_type);
-
-        switch (event_type) {
-                case 'I':
-                        g_hash_table_replace (manager->priv->smartcards,
-                                              card_name, card);
-                        card_name = NULL;
-
-                        gsd_smartcard_manager_emit_smartcard_inserted (manager, card);
-                        card = NULL;
-                        break;
-
-                case 'R':
-                        gsd_smartcard_manager_emit_smartcard_removed (manager, card);
-                        if (!g_hash_table_remove (manager->priv->smartcards, card_name)) {
-                                g_debug ("got removal event of unknown card!");
-                        }
-                        g_free (card_name);
-                        card_name = NULL;
-                        card = NULL;
-                        break;
-
-                default:
-                        g_free (card_name);
-                        card_name = NULL;
-                        g_object_unref (card);
-
-                        should_stop = TRUE;
-                        break;
-        }
-
-out:
-        if (should_stop) {
-                GError *error;
-
-                error = g_error_new (GSD_SMARTCARD_MANAGER_ERROR,
-                                     GSD_SMARTCARD_MANAGER_ERROR_WATCHING_FOR_EVENTS,
-                                     "%s", (condition & G_IO_IN) ? g_strerror (errno) : _("received error or hang up from event source"));
-
-                gsd_smartcard_manager_emit_error (manager, error);
-                g_error_free (error);
-                gsd_smartcard_manager_stop_now (manager);
-                return FALSE;
-        }
-
-        return TRUE;
-}
-
-static void
-stop_manager (GsdSmartcardManager *manager)
-{
-        manager->priv->state = GSD_SMARTCARD_MANAGER_STATE_STOPPED;
-
-        if (manager->priv->nss_is_loaded) {
-                NSS_Shutdown ();
-                manager->priv->nss_is_loaded = FALSE;
-        }
-        g_debug ("smartcard manager stopped");
-}
-
-static void
-stop_worker (GsdSmartcardManagerWorker *worker)
-{
-        GsdSmartcardManager *manager;
-
-        manager = worker->manager;
-
-        if (worker->event_source != NULL) {
-                g_source_destroy (worker->event_source);
-                worker->event_source = NULL;
-        }
-
-        if (worker->thread != NULL) {
-                SECMOD_CancelWait (worker->module);
-                worker->thread = NULL;
-        }
-
-        SECMOD_DestroyModule (worker->module);
-        manager->priv->workers = g_list_remove (manager->priv->workers, worker);
-
-        if (manager->priv->workers == NULL && manager->priv->state != GSD_SMARTCARD_MANAGER_STATE_STOPPED) {
-                stop_manager (manager);
-        }
-}
-
-static void
-gsd_smartcard_manager_event_processing_stopped_handler (GsdSmartcardManagerWorker *worker)
-{
-        worker->event_source = NULL;
-
-        stop_worker (worker);
-}
-
-static gboolean
-open_pipe (int *write_fd,
-           int *read_fd)
-{
-        int pipe_fds[2] = { -1, -1 };
-
-        g_assert (write_fd != NULL);
-        g_assert (read_fd != NULL);
-
-        if (pipe (pipe_fds) < 0) {
-                return FALSE;
-        }
-
-        if (fcntl (pipe_fds[0], F_SETFD, FD_CLOEXEC) < 0) {
-                close (pipe_fds[0]);
-                close (pipe_fds[1]);
-                return FALSE;
-        }
-
-        if (fcntl (pipe_fds[1], F_SETFD, FD_CLOEXEC) < 0) {
-                close (pipe_fds[0]);
-                close (pipe_fds[1]);
-                return FALSE;
-        }
-
-        *read_fd = pipe_fds[0];
-        *write_fd = pipe_fds[1];
-
-        return TRUE;
-}
-
-static void
-gsd_smartcard_manager_stop_watching_for_events (GsdSmartcardManager  *manager)
-{
-        GList *node;
-
-        node = manager->priv->workers;
-        while (node != NULL) {
-                GsdSmartcardManagerWorker *worker;
-                GList *next_node;
-
-                worker = (GsdSmartcardManagerWorker *) node->data;
-                next_node = node->next;
-
-                stop_worker (worker);
-
-                node = next_node;
-        }
-}
-
-static gboolean
-load_nss (GError **error)
-{
-        SECStatus status = SECSuccess;
-        static const guint32 flags =
-        NSS_INIT_READONLY |
-        NSS_INIT_FORCEOPEN | NSS_INIT_NOROOTINIT |
-        NSS_INIT_OPTIMIZESPACE | NSS_INIT_PK11RELOAD;
-
-        g_debug ("attempting to load NSS database '%s'",
-                 GSD_SMARTCARD_MANAGER_NSS_DB);
-
-        PR_Init (PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
-
-        status = NSS_Initialize (GSD_SMARTCARD_MANAGER_NSS_DB,
-                                 "", "", SECMOD_DB, flags);
-
-        if (status != SECSuccess) {
-                gsize error_message_size;
-                char *error_message;
-
-                error_message_size = PR_GetErrorTextLength ();
-
-                if (error_message_size == 0) {
-                        g_debug ("NSS security system could not be initialized");
-                        g_set_error (error,
-                                     GSD_SMARTCARD_MANAGER_ERROR,
-                                     GSD_SMARTCARD_MANAGER_ERROR_WITH_NSS,
-                                     _("NSS security system could not be initialized"));
-                        goto out;
-                }
-
-                error_message = g_slice_alloc0 (error_message_size);
-                PR_GetErrorText (error_message);
-
-                g_set_error (error,
-                             GSD_SMARTCARD_MANAGER_ERROR,
-                             GSD_SMARTCARD_MANAGER_ERROR_WITH_NSS,
-                             "%s", error_message);
-                g_debug ("NSS security system could not be initialized - %s",
-                          error_message);
-
-                g_slice_free1 (error_message_size, error_message);
-
-                goto out;
-        }
-
-        g_debug ("NSS database sucessfully loaded");
-        return TRUE;
-
-out:
-        g_debug ("NSS database couldn't be sucessfully loaded");
-        return FALSE;
-}
-
-static GList *
-get_available_modules (GsdSmartcardManager  *manager)
-{
-        SECMODModuleList *module_list, *tmp;
-        GList *modules;
-
-        g_debug ("Getting list of suitable modules");
-
-        module_list = SECMOD_GetDefaultModuleList ();
-        modules = NULL;
-        for (tmp = module_list; tmp != NULL; tmp = tmp->next) {
-                if (!SECMOD_HasRemovableSlots (tmp->module) ||
-                    !tmp->module->loaded)
-                        continue;
-
-                g_debug ("Using module '%s'", tmp->module->commonName);
-
-                modules = g_list_prepend (modules,
-                                          SECMOD_ReferenceModule (tmp->module));
-        }
-
-        return modules;
-}
-
-static gboolean
-load_driver (GsdSmartcardManager  *manager,
-             char                 *module_path,
-             GError              **error)
-{
-        GList *modules;
-        char *module_spec;
-        gboolean module_explicitly_specified;
-
-        g_debug ("attempting to load driver...");
-
-        modules = NULL;
-        module_explicitly_specified = module_path != NULL;
-        if (module_explicitly_specified) {
-                SECMODModule *module;
-
-                module_spec = g_strdup_printf ("library=\"%s\"", module_path);
-                g_debug ("loading smartcard driver using spec '%s'",
-                          module_spec);
-
-                module = SECMOD_LoadUserModule (module_spec,
-                                                NULL /* parent */,
-                                                FALSE /* recurse */);
-                g_free (module_spec);
-                module_spec = NULL;
-
-                if (SECMOD_HasRemovableSlots (module) &&
-                    module->loaded) {
-                        modules = g_list_prepend (modules, module);
-                } else {
-                        g_debug ("fallback module found but not %s",
-                                 SECMOD_HasRemovableSlots (module)?
-                                 "removable" : "loaded");
-                        SECMOD_DestroyModule (module);
-                }
-
-        } else {
-                SECMODListLock *lock;
-
-                lock = SECMOD_GetDefaultModuleListLock ();
-
-                if (lock != NULL) {
-                        SECMOD_GetReadLock (lock);
-                        modules = get_available_modules (manager);
-                        SECMOD_ReleaseReadLock (lock);
-                }
-
-                /* fallback to compiled in driver path
-                 */
-                if (modules == NULL) {
-                        SECMODModule *module;
-                        module_path = GSD_SMARTCARD_MANAGER_DRIVER;
-                        module_spec = g_strdup_printf ("library=\"%s\"", module_path);
-                        g_debug ("loading smartcard driver using spec '%s'",
-                                module_spec);
-
-                        module = SECMOD_LoadUserModule (module_spec,
-                                NULL /* parent */,
-                                FALSE /* recurse */);
-                        g_free (module_spec);
-                        module_spec = NULL;
-
-                        if (SECMOD_HasRemovableSlots (module) &&
-                            module->loaded) {
-                                modules = g_list_prepend (modules, module);
-                        } else {
-                                g_debug ("fallback module found but not loaded");
-                                SECMOD_DestroyModule (module);
-                        }
-                }
-
-        }
-
-        if (!module_explicitly_specified && modules == NULL) {
-                g_set_error (error,
-                             GSD_SMARTCARD_MANAGER_ERROR,
-                             GSD_SMARTCARD_MANAGER_ERROR_LOADING_DRIVER,
-                             _("no suitable smartcard driver could be found"));
-        } else if (modules == NULL) {
-
-                gsize error_message_size;
-                char *error_message;
-
-                error_message_size = PR_GetErrorTextLength ();
-
-                if (error_message_size == 0) {
-                        g_debug ("smartcard driver '%s' could not be loaded",
-                                  module_path);
-                        g_set_error (error,
-                                     GSD_SMARTCARD_MANAGER_ERROR,
-                                     GSD_SMARTCARD_MANAGER_ERROR_LOADING_DRIVER,
-                                     _("smartcard driver '%s' could not be "
-                                       "loaded"), module_path);
-                        goto out;
-                }
-
-                error_message = g_slice_alloc0 (error_message_size);
-                PR_GetErrorText (error_message);
-
-                g_set_error (error,
-                             GSD_SMARTCARD_MANAGER_ERROR,
-                             GSD_SMARTCARD_MANAGER_ERROR_LOADING_DRIVER,
-                             "%s", error_message);
-
-                g_debug ("smartcard driver '%s' could not be loaded - %s",
-                          module_path, error_message);
-                g_slice_free1 (error_message_size, error_message);
-        }
-
-        manager->priv->modules = modules;
-out:
-        return manager->priv->modules != NULL;
-}
-
-static void
-gsd_smartcard_manager_get_all_cards (GsdSmartcardManager *manager)
-{
-        GList *node;
-        int i;
-
-        node = manager->priv->workers;
-        while (node != NULL) {
-
-                GsdSmartcardManagerWorker *worker;
-
-                worker = (GsdSmartcardManagerWorker *) node->data;
-
-                for (i = 0; i < worker->module->slotCount; i++) {
-                        GsdSmartcard *card;
-                        CK_SLOT_ID    slot_id;
-                        int          slot_series;
-                        char         *card_name;
-
-                        slot_id = PK11_GetSlotID (worker->module->slots[i]);
-                        slot_series = PK11_GetSlotSeries (worker->module->slots[i]);
-
-                        card = _gsd_smartcard_new (worker->module,
-                                                   slot_id, slot_series);
-
-                        card_name = gsd_smartcard_get_name (card);
-
-                        g_hash_table_replace (manager->priv->smartcards,
-                                              card_name, card);
-                }
-                node = node->next;
-        }
-}
-
-static GsdSmartcardManagerWorker *
-start_worker (GsdSmartcardManager  *manager,
-              SECMODModule         *module,
-              GError              **error)
-{
-        GIOChannel *io_channel;
-        GSource *source;
-        GsdSmartcardManagerWorker *worker;
-
-        worker = gsd_smartcard_manager_create_worker (manager, module);
-
-        if (worker == NULL) {
-                g_set_error (error,
-                             GSD_SMARTCARD_MANAGER_ERROR,
-                             GSD_SMARTCARD_MANAGER_ERROR_WATCHING_FOR_EVENTS,
-                             _("could not watch for incoming card events - %s"),
-                             g_strerror (errno));
-
-                goto out;
-        }
-
-        io_channel = g_io_channel_unix_new (worker->manager_fd);
-
-        source = g_io_create_watch (io_channel, G_IO_IN | G_IO_HUP);
-        g_io_channel_unref (io_channel);
-        io_channel = NULL;
-
-        worker->event_source = source;
-
-        g_source_set_callback (worker->event_source,
-                               (GSourceFunc) (GIOFunc)
-                               gsd_smartcard_manager_check_for_and_process_events,
-                               worker,
-                               (GDestroyNotify)
-                               gsd_smartcard_manager_event_processing_stopped_handler);
-        g_source_attach (worker->event_source, NULL);
-        g_source_unref (worker->event_source);
-out:
-        return worker;
-}
-
-static void
-start_workers (GsdSmartcardManager *manager)
-{
-        GList        *node;
-
-        node = manager->priv->modules;
-        while (node != NULL) {
-                SECMODModule *module;
-                GsdSmartcardManagerWorker *worker;
-                GError *error;
-
-                module = (SECMODModule *) node->data;
-
-                error = NULL;
-                worker = start_worker (manager, module, &error);
-                if (worker == NULL) {
-                        g_warning ("%s", error->message);
-                        g_error_free (error);
-                } else {
-                        manager->priv->workers = g_list_prepend (manager->priv->workers,
-                                                                 worker);
-                }
-                node = node->next;
-        }
-}
-
-gboolean
-gsd_smartcard_manager_start (GsdSmartcardManager  *manager,
-                             GError              **error)
-{
-        GError *nss_error;
-
-        if (manager->priv->state == GSD_SMARTCARD_MANAGER_STATE_STARTED) {
-                g_debug ("smartcard manager already started");
-                return TRUE;
-        }
-
-        manager->priv->state = GSD_SMARTCARD_MANAGER_STATE_STARTING;
-
-        nss_error = NULL;
-        if (!manager->priv->nss_is_loaded && !load_nss (&nss_error)) {
-                g_propagate_error (error, nss_error);
-                goto out;
-        }
-        manager->priv->nss_is_loaded = TRUE;
-
-        if (manager->priv->modules == NULL) {
-                if (!load_driver (manager, manager->priv->module_path, &nss_error)) {
-                        g_propagate_error (error, nss_error);
-                        goto out;
-                }
-        }
-
-        start_workers (manager);
-
-        /* populate the hash with cards that are already inserted
-         */
-        gsd_smartcard_manager_get_all_cards (manager);
-
-        manager->priv->state = GSD_SMARTCARD_MANAGER_STATE_STARTED;
-
-out:
-        /* don't leave it in a half started state
-         */
-        if (manager->priv->state != GSD_SMARTCARD_MANAGER_STATE_STARTED) {
-                g_debug ("smartcard manager could not be completely started");
-                gsd_smartcard_manager_stop (manager);
-        } else {
-                g_debug ("smartcard manager started");
-        }
-
-        return manager->priv->state == GSD_SMARTCARD_MANAGER_STATE_STARTED;
-}
-
-static gboolean
-gsd_smartcard_manager_stop_now (GsdSmartcardManager *manager)
-{
-        if (manager->priv->state == GSD_SMARTCARD_MANAGER_STATE_STOPPED) {
-                return FALSE;
-        }
-
-        gsd_smartcard_manager_stop_watching_for_events (manager);
-
-        return FALSE;
-}
-
-static void
-gsd_smartcard_manager_queue_stop (GsdSmartcardManager *manager)
-{
-
-        manager->priv->state = GSD_SMARTCARD_MANAGER_STATE_STOPPING;
-
-        g_idle_add ((GSourceFunc) gsd_smartcard_manager_stop_now, manager);
-}
-
-void
-gsd_smartcard_manager_stop (GsdSmartcardManager *manager)
-{
-        if (manager->priv->state == GSD_SMARTCARD_MANAGER_STATE_STOPPED) {
-                return;
-        }
-
-        if (manager->priv->is_unstoppable) {
-                gsd_smartcard_manager_queue_stop (manager);
-                return;
-        }
-
-        gsd_smartcard_manager_stop_now (manager);
-}
-
-static void
-gsd_smartcard_manager_check_for_login_card (CK_SLOT_ID    slot_id,
-                                            GsdSmartcard *card,
-                                            gboolean     *is_inserted)
-{
-        g_assert (is_inserted != NULL);
-
-        if (gsd_smartcard_is_login_card (card)) {
-                *is_inserted = TRUE;
-        }
-
-}
-
-gboolean
-gsd_smartcard_manager_login_card_is_inserted (GsdSmartcardManager *manager)
-
-{
-        gboolean is_inserted;
-
-        is_inserted = FALSE;
-        g_hash_table_foreach (manager->priv->smartcards,
-                              (GHFunc)
-                              gsd_smartcard_manager_check_for_login_card,
-                              &is_inserted);
-        return is_inserted;
-}
-
-static GsdSmartcardManagerWorker *
-gsd_smartcard_manager_worker_new (GsdSmartcardManager *manager,
-                                  int                 worker_fd,
-                                  int                 manager_fd,
-                                  SECMODModule        *module)
-{
-        GsdSmartcardManagerWorker *worker;
-
-        worker = g_slice_new0 (GsdSmartcardManagerWorker);
-        worker->manager = manager;
-        worker->fd = worker_fd;
-        worker->manager_fd = manager_fd;
-        worker->module = module;
-
-        worker->smartcards =
-                g_hash_table_new_full ((GHashFunc) slot_id_hash,
-                                       (GEqualFunc) slot_id_equal,
-                                       (GDestroyNotify) g_free,
-                                       (GDestroyNotify) g_object_unref);
-
-        return worker;
-}
-
-static void
-gsd_smartcard_manager_worker_free (GsdSmartcardManagerWorker *worker)
-{
-        if (worker->smartcards != NULL) {
-                g_hash_table_destroy (worker->smartcards);
-                worker->smartcards = NULL;
-        }
-
-        g_slice_free (GsdSmartcardManagerWorker, worker);
-}
-
-static gboolean
-read_bytes (int      fd,
-            gpointer bytes,
-            gsize    num_bytes)
-{
-        size_t bytes_left;
-        size_t total_bytes_read;
-        ssize_t bytes_read;
-
-        bytes_left = (size_t) num_bytes;
-        total_bytes_read = 0;
-
-        do {
-                bytes_read = read (fd,
-                                   (char *) bytes + total_bytes_read,
-                                   bytes_left);
-                g_assert (bytes_read <= (ssize_t) bytes_left);
-
-                if (bytes_read <= 0) {
-                        if ((bytes_read < 0) && (errno == EINTR || errno == EAGAIN)) {
-                                continue;
-                        }
-
-                        bytes_left = 0;
-                } else {
-                        bytes_left -= bytes_read;
-                        total_bytes_read += bytes_read;
-                }
-        } while (bytes_left > 0);
-
-        if (total_bytes_read <  (size_t) num_bytes) {
-                return FALSE;
-        }
-
-        return TRUE;
-}
-
-static gboolean
-write_bytes (int           fd,
-             gconstpointer bytes,
-             gsize         num_bytes)
-{
-        size_t bytes_left;
-        size_t total_bytes_written;
-        ssize_t bytes_written;
-
-        bytes_left = (size_t) num_bytes;
-        total_bytes_written = 0;
-
-        do {
-                bytes_written = write (fd,
-                                       (char *) bytes + total_bytes_written,
-                                       bytes_left);
-                g_assert (bytes_written <= (ssize_t) bytes_left);
-
-                if (bytes_written <= 0) {
-                        if ((bytes_written < 0) && (errno == EINTR || errno == EAGAIN)) {
-                                continue;
-                        }
-
-                        bytes_left = 0;
-                } else {
-                        bytes_left -= bytes_written;
-                        total_bytes_written += bytes_written;
-                }
-        } while (bytes_left > 0);
-
-        if (total_bytes_written <  (size_t) num_bytes) {
-                return FALSE;
-        }
-
-        return TRUE;
-}
-
-static GsdSmartcard *
-read_smartcard (int           fd,
-                SECMODModule *module)
-{
-        GsdSmartcard *card;
-        char *card_name;
-        gsize card_name_size;
-
-        card_name_size = 0;
-        if (!read_bytes (fd, &card_name_size, sizeof (card_name_size))) {
-                return NULL;
-        }
-
-        card_name = g_slice_alloc0 (card_name_size);
-        if (!read_bytes (fd, card_name, card_name_size)) {
-                g_slice_free1 (card_name_size, card_name);
-                return NULL;
-        }
-        card = _gsd_smartcard_new_from_name (module, card_name);
-        g_slice_free1 (card_name_size, card_name);
-
-        return card;
-}
-
-static gboolean
-write_smartcard (int          fd,
-                    GsdSmartcard *card)
-{
-        gsize card_name_size;
-        char *card_name;
-
-        card_name = gsd_smartcard_get_name (card);
-        card_name_size = strlen (card_name) + 1;
-
-        if (!write_bytes (fd, &card_name_size, sizeof (card_name_size))) {
-                g_free (card_name);
-                return FALSE;
-        }
-
-        if (!write_bytes (fd, card_name, card_name_size)) {
-                g_free (card_name);
-                return FALSE;
-        }
-        g_free (card_name);
-
-        return TRUE;
-}
-
-static gboolean
-gsd_smartcard_manager_worker_emit_smartcard_removed (GsdSmartcardManagerWorker  *worker,
-                                                     GsdSmartcard               *card,
-                                                     GError                    **error)
-{
-        g_debug ("card '%s' removed!", gsd_smartcard_get_name (card));
-
-        if (!write_bytes (worker->fd, "R", 1)) {
-                goto error_out;
-        }
-
-        if (!write_smartcard (worker->fd, card)) {
-                goto error_out;
-        }
-
-        return TRUE;
-
-error_out:
-        g_set_error (error, GSD_SMARTCARD_MANAGER_ERROR,
-                     GSD_SMARTCARD_MANAGER_ERROR_REPORTING_EVENTS,
-                     "%s", g_strerror (errno));
-        return FALSE;
-}
-
-static gboolean
-gsd_smartcard_manager_worker_emit_smartcard_inserted (GsdSmartcardManagerWorker  *worker,
-                                                      GsdSmartcard               *card,
-                                                      GError                    **error)
-{
-        g_debug ("card '%s' inserted!", gsd_smartcard_get_name (card));
-        if (!write_bytes (worker->fd, "I", 1)) {
-                goto error_out;
-        }
-
-        if (!write_smartcard (worker->fd, card)) {
-                goto error_out;
-        }
-
-        return TRUE;
-
-error_out:
-        g_set_error (error, GSD_SMARTCARD_MANAGER_ERROR,
-                     GSD_SMARTCARD_MANAGER_ERROR_REPORTING_EVENTS,
-                     "%s", g_strerror (errno));
-        return FALSE;
-}
-
-static gboolean
-gsd_smartcard_manager_worker_watch_for_and_process_event (GsdSmartcardManagerWorker  *worker,
-                                                          GError                    **error)
-{
-        PK11SlotInfo *slot;
-        CK_SLOT_ID slot_id, *key = NULL;
-        int slot_series, card_slot_series;
-        GsdSmartcard *card;
-        GError *processing_error;
-        gboolean ret;
-
-        g_debug ("waiting for card event");
-        ret = FALSE;
-
-        slot = SECMOD_WaitForAnyTokenEvent (worker->module, 0, PR_SecondsToInterval (1));
-
-        processing_error = NULL;
-
-        if (slot == NULL) {
-                int error_code;
-
-                error_code = PORT_GetError ();
-                if ((error_code == 0) || (error_code == SEC_ERROR_NO_EVENT)) {
-                        g_debug ("spurrious event occurred");
-                        return TRUE;
-                }
-
-                /* FIXME: is there a function to convert from a PORT error
-                 * code to a translated string?
-                 */
-                g_set_error (error, GSD_SMARTCARD_MANAGER_ERROR,
-                             GSD_SMARTCARD_MANAGER_ERROR_WITH_NSS,
-                             _("encountered unexpected error while "
-                               "waiting for smartcard events"));
-                goto out;
-        }
-
-        /* the slot id and series together uniquely identify a card.
-         * You can never have two cards with the same slot id at the
-         * same time, however (I think), so we can key off of it.
-         */
-        slot_id = PK11_GetSlotID (slot);
-        slot_series = PK11_GetSlotSeries (slot);
-
-        /* First check to see if there is a card that we're currently
-         * tracking in the slot.
-         */
-        key = g_new (CK_SLOT_ID, 1);
-        *key = slot_id;
-        card = g_hash_table_lookup (worker->smartcards, key);
-
-        if (card != NULL) {
-                card_slot_series = gsd_smartcard_get_slot_series (card);
-        } else {
-                card_slot_series = -1;
-        }
-
-        if (PK11_IsPresent (slot)) {
-                /* Now, check to see if their is a new card in the slot.
-                 * If there was a different card in the slot now than
-                 * there was before, then we need to emit a removed signal
-                 * for the old card (we don't want unpaired insertion events).
-                 */
-                if ((card != NULL) &&
-                    card_slot_series != slot_series) {
-                        if (!gsd_smartcard_manager_worker_emit_smartcard_removed (worker, card, &processing_error)) {
-                                g_propagate_error (error, processing_error);
-                                goto out;
-                        }
-                }
-
-                card = _gsd_smartcard_new (worker->module,
-                                           slot_id, slot_series);
-
-                g_hash_table_replace (worker->smartcards,
-                                      key, card);
-                key = NULL;
-
-                if (!gsd_smartcard_manager_worker_emit_smartcard_inserted (worker, card, &processing_error)) {
-                        g_propagate_error (error, processing_error);
-                        goto out;
-                }
-        } else {
-                /* if we aren't tracking the card, just discard the event.
-                 * We don't want unpaired remove events.  Note on startup
-                 * NSS will generate an "insertion" event if a card is
-                 * already inserted in the slot.
-                 */
-                if ((card != NULL)) {
-                        /* FIXME: i'm not sure about this code.  Maybe we
-                         * shouldn't do this at all, or maybe we should do it
-                         * n times (where n = slot_series - card_slot_series + 1)
-                         *
-                         * Right now, i'm just doing it once.
-                         */
-                        if ((slot_series - card_slot_series) > 1) {
-
-                                if (!gsd_smartcard_manager_worker_emit_smartcard_removed (worker, card, &processing_error)) {
-                                        g_propagate_error (error, processing_error);
-                                        goto out;
-                                }
-                                g_hash_table_remove (worker->smartcards, key);
-
-                                card = _gsd_smartcard_new (worker->module,
-                                                                slot_id, slot_series);
-                                g_hash_table_replace (worker->smartcards,
-                                                      key, card);
-                                key = NULL;
-                                if (!gsd_smartcard_manager_worker_emit_smartcard_inserted (worker, card, &processing_error)) {
-                                        g_propagate_error (error, processing_error);
-                                        goto out;
-                                }
-                        }
-
-                        if (!gsd_smartcard_manager_worker_emit_smartcard_removed (worker, card, &processing_error)) {
-                                g_propagate_error (error, processing_error);
-                                goto out;
-                        }
-
-                        g_hash_table_remove (worker->smartcards, key);
-                        card = NULL;
-                } else {
-                        g_debug ("got spurious remove event");
-                }
-        }
-
-        ret = TRUE;
-
-out:
-        g_free (key);
-        PK11_FreeSlot (slot);
-
-        return ret;
-}
-
-static void
-gsd_smartcard_manager_worker_run (GsdSmartcardManagerWorker *worker)
-{
-        GError *error;
-        gboolean should_continue;
-
-        do
-        {
-                error = NULL;
-                should_continue = gsd_smartcard_manager_worker_watch_for_and_process_event (worker, &error);
-        }
-        while (should_continue);
-
-        if (error != NULL)  {
-                g_debug ("could not process card event - %s", error->message);
-                g_error_free (error);
-        }
-
-        gsd_smartcard_manager_worker_free (worker);
-}
-
-static GsdSmartcardManagerWorker *
-gsd_smartcard_manager_create_worker (GsdSmartcardManager  *manager,
-                                     SECMODModule         *module)
-{
-        GsdSmartcardManagerWorker *worker;
-        int write_fd, read_fd;
-
-        write_fd = -1;
-        read_fd = -1;
-        if (!open_pipe (&write_fd, &read_fd)) {
-                return NULL;
-        }
-
-        worker = gsd_smartcard_manager_worker_new (manager,
-                                                   write_fd,
-                                                   read_fd,
-                                                   module);
-
-        worker->thread = g_thread_create ((GThreadFunc)
-                                          gsd_smartcard_manager_worker_run,
-                                          worker, FALSE, NULL);
-
-        if (worker->thread == NULL) {
-                gsd_smartcard_manager_worker_free (worker);
-                return NULL;
-        }
-
-        return worker;
-}
-
-#ifdef GSD_SMARTCARD_MANAGER_ENABLE_TEST
-#include <glib.h>
-
-static GMainLoop *event_loop;
-static gboolean should_exit_on_next_remove = FALSE;
-
-static gboolean
-on_timeout (GsdSmartcardManager *manager)
-{
-        GError *error;
-        g_print ("Re-enabling manager.\n");
-
-        if (!gsd_smartcard_manager_start (manager, &error)) {
-                g_warning ("could not start smartcard manager - %s",
-                           error->message);
-                g_error_free (error);
-                return TRUE;
-        }
-        g_print ("Please re-insert smartcard\n");
-
-        should_exit_on_next_remove = TRUE;
-
-        return FALSE;
-}
-
-static void
-on_device_inserted (GsdSmartcardManager *manager,
-                    GsdSmartcard        *card)
-{
-        g_print ("smartcard inserted!\n");
-        g_print ("Please remove it.\n");
-}
-
-static void
-on_device_removed (GsdSmartcardManager *manager,
-                   GsdSmartcard        *card)
-{
-        g_print ("smartcard removed!\n");
-
-        if (should_exit_on_next_remove) {
-                g_main_loop_quit (event_loop);
-        } else {
-                g_print ("disabling manager for 2 seconds\n");
-                gsd_smartcard_manager_stop (manager);
-                g_timeout_add_seconds (2, (GSourceFunc) on_timeout, manager);
-        }
-}
-
-int
-main (int   argc,
-      char *argv[])
-{
-        GsdSmartcardManager *manager;
-        GError *error;
-
-        g_log_set_always_fatal (G_LOG_LEVEL_ERROR
-                                | G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING);
-
-        g_message ("creating instance of 'smartcard manager' object...");
-        manager = gsd_smartcard_manager_new (NULL);
-        g_message ("'smartcard manager' object created successfully");
-
-        g_signal_connect (manager, "smartcard-inserted",
-                          G_CALLBACK (on_device_inserted), NULL);
-
-        g_signal_connect (manager, "smartcard-removed",
-                          G_CALLBACK (on_device_removed), NULL);
-
-        g_message ("starting listener...");
-
-        error = NULL;
-        if (!gsd_smartcard_manager_start (manager, &error)) {
-                g_warning ("could not start smartcard manager - %s",
-                           error->message);
-                g_error_free (error);
-                return 1;
-        }
-
-        event_loop = g_main_loop_new (NULL, FALSE);
-        g_main_loop_run (event_loop);
-        g_main_loop_unref (event_loop);
-        event_loop = NULL;
-
-        g_message ("destroying previously created 'smartcard manager' object...");
-        g_object_unref (manager);
-        manager = NULL;
-        g_message ("'smartcard manager' object destroyed successfully");
-
-        return 0;
-}
-#endif
diff --git a/plugins/smartcard/gsd-smartcard-manager.h b/plugins/smartcard/gsd-smartcard-manager.h
deleted file mode 100644
index 949f194..0000000
--- a/plugins/smartcard/gsd-smartcard-manager.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/* gsd-smartcard-manager.h - object for monitoring smartcard insertion and
- *                           removal events
- *
- * Copyright (C) 2006, 2009 Red Hat, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- *
- * Written by: Ray Strode
- */
-#ifndef GSD_SMARTCARD_MANAGER_H
-#define GSD_SMARTCARD_MANAGER_H
-
-#define GSD_SMARTCARD_ENABLE_INTERNAL_API
-#include "gsd-smartcard.h"
-
-#include <glib.h>
-#include <glib-object.h>
-
-G_BEGIN_DECLS
-#define GSD_TYPE_SMARTCARD_MANAGER            (gsd_smartcard_manager_get_type ())
-#define GSD_SMARTCARD_MANAGER(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSD_TYPE_SMARTCARD_MANAGER, GsdSmartcardManager))
-#define GSD_SMARTCARD_MANAGER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GSD_TYPE_SMARTCARD_MANAGER, GsdSmartcardManagerClass))
-#define GSD_IS_SMARTCARD_MANAGER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SC_TYPE_SMARTCARD_MANAGER))
-#define GSD_IS_SMARTCARD_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SC_TYPE_SMARTCARD_MANAGER))
-#define GSD_SMARTCARD_MANAGER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), GSD_TYPE_SMARTCARD_MANAGER, GsdSmartcardManagerClass))
-#define GSD_SMARTCARD_MANAGER_ERROR           (gsd_smartcard_manager_error_quark ())
-typedef struct _GsdSmartcardManager GsdSmartcardManager;
-typedef struct _GsdSmartcardManagerClass GsdSmartcardManagerClass;
-typedef struct _GsdSmartcardManagerPrivate GsdSmartcardManagerPrivate;
-typedef enum _GsdSmartcardManagerError GsdSmartcardManagerError;
-
-struct _GsdSmartcardManager {
-    GObject parent;
-
-    /*< private > */
-    GsdSmartcardManagerPrivate *priv;
-};
-
-struct _GsdSmartcardManagerClass {
-        GObjectClass parent_class;
-
-        /* Signals */
-        void (*smartcard_inserted) (GsdSmartcardManager *manager,
-                                    GsdSmartcard        *token);
-        void (*smartcard_removed) (GsdSmartcardManager *manager,
-                                   GsdSmartcard        *token);
-        void (*error) (GsdSmartcardManager *manager,
-                       GError              *error);
-};
-
-enum _GsdSmartcardManagerError {
-    GSD_SMARTCARD_MANAGER_ERROR_GENERIC = 0,
-    GSD_SMARTCARD_MANAGER_ERROR_WITH_NSS,
-    GSD_SMARTCARD_MANAGER_ERROR_LOADING_DRIVER,
-    GSD_SMARTCARD_MANAGER_ERROR_WATCHING_FOR_EVENTS,
-    GSD_SMARTCARD_MANAGER_ERROR_REPORTING_EVENTS
-};
-
-GType gsd_smartcard_manager_get_type (void) G_GNUC_CONST;
-GQuark gsd_smartcard_manager_error_quark (void) G_GNUC_CONST;
-
-GsdSmartcardManager *gsd_smartcard_manager_new_default (void);
-
-GsdSmartcardManager *gsd_smartcard_manager_new (const char *module);
-
-gboolean gsd_smartcard_manager_start (GsdSmartcardManager  *manager,
-                                      GError              **error);
-
-void gsd_smartcard_manager_stop (GsdSmartcardManager *manager);
-
-char *gsd_smartcard_manager_get_module_path (GsdSmartcardManager *manager);
-gboolean gsd_smartcard_manager_login_card_is_inserted (GsdSmartcardManager *manager);
-
-G_END_DECLS
-#endif                                /* GSD_SMARTCARD_MANAGER_H */
diff --git a/plugins/smartcard/gsd-smartcard-plugin.c b/plugins/smartcard/gsd-smartcard-plugin.c
deleted file mode 100644
index df1a8c8..0000000
--- a/plugins/smartcard/gsd-smartcard-plugin.c
+++ /dev/null
@@ -1,337 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
- *
- * Copyright (C) 2010 Red Hat, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- */
-
-#include "config.h"
-
-#include <glib/gi18n-lib.h>
-#include <gmodule.h>
-
-#include <glib.h>
-#include <glib-object.h>
-#include <gio/gio.h>
-
-#include "gnome-settings-plugin.h"
-#include "gnome-settings-session.h"
-#include "gsd-smartcard-plugin.h"
-#include "gsd-smartcard-manager.h"
-
-struct GsdSmartcardPluginPrivate {
-        GsdSmartcardManager *manager;
-        GDBusConnection     *bus_connection;
-
-        guint32              is_active : 1;
-};
-
-typedef enum
-{
-    GSD_SMARTCARD_REMOVE_ACTION_NONE,
-    GSD_SMARTCARD_REMOVE_ACTION_LOCK_SCREEN,
-    GSD_SMARTCARD_REMOVE_ACTION_FORCE_LOGOUT,
-} GsdSmartcardRemoveAction;
-
-#define SCREENSAVER_DBUS_NAME      "org.gnome.ScreenSaver"
-#define SCREENSAVER_DBUS_PATH      "/"
-#define SCREENSAVER_DBUS_INTERFACE "org.gnome.ScreenSaver"
-
-#define SM_LOGOUT_MODE_FORCE 2
-
-#define KEY_REMOVE_ACTION "removal-action"
-
-#define GSD_SMARTCARD_PLUGIN_GET_PRIVATE(object) (G_TYPE_INSTANCE_GET_PRIVATE ((object), GSD_TYPE_SMARTCARD_PLUGIN, GsdSmartcardPluginPrivate))
-
-GNOME_SETTINGS_PLUGIN_REGISTER (GsdSmartcardPlugin, gsd_smartcard_plugin);
-
-static void
-simulate_user_activity (GsdSmartcardPlugin *plugin)
-{
-        GDBusProxy *screensaver_proxy;
-
-        g_debug ("GsdSmartcardPlugin telling screensaver about smart card insertion");
-        screensaver_proxy = g_dbus_proxy_new_sync (plugin->priv->bus_connection,
-                                                   0, NULL,
-                                                   SCREENSAVER_DBUS_NAME,
-                                                   SCREENSAVER_DBUS_PATH,
-                                                   SCREENSAVER_DBUS_INTERFACE,
-                                                   NULL, NULL);
-
-        g_dbus_proxy_call (screensaver_proxy,
-                           "SimulateUserActivity",
-                           NULL, G_DBUS_CALL_FLAGS_NONE,
-                           -1, NULL, NULL, NULL);
-
-        g_object_unref (screensaver_proxy);
-}
-
-static void
-lock_screen (GsdSmartcardPlugin *plugin)
-{
-        GDBusProxy *screensaver_proxy;
-
-        g_debug ("GsdSmartcardPlugin telling screensaver to lock screen");
-        screensaver_proxy = g_dbus_proxy_new_sync (plugin->priv->bus_connection,
-                                                   0, NULL,
-                                                   SCREENSAVER_DBUS_NAME,
-                                                   SCREENSAVER_DBUS_PATH,
-                                                   SCREENSAVER_DBUS_INTERFACE,
-                                                   NULL, NULL);
-
-        g_dbus_proxy_call (screensaver_proxy,
-                           "Lock",
-                           NULL, G_DBUS_CALL_FLAGS_NONE,
-                           -1, NULL, NULL, NULL);
-
-        g_object_unref (screensaver_proxy);
-}
-
-static void
-force_logout (GsdSmartcardPlugin *plugin)
-{
-        GDBusProxy *sm_proxy;
-        GError     *error;
-        GVariant   *res;
-
-        g_debug ("GsdSmartcardPlugin telling session manager to force logout");
-        sm_proxy = gnome_settings_session_get_session_proxy ();
-
-        error = NULL;
-        res = g_dbus_proxy_call_sync (sm_proxy,
-                                      "Logout",
-                                      g_variant_new ("(i)", SM_LOGOUT_MODE_FORCE),
-                                      G_DBUS_CALL_FLAGS_NONE,
-                                      -1, NULL, &error);
-
-        if (! res) {
-                g_warning ("GsdSmartcardPlugin Unable to force logout: %s", error->message);
-                g_error_free (error);
-        } else
-                g_variant_unref (res);
-
-        g_object_unref (sm_proxy);
-}
-
-static void
-gsd_smartcard_plugin_init (GsdSmartcardPlugin *plugin)
-{
-        plugin->priv = GSD_SMARTCARD_PLUGIN_GET_PRIVATE (plugin);
-
-        g_debug ("GsdSmartcardPlugin initializing");
-
-        plugin->priv->manager = gsd_smartcard_manager_new (NULL);
-}
-
-static void
-gsd_smartcard_plugin_finalize (GObject *object)
-{
-        GsdSmartcardPlugin *plugin;
-
-        g_return_if_fail (object != NULL);
-        g_return_if_fail (GSD_IS_SMARTCARD_PLUGIN (object));
-
-        g_debug ("GsdSmartcardPlugin finalizing");
-
-        plugin = GSD_SMARTCARD_PLUGIN (object);
-
-        g_return_if_fail (plugin->priv != NULL);
-
-        if (plugin->priv->manager != NULL) {
-                g_object_unref (plugin->priv->manager);
-        }
-
-        G_OBJECT_CLASS (gsd_smartcard_plugin_parent_class)->finalize (object);
-}
-
-static void
-smartcard_inserted_cb (GsdSmartcardManager *card_monitor,
-                       GsdSmartcard        *card,
-                       GsdSmartcardPlugin  *plugin)
-{
-        char *name;
-
-        name = gsd_smartcard_get_name (card);
-        g_debug ("GsdSmartcardPlugin smart card '%s' inserted", name);
-        g_free (name);
-
-        simulate_user_activity (plugin);
-}
-
-static gboolean
-user_logged_in_with_smartcard (void)
-{
-    return g_getenv ("PKCS11_LOGIN_TOKEN_NAME") != NULL;
-}
-
-static GsdSmartcardRemoveAction
-get_configured_remove_action (GsdSmartcardPlugin *plugin)
-{
-        GSettings *settings;
-        char *remove_action_string;
-        GsdSmartcardRemoveAction remove_action;
-
-        settings = g_settings_new ("org.gnome.settings-daemon.peripherals.smartcard");
-        remove_action_string = g_settings_get_string (settings, KEY_REMOVE_ACTION);
-
-        if (remove_action_string == NULL) {
-                g_warning ("GsdSmartcardPlugin unable to get smartcard remove action");
-                remove_action = GSD_SMARTCARD_REMOVE_ACTION_NONE;
-        } else if (strcmp (remove_action_string, "none") == 0) {
-                remove_action = GSD_SMARTCARD_REMOVE_ACTION_NONE;
-        } else if (strcmp (remove_action_string, "lock_screen") == 0) {
-                remove_action = GSD_SMARTCARD_REMOVE_ACTION_LOCK_SCREEN;
-        } else if (strcmp (remove_action_string, "force_logout") == 0) {
-                remove_action = GSD_SMARTCARD_REMOVE_ACTION_FORCE_LOGOUT;
-        } else {
-                g_warning ("GsdSmartcardPlugin unknown smartcard remove action");
-                remove_action = GSD_SMARTCARD_REMOVE_ACTION_NONE;
-        }
-
-        g_object_unref (settings);
-
-        return remove_action;
-}
-
-static void
-process_smartcard_removal (GsdSmartcardPlugin *plugin)
-{
-        GsdSmartcardRemoveAction remove_action;
-
-        g_debug ("GsdSmartcardPlugin processing smartcard removal");
-        remove_action = get_configured_remove_action (plugin);
-
-        switch (remove_action)
-        {
-            case GSD_SMARTCARD_REMOVE_ACTION_NONE:
-                return;
-            case GSD_SMARTCARD_REMOVE_ACTION_LOCK_SCREEN:
-                lock_screen (plugin);
-                break;
-            case GSD_SMARTCARD_REMOVE_ACTION_FORCE_LOGOUT:
-                force_logout (plugin);
-                break;
-        }
-}
-
-static void
-smartcard_removed_cb (GsdSmartcardManager *card_monitor,
-                      GsdSmartcard        *card,
-                      GsdSmartcardPlugin  *plugin)
-{
-
-        char *name;
-
-        name = gsd_smartcard_get_name (card);
-        g_debug ("GsdSmartcardPlugin smart card '%s' removed", name);
-        g_free (name);
-
-        if (!gsd_smartcard_is_login_card (card)) {
-                g_debug ("GsdSmartcardPlugin removed smart card was not used to login");
-                return;
-        }
-
-        process_smartcard_removal (plugin);
-}
-
-static void
-impl_activate (GnomeSettingsPlugin *plugin)
-{
-        GError *error;
-        GsdSmartcardPlugin *smartcard_plugin = GSD_SMARTCARD_PLUGIN (plugin);
-
-        if (smartcard_plugin->priv->is_active) {
-                g_debug ("GsdSmartcardPlugin Not activating smartcard plugin, because it's "
-                         "already active");
-                return;
-        }
-
-        if (!user_logged_in_with_smartcard ()) {
-                g_debug ("GsdSmartcardPlugin Not activating smartcard plugin, because user didn't use "
-                         " smartcard to log in");
-                smartcard_plugin->priv->is_active = FALSE;
-                return;
-        }
-
-        g_debug ("GsdSmartcardPlugin Activating smartcard plugin");
-
-        error = NULL;
-        smartcard_plugin->priv->bus_connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
-
-        if (smartcard_plugin->priv->bus_connection == NULL) {
-                g_warning ("GsdSmartcardPlugin Unable to connect to session bus: %s", error->message);
-                return;
-        }
-
-        if (!gsd_smartcard_manager_start (smartcard_plugin->priv->manager, &error)) {
-                g_warning ("GsdSmartcardPlugin Unable to start smartcard manager: %s", error->message);
-                g_error_free (error);
-        }
-
-        g_signal_connect (smartcard_plugin->priv->manager,
-                          "smartcard-removed",
-                          G_CALLBACK (smartcard_removed_cb), smartcard_plugin);
-
-        g_signal_connect (smartcard_plugin->priv->manager,
-                          "smartcard-inserted",
-                          G_CALLBACK (smartcard_inserted_cb), smartcard_plugin);
-
-        if (!gsd_smartcard_manager_login_card_is_inserted (smartcard_plugin->priv->manager)) {
-                g_debug ("GsdSmartcardPlugin processing smartcard removal immediately user logged in with smartcard "
-                         "and it's not inserted");
-                process_smartcard_removal (smartcard_plugin);
-        }
-
-        smartcard_plugin->priv->is_active = TRUE;
-}
-
-static void
-impl_deactivate (GnomeSettingsPlugin *plugin)
-{
-        GsdSmartcardPlugin *smartcard_plugin = GSD_SMARTCARD_PLUGIN (plugin);
-
-        if (!smartcard_plugin->priv->is_active) {
-                g_debug ("GsdSmartcardPlugin Not deactivating smartcard plugin, "
-                         "because it's already inactive");
-                return;
-        }
-
-        g_debug ("GsdSmartcardPlugin Deactivating smartcard plugin");
-
-        gsd_smartcard_manager_stop (smartcard_plugin->priv->manager);
-
-        g_signal_handlers_disconnect_by_func (smartcard_plugin->priv->manager,
-                                              smartcard_removed_cb, smartcard_plugin);
-
-        g_signal_handlers_disconnect_by_func (smartcard_plugin->priv->manager,
-                                              smartcard_inserted_cb, smartcard_plugin);
-        smartcard_plugin->priv->bus_connection = NULL;
-        smartcard_plugin->priv->is_active = FALSE;
-}
-
-static void
-gsd_smartcard_plugin_class_init (GsdSmartcardPluginClass *klass)
-{
-        GObjectClass *object_class = G_OBJECT_CLASS (klass);
-        GnomeSettingsPluginClass *plugin_class = GNOME_SETTINGS_PLUGIN_CLASS (klass);
-
-        object_class->finalize = gsd_smartcard_plugin_finalize;
-
-        plugin_class->activate = impl_activate;
-        plugin_class->deactivate = impl_deactivate;
-
-        g_type_class_add_private (klass, sizeof (GsdSmartcardPluginPrivate));
-}
diff --git a/plugins/smartcard/gsd-smartcard-plugin.h b/plugins/smartcard/gsd-smartcard-plugin.h
deleted file mode 100644
index f1458d1..0000000
--- a/plugins/smartcard/gsd-smartcard-plugin.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
- *
- * Copyright (C) 2010 Red Hat, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- */
-
-#ifndef __GSD_SMARTCARD_PLUGIN_H__
-#define __GSD_SMARTCARD_PLUGIN_H__
-
-#include <glib.h>
-#include <glib-object.h>
-#include <gmodule.h>
-
-#include "gnome-settings-plugin.h"
-
-G_BEGIN_DECLS
-
-#define GSD_TYPE_SMARTCARD_PLUGIN                (gsd_smartcard_plugin_get_type ())
-#define GSD_SMARTCARD_PLUGIN(o)                  (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_SMARTCARD_PLUGIN, GsdSmartcardPlugin))
-#define GSD_SMARTCARD_PLUGIN_CLASS(k)            (G_TYPE_CHECK_CLASS_CAST ((k), GSD_TYPE_SMARTCARD_PLUGIN, GsdSmartcardPluginClass))
-#define GSD_IS_SMARTCARD_PLUGIN(o)               (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_SMARTCARD_PLUGIN))
-#define GSD_IS_SMARTCARD_PLUGIN_CLASS(k)         (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_SMARTCARD_PLUGIN))
-#define GSD_SMARTCARD_PLUGIN_GET_CLASS(o)        (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_SMARTCARD_PLUGIN, GsdSmartcardPluginClass))
-
-typedef struct GsdSmartcardPluginPrivate GsdSmartcardPluginPrivate;
-
-typedef struct
-{
-        GnomeSettingsPlugin parent;
-        GsdSmartcardPluginPrivate *priv;
-} GsdSmartcardPlugin;
-
-typedef struct
-{
-        GnomeSettingsPluginClass parent_class;
-} GsdSmartcardPluginClass;
-
-GType gsd_smartcard_plugin_get_type (void) G_GNUC_CONST;
-
-/* All the plugins must implement this function */
-G_MODULE_EXPORT GType register_gnome_settings_plugin (GTypeModule *module);
-
-G_END_DECLS
-
-#endif /* __GSD_SMARTCARD_PLUGIN_H__ */
diff --git a/plugins/smartcard/gsd-smartcard.c b/plugins/smartcard/gsd-smartcard.c
deleted file mode 100644
index a926df1..0000000
--- a/plugins/smartcard/gsd-smartcard.c
+++ /dev/null
@@ -1,556 +0,0 @@
-/* gsd-smartcard.c - smartcard object
- *
- * Copyright (C) 2006 Ray Strode <rstrode@redhat.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- */
-
-#include "config.h"
-
-#define GSD_SMARTCARD_ENABLE_INTERNAL_API
-#include "gsd-smartcard.h"
-
-#include <errno.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <glib.h>
-#include <glib/gi18n.h>
-
-#include <cert.h>
-#include <nss.h>
-#include <pk11func.h>
-#include <prerror.h>
-#include <secmod.h>
-#include <secerr.h>
-
-struct _GsdSmartcardPrivate {
-        SECMODModule *module;
-        GsdSmartcardState state;
-
-        CK_SLOT_ID slot_id;
-        int slot_series;
-
-        PK11SlotInfo *slot;
-        char *name;
-
-        CERTCertificate *signing_certificate;
-        CERTCertificate *encryption_certificate;
-};
-
-static void gsd_smartcard_finalize (GObject *object);
-static void gsd_smartcard_class_install_signals (GsdSmartcardClass *card_class);
-static void gsd_smartcard_class_install_properties (GsdSmartcardClass *card_class);
-static void gsd_smartcard_set_property (GObject       *object,
-                                       guint          prop_id,
-                                       const GValue  *value,
-                                       GParamSpec    *pspec);
-static void gsd_smartcard_get_property (GObject     *object,
-                                       guint        prop_id,
-                                       GValue      *value,
-                                       GParamSpec  *pspec);
-static void gsd_smartcard_set_name (GsdSmartcard *card, const char *name);
-static void gsd_smartcard_set_slot_id (GsdSmartcard *card,
-                                      int                 slot_id);
-static void gsd_smartcard_set_slot_series (GsdSmartcard *card,
-                                          int          slot_series);
-static void gsd_smartcard_set_module (GsdSmartcard *card,
-                                     SECMODModule *module);
-
-static PK11SlotInfo *gsd_smartcard_find_slot_from_id (GsdSmartcard *card,
-                                                     int slot_id);
-
-static PK11SlotInfo *gsd_smartcard_find_slot_from_card_name (GsdSmartcard *card,
-                                                            const char  *card_name);
-
-#ifndef GSD_SMARTCARD_DEFAULT_SLOT_ID
-#define GSD_SMARTCARD_DEFAULT_SLOT_ID ((gulong) -1)
-#endif
-
-#ifndef GSD_SMARTCARD_DEFAULT_SLOT_SERIES
-#define GSD_SMARTCARD_DEFAULT_SLOT_SERIES -1
-#endif
-
-enum {
-        PROP_0 = 0,
-        PROP_NAME,
-        PROP_SLOT_ID,
-        PROP_SLOT_SERIES,
-        PROP_MODULE,
-        NUMBER_OF_PROPERTIES
-};
-
-enum {
-        INSERTED,
-        REMOVED,
-        NUMBER_OF_SIGNALS
-};
-
-static guint gsd_smartcard_signals[NUMBER_OF_SIGNALS];
-
-G_DEFINE_TYPE (GsdSmartcard, gsd_smartcard, G_TYPE_OBJECT);
-
-static void
-gsd_smartcard_class_init (GsdSmartcardClass *card_class)
-{
-        GObjectClass *gobject_class;
-
-        gobject_class = G_OBJECT_CLASS (card_class);
-
-        gobject_class->finalize = gsd_smartcard_finalize;
-
-        gsd_smartcard_class_install_signals (card_class);
-        gsd_smartcard_class_install_properties (card_class);
-
-        g_type_class_add_private (card_class,
-                                  sizeof (GsdSmartcardPrivate));
-}
-
-static void
-gsd_smartcard_class_install_signals (GsdSmartcardClass *card_class)
-{
-        GObjectClass *object_class;
-
-        object_class = G_OBJECT_CLASS (card_class);
-
-        gsd_smartcard_signals[INSERTED] =
-                g_signal_new ("inserted",
-                          G_OBJECT_CLASS_TYPE (object_class),
-                          G_SIGNAL_RUN_LAST,
-                          G_STRUCT_OFFSET (GsdSmartcardClass,
-                                           inserted),
-                          NULL, NULL, g_cclosure_marshal_VOID__VOID,
-                          G_TYPE_NONE, 0);
-
-        gsd_smartcard_signals[REMOVED] =
-                g_signal_new ("removed",
-                          G_OBJECT_CLASS_TYPE (object_class),
-                          G_SIGNAL_RUN_LAST,
-                          G_STRUCT_OFFSET (GsdSmartcardClass,
-                                           removed),
-                          NULL, NULL, g_cclosure_marshal_VOID__VOID,
-                          G_TYPE_NONE, 0);
-}
-
-static void
-gsd_smartcard_class_install_properties (GsdSmartcardClass *card_class)
-{
-        GObjectClass *object_class;
-        GParamSpec *param_spec;
-
-        object_class = G_OBJECT_CLASS (card_class);
-        object_class->set_property = gsd_smartcard_set_property;
-        object_class->get_property = gsd_smartcard_get_property;
-
-        param_spec = g_param_spec_ulong ("slot-id", "Slot ID",
-                                         "The slot the card is in",
-                                         1, G_MAXULONG,
-                                         GSD_SMARTCARD_DEFAULT_SLOT_ID,
-                                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
-        g_object_class_install_property (object_class, PROP_SLOT_ID, param_spec);
-
-        param_spec = g_param_spec_int ("slot-series", "Slot Series",
-                                       "per-slot card identifier",
-                                       -1, G_MAXINT,
-                                       GSD_SMARTCARD_DEFAULT_SLOT_SERIES,
-                                       G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
-        g_object_class_install_property (object_class, PROP_SLOT_SERIES, param_spec);
-
-        param_spec = g_param_spec_string ("name", "name",
-                                          "name", NULL,
-                                          G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
-        g_object_class_install_property (object_class, PROP_NAME, param_spec);
-
-        param_spec = g_param_spec_pointer ("module", "Module",
-                                           "smartcard driver",
-                                           G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY);
-        g_object_class_install_property (object_class, PROP_MODULE, param_spec);
-}
-
-static void
-gsd_smartcard_set_property (GObject       *object,
-                            guint          prop_id,
-                            const GValue  *value,
-                            GParamSpec    *pspec)
-{
-        GsdSmartcard *card = GSD_SMARTCARD (object);
-
-        switch (prop_id) {
-                case PROP_NAME:
-                        gsd_smartcard_set_name (card, g_value_get_string (value));
-                        break;
-
-                case PROP_SLOT_ID:
-                        gsd_smartcard_set_slot_id (card,
-                                                   g_value_get_ulong (value));
-                        break;
-
-                case PROP_SLOT_SERIES:
-                        gsd_smartcard_set_slot_series (card,
-                                                       g_value_get_int (value));
-                        break;
-
-                case PROP_MODULE:
-                        gsd_smartcard_set_module (card,
-                                                  (SECMODModule *)
-                                                  g_value_get_pointer (value));
-                        break;
-
-                default:
-                        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-        }
-}
-
-CK_SLOT_ID
-gsd_smartcard_get_slot_id (GsdSmartcard *card)
-{
-        return card->priv->slot_id;
-}
-
-GsdSmartcardState
-gsd_smartcard_get_state (GsdSmartcard *card)
-{
-        return card->priv->state;
-}
-
-char *
-gsd_smartcard_get_name (GsdSmartcard *card)
-{
-        return g_strdup (card->priv->name);
-}
-
-gboolean
-gsd_smartcard_is_login_card (GsdSmartcard *card)
-{
-        const char *login_card_name;
-        login_card_name = g_getenv ("PKCS11_LOGIN_TOKEN_NAME");
-
-        if ((login_card_name == NULL) || (card->priv->name == NULL)) {
-                return FALSE;
-        }
-
-        if (strcmp (card->priv->name, login_card_name) == 0) {
-                return TRUE;
-        }
-
-        return FALSE;
-}
-
-static void
-gsd_smartcard_get_property (GObject    *object,
-                            guint        prop_id,
-                            GValue      *value,
-                            GParamSpec  *pspec)
-{
-        GsdSmartcard *card = GSD_SMARTCARD (object);
-
-        switch (prop_id) {
-                case PROP_NAME:
-                        g_value_take_string (value,
-                                             gsd_smartcard_get_name (card));
-                        break;
-
-                case PROP_SLOT_ID:
-                        g_value_set_ulong (value,
-                                           (gulong) gsd_smartcard_get_slot_id (card));
-                        break;
-
-                case PROP_SLOT_SERIES:
-                        g_value_set_int (value,
-                                         gsd_smartcard_get_slot_series (card));
-                        break;
-
-                default:
-                        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-        }
-}
-
-static void
-gsd_smartcard_set_name (GsdSmartcard *card,
-                        const char   *name)
-{
-        if (name == NULL) {
-                return;
-        }
-
-        if ((card->priv->name == NULL) ||
-            (strcmp (card->priv->name, name) != 0)) {
-                g_free (card->priv->name);
-                card->priv->name = g_strdup (name);
-
-                if (card->priv->slot == NULL) {
-                        card->priv->slot = gsd_smartcard_find_slot_from_card_name (card,
-                                                                                     card->priv->name);
-
-                        if (card->priv->slot != NULL) {
-                                int slot_id, slot_series;
-
-                                slot_id = PK11_GetSlotID (card->priv->slot);
-                                if (slot_id != card->priv->slot_id) {
-                                        gsd_smartcard_set_slot_id (card, slot_id);
-                                }
-
-                                slot_series = PK11_GetSlotSeries (card->priv->slot);
-                                if (slot_series != card->priv->slot_series) {
-                                        gsd_smartcard_set_slot_series (card, slot_series);
-                                }
-
-                                _gsd_smartcard_set_state (card, GSD_SMARTCARD_STATE_INSERTED);
-                        } else {
-                                _gsd_smartcard_set_state (card, GSD_SMARTCARD_STATE_REMOVED);
-                        }
-                }
-
-                g_object_notify (G_OBJECT (card), "name");
-        }
-}
-
-static void
-gsd_smartcard_set_slot_id (GsdSmartcard *card,
-                           int           slot_id)
-{
-        if (card->priv->slot_id != slot_id) {
-                card->priv->slot_id = slot_id;
-
-                if (card->priv->slot == NULL) {
-                        card->priv->slot = gsd_smartcard_find_slot_from_id (card,
-                                                                             card->priv->slot_id);
-
-                        if (card->priv->slot != NULL) {
-                                const char *card_name;
-
-                                card_name = PK11_GetTokenName (card->priv->slot);
-                                if ((card->priv->name == NULL) ||
-                                    ((card_name != NULL) &&
-                                    (strcmp (card_name, card->priv->name) != 0))) {
-                                        gsd_smartcard_set_name (card, card_name);
-                                }
-
-                                _gsd_smartcard_set_state (card, GSD_SMARTCARD_STATE_INSERTED);
-                        } else {
-                                _gsd_smartcard_set_state (card, GSD_SMARTCARD_STATE_REMOVED);
-                        }
-                }
-
-                g_object_notify (G_OBJECT (card), "slot-id");
-        }
-}
-
-static void
-gsd_smartcard_set_slot_series (GsdSmartcard *card,
-                               int           slot_series)
-{
-        if (card->priv->slot_series != slot_series) {
-                card->priv->slot_series = slot_series;
-                g_object_notify (G_OBJECT (card), "slot-series");
-        }
-}
-
-static void
-gsd_smartcard_set_module (GsdSmartcard *card,
-                          SECMODModule *module)
-{
-        gboolean should_notify;
-
-        if (card->priv->module != module) {
-                should_notify = TRUE;
-        } else {
-                should_notify = FALSE;
-        }
-
-        if (card->priv->module != NULL) {
-                SECMOD_DestroyModule (card->priv->module);
-                card->priv->module = NULL;
-        }
-
-        if (module != NULL) {
-                card->priv->module = SECMOD_ReferenceModule (module);
-        }
-
-        if (should_notify) {
-                g_object_notify (G_OBJECT (card), "module");
-        }
-}
-
-int
-gsd_smartcard_get_slot_series (GsdSmartcard *card)
-{
-        return card->priv->slot_series;
-}
-
-static void
-gsd_smartcard_init (GsdSmartcard *card)
-{
-
-        g_debug ("initializing smartcard ");
-
-        card->priv = G_TYPE_INSTANCE_GET_PRIVATE (card,
-                                                  GSD_TYPE_SMARTCARD,
-                                                  GsdSmartcardPrivate);
-}
-
-static void gsd_smartcard_finalize (GObject *object)
-{
-        GsdSmartcard *card;
-        GObjectClass *gobject_class;
-
-        card = GSD_SMARTCARD (object);
-
-        g_free (card->priv->name);
-
-        gsd_smartcard_set_module (card, NULL);
-
-        gobject_class = G_OBJECT_CLASS (gsd_smartcard_parent_class);
-
-        gobject_class->finalize (object);
-}
-
-GQuark gsd_smartcard_error_quark (void)
-{
-        static GQuark error_quark = 0;
-
-        if (error_quark == 0) {
-                error_quark = g_quark_from_static_string ("gsd-smartcard-error-quark");
-        }
-
-        return error_quark;
-}
-
-GsdSmartcard *
-_gsd_smartcard_new (SECMODModule *module,
-                    CK_SLOT_ID    slot_id,
-                    int           slot_series)
-{
-        GsdSmartcard *card;
-
-        g_return_val_if_fail (module != NULL, NULL);
-        g_return_val_if_fail (slot_id >= 1, NULL);
-        g_return_val_if_fail (slot_series > 0, NULL);
-        g_return_val_if_fail (sizeof (gulong) == sizeof (slot_id), NULL);
-
-        card = GSD_SMARTCARD (g_object_new (GSD_TYPE_SMARTCARD,
-                                             "module", module,
-                                             "slot-id", (gulong) slot_id,
-                                             "slot-series", slot_series,
-                                             NULL));
-        return card;
-}
-
-GsdSmartcard *
-_gsd_smartcard_new_from_name (SECMODModule *module,
-                              const char   *name)
-{
-        GsdSmartcard *card;
-
-        g_return_val_if_fail (module != NULL, NULL);
-        g_return_val_if_fail (name != NULL, NULL);
-
-        card = GSD_SMARTCARD (g_object_new (GSD_TYPE_SMARTCARD,
-                                            "module", module,
-                                            "name", name,
-                                            NULL));
-        return card;
-}
-
-void
-_gsd_smartcard_set_state (GsdSmartcard      *card,
-                          GsdSmartcardState  state)
-{
-        /* gsd_smartcard_fetch_certificates (card); */
-        if (card->priv->state != state) {
-                card->priv->state = state;
-
-                if (state == GSD_SMARTCARD_STATE_INSERTED) {
-                        g_signal_emit (card, gsd_smartcard_signals[INSERTED], 0);
-                } else if (state == GSD_SMARTCARD_STATE_REMOVED) {
-                        g_signal_emit (card, gsd_smartcard_signals[REMOVED], 0);
-                } else {
-                        g_assert_not_reached ();
-                }
-        }
-}
-
-/* So we could conceivably make the closure data a pointer to the card
- * or something similiar and then emit signals when we want passwords,
- * but it's probably easier to just get the password up front and use
- * it.  So we just take the passed in g_malloc'd (well probably, who knows)
- * and strdup it using NSPR's memory allocation routines.
- */
-static char *
-gsd_smartcard_password_handler (PK11SlotInfo *slot,
-                                PRBool        is_retrying,
-                                const char   *password)
-{
-        if (is_retrying) {
-                return NULL;
-        }
-
-        return password != NULL? PL_strdup (password): NULL;
-}
-
-gboolean
-gsd_smartcard_unlock (GsdSmartcard *card,
-                      const char   *password)
-{
-        SECStatus status;
-
-        PK11_SetPasswordFunc ((PK11PasswordFunc) gsd_smartcard_password_handler);
-
-        /* we pass PR_TRUE to load certificates
-        */
-        status = PK11_Authenticate (card->priv->slot, PR_TRUE, (gpointer) password);
-
-        if (status != SECSuccess) {
-                g_debug ("could not unlock card - %d", status);
-                return FALSE;
-        }
-        return TRUE;
-}
-
-static PK11SlotInfo *
-gsd_smartcard_find_slot_from_card_name (GsdSmartcard *card,
-                                        const char   *card_name)
-{
-        int i;
-
-        for (i = 0; i < card->priv->module->slotCount; i++) {
-                const char *slot_card_name;
-
-                slot_card_name = PK11_GetTokenName (card->priv->module->slots[i]);
-
-                if ((slot_card_name != NULL) &&
-                    (strcmp (slot_card_name, card_name) == 0)) {
-                        return card->priv->module->slots[i];
-                }
-        }
-
-        return NULL;
-}
-
-static PK11SlotInfo *
-gsd_smartcard_find_slot_from_id (GsdSmartcard *card,
-                                 int           slot_id)
-{
-        int i;
-
-        for (i = 0; i < card->priv->module->slotCount; i++) {
-                if (PK11_GetSlotID (card->priv->module->slots[i]) == slot_id) {
-                        return card->priv->module->slots[i];
-                }
-        }
-
-        return NULL;
-}
diff --git a/plugins/smartcard/gsd-smartcard.h b/plugins/smartcard/gsd-smartcard.h
deleted file mode 100644
index c99b5fa..0000000
--- a/plugins/smartcard/gsd-smartcard.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/* securitycard.h - api for reading and writing data to a security card
- *
- * Copyright (C) 2006 Ray Strode
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- */
-#ifndef GSD_SMARTCARD_H
-#define GSD_SMARTCARD_H
-
-#include <glib.h>
-#include <glib-object.h>
-
-#include <secmod.h>
-
-G_BEGIN_DECLS
-#define GSD_TYPE_SMARTCARD            (gsd_smartcard_get_type ())
-#define GSD_SMARTCARD(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSD_TYPE_SMARTCARD, GsdSmartcard))
-#define GSD_SMARTCARD_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GSD_TYPE_SMARTCARD, GsdSmartcardClass))
-#define GSD_IS_SMARTCARD(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSD_TYPE_SMARTCARD))
-#define GSD_IS_SMARTCARD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GSD_TYPE_SMARTCARD))
-#define GSD_SMARTCARD_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), GSD_TYPE_SMARTCARD, GsdSmartcardClass))
-#define GSD_SMARTCARD_ERROR           (gsd_smartcard_error_quark ())
-typedef struct _GsdSmartcardClass GsdSmartcardClass;
-typedef struct _GsdSmartcard GsdSmartcard;
-typedef struct _GsdSmartcardPrivate GsdSmartcardPrivate;
-typedef enum _GsdSmartcardError GsdSmartcardError;
-typedef enum _GsdSmartcardState GsdSmartcardState;
-
-typedef struct _GsdSmartcardRequest GsdSmartcardRequest;
-
-struct _GsdSmartcard {
-    GObject parent;
-
-    /*< private > */
-    GsdSmartcardPrivate *priv;
-};
-
-struct _GsdSmartcardClass {
-    GObjectClass parent_class;
-
-    void (* inserted) (GsdSmartcard *card);
-    void (* removed)  (GsdSmartcard *card);
-};
-
-enum _GsdSmartcardError {
-    GSD_SMARTCARD_ERROR_GENERIC = 0,
-};
-
-enum _GsdSmartcardState {
-    GSD_SMARTCARD_STATE_INSERTED = 0,
-    GSD_SMARTCARD_STATE_REMOVED,
-};
-
-GType gsd_smartcard_get_type (void) G_GNUC_CONST;
-GQuark gsd_smartcard_error_quark (void) G_GNUC_CONST;
-
-CK_SLOT_ID gsd_smartcard_get_slot_id (GsdSmartcard *card);
-gint gsd_smartcard_get_slot_series (GsdSmartcard *card);
-GsdSmartcardState gsd_smartcard_get_state (GsdSmartcard *card);
-
-char *gsd_smartcard_get_name (GsdSmartcard *card);
-gboolean gsd_smartcard_is_login_card (GsdSmartcard *card);
-
-gboolean gsd_smartcard_unlock (GsdSmartcard *card,
-                               const char   *password);
-
-/* don't under any circumstances call these functions */
-#ifdef GSD_SMARTCARD_ENABLE_INTERNAL_API
-
-GsdSmartcard *_gsd_smartcard_new (SECMODModule *module,
-                                  CK_SLOT_ID    slot_id,
-                                  gint          slot_series);
-GsdSmartcard *_gsd_smartcard_new_from_name (SECMODModule *module,
-                                            const char   *name);
-
-void _gsd_smartcard_set_state (GsdSmartcard      *card,
-                               GsdSmartcardState  state);
-#endif
-
-G_END_DECLS
-#endif                                /* GSD_SMARTCARD_H */
diff --git a/plugins/smartcard/test-smartcard.c b/plugins/smartcard/test-smartcard.c
deleted file mode 100644
index b57d908..0000000
--- a/plugins/smartcard/test-smartcard.c
+++ /dev/null
@@ -1,7 +0,0 @@
-#define NEW gsd_smartcard_manager_new_default
-#define START gsd_smartcard_manager_start
-#define STOP gsd_smartcard_manager_stop
-#define MANAGER GsdSmartcardManager
-#include "gsd-smartcard-manager.h"
-
-#include "test-plugin.h"
-- 
1.8.3.1


From f2afbc595d58cd54a586a1145879051161adb10c Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Tue, 28 May 2013 09:22:39 -0400
Subject: [PATCH 2/11] smartcard: add back smartcard support

This commit lands a rewrite of the smartcard plugin.  It makes use
of the DBus ObjectManager interface to export tokens over the bus,
as they're inserted and removed.

https://bugzilla.gnome.org/show_bug.cgi?id=704890
---
 plugins/smartcard/Makefile.am                      | 105 +++
 plugins/smartcard/gsd-smartcard-enum-types.c.in    |  42 +
 plugins/smartcard/gsd-smartcard-enum-types.h.in    |  24 +
 plugins/smartcard/gsd-smartcard-manager.c          | 870 +++++++++++++++++++++
 plugins/smartcard/gsd-smartcard-manager.h          |  82 ++
 plugins/smartcard/gsd-smartcard-plugin.c           |  30 +
 plugins/smartcard/gsd-smartcard-service.c          | 773 ++++++++++++++++++
 plugins/smartcard/gsd-smartcard-service.h          |  81 ++
 plugins/smartcard/gsd-smartcard-utils.c            | 191 +++++
 plugins/smartcard/gsd-smartcard-utils.h            |  38 +
 .../org.gnome.SettingsDaemon.Smartcard.xml         |  91 +++
 plugins/smartcard/test-smartcard.c                 |   7 +
 13 files changed, 2340 insertions(+)
 create mode 100644 plugins/smartcard/Makefile.am
 create mode 100644 plugins/smartcard/gsd-smartcard-enum-types.c.in
 create mode 100644 plugins/smartcard/gsd-smartcard-enum-types.h.in
 create mode 100644 plugins/smartcard/gsd-smartcard-manager.c
 create mode 100644 plugins/smartcard/gsd-smartcard-manager.h
 create mode 100644 plugins/smartcard/gsd-smartcard-plugin.c
 create mode 100644 plugins/smartcard/gsd-smartcard-service.c
 create mode 100644 plugins/smartcard/gsd-smartcard-service.h
 create mode 100644 plugins/smartcard/gsd-smartcard-utils.c
 create mode 100644 plugins/smartcard/gsd-smartcard-utils.h
 create mode 100644 plugins/smartcard/org.gnome.SettingsDaemon.Smartcard.xml
 create mode 100644 plugins/smartcard/test-smartcard.c

diff --git a/plugins/smartcard/Makefile.am b/plugins/smartcard/Makefile.am
new file mode 100644
index 0000000..2d27d1c
--- /dev/null
+++ b/plugins/smartcard/Makefile.am
@@ -0,0 +1,105 @@
+plugin_name = smartcard
+libsmartcard_headers = gsd-smartcard-manager.h \
+		       gsd-smartcard-utils.h
+dbus_built_sources = org.gnome.SettingsDaemon.Smartcard.c org.gnome.SettingsDaemon.Smartcard.h
+enum_built_sources = gsd-smartcard-enum-types.h gsd-smartcard-enum-types.c
+BUILT_SOURCES = $(dbus_built_sources) $(enum_built_sources)
+
+libexec_PROGRAMS = gsd-test-smartcard
+
+plugin_LTLIBRARIES = \
+	libsmartcard.la
+
+$(dbus_built_sources) : Makefile.am org.gnome.SettingsDaemon.Smartcard.xml
+	$(AM_V_GEN) gdbus-codegen \
+	--interface-prefix org.gnome.SettingsDaemon.Smartcard. \
+	--c-namespace GsdSmartcardService \
+	--c-generate-object-manager \
+	--generate-c-code org.gnome.SettingsDaemon.Smartcard \
+	org.gnome.SettingsDaemon.Smartcard.xml
+
+gsd-smartcard-enum-types.h: gsd-smartcard-enum-types.h.in $(libsmartcard_headers)
+	$(AM_V_GEN) $(GLIB_MKENUMS) --template $^ > $@
+
+gsd-smartcard-enum-types.c: gsd-smartcard-enum-types.c.in $(libsmartcard_headers)
+	$(AM_V_GEN) $(GLIB_MKENUMS) --template $^ > $@
+
+gsd_test_smartcard_SOURCES =        \
+	$(dbus_built_sources)   \
+	$(enum_built_sources)   \
+	gsd-smartcard-service.c \
+	gsd-smartcard-manager.c \
+	gsd-smartcard-utils.c   \
+	test-smartcard.c
+
+gsd_test_smartcard_CPPFLAGS =                                   \
+	-I$(top_srcdir)/data/                                   \
+	-I$(top_srcdir)/gnome-settings-daemon                   \
+	-I$(top_srcdir)/plugins/common                          \
+	-DSYSCONFDIR=\""$(sysconfdir)"\"                        \
+	-DLIBDIR=\""$(libdir)"\"                                \
+	-DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\"      \
+	-DGSD_SMARTCARD_MANAGER_NSS_DB=\""$(NSS_DATABASE)"\"    \
+	$(AM_CPPFLAGS)
+
+gsd_test_smartcard_CFLAGS =                                     \
+	 $(PLUGIN_CFLAGS)                                       \
+	 $(SETTINGS_PLUGIN_CFLAGS)                              \
+	 $(MEDIA_KEYS_CFLAGS)                                   \
+	 $(NSS_CFLAGS)                                          \
+	 $(AM_CFLAGS)
+
+gsd_test_smartcard_LDADD =                                      \
+	$(top_builddir)/gnome-settings-daemon/libgsd.la         \
+	$(top_builddir)/plugins/common/libcommon.la             \
+	$(NSS_LIBS)                                             \
+	$(SETTINGS_DAEMON_LIBS)                                 \
+	$(SETTINGS_PLUGIN_LIBS)
+
+
+libsmartcard_la_SOURCES = \
+	$(libsmartcard_headers) \
+	$(dbus_built_sources) \
+	$(enum_built_sources) \
+	gsd-smartcard-manager.c \
+	gsd-smartcard-plugin.c  \
+	gsd-smartcard-service.c \
+	gsd-smartcard-utils.c
+
+libsmartcard_la_CPPFLAGS = \
+	-I$(top_srcdir)/gnome-settings-daemon \
+	-DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \
+	-I$(top_srcdir)/plugins/common \
+	-DSYSCONFDIR=\""$(sysconfdir)"\" \
+	-DLIBDIR=\""$(libdir)"\" \
+	-DGSD_SMARTCARD_MANAGER_NSS_DB=\""$(NSS_DATABASE)"\" \
+	$(AM_CPPFLAGS)
+
+libsmartcard_la_CFLAGS = \
+	$(PLUGIN_CFLAGS)        \
+	$(SETTINGS_PLUGIN_CFLAGS) \
+	$(NSS_CFLAGS)        \
+	$(AM_CFLAGS)
+
+libsmartcard_la_LDFLAGS = \
+	$(GSD_PLUGIN_LDFLAGS)
+
+libsmartcard_la_LIBADD = \
+	$(SETTINGS_PLUGIN_LIBS)        \
+	$(NSS_LIBS)
+
+@GSD_INTLTOOL_PLUGIN_RULE@
+
+plugin_in_files = \
+	smartcard.gnome-settings-plugin.in
+
+plugin_DATA = $(plugin_in_files:.gnome-settings-plugin.in=.gnome-settings-plugin)
+
+EXTRA_DIST = \
+	$(plugin_in_files)
+
+CLEANFILES = \
+	$(plugin_DATA)
+
+DISTCLEANFILES = \
+	$(plugin_DATA)
diff --git a/plugins/smartcard/gsd-smartcard-enum-types.c.in b/plugins/smartcard/gsd-smartcard-enum-types.c.in
new file mode 100644
index 0000000..f281cf4
--- /dev/null
+++ b/plugins/smartcard/gsd-smartcard-enum-types.c.in
@@ -0,0 +1,42 @@
+/*** BEGIN file-header ***/
+
+#include <glib-object.h>
+
+/*** END file-header ***/
+
+/*** BEGIN file-production ***/
+#include "@filename@"
+/* enumerations from "@filename@" */
+/*** END file-production ***/
+
+/*** BEGIN value-header ***/
+GType @enum_name@_get_type (void) G_GNUC_CONST;
+
+GType
+@enum_name@_get_type (void)
+{
+ static GType etype = 0;
+
+ if (G_UNLIKELY(etype == 0)) {
+ static const G@Type@Value values[] = {
+/*** END value-header ***/
+
+/*** BEGIN value-production ***/
+ { @VALUENAME@, "@VALUENAME@", "@valuenick@" },
+/*** END value-production ***/
+
+/*** BEGIN value-tail ***/
+ { 0, NULL, NULL }
+ };
+
+ etype = g_@type@_register_static (g_intern_static_string ("@EnumName@"), values);
+ }
+
+ return etype;
+}
+
+/*** END value-tail ***/
+
+/*** BEGIN file-tail ***/
+ /**/
+/*** END file-tail ***/
diff --git a/plugins/smartcard/gsd-smartcard-enum-types.h.in b/plugins/smartcard/gsd-smartcard-enum-types.h.in
new file mode 100644
index 0000000..79dcc3d
--- /dev/null
+++ b/plugins/smartcard/gsd-smartcard-enum-types.h.in
@@ -0,0 +1,24 @@
+/*** BEGIN file-header ***/
+#ifndef GSD_IDENTITY_ENUM_TYPES_H
+#define GSD_IDENTITY_ENUM_TYPES_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+/*** END file-header ***/
+
+/*** BEGIN file-production ***/
+
+/* enumerations from "@filename@" */
+/*** END file-production ***/
+
+/*** BEGIN value-header ***/
+GType @enum_name@_get_type (void) G_GNUC_CONST;
+#define @ENUMPREFIX@_TYPE_@ENUMSHORT@ (@enum_name@_get_type ())
+/*** END value-header ***/
+
+/*** BEGIN file-tail ***/
+G_END_DECLS
+
+#endif /* GSD_IDENTITY_ENUM_TYPES_H */
+/*** END file-tail ***/
diff --git a/plugins/smartcard/gsd-smartcard-manager.c b/plugins/smartcard/gsd-smartcard-manager.c
new file mode 100644
index 0000000..05f77f8
--- /dev/null
+++ b/plugins/smartcard/gsd-smartcard-manager.c
@@ -0,0 +1,870 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
+ * Copyright (C) 2010,2011 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <gio/gio.h>
+
+#include "gnome-settings-plugin.h"
+#include "gnome-settings-profile.h"
+#include "gsd-smartcard-manager.h"
+#include "gsd-smartcard-service.h"
+#include "gsd-smartcard-enum-types.h"
+#include "gsd-smartcard-utils.h"
+
+#include <prerror.h>
+#include <prinit.h>
+#include <nss.h>
+#include <pk11func.h>
+#include <secmod.h>
+#include <secerr.h>
+
+#define GSD_SMARTCARD_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_SMARTCARD_MANAGER, GsdSmartcardManagerPrivate))
+
+struct GsdSmartcardManagerPrivate
+{
+        guint start_idle_id;
+        GsdSmartcardService *service;
+        GList *smartcards_watch_tasks;
+        GCancellable *cancellable;
+
+        GSettings *settings;
+
+        guint32 nss_is_loaded : 1;
+};
+
+#define CONF_SCHEMA "org.gnome.settings-daemon.peripherals.smartcard"
+
+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);
+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);
+
+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;
+        SECStatus status = SECSuccess;
+        static const guint32 flags = NSS_INIT_READONLY
+                                   | NSS_INIT_FORCEOPEN
+                                   | NSS_INIT_NOROOTINIT
+                                   | NSS_INIT_OPTIMIZESPACE
+                                   | NSS_INIT_PK11RELOAD;
+
+        g_debug ("attempting to load NSS database '%s'",
+                 GSD_SMARTCARD_MANAGER_NSS_DB);
+
+        PR_Init (PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
+
+        status = NSS_Initialize (GSD_SMARTCARD_MANAGER_NSS_DB,
+                                 "", "", SECMOD_DB, flags);
+
+        if (status != SECSuccess) {
+                gsize error_message_size;
+                char *error_message;
+
+                error_message_size = PR_GetErrorTextLength ();
+
+                if (error_message_size == 0) {
+                        g_debug ("NSS security system could not be initialized");
+                } else {
+                        error_message = g_alloca (error_message_size);
+                        PR_GetErrorText (error_message);
+
+                        g_debug ("NSS security system could not be initialized - %s",
+                                 error_message);
+                }
+                priv->nss_is_loaded = FALSE;
+                return;
+
+        }
+
+        g_debug ("NSS database '%s' loaded", GSD_SMARTCARD_MANAGER_NSS_DB);
+        priv->nss_is_loaded = TRUE;
+}
+
+static void
+unload_nss (GsdSmartcardManager *self)
+{
+        g_debug ("attempting to unload NSS security system with database '%s'",
+                 GSD_SMARTCARD_MANAGER_NSS_DB);
+
+        if (self->priv->nss_is_loaded) {
+                NSS_Shutdown ();
+                self->priv->nss_is_loaded = FALSE;
+                g_debug ("NSS database '%s' unloaded", GSD_SMARTCARD_MANAGER_NSS_DB);
+        } else {
+                g_debug ("NSS database '%s' already not loaded", GSD_SMARTCARD_MANAGER_NSS_DB);
+        }
+}
+
+typedef struct
+{
+        SECMODModule *driver;
+        GHashTable *smartcards;
+} WatchSmartcardsOperation;
+
+static void
+on_watch_cancelled (GCancellable             *cancellable,
+                    WatchSmartcardsOperation *operation)
+{
+        SECMOD_CancelWait (operation->driver);
+}
+
+static gboolean
+watch_one_event_from_driver (GsdSmartcardManager       *self,
+                             WatchSmartcardsOperation  *operation,
+                             GCancellable              *cancellable,
+                             GError                   **error)
+{
+        GsdSmartcardManagerPrivate *priv = self->priv;
+        PK11SlotInfo *card, *old_card;
+        CK_SLOT_ID slot_id;
+        gulong handler_id;
+        int old_slot_series = -1, slot_series;
+
+        handler_id = g_cancellable_connect (cancellable,
+                                            G_CALLBACK (on_watch_cancelled),
+                                            operation,
+                                            NULL);
+
+        card = SECMOD_WaitForAnyTokenEvent (operation->driver, 0, PR_SecondsToInterval (1));
+
+        g_cancellable_disconnect (cancellable, handler_id);
+
+        if (card == NULL) {
+                int error_code;
+
+                error_code = PORT_GetError ();
+
+                g_warning ("smartcard event function failed.");
+
+                g_set_error (error,
+                             GSD_SMARTCARD_MANAGER_ERROR,
+                             GSD_SMARTCARD_MANAGER_ERROR_WITH_NSS,
+                             "encountered unexpected error while "
+                             "waiting for smartcard events (error %d)",
+                             error_code);
+                return FALSE;
+        }
+
+        slot_id = PK11_GetSlotID (card);
+        slot_series = PK11_GetSlotSeries (card);
+
+        old_card = g_hash_table_lookup (operation->smartcards, GINT_TO_POINTER ((int) slot_id));
+
+        /* If there is a different card in the slot now than
+         * there was before, then we need to emit a removed signal
+         * for the old card
+         */
+        if (old_card != NULL) {
+                old_slot_series = PK11_GetSlotSeries (old_card);
+
+                if (old_slot_series != slot_series) {
+                        /* Card registered with slot previously is
+                         * different than this card, so update its
+                         * exported state to track the implicit missed
+                         * removal
+                         */
+                        gsd_smartcard_service_sync_token (priv->service, old_card, cancellable);
+                }
+
+                g_hash_table_remove (operation->smartcards, GINT_TO_POINTER ((int) slot_id));
+        }
+
+        if (PK11_IsPresent (card)) {
+                g_debug ("Detected smartcard insertion event in slot %d", (int) slot_id);
+
+                g_hash_table_replace (operation->smartcards,
+                                      GINT_TO_POINTER ((int) slot_id),
+                                      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
+                 * event for slots that are empty at startup
+                 */
+                g_debug ("Detected slot %d is empty in reader", (int) slot_id);
+        } else {
+                g_debug ("Detected smartcard removal event in slot %d", (int) slot_id);
+
+                /* If the just removed smartcard is known to us then
+                 * we need to update its exported state to reflect the
+                 * removal
+                 */
+                if (old_slot_series == slot_series)
+                        gsd_smartcard_service_sync_token (priv->service, card, cancellable);
+        }
+
+        PK11_FreeSlot (card);
+
+        return TRUE;
+}
+
+static void
+watch_smartcards_from_driver (GTask                    *task,
+                              GsdSmartcardManager      *self,
+                              WatchSmartcardsOperation *operation,
+                              GCancellable             *cancellable)
+{
+        g_debug ("watching for smartcard events");
+        while (!g_cancellable_is_cancelled (cancellable)) {
+                gboolean watch_succeeded;
+                GError *error = NULL;
+
+                watch_succeeded = watch_one_event_from_driver (self, operation, cancellable, &error);
+
+                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
+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);
+
+        g_task_run_in_thread (task, (GTaskThreadFunc) watch_smartcards_from_driver);
+
+        g_object_unref (task);
+}
+
+typedef struct
+{
+        guint driver_registered : 1;
+        guint smartcards_watched : 1;
+} ActivateDriverOperation;
+
+static void
+try_to_complete_driver_activation (GTask *task)
+{
+        ActivateDriverOperation *operation;
+
+        operation = g_task_get_task_data (task);
+
+        if (!operation->driver_registered)
+                return;
+
+        if (!operation->smartcards_watched)
+                return;
+
+        g_task_return_boolean (task, TRUE);
+}
+
+static gboolean
+register_driver_finish (GsdSmartcardManager  *self,
+                        GAsyncResult         *result,
+                        GError              **error)
+{
+        return gsd_smartcard_utils_finish_boolean_task (G_OBJECT (self), result, error);
+}
+
+static void
+on_driver_registered (GsdSmartcardManager *self,
+                      GAsyncResult        *result,
+                      GTask               *task)
+{
+        ActivateDriverOperation *operation;
+        GError *error = NULL;
+
+        if (!register_driver_finish (self, result, &error)) {
+                g_task_return_error (task, error);
+                g_object_unref (task);
+                return;
+        }
+
+        operation = g_task_get_task_data (task);
+        operation->driver_registered = TRUE;
+
+        try_to_complete_driver_activation (task);
+}
+
+static void
+on_smartcards_from_driver_watched (GsdSmartcardManager *self,
+                                   GAsyncResult        *result,
+                                   GTask               *task)
+{
+        ActivateDriverOperation *operation;
+
+        operation = g_task_get_task_data (task);
+        operation->smartcards_watched = TRUE;
+
+        try_to_complete_driver_activation (task);
+}
+
+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);
+        priv = self->priv;
+        operation = g_task_get_task_data (task);
+
+        gsd_smartcard_service_register_driver (priv->service,
+                                               operation->driver);
+
+        source = g_idle_source_new ();
+        g_task_attach_source (task,
+                              source,
+                              (GSourceFunc) on_task_thread_to_complete_driver_registration);
+        g_source_unref (source);
+
+        return G_SOURCE_REMOVE;
+}
+
+static void
+register_driver (GsdSmartcardManager *self,
+                 SECMODModule         *driver,
+                 GCancellable         *cancellable,
+                 GAsyncReadyCallback   callback,
+                 gpointer              user_data)
+{
+        GTask *task;
+        DriverRegistrationOperation *operation;
+
+        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);
+}
+
+static void
+activate_driver (GsdSmartcardManager *self,
+                 SECMODModule        *driver,
+                 GCancellable        *cancellable,
+                 GAsyncReadyCallback  callback,
+                 gpointer             user_data)
+{
+        ActivateDriverOperation *operation;
+        GTask *task;
+
+        g_debug ("Activating driver '%s'", driver->commonName);
+
+        task = g_task_new (self, cancellable, callback, user_data);
+        operation = g_new0 (ActivateDriverOperation, 1);
+        g_task_set_task_data (task, operation, (GDestroyNotify) g_free);
+
+        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 gsd_smartcard_utils_finish_boolean_task (G_OBJECT (self), 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_boolean (task, FALSE);
+
+        g_object_unref (task);
+}
+
+static void
+on_driver_activated (GsdSmartcardManager *self,
+                     GAsyncResult        *result,
+                     GTask               *task)
+{
+        GError *error = NULL;
+        gboolean driver_activated;
+        ActivateAllDriversOperation *operation;
+
+        driver_activated = activate_driver_async_finish (self, result, &error);
+
+        operation = g_task_get_task_data (task);
+
+        if (driver_activated)
+                operation->activated_drivers_count++;
+
+        operation->pending_drivers_count--;
+
+        try_to_complete_all_drivers_activation (task);
+}
+
+static void
+activate_all_drivers_async (GsdSmartcardManager *self,
+                            GCancellable        *cancellable,
+                            GAsyncReadyCallback  callback,
+                            gpointer             user_data)
+{
+        GTask *task;
+        SECMODListLock *lock;
+        SECMODModuleList *driver_list, *node;
+        ActivateAllDriversOperation *operation;
+
+        task = g_task_new (self, cancellable, callback, user_data);
+        operation = g_new0 (ActivateAllDriversOperation, 1);
+        g_task_set_task_data (task, operation, (GDestroyNotify) g_free);
+
+        lock = SECMOD_GetDefaultModuleListLock ();
+
+        g_assert (lock != NULL);
+
+        SECMOD_GetReadLock (lock);
+        driver_list = SECMOD_GetDefaultModuleList ();
+        for (node = driver_list; node != NULL; node = node->next) {
+                if (!node->module->loaded)
+                        continue;
+
+                if (!SECMOD_HasRemovableSlots (node->module))
+                        continue;
+
+                operation->pending_drivers_count++;
+
+                activate_driver (self, node->module,
+                                 cancellable,
+                                 (GAsyncReadyCallback) on_driver_activated,
+                                 task);
+
+        }
+        SECMOD_ReleaseReadLock (lock);
+}
+
+static gboolean
+activate_all_drivers_async_finish (GsdSmartcardManager  *self,
+                                   GAsyncResult         *result,
+                                   GError              **error)
+{
+        return gsd_smartcard_utils_finish_boolean_task (G_OBJECT (self), result, error);
+}
+
+static void
+on_all_drivers_activated (GsdSmartcardManager *self,
+                          GAsyncResult        *result,
+                          GTask               *task)
+{
+        GError *error = NULL;
+        gboolean driver_activated;
+
+        driver_activated = activate_all_drivers_async_finish (self, result, &error);
+
+        if (!driver_activated) {
+                g_task_return_error (task, error);
+                return;
+        }
+
+        g_task_return_boolean (task, TRUE);
+}
+
+static void
+watch_smartcards (GTask               *task,
+                  GsdSmartcardManager *self,
+                  gpointer             data,
+                  GCancellable        *cancellable)
+{
+        GMainContext *context;
+        GMainLoop *loop;
+
+        g_debug ("Getting list of suitable drivers");
+        context = g_main_context_new ();
+        g_main_context_push_thread_default (context);
+
+        activate_all_drivers_async (self,
+                                    cancellable,
+                                    (GAsyncReadyCallback) on_all_drivers_activated,
+                                    task);
+
+        loop = g_main_loop_new (context, FALSE);
+        g_main_loop_run (loop);
+        g_main_loop_unref (loop);
+
+        g_main_context_pop_thread_default (context);
+        g_main_context_unref (context);
+}
+
+static void
+watch_smartcards_async (GsdSmartcardManager *self,
+                        GCancellable        *cancellable,
+                        GAsyncReadyCallback  callback,
+                        gpointer             user_data)
+{
+        GTask *task;
+
+        task = g_task_new (self, cancellable, callback, user_data);
+
+        g_task_run_in_thread (task, (GTaskThreadFunc) watch_smartcards);
+
+        g_object_unref (task);
+}
+
+static gboolean
+watch_smartcards_async_finish (GsdSmartcardManager  *self,
+                               GAsyncResult         *result,
+                               GError              **error)
+{
+        return gsd_smartcard_utils_finish_boolean_task (G_OBJECT (self), result, error);
+}
+
+static void
+on_smartcards_watched (GsdSmartcardManager *self,
+                       GAsyncResult        *result)
+{
+        GError *error = NULL;
+
+        if (!watch_smartcards_async_finish (self, result, &error)) {
+                g_debug ("Error watching smartcards: %s", error->message);
+                g_error_free (error);
+        }
+}
+
+static void
+on_service_created (GObject             *source_object,
+                    GAsyncResult        *result,
+                    GsdSmartcardManager *self)
+{
+        GsdSmartcardManagerPrivate *priv = self->priv;
+        GsdSmartcardService *service;
+        GError *error = NULL;
+
+        service = gsd_smartcard_service_new_finish (result, &error);
+
+        if (service == NULL) {
+                g_warning("Couldn't create session bus service: %s", error->message);
+                g_error_free (error);
+                return;
+        }
+
+        priv->service = service;
+
+        watch_smartcards_async (self,
+                                priv->cancellable,
+                                (GAsyncReadyCallback) on_smartcards_watched,
+                                NULL);
+
+}
+
+static gboolean
+gsd_smartcard_manager_idle_cb (GsdSmartcardManager *self)
+{
+        GsdSmartcardManagerPrivate *priv = self->priv;
+
+        gnome_settings_profile_start (NULL);
+
+        priv->cancellable = g_cancellable_new();
+        priv->settings = g_settings_new (CONF_SCHEMA);
+
+        load_nss (self);
+
+        gsd_smartcard_service_new_async (self,
+                                         priv->cancellable,
+                                         (GAsyncReadyCallback) on_service_created,
+                                         self);
+
+        gnome_settings_profile_end (NULL);
+
+        priv->start_idle_id = 0;
+        return FALSE;
+}
+
+gboolean
+gsd_smartcard_manager_start (GsdSmartcardManager  *self,
+                             GError              **error)
+{
+        GsdSmartcardManagerPrivate *priv = self->priv;
+
+        gnome_settings_profile_start (NULL);
+
+        priv->start_idle_id = g_idle_add ((GSourceFunc) gsd_smartcard_manager_idle_cb, self);
+
+        gnome_settings_profile_end (NULL);
+
+        return TRUE;
+}
+
+void
+gsd_smartcard_manager_stop (GsdSmartcardManager *self)
+{
+        GsdSmartcardManagerPrivate *priv = self->priv;
+
+        g_debug ("Stopping smartcard manager");
+
+        unload_nss (self);
+
+        g_clear_object (&priv->settings);
+        g_clear_object (&priv->cancellable);
+}
+
+static PK11SlotInfo *
+get_login_token_for_operation (GsdSmartcardManager      *self,
+                               WatchSmartcardsOperation *operation)
+{
+        GHashTableIter iter;
+        gpointer key, value;
+
+        g_hash_table_iter_init (&iter, operation->smartcards);
+        while (g_hash_table_iter_next (&iter, &key, &value)) {
+                PK11SlotInfo *card_slot;
+                const char *token_name;
+
+                card_slot = (PK11SlotInfo *) value;
+                token_name = PK11_GetTokenName (card_slot);
+
+                if (g_strcmp0 (g_getenv ("PKCS11_LOGIN_TOKEN_NAME"), token_name) == 0)
+                        return card_slot;
+        }
+
+        return NULL;
+}
+
+PK11SlotInfo *
+gsd_smartcard_manager_get_login_token (GsdSmartcardManager *self)
+{
+        GsdSmartcardManagerPrivate *priv = self->priv;
+        GList *node;
+
+        G_LOCK (gsd_smartcards_watch_tasks);
+        node = priv->smartcards_watch_tasks;
+        while (node != NULL) {
+                PK11SlotInfo *card_slot;
+
+                GTask *task = node->data;
+                WatchSmartcardsOperation *operation = g_task_get_task_data (task);
+
+                card_slot = get_login_token_for_operation (self, operation);
+
+                if (card_slot != NULL)
+                        return card_slot;
+
+                node = node->next;
+        }
+        G_UNLOCK (gsd_smartcards_watch_tasks);
+
+        return NULL;
+}
+
+static GList *
+get_inserted_tokens_for_operation (GsdSmartcardManager      *self,
+                                   WatchSmartcardsOperation *operation)
+{
+        GList *inserted_tokens = NULL;
+        GHashTableIter iter;
+        gpointer key, value;
+
+        g_hash_table_iter_init (&iter, operation->smartcards);
+        while (g_hash_table_iter_next (&iter, &key, &value)) {
+                PK11SlotInfo *card_slot;
+
+                card_slot = (PK11SlotInfo *) value;
+
+                if (PK11_IsPresent (card_slot))
+                        inserted_tokens = g_list_prepend (inserted_tokens, card_slot);
+        }
+
+        return inserted_tokens;
+}
+
+GList *
+gsd_smartcard_manager_get_inserted_tokens (GsdSmartcardManager *self,
+                                           gsize               *num_tokens)
+{
+        GsdSmartcardManagerPrivate *priv = self->priv;
+        GList *inserted_tokens = NULL, *node;
+
+        G_LOCK (gsd_smartcards_watch_tasks);
+        for (node = priv->smartcards_watch_tasks; node != NULL; node = node->next) {
+                GTask *task = node->data;
+                WatchSmartcardsOperation *operation = g_task_get_task_data (task);
+                GList *operation_inserted_tokens;
+
+                operation_inserted_tokens = get_inserted_tokens_for_operation (self, operation);
+
+                inserted_tokens = g_list_concat (inserted_tokens, operation_inserted_tokens);
+        }
+        G_UNLOCK (gsd_smartcards_watch_tasks);
+
+        if (num_tokens != NULL)
+                *num_tokens = g_list_length (inserted_tokens);
+
+        return inserted_tokens;
+}
+
+static void
+gsd_smartcard_manager_finalize (GObject *object)
+{
+        GsdSmartcardManager *self;
+        GsdSmartcardManagerPrivate *priv;
+
+        g_return_if_fail (object != NULL);
+        g_return_if_fail (GSD_IS_SMARTCARD_MANAGER (object));
+
+        self = GSD_SMARTCARD_MANAGER (object);
+        priv = self->priv;
+
+        g_return_if_fail (self->priv != NULL);
+
+        if (priv->start_idle_id != 0)
+                g_source_remove (priv->start_idle_id);
+
+        gsd_smartcard_manager_stop (self);
+
+        G_OBJECT_CLASS (gsd_smartcard_manager_parent_class)->finalize (object);
+}
+
+GsdSmartcardManager *
+gsd_smartcard_manager_new (void)
+{
+        if (manager_object != NULL) {
+                g_object_ref (manager_object);
+        } else {
+                manager_object = g_object_new (GSD_TYPE_SMARTCARD_MANAGER, NULL);
+                g_object_add_weak_pointer (manager_object,
+                                           (gpointer *) &manager_object);
+        }
+
+        return GSD_SMARTCARD_MANAGER (manager_object);
+}
diff --git a/plugins/smartcard/gsd-smartcard-manager.h b/plugins/smartcard/gsd-smartcard-manager.h
new file mode 100644
index 0000000..9d3a2ce
--- /dev/null
+++ b/plugins/smartcard/gsd-smartcard-manager.h
@@ -0,0 +1,82 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
+ * Copyright (C) 2010 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef __GSD_SMARTCARD_MANAGER_H
+#define __GSD_SMARTCARD_MANAGER_H
+
+#include <glib-object.h>
+
+#include <prerror.h>
+#include <prinit.h>
+#include <nss.h>
+#include <pk11func.h>
+#include <secmod.h>
+#include <secerr.h>
+
+G_BEGIN_DECLS
+
+#define GSD_TYPE_SMARTCARD_MANAGER         (gsd_smartcard_manager_get_type ())
+#define GSD_SMARTCARD_MANAGER(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_SMARTCARD_MANAGER, GsdSmartcardManager))
+#define GSD_SMARTCARD_MANAGER_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), GSD_TYPE_SMARTCARD_MANAGER, GsdSmartcardManagerClass))
+#define GSD_IS_SMARTCARD_MANAGER(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_SMARTCARD_MANAGER))
+#define GSD_IS_SMARTCARD_MANAGER_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_SMARTCARD_MANAGER))
+#define GSD_SMARTCARD_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_SMARTCARD_MANAGER, GsdSmartcardManagerClass))
+#define GSD_SMARTCARD_MANAGER_ERROR        (gsd_smartcard_manager_error_quark ())
+
+typedef struct GsdSmartcardManagerPrivate GsdSmartcardManagerPrivate;
+
+typedef struct
+{
+        GObject                     parent;
+        GsdSmartcardManagerPrivate *priv;
+} GsdSmartcardManager;
+
+typedef struct
+{
+        GObjectClass   parent_class;
+} GsdSmartcardManagerClass;
+
+typedef enum
+{
+         GSD_SMARTCARD_MANAGER_ERROR_GENERIC = 0,
+         GSD_SMARTCARD_MANAGER_ERROR_WITH_NSS,
+         GSD_SMARTCARD_MANAGER_ERROR_LOADING_DRIVER,
+         GSD_SMARTCARD_MANAGER_ERROR_WATCHING_FOR_EVENTS,
+         GSD_SMARTCARD_MANAGER_ERROR_REPORTING_EVENTS,
+         GSD_SMARTCARD_MANAGER_ERROR_FINDING_SMARTCARD
+} GsdSmartcardManagerError;
+
+GType                   gsd_smartcard_manager_get_type    (void);
+GQuark                  gsd_smartcard_manager_error_quark (void);
+
+
+GsdSmartcardManager *   gsd_smartcard_manager_new         (void);
+gboolean                gsd_smartcard_manager_start       (GsdSmartcardManager  *manager,
+                                                           GError              **error);
+void                    gsd_smartcard_manager_stop        (GsdSmartcardManager  *manager);
+
+PK11SlotInfo *          gsd_smartcard_manager_get_login_token (GsdSmartcardManager *manager);
+GList *                 gsd_smartcard_manager_get_inserted_tokens (GsdSmartcardManager *manager,
+                                                                   gsize               *num_tokens);
+
+G_END_DECLS
+
+#endif /* __GSD_SMARTCARD_MANAGER_H */
diff --git a/plugins/smartcard/gsd-smartcard-plugin.c b/plugins/smartcard/gsd-smartcard-plugin.c
new file mode 100644
index 0000000..ea78f85
--- /dev/null
+++ b/plugins/smartcard/gsd-smartcard-plugin.c
@@ -0,0 +1,30 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
+ * Copyright (C) 2010 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <glib/gi18n-lib.h>
+#include <gmodule.h>
+
+#include "gnome-settings-plugin.h"
+#include "gsd-smartcard-manager.h"
+
+GNOME_SETTINGS_PLUGIN_REGISTER (GsdSmartcard, gsd_smartcard)
diff --git a/plugins/smartcard/gsd-smartcard-service.c b/plugins/smartcard/gsd-smartcard-service.c
new file mode 100644
index 0000000..40350d0
--- /dev/null
+++ b/plugins/smartcard/gsd-smartcard-service.c
@@ -0,0 +1,773 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2012 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Authors: Ray Strode
+ */
+
+#include "config.h"
+
+#include "gsd-smartcard-service.h"
+#include "org.gnome.SettingsDaemon.Smartcard.h"
+#include "gsd-smartcard-manager.h"
+#include "gsd-smartcard-enum-types.h"
+#include "gsd-smartcard-utils.h"
+
+#include "gnome-settings-plugin.h"
+
+#include <glib/gi18n.h>
+#include <glib/gstdio.h>
+#include <gio/gio.h>
+
+struct _GsdSmartcardServicePrivate
+{
+        GDBusConnection            *bus_connection;
+        GDBusObjectManagerServer   *object_manager_server;
+        GsdSmartcardManager        *smartcard_manager;
+        GCancellable               *cancellable;
+        GHashTable                 *tokens;
+
+        guint name_id;
+};
+
+#define GSD_SMARTCARD_DBUS_NAME GSD_DBUS_NAME ".Smartcard"
+#define GSD_SMARTCARD_DBUS_PATH GSD_DBUS_PATH "/Smartcard"
+#define GSD_SMARTCARD_MANAGER_DBUS_PATH GSD_SMARTCARD_DBUS_PATH "/Manager"
+#define GSD_SMARTCARD_MANAGER_DRIVERS_DBUS_PATH GSD_SMARTCARD_MANAGER_DBUS_PATH "/Drivers"
+#define GSD_SMARTCARD_MANAGER_TOKENS_DBUS_PATH  GSD_SMARTCARD_MANAGER_DBUS_PATH "/Tokens"
+
+enum {
+        PROP_0,
+        PROP_MANAGER,
+        PROP_BUS_CONNECTION
+};
+
+static void gsd_smartcard_service_set_property (GObject *object,
+                                                guint property_id,
+                                                const GValue *value,
+                                                GParamSpec *param_spec);
+static void gsd_smartcard_service_get_property (GObject *object,
+                                                guint property_id,
+                                                GValue *value,
+                                                GParamSpec *param_spec);
+static void async_initable_interface_init (GAsyncInitableIface *interface);
+static void smartcard_service_manager_interface_init (GsdSmartcardServiceManagerIface *interface);
+
+G_LOCK_DEFINE_STATIC (gsd_smartcard_tokens);
+
+G_DEFINE_TYPE_WITH_CODE (GsdSmartcardService,
+                         gsd_smartcard_service,
+                         GSD_SMARTCARD_SERVICE_TYPE_MANAGER_SKELETON,
+                         G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE,
+                                                async_initable_interface_init)
+                         G_IMPLEMENT_INTERFACE (GSD_SMARTCARD_SERVICE_TYPE_MANAGER,
+                                                smartcard_service_manager_interface_init));
+
+static void
+set_bus_connection (GsdSmartcardService  *self,
+                    GDBusConnection      *connection)
+{
+        GsdSmartcardServicePrivate *priv = self->priv;
+
+        if (priv->bus_connection != connection) {
+                g_clear_object (&priv->bus_connection);
+                priv->bus_connection = g_object_ref (connection);
+                g_object_notify (G_OBJECT (self), "bus-connection");
+        }
+}
+
+static void
+register_object_manager (GsdSmartcardService *self)
+{
+        GsdSmartcardServiceObjectSkeleton *object;
+
+        self->priv->object_manager_server = g_dbus_object_manager_server_new (GSD_SMARTCARD_DBUS_PATH);
+
+        object = gsd_smartcard_service_object_skeleton_new (GSD_SMARTCARD_MANAGER_DBUS_PATH);
+        gsd_smartcard_service_object_skeleton_set_manager (object,
+                                                           GSD_SMARTCARD_SERVICE_MANAGER (self));
+
+        g_dbus_object_manager_server_export (self->priv->object_manager_server,
+                                             G_DBUS_OBJECT_SKELETON (object));
+        g_object_unref (object);
+
+        g_dbus_object_manager_server_set_connection (self->priv->object_manager_server,
+                                                     self->priv->bus_connection);
+}
+
+static void
+on_bus_gotten (GObject      *source_object,
+               GAsyncResult *result,
+               GTask        *task)
+{
+        GsdSmartcardService *self;
+        GsdSmartcardServicePrivate *priv;
+        GDBusConnection *connection;
+        GError *error = NULL;
+
+        connection = g_bus_get_finish (result, &error);
+        if (connection == NULL) {
+                g_task_return_error (task, error);
+                goto out;
+        }
+
+        g_debug ("taking name %s on session bus", GSD_SMARTCARD_DBUS_NAME);
+
+        self = g_task_get_source_object (task);
+        priv = self->priv;
+
+        set_bus_connection (self, connection);
+
+        register_object_manager (self);
+        priv->name_id = g_bus_own_name_on_connection (connection,
+                                                      GSD_SMARTCARD_DBUS_NAME,
+                                                      G_BUS_NAME_OWNER_FLAGS_NONE,
+                                                      NULL,
+                                                      NULL,
+                                                      NULL,
+                                                      NULL);
+        g_task_return_boolean (task, TRUE);
+
+out:
+        g_object_unref (task);
+        return;
+}
+
+static gboolean
+gsd_smartcard_service_initable_init_finish (GAsyncInitable  *initable,
+                                            GAsyncResult    *result,
+                                            GError         **error)
+{
+        GTask *task;
+
+        task = G_TASK (result);
+
+        return g_task_propagate_boolean (task, error);
+}
+
+static void
+gsd_smartcard_service_initable_init_async (GAsyncInitable      *initable,
+                                           int                  io_priority,
+                                           GCancellable        *cancellable,
+                                           GAsyncReadyCallback  callback,
+                                           gpointer             user_data)
+{
+        GsdSmartcardService *self = GSD_SMARTCARD_SERVICE (initable);
+        GTask *task;
+
+        task = g_task_new (G_OBJECT (self), cancellable, callback, user_data);
+        g_task_set_priority (task, io_priority);
+
+        g_bus_get (G_BUS_TYPE_SESSION, cancellable, (GAsyncReadyCallback) on_bus_gotten, task);
+}
+
+static void
+async_initable_interface_init (GAsyncInitableIface *interface)
+{
+        interface->init_async = gsd_smartcard_service_initable_init_async;
+        interface->init_finish = gsd_smartcard_service_initable_init_finish;
+}
+
+static char *
+get_object_path_for_token (GsdSmartcardService *self,
+                           PK11SlotInfo        *card_slot)
+{
+        char *object_path;
+        char *escaped_library_path;
+        SECMODModule *driver;
+        CK_SLOT_ID slot_id;
+
+        driver = PK11_GetModule (card_slot);
+        slot_id = PK11_GetSlotID (card_slot);
+
+        escaped_library_path = gsd_smartcard_utils_escape_object_path (driver->dllName);
+
+        object_path = g_strdup_printf ("%s/token_from_%s_slot_%lu",
+                                       GSD_SMARTCARD_MANAGER_TOKENS_DBUS_PATH,
+                                       escaped_library_path,
+                                       (gulong) slot_id);
+        g_free (escaped_library_path);
+
+        return object_path;
+}
+
+static gboolean
+gsd_smartcard_service_handle_get_login_token (GsdSmartcardServiceManager *manager,
+                                              GDBusMethodInvocation      *invocation)
+{
+        GsdSmartcardService *self = GSD_SMARTCARD_SERVICE (manager);
+        GsdSmartcardServicePrivate *priv = self->priv;
+        PK11SlotInfo *card_slot;
+        char *object_path;
+
+        card_slot = gsd_smartcard_manager_get_login_token (priv->smartcard_manager);
+
+        if (card_slot == NULL) {
+                g_dbus_method_invocation_return_error (invocation,
+                                                       GSD_SMARTCARD_MANAGER_ERROR,
+                                                       GSD_SMARTCARD_MANAGER_ERROR_FINDING_SMARTCARD,
+                                                       _("User was not logged in with smartcard."));
+
+                return TRUE;
+        }
+
+        object_path = get_object_path_for_token (self, card_slot);
+        gsd_smartcard_service_manager_complete_get_login_token (manager,
+                                                                invocation,
+                                                                object_path);
+        g_free (object_path);
+
+        return TRUE;
+}
+
+static gboolean
+gsd_smartcard_service_handle_get_inserted_tokens (GsdSmartcardServiceManager *manager,
+                                                  GDBusMethodInvocation      *invocation)
+{
+        GsdSmartcardService *self = GSD_SMARTCARD_SERVICE (manager);
+        GsdSmartcardServicePrivate *priv = self->priv;
+        GList *inserted_tokens, *node;
+        GPtrArray *object_paths;
+
+        inserted_tokens = gsd_smartcard_manager_get_inserted_tokens (priv->smartcard_manager,
+                                                                     NULL);
+
+        object_paths = g_ptr_array_new ();
+        for (node = inserted_tokens; node != NULL; node = node->next) {
+                PK11SlotInfo *card_slot = node->data;
+                char *object_path;
+
+                object_path = get_object_path_for_token (self, card_slot);
+                g_ptr_array_add (object_paths, object_path);
+        }
+        g_ptr_array_add (object_paths, NULL);
+        g_list_free (inserted_tokens);
+
+        gsd_smartcard_service_manager_complete_get_inserted_tokens (manager,
+                                                                    invocation,
+                                                                    (const char * const *) object_paths->pdata);
+
+        g_ptr_array_free (object_paths, TRUE);
+
+        return TRUE;
+}
+
+static void
+smartcard_service_manager_interface_init (GsdSmartcardServiceManagerIface *interface)
+{
+        interface->handle_get_login_token = gsd_smartcard_service_handle_get_login_token;
+        interface->handle_get_inserted_tokens = gsd_smartcard_service_handle_get_inserted_tokens;
+}
+
+static void
+gsd_smartcard_service_init (GsdSmartcardService *self)
+{
+        self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
+                                                  GSD_TYPE_SMARTCARD_SERVICE,
+                                                  GsdSmartcardServicePrivate);
+        self->priv->tokens = g_hash_table_new_full (g_str_hash,
+                                                    g_str_equal,
+                                                    (GDestroyNotify) g_free,
+                                                    NULL);
+}
+
+static void
+gsd_smartcard_service_dispose (GObject *object)
+{
+        GsdSmartcardService *self = GSD_SMARTCARD_SERVICE (object);
+
+        g_clear_object (&self->priv->bus_connection);
+        g_clear_object (&self->priv->object_manager_server);
+        g_clear_object (&self->priv->smartcard_manager);
+
+        g_cancellable_cancel (self->priv->cancellable);
+        g_clear_object (&self->priv->cancellable);
+        g_clear_pointer (&self->priv->tokens, g_hash_table_unref);
+
+        G_OBJECT_CLASS (gsd_smartcard_service_parent_class)->dispose (object);
+}
+
+static void
+gsd_smartcard_service_set_property (GObject      *object,
+                                    guint         property_id,
+                                    const GValue *value,
+                                    GParamSpec   *param_spec)
+{
+        GsdSmartcardService *self = GSD_SMARTCARD_SERVICE (object);
+        GsdSmartcardServicePrivate *priv = self->priv;
+
+        switch (property_id) {
+                case PROP_MANAGER:
+                        priv->smartcard_manager = g_value_dup_object (value);
+                        break;
+                default:
+                        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, param_spec);
+                        break;
+        }
+}
+
+static void
+gsd_smartcard_service_get_property (GObject    *object,
+                                    guint       property_id,
+                                    GValue     *value,
+                                    GParamSpec *param_spec)
+{
+        GsdSmartcardService *self = GSD_SMARTCARD_SERVICE (object);
+        GsdSmartcardServicePrivate *priv = self->priv;
+
+        switch (property_id) {
+                case PROP_MANAGER:
+                        g_value_set_object (value, priv->smartcard_manager);
+                        break;
+                case PROP_BUS_CONNECTION:
+                        g_value_set_object (value, priv->bus_connection);
+                        break;
+                default:
+                        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, param_spec);
+                        break;
+        }
+}
+
+static void
+gsd_smartcard_service_class_init (GsdSmartcardServiceClass *service_class)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (service_class);
+        GParamSpec *param_spec;
+
+        object_class->dispose = gsd_smartcard_service_dispose;
+        object_class->set_property = gsd_smartcard_service_set_property;
+        object_class->get_property = gsd_smartcard_service_get_property;
+
+        param_spec = g_param_spec_object ("manager",
+                                          "Smartcard Manager",
+                                          "Smartcard Manager",
+                                          GSD_TYPE_SMARTCARD_MANAGER,
+                                          G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
+        g_object_class_install_property (object_class, PROP_MANAGER, param_spec);
+        param_spec = g_param_spec_object ("bus-connection",
+                                          "Bus Connection",
+                                          "bus connection",
+                                          G_TYPE_DBUS_CONNECTION,
+                                          G_PARAM_READABLE);
+        g_object_class_install_property (object_class, PROP_BUS_CONNECTION, param_spec);
+
+        g_type_class_add_private (service_class, sizeof (GsdSmartcardServicePrivate));
+}
+
+static void
+on_new_async_finished (GObject      *source_object,
+                       GAsyncResult *result,
+                       GTask        *task)
+{
+        GError *error = NULL;
+        GObject *object;
+
+        object = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object),
+                                              result,
+                                              &error);
+
+        if (object == NULL) {
+                g_task_return_error (task, error);
+                goto out;
+        }
+
+        g_assert (GSD_IS_SMARTCARD_SERVICE (object));
+
+        g_task_return_pointer (task, object, g_object_unref);
+out:
+        g_object_unref (task);
+        return;
+}
+
+void
+gsd_smartcard_service_new_async (GsdSmartcardManager *manager,
+                                 GCancellable        *cancellable,
+                                 GAsyncReadyCallback  callback,
+                                 gpointer             user_data)
+{
+        GTask *task;
+
+        task = g_task_new (NULL, cancellable, callback, user_data);
+
+        g_async_initable_new_async (GSD_TYPE_SMARTCARD_SERVICE,
+                                    G_PRIORITY_DEFAULT,
+                                    cancellable,
+                                    (GAsyncReadyCallback) on_new_async_finished,
+                                    task,
+                                    "manager", manager,
+                                    NULL);
+}
+
+GsdSmartcardService *
+gsd_smartcard_service_new_finish (GAsyncResult  *result,
+                                  GError       **error)
+{
+        GTask *task;
+        GsdSmartcardService *self = NULL;
+
+        task = G_TASK (result);
+
+        self = g_task_propagate_pointer (task, error);
+
+        if (self == NULL)
+                return self;
+
+        return g_object_ref (self);
+}
+
+static char *
+get_object_path_for_driver (GsdSmartcardService *self,
+                            SECMODModule        *driver)
+{
+        char *object_path;
+        char *escaped_library_path;
+
+        escaped_library_path = gsd_smartcard_utils_escape_object_path (driver->dllName);
+
+        object_path = g_build_path ("/",
+                                    GSD_SMARTCARD_MANAGER_DRIVERS_DBUS_PATH,
+                                    escaped_library_path, NULL);
+        g_free (escaped_library_path);
+
+        return object_path;
+}
+
+void
+gsd_smartcard_service_register_driver (GsdSmartcardService  *self,
+                                       SECMODModule         *driver)
+{
+        char *object_path;
+        GDBusObjectSkeleton *object;
+        GDBusInterfaceSkeleton *interface;
+
+        object_path = get_object_path_for_driver (self, driver);
+        object = G_DBUS_OBJECT_SKELETON (gsd_smartcard_service_object_skeleton_new (object_path));
+        g_free (object_path);
+
+        interface = G_DBUS_INTERFACE_SKELETON (gsd_smartcard_service_driver_skeleton_new ());
+        g_dbus_object_skeleton_add_interface (object, interface);
+        g_object_unref (interface);
+
+        g_object_set (G_OBJECT (interface),
+                      "library", driver->dllName,
+                      "description", driver->commonName,
+                      NULL);
+        g_dbus_object_manager_server_export (self->priv->object_manager_server,
+                                             object);
+        g_object_unref (object);
+}
+
+static void
+synchronize_token_now (GsdSmartcardService *self,
+                       PK11SlotInfo        *card_slot)
+{
+        GsdSmartcardServicePrivate *priv = self->priv;
+        GDBusInterfaceSkeleton *interface;
+        char *object_path;
+        const char *token_name;
+        gboolean is_present, is_login_card;
+
+        object_path = get_object_path_for_token (self, card_slot);
+
+        G_LOCK (gsd_smartcard_tokens);
+        interface = g_hash_table_lookup (priv->tokens, object_path);
+        g_free (object_path);
+
+        if (interface == NULL)
+                goto out;
+
+        token_name = PK11_GetTokenName (card_slot);
+        is_present = PK11_IsPresent (card_slot);
+
+        if (g_strcmp0 (g_getenv ("PKCS11_LOGIN_TOKEN_NAME"), token_name) == 0)
+                is_login_card = TRUE;
+        else
+                is_login_card = FALSE;
+
+        g_debug ("===============================");
+        g_debug (" Token '%s'", token_name);
+        g_debug (" Inserted: %s", is_present? "yes" : "no");
+        g_debug (" Previously used to login: %s", is_login_card? "yes" : "no");
+        g_debug ("===============================\n");
+
+        g_object_set (G_OBJECT (interface),
+                      "used-to-login", is_login_card,
+                      "is-inserted", is_present,
+                      NULL);
+        g_object_get (G_OBJECT (interface),
+                      "used-to-login", &is_login_card,
+                      "is-inserted", &is_present,
+                      NULL);
+
+out:
+        G_UNLOCK (gsd_smartcard_tokens);
+}
+
+typedef struct
+{
+        PK11SlotInfo *card_slot;
+        char         *object_path;
+        GSource      *main_thread_source;
+} RegisterNewTokenOperation;
+
+static void
+destroy_register_new_token_operation (RegisterNewTokenOperation *operation)
+{
+        g_clear_pointer (&operation->main_thread_source,
+                         (GDestroyNotify) g_source_destroy);
+        PK11_FreeSlot (operation->card_slot);
+        g_free (operation->object_path);
+        g_free (operation);
+}
+
+static gboolean
+on_main_thread_to_register_new_token (GTask *task)
+{
+        GsdSmartcardService *self;
+        GsdSmartcardServicePrivate *priv;
+        GDBusObjectSkeleton *object;
+        GDBusInterfaceSkeleton *interface;
+        RegisterNewTokenOperation *operation;
+        SECMODModule *driver;
+        char *driver_object_path;
+        const char *token_name;
+
+        self = g_task_get_source_object (task);
+        priv = self->priv;
+
+        operation = g_task_get_task_data (task);
+        operation->main_thread_source = NULL;
+
+        object = G_DBUS_OBJECT_SKELETON (gsd_smartcard_service_object_skeleton_new (operation->object_path));
+        interface = G_DBUS_INTERFACE_SKELETON (gsd_smartcard_service_token_skeleton_new ());
+
+        g_dbus_object_skeleton_add_interface (object, interface);
+        g_object_unref (interface);
+
+        driver = PK11_GetModule (operation->card_slot);
+        driver_object_path = get_object_path_for_driver (self, driver);
+
+        token_name = PK11_GetTokenName (operation->card_slot);
+
+        g_object_set (G_OBJECT (interface),
+                      "driver", driver_object_path,
+                      "name", token_name,
+                      NULL);
+        g_free (driver_object_path);
+
+        g_dbus_object_manager_server_export (self->priv->object_manager_server,
+                                             object);
+
+        G_LOCK (gsd_smartcard_tokens);
+        g_hash_table_insert (priv->tokens, g_strdup (operation->object_path), interface);
+        G_UNLOCK (gsd_smartcard_tokens);
+
+        g_task_return_boolean (task, TRUE);
+
+        return G_SOURCE_REMOVE;
+}
+
+static void
+create_main_thread_source (GSourceFunc   callback,
+                           gpointer      user_data,
+                           GSource     **source_out)
+{
+        GSource *source;
+
+        source = g_idle_source_new ();
+        g_source_set_callback (source, callback, user_data, NULL);
+
+        *source_out = source;
+        g_source_attach (source, NULL);
+        g_source_unref (source);
+}
+
+static void
+register_new_token_in_main_thread (GsdSmartcardService *self,
+                                   PK11SlotInfo        *card_slot,
+                                   char                *object_path,
+                                   GCancellable        *cancellable,
+                                   GAsyncReadyCallback  callback,
+                                   gpointer             user_data)
+{
+        RegisterNewTokenOperation *operation;
+        GTask *task;
+
+        operation = g_new0 (RegisterNewTokenOperation, 1);
+        operation->card_slot = PK11_ReferenceSlot (card_slot);
+        operation->object_path = g_strdup (object_path);
+
+        task = g_task_new (self, cancellable, callback, user_data);
+
+        g_task_set_task_data (task,
+                              operation,
+                              (GDestroyNotify) destroy_register_new_token_operation);
+
+        create_main_thread_source ((GSourceFunc) on_main_thread_to_register_new_token,
+                                   task,
+                                   &operation->main_thread_source);
+}
+
+static gboolean
+register_new_token_in_main_thread_finish (GsdSmartcardService  *self,
+                                          GAsyncResult         *result,
+                                          GError              **error)
+{
+        return gsd_smartcard_utils_finish_boolean_task (G_OBJECT (self), result, error);
+}
+
+static void
+on_token_registered (GsdSmartcardService *self,
+                     GAsyncResult        *result,
+                     PK11SlotInfo        *card_slot)
+{
+        gboolean registered;
+        GError *error = NULL;
+
+        registered = register_new_token_in_main_thread_finish (self, result, &error);
+
+        if (!registered) {
+                g_debug ("Couldn't register token: %s",
+                         error->message);
+                goto out;
+        }
+
+        synchronize_token_now (self, card_slot);
+
+out:
+        PK11_FreeSlot (card_slot);
+}
+
+typedef struct
+{
+        PK11SlotInfo *card_slot;
+        GSource      *main_thread_source;
+} SynchronizeTokenOperation;
+
+static void
+destroy_synchronize_token_operation (SynchronizeTokenOperation *operation)
+{
+        g_clear_pointer (&operation->main_thread_source,
+                         (GDestroyNotify)
+                         g_source_destroy);
+        PK11_FreeSlot (operation->card_slot);
+        g_free (operation);
+}
+
+static gboolean
+on_main_thread_to_synchronize_token (GTask *task)
+{
+        GsdSmartcardService *self;
+        SynchronizeTokenOperation *operation;
+
+        self = g_task_get_source_object (task);
+
+        operation = g_task_get_task_data (task);
+        operation->main_thread_source = NULL;
+
+        synchronize_token_now (self, operation->card_slot);
+
+        g_task_return_boolean (task, TRUE);
+
+        return G_SOURCE_REMOVE;
+}
+
+static gboolean
+synchronize_token_in_main_thread_finish (GsdSmartcardService  *self,
+                                         GAsyncResult         *result,
+                                         GError              **error)
+{
+        return gsd_smartcard_utils_finish_boolean_task (G_OBJECT (self), result, error);
+}
+
+static void
+synchronize_token_in_main_thread (GsdSmartcardService *self,
+                                  PK11SlotInfo        *card_slot,
+                                  GCancellable        *cancellable,
+                                  GAsyncReadyCallback  callback,
+                                  gpointer             user_data)
+{
+        SynchronizeTokenOperation *operation;
+        GTask *task;
+
+        operation = g_new0 (SynchronizeTokenOperation, 1);
+        operation->card_slot = PK11_ReferenceSlot (card_slot);
+
+        task = g_task_new (self, cancellable, callback, user_data);
+
+        g_task_set_task_data (task,
+                              operation,
+                              (GDestroyNotify)
+                              destroy_synchronize_token_operation);
+
+        create_main_thread_source ((GSourceFunc)
+                                   on_main_thread_to_synchronize_token,
+                                   task,
+                                   &operation->main_thread_source);
+}
+
+static void
+on_token_synchronized (GsdSmartcardService *self,
+                       GAsyncResult        *result,
+                       PK11SlotInfo        *card_slot)
+{
+        gboolean synchronized;
+        GError *error = NULL;
+
+        synchronized = synchronize_token_in_main_thread_finish (self, result, &error);
+
+        if (!synchronized)
+                g_debug ("Couldn't synchronize token: %s", error->message);
+
+        PK11_FreeSlot (card_slot);
+}
+
+void
+gsd_smartcard_service_sync_token (GsdSmartcardService *self,
+                                  PK11SlotInfo        *card_slot,
+                                  GCancellable        *cancellable)
+{
+        GsdSmartcardServicePrivate *priv = self->priv;
+        char *object_path;
+        GDBusInterfaceSkeleton *interface;
+
+        object_path = get_object_path_for_token (self, card_slot);
+
+        G_LOCK (gsd_smartcard_tokens);
+        interface = g_hash_table_lookup (priv->tokens, object_path);
+        G_UNLOCK (gsd_smartcard_tokens);
+
+        if (interface == NULL)
+                register_new_token_in_main_thread (self,
+                                                   card_slot,
+                                                   object_path,
+                                                   cancellable,
+                                                   (GAsyncReadyCallback)
+                                                   on_token_registered,
+                                                   PK11_ReferenceSlot (card_slot));
+
+        else
+                synchronize_token_in_main_thread (self,
+                                                  card_slot,
+                                                  cancellable,
+                                                  (GAsyncReadyCallback)
+                                                  on_token_synchronized,
+                                                  PK11_ReferenceSlot (card_slot));
+
+        g_free (object_path);
+}
diff --git a/plugins/smartcard/gsd-smartcard-service.h b/plugins/smartcard/gsd-smartcard-service.h
new file mode 100644
index 0000000..2e48001
--- /dev/null
+++ b/plugins/smartcard/gsd-smartcard-service.h
@@ -0,0 +1,81 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2012 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Authors: Ray Strode
+ */
+
+#ifndef __GSD_SMARTCARD_SERVICE_H__
+#define __GSD_SMARTCARD_SERVICE_H__
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gio/gio.h>
+#include "gsd-smartcard-manager.h"
+
+#include "org.gnome.SettingsDaemon.Smartcard.h"
+
+#include <prerror.h>
+#include <prinit.h>
+#include <nss.h>
+#include <pk11func.h>
+#include <secmod.h>
+#include <secerr.h>
+
+G_BEGIN_DECLS
+
+#define GSD_TYPE_SMARTCARD_SERVICE (gsd_smartcard_service_get_type ())
+#define GSD_SMARTCARD_SERVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST (obj, GSD_TYPE_SMARTCARD_SERVICE, GsdSmartcardService))
+#define GSD_SMARTCARD_SERVICE_CLASS(cls) (G_TYPE_CHECK_CLASS_CAST (cls, GSD_TYPE_SMARTCARD_SERVICE, GsdSmartcardServiceClass))
+#define GSD_IS_SMARTCARD_SERVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE (obj, GSD_TYPE_SMARTCARD_SERVICE))
+#define GSD_IS_SMARTCARD_SERVICE_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE (obj, GSD_TYPE_SMARTCARD_SERVICE))
+#define GSD_SMARTCARD_SERVICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GSD_TYPE_SMARTCARD_SERVICE, GsdSmartcardServiceClass))
+
+typedef struct _GsdSmartcardService GsdSmartcardService;
+typedef struct _GsdSmartcardServiceClass GsdSmartcardServiceClass;
+typedef struct _GsdSmartcardServicePrivate GsdSmartcardServicePrivate;
+
+struct _GsdSmartcardService
+{
+        GsdSmartcardServiceManagerSkeleton parent_instance;
+        GsdSmartcardServicePrivate *priv;
+};
+
+struct _GsdSmartcardServiceClass
+{
+        GsdSmartcardServiceManagerSkeletonClass parent_class;
+};
+
+GType gsd_smartcard_service_get_type (void);
+void  gsd_smartcard_service_new_async (GsdSmartcardManager  *manager,
+                                       GCancellable         *cancellable,
+                                       GAsyncReadyCallback   callback,
+                                       gpointer              user_data);
+GsdSmartcardService *gsd_smartcard_service_new_finish (GAsyncResult         *result,
+                                                       GError              **error);
+
+void  gsd_smartcard_service_register_driver (GsdSmartcardService  *service,
+                                             SECMODModule         *driver);
+void  gsd_smartcard_service_sync_token (GsdSmartcardService  *service,
+                                        PK11SlotInfo         *slot_info,
+                                        GCancellable         *cancellable);
+
+
+G_END_DECLS
+
+#endif /* __GSD_SMARTCARD_SERVICE_H__ */
diff --git a/plugins/smartcard/gsd-smartcard-utils.c b/plugins/smartcard/gsd-smartcard-utils.c
new file mode 100644
index 0000000..a2511a5
--- /dev/null
+++ b/plugins/smartcard/gsd-smartcard-utils.c
@@ -0,0 +1,191 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2013 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "config.h"
+#include "gsd-smartcard-utils.h"
+
+#include <string.h>
+
+#include <glib.h>
+#include <gio/gio.h>
+
+static char *
+dashed_string_to_studly_caps (const char *dashed_string)
+{
+        char *studly_string;
+        size_t studly_string_length;
+        size_t i;
+
+        i = 0;
+
+        studly_string = g_strdup (dashed_string);
+        studly_string_length = strlen (studly_string);
+
+        studly_string[i] = g_ascii_toupper (studly_string[i]);
+        i++;
+
+        while (i < studly_string_length) {
+                if (studly_string[i] == '-' || studly_string[i] == '_') {
+                        memmove (studly_string + i,
+                                 studly_string + i + 1,
+                                 studly_string_length - i - 1);
+                        studly_string_length--;
+                        if (g_ascii_isalpha (studly_string[i])) {
+                                studly_string[i] = g_ascii_toupper (studly_string[i]);
+                        }
+                }
+                i++;
+        }
+        studly_string[studly_string_length] = '\0';
+
+        return studly_string;
+}
+
+static char *
+dashed_string_to_dbus_error_string (const char *dashed_string,
+                                    const char *old_prefix,
+                                    const char *new_prefix,
+                                    const char *suffix)
+{
+        char *studly_suffix;
+        char *dbus_error_string;
+        size_t dbus_error_string_length;
+        size_t i;
+
+        i = 0;
+
+        if (g_str_has_prefix (dashed_string, old_prefix) &&
+            (dashed_string[strlen(old_prefix)] == '-' ||
+             dashed_string[strlen(old_prefix)] == '_')) {
+                dashed_string += strlen (old_prefix) + 1;
+        }
+
+        studly_suffix = dashed_string_to_studly_caps (suffix);
+        dbus_error_string = g_strdup_printf ("%s.%s.%s", new_prefix, dashed_string, studly_suffix);
+        g_free (studly_suffix);
+        i += strlen (new_prefix) + 1;
+
+        dbus_error_string_length = strlen (dbus_error_string);
+
+        dbus_error_string[i] = g_ascii_toupper (dbus_error_string[i]);
+        i++;
+
+        while (i < dbus_error_string_length) {
+                if (dbus_error_string[i] == '_' || dbus_error_string[i] == '-') {
+                        dbus_error_string[i] = '.';
+
+                        if (g_ascii_isalpha (dbus_error_string[i + 1])) {
+                                dbus_error_string[i + 1] = g_ascii_toupper (dbus_error_string[i + 1]);
+                        }
+                }
+
+                i++;
+        }
+
+        return dbus_error_string;
+}
+
+void
+gsd_smartcard_utils_register_error_domain (GQuark error_domain,
+                                           GType  error_enum)
+{
+        const char *error_domain_string;
+        char *type_name;
+        GType type;
+        GTypeClass *type_class;
+        GEnumClass *enum_class;
+        guint i;
+
+        error_domain_string = g_quark_to_string (error_domain);
+        type_name = dashed_string_to_studly_caps (error_domain_string);
+        type = g_type_from_name (type_name);
+        type_class = g_type_class_ref (type);
+        enum_class = G_ENUM_CLASS (type_class);
+
+        for (i = 0; i < enum_class->n_values; i++) {
+                char *dbus_error_string;
+
+                dbus_error_string = dashed_string_to_dbus_error_string (error_domain_string,
+                                                                        "gsd",
+                                                                        "org.gnome.SettingsDaemon",
+                                                                        enum_class->values[i].value_nick);
+
+                g_debug ("%s: Registering dbus error %s", type_name, dbus_error_string);
+                g_dbus_error_register_error (error_domain,
+                                             enum_class->values[i].value,
+                                             dbus_error_string);
+                g_free (dbus_error_string);
+        }
+
+        g_type_class_unref (type_class);
+}
+
+char *
+gsd_smartcard_utils_escape_object_path (const char *unescaped_string)
+{
+  const char *p;
+  char *object_path;
+  GString *string;
+
+  g_return_val_if_fail (unescaped_string != NULL, NULL);
+
+  string = g_string_new ("");
+
+  for (p = unescaped_string; *p != '\0'; p++)
+    {
+      guchar character;
+
+      character = (guchar) * p;
+
+      if (((character >= ((guchar) 'a')) &&
+           (character <= ((guchar) 'z'))) ||
+          ((character >= ((guchar) 'A')) &&
+           (character <= ((guchar) 'Z'))) ||
+          ((character >= ((guchar) '0')) && (character <= ((guchar) '9'))))
+        {
+          g_string_append_c (string, (char) character);
+          continue;
+        }
+
+      g_string_append_printf (string, "_%x_", character);
+    }
+
+  object_path = string->str;
+
+  g_string_free (string, FALSE);
+
+  return object_path;
+}
+
+gboolean
+gsd_smartcard_utils_finish_boolean_task (GObject       *object,
+                                         GAsyncResult  *result,
+                                         GError       **error)
+{
+        gboolean return_value;
+
+        g_return_val_if_fail (g_task_is_valid (result, object), FALSE);
+
+        return_value = g_task_propagate_boolean (G_TASK (result), error);
+
+        g_object_unref (G_OBJECT (result));
+
+        return return_value;
+}
diff --git a/plugins/smartcard/gsd-smartcard-utils.h b/plugins/smartcard/gsd-smartcard-utils.h
new file mode 100644
index 0000000..c39b076
--- /dev/null
+++ b/plugins/smartcard/gsd-smartcard-utils.h
@@ -0,0 +1,38 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2013 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef __GSD_SMARTCARD_UTILS_H
+#define __GSD_SMARTCARD_UTILS_H
+
+#include <glib-object.h>
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+void             gsd_smartcard_utils_register_error_domain             (GQuark error_domain,
+                                                                        GType error_enum);
+char *           gsd_smartcard_utils_escape_object_path                (const char *unescaped_string);
+
+gboolean         gsd_smartcard_utils_finish_boolean_task               (GObject       *object,
+                                                                        GAsyncResult  *result,
+                                                                        GError       **error);
+
+G_END_DECLS
+
+#endif /* __GSD_SMARTCARD_MANAGER_H */
diff --git a/plugins/smartcard/org.gnome.SettingsDaemon.Smartcard.xml b/plugins/smartcard/org.gnome.SettingsDaemon.Smartcard.xml
new file mode 100644
index 0000000..3daade9
--- /dev/null
+++ b/plugins/smartcard/org.gnome.SettingsDaemon.Smartcard.xml
@@ -0,0 +1,91 @@
+<!DOCTYPE node PUBLIC
+        "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
+        "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+
+<!--
+        Copyright (C) 2013 Red Hat, Inc.
+
+        This library is free software; you can redistribute it and/or
+        modify it under the terms of the GNU Lesser General Public
+        License as published by the Free Software Foundation; either
+        version 2 of the License, or (at your option) any later version.
+
+        This library is distributed in the hope that it will be useful,
+        but WITHOUT ANY WARRANTY; without even the implied warranty of
+        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+        Lesser General Public License for more details.
+
+        You should have received a copy of the GNU Lesser General
+        Public License along with this library; if not, write to the
+        Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+        Boston, MA 02111-1307, USA.
+
+        Author: Ray Strode <rstrode@redhat.com>
+-->
+
+<node name="/" xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd">
+        <!--
+        org.gnome.SettingsDaemon.Smartcard.Manager:
+
+        An interface used for managing smartcard functionality.
+        -->
+        <interface name="org.gnome.SettingsDaemon.Smartcard.Manager">
+                <method name="GetLoginToken">
+                        <arg name="token" type="o" direction="out"/>
+                </method>
+
+                <method name="GetInsertedTokens">
+                        <arg name="tokens" type="ao" direction="out"/>
+                </method>
+        </interface>
+
+        <!--
+        org.gnome.SettingsDaemon.Smartcard.Driver:
+
+        The smartcard driver interface.
+        -->
+        <interface name="org.gnome.SettingsDaemon.Smartcard.Driver">
+                <!--
+                Library:
+                Path to PKCS11 module
+                -->
+                <property name="Library" type="s" access="read"/>
+
+                <!--
+                Description:
+                String describing the PKCS11 module
+                -->
+                <property name="Description" type="s" access="read"/>
+        </interface>
+
+        <!--
+        org.gnome.SettingsDaemon.Smartcard.Token:
+
+        The smartcard interface.
+        -->
+        <interface name="org.gnome.SettingsDaemon.Smartcard.Token">
+                <!--
+                Name:
+                Name of the token
+                -->
+                <property name="Name" type="s" access="read"/>
+
+                <!--
+                Driver:
+                Driver handling token
+                -->
+                <property name="Driver" type="o" access="read"/>
+
+                <!--
+                IsInserted:
+                Whether or not the card is inserted
+                -->
+                <property name="IsInserted" type="b" access="read"/>
+
+                <!--
+                UsedToLogin:
+                Whether or not the card was used to log in
+                -->
+                <property name="UsedToLogin" type="b" access="read"/>
+        </interface>
+</node>
diff --git a/plugins/smartcard/test-smartcard.c b/plugins/smartcard/test-smartcard.c
new file mode 100644
index 0000000..b5ee3d5
--- /dev/null
+++ b/plugins/smartcard/test-smartcard.c
@@ -0,0 +1,7 @@
+#define NEW gsd_smartcard_manager_new
+#define START gsd_smartcard_manager_start
+#define STOP gsd_smartcard_manager_stop
+#define MANAGER GsdSmartcardManager
+#include "gsd-smartcard-manager.h"
+
+#include "test-plugin.h"
-- 
1.8.3.1


From 7ad29294bcc95806b36bee3639c51901f44f8fc8 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Sat, 27 Jul 2013 10:35:55 -0400
Subject: [PATCH 3/11] Revert "build: Disable smartcard plugin for now"

This reverts commit e2998b46a9d5eaa9ec2812867efac1eff8b3937f.

Now that smartcard plugin is freshly revamped we can revert
the commit that disables it.

https://bugzilla.gnome.org/show_bug.cgi?id=704890
---
 configure.ac | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/configure.ac b/configure.ac
index d7a9ead..c8a35f0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -278,64 +278,63 @@ AC_ARG_ENABLE(packagekit,
                yes) WANT_PACKAGEKIT=yes ;;
                no)  WANT_PACKAGEKIT=no ;;
                *) AC_MSG_ERROR(bad value ${enableval} for --disable-packagekit) ;;
        esac],
        [WANT_PACKAGEKIT=yes]) dnl Default value
 
 if test x$WANT_PACKAGEKIT = xyes ; then
        PK_REQUIRED_VERSION=0.7.4
        PKG_CHECK_MODULES(PACKAGEKIT, glib-2.0 packagekit-glib2 >= $PK_REQUIRED_VERSION upower-glib >= $UPOWER_REQUIRED_VERSION gudev-1.0 libnotify >= $LIBNOTIFY_REQUIRED_VERSION,
              [have_packagekit=true
               AC_DEFINE(HAVE_PACKAGEKIT, 1, [Define if PackageKit should be used])],
              [have_packagekit=false])
 fi
 AM_CONDITIONAL(HAVE_PACKAGEKIT, test "x$have_packagekit" = "xtrue")
 
 AC_SUBST(PACKAGEKIT_CFLAGS)
 AC_SUBST(PACKAGEKIT_LIBS)
 
 dnl ==============================================
 dnl smartcard section
 dnl ==============================================
 have_smartcard_support=false
 AC_ARG_ENABLE(smartcard-support,
   AC_HELP_STRING([--disable-smartcard-support],
                  [turn off smartcard support]),
        [case "${enableval}" in
                yes) WANT_SMARTCARD_SUPPORT=yes ;;
                no)  WANT_SMARTCARD_SUPPORT=no ;;
                *) AC_MSG_ERROR(bad value ${enableval} for --disable-smartcard-support) ;;
        esac],
-       [WANT_SMARTCARD_SUPPORT=no])
+       [WANT_SMARTCARD_SUPPORT=yes])
 
 if test x$WANT_SMARTCARD_SUPPORT = xyes ; then
-       AC_MSG_ERROR(Smartcard support is broken in this version)
        NSS_REQUIRED_VERSION=3.11.2
        PKG_CHECK_MODULES(NSS, nss >= $NSS_REQUIRED_VERSION,
              [have_smartcard_support=true
               AC_DEFINE(SMARTCARD_SUPPORT, 1, [Define if smartcard support should be enabled])],
              [have_smartcard_support=false])
 fi
 AM_CONDITIONAL(SMARTCARD_SUPPORT, test "x$have_smartcard_support" = "xtrue")
 
 AC_SUBST(NSS_CFLAGS)
 AC_SUBST(NSS_LIBS)
 
 AC_ARG_WITH(nssdb,
   AC_HELP_STRING([--with-nssdb],
                  [where system NSS database is]))
 
 NSS_DATABASE=""
 if test "x$have_smartcard_support" = "xtrue"; then
         if ! test -z "$with_nssdb" ; then
                 NSS_DATABASE="$with_nssdb"
         else
                 NSS_DATABASE="${sysconfdir}/pki/nssdb"
         fi
 else
         if ! test -z "$with_nssdb" ; then
                 AC_MSG_WARN([nssdb specified when smartcard support is disabled])
         fi
 fi
 
 AC_SUBST(NSS_DATABASE)
 
-- 
1.8.3.1


From 667d9edf568556d9e840245ceed1a3723e8d352c Mon Sep 17 00:00:00 2001
From: Colin Walters <walters@verbum.org>
Date: Sat, 27 Jul 2013 13:46:29 -0400
Subject: [PATCH 4/11] build: Fix smartcard plugin with srcdir != builddir

---
 plugins/smartcard/Makefile.am | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/plugins/smartcard/Makefile.am b/plugins/smartcard/Makefile.am
index 2d27d1c..3ba5abd 100644
--- a/plugins/smartcard/Makefile.am
+++ b/plugins/smartcard/Makefile.am
@@ -1,49 +1,49 @@
 plugin_name = smartcard
 libsmartcard_headers = gsd-smartcard-manager.h \
 		       gsd-smartcard-utils.h
 dbus_built_sources = org.gnome.SettingsDaemon.Smartcard.c org.gnome.SettingsDaemon.Smartcard.h
 enum_built_sources = gsd-smartcard-enum-types.h gsd-smartcard-enum-types.c
 BUILT_SOURCES = $(dbus_built_sources) $(enum_built_sources)
 
 libexec_PROGRAMS = gsd-test-smartcard
 
 plugin_LTLIBRARIES = \
 	libsmartcard.la
 
 $(dbus_built_sources) : Makefile.am org.gnome.SettingsDaemon.Smartcard.xml
 	$(AM_V_GEN) gdbus-codegen \
 	--interface-prefix org.gnome.SettingsDaemon.Smartcard. \
 	--c-namespace GsdSmartcardService \
 	--c-generate-object-manager \
 	--generate-c-code org.gnome.SettingsDaemon.Smartcard \
-	org.gnome.SettingsDaemon.Smartcard.xml
+	$(srcdir)/org.gnome.SettingsDaemon.Smartcard.xml
 
 gsd-smartcard-enum-types.h: gsd-smartcard-enum-types.h.in $(libsmartcard_headers)
 	$(AM_V_GEN) $(GLIB_MKENUMS) --template $^ > $@
 
 gsd-smartcard-enum-types.c: gsd-smartcard-enum-types.c.in $(libsmartcard_headers)
 	$(AM_V_GEN) $(GLIB_MKENUMS) --template $^ > $@
 
 gsd_test_smartcard_SOURCES =        \
 	$(dbus_built_sources)   \
 	$(enum_built_sources)   \
 	gsd-smartcard-service.c \
 	gsd-smartcard-manager.c \
 	gsd-smartcard-utils.c   \
 	test-smartcard.c
 
 gsd_test_smartcard_CPPFLAGS =                                   \
 	-I$(top_srcdir)/data/                                   \
 	-I$(top_srcdir)/gnome-settings-daemon                   \
 	-I$(top_srcdir)/plugins/common                          \
 	-DSYSCONFDIR=\""$(sysconfdir)"\"                        \
 	-DLIBDIR=\""$(libdir)"\"                                \
 	-DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\"      \
 	-DGSD_SMARTCARD_MANAGER_NSS_DB=\""$(NSS_DATABASE)"\"    \
 	$(AM_CPPFLAGS)
 
 gsd_test_smartcard_CFLAGS =                                     \
 	 $(PLUGIN_CFLAGS)                                       \
 	 $(SETTINGS_PLUGIN_CFLAGS)                              \
 	 $(MEDIA_KEYS_CFLAGS)                                   \
 	 $(NSS_CFLAGS)                                          \
-- 
1.8.3.1


From bbf3aa7fbc268fff449d4cf0c2f3ee7f9bf791c0 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Sun, 28 Jul 2013 23:54:59 -0400
Subject: [PATCH 5/11] smartcard: fix driver activation notification

g-s-d fails to notice when it's finished loading all
the smartcard drivers. This is because the code was
waiting for the driver worker threads to finish instead
of to start (and also a fault >= instead > 0 check for
pending drivers)

The commit fixes that.
---
 plugins/smartcard/gsd-smartcard-manager.c | 40 +++----------------------------
 1 file changed, 3 insertions(+), 37 deletions(-)

diff --git a/plugins/smartcard/gsd-smartcard-manager.c b/plugins/smartcard/gsd-smartcard-manager.c
index 05f77f8..14c2f71 100644
--- a/plugins/smartcard/gsd-smartcard-manager.c
+++ b/plugins/smartcard/gsd-smartcard-manager.c
@@ -294,121 +294,90 @@ watch_smartcards_from_driver_async (GsdSmartcardManager *self,
         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);
 
         g_task_run_in_thread (task, (GTaskThreadFunc) watch_smartcards_from_driver);
 
         g_object_unref (task);
 }
 
-typedef struct
-{
-        guint driver_registered : 1;
-        guint smartcards_watched : 1;
-} ActivateDriverOperation;
-
-static void
-try_to_complete_driver_activation (GTask *task)
-{
-        ActivateDriverOperation *operation;
-
-        operation = g_task_get_task_data (task);
-
-        if (!operation->driver_registered)
-                return;
-
-        if (!operation->smartcards_watched)
-                return;
-
-        g_task_return_boolean (task, TRUE);
-}
-
 static gboolean
 register_driver_finish (GsdSmartcardManager  *self,
                         GAsyncResult         *result,
                         GError              **error)
 {
         return gsd_smartcard_utils_finish_boolean_task (G_OBJECT (self), result, error);
 }
 
 static void
 on_driver_registered (GsdSmartcardManager *self,
                       GAsyncResult        *result,
                       GTask               *task)
 {
-        ActivateDriverOperation *operation;
         GError *error = NULL;
 
         if (!register_driver_finish (self, result, &error)) {
                 g_task_return_error (task, error);
                 g_object_unref (task);
                 return;
         }
 
-        operation = g_task_get_task_data (task);
-        operation->driver_registered = TRUE;
-
-        try_to_complete_driver_activation (task);
+        g_task_return_boolean (task, TRUE);
 }
 
 static void
 on_smartcards_from_driver_watched (GsdSmartcardManager *self,
                                    GAsyncResult        *result,
                                    GTask               *task)
 {
-        ActivateDriverOperation *operation;
-
-        operation = g_task_get_task_data (task);
-        operation->smartcards_watched = TRUE;
-
-        try_to_complete_driver_activation (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
@@ -435,103 +404,100 @@ on_main_thread_to_register_driver (GTask *task)
         return G_SOURCE_REMOVE;
 }
 
 static void
 register_driver (GsdSmartcardManager *self,
                  SECMODModule         *driver,
                  GCancellable         *cancellable,
                  GAsyncReadyCallback   callback,
                  gpointer              user_data)
 {
         GTask *task;
         DriverRegistrationOperation *operation;
 
         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);
 }
 
 static void
 activate_driver (GsdSmartcardManager *self,
                  SECMODModule        *driver,
                  GCancellable        *cancellable,
                  GAsyncReadyCallback  callback,
                  gpointer             user_data)
 {
-        ActivateDriverOperation *operation;
         GTask *task;
 
         g_debug ("Activating driver '%s'", driver->commonName);
 
         task = g_task_new (self, cancellable, callback, user_data);
-        operation = g_new0 (ActivateDriverOperation, 1);
-        g_task_set_task_data (task, operation, (GDestroyNotify) g_free);
 
         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 gsd_smartcard_utils_finish_boolean_task (G_OBJECT (self), 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)
+        if (operation->pending_drivers_count > 0)
                 return;
 
         if (operation->activated_drivers_count > 0)
                 g_task_return_boolean (task, TRUE);
         else
                 g_task_return_boolean (task, FALSE);
 
         g_object_unref (task);
 }
 
 static void
 on_driver_activated (GsdSmartcardManager *self,
                      GAsyncResult        *result,
                      GTask               *task)
 {
         GError *error = NULL;
         gboolean driver_activated;
         ActivateAllDriversOperation *operation;
 
         driver_activated = activate_driver_async_finish (self, result, &error);
 
         operation = g_task_get_task_data (task);
 
         if (driver_activated)
                 operation->activated_drivers_count++;
 
         operation->pending_drivers_count--;
 
         try_to_complete_all_drivers_activation (task);
 }
-- 
1.8.3.1


From 94f03e52bd1863d16e1df9a4a5634235f7532dff Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Sun, 28 Jul 2013 22:19:18 -0400
Subject: [PATCH 6/11] smartcard: add screensaver proxy

We're going to need to be able to lock the screen in some
cases when a user removes their smartcard.

This commit adds the goo needed to get access to the lock
screen.
---
 plugins/smartcard/Makefile.am               | 14 ++++++++-
 plugins/smartcard/org.gnome.ScreenSaver.xml | 45 +++++++++++++++++++++++++++++
 2 files changed, 58 insertions(+), 1 deletion(-)
 create mode 100644 plugins/smartcard/org.gnome.ScreenSaver.xml

diff --git a/plugins/smartcard/Makefile.am b/plugins/smartcard/Makefile.am
index 3ba5abd..62f85e7 100644
--- a/plugins/smartcard/Makefile.am
+++ b/plugins/smartcard/Makefile.am
@@ -1,92 +1,104 @@
 plugin_name = smartcard
 libsmartcard_headers = gsd-smartcard-manager.h \
 		       gsd-smartcard-utils.h
 dbus_built_sources = org.gnome.SettingsDaemon.Smartcard.c org.gnome.SettingsDaemon.Smartcard.h
+screensaver_dbus_built_sources = org.gnome.ScreenSaver.c org.gnome.ScreenSaver.h
 enum_built_sources = gsd-smartcard-enum-types.h gsd-smartcard-enum-types.c
-BUILT_SOURCES = $(dbus_built_sources) $(enum_built_sources)
+BUILT_SOURCES = $(dbus_built_sources) $(screensaver_dbus_built_sources) $(enum_built_sourcs)
 
 libexec_PROGRAMS = gsd-test-smartcard
 
 plugin_LTLIBRARIES = \
 	libsmartcard.la
 
 $(dbus_built_sources) : Makefile.am org.gnome.SettingsDaemon.Smartcard.xml
 	$(AM_V_GEN) gdbus-codegen \
 	--interface-prefix org.gnome.SettingsDaemon.Smartcard. \
 	--c-namespace GsdSmartcardService \
 	--c-generate-object-manager \
 	--generate-c-code org.gnome.SettingsDaemon.Smartcard \
 	$(srcdir)/org.gnome.SettingsDaemon.Smartcard.xml
 
+$(screensaver_dbus_built_sources) : Makefile.am org.gnome.ScreenSaver.xml
+	gdbus-codegen						\
+		--interface-prefix org.gnome.ScreenSaver.	\
+		--generate-c-code org.gnome.ScreenSaver		\
+		--c-namespace Gsd				\
+		--annotate "org.gnome.ScreenSaver"		\
+		           "org.gtk.GDBus.C.Name" ScreenSaver	\
+		$(srcdir)/org.gnome.ScreenSaver.xml
+
 gsd-smartcard-enum-types.h: gsd-smartcard-enum-types.h.in $(libsmartcard_headers)
 	$(AM_V_GEN) $(GLIB_MKENUMS) --template $^ > $@
 
 gsd-smartcard-enum-types.c: gsd-smartcard-enum-types.c.in $(libsmartcard_headers)
 	$(AM_V_GEN) $(GLIB_MKENUMS) --template $^ > $@
 
 gsd_test_smartcard_SOURCES =        \
 	$(dbus_built_sources)   \
+	$(screensaver_dbus_built_sources) \
 	$(enum_built_sources)   \
 	gsd-smartcard-service.c \
 	gsd-smartcard-manager.c \
 	gsd-smartcard-utils.c   \
 	test-smartcard.c
 
 gsd_test_smartcard_CPPFLAGS =                                   \
 	-I$(top_srcdir)/data/                                   \
 	-I$(top_srcdir)/gnome-settings-daemon                   \
 	-I$(top_srcdir)/plugins/common                          \
 	-DSYSCONFDIR=\""$(sysconfdir)"\"                        \
 	-DLIBDIR=\""$(libdir)"\"                                \
 	-DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\"      \
 	-DGSD_SMARTCARD_MANAGER_NSS_DB=\""$(NSS_DATABASE)"\"    \
 	$(AM_CPPFLAGS)
 
 gsd_test_smartcard_CFLAGS =                                     \
 	 $(PLUGIN_CFLAGS)                                       \
 	 $(SETTINGS_PLUGIN_CFLAGS)                              \
 	 $(MEDIA_KEYS_CFLAGS)                                   \
 	 $(NSS_CFLAGS)                                          \
 	 $(AM_CFLAGS)
 
 gsd_test_smartcard_LDADD =                                      \
 	$(top_builddir)/gnome-settings-daemon/libgsd.la         \
 	$(top_builddir)/plugins/common/libcommon.la             \
 	$(NSS_LIBS)                                             \
 	$(SETTINGS_DAEMON_LIBS)                                 \
 	$(SETTINGS_PLUGIN_LIBS)
 
 
 libsmartcard_la_SOURCES = \
 	$(libsmartcard_headers) \
 	$(dbus_built_sources) \
+	$(screensaver_dbus_built_sources) \
 	$(enum_built_sources) \
 	gsd-smartcard-manager.c \
 	gsd-smartcard-plugin.c  \
 	gsd-smartcard-service.c \
 	gsd-smartcard-utils.c
 
 libsmartcard_la_CPPFLAGS = \
 	-I$(top_srcdir)/gnome-settings-daemon \
 	-DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \
 	-I$(top_srcdir)/plugins/common \
 	-DSYSCONFDIR=\""$(sysconfdir)"\" \
 	-DLIBDIR=\""$(libdir)"\" \
 	-DGSD_SMARTCARD_MANAGER_NSS_DB=\""$(NSS_DATABASE)"\" \
 	$(AM_CPPFLAGS)
 
 libsmartcard_la_CFLAGS = \
 	$(PLUGIN_CFLAGS)        \
 	$(SETTINGS_PLUGIN_CFLAGS) \
 	$(NSS_CFLAGS)        \
 	$(AM_CFLAGS)
 
 libsmartcard_la_LDFLAGS = \
 	$(GSD_PLUGIN_LDFLAGS)
 
 libsmartcard_la_LIBADD = \
 	$(SETTINGS_PLUGIN_LIBS)        \
 	$(NSS_LIBS)
 
 @GSD_INTLTOOL_PLUGIN_RULE@
 
diff --git a/plugins/smartcard/org.gnome.ScreenSaver.xml b/plugins/smartcard/org.gnome.ScreenSaver.xml
new file mode 100644
index 0000000..7a6cf86
--- /dev/null
+++ b/plugins/smartcard/org.gnome.ScreenSaver.xml
@@ -0,0 +1,45 @@
+<!DOCTYPE node PUBLIC
+        "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
+        "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+
+<!--
+        Copyright (C) 2013 Red Hat, Inc.
+
+        This library is free software; you can redistribute it and/or
+        modify it under the terms of the GNU Lesser General Public
+        License as published by the Free Software Foundation; either
+        version 2 of the License, or (at your option) any later version.
+
+        This library is distributed in the hope that it will be useful,
+        but WITHOUT ANY WARRANTY; without even the implied warranty of
+        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+        Lesser General Public License for more details.
+
+        You should have received a copy of the GNU Lesser General
+        Public License along with this library; if not, write to the
+        Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+        Boston, MA 02111-1307, USA.
+-->
+
+<node name="/" xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd">
+        <!--
+        org.gnome.ScreenSaver:
+
+        An interface used for managing the lock screen.
+        -->
+        <interface name="org.gnome.ScreenSaver">
+                <method name="Lock" />
+                <method name="GetActive">
+                        <arg name="active" direction="out" type="b" />
+                </method>
+                <method name="SetActive">
+                        <arg name="value" direction="in" type="b" />
+                </method>
+                <method name="GetActiveTime">
+                        <arg name="value" direction="out" type="u" />
+                </method>
+                <signal name="ActiveChanged">
+                        <arg name="new_value" type="b" />
+                </signal>
+        </interface>
+</node>
-- 
1.8.3.1


From 6ac958091b6f2742bcc504f29b716028fe0cb37b Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Sun, 28 Jul 2013 22:19:18 -0400
Subject: [PATCH 7/11] smartcard: add session manager proxy

We're going to need to be able to log the user out in some
cases when they remove their smartcard.

This commit adds the makefile goo and the xml file stolen from
gnome-session source tree to get access to the session
manager to log out.
---
 plugins/smartcard/Makefile.am                  |  14 +-
 plugins/smartcard/org.gnome.SessionManager.xml | 451 +++++++++++++++++++++++++
 2 files changed, 464 insertions(+), 1 deletion(-)
 create mode 100644 plugins/smartcard/org.gnome.SessionManager.xml

diff --git a/plugins/smartcard/Makefile.am b/plugins/smartcard/Makefile.am
index 62f85e7..098bb47 100644
--- a/plugins/smartcard/Makefile.am
+++ b/plugins/smartcard/Makefile.am
@@ -1,104 +1,116 @@
 plugin_name = smartcard
 libsmartcard_headers = gsd-smartcard-manager.h \
 		       gsd-smartcard-utils.h
 dbus_built_sources = org.gnome.SettingsDaemon.Smartcard.c org.gnome.SettingsDaemon.Smartcard.h
 screensaver_dbus_built_sources = org.gnome.ScreenSaver.c org.gnome.ScreenSaver.h
+session_manager_dbus_built_sources = org.gnome.SessionManager.c org.gnome.SessionManager.h
 enum_built_sources = gsd-smartcard-enum-types.h gsd-smartcard-enum-types.c
-BUILT_SOURCES = $(dbus_built_sources) $(screensaver_dbus_built_sources) $(enum_built_sourcs)
+BUILT_SOURCES = $(dbus_built_sources) $(screensaver_dbus_built_sources) $(session_manager_dbus_built_sources) $(enum_built_sources)
 
 libexec_PROGRAMS = gsd-test-smartcard
 
 plugin_LTLIBRARIES = \
 	libsmartcard.la
 
 $(dbus_built_sources) : Makefile.am org.gnome.SettingsDaemon.Smartcard.xml
 	$(AM_V_GEN) gdbus-codegen \
 	--interface-prefix org.gnome.SettingsDaemon.Smartcard. \
 	--c-namespace GsdSmartcardService \
 	--c-generate-object-manager \
 	--generate-c-code org.gnome.SettingsDaemon.Smartcard \
 	$(srcdir)/org.gnome.SettingsDaemon.Smartcard.xml
 
 $(screensaver_dbus_built_sources) : Makefile.am org.gnome.ScreenSaver.xml
 	gdbus-codegen						\
 		--interface-prefix org.gnome.ScreenSaver.	\
 		--generate-c-code org.gnome.ScreenSaver		\
 		--c-namespace Gsd				\
 		--annotate "org.gnome.ScreenSaver"		\
 		           "org.gtk.GDBus.C.Name" ScreenSaver	\
 		$(srcdir)/org.gnome.ScreenSaver.xml
 
+$(session_manager_dbus_built_sources) : Makefile.am org.gnome.SessionManager.xml
+	gdbus-codegen						\
+		--interface-prefix org.gnome.SessionManager.	\
+		--generate-c-code org.gnome.SessionManager	\
+		--c-namespace Gsd				\
+		--annotate "org.gnome.SessionManager"		\
+		           "org.gtk.GDBus.C.Name" SessionManager	\
+		$(srcdir)/org.gnome.SessionManager.xml
+
 gsd-smartcard-enum-types.h: gsd-smartcard-enum-types.h.in $(libsmartcard_headers)
 	$(AM_V_GEN) $(GLIB_MKENUMS) --template $^ > $@
 
 gsd-smartcard-enum-types.c: gsd-smartcard-enum-types.c.in $(libsmartcard_headers)
 	$(AM_V_GEN) $(GLIB_MKENUMS) --template $^ > $@
 
 gsd_test_smartcard_SOURCES =        \
 	$(dbus_built_sources)   \
 	$(screensaver_dbus_built_sources) \
+	$(session_manager_dbus_built_sources) \
 	$(enum_built_sources)   \
 	gsd-smartcard-service.c \
 	gsd-smartcard-manager.c \
 	gsd-smartcard-utils.c   \
 	test-smartcard.c
 
 gsd_test_smartcard_CPPFLAGS =                                   \
 	-I$(top_srcdir)/data/                                   \
 	-I$(top_srcdir)/gnome-settings-daemon                   \
 	-I$(top_srcdir)/plugins/common                          \
 	-DSYSCONFDIR=\""$(sysconfdir)"\"                        \
 	-DLIBDIR=\""$(libdir)"\"                                \
 	-DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\"      \
 	-DGSD_SMARTCARD_MANAGER_NSS_DB=\""$(NSS_DATABASE)"\"    \
 	$(AM_CPPFLAGS)
 
 gsd_test_smartcard_CFLAGS =                                     \
 	 $(PLUGIN_CFLAGS)                                       \
 	 $(SETTINGS_PLUGIN_CFLAGS)                              \
 	 $(MEDIA_KEYS_CFLAGS)                                   \
 	 $(NSS_CFLAGS)                                          \
 	 $(AM_CFLAGS)
 
 gsd_test_smartcard_LDADD =                                      \
 	$(top_builddir)/gnome-settings-daemon/libgsd.la         \
 	$(top_builddir)/plugins/common/libcommon.la             \
 	$(NSS_LIBS)                                             \
 	$(SETTINGS_DAEMON_LIBS)                                 \
 	$(SETTINGS_PLUGIN_LIBS)
 
 
 libsmartcard_la_SOURCES = \
 	$(libsmartcard_headers) \
 	$(dbus_built_sources) \
 	$(screensaver_dbus_built_sources) \
+	$(session_manager_dbus_built_sources) \
 	$(enum_built_sources) \
 	gsd-smartcard-manager.c \
 	gsd-smartcard-plugin.c  \
 	gsd-smartcard-service.c \
 	gsd-smartcard-utils.c
 
 libsmartcard_la_CPPFLAGS = \
 	-I$(top_srcdir)/gnome-settings-daemon \
 	-DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \
 	-I$(top_srcdir)/plugins/common \
 	-DSYSCONFDIR=\""$(sysconfdir)"\" \
 	-DLIBDIR=\""$(libdir)"\" \
 	-DGSD_SMARTCARD_MANAGER_NSS_DB=\""$(NSS_DATABASE)"\" \
 	$(AM_CPPFLAGS)
 
 libsmartcard_la_CFLAGS = \
 	$(PLUGIN_CFLAGS)        \
 	$(SETTINGS_PLUGIN_CFLAGS) \
 	$(NSS_CFLAGS)        \
 	$(AM_CFLAGS)
 
 libsmartcard_la_LDFLAGS = \
 	$(GSD_PLUGIN_LDFLAGS)
 
 libsmartcard_la_LIBADD = \
 	$(SETTINGS_PLUGIN_LIBS)        \
 	$(NSS_LIBS)
 
 @GSD_INTLTOOL_PLUGIN_RULE@
 
diff --git a/plugins/smartcard/org.gnome.SessionManager.xml b/plugins/smartcard/org.gnome.SessionManager.xml
new file mode 100644
index 0000000..eb69180
--- /dev/null
+++ b/plugins/smartcard/org.gnome.SessionManager.xml
@@ -0,0 +1,451 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+<node xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd">
+  <interface name="org.gnome.SessionManager">
+
+    <!-- Initialization phase interfaces -->
+
+    <method name="Setenv">
+      <arg name="variable" type="s" direction="in">
+        <doc:doc>
+          <doc:summary>The variable name</doc:summary>
+        </doc:doc>
+      </arg>
+      <arg name="value" type="s" direction="in">
+        <doc:doc>
+          <doc:summary>The value</doc:summary>
+        </doc:doc>
+      </arg>
+      <doc:doc>
+        <doc:description>
+          <doc:para>Adds the variable name to the application launch environment with the specified value.  May only be used during the Session Manager initialization phase.</doc:para>
+        </doc:description>
+      </doc:doc>
+    </method>
+
+    <method name="GetLocale">
+      <arg name="category" type="i" direction="in">
+        <doc:doc>
+          <doc:summary>The locale category</doc:summary>
+        </doc:doc>
+      </arg>
+      <arg name="value" type="s" direction="out">
+        <doc:doc>
+          <doc:summary>The value</doc:summary>
+        </doc:doc>
+      </arg>
+      <doc:doc>
+        <doc:description>
+          <doc:para>Reads the current state of the specific locale category.</doc:para>
+        </doc:description>
+      </doc:doc>
+    </method>
+
+    <method name="InitializationError">
+      <arg name="message" type="s" direction="in">
+        <doc:doc>
+          <doc:summary>The error message</doc:summary>
+        </doc:doc>
+      </arg>
+      <arg name="fatal" type="b" direction="in">
+        <doc:doc>
+          <doc:summary>Whether the error should be treated as fatal</doc:summary>
+        </doc:doc>
+      </arg>
+      <doc:doc>
+        <doc:description>
+          <doc:para>May be used by applications launched during the Session Manager initialization phase to indicate there was a problem.</doc:para>
+        </doc:description>
+      </doc:doc>
+    </method>
+
+    <!-- Running phase interfaces -->
+
+    <method name="RegisterClient">
+      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+      <arg type="s" name="app_id" direction="in">
+        <doc:doc>
+          <doc:summary>The application identifier</doc:summary>
+        </doc:doc>
+      </arg>
+      <arg type="s" name="client_startup_id" direction="in">
+        <doc:doc>
+          <doc:summary>Client startup identifier</doc:summary>
+        </doc:doc>
+      </arg>
+      <arg type="o" name="client_id" direction="out">
+        <doc:doc>
+          <doc:summary>The object path of the newly registered client</doc:summary>
+        </doc:doc>
+      </arg>
+      <doc:doc>
+        <doc:description>
+          <doc:para>Register the caller as a Session Management client.</doc:para>
+        </doc:description>
+      </doc:doc>
+    </method>
+
+    <method name="UnregisterClient">
+      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+      <arg type="o" name="client_id" direction="in">
+        <doc:doc>
+          <doc:summary>The object path of the client</doc:summary>
+        </doc:doc>
+      </arg>
+      <doc:doc>
+        <doc:description>
+          <doc:para>Unregister the specified client from Session Management.</doc:para>
+        </doc:description>
+      </doc:doc>
+    </method>
+
+    <method name="Inhibit">
+      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+      <arg type="s" name="app_id" direction="in">
+        <doc:doc>
+          <doc:summary>The application identifier</doc:summary>
+        </doc:doc>
+      </arg>
+      <arg type="u" name="toplevel_xid" direction="in">
+        <doc:doc>
+          <doc:summary>The toplevel X window identifier</doc:summary>
+        </doc:doc>
+      </arg>
+      <arg type="s" name="reason" direction="in">
+        <doc:doc>
+          <doc:summary>The reason for the inhibit</doc:summary>
+        </doc:doc>
+      </arg>
+      <arg type="u" name="flags" direction="in">
+        <doc:doc>
+          <doc:summary>Flags that specify what should be inhibited</doc:summary>
+        </doc:doc>
+      </arg>
+      <arg type="u" name="inhibit_cookie" direction="out">
+        <doc:doc>
+          <doc:summary>The cookie</doc:summary>
+        </doc:doc>
+      </arg>
+      <doc:doc>
+        <doc:summary>
+          Proactively indicates that the calling application is performing an action that should not be interrupted and sets a reason to be displayed to the user when an interruption is about to take placea.
+        </doc:summary>
+        <doc:description>
+          <doc:para>Applications should invoke this method when they begin an operation that
+            should not be interrupted, such as creating a CD or DVD.  The types of actions
+            that may be blocked are specified by the flags parameter.  When the application
+            completes the operation it should call <doc:ref type="method" to="org.gnome.SessionManager.Uninhibit">Uninhibit()</doc:ref>
+            or disconnect from the session bus.
+          </doc:para>
+          <doc:para>
+            Applications should not expect that they will always be able to block the
+            action.  In most cases, users will be given the option to force the action
+            to take place.
+          </doc:para>
+          <doc:para>
+            Reasons should be short and to the point.
+          </doc:para>
+          <doc:para>
+            The flags parameter must include at least one of the following:
+            <doc:list>
+              <doc:item>
+                <doc:term>1</doc:term>
+                <doc:definition>Inhibit logging out</doc:definition>
+              </doc:item>
+              <doc:item>
+                <doc:term>2</doc:term>
+                <doc:definition>Inhibit user switching</doc:definition>
+              </doc:item>
+              <doc:item>
+                <doc:term>4</doc:term>
+                <doc:definition>Inhibit suspending the session or computer</doc:definition>
+              </doc:item>
+              <doc:item>
+                <doc:term>8</doc:term>
+                <doc:definition>Inhibit the session being marked as idle</doc:definition>
+              </doc:item>
+              <doc:item>
+                <doc:term>16</doc:term>
+                <doc:definition>Inhibit auto-mounting removable media for the session</doc:definition>
+              </doc:item>
+            </doc:list>
+            Values for flags may be bitwise or'ed together.
+          </doc:para>
+          <doc:para>
+            The returned cookie is used to uniquely identify this request.  It should be used
+            as an argument to <doc:ref type="method" to="org.gnome.SessionManager.Uninhibit">Uninhibit()</doc:ref> in
+            order to remove the request.
+          </doc:para>
+        </doc:description>
+      </doc:doc>
+    </method>
+
+    <method name="Uninhibit">
+      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+      <arg type="u" name="inhibit_cookie" direction="in">
+        <doc:doc>
+          <doc:summary>The cookie</doc:summary>
+        </doc:doc>
+      </arg>
+      <doc:doc>
+        <doc:description>
+          <doc:para>Cancel a previous call to <doc:ref type="method" to="org.gnome.SessionManager.Inhibit">Inhibit()</doc:ref> identified by the cookie.</doc:para>
+        </doc:description>
+      </doc:doc>
+    </method>
+
+    <method name="IsInhibited">
+      <arg type="u" name="flags" direction="in">
+        <doc:doc>
+          <doc:summary>Flags that spefify what should be inhibited</doc:summary>
+        </doc:doc>
+      </arg>
+      <arg type="b" name="is_inhibited" direction="out">
+        <doc:doc>
+          <doc:summary>Returns TRUE if any of the operations in the bitfield flags are inhibited</doc:summary>
+        </doc:doc>
+      </arg>
+      <doc:doc>
+        <doc:description>
+          <doc:para>Determine if operation(s) specified by the flags
+            are currently inhibited.  Flags are same as those accepted
+            by the
+            <doc:ref type="method" to="org.gnome.SessionManager.Inhibit">Inhibit()</doc:ref>
+            method.</doc:para>
+        </doc:description>
+      </doc:doc>
+    </method>
+
+    <method name="GetClients">
+      <arg name="clients" direction="out" type="ao">
+        <doc:doc>
+          <doc:summary>an array of client IDs</doc:summary>
+        </doc:doc>
+      </arg>
+      <doc:doc>
+        <doc:description>
+          <doc:para>This gets a list of all the <doc:ref type="interface" to="org.gnome.SessionManager.Client">Clients</doc:ref>
+          that are currently known to the session manager.</doc:para>
+          <doc:para>Each Client ID is an D-Bus object path for the object that implements the
+          <doc:ref type="interface" to="org.gnome.SessionManager.Client">Client</doc:ref> interface.</doc:para>
+        </doc:description>
+        <doc:seealso><doc:ref type="interface" to="org.gnome.SessionManager.Client">org.gnome.SessionManager.Client</doc:ref></doc:seealso>
+      </doc:doc>
+    </method>
+
+    <method name="GetInhibitors">
+      <arg name="inhibitors" direction="out" type="ao">
+        <doc:doc>
+          <doc:summary>an array of inhibitor IDs</doc:summary>
+        </doc:doc>
+      </arg>
+      <doc:doc>
+        <doc:description>
+          <doc:para>This gets a list of all the <doc:ref type="interface" to="org.gnome.SessionManager.Inhibitor">Inhibitors</doc:ref>
+          that are currently known to the session manager.</doc:para>
+          <doc:para>Each Inhibitor ID is an D-Bus object path for the object that implements the
+          <doc:ref type="interface" to="org.gnome.SessionManager.Inhibitor">Inhibitor</doc:ref> interface.</doc:para>
+        </doc:description>
+        <doc:seealso><doc:ref type="interface" to="org.gnome.SessionManager.Inhibitor">org.gnome.SessionManager.Inhibitor</doc:ref></doc:seealso>
+      </doc:doc>
+    </method>
+
+
+    <method name="IsAutostartConditionHandled">
+      <arg name="condition" direction="in" type="s">
+        <doc:doc>
+          <doc:summary>The autostart condition string</doc:summary>
+        </doc:doc>
+      </arg>
+      <arg name="handled" direction="out" type="b">
+        <doc:doc>
+          <doc:summary>True if condition is handled, false otherwise</doc:summary>
+        </doc:doc>
+      </arg>
+      <doc:doc>
+        <doc:description>
+          <doc:para>Allows the caller to determine whether the session manager is
+          handling changes to the specified autostart condition.</doc:para>
+        </doc:description>
+      </doc:doc>
+    </method>
+
+    <method name="Shutdown">
+      <doc:doc>
+        <doc:description>
+          <doc:para>Request a shutdown dialog.</doc:para>
+        </doc:description>
+      </doc:doc>
+    </method>
+
+    <method name="Reboot">
+      <doc:doc>
+        <doc:description>
+          <doc:para>Request a reboot dialog.</doc:para>
+        </doc:description>
+      </doc:doc>
+    </method>
+
+    <method name="CanShutdown">
+      <arg name="is_available" direction="out" type="b">
+        <doc:doc>
+          <doc:summary>True if shutdown is available to the user, false otherwise</doc:summary>
+        </doc:doc>
+      </arg>
+      <doc:doc>
+        <doc:description>
+          <doc:para>Allows the caller to determine whether or not it's okay to show
+          a shutdown option in the UI</doc:para>
+        </doc:description>
+      </doc:doc>
+    </method>
+
+    <method name="Logout">
+      <arg name="mode" type="u" direction="in">
+        <doc:doc>
+          <doc:summary>The type of logout that is being requested</doc:summary>
+        </doc:doc>
+      </arg>
+      <doc:doc>
+        <doc:description>
+          <doc:para>Request a logout dialog</doc:para>
+          <doc:para>
+            Allowed values for the mode parameter are:
+            <doc:list>
+              <doc:item>
+                <doc:term>0</doc:term>
+                <doc:definition>Normal.</doc:definition>
+              </doc:item>
+              <doc:item>
+                <doc:term>1</doc:term>
+                <doc:definition>No confirmation inferface should be shown.</doc:definition>
+              </doc:item>
+              <doc:item>
+                <doc:term>2</doc:term>
+                <doc:definition>Forcefully logout.  No confirmation will be shown and any inhibitors will be ignored.</doc:definition>
+              </doc:item>
+            </doc:list>
+            Values for flags may be bitwise or'ed together.
+          </doc:para>
+        </doc:description>
+      </doc:doc>
+    </method>
+
+    <method name="IsSessionRunning">
+      <arg name="running" direction="out" type="b">
+        <doc:doc>
+          <doc:summary>True if the session has entered the Running phase, false otherwise</doc:summary>
+        </doc:doc>
+      </arg>
+      <doc:doc>
+        <doc:description>
+          <doc:para>Allows the caller to determine whether the session manager
+          has entered the Running phase, in case the client missed the
+          SessionRunning signal.</doc:para>
+        </doc:description>
+      </doc:doc>
+    </method>
+
+    <!-- Signals -->
+
+    <signal name="ClientAdded">
+      <arg name="id" type="o">
+        <doc:doc>
+          <doc:summary>The object path for the added client</doc:summary>
+        </doc:doc>
+      </arg>
+      <doc:doc>
+        <doc:description>
+          <doc:para>Emitted when a client has been added to the session manager.
+          </doc:para>
+        </doc:description>
+      </doc:doc>
+    </signal>
+    <signal name="ClientRemoved">
+      <arg name="id" type="o">
+        <doc:doc>
+          <doc:summary>The object path for the removed client</doc:summary>
+        </doc:doc>
+      </arg>
+      <doc:doc>
+        <doc:description>
+          <doc:para>Emitted when a client has been removed from the session manager.
+          </doc:para>
+        </doc:description>
+      </doc:doc>
+    </signal>
+
+    <signal name="InhibitorAdded">
+      <arg name="id" type="o">
+        <doc:doc>
+          <doc:summary>The object path for the added inhibitor</doc:summary>
+        </doc:doc>
+      </arg>
+      <doc:doc>
+        <doc:description>
+          <doc:para>Emitted when an inhibitor has been added to the session manager.
+          </doc:para>
+        </doc:description>
+      </doc:doc>
+    </signal>
+    <signal name="InhibitorRemoved">
+      <arg name="id" type="o">
+        <doc:doc>
+          <doc:summary>The object path for the removed inhibitor</doc:summary>
+        </doc:doc>
+      </arg>
+      <doc:doc>
+        <doc:description>
+          <doc:para>Emitted when an inhibitor has been removed from the session manager.
+          </doc:para>
+        </doc:description>
+      </doc:doc>
+    </signal>
+
+    <signal name="SessionRunning">
+      <doc:doc>
+        <doc:description>
+          <doc:para>Indicates the session has entered the Running phase.</doc:para>
+        </doc:description>
+      </doc:doc>
+    </signal>
+
+    <signal name="SessionOver">
+      <doc:doc>
+        <doc:description>
+          <doc:para>Indicates the session is about to end.</doc:para>
+        </doc:description>
+      </doc:doc>
+    </signal>
+
+    <!-- Properties -->
+
+    <property name="SessionName" type="s" access="read">
+      <doc:doc>
+        <doc:description>
+          <doc:para>The name of the session that has been loaded.</doc:para>
+        </doc:description>
+      </doc:doc>
+    </property>
+
+    <property name="SessionIsActive" type="b" access="read">
+      <doc:doc>
+        <doc:description>
+          <doc:para>If true, the session is currently in the
+          foreground and available for user input.</doc:para>
+        </doc:description>
+      </doc:doc>
+    </property>
+
+    <property name="InhibitedActions" type="u" access="read">
+      <doc:doc>
+        <doc:description>
+          <doc:para>A bitmask of flags to indicate which actions
+          are inhibited. See the Inhibit() function's description
+          for a list of possible values.</doc:para>
+        </doc:description>
+      </doc:doc>
+    </property>
+
+  </interface>
+</node>
-- 
1.8.3.1


From 69d86f2acb2a5cd632fc2c6b4e6beff431e06846 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Mon, 29 Jul 2013 00:02:04 -0400
Subject: [PATCH 8/11] 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 deletion(-)

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
@@ -4,86 +4,97 @@
  * Copyright (C) 2010,2011 Red Hat, Inc.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  *
  */
 
 #include "config.h"
 
 #include <glib.h>
 #include <gio/gio.h>
 
 #include "gnome-settings-plugin.h"
 #include "gnome-settings-profile.h"
 #include "gsd-smartcard-manager.h"
 #include "gsd-smartcard-service.h"
 #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>
 #include <pk11func.h>
 #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;
 
         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);
 
 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;
         SECStatus status = SECSuccess;
         static const guint32 flags = NSS_INIT_READONLY
@@ -194,61 +205,60 @@ watch_one_event_from_driver (GsdSmartcardManager       *self,
 
         old_card = g_hash_table_lookup (operation->smartcards, GINT_TO_POINTER ((int) slot_id));
 
         /* If there is a different card in the slot now than
          * there was before, then we need to emit a removed signal
          * for the old card
          */
         if (old_card != NULL) {
                 old_slot_series = PK11_GetSlotSeries (old_card);
 
                 if (old_slot_series != slot_series) {
                         /* Card registered with slot previously is
                          * different than this card, so update its
                          * exported state to track the implicit missed
                          * removal
                          */
                         gsd_smartcard_service_sync_token (priv->service, old_card, cancellable);
                 }
 
                 g_hash_table_remove (operation->smartcards, GINT_TO_POINTER ((int) slot_id));
         }
 
         if (PK11_IsPresent (card)) {
                 g_debug ("Detected smartcard insertion event in slot %d", (int) slot_id);
 
                 g_hash_table_replace (operation->smartcards,
                                       GINT_TO_POINTER ((int) slot_id),
                                       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
                  * event for slots that are empty at startup
                  */
                 g_debug ("Detected slot %d is empty in reader", (int) slot_id);
         } else {
                 g_debug ("Detected smartcard removal event in slot %d", (int) slot_id);
 
                 /* If the just removed smartcard is known to us then
                  * we need to update its exported state to reflect the
                  * removal
                  */
                 if (old_slot_series == slot_series)
                         gsd_smartcard_service_sync_token (priv->service, card, cancellable);
         }
 
         PK11_FreeSlot (card);
 
         return TRUE;
 }
 
 static void
 watch_smartcards_from_driver (GTask                    *task,
                               GsdSmartcardManager      *self,
                               WatchSmartcardsOperation *operation,
                               GCancellable             *cancellable)
 {
         g_debug ("watching for smartcard events");
         while (!g_cancellable_is_cancelled (cancellable)) {
@@ -529,68 +539,79 @@ activate_all_drivers_async (GsdSmartcardManager *self,
 
                 if (!SECMOD_HasRemovableSlots (node->module))
                         continue;
 
                 operation->pending_drivers_count++;
 
                 activate_driver (self, node->module,
                                  cancellable,
                                  (GAsyncReadyCallback) on_driver_activated,
                                  task);
 
         }
         SECMOD_ReleaseReadLock (lock);
 }
 
 static gboolean
 activate_all_drivers_async_finish (GsdSmartcardManager  *self,
                                    GAsyncResult         *result,
                                    GError              **error)
 {
         return gsd_smartcard_utils_finish_boolean_task (G_OBJECT (self), result, error);
 }
 
 static void
 on_all_drivers_activated (GsdSmartcardManager *self,
                           GAsyncResult        *result,
                           GTask               *task)
 {
         GError *error = NULL;
         gboolean driver_activated;
+        PK11SlotInfo *login_token;
 
         driver_activated = activate_all_drivers_async_finish (self, result, &error);
 
         if (!driver_activated) {
                 g_task_return_error (task, error);
                 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);
 }
 
 static void
 watch_smartcards (GTask               *task,
                   GsdSmartcardManager *self,
                   gpointer             data,
                   GCancellable        *cancellable)
 {
         GMainContext *context;
         GMainLoop *loop;
 
         g_debug ("Getting list of suitable drivers");
         context = g_main_context_new ();
         g_main_context_push_thread_default (context);
 
         activate_all_drivers_async (self,
                                     cancellable,
                                     (GAsyncReadyCallback) on_all_drivers_activated,
                                     task);
 
         loop = g_main_loop_new (context, FALSE);
         g_main_loop_run (loop);
         g_main_loop_unref (loop);
 
         g_main_context_pop_thread_default (context);
         g_main_context_unref (context);
 }
 
 static void
@@ -676,60 +697,207 @@ gsd_smartcard_manager_idle_cb (GsdSmartcardManager *self)
         priv->start_idle_id = 0;
         return FALSE;
 }
 
 gboolean
 gsd_smartcard_manager_start (GsdSmartcardManager  *self,
                              GError              **error)
 {
         GsdSmartcardManagerPrivate *priv = self->priv;
 
         gnome_settings_profile_start (NULL);
 
         priv->start_idle_id = g_idle_add ((GSourceFunc) gsd_smartcard_manager_idle_cb, self);
 
         gnome_settings_profile_end (NULL);
 
         return TRUE;
 }
 
 void
 gsd_smartcard_manager_stop (GsdSmartcardManager *self)
 {
         GsdSmartcardManagerPrivate *priv = self->priv;
 
         g_debug ("Stopping smartcard manager");
 
         unload_nss (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 *
 get_login_token_for_operation (GsdSmartcardManager      *self,
                                WatchSmartcardsOperation *operation)
 {
         GHashTableIter iter;
         gpointer key, value;
 
         g_hash_table_iter_init (&iter, operation->smartcards);
         while (g_hash_table_iter_next (&iter, &key, &value)) {
                 PK11SlotInfo *card_slot;
                 const char *token_name;
 
                 card_slot = (PK11SlotInfo *) value;
                 token_name = PK11_GetTokenName (card_slot);
 
                 if (g_strcmp0 (g_getenv ("PKCS11_LOGIN_TOKEN_NAME"), token_name) == 0)
                         return card_slot;
         }
 
         return NULL;
 }
 
 PK11SlotInfo *
 gsd_smartcard_manager_get_login_token (GsdSmartcardManager *self)
 {
         GsdSmartcardManagerPrivate *priv = self->priv;
         GList *node;
 
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
@@ -49,34 +49,35 @@ typedef struct
         GsdSmartcardManagerPrivate *priv;
 } GsdSmartcardManager;
 
 typedef struct
 {
         GObjectClass   parent_class;
 } GsdSmartcardManagerClass;
 
 typedef enum
 {
          GSD_SMARTCARD_MANAGER_ERROR_GENERIC = 0,
          GSD_SMARTCARD_MANAGER_ERROR_WITH_NSS,
          GSD_SMARTCARD_MANAGER_ERROR_LOADING_DRIVER,
          GSD_SMARTCARD_MANAGER_ERROR_WATCHING_FOR_EVENTS,
          GSD_SMARTCARD_MANAGER_ERROR_REPORTING_EVENTS,
          GSD_SMARTCARD_MANAGER_ERROR_FINDING_SMARTCARD
 } GsdSmartcardManagerError;
 
 GType                   gsd_smartcard_manager_get_type    (void);
 GQuark                  gsd_smartcard_manager_error_quark (void);
 
 
 GsdSmartcardManager *   gsd_smartcard_manager_new         (void);
 gboolean                gsd_smartcard_manager_start       (GsdSmartcardManager  *manager,
                                                            GError              **error);
 void                    gsd_smartcard_manager_stop        (GsdSmartcardManager  *manager);
 
 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
 
 #endif /* __GSD_SMARTCARD_MANAGER_H */
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
@@ -478,60 +478,71 @@ synchronize_token_now (GsdSmartcardService *self,
 {
         GsdSmartcardServicePrivate *priv = self->priv;
         GDBusInterfaceSkeleton *interface;
         char *object_path;
         const char *token_name;
         gboolean is_present, is_login_card;
 
         object_path = get_object_path_for_token (self, card_slot);
 
         G_LOCK (gsd_smartcard_tokens);
         interface = g_hash_table_lookup (priv->tokens, object_path);
         g_free (object_path);
 
         if (interface == NULL)
                 goto out;
 
         token_name = PK11_GetTokenName (card_slot);
         is_present = PK11_IsPresent (card_slot);
 
         if (g_strcmp0 (g_getenv ("PKCS11_LOGIN_TOKEN_NAME"), token_name) == 0)
                 is_login_card = TRUE;
         else
                 is_login_card = FALSE;
 
         g_debug ("===============================");
         g_debug (" Token '%s'", token_name);
         g_debug (" Inserted: %s", is_present? "yes" : "no");
         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,
                       NULL);
         g_object_get (G_OBJECT (interface),
                       "used-to-login", &is_login_card,
                       "is-inserted", &is_present,
                       NULL);
 
 out:
         G_UNLOCK (gsd_smartcard_tokens);
 }
 
 typedef struct
 {
         PK11SlotInfo *card_slot;
         char         *object_path;
         GSource      *main_thread_source;
 } RegisterNewTokenOperation;
 
 static void
 destroy_register_new_token_operation (RegisterNewTokenOperation *operation)
 {
         g_clear_pointer (&operation->main_thread_source,
                          (GDestroyNotify) g_source_destroy);
         PK11_FreeSlot (operation->card_slot);
         g_free (operation->object_path);
         g_free (operation);
 }
 
-- 
1.8.3.1


From 73526df53a92aa2829e7043f7dec0e51cf7b0dee Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Thu, 22 Aug 2013 17:52:35 -0400
Subject: [PATCH 9/11] smartcard: ignore softtoken

For some reason that I haven't fully fleshed out, sometimes
the soft token gets into the "will load list" and then havoc
ensues.

This commit fixes that by explicitly ignoring built-in modules.

https://bugzilla.gnome.org/show_bug.cgi?id=706620
---
 plugins/smartcard/gsd-smartcard-manager.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/plugins/smartcard/gsd-smartcard-manager.c b/plugins/smartcard/gsd-smartcard-manager.c
index 4ac31ae..eb22cb2 100644
--- a/plugins/smartcard/gsd-smartcard-manager.c
+++ b/plugins/smartcard/gsd-smartcard-manager.c
@@ -513,60 +513,63 @@ on_driver_activated (GsdSmartcardManager *self,
 }
 
 static void
 activate_all_drivers_async (GsdSmartcardManager *self,
                             GCancellable        *cancellable,
                             GAsyncReadyCallback  callback,
                             gpointer             user_data)
 {
         GTask *task;
         SECMODListLock *lock;
         SECMODModuleList *driver_list, *node;
         ActivateAllDriversOperation *operation;
 
         task = g_task_new (self, cancellable, callback, user_data);
         operation = g_new0 (ActivateAllDriversOperation, 1);
         g_task_set_task_data (task, operation, (GDestroyNotify) g_free);
 
         lock = SECMOD_GetDefaultModuleListLock ();
 
         g_assert (lock != NULL);
 
         SECMOD_GetReadLock (lock);
         driver_list = SECMOD_GetDefaultModuleList ();
         for (node = driver_list; node != NULL; node = node->next) {
                 if (!node->module->loaded)
                         continue;
 
                 if (!SECMOD_HasRemovableSlots (node->module))
                         continue;
 
+                if (node->module->dllName == NULL)
+                        continue;
+
                 operation->pending_drivers_count++;
 
                 activate_driver (self, node->module,
                                  cancellable,
                                  (GAsyncReadyCallback) on_driver_activated,
                                  task);
 
         }
         SECMOD_ReleaseReadLock (lock);
 }
 
 static gboolean
 activate_all_drivers_async_finish (GsdSmartcardManager  *self,
                                    GAsyncResult         *result,
                                    GError              **error)
 {
         return gsd_smartcard_utils_finish_boolean_task (G_OBJECT (self), result, error);
 }
 
 static void
 on_all_drivers_activated (GsdSmartcardManager *self,
                           GAsyncResult        *result,
                           GTask               *task)
 {
         GError *error = NULL;
         gboolean driver_activated;
         PK11SlotInfo *login_token;
 
         driver_activated = activate_all_drivers_async_finish (self, result, &error);
 
-- 
1.8.3.1

From 3f3914ef025aecb85cd737746c5629b656d7d21c Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Mon, 10 Feb 2014 12:33:21 -0500
Subject: [PATCH 10/11] smartcard: detect explicit cancelation explicitly

If the the smartcard function has been cancelled (because,
say, g-s-d is shutting down), handle that case explicitly,
so the right error message is propagated.

https://bugzilla.gnome.org/show_bug.cgi?id=724122
---
 plugins/smartcard/gsd-smartcard-manager.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/plugins/smartcard/gsd-smartcard-manager.c b/plugins/smartcard/gsd-smartcard-manager.c
index eb22cb2..a6eb144 100644
--- a/plugins/smartcard/gsd-smartcard-manager.c
+++ b/plugins/smartcard/gsd-smartcard-manager.c
@@ -157,60 +157,65 @@ typedef struct
 } WatchSmartcardsOperation;
 
 static void
 on_watch_cancelled (GCancellable             *cancellable,
                     WatchSmartcardsOperation *operation)
 {
         SECMOD_CancelWait (operation->driver);
 }
 
 static gboolean
 watch_one_event_from_driver (GsdSmartcardManager       *self,
                              WatchSmartcardsOperation  *operation,
                              GCancellable              *cancellable,
                              GError                   **error)
 {
         GsdSmartcardManagerPrivate *priv = self->priv;
         PK11SlotInfo *card, *old_card;
         CK_SLOT_ID slot_id;
         gulong handler_id;
         int old_slot_series = -1, slot_series;
 
         handler_id = g_cancellable_connect (cancellable,
                                             G_CALLBACK (on_watch_cancelled),
                                             operation,
                                             NULL);
 
         card = SECMOD_WaitForAnyTokenEvent (operation->driver, 0, PR_SecondsToInterval (1));
 
         g_cancellable_disconnect (cancellable, handler_id);
 
+        if (g_cancellable_is_cancelled (cancellable)) {
+                g_warning ("smartcard event function cancelled");
+                return FALSE;
+        }
+
         if (card == NULL) {
                 int error_code;
 
                 error_code = PORT_GetError ();
 
                 g_warning ("smartcard event function failed.");
 
                 g_set_error (error,
                              GSD_SMARTCARD_MANAGER_ERROR,
                              GSD_SMARTCARD_MANAGER_ERROR_WITH_NSS,
                              "encountered unexpected error while "
                              "waiting for smartcard events (error %d)",
                              error_code);
                 return FALSE;
         }
 
         slot_id = PK11_GetSlotID (card);
         slot_series = PK11_GetSlotSeries (card);
 
         old_card = g_hash_table_lookup (operation->smartcards, GINT_TO_POINTER ((int) slot_id));
 
         /* If there is a different card in the slot now than
          * there was before, then we need to emit a removed signal
          * for the old card
          */
         if (old_card != NULL) {
                 old_slot_series = PK11_GetSlotSeries (old_card);
 
                 if (old_slot_series != slot_series) {
                         /* Card registered with slot previously is
@@ -240,60 +245,64 @@ watch_one_event_from_driver (GsdSmartcardManager       *self,
                 g_debug ("Detected slot %d is empty in reader", (int) slot_id);
         } else {
                 g_debug ("Detected smartcard removal event in slot %d", (int) slot_id);
 
                 /* If the just removed smartcard is known to us then
                  * we need to update its exported state to reflect the
                  * removal
                  */
                 if (old_slot_series == slot_series)
                         gsd_smartcard_service_sync_token (priv->service, card, cancellable);
         }
 
         PK11_FreeSlot (card);
 
         return TRUE;
 }
 
 static void
 watch_smartcards_from_driver (GTask                    *task,
                               GsdSmartcardManager      *self,
                               WatchSmartcardsOperation *operation,
                               GCancellable             *cancellable)
 {
         g_debug ("watching for smartcard events");
         while (!g_cancellable_is_cancelled (cancellable)) {
                 gboolean watch_succeeded;
                 GError *error = NULL;
 
                 watch_succeeded = watch_one_event_from_driver (self, operation, cancellable, &error);
 
+                if (g_task_return_error_if_cancelled (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
 watch_smartcards_from_driver_async (GsdSmartcardManager *self,
                                     SECMODModule        *driver,
-- 
1.8.3.1


From a36d72a776767b401a29dd8b10c17f365643d9e6 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Tue, 11 Feb 2014 10:11:51 -0500
Subject: [PATCH 11/11] smartcard: filter out spurious errors

Some PKCS11 modules send spurious errors when the card is first
powered on.  This commit works around that problem by adding
retries.

This brings us back to status quo with the old smartcard plugin.

https://bugzilla.gnome.org/show_bug.cgi?id=724122
---
 plugins/smartcard/gsd-smartcard-manager.c | 27 +++++++++++++++++++--------
 1 file changed, 19 insertions(+), 8 deletions(-)

diff --git a/plugins/smartcard/gsd-smartcard-manager.c b/plugins/smartcard/gsd-smartcard-manager.c
index a6eb144..3fc4823 100644
--- a/plugins/smartcard/gsd-smartcard-manager.c
+++ b/plugins/smartcard/gsd-smartcard-manager.c
@@ -127,110 +127,121 @@ load_nss (GsdSmartcardManager *self)
                                  error_message);
                 }
                 priv->nss_is_loaded = FALSE;
                 return;
 
         }
 
         g_debug ("NSS database '%s' loaded", GSD_SMARTCARD_MANAGER_NSS_DB);
         priv->nss_is_loaded = TRUE;
 }
 
 static void
 unload_nss (GsdSmartcardManager *self)
 {
         g_debug ("attempting to unload NSS security system with database '%s'",
                  GSD_SMARTCARD_MANAGER_NSS_DB);
 
         if (self->priv->nss_is_loaded) {
                 NSS_Shutdown ();
                 self->priv->nss_is_loaded = FALSE;
                 g_debug ("NSS database '%s' unloaded", GSD_SMARTCARD_MANAGER_NSS_DB);
         } else {
                 g_debug ("NSS database '%s' already not loaded", GSD_SMARTCARD_MANAGER_NSS_DB);
         }
 }
 
 typedef struct
 {
         SECMODModule *driver;
         GHashTable *smartcards;
+        int number_of_consecutive_errors;
 } WatchSmartcardsOperation;
 
 static void
 on_watch_cancelled (GCancellable             *cancellable,
                     WatchSmartcardsOperation *operation)
 {
         SECMOD_CancelWait (operation->driver);
 }
 
 static gboolean
 watch_one_event_from_driver (GsdSmartcardManager       *self,
                              WatchSmartcardsOperation  *operation,
                              GCancellable              *cancellable,
                              GError                   **error)
 {
         GsdSmartcardManagerPrivate *priv = self->priv;
         PK11SlotInfo *card, *old_card;
         CK_SLOT_ID slot_id;
         gulong handler_id;
         int old_slot_series = -1, slot_series;
 
         handler_id = g_cancellable_connect (cancellable,
                                             G_CALLBACK (on_watch_cancelled),
                                             operation,
                                             NULL);
 
         card = SECMOD_WaitForAnyTokenEvent (operation->driver, 0, PR_SecondsToInterval (1));
 
         g_cancellable_disconnect (cancellable, handler_id);
 
         if (g_cancellable_is_cancelled (cancellable)) {
                 g_warning ("smartcard event function cancelled");
                 return FALSE;
         }
 
         if (card == NULL) {
                 int error_code;
 
                 error_code = PORT_GetError ();
 
-                g_warning ("smartcard event function failed.");
+                operation->number_of_consecutive_errors++;
+                if (operation->number_of_consecutive_errors > 10) {
+                     g_warning ("Got %d consecutive smartcard errors, so giving up.",
+                                operation->number_of_consecutive_errors);
+
+                     g_set_error (error,
+                                  GSD_SMARTCARD_MANAGER_ERROR,
+                                  GSD_SMARTCARD_MANAGER_ERROR_WITH_NSS,
+                                  "encountered unexpected error while "
+                                  "waiting for smartcard events (error %x)",
+                                  error_code);
+                     return FALSE;
+                }
 
-                g_set_error (error,
-                             GSD_SMARTCARD_MANAGER_ERROR,
-                             GSD_SMARTCARD_MANAGER_ERROR_WITH_NSS,
-                             "encountered unexpected error while "
-                             "waiting for smartcard events (error %d)",
-                             error_code);
-                return FALSE;
+                g_warning ("Got potentially spurious smartcard event error: %x.", error_code);
+
+                g_usleep (0.5 * G_USEC_PER_SEC);
+                return TRUE;
         }
+        operation->number_of_consecutive_errors = 0;
 
         slot_id = PK11_GetSlotID (card);
         slot_series = PK11_GetSlotSeries (card);
 
         old_card = g_hash_table_lookup (operation->smartcards, GINT_TO_POINTER ((int) slot_id));
 
         /* If there is a different card in the slot now than
          * there was before, then we need to emit a removed signal
          * for the old card
          */
         if (old_card != NULL) {
                 old_slot_series = PK11_GetSlotSeries (old_card);
 
                 if (old_slot_series != slot_series) {
                         /* Card registered with slot previously is
                          * different than this card, so update its
                          * exported state to track the implicit missed
                          * removal
                          */
                         gsd_smartcard_service_sync_token (priv->service, old_card, cancellable);
                 }
 
                 g_hash_table_remove (operation->smartcards, GINT_TO_POINTER ((int) slot_id));
         }
 
         if (PK11_IsPresent (card)) {
                 g_debug ("Detected smartcard insertion event in slot %d", (int) slot_id);
 
                 g_hash_table_replace (operation->smartcards,
                                       GINT_TO_POINTER ((int) slot_id),
-- 
1.8.3.1