gnome-keyring r1170 - in trunk: . daemon pk pk/tests pkix po ssh ssh/tests



Author: nnielsen
Date: Tue Jul  8 22:23:20 2008
New Revision: 1170
URL: http://svn.gnome.org/viewvc/gnome-keyring?rev=1170&view=rev

Log:
	* daemon/gkr-daemon.c:
	* pk/gkr-pk-object-storage.c:
	* pk/gkr-pk-object-storage.h:
	* pk/gkr-pk-storage.c:
	* pk/gkr-pk-storage.h:
	* pk/Makefile.am:
	* pkix/gkr-pkix-serialize.c:
	* pkix/gkr-pkix-serialize.h: Reimplement arbitrary token object
	storage in new storage framework.
	
	* pk/gkr-pk-object.c:
	* pk/gkr-pk-object.h:
	* pk/tests/Makefile.am: 
	* pk/tests/unit-test-pk-object.c: (added) 
	Better support for calculating and using labels for objects.
	
	* pk/gkr-pk-privkey.c:
	* pk/gkr-pk-privkey.h:
	* ssh/gkr-ssh-daemon-ops.c:
	* ssh/gkr-ssh-storage.c:
	* ssh/gkr-ssh-storage.h:
	* ssh/tests/unit-test-ssh-storage.c: Don't load SSH public keys 
	directly, just provide them as hints for the private keys to 
use.



Added:
   trunk/pk/tests/unit-test-pk-object.c
Modified:
   trunk/ChangeLog
   trunk/daemon/gkr-daemon.c
   trunk/pk/Makefile.am
   trunk/pk/gkr-pk-object-storage.c
   trunk/pk/gkr-pk-object-storage.h
   trunk/pk/gkr-pk-object.c
   trunk/pk/gkr-pk-object.h
   trunk/pk/gkr-pk-privkey.c
   trunk/pk/gkr-pk-privkey.h
   trunk/pk/gkr-pk-storage.c
   trunk/pk/gkr-pk-storage.h
   trunk/pk/tests/Makefile.am
   trunk/pkix/gkr-pkix-serialize.c
   trunk/pkix/gkr-pkix-serialize.h
   trunk/po/ChangeLog
   trunk/po/POTFILES.in
   trunk/ssh/gkr-ssh-daemon-ops.c
   trunk/ssh/gkr-ssh-storage.c
   trunk/ssh/gkr-ssh-storage.h
   trunk/ssh/tests/unit-test-ssh-storage.c

Modified: trunk/daemon/gkr-daemon.c
==============================================================================
--- trunk/daemon/gkr-daemon.c	(original)
+++ trunk/daemon/gkr-daemon.c	Tue Jul  8 22:23:20 2008
@@ -35,6 +35,8 @@
 
 #include "library/gnome-keyring.h"
 
+#include "pk/gkr-pk-object-storage.h"
+
 #include "pkcs11/gkr-pkcs11-daemon.h"
 
 #ifdef WITH_SSH
@@ -452,6 +454,10 @@
 
 	gcry_create_nonce (&seed, sizeof (seed));
 	srand (seed);
+	
+	/* Initialize object storage */
+	if (!gkr_pk_object_storage_initialize ())
+		cleanup_and_exit (1);
 
 	/* Initialize the appropriate components */
 	if (check_run_component ("keyring")) {

Modified: trunk/pk/Makefile.am
==============================================================================
--- trunk/pk/Makefile.am	(original)
+++ trunk/pk/Makefile.am	Tue Jul  8 22:23:20 2008
@@ -24,6 +24,7 @@
 	gkr-pk-netscape-trust.c gkr-pk-netscape-trust.h \
 	gkr-pk-object.c gkr-pk-object.h \
 	gkr-pk-object-manager.c gkr-pk-object-manager.h \
+	gkr-pk-object-storage.c gkr-pk-object-storage.h \
 	gkr-pk-places.h \
 	gkr-pk-privkey.c gkr-pk-privkey.h \
 	gkr-pk-pubkey.c gkr-pk-pubkey.h \

Modified: trunk/pk/gkr-pk-object-storage.c
==============================================================================
--- trunk/pk/gkr-pk-object-storage.c	(original)
+++ trunk/pk/gkr-pk-object-storage.c	Tue Jul  8 22:23:20 2008
@@ -1,5 +1,5 @@
 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/* gkr-pk-object-storage.c - Manage all 'token' PK objects
+/* gkr-pk-object-storage.c - Store general 'token' PK objects
 
    Copyright (C) 2007 Stefan Walter
 
@@ -31,19 +31,13 @@
 #include "gkr-pk-privkey.h"
 #include "gkr-pk-util.h"
 
-#include "common/gkr-cleanup.h"
 #include "common/gkr-location.h"
 #include "common/gkr-location-watch.h"
-#include "common/gkr-secure-memory.h"
-
-#include "keyrings/gkr-keyring-login.h"
 
 #include "pkcs11/pkcs11.h"
 
 #include "pkix/gkr-pkix-parser.h"
-
-#include "ui/gkr-ask-daemon.h"
-#include "ui/gkr-ask-request.h"
+#include "pkix/gkr-pkix-serialize.h"
 
 #include <glib.h>
 #include <glib/gi18n.h>
@@ -52,352 +46,93 @@
 
 typedef struct _GkrPkObjectStoragePrivate GkrPkObjectStoragePrivate;
 
+#define RELATIVE_DIRECTORY  "keystore" 
+#define UNWANTED_FILENAME_CHARS  ":/\\<>|\t\n\r\v"
+
 struct _GkrPkObjectStoragePrivate {
-	GHashTable *objects;
-	GHashTable *objects_by_location;
 	GHashTable *specific_load_requests;
 	GHashTable *denied_import_requests;
-
-	GSList *watches;
+	GkrLocationWatch *watch;
 };
 
 #define GKR_PK_OBJECT_STORAGE_GET_PRIVATE(o) \
       (G_TYPE_INSTANCE_GET_PRIVATE((o), GKR_TYPE_PK_OBJECT_STORAGE, GkrPkObjectStoragePrivate))
 
-G_DEFINE_TYPE(GkrPkObjectStorage, gkr_pk_object_storage, G_TYPE_OBJECT);
-
-static GkrPkObjectStorage *object_storage_singleton = NULL; 
+G_DEFINE_TYPE(GkrPkObjectStorage, gkr_pk_object_storage, GKR_TYPE_PK_STORAGE);
 
 typedef struct {
 	GkrPkObjectStorage *storage;       /* The object storage to parse into */
 	GQuark location;                   /* The location being parsed */
 	GHashTable *checks;                /* The set of objects that existed before parse */
-	GHashTable *types_by_digest;       /* The parse types for every object prompted for or seen */ 
 } ParseContext;
 
+
 #define NO_VALUE GUINT_TO_POINTER (TRUE)
 
 /* -----------------------------------------------------------------------------
  * HELPERS
  */
- 
-static void 
-cleanup_object_storage (void *unused)
-{
-	g_assert (object_storage_singleton);
-	g_object_unref (object_storage_singleton);
-	object_storage_singleton = NULL;
-}
 
-static const gchar*
-prepare_ask_title (GQuark type)
+static GQuark
+location_for_storing (GkrPkObjectStorage *storage, GkrPkObject *obj, GQuark type)
 {
-	/*
-	 * Yes this is unmaintainable and stupid, but is required 
-	 * for translations to work properly.
-	 */
-	if (type == GKR_PKIX_PRIVATE_KEY)
-		return _("Unlock private key");
-	else if (type == GKR_PKIX_CERTIFICATE)
-		return _("Unlock certificate");
-	else if (type == GKR_PKIX_PUBLIC_KEY)
-		return _("Unlock public key");
-	else 
-		return _("Unlock");
-}
-
-static const gchar*
-prepare_ask_primary (GQuark type)
-{
-	/*
-	 * Yes this is unmaintainable and stupid, but is required 
-	 * for translations to work properly.
-	 */
-	if (type == GKR_PKIX_PRIVATE_KEY)
-		return _("Enter password to unlock the private key");
-	else if (type == GKR_PKIX_CERTIFICATE)
-		return _("Enter password to unlock the certificate");
-	else if (type == GKR_PKIX_PUBLIC_KEY)
-		return _("Enter password to unlock the public key");
-	else 
-		return _("Enter password to unlock");
-}
-
-static const gchar*
-prepare_ask_check (GQuark type)
-{
-	/*
-	 * Yes this is unmaintainable and stupid, but is required 
-	 * for translations to work properly.
-	 */
-	if (type == GKR_PKIX_PRIVATE_KEY)
-		return _("Automatically unlock this private key when I log in.");
-	else if (type == GKR_PKIX_CERTIFICATE)
-		return _("Automatically unlock this certificate when I log in.");
-	else if (type == GKR_PKIX_PUBLIC_KEY)
-		return _("Automatically unlock this public key when I log in.");
-	else 
-		return _("Automatically unlock this when I log in");
-}
-
-static gchar*
-prepare_ask_secondary (GQuark type, gboolean indexed, const gchar *label)
-{
-	/*
-	 * Yes this is unmaintainable and stupid, but is required 
-	 * for translations to work properly.
-	 */
-
-	/* When we've already indexed this data */
-	if (indexed) {
-
-		if (type == GKR_PKIX_PRIVATE_KEY)
-			return g_strdup_printf (_("An application wants access to the private key '%s', but it is locked"), label);
-		else if (type == GKR_PKIX_CERTIFICATE)
-			return g_strdup_printf (_("An application wants access to the certificate '%s', but it is locked"), label);
-		else if (type == GKR_PKIX_PUBLIC_KEY)
-			return g_strdup_printf (_("An application wants access to the public key '%s', but it is locked"), label);
-		else 
-			return g_strdup_printf (_("An application wants access to '%s', but it is locked"), label);
+	const gchar *label;
+	const gchar *ext;
+	gchar *filename;
+	GQuark loc;
+	
+	/* A good extension */
+	ext = gkr_pkix_serialize_get_extension (type);
+	if (!ext) 
+		ext = "pk";
+	
+	/* Come up with a good relative name for the object */
+	label = gkr_pk_object_get_label (obj);
+	filename = g_strconcat (RELATIVE_DIRECTORY, G_DIR_SEPARATOR_S, label, ".", ext, NULL);
+	g_strdelimit (filename, UNWANTED_FILENAME_CHARS, '_');
 	
-	/* Never before seen this data */ 
-	} else {
-
-		if (type == GKR_PKIX_PRIVATE_KEY)
-			return g_strdup_printf (_("The system wants to import the private key '%s', but it is locked"), label);
-		else if (type == GKR_PKIX_CERTIFICATE)
-			return g_strdup_printf (_("The system wants to import the certificate '%s', but it is locked"), label);
-		else if (type == GKR_PKIX_PUBLIC_KEY)
-			return g_strdup_printf (_("The system wants to import the public key '%s', but it is locked"), label);
-		else 
-			return g_strdup_printf (_("The system wants to import '%s', but it is locked"), label);
-	}
+	loc = gkr_location_from_child (GKR_LOCATION_VOLUME_LOCAL, filename);
+	g_free (filename);
+	
+	return loc;
 }
 
