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