From 7f0d207d2c816e0a8cb2742b0a789911f7c99356 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 3 Jul 2014 01:17:26 +0200 Subject: [PATCH] sd-bus: support connecting to remote hosts, directly into containers systemctl -H root@foobar:waldi will now show a list of services running on container "waldi" on host "foobar", using "root" for authenticating at "foobar". Since entereing a container requires priviliges, this will only work correctly for root logins. --- src/bus-proxyd/bus-proxyd.c | 55 +++++++++++++++++++++++++++++----- src/libsystemd/sd-bus/sd-bus.c | 31 ++++++++++++++++--- src/machine/machined-dbus.c | 19 +----------- src/shared/util.c | 15 ++++++++++ src/shared/util.h | 2 ++ 5 files changed, 93 insertions(+), 29 deletions(-) diff --git a/src/bus-proxyd/bus-proxyd.c b/src/bus-proxyd/bus-proxyd.c index 3f095e0a3..79dbdcf36 100644 --- a/src/bus-proxyd/bus-proxyd.c +++ b/src/bus-proxyd/bus-proxyd.c @@ -47,7 +47,7 @@ #include "capability.h" #include "bus-policy.h" -static const char *arg_address = DEFAULT_SYSTEM_BUS_PATH; +static char *arg_address = NULL; static char *arg_command_line_buffer = NULL; static bool arg_drop_privileges = false; static char **arg_configuration = NULL; @@ -60,8 +60,9 @@ static int help(void) { " --version Show package version\n" " --drop-privileges Drop privileges\n" " --configuration=PATH Configuration file or directory\n" + " --machine=MACHINE Connect to specified machine\n" " --address=ADDRESS Connect to the bus specified by ADDRESS\n" - " (default: " KERNEL_SYSTEM_BUS_PATH ")\n", + " (default: " DEFAULT_SYSTEM_BUS_PATH ")\n", program_invocation_short_name); return 0; @@ -74,6 +75,7 @@ static int parse_argv(int argc, char *argv[]) { ARG_ADDRESS, ARG_DROP_PRIVILEGES, ARG_CONFIGURATION, + ARG_MACHINE, }; static const struct option options[] = { @@ -82,7 +84,8 @@ static int parse_argv(int argc, char *argv[]) { { "address", required_argument, NULL, ARG_ADDRESS }, { "drop-privileges", no_argument, NULL, ARG_DROP_PRIVILEGES }, { "configuration", required_argument, NULL, ARG_CONFIGURATION }, - { NULL, 0, NULL, 0 }, + { "machine", required_argument, NULL, ARG_MACHINE }, + {}, }; int c, r; @@ -103,9 +106,17 @@ static int parse_argv(int argc, char *argv[]) { puts(SYSTEMD_FEATURES); return 0; - case ARG_ADDRESS: - arg_address = optarg; + case ARG_ADDRESS: { + char *a; + + a = strdup(optarg); + if (!a) + return log_oom(); + + free(arg_address); + arg_address = a; break; + } case ARG_DROP_PRIVILEGES: arg_drop_privileges = true; @@ -117,6 +128,28 @@ static int parse_argv(int argc, char *argv[]) { return log_oom(); break; + case ARG_MACHINE: { + _cleanup_free_ char *e = NULL; + char *a; + + e = bus_address_escape(optarg); + if (!e) + return log_oom(); + +#ifdef ENABLE_KDBUS + a = strjoin("x-container-kernel:machine=", e, ";x-container-unix:machine=", e, NULL); +#else + a = strjoin("x-container-unix:machine=", e, NULL); +#endif + if (!a) + return log_oom(); + + free(arg_address); + arg_address = a; + + break; + } + case '?': return -EINVAL; @@ -129,12 +162,17 @@ static int parse_argv(int argc, char *argv[]) { * we'll write who we are talking to into it, so that "ps" is * explanatory */ arg_command_line_buffer = argv[optind]; - if (argc > optind + 1 || - (arg_command_line_buffer && arg_command_line_buffer[strspn(arg_command_line_buffer, "x")] != 0)) { + if (argc > optind + 1 || (arg_command_line_buffer && !in_charset(arg_command_line_buffer, "x"))) { log_error("Too many arguments"); return -EINVAL; } + if (!arg_address) { + arg_address = strdup(DEFAULT_SYSTEM_BUS_PATH); + if (!arg_address) + return log_oom(); + } + return 1; } @@ -1439,9 +1477,12 @@ int main(int argc, char *argv[]) { finish: sd_bus_flush(a); sd_bus_flush(b); + sd_bus_close(a); + sd_bus_close(b); policy_free(&policy); strv_free(arg_configuration); + free(arg_address); return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c index eb267d430..c25375c59 100644 --- a/src/libsystemd/sd-bus/sd-bus.c +++ b/src/libsystemd/sd-bus/sd-bus.c @@ -1209,15 +1209,38 @@ fail: int bus_set_address_system_remote(sd_bus *b, const char *host) { _cleanup_free_ char *e = NULL; + char *m = NULL, *c = NULL; assert(b); assert(host); - e = bus_address_escape(host); - if (!e) - return -ENOMEM; + /* Let's see if we shall enter some container */ + m = strchr(host, ':'); + if (m) { + m++; + + /* 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)) { + char *t; + + /* Cut out the host part */ + t = strndupa(host, m - host - 1); + e = bus_address_escape(t); + if (!e) + return -ENOMEM; + + c = strappenda(",argv4=--machine=", m); + } + } + + if (!e) { + e = bus_address_escape(host); + if (!e) + return -ENOMEM; + } - b->address = strjoin("unixexec:path=ssh,argv1=-xT,argv2=", e, ",argv3=systemd-stdio-bridge", NULL); + b->address = strjoin("unixexec:path=ssh,argv1=-xT,argv2=", e, ",argv3=systemd-stdio-bridge", c, NULL); if (!b->address) return -ENOMEM; diff --git a/src/machine/machined-dbus.c b/src/machine/machined-dbus.c index 0078a277d..6f8ba474f 100644 --- a/src/machine/machined-dbus.c +++ b/src/machine/machined-dbus.c @@ -41,23 +41,6 @@ #include "cgroup-util.h" #include "machined.h" -static bool valid_machine_name(const char *p) { - size_t l; - - if (!filename_is_safe(p)) - return false; - - if (!ascii_is_valid(p)) - return false; - - l = strlen(p); - - if (l < 1 || l> 64) - return false; - - return true; -} - static int method_get_machine(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) { _cleanup_free_ char *p = NULL; Manager *m = userdata; @@ -185,7 +168,7 @@ static int method_create_or_register_machine(Manager *manager, sd_bus_message *m r = sd_bus_message_read(message, "s", &name); if (r < 0) return r; - if (!valid_machine_name(name)) + if (!machine_name_is_valid(name)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid machine name"); r = sd_bus_message_read_array(message, 'y', &v, &n); diff --git a/src/shared/util.c b/src/shared/util.c index 4ad3f203d..3d875c72b 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -3975,6 +3975,21 @@ char* hostname_cleanup(char *s, bool lowercase) { return s; } +bool machine_name_is_valid(const char *s) { + + if (!hostname_is_valid(s)) + return false; + + /* Machine names should be useful hostnames, but also be + * useful in unit names, hence we enforce a stricter length + * limitation. */ + + if (strlen(s) > 64) + return false; + + return true; +} + int pipe_eof(int fd) { struct pollfd pollfd = { .fd = fd, diff --git a/src/shared/util.h b/src/shared/util.h index 6d3791be7..e23069c01 100644 --- a/src/shared/util.h +++ b/src/shared/util.h @@ -515,6 +515,8 @@ bool plymouth_running(void); bool hostname_is_valid(const char *s) _pure_; char* hostname_cleanup(char *s, bool lowercase); +bool machine_name_is_valid(const char *s) _pure_; + char* strshorten(char *s, size_t l); int terminal_vhangup_fd(int fd); -- 2.30.2