summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2013-10-30 13:52:40 +0100
committerLennart Poettering <lennart@poettering.net>2013-10-30 15:35:49 +0100
commit0f8bd8debb0ff7f5bff7738841931f6c41e40bc1 (patch)
tree50ab6e129131fd301e1665b15e8896ea80ff2e74
parent2004d23a0fcaa6e74631057a2ff75594a038d86e (diff)
bus: move ssh support into public API of libsystem-bus
-rw-r--r--src/cgroups-agent/cgroups-agent.c2
-rw-r--r--src/fsck/fsck.c2
-rw-r--r--src/initctl/initctl.c2
-rw-r--r--src/libsystemd-bus/bus-internal.c26
-rw-r--r--src/libsystemd-bus/bus-internal.h2
-rw-r--r--src/libsystemd-bus/bus-util.c92
-rw-r--r--src/libsystemd-bus/bus-util.h3
-rw-r--r--src/libsystemd-bus/sd-bus.c36
-rw-r--r--src/machine/machinectl.c2
-rw-r--r--src/systemd/sd-bus.h3
-rw-r--r--src/update-utmp/update-utmp.c2
11 files changed, 95 insertions, 77 deletions
diff --git a/src/cgroups-agent/cgroups-agent.c b/src/cgroups-agent/cgroups-agent.c
index 256de1f506..d8ae55a313 100644
--- a/src/cgroups-agent/cgroups-agent.c
+++ b/src/cgroups-agent/cgroups-agent.c
@@ -44,7 +44,7 @@ int main(int argc, char *argv[]) {
* this to avoid an activation loop when we start dbus when we
* are called when the dbus service is shut down. */
- r = bus_connect_system(&bus);
+ r = bus_open_system_systemd(&bus);
if (r < 0) {
log_warning("Failed to get D-Bus connection: %s", strerror(-r));
return EXIT_FAILURE;
diff --git a/src/fsck/fsck.c b/src/fsck/fsck.c
index 5c21c7e41f..3164d6899c 100644
--- a/src/fsck/fsck.c
+++ b/src/fsck/fsck.c
@@ -50,7 +50,7 @@ static void start_target(const char *target) {
assert(target);
- r = bus_connect_system(&bus);
+ r = bus_open_system_systemd(&bus);
if (r < 0) {
log_error("Failed to get D-Bus connection: %s", strerror(-r));
return;
diff --git a/src/initctl/initctl.c b/src/initctl/initctl.c
index 3c5986171f..0000d6ccd4 100644
--- a/src/initctl/initctl.c
+++ b/src/initctl/initctl.c
@@ -329,7 +329,7 @@ static int server_init(Server *s, unsigned n_sockets) {
s->n_fifos ++;
}
- r = bus_connect_system(&s->bus);
+ r = bus_open_system_systemd(&s->bus);
if (r < 0) {
log_error("Failed to get D-Bus connection: %s", strerror(-r));
r = -EIO;
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;
diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c
index 8795565f8e..241e360d49 100644
--- a/src/machine/machinectl.c
+++ b/src/machine/machinectl.c
@@ -759,7 +759,7 @@ int main(int argc, char*argv[]) {
if (arg_transport == TRANSPORT_NORMAL)
r = sd_bus_open_system(&bus);
else if (arg_transport == TRANSPORT_SSH)
- r = bus_connect_system_ssh(arg_host, &bus);
+ r = sd_bus_open_system_remote(arg_host, &bus);
else
assert_not_reached("Uh, invalid transport...");
if (r < 0) {
diff --git a/src/systemd/sd-bus.h b/src/systemd/sd-bus.h
index aa8caee70f..7b6c86dd39 100644
--- a/src/systemd/sd-bus.h
+++ b/src/systemd/sd-bus.h
@@ -58,8 +58,9 @@ typedef int (*sd_bus_node_enumerator_t) (sd_bus *bus, const char *path, char ***
/* Connections */
-int sd_bus_open_system(sd_bus **ret);
int sd_bus_open_user(sd_bus **ret);
+int sd_bus_open_system(sd_bus **ret);
+int sd_bus_open_system_remote(const char *host, sd_bus **ret);
int sd_bus_new(sd_bus **ret);
int sd_bus_set_address(sd_bus *bus, const char *address);
diff --git a/src/update-utmp/update-utmp.c b/src/update-utmp/update-utmp.c
index f5c143d39d..61db1e96d3 100644
--- a/src/update-utmp/update-utmp.c
+++ b/src/update-utmp/update-utmp.c
@@ -299,7 +299,7 @@ int main(int argc, char *argv[]) {
errno != EAFNOSUPPORT && errno != EPROTONOSUPPORT)
log_error("Failed to connect to audit log: %m");
#endif
- r = bus_connect_system(&c.bus);
+ r = bus_open_system_systemd(&c.bus);
if (r < 0) {
log_error("Failed to get D-Bus connection: %s", strerror(-r));
r = -EIO;