homed: add a ActivateHomeIfReferenced() bus call

This is very similar to ActivateHome() but will fail if the home
directory is not referenced yet. Or in other words, this doesn't add any
new reference, but simply is the other side of RefUnrestricted(): if we
allowed a home dir to be referenced without it actually being active,
then this can catch up with things and activated what was previously
referenced already.

This also relaxes access rights to that users can always activate their
own home dirs. This is useful once we allow user code to run without the
home dir being activated.
This commit is contained in:
Lennart Poettering
2023-11-27 17:05:54 +01:00
parent 508d344e0e
commit 336b1f1936
8 changed files with 54 additions and 5 deletions

View File

@@ -144,15 +144,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,
/* interctive= */ false,
h->uid,
&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;
@@ -822,7 +838,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",

View File

@@ -1383,12 +1383,15 @@ static int home_activate_internal(Home *h, UserRecord *secret, HomeState for_sta
return 0;
}
int home_activate(Home *h, UserRecord *secret, sd_bus_error *error) {
int home_activate(Home *h, bool if_referenced, UserRecord *secret, sd_bus_error *error) {
int r;
assert(h);
assert(secret);
if (if_referenced && !home_is_referenced(h))
return sd_bus_error_setf(error, BUS_ERROR_HOME_NOT_REFERENCED, "Home %s is currently not referenced.", h->user_name);
switch (home_get_state(h)) {
case HOME_UNFIXATED:
return home_fixate_internal(h, secret, HOME_FIXATING_FOR_ACTIVATION, error);

View File

@@ -190,7 +190,7 @@ int home_save_record(Home *h);
int home_unlink_record(Home *h);
int home_fixate(Home *h, UserRecord *secret, sd_bus_error *error);
int home_activate(Home *h, UserRecord *secret, sd_bus_error *error);
int home_activate(Home *h, bool if_referenced, UserRecord *secret, sd_bus_error *error);
int home_authenticate(Home *h, UserRecord *secret, sd_bus_error *error);
int home_deactivate(Home *h, bool force, sd_bus_error *error);
int home_create(Home *h, UserRecord *secret, sd_bus_error *error);

View File

@@ -737,7 +737,12 @@ static const sd_bus_vtable manager_vtable[] = {
SD_BUS_ARGS("s", user_name, "s", secret),
SD_BUS_NO_RESULT,
method_activate_home,
SD_BUS_VTABLE_SENSITIVE),
SD_BUS_VTABLE_UNPRIVILEGED|SD_BUS_VTABLE_SENSITIVE),
SD_BUS_METHOD_WITH_ARGS("ActivateHomeIfReferenced",
SD_BUS_ARGS("s", user_name, "s", secret),
SD_BUS_NO_RESULT,
method_activate_home,
SD_BUS_VTABLE_UNPRIVILEGED|SD_BUS_VTABLE_SENSITIVE),
SD_BUS_METHOD_WITH_ARGS("DeactivateHome",
SD_BUS_ARGS("s", user_name),
SD_BUS_NO_RESULT,

View File

@@ -57,6 +57,10 @@
send_interface="org.freedesktop.home1.Manager"
send_member="ActivateHome"/>
<allow send_destination="org.freedesktop.home1"
send_interface="org.freedesktop.home1.Manager"
send_member="ActivateHomeIfReferenced"/>
<allow send_destination="org.freedesktop.home1"
send_interface="org.freedesktop.home1.Manager"
send_member="DeactivateHome"/>
@@ -147,6 +151,10 @@
send_interface="org.freedesktop.home1.Home"
send_member="Activate"/>
<allow send_destination="org.freedesktop.home1"
send_interface="org.freedesktop.home1.Home"
send_member="ActivateIfReferenced"/>
<allow send_destination="org.freedesktop.home1"
send_interface="org.freedesktop.home1.Home"
send_member="Deactivate"/>

View File

@@ -78,4 +78,14 @@
<allow_active>auth_admin_keep</allow_active>
</defaults>
</action>
<action id="org.freedesktop.home1.activate-home">
<description gettext-domain="systemd">Activate a home area</description>
<message gettext-domain="systemd">Authentication is required to activate a user's home area.</message>
<defaults>
<allow_any>auth_admin_keep</allow_any>
<allow_inactive>auth_admin_keep</allow_inactive>
<allow_active>auth_admin_keep</allow_active>
</defaults>
</action>
</policyconfig>

View File

@@ -147,6 +147,7 @@ BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_common_errors[] = {
SD_BUS_ERROR_MAP(BUS_ERROR_HOME_CANT_AUTHENTICATE, EKEYREVOKED),
SD_BUS_ERROR_MAP(BUS_ERROR_HOME_IN_USE, EADDRINUSE),
SD_BUS_ERROR_MAP(BUS_ERROR_REBALANCE_NOT_NEEDED, EALREADY),
SD_BUS_ERROR_MAP(BUS_ERROR_HOME_NOT_REFERENCED, EBADR),
SD_BUS_ERROR_MAP_END
};

View File

@@ -152,5 +152,6 @@
#define BUS_ERROR_HOME_CANT_AUTHENTICATE "org.freedesktop.home1.HomeCantAuthenticate"
#define BUS_ERROR_HOME_IN_USE "org.freedesktop.home1.HomeInUse"
#define BUS_ERROR_REBALANCE_NOT_NEEDED "org.freedesktop.home1.RebalanceNotNeeded"
#define BUS_ERROR_HOME_NOT_REFERENCED "org.freedesktop.home1.HomeNotReferenced"
BUS_ERROR_MAP_ELF_USE(bus_common_errors);