chiark / gitweb /
Revert "bus-driverd: do not track identical matches"
[elogind.git] / src / bus-driverd / bus-driverd.c
index de2344503fe56720cf57712e88d159863a6d9346..7e0ad1e0c05111235d12cf17b75fd74951e3873c 100644 (file)
@@ -51,6 +51,7 @@
 #include "def.h"
 #include "unit-name.h"
 #include "bus-control.h"
+#include "cgroup-util.h"
 
 #define CLIENTS_MAX 1024
 #define MATCHES_MAX 1024
@@ -346,7 +347,7 @@ static int driver_remove_match(sd_bus *bus, sd_bus_message *message, void *userd
 
         m = hashmap_get(c->matches, normalized);
         if (!m) {
-                r = sd_bus_error_setf(error, SD_BUS_ERROR_MATCH_RULE_NOT_FOUND, "Match rule \"%s\" not found.");
+                r = sd_bus_error_setf(error, SD_BUS_ERROR_MATCH_RULE_NOT_FOUND, "Match rule \"%s\" not found.", normalized);
                 goto finish;
         }
 
@@ -364,19 +365,42 @@ finish:
         return r;
 }
 
-static int driver_get_security_ctx(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) {
-        _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
-        char *arg0;
+static int get_creds(sd_bus *bus, sd_bus_message *m, uint64_t mask, sd_bus_creds **_creds, sd_bus_error *error) {
+        _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
+        const char *name;
         int r;
 
-        r = sd_bus_message_read(m, "s", &arg0);
+        assert(bus);
+        assert(m);
+        assert(_creds);
+
+        r = sd_bus_message_read(m, "s", &name);
         if (r < 0)
                 return r;
 
-        assert_return(service_name_is_valid(arg0), -EINVAL);
+        assert_return(service_name_is_valid(name), -EINVAL);
+
+        r = sd_bus_get_owner(bus, name, mask, &c);
+        if (r == -ENOENT || r == -ENXIO)
+                return sd_bus_error_setf(error, SD_BUS_ERROR_NAME_HAS_NO_OWNER, "Name %s is currently not owned by anyone.", name);
+        if (r < 0)
+                return r;
+
+        if ((c->mask & mask) != mask)
+                return -ENOTSUP;
+
+        *_creds = c;
+        c = NULL;
+
+        return 0;
+}
+
+static int driver_get_security_context(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) {
+        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+        int r;
 
-        r = sd_bus_get_owner(bus, arg0, SD_BUS_CREDS_SELINUX_CONTEXT, &creds);
+        r = get_creds(bus, m, SD_BUS_CREDS_SELINUX_CONTEXT, &creds, error);
         if (r < 0)
                 return r;
 
@@ -393,38 +417,35 @@ static int driver_get_security_ctx(sd_bus *bus, sd_bus_message *m, void *userdat
 
 static int driver_get_pid(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) {
         _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
-        char *arg0;
         int r;
 
-        r = sd_bus_message_read(m, "s", &arg0);
-        if (r < 0)
-                return r;
-
-        assert_return(service_name_is_valid(arg0), -EINVAL);
-
-        r = sd_bus_get_owner(bus, arg0, SD_BUS_CREDS_PID, &creds);
+        r = get_creds(bus, m, SD_BUS_CREDS_PID, &creds, error);
         if (r < 0)
                 return r;
 
-        return sd_bus_reply_method_return(m, "u", creds->pid);
+        return sd_bus_reply_method_return(m, "u", (uint32_t) creds->pid);
 }
 
 static int driver_get_user(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) {
         _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
-        char *arg0;
         int r;
 
-        r = sd_bus_message_read(m, "s", &arg0);
+        r = get_creds(bus, m, SD_BUS_CREDS_UID, &creds, error);
         if (r < 0)
                 return r;
 
-        assert_return(service_name_is_valid(arg0), -EINVAL);
+        return sd_bus_reply_method_return(m, "u", (uint32_t) creds->uid);
+}
+
+static int driver_get_name_owner(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) {
+        _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+        int r;
 
-        r = sd_bus_get_owner(bus, arg0, SD_BUS_CREDS_UID, &creds);
+        r = get_creds(bus, m, SD_BUS_CREDS_UNIQUE_NAME, &creds, error);
         if (r < 0)
                 return r;
 
-        return sd_bus_reply_method_return(m, "u", creds->uid);
+        return sd_bus_reply_method_return(m, "s", creds->unique_name);
 }
 
 static int driver_get_id(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) {
@@ -439,24 +460,6 @@ static int driver_get_id(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_
         return sd_bus_reply_method_return(m, "s", sd_id128_to_string(server_id, buf));
 }
 
-static int driver_get_name_owner(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) {
-        _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
-        char *arg0;
-        int r;
-
-        r = sd_bus_message_read(m, "s", &arg0);
-        if (r < 0)
-                return r;
-
-        assert_return(service_name_is_valid(arg0), -EINVAL);
-
-        r = sd_bus_get_owner(bus, arg0, SD_BUS_CREDS_UNIQUE_NAME, &creds);
-        if (r < 0)
-                return r;
-
-        return sd_bus_reply_method_return(m, "s", creds->unique_name);
-}
-
 static int driver_hello(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) {
         return sd_bus_reply_method_return(m, "s", m->sender);
 }
@@ -535,7 +538,7 @@ static int driver_list_queued_owners(sd_bus *bus, sd_bus_message *m, void *userd
                 if (!streq(name->name, arg0))
                         continue;
 
-                if (asprintf(&n, ":1.%llu", (unsigned long long) name->id) < 0)
+                if (asprintf(&n, ":1.%llu", (unsigned long long) name->owner_id) < 0)
                         return -ENOMEM;
 
                 r = strv_push(&owners, n);
@@ -553,17 +556,17 @@ static int driver_list_queued_owners(sd_bus *bus, sd_bus_message *m, void *userd
 }
 
 static int driver_name_has_owner(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) {
-        char *arg0;
+        const char *name;
         int r;
 
-        r = sd_bus_message_read(m, "s", &arg0);
+        r = sd_bus_message_read(m, "s", &name);
         if (r < 0)
                 return r;
 
-        assert_return(service_name_is_valid(arg0), -EINVAL);
+        assert_return(service_name_is_valid(name), -EINVAL);
 
-        r = sd_bus_get_owner(bus, arg0, 0, NULL);
-        if (r < 0 && r != -ENOENT)
+        r = sd_bus_get_owner(bus, name, 0, NULL);
+        if (r < 0 && r != -ENOENT && r != -ENXIO)
                 return r;
 
         return sd_bus_reply_method_return(m, "b", r >= 0);
@@ -597,7 +600,7 @@ static int driver_request_name(sd_bus *bus, sd_bus_message *m, void *userdata, s
         if (r < 0)
                 return r;
 
-        n->id = id;
+        n->owner_id = id;
 
         r = ioctl(bus->input_fd, KDBUS_CMD_NAME_ACQUIRE, n);
         if (r < 0) {
@@ -640,7 +643,7 @@ static int driver_release_name(sd_bus *bus, sd_bus_message *m, void *userdata, s
         if (r < 0)
                 return r;
 
-        n->id = id;
+        n->owner_id = id;
 
         r = ioctl(bus->input_fd, KDBUS_CMD_NAME_RELEASE, n);
         if (r < 0) {
@@ -692,8 +695,8 @@ static int driver_start_service_by_name(sd_bus *bus, sd_bus_message *m, void *us
         if (r < 0)
                 return r;
 
-        if (!t[0] || t[1])
-                return -EIO;
+        if (!t || !t[0] || t[1])
+                return sd_bus_error_setf(error, SD_BUS_ERROR_SERVICE_UNKNOWN, "Bus name %s not found.", name);
 
         r = sd_bus_call_method(
                         bus,
@@ -712,14 +715,73 @@ static int driver_start_service_by_name(sd_bus *bus, sd_bus_message *m, void *us
         return sd_bus_reply_method_return(m, "u", BUS_START_REPLY_SUCCESS);
 }
 
+static int driver_update_environment(sd_bus*bus, sd_bus_message *m, void *userdata, sd_bus_error *error) {
+        _cleanup_bus_message_unref_ sd_bus_message *msg = NULL;
+        _cleanup_strv_free_ char **args = NULL;
+        int r;
+
+        r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{ss}");
+        if (r < 0)
+                return r;
+
+       while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "ss")) > 0) {
+                _cleanup_free_ char *s = NULL;
+                const char *key;
+                const char *value;
+
+                r = sd_bus_message_read(m, "ss", &key, &value);
+                if (r < 0)
+                        return r;
+
+                s = strjoin(key, "=", value, NULL);
+                if (!s)
+                        return ENOMEM;
+
+                r  = strv_extend(&args, s);
+                if (r < 0)
+                        return r;
+
+                r = sd_bus_message_exit_container(m);
+                if (r < 0)
+                        return r;
+        }
+
+        r = sd_bus_message_exit_container(m);
+        if (r < 0)
+                return r;
+
+        if (!args)
+                return -EINVAL;
+
+        r = sd_bus_message_new_method_call(
+                        bus,
+                        "org.freedesktop.systemd1",
+                        "/org/freedesktop/systemd1",
+                        "org.freedesktop.systemd1.Manager",
+                        "SetEnvironment",
+                        &msg);
+        if (r < 0)
+                return r;
+
+        r = sd_bus_message_append_strv(msg, args);
+        if (r < 0)
+                return r;
+
+        r = sd_bus_call(bus, msg, 0, NULL, NULL);
+        if (r < 0)
+                return r;
+
+        return sd_bus_reply_method_return(m, NULL);
+}
+
 static int driver_unsupported(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) {
         return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "%s() is not supported", sd_bus_message_get_member(m));
 }
 
 static const sd_bus_vtable driver_vtable[] = {
         SD_BUS_VTABLE_START(0),
-        SD_BUS_METHOD("AddMatch", "s", NULL, driver_add_match, 0),
-        SD_BUS_METHOD("GetConnectionSELinuxSecurityContext", "s", "ay", driver_get_security_ctx, SD_BUS_VTABLE_UNPRIVILEGED),
+        SD_BUS_METHOD("AddMatch", "s", NULL, driver_add_match, SD_BUS_VTABLE_UNPRIVILEGED),
+        SD_BUS_METHOD("GetConnectionSELinuxSecurityContext", "s", "ay", driver_get_security_context, SD_BUS_VTABLE_UNPRIVILEGED),
         SD_BUS_METHOD("GetConnectionUnixProcessID", "s", "u", driver_get_pid, SD_BUS_VTABLE_UNPRIVILEGED),
         SD_BUS_METHOD("GetConnectionUnixUser", "s", "u", driver_get_user, SD_BUS_VTABLE_UNPRIVILEGED),
         SD_BUS_METHOD("GetId", NULL, "s", driver_get_id, SD_BUS_VTABLE_UNPRIVILEGED),
@@ -734,7 +796,7 @@ static const sd_bus_vtable driver_vtable[] = {
         SD_BUS_METHOD("RemoveMatch", "s", NULL, driver_remove_match, SD_BUS_VTABLE_UNPRIVILEGED),
         SD_BUS_METHOD("RequestName", "su", "u", driver_request_name, SD_BUS_VTABLE_UNPRIVILEGED),
         SD_BUS_METHOD("StartServiceByName", "su", "u", driver_start_service_by_name, SD_BUS_VTABLE_UNPRIVILEGED),
-        SD_BUS_METHOD("UpdateActivationEnvironment", "a{ss}", NULL, driver_unsupported, SD_BUS_VTABLE_DEPRECATED),
+        SD_BUS_METHOD("UpdateActivationEnvironment", "a{ss}", NULL, driver_update_environment, 0),
         SD_BUS_SIGNAL("NameAcquired", "s", SD_BUS_VTABLE_DEPRECATED),
         SD_BUS_SIGNAL("NameLost", "s", SD_BUS_VTABLE_DEPRECATED),
         SD_BUS_SIGNAL("NameOwnerChanged", "sss", 0),
@@ -746,7 +808,11 @@ static int connect_bus(Context *c) {
 
         assert(c);
 
-        r = sd_bus_default_system(&c->bus);
+        r = cg_pid_get_owner_uid(0, NULL);
+        if (r < 0)
+                r = sd_bus_default_system(&c->bus);
+        else
+                r = sd_bus_default_user(&c->bus);
         if (r < 0) {
                 log_error("Failed to create bus: %s", strerror(-r));
                 return r;
@@ -765,7 +831,7 @@ static int connect_bus(Context *c) {
 
         r = sd_bus_request_name(c->bus, "org.freedesktop.DBus", 0);
         if (r < 0) {
-                log_error("Unable to request name: %s\n", strerror(-r));
+                log_error("Unable to request name: %s", strerror(-r));
                 return r;
         }
 
@@ -826,5 +892,4 @@ finish:
         sd_event_unref(context.event);
 
         return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
-
 }