diff -ruNp gnome-screensaver-2.19.1.1.orig/src/gnome-screensaver-dialog.c gnome-screensaver-2.19.1.1/src/gnome-screensaver-dialog.c
--- gnome-screensaver-2.19.1.1.orig/src/gnome-screensaver-dialog.c	2007-04-23 15:29:13.000000000 -0400
+++ gnome-screensaver-2.19.1.1/src/gnome-screensaver-dialog.c	2007-07-26 13:45:13.000000000 -0400
@@ -47,6 +47,7 @@ static gboolean enable_logout  = FALSE;
 static gboolean enable_switch  = FALSE;
 static char    *logout_command = NULL;
 static char    *away_message   = NULL;
+static gboolean token          = FALSE;
 
 static GOptionEntry entries [] = {
         { "verbose", 0, 0, G_OPTION_ARG_NONE, &verbose,
@@ -61,6 +62,8 @@ static GOptionEntry entries [] = {
           N_("Show the switch user button"), NULL },
         { "away-message", 0, 0, G_OPTION_ARG_STRING, &away_message,
           N_("Message to show in the dialog"), N_("MESSAGE") },
+        { "token", 0, 0, G_OPTION_ARG_NONE, &token,
+          N_("Authenticate using a smart card token"), NULL },
         { NULL }
 };
 
@@ -288,7 +291,7 @@ do_auth_check (GSLockPlug *plug)
 
         gs_lock_plug_disable_prompt (plug);
         gs_lock_plug_set_busy (plug);
-        res = gs_auth_verify_user (g_get_user_name (), g_getenv ("DISPLAY"), auth_message_handler, plug, &error);
+        res = gs_auth_verify_user (g_get_user_name (), g_getenv ("DISPLAY"), token, auth_message_handler, plug, &error);
 
         gs_debug ("Verify user returned: %s", res ? "TRUE" : "FALSE");
         if (! res) {
diff -ruNp gnome-screensaver-2.19.1.1.orig/src/gs-auth.h gnome-screensaver-2.19.1.1/src/gs-auth.h
--- gnome-screensaver-2.19.1.1.orig/src/gs-auth.h	2007-02-22 23:39:09.000000000 -0500
+++ gnome-screensaver-2.19.1.1/src/gs-auth.h	2007-07-26 13:45:13.000000000 -0400
@@ -56,6 +56,7 @@ gboolean gs_auth_priv_init   (void);
 gboolean gs_auth_init        (void);
 gboolean gs_auth_verify_user (const char       *username,
                               const char       *display,
+                              gboolean          token,
                               GSAuthMessageFunc func,
                               gpointer          data,
                               GError          **error);
diff -ruNp gnome-screensaver-2.19.1.1.orig/src/gs-auth-helper.c gnome-screensaver-2.19.1.1/src/gs-auth-helper.c
--- gnome-screensaver-2.19.1.1.orig/src/gs-auth-helper.c	2007-02-22 23:39:09.000000000 -0500
+++ gnome-screensaver-2.19.1.1/src/gs-auth-helper.c	2007-07-26 13:45:13.000000000 -0400
@@ -78,7 +78,8 @@ gs_auth_get_verbose (void)
 static gboolean
 ext_run (const char *user,
          const char *typed_passwd,
-         gboolean    verbose)
+         gboolean    verbose,
+         gboolean    token)
 {
         int   pfd[2], status;
         pid_t pid;
@@ -107,7 +108,9 @@ ext_run (const char *user,
                 }
 
                 /* Helper is invoked as helper service-name [user] */
-                execlp (PASSWD_HELPER_PROGRAM, PASSWD_HELPER_PROGRAM, "gnome-screensaver", user, NULL);
+                execlp (PASSWD_HELPER_PROGRAM, PASSWD_HELPER_PROGRAM, 
+                        token ? PAM_SERVICE_NAME"-smartcard" : PAM_SERVICE_NAME,
+                        user, NULL);
                 if (verbose) {
                         g_message ("%s: %s", PASSWD_HELPER_PROGRAM, strerror (errno));
                 }
@@ -150,6 +153,7 @@ ext_run (const char *user,
 gboolean
 gs_auth_verify_user (const char       *username,
                      const char       *display,
+                     gboolean          token,
                      GSAuthMessageFunc func,
                      gpointer          data,
                      GError          **error)
@@ -162,7 +166,7 @@ gs_auth_verify_user (const char       *u
         /* ask for the password for user */
         if (func != NULL) {
                 func (GS_AUTH_MESSAGE_PROMPT_ECHO_OFF,
-                      "Password: ",
+                      token ? "PIN: " : "Password: ",
                       &password,
                       data);
         }
@@ -171,7 +175,7 @@ gs_auth_verify_user (const char       *u
                 return FALSE;
         }
 
-        res = ext_run (username, password, gs_auth_get_verbose ());
+        res = ext_run (username, password, gs_auth_get_verbose (), token);
 
         return res;
 }
diff -ruNp gnome-screensaver-2.19.1.1.orig/src/gs-auth-pam.c gnome-screensaver-2.19.1.1/src/gs-auth-pam.c
--- gnome-screensaver-2.19.1.1.orig/src/gs-auth-pam.c	2007-02-22 23:39:09.000000000 -0500
+++ gnome-screensaver-2.19.1.1/src/gs-auth-pam.c	2007-07-26 13:45:13.000000000 -0400
@@ -373,10 +373,11 @@ static gboolean
 create_pam_handle (const char      *username,
                    const char      *display,
                    struct pam_conv *conv,
-                   int             *status_code)
+                   int             *status_code,
+                   gboolean token)
 {
         int         status;
-        const char *service = PAM_SERVICE_NAME;
+        const char *service = token ? PAM_SERVICE_NAME"-smartcard" : PAM_SERVICE_NAME;
         char       *disp;
         gboolean    ret;
 
@@ -668,6 +669,7 @@ gs_auth_pam_verify_user (pam_handle_t *h
 gboolean
 gs_auth_verify_user (const char       *username,
                      const char       *display,
+                     gboolean          token,
                      GSAuthMessageFunc func,
                      gpointer          data,
                      GError          **error)
@@ -690,7 +692,7 @@ gs_auth_verify_user (const char       *u
         conv.appdata_ptr = (void *) &c;
 
         /* Initialize PAM. */
-        create_pam_handle (username, display, &conv, &status);
+        create_pam_handle (username, display, &conv, &status, token);
         if (status != PAM_SUCCESS) {
                 goto done;
         }
diff -ruNp gnome-screensaver-2.19.1.1.orig/src/gs-auth-pwent.c gnome-screensaver-2.19.1.1/src/gs-auth-pwent.c
--- gnome-screensaver-2.19.1.1.orig/src/gs-auth-pwent.c	2007-02-22 23:39:09.000000000 -0500
+++ gnome-screensaver-2.19.1.1/src/gs-auth-pwent.c	2007-07-26 13:45:13.000000000 -0400
@@ -242,6 +242,7 @@ passwds_match (const char *cleartext,
 gboolean
 gs_auth_verify_user (const char       *username,
                      const char       *display,
+                     gboolean          token,
                      GSAuthMessageFunc func,
                      gpointer          data,
                      GError          **error)
diff -ruNp gnome-screensaver-2.19.1.1.orig/src/gs-manager.c gnome-screensaver-2.19.1.1/src/gs-manager.c
--- gnome-screensaver-2.19.1.1.orig/src/gs-manager.c	2007-04-23 15:29:13.000000000 -0400
+++ gnome-screensaver-2.19.1.1/src/gs-manager.c	2007-07-26 13:45:13.000000000 -0400
@@ -1284,7 +1284,7 @@ window_obscured_cb (GSWindow   *window,
         maybe_set_window_throttle (manager, window, obscured);
 
         if (! obscured) {
-                gs_manager_request_unlock (manager);
+                gs_manager_request_unlock (manager, FALSE);
         }
 }
 
@@ -1294,7 +1294,7 @@ window_activity_cb (GSWindow  *window,
 {
         gboolean handled;
 
-        handled = gs_manager_request_unlock (manager);
+        handled = gs_manager_request_unlock (manager, FALSE);
 
         return handled;
 }
@@ -1564,7 +1564,7 @@ gs_manager_get_active (GSManager *manage
 }
 
 gboolean
-gs_manager_request_unlock (GSManager *manager)
+gs_manager_request_unlock (GSManager *manager, gboolean token)
 {
         GSWindow *window;
 
@@ -1593,7 +1593,7 @@ gs_manager_request_unlock (GSManager *ma
 
         /* Find the GSWindow that contains the pointer */
         window = find_window_at_pointer (manager);
-        gs_window_request_unlock (window);
+        gs_window_request_unlock (window, token);
 
         return TRUE;
 }
diff -ruNp gnome-screensaver-2.19.1.1.orig/src/gs-manager.h gnome-screensaver-2.19.1.1/src/gs-manager.h
--- gnome-screensaver-2.19.1.1.orig/src/gs-manager.h	2007-04-23 15:29:13.000000000 -0400
+++ gnome-screensaver-2.19.1.1/src/gs-manager.h	2007-07-26 13:45:13.000000000 -0400
@@ -95,7 +95,7 @@ void        gs_manager_set_themes       
                                              GSList     *themes);
 void        gs_manager_set_mode             (GSManager  *manager,
                                              GSSaverMode mode);
-gboolean    gs_manager_request_unlock       (GSManager  *manager);
+gboolean    gs_manager_request_unlock       (GSManager  *manager, gboolean token);
 void        gs_manager_cancel_unlock_request (GSManager *manager);
 
 G_END_DECLS
diff -ruNp gnome-screensaver-2.19.1.1.orig/src/gs-monitor.c gnome-screensaver-2.19.1.1/src/gs-monitor.c
--- gnome-screensaver-2.19.1.1.orig/src/gs-monitor.c	2007-04-23 15:29:13.000000000 -0400
+++ gnome-screensaver-2.19.1.1/src/gs-monitor.c	2007-07-26 13:45:13.000000000 -0400
@@ -29,6 +29,10 @@
 #include <glib.h>
 #include <glib-object.h>
 
+#define DBUS_API_SUBJECT_TO_CHANGE
+#include <dbus/dbus.h>
+#include <dbus/dbus-glib.h>
+
 #include "gnome-screensaver.h"
 
 #include "gs-manager.h"
@@ -41,6 +45,10 @@
 #include "gs-prefs.h"
 #include "gs-debug.h"
 
+#define PKCS11_MONITOR_SERVICE   "com.novell.Pkcs11Monitor"
+#define PKCS11_MONITOR_PATH      "/com/novell/Pkcs11Monitor"
+#define PKCS11_MONITOR_INTERFACE "com.novell.Pkcs11Monitor"
+
 static void     gs_monitor_class_init (GSMonitorClass *klass);
 static void     gs_monitor_init       (GSMonitor      *monitor);
 static void     gs_monitor_finalize   (GObject        *object);
@@ -56,6 +64,8 @@ struct GSMonitorPrivate
         GSFade         *fade;
         GSGrab         *grab;
 
+        DBusGProxy     *security_token_monitor;
+
         guint           release_grab_id;
 };
 
@@ -229,7 +239,7 @@ gs_monitor_lock_screen (GSMonitor *monit
 }
 
 static void
-gs_monitor_simulate_user_activity (GSMonitor *monitor)
+gs_monitor_simulate_user_activity (GSMonitor *monitor, gboolean token)
 {
         /* in case the screen isn't blanked reset the
            idle watcher */
@@ -237,7 +247,7 @@ gs_monitor_simulate_user_activity (GSMon
 
         /* request that the manager unlock -
            will pop up a dialog if necessary */
-        gs_manager_request_unlock (monitor->priv->manager);
+        gs_manager_request_unlock (monitor->priv->manager, token);
 }
 
 static void
@@ -306,7 +316,59 @@ static void
 listener_simulate_user_activity_cb (GSListener *listener,
                                     GSMonitor  *monitor)
 {
-        gs_monitor_simulate_user_activity (monitor);
+        gs_monitor_simulate_user_activity (monitor, FALSE);
+}
+
+static void
+security_token_inserted_cb (DBusGProxy *proxy,
+                            const char *token_name,
+			    GSMonitor              *monitor)
+{
+        gs_monitor_simulate_user_activity (monitor, TRUE);
+}
+
+static gboolean
+gs_monitor_should_lock_on_login_security_token_removal (void)
+{
+    /* FIXME: lame hack
+     */
+    // return system ("pkcs11_setup rm_action | grep -q lock") == 0;
+    return TRUE;
+}
+
+static gboolean
+gs_monitor_is_token_inserted (DBusGProxy *proxy, const char *token_name)
+{
+        gboolean is_inserted = FALSE;
+        if (!dbus_g_proxy_call (proxy, "IsTokenInserted", NULL, 
+                                G_TYPE_STRING, token_name, G_TYPE_INVALID, 
+                                G_TYPE_BOOLEAN, &is_inserted, G_TYPE_INVALID)) {
+                return FALSE;
+        }
+        return is_inserted;
+}
+
+static gboolean
+sc_security_token_is_login_token (const char *token_name)
+{
+    const char *env_token_name;
+
+    env_token_name = g_getenv ("PKCS11_LOGIN_TOKEN_NAME");
+    return env_token_name && !strcmp (token_name, env_token_name);
+}
+
+static void
+security_token_removed_cb (DBusGProxy *proxy,
+                           const char *token_name,
+			   GSMonitor              *monitor)
+{
+    if (gs_monitor_should_lock_on_login_security_token_removal () &&
+	sc_security_token_is_login_token (token_name))
+	    gs_monitor_lock_screen (monitor);
+
+    /* If we're already locked and the lock dialog is up, kill it.
+     */
+    gs_manager_cancel_unlock_request (monitor->priv->manager);
 }
 
 static void
@@ -425,6 +487,33 @@ connect_manager_signals (GSMonitor *moni
 }
 
 static void
+disconnect_security_token_monitor_signals (GSMonitor *monitor)
+{
+    dbus_g_proxy_disconnect_signal (monitor->priv->security_token_monitor,
+                                    "SecurityTokenInserted",
+                                    G_CALLBACK (security_token_inserted_cb), monitor);
+    dbus_g_proxy_disconnect_signal (monitor->priv->security_token_monitor,
+                                    "SecurityTokenRemoved",
+                                    G_CALLBACK (security_token_removed_cb), monitor);
+}
+
+static void
+connect_security_token_monitor_signals (GSMonitor *monitor)
+{
+    dbus_g_proxy_add_signal (monitor->priv->security_token_monitor,
+                             "SecurityTokenInserted", G_TYPE_STRING, G_TYPE_INVALID);
+    dbus_g_proxy_connect_signal (monitor->priv->security_token_monitor,
+                                 "SecurityTokenInserted",
+                                 G_CALLBACK (security_token_inserted_cb), monitor, NULL);
+
+    dbus_g_proxy_add_signal (monitor->priv->security_token_monitor,
+                             "SecurityTokenRemoved", G_TYPE_STRING, G_TYPE_INVALID);
+    dbus_g_proxy_connect_signal (monitor->priv->security_token_monitor,
+                                 "SecurityTokenRemoved",
+                                 G_CALLBACK (security_token_removed_cb), monitor, NULL);
+}
+
+static void
 disconnect_prefs_signals (GSMonitor *monitor)
 {
         g_signal_handlers_disconnect_by_func (monitor->priv->prefs, _gs_monitor_update_from_prefs, monitor);
@@ -440,6 +529,8 @@ connect_prefs_signals (GSMonitor *monito
 static void
 gs_monitor_init (GSMonitor *monitor)
 {
+        DBusGConnection *conn;
+        GError *err = NULL;
 
         monitor->priv = GS_MONITOR_GET_PRIVATE (monitor);
 
@@ -458,6 +549,36 @@ gs_monitor_init (GSMonitor *monitor)
         monitor->priv->manager = gs_manager_new ();
         connect_manager_signals (monitor);
 
+	/* PKCS11_LOGIN_TOKEN_NAME is set if the user logged in with a
+	 * security token.
+	 */
+        conn = dbus_g_bus_get (DBUS_BUS_SYSTEM, &err);
+        if (!conn) {
+                g_warning ("couldn't connect to system bus: %s\n", err->message);
+                g_error_free (err);
+                monitor->priv->security_token_monitor = NULL;
+        } else {
+                gchar *env_token_name;
+
+                monitor->priv->security_token_monitor = dbus_g_proxy_new_for_name (conn,
+                                                                                   PKCS11_MONITOR_SERVICE,
+                                                                                   PKCS11_MONITOR_PATH,
+                                                                                   PKCS11_MONITOR_INTERFACE);
+                dbus_g_connection_unref (conn);
+
+                connect_security_token_monitor_signals (monitor);
+
+                env_token_name = g_getenv ("PKCS11_LOGIN_TOKEN_NAME");
+                /* if the user logged in with a security token but it's
+                 * not currently inserted, then they must have yanked it
+                 * before we started.  lock the screen immediately
+                 */
+                if (env_token_name && env_token_name[0] &&
+                    gs_monitor_should_lock_on_login_security_token_removal () &&
+                    !gs_monitor_is_token_inserted (monitor->priv->security_token_monitor, env_token_name))
+                        gs_monitor_lock_screen (monitor);
+        }
+        
         _gs_monitor_update_from_prefs (monitor, monitor->priv->prefs);
 }
 
@@ -473,6 +594,11 @@ gs_monitor_finalize (GObject *object)
 
         g_return_if_fail (monitor->priv != NULL);
 
+	if (monitor->priv->security_token_monitor != NULL) {
+		disconnect_security_token_monitor_signals (monitor);
+		g_object_unref (monitor->priv->security_token_monitor);
+	}
+
         disconnect_watcher_signals (monitor);
         disconnect_listener_signals (monitor);
         disconnect_manager_signals (monitor);
diff -ruNp gnome-screensaver-2.19.1.1.orig/src/gs-window.h gnome-screensaver-2.19.1.1/src/gs-window.h
--- gnome-screensaver-2.19.1.1.orig/src/gs-window.h	2007-04-23 15:29:13.000000000 -0400
+++ gnome-screensaver-2.19.1.1/src/gs-window.h	2007-07-26 13:45:13.000000000 -0400
@@ -82,7 +82,7 @@ void        gs_window_set_logout_command
 void        gs_window_set_away_message   (GSWindow   *window,
                                           const char *away_message);
 
-void        gs_window_request_unlock     (GSWindow  *window);
+void        gs_window_request_unlock     (GSWindow  *window, gboolean token);
 void        gs_window_cancel_unlock_request (GSWindow  *window);
 
 GSWindow  * gs_window_new                (GdkScreen *screen,
diff -ruNp gnome-screensaver-2.19.1.1.orig/src/gs-window-x11.c gnome-screensaver-2.19.1.1/src/gs-window-x11.c
--- gnome-screensaver-2.19.1.1.orig/src/gs-window-x11.c	2007-07-26 13:44:40.000000000 -0400
+++ gnome-screensaver-2.19.1.1/src/gs-window-x11.c	2007-07-26 13:45:13.000000000 -0400
@@ -78,6 +78,7 @@ struct GSWindowPrivate
         GtkWidget *keyboard_socket;
 
         guint      popup_dialog_idle_id;
+        gboolean   popup_dialog_idle_token;
 
         guint      dialog_map_signal_id;
         guint      dialog_unmap_signal_id;
@@ -571,8 +572,9 @@ remove_popup_dialog_idle (GSWindow *wind
 }
 
 static void
-add_popup_dialog_idle (GSWindow *window)
+add_popup_dialog_idle (GSWindow *window, gboolean token)
 {
+        window->priv->popup_dialog_idle_token = token;
         window->priv->popup_dialog_idle_id = g_idle_add ((GSourceFunc)popup_dialog_idle, window);
 }
 
@@ -1546,6 +1548,10 @@ popup_dialog_idle (GSWindow *window)
                 command = g_string_append (command, " --verbose");
         }
 
+        if (window->priv->popup_dialog_idle_token) {
+                command = g_string_append (command, " --token");
+        }
+
         gs_window_clear (window);
         set_invisible_cursor (GTK_WIDGET (window)->window, FALSE);
 
@@ -1561,13 +1567,14 @@ popup_dialog_idle (GSWindow *window)
 
         g_string_free (command, TRUE);
 
+        window->priv->popup_dialog_idle_token = FALSE;
         window->priv->popup_dialog_idle_id = 0;
 
         return FALSE;
 }
 
 void
-gs_window_request_unlock (GSWindow *window)
+gs_window_request_unlock (GSWindow *window, gboolean token)
 {
         g_return_if_fail (GS_IS_WINDOW (window));
 
@@ -1589,7 +1596,7 @@ gs_window_request_unlock (GSWindow *wind
         }
 
         if (window->priv->popup_dialog_idle_id == 0) {
-                add_popup_dialog_idle (window);
+                add_popup_dialog_idle (window, token);
         }
 
         g_signal_emit (window, signals [DIALOG_UP], 0);
diff -ruNp gnome-screensaver-2.19.1.1.orig/src/test-passwd.c gnome-screensaver-2.19.1.1/src/test-passwd.c
--- gnome-screensaver-2.19.1.1.orig/src/test-passwd.c	2007-02-22 23:39:09.000000000 -0500
+++ gnome-screensaver-2.19.1.1/src/test-passwd.c	2007-07-26 13:45:13.000000000 -0400
@@ -250,7 +250,7 @@ main (int    argc,
  again:
         error = NULL;
 
-        if (gs_auth_verify_user (g_get_user_name (), g_getenv ("DISPLAY"), auth_message_handler, NULL, &error)) {
+        if (gs_auth_verify_user (g_get_user_name (), g_getenv ("DISPLAY"), FALSE, auth_message_handler, NULL, &error)) {
                 printf ("Correct!\n");
         } else {
                 if (error != NULL) {
diff -ruNp gnome-screensaver-2.19.1.1.orig/src/test-window.c gnome-screensaver-2.19.1.1/src/test-window.c
--- gnome-screensaver-2.19.1.1.orig/src/test-window.c	2007-03-17 16:28:22.000000000 -0400
+++ gnome-screensaver-2.19.1.1/src/test-window.c	2007-07-26 13:45:13.000000000 -0400
@@ -69,7 +69,7 @@ static gboolean
 window_activity_cb (GSWindow  *window,
                     gpointer   data)
 {
-        gs_window_request_unlock (window);
+        gs_window_request_unlock (window, FALSE);
 
         return TRUE;
 }
