gdbus: support unix:dir= addresses

unix:dir= addresses are exactly the same as unix:tmpdir= addresses,
already supported by GDBus, except they forbid use of abstract sockets.
This is convenient for situations where abstract sockets are
impermissible, such as when a D-Bus client inside a network namespace
needs to connect to a server running in a different network namespace.
An abstract socket cannot be shared between two processes in different
network namespaces.

Applications could use unix:path= addresses instead, so this is only a
convenience, but there's no good reason not to support unix:dir=.
Currently it is not supported simply because unix:dir= is a relatively
recent addition to the D-Bus spec.
This commit is contained in:
Michael Catanzaro 2019-06-11 22:35:19 -05:00
parent d2450c8124
commit fc597fa5f9
3 changed files with 20 additions and 10 deletions

View File

@ -127,12 +127,14 @@ is_valid_unix (const gchar *address_entry,
GList *keys; GList *keys;
GList *l; GList *l;
const gchar *path; const gchar *path;
const gchar *dir;
const gchar *tmpdir; const gchar *tmpdir;
const gchar *abstract; const gchar *abstract;
ret = FALSE; ret = FALSE;
keys = NULL; keys = NULL;
path = NULL; path = NULL;
dir = NULL;
tmpdir = NULL; tmpdir = NULL;
abstract = NULL; abstract = NULL;
@ -142,6 +144,8 @@ is_valid_unix (const gchar *address_entry,
const gchar *key = l->data; const gchar *key = l->data;
if (g_strcmp0 (key, "path") == 0) if (g_strcmp0 (key, "path") == 0)
path = g_hash_table_lookup (key_value_pairs, key); path = g_hash_table_lookup (key_value_pairs, key);
else if (g_strcmp0 (key, "dir") == 0)
dir = g_hash_table_lookup (key_value_pairs, key);
else if (g_strcmp0 (key, "tmpdir") == 0) else if (g_strcmp0 (key, "tmpdir") == 0)
tmpdir = g_hash_table_lookup (key_value_pairs, key); tmpdir = g_hash_table_lookup (key_value_pairs, key);
else if (g_strcmp0 (key, "abstract") == 0) else if (g_strcmp0 (key, "abstract") == 0)
@ -158,9 +162,8 @@ is_valid_unix (const gchar *address_entry,
} }
} }
if ((path != NULL && tmpdir != NULL) || /* Exactly one key must be set */
(tmpdir != NULL && abstract != NULL) || if ((path != NULL) + (dir != NULL) + (tmpdir != NULL) + (abstract != NULL) > 1)
(abstract != NULL && path != NULL))
{ {
g_set_error (error, g_set_error (error,
G_IO_ERROR, G_IO_ERROR,
@ -169,12 +172,12 @@ is_valid_unix (const gchar *address_entry,
address_entry); address_entry);
goto out; goto out;
} }
else if (path == NULL && tmpdir == NULL && abstract == NULL) else if (path == NULL && dir == NULL && tmpdir == NULL && abstract == NULL)
{ {
g_set_error (error, g_set_error (error,
G_IO_ERROR, G_IO_ERROR,
G_IO_ERROR_INVALID_ARGUMENT, G_IO_ERROR_INVALID_ARGUMENT,
_("Address “%s” is invalid (need exactly one of path, tmpdir or abstract keys)"), _("Address “%s” is invalid (need exactly one of path, dir, tmpdir, or abstract keys)"),
address_entry); address_entry);
goto out; goto out;
} }

View File

@ -641,7 +641,7 @@ random_ascii (void)
return ret; return ret;
} }
/* note that address_entry has already been validated => exactly one of path, tmpdir or abstract keys are set */ /* note that address_entry has already been validated => exactly one of path, dir, tmpdir, or abstract keys are set */
static gboolean static gboolean
try_unix (GDBusServer *server, try_unix (GDBusServer *server,
const gchar *address_entry, const gchar *address_entry,
@ -650,6 +650,7 @@ try_unix (GDBusServer *server,
{ {
gboolean ret; gboolean ret;
const gchar *path; const gchar *path;
const gchar *dir;
const gchar *tmpdir; const gchar *tmpdir;
const gchar *abstract; const gchar *abstract;
GSocketAddress *address; GSocketAddress *address;
@ -658,6 +659,7 @@ try_unix (GDBusServer *server,
address = NULL; address = NULL;
path = g_hash_table_lookup (key_value_pairs, "path"); path = g_hash_table_lookup (key_value_pairs, "path");
dir = g_hash_table_lookup (key_value_pairs, "dir");
tmpdir = g_hash_table_lookup (key_value_pairs, "tmpdir"); tmpdir = g_hash_table_lookup (key_value_pairs, "tmpdir");
abstract = g_hash_table_lookup (key_value_pairs, "abstract"); abstract = g_hash_table_lookup (key_value_pairs, "abstract");
@ -665,20 +667,21 @@ try_unix (GDBusServer *server,
{ {
address = g_unix_socket_address_new (path); address = g_unix_socket_address_new (path);
} }
else if (tmpdir != NULL) else if (dir != NULL || tmpdir != NULL)
{ {
gint n; gint n;
GString *s; GString *s;
GError *local_error; GError *local_error;
retry: retry:
s = g_string_new (tmpdir); s = g_string_new (tmpdir != NULL ? tmpdir : dir);
g_string_append (s, "/dbus-"); g_string_append (s, "/dbus-");
for (n = 0; n < 8; n++) for (n = 0; n < 8; n++)
g_string_append_c (s, random_ascii ()); g_string_append_c (s, random_ascii ());
/* prefer abstract namespace if available */ /* prefer abstract namespace if available for tmpdir: addresses
if (g_unix_socket_address_abstract_names_supported ()) * abstract namespace is disallowed for dir: addresses */
if (tmpdir != NULL && g_unix_socket_address_abstract_names_supported ())
address = g_unix_socket_address_new_with_type (s->str, address = g_unix_socket_address_new_with_type (s->str,
-1, -1,
G_UNIX_SOCKET_ADDRESS_ABSTRACT); G_UNIX_SOCKET_ADDRESS_ABSTRACT);

View File

@ -113,9 +113,13 @@ test_unix_address (void)
g_assert_false (g_dbus_is_address ("unix:path=/foo;abstract=/bar")); g_assert_false (g_dbus_is_address ("unix:path=/foo;abstract=/bar"));
assert_is_supported_address ("unix:path=/tmp/concrete;unix:abstract=/tmp/abstract"); assert_is_supported_address ("unix:path=/tmp/concrete;unix:abstract=/tmp/abstract");
assert_is_supported_address ("unix:tmpdir=/tmp"); assert_is_supported_address ("unix:tmpdir=/tmp");
assert_is_supported_address ("unix:dir=/tmp");
assert_not_supported_address ("unix:tmpdir=/tmp,path=/tmp"); assert_not_supported_address ("unix:tmpdir=/tmp,path=/tmp");
assert_not_supported_address ("unix:tmpdir=/tmp,abstract=/tmp/foo"); assert_not_supported_address ("unix:tmpdir=/tmp,abstract=/tmp/foo");
assert_not_supported_address ("unix:tmpdir=/tmp,dir=/tmp");
assert_not_supported_address ("unix:path=/tmp,abstract=/tmp/foo"); assert_not_supported_address ("unix:path=/tmp,abstract=/tmp/foo");
assert_not_supported_address ("unix:path=/tmp,dir=/tmp");
assert_not_supported_address ("unix:abstract=/tmp/foo,dir=/tmp");
assert_not_supported_address ("unix:"); assert_not_supported_address ("unix:");
#endif #endif
} }