From e46b4adef5c6c6805b3ca6dbfbe99a4299252514 Mon Sep 17 00:00:00 2001 From: haxar Date: Tue, 21 Feb 2012 20:14:01 -0800 Subject: gsd to msd complete rename patch by NiceandGently; file rename commit --- plugins/smartcard/gsd-smartcard-manager.c | 1372 ----------------------------- plugins/smartcard/gsd-smartcard-manager.h | 90 -- plugins/smartcard/gsd-smartcard-plugin.c | 340 ------- plugins/smartcard/gsd-smartcard-plugin.h | 63 -- plugins/smartcard/gsd-smartcard.c | 555 ------------ plugins/smartcard/gsd-smartcard.h | 98 --- plugins/smartcard/msd-smartcard-manager.c | 1372 +++++++++++++++++++++++++++++ plugins/smartcard/msd-smartcard-manager.h | 90 ++ plugins/smartcard/msd-smartcard-plugin.c | 340 +++++++ plugins/smartcard/msd-smartcard-plugin.h | 63 ++ plugins/smartcard/msd-smartcard.c | 555 ++++++++++++ plugins/smartcard/msd-smartcard.h | 98 +++ 12 files changed, 2518 insertions(+), 2518 deletions(-) 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 create mode 100644 plugins/smartcard/msd-smartcard-manager.c create mode 100644 plugins/smartcard/msd-smartcard-manager.h create mode 100644 plugins/smartcard/msd-smartcard-plugin.c create mode 100644 plugins/smartcard/msd-smartcard-plugin.h create mode 100644 plugins/smartcard/msd-smartcard.c create mode 100644 plugins/smartcard/msd-smartcard.h (limited to 'plugins/smartcard') diff --git a/plugins/smartcard/gsd-smartcard-manager.c b/plugins/smartcard/gsd-smartcard-manager.c deleted file mode 100644 index ed823f4..0000000 --- a/plugins/smartcard/gsd-smartcard-manager.c +++ /dev/null @@ -1,1372 +0,0 @@ -/* msd-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 "msd-smartcard-manager.h" - -#define SMARTCARD_ENABLE_INTERNAL_API -#include "msd-smartcard.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include - -#ifndef MSD_SMARTCARD_MANAGER_NSS_DB -#define MSD_SMARTCARD_MANAGER_NSS_DB SYSCONFDIR"/pki/nssdb" -#endif - -typedef enum _MsdSmartcardManagerState MsdSmartcardManagerState; -typedef struct _MsdSmartcardManagerWorker MsdSmartcardManagerWorker; - -enum _MsdSmartcardManagerState { - MSD_SMARTCARD_MANAGER_STATE_STOPPED = 0, - MSD_SMARTCARD_MANAGER_STATE_STARTING, - MSD_SMARTCARD_MANAGER_STATE_STARTED, - MSD_SMARTCARD_MANAGER_STATE_STOPPING, -}; - -struct _MsdSmartcardManagerPrivate { - MsdSmartcardManagerState state; - SECMODModule *module; - char *module_path; - - GSource *smartcard_event_source; - GPid smartcard_event_watcher_pid; - GHashTable *smartcards; - - GThread *worker_thread; - - guint poll_timeout_id; - - guint32 is_unstoppable : 1; - guint32 nss_is_loaded : 1; -}; - -struct _MsdSmartcardManagerWorker { - SECMODModule *module; - GHashTable *smartcards; - int write_fd; - - guint32 nss_is_loaded : 1; -}; - -static void msd_smartcard_manager_finalize (GObject *object); -static void msd_smartcard_manager_class_install_signals (MsdSmartcardManagerClass *service_class); -static void msd_smartcard_manager_class_install_properties (MsdSmartcardManagerClass *service_class); -static void msd_smartcard_manager_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec); -static void msd_smartcard_manager_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec); -static void msd_smartcard_manager_set_module_path (MsdSmartcardManager *manager, - const char *module_path); -static void msd_smartcard_manager_card_removed_handler (MsdSmartcardManager *manager, - MsdSmartcard *card); -static void msd_smartcard_manager_card_inserted_handler (MsdSmartcardManager *manager_class, - MsdSmartcard *card); -static gboolean msd_smartcard_manager_stop_now (MsdSmartcardManager *manager); -static void msd_smartcard_manager_queue_stop (MsdSmartcardManager *manager); - -static gboolean msd_smartcard_manager_create_worker (MsdSmartcardManager *manager, - int *worker_fd, GThread **worker_thread); - -static MsdSmartcardManagerWorker * msd_smartcard_manager_worker_new (int write_fd); -static void msd_smartcard_manager_worker_free (MsdSmartcardManagerWorker *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 MsdSmartcard *read_smartcard (int fd, SECMODModule *module); -static gboolean write_smartcard (int fd, MsdSmartcard *card); - -enum { - PROP_0 = 0, - PROP_MODULE_PATH, - NUMBER_OF_PROPERTIES -}; - -enum { - SMARTCARD_INSERTED = 0, - SMARTCARD_REMOVED, - ERROR, - NUMBER_OF_SIGNALS -}; - -static guint msd_smartcard_manager_signals[NUMBER_OF_SIGNALS]; - -G_DEFINE_TYPE (MsdSmartcardManager, - msd_smartcard_manager, - G_TYPE_OBJECT); - -static void -msd_smartcard_manager_class_init (MsdSmartcardManagerClass *manager_class) -{ - GObjectClass *gobject_class; - - gobject_class = G_OBJECT_CLASS (manager_class); - - gobject_class->finalize = msd_smartcard_manager_finalize; - - msd_smartcard_manager_class_install_signals (manager_class); - msd_smartcard_manager_class_install_properties (manager_class); - - g_type_class_add_private (manager_class, - sizeof (MsdSmartcardManagerPrivate)); -} - -static void -msd_smartcard_manager_class_install_properties (MsdSmartcardManagerClass *card_class) -{ - GObjectClass *object_class; - GParamSpec *param_spec; - - object_class = G_OBJECT_CLASS (card_class); - object_class->set_property = msd_smartcard_manager_set_property; - object_class->get_property = msd_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 -msd_smartcard_manager_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MsdSmartcardManager *manager = MSD_SMARTCARD_MANAGER (object); - - switch (prop_id) { - case PROP_MODULE_PATH: - msd_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 -msd_smartcard_manager_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MsdSmartcardManager *manager = MSD_SMARTCARD_MANAGER (object); - char *module_path; - - switch (prop_id) { - case PROP_MODULE_PATH: - module_path = msd_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 * -msd_smartcard_manager_get_module_path (MsdSmartcardManager *manager) -{ - return manager->priv->module_path; -} - -static void -msd_smartcard_manager_set_module_path (MsdSmartcardManager *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 -msd_smartcard_manager_card_removed_handler (MsdSmartcardManager *manager, - MsdSmartcard *card) -{ - g_debug ("informing smartcard of its removal"); - _msd_smartcard_set_state (card, MSD_SMARTCARD_STATE_REMOVED); - g_debug ("done"); -} - -static void -msd_smartcard_manager_card_inserted_handler (MsdSmartcardManager *manager, - MsdSmartcard *card) -{ - g_debug ("informing smartcard of its insertion"); - - _msd_smartcard_set_state (card, MSD_SMARTCARD_STATE_INSERTED); - g_debug ("done"); - -} - -static void -msd_smartcard_manager_class_install_signals (MsdSmartcardManagerClass *manager_class) -{ - GObjectClass *object_class; - - object_class = G_OBJECT_CLASS (manager_class); - - msd_smartcard_manager_signals[SMARTCARD_INSERTED] = - g_signal_new ("smartcard-inserted", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (MsdSmartcardManagerClass, - smartcard_inserted), - NULL, NULL, g_cclosure_marshal_VOID__POINTER, - G_TYPE_NONE, 1, G_TYPE_POINTER); - manager_class->smartcard_inserted = msd_smartcard_manager_card_inserted_handler; - - msd_smartcard_manager_signals[SMARTCARD_REMOVED] = - g_signal_new ("smartcard-removed", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (MsdSmartcardManagerClass, - smartcard_removed), - NULL, NULL, g_cclosure_marshal_VOID__POINTER, - G_TYPE_NONE, 1, G_TYPE_POINTER); - manager_class->smartcard_removed = msd_smartcard_manager_card_removed_handler; - - msd_smartcard_manager_signals[ERROR] = - g_signal_new ("error", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (MsdSmartcardManagerClass, 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 -msd_smartcard_manager_init (MsdSmartcardManager *manager) -{ - g_debug ("initializing smartcard manager"); - - manager->priv = G_TYPE_INSTANCE_GET_PRIVATE (manager, - MSD_TYPE_SMARTCARD_MANAGER, - MsdSmartcardManagerPrivate); - manager->priv->poll_timeout_id = 0; - manager->priv->is_unstoppable = FALSE; - manager->priv->module = NULL; - - manager->priv->smartcards = - g_hash_table_new_full (g_str_hash, - g_str_equal, - (GDestroyNotify) g_free, - (GDestroyNotify) g_object_unref); - - if (!g_thread_supported ()) { - g_thread_init (NULL); - } - -} - -static void -msd_smartcard_manager_finalize (GObject *object) -{ - MsdSmartcardManager *manager; - GObjectClass *gobject_class; - - manager = MSD_SMARTCARD_MANAGER (object); - gobject_class = - G_OBJECT_CLASS (msd_smartcard_manager_parent_class); - - msd_smartcard_manager_stop_now (manager); - - g_hash_table_destroy (manager->priv->smartcards); - manager->priv->smartcards = NULL; - - gobject_class->finalize (object); -} - -GQuark -msd_smartcard_manager_error_quark (void) -{ - static GQuark error_quark = 0; - - if (error_quark == 0) { - error_quark = g_quark_from_static_string ("msd-smartcard-manager-error-quark"); - } - - return error_quark; -} - -MsdSmartcardManager * -msd_smartcard_manager_new (const char *module_path) -{ - MsdSmartcardManager *instance; - - instance = MSD_SMARTCARD_MANAGER (g_object_new (MSD_TYPE_SMARTCARD_MANAGER, - "module-path", module_path, - NULL)); - - return instance; -} - -static void -msd_smartcard_manager_emit_error (MsdSmartcardManager *manager, - GError *error) -{ - manager->priv->is_unstoppable = TRUE; - g_signal_emit (manager, msd_smartcard_manager_signals[ERROR], 0, - error); - manager->priv->is_unstoppable = FALSE; -} - -static void -msd_smartcard_manager_emit_smartcard_inserted (MsdSmartcardManager *manager, - MsdSmartcard *card) -{ - manager->priv->is_unstoppable = TRUE; - g_signal_emit (manager, msd_smartcard_manager_signals[SMARTCARD_INSERTED], 0, - card); - manager->priv->is_unstoppable = FALSE; -} - -static void -msd_smartcard_manager_emit_smartcard_removed (MsdSmartcardManager *manager, - MsdSmartcard *card) -{ - MsdSmartcardManagerState old_state; - - old_state = manager->priv->state; - manager->priv->is_unstoppable = TRUE; - g_signal_emit (manager, msd_smartcard_manager_signals[SMARTCARD_REMOVED], 0, - card); - manager->priv->is_unstoppable = FALSE; -} - -static gboolean -msd_smartcard_manager_check_for_and_process_events (GIOChannel *io_channel, - GIOCondition condition, - MsdSmartcardManager *manager) -{ - MsdSmartcard *card; - gboolean should_stop; - gchar event_type; - char *card_name; - int fd; - - 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)) { - goto out; - } - - fd = g_io_channel_unix_get_fd (io_channel); - - event_type = '\0'; - if (!read_bytes (fd, &event_type, 1)) { - should_stop = TRUE; - goto out; - } - - card = read_smartcard (fd, manager->priv->module); - - if (card == NULL) { - should_stop = TRUE; - goto out; - } - - card_name = msd_smartcard_get_name (card); - - switch (event_type) { - case 'I': - g_hash_table_replace (manager->priv->smartcards, - card_name, card); - card_name = NULL; - - msd_smartcard_manager_emit_smartcard_inserted (manager, card); - card = NULL; - break; - - case 'R': - msd_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 (MSD_SMARTCARD_MANAGER_ERROR, - MSD_SMARTCARD_MANAGER_ERROR_WATCHING_FOR_EVENTS, - "%s", (condition & G_IO_IN) ? g_strerror (errno) : _("received error or hang up from event source")); - - msd_smartcard_manager_emit_error (manager, error); - g_error_free (error); - msd_smartcard_manager_stop_now (manager); - return FALSE; - } - - return TRUE; -} - -static void -msd_smartcard_manager_event_processing_stopped_handler (MsdSmartcardManager *manager) -{ - manager->priv->smartcard_event_source = NULL; - msd_smartcard_manager_stop_now (manager); -} - -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 -msd_smartcard_manager_stop_watching_for_events (MsdSmartcardManager *manager) -{ - if (manager->priv->smartcard_event_source != NULL) { - g_source_destroy (manager->priv->smartcard_event_source); - manager->priv->smartcard_event_source = NULL; - } - - if (manager->priv->worker_thread != NULL) { - SECMOD_CancelWait (manager->priv->module); - manager->priv->worker_thread = NULL; - } -} - -static gboolean -load_nss (GError **error) -{ - SECStatus status = SECSuccess; - static const guint32 flags = - NSS_INIT_READONLY | NSS_INIT_NOCERTDB | NSS_INIT_NOMODDB | - NSS_INIT_FORCEOPEN | NSS_INIT_NOROOTINIT | - NSS_INIT_OPTIMIZESPACE | NSS_INIT_PK11RELOAD; - - g_debug ("attempting to load NSS database '%s'", - MSD_SMARTCARD_MANAGER_NSS_DB); - - status = NSS_Initialize (MSD_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, - MSD_SMARTCARD_MANAGER_ERROR, - MSD_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, - MSD_SMARTCARD_MANAGER_ERROR, - MSD_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 SECMODModule * -load_driver (char *module_path, - GError **error) -{ - SECMODModule *module; - char *module_spec; - gboolean module_explicitly_specified; - - g_debug ("attempting to load driver..."); - - module = NULL; - module_explicitly_specified = module_path != NULL; - if (module_explicitly_specified) { - 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; - - } else { - SECMODModuleList *modules, *tmp; - - modules = SECMOD_GetDefaultModuleList (); - - for (tmp = modules; tmp != NULL; tmp = tmp->next) { - if (!SECMOD_HasRemovableSlots (tmp->module) || - !tmp->module->loaded) - continue; - - module = SECMOD_ReferenceModule (tmp->module); - break; - } - } - - if (!module_explicitly_specified && module == NULL) { - g_set_error (error, - MSD_SMARTCARD_MANAGER_ERROR, - MSD_SMARTCARD_MANAGER_ERROR_LOADING_DRIVER, - _("no suitable smartcard driver could be found")); - } else if (module == NULL || !module->loaded) { - - gsize error_message_size; - char *error_message; - - if (module != NULL && !module->loaded) { - g_debug ("module found but not loaded?!"); - SECMOD_DestroyModule (module); - module = NULL; - } - - 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, - MSD_SMARTCARD_MANAGER_ERROR, - MSD_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, - MSD_SMARTCARD_MANAGER_ERROR, - MSD_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); - } - -out: - return module; -} - -static void -msd_smartcard_manager_get_all_cards (MsdSmartcardManager *manager) -{ - int i; - - for (i = 0; i < manager->priv->module->slotCount; i++) { - MsdSmartcard *card; - CK_SLOT_ID slot_id; - int slot_series; - char *card_name; - - slot_id = PK11_GetSlotID (manager->priv->module->slots[i]); - slot_series = PK11_GetSlotSeries (manager->priv->module->slots[i]); - - card = _msd_smartcard_new (manager->priv->module, - slot_id, slot_series); - - card_name = msd_smartcard_get_name (card); - - g_hash_table_replace (manager->priv->smartcards, - card_name, card); - } -} - -gboolean -msd_smartcard_manager_start (MsdSmartcardManager *manager, - GError **error) -{ - GError *watching_error; - int worker_fd; - GPid worker_pid; - GIOChannel *io_channel; - GSource *source; - GIOFlags channel_flags; - GError *nss_error; - - if (manager->priv->state == MSD_SMARTCARD_MANAGER_STATE_STARTED) { - g_debug ("smartcard manager already started"); - return TRUE; - } - - manager->priv->state = MSD_SMARTCARD_MANAGER_STATE_STARTING; - - worker_fd = -1; - worker_pid = 0; - - 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->module == NULL) { - manager->priv->module = load_driver (manager->priv->module_path, &nss_error); - } - - if (manager->priv->module == NULL) { - g_propagate_error (error, nss_error); - goto out; - } - - if (!msd_smartcard_manager_create_worker (manager, &worker_fd, &manager->priv->worker_thread)) { - - g_set_error (error, - MSD_SMARTCARD_MANAGER_ERROR, - MSD_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_fd); - - channel_flags = g_io_channel_get_flags (io_channel); - watching_error = NULL; - - source = g_io_create_watch (io_channel, G_IO_IN | G_IO_HUP); - g_io_channel_unref (io_channel); - io_channel = NULL; - - manager->priv->smartcard_event_source = source; - - g_source_set_callback (manager->priv->smartcard_event_source, - (GSourceFunc) (GIOFunc) - msd_smartcard_manager_check_for_and_process_events, - manager, - (GDestroyNotify) - msd_smartcard_manager_event_processing_stopped_handler); - g_source_attach (manager->priv->smartcard_event_source, NULL); - g_source_unref (manager->priv->smartcard_event_source); - - /* populate the hash with cards that are already inserted - */ - msd_smartcard_manager_get_all_cards (manager); - - manager->priv->state = MSD_SMARTCARD_MANAGER_STATE_STARTED; - -out: - /* don't leave it in a half started state - */ - if (manager->priv->state != MSD_SMARTCARD_MANAGER_STATE_STARTED) { - g_debug ("smartcard manager could not be completely started"); - msd_smartcard_manager_stop (manager); - } else { - g_debug ("smartcard manager started"); - } - - return manager->priv->state == MSD_SMARTCARD_MANAGER_STATE_STARTED; -} - -static gboolean -msd_smartcard_manager_stop_now (MsdSmartcardManager *manager) -{ - if (manager->priv->state == MSD_SMARTCARD_MANAGER_STATE_STOPPED) { - return FALSE; - } - - manager->priv->state = MSD_SMARTCARD_MANAGER_STATE_STOPPED; - msd_smartcard_manager_stop_watching_for_events (manager); - - if (manager->priv->module != NULL) { - SECMOD_DestroyModule (manager->priv->module); - manager->priv->module = NULL; - } - - if (manager->priv->nss_is_loaded) { - NSS_Shutdown (); - manager->priv->nss_is_loaded = FALSE; - } - - g_debug ("smartcard manager stopped"); - - return FALSE; -} - -static void -msd_smartcard_manager_queue_stop (MsdSmartcardManager *manager) -{ - - manager->priv->state = MSD_SMARTCARD_MANAGER_STATE_STOPPING; - - g_idle_add ((GSourceFunc) msd_smartcard_manager_stop_now, manager); -} - -void -msd_smartcard_manager_stop (MsdSmartcardManager *manager) -{ - if (manager->priv->state == MSD_SMARTCARD_MANAGER_STATE_STOPPED) { - return; - } - - if (manager->priv->is_unstoppable) { - msd_smartcard_manager_queue_stop (manager); - return; - } - - msd_smartcard_manager_stop_now (manager); -} - -static void -msd_smartcard_manager_check_for_login_card (CK_SLOT_ID slot_id, - MsdSmartcard *card, - gboolean *is_inserted) -{ - g_assert (is_inserted != NULL); - - if (msd_smartcard_is_login_card (card)) { - *is_inserted = TRUE; - } - -} - -gboolean -msd_smartcard_manager_login_card_is_inserted (MsdSmartcardManager *manager) - -{ - gboolean is_inserted; - - is_inserted = FALSE; - g_hash_table_foreach (manager->priv->smartcards, - (GHFunc) - msd_smartcard_manager_check_for_login_card, - &is_inserted); - return is_inserted; -} - -static MsdSmartcardManagerWorker * -msd_smartcard_manager_worker_new (int write_fd) -{ - MsdSmartcardManagerWorker *worker; - - worker = g_slice_new0 (MsdSmartcardManagerWorker); - worker->write_fd = write_fd; - worker->module = NULL; - - 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 -msd_smartcard_manager_worker_free (MsdSmartcardManagerWorker *worker) -{ - if (worker->smartcards != NULL) { - g_hash_table_destroy (worker->smartcards); - worker->smartcards = NULL; - } - - g_slice_free (MsdSmartcardManagerWorker, 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 MsdSmartcard * -read_smartcard (int fd, - SECMODModule *module) -{ - MsdSmartcard *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 = _msd_smartcard_new_from_name (module, card_name); - g_slice_free1 (card_name_size, card_name); - - return card; -} - -static gboolean -write_smartcard (int fd, - MsdSmartcard *card) -{ - gsize card_name_size; - char *card_name; - - card_name = msd_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 -msd_smartcard_manager_worker_emit_smartcard_removed (MsdSmartcardManagerWorker *worker, - MsdSmartcard *card, - GError **error) -{ - g_debug ("card '%s' removed!", msd_smartcard_get_name (card)); - - if (!write_bytes (worker->write_fd, "R", 1)) { - goto error_out; - } - - if (!write_smartcard (worker->write_fd, card)) { - goto error_out; - } - - return TRUE; - -error_out: - g_set_error (error, MSD_SMARTCARD_MANAGER_ERROR, - MSD_SMARTCARD_MANAGER_ERROR_REPORTING_EVENTS, - "%s", g_strerror (errno)); - return FALSE; -} - -static gboolean -msd_smartcard_manager_worker_emit_smartcard_inserted (MsdSmartcardManagerWorker *worker, - MsdSmartcard *card, - GError **error) -{ - GError *write_error; - - write_error = NULL; - g_debug ("card '%s' inserted!", msd_smartcard_get_name (card)); - if (!write_bytes (worker->write_fd, "I", 1)) { - goto error_out; - } - - if (!write_smartcard (worker->write_fd, card)) { - goto error_out; - } - - return TRUE; - -error_out: - g_set_error (error, MSD_SMARTCARD_MANAGER_ERROR, - MSD_SMARTCARD_MANAGER_ERROR_REPORTING_EVENTS, - "%s", g_strerror (errno)); - return FALSE; -} - -static gboolean -msd_smartcard_manager_worker_watch_for_and_process_event (MsdSmartcardManagerWorker *worker, - GError **error) -{ - PK11SlotInfo *slot; - CK_SLOT_ID slot_id, *key; - int slot_series, card_slot_series; - MsdSmartcard *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, MSD_SMARTCARD_MANAGER_ERROR, - MSD_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 = msd_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 (!msd_smartcard_manager_worker_emit_smartcard_removed (worker, card, &processing_error)) { - g_propagate_error (error, processing_error); - goto out; - } - } - - card = _msd_smartcard_new (worker->module, - slot_id, slot_series); - - g_hash_table_replace (worker->smartcards, - key, card); - key = NULL; - - if (!msd_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 (!msd_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 = _msd_smartcard_new (worker->module, - slot_id, slot_series); - g_hash_table_replace (worker->smartcards, - key, card); - key = NULL; - if (!msd_smartcard_manager_worker_emit_smartcard_inserted (worker, card, &processing_error)) { - g_propagate_error (error, processing_error); - goto out; - } - } - - if (!msd_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 -msd_smartcard_manager_worker_run (MsdSmartcardManagerWorker *worker) -{ - GError *error; - - - error = NULL; - - while (msd_smartcard_manager_worker_watch_for_and_process_event (worker, &error)); - - if (error != NULL) { - g_debug ("could not process card event - %s", error->message); - g_error_free (error); - } - - msd_smartcard_manager_worker_free (worker); -} - -static gboolean -msd_smartcard_manager_create_worker (MsdSmartcardManager *manager, - int *worker_fd, - GThread **worker_thread) -{ - MsdSmartcardManagerWorker *worker; - int write_fd, read_fd; - - write_fd = -1; - read_fd = -1; - if (!open_pipe (&write_fd, &read_fd)) { - return FALSE; - } - - worker = msd_smartcard_manager_worker_new (write_fd); - worker->module = manager->priv->module; - - *worker_thread = g_thread_create ((GThreadFunc) - msd_smartcard_manager_worker_run, - worker, FALSE, NULL); - - if (*worker_thread == NULL) { - msd_smartcard_manager_worker_free (worker); - return FALSE; - } - - if (worker_fd) { - *worker_fd = read_fd; - } - - return TRUE; -} - -#ifdef MSD_SMARTCARD_MANAGER_ENABLE_TEST -#include - -static GMainLoop *event_loop; -static gboolean should_exit_on_next_remove = FALSE; - -static gboolean -on_timeout (MsdSmartcardManager *manager) -{ - GError *error; - g_print ("Re-enabling manager.\n"); - - if (!msd_smartcard_manager_start (manager, &error)) { - g_warning ("could not start smartcard manager - %s", - error->message); - g_error_free (error); - return 1; - } - g_print ("Please re-insert smartcard\n"); - - should_exit_on_next_remove = TRUE; - - return FALSE; -} - -static void -on_device_inserted (MsdSmartcardManager *manager, - MsdSmartcard *card) -{ - g_print ("smartcard inserted!\n"); - g_print ("Please remove it.\n"); -} - -static void -on_device_removed (MsdSmartcardManager *manager, - MsdSmartcard *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"); - msd_smartcard_manager_stop (manager); - g_timeout_add (2000, (GSourceFunc) on_timeout, manager); - } -} - -int -main (int argc, - char *argv[]) -{ - MsdSmartcardManager *manager; - GError *error; - - g_log_set_always_fatal (G_LOG_LEVEL_ERROR - | G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING); - - g_type_init (); - - g_message ("creating instance of 'smartcard manager' object..."); - manager = msd_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 (!msd_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 269e1da..0000000 --- a/plugins/smartcard/gsd-smartcard-manager.h +++ /dev/null @@ -1,90 +0,0 @@ -/* msd-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 MSD_SMARTCARD_MANAGER_H -#define MSD_SMARTCARD_MANAGER_H - -#define MSD_SMARTCARD_ENABLE_INTERNAL_API -#include "msd-smartcard.h" - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif -#define MSD_TYPE_SMARTCARD_MANAGER (msd_smartcard_manager_get_type ()) -#define MSD_SMARTCARD_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MSD_TYPE_SMARTCARD_MANAGER, MsdSmartcardManager)) -#define MSD_SMARTCARD_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MSD_TYPE_SMARTCARD_MANAGER, MsdSmartcardManagerClass)) -#define MSD_IS_SMARTCARD_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SC_TYPE_SMARTCARD_MANAGER)) -#define MSD_IS_SMARTCARD_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SC_TYPE_SMARTCARD_MANAGER)) -#define MSD_SMARTCARD_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), MSD_TYPE_SMARTCARD_MANAGER, MsdSmartcardManagerClass)) -#define MSD_SMARTCARD_MANAGER_ERROR (msd_smartcard_manager_error_quark ()) -typedef struct _MsdSmartcardManager MsdSmartcardManager; -typedef struct _MsdSmartcardManagerClass MsdSmartcardManagerClass; -typedef struct _MsdSmartcardManagerPrivate MsdSmartcardManagerPrivate; -typedef enum _MsdSmartcardManagerError MsdSmartcardManagerError; - -struct _MsdSmartcardManager { - GObject parent; - - /*< private > */ - MsdSmartcardManagerPrivate *priv; -}; - -struct _MsdSmartcardManagerClass { - GObjectClass parent_class; - - /* Signals */ - void (*smartcard_inserted) (MsdSmartcardManager *manager, - MsdSmartcard *token); - void (*smartcard_removed) (MsdSmartcardManager *manager, - MsdSmartcard *token); - void (*error) (MsdSmartcardManager *manager, - GError *error); -}; - -enum _MsdSmartcardManagerError { - MSD_SMARTCARD_MANAGER_ERROR_GENERIC = 0, - MSD_SMARTCARD_MANAGER_ERROR_WITH_NSS, - MSD_SMARTCARD_MANAGER_ERROR_LOADING_DRIVER, - MSD_SMARTCARD_MANAGER_ERROR_WATCHING_FOR_EVENTS, - MSD_SMARTCARD_MANAGER_ERROR_REPORTING_EVENTS -}; - -GType msd_smartcard_manager_get_type (void) G_GNUC_CONST; -GQuark msd_smartcard_manager_error_quark (void) G_GNUC_CONST; - -MsdSmartcardManager *msd_smartcard_manager_new (const char *module); - -gboolean msd_smartcard_manager_start (MsdSmartcardManager *manager, - GError **error); - -void msd_smartcard_manager_stop (MsdSmartcardManager *manager); - -char *msd_smartcard_manager_get_module_path (MsdSmartcardManager *manager); -gboolean msd_smartcard_manager_login_card_is_inserted (MsdSmartcardManager *manager); - -#ifdef __cplusplus -} -#endif -#endif /* MSD_SMARTCARD_MANAGER_H */ diff --git a/plugins/smartcard/gsd-smartcard-plugin.c b/plugins/smartcard/gsd-smartcard-plugin.c deleted file mode 100644 index dc4cb8f..0000000 --- a/plugins/smartcard/gsd-smartcard-plugin.c +++ /dev/null @@ -1,340 +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 -#include - -#include -#include - -#include - -#include - -#include "mate-settings-plugin.h" -#include "msd-smartcard-plugin.h" -#include "msd-smartcard-manager.h" - -struct MsdSmartcardPluginPrivate { - MsdSmartcardManager *manager; - DBusGConnection *bus_connection; - - guint32 is_active : 1; -}; - -typedef enum -{ - MSD_SMARTCARD_REMOVE_ACTION_NONE, - MSD_SMARTCARD_REMOVE_ACTION_LOCK_SCREEN, - MSD_SMARTCARD_REMOVE_ACTION_FORCE_LOGOUT, -} MsdSmartcardRemoveAction; - -#define SCREENSAVER_DBUS_NAME "org.mate.ScreenSaver" -#define SCREENSAVER_DBUS_PATH "/" -#define SCREENSAVER_DBUS_INTERFACE "org.mate.ScreenSaver" - -#define SM_DBUS_NAME "org.mate.SessionManager" -#define SM_DBUS_PATH "/org/mate/SessionManager" -#define SM_DBUS_INTERFACE "org.mate.SessionManager" -#define SM_LOGOUT_MODE_FORCE 2 - -#define MSD_SMARTCARD_KEY "/desktop/mate/peripherals/smartcard" -#define KEY_REMOVE_ACTION MSD_SMARTCARD_KEY "/removal_action" - -#define MSD_SMARTCARD_PLUGIN_GET_PRIVATE(object) (G_TYPE_INSTANCE_GET_PRIVATE ((object), MSD_TYPE_SMARTCARD_PLUGIN, MsdSmartcardPluginPrivate)) - -MATE_SETTINGS_PLUGIN_REGISTER (MsdSmartcardPlugin, msd_smartcard_plugin); - -static void -simulate_user_activity (MsdSmartcardPlugin *plugin) -{ - DBusGProxy *screensaver_proxy; - - g_debug ("MsdSmartcardPlugin telling screensaver about smart card insertion"); - screensaver_proxy = dbus_g_proxy_new_for_name (plugin->priv->bus_connection, - SCREENSAVER_DBUS_NAME, - SCREENSAVER_DBUS_PATH, - SCREENSAVER_DBUS_INTERFACE); - - dbus_g_proxy_call_no_reply (screensaver_proxy, - "SimulateUserActivity", - G_TYPE_INVALID, G_TYPE_INVALID); - - g_object_unref (screensaver_proxy); -} - -static void -lock_screen (MsdSmartcardPlugin *plugin) -{ - DBusGProxy *screensaver_proxy; - - g_debug ("MsdSmartcardPlugin telling screensaver to lock screen"); - screensaver_proxy = dbus_g_proxy_new_for_name (plugin->priv->bus_connection, - SCREENSAVER_DBUS_NAME, - SCREENSAVER_DBUS_PATH, - SCREENSAVER_DBUS_INTERFACE); - - dbus_g_proxy_call_no_reply (screensaver_proxy, - "Lock", - G_TYPE_INVALID, G_TYPE_INVALID); - - g_object_unref (screensaver_proxy); -} - -static void -force_logout (MsdSmartcardPlugin *plugin) -{ - DBusGProxy *sm_proxy; - GError *error; - gboolean res; - - g_debug ("MsdSmartcardPlugin telling session manager to force logout"); - sm_proxy = dbus_g_proxy_new_for_name (plugin->priv->bus_connection, - SM_DBUS_NAME, - SM_DBUS_PATH, - SM_DBUS_INTERFACE); - - error = NULL; - res = dbus_g_proxy_call (sm_proxy, - "Logout", - &error, - G_TYPE_UINT, SM_LOGOUT_MODE_FORCE, - G_TYPE_INVALID, G_TYPE_INVALID); - - if (! res) { - g_warning ("MsdSmartcardPlugin Unable to force logout: %s", error->message); - g_error_free (error); - } - - g_object_unref (sm_proxy); -} - -static void -msd_smartcard_plugin_init (MsdSmartcardPlugin *plugin) -{ - plugin->priv = MSD_SMARTCARD_PLUGIN_GET_PRIVATE (plugin); - - g_debug ("MsdSmartcardPlugin initializing"); - - plugin->priv->manager = msd_smartcard_manager_new (NULL); -} - -static void -msd_smartcard_plugin_finalize (GObject *object) -{ - MsdSmartcardPlugin *plugin; - - g_return_if_fail (object != NULL); - g_return_if_fail (MSD_IS_SMARTCARD_PLUGIN (object)); - - g_debug ("MsdSmartcardPlugin finalizing"); - - plugin = MSD_SMARTCARD_PLUGIN (object); - - g_return_if_fail (plugin->priv != NULL); - - if (plugin->priv->manager != NULL) { - g_object_unref (plugin->priv->manager); - } - - G_OBJECT_CLASS (msd_smartcard_plugin_parent_class)->finalize (object); -} - -static void -smartcard_inserted_cb (MsdSmartcardManager *card_monitor, - MsdSmartcard *card, - MsdSmartcardPlugin *plugin) -{ - char *name; - - name = msd_smartcard_get_name (card); - g_debug ("MsdSmartcardPlugin 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 MsdSmartcardRemoveAction -get_configured_remove_action (MsdSmartcardPlugin *plugin) -{ - MateConfClient *client; - char *remove_action_string; - MsdSmartcardRemoveAction remove_action; - - client = mateconf_client_get_default (); - remove_action_string = mateconf_client_get_string (client, - KEY_REMOVE_ACTION, NULL); - - if (remove_action_string == NULL) { - g_warning ("MsdSmartcardPlugin unable to get smartcard remove action"); - remove_action = MSD_SMARTCARD_REMOVE_ACTION_NONE; - } else if (strcmp (remove_action_string, "none") == 0) { - remove_action = MSD_SMARTCARD_REMOVE_ACTION_NONE; - } else if (strcmp (remove_action_string, "lock_screen") == 0) { - remove_action = MSD_SMARTCARD_REMOVE_ACTION_LOCK_SCREEN; - } else if (strcmp (remove_action_string, "force_logout") == 0) { - remove_action = MSD_SMARTCARD_REMOVE_ACTION_FORCE_LOGOUT; - } else { - g_warning ("MsdSmartcardPlugin unknown smartcard remove action"); - remove_action = MSD_SMARTCARD_REMOVE_ACTION_NONE; - } - - g_object_unref (client); - - return remove_action; -} - -static void -process_smartcard_removal (MsdSmartcardPlugin *plugin) -{ - MsdSmartcardRemoveAction remove_action; - - g_debug ("MsdSmartcardPlugin processing smartcard removal"); - remove_action = get_configured_remove_action (plugin); - - switch (remove_action) - { - case MSD_SMARTCARD_REMOVE_ACTION_NONE: - return; - case MSD_SMARTCARD_REMOVE_ACTION_LOCK_SCREEN: - lock_screen (plugin); - break; - case MSD_SMARTCARD_REMOVE_ACTION_FORCE_LOGOUT: - force_logout (plugin); - break; - } -} - -static void -smartcard_removed_cb (MsdSmartcardManager *card_monitor, - MsdSmartcard *card, - MsdSmartcardPlugin *plugin) -{ - - char *name; - - name = msd_smartcard_get_name (card); - g_debug ("MsdSmartcardPlugin smart card '%s' removed", name); - g_free (name); - - if (!msd_smartcard_is_login_card (card)) { - g_debug ("MsdSmartcardPlugin removed smart card was not used to login"); - return; - } - - process_smartcard_removal (plugin); -} - -static void -impl_activate (MateSettingsPlugin *plugin) -{ - GError *error; - MsdSmartcardPlugin *smartcard_plugin = MSD_SMARTCARD_PLUGIN (plugin); - - if (smartcard_plugin->priv->is_active) { - g_debug ("MsdSmartcardPlugin Not activating smartcard plugin, because it's " - "already active"); - return; - } - - if (!user_logged_in_with_smartcard ()) { - g_debug ("MsdSmartcardPlugin Not activating smartcard plugin, because user didn't use " - " smartcard to log in"); - smartcard_plugin->priv->is_active = FALSE; - return; - } - - g_debug ("MsdSmartcardPlugin Activating smartcard plugin"); - - error = NULL; - smartcard_plugin->priv->bus_connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error); - - if (smartcard_plugin->priv->bus_connection == NULL) { - g_warning ("MsdSmartcardPlugin Unable to connect to session bus: %s", error->message); - return; - } - - if (!msd_smartcard_manager_start (smartcard_plugin->priv->manager, &error)) { - g_warning ("MsdSmartcardPlugin 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 (!msd_smartcard_manager_login_card_is_inserted (smartcard_plugin->priv->manager)) { - g_debug ("MsdSmartcardPlugin 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 (MateSettingsPlugin *plugin) -{ - MsdSmartcardPlugin *smartcard_plugin = MSD_SMARTCARD_PLUGIN (plugin); - - if (!smartcard_plugin->priv->is_active) { - g_debug ("MsdSmartcardPlugin Not deactivating smartcard plugin, " - "because it's already inactive"); - return; - } - - g_debug ("MsdSmartcardPlugin Deactivating smartcard plugin"); - - msd_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 -msd_smartcard_plugin_class_init (MsdSmartcardPluginClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - MateSettingsPluginClass *plugin_class = MATE_SETTINGS_PLUGIN_CLASS (klass); - - object_class->finalize = msd_smartcard_plugin_finalize; - - plugin_class->activate = impl_activate; - plugin_class->deactivate = impl_deactivate; - - g_type_class_add_private (klass, sizeof (MsdSmartcardPluginPrivate)); -} diff --git a/plugins/smartcard/gsd-smartcard-plugin.h b/plugins/smartcard/gsd-smartcard-plugin.h deleted file mode 100644 index 206e58d..0000000 --- a/plugins/smartcard/gsd-smartcard-plugin.h +++ /dev/null @@ -1,63 +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 __MSD_SMARTCARD_PLUGIN_H__ -#define __MSD_SMARTCARD_PLUGIN_H__ - -#include -#include -#include - -#include "mate-settings-plugin.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define MSD_TYPE_SMARTCARD_PLUGIN (msd_smartcard_plugin_get_type ()) -#define MSD_SMARTCARD_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), MSD_TYPE_SMARTCARD_PLUGIN, MsdSmartcardPlugin)) -#define MSD_SMARTCARD_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), MSD_TYPE_SMARTCARD_PLUGIN, MsdSmartcardPluginClass)) -#define MSD_IS_SMARTCARD_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), MSD_TYPE_SMARTCARD_PLUGIN)) -#define MSD_IS_SMARTCARD_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), MSD_TYPE_SMARTCARD_PLUGIN)) -#define MSD_SMARTCARD_PLUGIN_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), MSD_TYPE_SMARTCARD_PLUGIN, MsdSmartcardPluginClass)) - -typedef struct MsdSmartcardPluginPrivate MsdSmartcardPluginPrivate; - -typedef struct -{ - MateSettingsPlugin parent; - MsdSmartcardPluginPrivate *priv; -} MsdSmartcardPlugin; - -typedef struct -{ - MateSettingsPluginClass parent_class; -} MsdSmartcardPluginClass; - -GType msd_smartcard_plugin_get_type (void) G_GNUC_CONST; - -/* All the plugins must implement this function */ -G_MODULE_EXPORT GType register_mate_settings_plugin (GTypeModule *module); - -#ifdef __cplusplus -} -#endif - -#endif /* __MSD_SMARTCARD_PLUGIN_H__ */ diff --git a/plugins/smartcard/gsd-smartcard.c b/plugins/smartcard/gsd-smartcard.c deleted file mode 100644 index 9154200..0000000 --- a/plugins/smartcard/gsd-smartcard.c +++ /dev/null @@ -1,555 +0,0 @@ -/* msd-smartcard.c - smartcard object - * - * 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. - */ -#define MSD_SMARTCARD_ENABLE_INTERNAL_API -#include "msd-smartcard.h" - -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include -#include - -struct _MsdSmartcardPrivate { - SECMODModule *module; - MsdSmartcardState state; - - CK_SLOT_ID slot_id; - int slot_series; - - PK11SlotInfo *slot; - char *name; - - CERTCertificate *signing_certificate; - CERTCertificate *encryption_certificate; -}; - -static void msd_smartcard_finalize (GObject *object); -static void msd_smartcard_class_install_signals (MsdSmartcardClass *card_class); -static void msd_smartcard_class_install_properties (MsdSmartcardClass *card_class); -static void msd_smartcard_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec); -static void msd_smartcard_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec); -static void msd_smartcard_set_name (MsdSmartcard *card, const char *name); -static void msd_smartcard_set_slot_id (MsdSmartcard *card, - int slot_id); -static void msd_smartcard_set_slot_series (MsdSmartcard *card, - int slot_series); -static void msd_smartcard_set_module (MsdSmartcard *card, - SECMODModule *module); - -static PK11SlotInfo *msd_smartcard_find_slot_from_id (MsdSmartcard *card, - int slot_id); - -static PK11SlotInfo *msd_smartcard_find_slot_from_card_name (MsdSmartcard *card, - const char *card_name); -#ifndef MSD_SMARTCARD_DEFAULT_SLOT_ID -#define MSD_SMARTCARD_DEFAULT_SLOT_ID ((gulong) -1) -#endif - -#ifndef MSD_SMARTCARD_DEFAULT_SLOT_SERIES -#define MSD_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 msd_smartcard_signals[NUMBER_OF_SIGNALS]; - -G_DEFINE_TYPE (MsdSmartcard, msd_smartcard, G_TYPE_OBJECT); - -static void -msd_smartcard_class_init (MsdSmartcardClass *card_class) -{ - GObjectClass *gobject_class; - - gobject_class = G_OBJECT_CLASS (card_class); - - gobject_class->finalize = msd_smartcard_finalize; - - msd_smartcard_class_install_signals (card_class); - msd_smartcard_class_install_properties (card_class); - - g_type_class_add_private (card_class, - sizeof (MsdSmartcardPrivate)); -} - -static void -msd_smartcard_class_install_signals (MsdSmartcardClass *card_class) -{ - GObjectClass *object_class; - - object_class = G_OBJECT_CLASS (card_class); - - msd_smartcard_signals[INSERTED] = - g_signal_new ("inserted", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (MsdSmartcardClass, - inserted), - NULL, NULL, g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - msd_smartcard_signals[REMOVED] = - g_signal_new ("removed", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (MsdSmartcardClass, - removed), - NULL, NULL, g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); -} - -static void -msd_smartcard_class_install_properties (MsdSmartcardClass *card_class) -{ - GObjectClass *object_class; - GParamSpec *param_spec; - - object_class = G_OBJECT_CLASS (card_class); - object_class->set_property = msd_smartcard_set_property; - object_class->get_property = msd_smartcard_get_property; - - param_spec = g_param_spec_ulong ("slot-id", _("Slot ID"), - _("The slot the card is in"), - 1, G_MAXULONG, - MSD_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, - MSD_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 -msd_smartcard_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MsdSmartcard *card = MSD_SMARTCARD (object); - - switch (prop_id) { - case PROP_NAME: - msd_smartcard_set_name (card, g_value_get_string (value)); - break; - - case PROP_SLOT_ID: - msd_smartcard_set_slot_id (card, - g_value_get_ulong (value)); - break; - - case PROP_SLOT_SERIES: - msd_smartcard_set_slot_series (card, - g_value_get_int (value)); - break; - - case PROP_MODULE: - msd_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 -msd_smartcard_get_slot_id (MsdSmartcard *card) -{ - return card->priv->slot_id; -} - -MsdSmartcardState -msd_smartcard_get_state (MsdSmartcard *card) -{ - return card->priv->state; -} - -char * -msd_smartcard_get_name (MsdSmartcard *card) -{ - return g_strdup (card->priv->name); -} - -gboolean -msd_smartcard_is_login_card (MsdSmartcard *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 -msd_smartcard_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MsdSmartcard *card = MSD_SMARTCARD (object); - - switch (prop_id) { - case PROP_NAME: - g_value_take_string (value, - msd_smartcard_get_name (card)); - break; - - case PROP_SLOT_ID: - g_value_set_ulong (value, - (gulong) msd_smartcard_get_slot_id (card)); - break; - - case PROP_SLOT_SERIES: - g_value_set_int (value, - msd_smartcard_get_slot_series (card)); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -msd_smartcard_set_name (MsdSmartcard *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 = msd_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) { - msd_smartcard_set_slot_id (card, slot_id); - } - - slot_series = PK11_GetSlotSeries (card->priv->slot); - if (slot_series != card->priv->slot_series) { - msd_smartcard_set_slot_series (card, slot_series); - } - - _msd_smartcard_set_state (card, MSD_SMARTCARD_STATE_INSERTED); - } else { - _msd_smartcard_set_state (card, MSD_SMARTCARD_STATE_REMOVED); - } - } - - g_object_notify (G_OBJECT (card), "name"); - } -} - -static void -msd_smartcard_set_slot_id (MsdSmartcard *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 = msd_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))) { - msd_smartcard_set_name (card, card_name); - } - - _msd_smartcard_set_state (card, MSD_SMARTCARD_STATE_INSERTED); - } else { - _msd_smartcard_set_state (card, MSD_SMARTCARD_STATE_REMOVED); - } - } - - g_object_notify (G_OBJECT (card), "slot-id"); - } -} - -static void -msd_smartcard_set_slot_series (MsdSmartcard *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 -msd_smartcard_set_module (MsdSmartcard *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 -msd_smartcard_get_slot_series (MsdSmartcard *card) -{ - return card->priv->slot_series; -} - -static void -msd_smartcard_init (MsdSmartcard *card) -{ - - g_debug ("initializing smartcard "); - - card->priv = G_TYPE_INSTANCE_GET_PRIVATE (card, - MSD_TYPE_SMARTCARD, - MsdSmartcardPrivate); - - if (card->priv->slot != NULL) { - card->priv->name = g_strdup (PK11_GetTokenName (card->priv->slot)); - } -} - -static void msd_smartcard_finalize (GObject *object) -{ - MsdSmartcard *card; - GObjectClass *gobject_class; - - card = MSD_SMARTCARD (object); - - g_free (card->priv->name); - - msd_smartcard_set_module (card, NULL); - - gobject_class = G_OBJECT_CLASS (msd_smartcard_parent_class); - - gobject_class->finalize (object); -} - -GQuark msd_smartcard_error_quark (void) -{ - static GQuark error_quark = 0; - - if (error_quark == 0) { - error_quark = g_quark_from_static_string ("msd-smartcard-error-quark"); - } - - return error_quark; -} - -MsdSmartcard * -_msd_smartcard_new (SECMODModule *module, - CK_SLOT_ID slot_id, - int slot_series) -{ - MsdSmartcard *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 = MSD_SMARTCARD (g_object_new (MSD_TYPE_SMARTCARD, - "module", module, - "slot-id", (gulong) slot_id, - "slot-series", slot_series, - NULL)); - return card; -} - -MsdSmartcard * -_msd_smartcard_new_from_name (SECMODModule *module, - const char *name) -{ - MsdSmartcard *card; - - g_return_val_if_fail (module != NULL, NULL); - g_return_val_if_fail (name != NULL, NULL); - - card = MSD_SMARTCARD (g_object_new (MSD_TYPE_SMARTCARD, - "module", module, - "name", name, - NULL)); - return card; -} - -void -_msd_smartcard_set_state (MsdSmartcard *card, - MsdSmartcardState state) -{ - if (card->priv->state != state) { - card->priv->state = state; - - if (state == MSD_SMARTCARD_STATE_INSERTED) { - g_signal_emit (card, msd_smartcard_signals[INSERTED], 0); - } else if (state == MSD_SMARTCARD_STATE_REMOVED) { - g_signal_emit (card, msd_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 * -msd_smartcard_password_handler (PK11SlotInfo *slot, - PRBool is_retrying, - const char *password) -{ - if (is_retrying) { - return NULL; - } - - return password != NULL? PL_strdup (password): NULL; -} - -gboolean -msd_smartcard_unlock (MsdSmartcard *card, - const char *password) -{ - SECStatus status; - - PK11_SetPasswordFunc ((PK11PasswordFunc) msd_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 * -msd_smartcard_find_slot_from_card_name (MsdSmartcard *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 * -msd_smartcard_find_slot_from_id (MsdSmartcard *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 d00b8af..0000000 --- a/plugins/smartcard/gsd-smartcard.h +++ /dev/null @@ -1,98 +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 MSD_SMARTCARD_H -#define MSD_SMARTCARD_H - -#include -#include - -#include - -#ifdef __cplusplus -extern "C" { -#endif -#define MSD_TYPE_SMARTCARD (msd_smartcard_get_type ()) -#define MSD_SMARTCARD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MSD_TYPE_SMARTCARD, MsdSmartcard)) -#define MSD_SMARTCARD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MSD_TYPE_SMARTCARD, MsdSmartcardClass)) -#define MSD_IS_SMARTCARD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MSD_TYPE_SMARTCARD)) -#define MSD_IS_SMARTCARD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MSD_TYPE_SMARTCARD)) -#define MSD_SMARTCARD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), MSD_TYPE_SMARTCARD, MsdSmartcardClass)) -#define MSD_SMARTCARD_ERROR (msd_smartcard_error_quark ()) -typedef struct _MsdSmartcardClass MsdSmartcardClass; -typedef struct _MsdSmartcard MsdSmartcard; -typedef struct _MsdSmartcardPrivate MsdSmartcardPrivate; -typedef enum _MsdSmartcardError MsdSmartcardError; -typedef enum _MsdSmartcardState MsdSmartcardState; - -typedef struct _MsdSmartcardRequest MsdSmartcardRequest; - -struct _MsdSmartcard { - GObject parent; - - /*< private > */ - MsdSmartcardPrivate *priv; -}; - -struct _MsdSmartcardClass { - GObjectClass parent_class; - - void (* inserted) (MsdSmartcard *card); - void (* removed) (MsdSmartcard *card); -}; - -enum _MsdSmartcardError { - MSD_SMARTCARD_ERROR_GENERIC = 0, -}; - -enum _MsdSmartcardState { - MSD_SMARTCARD_STATE_INSERTED = 0, - MSD_SMARTCARD_STATE_REMOVED, -}; - -GType msd_smartcard_get_type (void) G_GNUC_CONST; -GQuark msd_smartcard_error_quark (void) G_GNUC_CONST; - -CK_SLOT_ID msd_smartcard_get_slot_id (MsdSmartcard *card); -gint msd_smartcard_get_slot_series (MsdSmartcard *card); -MsdSmartcardState msd_smartcard_get_state (MsdSmartcard *card); - -char *msd_smartcard_get_name (MsdSmartcard *card); -gboolean msd_smartcard_is_login_card (MsdSmartcard *card); - -gboolean msd_smartcard_unlock (MsdSmartcard *card, - const char *password); - -/* don't under any circumstances call these functions */ -#ifdef MSD_SMARTCARD_ENABLE_INTERNAL_API - -MsdSmartcard *_msd_smartcard_new (SECMODModule *module, - CK_SLOT_ID slot_id, - gint slot_series); -MsdSmartcard *_msd_smartcard_new_from_name (SECMODModule *module, - const char *name); - -void _msd_smartcard_set_state (MsdSmartcard *card, - MsdSmartcardState state); -#endif - -#ifdef __cplusplus -} -#endif -#endif /* MSD_SMARTCARD_H */ diff --git a/plugins/smartcard/msd-smartcard-manager.c b/plugins/smartcard/msd-smartcard-manager.c new file mode 100644 index 0000000..ed823f4 --- /dev/null +++ b/plugins/smartcard/msd-smartcard-manager.c @@ -0,0 +1,1372 @@ +/* msd-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 "msd-smartcard-manager.h" + +#define SMARTCARD_ENABLE_INTERNAL_API +#include "msd-smartcard.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#ifndef MSD_SMARTCARD_MANAGER_NSS_DB +#define MSD_SMARTCARD_MANAGER_NSS_DB SYSCONFDIR"/pki/nssdb" +#endif + +typedef enum _MsdSmartcardManagerState MsdSmartcardManagerState; +typedef struct _MsdSmartcardManagerWorker MsdSmartcardManagerWorker; + +enum _MsdSmartcardManagerState { + MSD_SMARTCARD_MANAGER_STATE_STOPPED = 0, + MSD_SMARTCARD_MANAGER_STATE_STARTING, + MSD_SMARTCARD_MANAGER_STATE_STARTED, + MSD_SMARTCARD_MANAGER_STATE_STOPPING, +}; + +struct _MsdSmartcardManagerPrivate { + MsdSmartcardManagerState state; + SECMODModule *module; + char *module_path; + + GSource *smartcard_event_source; + GPid smartcard_event_watcher_pid; + GHashTable *smartcards; + + GThread *worker_thread; + + guint poll_timeout_id; + + guint32 is_unstoppable : 1; + guint32 nss_is_loaded : 1; +}; + +struct _MsdSmartcardManagerWorker { + SECMODModule *module; + GHashTable *smartcards; + int write_fd; + + guint32 nss_is_loaded : 1; +}; + +static void msd_smartcard_manager_finalize (GObject *object); +static void msd_smartcard_manager_class_install_signals (MsdSmartcardManagerClass *service_class); +static void msd_smartcard_manager_class_install_properties (MsdSmartcardManagerClass *service_class); +static void msd_smartcard_manager_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec); +static void msd_smartcard_manager_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec); +static void msd_smartcard_manager_set_module_path (MsdSmartcardManager *manager, + const char *module_path); +static void msd_smartcard_manager_card_removed_handler (MsdSmartcardManager *manager, + MsdSmartcard *card); +static void msd_smartcard_manager_card_inserted_handler (MsdSmartcardManager *manager_class, + MsdSmartcard *card); +static gboolean msd_smartcard_manager_stop_now (MsdSmartcardManager *manager); +static void msd_smartcard_manager_queue_stop (MsdSmartcardManager *manager); + +static gboolean msd_smartcard_manager_create_worker (MsdSmartcardManager *manager, + int *worker_fd, GThread **worker_thread); + +static MsdSmartcardManagerWorker * msd_smartcard_manager_worker_new (int write_fd); +static void msd_smartcard_manager_worker_free (MsdSmartcardManagerWorker *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 MsdSmartcard *read_smartcard (int fd, SECMODModule *module); +static gboolean write_smartcard (int fd, MsdSmartcard *card); + +enum { + PROP_0 = 0, + PROP_MODULE_PATH, + NUMBER_OF_PROPERTIES +}; + +enum { + SMARTCARD_INSERTED = 0, + SMARTCARD_REMOVED, + ERROR, + NUMBER_OF_SIGNALS +}; + +static guint msd_smartcard_manager_signals[NUMBER_OF_SIGNALS]; + +G_DEFINE_TYPE (MsdSmartcardManager, + msd_smartcard_manager, + G_TYPE_OBJECT); + +static void +msd_smartcard_manager_class_init (MsdSmartcardManagerClass *manager_class) +{ + GObjectClass *gobject_class; + + gobject_class = G_OBJECT_CLASS (manager_class); + + gobject_class->finalize = msd_smartcard_manager_finalize; + + msd_smartcard_manager_class_install_signals (manager_class); + msd_smartcard_manager_class_install_properties (manager_class); + + g_type_class_add_private (manager_class, + sizeof (MsdSmartcardManagerPrivate)); +} + +static void +msd_smartcard_manager_class_install_properties (MsdSmartcardManagerClass *card_class) +{ + GObjectClass *object_class; + GParamSpec *param_spec; + + object_class = G_OBJECT_CLASS (card_class); + object_class->set_property = msd_smartcard_manager_set_property; + object_class->get_property = msd_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 +msd_smartcard_manager_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + MsdSmartcardManager *manager = MSD_SMARTCARD_MANAGER (object); + + switch (prop_id) { + case PROP_MODULE_PATH: + msd_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 +msd_smartcard_manager_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + MsdSmartcardManager *manager = MSD_SMARTCARD_MANAGER (object); + char *module_path; + + switch (prop_id) { + case PROP_MODULE_PATH: + module_path = msd_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 * +msd_smartcard_manager_get_module_path (MsdSmartcardManager *manager) +{ + return manager->priv->module_path; +} + +static void +msd_smartcard_manager_set_module_path (MsdSmartcardManager *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 +msd_smartcard_manager_card_removed_handler (MsdSmartcardManager *manager, + MsdSmartcard *card) +{ + g_debug ("informing smartcard of its removal"); + _msd_smartcard_set_state (card, MSD_SMARTCARD_STATE_REMOVED); + g_debug ("done"); +} + +static void +msd_smartcard_manager_card_inserted_handler (MsdSmartcardManager *manager, + MsdSmartcard *card) +{ + g_debug ("informing smartcard of its insertion"); + + _msd_smartcard_set_state (card, MSD_SMARTCARD_STATE_INSERTED); + g_debug ("done"); + +} + +static void +msd_smartcard_manager_class_install_signals (MsdSmartcardManagerClass *manager_class) +{ + GObjectClass *object_class; + + object_class = G_OBJECT_CLASS (manager_class); + + msd_smartcard_manager_signals[SMARTCARD_INSERTED] = + g_signal_new ("smartcard-inserted", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (MsdSmartcardManagerClass, + smartcard_inserted), + NULL, NULL, g_cclosure_marshal_VOID__POINTER, + G_TYPE_NONE, 1, G_TYPE_POINTER); + manager_class->smartcard_inserted = msd_smartcard_manager_card_inserted_handler; + + msd_smartcard_manager_signals[SMARTCARD_REMOVED] = + g_signal_new ("smartcard-removed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (MsdSmartcardManagerClass, + smartcard_removed), + NULL, NULL, g_cclosure_marshal_VOID__POINTER, + G_TYPE_NONE, 1, G_TYPE_POINTER); + manager_class->smartcard_removed = msd_smartcard_manager_card_removed_handler; + + msd_smartcard_manager_signals[ERROR] = + g_signal_new ("error", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (MsdSmartcardManagerClass, 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 +msd_smartcard_manager_init (MsdSmartcardManager *manager) +{ + g_debug ("initializing smartcard manager"); + + manager->priv = G_TYPE_INSTANCE_GET_PRIVATE (manager, + MSD_TYPE_SMARTCARD_MANAGER, + MsdSmartcardManagerPrivate); + manager->priv->poll_timeout_id = 0; + manager->priv->is_unstoppable = FALSE; + manager->priv->module = NULL; + + manager->priv->smartcards = + g_hash_table_new_full (g_str_hash, + g_str_equal, + (GDestroyNotify) g_free, + (GDestroyNotify) g_object_unref); + + if (!g_thread_supported ()) { + g_thread_init (NULL); + } + +} + +static void +msd_smartcard_manager_finalize (GObject *object) +{ + MsdSmartcardManager *manager; + GObjectClass *gobject_class; + + manager = MSD_SMARTCARD_MANAGER (object); + gobject_class = + G_OBJECT_CLASS (msd_smartcard_manager_parent_class); + + msd_smartcard_manager_stop_now (manager); + + g_hash_table_destroy (manager->priv->smartcards); + manager->priv->smartcards = NULL; + + gobject_class->finalize (object); +} + +GQuark +msd_smartcard_manager_error_quark (void) +{ + static GQuark error_quark = 0; + + if (error_quark == 0) { + error_quark = g_quark_from_static_string ("msd-smartcard-manager-error-quark"); + } + + return error_quark; +} + +MsdSmartcardManager * +msd_smartcard_manager_new (const char *module_path) +{ + MsdSmartcardManager *instance; + + instance = MSD_SMARTCARD_MANAGER (g_object_new (MSD_TYPE_SMARTCARD_MANAGER, + "module-path", module_path, + NULL)); + + return instance; +} + +static void +msd_smartcard_manager_emit_error (MsdSmartcardManager *manager, + GError *error) +{ + manager->priv->is_unstoppable = TRUE; + g_signal_emit (manager, msd_smartcard_manager_signals[ERROR], 0, + error); + manager->priv->is_unstoppable = FALSE; +} + +static void +msd_smartcard_manager_emit_smartcard_inserted (MsdSmartcardManager *manager, + MsdSmartcard *card) +{ + manager->priv->is_unstoppable = TRUE; + g_signal_emit (manager, msd_smartcard_manager_signals[SMARTCARD_INSERTED], 0, + card); + manager->priv->is_unstoppable = FALSE; +} + +static void +msd_smartcard_manager_emit_smartcard_removed (MsdSmartcardManager *manager, + MsdSmartcard *card) +{ + MsdSmartcardManagerState old_state; + + old_state = manager->priv->state; + manager->priv->is_unstoppable = TRUE; + g_signal_emit (manager, msd_smartcard_manager_signals[SMARTCARD_REMOVED], 0, + card); + manager->priv->is_unstoppable = FALSE; +} + +static gboolean +msd_smartcard_manager_check_for_and_process_events (GIOChannel *io_channel, + GIOCondition condition, + MsdSmartcardManager *manager) +{ + MsdSmartcard *card; + gboolean should_stop; + gchar event_type; + char *card_name; + int fd; + + 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)) { + goto out; + } + + fd = g_io_channel_unix_get_fd (io_channel); + + event_type = '\0'; + if (!read_bytes (fd, &event_type, 1)) { + should_stop = TRUE; + goto out; + } + + card = read_smartcard (fd, manager->priv->module); + + if (card == NULL) { + should_stop = TRUE; + goto out; + } + + card_name = msd_smartcard_get_name (card); + + switch (event_type) { + case 'I': + g_hash_table_replace (manager->priv->smartcards, + card_name, card); + card_name = NULL; + + msd_smartcard_manager_emit_smartcard_inserted (manager, card); + card = NULL; + break; + + case 'R': + msd_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 (MSD_SMARTCARD_MANAGER_ERROR, + MSD_SMARTCARD_MANAGER_ERROR_WATCHING_FOR_EVENTS, + "%s", (condition & G_IO_IN) ? g_strerror (errno) : _("received error or hang up from event source")); + + msd_smartcard_manager_emit_error (manager, error); + g_error_free (error); + msd_smartcard_manager_stop_now (manager); + return FALSE; + } + + return TRUE; +} + +static void +msd_smartcard_manager_event_processing_stopped_handler (MsdSmartcardManager *manager) +{ + manager->priv->smartcard_event_source = NULL; + msd_smartcard_manager_stop_now (manager); +} + +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 +msd_smartcard_manager_stop_watching_for_events (MsdSmartcardManager *manager) +{ + if (manager->priv->smartcard_event_source != NULL) { + g_source_destroy (manager->priv->smartcard_event_source); + manager->priv->smartcard_event_source = NULL; + } + + if (manager->priv->worker_thread != NULL) { + SECMOD_CancelWait (manager->priv->module); + manager->priv->worker_thread = NULL; + } +} + +static gboolean +load_nss (GError **error) +{ + SECStatus status = SECSuccess; + static const guint32 flags = + NSS_INIT_READONLY | NSS_INIT_NOCERTDB | NSS_INIT_NOMODDB | + NSS_INIT_FORCEOPEN | NSS_INIT_NOROOTINIT | + NSS_INIT_OPTIMIZESPACE | NSS_INIT_PK11RELOAD; + + g_debug ("attempting to load NSS database '%s'", + MSD_SMARTCARD_MANAGER_NSS_DB); + + status = NSS_Initialize (MSD_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, + MSD_SMARTCARD_MANAGER_ERROR, + MSD_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, + MSD_SMARTCARD_MANAGER_ERROR, + MSD_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 SECMODModule * +load_driver (char *module_path, + GError **error) +{ + SECMODModule *module; + char *module_spec; + gboolean module_explicitly_specified; + + g_debug ("attempting to load driver..."); + + module = NULL; + module_explicitly_specified = module_path != NULL; + if (module_explicitly_specified) { + 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; + + } else { + SECMODModuleList *modules, *tmp; + + modules = SECMOD_GetDefaultModuleList (); + + for (tmp = modules; tmp != NULL; tmp = tmp->next) { + if (!SECMOD_HasRemovableSlots (tmp->module) || + !tmp->module->loaded) + continue; + + module = SECMOD_ReferenceModule (tmp->module); + break; + } + } + + if (!module_explicitly_specified && module == NULL) { + g_set_error (error, + MSD_SMARTCARD_MANAGER_ERROR, + MSD_SMARTCARD_MANAGER_ERROR_LOADING_DRIVER, + _("no suitable smartcard driver could be found")); + } else if (module == NULL || !module->loaded) { + + gsize error_message_size; + char *error_message; + + if (module != NULL && !module->loaded) { + g_debug ("module found but not loaded?!"); + SECMOD_DestroyModule (module); + module = NULL; + } + + 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, + MSD_SMARTCARD_MANAGER_ERROR, + MSD_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, + MSD_SMARTCARD_MANAGER_ERROR, + MSD_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); + } + +out: + return module; +} + +static void +msd_smartcard_manager_get_all_cards (MsdSmartcardManager *manager) +{ + int i; + + for (i = 0; i < manager->priv->module->slotCount; i++) { + MsdSmartcard *card; + CK_SLOT_ID slot_id; + int slot_series; + char *card_name; + + slot_id = PK11_GetSlotID (manager->priv->module->slots[i]); + slot_series = PK11_GetSlotSeries (manager->priv->module->slots[i]); + + card = _msd_smartcard_new (manager->priv->module, + slot_id, slot_series); + + card_name = msd_smartcard_get_name (card); + + g_hash_table_replace (manager->priv->smartcards, + card_name, card); + } +} + +gboolean +msd_smartcard_manager_start (MsdSmartcardManager *manager, + GError **error) +{ + GError *watching_error; + int worker_fd; + GPid worker_pid; + GIOChannel *io_channel; + GSource *source; + GIOFlags channel_flags; + GError *nss_error; + + if (manager->priv->state == MSD_SMARTCARD_MANAGER_STATE_STARTED) { + g_debug ("smartcard manager already started"); + return TRUE; + } + + manager->priv->state = MSD_SMARTCARD_MANAGER_STATE_STARTING; + + worker_fd = -1; + worker_pid = 0; + + 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->module == NULL) { + manager->priv->module = load_driver (manager->priv->module_path, &nss_error); + } + + if (manager->priv->module == NULL) { + g_propagate_error (error, nss_error); + goto out; + } + + if (!msd_smartcard_manager_create_worker (manager, &worker_fd, &manager->priv->worker_thread)) { + + g_set_error (error, + MSD_SMARTCARD_MANAGER_ERROR, + MSD_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_fd); + + channel_flags = g_io_channel_get_flags (io_channel); + watching_error = NULL; + + source = g_io_create_watch (io_channel, G_IO_IN | G_IO_HUP); + g_io_channel_unref (io_channel); + io_channel = NULL; + + manager->priv->smartcard_event_source = source; + + g_source_set_callback (manager->priv->smartcard_event_source, + (GSourceFunc) (GIOFunc) + msd_smartcard_manager_check_for_and_process_events, + manager, + (GDestroyNotify) + msd_smartcard_manager_event_processing_stopped_handler); + g_source_attach (manager->priv->smartcard_event_source, NULL); + g_source_unref (manager->priv->smartcard_event_source); + + /* populate the hash with cards that are already inserted + */ + msd_smartcard_manager_get_all_cards (manager); + + manager->priv->state = MSD_SMARTCARD_MANAGER_STATE_STARTED; + +out: + /* don't leave it in a half started state + */ + if (manager->priv->state != MSD_SMARTCARD_MANAGER_STATE_STARTED) { + g_debug ("smartcard manager could not be completely started"); + msd_smartcard_manager_stop (manager); + } else { + g_debug ("smartcard manager started"); + } + + return manager->priv->state == MSD_SMARTCARD_MANAGER_STATE_STARTED; +} + +static gboolean +msd_smartcard_manager_stop_now (MsdSmartcardManager *manager) +{ + if (manager->priv->state == MSD_SMARTCARD_MANAGER_STATE_STOPPED) { + return FALSE; + } + + manager->priv->state = MSD_SMARTCARD_MANAGER_STATE_STOPPED; + msd_smartcard_manager_stop_watching_for_events (manager); + + if (manager->priv->module != NULL) { + SECMOD_DestroyModule (manager->priv->module); + manager->priv->module = NULL; + } + + if (manager->priv->nss_is_loaded) { + NSS_Shutdown (); + manager->priv->nss_is_loaded = FALSE; + } + + g_debug ("smartcard manager stopped"); + + return FALSE; +} + +static void +msd_smartcard_manager_queue_stop (MsdSmartcardManager *manager) +{ + + manager->priv->state = MSD_SMARTCARD_MANAGER_STATE_STOPPING; + + g_idle_add ((GSourceFunc) msd_smartcard_manager_stop_now, manager); +} + +void +msd_smartcard_manager_stop (MsdSmartcardManager *manager) +{ + if (manager->priv->state == MSD_SMARTCARD_MANAGER_STATE_STOPPED) { + return; + } + + if (manager->priv->is_unstoppable) { + msd_smartcard_manager_queue_stop (manager); + return; + } + + msd_smartcard_manager_stop_now (manager); +} + +static void +msd_smartcard_manager_check_for_login_card (CK_SLOT_ID slot_id, + MsdSmartcard *card, + gboolean *is_inserted) +{ + g_assert (is_inserted != NULL); + + if (msd_smartcard_is_login_card (card)) { + *is_inserted = TRUE; + } + +} + +gboolean +msd_smartcard_manager_login_card_is_inserted (MsdSmartcardManager *manager) + +{ + gboolean is_inserted; + + is_inserted = FALSE; + g_hash_table_foreach (manager->priv->smartcards, + (GHFunc) + msd_smartcard_manager_check_for_login_card, + &is_inserted); + return is_inserted; +} + +static MsdSmartcardManagerWorker * +msd_smartcard_manager_worker_new (int write_fd) +{ + MsdSmartcardManagerWorker *worker; + + worker = g_slice_new0 (MsdSmartcardManagerWorker); + worker->write_fd = write_fd; + worker->module = NULL; + + 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 +msd_smartcard_manager_worker_free (MsdSmartcardManagerWorker *worker) +{ + if (worker->smartcards != NULL) { + g_hash_table_destroy (worker->smartcards); + worker->smartcards = NULL; + } + + g_slice_free (MsdSmartcardManagerWorker, 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 MsdSmartcard * +read_smartcard (int fd, + SECMODModule *module) +{ + MsdSmartcard *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 = _msd_smartcard_new_from_name (module, card_name); + g_slice_free1 (card_name_size, card_name); + + return card; +} + +static gboolean +write_smartcard (int fd, + MsdSmartcard *card) +{ + gsize card_name_size; + char *card_name; + + card_name = msd_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 +msd_smartcard_manager_worker_emit_smartcard_removed (MsdSmartcardManagerWorker *worker, + MsdSmartcard *card, + GError **error) +{ + g_debug ("card '%s' removed!", msd_smartcard_get_name (card)); + + if (!write_bytes (worker->write_fd, "R", 1)) { + goto error_out; + } + + if (!write_smartcard (worker->write_fd, card)) { + goto error_out; + } + + return TRUE; + +error_out: + g_set_error (error, MSD_SMARTCARD_MANAGER_ERROR, + MSD_SMARTCARD_MANAGER_ERROR_REPORTING_EVENTS, + "%s", g_strerror (errno)); + return FALSE; +} + +static gboolean +msd_smartcard_manager_worker_emit_smartcard_inserted (MsdSmartcardManagerWorker *worker, + MsdSmartcard *card, + GError **error) +{ + GError *write_error; + + write_error = NULL; + g_debug ("card '%s' inserted!", msd_smartcard_get_name (card)); + if (!write_bytes (worker->write_fd, "I", 1)) { + goto error_out; + } + + if (!write_smartcard (worker->write_fd, card)) { + goto error_out; + } + + return TRUE; + +error_out: + g_set_error (error, MSD_SMARTCARD_MANAGER_ERROR, + MSD_SMARTCARD_MANAGER_ERROR_REPORTING_EVENTS, + "%s", g_strerror (errno)); + return FALSE; +} + +static gboolean +msd_smartcard_manager_worker_watch_for_and_process_event (MsdSmartcardManagerWorker *worker, + GError **error) +{ + PK11SlotInfo *slot; + CK_SLOT_ID slot_id, *key; + int slot_series, card_slot_series; + MsdSmartcard *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, MSD_SMARTCARD_MANAGER_ERROR, + MSD_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 = msd_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 (!msd_smartcard_manager_worker_emit_smartcard_removed (worker, card, &processing_error)) { + g_propagate_error (error, processing_error); + goto out; + } + } + + card = _msd_smartcard_new (worker->module, + slot_id, slot_series); + + g_hash_table_replace (worker->smartcards, + key, card); + key = NULL; + + if (!msd_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 (!msd_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 = _msd_smartcard_new (worker->module, + slot_id, slot_series); + g_hash_table_replace (worker->smartcards, + key, card); + key = NULL; + if (!msd_smartcard_manager_worker_emit_smartcard_inserted (worker, card, &processing_error)) { + g_propagate_error (error, processing_error); + goto out; + } + } + + if (!msd_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 +msd_smartcard_manager_worker_run (MsdSmartcardManagerWorker *worker) +{ + GError *error; + + + error = NULL; + + while (msd_smartcard_manager_worker_watch_for_and_process_event (worker, &error)); + + if (error != NULL) { + g_debug ("could not process card event - %s", error->message); + g_error_free (error); + } + + msd_smartcard_manager_worker_free (worker); +} + +static gboolean +msd_smartcard_manager_create_worker (MsdSmartcardManager *manager, + int *worker_fd, + GThread **worker_thread) +{ + MsdSmartcardManagerWorker *worker; + int write_fd, read_fd; + + write_fd = -1; + read_fd = -1; + if (!open_pipe (&write_fd, &read_fd)) { + return FALSE; + } + + worker = msd_smartcard_manager_worker_new (write_fd); + worker->module = manager->priv->module; + + *worker_thread = g_thread_create ((GThreadFunc) + msd_smartcard_manager_worker_run, + worker, FALSE, NULL); + + if (*worker_thread == NULL) { + msd_smartcard_manager_worker_free (worker); + return FALSE; + } + + if (worker_fd) { + *worker_fd = read_fd; + } + + return TRUE; +} + +#ifdef MSD_SMARTCARD_MANAGER_ENABLE_TEST +#include + +static GMainLoop *event_loop; +static gboolean should_exit_on_next_remove = FALSE; + +static gboolean +on_timeout (MsdSmartcardManager *manager) +{ + GError *error; + g_print ("Re-enabling manager.\n"); + + if (!msd_smartcard_manager_start (manager, &error)) { + g_warning ("could not start smartcard manager - %s", + error->message); + g_error_free (error); + return 1; + } + g_print ("Please re-insert smartcard\n"); + + should_exit_on_next_remove = TRUE; + + return FALSE; +} + +static void +on_device_inserted (MsdSmartcardManager *manager, + MsdSmartcard *card) +{ + g_print ("smartcard inserted!\n"); + g_print ("Please remove it.\n"); +} + +static void +on_device_removed (MsdSmartcardManager *manager, + MsdSmartcard *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"); + msd_smartcard_manager_stop (manager); + g_timeout_add (2000, (GSourceFunc) on_timeout, manager); + } +} + +int +main (int argc, + char *argv[]) +{ + MsdSmartcardManager *manager; + GError *error; + + g_log_set_always_fatal (G_LOG_LEVEL_ERROR + | G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING); + + g_type_init (); + + g_message ("creating instance of 'smartcard manager' object..."); + manager = msd_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 (!msd_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/msd-smartcard-manager.h b/plugins/smartcard/msd-smartcard-manager.h new file mode 100644 index 0000000..269e1da --- /dev/null +++ b/plugins/smartcard/msd-smartcard-manager.h @@ -0,0 +1,90 @@ +/* msd-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 MSD_SMARTCARD_MANAGER_H +#define MSD_SMARTCARD_MANAGER_H + +#define MSD_SMARTCARD_ENABLE_INTERNAL_API +#include "msd-smartcard.h" + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif +#define MSD_TYPE_SMARTCARD_MANAGER (msd_smartcard_manager_get_type ()) +#define MSD_SMARTCARD_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MSD_TYPE_SMARTCARD_MANAGER, MsdSmartcardManager)) +#define MSD_SMARTCARD_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MSD_TYPE_SMARTCARD_MANAGER, MsdSmartcardManagerClass)) +#define MSD_IS_SMARTCARD_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SC_TYPE_SMARTCARD_MANAGER)) +#define MSD_IS_SMARTCARD_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SC_TYPE_SMARTCARD_MANAGER)) +#define MSD_SMARTCARD_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), MSD_TYPE_SMARTCARD_MANAGER, MsdSmartcardManagerClass)) +#define MSD_SMARTCARD_MANAGER_ERROR (msd_smartcard_manager_error_quark ()) +typedef struct _MsdSmartcardManager MsdSmartcardManager; +typedef struct _MsdSmartcardManagerClass MsdSmartcardManagerClass; +typedef struct _MsdSmartcardManagerPrivate MsdSmartcardManagerPrivate; +typedef enum _MsdSmartcardManagerError MsdSmartcardManagerError; + +struct _MsdSmartcardManager { + GObject parent; + + /*< private > */ + MsdSmartcardManagerPrivate *priv; +}; + +struct _MsdSmartcardManagerClass { + GObjectClass parent_class; + + /* Signals */ + void (*smartcard_inserted) (MsdSmartcardManager *manager, + MsdSmartcard *token); + void (*smartcard_removed) (MsdSmartcardManager *manager, + MsdSmartcard *token); + void (*error) (MsdSmartcardManager *manager, + GError *error); +}; + +enum _MsdSmartcardManagerError { + MSD_SMARTCARD_MANAGER_ERROR_GENERIC = 0, + MSD_SMARTCARD_MANAGER_ERROR_WITH_NSS, + MSD_SMARTCARD_MANAGER_ERROR_LOADING_DRIVER, + MSD_SMARTCARD_MANAGER_ERROR_WATCHING_FOR_EVENTS, + MSD_SMARTCARD_MANAGER_ERROR_REPORTING_EVENTS +}; + +GType msd_smartcard_manager_get_type (void) G_GNUC_CONST; +GQuark msd_smartcard_manager_error_quark (void) G_GNUC_CONST; + +MsdSmartcardManager *msd_smartcard_manager_new (const char *module); + +gboolean msd_smartcard_manager_start (MsdSmartcardManager *manager, + GError **error); + +void msd_smartcard_manager_stop (MsdSmartcardManager *manager); + +char *msd_smartcard_manager_get_module_path (MsdSmartcardManager *manager); +gboolean msd_smartcard_manager_login_card_is_inserted (MsdSmartcardManager *manager); + +#ifdef __cplusplus +} +#endif +#endif /* MSD_SMARTCARD_MANAGER_H */ diff --git a/plugins/smartcard/msd-smartcard-plugin.c b/plugins/smartcard/msd-smartcard-plugin.c new file mode 100644 index 0000000..dc4cb8f --- /dev/null +++ b/plugins/smartcard/msd-smartcard-plugin.c @@ -0,0 +1,340 @@ +/* -*- 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 +#include + +#include +#include + +#include + +#include + +#include "mate-settings-plugin.h" +#include "msd-smartcard-plugin.h" +#include "msd-smartcard-manager.h" + +struct MsdSmartcardPluginPrivate { + MsdSmartcardManager *manager; + DBusGConnection *bus_connection; + + guint32 is_active : 1; +}; + +typedef enum +{ + MSD_SMARTCARD_REMOVE_ACTION_NONE, + MSD_SMARTCARD_REMOVE_ACTION_LOCK_SCREEN, + MSD_SMARTCARD_REMOVE_ACTION_FORCE_LOGOUT, +} MsdSmartcardRemoveAction; + +#define SCREENSAVER_DBUS_NAME "org.mate.ScreenSaver" +#define SCREENSAVER_DBUS_PATH "/" +#define SCREENSAVER_DBUS_INTERFACE "org.mate.ScreenSaver" + +#define SM_DBUS_NAME "org.mate.SessionManager" +#define SM_DBUS_PATH "/org/mate/SessionManager" +#define SM_DBUS_INTERFACE "org.mate.SessionManager" +#define SM_LOGOUT_MODE_FORCE 2 + +#define MSD_SMARTCARD_KEY "/desktop/mate/peripherals/smartcard" +#define KEY_REMOVE_ACTION MSD_SMARTCARD_KEY "/removal_action" + +#define MSD_SMARTCARD_PLUGIN_GET_PRIVATE(object) (G_TYPE_INSTANCE_GET_PRIVATE ((object), MSD_TYPE_SMARTCARD_PLUGIN, MsdSmartcardPluginPrivate)) + +MATE_SETTINGS_PLUGIN_REGISTER (MsdSmartcardPlugin, msd_smartcard_plugin); + +static void +simulate_user_activity (MsdSmartcardPlugin *plugin) +{ + DBusGProxy *screensaver_proxy; + + g_debug ("MsdSmartcardPlugin telling screensaver about smart card insertion"); + screensaver_proxy = dbus_g_proxy_new_for_name (plugin->priv->bus_connection, + SCREENSAVER_DBUS_NAME, + SCREENSAVER_DBUS_PATH, + SCREENSAVER_DBUS_INTERFACE); + + dbus_g_proxy_call_no_reply (screensaver_proxy, + "SimulateUserActivity", + G_TYPE_INVALID, G_TYPE_INVALID); + + g_object_unref (screensaver_proxy); +} + +static void +lock_screen (MsdSmartcardPlugin *plugin) +{ + DBusGProxy *screensaver_proxy; + + g_debug ("MsdSmartcardPlugin telling screensaver to lock screen"); + screensaver_proxy = dbus_g_proxy_new_for_name (plugin->priv->bus_connection, + SCREENSAVER_DBUS_NAME, + SCREENSAVER_DBUS_PATH, + SCREENSAVER_DBUS_INTERFACE); + + dbus_g_proxy_call_no_reply (screensaver_proxy, + "Lock", + G_TYPE_INVALID, G_TYPE_INVALID); + + g_object_unref (screensaver_proxy); +} + +static void +force_logout (MsdSmartcardPlugin *plugin) +{ + DBusGProxy *sm_proxy; + GError *error; + gboolean res; + + g_debug ("MsdSmartcardPlugin telling session manager to force logout"); + sm_proxy = dbus_g_proxy_new_for_name (plugin->priv->bus_connection, + SM_DBUS_NAME, + SM_DBUS_PATH, + SM_DBUS_INTERFACE); + + error = NULL; + res = dbus_g_proxy_call (sm_proxy, + "Logout", + &error, + G_TYPE_UINT, SM_LOGOUT_MODE_FORCE, + G_TYPE_INVALID, G_TYPE_INVALID); + + if (! res) { + g_warning ("MsdSmartcardPlugin Unable to force logout: %s", error->message); + g_error_free (error); + } + + g_object_unref (sm_proxy); +} + +static void +msd_smartcard_plugin_init (MsdSmartcardPlugin *plugin) +{ + plugin->priv = MSD_SMARTCARD_PLUGIN_GET_PRIVATE (plugin); + + g_debug ("MsdSmartcardPlugin initializing"); + + plugin->priv->manager = msd_smartcard_manager_new (NULL); +} + +static void +msd_smartcard_plugin_finalize (GObject *object) +{ + MsdSmartcardPlugin *plugin; + + g_return_if_fail (object != NULL); + g_return_if_fail (MSD_IS_SMARTCARD_PLUGIN (object)); + + g_debug ("MsdSmartcardPlugin finalizing"); + + plugin = MSD_SMARTCARD_PLUGIN (object); + + g_return_if_fail (plugin->priv != NULL); + + if (plugin->priv->manager != NULL) { + g_object_unref (plugin->priv->manager); + } + + G_OBJECT_CLASS (msd_smartcard_plugin_parent_class)->finalize (object); +} + +static void +smartcard_inserted_cb (MsdSmartcardManager *card_monitor, + MsdSmartcard *card, + MsdSmartcardPlugin *plugin) +{ + char *name; + + name = msd_smartcard_get_name (card); + g_debug ("MsdSmartcardPlugin 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 MsdSmartcardRemoveAction +get_configured_remove_action (MsdSmartcardPlugin *plugin) +{ + MateConfClient *client; + char *remove_action_string; + MsdSmartcardRemoveAction remove_action; + + client = mateconf_client_get_default (); + remove_action_string = mateconf_client_get_string (client, + KEY_REMOVE_ACTION, NULL); + + if (remove_action_string == NULL) { + g_warning ("MsdSmartcardPlugin unable to get smartcard remove action"); + remove_action = MSD_SMARTCARD_REMOVE_ACTION_NONE; + } else if (strcmp (remove_action_string, "none") == 0) { + remove_action = MSD_SMARTCARD_REMOVE_ACTION_NONE; + } else if (strcmp (remove_action_string, "lock_screen") == 0) { + remove_action = MSD_SMARTCARD_REMOVE_ACTION_LOCK_SCREEN; + } else if (strcmp (remove_action_string, "force_logout") == 0) { + remove_action = MSD_SMARTCARD_REMOVE_ACTION_FORCE_LOGOUT; + } else { + g_warning ("MsdSmartcardPlugin unknown smartcard remove action"); + remove_action = MSD_SMARTCARD_REMOVE_ACTION_NONE; + } + + g_object_unref (client); + + return remove_action; +} + +static void +process_smartcard_removal (MsdSmartcardPlugin *plugin) +{ + MsdSmartcardRemoveAction remove_action; + + g_debug ("MsdSmartcardPlugin processing smartcard removal"); + remove_action = get_configured_remove_action (plugin); + + switch (remove_action) + { + case MSD_SMARTCARD_REMOVE_ACTION_NONE: + return; + case MSD_SMARTCARD_REMOVE_ACTION_LOCK_SCREEN: + lock_screen (plugin); + break; + case MSD_SMARTCARD_REMOVE_ACTION_FORCE_LOGOUT: + force_logout (plugin); + break; + } +} + +static void +smartcard_removed_cb (MsdSmartcardManager *card_monitor, + MsdSmartcard *card, + MsdSmartcardPlugin *plugin) +{ + + char *name; + + name = msd_smartcard_get_name (card); + g_debug ("MsdSmartcardPlugin smart card '%s' removed", name); + g_free (name); + + if (!msd_smartcard_is_login_card (card)) { + g_debug ("MsdSmartcardPlugin removed smart card was not used to login"); + return; + } + + process_smartcard_removal (plugin); +} + +static void +impl_activate (MateSettingsPlugin *plugin) +{ + GError *error; + MsdSmartcardPlugin *smartcard_plugin = MSD_SMARTCARD_PLUGIN (plugin); + + if (smartcard_plugin->priv->is_active) { + g_debug ("MsdSmartcardPlugin Not activating smartcard plugin, because it's " + "already active"); + return; + } + + if (!user_logged_in_with_smartcard ()) { + g_debug ("MsdSmartcardPlugin Not activating smartcard plugin, because user didn't use " + " smartcard to log in"); + smartcard_plugin->priv->is_active = FALSE; + return; + } + + g_debug ("MsdSmartcardPlugin Activating smartcard plugin"); + + error = NULL; + smartcard_plugin->priv->bus_connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error); + + if (smartcard_plugin->priv->bus_connection == NULL) { + g_warning ("MsdSmartcardPlugin Unable to connect to session bus: %s", error->message); + return; + } + + if (!msd_smartcard_manager_start (smartcard_plugin->priv->manager, &error)) { + g_warning ("MsdSmartcardPlugin 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 (!msd_smartcard_manager_login_card_is_inserted (smartcard_plugin->priv->manager)) { + g_debug ("MsdSmartcardPlugin 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 (MateSettingsPlugin *plugin) +{ + MsdSmartcardPlugin *smartcard_plugin = MSD_SMARTCARD_PLUGIN (plugin); + + if (!smartcard_plugin->priv->is_active) { + g_debug ("MsdSmartcardPlugin Not deactivating smartcard plugin, " + "because it's already inactive"); + return; + } + + g_debug ("MsdSmartcardPlugin Deactivating smartcard plugin"); + + msd_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 +msd_smartcard_plugin_class_init (MsdSmartcardPluginClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + MateSettingsPluginClass *plugin_class = MATE_SETTINGS_PLUGIN_CLASS (klass); + + object_class->finalize = msd_smartcard_plugin_finalize; + + plugin_class->activate = impl_activate; + plugin_class->deactivate = impl_deactivate; + + g_type_class_add_private (klass, sizeof (MsdSmartcardPluginPrivate)); +} diff --git a/plugins/smartcard/msd-smartcard-plugin.h b/plugins/smartcard/msd-smartcard-plugin.h new file mode 100644 index 0000000..206e58d --- /dev/null +++ b/plugins/smartcard/msd-smartcard-plugin.h @@ -0,0 +1,63 @@ +/* -*- 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 __MSD_SMARTCARD_PLUGIN_H__ +#define __MSD_SMARTCARD_PLUGIN_H__ + +#include +#include +#include + +#include "mate-settings-plugin.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define MSD_TYPE_SMARTCARD_PLUGIN (msd_smartcard_plugin_get_type ()) +#define MSD_SMARTCARD_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), MSD_TYPE_SMARTCARD_PLUGIN, MsdSmartcardPlugin)) +#define MSD_SMARTCARD_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), MSD_TYPE_SMARTCARD_PLUGIN, MsdSmartcardPluginClass)) +#define MSD_IS_SMARTCARD_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), MSD_TYPE_SMARTCARD_PLUGIN)) +#define MSD_IS_SMARTCARD_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), MSD_TYPE_SMARTCARD_PLUGIN)) +#define MSD_SMARTCARD_PLUGIN_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), MSD_TYPE_SMARTCARD_PLUGIN, MsdSmartcardPluginClass)) + +typedef struct MsdSmartcardPluginPrivate MsdSmartcardPluginPrivate; + +typedef struct +{ + MateSettingsPlugin parent; + MsdSmartcardPluginPrivate *priv; +} MsdSmartcardPlugin; + +typedef struct +{ + MateSettingsPluginClass parent_class; +} MsdSmartcardPluginClass; + +GType msd_smartcard_plugin_get_type (void) G_GNUC_CONST; + +/* All the plugins must implement this function */ +G_MODULE_EXPORT GType register_mate_settings_plugin (GTypeModule *module); + +#ifdef __cplusplus +} +#endif + +#endif /* __MSD_SMARTCARD_PLUGIN_H__ */ diff --git a/plugins/smartcard/msd-smartcard.c b/plugins/smartcard/msd-smartcard.c new file mode 100644 index 0000000..9154200 --- /dev/null +++ b/plugins/smartcard/msd-smartcard.c @@ -0,0 +1,555 @@ +/* msd-smartcard.c - smartcard object + * + * 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. + */ +#define MSD_SMARTCARD_ENABLE_INTERNAL_API +#include "msd-smartcard.h" + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +struct _MsdSmartcardPrivate { + SECMODModule *module; + MsdSmartcardState state; + + CK_SLOT_ID slot_id; + int slot_series; + + PK11SlotInfo *slot; + char *name; + + CERTCertificate *signing_certificate; + CERTCertificate *encryption_certificate; +}; + +static void msd_smartcard_finalize (GObject *object); +static void msd_smartcard_class_install_signals (MsdSmartcardClass *card_class); +static void msd_smartcard_class_install_properties (MsdSmartcardClass *card_class); +static void msd_smartcard_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec); +static void msd_smartcard_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec); +static void msd_smartcard_set_name (MsdSmartcard *card, const char *name); +static void msd_smartcard_set_slot_id (MsdSmartcard *card, + int slot_id); +static void msd_smartcard_set_slot_series (MsdSmartcard *card, + int slot_series); +static void msd_smartcard_set_module (MsdSmartcard *card, + SECMODModule *module); + +static PK11SlotInfo *msd_smartcard_find_slot_from_id (MsdSmartcard *card, + int slot_id); + +static PK11SlotInfo *msd_smartcard_find_slot_from_card_name (MsdSmartcard *card, + const char *card_name); +#ifndef MSD_SMARTCARD_DEFAULT_SLOT_ID +#define MSD_SMARTCARD_DEFAULT_SLOT_ID ((gulong) -1) +#endif + +#ifndef MSD_SMARTCARD_DEFAULT_SLOT_SERIES +#define MSD_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 msd_smartcard_signals[NUMBER_OF_SIGNALS]; + +G_DEFINE_TYPE (MsdSmartcard, msd_smartcard, G_TYPE_OBJECT); + +static void +msd_smartcard_class_init (MsdSmartcardClass *card_class) +{ + GObjectClass *gobject_class; + + gobject_class = G_OBJECT_CLASS (card_class); + + gobject_class->finalize = msd_smartcard_finalize; + + msd_smartcard_class_install_signals (card_class); + msd_smartcard_class_install_properties (card_class); + + g_type_class_add_private (card_class, + sizeof (MsdSmartcardPrivate)); +} + +static void +msd_smartcard_class_install_signals (MsdSmartcardClass *card_class) +{ + GObjectClass *object_class; + + object_class = G_OBJECT_CLASS (card_class); + + msd_smartcard_signals[INSERTED] = + g_signal_new ("inserted", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (MsdSmartcardClass, + inserted), + NULL, NULL, g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + msd_smartcard_signals[REMOVED] = + g_signal_new ("removed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (MsdSmartcardClass, + removed), + NULL, NULL, g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); +} + +static void +msd_smartcard_class_install_properties (MsdSmartcardClass *card_class) +{ + GObjectClass *object_class; + GParamSpec *param_spec; + + object_class = G_OBJECT_CLASS (card_class); + object_class->set_property = msd_smartcard_set_property; + object_class->get_property = msd_smartcard_get_property; + + param_spec = g_param_spec_ulong ("slot-id", _("Slot ID"), + _("The slot the card is in"), + 1, G_MAXULONG, + MSD_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, + MSD_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 +msd_smartcard_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + MsdSmartcard *card = MSD_SMARTCARD (object); + + switch (prop_id) { + case PROP_NAME: + msd_smartcard_set_name (card, g_value_get_string (value)); + break; + + case PROP_SLOT_ID: + msd_smartcard_set_slot_id (card, + g_value_get_ulong (value)); + break; + + case PROP_SLOT_SERIES: + msd_smartcard_set_slot_series (card, + g_value_get_int (value)); + break; + + case PROP_MODULE: + msd_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 +msd_smartcard_get_slot_id (MsdSmartcard *card) +{ + return card->priv->slot_id; +} + +MsdSmartcardState +msd_smartcard_get_state (MsdSmartcard *card) +{ + return card->priv->state; +} + +char * +msd_smartcard_get_name (MsdSmartcard *card) +{ + return g_strdup (card->priv->name); +} + +gboolean +msd_smartcard_is_login_card (MsdSmartcard *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 +msd_smartcard_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + MsdSmartcard *card = MSD_SMARTCARD (object); + + switch (prop_id) { + case PROP_NAME: + g_value_take_string (value, + msd_smartcard_get_name (card)); + break; + + case PROP_SLOT_ID: + g_value_set_ulong (value, + (gulong) msd_smartcard_get_slot_id (card)); + break; + + case PROP_SLOT_SERIES: + g_value_set_int (value, + msd_smartcard_get_slot_series (card)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +msd_smartcard_set_name (MsdSmartcard *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 = msd_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) { + msd_smartcard_set_slot_id (card, slot_id); + } + + slot_series = PK11_GetSlotSeries (card->priv->slot); + if (slot_series != card->priv->slot_series) { + msd_smartcard_set_slot_series (card, slot_series); + } + + _msd_smartcard_set_state (card, MSD_SMARTCARD_STATE_INSERTED); + } else { + _msd_smartcard_set_state (card, MSD_SMARTCARD_STATE_REMOVED); + } + } + + g_object_notify (G_OBJECT (card), "name"); + } +} + +static void +msd_smartcard_set_slot_id (MsdSmartcard *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 = msd_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))) { + msd_smartcard_set_name (card, card_name); + } + + _msd_smartcard_set_state (card, MSD_SMARTCARD_STATE_INSERTED); + } else { + _msd_smartcard_set_state (card, MSD_SMARTCARD_STATE_REMOVED); + } + } + + g_object_notify (G_OBJECT (card), "slot-id"); + } +} + +static void +msd_smartcard_set_slot_series (MsdSmartcard *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 +msd_smartcard_set_module (MsdSmartcard *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 +msd_smartcard_get_slot_series (MsdSmartcard *card) +{ + return card->priv->slot_series; +} + +static void +msd_smartcard_init (MsdSmartcard *card) +{ + + g_debug ("initializing smartcard "); + + card->priv = G_TYPE_INSTANCE_GET_PRIVATE (card, + MSD_TYPE_SMARTCARD, + MsdSmartcardPrivate); + + if (card->priv->slot != NULL) { + card->priv->name = g_strdup (PK11_GetTokenName (card->priv->slot)); + } +} + +static void msd_smartcard_finalize (GObject *object) +{ + MsdSmartcard *card; + GObjectClass *gobject_class; + + card = MSD_SMARTCARD (object); + + g_free (card->priv->name); + + msd_smartcard_set_module (card, NULL); + + gobject_class = G_OBJECT_CLASS (msd_smartcard_parent_class); + + gobject_class->finalize (object); +} + +GQuark msd_smartcard_error_quark (void) +{ + static GQuark error_quark = 0; + + if (error_quark == 0) { + error_quark = g_quark_from_static_string ("msd-smartcard-error-quark"); + } + + return error_quark; +} + +MsdSmartcard * +_msd_smartcard_new (SECMODModule *module, + CK_SLOT_ID slot_id, + int slot_series) +{ + MsdSmartcard *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 = MSD_SMARTCARD (g_object_new (MSD_TYPE_SMARTCARD, + "module", module, + "slot-id", (gulong) slot_id, + "slot-series", slot_series, + NULL)); + return card; +} + +MsdSmartcard * +_msd_smartcard_new_from_name (SECMODModule *module, + const char *name) +{ + MsdSmartcard *card; + + g_return_val_if_fail (module != NULL, NULL); + g_return_val_if_fail (name != NULL, NULL); + + card = MSD_SMARTCARD (g_object_new (MSD_TYPE_SMARTCARD, + "module", module, + "name", name, + NULL)); + return card; +} + +void +_msd_smartcard_set_state (MsdSmartcard *card, + MsdSmartcardState state) +{ + if (card->priv->state != state) { + card->priv->state = state; + + if (state == MSD_SMARTCARD_STATE_INSERTED) { + g_signal_emit (card, msd_smartcard_signals[INSERTED], 0); + } else if (state == MSD_SMARTCARD_STATE_REMOVED) { + g_signal_emit (card, msd_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 * +msd_smartcard_password_handler (PK11SlotInfo *slot, + PRBool is_retrying, + const char *password) +{ + if (is_retrying) { + return NULL; + } + + return password != NULL? PL_strdup (password): NULL; +} + +gboolean +msd_smartcard_unlock (MsdSmartcard *card, + const char *password) +{ + SECStatus status; + + PK11_SetPasswordFunc ((PK11PasswordFunc) msd_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 * +msd_smartcard_find_slot_from_card_name (MsdSmartcard *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 * +msd_smartcard_find_slot_from_id (MsdSmartcard *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/msd-smartcard.h b/plugins/smartcard/msd-smartcard.h new file mode 100644 index 0000000..d00b8af --- /dev/null +++ b/plugins/smartcard/msd-smartcard.h @@ -0,0 +1,98 @@ +/* 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 MSD_SMARTCARD_H +#define MSD_SMARTCARD_H + +#include +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif +#define MSD_TYPE_SMARTCARD (msd_smartcard_get_type ()) +#define MSD_SMARTCARD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MSD_TYPE_SMARTCARD, MsdSmartcard)) +#define MSD_SMARTCARD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MSD_TYPE_SMARTCARD, MsdSmartcardClass)) +#define MSD_IS_SMARTCARD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MSD_TYPE_SMARTCARD)) +#define MSD_IS_SMARTCARD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MSD_TYPE_SMARTCARD)) +#define MSD_SMARTCARD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), MSD_TYPE_SMARTCARD, MsdSmartcardClass)) +#define MSD_SMARTCARD_ERROR (msd_smartcard_error_quark ()) +typedef struct _MsdSmartcardClass MsdSmartcardClass; +typedef struct _MsdSmartcard MsdSmartcard; +typedef struct _MsdSmartcardPrivate MsdSmartcardPrivate; +typedef enum _MsdSmartcardError MsdSmartcardError; +typedef enum _MsdSmartcardState MsdSmartcardState; + +typedef struct _MsdSmartcardRequest MsdSmartcardRequest; + +struct _MsdSmartcard { + GObject parent; + + /*< private > */ + MsdSmartcardPrivate *priv; +}; + +struct _MsdSmartcardClass { + GObjectClass parent_class; + + void (* inserted) (MsdSmartcard *card); + void (* removed) (MsdSmartcard *card); +}; + +enum _MsdSmartcardError { + MSD_SMARTCARD_ERROR_GENERIC = 0, +}; + +enum _MsdSmartcardState { + MSD_SMARTCARD_STATE_INSERTED = 0, + MSD_SMARTCARD_STATE_REMOVED, +}; + +GType msd_smartcard_get_type (void) G_GNUC_CONST; +GQuark msd_smartcard_error_quark (void) G_GNUC_CONST; + +CK_SLOT_ID msd_smartcard_get_slot_id (MsdSmartcard *card); +gint msd_smartcard_get_slot_series (MsdSmartcard *card); +MsdSmartcardState msd_smartcard_get_state (MsdSmartcard *card); + +char *msd_smartcard_get_name (MsdSmartcard *card); +gboolean msd_smartcard_is_login_card (MsdSmartcard *card); + +gboolean msd_smartcard_unlock (MsdSmartcard *card, + const char *password); + +/* don't under any circumstances call these functions */ +#ifdef MSD_SMARTCARD_ENABLE_INTERNAL_API + +MsdSmartcard *_msd_smartcard_new (SECMODModule *module, + CK_SLOT_ID slot_id, + gint slot_series); +MsdSmartcard *_msd_smartcard_new_from_name (SECMODModule *module, + const char *name); + +void _msd_smartcard_set_state (MsdSmartcard *card, + MsdSmartcardState state); +#endif + +#ifdef __cplusplus +} +#endif +#endif /* MSD_SMARTCARD_H */ -- cgit v1.2.1