]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/home/homework.c
man/systemd-sysext: list ephemeral/ephemeral-import in the list of options
[thirdparty/systemd.git] / src / home / homework.c
CommitLineData
db9ecf05 1/* SPDX-License-Identifier: LGPL-2.1-or-later */
70a5db58 2
572c1fe6 3#include <stdlib.h>
70a5db58 4#include <sys/mount.h>
4f18ff2e 5#include <unistd.h>
70a5db58 6
76d62b63
DDM
7#include "sd-daemon.h"
8
b25a930f 9#include "blockdev-util.h"
a5b009d9 10#include "bus-unit-util.h"
1e0e7c74 11#include "chase.h"
70a5db58
LP
12#include "chown-recursive.h"
13#include "copy.h"
572c1fe6 14#include "cryptsetup-util.h"
a5b009d9 15#include "env-util.h"
572c1fe6 16#include "errno-util.h"
70a5db58
LP
17#include "fd-util.h"
18#include "fileio.h"
7c604e89 19#include "filesystems.h"
a5b009d9 20#include "format-util.h"
572c1fe6 21#include "hashmap.h"
70a5db58 22#include "home-util.h"
572c1fe6
DDM
23#include "homework-fido2.h"
24#include "homework-password-cache.h"
25#include "homework-pkcs11.h"
309a747f 26#include "homework.h"
17ac40e4 27#include "homework-blob.h"
70a5db58
LP
28#include "homework-cifs.h"
29#include "homework-directory.h"
30#include "homework-fscrypt.h"
31#include "homework-luks.h"
32#include "homework-mount.h"
309a747f 33#include "json-util.h"
0e98d17e 34#include "libcrypt-util.h"
572c1fe6 35#include "loop-util.h"
70a5db58
LP
36#include "main-func.h"
37#include "memory-util.h"
38#include "missing_magic.h"
572c1fe6 39#include "missing_syscall.h"
70a5db58
LP
40#include "mount-util.h"
41#include "path-util.h"
73d874ba 42#include "recovery-key.h"
70a5db58
LP
43#include "rm-rf.h"
44#include "stat-util.h"
572c1fe6 45#include "string-util.h"
70a5db58 46#include "strv.h"
86019efa 47#include "sync-util.h"
572c1fe6 48#include "time-util.h"
70a5db58 49#include "tmpfile-util.h"
572c1fe6
DDM
50#include "user-record.h"
51#include "user-record-util.h"
70a5db58
LP
52#include "user-util.h"
53#include "virt.h"
54
55/* Make sure a bad password always results in a 3s delay, no matter what */
56#define BAD_PASSWORD_DELAY_USEC (3 * USEC_PER_SEC)
57
58int user_record_authenticate(
59 UserRecord *h,
60 UserRecord *secret,
7b78db28 61 PasswordCache *cache,
c8f145ad 62 bool strict_verify) {
70a5db58 63
17e7561a
LP
64 bool need_password = false, need_recovery_key = false, need_token = false, need_pin = false,
65 need_protected_authentication_path_permitted = false, need_user_presence_permitted = false,
66 need_user_verification_permitted = false, pin_locked = false, pin_incorrect = false,
67 pin_incorrect_few_tries_left = false, pin_incorrect_one_try_left = false, token_action_timeout = false;
70a5db58
LP
68 int r;
69
70 assert(h);
71 assert(secret);
b0118b25 72 assert(cache);
70a5db58
LP
73
74 /* Tries to authenticate a user record with the supplied secrets. i.e. checks whether at least one
75 * supplied plaintext passwords matches a hashed password field of the user record. Or if a
7b78db28 76 * configured PKCS#11 or FIDO2 token is around and can unlock the record.
70a5db58 77 *
7b78db28
LP
78 * Note that the 'cache' parameter is both an input and output parameter: it contains lists of
79 * configured, decrypted PKCS#11/FIDO2 passwords. We typically have to call this function multiple
80 * times over the course of an operation (think: on login we authenticate the host user record, the
81 * record embedded in the LUKS record and the one embedded in $HOME). Hence we keep a list of
82 * passwords we already decrypted, so that we don't have to do the (slow and potentially interactive)
5ec87d57
AV
83 * PKCS#11/FIDO2 dance for the relevant token again and again.
84 *
85 * The 'cache' parameter might also contain the LUKS volume key, loaded from the kernel keyring.
86 * In this case, authentication becomes optional - if a secret section is provided it will be
87 * verified, but if missing then authentication is skipped entirely. Thus, callers should
193134de 88 * consider carefully whether it is safe to load the volume key into 'cache' before doing so.
5ec87d57
AV
89 * Note that most of the time this is safe, because the home area must be active for the key
90 * to exist in the keyring, and the user would have had to authenticate when activating their
91 * home area; however, for some methods (i.e. ChangePassword, Authenticate) it makes more sense
92 * to force re-authentication. */
93
94 /* First, let's see if we already have a volume key from the keyring */
b0118b25 95 if (cache->volume_key &&
309a747f 96 sd_json_variant_is_blank_object(sd_json_variant_by_key(secret->json, "secret"))) {
5ec87d57
AV
97 log_info("LUKS volume key from keyring unlocks user record.");
98 return 1;
99 }
70a5db58 100
5ec87d57 101 /* Next, let's see if the supplied plain-text passwords work? */
87d7893c
LP
102 r = user_record_test_password(h, secret);
103 if (r == -ENOKEY)
70a5db58 104 need_password = true;
87d7893c 105 else if (r == -ENXIO)
70a5db58
LP
106 log_debug_errno(r, "User record has no hashed passwords, plaintext passwords not tested.");
107 else if (r < 0)
108 return log_error_errno(r, "Failed to validate password of record: %m");
109 else {
110 log_info("Provided password unlocks user record.");
c8f145ad 111 return 1;
70a5db58
LP
112 }
113
87d7893c
LP
114 /* Similar, but test against the recovery keys */
115 r = user_record_test_recovery_key(h, secret);
116 if (r == -ENOKEY)
117 need_recovery_key = true;
118 else if (r == -ENXIO)
119 log_debug_errno(r, "User record has no recovery keys, plaintext passwords not tested against it.");
120 else if (r < 0)
121 return log_error_errno(r, "Failed to validate the recovery key of the record: %m");
122 else {
123 log_info("Provided password is a recovery key that unlocks the user record.");
124 return 1;
125 }
126
127 if (need_password && need_recovery_key)
128 log_info("None of the supplied plaintext passwords unlock the user record's hashed passwords or recovery keys.");
129 else if (need_password)
130 log_info("None of the supplied plaintext passwords unlock the user record's hashed passwords.");
131 else
132 log_info("None of the supplied plaintext passwords unlock the user record's hashed recovery keys.");
133
5ec87d57 134 /* Next, test cached PKCS#11 passwords */
3b09af20 135 FOREACH_ARRAY(i, h->pkcs11_encrypted_key, h->n_pkcs11_encrypted_key)
7b78db28 136 STRV_FOREACH(pp, cache->pkcs11_passwords) {
3b09af20 137 r = test_password_one(i->hashed_password, *pp);
70a5db58
LP
138 if (r < 0)
139 return log_error_errno(r, "Failed to check supplied PKCS#11 password: %m");
140 if (r > 0) {
141 log_info("Previously acquired PKCS#11 password unlocks user record.");
c8f145ad 142 return 1;
70a5db58
LP
143 }
144 }
7b78db28 145
5ec87d57 146 /* Next, test cached FIDO2 passwords */
3b09af20 147 FOREACH_ARRAY(i, h->fido2_hmac_salt, h->n_fido2_hmac_salt)
7b78db28
LP
148 /* See if any of the previously calculated passwords work */
149 STRV_FOREACH(pp, cache->fido2_passwords) {
3b09af20 150 r = test_password_one(i->hashed_password, *pp);
7b78db28
LP
151 if (r < 0)
152 return log_error_errno(r, "Failed to check supplied FIDO2 password: %m");
153 if (r > 0) {
154 log_info("Previously acquired FIDO2 password unlocks user record.");
e4961427 155 return 1;
7b78db28
LP
156 }
157 }
7b78db28 158
5ec87d57 159 /* Next, let's see if any of the PKCS#11 security tokens are plugged in and help us */
3b09af20 160 FOREACH_ARRAY(i, h->pkcs11_encrypted_key, h->n_pkcs11_encrypted_key) {
7b78db28
LP
161#if HAVE_P11KIT
162 _cleanup_(pkcs11_callback_data_release) struct pkcs11_callback_data data = {
163 .user_record = h,
164 .secret = secret,
3b09af20 165 .encrypted_key = i,
7b78db28 166 };
70a5db58
LP
167
168 r = pkcs11_find_token(data.encrypted_key->uri, pkcs11_callback, &data);
169 switch (r) {
170 case -EAGAIN:
171 need_token = true;
172 break;
173 case -ENOANO:
174 need_pin = true;
175 break;
176 case -ERFKILL:
177 need_protected_authentication_path_permitted = true;
178 break;
179 case -EOWNERDEAD:
180 pin_locked = true;
181 break;
182 case -ENOLCK:
183 pin_incorrect = true;
184 break;
185 case -ETOOMANYREFS:
186 pin_incorrect = pin_incorrect_few_tries_left = true;
187 break;
188 case -EUCLEAN:
189 pin_incorrect = pin_incorrect_few_tries_left = pin_incorrect_one_try_left = true;
190 break;
191 default:
192 if (r < 0)
193 return r;
194
195 r = test_password_one(data.encrypted_key->hashed_password, data.decrypted_password);
196 if (r < 0)
197 return log_error_errno(r, "Failed to test PKCS#11 password: %m");
198 if (r == 0)
3b09af20
MY
199 return log_error_errno(SYNTHETIC_ERRNO(EPERM),
200 "Configured PKCS#11 security token %s does not decrypt encrypted key correctly.",
201 data.encrypted_key->uri);
70a5db58
LP
202
203 log_info("Decrypted password from PKCS#11 security token %s unlocks user record.", data.encrypted_key->uri);
204
7b78db28
LP
205 r = strv_extend(&cache->pkcs11_passwords, data.decrypted_password);
206 if (r < 0)
207 return log_oom();
208
e4961427 209 return 1;
7b78db28
LP
210 }
211#else
212 need_token = true;
213 break;
214#endif
215 }
216
5ec87d57 217 /* Next, let's see if any of the FIDO2 security tokens are plugged in and help us */
3b09af20 218 FOREACH_ARRAY(i, h->fido2_hmac_salt, h->n_fido2_hmac_salt) {
7b78db28
LP
219#if HAVE_LIBFIDO2
220 _cleanup_(erase_and_freep) char *decrypted_password = NULL;
221
3b09af20 222 r = fido2_use_token(h, secret, i, &decrypted_password);
7b78db28
LP
223 switch (r) {
224 case -EAGAIN:
225 need_token = true;
226 break;
227 case -ENOANO:
228 need_pin = true;
229 break;
230 case -EOWNERDEAD:
231 pin_locked = true;
232 break;
233 case -ENOLCK:
234 pin_incorrect = true;
235 break;
236 case -EMEDIUMTYPE:
237 need_user_presence_permitted = true;
238 break;
17e7561a
LP
239 case -ENOCSI:
240 need_user_verification_permitted = true;
241 break;
7b78db28
LP
242 case -ENOSTR:
243 token_action_timeout = true;
244 break;
245 default:
246 if (r < 0)
247 return r;
248
3b09af20 249 r = test_password_one(i->hashed_password, decrypted_password);
7b78db28
LP
250 if (r < 0)
251 return log_error_errno(r, "Failed to test FIDO2 password: %m");
252 if (r == 0)
3b09af20
MY
253 return log_error_errno(SYNTHETIC_ERRNO(EPERM),
254 "Configured FIDO2 security token does not decrypt encrypted key correctly.");
7b78db28
LP
255
256 log_info("Decrypted password from FIDO2 security token unlocks user record.");
257
258 r = strv_extend(&cache->fido2_passwords, decrypted_password);
70a5db58
LP
259 if (r < 0)
260 return log_oom();
261
c8f145ad 262 return 1;
70a5db58
LP
263 }
264#else
265 need_token = true;
266 break;
267#endif
268 }
269
270 /* Ordered by "relevance", i.e. the most "important" or "interesting" error condition is returned. */
271 if (pin_incorrect_one_try_left)
272 return -EUCLEAN;
273 if (pin_incorrect_few_tries_left)
274 return -ETOOMANYREFS;
275 if (pin_incorrect)
276 return -ENOLCK;
277 if (pin_locked)
278 return -EOWNERDEAD;
7b78db28
LP
279 if (token_action_timeout)
280 return -ENOSTR;
70a5db58
LP
281 if (need_protected_authentication_path_permitted)
282 return -ERFKILL;
7b78db28
LP
283 if (need_user_presence_permitted)
284 return -EMEDIUMTYPE;
17e7561a
LP
285 if (need_user_verification_permitted)
286 return -ENOCSI;
70a5db58
LP
287 if (need_pin)
288 return -ENOANO;
289 if (need_token)
290 return -EBADSLT;
291 if (need_password)
292 return -ENOKEY;
87d7893c
LP
293 if (need_recovery_key)
294 return -EREMOTEIO;
70a5db58 295
87d7893c
LP
296 /* Hmm, this means neither PCKS#11/FIDO2 nor classic hashed passwords or recovery keys were supplied,
297 * we cannot authenticate this reasonably */
c8f145ad
LP
298 if (strict_verify)
299 return log_debug_errno(SYNTHETIC_ERRNO(EKEYREVOKED),
87d7893c 300 "No hashed passwords, no recovery keys and no PKCS#11/FIDO2 tokens defined, cannot authenticate user record, refusing.");
c8f145ad
LP
301
302 /* If strict verification is off this means we are possibly in the case where we encountered an
303 * unfixated record, i.e. a synthetic one that accordingly lacks any authentication data. In this
304 * case, allow the authentication to pass for now, so that the second (or third) authentication level
305 * (the ones of the user record in the LUKS header or inside the home directory) will then catch
306 * invalid passwords. The second/third authentication always runs in strict verification mode. */
87d7893c 307 log_debug("No hashed passwords, not recovery keys and no PKCS#11 tokens defined in record, cannot authenticate user record. "
c8f145ad
LP
308 "Deferring to embedded user record.");
309 return 0;
70a5db58
LP
310}
311
86019efa
LP
312static void drop_caches_now(void) {
313 int r;
314
0e685823 315 /* Drop file system caches now. See https://docs.kernel.org/admin-guide/sysctl/vm.html
43ad1998 316 * for details. We write "3" into /proc/sys/vm/drop_caches to ensure dentries/inodes are flushed, but
2f8211c6 317 * not more. */
86019efa 318
43ad1998 319 r = write_string_file("/proc/sys/vm/drop_caches", "3\n", WRITE_STRING_FILE_DISABLE_BUFFER);
86019efa
LP
320 if (r < 0)
321 log_warning_errno(r, "Failed to drop caches, ignoring: %m");
322 else
323 log_debug("Dropped caches.");
324}
325
55166094
LP
326int home_setup_undo_mount(HomeSetup *setup, int level) {
327 int r;
328
329 assert(setup);
330
331 if (!setup->undo_mount)
332 return 0;
333
1147c538
LP
334 r = umount_recursive(HOME_RUNTIME_WORK_DIR, 0);
335 if (r < 0) {
336 if (level >= LOG_DEBUG) /* umount_recursive() does debug level logging anyway, no need to
337 * repeat that here */
338 return r;
339
a6f44d61 340 /* If a higher log level is requested, the generate a non-debug message here too. */
1147c538
LP
341 return log_full_errno(level, r, "Failed to unmount mount tree below %s: %m", HOME_RUNTIME_WORK_DIR);
342 }
55166094
LP
343
344 setup->undo_mount = false;
345 return 1;
346}
347
f7800049
LP
348int home_setup_undo_dm(HomeSetup *setup, int level) {
349 int r, ret;
350
351 assert(setup);
352
353 if (setup->undo_dm) {
354 assert(setup->crypt_device);
355 assert(setup->dm_name);
356
357 r = sym_crypt_deactivate_by_name(setup->crypt_device, setup->dm_name, 0);
358 if (r < 0)
359 return log_full_errno(level, r, "Failed to deactivate LUKS device: %m");
360
491347bd
LP
361 /* In case the device was already remove asynchronously by an early unmount via the deferred
362 * remove logic, let's wait for it */
363 (void) wait_for_block_device_gone(setup, USEC_PER_SEC * 30);
364
f7800049
LP
365 setup->undo_dm = false;
366 ret = 1;
367 } else
368 ret = 0;
369
370 if (setup->crypt_device) {
371 sym_crypt_free(setup->crypt_device);
372 setup->crypt_device = NULL;
373 }
374
375 return ret;
376}
377
d26cdde3
LP
378int keyring_unlink(key_serial_t k) {
379
380 if (k == -1) /* already invalidated? */
381 return -1;
382
383 if (keyctl(KEYCTL_UNLINK, k, KEY_SPEC_SESSION_KEYRING, 0, 0) < 0)
384 log_debug_errno(errno, "Failed to unlink key from session kernel keyring, ignoring: %m");
385
386 return -1; /* Always return the key_serial_t value for "invalid" */
387}
388
389static int keyring_flush(UserRecord *h) {
390 _cleanup_free_ char *name = NULL;
391 long serial;
392
393 assert(h);
394
c4b5de7e
LB
395 if (user_record_storage(h) == USER_FSCRYPT)
396 (void) home_flush_keyring_fscrypt(h);
397
d26cdde3
LP
398 name = strjoin("homework-user-", h->user_name);
399 if (!name)
400 return log_oom();
401
402 serial = keyctl(KEYCTL_SEARCH, (unsigned long) KEY_SPEC_SESSION_KEYRING, (unsigned long) "user", (unsigned long) name, 0);
403 if (serial == -1)
404 return log_debug_errno(errno, "Failed to find kernel keyring entry for user, ignoring: %m");
405
406 return keyring_unlink(serial);
407}
408
66aa51f8 409int home_setup_done(HomeSetup *setup) {
70a5db58
LP
410 int r = 0, q;
411
412 assert(setup);
413
28a7f106
LP
414 if (setup->root_fd >= 0) {
415 if (setup->do_offline_fitrim) {
416 q = run_fitrim(setup->root_fd);
417 if (q < 0)
418 r = q;
419 }
420
86019efa
LP
421 if (syncfs(setup->root_fd) < 0)
422 log_debug_errno(errno, "Failed to synchronize home directory, ignoring: %m");
423
28a7f106
LP
424 setup->root_fd = safe_close(setup->root_fd);
425 }
70a5db58 426
55166094
LP
427 q = home_setup_undo_mount(setup, LOG_DEBUG);
428 if (q < 0)
429 r = q;
70a5db58 430
f7800049
LP
431 q = home_setup_undo_dm(setup, LOG_DEBUG);
432 if (q < 0)
433 r = q;
70a5db58 434
28a7f106
LP
435 if (setup->image_fd >= 0) {
436 if (setup->do_offline_fallocate) {
437 q = run_fallocate(setup->image_fd, NULL);
438 if (q < 0)
439 r = q;
440 }
441
565ac8b1
LP
442 if (setup->do_mark_clean) {
443 q = run_mark_dirty(setup->image_fd, false);
444 if (q < 0)
445 r = q;
446 }
447
28a7f106
LP
448 setup->image_fd = safe_close(setup->image_fd);
449 }
450
32dda527
LP
451 if (setup->temporary_image_path) {
452 if (unlink(setup->temporary_image_path) < 0)
453 log_debug_errno(errno, "Failed to remove temporary image file '%s', ignoring: %m",
454 setup->temporary_image_path);
455
456 setup->temporary_image_path = mfree(setup->temporary_image_path);
457 }
458
d26cdde3
LP
459 setup->key_serial = keyring_unlink(setup->key_serial);
460
70a5db58
LP
461 setup->undo_mount = false;
462 setup->undo_dm = false;
28a7f106
LP
463 setup->do_offline_fitrim = false;
464 setup->do_offline_fallocate = false;
565ac8b1 465 setup->do_mark_clean = false;
70a5db58
LP
466
467 setup->dm_name = mfree(setup->dm_name);
468 setup->dm_node = mfree(setup->dm_node);
469
470 setup->loop = loop_device_unref(setup->loop);
70a5db58 471
fc4941d6 472 setup->volume_key = erase_and_free(setup->volume_key);
70a5db58
LP
473 setup->volume_key_size = 0;
474
86019efa
LP
475 if (setup->do_drop_caches)
476 drop_caches_now();
477
bf15879b
LP
478 setup->mount_suffix = mfree(setup->mount_suffix);
479
70a5db58
LP
480 return r;
481}
482
aa0a6214 483int home_setup(
70a5db58 484 UserRecord *h,
e1df968b 485 HomeSetupFlags flags,
70a5db58 486 HomeSetup *setup,
c00b2ddc 487 PasswordCache *cache,
70a5db58
LP
488 UserRecord **ret_header_home) {
489
490 int r;
491
492 assert(h);
493 assert(setup);
494 assert(!setup->loop);
495 assert(!setup->crypt_device);
496 assert(setup->root_fd < 0);
497 assert(!setup->undo_dm);
498 assert(!setup->undo_mount);
499
500 /* Makes a home directory accessible (through the root_fd file descriptor, not by path!). */
501
e1df968b 502 if (!FLAGS_SET(flags, HOME_SETUP_ALREADY_ACTIVATED)) /* If we set up the directory, we should also drop caches once we are done */
86019efa
LP
503 setup->do_drop_caches = setup->do_drop_caches || user_record_drop_caches(h);
504
70a5db58
LP
505 switch (user_record_storage(h)) {
506
507 case USER_LUKS:
c00b2ddc 508 return home_setup_luks(h, flags, NULL, setup, cache, ret_header_home);
70a5db58
LP
509
510 case USER_SUBVOLUME:
511 case USER_DIRECTORY:
e1df968b 512 r = home_setup_directory(h, setup);
70a5db58
LP
513 break;
514
515 case USER_FSCRYPT:
c00b2ddc 516 r = home_setup_fscrypt(h, setup, cache);
70a5db58
LP
517 break;
518
519 case USER_CIFS:
e1df968b 520 r = home_setup_cifs(h, flags, setup);
70a5db58
LP
521 break;
522
523 default:
524 return log_error_errno(SYNTHETIC_ERRNO(ENOLINK), "Processing home directories of type '%s' currently not supported.", user_storage_to_string(user_record_storage(h)));
525 }
526
527 if (r < 0)
528 return r;
529
530 if (ret_header_home)
531 *ret_header_home = NULL;
532
533 return r;
534}
535
536int home_sync_and_statfs(int root_fd, struct statfs *ret) {
537 assert(root_fd >= 0);
538
539 /* Let's sync this to disk, so that the disk space reported by fstatfs() below is accurate (for file
540 * systems such as btrfs where this is determined lazily). */
541
542 if (syncfs(root_fd) < 0)
543 return log_error_errno(errno, "Failed to synchronize file system: %m");
544
545 if (ret)
546 if (fstatfs(root_fd, ret) < 0)
547 return log_error_errno(errno, "Failed to statfs() file system: %m");
548
549 log_info("Synchronized disk.");
550
551 return 0;
552}
553
309a747f 554static int read_identity_file(int root_fd, sd_json_variant **ret) {
5d2a48da 555 _cleanup_fclose_ FILE *identity_file = NULL;
254d1313 556 _cleanup_close_ int identity_fd = -EBADF;
70a5db58
LP
557 int r;
558
559 assert(root_fd >= 0);
560 assert(ret);
561
562 identity_fd = openat(root_fd, ".identity", O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW|O_NONBLOCK);
563 if (identity_fd < 0)
564 return log_error_errno(errno, "Failed to open .identity file in home directory: %m");
565
566 r = fd_verify_regular(identity_fd);
567 if (r < 0)
568 return log_error_errno(r, "Embedded identity file is not a regular file, refusing: %m");
569
4fa744a3 570 identity_file = take_fdopen(&identity_fd, "r");
70a5db58
LP
571 if (!identity_file)
572 return log_oom();
573
9df18e4b 574 unsigned line = 0, column = 0;
309a747f 575 r = sd_json_parse_file(identity_file, ".identity", SD_JSON_PARSE_SENSITIVE, ret, &line, &column);
70a5db58
LP
576 if (r < 0)
577 return log_error_errno(r, "[.identity:%u:%u] Failed to parse JSON data: %m", line, column);
578
579 log_info("Read embedded .identity file.");
580
581 return 0;
582}
583
309a747f
LP
584static int write_identity_file(int root_fd, sd_json_variant *v, uid_t uid) {
585 _cleanup_(sd_json_variant_unrefp) sd_json_variant *normalized = NULL;
5d2a48da 586 _cleanup_fclose_ FILE *identity_file = NULL;
254d1313 587 _cleanup_close_ int identity_fd = -EBADF;
70a5db58
LP
588 _cleanup_free_ char *fn = NULL;
589 int r;
590
591 assert(root_fd >= 0);
592 assert(v);
593
309a747f 594 normalized = sd_json_variant_ref(v);
70a5db58 595
309a747f 596 r = sd_json_variant_normalize(&normalized);
70a5db58
LP
597 if (r < 0)
598 log_warning_errno(r, "Failed to normalize user record, ignoring: %m");
599
600 r = tempfn_random(".identity", NULL, &fn);
601 if (r < 0)
602 return r;
603
604 identity_fd = openat(root_fd, fn, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW, 0600);
605 if (identity_fd < 0)
606 return log_error_errno(errno, "Failed to create .identity file in home directory: %m");
607
4fa744a3 608 identity_file = take_fdopen(&identity_fd, "w");
70a5db58
LP
609 if (!identity_file) {
610 r = log_oom();
611 goto fail;
612 }
613
309a747f 614 sd_json_variant_dump(normalized, SD_JSON_FORMAT_PRETTY, identity_file, NULL);
70a5db58
LP
615
616 r = fflush_and_check(identity_file);
617 if (r < 0) {
618 log_error_errno(r, "Failed to write .identity file: %m");
619 goto fail;
620 }
621
622 if (fchown(fileno(identity_file), uid, uid) < 0) {
b05f4495 623 r = log_error_errno(errno, "Failed to change ownership of identity file: %m");
70a5db58
LP
624 goto fail;
625 }
626
627 if (renameat(root_fd, fn, root_fd, ".identity") < 0) {
628 r = log_error_errno(errno, "Failed to move identity file into place: %m");
629 goto fail;
630 }
631
632 log_info("Wrote embedded .identity file.");
633
634 return 0;
635
636fail:
637 (void) unlinkat(root_fd, fn, 0);
638 return r;
639}
640
641int home_load_embedded_identity(
642 UserRecord *h,
643 int root_fd,
644 UserRecord *header_home,
645 UserReconcileMode mode,
7b78db28 646 PasswordCache *cache,
70a5db58
LP
647 UserRecord **ret_embedded_home,
648 UserRecord **ret_new_home) {
649
650 _cleanup_(user_record_unrefp) UserRecord *embedded_home = NULL, *intermediate_home = NULL, *new_home = NULL;
309a747f 651 _cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL;
70a5db58
LP
652 int r;
653
654 assert(h);
655 assert(root_fd >= 0);
656
657 r = read_identity_file(root_fd, &v);
658 if (r < 0)
659 return r;
660
661 embedded_home = user_record_new();
662 if (!embedded_home)
663 return log_oom();
664
bfc0cc1a 665 r = user_record_load(embedded_home, v, USER_RECORD_LOAD_EMBEDDED|USER_RECORD_PERMISSIVE);
70a5db58
LP
666 if (r < 0)
667 return r;
668
669 if (!user_record_compatible(h, embedded_home))
80ace4f2 670 return log_error_errno(SYNTHETIC_ERRNO(EREMCHG), "Embedded home record not compatible with host record, refusing.");
70a5db58
LP
671
672 /* Insist that credentials the user supplies also unlocks any embedded records. */
7b78db28 673 r = user_record_authenticate(embedded_home, h, cache, /* strict_verify= */ true);
70a5db58
LP
674 if (r < 0)
675 return r;
c8f145ad 676 assert(r > 0); /* Insist that a password was verified */
70a5db58
LP
677
678 /* At this point we have three records to deal with:
679 *
680 * · The record we got passed from the host
681 * · The record included in the LUKS header (only if LUKS is used)
285ad523 682 * · The record in the home directory itself (~/.identity)
70a5db58
LP
683 *
684 * Now we have to reconcile all three, and let the newest one win. */
685
686 if (header_home) {
687 /* Note we relax the requirements here. Instead of insisting that the host record is strictly
688 * newer, let's also be OK if its equally new. If it is, we'll however insist that the
689 * embedded record must be newer, so that we update at least one of the two. */
690
691 r = user_record_reconcile(h, header_home, mode == USER_RECONCILE_REQUIRE_NEWER ? USER_RECONCILE_REQUIRE_NEWER_OR_EQUAL : mode, &intermediate_home);
692 if (r == -EREMCHG) /* this was supposed to be checked earlier already, but let's check this again */
693 return log_error_errno(r, "Identity stored on host and in header don't match, refusing.");
694 if (r == -ESTALE)
695 return log_error_errno(r, "Embedded identity record is newer than supplied record, refusing.");
696 if (r < 0)
697 return log_error_errno(r, "Failed to reconcile host and header identities: %m");
698 if (r == USER_RECONCILE_EMBEDDED_WON)
699 log_info("Reconciling header user identity completed (header version was newer).");
700 else if (r == USER_RECONCILE_HOST_WON) {
701 log_info("Reconciling header user identity completed (host version was newer).");
702
703 if (mode == USER_RECONCILE_REQUIRE_NEWER) /* Host version is newer than the header
704 * version, hence we'll update
705 * something. This means we can relax the
706 * requirements on the embedded
707 * identity. */
708 mode = USER_RECONCILE_REQUIRE_NEWER_OR_EQUAL;
709 } else {
710 assert(r == USER_RECONCILE_IDENTICAL);
711 log_info("Reconciling user identities completed (host and header version were identical).");
712 }
713
714 h = intermediate_home;
715 }
716
717 r = user_record_reconcile(h, embedded_home, mode, &new_home);
718 if (r == -EREMCHG)
719 return log_error_errno(r, "Identity stored on host and in home don't match, refusing.");
720 if (r == -ESTALE)
721 return log_error_errno(r, "Embedded identity record is equally new or newer than supplied record, refusing.");
722 if (r < 0)
723 return log_error_errno(r, "Failed to reconcile host and embedded identities: %m");
724 if (r == USER_RECONCILE_EMBEDDED_WON)
725 log_info("Reconciling embedded user identity completed (embedded version was newer).");
726 else if (r == USER_RECONCILE_HOST_WON)
727 log_info("Reconciling embedded user identity completed (host version was newer).");
728 else {
729 assert(r == USER_RECONCILE_IDENTICAL);
730 log_info("Reconciling embedded user identity completed (host and embedded version were identical).");
731 }
732
733 if (ret_embedded_home)
734 *ret_embedded_home = TAKE_PTR(embedded_home);
735
736 if (ret_new_home)
737 *ret_new_home = TAKE_PTR(new_home);
738
17ac40e4 739 return r; /* We pass along who won the reconciliation */
70a5db58
LP
740}
741
285ad523 742int home_store_embedded_identity(UserRecord *h, int root_fd, UserRecord *old_home) {
70a5db58
LP
743 _cleanup_(user_record_unrefp) UserRecord *embedded = NULL;
744 int r;
745
746 assert(h);
747 assert(root_fd >= 0);
70a5db58 748
bfc0cc1a 749 r = user_record_clone(h, USER_RECORD_EXTRACT_EMBEDDED|USER_RECORD_PERMISSIVE, &embedded);
70a5db58
LP
750 if (r < 0)
751 return log_error_errno(r, "Failed to determine new embedded record: %m");
752
753 if (old_home && user_record_equal(old_home, embedded)) {
754 log_debug("Not updating embedded home record.");
755 return 0;
756 }
757
758 /* The identity has changed, let's update it in the image */
759 r = write_identity_file(root_fd, embedded->json, h->uid);
760 if (r < 0)
761 return r;
762
763 return 1;
764}
765
766static const char *file_system_type_fd(int fd) {
767 struct statfs sfs;
768
769 assert(fd >= 0);
770
771 if (fstatfs(fd, &sfs) < 0) {
772 log_debug_errno(errno, "Failed to statfs(): %m");
773 return NULL;
774 }
775
7c604e89 776 return fs_type_to_string(sfs.f_type);
70a5db58
LP
777}
778
779int home_extend_embedded_identity(UserRecord *h, UserRecord *used, HomeSetup *setup) {
780 int r;
781
782 assert(h);
783 assert(used);
784 assert(setup);
785
786 r = user_record_add_binding(
787 h,
788 user_record_storage(used),
789 user_record_image_path(used),
790 setup->found_partition_uuid,
791 setup->found_luks_uuid,
792 setup->found_fs_uuid,
71eceff6
LP
793 setup->crypt_device ? sym_crypt_get_cipher(setup->crypt_device) : NULL,
794 setup->crypt_device ? sym_crypt_get_cipher_mode(setup->crypt_device) : NULL,
70a5db58
LP
795 setup->crypt_device ? luks_volume_key_size_convert(setup->crypt_device) : UINT64_MAX,
796 file_system_type_fd(setup->root_fd),
797 user_record_home_directory(used),
798 used->uid,
799 (gid_t) used->uid);
800 if (r < 0)
801 return log_error_errno(r, "Failed to update binding in record: %m");
802
803 return 0;
804}
805
806static int chown_recursive_directory(int root_fd, uid_t uid) {
807 int r;
808
809 assert(root_fd >= 0);
810 assert(uid_is_valid(uid));
811
812 r = fd_chown_recursive(root_fd, uid, (gid_t) uid, 0777);
813 if (r < 0)
814 return log_error_errno(r, "Failed to change ownership of files and directories: %m");
815 if (r == 0)
816 log_info("Recursive changing of ownership not necessary, skipped.");
817 else
818 log_info("Recursive changing of ownership completed.");
819
820 return 0;
821}
822
cf5115f6
LP
823int home_maybe_shift_uid(
824 UserRecord *h,
6f2c8136 825 HomeSetupFlags flags,
cf5115f6
LP
826 HomeSetup *setup) {
827
254d1313 828 _cleanup_close_ int mount_fd = -EBADF;
cf5115f6
LP
829 struct stat st;
830
831 assert(h);
832 assert(setup);
833 assert(setup->root_fd >= 0);
834
6f2c8136
LP
835 /* If the home dir is already activated, then the UID shift is already applied. */
836 if (FLAGS_SET(flags, HOME_SETUP_ALREADY_ACTIVATED))
837 return 0;
838
cf5115f6
LP
839 if (fstat(setup->root_fd, &st) < 0)
840 return log_error_errno(errno, "Failed to stat() home directory: %m");
841
842 /* Let's shift UIDs of this mount. Hopefully this makes the later chowning unnecessary. (Note that we
843 * also prefer to do UID mapping even if the UID already matches our goal UID. That's because we want
844 * to leave UIDs in the homed managed range unmapped.) */
845 (void) home_shift_uid(setup->root_fd, NULL, st.st_uid, h->uid, &mount_fd);
846
847 /* If this worked, then we'll have a reference to the mount now, which we can also use like an O_PATH
848 * fd to the new dir. Let's convert it into a proper O_DIRECTORY fd. */
849 if (mount_fd >= 0) {
850 safe_close(setup->root_fd);
851
852 setup->root_fd = fd_reopen(mount_fd, O_RDONLY|O_CLOEXEC|O_DIRECTORY);
853 if (setup->root_fd < 0)
854 return log_error_errno(setup->root_fd, "Failed to convert mount fd into regular directory fd: %m");
855 }
856
857 return 0;
858}
859
70a5db58
LP
860int home_refresh(
861 UserRecord *h,
6f2c8136 862 HomeSetupFlags flags,
70a5db58
LP
863 HomeSetup *setup,
864 UserRecord *header_home,
7b78db28 865 PasswordCache *cache,
70a5db58
LP
866 struct statfs *ret_statfs,
867 UserRecord **ret_new_home) {
868
869 _cleanup_(user_record_unrefp) UserRecord *embedded_home = NULL, *new_home = NULL;
17ac40e4 870 int r, reconciled;
70a5db58
LP
871
872 assert(h);
873 assert(setup);
874 assert(ret_new_home);
875
876 /* When activating a home directory, does the identity work: loads the identity from the $HOME
877 * directory, reconciles it with our idea, chown()s everything. */
878
17ac40e4
AV
879 reconciled = home_load_embedded_identity(h, setup->root_fd, header_home, USER_RECONCILE_ANY, cache, &embedded_home, &new_home);
880 if (reconciled < 0)
881 return reconciled;
70a5db58 882
6f2c8136 883 r = home_maybe_shift_uid(h, flags, setup);
cf5115f6
LP
884 if (r < 0)
885 return r;
886
70a5db58
LP
887 r = home_store_header_identity_luks(new_home, setup, header_home);
888 if (r < 0)
889 return r;
890
285ad523 891 r = home_store_embedded_identity(new_home, setup->root_fd, embedded_home);
70a5db58
LP
892 if (r < 0)
893 return r;
894
17ac40e4
AV
895 r = home_reconcile_blob_dirs(new_home, setup->root_fd, reconciled);
896 if (r < 0)
897 return r;
898
70a5db58
LP
899 r = chown_recursive_directory(setup->root_fd, h->uid);
900 if (r < 0)
901 return r;
902
903 r = home_sync_and_statfs(setup->root_fd, ret_statfs);
904 if (r < 0)
905 return r;
906
907 *ret_new_home = TAKE_PTR(new_home);
908 return 0;
909}
910
911static int home_activate(UserRecord *h, UserRecord **ret_home) {
a74e2e44 912 _cleanup_(home_setup_done) HomeSetup setup = HOME_SETUP_INIT;
70a5db58 913 _cleanup_(user_record_unrefp) UserRecord *new_home = NULL;
a74e2e44 914 _cleanup_(password_cache_free) PasswordCache cache = {};
6f2c8136 915 HomeSetupFlags flags = 0;
70a5db58
LP
916 int r;
917
918 assert(h);
919
920 if (!h->user_name)
921 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "User record lacks user name, refusing.");
922 if (!uid_is_valid(h->uid))
923 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "User record lacks UID, refusing.");
924 if (!IN_SET(user_record_storage(h), USER_LUKS, USER_DIRECTORY, USER_SUBVOLUME, USER_FSCRYPT, USER_CIFS))
925 return log_error_errno(SYNTHETIC_ERRNO(ENOTTY), "Activating home directories of type '%s' currently not supported.", user_storage_to_string(user_record_storage(h)));
926
7b78db28 927 r = user_record_authenticate(h, h, &cache, /* strict_verify= */ false);
70a5db58
LP
928 if (r < 0)
929 return r;
930
931 r = user_record_test_home_directory_and_warn(h);
932 if (r < 0)
933 return r;
934 if (r == USER_TEST_MOUNTED)
935 return log_error_errno(SYNTHETIC_ERRNO(EALREADY), "Home directory %s is already mounted, refusing.", user_record_home_directory(h));
936
937 r = user_record_test_image_path_and_warn(h);
938 if (r < 0)
939 return r;
940 if (r == USER_TEST_ABSENT)
2cf95e51 941 return log_error_errno(SYNTHETIC_ERRNO(ENETUNREACH), "Image path %s is missing, refusing.", user_record_image_path(h));
70a5db58
LP
942
943 switch (user_record_storage(h)) {
944
945 case USER_LUKS:
6f2c8136 946 r = home_activate_luks(h, flags, &setup, &cache, &new_home);
70a5db58
LP
947 break;
948
949 case USER_SUBVOLUME:
950 case USER_DIRECTORY:
951 case USER_FSCRYPT:
6f2c8136 952 r = home_activate_directory(h, flags, &setup, &cache, &new_home);
70a5db58
LP
953 break;
954
955 case USER_CIFS:
6f2c8136 956 r = home_activate_cifs(h, flags, &setup, &cache, &new_home);
70a5db58
LP
957 break;
958
959 default:
04499a70 960 assert_not_reached();
70a5db58 961 }
9ef81389
LP
962 if (r < 0)
963 return r;
70a5db58
LP
964
965 /* Note that the returned object might either be a reference to an updated version of the existing
966 * home object, or a reference to a newly allocated home object. The caller has to be able to deal
967 * with both, and consider the old object out-of-date. */
968 if (user_record_equal(h, new_home)) {
969 *ret_home = NULL;
970 return 0; /* no identity change */
971 }
972
973 *ret_home = TAKE_PTR(new_home);
974 return 1; /* identity updated */
975}
976
977static int home_deactivate(UserRecord *h, bool force) {
fc032ae1 978 _cleanup_(home_setup_done) HomeSetup setup = HOME_SETUP_INIT;
26191000 979 _cleanup_(password_cache_free) PasswordCache cache = {};
70a5db58
LP
980 bool done = false;
981 int r;
982
983 assert(h);
984
985 if (!h->user_name)
986 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "User record incomplete, refusing.");
987 if (!IN_SET(user_record_storage(h), USER_LUKS, USER_DIRECTORY, USER_SUBVOLUME, USER_FSCRYPT, USER_CIFS))
988 return log_error_errno(SYNTHETIC_ERRNO(ENOTTY), "Deactivating home directories of type '%s' currently not supported.", user_storage_to_string(user_record_storage(h)));
989
990 r = user_record_test_home_directory_and_warn(h);
991 if (r < 0)
992 return r;
993 if (r == USER_TEST_MOUNTED) {
a71a0693
LP
994 /* Before we do anything, let's move the home mount away. */
995 r = home_unshare_and_mkdir();
996 if (r < 0)
997 return r;
28a7f106 998
a71a0693
LP
999 r = mount_nofollow_verbose(LOG_ERR, user_record_home_directory(h), HOME_RUNTIME_WORK_DIR, NULL, MS_BIND, NULL);
1000 if (r < 0)
1001 return r;
1002
1003 setup.undo_mount = true; /* remember to unmount the new bind mount from HOME_RUNTIME_WORK_DIR */
1004
1005 /* Let's explicitly open the new root fs, using the moved path */
1006 setup.root_fd = open(HOME_RUNTIME_WORK_DIR, O_RDONLY|O_DIRECTORY|O_CLOEXEC);
1007 if (setup.root_fd < 0)
1008 return log_error_errno(errno, "Failed to open moved home directory: %m");
1009
1010 /* Now get rid of the home at its original place (we only keep the bind mount we created above) */
1011 r = umount_verbose(LOG_ERR, user_record_home_directory(h), UMOUNT_NOFOLLOW | (force ? MNT_FORCE|MNT_DETACH : 0));
86019efa 1012 if (r < 0)
a71a0693
LP
1013 return r;
1014
d26cdde3
LP
1015 if (user_record_storage(h) == USER_LUKS) {
1016 /* Automatically shrink on logout if that's enabled. To be able to shrink we need the
1017 * keys to the device. */
1018 password_cache_load_keyring(h, &cache);
a71a0693 1019 (void) home_trim_luks(h, &setup);
d26cdde3 1020 }
a71a0693
LP
1021
1022 /* Sync explicitly, so that the drop caches logic below can work as documented */
1023 if (syncfs(setup.root_fd) < 0)
1024 log_debug_errno(errno, "Failed to synchronize home directory, ignoring: %m");
86019efa
LP
1025 else
1026 log_info("Syncing completed.");
1027
26191000
LP
1028 if (user_record_storage(h) == USER_LUKS)
1029 (void) home_auto_shrink_luks(h, &setup, &cache);
1030
a71a0693
LP
1031 setup.root_fd = safe_close(setup.root_fd);
1032
1033 /* Now get rid of the bind mount, too */
1034 r = umount_verbose(LOG_ERR, HOME_RUNTIME_WORK_DIR, UMOUNT_NOFOLLOW | (force ? MNT_FORCE|MNT_DETACH : 0));
1035 if (r < 0)
1036 return r;
1037
1038 setup.undo_mount = false; /* Remember that the bind mount doesn't need to be unmounted anymore */
1039
1040 if (user_record_drop_caches(h))
1041 setup.do_drop_caches = true;
70a5db58
LP
1042
1043 log_info("Unmounting completed.");
1044 done = true;
1045 } else
1046 log_info("Directory %s is already unmounted.", user_record_home_directory(h));
1047
1048 if (user_record_storage(h) == USER_LUKS) {
fc032ae1 1049 r = home_deactivate_luks(h, &setup);
70a5db58
LP
1050 if (r < 0)
1051 return r;
1052 if (r > 0)
1053 done = true;
1054 }
1055
d26cdde3
LP
1056 /* Explicitly flush any per-user key from the keyring */
1057 (void) keyring_flush(h);
1058
70a5db58
LP
1059 if (!done)
1060 return log_error_errno(SYNTHETIC_ERRNO(ENOEXEC), "Home is not active.");
1061
a71a0693
LP
1062 if (setup.do_drop_caches) {
1063 setup.do_drop_caches = false;
86019efa 1064 drop_caches_now();
a71a0693 1065 }
86019efa 1066
70a5db58
LP
1067 log_info("Everything completed.");
1068 return 0;
1069}
1070
05e64ea4 1071static int copy_skel(UserRecord *h, int root_fd, const char *skel) {
1e0e7c74 1072 _cleanup_close_ int skel_fd = -EBADF;
70a5db58
LP
1073 int r;
1074
05e64ea4 1075 assert(h);
70a5db58
LP
1076 assert(root_fd >= 0);
1077
1e0e7c74 1078 r = chase(skel, /* root= */ NULL, CHASE_MUST_BE_DIRECTORY, /* ret_path= */ NULL, &skel_fd);
70a5db58
LP
1079 if (r == -ENOENT) {
1080 log_info("Skeleton directory %s missing, ignoring.", skel);
1081 return 0;
1082 }
1e0e7c74
DDM
1083
1084 r = copy_tree_at(
1085 skel_fd, /* from= */ NULL,
1086 root_fd, ".",
1087 h->uid, user_record_gid(h),
1088 COPY_MERGE|COPY_REPLACE,
1089 /* denylist= */ NULL,
1090 /* subvolumes= */ NULL);
70a5db58
LP
1091 if (r < 0)
1092 return log_error_errno(r, "Failed to copy in %s: %m", skel);
1093
1094 log_info("Copying in %s completed.", skel);
1095 return 0;
1096}
1097
1098static int change_access_mode(int root_fd, mode_t m) {
1099 assert(root_fd >= 0);
1100
1101 if (fchmod(root_fd, m) < 0)
1102 return log_error_errno(errno, "Failed to change access mode of top-level directory: %m");
1103
1104 log_info("Changed top-level directory access mode to 0%o.", m);
1105 return 0;
1106}
1107
1108int home_populate(UserRecord *h, int dir_fd) {
1109 int r;
1110
1111 assert(h);
1112 assert(dir_fd >= 0);
1113
05e64ea4 1114 r = copy_skel(h, dir_fd, user_record_skeleton_directory(h));
70a5db58
LP
1115 if (r < 0)
1116 return r;
1117
285ad523 1118 r = home_store_embedded_identity(h, dir_fd, NULL);
70a5db58
LP
1119 if (r < 0)
1120 return r;
1121
17ac40e4
AV
1122 r = home_reconcile_blob_dirs(h, dir_fd, USER_RECONCILE_HOST_WON);
1123 if (r < 0)
1124 return r;
1125
70a5db58
LP
1126 r = chown_recursive_directory(dir_fd, h->uid);
1127 if (r < 0)
1128 return r;
1129
1130 r = change_access_mode(dir_fd, user_record_access_mode(h));
1131 if (r < 0)
1132 return r;
1133
1134 return 0;
1135}
1136
1137static int user_record_compile_effective_passwords(
1138 UserRecord *h,
7b78db28
LP
1139 PasswordCache *cache,
1140 char ***ret_effective_passwords) {
70a5db58 1141
5d2a48da 1142 _cleanup_strv_free_erase_ char **effective = NULL;
70a5db58
LP
1143 int r;
1144
1145 assert(h);
7b78db28 1146 assert(cache);
70a5db58
LP
1147
1148 /* We insist on at least one classic hashed password to be defined in addition to any PKCS#11 one, as
1149 * a safe fallback, but also to simplify the password changing algorithm: there we require providing
1150 * the old literal password only (and do not care for the old PKCS#11 token) */
1151
1152 if (strv_isempty(h->hashed_password))
d7a0f1f4
FS
1153 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
1154 "User record has no hashed passwords, refusing.");
70a5db58
LP
1155
1156 /* Generates the list of plaintext passwords to propagate to LUKS/fscrypt devices, and checks whether
1157 * we have a plaintext password for each hashed one. If we are missing one we'll fail, since we
1158 * couldn't sync fscrypt/LUKS to the login account properly. */
1159
1160 STRV_FOREACH(i, h->hashed_password) {
1161 bool found = false;
70a5db58
LP
1162
1163 log_debug("Looking for plaintext password for: %s", *i);
1164
1165 /* Let's scan all provided plaintext passwords */
1166 STRV_FOREACH(j, h->password) {
1167 r = test_password_one(*i, *j);
1168 if (r < 0)
87d7893c 1169 return log_error_errno(r, "Failed to test plaintext password: %m");
70a5db58
LP
1170 if (r > 0) {
1171 if (ret_effective_passwords) {
1172 r = strv_extend(&effective, *j);
1173 if (r < 0)
1174 return log_oom();
1175 }
1176
1177 log_debug("Found literal plaintext password.");
1178 found = true;
1179 break;
1180 }
1181 }
1182
1183 if (!found)
1184 return log_error_errno(SYNTHETIC_ERRNO(ENOKEY), "Missing plaintext password for defined hashed password");
1185 }
1186
3b09af20 1187 FOREACH_ARRAY(i, h->recovery_key, h->n_recovery_key) {
87d7893c 1188 bool found = false;
87d7893c 1189
3b09af20 1190 log_debug("Looking for plaintext recovery key for: %s", i->hashed_password);
87d7893c
LP
1191
1192 STRV_FOREACH(j, h->password) {
1193 _cleanup_(erase_and_freep) char *mangled = NULL;
1194 const char *p;
1195
3b09af20 1196 if (streq(i->type, "modhex64")) {
87d7893c
LP
1197 r = normalize_recovery_key(*j, &mangled);
1198 if (r == -EINVAL) /* Not properly formatted, probably a regular password. */
1199 continue;
1200 if (r < 0)
1201 return log_error_errno(r, "Failed to normalize recovery key: %m");
1202
1203 p = mangled;
1204 } else
1205 p = *j;
1206
3b09af20 1207 r = test_password_one(i->hashed_password, p);
87d7893c
LP
1208 if (r < 0)
1209 return log_error_errno(r, "Failed to test plaintext recovery key: %m");
1210 if (r > 0) {
1211 if (ret_effective_passwords) {
1212 r = strv_extend(&effective, p);
1213 if (r < 0)
1214 return log_oom();
1215 }
1216
1217 log_debug("Found plaintext recovery key.");
1218 found = true;
1219 break;
1220 }
1221 }
1222
1223 if (!found)
3b09af20
MY
1224 return log_error_errno(SYNTHETIC_ERRNO(EREMOTEIO),
1225 "Missing plaintext recovery key for defined recovery key.");
87d7893c
LP
1226 }
1227
3b09af20 1228 FOREACH_ARRAY(i, h->pkcs11_encrypted_key, h->n_pkcs11_encrypted_key) {
70a5db58
LP
1229#if HAVE_P11KIT
1230 _cleanup_(pkcs11_callback_data_release) struct pkcs11_callback_data data = {
1231 .user_record = h,
1232 .secret = h,
3b09af20 1233 .encrypted_key = i,
70a5db58
LP
1234 };
1235
1236 r = pkcs11_find_token(data.encrypted_key->uri, pkcs11_callback, &data);
1237 if (r == -EAGAIN)
1238 return -EBADSLT;
1239 if (r < 0)
1240 return r;
1241
1242 r = test_password_one(data.encrypted_key->hashed_password, data.decrypted_password);
1243 if (r < 0)
1244 return log_error_errno(r, "Failed to test PKCS#11 password: %m");
1245 if (r == 0)
1246 return log_error_errno(SYNTHETIC_ERRNO(EPERM), "Decrypted password from token is not correct, refusing.");
1247
1248 if (ret_effective_passwords) {
1249 r = strv_extend(&effective, data.decrypted_password);
1250 if (r < 0)
1251 return log_oom();
1252 }
1253
7b78db28
LP
1254 r = strv_extend(&cache->pkcs11_passwords, data.decrypted_password);
1255 if (r < 0)
1256 return log_oom();
1257#else
1258 return -EBADSLT;
1259#endif
1260 }
1261
3b09af20 1262 FOREACH_ARRAY(i, h->fido2_hmac_salt, h->n_fido2_hmac_salt) {
7b78db28
LP
1263#if HAVE_LIBFIDO2
1264 _cleanup_(erase_and_freep) char *decrypted_password = NULL;
1265
3b09af20 1266 r = fido2_use_token(h, h, i, &decrypted_password);
7b78db28
LP
1267 if (r < 0)
1268 return r;
1269
3b09af20 1270 r = test_password_one(i->hashed_password, decrypted_password);
7b78db28
LP
1271 if (r < 0)
1272 return log_error_errno(r, "Failed to test FIDO2 password: %m");
1273 if (r == 0)
3b09af20
MY
1274 return log_error_errno(SYNTHETIC_ERRNO(EPERM),
1275 "Decrypted password from token is not correct, refusing.");
7b78db28
LP
1276
1277 if (ret_effective_passwords) {
1278 r = strv_extend(&effective, decrypted_password);
70a5db58
LP
1279 if (r < 0)
1280 return log_oom();
1281 }
7b78db28
LP
1282
1283 r = strv_extend(&cache->fido2_passwords, decrypted_password);
1284 if (r < 0)
1285 return log_oom();
70a5db58
LP
1286#else
1287 return -EBADSLT;
1288#endif
1289 }
1290
1291 if (ret_effective_passwords)
1292 *ret_effective_passwords = TAKE_PTR(effective);
70a5db58
LP
1293
1294 return 0;
1295}
1296
1dfe5de0
LP
1297static int determine_default_storage(UserStorage *ret) {
1298 UserStorage storage = _USER_STORAGE_INVALID;
1299 const char *e;
1300 int r;
1301
1302 assert(ret);
1303
1304 /* homed tells us via an environment variable which default storage to use */
1305 e = getenv("SYSTEMD_HOME_DEFAULT_STORAGE");
1306 if (e) {
1307 storage = user_storage_from_string(e);
1308 if (storage < 0)
1309 log_warning("$SYSTEMD_HOME_DEFAULT_STORAGE set to invalid storage type, ignoring: %s", e);
1310 else {
1311 log_info("Using configured default storage '%s'.", user_storage_to_string(storage));
1312 *ret = storage;
1313 return 0;
1314 }
1315 }
1316
1317 /* When neither user nor admin specified the storage type to use, fix it to be LUKS — unless we run
1318 * in a container where loopback devices and LUKS/DM are not available. Also, if /home is encrypted
1319 * anyway, let's avoid duplicate encryption. Note that we typically default to the assumption of
1320 * "classic" storage for most operations. However, if we create a new home, then let's user LUKS if
1321 * nothing is specified. */
1322
1323 r = detect_container();
1324 if (r < 0)
1325 return log_error_errno(r, "Failed to determine whether we are in a container: %m");
1326 if (r == 0) {
2700fecd 1327 r = path_is_encrypted(get_home_root());
0608e2d3 1328 if (r > 0)
2700fecd 1329 log_info("%s is encrypted, not using '%s' storage, in order to avoid double encryption.", get_home_root(), user_storage_to_string(USER_LUKS));
0608e2d3
LP
1330 else {
1331 if (r < 0)
2700fecd 1332 log_warning_errno(r, "Failed to determine if %s is encrypted, ignoring: %m", get_home_root());
1dfe5de0 1333
0608e2d3
LP
1334 r = dlopen_cryptsetup();
1335 if (r < 0)
1336 log_info("Not using '%s' storage, since libcryptsetup could not be loaded.", user_storage_to_string(USER_LUKS));
1337 else {
1338 log_info("Using automatic default storage of '%s'.", user_storage_to_string(USER_LUKS));
1339 *ret = USER_LUKS;
1340 return 0;
1341 }
1342 }
1dfe5de0
LP
1343 } else
1344 log_info("Running in container, not using '%s' storage.", user_storage_to_string(USER_LUKS));
1345
2700fecd 1346 r = path_is_fs_type(get_home_root(), BTRFS_SUPER_MAGIC);
1dfe5de0 1347 if (r < 0)
2700fecd 1348 log_warning_errno(r, "Failed to determine file system of %s, ignoring: %m", get_home_root());
1dfe5de0 1349 if (r > 0) {
2700fecd 1350 log_info("%s is on btrfs, using '%s' as storage.", get_home_root(), user_storage_to_string(USER_SUBVOLUME));
1dfe5de0
LP
1351 *ret = USER_SUBVOLUME;
1352 } else {
2700fecd 1353 log_info("%s is on simple file system, using '%s' as storage.", get_home_root(), user_storage_to_string(USER_DIRECTORY));
1dfe5de0
LP
1354 *ret = USER_DIRECTORY;
1355 }
1356
1357 return 0;
1358}
1359
a4d72746 1360static int home_create(UserRecord *h, Hashmap *blobs, UserRecord **ret_home) {
5d2a48da 1361 _cleanup_strv_free_erase_ char **effective_passwords = NULL;
a74e2e44 1362 _cleanup_(home_setup_done) HomeSetup setup = HOME_SETUP_INIT;
70a5db58 1363 _cleanup_(user_record_unrefp) UserRecord *new_home = NULL;
7b78db28 1364 _cleanup_(password_cache_free) PasswordCache cache = {};
1dfe5de0
LP
1365 UserStorage new_storage = _USER_STORAGE_INVALID;
1366 const char *new_fs = NULL;
70a5db58
LP
1367 int r;
1368
1369 assert(h);
1370
1371 if (!h->user_name)
1372 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "User record lacks name, refusing.");
1373 if (!uid_is_valid(h->uid))
1374 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "User record lacks UID, refusing.");
1375
7b78db28 1376 r = user_record_compile_effective_passwords(h, &cache, &effective_passwords);
70a5db58
LP
1377 if (r < 0)
1378 return r;
1379
1380 r = user_record_test_home_directory_and_warn(h);
1381 if (r < 0)
1382 return r;
1383 if (r != USER_TEST_ABSENT)
1384 return log_error_errno(SYNTHETIC_ERRNO(EEXIST), "Home directory %s already exists, refusing.", user_record_home_directory(h));
1385
70a5db58 1386 if (h->storage < 0) {
1dfe5de0 1387 r = determine_default_storage(&new_storage);
70a5db58 1388 if (r < 0)
1dfe5de0
LP
1389 return r;
1390 }
70a5db58 1391
1dfe5de0
LP
1392 if ((h->storage == USER_LUKS ||
1393 (h->storage < 0 && new_storage == USER_LUKS)) &&
1394 !h->file_system_type)
1395 new_fs = getenv("SYSTEMD_HOME_DEFAULT_FILE_SYSTEM_TYPE");
70a5db58 1396
1dfe5de0 1397 if (new_storage >= 0 || new_fs) {
70a5db58
LP
1398 r = user_record_add_binding(
1399 h,
1400 new_storage,
1401 NULL,
1402 SD_ID128_NULL,
1403 SD_ID128_NULL,
1404 SD_ID128_NULL,
1405 NULL,
1406 NULL,
1407 UINT64_MAX,
1dfe5de0 1408 new_fs,
70a5db58
LP
1409 NULL,
1410 UID_INVALID,
1411 GID_INVALID);
1412 if (r < 0)
1413 return log_error_errno(r, "Failed to change storage type to LUKS: %m");
70a5db58
LP
1414 }
1415
1416 r = user_record_test_image_path_and_warn(h);
1417 if (r < 0)
1418 return r;
1419 if (!IN_SET(r, USER_TEST_ABSENT, USER_TEST_UNDEFINED, USER_TEST_MAYBE))
1420 return log_error_errno(SYNTHETIC_ERRNO(EEXIST), "Image path %s already exists, refusing.", user_record_image_path(h));
1421
a4d72746
AV
1422 r = home_apply_new_blob_dir(h, blobs);
1423 if (r < 0)
1424 return r;
1425
70a5db58
LP
1426 switch (user_record_storage(h)) {
1427
1428 case USER_LUKS:
bc5890c6 1429 r = home_create_luks(h, &setup, &cache, effective_passwords, &new_home);
70a5db58
LP
1430 break;
1431
1432 case USER_DIRECTORY:
1433 case USER_SUBVOLUME:
e1aeaf27 1434 r = home_create_directory_or_subvolume(h, &setup, &new_home);
70a5db58
LP
1435 break;
1436
1437 case USER_FSCRYPT:
655807f5 1438 r = home_create_fscrypt(h, &setup, effective_passwords, &new_home);
70a5db58
LP
1439 break;
1440
1441 case USER_CIFS:
a74e2e44 1442 r = home_create_cifs(h, &setup, &new_home);
70a5db58
LP
1443 break;
1444
1445 default:
1446 return log_error_errno(SYNTHETIC_ERRNO(ENOTTY),
1447 "Creating home directories of type '%s' currently not supported.", user_storage_to_string(user_record_storage(h)));
1448 }
1449 if (r < 0)
1450 return r;
1451
1452 if (user_record_equal(h, new_home)) {
1453 *ret_home = NULL;
1454 return 0;
1455 }
1456
1457 *ret_home = TAKE_PTR(new_home);
1458 return 1;
1459}
1460
1461static int home_remove(UserRecord *h) {
1462 bool deleted = false;
1463 const char *ip, *hd;
1464 int r;
1465
1466 assert(h);
1467
1468 if (!h->user_name)
1469 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "User record lacks user name, refusing.");
1470 if (!IN_SET(user_record_storage(h), USER_LUKS, USER_DIRECTORY, USER_SUBVOLUME, USER_FSCRYPT, USER_CIFS))
1471 return log_error_errno(SYNTHETIC_ERRNO(ENOTTY), "Removing home directories of type '%s' currently not supported.", user_storage_to_string(user_record_storage(h)));
1472
1473 hd = user_record_home_directory(h);
1474
1475 r = user_record_test_home_directory_and_warn(h);
1476 if (r < 0)
1477 return r;
1478 if (r == USER_TEST_MOUNTED)
1479 return log_error_errno(SYNTHETIC_ERRNO(EBUSY), "Directory %s is still mounted, refusing.", hd);
1480
1481 assert(hd);
1482
1483 r = user_record_test_image_path_and_warn(h);
1484 if (r < 0)
1485 return r;
1486
1487 ip = user_record_image_path(h);
1488
1489 switch (user_record_storage(h)) {
1490
1491 case USER_LUKS: {
1492 struct stat st;
1493
1494 assert(ip);
1495
1496 if (stat(ip, &st) < 0) {
6b8664cb 1497 if (errno != ENOENT)
80ace4f2 1498 return log_error_errno(errno, "Failed to stat() %s: %m", ip);
70a5db58
LP
1499
1500 } else {
1501 if (S_ISREG(st.st_mode)) {
1502 if (unlink(ip) < 0) {
1503 if (errno != ENOENT)
1504 return log_error_errno(errno, "Failed to remove %s: %m", ip);
86019efa
LP
1505 } else {
1506 _cleanup_free_ char *parent = NULL;
1507
70a5db58
LP
1508 deleted = true;
1509
86019efa
LP
1510 r = path_extract_directory(ip, &parent);
1511 if (r < 0)
1512 log_debug_errno(r, "Failed to determine parent directory of '%s': %m", ip);
1513 else {
1514 r = fsync_path_at(AT_FDCWD, parent);
1515 if (r < 0)
1516 log_debug_errno(r, "Failed to synchronize disk after deleting '%s', ignoring: %m", ip);
1517 }
1518 }
1519
70a5db58
LP
1520 } else if (S_ISBLK(st.st_mode))
1521 log_info("Not removing file system on block device %s.", ip);
1522 else
1523 return log_error_errno(SYNTHETIC_ERRNO(ENOTBLK), "Image file %s is neither block device, nor regular, refusing removal.", ip);
1524 }
1525
1526 break;
1527 }
1528
1529 case USER_SUBVOLUME:
1530 case USER_DIRECTORY:
1531 case USER_FSCRYPT:
1532 assert(ip);
1533
86019efa 1534 r = rm_rf(ip, REMOVE_ROOT|REMOVE_PHYSICAL|REMOVE_SUBVOLUME|REMOVE_SYNCFS);
70a5db58
LP
1535 if (r < 0) {
1536 if (r != -ENOENT)
1537 return log_warning_errno(r, "Failed to remove %s: %m", ip);
1538 } else
1539 deleted = true;
1540
1541 /* If the image path and the home directory are the same invalidate the home directory, so
1542 * that we don't remove it anymore */
1543 if (path_equal(ip, hd))
1544 hd = NULL;
1545
1546 break;
1547
1548 case USER_CIFS:
1549 /* Nothing else to do here: we won't remove remote stuff. */
1550 log_info("Not removing home directory on remote server.");
1551 break;
1552
1553 default:
04499a70 1554 assert_not_reached();
70a5db58
LP
1555 }
1556
1557 if (hd) {
1558 if (rmdir(hd) < 0) {
1559 if (errno != ENOENT)
1560 return log_error_errno(errno, "Failed to remove %s, ignoring: %m", hd);
1561 } else
1562 deleted = true;
1563 }
1564
86019efa
LP
1565 if (deleted) {
1566 if (user_record_drop_caches(h))
1567 drop_caches_now();
1568
70a5db58 1569 log_info("Everything completed.");
86019efa 1570 } else
e4ff0393
FS
1571 return log_notice_errno(SYNTHETIC_ERRNO(EALREADY),
1572 "Nothing to remove.");
70a5db58
LP
1573
1574 return 0;
1575}
1576
d94c7eef 1577static int home_basic_validate_update(UserRecord *h) {
70a5db58 1578 assert(h);
70a5db58
LP
1579
1580 if (!h->user_name)
1581 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "User record lacks user name, refusing.");
d94c7eef 1582
70a5db58
LP
1583 if (!uid_is_valid(h->uid))
1584 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "User record lacks UID, refusing.");
d94c7eef 1585
70a5db58
LP
1586 if (!IN_SET(user_record_storage(h), USER_LUKS, USER_DIRECTORY, USER_SUBVOLUME, USER_FSCRYPT, USER_CIFS))
1587 return log_error_errno(SYNTHETIC_ERRNO(ENOTTY), "Processing home directories of type '%s' currently not supported.", user_storage_to_string(user_record_storage(h)));
1588
d94c7eef
AV
1589 return 0;
1590}
1591
1592static int home_validate_update(UserRecord *h, HomeSetup *setup, HomeSetupFlags *flags) {
1593 bool has_mount = false;
1594 int r;
1595
1596 assert(h);
1597 assert(setup);
1598
1599 r = home_basic_validate_update(h);
1600 if (r < 0)
1601 return r;
1602
70a5db58
LP
1603 r = user_record_test_home_directory_and_warn(h);
1604 if (r < 0)
1605 return r;
1606
1607 has_mount = r == USER_TEST_MOUNTED;
1608
1609 r = user_record_test_image_path_and_warn(h);
1610 if (r < 0)
1611 return r;
1612 if (r == USER_TEST_ABSENT)
2cf95e51 1613 return log_error_errno(SYNTHETIC_ERRNO(ENETUNREACH), "Image path %s does not exist", user_record_image_path(h));
70a5db58
LP
1614
1615 switch (user_record_storage(h)) {
1616
1617 case USER_DIRECTORY:
1618 case USER_SUBVOLUME:
1619 case USER_FSCRYPT:
1620 case USER_CIFS:
1621 break;
1622
1623 case USER_LUKS: {
e1ab6635 1624 r = home_get_state_luks(h, setup);
70a5db58
LP
1625 if (r < 0)
1626 return r;
1627 if ((r > 0) != has_mount)
1628 return log_error_errno(SYNTHETIC_ERRNO(EBUSY), "Home mount incompletely set up.");
1629
1630 break;
1631 }
1632
1633 default:
04499a70 1634 assert_not_reached();
70a5db58
LP
1635 }
1636
e1df968b
LP
1637 if (flags)
1638 SET_FLAG(*flags, HOME_SETUP_ALREADY_ACTIVATED, has_mount);
1639
70a5db58
LP
1640 return has_mount; /* return true if the home record is already active */
1641}
1642
a4d72746 1643static int home_update(UserRecord *h, Hashmap *blobs, UserRecord **ret) {
70a5db58 1644 _cleanup_(user_record_unrefp) UserRecord *new_home = NULL, *header_home = NULL, *embedded_home = NULL;
66aa51f8 1645 _cleanup_(home_setup_done) HomeSetup setup = HOME_SETUP_INIT;
7b78db28 1646 _cleanup_(password_cache_free) PasswordCache cache = {};
e1df968b 1647 HomeSetupFlags flags = 0;
d94c7eef 1648 bool offline;
70a5db58
LP
1649 int r;
1650
1651 assert(h);
1652 assert(ret);
1653
d94c7eef 1654 offline = getenv_bool("SYSTEMD_HOMEWORK_UPDATE_OFFLINE") > 0;
5ec87d57 1655
d94c7eef
AV
1656 if (!offline) {
1657 password_cache_load_keyring(h, &cache);
70a5db58 1658
d94c7eef
AV
1659 r = user_record_authenticate(h, h, &cache, /* strict_verify= */ true);
1660 if (r < 0)
1661 return r;
1662 assert(r > 0); /* Insist that a password was verified */
1663
1664 r = home_validate_update(h, &setup, &flags);
1665 } else {
1666 /* In offline mode we skip all authentication, since we're
1667 * not propagating anything into the home area. The new home
1668 * records's authentication will still be checked when the user
1669 * next logs in, so this is fine */
1670
1671 r = home_basic_validate_update(h);
1672 }
70a5db58
LP
1673 if (r < 0)
1674 return r;
1675
a4d72746
AV
1676 r = home_apply_new_blob_dir(h, blobs);
1677 if (r < 0)
1678 return r;
1679
d94c7eef
AV
1680 if (offline) {
1681 log_info("Offline update requested. Not touching embedded records.");
1682 return user_record_clone(h, USER_RECORD_LOAD_MASK_SECRET|USER_RECORD_PERMISSIVE, ret);
1683 }
1684
c00b2ddc 1685 r = home_setup(h, flags, &setup, &cache, &header_home);
70a5db58
LP
1686 if (r < 0)
1687 return r;
1688
7b78db28 1689 r = home_load_embedded_identity(h, setup.root_fd, header_home, USER_RECONCILE_REQUIRE_NEWER, &cache, &embedded_home, &new_home);
70a5db58
LP
1690 if (r < 0)
1691 return r;
1692
a8be0984
LP
1693 r = home_maybe_shift_uid(h, flags, &setup);
1694 if (r < 0)
1695 return r;
1696
70a5db58
LP
1697 r = home_store_header_identity_luks(new_home, &setup, header_home);
1698 if (r < 0)
1699 return r;
1700
285ad523 1701 r = home_store_embedded_identity(new_home, setup.root_fd, embedded_home);
70a5db58
LP
1702 if (r < 0)
1703 return r;
1704
17ac40e4
AV
1705 r = home_reconcile_blob_dirs(new_home, setup.root_fd, USER_RECONCILE_HOST_WON);
1706 if (r < 0)
1707 return r;
1708
70a5db58
LP
1709 r = home_extend_embedded_identity(new_home, h, &setup);
1710 if (r < 0)
1711 return r;
1712
1713 r = home_sync_and_statfs(setup.root_fd, NULL);
1714 if (r < 0)
1715 return r;
1716
66aa51f8 1717 r = home_setup_done(&setup);
70a5db58
LP
1718 if (r < 0)
1719 return r;
1720
1721 log_info("Everything completed.");
1722
1723 *ret = TAKE_PTR(new_home);
1724 return 0;
1725}
1726
5ec87d57 1727static int home_resize(UserRecord *h, UserRecord **ret) {
66aa51f8 1728 _cleanup_(home_setup_done) HomeSetup setup = HOME_SETUP_INIT;
7b78db28 1729 _cleanup_(password_cache_free) PasswordCache cache = {};
e1df968b 1730 HomeSetupFlags flags = 0;
70a5db58
LP
1731 int r;
1732
1733 assert(h);
1734 assert(ret);
1735
1736 if (h->disk_size == UINT64_MAX)
1737 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "No target size specified, refusing.");
1738
5ec87d57 1739 password_cache_load_keyring(h, &cache);
70a5db58 1740
5ec87d57 1741 r = user_record_authenticate(h, h, &cache, /* strict_verify= */ true);
70a5db58
LP
1742 if (r < 0)
1743 return r;
5ec87d57 1744 assert(r > 0); /* Insist that a password was verified */
70a5db58 1745
5ec87d57
AV
1746 r = home_validate_update(h, &setup, &flags);
1747 if (r < 0)
1748 return r;
d357b80d 1749
70a5db58
LP
1750 switch (user_record_storage(h)) {
1751
1752 case USER_LUKS:
c00b2ddc 1753 return home_resize_luks(h, flags, &setup, &cache, ret);
70a5db58
LP
1754
1755 case USER_DIRECTORY:
1756 case USER_SUBVOLUME:
1757 case USER_FSCRYPT:
c00b2ddc 1758 return home_resize_directory(h, flags, &setup, &cache, ret);
70a5db58
LP
1759
1760 default:
1761 return log_error_errno(SYNTHETIC_ERRNO(ENOTTY), "Resizing home directories of type '%s' currently not supported.", user_storage_to_string(user_record_storage(h)));
1762 }
1763}
1764
1765static int home_passwd(UserRecord *h, UserRecord **ret_home) {
1766 _cleanup_(user_record_unrefp) UserRecord *header_home = NULL, *embedded_home = NULL, *new_home = NULL;
5d2a48da 1767 _cleanup_strv_free_erase_ char **effective_passwords = NULL;
66aa51f8 1768 _cleanup_(home_setup_done) HomeSetup setup = HOME_SETUP_INIT;
7b78db28 1769 _cleanup_(password_cache_free) PasswordCache cache = {};
e1df968b 1770 HomeSetupFlags flags = 0;
17ac40e4 1771 int r, reconciled;
70a5db58
LP
1772
1773 assert(h);
1774 assert(ret_home);
1775
1776 if (!IN_SET(user_record_storage(h), USER_LUKS, USER_DIRECTORY, USER_SUBVOLUME, USER_FSCRYPT))
1777 return log_error_errno(SYNTHETIC_ERRNO(ENOTTY), "Changing password of home directories of type '%s' currently not supported.", user_storage_to_string(user_record_storage(h)));
1778
7b78db28 1779 r = user_record_compile_effective_passwords(h, &cache, &effective_passwords);
70a5db58
LP
1780 if (r < 0)
1781 return r;
1782
e1df968b 1783 r = home_validate_update(h, &setup, &flags);
70a5db58
LP
1784 if (r < 0)
1785 return r;
1786
c00b2ddc 1787 r = home_setup(h, flags, &setup, &cache, &header_home);
70a5db58
LP
1788 if (r < 0)
1789 return r;
1790
17ac40e4
AV
1791 reconciled = home_load_embedded_identity(h, setup.root_fd, header_home, USER_RECONCILE_REQUIRE_NEWER_OR_EQUAL, &cache, &embedded_home, &new_home);
1792 if (reconciled < 0)
1793 return reconciled;
70a5db58 1794
a8be0984
LP
1795 r = home_maybe_shift_uid(h, flags, &setup);
1796 if (r < 0)
1797 return r;
1798
70a5db58
LP
1799 switch (user_record_storage(h)) {
1800
1801 case USER_LUKS:
d26cdde3 1802 r = home_passwd_luks(h, flags, &setup, &cache, effective_passwords);
70a5db58
LP
1803 if (r < 0)
1804 return r;
1805 break;
1806
1807 case USER_FSCRYPT:
7b78db28 1808 r = home_passwd_fscrypt(h, &setup, &cache, effective_passwords);
70a5db58
LP
1809 if (r < 0)
1810 return r;
1811 break;
1812
1813 default:
5c9feb2d 1814 ;
70a5db58
LP
1815 }
1816
1817 r = home_store_header_identity_luks(new_home, &setup, header_home);
1818 if (r < 0)
1819 return r;
1820
285ad523 1821 r = home_store_embedded_identity(new_home, setup.root_fd, embedded_home);
70a5db58
LP
1822 if (r < 0)
1823 return r;
1824
17ac40e4
AV
1825 r = home_reconcile_blob_dirs(new_home, setup.root_fd, reconciled);
1826 if (r < 0)
1827 return r;
1828
70a5db58
LP
1829 r = home_extend_embedded_identity(new_home, h, &setup);
1830 if (r < 0)
1831 return r;
1832
1833 r = home_sync_and_statfs(setup.root_fd, NULL);
1834 if (r < 0)
1835 return r;
1836
66aa51f8 1837 r = home_setup_done(&setup);
70a5db58
LP
1838 if (r < 0)
1839 return r;
1840
1841 log_info("Everything completed.");
1842
1843 *ret_home = TAKE_PTR(new_home);
1844 return 1;
1845}
1846
1847static int home_inspect(UserRecord *h, UserRecord **ret_home) {
1848 _cleanup_(user_record_unrefp) UserRecord *header_home = NULL, *new_home = NULL;
66aa51f8 1849 _cleanup_(home_setup_done) HomeSetup setup = HOME_SETUP_INIT;
7b78db28 1850 _cleanup_(password_cache_free) PasswordCache cache = {};
e1df968b 1851 HomeSetupFlags flags = 0;
70a5db58
LP
1852 int r;
1853
1854 assert(h);
1855 assert(ret_home);
1856
7b78db28 1857 r = user_record_authenticate(h, h, &cache, /* strict_verify= */ false);
70a5db58
LP
1858 if (r < 0)
1859 return r;
1860
e1df968b 1861 r = home_validate_update(h, &setup, &flags);
70a5db58
LP
1862 if (r < 0)
1863 return r;
1864
c00b2ddc 1865 r = home_setup(h, flags, &setup, &cache, &header_home);
70a5db58
LP
1866 if (r < 0)
1867 return r;
1868
7b78db28 1869 r = home_load_embedded_identity(h, setup.root_fd, header_home, USER_RECONCILE_ANY, &cache, NULL, &new_home);
70a5db58
LP
1870 if (r < 0)
1871 return r;
1872
1873 r = home_extend_embedded_identity(new_home, h, &setup);
1874 if (r < 0)
1875 return r;
1876
66aa51f8 1877 r = home_setup_done(&setup);
70a5db58
LP
1878 if (r < 0)
1879 return r;
1880
1881 log_info("Everything completed.");
1882
1883 *ret_home = TAKE_PTR(new_home);
1884 return 1;
1885}
1886
b1ed7e67 1887static int user_session_freezer_new(uid_t uid, UnitFreezer **ret) {
a5b009d9
AV
1888 _cleanup_free_ char *unit = NULL;
1889 int r;
1890
12904d53
MY
1891 assert(uid_is_valid(uid));
1892 assert(ret);
1893
a5b009d9
AV
1894 r = getenv_bool("SYSTEMD_HOME_LOCK_FREEZE_SESSION");
1895 if (r < 0 && r != -ENXIO)
61fbc58c 1896 log_warning_errno(r, "Cannot parse value of $SYSTEMD_HOME_LOCK_FREEZE_SESSION, ignoring: %m");
a5b009d9 1897 else if (r == 0) {
12904d53 1898 *ret = NULL;
a5b009d9
AV
1899 return 0;
1900 }
1901
1902 if (asprintf(&unit, "user-" UID_FMT ".slice", uid) < 0)
1903 return log_oom();
1904
b1ed7e67 1905 r = unit_freezer_new(unit, ret);
a5b009d9
AV
1906 if (r < 0)
1907 return r;
12904d53 1908
a5b009d9
AV
1909 return 1;
1910}
1911
70a5db58 1912static int home_lock(UserRecord *h) {
fc032ae1 1913 _cleanup_(home_setup_done) HomeSetup setup = HOME_SETUP_INIT;
70a5db58
LP
1914 int r;
1915
1916 assert(h);
1917
1918 if (!h->user_name)
1919 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "User record incomplete, refusing.");
1920 if (user_record_storage(h) != USER_LUKS)
1921 return log_error_errno(SYNTHETIC_ERRNO(ENOTTY), "Locking home directories of type '%s' currently not supported.", user_storage_to_string(user_record_storage(h)));
1922
1923 r = user_record_test_home_directory_and_warn(h);
1924 if (r < 0)
1925 return r;
1926 if (r != USER_TEST_MOUNTED)
1927 return log_error_errno(SYNTHETIC_ERRNO(ENOEXEC), "Home directory of %s is not mounted, can't lock.", h->user_name);
1928
12904d53 1929 _cleanup_(unit_freezer_freep) UnitFreezer *f = NULL;
a5b009d9 1930
b1ed7e67 1931 r = user_session_freezer_new(h->uid, &f);
70a5db58
LP
1932 if (r < 0)
1933 return r;
b1ed7e67
MY
1934 if (r > 0) {
1935 r = unit_freezer_freeze(f);
1936 if (r < 0)
1937 return r;
1938 } else
1939 log_notice("Session remains unfrozen on explicit request ($SYSTEMD_HOME_LOCK_FREEZE_SESSION=0).\n"
1940 "This is not recommended, and might result in unexpected behavior including data loss!");
70a5db58 1941
12904d53
MY
1942 r = home_lock_luks(h, &setup);
1943 if (r < 0) {
1944 if (f)
1945 (void) unit_freezer_thaw(f);
1946
1947 return r;
1948 }
a5b009d9 1949
d0eff7a1
AV
1950 /* Explicitly flush any per-user key from the keyring */
1951 (void) keyring_flush(h);
1952
70a5db58
LP
1953 log_info("Everything completed.");
1954 return 1;
1955}
1956
1957static int home_unlock(UserRecord *h) {
fc032ae1 1958 _cleanup_(home_setup_done) HomeSetup setup = HOME_SETUP_INIT;
7b78db28 1959 _cleanup_(password_cache_free) PasswordCache cache = {};
70a5db58
LP
1960 int r;
1961
1962 assert(h);
1963
1964 if (!h->user_name)
1965 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "User record incomplete, refusing.");
1966 if (user_record_storage(h) != USER_LUKS)
1967 return log_error_errno(SYNTHETIC_ERRNO(ENOTTY), "Unlocking home directories of type '%s' currently not supported.", user_storage_to_string(user_record_storage(h)));
1968
1969 /* Note that we don't check if $HOME is actually mounted, since we want to avoid disk accesses on
1970 * that mount until we have resumed the device. */
1971
7b78db28 1972 r = user_record_authenticate(h, h, &cache, /* strict_verify= */ false);
70a5db58
LP
1973 if (r < 0)
1974 return r;
1975
fc032ae1 1976 r = home_unlock_luks(h, &setup, &cache);
70a5db58
LP
1977 if (r < 0)
1978 return r;
1979
12904d53
MY
1980 _cleanup_(unit_freezer_freep) UnitFreezer *f = NULL;
1981
a5b009d9 1982 /* We want to thaw the session only after it's safe to access $HOME */
b1ed7e67 1983 r = user_session_freezer_new(h->uid, &f);
12904d53
MY
1984 if (r > 0)
1985 r = unit_freezer_thaw(f);
a5b009d9 1986 if (r < 0)
12904d53 1987 return r;
a5b009d9 1988
70a5db58
LP
1989 log_info("Everything completed.");
1990 return 1;
1991}
1992
1993static int run(int argc, char *argv[]) {
1994 _cleanup_(user_record_unrefp) UserRecord *home = NULL, *new_home = NULL;
309a747f 1995 _cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL;
5d2a48da 1996 _cleanup_fclose_ FILE *opened_file = NULL;
a4d72746 1997 _cleanup_hashmap_free_ Hashmap *blobs = NULL;
a4d72746 1998 const char *json_path = NULL, *blob_filename;
70a5db58
LP
1999 FILE *json_file;
2000 usec_t start;
309a747f 2001 sd_json_variant *fdmap, *blob_fd_variant;
70a5db58
LP
2002 int r;
2003
2004 start = now(CLOCK_MONOTONIC);
2005
d2acb93d 2006 log_setup();
70a5db58 2007
30f19400
LP
2008 cryptsetup_enable_logging(NULL);
2009
70a5db58
LP
2010 umask(0022);
2011
2012 if (argc < 2 || argc > 3)
2013 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "This program takes one or two arguments.");
2014
2015 if (argc > 2) {
2016 json_path = argv[2];
2017
2018 opened_file = fopen(json_path, "re");
2019 if (!opened_file)
2020 return log_error_errno(errno, "Failed to open %s: %m", json_path);
2021
2022 json_file = opened_file;
2023 } else {
2024 json_path = "<stdin>";
2025 json_file = stdin;
2026 }
2027
9df18e4b 2028 unsigned line = 0, column = 0;
309a747f 2029 r = sd_json_parse_file(json_file, json_path, SD_JSON_PARSE_SENSITIVE, &v, &line, &column);
70a5db58
LP
2030 if (r < 0)
2031 return log_error_errno(r, "[%s:%u:%u] Failed to parse JSON data: %m", json_path, line, column);
2032
309a747f 2033 fdmap = sd_json_variant_by_key(v, HOMEWORK_BLOB_FDMAP_FIELD);
a4d72746
AV
2034 if (fdmap) {
2035 r = hashmap_ensure_allocated(&blobs, &blob_fd_hash_ops);
2036 if (r < 0)
2037 return log_oom();
2038
2039 JSON_VARIANT_OBJECT_FOREACH(blob_filename, blob_fd_variant, fdmap) {
2040 _cleanup_free_ char *filename = NULL;
2041 _cleanup_close_ int fd = -EBADF;
2042
309a747f
LP
2043 assert(sd_json_variant_is_integer(blob_fd_variant));
2044 assert(sd_json_variant_integer(blob_fd_variant) >= 0);
2045 assert(sd_json_variant_integer(blob_fd_variant) <= INT_MAX - SD_LISTEN_FDS_START);
2046 fd = SD_LISTEN_FDS_START + (int) sd_json_variant_integer(blob_fd_variant);
a4d72746
AV
2047
2048 if (DEBUG_LOGGING) {
2049 _cleanup_free_ char *resolved = NULL;
2050 r = fd_get_path(fd, &resolved);
2051 log_debug("Got blob from daemon: %s (%d) → %s",
2052 blob_filename, fd, resolved ?: STRERROR(r));
2053 }
2054
2055 filename = strdup(blob_filename);
2056 if (!filename)
2057 return log_oom();
2058
2059 r = fd_cloexec(fd, true);
2060 if (r < 0)
2061 return log_error_errno(r, "Failed to enable O_CLOEXEC on blob %s: %m", filename);
2062
2063 r = hashmap_put(blobs, filename, FD_TO_PTR(fd));
2064 if (r < 0)
2065 return log_error_errno(r, "Failed to insert blob %s into map: %m", filename);
2066 TAKE_PTR(filename); /* Ownership transfers to hashmap */
2067 TAKE_FD(fd);
2068 }
2069
309a747f 2070 r = sd_json_variant_filter(&v, STRV_MAKE(HOMEWORK_BLOB_FDMAP_FIELD));
a4d72746
AV
2071 if (r < 0)
2072 return log_error_errno(r, "Failed to strip internal fdmap from JSON: %m");
2073 }
2074
70a5db58
LP
2075 home = user_record_new();
2076 if (!home)
2077 return log_oom();
2078
bfc0cc1a 2079 r = user_record_load(home, v, USER_RECORD_LOAD_FULL|USER_RECORD_LOG|USER_RECORD_PERMISSIVE);
70a5db58
LP
2080 if (r < 0)
2081 return r;
2082
2083 /* Well known return values of these operations, that systemd-homed knows and converts to proper D-Bus errors:
2084 *
162392b7
ZJS
2085 * EMSGSIZE → file systems of this type cannot be shrunk
2086 * ETXTBSY → file systems of this type can only be shrunk offline
70a5db58
LP
2087 * ERANGE → file system size too small
2088 * ENOLINK → system does not support selected storage backend
2089 * EPROTONOSUPPORT → system does not support selected file system
2090 * ENOTTY → operation not support on this storage
2091 * ESOCKTNOSUPPORT → operation not support on this file system
2092 * ENOKEY → password incorrect (or not sufficient, or not supplied)
87d7893c 2093 * EREMOTEIO → recovery key incorrect (or not sufficeint, or not supplied — only if no passwords defined)
70a5db58 2094 * EBADSLT → similar, but PKCS#11 device is defined and might be able to provide password, if it was plugged in which it is not
7b78db28 2095 * ENOANO → suitable PKCS#11/FIDO2 device found, but PIN is missing to unlock it
70a5db58 2096 * ERFKILL → suitable PKCS#11 device found, but OK to ask for on-device interactive authentication not given
7b78db28 2097 * EMEDIUMTYPE → suitable FIDO2 device found, but OK to ask for user presence not given
17e7561a 2098 * ENOCSI → suitable FIDO2 device found, but OK to ask for user verification not given
7b78db28
LP
2099 * ENOSTR → suitable FIDO2 device found, but user didn't react to action request on token quickly enough
2100 * EOWNERDEAD → suitable PKCS#11/FIDO2 device found, but its PIN is locked
2101 * ENOLCK → suitable PKCS#11/FIDO2 device found, but PIN incorrect
70a5db58
LP
2102 * ETOOMANYREFS → suitable PKCS#11 device found, but PIN incorrect, and only few tries left
2103 * EUCLEAN → suitable PKCS#11 device found, but PIN incorrect, and only one try left
2104 * EBUSY → file system is currently active
2105 * ENOEXEC → file system is currently not active
2106 * ENOSPC → not enough disk space for operation
cbffdcec 2107 * EKEYREVOKED → user record has not suitable hashed password or pkcs#11 entry, we cannot authenticate
2aaf565a 2108 * EADDRINUSE → home image is already used elsewhere (lock taken)
2cf95e51 2109 * ENETUNREACH → backing storage is currently not (image is ENOENT, or AF_UNIX socket to connect to is ENOENT)
70a5db58
LP
2110 */
2111
2112 if (streq(argv[1], "activate"))
2113 r = home_activate(home, &new_home);
2114 else if (streq(argv[1], "deactivate"))
2115 r = home_deactivate(home, false);
2116 else if (streq(argv[1], "deactivate-force"))
2117 r = home_deactivate(home, true);
2118 else if (streq(argv[1], "create"))
a4d72746 2119 r = home_create(home, blobs, &new_home);
70a5db58
LP
2120 else if (streq(argv[1], "remove"))
2121 r = home_remove(home);
2122 else if (streq(argv[1], "update"))
a4d72746 2123 r = home_update(home, blobs, &new_home);
5ec87d57
AV
2124 else if (streq(argv[1], "resize"))
2125 r = home_resize(home, &new_home);
70a5db58
LP
2126 else if (streq(argv[1], "passwd"))
2127 r = home_passwd(home, &new_home);
2128 else if (streq(argv[1], "inspect"))
2129 r = home_inspect(home, &new_home);
2130 else if (streq(argv[1], "lock"))
2131 r = home_lock(home);
2132 else if (streq(argv[1], "unlock"))
2133 r = home_unlock(home);
2134 else
2135 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown verb '%s'.", argv[1]);
87d7893c 2136 if (IN_SET(r, -ENOKEY, -EREMOTEIO) && !strv_isempty(home->password) ) { /* There were passwords specified but they were incorrect */
70a5db58
LP
2137 usec_t end, n, d;
2138
2139 /* Make sure bad password replies always take at least 3s, and if longer multiples of 3s, so
2140 * that it's not clear how long we actually needed for our calculations. */
2141 n = now(CLOCK_MONOTONIC);
2142 assert(n >= start);
2143
2144 d = usec_sub_unsigned(n, start);
2145 if (d > BAD_PASSWORD_DELAY_USEC)
2146 end = start + DIV_ROUND_UP(d, BAD_PASSWORD_DELAY_USEC) * BAD_PASSWORD_DELAY_USEC;
2147 else
2148 end = start + BAD_PASSWORD_DELAY_USEC;
2149
2150 if (n < end)
4251512e 2151 (void) usleep_safe(usec_sub_unsigned(end, n));
70a5db58
LP
2152 }
2153 if (r < 0)
2154 return r;
2155
2156 /* We always pass the new record back, regardless if it changed or not. This allows our caller to
2157 * prepare a fresh record, send to us, and only if it works use it without having to keep a local
2158 * copy. */
2159 if (new_home)
309a747f 2160 sd_json_variant_dump(new_home->json, SD_JSON_FORMAT_NEWLINE, stdout, NULL);
70a5db58
LP
2161
2162 return 0;
2163}
2164
2165DEFINE_MAIN_FUNCTION(run);