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.
This commit is contained in:
parent
8f6e22a1ca
commit
7f0d207d2c
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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++;
|
||||
|
||||
b->address = strjoin("unixexec:path=ssh,argv1=-xT,argv2=", e, ",argv3=systemd-stdio-bridge", NULL);
|
||||
/* 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", c, NULL);
|
||||
if (!b->address)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue