[gnome-keyring] [daemon] Large refactoring of prompting for pkcs11 logins.



commit 9ea8eaa48fb22201e2f63d78ff4a331c1d3ce0ca
Author: Stef Walter <stef memberwebs com>
Date:   Sat Dec 19 19:00:01 2009 +0000

    [daemon] Large refactoring of prompting for pkcs11 logins.
    
     * Remove old ask code.
     * Remove old async code, location code daemon util code.
     * Move our custom GtkEntryBuffer into egg.
     * Remove old EggSecureEntry stuff.
     * Rework how threading works in pkcs11 daemon auth and prompting.
     * Use new prompting stuff for pkcs11 logins.
     * Make several fixes to the daemon/login code.

 configure.in                                       |    3 -
 daemon/Makefile.am                                 |    6 +-
 daemon/dbus/gkd-dbus-secrets.c                     |    4 +-
 daemon/gkd-main.c                                  |   19 +-
 daemon/login/gkd-login.c                           |   30 +-
 daemon/pkcs11/Makefile.am                          |   11 +-
 .../{gkr-pkcs11-auth-ep.c => gkd-pkcs11-auth.c}    |  860 +++++--
 .../{gkr-pkcs11-daemon.h => gkd-pkcs11-auth.h}     |   32 +-
 daemon/pkcs11/gkd-pkcs11-data.c                    |  263 ++
 daemon/pkcs11/gkd-pkcs11-data.h                    |   52 +
 .../pkcs11/{gkr-pkcs11-daemon.c => gkd-pkcs11.c}   |  168 +-
 .../pkcs11/{gkr-pkcs11-daemon.h => gkd-pkcs11.h}   |   32 +-
 daemon/pkcs11/gkr-pkcs11-auth.c                    |  657 -----
 daemon/pkcs11/gkr-pkcs11-auth.h                    |   96 -
 daemon/prompt/Makefile.am                          |    2 +-
 daemon/prompt/gkd-prompt-buffer.h                  |   59 -
 daemon/prompt/gkd-prompt-tool.c                    |    4 +-
 daemon/prompt/gkd-prompt.c                         |   55 +-
 daemon/prompt/gkd-prompt.h                         |    7 +
 daemon/prompt/gkd-prompt.ui                        |   13 +-
 daemon/ui/.gitignore                               |    7 -
 daemon/ui/Makefile.am                              |   48 -
 daemon/ui/gkr-ask-daemon.c                         |  194 --
 daemon/ui/gkr-ask-daemon.h                         |   37 -
 daemon/ui/gkr-ask-marshal.list                     |    1 -
 daemon/ui/gkr-ask-request.c                        |  967 -------
 daemon/ui/gkr-ask-request.h                        |  145 -
 daemon/ui/gkr-ask-tool-widgets.c                   |  201 --
 daemon/ui/gkr-ask-tool.c                           |  862 ------
 daemon/ui/gkr-ask-tool.h                           |   33 -
 daemon/ui/test-input.txt                           |    8 -
 daemon/util/.gitignore                             |    5 -
 daemon/util/Makefile.am                            |   31 -
 daemon/util/gkr-daemon-async.c                     |  633 -----
 daemon/util/gkr-daemon-async.h                     |  171 --
 daemon/util/gkr-daemon-util.c                      |  230 --
 daemon/util/gkr-daemon-util.h                      |   70 -
 daemon/util/gkr-location.c                         |  959 -------
 daemon/util/gkr-location.h                         |  130 -
 daemon/util/tests/.gitignore                       |    7 -
 daemon/util/tests/Makefile.am                      |   12 -
 daemon/util/tests/unit-test-async.c                |  222 --
 daemon/util/tests/unit-test-location.c             |  209 --
 egg/Makefile.am                                    |   14 +-
 .../gkd-prompt-buffer.c => egg/egg-entry-buffer.c  |   61 +-
 egg/egg-entry-buffer.h                             |   59 +
 egg/egg-secure-entry.c                             | 2754 --------------------
 egg/egg-secure-entry.h                             |  187 --
 gcr/Makefile.am                                    |    2 +-
 gcr/gcr-certificate.c                              |    2 +-
 gcr/gcr-import-dialog.c                            |   15 +-
 51 files changed, 1230 insertions(+), 9419 deletions(-)
---
diff --git a/configure.in b/configure.in
index 81c1c0d..a4bc774 100644
--- a/configure.in
+++ b/configure.in
@@ -558,9 +558,6 @@ daemon/login/Makefile
 daemon/pkcs11/Makefile
 daemon/prompt/Makefile
 daemon/prompt/tests/Makefile
-daemon/ui/Makefile
-daemon/util/Makefile
-daemon/util/tests/Makefile
 docs/Makefile
 docs/reference/Makefile
 docs/reference/gcr/Makefile
diff --git a/daemon/Makefile.am b/daemon/Makefile.am
index 5e3143f..979715f 100644
--- a/daemon/Makefile.am
+++ b/daemon/Makefile.am
@@ -1,6 +1,4 @@
 SUBDIRS = \
-	util \
-	ui \
 	prompt \
 	login \
 	control \
@@ -30,13 +28,11 @@ gnome_keyring_daemon_SOURCES = \
 	gkd-util.c gkd-util.h
 
 gnome_keyring_daemon_LDADD = \
-	$(top_builddir)/daemon/pkcs11/libgkr-pkcs11.la \
+	$(top_builddir)/daemon/pkcs11/libgkd-pkcs11.la \
 	$(top_builddir)/daemon/dbus/libgkr-dbus.la \
 	$(top_builddir)/daemon/login/libgkd-login.la \
-	$(top_builddir)/daemon/ui/libgkr-ui.la \
 	$(top_builddir)/daemon/control/libgkd-control.la \
 	$(top_builddir)/daemon/prompt/libgkd-prompt.la \
-	$(top_builddir)/daemon/util/libgkr-daemon-util.la \
 	$(top_builddir)/pkcs11/plex-layer/libgck-plex-layer.la \
 	$(top_builddir)/pkcs11/roots-store/libgck-roots-store.la \
 	$(top_builddir)/pkcs11/rpc-layer/libgck-rpc-layer.la \
diff --git a/daemon/dbus/gkd-dbus-secrets.c b/daemon/dbus/gkd-dbus-secrets.c
index e049d2a..68ab9f7 100644
--- a/daemon/dbus/gkd-dbus-secrets.c
+++ b/daemon/dbus/gkd-dbus-secrets.c
@@ -26,7 +26,7 @@
 #include "gkd-dbus-private.h"
 #include "gkd-secret-service.h"
 
-#include "daemon/pkcs11/gkr-pkcs11-daemon.h"
+#include "daemon/pkcs11/gkd-pkcs11.h"
 
 #include "gp11/gp11.h"
 
@@ -40,7 +40,7 @@ calculate_secrets_slot (void)
 	GList *slots, *l;
 	GP11SlotInfo *info;
 
-	module = gp11_module_new (gkr_pkcs11_daemon_get_functions ());
+	module = gp11_module_new (gkd_pkcs11_get_functions ());
 	g_return_val_if_fail (module, NULL);
 
 	/*
diff --git a/daemon/gkd-main.c b/daemon/gkd-main.c
index 01d297b..f88362f 100644
--- a/daemon/gkd-main.c
+++ b/daemon/gkd-main.c
@@ -37,11 +37,7 @@
 
 #include "login/gkd-login.h"
 
-#include "pkcs11/gkr-pkcs11-daemon.h"
-
-#include "ui/gkr-ask-daemon.h"
-
-#include "util/gkr-daemon-async.h"
+#include "pkcs11/gkd-pkcs11.h"
 
 #include <errno.h>
 #include <fcntl.h>
@@ -635,13 +631,13 @@ gkr_daemon_startup_steps (void)
 	/* Startup the appropriate components, creates sockets etc.. */
 #ifdef WITH_SSH
 	if (check_run_component ("ssh")) {
-		if (!gkr_pkcs11_daemon_startup_ssh ())
+		if (!gkd_pkcs11_startup_ssh ())
 			return FALSE;
 	}
 #endif
 
 	if (check_run_component ("pkcs11")) {
-		if (!gkr_pkcs11_daemon_startup_pkcs11 ())
+		if (!gkd_pkcs11_startup_pkcs11 ())
 			return FALSE;
 	}
 
