rpms/gdm/devel gdm-2.15.6-security-tokens.patch,1.1,1.2

fedora-cvs-commits at redhat.com fedora-cvs-commits at redhat.com
Tue Jul 18 05:59:40 UTC 2006


Author: rstrode

Update of /cvs/dist/rpms/gdm/devel
In directory cvs.devel.redhat.com:/tmp/cvs-serv11971

Modified Files:
	gdm-2.15.6-security-tokens.patch 
Log Message:
add forgotton file to patch


gdm-2.15.6-security-tokens.patch:
 config/Makefile.am            |   35 +
 config/gdm                    |   16 
 config/gdm-securitytokens     |   10 
 config/gdm.conf.in            |    7 
 config/securitytokens.conf.in |    4 
 configure.ac                  |    3 
 daemon/Makefile.am            |    7 
 daemon/gdm.c                  |  148 +++++++
 daemon/gdm.h                  |    5 
 daemon/gdmconfig.c            |   26 +
 daemon/gdmconfig.h            |    3 
 daemon/securitytoken.c        |  602 ++++++++++++++++++++++++++++++
 daemon/securitytoken.h        |  101 +++++
 daemon/securitytokenmonitor.c |  840 ++++++++++++++++++++++++++++++++++++++++++
 daemon/securitytokenmonitor.h |   81 ++++
 daemon/verify-pam.c           |    5 
 16 files changed, 1880 insertions(+), 13 deletions(-)

