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