-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
-static gchar* 
-parser_ask_password (GkrPkixParser *parser, GQuark loc, gkrid digest, 
-                     GQuark type, const gchar *label, gint *state,
-                     ParseContext *ctx)
+static gboolean
+parser_ask_password (GkrPkixParser *parser, GQuark loc, gkrconstid digest, 
+                     GQuark type, const gchar *label, gint *state, gchar **password,
+                     gpointer user_data)
 {
+ 	ParseContext *ctx = (ParseContext*)user_data;
  	GkrPkObjectStoragePrivate *pv = GKR_PK_OBJECT_STORAGE_GET_PRIVATE (ctx->storage);
-	GkrAskRequest *ask;
-	gchar *custom_label, *ret, *display_name, *stype, *secondary;
-	const gchar *password;
-	gboolean imported = FALSE;
-	gboolean importing = FALSE;
-	guint flags;
-	
-	g_return_val_if_fail (loc == ctx->location, NULL);
-	
-	/*
-	 * The password prompting is somewhat convoluted with the end goal of 
-	 * not prompting the user more than necessary. 
-	 * 
-	 *  - Check and see if we have a password on record for this.
-	 *  - Don't prompt unless the user is specifically requesting 
-	 *    this object *or* we've never seen it before. 
-	 *  - Make note of everything we've prompted for so that later 
-	 *    we can note having seen it.
-	 */ 
-	
-	/* See if we can find a valid password for this location */
-	if (failures == 0) {
-		password = gkr_keyring_login_lookup_secret (GNOME_KEYRING_ITEM_ENCRYPTION_KEY_PASSWORD,
-		                                            "pk-object", gkr_location_to_string (loc), NULL);
-		if (password != NULL)
-			return gkr_secure_strdup (password);
-	} else {
-		gkr_keyring_login_remove_secret (GNOME_KEYRING_ITEM_ENCRYPTION_KEY_PASSWORD,
-		                                 "pk-object", gkr_location_to_string (loc), NULL); 
-	}
-
-	/*
-	 * If we've parsed this before, then we can lookup in our index as to what 
-	 * exactly this is we're talking about here.  
-	 */
-	stype = gkr_pk_index_get_string_full (loc, digest, "parsed-type");
-	if (stype) {
-		if (!type && stype[0])
-			type = g_quark_from_string (stype);
-		g_free (stype);
-	}
+	gboolean ret;
 	
-	/* This is how we know if we've imported this object before */
-	imported = gkr_pk_index_get_boolean_full (loc, digest, "imported", FALSE);
+	g_return_val_if_fail (loc == ctx->location, FALSE);
 
 	/* 
-	 * If the user isn't specifically requeting this object, then we don't 
+	 * If the user isn't specifically requesting this object, then we don't 
 	 * necessarily prompt for a password. 
 	 */
 	if (!g_hash_table_lookup (pv->specific_load_requests, digest)) {
 		
 		/* If the user specifically denied this earlier, then don't prompt */
-		if (g_hash_table_lookup (pv->denied_import_requests, digest))
-			return NULL;
-		
-		/* If this has been imported already, then don't prompt */
-		if (imported)
-			return NULL;
-		
-		importing = TRUE;
+		if (g_hash_table_lookup (pv->denied_import_requests, digest)) {
+			*password = NULL;
+			return FALSE;
+		}
 	}
 
-	/* TODO: Load a better label if we have one */
-	custom_label = NULL;
+	/* TODO: Work out how imports work, add to denied import requests if necessary */
 	
-	if (custom_label != NULL)
-		label = custom_label;
-	
-	/* Build up the prompt */
-	if (importing)
-		flags = GKR_ASK_REQUEST_PASSWORD | GKR_ASK_REQUEST_OK_CANCEL_BUTTONS;
-	else
-		flags = GKR_ASK_REQUEST_PASSWORD | GKR_ASK_REQUEST_OK_DENY_BUTTONS;
-	ask = gkr_ask_request_new (prepare_ask_title (type), prepare_ask_primary (type), flags);
-
-	secondary = prepare_ask_secondary (type, !importing, label); 
-	gkr_ask_request_set_secondary (ask, secondary);
-	g_free (secondary);
-
-	gkr_ask_request_set_location (ask, loc);
-		
-	if (gkr_keyring_login_is_usable ())
-		gkr_ask_request_set_check_option (ask, prepare_ask_check (type));
-	
-	/* Prompt the user */
-	gkr_ask_daemon_process (ask);
+	ret = gkr_pk_storage_get_load_password (GKR_PK_STORAGE (ctx->storage), loc, digest, 
+	                                        type, label, state, password);
 
-	/* If the user denied ... */
-	if (ask->response == GKR_ASK_RESPONSE_DENY) {
-		
-		/* If we were importing then don't try again */
-		if (importing)
-			g_hash_table_insert (pv->denied_import_requests, 
-			                     gkr_id_dup (digest), NO_VALUE);
-		
-		ret = NULL;
-	
-	/* User cancelled or failure */
-	} else if (ask->response < GKR_ASK_RESPONSE_ALLOW) {
-		
-		ret = NULL;
-		
-	/* Successful response */
-	} else {
-		ret = gkr_secure_strdup (ask->typed_password);
-		if (ask->checked) {
-			display_name =  g_strdup_printf (_("Unlock password for '%s'"), label);
-			gkr_keyring_login_attach_secret (GNOME_KEYRING_ITEM_ENCRYPTION_KEY_PASSWORD,
-			                                 display_name, ret,
-			                                 "pk-object", gkr_location_to_string (loc), NULL);
-		} 
-		
-	xxxxxxxxxxxxxxxxxxxxxx
-		/* Track that we prompted for this */
-		g_hash_table_insert (ctx->types_by_digest, gkr_id_dup (digest), 
-		                     GUINT_TO_POINTER (type));
-	xxxxxxxxxxxxxxxxxxxxxx
-	}	
-		
-	g_free (custom_label);
 	return ret;
 }
 
-static void
-add_object_to_multihash (GHashTable *table, gpointer key, GkrPkObject *object)
-{
-	GArray *objs = (GArray*)g_hash_table_lookup (table, key);
-		
-	/* Add automatically if first at location */
-	if (!objs) {
-		objs = g_array_new (FALSE, TRUE, sizeof (GkrPkObject*));
-		g_hash_table_replace (table, key, objs);
-	}
-		
-	g_array_append_val (objs, object);
-}
-
-static gboolean
-remove_object_from_multihash (GHashTable *table, gconstpointer key, GkrPkObject *object)
-{
-	GArray *objs;
-	guint i; 
-	
-	objs = (GArray*)g_hash_table_lookup (table, key);
-	if (!objs)
-		return FALSE;
-		
-	for (i = 0; i < objs->len; ++i) {
-		if (g_array_index (objs, GkrPkObject*, i) == object)
-			break;
-	}
-
-	/* Not found */
-	if (i == objs->len)
-		return FALSE;	
-
-	g_array_remove_index_fast (objs, i);
-		
-	/* Remove automatically if last one */
-	if (objs->len == 0)
-		g_hash_table_remove (table, key);
-		
-	return TRUE;
-}
-
-static void
-add_object (GkrPkObjectStorage *storage, GkrPkObject *object)
-{
- 	GkrPkObjectStoragePrivate *pv = GKR_PK_OBJECT_STORAGE_GET_PRIVATE (storage);
-	gpointer k;
-	
-	g_assert (object);
-	g_assert (GKR_IS_PK_OBJECT (object));
-	g_assert (object->location);
-	g_assert (!g_hash_table_lookup (pv->objects, object));
-		
-	/* Mapping of location to the index key */
-	k = GUINT_TO_POINTER (object->location);
-	add_object_to_multihash (pv->objects_by_location, k, object); 
-
-	if (!object->storage)
-		object->storage = storage;
-	
-	/* Take ownership of the object */
-	g_object_ref (object);
-	g_hash_table_insert (pv->objects, object, NO_VALUE);
-}
-
-static void
-remove_object (GkrPkObjectStorage *storage, GkrPkObject *object)
-{
- 	GkrPkObjectStoragePrivate *pv = GKR_PK_OBJECT_STORAGE_GET_PRIVATE (storage);
-	gpointer k;
-
-	g_assert (object);
-	g_assert (GKR_IS_PK_OBJECT (object));
-	g_assert (object->location);
-	g_assert (g_hash_table_lookup (pv->objects, object));
-		
-	/* Mapping of location to the object */
-	k = GUINT_TO_POINTER (object->location);
-	if (!remove_object_from_multihash (pv->objects_by_location, k, object))
-		g_assert (FALSE);
-
-	if (object->storage == storage)
-		object->storage = NULL;
-
-	/* Release ownership */
-	if (!g_hash_table_remove (pv->objects, object))
-		g_assert (FALSE);
-}
-
 static GkrPkObject*
 prepare_object (GkrPkObjectStorage *storage, GQuark location, 
                 gkrconstid digest, GQuark type)
 {
-	GkrPkObjectStoragePrivate *pv = GKR_PK_OBJECT_STORAGE_GET_PRIVATE (storage);
 	GkrPkObjectManager *manager;
 	GkrPkObject *object;
 	GType gtype;
@@ -407,8 +142,7 @@
 	
 	/* The object already exists just reference it */
 	if (object) {
-		if (!g_hash_table_lookup (pv->objects, object))
-			add_object (storage, object);
+		gkr_pk_storage_add_object (GKR_PK_STORAGE (storage), object);
 		return object;
 	} 
 	
@@ -423,11 +157,10 @@
 	
 	object = g_object_new (gtype, "manager", manager, "location", location, 
 	                       "digest", digest, NULL);
-	add_object (storage, object);
+	gkr_pk_storage_add_object (GKR_PK_STORAGE (storage), object);
 
 	/* Object was reffed */
 	g_object_unref (object);
-	
 	return object;
 }
 
@@ -437,30 +170,19 @@
 {
  	GkrPkObjectStoragePrivate *pv = GKR_PK_OBJECT_STORAGE_GET_PRIVATE (ctx->storage);
  	GkrPkObject *object;
- 	gchar *stype;
- 	
-	/* If we don't know the type then look it up */
-	if (!type) {
-		stype = gkr_pk_index_get_string_full (location, digest, "parsed-type");
-		if (stype && stype[0])
-			type = g_quark_from_string (stype);
-		g_free (stype);
-	}
+
+ 	/* TODO: What do we do if we don't know the type? */
+	if (!type)
+		return FALSE;
 	
-	if (type) { 
-	 	object = prepare_object (ctx->storage, location, digest, type);
- 		g_return_val_if_fail (object != NULL, FALSE);
+ 	object = prepare_object (ctx->storage, location, digest, type);
+	g_return_val_if_fail (object != NULL, FALSE);
  	
-		/* Make note of having seen this object in load requests */
-		g_hash_table_remove (pv->specific_load_requests, digest);
+	/* Make note of having seen this object in load requests */
+	g_hash_table_remove (pv->specific_load_requests, digest);
 
-		/* Make note of having seen this one */
-		g_hash_table_remove (ctx->checks, object);
-	}
-	
-	/* Track the type of this digest */
-	g_hash_table_insert (ctx->types_by_digest, gkr_id_dup (digest), 
-		                 GUINT_TO_POINTER (type));
+	/* Make note of having seen this one */
+	gkr_pk_storage_checks_mark (ctx->checks, object);
 	
 	return TRUE;
 }
@@ -483,22 +205,10 @@
 	/* Make note of having seen this one */
 	g_hash_table_remove (ctx->checks, object);
 		
-	/* Track the type of this digest */
-	g_hash_table_insert (ctx->types_by_digest, gkr_id_dup (digest),
-		                 GUINT_TO_POINTER (type));
-	
-	/* Setup the sexp, probably a key on this object */
-	g_object_set (object, "gcrypt-sexp", sexp, NULL);
-	
-	/*
-	 * Now we have the object loaded and everything, and since it's a fully
-	 * loaded (if encrypted a password has been provided), take the 
-	 * opportunity to 'import' it and make sure we have all necessary data
-	 * on it.
-	 */
-	if (!gkr_pk_index_get_boolean (object, "imported", FALSE))
-		gkr_pk_object_import (object);
+	/* Make note of having seen this one */
+	gkr_pk_storage_checks_mark (ctx->checks, object);
 	
+	/* TODO: Work how imports work */
 	return TRUE;
 }
 
@@ -520,99 +230,39 @@
 	/* Make note of having seen this one */
 	g_hash_table_remove (ctx->checks, object);
 	
-	/* Track the type for this digest */
-	g_hash_table_insert (ctx->types_by_digest, gkr_id_dup (digest), 
-		                 GUINT_TO_POINTER (type));
-
 	/* Setup the asn1, probably a certificate on this object */
 	g_object_set (object, "asn1-tree", asn1, NULL); 
 	
