gnome-keyring r1170 - in trunk: . daemon pk pk/tests pkix po ssh ssh/tests
- From: nnielsen svn gnome org
- To: svn-commits-list gnome org
- Subject: gnome-keyring r1170 - in trunk: . daemon pk pk/tests pkix po ssh ssh/tests
- Date: Tue, 8 Jul 2008 22:23:20 +0000 (UTC)
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]