summaryrefslogtreecommitdiff
path: root/src/libsystemd-bus
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 /src/libsystemd-bus
parent2004d23a0fcaa6e74631057a2ff75594a038d86e (diff)
bus: move ssh support into public API of libsystem-bus
Diffstat (limited to 'src/libsystemd-bus')
-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
5 files changed, 88 insertions, 71 deletions
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;