William Jon McCann e8d4c0e
diff -up gnome-screensaver-2.23.90/configure.ac.securitytoken gnome-screensaver-2.23.90/configure.ac
William Jon McCann e8d4c0e
--- gnome-screensaver-2.23.90/configure.ac.securitytoken	2008-08-28 14:34:41.000000000 -0400
William Jon McCann e8d4c0e
+++ gnome-screensaver-2.23.90/configure.ac	2008-08-28 17:32:30.000000000 -0400
William Jon McCann e8d4c0e
@@ -45,6 +45,7 @@ GNOME_DESKTOP_REQUIRED_VERSION=2.23.2
William Jon McCann e8d4c0e
 
William Jon McCann e8d4c0e
 GLADE_REQUIRED_VERSION=2.5.0
William Jon McCann e8d4c0e
 LIBGNOMEKBDUI_REQUIRED_VERSION=0.1
William Jon McCann e8d4c0e
+NSS_REQUIRED_VERSION=3.11.2
William Jon McCann e8d4c0e
 
William Jon McCann e8d4c0e
 AC_CHECK_HEADERS(unistd.h)
William Jon McCann e8d4c0e
 AC_CHECK_HEADERS(crypt.h sys/select.h)
William Jon McCann e8d4c0e
@@ -59,7 +60,8 @@ PKG_CHECK_MODULES(GNOME_SCREENSAVER,
William Jon McCann e8d4c0e
         dbus-glib-1 >= $DBUS_REQUIRED_VERSION
William Jon McCann e8d4c0e
         gconf-2.0 >= $GCONF_REQUIRED_VERSION
William Jon McCann e8d4c0e
         gnome-desktop-2.0 >= $GNOME_DESKTOP_REQUIRED_VERSION
William Jon McCann e8d4c0e
-        libgnome-menu >= $LIBGNOME_MENU_REQUIRED_VERSION)
William Jon McCann e8d4c0e
+        libgnome-menu >= $LIBGNOME_MENU_REQUIRED_VERSION
William Jon McCann e8d4c0e
+        nss >= $NSS_REQUIRED_VERSION)
William Jon McCann e8d4c0e
 AC_SUBST(GNOME_SCREENSAVER_CFLAGS)
William Jon McCann e8d4c0e
 AC_SUBST(GNOME_SCREENSAVER_LIBS)
William Jon McCann e8d4c0e
 
William Jon McCann e8d4c0e
@@ -96,8 +98,6 @@ AC_PATH_PROG(GCONFTOOL, gconftool-2)
William Jon McCann e8d4c0e
 
William Jon McCann e8d4c0e
 AM_GCONF_SOURCE_2
William Jon McCann e8d4c0e
 
William Jon McCann e8d4c0e
-GNOME_COMPILE_WARNINGS(yes)
William Jon McCann e8d4c0e
-
William Jon McCann e8d4c0e
 # Solaris requires libresolv for daemon()
William Jon McCann e8d4c0e
 case "$host" in
William Jon McCann e8d4c0e
 	*-*-solaris*)
William Jon McCann e8d4c0e
@@ -171,6 +171,13 @@ PKG_CHECK_MODULES(LIB_GNOME_MENU,
William Jon McCann e8d4c0e
 AC_SUBST(LIB_GNOME_MENU_CFLAGS)
William Jon McCann e8d4c0e
 AC_SUBST(LIB_GNOME_MENU_LIBS)
William Jon McCann e8d4c0e
 
William Jon McCann e8d4c0e
+# security token support
William Jon McCann e8d4c0e
+PKG_CHECK_MODULES(SECURITY_TOKEN,
William Jon McCann e8d4c0e
+        gobject-2.0 >= $GLIB_REQUIRED_VERSION
William Jon McCann e8d4c0e
+        nss >= $NSS_REQUIRED_VERSION)
William Jon McCann e8d4c0e
+AC_SUBST(SECURITY_TOKEN_CFLAGS)
William Jon McCann e8d4c0e
+AC_SUBST(SECURITY_TOKEN_LIBS)
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
 dnl ---------------------------------------------------------------------------
William Jon McCann e8d4c0e
 dnl - Where should we put documentation ?
William Jon McCann e8d4c0e
 dnl ---------------------------------------------------------------------------
William Jon McCann e8d4c0e
diff -up gnome-screensaver-2.23.3/src/gs-auth-pam.c.securitytoken gnome-screensaver-2.23.3/src/gs-auth-pam.c
William Jon McCann e8d4c0e
--- gnome-screensaver-2.23.3/src/gs-auth-pam.c.securitytoken	2008-04-29 22:30:08.000000000 -0400
William Jon McCann e8d4c0e
+++ gnome-screensaver-2.23.3/src/gs-auth-pam.c	2008-07-27 23:20:06.000000000 -0400
William Jon McCann e8d4c0e
@@ -354,6 +354,13 @@ close_pam_handle (int status)
William Jon McCann e8d4c0e
                                    status2,
William Jon McCann e8d4c0e
                                    (status2 == PAM_SUCCESS ? "Success" : "Failure"));
William Jon McCann e8d4c0e
                 }
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+		/* iterate the glib event loop inbetween processing pam
William Jon McCann e8d4c0e
+		 * messages so that the user interface can be updated
William Jon McCann e8d4c0e
+		 * to reflect changes that are a result of the pam
William Jon McCann e8d4c0e
+		 * messages
William Jon McCann e8d4c0e
+		 */
William Jon McCann e8d4c0e
+		while (g_main_context_iteration (NULL, FALSE));
William Jon McCann e8d4c0e
         }
William Jon McCann e8d4c0e
 
William Jon McCann e8d4c0e
         if (message_handled_condition != NULL) {
William Jon McCann e8d4c0e
diff -up gnome-screensaver-2.23.3/src/gs-monitor.c.securitytoken gnome-screensaver-2.23.3/src/gs-monitor.c
William Jon McCann e8d4c0e
--- gnome-screensaver-2.23.3/src/gs-monitor.c.securitytoken	2008-04-29 22:30:08.000000000 -0400
William Jon McCann e8d4c0e
+++ gnome-screensaver-2.23.3/src/gs-monitor.c	2008-07-27 23:20:06.000000000 -0400
William Jon McCann e8d4c0e
@@ -41,10 +41,15 @@
William Jon McCann e8d4c0e
 #include "gs-prefs.h"
William Jon McCann e8d4c0e
 #include "gs-debug.h"
William Jon McCann e8d4c0e
 
William Jon McCann e8d4c0e
+#include "securitytokenmonitor.h"
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
 static void     gs_monitor_class_init (GSMonitorClass *klass);
William Jon McCann e8d4c0e
 static void     gs_monitor_init       (GSMonitor      *monitor);
William Jon McCann e8d4c0e
 static void     gs_monitor_finalize   (GObject        *object);
William Jon McCann e8d4c0e
 
William Jon McCann e8d4c0e
+static void     gs_monitor_simulate_user_activity (GSMonitor *monitor);
William Jon McCann e8d4c0e
+static void     gs_monitor_lock_screen (GSMonitor *monitor);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
 #define GS_MONITOR_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GS_TYPE_MONITOR, GSMonitorPrivate))
William Jon McCann e8d4c0e
 
William Jon McCann e8d4c0e
 struct GSMonitorPrivate
William Jon McCann e8d4c0e
@@ -56,6 +61,8 @@ struct GSMonitorPrivate
William Jon McCann e8d4c0e
         GSFade         *fade;
William Jon McCann e8d4c0e
         GSGrab         *grab;
William Jon McCann e8d4c0e
 
William Jon McCann e8d4c0e
+	ScSecurityTokenMonitor *security_token_monitor;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
         guint           release_grab_id;
William Jon McCann e8d4c0e
 };
William Jon McCann e8d4c0e
 
William Jon McCann e8d4c0e
@@ -100,6 +107,36 @@ manager_auth_request_end_cb (GSManager *
William Jon McCann e8d4c0e
         gs_listener_emit_auth_request_end (monitor->priv->listener);
William Jon McCann e8d4c0e
 }
William Jon McCann e8d4c0e
 
William Jon McCann e8d4c0e
+static void
William Jon McCann e8d4c0e
+security_token_inserted_cb (ScSecurityTokenMonitor *token_monitor,
William Jon McCann e8d4c0e
+			    ScSecurityToken        *token,
William Jon McCann e8d4c0e
+			    GSMonitor              *monitor)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+	gs_monitor_simulate_user_activity (monitor);
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+static gboolean
William Jon McCann e8d4c0e
+gs_monitor_should_lock_on_login_security_token_removal (void)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+    /* FIXME: lame hack
William Jon McCann e8d4c0e
+     */
William Jon McCann e8d4c0e
+    return system ("pkcs11_setup rm_action | grep -q lock") == 0;
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+static void
William Jon McCann e8d4c0e
+security_token_removed_cb (ScSecurityTokenMonitor *token_monitor,
William Jon McCann e8d4c0e
+			   ScSecurityToken        *token,
William Jon McCann e8d4c0e
+			   GSMonitor              *monitor)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+    if (gs_monitor_should_lock_on_login_security_token_removal () &&
William Jon McCann e8d4c0e
+	sc_security_token_is_login_token (token))
William Jon McCann e8d4c0e
+	    gs_monitor_lock_screen (monitor);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    /* If we're already locked and the lock dialog is up, kill it.
William Jon McCann e8d4c0e
+     */
William Jon McCann e8d4c0e
+    gs_manager_cancel_unlock_request (monitor->priv->manager);
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
 static gboolean
