[gnome-keyring/dbus-api] [dbus] Refactor object to dbus path mapping.
- From: Stefan Walter <stefw src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [gnome-keyring/dbus-api] [dbus] Refactor object to dbus path mapping.
- Date: Thu, 12 Nov 2009 01:25:07 +0000 (UTC)
commit 52aac7a5a95ad19a24149f6b1f54c12d5f0f90a8
Author: Stef Walter <stef memberwebs com>
Date: Wed Nov 11 03:49:14 2009 +0000
[dbus] Refactor object to dbus path mapping.
Put pkcs11 object to dbus path mapping of secret
collections and items into its own file.
daemon/dbus/Makefile.am | 3 +-
daemon/dbus/gkd-secret-objects.c | 402 +++++++------------------------------
daemon/dbus/gkd-secret-objects.h | 8 +-
daemon/dbus/gkd-secret-prompt.c | 14 +-
daemon/dbus/gkd-secret-prompt.h | 2 +
daemon/dbus/gkd-secret-types.h | 1 +
daemon/dbus/gkd-secret-util.c | 411 ++++++++++++++++++++++++++++++++++++++
daemon/dbus/gkd-secret-util.h | 45 ++++
8 files changed, 542 insertions(+), 344 deletions(-)
---
diff --git a/daemon/dbus/Makefile.am b/daemon/dbus/Makefile.am
index 5aa9758..8353bc9 100644
--- a/daemon/dbus/Makefile.am
+++ b/daemon/dbus/Makefile.am
@@ -23,7 +23,8 @@ libgkr_dbus_la_SOURCES = \
gkd-secret-service.c gkd-secret-service.h \
gkd-secret-session.c gkd-secret-session.h \
gkd-secret-types.h \
- gkd-secret-unlock.c gkd-secret-unlock.h
+ gkd-secret-unlock.c gkd-secret-unlock.h \
+ gkd-secret-util.c gkd-secret-util.h
libgkr_dbus_la_LIBADD = \
$(GLIB_LIBS) \
diff --git a/daemon/dbus/gkd-secret-objects.c b/daemon/dbus/gkd-secret-objects.c
index af61e46..b3a3fe1 100644
--- a/daemon/dbus/gkd-secret-objects.c
+++ b/daemon/dbus/gkd-secret-objects.c
@@ -26,6 +26,7 @@
#include "gkd-secret-service.h"
#include "gkd-secret-objects.h"
#include "gkd-secret-types.h"
+#include "gkd-secret-util.h"
#include "pkcs11/pkcs11i.h"
@@ -77,104 +78,6 @@ typedef enum _DataType {
* INTERNAL
*/
-static void
-encode_object_identifier (GString *result, const gchar* name, gssize length)
-{
- g_assert (result);
- g_assert (name);
-
- if (length < 0)
- length = strlen (name);
-
- while (length > 0) {
- char ch = *(name++);
- --length;
-
- /* Normal characters can go right through */
- if (G_LIKELY ((ch >= 'A' && ch <= 'Z') ||
- (ch >= 'a' && ch <= 'z') ||
- (ch >= '0' && ch <= '9'))) {
- g_string_append_c_inline (result, ch);
-
- /* Special characters are encoded with a _ */
- } else {
- g_string_append_printf (result, "_%02x", (unsigned int)ch);
- }
- }
-}
-
-static gchar*
-decode_object_identifier (const gchar* enc, gssize length)
-{
- GString *result;
-
- g_assert (enc);
-
- if (length < 0)
- length = strlen (enc);
-
- result = g_string_sized_new (length);
- while (length > 0) {
- char ch = *(enc++);
- --length;
-
- /* Underscores get special handling */
- if (G_UNLIKELY (ch == '_' &&
- g_ascii_isxdigit(enc[0]) &&
- g_ascii_isxdigit (enc[1]))) {
- ch = (g_ascii_xdigit_value (enc[0]) * 16) +
- (g_ascii_xdigit_value (enc[1]));
- enc += 2;
- length -= 2;
- }
-
- g_string_append_c_inline (result, ch);
- }
-
- return g_string_free (result, FALSE);
-}
-
-static gboolean
-parse_collection_and_item_from_path (const gchar *path, gchar **collection, gchar **item)
-{
- const gchar *pos;
-
- g_return_val_if_fail (path, FALSE);
- g_assert (collection);
- g_assert (item);
-
- /* Make sure it starts with our prefix */
- if (!g_str_has_prefix (path, SECRET_COLLECTION_PREFIX))
- return FALSE;
- path += strlen (SECRET_COLLECTION_PREFIX);
-
- /* Skip the path separator */
- if (path[0] != '/')
- return FALSE;
- ++path;
-
- /* Make sure we have something */
- if (path[0] == '\0')
- return FALSE;
-
- pos = strchr (path, '/');
-
- /* No item, just a collection */
- if (pos == NULL) {
- *collection = decode_object_identifier (path, -1);
- *item = NULL;
- return TRUE;
- }
-
- /* Make sure we have an item, and no further path bits */
- if (pos[1] == '\0' || strchr (pos + 1, '/'))
- return FALSE;
-
- *collection = decode_object_identifier (path, pos - path);
- *item = decode_object_identifier (pos + 1, -1);
- return TRUE;
-}
-
static gboolean
property_to_attribute (const gchar *prop_name, CK_ATTRIBUTE_TYPE *attr_type, DataType *data_type)
{
@@ -579,45 +482,17 @@ static void
iter_append_item_paths (DBusMessageIter *iter, GList *items)
{
DBusMessageIter array;
- GP11Attributes *attrs;
- GError *error = NULL;
- GP11Attribute *coll;
- GP11Attribute *id;
- GString *path;
+ gchar *path;
GList *l;
dbus_message_iter_open_container (iter, DBUS_TYPE_ARRAY, "o", &array);
for (l = items; l; l = g_list_next (l)) {
-
- /* Dig out the raw item identifier */
- attrs = gp11_object_get (l->data, &error, CKA_ID, CKA_G_COLLECTION, GP11_INVALID);
- if (error != NULL) {
- g_warning ("couldn't retrieve item collection or id: %s", error->message);
- g_clear_error (&error);
- continue;
- }
-
- coll = gp11_attributes_find (attrs, CKA_G_COLLECTION);
- id = gp11_attributes_find (attrs, CKA_ID);
-
- if (!coll || gp11_attribute_is_invalid (coll) ||
- !id || gp11_attribute_is_invalid (id)) {
- g_warning ("item has invalid collection or id");
-
- } else {
- path = g_string_new (SECRET_COLLECTION_PREFIX);
- g_string_append_c (path, '/');
- encode_object_identifier (path, (gchar*)coll->value, coll->length);
- g_string_append_c (path, '/');
- encode_object_identifier (path, (gchar*)id->value, id->length);
-
- dbus_message_iter_append_basic (&array, DBUS_TYPE_OBJECT_PATH, &(path->str));
-
- g_string_free (path, TRUE);
+ path = gkd_secret_util_path_for_item (l->data);
+ if (path != NULL) {
+ dbus_message_iter_append_basic (&array, DBUS_TYPE_OBJECT_PATH, &path);
+ g_free (path);
}
-
- gp11_attributes_unref (attrs);
}
dbus_message_iter_close_container (iter, &array);
@@ -626,33 +501,18 @@ iter_append_item_paths (DBusMessageIter *iter, GList *items)
static void
iter_append_collection_paths (DBusMessageIter *iter, GList *collections)
{
- GString *path;
DBusMessageIter array;
- GError *error = NULL;
- gpointer data;
- gsize n_data;
+ gchar *path;
GList *l;
dbus_message_iter_open_container (iter, DBUS_TYPE_ARRAY, "o", &array);
for (l = collections; l; l = g_list_next (l)) {
-
- /* Dig out the raw item identifier */
- data = gp11_object_get_data (l->data, CKA_ID, &n_data, &error);
- if (error != NULL) {
- g_warning ("couldn't retrieve collection id: %s", error->message);
- g_clear_error (&error);
-
- } else if (n_data) {
- path = g_string_new (SECRET_COLLECTION_PREFIX);
- g_string_append_c (path, '/');
- encode_object_identifier (path, (gchar*)data, n_data);
- dbus_message_iter_append_basic (&array, DBUS_TYPE_OBJECT_PATH, &(path->str));
- g_string_free (path, TRUE);
+ path = gkd_secret_util_path_for_collection (l->data);
+ if (path != NULL) {
+ dbus_message_iter_append_basic (&array, DBUS_TYPE_OBJECT_PATH, &path);
+ g_free (path);
}
-
- g_free (data);
-
}
dbus_message_iter_close_container (iter, &array);
@@ -741,42 +601,6 @@ object_property_set (GP11Object *object, DBusMessage *message,
return dbus_message_new_method_return (message);
}
-static GP11Object*
-item_for_identifier (GP11Session *session, const gchar *coll_id, const gchar *item_id)
-{
- GP11Object *object = NULL;
- GError *error = NULL;
- GList *objects;
-
- g_assert (coll_id);
- g_assert (item_id);
-
- /*
- * TODO: I think this could benefit from some sort of
- * caching?
- */
-
- objects = gp11_session_find_objects (session, &error,
- CKA_CLASS, GP11_ULONG, CKO_SECRET_KEY,
- CKA_G_COLLECTION, strlen (coll_id), coll_id,
- CKA_ID, strlen (item_id), item_id,
- GP11_INVALID);
-
- if (error != NULL) {
- g_warning ("couldn't lookup '%s/%s' item: %s", coll_id, item_id, error->message);
- g_clear_error (&error);
- return NULL;
- }
-
- if (objects) {
- object = g_object_ref (objects->data);
- gp11_object_set_session (object, session);
- }
-
- gp11_list_unref_free (objects);
- return object;
-}
-
static DBusMessage*
item_property_get (GP11Object *object, DBusMessage *message)
{
@@ -912,48 +736,6 @@ item_message_handler (GkdSecretObjects *self, GP11Object *object, DBusMessage *m
return NULL;
}
-static const gchar*
-collection_get_identifier (GP11Object *coll)
-{
- return g_object_get_data (G_OBJECT (coll), "coll-identifier");
-}
-
-static GP11Object*
-collection_for_identifier (GP11Session *session, const gchar *coll_id)
-{
- GP11Object *object = NULL;
- GError *error = NULL;
- GList *objects;
-
- g_assert (coll_id);
-
- /*
- * TODO: I think this could benefit from some sort of
- * caching?
- */
-
- objects = gp11_session_find_objects (session, &error,
- CKA_CLASS, GP11_ULONG, CKO_G_COLLECTION,
- CKA_ID, strlen (coll_id), coll_id,
- GP11_INVALID);
-
- if (error != NULL) {
- g_warning ("couldn't lookup '%s' collection: %s", coll_id, error->message);
- g_clear_error (&error);
- return NULL;
- }
-
- if (objects) {
- object = objects->data;
- gp11_object_set_session (object, session);
- g_object_set_data_full (G_OBJECT (object), "coll-identifier", g_strdup (coll_id), g_free);
- g_object_ref (object);
- }
-
- gp11_list_unref_free (objects);
- return object;
-}
-
static DBusMessage*
collection_property_get (GkdSecretObjects *self, GP11Object *object, DBusMessage *message)
{
@@ -975,8 +757,7 @@ collection_property_get (GkdSecretObjects *self, GP11Object *object, DBusMessage
if (g_str_equal (name, "Items")) {
reply = dbus_message_new_method_return (message);
dbus_message_iter_init_append (reply, &iter);
- gkd_secret_objects_append_item_paths (self, &iter, message,
- collection_get_identifier (object));
+ gkd_secret_objects_append_item_paths (self, &iter, message, object);
return reply;
}
@@ -1051,8 +832,7 @@ collection_property_getall (GkdSecretObjects *self, GP11Object *object, DBusMess
dbus_message_iter_open_container (&array, DBUS_TYPE_DICT_ENTRY, NULL, &dict);
name = "Items";
dbus_message_iter_append_basic (&dict, DBUS_TYPE_STRING, &name);
- gkd_secret_objects_append_item_paths (self, &dict, message,
- collection_get_identifier (object));
+ gkd_secret_objects_append_item_paths (self, &dict, message, object);
dbus_message_iter_close_container (&array, &dict);
dbus_message_iter_close_container (&iter, &array);
@@ -1062,12 +842,7 @@ collection_property_getall (GkdSecretObjects *self, GP11Object *object, DBusMess
static DBusMessage*
collection_method_search_items (GkdSecretObjects *self, GP11Object *object, DBusMessage *message)
{
- const gchar *coll_id;
-
- coll_id = collection_get_identifier (object);
- g_return_val_if_fail (coll_id, NULL);
-
- return gkd_secret_objects_handle_search_items (self, message, coll_id);
+ return gkd_secret_objects_handle_search_items (self, message, object);
}
static GP11Object*
@@ -1075,14 +850,14 @@ collection_find_matching_item (GkdSecretObjects *self, GP11Object *coll, GP11Att
{
GP11Attributes *attrs;
const gchar *identifier;
- GP11Object *result;
+ GP11Object *result = NULL;
GError *error = NULL;
GP11Session *session;
GP11Object *search;
gpointer data;
gsize n_data;
- identifier = collection_get_identifier (coll);
+ identifier = gkd_secret_util_identifier_for_collection (coll);
g_return_val_if_fail (identifier, NULL);
/* Find items matching the collection and fields */
@@ -1109,15 +884,16 @@ collection_find_matching_item (GkdSecretObjects *self, GP11Object *coll, GP11Att
/* Get the matched item handles, and delete the search object */
gp11_object_set_session (search, session);
data = gp11_object_get_data (search, CKA_G_MATCHED, &n_data, NULL);
- g_return_val_if_fail (data && n_data >= sizeof (CK_OBJECT_HANDLE), NULL);
gp11_object_destroy (search, NULL);
g_object_unref (search);
- result = gp11_object_from_handle (gp11_session_get_slot (session),
- *((CK_OBJECT_HANDLE_PTR)data));
- gp11_object_set_session (result, session);
- g_free (data);
+ if (n_data >= sizeof (CK_OBJECT_HANDLE)) {
+ result = gp11_object_from_handle (gp11_session_get_slot (session),
+ *((CK_OBJECT_HANDLE_PTR)data));
+ gp11_object_set_session (result, session);
+ }
+ g_free (data);
return result;
}
@@ -1133,9 +909,8 @@ collection_method_create_item (GkdSecretObjects *self, GP11Object *object, DBusM
GError *error = NULL;
GP11Session *session;
DBusMessage *reply;
- GString *path = NULL;
- gpointer data;
- gsize n_data;
+ gchar *path = NULL;
+ gchar *identifier;
/* Parse the message */
if (!dbus_message_has_signature (message, "a{sv}b"))
@@ -1168,28 +943,22 @@ collection_method_create_item (GkdSecretObjects *self, GP11Object *object, DBusM
} else {
session = gp11_object_get_session (object);
g_return_val_if_fail (session, NULL);
+ identifier = gkd_secret_util_identifier_for_collection (object);
+ g_return_val_if_fail (identifier, NULL);
gp11_attributes_add_ulong (attrs, CKA_CLASS, CKO_SECRET_KEY);
- gp11_attributes_add_string (attrs, CKA_G_COLLECTION, collection_get_identifier (object));
+ gp11_attributes_add_string (attrs, CKA_G_COLLECTION, identifier);
item = gp11_session_create_object_full (session, attrs, NULL, &error);
+ g_free (identifier);
}
/* Build up the item identifier */
- if (error == NULL) {
- data = gp11_object_get_data (item, CKA_ID, &n_data, &error);
- if (data != NULL) {
- path = g_string_new (SECRET_COLLECTION_PREFIX);
- g_string_append_c (path, '/');
- g_string_append (path, collection_get_identifier (object));
- g_string_append_c (path, '/');
- encode_object_identifier (path, data, n_data);
- g_free (data);
- }
- }
+ if (error == NULL)
+ path = gkd_secret_util_path_for_item (item);
- if (error == NULL) {
+ if (path != NULL) {
prompt = "/";
reply = dbus_message_new_method_return (message);
- dbus_message_append_args (reply, DBUS_TYPE_OBJECT_PATH, &(path->str),
+ dbus_message_append_args (reply, DBUS_TYPE_OBJECT_PATH, &path,
DBUS_TYPE_OBJECT_PATH, &prompt,
DBUS_TYPE_INVALID);
@@ -1205,8 +974,7 @@ collection_method_create_item (GkdSecretObjects *self, GP11Object *object, DBusM
if (item)
g_object_unref (item);
- if (path)
- g_string_free (path, TRUE);
+ g_free (path);
return reply;
}
@@ -1400,8 +1168,8 @@ gkd_secret_objects_dispatch (GkdSecretObjects *self, DBusMessage *message)
DBusMessage *reply = NULL;
GP11Object *object;
GP11Session *session;
- gchar *coll_id;
- gchar *item_id;
+ gboolean is_item;
+ const char *path;
g_return_val_if_fail (GKD_SECRET_IS_OBJECTS (self), NULL);
g_return_val_if_fail (message, NULL);
@@ -1411,30 +1179,19 @@ gkd_secret_objects_dispatch (GkdSecretObjects *self, DBusMessage *message)
if (session == NULL)
return NULL;
- /* Figure out which collection or item we're talking about */
- if (!parse_collection_and_item_from_path (dbus_message_get_path (message), &coll_id, &item_id))
- return NULL;
+ path = dbus_message_get_path (message);
+ g_return_val_if_fail (path, NULL);
- /* It's an item */
- if (item_id) {
- object = item_for_identifier (session, coll_id, item_id);
- if (object != NULL) {
- reply = item_message_handler (self, object, message);
- g_object_unref (object);
- }
-
- /* It's a collection */
- } else {
- object = collection_for_identifier (session, coll_id);
- if (object != NULL) {
- reply = collection_message_handler (self, object, message);
- g_object_unref (object);
- }
- }
+ object = gkd_secret_util_path_to_object (session, path, &is_item);
+ if (!object)
+ return NULL;
- g_free (coll_id);
- g_free (item_id);
+ if (is_item)
+ reply = item_message_handler (self, object, message);
+ else
+ reply = collection_message_handler (self, object, message);
+ g_object_unref (object);
return reply;
}
@@ -1480,36 +1237,41 @@ gkd_secret_objects_parse_item_props (GkdSecretObjects *self, DBusMessageIter *it
void
gkd_secret_objects_append_item_paths (GkdSecretObjects *self, DBusMessageIter *iter,
- DBusMessage *message, const gchar *coll_id)
+ DBusMessage *message, GP11Object *collection)
{
DBusMessageIter variant;
GP11Session *session;
GError *error = NULL;
+ gchar *identifier;
GList *items;
g_return_if_fail (GKD_SECRET_IS_OBJECTS (self));
- g_return_if_fail (coll_id);
+ g_return_if_fail (GP11_IS_OBJECT (collection));
g_return_if_fail (iter && message);
/* The session we're using to access the object */
session = gkd_secret_service_get_pkcs11_session (self->service, dbus_message_get_sender (message));
g_return_if_fail (session);
+ identifier = gkd_secret_util_identifier_for_collection (collection);
+ g_return_if_fail (identifier);
+
items = gp11_session_find_objects (session, &error,
CKA_CLASS, GP11_ULONG, CKO_SECRET_KEY,
- CKA_G_COLLECTION, strlen (coll_id), coll_id,
+ CKA_G_COLLECTION, strlen (identifier), identifier,
GP11_INVALID);
- if (error != NULL) {
- g_warning ("couldn't lookup items in '%s' collection: %s", coll_id, error->message);
+ if (error == NULL) {
+ dbus_message_iter_open_container (iter, DBUS_TYPE_VARIANT, "ao", &variant);
+ iter_append_item_paths (&variant, items);
+ dbus_message_iter_close_container (iter, &variant);
+ } else {
+ g_warning ("couldn't lookup items in '%s' collection: %s", identifier, error->message);
g_clear_error (&error);
- return;
}
- dbus_message_iter_open_container (iter, DBUS_TYPE_VARIANT, "ao", &variant);
- iter_append_item_paths (&variant, items);
- dbus_message_iter_close_container (iter, &variant);
gp11_list_unref_free (items);
+ g_free (identifier);
}
void
@@ -1546,7 +1308,7 @@ gkd_secret_objects_append_collection_paths (GkdSecretObjects *self, DBusMessageI
DBusMessage*
gkd_secret_objects_handle_search_items (GkdSecretObjects *self, DBusMessage *message,
- const gchar *coll_id)
+ GP11Object *collection)
{
GP11Attributes *attrs;
GP11Attribute *attr;
@@ -1555,10 +1317,14 @@ gkd_secret_objects_handle_search_items (GkdSecretObjects *self, DBusMessage *mes
GP11Session *session;
DBusMessage *reply;
GError *error = NULL;
+ gchar *identifier;
gpointer data;
gsize n_data;
GList *items;
+ g_return_val_if_fail (GKD_SECRET_IS_OBJECTS (self), NULL);
+ g_return_val_if_fail (message, NULL);
+
if (!dbus_message_has_signature (message, "a{ss}"))
return NULL;
@@ -1572,8 +1338,13 @@ gkd_secret_objects_handle_search_items (GkdSecretObjects *self, DBusMessage *mes
"Invalid data in attributes argument");
}
- if (coll_id)
- gp11_attributes_add_string (attrs, CKA_G_COLLECTION, coll_id);
+ if (collection != NULL) {
+ identifier = gkd_secret_util_identifier_for_collection (collection);
+ g_return_val_if_fail (identifier, NULL);
+ gp11_attributes_add_string (attrs, CKA_G_COLLECTION, identifier);
+ g_free (identifier);
+ }
+
gp11_attributes_add_ulong (attrs, CKA_CLASS, CKO_G_SEARCH);
gp11_attributes_add_boolean (attrs, CKA_TOKEN, FALSE);
@@ -1620,34 +1391,3 @@ gkd_secret_objects_handle_search_items (GkdSecretObjects *self, DBusMessage *mes
return reply;
}
-
-GP11Object*
-gkd_secret_objects_lookup_collection (GkdSecretObjects *self, const gchar *caller,
- const gchar *objpath)
-{
- GP11Session *session;
- GP11Object *coll;
- gchar *coll_id;
- gchar *item_id;
-
- g_return_val_if_fail (GKD_SECRET_IS_OBJECTS (self), NULL);
- g_return_val_if_fail (objpath, NULL);
- g_return_val_if_fail (caller, NULL);
-
- /* The session we're using to access the object */
- session = gkd_secret_service_get_pkcs11_session (self->service, caller);
- g_return_val_if_fail (session, NULL);
-
- /* Figure out which collection or item we're talking about */
- if (!parse_collection_and_item_from_path (objpath, &coll_id, &item_id))
- return NULL;
-
- g_return_val_if_fail (coll_id, NULL);
- coll = collection_for_identifier (session, coll_id);
-
- g_free (coll_id);
- g_free (item_id);
-
- return coll;
-
-}
diff --git a/daemon/dbus/gkd-secret-objects.h b/daemon/dbus/gkd-secret-objects.h
index 012068b..bb8fef7 100644
--- a/daemon/dbus/gkd-secret-objects.h
+++ b/daemon/dbus/gkd-secret-objects.h
@@ -48,7 +48,7 @@ DBusMessage* gkd_secret_objects_dispatch (GkdSecretObjec
DBusMessage* gkd_secret_objects_handle_search_items (GkdSecretObjects *self,
DBusMessage *message,
- const gchar *coll_id);
+ GP11Object *object);
void gkd_secret_objects_append_collection_paths (GkdSecretObjects *self,
DBusMessageIter *iter,
@@ -61,12 +61,8 @@ gboolean gkd_secret_objects_parse_item_props (GkdSecretObjec
void gkd_secret_objects_append_item_paths (GkdSecretObjects *self,
DBusMessageIter *iter,
DBusMessage *message,
- const gchar *coll_id);
+ GP11Object *collection);
GP11Slot* gkd_secret_objects_get_pkcs11_slot (GkdSecretObjects *self);
-GP11Object* gkd_secret_objects_lookup_collection (GkdSecretObjects *self,
- const gchar *caller,
- const gchar *objpath);
-
#endif /* __GKD_SECRET_OBJECTS_H__ */
diff --git a/daemon/dbus/gkd-secret-prompt.c b/daemon/dbus/gkd-secret-prompt.c
index 7912c73..aab53af 100644
--- a/daemon/dbus/gkd-secret-prompt.c
+++ b/daemon/dbus/gkd-secret-prompt.c
@@ -21,11 +21,12 @@
#include "config.h"
+#include "gkd-dbus-util.h"
#include "gkd-secret-service.h"
#include "gkd-secret-prompt.h"
#include "gkd-secret-objects.h"
#include "gkd-secret-types.h"
-#include "gkd-dbus-util.h"
+#include "gkd-secret-util.h"
#include "prompt/gkd-prompt.h"
@@ -376,15 +377,16 @@ gkd_secret_prompt_dismiss (GkdSecretPrompt *self)
}
GP11Object*
-gkd_secret_prompt_lookup_collection (GkdSecretPrompt *self, const gchar *objpath)
+gkd_secret_prompt_lookup_collection (GkdSecretPrompt *self, const gchar *path)
{
- GkdSecretObjects *objects;
+ GP11Session *session;
g_return_val_if_fail (GKD_SECRET_IS_PROMPT (self), NULL);
g_return_val_if_fail (self->pv->service, NULL);
+ g_return_val_if_fail (path, NULL);
- objects = gkd_secret_service_get_objects (self->pv->service);
- g_return_val_if_fail (objects, NULL);
+ session = gkd_secret_service_get_pkcs11_session (self->pv->service, self->pv->caller);
+ g_return_val_if_fail (session, NULL);
- return gkd_secret_objects_lookup_collection (objects, self->pv->caller, objpath);
+ return gkd_secret_util_path_to_collection (session, path);
}
diff --git a/daemon/dbus/gkd-secret-prompt.h b/daemon/dbus/gkd-secret-prompt.h
index fa29730..4ca1ac9 100644
--- a/daemon/dbus/gkd-secret-prompt.h
+++ b/daemon/dbus/gkd-secret-prompt.h
@@ -60,6 +60,8 @@ const gchar* gkd_secret_prompt_get_caller (GkdSecretPrompt *
const gchar* gkd_secret_prompt_get_object_path (GkdSecretPrompt *self);
+GP11Session* gkd_secret_prompt_get_pkcs11_session (GkdSecretPrompt *self);
+
GP11Object* gkd_secret_prompt_lookup_collection (GkdSecretPrompt *self,
const gchar *objpath);
diff --git a/daemon/dbus/gkd-secret-types.h b/daemon/dbus/gkd-secret-types.h
index 426e31a..c230ba4 100644
--- a/daemon/dbus/gkd-secret-types.h
+++ b/daemon/dbus/gkd-secret-types.h
@@ -44,6 +44,7 @@
#define SECRET_ERROR_NO_SESSION "org.freedesktop.Secrets.Error.NoSession"
typedef struct _GkdSecretCollection GkdSecretCollection;
+typedef struct _GkdSecretCreate GkdSecretCreate;
typedef struct _GkdSecretItem GkdSecretItem;
typedef struct _GkdSecretObjects GkdSecretObjects;
typedef struct _GkdSecretPrompt GkdSecretPrompt;
diff --git a/daemon/dbus/gkd-secret-util.c b/daemon/dbus/gkd-secret-util.c
new file mode 100644
index 0000000..1c7e162
--- /dev/null
+++ b/daemon/dbus/gkd-secret-util.c
@@ -0,0 +1,411 @@
+/*
+ * gnome-keyring
+ *
+ * Copyright (C) 2008 Stefan Walter
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include "gkd-secret-util.h"
+
+#include "pkcs11/pkcs11i.h"
+
+#include <string.h>
+
+/* -----------------------------------------------------------------------------
+ * INTERNAL
+ */
+
+static void
+encode_object_identifier (GString *result, const gchar* name, gssize length)
+{
+ g_assert (result);
+ g_assert (name);
+
+ if (length < 0)
+ length = strlen (name);
+
+ while (length > 0) {
+ char ch = *(name++);
+ --length;
+
+ /* Normal characters can go right through */
+ if (G_LIKELY ((ch >= 'A' && ch <= 'Z') ||
+ (ch >= 'a' && ch <= 'z') ||
+ (ch >= '0' && ch <= '9'))) {
+ g_string_append_c_inline (result, ch);
+
+ /* Special characters are encoded with a _ */
+ } else {
+ g_string_append_printf (result, "_%02x", (unsigned int)ch);
+ }
+ }
+}
+
+static gchar*
+decode_object_identifier (const gchar* enc, gssize length)
+{
+ GString *result;
+
+ g_assert (enc);
+
+ if (length < 0)
+ length = strlen (enc);
+
+ result = g_string_sized_new (length);
+ while (length > 0) {
+ char ch = *(enc++);
+ --length;
+
+ /* Underscores get special handling */
+ if (G_UNLIKELY (ch == '_' &&
+ g_ascii_isxdigit(enc[0]) &&
+ g_ascii_isxdigit (enc[1]))) {
+ ch = (g_ascii_xdigit_value (enc[0]) * 16) +
+ (g_ascii_xdigit_value (enc[1]));
+ enc += 2;
+ length -= 2;
+ }
+
+ g_string_append_c_inline (result, ch);
+ }
+
+ return g_string_free (result, FALSE);
+}
+
+static gboolean
+parse_collection_and_item_from_path (const gchar *path, gchar **collection, gchar **item)
+{
+ const gchar *pos;
+
+ g_return_val_if_fail (path, FALSE);
+
+ /* Make sure it starts with our prefix */
+ if (!g_str_has_prefix (path, SECRET_COLLECTION_PREFIX))
+ return FALSE;
+ path += strlen (SECRET_COLLECTION_PREFIX);
+
+ /* Skip the path separator */
+ if (path[0] != '/')
+ return FALSE;
+ ++path;
+
+ /* Make sure we have something */
+ if (path[0] == '\0')
+ return FALSE;
+
+ pos = strchr (path, '/');
+
+ /* No item, just a collection */
+ if (pos == NULL) {
+ if (collection)
+ *collection = decode_object_identifier (path, -1);
+ if (item)
+ *item = NULL;
+ return TRUE;
+ }
+
+ /* Make sure we have an item, and no further path bits */
+ if (pos[1] == '\0' || strchr (pos + 1, '/'))
+ return FALSE;
+
+ if (collection)
+ *collection = decode_object_identifier (path, pos - path);
+ if (item)
+ *item = decode_object_identifier (pos + 1, -1);
+ return TRUE;
+}
+
+static gchar*
+get_cached_path (GP11Object *object)
+{
+ gchar *path = g_object_get_data (G_OBJECT (object), "gkd-util-cached-identifier");
+ return g_strdup (path);
+}
+
+static void
+set_cached_path (GP11Object *object, const gchar *path)
+{
+ g_object_set_data_full (G_OBJECT (object), "gkd-util-cached-identifier",
+ g_strdup (path), g_free);
+}
+
+static GP11Object*
+item_for_identifier (GP11Session *session, const gchar *coll_id, const gchar *item_id)
+{
+ GP11Object *object = NULL;
+ GError *error = NULL;
+ GList *objects;
+
+ g_assert (coll_id);
+ g_assert (item_id);
+
+ /*
+ * TODO: I think this could benefit from some sort of
+ * caching?
+ */
+
+ objects = gp11_session_find_objects (session, &error,
+ CKA_CLASS, GP11_ULONG, CKO_SECRET_KEY,
+ CKA_G_COLLECTION, strlen (coll_id), coll_id,
+ CKA_ID, strlen (item_id), item_id,
+ GP11_INVALID);
+
+ if (error != NULL) {
+ g_warning ("couldn't lookup '%s/%s' item: %s", coll_id, item_id, error->message);
+ g_clear_error (&error);
+ return NULL;
+ }
+
+ if (objects) {
+ object = g_object_ref (objects->data);
+ gp11_object_set_session (object, session);
+ }
+
+ gp11_list_unref_free (objects);
+ return object;
+}
+
+static GP11Object*
+collection_for_identifier (GP11Session *session, const gchar *coll_id)
+{
+ GP11Object *object = NULL;
+ GError *error = NULL;
+ GList *objects;
+
+ g_assert (GP11_IS_SESSION (session));
+ g_assert (coll_id);
+
+ objects = gp11_session_find_objects (session, &error,
+ CKA_CLASS, GP11_ULONG, CKO_G_COLLECTION,
+ CKA_ID, strlen (coll_id), coll_id,
+ GP11_INVALID);
+
+ if (error != NULL) {
+ g_warning ("couldn't lookup '%s' collection: %s", coll_id, error->message);
+ g_clear_error (&error);
+ return NULL;
+ }
+
+ if (objects) {
+ object = objects->data;
+ gp11_object_set_session (object, session);
+ g_object_set_data_full (G_OBJECT (object), "coll-identifier", g_strdup (coll_id), g_free);
+ g_object_ref (object);
+ }
+
+ gp11_list_unref_free (objects);
+ return object;
+}
+
+GP11Object*
+gkd_secret_util_path_to_collection (GP11Session *session, const gchar *path)
+{
+ GP11Object *collection = NULL;
+ gchar *coll_id;
+ gchar *item_id;
+
+ g_return_val_if_fail (GP11_IS_SESSION (session), NULL);
+ g_return_val_if_fail (path, NULL);
+
+ /* Figure out which collection or item we're talking about */
+ if (!parse_collection_and_item_from_path (path, &coll_id, &item_id))
+ return NULL;
+
+ g_return_val_if_fail (coll_id, NULL);
+ collection = collection_for_identifier (session, coll_id);
+
+ g_free (coll_id);
+ g_free (item_id);
+
+ if (collection) {
+ set_cached_path (collection, path);
+ gp11_object_set_session (collection, session);
+ }
+
+ return collection;
+}
+
+gchar*
+gkd_secret_util_path_for_collection (GP11Object *object)
+{
+ GError *error = NULL;
+ GString *result;
+ gpointer data;
+ gsize n_data;
+ gchar *path;
+
+ g_return_val_if_fail (GP11_IS_OBJECT (object), NULL);
+
+ path = get_cached_path (object);
+ if (path != NULL)
+ return path;
+
+ data = gp11_object_get_data (object, CKA_ID, &n_data, &error);
+ if (data == NULL) {
+ g_warning ("couldn't lookup identifier for collection: %s",
+ error->message);
+ g_clear_error (&error);
+ g_return_val_if_reached (NULL);
+ }
+
+ result = g_string_new (SECRET_COLLECTION_PREFIX);
+ g_string_append_c (result, '/');
+ encode_object_identifier (result, data, n_data);
+ g_free (data);
+
+ path = g_string_free (result, FALSE);
+ set_cached_path (object, path);
+ return path;
+}
+
+GP11Object*
+gkd_secret_util_path_to_item (GP11Session *session, const gchar *path)
+{
+ GP11Object *item = NULL;
+ gchar *coll_id;
+ gchar *item_id;
+
+ g_return_val_if_fail (GP11_IS_SESSION (session), NULL);
+ g_return_val_if_fail (path, NULL);
+
+ /* Figure out which collection or item we're talking about */
+ if (!parse_collection_and_item_from_path (path, &coll_id, &item_id))
+ return NULL;
+
+ if (coll_id && item_id)
+ item = item_for_identifier (session, coll_id, item_id);
+ g_free (coll_id);
+ g_free (item_id);
+
+ if (item) {
+ set_cached_path (item, path);
+ gp11_object_set_session (item, session);
+ }
+
+ return item;
+}
+
+gchar*
+gkd_secret_util_path_for_item (GP11Object *object)
+{
+ GError *error = NULL;
+ GP11Attributes *attrs;
+ GP11Attribute *attr;
+ GString *result;
+ gchar *path;
+
+ g_return_val_if_fail (GP11_IS_OBJECT (object), NULL);
+
+ path = get_cached_path (object);
+ if (path != NULL)
+ return path;
+
+ attrs = gp11_object_get (object, &error, CKA_ID, CKA_G_COLLECTION, GP11_INVALID);
+ if (attrs == NULL) {
+ g_warning ("couldn't lookup identifier for item: %s", error->message);
+ g_clear_error (&error);
+ g_return_val_if_reached (NULL);
+ }
+
+ result = g_string_new (SECRET_COLLECTION_PREFIX);
+
+ g_string_append_c (result, '/');
+ attr = gp11_attributes_find (attrs, CKA_G_COLLECTION);
+ g_return_val_if_fail (attr && !gp11_attribute_is_invalid (attr), NULL);
+ encode_object_identifier (result, (const gchar*)attr->value, attr->length);
+
+ g_string_append_c (result, '/');
+ attr = gp11_attributes_find (attrs, CKA_ID);
+ g_return_val_if_fail (attr && !gp11_attribute_is_invalid (attr), NULL);
+ encode_object_identifier (result, (const gchar*)attr->value, attr->length);
+
+ gp11_attributes_unref (attrs);
+
+ path = g_string_free (result, FALSE);
+ set_cached_path (object, path);
+ return path;
+}
+
+GP11Object*
+gkd_secret_util_path_to_object (GP11Session *session, const gchar *path,
+ gboolean *is_item)
+{
+ GP11Object *object = NULL;
+ gchar *coll_id;
+ gchar *item_id;
+
+ g_return_val_if_fail (GP11_IS_SESSION (session), NULL);
+ g_return_val_if_fail (path, NULL);
+
+ /* Figure out which collection or item we're talking about */
+ if (!parse_collection_and_item_from_path (path, &coll_id, &item_id))
+ return NULL;
+
+ if (item_id) {
+ object = item_for_identifier (session, coll_id, item_id);
+ if (is_item)
+ *is_item = TRUE;
+ } else {
+ object = collection_for_identifier (session, coll_id);
+ }
+
+ g_free (coll_id);
+ g_free (item_id);
+
+ if (object) {
+ set_cached_path (object, path);
+ gp11_object_set_session (object, session);
+ }
+
+ return object;
+}
+
+
+gchar*
+gkd_secret_util_identifier_for_collection (GP11Object *collection)
+{
+ GError *error = NULL;
+ gchar *identifier = NULL;
+ gpointer data;
+ gsize n_data;
+ gchar *path;
+
+ g_return_val_if_fail (GP11_IS_OBJECT (collection), NULL);
+
+ /* Try to parse it out of the path */
+ path = get_cached_path (collection);
+ if (path != NULL) {
+ parse_collection_and_item_from_path (path, &identifier, NULL);
+ g_free (path);
+ }
+
+ /* Must do a lookup */
+ if (identifier == NULL) {
+ data = gp11_object_get_data (collection, CKA_ID, &n_data, &error);
+ if (data == NULL) {
+ g_warning ("couldn't get identifier for collection: %s", error->message);
+ g_clear_error (&error);
+ } else {
+ identifier = g_strndup (data, n_data);
+ g_free (data);
+ }
+ }
+
+ return identifier;
+}
diff --git a/daemon/dbus/gkd-secret-util.h b/daemon/dbus/gkd-secret-util.h
new file mode 100644
index 0000000..611899a
--- /dev/null
+++ b/daemon/dbus/gkd-secret-util.h
@@ -0,0 +1,45 @@
+/*
+ * gnome-keyring
+ *
+ * Copyright (C) 2009 Stefan Walter
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef __GKD_SECRET_UTIL_H__
+#define __GKD_SECRET_UTIL_H__
+
+#include "gkd-secret-types.h"
+
+#include "gp11/gp11.h"
+
+GP11Object* gkd_secret_util_path_to_collection (GP11Session *session,
+ const gchar *path);
+
+GP11Object* gkd_secret_util_path_to_item (GP11Session *session,
+ const gchar *path);
+
+GP11Object* gkd_secret_util_path_to_object (GP11Session *session,
+ const gchar *path,
+ gboolean *is_item);
+
+gchar* gkd_secret_util_path_for_collection (GP11Object *object);
+
+gchar* gkd_secret_util_path_for_item (GP11Object *object);
+
+gchar* gkd_secret_util_identifier_for_collection (GP11Object *collection);
+
+#endif /* __GKD_SECRET_UTIL_H__ */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]