chiark / gitweb /
bus: the owner of the bus driver name as reported by the driver's
[elogind.git] / src / bus-driverd / bus-driverd.c
index 7e0ad1e0c05111235d12cf17b75fd74951e3873c..b97206600b461a92c925e58a4a9f9c36a4d78a57 100644 (file)
@@ -93,7 +93,7 @@ static void match_free(Match *m) {
                 first = hashmap_get(m->client->matches, m->match);
                 LIST_REMOVE(matches, first, m);
                 if (first)
-                        assert_se(hashmap_replace(m->client->matches, m->match, first) >= 0);
+                        assert_se(hashmap_replace(m->client->matches, first->match, first) >= 0);
                 else
                         hashmap_remove(m->client->matches, m->match);
 
@@ -365,19 +365,14 @@ finish:
         return r;
 }
 
-static int get_creds(sd_bus *bus, sd_bus_message *m, uint64_t mask, sd_bus_creds **_creds, sd_bus_error *error) {
+static int get_creds_by_name(sd_bus *bus, const char *name, 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;
 
         assert(bus);
-        assert(m);
+        assert(name);
         assert(_creds);
 
-        r = sd_bus_message_read(m, "s", &name);
-        if (r < 0)
-                return r;
-
         assert_return(service_name_is_valid(name), -EINVAL);
 
         r = sd_bus_get_owner(bus, name, mask, &c);
@@ -395,12 +390,28 @@ static int get_creds(sd_bus *bus, sd_bus_message *m, uint64_t mask, sd_bus_creds
         return 0;
 }
 
+
+static int get_creds_by_message(sd_bus *bus, sd_bus_message *m, uint64_t mask, sd_bus_creds **_creds, sd_bus_error *error) {
+        const char *name;
+        int r;
+
+        assert(bus);
+        assert(m);
+        assert(_creds);
+
+        r = sd_bus_message_read(m, "s", &name);
+        if (r < 0)
+                return r;
+
+        return get_creds_by_name(bus, name, mask, _creds, error);
+}
+
 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 = get_creds(bus, m, SD_BUS_CREDS_SELINUX_CONTEXT, &creds, error);
+        r = get_creds_by_message(bus, m, SD_BUS_CREDS_SELINUX_CONTEXT, &creds, error);
         if (r < 0)
                 return r;
 
@@ -419,7 +430,7 @@ static int driver_get_pid(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus
         _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
         int r;
 
-        r = get_creds(bus, m, SD_BUS_CREDS_PID, &creds, error);
+        r = get_creds_by_message(bus, m, SD_BUS_CREDS_PID, &creds, error);
         if (r < 0)
                 return r;
 
@@ -430,7 +441,7 @@ static int driver_get_user(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bu
         _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
         int r;
 
-        r = get_creds(bus, m, SD_BUS_CREDS_UID, &creds, error);
+        r = get_creds_by_message(bus, m, SD_BUS_CREDS_UID, &creds, error);
         if (r < 0)
                 return r;
 
@@ -439,9 +450,20 @@ static int driver_get_user(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bu
 
 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;
+        const char *name;
         int r;
 
-        r = get_creds(bus, m, SD_BUS_CREDS_UNIQUE_NAME, &creds, error);
+        r = sd_bus_message_read(m, "s", &name);
+        if (r < 0)
+                return r;
+
+        /* Here's a special exception for compatibility with dbus1:
+         * the bus name of the driver is owned by itself, not by a
+         * unique ID. */
+        if (streq(name, "org.freedesktop.DBus"))
+                return sd_bus_reply_method_return(m, "s", "org.freedesktop.DBus");
+
+        r = get_creds_by_name(bus, name, SD_BUS_CREDS_UNIQUE_NAME, &creds, error);
         if (r < 0)
                 return r;
 
@@ -803,16 +825,51 @@ static const sd_bus_vtable driver_vtable[] = {
         SD_BUS_VTABLE_END
 };
 
+static int find_object(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                void *userdata,
+                void **ret_found,
+                sd_bus_error *ret_error) {
+
+        /* We support the driver interface on exactly two different
+         * paths: the root and the entry point object. This is a bit
+         * different from the original dbus-daemon which supported it
+         * on any path. */
+
+        if (streq_ptr(path, "/"))
+                return 1;
+
+        if (streq_ptr(path, "/org/freedesktop/DBus"))
+                return 1;
+
+        return 0;
+}
+
+static int node_enumerator(
+                sd_bus *bus,
+                const char *path,
+                void *userdata,
+                char ***ret_nodes,
+                sd_bus_error *ret_error) {
+
+        char **l;
+
+        l = strv_new("/", "/org/freedesktop/DBus", NULL);
+        if (!l)
+                return -ENOMEM;
+
+        *ret_nodes = l;
+        return 0;
+}
+
 static int connect_bus(Context *c) {
         int r;
 
         assert(c);
 
-        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);
+        r = sd_bus_default(&c->bus);
         if (r < 0) {
                 log_error("Failed to create bus: %s", strerror(-r));
                 return r;
@@ -823,12 +880,18 @@ static int connect_bus(Context *c) {
                 return -EPERM;
         }
 
-        r = sd_bus_add_object_vtable(c->bus, "/org/freedesktop/DBus", "org.freedesktop.DBus", driver_vtable, c);
+        r = sd_bus_add_fallback_vtable(c->bus, "/", "org.freedesktop.DBus", driver_vtable, find_object, c);
         if (r < 0) {
                 log_error("Failed to add manager object vtable: %s", strerror(-r));
                 return r;
         }
 
+        r = sd_bus_add_node_enumerator(c->bus, "/", node_enumerator, c);
+        if (r < 0) {
+                log_error("Failed to add node enumerator: %s", strerror(-r));
+                return r;
+        }
+
         r = sd_bus_request_name(c->bus, "org.freedesktop.DBus", 0);
         if (r < 0) {
                 log_error("Unable to request name: %s", strerror(-r));