From: Lennart Poettering Date: Fri, 8 Oct 2021 20:01:44 +0000 (+0200) Subject: cryptsetup: before querying user for a PIN, check if a FIDO2 device is actually plugg... X-Git-Tag: v250-rc1~535^2~4 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=40091021c3ea8a6428f974765caf9a8793ac598c;p=thirdparty%2Fsystemd.git cryptsetup: before querying user for a PIN, check if a FIDO2 device is actually plugged in Before we'd already ask for a PIN just because we know we'll need it when the token is plugged in. We'd only the try to talk to the device and notice it actually isn't plugged in. This is quite confusing, as querying for the PIN suggests we already had a device we are talking to. Let's hence check if there's actually device before we ask the PIN question. And if there is none, let's immediately inform the caller, so that they watch udev and retry once a device has shown up. --- diff --git a/src/cryptsetup/cryptsetup-fido2.c b/src/cryptsetup/cryptsetup-fido2.c index 3a870016d31..35d5dbe0075 100644 --- a/src/cryptsetup/cryptsetup-fido2.c +++ b/src/cryptsetup/cryptsetup-fido2.c @@ -32,6 +32,7 @@ int acquire_fido2_key( _cleanup_strv_free_erase_ char **pins = NULL; _cleanup_free_ void *loaded_salt = NULL; + bool device_exists = false; const char *salt; size_t salt_size; char *e; @@ -89,13 +90,29 @@ int acquire_fido2_key( -ENOANO, /* needs pin */ -ENOLCK)) /* pin incorrect */ return r; - } - pins = strv_free_erase(pins); + device_exists = true; /* that a PIN is needed/wasn't correct means that we managed to + * talk to a device */ + } if (headless) return log_error_errno(SYNTHETIC_ERRNO(ENOPKG), "PIN querying disabled via 'headless' option. Use the '$PIN' environment variable."); + if (!device_exists) { + /* Before we inquire for the PIN we'll need, if we never talked to the device, check + * if the device actually is plugged in. Otherwise we'll ask for the PIN already when + * the device is not plugged in, which is confusing. */ + + r = fido2_have_device(device); + if (r < 0) + return r; + if (r == 0) /* no device found, return EAGAIN so that caller will wait/watch udev */ + return -EAGAIN; + + device_exists = true; /* now we know for sure, a device exists, no need to ask again */ + } + + pins = strv_free_erase(pins); r = ask_password_auto("Please enter security token PIN:", "drive-harddisk", NULL, "fido2-pin", "cryptsetup.fido2-pin", until, ask_password_flags, &pins); if (r < 0) return log_error_errno(r, "Failed to ask for user password: %m");