1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 #include <linux/capability.h>
5 #include "bus-common-errors.h"
6 #include "bus-polkit.h"
9 #include "homed-home-bus.h"
10 #include "homed-home.h"
12 #include "user-record-util.h"
13 #include "user-util.h"
15 static int property_get_unix_record(
18 const char *interface
,
20 sd_bus_message
*reply
,
22 sd_bus_error
*error
) {
30 return sd_bus_message_append(
34 h
->record
? (uint32_t) user_record_gid(h
->record
) : GID_INVALID
,
35 h
->record
? user_record_real_name(h
->record
) : NULL
,
36 h
->record
? user_record_home_directory(h
->record
) : NULL
,
37 h
->record
? user_record_shell(h
->record
) : NULL
);
40 static int property_get_state(
43 const char *interface
,
45 sd_bus_message
*reply
,
47 sd_bus_error
*error
) {
55 return sd_bus_message_append(reply
, "s", home_state_to_string(home_get_state(h
)));
58 int bus_home_client_is_trusted(Home
*h
, sd_bus_message
*message
) {
59 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
68 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_EUID
, &creds
);
72 r
= sd_bus_creds_get_euid(creds
, &euid
);
76 return euid
== 0 || h
->uid
== euid
;
79 int bus_home_get_record_json(
81 sd_bus_message
*message
,
83 bool *ret_incomplete
) {
85 _cleanup_(user_record_unrefp
) UserRecord
*augmented
= NULL
;
86 UserRecordLoadFlags flags
;
92 trusted
= bus_home_client_is_trusted(h
, message
);
94 log_warning_errno(trusted
, "Failed to determine whether client is trusted, assuming untrusted.");
98 flags
= USER_RECORD_REQUIRE_REGULAR
|USER_RECORD_ALLOW_PER_MACHINE
|USER_RECORD_ALLOW_BINDING
|USER_RECORD_STRIP_SECRET
|USER_RECORD_ALLOW_STATUS
|USER_RECORD_ALLOW_SIGNATURE
;
100 flags
|= USER_RECORD_ALLOW_PRIVILEGED
;
102 flags
|= USER_RECORD_STRIP_PRIVILEGED
;
104 r
= home_augment_status(h
, flags
, &augmented
);
108 r
= json_variant_format(augmented
->json
, 0, ret
);
113 *ret_incomplete
= augmented
->incomplete
;
118 static int property_get_user_record(
121 const char *interface
,
122 const char *property
,
123 sd_bus_message
*reply
,
125 sd_bus_error
*error
) {
127 _cleanup_free_
char *json
= NULL
;
136 r
= bus_home_get_record_json(h
, sd_bus_get_current_message(bus
), &json
, &incomplete
);
140 return sd_bus_message_append(reply
, "(sb)", json
, incomplete
);
143 int bus_home_method_activate(
144 sd_bus_message
*message
,
146 sd_bus_error
*error
) {
148 _cleanup_(user_record_unrefp
) UserRecord
*secret
= NULL
;
155 r
= bus_message_read_secret(message
, &secret
, error
);
159 r
= home_activate(h
, secret
, error
);
164 assert(!h
->current_operation
);
166 /* The operation is now in process, keep track of this message so that we can later reply to it. */
167 r
= home_set_current_message(h
, message
);
174 int bus_home_method_deactivate(
175 sd_bus_message
*message
,
177 sd_bus_error
*error
) {
185 r
= home_deactivate(h
, false, error
);
190 assert(!h
->current_operation
);
192 r
= home_set_current_message(h
, message
);
199 int bus_home_method_unregister(
200 sd_bus_message
*message
,
202 sd_bus_error
*error
) {
210 r
= bus_verify_polkit_async(
213 "org.freedesktop.home1.remove-home",
217 &h
->manager
->polkit_registry
,
222 return 1; /* Will call us back */
224 r
= home_unregister(h
, error
);
230 /* Note that home_unregister() destroyed 'h' here, so no more accesses */
232 return sd_bus_reply_method_return(message
, NULL
);
235 int bus_home_method_realize(
236 sd_bus_message
*message
,
238 sd_bus_error
*error
) {
240 _cleanup_(user_record_unrefp
) UserRecord
*secret
= NULL
;
247 r
= bus_message_read_secret(message
, &secret
, error
);
251 r
= bus_verify_polkit_async(
254 "org.freedesktop.home1.create-home",
258 &h
->manager
->polkit_registry
,
263 return 1; /* Will call us back */
265 r
= home_create(h
, secret
, error
);
270 assert(!h
->current_operation
);
272 h
->unregister_on_failure
= false;
274 r
= home_set_current_message(h
, message
);
281 int bus_home_method_remove(
282 sd_bus_message
*message
,
284 sd_bus_error
*error
) {
292 r
= bus_verify_polkit_async(
295 "org.freedesktop.home1.remove-home",
299 &h
->manager
->polkit_registry
,
304 return 1; /* Will call us back */
306 r
= home_remove(h
, error
);
309 if (r
> 0) /* Done already. Note that home_remove() destroyed 'h' here, so no more accesses */
310 return sd_bus_reply_method_return(message
, NULL
);
312 assert(!h
->current_operation
);
314 r
= home_set_current_message(h
, message
);
321 int bus_home_method_fixate(
322 sd_bus_message
*message
,
324 sd_bus_error
*error
) {
326 _cleanup_(user_record_unrefp
) UserRecord
*secret
= NULL
;
333 r
= bus_message_read_secret(message
, &secret
, error
);
337 r
= home_fixate(h
, secret
, error
);
342 assert(!h
->current_operation
);
344 r
= home_set_current_message(h
, message
);
351 int bus_home_method_authenticate(
352 sd_bus_message
*message
,
354 sd_bus_error
*error
) {
356 _cleanup_(user_record_unrefp
) UserRecord
*secret
= NULL
;
363 r
= bus_message_read_secret(message
, &secret
, error
);
367 r
= bus_verify_polkit_async(
370 "org.freedesktop.home1.authenticate-home",
374 &h
->manager
->polkit_registry
,
379 return 1; /* Will call us back */
381 r
= home_authenticate(h
, secret
, error
);
386 assert(!h
->current_operation
);
388 r
= home_set_current_message(h
, message
);
395 int bus_home_method_update_record(Home
*h
, sd_bus_message
*message
, UserRecord
*hr
, sd_bus_error
*error
) {
402 r
= user_record_is_supported(hr
, error
);
406 r
= bus_verify_polkit_async(
409 "org.freedesktop.home1.update-home",
413 &h
->manager
->polkit_registry
,
418 return 1; /* Will call us back */
420 r
= home_update(h
, hr
, error
);
425 assert(!h
->current_operation
);
427 r
= home_set_current_message(h
, message
);
434 int bus_home_method_update(
435 sd_bus_message
*message
,
437 sd_bus_error
*error
) {
439 _cleanup_(user_record_unrefp
) UserRecord
*hr
= NULL
;
446 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
, &hr
, error
);
450 return bus_home_method_update_record(h
, message
, hr
, error
);
453 int bus_home_method_resize(
454 sd_bus_message
*message
,
456 sd_bus_error
*error
) {
458 _cleanup_(user_record_unrefp
) UserRecord
*secret
= NULL
;
466 r
= sd_bus_message_read(message
, "t", &sz
);
470 r
= bus_message_read_secret(message
, &secret
, error
);
474 r
= bus_verify_polkit_async(
477 "org.freedesktop.home1.resize-home",
481 &h
->manager
->polkit_registry
,
486 return 1; /* Will call us back */
488 r
= home_resize(h
, sz
, secret
, error
);
493 assert(!h
->current_operation
);
495 r
= home_set_current_message(h
, message
);
502 int bus_home_method_change_password(
503 sd_bus_message
*message
,
505 sd_bus_error
*error
) {
507 _cleanup_(user_record_unrefp
) UserRecord
*new_secret
= NULL
, *old_secret
= NULL
;
514 r
= bus_message_read_secret(message
, &new_secret
, error
);
518 r
= bus_message_read_secret(message
, &old_secret
, error
);
522 r
= bus_verify_polkit_async(
525 "org.freedesktop.home1.passwd-home",
529 &h
->manager
->polkit_registry
,
534 return 1; /* Will call us back */
536 r
= home_passwd(h
, new_secret
, old_secret
, error
);
541 assert(!h
->current_operation
);
543 r
= home_set_current_message(h
, message
);
550 int bus_home_method_lock(
551 sd_bus_message
*message
,
553 sd_bus_error
*error
) {
561 r
= home_lock(h
, error
);
564 if (r
> 0) /* Done */
565 return sd_bus_reply_method_return(message
, NULL
);
567 /* The operation is now in process, keep track of this message so that we can later reply to it. */
568 assert(!h
->current_operation
);
570 r
= home_set_current_message(h
, message
);
577 int bus_home_method_unlock(
578 sd_bus_message
*message
,
580 sd_bus_error
*error
) {
582 _cleanup_(user_record_unrefp
) UserRecord
*secret
= NULL
;
589 r
= bus_message_read_secret(message
, &secret
, error
);
593 r
= home_unlock(h
, secret
, error
);
598 assert(!h
->current_operation
);
600 /* The operation is now in process, keep track of this message so that we can later reply to it. */
601 r
= home_set_current_message(h
, message
);
608 int bus_home_method_acquire(
609 sd_bus_message
*message
,
611 sd_bus_error
*error
) {
613 _cleanup_(user_record_unrefp
) UserRecord
*secret
= NULL
;
614 _cleanup_(operation_unrefp
) Operation
*o
= NULL
;
615 _cleanup_close_
int fd
= -1;
616 int r
, please_suspend
;
622 r
= bus_message_read_secret(message
, &secret
, error
);
626 r
= sd_bus_message_read(message
, "b", &please_suspend
);
630 /* This operation might not be something we can executed immediately, hence queue it */
631 fd
= home_create_fifo(h
, please_suspend
);
633 return sd_bus_reply_method_errnof(message
, fd
, "Failed to allocate fifo for %s: %m", h
->user_name
);
635 o
= operation_new(OPERATION_ACQUIRE
, message
);
639 o
->secret
= TAKE_PTR(secret
);
640 o
->send_fd
= TAKE_FD(fd
);
642 r
= home_schedule_operation(h
, o
, error
);
649 int bus_home_method_ref(
650 sd_bus_message
*message
,
652 sd_bus_error
*error
) {
654 _cleanup_close_
int fd
= -1;
657 int please_suspend
, r
;
662 r
= sd_bus_message_read(message
, "b", &please_suspend
);
666 state
= home_get_state(h
);
669 return sd_bus_error_setf(error
, BUS_ERROR_HOME_ABSENT
, "Home %s is currently missing or not plugged in.", h
->user_name
);
672 return sd_bus_error_setf(error
, BUS_ERROR_HOME_NOT_ACTIVE
, "Home %s not active.", h
->user_name
);
674 return sd_bus_error_setf(error
, BUS_ERROR_HOME_LOCKED
, "Home %s is currently locked.", h
->user_name
);
676 if (HOME_STATE_IS_ACTIVE(state
))
679 return sd_bus_error_setf(error
, BUS_ERROR_HOME_BUSY
, "An operation on home %s is currently being executed.", h
->user_name
);
682 fd
= home_create_fifo(h
, please_suspend
);
684 return sd_bus_reply_method_errnof(message
, fd
, "Failed to allocate fifo for %s: %m", h
->user_name
);
686 return sd_bus_reply_method_return(message
, "h", fd
);
689 int bus_home_method_release(
690 sd_bus_message
*message
,
692 sd_bus_error
*error
) {
694 _cleanup_(operation_unrefp
) Operation
*o
= NULL
;
701 o
= operation_new(OPERATION_RELEASE
, message
);
705 r
= home_schedule_operation(h
, o
, error
);
712 /* We map a uid_t as uint32_t bus property, let's ensure this is safe. */
713 assert_cc(sizeof(uid_t
) == sizeof(uint32_t));
715 const sd_bus_vtable home_vtable
[] = {
716 SD_BUS_VTABLE_START(0),
717 SD_BUS_PROPERTY("UserName", "s", NULL
, offsetof(Home
, user_name
), SD_BUS_VTABLE_PROPERTY_CONST
),
718 SD_BUS_PROPERTY("UID", "u", NULL
, offsetof(Home
, uid
), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
719 SD_BUS_PROPERTY("UnixRecord", "(suusss)", property_get_unix_record
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
720 SD_BUS_PROPERTY("State", "s", property_get_state
, 0, 0),
721 SD_BUS_PROPERTY("UserRecord", "(sb)", property_get_user_record
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION
|SD_BUS_VTABLE_SENSITIVE
),
722 SD_BUS_METHOD("Activate", "s", NULL
, bus_home_method_activate
, SD_BUS_VTABLE_SENSITIVE
),
723 SD_BUS_METHOD("Deactivate", NULL
, NULL
, bus_home_method_deactivate
, 0),
724 SD_BUS_METHOD("Unregister", NULL
, NULL
, bus_home_method_unregister
, SD_BUS_VTABLE_UNPRIVILEGED
),
725 SD_BUS_METHOD("Realize", "s", NULL
, bus_home_method_realize
, SD_BUS_VTABLE_UNPRIVILEGED
|SD_BUS_VTABLE_SENSITIVE
),
726 SD_BUS_METHOD("Remove", NULL
, NULL
, bus_home_method_remove
, SD_BUS_VTABLE_UNPRIVILEGED
),
727 SD_BUS_METHOD("Fixate", "s", NULL
, bus_home_method_fixate
, SD_BUS_VTABLE_SENSITIVE
),
728 SD_BUS_METHOD("Authenticate", "s", NULL
, bus_home_method_authenticate
, SD_BUS_VTABLE_UNPRIVILEGED
|SD_BUS_VTABLE_SENSITIVE
),
729 SD_BUS_METHOD("Update", "s", NULL
, bus_home_method_update
, SD_BUS_VTABLE_UNPRIVILEGED
|SD_BUS_VTABLE_SENSITIVE
),
730 SD_BUS_METHOD("Resize", "ts", NULL
, bus_home_method_resize
, SD_BUS_VTABLE_UNPRIVILEGED
|SD_BUS_VTABLE_SENSITIVE
),
731 SD_BUS_METHOD("ChangePassword", "ss", NULL
, bus_home_method_change_password
, SD_BUS_VTABLE_UNPRIVILEGED
|SD_BUS_VTABLE_SENSITIVE
),
732 SD_BUS_METHOD("Lock", NULL
, NULL
, bus_home_method_lock
, 0),
733 SD_BUS_METHOD("Unlock", "s", NULL
, bus_home_method_unlock
, SD_BUS_VTABLE_SENSITIVE
),
734 SD_BUS_METHOD("Acquire", "sb", "h", bus_home_method_acquire
, SD_BUS_VTABLE_SENSITIVE
),
735 SD_BUS_METHOD("Ref", "b", "h", bus_home_method_ref
, 0),
736 SD_BUS_METHOD("Release", NULL
, NULL
, bus_home_method_release
, 0),
740 int bus_home_path(Home
*h
, char **ret
) {
743 return sd_bus_path_encode("/org/freedesktop/home1/home", h
->user_name
, ret
);
746 int bus_home_object_find(
749 const char *interface
,
752 sd_bus_error
*error
) {
754 _cleanup_free_
char *e
= NULL
;
755 Manager
*m
= userdata
;
760 r
= sd_bus_path_decode(path
, "/org/freedesktop/home1/home", &e
);
764 if (parse_uid(e
, &uid
) >= 0)
765 h
= hashmap_get(m
->homes_by_uid
, UID_TO_PTR(uid
));
767 h
= hashmap_get(m
->homes_by_name
, e
);
775 int bus_home_node_enumerator(
780 sd_bus_error
*error
) {
782 _cleanup_strv_free_
char **l
= NULL
;
783 Manager
*m
= userdata
;
791 l
= new0(char*, hashmap_size(m
->homes_by_uid
) + 1);
795 HASHMAP_FOREACH(h
, m
->homes_by_uid
, i
) {
796 r
= bus_home_path(h
, l
+ k
);
801 *nodes
= TAKE_PTR(l
);
805 static int on_deferred_change(sd_event_source
*s
, void *userdata
) {
806 _cleanup_free_
char *path
= NULL
;
812 h
->deferred_change_event_source
= sd_event_source_unref(h
->deferred_change_event_source
);
814 r
= bus_home_path(h
, &path
);
816 log_warning_errno(r
, "Failed to generate home bus path, ignoring: %m");
821 r
= sd_bus_emit_properties_changed_strv(h
->manager
->bus
, path
, "org.freedesktop.home1.Home", NULL
);
823 r
= sd_bus_emit_object_added(h
->manager
->bus
, path
);
825 log_warning_errno(r
, "Failed to send home change event, ignoring: %m");
832 int bus_home_emit_change(Home
*h
) {
837 if (h
->deferred_change_event_source
)
840 if (!h
->manager
->event
)
843 if (IN_SET(sd_event_get_state(h
->manager
->event
), SD_EVENT_FINISHED
, SD_EVENT_EXITING
))
846 r
= sd_event_add_defer(h
->manager
->event
, &h
->deferred_change_event_source
, on_deferred_change
, h
);
848 return log_error_errno(r
, "Failed to allocate deferred change event source: %m");
850 r
= sd_event_source_set_priority(h
->deferred_change_event_source
, SD_EVENT_PRIORITY_IDLE
+5);
852 log_warning_errno(r
, "Failed to tweak priority of event source, ignoring: %m");
854 (void) sd_event_source_set_description(h
->deferred_change_event_source
, "deferred-change-event");
858 int bus_home_emit_remove(Home
*h
) {
859 _cleanup_free_
char *path
= NULL
;
867 r
= bus_home_path(h
, &path
);
871 r
= sd_bus_emit_object_removed(h
->manager
->bus
, path
);
875 h
->announced
= false;