From a67793d9d52637e08ac841ff9df0f706830fe043 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Mon, 6 Jan 2014 18:12:14 +0000 Subject: [PATCH 3/4] Add xdg-runtime: transport This is basically the same as substituting the environment variable into "unix:path=$XDG_RUNTIME_DIR/dbus_user_bus_socket", but doesn't require escaping the XDG_RUNTIME_DIR if it contains special characters such as ':', and the XDG_RUNTIME_DIR can't get out of sync with the DBUS_SESSION_BUS_ADDRESS this way. --- dbus/dbus-server-unix.c | 31 ++++++++++++++++++++++++ dbus/dbus-sysdeps-unix.c | 39 ++++++++++++++++++++++++++++++ dbus/dbus-sysdeps-unix.h | 3 +++ dbus/dbus-transport-unix.c | 34 ++++++++++++++++++++++++++ doc/dbus-specification.xml | 24 +++++++++++++++++++ test/loopback.c | 60 ++++++++++++++++++++++++++++++++++++++++++++-- 6 files changed, 189 insertions(+), 2 deletions(-) diff --git a/dbus/dbus-server-unix.c b/dbus/dbus-server-unix.c index d995240..7a092ac 100644 --- a/dbus/dbus-server-unix.c +++ b/dbus/dbus-server-unix.c @@ -2,6 +2,7 @@ /* dbus-server-unix.c Server implementation for Unix network protocols. * * Copyright (C) 2002, 2003, 2004 Red Hat Inc. + * Copyright © 2013 Intel Corporation * * Licensed under the Academic Free License version 2.1 * @@ -147,6 +148,36 @@ _dbus_server_listen_platform_specific (DBusAddressEntry *entry, return DBUS_SERVER_LISTEN_DID_NOT_CONNECT; } } + else if (strcmp (method, "xdg-runtime") == 0) + { + DBusString socket_path; + const char *path; + + if (!_dbus_string_init (&socket_path)) + { + _DBUS_SET_OOM (error); + return DBUS_SERVER_LISTEN_DID_NOT_CONNECT; + } + + if (_dbus_append_xdg_runtime_path (&socket_path, error)) + { + path = _dbus_string_get_const_data (&socket_path); + *server_p = _dbus_server_new_for_domain_socket (path, FALSE, error); + } + + _dbus_string_free (&socket_path); + + if (*server_p != NULL) + { + _DBUS_ASSERT_ERROR_IS_CLEAR (error); + return DBUS_SERVER_LISTEN_OK; + } + else + { + _DBUS_ASSERT_ERROR_IS_SET (error); + return DBUS_SERVER_LISTEN_DID_NOT_CONNECT; + } + } else if (strcmp (method, "systemd") == 0) { int i, n, *fds; diff --git a/dbus/dbus-sysdeps-unix.c b/dbus/dbus-sysdeps-unix.c index 7f01564..b3e5995 100644 --- a/dbus/dbus-sysdeps-unix.c +++ b/dbus/dbus-sysdeps-unix.c @@ -3,6 +3,8 @@ * * Copyright (C) 2002, 2003, 2006 Red Hat, Inc. * Copyright (C) 2003 CodeFactory AB + * Copyright © 2013 Intel Corporation + * Copyright © 2014 Collabora Ltd. * * Licensed under the Academic Free License version 2.1 * @@ -4121,4 +4123,41 @@ _dbus_append_address_from_socket (int fd, return FALSE; } +dbus_bool_t +_dbus_append_xdg_runtime_path (DBusString *socket_path, + DBusError *error) +{ + const char *xdg_runtime_dir; + + if (_dbus_check_setuid ()) + { + dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED, + "Unable to use xdg-runtime: address when setuid"); + return FALSE; + } + + xdg_runtime_dir = _dbus_getenv ("XDG_RUNTIME_DIR"); + + if (xdg_runtime_dir == NULL) + { + dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED, + "Unable to use xdg-runtime: address without $XDG_RUNTIME_DIR"); + return FALSE; + } + + if (!_dbus_string_append (socket_path, xdg_runtime_dir)) + { + _DBUS_SET_OOM (error); + return FALSE; + } + + if (!_dbus_string_append (socket_path, "/bus")) + { + _DBUS_SET_OOM (error); + return FALSE; + } + + return TRUE; +} + /* tests in dbus-sysdeps-util.c */ diff --git a/dbus/dbus-sysdeps-unix.h b/dbus/dbus-sysdeps-unix.h index a265b33..4b8ef77 100644 --- a/dbus/dbus-sysdeps-unix.h +++ b/dbus/dbus-sysdeps-unix.h @@ -3,6 +3,7 @@ * * Copyright (C) 2002, 2003, 2006 Red Hat, Inc. * Copyright (C) 2003 CodeFactory AB + * Copyright © 2013 Intel Corporation * * Licensed under the Academic Free License version 2.1 * @@ -141,6 +142,8 @@ void _dbus_close_all (void); dbus_bool_t _dbus_append_address_from_socket (int fd, DBusString *address, DBusError *error); +dbus_bool_t _dbus_append_xdg_runtime_path (DBusString *socket_path, + DBusError *error); /** @} */ diff --git a/dbus/dbus-transport-unix.c b/dbus/dbus-transport-unix.c index 9a9fea5..134ce9b 100644 --- a/dbus/dbus-transport-unix.c +++ b/dbus/dbus-transport-unix.c @@ -2,6 +2,7 @@ /* dbus-transport-unix.c UNIX socket subclasses of DBusTransport * * Copyright (C) 2002, 2003, 2004 Red Hat Inc. + * Copyright © 2013 Intel Corporation * * Licensed under the Academic Free License version 2.1 * @@ -230,6 +231,8 @@ _dbus_transport_open_platform_specific (DBusAddressEntry *entry, method = dbus_address_entry_get_method (entry); _dbus_assert (method != NULL); + _dbus_assert (transport_p != NULL); + _dbus_assert (*transport_p == NULL); if (strcmp (method, "unix") == 0) { @@ -403,6 +406,37 @@ _dbus_transport_open_platform_specific (DBusAddressEntry *entry, } } #endif + else if (strcmp (method, "xdg-runtime") == 0) + { + DBusString socket_path; + const char *path; + + if (!_dbus_string_init (&socket_path)) + { + _DBUS_SET_OOM (error); + return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT; + } + + if (_dbus_append_xdg_runtime_path (&socket_path, error)) + { + path = _dbus_string_get_const_data (&socket_path); + *transport_p = _dbus_transport_new_for_domain_socket (path, FALSE, + error); + } + + _dbus_string_free (&socket_path); + + if (*transport_p != NULL) + { + _DBUS_ASSERT_ERROR_IS_CLEAR (error); + return DBUS_TRANSPORT_OPEN_OK; + } + else + { + _DBUS_ASSERT_ERROR_IS_SET (error); + return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT; + } + } else { _DBUS_ASSERT_ERROR_IS_CLEAR (error); diff --git a/doc/dbus-specification.xml b/doc/dbus-specification.xml index f149555..0f9621b 100644 --- a/doc/dbus-specification.xml +++ b/doc/dbus-specification.xml @@ -3366,6 +3366,30 @@ + + XDG_RUNTIME_DIR on Unix + + This transport uses a well-known Unix domain socket + bus + in the directory whose name is given by the + XDG_RUNTIME_DIR environment variable, + as described in the XDG Base Directory Specification. + Using this transport eliminates the need to escape the path + of that directory (if necessary), or keep the + DBUS_SESSION_BUS_ADDRESS and + XDG_RUNTIME_DIR variables in sync. + + + There are no key/value pairs defined for this transport. + + + Because this transport relies on an environment variable, it is not + supported in setuid, setgid or otherwise privileged processes. + + + This transport is not available on Windows. + + Meta Transports diff --git a/test/loopback.c b/test/loopback.c index 7526d8d..67ad6e0 100644 --- a/test/loopback.c +++ b/test/loopback.c @@ -2,6 +2,8 @@ * * Author: Simon McVittie * Copyright © 2010-2012 Nokia Corporation + * Copyright © 2013 Intel Corporation + * Copyright © 2014 Collabora Ltd. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation files @@ -26,17 +28,22 @@ #include +#ifdef HAVE_ERRNO_H +#include +#endif +#include + #include +#include #include -#include - #include "test-utils.h" typedef struct { TestMainContext *ctx; DBusError e; + GError *error; DBusServer *server; DBusConnection *server_conn; @@ -44,6 +51,9 @@ typedef struct { GQueue server_messages; DBusConnection *client_conn; + + gchar *xdg_runtime_dir; + gchar *xdg_socket; } Fixture; static void @@ -100,6 +110,27 @@ setup (Fixture *f, test_server_setup (f->ctx, f->server); } +#ifdef DBUS_UNIX +static void +setup_xdg_runtime (Fixture *f, + gconstpointer addr) +{ + f->xdg_runtime_dir = g_dir_make_tmp ("dbus-test-loopback-XXXXXX", + &f->error); + g_assert_no_error (f->error); + g_setenv ("XDG_RUNTIME_DIR", f->xdg_runtime_dir, TRUE); + + f->xdg_socket = g_strdup_printf ("%s/bus", + f->xdg_runtime_dir); + + g_assert (!g_file_test (f->xdg_socket, G_FILE_TEST_EXISTS)); + + setup (f, addr); + + g_assert (g_file_test (f->xdg_socket, G_FILE_TEST_EXISTS)); +} +#endif + static void test_connect (Fixture *f, gconstpointer addr G_GNUC_UNUSED) @@ -249,8 +280,30 @@ teardown (Fixture *f, } test_main_context_unref (f->ctx); + + g_clear_error (&f->error); } +#ifdef DBUS_UNIX +static void +teardown_xdg_runtime (Fixture *f, + gconstpointer addr) +{ + g_unsetenv ("XDG_RUNTIME_DIR"); + + g_assert (g_file_test (f->xdg_socket, G_FILE_TEST_EXISTS)); + + teardown (f, addr); + + g_assert (!g_file_test (f->xdg_socket, G_FILE_TEST_EXISTS)); + + g_free (f->xdg_socket); + + if (g_rmdir (f->xdg_runtime_dir) < 0) + g_error ("rmdir(%s): %s", f->xdg_runtime_dir, g_strerror (errno)); +} +#endif + int main (int argc, char **argv) @@ -273,6 +326,9 @@ main (int argc, test_connect, teardown); g_test_add ("/message/unix", Fixture, "unix:tmpdir=/tmp", setup, test_message, teardown); + + g_test_add ("/message/xdg-runtime", Fixture, "xdg-runtime:", + setup_xdg_runtime, test_message, teardown_xdg_runtime); #endif g_test_add ("/message/bad-guid", Fixture, "tcp:host=127.0.0.1", setup, -- 1.8.5.2