mirror of
https://github.com/systemd/systemd.git
synced 2024-12-13 04:03:35 +08:00
bus: move ssh support into public API of libsystem-bus
This commit is contained in:
parent
2004d23a0f
commit
0f8bd8debb
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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); \
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user