diff --git a/src/home/homed-home-bus.c b/src/home/homed-home-bus.c
index 5977ff2a47..b459cadcbf 100644
--- a/src/home/homed-home-bus.c
+++ b/src/home/homed-home-bus.c
@@ -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",
diff --git a/src/home/homed-home.c b/src/home/homed-home.c
index 8b0df9175e..2134f4352f 100644
--- a/src/home/homed-home.c
+++ b/src/home/homed-home.c
@@ -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);
diff --git a/src/home/homed-home.h b/src/home/homed-home.h
index b8b0046422..6c069ab5f0 100644
--- a/src/home/homed-home.h
+++ b/src/home/homed-home.h
@@ -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);
diff --git a/src/home/homed-manager-bus.c b/src/home/homed-manager-bus.c
index c484ef7ac2..c8e232f425 100644
--- a/src/home/homed-manager-bus.c
+++ b/src/home/homed-manager-bus.c
@@ -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,
diff --git a/src/home/org.freedesktop.home1.conf b/src/home/org.freedesktop.home1.conf
index b0c18f261e..d2c4b9dd29 100644
--- a/src/home/org.freedesktop.home1.conf
+++ b/src/home/org.freedesktop.home1.conf
@@ -57,6 +57,10 @@
send_interface="org.freedesktop.home1.Manager"
send_member="ActivateHome"/>
+
+
@@ -147,6 +151,10 @@
send_interface="org.freedesktop.home1.Home"
send_member="Activate"/>
+
+
diff --git a/src/home/org.freedesktop.home1.policy b/src/home/org.freedesktop.home1.policy
index 2ac710d66c..be32b2e8e4 100644
--- a/src/home/org.freedesktop.home1.policy
+++ b/src/home/org.freedesktop.home1.policy
@@ -78,4 +78,14 @@
auth_admin_keep
+
+
+ Activate a home area
+ Authentication is required to activate a user's home area.
+
+ auth_admin_keep
+ auth_admin_keep
+ auth_admin_keep
+
+
diff --git a/src/libsystemd/sd-bus/bus-common-errors.c b/src/libsystemd/sd-bus/bus-common-errors.c
index efdd6539cc..e44795b1d3 100644
--- a/src/libsystemd/sd-bus/bus-common-errors.c
+++ b/src/libsystemd/sd-bus/bus-common-errors.c
@@ -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
};
diff --git a/src/libsystemd/sd-bus/bus-common-errors.h b/src/libsystemd/sd-bus/bus-common-errors.h
index 2961ee4a9e..36f53dbde1 100644
--- a/src/libsystemd/sd-bus/bus-common-errors.h
+++ b/src/libsystemd/sd-bus/bus-common-errors.h
@@ -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);