gnome-keyring r1447 - in trunk: . daemon daemon/pkcs11 daemon/pkix daemon/ssh daemon/ui gp11 pkcs11 pkcs11/gck pkcs11/ssh-agent pkcs11/ssh-store po



Author: nnielsen
Date: Thu Jan  8 18:41:26 2009
New Revision: 1447
URL: http://svn.gnome.org/viewvc/gnome-keyring?rev=1447&view=rev

Log:
	* gp11/gp11-module.c: 
	* gp11/gp11-session.c: 
	* gp11/gp11-slot.c: Don't try to keep authenticating when 
	bad password on protected auth path authentication. Protected
	auth path repeats internally as necessary.

	* pkcs11/pkcs11g.h:
	* pkcs11/gck/gck-attributes.c:
	* pkcs11/gck/gck-object.c:
	* pkcs11/gck/gck-object.h: 
	* pkcs11/ssh-store/gck-ssh-module.c:
	* pkcs11/ssh-store/gck-ssh-private-key.c:
	* pkcs11/ssh-store/gck-ssh-private-key.h:
	* pkcs11/ssh-store/gck-ssh-public-key.c:
	* pkcs11/ssh-store/gck-ssh-public-key.h: Added CKA_GNOME_UNIQUE
	attribute. 

	* daemon/gkr-daemon.c:
	* daemon/Makefile.am:
	* daemon/pkcs11/gkr-pkcs11-auth.c: (added)
	* daemon/pkcs11/gkr-pkcs11-auth.h: (added)
	* daemon/pkcs11/gkr-pkcs11-auth-ep.c: (added)
	* daemon/pkcs11/gkr-pkcs11-daemon.c: (added)
	* daemon/pkcs11/gkr-pkcs11-daemon.h: (added)
	* daemon/pkcs11/Makefile.am:
	* daemon/pkix/gkr-pkix-asn1.c: 
	* daemon/ssh/gkr-ssh-daemon.h: (removed)
	* daemon/ssh/gkr-ssh-daemon-io.c: (removed)
	* daemon/ssh/gkr-ssh-daemon-ops.c: (removed)
	* daemon/ssh/Makefile.am: (removed)
	* daemon/ui/gkr-ask-daemon.c:
	* pkcs11/ssh-agent/gck-ssh-agent.c:
	* pkcs11/ssh-agent/gck-ssh-agent-ops.c: Integrate new modular SSH agent
	as the main gnome-keyring-daemon SSH agent.


Added:
   trunk/daemon/pkcs11/gkr-pkcs11-auth-ep.c
   trunk/daemon/pkcs11/gkr-pkcs11-auth.c
   trunk/daemon/pkcs11/gkr-pkcs11-auth.h
   trunk/daemon/pkcs11/gkr-pkcs11-daemon.c
   trunk/daemon/pkcs11/gkr-pkcs11-daemon.h
Removed:
   trunk/daemon/ssh/gkr-ssh-daemon-io.c
   trunk/daemon/ssh/gkr-ssh-daemon-ops.c
   trunk/daemon/ssh/gkr-ssh-daemon.h
Modified:
   trunk/ChangeLog
   trunk/daemon/Makefile.am
   trunk/daemon/gkr-daemon.c
   trunk/daemon/pkcs11/Makefile.am
   trunk/daemon/pkix/gkr-pkix-asn1.c
   trunk/daemon/ssh/Makefile.am
   trunk/daemon/ui/gkr-ask-daemon.c
   trunk/gp11/gp11-module.c
   trunk/gp11/gp11-session.c
   trunk/gp11/gp11-slot.c
   trunk/pkcs11/gck/gck-attributes.c
   trunk/pkcs11/gck/gck-object.c
   trunk/pkcs11/gck/gck-object.h
   trunk/pkcs11/pkcs11g.h
   trunk/pkcs11/ssh-agent/gck-ssh-agent-ops.c
   trunk/pkcs11/ssh-agent/gck-ssh-agent.c
   trunk/pkcs11/ssh-store/gck-ssh-module.c
   trunk/pkcs11/ssh-store/gck-ssh-private-key.c
   trunk/pkcs11/ssh-store/gck-ssh-private-key.h
   trunk/pkcs11/ssh-store/gck-ssh-public-key.c
   trunk/pkcs11/ssh-store/gck-ssh-public-key.h
   trunk/po/ChangeLog
   trunk/po/POTFILES.in

Modified: trunk/daemon/Makefile.am
==============================================================================
--- trunk/daemon/Makefile.am	(original)
+++ trunk/daemon/Makefile.am	Thu Jan  8 18:41:26 2009
@@ -43,7 +43,11 @@
 	$(top_builddir)/daemon/keyrings/libgkr-keyrings.la \
 	$(top_builddir)/daemon/ui/libgkr-ui.la \
 	$(top_builddir)/library/libgnome-keyring-common.la \
+	$(top_builddir)/pkcs11/ssh-agent/libgck-ssh-agent.la \
+	$(top_builddir)/pkcs11/ssh-store/libgck-ssh-store.la \
+	$(top_builddir)/pkcs11/gck/libgck.la \
 	$(top_builddir)/common/libgkr-common.la \
+	$(top_builddir)/gp11/libgp11.la \
 	$(DAEMON_LIBS) \
 	$(GOBJECT_LIBS) \
 	$(GTHREAD_LIBS) \

Modified: trunk/daemon/gkr-daemon.c
==============================================================================
--- trunk/daemon/gkr-daemon.c	(original)
+++ trunk/daemon/gkr-daemon.c	Thu Jan  8 18:41:26 2009
@@ -41,10 +41,10 @@
 #include "pk/gkr-pk-root-storage.h"
 #endif
 
+#include "pkcs11/gkr-pkcs11-daemon.h"
 #include "pkcs11/gkr-pkcs11-dispatch.h"
 
 #ifdef WITH_SSH
-#include "ssh/gkr-ssh-daemon.h"
 #include "ssh/gkr-ssh-storage.h"
 #endif
 
@@ -634,11 +634,16 @@
 		return TRUE;
 	}
 	
-	/* Initialize object storage */
+	/* Initialize new style PKCS#11 components */
+	if (!gkr_pkcs11_daemon_initialize ())
+		return FALSE;
+	
+	/* TODO: OLD, REMOVE */
 	if (!gkr_pk_object_storage_initialize ())
 		return FALSE;
 	
 #ifdef ROOT_CERTIFICATES
+	/* TODO: OLD, REMOVE */
 	if (!gkr_pk_root_storage_initialize ())
 		return FALSE;
 #endif
@@ -647,13 +652,17 @@
 	
 #ifdef WITH_SSH	
 	if (check_run_component ("ssh")) {
-		if (!gkr_daemon_ssh_io_initialize () ||
-		    !gkr_ssh_storage_initialize ())
+		if (!gkr_pkcs11_daemon_setup_ssh ())
+			return FALSE;
+				
+		/* TODO: OLD, REMOVE */
+		if (!gkr_ssh_storage_initialize ())
 			return FALSE;
 	}
 #endif
 	
 	if (check_run_component ("pkcs11")) {
+		/* TODO: OLD, REMOVE */
 		if (!gkr_pkcs11_dispatch_setup ())
 			return FALSE;
 	}
@@ -715,6 +724,11 @@
 		if (start_or_initialize_daemon ())
 			cleanup_and_exit (0);
 	} 
+
+	/* Initialize our daemon main loop and threading */
+	loop = g_main_loop_new (NULL, FALSE);
+	ctx = g_main_loop_get_context (loop);
+	gkr_async_workers_init (loop);
 	
 	/* 
 	 * Always initialize the keyring subsystem. This is a necessary
@@ -741,9 +755,6 @@
 	/* Prepare logging a second time, since we may be in a different process */
 	prepare_logging();
 
-	loop = g_main_loop_new (NULL, FALSE);
-	ctx = g_main_loop_get_context (loop);
-	
 	signal (SIGPIPE, SIG_IGN);
 	gkr_unix_signal_connect (ctx, SIGINT, signal_handler, NULL);
 	gkr_unix_signal_connect (ctx, SIGHUP, signal_handler, NULL);
@@ -751,8 +762,6 @@
              
 	/* TODO: Do we still need this? XFCE still seems to use it. */
 	slave_lifetime_to_fd ();
