From 8024e12aa05d19e87c9c548fe932fccc0c89120f Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Tue, 19 Feb 2013 15:47:26 +0000 Subject: [PATCH 7/8] 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 | 38 +++++++++++++++++++++++++ dbus/dbus-sysdeps-unix.h | 3 ++ dbus/dbus-transport-unix.c | 34 +++++++++++++++++++++++ doc/dbus-specification.xml | 24 ++++++++++++++++ test/loopback.c | 66 ++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 196 insertions(+) diff --git a/dbus/dbus-server-unix.c b/dbus/dbus-server-unix.c index dd20ed8..3864a59 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 * @@ -148,6 +149,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, TRUE, 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 e7ad017..c07df2f 100644 --- a/dbus/dbus-sysdeps-unix.c +++ b/dbus/dbus-sysdeps-unix.c @@ -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 * @@ -4289,4 +4290,41 @@ _dbus_string_get_dirname (const DBusString *filename, } /** @} */ /* DBusString stuff */ +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, "/dbus/user_bus_socket")) + { + _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 6ba5c0b..a5b3be6 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 fe632ea..bf984b5 100644 --- a/doc/dbus-specification.xml +++ b/doc/dbus-specification.xml @@ -3310,6 +3310,30 @@ + + XDG_RUNTIME_DIR on Unix + + This transport uses a well-known Unix domain socket + dbus/user_bus_socket + 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 d0d69c8..a083e1d 100644 --- a/test/loopback.c +++ b/test/loopback.c @@ -2,6 +2,7 @@ * * Author: Simon McVittie * Copyright © 2010-2011 Nokia Corporation + * Copyright © 2013 Intel Corporation * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation files @@ -26,13 +27,19 @@ #include +#ifdef HAVE_ERRNO_H +#include +#endif + #include +#include #include #include typedef struct { DBusError e; + GError *error; DBusServer *server; DBusConnection *server_conn; @@ -40,6 +47,12 @@ typedef struct { GQueue server_messages; DBusConnection *client_conn; + +#ifdef DBUS_UNIX + gchar *xdg_runtime_dir; + gchar *xdg_subdir; + gchar *xdg_socket; +#endif } Fixture; static void @@ -95,6 +108,31 @@ setup (Fixture *f, dbus_server_setup_with_g_main (f->server, NULL); } +#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_subdir = g_strdup_printf ("%s/dbus", + f->xdg_runtime_dir); + f->xdg_socket = g_strdup_printf ("%s/dbus/user_bus_socket", + f->xdg_runtime_dir); + + g_assert (!g_file_test (f->xdg_subdir, G_FILE_TEST_EXISTS)); + g_assert (!g_file_test (f->xdg_socket, G_FILE_TEST_EXISTS)); + + setup (f, addr); + + g_assert (g_file_test (f->xdg_subdir, G_FILE_TEST_IS_DIR)); + g_assert (g_file_test (f->xdg_socket, G_FILE_TEST_EXISTS)); +} +#endif + static void test_connect (Fixture *f, gconstpointer addr G_GNUC_UNUSED) @@ -182,8 +220,33 @@ teardown (Fixture *f, dbus_server_unref (f->server); f->server = NULL; } + + 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_subdir, G_FILE_TEST_IS_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_assert (!g_file_test (f->xdg_subdir, G_FILE_TEST_EXISTS)); + + g_free (f->xdg_socket); + g_free (f->xdg_subdir); + + 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) @@ -205,6 +268,9 @@ main (int argc, test_connect, teardown); g_test_add ("/message/unix", Fixture, "unix:tmpdir=/tmp", setup, test_message, teardown); + + g_test_add ("/connect/xdg-runtime", Fixture, "xdg-runtime:", + setup_xdg_runtime, test_message, teardown_xdg_runtime); #endif return g_test_run (); -- 1.7.10.4