|
Packit |
9ca0cf |
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
|
Packit |
9ca0cf |
*
|
|
Packit |
9ca0cf |
* Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
|
|
Packit |
9ca0cf |
* Copyright (C) 2010,2011 Red Hat, Inc.
|
|
Packit |
9ca0cf |
*
|
|
Packit |
9ca0cf |
* This program is free software; you can redistribute it and/or modify
|
|
Packit |
9ca0cf |
* it under the terms of the GNU General Public License as published by
|
|
Packit |
9ca0cf |
* the Free Software Foundation; either version 2 of the License, or
|
|
Packit |
9ca0cf |
* (at your option) any later version.
|
|
Packit |
9ca0cf |
*
|
|
Packit |
9ca0cf |
* This program is distributed in the hope that it will be useful,
|
|
Packit |
9ca0cf |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
9ca0cf |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit |
9ca0cf |
* GNU General Public License for more details.
|
|
Packit |
9ca0cf |
*
|
|
Packit |
9ca0cf |
* You should have received a copy of the GNU General Public License
|
|
Packit |
9ca0cf |
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
|
Packit |
9ca0cf |
*
|
|
Packit |
9ca0cf |
*/
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
#include "config.h"
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
#include <glib.h>
|
|
Packit |
9ca0cf |
#include <gio/gio.h>
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
#include "gnome-settings-profile.h"
|
|
Packit |
9ca0cf |
#include "gnome-settings-bus.h"
|
|
Packit |
9ca0cf |
#include "gsd-smartcard-manager.h"
|
|
Packit |
9ca0cf |
#include "gsd-smartcard-service.h"
|
|
Packit |
9ca0cf |
#include "gsd-smartcard-enum-types.h"
|
|
Packit |
9ca0cf |
#include "gsd-smartcard-utils.h"
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
#include <prerror.h>
|
|
Packit |
9ca0cf |
#include <prinit.h>
|
|
Packit |
9ca0cf |
#include <nss.h>
|
|
Packit |
9ca0cf |
#include <pk11func.h>
|
|
Packit |
9ca0cf |
#include <secmod.h>
|
|
Packit |
9ca0cf |
#include <secerr.h>
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
#define GSD_SMARTCARD_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_SMARTCARD_MANAGER, GsdSmartcardManagerPrivate))
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
#define GSD_SESSION_MANAGER_LOGOUT_MODE_FORCE 2
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
struct GsdSmartcardManagerPrivate
|
|
Packit |
9ca0cf |
{
|
|
Packit |
9ca0cf |
guint start_idle_id;
|
|
Packit |
9ca0cf |
GsdSmartcardService *service;
|
|
Packit |
9ca0cf |
GList *smartcards_watch_tasks;
|
|
Packit |
9ca0cf |
GCancellable *cancellable;
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
GsdSessionManager *session_manager;
|
|
Packit |
9ca0cf |
GsdScreenSaver *screen_saver;
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
GSettings *settings;
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
NSSInitContext *nss_context;
|
|
Packit |
9ca0cf |
};
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
#define CONF_SCHEMA "org.gnome.settings-daemon.peripherals.smartcard"
|
|
Packit |
9ca0cf |
#define KEY_REMOVE_ACTION "removal-action"
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
static void gsd_smartcard_manager_class_init (GsdSmartcardManagerClass *klass);
|
|
Packit |
9ca0cf |
static void gsd_smartcard_manager_init (GsdSmartcardManager *self);
|
|
Packit |
9ca0cf |
static void gsd_smartcard_manager_finalize (GObject *object);
|
|
Packit |
9ca0cf |
static void lock_screen (GsdSmartcardManager *self);
|
|
Packit |
9ca0cf |
static void log_out (GsdSmartcardManager *self);
|
|
Packit |
9ca0cf |
static void on_smartcards_from_driver_watched (GsdSmartcardManager *self,
|
|
Packit |
9ca0cf |
GAsyncResult *result,
|
|
Packit |
9ca0cf |
GTask *task);
|
|
Packit |
9ca0cf |
G_DEFINE_TYPE (GsdSmartcardManager, gsd_smartcard_manager, G_TYPE_OBJECT)
|
|
Packit |
9ca0cf |
G_DEFINE_QUARK (gsd-smartcard-manager-error, gsd_smartcard_manager_error)
|
|
Packit |
9ca0cf |
G_LOCK_DEFINE_STATIC (gsd_smartcards_watch_tasks);
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
typedef struct {
|
|
Packit |
9ca0cf |
SECMODModule *driver;
|
|
Packit |
9ca0cf |
guint idle_id;
|
|
Packit |
9ca0cf |
GError *error;
|
|
Packit |
9ca0cf |
} DriverRegistrationOperation;
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
static gpointer manager_object = NULL;
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
static void
|
|
Packit |
9ca0cf |
gsd_smartcard_manager_class_init (GsdSmartcardManagerClass *klass)
|
|
Packit |
9ca0cf |
{
|
|
Packit |
9ca0cf |
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
object_class->finalize = gsd_smartcard_manager_finalize;
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
gsd_smartcard_utils_register_error_domain (GSD_SMARTCARD_MANAGER_ERROR,
|
|
Packit |
9ca0cf |
GSD_TYPE_SMARTCARD_MANAGER_ERROR);
|
|
Packit |
9ca0cf |
g_type_class_add_private (klass, sizeof (GsdSmartcardManagerPrivate));
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
static void
|
|
Packit |
9ca0cf |
gsd_smartcard_manager_init (GsdSmartcardManager *self)
|
|
Packit |
9ca0cf |
{
|
|
Packit |
9ca0cf |
self->priv = GSD_SMARTCARD_MANAGER_GET_PRIVATE (self);
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
static void
|
|
Packit |
9ca0cf |
load_nss (GsdSmartcardManager *self)
|
|
Packit |
9ca0cf |
{
|
|
Packit |
9ca0cf |
GsdSmartcardManagerPrivate *priv = self->priv;
|
|
Packit |
9ca0cf |
NSSInitContext *context = NULL;
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
/* The first field in the NSSInitParameters structure
|
|
Packit |
9ca0cf |
* is the size of the structure. NSS requires this, so
|
|
Packit |
9ca0cf |
* that it can change the size of the structure in future
|
|
Packit |
9ca0cf |
* versions of NSS in a detectable way
|
|
Packit |
9ca0cf |
*/
|
|
Packit |
9ca0cf |
NSSInitParameters parameters = { sizeof (parameters), };
|
|
Packit |
9ca0cf |
static const guint32 flags = NSS_INIT_READONLY
|
|
Packit |
9ca0cf |
| NSS_INIT_FORCEOPEN
|
|
Packit |
9ca0cf |
| NSS_INIT_NOROOTINIT
|
|
Packit |
9ca0cf |
| NSS_INIT_OPTIMIZESPACE
|
|
Packit |
9ca0cf |
| NSS_INIT_PK11RELOAD;
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
g_debug ("attempting to load NSS database '%s'",
|
|
Packit |
9ca0cf |
GSD_SMARTCARD_MANAGER_NSS_DB);
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
PR_Init (PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
context = NSS_InitContext (GSD_SMARTCARD_MANAGER_NSS_DB,
|
|
Packit |
9ca0cf |
"", "", SECMOD_DB, ¶meters, flags);
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
if (context == NULL) {
|
|
Packit |
9ca0cf |
gsize error_message_size;
|
|
Packit |
9ca0cf |
char *error_message;
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
error_message_size = PR_GetErrorTextLength ();
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
if (error_message_size == 0) {
|
|
Packit |
9ca0cf |
g_debug ("NSS security system could not be initialized");
|
|
Packit |
9ca0cf |
} else {
|
|
Packit |
9ca0cf |
error_message = g_alloca (error_message_size);
|
|
Packit |
9ca0cf |
PR_GetErrorText (error_message);
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
g_debug ("NSS security system could not be initialized - %s",
|
|
Packit |
9ca0cf |
error_message);
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
priv->nss_context = NULL;
|
|
Packit |
9ca0cf |
return;
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
g_debug ("NSS database '%s' loaded", GSD_SMARTCARD_MANAGER_NSS_DB);
|
|
Packit |
9ca0cf |
priv->nss_context = context;
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
static void
|
|
Packit |
9ca0cf |
unload_nss (GsdSmartcardManager *self)
|
|
Packit |
9ca0cf |
{
|
|
Packit |
9ca0cf |
g_debug ("attempting to unload NSS security system with database '%s'",
|
|
Packit |
9ca0cf |
GSD_SMARTCARD_MANAGER_NSS_DB);
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
if (self->priv->nss_context != NULL) {
|
|
Packit |
9ca0cf |
g_clear_pointer (&self->priv->nss_context,
|
|
Packit |
9ca0cf |
NSS_ShutdownContext);
|
|
Packit |
9ca0cf |
g_debug ("NSS database '%s' unloaded", GSD_SMARTCARD_MANAGER_NSS_DB);
|
|
Packit |
9ca0cf |
} else {
|
|
Packit |
9ca0cf |
g_debug ("NSS database '%s' already not loaded", GSD_SMARTCARD_MANAGER_NSS_DB);
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
typedef struct
|
|
Packit |
9ca0cf |
{
|
|
Packit |
9ca0cf |
SECMODModule *driver;
|
|
Packit |
9ca0cf |
GHashTable *smartcards;
|
|
Packit |
9ca0cf |
int number_of_consecutive_errors;
|
|
Packit |
9ca0cf |
} WatchSmartcardsOperation;
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
static void
|
|
Packit |
9ca0cf |
on_watch_cancelled (GCancellable *cancellable,
|
|
Packit |
9ca0cf |
WatchSmartcardsOperation *operation)
|
|
Packit |
9ca0cf |
{
|
|
Packit |
9ca0cf |
SECMOD_CancelWait (operation->driver);
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
static gboolean
|
|
Packit |
9ca0cf |
watch_one_event_from_driver (GsdSmartcardManager *self,
|
|
Packit |
9ca0cf |
WatchSmartcardsOperation *operation,
|
|
Packit |
9ca0cf |
GCancellable *cancellable,
|
|
Packit |
9ca0cf |
GError **error)
|
|
Packit |
9ca0cf |
{
|
|
Packit |
9ca0cf |
GsdSmartcardManagerPrivate *priv = self->priv;
|
|
Packit Service |
5ac339 |
PK11SlotInfo *card, *old_card;
|
|
Packit |
9ca0cf |
CK_SLOT_ID slot_id;
|
|
Packit |
9ca0cf |
gulong handler_id;
|
|
Packit |
9ca0cf |
int old_slot_series = -1, slot_series;
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
handler_id = g_cancellable_connect (cancellable,
|
|
Packit |
9ca0cf |
G_CALLBACK (on_watch_cancelled),
|
|
Packit |
9ca0cf |
operation,
|
|
Packit |
9ca0cf |
NULL);
|
|
Packit |
9ca0cf |
|
|
Packit Service |
5ac339 |
card = SECMOD_WaitForAnyTokenEvent (operation->driver, 0, PR_SecondsToInterval (1));
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
g_cancellable_disconnect (cancellable, handler_id);
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
if (g_cancellable_set_error_if_cancelled (cancellable, error)) {
|
|
Packit |
9ca0cf |
g_warning ("smartcard event function cancelled");
|
|
Packit |
9ca0cf |
return FALSE;
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
if (card == NULL) {
|
|
Packit |
9ca0cf |
int error_code;
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
error_code = PORT_GetError ();
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
operation->number_of_consecutive_errors++;
|
|
Packit |
9ca0cf |
if (operation->number_of_consecutive_errors > 10) {
|
|
Packit |
9ca0cf |
g_warning ("Got %d consecutive smartcard errors, so giving up.",
|
|
Packit |
9ca0cf |
operation->number_of_consecutive_errors);
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
g_set_error (error,
|
|
Packit |
9ca0cf |
GSD_SMARTCARD_MANAGER_ERROR,
|
|
Packit |
9ca0cf |
GSD_SMARTCARD_MANAGER_ERROR_WITH_NSS,
|
|
Packit |
9ca0cf |
"encountered unexpected error while "
|
|
Packit |
9ca0cf |
"waiting for smartcard events (error %x)",
|
|
Packit |
9ca0cf |
error_code);
|
|
Packit |
9ca0cf |
return FALSE;
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
g_warning ("Got potentially spurious smartcard event error: %x.", error_code);
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
g_usleep (0.5 * G_USEC_PER_SEC);
|
|
Packit |
9ca0cf |
return TRUE;
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
operation->number_of_consecutive_errors = 0;
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
slot_id = PK11_GetSlotID (card);
|
|
Packit |
9ca0cf |
slot_series = PK11_GetSlotSeries (card);
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
old_card = g_hash_table_lookup (operation->smartcards, GINT_TO_POINTER ((int) slot_id));
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
/* If there is a different card in the slot now than
|
|
Packit |
9ca0cf |
* there was before, then we need to emit a removed signal
|
|
Packit |
9ca0cf |
* for the old card
|
|
Packit |
9ca0cf |
*/
|
|
Packit |
9ca0cf |
if (old_card != NULL) {
|
|
Packit |
9ca0cf |
old_slot_series = PK11_GetSlotSeries (old_card);
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
if (old_slot_series != slot_series) {
|
|
Packit |
9ca0cf |
/* Card registered with slot previously is
|
|
Packit |
9ca0cf |
* different than this card, so update its
|
|
Packit |
9ca0cf |
* exported state to track the implicit missed
|
|
Packit |
9ca0cf |
* removal
|
|
Packit |
9ca0cf |
*/
|
|
Packit |
9ca0cf |
gsd_smartcard_service_sync_token (priv->service, old_card, cancellable);
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
g_hash_table_remove (operation->smartcards, GINT_TO_POINTER ((int) slot_id));
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
if (PK11_IsPresent (card)) {
|
|
Packit |
9ca0cf |
g_debug ("Detected smartcard insertion event in slot %d", (int) slot_id);
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
g_hash_table_replace (operation->smartcards,
|
|
Packit |
9ca0cf |
GINT_TO_POINTER ((int) slot_id),
|
|
Packit |
9ca0cf |
PK11_ReferenceSlot (card));
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
gsd_smartcard_service_sync_token (priv->service, card, cancellable);
|
|
Packit |
9ca0cf |
} else if (old_card == NULL) {
|
|
Packit |
9ca0cf |
/* If the just removed smartcard is not known to us then
|
|
Packit |
9ca0cf |
* ignore the removal event. NSS sends a synthentic removal
|
|
Packit |
9ca0cf |
* event for slots that are empty at startup
|
|
Packit |
9ca0cf |
*/
|
|
Packit |
9ca0cf |
g_debug ("Detected slot %d is empty in reader", (int) slot_id);
|
|
Packit |
9ca0cf |
} else {
|
|
Packit |
9ca0cf |
g_debug ("Detected smartcard removal event in slot %d", (int) slot_id);
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
/* If the just removed smartcard is known to us then
|
|
Packit |
9ca0cf |
* we need to update its exported state to reflect the
|
|
Packit |
9ca0cf |
* removal
|
|
Packit |
9ca0cf |
*/
|
|
Packit |
9ca0cf |
if (old_slot_series == slot_series)
|
|
Packit |
9ca0cf |
gsd_smartcard_service_sync_token (priv->service, card, cancellable);
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
PK11_FreeSlot (card);
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
return TRUE;
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
static void
|
|
Packit |
9ca0cf |
watch_smartcards_from_driver (GTask *task,
|
|
Packit |
9ca0cf |
GsdSmartcardManager *self,
|
|
Packit |
9ca0cf |
WatchSmartcardsOperation *operation,
|
|
Packit |
9ca0cf |
GCancellable *cancellable)
|
|
Packit |
9ca0cf |
{
|
|
Packit |
9ca0cf |
g_debug ("watching for smartcard events");
|
|
Packit |
9ca0cf |
while (!g_cancellable_is_cancelled (cancellable)) {
|
|
Packit |
9ca0cf |
gboolean watch_succeeded;
|
|
Packit |
9ca0cf |
GError *error = NULL;
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
watch_succeeded = watch_one_event_from_driver (self, operation, cancellable, &error);
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
if (g_task_return_error_if_cancelled (task)) {
|
|
Packit |
9ca0cf |
break;
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
if (!watch_succeeded) {
|
|
Packit |
9ca0cf |
g_task_return_error (task, error);
|
|
Packit |
9ca0cf |
break;
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
static void
|
|
Packit |
9ca0cf |
destroy_watch_smartcards_operation (WatchSmartcardsOperation *operation)
|
|
Packit |
9ca0cf |
{
|
|
Packit |
9ca0cf |
SECMOD_DestroyModule (operation->driver);
|
|
Packit |
9ca0cf |
g_hash_table_unref (operation->smartcards);
|
|
Packit |
9ca0cf |
g_free (operation);
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
static void
|
|
Packit |
9ca0cf |
on_smartcards_watch_task_destroyed (GsdSmartcardManager *self,
|
|
Packit |
9ca0cf |
GTask *freed_task)
|
|
Packit |
9ca0cf |
{
|
|
Packit |
9ca0cf |
GsdSmartcardManagerPrivate *priv = self->priv;
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
G_LOCK (gsd_smartcards_watch_tasks);
|
|
Packit |
9ca0cf |
priv->smartcards_watch_tasks = g_list_remove (priv->smartcards_watch_tasks,
|
|
Packit |
9ca0cf |
freed_task);
|
|
Packit |
9ca0cf |
G_UNLOCK (gsd_smartcards_watch_tasks);
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
static void
|
|
Packit |
9ca0cf |
sync_initial_tokens_from_driver (GsdSmartcardManager *self,
|
|
Packit |
9ca0cf |
SECMODModule *driver,
|
|
Packit |
9ca0cf |
GHashTable *smartcards,
|
|
Packit |
9ca0cf |
GCancellable *cancellable)
|
|
Packit |
9ca0cf |
{
|
|
Packit |
9ca0cf |
GsdSmartcardManagerPrivate *priv = self->priv;
|
|
Packit |
9ca0cf |
int i;
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
for (i = 0; i < driver->slotCount; i++) {
|
|
Packit |
9ca0cf |
PK11SlotInfo *card;
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
card = driver->slots[i];
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
if (PK11_IsPresent (card)) {
|
|
Packit |
9ca0cf |
CK_SLOT_ID slot_id;
|
|
Packit |
9ca0cf |
slot_id = PK11_GetSlotID (card);
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
g_debug ("Detected smartcard in slot %d at start up", (int) slot_id);
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
g_hash_table_replace (smartcards,
|
|
Packit |
9ca0cf |
GINT_TO_POINTER ((int) slot_id),
|
|
Packit |
9ca0cf |
PK11_ReferenceSlot (card));
|
|
Packit |
9ca0cf |
gsd_smartcard_service_sync_token (priv->service, card, cancellable);
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
static void
|
|
Packit |
9ca0cf |
watch_smartcards_from_driver_async (GsdSmartcardManager *self,
|
|
Packit |
9ca0cf |
SECMODModule *driver,
|
|
Packit |
9ca0cf |
GCancellable *cancellable,
|
|
Packit |
9ca0cf |
GAsyncReadyCallback callback,
|
|
Packit |
9ca0cf |
gpointer user_data)
|
|
Packit |
9ca0cf |
{
|
|
Packit |
9ca0cf |
GsdSmartcardManagerPrivate *priv = self->priv;
|
|
Packit |
9ca0cf |
GTask *task;
|
|
Packit |
9ca0cf |
WatchSmartcardsOperation *operation;
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
operation = g_new0 (WatchSmartcardsOperation, 1);
|
|
Packit |
9ca0cf |
operation->driver = SECMOD_ReferenceModule (driver);
|
|
Packit |
9ca0cf |
operation->smartcards = g_hash_table_new_full (g_direct_hash,
|
|
Packit |
9ca0cf |
g_direct_equal,
|
|
Packit |
9ca0cf |
NULL,
|
|
Packit |
9ca0cf |
(GDestroyNotify) PK11_FreeSlot);
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
task = g_task_new (self, cancellable, callback, user_data);
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
g_task_set_task_data (task,
|
|
Packit |
9ca0cf |
operation,
|
|
Packit |
9ca0cf |
(GDestroyNotify) destroy_watch_smartcards_operation);
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
G_LOCK (gsd_smartcards_watch_tasks);
|
|
Packit |
9ca0cf |
priv->smartcards_watch_tasks = g_list_prepend (priv->smartcards_watch_tasks,
|
|
Packit |
9ca0cf |
task);
|
|
Packit |
9ca0cf |
g_object_weak_ref (G_OBJECT (task),
|
|
Packit |
9ca0cf |
(GWeakNotify) on_smartcards_watch_task_destroyed,
|
|
Packit |
9ca0cf |
self);
|
|
Packit |
9ca0cf |
G_UNLOCK (gsd_smartcards_watch_tasks);
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
sync_initial_tokens_from_driver (self, driver, operation->smartcards, cancellable);
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
g_task_run_in_thread (task, (GTaskThreadFunc) watch_smartcards_from_driver);
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
static gboolean
|
|
Packit |
9ca0cf |
register_driver_finish (GsdSmartcardManager *self,
|
|
Packit |
9ca0cf |
GAsyncResult *result,
|
|
Packit |
9ca0cf |
GError **error)
|
|
Packit |
9ca0cf |
{
|
|
Packit |
9ca0cf |
return g_task_propagate_boolean (G_TASK (result), error);
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
static void
|
|
Packit |
9ca0cf |
on_driver_registered (GsdSmartcardManager *self,
|
|
Packit |
9ca0cf |
GAsyncResult *result,
|
|
Packit |
9ca0cf |
GTask *task)
|
|
Packit |
9ca0cf |
{
|
|
Packit |
9ca0cf |
GError *error = NULL;
|
|
Packit |
9ca0cf |
DriverRegistrationOperation *operation;
|
|
Packit |
9ca0cf |
GsdSmartcardManagerPrivate *priv = self->priv;
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
operation = g_task_get_task_data (G_TASK (result));
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
if (!register_driver_finish (self, result, &error)) {
|
|
Packit |
9ca0cf |
g_task_return_error (task, error);
|
|
Packit |
9ca0cf |
g_object_unref (task);
|
|
Packit |
9ca0cf |
return;
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
watch_smartcards_from_driver_async (self,
|
|
Packit |
9ca0cf |
operation->driver,
|
|
Packit |
9ca0cf |
priv->cancellable,
|
|
Packit |
9ca0cf |
(GAsyncReadyCallback) on_smartcards_from_driver_watched,
|
|
Packit |
9ca0cf |
task);
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
g_task_return_boolean (task, TRUE);
|
|
Packit |
9ca0cf |
g_object_unref (task);
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
static void
|
|
Packit |
9ca0cf |
on_smartcards_from_driver_watched (GsdSmartcardManager *self,
|
|
Packit |
9ca0cf |
GAsyncResult *result,
|
|
Packit |
9ca0cf |
GTask *task)
|
|
Packit |
9ca0cf |
{
|
|
Packit |
9ca0cf |
g_debug ("Done watching smartcards from driver");
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
static void
|
|
Packit |
9ca0cf |
destroy_driver_registration_operation (DriverRegistrationOperation *operation)
|
|
Packit |
9ca0cf |
{
|
|
Packit |
9ca0cf |
SECMOD_DestroyModule (operation->driver);
|
|
Packit |
9ca0cf |
g_free (operation);
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
static gboolean
|
|
Packit |
9ca0cf |
on_task_thread_to_complete_driver_registration (GTask *task)
|
|
Packit |
9ca0cf |
{
|
|
Packit |
9ca0cf |
DriverRegistrationOperation *operation;
|
|
Packit |
9ca0cf |
operation = g_task_get_task_data (task);
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
if (operation->error != NULL)
|
|
Packit |
9ca0cf |
g_task_return_error (task, operation->error);
|
|
Packit |
9ca0cf |
else
|
|
Packit |
9ca0cf |
g_task_return_boolean (task, TRUE);
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
return G_SOURCE_REMOVE;
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
static gboolean
|
|
Packit |
9ca0cf |
on_main_thread_to_register_driver (GTask *task)
|
|
Packit |
9ca0cf |
{
|
|
Packit |
9ca0cf |
GsdSmartcardManager *self;
|
|
Packit |
9ca0cf |
GsdSmartcardManagerPrivate *priv;
|
|
Packit |
9ca0cf |
DriverRegistrationOperation *operation;
|
|
Packit |
9ca0cf |
GSource *source;
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
self = g_task_get_source_object (task);
|
|
Packit |
9ca0cf |
priv = self->priv;
|
|
Packit |
9ca0cf |
operation = g_task_get_task_data (task);
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
gsd_smartcard_service_register_driver (priv->service,
|
|
Packit |
9ca0cf |
operation->driver);
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
source = g_idle_source_new ();
|
|
Packit |
9ca0cf |
g_task_attach_source (task,
|
|
Packit |
9ca0cf |
source,
|
|
Packit |
9ca0cf |
(GSourceFunc) on_task_thread_to_complete_driver_registration);
|
|
Packit |
9ca0cf |
g_source_unref (source);
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
return G_SOURCE_REMOVE;
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
static void
|
|
Packit |
9ca0cf |
register_driver (GsdSmartcardManager *self,
|
|
Packit |
9ca0cf |
SECMODModule *driver,
|
|
Packit |
9ca0cf |
GCancellable *cancellable,
|
|
Packit |
9ca0cf |
GAsyncReadyCallback callback,
|
|
Packit |
9ca0cf |
gpointer user_data)
|
|
Packit |
9ca0cf |
{
|
|
Packit |
9ca0cf |
GTask *task;
|
|
Packit |
9ca0cf |
DriverRegistrationOperation *operation;
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
task = g_task_new (self, cancellable, callback, user_data);
|
|
Packit |
9ca0cf |
operation = g_new0 (DriverRegistrationOperation, 1);
|
|
Packit |
9ca0cf |
operation->driver = SECMOD_ReferenceModule (driver);
|
|
Packit |
9ca0cf |
g_task_set_task_data (task,
|
|
Packit |
9ca0cf |
operation,
|
|
Packit |
9ca0cf |
(GDestroyNotify) destroy_driver_registration_operation);
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
operation->idle_id = g_idle_add ((GSourceFunc) on_main_thread_to_register_driver, task);
|
|
Packit |
9ca0cf |
g_source_set_name_by_id (operation->idle_id, "[gnome-settings-daemon] on_main_thread_to_register_driver");
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
static void
|
|
Packit |
9ca0cf |
activate_driver (GsdSmartcardManager *self,
|
|
Packit |
9ca0cf |
SECMODModule *driver,
|
|
Packit |
9ca0cf |
GCancellable *cancellable,
|
|
Packit |
9ca0cf |
GAsyncReadyCallback callback,
|
|
Packit |
9ca0cf |
gpointer user_data)
|
|
Packit |
9ca0cf |
{
|
|
Packit |
9ca0cf |
GTask *task;
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
g_debug ("Activating driver '%s'", driver->commonName);
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
task = g_task_new (self, cancellable, callback, user_data);
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
register_driver (self,
|
|
Packit |
9ca0cf |
driver,
|
|
Packit |
9ca0cf |
cancellable,
|
|
Packit |
9ca0cf |
(GAsyncReadyCallback) on_driver_registered,
|
|
Packit |
9ca0cf |
task);
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
typedef struct
|
|
Packit |
9ca0cf |
{
|
|
Packit |
9ca0cf |
int pending_drivers_count;
|
|
Packit |
9ca0cf |
int activated_drivers_count;
|
|
Packit |
9ca0cf |
} ActivateAllDriversOperation;
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
static gboolean
|
|
Packit |
9ca0cf |
activate_driver_async_finish (GsdSmartcardManager *self,
|
|
Packit |
9ca0cf |
GAsyncResult *result,
|
|
Packit |
9ca0cf |
GError **error)
|
|
Packit |
9ca0cf |
{
|
|
Packit |
9ca0cf |
return g_task_propagate_boolean (G_TASK (result), error);
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
static void
|
|
Packit |
9ca0cf |
try_to_complete_all_drivers_activation (GTask *task)
|
|
Packit |
9ca0cf |
{
|
|
Packit |
9ca0cf |
ActivateAllDriversOperation *operation;
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
operation = g_task_get_task_data (task);
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
if (operation->pending_drivers_count > 0)
|
|
Packit |
9ca0cf |
return;
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
if (operation->activated_drivers_count > 0)
|
|
Packit |
9ca0cf |
g_task_return_boolean (task, TRUE);
|
|
Packit |
9ca0cf |
else
|
|
Packit |
9ca0cf |
g_task_return_new_error (task, GSD_SMARTCARD_MANAGER_ERROR,
|
|
Packit |
9ca0cf |
GSD_SMARTCARD_MANAGER_ERROR_NO_DRIVERS,
|
|
Packit |
9ca0cf |
"No smartcards exist to be activated.");
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
g_object_unref (task);
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
static void
|
|
Packit |
9ca0cf |
on_driver_activated (GsdSmartcardManager *self,
|
|
Packit |
9ca0cf |
GAsyncResult *result,
|
|
Packit |
9ca0cf |
GTask *task)
|
|
Packit |
9ca0cf |
{
|
|
Packit |
9ca0cf |
GError *error = NULL;
|
|
Packit |
9ca0cf |
gboolean driver_activated;
|
|
Packit |
9ca0cf |
ActivateAllDriversOperation *operation;
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
driver_activated = activate_driver_async_finish (self, result, &error);
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
operation = g_task_get_task_data (task);
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
if (driver_activated)
|
|
Packit |
9ca0cf |
operation->activated_drivers_count++;
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
operation->pending_drivers_count--;
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
try_to_complete_all_drivers_activation (task);
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
static void
|
|
Packit |
9ca0cf |
activate_all_drivers_async (GsdSmartcardManager *self,
|
|
Packit |
9ca0cf |
GCancellable *cancellable,
|
|
Packit |
9ca0cf |
GAsyncReadyCallback callback,
|
|
Packit |
9ca0cf |
gpointer user_data)
|
|
Packit |
9ca0cf |
{
|
|
Packit |
9ca0cf |
GTask *task;
|
|
Packit |
9ca0cf |
SECMODListLock *lock;
|
|
Packit |
9ca0cf |
SECMODModuleList *driver_list, *node;
|
|
Packit |
9ca0cf |
ActivateAllDriversOperation *operation;
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
task = g_task_new (self, cancellable, callback, user_data);
|
|
Packit |
9ca0cf |
operation = g_new0 (ActivateAllDriversOperation, 1);
|
|
Packit |
9ca0cf |
g_task_set_task_data (task, operation, (GDestroyNotify) g_free);
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
lock = SECMOD_GetDefaultModuleListLock ();
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
g_assert (lock != NULL);
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
SECMOD_GetReadLock (lock);
|
|
Packit |
9ca0cf |
driver_list = SECMOD_GetDefaultModuleList ();
|
|
Packit |
9ca0cf |
for (node = driver_list; node != NULL; node = node->next) {
|
|
Packit |
9ca0cf |
if (!node->module->loaded)
|
|
Packit |
9ca0cf |
continue;
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
if (!SECMOD_HasRemovableSlots (node->module))
|
|
Packit |
9ca0cf |
continue;
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
if (node->module->dllName == NULL)
|
|
Packit |
9ca0cf |
continue;
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
operation->pending_drivers_count++;
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
activate_driver (self, node->module,
|
|
Packit |
9ca0cf |
cancellable,
|
|
Packit |
9ca0cf |
(GAsyncReadyCallback) on_driver_activated,
|
|
Packit |
9ca0cf |
task);
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
SECMOD_ReleaseReadLock (lock);
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
try_to_complete_all_drivers_activation (task);
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
/* Will error with %GSD_SMARTCARD_MANAGER_ERROR_NO_DRIVERS if there were no
|
|
Packit |
9ca0cf |
* drivers to activate.. */
|
|
Packit |
9ca0cf |
static gboolean
|
|
Packit |
9ca0cf |
activate_all_drivers_async_finish (GsdSmartcardManager *self,
|
|
Packit |
9ca0cf |
GAsyncResult *result,
|
|
Packit |
9ca0cf |
GError **error)
|
|
Packit |
9ca0cf |
{
|
|
Packit |
9ca0cf |
return g_task_propagate_boolean (G_TASK (result), error);
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
static void
|
|
Packit |
9ca0cf |
on_all_drivers_activated (GsdSmartcardManager *self,
|
|
Packit |
9ca0cf |
GAsyncResult *result,
|
|
Packit |
9ca0cf |
GTask *task)
|
|
Packit |
9ca0cf |
{
|
|
Packit |
9ca0cf |
GError *error = NULL;
|
|
Packit |
9ca0cf |
gboolean driver_activated;
|
|
Packit |
9ca0cf |
PK11SlotInfo *login_token;
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
driver_activated = activate_all_drivers_async_finish (self, result, &error);
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
if (!driver_activated) {
|
|
Packit |
9ca0cf |
g_task_return_error (task, error);
|
|
Packit |
9ca0cf |
return;
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
login_token = gsd_smartcard_manager_get_login_token (self);
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
if (login_token || g_getenv ("PKCS11_LOGIN_TOKEN_NAME") != NULL) {
|
|
Packit |
9ca0cf |
/* The card used to log in was removed before login completed.
|
|
Packit |
9ca0cf |
* Do removal action immediately
|
|
Packit |
9ca0cf |
*/
|
|
Packit |
9ca0cf |
if (!login_token || !PK11_IsPresent (login_token))
|
|
Packit |
9ca0cf |
gsd_smartcard_manager_do_remove_action (self);
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
g_task_return_boolean (task, TRUE);
|
|
Packit |
9ca0cf |
g_object_unref (task);
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
static void
|
|
Packit |
9ca0cf |
watch_smartcards (GTask *task,
|
|
Packit |
9ca0cf |
GsdSmartcardManager *self,
|
|
Packit |
9ca0cf |
gpointer data,
|
|
Packit |
9ca0cf |
GCancellable *cancellable)
|
|
Packit |
9ca0cf |
{
|
|
Packit |
9ca0cf |
GMainContext *context;
|
|
Packit |
9ca0cf |
GMainLoop *loop;
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
g_debug ("Getting list of suitable drivers");
|
|
Packit |
9ca0cf |
context = g_main_context_new ();
|
|
Packit |
9ca0cf |
g_main_context_push_thread_default (context);
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
activate_all_drivers_async (self,
|
|
Packit |
9ca0cf |
cancellable,
|
|
Packit |
9ca0cf |
(GAsyncReadyCallback) on_all_drivers_activated,
|
|
Packit |
9ca0cf |
task);
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
loop = g_main_loop_new (context, FALSE);
|
|
Packit |
9ca0cf |
g_main_loop_run (loop);
|
|
Packit |
9ca0cf |
g_main_loop_unref (loop);
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
g_main_context_pop_thread_default (context);
|
|
Packit |
9ca0cf |
g_main_context_unref (context);
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
static void
|
|
Packit |
9ca0cf |
watch_smartcards_async (GsdSmartcardManager *self,
|
|
Packit |
9ca0cf |
GCancellable *cancellable,
|
|
Packit |
9ca0cf |
GAsyncReadyCallback callback,
|
|
Packit |
9ca0cf |
gpointer user_data)
|
|
Packit |
9ca0cf |
{
|
|
Packit |
9ca0cf |
GTask *task;
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
task = g_task_new (self, cancellable, callback, user_data);
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
g_task_run_in_thread (task, (GTaskThreadFunc) watch_smartcards);
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
static gboolean
|
|
Packit |
9ca0cf |
watch_smartcards_async_finish (GsdSmartcardManager *self,
|
|
Packit |
9ca0cf |
GAsyncResult *result,
|
|
Packit |
9ca0cf |
GError **error)
|
|
Packit |
9ca0cf |
{
|
|
Packit |
9ca0cf |
return g_task_propagate_boolean (G_TASK (result), error);
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
static void
|
|
Packit |
9ca0cf |
on_smartcards_watched (GsdSmartcardManager *self,
|
|
Packit |
9ca0cf |
GAsyncResult *result)
|
|
Packit |
9ca0cf |
{
|
|
Packit |
9ca0cf |
GError *error = NULL;
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
if (!watch_smartcards_async_finish (self, result, &error)) {
|
|
Packit |
9ca0cf |
g_debug ("Error watching smartcards: %s", error->message);
|
|
Packit |
9ca0cf |
g_error_free (error);
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
static void
|
|
Packit |
9ca0cf |
on_service_created (GObject *source_object,
|
|
Packit |
9ca0cf |
GAsyncResult *result,
|
|
Packit |
9ca0cf |
GsdSmartcardManager *self)
|
|
Packit |
9ca0cf |
{
|
|
Packit |
9ca0cf |
GsdSmartcardManagerPrivate *priv = self->priv;
|
|
Packit |
9ca0cf |
GsdSmartcardService *service;
|
|
Packit |
9ca0cf |
GError *error = NULL;
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
service = gsd_smartcard_service_new_finish (result, &error);
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
if (service == NULL) {
|
|
Packit |
9ca0cf |
g_warning("Couldn't create session bus service: %s", error->message);
|
|
Packit |
9ca0cf |
g_error_free (error);
|
|
Packit |
9ca0cf |
return;
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
priv->service = service;
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
watch_smartcards_async (self,
|
|
Packit |
9ca0cf |
priv->cancellable,
|
|
Packit |
9ca0cf |
(GAsyncReadyCallback) on_smartcards_watched,
|
|
Packit |
9ca0cf |
NULL);
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
static gboolean
|
|
Packit |
9ca0cf |
gsd_smartcard_manager_idle_cb (GsdSmartcardManager *self)
|
|
Packit |
9ca0cf |
{
|
|
Packit |
9ca0cf |
GsdSmartcardManagerPrivate *priv = self->priv;
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
gnome_settings_profile_start (NULL);
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
priv->cancellable = g_cancellable_new();
|
|
Packit |
9ca0cf |
priv->settings = g_settings_new (CONF_SCHEMA);
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
load_nss (self);
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
gsd_smartcard_service_new_async (self,
|
|
Packit |
9ca0cf |
priv->cancellable,
|
|
Packit |
9ca0cf |
(GAsyncReadyCallback) on_service_created,
|
|
Packit |
9ca0cf |
self);
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
gnome_settings_profile_end (NULL);
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
priv->start_idle_id = 0;
|
|
Packit |
9ca0cf |
return FALSE;
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
gboolean
|
|
Packit |
9ca0cf |
gsd_smartcard_manager_start (GsdSmartcardManager *self,
|
|
Packit |
9ca0cf |
GError **error)
|
|
Packit |
9ca0cf |
{
|
|
Packit |
9ca0cf |
GsdSmartcardManagerPrivate *priv = self->priv;
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
gnome_settings_profile_start (NULL);
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
priv->start_idle_id = g_idle_add ((GSourceFunc) gsd_smartcard_manager_idle_cb, self);
|
|
Packit |
9ca0cf |
g_source_set_name_by_id (priv->start_idle_id, "[gnome-settings-daemon] gsd_smartcard_manager_idle_cb");
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
gnome_settings_profile_end (NULL);
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
return TRUE;
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
void
|
|
Packit |
9ca0cf |
gsd_smartcard_manager_stop (GsdSmartcardManager *self)
|
|
Packit |
9ca0cf |
{
|
|
Packit |
9ca0cf |
GsdSmartcardManagerPrivate *priv = self->priv;
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
g_debug ("Stopping smartcard manager");
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
unload_nss (self);
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
g_clear_object (&priv->settings);
|
|
Packit |
9ca0cf |
g_clear_object (&priv->cancellable);
|
|
Packit |
9ca0cf |
g_clear_object (&priv->session_manager);
|
|
Packit |
9ca0cf |
g_clear_object (&priv->screen_saver);
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
static void
|
|
Packit |
9ca0cf |
on_screen_locked (GsdScreenSaver *screen_saver,
|
|
Packit |
9ca0cf |
GAsyncResult *result,
|
|
Packit |
9ca0cf |
GsdSmartcardManager *self)
|
|
Packit |
9ca0cf |
{
|
|
Packit |
9ca0cf |
gboolean is_locked;
|
|
Packit |
9ca0cf |
GError *error = NULL;
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
is_locked = gsd_screen_saver_call_lock_finish (screen_saver, result, &error);
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
if (!is_locked) {
|
|
Packit |
9ca0cf |
g_warning ("Couldn't lock screen: %s", error->message);
|
|
Packit |
9ca0cf |
g_error_free (error);
|
|
Packit |
9ca0cf |
return;
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
static void
|
|
Packit |
9ca0cf |
lock_screen (GsdSmartcardManager *self)
|
|
Packit |
9ca0cf |
{
|
|
Packit |
9ca0cf |
GsdSmartcardManagerPrivate *priv = self->priv;
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
if (priv->screen_saver == NULL)
|
|
Packit |
9ca0cf |
priv->screen_saver = gnome_settings_bus_get_screen_saver_proxy ();
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
gsd_screen_saver_call_lock (priv->screen_saver,
|
|
Packit |
9ca0cf |
priv->cancellable,
|
|
Packit |
9ca0cf |
(GAsyncReadyCallback) on_screen_locked,
|
|
Packit |
9ca0cf |
self);
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
static void
|
|
Packit |
9ca0cf |
on_logged_out (GsdSessionManager *session_manager,
|
|
Packit |
9ca0cf |
GAsyncResult *result,
|
|
Packit |
9ca0cf |
GsdSmartcardManager *self)
|
|
Packit |
9ca0cf |
{
|
|
Packit |
9ca0cf |
gboolean is_logged_out;
|
|
Packit |
9ca0cf |
GError *error = NULL;
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
is_logged_out = gsd_session_manager_call_logout_finish (session_manager, result, &error);
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
if (!is_logged_out) {
|
|
Packit |
9ca0cf |
g_warning ("Couldn't log out: %s", error->message);
|
|
Packit |
9ca0cf |
g_error_free (error);
|
|
Packit |
9ca0cf |
return;
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
static void
|
|
Packit |
9ca0cf |
log_out (GsdSmartcardManager *self)
|
|
Packit |
9ca0cf |
{
|
|
Packit |
9ca0cf |
GsdSmartcardManagerPrivate *priv = self->priv;
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
if (priv->session_manager == NULL)
|
|
Packit |
9ca0cf |
priv->session_manager = gnome_settings_bus_get_session_proxy ();
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
gsd_session_manager_call_logout (priv->session_manager,
|
|
Packit |
9ca0cf |
GSD_SESSION_MANAGER_LOGOUT_MODE_FORCE,
|
|
Packit |
9ca0cf |
priv->cancellable,
|
|
Packit |
9ca0cf |
(GAsyncReadyCallback) on_logged_out,
|
|
Packit |
9ca0cf |
self);
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
void
|
|
Packit |
9ca0cf |
gsd_smartcard_manager_do_remove_action (GsdSmartcardManager *self)
|
|
Packit |
9ca0cf |
{
|
|
Packit |
9ca0cf |
GsdSmartcardManagerPrivate *priv = self->priv;
|
|
Packit |
9ca0cf |
char *remove_action;
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
remove_action = g_settings_get_string (priv->settings, KEY_REMOVE_ACTION);
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
if (strcmp (remove_action, "lock-screen") == 0)
|
|
Packit |
9ca0cf |
lock_screen (self);
|
|
Packit |
9ca0cf |
else if (strcmp (remove_action, "force-logout") == 0)
|
|
Packit |
9ca0cf |
log_out (self);
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
static PK11SlotInfo *
|
|
Packit |
9ca0cf |
get_login_token_for_operation (GsdSmartcardManager *self,
|
|
Packit |
9ca0cf |
WatchSmartcardsOperation *operation)
|
|
Packit |
9ca0cf |
{
|
|
Packit |
9ca0cf |
GHashTableIter iter;
|
|
Packit |
9ca0cf |
gpointer key, value;
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
g_hash_table_iter_init (&iter, operation->smartcards);
|
|
Packit |
9ca0cf |
while (g_hash_table_iter_next (&iter, &key, &value)) {
|
|
Packit |
9ca0cf |
PK11SlotInfo *card_slot;
|
|
Packit |
9ca0cf |
const char *token_name;
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
card_slot = (PK11SlotInfo *) value;
|
|
Packit |
9ca0cf |
token_name = PK11_GetTokenName (card_slot);
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
if (g_strcmp0 (g_getenv ("PKCS11_LOGIN_TOKEN_NAME"), token_name) == 0)
|
|
Packit |
9ca0cf |
return card_slot;
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
return NULL;
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
PK11SlotInfo *
|
|
Packit |
9ca0cf |
gsd_smartcard_manager_get_login_token (GsdSmartcardManager *self)
|
|
Packit |
9ca0cf |
{
|
|
Packit |
9ca0cf |
GsdSmartcardManagerPrivate *priv = self->priv;
|
|
Packit |
9ca0cf |
PK11SlotInfo *card_slot = NULL;
|
|
Packit |
9ca0cf |
GList *node;
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
G_LOCK (gsd_smartcards_watch_tasks);
|
|
Packit |
9ca0cf |
node = priv->smartcards_watch_tasks;
|
|
Packit |
9ca0cf |
while (node != NULL) {
|
|
Packit |
9ca0cf |
GTask *task = node->data;
|
|
Packit |
9ca0cf |
WatchSmartcardsOperation *operation = g_task_get_task_data (task);
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
card_slot = get_login_token_for_operation (self, operation);
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
if (card_slot != NULL)
|
|
Packit |
9ca0cf |
break;
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
node = node->next;
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
G_UNLOCK (gsd_smartcards_watch_tasks);
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
return card_slot;
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
static GList *
|
|
Packit |
9ca0cf |
get_inserted_tokens_for_operation (GsdSmartcardManager *self,
|
|
Packit |
9ca0cf |
WatchSmartcardsOperation *operation)
|
|
Packit |
9ca0cf |
{
|
|
Packit |
9ca0cf |
GList *inserted_tokens = NULL;
|
|
Packit |
9ca0cf |
GHashTableIter iter;
|
|
Packit |
9ca0cf |
gpointer key, value;
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
g_hash_table_iter_init (&iter, operation->smartcards);
|
|
Packit |
9ca0cf |
while (g_hash_table_iter_next (&iter, &key, &value)) {
|
|
Packit |
9ca0cf |
PK11SlotInfo *card_slot;
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
card_slot = (PK11SlotInfo *) value;
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
if (PK11_IsPresent (card_slot))
|
|
Packit |
9ca0cf |
inserted_tokens = g_list_prepend (inserted_tokens, card_slot);
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
return inserted_tokens;
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
GList *
|
|
Packit |
9ca0cf |
gsd_smartcard_manager_get_inserted_tokens (GsdSmartcardManager *self,
|
|
Packit |
9ca0cf |
gsize *num_tokens)
|
|
Packit |
9ca0cf |
{
|
|
Packit |
9ca0cf |
GsdSmartcardManagerPrivate *priv = self->priv;
|
|
Packit |
9ca0cf |
GList *inserted_tokens = NULL, *node;
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
G_LOCK (gsd_smartcards_watch_tasks);
|
|
Packit |
9ca0cf |
for (node = priv->smartcards_watch_tasks; node != NULL; node = node->next) {
|
|
Packit |
9ca0cf |
GTask *task = node->data;
|
|
Packit |
9ca0cf |
WatchSmartcardsOperation *operation = g_task_get_task_data (task);
|
|
Packit |
9ca0cf |
GList *operation_inserted_tokens;
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
operation_inserted_tokens = get_inserted_tokens_for_operation (self, operation);
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
inserted_tokens = g_list_concat (inserted_tokens, operation_inserted_tokens);
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
G_UNLOCK (gsd_smartcards_watch_tasks);
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
if (num_tokens != NULL)
|
|
Packit |
9ca0cf |
*num_tokens = g_list_length (inserted_tokens);
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
return inserted_tokens;
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
static void
|
|
Packit |
9ca0cf |
gsd_smartcard_manager_finalize (GObject *object)
|
|
Packit |
9ca0cf |
{
|
|
Packit |
9ca0cf |
GsdSmartcardManager *self;
|
|
Packit |
9ca0cf |
GsdSmartcardManagerPrivate *priv;
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
g_return_if_fail (object != NULL);
|
|
Packit |
9ca0cf |
g_return_if_fail (GSD_IS_SMARTCARD_MANAGER (object));
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
self = GSD_SMARTCARD_MANAGER (object);
|
|
Packit |
9ca0cf |
priv = self->priv;
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
g_return_if_fail (self->priv != NULL);
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
if (priv->start_idle_id != 0)
|
|
Packit |
9ca0cf |
g_source_remove (priv->start_idle_id);
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
gsd_smartcard_manager_stop (self);
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
G_OBJECT_CLASS (gsd_smartcard_manager_parent_class)->finalize (object);
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
GsdSmartcardManager *
|
|
Packit |
9ca0cf |
gsd_smartcard_manager_new (void)
|
|
Packit |
9ca0cf |
{
|
|
Packit |
9ca0cf |
if (manager_object != NULL) {
|
|
Packit |
9ca0cf |
g_object_ref (manager_object);
|
|
Packit |
9ca0cf |
} else {
|
|
Packit |
9ca0cf |
manager_object = g_object_new (GSD_TYPE_SMARTCARD_MANAGER, NULL);
|
|
Packit |
9ca0cf |
g_object_add_weak_pointer (manager_object,
|
|
Packit |
9ca0cf |
(gpointer *) &manager_object);
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
return GSD_SMARTCARD_MANAGER (manager_object);
|
|
Packit |
9ca0cf |
}
|