diff options
38 files changed, 2312 insertions, 3025 deletions
diff --git a/configure.ac b/configure.ac index 3f0f6669..d9c4e92d 100644 --- a/configure.ac +++ b/configure.ac @@ -72,7 +72,7 @@ PKG_CHECK_MODULES(GOBJECT, glib-2.0 gobject-2.0) AC_SUBST(GOBJECT_CFLAGS) AC_SUBST(GOBJECT_LIBS) -PKG_CHECK_MODULES(GIO, glib-2.0 gio-2.0) +PKG_CHECK_MODULES(GIO, glib-2.0 gio-2.0 gio-unix-2.0) AC_SUBST(GIO_CFLAGS) AC_SUBST(GIO_LIBS) diff --git a/daemon/dbus/Makefile.am b/daemon/dbus/Makefile.am index 5a031edd..a4de4362 100644 --- a/daemon/dbus/Makefile.am +++ b/daemon/dbus/Makefile.am @@ -1,15 +1,46 @@ noinst_LTLIBRARIES += libgkd-dbus.la +daemon/dbus/gkd-secrets-generated.h: daemon/dbus/org.freedesktop.Secrets.xml Makefile.am + $(AM_V_GEN) gdbus-codegen --interface-prefix org.freedesktop.Secrets. \ + --generate-c-code $(srcdir)/daemon/dbus/gkd-secrets-generated \ + --c-namespace Gkd \ + $(srcdir)/daemon/dbus/org.freedesktop.Secrets.xml +daemon/dbus/gkd-secrets-generated.c: daemon/dbus/gkd-secrets-generated.h + @: # generated as a side-effect + +daemon/dbus/gkd-daemon-generated.h: daemon/dbus/org.gnome.keyring.Daemon.xml Makefile.am + $(AM_V_GEN) gdbus-codegen --interface-prefix org.gnome.keyring.Daemon. \ + --generate-c-code $(srcdir)/daemon/dbus/gkd-daemon-generated \ + --c-namespace Gkd \ + $(srcdir)/daemon/dbus/org.gnome.keyring.Daemon.xml +daemon/dbus/gkd-daemon-generated.c: daemon/dbus/gkd-daemon-generated.h + @: # generated as a side-effect + +daemon/dbus/gkd-internal-generated.h: daemon/dbus/org.gnome.keyring.InternalUnsupportedGuiltRiddenInterface.xml Makefile.am + $(AM_V_GEN) gdbus-codegen --interface-prefix org.gnome.keyring.InternalUnsupportedGuiltRiddenInterface. \ + --generate-c-code $(srcdir)/daemon/dbus/gkd-internal-generated \ + --c-namespace Gkd \ + $(srcdir)/daemon/dbus/org.gnome.keyring.InternalUnsupportedGuiltRiddenInterface.xml +daemon/dbus/gkd-internal-generated.c: daemon/dbus/gkd-internal-generated.h + @: # generated as a side-effect + +BUILT_SOURCES += \ + daemon/dbus/gkd-daemon-generated.c \ + daemon/dbus/gkd-daemon-generated.h \ + daemon/dbus/gkd-internal-generated.c \ + daemon/dbus/gkd-internal-generated.h \ + daemon/dbus/gkd-secrets-generated.c \ + daemon/dbus/gkd-secrets-generated.h + libgkd_dbus_la_SOURCES = \ + $(BUILT_SOURCES) \ daemon/dbus/gkd-dbus.c \ daemon/dbus/gkd-dbus.h \ daemon/dbus/gkd-dbus-environment.c \ daemon/dbus/gkd-dbus-private.h \ daemon/dbus/gkd-dbus-secrets.c \ daemon/dbus/gkd-dbus-session.c \ - daemon/dbus/gkd-dbus-util.c \ - daemon/dbus/gkd-dbus-util.h \ daemon/dbus/gkd-secret-change.c \ daemon/dbus/gkd-secret-change.h \ daemon/dbus/gkd-secret-create.c \ @@ -20,8 +51,6 @@ libgkd_dbus_la_SOURCES = \ daemon/dbus/gkd-secret-error.h \ daemon/dbus/gkd-secret-exchange.c \ daemon/dbus/gkd-secret-exchange.h \ - daemon/dbus/gkd-secret-introspect.c \ - daemon/dbus/gkd-secret-introspect.h \ daemon/dbus/gkd-secret-lock.c \ daemon/dbus/gkd-secret-lock.h \ daemon/dbus/gkd-secret-objects.c \ @@ -44,12 +73,14 @@ libgkd_dbus_la_SOURCES = \ $(NULL) libgkd_dbus_la_LIBADD = \ + $(GIO_LIBS) \ $(GLIB_LIBS) \ $(GOBJECT_LIBS) libgkd_dbus_la_CFLAGS = \ $(DAEMON_CFLAGS) \ $(GCR_BASE_CFLAGS) \ + $(GIO_CFLAGS) \ $(GOBJECT_CFLAGS) # ------------------------------------------------------------------- diff --git a/daemon/dbus/gkd-dbus-environment.c b/daemon/dbus/gkd-dbus-environment.c index 2047226f..11279bfb 100644 --- a/daemon/dbus/gkd-dbus-environment.c +++ b/daemon/dbus/gkd-dbus-environment.c @@ -26,8 +26,6 @@ #include "daemon/gkd-util.h" -#include <dbus/dbus.h> - #include <string.h> #define SERVICE_SESSION_MANAGER "org.gnome.SessionManager" @@ -35,38 +33,36 @@ #define IFACE_SESSION_MANAGER "org.gnome.SessionManager" void -gkd_dbus_environment_cleanup (DBusConnection *conn) +gkd_dbus_environment_cleanup (GDBusConnection *conn) { /* Nothing to do here */ } static void -on_setenv_reply (DBusPendingCall *pending, void *user_data) +on_setenv_reply (GObject *source, + GAsyncResult *result, + gpointer user_data) { - DBusMessage *reply; - DBusError derr = DBUS_ERROR_INIT; + GError *error = NULL; - reply = dbus_pending_call_steal_reply (pending); - g_return_if_fail (reply); + g_dbus_connection_call_finish (G_DBUS_CONNECTION (source), result, &error); - if (dbus_set_error_from_message (&derr, reply)) { - if (dbus_error_has_name (&derr, "org.gnome.SessionManager.NotInInitialization") || - dbus_error_has_name (&derr, DBUS_ERROR_SERVICE_UNKNOWN)) - g_debug ("couldn't set environment variable in session: %s", derr.message); + if (error != NULL) { + gchar *dbus_error; + dbus_error = g_dbus_error_get_remote_error (error); + if (g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_SERVICE_UNKNOWN) || + g_strcmp0 (dbus_error, "org.gnome.SessionManager.NotInInitialization")) + g_debug ("couldn't set environment variable in session: %s", error->message); else - g_message ("couldn't set environment variable in session: %s", derr.message); - dbus_error_free (&derr); + g_message ("couldn't set environment variable in session: %s", error->message); + g_error_free (error); + g_free (dbus_error); } - - dbus_message_unref (reply); } static void -setenv_request (DBusConnection *conn, const gchar *env) +setenv_request (GDBusConnection *conn, const gchar *env) { - DBusPendingCall *pending = NULL; - DBusError derr = DBUS_ERROR_INIT; - DBusMessage *msg; const gchar *value; gchar *name; @@ -78,43 +74,31 @@ setenv_request (DBusConnection *conn, const gchar *env) name = g_strndup (env, value - env); ++value; - msg = dbus_message_new_method_call (SERVICE_SESSION_MANAGER, - PATH_SESSION_MANAGER, - IFACE_SESSION_MANAGER, - "Setenv"); - g_return_if_fail (msg); - - if (!dbus_message_append_args (msg, DBUS_TYPE_STRING, &name, - DBUS_TYPE_STRING, &value, - DBUS_TYPE_INVALID)) - g_return_if_reached (); + g_dbus_connection_call (conn, + SERVICE_SESSION_MANAGER, + PATH_SESSION_MANAGER, + IFACE_SESSION_MANAGER, + "Setenv", + g_variant_new ("(ss)", + name, + value), + NULL, G_DBUS_CALL_FLAGS_NONE, + -1, NULL, + on_setenv_reply, NULL); g_free (name); - value = name = NULL; - - /* Send message and get a handle for a reply */ - dbus_connection_send_with_reply (conn, msg, &pending, -1); - dbus_message_unref (msg); - if (pending) { - dbus_pending_call_set_notify (pending, on_setenv_reply, NULL, NULL); - dbus_pending_call_unref (pending); - } else { - g_warning ("couldn't send dbus message: %s", - derr.message ? derr.message : ""); - dbus_error_free (&derr); - } } static void on_watch_environment (gpointer data, gpointer user_data) { - DBusConnection *conn = user_data; + GDBusConnection *conn = user_data; const gchar *env = data; setenv_request (conn, env); } void -gkd_dbus_environment_init (DBusConnection *conn) +gkd_dbus_environment_init (GDBusConnection *conn) { const gchar **envp; @@ -127,6 +111,6 @@ gkd_dbus_environment_init (DBusConnection *conn) for (; *envp; ++envp) setenv_request (conn, *envp); - gkd_util_watch_environment (on_watch_environment, dbus_connection_ref (conn), - (GDestroyNotify)dbus_connection_unref); + gkd_util_watch_environment (on_watch_environment, g_object_ref (conn), + (GDestroyNotify) g_object_unref); } diff --git a/daemon/dbus/gkd-dbus-private.h b/daemon/dbus/gkd-dbus-private.h index 893281a2..1955880b 100644 --- a/daemon/dbus/gkd-dbus-private.h +++ b/daemon/dbus/gkd-dbus-private.h @@ -24,22 +24,22 @@ #define GKD_DBUS_PRIVATE_H #include <glib.h> -#include <dbus/dbus.h> +#include <gio/gio.h> /* DBus environment variables sent to session */ -void gkd_dbus_environment_init (DBusConnection *conn); -void gkd_dbus_environment_cleanup (DBusConnection *conn); +void gkd_dbus_environment_init (GDBusConnection *conn); +void gkd_dbus_environment_cleanup (GDBusConnection *conn); /* The gnome-keyring Dbus service, very simple */ -void gkd_dbus_service_init (DBusConnection *conn); -void gkd_dbus_service_cleanup (DBusConnection *conn); +void gkd_dbus_service_init (GDBusConnection *conn); +void gkd_dbus_service_cleanup (GDBusConnection *conn); /* DBus desktop session interaction */ -void gkd_dbus_session_init (DBusConnection *conn); -void gkd_dbus_session_cleanup (DBusConnection *conn); +void gkd_dbus_session_init (GDBusConnection *conn); +void gkd_dbus_session_cleanup (GDBusConnection *conn); /* DBus secrets API */ -void gkd_dbus_secrets_init (DBusConnection *conn); -void gkd_dbus_secrets_cleanup (DBusConnection *conn); +void gkd_dbus_secrets_init (GDBusConnection *conn); +void gkd_dbus_secrets_cleanup (GDBusConnection *conn); #endif /* GKD_DBUS_PRIVATE_H */ diff --git a/daemon/dbus/gkd-dbus-secrets.c b/daemon/dbus/gkd-dbus-secrets.c index 58e0a8fb..f4e38fc4 100644 --- a/daemon/dbus/gkd-dbus-secrets.c +++ b/daemon/dbus/gkd-dbus-secrets.c @@ -33,7 +33,7 @@ #include <gck/gck.h> -static DBusConnection *dbus_conn = NULL; +static GDBusConnection *dbus_conn = NULL; static GkdSecretService *secrets_service = NULL; static GckSlot* @@ -66,18 +66,19 @@ calculate_secrets_slot (void) gboolean gkd_dbus_secrets_startup (void) { - DBusError error = DBUS_ERROR_INIT; - dbus_uint32_t result = 0; const gchar *service = NULL; unsigned int flags = 0; GckSlot *slot; + GError *error = NULL; + GVariant *request_variant; + guint res; g_return_val_if_fail (dbus_conn, FALSE); #ifdef WITH_DEBUG service = g_getenv ("GNOME_KEYRING_TEST_SERVICE"); if (service && service[0]) - flags = DBUS_NAME_FLAG_ALLOW_REPLACEMENT | DBUS_NAME_FLAG_REPLACE_EXISTING; + flags = G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT | G_BUS_NAME_OWNER_FLAGS_REPLACE; else #endif service = SECRET_SERVICE; @@ -87,29 +88,37 @@ gkd_dbus_secrets_startup (void) g_return_val_if_fail (slot, FALSE); /* Try and grab our name */ - result = dbus_bus_request_name (dbus_conn, service, flags, &error); - if (dbus_error_is_set (&error)) { + request_variant = g_dbus_connection_call_sync (dbus_conn, + "org.freedesktop.DBus", /* bus name */ + "/org/freedesktop/DBus", /* object path */ + "org.freedesktop.DBus", /* interface name */ + "RequestName", /* method name */ + g_variant_new ("(su)", + service, + flags), + G_VARIANT_TYPE ("(u)"), + G_DBUS_CALL_FLAGS_NONE, + -1, NULL, &error); + + if (error != NULL) { g_message ("couldn't request name '%s' on session bus: %s", - service, error.message); - dbus_error_free (&error); - + service, error->message); + g_error_free (error); } else { - switch (result) { + g_variant_get (request_variant, "(u)", &res); + g_variant_unref (request_variant); + switch (res) { /* We acquired the service name */ - case DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER: - break; - + case 1: /* DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER */ /* We already acquired the service name. */ - case DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER: + case 4: /* DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER */ break; - /* Another daemon is running */ - case DBUS_REQUEST_NAME_REPLY_IN_QUEUE: - case DBUS_REQUEST_NAME_REPLY_EXISTS: + case 2: /* DBUS_REQUEST_NAME_REPLY_IN_QUEUE */ + case 3: /* DBUS_REQUEST_NAME_REPLY_EXISTS */ g_message ("another secret service is running"); break; - default: g_return_val_if_reached (FALSE); break; @@ -128,19 +137,18 @@ static void cleanup_dbus_conn (gpointer unused) { g_assert (dbus_conn); - dbus_connection_unref (dbus_conn); - dbus_conn = NULL; + g_clear_object (&dbus_conn); } void -gkd_dbus_secrets_init (DBusConnection *conn) +gkd_dbus_secrets_init (GDBusConnection *conn) { - dbus_conn = dbus_connection_ref (conn); + dbus_conn = g_object_ref (conn); egg_cleanup_register (cleanup_dbus_conn, NULL); } void -gkd_dbus_secrets_cleanup (DBusConnection *conn) +gkd_dbus_secrets_cleanup (GDBusConnection *conn) { if (secrets_service) { g_object_run_dispose (G_OBJECT (secrets_service)); diff --git a/daemon/dbus/gkd-dbus-session.c b/daemon/dbus/gkd-dbus-session.c index 5f09772c..5fe687a2 100644 --- a/daemon/dbus/gkd-dbus-session.c +++ b/daemon/dbus/gkd-dbus-session.c @@ -26,8 +26,6 @@ #include "daemon/gkd-main.h" -#include <dbus/dbus.h> - #include <string.h> #define SERVICE_SESSION_MANAGER "org.gnome.SessionManager" @@ -37,108 +35,89 @@ #define IFACE_SESSION_PRIVATE "org.gnome.SessionManager.ClientPrivate" static gchar *client_session_path = NULL; -static gchar *client_session_rule = NULL; +static guint client_session_signal_id = 0; static void -send_end_session_response (DBusConnection *conn) +send_end_session_response (GDBusConnection *conn) { - DBusMessageIter args; - DBusMessage *msg; - DBusMessage *reply; - DBusError derr = { 0 }; const gchar *reason = ""; - dbus_bool_t is_ok = TRUE; + gboolean is_ok = TRUE; + GError *error = NULL; g_return_if_fail (client_session_path); - msg = dbus_message_new_method_call (SERVICE_SESSION_MANAGER, - client_session_path, - IFACE_SESSION_PRIVATE, - "EndSessionResponse"); - g_return_if_fail (msg); - - dbus_message_iter_init_append (msg, &args); - if (!dbus_message_iter_append_basic (&args, DBUS_TYPE_BOOLEAN, &is_ok) || - !dbus_message_iter_append_basic (&args, DBUS_TYPE_STRING, &reason)) - g_return_if_reached (); - - reply = dbus_connection_send_with_reply_and_block (conn, msg, 1000, &derr); - dbus_message_unref (msg); - - if (!reply) { - g_message ("dbus failure responding to ending session: %s", derr.message); + g_dbus_connection_call_sync (conn, + SERVICE_SESSION_MANAGER, + client_session_path, + IFACE_SESSION_PRIVATE, + "EndSessionResponse", + g_variant_new ("(bs)", + is_ok, + reason), + NULL, + G_DBUS_CALL_FLAGS_NONE, 1000, + NULL, &error); + + if (error != NULL) { + g_message ("dbus failure responding to ending session: %s", error->message); + g_error_free (error); return; } - - dbus_message_unref (reply); } static void -unregister_daemon_in_session (DBusConnection *conn) +unregister_daemon_in_session (GDBusConnection *conn) { - DBusMessageIter args; - DBusMessage *msg; - - if (client_session_rule) { - dbus_bus_remove_match (conn, client_session_rule, NULL); - g_free (client_session_rule); - client_session_rule = NULL; + if (client_session_signal_id) { + g_dbus_connection_signal_unsubscribe (conn, client_session_signal_id); + client_session_signal_id = 0; } if (!client_session_path) return; - msg = dbus_message_new_method_call (SERVICE_SESSION_MANAGER, - PATH_SESSION_MANAGER, - IFACE_SESSION_MANAGER, - "UnregisterClient"); - g_return_if_fail (msg); - - dbus_message_iter_init_append (msg, &args); - if (!dbus_message_iter_append_basic (&args, DBUS_TYPE_OBJECT_PATH, &client_session_path)) - g_return_if_reached (); - - dbus_message_set_no_reply (msg, TRUE); - dbus_connection_send (conn, msg, NULL); - dbus_connection_flush (conn); - dbus_message_unref (msg); + g_dbus_connection_call_sync (conn, + SERVICE_SESSION_MANAGER, + PATH_SESSION_MANAGER, + IFACE_SESSION_MANAGER, + "UnregisterClient", + g_variant_new ("(o)", client_session_path), + NULL, G_DBUS_CALL_FLAGS_NONE, + -1, NULL, NULL); g_free (client_session_path); client_session_path = NULL; } -static DBusHandlerResult -signal_filter (DBusConnection *conn, DBusMessage *msg, void *user_data) +static void +signal_filter (GDBusConnection *conn, + const gchar *sender_name, + const gchar *object_path, + const gchar *interface_name, + const gchar *signal_name, + GVariant *parameters, + gpointer user_data) { /* Quit the daemon when the session is over */ - if (dbus_message_is_signal (msg, IFACE_SESSION_PRIVATE, "Stop")) { + if (g_strcmp0 (signal_name, "Stop") == 0) { unregister_daemon_in_session (conn); gkd_main_quit (); - return DBUS_HANDLER_RESULT_HANDLED; - } else if (dbus_message_is_signal (msg, IFACE_SESSION_PRIVATE, "QueryEndSession")) { + } else if (g_strcmp0 (signal_name, "QueryEndSession") == 0) { send_end_session_response (conn); - return DBUS_HANDLER_RESULT_HANDLED; - } else if (dbus_message_is_signal (msg, IFACE_SESSION_PRIVATE, "EndSession")) { + } else if (g_strcmp0 (signal_name, "EndSession") == 0) { send_end_session_response (conn); unregister_daemon_in_session (conn); gkd_main_quit (); - return DBUS_HANDLER_RESULT_HANDLED; - } else if (dbus_message_is_signal (msg, DBUS_INTERFACE_LOCAL, "Disconnected")) { + } else if (g_strcmp0 (signal_name, "Disconnected") == 0) { gkd_main_quit (); - return DBUS_HANDLER_RESULT_HANDLED; } - - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } void -gkd_dbus_session_cleanup (DBusConnection *conn) +gkd_dbus_session_cleanup (GDBusConnection *conn) { g_free (client_session_path); client_session_path = NULL; - - g_free (client_session_rule); - client_session_rule = NULL; } /* @@ -146,50 +125,37 @@ gkd_dbus_session_cleanup (DBusConnection *conn) * session manager via DBus. */ void -gkd_dbus_session_init (DBusConnection *conn) +gkd_dbus_session_init (GDBusConnection *conn) { - DBusMessageIter args; - DBusMessage *msg; - DBusMessage *reply; - DBusError derr = { 0 }; const gchar *app_id = "gnome-keyring-daemon"; const gchar *client_id; + GError *error = NULL; + GVariant *object_path_variant; client_id = g_getenv ("DESKTOP_AUTOSTART_ID"); if (!client_id) return; - msg = dbus_message_new_method_call (SERVICE_SESSION_MANAGER, - PATH_SESSION_MANAGER, - IFACE_SESSION_MANAGER, - "RegisterClient"); - g_return_if_fail (msg); - - dbus_message_iter_init_append (msg, &args); - if (!dbus_message_iter_append_basic (&args, DBUS_TYPE_STRING, &app_id) || - !dbus_message_iter_append_basic (&args, DBUS_TYPE_STRING, &client_id)) - g_return_if_reached (); - - /* Send message and get a handle for a reply */ - reply = dbus_connection_send_with_reply_and_block (conn, msg, 1000, &derr); - dbus_message_unref (msg); - - if (!reply) { - g_message ("couldn't register in session: %s", derr.message); - dbus_error_free (&derr); + object_path_variant = g_dbus_connection_call_sync (conn, + SERVICE_SESSION_MANAGER, + PATH_SESSION_MANAGER, + IFACE_SESSION_MANAGER, + "RegisterClient", + g_variant_new ("(ss)", + app_id, + client_id), + G_VARIANT_TYPE ("(o)"), + G_DBUS_CALL_FLAGS_NONE, 1000, + NULL, &error); + + if (error != NULL) { + g_message ("couldn't register in session: %s", error->message); + g_error_free (error); return; } - /* Get out our client path */ - if (!dbus_message_iter_init (reply, &args) || - dbus_message_iter_get_arg_type (&args) != DBUS_TYPE_OBJECT_PATH) { - g_message ("invalid register response from session"); - } else { - dbus_message_iter_get_basic (&args, &client_session_path); - client_session_path = g_strdup (client_session_path); - } - - dbus_message_unref (reply); + g_variant_get (object_path_variant, "(o)", &client_session_path); + g_variant_unref (object_path_variant); /* * Unset DESKTOP_AUTOSTART_ID in order to avoid child processes to @@ -201,19 +167,10 @@ gkd_dbus_session_init (DBusConnection *conn) * Now we register for DBus signals on that client session path * These are fired specifically for us. */ - client_session_rule = g_strdup_printf("type='signal'," - "interface='org.gnome.SessionManager.ClientPrivate'," - "path='%s'", - client_session_path); - dbus_bus_add_match (conn, client_session_rule, &derr); - - if(dbus_error_is_set(&derr)) { - g_message ("couldn't listen for signals in session: %s", derr.message); - dbus_error_free (&derr); - g_free (client_session_rule); - client_session_rule = NULL; - return; - } - - dbus_connection_add_filter (conn, signal_filter, NULL, NULL); + g_dbus_connection_signal_subscribe (conn, + NULL, + "org.gnome.SessionManager.ClientPrivate", NULL, + client_session_path, NULL, + G_DBUS_SIGNAL_FLAGS_NONE, + signal_filter, NULL, NULL); } diff --git a/daemon/dbus/gkd-dbus-util.c b/daemon/dbus/gkd-dbus-util.c deleted file mode 100644 index 7c006349..00000000 --- a/daemon/dbus/gkd-dbus-util.c +++ /dev/null @@ -1,134 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ -/* gkd-dbus.c - hook into dbus, call other bits - - Copyright (C) 2007, 2009, 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, - <http://www.gnu.org/licenses/>. - - Author: Stef Walter <stef@memberwebs.com> -*/ - -#include "config.h" - -#include "gkd-dbus-util.h" -#include "gkd-secret-types.h" - -#include "egg/egg-error.h" - -#include <string.h> - -GType -gkd_dbus_connection_get_boxed_type (void) -{ - static GType type = 0; - if (!type) - type = g_boxed_type_register_static ("GkdDBusConnection", - (GBoxedCopyFunc)dbus_connection_ref, - (GBoxedFreeFunc)dbus_connection_unref); - return type; -} - -gboolean -gkd_dbus_interface_match (const gchar *interface, const gchar *match) -{ - g_return_val_if_fail (interface, FALSE); - - /* Null or zero length matches anything */ - if (!match || !match[0]) - return TRUE; - - return strcmp (interface, match) == 0; -} - -static gchar * -build_child_node_xml (const gchar *parent, - const gchar **children) -{ - GString *result; - const gchar *child; - guint i; - - result = g_string_new (""); - for (i = 0; children != NULL && children[i] != NULL; i++) { - if (children[i][0] == '/') { - if (!g_str_has_prefix (children[i], parent)) { - g_warning ("in introspection data child '%s' is not descendant of parent '%s'", - children[i], parent); - continue; - } - child = children[i] + strlen (parent); - while (child[0] == '/') - child++; - } else { - child = children[i]; - } - - g_string_append_printf (result, "\t<node name=\"%s\"/>\n", child); - } - - return g_string_free (result, FALSE); -} - -static gboolean -string_replace (GString *string, - const gchar *search, - const gchar *replace) -{ - const gchar *pos; - - pos = strstr (string->str, search); - if (pos == NULL) - return FALSE; - - g_string_erase (string, pos - string->str, strlen (search)); - g_string_insert (string, pos - string->str, replace); - return TRUE; -} - -DBusMessage * -gkd_dbus_introspect_handle (DBusMessage *message, - const gchar *data, - const gchar **children) -{ - DBusMessage *reply; - GString *output = NULL; - gchar *nodes; - - g_return_val_if_fail (message, NULL); - g_return_val_if_fail (data, NULL); - - if (dbus_message_is_method_call (message, DBUS_INTERFACE_INTROSPECTABLE, "Introspect") && - dbus_message_get_args (message, NULL, DBUS_TYPE_INVALID)) { - - if (children != NULL) { - output = g_string_new (data); - nodes = build_child_node_xml (dbus_message_get_path (message), children); - if (!string_replace (output, "<!--@children@-->", nodes)) - g_warning ("introspection data contained no location for child nodes"); - g_free (nodes); - data = output->str; - } - - reply = dbus_message_new_method_return (message); - if (!dbus_message_append_args (reply, DBUS_TYPE_STRING, &data, DBUS_TYPE_INVALID)) - g_return_val_if_reached (NULL); - - if (output) - g_string_free (output, TRUE); - return reply; - } - - return NULL; -} diff --git a/daemon/dbus/gkd-dbus-util.h b/daemon/dbus/gkd-dbus-util.h deleted file mode 100644 index 75d5199c..00000000 --- a/daemon/dbus/gkd-dbus-util.h +++ /dev/null @@ -1,40 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ -/* gkd-dbus.h - header for dbus component - - Copyright (C) 2009, 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, - <http://www.gnu.org/licenses/>. - - Author: Stef Walter <stef@memberwebs.com> -*/ - -#ifndef GKD_DBUS_H -#define GKD_DBUS_H - -#include <glib.h> -#include <glib-object.h> -#include <dbus/dbus.h> - -#define GKD_DBUS_TYPE_CONNECTION (gkd_dbus_connection_get_boxed_type ()) - -GType gkd_dbus_connection_get_boxed_type (void) G_GNUC_CONST; - -gboolean gkd_dbus_interface_match (const gchar *interface, const gchar *match); - -DBusMessage* gkd_dbus_introspect_handle (DBusMessage *message, - const gchar *data, - const gchar **children); - -#endif /* GKD_DBUS_H */ diff --git a/daemon/dbus/gkd-dbus.c b/daemon/dbus/gkd-dbus.c index ad2aff24..a7a4a724 100644 --- a/daemon/dbus/gkd-dbus.c +++ b/daemon/dbus/gkd-dbus.c @@ -22,6 +22,7 @@ #include "config.h" +#include "gkd-daemon-generated.h" #include "gkd-dbus.h" #include "gkd-dbus-private.h" @@ -32,10 +33,9 @@ #include "egg/egg-dbus.h" #include <glib.h> +#include <gio/gio.h> -#include <dbus/dbus.h> - -static DBusConnection *dbus_conn = NULL; +static GDBusConnection *dbus_conn = NULL; static gboolean object_registered = FALSE; static gboolean acquired_asked = FALSE; static gboolean acquired_service = FALSE; @@ -50,9 +50,7 @@ cleanup_session_bus (gpointer unused) if (!dbus_conn) return; - egg_dbus_disconnect_from_mainloop (dbus_conn, NULL); - dbus_connection_unref (dbus_conn); - dbus_conn = NULL; + g_clear_object (&dbus_conn); } static void @@ -65,115 +63,78 @@ on_connection_close (gpointer user_data) static gboolean connect_to_session_bus (void) { - DBusError derr = { 0 }; + GError *error = NULL; if (dbus_conn) return TRUE; - dbus_error_init (&derr); - - /* Get the dbus bus and hook up */ - dbus_conn = dbus_bus_get (DBUS_BUS_SESSION, &derr); + dbus_conn = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error); if (!dbus_conn) { - g_message ("couldn't connect to dbus session bus: %s", derr.message); - dbus_error_free (&derr); + g_message ("couldn't connect to dbus session bus: %s", error->message); + g_error_free (error); return FALSE; } - egg_dbus_connect_with_mainloop (dbus_conn, NULL, on_connection_close); - dbus_connection_set_exit_on_disconnect (dbus_conn, FALSE); + g_signal_connect (dbus_conn, "closed", + G_CALLBACK (on_connection_close), NULL); egg_cleanup_register (cleanup_session_bus, NULL); return TRUE; } -static DBusHandlerResult -message_handler_cb (DBusConnection *conn, DBusMessage *message, void *user_data) +static gboolean +handle_get_environment (GkdOrgGnomeKeyringDaemon *skeleton, + GDBusMethodInvocation *invocation, + gpointer user_data) { - /* - * Here we handle the requests to our own gnome-keyring DBus interfaces - */ - - DBusMessageIter args; - DBusMessage *reply = NULL; - - /* GetEnvironment */ - if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_CALL && - dbus_message_is_method_call (message, GNOME_KEYRING_DAEMON_INTERFACE, "GetEnvironment") && - g_str_equal (dbus_message_get_signature (message), "")) { - - const gchar **env; - DBusMessageIter items, entry; - - env = gkd_util_get_environment (); - g_return_val_if_fail (env, DBUS_HANDLER_RESULT_NOT_YET_HANDLED); - - /* Setup the result */ - reply = dbus_message_new_method_return (message); - dbus_message_iter_init_append (reply, &args); - if (!dbus_message_iter_open_container (&args, DBUS_TYPE_ARRAY, "{ss}", &items)) - g_return_val_if_reached (DBUS_HANDLER_RESULT_NEED_MEMORY); - while (*env) { - gchar **parts; - parts = g_strsplit (*env, "=", 2); - g_return_val_if_fail (parts && parts[0] && parts[1], DBUS_HANDLER_RESULT_NOT_YET_HANDLED); - if (!dbus_message_iter_open_container (&items, DBUS_TYPE_DICT_ENTRY, NULL, &entry) || - !dbus_message_iter_append_basic (&entry, DBUS_TYPE_STRING, &parts[0]) || - !dbus_message_iter_append_basic (&entry, DBUS_TYPE_STRING, &parts[1]) || - !dbus_message_iter_close_container (&items, &entry)) { - g_strfreev (parts); - g_return_val_if_reached (DBUS_HANDLER_RESULT_NEED_MEMORY); - } - g_strfreev (parts); - ++env; - } - if (!dbus_message_iter_close_container (&args, &items)) - g_return_val_if_reached (DBUS_HANDLER_RESULT_NEED_MEMORY); - - /* GetControlDirectory */ - } else if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_CALL && - dbus_message_is_method_call (message, GNOME_KEYRING_DAEMON_INTERFACE, "GetControlDirectory") && - g_str_equal (dbus_message_get_signature (message), "")) { - - /* Setup the result */ - const gchar *directory = gkd_util_get_master_directory (); - reply = dbus_message_new_method_return (message); - dbus_message_append_args (reply, DBUS_TYPE_STRING, &directory, DBUS_TYPE_INVALID); - - /* Unknown call */ - } else { - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } + const gchar **env; + gchar **parts; + GVariantBuilder builder; - /* Send the reply */ - if (!dbus_connection_send (conn, reply, NULL)) - g_return_val_if_reached (DBUS_HANDLER_RESULT_NEED_MEMORY); - dbus_connection_flush (conn); + env = gkd_util_get_environment (); + g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{ss}")); - return DBUS_HANDLER_RESULT_HANDLED; + while (*env) { + parts = g_strsplit (*env, "=", 2); + g_variant_builder_add (&builder, "{ss}", parts[0], parts[1]); + g_strfreev (parts); + } + + gkd_org_gnome_keyring_daemon_complete_get_environment (skeleton, invocation, + g_variant_builder_end (&builder)); + return TRUE; } -static DBusObjectPathVTable object_vtable = { - NULL, - message_handler_cb, - NULL, -}; +static gboolean +handle_get_control_directory (GkdOrgGnomeKeyringDaemon *skeleton, + GDBusMethodInvocation *invocation, + gpointer user_data) +{ + gkd_org_gnome_keyring_daemon_complete_get_control_directory (skeleton, invocation, + gkd_util_get_master_directory ()); + return TRUE; +} static void -cleanup_singleton (gpointer unused) +cleanup_singleton (gpointer user_data) { + GkdOrgGnomeKeyringDaemon *skeleton = user_data; + g_return_if_fail (dbus_conn); - if (object_registered) - dbus_connection_unregister_object_path (dbus_conn, GNOME_KEYRING_DAEMON_PATH); + if (object_registered) { + g_dbus_interface_skeleton_unexport_from_connection (G_DBUS_INTERFACE_SKELETON (skeleton), dbus_conn); + g_object_unref (skeleton); + } object_registered = FALSE; } gboolean gkd_dbus_singleton_acquire (gboolean *acquired) { - DBusError derr = DBUS_ERROR_INIT; - dbus_uint32_t res = 0; const gchar *service = NULL; - unsigned int flags = 0; + GBusNameOwnerFlags flags = G_BUS_NAME_OWNER_FLAGS_NONE; + GVariant *acquire_variant; + guint res; + GError *error = NULL; g_assert (acquired); @@ -182,63 +143,88 @@ gkd_dbus_singleton_acquire (gboolean *acquired) /* First register the object */ if (!object_registered) { - if (dbus_connection_register_object_path (dbus_conn, GNOME_KEYRING_DAEMON_PATH, - &object_vtable, NULL)) { + GError *error = NULL; + GkdOrgGnomeKeyringDaemon *skeleton = gkd_org_gnome_keyring_daemon_skeleton_new (); + + g_signal_connect (skeleton, "handle-get-control-directory", + G_CALLBACK (handle_get_control_directory), NULL); + g_signal_connect (skeleton, "handle-get-environment", + G_CALLBACK (handle_get_environment), NULL); + + g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (skeleton), dbus_conn, + GNOME_KEYRING_DAEMON_PATH, &error); + + if (error == NULL) { object_registered = TRUE; - egg_cleanup_register (cleanup_singleton, NULL); + egg_cleanup_register (cleanup_singleton, skeleton); } else { - g_message ("couldn't register dbus object path"); + g_message ("couldn't register dbus object path: %s", error->message); + g_error_free (error); } } /* Try and grab our name */ if (!acquired_asked) { - #ifdef WITH_DEBUG service = g_getenv ("GNOME_KEYRING_TEST_SERVICE"); if (service && service[0]) - flags = DBUS_NAME_FLAG_ALLOW_REPLACEMENT | DBUS_NAME_FLAG_REPLACE_EXISTING; + flags = G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT | G_BUS_NAME_OWNER_FLAGS_REPLACE; else #endif service = GNOME_KEYRING_DAEMON_SERVICE; - res = dbus_bus_request_name (dbus_conn, service, flags, &derr); - if (dbus_error_is_set (&derr)) { - g_message ("couldn't request name '%s' on session bus: %s", service, derr.message); - dbus_error_free (&derr); + /* attempt to acquire the name */ + acquire_variant = g_dbus_connection_call_sync (dbus_conn, + "org.freedesktop.DBus", /* bus name */ + "/org/freedesktop/DBus", /* object path */ + "org.freedesktop.DBus", /* interface name */ + "RequestName", /* method name */ + g_variant_new ("(su)", + service, + flags), + G_VARIANT_TYPE ("(u)"), + G_DBUS_CALL_FLAGS_NONE, + -1, NULL, &error); + + if (error != NULL) { + g_message ("couldn't request name '%s' on session bus: %s", service, error->message); + g_error_free (error); return FALSE; } acquired_asked = TRUE; + g_variant_get (acquire_variant, "(u)", &res); + g_variant_unref (acquire_variant); + switch (res) { - /* We acquired the service name */ - case DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER: - case DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER: - acquired_service = TRUE; - break; - /* Another daemon is running */ - case DBUS_REQUEST_NAME_REPLY_IN_QUEUE: - case DBUS_REQUEST_NAME_REPLY_EXISTS: - acquired_service = FALSE; - break; - default: - acquired_service = FALSE; - g_return_val_if_reached (FALSE); - break; - }; + /* We acquired the service name */ + case 1: /* DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER */ + case 4: /* DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER */ + acquired_service = TRUE; + break; + /* Another daemon is running */ + case 2: /* DBUS_REQUEST_NAME_REPLY_IN_QUEUE */ + case 3: /* DBUS_REQUEST_NAME_REPLY_EXISTS */ + acquired_service = FALSE; + break; + default: + acquired_service = FALSE; + g_return_val_if_reached (FALSE); + break; + }; } *acquired = acquired_service; + return TRUE; } gchar* gkd_dbus_singleton_control (void) { - DBusError derr = DBUS_ERROR_INIT; - DBusMessage *msg, *reply; gchar *control = NULL; - const char *path; + GError *error = NULL; + GVariant *control_variant; /* If tried to aquire the service must have failed */ g_return_val_if_fail (!acquired_service, NULL); @@ -246,34 +232,25 @@ gkd_dbus_singleton_control (void) if (!connect_to_session_bus ()) return NULL; - msg = dbus_message_new_method_call (GNOME_KEYRING_DAEMON_SERVICE, - GNOME_KEYRING_DAEMON_PATH, - GNOME_KEYRING_DAEMON_INTERFACE, - "GetControlDirectory"); - g_return_val_if_fail (msg, NULL); - dbus_message_set_auto_start (msg, FALSE); - - /* Send message and get a handle for a reply */ - reply = dbus_connection_send_with_reply_and_block (dbus_conn, msg, 1000, &derr); - dbus_message_unref (msg); - - if (!reply) { - if (!dbus_error_has_name (&derr, "org.freedesktop.DBus.Error.NameHasNoOwner")) - g_message ("couldn't communicate with already running daemon: %s", derr.message); - dbus_error_free (&derr); + control_variant = g_dbus_connection_call_sync (dbus_conn, + GNOME_KEYRING_DAEMON_SERVICE, + GNOME_KEYRING_DAEMON_PATH, + GNOME_KEYRING_DAEMON_INTERFACE, + "GetControlDirectory", + NULL, NULL, + G_DBUS_CALL_FLAGS_NO_AUTO_START, + 1000, NULL, &error); + + if (error != NULL) { + if (!g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_NAME_HAS_NO_OWNER)) + g_message ("couldn't communicate with already running daemon: %s", error->message); + g_error_free (error); return NULL; } - /* Get out our client path */ - if (!dbus_message_get_args (reply, &derr, DBUS_TYPE_STRING, &path, DBUS_TYPE_INVALID)) { - g_message ("couldn't parse response from already running daemon: %s", derr.message); - dbus_error_free (&derr); - control = NULL; - } else { - control = g_strdup (path); - } + g_variant_get (control_variant, "(s)", &control); + g_variant_unref (control_variant); - dbus_message_unref (reply); return control; } diff --git a/daemon/dbus/gkd-secret-change.c b/daemon/dbus/gkd-secret-change.c index 62a15198..24466ea0 100644 --- a/daemon/dbus/gkd-secret-change.c +++ b/daemon/dbus/gkd-secret-change.c @@ -26,7 +26,6 @@ #include "gkd-secret-service.h" #include "gkd-secret-session.h" #include "gkd-secret-types.h" -#include "gkd-secret-util.h" #include "egg/egg-error.h" #include "egg/egg-secure-memory.h" @@ -337,15 +336,10 @@ gkd_secret_change_prompt_ready (GkdSecretPrompt *prompt) g_clear_object (&collection); } -static void -gkd_secret_change_encode_result (GkdSecretPrompt *base, DBusMessageIter *iter) +static GVariant * +gkd_secret_change_encode_result (GkdSecretPrompt *base) { - DBusMessageIter variant; - const gchar *string = ""; - - dbus_message_iter_open_container (iter, DBUS_TYPE_VARIANT, "s", &variant); - dbus_message_iter_append_basic (&variant, DBUS_TYPE_STRING, &string); - dbus_message_iter_close_container (iter, &variant); + return g_variant_new_variant (g_variant_new_string ("")); } static void diff --git a/daemon/dbus/gkd-secret-create.c b/daemon/dbus/gkd-secret-create.c index 94529412..9e7c2d42 100644 --- a/daemon/dbus/gkd-secret-create.c +++ b/daemon/dbus/gkd-secret-create.c @@ -292,17 +292,14 @@ gkd_secret_create_prompt_ready (GkdSecretPrompt *prompt) perform_prompting (GKD_SECRET_CREATE (prompt)); } -static void -gkd_secret_create_encode_result (GkdSecretPrompt *base, DBusMessageIter *iter) +static GVariant * +gkd_secret_create_encode_result (GkdSecretPrompt *base) { 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); + return g_variant_new_variant (g_variant_new_object_path (path)); } static void diff --git a/daemon/dbus/gkd-secret-dispatch.c b/daemon/dbus/gkd-secret-dispatch.c index d1d9450e..fed4c13e 100644 --- a/daemon/dbus/gkd-secret-dispatch.c +++ b/daemon/dbus/gkd-secret-dispatch.c @@ -54,14 +54,6 @@ gkd_secret_dispatch_get_type (void) return type; } -DBusMessage* -gkd_secret_dispatch_message (GkdSecretDispatch *self, DBusMessage *message) -{ - g_return_val_if_fail (GKD_SECRET_IS_DISPATCH (self), NULL); - g_return_val_if_fail (GKD_SECRET_DISPATCH_GET_INTERFACE (self)->dispatch_message, NULL); - return GKD_SECRET_DISPATCH_GET_INTERFACE (self)->dispatch_message (self, message); -} - const gchar* gkd_secret_dispatch_get_object_path (GkdSecretDispatch *self) { diff --git a/daemon/dbus/gkd-secret-dispatch.h b/daemon/dbus/gkd-secret-dispatch.h index 5f0470a9..69586034 100644 --- a/daemon/dbus/gkd-secret-dispatch.h +++ b/daemon/dbus/gkd-secret-dispatch.h @@ -23,8 +23,6 @@ #include "gkd-secret-types.h" -#include <dbus/dbus.h> - #include <glib-object.h> G_BEGIN_DECLS @@ -40,16 +38,12 @@ struct _GkdSecretDispatchIface { GTypeInterface parent; const gchar* (*get_path) (GkdSecretDispatch *self); - DBusMessage* (*dispatch_message) (GkdSecretDispatch *self, DBusMessage *message); }; GType gkd_secret_dispatch_get_type (void) G_GNUC_CONST; const gchar* gkd_secret_dispatch_get_object_path (GkdSecretDispatch *self); -DBusMessage* gkd_secret_dispatch_message (GkdSecretDispatch *self, - DBusMessage *message); - G_END_DECLS #endif /* __GKD_SECRET_DISPATCH_H__ */ diff --git a/daemon/dbus/gkd-secret-error.c b/daemon/dbus/gkd-secret-error.c index dd06eca7..de286c46 100644 --- a/daemon/dbus/gkd-secret-error.c +++ b/daemon/dbus/gkd-secret-error.c @@ -28,52 +28,66 @@ #include <glib.h> -DBusMessage* -gkd_secret_error_no_such_object (DBusMessage *message) +static const GDBusErrorEntry gkd_secret_error_entries[] = { + { GKD_SECRET_ERROR_ALREADY_EXISTS, SECRET_INTERFACE_PREFIX "Error.AlreadyExists" }, + { GKD_SECRET_ERROR_IS_LOCKED, SECRET_INTERFACE_PREFIX "Error.IsLocked" }, + { GKD_SECRET_ERROR_NO_SESSION, SECRET_INTERFACE_PREFIX "Error.NoSession" }, + { GKD_SECRET_ERROR_NO_SUCH_OBJECT, SECRET_INTERFACE_PREFIX "Error.NoSuchObject" } +}; + +GQuark +gkd_secret_error_quark (void) { - g_return_val_if_fail (message, NULL); - return dbus_message_new_error_printf (message, SECRET_ERROR_NO_SUCH_OBJECT, - "The '%s' object does not exist", dbus_message_get_path (message)); + static volatile gsize quark_volatile = 0; + + g_dbus_error_register_error_domain ("gkd_secret_error", + &quark_volatile, + gkd_secret_error_entries, + G_N_ELEMENTS (gkd_secret_error_entries)); + return quark_volatile; } -DBusMessage* -gkd_secret_error_to_reply (DBusMessage *message, DBusError *derr) -{ - DBusMessage *reply; +static const GDBusErrorEntry gkd_secret_daemon_error_entries[] = { + { GKD_SECRET_DAEMON_ERROR_DENIED, "org.gnome.keyring.Error.Denied" } +}; - g_return_val_if_fail (message, NULL); - g_return_val_if_fail (derr, NULL); - g_return_val_if_fail (dbus_error_is_set (derr), NULL); +GQuark +gkd_secret_daemon_error_quark (void) +{ + static volatile gsize quark_volatile = 0; - reply = dbus_message_new_error (message, derr->name, derr->message); - dbus_error_free (derr); - return reply; + g_dbus_error_register_error_domain ("gkd_secret_daemon_error", + &quark_volatile, + gkd_secret_daemon_error_entries, + G_N_ELEMENTS (gkd_secret_daemon_error_entries)); + return quark_volatile; } -DBusMessage * -gkd_secret_propagate_error (DBusMessage *message, +void +gkd_secret_propagate_error (GDBusMethodInvocation *invocation, const gchar *description, GError *error) { - DBusError derr = DBUS_ERROR_INIT; - - g_return_val_if_fail (error != NULL, NULL); - if (g_error_matches (error, GCK_ERROR, CKR_USER_NOT_LOGGED_IN) || g_error_matches (error, GCK_ERROR, CKR_PIN_INCORRECT)) { - dbus_set_error (&derr, INTERNAL_ERROR_DENIED, "The password was invalid"); - + g_dbus_method_invocation_return_error_literal (invocation, + GKD_SECRET_DAEMON_ERROR, + GKD_SECRET_DAEMON_ERROR_DENIED, + "The password was invalid"); } else if (g_error_matches (error, GCK_ERROR, CKR_WRAPPED_KEY_INVALID) || g_error_matches (error, GCK_ERROR, CKR_WRAPPED_KEY_LEN_RANGE) || g_error_matches (error, GCK_ERROR, CKR_MECHANISM_PARAM_INVALID)) { - dbus_set_error_const (&derr, DBUS_ERROR_INVALID_ARGS, - "The secret was transferred or encrypted in an invalid way."); - + g_dbus_method_invocation_return_error_literal (invocation, + G_DBUS_ERROR, + G_DBUS_ERROR_INVALID_ARGS, + "The secret was transferred or encrypted in an invalid way."); } else { g_warning ("%s: %s", description, egg_error_message (error)); - dbus_set_error (&derr, DBUS_ERROR_FAILED, "Couldn't create new collection"); + g_dbus_method_invocation_return_error_literal (invocation, + G_DBUS_ERROR, + G_DBUS_ERROR_FAILED, + "Couldn't create new collection"); } g_error_free (error); - return gkd_secret_error_to_reply (message, &derr); } diff --git a/daemon/dbus/gkd-secret-error.h b/daemon/dbus/gkd-secret-error.h index f5c483d7..8c40222b 100644 --- a/daemon/dbus/gkd-secret-error.h +++ b/daemon/dbus/gkd-secret-error.h @@ -25,15 +25,27 @@ #include <glib.h> -#include <dbus/dbus.h> +#include <gio/gio.h> -DBusMessage * gkd_secret_error_no_such_object (DBusMessage *message); +enum _GkdSecretDaemonError { + GKD_SECRET_DAEMON_ERROR_DENIED +}; -DBusMessage * gkd_secret_propagate_error (DBusMessage *message, +enum _GkdSecretError { + GKD_SECRET_ERROR_ALREADY_EXISTS, + GKD_SECRET_ERROR_IS_LOCKED, + GKD_SECRET_ERROR_NO_SESSION, + GKD_SECRET_ERROR_NO_SUCH_OBJECT +}; + +#define GKD_SECRET_DAEMON_ERROR gkd_secret_daemon_error_quark () +GQuark gkd_secret_daemon_error_quark (void); + +#define GKD_SECRET_ERROR gkd_secret_error_quark () +GQuark gkd_secret_error_quark (void); + +void gkd_secret_propagate_error (GDBusMethodInvocation *invocation, const gchar *description, GError *error); -DBusMessage * gkd_secret_error_to_reply (DBusMessage *message, - DBusError *derr); - #endif /* __GKD_SECRET_ERROR_H__ */ diff --git a/daemon/dbus/gkd-secret-introspect.c b/daemon/dbus/gkd-secret-introspect.c deleted file mode 100644 index 2d22338a..00000000 --- a/daemon/dbus/gkd-secret-introspect.c +++ /dev/null @@ -1,283 +0,0 @@ -/* - * gnome-keyring - * - * Copyright (C) 2011 Collabora Ltd. - * - * 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, see - * <http://www.gnu.org/licenses/>. - * - * Author: Stef Walter <stefw@collabora.co.uk> - */ - -#include "config.h" - -#include "gkd-secret-introspect.h" - -const gchar *gkd_secret_introspect_root = - "<!DOCTYPE node PUBLIC '-//freedesktop//DTD D-BUS Object Introspection 1.0//EN'\n" - " 'http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd'>\n" - "<node>\n" - " <node name='org/freedesktop/secrets'/>\n" - "</node>\n"; - -const gchar *gkd_secret_introspect_collection = - "<!DOCTYPE node PUBLIC '-//freedesktop//DTD D-BUS Object Introspection 1.0//EN'\n" - " 'http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd'>\n" - "<node>\n" - "\n" - " <interface name='org.freedesktop.DBus.Introspectable'>\n" - " <method name='Introspect'>\n" - " <arg name='data' direction='out' type='s'/>\n" - " </method>\n" - " </interface>\n" - "\n" - " <interface name='org.freedesktop.DBus.Properties'>\n" - " <method name='Get'>\n" - " <arg name='interface' direction='in' type='s'/>\n" - " <arg name='propname' direction='in' type='s'/>\n" - " <arg name='value' direction='out' type='v'/>\n" - " </method>\n" - " <method name='Set'>\n" - " <arg name='interface' direction='in' type='s'/>\n" - " <arg name='propname' direction='in' type='s'/>\n" - " <arg name='value' direction='in' type='v'/>\n" - " </method>\n" - " <method name='GetAll'>\n" - " <arg name='interface' direction='in' type='s'/>\n" - " <arg name='props' direction='out' type='a{sv}'/>\n" - " </method>\n" - " </interface>\n" - "\n" - " <interface name='org.freedesktop.Secret.Collection'>\n" - " <property name='Items' type='ao' access='read'/>\n" - " <property name='Label' type='s' access='readwrite'/>\n" - " <property name='Locked' type='b' access='read'/>\n" - " <property name='Created' type='t' access='read'/>\n" - " <property name='Modified' type='t' access='read'/>\n" - " <method name='Delete'>\n" - " <arg name='prompt' type='o' direction='out'/>\n" - " </method>\n" - " <method name='SearchItems'>\n" - " <arg name='attributes' type='a{ss}' direction='in'/>\n" - " <arg name='results' type='ao' direction='out'/>\n" - " </method>\n" - " <method name='CreateItem'>\n" - " <arg name='props' type='a{sv}' direction='in'/>\n" - " <arg name='secret' type='(oayays)' direction='in'/>\n" - " <arg name='replace' type='b' direction='in'/>\n" - " <arg name='item' type='o' direction='out'/>\n" - " <arg name='prompt' type='o' direction='out'/>\n" - " </method>\n" - " <signal name='ItemCreated'>\n" - " <arg name='item' type='o'/>\n" - " </signal>\n" - " <signal name='ItemDeleted'>\n" - " <arg name='item' type='o'/>\n" - " </signal>\n" - " <signal name='ItemChanged'>\n" - " <arg name='item' type='o'/>\n" - " </signal>\n" - " </interface>\n" - "\n" - "<!--@children@-->" - "</node>\n"; - -const gchar *gkd_secret_introspect_item = - "<!DOCTYPE node PUBLIC '-//freedesktop//DTD D-BUS Object Introspection 1.0//EN'\n" - " 'http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd'>\n" - "<node>\n" - "\n" - " <interface name='org.freedesktop.DBus.Introspectable'>\n" - " <method name='Introspect'>\n" - " <arg name='data' direction='out' type='s'/>\n" - " </method>\n" - " </interface>\n" - "\n" - " <interface name='org.freedesktop.DBus.Properties'>\n" - " <method name='Get'>\n" - " <arg name='interface' direction='in' type='s'/>\n" - " <arg name='propname' direction='in' type='s'/>\n" - " <arg name='value' direction='out' type='v'/>\n" - " </method>\n" - " <method name='Set'>\n" - " <arg name='interface' direction='in' type='s'/>\n" - " <arg name='propname' direction='in' type='s'/>\n" - " <arg name='value' direction='in' type='v'/>\n" - " </method>\n" - " <method name='GetAll'>\n" - " <arg name='interface' direction='in' type='s'/>\n" - " <arg name='props' direction='out' type='a{sv}'/>\n" - " </method>\n" - " </interface>\n" - "\n" - " <interface name='org.freedesktop.Secret.Item'>\n" - " <property name='Locked' type='b' access='read'/>\n" - " <property name='Attributes' type='a{ss}' access='readwrite'/>\n" - " <property name='Label' type='s' access='readwrite'/>\n" - " <property name='Type' type='s' access='readwrite'/>\n" - " <property name='Created' type='t' access='read'/>\n" - " <property name='Modified' type='t' access='read'/>\n" - " <method name='Delete'>\n" - " <arg name='prompt' type='o' direction='out'/>\n" - " </method>\n" - " <method name='GetSecret'>\n" - " <arg name='session' type='o' direction='in'/>\n" - " <arg name='secret' type='(oayays)' direction='out'/>\n" - " </method>\n" - " <method name='SetSecret'>\n" - " <arg name='secret' type='(oayays)' direction='in'/>\n" - " </method>\n" - " </interface>\n" - "\n" - "</node>\n"; - -const gchar *gkd_secret_introspect_prompt = - "<!DOCTYPE node PUBLIC '-//freedesktop//DTD D-BUS Object Introspection 1.0//EN'\n" - " 'http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd'>\n" - "<node>\n" - "\n" - " <interface name='org.freedesktop.DBus.Introspectable'>\n" - " <method name='Introspect'>\n" - " <arg name='data' direction='out' type='s'/>\n" - " </method>\n" - " </interface>\n" - "\n" - " <interface name='org.freedesktop.Secret.Prompt'>\n" - " <method name='Prompt'>\n" - " <arg name='window-id' type='s' direction='in'/>\n" - " </method>\n" - " <method name='Dismiss'>\n" - " </method>\n" - " <signal name='Completed'>\n" - " <arg name='dismissed' type='b'/>\n" - " <arg name='result' type='v'/>\n" - " </signal>\n" - " </interface>\n" - "\n" - "</node>\n"; - -const gchar *gkd_secret_introspect_service = - "<!DOCTYPE node PUBLIC '-//freedesktop//DTD D-BUS Object Introspection 1.0//EN'\n" - " 'http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd'>\n" - "<node>\n" - "\n" - " <interface name='org.freedesktop.DBus.Introspectable'>\n" - " <method name='Introspect'>\n" - " <arg name='data' direction='out' type='s'/>\n" - " </method>\n" - " </interface>\n" - "\n" - " <interface name='org.freedesktop.DBus.Properties'>\n" - " <method name='Get'>\n" - " <arg name='interface' direction='in' type='s'/>\n" - " <arg name='propname' direction='in' type='s'/>\n" - " <arg name='value' direction='out' type='v'/>\n" - " </method>\n" - " <method name='Set'>\n" - " <arg name='interface' direction='in' type='s'/>\n" - " <arg name='propname' direction='in' type='s'/>\n" - " <arg name='value' direction='in' type='v'/>\n" - " </method>\n" - " <method name='GetAll'>\n" - " <arg name='interface' direction='in' type='s'/>\n" - " <arg name='props' direction='out' type='a{sv}'/>\n" - " </method>\n" - " </interface>\n" - "\n" - " <interface name='org.freedesktop.Secret.Service'>\n" - "\n" - " <property name='Collections' type='ao' access='read'/>\n" - "\n" - " <method name='OpenSession'>\n" - " <arg name='algorithm' type='s' direction='in'/>\n" - " <arg name='input' type='v' direction='in'/>\n" - " <arg name='output' type='v' direction='out'/>\n" - " <arg name='result' type='o' direction='out'/>\n" - " </method>\n" - "\n" - " <method name='CreateCollection'>\n" - " <arg name='properties' type='a{sv}' direction='in'/>\n" - " <arg name='alias' type='s' direction='in'/>\n" - " <arg name='collection' type='o' direction='out'/>\n" - " <arg name='prompt' type='o' direction='out'/>\n" - " </method>\n" - "\n" - " <method name='SearchItems'>\n" - " <arg name='attributes' type='a{ss}' direction='in'/>\n" - " <arg name='unlocked' type='ao' direction='out'/>\n" - " <arg name='locked' type='ao' direction='out'/>\n" - " </method>\n" - "\n" - " <method name='Unlock'>\n" - " <arg name='objects' type='ao' direction='in'/>\n" - " <arg name='unlocked' type='ao' direction='out'/>\n" - " <arg name='prompt' type='o' direction='out'/>\n" - " </method>\n" - "\n" - " <method name='Lock'>\n" - " <arg name='objects' type='ao' direction='in'/>\n" - " <arg name='locked' type='ao' direction='out'/>\n" - " <arg name='Prompt' type='o' direction='out'/>\n" - " </method>\n" - "\n" - " <method name='GetSecrets'>\n" - " <arg name='items' type='ao' direction='in'/>\n" - " <arg name='session' type='o' direction='in'/>\n" - " <arg name='secrets' type='a{o(oayays)}' direction='out'/>\n" - " </method>\n" - "\n" - " <method name='ReadAlias'>\n" - " <arg name='name' type='s' direction='in'/>\n" - " <arg name='collection' type='o' direction='out'/>\n" - " </method>\n" - "\n" - " <method name='SetAlias'>\n" - " <arg name='name' type='s' direction='in'/>\n" - " <arg name='collection' type='o' direction='in'/>\n" - " </method>\n" - "\n" - " <signal name='CollectionCreated'>\n" - " <arg name='collection' type='o'/>\n" - " </signal>\n" - "\n" - " <signal name='CollectionDeleted'>\n" - " <arg name='collection' type='o'/>\n" - " </signal>\n" - "\n" - " <signal name='CollectionChanged'>\n" - " <arg name='collection' type='o'/>\n" - " </signal>\n" - "\n" - " </interface>\n" - "\n" - "<!--@children@-->" - "</node>\n"; - -const gchar *gkd_secret_introspect_session = - "<!DOCTYPE node PUBLIC '-//freedesktop//DTD D-BUS Object Introspection 1.0//EN'\n" - " 'http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd'>\n" - "<node>\n" - "\n" - " <interface name='org.freedesktop.DBus.Introspectable'>\n" - " <method name='Introspect'>\n" - " <arg name='data' direction='out' type='s'/>\n" - " </method>\n" - " </interface>\n" - "\n" - " <interface name='org.freedesktop.Secret.Session'>\n" - " <method name='Close'>\n" - " </method>\n" - " </interface>\n" - "\n" - "</node>\n"; diff --git a/daemon/dbus/gkd-secret-introspect.h b/daemon/dbus/gkd-secret-introspect.h deleted file mode 100644 index c0d1b301..00000000 --- a/daemon/dbus/gkd-secret-introspect.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * gnome-keyring - * - * Copyright (C) 2011 Collabora Ltd. - * - * 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, see - * <http://www.gnu.org/licenses/>. - * - * Author: Stef Walter <stefw@collabora.co.uk> - */ - -#ifndef __GKD_SECRET_INTROSPECT_H__ -#define __GKD_SECRET_INTROSPECT_H__ - -#include <glib.h> - -extern const gchar *gkd_secret_introspect_root; -extern const gchar *gkd_secret_introspect_collection; -extern const gchar *gkd_secret_introspect_item; -extern const gchar *gkd_secret_introspect_prompt; -extern const gchar *gkd_secret_introspect_service; -extern const gchar *gkd_secret_introspect_session; - -#endif /* __GKD_SECRET_INTROSPECT_H__ */ diff --git a/daemon/dbus/gkd-secret-lock.c b/daemon/dbus/gkd-secret-lock.c index c6650dbb..70e34839 100644 --- a/daemon/dbus/gkd-secret-lock.c +++ b/daemon/dbus/gkd-secret-lock.c @@ -30,7 +30,8 @@ #include <gck/gck.h> gboolean -gkd_secret_lock (GckObject *collection, DBusError *derr) +gkd_secret_lock (GckObject *collection, + GError **error_out) { GckBuilder builder = GCK_BUILDER_INIT; GError *error = NULL; @@ -49,7 +50,9 @@ gkd_secret_lock (GckObject *collection, DBusError *derr) if (error != NULL) { g_warning ("couldn't search for credential objects: %s", egg_error_message (error)); - dbus_set_error (derr, DBUS_ERROR_FAILED, "Couldn't lock collection"); + g_set_error_literal (error_out, G_DBUS_ERROR, + G_DBUS_ERROR_FAILED, + "Couldn't lock collection"); g_clear_error (&error); return FALSE; } @@ -67,7 +70,7 @@ gkd_secret_lock (GckObject *collection, DBusError *derr) gboolean gkd_secret_lock_all (GckSession *session, - DBusError *derr) + GError **error_out) { GckBuilder builder = GCK_BUILDER_INIT; GError *error = NULL; @@ -80,7 +83,7 @@ gkd_secret_lock_all (GckSession *session, objects = gck_session_find_objects (session, gck_builder_end (&builder), NULL, &error); if (error != NULL) { g_warning ("couldn't search for credential objects: %s", egg_error_message (error)); - dbus_set_error (derr, DBUS_ERROR_FAILED, "Couldn't lock service"); + g_set_error (error_out, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "Couldn't lock service"); g_clear_error (&error); return FALSE; } @@ -99,7 +102,7 @@ gkd_secret_lock_all (GckSession *session, objects = gck_session_find_objects (session, gck_builder_end (&builder), NULL, &error); if (error != NULL) { g_warning ("couldn't search for session items: %s", egg_error_message (error)); - dbus_set_error (derr, DBUS_ERROR_FAILED, "Couldn't lock service"); + g_set_error (error_out, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "Couldn't lock service"); g_clear_error (&error); return FALSE; } diff --git a/daemon/dbus/gkd-secret-lock.h b/daemon/dbus/gkd-secret-lock.h index b6035fa6..7c3fc0f0 100644 --- a/daemon/dbus/gkd-secret-lock.h +++ b/daemon/dbus/gkd-secret-lock.h @@ -25,12 +25,10 @@ #include <gck/gck.h> -#include <dbus/dbus.h> - gboolean gkd_secret_lock (GckObject *collection, - DBusError *derr); + GError **error); gboolean gkd_secret_lock_all (GckSession *session, - DBusError *derr); + GError **error); #endif /* __GKD_SECRET_LOCK_H__ */ diff --git a/daemon/dbus/gkd-secret-objects.c b/daemon/dbus/gkd-secret-objects.c index dda27608..495605a7 100644 --- a/daemon/dbus/gkd-secret-objects.c +++ b/daemon/dbus/gkd-secret-objects.c @@ -20,10 +20,7 @@ #include "config.h" -#include "gkd-dbus-util.h" - #include "gkd-secret-error.h" -#include "gkd-secret-introspect.h" #include "gkd-secret-objects.h" #include "gkd-secret-property.h" #include "gkd-secret-secret.h" @@ -31,6 +28,7 @@ #include "gkd-secret-session.h" #include "gkd-secret-types.h" #include "gkd-secret-util.h" +#include "gkd-secrets-generated.h" #include "egg/egg-error.h" @@ -38,241 +36,501 @@ #include <string.h> -enum { - PROP_0, - PROP_PKCS11_SLOT, - PROP_SERVICE -}; - struct _GkdSecretObjects { GObject parent; GkdSecretService *service; GckSlot *pkcs11_slot; + GHashTable *collections_to_skeletons; + GHashTable *items_to_skeletons; }; -static gchar * object_path_for_item (const gchar *base, - GckObject *item); -static gchar * object_path_for_collection (GckObject *collection); +/* ----------------------------------------------------------------------------- + * SKELETON + */ -static gchar * collection_path_for_item (GckObject *item); +typedef struct { + GkdOrgFreedesktopSecretCollectionSkeleton parent; + GkdSecretObjects *objects; +} GkdSecretCollectionSkeleton; +typedef struct { + GkdOrgFreedesktopSecretCollectionSkeletonClass parent_class; +} GkdSecretCollectionSkeletonClass; +typedef struct { + GkdOrgFreedesktopSecretItemSkeleton parent; + GkdSecretObjects *objects; +} GkdSecretItemSkeleton; +typedef struct { + GkdOrgFreedesktopSecretItemSkeletonClass parent_class; +} GkdSecretItemSkeletonClass; + +static GckObject * secret_objects_lookup_gck_object_for_path (GkdSecretObjects *self, + const gchar *sender, + const gchar *path, + GError **error); + +GType gkd_secret_collection_skeleton_get_type (void); +G_DEFINE_TYPE (GkdSecretCollectionSkeleton, gkd_secret_collection_skeleton, GKD_TYPE_ORG_FREEDESKTOP_SECRET_COLLECTION_SKELETON) +GType gkd_secret_item_skeleton_get_type (void); +G_DEFINE_TYPE (GkdSecretItemSkeleton, gkd_secret_item_skeleton, GKD_TYPE_ORG_FREEDESKTOP_SECRET_ITEM_SKELETON) -G_DEFINE_TYPE (GkdSecretObjects, gkd_secret_objects, G_TYPE_OBJECT); +static void +on_object_path_append_to_builder (GkdSecretObjects *self, + const gchar *path, + GckObject *object, + gpointer user_data) +{ + GVariantBuilder *builder = user_data; + g_variant_builder_add (builder, "o", path); +} -/* ----------------------------------------------------------------------------- - * INTERNAL - */ +static GVariant * +gkd_secret_objects_append_item_paths (GkdSecretObjects *self, + const gchar *caller, + const gchar *base) +{ + GVariantBuilder builder; + + g_return_val_if_fail (GKD_SECRET_IS_OBJECTS (self), NULL); + g_return_val_if_fail (base, NULL); + + g_variant_builder_init (&builder, G_VARIANT_TYPE ("ao")); + gkd_secret_objects_foreach_item (self, caller, base, on_object_path_append_to_builder, &builder); + + return g_variant_builder_end (&builder); +} + +static gchar ** +gkd_secret_objects_get_collection_items (GkdSecretObjects *self, + const gchar *collection_path) +{ + GVariant *items_variant; + gchar **items; + + items_variant = gkd_secret_objects_append_item_paths (self, NULL, collection_path); + items = g_variant_dup_objv (items_variant, NULL); + g_variant_unref (items_variant); + + return items; +} static gboolean -parse_object_path (GkdSecretObjects *self, const gchar *path, gchar **collection, gchar **item) +object_property_set (GkdSecretObjects *objects, + GckObject *object, + const gchar *prop_name, + GVariant *value, + GError **error_out) { - const gchar *replace; + GckBuilder builder = GCK_BUILDER_INIT; + GError *error = NULL; + gulong attr_type; - g_assert (self); - g_assert (path); - g_assert (collection); + /* What type of property is it? */ + if (!gkd_secret_property_get_type (prop_name, &attr_type)) { + g_set_error (error_out, G_DBUS_ERROR, + G_DBUS_ERROR_FAILED, + "Object does not have the '%s' property", + prop_name); + return FALSE; + } - if (!gkd_secret_util_parse_path (path, collection, item)) + /* Retrieve the actual attribute value */ + if (!gkd_secret_property_parse_variant (value, prop_name, &builder)) { + gck_builder_clear (&builder); + g_set_error (error_out, G_DBUS_ERROR, + G_DBUS_ERROR_FAILED, + "The property type or value was invalid: %s", + prop_name); return FALSE; + } - if (g_str_has_prefix (path, SECRET_ALIAS_PREFIX)) { - replace = gkd_secret_service_get_alias (self->service, *collection); - if (!replace) { - g_free (*collection); - *collection = NULL; - if (item) { - g_free (*item); - *item = NULL; - } - return FALSE; - } - g_free (*collection); - *collection = g_strdup (replace); + gck_object_set (object, gck_builder_end (&builder), NULL, &error); + + if (error != NULL) { + if (g_error_matches (error, GCK_ERROR, CKR_USER_NOT_LOGGED_IN)) + g_set_error (error_out, GKD_SECRET_ERROR, + GKD_SECRET_ERROR_IS_LOCKED, + "Cannot set property on a locked object"); + else + g_set_error (error_out, G_DBUS_ERROR, + G_DBUS_ERROR_FAILED, + "Couldn't set '%s' property: %s", + prop_name, egg_error_message (error)); + g_clear_error (&error); + return FALSE; } return TRUE; } -static DBusMessage* -object_property_get (GckObject *object, DBusMessage *message, - const gchar *prop_name) +static GVariant * +object_property_get (GkdSecretObjects *objects, + GckObject *object, + const gchar *prop_name, + GError **error_out) { - DBusMessageIter iter; GError *error = NULL; - DBusMessage *reply; GckAttribute attr; gpointer value; gsize length; + GVariant *res; - if (!gkd_secret_property_get_type (prop_name, &attr.type)) - return dbus_message_new_error_printf (message, DBUS_ERROR_FAILED, - "Object does not have the '%s' property", prop_name); + if (!gkd_secret_property_get_type (prop_name, &attr.type)) { + g_set_error (error_out, G_DBUS_ERROR, + G_DBUS_ERROR_FAILED, + "Object does not have the '%s' property", + prop_name); + return NULL; + } /* Retrieve the actual attribute */ attr.value = value = gck_object_get_data (object, attr.type, NULL, &length, &error); if (error != NULL) { - reply = dbus_message_new_error_printf (message, DBUS_ERROR_FAILED, - "Couldn't retrieve '%s' property: %s", - prop_name, egg_error_message (error)); + g_set_error (error_out, G_DBUS_ERROR, + G_DBUS_ERROR_FAILED, + "Couldn't retrieve '%s' property: %s", + prop_name, egg_error_message (error)); g_clear_error (&error); - return reply; + return NULL; } /* Marshall the data back out */ attr.length = length; - reply = dbus_message_new_method_return (message); - dbus_message_iter_init_append (reply, &iter); - gkd_secret_property_append_variant (&iter, &attr); + res = gkd_secret_property_append_variant (&attr); g_free (value); - return reply; + + return res; } -static DBusMessage* -object_property_set (GckObject *object, - DBusMessage *message, - DBusMessageIter *iter, - const gchar *prop_name) +static gboolean +gkd_secret_collection_skeleton_set_property_dbus (GDBusConnection *connection, + const gchar *sender, + const gchar *object_path, + const gchar *interface_name, + const gchar *property_name, + GVariant *value, + GError **error, + gpointer user_data) { - GckBuilder builder = GCK_BUILDER_INIT; - DBusMessage *reply; - GError *error = NULL; - gulong attr_type; + GkdSecretCollectionSkeleton *self = (GkdSecretCollectionSkeleton *) user_data; + GckObject *object; - g_return_val_if_fail (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_VARIANT, NULL); + object = secret_objects_lookup_gck_object_for_path (self->objects, sender, object_path, error); + if (!object) + return FALSE; - /* What type of property is it? */ - if (!gkd_secret_property_get_type (prop_name, &attr_type)) - return dbus_message_new_error_printf (message, DBUS_ERROR_FAILED, - "Object does not have the '%s' property", prop_name); + if (!object_property_set (self->objects, object, property_name, value, error)) { + g_object_unref (object); + return FALSE; + } - /* Retrieve the actual attribute value */ - if (!gkd_secret_property_parse_variant (iter, prop_name, &builder)) { - gck_builder_clear (&builder); - return dbus_message_new_error_printf (message, DBUS_ERROR_FAILED, - "The property type or value was invalid: %s", prop_name); + if (g_strcmp0 (property_name, "Label") == 0) { + gkd_org_freedesktop_secret_collection_set_label (GKD_ORG_FREEDESKTOP_SECRET_COLLECTION (self), + g_variant_get_string (value, NULL)); } - gck_object_set (object, gck_builder_end (&builder), NULL, &error); + gkd_secret_service_emit_collection_changed (self->objects->service, object_path); + g_object_unref (object); - if (error != NULL) { - if (g_error_matches (error, GCK_ERROR, CKR_USER_NOT_LOGGED_IN)) - reply = dbus_message_new_error (message, SECRET_ERROR_IS_LOCKED, - "Cannot set property on a locked object"); - else - reply = dbus_message_new_error_printf (message, DBUS_ERROR_FAILED, - "Couldn't set '%s' property: %s", - prop_name, egg_error_message (error)); - g_clear_error (&error); - return reply; + return TRUE; +} + +static GVariant * +gkd_secret_collection_skeleton_get_property_dbus (GDBusConnection *connection, + const gchar *sender, + const gchar *object_path, + const gchar *interface_name, + const gchar *property_name, + GError **error, + gpointer user_data) +{ + GkdSecretCollectionSkeleton *self = (GkdSecretCollectionSkeleton *) user_data; + GckObject *object; + GVariant *variant; + + object = secret_objects_lookup_gck_object_for_path (self->objects, sender, object_path, error); + if (!object) + return FALSE; + + if (g_strcmp0 (property_name, "Items") == 0) + variant = gkd_secret_objects_append_item_paths (self->objects, sender, object_path); + else + variant = object_property_get (self->objects, object, property_name, error); + + + g_object_unref (object); + return variant; +} + +static GDBusInterfaceVTable * +gkd_secret_collection_skeleton_get_vtable (GDBusInterfaceSkeleton *skeleton) +{ + static GDBusInterfaceVTable vtable; + GDBusInterfaceVTable *parent_vtable; + + parent_vtable = G_DBUS_INTERFACE_SKELETON_CLASS (gkd_secret_collection_skeleton_parent_class)->get_vtable (skeleton); + + (&vtable)->get_property = gkd_secret_collection_skeleton_get_property_dbus; + (&vtable)->set_property = gkd_secret_collection_skeleton_set_property_dbus; + (&vtable)->method_call = parent_vtable->method_call; + + return &vtable; +} + +static void +gkd_secret_collection_skeleton_class_init (GkdSecretCollectionSkeletonClass *klass) +{ + GDBusInterfaceSkeletonClass *skclass = G_DBUS_INTERFACE_SKELETON_CLASS (klass); + skclass->get_vtable = gkd_secret_collection_skeleton_get_vtable; +} + +static void +gkd_secret_collection_skeleton_init (GkdSecretCollectionSkeleton *self) +{ +} + +static GkdOrgFreedesktopSecretCollection * +gkd_secret_collection_skeleton_new (GkdSecretObjects *objects) +{ + GkdOrgFreedesktopSecretCollection *self = g_object_new (gkd_secret_collection_skeleton_get_type (), NULL); + ((GkdSecretCollectionSkeleton *) self)->objects = objects; + return self; +} + +static gboolean +gkd_secret_item_skeleton_set_property_dbus (GDBusConnection *connection, + const gchar *sender, + const gchar *object_path, + const gchar *interface_name, + const gchar *property_name, + GVariant *value, + GError **error, + gpointer user_data) +{ + GkdSecretItemSkeleton *self = (GkdSecretItemSkeleton *) user_data; + GckObject *object; + + object = secret_objects_lookup_gck_object_for_path (self->objects, sender, object_path, error); + if (!object) + return FALSE; + + if (!object_property_set (self->objects, object, property_name, value, error)) { + g_object_unref (object); + return FALSE; + } + + if (g_strcmp0 (property_name, "Attributes") == 0) { + gkd_org_freedesktop_secret_item_set_attributes (GKD_ORG_FREEDESKTOP_SECRET_ITEM (self), + g_variant_get_variant (value)); + } else if (g_strcmp0 (property_name, "Label") == 0) { + gkd_org_freedesktop_secret_item_set_label (GKD_ORG_FREEDESKTOP_SECRET_ITEM (self), + g_variant_get_string (value, NULL)); } - return dbus_message_new_method_return (message); + gkd_secret_objects_emit_item_changed (self->objects, object); + g_object_unref (object); + + return TRUE; } -static DBusMessage* -item_property_get (GckObject *object, DBusMessage *message) +static GVariant * +gkd_secret_item_skeleton_get_property_dbus (GDBusConnection *connection, + const gchar *sender, + const gchar *object_path, + const gchar *interface_name, + const gchar *property_name, + GError **error, + gpointer user_data) { - const gchar *interface; - const gchar *name; + GkdSecretItemSkeleton *self = (GkdSecretItemSkeleton *) user_data; + GckObject *object; + GVariant *variant; - if (!dbus_message_get_args (message, NULL, DBUS_TYPE_STRING, &interface, - DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID)) + object = secret_objects_lookup_gck_object_for_path (self->objects, sender, object_path, error); + if (!object) return NULL; - if (!gkd_dbus_interface_match (SECRET_ITEM_INTERFACE, interface)) - return dbus_message_new_error_printf (message, DBUS_ERROR_FAILED, - "Object does not have properties on interface '%s'", - interface); + variant = object_property_get (self->objects, object, property_name, error); + g_object_unref (object); - return object_property_get (object, message, name); + return variant; } -static DBusMessage* -item_property_set (GkdSecretObjects *self, - GckObject *object, - DBusMessage *message) +static GDBusInterfaceVTable * +gkd_secret_item_skeleton_get_vtable (GDBusInterfaceSkeleton *skeleton) { - DBusMessageIter iter; - const char *interface; - const char *name; - DBusMessage *reply; + static GDBusInterfaceVTable vtable; + GDBusInterfaceVTable *parent_vtable; - if (!dbus_message_has_signature (message, "ssv")) - return NULL; + parent_vtable = G_DBUS_INTERFACE_SKELETON_CLASS (gkd_secret_item_skeleton_parent_class)->get_vtable (skeleton); - dbus_message_iter_init (message, &iter); - dbus_message_iter_get_basic (&iter, &interface); - dbus_message_iter_next (&iter); - dbus_message_iter_get_basic (&iter, &name); - dbus_message_iter_next (&iter); + (&vtable)->get_property = gkd_secret_item_skeleton_get_property_dbus; + (&vtable)->set_property = gkd_secret_item_skeleton_set_property_dbus; + (&vtable)->method_call = parent_vtable->method_call; - if (!gkd_dbus_interface_match (SECRET_ITEM_INTERFACE, interface)) - return dbus_message_new_error_printf (message, DBUS_ERROR_FAILED, - "Object does not have properties on interface '%s'", - interface); + return &vtable; +} - reply = object_property_set (object, message, &iter, name); +static void +gkd_secret_item_skeleton_class_init (GkdSecretItemSkeletonClass *klass) +{ + GDBusInterfaceSkeletonClass *skclass = G_DBUS_INTERFACE_SKELETON_CLASS (klass); + skclass->get_vtable = gkd_secret_item_skeleton_get_vtable; +} - /* Notify everyone a property changed */ - if (reply && dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_METHOD_RETURN) - gkd_secret_objects_emit_item_changed (self, object, name, NULL); +static void +gkd_secret_item_skeleton_init (GkdSecretItemSkeleton *self) +{ +} - return reply; +static GkdOrgFreedesktopSecretItem * +gkd_secret_item_skeleton_new (GkdSecretObjects *objects) +{ + GkdOrgFreedesktopSecretItem *self = g_object_new (gkd_secret_item_skeleton_get_type (), NULL); + ((GkdSecretItemSkeleton *) self)->objects = objects; + return self; } -static DBusMessage* -item_property_getall (GckObject *object, DBusMessage *message) +enum { + PROP_0, + PROP_PKCS11_SLOT, + PROP_SERVICE +}; + +static gchar * object_path_for_item (const gchar *base, + GckObject *item); + +static gchar * object_path_for_collection (GckObject *collection); + +static gchar * collection_path_for_item (GckObject *item); + +G_DEFINE_TYPE (GkdSecretObjects, gkd_secret_objects, G_TYPE_OBJECT); + +/* ----------------------------------------------------------------------------- + * INTERNAL + */ + +static gboolean +parse_object_path (GkdSecretObjects *self, const gchar *path, gchar **collection, gchar **item) +{ + const gchar *replace; + + g_assert (self); + g_assert (path); + g_assert (collection); + + if (!gkd_secret_util_parse_path (path, collection, item)) + return FALSE; + + if (g_str_has_prefix (path, SECRET_ALIAS_PREFIX)) { + replace = gkd_secret_service_get_alias (self->service, *collection); + if (!replace) { + g_free (*collection); + *collection = NULL; + if (item) { + g_free (*item); + *item = NULL; + } + return FALSE; + } + g_free (*collection); + *collection = g_strdup (replace); + } + + return TRUE; +} + +static GckObject * +secret_objects_lookup_gck_object_for_path (GkdSecretObjects *self, + const gchar *sender, + const gchar *path, + GError **error_out) +{ + GckBuilder builder = GCK_BUILDER_INIT; + GList *objects; + GckSession *session; + gchar *c_ident; + gchar *i_ident; + GckObject *object = NULL; + GError *error = NULL; + + g_return_val_if_fail (path, FALSE); + + if (!parse_object_path (self, path, &c_ident, &i_ident) || !c_ident) + goto out; + + /* The session we're using to access the object */ + session = gkd_secret_service_get_pkcs11_session (self->service, sender); + g_return_val_if_fail (session, FALSE); + + if (i_ident) { + gck_builder_add_ulong (&builder, CKA_CLASS, CKO_SECRET_KEY); + gck_builder_add_string (&builder, CKA_G_COLLECTION, c_ident); + gck_builder_add_string (&builder, CKA_ID, i_ident); + } else { + gck_builder_add_ulong (&builder, CKA_CLASS, CKO_G_COLLECTION); + gck_builder_add_string (&builder, CKA_ID, c_ident); + } + + objects = gck_session_find_objects (session, gck_builder_end (&builder), NULL, &error); + + g_free (c_ident); + g_free (i_ident); + + if (error != NULL) { + g_warning ("couldn't lookup object: %s: %s", path, egg_error_message (error)); + g_clear_error (&error); + } + + if (!objects) + goto out; + + object = g_object_ref (objects->data); + gck_list_unref_free (objects); + + out: + if (!object) + g_set_error (error_out, GKD_SECRET_ERROR, + GKD_SECRET_ERROR_NO_SUCH_OBJECT, + "The '%s' object does not exist", + path); + + return object; +} + +static GckObject * +secret_objects_lookup_gck_object_for_invocation (GkdSecretObjects *self, + GDBusMethodInvocation *invocation) { - GckAttributes *attrs; - DBusMessageIter iter; - DBusMessageIter array; GError *error = NULL; - DBusMessage *reply; - const gchar *interface; + GckObject *object; - if (!dbus_message_get_args (message, NULL, DBUS_TYPE_STRING, &interface, DBUS_TYPE_INVALID)) - return NULL; + object = secret_objects_lookup_gck_object_for_path (self, + g_dbus_method_invocation_get_sender (invocation), + g_dbus_method_invocation_get_object_path (invocation), + &error); - if (!gkd_dbus_interface_match (SECRET_ITEM_INTERFACE, interface)) - return dbus_message_new_error_printf (message, DBUS_ERROR_FAILED, - "Object does not have properties on interface '%s'", - interface); - - attrs = gck_object_get (object, NULL, &error, - CKA_LABEL, - CKA_G_SCHEMA, - CKA_G_LOCKED, - CKA_G_CREATED, - CKA_G_MODIFIED, - CKA_G_FIELDS, - GCK_INVALID); - - if (error != NULL) - return dbus_message_new_error_printf (message, DBUS_ERROR_FAILED, - "Couldn't retrieve properties: %s", - egg_error_message (error)); - - reply = dbus_message_new_method_return (message); - - dbus_message_iter_init_append (reply, &iter); - dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "{sv}", &array); - gkd_secret_property_append_all (&array, attrs); - dbus_message_iter_close_container (&iter, &array); - return reply; + if (!object) + g_dbus_method_invocation_take_error (invocation, error); + + return object; } -static DBusMessage* -item_method_delete (GkdSecretObjects *self, GckObject *object, DBusMessage *message) +static gboolean +item_method_delete (GkdOrgFreedesktopSecretItem *skeleton, + GDBusMethodInvocation *invocation, + GkdSecretObjects *self) { GError *error = NULL; gchar *collection_path; gchar *item_path; - DBusMessage *reply; - const gchar *prompt; GckObject *collection; + GckObject *object; - if (!dbus_message_get_args (message, NULL, DBUS_TYPE_INVALID)) - return NULL; + object = secret_objects_lookup_gck_object_for_invocation (self, invocation); + if (!object) { + return TRUE; + } collection_path = collection_path_for_item (object); item_path = object_path_for_item (NULL, object); @@ -284,113 +542,108 @@ item_method_delete (GkdSecretObjects *self, GckObject *object, DBusMessage *mess g_object_unref (collection); } - prompt = "/"; /* No prompt necessary */ - reply = dbus_message_new_method_return (message); - dbus_message_append_args (reply, DBUS_TYPE_OBJECT_PATH, &prompt, DBUS_TYPE_INVALID); + /* No prompt necessary */ + gkd_org_freedesktop_secret_item_complete_delete (skeleton, invocation, "/"); } else { if (g_error_matches (error, GCK_ERROR, CKR_USER_NOT_LOGGED_IN)) - reply = dbus_message_new_error_printf (message, SECRET_ERROR_IS_LOCKED, - "Cannot delete a locked item"); + g_dbus_method_invocation_return_error_literal (invocation, GKD_SECRET_ERROR, + GKD_SECRET_ERROR_IS_LOCKED, + "Cannot delete a locked item"); else - reply = dbus_message_new_error_printf (message, DBUS_ERROR_FAILED, - "Couldn't delete collection: %s", - egg_error_message (error)); + g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, + G_DBUS_ERROR_FAILED, + "Couldn't delete collection: %s", + egg_error_message (error)); g_clear_error (&error); } g_free (collection_path); g_free (item_path); - return reply; + g_object_unref (object); + + return TRUE; } -static DBusMessage* -item_method_get_secret (GkdSecretObjects *self, GckObject *item, DBusMessage *message) +static gboolean +item_method_get_secret (GkdOrgFreedesktopSecretItem *skeleton, + GDBusMethodInvocation *invocation, + gchar *path, + GkdSecretObjects *self) { - DBusError derr = DBUS_ERROR_INIT; GkdSecretSession *session; GkdSecretSecret *secret; - DBusMessage *reply; - DBusMessageIter iter; - const char *path; + GckObject *item; + GError *error = NULL; - if (!dbus_message_get_args (message, NULL, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID)) - return NULL; + item = secret_objects_lookup_gck_object_for_invocation (self, invocation); + if (!item) { + return TRUE; + } - session = gkd_secret_service_lookup_session (self->service, path, dbus_message_get_sender (message)); - if (session == NULL) - return dbus_message_new_error (message, SECRET_ERROR_NO_SESSION, "The session does not exist"); + session = gkd_secret_service_lookup_session (self->service, path, + g_dbus_method_invocation_get_sender (invocation)); + if (session == NULL) { + g_dbus_method_invocation_return_error_literal (invocation, GKD_SECRET_ERROR, + GKD_SECRET_ERROR_NO_SESSION, + "The session does not exist"); + goto cleanup; + } - secret = gkd_secret_session_get_item_secret (session, item, &derr); - if (secret == NULL) - return gkd_secret_error_to_reply (message, &derr); + secret = gkd_secret_session_get_item_secret (session, item, &error); + if (secret == NULL) { + g_dbus_method_invocation_take_error (invocation, error); + goto cleanup; + } - reply = dbus_message_new_method_return (message); - dbus_message_iter_init_append (reply, &iter); - gkd_secret_secret_append (secret, &iter); + gkd_org_freedesktop_secret_item_complete_get_secret (skeleton, invocation, + gkd_secret_secret_append (secret)); gkd_secret_secret_free (secret); - return reply; + + cleanup: + g_object_unref (item); + return TRUE; } -static DBusMessage* -item_method_set_secret (GkdSecretObjects *self, GckObject *item, DBusMessage *message) +static gboolean +item_method_set_secret (GkdOrgFreedesktopSecretItem *skeleton, + GDBusMethodInvocation *invocation, + GVariant *secret_variant, + GkdSecretObjects *self) { - DBusError derr = DBUS_ERROR_INIT; - DBusMessageIter iter; GkdSecretSecret *secret; const char *caller; + GckObject *item; + GError *error = NULL; - if (!dbus_message_has_signature (message, "(oayays)")) - return NULL; - dbus_message_iter_init (message, &iter); - secret = gkd_secret_secret_parse (self->service, message, &iter, &derr); - if (secret == NULL) - return gkd_secret_error_to_reply (message, &derr); + item = secret_objects_lookup_gck_object_for_invocation (self, invocation); + if (!item) { + return TRUE; + } - caller = dbus_message_get_sender (message); - g_return_val_if_fail (caller, NULL); + caller = g_dbus_method_invocation_get_sender (invocation); + secret = gkd_secret_secret_parse (self->service, caller, secret_variant, &error); + if (error != NULL) { + goto cleanup; + } - gkd_secret_session_set_item_secret (secret->session, item, secret, &derr); + gkd_secret_session_set_item_secret (secret->session, item, secret, &error); gkd_secret_secret_free (secret); - if (dbus_error_is_set (&derr)) - return gkd_secret_error_to_reply (message, &derr); - - return dbus_message_new_method_return (message); -} - -static DBusMessage* -item_message_handler (GkdSecretObjects *self, GckObject *object, DBusMessage *message) -{ - /* org.freedesktop.Secret.Item.Delete() */ - if (dbus_message_is_method_call (message, SECRET_ITEM_INTERFACE, "Delete")) - return item_method_delete (self, object, message); - - /* org.freedesktop.Secret.Session.GetSecret() */ - else if (dbus_message_is_method_call (message, SECRET_ITEM_INTERFACE, "GetSecret")) - return item_method_get_secret (self, object, message); - - /* org.freedesktop.Secret.Session.SetSecret() */ - else if (dbus_message_is_method_call (message, SECRET_ITEM_INTERFACE, "SetSecret")) - return item_method_set_secret (self, object, message); - - /* org.freedesktop.DBus.Properties.Get */ - if (dbus_message_is_method_call (message, DBUS_INTERFACE_PROPERTIES, "Get")) - return item_property_get (object, message); - - /* org.freedesktop.DBus.Properties.Set */ - else if (dbus_message_is_method_call (message, DBUS_INTERFACE_PROPERTIES, "Set")) - return item_property_set (self, object, message); - - /* org.freedesktop.DBus.Properties.GetAll */ - else if (dbus_message_is_method_call (message, DBUS_INTERFACE_PROPERTIES, "GetAll")) - return item_property_getall (object, message); + if (error != NULL) { + goto cleanup; + } - else if (dbus_message_has_interface (message, DBUS_INTERFACE_INTROSPECTABLE)) - return gkd_dbus_introspect_handle (message, gkd_secret_introspect_item, NULL); + cleanup: + if (error != NULL) { + g_dbus_method_invocation_take_error (invocation, error); + } else { + gkd_org_freedesktop_secret_item_complete_set_secret (skeleton, invocation); + } - return NULL; + g_object_unref (item); + return TRUE; } static void @@ -428,120 +681,15 @@ item_cleanup_search_results (GckSession *session, GList *items, *unlocked = g_list_reverse (*unlocked); } -static DBusMessage* -collection_property_get (GkdSecretObjects *self, GckObject *object, DBusMessage *message) -{ - DBusMessageIter iter; - DBusMessage *reply; - const gchar *interface; - const gchar *name; - - if (!dbus_message_get_args (message, NULL, DBUS_TYPE_STRING, &interface, - DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID)) - return NULL; - - if (!gkd_dbus_interface_match (SECRET_COLLECTION_INTERFACE, interface)) - return dbus_message_new_error_printf (message, DBUS_ERROR_FAILED, - "Object does not have properties on interface '%s'", - interface); - - /* Special case, the Items property */ - 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, dbus_message_get_path (message), &iter, message); - return reply; - } - - return object_property_get (object, message, name); -} - -static DBusMessage* -collection_property_set (GkdSecretObjects *self, GckObject *object, DBusMessage *message) -{ - DBusMessageIter iter; - DBusMessage *reply; - const char *interface; - const char *name; - - if (!dbus_message_has_signature (message, "ssv")) - return NULL; - - dbus_message_iter_init (message, &iter); - dbus_message_iter_get_basic (&iter, &interface); - dbus_message_iter_next (&iter); - dbus_message_iter_get_basic (&iter, &name); - dbus_message_iter_next (&iter); - - if (!gkd_dbus_interface_match (SECRET_COLLECTION_INTERFACE, interface)) - return dbus_message_new_error_printf (message, DBUS_ERROR_FAILED, - "Object does not have properties on interface '%s'", - interface); - - reply = object_property_set (object, message, &iter, name); - - /* Notify everyone a property changed */ - if (reply && dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_METHOD_RETURN) - gkd_secret_objects_emit_collection_changed (self, object, name, NULL); - - return reply; -} - -static DBusMessage* -collection_property_getall (GkdSecretObjects *self, GckObject *object, DBusMessage *message) -{ - GckAttributes *attrs; - DBusMessageIter iter; - DBusMessageIter array; - DBusMessageIter dict; - GError *error = NULL; - DBusMessage *reply; - const gchar *name; - const gchar *interface; - - if (!dbus_message_get_args (message, NULL, DBUS_TYPE_STRING, &interface, DBUS_TYPE_INVALID)) - return NULL; - - if (!gkd_dbus_interface_match (SECRET_COLLECTION_INTERFACE, interface)) - return dbus_message_new_error_printf (message, DBUS_ERROR_FAILED, - "Object does not have properties on interface '%s'", - interface); - - attrs = gck_object_get (object, NULL, &error, - CKA_LABEL, - CKA_G_LOCKED, - CKA_G_CREATED, - CKA_G_MODIFIED, - GCK_INVALID); - - if (error != NULL) - return dbus_message_new_error_printf (message, DBUS_ERROR_FAILED, - "Couldn't retrieve properties: %s", - egg_error_message (error)); - - reply = dbus_message_new_method_return (message); - - dbus_message_iter_init_append (reply, &iter); - dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "{sv}", &array); - - /* Append all the usual properties */ - gkd_secret_property_append_all (&array, attrs); - - /* Append the Items property */ - 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, dbus_message_get_path (message), &dict, message); - dbus_message_iter_close_container (&array, &dict); - - dbus_message_iter_close_container (&iter, &array); - return reply; -} - -static DBusMessage* -collection_method_search_items (GkdSecretObjects *self, GckObject *object, DBusMessage *message) +static gboolean +collection_method_search_items (GkdOrgFreedesktopSecretCollection *skeleton, + GDBusMethodInvocation *invocation, + GVariant *attributes, + GkdSecretObjects *self) { - return gkd_secret_objects_handle_search_items (self, message, dbus_message_get_path (message), FALSE); + return gkd_secret_objects_handle_search_items (self, invocation, attributes, + g_dbus_method_invocation_get_object_path (invocation), + FALSE); } static GckObject* @@ -654,53 +802,55 @@ object_path_for_collection (GckObject *collection) return path; } -static DBusMessage* -collection_method_create_item (GkdSecretObjects *self, GckObject *object, DBusMessage *message) +static gboolean +collection_method_create_item (GkdOrgFreedesktopSecretCollection *skeleton, + GDBusMethodInvocation *invocation, + GVariant *properties, + GVariant *secret_variant, + gboolean replace, + GkdSecretObjects *self) { GckBuilder builder = GCK_BUILDER_INIT; GckSession *pkcs11_session = NULL; - DBusError derr = DBUS_ERROR_INIT; GkdSecretSecret *secret = NULL; - dbus_bool_t replace = FALSE; GckAttributes *attrs = NULL; const GckAttribute *fields; - DBusMessageIter iter, array; GckObject *item = NULL; - const gchar *prompt; const gchar *base; GError *error = NULL; - DBusMessage *reply = NULL; gchar *path = NULL; gchar *identifier; gboolean created = FALSE; + GckObject *object; - /* Parse the message */ - if (!dbus_message_has_signature (message, "a{sv}(oayays)b")) - return NULL; - if (!dbus_message_iter_init (message, &iter)) - g_return_val_if_reached (NULL); - dbus_message_iter_recurse (&iter, &array); - if (!gkd_secret_property_parse_all (&array, SECRET_ITEM_INTERFACE, &builder)) { - reply = dbus_message_new_error (message, DBUS_ERROR_INVALID_ARGS, - "Invalid properties argument"); + object = secret_objects_lookup_gck_object_for_invocation (self, invocation); + if (!object) { + return TRUE; + } + + if (!gkd_secret_property_parse_all (properties, SECRET_ITEM_INTERFACE, &builder)) { + g_dbus_method_invocation_return_error_literal (invocation, G_DBUS_ERROR, + G_DBUS_ERROR_INVALID_ARGS, + "Invalid properties argument"); goto cleanup; } - dbus_message_iter_next (&iter); - secret = gkd_secret_secret_parse (self->service, message, &iter, &derr); + + base = g_dbus_method_invocation_get_object_path (invocation); + secret = gkd_secret_secret_parse (self->service, g_dbus_method_invocation_get_sender (invocation), + secret_variant, &error); + if (secret == NULL) { - reply = gkd_secret_error_to_reply (message, &derr); + g_dbus_method_invocation_take_error (invocation, error); + error = NULL; goto cleanup; } - dbus_message_iter_next (&iter); - dbus_message_iter_get_basic (&iter, &replace); - base = dbus_message_get_path (message); if (!parse_object_path (self, base, &identifier, NULL)) - g_return_val_if_reached (NULL); - g_return_val_if_fail (identifier, NULL); + g_return_val_if_reached (FALSE); + g_return_val_if_fail (identifier, FALSE); pkcs11_session = gck_object_get_session (object); - g_return_val_if_fail (pkcs11_session, NULL); + g_return_val_if_fail (pkcs11_session, FALSE); attrs = gck_attributes_ref_sink (gck_builder_end (&builder)); @@ -727,41 +877,31 @@ collection_method_create_item (GkdSecretObjects *self, GckObject *object, DBusMe } /* Set the secret */ - if (!gkd_secret_session_set_item_secret (secret->session, item, secret, &derr)) { + if (!gkd_secret_session_set_item_secret (secret->session, item, secret, &error)) { if (created) /* If we created, then try to destroy on failure */ gck_object_destroy (item, NULL, NULL); goto cleanup; } path = object_path_for_item (base, item); - gkd_secret_objects_emit_item_created (self, object, item); + gkd_secret_objects_emit_item_created (self, object, path); - /* Build up the item identifier */ - reply = dbus_message_new_method_return (message); - dbus_message_iter_init_append (reply, &iter); - dbus_message_iter_append_basic (&iter, DBUS_TYPE_OBJECT_PATH, &path); - prompt = "/"; - dbus_message_iter_append_basic (&iter, DBUS_TYPE_OBJECT_PATH, &prompt); + gkd_org_freedesktop_secret_collection_complete_create_item (skeleton, invocation, path, "/"); cleanup: if (error) { - if (!reply) { - if (g_error_matches (error, GCK_ERROR, CKR_USER_NOT_LOGGED_IN)) - reply = dbus_message_new_error_printf (message, SECRET_ERROR_IS_LOCKED, - "Cannot create an item in a locked collection"); - else - reply = dbus_message_new_error_printf (message, DBUS_ERROR_FAILED, - "Couldn't create item: %s", egg_error_message (error)); - } + if (g_error_matches (error, GCK_ERROR, CKR_USER_NOT_LOGGED_IN)) + g_dbus_method_invocation_return_error_literal (invocation, GKD_SECRET_ERROR, + GKD_SECRET_ERROR_IS_LOCKED, + "Cannot create an item in a locked collection"); + else + g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, + G_DBUS_ERROR_FAILED, + "Couldn't create item: %s", + egg_error_message (error)); g_clear_error (&error); } - if (dbus_error_is_set (&derr)) { - if (!reply) - reply = dbus_message_new_error (message, derr.name, derr.message); - dbus_error_free (&derr); - } - gkd_secret_secret_free (secret); gck_attributes_unref (attrs); if (item) @@ -769,127 +909,68 @@ cleanup: if (pkcs11_session) g_object_unref (pkcs11_session); g_free (path); + g_object_unref (object); - return reply; + return TRUE; } -static DBusMessage* -collection_method_delete (GkdSecretObjects *self, GckObject *object, DBusMessage *message) +static gboolean +collection_method_delete (GkdOrgFreedesktopSecretCollection *skeleton, + GDBusMethodInvocation *invocation, + GkdSecretObjects *self) { GError *error = NULL; - DBusMessage *reply; - const gchar *prompt; gchar *path; + GckObject *object; - if (!dbus_message_get_args (message, NULL, DBUS_TYPE_INVALID)) - return NULL; + object = secret_objects_lookup_gck_object_for_invocation (self, invocation); + if (!object) { + return TRUE; + } path = object_path_for_collection (object); - g_return_val_if_fail (path != NULL, NULL); + g_return_val_if_fail (path != NULL, FALSE); if (!gck_object_destroy (object, NULL, &error)) { - reply = dbus_message_new_error_printf (message, DBUS_ERROR_FAILED, + g_dbus_method_invocation_return_error (invocation, + G_DBUS_ERROR, + G_DBUS_ERROR_FAILED, "Couldn't delete collection: %s", egg_error_message (error)); g_clear_error (&error); - g_free (path); - return reply; + goto cleanup; } /* Notify the callers that a collection was deleted */ gkd_secret_service_emit_collection_deleted (self->service, path); - g_free (path); - - prompt = "/"; - reply = dbus_message_new_method_return (message); - dbus_message_append_args (reply, DBUS_TYPE_OBJECT_PATH, &prompt, DBUS_TYPE_INVALID); - return reply; -} - -static void -on_each_path_append_to_array (GkdSecretObjects *self, - const gchar *path, - GckObject *object, - gpointer user_data) -{ - GPtrArray *array = user_data; - g_ptr_array_add (array, g_strdup (path)); -} + gkd_org_freedesktop_secret_collection_complete_delete (skeleton, invocation, "/"); -static DBusMessage * -collection_introspect (GkdSecretObjects *self, - GckObject *object, - DBusMessage *message) -{ - GPtrArray *names; - DBusMessage *reply; - - names = g_ptr_array_new_with_free_func (g_free); - gkd_secret_objects_foreach_item (self, message, dbus_message_get_path (message), - on_each_path_append_to_array, names); - g_ptr_array_add (names, NULL); - - reply = gkd_dbus_introspect_handle (message, gkd_secret_introspect_collection, - (const gchar **)names->pdata); - - g_ptr_array_unref (names); - return reply; -} - -static DBusMessage* -collection_message_handler (GkdSecretObjects *self, GckObject *object, DBusMessage *message) -{ - /* org.freedesktop.Secret.Collection.Delete() */ - if (dbus_message_is_method_call (message, SECRET_COLLECTION_INTERFACE, "Delete")) - return collection_method_delete (self, object, message); - - /* org.freedesktop.Secret.Collection.SearchItems() */ - if (dbus_message_is_method_call (message, SECRET_COLLECTION_INTERFACE, "SearchItems")) - return collection_method_search_items (self, object, message); - - /* org.freedesktop.Secret.Collection.CreateItem() */ - if (dbus_message_is_method_call (message, SECRET_COLLECTION_INTERFACE, "CreateItem")) - return collection_method_create_item (self, object, message); - - /* org.freedesktop.DBus.Properties.Get() */ - if (dbus_message_is_method_call (message, DBUS_INTERFACE_PROPERTIES, "Get")) - return collection_property_get (self, object, message); - - /* org.freedesktop.DBus.Properties.Set() */ - else if (dbus_message_is_method_call (message, DBUS_INTERFACE_PROPERTIES, "Set")) - return collection_property_set (self, object, message); - - /* org.freedesktop.DBus.Properties.GetAll() */ - else if (dbus_message_is_method_call (message, DBUS_INTERFACE_PROPERTIES, "GetAll")) - return collection_property_getall (self, object, message); - - /* org.freedesktop.DBus.Introspectable.Introspect() */ - else if (dbus_message_has_interface (message, DBUS_INTERFACE_INTROSPECTABLE)) - return collection_introspect (self, object, message); + cleanup: + g_free (path); + g_object_unref (object); - return NULL; + return TRUE; } /* ----------------------------------------------------------------------------- * OBJECT */ -static GObject* -gkd_secret_objects_constructor (GType type, guint n_props, GObjectConstructParam *props) +static void +skeleton_destroy_func (gpointer user_data) { - GkdSecretObjects *self = GKD_SECRET_OBJECTS (G_OBJECT_CLASS (gkd_secret_objects_parent_class)->constructor(type, n_props, props)); - - g_return_val_if_fail (self, NULL); - g_return_val_if_fail (self->pkcs11_slot, NULL); - g_return_val_if_fail (self->service, NULL); - - return G_OBJECT (self); + GDBusInterfaceSkeleton *skeleton = user_data; + g_dbus_interface_skeleton_unexport (skeleton); + g_object_unref (skeleton); } static void gkd_secret_objects_init (GkdSecretObjects *self) { - + self->collections_to_skeletons = g_hash_table_new_full (g_str_hash, g_str_equal, + g_free, skeleton_destroy_func); + self->items_to_skeletons = g_hash_table_new_full (g_str_hash, g_str_equal, + g_free, skeleton_destroy_func); } static void @@ -908,6 +989,9 @@ gkd_secret_objects_dispose (GObject *obj) self->service = NULL; } + g_clear_pointer (&self->collections_to_skeletons, g_hash_table_unref); + g_clear_pointer (&self->items_to_skeletons, g_hash_table_unref); + G_OBJECT_CLASS (gkd_secret_objects_parent_class)->dispose (obj); } @@ -971,7 +1055,6 @@ gkd_secret_objects_class_init (GkdSecretObjectsClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - gobject_class->constructor = gkd_secret_objects_constructor; gobject_class->dispose = gkd_secret_objects_dispose; gobject_class->finalize = gkd_secret_objects_finalize; gobject_class->set_property = gkd_secret_objects_set_property; @@ -997,65 +1080,6 @@ gkd_secret_objects_get_pkcs11_slot (GkdSecretObjects *self) return self->pkcs11_slot; } -DBusMessage* -gkd_secret_objects_dispatch (GkdSecretObjects *self, DBusMessage *message) -{ - GckBuilder builder = GCK_BUILDER_INIT; - DBusMessage *reply = NULL; - GError *error = NULL; - GList *objects; - GckSession *session; - gchar *c_ident; - gchar *i_ident; - gboolean is_item; - const char *path; - - g_return_val_if_fail (GKD_SECRET_IS_OBJECTS (self), NULL); - g_return_val_if_fail (message, NULL); - - path = dbus_message_get_path (message); - g_return_val_if_fail (path, NULL); - - if (!parse_object_path (self, path, &c_ident, &i_ident) || !c_ident) - return gkd_secret_error_no_such_object (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_val_if_fail (session, NULL); - - if (i_ident) { - is_item = TRUE; - gck_builder_add_ulong (&builder, CKA_CLASS, CKO_SECRET_KEY); - gck_builder_add_string (&builder, CKA_G_COLLECTION, c_ident); - gck_builder_add_string (&builder, CKA_ID, i_ident); - } else { - is_item = FALSE; - gck_builder_add_ulong (&builder, CKA_CLASS, CKO_G_COLLECTION); - gck_builder_add_string (&builder, CKA_ID, c_ident); - } - - objects = gck_session_find_objects (session, gck_builder_end (&builder), NULL, &error); - - g_free (c_ident); - g_free (i_ident); - - if (error != NULL) { - g_warning ("couldn't lookup object: %s: %s", path, egg_error_message (error)); - g_clear_error (&error); - } - - if (!objects) - return gkd_secret_error_no_such_object (message); - - if (is_item) - reply = item_message_handler (self, objects->data, message); - else - reply = collection_message_handler (self, objects->data, message); - - gck_list_unref_free (objects); - return reply; -} - GckObject* gkd_secret_objects_lookup_collection (GkdSecretObjects *self, const gchar *caller, const gchar *path) @@ -1162,7 +1186,7 @@ objects_foreach_item (GkdSecretObjects *self, void gkd_secret_objects_foreach_item (GkdSecretObjects *self, - DBusMessage *message, + const gchar *caller, const gchar *base, GkdSecretObjectsForeach callback, gpointer user_data) @@ -1178,11 +1202,10 @@ gkd_secret_objects_foreach_item (GkdSecretObjects *self, g_return_if_fail (callback != NULL); /* The session we're using to access the object */ - if (message == NULL) { + if (caller == NULL) { session = gkd_secret_service_internal_pkcs11_session (self->service); } else { - session = gkd_secret_service_get_pkcs11_session (self->service, - dbus_message_get_sender (message)); + session = gkd_secret_service_get_pkcs11_session (self->service, caller); } if (!parse_object_path (self, base, &identifier, NULL)) @@ -1205,42 +1228,9 @@ gkd_secret_objects_foreach_item (GkdSecretObjects *self, g_free (identifier); } -static void -on_object_path_append_to_iter (GkdSecretObjects *self, - const gchar *path, - GckObject *object, - gpointer user_data) -{ - DBusMessageIter *array = user_data; - dbus_message_iter_append_basic (array, DBUS_TYPE_OBJECT_PATH, &path); -} - -void -gkd_secret_objects_append_item_paths (GkdSecretObjects *self, - const gchar *base, - DBusMessageIter *iter, - DBusMessage *message) -{ - DBusMessageIter variant; - DBusMessageIter array; - - g_return_if_fail (GKD_SECRET_IS_OBJECTS (self)); - g_return_if_fail (base); - g_return_if_fail (iter); - - - dbus_message_iter_open_container (iter, DBUS_TYPE_VARIANT, "ao", &variant); - dbus_message_iter_open_container (&variant, DBUS_TYPE_ARRAY, "o", &array); - - gkd_secret_objects_foreach_item (self, message, base, on_object_path_append_to_iter, &array); - - dbus_message_iter_close_container (&variant, &array); - dbus_message_iter_close_container (iter, &variant); -} - void gkd_secret_objects_foreach_collection (GkdSecretObjects *self, - DBusMessage *message, + const gchar *caller, GkdSecretObjectsForeach callback, gpointer user_data) { @@ -1256,11 +1246,10 @@ gkd_secret_objects_foreach_collection (GkdSecretObjects *self, g_return_if_fail (callback); /* The session we're using to access the object */ - if (message == NULL) { + if (caller == NULL) { session = gkd_secret_service_internal_pkcs11_session (self->service); } else { - session = gkd_secret_service_get_pkcs11_session (self->service, - dbus_message_get_sender (message)); + session = gkd_secret_service_get_pkcs11_session (self->service, caller); } gck_builder_add_ulong (&builder, CKA_CLASS, CKO_G_COLLECTION); @@ -1292,61 +1281,50 @@ gkd_secret_objects_foreach_collection (GkdSecretObjects *self, gck_list_unref_free (collections); } -void +GVariant * gkd_secret_objects_append_collection_paths (GkdSecretObjects *self, - DBusMessageIter *iter, - DBusMessage *message) + const gchar *caller) { - DBusMessageIter variant; - DBusMessageIter array; + GVariantBuilder builder; - g_return_if_fail (GKD_SECRET_IS_OBJECTS (self)); - g_return_if_fail (iter != NULL); - - dbus_message_iter_open_container (iter, DBUS_TYPE_VARIANT, "ao", &variant); - dbus_message_iter_open_container (&variant, DBUS_TYPE_ARRAY, "o", &array); + g_return_val_if_fail (GKD_SECRET_IS_OBJECTS (self), NULL); - gkd_secret_objects_foreach_collection (self, message, on_object_path_append_to_iter, &array); + g_variant_builder_init (&builder, G_VARIANT_TYPE ("ao")); + gkd_secret_objects_foreach_collection (self, caller, on_object_path_append_to_builder, &builder); - dbus_message_iter_close_container (&variant, &array); - dbus_message_iter_close_container (iter, &variant); + return g_variant_builder_end (&builder); } -DBusMessage* +gboolean gkd_secret_objects_handle_search_items (GkdSecretObjects *self, - DBusMessage *message, + GDBusMethodInvocation *invocation, + GVariant *attributes, const gchar *base, gboolean separate_locked) { GckBuilder builder = GCK_BUILDER_INIT; - DBusMessageIter iter; - DBusMessageIter array; GckObject *search; GckSession *session; - DBusMessage *reply; GError *error = NULL; gchar *identifier; gpointer data; gsize n_data; GList *locked, *unlocked; GList *items; + GVariantBuilder result; - 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; - - dbus_message_iter_init (message, &iter); - if (!gkd_secret_property_parse_fields (&iter, &builder)) { + if (!gkd_secret_property_parse_fields (attributes, &builder)) { gck_builder_clear (&builder); - return dbus_message_new_error (message, DBUS_ERROR_FAILED, - "Invalid data in attributes argument"); + g_dbus_method_invocation_return_error_literal (invocation, + G_DBUS_ERROR, + G_DBUS_ERROR_FAILED, + "Invalid data in attributes argument"); + return TRUE; } if (base != NULL) { if (!parse_object_path (self, base, &identifier, NULL)) - g_return_val_if_reached (NULL); + g_return_val_if_reached (FALSE); gck_builder_add_string (&builder, CKA_G_COLLECTION, identifier); g_free (identifier); } @@ -1355,18 +1333,20 @@ gkd_secret_objects_handle_search_items (GkdSecretObjects *self, gck_builder_add_boolean (&builder, CKA_TOKEN, FALSE); /* 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_val_if_fail (session, NULL); + session = gkd_secret_service_get_pkcs11_session (self->service, g_dbus_method_invocation_get_sender (invocation)); + g_return_val_if_fail (session, FALSE); /* Create the search object */ search = gck_session_create_object (session, gck_builder_end (&builder), NULL, &error); if (error != NULL) { - reply = dbus_message_new_error_printf (message, DBUS_ERROR_FAILED, + g_dbus_method_invocation_return_error (invocation, + G_DBUS_ERROR, + G_DBUS_ERROR_FAILED, "Couldn't search for items: %s", egg_error_message (error)); g_clear_error (&error); - return reply; + return TRUE; } /* Get the matched item handles, and delete the search object */ @@ -1375,116 +1355,108 @@ gkd_secret_objects_handle_search_items (GkdSecretObjects *self, g_object_unref (search); if (error != NULL) { - reply = dbus_message_new_error_printf (message, DBUS_ERROR_FAILED, + g_dbus_method_invocation_return_error (invocation, + G_DBUS_ERROR, + G_DBUS_ERROR_FAILED, "Couldn't retrieve matched items: %s", egg_error_message (error)); g_clear_error (&error); - return reply; + return TRUE; } /* Build a list of object handles */ items = gck_objects_from_handle_array (session, data, n_data / sizeof (CK_OBJECT_HANDLE)); g_free (data); - /* Prepare the reply message */ - reply = dbus_message_new_method_return (message); - dbus_message_iter_init_append (reply, &iter); - /* Filter out the locked items */ if (separate_locked) { + GVariant *unlocked_variant, *locked_variant; + item_cleanup_search_results (session, items, &locked, &unlocked); - dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "o", &array); - objects_foreach_item (self, unlocked, NULL, on_object_path_append_to_iter, &array); - dbus_message_iter_close_container (&iter, &array); + g_variant_builder_init (&result, G_VARIANT_TYPE ("ao")); + objects_foreach_item (self, unlocked, NULL, on_object_path_append_to_builder, &result); + unlocked_variant = g_variant_builder_end (&result); - dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "o", &array); - objects_foreach_item (self, locked, NULL, on_object_path_append_to_iter, &array); - dbus_message_iter_close_container (&iter, &array); + g_variant_builder_init (&result, G_VARIANT_TYPE ("ao")); + objects_foreach_item (self, locked, NULL, on_object_path_append_to_builder, &result); + locked_variant = g_variant_builder_end (&result); g_list_free (locked); g_list_free (unlocked); + g_dbus_method_invocation_return_value (invocation, + g_variant_new ("(@ao@ao)", + unlocked_variant, + locked_variant)); } else { - dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "o", &array); - objects_foreach_item (self, items, NULL, on_object_path_append_to_iter, &array); - dbus_message_iter_close_container (&iter, &array); + g_variant_builder_init (&result, G_VARIANT_TYPE ("ao")); + objects_foreach_item (self, items, NULL, on_object_path_append_to_builder, &result); + + g_dbus_method_invocation_return_value (invocation, + g_variant_new ("(@ao)", g_variant_builder_end (&result))); } gck_list_unref_free (items); - return reply; + return TRUE; } -DBusMessage* -gkd_secret_objects_handle_get_secrets (GkdSecretObjects *self, DBusMessage *message) +gboolean +gkd_secret_objects_handle_get_secrets (GkdSecretObjects *self, + GDBusMethodInvocation *invocation, + const gchar **paths, + const gchar *session_path) { - DBusError derr = DBUS_ERROR_INIT; GkdSecretSession *session; GkdSecretSecret *secret; - DBusMessage *reply; GckObject *item; - DBusMessageIter iter, array, dict; - const char *session_path; const char *caller; - char **paths; - int n_paths, i; - - if (!dbus_message_get_args (message, NULL, - DBUS_TYPE_ARRAY, DBUS_TYPE_OBJECT_PATH, &paths, &n_paths, - DBUS_TYPE_OBJECT_PATH, &session_path, - DBUS_TYPE_INVALID)) - return NULL; - - caller = dbus_message_get_sender (message); - g_return_val_if_fail (caller, NULL); + int i; + GVariantBuilder builder; + GError *error = NULL; - session = gkd_secret_service_lookup_session (self->service, session_path, - dbus_message_get_sender (message)); - if (session == NULL) - return dbus_message_new_error (message, SECRET_ERROR_NO_SESSION, "The session does not exist"); + caller = g_dbus_method_invocation_get_sender (invocation); + session = gkd_secret_service_lookup_session (self->service, session_path, caller); + if (session == NULL) { + g_dbus_method_invocation_return_error_literal (invocation, GKD_SECRET_ERROR, + GKD_SECRET_ERROR_NO_SESSION, + "The session does not exist"); + return TRUE; + } - reply = dbus_message_new_method_return (message); - dbus_message_iter_init_append (reply, &iter); - dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "{o(oayays)}", &array); + g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{o(oayays)")); - for (i = 0; i < n_paths; ++i) { + for (i = 0; paths[i] != NULL; ++i) { /* Try to find the item, if it doesn't exist, just ignore */ item = gkd_secret_objects_lookup_item (self, caller, paths[i]); if (!item) continue; - secret = gkd_secret_session_get_item_secret (session, item, &derr); + secret = gkd_secret_session_get_item_secret (session, item, &error); g_object_unref (item); if (secret == NULL) { /* We ignore is locked, and just leave out from response */ - if (dbus_error_has_name (&derr, SECRET_ERROR_IS_LOCKED)) { - dbus_error_free (&derr); + if (g_error_matches (error, GKD_SECRET_ERROR, GKD_SECRET_ERROR_IS_LOCKED)) { + g_clear_error (&error); continue; /* All other errors stop the operation */ } else { - dbus_message_unref (reply); - reply = dbus_message_new_error (message, derr.name, derr.message); - dbus_error_free (&derr); - break; + g_dbus_method_invocation_take_error (invocation, error); + return TRUE; } } - dbus_message_iter_open_container (&array, DBUS_TYPE_DICT_ENTRY, NULL, &dict); - dbus_message_iter_append_basic (&dict, DBUS_TYPE_OBJECT_PATH, &(paths[i])); - gkd_secret_secret_append (secret, &dict); + g_variant_builder_add (&builder, "o@(oayays)", paths[i], gkd_secret_secret_append (secret)); gkd_secret_secret_free (secret); - dbus_message_iter_close_container (&array, &dict); } - if (i == n_paths) - dbus_message_iter_close_container (&iter, &array); - dbus_free_string_array (paths); - - return reply; + g_dbus_method_invocation_return_value (invocation, + g_variant_new ("(@a{o(oayays)})", g_variant_builder_end (&builder))); + return TRUE; } static void @@ -1493,196 +1465,150 @@ on_each_item_emit_locked (GkdSecretObjects *self, GckObject *object, gpointer user_data) { - gkd_secret_objects_emit_item_changed (self, object, "Locked", NULL); + GkdOrgFreedesktopSecretItem *skeleton; + GVariant *value; + GError *error = NULL; + + skeleton = g_hash_table_lookup (self->items_to_skeletons, path); + if (skeleton == NULL) { + g_warning ("setting locked state on item %s, but no skeleton found", path); + return; + } + + value = object_property_get (self, object, "Locked", &error); + if (!value) { + g_warning ("setting locked state on item %s, but no property value: %s", + path, error->message); + g_error_free (error); + return; + } + + gkd_org_freedesktop_secret_item_set_locked (skeleton, g_variant_get_boolean (value)); + g_variant_unref (value); + + gkd_secret_objects_emit_item_changed (self, object); } void gkd_secret_objects_emit_collection_locked (GkdSecretObjects *self, GckObject *collection) { - const gchar *collection_path; + gchar *collection_path; + GkdOrgFreedesktopSecretCollection *skeleton; + GVariant *value; + GError *error = NULL; collection_path = object_path_for_collection (collection); gkd_secret_objects_foreach_item (self, NULL, collection_path, on_each_item_emit_locked, NULL); - gkd_secret_objects_emit_collection_changed (self, collection, "Locked", NULL); + skeleton = g_hash_table_lookup (self->collections_to_skeletons, collection_path); + if (skeleton == NULL) { + g_warning ("setting locked state on collection %s, but no skeleton found", collection_path); + return; + } + + value = object_property_get (self, collection, "Locked", &error); + if (!value) { + g_warning ("setting locked state on item %s, but no property value: %s", + collection_path, error->message); + g_error_free (error); + return; + } + + gkd_org_freedesktop_secret_collection_set_locked (skeleton, g_variant_get_boolean (value)); + g_variant_unref (value); + + gkd_secret_service_emit_collection_changed (self->service, collection_path); + g_free (collection_path); } static void -emit_object_properties_changed (GkdSecretObjects *self, - GckObject *object, - const gchar *path, - const gchar *iface, - va_list va) +gkd_secret_objects_register_item (GkdSecretObjects *self, + const gchar *item_path) { - gchar *collection_path; - const gchar *propname; - DBusMessage *message; - DBusMessageIter iter; - DBusMessageIter array; - DBusMessageIter dict; - CK_ATTRIBUTE_TYPE type; - GckAttributes *attrs; + GkdOrgFreedesktopSecretItem *skeleton; GError *error = NULL; - gboolean items = FALSE; - GArray *types; - - types = g_array_new (FALSE, FALSE, sizeof (CK_ATTRIBUTE_TYPE)); - while ((propname = va_arg (va, const gchar *)) != NULL) { - /* Special case the Items property */ - if (g_str_equal (propname, "Items")) { - items = TRUE; - continue; - } - - if (gkd_secret_property_get_type (propname, &type)) - g_array_append_val (types, type); - else - g_warning ("invalid property: %s", propname); + skeleton = g_hash_table_lookup (self->items_to_skeletons, item_path); + if (skeleton != NULL) { + g_warning ("asked to register item %p, but it's already registered", item_path); + return; } - attrs = gck_object_get_full (object, (CK_ATTRIBUTE_TYPE *)types->data, - types->len, NULL, &error); - g_array_free (types, TRUE); + skeleton = gkd_secret_item_skeleton_new (self); + g_hash_table_insert (self->items_to_skeletons, g_strdup (item_path), skeleton); + g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (skeleton), + gkd_secret_service_get_connection (self->service), + item_path, &error); if (error != NULL) { - g_warning ("couldn't retrieve properties: %s", egg_error_message (error)); - return; - } - - message = dbus_message_new_signal (path, DBUS_INTERFACE_PROPERTIES, - "PropertiesChanged"); - - dbus_message_iter_init_append (message, &iter); - dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &iface); - dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "{sv}", &array); - gkd_secret_property_append_all (&array, attrs); - - /* Append the Items property */ - if (items) { - collection_path = object_path_for_collection (object); - dbus_message_iter_open_container (&array, DBUS_TYPE_DICT_ENTRY, NULL, &dict); - propname = "Items"; - dbus_message_iter_append_basic (&dict, DBUS_TYPE_STRING, &propname); - gkd_secret_objects_append_item_paths (self, collection_path, &dict, NULL); - dbus_message_iter_close_container (&array, &dict); - g_free (collection_path); + g_warning ("could not register secret item on session bus: %s", error->message); + g_error_free (error); } - dbus_message_iter_close_container (&iter, &array); - dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "s", &array); - dbus_message_iter_close_container (&iter, &array); - - if (!dbus_connection_send (gkd_secret_service_get_connection (self->service), - message, NULL)) - g_return_if_reached (); - dbus_message_unref (message); - - gck_attributes_unref (attrs); + g_signal_connect (skeleton, "handle-delete", + G_CALLBACK (item_method_delete), self); + g_signal_connect (skeleton, "handle-get-secret", + G_CALLBACK (item_method_get_secret), self); + g_signal_connect (skeleton, "handle-set-secret", + G_CALLBACK (item_method_set_secret), self); } -void -gkd_secret_objects_emit_collection_changed (GkdSecretObjects *self, - GckObject *collection, - ...) +static void +gkd_secret_objects_unregister_item (GkdSecretObjects *self, + const gchar *item_path) { - DBusMessage *message; - gchar *collection_path; - va_list va; - - g_return_if_fail (GKD_SECRET_IS_OBJECTS (self)); - g_return_if_fail (GCK_OBJECT (collection)); - - collection_path = object_path_for_collection (collection); - - message = dbus_message_new_signal (SECRET_SERVICE_PATH, - SECRET_SERVICE_INTERFACE, - "CollectionChanged"); - dbus_message_append_args (message, DBUS_TYPE_OBJECT_PATH, &collection_path, - DBUS_TYPE_INVALID); - - if (!dbus_connection_send (gkd_secret_service_get_connection (self->service), - message, NULL)) - g_return_if_reached (); - - dbus_message_unref (message); - - va_start (va, collection); - emit_object_properties_changed (self, collection, collection_path, - SECRET_COLLECTION_INTERFACE, va); - va_end (va); - - g_free (collection_path); + if (!g_hash_table_remove (self->items_to_skeletons, item_path)) { + g_warning ("asked to unregister item %p, but it wasn't found", item_path); + return; + } } void gkd_secret_objects_emit_item_created (GkdSecretObjects *self, GckObject *collection, - GckObject *item) + const gchar *item_path) { - DBusMessage *message; + GkdOrgFreedesktopSecretCollection *skeleton; gchar *collection_path; - gchar *item_path; + gchar **items; g_return_if_fail (GKD_SECRET_IS_OBJECTS (self)); g_return_if_fail (GCK_OBJECT (collection)); - g_return_if_fail (GCK_OBJECT (item)); + g_return_if_fail (item_path != NULL); collection_path = object_path_for_collection (collection); - item_path = object_path_for_item (collection_path, item); - - message = dbus_message_new_signal (collection_path, - SECRET_COLLECTION_INTERFACE, - "ItemCreated"); - dbus_message_append_args (message, DBUS_TYPE_OBJECT_PATH, &item_path, - DBUS_TYPE_INVALID); + skeleton = g_hash_table_lookup (self->collections_to_skeletons, collection_path); + g_return_if_fail (skeleton != NULL); - if (!dbus_connection_send (gkd_secret_service_get_connection (self->service), - message, NULL)) - g_return_if_reached (); - - dbus_message_unref (message); + gkd_secret_objects_register_item (self, item_path); + gkd_org_freedesktop_secret_collection_emit_item_created (skeleton, item_path); - gkd_secret_objects_emit_collection_changed (self, collection, "Items", NULL); + items = gkd_secret_objects_get_collection_items (self, collection_path); + gkd_org_freedesktop_secret_collection_set_items (skeleton, (const gchar **) items); - g_free (item_path); g_free (collection_path); + g_strfreev (items); } void gkd_secret_objects_emit_item_changed (GkdSecretObjects *self, - GckObject *item, - ...) + GckObject *item) { - DBusMessage *message; + GkdOrgFreedesktopSecretCollection *skeleton; gchar *collection_path; gchar *item_path; - va_list va; g_return_if_fail (GKD_SECRET_IS_OBJECTS (self)); g_return_if_fail (GCK_OBJECT (item)); collection_path = collection_path_for_item (item); - item_path = object_path_for_item (collection_path, item); - - message = dbus_message_new_signal (collection_path, - SECRET_COLLECTION_INTERFACE, - "ItemChanged"); - dbus_message_append_args (message, DBUS_TYPE_OBJECT_PATH, &item_path, - DBUS_TYPE_INVALID); - - if (!dbus_connection_send (gkd_secret_service_get_connection (self->service), - message, NULL)) - g_return_if_reached (); + skeleton = g_hash_table_lookup (self->collections_to_skeletons, collection_path); + g_return_if_fail (skeleton != NULL); - dbus_message_unref (message); - - va_start (va, item); - emit_object_properties_changed (self, item, item_path, - SECRET_ITEM_INTERFACE, va); - va_end (va); + item_path = object_path_for_item (collection_path, item); + gkd_org_freedesktop_secret_collection_emit_item_changed (skeleton, item_path); g_free (item_path); g_free (collection_path); @@ -1693,27 +1619,82 @@ gkd_secret_objects_emit_item_deleted (GkdSecretObjects *self, GckObject *collection, const gchar *item_path) { - DBusMessage *message; + GkdOrgFreedesktopSecretCollection *skeleton; gchar *collection_path; + gchar **items; g_return_if_fail (GKD_SECRET_IS_OBJECTS (self)); g_return_if_fail (GCK_OBJECT (collection)); g_return_if_fail (item_path != NULL); collection_path = object_path_for_collection (collection); + skeleton = g_hash_table_lookup (self->collections_to_skeletons, collection_path); + g_return_if_fail (skeleton != NULL); - message = dbus_message_new_signal (collection_path, - SECRET_COLLECTION_INTERFACE, - "ItemDeleted"); - dbus_message_append_args (message, DBUS_TYPE_OBJECT_PATH, &item_path, - DBUS_TYPE_INVALID); + gkd_secret_objects_unregister_item (self, item_path); + gkd_org_freedesktop_secret_collection_emit_item_deleted (skeleton, item_path); - if (!dbus_connection_send (gkd_secret_service_get_connection (self->service), - message, NULL)) - g_return_if_reached (); + items = gkd_secret_objects_get_collection_items (self, collection_path); + gkd_org_freedesktop_secret_collection_set_items (skeleton, (const gchar **) items); - dbus_message_unref (message); + g_strfreev (items); g_free (collection_path); +} + +static void +gkd_secret_objects_init_collection_items (GkdSecretObjects *self, + const gchar *collection_path) +{ + gchar **items; + gint idx; + + items = gkd_secret_objects_get_collection_items (self, collection_path); + for (idx = 0; items[idx] != NULL; idx++) + gkd_secret_objects_register_item (self, items[idx]); + + g_strfreev (items); +} + +void +gkd_secret_objects_register_collection (GkdSecretObjects *self, + const gchar *collection_path) +{ + GkdOrgFreedesktopSecretCollection *skeleton; + GError *error = NULL; + + skeleton = g_hash_table_lookup (self->collections_to_skeletons, collection_path); + if (skeleton != NULL) { + g_warning ("asked to register collection %p, but it's already registered", collection_path); + return; + } + + skeleton = gkd_secret_collection_skeleton_new (self); + g_hash_table_insert (self->collections_to_skeletons, g_strdup (collection_path), skeleton); + + g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (skeleton), + gkd_secret_service_get_connection (self->service), + collection_path, &error); + if (error != NULL) { + g_warning ("could not register secret collection on session bus: %s", error->message); + g_error_free (error); + } + + g_signal_connect (skeleton, "handle-create-item", + G_CALLBACK (collection_method_create_item), self); + g_signal_connect (skeleton, "handle-delete", + G_CALLBACK (collection_method_delete), self); + g_signal_connect (skeleton, "handle-search-items", + G_CALLBACK (collection_method_search_items), self); + + gkd_secret_objects_init_collection_items (self, collection_path); +} - gkd_secret_objects_emit_collection_changed (self, collection, "Items", NULL); +void +gkd_secret_objects_unregister_collection (GkdSecretObjects *self, + const gchar *collection_path) +{ + if (!g_hash_table_remove (self->collections_to_skeletons, collection_path)) { + g_warning ("asked to unregister collection %p, but it wasn't found", collection_path); + return; + } } diff --git a/daemon/dbus/gkd-secret-objects.h b/daemon/dbus/gkd-secret-objects.h index ca224ff2..e9b61d4e 100644 --- a/daemon/dbus/gkd-secret-objects.h +++ b/daemon/dbus/gkd-secret-objects.h @@ -27,8 +27,6 @@ #include <glib-object.h> -#include <dbus/dbus.h> - #define GKD_SECRET_TYPE_OBJECTS (gkd_secret_objects_get_type ()) #define GKD_SECRET_OBJECTS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GKD_SECRET_TYPE_OBJECTS, GkdSecretObjects)) #define GKD_SECRET_OBJECTS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GKD_SECRET_TYPE_OBJECTS, GkdSecretObjectsClass)) @@ -49,36 +47,30 @@ typedef void (*GkdSecretObjectsForeach) (GkdSecretObject GType gkd_secret_objects_get_type (void); -DBusMessage* gkd_secret_objects_dispatch (GkdSecretObjects *self, - DBusMessage *message); - -DBusMessage* gkd_secret_objects_handle_search_items (GkdSecretObjects *self, - DBusMessage *message, +gboolean gkd_secret_objects_handle_search_items (GkdSecretObjects *self, + GDBusMethodInvocation *invocation, + GVariant *attributes, const gchar *base, gboolean separate_locked); -DBusMessage* gkd_secret_objects_handle_get_secrets (GkdSecretObjects *self, - DBusMessage *message); +gboolean gkd_secret_objects_handle_get_secrets (GkdSecretObjects *self, + GDBusMethodInvocation *invocation, + const gchar **paths, + const gchar *session_path); void gkd_secret_objects_foreach_collection (GkdSecretObjects *self, - DBusMessage *message, + const gchar *caller, GkdSecretObjectsForeach callback, gpointer user_data); void gkd_secret_objects_foreach_item (GkdSecretObjects *self, - DBusMessage *message, + const gchar *caller, const gchar *base, GkdSecretObjectsForeach callback, gpointer user_data); -void gkd_secret_objects_append_collection_paths (GkdSecretObjects *self, - DBusMessageIter *iter, - DBusMessage *message); - -void gkd_secret_objects_append_item_paths (GkdSecretObjects *self, - const gchar *base, - DBusMessageIter *iter, - DBusMessage *message); +GVariant* gkd_secret_objects_append_collection_paths (GkdSecretObjects *self, + const gchar *caller); GckSlot* gkd_secret_objects_get_pkcs11_slot (GkdSecretObjects *self); @@ -93,20 +85,21 @@ GckObject* gkd_secret_objects_lookup_item (GkdSecretObjec void gkd_secret_objects_emit_collection_locked (GkdSecretObjects *self, GckObject *collection); -void gkd_secret_objects_emit_collection_changed (GkdSecretObjects *self, - GckObject *collection, - ...) G_GNUC_NULL_TERMINATED; - void gkd_secret_objects_emit_item_created (GkdSecretObjects *self, GckObject *collection, - GckObject *item); + const gchar *item_path); void gkd_secret_objects_emit_item_changed (GkdSecretObjects *self, - GckObject *item, - ...) G_GNUC_NULL_TERMINATED; + GckObject *item); void gkd_secret_objects_emit_item_deleted (GkdSecretObjects *self, GckObject *collection, const gchar *item_path); +void gkd_secret_objects_register_collection (GkdSecretObjects *self, + const gchar *collection_path); + +void gkd_secret_objects_unregister_collection (GkdSecretObjects *self, + const gchar *collection_path); + #endif /* __GKD_SECRET_OBJECTS_H__ */ diff --git a/daemon/dbus/gkd-secret-prompt.c b/daemon/dbus/gkd-secret-prompt.c index 21c4a5ab..464a4e20 100644 --- a/daemon/dbus/gkd-secret-prompt.c +++ b/daemon/dbus/gkd-secret-prompt.c @@ -20,10 +20,9 @@ #include "config.h" -#include "gkd-dbus-util.h" #include "gkd-secret-dispatch.h" +#include "gkd-secret-error.h" #include "gkd-secret-exchange.h" -#include "gkd-secret-introspect.h" #include "gkd-secret-service.h" #include "gkd-secret-prompt.h" #include "gkd-secret-objects.h" @@ -31,6 +30,7 @@ #include "gkd-secret-session.h" #include "gkd-secret-types.h" #include "gkd-secret-util.h" +#include "gkd-secrets-generated.h" #include "egg/egg-dh.h" #include "egg/egg-error.h" @@ -48,6 +48,7 @@ struct _GkdSecretPromptPrivate { gchar *object_path; GkdSecretService *service; GkdSecretExchange *exchange; + GkdOrgFreedesktopSecretPrompt *skeleton; GCancellable *cancellable; gboolean prompted; gboolean completed; @@ -65,23 +66,13 @@ static guint unique_prompt_number = 0; static void emit_completed (GkdSecretPrompt *self, gboolean dismissed) { - DBusMessage *signal; - DBusMessageIter iter; - dbus_bool_t bval; - - signal = dbus_message_new_signal (self->pv->object_path, SECRET_PROMPT_INTERFACE, - "Completed"); - dbus_message_set_destination (signal, self->pv->caller); - dbus_message_iter_init_append (signal, &iter); - - bval = dismissed; - dbus_message_iter_append_basic (&iter, DBUS_TYPE_BOOLEAN, &bval); + GVariant *variant; g_return_if_fail (GKD_SECRET_PROMPT_GET_CLASS (self)->encode_result); - GKD_SECRET_PROMPT_GET_CLASS (self)->encode_result (self, &iter); + variant = GKD_SECRET_PROMPT_GET_CLASS (self)->encode_result (self); - gkd_secret_service_send (self->pv->service, signal); - dbus_message_unref (signal); + gkd_org_freedesktop_secret_prompt_emit_completed (self->pv->skeleton, + dismissed, variant); } static void @@ -106,25 +97,23 @@ on_system_prompt_inited (GObject *source, } } -static DBusMessage* -prompt_method_prompt (GkdSecretPrompt *self, - DBusMessage *message) +static gboolean +prompt_method_prompt (GkdOrgFreedesktopSecretPrompt *skeleton, + GDBusMethodInvocation *invocation, + gchar *window_id, + GkdSecretPrompt *self) { - DBusMessage *reply; - const char *window_id; - /* Act as if this object no longer exists */ if (self->pv->completed) - return NULL; - - if (!dbus_message_get_args (message, NULL, DBUS_TYPE_STRING, - &window_id, DBUS_TYPE_INVALID)) - return NULL; + return FALSE; /* Prompt can only be called once */ - if (self->pv->prompted) - return dbus_message_new_error (message, SECRET_ERROR_ALREADY_EXISTS, - "This prompt has already been shown."); + if (self->pv->prompted) { + g_dbus_method_invocation_return_error_literal (invocation, GKD_SECRET_ERROR, + GKD_SECRET_ERROR_ALREADY_EXISTS, + "This prompt has already been shown."); + return TRUE; + } self->pv->prompted = TRUE; @@ -133,28 +122,23 @@ prompt_method_prompt (GkdSecretPrompt *self, g_async_initable_init_async (G_ASYNC_INITABLE (self), G_PRIORITY_DEFAULT, self->pv->cancellable, on_system_prompt_inited, NULL); - reply = dbus_message_new_method_return (message); - dbus_message_append_args (reply, DBUS_TYPE_INVALID); - return reply; + gkd_org_freedesktop_secret_prompt_complete_prompt (skeleton, invocation); + return TRUE; } -static DBusMessage* -prompt_method_dismiss (GkdSecretPrompt *self, DBusMessage *message) +static gboolean +prompt_method_dismiss (GkdOrgFreedesktopSecretPrompt *skeleton, + GDBusMethodInvocation *invocation, + GkdSecretPrompt *self) { - DBusMessage *reply; - /* Act as if this object no longer exists */ if (self->pv->completed) - return NULL; - - if (!dbus_message_get_args (message, NULL, DBUS_TYPE_INVALID)) - return NULL; + return FALSE; gkd_secret_prompt_dismiss (self); - reply = dbus_message_new_method_return (message); - dbus_message_append_args (reply, DBUS_TYPE_INVALID); - return reply; + gkd_org_freedesktop_secret_prompt_complete_dismiss (skeleton, invocation); + return TRUE; } static void @@ -164,49 +148,18 @@ gkd_secret_prompt_real_prompt_ready (GkdSecretPrompt *self) g_return_if_reached (); } -static void -gkd_secret_prompt_real_encode_result (GkdSecretPrompt *self, DBusMessageIter *iter) +static GVariant * +gkd_secret_prompt_real_encode_result (GkdSecretPrompt *self) { /* Default implementation, unused */ - g_return_if_reached (); + g_return_val_if_reached (NULL); } -static DBusMessage* -gkd_secret_prompt_real_dispatch_message (GkdSecretDispatch *base, DBusMessage *message) -{ - DBusMessage *reply = NULL; - GkdSecretPrompt *self; - const gchar *caller; - - g_return_val_if_fail (message, NULL); - g_return_val_if_fail (GKD_SECRET_IS_PROMPT (base), NULL); - self = GKD_SECRET_PROMPT (base); - - /* This should already have been caught elsewhere */ - caller = dbus_message_get_sender (message); - if (!caller || !g_str_equal (caller, self->pv->caller)) - g_return_val_if_reached (NULL); - - /* org.freedesktop.Secret.Prompt.Prompt() */ - else if (dbus_message_is_method_call (message, SECRET_PROMPT_INTERFACE, "Prompt")) - reply = prompt_method_prompt (self, message); - - /* org.freedesktop.Secret.Prompt.Negotiate() */ - else if (dbus_message_is_method_call (message, SECRET_PROMPT_INTERFACE, "Dismiss")) - reply = prompt_method_dismiss (self, message); - - /* org.freedesktop.DBus.Introspectable.Introspect() */ - else if (dbus_message_has_interface (message, DBUS_INTERFACE_INTROSPECTABLE)) - return gkd_dbus_introspect_handle (message, gkd_secret_introspect_prompt, NULL); - - return reply; -} - - static void gkd_secret_prompt_constructed (GObject *obj) { GkdSecretPrompt *self = GKD_SECRET_PROMPT (obj); + GError *error = NULL; G_OBJECT_CLASS (gkd_secret_prompt_parent_class)->constructed (obj); @@ -220,6 +173,21 @@ gkd_secret_prompt_constructed (GObject *obj) /* Set the exchange for the prompt */ g_object_set (self, "secret-exchange", self->pv->exchange, NULL); + + self->pv->skeleton = gkd_org_freedesktop_secret_prompt_skeleton_new (); + g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (self->pv->skeleton), + gkd_secret_service_get_connection (self->pv->service), self->pv->object_path, + &error); + + if (error != NULL) { + g_warning ("could not register secret prompt on session bus: %s", error->message); + g_error_free (error); + } + + g_signal_connect (self->pv->skeleton, "handle-dismiss", + G_CALLBACK (prompt_method_dismiss), self); + g_signal_connect (self->pv->skeleton, "handle-prompt", + G_CALLBACK (prompt_method_prompt), self); } static void @@ -344,7 +312,6 @@ gkd_secret_prompt_class_init (GkdSecretPromptClass *klass) static void gkd_secret_dispatch_iface (GkdSecretDispatchIface *iface) { - iface->dispatch_message = gkd_secret_prompt_real_dispatch_message; } /* ----------------------------------------------------------------------------- diff --git a/daemon/dbus/gkd-secret-prompt.h b/daemon/dbus/gkd-secret-prompt.h index 297750b4..0b52ea08 100644 --- a/daemon/dbus/gkd-secret-prompt.h +++ b/daemon/dbus/gkd-secret-prompt.h @@ -28,8 +28,6 @@ #include <gck/gck.h> #include <gcr/gcr-base.h> -#include <dbus/dbus.h> - #define GKD_SECRET_TYPE_PROMPT (gkd_secret_prompt_get_type ()) #define GKD_SECRET_PROMPT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GKD_SECRET_TYPE_PROMPT, GkdSecretPrompt)) #define GKD_SECRET_PROMPT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GKD_SECRET_TYPE_PROMPT, GkdSecretPromptClass)) @@ -50,8 +48,7 @@ struct _GkdSecretPromptClass { void (*prompt_ready) (GkdSecretPrompt *self); - void (*encode_result) (GkdSecretPrompt *self, - DBusMessageIter *iter); + GVariant * (*encode_result) (GkdSecretPrompt *self); }; GType gkd_secret_prompt_get_type (void) G_GNUC_CONST; diff --git a/daemon/dbus/gkd-secret-property.c b/daemon/dbus/gkd-secret-property.c index bfa37391..9c30d808 100644 --- a/daemon/dbus/gkd-secret-property.c +++ b/daemon/dbus/gkd-secret-property.c @@ -149,86 +149,69 @@ attribute_to_property (CK_ATTRIBUTE_TYPE attr_type, const gchar **prop_name, Dat return TRUE; } -typedef void (*IterAppendFunc) (DBusMessageIter*, const GckAttribute *); -typedef gboolean (*IterGetFunc) (DBusMessageIter*, gulong, GckBuilder *); +typedef GVariant * (*IterAppendFunc) (const GckAttribute *); +typedef gboolean (*IterGetFunc) (GVariant *, gulong, GckBuilder *); -static void -iter_append_string (DBusMessageIter *iter, - const GckAttribute *attr) +static GVariant * +iter_append_string (const GckAttribute *attr) { - gchar *value; - - g_assert (iter); g_assert (attr); if (attr->length == 0) { - value = ""; - dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &value); + return g_variant_new_string (""); } else { - value = g_strndup ((const gchar*)attr->value, attr->length); - dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &value); - g_free (value); + return g_variant_new_take_string (g_strndup ((const gchar*)attr->value, attr->length)); } } static gboolean -iter_get_string (DBusMessageIter *iter, +iter_get_string (GVariant *variant, gulong attr_type, GckBuilder *builder) { const char *value; - g_assert (iter != NULL); + g_assert (variant != NULL); g_assert (builder != NULL); - g_return_val_if_fail (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_STRING, FALSE); - dbus_message_iter_get_basic (iter, &value); + value = g_variant_get_string (variant, NULL); if (value == NULL) value = ""; gck_builder_add_string (builder, attr_type, value); return TRUE; } -static void -iter_append_bool (DBusMessageIter *iter, - const GckAttribute *attr) +static GVariant * +iter_append_bool (const GckAttribute *attr) { - dbus_bool_t value; - - g_assert (iter); g_assert (attr); - value = gck_attribute_get_boolean (attr) ? TRUE : FALSE; - dbus_message_iter_append_basic (iter, DBUS_TYPE_BOOLEAN, &value); + return g_variant_new_boolean (gck_attribute_get_boolean (attr)); } static gboolean -iter_get_bool (DBusMessageIter *iter, +iter_get_bool (GVariant *variant, gulong attr_type, GckBuilder *builder) { - dbus_bool_t value; + gboolean value; - g_assert (iter != NULL); + g_assert (variant != NULL); g_assert (builder != NULL); - g_return_val_if_fail (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_BOOLEAN, FALSE); - dbus_message_iter_get_basic (iter, &value); - - gck_builder_add_boolean (builder, attr_type, value ? TRUE : FALSE); + value = g_variant_get_boolean (variant); + gck_builder_add_boolean (builder, attr_type, value); return TRUE; } -static void -iter_append_time (DBusMessageIter *iter, - const GckAttribute *attr) +static GVariant * +iter_append_time (const GckAttribute *attr) { guint64 value; struct tm tm; gchar buf[15]; time_t time; - g_assert (iter); g_assert (attr); if (attr->length == 0) { @@ -258,11 +241,11 @@ iter_append_time (DBusMessageIter *iter, } } - dbus_message_iter_append_basic (iter, DBUS_TYPE_UINT64, &value); + return g_variant_new_uint64 (value); } static gboolean -iter_get_time (DBusMessageIter *iter, +iter_get_time (GVariant *variant, gulong attr_type, GckBuilder *builder) { @@ -271,11 +254,10 @@ iter_get_time (DBusMessageIter *iter, gchar buf[20]; guint64 value; - g_assert (iter != NULL); + g_assert (variant != NULL); g_assert (builder != NULL); - g_return_val_if_fail (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_UINT64, FALSE); - dbus_message_iter_get_basic (iter, &value); + value = g_variant_get_uint64 (variant); if (value == 0) { gck_builder_add_empty (builder, attr_type); return TRUE; @@ -292,28 +274,25 @@ iter_get_time (DBusMessageIter *iter, return TRUE; } -static void -iter_append_fields (DBusMessageIter *iter, - const GckAttribute *attr) +static GVariant * +iter_append_fields (const GckAttribute *attr) { - DBusMessageIter array; - DBusMessageIter dict; const gchar *ptr; const gchar *last; const gchar *name; gsize n_name; const gchar *value; gsize n_value; - gchar *string; + gchar *name_string, *value_string; + GVariantBuilder builder; - g_assert (iter); g_assert (attr); ptr = (gchar*)attr->value; last = ptr + attr->length; - g_return_if_fail (ptr || last == ptr); + g_return_val_if_fail (ptr || last == ptr, NULL); - dbus_message_iter_open_container (iter, DBUS_TYPE_ARRAY, "{ss}", &array); + g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{ss}")); while (ptr && ptr != last) { g_assert (ptr < last); @@ -332,58 +311,43 @@ iter_append_fields (DBusMessageIter *iter, n_value = ptr - value; ++ptr; - dbus_message_iter_open_container (&array, DBUS_TYPE_DICT_ENTRY, NULL, &dict); - - string = g_strndup (name, n_name); - dbus_message_iter_append_basic (&dict, DBUS_TYPE_STRING, &string); - g_free (string); + name_string = g_strndup (name, n_name); + value_string = g_strndup (value, n_value); - string = g_strndup (value, n_value); - dbus_message_iter_append_basic (&dict, DBUS_TYPE_STRING, &string); - g_free (string); + g_variant_builder_add (&builder, "{ss}", name_string, value_string); - dbus_message_iter_close_container (&array, &dict); + g_free (name_string); + g_free (value_string); } - dbus_message_iter_close_container (iter, &array); + return g_variant_builder_end (&builder); } static gboolean -iter_get_fields (DBusMessageIter *iter, +iter_get_fields (GVariant *variant, gulong attr_type, GckBuilder *builder) { - DBusMessageIter array; - DBusMessageIter dict; GString *result; - const gchar *string; + const gchar *key, *value; + GVariantIter iter; - g_assert (iter != NULL); + g_assert (variant != NULL); g_assert (builder != NULL); - result = g_string_new (""); - - g_return_val_if_fail (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_ARRAY, FALSE); - dbus_message_iter_recurse (iter, &array); + g_return_val_if_fail (g_variant_type_is_array (g_variant_get_type (variant)), FALSE); - while (dbus_message_iter_get_arg_type (&array) == DBUS_TYPE_DICT_ENTRY) { - dbus_message_iter_recurse (&array, &dict); + result = g_string_new (""); + g_variant_iter_init (&iter, variant); + while (g_variant_iter_next (&iter, "{&s&s}", &key, &value)) { /* Key */ - g_return_val_if_fail (dbus_message_iter_get_arg_type (&dict) == DBUS_TYPE_STRING, FALSE); - dbus_message_iter_get_basic (&dict, &string); - g_string_append (result, string); + g_string_append (result, key); g_string_append_c (result, '\0'); - dbus_message_iter_next (&dict); - /* Value */ - g_return_val_if_fail (dbus_message_iter_get_arg_type (&dict) == DBUS_TYPE_STRING, FALSE); - dbus_message_iter_get_basic (&dict, &string); - g_string_append (result, string); + g_string_append (result, value); g_string_append_c (result, '\0'); - - dbus_message_iter_next (&array); } gck_builder_add_data (builder, attr_type, (const guchar *)result->str, result->len); @@ -391,94 +355,75 @@ iter_get_fields (DBusMessageIter *iter, return TRUE; } -static void -iter_append_variant (DBusMessageIter *iter, - DataType data_type, +static GVariant * +iter_append_variant (DataType data_type, const GckAttribute *attr) { - DBusMessageIter sub; IterAppendFunc func = NULL; - const gchar *sig = NULL; - g_assert (iter); g_assert (attr); switch (data_type) { case DATA_TYPE_STRING: func = iter_append_string; - sig = DBUS_TYPE_STRING_AS_STRING; break; case DATA_TYPE_BOOL: func = iter_append_bool; - sig = DBUS_TYPE_BOOLEAN_AS_STRING; break; case DATA_TYPE_TIME: func = iter_append_time; - sig = DBUS_TYPE_UINT64_AS_STRING; break; case DATA_TYPE_FIELDS: func = iter_append_fields; - sig = "a{ss}"; break; default: g_assert (FALSE); break; } - dbus_message_iter_open_container (iter, DBUS_TYPE_VARIANT, sig, &sub); - (func) (&sub, attr); - dbus_message_iter_close_container (iter, &sub); + return (func) (attr); } static gboolean -iter_get_variant (DBusMessageIter *iter, +iter_get_variant (GVariant *variant, DataType data_type, gulong attr_type, GckBuilder *builder) { - DBusMessageIter variant; IterGetFunc func = NULL; gboolean ret; - const gchar *sig = NULL; - char *signature; + const GVariantType *sig; - g_assert (iter != NULL); + g_assert (variant != NULL); g_assert (builder != NULL); - g_return_val_if_fail (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_VARIANT, FALSE); - dbus_message_iter_recurse (iter, &variant); - switch (data_type) { case DATA_TYPE_STRING: func = iter_get_string; - sig = DBUS_TYPE_STRING_AS_STRING; + sig = G_VARIANT_TYPE_STRING; break; case DATA_TYPE_BOOL: func = iter_get_bool; - sig = DBUS_TYPE_BOOLEAN_AS_STRING; + sig = G_VARIANT_TYPE_BOOLEAN; break; case DATA_TYPE_TIME: func = iter_get_time; - sig = DBUS_TYPE_UINT64_AS_STRING; + sig = G_VARIANT_TYPE_UINT64; break; case DATA_TYPE_FIELDS: func = iter_get_fields; - sig = "a{ss}"; + sig = G_VARIANT_TYPE ("a{ss}"); break; default: g_assert (FALSE); break; } - signature = dbus_message_iter_get_signature (&variant); - g_return_val_if_fail (signature, FALSE); - ret = g_str_equal (sig, signature); - dbus_free (signature); - + ret = g_variant_type_equal (g_variant_get_type (variant), sig); if (ret == FALSE) return FALSE; - return (func) (&variant, attr_type, builder); + return (func) (variant, attr_type, builder); } /* ----------------------------------------------------------------------------- @@ -497,107 +442,99 @@ gkd_secret_property_get_type (const gchar *property, CK_ATTRIBUTE_TYPE *type) } gboolean -gkd_secret_property_parse_all (DBusMessageIter *array, +gkd_secret_property_parse_all (GVariant *array, const gchar *interface, GckBuilder *builder) { - DBusMessageIter dict; CK_ATTRIBUTE_TYPE attr_type; const char *name; DataType data_type; + GVariantIter iter; + GVariant *variant; g_return_val_if_fail (array != NULL, FALSE); g_return_val_if_fail (builder != NULL, FALSE); - while (dbus_message_iter_get_arg_type (array) == DBUS_TYPE_DICT_ENTRY) { - dbus_message_iter_recurse (array, &dict); + g_variant_iter_init (&iter, array); + while (g_variant_iter_loop (&iter, "{sv}", &name, &variant)) { /* Property interface.name */ - g_return_val_if_fail (dbus_message_iter_get_arg_type (&dict) == DBUS_TYPE_STRING, FALSE); - dbus_message_iter_get_basic (&dict, &name); - dbus_message_iter_next (&dict); - if (!property_to_attribute (name, interface, &attr_type, &data_type)) return FALSE; /* Property value */ - g_return_val_if_fail (dbus_message_iter_get_arg_type (&dict) == DBUS_TYPE_VARIANT, FALSE); - if (!iter_get_variant (&dict, data_type, attr_type, builder)) + if (!iter_get_variant (variant, data_type, attr_type, builder)) return FALSE; - - dbus_message_iter_next (array); } return TRUE; } -gboolean -gkd_secret_property_append_all (DBusMessageIter *array, GckAttributes *attrs) +GVariant * +gkd_secret_property_append_all (GckAttributes *attrs) { - DBusMessageIter dict; const GckAttribute *attr; DataType data_type; const gchar *name; gulong num, i; + GVariantBuilder builder; + GVariant *variant; - g_return_val_if_fail (array, FALSE); - g_return_val_if_fail (attrs, FALSE); + g_return_val_if_fail (attrs, NULL); + g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}")); num = gck_attributes_count (attrs); + for (i = 0; i < num; ++i) { attr = gck_attributes_at (attrs, i); if (!attribute_to_property (attr->type, &name, &data_type)) - g_return_val_if_reached (FALSE); + g_return_val_if_reached (NULL); - dbus_message_iter_open_container (array, DBUS_TYPE_DICT_ENTRY, NULL, &dict); - dbus_message_iter_append_basic (&dict, DBUS_TYPE_STRING, &name); - iter_append_variant (&dict, data_type, attr); - dbus_message_iter_close_container (array, &dict); + variant = iter_append_variant (data_type, attr); + g_variant_builder_add (&builder, "{sv}", name, variant); + g_variant_unref (variant); } - return TRUE; + return g_variant_builder_end (&builder); } -gboolean -gkd_secret_property_append_variant (DBusMessageIter *iter, - const GckAttribute *attr) +GVariant * +gkd_secret_property_append_variant (const GckAttribute *attr) { const gchar *property; DataType data_type; - g_return_val_if_fail (attr, FALSE); - g_return_val_if_fail (iter, FALSE); + g_return_val_if_fail (attr, NULL); if (!attribute_to_property (attr->type, &property, &data_type)) - return FALSE; - iter_append_variant (iter, data_type, attr); - return TRUE; + return NULL; + return iter_append_variant (data_type, attr); } gboolean -gkd_secret_property_parse_variant (DBusMessageIter *iter, +gkd_secret_property_parse_variant (GVariant *variant, const gchar *property, GckBuilder *builder) { CK_ATTRIBUTE_TYPE attr_type; DataType data_type; - g_return_val_if_fail (iter, FALSE); + g_return_val_if_fail (variant, FALSE); g_return_val_if_fail (property, FALSE); g_return_val_if_fail (builder != NULL, FALSE); if (!property_to_attribute (property, NULL, &attr_type, &data_type)) return FALSE; - return iter_get_variant (iter, data_type, attr_type, builder); + return iter_get_variant (variant, data_type, attr_type, builder); } gboolean -gkd_secret_property_parse_fields (DBusMessageIter *iter, +gkd_secret_property_parse_fields (GVariant *variant, GckBuilder *builder) { - g_return_val_if_fail (iter != NULL, FALSE); + g_return_val_if_fail (variant != NULL, FALSE); g_return_val_if_fail (builder != NULL, FALSE); - return iter_get_fields (iter, CKA_G_FIELDS, builder); + return iter_get_fields (variant, CKA_G_FIELDS, builder); } diff --git a/daemon/dbus/gkd-secret-property.h b/daemon/dbus/gkd-secret-property.h index 3b37b9f1..b5f161ef 100644 --- a/daemon/dbus/gkd-secret-property.h +++ b/daemon/dbus/gkd-secret-property.h @@ -25,25 +25,23 @@ #include <gck/gck.h> -#include <dbus/dbus.h> +#include <gio/gio.h> gboolean gkd_secret_property_get_type (const gchar *property, CK_ATTRIBUTE_TYPE *type); -gboolean gkd_secret_property_append_variant (DBusMessageIter *iter, - const GckAttribute *attr); +GVariant * gkd_secret_property_append_variant (const GckAttribute *attr); -gboolean gkd_secret_property_append_all (DBusMessageIter *array, - GckAttributes *attrs); +GVariant * gkd_secret_property_append_all (GckAttributes *attrs); -gboolean gkd_secret_property_parse_variant (DBusMessageIter *iter, +gboolean gkd_secret_property_parse_variant (GVariant *variant, const gchar *property, GckBuilder *builder); -gboolean gkd_secret_property_parse_fields (DBusMessageIter *iter, +gboolean gkd_secret_property_parse_fields (GVariant *variant, GckBuilder *builder); -gboolean gkd_secret_property_parse_all (DBusMessageIter *array, +gboolean gkd_secret_property_parse_all (GVariant *variant, const gchar *interface, GckBuilder *builder); diff --git a/daemon/dbus/gkd-secret-secret.c b/daemon/dbus/gkd-secret-secret.c index e70efd6f..336ea498 100644 --- a/daemon/dbus/gkd-secret-secret.c +++ b/daemon/dbus/gkd-secret-secret.c @@ -21,6 +21,7 @@ #include "config.h" #include "gkd-secret-dispatch.h" +#include "gkd-secret-error.h" #include "gkd-secret-secret.h" #include "gkd-secret-service.h" #include "gkd-secret-session.h" @@ -76,112 +77,74 @@ gkd_secret_secret_new_take_memory (GkdSecretSession *session, } GkdSecretSecret* -gkd_secret_secret_parse (GkdSecretService *service, DBusMessage *message, - DBusMessageIter *iter, DBusError *derr) +gkd_secret_secret_parse (GkdSecretService *service, + const char *sender, + GVariant *variant, + GError **error) { - GkdSecretSecret *secret; + GkdSecretSecret *secret = NULL; GkdSecretSession *session; - DBusMessageIter struc, array; - void *parameter, *value; - int n_value, n_parameter; - char *path, *content_type; + const char *parameter, *value, *path, *content_type; + gsize n_parameter, n_value; + GVariant *parameter_variant, *value_variant; g_return_val_if_fail (GKD_SECRET_IS_SERVICE (service), NULL); - g_return_val_if_fail (message, NULL); - g_return_val_if_fail (iter, NULL); + g_return_val_if_fail (variant, NULL); + g_return_val_if_fail (sender, NULL); - g_return_val_if_fail (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_STRUCT, NULL); - dbus_message_iter_recurse (iter, &struc); + g_variant_get (variant, "(&o^&ay^&ay&s)", &path, NULL, NULL, &content_type); - /* Get the path */ - if (dbus_message_iter_get_arg_type (&struc) != DBUS_TYPE_OBJECT_PATH) { - dbus_set_error (derr, DBUS_ERROR_INVALID_ARGS, "Invalid secret argument"); - return NULL; - } - dbus_message_iter_get_basic (&struc, &path); - - /* Get the parameter */ - if (!dbus_message_iter_next (&struc) || - dbus_message_iter_get_arg_type (&struc) != DBUS_TYPE_ARRAY || - dbus_message_iter_get_element_type(&struc) != DBUS_TYPE_BYTE) { - dbus_set_error (derr, DBUS_ERROR_INVALID_ARGS, "Invalid secret argument"); - return NULL; - } - dbus_message_iter_recurse (&struc, &array); - dbus_message_iter_get_fixed_array (&array, ¶meter, &n_parameter); - - /* Get the value */ - if (!dbus_message_iter_next (&struc) || - dbus_message_iter_get_arg_type (&struc) != DBUS_TYPE_ARRAY || - dbus_message_iter_get_element_type(&struc) != DBUS_TYPE_BYTE) { - dbus_set_error (derr, DBUS_ERROR_INVALID_ARGS, "Invalid secret argument"); - return NULL; - } - dbus_message_iter_recurse (&struc, &array); - dbus_message_iter_get_fixed_array (&array, &value, &n_value); + /* parameter */ + parameter_variant = g_variant_get_child_value (variant, 1); + parameter = g_variant_get_fixed_array (parameter_variant, &n_parameter, sizeof (guint8)); - /* - * TODO: We currently don't do anythinrg with the content type, because - * we have nowhere to store it. - */ - if (!dbus_message_iter_next (&struc) || - dbus_message_iter_get_arg_type (&struc) != DBUS_TYPE_STRING) { - dbus_set_error (derr, DBUS_ERROR_INVALID_ARGS, "Invalid content type argument"); - return NULL; - } - dbus_message_iter_get_basic (&struc, &content_type); + /* value */ + value_variant = g_variant_get_child_value (variant, 2); + value = g_variant_get_fixed_array (value_variant, &n_value, sizeof (guint8)); /* Try to lookup the session */ - session = gkd_secret_service_lookup_session (service, path, - dbus_message_get_sender (message)); - + session = gkd_secret_service_lookup_session (service, path, sender); if (session == NULL) { - dbus_set_error (derr, SECRET_ERROR_NO_SESSION, - "The session wrapping the secret does not exist"); - return NULL; + g_set_error_literal (error, GKD_SECRET_ERROR, + GKD_SECRET_ERROR_NO_SESSION, + "The session wrapping the secret does not exist"); + goto out; } secret = g_slice_new0 (GkdSecretSecret); secret->session = g_object_ref (session); - secret->parameter = parameter; + secret->parameter = g_strndup (parameter, n_parameter); secret->n_parameter = n_parameter; - secret->value = value; + secret->value = g_strndup (value, n_value); secret->n_value = n_value; - /* All the memory is owned by the message */ - secret->destroy_data = dbus_message_ref (message); - secret->destroy_func = (GDestroyNotify)dbus_message_unref; + out: + g_variant_unref (parameter_variant); + g_variant_unref (value_variant); + return secret; } -void -gkd_secret_secret_append (GkdSecretSecret *secret, DBusMessageIter *iter) +GVariant * +gkd_secret_secret_append (GkdSecretSecret *secret) { + GVariantBuilder builder; const gchar *content_type = "text/plain"; - DBusMessageIter struc, array; const gchar *path; - int length; + GVariant *parameter, *value; path = gkd_secret_dispatch_get_object_path (GKD_SECRET_DISPATCH (secret->session)); - g_return_if_fail (path); - - dbus_message_iter_open_container (iter, DBUS_TYPE_STRUCT, NULL, &struc); - dbus_message_iter_append_basic (&struc, DBUS_TYPE_OBJECT_PATH, &path); - dbus_message_iter_open_container (&struc, DBUS_TYPE_ARRAY, "y", &array); - length = secret->n_parameter; - dbus_message_iter_append_fixed_array (&array, DBUS_TYPE_BYTE, &(secret->parameter), length); - dbus_message_iter_close_container (&struc, &array); - dbus_message_iter_open_container (&struc, DBUS_TYPE_ARRAY, "y", &array); - length = secret->n_value; - dbus_message_iter_append_fixed_array (&array, DBUS_TYPE_BYTE, &(secret->value), length); - dbus_message_iter_close_container (&struc, &array); + g_return_val_if_fail (path, NULL); - /* - * TODO: We're just putting a place holder value here for now. - */ - dbus_message_iter_append_basic (&struc, DBUS_TYPE_STRING, &content_type); + g_variant_builder_init (&builder, G_VARIANT_TYPE ("ay")); + g_variant_builder_add (&builder, "y", secret->parameter); + parameter = g_variant_builder_end (&builder); + + g_variant_builder_init (&builder, G_VARIANT_TYPE ("ay")); + g_variant_builder_add (&builder, "y", secret->value); + value = g_variant_builder_end (&builder); - dbus_message_iter_close_container (iter, &struc); + return g_variant_new ("(o@ay@ays)", path, parameter, value, content_type); } void diff --git a/daemon/dbus/gkd-secret-secret.h b/daemon/dbus/gkd-secret-secret.h index 39c09f4f..2520077d 100644 --- a/daemon/dbus/gkd-secret-secret.h +++ b/daemon/dbus/gkd-secret-secret.h @@ -25,8 +25,6 @@ #include <glib.h> -#include <dbus/dbus.h> - struct _GkdSecretSecret { GkdSecretSession *session; @@ -52,12 +50,11 @@ GkdSecretSecret* gkd_secret_secret_new_take_memory (GkdSecretSess gsize n_value); GkdSecretSecret* gkd_secret_secret_parse (GkdSecretService *service, - DBusMessage *message, - DBusMessageIter *iter, - DBusError *derr); + const char *sender, + GVariant *variant, + GError **error); -void gkd_secret_secret_append (GkdSecretSecret *secret, - DBusMessageIter *iter); +GVariant * gkd_secret_secret_append (GkdSecretSecret *secret); void gkd_secret_secret_free (gpointer data); diff --git a/daemon/dbus/gkd-secret-service.c b/daemon/dbus/gkd-secret-service.c index 4c62bbe7..1a37b6b7 100644 --- a/daemon/dbus/gkd-secret-service.c +++ b/daemon/dbus/gkd-secret-service.c @@ -20,12 +20,10 @@ #include "config.h" -#include "gkd-dbus-util.h" #include "gkd-secret-change.h" #include "gkd-secret-create.h" #include "gkd-secret-dispatch.h" #include "gkd-secret-error.h" -#include "gkd-secret-introspect.h" #include "gkd-secret-lock.h" #include "gkd-secret-objects.h" #include "gkd-secret-prompt.h" @@ -37,6 +35,9 @@ #include "gkd-secret-unlock.h" #include "gkd-secret-util.h" +#include "gkd-internal-generated.h" +#include "gkd-secrets-generated.h" + #include "egg/egg-error.h" #include "egg/egg-unix-credentials.h" @@ -46,6 +47,73 @@ #include <string.h> +/* ----------------------------------------------------------------------------- + * SKELETON + */ +typedef struct { + GkdOrgFreedesktopSecretServiceSkeleton parent; + GkdSecretService *service; +} GkdSecretServiceSkeleton; +typedef struct { + GkdOrgFreedesktopSecretServiceSkeletonClass parent_class; +} GkdSecretServiceSkeletonClass; + +GType gkd_secret_service_skeleton_get_type (void); +G_DEFINE_TYPE (GkdSecretServiceSkeleton, gkd_secret_service_skeleton, GKD_TYPE_ORG_FREEDESKTOP_SECRET_SERVICE_SKELETON) + +enum { + PROP_COLLECTIONS = 1 +}; + +static void +gkd_secret_service_skeleton_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + GkdSecretServiceSkeleton *skeleton = (GkdSecretServiceSkeleton *) object; + + switch (prop_id) { + case PROP_COLLECTIONS: + g_value_take_boxed (value, gkd_secret_service_get_collections (skeleton->service)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gkd_secret_service_skeleton_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + G_OBJECT_CLASS (gkd_secret_service_skeleton_parent_class)->set_property (object, prop_id, value, pspec); +} + +static void +gkd_secret_service_skeleton_class_init (GkdSecretServiceSkeletonClass *klass) +{ + GObjectClass *oclass = G_OBJECT_CLASS (klass); + oclass->get_property = gkd_secret_service_skeleton_get_property; + oclass->set_property = gkd_secret_service_skeleton_set_property; + gkd_org_freedesktop_secret_service_override_properties (oclass, PROP_COLLECTIONS); +} + +static void +gkd_secret_service_skeleton_init (GkdSecretServiceSkeleton *self) +{ +} + +static GkdOrgFreedesktopSecretService * +gkd_secret_service_skeleton_new (GkdSecretService *service) +{ + GkdOrgFreedesktopSecretService *skeleton = g_object_new (gkd_secret_service_skeleton_get_type (), NULL); + ((GkdSecretServiceSkeleton *) skeleton)->service = service; + return skeleton; +} + enum { PROP_0, PROP_CONNECTION, @@ -54,9 +122,13 @@ enum { struct _GkdSecretService { GObject parent; - DBusConnection *connection; + + GDBusConnection *connection; + GkdOrgFreedesktopSecretService *skeleton; + GkdOrgGnomeKeyringInternalUnsupportedGuiltRiddenInterface *internal_skeleton; + guint name_owner_id; + GHashTable *clients; - gchar *match_rule; GkdSecretObjects *objects; GHashTable *aliases; GckSession *internal_session; @@ -72,9 +144,6 @@ typedef struct _ServiceClient { GHashTable *dispatch; } ServiceClient; -/* Forward declaration */ -static void service_dispatch_message (GkdSecretService *, DBusMessage *); - G_DEFINE_TYPE (GkdSecretService, gkd_secret_service, G_TYPE_OBJECT); /* ----------------------------------------------------------------------------- @@ -210,57 +279,39 @@ free_client (gpointer data) g_free (client); } -typedef struct _on_get_connection_unix_process_id_args { - GkdSecretService *self; - DBusMessage *message; -} on_get_connection_unix_process_id_args; - -static void -free_on_get_connection_unix_process_id_args (gpointer data) -{ - on_get_connection_unix_process_id_args *args = data; - if (args != NULL) { - g_object_unref (args->self); - dbus_message_unref (args->message); - g_free (args); - } -} - static void -on_get_connection_unix_process_id (DBusPendingCall *pending, gpointer user_data) +initialize_service_client (GkdSecretService *self, + const gchar *caller) { - on_get_connection_unix_process_id_args *args = user_data; - DBusMessage *reply = NULL; - DBusError error = DBUS_ERROR_INIT; - dbus_uint32_t caller_pid = 0; - GkdSecretService *self; + GError *error = NULL; + guint32 caller_pid; + GVariant *variant; ServiceClient *client; - const gchar *caller; - - g_return_if_fail (GKD_SECRET_IS_SERVICE (args->self)); - self = args->self; - - /* Get the resulting process ID */ - reply = dbus_pending_call_steal_reply (pending); - g_return_if_fail (reply); - - caller = dbus_message_get_sender (args->message); - g_return_if_fail (caller); - - client = g_hash_table_lookup (self->clients, caller); - if (client == NULL) { - - /* 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); - /* 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 (); - } + g_assert (GKD_SECRET_IS_SERVICE (self)); + g_assert (caller); + + variant = g_dbus_connection_call_sync (self->connection, + "org.freedesktop.DBus", + "/org/freedesktop/DBus", + "org.freedesktop.DBus", + "GetConnectionUnixProcessID", + g_variant_new ("(s)", caller), + G_VARIANT_TYPE ("(u)"), + G_DBUS_CALL_FLAGS_NONE, + 2000, + NULL, &error); + + /* An error returned from GetConnectionUnixProcessID */ + if (error != NULL) { + g_message ("couldn't get the caller's unix process id: %s", error->message); + caller_pid = 0; + g_error_free (error); + + /* A PID was returned from GetConnectionUnixProcessID */ + } else { + g_variant_get (variant, "(u)", &caller_pid); + g_variant_unref (variant); /* Initialize the client object */ client = g_new0 (ServiceClient, 1); @@ -276,186 +327,109 @@ on_get_connection_unix_process_id (DBusPendingCall *pending, gpointer user_data) /* Update default collection each time someone connects */ update_default (self, TRUE); } - - dbus_message_unref (reply); - - /* Dispatch the original message again */ - service_dispatch_message (self, args->message); } static void -initialize_service_client (GkdSecretService *self, DBusMessage *message) +gkd_secret_service_ensure_client (GkdSecretService *self, + GDBusMethodInvocation *invocation) { - on_get_connection_unix_process_id_args *args; - DBusMessage *request; - DBusPendingCall *pending; - const gchar *caller; - - g_assert (GKD_SECRET_IS_SERVICE (self)); - 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); - - caller = dbus_message_get_sender (message); - g_return_if_fail (caller); + ServiceClient *client; + const gchar *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_if_reached (); - - /* - * Send of request for GetConnectionUnixProcessID, with lowish timeout. - * We're only talking to the session bus, so the reply should be fast. - * In addition we want to send off a reply to our caller, before it - * times out. - */ - if (!dbus_connection_send_with_reply (self->connection, request, &pending, 2000)) - g_return_if_reached (); - dbus_message_unref (request); - - /* 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); + caller = g_dbus_method_invocation_get_sender (invocation); + client = g_hash_table_lookup (self->clients, caller); + if (client == NULL) { + initialize_service_client (self, caller); + } } /* ----------------------------------------------------------------------------- * DBUS */ -static DBusMessage* -service_property_get (GkdSecretService *self, DBusMessage *message) +static gboolean +service_method_open_session (GkdOrgFreedesktopSecretService *skeleton, + GDBusMethodInvocation *invocation, + gchar *algorithm, + GVariant *input, + GkdSecretService *self) { - DBusMessage *reply = NULL; - DBusMessageIter iter; - const gchar *interface; - const gchar *name; - - if (!dbus_message_get_args (message, NULL, DBUS_TYPE_STRING, &interface, - DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID)) - return NULL; - - if (!gkd_dbus_interface_match (SECRET_SERVICE_INTERFACE, interface)) - return dbus_message_new_error_printf (message, DBUS_ERROR_FAILED, - "Object does not have properties on interface '%s'", - interface); + GkdSecretSession *session; + GVariant *output = NULL; + gchar *result = NULL; + GError *error = NULL; + const gchar *caller; + GVariant *input_payload; - /* The "Collections" property */ - if (g_str_equal (name, "Collections")) { - reply = dbus_message_new_method_return (message); - dbus_message_iter_init_append (reply, &iter); - gkd_secret_objects_append_collection_paths (self->objects, &iter, message); + gkd_secret_service_ensure_client (self, invocation); + caller = g_dbus_method_invocation_get_sender (invocation); - /* No such property */ + /* Now we can create a session with this information */ + session = gkd_secret_session_new (self, caller); + input_payload = g_variant_get_variant (input); + gkd_secret_session_handle_open (session, algorithm, input_payload, + &output, &result, + &error); + g_variant_unref (input_payload); + + if (error != NULL) { + g_dbus_method_invocation_take_error (invocation, error); } else { - reply = dbus_message_new_error_printf (message, DBUS_ERROR_FAILED, - "Object does not have the '%s' property", name); + gkd_secret_service_publish_dispatch (self, caller, + GKD_SECRET_DISPATCH (session)); + gkd_org_freedesktop_secret_service_complete_open_session (skeleton, invocation, output, result); + g_free (result); } - return reply; -} - -static DBusMessage* -service_property_set (GkdSecretService *self, DBusMessage *message) -{ - return NULL; /* TODO: Need to implement */ + g_object_unref (session); + return TRUE; } -static void -service_append_all_properties (GkdSecretService *self, - DBusMessageIter *iter) +static gboolean +service_method_search_items (GkdOrgFreedesktopSecretService *skeleton, + GDBusMethodInvocation *invocation, + GVariant *attributes, + GkdSecretService *self) { - DBusMessageIter array; - DBusMessageIter dict; - const gchar *name; - - dbus_message_iter_open_container (iter, DBUS_TYPE_ARRAY, "{sv}", &array); - - name = "Collections"; - dbus_message_iter_open_container (&array, DBUS_TYPE_DICT_ENTRY, NULL, &dict); - dbus_message_iter_append_basic (&dict, DBUS_TYPE_STRING, &name); - gkd_secret_objects_append_collection_paths (self->objects, &dict, NULL); - dbus_message_iter_close_container (&array, &dict); - - dbus_message_iter_close_container (iter, &array); + gkd_secret_service_ensure_client (self, invocation); + return gkd_secret_objects_handle_search_items (self->objects, invocation, + attributes, NULL, TRUE); } -static DBusMessage* -service_property_getall (GkdSecretService *self, DBusMessage *message) +static gboolean +service_method_get_secrets (GkdOrgFreedesktopSecretService *skeleton, + GDBusMethodInvocation *invocation, + gchar **items, + gchar *session, + GkdSecretService *self) { - DBusMessage *reply = NULL; - DBusMessageIter iter; - const gchar *interface; - - if (!dbus_message_get_args (message, NULL, DBUS_TYPE_STRING, &interface, DBUS_TYPE_INVALID)) - return NULL; - - if (!gkd_dbus_interface_match (SECRET_SERVICE_INTERFACE, interface)) - return dbus_message_new_error_printf (message, DBUS_ERROR_FAILED, - "Object does not have properties on interface '%s'", - interface); - - reply = dbus_message_new_method_return (message); - dbus_message_iter_init_append (reply, &iter); - service_append_all_properties (self, &iter); - return reply; + gkd_secret_service_ensure_client (self, invocation); + return gkd_secret_objects_handle_get_secrets (self->objects, invocation, + (const gchar **) items, session); } -static DBusMessage* -service_method_open_session (GkdSecretService *self, DBusMessage *message) -{ - GkdSecretSession *session; - DBusMessage *reply = NULL; - const gchar *caller; - - if (!dbus_message_has_signature (message, "sv")) - return NULL; - - caller = dbus_message_get_sender (message); - - /* Now we can create a session with this information */ - session = gkd_secret_session_new (self, caller); - reply = gkd_secret_session_handle_open (session, message); - - if (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_METHOD_RETURN) - gkd_secret_service_publish_dispatch (self, caller, - GKD_SECRET_DISPATCH (session)); - - g_object_unref (session); - return reply; -} - -static DBusMessage* -service_method_create_collection (GkdSecretService *self, DBusMessage *message) +static gboolean +service_method_create_collection (GkdOrgFreedesktopSecretService *skeleton, + GDBusMethodInvocation *invocation, + GVariant *properties, + gchar *alias, + GkdSecretService *self) { GckBuilder builder = GCK_BUILDER_INIT; - DBusMessageIter iter, array; GckAttributes *attrs; GkdSecretCreate *create; - DBusMessage *reply; const gchar *path; - const gchar *alias; const char *caller; - const gchar *coll; - /* Parse the incoming message */ - if (!dbus_message_has_signature (message, "a{sv}s")) - return NULL; - if (!dbus_message_iter_init (message, &iter)) - g_return_val_if_reached (NULL); - dbus_message_iter_recurse (&iter, &array); - if (!gkd_secret_property_parse_all (&array, SECRET_COLLECTION_INTERFACE, &builder)) { + gkd_secret_service_ensure_client (self, invocation); + + if (!gkd_secret_property_parse_all (properties, SECRET_COLLECTION_INTERFACE, &builder)) { gck_builder_clear (&builder); - return dbus_message_new_error_printf (message, DBUS_ERROR_INVALID_ARGS, - "Invalid properties"); + g_dbus_method_invocation_return_error_literal (invocation, G_DBUS_ERROR, + G_DBUS_ERROR_INVALID_ARGS, + "Invalid properties"); + return TRUE; } - if (!dbus_message_iter_next (&iter)) - g_return_val_if_reached (NULL); - dbus_message_iter_get_basic (&iter, &alias); /* Empty alias is no alias */ if (alias) { @@ -463,8 +437,10 @@ service_method_create_collection (GkdSecretService *self, DBusMessage *message) alias = NULL; } else if (!g_str_equal (alias, "default")) { gck_builder_clear (&builder); - return dbus_message_new_error (message, DBUS_ERROR_NOT_SUPPORTED, - "Only the 'default' alias is supported"); + g_dbus_method_invocation_return_error_literal (invocation, G_DBUS_ERROR, + G_DBUS_ERROR_NOT_SUPPORTED, + "Only the 'default' alias is supported"); + return TRUE; } } @@ -472,7 +448,7 @@ service_method_create_collection (GkdSecretService *self, DBusMessage *message) attrs = gck_attributes_ref_sink (gck_builder_end (&builder)); /* Create the prompt object, for the password */ - caller = dbus_message_get_sender (message); + caller = g_dbus_method_invocation_get_sender (invocation); create = gkd_secret_create_new (self, caller, attrs, alias); gck_attributes_unref (attrs); @@ -480,57 +456,52 @@ service_method_create_collection (GkdSecretService *self, DBusMessage *message) gkd_secret_service_publish_dispatch (self, caller, GKD_SECRET_DISPATCH (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); - - g_object_unref (create); - return reply; + gkd_org_freedesktop_secret_service_complete_create_collection (skeleton, invocation, + "/", path); + return TRUE; } -static DBusMessage* -service_method_lock_service (GkdSecretService *self, DBusMessage *message) +static gboolean +service_method_lock_service (GkdOrgFreedesktopSecretService *skeleton, + GDBusMethodInvocation *invocation, + GkdSecretService *self) { - DBusError derr = DBUS_ERROR_INIT; + GError *error = NULL; GckSession *session; const char *caller; - if (!dbus_message_get_args (message, NULL, DBUS_TYPE_INVALID)) - return NULL; + gkd_secret_service_ensure_client (self, invocation); - caller = dbus_message_get_sender (message); + caller = g_dbus_method_invocation_get_sender (invocation); session = gkd_secret_service_get_pkcs11_session (self, caller); - g_return_val_if_fail (session != NULL, NULL); + g_return_val_if_fail (session != NULL, FALSE); - if (!gkd_secret_lock_all (session, &derr)) - return gkd_secret_error_to_reply (message, &derr); + if (!gkd_secret_lock_all (session, &error)) + g_dbus_method_invocation_take_error (invocation, error); + else + gkd_org_freedesktop_secret_service_complete_lock_service (skeleton, invocation); - return dbus_message_new_method_return (message); + return TRUE; } -static DBusMessage* -service_method_unlock (GkdSecretService *self, DBusMessage *message) +static gboolean +service_method_unlock (GkdOrgFreedesktopSecretService *skeleton, + GDBusMethodInvocation *invocation, + gchar **objpaths, + GkdSecretService *self) { GkdSecretUnlock *unlock; - DBusMessage *reply; const char *caller; const gchar *path; - int n_objpaths, i; - char **objpaths; + int i, n_unlocked; + gchar **unlocked; - if (!dbus_message_get_args (message, NULL, - DBUS_TYPE_ARRAY, DBUS_TYPE_OBJECT_PATH, &objpaths, &n_objpaths, - DBUS_TYPE_INVALID)) - return NULL; + gkd_secret_service_ensure_client (self, invocation); - caller = dbus_message_get_sender (message); + caller = g_dbus_method_invocation_get_sender (invocation); unlock = gkd_secret_unlock_new (self, caller, NULL); - for (i = 0; i < n_objpaths; ++i) + for (i = 0; objpaths[i] != NULL; ++i) gkd_secret_unlock_queue (unlock, objpaths[i]); - dbus_free_string_array (objpaths); /* So do we need to prompt? */ if (gkd_secret_unlock_have_queued (unlock)) { @@ -543,38 +514,33 @@ service_method_unlock (GkdSecretService *self, DBusMessage *message) path = "/"; } - reply = dbus_message_new_method_return (message); - objpaths = gkd_secret_unlock_get_results (unlock, &n_objpaths); - dbus_message_append_args (reply, - DBUS_TYPE_ARRAY, DBUS_TYPE_OBJECT_PATH, &objpaths, n_objpaths, - DBUS_TYPE_OBJECT_PATH, &path, - DBUS_TYPE_INVALID); + unlocked = gkd_secret_unlock_get_results (unlock, &n_unlocked); + gkd_org_freedesktop_secret_service_complete_unlock (skeleton, invocation, + (const gchar **) unlocked, path); gkd_secret_unlock_reset_results (unlock); g_object_unref (unlock); - return reply; + return TRUE; } -static DBusMessage* -service_method_lock (GkdSecretService *self, DBusMessage *message) +static gboolean +service_method_lock (GkdOrgFreedesktopSecretService *skeleton, + GDBusMethodInvocation *invocation, + gchar **objpaths, + GkdSecretService *self) { - DBusMessage *reply; const char *caller; - const gchar *prompt; GckObject *collection; - int n_objpaths, i; - char **objpaths; + int i; + char **locked; GPtrArray *array; - if (!dbus_message_get_args (message, NULL, - DBUS_TYPE_ARRAY, DBUS_TYPE_OBJECT_PATH, &objpaths, &n_objpaths, - DBUS_TYPE_INVALID)) - return NULL; + gkd_secret_service_ensure_client (self, invocation); - caller = dbus_message_get_sender (message); + caller = g_dbus_method_invocation_get_sender (invocation); array = g_ptr_array_new (); - for (i = 0; i < n_objpaths; ++i) { + for (i = 0; objpaths[i] != NULL; ++i) { collection = gkd_secret_objects_lookup_collection (self->objects, caller, objpaths[i]); if (collection != NULL) { if (gkd_secret_lock (collection, NULL)) { @@ -586,60 +552,80 @@ service_method_lock (GkdSecretService *self, DBusMessage *message) } } - prompt = "/"; - reply = dbus_message_new_method_return (message); - dbus_message_append_args (reply, - DBUS_TYPE_ARRAY, DBUS_TYPE_OBJECT_PATH, &array->pdata, array->len, - DBUS_TYPE_OBJECT_PATH, &prompt, - DBUS_TYPE_INVALID); + g_ptr_array_add (array, NULL); + + locked = (gchar **) g_ptr_array_free (array, FALSE); + gkd_org_freedesktop_secret_service_complete_lock (skeleton, invocation, + (const gchar **) locked, "/"); - dbus_free_string_array (objpaths); - return reply; + return TRUE; } -static DBusMessage* -service_method_change_lock (GkdSecretService *self, DBusMessage *message) +static gboolean +method_change_lock_internal (GkdSecretService *self, + GDBusMethodInvocation *invocation, + const gchar *collection_path) { GkdSecretChange *change; - DBusMessage *reply; const char *caller; const gchar *path; GckObject *collection; - caller = dbus_message_get_sender (message); - if (!dbus_message_get_args (message, NULL, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID)) - return NULL; + caller = g_dbus_method_invocation_get_sender (invocation); /* Make sure it exists */ - collection = gkd_secret_objects_lookup_collection (self->objects, caller, path); - if (!collection) - return dbus_message_new_error (message, SECRET_ERROR_NO_SUCH_OBJECT, - "The collection does not exist"); + collection = gkd_secret_objects_lookup_collection (self->objects, caller, collection_path); + if (!collection) { + g_dbus_method_invocation_return_error_literal (invocation, GKD_SECRET_ERROR, + GKD_SECRET_ERROR_NO_SUCH_OBJECT, + "The collection does not exist"); + return TRUE; + } + g_object_unref (collection); - change = gkd_secret_change_new (self, caller, path); + change = gkd_secret_change_new (self, caller, collection_path); path = gkd_secret_dispatch_get_object_path (GKD_SECRET_DISPATCH (change)); gkd_secret_service_publish_dispatch (self, caller, GKD_SECRET_DISPATCH (change)); - reply = dbus_message_new_method_return (message); - dbus_message_append_args (reply, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID); - + g_dbus_method_invocation_return_value (invocation, g_variant_new ("(o)", path)); g_object_unref (change); - return reply; + + return TRUE; +} + +static gboolean +service_method_change_lock (GkdOrgFreedesktopSecretService *skeleton, + GDBusMethodInvocation *invocation, + gchar *collection_path, + GkdSecretService *self) +{ + gkd_secret_service_ensure_client (self, invocation); + return method_change_lock_internal (self, invocation, collection_path); } -static DBusMessage* -service_method_read_alias (GkdSecretService *self, DBusMessage *message) +static gboolean +service_method_change_with_prompt (GkdOrgGnomeKeyringInternalUnsupportedGuiltRiddenInterface *skeleton, + GDBusMethodInvocation *invocation, + gchar *collection_path, + GkdSecretService *self) +{ + gkd_secret_service_ensure_client (self, invocation); + return method_change_lock_internal (self, invocation, collection_path); +} + +static gboolean +service_method_read_alias (GkdOrgFreedesktopSecretService *skeleton, + GDBusMethodInvocation *invocation, + gchar *alias, + GkdSecretService *self) { - DBusMessage *reply; - const char *alias; gchar *path = NULL; const gchar *identifier; GckObject *collection = NULL; - if (!dbus_message_get_args (message, NULL, DBUS_TYPE_STRING, &alias, DBUS_TYPE_INVALID)) - return NULL; + gkd_secret_service_ensure_client (self, invocation); identifier = gkd_secret_service_get_alias (self, alias); if (identifier) @@ -648,7 +634,8 @@ service_method_read_alias (GkdSecretService *self, DBusMessage *message) /* Make sure it actually exists */ if (path) collection = gkd_secret_objects_lookup_collection (self->objects, - dbus_message_get_sender (message), path); + g_dbus_method_invocation_get_sender (invocation), + path); if (collection == NULL) { g_free (path); path = NULL; @@ -656,33 +643,33 @@ service_method_read_alias (GkdSecretService *self, DBusMessage *message) g_object_unref (collection); } - reply = dbus_message_new_method_return (message); if (path == NULL) path = g_strdup ("/"); - dbus_message_append_args (reply, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID); + + gkd_org_freedesktop_secret_service_complete_read_alias (skeleton, invocation, path); g_free (path); - return reply; + return TRUE; } -static DBusMessage* -service_method_set_alias (GkdSecretService *self, DBusMessage *message) +static gboolean +service_method_set_alias (GkdOrgFreedesktopSecretService *skeleton, + GDBusMethodInvocation *invocation, + gchar *alias, + gchar *path, + GkdSecretService *self) { GckObject *collection; gchar *identifier; - const char *alias; - const char *path; - if (!dbus_message_get_args (message, NULL, DBUS_TYPE_STRING, &alias, - DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID)) - return NULL; + gkd_secret_service_ensure_client (self, invocation); - g_return_val_if_fail (alias, NULL); - g_return_val_if_fail (path, NULL); - - if (!g_str_equal (alias, "default")) - return dbus_message_new_error (message, DBUS_ERROR_NOT_SUPPORTED, - "Only the 'default' alias is supported"); + if (!g_str_equal (alias, "default")) { + g_dbus_method_invocation_return_error_literal (invocation, G_DBUS_ERROR, + G_DBUS_ERROR_NOT_SUPPORTED, + "Only the 'default' alias is supported"); + return TRUE; + } /* No default collection */ if (g_str_equal (path, "/")) { @@ -691,16 +678,22 @@ service_method_set_alias (GkdSecretService *self, DBusMessage *message) /* Find a collection with that path */ } else { if (!object_path_has_prefix (path, SECRET_COLLECTION_PREFIX) || - !gkd_secret_util_parse_path (path, &identifier, NULL)) - return dbus_message_new_error (message, DBUS_ERROR_INVALID_ARGS, - "Invalid collection object path"); + !gkd_secret_util_parse_path (path, &identifier, NULL)) { + g_dbus_method_invocation_return_error_literal (invocation, G_DBUS_ERROR, + G_DBUS_ERROR_INVALID_ARGS, + "Invalid collection object path"); + return TRUE; + } collection = gkd_secret_objects_lookup_collection (self->objects, - dbus_message_get_sender (message), path); + g_dbus_method_invocation_get_sender (invocation), + path); if (collection == NULL) { g_free (identifier); - return dbus_message_new_error (message, SECRET_ERROR_NO_SUCH_OBJECT, - "No such collection exists"); + g_dbus_method_invocation_return_error_literal (invocation, GKD_SECRET_ERROR, + GKD_SECRET_ERROR_NO_SUCH_OBJECT, + "The collection does not exist"); + return TRUE; } g_object_unref (collection); @@ -709,37 +702,43 @@ service_method_set_alias (GkdSecretService *self, DBusMessage *message) gkd_secret_service_set_alias (self, alias, identifier); g_free (identifier); - return dbus_message_new_method_return (message); + gkd_org_freedesktop_secret_service_complete_set_alias (skeleton, invocation); + + return TRUE; } -static DBusMessage* -service_method_create_with_master_password (GkdSecretService *self, DBusMessage *message) +static gboolean +service_method_create_with_master_password (GkdOrgGnomeKeyringInternalUnsupportedGuiltRiddenInterface *skeleton, + GDBusMethodInvocation *invocation, + GVariant *attributes, + GVariant *master, + GkdSecretService *self) { GckBuilder builder = GCK_BUILDER_INIT; - DBusError derr = DBUS_ERROR_INIT; - DBusMessageIter iter, array; - DBusMessage *reply = NULL; GkdSecretSecret *secret = NULL; GckAttributes *attrs = NULL; GError *error = NULL; gchar *path; + const gchar *caller; - /* Parse the incoming message */ - if (!dbus_message_has_signature (message, "a{sv}(oayays)")) - return NULL; - if (!dbus_message_iter_init (message, &iter)) - g_return_val_if_reached (NULL); - dbus_message_iter_recurse (&iter, &array); - if (!gkd_secret_property_parse_all (&array, SECRET_COLLECTION_INTERFACE, &builder)) { + gkd_secret_service_ensure_client (self, invocation); + + if (!gkd_secret_property_parse_all (attributes, SECRET_COLLECTION_INTERFACE, &builder)) { gck_builder_clear (&builder); - return dbus_message_new_error (message, DBUS_ERROR_INVALID_ARGS, - "Invalid properties argument"); + g_dbus_method_invocation_return_error_literal (invocation, G_DBUS_ERROR, + G_DBUS_ERROR_INVALID_ARGS, + "Invalid properties argument"); + return TRUE; } - dbus_message_iter_next (&iter); - secret = gkd_secret_secret_parse (self, message, &iter, &derr); + + caller = g_dbus_method_invocation_get_sender (invocation); + secret = gkd_secret_secret_parse (self, + caller, + master, &error); if (secret == NULL) { gck_builder_clear (&builder); - return gkd_secret_error_to_reply (message, &derr); + g_dbus_method_invocation_take_error (invocation, error); + return TRUE; } gck_builder_add_boolean (&builder, CKA_TOKEN, TRUE); @@ -748,64 +747,73 @@ service_method_create_with_master_password (GkdSecretService *self, DBusMessage gck_attributes_unref (attrs); gkd_secret_secret_free (secret); - if (path == NULL) - return gkd_secret_propagate_error (message, "Couldn't create collection", error); + if (path == NULL) { + gkd_secret_propagate_error (invocation, "Couldn't create collection", error); + return TRUE; + } /* Notify the callers that a collection was created */ + g_message ("emit collection_Created"); gkd_secret_service_emit_collection_created (self, path); - reply = dbus_message_new_method_return (message); - dbus_message_append_args (reply, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID); + gkd_org_gnome_keyring_internal_unsupported_guilt_ridden_interface_complete_create_with_master_password + (skeleton, invocation, path); g_free (path); - return reply; + return TRUE; } -static DBusMessage* -service_method_change_with_master_password (GkdSecretService *self, DBusMessage *message) +static gboolean +service_method_change_with_master_password (GkdOrgGnomeKeyringInternalUnsupportedGuiltRiddenInterface *skeleton, + GDBusMethodInvocation *invocation, + gchar *path, + GVariant *original_variant, + GVariant *master_variant, + GkdSecretService *self) { - DBusError derr = DBUS_ERROR_INIT; GkdSecretSecret *original, *master; GckObject *collection; - DBusMessageIter iter; - DBusMessage *reply; GError *error = NULL; - const gchar *path; + const gchar *sender; + + gkd_secret_service_ensure_client (self, invocation); + + sender = g_dbus_method_invocation_get_sender (invocation); /* Parse the incoming message */ - if (!dbus_message_has_signature (message, "o(oayays)(oayays)")) - return NULL; - if (!dbus_message_iter_init (message, &iter)) - g_return_val_if_reached (NULL); - dbus_message_iter_get_basic (&iter, &path); - dbus_message_iter_next (&iter); - original = gkd_secret_secret_parse (self, message, &iter, &derr); - if (original == NULL) - return gkd_secret_error_to_reply (message, &derr); - dbus_message_iter_next (&iter); - master = gkd_secret_secret_parse (self, message, &iter, &derr); + original = gkd_secret_secret_parse (self, sender, + original_variant, &error); + if (original == NULL) { + g_dbus_method_invocation_take_error (invocation, error); + return TRUE; + } + + master = gkd_secret_secret_parse (self, sender, + master_variant, &error); if (master == NULL) { - gkd_secret_secret_free (original); - return gkd_secret_error_to_reply (message, &derr); + g_dbus_method_invocation_take_error (invocation, error); + return TRUE; } /* Make sure we have such a collection */ - collection = gkd_secret_objects_lookup_collection (self->objects, - dbus_message_get_sender (message), + collection = gkd_secret_objects_lookup_collection (self->objects, sender, path); /* No such collection */ - if (collection == NULL) - reply = dbus_message_new_error (message, SECRET_ERROR_NO_SUCH_OBJECT, - "The collection does not exist"); + if (collection == NULL) { + g_dbus_method_invocation_return_error_literal (invocation, GKD_SECRET_ERROR, + GKD_SECRET_ERROR_NO_SUCH_OBJECT, + "The collection does not exist"); + } /* Success */ else if (gkd_secret_change_with_secrets (collection, NULL, original, master, &error)) - reply = dbus_message_new_method_return (message); + gkd_org_gnome_keyring_internal_unsupported_guilt_ridden_interface_complete_change_with_master_password + (skeleton, invocation); /* Failure */ else - reply = gkd_secret_propagate_error (message, "Couldn't change collection password", error); + gkd_secret_propagate_error (invocation, "Couldn't change collection password", error); gkd_secret_secret_free (original); gkd_secret_secret_free (master); @@ -813,49 +821,50 @@ service_method_change_with_master_password (GkdSecretService *self, DBusMessage if (collection) g_object_unref (collection); - return reply; + return TRUE; } -static DBusMessage* -service_method_unlock_with_master_password (GkdSecretService *self, DBusMessage *message) +static gboolean +service_method_unlock_with_master_password (GkdOrgGnomeKeyringInternalUnsupportedGuiltRiddenInterface *skeleton, + GDBusMethodInvocation *invocation, + gchar *path, + GVariant *master_variant, + GkdSecretService *self) { - DBusError derr = DBUS_ERROR_INIT; GkdSecretSecret *master; GError *error = NULL; GckObject *collection; - DBusMessageIter iter; - DBusMessage *reply; - const gchar *path; + const gchar *sender; + + gkd_secret_service_ensure_client (self, invocation); + + sender = g_dbus_method_invocation_get_sender (invocation); /* Parse the incoming message */ - if (!dbus_message_has_signature (message, "o(oayays)")) - return NULL; - if (!dbus_message_iter_init (message, &iter)) - g_return_val_if_reached (NULL); - dbus_message_iter_get_basic (&iter, &path); - dbus_message_iter_next (&iter); - master = gkd_secret_secret_parse (self, message, &iter, &derr); - if (master == NULL) - return gkd_secret_error_to_reply (message, &derr); + master = gkd_secret_secret_parse (self, sender, master_variant, &error); + if (master == NULL) { + g_dbus_method_invocation_take_error (invocation, error); + return TRUE; + } /* Make sure we have such a collection */ - collection = gkd_secret_objects_lookup_collection (self->objects, - dbus_message_get_sender (message), - path); + collection = gkd_secret_objects_lookup_collection (self->objects, sender, path); /* No such collection */ if (collection == NULL) { - reply = dbus_message_new_error (message, SECRET_ERROR_NO_SUCH_OBJECT, - "The collection does not exist"); + g_dbus_method_invocation_return_error_literal (invocation, GKD_SECRET_ERROR, + GKD_SECRET_ERROR_NO_SUCH_OBJECT, + "The collection does not exist"); /* Success */ } else if (gkd_secret_unlock_with_secret (collection, master, &error)) { - reply = dbus_message_new_method_return (message); gkd_secret_objects_emit_collection_locked (self->objects, collection); + gkd_org_gnome_keyring_internal_unsupported_guilt_ridden_interface_complete_unlock_with_master_password + (skeleton, invocation); /* Failure */ } else { - reply = gkd_secret_propagate_error (message, "Couldn't unlock collection", error); + gkd_secret_propagate_error (invocation, "Couldn't unlock collection", error); } gkd_secret_secret_free (master); @@ -863,299 +872,55 @@ service_method_unlock_with_master_password (GkdSecretService *self, DBusMessage if (collection) g_object_unref (collection); - return reply; -} - -static void -on_each_path_append_to_array (GkdSecretObjects *self, - const gchar *path, - GckObject *object, - gpointer user_data) -{ - GPtrArray *array = user_data; - g_ptr_array_add (array, g_strdup (path)); -} - -static DBusMessage * -service_introspect (GkdSecretService *self, - DBusMessage *message) -{ - GPtrArray *names; - DBusMessage *reply; - ServiceClient *client; - const gchar *caller; - const gchar *path; - GHashTableIter iter; - - names = g_ptr_array_new_with_free_func (g_free); - gkd_secret_objects_foreach_collection (self->objects, message, - on_each_path_append_to_array, - names); - - /* Lookup all sessions and prompts for this client */ - caller = dbus_message_get_sender (message); - if (caller != NULL) { - client = g_hash_table_lookup (self->clients, caller); - if (client != NULL) { - g_hash_table_iter_init (&iter, client->dispatch); - while (g_hash_table_iter_next (&iter, (gpointer *)&path, NULL)) - g_ptr_array_add (names, g_strdup (path)); - } - } - - g_ptr_array_add (names, NULL); - - reply = gkd_dbus_introspect_handle (message, gkd_secret_introspect_service, - (const gchar **)names->pdata); - - g_ptr_array_unref (names); - return reply; -} - -static DBusMessage* -service_message_handler (GkdSecretService *self, DBusMessage *message) -{ - g_return_val_if_fail (message, NULL); - g_return_val_if_fail (GKD_SECRET_IS_SERVICE (self), NULL); - - /* org.freedesktop.Secret.Service.OpenSession() */ - if (dbus_message_is_method_call (message, SECRET_SERVICE_INTERFACE, "OpenSession")) - return service_method_open_session (self, message); - - /* org.freedesktop.Secret.Service.CreateCollection() */ - if (dbus_message_is_method_call (message, SECRET_SERVICE_INTERFACE, "CreateCollection")) - return service_method_create_collection (self, message); - - /* org.freedesktop.Secret.Service.LockService() */ - if (dbus_message_is_method_call (message, SECRET_SERVICE_INTERFACE, "LockService")) - return service_method_lock_service (self, message); - - /* org.freedesktop.Secret.Service.SearchItems() */ - if (dbus_message_is_method_call (message, SECRET_SERVICE_INTERFACE, "SearchItems")) - return gkd_secret_objects_handle_search_items (self->objects, message, NULL, TRUE); - - /* org.freedesktop.Secret.Service.GetSecrets() */ - if (dbus_message_is_method_call (message, SECRET_SERVICE_INTERFACE, "GetSecrets")) - return gkd_secret_objects_handle_get_secrets (self->objects, message); - - /* org.freedesktop.Secret.Service.Unlock() */ - if (dbus_message_is_method_call (message, SECRET_SERVICE_INTERFACE, "Unlock")) - return service_method_unlock (self, message); - - /* org.freedesktop.Secret.Service.Lock() */ - if (dbus_message_is_method_call (message, SECRET_SERVICE_INTERFACE, "Lock")) - return service_method_lock (self, message); - - /* org.gnome.keyring.InternalUnsupportedGuiltRiddenInterface.ChangeWithPrompt() */ - if (dbus_message_is_method_call (message, INTERNAL_SERVICE_INTERFACE, "ChangeWithPrompt") || - dbus_message_is_method_call (message, SECRET_SERVICE_INTERFACE, "ChangeLock")) - return service_method_change_lock (self, message); - - /* org.freedesktop.Secret.Service.ReadAlias() */ - if (dbus_message_is_method_call (message, SECRET_SERVICE_INTERFACE, "ReadAlias")) - return service_method_read_alias (self, message); - - /* org.freedesktop.Secret.Service.SetAlias() */ - if (dbus_message_is_method_call (message, SECRET_SERVICE_INTERFACE, "SetAlias")) - return service_method_set_alias (self, message); - - /* org.gnome.keyring.InternalUnsupportedGuiltRiddenInterface.CreateWithMasterPassword */ - if (dbus_message_is_method_call (message, INTERNAL_SERVICE_INTERFACE, "CreateWithMasterPassword")) - return service_method_create_with_master_password (self, message); - - /* org.gnome.keyring.InternalUnsupportedGuiltRiddenInterface.ChangeWithMasterPassword() */ - if (dbus_message_is_method_call (message, INTERNAL_SERVICE_INTERFACE, "ChangeWithMasterPassword")) - return service_method_change_with_master_password (self, message); - - /* org.gnome.keyring.InternalUnsupportedGuiltRiddenInterface.UnlockWithMasterPassword() */ - if (dbus_message_is_method_call (message, INTERNAL_SERVICE_INTERFACE, "UnlockWithMasterPassword")) - return service_method_unlock_with_master_password (self, message); - - /* org.freedesktop.DBus.Properties.Get() */ - if (dbus_message_is_method_call (message, DBUS_INTERFACE_PROPERTIES, "Get")) - return service_property_get (self, message); - - /* org.freedesktop.DBus.Properties.Set() */ - else if (dbus_message_is_method_call (message, DBUS_INTERFACE_PROPERTIES, "Set")) - return service_property_set (self, message); - - /* org.freedesktop.DBus.Properties.GetAll() */ - else if (dbus_message_is_method_call (message, DBUS_INTERFACE_PROPERTIES, "GetAll")) - return service_property_getall (self, message); - - /* org.freedesktop.DBus.Introspectable.Introspect() */ - else if (dbus_message_has_interface (message, DBUS_INTERFACE_INTROSPECTABLE)) - return service_introspect (self, message); - - return NULL; -} - -static gboolean -root_dispatch_message (GkdSecretService *self, - DBusMessage *message) -{ - DBusMessage *reply = NULL; - - if (dbus_message_has_interface (message, DBUS_INTERFACE_INTROSPECTABLE)) - reply = gkd_dbus_introspect_handle (message, gkd_secret_introspect_root, NULL); - - if (reply != NULL) { - dbus_connection_send (self->connection, reply, NULL); - dbus_message_unref (reply); - return TRUE; - } - - return FALSE; + return TRUE; } static void -service_dispatch_message (GkdSecretService *self, DBusMessage *message) +service_name_owner_changed (GDBusConnection *connection, + const gchar *sender_name, + const gchar *object_path, + const gchar *interface_name, + const gchar *signal_name, + GVariant *parameters, + gpointer user_data) { - DBusMessage *reply = NULL; - const gchar *caller; - ServiceClient *client; - const gchar *path; - gpointer object; - - g_assert (GKD_SECRET_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; - } - - 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 */ - } - - path = dbus_message_get_path (message); - g_return_if_fail (path); - - /* Dispatched to a session or prompt */ - if (object_path_has_prefix (path, SECRET_SESSION_PREFIX) || - object_path_has_prefix (path, SECRET_PROMPT_PREFIX)) { - object = g_hash_table_lookup (client->dispatch, path); - if (object == NULL) - reply = gkd_secret_error_no_such_object (message); - else - reply = gkd_secret_dispatch_message (GKD_SECRET_DISPATCH (object), message); - - /* Dispatched to a collection, off it goes */ - } else if (object_path_has_prefix (path, SECRET_COLLECTION_PREFIX) || - object_path_has_prefix (path, SECRET_ALIAS_PREFIX)) { - reply = gkd_secret_objects_dispatch (self->objects, message); - - /* Addressed to the service */ - } else if (g_str_equal (path, SECRET_SERVICE_PATH)) { - reply = service_message_handler (self, message); - } - - /* Should we send an error? */ - if (!reply && dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_CALL) { - if (!dbus_message_get_no_reply (message)) { - 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)); - } - } - - if (reply) { - dbus_connection_send (self->connection, reply, NULL); - dbus_message_unref (reply); - } -} - -static DBusHandlerResult -gkd_secret_service_filter_handler (DBusConnection *conn, DBusMessage *message, gpointer user_data) -{ - GkdSecretService *self = user_data; 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_SECRET_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, DBUS_INTERFACE_DBUS, "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)) { + GkdSecretService *self = user_data; - /* - * 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. + /* A peer is connecting or disconnecting from the bus, + * remove any client info, when client gone. */ - 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 (path != NULL && g_str_equal (path, "/")) { - if (root_dispatch_message (self, message)) - return DBUS_HANDLER_RESULT_HANDLED; - } - - if (object_path_has_prefix (path, SECRET_SERVICE_PATH)) { - interface = dbus_message_get_interface (message); - if (interface == NULL || - g_str_has_prefix (interface, SECRET_INTERFACE_PREFIX) || - g_str_equal (interface, DBUS_INTERFACE_PROPERTIES) || - g_str_equal (interface, INTERNAL_SERVICE_INTERFACE) || - g_str_equal (interface, DBUS_INTERFACE_INTROSPECTABLE)) { - service_dispatch_message (self, message); - return DBUS_HANDLER_RESULT_HANDLED; - } - } - break; + g_variant_get (parameters, "(&s&s&s)", &object_name, &old_owner, &new_owner); - /* Dispatch any signal for one of our objects */ - case DBUS_MESSAGE_TYPE_SIGNAL: - if (object_path_has_prefix (path, SECRET_SERVICE_PATH)) { - service_dispatch_message (self, message); - return DBUS_HANDLER_RESULT_HANDLED; - } - break; - - default: - break; - } - - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + if (g_str_equal (new_owner, "") && object_name[0] == ':') + g_hash_table_remove (self->clients, object_name); } /* ----------------------------------------------------------------------------- * OBJECT */ +static void +gkd_secret_service_init_collections (GkdSecretService *self) +{ + gchar **collections = gkd_secret_service_get_collections (self); + gint idx; + + for (idx = 0; collections[idx] != NULL; idx++) + gkd_secret_objects_register_collection (self->objects, collections[idx]); + + g_strfreev (collections); +} + static GObject* -gkd_secret_service_constructor (GType type, guint n_props, GObjectConstructParam *props) +gkd_secret_service_constructor (GType type, + guint n_props, + GObjectConstructParam *props) { GkdSecretService *self = GKD_SECRET_SERVICE (G_OBJECT_CLASS (gkd_secret_service_parent_class)->constructor(type, n_props, props)); - DBusError error = DBUS_ERROR_INIT; + GError *error = NULL; GckSlot *slot = NULL; guint i; @@ -1173,19 +938,65 @@ gkd_secret_service_constructor (GType type, guint n_props, GObjectConstructParam self->objects = g_object_new (GKD_SECRET_TYPE_OBJECTS, "pkcs11-slot", slot, "service", self, NULL); - /* Register for signals that let us know when clients leave the bus */ - self->match_rule = g_strdup_printf ("type='signal',member=NameOwnerChanged," - "interface='" DBUS_INTERFACE_DBUS "'"); - dbus_bus_add_match (self->connection, self->match_rule, &error); - if (dbus_error_is_set (&error)) { - g_warning ("couldn't listen for NameOwnerChanged signal on session bus: %s", error.message); - dbus_error_free (&error); - g_free (self->match_rule); - self->match_rule = NULL; + self->skeleton = gkd_secret_service_skeleton_new (self); + g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (self->skeleton), + self->connection, + SECRET_SERVICE_PATH, &error); + if (error != NULL) { + g_warning ("could not register secret service on session bus: %s", error->message); + g_clear_error (&error); } - if (!dbus_connection_add_filter (self->connection, gkd_secret_service_filter_handler, self, NULL)) - g_return_val_if_reached (NULL); + g_signal_connect (self->skeleton, "handle-change-lock", + G_CALLBACK (service_method_change_lock), self); + g_signal_connect (self->skeleton, "handle-create-collection", + G_CALLBACK (service_method_create_collection), self); + g_signal_connect (self->skeleton, "handle-get-secrets", + G_CALLBACK (service_method_get_secrets), self); + g_signal_connect (self->skeleton, "handle-lock", + G_CALLBACK (service_method_lock), self); + g_signal_connect (self->skeleton, "handle-lock-service", + G_CALLBACK (service_method_lock_service), self); + g_signal_connect (self->skeleton, "handle-open-session", + G_CALLBACK (service_method_open_session), self); + g_signal_connect (self->skeleton, "handle-read-alias", + G_CALLBACK (service_method_read_alias), self); + g_signal_connect (self->skeleton, "handle-search-items", + G_CALLBACK (service_method_search_items), self); + g_signal_connect (self->skeleton, "handle-set-alias", + G_CALLBACK (service_method_set_alias), self); + g_signal_connect (self->skeleton, "handle-unlock", + G_CALLBACK (service_method_unlock), self); + + self->internal_skeleton = gkd_org_gnome_keyring_internal_unsupported_guilt_ridden_interface_skeleton_new (); + g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (self->internal_skeleton), + self->connection, + SECRET_SERVICE_PATH, &error); + + if (error != NULL) { + g_warning ("could not register internal interface service on session bus: %s", error->message); + g_clear_error (&error); + } + + g_signal_connect (self->internal_skeleton, "handle-change-with-master-password", + G_CALLBACK (service_method_change_with_master_password), self); + g_signal_connect (self->internal_skeleton, "handle-change-with-prompt", + G_CALLBACK (service_method_change_with_prompt), self); + g_signal_connect (self->internal_skeleton, "handle-create-with-master-password", + G_CALLBACK (service_method_create_with_master_password), self); + g_signal_connect (self->internal_skeleton, "handle-unlock-with-master-password", + G_CALLBACK (service_method_unlock_with_master_password), self); + + self->name_owner_id = g_dbus_connection_signal_subscribe (self->connection, + NULL, + "org.freedesktop.DBus", + "NameOwnerChanged", + NULL, NULL, + G_DBUS_SIGNAL_FLAGS_NONE, + service_name_owner_changed, + self, NULL); + + gkd_secret_service_init_collections (self); return G_OBJECT (self); } @@ -1202,11 +1013,9 @@ gkd_secret_service_dispose (GObject *obj) { GkdSecretService *self = GKD_SECRET_SERVICE (obj); - if (self->match_rule) { - g_return_if_fail (self->connection); - dbus_bus_remove_match (self->connection, self->match_rule, NULL); - g_free (self->match_rule); - self->match_rule = NULL; + if (self->name_owner_id) { + g_dbus_connection_signal_unsubscribe (self->connection, self->name_owner_id); + self->name_owner_id = 0; } /* Closes all the clients */ @@ -1219,11 +1028,7 @@ gkd_secret_service_dispose (GObject *obj) self->objects = NULL; } - if (self->connection) { - dbus_connection_remove_filter (self->connection, gkd_secret_service_filter_handler, self); - dbus_connection_unref (self->connection); - self->connection = NULL; - } + g_clear_object (&self->connection); if (self->internal_session) { dispose_and_unref (self->internal_session); @@ -1260,7 +1065,7 @@ gkd_secret_service_set_property (GObject *obj, guint prop_id, const GValue *valu switch (prop_id) { case PROP_CONNECTION: g_return_if_fail (!self->connection); - self->connection = g_value_dup_boxed (value); + self->connection = g_value_dup_object (value); g_return_if_fail (self->connection); break; case PROP_PKCS11_SLOT: @@ -1280,7 +1085,7 @@ gkd_secret_service_get_property (GObject *obj, guint prop_id, GValue *value, switch (prop_id) { case PROP_CONNECTION: - g_value_set_boxed (value, gkd_secret_service_get_connection (self)); + g_value_set_object (value, gkd_secret_service_get_connection (self)); break; case PROP_PKCS11_SLOT: g_value_set_object (value, gkd_secret_service_get_pkcs11_slot (self)); @@ -1303,8 +1108,8 @@ gkd_secret_service_class_init (GkdSecretServiceClass *klass) gobject_class->get_property = gkd_secret_service_get_property; 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)); + g_param_spec_object ("connection", "Connection", "DBus Connection", + G_TYPE_DBUS_CONNECTION, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); 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", @@ -1315,13 +1120,6 @@ gkd_secret_service_class_init (GkdSecretServiceClass *klass) * PUBLIC */ -void -gkd_secret_service_send (GkdSecretService *self, DBusMessage *message) -{ - g_return_if_fail (GKD_SECRET_IS_SERVICE (self)); - dbus_connection_send (self->connection, message, NULL); -} - GkdSecretObjects* gkd_secret_service_get_objects (GkdSecretService *self) { @@ -1329,7 +1127,7 @@ gkd_secret_service_get_objects (GkdSecretService *self) return self->objects; } -DBusConnection* +GDBusConnection* gkd_secret_service_get_connection (GkdSecretService *self) { g_return_val_if_fail (GKD_SECRET_IS_SERVICE (self), NULL); @@ -1552,69 +1350,63 @@ gkd_secret_service_publish_dispatch (GkdSecretService *self, const gchar *caller g_hash_table_replace (client->dispatch, (gpointer)path, g_object_ref (object)); } -static void -emit_collections_properties_changed (GkdSecretService *self) +gchar ** +gkd_secret_service_get_collections (GkdSecretService *self) { - const gchar *iface = SECRET_SERVICE_INTERFACE; - DBusMessage *message; - DBusMessageIter array; - DBusMessageIter iter; - - message = dbus_message_new_signal (SECRET_SERVICE_PATH, - DBUS_INTERFACE_PROPERTIES, - "PropertiesChanged"); - - dbus_message_iter_init_append (message, &iter); - dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &iface); - service_append_all_properties (self, &iter); - dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "s", &array); - dbus_message_iter_close_container (&iter, &array); - - if (!dbus_connection_send (self->connection, message, NULL)) - g_return_if_reached (); - dbus_message_unref (message); + GVariant *collections_variant; + gchar **collections; + + g_return_val_if_fail (GKD_SECRET_IS_SERVICE (self), NULL); + + collections_variant = gkd_secret_objects_append_collection_paths (self->objects, NULL); + collections = g_variant_dup_objv (collections_variant, NULL); + g_variant_unref (collections_variant); + + return collections; } void gkd_secret_service_emit_collection_created (GkdSecretService *self, const gchar *collection_path) { - DBusMessage *message; + gchar **collections; g_return_if_fail (GKD_SECRET_IS_SERVICE (self)); g_return_if_fail (collection_path != NULL); - message = dbus_message_new_signal (SECRET_SERVICE_PATH, - SECRET_SERVICE_INTERFACE, - "CollectionCreated"); - dbus_message_append_args (message, DBUS_TYPE_OBJECT_PATH, &collection_path, - DBUS_TYPE_INVALID); + gkd_secret_objects_register_collection (self->objects, collection_path); - if (!dbus_connection_send (self->connection, message, NULL)) - g_return_if_reached (); - dbus_message_unref (message); + collections = gkd_secret_service_get_collections (self); + gkd_org_freedesktop_secret_service_set_collections (self->skeleton, (const gchar **) collections); + gkd_org_freedesktop_secret_service_emit_collection_created (self->skeleton, collection_path); - emit_collections_properties_changed (self); + g_strfreev (collections); } void gkd_secret_service_emit_collection_deleted (GkdSecretService *self, const gchar *collection_path) { - DBusMessage *message; + gchar **collections; g_return_if_fail (GKD_SECRET_IS_SERVICE (self)); g_return_if_fail (collection_path != NULL); - message = dbus_message_new_signal (SECRET_SERVICE_PATH, - SECRET_SERVICE_INTERFACE, - "CollectionDeleted"); - dbus_message_append_args (message, DBUS_TYPE_OBJECT_PATH, &collection_path, - DBUS_TYPE_INVALID); + gkd_secret_objects_unregister_collection (self->objects, collection_path); + + collections = gkd_secret_service_get_collections (self); + gkd_org_freedesktop_secret_service_set_collections (self->skeleton, (const gchar **) collections); + gkd_org_freedesktop_secret_service_emit_collection_deleted (self->skeleton, collection_path); - if (!dbus_connection_send (self->connection, message, NULL)) - g_return_if_reached (); - dbus_message_unref (message); + g_strfreev (collections); +} + +void +gkd_secret_service_emit_collection_changed (GkdSecretService *self, + const gchar *collection_path) +{ + g_return_if_fail (GKD_SECRET_IS_SERVICE (self)); + g_return_if_fail (collection_path != NULL); - emit_collections_properties_changed (self); + gkd_org_freedesktop_secret_service_emit_collection_changed (self->skeleton, collection_path); } diff --git a/daemon/dbus/gkd-secret-service.h b/daemon/dbus/gkd-secret-service.h index a1845e7c..f95ac960 100644 --- a/daemon/dbus/gkd-secret-service.h +++ b/daemon/dbus/gkd-secret-service.h @@ -25,8 +25,6 @@ #include <gck/gck.h> -#include <dbus/dbus.h> - #include <glib-object.h> #define GKD_SECRET_TYPE_SERVICE (gkd_secret_service_get_type ()) @@ -44,7 +42,7 @@ struct _GkdSecretServiceClass { GType gkd_secret_service_get_type (void); -DBusConnection* gkd_secret_service_get_connection (GkdSecretService *self); +GDBusConnection* gkd_secret_service_get_connection (GkdSecretService *self); GckSlot* gkd_secret_service_get_pkcs11_slot (GkdSecretService *self); @@ -64,9 +62,6 @@ GkdSecretSession* gkd_secret_service_lookup_session (GkdSecretSer void gkd_secret_service_close_session (GkdSecretService *self, GkdSecretSession *sess); -void gkd_secret_service_send (GkdSecretService *self, - DBusMessage *message); - const gchar* gkd_secret_service_get_alias (GkdSecretService *self, const gchar *alias); @@ -84,4 +79,9 @@ void gkd_secret_service_emit_collection_created (GkdSecretSer void gkd_secret_service_emit_collection_deleted (GkdSecretService *self, const gchar *collection_path); +void gkd_secret_service_emit_collection_changed (GkdSecretService *self, + const gchar *collection_path); + +gchar ** gkd_secret_service_get_collections (GkdSecretService *self); + #endif /* ___SECRET_SERVICE_H__ */ diff --git a/daemon/dbus/gkd-secret-session.c b/daemon/dbus/gkd-secret-session.c index 0d0fae2d..834e00c1 100644 --- a/daemon/dbus/gkd-secret-session.c +++ b/daemon/dbus/gkd-secret-session.c @@ -21,13 +21,13 @@ #include "config.h" #include "gkd-secret-dispatch.h" -#include "gkd-secret-introspect.h" +#include "gkd-secret-error.h" #include "gkd-secret-secret.h" #include "gkd-secret-service.h" #include "gkd-secret-session.h" #include "gkd-secret-types.h" #include "gkd-secret-util.h" -#include "gkd-dbus-util.h" +#include "gkd-secrets-generated.h" #include "egg/egg-dh.h" #include "egg/egg-error.h" @@ -50,6 +50,7 @@ struct _GkdSecretSession { /* Information about this object */ gchar *object_path; GkdSecretService *service; + GkdOrgFreedesktopSecretSession *skeleton; gchar *caller_exec; gchar *caller; @@ -166,24 +167,31 @@ aes_derive_key (GckSession *session, GckObject *priv_key, return TRUE; } -static DBusMessage* -aes_negotiate (GkdSecretSession *self, DBusMessage *message, gconstpointer input, gsize n_input) +static gboolean +aes_negotiate (GkdSecretSession *self, + GVariant *input_variant, + GVariant **output_variant, + gchar **result, + GError **error_out) { - DBusMessageIter iter, variant, array; GckSession *session; GckObject *pub, *priv, *key; GError *error = NULL; - DBusMessage *reply; gpointer output; gsize n_output; + const gchar *input; + gsize n_input; gboolean ret; session = gkd_secret_service_get_pkcs11_session (self->service, self->caller); - g_return_val_if_fail (session, NULL); + g_return_val_if_fail (session, FALSE); - if (!aes_create_dh_keys (session, "ietf-ike-grp-modp-1024", &pub, &priv)) - return dbus_message_new_error_printf (message, DBUS_ERROR_FAILED, - "Failed to create necessary crypto keys."); + if (!aes_create_dh_keys (session, "ietf-ike-grp-modp-1024", &pub, &priv)) { + g_set_error_literal (error_out, G_DBUS_ERROR, + G_DBUS_ERROR_FAILED, + "Failed to create necessary crypto keys."); + return FALSE; + } /* Get the output data */ output = gck_object_get_data (pub, CKA_VALUE, NULL, &n_output, &error); @@ -194,10 +202,13 @@ aes_negotiate (GkdSecretSession *self, DBusMessage *message, gconstpointer input g_warning ("couldn't get public key DH value: %s", egg_error_message (error)); g_clear_error (&error); g_object_unref (priv); - return dbus_message_new_error_printf (message, DBUS_ERROR_FAILED, - "Failed to retrieve necessary crypto keys."); + g_set_error_literal (error_out, G_DBUS_ERROR, + G_DBUS_ERROR_FAILED, + "Failed to retrieve necessary crypto keys."); + return FALSE; } + input = g_variant_get_fixed_array (input_variant, &n_input, sizeof (guint8)); ret = aes_derive_key (session, priv, input, n_input, &key); gck_object_destroy (priv, NULL, NULL); @@ -205,38 +216,44 @@ aes_negotiate (GkdSecretSession *self, DBusMessage *message, gconstpointer input if (ret == FALSE) { g_free (output); - return dbus_message_new_error_printf (message, DBUS_ERROR_FAILED, - "Failed to create necessary crypto key."); + g_set_error_literal (error_out, G_DBUS_ERROR, + G_DBUS_ERROR_FAILED, + "Failed to create necessary crypto key."); + return FALSE; } take_session_key (self, key, CKM_AES_CBC_PAD); - reply = dbus_message_new_method_return (message); - dbus_message_iter_init_append (reply, &iter); - dbus_message_iter_open_container (&iter, DBUS_TYPE_VARIANT, "ay", &variant); - dbus_message_iter_open_container (&variant, DBUS_TYPE_ARRAY, "y", &array); - dbus_message_iter_append_fixed_array (&array, DBUS_TYPE_BYTE, &output, n_output); - dbus_message_iter_close_container (&variant, &array); - dbus_message_iter_close_container (&iter, &variant); - dbus_message_iter_append_basic (&iter, DBUS_TYPE_OBJECT_PATH, &self->object_path); + if (output_variant != NULL) { + GVariantBuilder builder; + + g_variant_builder_init (&builder, G_VARIANT_TYPE ("ay")); + g_variant_builder_add (&builder, "y", (const gchar *) output); + *output_variant = g_variant_new_variant (g_variant_builder_end (&builder)); + } + + if (result != NULL) { + *result = g_strdup (self->object_path); + } g_free (output); - return reply; + + return TRUE; } -static DBusMessage* -plain_negotiate (GkdSecretSession *self, DBusMessage *message) +static gboolean +plain_negotiate (GkdSecretSession *self, + GVariant **output, + gchar **result, + GError **error_out) { GckBuilder builder = GCK_BUILDER_INIT; - DBusMessageIter iter, variant; GError *error = NULL; - const char *output = ""; - DBusMessage *reply; GckObject *key; GckSession *session; session = gkd_secret_service_get_pkcs11_session (self->service, self->caller); - g_return_val_if_fail (session, NULL); + g_return_val_if_fail (session, FALSE); gck_builder_add_ulong (&builder, CKA_CLASS, CKO_SECRET_KEY); gck_builder_add_ulong (&builder, CKA_KEY_TYPE, CKK_G_NULL); @@ -246,76 +263,47 @@ plain_negotiate (GkdSecretSession *self, DBusMessage *message) if (key == NULL) { g_warning ("couldn't create null key: %s", egg_error_message (error)); g_clear_error (&error); - return dbus_message_new_error_printf (message, DBUS_ERROR_FAILED, - "Failed to create necessary plain keys."); + g_set_error_literal (error_out, G_DBUS_ERROR, + G_DBUS_ERROR_FAILED, + "Failed to create necessary plain keys."); + return FALSE; } take_session_key (self, key, CKM_G_NULL); - reply = dbus_message_new_method_return (message); - dbus_message_iter_init_append (reply, &iter); - dbus_message_iter_open_container (&iter, DBUS_TYPE_VARIANT, "s", &variant); - dbus_message_iter_append_basic (&variant, DBUS_TYPE_STRING, &output); - dbus_message_iter_close_container (&iter, &variant); - dbus_message_iter_append_basic (&iter, DBUS_TYPE_OBJECT_PATH, &self->object_path); - return reply; + if (output != NULL) { + *output = g_variant_new_variant (g_variant_new_string ("")); + } + + if (result != NULL) { + *result = g_strdup (self->object_path); + } + + return TRUE; } /* ----------------------------------------------------------------------------- * DBUS */ - -static DBusMessage* -session_method_close (GkdSecretSession *self, DBusMessage *message) +static gboolean +session_method_close (GkdOrgFreedesktopSecretSession *skeleton, + GDBusMethodInvocation *invocation, + GkdSecretSession *self) { - DBusMessage *reply; - - g_return_val_if_fail (self->service, NULL); - - if (!dbus_message_get_args (message, NULL, DBUS_TYPE_INVALID)) - return NULL; - gkd_secret_service_close_session (self->service, self); + gkd_org_freedesktop_secret_session_complete_close (skeleton, invocation); - reply = dbus_message_new_method_return (message); - dbus_message_append_args (reply, DBUS_TYPE_INVALID); - return reply; + return TRUE; } /* ----------------------------------------------------------------------------- * OBJECT */ - -static DBusMessage* -gkd_secret_session_real_dispatch_message (GkdSecretDispatch *base, DBusMessage *message) -{ - const gchar *caller; - GkdSecretSession *self; - - g_return_val_if_fail (message, NULL); - g_return_val_if_fail (GKD_SECRET_IS_SESSION (base), NULL); - self = GKD_SECRET_SESSION (base); - - /* 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); - - /* org.freedesktop.Secret.Session.Close() */ - else if (dbus_message_is_method_call (message, SECRET_SESSION_INTERFACE, "Close")) - return session_method_close (self, message); - - /* org.freedesktop.DBus.Introspectable.Introspect() */ - else if (dbus_message_has_interface (message, DBUS_INTERFACE_INTROSPECTABLE)) - return gkd_dbus_introspect_handle (message, gkd_secret_introspect_session, NULL); - - return NULL; -} - static GObject* gkd_secret_session_constructor (GType type, guint n_props, GObjectConstructParam *props) { GkdSecretSession *self = GKD_SECRET_SESSION (G_OBJECT_CLASS (gkd_secret_session_parent_class)->constructor(type, n_props, props)); + GError *error = NULL; g_return_val_if_fail (self, NULL); g_return_val_if_fail (self->caller, NULL); @@ -324,6 +312,19 @@ gkd_secret_session_constructor (GType type, guint n_props, GObjectConstructParam /* Setup the path for the object */ self->object_path = g_strdup_printf (SECRET_SESSION_PREFIX "/s%d", ++unique_session_number); + self->skeleton = gkd_org_freedesktop_secret_session_skeleton_new (); + g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (self->skeleton), + gkd_secret_service_get_connection (self->service), + self->object_path, &error); + + if (error != NULL) { + g_warning ("could not register secret session on session bus: %s", error->message); + g_error_free (error); + } + + g_signal_connect (self->skeleton, "handle-close", + G_CALLBACK (session_method_close), self); + return G_OBJECT (self); } @@ -341,6 +342,11 @@ gkd_secret_session_dispose (GObject *obj) g_free (self->object_path); self->object_path = NULL; + if (self->skeleton) { + g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (self->skeleton)); + g_clear_object (&self->skeleton); + } + if (self->service) { g_object_remove_weak_pointer (G_OBJECT (self->service), (gpointer*)&(self->service)); @@ -457,7 +463,6 @@ gkd_secret_session_class_init (GkdSecretSessionClass *klass) static void gkd_secret_dispatch_iface (GkdSecretDispatchIface *iface) { - iface->dispatch_message = gkd_secret_session_real_dispatch_message; } /* ----------------------------------------------------------------------------- @@ -526,47 +531,49 @@ gkd_secret_session_complete (GkdSecretSession *self, gconstpointer peer, return TRUE; } -DBusMessage* -gkd_secret_session_handle_open (GkdSecretSession *self, DBusMessage *message) +gboolean +gkd_secret_session_handle_open (GkdSecretSession *self, + const gchar *algorithm, + GVariant *input, + GVariant **output, + gchar **result, + GError **error) { - DBusMessage *reply; - const char *algorithm; - DBusMessageIter iter, variant, array; - gconstpointer input; - int n_input; - - /* Parse the incoming message */ - if (!dbus_message_has_signature (message, "sv")) - return NULL; - if (!dbus_message_iter_init (message, &iter)) - g_return_val_if_reached (NULL); - dbus_message_iter_get_basic (&iter, &algorithm); - g_return_val_if_fail (algorithm, NULL); - if (!dbus_message_iter_next (&iter)) - g_return_val_if_reached (NULL); - dbus_message_iter_recurse (&iter, &variant); + const GVariantType *variant_type; + + variant_type = g_variant_get_type (input); /* Plain transfers? just remove our session key */ if (g_str_equal (algorithm, "plain")) { - if (!g_str_equal ("s", dbus_message_iter_get_signature (&variant))) - return dbus_message_new_error (message, DBUS_ERROR_INVALID_ARGS, - "The session algorithm input argument was invalid"); - reply = plain_negotiate (self, message); + if (!g_variant_type_equal (variant_type, G_VARIANT_TYPE_STRING)) { + g_set_error (error, G_DBUS_ERROR, + G_DBUS_ERROR_INVALID_ARGS, + "The session algorithm input argument (%s) was invalid", + algorithm); + return FALSE; + } + + return plain_negotiate (self, output, result, error); } else if (g_str_equal (algorithm, "dh-ietf1024-sha256-aes128-cbc-pkcs7")) { - if (!g_str_equal ("ay", dbus_message_iter_get_signature (&variant))) - return dbus_message_new_error (message, DBUS_ERROR_INVALID_ARGS, - "The session algorithm input argument was invalid"); - dbus_message_iter_recurse (&variant, &array); - dbus_message_iter_get_fixed_array (&array, &input, &n_input); - reply = aes_negotiate (self, message, input, n_input); + if (!g_variant_type_equal (variant_type, G_VARIANT_TYPE_BYTESTRING)) { + g_set_error (error, G_DBUS_ERROR, + G_DBUS_ERROR_INVALID_ARGS, + "The session algorithm input argument (%s) was invalid", + algorithm); + return FALSE; + } + + return aes_negotiate (self, input, output, result, error); } else { - reply = dbus_message_new_error_printf (message, DBUS_ERROR_NOT_SUPPORTED, - "The algorithm '%s' is not supported", algorithm); + g_set_error (error, G_DBUS_ERROR, + G_DBUS_ERROR_NOT_SUPPORTED, + "The algorithm '%s' is not supported", algorithm); + return FALSE; } - return reply; + g_assert_not_reached (); } @@ -593,7 +600,7 @@ gkd_secret_session_get_pkcs11_session (GkdSecretSession *self) GkdSecretSecret* gkd_secret_session_get_item_secret (GkdSecretSession *self, GckObject *item, - DBusError *derr) + GError **error_out) { GckMechanism mech = { 0UL, NULL, 0 }; GckSession *session; @@ -624,12 +631,14 @@ gkd_secret_session_get_item_secret (GkdSecretSession *self, GckObject *item, if (error != NULL) { if (g_error_matches (error, GCK_ERROR, CKR_USER_NOT_LOGGED_IN)) { - dbus_set_error_const (derr, SECRET_ERROR_IS_LOCKED, - "Cannot get secret of a locked object"); + g_set_error_literal (error_out, GKD_SECRET_ERROR, + GKD_SECRET_ERROR_IS_LOCKED, + "Cannot get secret of a locked object"); } else { g_message ("couldn't wrap item secret: %s", egg_error_message (error)); - dbus_set_error_const (derr, DBUS_ERROR_FAILED, - "Couldn't get item secret"); + g_set_error_literal (error_out, G_DBUS_ERROR, + G_DBUS_ERROR_FAILED, + "Couldn't get item secret"); } g_clear_error (&error); g_free (iv); @@ -641,7 +650,7 @@ gkd_secret_session_get_item_secret (GkdSecretSession *self, GckObject *item, gboolean gkd_secret_session_set_item_secret (GkdSecretSession *self, GckObject *item, - GkdSecretSecret *secret, DBusError *derr) + GkdSecretSecret *secret, GError **error_out) { GckBuilder builder = GCK_BUILDER_INIT; GckMechanism mech; @@ -663,8 +672,9 @@ gkd_secret_session_set_item_secret (GkdSecretSession *self, GckObject *item, attrs = gck_object_get (item, NULL, &error, CKA_ID, CKA_G_COLLECTION, GCK_INVALID); if (attrs == NULL) { - g_message ("couldn't get item attributes: %s", egg_error_message (error)); - dbus_set_error_const (derr, DBUS_ERROR_FAILED, "Couldn't set item secret"); + g_set_error_literal (error_out, G_DBUS_ERROR, + G_DBUS_ERROR_FAILED, + "Couldn't set item secret"); g_clear_error (&error); return FALSE; } @@ -684,16 +694,20 @@ gkd_secret_session_set_item_secret (GkdSecretSession *self, GckObject *item, if (object == NULL) { if (g_error_matches (error, GCK_ERROR, CKR_USER_NOT_LOGGED_IN)) { - dbus_set_error_const (derr, SECRET_ERROR_IS_LOCKED, - "Cannot set secret of a locked item"); + g_set_error_literal (error_out, GKD_SECRET_ERROR, + GKD_SECRET_ERROR_IS_LOCKED, + "Cannot set secret of a locked item"); } else if (g_error_matches (error, GCK_ERROR, CKR_WRAPPED_KEY_INVALID) || g_error_matches (error, GCK_ERROR, CKR_WRAPPED_KEY_LEN_RANGE) || g_error_matches (error, GCK_ERROR, CKR_MECHANISM_PARAM_INVALID)) { - dbus_set_error_const (derr, DBUS_ERROR_INVALID_ARGS, - "The secret was transferred or encrypted in an invalid way."); + g_set_error_literal (error_out, G_DBUS_ERROR, + G_DBUS_ERROR_INVALID_ARGS, + "The secret was transferred or encrypted in an invalid way."); } else { g_message ("couldn't unwrap item secret: %s", egg_error_message (error)); - dbus_set_error_const (derr, DBUS_ERROR_FAILED, "Couldn't set item secret"); + g_set_error_literal (error_out, G_DBUS_ERROR, + G_DBUS_ERROR_FAILED, + "Couldn't set item secret"); } g_clear_error (&error); return FALSE; @@ -701,7 +715,9 @@ gkd_secret_session_set_item_secret (GkdSecretSession *self, GckObject *item, if (!gck_object_equal (object, item)) { g_warning ("unwrapped secret went to new object, instead of item"); - dbus_set_error_const (derr, DBUS_ERROR_FAILED, "Couldn't set item secret"); + g_set_error_literal (error_out, G_DBUS_ERROR, + G_DBUS_ERROR_FAILED, + "Couldn't set item secret"); g_object_unref (object); return FALSE; } diff --git a/daemon/dbus/gkd-secret-session.h b/daemon/dbus/gkd-secret-session.h index 8ea6584e..0090f56c 100644 --- a/daemon/dbus/gkd-secret-session.h +++ b/daemon/dbus/gkd-secret-session.h @@ -59,12 +59,12 @@ GckSession* gkd_secret_session_get_pkcs11_session (GkdSecretSession GkdSecretSecret* gkd_secret_session_get_item_secret (GkdSecretSession *self, GckObject *item, - DBusError *derr); + GError **error); gboolean gkd_secret_session_set_item_secret (GkdSecretSession *self, GckObject *item, GkdSecretSecret *secret, - DBusError *derr); + GError **error); GckObject* gkd_secret_session_create_credential (GkdSecretSession *self, GckSession *session, @@ -72,7 +72,11 @@ GckObject* gkd_secret_session_create_credential (GkdSecretSession GkdSecretSecret *secret, GError **error); -DBusMessage* gkd_secret_session_handle_open (GkdSecretSession *self, - DBusMessage *message); +gboolean gkd_secret_session_handle_open (GkdSecretSession *self, + const gchar *algorithm, + GVariant *input, + GVariant **output, + gchar **result, + GError **error); #endif /* __GKD_SECRET_SESSION_H__ */ diff --git a/daemon/dbus/gkd-secret-types.h b/daemon/dbus/gkd-secret-types.h index 06b7dd94..1f756d23 100644 --- a/daemon/dbus/gkd-secret-types.h +++ b/daemon/dbus/gkd-secret-types.h @@ -22,7 +22,6 @@ #define __GKD_SECRET_TYPES_H__ #define INTERNAL_SERVICE_INTERFACE "org.gnome.keyring.InternalUnsupportedGuiltRiddenInterface" -#define INTERNAL_ERROR_DENIED "org.gnome.keyring.Error.Denied" #define SECRET_COLLECTION_INTERFACE "org.freedesktop.Secret.Collection" #define SECRET_ITEM_INTERFACE "org.freedesktop.Secret.Item" @@ -39,10 +38,8 @@ #define SECRET_PROMPT_PREFIX "/org/freedesktop/secrets/prompt" #define SECRET_ALIAS_PREFIX "/org/freedesktop/secrets/aliases" -#define SECRET_ERROR_ALREADY_EXISTS "org.freedesktop.Secret.Error.AlreadyExists" -#define SECRET_ERROR_IS_LOCKED "org.freedesktop.Secret.Error.IsLocked" -#define SECRET_ERROR_NO_SESSION "org.freedesktop.Secret.Error.NoSession" -#define SECRET_ERROR_NO_SUCH_OBJECT "org.freedesktop.Secret.Error.NoSuchObject" +typedef enum _GkdSecretDaemonError GkdSecretDaemonError; +typedef enum _GkdSecretError GkdSecretError; typedef struct _GkdSecretCollection GkdSecretCollection; typedef struct _GkdSecretChange GkdSecretChange; diff --git a/daemon/dbus/gkd-secret-unlock.c b/daemon/dbus/gkd-secret-unlock.c index 1335cdbe..290837c8 100644 --- a/daemon/dbus/gkd-secret-unlock.c +++ b/daemon/dbus/gkd-secret-unlock.c @@ -20,9 +20,8 @@ #include "config.h" -#include "gkd-dbus-util.h" #include "gkd-secret-dispatch.h" -#include "gkd-secret-introspect.h" +#include "gkd-secret-error.h" #include "gkd-secret-objects.h" #include "gkd-secret-secret.h" #include "gkd-secret-session.h" @@ -30,6 +29,7 @@ #include "gkd-secret-types.h" #include "gkd-secret-unlock.h" #include "gkd-secret-util.h" +#include "gkd-secrets-generated.h" #include "egg/egg-error.h" #include "egg/egg-secure-memory.h" @@ -62,6 +62,7 @@ struct _GkdSecretUnlock { GObject parent; gchar *object_path; GkdSecretService *service; + GkdOrgFreedesktopSecretPrompt *skeleton; gchar *caller; gchar *window_id; GQueue *queued; @@ -144,39 +145,23 @@ static gboolean mark_as_complete (GkdSecretUnlock *self, gboolean dismissed) { GkdSecretUnlock *other; - DBusMessage *signal; - DBusMessageIter iter; - dbus_bool_t bval; - DBusMessageIter variant; - DBusMessageIter array; const char *value; gint i; + GVariantBuilder builder; if (self->completed) return FALSE; self->completed = TRUE; - signal = dbus_message_new_signal (self->object_path, SECRET_PROMPT_INTERFACE, - "Completed"); - dbus_message_set_destination (signal, self->caller); - dbus_message_iter_init_append (signal, &iter); - - bval = dismissed; - dbus_message_iter_append_basic (&iter, DBUS_TYPE_BOOLEAN, &bval); - - dbus_message_iter_open_container (&iter, DBUS_TYPE_VARIANT, "ao", &variant); - dbus_message_iter_open_container (&variant, DBUS_TYPE_ARRAY, "o", &array); - + g_variant_builder_init (&builder, G_VARIANT_TYPE ("ao")); for (i = 0; i < self->results->len; ++i) { value = g_array_index (self->results, gchar*, i); - dbus_message_iter_append_basic (&array, DBUS_TYPE_OBJECT_PATH, &value); + g_variant_builder_add (&builder, "o", value); } - dbus_message_iter_close_container (&variant, &array); - dbus_message_iter_close_container (&iter, &variant); - - gkd_secret_service_send (self->service, signal); - dbus_message_unref (signal); + gkd_org_freedesktop_secret_prompt_emit_completed (self->skeleton, + dismissed, + g_variant_new_variant (g_variant_builder_end (&builder))); /* Fire off the next item in the unlock prompt queue */ other = g_queue_pop_head (&unlock_prompt_queue); @@ -313,87 +298,51 @@ perform_next_unlock (GkdSecretUnlock *self) * DBUS */ -static DBusMessage* -prompt_method_prompt (GkdSecretUnlock *self, DBusMessage *message) +static gboolean +prompt_method_prompt (GkdOrgFreedesktopSecretPrompt *skeleton, + GDBusMethodInvocation *invocation, + gchar *window_id, + GkdSecretUnlock *self) { - DBusMessage *reply; - const char *window_id; - /* Act as if this object no longer exists */ if (self->completed) - return NULL; - - if (!dbus_message_get_args (message, NULL, DBUS_TYPE_STRING, - &window_id, DBUS_TYPE_INVALID)) - return NULL; + return FALSE; /* Prompt can only be called once */ - if (self->prompted) - return dbus_message_new_error (message, SECRET_ERROR_ALREADY_EXISTS, - "This prompt has already been shown."); + if (self->prompted) { + g_dbus_method_invocation_return_error_literal (invocation, + GKD_SECRET_ERROR, + GKD_SECRET_ERROR_ALREADY_EXISTS, + "This prompt has already been shown."); + return TRUE; + } gkd_secret_unlock_call_prompt (self, window_id); - reply = dbus_message_new_method_return (message); - dbus_message_append_args (reply, DBUS_TYPE_INVALID); - return reply; + gkd_org_freedesktop_secret_prompt_complete_prompt (skeleton, invocation); + return TRUE; } -static DBusMessage* -prompt_method_dismiss (GkdSecretUnlock *self, DBusMessage *message) +static gboolean +prompt_method_dismiss (GkdOrgFreedesktopSecretPrompt *skeleton, + GDBusMethodInvocation *invocation, + GkdSecretUnlock *self) { - DBusMessage *reply; - /* Act as if this object no longer exists */ if (self->completed) - return NULL; - - if (!dbus_message_get_args (message, NULL, DBUS_TYPE_INVALID)) - return NULL; + return FALSE; g_cancellable_cancel (self->cancellable); mark_as_complete (self, TRUE); - reply = dbus_message_new_method_return (message); - dbus_message_append_args (reply, DBUS_TYPE_INVALID); - return reply; + gkd_org_freedesktop_secret_prompt_complete_dismiss (skeleton, invocation); + return TRUE; } /* ----------------------------------------------------------------------------- * OBJECT */ -static DBusMessage* -gkd_secret_unlock_real_dispatch_message (GkdSecretDispatch *base, DBusMessage *message) -{ - DBusMessage *reply = NULL; - GkdSecretUnlock *self; - const gchar *caller; - - g_return_val_if_fail (message, NULL); - g_return_val_if_fail (GKD_SECRET_IS_UNLOCK (base), NULL); - self = GKD_SECRET_UNLOCK (base); - - /* 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); - - /* org.freedesktop.Secret.Prompt.Prompt() */ - else if (dbus_message_is_method_call (message, SECRET_PROMPT_INTERFACE, "Prompt")) - reply = prompt_method_prompt (self, message); - - /* org.freedesktop.Secret.Prompt.Negotiate() */ - else if (dbus_message_is_method_call (message, SECRET_PROMPT_INTERFACE, "Dismiss")) - reply = prompt_method_dismiss (self, message); - - /* org.freedesktop.DBus.Introspectable.Introspect() */ - else if (dbus_message_has_interface (message, DBUS_INTERFACE_INTROSPECTABLE)) - return gkd_dbus_introspect_handle (message, gkd_secret_introspect_prompt, NULL); - - return reply; -} - static void gkd_secret_unlock_init (GkdSecretUnlock *self) { @@ -406,6 +355,7 @@ static GObject* gkd_secret_unlock_constructor (GType type, guint n_props, GObjectConstructParam *props) { GkdSecretUnlock *self = GKD_SECRET_UNLOCK (G_OBJECT_CLASS (gkd_secret_unlock_parent_class)->constructor(type, n_props, props)); + GError *error = NULL; g_return_val_if_fail (self, NULL); g_return_val_if_fail (self->caller, NULL); @@ -415,6 +365,21 @@ gkd_secret_unlock_constructor (GType type, guint n_props, GObjectConstructParam if (!self->object_path) self->object_path = g_strdup_printf (SECRET_PROMPT_PREFIX "/u%d", ++unique_prompt_number); + self->skeleton = gkd_org_freedesktop_secret_prompt_skeleton_new (); + g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (self->skeleton), + gkd_secret_service_get_connection (self->service), self->object_path, + &error); + + if (error != NULL) { + g_warning ("could not register secret prompt on session bus: %s", error->message); + g_error_free (error); + } + + g_signal_connect (self->skeleton, "handle-dismiss", + G_CALLBACK (prompt_method_dismiss), self); + g_signal_connect (self->skeleton, "handle-prompt", + G_CALLBACK (prompt_method_prompt), self); + return G_OBJECT (self); } @@ -423,6 +388,11 @@ gkd_secret_unlock_dispose (GObject *obj) { GkdSecretUnlock *self = GKD_SECRET_UNLOCK (obj); + if (self->skeleton) { + g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (self->skeleton)); + g_clear_object (&self->skeleton); + } + if (self->service) { g_object_remove_weak_pointer (G_OBJECT (self->service), (gpointer*)&(self->service)); @@ -552,7 +522,6 @@ gkd_secret_unlock_class_init (GkdSecretUnlockClass *klass) static void gkd_secret_dispatch_iface (GkdSecretDispatchIface *iface) { - iface->dispatch_message = gkd_secret_unlock_real_dispatch_message; } /* ----------------------------------------------------------------------------- @@ -674,7 +643,7 @@ gkd_secret_unlock_with_secret (GckObject *collection, gboolean gkd_secret_unlock_with_password (GckObject *collection, const guchar *password, - gsize n_password, DBusError *derr) + gsize n_password, GError **error_out) { GckBuilder builder = GCK_BUILDER_INIT; GError *error = NULL; @@ -700,10 +669,14 @@ gkd_secret_unlock_with_password (GckObject *collection, const guchar *password, cred = gck_session_create_object (session, gck_builder_end (&builder), NULL, &error); if (cred == NULL) { if (g_error_matches (error, GCK_ERROR, CKR_PIN_INCORRECT)) { - dbus_set_error_const (derr, INTERNAL_ERROR_DENIED, "The password was incorrect."); + g_set_error_literal (error_out, GKD_SECRET_DAEMON_ERROR, + GKD_SECRET_DAEMON_ERROR_DENIED, + "The password was incorrect."); } else { g_message ("couldn't create credential: %s", egg_error_message (error)); - dbus_set_error_const (derr, DBUS_ERROR_FAILED, "Couldn't use credentials"); + g_set_error_literal (error_out, G_DBUS_ERROR, + G_DBUS_ERROR_FAILED, + "Couldn't use credentials"); } g_clear_error (&error); return FALSE; diff --git a/daemon/dbus/gkd-secret-unlock.h b/daemon/dbus/gkd-secret-unlock.h index 0f399e3e..77319c52 100644 --- a/daemon/dbus/gkd-secret-unlock.h +++ b/daemon/dbus/gkd-secret-unlock.h @@ -66,6 +66,6 @@ gboolean gkd_secret_unlock_with_secret (GckObject *collec gboolean gkd_secret_unlock_with_password (GckObject *collection, const guchar *password, gsize n_password, - DBusError *derr); + GError **error); #endif /* __GKD_SECRET_UNLOCK_H__ */ diff --git a/daemon/dbus/gkd-secret-util.h b/daemon/dbus/gkd-secret-util.h index f81e3e68..99e7814f 100644 --- a/daemon/dbus/gkd-secret-util.h +++ b/daemon/dbus/gkd-secret-util.h @@ -25,8 +25,6 @@ #include <glib.h> -#include <dbus/dbus.h> - gboolean gkd_secret_util_parse_path (const gchar *path, gchar **collection, gchar **item); diff --git a/daemon/dbus/org.freedesktop.Secrets.xml b/daemon/dbus/org.freedesktop.Secrets.xml new file mode 100644 index 00000000..c1624ef0 --- /dev/null +++ b/daemon/dbus/org.freedesktop.Secrets.xml @@ -0,0 +1,167 @@ +<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" + "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> + +<node name="/org/freedesktop/Secrets"> + + <interface name="org.freedesktop.Secret.Service"> + <property name="Collections" type="ao" access="read" /> + + <method name="OpenSession"> + <arg name="algorithm" type="s" direction="in"/> + <arg name="input" type="v" direction="in"/> + <arg name="output" type="v" direction="out"/> + <arg name="result" type="o" direction="out"/> + </method> + + <method name="CreateCollection"> + <arg name="properties" type="a{sv}" direction="in"/> + <arg name="alias" type="s" direction="in"/> + <arg name="collection" type="o" direction="out"/> + <arg name="prompt" type="o" direction="out"/> + </method> + + <method name="SearchItems"> + <arg name="attributes" type="a{ss}" direction="in"/> + <arg name="unlocked" type="ao" direction="out"/> + <arg name="locked" type="ao" direction="out"/> + </method> + + <method name="Unlock"> + <arg name="objects" type="ao" direction="in"/> + <arg name="unlocked" type="ao" direction="out"/> + <arg name="prompt" type="o" direction="out"/> + </method> + + <method name="Lock"> + <arg name="objects" type="ao" direction="in"/> + <arg name="locked" type="ao" direction="out"/> + <arg name="Prompt" type="o" direction="out"/> + </method> + + <method name="LockService"/> + + <method name="ChangeLock"> + <arg name="collection" type="o" direction="in"/> + <arg name="prompt" type="o" direction="out"/> + </method> + + <method name="GetSecrets"> + <arg name="items" type="ao" direction="in"/> + <arg name="session" type="o" direction="in"/> + <arg name="secrets" type="a{o(oayays)}" direction="out"/> + </method> + + <method name="ReadAlias"> + <arg name="name" type='s' direction='in'/> + <arg name="collection" type='o' direction='out'/> + </method> + + <method name="SetAlias"> + <arg name="name" type='s' direction='in'/> + <arg name="collection" type='o' direction='in'/> + </method> + + <signal name="CollectionCreated"> + <arg name="collection" type="o"/> + </signal> + + <signal name="CollectionDeleted"> + <arg name="collection" type="o"/> + </signal> + + <signal name="CollectionChanged"> + <arg name="collection" type="o"/> + </signal> + + </interface> + + <interface name="org.freedesktop.Secret.Collection"> + + <property name="Items" type="ao" access="read"/> + <property name="Label" type="s" access="readwrite"/> + <property name="Locked" type="b" access="read"/> + <property name="Created" type="t" access="read"/> + <property name="Modified" type="t" access="read"/> + + <method name="Delete"> + <arg name="prompt" type="o" direction="out"/> + </method> + + <method name="SearchItems"> + <arg name="attributes" type="a{ss}" direction="in"/> + <arg name="results" type="ao" direction="out"/> + </method> + + <method name="CreateItem"> + <arg name="properties" type="a{sv}" direction="in"/> + <arg name="secret" type="(oayays)" direction="in"/> + <arg name="replace" type="b" direction="in"/> + <arg name="item" type="o" direction="out"/> + <arg name="prompt" type="o" direction="out"/> + </method> + + <signal name="ItemCreated"> + <arg name="item" type="o"/> + </signal> + + <signal name="ItemDeleted"> + <arg name="item" type="o"/> + </signal> + + <signal name="ItemChanged"> + <arg name="item" type="o"/> + </signal> + + </interface> + + <interface name="org.freedesktop.Secret.Item"> + + <property name="Locked" type="b" access="read"/> + + <property name="Attributes" type="a{ss}" access="readwrite"/> + + <property name="Label" type="s" access="readwrite"/> + + <property name="Created" type="t" access="read"/> + + <property name="Modified" type="t" access="read"/> + + <method name="Delete"> + <arg name="Prompt" type="o" direction="out"/> + </method> + + <method name="GetSecret"> + <arg name="session" type="o" direction="in"/> + <arg name="secret" type="(oayays)" direction="out"/> + </method> + + <method name="SetSecret"> + <arg name="secret" type="(oayays)" direction="in"/> + </method> + + </interface> + + + <interface name="org.freedesktop.Secret.Session"> + + <method name="Close"> + </method> + + </interface> + + <interface name="org.freedesktop.Secret.Prompt"> + + <method name="Prompt"> + <arg name="window_id" type="s" direction="in"/> + </method> + + <method name="Dismiss"> + </method> + + <signal name="Completed"> + <arg name="dismissed" type="b"/> + <arg name="result" type="v"/> + </signal> + </interface> +s +</node> diff --git a/daemon/dbus/org.gnome.keyring.Daemon.xml b/daemon/dbus/org.gnome.keyring.Daemon.xml new file mode 100644 index 00000000..b4334d9b --- /dev/null +++ b/daemon/dbus/org.gnome.keyring.Daemon.xml @@ -0,0 +1,13 @@ +<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" + "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> + +<node name="/org/gnome/keyring/daemon"> + <interface name="org.gnome.keyring.Daemon"> + <method name="GetEnvironment"> + <arg name="Environment" type="a{ss}" direction="out"/> + </method> + <method name="GetControlDirectory"> + <arg name="ControlDirectory" type="s" direction="out"/> + </method> + </interface> +</node> diff --git a/daemon/dbus/org.gnome.keyring.InternalUnsupportedGuiltRiddenInterface.xml b/daemon/dbus/org.gnome.keyring.InternalUnsupportedGuiltRiddenInterface.xml new file mode 100644 index 00000000..c722a00e --- /dev/null +++ b/daemon/dbus/org.gnome.keyring.InternalUnsupportedGuiltRiddenInterface.xml @@ -0,0 +1,25 @@ +<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" + "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> + +<node name="/org/gnome/keyring/InternalUnsupportedGuiltRiddenInterface"> + <interface name="org.gnome.keyring.InternalUnsupportedGuiltRiddenInterface"> + <method name="ChangeWithMasterPassword"> + <arg name="collection" type="o" direction="in"/> + <arg name="original" type="(oayays)" direction="in"/> + <arg name="master" type="(oayays)" direction="in"/> + </method> + <method name="ChangeWithPrompt"> + <arg name="collection" type="o" direction="in"/> + <arg name="prompt" type="o" direction="out"/> + </method> + <method name="CreateWithMasterPassword"> + <arg name="attributes" type="a{sv}" direction="in"/> + <arg name="master" type="(oayays)" direction="in"/> + <arg name="collection" type="o" direction="out"/> + </method> + <method name="UnlockWithMasterPassword"> + <arg name="collection" type="o" direction="in"/> + <arg name="master" type="(oayays)" direction="in"/> + </method> + </interface> +</node> |