From 64f2e1ff05d210d7c0e62d8625e326d8d85911f0 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 4 Jun 2024 13:53:55 +0200 Subject: [PATCH] cryptsetup: unset an unlock path on each unlock retry If we couldn't unlock a device with the chosen unlock path, let's not fall back to the lowest one right away, but only flush out one path, and try the next. Fixes: #30425 Follow-up-for: #30185 Alternative-to: #33183 --- src/cryptsetup/cryptsetup.c | 54 ++++++++++++++++++++++++++++--------- 1 file changed, 42 insertions(+), 12 deletions(-) diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c index 8ad0528dec..638e9d0c79 100644 --- a/src/cryptsetup/cryptsetup.c +++ b/src/cryptsetup/cryptsetup.c @@ -2416,8 +2416,9 @@ static int run(int argc, char *argv[]) { } #endif + _cleanup_strv_free_erase_ char **passwords = NULL; for (tries = 0; arg_tries == 0 || tries < arg_tries; tries++) { - _cleanup_strv_free_erase_ char **passwords = NULL; + log_debug("Beginning attempt %u to unlock.", tries); /* When we were able to acquire multiple keys, let's always process them in this order: * @@ -2428,7 +2429,9 @@ static int run(int argc, char *argv[]) { * 5. We enquire the user for a password */ - if (!key_file && !key_data && !arg_pkcs11_uri && !arg_pkcs11_uri_auto && !arg_fido2_device && !arg_fido2_device_auto && !arg_tpm2_device && !arg_tpm2_device_auto) { + if (!passwords && !key_file && !key_data && !arg_pkcs11_uri && !arg_pkcs11_uri_auto && !arg_fido2_device && !arg_fido2_device_auto && !arg_tpm2_device && !arg_tpm2_device_auto) { + + /* If we have nothing to try anymore, then acquire a new password */ if (arg_try_empty_password) { /* Hmm, let's try an empty password now, but only once */ @@ -2465,17 +2468,44 @@ static int run(int argc, char *argv[]) { if (r != -EAGAIN) return r; - /* Key not correct? Let's try again! */ + /* Key not correct? Let's try again, but let's invalidate one of the passed fields, + * so that we fallback to the next best thing. */ - key_file = NULL; - key_data = erase_and_free(key_data); - key_data_size = 0; - arg_pkcs11_uri = mfree(arg_pkcs11_uri); - arg_pkcs11_uri_auto = false; - arg_fido2_device = mfree(arg_fido2_device); - arg_fido2_device_auto = false; - arg_tpm2_device = mfree(arg_tpm2_device); - arg_tpm2_device_auto = false; + if (arg_tpm2_device || arg_tpm2_device_auto) { + arg_tpm2_device = mfree(arg_tpm2_device); + arg_tpm2_device_auto = false; + continue; + } + + if (arg_fido2_device || arg_fido2_device_auto) { + arg_fido2_device = mfree(arg_fido2_device); + arg_fido2_device_auto = false; + continue; + } + + if (arg_pkcs11_uri || arg_pkcs11_uri_auto) { + arg_pkcs11_uri = mfree(arg_pkcs11_uri); + arg_pkcs11_uri_auto = false; + continue; + } + + if (key_data) { + key_data = erase_and_free(key_data); + key_data_size = 0; + continue; + } + + if (key_file) { + key_file = NULL; + continue; + } + + if (passwords) { + passwords = strv_free_erase(passwords); + continue; + } + + log_debug("Prepared for next attempt to unlock."); } if (arg_tries != 0 && tries >= arg_tries) -- 2.25.1