[gnome-keyring/dbus-api] [dbus] Implement Service.CreateCollection()
- From: Stefan Walter <stefw src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [gnome-keyring/dbus-api] [dbus] Implement Service.CreateCollection()
- Date: Thu, 12 Nov 2009 06:38:23 +0000 (UTC)
commit 41e7dd756876fd3a33866703ad4739a7eac45fea
Author: Stef Walter <stef memberwebs com>
Date: Thu Nov 12 04:00:32 2009 +0000
[dbus] Implement Service.CreateCollection()
Implement creating of collections, including prompting for
the password.
daemon/data/introspect-service.xml | 5 +-
daemon/dbus/Makefile.am | 1 +
daemon/dbus/gkd-secret-create.c | 267 ++++++++++++++++++++++++++++++++++++
daemon/dbus/gkd-secret-create.h | 51 +++++++
daemon/dbus/gkd-secret-prompt.c | 24 ++--
daemon/dbus/gkd-secret-prompt.h | 3 -
daemon/dbus/gkd-secret-service.c | 58 ++++++++-
daemon/dbus/gkd-secret-unlock.c | 18 ++-
8 files changed, 403 insertions(+), 24 deletions(-)
---
diff --git a/daemon/data/introspect-service.xml b/daemon/data/introspect-service.xml
index 31f92cf..056175c 100644
--- a/daemon/data/introspect-service.xml
+++ b/daemon/data/introspect-service.xml
@@ -35,8 +35,9 @@
</method>
<method name="CreateCollection">
- <arg name="label" type="s" direction="in"/>
- <arg name="private" type="b" direction="in"/>
+ <arg name="props" type="a{sv}" direction="in"/>
+ <arg name="collection" type="o" direction="out"/>
+ <arg name="prompt" type="o" direction="out"/>
</method>
<method name="LockService">
diff --git a/daemon/dbus/Makefile.am b/daemon/dbus/Makefile.am
index ab99cad..f6116e7 100644
--- a/daemon/dbus/Makefile.am
+++ b/daemon/dbus/Makefile.am
@@ -18,6 +18,7 @@ libgkr_dbus_la_SOURCES = \
gkd-dbus-service.c \
gkd-dbus-session.c \
gkd-dbus-util.c gkd-dbus-util.h \
+ gkd-secret-create.c gkd-secret-create.h \
gkd-secret-objects.c gkd-secret-objects.h \
gkd-secret-property.c gkd-secret-property.h \
gkd-secret-prompt.c gkd-secret-prompt.h \
diff --git a/daemon/dbus/gkd-secret-create.c b/daemon/dbus/gkd-secret-create.c
new file mode 100644
index 0000000..f2cde76
--- /dev/null
+++ b/daemon/dbus/gkd-secret-create.c
@@ -0,0 +1,267 @@
+/*
+ * 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-create.h"
+#include "gkd-secret-service.h"
+#include "gkd-secret-prompt.h"
+#include "gkd-secret-types.h"
+#include "gkd-secret-util.h"
+
+#include "egg/egg-secure-memory.h"
+
+#include "pkcs11/pkcs11i.h"
+
+#include <glib/gi18n.h>
+
+#include <gp11/gp11.h>
+
+#include <string.h>
+
+enum {
+ PROP_0,
+ PROP_PKCS11_ATTRIBUTES
+};
+
+struct _GkdSecretCreate {
+ GkdSecretPrompt parent;
+ GP11Attributes *pkcs11_attrs;
+ gchar *result_path;
+};
+
+G_DEFINE_TYPE (GkdSecretCreate, gkd_secret_create, GKD_SECRET_TYPE_PROMPT);
+
+/* -----------------------------------------------------------------------------
+ * INTERNAL
+ */
+
+static void
+prepare_create_prompt (GkdSecretCreate *self)
+{
+ GkdPrompt *prompt;
+ gchar *label;
+ gchar *text;
+
+ g_assert (GKD_SECRET_IS_CREATE (self));
+ g_assert (self->pkcs11_attrs);
+
+ prompt = GKD_PROMPT (self);
+
+ if (!gp11_attributes_find_string (self->pkcs11_attrs, CKA_LABEL, &label))
+ label = g_strdup (_("Unnamed"));
+
+ gkd_prompt_reset (prompt);
+
+ gkd_prompt_set_title (prompt, _("New Keyring Password"));
+ gkd_prompt_set_primary_text (prompt, _("Choose password for new keyring"));
+
+ text = g_markup_printf_escaped (_("An application wants to create a new keyring called '%s'. "
+ "Choose the password you want to use for it."), label);
+ gkd_prompt_set_secondary_text (prompt, text);
+ g_free (text);
+
+ gkd_prompt_hide_widget (prompt, "name_area");
+ gkd_prompt_hide_widget (prompt, "confirm_area");
+ gkd_prompt_hide_widget (prompt, "details_area");
+
+ g_free (label);
+}
+
+static gboolean
+create_collection (GkdSecretCreate *self, const gchar *password)
+{
+ GError *error = NULL;
+ GP11Session *session;
+ GP11Object *collection;
+ GP11Object *cred;
+ gsize n_password;
+ gboolean token;
+
+ g_assert (GKD_SECRET_IS_CREATE (self));
+ g_return_val_if_fail (self->pkcs11_attrs, FALSE);
+ g_return_val_if_fail (!self->result_path, FALSE);
+
+ if (gp11_attributes_find_boolean (self->pkcs11_attrs, CKA_TOKEN, &token))
+ token = FALSE;
+ n_password = password ? strlen (password) : 0;
+
+ session = gkd_secret_prompt_get_pkcs11_session (GKD_SECRET_PROMPT (self));
+ g_return_val_if_fail (session, FALSE);
+
+ cred = gp11_session_create_object (session, &error,
+ CKA_CLASS, GP11_ULONG, CKO_G_CREDENTIAL,
+ CKA_GNOME_TRANSIENT, GP11_BOOLEAN, TRUE,
+ CKA_TOKEN, GP11_BOOLEAN, token,
+ CKA_VALUE, n_password, password,
+ GP11_INVALID);
+
+ if (!cred) {
+ g_warning ("couldn't create credential for new collection: %s", error->message);
+ g_clear_error (&error);
+ return FALSE;
+ }
+
+ /* Setup remainder of attributes on collection */
+ gp11_attributes_add_ulong (self->pkcs11_attrs, CKA_G_CREDENTIAL,
+ gp11_object_get_handle (cred));
+ g_object_unref (cred);
+
+ collection = gp11_session_create_object_full (session, self->pkcs11_attrs, NULL, &error);
+ if (!collection) {
+ g_warning ("couldn't create collection: %s", error->message);
+ g_clear_error (&error);
+ return FALSE;
+ }
+
+ gp11_object_set_session (collection, session);
+ self->result_path = gkd_secret_util_path_for_collection (collection);
+ g_object_unref (collection);
+
+ return TRUE;
+}
+
+/* -----------------------------------------------------------------------------
+ * OBJECT
+ */
+
+static void
+gkd_secret_create_prompt_ready (GkdSecretPrompt *base)
+{
+ GkdSecretCreate *self = GKD_SECRET_CREATE (base);
+ GkdPrompt *prompt = GKD_PROMPT (self);
+ gchar *password;
+
+ if (!gkd_prompt_has_response (prompt)) {
+ prepare_create_prompt (self);
+ return;
+ }
+
+ /* Already prompted, create collection */
+ g_return_if_fail (gkd_prompt_get_response (prompt) == GKD_RESPONSE_OK);
+ password = gkd_prompt_get_password (prompt, "password");
+
+ if (create_collection (self, password))
+ gkd_secret_prompt_complete (GKD_SECRET_PROMPT (self));
+ else
+ gkd_secret_prompt_dismiss (GKD_SECRET_PROMPT (self));
+
+ egg_secure_strfree (password);
+}
+
+static void
+gkd_secret_create_encode_result (GkdSecretPrompt *base, DBusMessageIter *iter)
+{
+ GkdSecretCreate *self = GKD_SECRET_CREATE (base);
+ DBusMessageIter variant;
+ const gchar *path;
+
+ dbus_message_iter_open_container (iter, DBUS_TYPE_VARIANT, "o", &variant);
+ path = self->result_path ? self->result_path : "/";
+ dbus_message_iter_append_basic (&variant, DBUS_TYPE_OBJECT_PATH, &path);
+ dbus_message_iter_close_container (iter, &variant);
+}
+
+static void
+gkd_secret_create_init (GkdSecretCreate *self)
+{
+
+}
+
+static void
+gkd_secret_create_finalize (GObject *obj)
+{
+ GkdSecretCreate *self = GKD_SECRET_CREATE (obj);
+
+ if (self->pkcs11_attrs)
+ gp11_attributes_unref (self->pkcs11_attrs);
+ self->pkcs11_attrs = NULL;
+
+ G_OBJECT_CLASS (gkd_secret_create_parent_class)->finalize (obj);
+}
+
+static void
+gkd_secret_create_set_property (GObject *obj, guint prop_id, const GValue *value,
+ GParamSpec *pspec)
+{
+ GkdSecretCreate *self = GKD_SECRET_CREATE (obj);
+
+ switch (prop_id) {
+ case PROP_PKCS11_ATTRIBUTES:
+ g_return_if_fail (!self->pkcs11_attrs);
+ self->pkcs11_attrs = g_value_dup_boxed (value);
+ gp11_attributes_add_ulong (self->pkcs11_attrs, CKA_CLASS, CKO_G_COLLECTION);
+ g_return_if_fail (self->pkcs11_attrs);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gkd_secret_create_get_property (GObject *obj, guint prop_id, GValue *value,
+ GParamSpec *pspec)
+{
+ GkdSecretCreate *self = GKD_SECRET_CREATE (obj);
+
+ switch (prop_id) {
+ case PROP_PKCS11_ATTRIBUTES:
+ g_value_set_boxed (value, self->pkcs11_attrs);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gkd_secret_create_class_init (GkdSecretCreateClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GkdSecretPromptClass *prompt_class = GKD_SECRET_PROMPT_CLASS (klass);
+
+ gobject_class->finalize = gkd_secret_create_finalize;
+ gobject_class->get_property = gkd_secret_create_get_property;
+ gobject_class->set_property = gkd_secret_create_set_property;
+
+ prompt_class->prompt_ready = gkd_secret_create_prompt_ready;
+ prompt_class->encode_result = gkd_secret_create_encode_result;
+
+ g_object_class_install_property (gobject_class, PROP_PKCS11_ATTRIBUTES,
+ g_param_spec_boxed ("pkcs11-attributes", "PKCS11 Attributes", "PKCS11 Attributes",
+ GP11_TYPE_ATTRIBUTES, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+}
+
+/* -----------------------------------------------------------------------------
+ * PUBLIC
+ */
+
+GkdSecretCreate*
+gkd_secret_create_new (GkdSecretService *service, const gchar *caller,
+ GP11Attributes *attrs)
+{
+ return g_object_new (GKD_SECRET_TYPE_CREATE,
+ "service", service,
+ "caller", caller,
+ "pkcs11-attributes", attrs,
+ NULL);
+}
diff --git a/daemon/dbus/gkd-secret-create.h b/daemon/dbus/gkd-secret-create.h
new file mode 100644
index 0000000..050deff
--- /dev/null
+++ b/daemon/dbus/gkd-secret-create.h
@@ -0,0 +1,51 @@
+/*
+ * 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_CREATE_H__
+#define __GKD_SECRET_CREATE_H__
+
+#include <glib-object.h>
+
+#include "gkd-secret-prompt.h"
+#include "gkd-secret-types.h"
+
+#include "gp11/gp11.h"
+
+#define GKD_SECRET_TYPE_CREATE (gkd_secret_create_get_type ())
+#define GKD_SECRET_CREATE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GKD_SECRET_TYPE_CREATE, GkdSecretCreate))
+#define GKD_SECRET_CREATE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GKD_SECRET_TYPE_CREATE, GkdSecretCreateClass))
+#define GKD_SECRET_IS_CREATE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GKD_SECRET_TYPE_CREATE))
+#define GKD_SECRET_IS_CREATE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GKD_SECRET_TYPE_CREATE))
+#define GKD_SECRET_CREATE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GKD_SECRET_TYPE_CREATE, GkdSecretCreateClass))
+
+typedef struct _GkdSecretCreateClass GkdSecretCreateClass;
+
+struct _GkdSecretCreateClass {
+ GkdSecretPromptClass parent_class;
+};
+
+GType gkd_secret_create_get_type (void);
+
+GkdSecretCreate* gkd_secret_create_new (GkdSecretService *service,
+ const gchar *caller,
+ GP11Attributes *attrs);
+
+#endif /* __GKD_SECRET_CREATE_H__ */
diff --git a/daemon/dbus/gkd-secret-prompt.c b/daemon/dbus/gkd-secret-prompt.c
index aab53af..2ad6c0e 100644
--- a/daemon/dbus/gkd-secret-prompt.c
+++ b/daemon/dbus/gkd-secret-prompt.c
@@ -358,6 +358,15 @@ gkd_secret_prompt_get_object_path (GkdSecretPrompt *self)
return self->pv->object_path;
}
+GP11Session*
+gkd_secret_prompt_get_pkcs11_session (GkdSecretPrompt *self)
+{
+ g_return_val_if_fail (GKD_SECRET_IS_PROMPT (self), NULL);
+ g_return_val_if_fail (self->pv->service, NULL);
+
+ return gkd_secret_service_get_pkcs11_session (self->pv->service, self->pv->caller);
+}
+
void
gkd_secret_prompt_complete (GkdSecretPrompt *self)
{
@@ -375,18 +384,3 @@ gkd_secret_prompt_dismiss (GkdSecretPrompt *self)
self->pv->completed = TRUE;
emit_completed (self, TRUE);
}
-
-GP11Object*
-gkd_secret_prompt_lookup_collection (GkdSecretPrompt *self, const gchar *path)
-{
- 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);
-
- session = gkd_secret_service_get_pkcs11_session (self->pv->service, self->pv->caller);
- g_return_val_if_fail (session, NULL);
-
- 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 de8c069..ded1ae4 100644
--- a/daemon/dbus/gkd-secret-prompt.h
+++ b/daemon/dbus/gkd-secret-prompt.h
@@ -66,9 +66,6 @@ const gchar* gkd_secret_prompt_get_object_path (GkdSecretPrompt *
GP11Session* gkd_secret_prompt_get_pkcs11_session (GkdSecretPrompt *self);
-GP11Object* gkd_secret_prompt_lookup_collection (GkdSecretPrompt *self,
- const gchar *objpath);
-
void gkd_secret_prompt_complete (GkdSecretPrompt *self);
void gkd_secret_prompt_dismiss (GkdSecretPrompt *self);
diff --git a/daemon/dbus/gkd-secret-service.c b/daemon/dbus/gkd-secret-service.c
index 8cd42a8..f1e81ce 100644
--- a/daemon/dbus/gkd-secret-service.c
+++ b/daemon/dbus/gkd-secret-service.c
@@ -22,8 +22,10 @@
#include "config.h"
#include "gkd-dbus-util.h"
+#include "gkd-secret-create.h"
#include "gkd-secret-objects.h"
#include "gkd-secret-prompt.h"
+#include "gkd-secret-property.h"
#include "gkd-secret-service.h"
#include "gkd-secret-session.h"
#include "gkd-secret-types.h"
@@ -370,6 +372,60 @@ service_method_open_session (GkdSecretService *self, DBusMessage *message)
}
static DBusMessage*
+service_method_create_collection (GkdSecretService *self, DBusMessage *message)
+{
+ DBusMessageIter iter, array;
+ GP11Attributes *attrs, *all;
+ GP11Attribute *label;
+ GkdSecretCreate *create;
+ ServiceClient *client;
+ DBusMessage *reply;
+ const gchar *path;
+ const char *caller;
+ const gchar *coll;
+
+ /* Parse the incoming message */
+ if (!dbus_message_has_signature (message, "a{sv}"))
+ return NULL;
+ if (!dbus_message_iter_init (message, &iter))
+ g_return_val_if_reached (NULL);
+ all = gp11_attributes_new ();
+ dbus_message_iter_recurse (&iter, &array);
+ if (!gkd_secret_property_parse_all (&array, all)) {
+ gp11_attributes_unref (all);
+ return dbus_message_new_error_printf (message, DBUS_ERROR_INVALID_ARGS,
+ "Invalid properties");
+ }
+
+ /* The only thing we actually use from the properties right now is the label */
+ label = gp11_attributes_find (all, CKA_LABEL);
+ attrs = gp11_attributes_new ();
+ if (label != NULL)
+ gp11_attributes_add (attrs, label);
+ gp11_attributes_add_boolean (attrs, CKA_TOKEN, TRUE);
+ gp11_attributes_unref (all);
+
+ /* Create the prompt object, for the password */
+ caller = dbus_message_get_sender (message);
+ create = gkd_secret_create_new (self, caller, attrs);
+ gp11_attributes_unref (attrs);
+
+ path = gkd_secret_prompt_get_object_path (GKD_SECRET_PROMPT (create));
+ client = g_hash_table_lookup (self->clients, caller);
+ g_return_val_if_fail (client, NULL);
+ g_hash_table_replace (client->prompts, (gpointer)path, create);
+
+ coll = "/";
+ reply = dbus_message_new_method_return (message);
+ dbus_message_append_args (reply,
+ DBUS_TYPE_OBJECT_PATH, &coll,
+ DBUS_TYPE_OBJECT_PATH, &path,
+ DBUS_TYPE_INVALID);
+
+ return reply;
+}
+
+static DBusMessage*
service_method_unlock (GkdSecretService *self, DBusMessage *message)
{
GkdSecretUnlock *unlock;
@@ -430,7 +486,7 @@ service_message_handler (GkdSecretService *self, DBusMessage *message)
/* org.freedesktop.Secrets.Service.CreateCollection() */
if (dbus_message_is_method_call (message, SECRET_SERVICE_INTERFACE, "CreateCollection"))
- g_return_val_if_reached (NULL); /* TODO: Need to implement */
+ reply = service_method_create_collection (self, message);
/* org.freedesktop.Secrets.Service.LockService() */
if (dbus_message_is_method_call (message, SECRET_SERVICE_INTERFACE, "LockService"))
diff --git a/daemon/dbus/gkd-secret-unlock.c b/daemon/dbus/gkd-secret-unlock.c
index c416587..b62285a 100644
--- a/daemon/dbus/gkd-secret-unlock.c
+++ b/daemon/dbus/gkd-secret-unlock.c
@@ -25,6 +25,7 @@
#include "gkd-secret-prompt.h"
#include "gkd-secret-types.h"
#include "gkd-secret-unlock.h"
+#include "gkd-secret-util.h"
#include "egg/egg-secure-memory.h"
@@ -168,6 +169,17 @@ authenticate_collection (GkdSecretUnlock *self, GP11Object *coll, gboolean *lock
}
}
+static GP11Object*
+lookup_collection (GkdSecretUnlock *self, const gchar *path)
+{
+ GP11Session *session;
+
+ session = gkd_secret_prompt_get_pkcs11_session (GKD_SECRET_PROMPT (self));
+ g_return_val_if_fail (session, NULL);
+
+ return gkd_secret_util_path_to_collection (session, path);
+}
+
/* -----------------------------------------------------------------------------
* OBJECT
*/
@@ -182,7 +194,7 @@ gkd_secret_unlock_prompt_ready (GkdSecretPrompt *base)
/* Already prompted for an item */
if (self->current) {
- coll = gkd_secret_prompt_lookup_collection (base, self->current);
+ coll = lookup_collection (self, self->current);
/* If the object or collection is gone, no need to unlock */
if (coll == NULL) {
@@ -221,7 +233,7 @@ gkd_secret_unlock_prompt_ready (GkdSecretPrompt *base)
}
/* Find the collection, make sure it's still around */
- coll = gkd_secret_prompt_lookup_collection (base, objpath);
+ coll = lookup_collection (self, objpath);
if (coll == NULL) {
g_free (objpath);
continue;
@@ -327,7 +339,7 @@ gkd_secret_unlock_queue (GkdSecretUnlock *self, const gchar *objpath)
g_return_if_fail (GKD_SECRET_IS_UNLOCK (self));
g_return_if_fail (objpath);
- coll = gkd_secret_prompt_lookup_collection (GKD_SECRET_PROMPT (self), objpath);
+ coll = lookup_collection (self, objpath);
if (coll == NULL)
return;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]