-	
-	gkr_async_workers_init (loop);
 
 	/*
 	 * Unlock the login keyring if we were given a password on STDIN.

Modified: trunk/daemon/pkcs11/Makefile.am
==============================================================================
--- trunk/daemon/pkcs11/Makefile.am	(original)
+++ trunk/daemon/pkcs11/Makefile.am	Thu Jan  8 18:41:26 2009
@@ -8,6 +8,8 @@
 	$(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 \
 	gkr-pkcs11-dispatch.c gkr-pkcs11-dispatch.h \
 	gkr-pkcs11-dispatch-session.c \
 	gkr-pkcs11-dsa.c gkr-pkcs11-dsa.h \

Added: trunk/daemon/pkcs11/gkr-pkcs11-auth-ep.c
==============================================================================
--- (empty file)
+++ trunk/daemon/pkcs11/gkr-pkcs11-auth-ep.c	Thu Jan  8 18:41:26 2009
@@ -0,0 +1,1044 @@
+/* 
+ * 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 "gkr-pkcs11-auth.h"
+
+#include "common/gkr-async.h"
+
+#include "pkcs11/pkcs11.h"
+#include "pkcs11/pkcs11g.h"
+
+#include <glib.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:
+ * 
+ * gkr_async_end_concurrent ();
+ * 
+ *     ...
+ *     
+ * gkr_async_begin_concurrent ();
+ */
+
+static CK_FUNCTION_LIST_PTR pkcs11_lower = NULL;
+
+/* --------------------------------------------------------------------------------------
+ * HELPERS 
+ */
+
+static GkrPkcs11AuthObject*
+lookup_specific_auth_object (CK_SESSION_HANDLE handle, CK_OBJECT_HANDLE object)
+{
+	GkrPkcs11AuthObject *info = NULL;
+	CK_SESSION_INFO session_info;
+	CK_ATTRIBUTE attrs[5];
+	CK_OBJECT_CLASS klass;
+	gchar *label = NULL;
+	gchar *unique = NULL;
+	CK_BBOOL token, always;
+	CK_ULONG n_attrs;
+	CK_RV rv;
+	
+	/* Lookup information about the specific object */
+	attrs[0].type = CKA_LABEL;
+	attrs[0].pValue = label = NULL;
+	attrs[0].ulValueLen = 0;
+
+	attrs[1].type = CKA_GNOME_UNIQUE;
+	attrs[1].pValue = unique = NULL;
+	attrs[1].ulValueLen = 0;
+
+	attrs[2].type = CKA_CLASS;
+	attrs[2].pValue = &klass;
+	attrs[2].ulValueLen = sizeof (klass);
+
+	always = CK_FALSE;
+	attrs[3].type = CKA_ALWAYS_AUTHENTICATE;
+	attrs[3].pValue = &always;
+	attrs[3].ulValueLen = sizeof (always);
+	
+	token = CK_FALSE;
+	attrs[4].type = CKA_TOKEN;
+	attrs[4].pValue = &token;
+	attrs[4].ulValueLen = sizeof (token);
+	
+	n_attrs = 5;
+	
+	/* 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;
+
+	/* Make sure we can get the session info */
+	rv = (pkcs11_lower->C_GetSessionInfo) (handle, &session_info);
+	if (rv != CKR_OK)
+		return NULL;
+
+	/* Allocate memory for big attributes */
+	if (attrs[0].ulValueLen != (CK_ULONG)-1)
+		attrs[0].pValue = label = g_malloc0 (attrs[0].ulValueLen + 1);
+	if (attrs[1].ulValueLen != (CK_ULONG)-1)
+		attrs[1].pValue = unique = g_malloc0 (attrs[1].ulValueLen + 1);
+	
+	/* Get actual attributes */
+	rv = (pkcs11_lower->C_GetAttributeValue) (handle, object, attrs, n_attrs);
+	if (rv != CKR_OK && rv != CKR_ATTRIBUTE_TYPE_INVALID) {
+		g_free (label);
+		g_free (unique);
+		return NULL;
+	}
+	
+	info = g_new0 (GkrPkcs11AuthObject, 1);
+	
+	if (attrs[0].ulValueLen != (CK_ULONG)-1) {
+		info->label = label;
+		label = NULL;
+	}
+
+	if (attrs[1].ulValueLen != (CK_ULONG)-1) {
+		info->unique = unique;
+		unique = NULL;
+	}
+
+	info->token = token;
+	info->klass = klass;
+	info->handle = object;
+	info->slot = session_info.slotID;
+	
+	g_free (label);
+	g_free (unique);
+	
+	return info;
+}
+
+/* --------------------------------------------------------------------------------------
+ * PKCS#11 ENTRY POINTS
+ */
+
+static CK_RV
+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) {
+		gkr_async_end_concurrent ();
+	
+			/* Let our auth caches/storage know we're initializing */
+			gkr_pkcs11_auth_initialized ();
+		
+		gkr_async_begin_concurrent ();
+	}
+	
+	return rv;
+}
+
+static CK_RV
+auth_C_Finalize (CK_VOID_PTR reserved)
+{
+	CK_RV rv;
+	
+	rv = (pkcs11_lower->C_Finalize) (reserved);
+	
+	if (rv == CKR_OK) {
+		gkr_async_end_concurrent ();
+	
+			/* Let our auth caches/storage know we're initializing */
+			gkr_pkcs11_auth_finalized ();
+		
+		gkr_async_begin_concurrent ();
+	}
+
+	return rv;
+}
+
+static CK_RV
+auth_C_GetInfo (CK_INFO_PTR info)
+{
+	return (pkcs11_lower->C_GetInfo) (info);
+}
+
+static CK_RV
+auth_C_GetFunctionList (CK_FUNCTION_LIST_PTR_PTR list)
+{
+	if (!list)
+		return CKR_ARGUMENTS_BAD;
+	*list = gkr_pkcs11_auth_get_functions ();
+	return CKR_OK;
+}
+
+static CK_RV
+auth_C_GetSlotList (CK_BBOOL token_present, CK_SLOT_ID_PTR slot_list, CK_ULONG_PTR count)
+{
+	return (pkcs11_lower->C_GetSlotList) (token_present, slot_list, count);
+}
+
+static CK_RV
+auth_C_GetSlotInfo (CK_SLOT_ID id, CK_SLOT_INFO_PTR info)
+{
+	return (pkcs11_lower->C_GetSlotInfo) (id, info);
+}
+
+static CK_RV
+auth_C_GetTokenInfo (CK_SLOT_ID id, CK_TOKEN_INFO_PTR info)
+{
+	CK_RV rv = (pkcs11_lower->C_GetTokenInfo) (id, info);
+	if (rv == CKR_OK)
+		info->flags |= CKF_PROTECTED_AUTHENTICATION_PATH;
+	return rv;
+}
+
+static CK_RV
+auth_C_GetMechanismList (CK_SLOT_ID id, CK_MECHANISM_TYPE_PTR mechanism_list, CK_ULONG_PTR count)
+{
+	return (pkcs11_lower->C_GetMechanismList) (id, mechanism_list, count);
+}
+
+static CK_RV
+auth_C_GetMechanismInfo (CK_SLOT_ID id, CK_MECHANISM_TYPE type, CK_MECHANISM_INFO_PTR info)
+{
+	return (pkcs11_lower->C_GetMechanismInfo) (id, type, info);
+}
+
+static CK_RV
+auth_C_InitToken (CK_SLOT_ID id, CK_UTF8CHAR_PTR pin, CK_ULONG pin_len, CK_UTF8CHAR_PTR label)
+{
+	/* TODO: Implement prompting for auth here */
+	return (pkcs11_lower->C_InitToken) (id, pin, pin_len, label);
+}
+
+static CK_RV
+auth_C_WaitForSlotEvent (CK_FLAGS flags, CK_SLOT_ID_PTR slot, CK_VOID_PTR reserved)
+{
+	return (pkcs11_lower->C_WaitForSlotEvent) (flags, slot, reserved);
+}
+
+static CK_RV
+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;
+	CK_RV rv;
+
+	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) {
+			gkr_async_end_concurrent ();
+
+				/* Track this session in our auth layer */
+				gkr_pkcs11_auth_session_opened (*handle, &session_info);
+
+			gkr_async_begin_concurrent ();
+		}
+	}
+	
+	return rv;
+}
+
+static CK_RV
+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) 
+		have_session_info = TRUE;
+	
+	rv = (pkcs11_lower->C_CloseSession) (handle);
+	if (rv == CKR_OK && have_session_info) {
+		gkr_async_end_concurrent ();
+	
+			/* Track this session closure in our auth cache/store */
+			gkr_pkcs11_auth_session_closed (handle, &session_info);
+		
+		gkr_async_begin_concurrent ();
+	}
+	
+	return rv; 
+}
+
+static CK_RV
+auth_C_CloseAllSessions (CK_SLOT_ID id)
+{
+	CK_RV rv = (pkcs11_lower->C_CloseAllSessions) (id);
+	
+	if (rv == CKR_OK) {
+		gkr_async_end_concurrent ();
+	
+			/* Track this session closure in our auth cache/store */
+			gkr_pkcs11_auth_session_closed_all (id);
+		
+		gkr_async_begin_concurrent ();
+	}
+	
+	return rv; 
+}
+
+static CK_RV
+auth_C_GetFunctionStatus (CK_SESSION_HANDLE handle)
+{
+	return (pkcs11_lower->C_GetFunctionStatus) (handle);
+}
+
+static CK_RV
+auth_C_CancelFunction (CK_SESSION_HANDLE handle)
+{
+	return (pkcs11_lower->C_CancelFunction) (handle);
+}
+
+static CK_RV
+auth_C_GetSessionInfo (CK_SESSION_HANDLE handle, CK_SESSION_INFO_PTR info)
+{
+	return (pkcs11_lower->C_GetSessionInfo) (handle, info);
+}
+
+static CK_RV
+auth_C_InitPIN (CK_SESSION_HANDLE handle, CK_UTF8CHAR_PTR pin, CK_ULONG pin_len)
+{
+	/* 
+	 * TODO: Need to implement this properly.
+	 * 
+	 * Prompt the user for new password if 
+	 * CKF_PROTECTED_AUTHENTICATION path.
+	 */
+	return (pkcs11_lower->C_InitPIN) (handle, pin, pin_len);
+}
+
+static CK_RV
+auth_C_SetPIN (CK_SESSION_HANDLE handle, CK_UTF8CHAR_PTR old_pin, CK_ULONG old_pin_len, 
+               CK_UTF8CHAR_PTR new_pin, CK_ULONG new_pin_len)
+{
+	/* 
+	 * TODO: Need to implement this properly.
+	 * 
+	 * Prompt the user for old and new passwords if 
+	 * CKF_PROTECTED_AUTHENTICATION path.
+	 */
+	return (pkcs11_lower->C_SetPIN) (handle, old_pin, old_pin_len, new_pin, new_pin_len);
+}
+
+static CK_RV
+auth_C_GetOperationState (CK_SESSION_HANDLE handle, CK_BYTE_PTR operation_state, CK_ULONG_PTR operation_state_len)
+{
+	return (pkcs11_lower->C_GetOperationState) (handle, operation_state, operation_state_len);
+}
+
+static CK_RV
+auth_C_SetOperationState (CK_SESSION_HANDLE handle, CK_BYTE_PTR operation_state,
+                          CK_ULONG operation_state_len, CK_OBJECT_HANDLE encryption_key,
+                          CK_OBJECT_HANDLE authentication_key)
+{
+	return (pkcs11_lower->C_SetOperationState) (handle, operation_state, operation_state_len, encryption_key, authentication_key);
+}
+
+static CK_RV
+auth_C_Login (CK_SESSION_HANDLE handle, CK_USER_TYPE user_type,
+              CK_UTF8CHAR_PTR pin, CK_ULONG pin_len)
+{
+	CK_SESSION_INFO session_info;
+	CK_TOKEN_INFO token_info;
+	gboolean auth = FALSE;
+	CK_RV rv;
+
+	/* 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 (pin != NULL || rv != CKR_PIN_INCORRECT)
+		return rv;
+
+	/* Dig up the information we'll need */
+	if ((pkcs11_lower->C_GetSessionInfo) (handle, &session_info) != CKR_OK)
+		return rv;
+	if ((pkcs11_lower->C_GetTokenInfo) (session_info.slotID, &token_info) != CKR_OK)
+		return rv;
+
+	/* If lower level is a protected authentication path, then don't bother */
+	if (token_info.flags & CKF_PROTECTED_AUTHENTICATION_PATH) 
+		return rv;
+	
+	/* Loop until logged in or user cancels */
+	while (rv == CKR_PIN_INCORRECT) {
+		
+		gkr_async_end_concurrent ();
+			switch (user_type) {
+			case CKU_CONTEXT_SPECIFIC:
+				auth = gkr_pkcs11_auth_login_specific_prompt (handle, &session_info, &pin, &pin_len);
+				break;
+			case CKU_USER:
+				auth = gkr_pkcs11_auth_login_user_prompt (handle, &token_info, &pin, &pin_len);
+				break;
+			default:
+				break;
+			};
+		gkr_async_begin_concurrent ();
+		
+		if (!auth) {
+			rv = CKR_FUNCTION_CANCELED;
+			break;
+		}
+	
+		/* Try the login again */
+		rv = (pkcs11_lower->C_Login) (handle, user_type, pin, pin_len);	
+	
+		gkr_async_end_concurrent ();
+			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;
+			};
+		gkr_async_begin_concurrent ();
+	}
+
+	return rv;
+}
+
+static CK_RV
+auth_C_Logout (CK_SESSION_HANDLE handle)
+{
+	return (pkcs11_lower->C_Logout) (handle);
+}
+
+static CK_RV
+auth_C_CreateObject (CK_SESSION_HANDLE handle, CK_ATTRIBUTE_PTR template,
+                     CK_ULONG count, CK_OBJECT_HANDLE_PTR new_object)
+{
+	/* TODO: Need to implement CKA_GNOME_AUTH_CACHE attributes. */
+	return (pkcs11_lower->C_CreateObject) (handle, template, count, new_object);
+}
+
+static CK_RV
+auth_C_CopyObject (CK_SESSION_HANDLE handle, CK_OBJECT_HANDLE object,
+                   CK_ATTRIBUTE_PTR template, CK_ULONG count,
+                   CK_OBJECT_HANDLE_PTR new_object)
+{
+	/* TODO: Need to implement CKA_GNOME_AUTH_CACHE attributes. */
+	return (pkcs11_lower->C_CopyObject) (handle, object, template, count, new_object);
+}
+
+static CK_RV
+auth_C_DestroyObject (CK_SESSION_HANDLE handle, CK_OBJECT_HANDLE object)
+{
+	return (pkcs11_lower->C_DestroyObject) (handle, object);
+}
+
+static CK_RV
+auth_C_GetObjectSize (CK_SESSION_HANDLE handle, CK_OBJECT_HANDLE object,
+                      CK_ULONG_PTR size)
+{
+	return (pkcs11_lower->C_GetObjectSize) (handle, object, size);
+}
+
+static CK_RV
+auth_C_GetAttributeValue (CK_SESSION_HANDLE handle, CK_OBJECT_HANDLE object,
+                          CK_ATTRIBUTE_PTR template, CK_ULONG count)
+{
+	/* TODO: Need to implement CKA_GNOME_AUTH_CACHE attributes. */
+	return (pkcs11_lower->C_GetAttributeValue) (handle, object, template, count);
+}
+
+static CK_RV
+auth_C_SetAttributeValue (CK_SESSION_HANDLE handle, CK_OBJECT_HANDLE object,
+                          CK_ATTRIBUTE_PTR template, CK_ULONG count)
+{
+	/* TODO: Need to implement CKA_GNOME_AUTH_CACHE attributes. */
+	return (pkcs11_lower->C_SetAttributeValue) (handle, object, template, count);
+}
+
+static CK_RV
+auth_C_FindObjectsInit (CK_SESSION_HANDLE handle, CK_ATTRIBUTE_PTR template,
+                            CK_ULONG count)
+{
+	/* TODO: Need to implement CKA_GNOME_AUTH_CACHE attributes. */
+	return (pkcs11_lower->C_FindObjectsInit) (handle, template, count);
+}
+
+static CK_RV
+auth_C_FindObjects (CK_SESSION_HANDLE handle, CK_OBJECT_HANDLE_PTR objects,
+                    CK_ULONG max_count, CK_ULONG_PTR count)
+{
+	/* TODO: Need to implement CKA_GNOME_AUTH_CACHE attributes. */
+	return (pkcs11_lower->C_FindObjects) (handle, objects, max_count, count);
+}
+
+static CK_RV
+auth_C_FindObjectsFinal (CK_SESSION_HANDLE handle)
+{
+	/* TODO: Need to implement CKA_GNOME_AUTH_CACHE attributes. */
+	return (pkcs11_lower->C_FindObjectsFinal) (handle);
+}
+
+static CK_RV
+auth_C_EncryptInit (CK_SESSION_HANDLE handle, CK_MECHANISM_PTR mechanism,
+                    CK_OBJECT_HANDLE key)
+{
+	GkrPkcs11AuthObject *object = NULL;
+	CK_RV rv;
+	
+	rv = (pkcs11_lower->C_EncryptInit) (handle, mechanism, key);
+	if (rv == CKR_OK) {
+		object = lookup_specific_auth_object (handle, key);
+		if (object != NULL) {
+			gkr_async_end_concurrent ();
+					
+				gkr_pkcs11_auth_login_specific_prepare (handle, object);
+					
+			gkr_async_begin_concurrent ();
+		}
+	}
+	
+	return CKR_OK;
+}
+
+static CK_RV
+auth_C_Encrypt (CK_SESSION_HANDLE handle, CK_BYTE_PTR data, CK_ULONG data_len,
+                CK_BYTE_PTR encrypted_data, CK_ULONG_PTR encrypted_data_len)
+{
+	CK_RV rv = (pkcs11_lower->C_Encrypt) (handle, data, data_len, encrypted_data, encrypted_data_len);
+	if (rv == CKR_USER_NOT_LOGGED_IN) {
+		if (auth_C_Login (handle, CKU_CONTEXT_SPECIFIC, NULL, 0) == CKR_OK)
+			rv = (pkcs11_lower->C_Encrypt) (handle, data, data_len, encrypted_data, encrypted_data_len);
+	}
+	return rv;
+}
+
+static CK_RV
+auth_C_EncryptUpdate (CK_SESSION_HANDLE handle, CK_BYTE_PTR part,
+                      CK_ULONG part_len, CK_BYTE_PTR encrypted_part,
+                      CK_ULONG_PTR encrypted_part_len)
+{
+	CK_RV rv = (pkcs11_lower->C_EncryptUpdate) (handle, part, part_len, encrypted_part, encrypted_part_len);
+	if (rv == CKR_USER_NOT_LOGGED_IN) {
+		if (auth_C_Login (handle, CKU_CONTEXT_SPECIFIC, NULL, 0) == CKR_OK)
+			rv = (pkcs11_lower->C_EncryptUpdate) (handle, part, part_len, encrypted_part, encrypted_part_len);
+	}
+	return rv;
+}
+
+static CK_RV
+auth_C_EncryptFinal (CK_SESSION_HANDLE handle, CK_BYTE_PTR last_part,
+                     CK_ULONG_PTR last_part_len)
+{
+	return (pkcs11_lower->C_EncryptFinal) (handle, last_part, last_part_len);
+}
+
+static CK_RV
+auth_C_DecryptInit (CK_SESSION_HANDLE handle, CK_MECHANISM_PTR mechanism,
+                    CK_OBJECT_HANDLE key)
+{
+	GkrPkcs11AuthObject *object = NULL;
+	CK_RV rv;
+
+	rv = (pkcs11_lower->C_DecryptInit) (handle, mechanism, key);
+	if (rv == CKR_OK) {
+		object = lookup_specific_auth_object (handle, key);
+		if (object != NULL) {
+			gkr_async_end_concurrent ();
+					
+				gkr_pkcs11_auth_login_specific_prepare (handle, object);
+					
+			gkr_async_begin_concurrent ();
+		}
+	}
+	
+	return rv;
+}
+
+static CK_RV
+auth_C_Decrypt (CK_SESSION_HANDLE handle, CK_BYTE_PTR enc_data,
+                CK_ULONG enc_data_len, CK_BYTE_PTR data, CK_ULONG_PTR data_len)
+{
+	CK_RV rv = (pkcs11_lower->C_Decrypt) (handle, enc_data, enc_data_len, data, data_len);
+	if (rv == CKR_USER_NOT_LOGGED_IN) {
+		if (auth_C_Login (handle, CKU_CONTEXT_SPECIFIC, NULL, 0) == CKR_OK)
+			rv = (pkcs11_lower->C_Decrypt) (handle, enc_data, enc_data_len, data, data_len);
+	}
+	return rv;
+}
+
+static CK_RV
+auth_C_DecryptUpdate (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_DecryptUpdate) (handle, enc_part, enc_part_len, part, part_len);
+	if (rv == CKR_USER_NOT_LOGGED_IN) {
+		if (auth_C_Login (handle, CKU_CONTEXT_SPECIFIC, NULL, 0) == CKR_OK)
+			rv = (pkcs11_lower->C_DecryptUpdate) (handle, enc_part, enc_part_len, part, part_len);
+	}
+	return rv;
+}
+
+static CK_RV
+auth_C_DecryptFinal (CK_SESSION_HANDLE handle, CK_BYTE_PTR last_part,
+                    CK_ULONG_PTR last_part_len)
+{
+	return (pkcs11_lower->C_DecryptFinal) (handle, last_part, last_part_len);
+}
+
+static CK_RV
+auth_C_DigestInit (CK_SESSION_HANDLE handle, CK_MECHANISM_PTR mechanism)
+{
+	return (pkcs11_lower->C_DigestInit) (handle, mechanism);
+}
+
+static CK_RV
+auth_C_Digest (CK_SESSION_HANDLE handle, CK_BYTE_PTR data, CK_ULONG data_len,
+               CK_BYTE_PTR digest, CK_ULONG_PTR digest_len)
+{
+	return (pkcs11_lower->C_Digest) (handle, data, data_len, digest, digest_len);
+}
+
+static CK_RV
+auth_C_DigestUpdate (CK_SESSION_HANDLE handle, CK_BYTE_PTR part, CK_ULONG part_len)
+{
+	return (pkcs11_lower->C_DigestUpdate) (handle, part, part_len);
+}
+
+static CK_RV
+auth_C_DigestKey (CK_SESSION_HANDLE handle, CK_OBJECT_HANDLE key)
+{
+	return (pkcs11_lower->C_DigestKey) (handle, key);
+}
+
+static CK_RV
+auth_C_DigestFinal (CK_SESSION_HANDLE handle, CK_BYTE_PTR digest,
+                    CK_ULONG_PTR digest_len)
+{
+	return (pkcs11_lower->C_DigestFinal) (handle, digest, digest_len);
+}
+
+static CK_RV
+auth_C_SignInit (CK_SESSION_HANDLE handle, CK_MECHANISM_PTR mechanism,
+                 CK_OBJECT_HANDLE key)
+{
+	GkrPkcs11AuthObject *object = NULL;
+	CK_RV rv;
+
+	rv = (pkcs11_lower->C_SignInit) (handle, mechanism, key);
+	if (rv == CKR_OK) {
+		object = lookup_specific_auth_object (handle, key);
+		if (object != NULL) {
+			gkr_async_end_concurrent ();
+					
+				gkr_pkcs11_auth_login_specific_prepare (handle, object);
+					
+			gkr_async_begin_concurrent ();
+		}
+	}
+	
+	return CKR_OK;
+}
+
+static CK_RV
+auth_C_Sign (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_Sign) (handle, data, data_len, signature, signature_len);
+	if (rv == CKR_USER_NOT_LOGGED_IN) {
+		if (auth_C_Login (handle, CKU_CONTEXT_SPECIFIC, NULL, 0) == CKR_OK)
+			rv = (pkcs11_lower->C_Sign) (handle, data, data_len, signature, signature_len);
+	}
+	return rv;
+}
+
+static CK_RV
+auth_C_SignUpdate (CK_SESSION_HANDLE handle, CK_BYTE_PTR part, CK_ULONG part_len)
+{
+	CK_RV rv = (pkcs11_lower->C_SignUpdate) (handle, part, part_len);
+	if (rv == CKR_USER_NOT_LOGGED_IN) {
+		if (auth_C_Login (handle, CKU_CONTEXT_SPECIFIC, NULL, 0) == CKR_OK)
+			rv = (pkcs11_lower->C_SignUpdate) (handle, part, part_len);
+	}
+	return rv;
+}
+
+static CK_RV
+auth_C_SignFinal (CK_SESSION_HANDLE handle, CK_BYTE_PTR signature,
+                  CK_ULONG_PTR signature_len)
+{
+	return (pkcs11_lower->C_SignFinal) (handle, signature, signature_len);
+}
+
+static CK_RV
+auth_C_SignRecoverInit (CK_SESSION_HANDLE handle, CK_MECHANISM_PTR mechanism,
+                        CK_OBJECT_HANDLE key)
+{
+	GkrPkcs11AuthObject *object = NULL;
+	CK_RV rv;
+
+	rv = (pkcs11_lower->C_SignRecoverInit) (handle, mechanism, key);
+	if (rv == CKR_OK) {
+		object = lookup_specific_auth_object (handle, key);
+		if (object != NULL) {
+			gkr_async_end_concurrent ();
+					
+				gkr_pkcs11_auth_login_specific_prepare (handle, object);
+					
+			gkr_async_begin_concurrent ();
+		}
+	}
+	
+	return CKR_OK;
+}
+
+static CK_RV
+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);
+	if (rv == CKR_USER_NOT_LOGGED_IN) {
+		if (auth_C_Login (handle, CKU_CONTEXT_SPECIFIC, NULL, 0) == CKR_OK)
+			rv = (pkcs11_lower->C_SignRecover) (handle, data, data_len, signature, signature_len);
+	}
+	return rv;
+}
+
+static CK_RV
+auth_C_VerifyInit (CK_SESSION_HANDLE handle, CK_MECHANISM_PTR mechanism,
+                   CK_OBJECT_HANDLE key)
+{
+	GkrPkcs11AuthObject *object = NULL;
+	CK_RV rv;
+
+	rv = (pkcs11_lower->C_VerifyInit) (handle, mechanism, key);
+	if (rv == CKR_OK) {
+		object = lookup_specific_auth_object (handle, key);
+		if (object != NULL) {
+			gkr_async_end_concurrent ();
+					
+				gkr_pkcs11_auth_login_specific_prepare (handle, object);
+					
+			gkr_async_begin_concurrent ();
+		}
+	}
+	
+	return CKR_OK;
+}
+
+static CK_RV
+auth_C_Verify (CK_SESSION_HANDLE handle, CK_BYTE_PTR data, CK_ULONG data_len,
+               CK_BYTE_PTR signature, CK_ULONG signature_len)
+{
+	CK_RV rv = (pkcs11_lower->C_Verify) (handle, data, data_len, signature, signature_len);
+	if (rv == CKR_USER_NOT_LOGGED_IN) {
+		if (auth_C_Login (handle, CKU_CONTEXT_SPECIFIC, NULL, 0) == CKR_OK)
+			rv = (pkcs11_lower->C_Verify) (handle, data, data_len, signature, signature_len);
+	}
+	return rv;
+}
+
+static CK_RV
+auth_C_VerifyUpdate (CK_SESSION_HANDLE handle, CK_BYTE_PTR part, CK_ULONG part_len)
+{
+	CK_RV rv = (pkcs11_lower->C_VerifyUpdate) (handle, part, part_len);
+	if (rv == CKR_USER_NOT_LOGGED_IN) {
+		if (auth_C_Login (handle, CKU_CONTEXT_SPECIFIC, NULL, 0) == CKR_OK)
+			rv = (pkcs11_lower->C_VerifyUpdate) (handle, part, part_len);
+	}
+	return rv;
+}
+
+static CK_RV
+auth_C_VerifyFinal (CK_SESSION_HANDLE handle, CK_BYTE_PTR signature,
+                    CK_ULONG signature_len)
+{
+	return (pkcs11_lower->C_VerifyFinal) (handle, signature, signature_len);
+}
+
+static CK_RV
+auth_C_VerifyRecoverInit (CK_SESSION_HANDLE handle, CK_MECHANISM_PTR mechanism,
+                          CK_OBJECT_HANDLE key)
+{
+	GkrPkcs11AuthObject *object = NULL;
+	CK_RV rv;
+
+	rv = (pkcs11_lower->C_VerifyRecoverInit) (handle, mechanism, key);
+	if (rv == CKR_OK) {
+		object = lookup_specific_auth_object (handle, key);
+		if (object != NULL) {
+			gkr_async_end_concurrent ();
+					
+				gkr_pkcs11_auth_login_specific_prepare (handle, object);
+					
+			gkr_async_begin_concurrent ();
+		}
+	}
+
+	return rv;
+}
+
+static CK_RV
+auth_C_VerifyRecover (CK_SESSION_HANDLE handle, CK_BYTE_PTR signature,
+                      CK_ULONG signature_len, CK_BYTE_PTR data, CK_ULONG_PTR data_len)
+{
+	CK_RV rv = (pkcs11_lower->C_VerifyRecover) (handle, signature, signature_len, data, data_len);
+	if (rv == CKR_USER_NOT_LOGGED_IN) {
+		if (auth_C_Login (handle, CKU_CONTEXT_SPECIFIC, NULL, 0) == CKR_OK)
+			rv = (pkcs11_lower->C_VerifyRecover) (handle, signature, signature_len, data, data_len);
+	}
+	return rv;
+}
+
+static CK_RV
+auth_C_DigestEncryptUpdate (CK_SESSION_HANDLE handle, CK_BYTE_PTR part,
+                            CK_ULONG part_len, CK_BYTE_PTR enc_part,
+                            CK_ULONG_PTR enc_part_len)
+{
+	CK_RV rv = (pkcs11_lower->C_DigestEncryptUpdate) (handle, part, part_len, enc_part, enc_part_len);
+	if (rv == CKR_USER_NOT_LOGGED_IN) {
+		if (auth_C_Login (handle, CKU_CONTEXT_SPECIFIC, NULL, 0) == CKR_OK)
+			rv = (pkcs11_lower->C_DigestEncryptUpdate) (handle, part, part_len, enc_part, enc_part_len);
+	}
+	return rv;
+}
+
+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_PTR part_len)
+{
+	CK_RV rv = (pkcs11_lower->C_DecryptDigestUpdate) (handle, enc_part, enc_part_len, part, part_len);
+	if (rv == CKR_USER_NOT_LOGGED_IN) {
+		if (auth_C_Login (handle, CKU_CONTEXT_SPECIFIC, NULL, 0) == CKR_OK)
+			rv = (pkcs11_lower->C_DecryptDigestUpdate) (handle, enc_part, enc_part_len, part, part_len);
+	}
+	return rv;
+}
+
+static CK_RV
+auth_C_SignEncryptUpdate (CK_SESSION_HANDLE handle, CK_BYTE_PTR part,
+                          CK_ULONG part_len, CK_BYTE_PTR enc_part,
+                          CK_ULONG_PTR enc_part_len)
+{
+	CK_RV rv = (pkcs11_lower->C_SignEncryptUpdate) (handle, part, part_len, enc_part, enc_part_len);
+	if (rv == CKR_USER_NOT_LOGGED_IN) {
+		if (auth_C_Login (handle, CKU_CONTEXT_SPECIFIC, NULL, 0) == CKR_OK)
+			rv = (pkcs11_lower->C_SignEncryptUpdate) (handle, part, part_len, enc_part, enc_part_len);
+	}
+	return rv;
+}
+
+static CK_RV
+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);
+	if (rv == CKR_USER_NOT_LOGGED_IN) {
+		if (auth_C_Login (handle, CKU_CONTEXT_SPECIFIC, NULL, 0) == CKR_OK)
+			rv = (pkcs11_lower->C_DecryptVerifyUpdate) (handle, enc_part, enc_part_len, part, part_len);
+	}
+	return rv;
+}
+
+static CK_RV
+auth_C_GenerateKey (CK_SESSION_HANDLE handle, CK_MECHANISM_PTR mechanism,
+                    CK_ATTRIBUTE_PTR template, CK_ULONG count, 
+                    CK_OBJECT_HANDLE_PTR key)
+{
+	return (pkcs11_lower->C_GenerateKey) (handle, mechanism, template, count, key);
+}
+
+static CK_RV
+auth_C_GenerateKeyPair (CK_SESSION_HANDLE handle, CK_MECHANISM_PTR mechanism,
+                        CK_ATTRIBUTE_PTR pub_template, CK_ULONG pub_count,
+                        CK_ATTRIBUTE_PTR priv_template, CK_ULONG priv_count,
+                        CK_OBJECT_HANDLE_PTR pub_key, CK_OBJECT_HANDLE_PTR priv_key)
+{
+	return (pkcs11_lower->C_GenerateKeyPair) (handle, mechanism, pub_template, pub_count, priv_template, priv_count, pub_key, priv_key);
+}
+
+static CK_RV
+auth_C_WrapKey (CK_SESSION_HANDLE handle, CK_MECHANISM_PTR mechanism,
+                CK_OBJECT_HANDLE wrapping_key, CK_OBJECT_HANDLE key,
+                CK_BYTE_PTR wrapped_key, CK_ULONG_PTR wrapped_key_len)
+{
+	return (pkcs11_lower->C_WrapKey) (handle, mechanism, wrapping_key, key, wrapped_key, wrapped_key_len);
+}
+
+static CK_RV
+auth_C_UnwrapKey (CK_SESSION_HANDLE handle, CK_MECHANISM_PTR mechanism,
+                  CK_OBJECT_HANDLE unwrapping_key, CK_BYTE_PTR wrapped_key,
+                  CK_ULONG wrapped_key_len, CK_ATTRIBUTE_PTR template,
+                  CK_ULONG count, CK_OBJECT_HANDLE_PTR key)
+{
+	return (pkcs11_lower->C_UnwrapKey) (handle, mechanism, unwrapping_key, wrapped_key, wrapped_key_len, template, count, key);
+}
+
+static CK_RV
+auth_C_DeriveKey (CK_SESSION_HANDLE handle, CK_MECHANISM_PTR mechanism,
+                  CK_OBJECT_HANDLE base_key, CK_ATTRIBUTE_PTR template,
+                  CK_ULONG count, CK_OBJECT_HANDLE_PTR key)
+{
+	return (pkcs11_lower->C_DeriveKey) (handle, mechanism, base_key, template, count, key);
+}
+
+static CK_RV
+auth_C_SeedRandom (CK_SESSION_HANDLE handle, CK_BYTE_PTR seed, CK_ULONG seed_len)
+{
+	return (pkcs11_lower->C_SeedRandom) (handle, seed, seed_len);
+}
+
+static CK_RV
+auth_C_GenerateRandom (CK_SESSION_HANDLE handle, CK_BYTE_PTR random_data,
+                       CK_ULONG random_len)
+{
+	return (pkcs11_lower->C_GenerateRandom) (handle, random_data, random_len);
+}
+
+/* --------------------------------------------------------------------
+ * 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. 
+ * 
+ * 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.
+ */
+
+static CK_FUNCTION_LIST auth_function_list = {
+	{ CRYPTOKI_VERSION_MAJOR, CRYPTOKI_VERSION_MINOR },  /* version */
+	auth_C_Initialize,
+	auth_C_Finalize,
+	auth_C_GetInfo,
+	auth_C_GetFunctionList,
+	auth_C_GetSlotList,
+	auth_C_GetSlotInfo,
+	auth_C_GetTokenInfo,
+	auth_C_GetMechanismList,
+	auth_C_GetMechanismInfo,
+	auth_C_InitToken,
+	auth_C_InitPIN,
+	auth_C_SetPIN,
+	auth_C_OpenSession,
+	auth_C_CloseSession,
+	auth_C_CloseAllSessions,
+	auth_C_GetSessionInfo,
+	auth_C_GetOperationState,
+	auth_C_SetOperationState,
+	auth_C_Login,
+	auth_C_Logout,
+	auth_C_CreateObject,
+	auth_C_CopyObject,
+	auth_C_DestroyObject,
+	auth_C_GetObjectSize,
+	auth_C_GetAttributeValue,
+	auth_C_SetAttributeValue,
+	auth_C_FindObjectsInit,
+	auth_C_FindObjects,
+	auth_C_FindObjectsFinal,
+	auth_C_EncryptInit,
+	auth_C_Encrypt,
+	auth_C_EncryptUpdate,
+	auth_C_EncryptFinal,
+	auth_C_DecryptInit,
+	auth_C_Decrypt,
+	auth_C_DecryptUpdate,
+	auth_C_DecryptFinal,
+	auth_C_DigestInit,
+	auth_C_Digest,
+	auth_C_DigestUpdate,
+	auth_C_DigestKey,
+	auth_C_DigestFinal,
+	auth_C_SignInit,
+	auth_C_Sign,
+	auth_C_SignUpdate,
+	auth_C_SignFinal,
+	auth_C_SignRecoverInit,
+	auth_C_SignRecover,
+	auth_C_VerifyInit,
+	auth_C_Verify,
+	auth_C_VerifyUpdate,
+	auth_C_VerifyFinal,
+	auth_C_VerifyRecoverInit,
+	auth_C_VerifyRecover,
+	auth_C_DigestEncryptUpdate,
+	auth_C_DecryptDigestUpdate,
+	auth_C_SignEncryptUpdate,
+	auth_C_DecryptVerifyUpdate,
+	auth_C_GenerateKey,
+	auth_C_GenerateKeyPair,
+	auth_C_WrapKey,
+	auth_C_UnwrapKey,
+	auth_C_DeriveKey,
+	auth_C_SeedRandom,
+	auth_C_GenerateRandom,
+	auth_C_GetFunctionStatus,
+	auth_C_CancelFunction,
+	auth_C_WaitForSlotEvent
+};
+
+CK_FUNCTION_LIST_PTR
+gkr_pkcs11_auth_get_functions (void)
+{
+	return &auth_function_list;	
+}
+
+void
+gkr_pkcs11_auth_chain_functions (CK_FUNCTION_LIST_PTR funcs)
+{
+	g_assert (funcs);
+	g_assert (!pkcs11_lower);
+	pkcs11_lower = funcs;
+}
+

