[gnome-keyring] Prompting for creation of credentials in wrap layer.



commit bf0d4ea4f4ef51d95238bf30d3a434203319987c
Author: Stef Walter <stef memberwebs com>
Date:   Sat Jun 5 22:44:35 2010 +0000

    Prompting for creation of credentials in wrap layer.
    
     * Not yet tested.
     * Not yet used by Secret Service API.

 Makefile.am                         |    2 +-
 daemon/dbus/gkd-secret-iface.c      |   59 +++
 daemon/dbus/gkd-secret-iface.h      |   45 +++
 daemon/dbus/gkd-secret-unlock.c     |    4 +
 daemon/pkcs11/gkd-pkcs11-auth.c     |   10 +-
 pkcs11/gkm/gkm-util.c               |  100 +++++
 pkcs11/gkm/gkm-util.h               |    2 +
 pkcs11/wrap-layer/Makefile.am       |    7 +-
 pkcs11/wrap-layer/gkm-wrap-layer.c  |   70 ++++-
 pkcs11/wrap-layer/gkm-wrap-prompt.c |  688 +++++++++++++++++++++++++++++++++++
 pkcs11/wrap-layer/gkm-wrap-prompt.h |   63 ++++
 ui/gku-prompt.c                     |   53 +--
 ui/gku-prompt.h                     |   16 +-
 13 files changed, 1068 insertions(+), 51 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index ef22bc7..7805792 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -15,8 +15,8 @@ SUBDIRS = \
 	gp11 \
 	egg \
 	gcr \
-	pkcs11 \
 	ui \
+	pkcs11 \
 	daemon \
 	tool \
 	$(TESTS_DIR) \
