mirror of
https://github.com/systemd/systemd.git
synced 2024-11-23 02:03:37 +08:00
cryptsetup: allow customizing cache behavior
The new "password-cache" option allows customizing behavior of the ask-password module in regards to caching credentials in the kernel keyring. There are 3 possible values for this option: * read-only - look for credentials in kernel keyring before asking * on - same as read-only, but also save credentials input by user * off - disable keyring credential cache Currently the cache is forced upon the user and this can cause issues. For example, if user wants to attach two volumes with two different FIDO2 tokens in a quick succession, the attachment operation for the second volume will use the PIN cached from the first FIDO2 token, which of course will fail and since tokens are only attempted once, this will cause fallback to a password prompt.
This commit is contained in:
parent
53b6c99018
commit
fd8ed7f26b
@ -673,6 +673,26 @@
|
||||
<xi:include href="version-info.xml" xpointer="v249"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>password-cache=yes|no|read-only</option></term>
|
||||
|
||||
<listitem><para>Controls whether to use cache for passwords or security token PINs.
|
||||
Takes a boolean or the special string <literal>read-only</literal>. Defaults to
|
||||
<literal>yes</literal>.</para>
|
||||
|
||||
<para>If set to <literal>read-only</literal>, the kernel keyring is checked for a
|
||||
password/PIN before requesting one interactively. If set to <literal>yes</literal>,
|
||||
in addition to checking the keyring, any password/PIN entered interactively is cached
|
||||
in the keyring with a 2.5-minute timeout before being purged.</para>
|
||||
|
||||
<para>Note that this option is not permitted for PKCS#11 security tokens. The reasoning
|
||||
behind this is that PKCS#11 security tokens are usually configured to lock after being
|
||||
supplied an invalid PIN multiple times, so using the cache might inadvertently lock the
|
||||
token.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v257"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>pkcs11-uri=</option></term>
|
||||
|
||||
|
@ -94,8 +94,9 @@
|
||||
<listitem><para>If the <varname>try-empty-password</varname> option is specified then unlocking the
|
||||
volume with an empty password is attempted.</para></listitem>
|
||||
|
||||
<listitem><para>The kernel keyring is then checked for a suitable cached password from previous
|
||||
attempts.</para></listitem>
|
||||
<listitem><para>If the <varname>password-cache=</varname> option is set to <literal>yes</literal> or
|
||||
<literal>read-only</literal>, the kernel keyring is then checked for a suitable cached password from
|
||||
previous attempts.</para></listitem>
|
||||
|
||||
<listitem><para>Finally, the user is queried for a password, possibly multiple times, unless
|
||||
the <varname>headless</varname> option is set.</para></listitem>
|
||||
|
@ -84,7 +84,8 @@ static char *arg_header = NULL;
|
||||
static unsigned arg_tries = 3;
|
||||
static bool arg_readonly = false;
|
||||
static bool arg_verify = false;
|
||||
static AskPasswordFlags arg_ask_password_flags = 0;
|
||||
static bool arg_password_cache_set = false; /* Not the actual argument value, just an indicator that some value is set */
|
||||
static AskPasswordFlags arg_ask_password_flags = ASK_PASSWORD_ACCEPT_CACHED | ASK_PASSWORD_PUSH_CACHE;
|
||||
static bool arg_discards = false;
|
||||
static bool arg_same_cpu_crypt = false;
|
||||
static bool arg_submit_from_crypt_cpus = false;
|
||||
@ -299,6 +300,21 @@ static int parse_one_option(const char *option) {
|
||||
SET_FLAG(arg_ask_password_flags, ASK_PASSWORD_ECHO, r);
|
||||
SET_FLAG(arg_ask_password_flags, ASK_PASSWORD_SILENT, !r);
|
||||
}
|
||||
} else if ((val = startswith(option, "password-cache="))) {
|
||||
arg_password_cache_set = true;
|
||||
|
||||
if (streq(val, "read-only")) {
|
||||
arg_ask_password_flags |= ASK_PASSWORD_ACCEPT_CACHED;
|
||||
arg_ask_password_flags &= ~ASK_PASSWORD_PUSH_CACHE;
|
||||
} else {
|
||||
r = parse_boolean(val);
|
||||
if (r < 0) {
|
||||
log_warning_errno(r, "Invalid password-cache= option \"%s\", ignoring.", val);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SET_FLAG(arg_ask_password_flags, ASK_PASSWORD_ACCEPT_CACHED|ASK_PASSWORD_PUSH_CACHE, r);
|
||||
}
|
||||
} else if (STR_IN_SET(option, "allow-discards", "discard"))
|
||||
arg_discards = true;
|
||||
else if (streq(option, "same-cpu-crypt"))
|
||||
@ -649,6 +665,17 @@ static int parse_crypt_config(const char *options) {
|
||||
log_warning("skip= ignored with type %s", arg_type);
|
||||
}
|
||||
|
||||
if (arg_pkcs11_uri || arg_pkcs11_uri_auto) {
|
||||
/* If password-cache was not configured explicitly, default to no cache for PKCS#11 */
|
||||
if (!arg_password_cache_set)
|
||||
arg_ask_password_flags &= ~(ASK_PASSWORD_ACCEPT_CACHED|ASK_PASSWORD_PUSH_CACHE);
|
||||
|
||||
/* This prevents future backward-compatibility issues if we decide to allow caching for PKCS#11 */
|
||||
if (FLAGS_SET(arg_ask_password_flags, ASK_PASSWORD_ACCEPT_CACHED))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"Password cache is not supported for PKCS#11 security tokens.");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -847,13 +874,13 @@ static int get_password(
|
||||
const char *vol,
|
||||
const char *src,
|
||||
usec_t until,
|
||||
bool accept_cached,
|
||||
bool ignore_cached,
|
||||
PassphraseType passphrase_type,
|
||||
char ***ret) {
|
||||
|
||||
_cleanup_free_ char *friendly = NULL, *text = NULL, *disk_path = NULL, *id = NULL;
|
||||
_cleanup_strv_free_erase_ char **passwords = NULL;
|
||||
AskPasswordFlags flags = arg_ask_password_flags | ASK_PASSWORD_PUSH_CACHE;
|
||||
AskPasswordFlags flags = arg_ask_password_flags;
|
||||
int r;
|
||||
|
||||
assert(vol);
|
||||
@ -886,11 +913,10 @@ static int get_password(
|
||||
.credential = "cryptsetup.passphrase",
|
||||
};
|
||||
|
||||
r = ask_password_auto(
|
||||
&req,
|
||||
until,
|
||||
flags | (accept_cached*ASK_PASSWORD_ACCEPT_CACHED),
|
||||
&passwords);
|
||||
if (ignore_cached)
|
||||
flags &= ~ASK_PASSWORD_ACCEPT_CACHED;
|
||||
|
||||
r = ask_password_auto(&req, until, flags, &passwords);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to query password: %m");
|
||||
|
||||
@ -1349,7 +1375,7 @@ static int crypt_activate_by_token_pin_ask_password(
|
||||
const char *credential) {
|
||||
|
||||
#if HAVE_LIBCRYPTSETUP_PLUGINS
|
||||
AskPasswordFlags flags = arg_ask_password_flags | ASK_PASSWORD_PUSH_CACHE | ASK_PASSWORD_ACCEPT_CACHED;
|
||||
AskPasswordFlags flags = arg_ask_password_flags;
|
||||
_cleanup_strv_free_erase_ char **pins = NULL;
|
||||
int r;
|
||||
|
||||
@ -2521,7 +2547,13 @@ static int run(int argc, char *argv[]) {
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "No passphrase or recovery key registered.");
|
||||
}
|
||||
|
||||
r = get_password(volume, source, until, use_cached_passphrase && !arg_verify, passphrase_type, &passwords);
|
||||
r = get_password(
|
||||
volume,
|
||||
source,
|
||||
until,
|
||||
/* ignore_cached= */ !use_cached_passphrase || arg_verify,
|
||||
passphrase_type,
|
||||
&passwords);
|
||||
use_cached_passphrase = false;
|
||||
if (r == -EAGAIN)
|
||||
continue;
|
||||
|
@ -44,8 +44,6 @@ int acquire_fido2_key(
|
||||
return log_error_errno(SYNTHETIC_ERRNO(ENOPKG),
|
||||
"Local verification is required to unlock this volume, but the 'headless' parameter was set.");
|
||||
|
||||
askpw_flags |= ASK_PASSWORD_PUSH_CACHE | ASK_PASSWORD_ACCEPT_CACHED;
|
||||
|
||||
assert(cid);
|
||||
assert(key_file || key_data);
|
||||
|
||||
|
@ -178,6 +178,8 @@ int acquire_tpm2_key(
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
askpw_flags &= ~ASK_PASSWORD_ACCEPT_CACHED;
|
||||
|
||||
if (iovec_is_set(salt)) {
|
||||
uint8_t salted_pin[SHA256_DIGEST_SIZE] = {};
|
||||
CLEANUP_ERASE(salted_pin);
|
||||
|
Loading…
Reference in New Issue
Block a user