From 026df70eaf0b5563a103b10650668c4d63937edf Mon Sep 17 00:00:00 2001 From: Shawn Landden Date: Thu, 8 Feb 2018 09:19:14 -0800 Subject: [PATCH 1/6] man: update to reflect changes in -H HOST parsing --- man/user-system-options.xml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/man/user-system-options.xml b/man/user-system-options.xml index eb875661de..4ad2d3b16d 100644 --- a/man/user-system-options.xml +++ b/man/user-system-options.xml @@ -33,12 +33,13 @@ Execute the operation remotely. Specify a hostname, or a username and hostname separated by @, to connect to. The hostname may optionally be suffixed by a - container name, separated by :, which + port ssh is listening on, seperated by :, and then a + container name, separated by /, which connects directly to a specific container on the specified host. This will use SSH to talk to the remote machine manager instance. Container names may be enumerated with machinectl -H - HOST. + HOST. Put IPv6 addresses in brackets. From b85b4a70d755f84bf119e3210792d9919bf8e0eb Mon Sep 17 00:00:00 2001 From: Shawn Landden Date: Fri, 9 Feb 2018 10:28:58 -0800 Subject: [PATCH 2/6] sd-bus rework host handling --machine has been missing for a while in systemd-stdio-bridge this syntax can be switched to be more standard. v2: Support the old syntax too. timedatectl -H server1.myhostingcompany.com:5555/container1 Closes: #8071 --- src/libsystemd/sd-bus/sd-bus.c | 78 ++++++++++++++++++++++++++++------ 1 file changed, 64 insertions(+), 14 deletions(-) diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c index 4412fe152f..e0a2a08c6e 100644 --- a/src/libsystemd/sd-bus/sd-bus.c +++ b/src/libsystemd/sd-bus/sd-bus.c @@ -1357,38 +1357,88 @@ _public_ int sd_bus_open_user(sd_bus **ret) { int bus_set_address_system_remote(sd_bus *b, const char *host) { _cleanup_free_ char *e = NULL; - char *m = NULL, *c = NULL, *a; + char *m = NULL, *c = NULL, *a, *rbracket = NULL, *p = NULL; assert(b); assert(host); - /* Let's see if we shall enter some container */ - m = strchr(host, ':'); - if (m) { - m++; + /* Skip ":"s in ipv6 addresses */ + if (*host == '[') { + char *t; - /* Let's make sure this is not a port of some kind, - * and is a valid machine name. */ - if (!in_charset(m, DIGITS) && machine_name_is_valid(m)) { - char *t; + rbracket = strchr(host, ']'); + if (!rbracket) + return -EINVAL; + t = strndupa(host + 1, rbracket - host - 1); + e = bus_address_escape(t); + if (!e) + return -ENOMEM; + } else if ((a = strchr(host, '@'))) + if (*(a + 1) == '[') { + _cleanup_free_ char *t = NULL; - /* Cut out the host part */ - t = strndupa(host, m - host - 1); + rbracket = strchr(a + 1, ']'); + if (!rbracket) + return -EINVAL; + t = new0(char, strlen(host)); + if (!t) + return -ENOMEM; + strncat(t, host, a - host + 1); + strncat(t, a + 2, rbracket - a - 2); e = bus_address_escape(t); if (!e) return -ENOMEM; + } - c = strjoina(",argv5=--machine=", m); + /* Let's see if a port was given */ + m = strchr(rbracket ? rbracket + 1 : host, ':'); + if (m) { + char *t; + bool got_forward_slash = false; + + p = m + 1; + + t = strchr(p, '/'); + if (t) { + p = strndupa(p, t - p); + got_forward_slash = true; + } + + if (!in_charset(p, "0123456789")) { + if (!machine_name_is_valid(p) || got_forward_slash) + return -EINVAL; + else { + m = p; + p = NULL; + goto interpret_port_as_machine_old_syntax; + } } } + /* Let's see if a machine was given */ + m = strchr(rbracket ? rbracket + 1 : host, '/'); + if (m) { + m++; +interpret_port_as_machine_old_syntax: + /* Let's make sure this is not a port of some kind, + * and is a valid machine name. */ + if (!in_charset(m, "0123456789") && machine_name_is_valid(m)) + c = strjoina(",argv", p ? "7" : "5", "=--machine=", m); + } + if (!e) { - e = bus_address_escape(host); + char *t; + + t = strndupa(host, strcspn(host, ":/")); + + e = bus_address_escape(t); if (!e) return -ENOMEM; } - a = strjoin("unixexec:path=ssh,argv1=-xT,argv2=--,argv3=", e, ",argv4=systemd-stdio-bridge", c); + a = strjoin("unixexec:path=ssh,argv1=-xT", p ? ",argv2=-p,argv3=" : "", strempty(p), + ",argv", p ? "4" : "2", "=--,argv", p ? "5" : "3", "=", e, + ",argv", p ? "6" : "4", "=systemd-stdio-bridge", c); if (!a) return -ENOMEM; From 19df1528fc3b8b3069496cba3a83107784a1ccd5 Mon Sep 17 00:00:00 2001 From: Shawn Landden Date: Fri, 9 Feb 2018 10:29:27 -0800 Subject: [PATCH 3/6] stdio-bridge: support --machine --machine hasn't been supported since 798c486 Closes: #8116 --- src/stdio-bridge/stdio-bridge.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/src/stdio-bridge/stdio-bridge.c b/src/stdio-bridge/stdio-bridge.c index 519a92a094..0034ec8878 100644 --- a/src/stdio-bridge/stdio-bridge.c +++ b/src/stdio-bridge/stdio-bridge.c @@ -10,6 +10,7 @@ #include "sd-bus.h" #include "sd-daemon.h" +#include "alloc-util.h" #include "bus-internal.h" #include "bus-util.h" #include "build.h" @@ -18,7 +19,8 @@ #define DEFAULT_BUS_PATH "unix:path=/run/dbus/system_bus_socket" -const char *arg_bus_path = DEFAULT_BUS_PATH; +static const char *arg_bus_path = DEFAULT_BUS_PATH; +static BusTransport arg_transport = BUS_TRANSPORT_LOCAL; static int help(void) { @@ -26,7 +28,8 @@ static int help(void) { "STDIO or socket-activatable proxy to a given DBus endpoint.\n\n" " -h --help Show this help\n" " --version Show package version\n" - " -p --bus-path=PATH Path to the kernel bus (default: %s)\n", + " -p --bus-path=PATH Path to the kernel bus (default: %s)\n" + " -M --machine=MACHINE Name of machine to connect to\n", program_invocation_short_name, DEFAULT_BUS_PATH); return 0; @@ -36,12 +39,14 @@ static int parse_argv(int argc, char *argv[]) { enum { ARG_VERSION = 0x100, + ARG_MACHINE, }; static const struct option options[] = { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, ARG_VERSION }, { "bus-path", required_argument, NULL, 'p' }, + { "machine", required_argument, NULL, 'M' }, {}, }; @@ -66,8 +71,15 @@ static int parse_argv(int argc, char *argv[]) { case 'p': arg_bus_path = optarg; + break; + case 'M': + arg_bus_path = optarg; + + arg_transport = BUS_TRANSPORT_MACHINE; + + break; default: log_error("Unknown option code %c", c); return -EINVAL; @@ -113,7 +125,10 @@ int main(int argc, char *argv[]) { goto finish; } - r = sd_bus_set_address(a, arg_bus_path); + if (arg_transport == BUS_TRANSPORT_MACHINE) + r = bus_set_address_system_machine(a, arg_bus_path); + else + r = sd_bus_set_address(a, arg_bus_path); if (r < 0) { log_error_errno(r, "Failed to set address to connect to: %m"); goto finish; From 2e6fe09002c29bb9529a609a3644c0acbf14e835 Mon Sep 17 00:00:00 2001 From: Shawn Landden Date: Thu, 8 Mar 2018 19:30:48 -0800 Subject: [PATCH 4/6] man/sd_bus_default: update to reflect changes --- man/sd_bus_default.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/man/sd_bus_default.xml b/man/sd_bus_default.xml index 73ad568b91..dfb32b9b4f 100644 --- a/man/sd_bus_default.xml +++ b/man/sd_bus_default.xml @@ -181,7 +181,8 @@ ssh1. host consists of an optional user name followed by the @ symbol, and the hostname, optionally followed by a - : and a machine name. If the machine name is given, a connection + : and a port, optionally followed by a + / and a machine name. If the machine name is given, a connection is created to the system bus in the specified container on the remote machine, and otherwise a connection to the system bus on the specified host is created. From 8a0c1913e0d793336296dd9ea75a26635b0cbde6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Mon, 6 Aug 2018 13:16:29 +0200 Subject: [PATCH 5/6] test-bus-address: a simple test for address parsing --- src/libsystemd/sd-bus/test-bus-address.c | 69 ++++++++++++++++++++++++ src/test/meson.build | 4 ++ 2 files changed, 73 insertions(+) create mode 100644 src/libsystemd/sd-bus/test-bus-address.c diff --git a/src/libsystemd/sd-bus/test-bus-address.c b/src/libsystemd/sd-bus/test-bus-address.c new file mode 100644 index 0000000000..fb3efc3cac --- /dev/null +++ b/src/libsystemd/sd-bus/test-bus-address.c @@ -0,0 +1,69 @@ +#include "sd-bus.h" + +#include "bus-internal.h" +#include "log.h" +#include "string-util.h" +#include "strv.h" + +static void test_one_address(sd_bus *b, + const char *host, + int result, const char *expected) { + int r; + + r = bus_set_address_system_remote(b, host); + log_info("\"%s\" → %d, \"%s\"", host, r, strna(r >= 0 ? b->address : NULL)); + if (result < 0 || expected) { + assert(r == result); + if (r >= 0) + assert_se(streq(b->address, expected)); + } +} + +static void test_bus_set_address_system_remote(char **args) { + _cleanup_(sd_bus_unrefp) sd_bus *b = NULL; + + assert_se(sd_bus_new(&b) >= 0); + if (!strv_isempty(args)) { + char **a; + STRV_FOREACH(a, args) + test_one_address(b, *a, 0, NULL); + return; + }; + + test_one_address(b, "host", + 0, "unixexec:path=ssh,argv1=-xT,argv2=--,argv3=host,argv4=systemd-stdio-bridge"); + test_one_address(b, "host:123", + 0, "unixexec:path=ssh,argv1=-xT,argv2=-p,argv3=123,argv4=--,argv5=host,argv6=systemd-stdio-bridge"); + test_one_address(b, "host:123:123", + -EINVAL, NULL); + // test_one_address(b, "host:", + // -EINVAL, NULL); + test_one_address(b, "user@host", + 0, "unixexec:path=ssh,argv1=-xT,argv2=--,argv3=user%40host,argv4=systemd-stdio-bridge"); + // test_one_address(b, "user@host@host", + // -EINVAL, NULL); + test_one_address(b, "[::1]", + 0, "unixexec:path=ssh,argv1=-xT,argv2=--,argv3=%3a%3a1,argv4=systemd-stdio-bridge"); + test_one_address(b, "user@[::1]", + 0, "unixexec:path=ssh,argv1=-xT,argv2=--,argv3=user%40%3a%3a1,argv4=systemd-stdio-bridge"); + test_one_address(b, "user@[::1]:99", + 0, "unixexec:path=ssh,argv1=-xT,argv2=-p,argv3=99,argv4=--,argv5=user%40%3a%3a1,argv6=systemd-stdio-bridge"); + //test_one_address(b, "user@[::1]:", + // -EINVAL, NULL); + test_one_address(b, "user@[::1:", + -EINVAL, NULL); + //test_one_address(b, "user@", + // -EINVAL, NULL); + //test_one_address(b, "user@@", + // -EINVAL, NULL); +} + +int main(int argc, char *argv[]) { + log_set_max_level(LOG_INFO); + log_parse_environment(); + log_open(); + + test_bus_set_address_system_remote(argv + 1); + + return 0; +} diff --git a/src/test/meson.build b/src/test/meson.build index 18f05b2dc2..dd6c83700d 100644 --- a/src/test/meson.build +++ b/src/test/meson.build @@ -782,6 +782,10 @@ tests += [ ############################################################ tests += [ + [['src/libsystemd/sd-bus/test-bus-address.c'], + [], + [threads]], + [['src/libsystemd/sd-bus/test-bus-marshal.c'], [], [threads, From 6a5558491b27da3181ac6462add72389b8fd328a Mon Sep 17 00:00:00 2001 From: Shawn Landden Date: Mon, 6 Aug 2018 14:21:39 -0700 Subject: [PATCH 6/6] sd-bus: fix test cases on host handling --- src/libsystemd/sd-bus/sd-bus.c | 8 +++++--- src/libsystemd/sd-bus/test-bus-address.c | 20 ++++++++++---------- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c index e0a2a08c6e..0da69a17d6 100644 --- a/src/libsystemd/sd-bus/sd-bus.c +++ b/src/libsystemd/sd-bus/sd-bus.c @@ -1373,7 +1373,7 @@ int bus_set_address_system_remote(sd_bus *b, const char *host) { e = bus_address_escape(t); if (!e) return -ENOMEM; - } else if ((a = strchr(host, '@'))) + } else if ((a = strchr(host, '@'))) { if (*(a + 1) == '[') { _cleanup_free_ char *t = NULL; @@ -1388,7 +1388,9 @@ int bus_set_address_system_remote(sd_bus *b, const char *host) { e = bus_address_escape(t); if (!e) return -ENOMEM; - } + } else if (*(a + 1) == '\0' || strchr(a + 1, '@')) + return -EINVAL; + } /* Let's see if a port was given */ m = strchr(rbracket ? rbracket + 1 : host, ':'); @@ -1404,7 +1406,7 @@ int bus_set_address_system_remote(sd_bus *b, const char *host) { got_forward_slash = true; } - if (!in_charset(p, "0123456789")) { + if (!in_charset(p, "0123456789") || *p == '\0') { if (!machine_name_is_valid(p) || got_forward_slash) return -EINVAL; else { diff --git a/src/libsystemd/sd-bus/test-bus-address.c b/src/libsystemd/sd-bus/test-bus-address.c index fb3efc3cac..db5ff72ef4 100644 --- a/src/libsystemd/sd-bus/test-bus-address.c +++ b/src/libsystemd/sd-bus/test-bus-address.c @@ -36,26 +36,26 @@ static void test_bus_set_address_system_remote(char **args) { 0, "unixexec:path=ssh,argv1=-xT,argv2=-p,argv3=123,argv4=--,argv5=host,argv6=systemd-stdio-bridge"); test_one_address(b, "host:123:123", -EINVAL, NULL); - // test_one_address(b, "host:", - // -EINVAL, NULL); + test_one_address(b, "host:", + -EINVAL, NULL); test_one_address(b, "user@host", 0, "unixexec:path=ssh,argv1=-xT,argv2=--,argv3=user%40host,argv4=systemd-stdio-bridge"); - // test_one_address(b, "user@host@host", - // -EINVAL, NULL); + test_one_address(b, "user@host@host", + -EINVAL, NULL); test_one_address(b, "[::1]", 0, "unixexec:path=ssh,argv1=-xT,argv2=--,argv3=%3a%3a1,argv4=systemd-stdio-bridge"); test_one_address(b, "user@[::1]", 0, "unixexec:path=ssh,argv1=-xT,argv2=--,argv3=user%40%3a%3a1,argv4=systemd-stdio-bridge"); test_one_address(b, "user@[::1]:99", 0, "unixexec:path=ssh,argv1=-xT,argv2=-p,argv3=99,argv4=--,argv5=user%40%3a%3a1,argv6=systemd-stdio-bridge"); - //test_one_address(b, "user@[::1]:", - // -EINVAL, NULL); + test_one_address(b, "user@[::1]:", + -EINVAL, NULL); test_one_address(b, "user@[::1:", -EINVAL, NULL); - //test_one_address(b, "user@", - // -EINVAL, NULL); - //test_one_address(b, "user@@", - // -EINVAL, NULL); + test_one_address(b, "user@", + -EINVAL, NULL); + test_one_address(b, "user@@", + -EINVAL, NULL); } int main(int argc, char *argv[]) {