Added: trunk/daemon/pkcs11/gkr-pkcs11-auth.c
==============================================================================
--- (empty file)
+++ trunk/daemon/pkcs11/gkr-pkcs11-auth.c	Thu Jan  8 18:41:26 2009
@@ -0,0 +1,538 @@
+/* 
+ * 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 "gkr-pkcs11-auth.h"
+
+#include "common/gkr-secure-memory.h"
+#include "common/gkr-cleanup.h"
+
+#include "keyrings/gkr-keyring-login.h"
+
+#include "ui/gkr-ask-request.h"
+#include "ui/gkr-ask-daemon.h"
+
+#include "pkcs11/pkcs11.h"
+
+#include <glib.h>
+#include <glib/gi18n.h>
+
+#include <unistd.h>
+
+typedef struct _SlotData {
+	gint open_sessions;
+	GHashTable *auth_specific;
+	GHashTable *auth_cache;
+} SlotData;
+
+/* A hash table of CK_SLOT_ID_PTR to SlotData */
+static GHashTable *per_slot_data = NULL;
+
+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
+free_auth_object (GkrPkcs11AuthObject *info)
+{
+	g_assert (info);
+	g_free (info->label);
+	g_free (info->unique);
+	g_free (info);
+}
+
+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)gkr_secure_strdup (password);
+		*pin_len = strlen (password);
+	}
+}
+
+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:
+		return g_strdup_printf (_("An application wants access to the private key '%s', but it is locked"), label);
+	case CKO_CERTIFICATE:
+		return g_strdup_printf (_("An application wants access to the certificate '%s', but it is locked"), label);
+	case CKO_PUBLIC_KEY:
+		return g_strdup_printf (_("An application wants access to the public key '%s', but it is locked"), label);
+	default:
+		return g_strdup_printf (_("An application wants access to '%s', but it is locked"), label);
+	}
+}
+
+static const gchar*
+prepare_specific_check (CK_OBJECT_CLASS klass)
+{
+	switch (klass) {
+	case CKO_PRIVATE_KEY:
+		return _("Automatically unlock this private key when I log in.");
+	case CKO_CERTIFICATE:
+		return _("Automatically unlock this certificate when I log in.");
+	case CKO_PUBLIC_KEY:
+		return _("Automatically unlock this public key when I log in.");
+	default:
+		return _("Automatically unlock this when I log in");
+	}
+}
+
+void
+gkr_pkcs11_auth_login_specific_prepare (CK_SESSION_HANDLE handle, GkrPkcs11AuthObject *object)
+{
+	SlotData *slot;
+	
+	g_assert (object);
+	
+	/* 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, &object->slot);
+	g_return_if_fail (slot);
+
+	/* Delayed allocation because we may never use this on a slot */
+	if (slot->auth_specific == NULL)
+		slot->auth_specific = g_hash_table_new_full (ulong_hash, ulong_equal, ulong_free, 
+		                                             (GDestroyNotify)free_auth_object);
+	
+	/* Store the object info for a later prompt */
+	g_hash_table_replace (slot->auth_specific, ulong_alloc (handle), object);
+}
+
+gboolean 
+gkr_pkcs11_auth_login_specific_prompt (CK_SESSION_HANDLE handle, CK_SESSION_INFO *info,
+                                       CK_UTF8CHAR_PTR *pin, CK_ULONG *pin_len)
+{
+	GkrPkcs11AuthObject *object;
+	const gchar *password;
+	SlotData *slot;
+	gchar *secondary;
+	GkrAskRequest *ask;
+	gboolean ret;
+	guint flags;
+	
+	g_assert (info);
+	g_assert (pin);
+	g_assert (pin_len);	
+
+	/* 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, &info->slotID);
+	if (slot == NULL || slot->auth_specific == NULL)
+		return FALSE;
+
+	/* Find the object we're authenticating */
+	object = g_hash_table_lookup (slot->auth_specific, &handle);
+	if (object == NULL)
+		return FALSE;
+
+	/* Look in our internal password cache */
+	if (slot->auth_cache) {
+		password = g_hash_table_lookup (slot->auth_cache, &object->handle);
+		if (password != NULL) {
+			password_to_pin (password, pin, pin_len);
+			return TRUE;
+		}
+	}
+	
+	/* See if we can just use the login keyring password for this */
+	if (object->unique && object->token && gkr_keyring_login_is_usable ()) {
+		password = gkr_keyring_login_lookup_secret (GNOME_KEYRING_ITEM_ENCRYPTION_KEY_PASSWORD,
+		                                            "unique", object->unique, NULL);
+		if (password != NULL) { 
+			password_to_pin (password, pin, pin_len);
+			return TRUE;
+		}
+	}
+
+	/* Build up the prompt */
+	flags = GKR_ASK_REQUEST_PASSWORD | GKR_ASK_REQUEST_OK_DENY_BUTTONS;
+	ask = gkr_ask_request_new (prepare_specific_title (object->klass), 
+	                           prepare_specific_primary (object->klass), flags);
+
+	secondary = prepare_specific_secondary (object->klass, object->label); 
+	gkr_ask_request_set_secondary (ask, secondary);
+	g_free (secondary);
+
+	if (object->unique && gkr_keyring_login_is_usable ())
+		gkr_ask_request_set_check_option (ask, prepare_specific_check (object->klass));
+
+	/* Prompt the user */
+	gkr_ask_daemon_process (ask);
+
+	/* If the user denied ... */
+	if (ask->response == GKR_ASK_RESPONSE_DENY) {
+		ret = FALSE;
+		
+	/* User cancelled or failure */
+	} else if (ask->response < GKR_ASK_RESPONSE_ALLOW) {
+		ret = FALSE;
+			
+	/* Successful response */
+	} else {
+		password_to_pin (ask->typed_password, pin, pin_len);
+		ret = TRUE;
+		
+		/* Store forever */
+		if (ask->checked && object->unique && object->token) {
+			gkr_keyring_login_attach_secret (GNOME_KEYRING_ITEM_ENCRYPTION_KEY_PASSWORD, 
+			                                 object->label, ask->typed_password, 
+			                                 "unique", object->unique, NULL);
+		
+		/* Store for the session */
+		} else { 
+			/* This is delayed allocation because we may never use this for a slot */
+			if (slot->auth_cache == NULL)
+				slot->auth_cache = g_hash_table_new_full (ulong_hash, ulong_equal, ulong_free,
+				                                          (GDestroyNotify)gkr_secure_free);
+			
+			g_hash_table_replace (slot->auth_cache, ulong_alloc (object->handle), 
+			                      gkr_secure_strdup (ask->typed_password));
+		}
+	}
+	
+	g_object_unref (ask);
+	return ret;
+}
+
+void
+gkr_pkcs11_auth_login_specific_done (CK_SESSION_HANDLE handle, CK_SESSION_INFO *info, 
+                                     CK_UTF8CHAR_PTR *pin, CK_ULONG *pin_len, CK_RV rv)
+{
+	GkrPkcs11AuthObject *object;
+	SlotData *slot;
+	
+	g_assert (pin);
+	g_assert (pin_len);
+
+	/* Because we should have been notified of open session */
+	g_return_if_fail (per_slot_data);
+
+	slot = g_hash_table_lookup (per_slot_data, &info->slotID);
+	g_assert (slot != NULL && slot->auth_specific != NULL);
+
+	object = g_hash_table_lookup (slot->auth_specific, &handle);
+	g_assert (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)
+			gkr_keyring_login_remove_secret (GNOME_KEYRING_ITEM_ENCRYPTION_KEY_PASSWORD,
+			                                 "unique", object->unique, NULL);
+		g_hash_table_remove (slot->auth_cache, &object->handle);
+		break;
+		
+	case CKR_OK:
+		g_hash_table_remove (slot->auth_specific, &handle);
+		break;
+		
+	default:
+		break;
+	}
+	
+	gkr_secure_strfree ((gchar*)*pin);
+	
+	*pin = NULL;
+	*pin_len = 0;
+}
+
+gboolean
+gkr_pkcs11_auth_login_user_prompt (CK_SESSION_HANDLE handle, CK_TOKEN_INFO *info,
+                                   CK_UTF8CHAR_PTR *pin, CK_ULONG *pin_len)
+{
+	GkrAskRequest *ask;
+	gchar *label;
+	gchar *secondary;
+	gchar *manufacturer;
+	gchar *serial;
+	const gchar *password;
+	gboolean ret = TRUE;
+	guint flags;
+	
+	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 (gkr_keyring_login_is_usable ()) {
+
+		password = gkr_keyring_login_lookup_secret (GNOME_KEYRING_ITEM_CHAINED_KEYRING_PASSWORD, 
+		                                            "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 */
+	flags = GKR_ASK_REQUEST_PASSWORD | GKR_ASK_REQUEST_OK_DENY_BUTTONS;
+	ask = gkr_ask_request_new (_("Unlock certificate/key storage"), 
+	                           _("Enter password to unlock the certificate/key storage"), flags); 
+	gkr_ask_request_set_secondary (ask, secondary);
+	
+	secondary = g_strdup_printf (_("An application wants access to the certificate/key storage '%s', but it is locked"), label);
+	gkr_ask_request_set_secondary (ask, secondary);
+	g_free (secondary);
+	g_free (label);
+	
+	if (gkr_keyring_login_is_usable ())
+		gkr_ask_request_set_check_option (ask, _("Automatically unlock secure storage when I log in."));
+
+	/* Prompt the user */
+	gkr_ask_daemon_process (ask);
+
+	/* If the user denied ... */
+	if (ask->response == GKR_ASK_RESPONSE_DENY) {
+		ret = FALSE;
+		
+	/* User cancelled or failure */
+	} else if (ask->response < GKR_ASK_RESPONSE_ALLOW) {
+		ret = FALSE;
+			
+	/* Successful response */
+	} else {
+		password_to_pin (ask->typed_password, pin, pin_len);
+		ret = TRUE;
+		
+		/* Store forever */
+		if (ask->checked) {
+			gkr_keyring_login_attach_secret (GNOME_KEYRING_ITEM_CHAINED_KEYRING_PASSWORD, 
+			                                 label, ask->typed_password,
+			                                 "manufacturer", manufacturer, 
+			                                 "serial-number", serial,
+			                                 NULL);
+		}
+	}
+	
+	g_free (manufacturer);
+	g_free (serial);
+	g_free (label);
+	
+	g_object_unref (ask);
+	return ret;
+}
+
+void 
+gkr_pkcs11_auth_login_user_done (CK_SESSION_HANDLE handle, CK_TOKEN_INFO *info,
+                                 CK_UTF8CHAR_PTR *pin, CK_ULONG *pin_len, CK_RV rv)
+{
+	gchar *manufacturer;
+	gchar *serial;
+
+	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:
+		
+		/* 
+		 * 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);
+
+		gkr_keyring_login_remove_secret (GNOME_KEYRING_ITEM_CHAINED_KEYRING_PASSWORD,
+		                                 "manufacturer", manufacturer, 
+		                                 "serial-number", serial, 
+		                                 NULL);
+		
+		g_free (manufacturer);
+		g_free (serial);
+		
+		break;
+	}
+	
+	gkr_secure_strfree ((gchar*)*pin);
+	
+	*pin = NULL;
+	*pin_len = 0;
+}
+
+static void
+free_slot_data (SlotData *slot)
+{
+	g_assert (slot);
+	if (slot->auth_cache)
+		g_hash_table_destroy (slot->auth_cache);
+	if (slot->auth_specific)
+		g_hash_table_destroy (slot->auth_specific);
+	g_slice_free (SlotData, slot);
+}
+
+void
+gkr_pkcs11_auth_initialized (void)
+{
+	g_return_if_fail (!per_slot_data);
+	
+	/* Remove information stored about this session */
+	per_slot_data = g_hash_table_new_full (ulong_hash, ulong_equal, ulong_free, 
+	                                       (GDestroyNotify)free_slot_data);
+}
+
+void
+gkr_pkcs11_auth_session_opened (CK_SESSION_HANDLE handle, CK_SESSION_INFO *info)
+{
+	SlotData *slot;
+	
+	g_assert (info);
+	
+	slot = g_hash_table_lookup (per_slot_data, &info->slotID);
+	if (slot == NULL) {
+		slot = g_slice_new0 (SlotData);
+		g_hash_table_replace (per_slot_data, ulong_alloc (info->slotID), slot);
+	}
+
+	/* Track how many open sessions there are */
+	++slot->open_sessions;
+}
+
+void
+gkr_pkcs11_auth_session_closed (CK_SESSION_HANDLE handle, CK_SESSION_INFO *info)
+{
+	SlotData *slot;
+	
+	g_assert (info);
+	g_return_if_fail (per_slot_data);
+	
+	slot = g_hash_table_lookup (per_slot_data, &info->slotID);
+	g_return_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, &info->slotID);
+}
+
+void
+gkr_pkcs11_auth_session_closed_all (CK_SLOT_ID id)
+{
+	g_return_if_fail (per_slot_data);
+
+	/* Remove all information about this slot */
+	if (!g_hash_table_remove (per_slot_data, &id))
+		g_return_if_reached ();
+}
+
+void
+gkr_pkcs11_auth_finalized (void)
+{
+	g_return_if_fail (per_slot_data);
+	g_hash_table_destroy (per_slot_data);
+	per_slot_data = NULL;
+}

Added: trunk/daemon/pkcs11/gkr-pkcs11-auth.h
==============================================================================
--- (empty file)
+++ trunk/daemon/pkcs11/gkr-pkcs11-auth.h	Thu Jan  8 18:41:26 2009
@@ -0,0 +1,81 @@
+/* 
+ * 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 GKR_PKCS11_AUTH_H_
+#define GKR_PKCS11_AUTH_H_
+
+#include <glib.h>
+
+#include "pkcs11/pkcs11.h"
+
+typedef struct _GkrPkcs11AuthObject {
+	CK_OBJECT_HANDLE handle;
+	CK_OBJECT_CLASS klass;
+	CK_SLOT_ID slot;
+	CK_BBOOL token;
+	gchar *label;
+	gchar *unique;
+} GkrPkcs11AuthObject;
+
+void                            gkr_pkcs11_auth_chain_functions          (CK_FUNCTION_LIST_PTR funcs); 
+
+CK_FUNCTION_LIST_PTR            gkr_pkcs11_auth_get_functions            (void);
+
+gboolean                        gkr_pkcs11_auth_login_user_prompt        (CK_SESSION_HANDLE handle,
+                                                                          CK_TOKEN_INFO *info,
+                                                                          CK_UTF8CHAR_PTR *pin, 
+                                                                          CK_ULONG *pin_len);
+
+void                            gkr_pkcs11_auth_login_user_done          (CK_SESSION_HANDLE handle, 
+                                                                          CK_TOKEN_INFO *info,
+                                                                          CK_UTF8CHAR_PTR *pin, 
+                                                                          CK_ULONG *pin_len,
+                                                                          CK_RV rv);
+
+void                            gkr_pkcs11_auth_login_specific_prepare   (CK_SESSION_HANDLE handle,
+                                                                          GkrPkcs11AuthObject *object);
+
+gboolean                        gkr_pkcs11_auth_login_specific_prompt    (CK_SESSION_HANDLE handle, 
+                                                                          CK_SESSION_INFO *info,
+                                                                          CK_UTF8CHAR_PTR *pin, 
+                                                                          CK_ULONG *pin_len);
+
+void                            gkr_pkcs11_auth_login_specific_done      (CK_SESSION_HANDLE handle, 
+                                                                          CK_SESSION_INFO *info,
+                                                                          CK_UTF8CHAR_PTR *pin, 
+                                                                          CK_ULONG *pin_len,
+                                                                          CK_RV rv);
+
+void                            gkr_pkcs11_auth_initialized              (void);
+
+void                            gkr_pkcs11_auth_session_opened           (CK_SESSION_HANDLE handle,
+                                                                          CK_SESSION_INFO *info);
+
+void                            gkr_pkcs11_auth_session_closed           (CK_SESSION_HANDLE handle,
+                                                                          CK_SESSION_INFO *info);
+
+void                            gkr_pkcs11_auth_session_closed_all       (CK_SLOT_ID slot);
+
+void                            gkr_pkcs11_auth_finalized                (void);
+
+void                            gkr_pkcs11_auth_free_object              (GkrPkcs11AuthObject *info);
+
+#endif /* GKR_PKCS11_AUTH_H_ */

Added: trunk/daemon/pkcs11/gkr-pkcs11-daemon.c
==============================================================================
--- (empty file)
+++ trunk/daemon/pkcs11/gkr-pkcs11-daemon.c	Thu Jan  8 18:41:26 2009
@@ -0,0 +1,209 @@
+/* 
+ * 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 "gkr-pkcs11-auth.h"
+#include "gkr-pkcs11-daemon.h"
+
+#include "pkcs11/ssh-store/gck-ssh-store.h"
+#include "pkcs11/rpc-layer/gck-rpc-layer.h"
+#include "pkcs11/ssh-agent/gck-ssh-agent.h"
+
+#include "common/gkr-async.h"
+#include "common/gkr-daemon-util.h"
+#include "common/gkr-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_async_begin_concurrent ();
+ *	
+ *		gck_call_xxxx (xxx);
+ *	
+ *	gkr_async_end_concurrent ();
+ */
+
+/* The top level of our internal PKCS#11 module stack */
+static CK_FUNCTION_LIST_PTR pkcs11_roof = NULL;
+
+static void
+pkcs11_daemon_cleanup (gpointer unused)
+{
+	CK_RV rv;
+	
+	g_assert (pkcs11_roof);
+	
+	gkr_async_begin_concurrent ();
+	
+		rv = (pkcs11_roof->C_Finalize) (NULL);
+	
+	gkr_async_end_concurrent ();
+	
+	if (rv != CKR_OK)
+		g_warning ("couldn't finalize internal PKCS#11 stack (code: %d)", (gint)rv);
+
+	pkcs11_roof = NULL;
+}
+
+gboolean
+gkr_pkcs11_daemon_initialize (void)
+{
+	CK_FUNCTION_LIST_PTR ssh_store;
+	CK_RV rv;
+
+	/* Now initialize them all */
+	gkr_async_begin_concurrent ();
+
+		/* Initialize the SSH storage */
+		ssh_store = gck_ssh_store_get_functions ();
+
+		/* TODO: More will come here, but currently this is it */
+
+		/* The auth component is the top component */
+		gkr_pkcs11_auth_chain_functions (ssh_store);
+		pkcs11_roof = gkr_pkcs11_auth_get_functions ();
+	
+		rv = (pkcs11_roof->C_Initialize) (NULL);
+
+	gkr_async_end_concurrent ();
+
+	if (rv != CKR_OK) {
+		g_warning ("couldn't initialize internal PKCS#11 stack (code: %d)", (gint)rv);
+		return FALSE;
+	}		
+	
+	gkr_cleanup_register (pkcs11_daemon_cleanup, NULL);
+	return TRUE;
+}
+
+#if 0
+static void
+pkcs11_rpc_cleanup (gpointer unused)
+{
+	gkr_async_begin_concurrent ();
+
+		gck_rpc_layer_uninitialize ();
+		
+	gkr_async_end_concurrent ();
+}
+
+static gboolean
+accept_rpc_client (GIOChannel *channel, GIOCondition cond, gpointer unused)
+{
+	gkr_async_begin_concurrent ();
+
+		if (cond == G_IO_IN)
+			gck_rpc_layer_accept ();
+		
+	gkr_async_end_concurrent ();
+	
+	return TRUE;
+}
+
+gboolean
+gkr_pkcs11_daemon_setup_pkcs11 (void)
+{
+	GIOChannel *channel;
+	const gchar *base_dir;
+	int sock;
+	
+	g_assert (pkcs11_roof);
+
+	base_dir = gkr_daemon_util_get_master_directory ();
+	g_return_val_if_fail (base_dir, FALSE);
+
+	gkr_async_begin_concurrent ();
+
+		sock = gck_rpc_layer_initialize (base_dir, pkcs11_roof, NULL);
+		
+	gkr_async_end_concurrent ();
+	
+	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);
+
+	gkr_cleanup_register (pkcs11_rpc_cleanup, NULL);
+
+	return TRUE;
+}
+#endif
+
+static void
+pkcs11_ssh_cleanup (gpointer unused)
+{
+	gkr_async_begin_concurrent ();
+
+		gck_ssh_agent_uninitialize ();
+		
+	gkr_async_end_concurrent ();
+}
+
+static gboolean
+accept_ssh_client (GIOChannel *channel, GIOCondition cond, gpointer unused)
+{
+	gkr_async_begin_concurrent ();
+
+		if (cond == G_IO_IN)
+			gck_ssh_agent_accept ();
+		
+	gkr_async_end_concurrent ();
+				
+	return TRUE;
+}
+
+gboolean
+gkr_pkcs11_daemon_setup_ssh (void)
+{
+	GIOChannel *channel;
+	const gchar *base_dir;
+	int sock;
+	
+	g_assert (pkcs11_roof);
+
+	base_dir = gkr_daemon_util_get_master_directory ();
+	g_return_val_if_fail (base_dir, FALSE);
+
+	gkr_async_begin_concurrent ();
+	
+		sock = gck_ssh_agent_initialize (base_dir, pkcs11_roof);
+		
+	gkr_async_end_concurrent ();
+	
+	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 */
+	gkr_daemon_util_push_environment ("SSH_AUTH_SOCK", g_getenv ("SSH_AUTH_SOCK"));
+
+	gkr_cleanup_register (pkcs11_ssh_cleanup, NULL);
+
+	return TRUE;
+}

Added: trunk/daemon/pkcs11/gkr-pkcs11-daemon.h
==============================================================================
--- (empty file)
+++ trunk/daemon/pkcs11/gkr-pkcs11-daemon.h	Thu Jan  8 18:41:26 2009
@@ -0,0 +1,33 @@
+/* 
+ * 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 GKRPKCS11DAEMON_H_
+#define GKRPKCS11DAEMON_H_
+
+#include <glib.h>
+
+gboolean      gkr_pkcs11_daemon_initialize       (void);
+
+gboolean      gkr_pkcs11_daemon_setup_pkcs11     (void);
+
+gboolean      gkr_pkcs11_daemon_setup_ssh        (void);
+
+#endif /* GKRPKCS11DAEMON_H_ */

Modified: trunk/daemon/pkix/gkr-pkix-asn1.c
==============================================================================
--- trunk/daemon/pkix/gkr-pkix-asn1.c	(original)
+++ trunk/daemon/pkix/gkr-pkix-asn1.c	Thu Jan  8 18:41:26 2009
@@ -30,12 +30,18 @@
 
 #include <libtasn1.h>
 
+/* 
+ * TODO: This code is on it's way out, but conflicts with symbols 
+ * in new code. Quick fix. 
+ */
+#define pk_asn1_tab old_pk_asn1_tab
+#define pkix_asn1_tab old_pkix_asn1_tab
 
 /* 
  * HACK: asn1Parser defines these arrays as extern const, which gives 
  * gcc a fit. So we def it out. 
  */
