]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/home/homed-manager.c
homed: move supported_fstype() to home-util.c
[thirdparty/systemd.git] / src / home / homed-manager.c
CommitLineData
70a5db58
LP
1/* SPDX-License-Identifier: LGPL-2.1+ */
2
3#include <grp.h>
4#include <linux/fs.h>
5#include <linux/magic.h>
6#include <openssl/pem.h>
7#include <pwd.h>
8#include <sys/ioctl.h>
9#include <sys/quota.h>
10#include <sys/stat.h>
11
12#include "btrfs-util.h"
13#include "bus-common-errors.h"
14#include "bus-error.h"
ac9f55ed 15#include "bus-log-control-api.h"
70a5db58
LP
16#include "bus-polkit.h"
17#include "clean-ipc.h"
18#include "conf-files.h"
19#include "device-util.h"
20#include "dirent-util.h"
21#include "fd-util.h"
22#include "fileio.h"
23#include "format-util.h"
24#include "fs-util.h"
25#include "gpt.h"
26#include "home-util.h"
27#include "homed-home-bus.h"
28#include "homed-home.h"
29#include "homed-manager-bus.h"
30#include "homed-manager.h"
31#include "homed-varlink.h"
32#include "io-util.h"
33#include "mkdir.h"
34#include "process-util.h"
35#include "quota-util.h"
36#include "random-util.h"
37#include "socket-util.h"
38#include "stat-util.h"
39#include "strv.h"
40#include "tmpfile-util.h"
41#include "udev-util.h"
42#include "user-record-sign.h"
43#include "user-record-util.h"
44#include "user-record.h"
45#include "user-util.h"
46
47/* Where to look for private/public keys that are used to sign the user records. We are not using
48 * CONF_PATHS_NULSTR() here since we want to insert /var/lib/systemd/home/ in the middle. And we insert that
49 * since we want to auto-generate a persistent private/public key pair if we need to. */
50#define KEY_PATHS_NULSTR \
51 "/etc/systemd/home/\0" \
52 "/run/systemd/home/\0" \
53 "/var/lib/systemd/home/\0" \
54 "/usr/local/lib/systemd/home/\0" \
55 "/usr/lib/systemd/home/\0"
56
57static bool uid_is_home(uid_t uid) {
58 return uid >= HOME_UID_MIN && uid <= HOME_UID_MAX;
59}
60/* Takes a value generated randomly or by hashing and turns it into a UID in the right range */
61
62#define UID_CLAMP_INTO_HOME_RANGE(rnd) (((uid_t) (rnd) % (HOME_UID_MAX - HOME_UID_MIN + 1)) + HOME_UID_MIN)
63
64DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(homes_by_uid_hash_ops, void, trivial_hash_func, trivial_compare_func, Home, home_free);
65DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(homes_by_name_hash_ops, char, string_hash_func, string_compare_func, Home, home_free);
66DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(homes_by_worker_pid_hash_ops, void, trivial_hash_func, trivial_compare_func, Home, home_free);
67DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(homes_by_sysfs_hash_ops, char, path_hash_func, path_compare, Home, home_free);
68
69static int on_home_inotify(sd_event_source *s, const struct inotify_event *event, void *userdata);
70static int manager_gc_images(Manager *m);
71static int manager_enumerate_images(Manager *m);
72static int manager_assess_image(Manager *m, int dir_fd, const char *dir_path, const char *dentry_name);
73static void manager_revalidate_image(Manager *m, Home *h);
74
75static void manager_watch_home(Manager *m) {
76 struct statfs sfs;
77 int r;
78
79 assert(m);
80
81 m->inotify_event_source = sd_event_source_unref(m->inotify_event_source);
82 m->scan_slash_home = false;
83
84 if (statfs("/home/", &sfs) < 0) {
85 log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_WARNING, errno,
86 "Failed to statfs() /home/ directory, disabling automatic scanning.");
87 return;
88 }
89
90 if (is_network_fs(&sfs)) {
91 log_info("/home/ is a network file system, disabling automatic scanning.");
92 return;
93 }
94
95 if (is_fs_type(&sfs, AUTOFS_SUPER_MAGIC)) {
96 log_info("/home/ is on autofs, disabling automatic scanning.");
97 return;
98 }
99
100 m->scan_slash_home = true;
101
102 r = sd_event_add_inotify(m->event, &m->inotify_event_source, "/home/", IN_CREATE|IN_CLOSE_WRITE|IN_DELETE_SELF|IN_MOVE_SELF|IN_ONLYDIR|IN_MOVED_TO|IN_MOVED_FROM|IN_DELETE, on_home_inotify, m);
103 if (r < 0)
104 log_full_errno(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, r,
105 "Failed to create inotify watch on /home/, ignoring.");
106
107 (void) sd_event_source_set_description(m->inotify_event_source, "home-inotify");
108}
109
110static int on_home_inotify(sd_event_source *s, const struct inotify_event *event, void *userdata) {
111 Manager *m = userdata;
112 const char *e, *n;
113
114 assert(m);
115 assert(event);
116
117 if ((event->mask & (IN_Q_OVERFLOW|IN_MOVE_SELF|IN_DELETE_SELF|IN_IGNORED|IN_UNMOUNT)) != 0) {
118
119 if (FLAGS_SET(event->mask, IN_Q_OVERFLOW))
120 log_debug("/home/ inotify queue overflow, rescanning.");
121 else if (FLAGS_SET(event->mask, IN_MOVE_SELF))
122 log_info("/home/ moved or renamed, recreating watch and rescanning.");
123 else if (FLAGS_SET(event->mask, IN_DELETE_SELF))
124 log_info("/home/ deleted, recreating watch and rescanning.");
125 else if (FLAGS_SET(event->mask, IN_UNMOUNT))
126 log_info("/home/ unmounted, recreating watch and rescanning.");
127 else if (FLAGS_SET(event->mask, IN_IGNORED))
128 log_info("/home/ watch invalidated, recreating watch and rescanning.");
129
130 manager_watch_home(m);
131 (void) manager_gc_images(m);
132 (void) manager_enumerate_images(m);
133 (void) bus_manager_emit_auto_login_changed(m);
134 return 0;
135 }
136
137 /* For the other inotify events, let's ignore all events for file names that don't match our
138 * expectations */
139 if (isempty(event->name))
140 return 0;
141 e = endswith(event->name, FLAGS_SET(event->mask, IN_ISDIR) ? ".homedir" : ".home");
142 if (!e)
143 return 0;
144
145 n = strndupa(event->name, e - event->name);
146 if (!suitable_user_name(n))
147 return 0;
148
149 if ((event->mask & (IN_CREATE|IN_CLOSE_WRITE|IN_MOVED_TO)) != 0) {
150 if (FLAGS_SET(event->mask, IN_CREATE))
151 log_debug("/home/%s has been created, having a look.", event->name);
152 else if (FLAGS_SET(event->mask, IN_CLOSE_WRITE))
153 log_debug("/home/%s has been modified, having a look.", event->name);
154 else if (FLAGS_SET(event->mask, IN_MOVED_TO))
155 log_debug("/home/%s has been moved in, having a look.", event->name);
156
157 (void) manager_assess_image(m, -1, "/home/", event->name);
158 (void) bus_manager_emit_auto_login_changed(m);
159 }
160
161 if ((event->mask & (IN_DELETE|IN_MOVED_FROM|IN_DELETE)) != 0) {
162 Home *h;
163
164 if (FLAGS_SET(event->mask, IN_DELETE))
165 log_debug("/home/%s has been deleted, revalidating.", event->name);
166 else if (FLAGS_SET(event->mask, IN_CLOSE_WRITE))
167 log_debug("/home/%s has been closed after writing, revalidating.", event->name);
168 else if (FLAGS_SET(event->mask, IN_MOVED_FROM))
169 log_debug("/home/%s has been moved away, revalidating.", event->name);
170
171 h = hashmap_get(m->homes_by_name, n);
172 if (h) {
173 manager_revalidate_image(m, h);
174 (void) bus_manager_emit_auto_login_changed(m);
175 }
176 }
177
178 return 0;
179}
180
181int manager_new(Manager **ret) {
182 _cleanup_(manager_freep) Manager *m = NULL;
183 int r;
184
185 assert(ret);
186
187 m = new0(Manager, 1);
188 if (!m)
189 return -ENOMEM;
190
191 r = sd_event_default(&m->event);
192 if (r < 0)
193 return r;
194
195 r = sd_event_add_signal(m->event, NULL, SIGINT, NULL, NULL);
196 if (r < 0)
197 return r;
198
199 r = sd_event_add_signal(m->event, NULL, SIGTERM, NULL, NULL);
200 if (r < 0)
201 return r;
202
203 (void) sd_event_set_watchdog(m->event, true);
204
205 m->homes_by_uid = hashmap_new(&homes_by_uid_hash_ops);
206 if (!m->homes_by_uid)
207 return -ENOMEM;
208
209 m->homes_by_name = hashmap_new(&homes_by_name_hash_ops);
210 if (!m->homes_by_name)
211 return -ENOMEM;
212
213 m->homes_by_worker_pid = hashmap_new(&homes_by_worker_pid_hash_ops);
214 if (!m->homes_by_worker_pid)
215 return -ENOMEM;
216
217 m->homes_by_sysfs = hashmap_new(&homes_by_sysfs_hash_ops);
218 if (!m->homes_by_sysfs)
219 return -ENOMEM;
220
221 *ret = TAKE_PTR(m);
222 return 0;
223}
224
225Manager* manager_free(Manager *m) {
226 assert(m);
227
228 hashmap_free(m->homes_by_uid);
229 hashmap_free(m->homes_by_name);
230 hashmap_free(m->homes_by_worker_pid);
231 hashmap_free(m->homes_by_sysfs);
232
233 m->inotify_event_source = sd_event_source_unref(m->inotify_event_source);
234
235 bus_verify_polkit_async_registry_free(m->polkit_registry);
236
237 sd_bus_flush_close_unref(m->bus);
238 sd_event_unref(m->event);
239
240 m->notify_socket_event_source = sd_event_source_unref(m->notify_socket_event_source);
241 m->device_monitor = sd_device_monitor_unref(m->device_monitor);
242
243 m->deferred_rescan_event_source = sd_event_source_unref(m->deferred_rescan_event_source);
244 m->deferred_gc_event_source = sd_event_source_unref(m->deferred_gc_event_source);
245 m->deferred_auto_login_event_source = sd_event_source_unref(m->deferred_auto_login_event_source);
246
247 if (m->private_key)
248 EVP_PKEY_free(m->private_key);
249
250 hashmap_free(m->public_keys);
251
252 varlink_server_unref(m->varlink_server);
253
254 return mfree(m);
255}
256
257int manager_verify_user_record(Manager *m, UserRecord *hr) {
258 EVP_PKEY *pkey;
259 Iterator i;
260 int r;
261
262 assert(m);
263 assert(hr);
264
265 if (!m->private_key && hashmap_isempty(m->public_keys)) {
266 r = user_record_has_signature(hr);
267 if (r < 0)
268 return r;
269
270 return r ? -ENOKEY : USER_RECORD_UNSIGNED;
271 }
272
273 /* Is it our own? */
274 if (m->private_key) {
275 r = user_record_verify(hr, m->private_key);
276 switch (r) {
277
278 case USER_RECORD_FOREIGN:
279 /* This record is not signed by this key, but let's see below */
280 break;
281
282 case USER_RECORD_SIGNED: /* Signed by us, but also by others, let's propagate that */
283 case USER_RECORD_SIGNED_EXCLUSIVE: /* Signed by us, and nothing else, ditto */
284 case USER_RECORD_UNSIGNED: /* Not signed at all, ditto */
285 default:
286 return r;
287 }
288 }
289
290 HASHMAP_FOREACH(pkey, m->public_keys, i) {
291 r = user_record_verify(hr, pkey);
292 switch (r) {
293
294 case USER_RECORD_FOREIGN:
295 /* This record is not signed by this key, but let's see our other keys */
296 break;
297
298 case USER_RECORD_SIGNED: /* It's signed by this key we are happy with, but which is not our own. */
299 case USER_RECORD_SIGNED_EXCLUSIVE:
300 return USER_RECORD_FOREIGN;
301
302 case USER_RECORD_UNSIGNED: /* It's not signed at all */
303 default:
304 return r;
305 }
306 }
307
308 return -ENOKEY;
309}
310
311static int manager_add_home_by_record(
312 Manager *m,
313 const char *name,
314 int dir_fd,
315 const char *fname) {
316
317 _cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
852640f8 318 _cleanup_(user_record_unrefp) UserRecord *hr = NULL;
70a5db58
LP
319 unsigned line, column;
320 int r, is_signed;
321 Home *h;
322
323 assert(m);
324 assert(name);
325 assert(fname);
326
327 r = json_parse_file_at(NULL, dir_fd, fname, JSON_PARSE_SENSITIVE, &v, &line, &column);
328 if (r < 0)
329 return log_error_errno(r, "Failed to parse identity record at %s:%u%u: %m", fname, line, column);
330
331 hr = user_record_new();
332 if (!hr)
333 return log_oom();
334
335 r = user_record_load(hr, v, USER_RECORD_LOAD_REFUSE_SECRET);
336 if (r < 0)
337 return r;
338
339 if (!streq_ptr(hr->user_name, name))
340 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Identity's user name %s does not match file name %s, refusing.", hr->user_name, name);
341
342 is_signed = manager_verify_user_record(m, hr);
343 switch (is_signed) {
344
345 case -ENOKEY:
346 return log_warning_errno(is_signed, "User record %s is not signed by any accepted key, ignoring.", fname);
347 case USER_RECORD_UNSIGNED:
348 return log_warning_errno(SYNTHETIC_ERRNO(EPERM), "User record %s is not signed at all, ignoring.", fname);
349 case USER_RECORD_SIGNED:
350 log_info("User record %s is signed by us (and others), accepting.", fname);
351 break;
352 case USER_RECORD_SIGNED_EXCLUSIVE:
353 log_info("User record %s is signed only by us, accepting.", fname);
354 break;
355 case USER_RECORD_FOREIGN:
356 log_info("User record %s is signed by registered key from others, accepting.", fname);
357 break;
358 default:
359 assert(is_signed < 0);
360 return log_error_errno(is_signed, "Failed to verify signature of user record in %s: %m", fname);
361 }
362
363 h = hashmap_get(m->homes_by_name, name);
364 if (h) {
365 r = home_set_record(h, hr);
366 if (r < 0)
367 return log_error_errno(r, "Failed to update home record for %s: %m", name);
368
369 /* If we acquired a record now for a previously unallocated entry, then reset the state. This
370 * makes sure home_get_state() will check for the availability of the image file dynamically
162392b7 371 * in order to detect to distinguish HOME_INACTIVE and HOME_ABSENT. */
70a5db58
LP
372 if (h->state == HOME_UNFIXATED)
373 h->state = _HOME_STATE_INVALID;
374 } else {
375 r = home_new(m, hr, NULL, &h);
376 if (r < 0)
377 return log_error_errno(r, "Failed to allocate new home object: %m");
378
379 log_info("Added registered home for user %s.", hr->user_name);
380 }
381
382 /* Only entries we exclusively signed are writable to us, hence remember the result */
383 h->signed_locally = is_signed == USER_RECORD_SIGNED_EXCLUSIVE;
384
385 return 1;
386}
387
388static int manager_enumerate_records(Manager *m) {
389 _cleanup_closedir_ DIR *d = NULL;
390 struct dirent *de;
391
392 assert(m);
393
394 d = opendir("/var/lib/systemd/home/");
395 if (!d)
396 return log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_ERR, errno,
397 "Failed to open /var/lib/systemd/home/: %m");
398
399 FOREACH_DIRENT(de, d, return log_error_errno(errno, "Failed to read record directory: %m")) {
400 _cleanup_free_ char *n = NULL;
401 const char *e;
402
403 if (!dirent_is_file(de))
404 continue;
405
406 e = endswith(de->d_name, ".identity");
407 if (!e)
408 continue;
409
410 n = strndup(de->d_name, e - de->d_name);
411 if (!n)
412 return log_oom();
413
414 if (!suitable_user_name(n))
415 continue;
416
417 (void) manager_add_home_by_record(m, n, dirfd(d), de->d_name);
418 }
419
420 return 0;
421}
422
423static int search_quota(uid_t uid, const char *exclude_quota_path) {
424 struct stat exclude_st = {};
425 dev_t previous_devno = 0;
426 const char *where;
427 int r;
428
429 /* Checks whether the specified UID owns any files on the files system, but ignore any file system
430 * backing the specified file. The file is used when operating on home directories, where it's OK if
431 * the UID of them already owns files. */
432
433 if (exclude_quota_path && stat(exclude_quota_path, &exclude_st) < 0) {
434 if (errno != ENOENT)
435 return log_warning_errno(errno, "Failed to stat %s, ignoring: %m", exclude_quota_path);
436 }
437
438 /* Check a few usual suspects where regular users might own files. Note that this is by no means
439 * comprehensive, but should cover most cases. Note that in an ideal world every user would be
440 * registered in NSS and avoid our own UID range, but for all other cases, it's a good idea to be
441 * paranoid and check quota if we can. */
442 FOREACH_STRING(where, "/home/", "/tmp/", "/var/", "/var/mail/", "/var/tmp/", "/var/spool/") {
443 struct dqblk req;
444 struct stat st;
445
446 if (stat(where, &st) < 0) {
447 log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_ERR, errno,
448 "Failed to stat %s, ignoring: %m", where);
449 continue;
450 }
451
452 if (major(st.st_dev) == 0) {
453 log_debug("Directory %s is not on a real block device, not checking quota for UID use.", where);
454 continue;
455 }
456
457 if (st.st_dev == exclude_st.st_dev) { /* If an exclude path is specified, then ignore quota
458 * reported on the same block device as that path. */
459 log_debug("Directory %s is where the home directory is located, not checking quota for UID use.", where);
460 continue;
461 }
462
463 if (st.st_dev == previous_devno) { /* Does this directory have the same devno as the previous
464 * one we tested? If so, there's no point in testing this
465 * again. */
466 log_debug("Directory %s is on same device as previous tested directory, not checking quota for UID use a second time.", where);
467 continue;
468 }
469
470 previous_devno = st.st_dev;
471
472 r = quotactl_devno(QCMD_FIXED(Q_GETQUOTA, USRQUOTA), st.st_dev, uid, &req);
473 if (r < 0) {
474 if (ERRNO_IS_NOT_SUPPORTED(r))
475 log_debug_errno(r, "No UID quota support on %s, ignoring.", where);
476 else
477 log_warning_errno(r, "Failed to query quota on %s, ignoring.", where);
478
479 continue;
480 }
481
482 if ((FLAGS_SET(req.dqb_valid, QIF_SPACE) && req.dqb_curspace > 0) ||
483 (FLAGS_SET(req.dqb_valid, QIF_INODES) && req.dqb_curinodes > 0)) {
484 log_debug_errno(errno, "Quota reports UID " UID_FMT " occupies disk space on %s.", uid, where);
485 return 1;
486 }
487 }
488
489 return 0;
490}
491
492static int manager_acquire_uid(
493 Manager *m,
494 uid_t start_uid,
495 const char *user_name,
496 const char *exclude_quota_path,
497 uid_t *ret) {
498
499 static const uint8_t hash_key[] = {
500 0xa3, 0xb8, 0x82, 0x69, 0x9a, 0x71, 0xf7, 0xa9,
501 0xe0, 0x7c, 0xf6, 0xf1, 0x21, 0x69, 0xd2, 0x1e
502 };
503
504 enum {
505 PHASE_SUGGESTED,
506 PHASE_HASHED,
507 PHASE_RANDOM
508 } phase = PHASE_SUGGESTED;
509
510 unsigned n_tries = 100;
511 int r;
512
513 assert(m);
514 assert(ret);
515
516 for (;;) {
517 struct passwd *pw;
518 struct group *gr;
519 uid_t candidate;
520 Home *other;
521
522 if (--n_tries <= 0)
523 return -EBUSY;
524
525 switch (phase) {
526
527 case PHASE_SUGGESTED:
528 phase = PHASE_HASHED;
529
530 if (!uid_is_home(start_uid))
531 continue;
532
533 candidate = start_uid;
534 break;
535
536 case PHASE_HASHED:
537 phase = PHASE_RANDOM;
538
539 if (!user_name)
540 continue;
541
542 candidate = UID_CLAMP_INTO_HOME_RANGE(siphash24(user_name, strlen(user_name), hash_key));
543 break;
544
545 case PHASE_RANDOM:
546 random_bytes(&candidate, sizeof(candidate));
547 candidate = UID_CLAMP_INTO_HOME_RANGE(candidate);
548 break;
549
550 default:
551 assert_not_reached("unknown phase");
552 }
553
554 other = hashmap_get(m->homes_by_uid, UID_TO_PTR(candidate));
555 if (other) {
556 log_debug("Candidate UID " UID_FMT " already used by another home directory (%s), let's try another.", candidate, other->user_name);
557 continue;
558 }
559
560 pw = getpwuid(candidate);
561 if (pw) {
562 log_debug("Candidate UID " UID_FMT " already registered by another user in NSS (%s), let's try another.", candidate, pw->pw_name);
563 continue;
564 }
565
566 gr = getgrgid((gid_t) candidate);
567 if (gr) {
568 log_debug("Candidate UID " UID_FMT " already registered by another group in NSS (%s), let's try another.", candidate, gr->gr_name);
569 continue;
570 }
571
572 r = search_ipc(candidate, (gid_t) candidate);
573 if (r < 0)
574 continue;
575 if (r > 0) {
576 log_debug_errno(r, "Candidate UID " UID_FMT " already owns IPC objects, let's try another: %m", candidate);
577 continue;
578 }
579
580 r = search_quota(candidate, exclude_quota_path);
581 if (r != 0)
582 continue;
583
584 *ret = candidate;
585 return 0;
586 }
587}
588
589static int manager_add_home_by_image(
590 Manager *m,
591 const char *user_name,
592 const char *realm,
593 const char *image_path,
594 const char *sysfs,
595 UserStorage storage,
596 uid_t start_uid) {
597
598 _cleanup_(user_record_unrefp) UserRecord *hr = NULL;
599 uid_t uid;
600 Home *h;
601 int r;
602
603 assert(m);
604
605 assert(m);
606 assert(user_name);
607 assert(image_path);
608 assert(storage >= 0);
609 assert(storage < _USER_STORAGE_MAX);
610
611 h = hashmap_get(m->homes_by_name, user_name);
612 if (h) {
613 bool same;
614
615 if (h->state != HOME_UNFIXATED) {
616 log_debug("Found an image for user %s which already has a record, skipping.", user_name);
617 return 0; /* ignore images that synthesize a user we already have a record for */
618 }
619
620 same = user_record_storage(h->record) == storage;
621 if (same) {
622 if (h->sysfs && sysfs)
623 same = path_equal(h->sysfs, sysfs);
624 else if (!!h->sysfs != !!sysfs)
625 same = false;
626 else {
627 const char *p;
628
629 p = user_record_image_path(h->record);
630 same = p && path_equal(p, image_path);
631 }
632 }
633
634 if (!same) {
80ace4f2 635 log_debug("Found multiple images for user '%s', ignoring image '%s'.", user_name, image_path);
70a5db58
LP
636 return 0;
637 }
638 } else {
639 /* Check NSS, in case there's another user or group by this name */
640 if (getpwnam(user_name) || getgrnam(user_name)) {
641 log_debug("Found an existing user or group by name '%s', ignoring image '%s'.", user_name, image_path);
642 return 0;
643 }
644 }
645
646 if (h && uid_is_valid(h->uid))
647 uid = h->uid;
648 else {
649 r = manager_acquire_uid(m, start_uid, user_name, IN_SET(storage, USER_SUBVOLUME, USER_DIRECTORY, USER_FSCRYPT) ? image_path : NULL, &uid);
650 if (r < 0)
651 return log_warning_errno(r, "Failed to acquire unused UID for %s: %m", user_name);
652 }
653
654 hr = user_record_new();
655 if (!hr)
656 return log_oom();
657
658 r = user_record_synthesize(hr, user_name, realm, image_path, storage, uid, (gid_t) uid);
659 if (r < 0)
660 return log_error_errno(r, "Failed to synthesize home record for %s (image %s): %m", user_name, image_path);
661
662 if (h) {
663 r = home_set_record(h, hr);
664 if (r < 0)
665 return log_error_errno(r, "Failed to update home record for %s: %m", user_name);
666 } else {
667 r = home_new(m, hr, sysfs, &h);
668 if (r < 0)
669 return log_error_errno(r, "Failed to allocate new home object: %m");
670
671 h->state = HOME_UNFIXATED;
672
673 log_info("Discovered new home for user %s through image %s.", user_name, image_path);
674 }
675
676 return 1;
677}
678
679int manager_augment_record_with_uid(
680 Manager *m,
681 UserRecord *hr) {
682
683 const char *exclude_quota_path = NULL;
684 uid_t start_uid = UID_INVALID, uid;
685 int r;
686
687 assert(m);
688 assert(hr);
689
690 if (uid_is_valid(hr->uid))
691 return 0;
692
693 if (IN_SET(hr->storage, USER_CLASSIC, USER_SUBVOLUME, USER_DIRECTORY, USER_FSCRYPT)) {
694 const char * ip;
695
696 ip = user_record_image_path(hr);
697 if (ip) {
698 struct stat st;
699
700 if (stat(ip, &st) < 0) {
701 if (errno != ENOENT)
702 log_warning_errno(errno, "Failed to stat(%s): %m", ip);
703 } else if (uid_is_home(st.st_uid)) {
704 start_uid = st.st_uid;
705 exclude_quota_path = ip;
706 }
707 }
708 }
709
710 r = manager_acquire_uid(m, start_uid, hr->user_name, exclude_quota_path, &uid);
711 if (r < 0)
712 return r;
713
714 log_debug("Acquired new UID " UID_FMT " for %s.", uid, hr->user_name);
715
716 r = user_record_add_binding(
717 hr,
718 _USER_STORAGE_INVALID,
719 NULL,
720 SD_ID128_NULL,
721 SD_ID128_NULL,
722 SD_ID128_NULL,
723 NULL,
724 NULL,
725 UINT64_MAX,
726 NULL,
727 NULL,
728 uid,
729 (gid_t) uid);
730 if (r < 0)
731 return r;
732
733 return 1;
734}
735
736static int manager_assess_image(
737 Manager *m,
738 int dir_fd,
739 const char *dir_path,
740 const char *dentry_name) {
741
742 char *luks_suffix, *directory_suffix;
743 _cleanup_free_ char *path = NULL;
744 struct stat st;
745 int r;
746
747 assert(m);
748 assert(dir_path);
749 assert(dentry_name);
750
751 luks_suffix = endswith(dentry_name, ".home");
752 if (luks_suffix)
753 directory_suffix = NULL;
754 else
755 directory_suffix = endswith(dentry_name, ".homedir");
756
757 /* Early filter out: by name */
758 if (!luks_suffix && !directory_suffix)
759 return 0;
760
761 path = path_join(dir_path, dentry_name);
762 if (!path)
763 return log_oom();
764
765 /* Follow symlinks here, to allow people to link in stuff to make them available locally. */
766 if (dir_fd >= 0)
767 r = fstatat(dir_fd, dentry_name, &st, 0);
768 else
769 r = stat(path, &st);
770 if (r < 0)
771 return log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_WARNING, errno,
80ace4f2 772 "Failed to stat() directory entry '%s', ignoring: %m", dentry_name);
70a5db58
LP
773
774 if (S_ISREG(st.st_mode)) {
775 _cleanup_free_ char *n = NULL, *user_name = NULL, *realm = NULL;
776
777 if (!luks_suffix)
778 return 0;
779
780 n = strndup(dentry_name, luks_suffix - dentry_name);
781 if (!n)
782 return log_oom();
783
784 r = split_user_name_realm(n, &user_name, &realm);
785 if (r == -EINVAL) /* Not the right format: ignore */
786 return 0;
787 if (r < 0)
788 return log_error_errno(r, "Failed to split image name into user name/realm: %m");
789
790 return manager_add_home_by_image(m, user_name, realm, path, NULL, USER_LUKS, UID_INVALID);
791 }
792
793 if (S_ISDIR(st.st_mode)) {
794 _cleanup_free_ char *n = NULL, *user_name = NULL, *realm = NULL;
795 _cleanup_close_ int fd = -1;
796 UserStorage storage;
797
798 if (!directory_suffix)
799 return 0;
800
801 n = strndup(dentry_name, directory_suffix - dentry_name);
802 if (!n)
803 return log_oom();
804
805 r = split_user_name_realm(n, &user_name, &realm);
806 if (r == -EINVAL) /* Not the right format: ignore */
807 return 0;
808 if (r < 0)
809 return log_error_errno(r, "Failed to split image name into user name/realm: %m");
810
811 if (dir_fd >= 0)
812 fd = openat(dir_fd, dentry_name, O_DIRECTORY|O_RDONLY|O_CLOEXEC);
813 else
814 fd = open(path, O_DIRECTORY|O_RDONLY|O_CLOEXEC);
815 if (fd < 0)
816 return log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_WARNING, errno,
817 "Failed to open directory '%s', ignoring: %m", path);
818
819 if (fstat(fd, &st) < 0)
820 return log_warning_errno(errno, "Failed to fstat() %s, ignoring: %m", path);
821
822 assert(S_ISDIR(st.st_mode)); /* Must hold, we used O_DIRECTORY above */
823
824 r = btrfs_is_subvol_fd(fd);
825 if (r < 0)
826 return log_warning_errno(errno, "Failed to determine whether %s is a btrfs subvolume: %m", path);
827 if (r > 0)
828 storage = USER_SUBVOLUME;
829 else {
830 struct fscrypt_policy policy;
831
832 if (ioctl(fd, FS_IOC_GET_ENCRYPTION_POLICY, &policy) < 0) {
833
834 if (errno == ENODATA)
835 log_debug_errno(errno, "Determined %s is not fscrypt encrypted.", path);
836 else if (ERRNO_IS_NOT_SUPPORTED(errno))
80ace4f2 837 log_debug_errno(errno, "Determined %s is not fscrypt encrypted because kernel or file system doesn't support it.", path);
70a5db58
LP
838 else
839 log_debug_errno(errno, "FS_IOC_GET_ENCRYPTION_POLICY failed with unexpected error code on %s, ignoring: %m", path);
840
841 storage = USER_DIRECTORY;
842 } else
843 storage = USER_FSCRYPT;
844 }
845
846 return manager_add_home_by_image(m, user_name, realm, path, NULL, storage, st.st_uid);
847 }
848
849 return 0;
850}
851
852int manager_enumerate_images(Manager *m) {
853 _cleanup_closedir_ DIR *d = NULL;
854 struct dirent *de;
855
856 assert(m);
857
858 if (!m->scan_slash_home)
859 return 0;
860
861 d = opendir("/home/");
862 if (!d)
863 return log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_ERR, errno,
864 "Failed to open /home/: %m");
865
866 FOREACH_DIRENT(de, d, return log_error_errno(errno, "Failed to read /home/ directory: %m"))
867 (void) manager_assess_image(m, dirfd(d), "/home", de->d_name);
868
869 return 0;
870}
871
872static int manager_connect_bus(Manager *m) {
873 int r;
874
875 assert(m);
876 assert(!m->bus);
877
878 r = sd_bus_default_system(&m->bus);
879 if (r < 0)
880 return log_error_errno(r, "Failed to connect to system bus: %m");
881
cfd508a9 882 r = bus_add_implementation(m->bus, &manager_object, m);
ac9f55ed
LP
883 if (r < 0)
884 return r;
885
70a5db58
LP
886 r = sd_bus_request_name_async(m->bus, NULL, "org.freedesktop.home1", 0, NULL, NULL);
887 if (r < 0)
888 return log_error_errno(r, "Failed to request name: %m");
889
890 r = sd_bus_attach_event(m->bus, m->event, 0);
891 if (r < 0)
892 return log_error_errno(r, "Failed to attach bus to event loop: %m");
893
894 (void) sd_bus_set_exit_on_disconnect(m->bus, true);
895
896 return 0;
897}
898
899static int manager_bind_varlink(Manager *m) {
900 int r;
901
902 assert(m);
903 assert(!m->varlink_server);
904
905 r = varlink_server_new(&m->varlink_server, VARLINK_SERVER_ACCOUNT_UID);
906 if (r < 0)
907 return log_error_errno(r, "Failed to allocate varlink server object: %m");
908
909 varlink_server_set_userdata(m->varlink_server, m);
910
911 r = varlink_server_bind_method_many(
912 m->varlink_server,
913 "io.systemd.UserDatabase.GetUserRecord", vl_method_get_user_record,
914 "io.systemd.UserDatabase.GetGroupRecord", vl_method_get_group_record,
915 "io.systemd.UserDatabase.GetMemberships", vl_method_get_memberships);
916 if (r < 0)
917 return log_error_errno(r, "Failed to register varlink methods: %m");
918
919 (void) mkdir_p("/run/systemd/userdb", 0755);
920
921 r = varlink_server_listen_address(m->varlink_server, "/run/systemd/userdb/io.systemd.Home", 0666);
922 if (r < 0)
923 return log_error_errno(r, "Failed to bind to varlink socket: %m");
924
925 r = varlink_server_attach_event(m->varlink_server, m->event, SD_EVENT_PRIORITY_NORMAL);
926 if (r < 0)
927 return log_error_errno(r, "Failed to attach varlink connection to event loop: %m");
928
929 return 0;
930}
931
932static ssize_t read_datagram(int fd, struct ucred *ret_sender, void **ret) {
933 _cleanup_free_ void *buffer = NULL;
934 ssize_t n, m;
935
936 assert(fd >= 0);
937 assert(ret_sender);
938 assert(ret);
939
940 n = next_datagram_size_fd(fd);
941 if (n < 0)
942 return n;
943
944 buffer = malloc(n + 2);
945 if (!buffer)
946 return -ENOMEM;
947
948 if (ret_sender) {
949 union {
950 struct cmsghdr cmsghdr;
951 uint8_t buf[CMSG_SPACE(sizeof(struct ucred))];
952 } control;
953 bool found_ucred = false;
954 struct cmsghdr *cmsg;
955 struct msghdr mh;
956 struct iovec iov;
957
958 /* Pass one extra byte, as a size check */
959 iov = IOVEC_MAKE(buffer, n + 1);
960
961 mh = (struct msghdr) {
962 .msg_iov = &iov,
963 .msg_iovlen = 1,
964 .msg_control = &control,
965 .msg_controllen = sizeof(control),
966 };
967
3691bcf3 968 m = recvmsg_safe(fd, &mh, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
70a5db58 969 if (m < 0)
3691bcf3 970 return m;
70a5db58
LP
971
972 cmsg_close_all(&mh);
973
974 /* Ensure the size matches what we determined before */
975 if (m != n)
976 return -EMSGSIZE;
977
978 CMSG_FOREACH(cmsg, &mh)
979 if (cmsg->cmsg_level == SOL_SOCKET &&
980 cmsg->cmsg_type == SCM_CREDENTIALS &&
981 cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) {
982
983 memcpy(ret_sender, CMSG_DATA(cmsg), sizeof(struct ucred));
984 found_ucred = true;
985 }
986
987 if (!found_ucred)
988 *ret_sender = (struct ucred) {
989 .pid = 0,
990 .uid = UID_INVALID,
991 .gid = GID_INVALID,
992 };
993 } else {
994 m = recv(fd, buffer, n + 1, MSG_DONTWAIT);
995 if (m < 0)
996 return -errno;
997
998 /* Ensure the size matches what we determined before */
999 if (m != n)
1000 return -EMSGSIZE;
1001 }
1002
1003 /* For safety reasons: let's always NUL terminate. */
1004 ((char*) buffer)[n] = 0;
1005 *ret = TAKE_PTR(buffer);
1006
1007 return 0;
1008}
1009
1010static int on_notify_socket(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
1011 _cleanup_strv_free_ char **l = NULL;
1012 _cleanup_free_ void *datagram = NULL;
1013 struct ucred sender;
1014 Manager *m = userdata;
1015 ssize_t n;
1016 Home *h;
1017
1018 assert(s);
1019 assert(m);
1020
1021 n = read_datagram(fd, &sender, &datagram);
1022 if (IN_SET(n, -EAGAIN, -EINTR))
1023 return 0;
1024 if (n < 0)
1025 return log_error_errno(n, "Failed to read notify datagram: %m");
1026
1027 if (sender.pid <= 0) {
1028 log_warning("Received notify datagram without valid sender PID, ignoring.");
1029 return 0;
1030 }
1031
1032 h = hashmap_get(m->homes_by_worker_pid, PID_TO_PTR(sender.pid));
1033 if (!h) {
162392b7 1034 log_warning("Received notify datagram of unknown process, ignoring.");
70a5db58
LP
1035 return 0;
1036 }
1037
1038 l = strv_split(datagram, "\n");
1039 if (!l)
1040 return log_oom();
1041
1042 home_process_notify(h, l);
1043 return 0;
1044}
1045
1046static int manager_listen_notify(Manager *m) {
1047 _cleanup_close_ int fd = -1;
425d925f
ZJS
1048 union sockaddr_union sa = {
1049 .un.sun_family = AF_UNIX,
1050 .un.sun_path = "/run/systemd/home/notify",
1051 };
70a5db58
LP
1052 int r;
1053
1054 assert(m);
1055 assert(!m->notify_socket_event_source);
1056
1057 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
1058 if (fd < 0)
1059 return log_error_errno(errno, "Failed to create listening socket: %m");
1060
70a5db58
LP
1061 (void) mkdir_parents(sa.un.sun_path, 0755);
1062 (void) sockaddr_un_unlink(&sa.un);
1063
1064 if (bind(fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)) < 0)
1065 return log_error_errno(errno, "Failed to bind to socket: %m");
1066
1067 r = setsockopt_int(fd, SOL_SOCKET, SO_PASSCRED, true);
1068 if (r < 0)
1069 return r;
1070
1071 r = sd_event_add_io(m->event, &m->notify_socket_event_source, fd, EPOLLIN, on_notify_socket, m);
1072 if (r < 0)
1073 return log_error_errno(r, "Failed to allocate event source for notify socket: %m");
1074
1075 (void) sd_event_source_set_description(m->notify_socket_event_source, "notify-socket");
1076
1077 /* Make sure we process sd_notify() before SIGCHLD for any worker, so that we always know the error
1078 * number of a client before it exits. */
1079 r = sd_event_source_set_priority(m->notify_socket_event_source, SD_EVENT_PRIORITY_NORMAL - 5);
1080 if (r < 0)
1081 return log_error_errno(r, "Failed to alter priority of NOTIFY_SOCKET event source: %m");
1082
1083 r = sd_event_source_set_io_fd_own(m->notify_socket_event_source, true);
1084 if (r < 0)
1085 return log_error_errno(r, "Failed to pass ownership of notify socket: %m");
1086
1087 return TAKE_FD(fd);
1088}
1089
1090static int manager_add_device(Manager *m, sd_device *d) {
1091 _cleanup_free_ char *user_name = NULL, *realm = NULL, *node = NULL;
1092 const char *tabletype, *parttype, *partname, *partuuid, *sysfs;
1093 sd_id128_t id;
1094 int r;
1095
1096 assert(m);
1097 assert(d);
1098
1099 r = sd_device_get_syspath(d, &sysfs);
1100 if (r < 0)
1101 return log_error_errno(r, "Failed to acquire sysfs path of device: %m");
1102
1103 r = sd_device_get_property_value(d, "ID_PART_TABLE_TYPE", &tabletype);
1104 if (r == -ENOENT)
1105 return 0;
1106 if (r < 0)
1107 return log_error_errno(r, "Failed to acquire ID_PART_TABLE_TYPE device property, ignoring: %m");
1108
1109 if (!streq(tabletype, "gpt")) {
1110 log_debug("Found partition (%s) on non-GPT table, ignoring.", sysfs);
1111 return 0;
1112 }
1113
1114 r = sd_device_get_property_value(d, "ID_PART_ENTRY_TYPE", &parttype);
1115 if (r == -ENOENT)
1116 return 0;
1117 if (r < 0)
1118 return log_error_errno(r, "Failed to acquire ID_PART_ENTRY_TYPE device property, ignoring: %m");
1119 r = sd_id128_from_string(parttype, &id);
1120 if (r < 0)
1121 return log_debug_errno(r, "Failed to parse ID_PART_ENTRY_TYPE field '%s', ignoring: %m", parttype);
1122 if (!sd_id128_equal(id, GPT_USER_HOME)) {
1123 log_debug("Found partition (%s) we don't care about, ignoring.", sysfs);
1124 return 0;
1125 }
1126
1127 r = sd_device_get_property_value(d, "ID_PART_ENTRY_NAME", &partname);
1128 if (r < 0)
1129 return log_warning_errno(r, "Failed to acquire ID_PART_ENTRY_NAME device property, ignoring: %m");
1130
1131 r = split_user_name_realm(partname, &user_name, &realm);
1132 if (r == -EINVAL)
1133 return log_warning_errno(r, "Found partition with correct partition type but a non-parsable partition name '%s', ignoring.", partname);
1134 if (r < 0)
1135 return log_error_errno(r, "Failed to validate partition name '%s': %m", partname);
1136
1137 r = sd_device_get_property_value(d, "ID_FS_UUID", &partuuid);
1138 if (r < 0)
1139 return log_warning_errno(r, "Failed to acquire ID_FS_UUID device property, ignoring: %m");
1140
1141 r = sd_id128_from_string(partuuid, &id);
1142 if (r < 0)
1143 return log_warning_errno(r, "Failed to parse ID_FS_UUID field '%s', ignoring: %m", partuuid);
1144
1145 if (asprintf(&node, "/dev/disk/by-uuid/" SD_ID128_UUID_FORMAT_STR, SD_ID128_FORMAT_VAL(id)) < 0)
1146 return log_oom();
1147
1148 return manager_add_home_by_image(m, user_name, realm, node, sysfs, USER_LUKS, UID_INVALID);
1149}
1150
1151static int manager_on_device(sd_device_monitor *monitor, sd_device *d, void *userdata) {
1152 Manager *m = userdata;
1153 int r;
1154
1155 assert(m);
1156 assert(d);
1157
1158 if (device_for_action(d, DEVICE_ACTION_REMOVE)) {
1159 const char *sysfs;
1160 Home *h;
1161
1162 r = sd_device_get_syspath(d, &sysfs);
1163 if (r < 0) {
1164 log_warning_errno(r, "Failed to acquire sysfs path from device: %m");
1165 return 0;
1166 }
1167
1168 log_info("block device %s has been removed.", sysfs);
1169
1170 /* Let's see if we previously synthesized a home record from this device, if so, let's just
1171 * revalidate that. Otherwise let's revalidate them all, but asynchronously. */
1172 h = hashmap_get(m->homes_by_sysfs, sysfs);
1173 if (h)
1174 manager_revalidate_image(m, h);
1175 else
1176 manager_enqueue_gc(m, NULL);
1177 } else
1178 (void) manager_add_device(m, d);
1179
1180 (void) bus_manager_emit_auto_login_changed(m);
1181 return 0;
1182}
1183
1184static int manager_watch_devices(Manager *m) {
1185 int r;
1186
1187 assert(m);
1188 assert(!m->device_monitor);
1189
1190 r = sd_device_monitor_new(&m->device_monitor);
1191 if (r < 0)
1192 return log_error_errno(r, "Failed to allocate device monitor: %m");
1193
1194 r = sd_device_monitor_filter_add_match_subsystem_devtype(m->device_monitor, "block", NULL);
1195 if (r < 0)
1196 return log_error_errno(r, "Failed to configure device monitor match: %m");
1197
1198 r = sd_device_monitor_attach_event(m->device_monitor, m->event);
1199 if (r < 0)
1200 return log_error_errno(r, "Failed to attach device monitor to event loop: %m");
1201
1202 r = sd_device_monitor_start(m->device_monitor, manager_on_device, m);
1203 if (r < 0)
1204 return log_error_errno(r, "Failed to start device monitor: %m");
1205
1206 return 0;
1207}
1208
1209static int manager_enumerate_devices(Manager *m) {
1210 _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
1211 sd_device *d;
1212 int r;
1213
1214 assert(m);
1215
1216 r = sd_device_enumerator_new(&e);
1217 if (r < 0)
1218 return r;
1219
1220 r = sd_device_enumerator_add_match_subsystem(e, "block", true);
1221 if (r < 0)
1222 return r;
1223
1224 FOREACH_DEVICE(e, d)
1225 (void) manager_add_device(m, d);
1226
1227 return 0;
1228}
1229
1230static int manager_load_key_pair(Manager *m) {
1231 _cleanup_(fclosep) FILE *f = NULL;
1232 struct stat st;
1233 int r;
1234
1235 assert(m);
1236
1237 if (m->private_key) {
1238 EVP_PKEY_free(m->private_key);
1239 m->private_key = NULL;
1240 }
1241
1242 r = search_and_fopen_nulstr("local.private", "re", NULL, KEY_PATHS_NULSTR, &f);
1243 if (r == -ENOENT)
1244 return 0;
1245 if (r < 0)
1246 return log_error_errno(r, "Failed to read private key file: %m");
1247
1248 if (fstat(fileno(f), &st) < 0)
1249 return log_error_errno(errno, "Failed to stat private key file: %m");
1250
1251 r = stat_verify_regular(&st);
1252 if (r < 0)
1253 return log_error_errno(r, "Private key file is not regular: %m");
1254
1255 if (st.st_uid != 0 || (st.st_mode & 0077) != 0)
1256 return log_error_errno(SYNTHETIC_ERRNO(EPERM), "Private key file is readable by more than the root user");
1257
1258 m->private_key = PEM_read_PrivateKey(f, NULL, NULL, NULL);
1259 if (!m->private_key)
1260 return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to load private key pair");
1261
1262 log_info("Successfully loaded private key pair.");
1263
1264 return 1;
1265}
1266
1267DEFINE_TRIVIAL_CLEANUP_FUNC(EVP_PKEY_CTX*, EVP_PKEY_CTX_free);
1268
1269static int manager_generate_key_pair(Manager *m) {
1270 _cleanup_(EVP_PKEY_CTX_freep) EVP_PKEY_CTX *ctx = NULL;
1271 _cleanup_(unlink_and_freep) char *temp_public = NULL, *temp_private = NULL;
1272 _cleanup_fclose_ FILE *fpublic = NULL, *fprivate = NULL;
1273 int r;
1274
1275 if (m->private_key) {
1276 EVP_PKEY_free(m->private_key);
1277 m->private_key = NULL;
1278 }
1279
1280 ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_ED25519, NULL);
1281 if (!ctx)
1282 return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to allocate Ed25519 key generation context.");
1283
1284 if (EVP_PKEY_keygen_init(ctx) <= 0)
1285 return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to initialize Ed25519 key generation context.");
1286
1287 log_info("Generating key pair for signing local user identity records.");
1288
1289 if (EVP_PKEY_keygen(ctx, &m->private_key) <= 0)
1290 return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to generate Ed25519 key pair");
1291
1292 log_info("Successfully created Ed25519 key pair.");
1293
1294 (void) mkdir_p("/var/lib/systemd/home", 0755);
1295
1296 /* Write out public key (note that we only do that as a help to the user, we don't make use of this ever */
1297 r = fopen_temporary("/var/lib/systemd/home/local.public", &fpublic, &temp_public);
1298 if (r < 0)
80ace4f2 1299 return log_error_errno(errno, "Failed to open key file for writing: %m");
70a5db58
LP
1300
1301 if (PEM_write_PUBKEY(fpublic, m->private_key) <= 0)
1302 return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to write public key.");
1303
1304 r = fflush_and_check(fpublic);
1305 if (r < 0)
1306 return log_error_errno(r, "Failed to write private key: %m");
1307
1308 fpublic = safe_fclose(fpublic);
1309
1310 /* Write out the private key (this actually writes out both private and public, OpenSSL is confusing) */
1311 r = fopen_temporary("/var/lib/systemd/home/local.private", &fprivate, &temp_private);
1312 if (r < 0)
80ace4f2 1313 return log_error_errno(errno, "Failed to open key file for writing: %m");
70a5db58
LP
1314
1315 if (PEM_write_PrivateKey(fprivate, m->private_key, NULL, NULL, 0, NULL, 0) <= 0)
1316 return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to write private key pair.");
1317
1318 r = fflush_and_check(fprivate);
1319 if (r < 0)
1320 return log_error_errno(r, "Failed to write private key: %m");
1321
1322 fprivate = safe_fclose(fprivate);
1323
1324 /* Both are written now, move them into place */
1325
1326 if (rename(temp_public, "/var/lib/systemd/home/local.public") < 0)
1327 return log_error_errno(errno, "Failed to move public key file into place: %m");
1328 temp_public = mfree(temp_public);
1329
1330 if (rename(temp_private, "/var/lib/systemd/home/local.private") < 0) {
1331 (void) unlink_noerrno("/var/lib/systemd/home/local.public"); /* try to remove the file we already created */
1332 return log_error_errno(errno, "Failed to move privtate key file into place: %m");
1333 }
1334 temp_private = mfree(temp_private);
1335
1336 return 1;
1337}
1338
1339int manager_acquire_key_pair(Manager *m) {
1340 int r;
1341
1342 assert(m);
1343
1344 /* Already there? */
1345 if (m->private_key)
1346 return 1;
1347
1348 /* First try to load key off disk */
1349 r = manager_load_key_pair(m);
1350 if (r != 0)
1351 return r;
1352
1353 /* Didn't work, generate a new one */
1354 return manager_generate_key_pair(m);
1355}
1356
1357int manager_sign_user_record(Manager *m, UserRecord *u, UserRecord **ret, sd_bus_error *error) {
1358 int r;
1359
1360 assert(m);
1361 assert(u);
1362 assert(ret);
1363
1364 r = manager_acquire_key_pair(m);
1365 if (r < 0)
1366 return r;
1367 if (r == 0)
1368 return sd_bus_error_setf(error, BUS_ERROR_NO_PRIVATE_KEY, "Can't sign without local key.");
1369
1370 return user_record_sign(u, m->private_key, ret);
1371}
1372
1373DEFINE_PRIVATE_HASH_OPS_FULL(public_key_hash_ops, char, string_hash_func, string_compare_func, free, EVP_PKEY, EVP_PKEY_free);
1374DEFINE_TRIVIAL_CLEANUP_FUNC(EVP_PKEY*, EVP_PKEY_free);
1375
1376static int manager_load_public_key_one(Manager *m, const char *path) {
1377 _cleanup_(EVP_PKEY_freep) EVP_PKEY *pkey = NULL;
1378 _cleanup_fclose_ FILE *f = NULL;
1379 _cleanup_free_ char *fn = NULL;
1380 struct stat st;
1381 int r;
1382
1383 assert(m);
1384
1385 if (streq(basename(path), "local.public")) /* we already loaded the private key, which includes the public one */
1386 return 0;
1387
1388 f = fopen(path, "re");
1389 if (!f) {
1390 if (errno == ENOENT)
1391 return 0;
1392
1393 return log_error_errno(errno, "Failed to open public key %s: %m", path);
1394 }
1395
1396 if (fstat(fileno(f), &st) < 0)
1397 return log_error_errno(errno, "Failed to stat public key %s: %m", path);
1398
1399 r = stat_verify_regular(&st);
1400 if (r < 0)
1401 return log_error_errno(r, "Public key file %s is not a regular file: %m", path);
1402
1403 if (st.st_uid != 0 || (st.st_mode & 0022) != 0)
1404 return log_error_errno(SYNTHETIC_ERRNO(EPERM), "Public key file %s is writable by more than the root user, refusing.", path);
1405
1406 r = hashmap_ensure_allocated(&m->public_keys, &public_key_hash_ops);
1407 if (r < 0)
1408 return log_oom();
1409
1410 pkey = PEM_read_PUBKEY(f, &pkey, NULL, NULL);
1411 if (!pkey)
1412 return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to parse public key file %s.", path);
1413
1414 fn = strdup(basename(path));
1415 if (!fn)
1416 return log_oom();
1417
1418 r = hashmap_put(m->public_keys, fn, pkey);
1419 if (r < 0)
1420 return log_error_errno(r, "Failed to add public key to set: %m");
1421
1422 TAKE_PTR(fn);
1423 TAKE_PTR(pkey);
1424
1425 return 0;
1426}
1427
1428static int manager_load_public_keys(Manager *m) {
1429 _cleanup_strv_free_ char **files = NULL;
1430 char **i;
1431 int r;
1432
1433 assert(m);
1434
1435 m->public_keys = hashmap_free(m->public_keys);
1436
1437 r = conf_files_list_nulstr(
1438 &files,
1439 ".public",
1440 NULL,
1441 CONF_FILES_REGULAR|CONF_FILES_FILTER_MASKED,
1442 KEY_PATHS_NULSTR);
1443 if (r < 0)
1444 return log_error_errno(r, "Failed to assemble list of public key directories: %m");
1445
1446 STRV_FOREACH(i, files)
1447 (void) manager_load_public_key_one(m, *i);
1448
1449 return 0;
1450}
1451
1452int manager_startup(Manager *m) {
1453 int r;
1454
1455 assert(m);
1456
1457 r = manager_listen_notify(m);
1458 if (r < 0)
1459 return r;
1460
1461 r = manager_connect_bus(m);
1462 if (r < 0)
1463 return r;
1464
1465 r = manager_bind_varlink(m);
1466 if (r < 0)
1467 return r;
1468
1469 r = manager_load_key_pair(m); /* only try to load it, don't generate any */
1470 if (r < 0)
1471 return r;
1472
1473 r = manager_load_public_keys(m);
1474 if (r < 0)
1475 return r;
1476
1477 manager_watch_home(m);
1478 (void) manager_watch_devices(m);
1479
1480 (void) manager_enumerate_records(m);
1481 (void) manager_enumerate_images(m);
1482 (void) manager_enumerate_devices(m);
1483
1484 /* Let's clean up home directories whose devices got removed while we were not running */
1485 (void) manager_enqueue_gc(m, NULL);
1486
1487 return 0;
1488}
1489
1490void manager_revalidate_image(Manager *m, Home *h) {
1491 int r;
1492
1493 assert(m);
1494 assert(h);
1495
1496 /* Frees an automatically discovered image, if it's synthetic and its image disappeared. Unmounts any
1497 * image if it's mounted but it's image vanished. */
1498
1499 if (h->current_operation || !ordered_set_isempty(h->pending_operations))
1500 return;
1501
1502 if (h->state == HOME_UNFIXATED) {
1503 r = user_record_test_image_path(h->record);
1504 if (r < 0)
1505 log_warning_errno(r, "Can't determine if image of %s exists, freeing unfixated user: %m", h->user_name);
1506 else if (r == USER_TEST_ABSENT)
1507 log_info("Image for %s disappeared, freeing unfixated user.", h->user_name);
1508 else
1509 return;
1510
1511 home_free(h);
1512
1513 } else if (h->state < 0) {
1514
1515 r = user_record_test_home_directory(h->record);
1516 if (r < 0) {
1517 log_warning_errno(r, "Unable to determine state of home directory, ignoring: %m");
1518 return;
1519 }
1520
1521 if (r == USER_TEST_MOUNTED) {
1522 r = user_record_test_image_path(h->record);
1523 if (r < 0) {
1524 log_warning_errno(r, "Unable to determine state of image path, ignoring: %m");
1525 return;
1526 }
1527
1528 if (r == USER_TEST_ABSENT) {
1529 _cleanup_(operation_unrefp) Operation *o = NULL;
1530
1531 log_notice("Backing image disappeared while home directory %s was mounted, unmounting it forcibly.", h->user_name);
1532 /* Wowza, the thing is mounted, but the device is gone? Act on it. */
1533
1534 r = home_killall(h);
1535 if (r < 0)
1536 log_warning_errno(r, "Failed to kill processes of user %s, ignoring: %m", h->user_name);
1537
1538 /* We enqueue the operation here, after all the home directory might
1539 * currently already run some operation, and we can deactivate it only after
1540 * that's complete. */
1541 o = operation_new(OPERATION_DEACTIVATE_FORCE, NULL);
1542 if (!o) {
1543 log_oom();
1544 return;
1545 }
1546
1547 r = home_schedule_operation(h, o, NULL);
1548 if (r < 0)
1549 log_warning_errno(r, "Failed to enqueue forced home directory %s deactivation, ignoring: %m", h->user_name);
1550 }
1551 }
1552 }
1553}
1554
1555int manager_gc_images(Manager *m) {
1556 Home *h;
1557
1558 assert_se(m);
1559
1560 if (m->gc_focus) {
1561 /* Focus on a specific home */
1562
1563 h = TAKE_PTR(m->gc_focus);
1564 manager_revalidate_image(m, h);
1565 } else {
1566 /* Gc all */
1567 Iterator i;
1568
1569 HASHMAP_FOREACH(h, m->homes_by_name, i)
1570 manager_revalidate_image(m, h);
1571 }
1572
1573 return 0;
1574}
1575
1576static int on_deferred_rescan(sd_event_source *s, void *userdata) {
1577 Manager *m = userdata;
1578
1579 assert(m);
1580
1581 m->deferred_rescan_event_source = sd_event_source_unref(m->deferred_rescan_event_source);
1582
1583 manager_enumerate_devices(m);
1584 manager_enumerate_images(m);
1585 return 0;
1586}
1587
1588int manager_enqueue_rescan(Manager *m) {
1589 int r;
1590
1591 assert(m);
1592
1593 if (m->deferred_rescan_event_source)
1594 return 0;
1595
1596 if (!m->event)
1597 return 0;
1598
1599 if (IN_SET(sd_event_get_state(m->event), SD_EVENT_FINISHED, SD_EVENT_EXITING))
1600 return 0;
1601
1602 r = sd_event_add_defer(m->event, &m->deferred_rescan_event_source, on_deferred_rescan, m);
1603 if (r < 0)
1604 return log_error_errno(r, "Failed to allocate rescan event source: %m");
1605
1606 r = sd_event_source_set_priority(m->deferred_rescan_event_source, SD_EVENT_PRIORITY_IDLE+1);
1607 if (r < 0)
1608 log_warning_errno(r, "Failed to tweak priority of event source, ignoring: %m");
1609
1610 (void) sd_event_source_set_description(m->deferred_rescan_event_source, "deferred-rescan");
1611 return 1;
1612}
1613
1614static int on_deferred_gc(sd_event_source *s, void *userdata) {
1615 Manager *m = userdata;
1616
1617 assert(m);
1618
1619 m->deferred_gc_event_source = sd_event_source_unref(m->deferred_gc_event_source);
1620
1621 manager_gc_images(m);
1622 return 0;
1623}
1624
1625int manager_enqueue_gc(Manager *m, Home *focus) {
1626 int r;
1627
1628 assert(m);
1629
1630 /* This enqueues a request to GC dead homes. It may be called with focus=NULL in which case all homes
1631 * will be scanned, or with the parameter set, in which case only that home is checked. */
1632
1633 if (!m->event)
1634 return 0;
1635
1636 if (IN_SET(sd_event_get_state(m->event), SD_EVENT_FINISHED, SD_EVENT_EXITING))
1637 return 0;
1638
1639 /* If a focus home is specified, then remember to focus just on this home. Otherwise invalidate any
1640 * focus that might be set to look at all homes. */
1641
1642 if (m->deferred_gc_event_source) {
1643 if (m->gc_focus != focus) /* not the same focus, then look at everything */
1644 m->gc_focus = NULL;
1645
1646 return 0;
1647 } else
162392b7 1648 m->gc_focus = focus; /* start focused */
70a5db58
LP
1649
1650 r = sd_event_add_defer(m->event, &m->deferred_gc_event_source, on_deferred_gc, m);
1651 if (r < 0)
80ace4f2 1652 return log_error_errno(r, "Failed to allocate GC event source: %m");
70a5db58
LP
1653
1654 r = sd_event_source_set_priority(m->deferred_gc_event_source, SD_EVENT_PRIORITY_IDLE);
1655 if (r < 0)
1656 log_warning_errno(r, "Failed to tweak priority of event source, ignoring: %m");
1657
1658 (void) sd_event_source_set_description(m->deferred_gc_event_source, "deferred-gc");
1659 return 1;
1660}