1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
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
= ASSERT_PTR(userdata
);
34 r
= sd_bus_message_open_container(reply
, 'a', "(sso)");
38 HASHMAP_FOREACH(h
, m
->homes_by_name
) {
39 _cleanup_strv_free_
char **seats
= NULL
;
40 _cleanup_free_
char *home_path
= NULL
;
42 r
= home_auto_login(h
, &seats
);
44 log_debug_errno(r
, "Failed to determine whether home '%s' is candidate for auto-login, ignoring: %m", h
->user_name
);
50 r
= bus_home_path(h
, &home_path
);
52 return log_error_errno(r
, "Failed to generate home bus path: %m");
54 STRV_FOREACH(s
, seats
) {
55 r
= sd_bus_message_append(reply
, "(sso)", h
->user_name
, *s
, home_path
);
61 return sd_bus_message_close_container(reply
);
64 static int method_get_home_by_name(
65 sd_bus_message
*message
,
67 sd_bus_error
*error
) {
69 _cleanup_free_
char *path
= NULL
;
70 const char *user_name
;
71 Manager
*m
= ASSERT_PTR(userdata
);
77 r
= sd_bus_message_read(message
, "s", &user_name
);
80 if (!valid_user_group_name(user_name
, 0))
81 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "User name %s is not valid", user_name
);
83 h
= hashmap_get(m
->homes_by_name
, user_name
);
85 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_HOME
, "No home for user %s known", user_name
);
87 r
= bus_home_path(h
, &path
);
91 return sd_bus_reply_method_return(
94 home_state_to_string(home_get_state(h
)),
95 h
->record
? (uint32_t) user_record_gid(h
->record
) : GID_INVALID
,
96 h
->record
? user_record_real_name(h
->record
) : NULL
,
97 h
->record
? user_record_home_directory(h
->record
) : NULL
,
98 h
->record
? user_record_shell(h
->record
) : NULL
,
102 static int method_get_home_by_uid(
103 sd_bus_message
*message
,
105 sd_bus_error
*error
) {
107 _cleanup_free_
char *path
= NULL
;
108 Manager
*m
= ASSERT_PTR(userdata
);
115 r
= sd_bus_message_read(message
, "u", &uid
);
118 if (!uid_is_valid(uid
))
119 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "UID " UID_FMT
" is not valid", uid
);
121 h
= hashmap_get(m
->homes_by_uid
, UID_TO_PTR(uid
));
123 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_HOME
, "No home for UID " UID_FMT
" known", uid
);
125 /* Note that we don't use bus_home_path() here, but build the path manually, since if we are queried
126 * for a UID we should also generate the bus path with a UID, and bus_home_path() uses our more
127 * typical bus path by name. */
128 if (asprintf(&path
, "/org/freedesktop/home1/home/" UID_FMT
, h
->uid
) < 0)
131 return sd_bus_reply_method_return(
134 home_state_to_string(home_get_state(h
)),
135 h
->record
? (uint32_t) user_record_gid(h
->record
) : GID_INVALID
,
136 h
->record
? user_record_real_name(h
->record
) : NULL
,
137 h
->record
? user_record_home_directory(h
->record
) : NULL
,
138 h
->record
? user_record_shell(h
->record
) : NULL
,
142 static int method_list_homes(
143 sd_bus_message
*message
,
145 sd_bus_error
*error
) {
147 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
148 Manager
*m
= ASSERT_PTR(userdata
);
154 r
= sd_bus_message_new_method_return(message
, &reply
);
158 r
= sd_bus_message_open_container(reply
, 'a', "(susussso)");
162 HASHMAP_FOREACH(h
, m
->homes_by_uid
) {
163 _cleanup_free_
char *path
= NULL
;
165 r
= bus_home_path(h
, &path
);
169 r
= sd_bus_message_append(
173 home_state_to_string(home_get_state(h
)),
174 h
->record
? (uint32_t) user_record_gid(h
->record
) : GID_INVALID
,
175 h
->record
? user_record_real_name(h
->record
) : NULL
,
176 h
->record
? user_record_home_directory(h
->record
) : NULL
,
177 h
->record
? user_record_shell(h
->record
) : NULL
,
183 r
= sd_bus_message_close_container(reply
);
187 return sd_bus_send(NULL
, reply
, NULL
);
190 static int method_get_user_record_by_name(
191 sd_bus_message
*message
,
193 sd_bus_error
*error
) {
195 _cleanup_free_
char *json
= NULL
, *path
= NULL
;
196 Manager
*m
= ASSERT_PTR(userdata
);
197 const char *user_name
;
204 r
= sd_bus_message_read(message
, "s", &user_name
);
207 if (!valid_user_group_name(user_name
, 0))
208 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "User name %s is not valid", user_name
);
210 h
= hashmap_get(m
->homes_by_name
, user_name
);
212 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_HOME
, "No home for user %s known", user_name
);
214 r
= bus_home_get_record_json(h
, message
, &json
, &incomplete
);
218 r
= bus_home_path(h
, &path
);
222 return sd_bus_reply_method_return(
229 static int method_get_user_record_by_uid(
230 sd_bus_message
*message
,
232 sd_bus_error
*error
) {
234 _cleanup_free_
char *json
= NULL
, *path
= NULL
;
235 Manager
*m
= ASSERT_PTR(userdata
);
243 r
= sd_bus_message_read(message
, "u", &uid
);
246 if (!uid_is_valid(uid
))
247 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "UID " UID_FMT
" is not valid", uid
);
249 h
= hashmap_get(m
->homes_by_uid
, UID_TO_PTR(uid
));
251 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_HOME
, "No home for UID " UID_FMT
" known", uid
);
253 r
= bus_home_get_record_json(h
, message
, &json
, &incomplete
);
257 if (asprintf(&path
, "/org/freedesktop/home1/home/" UID_FMT
, h
->uid
) < 0)
260 return sd_bus_reply_method_return(
267 static int generic_home_method(
269 sd_bus_message
*message
,
270 sd_bus_message_handler_t handler
,
271 sd_bus_error
*error
) {
273 const char *user_name
;
277 r
= sd_bus_message_read(message
, "s", &user_name
);
281 if (!valid_user_group_name(user_name
, 0))
282 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "User name %s is not valid", user_name
);
284 h
= hashmap_get(m
->homes_by_name
, user_name
);
286 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_HOME
, "No home for user %s known", user_name
);
288 return handler(message
, h
, error
);
291 static int method_activate_home(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
292 return generic_home_method(userdata
, message
, bus_home_method_activate
, error
);
295 static int method_deactivate_home(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
296 return generic_home_method(userdata
, message
, bus_home_method_deactivate
, error
);
299 static int validate_and_allocate_home(Manager
*m
, UserRecord
*hr
, Home
**ret
, sd_bus_error
*error
) {
300 _cleanup_(user_record_unrefp
) UserRecord
*signed_hr
= NULL
;
311 r
= user_record_is_supported(hr
, error
);
315 other
= hashmap_get(m
->homes_by_name
, hr
->user_name
);
317 return sd_bus_error_setf(error
, BUS_ERROR_USER_NAME_EXISTS
, "Specified user name %s exists already, refusing.", hr
->user_name
);
319 pw
= getpwnam(hr
->user_name
);
321 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
);
323 gr
= getgrnam(hr
->user_name
);
325 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
);
327 r
= manager_verify_user_record(m
, hr
);
330 case USER_RECORD_UNSIGNED
:
331 /* If the record is unsigned, then let's sign it with our own key */
332 r
= manager_sign_user_record(m
, hr
, &signed_hr
, error
);
339 case USER_RECORD_SIGNED_EXCLUSIVE
:
340 signed_locally
= true;
343 case USER_RECORD_SIGNED
:
344 case USER_RECORD_FOREIGN
:
345 signed_locally
= false;
349 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
);
352 return sd_bus_error_set_errnof(error
, r
, "Failed to validate signature for '%s': %m", hr
->user_name
);
355 if (uid_is_valid(hr
->uid
)) {
356 other
= hashmap_get(m
->homes_by_uid
, UID_TO_PTR(hr
->uid
));
358 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
);
360 pw
= getpwuid(hr
->uid
);
362 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
);
364 gr
= getgrgid(hr
->uid
);
366 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
);
368 r
= manager_augment_record_with_uid(m
, hr
);
370 return sd_bus_error_set_errnof(error
, r
, "Failed to acquire UID for '%s': %m", hr
->user_name
);
373 r
= home_new(m
, hr
, NULL
, ret
);
377 (*ret
)->signed_locally
= signed_locally
;
381 static int method_register_home(
382 sd_bus_message
*message
,
384 sd_bus_error
*error
) {
386 _cleanup_(user_record_unrefp
) UserRecord
*hr
= NULL
;
387 Manager
*m
= ASSERT_PTR(userdata
);
388 _cleanup_(home_freep
) Home
*h
= NULL
;
393 r
= bus_message_read_home_record(message
, USER_RECORD_LOAD_EMBEDDED
|USER_RECORD_PERMISSIVE
, &hr
, error
);
397 r
= bus_verify_polkit_async(
400 "org.freedesktop.home1.create-home",
409 return 1; /* Will call us back */
411 r
= validate_and_allocate_home(m
, hr
, &h
, error
);
415 r
= home_save_record(h
);
421 return sd_bus_reply_method_return(message
, NULL
);
424 static int method_unregister_home(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
425 return generic_home_method(userdata
, message
, bus_home_method_unregister
, error
);
428 static int method_create_home(
429 sd_bus_message
*message
,
431 sd_bus_error
*error
) {
433 _cleanup_(user_record_unrefp
) UserRecord
*hr
= NULL
;
434 Manager
*m
= ASSERT_PTR(userdata
);
440 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
);
444 r
= bus_verify_polkit_async(
447 "org.freedesktop.home1.create-home",
456 return 1; /* Will call us back */
458 r
= validate_and_allocate_home(m
, hr
, &h
, error
);
462 r
= home_create(h
, hr
, error
);
467 h
->unregister_on_failure
= true;
468 assert(!h
->current_operation
);
470 r
= home_set_current_message(h
, message
);
477 (void) home_unlink_record(h
);
482 static int method_realize_home(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
483 return generic_home_method(userdata
, message
, bus_home_method_realize
, error
);
486 static int method_remove_home(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
487 return generic_home_method(userdata
, message
, bus_home_method_remove
, error
);
490 static int method_fixate_home(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
491 return generic_home_method(userdata
, message
, bus_home_method_fixate
, error
);
494 static int method_authenticate_home(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
495 return generic_home_method(userdata
, message
, bus_home_method_authenticate
, error
);
498 static int method_update_home(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
499 _cleanup_(user_record_unrefp
) UserRecord
*hr
= NULL
;
500 Manager
*m
= ASSERT_PTR(userdata
);
506 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
);
510 assert(hr
->user_name
);
512 h
= hashmap_get(m
->homes_by_name
, hr
->user_name
);
514 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_HOME
, "No home for user %s known", hr
->user_name
);
516 return bus_home_method_update_record(h
, message
, hr
, error
);
519 static int method_resize_home(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
520 return generic_home_method(userdata
, message
, bus_home_method_resize
, error
);
523 static int method_change_password_home(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
524 return generic_home_method(userdata
, message
, bus_home_method_change_password
, error
);
527 static int method_lock_home(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
528 return generic_home_method(userdata
, message
, bus_home_method_lock
, error
);
531 static int method_unlock_home(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
532 return generic_home_method(userdata
, message
, bus_home_method_unlock
, error
);
535 static int method_acquire_home(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
536 return generic_home_method(userdata
, message
, bus_home_method_acquire
, error
);
539 static int method_ref_home(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
540 return generic_home_method(userdata
, message
, bus_home_method_ref
, error
);
543 static int method_release_home(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
544 return generic_home_method(userdata
, message
, bus_home_method_release
, error
);
547 static int method_lock_all_homes(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
548 _cleanup_(operation_unrefp
) Operation
*o
= NULL
;
549 bool waiting
= false;
550 Manager
*m
= ASSERT_PTR(userdata
);
554 /* This is called from logind when we are preparing for system suspend. We enqueue a lock operation
555 * for every suitable home we have and only when all of them completed we send a reply indicating
558 HASHMAP_FOREACH(h
, m
->homes_by_name
) {
560 /* Automatically suspend all homes that have at least one client referencing it that asked
561 * for "please suspend", and no client that asked for "please do not suspend". */
562 if (h
->ref_event_source_dont_suspend
||
563 !h
->ref_event_source_please_suspend
)
567 o
= operation_new(OPERATION_LOCK_ALL
, message
);
572 log_info("Automatically locking home of user %s.", h
->user_name
);
574 r
= home_schedule_operation(h
, o
, error
);
581 if (waiting
) /* At least one lock operation was enqeued, let's leave here without a reply: it will
582 * be sent as soon as the last of the lock operations completed. */
585 return sd_bus_reply_method_return(message
, NULL
);
588 static int method_deactivate_all_homes(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
589 _cleanup_(operation_unrefp
) Operation
*o
= NULL
;
590 bool waiting
= false;
591 Manager
*m
= ASSERT_PTR(userdata
);
595 /* This is called from systemd-homed-activate.service's ExecStop= command to ensure that all home
596 * directories are shutdown before the system goes down. Note that we don't do this from
597 * systemd-homed.service itself since we want to allow restarting of it without tearing down all home
600 HASHMAP_FOREACH(h
, m
->homes_by_name
) {
603 o
= operation_new(OPERATION_DEACTIVATE_ALL
, message
);
608 log_info("Automatically deactivating home of user %s.", h
->user_name
);
610 r
= home_schedule_operation(h
, o
, error
);
617 if (waiting
) /* At least one lock operation was enqeued, let's leave here without a reply: it will be
618 * sent as soon as the last of the deactivation operations completed. */
621 return sd_bus_reply_method_return(message
, NULL
);
624 static int method_rebalance(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
625 Manager
*m
= ASSERT_PTR(userdata
);
628 r
= manager_schedule_rebalance(m
, /* immediately= */ true);
630 return sd_bus_reply_method_errorf(message
, BUS_ERROR_REBALANCE_NOT_NEEDED
, "No home directories need rebalancing.");
634 /* Keep a reference to this message, so that we can reply to it once we are done */
635 r
= set_ensure_put(&m
->rebalance_queued_method_calls
, &bus_message_hash_ops
, message
);
637 return log_error_errno(r
, "Failed to track rebalance bus message: %m");
639 sd_bus_message_ref(message
);
643 static const sd_bus_vtable manager_vtable
[] = {
644 SD_BUS_VTABLE_START(0),
646 SD_BUS_PROPERTY("AutoLogin", "a(sso)", property_get_auto_login
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
648 SD_BUS_METHOD_WITH_ARGS("GetHomeByName",
649 SD_BUS_ARGS("s", user_name
),
650 SD_BUS_RESULT("u", uid
,
657 method_get_home_by_name
,
658 SD_BUS_VTABLE_UNPRIVILEGED
),
659 SD_BUS_METHOD_WITH_ARGS("GetHomeByUID",
660 SD_BUS_ARGS("u", uid
),
661 SD_BUS_RESULT("s", user_name
,
668 method_get_home_by_uid
,
669 SD_BUS_VTABLE_UNPRIVILEGED
),
670 SD_BUS_METHOD_WITH_ARGS("GetUserRecordByName",
671 SD_BUS_ARGS("s", user_name
),
672 SD_BUS_RESULT("s", user_record
, "b", incomplete
, "o", bus_path
),
673 method_get_user_record_by_name
,
674 SD_BUS_VTABLE_UNPRIVILEGED
|SD_BUS_VTABLE_SENSITIVE
),
675 SD_BUS_METHOD_WITH_ARGS("GetUserRecordByUID",
676 SD_BUS_ARGS("u", uid
),
677 SD_BUS_RESULT("s", user_record
, "b", incomplete
, "o", bus_path
),
678 method_get_user_record_by_uid
,
679 SD_BUS_VTABLE_UNPRIVILEGED
|SD_BUS_VTABLE_SENSITIVE
),
680 SD_BUS_METHOD_WITH_ARGS("ListHomes",
682 SD_BUS_RESULT("a(susussso)", home_areas
),
684 SD_BUS_VTABLE_UNPRIVILEGED
),
686 /* The following methods directly execute an operation on a home area, without ref-counting, queueing
687 * or anything, and are accessible through homectl. */
688 SD_BUS_METHOD_WITH_ARGS("ActivateHome",
689 SD_BUS_ARGS("s", user_name
, "s", secret
),
691 method_activate_home
,
692 SD_BUS_VTABLE_SENSITIVE
),
693 SD_BUS_METHOD_WITH_ARGS("DeactivateHome",
694 SD_BUS_ARGS("s", user_name
),
696 method_deactivate_home
,
699 /* Add the JSON record to homed, but don't create actual $HOME */
700 SD_BUS_METHOD_WITH_ARGS("RegisterHome",
701 SD_BUS_ARGS("s", user_record
),
703 method_register_home
,
704 SD_BUS_VTABLE_UNPRIVILEGED
),
706 /* Remove the JSON record from homed, but don't remove actual $HOME */
707 SD_BUS_METHOD_WITH_ARGS("UnregisterHome",
708 SD_BUS_ARGS("s", user_name
),
710 method_unregister_home
,
711 SD_BUS_VTABLE_UNPRIVILEGED
),
713 /* Add JSON record, and create $HOME for it */
714 SD_BUS_METHOD_WITH_ARGS("CreateHome",
715 SD_BUS_ARGS("s", user_record
),
718 SD_BUS_VTABLE_UNPRIVILEGED
|SD_BUS_VTABLE_SENSITIVE
),
720 /* Create $HOME for already registered JSON entry */
721 SD_BUS_METHOD_WITH_ARGS("RealizeHome",
722 SD_BUS_ARGS("s", user_name
, "s", secret
),
725 SD_BUS_VTABLE_UNPRIVILEGED
|SD_BUS_VTABLE_SENSITIVE
),
727 /* Remove the JSON record and remove $HOME */
728 SD_BUS_METHOD_WITH_ARGS("RemoveHome",
729 SD_BUS_ARGS("s", user_name
),
732 SD_BUS_VTABLE_UNPRIVILEGED
),
734 /* Investigate $HOME and propagate contained JSON record into our database */
735 SD_BUS_METHOD_WITH_ARGS("FixateHome",
736 SD_BUS_ARGS("s", user_name
, "s", secret
),
739 SD_BUS_VTABLE_SENSITIVE
),
741 /* Just check credentials */
742 SD_BUS_METHOD_WITH_ARGS("AuthenticateHome",
743 SD_BUS_ARGS("s", user_name
, "s", secret
),
745 method_authenticate_home
,
746 SD_BUS_VTABLE_UNPRIVILEGED
|SD_BUS_VTABLE_SENSITIVE
),
748 /* Update the JSON record of existing user */
749 SD_BUS_METHOD_WITH_ARGS("UpdateHome",
750 SD_BUS_ARGS("s", user_record
),
753 SD_BUS_VTABLE_UNPRIVILEGED
|SD_BUS_VTABLE_SENSITIVE
),
755 SD_BUS_METHOD_WITH_ARGS("ResizeHome",
756 SD_BUS_ARGS("s", user_name
, "t", size
, "s", secret
),
759 SD_BUS_VTABLE_UNPRIVILEGED
|SD_BUS_VTABLE_SENSITIVE
),
761 SD_BUS_METHOD_WITH_ARGS("ChangePasswordHome",
762 SD_BUS_ARGS("s", user_name
, "s", new_secret
, "s", old_secret
),
764 method_change_password_home
,
765 SD_BUS_VTABLE_UNPRIVILEGED
|SD_BUS_VTABLE_SENSITIVE
),
767 /* Prepare active home for system suspend: flush out passwords, suspend access */
768 SD_BUS_METHOD_WITH_ARGS("LockHome",
769 SD_BUS_ARGS("s", user_name
),
774 /* Make $HOME usable after system resume again */
775 SD_BUS_METHOD_WITH_ARGS("UnlockHome",
776 SD_BUS_ARGS("s", user_name
, "s", secret
),
779 SD_BUS_VTABLE_SENSITIVE
),
781 /* The following methods implement ref-counted activation, and are what the PAM module and "homectl
782 * with" use. In contrast to the methods above which fail if an operation is already being executed
783 * on a home directory, these ones will queue the request, and are thus more reliable. Moreover,
784 * they are a bit smarter: AcquireHome() will fixate, activate, unlock, or authenticate depending on
785 * the state of the home area, so that the end result is always the same (i.e. the home directory is
786 * accessible), and we always validate the specified passwords. RefHome() will not authenticate, and
787 * thus only works if the home area is already active. */
788 SD_BUS_METHOD_WITH_ARGS("AcquireHome",
789 SD_BUS_ARGS("s", user_name
, "s", secret
, "b", please_suspend
),
790 SD_BUS_RESULT("h", send_fd
),
792 SD_BUS_VTABLE_UNPRIVILEGED
|SD_BUS_VTABLE_SENSITIVE
),
793 SD_BUS_METHOD_WITH_ARGS("RefHome",
794 SD_BUS_ARGS("s", user_name
, "b", please_suspend
),
795 SD_BUS_RESULT("h", send_fd
),
798 SD_BUS_METHOD_WITH_ARGS("ReleaseHome",
799 SD_BUS_ARGS("s", user_name
),
804 /* An operation that acts on all homes that allow it */
805 SD_BUS_METHOD("LockAllHomes", NULL
, NULL
, method_lock_all_homes
, 0),
806 SD_BUS_METHOD("DeactivateAllHomes", NULL
, NULL
, method_deactivate_all_homes
, 0),
807 SD_BUS_METHOD("Rebalance", NULL
, NULL
, method_rebalance
, 0),
812 const BusObjectImplementation manager_object
= {
813 "/org/freedesktop/home1",
814 "org.freedesktop.home1.Manager",
815 .vtables
= BUS_VTABLES(manager_vtable
),
816 .children
= BUS_IMPLEMENTATIONS(&home_object
),
819 static int on_deferred_auto_login(sd_event_source
*s
, void *userdata
) {
820 Manager
*m
= ASSERT_PTR(userdata
);
823 m
->deferred_auto_login_event_source
= sd_event_source_disable_unref(m
->deferred_auto_login_event_source
);
825 r
= sd_bus_emit_properties_changed(
827 "/org/freedesktop/home1",
828 "org.freedesktop.home1.Manager",
831 log_warning_errno(r
, "Failed to send AutoLogin property change event, ignoring: %m");
836 int bus_manager_emit_auto_login_changed(Manager
*m
) {
840 if (m
->deferred_auto_login_event_source
)
846 if (IN_SET(sd_event_get_state(m
->event
), SD_EVENT_FINISHED
, SD_EVENT_EXITING
))
849 r
= sd_event_add_defer(m
->event
, &m
->deferred_auto_login_event_source
, on_deferred_auto_login
, m
);
851 return log_error_errno(r
, "Failed to allocate auto login event source: %m");
853 r
= sd_event_source_set_priority(m
->deferred_auto_login_event_source
, SD_EVENT_PRIORITY_IDLE
+10);
855 log_warning_errno(r
, "Failed to tweak priority of event source, ignoring: %m");
857 (void) sd_event_source_set_description(m
->deferred_auto_login_event_source
, "deferred-auto-login");