Index: gdm-2.15.6-security-tokens.patch
===================================================================
RCS file: /cvs/dist/rpms/gdm/devel/gdm-2.15.6-security-tokens.patch,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- gdm-2.15.6-security-tokens.patch	18 Jul 2006 05:46:11 -0000	1.1
+++ gdm-2.15.6-security-tokens.patch	18 Jul 2006 05:59:38 -0000	1.2
@@ -2106,1787 +2106,11 @@
      if ( ! create_pamh (d, pam_stack, login, &pamc, display, &pamerr)) {
  	    if (started_timer)
  		    gdm_slave_greeter_ctl_no_ret (GDM_STOPTIMER, "");
-deleted file mode 100644
 --- /dev/null
-+++ gdm-2.15.6/utils/gdmsecuritytokenmonitor.c
-@@ -0,0 +1,197 @@
-+/* GDM Security Token monitor 
-+ * Copyright (C) 2006 Ray Strode <rstrode at redhat.com>
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+ */
-+#include "config.h"
-+
-+#include <locale.h>
-+#include <syslog.h>
-+
-+#include <glib.h>
-+#include <glib/gi18n.h>
-+
-+#include "securitytokenmonitor.h"
-+
-+static gchar *pkcs11_module;
-+static GOptionEntry options[] = {
-+	{
-+		"pkcs11-module", 0, 0, G_OPTION_ARG_STRING, &pkcs11_module,
-+		N_("PKCS#11 driver for security token"),
-+		N_("MODULE")
-+	},
-+	{ NULL }
-+};
-+
-+static typedef struct 
-+{
-+    ScSecurityMonitor *monitor;
-+    GMainLoop *event_loop;
-+} Daemon;
-+
-+static Daemon *daemon_new (void);
-+static void daemon_free (Monitor *monitor);
-+
-+static void gdm_handle_security_token_insertion (ScSecurityTokenMonitor *monitor,
-+						 ScSecurityToken *token);
-+static void gdm_handle_security_token_removal (ScSecurityTokenMonitor *monitor,
-+					       ScSecurityToken *token);
-+static void gdm_watch_for_security_tokens (const gchar *driver);
-+
-+static Daemon *
-+daemon_new (const gchar *driver)
-+{
-+    Daemon *daemon;
-+
-+
-+    daemon = g_slice_new0 (Daemon);
-+    daemon->event_loop = g_main_loop_new (NULL, FALSE);
-+
-+    return daemon;
-+}
-+
-+static gboolean
-+daemon_run (Daemon *daemon)
-+{
-+    pid_t pid;
-+    pid = fork ();
-+
-+    if (pid < 0)
-+	    return FALSE;
-+
-+    if (pid != 0) {
-+	    gint status;
-+
-+	    waitpid (pid, &status, 0);
-+	    _exit (status);
-+    }
-+
-+    daemon ();
-+
-+    gdm_watch_for_security_tokens (pkcs11_module);
-+    g_main_loop_run (daemon->event_loop);
-+
-+    return TRUE;
-+}
-+
-+static void 
-+monitor_free (Monitor *monitor)
-+{
-+    if (daemon->loop != NULL) {
-+	    g_main_loop_unref (daemon->loop);
-+	    daemon->loop = NULL;
-+    }
-+    g_slice_free1 (Monitor, monitor);
-+}
-+
-+static void
-+gdm_handle_security_token_insertion (ScSecurityTokenMonitor *monitor,
-+				     ScSecurityToken        *token)
-+{
-+    GSList *li;
-+
-+    g_debug ("notifying local displays about token insertion");
-+#if 0
-+    for (li = displays; li != NULL; li = li->next) {
-+	    GdmDisplay *d = li->data;
-+
-+	    if (SERVER_IS_LOCAL (d)) {
-+		    g_debug ("notifying display '%s'", d->name);
-+		    send_slave_command (d, GDM_NOTIFY_RESET);
-+	    } else {
-+		    g_debug ("display '%s' is not local", d->name);
-+	    }
-+    }
-+#endif
-+}
-+
-+static void
-+gdm_handle_security_token_removal (ScSecurityTokenMonitor *monitor,
-+				   ScSecurityToken        *token)
-+{
-+    GSList *li;
-+
-+    g_debug ("notifying local displays about token removal");
-+#if 0
-+    for (li = displays; li != NULL; li = li->next) {
-+	    GdmDisplay *d = li->data;
-+
-+	    if (SERVER_IS_LOCAL (d)) {
-+		    g_debug ("notifying display '%s'", d->name);
-+		    send_slave_command (d, GDM_NOTIFY_RESET);
-+	    } else {
-+		    g_debug ("display '%s' is not local", d->name);
-+	    }
-+    }
-+#endif
-+}
-+
-+static void
-+gdm_watch_for_security_tokens (const gchar *driver)
-+{
-+    GError *error;
-+    ScSecurityTokenMonitor *monitor;
-+
-+    g_debug ("watching for security token insertion and removal events");
-+
-+    monitor = sc_security_token_monitor_new (driver);
-+    g_signal_connect (monitor,
-+		      "security-token-inserted",
-+		      G_CALLBACK (gdm_handle_security_token_insertion), NULL);
-+
-+    g_signal_connect (monitor,
-+		      "security-token-removed",
-+		      G_CALLBACK (gdm_handle_security_token_removal), NULL);
-+    error = NULL;
-+    if (!sc_security_token_monitor_start (monitor, 
-+					  &error)) {
-+	    if (error != NULL) {
-+		    syslog (LOG_ERR, "%s", error->message);
-+		    g_error_free (error);
-+	    } else {
-+		    syslog (LOG_ERR, "could not start security token monitor");
-+
-+	    }
-+    }
-+}
-+
-+gint 
-+main (gint    argc, 
-+      gchar **argv)
-+{
-+    Daemon *daemon;
-+    GOptionContext *options_context;
-+
-+    setlocale (LC_ALL, "");
-+    bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
-+    textdomain (GETTEXT_PACKAGE);
-+
-+    g_type_init ();
-+
-+    options_context = g_option_context_new (_("- helps gdm monitor for security "
-+					      "token insertion and deletion events"));
-+    g_option_context_add_main_entries (options_context, options, GETTEXT_PACKAGE);
-+    g_option_context_parse (options_context, &argc, &argv, NULL);
-+    g_option_context_free (options_context);
-+
-+    openlog ("gdm[security-token-monitor]", 0, LOG_DAEMON);
-+    daemon = daemon_new ();
-+
-+    if (!daemon_run ())
-+	    return 1;
-+
-+    daemon_free (daemon);
-+    return 0;
-+}
---- /dev/null
-+++ gdm-2.15.6/utils/securitytoken.c
-@@ -0,0 +1,573 @@
-+/* securitytoken.c - security token
-+ * 
-+ * Copyright (C) 2006 Ray Strode <rstrode at redhat.com>
-+ * 
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2, or (at your option)
-+ * any later version.
-+ * 
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ * 
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-+ * 02111-1307, USA.  
-+ *
-+ * TODO:     - doing this per project is a bad idea i think.
-+ *             We should probably make this a system service 
-+ *             and use dbus.
-+ *
-+ *           - We hardcode a driver right now.  We should probably
-+ *             look up the default list and go from there. 
-+ */
-+#define SC_SECURITY_TOKEN_ENABLE_INTERNAL_API
-+#include "securitytoken.h"
-+
-+#include <errno.h>
-+#include <string.h>
-+#include <unistd.h>
-+
-+#include <glib.h>
-+#include <glib/gi18n.h>
-+
-+#include <cert.h>
-+#include <nss.h>
-+#include <pk11func.h>
-+#include <prerror.h>
-+#include <secmod.h>
-+#include <secerr.h>
-+
-+/* wtf
-+ */
-+#include "/tmp/certhtml.c"
-+
-+#if defined (SC_SECURITY_TOKEN_ENABLE_TEST) || defined (SC_SECURITY_TOKEN_MONITOR_ENABLE_TEST)
-+#define sc_debug(format, args...) g_printerr (format "\n", ##args)
-+#define sc_warning(format, args...) g_printerr (format "\n", ##args)
-+#else
-+#define sc_debug(format, args...) 
-+#define sc_warning(format, args...) 
-+#endif
-+
-+struct _ScSecurityTokenPrivate {
-+	SECMODModule *module;
-+	ScSecurityTokenState state;
-+
-+	CK_SLOT_ID slot_id;
-+	gint slot_series;
-+
-+	PK11SlotInfo *slot;
-+
-+	CERTCertificate *signing_certificate;
-+	CERTCertificate *encryption_certificate;
-+};
-+
-+static void sc_security_token_finalize (GObject *object);
-+static void sc_security_token_class_install_signals (ScSecurityTokenClass *token_class);
-+static void sc_security_token_class_install_properties (ScSecurityTokenClass *token_class);
-+static void sc_security_token_set_property (GObject       *object,
-+					    guint          prop_id,
-+					    const GValue  *value,
-+					    GParamSpec    *pspec);
-+static void sc_security_token_get_property (GObject     *object,
-+					    guint        prop_id,
-+					    GValue      *value,
-+					    GParamSpec  *pspec);
-+
-+static void sc_security_token_set_slot_id (ScSecurityToken *token, 
-+					   gint             slot_id);
-+static void sc_security_token_set_slot_series (ScSecurityToken *token, 
-+					       gint             slot_series);
-+static void sc_security_token_set_module (ScSecurityToken *token,
-+					  SECMODModule    *module);
-+
-+static PK11SlotInfo *sc_security_token_find_slot_from_id (ScSecurityToken *token,
-+							  gint slot_id);
-+static gboolean sc_security_token_fetch_certificates (ScSecurityToken *token);
-+
-+
-+#ifndef SC_SECURITY_TOKEN_DEFAULT_SLOT_ID 
-+#define SC_SECURITY_TOKEN_DEFAULT_SLOT_ID ((gulong) -1)
-+#endif
-+
-+#ifndef SC_SECURITY_TOKEN_DEFAULT_SLOT_SERIES
-+#define SC_SECURITY_TOKEN_DEFAULT_SLOT_SERIES -1
-+#endif
-+
-+enum {
-+	PROP_0 = 0,
-+	PROP_SLOT_ID,
-+	PROP_SLOT_SERIES,
-+	PROP_MODULE,
-+	NUMBER_OF_PROPERTIES
-+};
-+
-+enum {
-+	INSERTED,
-+	REMOVED,
-+	NUMBER_OF_SIGNALS
-+};
-+
-+static guint sc_security_token_signals[NUMBER_OF_SIGNALS];
-+
-+G_DEFINE_TYPE (ScSecurityToken, sc_security_token, G_TYPE_OBJECT);
-+
-+static void
-+sc_security_token_class_init (ScSecurityTokenClass *token_class)
-+{
-+    GObjectClass *gobject_class;
-+
-+    gobject_class = G_OBJECT_CLASS (token_class);
-+
-+    gobject_class->finalize = sc_security_token_finalize;
-+
-+    sc_security_token_class_install_signals (token_class);
-+    sc_security_token_class_install_properties (token_class);
-+
-+    g_type_class_add_private (token_class,
-+			      sizeof (ScSecurityTokenPrivate));
-+}
-+
-+static void
-+sc_security_token_class_install_signals (ScSecurityTokenClass *token_class)
-+{
-+    GObjectClass *object_class;
-+
-+    object_class = G_OBJECT_CLASS (token_class);
-+
-+    sc_security_token_signals[INSERTED] =
-+	    g_signal_new ("inserted",
-+			  G_OBJECT_CLASS_TYPE (object_class),
-+			  G_SIGNAL_RUN_LAST,
-+			  G_STRUCT_OFFSET (ScSecurityTokenClass,
-+					   inserted), 
-+			  NULL, NULL, g_cclosure_marshal_VOID__VOID, 
-+			  G_TYPE_NONE, 0);
-+    token_class->inserted = NULL;
-+
-+    sc_security_token_signals[REMOVED] =
-+	    g_signal_new ("removed",
-+			  G_OBJECT_CLASS_TYPE (object_class),
-+			  G_SIGNAL_RUN_LAST,
-+			  G_STRUCT_OFFSET (ScSecurityTokenClass,
-+					   removed), 
-+			  NULL, NULL, g_cclosure_marshal_VOID__VOID, 
-+			  G_TYPE_NONE, 0);
-+    token_class->removed = NULL;
-+}
-+
-+static void
-+sc_security_token_class_install_properties (ScSecurityTokenClass *token_class)
-+{
-+    GObjectClass *object_class;
-+    GParamSpec *param_spec;
-+
-+    object_class = G_OBJECT_CLASS (token_class);
-+    object_class->set_property = sc_security_token_set_property;
-+    object_class->get_property = sc_security_token_get_property;
-+
-+    param_spec = g_param_spec_ulong ("slot-id", _("Slot ID"),
-+				   _("The slot the token is in"),
-+				   1, G_MAXULONG,
-+				   SC_SECURITY_TOKEN_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 token identifier"),
-+				   -1, G_MAXINT,
-+				   SC_SECURITY_TOKEN_DEFAULT_SLOT_SERIES,
-+				   G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
-+    g_object_class_install_property (object_class, PROP_SLOT_SERIES, param_spec);
-+
-+    /* FIXME: maybe make this a boxed type?
-+     */
-+    param_spec = g_param_spec_pointer ("module", _("Module"),
-+				       _("security token driver"),
-+				       G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY);
-+    g_object_class_install_property (object_class, PROP_MODULE, param_spec);
-+}
-+
-+static void 
-+sc_security_token_set_property (GObject       *object,
-+				guint          prop_id,
-+				const GValue  *value,
-+				GParamSpec    *pspec)
-+{
-+    ScSecurityToken *token = SC_SECURITY_TOKEN (object);
-+
-+    switch (prop_id)
-+    {
-+	    case PROP_SLOT_ID:
-+		    sc_security_token_set_slot_id (token, 
-+						   g_value_get_ulong (value));
-+		    break;
-+
-+	    case PROP_SLOT_SERIES:
-+		    sc_security_token_set_slot_series (token, 
-+						       g_value_get_int (value));
-+		    break;
-+
-+	    case PROP_MODULE:
-+		    sc_security_token_set_module (token, 
-+						  (SECMODModule *)
-+						  g_value_get_pointer (value));
-+		    break;
-+
-+	    default:
-+		    G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-+    }
-+}
-+
-+CK_SLOT_ID
-+sc_security_token_get_slot_id (ScSecurityToken *token)
-+{
-+    return token->priv->slot_id;
-+}
-+
-+static void 
-+sc_security_token_get_property (GObject    *object,
-+				guint        prop_id,
-+				GValue      *value,
-+				GParamSpec  *pspec)
-+{
-+    ScSecurityToken *token = SC_SECURITY_TOKEN (object);
-+
-+    switch (prop_id)
-+    {
-+	    case PROP_SLOT_ID:
-+		    g_value_set_ulong (value, 
-+				       (gulong) sc_security_token_get_slot_id (token));
-+		    break;
-+
-+	    case PROP_SLOT_SERIES:
-+		    g_value_set_int (value, 
-+				     sc_security_token_get_slot_series (token));
-+		    break;
-+
-+	    default:
-+		    G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-+    }
-+}
-+
-+void
-+sc_security_token_set_slot_id (ScSecurityToken *token,
-+			       gint             slot_id)
-+{
-+    if (token->priv->slot_id != slot_id)
-+    {
-+	    token->priv->slot_id = slot_id;
-+
-+	    token->priv->slot = sc_security_token_find_slot_from_id (token,
-+								     token->priv->slot_id);
-+
-+	    g_object_notify (G_OBJECT (token), "slot-id");
-+    }
-+}
-+
-+void
-+sc_security_token_set_slot_series (ScSecurityToken *token,
-+				   gint             slot_series)
-+{
-+    if (token->priv->slot_series != slot_series)
-+    {
-+	    token->priv->slot_series = slot_series;
-+	    g_object_notify (G_OBJECT (token), "slot-series");
-+    }
-+}
-+
-+static void
-+sc_security_token_set_module (ScSecurityToken *token,
-+			      SECMODModule    *module)
-+{
-+    gboolean should_notify;
-+
-+    if (token->priv->module != module)
-+	    should_notify = TRUE;
-+    else
-+	    should_notify = FALSE;
-+
-+    if (token->priv->module != NULL) {
-+	    SECMOD_DestroyModule (token->priv->module);
-+	    token->priv->module = NULL;
-+    }
-+
-+    if (module != NULL)
-+	    token->priv->module = SECMOD_ReferenceModule (module);
-+
-+    if (should_notify)
-+	    g_object_notify (G_OBJECT (token), "module");
-+}
-+
-+gint 
-+sc_security_token_get_slot_series (ScSecurityToken *token)
-+{
-+    return token->priv->slot_series;
-+}
-+
-+static void
-+sc_security_token_init (ScSecurityToken *token)
-+{
-+
-+    sc_debug ("initializing security token ");
-+
-+    token->priv = G_TYPE_INSTANCE_GET_PRIVATE (token,
-+					       SC_TYPE_SECURITY_TOKEN,
-+					       ScSecurityTokenPrivate);
-+}
-+
-+static void sc_security_token_finalize (GObject *object)
-+{
-+    ScSecurityToken *token;
-+    GObjectClass *gobject_class;
-+
-+    token = SC_SECURITY_TOKEN (object);
-+
-+    sc_security_token_set_module (token, NULL);
-+
-+    gobject_class =
-+	    G_OBJECT_CLASS (sc_security_token_parent_class);
-+
-+    gobject_class->finalize (object);
-+}
-+
-+GQuark sc_security_token_error_quark (void)
-+{
-+    static GQuark error_quark = 0;
-+
-+    if (error_quark == 0)
-+	    error_quark = g_quark_from_static_string ("sc-security-token-error-quark");
-+
-+    return error_quark;
-+}
-+
-+ScSecurityToken *
-+_sc_security_token_new (SECMODModule *module,
-+			CK_SLOT_ID    slot_id,
-+			gint          slot_series)
-+{
-+    ScSecurityToken *token;
-+
-+    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);
-+
-+    token = SC_SECURITY_TOKEN (g_object_new (SC_TYPE_SECURITY_TOKEN,
-+					     "module", module,
-+					     "slot-id", (gulong) slot_id,
-+					     "slot-series", slot_series,
-+					     NULL));
-+    return token;
-+}
-+
-+void 
-+_sc_security_token_set_state (ScSecurityToken      *token,
-+			      ScSecurityTokenState  state)
-+{
-+    sc_security_token_fetch_certificates (token);
-+    if (token->priv->state != state)
-+    {
-+	    token->priv->state = state;
-+
-+	    if (state == SC_SECURITY_TOKEN_STATE_INSERTED) {
-+		    g_signal_emit (token, sc_security_token_signals[INSERTED], 0);
-+	    } else if (state == SC_SECURITY_TOKEN_STATE_REMOVED)
-+		    g_signal_emit (token, sc_security_token_signals[REMOVED], 0);
-+	    else
-+		    g_assert_not_reached ();
-+    }
-+}
-+
-+/* So we could conceivably make the closure data a pointer to the token
-+ * 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 *
-+sc_security_token_password_handler (PK11SlotInfo *slot, 
-+				    PRBool        is_retrying, 
-+				    const gchar  *password)
-+{
-+    if (is_retrying)
-+	    return NULL;
-+
-+    return password != NULL? PL_strdup (password): NULL;
-+}
-+
-+gboolean
-+sc_security_token_unlock (ScSecurityToken *token,
-+			  const gchar     *password)
-+{   
-+    SECStatus status;
-+
-+    PK11_SetPasswordFunc ((PK11PasswordFunc) sc_security_token_password_handler);
-+
-+    /* we pass PR_TRUE to load certificates
-+     */
-+    status = PK11_Authenticate (token->priv->slot, PR_TRUE, (gpointer) password);
-+
-+    if (status != SECSuccess) {
-+	    sc_debug ("could not unlock token - %d", status);
-+	    return FALSE;
-+    }
-+    return TRUE;
-+}
-+
-+static PK11SlotInfo *
-+sc_security_token_find_slot_from_id (ScSecurityToken *token,
-+                                     gint slot_id)
-+{
-+    int i;
-+
-+    for (i = 0; i < token->priv->module->slotCount; i++)
-+	    if (PK11_GetSlotID (token->priv->module->slots[i]) == slot_id)
-+		    return token->priv->module->slots[i];
-+
-+    return NULL;
-+}
-+
-+static gboolean
-+sc_security_token_fetch_certificates (ScSecurityToken *token)
-+{
-+    PK11SlotInfo *slot;
-+    CERTCertList *certificates;
-+    CERTCertListNode *node;
-+    SECStatus status;
-+    int i;
-+
-+    sc_security_token_unlock (token, "0000");
-+
-+    sc_debug ("fetching certificates for token in slot %lu",
-+	      token->priv->slot_id);
-+
-+    slot = sc_security_token_find_slot_from_id (token,
-+						token->priv->slot_id);
-+
-+    g_assert (PK11_GetSlotID (slot) == token->priv->slot_id);
-+
-+    if (i == token->priv->module->slotCount) {
-+	    sc_debug ("could not find slot %lu", token->priv->slot_id);
-+	    return FALSE;
-+    }
-+
-+    certificates = PK11_ListCertsInSlot (slot);
-+
-+    sc_debug ("filtering out non-user certificates");
-+    if (CERT_FilterCertListForUserCerts (certificates) != SECSuccess) {
-+	    CERT_DestroyCertList (certificates);
-+	    sc_debug ("could not filter out non-user certificates");
-+	    return FALSE;
-+    }
-+
-+    for (node = CERT_LIST_HEAD (certificates); 
-+	 !CERT_LIST_END (node, certificates);
-+	 node = CERT_LIST_NEXT(node)) {
-+
-+	    SECCertificateUsage cert_usages;
-+
-+	    sc_debug ("verifying certificate for use");
-+	    status = CERT_VerifyCertificateNow (NULL, node->cert, TRUE, 
-+						0, NULL, &cert_usages);
-+
-+	    if (status != SECSuccess) {
-+		    sc_debug ("could not be verified, skipping...");
-+		    continue;
-+	    }
-+
-+	    sc_debug ("got cert with usages 0x%x", cert_usages);
-+
-+	    if (token->priv->encryption_certificate == NULL) {
-+
-+		    sc_debug ("checking if certificate can be used for data "
-+			      "encryption");
-+		    status = CERT_CheckCertUsage (node->cert, 
-+						  KU_DATA_ENCIPHERMENT);
-+
-+		    if (status == SECSuccess) {
-+			    token->priv->encryption_certificate = 
-+				    CERT_DupCertificate (node->cert);
-+			    sc_debug ("using encryption certificate:\n%s", 
-+				      CERT_HTMLCertInfo (node->cert, PR_FALSE, PR_TRUE));
-+		    } else {
-+			    sc_debug ("certificate can not be used for encryption");
-+		    }
-+	    }
-+
-+	    if (token->priv->signing_certificate == NULL) {
-+
-+		    sc_debug ("checking if certificate can be used for data "
-+			      "signing");
-+		    status = CERT_CheckCertUsage (node->cert, 
-+						  KU_DIGITAL_SIGNATURE);
-+
-+		    if (status == SECSuccess) {
-+			    token->priv->signing_certificate = 
-+				    CERT_DupCertificate (node->cert);
-+
-+			    sc_debug ("using signing certificate:\n%s", 
-+				      CERT_HTMLCertInfo (node->cert, PR_FALSE, PR_TRUE));
-+		    } else {
-+			    sc_debug ("certificate can not be used for signing things");
-+		    }
-+	    }
-+    }
-+    return TRUE;
-+}
-+
-+ScSecurityTokenRequest *
-+sc_security_token_upload_data (ScSecurityToken *token,
-+			       const gchar     *key,
-+			       const gchar     *data)
-+{
-+    return NULL;
-+}
-+
-+ScSecurityTokenRequest *
-+sc_security_token_download_data (ScSecurityToken *token,
-+				 const gchar     *key)
-+{
-+    return NULL;
-+}
-+
-+ScSecurityTokenRequest *
-+sc_security_token_delete_data (ScSecurityToken *token,
-+			       const gchar     *key)
-+{
-+    return NULL;
-+}
-+
-+#ifdef SC_SECURITY_TOKEN_ENABLE_TEST
-+#include <glib.h>
-+
-+static GMainLoop *event_loop;
-+
-+int 
-+main (int   argc, 
-+      char *argv[])
-+{
-+    ScSecurityToken *token;
-+    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 'security token' object...");
-+    token = _sc_security_token_new (NULL, 1, 1);
-+    g_message ("'security token' object created successfully");
-+
-+    g_message ("destroying previously created 'security token' object...");
-+    g_object_unref (token);
-+    token = NULL;
-+    g_message ("'security token' object destroyed successfully");
-+
-+    return 0;
-+}
-+#endif
---- /dev/null
-+++ gdm-2.15.6/utils/securitytoken.h
-@@ -0,0 +1,97 @@
-+/* securitytoken.h - api for reading and writing data to a security token 
-+ *
-+ * 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 SC_SECURITY_TOKEN_H
-+#define SC_SECURITY_TOKEN_H
-+
-+#include <glib.h>
-+#include <glib-object.h>
-+
-+#include <secmod.h>
-+
-+G_BEGIN_DECLS
-+#define SC_TYPE_SECURITY_TOKEN            (sc_security_token_get_type ())
-+#define SC_SECURITY_TOKEN(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), SC_TYPE_SECURITY_TOKEN, ScSecurityToken))
-+#define SC_SECURITY_TOKEN_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), SC_TYPE_SECURITY_TOKEN, ScSecurityTokenClass))
-+#define SC_IS_SECURITY_TOKEN(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SC_TYPE_SECURITY_TOKEN))
-+#define SC_IS_SECURITY_TOKEN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SC_TYPE_SECURITY_TOKEN))
-+#define SC_SECURITY_TOKEN_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), SC_TYPE_SECURITY_TOKEN, ScSecurityTokenClass))
-+#define SC_SECURITY_TOKEN_ERROR           (sc_security_token_error_quark ())
-+typedef struct _ScSecurityTokenClass ScSecurityTokenClass;
-+typedef struct _ScSecurityToken ScSecurityToken;
-+typedef struct _ScSecurityTokenPrivate ScSecurityTokenPrivate;
-+typedef enum _ScSecurityTokenError ScSecurityTokenError;
-+typedef enum _ScSecurityTokenState ScSecurityTokenState;
-+
-+typedef struct _ScSecurityTokenRequest ScSecurityTokenRequest;
-+
-+struct _ScSecurityToken {
-+    GObject parent;
-+
-+    /*< private > */
-+    ScSecurityTokenPrivate *priv;
-+};
-+
-+struct _ScSecurityTokenClass {
-+    GObjectClass parent_class;
-+
-+    void (* inserted) (ScSecurityToken *token);
-+    void (* removed) (ScSecurityToken *token);
-+};
-+
-+enum _ScSecurityTokenError {
-+    SC_SECURITY_TOKEN_ERROR_GENERIC = 0,
-+};
-+
-+enum _ScSecurityTokenState {
-+    SC_SECURITY_TOKEN_STATE_INSERTED = 0,
-+    SC_SECURITY_TOKEN_STATE_REMOVED,
-+};
-+
-+GType sc_security_token_get_type (void) G_GNUC_CONST;
-+GQuark sc_security_token_error_quark (void) G_GNUC_CONST;
-+
-+CK_SLOT_ID sc_security_token_get_slot_id (ScSecurityToken *token);
-+gint sc_security_token_get_slot_series (ScSecurityToken *token);
-+
-+gboolean sc_security_token_unlock (ScSecurityToken *token,
-+				   const gchar     *password);
-+
-+ScSecurityTokenRequest *sc_security_token_upload_data (ScSecurityToken *token,
-+						       const gchar     *key,
-+						       const gchar     *data);
-+
-+ScSecurityTokenRequest *sc_security_token_download_data (ScSecurityToken *token,
-+							 const gchar     *key);
-+
-+ScSecurityTokenRequest *sc_security_token_delete_data (ScSecurityToken *token,
-+						       const gchar     *key);
-+
-+/* don't under any circumstances call these functions */
-+#ifdef SC_SECURITY_TOKEN_ENABLE_INTERNAL_API
-+
-+ScSecurityToken *_sc_security_token_new (SECMODModule *module,
-+					 CK_SLOT_ID slot_id, 
-+					 gint slot_series);
-+void _sc_security_token_set_state (ScSecurityToken      *token,
-+				   ScSecurityTokenState  state);
-+#endif 
-+
-+G_END_DECLS
-+#endif				/* SC_SECURITY_TOKEN_H */
---- /dev/null
-+++ gdm-2.15.6/utils/securitytokenmonitor.c
-@@ -0,0 +1,819 @@
-+/* securitytokenmonitor.c - monitor for security token insertion and
-+ *                          removal events
-+ * 
-+ * Copyright (C) 2006 Ray Strode <rstrode at redhat.com>
-+ * 
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2, or (at your option)
-+ * any later version.
-+ * 
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ * 
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-+ * 02111-1307, USA.  
-+ *
-+ * TODO:     - doing this per project is a bad idea i think.
-+ *             We should probably make this a system service 
-+ *             and use dbus.
-+ *
-+ *           - We hardcode a driver right now.  We should probably
-+ *             look up the default list and go from there. 
-+ */
-+#include "securitytokenmonitor.h"
-+
-+#define SC_SECURITY_TOKEN_ENABLE_INTERNAL_API
-+#include "securitytoken.h"
-+
-+#include <errno.h>
-+#include <string.h>
-+#include <unistd.h>
-+
-+#include <glib.h>
-+#include <glib/gi18n.h>
-+
-+#include <prerror.h>
-+#include <nss.h>
-+#include <pk11func.h>
-+#include <secmod.h>
-+#include <secerr.h>
-+
-+#include "marshal.h"
-+
-+#ifndef SC_SECURITY_TOKEN_MONITOR_ENABLE_TEST
-+#include "misc.h"
-+#endif
-+
-+#ifndef SC_SECURITY_TOKEN_MONITOR_DRIVER
-+#define SC_SECURITY_TOKEN_MONITOR_DRIVER LIBDIR"/pkcs11/libcoolkeypk11.so"
-+#endif
-+
-+#ifndef SC_SECURITY_TOKEN_MONITOR_NSS_DB
-+#define SC_SECURITY_TOKEN_MONITOR_NSS_DB SYSCONFDIR"/pki/nssdb"
-+#endif 
-+
-+#ifndef SC_SECURITY_TOKEN_MONITOR_POLL_INTERVAL
-+#define SC_SECURITY_TOKEN_MONITOR_POLL_INTERVAL 100	/* ms */
-+#endif
-+
-+#ifndef sc_debug
-+#ifdef gdm_debug
-+#define sc_debug(fmt, args...) gdm_debug(fmt, ##args)
-+#elif defined (SC_SECURITY_TOKEN_MONITOR_ENABLE_TEST)
-+#define sc_debug(fmt, args...) g_printerr(fmt "\n", ##args)
-+#else
-+#define sc_debug(fmt, args...) 
-+#endif
-+#endif
-+
-+typedef enum _ScSecurityTokenMonitorState ScSecurityTokenMonitorState;
-+
-+enum _ScSecurityTokenMonitorState {
-+	SC_SECURITY_TOKEN_MONITOR_STATE_STOPPED = 0,
-+	SC_SECURITY_TOKEN_MONITOR_STATE_STARTING,
-+	SC_SECURITY_TOKEN_MONITOR_STATE_STARTED,
-+	SC_SECURITY_TOKEN_MONITOR_STATE_STOPPING,
-+};
-+
-+struct _ScSecurityTokenMonitorPrivate {
-+	ScSecurityTokenMonitorState state;
-+
-+	gchar        *module_path;
-+	SECMODModule *module;
-+	GHashTable *security_tokens;
-+
-+	guint32 nss_is_loaded : 1;
-+	guint32 is_unstoppable : 1;
-+
-+	guint poll_timeout_id;
-+};
-+
-+static void sc_security_token_monitor_finalize (GObject *object);
-+static void sc_security_token_monitor_class_install_signals (ScSecurityTokenMonitorClass *service_class);
-+static void sc_security_token_monitor_class_install_properties (ScSecurityTokenMonitorClass *service_class);
-+static void sc_security_token_monitor_set_property (GObject       *object,
-+						    guint          prop_id,
-+						    const GValue  *value,
-+						    GParamSpec    *pspec);
-+static void sc_security_token_monitor_get_property (GObject    *object,
-+						    guint       prop_id,
-+						    GValue     *value,
-+						    GParamSpec *pspec);
-+
-+static void
-+sc_security_token_monitor_set_module_path (ScSecurityTokenMonitor *monitor,
-+					   const gchar            *module_path);
-+
-+
-+static void sc_security_token_monitor_token_removed_handler (ScSecurityTokenMonitor *monitor,
-+							     ScSecurityToken        *token);
-+static void sc_security_token_monitor_token_inserted_handler (ScSecurityTokenMonitor *monitor_class,
-+							      ScSecurityToken        *token);
-+static gboolean sc_security_token_monitor_stop_now (ScSecurityTokenMonitor *monitor);
-+
-+static void sc_security_token_monitor_queue_stop (ScSecurityTokenMonitor *monitor);
-+
-+enum {
-+	PROP_0 = 0,
-+	PROP_MODULE_PATH,
-+	NUMBER_OF_PROPERTIES
-+};
-+
-+enum {
-+	SECURITY_TOKEN_INSERTED = 0,
-+	SECURITY_TOKEN_REMOVED,
-+	ERROR,
-+	NUMBER_OF_SIGNALS
-+};
-+
-+static guint sc_security_token_monitor_signals[NUMBER_OF_SIGNALS];
-+
-+G_DEFINE_TYPE (ScSecurityTokenMonitor, 
-+	       sc_security_token_monitor, 
-+	       G_TYPE_OBJECT);
-+
-+static void
-+sc_security_token_monitor_class_init (ScSecurityTokenMonitorClass *monitor_class)
-+{
-+    GObjectClass *gobject_class;
-+
-+    gobject_class = G_OBJECT_CLASS (monitor_class);
-+
-+    gobject_class->finalize = sc_security_token_monitor_finalize;
-+
-+    sc_security_token_monitor_class_install_signals (monitor_class);
-+    sc_security_token_monitor_class_install_properties (monitor_class);
-+
-+    g_type_class_add_private (monitor_class,
-+			      sizeof (ScSecurityTokenMonitorPrivate));
-+}
-+
-+static void
-+sc_security_token_monitor_class_install_properties (ScSecurityTokenMonitorClass *token_class)
-+{
-+    GObjectClass *object_class;
-+    GParamSpec *param_spec;
-+
-+    object_class = G_OBJECT_CLASS (token_class);
-+    object_class->set_property = sc_security_token_monitor_set_property;
-+    object_class->get_property = sc_security_token_monitor_get_property;
-+
-+    param_spec = g_param_spec_string ("module-path", _("Module Path"),
-+				      _("path to security token 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 
-+sc_security_token_monitor_set_property (GObject       *object,
-+					guint          prop_id,
-+					const GValue  *value,
-+					GParamSpec    *pspec)
-+{
-+    ScSecurityTokenMonitor *monitor = SC_SECURITY_TOKEN_MONITOR (object);
-+
-+    switch (prop_id)
-+    {
-+	    case PROP_MODULE_PATH:
-+		    sc_security_token_monitor_set_module_path (monitor, 
-+							       g_value_get_string (value));
-+		    break;
-+
-+	    default:
-+		    G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-+    }
-+}
-+
-+static void 
-+sc_security_token_monitor_get_property (GObject    *object,
-+					guint       prop_id,
-+					GValue     *value,
-+					GParamSpec *pspec)
-+{
-+    ScSecurityTokenMonitor *monitor = SC_SECURITY_TOKEN_MONITOR (object);
-+    gchar *module_path;
-+
-+    switch (prop_id)
-+    {
-+	    case PROP_MODULE_PATH:
-+		    module_path = sc_security_token_monitor_get_module_path (monitor);
-+		    g_value_set_string (value, module_path);
-+		    g_free (module_path);
-+		    break;
-+
-+	    default:
-+		    G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-+    }
-+}
-+
-+gchar *
-+sc_security_token_monitor_get_module_path (ScSecurityTokenMonitor *monitor)
-+{
-+    return monitor->priv->module_path;
-+}
-+
-+static void
-+sc_security_token_monitor_set_module_path (ScSecurityTokenMonitor *monitor,
-+					   const gchar            *module_path)
-+{
-+    if (module_path == NULL)
-+	    module_path = SC_SECURITY_TOKEN_MONITOR_DRIVER;
-+
-+    g_assert (module_path != NULL);
-+
-+    if (((monitor->priv->module_path == NULL) ||
-+	 (strcmp (monitor->priv->module_path, module_path) != 0))) {
-+	    g_free (monitor->priv->module_path);
-+	    monitor->priv->module_path = g_strdup (module_path);
-+	    g_object_notify (G_OBJECT (monitor), "module-path");
-+    }
-+}
-+
-+static void
-+sc_security_token_monitor_token_removed_handler (ScSecurityTokenMonitor *monitor,
-+						 ScSecurityToken        *token)
-+{
-+    sc_debug ("informing security token of its removal");
-+    _sc_security_token_set_state (token, SC_SECURITY_TOKEN_STATE_REMOVED);
-+}
-+
-+static void
-+sc_security_token_monitor_token_inserted_handler (ScSecurityTokenMonitor *monitor,
-+						  ScSecurityToken        *token)
-+{
-+    sc_debug ("informing security token of its insertion");
-+    _sc_security_token_set_state (token, SC_SECURITY_TOKEN_STATE_INSERTED);
-+}
-+
-+static void
-+sc_security_token_monitor_class_install_signals (ScSecurityTokenMonitorClass *monitor_class)
-+{
-+    GObjectClass *object_class;
-+
-+    object_class = G_OBJECT_CLASS (monitor_class);
-+
-+    sc_security_token_monitor_signals[SECURITY_TOKEN_INSERTED] =
-+	    g_signal_new ("security-token-inserted",
-+			  G_OBJECT_CLASS_TYPE (object_class),
-+			  G_SIGNAL_RUN_FIRST,
-+			  G_STRUCT_OFFSET (ScSecurityTokenMonitorClass,
-+					   security_token_inserted), 
-+			  NULL, NULL, g_cclosure_marshal_VOID__POINTER, 
-+			  G_TYPE_NONE, 1, G_TYPE_POINTER);
-+    monitor_class->security_token_inserted = sc_security_token_monitor_token_inserted_handler;
-+
-+    sc_security_token_monitor_signals[SECURITY_TOKEN_REMOVED] =
-+	    g_signal_new ("security-token-removed",
-+			  G_OBJECT_CLASS_TYPE (object_class),
-+			  G_SIGNAL_RUN_FIRST,
-+			  G_STRUCT_OFFSET (ScSecurityTokenMonitorClass,
-+					   security_token_removed), 
-+			  NULL, NULL, g_cclosure_marshal_VOID__POINTER, 
-+			  G_TYPE_NONE, 1, G_TYPE_POINTER);
-+    monitor_class->security_token_removed = sc_security_token_monitor_token_removed_handler;
-+
-+    sc_security_token_monitor_signals[ERROR] =
-+	    g_signal_new ("error",
-+			  G_OBJECT_CLASS_TYPE (object_class),
-+			  G_SIGNAL_RUN_LAST,
-+			  G_STRUCT_OFFSET (ScSecurityTokenMonitorClass, error),
-+			  NULL, NULL, g_cclosure_marshal_VOID__POINTER,
-+			  G_TYPE_NONE, 1, G_TYPE_POINTER);
-+    monitor_class->error = NULL;
-+}
-+
-+static gboolean
-+sc_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
-+sc_slot_id_hash (CK_SLOT_ID *slot_id) 
-+{
-+    guint32 upper_bits, lower_bits;
-+    gint temp;
-+
-+    if (sizeof (CK_SLOT_ID) == sizeof (gint))
-+	    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
-+sc_security_token_monitor_init (ScSecurityTokenMonitor *monitor)
-+{
-+    sc_debug ("initializing security token monitor");
-+
-+    monitor->priv = G_TYPE_INSTANCE_GET_PRIVATE (monitor,
-+						 SC_TYPE_SECURITY_TOKEN_MONITOR,
-+						 ScSecurityTokenMonitorPrivate);
-+    monitor->priv->poll_timeout_id = 0;
-+    monitor->priv->security_tokens = NULL;
-+    monitor->priv->is_unstoppable = FALSE;
-+}
-+
-+static void 
-+sc_security_token_monitor_finalize (GObject *object)
-+{
-+    ScSecurityTokenMonitor *monitor;
-+    GObjectClass *gobject_class;
-+
-+    monitor = SC_SECURITY_TOKEN_MONITOR (object);
-+    gobject_class =
-+	    G_OBJECT_CLASS (sc_security_token_monitor_parent_class);
-+
-+    sc_security_token_monitor_stop_now (monitor);
-+
-+    gobject_class->finalize (object);
-+}
-+
-+GQuark 
-+sc_security_token_monitor_error_quark (void)
-+{
-+    static GQuark error_quark = 0;
-+
-+    if (error_quark == 0)
-+	    error_quark = g_quark_from_static_string ("sc-security-token-monitor-error-quark");
-+
-+    return error_quark;
-+}
-+
-+ScSecurityTokenMonitor *
-+sc_security_token_monitor_new (const gchar *module_path)
-+{
-+    ScSecurityTokenMonitor *instance;
-+
-+    instance = SC_SECURITY_TOKEN_MONITOR (g_object_new (SC_TYPE_SECURITY_TOKEN_MONITOR, 
-+							"module-path", module_path,
-+							NULL));
-+
-+    return instance;
-+}
-+
-+static void 
-+sc_security_token_monitor_emit_error (ScSecurityTokenMonitor *monitor,
-+				      GError                 *error)
-+{
-+    monitor->priv->is_unstoppable = TRUE;
-+    g_signal_emit (monitor, sc_security_token_monitor_signals[ERROR], 0,
-+		   error);
-+    monitor->priv->is_unstoppable = FALSE;
-+}
-+
-+static void 
-+sc_security_token_monitor_emit_security_token_inserted (ScSecurityTokenMonitor *monitor,
-+							ScSecurityToken        *token)
-+{
-+    monitor->priv->is_unstoppable = TRUE;
-+    g_signal_emit (monitor, sc_security_token_monitor_signals[SECURITY_TOKEN_INSERTED], 0,
-+		   token);
-+    monitor->priv->is_unstoppable = FALSE;
-+}
-+
-+static void 
-+sc_security_token_monitor_emit_security_token_removed (ScSecurityTokenMonitor *monitor,
-+							ScSecurityToken        *token)
-+{
-+    ScSecurityTokenMonitorState old_state;
-+
-+    old_state = monitor->priv->state;
-+    monitor->priv->is_unstoppable = TRUE;
-+    g_signal_emit (monitor, sc_security_token_monitor_signals[SECURITY_TOKEN_REMOVED], 0,
-+		   token);
-+    monitor->priv->is_unstoppable = FALSE;
-+}
-+
-+static gboolean
-+sc_security_token_monitor_check_for_and_process_events (ScSecurityTokenMonitor *monitor)
-+{
-+    PK11SlotInfo *slot;
-+    CK_SLOT_ID slot_id, *key;
-+    gint slot_series, token_slot_series;
-+    ScSecurityToken *token;
-+
-+    slot = SECMOD_WaitForAnyTokenEvent (monitor->priv->module, CKF_DONT_BLOCK,
-+					PR_INTERVAL_NO_WAIT);
-+
-+    if (slot == NULL) {
-+	    GError *error;
-+	    int error_code;
-+
-+	    error_code = PORT_GetError ();
-+	    if ((error_code == 0) || (error_code == SEC_ERROR_NO_EVENT))
-+		    return TRUE;
-+
-+	    /* FIXME: is there a function to convert from a PORT error
-+	     * code to a translated string?
-+	     */
-+	    error = g_error_new (SC_SECURITY_TOKEN_MONITOR_ERROR,
-+				 SC_SECURITY_TOKEN_MONITOR_ERROR_WITH_NSS,
-+				 _("encountered unexpected error while "
-+				   "waiting for security token events"));
-+	    g_error_free (error);
-+
-+	    return FALSE;
-+    }
-+
-+    /* the slot id and series together uniquely identify a token.
-+     * You can never have two tokens 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 token that we're currently
-+     * tracking in the slot.
-+     */
-+    key = g_new (CK_SLOT_ID, 1);
-+    *key = slot_id;
-+    token = g_hash_table_lookup (monitor->priv->security_tokens, key);
-+
-+    if (token != NULL)
-+	    token_slot_series = sc_security_token_get_slot_series (token);
-+
-+    if (PK11_IsPresent (slot)) {
-+	    /* Now, check to see if their is a new token in the slot.
-+	     * If there was a different token in the slot now than
-+	     * there was before, then we need to emit a removed signal
-+	     * for the old token.
-+	     * 
-+	     * FIXME: So, I *think* the reason we need to do this is
-+	     * for the case where a token is removed and another
-+	     * inserted faster than the internal poll granualarity of
-+	     * NSS. In that case we won't get a separate removed event
-+	     * so we need to handle it ourselves.  But what happens if
-+	     * a token is removed, another inserted, then removed, and
-+	     * another inserted really fast?  Shouldn't we emit
-+	     * several removed/inserted events?  If so, can we depend
-+	     * on the difference of the series numbers to determine
-+	     * how many events to emit? It's all hard to trigger
-+	     * corner cases that probably don't matter anyhow, though.
-+	     */
-+	    if ((token != NULL) && 
-+		token_slot_series != slot_series) {
-+		    sc_security_token_monitor_emit_security_token_removed (monitor, token);
-+	    }
-+
-+	    token = _sc_security_token_new (monitor->priv->module, 
-+					    slot_id, slot_series);
-+
-+	    g_hash_table_replace (monitor->priv->security_tokens,
-+				  key, token);
-+	    key = NULL;
-+
-+	    sc_security_token_monitor_emit_security_token_inserted (monitor, token);
-+    } else {
-+	    /* if we aren't tracking the token, just discard the event.
-+	     * We don't want unpaired remove events.  Note on startup
-+	     * NSS will generate an "insertion" event if a token is
-+	     * already inserted in the slot.
-+	     */
-+	    if ((token != 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 - token_slot_series + 1)
-+		     * (see the comment in the if part of this if/else
-+		     * clause for more information)
-+		     * 
-+		     * Right now, i'm just doing it once.  
-+		     */
-+		    if ((slot_series - token_slot_series) > 1) {
-+
-+			    sc_security_token_monitor_emit_security_token_removed (monitor, token);
-+			    g_hash_table_remove (monitor->priv->security_tokens, key);
-+
-+			    token = _sc_security_token_new (monitor->priv->module, 
-+							    slot_id, slot_series);
-+			    g_hash_table_replace (monitor->priv->security_tokens,
-+						  key, token);
-+			    key = NULL;
-+			    sc_security_token_monitor_emit_security_token_inserted (monitor, token);
-+		    }
-+
-+		    sc_security_token_monitor_emit_security_token_removed (monitor, token);
-+
-+		    g_hash_table_remove (monitor->priv->security_tokens, key);
-+		    token = NULL;
-+	    }
-+    }
-+
-+    g_free (key);
-+    PK11_FreeSlot (slot);
-+
-+    return TRUE;
-+}
-+
-+static void
-+sc_security_token_monitor_polling_stopped_handler (ScSecurityTokenMonitor *monitor)
-+{
-+    monitor->priv->poll_timeout_id = 0;
-+    sc_security_token_monitor_stop_now (monitor);
-+}
-+
-+gboolean
-+sc_security_token_monitor_start (ScSecurityTokenMonitor  *monitor,
-+				 GError                 **error)
-+{
-+    SECStatus status = SECSuccess;
-+    gchar *module_spec;
-+
-+    if (monitor->priv->state == SC_SECURITY_TOKEN_MONITOR_STATE_STARTED) {
-+	    sc_debug ("security token monitor already started");
-+	    return TRUE;
-+    }
-+
-+    monitor->priv->state = SC_SECURITY_TOKEN_MONITOR_STATE_STARTING;
-+
-+    if (!monitor->priv->nss_is_loaded) {
-+	    sc_debug ("attempting to load NSS database '%s'",
-+		       SC_SECURITY_TOKEN_MONITOR_NSS_DB);
-+	    status = NSS_NoDB_Init (SC_SECURITY_TOKEN_MONITOR_NSS_DB);
-+    }
-+
-+    if (status != SECSuccess) {
-+	    gsize error_message_size;
-+	    gchar *error_message;
-+
-+	    error_message_size = PR_GetErrorTextLength ();
-+
-+	    if (error_message_size == 0) {
-+		    sc_debug ("NSS security system could not be initialized");
-+		    g_set_error (error,
-+				 SC_SECURITY_TOKEN_MONITOR_ERROR,
-+				 SC_SECURITY_TOKEN_MONITOR_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,
-+			 SC_SECURITY_TOKEN_MONITOR_ERROR,
-+			 SC_SECURITY_TOKEN_MONITOR_ERROR_WITH_NSS,
-+			 "%s", error_message);
-+	    sc_debug ("NSS security system could not be initialized - %s",
-+		     error_message);
-+
-+	    g_slice_free1 (error_message_size, error_message);
-+
-+	    goto out;
-+    }
-+    sc_debug ("NSS database sucessfully loaded");
-+    monitor->priv->nss_is_loaded = TRUE;
-+
-+    if (monitor->priv->module == NULL) {
-+	    g_assert (monitor->priv->module_path != NULL);
-+	    module_spec = g_strdup_printf ("library=\"%s\" name=\"SecurityToken\"",
-+					   monitor->priv->module_path);
-+	    sc_debug ("loading security token driver using spec '%s'",
-+		     module_spec);
-+
-+	    /* FIXME: this API is apparently deprecated, find out what is replacing it
-+	     */
-+	    monitor->priv->module = SECMOD_LoadUserModule (module_spec, 
-+							   NULL /* parent */, 
-+							   FALSE /* recurse */);
-+	    g_free (module_spec);
-+    }
-+
-+    if ((monitor->priv->module == NULL) || !monitor->priv->module->loaded) {
-+	    gsize error_message_size;
-+	    gchar *error_message;
-+
-+	    error_message_size = PR_GetErrorTextLength ();
-+
-+	    if (error_message_size == 0) {
-+		    sc_debug ("security token driver '%s' could not be loaded",
-+			     monitor->priv->module_path);
-+		    g_set_error (error,
-+				 SC_SECURITY_TOKEN_MONITOR_ERROR,
-+				 SC_SECURITY_TOKEN_MONITOR_ERROR_LOADING_DRIVER,
-+				 _
-+				 ("security token driver '%s' could not be loaded"),
-+				 monitor->priv->module_path);
-+		    goto out;
-+	    }
-+
-+	    error_message = g_slice_alloc0 (error_message_size);
-+	    PR_GetErrorText (error_message);
-+
-+	    g_set_error (error,
-+			 SC_SECURITY_TOKEN_MONITOR_ERROR,
-+			 SC_SECURITY_TOKEN_MONITOR_ERROR_LOADING_DRIVER,
-+			 "%s", error_message);
-+
-+	    sc_debug ("security token driver '%s' could not be loaded - %s",
-+		     monitor->priv->module_path, error_message);
-+	    g_slice_free1 (error_message_size, error_message);
-+
-+	    goto out;
-+    }
-+
-+    /* FIXME: so it sort of sucks that we have to poll here.  NSS
-+     * does offer a non-blocking API (that we use), but there is
-+     * no way to wake up the event loop when new events arrive, so
-+     * we just have to poll periodically.  An alternative would be
-+     * to fork (or bring in threads, ick) and use the blocking api
-+     * plus a message pipe, but that's significantly more
-+     * complicated to implement.  Maybe a better solution is to
-+     * move all this off to Yet Another Daemon Process and have it
-+     * emit dbus signals that we watch for.
-+     */
-+    monitor->priv->poll_timeout_id =
-+	    g_timeout_add_full (G_PRIORITY_DEFAULT_IDLE,
-+				SC_SECURITY_TOKEN_MONITOR_POLL_INTERVAL,
-+				(GSourceFunc)
-+				sc_security_token_monitor_check_for_and_process_events,
-+				monitor, (GDestroyNotify)
-+				sc_security_token_monitor_polling_stopped_handler);
-+
-+    monitor->priv->security_tokens =
-+	    g_hash_table_new_full ((GHashFunc) sc_slot_id_hash, 
-+				   (GEqualFunc) sc_slot_id_equal, 
-+				   (GDestroyNotify) g_free, 
-+				   (GDestroyNotify) g_object_unref);
-+
-+    monitor->priv->state = SC_SECURITY_TOKEN_MONITOR_STATE_STARTED;
-+
-+out:
-+    /* don't leave it in a half started state
-+     */
-+    if (monitor->priv->state != SC_SECURITY_TOKEN_MONITOR_STATE_STARTED) {
-+	    sc_debug
-+		    ("security token monitor could not be completely started");
-+	    sc_security_token_monitor_stop (monitor);
-+    } else
-+	    sc_debug ("security token monitor started");
-+
-+    return monitor->priv->state == SC_SECURITY_TOKEN_MONITOR_STATE_STARTED;
-+}
-+
-+static gboolean
-+sc_security_token_monitor_stop_now (ScSecurityTokenMonitor *monitor)
-+{
-+    if (monitor->priv->state == SC_SECURITY_TOKEN_MONITOR_STATE_STOPPED)
-+	    return FALSE;
-+
-+    sc_debug ("stopping security token monitor");
-+
-+    monitor->priv->state = SC_SECURITY_TOKEN_MONITOR_STATE_STOPPED;
-+    if (monitor->priv->security_tokens != NULL) {
-+	    g_hash_table_destroy (monitor->priv->security_tokens);
-+	    monitor->priv->security_tokens = NULL;
-+    }
-+
-+    if (monitor->priv->poll_timeout_id != 0) {
-+	    g_source_remove (monitor->priv->poll_timeout_id);
-+	    monitor->priv->poll_timeout_id = 0;
-+    }
-+
-+#ifdef SC_SECURITY_TOKEN_MONITOR_DRIVER_CAN_BE_RELOADED_AFTER_BEING_DESTROYED
-+    if (monitor->priv->module != NULL) {
-+	    SECMOD_DestroyModule (monitor->priv->module);
-+	    monitor->priv->module = NULL;
-+    }
-+
-+    if (monitor->priv->nss_is_loaded) {
-+	    NSS_Shutdown ();
-+	    monitor->priv->nss_is_loaded = FALSE;
-+    }
-+#endif
-+    sc_debug ("security token monitor stopped");
-+    
-+    return FALSE;
-+}
-+
-+static void
-+sc_security_token_monitor_queue_stop (ScSecurityTokenMonitor *monitor)
-+{
-+
-+    monitor->priv->state = SC_SECURITY_TOKEN_MONITOR_STATE_STOPPING;
-+
-+    g_idle_add ((GSourceFunc) sc_security_token_monitor_stop_now, monitor);
-+}
-+
-+void 
-+sc_security_token_monitor_stop (ScSecurityTokenMonitor *monitor)
-+{
-+    if (monitor->priv->state == SC_SECURITY_TOKEN_MONITOR_STATE_STOPPED)
-+	    return;
-+
-+    if (monitor->priv->is_unstoppable) {
-+	    sc_security_token_monitor_queue_stop (monitor);
-+	    return;
-+    } 
-+
-+    sc_security_token_monitor_stop_now (monitor);
-+}
-+
-+#ifdef SC_SECURITY_TOKEN_MONITOR_ENABLE_TEST
-+#include <glib.h>
-+
-+static GMainLoop *event_loop;
-+static gboolean should_exit_on_next_remove = FALSE;
-+
-+static gboolean on_timeout (ScSecurityTokenMonitor *monitor)
-+{
-+    GError *error;
-+    g_print ("Re-enabling monitor.\n");
-+
-+    if (!sc_security_token_monitor_start (monitor, &error)) {
-+	    g_warning ("could not start security token monitor - %s",
-+		       error->message);
-+	    g_error_free (error);
-+	    return 1;
-+    }
-+    g_print ("Please re-insert security token\n");
-+
-+    should_exit_on_next_remove = TRUE;
-+
-+    return FALSE;
-+}
-+
-+static void
-+on_device_inserted (ScSecurityTokenMonitor * monitor,
-+		    ScSecurityToken *token)
-+{
-+    g_print ("security token inserted!\n");
-+    g_print ("Please remove it.\n");
-+}
-+
-+static void
-+on_device_removed (ScSecurityTokenMonitor * monitor,
-+		   ScSecurityToken *token)
-+{
-+    g_print ("security token removed!\n");
-+
-+    if (should_exit_on_next_remove)
-+	    g_main_loop_quit (event_loop);
-+    else {
-+	    g_print ("disabling monitor for 2 seconds\n");
-+	    sc_security_token_monitor_stop (monitor);
-+	    g_timeout_add (2000, (GSourceFunc) on_timeout, monitor);
-+    }
-+}
-+
-+int 
-+main (int   argc, 
-+      char *argv[])
-+{
-+    ScSecurityTokenMonitor *monitor;
-+    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 'security token monitor' object...");
-+    monitor = sc_security_token_monitor_new (NULL);
-+    g_message ("'security token monitor' object created successfully");
-+
-+    g_signal_connect (monitor, "security-token-inserted",
-+		      G_CALLBACK (on_device_inserted), NULL);
-+
-+    g_signal_connect (monitor, "security-token-removed",
-+		      G_CALLBACK (on_device_removed), NULL);
-+
-+    g_message ("starting listener...");
-+
-+    error = NULL;
-+    if (!sc_security_token_monitor_start (monitor, &error)) {
-+	    g_warning ("could not start security token monitor - %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 'security token monitor' object...");
-+    g_object_unref (monitor);
-+    monitor = NULL;
-+    g_message ("'security token monitor' object destroyed successfully");
-+
-+    return 0;
-+}
-+#endif
---- /dev/null
-+++ gdm-2.15.6/utils/securitytokenmonitor.h
-@@ -0,0 +1,82 @@
-+/* securitytokenmonitor.h - monitor for security token insertion and
-+ *                          removal events
-+ *
-+ * 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 SC_SECURITY_TOKEN_MONITOR_H
-+#define SC_SECURITY_TOKEN_MONITOR_H
-+
-+#define SC_SECURITY_TOKEN_ENABLE_INTERNAL_API
-+#include "securitytoken.h"
-+
-+#include <glib.h>
-+#include <glib-object.h>
-+
-+G_BEGIN_DECLS
-+#define SC_TYPE_SECURITY_TOKEN_MONITOR            (sc_security_token_monitor_get_type ())
-+#define SC_SECURITY_TOKEN_MONITOR(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), SC_TYPE_SECURITY_TOKEN_MONITOR, ScSecurityTokenMonitor))
-+#define SC_SECURITY_TOKEN_MONITOR_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), SC_TYPE_SECURITY_TOKEN_MONITOR, ScSecurityTokenMonitorClass))
-+#define SC_IS_SECURITY_TOKEN_MONITOR(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SC_TYPE_SECURITY_TOKEN_MONITOR))
-+#define SC_IS_SECURITY_TOKEN_MONITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SC_TYPE_SECURITY_TOKEN_MONITOR))
-+#define SC_SECURITY_TOKEN_MONITOR_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), SC_TYPE_SECURITY_TOKEN_MONITOR, ScSecurityTokenMonitorClass))
-+#define SC_SECURITY_TOKEN_MONITOR_ERROR           (sc_security_token_monitor_error_quark ())
-+typedef struct _ScSecurityTokenMonitor ScSecurityTokenMonitor;
-+typedef struct _ScSecurityTokenMonitorClass ScSecurityTokenMonitorClass;
-+typedef struct _ScSecurityTokenMonitorPrivate ScSecurityTokenMonitorPrivate;
-+typedef enum _ScSecurityTokenMonitorError ScSecurityTokenMonitorError;
-+
-+struct _ScSecurityTokenMonitor {
-+    GObject parent;
-+
-+    /*< private > */
-+    ScSecurityTokenMonitorPrivate *priv;
-+};
-+
-+struct _ScSecurityTokenMonitorClass {
-+    GObjectClass parent_class;
-+
-+    /* Signals */
-+    void (*security_token_inserted) (ScSecurityTokenMonitor *monitor,
-+				     ScSecurityToken *token);
-+    void (*security_token_removed) (ScSecurityTokenMonitor *monitor,
-+				    ScSecurityToken *token);
-+    void (*error) (ScSecurityTokenMonitor *monitor, 
-+		   GError                 *error);
-+};
-+
-+enum _ScSecurityTokenMonitorError {
-+    SC_SECURITY_TOKEN_MONITOR_ERROR_GENERIC = 0,
-+    SC_SECURITY_TOKEN_MONITOR_ERROR_WITH_NSS,
-+    SC_SECURITY_TOKEN_MONITOR_ERROR_LOADING_DRIVER,
-+};
-+
-+GType sc_security_token_monitor_get_type (void) G_GNUC_CONST;
-+GQuark sc_security_token_monitor_error_quark (void) G_GNUC_CONST;
-+
-+ScSecurityTokenMonitor *sc_security_token_monitor_new (const gchar *module);
-+
-+
-+gboolean sc_security_token_monitor_start (ScSecurityTokenMonitor  *monitor, 
-+				 	  GError                 **error);
-+
-+void sc_security_token_monitor_stop (ScSecurityTokenMonitor *monitor);
-+
-+gchar *sc_security_token_monitor_get_module_path (ScSecurityTokenMonitor *monitor);
-+
-+G_END_DECLS
-+#endif				/* SC_SECURITY_TOKEN_MONITOR_H */
++++ gdm-2.15.6/config/securitytokens.conf.in
+@@ -0,0 +1,4 @@
++[SecurityTokens]
++Enable=true
++#Driver=@libdir@/pkcs11/libcoolkeypk11.so
++#PamStack=gdm-securitytokens
+




More information about the fedora-cvs-commits mailing list