-	/*
-	 * Now we have the object loaded and everything, and since it's a fully
-	 * loaded (if encrypted a password has been provided), take the 
-	 * opportunity to 'import' it and make sure we have all necessary data
-	 * on it.
-	 */
-	if (gkr_pk_index_get_boolean (object, "imported", FALSE))
-		gkr_pk_object_import (object);
-	
+	/* TODO: Work out how imports work */
 	return TRUE;
 }
 
-static void
-remove_each_object (GkrPkObject *object, gpointer unused, GkrPkObjectStorage *storage)
-{
-	GkrPkObjectStoragePrivate *pv = GKR_PK_OBJECT_STORAGE_GET_PRIVATE (storage);
-	if (g_hash_table_lookup (pv->objects, object))
-		remove_object (storage, object);
-}
-
-static void
-index_each_digest (gkrid digest, gpointer value, gpointer data)
-{
-	GQuark location = GPOINTER_TO_UINT (data);
-	GQuark type = GPOINTER_TO_UINT (value);
-	
-	if (!type)
-		return;
-
-	/* Stash away the parsed type, in case we need it when prompting for a password */
-	gkr_pk_index_set_string_full (location, digest, "parsed-type", 
-	                              g_quark_to_string (type));
-}
-
 static gboolean
 load_objects_at_location (GkrPkObjectStorage *storage, GQuark loc, GError **err)
 {
- 	GkrPkObjectStoragePrivate *pv = GKR_PK_OBJECT_STORAGE_GET_PRIVATE (storage);
  	GkrPkixParser *parser;
- 	GkrPkixResult ret;
- 	GkrPkObject *object;
+ 	gboolean ret;
 	ParseContext ctx;
-	GArray *objs;
-	gpointer k;
-	guint i;
 	
 	g_return_val_if_fail (loc != 0, FALSE);
 
 	ctx.location = loc;
 	ctx.storage = storage;
-	ctx.checks = g_hash_table_new_full (g_direct_hash, g_direct_equal, 
-	                                    g_object_unref, NULL);
-	ctx.types_by_digest = g_hash_table_new_full (gkr_id_hash, gkr_id_equals, 
-	                                             gkr_id_free, NULL);
-
-	/* Create a table of what is at the location */
-	k = GUINT_TO_POINTER (loc);
-	objs = (GArray*)g_hash_table_lookup (pv->objects_by_location, k);
-	for (i = 0; objs && i < objs->len; ++i) {	
-		object = g_array_index (objs, GkrPkObject*, i);
-		g_object_ref (object);
-		g_hash_table_replace (ctx.checks, object, NO_VALUE);
-	} 
-	
+	ctx.checks = gkr_pk_storage_checks_prepare (GKR_PK_STORAGE (storage), loc);
+
 	/* TODO: Try and use a shared parser? */
 	parser = gkr_pkix_parser_new ();
 	g_signal_connect (parser, "parsed-asn1", G_CALLBACK (parser_parsed_asn1), &ctx);
 	g_signal_connect (parser, "parsed-sexp", G_CALLBACK (parser_parsed_sexp), &ctx);
 	g_signal_connect (parser, "parsed-partial", G_CALLBACK (parser_parsed_partial), &ctx);
-	xxxxxxxxxxxxxxxxxxxxxxxx
  	g_signal_connect (parser, "ask-password", G_CALLBACK (parser_ask_password), &ctx);
 
 	ret = gkr_pkix_parser_parse_location (parser, loc, err);
 	g_object_unref (parser);
 
 	/* Remove any still in checks array */
-	g_hash_table_foreach (ctx.checks, (GHFunc)remove_each_object, storage);
-	g_hash_table_destroy (ctx.checks);
-	
-	/* 
-	 * Note any in the index that we prompted for but didn't actually 
-	 * get an object out about.
-	 */  
-	g_hash_table_foreach (ctx.types_by_digest, (GHFunc)index_each_digest, k);
-	g_hash_table_destroy (ctx.types_by_digest);
-	
+	gkr_pk_storage_checks_purge (GKR_PK_STORAGE (storage), ctx.checks);
+
 	return ret;
 }
 
@@ -631,34 +281,7 @@
 static void
 location_remove (GkrLocationWatch *watch, GQuark loc, GkrPkObjectStorage *storage)
 {
- 	GkrPkObjectStoragePrivate *pv = GKR_PK_OBJECT_STORAGE_GET_PRIVATE (storage);
-	GArray *objs, *copy;
-	gpointer k;
-	guint i;
-	
-	/* Remove everything that is at that location */
-	k = GUINT_TO_POINTER (loc);
-	objs = (GArray*)g_hash_table_lookup (pv->objects_by_location, k);
-	if (!objs)
-		return;
-		
-	/* When removing we cleanup empty arrays */
-	g_assert (objs->len);
-
-	/* We copy because otherwise the array will change from underneath us */
-	copy = g_array_sized_new (FALSE, FALSE, sizeof (GkrPkObject*), objs->len);
-	g_array_append_vals (copy, objs->data, objs->len);
-	for (i = 0; i < copy->len; ++i)
-		remove_object (storage, g_array_index (copy, GkrPkObject*, i));
-	 
-	g_array_free (copy, TRUE);
-}
-
-static void
-free_array (gpointer data)
-{
-	if (data)
-		g_array_free ((GArray*)data, TRUE);	
+	gkr_pk_storage_clr_objects (GKR_PK_STORAGE (storage), loc);
 }
 
 /* -----------------------------------------------------------------------------
@@ -669,34 +292,163 @@
 gkr_pk_object_storage_init (GkrPkObjectStorage *storage)
 {
  	GkrPkObjectStoragePrivate *pv = GKR_PK_OBJECT_STORAGE_GET_PRIVATE (storage);
- 	GkrLocationWatch *watch;
- 	const GkrPkPlace *place;
- 	GQuark volume;
- 	guint i;
  	
- 	pv->objects = g_hash_table_new_full (g_direct_hash, g_direct_equal, g_object_unref, NULL);
- 	pv->objects_by_location = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, free_array);
 	pv->specific_load_requests = g_hash_table_new_full (gkr_id_hash, gkr_id_equals, gkr_id_free, NULL);
 	pv->denied_import_requests = g_hash_table_new_full (gkr_id_hash, gkr_id_equals, gkr_id_free, NULL);
 	
-	for (i = 0; i < G_N_ELEMENTS (gkr_pk_places); ++i) {
-		place = &gkr_pk_places[i];
-		g_return_if_fail (place->directory);
-		
-		/* A null means any active volume */
-		volume = place->volume ? gkr_location_from_string (place->volume) : 0;
-		
-		watch = gkr_location_watch_new (NULL, volume, place->directory, 
-		                                place->include, place->exclude);
-		g_return_if_fail (watch); 
-
- 		g_signal_connect (watch, "location-added", G_CALLBACK (location_load), storage);
- 		g_signal_connect (watch, "location-changed", G_CALLBACK (location_load), storage);
- 		g_signal_connect (watch, "location-removed", G_CALLBACK (location_remove), storage);
+	/* The main key and certificate storage */
+	pv->watch = gkr_location_watch_new (NULL, 0, RELATIVE_DIRECTORY, "*", "*.keystore");
+	
+	g_signal_connect (pv->watch, "location-added", G_CALLBACK (location_load), storage);
+	g_signal_connect (pv->watch, "location-changed", G_CALLBACK (location_load), storage);
+	g_signal_connect (pv->watch, "location-removed", G_CALLBACK (location_remove), storage);
+}
 
-		/* Assumes ownership */		
-		pv->watches = g_slist_prepend (pv->watches, watch);
+static void
+gkr_pk_object_storage_refresh (GkrPkStorage *storage)
+{
+	GkrPkObjectStoragePrivate *pv = GKR_PK_OBJECT_STORAGE_GET_PRIVATE (storage);
+	gkr_location_watch_refresh (pv->watch, FALSE);
+}
+
+static gboolean
+gkr_pk_object_storage_load (GkrPkStorage *storage, GkrPkObject *obj, GError **err)
+{
+ 	GkrPkObjectStoragePrivate *pv = GKR_PK_OBJECT_STORAGE_GET_PRIVATE (storage);
+	gboolean ret = FALSE;
+	
+	g_return_val_if_fail (obj, FALSE);
+	
+	g_object_ref (obj);
+	
+	/* We need to have this object */
+	if (!obj->location) {
+		g_set_error (err, GKR_PK_STORAGE_ERROR, 0, "The object doesn't reside on disk");
+		goto done;
 	}
+
+	/* Make note of the specific load request */
+	g_hash_table_replace (pv->specific_load_requests, gkr_id_dup (obj->digest), NO_VALUE); 
+	ret = load_objects_at_location (GKR_PK_OBJECT_STORAGE (storage), obj->location, err);
+
+	if (!ret) 
+		goto done;
+	 
+	/* See if it was seen */
+	if (g_hash_table_lookup (pv->specific_load_requests, obj->digest)) {
+		g_set_error (err, GKR_PK_STORAGE_ERROR, 0, "The object was not found at: %s",
+		             g_quark_to_string (obj->location));
+		goto done;
+	}
+	
+	ret = TRUE;
+
+done:
+	g_hash_table_remove (pv->specific_load_requests, obj->digest);
+	g_object_unref (obj);
+	return ret;
+}
+
+static gboolean
+gkr_pk_object_storage_store (GkrPkStorage *stor, GkrPkObject *obj, GError **err)
+{
+	GkrPkObjectStorage *storage;
+	gpointer what;
+	gchar *password;
+	gkrid digest;
+	gboolean ret;
+	GQuark loc, type;
+	GType gtype;
+	guchar *data;
+	gsize n_data;
+
+	g_return_val_if_fail (!err || !*err, FALSE);
+	g_return_val_if_fail (GKR_IS_PK_STORAGE (stor), FALSE);
+	g_return_val_if_fail (obj->storage == NULL, FALSE);
+	g_return_val_if_fail (obj->location == 0, FALSE);
+
+	storage = GKR_PK_OBJECT_STORAGE (stor);
+
+	/* What are we dealing with? */
+	gtype = G_OBJECT_TYPE (obj);
+	if (gtype == GKR_TYPE_PK_PRIVKEY) {
+		type = GKR_PKIX_PRIVATE_KEY;
+		g_object_get (obj, "gcrypt-sexp", &what, NULL);
+	} else if (gtype == GKR_PKIX_PUBLIC_KEY) {
+		type = GKR_TYPE_PK_PUBKEY;
+		g_object_get (obj, "gcrypt-sexp", &what, NULL);
+	} else if (gtype == GKR_PKIX_CERTIFICATE) {
+		type = GKR_TYPE_PK_CERT;
+		g_object_get (obj, "asn1-tree", &what, NULL);
+	} else {
+		g_return_val_if_reached (FALSE);
+	}
+	
+	g_return_val_if_fail (what != NULL, FALSE);
+
+	/* Find a good location to store this key */
+	loc = location_for_storing (storage, obj, type);
+	g_return_val_if_fail (loc, FALSE);
+	
+	/* Get a password for this key, determines whether encrypted or not */
+	ret = gkr_pk_storage_get_store_password (stor, loc, obj->digest, type, 
+	                                         gkr_pk_object_get_label (obj), 
+	                                         &password);
+	
+	/* Prompt for a password was denied */
+	if (!ret)
+		return TRUE;
+
+	/* Store the object into memory */
+	data = gkr_pkix_serialize_to_data (type, what, password, &n_data);
+	g_return_val_if_fail (data, FALSE);
+	
+	/* A digest for this object */
+	digest = gkr_id_new_digest (data, n_data);
+	
+	/* Store the data to a file */
+	ret = gkr_location_write_file (loc, data, n_data, err);
+	g_free (data);
+
+	if (ret) {
+		/* The object now has a (possibly new) location, and possibly new digest */
+		g_object_set (obj, "location", loc, "storage", stor, "digest", digest, NULL);
+	}
+	
+	gkr_id_free (digest);
+	return ret;
+}
+
+static gboolean
+gkr_pk_object_storage_remove (GkrPkStorage *storage, GkrPkObject *obj, 
+                              GError **err)
+{
+	GSList* objs;
+	guint num;
+	
+	g_return_val_if_fail (!err || !*err, FALSE);
+	g_return_val_if_fail (GKR_IS_PK_OBJECT_STORAGE (storage), FALSE);
+	g_return_val_if_fail (obj->storage == storage, FALSE);
+	g_return_val_if_fail (obj->location, FALSE);
+	
+	objs = gkr_pk_storage_get_objects (storage, obj->location);
+	num = g_slist_length (objs);
+	g_slist_free (objs);
+	
+	/* Are there multiple objects at this location? */	
+	if (g_slist_length (objs) > 1) {
+		g_set_error (err, GKR_PK_STORAGE_ERROR, 0, 
+		             _("Cannot delete '%s' because it is tied to other objects."),
+		             gkr_pk_object_get_label (obj));
+		
+		return FALSE;
+	}
+
+	/* Delete the object itself */
+	if (!gkr_location_delete_file (obj->location, err))
+		return FALSE;
+
+	return TRUE;
 }
 
 static void
