bus: move ssh support into public API of libsystem-bus

This commit is contained in:
Lennart Poettering 2013-10-30 13:52:40 +01:00
parent 2004d23a0f
commit 0f8bd8debb
11 changed files with 96 additions and 78 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;
}

View File

@ -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); \

View File

@ -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 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 bus_open_system_systemd(sd_bus **_bus) {
_cleanup_bus_unref_ sd_bus *bus = NULL;
int r;
assert(_bus);
assert(host);
asprintf(&p, "unixexec:path=ssh,argv1=-xT,argv2=%s,argv3=systemd-stdio-bridge", host);
if (!p)
return -ENOMEM;
if (geteuid() != 0)
return sd_bus_open_system(_bus);
r = sd_bus_new(&bus);
if (r < 0)
return r;
/* If we are root, then let's talk directly to the system
* instance, instead of going via the bus */
r = sd_bus_set_address(bus, p);
if (r < 0)
return r;
r = sd_bus_new(&bus);
if (r < 0)
return r;
r = sd_bus_set_bus_client(bus, true);
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);
r = sd_bus_start(bus);
if (r < 0)
return r;
r = bus_check_peercred(bus);
if (r < 0)
return r;
*_bus = bus;
bus = NULL;
return 0;
}

View File

@ -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);

View File

@ -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;

View File

@ -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) {

View File

@ -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);

View File

@ -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;