diff --git a/daemon/dbus/gkd-secret-iface.c b/daemon/dbus/gkd-secret-iface.c
new file mode 100644
index 0000000..de52c49
--- /dev/null
+++ b/daemon/dbus/gkd-secret-iface.c
@@ -0,0 +1,59 @@
+/*
+ * 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 Public 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 Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include "gkm-zzz.h"
+
+static void
+gkm_zzz_base_init (gpointer gobject_class)
+{
+	static gboolean initialized = FALSE;
+	if (!initialized) {
+		/* Add properties and signals to the interface */
+
+
+		initialized = TRUE;
+	}
+}
+
+GType
+gkm_zzz_get_type (void)
+{
+	static GType type = 0;
+	if (!type) {
+		static const GTypeInfo info = {
+			sizeof (GkmZzzIFace),
+			gkm_zzz_base_init,               /* base init */
+			NULL,             /* base finalize */
+			NULL,             /* class_init */
+			NULL,             /* class finalize */
+			NULL,             /* class data */
+			0,
+			0,                /* n_preallocs */
+			NULL,             /* instance init */
+		};
+		type = g_type_register_static (G_TYPE_INTERFACE, "GkmZzzIFace", &info, 0);
+		g_type_interface_add_prerequisite (type, G_TYPE_OBJECT);
+	}
+
+	return type;
+}
diff --git a/daemon/dbus/gkd-secret-iface.h b/daemon/dbus/gkd-secret-iface.h
new file mode 100644
index 0000000..60dd29f
--- /dev/null
+++ b/daemon/dbus/gkd-secret-iface.h
@@ -0,0 +1,45 @@
+/*
+ * 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 Public 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 Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef __GKR_ZZZ_H__
+#define __GKR_ZZZ_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define GKR_TYPE_ZZZ                 (gkr_zzz_get_type())
+#define GKR_ZZZ(obj)                 (G_TYPE_CHECK_INSTANCE_CAST ((obj), GKR_TYPE_ZZZ, GkrZzz))
+#define GKR_IS_ZZZ(obj)              (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GKR_TYPE_ZZZ))
+#define GKR_ZZZ_GET_INTERFACE(inst)  (G_TYPE_INSTANCE_GET_INTERFACE ((inst), GKR_TYPE_ZZZ, GkrZzzIface))
+
+typedef struct _GkrZzz      GkrZzz;
+typedef struct _GkrZzzIface GkrZzzIface;
+
+struct _GkrZzzIface {
+	GTypeInterface parent;
+};
+
+GType                  gkr_zzz_get_type                          (void) G_GNUC_CONST;
+
+G_END_DECLS
+
+#endif /* __GKR_ZZZ_H__ */
diff --git a/daemon/dbus/gkd-secret-unlock.c b/daemon/dbus/gkd-secret-unlock.c
index d7e5bcb..d86578b 100644
--- a/daemon/dbus/gkd-secret-unlock.c
+++ b/daemon/dbus/gkd-secret-unlock.c
@@ -209,7 +209,9 @@ prepare_unlock_prompt (GkdSecretUnlock *self, GP11Object *coll, gboolean first)
 	if (first) {
 		template = gp11_object_get_template (coll, CKA_G_CREDENTIAL_TEMPLATE, &error);
 		if (template) {
+#if 0
 			gku_prompt_set_unlock_options (prompt, template);
+#endif
 			gp11_attributes_unref (template);
 		} else {
 			g_warning ("couldn't get credential template for collection: %s",
@@ -318,7 +320,9 @@ authenticate_collection (GkdSecretUnlock *self, GP11Object *collection, gboolean
 	/* The various unlock options */
 	template = gp11_attributes_new ();
 	common_unlock_attributes (template, collection);
+#if 0
 	gku_prompt_get_unlock_options (GKU_PROMPT (self), template);
+#endif
 
 	/* If it's supposed to save non-transient, then we override that */
 	attr = gp11_attributes_find (template, CKA_GNOME_TRANSIENT);
diff --git a/daemon/pkcs11/gkd-pkcs11-auth.c b/daemon/pkcs11/gkd-pkcs11-auth.c
index 8809c72..912c6f5 100644
--- a/daemon/pkcs11/gkd-pkcs11-auth.c
+++ b/daemon/pkcs11/gkd-pkcs11-auth.c
@@ -268,6 +268,7 @@ init_user_prompt (CK_SESSION_HANDLE handle, CK_TOKEN_INFO *info,
 	gchar *manufacturer;
 	gchar *serial;
 	gboolean ret = TRUE;
+	gint value = 0;
 
 	g_assert (info);
 	g_assert (pin);
@@ -317,7 +318,7 @@ init_user_prompt (CK_SESSION_HANDLE handle, CK_TOKEN_INFO *info,
 	} else {
 		password = gku_prompt_get_password (prompt, "password");
 
-		if (gku_prompt_get_unlock_auto (prompt)) {
+		if (gku_prompt_get_unlock_option (prompt, GKU_UNLOCK_AUTO, &value) && value) {
 			gkd_login_attach_secret (label, password,
 			                         "manufacturer", manufacturer,
 			                         "serial-number", serial,
@@ -417,6 +418,7 @@ login_specific_prompt (CK_SESSION_HANDLE handle, CK_SESSION_INFO *info,
 	GkuPrompt *prompt;
 	gchar *secondary;
 	gboolean ret;
+	gint value = 0;
 
 	g_assert (info);
 	g_assert (pin);
@@ -481,7 +483,8 @@ login_specific_prompt (CK_SESSION_HANDLE handle, CK_SESSION_INFO *info,
 		password = gku_prompt_get_password (prompt, "password");
 
 		/* Store forever */
-		if (gku_prompt_get_unlock_auto (prompt) && object->unique && object->token) {
+		if (gku_prompt_get_unlock_option (prompt, GKU_UNLOCK_AUTO, &value) &&
+		    value && object->unique && object->token) {
 			gkd_login_attach_secret (object->label, password,
 			                         "unique", object->unique, NULL);
 		}
@@ -554,6 +557,7 @@ login_user_prompt (CK_SESSION_HANDLE handle, CK_TOKEN_INFO *info,
 	gchar *serial;
 	const gchar *password;
 	gboolean ret = TRUE;
+	gint value = 0;
 
 	g_assert (info);
 	g_assert (pin);
@@ -621,7 +625,7 @@ login_user_prompt (CK_SESSION_HANDLE handle, CK_TOKEN_INFO *info,
 		password = gku_prompt_get_password (prompt, "password");
 
 		/* Store forever */
-		if (gku_prompt_get_unlock_auto (prompt)) {
+		if (gku_prompt_get_unlock_option (prompt, GKU_UNLOCK_AUTO, &value) && value) {
 			gkd_login_attach_secret (label, password,
 			                         "manufacturer", manufacturer,
 			                         "serial-number", serial,
diff --git a/pkcs11/gkm/gkm-util.c b/pkcs11/gkm/gkm-util.c
index a1c6253..984c5ce 100644
--- a/pkcs11/gkm/gkm-util.c
+++ b/pkcs11/gkm/gkm-util.c
@@ -98,3 +98,103 @@ gkm_util_dispose_unref (gpointer object)
 	g_object_run_dispose (G_OBJECT (object));
 	g_object_unref (object);
 }
+
+const gchar*
+gkm_util_rv_to_string (CK_RV rv)
+{
+	#define GKM_X(rv) case rv: return #rv;
+	switch (rv) {
+
+	/* These are not really errors, or not current */
+	GKM_X (CKR_OK)
+	GKM_X (CKR_NO_EVENT)
+	GKM_X (CKR_FUNCTION_NOT_PARALLEL)
+	GKM_X (CKR_SESSION_PARALLEL_NOT_SUPPORTED)
+	GKM_X (CKR_CANCEL)
+	GKM_X (CKR_FUNCTION_CANCELED)
+	GKM_X (CKR_HOST_MEMORY)
+	GKM_X (CKR_SLOT_ID_INVALID)
+	GKM_X (CKR_GENERAL_ERROR)
+	GKM_X (CKR_FUNCTION_FAILED)
+	GKM_X (CKR_ARGUMENTS_BAD)
+	GKM_X (CKR_NEED_TO_CREATE_THREADS)
+	GKM_X (CKR_CANT_LOCK)
+	GKM_X (CKR_ATTRIBUTE_READ_ONLY)
+	GKM_X (CKR_ATTRIBUTE_SENSITIVE)
+	GKM_X (CKR_ATTRIBUTE_TYPE_INVALID)
+	GKM_X (CKR_ATTRIBUTE_VALUE_INVALID)
+	GKM_X (CKR_DATA_INVALID)
+	GKM_X (CKR_DATA_LEN_RANGE)
+	GKM_X (CKR_DEVICE_ERROR)
+	GKM_X (CKR_DEVICE_MEMORY)
+	GKM_X (CKR_DEVICE_REMOVED)
+	GKM_X (CKR_ENCRYPTED_DATA_INVALID)
+	GKM_X (CKR_ENCRYPTED_DATA_LEN_RANGE)
+	GKM_X (CKR_FUNCTION_NOT_SUPPORTED)
+	GKM_X (CKR_KEY_HANDLE_INVALID)
+	GKM_X (CKR_KEY_SIZE_RANGE)
+	GKM_X (CKR_KEY_TYPE_INCONSISTENT)
+	GKM_X (CKR_KEY_NOT_NEEDED)
+	GKM_X (CKR_KEY_CHANGED)
+	GKM_X (CKR_KEY_NEEDED)
+	GKM_X (CKR_KEY_INDIGESTIBLE)
+	GKM_X (CKR_KEY_FUNCTION_NOT_PERMITTED)
+	GKM_X (CKR_KEY_NOT_WRAPPABLE)
+	GKM_X (CKR_KEY_UNEXTRACTABLE)
+	GKM_X (CKR_MECHANISM_INVALID)
+	GKM_X (CKR_MECHANISM_PARAM_INVALID)
+	GKM_X (CKR_OBJECT_HANDLE_INVALID)
+	GKM_X (CKR_OPERATION_ACTIVE)
+	GKM_X (CKR_OPERATION_NOT_INITIALIZED)
+	GKM_X (CKR_PIN_INCORRECT)
+	GKM_X (CKR_PIN_INVALID)
+	GKM_X (CKR_PIN_LEN_RANGE)
+	GKM_X (CKR_PIN_EXPIRED)
+	GKM_X (CKR_PIN_LOCKED)
+	GKM_X (CKR_SESSION_CLOSED)
+	GKM_X (CKR_SESSION_COUNT)
+	GKM_X (CKR_SESSION_HANDLE_INVALID)
+	GKM_X (CKR_SESSION_READ_ONLY)
+	GKM_X (CKR_SESSION_EXISTS)
+	GKM_X (CKR_SESSION_READ_ONLY_EXISTS)
+	GKM_X (CKR_SESSION_READ_WRITE_SO_EXISTS)
+	GKM_X (CKR_SIGNATURE_INVALID)
+	GKM_X (CKR_SIGNATURE_LEN_RANGE)
+	GKM_X (CKR_TEMPLATE_INCOMPLETE)
+	GKM_X (CKR_TEMPLATE_INCONSISTENT)
+	GKM_X (CKR_TOKEN_NOT_PRESENT)
+	GKM_X (CKR_TOKEN_NOT_RECOGNIZED)
+	GKM_X (CKR_TOKEN_WRITE_PROTECTED)
+	GKM_X (CKR_UNWRAPPING_KEY_HANDLE_INVALID)
+	GKM_X (CKR_UNWRAPPING_KEY_SIZE_RANGE)
+	GKM_X (CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT)
+	GKM_X (CKR_USER_ALREADY_LOGGED_IN)
+	GKM_X (CKR_USER_NOT_LOGGED_IN)
+	GKM_X (CKR_USER_PIN_NOT_INITIALIZED)
+	GKM_X (CKR_USER_TYPE_INVALID)
+	GKM_X (CKR_USER_ANOTHER_ALREADY_LOGGED_IN)
+	GKM_X (CKR_USER_TOO_MANY_TYPES)
+	GKM_X (CKR_WRAPPED_KEY_INVALID)
+	GKM_X (CKR_WRAPPED_KEY_LEN_RANGE)
+	GKM_X (CKR_WRAPPING_KEY_HANDLE_INVALID)
+	GKM_X (CKR_WRAPPING_KEY_SIZE_RANGE)
+	GKM_X (CKR_WRAPPING_KEY_TYPE_INCONSISTENT)
+	GKM_X (CKR_RANDOM_SEED_NOT_SUPPORTED)
+	GKM_X (CKR_RANDOM_NO_RNG)
+	GKM_X (CKR_DOMAIN_PARAMS_INVALID)
+	GKM_X (CKR_BUFFER_TOO_SMALL)
+	GKM_X (CKR_SAVED_STATE_INVALID)
+	GKM_X (CKR_INFORMATION_SENSITIVE)
+	GKM_X (CKR_STATE_UNSAVEABLE)
+	GKM_X (CKR_CRYPTOKI_NOT_INITIALIZED)
+	GKM_X (CKR_CRYPTOKI_ALREADY_INITIALIZED)
+	GKM_X (CKR_MUTEX_BAD)
+	GKM_X (CKR_MUTEX_NOT_LOCKED)
+	GKM_X (CKR_FUNCTION_REJECTED)
+	default:
+		g_message ("unknown error: %lu", (gulong)rv);
+		return "CKR_?UNKNOWN?";
+	}
+
+	#undef GKM_X
+}
diff --git a/pkcs11/gkm/gkm-util.h b/pkcs11/gkm/gkm-util.h
index 1152bc8..d6ac807 100644
--- a/pkcs11/gkm/gkm-util.h
+++ b/pkcs11/gkm/gkm-util.h
@@ -49,4 +49,6 @@ CK_ULONG              gkm_util_next_handle                        (void);
 
 void                  gkm_util_dispose_unref                      (gpointer object);
 
+const gchar*          gkm_util_rv_to_string                       (CK_RV rv);
+
 #endif /* GKM_UTIL_H_ */
diff --git a/pkcs11/wrap-layer/Makefile.am b/pkcs11/wrap-layer/Makefile.am
index 436f81f..f4d3a28 100644
--- a/pkcs11/wrap-layer/Makefile.am
+++ b/pkcs11/wrap-layer/Makefile.am
@@ -4,15 +4,18 @@ noinst_LTLIBRARIES = \
 
 INCLUDES = -I. \
 	-I$(top_srcdir) \
-	-I$(top_builddir)
+	-I$(top_builddir) \
+	-I$(top_srcdir)/pkcs11
 
 # ------------------------------------------------------------------------------
 # The code
 
 libgkm_wrap_layer_la_SOURCES = \
-	gkm-wrap-layer.c gkm-wrap-layer.h
+	gkm-wrap-layer.c gkm-wrap-layer.h \
+	gkm-wrap-prompt.c gkm-wrap-prompt.h
 
 libgkm_wrap_layer_la_LIBADD = \
+	$(top_builddir)/pkcs11/gkm/libgkm.la \
 	$(GTHREAD_LIBS) \
 	$(GLIB_LIBS)
 
diff --git a/pkcs11/wrap-layer/gkm-wrap-layer.c b/pkcs11/wrap-layer/gkm-wrap-layer.c
index 558567a..bee7832 100644
--- a/pkcs11/wrap-layer/gkm-wrap-layer.c
+++ b/pkcs11/wrap-layer/gkm-wrap-layer.c
@@ -1,7 +1,7 @@
 /*
  * gnome-keyring
  *
- * Copyright (C) 2008 Stefan Walter
+ * Copyright (C) 2010 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
@@ -22,6 +22,7 @@
 #include "config.h"
 
 #include "gkm-wrap-layer.h"
+#include "gkm-wrap-prompt.h"
 
 #include "pkcs11/pkcs11.h"
 #include "pkcs11/pkcs11g.h"
@@ -569,17 +570,82 @@ wrap_C_Logout (CK_SESSION_HANDLE handle)
 	return (map.funcs->C_Logout) (handle);
 }
 
+#if 0
+static CK_RV
+wrap_C_CreateObject (CK_SESSION_HANDLE handle, CK_ATTRIBUTE_PTR template,
+                     CK_ULONG n_template, CK_OBJECT_HANDLE_PTR new_object)
+{
+	CK_ATTRIBUTE_PTR attrs = NULL;
+	CK_ULONG n_attrs;
+	Mapping map;
+	CK_RV rv;
+
+	rv = map_session_to_real (&handle, &map);
+	if (rv != CKR_OK)
+		return rv;
+
+	while (rv == CKR_OK) {
+		rv = (map.funcs->C_CreateObject) (handle,
+		                                  attrs ? attrs : template,
+		                                  attrs ? n_attrs : n_template,
+		                                  new_object);
+
+		if (attrs != NULL) {
+			if (rv == CKR_OK)
+				gkm_wrap_prompt_done_create_object (map.funcs, handle,
+				                                    attrs, n_attrs);
+			g_free (attrs);
+			attrs = NULL;
+		}
+
+		if (rv != CKR_PIN_INVALID)
+			break;
+
+		/* Only prompting for creating credentials, under certain circumstances */
+		rv = gkm_wrap_prompt_for_create_object (map.funcs, handle, template,
+		                                        n_template, &attrs, &n_attrs);
+	}
+
+	g_assert (attrs == NULL);
+	return rv;
+}
+#endif
+
 static CK_RV
 wrap_C_CreateObject (CK_SESSION_HANDLE handle, CK_ATTRIBUTE_PTR template,
                      CK_ULONG count, CK_OBJECT_HANDLE_PTR new_object)
 {
+	GkmWrapPrompt *prompt = NULL;
 	Mapping map;
 	CK_RV rv;
 
 	rv = map_session_to_real (&handle, &map);
 	if (rv != CKR_OK)
 		return rv;
-	return (map.funcs->C_CreateObject) (handle, template, count, new_object);
+
+	for (;;) {
+		rv = (map.funcs->C_CreateObject) (handle, template, count, new_object);
+
+		if (rv != CKR_PIN_INVALID)
+			break;
+
+		if (!prompt) {
+			prompt = gkm_wrap_prompt_for_credential (map.funcs, handle, template, count);
+			if (prompt == NULL)
+				break;
+		}
+
+		if (!gkm_wrap_prompt_do_credential (prompt, &template, &count))
+			break;
+	}
+
+
+	if (prompt) {
+		gkm_wrap_prompt_done_credential (prompt, rv);
+		g_object_unref (prompt);
+	}
+
+	return rv;
 }
 
 static CK_RV
diff --git a/pkcs11/wrap-layer/gkm-wrap-prompt.c b/pkcs11/wrap-layer/gkm-wrap-prompt.c
new file mode 100644
index 0000000..8e7746f
--- /dev/null
+++ b/pkcs11/wrap-layer/gkm-wrap-prompt.c
@@ -0,0 +1,688 @@
+/*
+ * gnome-keyring
+ *
+ * Copyright (C) 2010 Stefan Walter
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public 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 Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include "gkm-wrap-prompt.h"
+
+#include "egg/egg-secure-memory.h"
+
+#include "gkm/gkm-attributes.h"
+#include "gkm/gkm-util.h"
+
+#include "pkcs11/pkcs11.h"
+#include "pkcs11/pkcs11i.h"
+
+#include "ui/gku-prompt.h"
+
+#include <glib/gi18n.h>
+
+#include <string.h>
+
+struct _GkmWrapPrompt {
+	GkuPrompt parent;
+
+	CK_FUNCTION_LIST_PTR module;
+	CK_SESSION_HANDLE session;
+	CK_OBJECT_HANDLE object;
+
+	GArray *template;
+	CK_ULONG n_template;
+
+	gchar *password;
+	GQueue pool;
+};
+
+G_DEFINE_TYPE (GkmWrapPrompt, gkm_wrap_prompt, GKU_TYPE_PROMPT);
+
+/* -----------------------------------------------------------------------------
+ * INTERNAL
+ */
+
+#if 0
+static gchar*
+location_string_for_attributes (GP11Attributes *attrs)
+{
+	gchar *identifier;
+	gchar *location;
+
+	identifier = identifier_string_for_attributes (attrs);
+	if (identifier == NULL)
+		return NULL;
+
+	/*
+	 * COMPAT: Format it into a string. This is done this way for compatibility
+	 * with old gnome-keyring releases. In the future this may change.
+	 *
+	 * FYI: gp11_object_get_data() null terminates
+	 */
+	location = g_strdup_printf ("LOCAL:/keyrings/%s.keyring", (gchar*)identifier);
+	g_free (identifier);
+	return location;
+}
+
+static void
+set_warning_wrong (GkdSecretUnlock *self)
+{
+	g_assert (GKD_SECRET_IS_UNLOCK (self));
+	gku_prompt_set_warning (GKU_PROMPT (self), _("The unlock password was incorrect"));
+}
+
+static void
+attach_unlock_to_login (GP11Object *collection, GkdSecretSecret *master)
+{
+	DBusError derr = DBUS_ERROR_INIT;
+	GP11Attributes *attrs;
+	GP11Object *cred;
+	gchar *location;
+	gchar *label;
+
+	g_assert (GP11_IS_OBJECT (collection));
+
+	/* Relevant information for the unlock item */
+	attrs = attributes_for_collection (collection);
+	g_return_if_fail (attrs);
+	location = location_string_for_attributes (attrs);
+	label = label_string_for_attributes (attrs);
+	gp11_attributes_unref (attrs);
+
+	attrs = gkd_login_attach_make_attributes (label, "keyring", location, NULL);
+	g_free (location);
+	g_free (label);
+
+	cred = gkd_secret_session_create_credential (master->session, NULL, attrs, master, &derr);
+	gp11_attributes_unref (attrs);
+	g_object_unref (cred);
+
+	if (!cred) {
+		g_warning ("couldn't save unlock password in login collection: %s", derr.message);
+		dbus_error_free (&derr);
+	}
+}
+
+/* Save it to the login keyring */
+if (!transient)
+	attach_unlock_to_login (collection, master);
+
+/* Or try to use login keyring's passwords */
+} else {
+	attrs = attributes_for_collection (coll);
+	location = location_string_for_attributes (attrs);
+	gp11_attributes_unref (attrs);
+
+	if (location) {
+		password = gkd_login_lookup_secret ("keyring", location, NULL);
+		g_free (location);
+
+		if (password) {
+			if (gkd_secret_unlock_with_password (coll, NULL, 0, NULL))
+				locked = FALSE;
+			egg_secure_strfree (password);
+		}
+	}
+
+#endif
+
+static GkuPrompt*
+on_prompt_attention (gpointer user_data)
+{
+	/* We passed the prompt as the argument */
+	return g_object_ref (user_data);
+}
+
+static gpointer
+pool_alloc (GkmWrapPrompt *self, gsize length)
+{
+	gpointer memory = g_malloc0 (length);
+
+	g_assert (GKM_WRAP_IS_PROMPT (self));
+	g_queue_push_tail (&self->pool, memory);
+	return memory;
+}
+
+static gpointer
+pool_dup (GkmWrapPrompt *self, gconstpointer original, gsize length)
+{
+	gpointer memory = pool_alloc (self, length);
+	memcpy (memory, original, length);
+	return memory;
+}
+
+static CK_ATTRIBUTE_PTR
+get_unlock_options_from_object (GkmWrapPrompt *self, CK_ULONG_PTR n_options)
+{
+	CK_ATTRIBUTE_PTR options;
+	CK_ATTRIBUTE attr;
+	CK_ULONG i;
+	CK_RV rv;
+
+	g_assert (GKM_WRAP_IS_PROMPT (self));
+	g_assert (self->module);
+	g_assert (n_options);
+
+	*n_options = 0;
+
+	attr.type = CKA_G_CREDENTIAL_TEMPLATE;
+	attr.ulValueLen = 0;
+	attr.pValue = NULL;
+
+	/* Get the length of the entire template */
+	rv = (self->module->C_GetAttributeValue) (self->session, self->object, &attr, 1);
+	if (rv != CKR_OK) {
+		if (rv != CKR_ATTRIBUTE_TYPE_INVALID)
+			g_warning ("couldn't get credential template for prompt: %s",
+			           gkm_util_rv_to_string (rv));
+		return NULL;
+	}
+
+	/* Number of attributes, rounded down */
+	*n_options = (attr.ulValueLen / sizeof (CK_ATTRIBUTE));;
+	options = pool_alloc (self, attr.ulValueLen);
+
+	/* Get the size of each value */
+	rv = (self->module->C_GetAttributeValue) (self->session, self->object, &attr, 1);
+	if (rv != CKR_OK) {
+		g_warning ("couldn't read credential template for prompt: %s",
+		           gkm_util_rv_to_string (rv));
+		return NULL;
+	}
+
+	/* Allocate memory for each value */
+	for (i = 0; i < *n_options; ++i) {
+		if (options[i].ulValueLen != (CK_ULONG)-1)
+			options[i].pValue = pool_alloc (self, options[i].ulValueLen);
+	}
+
+	/* Now get the actual values */
+	rv = (self->module->C_GetAttributeValue) (self->session, self->object, &attr, 1);
+	if (rv != CKR_OK) {
+		g_warning ("couldn't retrieve credential template for prompt: %s",
+		           gkm_util_rv_to_string (rv));
+		return NULL;
+	}
+
+	return options;
+}
+
+static void
+set_unlock_options_on_object (GkmWrapPrompt *self, CK_ATTRIBUTE_PTR options, CK_ULONG n_options)
+{
+	CK_ATTRIBUTE attr;
+	CK_RV rv;
+
+	g_assert (GKM_WRAP_IS_PROMPT (self));
+	g_assert (self->module);
+	g_assert (options);
+
+	attr.type = CKA_G_CREDENTIAL_TEMPLATE;
+	attr.pValue = options;
+	attr.ulValueLen = sizeof (CK_ATTRIBUTE) * n_options;
+
+	rv = (self->module->C_SetAttributeValue) (self->session, self->object, &attr, 1);
+	if (rv != CKR_OK && rv != CKR_ATTRIBUTE_TYPE_INVALID) {
+		g_warning ("Couldn't set credential template for prompt: %s",
+		           gkm_util_rv_to_string (rv));
+	}
+}
+
+static CK_ATTRIBUTE_PTR
+get_unlock_options_from_prompt (GkmWrapPrompt *self, CK_ULONG_PTR n_options)
+{
+	CK_ATTRIBUTE_PTR options;
+	CK_BBOOL bval;
+	CK_ULONG uval;
+	gint value;
+
+	g_assert (GKM_WRAP_IS_PROMPT (self));
+	g_assert (n_options);
+
+	*n_options = 4;
+	options = pool_alloc (self, sizeof (CK_ATTRIBUTE) * (*n_options));
+
+	/* CKA_TOKEN */
+	bval = TRUE;
+	options[0].type = CKA_TOKEN;
+	options[0].pValue = pool_dup (self, &bval, sizeof (bval));
+	options[0].ulValueLen = sizeof (bval);
+
+	/* CKA_GNOME_TRANSIENT */
+	bval = TRUE;
+	options[1].type = CKA_GNOME_TRANSIENT;
+	options[1].pValue = pool_dup (self, &bval, sizeof (bval));
+	options[1].ulValueLen = sizeof (bval);
+
+	/* CKA_G_DESTRUCT_IDLE */
+	value = 0;
+	gku_prompt_get_unlock_option (GKU_PROMPT (self), GKU_UNLOCK_IDLE, &value);
+	uval = value < 0 ? 0 : value;
+	options[2].type = CKA_G_DESTRUCT_IDLE;
+	options[2].pValue = pool_dup (self, &uval, sizeof (uval));
+	options[2].ulValueLen = sizeof (uval);
+
+	/* CKA_G_DESTRUCT_AFTER */
+	value = 0;
+	gku_prompt_get_unlock_option (GKU_PROMPT (self), GKU_UNLOCK_TIMEOUT, &value);
+	uval = value < 0 ? 0 : value;
+	options[3].type = CKA_G_DESTRUCT_AFTER;
+	options[3].pValue = pool_dup (self, &uval, sizeof (uval));
+	options[3].ulValueLen = sizeof (uval);
+
+	return options;
+}
+
+static void
+set_unlock_options_on_prompt (GkmWrapPrompt *self, CK_ATTRIBUTE_PTR options, CK_ULONG n_options)
+{
+	gboolean bval;
+	gulong uval;
+
+	g_assert (GKM_WRAP_IS_PROMPT (self));
+	g_assert (options || !n_options);
+
+	if (gkm_attributes_find_boolean (options, n_options, CKA_GNOME_TRANSIENT, &bval))
+		gku_prompt_set_unlock_option (GKU_PROMPT (self), GKU_UNLOCK_AUTO, bval ? 0 : 1);
+
+	if (gkm_attributes_find_ulong (options, n_options, CKA_G_DESTRUCT_IDLE, &uval))
+		gku_prompt_set_unlock_option (GKU_PROMPT (self), GKU_UNLOCK_IDLE, (int)uval);
+
+	if (gkm_attributes_find_ulong (options, n_options, CKA_G_DESTRUCT_AFTER, &uval))
+		gku_prompt_set_unlock_option (GKU_PROMPT (self), GKU_UNLOCK_TIMEOUT, (int)uval);
+}
+
+static CK_ATTRIBUTE_PTR
+get_attributes_from_object (GkmWrapPrompt *self, CK_ULONG *n_attrs)
+{
+	CK_ATTRIBUTE attrs[3];
+	CK_ULONG i, count = 3;
+	CK_RV rv;
+
+	g_assert (GKM_WRAP_IS_PROMPT (self));
+	g_assert (n_attrs);
+	g_assert (self->module);
+
+	memset (attrs, 0, sizeof (attrs));
+	attrs[0].type = CKA_LABEL;
+	attrs[1].type = CKA_ID;
+	attrs[2].type = CKA_CLASS;
+
+	rv = (self->module->C_GetAttributeValue) (self->session, self->object, attrs, count);
+	if (rv != CKR_OK && rv != CKR_ATTRIBUTE_TYPE_INVALID) {
+		g_warning ("Couldn't retrieve information about object to unlock: %s",
+		           gkm_util_rv_to_string (rv));
+		return NULL;
+	}
+
+	/* Allocate for each value, note we're null terminating values */
+	for (i = 0; i < count; ++i) {
+		if (attrs[i].ulValueLen != (CK_ULONG)-1)
+			attrs[i].pValue = pool_alloc (self, attrs[i].ulValueLen + 1);
+	}
+
+	/* Now get the actual values */
+	rv = (self->module->C_GetAttributeValue) (self->session, self->object, attrs, count);
+	if (rv != CKR_OK && rv != CKR_ATTRIBUTE_TYPE_INVALID) {
+		g_warning ("couldn't retrieve credential template for prompt: %s",
+		           gkm_util_rv_to_string (rv));
+		return NULL;
+	}
+
+	*n_attrs = count;
+	return pool_dup (self, attrs, sizeof (attrs));
+
+}
+
+static void
+prepare_unlock_login_keyring (GkmWrapPrompt *self)
+{
+	GkuPrompt *prompt;
+	const gchar *text;
+
+	g_assert (GKM_WRAP_IS_PROMPT (self));
+
+	prompt = GKU_PROMPT (self);
+
+	gku_prompt_set_title (prompt, _("Unlock Login Keyring"));
+
+	text = _("Enter password for to unlock your login keyring");
+	gku_prompt_set_primary_text (prompt, text);
+
+#if 0
+	/* TODO: Reimplement this */
+	if (gkd_login_did_unlock_fail ())
+		text = _("The password you use to log in to your computer no longer matches that of your login keyring.");
+	else
+#endif
+		text = _("The login keyring did not get unlocked when you logged into your computer.");
+	gku_prompt_set_secondary_text (prompt, text);
+
+	gku_prompt_hide_widget (prompt, "name_area");
+	gku_prompt_hide_widget (prompt, "confirm_area");
+	gku_prompt_show_widget (prompt, "password_area");
+}
+
+
+
+static void
+prepare_unlock_other_keyring (GkmWrapPrompt *self, const gchar *label)
+{
+	GkuPrompt *prompt;
+	gchar *text;
+
+	g_assert (GKM_WRAP_IS_PROMPT (self));
+
+	prompt = GKU_PROMPT (self);
+
+	gku_prompt_set_title (prompt, _("Unlock Keyring"));
+
+	text = g_markup_printf_escaped (_("Enter password for keyring '%s' to unlock"), label);
+	gku_prompt_set_primary_text (prompt, text);
+	g_free (text);
+
+	text = g_markup_printf_escaped (_("An application wants access to the keyring '%s', but it is locked"), label);
+	gku_prompt_set_secondary_text (prompt, text);
+	g_free (text);
+
+	gku_prompt_hide_widget (prompt, "name_area");
+	gku_prompt_hide_widget (prompt, "confirm_area");
+	gku_prompt_show_widget (prompt, "details_area");
+	gku_prompt_show_widget (prompt, "password_area");
+	gku_prompt_show_widget (prompt, "lock_area");
+	gku_prompt_show_widget (prompt, "options_area");
+
+#if 0 /* TODO: Implement */
+	if (gkd_login_is_usable ())
+		gku_prompt_show_widget (prompt, "auto_unlock_check");
+	else
+#endif
+		gku_prompt_hide_widget (prompt, "auto_unlock_check");
+}
+
+static void
+prepare_unlock_other_object (GkmWrapPrompt *self, const gchar *label)
+{
+	GkuPrompt *prompt;
+	gchar *text;
+
+	g_assert (GKM_WRAP_IS_PROMPT (self));
+
+	prompt = GKU_PROMPT (self);
+
+	gku_prompt_set_title (prompt, _("Unlock"));
+
+	text = g_markup_printf_escaped (_("Enter password for '%s' to unlock"), label);
+	gku_prompt_set_primary_text (prompt, text);
+	g_free (text);
+
+	text = g_markup_printf_escaped (_("An application wants access to '%s', but it is locked"), label);
+	gku_prompt_set_secondary_text (prompt, text);
+	g_free (text);
+
+	gku_prompt_hide_widget (prompt, "name_area");
+	gku_prompt_hide_widget (prompt, "confirm_area");
+	gku_prompt_show_widget (prompt, "details_area");
+	gku_prompt_show_widget (prompt, "password_area");
+	gku_prompt_show_widget (prompt, "lock_area");
+	gku_prompt_show_widget (prompt, "options_area");
+	gku_prompt_hide_widget (prompt, "auto_unlock_check");
+}
+
+static void
+prepare_unlock_prompt (GkmWrapPrompt *self, gboolean first)
+{
+	CK_ATTRIBUTE_PTR attrs;
+	CK_ATTRIBUTE_PTR attr;
+	CK_ULONG n_attrs;
+	GkuPrompt *prompt;
+	const gchar *label = NULL;
+	CK_OBJECT_CLASS klass;
+
+	g_assert (GKM_WRAP_IS_PROMPT (self));
+
+	prompt = GKU_PROMPT (self);
+
+	/* Hard reset on first prompt, soft on later */
+	gku_prompt_reset (GKU_PROMPT (prompt), first);
+
+	/* Load up all the values, note they're null terminated */
+	attrs = get_attributes_from_object (self, &n_attrs);
+	g_return_if_fail (attrs);
+
+	/* Load up the object class */
+	if (!gkm_attributes_find_ulong (attrs, n_attrs, CKA_CLASS, &klass))
+		klass = (CK_ULONG)-1;
+
+	/* Load up its label */
+	attr = gkm_attributes_find (attrs, n_attrs, CKA_LABEL);
+	if (attr != NULL)
+		label = attr->pValue;
+
+	/* Load up the identifier */
+	attr = gkm_attributes_find (attrs, n_attrs, CKA_ID);
+	if (attr != NULL && !label)
+		label = attr->pValue;
+
+	if (!label)
+		label = _("Unnamed");
+
+	if (klass == CKO_G_COLLECTION) {
+		if (attr && attr->pValue && attr->ulValueLen == 5 &&
+		    memcmp (attr->pValue, "login", 5)) {
+			prepare_unlock_login_keyring (self);
+		} else {
+			prepare_unlock_other_keyring (self, label);
+		}
+	} else {
+		prepare_unlock_other_object (self, label);
+	}
+}
+
+/* -----------------------------------------------------------------------------
+ * OBJECT
+ */
+
+static void
+gkm_wrap_prompt_init (GkmWrapPrompt *self)
+{
+	g_queue_init (&self->pool);
+}
+
+#if 0
+static void
+gkm_wrap_prompt_dispose (GObject *obj)
+{
+	GkmWrapPrompt *self = GKM_WRAP_PROMPT (obj);
+
+	G_OBJECT_CLASS (gkm_wrap_prompt_parent_class)->dispose (obj);
+}
+#endif
+
+static void
+gkm_wrap_prompt_finalize (GObject *obj)
+{
+	GkmWrapPrompt *self = GKM_WRAP_PROMPT (obj);
+
+	egg_secure_strfree (self->password);
+
+	while (!g_queue_is_empty(&self->pool))
+		g_free (g_queue_pop_head (&self->pool));
+
+	g_array_free (self->template, TRUE);
+
+	G_OBJECT_CLASS (gkm_wrap_prompt_parent_class)->finalize (obj);
+}
+
+static void
+gkm_wrap_prompt_set_property (GObject *obj, guint prop_id, const GValue *value,
+                                GParamSpec *pspec)
+{
+	switch (prop_id) {
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+gkm_wrap_prompt_get_property (GObject *obj, guint prop_id, GValue *value,
+                                GParamSpec *pspec)
+{
+	switch (prop_id) {
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+gkm_wrap_prompt_class_init (GkmWrapPromptClass *klass)
+{
+	GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+#if 0
+	gobject_class->dispose = gkm_wrap_prompt_dispose;
+#endif
+	gobject_class->finalize = gkm_wrap_prompt_finalize;
+	gobject_class->set_property = gkm_wrap_prompt_set_property;
+	gobject_class->get_property = gkm_wrap_prompt_get_property;
+}
+
+/* -----------------------------------------------------------------------------
+ * PUBLIC
+ */
+
+GkmWrapPrompt*
+gkm_wrap_prompt_for_credential (CK_FUNCTION_LIST_PTR module, CK_SESSION_HANDLE session,
+                                CK_ATTRIBUTE_PTR template, CK_ULONG n_template)
+{
+	CK_ATTRIBUTE_PTR attr;
+	CK_ATTRIBUTE_PTR options;
+	CK_ULONG n_options, i;
+	CK_OBJECT_CLASS klass;
+	CK_OBJECT_HANDLE object;
+	GkmWrapPrompt *self;
+
+	g_return_val_if_fail (module, NULL);
+	g_return_val_if_fail (session, NULL);
+	g_return_val_if_fail (n_template || !template, NULL);
+
+	/* Must be credential and have object for protected outh path */
+	if (!gkm_attributes_find_ulong (template, n_template, CKA_CLASS, &klass) ||
+	    !gkm_attributes_find_ulong (template, n_template, CKA_G_OBJECT, &object) ||
+	    klass != CKO_G_CREDENTIAL || object == 0)
+		return NULL;
+
+	/* Must have CKA_VALUE with pValue set to null for protected auth path */
+	attr = gkm_attributes_find (template, n_template, CKA_VALUE);
+	if (attr == NULL || attr->pValue != NULL)
+		return NULL;
+
+	/* Build up the prompt */
+	self = g_object_new (GKM_WRAP_TYPE_PROMPT, NULL);
+	self->object = object;
+	self->module = module;
+	self->session = session;
+	prepare_unlock_prompt (self, TRUE);
+
+	/* Build up a copy of the template with CKA_VALUE first */
+	self->template = g_array_new (FALSE, FALSE, sizeof (CK_ATTRIBUTE));
+	g_array_append_val (self->template, *attr);
+	for (i = 0; i < n_template; ++i) {
+		if (template[i].type != CKA_VALUE)
+			g_array_append_val (self->template, template[i]);
+	}
+
+	self->n_template = n_template;
+
+	/* Now load up the unlock options into the prompt*/
+	options = get_unlock_options_from_object (self, &n_options);
+	if (options != NULL)
+		set_unlock_options_on_prompt (self, options, n_options);
+
+	return self;
+}
+
+gboolean
+gkm_wrap_prompt_do_credential (GkmWrapPrompt *self, CK_ATTRIBUTE_PTR *template,
+                               CK_ULONG *n_template)
+{
+	CK_ATTRIBUTE_PTR options;
+	CK_ATTRIBUTE_PTR attr;
+	CK_ULONG n_options, i;
+
+	g_return_val_if_fail (GKM_WRAP_IS_PROMPT (self), FALSE);
+	g_return_val_if_fail (template, FALSE);
+	g_return_val_if_fail (n_template, FALSE);
+
+	gku_prompt_request_attention_sync (NULL, on_prompt_attention,
+	                                   g_object_ref (self), g_object_unref);
+
+	if (gku_prompt_get_response (GKU_PROMPT (self)) != GKU_RESPONSE_OK)
+		return FALSE;
+
+	egg_secure_strfree (self->password);
+	self->password = gku_prompt_get_password (GKU_PROMPT (self), "password");
+	g_return_val_if_fail (self->password, FALSE);
+
+	/* Truncate any extra options off the end of template */
+	g_assert (self->n_template > 0);
+	g_assert (self->template->len >= self->n_template);
+	g_array_set_size (self->template, self->n_template);
+
+	/* Put the password into the template, always first */
+	attr = &g_array_index (self->template, CK_ATTRIBUTE, 0);
+	g_assert (attr->type == CKA_VALUE);
+	attr->pValue = self->password;
+	attr->ulValueLen = strlen (self->password);
+
+	/* Tag any options onto the end of template */
+	options = get_unlock_options_from_prompt (self, &n_options);
+	for (i = 0; options && i < n_options; ++i)
+		g_array_append_val (self->template, options[i]);
+
+	*template = (CK_ATTRIBUTE_PTR)self->template->data;
+	*n_template = self->template->len;
+	return TRUE;
+}
+
+void
+gkm_wrap_prompt_done_credential (GkmWrapPrompt *self, CK_RV call_result)
+{
+	CK_ATTRIBUTE_PTR options;
+	CK_ULONG n_options;
+	gint value = 0;
+
+	g_return_if_fail (GKM_WRAP_IS_PROMPT (self));
+
+	/* Save the options, and possibly auto unlock */
+	if (call_result == CKR_OK) {
+		options = get_unlock_options_from_prompt (self, &n_options);
+		if (options != NULL)
+			set_unlock_options_on_object (self, options, n_options);
+
+		if (gku_prompt_get_unlock_option (GKU_PROMPT (self), GKU_UNLOCK_AUTO, &value) && value) {
+			g_assert_not_reached (); /* TODO: Need to implement */
+		}
+
+	/* Make sure to remove any auto-unlock when we fail */
+	} else if (call_result == CKR_PIN_INCORRECT) {
+		/* TODO: Implement removal from login keyring */
+	}
+}
diff --git a/pkcs11/wrap-layer/gkm-wrap-prompt.h b/pkcs11/wrap-layer/gkm-wrap-prompt.h
new file mode 100644
index 0000000..855ce89
--- /dev/null
+++ b/pkcs11/wrap-layer/gkm-wrap-prompt.h
@@ -0,0 +1,63 @@
+/*
+ * gnome-keyring
+ *
+ * Copyright (C) 2010 Stefan Walter
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public 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 Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef __GKM_WRAP_PROMPT_H__
+#define __GKM_WRAP_PROMPT_H__
+
+#include <glib-object.h>
+
+#include "ui/gku-prompt.h"
+
+#define GKM_WRAP_TYPE_PROMPT               (gkm_wrap_prompt_get_type ())
+#define GKM_WRAP_PROMPT(obj)               (G_TYPE_CHECK_INSTANCE_CAST ((obj), GKM_WRAP_TYPE_PROMPT, GkmWrapPrompt))
+#define GKM_WRAP_PROMPT_CLASS(klass)       (G_TYPE_CHECK_CLASS_CAST ((klass), GKM_WRAP_TYPE_PROMPT, GkmWrapPromptClass))
+#define GKM_WRAP_IS_PROMPT(obj)            (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GKM_WRAP_TYPE_PROMPT))
+#define GKM_WRAP_IS_PROMPT_CLASS(klass)    (G_TYPE_CHECK_CLASS_TYPE ((klass), GKM_WRAP_TYPE_PROMPT))
+#define GKM_WRAP_PROMPT_GET_CLASS(obj)     (G_TYPE_INSTANCE_GET_CLASS ((obj), GKM_WRAP_TYPE_PROMPT, GkmWrapPromptClass))
+
+typedef struct _GkmWrapPrompt GkmWrapPrompt;
+typedef struct _GkmWrapPromptClass GkmWrapPromptClass;
+
+struct _GkmWrapPromptClass {
+	GkuPromptClass parent_class;
+};
+
+GType               gkm_wrap_prompt_get_type                (void);
+
+GkmWrapPrompt*      gkm_wrap_prompt_for_credential          (CK_FUNCTION_LIST_PTR module,
+                                                             CK_SESSION_HANDLE session,
+                                                             CK_ATTRIBUTE_PTR template,
+                                                             CK_ULONG n_template);
+
+gboolean            gkm_wrap_prompt_do_credential           (GkmWrapPrompt *self,
+                                                             CK_ATTRIBUTE_PTR *template,
+                                                             CK_ULONG *n_template);
+
+void                gkm_wrap_prompt_done_credential         (GkmWrapPrompt *self,
+                                                             CK_RV call_result);
+
+#if 0
+void                gkm_wrap_prompt_complete                (GkmWrapPrompt *self);
+
+void                gkm_wrap_prompt_dismiss                 (GkmWrapPrompt *self);
+#endif
+
+#endif /* __GKM_WRAP_PROMPT_H__ */
diff --git a/ui/gku-prompt.c b/ui/gku-prompt.c
index 01c7c77..d485885 100644
--- a/ui/gku-prompt.c
+++ b/ui/gku-prompt.c
@@ -839,54 +839,33 @@ gku_prompt_get_transport_password (GkuPrompt *self, const gchar *password_type,
 	return TRUE;
 }
 
-void
-gku_prompt_get_unlock_options (GkuPrompt *self, GP11Attributes *attrs)
+gboolean
+gku_prompt_get_unlock_option (GkuPrompt *self, const gchar *option, gint *value)
 {
-	gboolean bval;
-	gint ival;
-
-	g_return_if_fail (GKU_IS_PROMPT (self));
-	g_return_if_fail (attrs);
-	g_return_if_fail (self->pv->output);
-
-	gp11_attributes_add_boolean (attrs, CKA_TOKEN, TRUE);
+	GError *error = NULL;
 
-	bval = g_key_file_get_boolean (self->pv->output, "unlock-options", "unlock-auto", NULL);
-	gp11_attributes_add_boolean (attrs, CKA_GNOME_TRANSIENT, !bval);
+	g_return_val_if_fail (GKU_IS_PROMPT (self), FALSE);
+	g_return_val_if_fail (option, FALSE);
+	g_return_val_if_fail (value, FALSE);
+	g_return_val_if_fail (self->pv->output, FALSE);
 
-	ival = g_key_file_get_integer (self->pv->output, "unlock-options", "unlock-idle", NULL);
-	gp11_attributes_add_ulong (attrs, CKA_G_DESTRUCT_IDLE, ival <= 0 ? 0 : ival);
+	*value = g_key_file_get_integer (self->pv->output, "unlock-options", option, &error);
+	if (error != NULL) {
+		g_clear_error (&error);
+		return FALSE;
+	}
 
-	ival = g_key_file_get_integer (self->pv->output, "unlock-options", "unlock-timeout", NULL);
-	gp11_attributes_add_ulong (attrs, CKA_G_DESTRUCT_AFTER, ival <= 0 ? 0 : ival);
+	return TRUE;
 }
 
 void
-gku_prompt_set_unlock_options (GkuPrompt *self, GP11Attributes *attrs)
+gku_prompt_set_unlock_option (GkuPrompt *self, const gchar *option, gint value)
 {
-	gboolean bval;
-	gulong uval;
-
 	g_return_if_fail (GKU_IS_PROMPT (self));
-	g_return_if_fail (attrs);
+	g_return_if_fail (option);
 	g_return_if_fail (self->pv->input);
 
-	if (gp11_attributes_find_boolean (attrs, CKA_GNOME_TRANSIENT, &bval))
-		g_key_file_set_boolean (self->pv->input, "unlock-options", "unlock-auto", !bval);
-
-	if (gp11_attributes_find_ulong (attrs, CKA_G_DESTRUCT_IDLE, &uval))
-		g_key_file_set_integer (self->pv->input, "unlock-options", "unlock-idle", (int)uval);
-
-	if (gp11_attributes_find_ulong (attrs, CKA_G_DESTRUCT_AFTER, &uval))
-		g_key_file_set_integer (self->pv->input, "unlock-options", "unlock-timeout", (int)uval);
-}
-
-gboolean
-gku_prompt_get_unlock_auto (GkuPrompt *self)
-{
-	g_return_val_if_fail (GKU_IS_PROMPT (self), FALSE);
-	g_return_val_if_fail (self->pv->output, FALSE);
-	return g_key_file_get_boolean (self->pv->output, "unlock-options", "unlock-auto", NULL);
+	g_key_file_set_integer (self->pv->input, "unlock-options", option, value);
 }
 
 /* ----------------------------------------------------------------------------------
diff --git a/ui/gku-prompt.h b/ui/gku-prompt.h
index 1520f89..a1c6fcb 100644
--- a/ui/gku-prompt.h
+++ b/ui/gku-prompt.h
@@ -34,6 +34,10 @@ typedef enum {
 	GKU_RESPONSE_OTHER        = 3,
 } GkuResponse;
 
+#define GKU_UNLOCK_AUTO       "unlock-auto"
+#define GKU_UNLOCK_IDLE       "unlock-idle"
+#define GKU_UNLOCK_TIMEOUT    "unlock-timeout"
+
 #define GKU_TYPE_PROMPT               (gku_prompt_get_type ())
 #define GKU_PROMPT(obj)               (G_TYPE_CHECK_INSTANCE_CAST ((obj), GKU_TYPE_PROMPT, GkuPrompt))
 #define GKU_PROMPT_CLASS(klass)       (G_TYPE_CHECK_CLASS_CAST ((klass), GKU_TYPE_PROMPT, GkuPromptClass))
@@ -112,13 +116,13 @@ gboolean            gku_prompt_get_transport_password (GkuPrompt *self,
                                                        gpointer *value,
                                                        gsize *n_value);
 
-void                gku_prompt_get_unlock_options     (GkuPrompt *self,
-                                                       GP11Attributes *attrs);
-
-void                gku_prompt_set_unlock_options     (GkuPrompt *self,
-                                                       GP11Attributes *attrs);
+gboolean            gku_prompt_get_unlock_option      (GkuPrompt *self,
+                                                       const gchar *option,
+                                                       gint *value);
 
-gboolean            gku_prompt_get_unlock_auto        (GkuPrompt *self);
+void                gku_prompt_set_unlock_option      (GkuPrompt *self,
+                                                       const gchar *option,
+                                                       gint value);
 
 gboolean            gku_prompt_is_widget_selected     (GkuPrompt *prompt,
                                                        const gchar *widget);



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