From 0f8bd8debb0ff7f5bff7738841931f6c41e40bc1 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 30 Oct 2013 13:52:40 +0100 Subject: bus: move ssh support into public API of libsystem-bus --- src/libsystemd-bus/bus-internal.c | 26 +++++++++++ src/libsystemd-bus/bus-internal.h | 2 + src/libsystemd-bus/bus-util.c | 92 ++++++++++----------------------------- src/libsystemd-bus/bus-util.h | 3 +- src/libsystemd-bus/sd-bus.c | 36 +++++++++++++++ 5 files changed, 88 insertions(+), 71 deletions(-) (limited to 'src/libsystemd-bus') diff --git a/src/libsystemd-bus/bus-internal.c b/src/libsystemd-bus/bus-internal.c index 942ac2b953..0bea8cac49 100644 --- a/src/libsystemd-bus/bus-internal.c +++ b/src/libsystemd-bus/bus-internal.c @@ -277,3 +277,29 @@ const char *bus_message_type_to_string(uint8_t u) { else return NULL; } + +char *bus_address_escape(const char *v) { + const char *a; + char *r, *b; + + r = new(char, strlen(v)*3+1); + if (!r) + return NULL; + + for (a = v, b = r; *a; a++) { + + if ((*a >= '0' && *a <= '9') || + (*a >= 'a' && *a <= 'z') || + (*a >= 'A' && *a <= 'Z') || + strchr("_-/.", *a)) + *(b++) = *a; + else { + *(b++) = '%'; + *(b++) = hexchar(*a >> 4); + *(b++) = hexchar(*a & 0xF); + } + } + + *b = 0; + return r; +} diff --git a/src/libsystemd-bus/bus-internal.h b/src/libsystemd-bus/bus-internal.h index 5f8298bbb1..2ae7961915 100644 --- a/src/libsystemd-bus/bus-internal.h +++ b/src/libsystemd-bus/bus-internal.h @@ -289,6 +289,8 @@ int bus_next_address(sd_bus *bus); bool bus_pid_changed(sd_bus *bus); +char *bus_address_escape(const char *v); + #define OBJECT_PATH_FOREACH_PREFIX(prefix, path) \ for (char *_slash = ({ strcpy((prefix), (path)); streq((prefix), "/") ? NULL : strrchr((prefix), '/'); }) ; \ _slash && !(_slash[(_slash) == (prefix)] = 0); \ diff --git a/src/libsystemd-bus/bus-util.c b/src/libsystemd-bus/bus-util.c index 6a2fb04a77..53be009be2 100644 --- a/src/libsystemd-bus/bus-util.c +++ b/src/libsystemd-bus/bus-util.c @@ -380,26 +380,22 @@ void bus_verify_polkit_async_registry_free(sd_bus *bus, Hashmap *registry) { } static int bus_check_peercred(sd_bus *c) { - int fd; struct ucred ucred; socklen_t l; + int fd; assert(c); fd = sd_bus_get_fd(c); - - assert(fd >= 0); + if (fd < 0) + return fd; l = sizeof(struct ucred); - if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &l) < 0) { - log_error("SO_PEERCRED failed: %m"); + if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &l) < 0) return -errno; - } - if (l != sizeof(struct ucred)) { - log_error("SO_PEERCRED returned wrong size."); + if (l != sizeof(struct ucred)) return -E2BIG; - } if (ucred.uid != 0 && ucred.uid != geteuid()) return -EPERM; @@ -407,79 +403,37 @@ static int bus_check_peercred(sd_bus *c) { return 1; } -int bus_connect_system(sd_bus **_bus) { - sd_bus *bus = NULL; +int bus_open_system_systemd(sd_bus **_bus) { + _cleanup_bus_unref_ sd_bus *bus = NULL; int r; - bool private = true; assert(_bus); - if (geteuid() == 0) { - /* If we are root, then let's talk directly to the - * system instance, instead of going via the bus */ - - r = sd_bus_new(&bus); - if (r < 0) - return r; - - r = sd_bus_set_address(bus, "unix:path=/run/systemd/private"); - if (r < 0) - return r; - - r = sd_bus_start(bus); - if (r < 0) - return r; - - } else { - r = sd_bus_open_system(&bus); - if (r < 0) - return r; - - private = false; - } - - if (private) { - r = bus_check_peercred(bus); - if (r < 0) { - sd_bus_unref(bus); - - return -EACCES; - } - } - - *_bus = bus; - return 0; -} - -int bus_connect_system_ssh(const char *host, sd_bus **_bus) { - sd_bus *bus; - char *p = NULL; - int r; + if (geteuid() != 0) + return sd_bus_open_system(_bus); - assert(_bus); - assert(host); - - asprintf(&p, "unixexec:path=ssh,argv1=-xT,argv2=%s,argv3=systemd-stdio-bridge", host); - if (!p) - return -ENOMEM; + /* If we are root, then let's talk directly to the system + * instance, instead of going via the bus */ - r = sd_bus_new(&bus); - if (r < 0) - return r; + r = sd_bus_new(&bus); + if (r < 0) + return r; - r = sd_bus_set_address(bus, p); - if (r < 0) - return r; + r = sd_bus_set_address(bus, "unix:path=/run/systemd/private"); + if (r < 0) + return r; - r = sd_bus_set_bus_client(bus, true); - if (r < 0) - return r; + r = sd_bus_start(bus); + if (r < 0) + return r; - r = sd_bus_start(bus); + r = bus_check_peercred(bus); if (r < 0) return r; *_bus = bus; + bus = NULL; + return 0; } diff --git a/src/libsystemd-bus/bus-util.h b/src/libsystemd-bus/bus-util.h index 5ddab2c11b..46e10b3c1d 100644 --- a/src/libsystemd-bus/bus-util.h +++ b/src/libsystemd-bus/bus-util.h @@ -37,8 +37,7 @@ int bus_verify_polkit(sd_bus *bus, sd_bus_message *m, const char *action, bool i int bus_verify_polkit_async(sd_bus *bus, Hashmap **registry, sd_bus_message *m, const char *action, bool interactive, sd_bus_error *error, sd_bus_message_handler_t callback, void *userdata); void bus_verify_polkit_async_registry_free(sd_bus *bus, Hashmap *registry); -int bus_connect_system(sd_bus **_bus); -int bus_connect_system_ssh(const char *host, sd_bus **_bus); +int bus_open_system_systemd(sd_bus **_bus); int bus_generic_print_property(const char *name, sd_bus_message *property, bool all); diff --git a/src/libsystemd-bus/sd-bus.c b/src/libsystemd-bus/sd-bus.c index 55d964ed8f..383b035b7e 100644 --- a/src/libsystemd-bus/sd-bus.c +++ b/src/libsystemd-bus/sd-bus.c @@ -1033,6 +1033,42 @@ fail: return r; } +int sd_bus_open_system_remote(const char *host, sd_bus **ret) { + _cleanup_free_ char *e = NULL; + char *p = NULL; + sd_bus *bus; + int r; + + assert_return(host, -EINVAL); + assert_return(ret, -EINVAL); + + e = bus_address_escape(host); + if (!e) + return -ENOMEM; + + p = strjoin("unixexec:path=ssh,argv1=-xT,argv2=", e, ",argv3=systemd-stdio-bridge", NULL); + if (!p) + return -ENOMEM; + + r = sd_bus_new(&bus); + if (r < 0) { + free(p); + return r; + } + + bus->address = p; + bus->bus_client = true; + + r = sd_bus_start(bus); + if (r < 0) { + bus_free(bus); + return r; + } + + *ret = bus; + return 0; +} + void sd_bus_close(sd_bus *bus) { if (!bus) return; -- cgit v1.2.3-54-g00ecf