- 
+
 #define extern 
 #include "asn1-def-pk.h"
 #include "asn1-def-pkix.h"

Modified: trunk/daemon/ssh/Makefile.am
==============================================================================
--- trunk/daemon/ssh/Makefile.am	(original)
+++ trunk/daemon/ssh/Makefile.am	Thu Jan  8 18:41:26 2009
@@ -13,9 +13,6 @@
 	$(GLIB_CFLAGS)
 
 libgkr_ssh_la_SOURCES = \
-	gkr-ssh-daemon.h \
-	gkr-ssh-daemon-io.c \
-	gkr-ssh-daemon-ops.c \
 	gkr-ssh-private.h \
 	gkr-ssh-proto.c \
 	gkr-ssh-storage.c gkr-ssh-storage.h 

Modified: trunk/daemon/ui/gkr-ask-daemon.c
==============================================================================
--- trunk/daemon/ui/gkr-ask-daemon.c	(original)
+++ trunk/daemon/ui/gkr-ask-daemon.c	Thu Jan  8 18:41:26 2009
@@ -76,7 +76,8 @@
 	gboolean ret;
 	
 	client = gkr_daemon_client_get_current ();
-	g_return_val_if_fail (client, FALSE);
+	if (client == NULL)
+		return FALSE;
 	
 	denied = g_object_get_data (G_OBJECT (client), "gkr-ask-daemon.denied");
 	if (!denied)
