[gnome-keyring/dbus-api] [dbus] Do our own dispatch of dbus messages.
- From: Stefan Walter <stefw src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [gnome-keyring/dbus-api] [dbus] Do our own dispatch of dbus messages.
- Date: Sun, 23 Aug 2009 01:58:58 +0000 (UTC)
commit 3e8b8fc73a4c70a91159d92efe1a74d0a3f31051
Author: Stef Walter <stef memberwebs com>
Date: Sat Aug 22 19:34:13 2009 +0000
[dbus] Do our own dispatch of dbus messages.
Do our own dispatch of dbus messages, which allows us to:
a) Make sure we've identified the client, b) show certain
objects to certain clients.
daemon/dbus/gkd-secrets-objects.c | 98 ++++-----
daemon/dbus/gkd-secrets-objects.h | 4 +-
daemon/dbus/gkd-secrets-service.c | 416 +++++++++++++++++++++++--------------
daemon/dbus/gkd-secrets-service.h | 1 -
daemon/dbus/gkd-secrets-session.c | 116 +++++------
daemon/dbus/gkd-secrets-session.h | 4 +-
daemon/dbus/gkd-secrets-types.h | 2 +-
pkcs11/pkcs11i.h | 2 -
8 files changed, 356 insertions(+), 287 deletions(-)
---
diff --git a/daemon/dbus/gkd-secrets-objects.c b/daemon/dbus/gkd-secrets-objects.c
index 5e6259a..5a3cb3e 100644
--- a/daemon/dbus/gkd-secrets-objects.c
+++ b/daemon/dbus/gkd-secrets-objects.c
@@ -93,53 +93,6 @@ gkd_sercets_objects_property_handler (DBusConnection *conn, DBusMessage *message
}
#endif
-static DBusHandlerResult
-gkd_secrets_objects_message_handler (DBusConnection *conn, DBusMessage *message, gpointer user_data)
-{
- GkdSecretsObjects *self = user_data;
- DBusMessage *reply = NULL;
-
- g_return_val_if_fail (conn && message, DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
- g_return_val_if_fail (GKD_SECRETS_IS_OBJECTS (self), DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
-
-#if 0
- /* Check if it's properties, and hand off to property handler. */
- if (dbus_message_has_interface (message, PROPERTIES_INTERFACE))
- return gkd_sercets_objects_property_handler (conn, message, self);
-
- /* org.freedesktop.Secrets.Objects.Close() */
- else if (dbus_message_is_method_call (message, SECRETS_SERVICE_INTERFACE, "Close"))
- return gkd_secrets_objects_close (self, conn, message);
-
- /* org.freedesktop.Secrets.Objects.Negotiate() */
- else if (dbus_message_is_method_call (message, SECRETS_SERVICE_INTERFACE, "Negotiate"))
- g_return_val_if_reached (DBUS_HANDLER_RESULT_NOT_YET_HANDLED); /* TODO: Need to implement */
-
- /* org.freedesktop.Secrets.Objects.GetSecret() */
- else if (dbus_message_is_method_call (message, SECRETS_SERVICE_INTERFACE, "GetSecret"))
- g_return_val_if_reached (DBUS_HANDLER_RESULT_NOT_YET_HANDLED); /* TODO: Need to implement */
-
- /* org.freedesktop.Secrets.Objects.SetSecret() */
- else if (dbus_message_is_method_call (message, SECRETS_SERVICE_INTERFACE, "SetSecret"))
- g_return_val_if_reached (DBUS_HANDLER_RESULT_NOT_YET_HANDLED); /* TODO: Need to implement */
-
- /* org.freedesktop.Secrets.Objects.GetSecrets() */
- else if (dbus_message_is_method_call (message, SECRETS_SERVICE_INTERFACE, "GetSecrets"))
- g_return_val_if_reached (DBUS_HANDLER_RESULT_NOT_YET_HANDLED); /* TODO: Need to implement */
-
- /* org.freedesktop.Secrets.Objects.GetSecret() */
- else if (dbus_message_is_method_call (message, SECRETS_SERVICE_INTERFACE, "GetSecret"))
- g_return_val_if_reached (DBUS_HANDLER_RESULT_NOT_YET_HANDLED); /* TODO: Need to implement */
-#endif
-
- if (reply == NULL)
- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-
- dbus_connection_send (conn, reply, NULL);
- dbus_message_unref (reply);
- return DBUS_HANDLER_RESULT_HANDLED;
-}
-
/* -----------------------------------------------------------------------------
* OBJECT
*/
@@ -153,11 +106,6 @@ gkd_secrets_objects_constructor (GType type, guint n_props, GObjectConstructPara
g_return_val_if_fail (self->pkcs11_slot, NULL);
g_return_val_if_fail (self->service, NULL);
- /* Register all the collections, and items paths */
- if (!dbus_connection_register_fallback (gkd_secrets_service_get_connection (self->service), SECRETS_COLLECTION_PREFIX,
- &GKD_SECRETS_OBJECTS_GET_CLASS (self)->dbus_vtable, self))
- g_return_val_if_reached (NULL);
-
return G_OBJECT (self);
}
@@ -178,9 +126,6 @@ gkd_secrets_objects_dispose (GObject *obj)
}
if (self->service) {
- if (!dbus_connection_unregister_object_path (gkd_secrets_service_get_connection (self->service),
- SECRETS_COLLECTION_PREFIX))
- g_return_if_reached ();
g_object_remove_weak_pointer (G_OBJECT (self->service),
(gpointer*)&(self->service));
self->service = NULL;
@@ -255,8 +200,6 @@ gkd_secrets_objects_class_init (GkdSecretsObjectsClass *klass)
gobject_class->set_property = gkd_secrets_objects_set_property;
gobject_class->get_property = gkd_secrets_objects_get_property;
- klass->dbus_vtable.message_function = gkd_secrets_objects_message_handler;
-
g_object_class_install_property (gobject_class, PROP_PKCS11_SLOT,
g_param_spec_object ("pkcs11-slot", "Pkcs11 Slot", "PKCS#11 slot that we use for secrets",
GP11_TYPE_SLOT, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
@@ -276,3 +219,44 @@ gkd_secrets_objects_get_pkcs11_slot (GkdSecretsObjects *self)
g_return_val_if_fail (GKD_SECRETS_IS_OBJECTS (self), NULL);
return self->pkcs11_slot;
}
+
+DBusMessage*
+gkd_secrets_objects_dispatch (GkdSecretsObjects *self, DBusMessage *message)
+{
+ DBusMessage *reply = NULL;
+
+ g_return_val_if_fail (GKD_SECRETS_IS_OBJECTS (self), NULL);
+ g_return_val_if_fail (message, NULL);
+
+#if 0
+ /* Check if it's properties, and hand off to property handler. */
+ if (dbus_message_has_interface (message, PROPERTIES_INTERFACE))
+ return gkd_sercets_objects_property_handler (conn, message, self);
+
+ /* org.freedesktop.Secrets.Objects.Close() */
+ else if (dbus_message_is_method_call (message, SECRETS_SERVICE_INTERFACE, "Close"))
+ return gkd_secrets_objects_close (self, conn, message);
+
+ /* org.freedesktop.Secrets.Objects.Negotiate() */
+ else if (dbus_message_is_method_call (message, SECRETS_SERVICE_INTERFACE, "Negotiate"))
+ g_return_val_if_reached (DBUS_HANDLER_RESULT_NOT_YET_HANDLED); /* TODO: Need to implement */
+
+ /* org.freedesktop.Secrets.Objects.GetSecret() */
+ else if (dbus_message_is_method_call (message, SECRETS_SERVICE_INTERFACE, "GetSecret"))
+ g_return_val_if_reached (DBUS_HANDLER_RESULT_NOT_YET_HANDLED); /* TODO: Need to implement */
+
+ /* org.freedesktop.Secrets.Objects.SetSecret() */
+ else if (dbus_message_is_method_call (message, SECRETS_SERVICE_INTERFACE, "SetSecret"))
+ g_return_val_if_reached (DBUS_HANDLER_RESULT_NOT_YET_HANDLED); /* TODO: Need to implement */
+
+ /* org.freedesktop.Secrets.Objects.GetSecrets() */
+ else if (dbus_message_is_method_call (message, SECRETS_SERVICE_INTERFACE, "GetSecrets"))
+ g_return_val_if_reached (DBUS_HANDLER_RESULT_NOT_YET_HANDLED); /* TODO: Need to implement */
+
+ /* org.freedesktop.Secrets.Objects.GetSecret() */
+ else if (dbus_message_is_method_call (message, SECRETS_SERVICE_INTERFACE, "GetSecret"))
+ g_return_val_if_reached (DBUS_HANDLER_RESULT_NOT_YET_HANDLED); /* TODO: Need to implement */
+#endif
+
+ return reply;
+}
diff --git a/daemon/dbus/gkd-secrets-objects.h b/daemon/dbus/gkd-secrets-objects.h
index 1a179d3..6bef63a 100644
--- a/daemon/dbus/gkd-secrets-objects.h
+++ b/daemon/dbus/gkd-secrets-objects.h
@@ -39,11 +39,13 @@ typedef struct _GkdSecretsObjectsClass GkdSecretsObjectsClass;
struct _GkdSecretsObjectsClass {
GObjectClass parent_class;
- DBusObjectPathVTable dbus_vtable;
};
GType gkd_secrets_objects_get_type (void);
+DBusMessage* gkd_secrets_objects_dispatch (GkdSecretsObjects *self,
+ DBusMessage *message);
+
GP11Slot* gkd_secrets_objects_get_pkcs11_slot (GkdSecretsObjects *self);
#endif /* __GKD_SECRETS_OBJECTS_H__ */
diff --git a/daemon/dbus/gkd-secrets-service.c b/daemon/dbus/gkd-secrets-service.c
index d1f0283..6b06a54 100644
--- a/daemon/dbus/gkd-secrets-service.c
+++ b/daemon/dbus/gkd-secrets-service.c
@@ -31,6 +31,10 @@
#include "gp11/gp11.h"
+#include "pkcs11/pkcs11i.h"
+
+#include <string.h>
+
enum {
PROP_0,
PROP_CONNECTION,
@@ -45,7 +49,7 @@ enum {
struct _GkdSecretsService {
GObject parent;
DBusConnection *connection;
- GHashTable *sessions;
+ GHashTable *clients;
gchar *match_rule;
GkdSecretsObjects *objects;
#if 0
@@ -57,6 +61,18 @@ struct _GkdSecretsService {
#define LOC_DEFAULT_FILE (gkd_location_from_string ("LOCAL:/keyrings/default"))
#endif
+typedef struct _ServiceClient {
+ gchar *caller_peer;
+ gchar *caller_exec;
+ pid_t caller_pid;
+ CK_G_APPLICATION app;
+ GP11Session *pkcs11_session;
+ GList *sessions;
+} ServiceClient;
+
+/* Forward declaration */
+static void service_dispatch_message (GkdSecretsService *, DBusMessage *);
+
G_DEFINE_TYPE (GkdSecretsService, gkd_secrets_service, G_TYPE_OBJECT);
/* -----------------------------------------------------------------------------
@@ -81,64 +97,56 @@ update_default (GkdSecretsService *self)
}
#endif
-static void
-dispose_session (GkdSecretsSession *session)
-{
- g_object_run_dispose (G_OBJECT (session));
- g_object_unref (session);
-}
-
-static void
-take_session (GkdSecretsService *self, GkdSecretsSession *session)
+static gboolean
+object_path_has_prefix (const gchar *path, const gchar *prefix)
{
- GPtrArray *sessions;
- const gchar *caller;
+ gsize len;
- g_assert (GKD_SECRETS_SERVICE (self));
- g_assert (GKD_SECRETS_SESSION (session));
+ g_assert (prefix);
- caller = gkd_secrets_session_get_caller (session);
- sessions = g_hash_table_lookup (self->sessions, caller);
- if (!sessions) {
- sessions = g_ptr_array_new ();
- g_hash_table_replace (self->sessions, g_strdup (caller), sessions);
- }
+ if (!path)
+ return FALSE;
- g_ptr_array_add (sessions, session);
+ len = strlen (prefix);
+ return g_ascii_strncasecmp (path, prefix, len) == 0 &&
+ (path[len] == '\0' || path[len] == '/');
}
static void
-remove_session (GkdSecretsService *self, GkdSecretsSession *session)
+dispose_session (GkdSecretsSession *session)
{
- GPtrArray *sessions;
- const gchar *caller;
+ g_object_run_dispose (G_OBJECT (session));
+ g_object_unref (session);
+}
- g_assert (GKD_SECRETS_SERVICE (self));
- g_assert (GKD_SECRETS_SESSION (session));
+static void
+free_client (gpointer data)
+{
+ ServiceClient *client = data;
+ GList *l;
- caller = gkd_secrets_session_get_caller (session);
- sessions = g_hash_table_lookup (self->sessions, caller);
- g_return_if_fail (sessions);
+ if (!client)
+ return;
- g_ptr_array_remove_fast (sessions, session);
- if (sessions->len == 0)
- g_hash_table_remove (self->sessions, caller);
+ /* Info about our client */
+ g_free (client->caller_peer);
+ g_free (client->caller_exec);
- dispose_session (session);
-}
+ /* The session we use for accessing as our client */
+ if (client->pkcs11_session) {
+#if 0
+ gp11_session_close (client->pkcs11_session, NULL);
+#endif
+ g_object_unref (client->pkcs11_session);
+ }
-static void
-free_sessions (gpointer data)
-{
- GPtrArray *sessions = data;
- guint i;
+ /* The secrets API sessions client has open */
+ for (l = client->sessions; l; l = g_list_next (l))
+ dispose_session (l->data);
- for (i = 0; i < sessions->len; ++i)
- dispose_session (g_ptr_array_index (sessions, i));
- g_ptr_array_free (sessions, TRUE);
+ g_free (client);
}
-
typedef struct _on_get_connection_unix_process_id_args {
GkdSecretsService *self;
DBusMessage *message;
@@ -161,89 +169,76 @@ on_get_connection_unix_process_id (DBusPendingCall *pending, gpointer user_data)
on_get_connection_unix_process_id_args *args = user_data;
DBusMessage *reply = NULL;
DBusError error = DBUS_ERROR_INIT;
- gchar *caller_exec = NULL;
dbus_uint32_t caller_pid = 0;
- GkdSecretsSession *session;
GkdSecretsService *self;
+ ServiceClient *client;
const gchar *caller;
- const gchar *path;
g_return_if_fail (GKD_SECRETS_IS_SERVICE (args->self));
self = args->self;
- caller = dbus_message_get_sender (args->message);
- g_return_if_fail (caller);
-
/* Get the resulting process ID */
reply = dbus_pending_call_steal_reply (pending);
g_return_if_fail (reply);
- /* An error returned from GetConnectionUnixProcessID */
- if (dbus_set_error_from_message (&error, reply)) {
- g_message ("couldn't get the caller's unix process id: %s", error.message);
- caller_pid = 0;
- dbus_error_free (&error);
+ caller = dbus_message_get_sender (args->message);
+ g_return_if_fail (caller);
- /* A PID was returned from GetConnectionUnixProcessID */
- } else {
- if (!dbus_message_get_args (reply, NULL, DBUS_TYPE_UINT32, &caller_pid, DBUS_TYPE_INVALID))
- g_return_if_reached ();
- }
+ client = g_hash_table_lookup (self->clients, caller);
+ if (client == NULL) {
- dbus_message_unref (reply);
+ /* An error returned from GetConnectionUnixProcessID */
+ if (dbus_set_error_from_message (&error, reply)) {
+ g_message ("couldn't get the caller's unix process id: %s", error.message);
+ caller_pid = 0;
+ dbus_error_free (&error);
- /* Dig out the process executable if possible */
- if (caller_pid != 0)
- caller_exec = egg_unix_credentials_executable (caller_pid);
+ /* A PID was returned from GetConnectionUnixProcessID */
+ } else {
+ if (!dbus_message_get_args (reply, NULL, DBUS_TYPE_UINT32, &caller_pid, DBUS_TYPE_INVALID))
+ g_return_if_reached ();
+ }
- /* Now we can create a session with this information */
- session = g_object_new (GKD_SECRETS_TYPE_SESSION,
- "caller-executable", caller_exec,
- "caller", caller,
- "service", self,
- NULL);
- g_free (caller_exec);
+ /* Initialize the client object */
+ client = g_new0 (ServiceClient, 1);
+ client->caller_peer = g_strdup (caller);
+ client->caller_pid = caller_pid;
+ if (caller_pid != 0)
+ client->caller_exec = egg_unix_credentials_executable (caller_pid);
+ client->app.applicationData = client;
- /* Take ownership of the session */
- take_session (self, session);
+ g_hash_table_replace (self->clients, client->caller_peer, client);
+ }
- path = gkd_secrets_session_get_object_path (session);
- reply = dbus_message_new_method_return (args->message);
- dbus_message_append_args (reply, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID);
- dbus_connection_send (args->self->connection, reply, NULL);
dbus_message_unref (reply);
-}
-/* -----------------------------------------------------------------------------
- * DBUS
- */
+ /* Dispatch the original message again */
+ service_dispatch_message (self, args->message);
+}
-static DBusHandlerResult
-service_begin_open_session (GkdSecretsService *self, DBusConnection *conn, DBusMessage *message)
+static void
+initialize_service_client (GkdSecretsService *self, DBusMessage *message)
{
on_get_connection_unix_process_id_args *args;
- DBusMessage *request, *reply;
+ DBusMessage *request;
DBusPendingCall *pending;
const gchar *caller;
g_assert (GKD_SECRETS_IS_SERVICE (self));
- g_assert (conn && message);
+ g_assert (message);
+
+ args = g_new0 (on_get_connection_unix_process_id_args, 1);
+ args->self = g_object_ref (self);
+ args->message = dbus_message_ref (message);
- /* Who is the caller of this message? */
caller = dbus_message_get_sender (message);
- if (caller == NULL) {
- reply = dbus_message_new_error (message, DBUS_ERROR_FAILED,
- "Could not not identify calling client application");
- dbus_connection_send (conn, reply, NULL);
- dbus_message_unref (reply);
- return DBUS_HANDLER_RESULT_HANDLED;
- }
+ g_return_if_fail (caller);
/* Message org.freedesktop.DBus.GetConnectionUnixProcessID(IN String caller) */
request = dbus_message_new_method_call ("org.freedesktop.DBus", "/org/freedesktop/DBus",
"org.freedesktop.DBus", "GetConnectionUnixProcessID");
if (!request || !dbus_message_append_args (request, DBUS_TYPE_STRING, &caller, DBUS_TYPE_INVALID))
- g_return_val_if_reached (DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
+ g_return_if_reached ();
/*
* Send of request for GetConnectionUnixProcessID, with lowish timeout.
@@ -251,22 +246,21 @@ service_begin_open_session (GkdSecretsService *self, DBusConnection *conn, DBusM
* In addition we want to send off a reply to our caller, before it
* times out.
*/
- if (!dbus_connection_send_with_reply (conn, request, &pending, 2000))
- g_return_val_if_reached (DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
+ if (!dbus_connection_send_with_reply (self->connection, request, &pending, 2000))
+ g_return_if_reached ();
dbus_message_unref (request);
- args = g_new0 (on_get_connection_unix_process_id_args, 1);
- args->self = g_object_ref (self);
- args->message = dbus_message_ref (message);
-
/* Track our new session object, on this call */
dbus_pending_call_set_notify (pending, on_get_connection_unix_process_id, args,
free_on_get_connection_unix_process_id_args);
dbus_pending_call_unref (pending);
-
- return DBUS_HANDLER_RESULT_HANDLED;
}
+
+/* -----------------------------------------------------------------------------
+ * DBUS
+ */
+
static DBusMessage*
service_property_handler (GkdSecretsService *self, DBusMessage *message)
{
@@ -290,45 +284,118 @@ service_property_handler (GkdSecretsService *self, DBusMessage *message)
#endif
}
-static DBusHandlerResult
-gkd_secrets_service_message_handler (DBusConnection *conn, DBusMessage *message, gpointer user_data)
+static DBusMessage*
+service_method_open_session (GkdSecretsService *self, DBusMessage *message)
+{
+ GkdSecretsSession *session;
+ ServiceClient *client;
+ DBusMessage *reply;
+ const gchar *caller;
+ const gchar *path;
+
+ if (!dbus_message_get_args (message, NULL, DBUS_TYPE_INVALID))
+ return NULL;
+
+ caller = dbus_message_get_sender (message);
+
+ /* Now we can create a session with this information */
+ session = g_object_new (GKD_SECRETS_TYPE_SESSION,
+ "caller", caller,
+ "service", self,
+ NULL);
+
+ /* Take ownership of the session */
+ client = g_hash_table_lookup (self->clients, caller);
+ g_return_val_if_fail (client, NULL);
+ client->sessions = g_list_prepend (client->sessions, session);
+
+ /* Return the response */
+ path = gkd_secrets_session_get_object_path (session);
+ reply = dbus_message_new_method_return (message);
+ dbus_message_append_args (reply, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID);
+ return reply;
+}
+
+static DBusMessage*
+service_method_handler (GkdSecretsService *self, DBusMessage *message)
{
- GkdSecretsService *self = user_data;
DBusMessage *reply = NULL;
- g_return_val_if_fail (conn && message, DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
- g_return_val_if_fail (GKD_SECRETS_IS_SERVICE (self), DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
+ g_return_val_if_fail (message, NULL);
+ g_return_val_if_fail (GKD_SECRETS_IS_SERVICE (self), NULL);
+
+ if (dbus_message_is_method_call (message, SECRETS_SERVICE_INTERFACE, "OpenSession"))
+ reply = service_method_open_session (self, message);
+
+ return reply;
+}
+
+static void
+service_dispatch_message (GkdSecretsService *self, DBusMessage *message)
+{
+ DBusMessage *reply = NULL;
+ const gchar *caller;
+ ServiceClient *client;
+ const gchar *path;
+ GList *l;
+
+ g_assert (GKD_SECRETS_IS_SERVICE (self));
+ g_assert (message);
+
+ /* The first thing we do is try to allocate a client context */
+ caller = dbus_message_get_sender (message);
+ if (caller == NULL) {
+ reply = dbus_message_new_error (message, DBUS_ERROR_FAILED,
+ "Could not not identify calling client application");
+ dbus_connection_send (self->connection, reply, NULL);
+ dbus_message_unref (reply);
+ return;
+ }
- /* Check if it's properties, and hand off to property handler. */
- if (dbus_message_has_interface (message, PROPERTIES_INTERFACE))
- reply = service_property_handler (self, message);
+ client = g_hash_table_lookup (self->clients, caller);
+ if (client == NULL) {
+ initialize_service_client (self, message);
+ return; /* This function called again, when client is initialized */
+ }
- /* org.freedesktop.Secrets.Service.OpenSession() */
- else if (dbus_message_is_method_call (message, SECRETS_SERVICE_INTERFACE, "OpenSession"))
- return service_begin_open_session (self, conn, message);
+ path = dbus_message_get_path (message);
+ g_return_if_fail (path);
- /* org.freedesktop.Secrets.Service.CreateCollection() */
- else if (dbus_message_is_method_call (message, SECRETS_SERVICE_INTERFACE, "CreateCollection"))
- g_return_val_if_reached (DBUS_HANDLER_RESULT_NOT_YET_HANDLED); /* TODO: Need to implement */
+ /* Dispatched to a session, find a session in this client */
+ if (object_path_has_prefix (path, SECRETS_SESSION_PREFIX)) {
+ for (l = client->sessions; l; l = g_list_next (l)) {
+ if (g_str_equal (path, gkd_secrets_session_get_object_path (l->data))) {
+ reply = gkd_secrets_session_dispatch (l->data, message);
+ break;
+ }
+ }
- /* org.freedesktop.Secrets.Service.LockService() */
- else if (dbus_message_is_method_call (message, SECRETS_SERVICE_INTERFACE, "CreateCollection"))
- g_return_val_if_reached (DBUS_HANDLER_RESULT_NOT_YET_HANDLED); /* TODO: Need to implement */
+ /* Dispatched to a collection, off it goes */
+ } else if (object_path_has_prefix (path, SECRETS_COLLECTION_PREFIX)) {
+ reply = gkd_secrets_objects_dispatch (self->objects, message);
- /* org.freedesktop.Secrets.Service.SearchItems() */
- else if (dbus_message_is_method_call (message, SECRETS_SERVICE_INTERFACE, "SearchItems"))
- g_return_val_if_reached (DBUS_HANDLER_RESULT_NOT_YET_HANDLED); /* TODO: Need to implement */
+ } else if (g_str_equal (path, SECRETS_SERVICE_PATH)) {
- /* org.freedesktop.Secrets.Service.RetrieveSecrets() */
- else if (dbus_message_is_method_call (message, SECRETS_SERVICE_INTERFACE, "RetrieveSecrets"))
- g_return_val_if_reached (DBUS_HANDLER_RESULT_NOT_YET_HANDLED); /* TODO: Need to implement */
+ /* Check if it's properties, and hand off to property handler. */
+ if (dbus_message_has_interface (message, PROPERTIES_INTERFACE))
+ reply = service_property_handler (self, message);
+ else
+ reply = service_method_handler (self, message);
+ }
- if (reply == NULL)
- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ /* Should we send an error? */
+ if (!reply && dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_CALL) {
+ reply = dbus_message_new_error_printf (message, DBUS_ERROR_UNKNOWN_METHOD,
+ "Method \"%s\" with signature \"%s\" on interface \"%s\" doesn't exist\n",
+ dbus_message_get_member (message),
+ dbus_message_get_signature (message),
+ dbus_message_get_interface (message));
+ }
- dbus_connection_send (conn, reply, NULL);
- dbus_message_unref (reply);
- return DBUS_HANDLER_RESULT_HANDLED;
+ if (reply) {
+ dbus_connection_send (self->connection, reply, NULL);
+ dbus_message_unref (reply);
+ }
}
static DBusHandlerResult
@@ -338,25 +405,62 @@ gkd_secrets_service_filter_handler (DBusConnection *conn, DBusMessage *message,
const gchar *object_name;
const gchar *old_owner;
const gchar *new_owner;
+ const gchar *path;
+ const gchar *interface;
g_return_val_if_fail (conn && message, DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
g_return_val_if_fail (GKD_SECRETS_IS_SERVICE (self), DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
/* org.freedesktop.DBus.NameOwnerChanged(STRING name, STRING old_owner, STRING new_owner) */
- if (!dbus_message_is_signal (message, BUS_INTERFACE, "NameOwnerChanged") ||
- !dbus_message_get_args (message, NULL, DBUS_TYPE_STRING, &object_name,
- DBUS_TYPE_STRING, &old_owner, DBUS_TYPE_STRING, &new_owner,
- DBUS_TYPE_INVALID))
+ if (dbus_message_is_signal (message, BUS_INTERFACE, "NameOwnerChanged") &&
+ dbus_message_get_args (message, NULL, DBUS_TYPE_STRING, &object_name,
+ DBUS_TYPE_STRING, &old_owner, DBUS_TYPE_STRING, &new_owner,
+ DBUS_TYPE_INVALID)) {
+
+ /*
+ * A peer is connecting or disconnecting from the bus,
+ * remove any client info, when client gone.
+ */
+
+ g_return_val_if_fail (object_name && new_owner, DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
+ if (g_str_equal (new_owner, "") && object_name[0] == ':')
+ g_hash_table_remove (self->clients, object_name);
+
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ }
+
+ /*
+ * If the path is a within our object tree, then we do our own dispatch.
+ */
+ path = dbus_message_get_path (message);
+ switch (dbus_message_get_type (message)) {
+
+ /* Dispatch any method call on our interfaces, for our objects */
+ case DBUS_MESSAGE_TYPE_METHOD_CALL:
+ if (object_path_has_prefix (path, SECRETS_SERVICE_PATH)) {
+ interface = dbus_message_get_interface (message);
+ if (interface == NULL ||
+ g_str_has_prefix (interface, SECRETS_INTERFACE_PREFIX) ||
+ g_str_equal (interface, DBUS_INTERFACE_PROPERTIES)) {
+ service_dispatch_message (self, message);
+ return DBUS_HANDLER_RESULT_HANDLED;
+ }
+ }
+ break;
- g_return_val_if_fail (object_name && new_owner, DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
+ /* Dispatch any signal for one of our objects */
+ case DBUS_MESSAGE_TYPE_SIGNAL:
+ if (object_path_has_prefix (path, SECRETS_SERVICE_PATH)) {
+ service_dispatch_message (self, message);
+ return DBUS_HANDLER_RESULT_HANDLED;
+ }
+ break;
- /* See if it's something that owns our sessions, close if so */
- if (g_str_equal (new_owner, "") && object_name[0] == ':')
- g_hash_table_remove (self->sessions, object_name);
+ default:
+ break;
+ }
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-
}
/* -----------------------------------------------------------------------------
@@ -374,11 +478,6 @@ gkd_secrets_service_constructor (GType type, guint n_props, GObjectConstructPara
g_return_val_if_fail (self, NULL);
g_return_val_if_fail (self->connection, NULL);
- /* Now register the object */
- if (!dbus_connection_register_object_path (self->connection, SECRETS_SERVICE_PATH,
- &GKD_SECRETS_SERVICE_GET_CLASS (self)->dbus_vtable, self))
- g_return_val_if_reached (NULL);
-
/* Find the pkcs11-slot parameter */
for (i = 0; !slot && i < n_props; ++i) {
if (g_str_equal (props[i].pspec->name, "pkcs11-slot"))
@@ -399,17 +498,18 @@ gkd_secrets_service_constructor (GType type, guint n_props, GObjectConstructPara
dbus_error_free (&error);
g_free (self->match_rule);
self->match_rule = NULL;
- } else {
- dbus_connection_add_filter (self->connection, gkd_secrets_service_filter_handler, self, NULL);
}
+ if (!dbus_connection_add_filter (self->connection, gkd_secrets_service_filter_handler, self, NULL))
+ g_return_val_if_reached (NULL);
+
return G_OBJECT (self);
}
static void
gkd_secrets_service_init (GkdSecretsService *self)
{
- self->sessions = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, free_sessions);
+ self->clients = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, free_client);
}
static void
@@ -419,14 +519,13 @@ gkd_secrets_service_dispose (GObject *obj)
if (self->match_rule) {
g_return_if_fail (self->connection);
- dbus_connection_remove_filter (self->connection, gkd_secrets_service_filter_handler, self);
dbus_bus_remove_match (self->connection, self->match_rule, NULL);
g_free (self->match_rule);
self->match_rule = NULL;
}
/* Closes all the sessions */
- g_hash_table_remove_all (self->sessions);
+ g_hash_table_remove_all (self->clients);
/* Hide all the objects */
if (self->objects) {
@@ -436,8 +535,7 @@ gkd_secrets_service_dispose (GObject *obj)
}
if (self->connection) {
- if (!dbus_connection_unregister_object_path (self->connection, SECRETS_SERVICE_PATH))
- g_return_if_reached ();
+ dbus_connection_remove_filter (self->connection, gkd_secrets_service_filter_handler, self);
dbus_connection_unref (self->connection);
self->connection = NULL;
}
@@ -450,9 +548,9 @@ gkd_secrets_service_finalize (GObject *obj)
{
GkdSecretsService *self = GKD_SECRETS_SERVICE (obj);
- g_assert (g_hash_table_size (self->sessions) == 0);
- g_hash_table_destroy (self->sessions);
- self->sessions = NULL;
+ g_assert (g_hash_table_size (self->clients) == 0);
+ g_hash_table_destroy (self->clients);
+ self->clients = NULL;
#if 0
g_free (self->pv->default_collection);
@@ -513,8 +611,6 @@ gkd_secrets_service_class_init (GkdSecretsServiceClass *klass)
gobject_class->set_property = gkd_secrets_service_set_property;
gobject_class->get_property = gkd_secrets_service_get_property;
- klass->dbus_vtable.message_function = gkd_secrets_service_message_handler;
-
g_object_class_install_property (gobject_class, PROP_CONNECTION,
g_param_spec_boxed ("connection", "Connection", "DBus Connection",
GKD_DBUS_TYPE_CONNECTION, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
@@ -545,10 +641,18 @@ gkd_secrets_service_get_pkcs11_slot (GkdSecretsService *self)
void
gkd_secrets_service_close_session (GkdSecretsService *self, GkdSecretsSession *session)
{
+ ServiceClient *client;
+ const gchar *caller;
+
g_return_if_fail (GKD_SECRETS_IS_SERVICE (self));
g_return_if_fail (GKD_SECRETS_IS_SESSION (session));
- remove_session (self, session);
+ caller = gkd_secrets_session_get_caller (session);
+ client = g_hash_table_lookup (self->clients, caller);
+ g_return_if_fail (client);
+
+ client->sessions = g_list_remove (client->sessions, session);
+ dispose_session (session);
}
#if 0
diff --git a/daemon/dbus/gkd-secrets-service.h b/daemon/dbus/gkd-secrets-service.h
index 83c182d..27fc76c 100644
--- a/daemon/dbus/gkd-secrets-service.h
+++ b/daemon/dbus/gkd-secrets-service.h
@@ -41,7 +41,6 @@ typedef struct _GkdSecretsServiceClass GkdSecretsServiceClass;
struct _GkdSecretsServiceClass {
GObjectClass parent_class;
- DBusObjectPathVTable dbus_vtable;
#if 0
/* signals --------------------------------------------------------- */
diff --git a/daemon/dbus/gkd-secrets-session.c b/daemon/dbus/gkd-secrets-session.c
index 63c1cc3..af02216 100644
--- a/daemon/dbus/gkd-secrets-session.c
+++ b/daemon/dbus/gkd-secrets-session.c
@@ -41,7 +41,6 @@ struct _GkdSecretsSession {
GkdSecretsService *service;
gchar *caller_exec;
gchar *caller;
- gboolean registered;
};
G_DEFINE_TYPE (GkdSecretsSession, gkd_secrets_session, G_TYPE_OBJECT);
@@ -96,58 +95,6 @@ session_property_handler (GkdSecretsSession *self, DBusMessage *message)
#endif
}
-static DBusHandlerResult
-gkd_secrets_session_message_handler (DBusConnection *conn, DBusMessage *message, gpointer user_data)
-{
- GkdSecretsSession *self = user_data;
- DBusMessage *reply = NULL;
- const gchar *caller;
-
- g_return_val_if_fail (conn && message, DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
- g_return_val_if_fail (GKD_SECRETS_IS_SESSION (self), DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
-
- /* Who is the caller of this message? */
- caller = dbus_message_get_sender (message);
- if (!caller || !g_str_equal (caller, self->caller)) {
- reply = dbus_message_new_error (message, DBUS_ERROR_ACCESS_DENIED,
- "This session does not belong to your application");
-
- /* Check if it's properties, and hand off to property handler. */
- } else if (dbus_message_has_interface (message, PROPERTIES_INTERFACE))
- reply = session_property_handler (self, message);
-
- /* org.freedesktop.Secrets.Session.Close() */
- else if (dbus_message_is_method_call (message, SECRETS_SERVICE_INTERFACE, "Close"))
- reply = session_method_close (self, message);
-
- /* org.freedesktop.Secrets.Session.Negotiate() */
- else if (dbus_message_is_method_call (message, SECRETS_SERVICE_INTERFACE, "Negotiate"))
- g_return_val_if_reached (DBUS_HANDLER_RESULT_NOT_YET_HANDLED); /* TODO: Need to implement */
-
- /* org.freedesktop.Secrets.Session.GetSecret() */
- else if (dbus_message_is_method_call (message, SECRETS_SERVICE_INTERFACE, "GetSecret"))
- g_return_val_if_reached (DBUS_HANDLER_RESULT_NOT_YET_HANDLED); /* TODO: Need to implement */
-
- /* org.freedesktop.Secrets.Session.SetSecret() */
- else if (dbus_message_is_method_call (message, SECRETS_SERVICE_INTERFACE, "SetSecret"))
- g_return_val_if_reached (DBUS_HANDLER_RESULT_NOT_YET_HANDLED); /* TODO: Need to implement */
-
- /* org.freedesktop.Secrets.Session.GetSecrets() */
- else if (dbus_message_is_method_call (message, SECRETS_SERVICE_INTERFACE, "GetSecrets"))
- g_return_val_if_reached (DBUS_HANDLER_RESULT_NOT_YET_HANDLED); /* TODO: Need to implement */
-
- /* org.freedesktop.Secrets.Session.GetSecret() */
- else if (dbus_message_is_method_call (message, SECRETS_SERVICE_INTERFACE, "GetSecret"))
- g_return_val_if_reached (DBUS_HANDLER_RESULT_NOT_YET_HANDLED); /* TODO: Need to implement */
-
- if (reply == NULL)
- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-
- dbus_connection_send (conn, reply, NULL);
- dbus_message_unref (reply);
- return DBUS_HANDLER_RESULT_HANDLED;
-}
-
/* -----------------------------------------------------------------------------
* OBJECT
*/
@@ -161,11 +108,8 @@ gkd_secrets_session_constructor (GType type, guint n_props, GObjectConstructPara
g_return_val_if_fail (self->caller, NULL);
g_return_val_if_fail (self->service, NULL);
- /* Now register the object */
+ /* Setup the path for the object */
self->object_path = g_strdup_printf (SECRETS_SESSION_PREFIX "/s%d", ++unique_session_number);
- if (!dbus_connection_register_object_path (gkd_secrets_service_get_connection (self->service), self->object_path,
- &GKD_SECRETS_SESSION_GET_CLASS (self)->dbus_vtable, self))
- g_return_val_if_reached (NULL);
return G_OBJECT (self);
}
@@ -181,15 +125,8 @@ gkd_secrets_session_dispose (GObject *obj)
{
GkdSecretsSession *self = GKD_SECRETS_SESSION (obj);
- if (self->object_path) {
- if (self->service) {
- if (!dbus_connection_unregister_object_path (gkd_secrets_service_get_connection (self->service),
- self->object_path))
- g_return_if_reached ();
- }
- g_free (self->object_path);
- self->object_path = NULL;
- }
+ g_free (self->object_path);
+ self->object_path = NULL;
if (self->service) {
g_object_remove_weak_pointer (G_OBJECT (self->service),
@@ -281,8 +218,6 @@ gkd_secrets_session_class_init (GkdSecretsSessionClass *klass)
gobject_class->set_property = gkd_secrets_session_set_property;
gobject_class->get_property = gkd_secrets_session_get_property;
- klass->dbus_vtable.message_function = gkd_secrets_session_message_handler;
-
g_object_class_install_property (gobject_class, PROP_CALLER,
g_param_spec_string ("caller", "Caller", "DBus caller name",
NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ));
@@ -304,6 +239,51 @@ gkd_secrets_session_class_init (GkdSecretsSessionClass *klass)
* PUBLIC
*/
+DBusMessage*
+gkd_secrets_session_dispatch (GkdSecretsSession *self, DBusMessage *message)
+{
+ DBusMessage *reply = NULL;
+ const gchar *caller;
+
+ g_return_val_if_fail (message, NULL);
+ g_return_val_if_fail (GKD_SECRETS_IS_SESSION (self), NULL);
+
+ /* This should already have been caught elsewhere */
+ caller = dbus_message_get_sender (message);
+ if (!caller || !g_str_equal (caller, self->caller))
+ g_return_val_if_reached (NULL);
+
+ /* Check if it's properties, and hand off to property handler. */
+ if (dbus_message_has_interface (message, PROPERTIES_INTERFACE))
+ reply = session_property_handler (self, message);
+
+ /* org.freedesktop.Secrets.Session.Close() */
+ else if (dbus_message_is_method_call (message, SECRETS_SERVICE_INTERFACE, "Close"))
+ reply = session_method_close (self, message);
+
+ /* org.freedesktop.Secrets.Session.Negotiate() */
+ else if (dbus_message_is_method_call (message, SECRETS_SERVICE_INTERFACE, "Negotiate"))
+ g_return_val_if_reached (NULL); /* TODO: Need to implement */
+
+ /* org.freedesktop.Secrets.Session.GetSecret() */
+ else if (dbus_message_is_method_call (message, SECRETS_SERVICE_INTERFACE, "GetSecret"))
+ g_return_val_if_reached (NULL); /* TODO: Need to implement */
+
+ /* org.freedesktop.Secrets.Session.SetSecret() */
+ else if (dbus_message_is_method_call (message, SECRETS_SERVICE_INTERFACE, "SetSecret"))
+ g_return_val_if_reached (NULL); /* TODO: Need to implement */
+
+ /* org.freedesktop.Secrets.Session.GetSecrets() */
+ else if (dbus_message_is_method_call (message, SECRETS_SERVICE_INTERFACE, "GetSecrets"))
+ g_return_val_if_reached (NULL); /* TODO: Need to implement */
+
+ /* org.freedesktop.Secrets.Session.GetSecret() */
+ else if (dbus_message_is_method_call (message, SECRETS_SERVICE_INTERFACE, "GetSecret"))
+ g_return_val_if_reached (NULL); /* TODO: Need to implement */
+
+ return reply;
+}
+
const gchar*
gkd_secrets_session_get_caller (GkdSecretsSession *self)
{
diff --git a/daemon/dbus/gkd-secrets-session.h b/daemon/dbus/gkd-secrets-session.h
index 346ce4d..4680107 100644
--- a/daemon/dbus/gkd-secrets-session.h
+++ b/daemon/dbus/gkd-secrets-session.h
@@ -37,11 +37,13 @@ typedef struct _GkdSecretsSessionClass GkdSecretsSessionClass;
struct _GkdSecretsSessionClass {
GObjectClass parent_class;
- DBusObjectPathVTable dbus_vtable;
};
GType gkd_secrets_session_get_type (void);
+DBusMessage* gkd_secrets_session_dispatch (GkdSecretsSession *self,
+ DBusMessage *message);
+
const gchar* gkd_secrets_session_get_caller (GkdSecretsSession *self);
const gchar* gkd_secrets_session_get_caller_executable (GkdSecretsSession *self);
diff --git a/daemon/dbus/gkd-secrets-types.h b/daemon/dbus/gkd-secrets-types.h
index 6db292a..426500b 100644
--- a/daemon/dbus/gkd-secrets-types.h
+++ b/daemon/dbus/gkd-secrets-types.h
@@ -29,8 +29,8 @@
#define SECRETS_SERVICE_PATH "/org/freedesktop/secrets"
#define SECRETS_SERVICE "org.freedesktop.secrets"
+#define SECRETS_INTERFACE_PREFIX "org.freedesktop.Secrets"
#define SECRETS_COLLECTION_PREFIX "/org/freedesktop/secrets/collection"
-
#define SECRETS_SESSION_PREFIX "/org/freedesktop/secrets/session"
#define SECRETS_ERROR_ALREADY_EXISTS "org.freedesktop.Secrets.Error.AlreadyExists"
diff --git a/pkcs11/pkcs11i.h b/pkcs11/pkcs11i.h
index d1018a3..05beda6 100644
--- a/pkcs11/pkcs11i.h
+++ b/pkcs11/pkcs11i.h
@@ -53,9 +53,7 @@
typedef CK_ULONG CK_G_APPLICATION_ID;
typedef struct CK_G_APPLICATION {
- CK_UTF8CHAR applicationName;
CK_VOID_PTR applicationData;
- CK_FLAGS flags;
CK_G_APPLICATION_ID applicationId;
} CK_G_APPLICATION;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]