]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/home/homed-home-bus.c
tree-wide: use -EBADF for fd initialization
[thirdparty/systemd.git] / src / home / homed-home-bus.c
CommitLineData
db9ecf05 1/* SPDX-License-Identifier: LGPL-2.1-or-later */
70a5db58
LP
2
3#include <linux/capability.h>
4
5#include "bus-common-errors.h"
6#include "bus-polkit.h"
7#include "fd-util.h"
8#include "homed-bus.h"
9#include "homed-home-bus.h"
10#include "homed-home.h"
11#include "strv.h"
12#include "user-record-util.h"
13#include "user-util.h"
14
15static int property_get_unix_record(
16 sd_bus *bus,
17 const char *path,
18 const char *interface,
19 const char *property,
20 sd_bus_message *reply,
21 void *userdata,
22 sd_bus_error *error) {
23
99534007 24 Home *h = ASSERT_PTR(userdata);
70a5db58
LP
25
26 assert(bus);
27 assert(reply);
70a5db58
LP
28
29 return sd_bus_message_append(
30 reply, "(suusss)",
31 h->user_name,
32 (uint32_t) h->uid,
33 h->record ? (uint32_t) user_record_gid(h->record) : GID_INVALID,
34 h->record ? user_record_real_name(h->record) : NULL,
35 h->record ? user_record_home_directory(h->record) : NULL,
36 h->record ? user_record_shell(h->record) : NULL);
37}
38
39static int property_get_state(
40 sd_bus *bus,
41 const char *path,
42 const char *interface,
43 const char *property,
44 sd_bus_message *reply,
45 void *userdata,
46 sd_bus_error *error) {
47
99534007 48 Home *h = ASSERT_PTR(userdata);
70a5db58
LP
49
50 assert(bus);
51 assert(reply);
70a5db58
LP
52
53 return sd_bus_message_append(reply, "s", home_state_to_string(home_get_state(h)));
54}
55
56int bus_home_client_is_trusted(Home *h, sd_bus_message *message) {
57 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
58 uid_t euid;
59 int r;
60
61 assert(h);
62
63 if (!message)
64 return -EINVAL;
65
66 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
67 if (r < 0)
68 return r;
69
70 r = sd_bus_creds_get_euid(creds, &euid);
71 if (r < 0)
72 return r;
73
74 return euid == 0 || h->uid == euid;
75}
76
77int bus_home_get_record_json(
78 Home *h,
79 sd_bus_message *message,
80 char **ret,
81 bool *ret_incomplete) {
82
83 _cleanup_(user_record_unrefp) UserRecord *augmented = NULL;
84 UserRecordLoadFlags flags;
85 int r, trusted;
86
87 assert(h);
88 assert(ret);
89
90 trusted = bus_home_client_is_trusted(h, message);
91 if (trusted < 0) {
92 log_warning_errno(trusted, "Failed to determine whether client is trusted, assuming untrusted.");
93 trusted = false;
94 }
95
bfc0cc1a 96 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|USER_RECORD_PERMISSIVE;
70a5db58
LP
97 if (trusted)
98 flags |= USER_RECORD_ALLOW_PRIVILEGED;
99 else
100 flags |= USER_RECORD_STRIP_PRIVILEGED;
101
102 r = home_augment_status(h, flags, &augmented);
103 if (r < 0)
104 return r;
105
106 r = json_variant_format(augmented->json, 0, ret);
107 if (r < 0)
108 return r;
109
110 if (ret_incomplete)
111 *ret_incomplete = augmented->incomplete;
112
113 return 0;
114}
115
116static int property_get_user_record(
117 sd_bus *bus,
118 const char *path,
119 const char *interface,
120 const char *property,
121 sd_bus_message *reply,
122 void *userdata,
123 sd_bus_error *error) {
124
125 _cleanup_free_ char *json = NULL;
99534007 126 Home *h = ASSERT_PTR(userdata);
70a5db58
LP
127 bool incomplete;
128 int r;
129
130 assert(bus);
131 assert(reply);
70a5db58
LP
132
133 r = bus_home_get_record_json(h, sd_bus_get_current_message(bus), &json, &incomplete);
134 if (r < 0)
135 return r;
136
137 return sd_bus_message_append(reply, "(sb)", json, incomplete);
138}
139
140int bus_home_method_activate(
141 sd_bus_message *message,
142 void *userdata,
143 sd_bus_error *error) {
144
145 _cleanup_(user_record_unrefp) UserRecord *secret = NULL;
99534007 146 Home *h = ASSERT_PTR(userdata);
70a5db58
LP
147 int r;
148
149 assert(message);
70a5db58
LP
150
151 r = bus_message_read_secret(message, &secret, error);
152 if (r < 0)
153 return r;
154
155 r = home_activate(h, secret, error);
156 if (r < 0)
157 return r;
158
159 assert(r == 0);
160 assert(!h->current_operation);
161
162 /* The operation is now in process, keep track of this message so that we can later reply to it. */
163 r = home_set_current_message(h, message);
164 if (r < 0)
165 return r;
166
167 return 1;
168}
169
170int bus_home_method_deactivate(
171 sd_bus_message *message,
172 void *userdata,
173 sd_bus_error *error) {
174
99534007 175 Home *h = ASSERT_PTR(userdata);
70a5db58
LP
176 int r;
177
178 assert(message);
70a5db58
LP
179
180 r = home_deactivate(h, false, error);
181 if (r < 0)
182 return r;
183
184 assert(r == 0);
185 assert(!h->current_operation);
186
187 r = home_set_current_message(h, message);
188 if (r < 0)
189 return r;
190
191 return 1;
192}
193
194int bus_home_method_unregister(
195 sd_bus_message *message,
196 void *userdata,
197 sd_bus_error *error) {
198
99534007 199 Home *h = ASSERT_PTR(userdata);
70a5db58
LP
200 int r;
201
202 assert(message);
70a5db58
LP
203
204 r = bus_verify_polkit_async(
205 message,
206 CAP_SYS_ADMIN,
207 "org.freedesktop.home1.remove-home",
208 NULL,
209 true,
210 UID_INVALID,
211 &h->manager->polkit_registry,
212 error);
213 if (r < 0)
214 return r;
215 if (r == 0)
216 return 1; /* Will call us back */
217
218 r = home_unregister(h, error);
219 if (r < 0)
220 return r;
221
222 assert(r > 0);
223
224 /* Note that home_unregister() destroyed 'h' here, so no more accesses */
225
226 return sd_bus_reply_method_return(message, NULL);
227}
228
229int bus_home_method_realize(
230 sd_bus_message *message,
231 void *userdata,
232 sd_bus_error *error) {
233
234 _cleanup_(user_record_unrefp) UserRecord *secret = NULL;
99534007 235 Home *h = ASSERT_PTR(userdata);
70a5db58
LP
236 int r;
237
238 assert(message);
70a5db58
LP
239
240 r = bus_message_read_secret(message, &secret, error);
241 if (r < 0)
242 return r;
243
244 r = bus_verify_polkit_async(
245 message,
246 CAP_SYS_ADMIN,
247 "org.freedesktop.home1.create-home",
248 NULL,
249 true,
250 UID_INVALID,
251 &h->manager->polkit_registry,
252 error);
253 if (r < 0)
254 return r;
255 if (r == 0)
256 return 1; /* Will call us back */
257
258 r = home_create(h, secret, error);
259 if (r < 0)
260 return r;
261
262 assert(r == 0);
263 assert(!h->current_operation);
264
265 h->unregister_on_failure = false;
266
267 r = home_set_current_message(h, message);
268 if (r < 0)
269 return r;
270
271 return 1;
272}
273
274int bus_home_method_remove(
275 sd_bus_message *message,
276 void *userdata,
277 sd_bus_error *error) {
278
99534007 279 Home *h = ASSERT_PTR(userdata);
70a5db58
LP
280 int r;
281
282 assert(message);
70a5db58
LP
283
284 r = bus_verify_polkit_async(
285 message,
286 CAP_SYS_ADMIN,
287 "org.freedesktop.home1.remove-home",
288 NULL,
289 true,
290 UID_INVALID,
291 &h->manager->polkit_registry,
292 error);
293 if (r < 0)
294 return r;
295 if (r == 0)
296 return 1; /* Will call us back */
297
298 r = home_remove(h, error);
299 if (r < 0)
300 return r;
301 if (r > 0) /* Done already. Note that home_remove() destroyed 'h' here, so no more accesses */
302 return sd_bus_reply_method_return(message, NULL);
303
304 assert(!h->current_operation);
305
306 r = home_set_current_message(h, message);
307 if (r < 0)
308 return r;
309
310 return 1;
311}
312
313int bus_home_method_fixate(
314 sd_bus_message *message,
315 void *userdata,
316 sd_bus_error *error) {
317
318 _cleanup_(user_record_unrefp) UserRecord *secret = NULL;
99534007 319 Home *h = ASSERT_PTR(userdata);
70a5db58
LP
320 int r;
321
322 assert(message);
70a5db58
LP
323
324 r = bus_message_read_secret(message, &secret, error);
325 if (r < 0)
326 return r;
327
328 r = home_fixate(h, secret, error);
329 if (r < 0)
330 return r;
331
332 assert(r == 0);
333 assert(!h->current_operation);
334
335 r = home_set_current_message(h, message);
336 if (r < 0)
337 return r;
338
339 return 1;
340}
341
342int bus_home_method_authenticate(
343 sd_bus_message *message,
344 void *userdata,
345 sd_bus_error *error) {
346
347 _cleanup_(user_record_unrefp) UserRecord *secret = NULL;
99534007 348 Home *h = ASSERT_PTR(userdata);
70a5db58
LP
349 int r;
350
351 assert(message);
70a5db58
LP
352
353 r = bus_message_read_secret(message, &secret, error);
354 if (r < 0)
355 return r;
356
357 r = bus_verify_polkit_async(
358 message,
359 CAP_SYS_ADMIN,
360 "org.freedesktop.home1.authenticate-home",
361 NULL,
362 true,
363 h->uid,
364 &h->manager->polkit_registry,
365 error);
366 if (r < 0)
367 return r;
368 if (r == 0)
369 return 1; /* Will call us back */
370
371 r = home_authenticate(h, secret, error);
372 if (r < 0)
373 return r;
374
375 assert(r == 0);
376 assert(!h->current_operation);
377
378 r = home_set_current_message(h, message);
379 if (r < 0)
380 return r;
381
382 return 1;
383}
384
385int bus_home_method_update_record(Home *h, sd_bus_message *message, UserRecord *hr, sd_bus_error *error) {
386 int r;
387
388 assert(h);
389 assert(message);
390 assert(hr);
391
392 r = user_record_is_supported(hr, error);
393 if (r < 0)
394 return r;
395
396 r = bus_verify_polkit_async(
397 message,
398 CAP_SYS_ADMIN,
399 "org.freedesktop.home1.update-home",
400 NULL,
401 true,
402 UID_INVALID,
403 &h->manager->polkit_registry,
404 error);
405 if (r < 0)
406 return r;
407 if (r == 0)
408 return 1; /* Will call us back */
409
410 r = home_update(h, hr, error);
411 if (r < 0)
412 return r;
413
414 assert(r == 0);
415 assert(!h->current_operation);
416
417 r = home_set_current_message(h, message);
418 if (r < 0)
419 return r;
420
421 return 1;
422}
423
424int bus_home_method_update(
425 sd_bus_message *message,
426 void *userdata,
427 sd_bus_error *error) {
428
429 _cleanup_(user_record_unrefp) UserRecord *hr = NULL;
99534007 430 Home *h = ASSERT_PTR(userdata);
70a5db58
LP
431 int r;
432
433 assert(message);
70a5db58 434
bfc0cc1a 435 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|USER_RECORD_PERMISSIVE, &hr, error);
70a5db58
LP
436 if (r < 0)
437 return r;
438
439 return bus_home_method_update_record(h, message, hr, error);
440}
441
442int bus_home_method_resize(
443 sd_bus_message *message,
444 void *userdata,
445 sd_bus_error *error) {
446
447 _cleanup_(user_record_unrefp) UserRecord *secret = NULL;
99534007 448 Home *h = ASSERT_PTR(userdata);
70a5db58
LP
449 uint64_t sz;
450 int r;
451
452 assert(message);
70a5db58
LP
453
454 r = sd_bus_message_read(message, "t", &sz);
455 if (r < 0)
456 return r;
457
458 r = bus_message_read_secret(message, &secret, error);
459 if (r < 0)
460 return r;
461
462 r = bus_verify_polkit_async(
463 message,
464 CAP_SYS_ADMIN,
465 "org.freedesktop.home1.resize-home",
466 NULL,
467 true,
468 UID_INVALID,
469 &h->manager->polkit_registry,
470 error);
471 if (r < 0)
472 return r;
473 if (r == 0)
474 return 1; /* Will call us back */
475
d357b80d 476 r = home_resize(h, sz, secret, /* automatic= */ false, error);
70a5db58
LP
477 if (r < 0)
478 return r;
479
480 assert(r == 0);
481 assert(!h->current_operation);
482
483 r = home_set_current_message(h, message);
484 if (r < 0)
485 return r;
486
487 return 1;
488}
489
490int bus_home_method_change_password(
491 sd_bus_message *message,
492 void *userdata,
493 sd_bus_error *error) {
494
495 _cleanup_(user_record_unrefp) UserRecord *new_secret = NULL, *old_secret = NULL;
99534007 496 Home *h = ASSERT_PTR(userdata);
70a5db58
LP
497 int r;
498
499 assert(message);
70a5db58
LP
500
501 r = bus_message_read_secret(message, &new_secret, error);
502 if (r < 0)
503 return r;
504
505 r = bus_message_read_secret(message, &old_secret, error);
506 if (r < 0)
507 return r;
508
509 r = bus_verify_polkit_async(
510 message,
511 CAP_SYS_ADMIN,
512 "org.freedesktop.home1.passwd-home",
513 NULL,
514 true,
515 h->uid,
516 &h->manager->polkit_registry,
517 error);
518 if (r < 0)
519 return r;
520 if (r == 0)
521 return 1; /* Will call us back */
522
523 r = home_passwd(h, new_secret, old_secret, error);
524 if (r < 0)
525 return r;
526
527 assert(r == 0);
528 assert(!h->current_operation);
529
530 r = home_set_current_message(h, message);
531 if (r < 0)
532 return r;
533
534 return 1;
535}
536
537int bus_home_method_lock(
538 sd_bus_message *message,
539 void *userdata,
540 sd_bus_error *error) {
541
99534007 542 Home *h = ASSERT_PTR(userdata);
70a5db58
LP
543 int r;
544
545 assert(message);
70a5db58
LP
546
547 r = home_lock(h, error);
548 if (r < 0)
549 return r;
550 if (r > 0) /* Done */
551 return sd_bus_reply_method_return(message, NULL);
552
553 /* The operation is now in process, keep track of this message so that we can later reply to it. */
554 assert(!h->current_operation);
555
556 r = home_set_current_message(h, message);
557 if (r < 0)
558 return r;
559
560 return 1;
561}
562
563int bus_home_method_unlock(
564 sd_bus_message *message,
565 void *userdata,
566 sd_bus_error *error) {
567
568 _cleanup_(user_record_unrefp) UserRecord *secret = NULL;
99534007 569 Home *h = ASSERT_PTR(userdata);
70a5db58
LP
570 int r;
571
572 assert(message);
70a5db58
LP
573
574 r = bus_message_read_secret(message, &secret, error);
575 if (r < 0)
576 return r;
577
578 r = home_unlock(h, secret, error);
579 if (r < 0)
580 return r;
581
582 assert(r == 0);
583 assert(!h->current_operation);
584
585 /* The operation is now in process, keep track of this message so that we can later reply to it. */
586 r = home_set_current_message(h, message);
587 if (r < 0)
588 return r;
589
590 return 1;
591}
592
593int bus_home_method_acquire(
594 sd_bus_message *message,
595 void *userdata,
596 sd_bus_error *error) {
597
598 _cleanup_(user_record_unrefp) UserRecord *secret = NULL;
599 _cleanup_(operation_unrefp) Operation *o = NULL;
254d1313 600 _cleanup_close_ int fd = -EBADF;
70a5db58 601 int r, please_suspend;
99534007 602 Home *h = ASSERT_PTR(userdata);
70a5db58
LP
603
604 assert(message);
70a5db58
LP
605
606 r = bus_message_read_secret(message, &secret, error);
607 if (r < 0)
608 return r;
609
610 r = sd_bus_message_read(message, "b", &please_suspend);
611 if (r < 0)
612 return r;
613
614 /* This operation might not be something we can executed immediately, hence queue it */
615 fd = home_create_fifo(h, please_suspend);
616 if (fd < 0)
80ace4f2 617 return sd_bus_reply_method_errnof(message, fd, "Failed to allocate FIFO for %s: %m", h->user_name);
70a5db58
LP
618
619 o = operation_new(OPERATION_ACQUIRE, message);
620 if (!o)
621 return -ENOMEM;
622
623 o->secret = TAKE_PTR(secret);
624 o->send_fd = TAKE_FD(fd);
625
626 r = home_schedule_operation(h, o, error);
627 if (r < 0)
628 return r;
629
630 return 1;
631}
632
633int bus_home_method_ref(
634 sd_bus_message *message,
635 void *userdata,
636 sd_bus_error *error) {
637
254d1313 638 _cleanup_close_ int fd = -EBADF;
99534007 639 Home *h = ASSERT_PTR(userdata);
70a5db58
LP
640 HomeState state;
641 int please_suspend, r;
642
643 assert(message);
70a5db58
LP
644
645 r = sd_bus_message_read(message, "b", &please_suspend);
646 if (r < 0)
647 return r;
648
649 state = home_get_state(h);
650 switch (state) {
651 case HOME_ABSENT:
652 return sd_bus_error_setf(error, BUS_ERROR_HOME_ABSENT, "Home %s is currently missing or not plugged in.", h->user_name);
653 case HOME_UNFIXATED:
654 case HOME_INACTIVE:
9be99f81 655 case HOME_DIRTY:
70a5db58
LP
656 return sd_bus_error_setf(error, BUS_ERROR_HOME_NOT_ACTIVE, "Home %s not active.", h->user_name);
657 case HOME_LOCKED:
658 return sd_bus_error_setf(error, BUS_ERROR_HOME_LOCKED, "Home %s is currently locked.", h->user_name);
659 default:
660 if (HOME_STATE_IS_ACTIVE(state))
661 break;
662
663 return sd_bus_error_setf(error, BUS_ERROR_HOME_BUSY, "An operation on home %s is currently being executed.", h->user_name);
664 }
665
666 fd = home_create_fifo(h, please_suspend);
667 if (fd < 0)
80ace4f2 668 return sd_bus_reply_method_errnof(message, fd, "Failed to allocate FIFO for %s: %m", h->user_name);
70a5db58
LP
669
670 return sd_bus_reply_method_return(message, "h", fd);
671}
672
673int bus_home_method_release(
674 sd_bus_message *message,
675 void *userdata,
676 sd_bus_error *error) {
677
678 _cleanup_(operation_unrefp) Operation *o = NULL;
99534007 679 Home *h = ASSERT_PTR(userdata);
70a5db58
LP
680 int r;
681
682 assert(message);
70a5db58
LP
683
684 o = operation_new(OPERATION_RELEASE, message);
685 if (!o)
686 return -ENOMEM;
687
688 r = home_schedule_operation(h, o, error);
689 if (r < 0)
690 return r;
691
692 return 1;
693}
694
695/* We map a uid_t as uint32_t bus property, let's ensure this is safe. */
696assert_cc(sizeof(uid_t) == sizeof(uint32_t));
697
70a5db58
LP
698int bus_home_path(Home *h, char **ret) {
699 assert(ret);
700
701 return sd_bus_path_encode("/org/freedesktop/home1/home", h->user_name, ret);
702}
703
cfd508a9 704static int bus_home_object_find(
70a5db58
LP
705 sd_bus *bus,
706 const char *path,
707 const char *interface,
708 void *userdata,
709 void **found,
710 sd_bus_error *error) {
711
712 _cleanup_free_ char *e = NULL;
713 Manager *m = userdata;
714 uid_t uid;
715 Home *h;
716 int r;
717
718 r = sd_bus_path_decode(path, "/org/freedesktop/home1/home", &e);
719 if (r <= 0)
720 return 0;
721
722 if (parse_uid(e, &uid) >= 0)
723 h = hashmap_get(m->homes_by_uid, UID_TO_PTR(uid));
724 else
725 h = hashmap_get(m->homes_by_name, e);
726 if (!h)
727 return 0;
728
729 *found = h;
730 return 1;
731}
732
cfd508a9 733static int bus_home_node_enumerator(
70a5db58
LP
734 sd_bus *bus,
735 const char *path,
736 void *userdata,
737 char ***nodes,
738 sd_bus_error *error) {
739
740 _cleanup_strv_free_ char **l = NULL;
741 Manager *m = userdata;
742 size_t k = 0;
70a5db58
LP
743 Home *h;
744 int r;
745
746 assert(nodes);
747
748 l = new0(char*, hashmap_size(m->homes_by_uid) + 1);
749 if (!l)
750 return -ENOMEM;
751
90e74a66 752 HASHMAP_FOREACH(h, m->homes_by_uid) {
70a5db58
LP
753 r = bus_home_path(h, l + k);
754 if (r < 0)
755 return r;
52023622
YW
756
757 k++;
70a5db58
LP
758 }
759
760 *nodes = TAKE_PTR(l);
761 return 1;
762}
763
cfd508a9
ZJS
764const sd_bus_vtable home_vtable[] = {
765 SD_BUS_VTABLE_START(0),
766
767 SD_BUS_PROPERTY("UserName", "s",
768 NULL, offsetof(Home, user_name),
769 SD_BUS_VTABLE_PROPERTY_CONST),
770 SD_BUS_PROPERTY("UID", "u",
771 NULL, offsetof(Home, uid),
772 SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
773 SD_BUS_PROPERTY("UnixRecord", "(suusss)",
774 property_get_unix_record, 0,
775 SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
776 SD_BUS_PROPERTY("State", "s",
777 property_get_state, 0,
778 0),
779 SD_BUS_PROPERTY("UserRecord", "(sb)",
780 property_get_user_record, 0,
781 SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION|SD_BUS_VTABLE_SENSITIVE),
782
9a814166
NK
783 SD_BUS_METHOD_WITH_ARGS("Activate",
784 SD_BUS_ARGS("s", secret),
785 SD_BUS_NO_RESULT,
786 bus_home_method_activate,
787 SD_BUS_VTABLE_SENSITIVE),
cfd508a9
ZJS
788 SD_BUS_METHOD("Deactivate", NULL, NULL, bus_home_method_deactivate, 0),
789 SD_BUS_METHOD("Unregister", NULL, NULL, bus_home_method_unregister, SD_BUS_VTABLE_UNPRIVILEGED),
9a814166
NK
790 SD_BUS_METHOD_WITH_ARGS("Realize",
791 SD_BUS_ARGS("s", secret),
792 SD_BUS_NO_RESULT,
793 bus_home_method_realize,
794 SD_BUS_VTABLE_UNPRIVILEGED|SD_BUS_VTABLE_SENSITIVE),
cfd508a9
ZJS
795
796 SD_BUS_METHOD("Remove", NULL, NULL, bus_home_method_remove, SD_BUS_VTABLE_UNPRIVILEGED),
9a814166
NK
797 SD_BUS_METHOD_WITH_ARGS("Fixate",
798 SD_BUS_ARGS("s", secret),
799 SD_BUS_NO_RESULT,
800 bus_home_method_fixate,
801 SD_BUS_VTABLE_SENSITIVE),
802 SD_BUS_METHOD_WITH_ARGS("Authenticate",
803 SD_BUS_ARGS("s", secret),
804 SD_BUS_NO_RESULT,
805 bus_home_method_authenticate,
806 SD_BUS_VTABLE_UNPRIVILEGED|SD_BUS_VTABLE_SENSITIVE),
807 SD_BUS_METHOD_WITH_ARGS("Update",
808 SD_BUS_ARGS("s", user_record),
809 SD_BUS_NO_RESULT,
810 bus_home_method_update,
811 SD_BUS_VTABLE_UNPRIVILEGED|SD_BUS_VTABLE_SENSITIVE),
812 SD_BUS_METHOD_WITH_ARGS("Resize",
813 SD_BUS_ARGS("t", size, "s", secret),
814 SD_BUS_NO_RESULT,
815 bus_home_method_resize,
816 SD_BUS_VTABLE_UNPRIVILEGED|SD_BUS_VTABLE_SENSITIVE),
817 SD_BUS_METHOD_WITH_ARGS("ChangePassword",
818 SD_BUS_ARGS("s", new_secret, "s", old_secret),
819 SD_BUS_NO_RESULT,
820 bus_home_method_change_password,
821 SD_BUS_VTABLE_UNPRIVILEGED|SD_BUS_VTABLE_SENSITIVE),
cfd508a9 822 SD_BUS_METHOD("Lock", NULL, NULL, bus_home_method_lock, 0),
9a814166
NK
823 SD_BUS_METHOD_WITH_ARGS("Unlock",
824 SD_BUS_ARGS("s", secret),
825 SD_BUS_NO_RESULT,
826 bus_home_method_unlock,
827 SD_BUS_VTABLE_SENSITIVE),
828 SD_BUS_METHOD_WITH_ARGS("Acquire",
829 SD_BUS_ARGS("s", secret, "b", please_suspend),
830 SD_BUS_RESULT("h", send_fd),
831 bus_home_method_acquire,
832 SD_BUS_VTABLE_SENSITIVE),
833 SD_BUS_METHOD_WITH_ARGS("Ref",
834 SD_BUS_ARGS("b", please_suspend),
835 SD_BUS_RESULT("h", send_fd),
836 bus_home_method_ref,
837 0),
cfd508a9
ZJS
838 SD_BUS_METHOD("Release", NULL, NULL, bus_home_method_release, 0),
839 SD_BUS_VTABLE_END
840};
841
842const BusObjectImplementation home_object = {
843 "/org/freedesktop/home1/home",
844 "org.freedesktop.home1.Home",
845 .fallback_vtables = BUS_FALLBACK_VTABLES({home_vtable, bus_home_object_find}),
846 .node_enumerator = bus_home_node_enumerator,
847 .manager = true,
848};
849
70a5db58
LP
850static int on_deferred_change(sd_event_source *s, void *userdata) {
851 _cleanup_free_ char *path = NULL;
99534007 852 Home *h = ASSERT_PTR(userdata);
70a5db58
LP
853 int r;
854
cf536638 855 h->deferred_change_event_source = sd_event_source_disable_unref(h->deferred_change_event_source);
70a5db58
LP
856
857 r = bus_home_path(h, &path);
858 if (r < 0) {
859 log_warning_errno(r, "Failed to generate home bus path, ignoring: %m");
860 return 0;
861 }
862
863 if (h->announced)
864 r = sd_bus_emit_properties_changed_strv(h->manager->bus, path, "org.freedesktop.home1.Home", NULL);
865 else
866 r = sd_bus_emit_object_added(h->manager->bus, path);
867 if (r < 0)
868 log_warning_errno(r, "Failed to send home change event, ignoring: %m");
869 else
870 h->announced = true;
871
872 return 0;
873}
874
875int bus_home_emit_change(Home *h) {
876 int r;
877
878 assert(h);
879
880 if (h->deferred_change_event_source)
881 return 1;
882
883 if (!h->manager->event)
884 return 0;
885
886 if (IN_SET(sd_event_get_state(h->manager->event), SD_EVENT_FINISHED, SD_EVENT_EXITING))
887 return 0;
888
889 r = sd_event_add_defer(h->manager->event, &h->deferred_change_event_source, on_deferred_change, h);
890 if (r < 0)
891 return log_error_errno(r, "Failed to allocate deferred change event source: %m");
892
893 r = sd_event_source_set_priority(h->deferred_change_event_source, SD_EVENT_PRIORITY_IDLE+5);
894 if (r < 0)
895 log_warning_errno(r, "Failed to tweak priority of event source, ignoring: %m");
896
897 (void) sd_event_source_set_description(h->deferred_change_event_source, "deferred-change-event");
898 return 1;
899}
900
901int bus_home_emit_remove(Home *h) {
902 _cleanup_free_ char *path = NULL;
903 int r;
904
905 assert(h);
906
907 if (!h->announced)
908 return 0;
909
2ff45772
YW
910 if (!h->manager)
911 return 0;
912
913 if (!h->manager->bus)
914 return 0;
915
70a5db58
LP
916 r = bus_home_path(h, &path);
917 if (r < 0)
918 return r;
919
920 r = sd_bus_emit_object_removed(h->manager->bus, path);
921 if (r < 0)
922 return r;
923
924 h->announced = false;
925 return 1;
926}