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