@@ -100,7 +101,8 @@
 	g_return_if_fail (unique);
 	
 	client = gkr_daemon_client_get_current ();
-	g_return_if_fail (client);
+	if (!client)
+		return;
 
 	/* Associate the denied table with the current client */
 	denied = g_object_get_data (G_OBJECT (client), "gkr-ask-daemon.denied");

Modified: trunk/gp11/gp11-module.c
==============================================================================
--- trunk/gp11/gp11-module.c	(original)
+++ trunk/gp11/gp11-module.c	Thu Jan  8 18:41:26 2009
@@ -369,11 +369,15 @@
 
 	info = gp11_slot_get_token_info (slot);
 	if (info != NULL) {
-		if (info->flags & CKF_PROTECTED_AUTHENTICATION_PATH) {
-			gp11_token_info_free (info);
-			*password = NULL;
-			return TRUE;
-		}
+		
+		/* 
+		 * We'll have tried to login at least once at this point,
+		 * with NULL password. This means that CKF_PROTECTED_AUTHENTICATION_PATH
+		 * tokens have had their chance and we don't need to prompt for it.
+		 */
+
+		if (info->flags & CKF_PROTECTED_AUTHENTICATION_PATH)
+			return FALSE;
 		
 		if (label == NULL)
 			label = allocated = g_strdup (info->label);

Modified: trunk/gp11/gp11-session.c
==============================================================================
--- trunk/gp11/gp11-session.c	(original)
+++ trunk/gp11/gp11-session.c	Thu Jan  8 18:41:26 2009
@@ -1047,10 +1047,7 @@
 		/* Protected authentication path, just go to perform */
 		if (args->protected_auth) {
 			args->state = AUTHENTICATE_PERFORM;
-			do {
-				rv = authenticate_perform (args, base);
-			} while (rv == CKR_PIN_INCORRECT);
-			return rv;
+			return authenticate_perform (args, base);
 		}
 
 		/* Get the label for a prompt */

Modified: trunk/gp11/gp11-slot.c
==============================================================================
--- trunk/gp11/gp11-slot.c	(original)
+++ trunk/gp11/gp11-slot.c	Thu Jan  8 18:41:26 2009
@@ -683,7 +683,7 @@
 		
 		ret = _gp11_module_fire_authenticate_slot (module, args->slot, NULL, &args->password);
 		
-		/* Call is not complete */
+		/* If authenticate returns TRUE then call is not complete */
 		ret = !ret;
 	}
 

