Skip to content

Commit c8f145a

Browse files
committed
homed: don't insist on authentication against host-copy user record
homed maintains two or three copies of the user's identity record per home directory: one on the host, one inside the LUKS header, and one embedded in the home directory. Previously we'd insist that if a user logs in they have to authenticate against all three, as a safety feature. This broke logging into unfixated records however, since in that case the host version is synthetic and thus does not carry any authentication data. Let's hence losen the strictness here: accept authentication against host records that carry no auth data. This should be safe as we know after all that the second/third record will catch invalid accesses. Fixes: systemd#15178
1 parent 1a53adb commit c8f145a

File tree

3 files changed

+29
-13
lines changed

3 files changed

+29
-13
lines changed

src/home/homework-luks.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -727,9 +727,10 @@ static int luks_validate_home_record(
727727
if (!user_record_compatible(h, lhr))
728728
return log_error_errno(SYNTHETIC_ERRNO(EREMCHG), "LUKS home record not compatible with host record, refusing.");
729729

730-
r = user_record_authenticate(lhr, h, pkcs11_decrypted_passwords);
730+
r = user_record_authenticate(lhr, h, pkcs11_decrypted_passwords, /* strict_verify= */ true);
731731
if (r < 0)
732732
return r;
733+
assert(r > 0); /* Insist that a password was verified */
733734

734735
*ret_luks_home_record = TAKE_PTR(lhr);
735736
return 0;

src/home/homework.c

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@
3535
int user_record_authenticate(
3636
UserRecord *h,
3737
UserRecord *secret,
38-
char ***pkcs11_decrypted_passwords) {
38+
char ***pkcs11_decrypted_passwords,
39+
bool strict_verify) {
3940

4041
bool need_password = false, need_token = false, need_pin = false, need_protected_authentication_path_permitted = false,
4142
pin_locked = false, pin_incorrect = false, pin_incorrect_few_tries_left = false, pin_incorrect_one_try_left = false;
@@ -66,7 +67,7 @@ int user_record_authenticate(
6667
return log_error_errno(r, "Failed to validate password of record: %m");
6768
else {
6869
log_info("Provided password unlocks user record.");
69-
return 0;
70+
return 1;
7071
}
7172

7273
/* Second, let's see if any of the PKCS#11 security tokens are plugged in and help us */
@@ -86,7 +87,7 @@ int user_record_authenticate(
8687
return log_error_errno(r, "Failed to check supplied PKCS#11 password: %m");
8788
if (r > 0) {
8889
log_info("Previously acquired PKCS#11 password unlocks user record.");
89-
return 0;
90+
return 1;
9091
}
9192
}
9293

@@ -129,7 +130,7 @@ int user_record_authenticate(
129130
if (r < 0)
130131
return log_oom();
131132

132-
return 0;
133+
return 1;
133134
}
134135
#else
135136
need_token = true;
@@ -156,7 +157,18 @@ int user_record_authenticate(
156157
return -ENOKEY;
157158

158159
/* Hmm, this means neither PCKS#11 nor classic hashed passwords were supplied, we cannot authenticate this reasonably */
159-
return log_debug_errno(SYNTHETIC_ERRNO(EKEYREVOKED), "No hashed passwords and no PKCS#11 tokens defined, cannot authenticate user record.");
160+
if (strict_verify)
161+
return log_debug_errno(SYNTHETIC_ERRNO(EKEYREVOKED),
162+
"No hashed passwords and no PKCS#11 tokens defined, cannot authenticate user record, refusing.");
163+
164+
/* If strict verification is off this means we are possibly in the case where we encountered an
165+
* unfixated record, i.e. a synthetic one that accordingly lacks any authentication data. In this
166+
* case, allow the authentication to pass for now, so that the second (or third) authentication level
167+
* (the ones of the user record in the LUKS header or inside the home directory) will then catch
168+
* invalid passwords. The second/third authentication always runs in strict verification mode. */
169+
log_debug("No hashed passwords and no PKCS#11 tokens defined in record, cannot authenticate user record. "
170+
"Deferring to embedded user record.");
171+
return 0;
160172
}
161173

162174
int home_setup_undo(HomeSetup *setup) {
@@ -402,9 +414,10 @@ int home_load_embedded_identity(
402414
return log_error_errno(SYNTHETIC_ERRNO(EREMCHG), "Embedded home record not compatible with host record, refusing.");
403415

404416
/* Insist that credentials the user supplies also unlocks any embedded records. */
405-
r = user_record_authenticate(embedded_home, h, pkcs11_decrypted_passwords);
417+
r = user_record_authenticate(embedded_home, h, pkcs11_decrypted_passwords, /* strict_verify= */ true);
406418
if (r < 0)
407419
return r;
420+
assert(r > 0); /* Insist that a password was verified */
408421

409422
/* At this point we have three records to deal with:
410423
*
@@ -615,7 +628,7 @@ static int home_activate(UserRecord *h, UserRecord **ret_home) {
615628
if (!IN_SET(user_record_storage(h), USER_LUKS, USER_DIRECTORY, USER_SUBVOLUME, USER_FSCRYPT, USER_CIFS))
616629
return log_error_errno(SYNTHETIC_ERRNO(ENOTTY), "Activating home directories of type '%s' currently not supported.", user_storage_to_string(user_record_storage(h)));
617630

618-
r = user_record_authenticate(h, h, &pkcs11_decrypted_passwords);
631+
r = user_record_authenticate(h, h, &pkcs11_decrypted_passwords, /* strict_verify= */ false);
619632
if (r < 0)
620633
return r;
621634

@@ -1177,9 +1190,10 @@ static int home_update(UserRecord *h, UserRecord **ret) {
11771190
assert(h);
11781191
assert(ret);
11791192

1180-
r = user_record_authenticate(h, h, &pkcs11_decrypted_passwords);
1193+
r = user_record_authenticate(h, h, &pkcs11_decrypted_passwords, /* strict_verify= */ true);
11811194
if (r < 0)
11821195
return r;
1196+
assert(r > 0); /* Insist that a password was verified */
11831197

11841198
r = home_validate_update(h, &setup);
11851199
if (r < 0)
@@ -1233,9 +1247,10 @@ static int home_resize(UserRecord *h, UserRecord **ret) {
12331247
if (h->disk_size == UINT64_MAX)
12341248
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "No target size specified, refusing.");
12351249

1236-
r = user_record_authenticate(h, h, &pkcs11_decrypted_passwords);
1250+
r = user_record_authenticate(h, h, &pkcs11_decrypted_passwords, /* strict_verify= */ true);
12371251
if (r < 0)
12381252
return r;
1253+
assert(r > 0); /* Insist that a password was verified */
12391254

12401255
r = home_validate_update(h, &setup);
12411256
if (r < 0)
@@ -1343,7 +1358,7 @@ static int home_inspect(UserRecord *h, UserRecord **ret_home) {
13431358
assert(h);
13441359
assert(ret_home);
13451360

1346-
r = user_record_authenticate(h, h, &pkcs11_decrypted_passwords);
1361+
r = user_record_authenticate(h, h, &pkcs11_decrypted_passwords, /* strict_verify= */ false);
13471362
if (r < 0)
13481363
return r;
13491364

@@ -1413,7 +1428,7 @@ static int home_unlock(UserRecord *h) {
14131428
/* Note that we don't check if $HOME is actually mounted, since we want to avoid disk accesses on
14141429
* that mount until we have resumed the device. */
14151430

1416-
r = user_record_authenticate(h, h, &pkcs11_decrypted_passwords);
1431+
r = user_record_authenticate(h, h, &pkcs11_decrypted_passwords, /* strict_verify= */ false);
14171432
if (r < 0)
14181433
return r;
14191434

src/home/homework.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,6 @@ int home_load_embedded_identity(UserRecord *h, int root_fd, UserRecord *header_h
5656
int home_store_embedded_identity(UserRecord *h, int root_fd, uid_t uid, UserRecord *old_home);
5757
int home_extend_embedded_identity(UserRecord *h, UserRecord *used, HomeSetup *setup);
5858

59-
int user_record_authenticate(UserRecord *h, UserRecord *secret, char ***pkcs11_decrypted_passwords);
59+
int user_record_authenticate(UserRecord *h, UserRecord *secret, char ***pkcs11_decrypted_passwords, bool strict_verify);
6060

6161
int home_sync_and_statfs(int root_fd, struct statfs *ret);

0 commit comments

Comments
 (0)