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
- From: nnielsen svn gnome org
- To: svn-commits-list gnome org
- Subject: 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
- Date: Thu, 8 Jan 2009 18:41:27 +0000 (UTC)
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]