Modified: trunk/pkcs11/gck/gck-attributes.c
==============================================================================
--- trunk/pkcs11/gck/gck-attributes.c	(original)
+++ trunk/pkcs11/gck/gck-attributes.c	Thu Jan  8 18:41:26 2009
@@ -43,8 +43,8 @@
 CK_RV
 gck_attribute_set_string (CK_ATTRIBUTE_PTR attr, const gchar* string)
 {
-	g_return_val_if_fail (string, CKR_GENERAL_ERROR);
-	return gck_attribute_set_data (attr, (CK_VOID_PTR)string, strlen (string));
+	return gck_attribute_set_data (attr, (CK_VOID_PTR)string, 
+	                               string ? strlen (string) : 0);
 }
 
 CK_RV

Modified: trunk/pkcs11/gck/gck-object.c
==============================================================================
--- trunk/pkcs11/gck/gck-object.c	(original)
+++ trunk/pkcs11/gck/gck-object.c	Thu Jan  8 18:41:26 2009
@@ -22,6 +22,7 @@
 #include "config.h"
 
 #include "pkcs11/pkcs11.h"
+#include "pkcs11/pkcs11g.h"
 
 #include "gck-attributes.h"
 #include "gck-manager.h"
@@ -34,7 +35,8 @@
 	PROP_0,
 	PROP_HANDLE,
 	PROP_MANAGER,
-	PROP_STORE
+	PROP_STORE,
+	PROP_UNIQUE
 };
 
 enum {
@@ -48,6 +50,7 @@
 	CK_OBJECT_HANDLE handle;
 	GckManager *manager;
 	GckStore *store;
+	gchar *unique;
 };
 
 G_DEFINE_TYPE (GckObject, gck_object, G_TYPE_OBJECT);
@@ -76,6 +79,10 @@
 		return gck_attribute_set_bool (attr, FALSE);
 	case CKA_TOKEN:
 		return gck_attribute_set_bool (attr, (self->pv->handle & GCK_OBJECT_IS_PERMANENT) ? TRUE : FALSE);
+	case CKA_GNOME_UNIQUE:
+		if (self->pv->unique)
+			return gck_attribute_set_string (attr, self->pv->unique);
+		return CKR_ATTRIBUTE_TYPE_INVALID;
 	};
 
 	/* Give store a shot */
@@ -104,6 +111,11 @@
 	case CKA_CLASS:
 		gck_transaction_fail (transaction, CKR_ATTRIBUTE_READ_ONLY);
 		return;
+	case CKA_GNOME_UNIQUE:
+		gck_transaction_fail (transaction, self->pv->unique ? 
+		                                       CKR_ATTRIBUTE_READ_ONLY : 
+		                                       CKR_ATTRIBUTE_TYPE_INVALID);
+		return;
 	};
 
 	/* Give store a shot */
@@ -177,6 +189,7 @@
 	GckObject *self = GCK_OBJECT (obj);
 	
 	g_assert (self->pv->manager == NULL);
+	g_free (self->pv->unique);
 
 	G_OBJECT_CLASS (gck_object_parent_class)->finalize (obj);
 }
@@ -221,6 +234,10 @@
 		
 		g_object_notify (G_OBJECT (self), "store");
 		break;
+	case PROP_UNIQUE:
+		g_return_if_fail (!self->pv->unique);
+		self->pv->unique = g_value_dup_string (value);
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
 		break;
@@ -243,6 +260,9 @@
 	case PROP_STORE:
 		g_value_set_object (value, self->pv->store);
 		break;
+	case PROP_UNIQUE:
+		g_value_set_string (value, gck_object_get_unique (self));
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
 		break;
@@ -279,6 +299,10 @@
 	           g_param_spec_object ("store", "Store", "Object store", 
 	                                GCK_TYPE_STORE, G_PARAM_READWRITE));
 	
