diff options
Diffstat (limited to '')
-rw-r--r-- | src/home/homed-home-bus.c | 187 |
1 files changed, 129 insertions, 58 deletions
diff --git a/src/home/homed-home-bus.c b/src/home/homed-home-bus.c index a47f4d8..23578fe 100644 --- a/src/home/homed-home-bus.c +++ b/src/home/homed-home-bus.c @@ -5,6 +5,8 @@ #include "bus-common-errors.h" #include "bus-polkit.h" #include "fd-util.h" +#include "format-util.h" +#include "home-util.h" #include "homed-bus.h" #include "homed-home-bus.h" #include "homed-home.h" @@ -74,6 +76,34 @@ int bus_home_client_is_trusted(Home *h, sd_bus_message *message) { return euid == 0 || h->uid == euid; } +static int home_verify_polkit_async( + Home *h, + sd_bus_message *message, + const char *action, + uid_t good_uid, + sd_bus_error *error) { + + assert(h); + assert(message); + assert(action); + assert(error); + + const char *details[] = { + "uid", FORMAT_UID(h->uid), + "username", h->user_name, + NULL + }; + + return bus_verify_polkit_async_full( + message, + action, + details, + good_uid, + /* flags= */ 0, + &h->manager->polkit_registry, + error); +} + int bus_home_get_record_json( Home *h, sd_bus_message *message, @@ -144,15 +174,31 @@ int bus_home_method_activate( _cleanup_(user_record_unrefp) UserRecord *secret = NULL; Home *h = ASSERT_PTR(userdata); + bool if_referenced; int r; assert(message); + if_referenced = endswith(sd_bus_message_get_member(message), "IfReferenced"); + + r = bus_verify_polkit_async_full( + message, + "org.freedesktop.home1.activate-home", + /* details= */ NULL, + h->uid, + /* flags= */ 0, + &h->manager->polkit_registry, + error); + if (r < 0) + return r; + if (r == 0) + return 1; /* Will call us back */ + r = bus_message_read_secret(message, &secret, error); if (r < 0) return r; - r = home_activate(h, secret, error); + r = home_activate(h, if_referenced, secret, error); if (r < 0) return r; @@ -201,14 +247,11 @@ int bus_home_method_unregister( assert(message); - r = bus_verify_polkit_async( + r = home_verify_polkit_async( + h, message, - CAP_SYS_ADMIN, "org.freedesktop.home1.remove-home", - NULL, - true, UID_INVALID, - &h->manager->polkit_registry, error); if (r < 0) return r; @@ -241,21 +284,18 @@ int bus_home_method_realize( if (r < 0) return r; - r = bus_verify_polkit_async( + r = home_verify_polkit_async( + h, message, - CAP_SYS_ADMIN, "org.freedesktop.home1.create-home", - NULL, - true, UID_INVALID, - &h->manager->polkit_registry, error); if (r < 0) return r; if (r == 0) return 1; /* Will call us back */ - r = home_create(h, secret, error); + r = home_create(h, secret, NULL, 0, error); if (r < 0) return r; @@ -281,14 +321,11 @@ int bus_home_method_remove( assert(message); - r = bus_verify_polkit_async( + r = home_verify_polkit_async( + h, message, - CAP_SYS_ADMIN, "org.freedesktop.home1.remove-home", - NULL, - true, UID_INVALID, - &h->manager->polkit_registry, error); if (r < 0) return r; @@ -354,14 +391,11 @@ int bus_home_method_authenticate( if (r < 0) return r; - r = bus_verify_polkit_async( + r = home_verify_polkit_async( + h, message, - CAP_SYS_ADMIN, "org.freedesktop.home1.authenticate-home", - NULL, - true, h->uid, - &h->manager->polkit_registry, error); if (r < 0) return r; @@ -382,7 +416,13 @@ int bus_home_method_authenticate( return 1; } -int bus_home_method_update_record(Home *h, sd_bus_message *message, UserRecord *hr, sd_bus_error *error) { +int bus_home_update_record( + Home *h, + sd_bus_message *message, + UserRecord *hr, + Hashmap *blobs, + uint64_t flags, + sd_bus_error *error) { int r; assert(h); @@ -393,21 +433,21 @@ int bus_home_method_update_record(Home *h, sd_bus_message *message, UserRecord * if (r < 0) return r; - r = bus_verify_polkit_async( + if ((flags & ~SD_HOMED_UPDATE_FLAGS_ALL) != 0) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid flags provided."); + + r = home_verify_polkit_async( + h, message, - CAP_SYS_ADMIN, "org.freedesktop.home1.update-home", - NULL, - true, UID_INVALID, - &h->manager->polkit_registry, error); if (r < 0) return r; if (r == 0) return 1; /* Will call us back */ - r = home_update(h, hr, error); + r = home_update(h, hr, blobs, flags, error); if (r < 0) return r; @@ -418,6 +458,8 @@ int bus_home_method_update_record(Home *h, sd_bus_message *message, UserRecord * if (r < 0) return r; + h->current_operation->call_flags = flags; + return 1; } @@ -427,16 +469,28 @@ int bus_home_method_update( sd_bus_error *error) { _cleanup_(user_record_unrefp) UserRecord *hr = NULL; + _cleanup_hashmap_free_ Hashmap *blobs = NULL; + uint64_t flags = 0; Home *h = ASSERT_PTR(userdata); int r; assert(message); - 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); + r = bus_message_read_home_record(message, USER_RECORD_REQUIRE_REGULAR|USER_RECORD_ALLOW_SECRET|USER_RECORD_ALLOW_PRIVILEGED|USER_RECORD_ALLOW_PER_MACHINE|USER_RECORD_ALLOW_SIGNATURE|USER_RECORD_PERMISSIVE, &hr, error); if (r < 0) return r; - return bus_home_method_update_record(h, message, hr, error); + if (endswith(sd_bus_message_get_member(message), "Ex")) { + r = bus_message_read_blobs(message, &blobs, error); + if (r < 0) + return r; + + r = sd_bus_message_read(message, "t", &flags); + if (r < 0) + return r; + } + + return bus_home_update_record(h, message, hr, blobs, flags, error); } int bus_home_method_resize( @@ -459,21 +513,18 @@ int bus_home_method_resize( if (r < 0) return r; - r = bus_verify_polkit_async( + r = home_verify_polkit_async( + h, message, - CAP_SYS_ADMIN, "org.freedesktop.home1.resize-home", - NULL, - true, UID_INVALID, - &h->manager->polkit_registry, error); if (r < 0) return r; if (r == 0) return 1; /* Will call us back */ - r = home_resize(h, sz, secret, /* automatic= */ false, error); + r = home_resize(h, sz, secret, error); if (r < 0) return r; @@ -506,14 +557,11 @@ int bus_home_method_change_password( if (r < 0) return r; - r = bus_verify_polkit_async( + r = home_verify_polkit_async( + h, message, - CAP_SYS_ADMIN, "org.freedesktop.home1.passwd-home", - NULL, - true, h->uid, - &h->manager->polkit_registry, error); if (r < 0) return r; @@ -637,30 +685,38 @@ int bus_home_method_ref( _cleanup_close_ int fd = -EBADF; Home *h = ASSERT_PTR(userdata); - HomeState state; int please_suspend, r; + bool unrestricted; assert(message); + /* In unrestricted mode we'll add a reference to the home even if it's not active */ + unrestricted = strstr(sd_bus_message_get_member(message), "Unrestricted"); + r = sd_bus_message_read(message, "b", &please_suspend); if (r < 0) return r; - state = home_get_state(h); - switch (state) { - case HOME_ABSENT: - 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); - default: - if (HOME_STATE_IS_ACTIVE(state)) - break; + if (!unrestricted) { + HomeState state; + + state = home_get_state(h); - return sd_bus_error_setf(error, BUS_ERROR_HOME_BUSY, "An operation on home %s is currently being executed.", h->user_name); + switch (state) { + case HOME_ABSENT: + 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); + default: + if (HOME_STATE_IS_ACTIVE(state)) + break; + + return sd_bus_error_setf(error, BUS_ERROR_HOME_BUSY, "An operation on home %s is currently being executed.", h->user_name); + } } fd = home_create_fifo(h, please_suspend); @@ -784,7 +840,12 @@ const sd_bus_vtable home_vtable[] = { SD_BUS_ARGS("s", secret), SD_BUS_NO_RESULT, bus_home_method_activate, - SD_BUS_VTABLE_SENSITIVE), + SD_BUS_VTABLE_UNPRIVILEGED|SD_BUS_VTABLE_SENSITIVE), + SD_BUS_METHOD_WITH_ARGS("ActivateIfReferenced", + SD_BUS_ARGS("s", secret), + SD_BUS_NO_RESULT, + bus_home_method_activate, + SD_BUS_VTABLE_UNPRIVILEGED|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", @@ -809,6 +870,11 @@ const sd_bus_vtable home_vtable[] = { SD_BUS_NO_RESULT, bus_home_method_update, SD_BUS_VTABLE_UNPRIVILEGED|SD_BUS_VTABLE_SENSITIVE), + SD_BUS_METHOD_WITH_ARGS("UpdateEx", + SD_BUS_ARGS("s", user_record, "a{sh}", blobs, "t", flags), + 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, @@ -835,6 +901,11 @@ const sd_bus_vtable home_vtable[] = { SD_BUS_RESULT("h", send_fd), bus_home_method_ref, 0), + SD_BUS_METHOD_WITH_ARGS("RefUnrestricted", + 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 }; |