William Jon McCann e8d4c0e
 watcher_idle_cb (GSWatcher *watcher,
William Jon McCann e8d4c0e
                  gboolean   is_idle,
William Jon McCann e8d4c0e
@@ -210,37 +247,6 @@ watcher_idle_notice_cb (GSWatcher *watch
William Jon McCann e8d4c0e
 }
William Jon McCann e8d4c0e
 
William Jon McCann e8d4c0e
 static void
William Jon McCann e8d4c0e
-gs_monitor_lock_screen (GSMonitor *monitor)
William Jon McCann e8d4c0e
-{
William Jon McCann e8d4c0e
-        gboolean res;
William Jon McCann e8d4c0e
-        gboolean locked;
William Jon McCann e8d4c0e
-
William Jon McCann e8d4c0e
-        /* set lock flag before trying to activate screensaver
William Jon McCann e8d4c0e
-           in case something tries to react to the ActiveChanged signal */
William Jon McCann e8d4c0e
-
William Jon McCann e8d4c0e
-        gs_manager_get_lock_active (monitor->priv->manager, &locked);
William Jon McCann e8d4c0e
-        gs_manager_set_lock_active (monitor->priv->manager, TRUE);
William Jon McCann e8d4c0e
-        res = gs_listener_set_active (monitor->priv->listener, TRUE);
William Jon McCann e8d4c0e
-        if (! res) {
William Jon McCann e8d4c0e
-                /* If we've failed then restore lock status */
William Jon McCann e8d4c0e
-                gs_manager_set_lock_active (monitor->priv->manager, locked);
William Jon McCann e8d4c0e
-                gs_debug ("Unable to lock the screen");
William Jon McCann e8d4c0e
-        }
William Jon McCann e8d4c0e
-}
William Jon McCann e8d4c0e
-
William Jon McCann e8d4c0e
-static void
William Jon McCann e8d4c0e
-gs_monitor_simulate_user_activity (GSMonitor *monitor)
William Jon McCann e8d4c0e
-{
William Jon McCann e8d4c0e
-        /* in case the screen isn't blanked reset the
William Jon McCann e8d4c0e
-           idle watcher */
William Jon McCann e8d4c0e
-        gs_watcher_reset (monitor->priv->watcher);
William Jon McCann e8d4c0e
-
William Jon McCann e8d4c0e
-        /* request that the manager unlock -
William Jon McCann e8d4c0e
-           will pop up a dialog if necessary */
William Jon McCann e8d4c0e
-        gs_manager_request_unlock (monitor->priv->manager);
William Jon McCann e8d4c0e
-}
William Jon McCann e8d4c0e
-
William Jon McCann e8d4c0e
-static void
William Jon McCann e8d4c0e
 listener_lock_cb (GSListener *listener,
William Jon McCann e8d4c0e
                   GSMonitor  *monitor)
William Jon McCann e8d4c0e
 {
William Jon McCann e8d4c0e
@@ -425,6 +431,27 @@ connect_manager_signals (GSMonitor *moni
William Jon McCann e8d4c0e
 }
William Jon McCann e8d4c0e
 
William Jon McCann e8d4c0e
 static void
William Jon McCann e8d4c0e
+disconnect_security_token_monitor_signals (GSMonitor *monitor)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+        g_signal_handlers_disconnect_by_func (monitor->priv->security_token_monitor,
William Jon McCann e8d4c0e
+					      security_token_removed_cb, monitor);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+        g_signal_handlers_disconnect_by_func (monitor->priv->security_token_monitor,
William Jon McCann e8d4c0e
+					      security_token_inserted_cb, monitor);
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+static void
William Jon McCann e8d4c0e
+connect_security_token_monitor_signals (GSMonitor *monitor)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+	g_signal_connect (monitor->priv->security_token_monitor, 
William Jon McCann e8d4c0e
+			  "security-token-removed",
William Jon McCann e8d4c0e
+			  G_CALLBACK (security_token_removed_cb), monitor);
William Jon McCann e8d4c0e
+	g_signal_connect (monitor->priv->security_token_monitor, 
William Jon McCann e8d4c0e
+			  "security-token-inserted",
William Jon McCann e8d4c0e
+			  G_CALLBACK (security_token_inserted_cb), monitor);
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+static void
William Jon McCann e8d4c0e
 disconnect_prefs_signals (GSMonitor *monitor)
William Jon McCann e8d4c0e
 {
William Jon McCann e8d4c0e
         g_signal_handlers_disconnect_by_func (monitor->priv->prefs, _gs_monitor_update_from_prefs, monitor);
William Jon McCann e8d4c0e
@@ -458,6 +485,26 @@ gs_monitor_init (GSMonitor *monitor)
William Jon McCann e8d4c0e
         monitor->priv->manager = gs_manager_new ();
William Jon McCann e8d4c0e
         connect_manager_signals (monitor);
William Jon McCann e8d4c0e
 
William Jon McCann e8d4c0e
+	/* PKCS11_LOGIN_TOKEN_NAME is set if the user logged in with a
William Jon McCann e8d4c0e
+	 * security token.
William Jon McCann e8d4c0e
+	 */
William Jon McCann e8d4c0e
+	if (g_getenv ("PKCS11_LOGIN_TOKEN_NAME") != NULL) {
William Jon McCann e8d4c0e
+		monitor->priv->security_token_monitor = sc_security_token_monitor_new (NULL);
William Jon McCann e8d4c0e
+		sc_security_token_monitor_start (monitor->priv->security_token_monitor,
William Jon McCann e8d4c0e
+						 NULL);
William Jon McCann e8d4c0e
+		connect_security_token_monitor_signals (monitor);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+		/* if the user logged in with a security token but it's
William Jon McCann e8d4c0e
+		 * not currently inserted, then they must have yanked it
William Jon McCann e8d4c0e
+		 * before we started.  lock the screen immediately
William Jon McCann e8d4c0e
+		 */
William Jon McCann e8d4c0e
+		if (gs_monitor_should_lock_on_login_security_token_removal () &&
William Jon McCann e8d4c0e
+		    !sc_security_token_monitor_login_token_is_inserted (monitor->priv->security_token_monitor))
William Jon McCann e8d4c0e
+			gs_monitor_lock_screen (monitor);
William Jon McCann e8d4c0e
+	} else {
William Jon McCann e8d4c0e
+		monitor->priv->security_token_monitor = NULL;
William Jon McCann e8d4c0e
+	}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
         _gs_monitor_update_from_prefs (monitor, monitor->priv->prefs);
William Jon McCann e8d4c0e
 }
William Jon McCann e8d4c0e
 
William Jon McCann e8d4c0e
@@ -473,6 +520,12 @@ gs_monitor_finalize (GObject *object)
William Jon McCann e8d4c0e
 
William Jon McCann e8d4c0e
         g_return_if_fail (monitor->priv != NULL);
William Jon McCann e8d4c0e
 
William Jon McCann e8d4c0e
+	if (monitor->priv->security_token_monitor != NULL) {
William Jon McCann e8d4c0e
+		sc_security_token_monitor_stop (monitor->priv->security_token_monitor);
William Jon McCann e8d4c0e
+		disconnect_security_token_monitor_signals (monitor);
William Jon McCann e8d4c0e
+		g_object_unref (monitor->priv->security_token_monitor);
William Jon McCann e8d4c0e
+	}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
         disconnect_watcher_signals (monitor);
William Jon McCann e8d4c0e
         disconnect_listener_signals (monitor);
William Jon McCann e8d4c0e
         disconnect_manager_signals (monitor);
William Jon McCann e8d4c0e
@@ -510,3 +563,34 @@ gs_monitor_start (GSMonitor *monitor,
William Jon McCann e8d4c0e
 
William Jon McCann e8d4c0e
         return TRUE;
William Jon McCann e8d4c0e
 }
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+static void     
William Jon McCann e8d4c0e
+gs_monitor_simulate_user_activity (GSMonitor *monitor)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+        /* in case the screen isn't blanked reset the
William Jon McCann e8d4c0e
+           idle watcher */
William Jon McCann e8d4c0e
+        gs_watcher_reset (monitor->priv->watcher);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+        /* request that the manager unlock -
William Jon McCann e8d4c0e
+           will pop up a dialog if necessary */
William Jon McCann e8d4c0e
+        gs_manager_request_unlock (monitor->priv->manager);
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+static void     
William Jon McCann e8d4c0e
+gs_monitor_lock_screen (GSMonitor *monitor)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+        gboolean res;
William Jon McCann e8d4c0e
+        gboolean locked;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+        /* set lock flag before trying to activate screensaver
William Jon McCann e8d4c0e
+           in case something tries to react to the ActiveChanged signal */
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+        gs_manager_get_lock_active (monitor->priv->manager, &locked);
William Jon McCann e8d4c0e
+        gs_manager_set_lock_active (monitor->priv->manager, TRUE);
William Jon McCann e8d4c0e
+        res = gs_listener_set_active (monitor->priv->listener, TRUE);
William Jon McCann e8d4c0e
+        if (! res) {
William Jon McCann e8d4c0e
+                /* If we've failed then restore lock status */
William Jon McCann e8d4c0e
+                gs_manager_set_lock_active (monitor->priv->manager, locked);
William Jon McCann e8d4c0e
+                gs_debug ("Unable to lock the screen");
William Jon McCann e8d4c0e
+        }
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
diff -up gnome-screensaver-2.23.3/src/Makefile.am.securitytoken gnome-screensaver-2.23.3/src/Makefile.am
William Jon McCann e8d4c0e
--- gnome-screensaver-2.23.3/src/Makefile.am.securitytoken	2008-05-14 01:14:43.000000000 -0400
William Jon McCann e8d4c0e
+++ gnome-screensaver-2.23.3/src/Makefile.am	2008-07-27 23:26:19.000000000 -0400
William Jon McCann e8d4c0e
@@ -51,6 +51,18 @@ noinst_PROGRAMS = 	\
William Jon McCann e8d4c0e
 	test-window	\
William Jon McCann e8d4c0e
 	$(NULL)
William Jon McCann e8d4c0e
 
William Jon McCann e8d4c0e
+noinst_LIBRARIES = libsecuritytoken.a
William Jon McCann e8d4c0e
+ 
William Jon McCann e8d4c0e
+libsecuritytoken_a_SOURCES = \
William Jon McCann e8d4c0e
+	securitytoken.h \
William Jon McCann e8d4c0e
+	securitytoken.c \
William Jon McCann e8d4c0e
+	securitytokenmonitor.h \
William Jon McCann e8d4c0e
+	securitytokenmonitor.c
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+libsecuritytoken_a_CFLAGS = $(SECURITY_TOKEN_CFLAGS) \
William Jon McCann e8d4c0e
+			-DLIBDIR=\""$(libdir)"\"  \
William Jon McCann e8d4c0e
+			-DSYSCONFDIR=\""$(sysconfdir)"\"
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
 gnome_screensaver_command_SOURCES = 	\
William Jon McCann e8d4c0e
 	gnome-screensaver-command.c	\
William Jon McCann e8d4c0e
 	$(NULL)
William Jon McCann e8d4c0e
@@ -208,6 +220,7 @@ gnome_screensaver_gl_helper_SOURCES =	\
William Jon McCann e8d4c0e
 gnome_screensaver_LDADD =		\
William Jon McCann e8d4c0e
 	$(GNOME_SCREENSAVER_LIBS)	\
William Jon McCann e8d4c0e
 	$(SAVER_LIBS)			\
William Jon McCann e8d4c0e
+ 	$(top_builddir)/src/libsecuritytoken.a \
William Jon McCann e8d4c0e
 	$(NULL)
William Jon McCann e8d4c0e
 
William Jon McCann e8d4c0e
 gnome_screensaver_LDFLAGS = -export-dynamic
William Jon McCann e8d4c0e
diff -up /dev/null gnome-screensaver-2.23.3/src/securitytoken.c
William Jon McCann e8d4c0e
--- /dev/null	2008-07-27 17:37:58.142005663 -0400
William Jon McCann e8d4c0e
+++ gnome-screensaver-2.23.3/src/securitytoken.c	2008-07-27 23:20:06.000000000 -0400
William Jon McCann e8d4c0e
@@ -0,0 +1,680 @@
William Jon McCann e8d4c0e
+/* securitytoken.c - security token
William Jon McCann e8d4c0e
+ * 
William Jon McCann e8d4c0e
+ * Copyright (C) 2006 Ray Strode <rstrode@redhat.com>
William Jon McCann e8d4c0e
+ * 
William Jon McCann e8d4c0e
+ * This program is free software; you can redistribute it and/or modify
William Jon McCann e8d4c0e
+ * it under the terms of the GNU General Public License as published by
William Jon McCann e8d4c0e
+ * the Free Software Foundation; either version 2, or (at your option)
William Jon McCann e8d4c0e
+ * any later version.
William Jon McCann e8d4c0e
+ * 
William Jon McCann e8d4c0e
+ * This program is distributed in the hope that it will be useful,
William Jon McCann e8d4c0e
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
William Jon McCann e8d4c0e
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
William Jon McCann e8d4c0e
+ * GNU General Public License for more details.
William Jon McCann e8d4c0e
+ * 
William Jon McCann e8d4c0e
+ * You should have received a copy of the GNU General Public License
William Jon McCann e8d4c0e
+ * along with this program; if not, write to the Free Software
William Jon McCann e8d4c0e
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
William Jon McCann e8d4c0e
+ * 02111-1307, USA.  
William Jon McCann e8d4c0e
+ *
William Jon McCann e8d4c0e
+ * TODO:     - doing this per project is a bad idea i think.
William Jon McCann e8d4c0e
+ *             We should probably make this a system service 
William Jon McCann e8d4c0e
+ *             and use dbus.
William Jon McCann e8d4c0e
+ *
William Jon McCann e8d4c0e
+ *           - We hardcode a driver right now.  We should probably
William Jon McCann e8d4c0e
+ *             look up the default list and go from there. 
William Jon McCann e8d4c0e
+ */
William Jon McCann e8d4c0e
+#define SC_SECURITY_TOKEN_ENABLE_INTERNAL_API
William Jon McCann e8d4c0e
+#include "securitytoken.h"
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+#include <errno.h>
William Jon McCann e8d4c0e
+#include <string.h>
William Jon McCann e8d4c0e
+#include <unistd.h>
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+#include <glib.h>
William Jon McCann e8d4c0e
+#include <glib/gi18n.h>
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+#include <cert.h>
William Jon McCann e8d4c0e
+#include <nss.h>
William Jon McCann e8d4c0e
+#include <pk11func.h>
William Jon McCann e8d4c0e
+#include <prerror.h>
William Jon McCann e8d4c0e
+#include <secmod.h>
William Jon McCann e8d4c0e
+#include <secerr.h>
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+#if defined (SC_SECURITY_TOKEN_ENABLE_TEST) || defined (SC_SECURITY_TOKEN_MONITOR_ENABLE_TEST)
William Jon McCann e8d4c0e
+#define sc_debug(format, args...) g_printerr (format "\n", ##args)
William Jon McCann e8d4c0e
+#define sc_warning(format, args...) g_printerr (format "\n", ##args)
William Jon McCann e8d4c0e
+#else
William Jon McCann e8d4c0e
+#define sc_debug(format, args...) 
William Jon McCann e8d4c0e
+#define sc_warning(format, args...) 
William Jon McCann e8d4c0e
+#endif
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+struct _ScSecurityTokenPrivate {
William Jon McCann e8d4c0e
+	SECMODModule *module;
William Jon McCann e8d4c0e
+	ScSecurityTokenState state;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	CK_SLOT_ID slot_id;
William Jon McCann e8d4c0e
+	gint slot_series;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	PK11SlotInfo *slot;
William Jon McCann e8d4c0e
+	gchar *name;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	CERTCertificate *signing_certificate;
William Jon McCann e8d4c0e
+	CERTCertificate *encryption_certificate;
William Jon McCann e8d4c0e
+};
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+static void sc_security_token_finalize (GObject *object);
William Jon McCann e8d4c0e
+static void sc_security_token_class_install_signals (ScSecurityTokenClass *token_class);
William Jon McCann e8d4c0e
+static void sc_security_token_class_install_properties (ScSecurityTokenClass *token_class);
William Jon McCann e8d4c0e
+static void sc_security_token_set_property (GObject       *object,
William Jon McCann e8d4c0e
+					    guint          prop_id,
William Jon McCann e8d4c0e
+					    const GValue  *value,
William Jon McCann e8d4c0e
+					    GParamSpec    *pspec);
William Jon McCann e8d4c0e
+static void sc_security_token_get_property (GObject     *object,
William Jon McCann e8d4c0e
+					    guint        prop_id,
William Jon McCann e8d4c0e
+					    GValue      *value,
William Jon McCann e8d4c0e
+					    GParamSpec  *pspec);
William Jon McCann e8d4c0e
+static void sc_security_token_set_name (ScSecurityToken *token, const gchar *name);
William Jon McCann e8d4c0e
+static void sc_security_token_set_slot_id (ScSecurityToken *token, 
William Jon McCann e8d4c0e
+					   gint             slot_id);
William Jon McCann e8d4c0e
+static void sc_security_token_set_slot_series (ScSecurityToken *token, 
William Jon McCann e8d4c0e
+					       gint             slot_series);
William Jon McCann e8d4c0e
+static void sc_security_token_set_module (ScSecurityToken *token,
William Jon McCann e8d4c0e
+					  SECMODModule    *module);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+static PK11SlotInfo *sc_security_token_find_slot_from_id (ScSecurityToken *token,
William Jon McCann e8d4c0e
+							  gint slot_id);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+static PK11SlotInfo *sc_security_token_find_slot_from_token_name (ScSecurityToken *token,
William Jon McCann e8d4c0e
+								  const gchar     *token_name);
William Jon McCann e8d4c0e
+static gboolean sc_security_token_fetch_certificates (ScSecurityToken *token);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+#ifndef SC_SECURITY_TOKEN_DEFAULT_SLOT_ID 
William Jon McCann e8d4c0e
+#define SC_SECURITY_TOKEN_DEFAULT_SLOT_ID ((gulong) -1)
William Jon McCann e8d4c0e
+#endif
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+#ifndef SC_SECURITY_TOKEN_DEFAULT_SLOT_SERIES
William Jon McCann e8d4c0e
+#define SC_SECURITY_TOKEN_DEFAULT_SLOT_SERIES -1
William Jon McCann e8d4c0e
+#endif
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+enum {
William Jon McCann e8d4c0e
+	PROP_0 = 0,
William Jon McCann e8d4c0e
+	PROP_NAME,
William Jon McCann e8d4c0e
+	PROP_SLOT_ID,
William Jon McCann e8d4c0e
+	PROP_SLOT_SERIES,
William Jon McCann e8d4c0e
+	PROP_MODULE,
William Jon McCann e8d4c0e
+	NUMBER_OF_PROPERTIES
William Jon McCann e8d4c0e
+};
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+enum {
William Jon McCann e8d4c0e
+	INSERTED,
William Jon McCann e8d4c0e
+	REMOVED,
William Jon McCann e8d4c0e
+	NUMBER_OF_SIGNALS
William Jon McCann e8d4c0e
+};
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+static guint sc_security_token_signals[NUMBER_OF_SIGNALS];
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+G_DEFINE_TYPE (ScSecurityToken, sc_security_token, G_TYPE_OBJECT);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+static void
William Jon McCann e8d4c0e
+sc_security_token_class_init (ScSecurityTokenClass *token_class)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+    GObjectClass *gobject_class;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    gobject_class = G_OBJECT_CLASS (token_class);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    gobject_class->finalize = sc_security_token_finalize;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    sc_security_token_class_install_signals (token_class);
William Jon McCann e8d4c0e
+    sc_security_token_class_install_properties (token_class);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    g_type_class_add_private (token_class,
William Jon McCann e8d4c0e
+			      sizeof (ScSecurityTokenPrivate));
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+static void
William Jon McCann e8d4c0e
+sc_security_token_class_install_signals (ScSecurityTokenClass *token_class)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+    GObjectClass *object_class;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    object_class = G_OBJECT_CLASS (token_class);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    sc_security_token_signals[INSERTED] =
William Jon McCann e8d4c0e
+	    g_signal_new ("inserted",
William Jon McCann e8d4c0e
+			  G_OBJECT_CLASS_TYPE (object_class),
William Jon McCann e8d4c0e
+			  G_SIGNAL_RUN_LAST,
William Jon McCann e8d4c0e
+			  G_STRUCT_OFFSET (ScSecurityTokenClass,
William Jon McCann e8d4c0e
+					   inserted), 
William Jon McCann e8d4c0e
+			  NULL, NULL, g_cclosure_marshal_VOID__VOID, 
William Jon McCann e8d4c0e
+			  G_TYPE_NONE, 0);
William Jon McCann e8d4c0e
+    token_class->inserted = NULL;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    sc_security_token_signals[REMOVED] =
William Jon McCann e8d4c0e
+	    g_signal_new ("removed",
William Jon McCann e8d4c0e
+			  G_OBJECT_CLASS_TYPE (object_class),
William Jon McCann e8d4c0e
+			  G_SIGNAL_RUN_LAST,
William Jon McCann e8d4c0e
+			  G_STRUCT_OFFSET (ScSecurityTokenClass,
William Jon McCann e8d4c0e
+					   removed), 
William Jon McCann e8d4c0e
+			  NULL, NULL, g_cclosure_marshal_VOID__VOID, 
William Jon McCann e8d4c0e
+			  G_TYPE_NONE, 0);
William Jon McCann e8d4c0e
+    token_class->removed = NULL;
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+static void
William Jon McCann e8d4c0e
+sc_security_token_class_install_properties (ScSecurityTokenClass *token_class)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+    GObjectClass *object_class;
William Jon McCann e8d4c0e
+    GParamSpec *param_spec;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    object_class = G_OBJECT_CLASS (token_class);
William Jon McCann e8d4c0e
+    object_class->set_property = sc_security_token_set_property;
William Jon McCann e8d4c0e
+    object_class->get_property = sc_security_token_get_property;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    param_spec = g_param_spec_ulong ("slot-id", _("Slot ID"),
William Jon McCann e8d4c0e
+				   _("The slot the token is in"),
William Jon McCann e8d4c0e
+				   1, G_MAXULONG,
William Jon McCann e8d4c0e
+				   SC_SECURITY_TOKEN_DEFAULT_SLOT_ID,
William Jon McCann e8d4c0e
+				   G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
William Jon McCann e8d4c0e
+    g_object_class_install_property (object_class, PROP_SLOT_ID, param_spec);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    param_spec = g_param_spec_int ("slot-series", _("Slot Series"),
William Jon McCann e8d4c0e
+				   _("per-slot token identifier"),
William Jon McCann e8d4c0e
+				   -1, G_MAXINT,
William Jon McCann e8d4c0e
+				   SC_SECURITY_TOKEN_DEFAULT_SLOT_SERIES,
William Jon McCann e8d4c0e
+				   G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
William Jon McCann e8d4c0e
+    g_object_class_install_property (object_class, PROP_SLOT_SERIES, param_spec);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    param_spec = g_param_spec_string ("name", _("name"),
William Jon McCann e8d4c0e
+				      _("name"), NULL,
William Jon McCann e8d4c0e
+				      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
William Jon McCann e8d4c0e
+    g_object_class_install_property (object_class, PROP_NAME, param_spec);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    param_spec = g_param_spec_pointer ("module", _("Module"),
William Jon McCann e8d4c0e
+				       _("security token driver"),
William Jon McCann e8d4c0e
+				       G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY);
William Jon McCann e8d4c0e
+    g_object_class_install_property (object_class, PROP_MODULE, param_spec);
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+static void 
William Jon McCann e8d4c0e
+sc_security_token_set_property (GObject       *object,
William Jon McCann e8d4c0e
+				guint          prop_id,
William Jon McCann e8d4c0e
+				const GValue  *value,
William Jon McCann e8d4c0e
+				GParamSpec    *pspec)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+    ScSecurityToken *token = SC_SECURITY_TOKEN (object);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    switch (prop_id)
William Jon McCann e8d4c0e
+    {
William Jon McCann e8d4c0e
+	    case PROP_NAME:
William Jon McCann e8d4c0e
+		    sc_security_token_set_name (token, g_value_get_string (value));
William Jon McCann e8d4c0e
+		    break;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	    case PROP_SLOT_ID:
William Jon McCann e8d4c0e
+		    sc_security_token_set_slot_id (token, 
William Jon McCann e8d4c0e
+						   g_value_get_ulong (value));
William Jon McCann e8d4c0e
+		    break;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	    case PROP_SLOT_SERIES:
William Jon McCann e8d4c0e
+		    sc_security_token_set_slot_series (token, 
William Jon McCann e8d4c0e
+						       g_value_get_int (value));
William Jon McCann e8d4c0e
+		    break;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	    case PROP_MODULE:
William Jon McCann e8d4c0e
+		    sc_security_token_set_module (token, 
William Jon McCann e8d4c0e
+						  (SECMODModule *)
William Jon McCann e8d4c0e
+						  g_value_get_pointer (value));
William Jon McCann e8d4c0e
+		    break;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	    default:
William Jon McCann e8d4c0e
+		    G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
William Jon McCann e8d4c0e
+    }
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+CK_SLOT_ID
William Jon McCann e8d4c0e
+sc_security_token_get_slot_id (ScSecurityToken *token)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+    return token->priv->slot_id;
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+ScSecurityTokenState 
William Jon McCann e8d4c0e
+sc_security_token_get_state (ScSecurityToken *token)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+    return token->priv->state;
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+gchar *
William Jon McCann e8d4c0e
+sc_security_token_get_name (ScSecurityToken *token)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+    return g_strdup (token->priv->name);
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+gboolean
William Jon McCann e8d4c0e
+sc_security_token_is_login_token (ScSecurityToken *token)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+    const gchar *login_token_name;
William Jon McCann e8d4c0e
+    login_token_name = g_getenv ("PKCS11_LOGIN_TOKEN_NAME");
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    if ((login_token_name == NULL) || (token->priv->name == NULL))
William Jon McCann e8d4c0e
+	    return FALSE;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    if (strcmp (token->priv->name, login_token_name) == 0)
William Jon McCann e8d4c0e
+	    return TRUE;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    return FALSE;
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+static void 
William Jon McCann e8d4c0e
+sc_security_token_get_property (GObject    *object,
William Jon McCann e8d4c0e
+				guint        prop_id,
William Jon McCann e8d4c0e
+				GValue      *value,
William Jon McCann e8d4c0e
+				GParamSpec  *pspec)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+    ScSecurityToken *token = SC_SECURITY_TOKEN (object);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    switch (prop_id)
William Jon McCann e8d4c0e
+    {
William Jon McCann e8d4c0e
+	    case PROP_NAME:
William Jon McCann e8d4c0e
+		    g_value_take_string (value, 
William Jon McCann e8d4c0e
+					 sc_security_token_get_name (token));
William Jon McCann e8d4c0e
+		    break;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	    case PROP_SLOT_ID:
William Jon McCann e8d4c0e
+		    g_value_set_ulong (value, 
William Jon McCann e8d4c0e
+				       (gulong) sc_security_token_get_slot_id (token));
William Jon McCann e8d4c0e
+		    break;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	    case PROP_SLOT_SERIES:
William Jon McCann e8d4c0e
+		    g_value_set_int (value, 
William Jon McCann e8d4c0e
+				     sc_security_token_get_slot_series (token));
William Jon McCann e8d4c0e
+		    break;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	    default:
William Jon McCann e8d4c0e
+		    G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
William Jon McCann e8d4c0e
+    }
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+static void
William Jon McCann e8d4c0e
+sc_security_token_set_name (ScSecurityToken *token,
William Jon McCann e8d4c0e
+			    const gchar     *name)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+    if (name == NULL)
William Jon McCann e8d4c0e
+	    return;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    if ((token->priv->name == NULL) ||
William Jon McCann e8d4c0e
+	(strcmp (token->priv->name, name) != 0)) {
William Jon McCann e8d4c0e
+	    g_free (token->priv->name);
William Jon McCann e8d4c0e
+	    token->priv->name = g_strdup (name);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	    if (token->priv->slot == NULL) {
William Jon McCann e8d4c0e
+		    token->priv->slot = sc_security_token_find_slot_from_token_name (token,
William Jon McCann e8d4c0e
+										     token->priv->name);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+		    if (token->priv->slot != NULL) {
William Jon McCann e8d4c0e
+			    gint slot_id, slot_series;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+			    slot_id = PK11_GetSlotID (token->priv->slot);
William Jon McCann e8d4c0e
+			    if (slot_id != token->priv->slot_id)
William Jon McCann e8d4c0e
+				    sc_security_token_set_slot_id (token, slot_id);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+			    slot_series = PK11_GetSlotSeries (token->priv->slot);
William Jon McCann e8d4c0e
+			    if (slot_series != token->priv->slot_series)
William Jon McCann e8d4c0e
+				    sc_security_token_set_slot_series (token, slot_series);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+			    _sc_security_token_set_state (token, SC_SECURITY_TOKEN_STATE_INSERTED);
William Jon McCann e8d4c0e
+		    } else {
William Jon McCann e8d4c0e
+			    _sc_security_token_set_state (token, SC_SECURITY_TOKEN_STATE_REMOVED);
William Jon McCann e8d4c0e
+		    }
William Jon McCann e8d4c0e
+	    }
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	    g_object_notify (G_OBJECT (token), "name");
William Jon McCann e8d4c0e
+    }
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+static void
William Jon McCann e8d4c0e
+sc_security_token_set_slot_id (ScSecurityToken *token,
William Jon McCann e8d4c0e
+			       gint             slot_id)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+    if (token->priv->slot_id != slot_id)
William Jon McCann e8d4c0e
+    {
William Jon McCann e8d4c0e
+	    token->priv->slot_id = slot_id;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	    if (token->priv->slot == NULL) {
William Jon McCann e8d4c0e
+		    token->priv->slot = sc_security_token_find_slot_from_id (token,
William Jon McCann e8d4c0e
+									     token->priv->slot_id);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+		    if (token->priv->slot != NULL) {
William Jon McCann e8d4c0e
+			    const gchar *token_name;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+			    token_name = PK11_GetTokenName (token->priv->slot);
William Jon McCann e8d4c0e
+			    if ((token->priv->name == NULL) || 
William Jon McCann e8d4c0e
+				((token_name != NULL) &&
William Jon McCann e8d4c0e
+				(strcmp (token_name, token->priv->name) != 0)))
William Jon McCann e8d4c0e
+				    sc_security_token_set_name (token, token_name);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+			    _sc_security_token_set_state (token, SC_SECURITY_TOKEN_STATE_INSERTED);
William Jon McCann e8d4c0e
+		    } else {
William Jon McCann e8d4c0e
+			    _sc_security_token_set_state (token, SC_SECURITY_TOKEN_STATE_REMOVED);
William Jon McCann e8d4c0e
+		    }
William Jon McCann e8d4c0e
+	    }
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	    g_object_notify (G_OBJECT (token), "slot-id");
William Jon McCann e8d4c0e
+    }
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+static void
William Jon McCann e8d4c0e
+sc_security_token_set_slot_series (ScSecurityToken *token,
William Jon McCann e8d4c0e
+				   gint             slot_series)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+    if (token->priv->slot_series != slot_series)
William Jon McCann e8d4c0e
+    {
William Jon McCann e8d4c0e
+	    token->priv->slot_series = slot_series;
William Jon McCann e8d4c0e
+	    g_object_notify (G_OBJECT (token), "slot-series");
William Jon McCann e8d4c0e
+    }
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+static void
William Jon McCann e8d4c0e
+sc_security_token_set_module (ScSecurityToken *token,
William Jon McCann e8d4c0e
+			      SECMODModule    *module)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+    gboolean should_notify;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    if (token->priv->module != module)
William Jon McCann e8d4c0e
+	    should_notify = TRUE;
William Jon McCann e8d4c0e
+    else
William Jon McCann e8d4c0e
+	    should_notify = FALSE;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    if (token->priv->module != NULL) {
William Jon McCann e8d4c0e
+	    SECMOD_DestroyModule (token->priv->module);
William Jon McCann e8d4c0e
+	    token->priv->module = NULL;
William Jon McCann e8d4c0e
+    }
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    if (module != NULL)
William Jon McCann e8d4c0e
+	    token->priv->module = SECMOD_ReferenceModule (module);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    if (should_notify)
William Jon McCann e8d4c0e
+	    g_object_notify (G_OBJECT (token), "module");
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+gint 
William Jon McCann e8d4c0e
+sc_security_token_get_slot_series (ScSecurityToken *token)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+    return token->priv->slot_series;
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+static void
William Jon McCann e8d4c0e
+sc_security_token_init (ScSecurityToken *token)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    sc_debug ("initializing security token ");
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    token->priv = G_TYPE_INSTANCE_GET_PRIVATE (token,
William Jon McCann e8d4c0e
+					       SC_TYPE_SECURITY_TOKEN,
William Jon McCann e8d4c0e
+					       ScSecurityTokenPrivate);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    if (token->priv->slot != NULL)
William Jon McCann e8d4c0e
+	    token->priv->name = g_strdup (PK11_GetTokenName (token->priv->slot));
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+static void sc_security_token_finalize (GObject *object)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+    ScSecurityToken *token;
William Jon McCann e8d4c0e
+    GObjectClass *gobject_class;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    token = SC_SECURITY_TOKEN (object);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    g_free (token->priv->name);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    sc_security_token_set_module (token, NULL);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    gobject_class =
William Jon McCann e8d4c0e
+	    G_OBJECT_CLASS (sc_security_token_parent_class);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    gobject_class->finalize (object);
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+GQuark sc_security_token_error_quark (void)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+    static GQuark error_quark = 0;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    if (error_quark == 0)
William Jon McCann e8d4c0e
+	    error_quark = g_quark_from_static_string ("sc-security-token-error-quark");
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    return error_quark;
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+ScSecurityToken *
William Jon McCann e8d4c0e
+_sc_security_token_new (SECMODModule *module,
William Jon McCann e8d4c0e
+			CK_SLOT_ID    slot_id,
William Jon McCann e8d4c0e
+			gint          slot_series)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+    ScSecurityToken *token;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    g_return_val_if_fail (module != NULL, NULL);
William Jon McCann e8d4c0e
+    g_return_val_if_fail (slot_id >= 1, NULL);
William Jon McCann e8d4c0e
+    g_return_val_if_fail (slot_series > 0, NULL);
William Jon McCann e8d4c0e
+    g_return_val_if_fail (sizeof (gulong) == sizeof (slot_id), NULL);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    token = SC_SECURITY_TOKEN (g_object_new (SC_TYPE_SECURITY_TOKEN,
William Jon McCann e8d4c0e
+					     "module", module,
William Jon McCann e8d4c0e
+					     "slot-id", (gulong) slot_id,
William Jon McCann e8d4c0e
+					     "slot-series", slot_series,
William Jon McCann e8d4c0e
+					     NULL));
William Jon McCann e8d4c0e
+    return token;
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+ScSecurityToken *
William Jon McCann e8d4c0e
+_sc_security_token_new_from_name (SECMODModule *module,
William Jon McCann e8d4c0e
+				  const gchar  *name)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+    ScSecurityToken *token;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    g_return_val_if_fail (module != NULL, NULL);
William Jon McCann e8d4c0e
+    g_return_val_if_fail (name != NULL, NULL);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    token = SC_SECURITY_TOKEN (g_object_new (SC_TYPE_SECURITY_TOKEN,
William Jon McCann e8d4c0e
+					     "module", module,
William Jon McCann e8d4c0e
+					     "name", name,
William Jon McCann e8d4c0e
+					     NULL));
William Jon McCann e8d4c0e
+    return token;
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+void 
William Jon McCann e8d4c0e
+_sc_security_token_set_state (ScSecurityToken      *token,
William Jon McCann e8d4c0e
+			      ScSecurityTokenState  state)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+    /* sc_security_token_fetch_certificates (token); */
William Jon McCann e8d4c0e
+    if (token->priv->state != state)
William Jon McCann e8d4c0e
+    {
William Jon McCann e8d4c0e
+	    token->priv->state = state;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	    if (state == SC_SECURITY_TOKEN_STATE_INSERTED) {
William Jon McCann e8d4c0e
+		    g_signal_emit (token, sc_security_token_signals[INSERTED], 0);
William Jon McCann e8d4c0e
+	    } else if (state == SC_SECURITY_TOKEN_STATE_REMOVED)
William Jon McCann e8d4c0e
+		    g_signal_emit (token, sc_security_token_signals[REMOVED], 0);
William Jon McCann e8d4c0e
+	    else
William Jon McCann e8d4c0e
+		    g_assert_not_reached ();
William Jon McCann e8d4c0e
+    }
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+/* So we could conceivably make the closure data a pointer to the token
William Jon McCann e8d4c0e
+ * or something similiar and then emit signals when we want passwords,
William Jon McCann e8d4c0e
+ * but it's probably easier to just get the password up front and use
William Jon McCann e8d4c0e
+ * it.  So we just take the passed in g_malloc'd (well probably, who knows)
William Jon McCann e8d4c0e
+ * and strdup it using NSPR's memory allocation routines.
William Jon McCann e8d4c0e
+ */
William Jon McCann e8d4c0e
+static char *
William Jon McCann e8d4c0e
+sc_security_token_password_handler (PK11SlotInfo *slot, 
William Jon McCann e8d4c0e
+				    PRBool        is_retrying, 
William Jon McCann e8d4c0e
+				    const gchar  *password)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+    if (is_retrying)
William Jon McCann e8d4c0e
+	    return NULL;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    return password != NULL? PL_strdup (password): NULL;
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+gboolean
William Jon McCann e8d4c0e
+sc_security_token_unlock (ScSecurityToken *token,
William Jon McCann e8d4c0e
+			  const gchar     *password)
William Jon McCann e8d4c0e
+{   
William Jon McCann e8d4c0e
+    SECStatus status;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    PK11_SetPasswordFunc ((PK11PasswordFunc) sc_security_token_password_handler);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    /* we pass PR_TRUE to load certificates
William Jon McCann e8d4c0e
+     */
William Jon McCann e8d4c0e
+    status = PK11_Authenticate (token->priv->slot, PR_TRUE, (gpointer) password);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    if (status != SECSuccess) {
William Jon McCann e8d4c0e
+	    sc_debug ("could not unlock token - %d", status);
William Jon McCann e8d4c0e
+	    return FALSE;
William Jon McCann e8d4c0e
+    }
William Jon McCann e8d4c0e
+    return TRUE;
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+static PK11SlotInfo *
William Jon McCann e8d4c0e
+sc_security_token_find_slot_from_token_name (ScSecurityToken *token,
William Jon McCann e8d4c0e
+					     const gchar     *token_name)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+    int i;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    for (i = 0; i < token->priv->module->slotCount; i++) {
William Jon McCann e8d4c0e
+	    const gchar *slot_token_name;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	    slot_token_name = PK11_GetTokenName (token->priv->module->slots[i]);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	    if ((slot_token_name != NULL) &&
William Jon McCann e8d4c0e
+		(strcmp (slot_token_name, token_name) == 0))
William Jon McCann e8d4c0e
+		    return token->priv->module->slots[i];
William Jon McCann e8d4c0e
+    }
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    return NULL;
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+static PK11SlotInfo *
William Jon McCann e8d4c0e
+sc_security_token_find_slot_from_id (ScSecurityToken *token,
William Jon McCann e8d4c0e
+                                     gint slot_id)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+    int i;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    for (i = 0; i < token->priv->module->slotCount; i++)
William Jon McCann e8d4c0e
+	    if (PK11_GetSlotID (token->priv->module->slots[i]) == slot_id)
William Jon McCann e8d4c0e
+		    return token->priv->module->slots[i];
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    return NULL;
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+static gboolean
William Jon McCann e8d4c0e
+sc_security_token_fetch_certificates (ScSecurityToken *token)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+    PK11SlotInfo *slot;
William Jon McCann e8d4c0e
+    CERTCertList *certificates;
William Jon McCann e8d4c0e
+    CERTCertListNode *node;
William Jon McCann e8d4c0e
+    SECStatus status;
William Jon McCann e8d4c0e
+    int i;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    sc_security_token_unlock (token, "0000");
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    sc_debug ("fetching certificates for token in slot %lu",
William Jon McCann e8d4c0e
+	      token->priv->slot_id);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    slot = sc_security_token_find_slot_from_id (token,
William Jon McCann e8d4c0e
+						token->priv->slot_id);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    g_assert (PK11_GetSlotID (slot) == token->priv->slot_id);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    if (i == token->priv->module->slotCount) {
William Jon McCann e8d4c0e
+	    sc_debug ("could not find slot %lu", token->priv->slot_id);
William Jon McCann e8d4c0e
+	    return FALSE;
William Jon McCann e8d4c0e
+    }
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    certificates = PK11_ListCertsInSlot (slot);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    sc_debug ("filtering out non-user certificates");
William Jon McCann e8d4c0e
+    if (CERT_FilterCertListForUserCerts (certificates) != SECSuccess) {
William Jon McCann e8d4c0e
+	    CERT_DestroyCertList (certificates);
William Jon McCann e8d4c0e
+	    sc_debug ("could not filter out non-user certificates");
William Jon McCann e8d4c0e
+	    return FALSE;
William Jon McCann e8d4c0e
+    }
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    for (node = CERT_LIST_HEAD (certificates); 
William Jon McCann e8d4c0e
+	 !CERT_LIST_END (node, certificates);
William Jon McCann e8d4c0e
+	 node = CERT_LIST_NEXT(node)) {
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	    SECCertificateUsage cert_usages;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	    sc_debug ("verifying certificate for use");
William Jon McCann e8d4c0e
+	    status = CERT_VerifyCertificateNow (NULL, node->cert, TRUE, 
William Jon McCann e8d4c0e
+						0, NULL, &cert_usages);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	    if (status != SECSuccess) {
William Jon McCann e8d4c0e
+		    sc_debug ("could not be verified, skipping...");
William Jon McCann e8d4c0e
+		    continue;
William Jon McCann e8d4c0e
+	    }
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	    sc_debug ("got cert with usages 0x%lx", (gulong) cert_usages);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	    if (token->priv->encryption_certificate == NULL) {
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+		    sc_debug ("checking if certificate can be used for data "
William Jon McCann e8d4c0e
+			      "encryption");
William Jon McCann e8d4c0e
+		    status = CERT_CheckCertUsage (node->cert, 
William Jon McCann e8d4c0e
+						  KU_DATA_ENCIPHERMENT);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+		    if (status == SECSuccess) {
William Jon McCann e8d4c0e
+			    token->priv->encryption_certificate = 
William Jon McCann e8d4c0e
+				    CERT_DupCertificate (node->cert);
William Jon McCann e8d4c0e
+		    } else {
William Jon McCann e8d4c0e
+			    sc_debug ("certificate can not be used for encryption");
William Jon McCann e8d4c0e
+		    }
William Jon McCann e8d4c0e
+	    }
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	    if (token->priv->signing_certificate == NULL) {
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+		    sc_debug ("checking if certificate can be used for data "
William Jon McCann e8d4c0e
+			      "signing");
William Jon McCann e8d4c0e
+		    status = CERT_CheckCertUsage (node->cert, 
William Jon McCann e8d4c0e
+						  KU_DIGITAL_SIGNATURE);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+		    if (status == SECSuccess) {
William Jon McCann e8d4c0e
+			    token->priv->signing_certificate = 
William Jon McCann e8d4c0e
+				    CERT_DupCertificate (node->cert);
William Jon McCann e8d4c0e
+		    } else {
William Jon McCann e8d4c0e
+			    sc_debug ("certificate can not be used for signing things");
William Jon McCann e8d4c0e
+		    }
William Jon McCann e8d4c0e
+	    }
William Jon McCann e8d4c0e
+    }
William Jon McCann e8d4c0e
+    return TRUE;
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+#ifdef SC_SECURITY_TOKEN_ENABLE_TEST
William Jon McCann e8d4c0e
+#include <glib.h>
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+static GMainLoop *event_loop;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+int 
William Jon McCann e8d4c0e
+main (int   argc, 
William Jon McCann e8d4c0e
+      char *argv[])
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+    ScSecurityToken *token;
William Jon McCann e8d4c0e
+    GError *error;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    g_log_set_always_fatal (G_LOG_LEVEL_ERROR
William Jon McCann e8d4c0e
+			    | G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    g_type_init ();
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    g_message ("creating instance of 'security token' object...");
William Jon McCann e8d4c0e
+    token = _sc_security_token_new (NULL, 1, 1);
William Jon McCann e8d4c0e
+    g_message ("'security token' object created successfully");
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    g_message ("destroying previously created 'security token' object...");
William Jon McCann e8d4c0e
+    g_object_unref (token);
William Jon McCann e8d4c0e
+    token = NULL;
William Jon McCann e8d4c0e
+    g_message ("'security token' object destroyed successfully");
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    return 0;
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+#endif
William Jon McCann e8d4c0e
diff -up /dev/null gnome-screensaver-2.23.3/src/securitytoken.h
William Jon McCann e8d4c0e
--- /dev/null	2008-07-27 17:37:58.142005663 -0400
William Jon McCann e8d4c0e
+++ gnome-screensaver-2.23.3/src/securitytoken.h	2008-07-27 23:20:06.000000000 -0400
William Jon McCann e8d4c0e
@@ -0,0 +1,94 @@
William Jon McCann e8d4c0e
+/* securitytoken.h - api for reading and writing data to a security token 
William Jon McCann e8d4c0e
+ *
William Jon McCann e8d4c0e
+ * Copyright (C) 2006 Ray Strode
William Jon McCann e8d4c0e
+ *
William Jon McCann e8d4c0e
+ * This program is free software; you can redistribute it and/or modify
William Jon McCann e8d4c0e
+ * it under the terms of the GNU General Public License as published by
William Jon McCann e8d4c0e
+ * the Free Software Foundation; either version 2, or (at your option)
William Jon McCann e8d4c0e
+ * any later version.
William Jon McCann e8d4c0e
+ *
William Jon McCann e8d4c0e
+ * This program is distributed in the hope that it will be useful,
William Jon McCann e8d4c0e
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
William Jon McCann e8d4c0e
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
William Jon McCann e8d4c0e
+ * GNU General Public License for more details.
William Jon McCann e8d4c0e
+ *
William Jon McCann e8d4c0e
+ * You should have received a copy of the GNU General Public License
William Jon McCann e8d4c0e
+ * along with this program; if not, write to the Free Software
William Jon McCann e8d4c0e
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
William Jon McCann e8d4c0e
+ * 02111-1307, USA.  
William Jon McCann e8d4c0e
+ */
William Jon McCann e8d4c0e
+#ifndef SC_SECURITY_TOKEN_H
William Jon McCann e8d4c0e
+#define SC_SECURITY_TOKEN_H
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+#include <glib.h>
William Jon McCann e8d4c0e
+#include <glib-object.h>
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+#include <secmod.h>
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+G_BEGIN_DECLS
William Jon McCann e8d4c0e
+#define SC_TYPE_SECURITY_TOKEN            (sc_security_token_get_type ())
William Jon McCann e8d4c0e
+#define SC_SECURITY_TOKEN(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), SC_TYPE_SECURITY_TOKEN, ScSecurityToken))
William Jon McCann e8d4c0e
+#define SC_SECURITY_TOKEN_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), SC_TYPE_SECURITY_TOKEN, ScSecurityTokenClass))
William Jon McCann e8d4c0e
+#define SC_IS_SECURITY_TOKEN(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SC_TYPE_SECURITY_TOKEN))
William Jon McCann e8d4c0e
+#define SC_IS_SECURITY_TOKEN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SC_TYPE_SECURITY_TOKEN))
William Jon McCann e8d4c0e
+#define SC_SECURITY_TOKEN_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), SC_TYPE_SECURITY_TOKEN, ScSecurityTokenClass))
William Jon McCann e8d4c0e
+#define SC_SECURITY_TOKEN_ERROR           (sc_security_token_error_quark ())
William Jon McCann e8d4c0e
+typedef struct _ScSecurityTokenClass ScSecurityTokenClass;
William Jon McCann e8d4c0e
+typedef struct _ScSecurityToken ScSecurityToken;
William Jon McCann e8d4c0e
+typedef struct _ScSecurityTokenPrivate ScSecurityTokenPrivate;
William Jon McCann e8d4c0e
+typedef enum _ScSecurityTokenError ScSecurityTokenError;
William Jon McCann e8d4c0e
+typedef enum _ScSecurityTokenState ScSecurityTokenState;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+typedef struct _ScSecurityTokenRequest ScSecurityTokenRequest;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+struct _ScSecurityToken {
William Jon McCann e8d4c0e
+    GObject parent;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    /*< private > */
William Jon McCann e8d4c0e
+    ScSecurityTokenPrivate *priv;
William Jon McCann e8d4c0e
+};
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+struct _ScSecurityTokenClass {
William Jon McCann e8d4c0e
+    GObjectClass parent_class;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    void (* inserted) (ScSecurityToken *token);
William Jon McCann e8d4c0e
+    void (* removed) (ScSecurityToken *token);
William Jon McCann e8d4c0e
+};
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+enum _ScSecurityTokenError {
William Jon McCann e8d4c0e
+    SC_SECURITY_TOKEN_ERROR_GENERIC = 0,
William Jon McCann e8d4c0e
+};
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+enum _ScSecurityTokenState {
William Jon McCann e8d4c0e
+    SC_SECURITY_TOKEN_STATE_INSERTED = 0,
William Jon McCann e8d4c0e
+    SC_SECURITY_TOKEN_STATE_REMOVED,
William Jon McCann e8d4c0e
+};
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+GType sc_security_token_get_type (void) G_GNUC_CONST;
William Jon McCann e8d4c0e
+GQuark sc_security_token_error_quark (void) G_GNUC_CONST;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+CK_SLOT_ID sc_security_token_get_slot_id (ScSecurityToken *token);
William Jon McCann e8d4c0e
+gint sc_security_token_get_slot_series (ScSecurityToken *token);
William Jon McCann e8d4c0e
+ScSecurityTokenState sc_security_token_get_state (ScSecurityToken *token);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+gchar *sc_security_token_get_name (ScSecurityToken *token);
William Jon McCann e8d4c0e
+gboolean sc_security_token_is_login_token (ScSecurityToken *token);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+gboolean sc_security_token_unlock (ScSecurityToken *token,
William Jon McCann e8d4c0e
+				   const gchar     *password);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+/* don't under any circumstances call these functions */
William Jon McCann e8d4c0e
+#ifdef SC_SECURITY_TOKEN_ENABLE_INTERNAL_API
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+ScSecurityToken *_sc_security_token_new (SECMODModule *module,
William Jon McCann e8d4c0e
+					 CK_SLOT_ID slot_id, 
William Jon McCann e8d4c0e
+					 gint slot_series);
William Jon McCann e8d4c0e
+ScSecurityToken *_sc_security_token_new_from_name (SECMODModule *module,
William Jon McCann e8d4c0e
+						   const gchar *name);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+void _sc_security_token_set_state (ScSecurityToken      *token,
William Jon McCann e8d4c0e
+				   ScSecurityTokenState  state);
William Jon McCann e8d4c0e
+#endif 
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+G_END_DECLS
William Jon McCann e8d4c0e
+#endif				/* SC_SECURITY_TOKEN_H */
William Jon McCann e8d4c0e
diff -up /dev/null gnome-screensaver-2.23.3/src/securitytokenmonitor.c
William Jon McCann e8d4c0e
--- /dev/null	2008-07-27 17:37:58.142005663 -0400
William Jon McCann e8d4c0e
+++ gnome-screensaver-2.23.3/src/securitytokenmonitor.c	2008-07-27 23:20:06.000000000 -0400
William Jon McCann e8d4c0e
@@ -0,0 +1,1743 @@
William Jon McCann e8d4c0e
+/* securitytokenmonitor.c - monitor for security token insertion and
William Jon McCann e8d4c0e
+ *                          removal events
William Jon McCann e8d4c0e
+ * 
William Jon McCann e8d4c0e
+ * Copyright (C) 2006 Ray Strode <rstrode@redhat.com>
William Jon McCann e8d4c0e
+ * 
William Jon McCann e8d4c0e
+ * This program is free software; you can redistribute it and/or modify
William Jon McCann e8d4c0e
+ * it under the terms of the GNU General Public License as published by
William Jon McCann e8d4c0e
+ * the Free Software Foundation; either version 2, or (at your option)
William Jon McCann e8d4c0e
+ * any later version.
William Jon McCann e8d4c0e
+ * 
William Jon McCann e8d4c0e
+ * This program is distributed in the hope that it will be useful,
William Jon McCann e8d4c0e
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
William Jon McCann e8d4c0e
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
William Jon McCann e8d4c0e
+ * GNU General Public License for more details.
William Jon McCann e8d4c0e
+ * 
William Jon McCann e8d4c0e
+ * You should have received a copy of the GNU General Public License
William Jon McCann e8d4c0e
+ * along with this program; if not, write to the Free Software
William Jon McCann e8d4c0e
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
William Jon McCann e8d4c0e
+ * 02111-1307, USA.  
William Jon McCann e8d4c0e
+ *
William Jon McCann e8d4c0e
+ * TODO:     - doing this per project is a bad idea i think.
William Jon McCann e8d4c0e
+ *             We should probably make this a system service 
William Jon McCann e8d4c0e
+ *             and use dbus.
William Jon McCann e8d4c0e
+ */
William Jon McCann e8d4c0e
+#define _GNU_SOURCE
William Jon McCann e8d4c0e
+#include "securitytokenmonitor.h"
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+#define SC_SECURITY_TOKEN_ENABLE_INTERNAL_API
William Jon McCann e8d4c0e
+#include "securitytoken.h"
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+#include <dirent.h>
William Jon McCann e8d4c0e
+#include <errno.h>
William Jon McCann e8d4c0e
+#include <fcntl.h>
William Jon McCann e8d4c0e
+#include <limits.h>
William Jon McCann e8d4c0e
+#include <poll.h>
William Jon McCann e8d4c0e
+#include <signal.h>
William Jon McCann e8d4c0e
+#include <stdlib.h>
William Jon McCann e8d4c0e
+#include <string.h>
William Jon McCann e8d4c0e
+#include <sys/resource.h>
William Jon McCann e8d4c0e
+#include <sys/time.h>
William Jon McCann e8d4c0e
+#include <sys/wait.h>
William Jon McCann e8d4c0e
+#include <unistd.h>
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+#include <glib.h>
William Jon McCann e8d4c0e
+#include <glib/gi18n.h>
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+#include <prerror.h>
William Jon McCann e8d4c0e
+#include <nss.h>
William Jon McCann e8d4c0e
+#include <pk11func.h>
William Jon McCann e8d4c0e
+#include <secmod.h>
William Jon McCann e8d4c0e
+#include <secerr.h>
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+#ifndef SC_SECURITY_TOKEN_MONITOR_DRIVER
William Jon McCann e8d4c0e
+#define SC_SECURITY_TOKEN_MONITOR_DRIVER LIBDIR"/pkcs11/libcoolkeypk11.so"
William Jon McCann e8d4c0e
+#endif
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+#ifndef SC_SECURITY_TOKEN_MONITOR_NSS_DB
William Jon McCann e8d4c0e
+#define SC_SECURITY_TOKEN_MONITOR_NSS_DB SYSCONFDIR"/pki/nssdb"
William Jon McCann e8d4c0e
+#endif 
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+#ifndef SC_MAX_OPEN_FILE_DESCRIPTORS
William Jon McCann e8d4c0e
+#define SC_MAX_OPEN_FILE_DESCRIPTORS 1024
William Jon McCann e8d4c0e
+#endif
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+#ifndef SC_OPEN_FILE_DESCRIPTORS_DIR
William Jon McCann e8d4c0e
+#define SC_OPEN_FILE_DESCRIPTORS_DIR "/proc/self/fd"
William Jon McCann e8d4c0e
+#endif
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+#ifndef sc_debug
William Jon McCann e8d4c0e
+#if defined (SC_SECURITY_TOKEN_MONITOR_ENABLE_TEST)
William Jon McCann e8d4c0e
+#define sc_debug(fmt, args...) g_printerr("[%u] " fmt " \n", getpid(), ##args)
William Jon McCann e8d4c0e
+#else
William Jon McCann e8d4c0e
+#define sc_debug(fmt, args...) 
William Jon McCann e8d4c0e
+#endif
William Jon McCann e8d4c0e
+#endif
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+typedef enum _ScSecurityTokenMonitorState ScSecurityTokenMonitorState;
William Jon McCann e8d4c0e
+typedef struct _ScSecurityTokenMonitorWorker ScSecurityTokenMonitorWorker;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+enum _ScSecurityTokenMonitorState {
William Jon McCann e8d4c0e
+	SC_SECURITY_TOKEN_MONITOR_STATE_STOPPED = 0,
William Jon McCann e8d4c0e
+	SC_SECURITY_TOKEN_MONITOR_STATE_STARTING,
William Jon McCann e8d4c0e
+	SC_SECURITY_TOKEN_MONITOR_STATE_STARTED,
William Jon McCann e8d4c0e
+	SC_SECURITY_TOKEN_MONITOR_STATE_STOPPING,
William Jon McCann e8d4c0e
+};
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+struct _ScSecurityTokenMonitorPrivate {
William Jon McCann e8d4c0e
+	ScSecurityTokenMonitorState state;
William Jon McCann e8d4c0e
+	SECMODModule *module;
William Jon McCann e8d4c0e
+	gchar        *module_path;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	GSource *security_token_event_source;
William Jon McCann e8d4c0e
+	GPid security_token_event_watcher_pid;
William Jon McCann e8d4c0e
+	GHashTable *security_tokens;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	guint poll_timeout_id;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	guint32 is_unstoppable : 1;
William Jon McCann e8d4c0e
+	guint32 nss_is_loaded : 1;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+#ifndef SC_SECURITY_TOKEN_MONITOR_DRIVER_CAN_BE_RELOADED_AFTER_BEING_DESTROYED
William Jon McCann e8d4c0e
+	GArray *fds_to_close_on_fork;
William Jon McCann e8d4c0e
+#endif 
William Jon McCann e8d4c0e
+};
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+struct _ScSecurityTokenMonitorWorker {
William Jon McCann e8d4c0e
+	SECMODModule *module;
William Jon McCann e8d4c0e
+	GHashTable *security_tokens;
William Jon McCann e8d4c0e
+	gint write_fd;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	guint32 nss_is_loaded : 1;
William Jon McCann e8d4c0e
+};
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+static void sc_security_token_monitor_finalize (GObject *object);
William Jon McCann e8d4c0e
+static void sc_security_token_monitor_class_install_signals (ScSecurityTokenMonitorClass *service_class);
William Jon McCann e8d4c0e
+static void sc_security_token_monitor_class_install_properties (ScSecurityTokenMonitorClass *service_class);
William Jon McCann e8d4c0e
+static void sc_security_token_monitor_set_property (GObject       *object,
William Jon McCann e8d4c0e
+						    guint          prop_id,
William Jon McCann e8d4c0e
+						    const GValue  *value,
William Jon McCann e8d4c0e
+						    GParamSpec    *pspec);
William Jon McCann e8d4c0e
+static void sc_security_token_monitor_get_property (GObject    *object,
William Jon McCann e8d4c0e
+						    guint       prop_id,
William Jon McCann e8d4c0e
+						    GValue     *value,
William Jon McCann e8d4c0e
+						    GParamSpec *pspec);
William Jon McCann e8d4c0e
+static void sc_security_token_monitor_set_module_path (ScSecurityTokenMonitor *monitor,
William Jon McCann e8d4c0e
+						       const gchar            *module_path);
William Jon McCann e8d4c0e
+static void sc_security_token_monitor_token_removed_handler (ScSecurityTokenMonitor *monitor,
William Jon McCann e8d4c0e
+							     ScSecurityToken        *token);
William Jon McCann e8d4c0e
+static void sc_security_token_monitor_token_inserted_handler (ScSecurityTokenMonitor *monitor_class,
William Jon McCann e8d4c0e
+							      ScSecurityToken        *token);
William Jon McCann e8d4c0e
+static gboolean sc_security_token_monitor_stop_now (ScSecurityTokenMonitor *monitor);
William Jon McCann e8d4c0e
+static void sc_security_token_monitor_queue_stop (ScSecurityTokenMonitor *monitor);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+static gboolean sc_security_token_monitor_create_worker (ScSecurityTokenMonitor *monitor,
William Jon McCann e8d4c0e
+							 gint *worker_fd, GPid *worker_pid);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+static ScSecurityTokenMonitorWorker * sc_security_token_monitor_worker_new (gint write_fd);
William Jon McCann e8d4c0e
+static void sc_security_token_monitor_worker_free (ScSecurityTokenMonitorWorker *worker);
William Jon McCann e8d4c0e
+static void sc_security_token_monitor_worker_die_with_parent (ScSecurityTokenMonitorWorker *worker);
William Jon McCann e8d4c0e
+static gboolean sc_open_pipe (gint *write_fd, gint *read_fd);
William Jon McCann e8d4c0e
+static gboolean sc_read_bytes (gint fd, gpointer bytes, gsize num_bytes);
William Jon McCann e8d4c0e
+static gboolean sc_write_bytes (gint fd, gconstpointer bytes, gsize num_bytes);
William Jon McCann e8d4c0e
+static ScSecurityToken *sc_read_security_token (gint fd, SECMODModule *module);
William Jon McCann e8d4c0e
+static gboolean sc_write_security_token (gint fd, ScSecurityToken *token);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+enum {
William Jon McCann e8d4c0e
+	PROP_0 = 0,
William Jon McCann e8d4c0e
+	PROP_MODULE_PATH,
William Jon McCann e8d4c0e
+	NUMBER_OF_PROPERTIES
William Jon McCann e8d4c0e
+};
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+enum {
William Jon McCann e8d4c0e
+	SECURITY_TOKEN_INSERTED = 0,
William Jon McCann e8d4c0e
+	SECURITY_TOKEN_REMOVED,
William Jon McCann e8d4c0e
+	ERROR,
William Jon McCann e8d4c0e
+	NUMBER_OF_SIGNALS
William Jon McCann e8d4c0e
+};
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+static guint sc_security_token_monitor_signals[NUMBER_OF_SIGNALS];
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+G_DEFINE_TYPE (ScSecurityTokenMonitor, 
William Jon McCann e8d4c0e
+	       sc_security_token_monitor, 
William Jon McCann e8d4c0e
+	       G_TYPE_OBJECT);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+static void
William Jon McCann e8d4c0e
+sc_security_token_monitor_class_init (ScSecurityTokenMonitorClass *monitor_class)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+    GObjectClass *gobject_class;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    gobject_class = G_OBJECT_CLASS (monitor_class);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    gobject_class->finalize = sc_security_token_monitor_finalize;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    sc_security_token_monitor_class_install_signals (monitor_class);
William Jon McCann e8d4c0e
+    sc_security_token_monitor_class_install_properties (monitor_class);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    g_type_class_add_private (monitor_class,
William Jon McCann e8d4c0e
+			      sizeof (ScSecurityTokenMonitorPrivate));
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+static void
William Jon McCann e8d4c0e
+sc_security_token_monitor_class_install_properties (ScSecurityTokenMonitorClass *token_class)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+    GObjectClass *object_class;
William Jon McCann e8d4c0e
+    GParamSpec *param_spec;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    object_class = G_OBJECT_CLASS (token_class);
William Jon McCann e8d4c0e
+    object_class->set_property = sc_security_token_monitor_set_property;
William Jon McCann e8d4c0e
+    object_class->get_property = sc_security_token_monitor_get_property;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    param_spec = g_param_spec_string ("module-path", _("Module Path"),
William Jon McCann e8d4c0e
+				      _("path to security token PKCS #11 driver"),
William Jon McCann e8d4c0e
+				      NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
William Jon McCann e8d4c0e
+    g_object_class_install_property (object_class, PROP_MODULE_PATH, param_spec);
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+static void 
William Jon McCann e8d4c0e
+sc_security_token_monitor_set_property (GObject       *object,
William Jon McCann e8d4c0e
+					guint          prop_id,
William Jon McCann e8d4c0e
+					const GValue  *value,
William Jon McCann e8d4c0e
+					GParamSpec    *pspec)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+    ScSecurityTokenMonitor *monitor = SC_SECURITY_TOKEN_MONITOR (object);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    switch (prop_id)
William Jon McCann e8d4c0e
+    {
William Jon McCann e8d4c0e
+	    case PROP_MODULE_PATH:
William Jon McCann e8d4c0e
+		    sc_security_token_monitor_set_module_path (monitor, 
William Jon McCann e8d4c0e
+							       g_value_get_string (value));
William Jon McCann e8d4c0e
+		    break;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	    default:
William Jon McCann e8d4c0e
+		    G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
William Jon McCann e8d4c0e
+		    break;
William Jon McCann e8d4c0e
+    }
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+static void 
William Jon McCann e8d4c0e
+sc_security_token_monitor_get_property (GObject    *object,
William Jon McCann e8d4c0e
+					guint       prop_id,
William Jon McCann e8d4c0e
+					GValue     *value,
William Jon McCann e8d4c0e
+					GParamSpec *pspec)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+    ScSecurityTokenMonitor *monitor = SC_SECURITY_TOKEN_MONITOR (object);
William Jon McCann e8d4c0e
+    gchar *module_path;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    switch (prop_id)
William Jon McCann e8d4c0e
+    {
William Jon McCann e8d4c0e
+	    case PROP_MODULE_PATH:
William Jon McCann e8d4c0e
+		    module_path = sc_security_token_monitor_get_module_path (monitor);
William Jon McCann e8d4c0e
+		    g_value_set_string (value, module_path);
William Jon McCann e8d4c0e
+		    g_free (module_path);
William Jon McCann e8d4c0e
+		    break;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	    default:
William Jon McCann e8d4c0e
+		    G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
William Jon McCann e8d4c0e
+		    break;
William Jon McCann e8d4c0e
+    }
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+gchar *
William Jon McCann e8d4c0e
+sc_security_token_monitor_get_module_path (ScSecurityTokenMonitor *monitor)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+    return monitor->priv->module_path;
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+static void
William Jon McCann e8d4c0e
+sc_security_token_monitor_set_module_path (ScSecurityTokenMonitor *monitor,
William Jon McCann e8d4c0e
+					   const gchar            *module_path)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+    if ((monitor->priv->module_path == NULL) && (module_path == NULL))
William Jon McCann e8d4c0e
+	    return;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    if (((monitor->priv->module_path == NULL) ||
William Jon McCann e8d4c0e
+	 (module_path == NULL) ||
William Jon McCann e8d4c0e
+	 (strcmp (monitor->priv->module_path, module_path) != 0))) {
William Jon McCann e8d4c0e
+	    g_free (monitor->priv->module_path);
William Jon McCann e8d4c0e
+	    monitor->priv->module_path = g_strdup (module_path);
William Jon McCann e8d4c0e
+	    g_object_notify (G_OBJECT (monitor), "module-path");
William Jon McCann e8d4c0e
+    }
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+static void
William Jon McCann e8d4c0e
+sc_security_token_monitor_token_removed_handler (ScSecurityTokenMonitor *monitor,
William Jon McCann e8d4c0e
+						 ScSecurityToken        *token)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+    sc_debug ("informing security token of its removal");
William Jon McCann e8d4c0e
+    _sc_security_token_set_state (token, SC_SECURITY_TOKEN_STATE_REMOVED);
William Jon McCann e8d4c0e
+    sc_debug ("done");
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+static void
William Jon McCann e8d4c0e
+sc_security_token_monitor_token_inserted_handler (ScSecurityTokenMonitor *monitor,
William Jon McCann e8d4c0e
+						  ScSecurityToken        *token)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+    sc_debug ("informing security token of its insertion");
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    _sc_security_token_set_state (token, SC_SECURITY_TOKEN_STATE_INSERTED);
William Jon McCann e8d4c0e
+    sc_debug ("done");
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+static void
William Jon McCann e8d4c0e
+sc_security_token_monitor_class_install_signals (ScSecurityTokenMonitorClass *monitor_class)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+    GObjectClass *object_class;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    object_class = G_OBJECT_CLASS (monitor_class);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    sc_security_token_monitor_signals[SECURITY_TOKEN_INSERTED] =
William Jon McCann e8d4c0e
+	    g_signal_new ("security-token-inserted",
William Jon McCann e8d4c0e
+			  G_OBJECT_CLASS_TYPE (object_class),
William Jon McCann e8d4c0e
+			  G_SIGNAL_RUN_FIRST,
William Jon McCann e8d4c0e
+			  G_STRUCT_OFFSET (ScSecurityTokenMonitorClass,
William Jon McCann e8d4c0e
+					   security_token_inserted), 
William Jon McCann e8d4c0e
+			  NULL, NULL, g_cclosure_marshal_VOID__POINTER, 
William Jon McCann e8d4c0e
+			  G_TYPE_NONE, 1, G_TYPE_POINTER);
William Jon McCann e8d4c0e
+    monitor_class->security_token_inserted = sc_security_token_monitor_token_inserted_handler;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    sc_security_token_monitor_signals[SECURITY_TOKEN_REMOVED] =
William Jon McCann e8d4c0e
+	    g_signal_new ("security-token-removed",
William Jon McCann e8d4c0e
+			  G_OBJECT_CLASS_TYPE (object_class),
William Jon McCann e8d4c0e
+			  G_SIGNAL_RUN_FIRST,
William Jon McCann e8d4c0e
+			  G_STRUCT_OFFSET (ScSecurityTokenMonitorClass,
William Jon McCann e8d4c0e
+					   security_token_removed), 
William Jon McCann e8d4c0e
+			  NULL, NULL, g_cclosure_marshal_VOID__POINTER, 
William Jon McCann e8d4c0e
+			  G_TYPE_NONE, 1, G_TYPE_POINTER);
William Jon McCann e8d4c0e
+    monitor_class->security_token_removed = sc_security_token_monitor_token_removed_handler;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    sc_security_token_monitor_signals[ERROR] =
William Jon McCann e8d4c0e
+	    g_signal_new ("error",
William Jon McCann e8d4c0e
+			  G_OBJECT_CLASS_TYPE (object_class),
William Jon McCann e8d4c0e
+			  G_SIGNAL_RUN_LAST,
William Jon McCann e8d4c0e
+			  G_STRUCT_OFFSET (ScSecurityTokenMonitorClass, error),
William Jon McCann e8d4c0e
+			  NULL, NULL, g_cclosure_marshal_VOID__POINTER,
William Jon McCann e8d4c0e
+			  G_TYPE_NONE, 1, G_TYPE_POINTER);
William Jon McCann e8d4c0e
+    monitor_class->error = NULL;
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+static gboolean
William Jon McCann e8d4c0e
+sc_slot_id_equal (CK_SLOT_ID *slot_id_1, 
William Jon McCann e8d4c0e
+		  CK_SLOT_ID *slot_id_2)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+    g_assert (slot_id_1 != NULL);
William Jon McCann e8d4c0e
+    g_assert (slot_id_2 != NULL);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    return *slot_id_1 == *slot_id_2;
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+static gboolean
William Jon McCann e8d4c0e
+sc_slot_id_hash (CK_SLOT_ID *slot_id) 
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+    guint32 upper_bits, lower_bits;
William Jon McCann e8d4c0e
+    gint temp;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    if (sizeof (CK_SLOT_ID) == sizeof (gint))
William Jon McCann e8d4c0e
+	    return g_int_hash (slot_id);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    upper_bits = ((*slot_id) >> 31) - 1;
William Jon McCann e8d4c0e
+    lower_bits = (*slot_id) & 0xffffffff;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    /* The upper bits are almost certainly always zero,
William Jon McCann e8d4c0e
+     * so let's degenerate to g_int_hash for the 
William Jon McCann e8d4c0e
+     * (very) common case
William Jon McCann e8d4c0e
+     */
William Jon McCann e8d4c0e
+    temp = lower_bits + upper_bits;
William Jon McCann e8d4c0e
+    return upper_bits + g_int_hash (&temp);
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+static void
William Jon McCann e8d4c0e
+sc_security_token_monitor_init (ScSecurityTokenMonitor *monitor)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+    sc_debug ("initializing security token monitor");
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    monitor->priv = G_TYPE_INSTANCE_GET_PRIVATE (monitor,
William Jon McCann e8d4c0e
+						 SC_TYPE_SECURITY_TOKEN_MONITOR,
William Jon McCann e8d4c0e
+						 ScSecurityTokenMonitorPrivate);
William Jon McCann e8d4c0e
+    monitor->priv->poll_timeout_id = 0;
William Jon McCann e8d4c0e
+    monitor->priv->is_unstoppable = FALSE;
William Jon McCann e8d4c0e
+    monitor->priv->module = NULL;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    monitor->priv->security_tokens = 
William Jon McCann e8d4c0e
+	    g_hash_table_new_full (g_str_hash, 
William Jon McCann e8d4c0e
+				   g_str_equal,
William Jon McCann e8d4c0e
+				   (GDestroyNotify) g_free, 
William Jon McCann e8d4c0e
+				   (GDestroyNotify) g_object_unref);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+#ifndef SC_SECURITY_TOKEN_MONITOR_DRIVER_CAN_BE_RELOADED_AFTER_BEING_DESTROYED
William Jon McCann e8d4c0e
+    monitor->priv->fds_to_close_on_fork = g_array_new (FALSE, FALSE, sizeof (gint));
William Jon McCann e8d4c0e
+#endif
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+static void 
William Jon McCann e8d4c0e
+sc_security_token_monitor_finalize (GObject *object)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+    ScSecurityTokenMonitor *monitor;
William Jon McCann e8d4c0e
+    GObjectClass *gobject_class;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    monitor = SC_SECURITY_TOKEN_MONITOR (object);
William Jon McCann e8d4c0e
+    gobject_class =
William Jon McCann e8d4c0e
+	    G_OBJECT_CLASS (sc_security_token_monitor_parent_class);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    sc_security_token_monitor_stop_now (monitor);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    g_hash_table_destroy (monitor->priv->security_tokens);
William Jon McCann e8d4c0e
+    monitor->priv->security_tokens = NULL;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+#ifndef SC_SECURITY_TOKEN_MONITOR_DRIVER_CAN_BE_RELOADED_AFTER_BEING_DESTROYED
William Jon McCann e8d4c0e
+    g_array_free (monitor->priv->fds_to_close_on_fork, TRUE);
William Jon McCann e8d4c0e
+#endif 
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    gobject_class->finalize (object);
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+GQuark 
William Jon McCann e8d4c0e
+sc_security_token_monitor_error_quark (void)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+    static GQuark error_quark = 0;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    if (error_quark == 0)
William Jon McCann e8d4c0e
+	    error_quark = g_quark_from_static_string ("sc-security-token-monitor-error-quark");
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    return error_quark;
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+ScSecurityTokenMonitor *
William Jon McCann e8d4c0e
+sc_security_token_monitor_new (const gchar *module_path)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+    ScSecurityTokenMonitor *instance;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    instance = SC_SECURITY_TOKEN_MONITOR (g_object_new (SC_TYPE_SECURITY_TOKEN_MONITOR, 
William Jon McCann e8d4c0e
+							"module-path", module_path,
William Jon McCann e8d4c0e
+							NULL));
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    return instance;
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+static void 
William Jon McCann e8d4c0e
+sc_security_token_monitor_emit_error (ScSecurityTokenMonitor *monitor,
William Jon McCann e8d4c0e
+				      GError                 *error)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+    monitor->priv->is_unstoppable = TRUE;
William Jon McCann e8d4c0e
+    g_signal_emit (monitor, sc_security_token_monitor_signals[ERROR], 0,
William Jon McCann e8d4c0e
+		   error);
William Jon McCann e8d4c0e
+    monitor->priv->is_unstoppable = FALSE;
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+static void 
William Jon McCann e8d4c0e
+sc_security_token_monitor_emit_security_token_inserted (ScSecurityTokenMonitor *monitor,
William Jon McCann e8d4c0e
+							ScSecurityToken        *token)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+    monitor->priv->is_unstoppable = TRUE;
William Jon McCann e8d4c0e
+    g_signal_emit (monitor, sc_security_token_monitor_signals[SECURITY_TOKEN_INSERTED], 0,
William Jon McCann e8d4c0e
+		   token);
William Jon McCann e8d4c0e
+    monitor->priv->is_unstoppable = FALSE;
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+static void 
William Jon McCann e8d4c0e
+sc_security_token_monitor_emit_security_token_removed (ScSecurityTokenMonitor *monitor,
William Jon McCann e8d4c0e
+							ScSecurityToken        *token)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+    ScSecurityTokenMonitorState old_state;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    old_state = monitor->priv->state;
William Jon McCann e8d4c0e
+    monitor->priv->is_unstoppable = TRUE;
William Jon McCann e8d4c0e
+    g_signal_emit (monitor, sc_security_token_monitor_signals[SECURITY_TOKEN_REMOVED], 0,
William Jon McCann e8d4c0e
+		   token);
William Jon McCann e8d4c0e
+    monitor->priv->is_unstoppable = FALSE;
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+static gboolean
William Jon McCann e8d4c0e
+sc_security_token_monitor_check_for_and_process_events (GIOChannel *io_channel,
William Jon McCann e8d4c0e
+							GIOCondition condition,
William Jon McCann e8d4c0e
+							ScSecurityTokenMonitor *monitor)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+    ScSecurityToken *token;
William Jon McCann e8d4c0e
+    gboolean should_stop;
William Jon McCann e8d4c0e
+    guchar event_type;
William Jon McCann e8d4c0e
+    gchar *token_name;
William Jon McCann e8d4c0e
+    gint fd;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    token = NULL;
William Jon McCann e8d4c0e
+    should_stop = (condition & G_IO_HUP) || (condition & G_IO_ERR);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    if (should_stop)
William Jon McCann e8d4c0e
+	    sc_debug ("received %s on event socket, stopping "
William Jon McCann e8d4c0e
+		      "monitor...", 
William Jon McCann e8d4c0e
+		      (condition & G_IO_HUP) && (condition & G_IO_ERR)? 
William Jon McCann e8d4c0e
+		      "error and hangup" : 
William Jon McCann e8d4c0e
+		      (condition & G_IO_HUP)? 
William Jon McCann e8d4c0e
+		      "hangup" : "error");
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    if (!(condition & G_IO_IN))
William Jon McCann e8d4c0e
+	    goto out;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    fd = g_io_channel_unix_get_fd (io_channel);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    event_type = '\0';
William Jon McCann e8d4c0e
+    if (!sc_read_bytes (fd, &event_type, 1)) {
William Jon McCann e8d4c0e
+	    should_stop = TRUE;
William Jon McCann e8d4c0e
+	    goto out;
William Jon McCann e8d4c0e
+    }
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    token = sc_read_security_token (fd, monitor->priv->module);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    if (token == NULL) {
William Jon McCann e8d4c0e
+	    should_stop = TRUE;
William Jon McCann e8d4c0e
+	    goto out;
William Jon McCann e8d4c0e
+    }
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    token_name = sc_security_token_get_name (token);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    switch (event_type) {
William Jon McCann e8d4c0e
+	    case 'I':
William Jon McCann e8d4c0e
+		    g_hash_table_replace (monitor->priv->security_tokens,
William Jon McCann e8d4c0e
+					  token_name, token);
William Jon McCann e8d4c0e
+		    token_name = NULL;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+		    sc_security_token_monitor_emit_security_token_inserted (monitor, token);
William Jon McCann e8d4c0e
+		    token = NULL;
William Jon McCann e8d4c0e
+		    break;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	    case 'R':
William Jon McCann e8d4c0e
+		    sc_security_token_monitor_emit_security_token_removed (monitor, token);
William Jon McCann e8d4c0e
+		    if (!g_hash_table_remove (monitor->priv->security_tokens, token_name))
William Jon McCann e8d4c0e
+			    sc_debug ("got removal event of unknown token!");
William Jon McCann e8d4c0e
+		    g_free (token_name);
William Jon McCann e8d4c0e
+		    token_name = NULL;
William Jon McCann e8d4c0e
+		    token = NULL;
William Jon McCann e8d4c0e
+		    break;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	    default: 
William Jon McCann e8d4c0e
+		    g_free (token_name);
William Jon McCann e8d4c0e
+		    token_name = NULL;
William Jon McCann e8d4c0e
+		    g_object_unref (token);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+		    should_stop = TRUE;
William Jon McCann e8d4c0e
+		    break;
William Jon McCann e8d4c0e
+    }
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+out:
William Jon McCann e8d4c0e
+    if (should_stop) {
William Jon McCann e8d4c0e
+	    GError *error;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	    error = g_error_new (SC_SECURITY_TOKEN_MONITOR_ERROR,
William Jon McCann e8d4c0e
+				 SC_SECURITY_TOKEN_MONITOR_ERROR_WATCHING_FOR_EVENTS,
William Jon McCann e8d4c0e
+				 "%s", (condition & G_IO_IN) ? g_strerror (errno) : _("received error or hang up from event source"));
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	    sc_security_token_monitor_emit_error (monitor, error);
William Jon McCann e8d4c0e
+	    g_error_free (error);
William Jon McCann e8d4c0e
+	    sc_security_token_monitor_stop_now (monitor);
William Jon McCann e8d4c0e
+	    return FALSE;
William Jon McCann e8d4c0e
+    }
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    return TRUE;
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+static void
William Jon McCann e8d4c0e
+sc_security_token_monitor_event_processing_stopped_handler (ScSecurityTokenMonitor *monitor)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+    monitor->priv->security_token_event_source = NULL;
William Jon McCann e8d4c0e
+    sc_security_token_monitor_stop_now (monitor);
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+/* sorta complex function that is nothing more than fork() without having
William Jon McCann e8d4c0e
+ * to worry about reaping the child later with waitpid
William Jon McCann e8d4c0e
+ */
William Jon McCann e8d4c0e
+static GPid
William Jon McCann e8d4c0e
+sc_fork_and_disown (void)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+    pid_t child_pid;
William Jon McCann e8d4c0e
+    GPid grandchild_pid;
William Jon McCann e8d4c0e
+    gint write_fd, read_fd;
William Jon McCann e8d4c0e
+    gint saved_errno;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    write_fd = -1;
William Jon McCann e8d4c0e
+    read_fd = -1;
William Jon McCann e8d4c0e
+    if (!sc_open_pipe (&write_fd, &read_fd))
William Jon McCann e8d4c0e
+	    return (GPid) -1;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    child_pid = fork ();
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    if (child_pid < 0) {
William Jon McCann e8d4c0e
+	    close (write_fd);
William Jon McCann e8d4c0e
+	    close (read_fd);
William Jon McCann e8d4c0e
+	    return (GPid) child_pid;
William Jon McCann e8d4c0e
+    }
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    if (child_pid == 0) {
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	    /* close the end of the pipe we're not going to use
William Jon McCann e8d4c0e
+	     */
William Jon McCann e8d4c0e
+	    close (read_fd);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	    /* fork again 
William Jon McCann e8d4c0e
+	     */
William Jon McCann e8d4c0e
+	    child_pid = fork ();
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	    /* in the event of error, write out negative errno
William Jon McCann e8d4c0e
+	     */
William Jon McCann e8d4c0e
+	    if (child_pid < 0) {
William Jon McCann e8d4c0e
+		    child_pid = -1 * errno;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+		    sc_write_bytes (write_fd, &child_pid, sizeof (child_pid));
William Jon McCann e8d4c0e
+		    close (write_fd);
William Jon McCann e8d4c0e
+		    _exit (1);
William Jon McCann e8d4c0e
+	    }
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	    /* otherwise write out the pid of the child and exit
William Jon McCann e8d4c0e
+	     */
William Jon McCann e8d4c0e
+	    if (child_pid != 0) {
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+		    signal (SIGPIPE, SIG_IGN);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+		    if (!sc_write_bytes (write_fd, &child_pid, sizeof (child_pid))) {
William Jon McCann e8d4c0e
+			    kill (SIGKILL, child_pid);
William Jon McCann e8d4c0e
+			    _exit (2);
William Jon McCann e8d4c0e
+		    }
William Jon McCann e8d4c0e
+		    close (write_fd);
William Jon McCann e8d4c0e
+		    _exit (0);
William Jon McCann e8d4c0e
+	    }
William Jon McCann e8d4c0e
+	    close (write_fd);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	    /* we're done, we've forked without having to worry about
William Jon McCann e8d4c0e
+	     * reaping the child later
William Jon McCann e8d4c0e
+	     */
William Jon McCann e8d4c0e
+	    g_assert (child_pid == 0);
William Jon McCann e8d4c0e
+	    return (GPid) 0;
William Jon McCann e8d4c0e
+    }
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    /* close the end of the pipe we're not going to use
William Jon McCann e8d4c0e
+     */
William Jon McCann e8d4c0e
+    close (write_fd);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    grandchild_pid = -1;
William Jon McCann e8d4c0e
+    if (!sc_read_bytes (read_fd, &grandchild_pid, sizeof (grandchild_pid))) {
William Jon McCann e8d4c0e
+	    grandchild_pid = -1;
William Jon McCann e8d4c0e
+    }
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    saved_errno = errno;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    /* close the other end of the pipe since we're done with it
William Jon McCann e8d4c0e
+     */
William Jon McCann e8d4c0e
+    close (read_fd);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    /* wait for child to die (and emancipate the grandchild)
William Jon McCann e8d4c0e
+     */
William Jon McCann e8d4c0e
+    waitpid (child_pid, NULL, 0);
William Jon McCann e8d4c0e
+    
William Jon McCann e8d4c0e
+    errno = saved_errno;
William Jon McCann e8d4c0e
+    return (GPid) grandchild_pid;
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+static gboolean
William Jon McCann e8d4c0e
+sc_open_pipe (gint *write_fd,
William Jon McCann e8d4c0e
+	      gint *read_fd)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+    gint pipe_fds[2] = { -1, -1 };
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    g_assert (write_fd != NULL);
William Jon McCann e8d4c0e
+    g_assert (read_fd != NULL);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    if (pipe (pipe_fds) < 0)
William Jon McCann e8d4c0e
+	    return FALSE;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    if (fcntl (pipe_fds[0], F_SETFD, FD_CLOEXEC) < 0) {
William Jon McCann e8d4c0e
+	    close (pipe_fds[0]);
William Jon McCann e8d4c0e
+	    close (pipe_fds[1]);
William Jon McCann e8d4c0e
+	    return FALSE;
William Jon McCann e8d4c0e
+    }
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    if (fcntl (pipe_fds[1], F_SETFD, FD_CLOEXEC) < 0) {
William Jon McCann e8d4c0e
+	    close (pipe_fds[0]);
William Jon McCann e8d4c0e
+	    close (pipe_fds[1]);
William Jon McCann e8d4c0e
+	    return FALSE;
William Jon McCann e8d4c0e
+    }
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    *read_fd = pipe_fds[0];
William Jon McCann e8d4c0e
+    *write_fd = pipe_fds[1];
William Jon McCann e8d4c0e
+ 
William Jon McCann e8d4c0e
+    return TRUE;
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+static void
William Jon McCann e8d4c0e
+sc_security_token_monitor_stop_watching_for_events (ScSecurityTokenMonitor  *monitor)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+    if (monitor->priv->security_token_event_source != NULL) {
William Jon McCann e8d4c0e
+	    g_source_destroy (monitor->priv->security_token_event_source);
William Jon McCann e8d4c0e
+	    monitor->priv->security_token_event_source = NULL;
William Jon McCann e8d4c0e
+    }
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    if (monitor->priv->security_token_event_watcher_pid > 0) {
William Jon McCann e8d4c0e
+	    kill (monitor->priv->security_token_event_watcher_pid, SIGKILL);
William Jon McCann e8d4c0e
+	    monitor->priv->security_token_event_watcher_pid = 0;
William Jon McCann e8d4c0e
+    }
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+static gboolean
William Jon McCann e8d4c0e
+sc_load_nss (GError **error)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+    SECStatus status = SECSuccess;
William Jon McCann e8d4c0e
+    static const guint32 flags = 
William Jon McCann e8d4c0e
+	NSS_INIT_READONLY| NSS_INIT_NOCERTDB | NSS_INIT_NOMODDB | 
William Jon McCann e8d4c0e
+	NSS_INIT_FORCEOPEN | NSS_INIT_NOROOTINIT | 
William Jon McCann e8d4c0e
+	NSS_INIT_OPTIMIZESPACE | NSS_INIT_PK11RELOAD;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    sc_debug ("attempting to load NSS database '%s'",
William Jon McCann e8d4c0e
+	      SC_SECURITY_TOKEN_MONITOR_NSS_DB);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    status = NSS_Initialize (SC_SECURITY_TOKEN_MONITOR_NSS_DB,
William Jon McCann e8d4c0e
+			     "", "", SECMOD_DB, flags);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    if (status != SECSuccess) {
William Jon McCann e8d4c0e
+	    gsize error_message_size;
William Jon McCann e8d4c0e
+	    gchar *error_message;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	    error_message_size = PR_GetErrorTextLength ();
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	    if (error_message_size == 0) {
William Jon McCann e8d4c0e
+		    sc_debug ("NSS security system could not be initialized");
William Jon McCann e8d4c0e
+		    g_set_error (error,
William Jon McCann e8d4c0e
+				 SC_SECURITY_TOKEN_MONITOR_ERROR,
William Jon McCann e8d4c0e
+				 SC_SECURITY_TOKEN_MONITOR_ERROR_WITH_NSS,
William Jon McCann e8d4c0e
+				 _("NSS security system could not be initialized"));
William Jon McCann e8d4c0e
+		    goto out;
William Jon McCann e8d4c0e
+	    }
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	    error_message = g_slice_alloc0 (error_message_size);
William Jon McCann e8d4c0e
+	    PR_GetErrorText (error_message);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	    g_set_error (error,
William Jon McCann e8d4c0e
+			 SC_SECURITY_TOKEN_MONITOR_ERROR,
William Jon McCann e8d4c0e
+			 SC_SECURITY_TOKEN_MONITOR_ERROR_WITH_NSS,
William Jon McCann e8d4c0e
+			 "%s", error_message);
William Jon McCann e8d4c0e
+	    sc_debug ("NSS security system could not be initialized - %s",
William Jon McCann e8d4c0e
+		      error_message);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	    g_slice_free1 (error_message_size, error_message);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	    goto out;
William Jon McCann e8d4c0e
+    }
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    sc_debug ("NSS database sucessfully loaded");
William Jon McCann e8d4c0e
+    return TRUE;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+out:
William Jon McCann e8d4c0e
+    sc_debug ("NSS database couldn't be sucessfully loaded");
William Jon McCann e8d4c0e
+    return FALSE;
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+static SECMODModule *
William Jon McCann e8d4c0e
+sc_load_driver (gchar   *module_path,
William Jon McCann e8d4c0e
+		GError **error)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+    SECMODModule *module;
William Jon McCann e8d4c0e
+    gchar *module_spec;
William Jon McCann e8d4c0e
+    gboolean module_explicitly_specified;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    sc_debug ("attempting to load driver...");
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    module = NULL;
William Jon McCann e8d4c0e
+    module_explicitly_specified = module_path != NULL;
William Jon McCann e8d4c0e
+    if (module_explicitly_specified) {
William Jon McCann e8d4c0e
+	    module_spec = g_strdup_printf ("library=\"%s\"", module_path);
William Jon McCann e8d4c0e
+	    sc_debug ("loading security token driver using spec '%s'",
William Jon McCann e8d4c0e
+		      module_spec);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	    module = SECMOD_LoadUserModule (module_spec, 
William Jon McCann e8d4c0e
+					    NULL /* parent */, 
William Jon McCann e8d4c0e
+					    FALSE /* recurse */);
William Jon McCann e8d4c0e
+	    g_free (module_spec);
William Jon McCann e8d4c0e
+	    module_spec = NULL;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    } else {
William Jon McCann e8d4c0e
+	    SECMODModuleList *modules, *tmp;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	    modules = SECMOD_GetDefaultModuleList ();
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	    for (tmp = modules; tmp != NULL; tmp = tmp->next) {
William Jon McCann e8d4c0e
+		    if (!SECMOD_HasRemovableSlots (tmp->module) ||
William Jon McCann e8d4c0e
+			!tmp->module->loaded)
William Jon McCann e8d4c0e
+			    continue;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+		    module = SECMOD_ReferenceModule (tmp->module);
William Jon McCann e8d4c0e
+		    break;
William Jon McCann e8d4c0e
+	    }
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	    /* fallback to compiled in driver path
William Jon McCann e8d4c0e
+	     */
William Jon McCann e8d4c0e
+	    if (module == NULL) {
William Jon McCann e8d4c0e
+		    if (g_file_test (SC_SECURITY_TOKEN_MONITOR_DRIVER,
William Jon McCann e8d4c0e
+				     G_FILE_TEST_IS_REGULAR)) {
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+			    module_spec = g_strdup_printf ("library=\"%s\"", module_path);
William Jon McCann e8d4c0e
+			    sc_debug ("loading security token driver using spec '%s'",
William Jon McCann e8d4c0e
+				      module_spec);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+			    module = SECMOD_LoadUserModule (module_spec, 
William Jon McCann e8d4c0e
+							    NULL /* parent */, 
William Jon McCann e8d4c0e
+							    FALSE /* recurse */);
William Jon McCann e8d4c0e
+			    g_free (module_spec);
William Jon McCann e8d4c0e
+			    module_spec = NULL;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+		    }
William Jon McCann e8d4c0e
+	    }
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    }
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    if (!module_explicitly_specified && module == NULL) {
William Jon McCann e8d4c0e
+	    g_set_error (error,
William Jon McCann e8d4c0e
+			 SC_SECURITY_TOKEN_MONITOR_ERROR,
William Jon McCann e8d4c0e
+			 SC_SECURITY_TOKEN_MONITOR_ERROR_LOADING_DRIVER,
William Jon McCann e8d4c0e
+			 _("no suitable security token driver could be found"));
William Jon McCann e8d4c0e
+    } else if (module == NULL || !module->loaded) {
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	    gsize error_message_size;
William Jon McCann e8d4c0e
+	    gchar *error_message;
William Jon McCann e8d4c0e
+            
William Jon McCann e8d4c0e
+	    if (module != NULL && !module->loaded) {
William Jon McCann e8d4c0e
+		    sc_debug ("module found but not loaded?!");
William Jon McCann e8d4c0e
+		    SECMOD_DestroyModule (module);
William Jon McCann e8d4c0e
+		    module = NULL;
William Jon McCann e8d4c0e
+	    }
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	    error_message_size = PR_GetErrorTextLength ();
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	    if (error_message_size == 0) {
William Jon McCann e8d4c0e
+		    sc_debug ("security token driver '%s' could not be loaded",
William Jon McCann e8d4c0e
+			      module_path);
William Jon McCann e8d4c0e
+		    g_set_error (error,
William Jon McCann e8d4c0e
+				 SC_SECURITY_TOKEN_MONITOR_ERROR,
William Jon McCann e8d4c0e
+				 SC_SECURITY_TOKEN_MONITOR_ERROR_LOADING_DRIVER,
William Jon McCann e8d4c0e
+				 _("security token driver '%s' could not be "
William Jon McCann e8d4c0e
+				   "loaded"), module_path);
William Jon McCann e8d4c0e
+		    goto out;
William Jon McCann e8d4c0e
+	    }
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	    error_message = g_slice_alloc0 (error_message_size);
William Jon McCann e8d4c0e
+	    PR_GetErrorText (error_message);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	    g_set_error (error,
William Jon McCann e8d4c0e
+			 SC_SECURITY_TOKEN_MONITOR_ERROR,
William Jon McCann e8d4c0e
+			 SC_SECURITY_TOKEN_MONITOR_ERROR_LOADING_DRIVER,
William Jon McCann e8d4c0e
+			 "%s", error_message);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	    sc_debug ("security token driver '%s' could not be loaded - %s",
William Jon McCann e8d4c0e
+		      module_path, error_message);
William Jon McCann e8d4c0e
+	    g_slice_free1 (error_message_size, error_message);
William Jon McCann e8d4c0e
+    }
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+out:
William Jon McCann e8d4c0e
+    return module;
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+static void
William Jon McCann e8d4c0e
+sc_security_token_monitor_get_all_tokens (ScSecurityTokenMonitor *monitor)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+    int i;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    for (i = 0; i < monitor->priv->module->slotCount; i++) {
William Jon McCann e8d4c0e
+	    ScSecurityToken *token;
William Jon McCann e8d4c0e
+	    CK_SLOT_ID    slot_id;
William Jon McCann e8d4c0e
+	    gint          slot_series;
William Jon McCann e8d4c0e
+	    gchar *token_name;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	    slot_id = PK11_GetSlotID (monitor->priv->module->slots[i]);
William Jon McCann e8d4c0e
+	    slot_series = PK11_GetSlotSeries (monitor->priv->module->slots[i]);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	    token = _sc_security_token_new (monitor->priv->module, 
William Jon McCann e8d4c0e
+					    slot_id, slot_series);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	    token_name = sc_security_token_get_name (token);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	    g_hash_table_replace (monitor->priv->security_tokens,
William Jon McCann e8d4c0e
+				  token_name, token);
William Jon McCann e8d4c0e
+    }
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+gboolean
William Jon McCann e8d4c0e
+sc_security_token_monitor_start (ScSecurityTokenMonitor  *monitor,
William Jon McCann e8d4c0e
+				 GError                 **error)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+    GError *watching_error;
William Jon McCann e8d4c0e
+    gint worker_fd;
William Jon McCann e8d4c0e
+    GPid worker_pid;
William Jon McCann e8d4c0e
+    GIOChannel *io_channel;
William Jon McCann e8d4c0e
+    GSource *source;
William Jon McCann e8d4c0e
+    GIOFlags channel_flags;
William Jon McCann e8d4c0e
+    GError *nss_error;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    if (monitor->priv->state == SC_SECURITY_TOKEN_MONITOR_STATE_STARTED) {
William Jon McCann e8d4c0e
+	    sc_debug ("security token monitor already started");
William Jon McCann e8d4c0e
+	    return TRUE;
William Jon McCann e8d4c0e
+    }
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    monitor->priv->state = SC_SECURITY_TOKEN_MONITOR_STATE_STARTING;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    worker_fd = -1;
William Jon McCann e8d4c0e
+    worker_pid = 0;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    nss_error = NULL;
William Jon McCann e8d4c0e
+    if (!monitor->priv->nss_is_loaded && !sc_load_nss (&nss_error)) {
William Jon McCann e8d4c0e
+	    g_propagate_error (error, nss_error);
William Jon McCann e8d4c0e
+	    goto out;
William Jon McCann e8d4c0e
+    }
William Jon McCann e8d4c0e
+    monitor->priv->nss_is_loaded = TRUE;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    if (monitor->priv->module == NULL)
William Jon McCann e8d4c0e
+	    monitor->priv->module = sc_load_driver (monitor->priv->module_path, &nss_error);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    if (monitor->priv->module == NULL) {
William Jon McCann e8d4c0e
+	    g_propagate_error (error, nss_error);
William Jon McCann e8d4c0e
+	    goto out;
William Jon McCann e8d4c0e
+    }
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    if (!sc_security_token_monitor_create_worker (monitor, &worker_fd, &worker_pid)) {
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	    g_set_error (error,
William Jon McCann e8d4c0e
+			 SC_SECURITY_TOKEN_MONITOR_ERROR,
William Jon McCann e8d4c0e
+			 SC_SECURITY_TOKEN_MONITOR_ERROR_WATCHING_FOR_EVENTS,
William Jon McCann e8d4c0e
+			 _("could not watch for incoming token events - %s"),
William Jon McCann e8d4c0e
+			 g_strerror (errno));
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	    goto out;
William Jon McCann e8d4c0e
+    }
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    monitor->priv->security_token_event_watcher_pid = worker_pid;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    io_channel = g_io_channel_unix_new (worker_fd);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    channel_flags = g_io_channel_get_flags (io_channel);
William Jon McCann e8d4c0e
+    watching_error = NULL;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    source = g_io_create_watch (io_channel, G_IO_IN | G_IO_HUP);
William Jon McCann e8d4c0e
+    g_io_channel_unref (io_channel);
William Jon McCann e8d4c0e
+    io_channel = NULL;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    monitor->priv->security_token_event_source = source;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    g_source_set_callback (monitor->priv->security_token_event_source,
William Jon McCann e8d4c0e
+			   (GSourceFunc) (GIOFunc)
William Jon McCann e8d4c0e
+			   sc_security_token_monitor_check_for_and_process_events,
William Jon McCann e8d4c0e
+			   monitor,
William Jon McCann e8d4c0e
+			   (GDestroyNotify)
William Jon McCann e8d4c0e
+			   sc_security_token_monitor_event_processing_stopped_handler);
William Jon McCann e8d4c0e
+    g_source_attach (monitor->priv->security_token_event_source, NULL);
William Jon McCann e8d4c0e
+    g_source_unref (monitor->priv->security_token_event_source);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    /* populate the hash with tokens that are already inserted
William Jon McCann e8d4c0e
+     */
William Jon McCann e8d4c0e
+    sc_security_token_monitor_get_all_tokens (monitor);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    monitor->priv->state = SC_SECURITY_TOKEN_MONITOR_STATE_STARTED;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+out:
William Jon McCann e8d4c0e
+    /* don't leave it in a half started state
William Jon McCann e8d4c0e
+     */
William Jon McCann e8d4c0e
+    if (monitor->priv->state != SC_SECURITY_TOKEN_MONITOR_STATE_STARTED) {
William Jon McCann e8d4c0e
+	    sc_debug ("security token monitor could not be completely started");
William Jon McCann e8d4c0e
+	    sc_security_token_monitor_stop (monitor);
William Jon McCann e8d4c0e
+    } else
William Jon McCann e8d4c0e
+	    sc_debug ("security token monitor started");
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    return monitor->priv->state == SC_SECURITY_TOKEN_MONITOR_STATE_STARTED;
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+static gboolean
William Jon McCann e8d4c0e
+sc_security_token_monitor_stop_now (ScSecurityTokenMonitor *monitor)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+    if (monitor->priv->state == SC_SECURITY_TOKEN_MONITOR_STATE_STOPPED)
William Jon McCann e8d4c0e
+	    return FALSE;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    monitor->priv->state = SC_SECURITY_TOKEN_MONITOR_STATE_STOPPED;
William Jon McCann e8d4c0e
+    sc_security_token_monitor_stop_watching_for_events (monitor);
William Jon McCann e8d4c0e
+#ifdef SC_SECURITY_TOKEN_MONITOR_DRIVER_CAN_BE_RELOADED_AFTER_BEING_DESTROYED
William Jon McCann e8d4c0e
+    if (monitor->priv->module != NULL) {
William Jon McCann e8d4c0e
+	    SECMOD_DestroyModule (monitor->priv->module);
William Jon McCann e8d4c0e
+	    monitor->priv->module = NULL;
William Jon McCann e8d4c0e
+    }
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    if (monitor->priv->nss_is_loaded) {
William Jon McCann e8d4c0e
+	    NSS_Shutdown ();
William Jon McCann e8d4c0e
+	    monitor->priv->nss_is_loaded = FALSE;
William Jon McCann e8d4c0e
+    }
William Jon McCann e8d4c0e
+#endif
William Jon McCann e8d4c0e
+    sc_debug ("security token monitor stopped");
William Jon McCann e8d4c0e
+    
William Jon McCann e8d4c0e
+    return FALSE;
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+static void
William Jon McCann e8d4c0e
+sc_security_token_monitor_queue_stop (ScSecurityTokenMonitor *monitor)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    monitor->priv->state = SC_SECURITY_TOKEN_MONITOR_STATE_STOPPING;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    g_idle_add ((GSourceFunc) sc_security_token_monitor_stop_now, monitor);
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+void 
William Jon McCann e8d4c0e
+sc_security_token_monitor_stop (ScSecurityTokenMonitor *monitor)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+    if (monitor->priv->state == SC_SECURITY_TOKEN_MONITOR_STATE_STOPPED)
William Jon McCann e8d4c0e
+	    return;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    if (monitor->priv->is_unstoppable) {
William Jon McCann e8d4c0e
+	    sc_security_token_monitor_queue_stop (monitor);
William Jon McCann e8d4c0e
+	    return;
William Jon McCann e8d4c0e
+    } 
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    sc_security_token_monitor_stop_now (monitor);
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+static void
William Jon McCann e8d4c0e
+sc_security_token_monitor_check_for_login_token (CK_SLOT_ID       slot_id,
William Jon McCann e8d4c0e
+						 ScSecurityToken *token,
William Jon McCann e8d4c0e
+						 gboolean        *is_inserted)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+    g_assert (is_inserted != NULL);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    if (sc_security_token_is_login_token (token))
William Jon McCann e8d4c0e
+	    *is_inserted = TRUE;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+gboolean 
William Jon McCann e8d4c0e
+sc_security_token_monitor_login_token_is_inserted (ScSecurityTokenMonitor *monitor) 
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+    gboolean is_inserted;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    is_inserted = FALSE;
William Jon McCann e8d4c0e
+    g_hash_table_foreach (monitor->priv->security_tokens, 
William Jon McCann e8d4c0e
+			  (GHFunc)
William Jon McCann e8d4c0e
+			  sc_security_token_monitor_check_for_login_token,
William Jon McCann e8d4c0e
+			  &is_inserted);
William Jon McCann e8d4c0e
+    return is_inserted;
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+static gint
William Jon McCann e8d4c0e
+sc_get_max_open_fds (void)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+  struct rlimit open_fd_limit;
William Jon McCann e8d4c0e
+  const gint fallback_limit = SC_MAX_OPEN_FILE_DESCRIPTORS;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+  if (getrlimit (RLIMIT_NOFILE, &open_fd_limit) < 0) {
William Jon McCann e8d4c0e
+	  sc_debug ("could not get file descriptor limit: %s",
William Jon McCann e8d4c0e
+		    g_strerror (errno));
William Jon McCann e8d4c0e
+	  sc_debug ("returning fallback file descriptor limit of %d",
William Jon McCann e8d4c0e
+		    fallback_limit);
William Jon McCann e8d4c0e
+	  return fallback_limit;
William Jon McCann e8d4c0e
+  }
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+  if (open_fd_limit.rlim_cur == RLIM_INFINITY) {
William Jon McCann e8d4c0e
+	  sc_debug ("currently no file descriptor limit, returning fallback limit of %d",
William Jon McCann e8d4c0e
+		    fallback_limit);
William Jon McCann e8d4c0e
+	  return fallback_limit;
William Jon McCann e8d4c0e
+  }
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+  return (gint) open_fd_limit.rlim_cur;
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+static void
William Jon McCann e8d4c0e
+sc_close_all_fds (int *fds_to_keep_open)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+    int max_open_fds, fd;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    sc_debug ("closing all file descriptors");
William Jon McCann e8d4c0e
+    max_open_fds = sc_get_max_open_fds ();
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    for (fd = 0; fd < max_open_fds; fd++) {
William Jon McCann e8d4c0e
+	    int i;
William Jon McCann e8d4c0e
+	    gboolean should_close_fd;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	    should_close_fd = TRUE;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	    if (fds_to_keep_open != NULL) {
William Jon McCann e8d4c0e
+		    for (i = 0; fds_to_keep_open[i] >= 0; i++) {
William Jon McCann e8d4c0e
+			    if (fd == fds_to_keep_open[i]) {
William Jon McCann e8d4c0e
+				    should_close_fd = FALSE;
William Jon McCann e8d4c0e
+				    break;
William Jon McCann e8d4c0e
+			    }
William Jon McCann e8d4c0e
+		    }
William Jon McCann e8d4c0e
+	    } 
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	    if (should_close_fd) {
William Jon McCann e8d4c0e
+		    sc_debug ("closing file descriptor '%d'", fd);
William Jon McCann e8d4c0e
+		    close (fd);
William Jon McCann e8d4c0e
+	    }
William Jon McCann e8d4c0e
+    }
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+static void
William Jon McCann e8d4c0e
+sc_close_open_fds (int *fds_to_keep_open)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+    /* using DIR instead of GDir because we need access to dirfd so
William Jon McCann e8d4c0e
+     * that we can iterate through the fds and close them in one sweep.
William Jon McCann e8d4c0e
+     * (if we just closed all of them then we would close the one we're using
William Jon McCann e8d4c0e
+     * for reading the directory!)
William Jon McCann e8d4c0e
+     */
William Jon McCann e8d4c0e
+    DIR *dir;
William Jon McCann e8d4c0e
+    struct dirent *entry;
William Jon McCann e8d4c0e
+    gint fd, opendir_fd;
William Jon McCann e8d4c0e
+    gboolean should_use_fallback;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    should_use_fallback = FALSE;
William Jon McCann e8d4c0e
+    opendir_fd = -1;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    dir = opendir (SC_OPEN_FILE_DESCRIPTORS_DIR);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    if (dir != NULL)
William Jon McCann e8d4c0e
+	    opendir_fd = dirfd (dir);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    if ((dir == NULL) || (opendir_fd < 0)) {
William Jon McCann e8d4c0e
+	    sc_debug ("could not open "SC_OPEN_FILE_DESCRIPTORS_DIR": %s", g_strerror (errno));
William Jon McCann e8d4c0e
+	    should_use_fallback = TRUE;
William Jon McCann e8d4c0e
+    } else {
William Jon McCann e8d4c0e
+	    sc_debug ("reading files in '"SC_OPEN_FILE_DESCRIPTORS_DIR"'");
William Jon McCann e8d4c0e
+	    while ((entry = readdir (dir)) != NULL) {
William Jon McCann e8d4c0e
+		    gint i;
William Jon McCann e8d4c0e
+		    glong filename_as_number;
William Jon McCann e8d4c0e
+		    gchar *byte_after_number;
William Jon McCann e8d4c0e
+		    gboolean should_close_fd;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+		    errno = 0;
William Jon McCann e8d4c0e
+		    if (entry->d_name[0] == '.')
William Jon McCann e8d4c0e
+			    continue;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+		    sc_debug ("scanning filename '%s' for file descriptor number",
William Jon McCann e8d4c0e
+			       entry->d_name);
William Jon McCann e8d4c0e
+		    fd = -1;
William Jon McCann e8d4c0e
+		    filename_as_number = strtol (entry->d_name, &byte_after_number, 10);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+		    g_assert (byte_after_number != NULL);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+		    if ((*byte_after_number != '\0') ||
William Jon McCann e8d4c0e
+			(filename_as_number < 0) ||
William Jon McCann e8d4c0e
+			(filename_as_number >= G_MAXINT)) {
William Jon McCann e8d4c0e
+			    sc_debug ("filename '%s' does not appear to represent a "
William Jon McCann e8d4c0e
+				       "file descriptor: %s",
William Jon McCann e8d4c0e
+				       entry->d_name, strerror (errno));
William Jon McCann e8d4c0e
+			    should_use_fallback = TRUE;
William Jon McCann e8d4c0e
+		    } else {
William Jon McCann e8d4c0e
+			    fd = (gint) filename_as_number;
William Jon McCann e8d4c0e
+			    sc_debug ("filename '%s' represents file descriptor '%d'",
William Jon McCann e8d4c0e
+				       entry->d_name, fd);
William Jon McCann e8d4c0e
+			    should_use_fallback = FALSE;
William Jon McCann e8d4c0e
+		    }
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+		    if (fd == opendir_fd) {
William Jon McCann e8d4c0e
+			    should_close_fd = FALSE;
William Jon McCann e8d4c0e
+		    } else {
William Jon McCann e8d4c0e
+			    should_close_fd = TRUE;
William Jon McCann e8d4c0e
+			    if (fds_to_keep_open != NULL)
William Jon McCann e8d4c0e
+				    for (i = 0; fds_to_keep_open[i] >= 0; i++) {
William Jon McCann e8d4c0e
+					    if (fd == fds_to_keep_open[i]) {
William Jon McCann e8d4c0e
+						    should_close_fd = FALSE;
William Jon McCann e8d4c0e
+						    break;
William Jon McCann e8d4c0e
+					    }
William Jon McCann e8d4c0e
+				    }
William Jon McCann e8d4c0e
+		    }
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+		    if (should_close_fd) {
William Jon McCann e8d4c0e
+			    sc_debug ("closing file descriptor '%d'", fd);
William Jon McCann e8d4c0e
+			    close (fd);
William Jon McCann e8d4c0e
+		    } else {
William Jon McCann e8d4c0e
+			    sc_debug ("will not close file descriptor '%d' because it "
William Jon McCann e8d4c0e
+				      "is still needed", fd);
William Jon McCann e8d4c0e
+		    }
William Jon McCann e8d4c0e
+	    }
William Jon McCann e8d4c0e
+	    
William Jon McCann e8d4c0e
+	    if (entry != NULL)
William Jon McCann e8d4c0e
+		    should_use_fallback = TRUE;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	    sc_debug ("closing directory '"SC_OPEN_FILE_DESCRIPTORS_DIR"'");
William Jon McCann e8d4c0e
+	    closedir (dir);
William Jon McCann e8d4c0e
+    }
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    /* if /proc isn't mounted or something else is screwy,
William Jon McCann e8d4c0e
+     * fall back to closing everything
William Jon McCann e8d4c0e
+     */
William Jon McCann e8d4c0e
+    if (should_use_fallback)
William Jon McCann e8d4c0e
+	    sc_close_all_fds (fds_to_keep_open);
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+static void
William Jon McCann e8d4c0e
+sc_close_fds (gint *fds, 
William Jon McCann e8d4c0e
+	      gint  num_fds)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+    gint i;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    for (i = 0; i < num_fds; i++)
William Jon McCann e8d4c0e
+	    close (fds[i]);
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+static ScSecurityTokenMonitorWorker *
William Jon McCann e8d4c0e
+sc_security_token_monitor_worker_new (gint write_fd)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+    ScSecurityTokenMonitorWorker *worker;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    worker = g_slice_new0 (ScSecurityTokenMonitorWorker);
William Jon McCann e8d4c0e
+    worker->write_fd = write_fd;
William Jon McCann e8d4c0e
+    worker->module = NULL;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    worker->security_tokens =
William Jon McCann e8d4c0e
+	    g_hash_table_new_full ((GHashFunc) sc_slot_id_hash, 
William Jon McCann e8d4c0e
+				   (GEqualFunc) sc_slot_id_equal, 
William Jon McCann e8d4c0e
+				   (GDestroyNotify) g_free, 
William Jon McCann e8d4c0e
+				   (GDestroyNotify) g_object_unref);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    return worker;
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+static void 
William Jon McCann e8d4c0e
+sc_security_token_monitor_worker_free (ScSecurityTokenMonitorWorker *worker)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+    if (worker->security_tokens != NULL) {
William Jon McCann e8d4c0e
+	    g_hash_table_destroy (worker->security_tokens);
William Jon McCann e8d4c0e
+	    worker->security_tokens = NULL;
William Jon McCann e8d4c0e
+    }
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    g_slice_free (ScSecurityTokenMonitorWorker, worker);
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+/* This function checks to see if the helper's connection to the
William Jon McCann e8d4c0e
+ * parent process has been closed.  If it has, we assume the
William Jon McCann e8d4c0e
+ * parent has died (or is otherwise done with the connection)
William Jon McCann e8d4c0e
+ * and so we die, too.  We do this from a signal handler (yuck!)
William Jon McCann e8d4c0e
+ * because there isn't a nice way to cancel the 
William Jon McCann e8d4c0e
+ * SECMOD_WaitForAnyTokenEvent call, which just sits and blocks
William Jon McCann e8d4c0e
+ * indefinitely.  There is a SECMOD_CancelWait wait function
William Jon McCann e8d4c0e
+ * that we could call if we would have gone multithreaded like
William Jon McCann e8d4c0e
+ * NSS really wants us to do, but that call isn't signal handler
William Jon McCann e8d4c0e
+ * safe, so we just _exit() instead (eww).
William Jon McCann e8d4c0e
+ */
William Jon McCann e8d4c0e
+static void
William Jon McCann e8d4c0e
+worker_io_signal_handler (int        signal_number, 
William Jon McCann e8d4c0e
+			  siginfo_t *signal_info,
William Jon McCann e8d4c0e
+			  void      *data)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+    int number_of_events;
William Jon McCann e8d4c0e
+    int old_errno;
William Jon McCann e8d4c0e
+    struct pollfd poll_fds[1] = { { 0 } };
William Jon McCann e8d4c0e
+    int parent_fd;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    old_errno = errno;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    /* pipe fd set up to talk to the parent */
William Jon McCann e8d4c0e
+    parent_fd = signal_info->si_fd;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    /* We only care about disconnection events
William Jon McCann e8d4c0e
+     * (which get unmasked implicitly), so we just
William Jon McCann e8d4c0e
+     * pass 0 for the event mask
William Jon McCann e8d4c0e
+     */
William Jon McCann e8d4c0e
+    poll_fds[0].events = 0;
William Jon McCann e8d4c0e
+    poll_fds[0].fd = parent_fd;
William Jon McCann e8d4c0e
+    
William Jon McCann e8d4c0e
+    do {
William Jon McCann e8d4c0e
+	    number_of_events = poll (poll_fds, G_N_ELEMENTS (poll_fds), 0);
William Jon McCann e8d4c0e
+    } while ((number_of_events < 0) && (errno == EINTR));
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    g_assert (number_of_events <= G_N_ELEMENTS (poll_fds));
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    if (number_of_events < 0)
William Jon McCann e8d4c0e
+	    _exit (errno);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    /* pipe disconnected; parent died
William Jon McCann e8d4c0e
+     */
William Jon McCann e8d4c0e
+    if (number_of_events > 0) {
William Jon McCann e8d4c0e
+	    g_assert (!(poll_fds[0].revents & POLLNVAL));
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	    if ((poll_fds[0].revents & POLLHUP) ||
William Jon McCann e8d4c0e
+		(poll_fds[0].revents & POLLERR)) {
William Jon McCann e8d4c0e
+		    _exit (poll_fds[0].revents);
William Jon McCann e8d4c0e
+	    }
William Jon McCann e8d4c0e
+    } 
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    errno = old_errno;
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+static void
William Jon McCann e8d4c0e
+sc_security_token_monitor_worker_die_with_parent (ScSecurityTokenMonitorWorker *worker)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+    struct sigaction action = { { 0 } };
William Jon McCann e8d4c0e
+    gint flags;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    /* dirty hack to clean up worker if parent goes away
William Jon McCann e8d4c0e
+     */
William Jon McCann e8d4c0e
+    sigemptyset (&action.sa_mask);
William Jon McCann e8d4c0e
+    action.sa_sigaction = worker_io_signal_handler;
William Jon McCann e8d4c0e
+    action.sa_flags = SA_SIGINFO;
William Jon McCann e8d4c0e
+    sigaction (SIGIO, &action, NULL);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    flags = fcntl (worker->write_fd, F_GETFL, 0);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    fcntl (worker->write_fd, F_SETOWN, getpid ());
William Jon McCann e8d4c0e
+    fcntl (worker->write_fd, F_SETFL, flags | O_ASYNC);
William Jon McCann e8d4c0e
+    fcntl (worker->write_fd, F_SETSIG, SIGIO);
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+static gboolean
William Jon McCann e8d4c0e
+sc_read_bytes (gint fd, gpointer bytes, gsize num_bytes)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+    size_t bytes_left;
William Jon McCann e8d4c0e
+    size_t total_bytes_read;
William Jon McCann e8d4c0e
+    ssize_t bytes_read;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    bytes_left = (size_t) num_bytes;
William Jon McCann e8d4c0e
+    total_bytes_read = 0;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    do {
William Jon McCann e8d4c0e
+	    bytes_read = read (fd, bytes + total_bytes_read, bytes_left);
William Jon McCann e8d4c0e
+	    g_assert (bytes_read <= (ssize_t) bytes_left);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	    if (bytes_read <= 0) {
William Jon McCann e8d4c0e
+		    if ((bytes_read < 0) && (errno == EINTR || errno == EAGAIN))
William Jon McCann e8d4c0e
+			    continue;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+		    bytes_left = 0;
William Jon McCann e8d4c0e
+	    } else {
William Jon McCann e8d4c0e
+		    bytes_left -= bytes_read;
William Jon McCann e8d4c0e
+		    total_bytes_read += bytes_read;
William Jon McCann e8d4c0e
+	    }
William Jon McCann e8d4c0e
+    } while (bytes_left > 0);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    if (total_bytes_read <  (size_t) num_bytes)
William Jon McCann e8d4c0e
+	    return FALSE;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    return TRUE;
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+static gboolean
William Jon McCann e8d4c0e
+sc_write_bytes (gint fd, gconstpointer bytes, gsize num_bytes)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+    size_t bytes_left;
William Jon McCann e8d4c0e
+    size_t total_bytes_written;
William Jon McCann e8d4c0e
+    ssize_t bytes_written;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    bytes_left = (size_t) num_bytes;
William Jon McCann e8d4c0e
+    total_bytes_written = 0;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    do {
William Jon McCann e8d4c0e
+	    bytes_written = write (fd, bytes + total_bytes_written, bytes_left);
William Jon McCann e8d4c0e
+	    g_assert (bytes_written <= (ssize_t) bytes_left);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	    if (bytes_written <= 0) {
William Jon McCann e8d4c0e
+		    if ((bytes_written < 0) && (errno == EINTR || errno == EAGAIN))
William Jon McCann e8d4c0e
+			    continue;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+		    bytes_left = 0;
William Jon McCann e8d4c0e
+	    } else {
William Jon McCann e8d4c0e
+		    bytes_left -= bytes_written;
William Jon McCann e8d4c0e
+		    total_bytes_written += bytes_written;
William Jon McCann e8d4c0e
+	    }
William Jon McCann e8d4c0e
+    } while (bytes_left > 0);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    if (total_bytes_written <  (size_t) num_bytes)
William Jon McCann e8d4c0e
+	    return FALSE;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    return TRUE;
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+static ScSecurityToken *
William Jon McCann e8d4c0e
+sc_read_security_token (gint fd, SECMODModule *module)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+    ScSecurityToken *token;
William Jon McCann e8d4c0e
+    gchar *token_name;
William Jon McCann e8d4c0e
+    gsize token_name_size;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    token_name_size = 0;
William Jon McCann e8d4c0e
+    if (!sc_read_bytes (fd, &token_name_size, sizeof (token_name_size)))
William Jon McCann e8d4c0e
+	return NULL;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    token_name = g_slice_alloc0 (token_name_size);
William Jon McCann e8d4c0e
+    if (!sc_read_bytes (fd, token_name, token_name_size)) {
William Jon McCann e8d4c0e
+	    g_slice_free1 (token_name_size, token_name);
William Jon McCann e8d4c0e
+	    return NULL;
William Jon McCann e8d4c0e
+    }
William Jon McCann e8d4c0e
+    token = _sc_security_token_new_from_name (module, token_name);
William Jon McCann e8d4c0e
+    g_slice_free1 (token_name_size, token_name);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    return token;
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+static gboolean
William Jon McCann e8d4c0e
+sc_write_security_token (gint             fd, 
William Jon McCann e8d4c0e
+			 ScSecurityToken *token)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+    gsize token_name_size;
William Jon McCann e8d4c0e
+    gchar *token_name;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    token_name = sc_security_token_get_name (token);
William Jon McCann e8d4c0e
+    token_name_size = strlen (token_name) + 1;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    if (!sc_write_bytes (fd, &token_name_size, sizeof (token_name_size))) {
William Jon McCann e8d4c0e
+	g_free (token_name);
William Jon McCann e8d4c0e
+	return FALSE;
William Jon McCann e8d4c0e
+    }
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    if (!sc_write_bytes (fd, token_name, token_name_size)) {
William Jon McCann e8d4c0e
+	g_free (token_name);
William Jon McCann e8d4c0e
+	return FALSE;
William Jon McCann e8d4c0e
+    }
William Jon McCann e8d4c0e
+    g_free (token_name);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    return TRUE;
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+static gboolean
William Jon McCann e8d4c0e
+sc_security_token_monitor_worker_emit_security_token_removed (ScSecurityTokenMonitorWorker  *worker, 
William Jon McCann e8d4c0e
+							      ScSecurityToken               *token, 
William Jon McCann e8d4c0e
+							      GError                       **error)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+    sc_debug ("token '%s' removed!", sc_security_token_get_name (token));
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    if (!sc_write_bytes (worker->write_fd, "R", 1)) 
William Jon McCann e8d4c0e
+	    goto error_out;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    if (!sc_write_security_token (worker->write_fd, token))
William Jon McCann e8d4c0e
+	    goto error_out;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    return TRUE;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+error_out:
William Jon McCann e8d4c0e
+    g_set_error (error, SC_SECURITY_TOKEN_MONITOR_ERROR,
William Jon McCann e8d4c0e
+		 SC_SECURITY_TOKEN_MONITOR_ERROR_REPORTING_EVENTS, 
William Jon McCann e8d4c0e
+		 "%s", g_strerror (errno));
William Jon McCann e8d4c0e
+    return FALSE;
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+static gboolean
William Jon McCann e8d4c0e
+sc_security_token_monitor_worker_emit_security_token_inserted (ScSecurityTokenMonitorWorker  *worker, 
William Jon McCann e8d4c0e
+							       ScSecurityToken               *token,
William Jon McCann e8d4c0e
+							       GError                       **error)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+    GError *write_error;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    write_error = NULL;
William Jon McCann e8d4c0e
+    sc_debug ("token '%s' inserted!", sc_security_token_get_name (token));
William Jon McCann e8d4c0e
+    if (!sc_write_bytes (worker->write_fd, "I", 1)) 
William Jon McCann e8d4c0e
+	    goto error_out;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    if (!sc_write_security_token (worker->write_fd, token))
William Jon McCann e8d4c0e
+	    goto error_out;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    return TRUE;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+error_out:
William Jon McCann e8d4c0e
+    g_set_error (error, SC_SECURITY_TOKEN_MONITOR_ERROR,
William Jon McCann e8d4c0e
+		 SC_SECURITY_TOKEN_MONITOR_ERROR_REPORTING_EVENTS, 
William Jon McCann e8d4c0e
+		 "%s", g_strerror (errno));
William Jon McCann e8d4c0e
+    return FALSE;
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+static gboolean
William Jon McCann e8d4c0e
+sc_security_token_monitor_worker_watch_for_and_process_event (ScSecurityTokenMonitorWorker *worker,
William Jon McCann e8d4c0e
+							      GError                      **error)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+    PK11SlotInfo *slot;
William Jon McCann e8d4c0e
+    CK_SLOT_ID slot_id, *key;
William Jon McCann e8d4c0e
+    gint slot_series, token_slot_series;
William Jon McCann e8d4c0e
+    ScSecurityToken *token;
William Jon McCann e8d4c0e
+    GError *processing_error;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    sc_debug ("waiting for token event");
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    /* FIXME: we return FALSE quite a bit in this function without cleaning up
William Jon McCann e8d4c0e
+     * resources.  By returning FALSE we're going to ultimately exit anyway, but
William Jon McCann e8d4c0e
+     * we should still be tidier about things.
William Jon McCann e8d4c0e
+     */
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    slot = SECMOD_WaitForAnyTokenEvent (worker->module, 0, PR_SecondsToInterval (1)); 
William Jon McCann e8d4c0e
+    processing_error = NULL;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    if (slot == NULL) {
William Jon McCann e8d4c0e
+	    int error_code;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	    error_code = PORT_GetError ();
William Jon McCann e8d4c0e
+	    if ((error_code == 0) || (error_code == SEC_ERROR_NO_EVENT)) {
William Jon McCann e8d4c0e
+		    sc_debug ("spurrious event occurred");
William Jon McCann e8d4c0e
+		    return TRUE;
William Jon McCann e8d4c0e
+	    }
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	    /* FIXME: is there a function to convert from a PORT error
William Jon McCann e8d4c0e
+	     * code to a translated string?
William Jon McCann e8d4c0e
+	     */
William Jon McCann e8d4c0e
+	    g_set_error (error, SC_SECURITY_TOKEN_MONITOR_ERROR,
William Jon McCann e8d4c0e
+			 SC_SECURITY_TOKEN_MONITOR_ERROR_WITH_NSS,
William Jon McCann e8d4c0e
+			 _("encountered unexpected error while "
William Jon McCann e8d4c0e
+			   "waiting for security token events"));
William Jon McCann e8d4c0e
+	    return FALSE;
William Jon McCann e8d4c0e
+    }
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    /* the slot id and series together uniquely identify a token.
William Jon McCann e8d4c0e
+     * You can never have two tokens with the same slot id at the
William Jon McCann e8d4c0e
+     * same time, however (I think), so we can key off of it.
William Jon McCann e8d4c0e
+     */
William Jon McCann e8d4c0e
+    slot_id = PK11_GetSlotID (slot);
William Jon McCann e8d4c0e
+    slot_series = PK11_GetSlotSeries (slot);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    /* First check to see if there is a token that we're currently
William Jon McCann e8d4c0e
+     * tracking in the slot.
William Jon McCann e8d4c0e
+     */
William Jon McCann e8d4c0e
+    key = g_new (CK_SLOT_ID, 1);
William Jon McCann e8d4c0e
+    *key = slot_id;
William Jon McCann e8d4c0e
+    token = g_hash_table_lookup (worker->security_tokens, key);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    if (token != NULL)
William Jon McCann e8d4c0e
+	    token_slot_series = sc_security_token_get_slot_series (token);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    if (PK11_IsPresent (slot)) {
William Jon McCann e8d4c0e
+	    /* Now, check to see if their is a new token in the slot.
William Jon McCann e8d4c0e
+	     * If there was a different token in the slot now than
William Jon McCann e8d4c0e
+	     * there was before, then we need to emit a removed signal
William Jon McCann e8d4c0e
+	     * for the old token (we don't want unpaired insertion events).
William Jon McCann e8d4c0e
+	     */
William Jon McCann e8d4c0e
+	    if ((token != NULL) && 
William Jon McCann e8d4c0e
+		token_slot_series != slot_series) {
William Jon McCann e8d4c0e
+		    if (!sc_security_token_monitor_worker_emit_security_token_removed (worker, token, &processing_error)) {
William Jon McCann e8d4c0e
+			    g_propagate_error (error, processing_error);
William Jon McCann e8d4c0e
+			    return FALSE;
William Jon McCann e8d4c0e
+		    }
William Jon McCann e8d4c0e
+	    }
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	    token = _sc_security_token_new (worker->module, 
William Jon McCann e8d4c0e
+					    slot_id, slot_series);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	    g_hash_table_replace (worker->security_tokens,
William Jon McCann e8d4c0e
+				  key, token);
William Jon McCann e8d4c0e
+	    key = NULL;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	    if (!sc_security_token_monitor_worker_emit_security_token_inserted (worker, token, &processing_error)) {
William Jon McCann e8d4c0e
+		    g_propagate_error (error, processing_error);
William Jon McCann e8d4c0e
+		    return FALSE;
William Jon McCann e8d4c0e
+	    }
William Jon McCann e8d4c0e
+    } else {
William Jon McCann e8d4c0e
+	    /* if we aren't tracking the token, just discard the event.
William Jon McCann e8d4c0e
+	     * We don't want unpaired remove events.  Note on startup
William Jon McCann e8d4c0e
+	     * NSS will generate an "insertion" event if a token is
William Jon McCann e8d4c0e
+	     * already inserted in the slot.
William Jon McCann e8d4c0e
+	     */
William Jon McCann e8d4c0e
+	    if ((token != NULL)) {
William Jon McCann e8d4c0e
+		    /* FIXME: i'm not sure about this code.  Maybe we
William Jon McCann e8d4c0e
+		     * shouldn't do this at all, or maybe we should do it
William Jon McCann e8d4c0e
+		     * n times (where n = slot_series - token_slot_series + 1)
William Jon McCann e8d4c0e
+		     * 
William Jon McCann e8d4c0e
+		     * Right now, i'm just doing it once.  
William Jon McCann e8d4c0e
+		     */
William Jon McCann e8d4c0e
+		    if ((slot_series - token_slot_series) > 1) {
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+			    if (!sc_security_token_monitor_worker_emit_security_token_removed (worker, token, &processing_error)) {
William Jon McCann e8d4c0e
+				    g_propagate_error (error, processing_error);
William Jon McCann e8d4c0e
+				    return FALSE;
William Jon McCann e8d4c0e
+			    }
William Jon McCann e8d4c0e
+			    g_hash_table_remove (worker->security_tokens, key);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+			    token = _sc_security_token_new (worker->module, 
William Jon McCann e8d4c0e
+							    slot_id, slot_series);
William Jon McCann e8d4c0e
+			    g_hash_table_replace (worker->security_tokens,
William Jon McCann e8d4c0e
+						  key, token);
William Jon McCann e8d4c0e
+			    key = NULL;
William Jon McCann e8d4c0e
+			    if (!sc_security_token_monitor_worker_emit_security_token_inserted (worker, token, &processing_error)) {
William Jon McCann e8d4c0e
+				    g_propagate_error (error, processing_error);
William Jon McCann e8d4c0e
+				    return FALSE;
William Jon McCann e8d4c0e
+			    }
William Jon McCann e8d4c0e
+		    }
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+		    if (!sc_security_token_monitor_worker_emit_security_token_removed (worker, token, &processing_error)) {
William Jon McCann e8d4c0e
+			    g_propagate_error (error, processing_error);
William Jon McCann e8d4c0e
+			    return FALSE;
William Jon McCann e8d4c0e
+		    }
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+		    g_hash_table_remove (worker->security_tokens, key);
William Jon McCann e8d4c0e
+		    token = NULL;
William Jon McCann e8d4c0e
+	    } else {
William Jon McCann e8d4c0e
+		    sc_debug ("got spurious remove event");
William Jon McCann e8d4c0e
+	    }
William Jon McCann e8d4c0e
+    }
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    g_free (key);
William Jon McCann e8d4c0e
+    PK11_FreeSlot (slot);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    return TRUE;
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+static gboolean
William Jon McCann e8d4c0e
+sc_security_token_monitor_create_worker (ScSecurityTokenMonitor *monitor,
William Jon McCann e8d4c0e
+					 gint *worker_fd, GPid *worker_pid)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+    GPid child_pid;
William Jon McCann e8d4c0e
+    gint write_fd, read_fd;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    write_fd = -1;
William Jon McCann e8d4c0e
+    read_fd = -1;
William Jon McCann e8d4c0e
+    if (!sc_open_pipe (&write_fd, &read_fd))
William Jon McCann e8d4c0e
+	    return FALSE;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    child_pid = sc_fork_and_disown ();
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    if (child_pid < 0)
William Jon McCann e8d4c0e
+	    return FALSE;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    if (child_pid == 0) {
William Jon McCann e8d4c0e
+	    GError *error;
William Jon McCann e8d4c0e
+	    ScSecurityTokenMonitorWorker *worker;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+/* FIXME: Gotta figure out why this isn't working
William Jon McCann e8d4c0e
+*/
William Jon McCann e8d4c0e
+#ifdef SC_SECURITY_TOKEN_MONITOR_DRIVER_CAN_BE_RELOADED_AFTER_BEING_DESTROYED
William Jon McCann e8d4c0e
+	    gint fds_to_keep_open[] = { -1, STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO, -1 };
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	    SECMOD_DestroyModule (monitor->priv->module);
William Jon McCann e8d4c0e
+	    monitor->priv->module = NULL;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	    NSS_Shutdown ();
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	    fds_to_keep_open[0] = write_fd;
William Jon McCann e8d4c0e
+	    sc_close_open_fds (fds_to_keep_open);
William Jon McCann e8d4c0e
+	    read_fd = -1;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	    if (!sc_load_nss (&error)) {
William Jon McCann e8d4c0e
+		    sc_debug ("could not load nss - %s", error->message);
William Jon McCann e8d4c0e
+		    g_error_free (error);
William Jon McCann e8d4c0e
+		    _exit (1);
William Jon McCann e8d4c0e
+	    }
William Jon McCann e8d4c0e
+#else
William Jon McCann e8d4c0e
+	    g_array_append_val (monitor->priv->fds_to_close_on_fork, read_fd);
William Jon McCann e8d4c0e
+	    /* Junky workaround to keep from leaking fds
William Jon McCann e8d4c0e
+	     */
William Jon McCann e8d4c0e
+	    sc_close_fds ((gint *) monitor->priv->fds_to_close_on_fork->data,
William Jon McCann e8d4c0e
+			  monitor->priv->fds_to_close_on_fork->len);
William Jon McCann e8d4c0e
+#endif
William Jon McCann e8d4c0e
+	    error = NULL;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	    worker = sc_security_token_monitor_worker_new (write_fd);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	    sc_security_token_monitor_worker_die_with_parent (worker);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	    worker->module = sc_load_driver (monitor->priv->module_path, &error);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	    if (worker->module == NULL) {
William Jon McCann e8d4c0e
+		    sc_debug ("could not load nss driver - %s", error->message);
William Jon McCann e8d4c0e
+		    g_error_free (error);
William Jon McCann e8d4c0e
+		    _exit (2);
William Jon McCann e8d4c0e
+	    }
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	    while (sc_security_token_monitor_worker_watch_for_and_process_event (worker, &error));
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	    sc_debug ("could not process token event - %s", error->message);
William Jon McCann e8d4c0e
+	    sc_security_token_monitor_worker_free (worker);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+	    _exit (0);
William Jon McCann e8d4c0e
+    }
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    close (write_fd);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+#ifndef SC_SECURITY_TOKEN_MONITOR_DRIVER_CAN_BE_RELOADED_AFTER_BEING_DESTROYED
William Jon McCann e8d4c0e
+    g_array_append_val (monitor->priv->fds_to_close_on_fork, read_fd);
William Jon McCann e8d4c0e
+#endif
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    if (worker_pid)
William Jon McCann e8d4c0e
+	    *worker_pid = child_pid;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    if (worker_fd)
William Jon McCann e8d4c0e
+	    *worker_fd = read_fd;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    return TRUE;
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+#ifdef SC_SECURITY_TOKEN_MONITOR_ENABLE_TEST
William Jon McCann e8d4c0e
+#include <glib.h>
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+static GMainLoop *event_loop;
William Jon McCann e8d4c0e
+static gboolean should_exit_on_next_remove = FALSE;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+static gboolean 
William Jon McCann e8d4c0e
+on_timeout (ScSecurityTokenMonitor *monitor)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+    GError *error;
William Jon McCann e8d4c0e
+    g_print ("Re-enabling monitor.\n");
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    if (!sc_security_token_monitor_start (monitor, &error)) {
William Jon McCann e8d4c0e
+	    g_warning ("could not start security token monitor - %s",
William Jon McCann e8d4c0e
+		       error->message);
William Jon McCann e8d4c0e
+	    g_error_free (error);
William Jon McCann e8d4c0e
+	    return 1;
William Jon McCann e8d4c0e
+    }
William Jon McCann e8d4c0e
+    g_print ("Please re-insert security token\n");
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    should_exit_on_next_remove = TRUE;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    return FALSE;
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+static void
William Jon McCann e8d4c0e
+on_device_inserted (ScSecurityTokenMonitor * monitor,
William Jon McCann e8d4c0e
+		    ScSecurityToken *token)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+    g_print ("security token inserted!\n");
William Jon McCann e8d4c0e
+    g_print ("Please remove it.\n");
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+static void
William Jon McCann e8d4c0e
+on_device_removed (ScSecurityTokenMonitor * monitor,
William Jon McCann e8d4c0e
+		   ScSecurityToken *token)
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+    g_print ("security token removed!\n");
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    if (should_exit_on_next_remove)
William Jon McCann e8d4c0e
+	    g_main_loop_quit (event_loop);
William Jon McCann e8d4c0e
+    else {
William Jon McCann e8d4c0e
+	    g_print ("disabling monitor for 2 seconds\n");
William Jon McCann e8d4c0e
+	    sc_security_token_monitor_stop (monitor);
William Jon McCann e8d4c0e
+	    g_timeout_add (2000, (GSourceFunc) on_timeout, monitor);
William Jon McCann e8d4c0e
+    }
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+int 
William Jon McCann e8d4c0e
+main (int   argc, 
William Jon McCann e8d4c0e
+      char *argv[])
William Jon McCann e8d4c0e
+{
William Jon McCann e8d4c0e
+    ScSecurityTokenMonitor *monitor;
William Jon McCann e8d4c0e
+    GError *error;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    g_log_set_always_fatal (G_LOG_LEVEL_ERROR
William Jon McCann e8d4c0e
+			    | G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    g_type_init ();
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    g_message ("creating instance of 'security token monitor' object...");
William Jon McCann e8d4c0e
+    monitor = sc_security_token_monitor_new (NULL);
William Jon McCann e8d4c0e
+    g_message ("'security token monitor' object created successfully");
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    g_signal_connect (monitor, "security-token-inserted",
William Jon McCann e8d4c0e
+		      G_CALLBACK (on_device_inserted), NULL);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    g_signal_connect (monitor, "security-token-removed",
William Jon McCann e8d4c0e
+		      G_CALLBACK (on_device_removed), NULL);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    g_message ("starting listener...");
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    error = NULL;
William Jon McCann e8d4c0e
+    if (!sc_security_token_monitor_start (monitor, &error)) {
William Jon McCann e8d4c0e
+	    g_warning ("could not start security token monitor - %s",
William Jon McCann e8d4c0e
+		       error->message);
William Jon McCann e8d4c0e
+	    g_error_free (error);
William Jon McCann e8d4c0e
+	    return 1;
William Jon McCann e8d4c0e
+    }
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    event_loop = g_main_loop_new (NULL, FALSE);
William Jon McCann e8d4c0e
+    g_main_loop_run (event_loop);
William Jon McCann e8d4c0e
+    g_main_loop_unref (event_loop);
William Jon McCann e8d4c0e
+    event_loop = NULL;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    g_message ("destroying previously created 'security token monitor' object...");
William Jon McCann e8d4c0e
+    g_object_unref (monitor);
William Jon McCann e8d4c0e
+    monitor = NULL;
William Jon McCann e8d4c0e
+    g_message ("'security token monitor' object destroyed successfully");
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    return 0;
William Jon McCann e8d4c0e
+}
William Jon McCann e8d4c0e
+#endif
William Jon McCann e8d4c0e
diff -up /dev/null gnome-screensaver-2.23.3/src/securitytokenmonitor.h
William Jon McCann e8d4c0e
--- /dev/null	2008-07-27 17:37:58.142005663 -0400
William Jon McCann e8d4c0e
+++ gnome-screensaver-2.23.3/src/securitytokenmonitor.h	2008-07-27 23:20:06.000000000 -0400
William Jon McCann e8d4c0e
@@ -0,0 +1,84 @@
William Jon McCann e8d4c0e
+/* securitytokenmonitor.h - monitor for security token insertion and
William Jon McCann e8d4c0e
+ *                          removal events
William Jon McCann e8d4c0e
+ *
William Jon McCann e8d4c0e
+ * Copyright (C) 2006 Ray Strode
William Jon McCann e8d4c0e
+ *
William Jon McCann e8d4c0e
+ * This program is free software; you can redistribute it and/or modify
William Jon McCann e8d4c0e
+ * it under the terms of the GNU General Public License as published by
William Jon McCann e8d4c0e
+ * the Free Software Foundation; either version 2, or (at your option)
William Jon McCann e8d4c0e
+ * any later version.
William Jon McCann e8d4c0e
+ *
William Jon McCann e8d4c0e
+ * This program is distributed in the hope that it will be useful,
William Jon McCann e8d4c0e
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
William Jon McCann e8d4c0e
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
William Jon McCann e8d4c0e
+ * GNU General Public License for more details.
William Jon McCann e8d4c0e
+ *
William Jon McCann e8d4c0e
+ * You should have received a copy of the GNU General Public License
William Jon McCann e8d4c0e
+ * along with this program; if not, write to the Free Software
William Jon McCann e8d4c0e
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
William Jon McCann e8d4c0e
+ * 02111-1307, USA.  
William Jon McCann e8d4c0e
+ */
William Jon McCann e8d4c0e
+#ifndef SC_SECURITY_TOKEN_MONITOR_H
William Jon McCann e8d4c0e
+#define SC_SECURITY_TOKEN_MONITOR_H
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+#define SC_SECURITY_TOKEN_ENABLE_INTERNAL_API
William Jon McCann e8d4c0e
+#include "securitytoken.h"
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+#include <glib.h>
William Jon McCann e8d4c0e
+#include <glib-object.h>
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+G_BEGIN_DECLS
William Jon McCann e8d4c0e
+#define SC_TYPE_SECURITY_TOKEN_MONITOR            (sc_security_token_monitor_get_type ())
William Jon McCann e8d4c0e
+#define SC_SECURITY_TOKEN_MONITOR(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), SC_TYPE_SECURITY_TOKEN_MONITOR, ScSecurityTokenMonitor))
William Jon McCann e8d4c0e
+#define SC_SECURITY_TOKEN_MONITOR_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), SC_TYPE_SECURITY_TOKEN_MONITOR, ScSecurityTokenMonitorClass))
William Jon McCann e8d4c0e
+#define SC_IS_SECURITY_TOKEN_MONITOR(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SC_TYPE_SECURITY_TOKEN_MONITOR))
William Jon McCann e8d4c0e
+#define SC_IS_SECURITY_TOKEN_MONITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SC_TYPE_SECURITY_TOKEN_MONITOR))
William Jon McCann e8d4c0e
+#define SC_SECURITY_TOKEN_MONITOR_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), SC_TYPE_SECURITY_TOKEN_MONITOR, ScSecurityTokenMonitorClass))
William Jon McCann e8d4c0e
+#define SC_SECURITY_TOKEN_MONITOR_ERROR           (sc_security_token_monitor_error_quark ())
William Jon McCann e8d4c0e
+typedef struct _ScSecurityTokenMonitor ScSecurityTokenMonitor;
William Jon McCann e8d4c0e
+typedef struct _ScSecurityTokenMonitorClass ScSecurityTokenMonitorClass;
William Jon McCann e8d4c0e
+typedef struct _ScSecurityTokenMonitorPrivate ScSecurityTokenMonitorPrivate;
William Jon McCann e8d4c0e
+typedef enum _ScSecurityTokenMonitorError ScSecurityTokenMonitorError;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+struct _ScSecurityTokenMonitor {
William Jon McCann e8d4c0e
+    GObject parent;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    /*< private > */
William Jon McCann e8d4c0e
+    ScSecurityTokenMonitorPrivate *priv;
William Jon McCann e8d4c0e
+};
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+struct _ScSecurityTokenMonitorClass {
William Jon McCann e8d4c0e
+    GObjectClass parent_class;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+    /* Signals */
William Jon McCann e8d4c0e
+    void (*security_token_inserted) (ScSecurityTokenMonitor *monitor,
William Jon McCann e8d4c0e
+				     ScSecurityToken *token);
William Jon McCann e8d4c0e
+    void (*security_token_removed) (ScSecurityTokenMonitor *monitor,
William Jon McCann e8d4c0e
+				    ScSecurityToken *token);
William Jon McCann e8d4c0e
+    void (*error) (ScSecurityTokenMonitor *monitor, 
William Jon McCann e8d4c0e
+		   GError                 *error);
William Jon McCann e8d4c0e
+};
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+enum _ScSecurityTokenMonitorError {
William Jon McCann e8d4c0e
+    SC_SECURITY_TOKEN_MONITOR_ERROR_GENERIC = 0,
William Jon McCann e8d4c0e
+    SC_SECURITY_TOKEN_MONITOR_ERROR_WITH_NSS,
William Jon McCann e8d4c0e
+    SC_SECURITY_TOKEN_MONITOR_ERROR_LOADING_DRIVER,
William Jon McCann e8d4c0e
+    SC_SECURITY_TOKEN_MONITOR_ERROR_WATCHING_FOR_EVENTS,
William Jon McCann e8d4c0e
+    SC_SECURITY_TOKEN_MONITOR_ERROR_REPORTING_EVENTS
William Jon McCann e8d4c0e
+};
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+GType sc_security_token_monitor_get_type (void) G_GNUC_CONST;
William Jon McCann e8d4c0e
+GQuark sc_security_token_monitor_error_quark (void) G_GNUC_CONST;
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+ScSecurityTokenMonitor *sc_security_token_monitor_new (const gchar *module);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+gboolean sc_security_token_monitor_start (ScSecurityTokenMonitor  *monitor, 
William Jon McCann e8d4c0e
+				 	  GError                 **error);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+void sc_security_token_monitor_stop (ScSecurityTokenMonitor *monitor);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+gchar *sc_security_token_monitor_get_module_path (ScSecurityTokenMonitor *monitor);
William Jon McCann e8d4c0e
+gboolean sc_security_token_monitor_login_token_is_inserted (ScSecurityTokenMonitor *monitor);
William Jon McCann e8d4c0e
+
William Jon McCann e8d4c0e
+G_END_DECLS
William Jon McCann e8d4c0e
+#endif				/* SC_SECURITY_TOKEN_MONITOR_H */