1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 #include <linux/capability.h>
5 #include "alloc-util.h"
6 #include "bus-common-errors.h"
7 #include "bus-polkit.h"
8 #include "format-util.h"
10 #include "homed-home-bus.h"
11 #include "homed-manager-bus.h"
12 #include "homed-manager.h"
14 #include "user-record-sign.h"
15 #include "user-record-util.h"
16 #include "user-util.h"
18 static int property_get_auto_login(
21 const char *interface
,
23 sd_bus_message
*reply
,
25 sd_bus_error
*error
) {
27 Manager
*m
= userdata
;
35 r
= sd_bus_message_open_container(reply
, 'a', "(sso)");
39 HASHMAP_FOREACH(h
, m
->homes_by_name
) {
40 _cleanup_(strv_freep
) char **seats
= NULL
;
41 _cleanup_free_
char *home_path
= NULL
;
44 r
= home_auto_login(h
, &seats
);
46 log_debug_errno(r
, "Failed to determine whether home '%s' is candidate for auto-login, ignoring: %m", h
->user_name
);
52 r
= bus_home_path(h
, &home_path
);
54 return log_error_errno(r
, "Failed to generate home bus path: %m");
56 STRV_FOREACH(s
, seats
) {
57 r
= sd_bus_message_append(reply
, "(sso)", h
->user_name
, *s
, home_path
);
63 return sd_bus_message_close_container(reply
);
66 static int method_get_home_by_name(
67 sd_bus_message
*message
,
69 sd_bus_error
*error
) {
71 _cleanup_free_
char *path
= NULL
;
72 const char *user_name
;
73 Manager
*m
= userdata
;
80 r
= sd_bus_message_read(message
, "s", &user_name
);
83 if (!valid_user_group_name(user_name
, 0))
84 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "User name %s is not valid", user_name
);
86 h
= hashmap_get(m
->homes_by_name
, user_name
);
88 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_HOME
, "No home for user %s known", user_name
);
90 r
= bus_home_path(h
, &path
);
94 return sd_bus_reply_method_return(
97 home_state_to_string(home_get_state(h
)),
98 h
->record
? (uint32_t) user_record_gid(h
->record
) : GID_INVALID
,
99 h
->record
? user_record_real_name(h
->record
) : NULL
,
100 h
->record
? user_record_home_directory(h
->record
) : NULL
,
101 h
->record
? user_record_shell(h
->record
) : NULL
,
105 static int method_get_home_by_uid(
106 sd_bus_message
*message
,
108 sd_bus_error
*error
) {
110 _cleanup_free_
char *path
= NULL
;
111 Manager
*m
= userdata
;
119 r
= sd_bus_message_read(message
, "u", &uid
);
122 if (!uid_is_valid(uid
))
123 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "UID " UID_FMT
" is not valid", uid
);
125 h
= hashmap_get(m
->homes_by_uid
, UID_TO_PTR(uid
));
127 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_HOME
, "No home for UID " UID_FMT
" known", uid
);
129 /* Note that we don't use bus_home_path() here, but build the path manually, since if we are queried
130 * for a UID we should also generate the bus path with a UID, and bus_home_path() uses our more
131 * typical bus path by name. */
132 if (asprintf(&path
, "/org/freedesktop/home1/home/" UID_FMT
, h
->uid
) < 0)
135 return sd_bus_reply_method_return(
138 home_state_to_string(home_get_state(h
)),
139 h
->record
? (uint32_t) user_record_gid(h
->record
) : GID_INVALID
,
140 h
->record
? user_record_real_name(h
->record
) : NULL
,
141 h
->record
? user_record_home_directory(h
->record
) : NULL
,
142 h
->record
? user_record_shell(h
->record
) : NULL
,
146 static int method_list_homes(
147 sd_bus_message
*message
,
149 sd_bus_error
*error
) {
151 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
152 Manager
*m
= userdata
;
159 r
= sd_bus_message_new_method_return(message
, &reply
);
163 r
= sd_bus_message_open_container(reply
, 'a', "(susussso)");
167 HASHMAP_FOREACH(h
, m
->homes_by_uid
) {
168 _cleanup_free_
char *path
= NULL
;
170 r
= bus_home_path(h
, &path
);
174 r
= sd_bus_message_append(
178 home_state_to_string(home_get_state(h
)),
179 h
->record
? (uint32_t) user_record_gid(h
->record
) : GID_INVALID
,
180 h
->record
? user_record_real_name(h
->record
) : NULL
,
181 h
->record
? user_record_home_directory(h
->record
) : NULL
,
182 h
->record
? user_record_shell(h
->record
) : NULL
,
188 r
= sd_bus_message_close_container(reply
);
192 return sd_bus_send(NULL
, reply
, NULL
);
195 static int method_get_user_record_by_name(
196 sd_bus_message
*message
,
198 sd_bus_error
*error
) {
200 _cleanup_free_
char *json
= NULL
, *path
= NULL
;
201 Manager
*m
= userdata
;
202 const char *user_name
;
210 r
= sd_bus_message_read(message
, "s", &user_name
);
213 if (!valid_user_group_name(user_name
, 0))
214 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "User name %s is not valid", user_name
);
216 h
= hashmap_get(m
->homes_by_name
, user_name
);
218 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_HOME
, "No home for user %s known", user_name
);
220 r
= bus_home_get_record_json(h
, message
, &json
, &incomplete
);
224 r
= bus_home_path(h
, &path
);
228 return sd_bus_reply_method_return(
235 static int method_get_user_record_by_uid(
236 sd_bus_message
*message
,
238 sd_bus_error
*error
) {
240 _cleanup_free_
char *json
= NULL
, *path
= NULL
;
241 Manager
*m
= userdata
;
250 r
= sd_bus_message_read(message
, "u", &uid
);
253 if (!uid_is_valid(uid
))
254 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "UID " UID_FMT
" is not valid", uid
);
256 h
= hashmap_get(m
->homes_by_uid
, UID_TO_PTR(uid
));
258 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_HOME
, "No home for UID " UID_FMT
" known", uid
);
260 r
= bus_home_get_record_json(h
, message
, &json
, &incomplete
);
264 if (asprintf(&path
, "/org/freedesktop/home1/home/" UID_FMT
, h
->uid
) < 0)
267 return sd_bus_reply_method_return(
274 static int generic_home_method(
276 sd_bus_message
*message
,
277 sd_bus_message_handler_t handler
,
278 sd_bus_error
*error
) {
280 const char *user_name
;
284 r
= sd_bus_message_read(message
, "s", &user_name
);
288 if (!valid_user_group_name(user_name
, 0))
289 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "User name %s is not valid", user_name
);
291 h
= hashmap_get(m
->homes_by_name
, user_name
);
293 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_HOME
, "No home for user %s known", user_name
);
295 return handler(message
, h
, error
);
298 static int method_activate_home(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
299 return generic_home_method(userdata
, message
, bus_home_method_activate
, error
);
302 static int method_deactivate_home(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
303 return generic_home_method(userdata
, message
, bus_home_method_deactivate
, error
);
306 static int validate_and_allocate_home(Manager
*m
, UserRecord
*hr
, Home
**ret
, sd_bus_error
*error
) {
307 _cleanup_(user_record_unrefp
) UserRecord
*signed_hr
= NULL
;
318 r
= user_record_is_supported(hr
, error
);
322 other
= hashmap_get(m
->homes_by_name
, hr
->user_name
);
324 return sd_bus_error_setf(error
, BUS_ERROR_USER_NAME_EXISTS
, "Specified user name %s exists already, refusing.", hr
->user_name
);
326 pw
= getpwnam(hr
->user_name
);
328 return sd_bus_error_setf(error
, BUS_ERROR_USER_NAME_EXISTS
, "Specified user name %s exists in the NSS user database, refusing.", hr
->user_name
);
330 gr
= getgrnam(hr
->user_name
);
332 return sd_bus_error_setf(error
, BUS_ERROR_USER_NAME_EXISTS
, "Specified user name %s conflicts with an NSS group by the same name, refusing.", hr
->user_name
);
334 r
= manager_verify_user_record(m
, hr
);
337 case USER_RECORD_UNSIGNED
:
338 /* If the record is unsigned, then let's sign it with our own key */
339 r
= manager_sign_user_record(m
, hr
, &signed_hr
, error
);
346 case USER_RECORD_SIGNED_EXCLUSIVE
:
347 signed_locally
= true;
350 case USER_RECORD_SIGNED
:
351 case USER_RECORD_FOREIGN
:
352 signed_locally
= false;
356 return sd_bus_error_setf(error
, BUS_ERROR_BAD_SIGNATURE
, "Specified user record for %s is signed by a key we don't recognize, refusing.", hr
->user_name
);
359 return sd_bus_error_set_errnof(error
, r
, "Failed to validate signature for '%s': %m", hr
->user_name
);
362 if (uid_is_valid(hr
->uid
)) {
363 other
= hashmap_get(m
->homes_by_uid
, UID_TO_PTR(hr
->uid
));
365 return sd_bus_error_setf(error
, BUS_ERROR_UID_IN_USE
, "Specified UID " UID_FMT
" already in use by home %s, refusing.", hr
->uid
, other
->user_name
);
367 pw
= getpwuid(hr
->uid
);
369 return sd_bus_error_setf(error
, BUS_ERROR_UID_IN_USE
, "Specified UID " UID_FMT
" already in use by NSS user %s, refusing.", hr
->uid
, pw
->pw_name
);
371 gr
= getgrgid(hr
->uid
);
373 return sd_bus_error_setf(error
, BUS_ERROR_UID_IN_USE
, "Specified UID " UID_FMT
" already in use as GID by NSS group %s, refusing.", hr
->uid
, gr
->gr_name
);
375 r
= manager_augment_record_with_uid(m
, hr
);
377 return sd_bus_error_set_errnof(error
, r
, "Failed to acquire UID for '%s': %m", hr
->user_name
);
380 r
= home_new(m
, hr
, NULL
, ret
);
384 (*ret
)->signed_locally
= signed_locally
;
388 static int method_register_home(
389 sd_bus_message
*message
,
391 sd_bus_error
*error
) {
393 _cleanup_(user_record_unrefp
) UserRecord
*hr
= NULL
;
394 Manager
*m
= userdata
;
401 r
= bus_message_read_home_record(message
, USER_RECORD_LOAD_EMBEDDED
, &hr
, error
);
405 r
= bus_verify_polkit_async(
408 "org.freedesktop.home1.create-home",
417 return 1; /* Will call us back */
419 r
= validate_and_allocate_home(m
, hr
, &h
, error
);
423 r
= home_save_record(h
);
429 return sd_bus_reply_method_return(message
, NULL
);
432 static int method_unregister_home(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
433 return generic_home_method(userdata
, message
, bus_home_method_unregister
, error
);
436 static int method_create_home(
437 sd_bus_message
*message
,
439 sd_bus_error
*error
) {
441 _cleanup_(user_record_unrefp
) UserRecord
*hr
= NULL
;
442 Manager
*m
= userdata
;
449 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
, &hr
, error
);
453 r
= bus_verify_polkit_async(
456 "org.freedesktop.home1.create-home",
465 return 1; /* Will call us back */
467 r
= validate_and_allocate_home(m
, hr
, &h
, error
);
471 r
= home_create(h
, hr
, error
);
476 h
->unregister_on_failure
= true;
477 assert(!h
->current_operation
);
479 r
= home_set_current_message(h
, message
);
486 (void) home_unlink_record(h
);
491 static int method_realize_home(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
492 return generic_home_method(userdata
, message
, bus_home_method_realize
, error
);
495 static int method_remove_home(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
496 return generic_home_method(userdata
, message
, bus_home_method_remove
, error
);
499 static int method_fixate_home(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
500 return generic_home_method(userdata
, message
, bus_home_method_fixate
, error
);
503 static int method_authenticate_home(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
504 return generic_home_method(userdata
, message
, bus_home_method_authenticate
, error
);
507 static int method_update_home(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
508 _cleanup_(user_record_unrefp
) UserRecord
*hr
= NULL
;
509 Manager
*m
= userdata
;
516 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
, &hr
, error
);
520 assert(hr
->user_name
);
522 h
= hashmap_get(m
->homes_by_name
, hr
->user_name
);
524 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_HOME
, "No home for user %s known", hr
->user_name
);
526 return bus_home_method_update_record(h
, message
, hr
, error
);
529 static int method_resize_home(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
530 return generic_home_method(userdata
, message
, bus_home_method_resize
, error
);
533 static int method_change_password_home(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
534 return generic_home_method(userdata
, message
, bus_home_method_change_password
, error
);
537 static int method_lock_home(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
538 return generic_home_method(userdata
, message
, bus_home_method_lock
, error
);
541 static int method_unlock_home(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
542 return generic_home_method(userdata
, message
, bus_home_method_unlock
, error
);
545 static int method_acquire_home(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
546 return generic_home_method(userdata
, message
, bus_home_method_acquire
, error
);
549 static int method_ref_home(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
550 return generic_home_method(userdata
, message
, bus_home_method_ref
, error
);
553 static int method_release_home(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
554 return generic_home_method(userdata
, message
, bus_home_method_release
, error
);
557 static int method_lock_all_homes(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
558 _cleanup_(operation_unrefp
) Operation
*o
= NULL
;
559 bool waiting
= false;
560 Manager
*m
= userdata
;
566 /* This is called from logind when we are preparing for system suspend. We enqueue a lock operation
567 * for every suitable home we have and only when all of them completed we send a reply indicating
570 HASHMAP_FOREACH(h
, m
->homes_by_name
) {
572 /* Automatically suspend all homes that have at least one client referencing it that asked
573 * for "please suspend", and no client that asked for "please do not suspend". */
574 if (h
->ref_event_source_dont_suspend
||
575 !h
->ref_event_source_please_suspend
)
579 o
= operation_new(OPERATION_LOCK_ALL
, message
);
584 log_info("Automatically locking home of user %s.", h
->user_name
);
586 r
= home_schedule_operation(h
, o
, error
);
593 if (waiting
) /* At least one lock operation was enqeued, let's leave here without a reply: it will
594 * be sent as soon as the last of the lock operations completed. */
597 return sd_bus_reply_method_return(message
, NULL
);
600 static int method_deactivate_all_homes(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
601 _cleanup_(operation_unrefp
) Operation
*o
= NULL
;
602 bool waiting
= false;
603 Manager
*m
= userdata
;
609 /* This is called from systemd-homed-activate.service's ExecStop= command to ensure that all home
610 * directories are shutdown before the system goes down. Note that we don't do this from
611 * systemd-homed.service itself since we want to allow restarting of it without tearing down all home
614 HASHMAP_FOREACH(h
, m
->homes_by_name
) {
617 o
= operation_new(OPERATION_DEACTIVATE_ALL
, message
);
622 log_info("Automatically deactivating home of user %s.", h
->user_name
);
624 r
= home_schedule_operation(h
, o
, error
);
631 if (waiting
) /* At least one lock operation was enqeued, let's leave here without a reply: it will be
632 * sent as soon as the last of the deactivation operations completed. */
635 return sd_bus_reply_method_return(message
, NULL
);
638 static const sd_bus_vtable manager_vtable
[] = {
639 SD_BUS_VTABLE_START(0),
641 SD_BUS_PROPERTY("AutoLogin", "a(sso)", property_get_auto_login
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
643 SD_BUS_METHOD_WITH_NAMES("GetHomeByName",
645 SD_BUS_PARAM(user_name
),
648 SD_BUS_PARAM(home_state
)
650 SD_BUS_PARAM(real_name
)
651 SD_BUS_PARAM(home_directory
)
653 SD_BUS_PARAM(bus_path
),
654 method_get_home_by_name
,
655 SD_BUS_VTABLE_UNPRIVILEGED
),
656 SD_BUS_METHOD_WITH_NAMES("GetHomeByUID",
660 SD_BUS_PARAM(user_name
)
661 SD_BUS_PARAM(home_state
)
663 SD_BUS_PARAM(real_name
)
664 SD_BUS_PARAM(home_directory
)
666 SD_BUS_PARAM(bus_path
),
667 method_get_home_by_uid
,
668 SD_BUS_VTABLE_UNPRIVILEGED
),
669 SD_BUS_METHOD_WITH_NAMES("GetUserRecordByName",
671 SD_BUS_PARAM(user_name
),
673 SD_BUS_PARAM(user_record
)
674 SD_BUS_PARAM(incomplete
)
675 SD_BUS_PARAM(bus_path
),
676 method_get_user_record_by_name
,
677 SD_BUS_VTABLE_UNPRIVILEGED
|SD_BUS_VTABLE_SENSITIVE
),
678 SD_BUS_METHOD_WITH_NAMES("GetUserRecordByUID",
682 SD_BUS_PARAM(user_record
)
683 SD_BUS_PARAM(incomplete
)
684 SD_BUS_PARAM(bus_path
),
685 method_get_user_record_by_uid
,
686 SD_BUS_VTABLE_UNPRIVILEGED
|SD_BUS_VTABLE_SENSITIVE
),
687 SD_BUS_METHOD_WITH_NAMES("ListHomes",
690 SD_BUS_PARAM(home_areas
),
692 SD_BUS_VTABLE_UNPRIVILEGED
),
694 /* The following methods directly execute an operation on a home area, without ref-counting, queueing
695 * or anything, and are accessible through homectl. */
696 SD_BUS_METHOD_WITH_NAMES("ActivateHome",
698 SD_BUS_PARAM(user_name
)
699 SD_BUS_PARAM(secret
),
701 method_activate_home
,
702 SD_BUS_VTABLE_SENSITIVE
),
703 SD_BUS_METHOD_WITH_NAMES("DeactivateHome",
705 SD_BUS_PARAM(user_name
),
707 method_deactivate_home
,
710 /* Add the JSON record to homed, but don't create actual $HOME */
711 SD_BUS_METHOD_WITH_NAMES("RegisterHome",
713 SD_BUS_PARAM(user_record
),
715 method_register_home
,
716 SD_BUS_VTABLE_UNPRIVILEGED
),
718 /* Remove the JSON record from homed, but don't remove actual $HOME */
719 SD_BUS_METHOD_WITH_NAMES("UnregisterHome",
721 SD_BUS_PARAM(user_name
),
723 method_unregister_home
,
724 SD_BUS_VTABLE_UNPRIVILEGED
),
726 /* Add JSON record, and create $HOME for it */
727 SD_BUS_METHOD_WITH_NAMES("CreateHome",
729 SD_BUS_PARAM(user_record
),
732 SD_BUS_VTABLE_UNPRIVILEGED
|SD_BUS_VTABLE_SENSITIVE
),
734 /* Create $HOME for already registered JSON entry */
735 SD_BUS_METHOD_WITH_NAMES("RealizeHome",
737 SD_BUS_PARAM(user_name
)
738 SD_BUS_PARAM(secret
),
741 SD_BUS_VTABLE_UNPRIVILEGED
|SD_BUS_VTABLE_SENSITIVE
),
743 /* Remove the JSON record and remove $HOME */
744 SD_BUS_METHOD_WITH_NAMES("RemoveHome",
746 SD_BUS_PARAM(user_name
),
749 SD_BUS_VTABLE_UNPRIVILEGED
),
751 /* Investigate $HOME and propagate contained JSON record into our database */
752 SD_BUS_METHOD_WITH_NAMES("FixateHome",
754 SD_BUS_PARAM(user_name
)
755 SD_BUS_PARAM(secret
),
758 SD_BUS_VTABLE_SENSITIVE
),
760 /* Just check credentials */
761 SD_BUS_METHOD_WITH_NAMES("AuthenticateHome",
763 SD_BUS_PARAM(user_name
)
764 SD_BUS_PARAM(secret
),
766 method_authenticate_home
,
767 SD_BUS_VTABLE_UNPRIVILEGED
|SD_BUS_VTABLE_SENSITIVE
),
769 /* Update the JSON record of existing user */
770 SD_BUS_METHOD_WITH_NAMES("UpdateHome",
772 SD_BUS_PARAM(user_record
),
775 SD_BUS_VTABLE_UNPRIVILEGED
|SD_BUS_VTABLE_SENSITIVE
),
777 SD_BUS_METHOD_WITH_NAMES("ResizeHome",
779 SD_BUS_PARAM(user_name
)
781 SD_BUS_PARAM(secret
),
784 SD_BUS_VTABLE_UNPRIVILEGED
|SD_BUS_VTABLE_SENSITIVE
),
786 SD_BUS_METHOD_WITH_NAMES("ChangePasswordHome",
788 SD_BUS_PARAM(user_name
)
789 SD_BUS_PARAM(new_secret
)
790 SD_BUS_PARAM(old_secret
),
792 method_change_password_home
,
793 SD_BUS_VTABLE_UNPRIVILEGED
|SD_BUS_VTABLE_SENSITIVE
),
795 /* Prepare active home for system suspend: flush out passwords, suspend access */
796 SD_BUS_METHOD_WITH_NAMES("LockHome",
798 SD_BUS_PARAM(user_name
),
803 /* Make $HOME usable after system resume again */
804 SD_BUS_METHOD_WITH_NAMES("UnlockHome",
806 SD_BUS_PARAM(user_name
)
807 SD_BUS_PARAM(secret
),
810 SD_BUS_VTABLE_SENSITIVE
),
812 /* The following methods implement ref-counted activation, and are what the PAM module and "homectl
813 * with" use. In contrast to the methods above which fail if an operation is already being executed
814 * on a home directory, these ones will queue the request, and are thus more reliable. Moreover,
815 * they are a bit smarter: AcquireHome() will fixate, activate, unlock, or authenticate depending on
816 * the state of the home area, so that the end result is always the same (i.e. the home directory is
817 * accessible), and we always validate the specified passwords. RefHome() will not authenticate, and
818 * thus only works if the home area is already active. */
819 SD_BUS_METHOD_WITH_NAMES("AcquireHome",
821 SD_BUS_PARAM(user_name
)
823 SD_BUS_PARAM(please_suspend
),
825 SD_BUS_PARAM(send_fd
),
827 SD_BUS_VTABLE_UNPRIVILEGED
|SD_BUS_VTABLE_SENSITIVE
),
828 SD_BUS_METHOD_WITH_NAMES("RefHome",
830 SD_BUS_PARAM(user_name
)
831 SD_BUS_PARAM(please_suspend
),
833 SD_BUS_PARAM(send_fd
),
836 SD_BUS_METHOD_WITH_NAMES("ReleaseHome",
838 SD_BUS_PARAM(user_name
),
843 /* An operation that acts on all homes that allow it */
844 SD_BUS_METHOD("LockAllHomes", NULL
, NULL
, method_lock_all_homes
, 0),
845 SD_BUS_METHOD("DeactivateAllHomes", NULL
, NULL
, method_deactivate_all_homes
, 0),
850 const BusObjectImplementation manager_object
= {
851 "/org/freedesktop/home1",
852 "org.freedesktop.home1.Manager",
853 .vtables
= BUS_VTABLES(manager_vtable
),
854 .children
= BUS_IMPLEMENTATIONS(&home_object
),
857 static int on_deferred_auto_login(sd_event_source
*s
, void *userdata
) {
858 Manager
*m
= userdata
;
863 m
->deferred_auto_login_event_source
= sd_event_source_unref(m
->deferred_auto_login_event_source
);
865 r
= sd_bus_emit_properties_changed(
867 "/org/freedesktop/home1",
868 "org.freedesktop.home1.Manager",
871 log_warning_errno(r
, "Failed to send AutoLogin property change event, ignoring: %m");
876 int bus_manager_emit_auto_login_changed(Manager
*m
) {
880 if (m
->deferred_auto_login_event_source
)
886 if (IN_SET(sd_event_get_state(m
->event
), SD_EVENT_FINISHED
, SD_EVENT_EXITING
))
889 r
= sd_event_add_defer(m
->event
, &m
->deferred_auto_login_event_source
, on_deferred_auto_login
, m
);
891 return log_error_errno(r
, "Failed to allocate auto login event source: %m");
893 r
= sd_event_source_set_priority(m
->deferred_auto_login_event_source
, SD_EVENT_PRIORITY_IDLE
+10);
895 log_warning_errno(r
, "Failed to tweak priority of event source, ignoring: %m");
897 (void) sd_event_source_set_description(m
->deferred_auto_login_event_source
, "deferred-auto-login");