summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog13
-rw-r--r--Makefile.am3
-rw-r--r--README2
-rw-r--r--configure.in25
-rw-r--r--gnome-keyring-daemon-dbus.c519
-rw-r--r--gnome-keyring-daemon.c8
-rw-r--r--gnome-keyring-daemon.h6
-rw-r--r--gnome-keyring-private.h6
-rw-r--r--gnome-keyring.c131
9 files changed, 677 insertions, 36 deletions
diff --git a/ChangeLog b/ChangeLog
index 836065c8..835d3758 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2007-02-12 Nate Nielsen <nielsen@memberwebs.com>
+
+ * Makefile.am:
+ * README:
+ * configure.in:
+ * gnome-keyring-daemon-dbus.c: (added)
+ * gnome-keyring-daemon.c: (main):
+ * gnome-keyring-daemon.h:
+ * gnome-keyring-private.h:
+ * gnome-keyring.c: (connect_to_daemon):
+ Added secondary method for daemon discover: via DBus. Added dependency
+ on DBus. Fixes bug #400956
+
2007-01-04 Nate Nielsen <nielsen@memberwebs.com>
* configure.in: Bump version number
diff --git a/Makefile.am b/Makefile.am
index 02d49f23..8aa1579f 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -70,7 +70,8 @@ gnome_keyring_daemon_SOURCES = \
gnome-keyring-daemon.c \
gnome-keyring-daemon-file.c \
gnome-keyring-daemon.h \
- gnome-keyring-daemon-io.c
+ gnome-keyring-daemon-io.c \
+ gnome-keyring-daemon-dbus.c
gnome_keyring_daemon_LDADD = \
libgnome-keyring-common.la \
diff --git a/README b/README
index 759b4444..0a87ebef 100644
--- a/README
+++ b/README
@@ -1,6 +1,6 @@
gnome-keyring is a program that keep password and other secrets for
users. It is run as a damon in the session, similar to ssh-agent, and
-other applications can locate it by an environment variable.
+other applications locate it via an environment variable or a dbus.
The program can manage several keyrings, each with its own master
password, and there is also a session keyring which is never stored to
diff --git a/configure.in b/configure.in
index 2e8d2814..bd66b98d 100644
--- a/configure.in
+++ b/configure.in
@@ -55,10 +55,10 @@ AC_TRY_COMPILE([
],[
socklen_t foo;
foo = 1;
-],dbus_have_socklen_t=yes,dbus_have_socklen_t=no)
-AC_MSG_RESULT($dbus_have_socklen_t)
+],have_socklen_t=yes,have_socklen_t=no)
+AC_MSG_RESULT($have_socklen_t)
-if test "x$dbus_have_socklen_t" = "xyes"; then
+if test "x$have_socklen_t" = "xyes"; then
AC_DEFINE(HAVE_SOCKLEN_T,1,[Have socklen_t type])
fi
@@ -71,10 +71,10 @@ AC_TRY_COMPILE([
struct cmsgcred cred;
cred.cmcred_pid = 0;
-],dbus_have_struct_cmsgcred=yes,dbus_have_struct_cmsgcred=no)
-AC_MSG_RESULT($dbus_have_struct_cmsgcred)
+],have_struct_cmsgcred=yes,have_struct_cmsgcred=no)
+AC_MSG_RESULT($have_struct_cmsgcred)
-if test x$dbus_have_struct_cmsgcred = xyes; then
+if test x$have_struct_cmsgcred = xyes; then
AC_DEFINE(HAVE_CMSGCRED,1,[Have cmsgcred structure])
fi
@@ -128,6 +128,19 @@ if test $have_socket = no; then
done
fi
+# DBUS CHECKS
+
+DBUS_REQUIRED=1.0
+
+PKG_CHECK_MODULES([DBUS], [dbus-1 >= $DBUS_REQUIRED], [enable_dbus=yes], [enable_dbus=no])
+if test "$enable_dbus" = "yes"; then
+ AC_DEFINE_UNQUOTED(WITH_DBUS, 1, [Include DBus dependant code])
+fi
+
+CFLAGS="$CFLAGS $DBUS_CFLAGS"
+LIBS="$LIBS $DBUS_LIBS"
+
+
# Check for /dev/random
#
AC_CHECK_FILE(/dev/random, AC_DEFINE(HAVE_DEVRANDOM,1,[Have /dev/random]))
diff --git a/gnome-keyring-daemon-dbus.c b/gnome-keyring-daemon-dbus.c
new file mode 100644
index 00000000..74994984
--- /dev/null
+++ b/gnome-keyring-daemon-dbus.c
@@ -0,0 +1,519 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* gnome-keyring-daemon-dbus.c - daemon usage of dbus
+
+ Copyright (C) 2007, Nate Nielsen
+
+ Gnome keyring is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ Gnome keyring 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
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Author: Nate Nielsen <nielsen@memberwebs.com>
+*/
+
+#include "config.h"
+
+#ifdef WITH_DBUS
+
+#include "gnome-keyring.h"
+#include "gnome-keyring-private.h"
+#include "gnome-keyring-daemon.h"
+
+#include <dbus/dbus.h>
+
+static DBusConnection *dbus_conn = NULL;
+static const char* socket_path = NULL;
+
+/* ------------------------------------------------------------------------
+ * DBUS GLIB MAIN LOOP INTEGRATION
+ *
+ * Copied from dbus-gmain.c due to API instabilities in dbus-glib bindings. :(
+ */
+
+typedef struct {
+ GSource source; /* the parent GSource */
+ DBusConnection *connection; /* the connection to dispatch */
+} DBusGMessageQueue;
+
+static gboolean
+message_queue_prepare (GSource *source, gint *timeout)
+{
+ DBusConnection *connection = ((DBusGMessageQueue *)source)->connection;
+ *timeout = -1;
+ return (dbus_connection_get_dispatch_status (connection) == DBUS_DISPATCH_DATA_REMAINS);
+}
+
+static gboolean
+message_queue_check (GSource *source)
+{
+ return FALSE;
+}
+
+static gboolean
+message_queue_dispatch (GSource *source, GSourceFunc callback, gpointer user_data)
+{
+ DBusConnection *connection = ((DBusGMessageQueue *)source)->connection;
+ dbus_connection_ref (connection);
+
+ /* Only dispatch once - we don't want to starve other GSource */
+ dbus_connection_dispatch (connection);
+ dbus_connection_unref (connection);
+ return TRUE;
+}
+
+static const GSourceFuncs message_queue_funcs = {
+ message_queue_prepare,
+ message_queue_check,
+ message_queue_dispatch,
+ NULL
+};
+
+typedef struct {
+ GMainContext *context; /* the main context */
+ GSList *ios; /* all IOHandler */
+ GSList *timeouts; /* all TimeoutHandler */
+ DBusConnection *connection; /* NULL if this is really for a server not a connection */
+ GSource *message_queue_source; /* DBusGMessageQueue */
+} ConnectionSetup;
+
+static ConnectionSetup *the_setup = NULL;
+
+typedef struct {
+ ConnectionSetup *cs;
+ GSource *source;
+ DBusWatch *watch;
+} IOHandler;
+
+typedef struct {
+ ConnectionSetup *cs;
+ GSource *source;
+ DBusTimeout *timeout;
+} TimeoutHandler;
+
+static ConnectionSetup*
+connection_setup_new (GMainContext *context, DBusConnection *connection)
+{
+ ConnectionSetup *cs = g_new0 (ConnectionSetup, 1);
+ g_assert (context != NULL);
+
+ cs->context = context;
+ g_main_context_ref (cs->context);
+
+ if (connection) {
+ cs->connection = connection;
+ cs->message_queue_source = g_source_new ((GSourceFuncs *) &message_queue_funcs,
+ sizeof (DBusGMessageQueue));
+ ((DBusGMessageQueue*)cs->message_queue_source)->connection = connection;
+ g_source_attach (cs->message_queue_source, cs->context);
+ }
+
+ return cs;
+}
+
+static void
+io_handler_source_finalized (gpointer data)
+{
+ IOHandler *handler = data;
+ if (handler->watch)
+ dbus_watch_set_data (handler->watch, NULL, NULL);
+ g_free (handler);
+}
+
+static void
+io_handler_destroy_source (void *data)
+{
+ IOHandler *handler = data;
+ if (handler->source) {
+ GSource *source = handler->source;
+ handler->source = NULL;
+ handler->cs->ios = g_slist_remove (handler->cs->ios, handler);
+ g_source_destroy (source);
+ g_source_unref (source);
+ }
+}
+
+static void
+io_handler_watch_freed (void *data)
+{
+ IOHandler *handler = data;
+ handler->watch = NULL;
+ io_handler_destroy_source (handler);
+}
+
+static gboolean
+io_handler_dispatch (GIOChannel *source, GIOCondition condition, gpointer data)
+{
+ IOHandler *handler = data;
+ guint dbus_condition = 0;
+ DBusConnection *connection = handler->cs->connection;
+
+ if (connection)
+ dbus_connection_ref (connection);
+
+ if (condition & G_IO_IN)
+ dbus_condition |= DBUS_WATCH_READABLE;
+ if (condition & G_IO_OUT)
+ dbus_condition |= DBUS_WATCH_WRITABLE;
+ if (condition & G_IO_ERR)
+ dbus_condition |= DBUS_WATCH_ERROR;
+ if (condition & G_IO_HUP)
+ dbus_condition |= DBUS_WATCH_HANGUP;
+
+ /* Note that we don't touch the handler after this, because
+ * dbus may have disabled the watch and thus killed the
+ * handler.
+ */
+ dbus_watch_handle (handler->watch, dbus_condition);
+ handler = NULL;
+
+ if (connection)
+ dbus_connection_unref (connection);
+
+ return TRUE;
+}
+
+static void
+connection_setup_add_watch (ConnectionSetup *cs, DBusWatch *watch)
+{
+ guint flags;
+ GIOCondition condition;
+ GIOChannel *channel;
+ IOHandler *handler;
+
+ if (!dbus_watch_get_enabled (watch))
+ return;
+
+ g_assert (dbus_watch_get_data (watch) == NULL);
+
+ flags = dbus_watch_get_flags (watch);
+
+ condition = G_IO_ERR | G_IO_HUP;
+ if (flags & DBUS_WATCH_READABLE)
+ condition |= G_IO_IN;
+ if (flags & DBUS_WATCH_WRITABLE)
+ condition |= G_IO_OUT;
+
+ handler = g_new0 (IOHandler, 1);
+ handler->cs = cs;
+ handler->watch = watch;
+
+ channel = g_io_channel_unix_new (dbus_watch_get_fd (watch));
+
+ handler->source = g_io_create_watch (channel, condition);
+ g_source_set_callback (handler->source, (GSourceFunc) io_handler_dispatch, handler,
+ io_handler_source_finalized);
+ g_source_attach (handler->source, cs->context);
+
+ cs->ios = g_slist_prepend (cs->ios, handler);
+
+ dbus_watch_set_data (watch, handler, io_handler_watch_freed);
+ g_io_channel_unref (channel);
+}
+
+static void
+connection_setup_remove_watch (ConnectionSetup *cs, DBusWatch *watch)
+{
+ IOHandler *handler = dbus_watch_get_data (watch);
+ if (handler != NULL)
+ io_handler_destroy_source (handler);
+}
+
+static void
+timeout_handler_source_finalized (gpointer data)
+{
+ TimeoutHandler *handler = data;
+ if (handler->timeout)
+ dbus_timeout_set_data (handler->timeout, NULL, NULL);
+ g_free (handler);
+}
+
+static void
+timeout_handler_destroy_source (void *data)
+{
+ TimeoutHandler *handler = data;
+ if (handler->source) {
+ GSource *source = handler->source;
+ handler->source = NULL;
+ handler->cs->timeouts = g_slist_remove (handler->cs->timeouts, handler);
+ g_source_destroy (source);
+ g_source_unref (source);
+ }
+}
+
+static void
+timeout_handler_timeout_freed (void *data)
+{
+ TimeoutHandler *handler = data;
+ handler->timeout = NULL;
+ timeout_handler_destroy_source (handler);
+}
+
+static gboolean
+timeout_handler_dispatch (gpointer data)
+{
+ TimeoutHandler *handler = data;
+ dbus_timeout_handle (handler->timeout);
+ return TRUE;
+}
+
+static void
+connection_setup_add_timeout (ConnectionSetup *cs,
+ DBusTimeout *timeout)
+{
+ TimeoutHandler *handler;
+ if (!dbus_timeout_get_enabled (timeout))
+ return;
+ g_assert (dbus_timeout_get_data (timeout) == NULL);
+
+ handler = g_new0 (TimeoutHandler, 1);
+ handler->cs = cs;
+ handler->timeout = timeout;
+
+ handler->source = g_timeout_source_new (dbus_timeout_get_interval (timeout));
+ g_source_set_callback (handler->source, timeout_handler_dispatch, handler,
+ timeout_handler_source_finalized);
+ g_source_attach (handler->source, handler->cs->context);
+ cs->timeouts = g_slist_prepend (cs->timeouts, handler);
+ dbus_timeout_set_data (timeout, handler, timeout_handler_timeout_freed);
+}
+
+static void
+connection_setup_remove_timeout (ConnectionSetup *cs, DBusTimeout *timeout)
+{
+ TimeoutHandler *handler = dbus_timeout_get_data (timeout);
+ if (handler != NULL)
+ timeout_handler_destroy_source (handler);
+}
+
+static void
+connection_setup_free (ConnectionSetup *cs)
+{
+ while (cs->ios)
+ io_handler_destroy_source (cs->ios->data);
+
+ while (cs->timeouts)
+ timeout_handler_destroy_source (cs->timeouts->data);
+
+ if (cs->message_queue_source) {
+ GSource *source = cs->message_queue_source;
+ cs->message_queue_source = NULL;
+
+ g_source_destroy (source);
+ g_source_unref (source);
+ }
+
+ g_main_context_unref (cs->context);
+ g_free (cs);
+}
+
+static dbus_bool_t
+add_watch (DBusWatch *watch, gpointer data)
+{
+ ConnectionSetup *cs = data;
+ connection_setup_add_watch (cs, watch);
+ return TRUE;
+}
+
+static void
+remove_watch (DBusWatch *watch, gpointer data)
+{
+ ConnectionSetup *cs = data;
+ connection_setup_remove_watch (cs, watch);
+}
+
+static void
+watch_toggled (DBusWatch *watch, void *data)
+{
+ if (dbus_watch_get_enabled (watch))
+ add_watch (watch, data);
+ else
+ remove_watch (watch, data);
+}
+
+static dbus_bool_t
+add_timeout (DBusTimeout *timeout, void *data)
+{
+ ConnectionSetup *cs = data;
+ if (!dbus_timeout_get_enabled (timeout))
+ return TRUE;
+ connection_setup_add_timeout (cs, timeout);
+ return TRUE;
+}
+
+static void
+remove_timeout (DBusTimeout *timeout, void *data)
+{
+ ConnectionSetup *cs = data;
+ connection_setup_remove_timeout (cs, timeout);
+}
+
+static void
+timeout_toggled (DBusTimeout *timeout, void *data)
+{
+ if (dbus_timeout_get_enabled (timeout))
+ add_timeout (timeout, data);
+ else
+ remove_timeout (timeout, data);
+}
+
+static void
+wakeup_main (void *data)
+{
+ ConnectionSetup *cs = data;
+ g_main_context_wakeup (cs->context);
+}
+
+static void
+connect_dbus_with_glib (DBusConnection *connection, GMainContext *context)
+{
+ ConnectionSetup *cs;
+
+ if (context == NULL)
+ context = g_main_context_default ();
+ cs = connection_setup_new (context, connection);
+ the_setup = cs;
+
+ if (!dbus_connection_set_watch_functions (connection, add_watch,
+ remove_watch, watch_toggled,
+ cs, NULL))
+ goto nomem;
+
+ if (!dbus_connection_set_timeout_functions (connection, add_timeout,
+ remove_timeout, timeout_toggled,
+ cs, NULL))
+ goto nomem;
+
+ dbus_connection_set_wakeup_main_function (connection, wakeup_main, cs, NULL);
+
+ return;
+
+nomem:
+ g_error ("Not enough memory to set up DBusConnection for use with GLib");
+}
+
+static void
+disconnect_dbus_from_glib (DBusConnection *connection, GMainContext *context)
+{
+ ConnectionSetup *cs = the_setup;
+ the_setup = NULL;
+
+ if (cs)
+ connection_setup_free (cs);
+}
+
+/*
+ * END OF DBUS GLIB CODE
+ * ----------------------------------------------------------------------*/
+
+static DBusHandlerResult
+message_handler_cb (DBusConnection *conn, DBusMessage *message, void *user_data)
+{
+ DBusMessageIter args;
+ DBusMessage *reply;
+
+ if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL ||
+ !dbus_message_is_method_call (message, GNOME_KEYRING_DAEMON_INTERFACE, "GetSocketPath") ||
+ !g_str_equal (dbus_message_get_signature (message), "")) {
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ }
+
+ g_return_val_if_fail (socket_path, 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_append_basic (&args, DBUS_TYPE_STRING, &socket_path))
+ g_return_val_if_reached (DBUS_HANDLER_RESULT_NEED_MEMORY);
+
+ /* Send the reply */
+ if (!dbus_connection_send (dbus_conn, reply, NULL))
+ g_return_val_if_reached (DBUS_HANDLER_RESULT_NEED_MEMORY);
+ dbus_connection_flush (dbus_conn);
+
+ return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static DBusObjectPathVTable object_vtable = {
+ NULL,
+ message_handler_cb,
+ NULL,
+};
+
+void
+gnome_keyring_daemon_dbus_setup (GMainLoop *loop, const gchar *socket)
+{
+ dbus_uint32_t res = 0;
+ DBusError derr = { 0 };
+
+ socket_path = socket;
+ dbus_error_init (&derr);
+
+ /* Get the dbus bus and hook up */
+ dbus_conn = dbus_bus_get (DBUS_BUS_SESSION, &derr);
+ if (!dbus_conn) {
+ g_warning ("couldn't connect to dbus session bus: %s", derr.message);
+ dbus_error_free (&derr);
+ return;
+ }
+
+ connect_dbus_with_glib (dbus_conn, NULL);
+
+ /* Make sure dbus doesn't kill our app */
+ dbus_connection_set_exit_on_disconnect (dbus_conn, FALSE);
+
+ /* Try and grab our name */
+ res = dbus_bus_request_name (dbus_conn, GNOME_KEYRING_DAEMON_SERVICE,
+ DBUS_NAME_FLAG_DO_NOT_QUEUE, &derr);
+ if (dbus_error_is_set (&derr)) {
+ g_warning ("couldn't request name on session bus: %s", derr.message);
+ dbus_error_free (&derr);
+ }
+
+ switch (res) {
+ /* We acquired the service name */
+ case DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER:
+ break;
+ /* We already acquired the service name. Odd */
+ case DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER:
+ g_return_if_reached ();
+ break;
+ /* Another daemon is running */
+ case DBUS_REQUEST_NAME_REPLY_IN_QUEUE:
+ case DBUS_REQUEST_NAME_REPLY_EXISTS:
+ g_message ("another gnome-keyring-daemon is running");
+ return;
+ default:
+ g_return_if_reached ();
+ break;
+ };
+
+ /* Now register the object */
+ if (!dbus_connection_register_object_path (dbus_conn, GNOME_KEYRING_DAEMON_PATH,
+ &object_vtable, NULL)) {
+ g_warning ("couldn't register dbus object path");
+ return;
+ }
+}
+
+void
+gnome_keyring_daemon_dbus_cleanup (void)
+{
+ if (dbus_conn) {
+ dbus_connection_unregister_object_path (dbus_conn, GNOME_KEYRING_DAEMON_PATH);
+ disconnect_dbus_from_glib (dbus_conn, NULL);
+ dbus_connection_unref (dbus_conn);
+ dbus_conn = NULL;
+ }
+}
+
+#endif
+
diff --git a/gnome-keyring-daemon.c b/gnome-keyring-daemon.c
index 55e37f9b..cd58976c 100644
--- a/gnome-keyring-daemon.c
+++ b/gnome-keyring-daemon.c
@@ -2992,9 +2992,17 @@ main (int argc, char *argv[])
}
+#ifdef WITH_DBUS
+ gnome_keyring_daemon_dbus_setup (loop, path);
+#endif
g_main_loop_run (loop);
+
+#ifdef WITH_DBUS
+ gnome_keyring_daemon_dbus_cleanup ();
+#endif
cleanup_socket_dir ();
return 0;
}
+
diff --git a/gnome-keyring-daemon.h b/gnome-keyring-daemon.h
index ff6ff38b..660104dc 100644
--- a/gnome-keyring-daemon.h
+++ b/gnome-keyring-daemon.h
@@ -182,4 +182,10 @@ extern GList *keyrings;
extern GnomeKeyring *session_keyring;
extern GnomeKeyring *default_keyring;
+/* Dbus Initialization/Cleanup */
+#ifdef WITH_DBUS
+void gnome_keyring_daemon_dbus_setup (GMainLoop *loop, const gchar* socket);
+void gnome_keyring_daemon_dbus_cleanup (void);
+#endif
+
#endif /* GNOME_KEYRING_DAEMON_H */
diff --git a/gnome-keyring-private.h b/gnome-keyring-private.h
index 3fda2420..f1c17a76 100644
--- a/gnome-keyring-private.h
+++ b/gnome-keyring-private.h
@@ -59,5 +59,11 @@ typedef enum {
GNOME_KEYRING_ASK_RESPONSE_ALLOW_FOREVER
} GnomeKeyringAskResponse;
+#ifdef WITH_DBUS
+#define GNOME_KEYRING_DAEMON_SERVICE "org.gnome.keyring"
+#define GNOME_KEYRING_DAEMON_PATH "/org/gnome/keyring/daemon"
+#define GNOME_KEYRING_DAEMON_INTERFACE "org.gnome.keyring.Daemon"
+#endif
#endif /* GNOME_KEYRING_PRIVATE_H */
+
diff --git a/gnome-keyring.c b/gnome-keyring.c
index 23d8f23a..c3e7fb99 100644
--- a/gnome-keyring.c
+++ b/gnome-keyring.c
@@ -40,6 +40,10 @@
#include <sys/un.h>
#include <stdarg.h>
+#ifdef WITH_DBUS
+#include <dbus/dbus.h>
+#endif
+
typedef enum {
CALLBACK_DONE,
CALLBACK_GET_STRING,
@@ -84,37 +88,69 @@ struct GnomeKeyringOperation {
KeyringHandleReply reply_handler;
};
-/**
- * GnomeKeyringAttributeList:
- *
- * A list of keyring item attributes. It's used to search for keyring items
- * with eg. gnome_keyring_find_items_sync().
- */
+#ifdef WITH_DBUS
+
+static gchar*
+find_daemon_via_dbus ()
+{
+ DBusConnection *dconn;
+ DBusMessage *reply;
+ DBusMessage *msg;
+ DBusMessageIter args;
+ DBusError derr;
+ char* socket = NULL;
+
+ dbus_error_init (&derr);
+ dconn = dbus_bus_get (DBUS_BUS_SESSION, &derr);
+ if (!dconn) {
+ g_warning ("couldn't connect to dbus session bus: %s", derr.message);
+ return NULL;
+ }
+
+ msg = dbus_message_new_method_call (GNOME_KEYRING_DAEMON_SERVICE,
+ GNOME_KEYRING_DAEMON_PATH,
+ GNOME_KEYRING_DAEMON_INTERFACE,
+ "GetSocketPath");
+ if (!msg) {
+ g_warning ("couldn't create dbus message");
+ dbus_connection_unref (dconn);
+ return NULL;
+ }
+
+ /* Send message and get a handle for a reply */
+ reply = dbus_connection_send_with_reply_and_block (dconn, msg, 1000, &derr);
+ dbus_message_unref (msg);
+ if (!reply) {
+ g_warning ("couldn't communicate with gnome keyring daemon via dbus: %s", derr.message);
+ dbus_connection_unref (dconn);
+ return NULL;
+ }
+
+ /* Read the return value */
+ if (!dbus_message_iter_init(reply, &args) ||
+ dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_STRING) {
+ g_warning ("gnome-keyring-daemon sent back an invalid reply");
+ } else {
+ dbus_message_iter_get_basic(&args, &socket);
+ socket = g_strdup (socket);
+ }
-/**
- * gnome_keyring_attribute_list_new():
- *
- * Create a new #GnomeKeyringAttributeList.
- *
- * Returns an empty #GnomeKeyringAttributeList.
- */
+ dbus_message_unref (reply);
+ dbus_connection_unref (dconn);
-static int
-connect_to_daemon (gboolean non_blocking)
+ return socket;
+}
+
+#endif
+
+static int
+connect_to_daemon_at (const gchar *path)
{
- const char *socket_file;
struct sockaddr_un addr;
int sock;
- int val;
-
- socket_file = g_getenv ("GNOME_KEYRING_SOCKET");
-
- if (socket_file == NULL) {
- return -1;
- }
addr.sun_family = AF_UNIX;
- strncpy (addr.sun_path, socket_file, sizeof (addr.sun_path));
+ strncpy (addr.sun_path, path, sizeof (addr.sun_path));
sock = socket (AF_UNIX, SOCK_STREAM, 0);
if (sock < 0) {
@@ -132,13 +168,52 @@ connect_to_daemon (gboolean non_blocking)
return -1;
}
- val = fcntl (sock, F_GETFL, 0);
- if (val < 0) {
- close (sock);
- return -1;
+ return sock;
+}
+
+static int
+connect_to_daemon (gboolean non_blocking)
+{
+ const gchar *epath = NULL;
+ int sock = -1;
+ int val;
+
+ /* Try using the environment variable */
+ epath = g_getenv ("GNOME_KEYRING_SOCKET");
+ if (epath && epath[0]) {
+ sock = connect_to_daemon_at (epath);
+ if (sock < 0) {
+ g_warning ("couldn't connect to daemon at $GNOME_KEYRING_SOCKET: %s: %s",
+ epath, g_strerror (errno));
+ }
+ }
+
+#ifdef WITH_DBUS
+ /* Try using DBus to find daemon */
+ if (sock < 0) {
+ gchar *dpath = find_daemon_via_dbus ();
+ if (dpath) {
+ sock = connect_to_daemon_at (dpath);
+ g_free (dpath);
+ if (sock < 0) {
+ g_warning ("couldn't connect to daemon at DBus discovered socket: %s: %s",
+ dpath, g_strerror (errno));
+ }
+ }
}
+#endif
+ if (sock < 0)
+ return -1;
+
+ /* Setup non blocking */
if (non_blocking) {
+ val = fcntl (sock, F_GETFL, 0);
+ if (val < 0) {
+ close (sock);
+ return -1;
+ }
+
if (fcntl (sock, F_SETFL, val | O_NONBLOCK) < 0) {
close (sock);
return -1;