@@ -704,18 +456,15 @@
 {
 	GkrPkObjectStorage *storage = GKR_PK_OBJECT_STORAGE (obj);
  	GkrPkObjectStoragePrivate *pv = GKR_PK_OBJECT_STORAGE_GET_PRIVATE (obj);
- 	GkrLocationWatch *watch;
- 	GSList *l;
  	
- 	g_hash_table_remove_all (pv->objects_by_location);
  	g_hash_table_remove_all (pv->specific_load_requests);
  	g_hash_table_remove_all (pv->denied_import_requests);
- 	g_hash_table_remove_all (pv->objects);
  	
- 	for (l = pv->watches; l; l = g_slist_next (l)) {
-		watch = GKR_LOCATION_WATCH (l->data);
-		g_signal_handlers_disconnect_by_func (watch, location_load, storage);
-		g_signal_handlers_disconnect_by_func (watch, location_remove, storage);
+ 	if (pv->watch) {
+ 		g_signal_handlers_disconnect_by_func (pv->watch, location_load, storage);
+ 		g_signal_handlers_disconnect_by_func (pv->watch, location_remove, storage);
+ 		g_object_unref (pv->watch);
+ 	 	pv->watch = NULL;
  	}
  	
 	G_OBJECT_CLASS (gkr_pk_object_storage_parent_class)->dispose (obj);
@@ -725,20 +474,11 @@
 gkr_pk_object_storage_finalize (GObject *obj)
 {
  	GkrPkObjectStoragePrivate *pv = GKR_PK_OBJECT_STORAGE_GET_PRIVATE (obj);
- 	GkrLocationWatch *watch;
- 	GSList *l;
  	
- 	g_hash_table_destroy (pv->objects);
-	g_hash_table_destroy (pv->objects_by_location);
 	g_hash_table_destroy (pv->specific_load_requests);
 	g_hash_table_destroy (pv->denied_import_requests);
 
- 	for (l = pv->watches; l; l = g_slist_next (l)) {
-		watch = GKR_LOCATION_WATCH (l->data);
-		g_object_unref (watch);
- 	}
- 	g_slist_free (pv->watches);
- 	pv->watches = NULL;
+	g_assert (pv->watch == NULL);
 	
 	G_OBJECT_CLASS (gkr_pk_object_storage_parent_class)->finalize (obj);
 }
@@ -746,96 +486,34 @@
 static void
 gkr_pk_object_storage_class_init (GkrPkObjectStorageClass *klass)
 {
-	GObjectClass *gobject_class;
-	gobject_class = (GObjectClass*)klass;
+	GkrPkStorageClass *storage_class = GKR_PK_STORAGE_CLASS (klass);
+	GObjectClass *gobject_class = (GObjectClass*)klass;
 
 	gkr_pk_object_storage_parent_class = g_type_class_peek_parent (klass);
+	
 	gobject_class->dispose = gkr_pk_object_storage_dispose;
 	gobject_class->finalize = gkr_pk_object_storage_finalize;
+	
+	storage_class->load = gkr_pk_object_storage_load;
+	storage_class->refresh = gkr_pk_object_storage_refresh;
+	storage_class->store = gkr_pk_object_storage_store;
+	storage_class->remove = gkr_pk_object_storage_remove;
 
 	g_type_class_add_private (gobject_class, sizeof (GkrPkObjectStoragePrivate));
 }
 
-GkrPkObjectStorage*
-gkr_pk_object_storage_get (void)
-{
-	if (!object_storage_singleton) {
-		object_storage_singleton = g_object_new (GKR_TYPE_PK_OBJECT_STORAGE, NULL);
-		gkr_cleanup_register (cleanup_object_storage, NULL);
-		gkr_pk_object_storage_refresh (object_storage_singleton);
-	}
-	
-	return object_storage_singleton;
-}	
-
-void
-gkr_pk_object_storage_refresh (GkrPkObjectStorage *storage)
-{
-	GkrPkObjectStoragePrivate *pv;
-	GSList *l;
-	
-	if (!storage)
-		storage = gkr_pk_object_storage_get ();
-		
-	g_return_if_fail (GKR_IS_PK_OBJECT_STORAGE (storage));
-	pv = GKR_PK_OBJECT_STORAGE_GET_PRIVATE (storage);
-	
-	for (l = pv->watches; l; l = g_slist_next (l)) 
-		gkr_location_watch_refresh (GKR_LOCATION_WATCH (l->data), FALSE);
-}
+/* -------------------------------------------------------------------------------
+ * PUBLIC
+ */
 
 gboolean
-gkr_pk_object_storage_load_complete (GkrPkObjectStorage *storage, GkrPkObject *obj, 
-                                     GError **err)
+gkr_pk_object_storage_initialize (void)
 {
- 	GkrPkObjectStoragePrivate *pv = GKR_PK_OBJECT_STORAGE_GET_PRIVATE (storage);
-	gboolean ret = FALSE;
-	
-	g_return_val_if_fail (obj, FALSE);
-	
-	g_object_ref (obj);
-	
-	/* We need to have this object */
-	if (!obj->location) {
-		g_set_error (err, GKR_PKIX_PARSE_ERROR, 0, "The object doesn't reside on disk");
-		goto done;
-	}
-
+	GkrPkStorage *storage;
 	
-	/* Make note of the specific load request */
-	g_hash_table_replace (pv->specific_load_requests, gkr_id_dup (obj->digest), NO_VALUE); 
-	ret = load_objects_at_location (storage, obj->location, err);
-
-	if (!ret) 
-		goto done;
-	 
-	/* See if it was seen */
-	if (g_hash_table_lookup (pv->specific_load_requests, obj->digest)) {
-		g_set_error (err, GKR_PKIX_PARSE_ERROR, 0, "the object was not found at: %s",
-		             g_quark_to_string (obj->location));
-		goto done;
-	}
+	storage = g_object_new (GKR_TYPE_PK_OBJECT_STORAGE, NULL);
+	gkr_pk_storage_register (storage, FALSE);
+	g_object_unref (storage);
 	
-	ret = TRUE;
-
-done:
-	g_hash_table_remove (pv->specific_load_requests, obj->digest);
-	g_object_unref (obj);
-	return ret;
-}
-
-gboolean
-gkr_pk_object_storage_add (GkrPkObjectStorage *storage, GkrPkObject *obj, 
-                           GError **err)
-{
-	/* TODO: Need to implement */
-	g_return_val_if_reached (FALSE);
-}
-
-gboolean
-gkr_pk_object_storage_remove (GkrPkObjectStorage *storage, GkrPkObject *obj, 
-                              GError **err)
-{
-	/* TODO: Need to implement */
-	g_return_val_if_reached (FALSE);
+	return TRUE;
 }

Modified: trunk/pk/gkr-pk-object-storage.h
==============================================================================
--- trunk/pk/gkr-pk-object-storage.h	(original)
+++ trunk/pk/gkr-pk-object-storage.h	Tue Jul  8 22:23:20 2008
@@ -1,5 +1,5 @@
 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/* gkr-pk-object-storage.h - Manage all 'token' PK objects
+/* gkr-pk-object-storage.h - Store general 'token' PK objects
 
    Copyright (C) 2007 Stefan Walter
 
@@ -27,7 +27,7 @@
 #include <gcrypt.h>
 #include <glib-object.h>
 
-#include "gkr-pk-object.h"
+#include "gkr-pk-storage.h"
 
 G_BEGIN_DECLS
 
@@ -42,27 +42,16 @@
 typedef struct _GkrPkObjectStorageClass GkrPkObjectStorageClass;
 
 struct _GkrPkObjectStorage {
-	 GObject parent;
+	 GkrPkStorage parent;
 };
 
 struct _GkrPkObjectStorageClass {
-	GObjectClass parent_class;
+	GkrPkStorageClass parent_class;
 };
 
 GType                   gkr_pk_object_storage_get_type           (void) G_GNUC_CONST;
 
-GkrPkObjectStorage*     gkr_pk_object_storage_get                (void);
-
-void                    gkr_pk_object_storage_refresh            (GkrPkObjectStorage *storage);
-
-gboolean                gkr_pk_object_storage_load_complete      (GkrPkObjectStorage *storage, 
-                                                                  GkrPkObject *obj, GError **err);
-
-gboolean                gkr_pk_object_storage_add                (GkrPkObjectStorage *storage,
-                                                                  GkrPkObject *obj, GError **err);
-
-gboolean                gkr_pk_object_storage_remove             (GkrPkObjectStorage *storage,
-                                                                  GkrPkObject *obj, GError **err);
+gboolean                gkr_pk_object_storage_initialize         (void);
 
 G_END_DECLS
 

Modified: trunk/pk/gkr-pk-object.c
==============================================================================
--- trunk/pk/gkr-pk-object.c	(original)
+++ trunk/pk/gkr-pk-object.c	Tue Jul  8 22:23:20 2008
@@ -34,6 +34,8 @@
 
 #include "common/gkr-location.h"
 
+#include <glib/gi18n.h>
+
 #include <string.h>
 
 /* --------------------------------------------------------------------------------
@@ -59,6 +61,7 @@
 
 struct _GkrPkObjectPrivate {
 	GHashTable *attr_cache;
+	gchar *label;
 	gchar *orig_label;
 	guint load_state;
 	gboolean dummy_digest;
@@ -70,6 +73,8 @@
 #define GKR_PK_OBJECT_GET_PRIVATE(o)  \
 	(G_TYPE_INSTANCE_GET_PRIVATE((o), GKR_TYPE_PK_OBJECT, GkrPkObjectPrivate))
 
+static guint64 unique_counter = 0;
+
 G_DEFINE_TYPE(GkrPkObject, gkr_pk_object, G_TYPE_OBJECT);
 
 /* --------------------------------------------------------------------------------
@@ -137,16 +142,6 @@
 		gkr_pk_index_delete (old_index, obj->digest);
 }
 
-static void
-remove_indexes (GkrPkObject *obj)
-{
-	GkrPkIndex *index = NULL;
-	
-	if (obj->storage)
-		index = gkr_pk_storage_index (obj->storage, obj->location);
-	gkr_pk_index_delete (index, obj->digest);
-}
-
 /* --------------------------------------------------------------------------------
  * OBJECT
  */
@@ -155,12 +150,16 @@
 gkr_pk_object_init (GkrPkObject *obj)
 {
 	GkrPkObjectPrivate *pv = GKR_PK_OBJECT_GET_PRIVATE (obj);
+	
 	pv->attr_cache = g_hash_table_new_full (g_direct_hash, g_direct_equal, 
 	                                        NULL, gkr_pk_attribute_free);
 	
-	/* Create a dummy digest which is the object address */
+	/* Create a dummy digest which has the object address */
 	pv->dummy_digest = TRUE;
-	obj->digest = gkr_id_new ((guchar*)&obj, sizeof (obj));
+	++unique_counter;
+	obj->digest = gkr_id_new_digestv((guchar*)&obj, sizeof (obj),
+	                                 (guchar*)&unique_counter, sizeof (unique_counter),
+	                                 NULL);
 }
 
 static GObject*
@@ -202,17 +201,10 @@
 gkr_pk_object_get_attribute_common (GkrPkObject *obj, CK_ATTRIBUTE_PTR attr)
 {
 	CK_OBJECT_CLASS cls;
-	gchar *label;
 
 	switch (attr->type) {
 	case CKA_LABEL:
-		label = gkr_pk_object_get_label (obj);
-		if (!label && obj->location)
-			label = gkr_location_to_display (obj->location);
-		if (!label)
-			label = g_strdup ("");
-		gkr_pk_attribute_set_string (attr, label);
-		g_free (label);
+		gkr_pk_attribute_set_string (attr, gkr_pk_object_get_label (obj));
 		return CKR_OK;
 	
 	case CKA_TOKEN:
@@ -294,7 +286,7 @@
 		g_value_set_string (value, pv->orig_label);
 		break;
 	case PROP_LABEL:
-		g_value_take_string (value, gkr_pk_object_get_label (xobj));
+		g_value_set_string (value, gkr_pk_object_get_label (xobj));
 		break;
 	case PROP_STORAGE:
 		g_value_set_object (value, xobj->storage);
@@ -308,6 +300,7 @@
 {
 	GkrPkObject *xobj = GKR_PK_OBJECT (obj);
 	GkrPkObjectPrivate *pv = GKR_PK_OBJECT_GET_PRIVATE (xobj);
+	GkrPkObjectManager *manager;
 	GkrPkIndex *index;
 	GkrPkStorage *storage;
 	gkrid digest;
@@ -327,6 +320,7 @@
 		if (location)
 			move_indexes_if_necessary (xobj, xobj->storage, location);
 		xobj->location = location; 
+		gkr_pk_object_flush (xobj);
 		break;
 		
 	case PROP_DIGEST:
@@ -341,8 +335,9 @@
 		g_return_if_fail (digest);
 		
 		/* Unregister old digest with object manager */
-		if (xobj->manager)
-			gkr_pk_object_manager_unregister (xobj->manager, xobj);
+		manager = xobj->manager;
+		if (manager)
+			gkr_pk_object_manager_unregister (manager, xobj);
 
 		/* Rename to the new digest in the index */
 		index = xobj->storage ? gkr_pk_storage_index (xobj->storage, xobj->location) : NULL;
@@ -354,16 +349,18 @@
 		/* Change to new digest */
 		gkr_id_free (xobj->digest);
 		xobj->digest = digest;
+		gkr_pk_object_flush (xobj);
 
 		/* Register with the object manager with the new digest */
-		if (xobj->manager)
-			gkr_pk_object_manager_register (xobj->manager, xobj);
+		if (manager)
+			gkr_pk_object_manager_register (manager, xobj);
 		
 		break;
 		
 	case PROP_ORIG_LABEL:
 		g_free (pv->orig_label);
 		pv->orig_label = g_value_dup_string (value);
+		gkr_pk_object_flush (xobj);
 		break;
 		
 	case PROP_LABEL:
@@ -381,6 +378,7 @@
 		
 		/* We don't reference, storage should remove itself before the end */
 		xobj->storage = storage;
+		gkr_pk_object_flush (xobj);
 		break;
 	};
 }
@@ -391,10 +389,6 @@
 	GkrPkObject *xobj = GKR_PK_OBJECT (obj);
 	GkrPkObjectPrivate *pv = GKR_PK_OBJECT_GET_PRIVATE (xobj);
 	
-	/* If this never actually got stored properly, then remove it */
-	if (pv->dummy_digest || !xobj->storage)
-		remove_indexes (xobj);
-	
 	if (pv->attr_cache)
 		g_hash_table_destroy (pv->attr_cache);
 		
@@ -440,7 +434,7 @@
 		                   
 	g_object_class_install_property (gobject_class, PROP_DIGEST,
 		g_param_spec_boxed ("digest", "Digest", "Digest Identifier for Data",
-		                    GKR_ID_BOXED_TYPE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+		                    GKR_ID_BOXED_TYPE, G_PARAM_READWRITE));
 		                    
 	g_object_class_install_property (gobject_class, PROP_ORIG_LABEL,
 		g_param_spec_string ("orig-label", "Original Label", "Original Label",
@@ -519,7 +513,11 @@
 {
 	GkrPkObjectPrivate *pv = GKR_PK_OBJECT_GET_PRIVATE(object);
 	g_return_if_fail (GKR_IS_PK_OBJECT (object));
+	
 	g_hash_table_remove_all (pv->attr_cache);
+	
+	g_free (pv->label);
+	pv->label = NULL;
 }
 
 void
@@ -781,11 +779,44 @@
 	return ret;
 }
 
-gchar*
+const gchar*
 gkr_pk_object_get_label (GkrPkObject *xobj)
 {
+	GkrPkObjectPrivate *pv = GKR_PK_OBJECT_GET_PRIVATE (xobj);
+	GType type;
+	
 	g_return_val_if_fail (GKR_IS_PK_OBJECT (xobj), NULL);
-	return gkr_pk_object_index_get_string (xobj, "label");
+	
+	if (!pv->label) {
+		/* Try the label from the index */
+		pv->label = gkr_pk_object_index_get_string (xobj, GKR_PK_INDEX_LABEL);
+				
+		/* Try any original label handed us by parsers */
+		if (!pv->label && pv->orig_label) 
+			pv->label = g_strdup (pv->orig_label);
+		
+		/* Try and use the filename */
+		if (!pv->label && xobj->location) 
+			pv->label = gkr_location_to_display (xobj->location);
+		
+		/* Come up with a name depending on the type */
+		if (!pv->label) {
+			type = G_OBJECT_TYPE (xobj);
+			if (type == GKR_TYPE_PK_CERT) {
+				pv->label = g_strdup (_("Certificate"));
+			} else if (type == GKR_TYPE_PK_PRIVKEY) {
+				pv->label = g_strdup (_("Private Key"));
+			} else if (type == GKR_TYPE_PK_PUBKEY) {
+				pv->label = g_strdup (_("Public Key"));
+			} else {
+				g_warning ("no default label for objects of type: %s",
+				           G_OBJECT_TYPE_NAME (xobj));
+				pv->label = g_strdup (G_OBJECT_TYPE_NAME (xobj));
+			}
+		}
+	}
+	
+	return pv->label;
 }
 
 void

Modified: trunk/pk/gkr-pk-object.h
==============================================================================
--- trunk/pk/gkr-pk-object.h	(original)
+++ trunk/pk/gkr-pk-object.h	Tue Jul  8 22:23:20 2008
@@ -31,7 +31,9 @@
 
 G_BEGIN_DECLS
 
-#define GKR_PK_OBJECT_HANDLE_MASK      0x0FFFFFFF
+#define GKR_PK_INDEX_LABEL              "label"
+
+#define GKR_PK_OBJECT_HANDLE_MASK       0x0FFFFFFF
 #define GKR_PK_OBJECT_IS_PERMANENT	0x10000000
 #define GKR_PK_OBJECT_IS_TEMPORARY	0x00000000
 
@@ -145,7 +147,7 @@
 CK_RV               gkr_pk_object_set_attributes   (GkrPkObject *object, 
                                                     GArray *attrs);
 
-gchar*              gkr_pk_object_get_label        (GkrPkObject *object);
+const gchar*        gkr_pk_object_get_label        (GkrPkObject *object);
 
 void                gkr_pk_object_set_label        (GkrPkObject *object, 
                                                     const gchar *label);

Modified: trunk/pk/gkr-pk-privkey.c
==============================================================================
--- trunk/pk/gkr-pk-privkey.c	(original)
+++ trunk/pk/gkr-pk-privkey.c	Tue Jul  8 22:23:20 2008
@@ -116,7 +116,7 @@
 	obj = GKR_PK_OBJECT (key);
 	
 	/* Do we have a public key in the indexes? */
-	data = gkr_pk_object_index_get_binary (obj, "public-key", &n_data);
+	data = gkr_pk_object_index_get_binary (obj, GKR_PK_INDEX_PUBLIC_KEY, &n_data);
 	if (data) {
 		res = gkr_pkix_der_read_public_key (data, n_data, &s_key);
 		if (res == GKR_PKIX_SUCCESS) {
@@ -125,7 +125,7 @@
 			goto done;
 		} 
 
-		gkr_pk_object_index_set_binary (obj, "public-key", NULL, 0);
+		gkr_pk_object_index_set_binary (obj, GKR_PK_INDEX_PUBLIC_KEY, NULL, 0);
 		g_warning ("invalid public-key in indexes for: %s", g_quark_to_string (obj->location));
 	}
 	
@@ -147,7 +147,8 @@
 		g_return_val_if_fail (data != NULL, NULL);
 		
 		/* Write the public key out to the indexes */
-		gkr_pk_object_index_set_binary (obj, "public-key", data, n_data);
+		gkr_pk_object_index_set_binary (obj, GKR_PK_INDEX_PUBLIC_KEY, data, n_data);
+		g_free (data);
 		
 		key->priv->pubkey = gkr_pk_pubkey_instance (obj->manager, 0, s_key);
 		goto done;

Modified: trunk/pk/gkr-pk-privkey.h
==============================================================================
--- trunk/pk/gkr-pk-privkey.h	(original)
+++ trunk/pk/gkr-pk-privkey.h	Tue Jul  8 22:23:20 2008
@@ -33,6 +33,8 @@
 
 G_BEGIN_DECLS
 
+#define GKR_PK_INDEX_PUBLIC_KEY         "public-key"
+
 #define GKR_TYPE_PK_PRIVKEY             (gkr_pk_privkey_get_type())
 #define GKR_PK_PRIVKEY(obj)             (G_TYPE_CHECK_INSTANCE_CAST((obj), GKR_TYPE_PK_PRIVKEY, GkrPkPrivkey))
 #define GKR_PK_PRIVKEY_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST((klass), GKR_TYPE_PK_PRIVKEY, GkrPkPrivkey))
@@ -61,7 +63,7 @@
 CK_RV               gkr_pk_privkey_create             (GkrPkObjectManager* manager, 
                                                        GArray* array, GkrPkObject **object);
                                                        
-gkrconstid      gkr_pk_privkey_get_keyid          (GkrPkPrivkey *pkey);
+gkrconstid          gkr_pk_privkey_get_keyid          (GkrPkPrivkey *pkey);
 
 gkrid               gkr_pk_privkey_make_keyid         (gcry_sexp_t skey);
 

Modified: trunk/pk/gkr-pk-storage.c
==============================================================================
--- trunk/pk/gkr-pk-storage.c	(original)
+++ trunk/pk/gkr-pk-storage.c	Tue Jul  8 22:23:20 2008
@@ -374,6 +374,16 @@
  * PUBLIC 
  */
 
+
+GQuark
+gkr_pk_storage_get_error_domain (void)
+{
+	static GQuark domain = 0;
+	if (domain == 0)
+		domain = g_quark_from_static_string ("gkr-pk-storage-error");
+	return domain;
+}
+
 void
 gkr_pk_storage_register (GkrPkStorage *storage, gboolean is_default)
 {
@@ -585,6 +595,32 @@
 	g_array_free (copy, TRUE);
 }
 
+GSList*
+gkr_pk_storage_get_objects (GkrPkStorage *storage, GQuark location)
+{
+	GkrPkStoragePrivate *pv = GKR_PK_STORAGE_GET_PRIVATE (storage);
+	GArray *objs;
+	gpointer k;
+	GSList *result;
+	guint i;
+		
+	/* Remove everything that is at that location */
+	k = GUINT_TO_POINTER (location);
+	objs = (GArray*)g_hash_table_lookup (pv->objects_by_location, k);
+	if (!objs)
+		return NULL;
+			
+	/* When removing we cleanup empty arrays */
+	g_assert (objs->len);
+
+	/* We copy because otherwise the array will change from underneath us */
+	result = NULL;
+	for (i = 0; i < objs->len; ++i)
+		result = g_slist_prepend (result, g_array_index (objs, GkrPkObject*, i));
+	
+	return result;
+}
+
 GkrPkChecks*
 gkr_pk_storage_checks_prepare (GkrPkStorage *storage, GQuark location)
 {
@@ -633,9 +669,8 @@
 }
 
 gboolean
-gkr_pk_storage_get_store_password (GkrPkStorage *storage, GQuark location,
-                                   GQuark type, const gchar *label, gboolean *save,
-                                   gchar **result)
+gkr_pk_storage_get_store_password (GkrPkStorage *storage, GQuark location, gkrconstid digest,
+                                   GQuark type, const gchar *label, gchar **result)
 {
 	GkrAskRequest *ask;
 	gchar *custom_label = NULL;
@@ -643,13 +678,21 @@
 	gchar *display = NULL;
 	gboolean ret;
 	guint flags;
+	GkrPkIndex *index;
 	GkrKeyring *login;
 	
 	g_return_val_if_fail (GKR_IS_PK_STORAGE (storage), FALSE);
 	g_return_val_if_fail (result != NULL, FALSE);
-	g_return_val_if_fail (save != NULL, FALSE);
-	
-	*save = FALSE;
+
+	index = gkr_pk_storage_index (storage, location);
+	g_return_val_if_fail (index, FALSE);
+
+	/*
+	 * We save the password while still here in this function.
+	 *  - Optimistic, assuming it'll succeed.
+	 *  - Can store to the possibly bogus digest, because objects
+	 *    will move all index storage to the real digest later.
+	 */
 
 	/* See if we can just use the login keyring password for this */
 	if (gkr_keyring_login_is_usable ()) {
@@ -663,8 +706,8 @@
 		 * Always same a 'login' password used as a secret. So that 
 		 * the user can later change the login password, and this'll 
 		 * still work. 
-		 */ 
-		*save = TRUE;
+		 */
+		gkr_pk_index_set_secret (index, digest, *result);
 		return TRUE;
 	}
 
@@ -699,7 +742,8 @@
 	/* Successful response */
 	} else {
 		*result = gkr_secure_strdup (ask->typed_password);
-		*save = ask->checked;
+		if (ask->checked)
+			gkr_pk_index_set_secret (index, digest, *result);
 	}
 	
 	g_free (display);
@@ -714,7 +758,6 @@
                                   gchar **result)
 {
 	GkrAskRequest *ask;
-	gchar *custom_label = NULL;
 	gchar *stype, *secondary;
 	gchar *display = NULL;
 	gboolean ret;
@@ -788,12 +831,6 @@
 			type = g_quark_from_string (stype);
 		g_free (stype);
 	}
-		
-	/* TODO: Load a better label if we have one */
-	custom_label = NULL;
-		
-	if (custom_label != NULL)
-		label = custom_label;
 	
 	if (!label) 
 		label = display = gkr_location_to_display (location);
@@ -834,7 +871,6 @@
 	}
 	
 	g_free (display);
-	g_free (custom_label);
 	g_object_unref (ask);
 	return ret;
 }

Modified: trunk/pk/gkr-pk-storage.h
==============================================================================
--- trunk/pk/gkr-pk-storage.h	(original)
+++ trunk/pk/gkr-pk-storage.h	Tue Jul  8 22:23:20 2008
@@ -32,6 +32,8 @@
 
 G_BEGIN_DECLS
 
+#define GKR_PK_STORAGE_ERROR            (gkr_pk_storage_get_error_domain ())
+
 #define GKR_TYPE_PK_STORAGE             (gkr_pk_storage_get_type ())
 #define GKR_PK_STORAGE(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), GKR_TYPE_PK_STORAGE, GkrPkStorage))
 #define GKR_PK_STORAGE_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), GKR_TYPE_PK_STORAGE, GkrPkStorageClass))
@@ -58,6 +60,8 @@
 
 GType                   gkr_pk_storage_get_type           (void) G_GNUC_CONST;
 
+GQuark 	                gkr_pk_storage_get_error_domain   (void) G_GNUC_CONST;
+
 void                    gkr_pk_storage_register           (GkrPkStorage *storage, 
                                                            gboolean default_storage);
 
@@ -94,6 +98,9 @@
 void                    gkr_pk_storage_clr_objects        (GkrPkStorage *storage, 
                                                            GQuark location);
 
+GSList*                 gkr_pk_storage_get_objects        (GkrPkStorage *storage,
+                                                           GQuark location);
+
 typedef GHashTable GkrPkChecks;
 
 GkrPkChecks*            gkr_pk_storage_checks_prepare     (GkrPkStorage *storage, 
@@ -109,9 +116,9 @@
 #define GKR_PK_STORAGE_PASSWD_PROMPT	 2
 
 gboolean                gkr_pk_storage_get_store_password (GkrPkStorage *storage, 
-                                                           GQuark location, GQuark type, 
-                                                           const gchar *label, gboolean *save, 
-                                                           gchar **passowrd);
+                                                           GQuark location, gkrconstid digest, 
+                                                           GQuark type, const gchar *label,  
+                                                           gchar **password);
 	
 gboolean                gkr_pk_storage_get_load_password  (GkrPkStorage *storage, 
                                                            GQuark location, gkrconstid digest, 

Modified: trunk/pk/tests/Makefile.am
==============================================================================
--- trunk/pk/tests/Makefile.am	(original)
+++ trunk/pk/tests/Makefile.am	Tue Jul  8 22:23:20 2008
@@ -3,7 +3,8 @@
 	unit-test-pk-index.c \
 	unit-test-pk-cert.c \
 	unit-test-pk-key.c \
-	unit-test-pk-netscape-trust.c
+	unit-test-pk-netscape-trust.c \
+	unit-test-pk-object.c
 
 UNIT_PROMPT = 
 

Added: trunk/pk/tests/unit-test-pk-object.c
==============================================================================
--- (empty file)
+++ trunk/pk/tests/unit-test-pk-object.c	Tue Jul  8 22:23:20 2008
@@ -0,0 +1,135 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* unit-test-pk-object.c: Test a object
+
+   Copyright (C) 2007 Stefan Walter
+
+   The Gnome Keyring Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The Gnome Keyring Library 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the Gnome Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.
+
+   Author: Stef Walter <stef memberwebs com>
+*/
+
+#include "config.h"
+
+#include "run-auto-test.h"
+
+#include "common/gkr-location.h"
+
+#include "pk/gkr-pk-cert.h"
+#include "pk/gkr-pk-index.h"
+#include "pk/gkr-pk-object.h"
+#include "pk/gkr-pk-object-manager.h"
+
+#include "pkcs11/pkcs11.h"
+#include "pkcs11/pkcs11g.h"
+
+#include "pkix/gkr-pkix-der.h"
+
+#include <glib.h>
+#include <memory.h>
+
+/* 
+ * Each test looks like (on one line):
+ *     void unit_test_xxxxx (CuTest* cu)
+ * 
+ * Each setup looks like (on one line):
+ *     void unit_setup_xxxxx (void)
+ * 
+ * Each teardown looks like (on one line):
+ *     void unit_teardown_xxxxx (void)
+ * 
+ * Tests be run in the order specified here.
+ */
+
+static GkrPkObjectManager *manager = NULL;
+static GkrPkObject *object_1 = NULL;
+
+void unit_setup_object (void)
+{
+	/* Our own object manager */
+	manager = gkr_pk_object_manager_instance_for_client (1239);
+	object_1 = g_object_new (GKR_TYPE_PK_CERT, "location", 0, "manager", manager, NULL);
+}
+
+void unit_test_object_label (CuTest* cu)
+{
+	CK_ATTRIBUTE attr;
+	const gchar *label;
+	GQuark loc;
+	
+	/* Should always return a default label */
+	label = gkr_pk_object_get_label (object_1);
+	CuAssert (cu, "no label returned for empty object", label != NULL);
+	g_printerr ("EMPTY LABEL: %s\n", label);
+	
+	/* The next priority should be the location based label */
+	loc = gkr_location_from_child (GKR_LOCATION_VOLUME_FILE, "test-object.pk");
+	g_object_set (object_1, "location", loc, NULL);
+	label = gkr_pk_object_get_label (object_1);
+	CuAssert (cu, "no label returned after location label", label != NULL);
+	CuAssert (cu, "wrong label returned after location label", strcmp (label, "test-object.pk") == 0);
+	g_printerr ("LOCATION LABEL: %s\n", label);
+	
+	/* Should return the original label by default (parsed) */
+	g_object_set (object_1, "orig-label", "Orig Label", NULL);
+	label = gkr_pk_object_get_label (object_1);
+	CuAssert (cu, "no label returned after orig label", label != NULL);
+	CuAssert (cu, "wrong label returned after orig label", strcmp (label, "Orig Label") == 0);
+	g_printerr ("ORIG LABEL: %s\n", label);
+	
+	/* After setting a label in index, should return that */
+	gkr_pk_object_index_set_string (object_1, GKR_PK_INDEX_LABEL, "Index Label");
+	label = gkr_pk_object_get_label (object_1);
+	CuAssert (cu, "no label returned after index label", label != NULL);
+	CuAssert (cu, "wrong label returned after index label", strcmp (label, "Index Label") == 0);
+	g_printerr ("INDEX LABEL: %s\n", label);
+	
+	/* Should be able to set the label via pkcs11 */
+	attr.pValue = "Pkcs11 Label";
+	attr.ulValueLen = strlen (attr.pValue);
+	attr.type = CKA_LABEL;
+	gkr_pk_object_set_attribute (object_1, &attr);
+	label = gkr_pk_object_get_label (object_1);
+	CuAssert (cu, "no label returned after pkcs11 label", label != NULL);
+	CuAssert (cu, "wrong label returned after pkcs11 label", strcmp (label, "Pkcs11 Label") == 0);
+	g_printerr ("PKCS11 LABEL: %s\n", label);
+	
+	/* Should be able to set the label via properties */
+	g_object_set (object_1, "label", "Property Label", NULL);
+	label = gkr_pk_object_get_label (object_1);
+	CuAssert (cu, "no label returned after property label", label != NULL);
+	CuAssert (cu, "wrong label returned after property label", strcmp (label, "Property Label") == 0);
+	g_printerr ("PROPERTY LABEL: %s\n", label);
+
+	/* Should be able to set the label directly */
+	gkr_pk_object_set_label(object_1, "Direct Label");
+	label = gkr_pk_object_get_label (object_1);
+	CuAssert (cu, "no label returned after direct label", label != NULL);
+	CuAssert (cu, "wrong label returned after direct label", strcmp (label, "Direct Label") == 0);
+	g_printerr ("DIRECT LABEL: %s\n", label);
+}
+
+#include "check-attribute.c"
+		 
+void unit_test_object_static (CuTest *cu)
+{
+	gkr_pk_object_set_label (object_1, "The Label");
+	
+	CHECK_BOOL_ATTRIBUTE (cu, object_1, CKA_PRIVATE, CK_FALSE);
+	CHECK_BOOL_ATTRIBUTE (cu, object_1, CKA_TOKEN, CK_FALSE);
+	CHECK_BOOL_ATTRIBUTE (cu, object_1, CKA_MODIFIABLE, CK_TRUE);
+	CHECK_BYTE_ATTRIBUTE (cu, object_1, CKA_LABEL, "The Label", strlen ("The Label"));
+}
+

Modified: trunk/pkix/gkr-pkix-serialize.c
==============================================================================
--- trunk/pkix/gkr-pkix-serialize.c	(original)
+++ trunk/pkix/gkr-pkix-serialize.c	Tue Jul  8 22:23:20 2008
@@ -295,3 +295,18 @@
 	
 	return data;
 }
+
+const gchar*
+gkr_pkix_serialize_get_extension (GQuark type)
+{
+	g_return_val_if_fail (type, NULL);
+	
+	if (type == GKR_PKIX_CERTIFICATE)
+		return "crt";
+	else if (type == GKR_PKIX_PUBLIC_KEY)
+		return "key";
+	else if (type == GKR_PKIX_PRIVATE_KEY)
+		return "pkcs8";
+	return "pk";
+}
+

Modified: trunk/pkix/gkr-pkix-serialize.h
==============================================================================
--- trunk/pkix/gkr-pkix-serialize.h	(original)
+++ trunk/pkix/gkr-pkix-serialize.h	Tue Jul  8 22:23:20 2008
@@ -14,6 +14,8 @@
                                                          const gchar *password, 
                                                          gsize *n_data);
 
