Skip to content

Commit

Permalink
homed: don't insist on authentication against host-copy user record
Browse files Browse the repository at this point in the history
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
  • Loading branch information
poettering committed May 21, 2020
1 parent 1a53adb commit c8f145a
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 13 deletions.
3 changes: 2 additions & 1 deletion src/home/homework-luks.c
Original file line number Diff line number Diff line change
Expand Up @@ -727,9 +727,10 @@ static int luks_validate_home_record(
if (!user_record_compatible(h, lhr))
return log_error_errno(SYNTHETIC_ERRNO(EREMCHG), "LUKS home record not compatible with host record, refusing.");

r = user_record_authenticate(lhr, h, pkcs11_decrypted_passwords);
r = user_record_authenticate(lhr, h, pkcs11_decrypted_passwords, /* strict_verify= */ true);
if (r < 0)
return r;
assert(r > 0); /* Insist that a password was verified */

*ret_luks_home_record = TAKE_PTR(lhr);
return 0;
Expand Down
37 changes: 26 additions & 11 deletions src/home/homework.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@
int user_record_authenticate(
UserRecord *h,
UserRecord *secret,
char ***pkcs11_decrypted_passwords) {
char ***pkcs11_decrypted_passwords,
bool strict_verify) {

bool need_password = false, need_token = false, need_pin = false, need_protected_authentication_path_permitted = false,
pin_locked = false, pin_incorrect = false, pin_incorrect_few_tries_left = false, pin_incorrect_one_try_left = false;
Expand Down Expand Up @@ -66,7 +67,7 @@ int user_record_authenticate(
return log_error_errno(r, "Failed to validate password of record: %m");
else {
log_info("Provided password unlocks user record.");
return 0;
return 1;
}

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

Expand Down Expand Up @@ -129,7 +130,7 @@ int user_record_authenticate(
if (r < 0)
return log_oom();

return 0;
return 1;
}
#else
need_token = true;
Expand All @@ -156,7 +157,18 @@ int user_record_authenticate(
return -ENOKEY;

/* Hmm, this means neither PCKS#11 nor classic hashed passwords were supplied, we cannot authenticate this reasonably */
return log_debug_errno(SYNTHETIC_ERRNO(EKEYREVOKED), "No hashed passwords and no PKCS#11 tokens defined, cannot authenticate user record.");
if (strict_verify)
return log_debug_errno(SYNTHETIC_ERRNO(EKEYREVOKED),
"No hashed passwords and no PKCS#11 tokens defined, cannot authenticate user record, refusing.");

/* If strict verification is off this means we are possibly in the case where we encountered an
* unfixated record, i.e. a synthetic one that accordingly lacks any authentication data. In this
* case, allow the authentication to pass for now, so that the second (or third) authentication level
* (the ones of the user record in the LUKS header or inside the home directory) will then catch
* invalid passwords. The second/third authentication always runs in strict verification mode. */
log_debug("No hashed passwords and no PKCS#11 tokens defined in record, cannot authenticate user record. "
"Deferring to embedded user record.");
return 0;
}

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

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

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

r = user_record_authenticate(h, h, &pkcs11_decrypted_passwords);
r = user_record_authenticate(h, h, &pkcs11_decrypted_passwords, /* strict_verify= */ false);
if (r < 0)
return r;

Expand Down Expand Up @@ -1177,9 +1190,10 @@ static int home_update(UserRecord *h, UserRecord **ret) {
assert(h);
assert(ret);

r = user_record_authenticate(h, h, &pkcs11_decrypted_passwords);
r = user_record_authenticate(h, h, &pkcs11_decrypted_passwords, /* strict_verify= */ true);
if (r < 0)
return r;
assert(r > 0); /* Insist that a password was verified */

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

r = user_record_authenticate(h, h, &pkcs11_decrypted_passwords);
r = user_record_authenticate(h, h, &pkcs11_decrypted_passwords, /* strict_verify= */ true);
if (r < 0)
return r;
assert(r > 0); /* Insist that a password was verified */

r = home_validate_update(h, &setup);
if (r < 0)
Expand Down Expand Up @@ -1343,7 +1358,7 @@ static int home_inspect(UserRecord *h, UserRecord **ret_home) {
assert(h);
assert(ret_home);

r = user_record_authenticate(h, h, &pkcs11_decrypted_passwords);
r = user_record_authenticate(h, h, &pkcs11_decrypted_passwords, /* strict_verify= */ false);
if (r < 0)
return r;

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

r = user_record_authenticate(h, h, &pkcs11_decrypted_passwords);
r = user_record_authenticate(h, h, &pkcs11_decrypted_passwords, /* strict_verify= */ false);
if (r < 0)
return r;

Expand Down
2 changes: 1 addition & 1 deletion src/home/homework.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,6 @@ int home_load_embedded_identity(UserRecord *h, int root_fd, UserRecord *header_h
int home_store_embedded_identity(UserRecord *h, int root_fd, uid_t uid, UserRecord *old_home);
int home_extend_embedded_identity(UserRecord *h, UserRecord *used, HomeSetup *setup);

int user_record_authenticate(UserRecord *h, UserRecord *secret, char ***pkcs11_decrypted_passwords);
int user_record_authenticate(UserRecord *h, UserRecord *secret, char ***pkcs11_decrypted_passwords, bool strict_verify);

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

0 comments on commit c8f145a

Please sign in to comment.