]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/home/homework.c
resolve: allow configurable bind address
[thirdparty/systemd.git] / src / home / homework.c
CommitLineData
70a5db58
LP
1/* SPDX-License-Identifier: LGPL-2.1+ */
2
3#include <stddef.h>
4#include <sys/mount.h>
5
6#include "chown-recursive.h"
7#include "copy.h"
8#include "fd-util.h"
9#include "fileio.h"
1dfe5de0 10#include "fs-util.h"
70a5db58
LP
11#include "home-util.h"
12#include "homework-cifs.h"
13#include "homework-directory.h"
7b78db28 14#include "homework-fido2.h"
70a5db58
LP
15#include "homework-fscrypt.h"
16#include "homework-luks.h"
17#include "homework-mount.h"
18#include "homework-pkcs11.h"
19#include "homework.h"
20#include "main-func.h"
21#include "memory-util.h"
22#include "missing_magic.h"
87d7893c 23#include "modhex.h"
70a5db58
LP
24#include "mount-util.h"
25#include "path-util.h"
70a5db58
LP
26#include "rm-rf.h"
27#include "stat-util.h"
28#include "strv.h"
29#include "tmpfile-util.h"
30#include "user-util.h"
31#include "virt.h"
32
33/* Make sure a bad password always results in a 3s delay, no matter what */
34#define BAD_PASSWORD_DELAY_USEC (3 * USEC_PER_SEC)
35
7b78db28
LP
36void password_cache_free(PasswordCache *cache) {
37 if (!cache)
38 return;
39
40 cache->pkcs11_passwords = strv_free_erase(cache->pkcs11_passwords);
41 cache->fido2_passwords = strv_free_erase(cache->fido2_passwords);
42}
43
70a5db58
LP
44int user_record_authenticate(
45 UserRecord *h,
46 UserRecord *secret,
7b78db28 47 PasswordCache *cache,
c8f145ad 48 bool strict_verify) {
70a5db58 49
87d7893c 50 bool need_password = false, need_recovery_key = false, need_token = false, need_pin = false, need_protected_authentication_path_permitted = false, need_user_presence_permitted = false,
7b78db28 51 pin_locked = false, pin_incorrect = false, 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 */
3aeea37d 102 for (size_t n = 0; n < h->n_pkcs11_encrypted_key; n++) {
70a5db58
LP
103 char **pp;
104
7b78db28
LP
105 STRV_FOREACH(pp, cache->pkcs11_passwords) {
106 r = test_password_one(h->pkcs11_encrypted_key[n].hashed_password, *pp);
70a5db58
LP
107 if (r < 0)
108 return log_error_errno(r, "Failed to check supplied PKCS#11 password: %m");
109 if (r > 0) {
110 log_info("Previously acquired PKCS#11 password unlocks user record.");
c8f145ad 111 return 1;
70a5db58
LP
112 }
113 }
7b78db28
LP
114 }
115
116 /* Third, test cached FIDO2 passwords */
117 for (size_t n = 0; n < h->n_fido2_hmac_salt; n++) {
118 char **pp;
119
120 /* See if any of the previously calculated passwords work */
121 STRV_FOREACH(pp, cache->fido2_passwords) {
122 r = test_password_one(h->fido2_hmac_salt[n].hashed_password, *pp);
123 if (r < 0)
124 return log_error_errno(r, "Failed to check supplied FIDO2 password: %m");
125 if (r > 0) {
126 log_info("Previously acquired FIDO2 password unlocks user record.");
127 return 0;
128 }
129 }
130 }
131
132 /* Fourth, let's see if any of the PKCS#11 security tokens are plugged in and help us */
133 for (size_t n = 0; n < h->n_pkcs11_encrypted_key; n++) {
134#if HAVE_P11KIT
135 _cleanup_(pkcs11_callback_data_release) struct pkcs11_callback_data data = {
136 .user_record = h,
137 .secret = secret,
138 .encrypted_key = h->pkcs11_encrypted_key + n,
139 };
70a5db58
LP
140
141 r = pkcs11_find_token(data.encrypted_key->uri, pkcs11_callback, &data);
142 switch (r) {
143 case -EAGAIN:
144 need_token = true;
145 break;
146 case -ENOANO:
147 need_pin = true;
148 break;
149 case -ERFKILL:
150 need_protected_authentication_path_permitted = true;
151 break;
152 case -EOWNERDEAD:
153 pin_locked = true;
154 break;
155 case -ENOLCK:
156 pin_incorrect = true;
157 break;
158 case -ETOOMANYREFS:
159 pin_incorrect = pin_incorrect_few_tries_left = true;
160 break;
161 case -EUCLEAN:
162 pin_incorrect = pin_incorrect_few_tries_left = pin_incorrect_one_try_left = true;
163 break;
164 default:
165 if (r < 0)
166 return r;
167
168 r = test_password_one(data.encrypted_key->hashed_password, data.decrypted_password);
169 if (r < 0)
170 return log_error_errno(r, "Failed to test PKCS#11 password: %m");
171 if (r == 0)
172 return log_error_errno(SYNTHETIC_ERRNO(EPERM), "Configured PKCS#11 security token %s does not decrypt encrypted key correctly.", data.encrypted_key->uri);
173
174 log_info("Decrypted password from PKCS#11 security token %s unlocks user record.", data.encrypted_key->uri);
175
7b78db28
LP
176 r = strv_extend(&cache->pkcs11_passwords, data.decrypted_password);
177 if (r < 0)
178 return log_oom();
179
180 return 0;
181 }
182#else
183 need_token = true;
184 break;
185#endif
186 }
187
188 /* Fifth, let's see if any of the FIDO2 security tokens are plugged in and help us */
189 for (size_t n = 0; n < h->n_fido2_hmac_salt; n++) {
190#if HAVE_LIBFIDO2
191 _cleanup_(erase_and_freep) char *decrypted_password = NULL;
192
193 r = fido2_use_token(h, secret, h->fido2_hmac_salt + n, &decrypted_password);
194 switch (r) {
195 case -EAGAIN:
196 need_token = true;
197 break;
198 case -ENOANO:
199 need_pin = true;
200 break;
201 case -EOWNERDEAD:
202 pin_locked = true;
203 break;
204 case -ENOLCK:
205 pin_incorrect = true;
206 break;
207 case -EMEDIUMTYPE:
208 need_user_presence_permitted = true;
209 break;
210 case -ENOSTR:
211 token_action_timeout = true;
212 break;
213 default:
214 if (r < 0)
215 return r;
216
217 r = test_password_one(h->fido2_hmac_salt[n].hashed_password, decrypted_password);
218 if (r < 0)
219 return log_error_errno(r, "Failed to test FIDO2 password: %m");
220 if (r == 0)
221 return log_error_errno(SYNTHETIC_ERRNO(EPERM), "Configured FIDO2 security token does not decrypt encrypted key correctly.");
222
223 log_info("Decrypted password from FIDO2 security token unlocks user record.");
224
225 r = strv_extend(&cache->fido2_passwords, decrypted_password);
70a5db58
LP
226 if (r < 0)
227 return log_oom();
228
c8f145ad 229 return 1;
70a5db58
LP
230 }
231#else
232 need_token = true;
233 break;
234#endif
235 }
236
237 /* Ordered by "relevance", i.e. the most "important" or "interesting" error condition is returned. */
238 if (pin_incorrect_one_try_left)
239 return -EUCLEAN;
240 if (pin_incorrect_few_tries_left)
241 return -ETOOMANYREFS;
242 if (pin_incorrect)
243 return -ENOLCK;
244 if (pin_locked)
245 return -EOWNERDEAD;
7b78db28
LP
246 if (token_action_timeout)
247 return -ENOSTR;
70a5db58
LP
248 if (need_protected_authentication_path_permitted)
249 return -ERFKILL;
7b78db28
LP
250 if (need_user_presence_permitted)
251 return -EMEDIUMTYPE;
70a5db58
LP
252 if (need_pin)
253 return -ENOANO;
254 if (need_token)
255 return -EBADSLT;
256 if (need_password)
257 return -ENOKEY;
87d7893c
LP
258 if (need_recovery_key)
259 return -EREMOTEIO;
70a5db58 260
87d7893c
LP
261 /* Hmm, this means neither PCKS#11/FIDO2 nor classic hashed passwords or recovery keys were supplied,
262 * we cannot authenticate this reasonably */
c8f145ad
LP
263 if (strict_verify)
264 return log_debug_errno(SYNTHETIC_ERRNO(EKEYREVOKED),
87d7893c 265 "No hashed passwords, no recovery keys and no PKCS#11/FIDO2 tokens defined, cannot authenticate user record, refusing.");
c8f145ad
LP
266
267 /* If strict verification is off this means we are possibly in the case where we encountered an
268 * unfixated record, i.e. a synthetic one that accordingly lacks any authentication data. In this
269 * case, allow the authentication to pass for now, so that the second (or third) authentication level
270 * (the ones of the user record in the LUKS header or inside the home directory) will then catch
271 * invalid passwords. The second/third authentication always runs in strict verification mode. */
87d7893c 272 log_debug("No hashed passwords, not recovery keys and no PKCS#11 tokens defined in record, cannot authenticate user record. "
c8f145ad
LP
273 "Deferring to embedded user record.");
274 return 0;
70a5db58
LP
275}
276
277int home_setup_undo(HomeSetup *setup) {
278 int r = 0, q;
279
280 assert(setup);
281
28a7f106
LP
282 if (setup->root_fd >= 0) {
283 if (setup->do_offline_fitrim) {
284 q = run_fitrim(setup->root_fd);
285 if (q < 0)
286 r = q;
287 }
288
289 setup->root_fd = safe_close(setup->root_fd);
290 }
70a5db58
LP
291
292 if (setup->undo_mount) {
293 q = umount_verbose("/run/systemd/user-home-mount");
294 if (q < 0)
295 r = q;
296 }
297
298 if (setup->undo_dm && setup->crypt_device && setup->dm_name) {
299 q = crypt_deactivate(setup->crypt_device, setup->dm_name);
300 if (q < 0)
301 r = q;
302 }
303
28a7f106
LP
304 if (setup->image_fd >= 0) {
305 if (setup->do_offline_fallocate) {
306 q = run_fallocate(setup->image_fd, NULL);
307 if (q < 0)
308 r = q;
309 }
310
565ac8b1
LP
311 if (setup->do_mark_clean) {
312 q = run_mark_dirty(setup->image_fd, false);
313 if (q < 0)
314 r = q;
315 }
316
28a7f106
LP
317 setup->image_fd = safe_close(setup->image_fd);
318 }
319
70a5db58
LP
320 setup->undo_mount = false;
321 setup->undo_dm = false;
28a7f106
LP
322 setup->do_offline_fitrim = false;
323 setup->do_offline_fallocate = false;
565ac8b1 324 setup->do_mark_clean = false;
70a5db58
LP
325
326 setup->dm_name = mfree(setup->dm_name);
327 setup->dm_node = mfree(setup->dm_node);
328
329 setup->loop = loop_device_unref(setup->loop);
330 crypt_free(setup->crypt_device);
331 setup->crypt_device = NULL;
332
333 explicit_bzero_safe(setup->volume_key, setup->volume_key_size);
334 setup->volume_key = mfree(setup->volume_key);
335 setup->volume_key_size = 0;
336
337 return r;
338}
339
340int home_prepare(
341 UserRecord *h,
342 bool already_activated,
7b78db28 343 PasswordCache *cache,
70a5db58
LP
344 HomeSetup *setup,
345 UserRecord **ret_header_home) {
346
347 int r;
348
349 assert(h);
350 assert(setup);
351 assert(!setup->loop);
352 assert(!setup->crypt_device);
353 assert(setup->root_fd < 0);
354 assert(!setup->undo_dm);
355 assert(!setup->undo_mount);
356
357 /* Makes a home directory accessible (through the root_fd file descriptor, not by path!). */
358
359 switch (user_record_storage(h)) {
360
361 case USER_LUKS:
7b78db28 362 return home_prepare_luks(h, already_activated, NULL, cache, setup, ret_header_home);
70a5db58
LP
363
364 case USER_SUBVOLUME:
365 case USER_DIRECTORY:
366 r = home_prepare_directory(h, already_activated, setup);
367 break;
368
369 case USER_FSCRYPT:
7b78db28 370 r = home_prepare_fscrypt(h, already_activated, cache, setup);
70a5db58
LP
371 break;
372
373 case USER_CIFS:
374 r = home_prepare_cifs(h, already_activated, setup);
375 break;
376
377 default:
378 return log_error_errno(SYNTHETIC_ERRNO(ENOLINK), "Processing home directories of type '%s' currently not supported.", user_storage_to_string(user_record_storage(h)));
379 }
380
381 if (r < 0)
382 return r;
383
384 if (ret_header_home)
385 *ret_header_home = NULL;
386
387 return r;
388}
389
390int home_sync_and_statfs(int root_fd, struct statfs *ret) {
391 assert(root_fd >= 0);
392
393 /* Let's sync this to disk, so that the disk space reported by fstatfs() below is accurate (for file
394 * systems such as btrfs where this is determined lazily). */
395
396 if (syncfs(root_fd) < 0)
397 return log_error_errno(errno, "Failed to synchronize file system: %m");
398
399 if (ret)
400 if (fstatfs(root_fd, ret) < 0)
401 return log_error_errno(errno, "Failed to statfs() file system: %m");
402
403 log_info("Synchronized disk.");
404
405 return 0;
406}
407
408static int read_identity_file(int root_fd, JsonVariant **ret) {
409 _cleanup_(fclosep) FILE *identity_file = NULL;
410 _cleanup_close_ int identity_fd = -1;
411 unsigned line, column;
412 int r;
413
414 assert(root_fd >= 0);
415 assert(ret);
416
417 identity_fd = openat(root_fd, ".identity", O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW|O_NONBLOCK);
418 if (identity_fd < 0)
419 return log_error_errno(errno, "Failed to open .identity file in home directory: %m");
420
421 r = fd_verify_regular(identity_fd);
422 if (r < 0)
423 return log_error_errno(r, "Embedded identity file is not a regular file, refusing: %m");
424
4fa744a3 425 identity_file = take_fdopen(&identity_fd, "r");
70a5db58
LP
426 if (!identity_file)
427 return log_oom();
428
70a5db58
LP
429 r = json_parse_file(identity_file, ".identity", JSON_PARSE_SENSITIVE, ret, &line, &column);
430 if (r < 0)
431 return log_error_errno(r, "[.identity:%u:%u] Failed to parse JSON data: %m", line, column);
432
433 log_info("Read embedded .identity file.");
434
435 return 0;
436}
437
438static int write_identity_file(int root_fd, JsonVariant *v, uid_t uid) {
439 _cleanup_(json_variant_unrefp) JsonVariant *normalized = NULL;
440 _cleanup_(fclosep) FILE *identity_file = NULL;
441 _cleanup_close_ int identity_fd = -1;
442 _cleanup_free_ char *fn = NULL;
443 int r;
444
445 assert(root_fd >= 0);
446 assert(v);
447
448 normalized = json_variant_ref(v);
449
450 r = json_variant_normalize(&normalized);
451 if (r < 0)
452 log_warning_errno(r, "Failed to normalize user record, ignoring: %m");
453
454 r = tempfn_random(".identity", NULL, &fn);
455 if (r < 0)
456 return r;
457
458 identity_fd = openat(root_fd, fn, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW, 0600);
459 if (identity_fd < 0)
460 return log_error_errno(errno, "Failed to create .identity file in home directory: %m");
461
4fa744a3 462 identity_file = take_fdopen(&identity_fd, "w");
70a5db58
LP
463 if (!identity_file) {
464 r = log_oom();
465 goto fail;
466 }
467
70a5db58
LP
468 json_variant_dump(normalized, JSON_FORMAT_PRETTY, identity_file, NULL);
469
470 r = fflush_and_check(identity_file);
471 if (r < 0) {
472 log_error_errno(r, "Failed to write .identity file: %m");
473 goto fail;
474 }
475
476 if (fchown(fileno(identity_file), uid, uid) < 0) {
477 log_error_errno(r, "Failed to change ownership of identity file: %m");
478 goto fail;
479 }
480
481 if (renameat(root_fd, fn, root_fd, ".identity") < 0) {
482 r = log_error_errno(errno, "Failed to move identity file into place: %m");
483 goto fail;
484 }
485
486 log_info("Wrote embedded .identity file.");
487
488 return 0;
489
490fail:
491 (void) unlinkat(root_fd, fn, 0);
492 return r;
493}
494
495int home_load_embedded_identity(
496 UserRecord *h,
497 int root_fd,
498 UserRecord *header_home,
499 UserReconcileMode mode,
7b78db28 500 PasswordCache *cache,
70a5db58
LP
501 UserRecord **ret_embedded_home,
502 UserRecord **ret_new_home) {
503
504 _cleanup_(user_record_unrefp) UserRecord *embedded_home = NULL, *intermediate_home = NULL, *new_home = NULL;
505 _cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
506 int r;
507
508 assert(h);
509 assert(root_fd >= 0);
510
511 r = read_identity_file(root_fd, &v);
512 if (r < 0)
513 return r;
514
515 embedded_home = user_record_new();
516 if (!embedded_home)
517 return log_oom();
518
519 r = user_record_load(embedded_home, v, USER_RECORD_LOAD_EMBEDDED);
520 if (r < 0)
521 return r;
522
523 if (!user_record_compatible(h, embedded_home))
80ace4f2 524 return log_error_errno(SYNTHETIC_ERRNO(EREMCHG), "Embedded home record not compatible with host record, refusing.");
70a5db58
LP
525
526 /* Insist that credentials the user supplies also unlocks any embedded records. */
7b78db28 527 r = user_record_authenticate(embedded_home, h, cache, /* strict_verify= */ true);
70a5db58
LP
528 if (r < 0)
529 return r;
c8f145ad 530 assert(r > 0); /* Insist that a password was verified */
70a5db58
LP
531
532 /* At this point we have three records to deal with:
533 *
534 * · The record we got passed from the host
535 * · The record included in the LUKS header (only if LUKS is used)
536 * · The record in the home directory itself (~.identity)
537 *
538 * Now we have to reconcile all three, and let the newest one win. */
539
540 if (header_home) {
541 /* Note we relax the requirements here. Instead of insisting that the host record is strictly
542 * newer, let's also be OK if its equally new. If it is, we'll however insist that the
543 * embedded record must be newer, so that we update at least one of the two. */
544
545 r = user_record_reconcile(h, header_home, mode == USER_RECONCILE_REQUIRE_NEWER ? USER_RECONCILE_REQUIRE_NEWER_OR_EQUAL : mode, &intermediate_home);
546 if (r == -EREMCHG) /* this was supposed to be checked earlier already, but let's check this again */
547 return log_error_errno(r, "Identity stored on host and in header don't match, refusing.");
548 if (r == -ESTALE)
549 return log_error_errno(r, "Embedded identity record is newer than supplied record, refusing.");
550 if (r < 0)
551 return log_error_errno(r, "Failed to reconcile host and header identities: %m");
552 if (r == USER_RECONCILE_EMBEDDED_WON)
553 log_info("Reconciling header user identity completed (header version was newer).");
554 else if (r == USER_RECONCILE_HOST_WON) {
555 log_info("Reconciling header user identity completed (host version was newer).");
556
557 if (mode == USER_RECONCILE_REQUIRE_NEWER) /* Host version is newer than the header
558 * version, hence we'll update
559 * something. This means we can relax the
560 * requirements on the embedded
561 * identity. */
562 mode = USER_RECONCILE_REQUIRE_NEWER_OR_EQUAL;
563 } else {
564 assert(r == USER_RECONCILE_IDENTICAL);
565 log_info("Reconciling user identities completed (host and header version were identical).");
566 }
567
568 h = intermediate_home;
569 }
570
571 r = user_record_reconcile(h, embedded_home, mode, &new_home);
572 if (r == -EREMCHG)
573 return log_error_errno(r, "Identity stored on host and in home don't match, refusing.");
574 if (r == -ESTALE)
575 return log_error_errno(r, "Embedded identity record is equally new or newer than supplied record, refusing.");
576 if (r < 0)
577 return log_error_errno(r, "Failed to reconcile host and embedded identities: %m");
578 if (r == USER_RECONCILE_EMBEDDED_WON)
579 log_info("Reconciling embedded user identity completed (embedded version was newer).");
580 else if (r == USER_RECONCILE_HOST_WON)
581 log_info("Reconciling embedded user identity completed (host version was newer).");
582 else {
583 assert(r == USER_RECONCILE_IDENTICAL);
584 log_info("Reconciling embedded user identity completed (host and embedded version were identical).");
585 }
586
587 if (ret_embedded_home)
588 *ret_embedded_home = TAKE_PTR(embedded_home);
589
590 if (ret_new_home)
591 *ret_new_home = TAKE_PTR(new_home);
592
593 return 0;
594}
595
596int home_store_embedded_identity(UserRecord *h, int root_fd, uid_t uid, UserRecord *old_home) {
597 _cleanup_(user_record_unrefp) UserRecord *embedded = NULL;
598 int r;
599
600 assert(h);
601 assert(root_fd >= 0);
602 assert(uid_is_valid(uid));
603
604 r = user_record_clone(h, USER_RECORD_EXTRACT_EMBEDDED, &embedded);
605 if (r < 0)
606 return log_error_errno(r, "Failed to determine new embedded record: %m");
607
608 if (old_home && user_record_equal(old_home, embedded)) {
609 log_debug("Not updating embedded home record.");
610 return 0;
611 }
612
613 /* The identity has changed, let's update it in the image */
614 r = write_identity_file(root_fd, embedded->json, h->uid);
615 if (r < 0)
616 return r;
617
618 return 1;
619}
620
621static const char *file_system_type_fd(int fd) {
622 struct statfs sfs;
623
624 assert(fd >= 0);
625
626 if (fstatfs(fd, &sfs) < 0) {
627 log_debug_errno(errno, "Failed to statfs(): %m");
628 return NULL;
629 }
630
631 if (is_fs_type(&sfs, XFS_SB_MAGIC))
632 return "xfs";
633 if (is_fs_type(&sfs, EXT4_SUPER_MAGIC))
634 return "ext4";
635 if (is_fs_type(&sfs, BTRFS_SUPER_MAGIC))
636 return "btrfs";
637
638 return NULL;
639}
640
641int home_extend_embedded_identity(UserRecord *h, UserRecord *used, HomeSetup *setup) {
642 int r;
643
644 assert(h);
645 assert(used);
646 assert(setup);
647
648 r = user_record_add_binding(
649 h,
650 user_record_storage(used),
651 user_record_image_path(used),
652 setup->found_partition_uuid,
653 setup->found_luks_uuid,
654 setup->found_fs_uuid,
655 setup->crypt_device ? crypt_get_cipher(setup->crypt_device) : NULL,
656 setup->crypt_device ? crypt_get_cipher_mode(setup->crypt_device) : NULL,
657 setup->crypt_device ? luks_volume_key_size_convert(setup->crypt_device) : UINT64_MAX,
658 file_system_type_fd(setup->root_fd),
659 user_record_home_directory(used),
660 used->uid,
661 (gid_t) used->uid);
662 if (r < 0)
663 return log_error_errno(r, "Failed to update binding in record: %m");
664
665 return 0;
666}
667
668static int chown_recursive_directory(int root_fd, uid_t uid) {
669 int r;
670
671 assert(root_fd >= 0);
672 assert(uid_is_valid(uid));
673
674 r = fd_chown_recursive(root_fd, uid, (gid_t) uid, 0777);
675 if (r < 0)
676 return log_error_errno(r, "Failed to change ownership of files and directories: %m");
677 if (r == 0)
678 log_info("Recursive changing of ownership not necessary, skipped.");
679 else
680 log_info("Recursive changing of ownership completed.");
681
682 return 0;
683}
684
685int home_refresh(
686 UserRecord *h,
687 HomeSetup *setup,
688 UserRecord *header_home,
7b78db28 689 PasswordCache *cache,
70a5db58
LP
690 struct statfs *ret_statfs,
691 UserRecord **ret_new_home) {
692
693 _cleanup_(user_record_unrefp) UserRecord *embedded_home = NULL, *new_home = NULL;
694 int r;
695
696 assert(h);
697 assert(setup);
698 assert(ret_new_home);
699
700 /* When activating a home directory, does the identity work: loads the identity from the $HOME
701 * directory, reconciles it with our idea, chown()s everything. */
702
7b78db28 703 r = home_load_embedded_identity(h, setup->root_fd, header_home, USER_RECONCILE_ANY, cache, &embedded_home, &new_home);
70a5db58
LP
704 if (r < 0)
705 return r;
706
707 r = home_store_header_identity_luks(new_home, setup, header_home);
708 if (r < 0)
709 return r;
710
711 r = home_store_embedded_identity(new_home, setup->root_fd, h->uid, embedded_home);
712 if (r < 0)
713 return r;
714
715 r = chown_recursive_directory(setup->root_fd, h->uid);
716 if (r < 0)
717 return r;
718
719 r = home_sync_and_statfs(setup->root_fd, ret_statfs);
720 if (r < 0)
721 return r;
722
723 *ret_new_home = TAKE_PTR(new_home);
724 return 0;
725}
726
727static int home_activate(UserRecord *h, UserRecord **ret_home) {
7b78db28 728 _cleanup_(password_cache_free) PasswordCache cache = {};
70a5db58
LP
729 _cleanup_(user_record_unrefp) UserRecord *new_home = NULL;
730 int r;
731
732 assert(h);
733
734 if (!h->user_name)
735 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "User record lacks user name, refusing.");
736 if (!uid_is_valid(h->uid))
737 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "User record lacks UID, refusing.");
738 if (!IN_SET(user_record_storage(h), USER_LUKS, USER_DIRECTORY, USER_SUBVOLUME, USER_FSCRYPT, USER_CIFS))
739 return log_error_errno(SYNTHETIC_ERRNO(ENOTTY), "Activating home directories of type '%s' currently not supported.", user_storage_to_string(user_record_storage(h)));
740
7b78db28 741 r = user_record_authenticate(h, h, &cache, /* strict_verify= */ false);
70a5db58
LP
742 if (r < 0)
743 return r;
744
745 r = user_record_test_home_directory_and_warn(h);
746 if (r < 0)
747 return r;
748 if (r == USER_TEST_MOUNTED)
749 return log_error_errno(SYNTHETIC_ERRNO(EALREADY), "Home directory %s is already mounted, refusing.", user_record_home_directory(h));
750
751 r = user_record_test_image_path_and_warn(h);
752 if (r < 0)
753 return r;
754 if (r == USER_TEST_ABSENT)
755 return log_error_errno(SYNTHETIC_ERRNO(ENOENT), "Image path %s is missing, refusing.", user_record_image_path(h));
756
757 switch (user_record_storage(h)) {
758
759 case USER_LUKS:
7b78db28 760 r = home_activate_luks(h, &cache, &new_home);
70a5db58
LP
761 if (r < 0)
762 return r;
763
764 break;
765
766 case USER_SUBVOLUME:
767 case USER_DIRECTORY:
768 case USER_FSCRYPT:
7b78db28 769 r = home_activate_directory(h, &cache, &new_home);
70a5db58
LP
770 if (r < 0)
771 return r;
772
773 break;
774
775 case USER_CIFS:
7b78db28 776 r = home_activate_cifs(h, &cache, &new_home);
70a5db58
LP
777 if (r < 0)
778 return r;
779
780 break;
781
782 default:
783 assert_not_reached("unexpected type");
784 }
785
786 /* Note that the returned object might either be a reference to an updated version of the existing
787 * home object, or a reference to a newly allocated home object. The caller has to be able to deal
788 * with both, and consider the old object out-of-date. */
789 if (user_record_equal(h, new_home)) {
790 *ret_home = NULL;
791 return 0; /* no identity change */
792 }
793
794 *ret_home = TAKE_PTR(new_home);
795 return 1; /* identity updated */
796}
797
798static int home_deactivate(UserRecord *h, bool force) {
799 bool done = false;
800 int r;
801
802 assert(h);
803
804 if (!h->user_name)
805 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "User record incomplete, refusing.");
806 if (!IN_SET(user_record_storage(h), USER_LUKS, USER_DIRECTORY, USER_SUBVOLUME, USER_FSCRYPT, USER_CIFS))
807 return log_error_errno(SYNTHETIC_ERRNO(ENOTTY), "Deactivating home directories of type '%s' currently not supported.", user_storage_to_string(user_record_storage(h)));
808
809 r = user_record_test_home_directory_and_warn(h);
810 if (r < 0)
811 return r;
812 if (r == USER_TEST_MOUNTED) {
28a7f106
LP
813 if (user_record_storage(h) == USER_LUKS) {
814 r = home_trim_luks(h);
815 if (r < 0)
816 return r;
817 }
818
70a5db58
LP
819 if (umount2(user_record_home_directory(h), UMOUNT_NOFOLLOW | (force ? MNT_FORCE|MNT_DETACH : 0)) < 0)
820 return log_error_errno(errno, "Failed to unmount %s: %m", user_record_home_directory(h));
821
822 log_info("Unmounting completed.");
823 done = true;
824 } else
825 log_info("Directory %s is already unmounted.", user_record_home_directory(h));
826
827 if (user_record_storage(h) == USER_LUKS) {
828 r = home_deactivate_luks(h);
829 if (r < 0)
830 return r;
831 if (r > 0)
832 done = true;
833 }
834
835 if (!done)
836 return log_error_errno(SYNTHETIC_ERRNO(ENOEXEC), "Home is not active.");
837
838 log_info("Everything completed.");
839 return 0;
840}
841
842static int copy_skel(int root_fd, const char *skel) {
843 int r;
844
845 assert(root_fd >= 0);
846
847 r = copy_tree_at(AT_FDCWD, skel, root_fd, ".", UID_INVALID, GID_INVALID, COPY_MERGE|COPY_REPLACE);
848 if (r == -ENOENT) {
849 log_info("Skeleton directory %s missing, ignoring.", skel);
850 return 0;
851 }
852 if (r < 0)
853 return log_error_errno(r, "Failed to copy in %s: %m", skel);
854
855 log_info("Copying in %s completed.", skel);
856 return 0;
857}
858
859static int change_access_mode(int root_fd, mode_t m) {
860 assert(root_fd >= 0);
861
862 if (fchmod(root_fd, m) < 0)
863 return log_error_errno(errno, "Failed to change access mode of top-level directory: %m");
864
865 log_info("Changed top-level directory access mode to 0%o.", m);
866 return 0;
867}
868
869int home_populate(UserRecord *h, int dir_fd) {
870 int r;
871
872 assert(h);
873 assert(dir_fd >= 0);
874
875 r = copy_skel(dir_fd, user_record_skeleton_directory(h));
876 if (r < 0)
877 return r;
878
879 r = home_store_embedded_identity(h, dir_fd, h->uid, NULL);
880 if (r < 0)
881 return r;
882
883 r = chown_recursive_directory(dir_fd, h->uid);
884 if (r < 0)
885 return r;
886
887 r = change_access_mode(dir_fd, user_record_access_mode(h));
888 if (r < 0)
889 return r;
890
891 return 0;
892}
893
894static int user_record_compile_effective_passwords(
895 UserRecord *h,
7b78db28
LP
896 PasswordCache *cache,
897 char ***ret_effective_passwords) {
70a5db58 898
7b78db28 899 _cleanup_(strv_free_erasep) char **effective = NULL;
70a5db58
LP
900 size_t n;
901 char **i;
902 int r;
903
904 assert(h);
7b78db28 905 assert(cache);
70a5db58
LP
906
907 /* We insist on at least one classic hashed password to be defined in addition to any PKCS#11 one, as
908 * a safe fallback, but also to simplify the password changing algorithm: there we require providing
909 * the old literal password only (and do not care for the old PKCS#11 token) */
910
911 if (strv_isempty(h->hashed_password))
912 return log_error_errno(EINVAL, "User record has no hashed passwords, refusing.");
913
914 /* Generates the list of plaintext passwords to propagate to LUKS/fscrypt devices, and checks whether
915 * we have a plaintext password for each hashed one. If we are missing one we'll fail, since we
916 * couldn't sync fscrypt/LUKS to the login account properly. */
917
918 STRV_FOREACH(i, h->hashed_password) {
919 bool found = false;
920 char **j;
921
922 log_debug("Looking for plaintext password for: %s", *i);
923
924 /* Let's scan all provided plaintext passwords */
925 STRV_FOREACH(j, h->password) {
926 r = test_password_one(*i, *j);
927 if (r < 0)
87d7893c 928 return log_error_errno(r, "Failed to test plaintext password: %m");
70a5db58
LP
929 if (r > 0) {
930 if (ret_effective_passwords) {
931 r = strv_extend(&effective, *j);
932 if (r < 0)
933 return log_oom();
934 }
935
936 log_debug("Found literal plaintext password.");
937 found = true;
938 break;
939 }
940 }
941
942 if (!found)
943 return log_error_errno(SYNTHETIC_ERRNO(ENOKEY), "Missing plaintext password for defined hashed password");
944 }
945
87d7893c
LP
946 for (n = 0; n < h->n_recovery_key; n++) {
947 bool found = false;
948 char **j;
949
950 log_debug("Looking for plaintext recovery key for: %s", h->recovery_key[n].hashed_password);
951
952 STRV_FOREACH(j, h->password) {
953 _cleanup_(erase_and_freep) char *mangled = NULL;
954 const char *p;
955
956 if (streq(h->recovery_key[n].type, "modhex64")) {
957
958 r = normalize_recovery_key(*j, &mangled);
959 if (r == -EINVAL) /* Not properly formatted, probably a regular password. */
960 continue;
961 if (r < 0)
962 return log_error_errno(r, "Failed to normalize recovery key: %m");
963
964 p = mangled;
965 } else
966 p = *j;
967
968 r = test_password_one(h->recovery_key[n].hashed_password, p);
969 if (r < 0)
970 return log_error_errno(r, "Failed to test plaintext recovery key: %m");
971 if (r > 0) {
972 if (ret_effective_passwords) {
973 r = strv_extend(&effective, p);
974 if (r < 0)
975 return log_oom();
976 }
977
978 log_debug("Found plaintext recovery key.");
979 found = true;
980 break;
981 }
982 }
983
984 if (!found)
985 return log_error_errno(SYNTHETIC_ERRNO(EREMOTEIO), "Missing plaintext recovery key for defined recovery key");
986 }
987
70a5db58
LP
988 for (n = 0; n < h->n_pkcs11_encrypted_key; n++) {
989#if HAVE_P11KIT
990 _cleanup_(pkcs11_callback_data_release) struct pkcs11_callback_data data = {
991 .user_record = h,
992 .secret = h,
993 .encrypted_key = h->pkcs11_encrypted_key + n,
994 };
995
996 r = pkcs11_find_token(data.encrypted_key->uri, pkcs11_callback, &data);
997 if (r == -EAGAIN)
998 return -EBADSLT;
999 if (r < 0)
1000 return r;
1001
1002 r = test_password_one(data.encrypted_key->hashed_password, data.decrypted_password);
1003 if (r < 0)
1004 return log_error_errno(r, "Failed to test PKCS#11 password: %m");
1005 if (r == 0)
1006 return log_error_errno(SYNTHETIC_ERRNO(EPERM), "Decrypted password from token is not correct, refusing.");
1007
1008 if (ret_effective_passwords) {
1009 r = strv_extend(&effective, data.decrypted_password);
1010 if (r < 0)
1011 return log_oom();
1012 }
1013
7b78db28
LP
1014 r = strv_extend(&cache->pkcs11_passwords, data.decrypted_password);
1015 if (r < 0)
1016 return log_oom();
1017#else
1018 return -EBADSLT;
1019#endif
1020 }
1021
1022 for (n = 0; n < h->n_fido2_hmac_salt; n++) {
1023#if HAVE_LIBFIDO2
1024 _cleanup_(erase_and_freep) char *decrypted_password = NULL;
1025
1026 r = fido2_use_token(h, h, h->fido2_hmac_salt + n, &decrypted_password);
1027 if (r < 0)
1028 return r;
1029
1030 r = test_password_one(h->fido2_hmac_salt[n].hashed_password, decrypted_password);
1031 if (r < 0)
1032 return log_error_errno(r, "Failed to test FIDO2 password: %m");
1033 if (r == 0)
1034 return log_error_errno(SYNTHETIC_ERRNO(EPERM), "Decrypted password from token is not correct, refusing.");
1035
1036 if (ret_effective_passwords) {
1037 r = strv_extend(&effective, decrypted_password);
70a5db58
LP
1038 if (r < 0)
1039 return log_oom();
1040 }
7b78db28
LP
1041
1042 r = strv_extend(&cache->fido2_passwords, decrypted_password);
1043 if (r < 0)
1044 return log_oom();
70a5db58
LP
1045#else
1046 return -EBADSLT;
1047#endif
1048 }
1049
1050 if (ret_effective_passwords)
1051 *ret_effective_passwords = TAKE_PTR(effective);
70a5db58
LP
1052
1053 return 0;
1054}
1055
1dfe5de0
LP
1056static int determine_default_storage(UserStorage *ret) {
1057 UserStorage storage = _USER_STORAGE_INVALID;
1058 const char *e;
1059 int r;
1060
1061 assert(ret);
1062
1063 /* homed tells us via an environment variable which default storage to use */
1064 e = getenv("SYSTEMD_HOME_DEFAULT_STORAGE");
1065 if (e) {
1066 storage = user_storage_from_string(e);
1067 if (storage < 0)
1068 log_warning("$SYSTEMD_HOME_DEFAULT_STORAGE set to invalid storage type, ignoring: %s", e);
1069 else {
1070 log_info("Using configured default storage '%s'.", user_storage_to_string(storage));
1071 *ret = storage;
1072 return 0;
1073 }
1074 }
1075
1076 /* When neither user nor admin specified the storage type to use, fix it to be LUKS — unless we run
1077 * in a container where loopback devices and LUKS/DM are not available. Also, if /home is encrypted
1078 * anyway, let's avoid duplicate encryption. Note that we typically default to the assumption of
1079 * "classic" storage for most operations. However, if we create a new home, then let's user LUKS if
1080 * nothing is specified. */
1081
1082 r = detect_container();
1083 if (r < 0)
1084 return log_error_errno(r, "Failed to determine whether we are in a container: %m");
1085 if (r == 0) {
1086 r = path_is_encrypted("/home");
1087 if (r < 0)
1088 log_warning_errno(r, "Failed to determine if /home is encrypted, ignoring: %m");
1089 if (r <= 0) {
1090 log_info("Using automatic default storage of '%s'.", user_storage_to_string(USER_LUKS));
1091 *ret = USER_LUKS;
1092 return 0;
1093 }
1094
1095 log_info("/home is encrypted, not using '%s' storage, in order to avoid double encryption.", user_storage_to_string(USER_LUKS));
1096 } else
1097 log_info("Running in container, not using '%s' storage.", user_storage_to_string(USER_LUKS));
1098
1099 r = path_is_fs_type("/home", BTRFS_SUPER_MAGIC);
1100 if (r < 0)
1101 log_warning_errno(r, "Failed to determine file system of /home, ignoring: %m");
1102 if (r > 0) {
1103 log_info("/home is on btrfs, using '%s' as storage.", user_storage_to_string(USER_SUBVOLUME));
1104 *ret = USER_SUBVOLUME;
1105 } else {
1106 log_info("/home is on simple file system, using '%s' as storage.", user_storage_to_string(USER_DIRECTORY));
1107 *ret = USER_DIRECTORY;
1108 }
1109
1110 return 0;
1111}
1112
70a5db58 1113static int home_create(UserRecord *h, UserRecord **ret_home) {
7b78db28 1114 _cleanup_(strv_free_erasep) char **effective_passwords = NULL;
70a5db58 1115 _cleanup_(user_record_unrefp) UserRecord *new_home = NULL;
7b78db28 1116 _cleanup_(password_cache_free) PasswordCache cache = {};
1dfe5de0
LP
1117 UserStorage new_storage = _USER_STORAGE_INVALID;
1118 const char *new_fs = NULL;
70a5db58
LP
1119 int r;
1120
1121 assert(h);
1122
1123 if (!h->user_name)
1124 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "User record lacks name, refusing.");
1125 if (!uid_is_valid(h->uid))
1126 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "User record lacks UID, refusing.");
1127
7b78db28 1128 r = user_record_compile_effective_passwords(h, &cache, &effective_passwords);
70a5db58
LP
1129 if (r < 0)
1130 return r;
1131
1132 r = user_record_test_home_directory_and_warn(h);
1133 if (r < 0)
1134 return r;
1135 if (r != USER_TEST_ABSENT)
1136 return log_error_errno(SYNTHETIC_ERRNO(EEXIST), "Home directory %s already exists, refusing.", user_record_home_directory(h));
1137
70a5db58 1138 if (h->storage < 0) {
1dfe5de0 1139 r = determine_default_storage(&new_storage);
70a5db58 1140 if (r < 0)
1dfe5de0
LP
1141 return r;
1142 }
70a5db58 1143
1dfe5de0
LP
1144 if ((h->storage == USER_LUKS ||
1145 (h->storage < 0 && new_storage == USER_LUKS)) &&
1146 !h->file_system_type)
1147 new_fs = getenv("SYSTEMD_HOME_DEFAULT_FILE_SYSTEM_TYPE");
70a5db58 1148
1dfe5de0 1149 if (new_storage >= 0 || new_fs) {
70a5db58
LP
1150 r = user_record_add_binding(
1151 h,
1152 new_storage,
1153 NULL,
1154 SD_ID128_NULL,
1155 SD_ID128_NULL,
1156 SD_ID128_NULL,
1157 NULL,
1158 NULL,
1159 UINT64_MAX,
1dfe5de0 1160 new_fs,
70a5db58
LP
1161 NULL,
1162 UID_INVALID,
1163 GID_INVALID);
1164 if (r < 0)
1165 return log_error_errno(r, "Failed to change storage type to LUKS: %m");
70a5db58
LP
1166 }
1167
1168 r = user_record_test_image_path_and_warn(h);
1169 if (r < 0)
1170 return r;
1171 if (!IN_SET(r, USER_TEST_ABSENT, USER_TEST_UNDEFINED, USER_TEST_MAYBE))
1172 return log_error_errno(SYNTHETIC_ERRNO(EEXIST), "Image path %s already exists, refusing.", user_record_image_path(h));
1173
1174 switch (user_record_storage(h)) {
1175
1176 case USER_LUKS:
7b78db28 1177 r = home_create_luks(h, &cache, effective_passwords, &new_home);
70a5db58
LP
1178 break;
1179
1180 case USER_DIRECTORY:
1181 case USER_SUBVOLUME:
1182 r = home_create_directory_or_subvolume(h, &new_home);
1183 break;
1184
1185 case USER_FSCRYPT:
1186 r = home_create_fscrypt(h, effective_passwords, &new_home);
1187 break;
1188
1189 case USER_CIFS:
1190 r = home_create_cifs(h, &new_home);
1191 break;
1192
1193 default:
1194 return log_error_errno(SYNTHETIC_ERRNO(ENOTTY),
1195 "Creating home directories of type '%s' currently not supported.", user_storage_to_string(user_record_storage(h)));
1196 }
1197 if (r < 0)
1198 return r;
1199
1200 if (user_record_equal(h, new_home)) {
1201 *ret_home = NULL;
1202 return 0;
1203 }
1204
1205 *ret_home = TAKE_PTR(new_home);
1206 return 1;
1207}
1208
1209static int home_remove(UserRecord *h) {
1210 bool deleted = false;
1211 const char *ip, *hd;
1212 int r;
1213
1214 assert(h);
1215
1216 if (!h->user_name)
1217 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "User record lacks user name, refusing.");
1218 if (!IN_SET(user_record_storage(h), USER_LUKS, USER_DIRECTORY, USER_SUBVOLUME, USER_FSCRYPT, USER_CIFS))
1219 return log_error_errno(SYNTHETIC_ERRNO(ENOTTY), "Removing home directories of type '%s' currently not supported.", user_storage_to_string(user_record_storage(h)));
1220
1221 hd = user_record_home_directory(h);
1222
1223 r = user_record_test_home_directory_and_warn(h);
1224 if (r < 0)
1225 return r;
1226 if (r == USER_TEST_MOUNTED)
1227 return log_error_errno(SYNTHETIC_ERRNO(EBUSY), "Directory %s is still mounted, refusing.", hd);
1228
1229 assert(hd);
1230
1231 r = user_record_test_image_path_and_warn(h);
1232 if (r < 0)
1233 return r;
1234
1235 ip = user_record_image_path(h);
1236
1237 switch (user_record_storage(h)) {
1238
1239 case USER_LUKS: {
1240 struct stat st;
1241
1242 assert(ip);
1243
1244 if (stat(ip, &st) < 0) {
6b8664cb 1245 if (errno != ENOENT)
80ace4f2 1246 return log_error_errno(errno, "Failed to stat() %s: %m", ip);
70a5db58
LP
1247
1248 } else {
1249 if (S_ISREG(st.st_mode)) {
1250 if (unlink(ip) < 0) {
1251 if (errno != ENOENT)
1252 return log_error_errno(errno, "Failed to remove %s: %m", ip);
1253 } else
1254 deleted = true;
1255
1256 } else if (S_ISBLK(st.st_mode))
1257 log_info("Not removing file system on block device %s.", ip);
1258 else
1259 return log_error_errno(SYNTHETIC_ERRNO(ENOTBLK), "Image file %s is neither block device, nor regular, refusing removal.", ip);
1260 }
1261
1262 break;
1263 }
1264
1265 case USER_SUBVOLUME:
1266 case USER_DIRECTORY:
1267 case USER_FSCRYPT:
1268 assert(ip);
1269
1270 r = rm_rf(ip, REMOVE_ROOT|REMOVE_PHYSICAL|REMOVE_SUBVOLUME);
1271 if (r < 0) {
1272 if (r != -ENOENT)
1273 return log_warning_errno(r, "Failed to remove %s: %m", ip);
1274 } else
1275 deleted = true;
1276
1277 /* If the image path and the home directory are the same invalidate the home directory, so
1278 * that we don't remove it anymore */
1279 if (path_equal(ip, hd))
1280 hd = NULL;
1281
1282 break;
1283
1284 case USER_CIFS:
1285 /* Nothing else to do here: we won't remove remote stuff. */
1286 log_info("Not removing home directory on remote server.");
1287 break;
1288
1289 default:
1290 assert_not_reached("unknown storage type");
1291 }
1292
1293 if (hd) {
1294 if (rmdir(hd) < 0) {
1295 if (errno != ENOENT)
1296 return log_error_errno(errno, "Failed to remove %s, ignoring: %m", hd);
1297 } else
1298 deleted = true;
1299 }
1300
1301 if (deleted)
1302 log_info("Everything completed.");
e4ff0393
FS
1303 else
1304 return log_notice_errno(SYNTHETIC_ERRNO(EALREADY),
1305 "Nothing to remove.");
70a5db58
LP
1306
1307 return 0;
1308}
1309
1310static int home_validate_update(UserRecord *h, HomeSetup *setup) {
1311 bool has_mount = false;
1312 int r;
1313
1314 assert(h);
1315 assert(setup);
1316
1317 if (!h->user_name)
1318 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "User record lacks user name, refusing.");
1319 if (!uid_is_valid(h->uid))
1320 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "User record lacks UID, refusing.");
1321 if (!IN_SET(user_record_storage(h), USER_LUKS, USER_DIRECTORY, USER_SUBVOLUME, USER_FSCRYPT, USER_CIFS))
1322 return log_error_errno(SYNTHETIC_ERRNO(ENOTTY), "Processing home directories of type '%s' currently not supported.", user_storage_to_string(user_record_storage(h)));
1323
1324 r = user_record_test_home_directory_and_warn(h);
1325 if (r < 0)
1326 return r;
1327
1328 has_mount = r == USER_TEST_MOUNTED;
1329
1330 r = user_record_test_image_path_and_warn(h);
1331 if (r < 0)
1332 return r;
1333 if (r == USER_TEST_ABSENT)
1334 return log_error_errno(SYNTHETIC_ERRNO(ENOENT), "Image path %s does not exist", user_record_image_path(h));
1335
1336 switch (user_record_storage(h)) {
1337
1338 case USER_DIRECTORY:
1339 case USER_SUBVOLUME:
1340 case USER_FSCRYPT:
1341 case USER_CIFS:
1342 break;
1343
1344 case USER_LUKS: {
1345 r = home_validate_update_luks(h, setup);
1346 if (r < 0)
1347 return r;
1348 if ((r > 0) != has_mount)
1349 return log_error_errno(SYNTHETIC_ERRNO(EBUSY), "Home mount incompletely set up.");
1350
1351 break;
1352 }
1353
1354 default:
1355 assert_not_reached("unexpected storage type");
1356 }
1357
1358 return has_mount; /* return true if the home record is already active */
1359}
1360
1361static int home_update(UserRecord *h, UserRecord **ret) {
1362 _cleanup_(user_record_unrefp) UserRecord *new_home = NULL, *header_home = NULL, *embedded_home = NULL;
70a5db58 1363 _cleanup_(home_setup_undo) HomeSetup setup = HOME_SETUP_INIT;
7b78db28 1364 _cleanup_(password_cache_free) PasswordCache cache = {};
70a5db58
LP
1365 bool already_activated = false;
1366 int r;
1367
1368 assert(h);
1369 assert(ret);
1370
7b78db28 1371 r = user_record_authenticate(h, h, &cache, /* strict_verify= */ true);
70a5db58
LP
1372 if (r < 0)
1373 return r;
c8f145ad 1374 assert(r > 0); /* Insist that a password was verified */
70a5db58
LP
1375
1376 r = home_validate_update(h, &setup);
1377 if (r < 0)
1378 return r;
1379
1380 already_activated = r > 0;
1381
7b78db28 1382 r = home_prepare(h, already_activated, &cache, &setup, &header_home);
70a5db58
LP
1383 if (r < 0)
1384 return r;
1385
7b78db28 1386 r = home_load_embedded_identity(h, setup.root_fd, header_home, USER_RECONCILE_REQUIRE_NEWER, &cache, &embedded_home, &new_home);
70a5db58
LP
1387 if (r < 0)
1388 return r;
1389
1390 r = home_store_header_identity_luks(new_home, &setup, header_home);
1391 if (r < 0)
1392 return r;
1393
1394 r = home_store_embedded_identity(new_home, setup.root_fd, h->uid, embedded_home);
1395 if (r < 0)
1396 return r;
1397
1398 r = home_extend_embedded_identity(new_home, h, &setup);
1399 if (r < 0)
1400 return r;
1401
1402 r = home_sync_and_statfs(setup.root_fd, NULL);
1403 if (r < 0)
1404 return r;
1405
1406 r = home_setup_undo(&setup);
1407 if (r < 0)
1408 return r;
1409
1410 log_info("Everything completed.");
1411
1412 *ret = TAKE_PTR(new_home);
1413 return 0;
1414}
1415
1416static int home_resize(UserRecord *h, UserRecord **ret) {
1417 _cleanup_(home_setup_undo) HomeSetup setup = HOME_SETUP_INIT;
7b78db28 1418 _cleanup_(password_cache_free) PasswordCache cache = {};
70a5db58
LP
1419 bool already_activated = false;
1420 int r;
1421
1422 assert(h);
1423 assert(ret);
1424
1425 if (h->disk_size == UINT64_MAX)
1426 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "No target size specified, refusing.");
1427
7b78db28 1428 r = user_record_authenticate(h, h, &cache, /* strict_verify= */ true);
70a5db58
LP
1429 if (r < 0)
1430 return r;
c8f145ad 1431 assert(r > 0); /* Insist that a password was verified */
70a5db58
LP
1432
1433 r = home_validate_update(h, &setup);
1434 if (r < 0)
1435 return r;
1436
1437 already_activated = r > 0;
1438
1439 switch (user_record_storage(h)) {
1440
1441 case USER_LUKS:
7b78db28 1442 return home_resize_luks(h, already_activated, &cache, &setup, ret);
70a5db58
LP
1443
1444 case USER_DIRECTORY:
1445 case USER_SUBVOLUME:
1446 case USER_FSCRYPT:
7b78db28 1447 return home_resize_directory(h, already_activated, &cache, &setup, ret);
70a5db58
LP
1448
1449 default:
1450 return log_error_errno(SYNTHETIC_ERRNO(ENOTTY), "Resizing home directories of type '%s' currently not supported.", user_storage_to_string(user_record_storage(h)));
1451 }
1452}
1453
1454static int home_passwd(UserRecord *h, UserRecord **ret_home) {
1455 _cleanup_(user_record_unrefp) UserRecord *header_home = NULL, *embedded_home = NULL, *new_home = NULL;
7b78db28 1456 _cleanup_(strv_free_erasep) char **effective_passwords = NULL;
70a5db58 1457 _cleanup_(home_setup_undo) HomeSetup setup = HOME_SETUP_INIT;
7b78db28 1458 _cleanup_(password_cache_free) PasswordCache cache = {};
70a5db58
LP
1459 bool already_activated = false;
1460 int r;
1461
1462 assert(h);
1463 assert(ret_home);
1464
1465 if (!IN_SET(user_record_storage(h), USER_LUKS, USER_DIRECTORY, USER_SUBVOLUME, USER_FSCRYPT))
1466 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)));
1467
7b78db28 1468 r = user_record_compile_effective_passwords(h, &cache, &effective_passwords);
70a5db58
LP
1469 if (r < 0)
1470 return r;
1471
1472 r = home_validate_update(h, &setup);
1473 if (r < 0)
1474 return r;
1475
1476 already_activated = r > 0;
1477
7b78db28 1478 r = home_prepare(h, already_activated, &cache, &setup, &header_home);
70a5db58
LP
1479 if (r < 0)
1480 return r;
1481
7b78db28 1482 r = home_load_embedded_identity(h, setup.root_fd, header_home, USER_RECONCILE_REQUIRE_NEWER_OR_EQUAL, &cache, &embedded_home, &new_home);
70a5db58
LP
1483 if (r < 0)
1484 return r;
1485
1486 switch (user_record_storage(h)) {
1487
1488 case USER_LUKS:
7b78db28 1489 r = home_passwd_luks(h, &setup, &cache, effective_passwords);
70a5db58
LP
1490 if (r < 0)
1491 return r;
1492 break;
1493
1494 case USER_FSCRYPT:
7b78db28 1495 r = home_passwd_fscrypt(h, &setup, &cache, effective_passwords);
70a5db58
LP
1496 if (r < 0)
1497 return r;
1498 break;
1499
1500 default:
1501 break;
1502 }
1503
1504 r = home_store_header_identity_luks(new_home, &setup, header_home);
1505 if (r < 0)
1506 return r;
1507
1508 r = home_store_embedded_identity(new_home, setup.root_fd, h->uid, embedded_home);
1509 if (r < 0)
1510 return r;
1511
1512 r = home_extend_embedded_identity(new_home, h, &setup);
1513 if (r < 0)
1514 return r;
1515
1516 r = home_sync_and_statfs(setup.root_fd, NULL);
1517 if (r < 0)
1518 return r;
1519
1520 r = home_setup_undo(&setup);
1521 if (r < 0)
1522 return r;
1523
1524 log_info("Everything completed.");
1525
1526 *ret_home = TAKE_PTR(new_home);
1527 return 1;
1528}
1529
1530static int home_inspect(UserRecord *h, UserRecord **ret_home) {
1531 _cleanup_(user_record_unrefp) UserRecord *header_home = NULL, *new_home = NULL;
1532 _cleanup_(home_setup_undo) HomeSetup setup = HOME_SETUP_INIT;
7b78db28 1533 _cleanup_(password_cache_free) PasswordCache cache = {};
70a5db58
LP
1534 bool already_activated = false;
1535 int r;
1536
1537 assert(h);
1538 assert(ret_home);
1539
7b78db28 1540 r = user_record_authenticate(h, h, &cache, /* strict_verify= */ false);
70a5db58
LP
1541 if (r < 0)
1542 return r;
1543
1544 r = home_validate_update(h, &setup);
1545 if (r < 0)
1546 return r;
1547
1548 already_activated = r > 0;
1549
7b78db28 1550 r = home_prepare(h, already_activated, &cache, &setup, &header_home);
70a5db58
LP
1551 if (r < 0)
1552 return r;
1553
7b78db28 1554 r = home_load_embedded_identity(h, setup.root_fd, header_home, USER_RECONCILE_ANY, &cache, NULL, &new_home);
70a5db58
LP
1555 if (r < 0)
1556 return r;
1557
1558 r = home_extend_embedded_identity(new_home, h, &setup);
1559 if (r < 0)
1560 return r;
1561
1562 r = home_setup_undo(&setup);
1563 if (r < 0)
1564 return r;
1565
1566 log_info("Everything completed.");
1567
1568 *ret_home = TAKE_PTR(new_home);
1569 return 1;
1570}
1571
1572static int home_lock(UserRecord *h) {
1573 int r;
1574
1575 assert(h);
1576
1577 if (!h->user_name)
1578 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "User record incomplete, refusing.");
1579 if (user_record_storage(h) != USER_LUKS)
1580 return log_error_errno(SYNTHETIC_ERRNO(ENOTTY), "Locking home directories of type '%s' currently not supported.", user_storage_to_string(user_record_storage(h)));
1581
1582 r = user_record_test_home_directory_and_warn(h);
1583 if (r < 0)
1584 return r;
1585 if (r != USER_TEST_MOUNTED)
1586 return log_error_errno(SYNTHETIC_ERRNO(ENOEXEC), "Home directory of %s is not mounted, can't lock.", h->user_name);
1587
1588 r = home_lock_luks(h);
1589 if (r < 0)
1590 return r;
1591
1592 log_info("Everything completed.");
1593 return 1;
1594}
1595
1596static int home_unlock(UserRecord *h) {
7b78db28 1597 _cleanup_(password_cache_free) PasswordCache cache = {};
70a5db58
LP
1598 int r;
1599
1600 assert(h);
1601
1602 if (!h->user_name)
1603 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "User record incomplete, refusing.");
1604 if (user_record_storage(h) != USER_LUKS)
1605 return log_error_errno(SYNTHETIC_ERRNO(ENOTTY), "Unlocking home directories of type '%s' currently not supported.", user_storage_to_string(user_record_storage(h)));
1606
1607 /* Note that we don't check if $HOME is actually mounted, since we want to avoid disk accesses on
1608 * that mount until we have resumed the device. */
1609
7b78db28 1610 r = user_record_authenticate(h, h, &cache, /* strict_verify= */ false);
70a5db58
LP
1611 if (r < 0)
1612 return r;
1613
7b78db28 1614 r = home_unlock_luks(h, &cache);
70a5db58
LP
1615 if (r < 0)
1616 return r;
1617
1618 log_info("Everything completed.");
1619 return 1;
1620}
1621
1622static int run(int argc, char *argv[]) {
1623 _cleanup_(user_record_unrefp) UserRecord *home = NULL, *new_home = NULL;
1624 _cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
1625 _cleanup_(fclosep) FILE *opened_file = NULL;
1626 unsigned line = 0, column = 0;
1627 const char *json_path = NULL;
1628 FILE *json_file;
1629 usec_t start;
1630 int r;
1631
1632 start = now(CLOCK_MONOTONIC);
1633
1634 log_setup_service();
1635
1636 umask(0022);
1637
1638 if (argc < 2 || argc > 3)
1639 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "This program takes one or two arguments.");
1640
1641 if (argc > 2) {
1642 json_path = argv[2];
1643
1644 opened_file = fopen(json_path, "re");
1645 if (!opened_file)
1646 return log_error_errno(errno, "Failed to open %s: %m", json_path);
1647
1648 json_file = opened_file;
1649 } else {
1650 json_path = "<stdin>";
1651 json_file = stdin;
1652 }
1653
1654 r = json_parse_file(json_file, json_path, JSON_PARSE_SENSITIVE, &v, &line, &column);
1655 if (r < 0)
1656 return log_error_errno(r, "[%s:%u:%u] Failed to parse JSON data: %m", json_path, line, column);
1657
1658 home = user_record_new();
1659 if (!home)
1660 return log_oom();
1661
1662 r = user_record_load(home, v, USER_RECORD_LOAD_FULL|USER_RECORD_LOG);
1663 if (r < 0)
1664 return r;
1665
1666 /* Well known return values of these operations, that systemd-homed knows and converts to proper D-Bus errors:
1667 *
162392b7
ZJS
1668 * EMSGSIZE → file systems of this type cannot be shrunk
1669 * ETXTBSY → file systems of this type can only be shrunk offline
70a5db58
LP
1670 * ERANGE → file system size too small
1671 * ENOLINK → system does not support selected storage backend
1672 * EPROTONOSUPPORT → system does not support selected file system
1673 * ENOTTY → operation not support on this storage
1674 * ESOCKTNOSUPPORT → operation not support on this file system
1675 * ENOKEY → password incorrect (or not sufficient, or not supplied)
87d7893c 1676 * EREMOTEIO → recovery key incorrect (or not sufficeint, or not supplied — only if no passwords defined)
70a5db58 1677 * 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 1678 * ENOANO → suitable PKCS#11/FIDO2 device found, but PIN is missing to unlock it
70a5db58 1679 * ERFKILL → suitable PKCS#11 device found, but OK to ask for on-device interactive authentication not given
7b78db28
LP
1680 * EMEDIUMTYPE → suitable FIDO2 device found, but OK to ask for user presence not given
1681 * ENOSTR → suitable FIDO2 device found, but user didn't react to action request on token quickly enough
1682 * EOWNERDEAD → suitable PKCS#11/FIDO2 device found, but its PIN is locked
1683 * ENOLCK → suitable PKCS#11/FIDO2 device found, but PIN incorrect
70a5db58
LP
1684 * ETOOMANYREFS → suitable PKCS#11 device found, but PIN incorrect, and only few tries left
1685 * EUCLEAN → suitable PKCS#11 device found, but PIN incorrect, and only one try left
1686 * EBUSY → file system is currently active
1687 * ENOEXEC → file system is currently not active
1688 * ENOSPC → not enough disk space for operation
cbffdcec 1689 * EKEYREVOKED → user record has not suitable hashed password or pkcs#11 entry, we cannot authenticate
70a5db58
LP
1690 */
1691
1692 if (streq(argv[1], "activate"))
1693 r = home_activate(home, &new_home);
1694 else if (streq(argv[1], "deactivate"))
1695 r = home_deactivate(home, false);
1696 else if (streq(argv[1], "deactivate-force"))
1697 r = home_deactivate(home, true);
1698 else if (streq(argv[1], "create"))
1699 r = home_create(home, &new_home);
1700 else if (streq(argv[1], "remove"))
1701 r = home_remove(home);
1702 else if (streq(argv[1], "update"))
1703 r = home_update(home, &new_home);
1704 else if (streq(argv[1], "resize"))
1705 r = home_resize(home, &new_home);
1706 else if (streq(argv[1], "passwd"))
1707 r = home_passwd(home, &new_home);
1708 else if (streq(argv[1], "inspect"))
1709 r = home_inspect(home, &new_home);
1710 else if (streq(argv[1], "lock"))
1711 r = home_lock(home);
1712 else if (streq(argv[1], "unlock"))
1713 r = home_unlock(home);
1714 else
1715 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown verb '%s'.", argv[1]);
87d7893c 1716 if (IN_SET(r, -ENOKEY, -EREMOTEIO) && !strv_isempty(home->password) ) { /* There were passwords specified but they were incorrect */
70a5db58
LP
1717 usec_t end, n, d;
1718
1719 /* Make sure bad password replies always take at least 3s, and if longer multiples of 3s, so
1720 * that it's not clear how long we actually needed for our calculations. */
1721 n = now(CLOCK_MONOTONIC);
1722 assert(n >= start);
1723
1724 d = usec_sub_unsigned(n, start);
1725 if (d > BAD_PASSWORD_DELAY_USEC)
1726 end = start + DIV_ROUND_UP(d, BAD_PASSWORD_DELAY_USEC) * BAD_PASSWORD_DELAY_USEC;
1727 else
1728 end = start + BAD_PASSWORD_DELAY_USEC;
1729
1730 if (n < end)
1731 (void) usleep(usec_sub_unsigned(end, n));
1732 }
1733 if (r < 0)
1734 return r;
1735
1736 /* We always pass the new record back, regardless if it changed or not. This allows our caller to
1737 * prepare a fresh record, send to us, and only if it works use it without having to keep a local
1738 * copy. */
1739 if (new_home)
1740 json_variant_dump(new_home->json, JSON_FORMAT_NEWLINE, stdout, NULL);
1741
1742 return 0;
1743}
1744
1745DEFINE_MAIN_FUNCTION(run);