+const gchar*      gkr_pkix_serialize_get_extension      (GQuark type);
+
 guchar*           gkr_pkix_serialize_certificate        (ASN1_TYPE asn, gsize *n_data);
 
 guchar*           gkr_pkix_serialize_public_key         (gcry_sexp_t skey, gsize *n_data);

Modified: trunk/po/POTFILES.in
==============================================================================
--- trunk/po/POTFILES.in	(original)
+++ trunk/po/POTFILES.in	Tue Jul  8 22:23:20 2008
@@ -7,6 +7,8 @@
 keyrings/gkr-keyring-login.c
 keyrings/gkr-keyring.c
 pk/gkr-pk-index.c
+pk/gkr-pk-object.c
+pk/gkr-pk-object-storage.c
 pk/gkr-pk-storage.c
 pkix/gkr-pkix-parser.c
 pkix/gkr-pkix-serialize.c

Modified: trunk/ssh/gkr-ssh-daemon-ops.c
==============================================================================
--- trunk/ssh/gkr-ssh-daemon-ops.c	(original)
+++ trunk/ssh/gkr-ssh-daemon-ops.c	Tue Jul  8 22:23:20 2008
@@ -265,7 +265,6 @@
 	GList *objects, *pubkeys, *l;
 	GkrPkPubkey *pub;
 	gsize blobpos;