@@ -653,7 +649,7 @@ static gboolean
 gkr_daemon_initialize_steps (void)
 {
 	/* Initialize new style PKCS#11 components */
-	if (!gkr_pkcs11_daemon_initialize ())
+	if (!gkd_pkcs11_initialize ())
 		return FALSE;
 
 	/*
@@ -756,7 +752,6 @@ main (int argc, char *argv[])
 	/* Initialize our daemon main loop and threading */
 	loop = g_main_loop_new (NULL, FALSE);
 	ctx = g_main_loop_get_context (loop);
-	gkr_daemon_async_workers_init (loop);
 
 	/* Initialize our control socket */
 	if (!gkd_control_listen ())
@@ -800,15 +795,9 @@ main (int argc, char *argv[])
 
 	g_main_loop_run (loop);
 
-	/* Make sure no other threads are running */
-	gkr_daemon_async_workers_stop_all ();
-
 	/* This wraps everything up in order */
 	egg_cleanup_perform ();
 
-	/* Final shutdown of anything workers running about */
-	gkr_daemon_async_workers_uninit ();
-
 	/* Wrap up signal handling here */
 	cleanup_signal_handling ();
 
diff --git a/daemon/login/gkd-login.c b/daemon/login/gkd-login.c
index f327e34..772916b 100644
--- a/daemon/login/gkd-login.c
+++ b/daemon/login/gkd-login.c
@@ -25,7 +25,7 @@
 
 #include "egg/egg-secure-memory.h"
 
-#include "pkcs11/gkr-pkcs11-daemon.h"
+#include "pkcs11/gkd-pkcs11.h"
 #include "pkcs11/pkcs11i.h"
 
 #include <string.h>
@@ -41,7 +41,7 @@ note_that_unlock_failed (void)
 static GP11Module*
 module_instance (void)
 {
-	GP11Module *module = gp11_module_new (gkr_pkcs11_daemon_get_base_functions ());
+	GP11Module *module = gp11_module_new (gkd_pkcs11_get_base_functions ());
 	gp11_module_set_pool_sessions (module, FALSE);
 	gp11_module_set_auto_authenticate (module, FALSE);
 	g_return_val_if_fail (module, NULL);
@@ -52,14 +52,20 @@ static GP11Session*
 open_and_login_session (GP11Slot *slot, CK_USER_TYPE user_type, GError **error)
 {
 	GP11Session *session;
+	GError *err = NULL;
 
 	g_return_val_if_fail (GP11_IS_SLOT (slot), NULL);
 
+	if (!error)
+		error = &err;
+
 	session = gp11_slot_open_session (slot, CKF_RW_SESSION, error);
 	if (session != NULL) {
 		if (!gp11_session_login (session, user_type, NULL, 0, error)) {
-			g_object_unref (session);
-			session = NULL;
+			if ((*error)->code != CKR_USER_ALREADY_LOGGED_IN) {
+				g_object_unref (session);
+				session = NULL;
+			}
 		}
 	}
 
@@ -458,7 +464,7 @@ gkd_login_is_usable (void)
 		login = lookup_login_keyring (session);
 		if (login) {
 			data = gp11_object_get_data (login, CKA_G_LOCKED, &n_data, NULL);
-			usable = (data && n_data == sizeof (CK_BBOOL) && *((CK_BBOOL*)data));
+			usable = (data && n_data == sizeof (CK_BBOOL) && !*((CK_BBOOL*)data));
 			g_free (data);
 			g_object_unref (login);
 		}
@@ -491,7 +497,7 @@ static GP11Object*
 find_login_keyring_item (GP11Session *session, GP11Attribute *fields)
 {
 	GP11Object *search;
-	GP11Object *item;
+	GP11Object *item = NULL;
 	GList *objects;
 	GError *error = NULL;
 	gpointer data;
@@ -503,6 +509,7 @@ find_login_keyring_item (GP11Session *session, GP11Attribute *fields)
 	search = gp11_session_create_object (session, &error,
 	                                     CKA_CLASS, GP11_ULONG, CKO_G_SEARCH,
 	                                     CKA_G_COLLECTION, 5, "login",
+	                                     CKA_TOKEN, GP11_BOOLEAN, FALSE,
 	                                     CKA_G_FIELDS, fields->length, fields->value,
 	                                     GP11_INVALID);
 
@@ -591,12 +598,11 @@ gkd_login_attach_secret (const gchar *display_name, const gchar *secret,
 gchar*
 gkd_login_lookup_secret (const gchar *first, ...)
 {
-	GError *error = NULL;
 	GP11Attribute fields;
 	GP11Session *session;
 	GP11Module *module;
 	GP11Object* item;
-	gpointer data;
+	gpointer data = NULL;
 	gsize n_data;
 	va_list va;
 
@@ -609,9 +615,9 @@ gkd_login_lookup_secret (const gchar *first, ...)
 	va_end(va);
 
 	item = find_login_keyring_item (session, &fields);
-	if (item == NULL) {
-		data = gp11_object_get_data_full (item, CKA_VALUE, egg_secure_realloc, NULL, &n_data, &error);
-		if (!g_utf8_validate (data, n_data, NULL)) {
+	if (item != NULL) {
+		data = gp11_object_get_data_full (item, CKA_VALUE, egg_secure_realloc, NULL, &n_data, NULL);
+		if (data && !g_utf8_validate (data, n_data, NULL)) {
 			g_warning ("expected string, but found binary secret in login keyring");
 			egg_secure_clear (data, n_data);
 			egg_secure_free (data);
@@ -646,7 +652,7 @@ gkd_login_remove_secret (const gchar *first, ...)
 	va_end(va);
 
 	item = find_login_keyring_item (session, &fields);
-	if (item == NULL) {
+	if (item != NULL) {
 		if (!gp11_object_destroy (item, &error)) {
 			g_warning ("couldn't remove stored secret from login keyring: %s", error->message);
 			g_clear_error (&error);
diff --git a/daemon/pkcs11/Makefile.am b/daemon/pkcs11/Makefile.am
index bcae8ce..f096027 100644
--- a/daemon/pkcs11/Makefile.am
+++ b/daemon/pkcs11/Makefile.am
@@ -8,14 +8,15 @@ INCLUDES = \
 	$(GLIB_CFLAGS)
 
 DAEMON_SRCS = \
-	gkr-pkcs11-auth.c gkr-pkcs11-auth.h gkr-pkcs11-auth-ep.c \
-	gkr-pkcs11-daemon.c gkr-pkcs11-daemon.h
+	gkd-pkcs11-auth.c gkd-pkcs11-auth.h \
+	gkd-pkcs11-data.c gkd-pkcs11-data.h \
+	gkd-pkcs11.c gkd-pkcs11.h
 
-noinst_LTLIBRARIES = libgkr-pkcs11.la
+noinst_LTLIBRARIES = libgkd-pkcs11.la
 
-libgkr_pkcs11_la_SOURCES = $(DAEMON_SRCS)
+libgkd_pkcs11_la_SOURCES = $(DAEMON_SRCS)
 
-libgkr_pkcs11_la_LIBADD = \
+libgkd_pkcs11_la_LIBADD = \
 	$(GLIB_LIBS) \
 	$(GOBJECT_LIBS)
 
diff --git a/daemon/pkcs11/gkr-pkcs11-auth-ep.c b/daemon/pkcs11/gkd-pkcs11-auth.c
similarity index 63%
rename from daemon/pkcs11/gkr-pkcs11-auth-ep.c
rename to daemon/pkcs11/gkd-pkcs11-auth.c
index 984b297..599e212 100644
--- a/daemon/pkcs11/gkr-pkcs11-auth-ep.c
+++ b/daemon/pkcs11/gkd-pkcs11-auth.c
@@ -1,65 +1,81 @@
-/* 
+/*
  * gnome-keyring
- * 
+ *
  * Copyright (C) 2008 Stefan Walter
- * 
- * This program is free software; you can redistribute it and/or modify 
+ *
+ * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU Lesser General  License as
  * published by the Free Software Foundation; either version 2.1 of
  * the License, or (at your option) any later version.
- *  
+ *
  * This program is distributed in the hope that it will be useful, but
  * WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General  License for more details.
- *  
- * You should have received a copy of the GNU Lesser General 
+ *
+ * You should have received a copy of the GNU Lesser General
  * License along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.  
+ * 02111-1307, USA.
  */
 
 #include "config.h"
 
-#include "gkr-pkcs11-auth.h"
+#include "gkd-pkcs11-auth.h"
+#include "gkd-pkcs11-data.h"
+
+#include "egg/egg-secure-memory.h"
 
-#include "daemon/util/gkr-daemon-async.h"
+#include "login/gkd-login.h"
 
 #include "pkcs11/pkcs11.h"
 #include "pkcs11/pkcs11g.h"
 #include "pkcs11/pkcs11i.h"
 
+#include "prompt/gkd-prompt.h"
+
 #include <glib.h>
+#include <glib/gi18n.h>
 
 #include <string.h>
 
 /*
- * All these function entry points operate outside of any threading locks. 
- * Any calls to parts of the daemon must be locked inside blocks of:
- * 
- * DAEMON_ENTER ();
- * 
- *     ...
- *     
- * DAEMON_LEAVE ();
+ * All these function entry points operate outside of any threading locks.
+ * Only calls that may be made to gkd_*() functions are to gkd_pkcs11_auth_*()
+ * functions.
  */
 
 static CK_FUNCTION_LIST_PTR pkcs11_lower = NULL;
 
-#define DAEMON_ENTER() \
-	gkr_daemon_async_end_concurrent ()
+typedef struct _AuthObject {
+	CK_OBJECT_HANDLE handle;
+	CK_OBJECT_CLASS klass;
+	CK_SLOT_ID slot;
+	CK_BBOOL token;
+	gchar *label;
+	gchar *unique;
+	gchar *digest;
+} AuthObject;
 
-#define DAEMON_LEAVE() \
-	gkr_daemon_async_begin_concurrent ()
+static void
+auth_object_free (gpointer data)
+{
+	AuthObject *object = data;
+	g_assert (object);
+	g_free (object->label);
+	g_free (object->unique);
+	g_free (object->digest);
+	g_free (object);
+}
 
 /* --------------------------------------------------------------------------------------
- * HELPERS 
+ * HELPERS
  */
 
-static GkrPkcs11AuthObject*
+static AuthObject*
 auth_object_for_context_specific (CK_SESSION_HANDLE handle, CK_OBJECT_HANDLE object)
 {
-	GkrPkcs11AuthObject *info = NULL;
+	AuthObject *info = NULL;
 	CK_SESSION_INFO session_info;
 	CK_ATTRIBUTE attrs[6];
 	CK_OBJECT_CLASS klass;
@@ -92,19 +108,19 @@ auth_object_for_context_specific (CK_SESSION_HANDLE handle, CK_OBJECT_HANDLE obj
 	attrs[4].type = CKA_ALWAYS_AUTHENTICATE;
 	attrs[4].pValue = &always;
 	attrs[4].ulValueLen = sizeof (always);
-	
+
 	token = CK_FALSE;
 	attrs[5].type = CKA_TOKEN;
 	attrs[5].pValue = &token;
 	attrs[5].ulValueLen = sizeof (token);
-	
+
 	n_attrs = 6;
-	
+
 	/* Get attribute sizes */
 	rv = (pkcs11_lower->C_GetAttributeValue) (handle, object, attrs, n_attrs);
 	if (rv != CKR_OK && rv != CKR_ATTRIBUTE_TYPE_INVALID)
 		return NULL;
-	
+
 	/* If this isn't an always auth object, then skip */
 	if (always != CK_TRUE)
 		return NULL;
@@ -121,7 +137,7 @@ auth_object_for_context_specific (CK_SESSION_HANDLE handle, CK_OBJECT_HANDLE obj
 		attrs[1].pValue = unique = g_malloc0 (attrs[1].ulValueLen + 1);
 	if (attrs[2].ulValueLen != (CK_ULONG)-1)
 		attrs[2].pValue = digest = g_malloc0 (attrs[2].ulValueLen + 1);
-	
+
 	/* Get actual attributes */
 	rv = (pkcs11_lower->C_GetAttributeValue) (handle, object, attrs, n_attrs);
 	if (rv != CKR_OK && rv != CKR_ATTRIBUTE_TYPE_INVALID) {
@@ -130,9 +146,9 @@ auth_object_for_context_specific (CK_SESSION_HANDLE handle, CK_OBJECT_HANDLE obj
 		g_free (digest);
 		return NULL;
 	}
-	
-	info = g_new0 (GkrPkcs11AuthObject, 1);
-	
+
+	info = g_new0 (AuthObject, 1);
+
 	if (attrs[0].ulValueLen != (CK_ULONG)-1) {
 		info->label = label;
 		label = NULL;
@@ -142,7 +158,7 @@ auth_object_for_context_specific (CK_SESSION_HANDLE handle, CK_OBJECT_HANDLE obj
 		info->unique = unique;
 		unique = NULL;
 	}
-	
+
 	if (attrs[2].ulValueLen != (CK_ULONG)-1) {
 		info->digest = digest;
 		digest = NULL;
@@ -152,11 +168,11 @@ auth_object_for_context_specific (CK_SESSION_HANDLE handle, CK_OBJECT_HANDLE obj
 	info->klass = klass;
 	info->handle = object;
 	info->slot = session_info.slotID;
-	
+
 	g_free (label);
 	g_free (unique);
 	g_free (digest);
-	
+
 	return info;
 }
 
@@ -183,6 +199,464 @@ auth_create_credential (CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object,
 		g_message ("failed to create credential object (code: %lu)", (gulong)rv);
 }
 
+static void
+password_to_pin (const gchar *password, CK_UTF8CHAR_PTR *pin, CK_ULONG *pin_len)
+{
+	g_assert (pin);
+	g_assert (pin_len);
+
+	if (password == NULL) {
+		*pin = NULL;
+		*pin_len = 0;
+	} else {
+		*pin = (CK_UTF8CHAR_PTR)password;
+		*pin_len = strlen (password);
+	}
+}
+
+static void
+convert_upper_case (gchar *str)
+{
+	for (; *str; ++str)
+		*str = g_ascii_toupper (*str);
+}
+
+static GkdPrompt*
+on_prompt_attention (gpointer user_data)
+{
+	/* We were passed the prompt */
+	return g_object_ref (user_data);
+}
+
+static void
+clear_user_login (CK_TOKEN_INFO *info)
+{
+	gchar *manufacturer;
+	gchar *serial;
+
+	g_assert (info);
+
+	if (gkd_login_is_usable ()) {
+		/*
+		 * The manufacturer and serial number together uniquely identify token
+		 * They're stored with space padded in the token info structure.
+		 */
+
+		manufacturer = g_strndup ((gchar*)info->manufacturerID, sizeof (info->manufacturerID));
+		g_strchomp (manufacturer);
+
+		serial = g_strndup ((gchar*)info->serialNumber, sizeof (info->serialNumber));
+		g_strchomp (serial);
+
+		gkd_login_remove_secret ("manufacturer", manufacturer,
+		                         "serial-number", serial,
+		                         NULL);
+
+		g_free (manufacturer);
+		g_free (serial);
+	}
+}
+
+static gboolean
+init_user_prompt (CK_SESSION_HANDLE handle, CK_TOKEN_INFO *info,
+                  CK_UTF8CHAR_PTR *pin, CK_ULONG *pin_len)
+{
+	GkdPrompt *prompt;
+	gchar *password;
+	gchar *label;
+	gchar *secondary;
+	gchar *manufacturer;
+	gchar *serial;
+	gboolean ret = TRUE;
+
+	g_assert (info);
+	g_assert (pin);
+	g_assert (pin_len);
+
+	/*
+	 * The manufacturer and serial number together uniquely identify token
+	 * They're stored with space padded in the token info structure.
+	 */
+
+	manufacturer = g_strndup ((gchar*)info->manufacturerID, sizeof (info->manufacturerID));
+	g_strchomp (manufacturer);
+
+	serial = g_strndup ((gchar*)info->serialNumber, sizeof (info->serialNumber));
+	g_strchomp (serial);
+
+	label = g_strndup ((gchar*)info->label, sizeof (info->label));
+	g_strchomp (label);
+
+	/* Build up the prompt */
+	prompt = gkd_prompt_new ();
+	gkd_prompt_show_widget (prompt, "password_area");
+	gkd_prompt_show_widget (prompt, "confirm_area");
+	gkd_prompt_set_title (prompt, _("New Password Required"));
+	gkd_prompt_set_primary_text (prompt, _("New password required for secure storage"));
+
+	secondary = g_strdup_printf (_("In order to prepare '%s' for storage of certificates or keys, a password is required"), label);
+	gkd_prompt_set_secondary_text (prompt, secondary);
+	g_free (secondary);
+
+#if 0
+	if (gkd_login_is_usable ())
+		gkd_ask_request_set_check_option (ask, _("Automatically unlock secure storage when I log in."));
+#endif
+
+	/* Prompt the user */
+	gkd_prompt_request_attention_async (NULL, on_prompt_attention, prompt, NULL);
+
+	if (!gkd_prompt_has_response (prompt)) {
+		ret = FALSE;
+
+	} else if (gkd_prompt_get_response (prompt) != GKD_RESPONSE_OK) {
+		ret = FALSE;
+
+	/* Successful response */
+	} else {
+		password = gkd_prompt_get_password (prompt, "password");
+		password_to_pin (password, pin, pin_len);
+
+#if 0
+		if (ask->checked) {
+			gkd_login_attach_secret (label, ask->typed_password,
+			                         "manufacturer", manufacturer,
+			                         "serial-number", serial,
+			                         NULL);
+		}
+#endif
+
+		ret = TRUE;
+	}
+
+	g_free (manufacturer);
+	g_free (serial);
+	g_free (label);
+
+	g_object_unref (prompt);
+	return ret;
+}
+
+static void
+init_user_done (CK_SESSION_HANDLE handle, CK_TOKEN_INFO *token_info,
+                CK_UTF8CHAR_PTR *pin, CK_ULONG *pin_len, CK_RV rv)
+{
+	g_assert (pin);
+	g_assert (pin_len);
+
+	if (rv != CKR_OK)
+		clear_user_login (token_info);
+
+	egg_secure_strfree ((gchar*)*pin);
+
+	*pin = NULL;
+	*pin_len = 0;
+}
+
+static const gchar*
+prepare_specific_title (CK_OBJECT_CLASS klass)
+{
+	switch (klass) {
+	case CKO_PRIVATE_KEY:
+		return _("Unlock private key");
+	case CKO_CERTIFICATE:
+		return _("Unlock certificate");
+	case CKO_PUBLIC_KEY:
+		return _("Unlock public key");
+	default:
+		return _("Unlock");
+	}
+}
+
+static const gchar*
+prepare_specific_primary (CK_OBJECT_CLASS klass)
+{
+	switch (klass) {
+	case CKO_PRIVATE_KEY:
+		return _("Enter password to unlock the private key");
+	case CKO_CERTIFICATE:
+		return _("Enter password to unlock the certificate");
+	case CKO_PUBLIC_KEY:
+		return _("Enter password to unlock the public key");
+	default:
+		return _("Enter password to unlock");
+	}
+}
+
+static gchar*
+prepare_specific_secondary (CK_OBJECT_CLASS klass, const gchar *label)
+{
+	switch (klass) {
+	case CKO_PRIVATE_KEY:
+		/* TRANSLATORS: The private key is locked */
+		return g_strdup_printf (_("An application wants access to the private key '%s', but it is locked"), label);
+	case CKO_CERTIFICATE:
+		/* TRANSLATORS: The certificate is locked */
+		return g_strdup_printf (_("An application wants access to the certificate '%s', but it is locked"), label);
+	case CKO_PUBLIC_KEY:
+		/* TRANSLATORS: The public key is locked */
+		return g_strdup_printf (_("An application wants access to the public key '%s', but it is locked"), label);
+	default:
+		/* TRANSLATORS: The object '%s' is locked */
+		return g_strdup_printf (_("An application wants access to '%s', but it is locked"), label);
+	}
+}
+
+static void
+login_specific_prepare (CK_SESSION_HANDLE handle, AuthObject *object)
+{
+	gkd_pkcs11_data_session_store (object->slot, handle, object, auth_object_free);
+}
+
+static gboolean
+login_specific_prompt (CK_SESSION_HANDLE handle, CK_SESSION_INFO *info,
+                       CK_UTF8CHAR_PTR *pin, CK_ULONG *pin_len,
+                       CK_OBJECT_HANDLE_PTR specific)
+{
+	AuthObject *object;
+	const gchar *password;
+	GkdPrompt *prompt;
+	gchar *secondary;
+	gboolean ret;
+
+	g_assert (info);
+	g_assert (pin);
+	g_assert (pin_len);
+
+	/* Because we should have been notified of open session */
+	object = gkd_pkcs11_data_session_lookup (info->slotID, handle);
+	if (object == NULL)
+		return FALSE;
+
+	if (specific)
+		*specific = object->handle;
+
+	/* See if we can just use the login keyring password for this */
+	if (object->unique && object->token) {
+		password = gkd_login_lookup_secret ("unique", object->unique, NULL);
+		if (password != NULL) {
+			password_to_pin (password, pin, pin_len);
+			return TRUE;
+		}
+	}
+
+	/* COMPAT: Check old method of storing secrets for objects in login keyring */
+	if (object->digest) {
+		convert_upper_case (object->digest);
+		password = gkd_login_lookup_secret ("object-digest", object->digest, NULL);
+		if (password != NULL) {
+			if (object->unique)
+				gkd_login_attach_secret (object->label, password,
+				                         "unique", object->unique, NULL);
+			password_to_pin (password, pin, pin_len);
+			return TRUE;
+		}
+	}
+
+	/* Build up the prompt */
+	prompt = gkd_prompt_new ();
+	gkd_prompt_show_widget (prompt, "password_area");
+	gkd_prompt_hide_widget (prompt, "confirm_area");
+	gkd_prompt_hide_widget (prompt, "original_area");
+	gkd_prompt_set_title (prompt, prepare_specific_title (object->klass));
+	gkd_prompt_set_primary_text (prompt, prepare_specific_primary (object->klass));
+
+	secondary = prepare_specific_secondary (object->klass, object->label);
+	gkd_prompt_set_secondary_text (prompt, secondary);
+	g_free (secondary);
+
+#if 0
+	if (object->unique && gkd_login_is_usable ())
+		gkd_ask_request_set_check_option (ask, prepare_specific_check (object->klass));
+#endif
+
+	/* Prompt the user */
+	gkd_prompt_request_attention_sync (NULL, on_prompt_attention, prompt, NULL);
+
+	if (!gkd_prompt_has_response (prompt))
+		ret = FALSE;
+
+	/* Successful response */
+	else if (gkd_prompt_get_response (prompt) == GKD_RESPONSE_OK) {
+		password = gkd_prompt_get_password (prompt, "password");
+		password_to_pin (password, pin, pin_len);
+		ret = TRUE;
+
+#if 0
+		/* Store forever */
+		if (ask->checked && object->unique && object->token) {
+			gkd_login_attach_secret (object->label, ask->typed_password,
+			                         "unique", object->unique, NULL);
+		}
+#endif
+
+	/* Other failures etc... */
+	} else {
+		ret = FALSE;
+	}
+
+	g_object_unref (prompt);
+	return ret;
+}
+
+static void
+login_specific_done (CK_SESSION_HANDLE handle, CK_SESSION_INFO *info,
+                     CK_UTF8CHAR_PTR *pin, CK_ULONG *pin_len, CK_RV rv)
+{
+	AuthObject *object;
+
+	g_assert (pin);
+	g_assert (pin_len);
+
+	/* Because we should have been notified of open session */
+	object = gkd_pkcs11_data_session_lookup (info->slotID, handle);
+	g_return_if_fail (object);
+
+	switch (rv) {
+	case CKR_PIN_INCORRECT:
+	case CKR_PIN_EXPIRED:
+	case CKR_PIN_INVALID:
+	case CKR_PIN_LEN_RANGE:
+	case CKR_PIN_LOCKED:
+		if (object->unique && object->token)
+			gkd_login_remove_secret ("unique", object->unique, NULL);
+		break;
+
+	case CKR_OK:
+		gkd_pkcs11_data_session_remove (info->slotID, handle);
+		break;
+
+	default:
+		break;
+	}
+
+	egg_secure_strfree ((gchar*)*pin);
+
+	*pin = NULL;
+	*pin_len = 0;
+}
+
+
+static gboolean
+login_user_prompt (CK_SESSION_HANDLE handle, CK_TOKEN_INFO *info,
+                   CK_UTF8CHAR_PTR *pin, CK_ULONG *pin_len)
+{
+	GkdPrompt *prompt;
+	gchar *label;
+	gchar *secondary;
+	gchar *manufacturer;
+	gchar *serial;
+	const gchar *password;
+	gboolean ret = TRUE;
+
+	g_assert (info);
+	g_assert (pin);
+	g_assert (pin_len);
+
+	/*
+	 * The manufacturer and serial number together uniquely identify token
+	 * They're stored with space padded in the token info structure.
+	 */
+
+	manufacturer = g_strndup ((gchar*)info->manufacturerID, sizeof (info->manufacturerID));
+	g_strchomp (manufacturer);
+
+	serial = g_strndup ((gchar*)info->serialNumber, sizeof (info->serialNumber));
+	g_strchomp (serial);
+
+	label = g_strndup ((gchar*)info->label, sizeof (info->label));
+	g_strchomp (label);
+
+	if (gkd_login_is_usable ()) {
+
+		password = gkd_login_lookup_secret ("manufacturer", manufacturer,
+		                                    "serial-number", serial,
+		                                    NULL);
+		if (password != NULL) {
+			password_to_pin (password, pin, pin_len);
+			g_free (manufacturer);
+			g_free (serial);
+			g_free (label);
+			return TRUE;
+		}
+	}
+
+	/* Build up the prompt */
+	prompt = gkd_prompt_new ();
+	gkd_prompt_show_widget (prompt, "password_area");
+	gkd_prompt_hide_widget (prompt, "confirm_area");
+	gkd_prompt_hide_widget (prompt, "original_area");
+	gkd_prompt_set_title (prompt, _("Unlock certificate/key storage"));
+	gkd_prompt_set_primary_text (prompt, _("Enter password to unlock the certificate/key storage"));
+
+	/* TRANSLATORS: The storage is locked, and needs unlocking before the application can use it. */
+	secondary = g_strdup_printf (_("An application wants access to the certificate/key storage '%s', but it is locked"), label);
+	gkd_prompt_set_secondary_text (prompt, secondary);
+	g_free (secondary);
+
+#if 0
+	if (gkd_login_is_usable ())
+		gkd_ask_request_set_check_option (ask, _("Automatically unlock secure storage when I log in."));
+#endif
+
+	/* Prompt the user */
+	gkd_prompt_request_attention_sync (NULL, on_prompt_attention, prompt, NULL);
+
+	if (!gkd_prompt_has_response (prompt)) {
+		ret = FALSE;
+
+	/* User cancelled or failure */
+	} else if (gkd_prompt_get_response (prompt) != GKD_RESPONSE_OK) {
+		ret = FALSE;
+
+	/* Successful response */
+	} else {
+		password = gkd_prompt_get_password (prompt, "password");
+		password_to_pin (password, pin, pin_len);
+		ret = TRUE;
+#if 0
+		/* Store forever */
+		if (ask->checked) {
+			gkd_login_attach_secret (label, ask->typed_password,
+			                         "manufacturer", manufacturer,
+			                         "serial-number", serial,
+			                         NULL);
+		}
+#endif
+	}
+
+	g_free (manufacturer);
+	g_free (serial);
+	g_free (label);
+
+	g_object_unref (prompt);
+	return ret;
+}
+
+
+static void
+login_user_done (CK_SESSION_HANDLE handle, CK_TOKEN_INFO *info,
+                 CK_UTF8CHAR_PTR *pin, CK_ULONG *pin_len, CK_RV rv)
+{
+	g_assert (pin);
+	g_assert (pin_len);
+
+	switch (rv) {
+	case CKR_PIN_INCORRECT:
+	case CKR_PIN_EXPIRED:
+	case CKR_PIN_INVALID:
+	case CKR_PIN_LEN_RANGE:
+	case CKR_PIN_LOCKED:
+		clear_user_login (info);
+		break;
+	}
+
+	egg_secure_strfree ((gchar*)*pin);
+
+	*pin = NULL;
+	*pin_len = 0;
+}
+
 /* --------------------------------------------------------------------------------------
  * PKCS#11 ENTRY POINTS
  */
@@ -193,42 +667,37 @@ auth_C_Initialize (CK_VOID_PTR init_args)
 	CK_C_INITIALIZE_ARGS_PTR args = (CK_C_INITIALIZE_ARGS_PTR)init_args;
 	gboolean supplied_ok;
 	CK_RV rv;
-	
+
 	if (args) {
-		
+
 		/* ALL supplied function pointers need to have the value either NULL or non-NULL. */
 		supplied_ok = (args->CreateMutex == NULL && args->DestroyMutex == NULL &&
 		               args->LockMutex == NULL && args->UnlockMutex == NULL) ||
 		              (args->CreateMutex != NULL && args->DestroyMutex != NULL &&
 		               args->LockMutex != NULL && args->UnlockMutex != NULL);
-		
+
 		if (!supplied_ok) {
 			g_message ("invalid set of mutex calls supplied");
 			return CKR_ARGUMENTS_BAD;
 		}
-		
+
 		if (!(args->flags & CKF_LIBRARY_CANT_CREATE_OS_THREADS)) {
 			g_message ("must be able to create our own threads");
 			return CKR_NEED_TO_CREATE_THREADS;
 		}
-		
+
 		if (!(args->flags & CKF_OS_LOCKING_OK)) {
 			g_message ("must be able to use our own locking and multi-thread primitives");
 			return CKR_CANT_LOCK;
 		}
 	}
-	
+
 	rv = pkcs11_lower->C_Initialize (init_args);
-	
-	if (rv == CKR_OK) {
-		DAEMON_ENTER ();
-	
-			/* Let our auth caches/storage know we're initializing */
-			gkr_pkcs11_auth_initialized ();
-		
-		DAEMON_LEAVE ();
-	}
-	
+
+	/* Let our auth caches/storage know we're initializing */
+	if (rv == CKR_OK)
+		gkd_pkcs11_data_initialized ();
+
 	return rv;
 }
 
@@ -236,17 +705,12 @@ static CK_RV
 auth_C_Finalize (CK_VOID_PTR reserved)
 {
 	CK_RV rv;
-	
+
 	rv = (pkcs11_lower->C_Finalize) (reserved);
-	
-	if (rv == CKR_OK) {
-		DAEMON_ENTER ();
-	
-			/* Let our auth caches/storage know we're initializing */
-			gkr_pkcs11_auth_finalized ();
-		
-		DAEMON_LEAVE ();
-	}
+
+	/* Let our auth caches/storage know we're initializing */
+	if (rv == CKR_OK)
+		gkd_pkcs11_data_finalized ();
 
 	return rv;
 }
@@ -262,7 +726,7 @@ auth_C_GetFunctionList (CK_FUNCTION_LIST_PTR_PTR list)
 {
 	if (!list)
 		return CKR_ARGUMENTS_BAD;
-	*list = gkr_pkcs11_auth_get_functions ();
+	*list = gkd_pkcs11_auth_get_functions ();
 	return CKR_OK;
 }
 
@@ -313,7 +777,7 @@ auth_C_WaitForSlotEvent (CK_FLAGS flags, CK_SLOT_ID_PTR slot, CK_VOID_PTR reserv
 }
 
 static CK_RV
-auth_C_OpenSession (CK_SLOT_ID id, CK_FLAGS flags, CK_VOID_PTR user_data, 
+auth_C_OpenSession (CK_SLOT_ID id, CK_FLAGS flags, CK_VOID_PTR user_data,
                     CK_NOTIFY callback, CK_SESSION_HANDLE_PTR handle)
 {
 	CK_SESSION_INFO session_info;
@@ -321,16 +785,11 @@ auth_C_OpenSession (CK_SLOT_ID id, CK_FLAGS flags, CK_VOID_PTR user_data,
 
 	rv = (pkcs11_lower->C_OpenSession) (id, flags, user_data, callback, handle);
 	if (rv == CKR_OK) {
-		if ((pkcs11_lower->C_GetSessionInfo) (*handle, &session_info) == CKR_OK) {
-			DAEMON_ENTER ();
-
-				/* Track this session in our auth layer */
-				gkr_pkcs11_auth_session_opened (*handle, &session_info);
-
-			DAEMON_LEAVE ();
-		}
+		/* Track this session in our auth layer */
+		if ((pkcs11_lower->C_GetSessionInfo) (*handle, &session_info) == CKR_OK)
+			gkd_pkcs11_data_session_opened (session_info.slotID, *handle);
 	}
-	
+
 	return rv;
 }
 
@@ -340,38 +799,29 @@ auth_C_CloseSession (CK_SESSION_HANDLE handle)
 	gboolean have_session_info = FALSE;
 	CK_SESSION_INFO session_info;
 	CK_RV rv;
-	
-	if ((pkcs11_lower->C_GetSessionInfo) (handle, &session_info) == CKR_OK) 
+
+	if ((pkcs11_lower->C_GetSessionInfo) (handle, &session_info) == CKR_OK)
 		have_session_info = TRUE;
-	
+
 	rv = (pkcs11_lower->C_CloseSession) (handle);
-	if (rv == CKR_OK && have_session_info) {
-		DAEMON_ENTER ();
-	
-			/* Track this session closure in our auth cache/store */
-			gkr_pkcs11_auth_session_closed (handle, &session_info);
-		
-		DAEMON_LEAVE ();
-	}
-	
-	return rv; 
+
+	/* Track this session closure in our auth cache/store */
+	if (rv == CKR_OK && have_session_info)
+		gkd_pkcs11_data_session_closed (session_info.slotID, handle);
+
+	return rv;
 }
 
 static CK_RV
 auth_C_CloseAllSessions (CK_SLOT_ID id)
 {
 	CK_RV rv = (pkcs11_lower->C_CloseAllSessions) (id);
-	
-	if (rv == CKR_OK) {
-		DAEMON_ENTER ();
-	
-			/* Track this session closure in our auth cache/store */
-			gkr_pkcs11_auth_session_closed_all (id);
-		
-		DAEMON_LEAVE ();
-	}
-	
-	return rv; 
+
+	/* Track this session closure in our auth cache/store */
+	if (rv == CKR_OK)
+		gkd_pkcs11_data_session_closed_all (id);
+
+	return rv;
 }
 
 static CK_RV
@@ -399,66 +849,47 @@ auth_C_InitPIN (CK_SESSION_HANDLE handle, CK_UTF8CHAR_PTR pin, CK_ULONG n_pin)
 	CK_TOKEN_INFO token_info;
 	gboolean init_auth = FALSE;
 	CK_RV rv;
-	
+
 	/* Dig up the information we'll need, and don't prompt if protected auth path */
 	if ((pkcs11_lower->C_GetSessionInfo) (handle, &session_info) == CKR_OK &&
-	    (pkcs11_lower->C_GetTokenInfo) (session_info.slotID, &token_info) == CKR_OK && 
-	    !(token_info.flags & CKF_PROTECTED_AUTHENTICATION_PATH)) { 
-
-		DAEMON_ENTER ();
-		
-			init_auth = gkr_pkcs11_auth_init_user_prompt (handle, &token_info, &pin, &n_pin);
-
-		DAEMON_LEAVE ();
+	    (pkcs11_lower->C_GetTokenInfo) (session_info.slotID, &token_info) == CKR_OK &&
+	    !(token_info.flags & CKF_PROTECTED_AUTHENTICATION_PATH)) {
+		init_auth = init_user_prompt (handle, &token_info, &pin, &n_pin);
 	}
 
 	rv = (pkcs11_lower->C_InitPIN) (handle, pin, n_pin);
-	
-	if (init_auth) {
-		DAEMON_ENTER ();
-		
-			gkr_pkcs11_auth_init_user_done (handle, &token_info, &pin, &n_pin, rv);
-			
-		DAEMON_LEAVE ();
-	}
-	
+
+	if (init_auth)
+		init_user_done (handle, &token_info, &pin, &n_pin, rv);
+
 	return rv;
 }
 
 static CK_RV
-auth_C_SetPIN (CK_SESSION_HANDLE handle, CK_UTF8CHAR_PTR old_pin, CK_ULONG n_old_pin, 
+auth_C_SetPIN (CK_SESSION_HANDLE handle, CK_UTF8CHAR_PTR old_pin, CK_ULONG n_old_pin,
                CK_UTF8CHAR_PTR new_pin, CK_ULONG n_new_pin)
 {
 	CK_SESSION_INFO session_info;
 	CK_TOKEN_INFO token_info;
 	gboolean init_auth = FALSE;
 	CK_RV rv;
-	
+
 	/* Dig up the information we'll need, and don't prompt if protected auth path */
 	if ((pkcs11_lower->C_GetSessionInfo) (handle, &session_info) == CKR_OK &&
-	    (pkcs11_lower->C_GetTokenInfo) (session_info.slotID, &token_info) == CKR_OK && 
-	    !(token_info.flags & CKF_PROTECTED_AUTHENTICATION_PATH)) { 
-
-		DAEMON_ENTER ();
-		
-			if (!(token_info.flags & CKF_USER_PIN_INITIALIZED))
-				init_auth = gkr_pkcs11_auth_init_user_prompt (handle, &token_info, &new_pin, &n_new_pin);
-			/* TODO: Prompt for other 'change password' case */
-
-		DAEMON_LEAVE ();
+	    (pkcs11_lower->C_GetTokenInfo) (session_info.slotID, &token_info) == CKR_OK &&
+	    !(token_info.flags & CKF_PROTECTED_AUTHENTICATION_PATH)) {
+		if (!(token_info.flags & CKF_USER_PIN_INITIALIZED))
+			init_auth = init_user_prompt (handle, &token_info, &new_pin, &n_new_pin);
+		/* TODO: Prompt for other 'change password' case */
 	}
 
 	rv = (pkcs11_lower->C_SetPIN) (handle, old_pin, n_old_pin, new_pin, n_new_pin);
-	
+
 	if (init_auth) {
-		DAEMON_ENTER ();
-		
-			gkr_pkcs11_auth_init_user_done (handle, &token_info, &new_pin, &n_new_pin, rv);
-			/* TODO: Done for other case */
-			
-		DAEMON_LEAVE ();
+		init_user_done (handle, &token_info, &new_pin, &n_new_pin, rv);
+		/* TODO: Done for other case */
 	}
-	
+
 	return rv;
 }
 
@@ -488,7 +919,7 @@ auth_C_Login (CK_SESSION_HANDLE handle, CK_USER_TYPE user_type,
 
 	/* Try the login first, this allows NULL logins to be tried */
 	rv = (pkcs11_lower->C_Login) (handle, user_type, pin, pin_len);
-	
+
 	/* See if we can help the login to work */
 	if (rv != CKR_PIN_INCORRECT)
 		return rv;
@@ -500,51 +931,45 @@ auth_C_Login (CK_SESSION_HANDLE handle, CK_USER_TYPE user_type,
 		return rv;
 
 	/* If lower level is a protected authentication path, then don't bother */
-	if (token_info.flags & CKF_PROTECTED_AUTHENTICATION_PATH) 
+	if (token_info.flags & CKF_PROTECTED_AUTHENTICATION_PATH)
 		return rv;
-	
+
 	/* Loop until logged in or user cancels */
 	while (rv == CKR_PIN_INCORRECT) {
-		
-		DAEMON_ENTER ();
-			switch (user_type) {
-			case CKU_CONTEXT_SPECIFIC:
-				auth = gkr_pkcs11_auth_login_specific_prompt (handle, &session_info, &pin, &pin_len);
-				object = gkr_pkcs11_auth_login_specific_object (handle, &session_info);
-				break;
-			case CKU_USER:
-				auth = gkr_pkcs11_auth_login_user_prompt (handle, &token_info, &pin, &pin_len);
-				break;
-			default:
-				break;
-			};
-		DAEMON_LEAVE ();
-		
+		switch (user_type) {
+		case CKU_CONTEXT_SPECIFIC:
+			auth = login_specific_prompt (handle, &session_info, &pin, &pin_len, &object);
+			break;
+		case CKU_USER:
+			auth = login_user_prompt (handle, &token_info, &pin, &pin_len);
+			break;
+		default:
+			break;
+		};
+
 		if (!auth) {
 			rv = CKR_FUNCTION_CANCELED;
 			break;
 		}
-	
+
 		/* Try the login again */
-		rv = (pkcs11_lower->C_Login) (handle, user_type, pin, pin_len);	
+		rv = (pkcs11_lower->C_Login) (handle, user_type, pin, pin_len);
 
 		/* If that was successful, then we can create an authenticator object */
 		if (user_type == CKU_CONTEXT_SPECIFIC && rv == CKR_OK && object != 0)
 			auth_create_credential (handle, object, pin, pin_len);
 
 		/* Wrap things up */
-		DAEMON_ENTER ();
-			switch (user_type) {
-			case CKU_CONTEXT_SPECIFIC:
-				gkr_pkcs11_auth_login_specific_done (handle, &session_info, &pin, &pin_len, rv);
-				break;
-			case CKU_USER:
-				gkr_pkcs11_auth_login_user_done (handle, &token_info, &pin, &pin_len, rv);
-				break;
-			default:
-				break;
-			};
-		DAEMON_LEAVE ();
+		switch (user_type) {
+		case CKU_CONTEXT_SPECIFIC:
+			login_specific_done (handle, &session_info, &pin, &pin_len, rv);
+			break;
+		case CKU_USER:
+			login_user_done (handle, &token_info, &pin, &pin_len, rv);
+			break;
+		default:
+			break;
+		};
 	}
 
 	return rv;
@@ -621,21 +1046,16 @@ static CK_RV
 auth_C_EncryptInit (CK_SESSION_HANDLE handle, CK_MECHANISM_PTR mechanism,
                     CK_OBJECT_HANDLE key)
 {
-	GkrPkcs11AuthObject *object = NULL;
+	AuthObject *object = NULL;
 	CK_RV rv;
-	
+
 	rv = (pkcs11_lower->C_EncryptInit) (handle, mechanism, key);
 	if (rv == CKR_OK) {
 		object = auth_object_for_context_specific (handle, key);
-		if (object != NULL) {
-			DAEMON_ENTER ();
-					
-				gkr_pkcs11_auth_login_specific_prepare (handle, object);
-					
-			DAEMON_LEAVE ();
-		}
+		if (object != NULL)
+			login_specific_prepare (handle, object);
 	}
-	
+
 	return rv;
 }
 
@@ -675,21 +1095,16 @@ static CK_RV
 auth_C_DecryptInit (CK_SESSION_HANDLE handle, CK_MECHANISM_PTR mechanism,
                     CK_OBJECT_HANDLE key)
 {
-	GkrPkcs11AuthObject *object = NULL;
+	AuthObject *object = NULL;
 	CK_RV rv;
 
 	rv = (pkcs11_lower->C_DecryptInit) (handle, mechanism, key);
 	if (rv == CKR_OK) {
 		object = auth_object_for_context_specific (handle, key);
-		if (object != NULL) {
-			DAEMON_ENTER ();
-					
-				gkr_pkcs11_auth_login_specific_prepare (handle, object);
-					
-			DAEMON_LEAVE ();
-		}
+		if (object != NULL)
+			login_specific_prepare (handle, object);
 	}
-	
+
 	return rv;
 }
 
@@ -760,21 +1175,16 @@ static CK_RV
 auth_C_SignInit (CK_SESSION_HANDLE handle, CK_MECHANISM_PTR mechanism,
                  CK_OBJECT_HANDLE key)
 {
-	GkrPkcs11AuthObject *object = NULL;
+	AuthObject *object = NULL;
 	CK_RV rv;
 
 	rv = (pkcs11_lower->C_SignInit) (handle, mechanism, key);
 	if (rv == CKR_OK) {
 		object = auth_object_for_context_specific (handle, key);
-		if (object != NULL) {
-			DAEMON_ENTER ();
-					
-				gkr_pkcs11_auth_login_specific_prepare (handle, object);
-					
-			DAEMON_LEAVE ();
-		}
+		if (object != NULL)
+			login_specific_prepare (handle, object);
 	}
-	
+
 	return rv;
 }
 
@@ -812,26 +1222,21 @@ static CK_RV
 auth_C_SignRecoverInit (CK_SESSION_HANDLE handle, CK_MECHANISM_PTR mechanism,
                         CK_OBJECT_HANDLE key)
 {
-	GkrPkcs11AuthObject *object = NULL;
+	AuthObject *object = NULL;
 	CK_RV rv;
 
 	rv = (pkcs11_lower->C_SignRecoverInit) (handle, mechanism, key);
 	if (rv == CKR_OK) {
 		object = auth_object_for_context_specific (handle, key);
-		if (object != NULL) {
-			DAEMON_ENTER ();
-					
-				gkr_pkcs11_auth_login_specific_prepare (handle, object);
-					
-			DAEMON_LEAVE ();
-		}
+		if (object != NULL)
+			login_specific_prepare (handle, object);
 	}
-	
+
 	return rv;
 }
 
 static CK_RV
-auth_C_SignRecover (CK_SESSION_HANDLE handle, CK_BYTE_PTR data, CK_ULONG data_len, 
+auth_C_SignRecover (CK_SESSION_HANDLE handle, CK_BYTE_PTR data, CK_ULONG data_len,
                     CK_BYTE_PTR signature, CK_ULONG_PTR signature_len)
 {
 	CK_RV rv = (pkcs11_lower->C_SignRecover) (handle, data, data_len, signature, signature_len);
@@ -846,21 +1251,16 @@ static CK_RV
 auth_C_VerifyInit (CK_SESSION_HANDLE handle, CK_MECHANISM_PTR mechanism,
                    CK_OBJECT_HANDLE key)
 {
-	GkrPkcs11AuthObject *object = NULL;
+	AuthObject *object = NULL;
 	CK_RV rv;
 
 	rv = (pkcs11_lower->C_VerifyInit) (handle, mechanism, key);
 	if (rv == CKR_OK) {
 		object = auth_object_for_context_specific (handle, key);
-		if (object != NULL) {
-			DAEMON_ENTER ();
-					
-				gkr_pkcs11_auth_login_specific_prepare (handle, object);
-					
-			DAEMON_LEAVE ();
-		}
+		if (object != NULL)
+			login_specific_prepare (handle, object);
 	}
-	
+
 	return rv;
 }
 
@@ -898,19 +1298,14 @@ static CK_RV
 auth_C_VerifyRecoverInit (CK_SESSION_HANDLE handle, CK_MECHANISM_PTR mechanism,
                           CK_OBJECT_HANDLE key)
 {
-	GkrPkcs11AuthObject *object = NULL;
+	AuthObject *object = NULL;
 	CK_RV rv;
 
 	rv = (pkcs11_lower->C_VerifyRecoverInit) (handle, mechanism, key);
 	if (rv == CKR_OK) {
 		object = auth_object_for_context_specific (handle, key);
-		if (object != NULL) {
-			DAEMON_ENTER ();
-					
-				gkr_pkcs11_auth_login_specific_prepare (handle, object);
-					
-			DAEMON_LEAVE ();
-		}
+		if (object != NULL)
+			login_specific_prepare (handle, object);
 	}
 
 	return rv;
@@ -943,7 +1338,7 @@ auth_C_DigestEncryptUpdate (CK_SESSION_HANDLE handle, CK_BYTE_PTR part,
 
 static CK_RV
 auth_C_DecryptDigestUpdate (CK_SESSION_HANDLE handle, CK_BYTE_PTR enc_part,
-                            CK_ULONG enc_part_len, CK_BYTE_PTR part, 
+                            CK_ULONG enc_part_len, CK_BYTE_PTR part,
                             CK_ULONG_PTR part_len)
 {
 	CK_RV rv = (pkcs11_lower->C_DecryptDigestUpdate) (handle, enc_part, enc_part_len, part, part_len);
@@ -968,7 +1363,7 @@ auth_C_SignEncryptUpdate (CK_SESSION_HANDLE handle, CK_BYTE_PTR part,
 }
 
 static CK_RV
-auth_C_DecryptVerifyUpdate (CK_SESSION_HANDLE handle, CK_BYTE_PTR enc_part, CK_ULONG enc_part_len, 
+auth_C_DecryptVerifyUpdate (CK_SESSION_HANDLE handle, CK_BYTE_PTR enc_part, CK_ULONG enc_part_len,
                             CK_BYTE_PTR part, CK_ULONG_PTR part_len)
 {
 	CK_RV rv = (pkcs11_lower->C_DecryptVerifyUpdate) (handle, enc_part, enc_part_len, part, part_len);
@@ -981,7 +1376,7 @@ auth_C_DecryptVerifyUpdate (CK_SESSION_HANDLE handle, CK_BYTE_PTR enc_part, CK_U
 
 static CK_RV
 auth_C_GenerateKey (CK_SESSION_HANDLE handle, CK_MECHANISM_PTR mechanism,
-                    CK_ATTRIBUTE_PTR template, CK_ULONG count, 
+                    CK_ATTRIBUTE_PTR template, CK_ULONG count,
                     CK_OBJECT_HANDLE_PTR key)
 {
 	return (pkcs11_lower->C_GenerateKey) (handle, mechanism, template, count, key);
@@ -1038,10 +1433,10 @@ auth_C_GenerateRandom (CK_SESSION_HANDLE handle, CK_BYTE_PTR random_data,
  * MODULE ENTRY POINT
  */
 
-/* 
- * PKCS#11 is broken here. It states that Unix compilers automatically byte 
- * pack structures. This is wrong. GCC on Linux aligns to 4 by default. 
- * 
+/*
+ * PKCS#11 is broken here. It states that Unix compilers automatically byte
+ * pack structures. This is wrong. GCC on Linux aligns to 4 by default.
+ *
  * This results in incompatibilities. Where this structure's first version
  * members take up too much or too little space depending on how this module
  * is compiled.
@@ -1120,16 +1515,15 @@ static CK_FUNCTION_LIST auth_function_list = {
 };
 
 CK_FUNCTION_LIST_PTR
-gkr_pkcs11_auth_get_functions (void)
+gkd_pkcs11_auth_get_functions (void)
 {
-	return &auth_function_list;	
+	return &auth_function_list;
 }
 
 void
-gkr_pkcs11_auth_chain_functions (CK_FUNCTION_LIST_PTR funcs)
+gkd_pkcs11_auth_chain_functions (CK_FUNCTION_LIST_PTR funcs)
 {
 	g_assert (funcs);
 	g_assert (!pkcs11_lower);
 	pkcs11_lower = funcs;
 }
-
diff --git a/daemon/pkcs11/gkr-pkcs11-daemon.h b/daemon/pkcs11/gkd-pkcs11-auth.h
similarity index 58%
copy from daemon/pkcs11/gkr-pkcs11-daemon.h
copy to daemon/pkcs11/gkd-pkcs11-auth.h
index 8f8f83e..d7edd3d 100644
--- a/daemon/pkcs11/gkr-pkcs11-daemon.h
+++ b/daemon/pkcs11/gkd-pkcs11-auth.h
@@ -1,39 +1,33 @@
-/* 
+/*
  * gnome-keyring
- * 
+ *
  * Copyright (C) 2008 Stefan Walter
- * 
- * This program is free software; you can redistribute it and/or modify 
+ *
+ * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU Lesser General  License as
  * published by the Free Software Foundation; either version 2.1 of
  * the License, or (at your option) any later version.
- *  
+ *
  * This program is distributed in the hope that it will be useful, but
  * WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General  License for more details.
- *  
- * You should have received a copy of the GNU Lesser General 
+ *
+ * You should have received a copy of the GNU Lesser General
  * License along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.  
+ * 02111-1307, USA.
  */
 
-#ifndef GKRPKCS11DAEMON_H_
-#define GKRPKCS11DAEMON_H_
+#ifndef GKD_PKCS11_AUTH_H_
+#define GKD_PKCS11_AUTH_H_
 
 #include <glib.h>
 
 #include "pkcs11/pkcs11.h"
 
-gboolean      gkr_pkcs11_daemon_initialize       (void);
+void                            gkd_pkcs11_auth_chain_functions          (CK_FUNCTION_LIST_PTR funcs);
 
-gboolean      gkr_pkcs11_daemon_startup_pkcs11   (void);
+CK_FUNCTION_LIST_PTR            gkd_pkcs11_auth_get_functions            (void);
 
-gboolean      gkr_pkcs11_daemon_startup_ssh      (void);
-
-CK_FUNCTION_LIST_PTR   gkr_pkcs11_daemon_get_functions    (void);
-
-CK_FUNCTION_LIST_PTR   gkr_pkcs11_daemon_get_base_functions    (void);
-
-#endif /* GKRPKCS11DAEMON_H_ */
+#endif /* GKD_PKCS11_AUTH_H_ */
diff --git a/daemon/pkcs11/gkd-pkcs11-data.c b/daemon/pkcs11/gkd-pkcs11-data.c
new file mode 100644
index 0000000..17f3d55
--- /dev/null
+++ b/daemon/pkcs11/gkd-pkcs11-data.c
@@ -0,0 +1,263 @@
+/*
+ * gnome-keyring
+ *
+ * Copyright (C) 2008 Stefan Walter
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General  License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General  License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include "gkd-pkcs11-data.h"
+
+#include "egg/egg-cleanup.h"
+#include "egg/egg-secure-memory.h"
+
+#include "login/gkd-login.h"
+
+#include "pkcs11/pkcs11.h"
+
+#include "prompt/gkd-prompt.h"
+
+#include <glib.h>
+#include <glib/gi18n.h>
+
+#include <unistd.h>
+
+/*
+ * THREADING INFO: These functions are called from multiple threads. All gkd_pkcs11_data_*()
+ * functions here with the exception of gkd_pkcs11_data_free_object() are locked. Again with
+ * the exception of gkd_pkcs11_data_free_object() they must not be called from one another.
+ */
+
+typedef struct _SlotData {
+	gint open_sessions;
+	GHashTable *session_to_data;
+} SlotData;
+
+typedef struct _SessionData {
+	gpointer user_data;
+	GDestroyNotify destroy_func;
+} SessionData;
+
+/* A hash table of CK_SLOT_ID_PTR to SlotData */
+static GHashTable *per_slot_data = NULL;
+G_LOCK_DEFINE_STATIC (pkcs11_data);
+
+static void
+free_slot_data (gpointer data)
+{
+	SlotData *sdata = data;
+	g_assert (sdata);
+	if (sdata->session_to_data)
+		g_hash_table_destroy (sdata->session_to_data);
+	g_slice_free (SlotData, sdata);
+}
+
+static void
+free_session_data (gpointer data)
+{
+	SessionData *sdata = data;
+	g_assert (sdata);
+	if (sdata->destroy_func && sdata->user_data)
+		(sdata->destroy_func) (sdata->user_data);
+	g_slice_free (SessionData, sdata);
+}
+
+static gulong*
+ulong_alloc (CK_ULONG value)
+{
+	return g_slice_dup (CK_ULONG, &value);
+}
+
+static void
+ulong_free (gpointer ptr_to_ulong)
+{
+	g_slice_free (CK_ULONG, ptr_to_ulong);
+}
+
+static guint
+ulong_hash (gconstpointer v)
+{
+	const signed char *p = v;
+	guint32 i, h = *p;
+	for(i = 0; i < sizeof (CK_ULONG); ++i)
+		h = (h << 5) - h + *(p++);
+	return h;
+}
+
+static gboolean
+ulong_equal (gconstpointer v1, gconstpointer v2)
+{
+	return *((const CK_ULONG*)v1) == *((const CK_ULONG*)v2);
+}
+
+static void
+store_data_unlocked (CK_SLOT_ID slot_id, CK_SESSION_HANDLE handle,
+                     gpointer data, GDestroyNotify destroy_func)
+{
+	SessionData *sdata;
+	SlotData *slot;
+
+	/* Because we should have been notified when a session was opened */
+	g_return_if_fail (per_slot_data);
+
+	slot = g_hash_table_lookup (per_slot_data, &slot_id);
+	g_return_if_fail (slot);
+
+	/* Delayed allocation because we may never use this on a slot */
+	if (slot->session_to_data == NULL)
+		slot->session_to_data = g_hash_table_new_full (ulong_hash, ulong_equal, ulong_free, free_session_data);
+
+	sdata = g_slice_new0 (SessionData);
+	sdata->user_data = data;
+	sdata->destroy_func = destroy_func;
+	g_hash_table_replace (slot->session_to_data, ulong_alloc (handle), sdata);
+}
+
+void
+gkd_pkcs11_data_session_store (CK_SLOT_ID slot_id, CK_SESSION_HANDLE handle,
+                               gpointer data, GDestroyNotify destroy_func)
+{
+	G_LOCK(pkcs11_data);
+	store_data_unlocked (slot_id, handle, data, destroy_func);
+	G_UNLOCK (pkcs11_data);
+}
+
+static gpointer
+lookup_data_unlocked (CK_SLOT_ID slot_id, CK_SESSION_HANDLE handle)
+{
+	SessionData *sdata;
+	SlotData *slot;
+
+	/* Because we should have been notified of open session */
+	g_return_val_if_fail (per_slot_data, FALSE);
+
+	/* Lookup the structure for this slot */
+	slot = g_hash_table_lookup (per_slot_data, &slot_id);
+	if (slot == NULL || slot->session_to_data == NULL)
+		return NULL;
+
+	sdata = g_hash_table_lookup (slot->session_to_data, &handle);
+	if (sdata == NULL)
+		return NULL;
+
+	return sdata->user_data;
+}
+
+gpointer
+gkd_pkcs11_data_session_lookup (CK_SLOT_ID slot_id, CK_SESSION_HANDLE handle)
+{
+	gpointer ret;
+	G_LOCK (pkcs11_data);
+	ret = lookup_data_unlocked (slot_id, handle);
+	G_UNLOCK (pkcs11_data);
+	return ret;
+}
+
+static void
+remove_data_unlocked (CK_SLOT_ID slot_id, CK_SESSION_HANDLE handle)
+{
+	SlotData *slot;
+
+	/* Because we should have been notified of open session */
+	g_return_if_fail (per_slot_data);
+
+	slot = g_hash_table_lookup (per_slot_data, &slot_id);
+	g_assert (slot != NULL && slot->session_to_data != NULL);
+
+	g_hash_table_remove (slot->session_to_data, &handle);
+}
+
+void
+gkd_pkcs11_data_session_remove (CK_SLOT_ID slot_id, CK_SESSION_HANDLE handle)
+{
+	G_LOCK (pkcs11_data);
+	remove_data_unlocked (slot_id, handle);
+	G_UNLOCK (pkcs11_data);
+}
+
+void
+gkd_pkcs11_data_initialized (void)
+{
+	G_LOCK (pkcs11_data);
+	g_warn_if_fail (!per_slot_data);
+	per_slot_data = g_hash_table_new_full (ulong_hash, ulong_equal, ulong_free,
+	                                       (GDestroyNotify)free_slot_data);
+	G_UNLOCK (pkcs11_data);
+}
+
+void
+gkd_pkcs11_data_session_opened (CK_SLOT_ID slot_id, CK_SESSION_HANDLE handle)
+{
+	SlotData *slot;
+
+	G_LOCK (pkcs11_data);
+
+	slot = g_hash_table_lookup (per_slot_data, &slot_id);
+	if (slot == NULL) {
+		slot = g_slice_new0 (SlotData);
+		g_hash_table_replace (per_slot_data, ulong_alloc (slot_id), slot);
+	}
+
+	/* Track how many open sessions there are */
+	++slot->open_sessions;
+
+	G_UNLOCK (pkcs11_data);
+}
+
+void
+gkd_pkcs11_data_session_closed (CK_SLOT_ID slot_id, CK_SESSION_HANDLE handle)
+{
+	SlotData *slot;
+
+	G_LOCK (pkcs11_data);
+
+	g_warn_if_fail (per_slot_data);
+
+	slot = g_hash_table_lookup (per_slot_data, &slot_id);
+	g_warn_if_fail (slot);
+	g_assert (slot->open_sessions > 0);
+
+	/* Track how many open sessions there are */
+	--(slot->open_sessions);
+	if (slot->open_sessions == 0)
+		g_hash_table_remove (per_slot_data, &slot_id);
+
+	G_UNLOCK (pkcs11_data);
+}
+
+void
+gkd_pkcs11_data_session_closed_all (CK_SLOT_ID id)
+{
+	G_LOCK (pkcs11_data);
+
+	/* Remove all information about this slot */
+	g_warn_if_fail (per_slot_data);
+	g_hash_table_remove (per_slot_data, &id);
+
+	G_UNLOCK (pkcs11_data);
+}
+
+void
+gkd_pkcs11_data_finalized (void)
+{
+	G_LOCK (pkcs11_data);
+	g_warn_if_fail (per_slot_data);
+	g_hash_table_destroy (per_slot_data);
+	per_slot_data = NULL;
+	G_UNLOCK (pkcs11_data);
+}
diff --git a/daemon/pkcs11/gkd-pkcs11-data.h b/daemon/pkcs11/gkd-pkcs11-data.h
new file mode 100644
index 0000000..0d22a7a
--- /dev/null
+++ b/daemon/pkcs11/gkd-pkcs11-data.h
@@ -0,0 +1,52 @@
+/*
+ * gnome-keyring
+ *
+ * Copyright (C) 2008 Stefan Walter
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General  License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General  License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef GKD_PKCS11_DATA_H_
+#define GKD_PKCS11_DATA_H_
+
+#include <glib.h>
+
+#include "pkcs11/pkcs11.h"
+
+void                            gkd_pkcs11_data_initialized              (void);
+
+void                            gkd_pkcs11_data_session_opened           (CK_SLOT_ID slot_id,
+                                                                          CK_SESSION_HANDLE handle);
+
+void                            gkd_pkcs11_data_session_closed           (CK_SLOT_ID slot_id,
+                                                                          CK_SESSION_HANDLE handle);
+
+void                            gkd_pkcs11_data_session_closed_all       (CK_SLOT_ID slot);
+
+void                            gkd_pkcs11_data_finalized                (void);
+
+void                            gkd_pkcs11_data_session_store            (CK_SLOT_ID slot_id,
+                                                                          CK_SESSION_HANDLE handle,
+                                                                          gpointer data,
+                                                                          GDestroyNotify destroy_func);
+
+gpointer                        gkd_pkcs11_data_session_lookup            (CK_SLOT_ID slot_id,
+                                                                           CK_SESSION_HANDLE handle);
+
+void                            gkd_pkcs11_data_session_remove            (CK_SLOT_ID slot_id,
+                                                                           CK_SESSION_HANDLE handle);
+
+#endif /* GKD_PKCS11_DATA_H_ */
diff --git a/daemon/pkcs11/gkr-pkcs11-daemon.c b/daemon/pkcs11/gkd-pkcs11.c
similarity index 54%
rename from daemon/pkcs11/gkr-pkcs11-daemon.c
rename to daemon/pkcs11/gkd-pkcs11.c
index 4850fb7..8009e8f 100644
--- a/daemon/pkcs11/gkr-pkcs11-daemon.c
+++ b/daemon/pkcs11/gkd-pkcs11.c
@@ -1,29 +1,29 @@
-/* 
+/*
  * gnome-keyring
- * 
+ *
  * Copyright (C) 2008 Stefan Walter
- * 
- * This program is free software; you can redistribute it and/or modify 
+ *
+ * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU Lesser General  License as
  * published by the Free Software Foundation; either version 2.1 of
  * the License, or (at your option) any later version.
- *  
+ *
  * This program is distributed in the hope that it will be useful, but
  * WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General  License for more details.
- *  
- * You should have received a copy of the GNU Lesser General 
+ *
+ * You should have received a copy of the GNU Lesser General
  * License along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.  
+ * 02111-1307, USA.
  */
 
 #include "config.h"
 
 #include "gkd-util.h"
-#include "gkr-pkcs11-auth.h"
-#include "gkr-pkcs11-daemon.h"
+#include "gkd-pkcs11-auth.h"
+#include "gkd-pkcs11.h"
 
 #include "pkcs11/plex-layer/gck-plex-layer.h"
 #include "pkcs11/roots-store/gck-roots-store.h"
@@ -33,22 +33,8 @@
 #include "pkcs11/ssh-store/gck-ssh-store.h"
 #include "pkcs11/user-store/gck-user-store.h"
 
-#include "daemon/util/gkr-daemon-async.h"
-
 #include "egg/egg-cleanup.h"
 
-/*
- * ALL calls into PKCS#11 and anything starting with 'gck'
- * must be concurrent. That is must UNLOCK the demon lock, 
- * perform the call and then relock. 
- * 
- * 	gkr_daemon_async_begin_concurrent ();
- *	
- *		gck_call_xxxx (xxx);
- *	
- *	gkr_daemon_async_end_concurrent ();
- */
-
 /* The top level of our internal PKCS#11 module stack */
 static CK_FUNCTION_LIST_PTR pkcs11_roof = NULL;
 static CK_FUNCTION_LIST_PTR pkcs11_base = NULL;
@@ -57,17 +43,13 @@ static void
 pkcs11_daemon_cleanup (gpointer unused)
 {
 	CK_RV rv;
-	
+
 	g_assert (pkcs11_roof);
 
-	gkr_daemon_async_begin_concurrent ();
+	gck_ssh_agent_uninitialize ();
+	gck_rpc_layer_uninitialize ();
+	rv = (pkcs11_roof->C_Finalize) (NULL);
 
-		gck_ssh_agent_uninitialize ();
-		gck_rpc_layer_uninitialize ();
-		rv = (pkcs11_roof->C_Finalize) (NULL);
-	
-	gkr_daemon_async_end_concurrent ();
-	
 	if (rv != CKR_OK)
 		g_warning ("couldn't finalize internal PKCS#11 stack (code: %d)", (gint)rv);
 
@@ -75,7 +57,7 @@ pkcs11_daemon_cleanup (gpointer unused)
 }
 
 gboolean
-gkr_pkcs11_daemon_initialize (void)
+gkd_pkcs11_initialize (void)
 {
 	CK_FUNCTION_LIST_PTR roots_store;
 	CK_FUNCTION_LIST_PTR secret_store;
@@ -84,53 +66,44 @@ gkr_pkcs11_daemon_initialize (void)
 	gboolean ret;
 	CK_RV rv;
 
-	/* Now initialize them all */
-	gkr_daemon_async_begin_concurrent ();
-
-		/* Secrets */
-		secret_store = gck_secret_store_get_functions ();
-
-		/* SSH storage */
-		ssh_store = gck_ssh_store_get_functions ();
-		
-		/* Root certificates */
-		roots_store = gck_roots_store_get_functions ();
-		
-		/* User certificates */
-		user_store = gck_user_store_get_functions ();
-		
-		/* Add all of those into the multiplexing layer */
-		gck_plex_layer_add_module (ssh_store);
+	/* Secrets */
+	secret_store = gck_secret_store_get_functions ();
+
+	/* SSH storage */
+	ssh_store = gck_ssh_store_get_functions ();
+
+	/* Root certificates */
+	roots_store = gck_roots_store_get_functions ();
+
+	/* User certificates */
+	user_store = gck_user_store_get_functions ();
+
+	/* Add all of those into the multiplexing layer */
+	gck_plex_layer_add_module (ssh_store);
 #ifdef ROOT_CERTIFICATES
-		gck_plex_layer_add_module (roots_store);
+	gck_plex_layer_add_module (roots_store);
 #endif
-		gck_plex_layer_add_module (secret_store);
-		gck_plex_layer_add_module (user_store);
+	gck_plex_layer_add_module (secret_store);
+	gck_plex_layer_add_module (user_store);
 
-		pkcs11_base = gck_plex_layer_get_functions ();
+	pkcs11_base = gck_plex_layer_get_functions ();
 
-		/* The auth component is the top component */
-		gkr_pkcs11_auth_chain_functions (pkcs11_base);
-		pkcs11_roof = gkr_pkcs11_auth_get_functions ();
-	
-		/* Initialize the whole caboodle */
-		rv = (pkcs11_roof->C_Initialize) (NULL);
+	/* The auth component is the top component */
+	gkd_pkcs11_auth_chain_functions (pkcs11_base);
+	pkcs11_roof = gkd_pkcs11_auth_get_functions ();
 
-	gkr_daemon_async_end_concurrent ();
+	/* Initialize the whole caboodle */
+	rv = (pkcs11_roof->C_Initialize) (NULL);
 
 	if (rv != CKR_OK) {
 		g_warning ("couldn't initialize internal PKCS#11 stack (code: %d)", (gint)rv);
 		return FALSE;
-	}		
-	
-	egg_cleanup_register (pkcs11_daemon_cleanup, NULL);
-
-	gkr_daemon_async_begin_concurrent ();
+	}
 
-		ret = gck_ssh_agent_initialize (pkcs11_roof) &&
-		      gck_rpc_layer_initialize (pkcs11_roof);
+	egg_cleanup_register (pkcs11_daemon_cleanup, NULL);
 
-	gkr_daemon_async_end_concurrent ();
+	ret = gck_ssh_agent_initialize (pkcs11_roof) &&
+	      gck_rpc_layer_initialize (pkcs11_roof);
 
 	return ret;
 }
@@ -138,28 +111,20 @@ gkr_pkcs11_daemon_initialize (void)
 static void
 pkcs11_rpc_cleanup (gpointer unused)
 {
-	gkr_daemon_async_begin_concurrent ();
-
-		gck_rpc_layer_shutdown ();
-
-	gkr_daemon_async_end_concurrent ();
+	gck_rpc_layer_shutdown ();
 }
 
 static gboolean
 accept_rpc_client (GIOChannel *channel, GIOCondition cond, gpointer unused)
 {
-	gkr_daemon_async_begin_concurrent ();
+	if (cond == G_IO_IN)
+		gck_rpc_layer_accept ();
 
-		if (cond == G_IO_IN)
-			gck_rpc_layer_accept ();
-		
-	gkr_daemon_async_end_concurrent ();
-	
 	return TRUE;
 }
 
 gboolean
-gkr_pkcs11_daemon_startup_pkcs11 (void)
+gkd_pkcs11_startup_pkcs11 (void)
 {
 	GIOChannel *channel;
 	const gchar *base_dir;
@@ -168,15 +133,10 @@ gkr_pkcs11_daemon_startup_pkcs11 (void)
 	base_dir = gkd_util_get_master_directory ();
 	g_return_val_if_fail (base_dir, FALSE);
 
-	gkr_daemon_async_begin_concurrent ();
-
-		sock = gck_rpc_layer_startup (base_dir);
-
-	gkr_daemon_async_end_concurrent ();
-	
+	sock = gck_rpc_layer_startup (base_dir);
 	if (sock == -1)
 		return FALSE;
-	
+
 	channel = g_io_channel_unix_new (sock);
 	g_io_add_watch (channel, G_IO_IN | G_IO_HUP, accept_rpc_client, NULL);
 	g_io_channel_unref (channel);
@@ -189,28 +149,19 @@ gkr_pkcs11_daemon_startup_pkcs11 (void)
 static void
 pkcs11_ssh_cleanup (gpointer unused)
 {
-	gkr_daemon_async_begin_concurrent ();
-
-		gck_ssh_agent_shutdown ();
-
-	gkr_daemon_async_end_concurrent ();
+	gck_ssh_agent_shutdown ();
 }
 
 static gboolean
 accept_ssh_client (GIOChannel *channel, GIOCondition cond, gpointer unused)
 {
-	gkr_daemon_async_begin_concurrent ();
-
-		if (cond == G_IO_IN)
-			gck_ssh_agent_accept ();
-		
-	gkr_daemon_async_end_concurrent ();
-				
+	if (cond == G_IO_IN)
+		gck_ssh_agent_accept ();
 	return TRUE;
 }
 
 gboolean
-gkr_pkcs11_daemon_startup_ssh (void)
+gkd_pkcs11_startup_ssh (void)
 {
 	GIOChannel *channel;
 	const gchar *base_dir;
@@ -219,19 +170,14 @@ gkr_pkcs11_daemon_startup_ssh (void)
 	base_dir = gkd_util_get_master_directory ();
 	g_return_val_if_fail (base_dir, FALSE);
 
-	gkr_daemon_async_begin_concurrent ();
-
-		sock = gck_ssh_agent_startup (base_dir);
-
-	gkr_daemon_async_end_concurrent ();
-	
+	sock = gck_ssh_agent_startup (base_dir);
 	if (sock == -1)
 		return FALSE;
-	
+
 	channel = g_io_channel_unix_new (sock);
 	g_io_add_watch (channel, G_IO_IN | G_IO_HUP, accept_ssh_client, NULL);
 	g_io_channel_unref (channel);
-	
+
 	/* gck-ssh-agent sets the environment variable */
 	gkd_util_push_environment ("SSH_AUTH_SOCK", g_getenv ("SSH_AUTH_SOCK"));
 
@@ -241,13 +187,13 @@ gkr_pkcs11_daemon_startup_ssh (void)
 }
 
 CK_FUNCTION_LIST_PTR
-gkr_pkcs11_daemon_get_functions (void)
+gkd_pkcs11_get_functions (void)
 {
 	return pkcs11_roof;
 }
 
 CK_FUNCTION_LIST_PTR
-gkr_pkcs11_daemon_get_base_functions (void)
+gkd_pkcs11_get_base_functions (void)
 {
 	return pkcs11_base;
 }
diff --git a/daemon/pkcs11/gkr-pkcs11-daemon.h b/daemon/pkcs11/gkd-pkcs11.h
similarity index 59%
rename from daemon/pkcs11/gkr-pkcs11-daemon.h
rename to daemon/pkcs11/gkd-pkcs11.h
index 8f8f83e..e597b50 100644
--- a/daemon/pkcs11/gkr-pkcs11-daemon.h
+++ b/daemon/pkcs11/gkd-pkcs11.h
@@ -1,39 +1,39 @@
-/* 
+/*
  * gnome-keyring
- * 
+ *
  * Copyright (C) 2008 Stefan Walter
- * 
- * This program is free software; you can redistribute it and/or modify 
+ *
+ * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU Lesser General  License as
  * published by the Free Software Foundation; either version 2.1 of
  * the License, or (at your option) any later version.
- *  
+ *
  * This program is distributed in the hope that it will be useful, but
  * WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General  License for more details.
- *  
- * You should have received a copy of the GNU Lesser General 
+ *
+ * You should have received a copy of the GNU Lesser General
  * License along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.  
+ * 02111-1307, USA.
  */
 
-#ifndef GKRPKCS11DAEMON_H_
-#define GKRPKCS11DAEMON_H_
+#ifndef GKD_PKCS11_H_
+#define GKD_PKCS11_H_
 
 #include <glib.h>
 
 #include "pkcs11/pkcs11.h"
 
-gboolean      gkr_pkcs11_daemon_initialize       (void);
+gboolean               gkd_pkcs11_initialize           (void);
 
-gboolean      gkr_pkcs11_daemon_startup_pkcs11   (void);
+gboolean               gkd_pkcs11_startup_pkcs11       (void);
 
-gboolean      gkr_pkcs11_daemon_startup_ssh      (void);
+gboolean               gkd_pkcs11_startup_ssh          (void);
 
-CK_FUNCTION_LIST_PTR   gkr_pkcs11_daemon_get_functions    (void);
+CK_FUNCTION_LIST_PTR   gkd_pkcs11_get_functions        (void);
 
-CK_FUNCTION_LIST_PTR   gkr_pkcs11_daemon_get_base_functions    (void);
+CK_FUNCTION_LIST_PTR   gkd_pkcs11_get_base_functions   (void);
 
-#endif /* GKRPKCS11DAEMON_H_ */
+#endif /* GKD_PKCS11_H_ */
diff --git a/daemon/prompt/Makefile.am b/daemon/prompt/Makefile.am
index c739fe2..ee4c398 100644
--- a/daemon/prompt/Makefile.am
+++ b/daemon/prompt/Makefile.am
@@ -61,11 +61,11 @@ libexec_PROGRAMS= \
 
 gnome_keyring_prompt_SOURCES = \
 	gkd-prompt-tool.c \
-	gkd-prompt-buffer.c gkd-prompt-buffer.h \
 	gkd-prompt-util.c gkd-prompt-util.h
 
 gnome_keyring_prompt_LDADD = \
 	$(top_builddir)/egg/libegg-prompt.la \
+	$(top_builddir)/egg/libegg-entry-buffer.la \
 	$(LIBGCRYPT_LIBS) \
 	$(GTK_LIBS)
 
diff --git a/daemon/prompt/gkd-prompt-tool.c b/daemon/prompt/gkd-prompt-tool.c
index 7d034f4..8fec75c 100644
--- a/daemon/prompt/gkd-prompt-tool.c
+++ b/daemon/prompt/gkd-prompt-tool.c
@@ -22,10 +22,10 @@
 
 #include "config.h"
 
-#include "gkd-prompt-buffer.h"
 #include "gkd-prompt-util.h"
 
 #include "egg/egg-dh.h"
+#include "egg/egg-entry-buffer.h"
 #include "egg/egg-libgcrypt.h"
 #include "egg/egg-secure-memory.h"
 
@@ -267,7 +267,7 @@ prepare_buttons (GtkBuilder *builder, GtkDialog *dialog)
 static void
 prepare_password_entry (GtkEntry *entry)
 {
-	GtkEntryBuffer *buffer = gkd_prompt_buffer_new ();
+	GtkEntryBuffer *buffer = egg_entry_buffer_new ();
 	g_return_if_fail (entry);
 	gtk_entry_set_buffer (entry, buffer);
 	g_object_unref (buffer);
diff --git a/daemon/prompt/gkd-prompt.c b/daemon/prompt/gkd-prompt.c
index c92aae8..999964e 100644
--- a/daemon/prompt/gkd-prompt.c
+++ b/daemon/prompt/gkd-prompt.c
@@ -577,6 +577,12 @@ gkd_prompt_class_init (GkdPromptClass *klass)
  * PUBLIC
  */
 
+GkdPrompt*
+gkd_prompt_new (void)
+{
+	return g_object_new (GKD_TYPE_PROMPT, NULL);
+}
+
 void
 gkd_prompt_set_title (GkdPrompt *self, const gchar *title)
 {
@@ -819,9 +825,11 @@ typedef struct _Attention {
 	gpointer user_data;
 	GkdPrompt *prompt;
 	gboolean active;
+	GCond *cond;
 } AttentionReq;
 
 static GHashTable *attention_reqs = NULL;
+static GStaticMutex attention_mutex = G_STATIC_MUTEX_INIT;
 
 static void
 done_attention_req (GkdPrompt *prompt, gpointer user_data)
@@ -835,6 +843,13 @@ done_attention_req (GkdPrompt *prompt, gpointer user_data)
 		att->active = FALSE;
 		next_attention_req (att->window_id);
 	}
+
+	if (att->cond) {
+		g_static_mutex_lock (&attention_mutex);
+		g_cond_broadcast (att->cond);
+		g_static_mutex_unlock (&attention_mutex);
+		att->cond = NULL;
+	}
 }
 
 static void
@@ -863,6 +878,7 @@ free_attention_req (gpointer data)
 	gchar *window_id = NULL;
 
 	if (att) {
+		att->cond = NULL;
 		if (att->destroy)
 			(att->destroy) (att->user_data);
 		if (att->prompt) {
@@ -904,7 +920,6 @@ alloc_attention_queue (void)
 	return g_queue_new ();
 }
 
-
 static void
 next_attention_req (const gchar *window_id)
 {
@@ -980,13 +995,13 @@ service_attention_req (gpointer user_data)
 	return FALSE;
 }
 
-void
-gkd_prompt_request_attention_async (const gchar *window_id, GkdPromptAttentionFunc callback,
-                                    gpointer user_data, GDestroyNotify destroy_notify)
+static AttentionReq*
+prepare_attention_req (const gchar *window_id, GkdPromptAttentionFunc callback,
+                       gpointer user_data, GDestroyNotify destroy_notify)
 {
 	AttentionReq *att;
 
-	g_return_if_fail (callback);
+	g_return_val_if_fail (callback, NULL);
 
 	if (!window_id)
 		window_id = "";
@@ -995,5 +1010,35 @@ gkd_prompt_request_attention_async (const gchar *window_id, GkdPromptAttentionFu
 	att->user_data = user_data;
 	att->destroy = destroy_notify;
 
+	return att;
+}
+
+void
+gkd_prompt_request_attention_async (const gchar *window_id, GkdPromptAttentionFunc callback,
+                                    gpointer user_data, GDestroyNotify destroy_notify)
+{
+	AttentionReq *att = prepare_attention_req (window_id, callback, user_data, destroy_notify);
+	g_return_if_fail (att);
 	g_timeout_add (0, service_attention_req, att);
 }
+
+void
+gkd_prompt_request_attention_sync (const gchar *window_id, GkdPromptAttentionFunc callback,
+                                   gpointer user_data, GDestroyNotify destroy_notify)
+{
+	AttentionReq *att = prepare_attention_req (window_id, callback, user_data, destroy_notify);
+	GCond *cond = g_cond_new ();
+
+	g_return_if_fail (att);
+	att->cond = cond;
+
+	g_static_mutex_lock (&attention_mutex);
+		g_timeout_add (0, service_attention_req, att);
+
+		/* WARNING: att may have been destroyed past this point */
+
+		g_cond_wait (cond, g_static_mutex_get_mutex (&attention_mutex));
+	g_static_mutex_unlock (&attention_mutex);
+
+	g_cond_free (cond);
+}
diff --git a/daemon/prompt/gkd-prompt.h b/daemon/prompt/gkd-prompt.h
index d3917c4..4cc8a91 100644
--- a/daemon/prompt/gkd-prompt.h
+++ b/daemon/prompt/gkd-prompt.h
@@ -58,6 +58,8 @@ struct _GkdPromptClass {
 
 GType               gkd_prompt_get_type               (void);
 
+GkdPrompt*          gkd_prompt_new                    (void);
+
 void                gkd_prompt_reset                  (GkdPrompt *prompt);
 
 void                gkd_prompt_set_title              (GkdPrompt *prompt,
@@ -117,4 +119,9 @@ void                gkd_prompt_request_attention_async    (const gchar *window_i
                                                            gpointer user_data,
                                                            GDestroyNotify destroy_notify);
 
+void                gkd_prompt_request_attention_sync     (const gchar *window_id,
+                                                           GkdPromptAttentionFunc callback,
+                                                           gpointer user_data,
+                                                           GDestroyNotify destroy_notify);
+
 #endif /* __GKD_PROMPT_H__ */
diff --git a/daemon/prompt/gkd-prompt.ui b/daemon/prompt/gkd-prompt.ui
index 0125619..5b53b90 100644
--- a/daemon/prompt/gkd-prompt.ui
+++ b/daemon/prompt/gkd-prompt.ui
@@ -69,7 +69,6 @@ An application wants access to the keyring 'xxx', but it is locked.</property>
                         <property name="spacing">6</property>
                         <child>
                           <object class="GtkHBox" id="name_area">
-                            <property name="visible">True</property>
                             <property name="spacing">6</property>
                             <child>
                               <object class="GtkLabel" id="name_label">
@@ -102,7 +101,6 @@ An application wants access to the keyring 'xxx', but it is locked.</property>
                         </child>
                         <child>
                           <object class="GtkHBox" id="original_area">
-                            <property name="visible">True</property>
                             <property name="spacing">6</property>
                             <child>
                               <object class="GtkLabel" id="original_label">
@@ -135,7 +133,6 @@ An application wants access to the keyring 'xxx', but it is locked.</property>
                         </child>
                         <child>
                           <object class="GtkHBox" id="password_area">
-                            <property name="visible">True</property>
                             <property name="spacing">6</property>
                             <child>
                               <object class="GtkLabel" id="password_label">
@@ -168,7 +165,6 @@ An application wants access to the keyring 'xxx', but it is locked.</property>
                         </child>
                         <child>
                           <object class="GtkVBox" id="confirm_area">
-                            <property name="visible">True</property>
                             <property name="orientation">vertical</property>
                             <property name="spacing">6</property>
                             <child>
@@ -255,7 +251,6 @@ An application wants access to the keyring 'xxx', but it is locked.</property>
             </child>
             <child>
               <object class="GtkExpander" id="details_area">
-                <property name="visible">True</property>
                 <property name="can_focus">True</property>
                 <child>
                   <object class="GtkAlignment" id="alignment1">
@@ -478,11 +473,11 @@ An application wants access to the keyring 'xxx', but it is locked.</property>
   </object>
   <object class="GtkSizeGroup" id="prompt_label_sizegroup">
     <widgets>
-      <widget name="name_label"/>
-      <widget name="original_label"/>
-      <widget name="password_label"/>
-      <widget name="confirm_label"/>
       <widget name="strength_label"/>
+      <widget name="confirm_label"/>
+      <widget name="password_label"/>
+      <widget name="original_label"/>
+      <widget name="name_label"/>
     </widgets>
   </object>
 </interface>
diff --git a/egg/Makefile.am b/egg/Makefile.am
index 6d5d3c8..94e8ea2 100644
--- a/egg/Makefile.am
+++ b/egg/Makefile.am
@@ -6,7 +6,7 @@ noinst_LTLIBRARIES = \
 	libegg-dbus.la \
 	libegg-secure.la \
 	libegg-prompt.la \
-	libegg-secure-entry.la
+	libegg-entry-buffer.la
 
 BUILT_SOURCES = \
 	asn1-def-pk.h asn1-def-pkix.h
@@ -53,19 +53,19 @@ DISTCLEANFILES = \
 # COMMON STUFF COMPILED INTO SMALLER COMPONENTS
  
 libegg_secure_la_SOURCES = \
- 	egg-secure-memory.c egg-secure-memory.h
+	egg-secure-memory.c egg-secure-memory.h
 
-libegg_secure_entry_la_SOURCES = \
- 	egg-secure-entry.c egg-secure-entry.h
+libegg_entry_buffer_la_SOURCES = \
+	egg-entry-buffer.c egg-entry-buffer.h
 
-libegg_secure_entry_la_CFLAGS = \
+libegg_entry_buffer_la_CFLAGS = \
 	$(GOBJECT_CFLAGS) \
 	$(GLIB_CFLAGS) \
 	$(GTK_CFLAGS)
-	
+
 libegg_buffer_la_SOURCES = \
 	egg-buffer.c egg-buffer.h 
- 	
+
 libegg_creds_la_SOURCES = \
 	egg-unix-credentials.c egg-unix-credentials.h	
 
diff --git a/daemon/prompt/gkd-prompt-buffer.c b/egg/egg-entry-buffer.c
similarity index 70%
rename from daemon/prompt/gkd-prompt-buffer.c
rename to egg/egg-entry-buffer.c
index 3e07400..afb4093 100644
--- a/daemon/prompt/gkd-prompt-buffer.c
+++ b/egg/egg-entry-buffer.c
@@ -23,16 +23,15 @@
 
 #include "config.h"
 
-#include "gkd-prompt-buffer.h"
-
-#include "egg/egg-secure-memory.h"
+#include "egg-entry-buffer.h"
+#include "egg-secure-memory.h"
 
 #include <string.h>
 
 /* Initial size of buffer, in bytes */
 #define MIN_SIZE 16
 
-struct _GkdPromptBufferPrivate
+struct _EggEntryBufferPrivate
 {
 	gchar *text;
 	gsize text_size;
@@ -40,16 +39,16 @@ struct _GkdPromptBufferPrivate
 	guint text_chars;
 };
 
-G_DEFINE_TYPE (GkdPromptBuffer, gkd_prompt_buffer, GTK_TYPE_ENTRY_BUFFER);
+G_DEFINE_TYPE (EggEntryBuffer, egg_entry_buffer, GTK_TYPE_ENTRY_BUFFER);
 
 /* --------------------------------------------------------------------------------
  * SECURE IMPLEMENTATIONS OF TEXT BUFFER
  */
 
 static const gchar*
-gkd_prompt_buffer_real_get_text (GtkEntryBuffer *buffer, gsize *n_bytes)
+egg_entry_buffer_real_get_text (GtkEntryBuffer *buffer, gsize *n_bytes)
 {
-	GkdPromptBuffer *self = GKD_PROMPT_BUFFER (buffer);
+	EggEntryBuffer *self = EGG_ENTRY_BUFFER (buffer);
 	if (n_bytes)
 		*n_bytes = self->priv->text_bytes;
 	if (!self->priv->text)
@@ -58,18 +57,18 @@ gkd_prompt_buffer_real_get_text (GtkEntryBuffer *buffer, gsize *n_bytes)
 }
 
 static guint
-gkd_prompt_buffer_real_get_length (GtkEntryBuffer *buffer)
+egg_entry_buffer_real_get_length (GtkEntryBuffer *buffer)
 {
-	GkdPromptBuffer *self = GKD_PROMPT_BUFFER (buffer);
+	EggEntryBuffer *self = EGG_ENTRY_BUFFER (buffer);
 	return self->priv->text_chars;
 }
 
 static guint
-gkd_prompt_buffer_real_insert_text (GtkEntryBuffer *buffer, guint position,
+egg_entry_buffer_real_insert_text (GtkEntryBuffer *buffer, guint position,
                                     const gchar *chars, guint n_chars)
 {
-	GkdPromptBuffer *self = GKD_PROMPT_BUFFER (buffer);
-	GkdPromptBufferPrivate *pv = self->priv;
+	EggEntryBuffer *self = EGG_ENTRY_BUFFER (buffer);
+	EggEntryBufferPrivate *pv = self->priv;
 	gsize n_bytes;
 	gsize at;
 
@@ -115,10 +114,10 @@ gkd_prompt_buffer_real_insert_text (GtkEntryBuffer *buffer, guint position,
 }
 
 static guint
-gkd_prompt_buffer_real_delete_text (GtkEntryBuffer *buffer, guint position, guint n_chars)
+egg_entry_buffer_real_delete_text (GtkEntryBuffer *buffer, guint position, guint n_chars)
 {
-	GkdPromptBuffer *self = GKD_PROMPT_BUFFER (buffer);
-	GkdPromptBufferPrivate *pv = self->priv;
+	EggEntryBuffer *self = EGG_ENTRY_BUFFER (buffer);
+	EggEntryBufferPrivate *pv = self->priv;
 	gsize start, end;
 
 	if (position > pv->text_chars)
@@ -145,10 +144,10 @@ gkd_prompt_buffer_real_delete_text (GtkEntryBuffer *buffer, guint position, guin
  */
 
 static void
-gkd_prompt_buffer_init (GkdPromptBuffer *self)
+egg_entry_buffer_init (EggEntryBuffer *self)
 {
-	GkdPromptBufferPrivate *pv;
-	pv = self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GKD_TYPE_PROMPT_BUFFER, GkdPromptBufferPrivate);
+	EggEntryBufferPrivate *pv;
+	pv = self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, EGG_TYPE_ENTRY_BUFFER, EggEntryBufferPrivate);
 
 	pv->text = NULL;
 	pv->text_chars = 0;
@@ -157,10 +156,10 @@ gkd_prompt_buffer_init (GkdPromptBuffer *self)
 }
 
 static void
-gkd_prompt_buffer_finalize (GObject *obj)
+egg_entry_buffer_finalize (GObject *obj)
 {
-	GkdPromptBuffer *self = GKD_PROMPT_BUFFER (obj);
-	GkdPromptBufferPrivate *pv = self->priv;
+	EggEntryBuffer *self = EGG_ENTRY_BUFFER (obj);
+	EggEntryBufferPrivate *pv = self->priv;
 
 	if (pv->text) {
 		egg_secure_strfree (pv->text);
@@ -169,23 +168,23 @@ gkd_prompt_buffer_finalize (GObject *obj)
 		pv->text_chars = 0;
 	}
 
-	G_OBJECT_CLASS (gkd_prompt_buffer_parent_class)->finalize (obj);
+	G_OBJECT_CLASS (egg_entry_buffer_parent_class)->finalize (obj);
 }
 
 static void
-gkd_prompt_buffer_class_init (GkdPromptBufferClass *klass)
+egg_entry_buffer_class_init (EggEntryBufferClass *klass)
 {
 	GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 	GtkEntryBufferClass *buffer_class = GTK_ENTRY_BUFFER_CLASS (klass);
 
-	gobject_class->finalize = gkd_prompt_buffer_finalize;
+	gobject_class->finalize = egg_entry_buffer_finalize;
 
-	buffer_class->get_text = gkd_prompt_buffer_real_get_text;
-	buffer_class->get_length = gkd_prompt_buffer_real_get_length;
-	buffer_class->insert_text = gkd_prompt_buffer_real_insert_text;
-	buffer_class->delete_text = gkd_prompt_buffer_real_delete_text;
+	buffer_class->get_text = egg_entry_buffer_real_get_text;
+	buffer_class->get_length = egg_entry_buffer_real_get_length;
+	buffer_class->insert_text = egg_entry_buffer_real_insert_text;
+	buffer_class->delete_text = egg_entry_buffer_real_delete_text;
 
-	g_type_class_add_private (gobject_class, sizeof (GkdPromptBufferPrivate));
+	g_type_class_add_private (gobject_class, sizeof (EggEntryBufferPrivate));
 }
 
 /* --------------------------------------------------------------------------------
@@ -193,7 +192,7 @@ gkd_prompt_buffer_class_init (GkdPromptBufferClass *klass)
  */
 
 GtkEntryBuffer*
-gkd_prompt_buffer_new (void)
+egg_entry_buffer_new (void)
 {
-	return g_object_new (GKD_TYPE_PROMPT_BUFFER, NULL);
+	return g_object_new (EGG_TYPE_ENTRY_BUFFER, NULL);
 }
diff --git a/egg/egg-entry-buffer.h b/egg/egg-entry-buffer.h
new file mode 100644
index 0000000..1a7208d
--- /dev/null
+++ b/egg/egg-entry-buffer.h
@@ -0,0 +1,59 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* egg-secure-buffer.h - secure memory gtkentry buffer
+
+   Copyright (C) 2009 Stefan Walter
+
+   The Gnome Keyring Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The Gnome Keyring Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the Gnome Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.
+
+   Author: Stef Walter <stef memberwebs com>
+*/
+
+#ifndef __EGG_ENTRY_BUFFER_H__
+#define __EGG_ENTRY_BUFFER_H__
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define EGG_TYPE_ENTRY_BUFFER            (egg_entry_buffer_get_type ())
+#define EGG_ENTRY_BUFFER(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), EGG_TYPE_ENTRY_BUFFER, EggEntryBuffer))
+#define EGG_ENTRY_BUFFER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), EGG_TYPE_ENTRY_BUFFER, EggEntryBufferClass))
+#define EGG_IS_ENTRY_BUFFER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EGG_TYPE_ENTRY_BUFFER))
+#define EGG_IS_ENTRY_BUFFER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EGG_TYPE_ENTRY_BUFFER))
+#define EGG_ENTRY_BUFFER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), EGG_TYPE_ENTRY_BUFFER, EggEntryBufferClass))
+
+typedef struct _EggEntryBuffer            EggEntryBuffer;
+typedef struct _EggEntryBufferClass       EggEntryBufferClass;
+typedef struct _EggEntryBufferPrivate     EggEntryBufferPrivate;
+
+struct _EggEntryBuffer
+{
+	GtkEntryBuffer parent;
+	EggEntryBufferPrivate *priv;
+};
+
+struct _EggEntryBufferClass
+{
+	GtkEntryBufferClass parent_class;
+};
+
+GType                     egg_entry_buffer_get_type               (void) G_GNUC_CONST;
+
+GtkEntryBuffer*           egg_entry_buffer_new                    (void);
+
+G_END_DECLS
+
+#endif /* __EGG_ENTRY_BUFFER_H__ */
diff --git a/gcr/Makefile.am b/gcr/Makefile.am
index d8192e9..e46cf2b 100644
--- a/gcr/Makefile.am
+++ b/gcr/Makefile.am
@@ -63,7 +63,7 @@ libgcr_la_LDFLAGS = \
     
 libgcr_la_LIBADD = \
 	$(top_builddir)/egg/libegg.la \
-	$(top_builddir)/egg/libegg-secure-entry.la \
+	$(top_builddir)/egg/libegg-entry-buffer.la \
 	$(top_builddir)/gp11/libgp11.la \
 	$(GOBJECT_LIBS) \
 	$(GLIB_LIBS) \
diff --git a/gcr/gcr-certificate.c b/gcr/gcr-certificate.c
index d4a36bd..55abc68 100644
--- a/gcr/gcr-certificate.c
+++ b/gcr/gcr-certificate.c
@@ -262,7 +262,7 @@ gcr_certificate_get_type (void)
 /**
  * gcr_certificate_get_der_data:
  * @self: a #GcrCertificate
- * @n_length: a pointer to a location to store the size of the resulting DER data.
+ * @n_data: a pointer to a location to store the size of the resulting DER data.
  * 
  * Gets the raw DER data for an X509 certificate.
  * 
diff --git a/gcr/gcr-import-dialog.c b/gcr/gcr-import-dialog.c
index b017bd2..9fcb612 100644
--- a/gcr/gcr-import-dialog.c
+++ b/gcr/gcr-import-dialog.c
@@ -24,7 +24,7 @@
 #include "gcr-import-dialog.h"
 #include "gcr-internal.h"
 
-#include "egg/egg-secure-entry.h"
+#include "egg/egg-entry-buffer.h"
 
 enum {
 	PROP_0,
@@ -43,7 +43,7 @@ enum {
 
 struct _GcrImportDialogPrivate {
 	GtkBuilder *builder;
-	EggSecureEntry *entry;
+	GtkEntry *entry;
 	GtkWidget *button;
 	GtkComboBox *combo;
 	GtkListStore *slots;
@@ -120,8 +120,9 @@ gcr_import_dialog_constructor (GType type, guint n_props, GObjectConstructParam
 {
 	GcrImportDialog *self = GCR_IMPORT_DIALOG (G_OBJECT_CLASS (_gcr_import_dialog_parent_class)->constructor(type, n_props, props));
 	GtkCellRenderer *renderer;
+	GtkEntryBuffer *buffer;
 	GtkWidget *widget;
-	
+
 	g_return_val_if_fail (self, NULL);
 	
 	if (!gtk_builder_add_from_file (self->pv->builder, UIDIR "gcr-import-dialog.ui", NULL))
@@ -133,7 +134,9 @@ gcr_import_dialog_constructor (GType type, guint n_props, GObjectConstructParam
 	gtk_container_add (GTK_CONTAINER (GTK_DIALOG (self)->vbox), widget);
 
 	/* Add a secure entry */
-	self->pv->entry = EGG_SECURE_ENTRY (egg_secure_entry_new ());
+	buffer = egg_entry_buffer_new ();
+	self->pv->entry = GTK_ENTRY (gtk_entry_new_with_buffer (buffer));
+	g_object_unref (buffer);
 	widget = GTK_WIDGET (gtk_builder_get_object (self->pv->builder, "password-area"));
 	gtk_container_add (GTK_CONTAINER (widget), GTK_WIDGET (self->pv->entry));
 	gtk_widget_show (GTK_WIDGET (self->pv->entry));
@@ -384,7 +387,7 @@ const gchar*
 _gcr_import_dialog_get_password (GcrImportDialog *self)
 {
 	g_return_val_if_fail (GCR_IS_IMPORT_DIALOG (self), NULL);
-	return egg_secure_entry_get_text (self->pv->entry);
+	return gtk_entry_get_text (self->pv->entry);
 }
 
 void
@@ -393,7 +396,7 @@ _gcr_import_dialog_set_password (GcrImportDialog *self, const gchar *password)
 	g_return_if_fail (GCR_IS_IMPORT_DIALOG (self));
 	if (password == NULL)
 		password = "";
-	egg_secure_entry_set_text (self->pv->entry, password);
+	gtk_entry_set_text (self->pv->entry, password);
 }
 
 void



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]