]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
homed: don't insist on authentication against host-copy user record 15869/head
authorLennart Poettering <lennart@poettering.net>
Wed, 20 May 2020 16:38:07 +0000 (18:38 +0200)
committerLennart Poettering <lennart@poettering.net>
Thu, 21 May 2020 21:39:30 +0000 (23:39 +0200)
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: #15178
src/home/homework-luks.c
src/home/homework.c
src/home/homework.h

index caa4168265a0a2ef50f74119f98a1fef74415f40..44face338985b4cac8c217d34ffe97eb01f7f7ea 100644 (file)
@@ -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;
index 2c10997b6b8949bd5d94c7f14b0bc6887ba98250..316933cf4ebf69b3be051d050a874e6e97e250ed 100644 (file)
@@ -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;
@@ -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 */
@@ -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;
                         }
                 }
 
@@ -129,7 +130,7 @@ int user_record_authenticate(
                         if (r < 0)
                                 return log_oom();
 
-                        return 0;
+                        return 1;
                 }
 #else
                 need_token = true;
@@ -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) {
@@ -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:
          *
@@ -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;
 
@@ -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)
@@ -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)
@@ -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;
 
@@ -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;
 
index 3bcf3ad9b01a0ac43fbd4253edd2354cecc5a4c5..46641172a421e2e5fab5243b3455f94adc95cb4d 100644 (file)
@@ -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);