-	const gchar *label;
 	
 	/* Only find the keys that have usage = ssh */
 	objects = gkr_pk_object_manager_findv (gkr_pk_object_manager_for_token (), GKR_TYPE_PK_PRIVKEY, 
@@ -298,8 +297,7 @@
 		gkr_buffer_set_uint32 (resp, blobpos, (resp->len - blobpos) - 4);
 		
 		/* And now a per key comment */
-		label = gkr_pk_object_get_label (GKR_PK_OBJECT (pub));
-		gkr_buffer_add_string (resp, label ? label : "");
+		gkr_buffer_add_string (resp, gkr_pk_object_get_label (GKR_PK_OBJECT (pub)));
 	}
 	
 	g_list_free (pubkeys);

Modified: trunk/ssh/gkr-ssh-storage.c
==============================================================================
--- trunk/ssh/gkr-ssh-storage.c	(original)
+++ trunk/ssh/gkr-ssh-storage.c	Tue Jul  8 22:23:20 2008
@@ -71,7 +71,7 @@
 static GQuark PEM_RSA_PRIVATE_KEY;
 static GQuark PEM_DSA_PRIVATE_KEY;
 
-#define NO_VALUE GUINT_TO_POINTER (TRUE)
+static GkrPkIndex* gkr_ssh_storage_index (GkrPkStorage *storage, GQuark unused);
 
 /* -----------------------------------------------------------------------------
  * HELPERS
@@ -114,12 +114,10 @@
 }
 
 static GkrPkObject*
-prepare_object (GkrSshStorage *storage, GQuark location, 
-                gkrconstid digest, gboolean is_public)
+prepare_object (GkrSshStorage *storage, GQuark location, gkrconstid digest)
 {
 	GkrPkObjectManager *manager;
 	GkrPkObject *object;
-	GType gtype;
 	
 	manager = gkr_pk_object_manager_for_token ();
 	object = gkr_pk_object_manager_find_by_digest (manager, digest);
@@ -130,12 +128,7 @@
 		return object;
 	} 
 	
-	if (is_public)
-		gtype = GKR_TYPE_PK_PUBKEY;
-	else
-		gtype = GKR_TYPE_PK_PRIVKEY;
-	
-	object = g_object_new (gtype, "manager", manager, "location", location, 
+	object = g_object_new (GKR_TYPE_PK_PRIVKEY, "manager", manager, "location", location, 
 	                       "digest", digest, NULL);
 	gkr_pk_storage_add_object (GKR_PK_STORAGE (storage), object);
 
@@ -158,49 +151,8 @@
 }
 
 static gboolean
-storage_load_public_key (GkrSshStorage *storage, GQuark loc, GError **err)
-{
- 	GkrPkObject *object;
-	GkrPkixResult res;
-	gcry_sexp_t sexp;
-	gkrid digest;
-	gchar *comment;
-	guchar *data;
-	gsize n_data;
-	
-	g_return_val_if_fail (loc, FALSE);
-	g_return_val_if_fail (!err || !*err, FALSE);
-	
-	if (!gkr_location_read_file (loc, &data, &n_data, err))
-		return FALSE;
-
-	res = gkr_ssh_storage_load_public_key (data, n_data, &sexp, &comment);
-	if (res == GKR_PKIX_FAILURE) {
-		g_set_error (err, GKR_SSH_STORAGE_ERROR, 0, _("Couldn't read secure shell key public key: %s"),
-		             g_quark_to_string (loc));
-		return FALSE;
-	} else if (res == GKR_PKIX_UNRECOGNIZED) {
-		g_set_error (err, GKR_SSH_STORAGE_ERROR, 0, _("Invalid secure shell public key at: %s"),
-		             g_quark_to_string (loc));
-		return FALSE;
-	}
-	
-	digest = gkr_id_new_digest (data, n_data);
-	
-	/* Prepare and setup the object */
-	object = prepare_object (storage, loc, digest, TRUE);
-	g_object_set (object, "orig-label", comment, NULL);
-	g_object_set (object, "gcrypt-sexp", sexp, NULL);
-	
-	
-	gkr_id_free (digest);
-	g_free (comment);
-	return TRUE;
-}
-
-static gboolean
 storage_write_public_key (GkrSshStorage *storage, gcry_sexp_t sexp, 
-                          GQuark loc, GError **err)
+                          const gchar *comment, GQuark loc, GError **err)
 {
 	guchar *data;
 	gsize n_data;
@@ -209,10 +161,9 @@
 	g_return_val_if_fail (loc, FALSE);
 	g_return_val_if_fail (!err || !*err, FALSE);
 
-	/* TODO: What about the comment? */
-	data = gkr_ssh_storage_write_public_key(sexp, NULL, &n_data); 
+	data = gkr_ssh_storage_write_public_key (sexp, comment, &n_data); 
 	if (!data) {
-		g_set_error (err, GKR_SSH_STORAGE_ERROR, 0, _("Couldn't encode secure shell public key."));
+		g_set_error (err, GKR_PK_STORAGE_ERROR, 0, _("Couldn't encode secure shell public key."));
 		return FALSE;
 	}
 	
@@ -226,6 +177,7 @@
 store_public_key_for_private (GkrSshStorage *storage, GkrPkObject *priv, GError **err)
 {
 	gcry_sexp_t sexp, psexp;
+	gchar *label;
 	gboolean ret;
 	GQuark ploc;
 	
@@ -243,7 +195,9 @@
 	
 	/* And then store that public key next to the private */
 	ploc = public_location_for_private (priv->location);
-	ret = storage_write_public_key (storage, psexp, ploc, err);
+	g_object_get (priv, "orig-label", &label, NULL);
+	ret = storage_write_public_key (storage, psexp, label, ploc, err);
+	g_free (label);
 	gcry_sexp_release (psexp);
 	
 	return ret;
@@ -299,23 +253,62 @@
 	return GKR_PKIX_FAILURE;
 }
 
-
 static void
-add_corresponding_public (GkrSshStorage *storage, GQuark loc)
+index_correspending_public_key (GkrSshStorage *storage, GQuark loc, gkrconstid digest, 
+                                gchar **comment)
 {
-	GError *err = NULL;
+ 	GError *err = NULL;
+	GkrPkixResult res;
+	GkrPkIndex *index;
+	gcry_sexp_t sexp;
+	guchar *data;
+	gsize n_data;
 	GQuark ploc;
 	
+	*comment = NULL;
+
 	g_return_if_fail (loc);
+	
+	index = gkr_ssh_storage_index (GKR_PK_STORAGE (storage), loc);
+	g_return_if_fail (index);
+	
 	ploc = public_location_for_private (loc);
+	g_return_if_fail (ploc);
 	
-	if (gkr_location_test_file (ploc, G_FILE_TEST_IS_REGULAR)) {
-		if (!storage_load_public_key (storage, ploc, &err)) {
-			g_message ("couldn't parse public key: %s: %s", g_quark_to_string (ploc),
-			           err && err->message ? err->message : "");
-			g_clear_error (&err);
-		}
+	/* Does the file even exist? */
+	if (!gkr_location_test_file (ploc, G_FILE_TEST_IS_REGULAR))
+		return;
+			
+	if (!gkr_location_read_file (ploc, &data, &n_data, &err)) {
+		g_message ("couldn't read public key file: %s: %s", g_quark_to_string (ploc),
+		           err && err->message ? err->message : "");
+		g_clear_error (&err);
+		return;
 	}
+
+	res = gkr_ssh_storage_load_public_key (data, n_data, &sexp, comment);
+	g_free (data);
+	
+	if (res == GKR_PKIX_FAILURE) {
+		g_message ("couldn't parse public key file: %s", g_quark_to_string (ploc));
+		g_free (*comment);
+		*comment = NULL;
+		return;
+	} else if (res == GKR_PKIX_UNRECOGNIZED) {
+		g_message ("invalid secure shell public key file: %s", g_quark_to_string (ploc));
+		g_free (*comment);
+		*comment = NULL;
+		return;
+	}
+
+	/* Write key to the indexes */
+	if (!gkr_pk_index_has_value (index, digest, GKR_PK_INDEX_PUBLIC_KEY)) {
+		data = gkr_pkix_der_write_public_key (sexp, &n_data);
+		g_return_if_fail (data != NULL);
+		gkr_pk_index_set_binary (index, digest, GKR_PK_INDEX_PUBLIC_KEY, data, n_data);
+	}
+	
+	gcry_sexp_release (sexp);
 }
 
 typedef struct _Load {
@@ -331,9 +324,10 @@
 {
 	Load *ctx = (Load*)user_data;
  	GkrSshStoragePrivate *pv = GKR_SSH_STORAGE_GET_PRIVATE (ctx->storage);
-	gcry_sexp_t sexp;
+	gcry_sexp_t sexp = NULL;
 	GkrPkObject *object;
 	const gchar *dekinfo;
+	gchar *comment;
 	gkrid digest;
 	
 	/* Only handle SSHv2 private keys */
@@ -366,17 +360,30 @@
 		ctx->result = gkr_pkix_der_read_private_key (data, n_data, &sexp);
 	}
 	
-	if (ctx->result == GKR_PKIX_SUCCESS) {
-		if (gkr_id_equals (pv->specific_load_request, digest))
-			pv->specific_load_request = NULL;
-	
-		/* Prepare and setup the object */
-		object = prepare_object (ctx->storage, ctx->location, digest, FALSE);
-		if (sexp)
-			g_object_set (object, "gcrypt-sexp", sexp, NULL);
-	
+	if (!ctx->result == GKR_PKIX_SUCCESS) {
 		gkr_id_free (digest);
+		return;
 	}
+	
+	/* 
+	 * Now that we have a digest, and we know the key parses, let's be helpful
+	 * and check whether we have the public key in our indexes. If not, load it up.
+	 * It's important that we do this before the private key object is instantiated
+	 */
+	index_correspending_public_key (ctx->storage, ctx->location, digest, &comment);
+	
+	if (gkr_id_equals (pv->specific_load_request, digest))
+		pv->specific_load_request = NULL;
+	
+	/* Prepare and setup the object */
+	object = prepare_object (ctx->storage, ctx->location, digest);
+	if (sexp)
+		g_object_set (object, "gcrypt-sexp", sexp, NULL);
+	if (comment)
+		g_object_set (object, "orig-label", comment, NULL);
+	
+	g_free (comment);
+	gkr_id_free (digest);
 }
 
 static gboolean
@@ -404,18 +411,15 @@
 		return TRUE;
 	
 	if (ctx.result == GKR_PKIX_FAILURE) {
-		g_set_error (err, GKR_SSH_STORAGE_ERROR, 0, _("Couldn't read secure shell key private key: %s"),
+		g_set_error (err, GKR_PK_STORAGE_ERROR, 0, _("Couldn't read secure shell key private key: %s"),
 		             g_quark_to_string (loc));
 		return FALSE;
 	} else if (ctx.result == GKR_PKIX_UNRECOGNIZED) {
-		g_set_error (err, GKR_SSH_STORAGE_ERROR, 0, _("Invalid secure shell private key at: %s"),
+		g_set_error (err, GKR_PK_STORAGE_ERROR, 0, _("Invalid secure shell private key at: %s"),
 		             g_quark_to_string (loc));
 		return FALSE;
 	}
 	
-	/* Load the corresponding public key */
-	add_corresponding_public (storage, loc);
-	
 	return TRUE;
 }
 
@@ -459,7 +463,7 @@
 
 		if (!gkr_pkix_openssl_encrypt_block (dekinfo, password, data, n_data,
 		                                     &encrypted, &n_encrypted)) {
-			g_set_error (err, GKR_SSH_STORAGE_ERROR, 0, 
+			g_set_error (err, GKR_PK_STORAGE_ERROR, 0, 
 			             _("Couldn't encrypt the SSH key to store it."));
 			goto done;
 		}
@@ -475,7 +479,7 @@
 	
 	/* Make sure it worked */
 	if (!result) {
-		g_set_error (err, GKR_SSH_STORAGE_ERROR, 0, 
+		g_set_error (err, GKR_PK_STORAGE_ERROR, 0, 
 		             _("Couldn't encode the SSH key to store it."));
 		gkr_id_free (digest);
 		digest = NULL;
@@ -553,16 +557,12 @@
 	if (GKR_IS_PK_PRIVKEY (obj))
 		storage_load_private_key (GKR_SSH_STORAGE (storage), obj->location, err);
 	
-	/* Load a private key from this location */
-	else if (GKR_IS_PK_PUBKEY (obj))
-		storage_load_public_key (GKR_SSH_STORAGE (storage), obj->location, err);
-	
 	else
 		g_return_val_if_reached (FALSE);
 	
 	/* See if it was seen */
 	if (pv->specific_load_request != NULL) {
-		g_set_error (err, GKR_SSH_STORAGE_ERROR, 0, "The object was not found at: %s",
+		g_set_error (err, GKR_PK_STORAGE_ERROR, 0, "The object was not found at: %s",
 		             g_quark_to_string (obj->location));
 		pv->specific_load_request = NULL;
 		goto done;
@@ -572,7 +572,8 @@
 	 * At this point, if we were loading a public key, it should be all loaded, 
 	 * including encrypted parts. Write out the public key if needed. 
 	 */
-	if (GKR_IS_PK_PRIVKEY (obj))
+	if (GKR_IS_PK_PRIVKEY (obj) && 
+	    !gkr_location_test_file (public_location_for_private (obj->location), G_FILE_TEST_EXISTS))
 		store_public_key_for_private (GKR_SSH_STORAGE (storage), obj, NULL);
 
 	ret = TRUE;
@@ -588,9 +589,8 @@
 	GkrSshStorage *storage;
 	gcry_sexp_t sexp;
 	gchar *password;
-	gchar *label;
 	gkrid digest;
-	gboolean save, ret;
+	gboolean ret;
 	GQuark loc;
 	
 	g_return_val_if_fail (!err || !*err, FALSE);
@@ -601,9 +601,6 @@
 	storage = GKR_SSH_STORAGE (stor);
 	
 	/* We don't yet support storing arbitrary public keys */
-	if (GKR_IS_PK_PUBKEY (obj))
-		return TRUE;
-	
 	g_return_val_if_fail (GKR_IS_PK_PRIVKEY (obj), FALSE);
 	
 	/* Pull out the actual part of the key */
@@ -615,10 +612,9 @@
 	g_return_val_if_fail (loc, FALSE);
 		
 	/* Get a password for this key, determines whether encrypted or not */
-	label = gkr_pk_object_get_label (obj);
-	ret = gkr_pk_storage_get_store_password (stor, loc, GKR_PKIX_PRIVATE_KEY, 
-	                                         label, &save, &password);
-	g_free (label);
+	ret = gkr_pk_storage_get_store_password (stor, loc, obj->digest, GKR_PKIX_PRIVATE_KEY, 
+	                                         gkr_pk_object_get_label (obj),
+	                                         &password);
 	
 	/* Prompt for a password was denied */
 	if (!ret)
@@ -765,15 +761,6 @@
  * PUBLIC FUNCTIONS
  */
 
-GQuark
-gkr_ssh_storage_get_error_domain (void)
-{
-	static GQuark domain = 0;
-	if (domain == 0)
-		domain = g_quark_from_static_string ("gkr-ssh-storage-error");
-	return domain;
-}
-
 gboolean
 gkr_ssh_storage_initialize (void)
 {
@@ -882,14 +869,14 @@
 	}
 	
 	/* If there's data left, its the comment */
-	if (comment && n_data)
-		*comment = g_strndup ((gchar*)data, n_data);
+	if (comment)
+		*comment = n_data ? g_strndup ((gchar*)data, n_data) : NULL;
 
 	return GKR_PKIX_SUCCESS;
 }
 
 guchar*
-gkr_ssh_storage_write_public_key (gcry_sexp_t sexp, gchar *comment,
+gkr_ssh_storage_write_public_key (gcry_sexp_t sexp, const gchar *comment,
                                   gsize *n_data)
 {
 	GString *result;
@@ -929,6 +916,8 @@
 		g_string_append (result, comment);
 	}
 	
+	g_string_append_c (result, '\n');
+	
 	*n_data = result->len;
 	return (guchar*)g_string_free (result, FALSE);
 }

Modified: trunk/ssh/gkr-ssh-storage.h
==============================================================================
--- trunk/ssh/gkr-ssh-storage.h	(original)
+++ trunk/ssh/gkr-ssh-storage.h	Tue Jul  8 22:23:20 2008
@@ -9,8 +9,6 @@
 
 G_BEGIN_DECLS
 
-#define GKR_SSH_STORAGE_ERROR            (gkr_ssh_storage_get_error_domain ())
-
 #define GKR_TYPE_SSH_STORAGE             (gkr_ssh_storage_get_type ())
 #define GKR_SSH_STORAGE(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), GKR_TYPE_SSH_STORAGE, GkrSshStorage))
 #define GKR_SSH_STORAGE_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), GKR_TYPE_SSH_STORAGE, GObject))
@@ -31,14 +29,12 @@
 
 GType                   gkr_ssh_storage_get_type          (void) G_GNUC_CONST;
 
-GQuark 	                gkr_ssh_storage_get_error_domain  (void) G_GNUC_CONST;
-
 gboolean                gkr_ssh_storage_initialize        (void);
 
 GkrPkixResult           gkr_ssh_storage_load_public_key   (const guchar *data, gsize n_data, 
                                                            gcry_sexp_t *sexp, gchar **comment);
 
-guchar*                 gkr_ssh_storage_write_public_key  (gcry_sexp_t sexp, gchar *comment,
+guchar*                 gkr_ssh_storage_write_public_key  (gcry_sexp_t sexp, const gchar *comment,
                                                            gsize *n_data);
 
 G_END_DECLS

Modified: trunk/ssh/tests/unit-test-ssh-storage.c
==============================================================================
--- trunk/ssh/tests/unit-test-ssh-storage.c	(original)
+++ trunk/ssh/tests/unit-test-ssh-storage.c	Tue Jul  8 22:23:20 2008
@@ -49,8 +49,8 @@
  * Tests be run in the order specified here.
  */
 
-static const gchar *TEST_DSA_KEY = "ssh-dss AAAAB3NzaC1kc3MAAACBAJhgJycWojhw+UkvgFTdrBnCyVAZZPbbGCJ9bvoVb8N75MAmsPZugNInz6j6Iz+sa1nsYlBZnrhg4mXfxeWOTiI6/YDbPdA65P/q4oNDjKIjgBiC135un40+Qz8JGq2JPrU5pElH4jb8NYA4PymuIL7vingUvFK3XJiWSb2ZepNXAAAAFQCWBBXsX/Vi3GpSlG88Z+P8NQqmQQAAAIB0JOhEstQgJKic5Vx+C1MtBS2DX8dQ1TLo4bgzDTbYU4mbqJDUkhhYP2IGFEpuWFxLaCGsWoBfWi98Wz9o1P9TYkbmCiDd8mt7Px5bUR09orMUvHiNaLM9kH0KxUxAifGcrAsATloLJ8ReNJkypB9frjjbN1b/7YDyEP0zSiwDwwAAAIA9syAP6aY0kIdv7yqC5biGJqY170cpJYOE/vFHDVUXrXaTgPsoEQuRMFwHZbhgrVcUTKLJsmIyrpqWZ41PxDHgk1SC9GYDLmb65Pn23NvUDAZKft6E09KGL49LNpitfzLxvZAMLcU+YVCrUJwT/NgPTJ70GFrLs3z8UsKeFFxEUA== Test Comment"; 
-static const gchar *TEST_RSA_KEY = "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEAz8Ji7Z1/NK7tvHETqSuLWPyn4l0fF6lTTbYf9Jx21RtaNwmaCi9u1Id3wVQMtuuR+0NLoBPyVdDrWi6ap9TkKdNQnnqW4Ang+GZc+9sXzbgWmgXnjKTXo+EcpMJLqpTLXPcaxYtwGIL/K/BE7NJ9i43HPqUG5z8ezE1/iHkfHMk= stef memberwebs com"; 
+static const gchar *TEST_DSA_KEY = "ssh-dss AAAAB3NzaC1kc3MAAACBAJhgJycWojhw+UkvgFTdrBnCyVAZZPbbGCJ9bvoVb8N75MAmsPZugNInz6j6Iz+sa1nsYlBZnrhg4mXfxeWOTiI6/YDbPdA65P/q4oNDjKIjgBiC135un40+Qz8JGq2JPrU5pElH4jb8NYA4PymuIL7vingUvFK3XJiWSb2ZepNXAAAAFQCWBBXsX/Vi3GpSlG88Z+P8NQqmQQAAAIB0JOhEstQgJKic5Vx+C1MtBS2DX8dQ1TLo4bgzDTbYU4mbqJDUkhhYP2IGFEpuWFxLaCGsWoBfWi98Wz9o1P9TYkbmCiDd8mt7Px5bUR09orMUvHiNaLM9kH0KxUxAifGcrAsATloLJ8ReNJkypB9frjjbN1b/7YDyEP0zSiwDwwAAAIA9syAP6aY0kIdv7yqC5biGJqY170cpJYOE/vFHDVUXrXaTgPsoEQuRMFwHZbhgrVcUTKLJsmIyrpqWZ41PxDHgk1SC9GYDLmb65Pn23NvUDAZKft6E09KGL49LNpitfzLxvZAMLcU+YVCrUJwT/NgPTJ70GFrLs3z8UsKeFFxEUA== Test Comment\n"; 
+static const gchar *TEST_RSA_KEY = "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEAz8Ji7Z1/NK7tvHETqSuLWPyn4l0fF6lTTbYf9Jx21RtaNwmaCi9u1Id3wVQMtuuR+0NLoBPyVdDrWi6ap9TkKdNQnnqW4Ang+GZc+9sXzbgWmgXnjKTXo+EcpMJLqpTLXPcaxYtwGIL/K/BE7NJ9i43HPqUG5z8ezE1/iHkfHMk= stef memberwebs com\n"; 
 static const gchar *TEST_COMMENT_KEY = "# a line that shouldn't be parsed \n\nssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEAz8Ji7Z1/NK7tvHETqSuLWPyn4l0fF6lTTbYf9Jx21RtaNwmaCi9u1Id3wVQMtuuR+0NLoBPyVdDrWi6ap9TkKdNQnnqW4Ang+GZc+9sXzbgWmgXnjKTXo+EcpMJLqpTLXPcaxYtwGIL/K/BE7NJ9i43HPqUG5z8ezE1/iHkfHMk= stef memberwebs com\n# \n"; 
 
 void unit_test_ssh_public_dsa (CuTest* cu)



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