summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2014-07-03 01:17:26 +0200
committerLennart Poettering <lennart@poettering.net>2014-07-03 01:17:26 +0200
commit7f0d207d2c816e0a8cb2742b0a789911f7c99356 (patch)
tree148eea6477a079339c5ecfa1a03d7debe50fed17
parent8f6e22a1cafafb4e78e23c1998f23a997c1b294f (diff)
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.
-rw-r--r--src/bus-proxyd/bus-proxyd.c55
-rw-r--r--src/libsystemd/sd-bus/sd-bus.c31
-rw-r--r--src/machine/machined-dbus.c19
-rw-r--r--src/shared/util.c15
-rw-r--r--src/shared/util.h2
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);