gnome-keyring r1473 - in trunk: . daemon/pkcs11 pkcs11 pkcs11/ssh-agent
- From: nnielsen svn gnome org
- To: svn-commits-list gnome org
- Subject: gnome-keyring r1473 - in trunk: . daemon/pkcs11 pkcs11 pkcs11/ssh-agent
- Date: Thu, 22 Jan 2009 22:23:49 +0000 (UTC)
Author: nnielsen
Date: Thu Jan 22 22:23:49 2009
New Revision: 1473
URL: http://svn.gnome.org/viewvc/gnome-keyring?rev=1473&view=rev
Log:
* daemon/pkcs11/gkr-pkcs11-auth.c:
* daemon/pkcs11/gkr-pkcs11-auth.h:
* daemon/pkcs11/gkr-pkcs11-auth-ep.c:
* pkcs11/pkcs11g.h:
* pkcs11/ssh-agent/gck-ssh-agent-ops.c: Added ability to clear cached
authentication for an object. In addition made 'ssh-add -D' clear any
cached authentication for SSH keys. Fixes bug #568525
Modified:
trunk/ChangeLog
trunk/daemon/pkcs11/gkr-pkcs11-auth-ep.c
trunk/daemon/pkcs11/gkr-pkcs11-auth.c
trunk/daemon/pkcs11/gkr-pkcs11-auth.h
trunk/pkcs11/pkcs11g.h
trunk/pkcs11/ssh-agent/gck-ssh-agent-ops.c
Modified: trunk/daemon/pkcs11/gkr-pkcs11-auth-ep.c
==============================================================================
--- trunk/daemon/pkcs11/gkr-pkcs11-auth-ep.c (original)
+++ trunk/daemon/pkcs11/gkr-pkcs11-auth-ep.c Thu Jan 22 22:23:49 2009
@@ -30,25 +30,33 @@
#include <glib.h>
+#include <string.h>
+
/*
* All these function entry points operate outside of any threading locks.
* Any calls to parts of the daemon must be locked inside blocks of:
*
- * gkr_async_end_concurrent ();
+ * DAEMON_ENTER ();
*
* ...
*
- * gkr_async_begin_concurrent ();
+ * DAEMON_LEAVE ();
*/
static CK_FUNCTION_LIST_PTR pkcs11_lower = NULL;
+#define DAEMON_ENTER() \
+ gkr_async_end_concurrent ()
+
+#define DAEMON_LEAVE() \
+ gkr_async_begin_concurrent ()
+
/* --------------------------------------------------------------------------------------
* HELPERS
*/
static GkrPkcs11AuthObject*
-lookup_specific_auth_object (CK_SESSION_HANDLE handle, CK_OBJECT_HANDLE object)
+auth_object_for_context_specific (CK_SESSION_HANDLE handle, CK_OBJECT_HANDLE object)
{
GkrPkcs11AuthObject *info = NULL;
CK_SESSION_INFO session_info;
@@ -136,6 +144,71 @@
return info;
}
+static GkrPkcs11AuthObject*
+auth_object_for_cache (CK_SESSION_HANDLE handle, CK_OBJECT_HANDLE object)
+{
+ GkrPkcs11AuthObject *info = NULL;
+ CK_SESSION_INFO session_info;
+ CK_ATTRIBUTE attrs[3];
+ CK_OBJECT_CLASS klass;
+ gchar *unique = NULL;
+ CK_BBOOL token;
+ CK_ULONG n_attrs;
+ CK_RV rv;
+
+ attrs[0].type = CKA_GNOME_UNIQUE;
+ attrs[0].pValue = unique = NULL;
+ attrs[0].ulValueLen = 0;
+
+ attrs[1].type = CKA_CLASS;
+ attrs[1].pValue = &klass;
+ attrs[1].ulValueLen = sizeof (klass);
+
+ token = CK_FALSE;
+ attrs[2].type = CKA_TOKEN;
+ attrs[2].pValue = &token;
+ attrs[2].ulValueLen = sizeof (token);
+
+ n_attrs = 3;
+
+ /* Make sure we can get the session info */
+ rv = (pkcs11_lower->C_GetSessionInfo) (handle, &session_info);
+ if (rv != CKR_OK)
+ return NULL;
+
+ /* Get attribute sizes */
+ rv = (pkcs11_lower->C_GetAttributeValue) (handle, object, attrs, n_attrs);
+ if (rv != CKR_OK && rv != CKR_ATTRIBUTE_TYPE_INVALID)
+ return NULL;
+
+ /* Allocate memory for big attributes */
+ if (attrs[0].ulValueLen != (CK_ULONG)-1)
+ attrs[0].pValue = unique = g_malloc0 (attrs[0].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 (unique);
+ return NULL;
+ }
+
+ info = g_new0 (GkrPkcs11AuthObject, 1);
+
+ 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 (unique);
+
+ return info;
+}
+
static CK_RV
perform_set_user_pin (CK_SESSION_HANDLE handle, CK_UTF8CHAR_PTR old_pin, CK_ULONG n_old_pin,
CK_UTF8CHAR_PTR new_pin, CK_ULONG n_new_pin, gboolean also_login)
@@ -150,13 +223,13 @@
(pkcs11_lower->C_GetTokenInfo) (session_info.slotID, &token_info) == CKR_OK &&
!(token_info.flags & CKF_PROTECTED_AUTHENTICATION_PATH)) {
- gkr_async_end_concurrent ();
+ DAEMON_ENTER ();
if (!(token_info.flags & CKF_USER_PIN_INITIALIZED))
auth = gkr_pkcs11_auth_init_user_prompt (handle, &token_info, &new_pin, &n_new_pin);
/* TODO: Prompt for other 'change password' case */
- gkr_async_begin_concurrent ();
+ DAEMON_LEAVE ();
}
rv = (pkcs11_lower->C_SetPIN) (handle, old_pin, n_old_pin, new_pin, n_new_pin);
@@ -168,13 +241,13 @@
}
if (auth) {
- gkr_async_end_concurrent ();
+ DAEMON_ENTER ();
if (!(token_info.flags & CKF_USER_PIN_INITIALIZED))
gkr_pkcs11_auth_init_user_done (handle, &token_info, &new_pin, &n_new_pin, rv);
/* TODO: Done for other case */
- gkr_async_begin_concurrent ();
+ DAEMON_LEAVE ();
}
if (login_rv != CKR_OK)
@@ -221,12 +294,12 @@
rv = pkcs11_lower->C_Initialize (init_args);
if (rv == CKR_OK) {
- gkr_async_end_concurrent ();
+ DAEMON_ENTER ();
/* Let our auth caches/storage know we're initializing */
gkr_pkcs11_auth_initialized ();
- gkr_async_begin_concurrent ();
+ DAEMON_LEAVE ();
}
return rv;
@@ -240,12 +313,12 @@
rv = (pkcs11_lower->C_Finalize) (reserved);
if (rv == CKR_OK) {
- gkr_async_end_concurrent ();
+ DAEMON_ENTER ();
/* Let our auth caches/storage know we're initializing */
gkr_pkcs11_auth_finalized ();
- gkr_async_begin_concurrent ();
+ DAEMON_LEAVE ();
}
return rv;
@@ -322,12 +395,12 @@
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 ();
+ DAEMON_ENTER ();
/* Track this session in our auth layer */
gkr_pkcs11_auth_session_opened (*handle, &session_info);
- gkr_async_begin_concurrent ();
+ DAEMON_LEAVE ();
}
}
@@ -346,12 +419,12 @@
rv = (pkcs11_lower->C_CloseSession) (handle);
if (rv == CKR_OK && have_session_info) {
- gkr_async_end_concurrent ();
+ DAEMON_ENTER ();
/* Track this session closure in our auth cache/store */
gkr_pkcs11_auth_session_closed (handle, &session_info);
- gkr_async_begin_concurrent ();
+ DAEMON_LEAVE ();
}
return rv;
@@ -363,12 +436,12 @@
CK_RV rv = (pkcs11_lower->C_CloseAllSessions) (id);
if (rv == CKR_OK) {
- gkr_async_end_concurrent ();
+ DAEMON_ENTER ();
/* Track this session closure in our auth cache/store */
gkr_pkcs11_auth_session_closed_all (id);
- gkr_async_begin_concurrent ();
+ DAEMON_LEAVE ();
}
return rv;
@@ -441,7 +514,7 @@
/*
* Try and initialize the token login, gnome-keyring modules allow
- * this to be called on CKU_USER if no user pin has yet been set.
+ * C_SetPIN to be called on with a NULL if no user pin has yet been set.
*/
if (user_type == CKU_USER)
@@ -467,7 +540,7 @@
/* Loop until logged in or user cancels */
while (rv == CKR_PIN_INCORRECT) {
- gkr_async_end_concurrent ();
+ DAEMON_ENTER ();
switch (user_type) {
case CKU_CONTEXT_SPECIFIC:
auth = gkr_pkcs11_auth_login_specific_prompt (handle, &session_info, &pin, &pin_len);
@@ -478,7 +551,7 @@
default:
break;
};
- gkr_async_begin_concurrent ();
+ DAEMON_LEAVE ();
if (!auth) {
rv = CKR_FUNCTION_CANCELED;
@@ -488,7 +561,7 @@
/* Try the login again */
rv = (pkcs11_lower->C_Login) (handle, user_type, pin, pin_len);
- gkr_async_end_concurrent ();
+ DAEMON_ENTER ();
switch (user_type) {
case CKU_CONTEXT_SPECIFIC:
gkr_pkcs11_auth_login_specific_done (handle, &session_info, &pin, &pin_len, rv);
@@ -499,7 +572,7 @@
default:
break;
};
- gkr_async_begin_concurrent ();
+ DAEMON_LEAVE ();
}
return rv;
@@ -515,7 +588,14 @@
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. */
+ CK_ULONG i;
+
+ /* Can't set auth cached when creating */
+ for (i = 0; i < count; ++i) {
+ if (template[i].type == CKA_GNOME_AUTH_CACHED)
+ return CKR_TEMPLATE_INCONSISTENT;
+ }
+
return (pkcs11_lower->C_CreateObject) (handle, template, count, new_object);
}
@@ -524,7 +604,14 @@
CK_ATTRIBUTE_PTR template, CK_ULONG count,
CK_OBJECT_HANDLE_PTR new_object)
{
- /* TODO: Need to implement CKA_GNOME_AUTH_CACHE attributes. */
+ CK_ULONG i;
+
+ /* Can't set auth cached when copying */
+ for (i = 0; i < count; ++i) {
+ if (template[i].type == CKA_GNOME_AUTH_CACHED)
+ return CKR_TEMPLATE_INCONSISTENT;
+ }
+
return (pkcs11_lower->C_CopyObject) (handle, object, template, count, new_object);
}
@@ -545,38 +632,298 @@
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);
+ gboolean have_auth = FALSE;
+ GkrPkcs11AuthObject *info;
+ CK_ATTRIBUTE_PTR normal;
+ CK_ULONG n_normal;
+ CK_RV rv = CKR_OK;
+ CK_BBOOL cached;
+ CK_ULONG i, n;
+
+ /* Are there auth custom attributes? */
+ for (i = 0; i < count; ++i) {
+ if (template[i].type == CKA_GNOME_AUTH_CACHED)
+ have_auth = TRUE;
+ }
+
+ /* No custom attributes, just pass through */
+ if (!have_auth)
+ return (pkcs11_lower->C_GetAttributeValue) (handle, object, template, count);
+
+ normal = g_new0 (CK_ATTRIBUTE, count);
+ n_normal = 0;
+
+ /* Shallow copy all non-auth attributes into our own buffer */
+ for (i = 0; i < count; ++i) {
+ if (template[i].type != CKA_GNOME_AUTH_CACHED) {
+ memcpy (normal + n_normal, template + i, sizeof (CK_ATTRIBUTE));
+ ++n_normal;
+ }
+ }
+
+ /* Call the lower level with our copy */
+ if (n_normal > 0) {
+ rv = (pkcs11_lower->C_GetAttributeValue) (handle, object, normal, n_normal);
+
+ /* Actual error codes from lower level */
+ if (rv != CKR_BUFFER_TOO_SMALL && rv != CKR_ATTRIBUTE_SENSITIVE &&
+ rv != CKR_ATTRIBUTE_TYPE_INVALID && rv != CKR_OK) {
+ g_free (normal);
+ return rv;
+ }
+ }
+
+ /* Lookup cache information about the object */
+ cached = FALSE;
+ info = auth_object_for_cache (handle, object);
+ if (info != NULL) {
+ DAEMON_ENTER ();
+ {
+ gkr_pkcs11_auth_cached_lookup (info, &cached);
+ gkr_pkcs11_auth_free_object (info);
+ }
+ DAEMON_LEAVE ();
+ }
+
+ /* Fill in all the attributes appropriately */
+ for (i = 0, n = 0; i < count; ++i, ++n) {
+ if (template[i].type == CKA_GNOME_AUTH_CACHED) {
+
+ if (template[i].pValue && template[i].ulValueLen < 1) {
+ rv = CKR_BUFFER_TOO_SMALL;
+ template[i].ulValueLen = 1;
+ } else if (!template[i].pValue) {
+ template[i].ulValueLen = 1;
+ } else {
+ *((CK_BBOOL*)template[i].pValue) = cached;
+ template[i].ulValueLen = 1;
+ }
+
+ /* A normal attribute */
+ } else {
+ /* This should never happen with a well behaved module */
+ if (n >= n_normal || template[i].type != normal[n].type) {
+ g_warning ("lower level PKCS#11 module changed attribute type");
+ rv = CKR_GENERAL_ERROR;
+ break;
+ }
+
+ /* Remember we just made a shallow copy, so this is enough */
+ memcpy (template + i, normal + n, sizeof (CK_ATTRIBUTE));
+ }
+ }
+
+ g_free (normal);
+ return rv;
}
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);
+ gboolean have_auth = FALSE;
+ GkrPkcs11AuthObject *info;
+ CK_ATTRIBUTE_PTR normal;
+ CK_ULONG n_normal;
+ CK_RV rv = CKR_OK;
+ CK_BBOOL cached;
+ CK_ULONG i;
+
+ /* Are there auth custom attributes, also validate. */
+ for (i = 0; i < count; ++i) {
+ if (template[i].type == CKA_GNOME_AUTH_CACHED) {
+ have_auth = TRUE;
+ if (template[i].ulValueLen != sizeof (CK_BBOOL))
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ cached = *((CK_BBOOL*)template[i].pValue);
+ if (cached != CK_FALSE)
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+ }
+
+ /* No custom attributes, just pass through */
+ if (!have_auth)
+ return (pkcs11_lower->C_SetAttributeValue) (handle, object, template, count);
+
+ normal = g_new0 (CK_ATTRIBUTE, count);
+ n_normal = 0;
+
+ /* Shallow copy all non-auth attributes into our own buffer */
+ for (i = 0; i < count; ++i) {
+ if (template[i].type != CKA_GNOME_AUTH_CACHED) {
+ memcpy (normal + n_normal, template + i, sizeof (CK_ATTRIBUTE));
+ ++n_normal;
+ }
+ }
+
+ /* Call the lower level with our copy */
+ if (n_normal > 0) {
+ rv = (pkcs11_lower->C_SetAttributeValue) (handle, object, normal, n_normal);
+
+ /* Lower level failed, don't commit ours */
+ if (rv != CKR_OK) {
+ g_free (normal);
+ return rv;
+ }
+ }
+
+ /* Store the custom attributes appropriately */
+ info = auth_object_for_cache (handle, object);
+ if (info != NULL) {
+ DAEMON_ENTER ();
+ {
+ g_assert (cached == CK_FALSE);
+ gkr_pkcs11_auth_cached_clear (info);
+ }
+ DAEMON_LEAVE ();
+ }
+
+ g_free (normal);
+ return rv;
}
static CK_RV
-auth_C_FindObjectsInit (CK_SESSION_HANDLE handle, CK_ATTRIBUTE_PTR template,
- CK_ULONG count)
+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);
+ CK_SESSION_INFO session_info;
+ gboolean have_auth = FALSE;
+ CK_ATTRIBUTE_PTR normal;
+ CK_ULONG n_normal;
+ CK_BBOOL cached;
+ CK_ULONG i;
+ CK_RV rv;
+
+ /* Are there auth custom attributes, also validate. */
+ for (i = 0; i < count; ++i) {
+ if (template[i].type == CKA_GNOME_AUTH_CACHED) {
+ if (template[i].ulValueLen == sizeof (CK_BBOOL)) {
+ cached = *((CK_BBOOL*)template[i].pValue);
+ have_auth = TRUE;
+ break;
+ }
+ }
+ }
+
+ /* No custom attributes, just pass through */
+ if (!have_auth)
+ return (pkcs11_lower->C_FindObjectsInit) (handle, template, count);
+
+ normal = g_new0 (CK_ATTRIBUTE, count);
+ n_normal = 0;
+
+ /* Shallow copy all non-auth attributes into our own buffer */
+ for (i = 0; i < count; ++i) {
+ if (template[i].type != CKA_GNOME_AUTH_CACHED) {
+ memcpy (normal + n_normal, template + i, sizeof (CK_ATTRIBUTE));
+ ++n_normal;
+ }
+ }
+
+ rv = (pkcs11_lower->C_FindObjectsInit) (handle, normal, n_normal);
+
+ if (rv != CKR_OK) {
+ g_free (normal);
+ return rv;
+ }
+
+
+ if ((pkcs11_lower->C_GetSessionInfo) (handle, &session_info) == CKR_OK) {
+ DAEMON_ENTER ();
+ {
+ /* Store away our custom attributes */
+ gkr_pkcs11_auth_cached_set_filter (handle, &session_info, &cached);
+ }
+ DAEMON_LEAVE ();
+ }
+
+ return rv;
}
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);
+ gboolean have_auth = FALSE;
+ CK_SESSION_INFO session_info;
+ GkrPkcs11AuthObject *info;
+ CK_OBJECT_HANDLE_PTR normal;
+ CK_ULONG n_normal, i;
+ CK_BBOOL is_cached;
+ CK_BBOOL cached;
+ CK_RV rv;
+
+ if ((pkcs11_lower->C_GetSessionInfo) (handle, &session_info) == CKR_OK) {
+ DAEMON_ENTER ();
+ {
+ have_auth = gkr_pkcs11_auth_cached_get_filter (handle, &session_info, &cached);
+ }
+ DAEMON_LEAVE ();
+ }
+
+ /* No custom attributes, just pass through */
+ if (!have_auth)
+ return (pkcs11_lower->C_FindObjects) (handle, objects, max_count, count);
+
+ if (count == NULL)
+ return CKR_ARGUMENTS_BAD;
+ if (max_count == 0)
+ return CKR_OK;
+
+ normal = g_new0 (CK_OBJECT_HANDLE, max_count);
+
+ *count = 0;
+ while (*count < max_count) {
+
+ /* Get a block of objects from lower module, as many as will fit */
+ rv = (pkcs11_lower->C_FindObjects) (handle, normal, max_count - *count, &n_normal);
+ if (rv != CKR_OK)
+ break;
+ if (n_normal == 0)
+ break;
+
+ /* Filter those objects */
+ for (i = 0; i < n_normal; ++i) {
+
+ is_cached = FALSE;
+ info = auth_object_for_cache (handle, normal[i]);
+ if (info != NULL) {
+ DAEMON_ENTER ();
+ {
+ gkr_pkcs11_auth_cached_lookup (info, &is_cached);
+ gkr_pkcs11_auth_free_object (info);
+ }
+ DAEMON_LEAVE ();
+ }
+
+ /* Compare what we found */
+ if (is_cached != cached)
+ continue;
+
+ /* Add it to the output */
+ g_assert (*count < max_count);
+ objects[*count] = normal[i];
+ ++(*count);
+ }
+ }
+
+ g_free (normal);
+ return rv;
}
static CK_RV
auth_C_FindObjectsFinal (CK_SESSION_HANDLE handle)
{
- /* TODO: Need to implement CKA_GNOME_AUTH_CACHE attributes. */
+ CK_SESSION_INFO session_info;
+
+ if ((pkcs11_lower->C_GetSessionInfo) (handle, &session_info) == CKR_OK) {
+ DAEMON_ENTER ();
+ {
+ /* Clear out custom attribute state */
+ gkr_pkcs11_auth_cached_set_filter (handle, &session_info, NULL);
+ }
+ DAEMON_LEAVE ();
+ }
+
return (pkcs11_lower->C_FindObjectsFinal) (handle);
}
@@ -589,13 +936,13 @@
rv = (pkcs11_lower->C_EncryptInit) (handle, mechanism, key);
if (rv == CKR_OK) {
- object = lookup_specific_auth_object (handle, key);
+ object = auth_object_for_context_specific (handle, key);
if (object != NULL) {
- gkr_async_end_concurrent ();
+ DAEMON_ENTER ();
gkr_pkcs11_auth_login_specific_prepare (handle, object);
- gkr_async_begin_concurrent ();
+ DAEMON_LEAVE ();
}
}
@@ -643,13 +990,13 @@
rv = (pkcs11_lower->C_DecryptInit) (handle, mechanism, key);
if (rv == CKR_OK) {
- object = lookup_specific_auth_object (handle, key);
+ object = auth_object_for_context_specific (handle, key);
if (object != NULL) {
- gkr_async_end_concurrent ();
+ DAEMON_ENTER ();
gkr_pkcs11_auth_login_specific_prepare (handle, object);
- gkr_async_begin_concurrent ();
+ DAEMON_LEAVE ();
}
}
@@ -728,13 +1075,13 @@
rv = (pkcs11_lower->C_SignInit) (handle, mechanism, key);
if (rv == CKR_OK) {
- object = lookup_specific_auth_object (handle, key);
+ object = auth_object_for_context_specific (handle, key);
if (object != NULL) {
- gkr_async_end_concurrent ();
+ DAEMON_ENTER ();
gkr_pkcs11_auth_login_specific_prepare (handle, object);
- gkr_async_begin_concurrent ();
+ DAEMON_LEAVE ();
}
}
@@ -780,13 +1127,13 @@
rv = (pkcs11_lower->C_SignRecoverInit) (handle, mechanism, key);
if (rv == CKR_OK) {
- object = lookup_specific_auth_object (handle, key);
+ object = auth_object_for_context_specific (handle, key);
if (object != NULL) {
- gkr_async_end_concurrent ();
+ DAEMON_ENTER ();
gkr_pkcs11_auth_login_specific_prepare (handle, object);
- gkr_async_begin_concurrent ();
+ DAEMON_LEAVE ();
}
}
@@ -814,13 +1161,13 @@
rv = (pkcs11_lower->C_VerifyInit) (handle, mechanism, key);
if (rv == CKR_OK) {
- object = lookup_specific_auth_object (handle, key);
+ object = auth_object_for_context_specific (handle, key);
if (object != NULL) {
- gkr_async_end_concurrent ();
+ DAEMON_ENTER ();
gkr_pkcs11_auth_login_specific_prepare (handle, object);
- gkr_async_begin_concurrent ();
+ DAEMON_LEAVE ();
}
}
@@ -866,13 +1213,13 @@
rv = (pkcs11_lower->C_VerifyRecoverInit) (handle, mechanism, key);
if (rv == CKR_OK) {
- object = lookup_specific_auth_object (handle, key);
+ object = auth_object_for_context_specific (handle, key);
if (object != NULL) {
- gkr_async_end_concurrent ();
+ DAEMON_ENTER ();
gkr_pkcs11_auth_login_specific_prepare (handle, object);
- gkr_async_begin_concurrent ();
+ DAEMON_LEAVE ();
}
}
@@ -947,6 +1294,14 @@
CK_ATTRIBUTE_PTR template, CK_ULONG count,
CK_OBJECT_HANDLE_PTR key)
{
+ CK_ULONG i;
+
+ /* Can't set auth cached when creating */
+ for (i = 0; i < count; ++i) {
+ if (template[i].type == CKA_GNOME_AUTH_CACHED)
+ return CKR_TEMPLATE_INCONSISTENT;
+ }
+
return (pkcs11_lower->C_GenerateKey) (handle, mechanism, template, count, key);
}
@@ -956,6 +1311,19 @@
CK_ATTRIBUTE_PTR priv_template, CK_ULONG priv_count,
CK_OBJECT_HANDLE_PTR pub_key, CK_OBJECT_HANDLE_PTR priv_key)
{
+ CK_ULONG i;
+
+ /* Can't set auth cached when creating */
+ for (i = 0; i < pub_count; ++i) {
+ if (pub_template[i].type == CKA_GNOME_AUTH_CACHED)
+ return CKR_TEMPLATE_INCONSISTENT;
+ }
+
+ for (i = 0; i < priv_count; ++i) {
+ if (priv_template[i].type == CKA_GNOME_AUTH_CACHED)
+ return CKR_TEMPLATE_INCONSISTENT;
+ }
+
return (pkcs11_lower->C_GenerateKeyPair) (handle, mechanism, pub_template, pub_count, priv_template, priv_count, pub_key, priv_key);
}
@@ -973,6 +1341,14 @@
CK_ULONG wrapped_key_len, CK_ATTRIBUTE_PTR template,
CK_ULONG count, CK_OBJECT_HANDLE_PTR key)
{
+ CK_ULONG i;
+
+ /* Can't set auth cached when creating */
+ for (i = 0; i < count; ++i) {
+ if (template[i].type == CKA_GNOME_AUTH_CACHED)
+ return CKR_TEMPLATE_INCONSISTENT;
+ }
+
return (pkcs11_lower->C_UnwrapKey) (handle, mechanism, unwrapping_key, wrapped_key, wrapped_key_len, template, count, key);
}
@@ -981,6 +1357,14 @@
CK_OBJECT_HANDLE base_key, CK_ATTRIBUTE_PTR template,
CK_ULONG count, CK_OBJECT_HANDLE_PTR key)
{
+ CK_ULONG i;
+
+ /* Can't set auth cached when creating */
+ for (i = 0; i < count; ++i) {
+ if (template[i].type == CKA_GNOME_AUTH_CACHED)
+ return CKR_TEMPLATE_INCONSISTENT;
+ }
+
return (pkcs11_lower->C_DeriveKey) (handle, mechanism, base_key, template, count, key);
}
Modified: trunk/daemon/pkcs11/gkr-pkcs11-auth.c
==============================================================================
--- trunk/daemon/pkcs11/gkr-pkcs11-auth.c (original)
+++ trunk/daemon/pkcs11/gkr-pkcs11-auth.c Thu Jan 22 22:23:49 2009
@@ -40,7 +40,8 @@
typedef struct _SlotData {
gint open_sessions;
- GHashTable *auth_specific;
+ GHashTable *session_to_specific;
+ GHashTable *session_to_filter;
GHashTable *auth_cache;
} SlotData;
@@ -75,15 +76,6 @@
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)
{
@@ -173,12 +165,12 @@
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);
+ if (slot->session_to_specific == NULL)
+ slot->session_to_specific = g_hash_table_new_full (ulong_hash, ulong_equal, ulong_free,
+ (GDestroyNotify)gkr_pkcs11_auth_free_object);
/* Store the object info for a later prompt */
- g_hash_table_replace (slot->auth_specific, ulong_alloc (handle), object);
+ g_hash_table_replace (slot->session_to_specific, ulong_alloc (handle), object);
}
gboolean
@@ -202,11 +194,11 @@
/* Lookup the structure for this slot */
slot = g_hash_table_lookup (per_slot_data, &info->slotID);
- if (slot == NULL || slot->auth_specific == NULL)
+ if (slot == NULL || slot->session_to_specific == NULL)
return FALSE;
/* Find the object we're authenticating */
- object = g_hash_table_lookup (slot->auth_specific, &handle);
+ object = g_hash_table_lookup (slot->session_to_specific, &handle);
if (object == NULL)
return FALSE;
@@ -293,9 +285,9 @@
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);
+ g_assert (slot != NULL && slot->session_to_specific != NULL);
- object = g_hash_table_lookup (slot->auth_specific, &handle);
+ object = g_hash_table_lookup (slot->session_to_specific, &handle);
g_assert (object);
switch (rv) {
@@ -311,7 +303,7 @@
break;
case CKR_OK:
- g_hash_table_remove (slot->auth_specific, &handle);
+ g_hash_table_remove (slot->session_to_specific, &handle);
break;
default:
@@ -584,14 +576,140 @@
*pin_len = 0;
}
+/* ---------------------------------------------------------------------------------
+ * AUTH CACHED STATUS
+ */
+
+/*
+ * Given information about an object, see if we have
+ * authentication cached, whether for the session or
+ * long term in the keyrings.
+ */
+void
+gkr_pkcs11_auth_cached_lookup (GkrPkcs11AuthObject *object, CK_BBOOL *cached)
+{
+ SlotData *slot;
+
+ g_assert (object);
+ g_assert (cached);
+
+ *cached = FALSE;
+
+ /* Lookup the structure for this slot */
+ slot = g_hash_table_lookup (per_slot_data, &object->slot);
+ g_return_if_fail (slot);
+
+ /* Look in our internal password cache */
+ if (slot->auth_cache) {
+ if (g_hash_table_lookup (slot->auth_cache, &object->handle) != NULL) {
+ *cached = TRUE;
+ return;
+ }
+ }
+
+ if (object->unique && object->token && gkr_keyring_login_is_usable ()) {
+ if (gkr_keyring_login_lookup_secret (GNOME_KEYRING_ITEM_ENCRYPTION_KEY_PASSWORD,
+ "unique", object->unique, NULL) != NULL) {
+ *cached = TRUE;
+ return;
+ }
+ }
+
+ return;
+}
+
+/*
+ * Clear any cached authentication for an object whether it's just cached
+ * for the session, or for the long term in the keyrings.
+ */
+void
+gkr_pkcs11_auth_cached_clear (GkrPkcs11AuthObject *object)
+{
+ SlotData *slot;
+
+ g_assert (object);
+
+ /* Lookup the structure for this slot */
+ slot = g_hash_table_lookup (per_slot_data, &object->slot);
+ g_return_if_fail (slot);
+
+ if (slot->auth_cache)
+ g_hash_table_remove (slot->auth_cache, &object->handle);
+
+ if (object->unique && object->token && gkr_keyring_login_is_usable ())
+ gkr_keyring_login_remove_secret (GNOME_KEYRING_ITEM_ENCRYPTION_KEY_PASSWORD,
+ "unique", object->unique, NULL);
+}
+
+void
+gkr_pkcs11_auth_cached_set_filter (CK_SESSION_HANDLE handle, CK_SESSION_INFO *info, CK_BBOOL *cached)
+{
+ SlotData *slot;
+
+ /*
+ * Stash away a filter of a cached attribute for a given session,
+ * This is used by the auth C_FindObjectsInit to preserve state until
+ * C_FindObjects is called.
+ */
+
+ g_assert (info);
+
+ /* Lookup the structure for this slot */
+ slot = g_hash_table_lookup (per_slot_data, &info->slotID);
+ g_return_if_fail (slot);
+
+ if (cached == NULL) {
+ if (slot->session_to_filter)
+ g_hash_table_remove (slot->session_to_filter, &handle);
+ } else {
+ if (slot->session_to_filter == NULL)
+ slot->session_to_filter = g_hash_table_new_full (ulong_hash, ulong_equal, ulong_free, NULL);
+ g_hash_table_insert (slot->session_to_filter, ulong_alloc (handle), GUINT_TO_POINTER ((guint)(*cached)));
+ }
+
+}
+
+gboolean
+gkr_pkcs11_auth_cached_get_filter (CK_SESSION_HANDLE handle, CK_SESSION_INFO *info, CK_BBOOL *cached)
+{
+ SlotData *slot;
+ gpointer value;
+
+ /*
+ * Lookup stashed filter of a cached attribute for a given session.
+ * This is used by the auth C_FindObjects (see above)
+ */
+
+ g_assert (info);
+ g_assert (cached);
+
+ /* Lookup the structure for this slot */
+ slot = g_hash_table_lookup (per_slot_data, &info->slotID);
+ g_return_val_if_fail (slot, FALSE);
+
+ if (!slot->session_to_filter)
+ return FALSE;
+
+ if (!g_hash_table_lookup_extended (slot->session_to_filter, &handle, NULL, &value))
+ return FALSE;
+
+ *cached = GPOINTER_TO_UINT (value);
+ return TRUE;
+}
+
+
+/* ---------------------------------------------------------------------------------
+ * SLOT / SESSION TRACKING
+ */
+
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);
+ if (slot->session_to_specific)
+ g_hash_table_destroy (slot->session_to_specific);
g_slice_free (SlotData, slot);
}
@@ -656,3 +774,12 @@
g_hash_table_destroy (per_slot_data);
per_slot_data = NULL;
}
+
+void
+gkr_pkcs11_auth_free_object (GkrPkcs11AuthObject *info)
+{
+ g_assert (info);
+ g_free (info->label);
+ g_free (info->unique);
+ g_free (info);
+}
Modified: trunk/daemon/pkcs11/gkr-pkcs11-auth.h
==============================================================================
--- trunk/daemon/pkcs11/gkr-pkcs11-auth.h (original)
+++ trunk/daemon/pkcs11/gkr-pkcs11-auth.h Thu Jan 22 22:23:49 2009
@@ -75,6 +75,19 @@
CK_ULONG *pin_len,
CK_RV rv);
+void gkr_pkcs11_auth_cached_lookup (GkrPkcs11AuthObject *object,
+ CK_BBOOL *cached);
+
+void gkr_pkcs11_auth_cached_clear (GkrPkcs11AuthObject *object);
+
+void gkr_pkcs11_auth_cached_set_filter (CK_SESSION_HANDLE handle,
+ CK_SESSION_INFO *info,
+ CK_BBOOL *cached);
+
+gboolean gkr_pkcs11_auth_cached_get_filter (CK_SESSION_HANDLE handle,
+ CK_SESSION_INFO *info,
+ CK_BBOOL *cached);
+
void gkr_pkcs11_auth_initialized (void);
void gkr_pkcs11_auth_session_opened (CK_SESSION_HANDLE handle,
Modified: trunk/pkcs11/pkcs11g.h
==============================================================================
--- trunk/pkcs11/pkcs11g.h (original)
+++ trunk/pkcs11/pkcs11g.h Thu Jan 22 22:23:49 2009
@@ -79,6 +79,8 @@
#define CKV_GNOME_AUTH_CACHE_SESSION 0x40000000
#define CKV_GNOME_AUTH_CACHE_UNLIMITED 0x80000000
+#define CKA_GNOME_AUTH_CACHED (CKA_GNOME + 301)
+
/* -------------------------------------------------------------------
* OBJECT UNIQUE IDENTIFIER
*/
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 22 22:23:49 2009
@@ -26,6 +26,9 @@
#include "gp11/gp11.h"
+#include "pkcs11/pkcs11.h"
+#include "pkcs11/pkcs11g.h"
+
#include "egg/egg-secure-memory.h"
#include <glib.h>
@@ -375,7 +378,23 @@
static void
lock_key_pair (GP11Session *session, GP11Object *priv, GP11Object *pub)
{
- /* TODO: Implement */
+ GError *error = NULL;
+ g_assert (GP11_IS_SESSION (session));
+ g_assert (GP11_IS_OBJECT (pub));
+
+ gp11_object_set_session (priv, session);
+ gp11_object_set (priv, &error, CKA_GNOME_AUTH_CACHED, GP11_BOOLEAN, FALSE, GP11_INVALID);
+ if (error != NULL) {
+ g_warning ("couldn't clear cached authentication for key: %s", error->message);
+ g_clear_error (&error);
+ }
+
+ gp11_object_set_session (pub, session);
+ gp11_object_set (pub, &error, CKA_GNOME_AUTH_CACHED, GP11_BOOLEAN, FALSE, GP11_INVALID);
+ if (error != NULL) {
+ g_warning ("couldn't clear cached authentication for key: %s", error->message);
+ g_clear_error (&error);
+ }
}
static void
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]