]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/home/homed-home-bus.c
polkit: simplify bus_verify_polkit_async() + drop auth-by-cap dbus feature
[thirdparty/systemd.git] / src / home / homed-home-bus.c
index 6b4fa58a6f62b1862667b39fb6e582703455f122..413a706f4c363367b586fc2c7c22c422760f23ca 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: LGPL-2.1+ */
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
 
 #include <linux/capability.h>
 
@@ -21,11 +21,10 @@ static int property_get_unix_record(
                 void *userdata,
                 sd_bus_error *error) {
 
-        Home *h = userdata;
+        Home *h = ASSERT_PTR(userdata);
 
         assert(bus);
         assert(reply);
-        assert(h);
 
         return sd_bus_message_append(
                         reply, "(suusss)",
@@ -46,11 +45,10 @@ static int property_get_state(
                 void *userdata,
                 sd_bus_error *error) {
 
-        Home *h = userdata;
+        Home *h = ASSERT_PTR(userdata);
 
         assert(bus);
         assert(reply);
-        assert(h);
 
         return sd_bus_message_append(reply, "s", home_state_to_string(home_get_state(h)));
 }
@@ -95,7 +93,7 @@ int bus_home_get_record_json(
                 trusted = false;
         }
 
-        flags = USER_RECORD_REQUIRE_REGULAR|USER_RECORD_ALLOW_PER_MACHINE|USER_RECORD_ALLOW_BINDING|USER_RECORD_STRIP_SECRET|USER_RECORD_ALLOW_STATUS|USER_RECORD_ALLOW_SIGNATURE;
+        flags = USER_RECORD_REQUIRE_REGULAR|USER_RECORD_ALLOW_PER_MACHINE|USER_RECORD_ALLOW_BINDING|USER_RECORD_STRIP_SECRET|USER_RECORD_ALLOW_STATUS|USER_RECORD_ALLOW_SIGNATURE|USER_RECORD_PERMISSIVE;
         if (trusted)
                 flags |= USER_RECORD_ALLOW_PRIVILEGED;
         else
@@ -125,13 +123,12 @@ static int property_get_user_record(
                 sd_bus_error *error) {
 
         _cleanup_free_ char *json = NULL;
-        Home *h = userdata;
+        Home *h = ASSERT_PTR(userdata);
         bool incomplete;
         int r;
 
         assert(bus);
         assert(reply);
-        assert(h);
 
         r = bus_home_get_record_json(h, sd_bus_get_current_message(bus), &json, &incomplete);
         if (r < 0)
@@ -146,11 +143,10 @@ int bus_home_method_activate(
                 sd_bus_error *error) {
 
         _cleanup_(user_record_unrefp) UserRecord *secret = NULL;
-        Home *h = userdata;
+        Home *h = ASSERT_PTR(userdata);
         int r;
 
         assert(message);
-        assert(h);
 
         r = bus_message_read_secret(message, &secret, error);
         if (r < 0)
@@ -176,11 +172,10 @@ int bus_home_method_deactivate(
                 void *userdata,
                 sd_bus_error *error) {
 
-        Home *h = userdata;
+        Home *h = ASSERT_PTR(userdata);
         int r;
 
         assert(message);
-        assert(h);
 
         r = home_deactivate(h, false, error);
         if (r < 0)
@@ -201,19 +196,15 @@ int bus_home_method_unregister(
                 void *userdata,
                 sd_bus_error *error) {
 
-        Home *h = userdata;
+        Home *h = ASSERT_PTR(userdata);
         int r;
 
         assert(message);
-        assert(h);
 
         r = bus_verify_polkit_async(
                         message,
-                        CAP_SYS_ADMIN,
                         "org.freedesktop.home1.remove-home",
-                        NULL,
-                        true,
-                        UID_INVALID,
+                        /* details= */ NULL,
                         &h->manager->polkit_registry,
                         error);
         if (r < 0)
@@ -238,11 +229,10 @@ int bus_home_method_realize(
                 sd_bus_error *error) {
 
         _cleanup_(user_record_unrefp) UserRecord *secret = NULL;
-        Home *h = userdata;
+        Home *h = ASSERT_PTR(userdata);
         int r;
 
         assert(message);
-        assert(h);
 
         r = bus_message_read_secret(message, &secret, error);
         if (r < 0)
@@ -250,11 +240,8 @@ int bus_home_method_realize(
 
         r = bus_verify_polkit_async(
                         message,
-                        CAP_SYS_ADMIN,
                         "org.freedesktop.home1.create-home",
-                        NULL,
-                        true,
-                        UID_INVALID,
+                        /* details= */ NULL,
                         &h->manager->polkit_registry,
                         error);
         if (r < 0)
@@ -283,19 +270,15 @@ int bus_home_method_remove(
                 void *userdata,
                 sd_bus_error *error) {
 
-        Home *h = userdata;
+        Home *h = ASSERT_PTR(userdata);
         int r;
 
         assert(message);
-        assert(h);
 
         r = bus_verify_polkit_async(
                         message,
-                        CAP_SYS_ADMIN,
                         "org.freedesktop.home1.remove-home",
-                        NULL,
-                        true,
-                        UID_INVALID,
+                        /* details= */ NULL,
                         &h->manager->polkit_registry,
                         error);
         if (r < 0)
@@ -324,11 +307,10 @@ int bus_home_method_fixate(
                 sd_bus_error *error) {
 
         _cleanup_(user_record_unrefp) UserRecord *secret = NULL;
-        Home *h = userdata;
+        Home *h = ASSERT_PTR(userdata);
         int r;
 
         assert(message);
-        assert(h);
 
         r = bus_message_read_secret(message, &secret, error);
         if (r < 0)
@@ -354,22 +336,20 @@ int bus_home_method_authenticate(
                 sd_bus_error *error) {
 
         _cleanup_(user_record_unrefp) UserRecord *secret = NULL;
-        Home *h = userdata;
+        Home *h = ASSERT_PTR(userdata);
         int r;
 
         assert(message);
-        assert(h);
 
         r = bus_message_read_secret(message, &secret, error);
         if (r < 0)
                 return r;
 
-        r = bus_verify_polkit_async(
+        r = bus_verify_polkit_async_full(
                         message,
-                        CAP_SYS_ADMIN,
                         "org.freedesktop.home1.authenticate-home",
-                        NULL,
-                        true,
+                        /* details= */ NULL,
+                        /* interactive= */ false,
                         h->uid,
                         &h->manager->polkit_registry,
                         error);
@@ -405,11 +385,8 @@ int bus_home_method_update_record(Home *h, sd_bus_message *message, UserRecord *
 
         r = bus_verify_polkit_async(
                         message,
-                        CAP_SYS_ADMIN,
                         "org.freedesktop.home1.update-home",
-                        NULL,
-                        true,
-                        UID_INVALID,
+                        /* details= */ NULL,
                         &h->manager->polkit_registry,
                         error);
         if (r < 0)
@@ -437,13 +414,12 @@ int bus_home_method_update(
                 sd_bus_error *error) {
 
         _cleanup_(user_record_unrefp) UserRecord *hr = NULL;
-        Home *h = userdata;
+        Home *h = ASSERT_PTR(userdata);
         int r;
 
         assert(message);
-        assert(h);
 
-        r = bus_message_read_home_record(message, USER_RECORD_REQUIRE_REGULAR|USER_RECORD_REQUIRE_SECRET|USER_RECORD_ALLOW_PRIVILEGED|USER_RECORD_ALLOW_PER_MACHINE|USER_RECORD_ALLOW_SIGNATURE, &hr, error);
+        r = bus_message_read_home_record(message, USER_RECORD_REQUIRE_REGULAR|USER_RECORD_REQUIRE_SECRET|USER_RECORD_ALLOW_PRIVILEGED|USER_RECORD_ALLOW_PER_MACHINE|USER_RECORD_ALLOW_SIGNATURE|USER_RECORD_PERMISSIVE, &hr, error);
         if (r < 0)
                 return r;
 
@@ -456,12 +432,11 @@ int bus_home_method_resize(
                 sd_bus_error *error) {
 
         _cleanup_(user_record_unrefp) UserRecord *secret = NULL;
-        Home *h = userdata;
+        Home *h = ASSERT_PTR(userdata);
         uint64_t sz;
         int r;
 
         assert(message);
-        assert(h);
 
         r = sd_bus_message_read(message, "t", &sz);
         if (r < 0)
@@ -473,11 +448,8 @@ int bus_home_method_resize(
 
         r = bus_verify_polkit_async(
                         message,
-                        CAP_SYS_ADMIN,
                         "org.freedesktop.home1.resize-home",
-                        NULL,
-                        true,
-                        UID_INVALID,
+                        /* details= */ NULL,
                         &h->manager->polkit_registry,
                         error);
         if (r < 0)
@@ -485,7 +457,7 @@ int bus_home_method_resize(
         if (r == 0)
                 return 1; /* Will call us back */
 
-        r = home_resize(h, sz, secret, error);
+        r = home_resize(h, sz, secret, /* automatic= */ false, error);
         if (r < 0)
                 return r;
 
@@ -505,11 +477,10 @@ int bus_home_method_change_password(
                 sd_bus_error *error) {
 
         _cleanup_(user_record_unrefp) UserRecord *new_secret = NULL, *old_secret = NULL;
-        Home *h = userdata;
+        Home *h = ASSERT_PTR(userdata);
         int r;
 
         assert(message);
-        assert(h);
 
         r = bus_message_read_secret(message, &new_secret, error);
         if (r < 0)
@@ -519,12 +490,11 @@ int bus_home_method_change_password(
         if (r < 0)
                 return r;
 
-        r = bus_verify_polkit_async(
+        r = bus_verify_polkit_async_full(
                         message,
-                        CAP_SYS_ADMIN,
                         "org.freedesktop.home1.passwd-home",
-                        NULL,
-                        true,
+                        /* details= */ NULL,
+                        /* interactive= */ false,
                         h->uid,
                         &h->manager->polkit_registry,
                         error);
@@ -552,11 +522,10 @@ int bus_home_method_lock(
                 void *userdata,
                 sd_bus_error *error) {
 
-        Home *h = userdata;
+        Home *h = ASSERT_PTR(userdata);
         int r;
 
         assert(message);
-        assert(h);
 
         r = home_lock(h, error);
         if (r < 0)
@@ -580,11 +549,10 @@ int bus_home_method_unlock(
                 sd_bus_error *error) {
 
         _cleanup_(user_record_unrefp) UserRecord *secret = NULL;
-        Home *h = userdata;
+        Home *h = ASSERT_PTR(userdata);
         int r;
 
         assert(message);
-        assert(h);
 
         r = bus_message_read_secret(message, &secret, error);
         if (r < 0)
@@ -612,12 +580,11 @@ int bus_home_method_acquire(
 
         _cleanup_(user_record_unrefp) UserRecord *secret = NULL;
         _cleanup_(operation_unrefp) Operation *o = NULL;
-        _cleanup_close_ int fd = -1;
+        _cleanup_close_ int fd = -EBADF;
         int r, please_suspend;
-        Home *h = userdata;
+        Home *h = ASSERT_PTR(userdata);
 
         assert(message);
-        assert(h);
 
         r = bus_message_read_secret(message, &secret, error);
         if (r < 0)
@@ -651,13 +618,12 @@ int bus_home_method_ref(
                 void *userdata,
                 sd_bus_error *error) {
 
-        _cleanup_close_ int fd = -1;
-        Home *h = userdata;
+        _cleanup_close_ int fd = -EBADF;
+        Home *h = ASSERT_PTR(userdata);
         HomeState state;
         int please_suspend, r;
 
         assert(message);
-        assert(h);
 
         r = sd_bus_message_read(message, "b", &please_suspend);
         if (r < 0)
@@ -669,6 +635,7 @@ int bus_home_method_ref(
                 return sd_bus_error_setf(error, BUS_ERROR_HOME_ABSENT, "Home %s is currently missing or not plugged in.", h->user_name);
         case HOME_UNFIXATED:
         case HOME_INACTIVE:
+        case HOME_DIRTY:
                 return sd_bus_error_setf(error, BUS_ERROR_HOME_NOT_ACTIVE, "Home %s not active.", h->user_name);
         case HOME_LOCKED:
                 return sd_bus_error_setf(error, BUS_ERROR_HOME_LOCKED, "Home %s is currently locked.", h->user_name);
@@ -692,11 +659,10 @@ int bus_home_method_release(
                 sd_bus_error *error) {
 
         _cleanup_(operation_unrefp) Operation *o = NULL;
-        Home *h = userdata;
+        Home *h = ASSERT_PTR(userdata);
         int r;
 
         assert(message);
-        assert(h);
 
         o = operation_new(OPERATION_RELEASE, message);
         if (!o)
@@ -712,38 +678,13 @@ int bus_home_method_release(
 /* We map a uid_t as uint32_t bus property, let's ensure this is safe. */
 assert_cc(sizeof(uid_t) == sizeof(uint32_t));
 
-const sd_bus_vtable home_vtable[] = {
-        SD_BUS_VTABLE_START(0),
-        SD_BUS_PROPERTY("UserName", "s", NULL, offsetof(Home, user_name), SD_BUS_VTABLE_PROPERTY_CONST),
-        SD_BUS_PROPERTY("UID", "u", NULL, offsetof(Home, uid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
-        SD_BUS_PROPERTY("UnixRecord", "(suusss)", property_get_unix_record, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
-        SD_BUS_PROPERTY("State", "s", property_get_state, 0, 0),
-        SD_BUS_PROPERTY("UserRecord", "(sb)", property_get_user_record, 0, SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION|SD_BUS_VTABLE_SENSITIVE),
-        SD_BUS_METHOD("Activate", "s", NULL, bus_home_method_activate, SD_BUS_VTABLE_SENSITIVE),
-        SD_BUS_METHOD("Deactivate", NULL, NULL, bus_home_method_deactivate, 0),
-        SD_BUS_METHOD("Unregister", NULL, NULL, bus_home_method_unregister, SD_BUS_VTABLE_UNPRIVILEGED),
-        SD_BUS_METHOD("Realize", "s", NULL, bus_home_method_realize, SD_BUS_VTABLE_UNPRIVILEGED|SD_BUS_VTABLE_SENSITIVE),
-        SD_BUS_METHOD("Remove", NULL, NULL, bus_home_method_remove, SD_BUS_VTABLE_UNPRIVILEGED),
-        SD_BUS_METHOD("Fixate", "s", NULL, bus_home_method_fixate, SD_BUS_VTABLE_SENSITIVE),
-        SD_BUS_METHOD("Authenticate", "s", NULL, bus_home_method_authenticate, SD_BUS_VTABLE_UNPRIVILEGED|SD_BUS_VTABLE_SENSITIVE),
-        SD_BUS_METHOD("Update", "s", NULL, bus_home_method_update, SD_BUS_VTABLE_UNPRIVILEGED|SD_BUS_VTABLE_SENSITIVE),
-        SD_BUS_METHOD("Resize", "ts", NULL, bus_home_method_resize, SD_BUS_VTABLE_UNPRIVILEGED|SD_BUS_VTABLE_SENSITIVE),
-        SD_BUS_METHOD("ChangePassword", "ss", NULL, bus_home_method_change_password, SD_BUS_VTABLE_UNPRIVILEGED|SD_BUS_VTABLE_SENSITIVE),
-        SD_BUS_METHOD("Lock", NULL, NULL, bus_home_method_lock, 0),
-        SD_BUS_METHOD("Unlock", "s", NULL, bus_home_method_unlock, SD_BUS_VTABLE_SENSITIVE),
-        SD_BUS_METHOD("Acquire", "sb", "h", bus_home_method_acquire, SD_BUS_VTABLE_SENSITIVE),
-        SD_BUS_METHOD("Ref", "b", "h", bus_home_method_ref, 0),
-        SD_BUS_METHOD("Release", NULL, NULL, bus_home_method_release, 0),
-        SD_BUS_VTABLE_END
-};
-
 int bus_home_path(Home *h, char **ret) {
         assert(ret);
 
         return sd_bus_path_encode("/org/freedesktop/home1/home", h->user_name, ret);
 }
 
-int bus_home_object_find(
+static int bus_home_object_find(
                 sd_bus *bus,
                 const char *path,
                 const char *interface,
@@ -772,7 +713,7 @@ int bus_home_object_find(
         return 1;
 }
 
-int bus_home_node_enumerator(
+static int bus_home_node_enumerator(
                 sd_bus *bus,
                 const char *path,
                 void *userdata,
@@ -782,7 +723,6 @@ int bus_home_node_enumerator(
         _cleanup_strv_free_ char **l = NULL;
         Manager *m = userdata;
         size_t k = 0;
-        Iterator i;
         Home *h;
         int r;
 
@@ -792,24 +732,110 @@ int bus_home_node_enumerator(
         if (!l)
                 return -ENOMEM;
 
-        HASHMAP_FOREACH(h, m->homes_by_uid, i) {
+        HASHMAP_FOREACH(h, m->homes_by_uid) {
                 r = bus_home_path(h, l + k);
                 if (r < 0)
                         return r;
+
+                k++;
         }
 
         *nodes = TAKE_PTR(l);
         return 1;
 }
 
+const sd_bus_vtable home_vtable[] = {
+        SD_BUS_VTABLE_START(0),
+
+        SD_BUS_PROPERTY("UserName", "s",
+                        NULL, offsetof(Home, user_name),
+                        SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("UID", "u",
+                        NULL, offsetof(Home, uid),
+                        SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        SD_BUS_PROPERTY("UnixRecord", "(suusss)",
+                        property_get_unix_record, 0,
+                        SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        SD_BUS_PROPERTY("State", "s",
+                        property_get_state, 0,
+                        0),
+        SD_BUS_PROPERTY("UserRecord", "(sb)",
+                        property_get_user_record, 0,
+                        SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION|SD_BUS_VTABLE_SENSITIVE),
+
+        SD_BUS_METHOD_WITH_ARGS("Activate",
+                                SD_BUS_ARGS("s", secret),
+                                SD_BUS_NO_RESULT,
+                                bus_home_method_activate,
+                                SD_BUS_VTABLE_SENSITIVE),
+        SD_BUS_METHOD("Deactivate", NULL, NULL, bus_home_method_deactivate, 0),
+        SD_BUS_METHOD("Unregister", NULL, NULL, bus_home_method_unregister, SD_BUS_VTABLE_UNPRIVILEGED),
+        SD_BUS_METHOD_WITH_ARGS("Realize",
+                                SD_BUS_ARGS("s", secret),
+                                SD_BUS_NO_RESULT,
+                                bus_home_method_realize,
+                                SD_BUS_VTABLE_UNPRIVILEGED|SD_BUS_VTABLE_SENSITIVE),
+
+        SD_BUS_METHOD("Remove", NULL, NULL, bus_home_method_remove, SD_BUS_VTABLE_UNPRIVILEGED),
+        SD_BUS_METHOD_WITH_ARGS("Fixate",
+                                SD_BUS_ARGS("s", secret),
+                                SD_BUS_NO_RESULT,
+                                bus_home_method_fixate,
+                                SD_BUS_VTABLE_SENSITIVE),
+        SD_BUS_METHOD_WITH_ARGS("Authenticate",
+                                SD_BUS_ARGS("s", secret),
+                                SD_BUS_NO_RESULT,
+                                bus_home_method_authenticate,
+                                SD_BUS_VTABLE_UNPRIVILEGED|SD_BUS_VTABLE_SENSITIVE),
+        SD_BUS_METHOD_WITH_ARGS("Update",
+                                SD_BUS_ARGS("s", user_record),
+                                SD_BUS_NO_RESULT,
+                                bus_home_method_update,
+                                SD_BUS_VTABLE_UNPRIVILEGED|SD_BUS_VTABLE_SENSITIVE),
+        SD_BUS_METHOD_WITH_ARGS("Resize",
+                                SD_BUS_ARGS("t", size, "s", secret),
+                                SD_BUS_NO_RESULT,
+                                bus_home_method_resize,
+                                SD_BUS_VTABLE_UNPRIVILEGED|SD_BUS_VTABLE_SENSITIVE),
+        SD_BUS_METHOD_WITH_ARGS("ChangePassword",
+                                SD_BUS_ARGS("s", new_secret, "s", old_secret),
+                                SD_BUS_NO_RESULT,
+                                bus_home_method_change_password,
+                                SD_BUS_VTABLE_UNPRIVILEGED|SD_BUS_VTABLE_SENSITIVE),
+        SD_BUS_METHOD("Lock", NULL, NULL, bus_home_method_lock, 0),
+        SD_BUS_METHOD_WITH_ARGS("Unlock",
+                                SD_BUS_ARGS("s", secret),
+                                SD_BUS_NO_RESULT,
+                                bus_home_method_unlock,
+                                SD_BUS_VTABLE_SENSITIVE),
+        SD_BUS_METHOD_WITH_ARGS("Acquire",
+                                SD_BUS_ARGS("s", secret, "b", please_suspend),
+                                SD_BUS_RESULT("h", send_fd),
+                                bus_home_method_acquire,
+                                SD_BUS_VTABLE_SENSITIVE),
+        SD_BUS_METHOD_WITH_ARGS("Ref",
+                                SD_BUS_ARGS("b", please_suspend),
+                                SD_BUS_RESULT("h", send_fd),
+                                bus_home_method_ref,
+                                0),
+        SD_BUS_METHOD("Release", NULL, NULL, bus_home_method_release, 0),
+        SD_BUS_VTABLE_END
+};
+
+const BusObjectImplementation home_object = {
+        "/org/freedesktop/home1/home",
+        "org.freedesktop.home1.Home",
+        .fallback_vtables = BUS_FALLBACK_VTABLES({home_vtable, bus_home_object_find}),
+        .node_enumerator = bus_home_node_enumerator,
+        .manager = true,
+};
+
 static int on_deferred_change(sd_event_source *s, void *userdata) {
         _cleanup_free_ char *path = NULL;
-        Home *h = userdata;
+        Home *h = ASSERT_PTR(userdata);
         int r;
 
-        assert(h);
-
-        h->deferred_change_event_source = sd_event_source_unref(h->deferred_change_event_source);
+        h->deferred_change_event_source = sd_event_source_disable_unref(h->deferred_change_event_source);
 
         r = bus_home_path(h, &path);
         if (r < 0) {
@@ -864,6 +890,12 @@ int bus_home_emit_remove(Home *h) {
         if (!h->announced)
                 return 0;
 
+        if (!h->manager)
+                return 0;
+
+        if (!h->manager->bus)
+                return 0;
+
         r = bus_home_path(h, &path);
         if (r < 0)
                 return r;