+	g_object_class_install_property (gobject_class, PROP_UNIQUE,
+	           g_param_spec_string ("unique", "Unique Identifer", "Machine unique identifier", 
+	                                NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+	
 	signals[NOTIFY_ATTRIBUTE] = g_signal_new ("notify-attribute", GCK_TYPE_OBJECT, 
 	                                G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GckObjectClass, notify_attribute),
 	                                NULL, NULL, g_cclosure_marshal_VOID__ULONG, 
@@ -401,6 +425,13 @@
 	return self->pv->manager;
 }
 
+const gchar*
+gck_object_get_unique (GckObject *self)
+{
+	g_return_val_if_fail (GCK_IS_OBJECT (self), NULL);
+	return self->pv->unique;
+}
+
 CK_RV
 gck_object_unlock (GckObject *self, CK_UTF8CHAR_PTR pin, CK_ULONG n_pin)
 {

Modified: trunk/pkcs11/gck/gck-object.h
==============================================================================
--- trunk/pkcs11/gck/gck-object.h	(original)
+++ trunk/pkcs11/gck/gck-object.h	Thu Jan  8 18:41:26 2009
@@ -72,6 +72,8 @@
 
 GckManager*            gck_object_get_manager            (GckObject *self);
 
+const gchar*           gck_object_get_unique             (GckObject *self);
+
 CK_RV                  gck_object_unlock                 (GckObject *self, 
                                                           CK_UTF8CHAR_PTR pin, 
                                                           CK_ULONG n_pin);

Modified: trunk/pkcs11/pkcs11g.h
==============================================================================
--- trunk/pkcs11/pkcs11g.h	(original)
+++ trunk/pkcs11/pkcs11g.h	Thu Jan  8 18:41:26 2009
@@ -79,6 +79,14 @@
 #define CKV_GNOME_AUTH_CACHE_SESSION                0x40000000
 #define CKV_GNOME_AUTH_CACHE_UNLIMITED              0x80000000
 
+/* -------------------------------------------------------------------
+ * OBJECT UNIQUE IDENTIFIER
+ */
+
+/* A string unique among all objects on a given machine */
+#define CKA_GNOME_UNIQUE                            (CKA_GNOME + 350)
+
+
 /* ----------------------------------------------------------------------
  * TODO: EXTENSIONS BELOW NEED TO BE INDIVIDUALLY CONSIDERED CAREFULLY
  */

Modified: trunk/pkcs11/ssh-agent/gck-ssh-agent-ops.c
==============================================================================
--- trunk/pkcs11/ssh-agent/gck-ssh-agent-ops.c	(original)
+++ trunk/pkcs11/ssh-agent/gck-ssh-agent-ops.c	Thu Jan  8 18:41:26 2009
@@ -883,7 +883,8 @@
 	g_free (hash);
 	
 	if (error) {
-		g_warning ("signing of the data failed: %s", error->message);
+		if (error->code != CKR_FUNCTION_CANCELED)
+			g_message ("signing of the data failed: %s", error->message);
 		g_clear_error (&error);
 		gkr_buffer_add_byte (call->resp, GCK_SSH_RES_FAILURE);
 		return TRUE;
@@ -999,7 +1000,8 @@
 	g_object_unref (key);
 	
 	if (error) {
-		g_warning ("decryption of the data failed: %s", error->message);
+		if (error->code != CKR_FUNCTION_CANCELED)
+			g_message ("decryption of the data failed: %s", error->message);
 		g_clear_error (&error);
 		gkr_buffer_add_byte (call->resp, GCK_SSH_RES_FAILURE);
 		return TRUE;

Modified: trunk/pkcs11/ssh-agent/gck-ssh-agent.c
==============================================================================
--- trunk/pkcs11/ssh-agent/gck-ssh-agent.c	(original)
+++ trunk/pkcs11/ssh-agent/gck-ssh-agent.c	Thu Jan  8 18:41:26 2009
@@ -399,9 +399,11 @@
 	g_return_val_if_fail (prefix, -1);
 	
 	module = gp11_module_new (funcs);
+	gp11_module_set_auto_authenticate (module, TRUE);
+	gp11_module_set_pool_sessions (module, TRUE);
 	sock = gck_ssh_agent_initialize_with_module (prefix, module);
 	g_object_unref (module);
-	
+		
 	return sock;
 }
 
@@ -414,7 +416,7 @@
 	g_return_val_if_fail (prefix, -1);
 	g_return_val_if_fail (GP11_IS_MODULE (module), -1);
 	
-	snprintf (socket_path, sizeof (socket_path), "%s.ssh", prefix);
+	snprintf (socket_path, sizeof (socket_path), "%s/socket.ssh", prefix);
 	unlink (socket_path);
 
 	sock = socket (AF_UNIX, SOCK_STREAM, 0);

Modified: trunk/pkcs11/ssh-store/gck-ssh-module.c
==============================================================================
--- trunk/pkcs11/ssh-store/gck-ssh-module.c	(original)
+++ trunk/pkcs11/ssh-store/gck-ssh-module.c	Thu Jan  8 18:41:26 2009
@@ -102,6 +102,7 @@
 	gchar *private_path;
 	GckManager *manager;
 	GError *error = NULL;
+	gchar *unique;
 	
 	g_return_if_fail (path);
 	g_return_if_fail (GCK_IS_SSH_MODULE (self));
@@ -116,7 +117,10 @@
 	/* Create a key if necessary */
 	key = g_hash_table_lookup (self->keys_by_path, path);
 	if (key == NULL) {
-		key = gck_ssh_private_key_new ();
+		unique = g_strdup_printf ("ssh-store:%s", private_path);
+		key = gck_ssh_private_key_new (unique);
+		g_free (unique);
+		
 		g_hash_table_replace (self->keys_by_path, g_strdup (path), key);
 	}
 	

Modified: trunk/pkcs11/ssh-store/gck-ssh-private-key.c
==============================================================================
--- trunk/pkcs11/ssh-store/gck-ssh-private-key.c	(original)
+++ trunk/pkcs11/ssh-store/gck-ssh-private-key.c	Thu Jan  8 18:41:26 2009
@@ -139,7 +139,7 @@
 	
 	switch (attr->type) {
 	case CKA_LABEL:
-		return gck_attribute_set_string (attr, self->label ? self->label : "");
+		return gck_attribute_set_string (attr, self->label);
 	}
 	
 	return GCK_OBJECT_CLASS (gck_ssh_private_key_parent_class)->get_attribute (base, attr);
@@ -152,10 +152,25 @@
 	return unlock_private_key (self, (const gchar*)pin, n_pin);
 }
 
+static GObject* 
+gck_ssh_private_key_constructor (GType type, guint n_props, GObjectConstructParam *props) 
+{
+	GckSshPrivateKey *self = GCK_SSH_PRIVATE_KEY (G_OBJECT_CLASS (gck_ssh_private_key_parent_class)->constructor(type, n_props, props));
+	gchar *unique;
+	
+	g_return_val_if_fail (self, NULL);	
+
+	unique = g_strdup_printf ("%s.pub", gck_object_get_unique (GCK_OBJECT (self)));
+	self->pubkey = gck_ssh_public_key_new (unique);
+	g_free (unique);
+	
+	return G_OBJECT (self);
+}
+
 static void
 gck_ssh_private_key_init (GckSshPrivateKey *self)
 {
-	self->pubkey = gck_ssh_public_key_new ();
+	
 }
 
 static void
@@ -227,6 +242,7 @@
 	GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 	GckObjectClass *gck_class = GCK_OBJECT_CLASS (klass);
 	
+	gobject_class->constructor = gck_ssh_private_key_constructor;
 	gobject_class->dispose = gck_ssh_private_key_dispose;
 	gobject_class->finalize = gck_ssh_private_key_finalize;
 	gobject_class->set_property = gck_ssh_private_key_set_property;
@@ -249,9 +265,9 @@
  */
 
 GckSshPrivateKey*
-gck_ssh_private_key_new (void)
+gck_ssh_private_key_new (const gchar *unique)
 {
-	return g_object_new (GCK_TYPE_SSH_PRIVATE_KEY, NULL);
+	return g_object_new (GCK_TYPE_SSH_PRIVATE_KEY, "unique", unique, NULL);
 }
 
 gboolean

Modified: trunk/pkcs11/ssh-store/gck-ssh-private-key.h
==============================================================================
--- trunk/pkcs11/ssh-store/gck-ssh-private-key.h	(original)
+++ trunk/pkcs11/ssh-store/gck-ssh-private-key.h	Thu Jan  8 18:41:26 2009
@@ -44,7 +44,7 @@
 
 GType               gck_ssh_private_key_get_type               (void);
 
-GckSshPrivateKey*   gck_ssh_private_key_new                    (void);
+GckSshPrivateKey*   gck_ssh_private_key_new                    (const gchar *unique);
 
 gboolean            gck_ssh_private_key_parse                  (GckSshPrivateKey *self,
                                                                 const gchar *public_path,

Modified: trunk/pkcs11/ssh-store/gck-ssh-public-key.c
==============================================================================
--- trunk/pkcs11/ssh-store/gck-ssh-public-key.c	(original)
+++ trunk/pkcs11/ssh-store/gck-ssh-public-key.c	Thu Jan  8 18:41:26 2009
@@ -129,9 +129,9 @@
  */
 
 GckSshPublicKey*
-gck_ssh_public_key_new (void)
+gck_ssh_public_key_new (const gchar *unique)
 {
-	return g_object_new (GCK_TYPE_SSH_PUBLIC_KEY, NULL);
+	return g_object_new (GCK_TYPE_SSH_PUBLIC_KEY, "unique", unique, NULL);
 }
 
 const gchar*

Modified: trunk/pkcs11/ssh-store/gck-ssh-public-key.h
==============================================================================
--- trunk/pkcs11/ssh-store/gck-ssh-public-key.h	(original)
+++ trunk/pkcs11/ssh-store/gck-ssh-public-key.h	Thu Jan  8 18:41:26 2009
@@ -42,11 +42,11 @@
 
 GType               gck_ssh_public_key_get_type               (void);
 
-GckSshPublicKey*    gck_ssh_public_key_new                    (void);
+GckSshPublicKey*    gck_ssh_public_key_new                    (const gchar *unique);
 
 const gchar*        gck_ssh_public_key_get_label              (GckSshPublicKey *key);
 
 void                gck_ssh_public_key_set_label              (GckSshPublicKey *key,
-                                                                const gchar *label);
+                                                               const gchar *label);
 
 #endif /* __GCK_SSH_PUBLIC_KEY_H__ */

Modified: trunk/po/POTFILES.in
==============================================================================
--- trunk/po/POTFILES.in	(original)
+++ trunk/po/POTFILES.in	Thu Jan  8 18:41:26 2009
@@ -11,6 +11,7 @@
 daemon/pk/gkr-pk-object.c
 daemon/pk/gkr-pk-object-storage.c
 daemon/pk/gkr-pk-storage.c
+daemon/pkcs11/gkr-pkcs11-auth.c
 daemon/pkix/gkr-pkix-parser.c
 daemon/pkix/gkr-pkix-serialize.c
 daemon/ssh/gkr-ssh-storage.c



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