gnome-keyring r1441 - in trunk: . gp11 pkcs11/ssh-agent
- From: nnielsen svn gnome org
- To: svn-commits-list gnome org
- Subject: gnome-keyring r1441 - in trunk: . gp11 pkcs11/ssh-agent
- Date: Tue, 6 Jan 2009 03:13:27 +0000 (UTC)
Author: nnielsen
Date: Tue Jan 6 03:13:26 2009
New Revision: 1441
URL: http://svn.gnome.org/viewvc/gnome-keyring?rev=1441&view=rev
Log:
* gp11/gp11.h:
* gp11/gp11-slot.c: Helper function for matching mechanism types.
* pkcs11/ssh-agent/gck-ssh-agent.c:
* pkcs11/ssh-agent/gck-ssh-agent.h:
* pkcs11/ssh-agent/gck-ssh-agent-ops.c:
* pkcs11/ssh-agent/gck-ssh-agent-private.h:
* pkcs11/ssh-agent/gck-ssh-agent-standalone.c: The modular ssh agent now
uses keys from any available PKCS#11 slots, and automatically selects a decent
slot for it's session keys.
Modified:
trunk/ChangeLog
trunk/gp11/gp11-slot.c
trunk/gp11/gp11.h
trunk/pkcs11/ssh-agent/gck-ssh-agent-ops.c
trunk/pkcs11/ssh-agent/gck-ssh-agent-private.h
trunk/pkcs11/ssh-agent/gck-ssh-agent-standalone.c
trunk/pkcs11/ssh-agent/gck-ssh-agent.c
trunk/pkcs11/ssh-agent/gck-ssh-agent.h
Modified: trunk/gp11/gp11-slot.c
==============================================================================
--- trunk/gp11/gp11-slot.c (original)
+++ trunk/gp11/gp11-slot.c Tue Jan 6 03:13:26 2009
@@ -270,6 +270,50 @@
}
/**
+ * gp11_mechanisms_check:
+ * @mechanisms: A list of mechanisms, perhaps retrieved from gp11_slot_get_mechanisms().
+ *
+ * Check whether all the mechanism types are in the list.
+ *
+ * The arguments should be a list of CKM_XXX mechanism types. The last argument
+ * should be GP11_INVALID.
+ *
+ * Return value: Whether the mechanism is in the list or not.
+ **/
+gboolean
+gp11_mechanisms_check (GP11Mechanisms *mechanisms, ...)
+{
+ gboolean found = TRUE;
+ va_list va;
+ gulong mech;
+ gsize i;
+
+ g_return_val_if_fail (mechanisms, FALSE);
+
+ va_start (va, mechanisms);
+ for (;;) {
+ mech = va_arg (va, gulong);
+ if (mech == GP11_INVALID)
+ break;
+
+ found = FALSE;
+ for (i = 0; i < gp11_mechanisms_length (mechanisms); ++i) {
+ if (gp11_mechanisms_at (mechanisms, i) == mech) {
+ found = TRUE;
+ break;
+ }
+ }
+
+ if (found == FALSE)
+ break;
+
+ }
+ va_end (va);
+
+ return found;
+}
+
+/**
* gp11_slot_get_handle:
* @self: The slot to get the handle of.
*
Modified: trunk/gp11/gp11.h
==============================================================================
--- trunk/gp11/gp11.h (original)
+++ trunk/gp11/gp11.h Tue Jan 6 03:13:26 2009
@@ -387,6 +387,9 @@
#define gp11_mechanisms_free(a) (g_array_free(a, TRUE))
+gboolean gp11_mechanisms_check (GP11Mechanisms *mechanisms,
+ ...);
+
#define GP11_TYPE_SLOT (gp11_slot_get_type())
#define GP11_SLOT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GP11_TYPE_SLOT, GP11Slot))
#define GP11_SLOT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GP11_TYPE_SLOT, GP11Slot))
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 Tue Jan 6 03:13:26 2009
@@ -40,6 +40,7 @@
/* ---------------------------------------------------------------------------- */
+
static void
copy_attribute (GP11Attributes *original, CK_ATTRIBUTE_TYPE type, GP11Attributes *dest)
{
@@ -53,16 +54,12 @@
gp11_attributes_add (dest, attr);
}
-static GList*
-find_keys_for_attributes (GP11Session *session, GP11Attributes *attrs,
- CK_OBJECT_CLASS klass)
+static GP11Attributes*
+build_like_attributes (GP11Attributes *attrs, CK_OBJECT_CLASS klass)
{
GP11Attributes *search;
- GError *error = NULL;
gulong key_type;
- GList *keys;
- g_assert (GP11_IS_SESSION (session));
g_assert (attrs);
/* Determine the key type */
@@ -92,97 +89,257 @@
break;
}
- keys = gp11_session_find_objects_full (session, search, NULL, &error);
- gp11_attributes_unref (search);
+ return search;
+}
+
+static void
+search_keys_like_attributes (gpointer session_or_module, GP11Attributes *attrs, CK_OBJECT_CLASS klass,
+ GP11ObjectForeachFunc func, gpointer user_data)
+{
+ GP11Attributes *search;
+ GError *error = NULL;
+ GList *keys, *l;
- if (error) {
- g_warning ("couldn't search for matching keys: %s", error->message);
- g_clear_error (&error);
- return NULL;
+ search = build_like_attributes (attrs, klass);
+
+ /* In all slots */
+ if (GP11_IS_MODULE (session_or_module)) {
+ if (!gp11_module_enumerate_objects_full (session_or_module, search, NULL,
+ func, user_data, &error)) {
+ g_warning ("couldn't enumerate matching keys: %s", error->message);
+ g_clear_error (&error);
+ }
+
+ /* Otherwise search in the session */
+ } else if (GP11_IS_SESSION (session_or_module)){
+ keys = gp11_session_find_objects_full (session_or_module, search, NULL, &error);
+
+ if (error) {
+ g_warning ("couldn't find matching keys: %s", error->message);
+ g_clear_error (&error);
+
+ } else {
+ for (l = keys; l; l = g_list_next (l)) {
+ if (!(func) (l->data, user_data))
+ break;
+ }
+
+ gp11_list_unref_free (keys);
+ }
+
+ /* Bad object passed in */
+ } else {
+ g_assert_not_reached ();
}
- return keys;
+ gp11_attributes_unref (search);
}
-static GP11Object*
-public_key_for_attributes (GP11Session *session, GP11Attributes *attrs)
+static gboolean
+list_all_matching (GP11Object *object, gpointer user_data)
{
- GList *keys;
- GP11Object *object;
+ GList** list = (GList**)user_data;
+ g_return_val_if_fail (GP11_IS_OBJECT (object), FALSE);
+ *list = g_list_prepend (*list, g_object_ref (object));
- g_assert (GP11_IS_SESSION (session));
- g_assert (attrs);
+ /* Keep going */
+ return TRUE;
+}
+
+static gboolean
+return_first_matching (GP11Object *object, gpointer user_data)
+{
+ GP11Object **result = (GP11Object**)user_data;
- keys = find_keys_for_attributes (session, attrs, CKO_PUBLIC_KEY);
- if (!keys) {
- g_message ("couldn't find matching public key");
- return NULL;
- }
+ g_return_val_if_fail (GP11_IS_OBJECT (object), FALSE);
+ g_return_val_if_fail (result != NULL, FALSE);
+ g_return_val_if_fail (*result == NULL, FALSE);
+ *result = g_object_ref (object);
- object = g_object_ref (keys->data);
- gp11_list_unref_free (keys);
- return object;
+ /* We've seen enough */
+ return FALSE;
}
-static GP11Object*
-private_key_for_public (GP11Session *session, GP11Object *pub)
+static gboolean
+return_private_matching (GP11Object *object, gpointer user_data)
{
- GP11Object *priv = NULL;
+ GP11Object **result = (GP11Object**)user_data;
+ GP11Session *session;
GP11Attributes *attrs;
- GError *error = NULL;
+ GP11Attribute *attr;
+ gboolean token;
GList *objects;
-
- g_assert (GP11_IS_SESSION (session));
- g_assert (GP11_IS_OBJECT (pub));
-
- gp11_object_set_session (pub, session);
- attrs = gp11_object_get (pub, &error, CKA_ID, CKA_TOKEN,
- GP11_INVALID);
+ GError *error = NULL;
+
+ g_return_val_if_fail (GP11_IS_OBJECT (object), FALSE);
+ g_return_val_if_fail (result != NULL, FALSE);
+ g_return_val_if_fail (*result == NULL, FALSE);
+
+ /* Get the key identifier and token */
+ attrs = gp11_object_get (object, &error, CKA_ID, CKA_TOKEN, -1);
if (error) {
- g_warning ("couldn't lookup attributes for key: %s", error->message);
+ g_warning ("error retrieving attributes for public key: %s", error->message);
g_clear_error (&error);
- return NULL;
+ return TRUE;
}
+
+ /* Dig out the key identifier and token */
+ attr = gp11_attributes_find (attrs, CKA_ID);
+ g_return_val_if_fail (attr, FALSE);
- /* Search for exactly the same attributes but with a private key class */
- gp11_attributes_add_ulong (attrs, CKA_CLASS, CKO_PRIVATE_KEY);
- objects = gp11_session_find_objects_full (session, attrs, NULL, &error);
+ if (!gp11_attributes_find_boolean (attrs, CKA_TOKEN, &token))
+ token = FALSE;
+
+ session = gp11_object_get_session (object);
+ g_return_val_if_fail (GP11_IS_SESSION (session), FALSE);
+
+ /* Search for the matching private key */
+ objects = gp11_session_find_objects (session, NULL,
+ CKA_ID, attr->length, attr->value,
+ CKA_CLASS, GP11_ULONG, CKO_PRIVATE_KEY,
+ CKA_TOKEN, GP11_BOOLEAN, token,
+ GP11_INVALID);
+
gp11_attributes_unref (attrs);
+
+ /* Keep searching, not found */
+ if (objects) {
+ *result = g_object_ref (objects->data);
+ gp11_object_set_session (*result, session);
+ gp11_list_unref_free (objects);
+ }
+
+ g_object_unref (session);
+
+ /* Stop once we have a key */
+ return (*result == NULL);
+}
+
+static gboolean
+load_identity_v1_attributes (GP11Object *object, gpointer user_data)
+{
+ GP11Attributes *attrs;
+ GP11Attribute *attr;
+ GP11Session *session;
+ GError *error = NULL;
+ gboolean valid = TRUE;
+ GList **all_attrs;
+ GList *objects;
+
+ g_return_val_if_fail (GP11_IS_OBJECT (object), FALSE);
+ g_return_val_if_fail (user_data, FALSE);
+ /*
+ * The encompassing search should have limited to the right label.
+ * In addition V1 keys are only RSA.
+ */
+
+ attrs = gp11_object_get (object, &error, CKA_ID, CKA_LABEL, CKA_KEY_TYPE, CKA_MODULUS,
+ CKA_PUBLIC_EXPONENT, CKA_CLASS, CKA_MODULUS_BITS, -1);
if (error) {
- g_warning ("couldn't search for related key: %s", error->message);
+ g_warning ("error retrieving attributes for public key: %s", error->message);
g_clear_error (&error);
- return NULL;
+ return TRUE;
}
+
+ /* Find a private key for this one */
+ attr = gp11_attributes_find (attrs, CKA_ID);
+ if (attr != NULL) {
+ session = gp11_object_get_session (object);
+ g_return_val_if_fail (GP11_IS_SESSION (session), FALSE);
+
+ objects = gp11_session_find_objects (session, NULL,
+ CKA_ID, attr->length, attr->value,
+ CKA_CLASS, GP11_ULONG, CKO_PRIVATE_KEY,
+ CKA_TOKEN, GP11_BOOLEAN, FALSE,
+ GP11_INVALID);
+
+ g_object_unref (session);
+
+ if (!objects)
+ valid = FALSE;
+
+ gp11_list_unref_free (objects);
+ }
+
+ all_attrs = (GList**)user_data;
+ if (valid == TRUE)
+ *all_attrs = g_list_prepend (*all_attrs, attrs);
+ else
+ gp11_attributes_unref (attrs);
- if (objects)
- priv = g_object_ref (objects->data);
- gp11_list_unref_free (objects);
-
- return priv;
+ /* Note that we haven't reffed the object or session */
+
+ /* Keep going */
+ return TRUE;
}
-static GP11Object*
-private_key_for_attributes (GP11Session *session, GP11Attributes *attrs)
+static gboolean
+load_identity_v2_attributes (GP11Object *object, gpointer user_data)
{
- GP11Object *pub, *prv;
-
- g_assert (GP11_IS_SESSION (session));
- g_assert (attrs);
+ GP11Attributes *attrs;
+ GP11Attribute *attr;
+ GP11Session *session;
+ GError *error = NULL;
+ gboolean valid = TRUE;
+ gboolean token;
+ GList **all_attrs;
+ GList *objects;
- pub = public_key_for_attributes (session, attrs);
- if (pub == NULL)
- return NULL;
+ g_return_val_if_fail (GP11_IS_OBJECT (object), FALSE);
+ g_return_val_if_fail (user_data, FALSE);
- prv = private_key_for_public (session, pub);
- g_object_unref (pub);
+ attrs = gp11_object_get (object, &error, CKA_ID, CKA_LABEL, CKA_KEY_TYPE, CKA_MODULUS,
+ CKA_PUBLIC_EXPONENT, CKA_PRIME, CKA_SUBPRIME, CKA_BASE,
+ CKA_VALUE, CKA_CLASS, CKA_MODULUS_BITS, CKA_TOKEN, -1);
+ if (error) {
+ g_warning ("error retrieving attributes for public key: %s", error->message);
+ g_clear_error (&error);
+ return TRUE;
+ }
- if (prv == NULL) {
- g_message ("couldn't find matching private key");
- return NULL;
+ /* Dig out the label, and see if it's not v1, skip if so */
+ attr = gp11_attributes_find (attrs, CKA_LABEL);
+ if (attr != NULL) {
+ if (attr->length == strlen (V1_LABEL) &&
+ strncmp ((gchar*)attr->value, V1_LABEL, attr->length) == 0)
+ valid = FALSE;
}
- return prv;
+ /* Figure out if it's a token object or not */
+ if (!gp11_attributes_find_boolean (attrs, CKA_TOKEN, &token))
+ token = FALSE;
+
+ /* Find a private key for this one */
+ attr = gp11_attributes_find (attrs, CKA_ID);
+ if (attr != NULL) {
+ session = gp11_object_get_session (object);
+ g_return_val_if_fail (GP11_IS_SESSION (session), FALSE);
+
+ objects = gp11_session_find_objects (session, NULL,
+ CKA_ID, attr->length, attr->value,
+ CKA_CLASS, GP11_ULONG, CKO_PRIVATE_KEY,
+ CKA_TOKEN, GP11_BOOLEAN, token,
+ GP11_INVALID);
+
+ g_object_unref (session);
+
+ if (!objects)
+ valid = FALSE;
+
+ gp11_list_unref_free (objects);
+ }
+
+ all_attrs = (GList**)user_data;
+ if (valid == TRUE)
+ *all_attrs = g_list_prepend (*all_attrs, attrs);
+ else
+ gp11_attributes_unref (attrs);
+
+ /* Note that we haven't reffed the object or session */
+
+ /* Keep going */
+ return TRUE;
}
static void
@@ -222,21 +379,7 @@
}
static void
-remove_by_public_key (GP11Session *session, GP11Object *pub)
-{
- GP11Object *priv;
-
- g_assert (GP11_IS_SESSION (session));
- g_assert (GP11_IS_OBJECT (pub));
-
- priv = private_key_for_public (session, pub);
- remove_key_pair (session, priv, pub);
- if (pub != NULL)
- g_object_unref (priv);
-}
-
-static void
-remove_or_lock_by_public_key (GP11Session *session, GP11Object *pub)
+remove_by_public_key (GP11Session *session, GP11Object *pub, gboolean exclude_v1)
{
GP11Attributes *attrs;
GError *error = NULL;
@@ -258,7 +401,7 @@
}
/* Skip over SSH V1 keys */
- if (gp11_attributes_find_string (attrs, CKA_LABEL, &label)) {
+ if (exclude_v1 && gp11_attributes_find_string (attrs, CKA_LABEL, &label)) {
if (label && strcmp (label, V1_LABEL) == 0) {
gp11_attributes_unref (attrs);
g_free (label);
@@ -358,8 +501,9 @@
gp11_attributes_add_boolean (pub, CKA_TOKEN, FALSE);
/* Find the previous keys that match the same description */
- priv_prev = find_keys_for_attributes (session, priv, CKO_PRIVATE_KEY);
- pub_prev = find_keys_for_attributes (session, pub, CKO_PUBLIC_KEY);
+ priv_prev = pub_prev = NULL;
+ search_keys_like_attributes (session, priv, CKO_PRIVATE_KEY, list_all_matching, &priv_prev);
+ search_keys_like_attributes (session, priv, CKO_PUBLIC_KEY, list_all_matching, &pub_prev);
/* Now try and create the new keys */
if (create_key_pair (session, priv, pub)) {
@@ -504,68 +648,22 @@
static gboolean
op_request_identities (GckSshAgentCall *call)
{
- GList *objects, *l;
- GList *all_attrs;
- GError *error = NULL;
+ GList *all_attrs, *l;
GP11Attributes *attrs;
- GP11Object *pub, *priv;
- GP11Attribute *label;
gsize blobpos;
gchar *comment;
- /* Find all the private keys*/
+ /* Find all the keys (we filter out v1 later) */
/* TODO: Check SSH purpose */
- objects = gp11_session_find_objects (call->session, &error,
- CKA_CLASS, GP11_ULONG, CKO_PUBLIC_KEY,
- GP11_INVALID);
- if (error) {
- g_warning ("couldn't search for private keys: %s", error->message);
- g_clear_error (&error);
+ all_attrs = NULL;
+ if (!gp11_module_enumerate_objects (call->module,
+ load_identity_v2_attributes, &all_attrs,
+ CKA_CLASS, GP11_ULONG, CKO_PUBLIC_KEY,
+ GP11_INVALID)) {
gkr_buffer_add_byte (call->resp, GCK_SSH_RES_FAILURE);
return TRUE;
}
- /* Find the public key, and load attributes for each public */
- for (l = objects; l; l = g_list_next (l)) {
- pub = l->data;
-
- /* For each public key we find a private key. */
- priv = private_key_for_public (call->session, pub);
- if (priv == NULL)
- continue;
- g_object_unref (priv);
-
- /*
- * Now get attributes for that public key. Any attributes not present on
- * the key will be returned as invalid.
- */
- gp11_object_set_session (pub, call->session);
- attrs = gp11_object_get (pub, &error, CKA_LABEL, CKA_KEY_TYPE, CKA_MODULUS,
- CKA_PUBLIC_EXPONENT, CKA_PRIME, CKA_SUBPRIME, CKA_BASE,
- CKA_VALUE, CKA_CLASS, CKA_MODULUS_BITS, -1);
-
- if (error) {
- g_warning ("error retrieving attributes for public key: %s", error->message);
- g_clear_error (&error);
- continue;
- }
-
- /* Dig out the label, and see if it's not v1, skip if so */
- label = gp11_attributes_find (attrs, CKA_LABEL);
- if (label != NULL) {
- if (label->length == strlen (V1_LABEL) &&
- strncmp ((gchar*)label->value, V1_LABEL, label->length) == 0) {
- gp11_attributes_unref (attrs);
- continue;
- }
- }
-
- /* We have this one squared away and ready to send */
- all_attrs = g_list_prepend (all_attrs, attrs);
- }
-
- gp11_list_unref_free (objects);
-
gkr_buffer_add_byte (call->resp, GCK_SSH_RES_IDENTITIES_ANSWER);
gkr_buffer_add_uint32 (call->resp, g_list_length (all_attrs));
@@ -602,56 +700,22 @@
static gboolean
op_v1_request_identities (GckSshAgentCall *call)
{
- GList *objects, *l;
- GError *error = NULL;
- GList *all_attrs;
+ GList *all_attrs, *l;
GP11Attributes *attrs;
- GP11Object *pub, *priv;
-
+
/* Find all the keys not on token, and are V1 */
/* TODO: Check SSH purpose */
- objects = gp11_session_find_objects (call->session, &error,
- CKA_CLASS, GP11_ULONG, CKO_PUBLIC_KEY,
- CKA_TOKEN, GP11_BOOLEAN, FALSE,
- CKA_LABEL, GP11_STRING, V1_LABEL,
- GP11_INVALID);
- if (error) {
- g_warning ("couldn't search for public keys: %s", error->message);
- g_clear_error (&error);
+ all_attrs = NULL;
+ if (!gp11_module_enumerate_objects (call->module,
+ load_identity_v1_attributes, &all_attrs,
+ CKA_CLASS, GP11_ULONG, CKO_PUBLIC_KEY,
+ CKA_TOKEN, GP11_BOOLEAN, FALSE,
+ CKA_LABEL, GP11_STRING, V1_LABEL,
+ GP11_INVALID)) {
gkr_buffer_add_byte (call->resp, GCK_SSH_RES_FAILURE);
return TRUE;
}
- /* Find the public key, and load attributes for each public */
- for (l = objects; l; l = g_list_next (l)) {
- pub = l->data;
-
- /* For each public key we find a private key. */
- priv = private_key_for_public (call->session, pub);
- if (priv == NULL)
- continue;
- g_object_unref (priv);
-
- /*
- * Now get attributes for that public key. Any attributes not present on
- * the key will be returned as invalid.
- */
- gp11_object_set_session (pub, call->session);
- attrs = gp11_object_get (pub, &error, CKA_KEY_TYPE, CKA_MODULUS,
- CKA_PUBLIC_EXPONENT, CKA_MODULUS_BITS, CKA_CLASS, -1);
-
- if (error) {
- g_warning ("error retrieving attributes for public key: %s", error->message);
- g_clear_error (&error);
- continue;
- }
-
- /* We have this one squared away and ready to send */
- all_attrs = g_list_prepend (all_attrs, attrs);
- }
-
- gp11_list_unref_free (objects);
-
gkr_buffer_add_byte (call->resp, GCK_SSH_RES_RSA_IDENTITIES_ANSWER);
gkr_buffer_add_uint32 (call->resp, g_list_length (all_attrs));
@@ -747,9 +811,10 @@
{
GP11Attributes *attrs;
GError *error = NULL;
+ GP11Object *key = NULL;
const guchar *data;
const gchar *salgo;
- GP11Object *key;
+ GP11Session *session;
guchar *result;
gsize n_data, n_result;
guint32 flags;
@@ -787,7 +852,7 @@
}
/* Lookup the key */
- key = private_key_for_attributes (call->session, attrs);
+ search_keys_like_attributes (call->module, attrs, CKO_PUBLIC_KEY, return_private_matching, &key);
gp11_attributes_unref (attrs);
if (!key) {
@@ -807,8 +872,13 @@
else
hash = make_raw_sign_hash (halgo, data, n_data, &n_hash);
+ session = gp11_object_get_session (key);
+ g_return_val_if_fail (session, FALSE);
+
/* Do the magic */
- result = gp11_session_sign (call->session, key, mech, hash, n_hash, &n_result, &error);
+ result = gp11_session_sign (session, key, mech, hash, n_hash, &n_result, &error);
+
+ g_object_unref (session);
g_object_unref (key);
g_free (hash);
@@ -855,6 +925,7 @@
op_v1_challenge (GckSshAgentCall *call)
{
gsize offset, n_data, n_result, n_hash;
+ GP11Session *session;
GP11Attributes *attrs;
guchar session_id[16];
guint8 hash[16];
@@ -910,7 +981,7 @@
}
/* Lookup the key */
- key = private_key_for_attributes (call->session, attrs);
+ search_keys_like_attributes (call->module, attrs, CKO_PUBLIC_KEY, return_private_matching, &key);
gp11_attributes_unref (attrs);
/* Didn't find a key? */
@@ -919,7 +990,12 @@
return TRUE;
}
- result = gp11_session_decrypt (call->session, key, CKM_RSA_PKCS, data, n_data, &n_result, &error);
+ session = gp11_object_get_session (key);
+ g_return_val_if_fail (session, FALSE);
+
+ result = gp11_session_decrypt (session, key, CKM_RSA_PKCS, data, n_data, &n_result, &error);
+
+ g_object_unref (session);
g_object_unref (key);
if (error) {
@@ -948,7 +1024,7 @@
{
GP11Attributes *attrs;
GP11Session *session;
- GP11Object *key;
+ GP11Object *key = NULL;
gsize offset;
guint sz;
@@ -964,27 +1040,27 @@
gp11_attributes_unref (attrs);
return FALSE;
}
+
+ /*
+ * This is the session that owns these objects. Only
+ * one thread can use it at a time.
+ */
- key = public_key_for_attributes (call->session, attrs);
+ session = gck_ssh_agent_checkout_main_session ();
+ g_return_val_if_fail (session, FALSE);
+
+ search_keys_like_attributes (session, attrs, CKO_PUBLIC_KEY, return_first_matching, &key);
gp11_attributes_unref (attrs);
if (key != NULL) {
-
- /*
- * This is the session that owns these objects. Only
- * one thread can use it at a time.
- */
-
- session = gck_ssh_agent_checkout_main_session ();
- g_return_val_if_fail (session, FALSE);
-
- remove_or_lock_by_public_key (session, key);
-
- gck_ssh_agent_checkin_main_session (session);
-
+ remove_by_public_key (session, key, TRUE);
g_object_unref (key);
}
+ gck_ssh_agent_checkin_main_session (session);
+
+ /* TODO: Implement locking of other keys */
+
gkr_buffer_add_byte (call->resp, GCK_SSH_RES_SUCCESS);
return TRUE;
@@ -995,7 +1071,7 @@
{
GP11Session *session;
GP11Attributes *attrs;
- GP11Object *key;
+ GP11Object *key = NULL;
gsize offset;
offset = 5;
@@ -1005,32 +1081,25 @@
gp11_attributes_unref (attrs);
return FALSE;
}
-
- key = public_key_for_attributes (call->session, attrs);
- gp11_attributes_unref (attrs);
-
+
/*
* This is the session that owns these objects. Only
* one thread can use it at a time.
*/
+
+ session = gck_ssh_agent_checkout_main_session ();
+ g_return_val_if_fail (session, FALSE);
+
+ search_keys_like_attributes (session, attrs, CKO_PUBLIC_KEY, return_first_matching, &key);
+ gp11_attributes_unref (attrs);
if (key != NULL) {
-
- /*
- * This is the session that owns these objects. Only
- * one thread can use it at a time.
- */
-
- session = gck_ssh_agent_checkout_main_session ();
- g_return_val_if_fail (session, FALSE);
-
- remove_by_public_key (session, key);
-
- gck_ssh_agent_checkin_main_session (session);
-
+ remove_by_public_key (session, key, FALSE);
g_object_unref (key);
}
-
+
+ gck_ssh_agent_checkin_main_session (session);
+
gkr_buffer_add_byte (call->resp, GCK_SSH_RES_SUCCESS);
return TRUE;
}
@@ -1042,12 +1111,6 @@
GList *objects, *l;
GError *error = NULL;
- /* Find all session SSH public keys */
- objects = gp11_session_find_objects (call->session, &error,
- CKA_CLASS, GP11_ULONG, CKO_PUBLIC_KEY,
- GP11_INVALID);
-
-
/*
* This is the session that owns these objects. Only
* one thread can use it at a time.
@@ -1055,14 +1118,22 @@
session = gck_ssh_agent_checkout_main_session ();
g_return_val_if_fail (session, FALSE);
+
+ /* Find all session SSH public keys */
+ objects = gp11_session_find_objects (session, &error,
+ CKA_CLASS, GP11_ULONG, CKO_PUBLIC_KEY,
+ GP11_INVALID);
+
for (l = objects; l; l = g_list_next (l))
- remove_or_lock_by_public_key (session, l->data);
+ remove_by_public_key (session, l->data, TRUE);
- gck_ssh_agent_checkin_main_session (session);
-
gp11_list_unref_free (objects);
+
+ gck_ssh_agent_checkin_main_session (session);
+ /* TODO: Go through all open tokens and lock private SSH keys */
+
gkr_buffer_add_byte (call->resp, GCK_SSH_RES_SUCCESS);
return TRUE;
}
@@ -1073,13 +1144,6 @@
GP11Session *session;
GList *objects, *l;
GError *error = NULL;
-
- /* Find all session SSH v1 public keys */
- objects = gp11_session_find_objects (call->session, &error,
- CKA_TOKEN, GP11_BOOLEAN, FALSE,
- CKA_CLASS, GP11_ULONG, CKO_PUBLIC_KEY,
- CKA_LABEL, GP11_STRING, V1_LABEL,
- GP11_INVALID);
/*
* This is the session that owns these objects. Only
@@ -1089,13 +1153,20 @@
session = gck_ssh_agent_checkout_main_session ();
g_return_val_if_fail (session, FALSE);
+ /* Find all session SSH v1 public keys */
+ objects = gp11_session_find_objects (session, &error,
+ CKA_TOKEN, GP11_BOOLEAN, FALSE,
+ CKA_CLASS, GP11_ULONG, CKO_PUBLIC_KEY,
+ CKA_LABEL, GP11_STRING, V1_LABEL,
+ GP11_INVALID);
+
for (l = objects; l; l = g_list_next (l))
- remove_by_public_key (session, l->data);
+ remove_by_public_key (session, l->data, FALSE);
+
+ gp11_list_unref_free (objects);
gck_ssh_agent_checkin_main_session (session);
- gp11_list_unref_free (objects);
-
gkr_buffer_add_byte (call->resp, GCK_SSH_RES_SUCCESS);
return TRUE;
}
Modified: trunk/pkcs11/ssh-agent/gck-ssh-agent-private.h
==============================================================================
--- trunk/pkcs11/ssh-agent/gck-ssh-agent-private.h (original)
+++ trunk/pkcs11/ssh-agent/gck-ssh-agent-private.h Tue Jan 6 03:13:26 2009
@@ -33,7 +33,7 @@
typedef struct _GckSshAgentCall {
int sock;
- GP11Session *session;
+ GP11Module *module;
GkrBuffer *req;
GkrBuffer *resp;
} GckSshAgentCall;
@@ -91,6 +91,8 @@
* gck-ssh-agent.c
*/
+int gck_ssh_agent_initialize_with_module (const gchar *prefix, GP11Module *module);
+
GP11Session* gck_ssh_agent_checkout_main_session (void);
void gck_ssh_agent_checkin_main_session (GP11Session* session);
Modified: trunk/pkcs11/ssh-agent/gck-ssh-agent-standalone.c
==============================================================================
--- trunk/pkcs11/ssh-agent/gck-ssh-agent-standalone.c (original)
+++ trunk/pkcs11/ssh-agent/gck-ssh-agent-standalone.c Tue Jan 6 03:13:26 2009
@@ -22,12 +22,20 @@
#include "config.h"
-#include <glib.h>
-
#include "gck-ssh-agent.h"
+#include "gck-ssh-agent-private.h"
#include "common/gkr-secure-memory.h"
+#include "gp11/gp11.h"
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include <pwd.h>
+#include <string.h>
+#include <unistd.h>
+
G_LOCK_DEFINE_STATIC (memory_mutex);
void gkr_memory_lock (void)
@@ -72,11 +80,10 @@
main(int argc, char *argv[])
{
GP11Module *module;
- GList *slots;
- GP11Slot *slot;
GError *error = NULL;
GIOChannel *channel;
GMainLoop *loop;
+ int sock;
g_type_init ();
@@ -90,28 +97,22 @@
return 1;
}
- /* This is currently brittle because it's just used for development */
- slots = gp11_module_get_slots (module, TRUE);
- if (!slots) {
- g_message ("no slots present in pkcs11 module");
- return 1;
- }
-
- slot = g_object_ref (slots->data);
- gp11_list_unref_free (slots);
g_signal_connect (module, "authenticate-slot", G_CALLBACK (authenticate_slot), NULL);
g_signal_connect (module, "authenticate-object", G_CALLBACK (authenticate_object), NULL);
gp11_module_set_auto_authenticate (module, TRUE);
- if (!gck_ssh_agent_initialize ("/tmp/test-gck-ssh-agent", slot))
+ sock = gck_ssh_agent_initialize_with_module ("/tmp/test-gck-ssh-agent", module);
+ g_object_unref (module);
+
+ if (sock == -1)
return 1;
- channel = g_io_channel_unix_new (gck_ssh_agent_get_socket_fd ());
+ channel = g_io_channel_unix_new (sock);
g_io_add_watch (channel, G_IO_IN | G_IO_HUP, accept_client, NULL);
g_io_channel_unref (channel);
- g_print ("SSH_AUTH_SOCK=%s\n", gck_ssh_agent_get_socket_path ());
+ g_print ("SSH_AUTH_SOCK=%s\n", g_getenv ("SSH_AUTH_SOCK"));
/* Run a main loop */
loop = g_main_loop_new (NULL, FALSE);
@@ -119,7 +120,6 @@
g_main_loop_unref (loop);
gck_ssh_agent_uninitialize ();
- g_object_unref (slot);
return 0;
}
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 Tue Jan 6 03:13:26 2009
@@ -43,8 +43,8 @@
#define socklen_t int
#endif
-/* The PKCS#11 slot we call into */
-static GP11Slot *pkcs11_slot = NULL;
+/* The loaded PKCS#11 module */
+static GP11Module *pkcs11_module = NULL;
static gboolean
read_all (int fd, guchar *buf, int len)
@@ -125,15 +125,13 @@
static gpointer
run_client_thread (gpointer data)
{
- gboolean running = TRUE;
- GError *error = NULL;
gint *socket = data;
GckSshAgentCall call;
GkrBuffer req;
GkrBuffer resp;
guchar op;
- g_assert (pkcs11_slot);
+ g_assert (GP11_IS_MODULE (pkcs11_module));
memset (&call, 0, sizeof (call));
call.sock = g_atomic_int_get (socket);
@@ -143,16 +141,9 @@
gkr_buffer_init_full (&resp, 128, (GkrBufferAllocator)g_realloc);
call.req = &req;
call.resp = &resp;
-
- /* Try to open a session for this thread */
- call.session = gp11_slot_open_session (pkcs11_slot, CKF_SERIAL_SESSION, &error);
- if (!call.session) {
- g_warning ("couldn't open pkcs#11 session for agent thread: %s", error->message);
- g_clear_error (&error);
- running = FALSE;
- }
+ call.module = g_object_ref (pkcs11_module);
- while (running) {
+ for (;;) {
gkr_buffer_reset (call.req);
@@ -182,7 +173,8 @@
gkr_buffer_uninit (&req);
gkr_buffer_uninit (&resp);
-
+ g_object_unref (call.module);
+
close (call.sock);
g_atomic_int_set (socket, -1);
@@ -190,35 +182,57 @@
}
/* --------------------------------------------------------------------------------------
- * MAIN SESSION
+ * SESSION MANAGEMENT
*/
/* The main PKCS#11 session that owns objects, and the mutex/cond for waiting on it */
-static GP11Session *pkcs11_session = NULL;
-static gboolean pkcs11_session_checked = FALSE;
-static GMutex *pkcs11_session_mutex = NULL;
-static GCond *pkcs11_session_cond = NULL;
+static GP11Session *pkcs11_main_session = NULL;
+static gboolean pkcs11_main_checked = FALSE;
+static GMutex *pkcs11_main_mutex = NULL;
+static GCond *pkcs11_main_cond = NULL;
static gboolean
-init_main_session (GP11Slot *slot)
+init_pkcs11 (GP11Module *module)
{
- GP11Session *session;
+ GP11Session *session = NULL;
+ GList *slots, *l;
+ GP11Mechanisms *mechs;
GError *error = NULL;
- g_assert (GP11_IS_SLOT (slot));
-
- /* Load our main session */
- session = gp11_slot_open_session (slot, CKF_SERIAL_SESSION, &error);
+ g_assert (GP11_IS_MODULE (module));
+
+ /* Find a good slot for our session keys */
+ slots = gp11_module_get_slots (module, TRUE);
+ for (l = slots; session == NULL && l; l = g_list_next (l)) {
+
+ /* Check that it has the mechanisms we need */
+ mechs = gp11_slot_get_mechanisms (l->data);
+ if (gp11_mechanisms_check (mechs, CKM_RSA_PKCS, CKM_DSA, GP11_INVALID)) {
+
+ /* Try and open a session */
+ session = gp11_slot_open_session (l->data, CKF_SERIAL_SESSION, &error);
+ if (!session) {
+ g_warning ("couldn't create pkcs#11 session: %s", error->message);
+ g_clear_error (&error);
+ }
+ }
+
+ gp11_mechanisms_free (mechs);
+ }
+
+ gp11_list_unref_free (slots);
+
if (!session) {
- g_warning ("couldn't create pkcs#11 session: %s", error->message);
- g_clear_error (&error);
+ g_warning ("couldn't select a usable pkcs#11 slot for the ssh agent to use");
return FALSE;
}
- pkcs11_session_mutex = g_mutex_new ();
- pkcs11_session_cond = g_cond_new ();
- pkcs11_session_checked = FALSE;
- pkcs11_session = session;
+ pkcs11_module = g_object_ref (module);
+
+ pkcs11_main_mutex = g_mutex_new ();
+ pkcs11_main_cond = g_cond_new ();
+ pkcs11_main_checked = FALSE;
+ pkcs11_main_session = session;
return TRUE;
}
@@ -228,15 +242,15 @@
{
GP11Session *result;
- g_mutex_lock (pkcs11_session_mutex);
+ g_mutex_lock (pkcs11_main_mutex);
- g_assert (GP11_IS_SESSION (pkcs11_session));
- while (pkcs11_session_checked)
- g_cond_wait (pkcs11_session_cond, pkcs11_session_mutex);
- pkcs11_session_checked = TRUE;
- result = g_object_ref (pkcs11_session);
+ g_assert (GP11_IS_SESSION (pkcs11_main_session));
+ while (pkcs11_main_checked)
+ g_cond_wait (pkcs11_main_cond, pkcs11_main_mutex);
+ pkcs11_main_checked = TRUE;
+ result = g_object_ref (pkcs11_main_session);
- g_mutex_unlock (pkcs11_session_mutex);
+ g_mutex_unlock (pkcs11_main_mutex);
return result;
}
@@ -246,35 +260,38 @@
{
g_assert (GP11_IS_SESSION (session));
- g_mutex_lock (pkcs11_session_mutex);
+ g_mutex_lock (pkcs11_main_mutex);
- g_assert (session == pkcs11_session);
- g_assert (pkcs11_session_checked);
+ g_assert (session == pkcs11_main_session);
+ g_assert (pkcs11_main_checked);
g_object_unref (session);
- pkcs11_session_checked = FALSE;
- g_cond_signal (pkcs11_session_cond);
+ pkcs11_main_checked = FALSE;
+ g_cond_signal (pkcs11_main_cond);
- g_mutex_unlock (pkcs11_session_mutex);
+ g_mutex_unlock (pkcs11_main_mutex);
}
static void
-uninit_main_session (void)
+uninit_pkcs11 (void)
{
gboolean ret;
- g_assert (pkcs11_session_mutex);
- ret = g_mutex_trylock (pkcs11_session_mutex);
+ g_assert (pkcs11_main_mutex);
+ ret = g_mutex_trylock (pkcs11_main_mutex);
g_assert (ret);
- g_assert (GP11_IS_SESSION (pkcs11_session));
- g_assert (!pkcs11_session_checked);
- g_object_unref (pkcs11_session);
- pkcs11_session = NULL;
-
- g_mutex_unlock (pkcs11_session_mutex);
- g_mutex_free (pkcs11_session_mutex);
- g_cond_free (pkcs11_session_cond);
+ g_assert (GP11_IS_SESSION (pkcs11_main_session));
+ g_assert (!pkcs11_main_checked);
+ g_object_unref (pkcs11_main_session);
+ pkcs11_main_session = NULL;
+
+ g_mutex_unlock (pkcs11_main_mutex);
+ g_mutex_free (pkcs11_main_mutex);
+ g_cond_free (pkcs11_main_cond);
+
+ g_assert (pkcs11_module);
+ g_object_unref (pkcs11_module);
}
/* --------------------------------------------------------------------------------------
@@ -295,18 +312,6 @@
/* The path of the socket listening on */
static char socket_path[1024] = { 0, };
-int
-gck_ssh_agent_get_socket_fd (void)
-{
- return socket_fd;
-}
-
-const gchar*
-gck_ssh_agent_get_socket_path (void)
-{
- return socket_path;
-}
-
void
gck_ssh_agent_accept (void)
{
@@ -381,20 +386,33 @@
g_list_free (socket_clients);
socket_clients = NULL;
- uninit_main_session ();
+ uninit_pkcs11 ();
+}
+
+int
+gck_ssh_agent_initialize (const gchar *prefix, CK_FUNCTION_LIST_PTR funcs)
+{
+ GP11Module *module;
+ int sock;
+
+ g_return_val_if_fail (funcs, -1);
+ g_return_val_if_fail (prefix, -1);
+
+ module = gp11_module_new (funcs);
+ sock = gck_ssh_agent_initialize_with_module (prefix, module);
+ g_object_unref (module);
- g_object_unref (pkcs11_slot);
- pkcs11_slot = NULL;
+ return sock;
}
-gboolean
-gck_ssh_agent_initialize (const gchar *prefix, GP11Slot *slot)
+int
+gck_ssh_agent_initialize_with_module (const gchar *prefix, GP11Module *module)
{
struct sockaddr_un addr;
int sock;
- g_return_val_if_fail (GP11_IS_SLOT (slot), FALSE);
- g_return_val_if_fail (prefix, FALSE);
+ 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);
unlink (socket_path);
@@ -402,7 +420,7 @@
sock = socket (AF_UNIX, SOCK_STREAM, 0);
if (sock < 0) {
g_warning ("couldn't create socket: %s", g_strerror (errno));
- return FALSE;
+ return -1;
}
memset(&addr, 0, sizeof(addr));
@@ -411,22 +429,23 @@
if (bind (sock, (struct sockaddr *) & addr, sizeof (addr)) < 0) {
g_warning ("couldn't bind to socket: %s: %s", socket_path, g_strerror (errno));
close (sock);
- return FALSE;
+ return -1;
}
if (listen (sock, 128) < 0) {
g_warning ("couldn't listen on socket: %s", g_strerror (errno));
close (sock);
- return FALSE;
+ return -1;
}
/* Load our main session */
- if (!init_main_session (slot)) {
+ if (!init_pkcs11 (module)) {
close (sock);
- return FALSE;
+ return -1;
}
- pkcs11_slot = g_object_ref (slot);
+ g_setenv ("SSH_AUTH_SOCK", socket_path, TRUE);
+
socket_fd = sock;
- return TRUE;
+ return sock;
}
Modified: trunk/pkcs11/ssh-agent/gck-ssh-agent.h
==============================================================================
--- trunk/pkcs11/ssh-agent/gck-ssh-agent.h (original)
+++ trunk/pkcs11/ssh-agent/gck-ssh-agent.h Tue Jan 6 03:13:26 2009
@@ -3,13 +3,9 @@
#include <glib.h>
-#include "gp11/gp11.h"
+#include "pkcs11/pkcs11.h"
-gboolean gck_ssh_agent_initialize (const gchar *prefix, GP11Slot *slot);
-
-int gck_ssh_agent_get_socket_fd (void);
-
-const gchar* gck_ssh_agent_get_socket_path (void);
+int gck_ssh_agent_initialize (const gchar *prefix, CK_FUNCTION_LIST_PTR funcs);
void gck_ssh_agent_accept (void);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]