diff --git a/man/systemd-cryptenroll.xml b/man/systemd-cryptenroll.xml index dfc6d31cf4..c687ac31bb 100644 --- a/man/systemd-cryptenroll.xml +++ b/man/systemd-cryptenroll.xml @@ -650,6 +650,51 @@ + + Credentials + + systemd-cryptenroll supports the service credentials logic as implemented by + ImportCredential=/LoadCredential=/SetCredential= + (see systemd.exec5 for + details). The following credentials are used when passed in: + + + + cryptenroll.passphrase + cryptenroll.new-passphrase + + May contain the passphrase to unlock the volume with/to newly enroll. + + + + + + cryptenroll.tpm2-pin + cryptenroll.new-tpm2-pin + + May contain the TPM2 PIN to unlock the volume with/to newly enroll. + + + + + + cryptenroll.fido2-pin + + If a FIDO2 token is enrolled this may contain the PIN of the token. + + + + + + cryptenroll.pkcs11-pin + + If a PKCS#11 token is enrolled this may contain the PIN of the token. + + + + + + Exit status diff --git a/man/systemd-cryptsetup.xml b/man/systemd-cryptsetup.xml index 5f12dc4748..72dc56390f 100644 --- a/man/systemd-cryptsetup.xml +++ b/man/systemd-cryptsetup.xml @@ -105,7 +105,7 @@ - System Credentials + Credentials systemd-cryptsetup supports the service credentials logic as implemented by ImportCredential=/LoadCredential=/SetCredential= @@ -122,14 +122,6 @@ - - cryptsetup.fido2-pin - - This credential specifies the FIDO2 token pin. - - - - cryptsetup.tpm2-pin @@ -139,9 +131,9 @@ - cryptsetup.luks2-pin + cryptsetup.fido2-pin - This credential specifies the LUKS2 token pin. + This credential specifies the FIDO2 token pin. @@ -153,6 +145,14 @@ + + + cryptsetup.luks2-pin + + This credential specifies the PIN requested by generic LUKS2 token modules. + + + diff --git a/man/systemd.system-credentials.xml b/man/systemd.system-credentials.xml index 749d3bfb15..2a345c47b4 100644 --- a/man/systemd.system-credentials.xml +++ b/man/systemd.system-credentials.xml @@ -353,6 +353,20 @@ + + + cryptsetup.passphrase + cryptsetup.tpm2-pin + cryptsetup.fido2-pin + cryptsetup.pkcs11-pin + cryptsetup.luks2-pin + + Specifies the passphrase/PINs to use for unlock encrypted storage volumes. For details see + systemd-cryptsetup8. + + + + diff --git a/src/ask-password/ask-password.c b/src/ask-password/ask-password.c index bf4c93e2dc..371d316332 100644 --- a/src/ask-password/ask-password.c +++ b/src/ask-password/ask-password.c @@ -239,7 +239,15 @@ static int run(int argc, char *argv[]) { else timeout = 0; - r = ask_password_auto(arg_message, arg_icon, arg_id, arg_key_name, arg_credential_name ?: "password", timeout, arg_flags, &l); + AskPasswordRequest req = { + .message = arg_message, + .icon = arg_icon, + .id = arg_id, + .keyring = arg_key_name, + .credential = arg_credential_name ?: "password", + }; + + r = ask_password_auto(&req, timeout, arg_flags, &l); if (r < 0) return log_error_errno(r, "Failed to query password: %m"); diff --git a/src/cryptenroll/cryptenroll-fido2.c b/src/cryptenroll/cryptenroll-fido2.c index 2baeb92e07..baa630a6b3 100644 --- a/src/cryptenroll/cryptenroll-fido2.c +++ b/src/cryptenroll/cryptenroll-fido2.c @@ -33,10 +33,10 @@ int load_volume_key_fido2( cd_node, device, /* until= */ 0, - /* headless= */ false, + "cryptenroll.fido2-pin", + ASK_PASSWORD_PUSH_CACHE|ASK_PASSWORD_ACCEPT_CACHED, &decrypted_key, - &decrypted_key_size, - ASK_PASSWORD_PUSH_CACHE|ASK_PASSWORD_ACCEPT_CACHED); + &decrypted_key_size); if (r == -EAGAIN) return log_error_errno(r, "FIDO2 token does not exist, or UV is blocked. Please try again."); if (r < 0) @@ -97,6 +97,7 @@ int enroll_fido2( /* user_display_name= */ node, /* user_icon_name= */ NULL, /* askpw_icon_name= */ "drive-harddisk", + /* askpw_credential= */ "cryptenroll.fido2-pin", lock_with, cred_alg, &cid, &cid_size, diff --git a/src/cryptenroll/cryptenroll-password.c b/src/cryptenroll/cryptenroll-password.c index c35b6092c8..a9bd8a1dd0 100644 --- a/src/cryptenroll/cryptenroll-password.c +++ b/src/cryptenroll/cryptenroll-password.c @@ -38,9 +38,8 @@ int load_volume_key_password( return log_error_errno(r, "Password from environment variable $PASSWORD did not work: %m"); } else { AskPasswordFlags ask_password_flags = ASK_PASSWORD_PUSH_CACHE|ASK_PASSWORD_ACCEPT_CACHED; - _cleanup_free_ char *question = NULL, *disk_path = NULL; + _cleanup_free_ char *question = NULL, *id = NULL, *disk_path = NULL; unsigned i = 5; - const char *id; question = strjoin("Please enter current passphrase for disk ", cd_node, ":"); if (!question) @@ -50,7 +49,17 @@ int load_volume_key_password( if (!disk_path) return log_oom(); - id = strjoina("cryptsetup:", disk_path); + id = strjoin("cryptenroll:", disk_path); + if (!id) + return log_oom(); + + AskPasswordRequest req = { + .message = question, + .icon = "drive-harddisk", + .id = id, + .keyring = "cryptenroll", + .credential = "cryptenroll.passphrase", + }; for (;;) { _cleanup_strv_free_erase_ char **passwords = NULL; @@ -59,10 +68,7 @@ int load_volume_key_password( return log_error_errno(SYNTHETIC_ERRNO(ENOKEY), "Too many attempts, giving up."); - r = ask_password_auto( - question, "drive-harddisk", id, "cryptenroll", "cryptenroll.passphrase", USEC_INFINITY, - ask_password_flags, - &passwords); + r = ask_password_auto(&req, USEC_INFINITY, ask_password_flags, &passwords); if (r < 0) return log_error_errno(r, "Failed to query password: %m"); @@ -105,9 +111,8 @@ int enroll_password( if (r < 0) return log_error_errno(r, "Failed to acquire password from environment: %m"); if (r == 0) { - _cleanup_free_ char *disk_path = NULL; + _cleanup_free_ char *disk_path = NULL, *id = NULL; unsigned i = 5; - const char *id; assert_se(node = crypt_get_device_name(cd)); @@ -117,7 +122,16 @@ int enroll_password( if (!disk_path) return log_oom(); - id = strjoina("cryptsetup:", disk_path); + id = strjoin("cryptenroll-new:", disk_path); + if (!id) + return log_oom(); + + AskPasswordRequest req = { + .icon = "drive-harddisk", + .id = id, + .keyring = "cryptenroll", + .credential = "cryptenroll.new-passphrase", + }; for (;;) { _cleanup_strv_free_erase_ char **passwords = NULL, **passwords2 = NULL; @@ -131,7 +145,9 @@ int enroll_password( if (!question) return log_oom(); - r = ask_password_auto(question, "drive-harddisk", id, "cryptenroll", "cryptenroll.new-passphrase", USEC_INFINITY, 0, &passwords); + req.message = question; + + r = ask_password_auto(&req, USEC_INFINITY, /* flags= */ 0, &passwords); if (r < 0) return log_error_errno(r, "Failed to query password: %m"); @@ -142,7 +158,9 @@ int enroll_password( if (!question) return log_oom(); - r = ask_password_auto(question, "drive-harddisk", id, "cryptenroll", "cryptenroll.new-passphrase", USEC_INFINITY, 0, &passwords2); + req.message = question; + + r = ask_password_auto(&req, USEC_INFINITY, /* flags= */ 0, &passwords2); if (r < 0) return log_error_errno(r, "Failed to query password: %m"); diff --git a/src/cryptenroll/cryptenroll-pkcs11.c b/src/cryptenroll/cryptenroll-pkcs11.c index 6b70a147c3..09875c1598 100644 --- a/src/cryptenroll/cryptenroll-pkcs11.c +++ b/src/cryptenroll/cryptenroll-pkcs11.c @@ -55,7 +55,14 @@ int enroll_pkcs11( assert_se(node = crypt_get_device_name(cd)); - r = pkcs11_acquire_public_key(uri, "volume enrollment operation", "drive-harddisk", &pkey, NULL); + r = pkcs11_acquire_public_key( + uri, + "volume enrollment operation", + "drive-harddisk", + "cryptenroll.pkcs11-pin", + /* askpw_flags= */ 0, + &pkey, + /* ret_pin_used= */ NULL); if (r < 0) return r; diff --git a/src/cryptenroll/cryptenroll-tpm2.c b/src/cryptenroll/cryptenroll-tpm2.c index fb862a3329..3ded815fb0 100644 --- a/src/cryptenroll/cryptenroll-tpm2.c +++ b/src/cryptenroll/cryptenroll-tpm2.c @@ -87,28 +87,29 @@ static int get_pin(char **ret_pin_str, TPM2Flags *ret_flags) { return log_error_errno( SYNTHETIC_ERRNO(ENOKEY), "Too many attempts, giving up."); + AskPasswordRequest req = { + .message = "Please enter TPM2 PIN:", + .icon = "drive-harddisk", + .keyring = "tpm2-pin", + .credential = "cryptenroll.new-tpm2-pin", + }; + pin = strv_free_erase(pin); r = ask_password_auto( - "Please enter TPM2 PIN:", - "drive-harddisk", - NULL, - "tpm2-pin", - "cryptenroll.tpm2-pin", - USEC_INFINITY, - 0, + &req, + /* until= */ USEC_INFINITY, + /* flags= */ 0, &pin); if (r < 0) return log_error_errno(r, "Failed to ask for user pin: %m"); assert(strv_length(pin) == 1); + req.message = "Please enter TPM2 PIN (repeat):"; + r = ask_password_auto( - "Please enter TPM2 PIN (repeat):", - "drive-harddisk", - NULL, - "tpm2-pin", - "cryptenroll.tpm2-pin", + &req, USEC_INFINITY, - 0, + /* flags= */ 0, &pin2); if (r < 0) return log_error_errno(r, "Failed to ask for user pin: %m"); @@ -209,8 +210,8 @@ int load_volume_key_tpm2( &pcrlock_nv, tpm2_flags, /* until= */ 0, - /* headless= */ false, - /* ask_password_flags */ false, + "cryptenroll.tpm2-pin", + /* askpw_flags= */ 0, &decrypted_key); if (IN_SET(r, -EACCES, -ENOLCK)) return log_notice_errno(SYNTHETIC_ERRNO(EAGAIN), "TPM2 PIN unlock failed"); diff --git a/src/cryptsetup/cryptsetup-pkcs11.c b/src/cryptsetup/cryptsetup-pkcs11.c index 4ef249509d..4b2b5bbf00 100644 --- a/src/cryptsetup/cryptsetup-pkcs11.c +++ b/src/cryptsetup/cryptsetup-pkcs11.c @@ -34,14 +34,14 @@ int decrypt_pkcs11_key( const void *key_data, /* … or key_data and key_data_size (for literal keys) */ size_t key_data_size, usec_t until, - bool headless, + AskPasswordFlags askpw_flags, void **ret_decrypted_key, size_t *ret_decrypted_key_size) { _cleanup_(pkcs11_crypt_device_callback_data_release) pkcs11_crypt_device_callback_data data = { .friendly_name = friendly_name, + .askpw_flags = askpw_flags, .until = until, - .headless = headless, }; int r; diff --git a/src/cryptsetup/cryptsetup-pkcs11.h b/src/cryptsetup/cryptsetup-pkcs11.h index 256c09a9b6..22e6992582 100644 --- a/src/cryptsetup/cryptsetup-pkcs11.h +++ b/src/cryptsetup/cryptsetup-pkcs11.h @@ -19,7 +19,7 @@ int decrypt_pkcs11_key( const void *key_data, size_t key_data_size, usec_t until, - bool headless, + AskPasswordFlags askpw_flags, void **ret_decrypted_key, size_t *ret_decrypted_key_size); @@ -42,7 +42,7 @@ static inline int decrypt_pkcs11_key( const void *key_data, size_t key_data_size, usec_t until, - bool headless, + AskPasswordFlags askpw_flags, void **ret_decrypted_key, size_t *ret_decrypted_key_size) { diff --git a/src/cryptsetup/cryptsetup-tokens/luks2-pkcs11.c b/src/cryptsetup/cryptsetup-tokens/luks2-pkcs11.c index 512a4cf18a..ac5100f688 100644 --- a/src/cryptsetup/cryptsetup-tokens/luks2-pkcs11.c +++ b/src/cryptsetup/cryptsetup-tokens/luks2-pkcs11.c @@ -157,7 +157,7 @@ static int acquire_luks2_key_systemd( assert(params); data.friendly_name = params->friendly_name; - data.headless = params->headless; + data.askpw_credential = params->askpw_credential; data.askpw_flags = params->askpw_flags; data.until = params->until; diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c index 1caaa514d5..7099f68f88 100644 --- a/src/cryptsetup/cryptsetup.c +++ b/src/cryptsetup/cryptsetup.c @@ -101,7 +101,6 @@ static uint32_t arg_tpm2_pcr_mask = UINT32_MAX; static char *arg_tpm2_signature = NULL; static bool arg_tpm2_pin = false; static char *arg_tpm2_pcrlock = NULL; -static bool arg_headless = false; static usec_t arg_token_timeout_usec = 30*USEC_PER_SEC; static unsigned arg_tpm2_measure_pcr = UINT_MAX; /* This and the following field is about measuring the unlocked volume key to the local TPM */ static char **arg_tpm2_measure_banks = NULL; @@ -504,9 +503,9 @@ static int parse_one_option(const char *option) { return 0; } - arg_headless = r; + SET_FLAG(arg_ask_password_flags, ASK_PASSWORD_HEADLESS, r); } else if (streq(option, "headless")) - arg_headless = true; + arg_ask_password_flags |= ASK_PASSWORD_HEADLESS; else if ((val = startswith(option, "token-timeout="))) { @@ -798,17 +797,16 @@ static int get_password( PassphraseType passphrase_type, char ***ret) { - _cleanup_free_ char *friendly = NULL, *text = NULL, *disk_path = NULL; + _cleanup_free_ char *friendly = NULL, *text = NULL, *disk_path = NULL, *id = NULL; _cleanup_strv_free_erase_ char **passwords = NULL; - char *id; - int r = 0; AskPasswordFlags flags = arg_ask_password_flags | ASK_PASSWORD_PUSH_CACHE; + int r; assert(vol); assert(src); assert(ret); - if (arg_headless) + if (FLAGS_SET(arg_ask_password_flags, ASK_PASSWORD_HEADLESS)) return log_error_errno(SYNTHETIC_ERRNO(ENOPKG), "Password querying disabled via 'headless' option."); friendly = friendly_disk_name(src, vol); @@ -822,11 +820,23 @@ static int get_password( if (!disk_path) return log_oom(); - id = strjoina("cryptsetup:", disk_path); + id = strjoin("cryptsetup:", disk_path); + if (!id) + return log_oom(); - r = ask_password_auto(text, "drive-harddisk", id, "cryptsetup", "cryptsetup.passphrase", until, - flags | (accept_cached*ASK_PASSWORD_ACCEPT_CACHED), - &passwords); + AskPasswordRequest req = { + .message = text, + .icon = "drive-harddisk", + .id = id, + .keyring = "cryptsetup", + .credential = "cryptsetup.passphrase", + }; + + r = ask_password_auto( + &req, + until, + flags | (accept_cached*ASK_PASSWORD_ACCEPT_CACHED), + &passwords); if (r < 0) return log_error_errno(r, "Failed to query password: %m"); @@ -835,12 +845,19 @@ static int get_password( assert(strv_length(passwords) == 1); + text = mfree(text); if (asprintf(&text, "Please enter %s for disk %s (verification):", passphrase_type_to_string(passphrase_type), friendly) < 0) return log_oom(); - id = strjoina("cryptsetup-verification:", disk_path); + free(id); + id = strjoin("cryptsetup-verification:", disk_path); + if (!id) + return log_oom(); - r = ask_password_auto(text, "drive-harddisk", id, "cryptsetup", "cryptsetup.passphrase", until, flags, &passwords2); + req.message = text; + req.id = id; + + r = ask_password_auto(&req, until, flags, &passwords2); if (r < 0) return log_error_errno(r, "Failed to query verification password: %m"); @@ -1248,12 +1265,11 @@ static int crypt_activate_by_token_pin_ask_password( const char *name, const char *type, usec_t until, - bool headless, void *userdata, uint32_t activation_flags, const char *message, - const char *key_name, - const char *credential_name) { + const char *keyring, + const char *credential) { #if HAVE_LIBCRYPTSETUP_PLUGINS AskPasswordFlags flags = arg_ask_password_flags | ASK_PASSWORD_PUSH_CACHE | ASK_PASSWORD_ACCEPT_CACHED; @@ -1278,12 +1294,20 @@ static int crypt_activate_by_token_pin_ask_password( return r; } - if (headless) + if (FLAGS_SET(arg_ask_password_flags, ASK_PASSWORD_HEADLESS)) return log_error_errno(SYNTHETIC_ERRNO(ENOPKG), "PIN querying disabled via 'headless' option. Use the '$PIN' environment variable."); for (;;) { pins = strv_free_erase(pins); - r = ask_password_auto(message, "drive-harddisk", /* id= */ NULL, key_name, credential_name, until, flags, &pins); + + AskPasswordRequest req = { + .message = message, + .icon = "drive-harddisk", + .keyring = keyring, + .credential = credential, + }; + + r = ask_password_auto(&req, until, flags, &pins); if (r < 0) return r; @@ -1307,7 +1331,6 @@ static int attach_luks2_by_fido2_via_plugin( struct crypt_device *cd, const char *name, usec_t until, - bool headless, void *userdata, uint32_t activation_flags) { @@ -1316,7 +1339,6 @@ static int attach_luks2_by_fido2_via_plugin( name, "systemd-fido2", until, - headless, userdata, activation_flags, "Please enter security token PIN:", @@ -1371,7 +1393,7 @@ static int attach_luks_or_plain_or_bitlk_by_fido2( for (;;) { if (use_libcryptsetup_plugin && !arg_fido2_cid) { - r = attach_luks2_by_fido2_via_plugin(cd, name, until, arg_headless, arg_fido2_device, flags); + r = attach_luks2_by_fido2_via_plugin(cd, name, until, arg_fido2_device, flags); if (IN_SET(r, -ENOTUNIQ, -ENXIO, -ENOENT)) return log_debug_errno(SYNTHETIC_ERRNO(EAGAIN), "Automatic FIDO2 metadata discovery was not possible because missing or not unique, falling back to traditional unlocking."); @@ -1387,10 +1409,11 @@ static int attach_luks_or_plain_or_bitlk_by_fido2( key_file, arg_keyfile_size, arg_keyfile_offset, key_data, key_data_size, until, - arg_headless, required, - &decrypted_key, &decrypted_key_size, - arg_ask_password_flags); + "cryptsetup.fido2-pin", + arg_ask_password_flags, + &decrypted_key, + &decrypted_key_size); else r = acquire_fido2_key_auto( cd, @@ -1398,9 +1421,10 @@ static int attach_luks_or_plain_or_bitlk_by_fido2( friendly, arg_fido2_device, until, - arg_headless, - &decrypted_key, &decrypted_key_size, - arg_ask_password_flags); + "cryptsetup.fido2-pin", + arg_ask_password_flags, + &decrypted_key, + &decrypted_key_size); if (r >= 0) break; } @@ -1461,7 +1485,7 @@ static int attach_luks2_by_pkcs11_via_plugin( const char *name, const char *friendly_name, usec_t until, - bool headless, + const char *askpw_credential, uint32_t flags) { #if HAVE_LIBCRYPTSETUP_PLUGINS @@ -1473,7 +1497,7 @@ static int attach_luks2_by_pkcs11_via_plugin( systemd_pkcs11_plugin_params params = { .friendly_name = friendly_name, .until = until, - .headless = headless, + .askpw_credential = askpw_credential, .askpw_flags = arg_ask_password_flags, }; @@ -1537,7 +1561,13 @@ static int attach_luks_or_plain_or_bitlk_by_pkcs11( for (;;) { if (use_libcryptsetup_plugin && arg_pkcs11_uri_auto) - r = attach_luks2_by_pkcs11_via_plugin(cd, name, friendly, until, arg_headless, flags); + r = attach_luks2_by_pkcs11_via_plugin( + cd, + name, + friendly, + until, + "cryptsetup.pkcs11-pin", + flags); else { r = decrypt_pkcs11_key( name, @@ -1546,7 +1576,7 @@ static int attach_luks_or_plain_or_bitlk_by_pkcs11( key_file, arg_keyfile_size, arg_keyfile_offset, key_data, key_data_size, until, - arg_headless, + arg_ask_password_flags, &decrypted_key, &decrypted_key_size); if (r >= 0) break; @@ -1671,7 +1701,6 @@ static int attach_luks2_by_tpm2_via_plugin( struct crypt_device *cd, const char *name, usec_t until, - bool headless, uint32_t flags) { #if HAVE_LIBCRYPTSETUP_PLUGINS @@ -1691,7 +1720,6 @@ static int attach_luks2_by_tpm2_via_plugin( name, "systemd-tpm2", until, - headless, ¶ms, flags, "Please enter TPM2 PIN:", @@ -1747,7 +1775,7 @@ static int attach_luks_or_plain_or_bitlk_by_tpm2( /* pcrlock_nv= */ NULL, arg_tpm2_pin ? TPM2_FLAGS_USE_PIN : 0, until, - arg_headless, + "cryptsetup.tpm2-pin", arg_ask_password_flags, &decrypted_key); if (r >= 0) @@ -1762,7 +1790,7 @@ static int attach_luks_or_plain_or_bitlk_by_tpm2( return -EAGAIN; /* Mangle error code: let's make any form of TPM2 failure non-fatal. */ } } else { - r = attach_luks2_by_tpm2_via_plugin(cd, name, until, arg_headless, flags); + r = attach_luks2_by_tpm2_via_plugin(cd, name, until, flags); if (r >= 0) return 0; /* EAGAIN means: no tpm2 chip found @@ -1845,7 +1873,7 @@ static int attach_luks_or_plain_or_bitlk_by_tpm2( &pcrlock_nv, tpm2_flags, until, - arg_headless, + "cryptsetup.tpm2-pin", arg_ask_password_flags, &decrypted_key); if (IN_SET(r, -EACCES, -ENOLCK)) @@ -2365,7 +2393,6 @@ static int run(int argc, char *argv[]) { volume, /* type= */ NULL, until, - arg_headless, /* userdata= */ NULL, flags, "Please enter LUKS2 token PIN:", diff --git a/src/firstboot/firstboot.c b/src/firstboot/firstboot.c index 76af4e4ed5..d9d2e28251 100644 --- a/src/firstboot/firstboot.c +++ b/src/firstboot/firstboot.c @@ -797,7 +797,11 @@ static int prompt_root_password(int rfd) { _cleanup_strv_free_erase_ char **a = NULL, **b = NULL; _cleanup_free_ char *error = NULL; - r = ask_password_tty(-1, msg1, NULL, 0, 0, NULL, &a); + AskPasswordRequest req = { + .message = msg1, + }; + + r = ask_password_tty(-EBADF, &req, /* until= */ 0, /* flags= */ 0, /* flag_file= */ NULL, &a); if (r < 0) return log_error_errno(r, "Failed to query root password: %m"); if (strv_length(a) != 1) @@ -817,7 +821,9 @@ static int prompt_root_password(int rfd) { else if (r == 0) log_warning("Password is weak, accepting anyway: %s", error); - r = ask_password_tty(-1, msg2, NULL, 0, 0, NULL, &b); + req.message = msg2; + + r = ask_password_tty(-EBADF, &req, /* until= */ 0, /* flags= */ 0, /* flag_file= */ NULL, &b); if (r < 0) return log_error_errno(r, "Failed to query root password: %m"); if (strv_length(b) != 1) diff --git a/src/home/homectl-fido2.c b/src/home/homectl-fido2.c index 3cbdf912aa..384461a1ca 100644 --- a/src/home/homectl-fido2.c +++ b/src/home/homectl-fido2.c @@ -167,6 +167,7 @@ int identity_add_fido2_parameters( /* user_display_name= */ rn ? json_variant_string(rn) : NULL, /* user_icon_name= */ NULL, /* askpw_icon_name= */ "user-home", + /* askpw_credential= */ "home.token-pin", lock_with, cred_alg, &cid, &cid_size, diff --git a/src/home/homectl-pkcs11.c b/src/home/homectl-pkcs11.c index 5c54ec016e..bb582d7d47 100644 --- a/src/home/homectl-pkcs11.c +++ b/src/home/homectl-pkcs11.c @@ -153,7 +153,14 @@ int identity_add_pkcs11_key_data(JsonVariant **v, const char *uri) { assert(v); - r = pkcs11_acquire_public_key(uri, "home directory operation", "user-home", &pkey, &pin); + r = pkcs11_acquire_public_key( + uri, + "home directory operation", + "user-home", + "home.token-pin", + /* askpw_flags= */ 0, + &pkey, + &pin); if (r < 0) return r; diff --git a/src/home/homectl.c b/src/home/homectl.c index 5357e791a5..3a839c73ea 100644 --- a/src/home/homectl.c +++ b/src/home/homectl.c @@ -261,14 +261,14 @@ static int acquire_existing_password( user_name) < 0) return log_oom(); - r = ask_password_auto(question, - /* icon= */ "user-home", - NULL, - /* key_name= */ "home-password", - /* credential_name= */ "home.password", - USEC_INFINITY, - flags, - &password); + AskPasswordRequest req = { + .message = question, + .icon = "user-home", + .keyring = "home-password", + .credential = "home.password", + }; + + r = ask_password_auto(&req, USEC_INFINITY, flags, &password); if (r == -EUNATCH) { /* EUNATCH is returned if no password was found and asking interactively was * disabled via the flags. Not an error for us. */ log_debug_errno(r, "No passwords acquired."); @@ -319,14 +319,14 @@ static int acquire_recovery_key( if (asprintf(&question, "Please enter recovery key for user %s:", user_name) < 0) return log_oom(); - r = ask_password_auto(question, - /* icon= */ "user-home", - NULL, - /* key_name= */ "home-recovery-key", - /* credential_name= */ "home.recovery-key", - USEC_INFINITY, - flags, - &recovery_key); + AskPasswordRequest req = { + .message = question, + .icon = "user-home", + .keyring = "home-recovery-key", + .credential = "home.recovery-key", + }; + + r = ask_password_auto(&req, USEC_INFINITY, flags, &recovery_key); if (r == -EUNATCH) { /* EUNATCH is returned if no recovery key was found and asking interactively was * disabled via the flags. Not an error for us. */ log_debug_errno(r, "No recovery keys acquired."); @@ -373,15 +373,14 @@ static int acquire_token_pin( if (asprintf(&question, "Please enter security token PIN for user %s:", user_name) < 0) return log_oom(); - r = ask_password_auto( - question, - /* icon= */ "user-home", - NULL, - /* key_name= */ "token-pin", - /* credential_name= */ "home.token-pin", - USEC_INFINITY, - flags, - &pin); + AskPasswordRequest req = { + .message = question, + .icon = "user-home", + .keyring = "token-pin", + .credential = "home.token-pin", + }; + + r = ask_password_auto(&req, USEC_INFINITY, flags, &pin); if (r == -EUNATCH) { /* EUNATCH is returned if no PIN was found and asking interactively was disabled * via the flags. Not an error for us. */ log_debug_errno(r, "No security token PINs acquired."); @@ -1228,14 +1227,17 @@ static int acquire_new_password( if (asprintf(&question, "Please enter new password for user %s:", user_name) < 0) return log_oom(); + AskPasswordRequest req = { + .message = question, + .icon = "user-home", + .keyring = "home-password", + .credential = "home.new-password", + }; + r = ask_password_auto( - question, - /* icon= */ "user-home", - NULL, - /* key_name= */ "home-password", - /* credential_name= */ "home.new-password", + &req, USEC_INFINITY, - 0, /* no caching, we want to collect a new password here after all */ + /* flags= */ 0, /* no caching, we want to collect a new password here after all */ &first); if (r < 0) return log_error_errno(r, "Failed to acquire password: %m"); @@ -1244,14 +1246,12 @@ static int acquire_new_password( if (asprintf(&question, "Please enter new password for user %s (repeat):", user_name) < 0) return log_oom(); + req.message = question; + r = ask_password_auto( - question, - /* icon= */ "user-home", - NULL, - /* key_name= */ "home-password", - /* credential_name= */ "home.new-password", + &req, USEC_INFINITY, - 0, /* no caching */ + /* flags= */ 0, /* no caching */ &second); if (r < 0) return log_error_errno(r, "Failed to acquire password: %m"); diff --git a/src/pcrlock/pcrlock.c b/src/pcrlock/pcrlock.c index 1dd3d86a73..e70c44c675 100644 --- a/src/pcrlock/pcrlock.c +++ b/src/pcrlock/pcrlock.c @@ -4444,12 +4444,14 @@ static int make_policy(bool force, bool recovery_pin) { if (r == 0) { _cleanup_(strv_free_erasep) char **l = NULL; + AskPasswordRequest req = { + .message = "Recovery PIN", + .id = "pcrlock-recovery-pin", + .credential = "pcrlock.recovery-pin", + }; + r = ask_password_auto( - "Recovery PIN", - /* icon= */ NULL, - /* id= */ "pcrlock-recovery-pin", - /* key_name= */ NULL, - /* credential_name= */ "systemd-pcrlock.recovery-pin", + &req, /* until= */ 0, /* flags= */ 0, &l); diff --git a/src/shared/ask-password-api.c b/src/shared/ask-password-api.c index 6d71245549..462b3d2e00 100644 --- a/src/shared/ask-password-api.c +++ b/src/shared/ask-password-api.c @@ -147,18 +147,17 @@ static int add_to_keyring_and_log(const char *keyname, AskPasswordFlags flags, c return 0; } -static int ask_password_keyring(const char *keyname, AskPasswordFlags flags, char ***ret) { - +static int ask_password_keyring(const AskPasswordRequest *req, AskPasswordFlags flags, char ***ret) { key_serial_t serial; int r; - assert(keyname); + assert(req); assert(ret); if (!FLAGS_SET(flags, ASK_PASSWORD_ACCEPT_CACHED)) return -EUNATCH; - r = lookup_key(keyname, &serial); + r = lookup_key(req->keyring, &serial); if (ERRNO_IS_NEG_NOT_SUPPORTED(r) || r == -EPERM) /* When retrieving, the distinction between "kernel or container manager don't support or * allow this" and "no matching key known" doesn't matter. Note that we propagate EACCESS @@ -205,7 +204,7 @@ static int backspace_string(int ttyfd, const char *str) { } int ask_password_plymouth( - const char *message, + const AskPasswordRequest *req, usec_t until, AskPasswordFlags flags, const char *flag_file, @@ -225,8 +224,10 @@ int ask_password_plymouth( assert(ret); - if (!message) - message = "Password:"; + if (FLAGS_SET(flags, ASK_PASSWORD_HEADLESS)) + return -ENOEXEC; + + const char *message = req && req->message ? req->message : "Password:"; if (flag_file) { notify = inotify_init1(IN_CLOEXEC|IN_NONBLOCK); @@ -357,8 +358,7 @@ int ask_password_plymouth( int ask_password_tty( int ttyfd, - const char *message, - const char *keyname, + const AskPasswordRequest *req, usec_t until, AskPasswordFlags flags, const char *flag_file, @@ -381,16 +381,19 @@ int ask_password_tty( assert(ret); + if (FLAGS_SET(flags, ASK_PASSWORD_HEADLESS)) + return -ENOEXEC; + if (FLAGS_SET(flags, ASK_PASSWORD_NO_TTY)) return -EUNATCH; - if (!message) - message = "Password:"; + const char *message = req && req->message ? req->message : "Password:"; + const char *keyring = req ? req->keyring : NULL; if (!FLAGS_SET(flags, ASK_PASSWORD_HIDE_EMOJI) && emoji_enabled()) message = strjoina(special_glyph(SPECIAL_GLYPH_LOCK_AND_KEY), " ", message); - if (flag_file || (FLAGS_SET(flags, ASK_PASSWORD_ACCEPT_CACHED) && keyname)) { + if (flag_file || (FLAGS_SET(flags, ASK_PASSWORD_ACCEPT_CACHED) && keyring)) { notify = inotify_init1(IN_CLOEXEC|IN_NONBLOCK); if (notify < 0) return -errno; @@ -399,8 +402,8 @@ int ask_password_tty( if (inotify_add_watch(notify, flag_file, IN_ATTRIB /* for the link count */) < 0) return -errno; } - if (FLAGS_SET(flags, ASK_PASSWORD_ACCEPT_CACHED) && keyname) { - r = ask_password_keyring(keyname, flags, ret); + if (FLAGS_SET(flags, ASK_PASSWORD_ACCEPT_CACHED) && req && keyring) { + r = ask_password_keyring(req, flags, ret); if (r >= 0) return 0; else if (r != -ENOKEY) @@ -487,10 +490,10 @@ int ask_password_tty( goto finish; } - if (notify >= 0 && pollfd[POLL_INOTIFY].revents != 0 && keyname) { + if (notify >= 0 && pollfd[POLL_INOTIFY].revents != 0 && keyring) { (void) flush_fd(notify); - r = ask_password_keyring(keyname, flags, ret); + r = ask_password_keyring(req, flags, ret); if (r >= 0) { r = 0; goto finish; @@ -629,8 +632,8 @@ skipped: if (strv_isempty(l)) r = log_debug_errno(SYNTHETIC_ERRNO(ECANCELED), "Password query was cancelled."); else { - if (keyname) - (void) add_to_keyring_and_log(keyname, flags, l); + if (keyring) + (void) add_to_keyring_and_log(keyring, flags, l); *ret = TAKE_PTR(l); r = 0; @@ -679,10 +682,7 @@ static int create_socket(char **ret) { } int ask_password_agent( - const char *message, - const char *icon, - const char *id, - const char *keyname, + const AskPasswordRequest *req, usec_t until, AskPasswordFlags flags, char ***ret) { @@ -706,6 +706,9 @@ int ask_password_agent( assert(ret); + if (FLAGS_SET(flags, ASK_PASSWORD_HEADLESS)) + return -ENOEXEC; + if (FLAGS_SET(flags, ASK_PASSWORD_NO_AGENT)) return -EUNATCH; @@ -715,8 +718,8 @@ int ask_password_agent( (void) mkdir_p_label("/run/systemd/ask-password", 0755); - if (FLAGS_SET(flags, ASK_PASSWORD_ACCEPT_CACHED) && keyname) { - r = ask_password_keyring(keyname, flags, ret); + if (FLAGS_SET(flags, ASK_PASSWORD_ACCEPT_CACHED) && req && req->keyring) { + r = ask_password_keyring(req, flags, ret); if (r >= 0) { r = 0; goto finish; @@ -775,14 +778,16 @@ int ask_password_agent( until, FLAGS_SET(flags, ASK_PASSWORD_SILENT)); - if (message) - fprintf(f, "Message=%s\n", message); + if (req) { + if (req->message) + fprintf(f, "Message=%s\n", req->message); - if (icon) - fprintf(f, "Icon=%s\n", icon); + if (req->icon) + fprintf(f, "Icon=%s\n", req->icon); - if (id) - fprintf(f, "Id=%s\n", id); + if (req->id) + fprintf(f, "Id=%s\n", req->id); + } r = fflush_and_check(f); if (r < 0) @@ -837,12 +842,14 @@ int ask_password_agent( if (notify >= 0 && pollfd[FD_INOTIFY].revents != 0) { (void) flush_fd(notify); - r = ask_password_keyring(keyname, flags, ret); - if (r >= 0) { - r = 0; - goto finish; - } else if (r != -ENOKEY) - goto finish; + if (req && req->keyring) { + r = ask_password_keyring(req, flags, ret); + if (r >= 0) { + r = 0; + goto finish; + } else if (r != -ENOKEY) + goto finish; + } } if (pollfd[FD_SOCKET].revents == 0) @@ -921,8 +928,8 @@ int ask_password_agent( log_debug("Invalid packet"); } - if (keyname) - (void) add_to_keyring_and_log(keyname, flags, l); + if (req && req->keyring) + (void) add_to_keyring_and_log(req->keyring, flags, l); *ret = TAKE_PTR(l); r = 0; @@ -940,16 +947,17 @@ finish: return r; } -static int ask_password_credential(const char *credential_name, AskPasswordFlags flags, char ***ret) { +static int ask_password_credential(const AskPasswordRequest *req, AskPasswordFlags flags, char ***ret) { _cleanup_(erase_and_freep) char *buffer = NULL; size_t size; char **l; int r; - assert(credential_name); + assert(req); + assert(req->credential); assert(ret); - r = read_credential(credential_name, (void**) &buffer, &size); + r = read_credential(req->credential, (void**) &buffer, &size); if (IN_SET(r, -ENXIO, -ENOENT)) /* No credentials passed or this credential not defined? */ return -ENOKEY; @@ -962,11 +970,7 @@ static int ask_password_credential(const char *credential_name, AskPasswordFlags } int ask_password_auto( - const char *message, - const char *icon, - const char *id, /* id in "ask-password" protocol */ - const char *key_name, /* name in kernel keyring */ - const char *credential_name, /* name in $CREDENTIALS_DIRECTORY directory */ + const AskPasswordRequest *req, usec_t until, AskPasswordFlags flags, char ***ret) { @@ -975,26 +979,26 @@ int ask_password_auto( assert(ret); - if (!FLAGS_SET(flags, ASK_PASSWORD_NO_CREDENTIAL) && credential_name) { - r = ask_password_credential(credential_name, flags, ret); + if (!FLAGS_SET(flags, ASK_PASSWORD_NO_CREDENTIAL) && req && req->credential) { + r = ask_password_credential(req, flags, ret); if (r != -ENOKEY) return r; } if (FLAGS_SET(flags, ASK_PASSWORD_ACCEPT_CACHED) && - key_name && + req && req->keyring && (FLAGS_SET(flags, ASK_PASSWORD_NO_TTY) || !isatty(STDIN_FILENO)) && FLAGS_SET(flags, ASK_PASSWORD_NO_AGENT)) { - r = ask_password_keyring(key_name, flags, ret); + r = ask_password_keyring(req, flags, ret); if (r != -ENOKEY) return r; } if (!FLAGS_SET(flags, ASK_PASSWORD_NO_TTY) && isatty(STDIN_FILENO)) - return ask_password_tty(-1, message, key_name, until, flags, NULL, ret); + return ask_password_tty(-EBADF, req, until, flags, NULL, ret); if (!FLAGS_SET(flags, ASK_PASSWORD_NO_AGENT)) - return ask_password_agent(message, icon, id, key_name, until, flags, ret); + return ask_password_agent(req, until, flags, ret); return -EUNATCH; } diff --git a/src/shared/ask-password-api.h b/src/shared/ask-password-api.h index 7464e7f6de..e851d6d087 100644 --- a/src/shared/ask-password-api.h +++ b/src/shared/ask-password-api.h @@ -15,9 +15,19 @@ typedef enum AskPasswordFlags { ASK_PASSWORD_CONSOLE_COLOR = 1 << 6, /* Use color if /dev/console points to a console that supports color */ ASK_PASSWORD_NO_CREDENTIAL = 1 << 7, /* never use $CREDENTIALS_DIRECTORY data */ ASK_PASSWORD_HIDE_EMOJI = 1 << 8, /* hide the lock and key emoji */ + ASK_PASSWORD_HEADLESS = 1 << 9, /* headless mode: never query interactively */ } AskPasswordFlags; -int ask_password_tty(int tty_fd, const char *message, const char *key_name, usec_t until, AskPasswordFlags flags, const char *flag_file, char ***ret); -int ask_password_plymouth(const char *message, usec_t until, AskPasswordFlags flags, const char *flag_file, char ***ret); -int ask_password_agent(const char *message, const char *icon, const char *id, const char *key_name, usec_t until, AskPasswordFlags flag, char ***ret); -int ask_password_auto(const char *message, const char *icon, const char *id, const char *key_name, const char *credential_name, usec_t until, AskPasswordFlags flag, char ***ret); +/* Encapsulates the mostly static fields of a password query */ +typedef struct AskPasswordRequest { + const char *message; /* The human readable password prompt when asking interactively */ + const char *keyring; /* kernel keyring key name (key of "user" type) */ + const char *icon; /* freedesktop icon spec name */ + const char *id; /* some identifier used for this prompt for the "ask-password" protocol */ + const char *credential; /* $CREDENTIALS_DIRECTORY credential name */ +} AskPasswordRequest; + +int ask_password_tty(int tty_fd, const AskPasswordRequest *req, usec_t until, AskPasswordFlags flags, const char *flag_file, char ***ret); +int ask_password_plymouth(const AskPasswordRequest *req, usec_t until, AskPasswordFlags flags, const char *flag_file, char ***ret); +int ask_password_agent(const AskPasswordRequest *req, usec_t until, AskPasswordFlags flag, char ***ret); +int ask_password_auto(const AskPasswordRequest *req, usec_t until, AskPasswordFlags flag, char ***ret); diff --git a/src/shared/cryptsetup-fido2.c b/src/shared/cryptsetup-fido2.c index 2d59a630a6..5ab5cefe8f 100644 --- a/src/shared/cryptsetup-fido2.c +++ b/src/shared/cryptsetup-fido2.c @@ -24,11 +24,11 @@ int acquire_fido2_key( const void *key_data, size_t key_data_size, usec_t until, - bool headless, Fido2EnrollFlags required, + const char *askpw_credential, + AskPasswordFlags askpw_flags, void **ret_decrypted_key, - size_t *ret_decrypted_key_size, - AskPasswordFlags ask_password_flags) { + size_t *ret_decrypted_key_size) { _cleanup_(erase_and_freep) char *envpw = NULL; _cleanup_strv_free_erase_ char **pins = NULL; @@ -38,11 +38,11 @@ int acquire_fido2_key( size_t salt_size; int r; - if ((required & (FIDO2ENROLL_PIN | FIDO2ENROLL_UP | FIDO2ENROLL_UV)) && headless) + if ((required & (FIDO2ENROLL_PIN | FIDO2ENROLL_UP | FIDO2ENROLL_UV)) && FLAGS_SET(askpw_flags, ASK_PASSWORD_HEADLESS)) return log_error_errno(SYNTHETIC_ERRNO(ENOPKG), "Local verification is required to unlock this volume, but the 'headless' parameter was set."); - ask_password_flags |= ASK_PASSWORD_PUSH_CACHE | ASK_PASSWORD_ACCEPT_CACHED; + askpw_flags |= ASK_PASSWORD_PUSH_CACHE | ASK_PASSWORD_ACCEPT_CACHED; assert(cid); assert(key_file || key_data); @@ -115,15 +115,22 @@ int acquire_fido2_key( device_exists = true; /* that a PIN is needed/wasn't correct means that we managed to * talk to a device */ - if (headless) + if (FLAGS_SET(askpw_flags, ASK_PASSWORD_HEADLESS)) return log_error_errno(SYNTHETIC_ERRNO(ENOPKG), "PIN querying disabled via 'headless' option. Use the '$PIN' environment variable."); + static const AskPasswordRequest req = { + .message = "Please enter security token PIN:", + .icon = "drive-harddisk", + .keyring = "fido2-pin", + .credential = "cryptsetup.fido2-pin", + }; + 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); + r = ask_password_auto(&req, until, askpw_flags, &pins); if (r < 0) return log_error_errno(r, "Failed to ask for user password: %m"); - ask_password_flags &= ~ASK_PASSWORD_ACCEPT_CACHED; + askpw_flags &= ~ASK_PASSWORD_ACCEPT_CACHED; } } @@ -133,10 +140,10 @@ int acquire_fido2_key_auto( const char *friendly_name, const char *fido2_device, usec_t until, - bool headless, + const char *askpw_credential, + AskPasswordFlags askpw_flags, void **ret_decrypted_key, - size_t *ret_decrypted_key_size, - AskPasswordFlags ask_password_flags) { + size_t *ret_decrypted_key_size) { _cleanup_free_ void *cid = NULL; size_t cid_size = 0; @@ -254,10 +261,11 @@ int acquire_fido2_key_auto( /* key_file_offset= */ 0, salt, salt_size, until, - headless, required, - ret_decrypted_key, ret_decrypted_key_size, - ask_password_flags); + "cryptsetup.fido2-pin", + askpw_flags, + ret_decrypted_key, + ret_decrypted_key_size); if (ret == 0) break; } diff --git a/src/shared/cryptsetup-fido2.h b/src/shared/cryptsetup-fido2.h index d96bb403ff..bd25566806 100644 --- a/src/shared/cryptsetup-fido2.h +++ b/src/shared/cryptsetup-fido2.h @@ -23,11 +23,11 @@ int acquire_fido2_key( const void *key_data, size_t key_data_size, usec_t until, - bool headless, Fido2EnrollFlags required, + const char *askpw_credential, + AskPasswordFlags askpw_flags, void **ret_decrypted_key, - size_t *ret_decrypted_key_size, - AskPasswordFlags ask_password_flags); + size_t *ret_decrypted_key_size); int acquire_fido2_key_auto( struct crypt_device *cd, @@ -35,10 +35,10 @@ int acquire_fido2_key_auto( const char *friendly_name, const char *fido2_device, usec_t until, - bool headless, + const char *askpw_credential, + AskPasswordFlags askpw_flags, void **ret_decrypted_key, - size_t *ret_decrypted_key_size, - AskPasswordFlags ask_password_flags); + size_t *ret_decrypted_key_size); #else @@ -55,11 +55,11 @@ static inline int acquire_fido2_key( const void *key_data, size_t key_data_size, usec_t until, - bool headless, Fido2EnrollFlags required, + const char *askpw_credential, + AskPasswordFlags askpw_flags, void **ret_decrypted_key, - size_t *ret_decrypted_key_size, - AskPasswordFlags ask_password_flags) { + size_t *ret_decrypted_key_size) { return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "FIDO2 token support not available."); @@ -71,10 +71,10 @@ static inline int acquire_fido2_key_auto( const char *friendly_name, const char *fido2_device, usec_t until, - bool headless, + const char *askpw_credential, + AskPasswordFlags askpw_flags, void **ret_decrypted_key, - size_t *ret_decrypted_key_size, - AskPasswordFlags ask_password_flags) { + size_t *ret_decrypted_key_size) { return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "FIDO2 token support not available."); diff --git a/src/shared/cryptsetup-tpm2.c b/src/shared/cryptsetup-tpm2.c index 297ef6fe4a..ee664a95a1 100644 --- a/src/shared/cryptsetup-tpm2.c +++ b/src/shared/cryptsetup-tpm2.c @@ -12,7 +12,11 @@ #include "sha256.h" #include "tpm2-util.h" -static int get_pin(usec_t until, AskPasswordFlags ask_password_flags, bool headless, char **ret_pin_str) { +static int get_pin( + usec_t until, + const char *askpw_credential, + AskPasswordFlags askpw_flags, + char **ret_pin_str) { _cleanup_(erase_and_freep) char *pin_str = NULL; _cleanup_strv_free_erase_ char **pin = NULL; int r; @@ -23,22 +27,21 @@ static int get_pin(usec_t until, AskPasswordFlags ask_password_flags, bool headl if (r < 0) return log_error_errno(r, "Failed to acquire PIN from environment: %m"); if (!r) { - if (headless) + if (FLAGS_SET(askpw_flags, ASK_PASSWORD_HEADLESS)) return log_error_errno( SYNTHETIC_ERRNO(ENOPKG), "PIN querying disabled via 'headless' option. " "Use the '$PIN' environment variable."); + AskPasswordRequest req = { + .message = "Please enter TPM2 PIN:", + .icon = "drive-harddisk", + .keyring = "tpm2-pin", + .credential = askpw_credential, + }; + pin = strv_free_erase(pin); - r = ask_password_auto( - "Please enter TPM2 PIN:", - "drive-harddisk", - NULL, - "tpm2-pin", - "cryptsetup.tpm2-pin", - until, - ask_password_flags, - &pin); + r = ask_password_auto(&req, until, askpw_flags, &pin); if (r < 0) return log_error_errno(r, "Failed to ask for user pin: %m"); assert(strv_length(pin) == 1); @@ -73,8 +76,8 @@ int acquire_tpm2_key( const struct iovec *pcrlock_nv, TPM2Flags flags, usec_t until, - bool headless, - AskPasswordFlags ask_password_flags, + const char *askpw_credential, + AskPasswordFlags askpw_flags, struct iovec *ret_decrypted_key) { _cleanup_(json_variant_unrefp) JsonVariant *signature_json = NULL; @@ -170,7 +173,7 @@ int acquire_tpm2_key( if (i <= 0) return -EACCES; - r = get_pin(until, ask_password_flags, headless, &pin_str); + r = get_pin(until, askpw_credential, askpw_flags, &pin_str); if (r < 0) return r; diff --git a/src/shared/cryptsetup-tpm2.h b/src/shared/cryptsetup-tpm2.h index 0eaf9280ef..b9905f4f4b 100644 --- a/src/shared/cryptsetup-tpm2.h +++ b/src/shared/cryptsetup-tpm2.h @@ -31,8 +31,8 @@ int acquire_tpm2_key( const struct iovec *pcrlock_nv, TPM2Flags flags, usec_t until, - bool headless, - AskPasswordFlags ask_password_flags, + const char *askpw_credential, + AskPasswordFlags askpw_flags, struct iovec *ret_decrypted_key); int find_tpm2_auto_data( @@ -75,8 +75,8 @@ static inline int acquire_tpm2_key( const struct iovec *pcrlock_nv, TPM2Flags flags, usec_t until, - bool headless, - AskPasswordFlags ask_password_flags, + const char *askpw_credential, + AskPasswordFlags askpw_flags, struct iovec *ret_decrypted_key) { return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), diff --git a/src/shared/dissect-image.c b/src/shared/dissect-image.c index d7c705184a..216c036a31 100644 --- a/src/shared/dissect-image.c +++ b/src/shared/dissect-image.c @@ -2989,9 +2989,16 @@ int dissected_image_decrypt_interactively( return log_error_errno(SYNTHETIC_ERRNO(EKEYREJECTED), "Too many retries."); - z = strv_free(z); + z = strv_free_erase(z); - r = ask_password_auto("Please enter image passphrase:", NULL, "dissect", "dissect", "dissect.passphrase", USEC_INFINITY, 0, &z); + static const AskPasswordRequest req = { + .message = "Please enter image passphrase:", + .id = "dissect", + .keyring = "dissect", + .credential = "dissect.passphrase", + }; + + r = ask_password_auto(&req, USEC_INFINITY, /* flags= */ 0, &z); if (r < 0) return log_error_errno(r, "Failed to query for passphrase: %m"); diff --git a/src/shared/libfido2-util.c b/src/shared/libfido2-util.c index 43efa3529a..f5df579369 100644 --- a/src/shared/libfido2-util.c +++ b/src/shared/libfido2-util.c @@ -686,7 +686,8 @@ int fido2_generate_hmac_hash( const char *user_name, const char *user_display_name, const char *user_icon, - const char *askpw_icon_name, + const char *askpw_icon, + const char *askpw_credential, Fido2EnrollFlags lock_with, int cred_alg, void **ret_cid, size_t *ret_cid_size, @@ -838,8 +839,14 @@ int fido2_generate_hmac_hash( for (;;) { _cleanup_strv_free_erase_ char **pin = NULL; + AskPasswordRequest req = { + .message = "Please enter security token PIN:", + .icon = askpw_icon, + .keyring = "fido2-pin", + .credential = askpw_credential, + }; - r = ask_password_auto("Please enter security token PIN:", askpw_icon_name, NULL, "fido2-pin", "fido2-pin", USEC_INFINITY, 0, &pin); + r = ask_password_auto(&req, USEC_INFINITY, /* flags= */ 0, &pin); if (r < 0) return log_error_errno(r, "Failed to acquire user PIN: %m"); diff --git a/src/shared/libfido2-util.h b/src/shared/libfido2-util.h index 4cfc95f712..3520ab4ec3 100644 --- a/src/shared/libfido2-util.h +++ b/src/shared/libfido2-util.h @@ -109,7 +109,8 @@ int fido2_generate_hmac_hash( const char *user_name, const char *user_display_name, const char *user_icon, - const char *askpw_icon_name, + const char *askpw_icon, + const char *askpw_credential, Fido2EnrollFlags lock_with, int cred_alg, void **ret_cid, size_t *ret_cid_size, diff --git a/src/shared/pkcs11-util.c b/src/shared/pkcs11-util.c index 832d8af7e4..c330d9b6e0 100644 --- a/src/shared/pkcs11-util.c +++ b/src/shared/pkcs11-util.c @@ -291,12 +291,11 @@ int pkcs11_token_login( CK_SLOT_ID slotid, const CK_TOKEN_INFO *token_info, const char *friendly_name, - const char *icon_name, - const char *key_name, - const char *credential_name, + const char *askpw_icon, + const char *askpw_keyring, + const char *askpw_credential, usec_t until, - AskPasswordFlags ask_password_flags, - bool headless, + AskPasswordFlags askpw_flags, char **ret_used_pin) { _cleanup_free_ char *token_uri_string = NULL, *token_uri_escaped = NULL, *id = NULL, *token_label = NULL; @@ -351,7 +350,7 @@ int pkcs11_token_login( if (!passwords) return log_oom(); - } else if (headless) + } else if (FLAGS_SET(askpw_flags, ASK_PASSWORD_HEADLESS)) return log_error_errno(SYNTHETIC_ERRNO(ENOPKG), "PIN querying disabled via 'headless' option. Use the 'PIN' environment variable."); else { _cleanup_free_ char *text = NULL; @@ -375,8 +374,16 @@ int pkcs11_token_login( if (r < 0) return log_oom(); + AskPasswordRequest req = { + .message = text, + .icon = askpw_icon, + .id = id, + .keyring = askpw_keyring, + .credential = askpw_credential, + }; + /* We never cache PINs, simply because it's fatal if we use wrong PINs, since usually there are only 3 tries */ - r = ask_password_auto(text, icon_name, id, key_name, credential_name, until, ask_password_flags, &passwords); + r = ask_password_auto(&req, until, askpw_flags, &passwords); if (r < 0) return log_error_errno(r, "Failed to query PIN for security token '%s': %m", token_label); } @@ -1643,9 +1650,8 @@ int pkcs11_find_token( struct pkcs11_acquire_public_key_callback_data { char *pin_used; EVP_PKEY *pkey; - const char *askpw_friendly_name, *askpw_icon_name; + const char *askpw_friendly_name, *askpw_icon, *askpw_credential; AskPasswordFlags askpw_flags; - bool headless; }; static void pkcs11_acquire_public_key_callback_data_release(struct pkcs11_acquire_public_key_callback_data *data) { @@ -1690,12 +1696,11 @@ static int pkcs11_acquire_public_key_callback( slot_id, token_info, data->askpw_friendly_name, - data->askpw_icon_name, - "pkcs11-pin", + data->askpw_icon, "pkcs11-pin", + data->askpw_credential, UINT64_MAX, data->askpw_flags, - data->headless, &pin_used); if (r < 0) return r; @@ -1821,13 +1826,17 @@ success: int pkcs11_acquire_public_key( const char *uri, const char *askpw_friendly_name, - const char *askpw_icon_name, + const char *askpw_icon, + const char *askpw_credential, + AskPasswordFlags askpw_flags, EVP_PKEY **ret_pkey, char **ret_pin_used) { _cleanup_(pkcs11_acquire_public_key_callback_data_release) struct pkcs11_acquire_public_key_callback_data data = { .askpw_friendly_name = askpw_friendly_name, - .askpw_icon_name = askpw_icon_name, + .askpw_icon = askpw_icon, + .askpw_credential = askpw_credential, + .askpw_flags = askpw_flags, }; int r; @@ -2032,10 +2041,9 @@ int pkcs11_crypt_device_callback( data->friendly_name, "drive-harddisk", "pkcs11-pin", - "cryptsetup.pkcs11-pin", + data->askpw_credential, data->until, data->askpw_flags, - data->headless, NULL); if (r < 0) return r; diff --git a/src/shared/pkcs11-util.h b/src/shared/pkcs11-util.h index 838f90b6c1..6927a37113 100644 --- a/src/shared/pkcs11-util.h +++ b/src/shared/pkcs11-util.h @@ -53,7 +53,7 @@ char *pkcs11_token_manufacturer_id(const CK_TOKEN_INFO *token_info); char *pkcs11_token_model(const CK_TOKEN_INFO *token_info); int pkcs11_token_login_by_pin(CK_FUNCTION_LIST *m, CK_SESSION_HANDLE session, const CK_TOKEN_INFO *token_info, const char *token_label, const void *pin, size_t pin_size); -int pkcs11_token_login(CK_FUNCTION_LIST *m, CK_SESSION_HANDLE session, CK_SLOT_ID slotid, const CK_TOKEN_INFO *token_info, const char *friendly_name, const char *icon_name, const char *key_name, const char *credential_name, usec_t until, AskPasswordFlags ask_password_flags, bool headless, char **ret_used_pin); +int pkcs11_token_login(CK_FUNCTION_LIST *m, CK_SESSION_HANDLE session, CK_SLOT_ID slotid, const CK_TOKEN_INFO *token_info, const char *friendly_name, const char *icon_name, const char *key_name, const char *credential_name, usec_t until, AskPasswordFlags ask_password_flags, char **ret_used_pin); int pkcs11_token_find_related_object(CK_FUNCTION_LIST *m, CK_SESSION_HANDLE session, CK_OBJECT_HANDLE prototype, CK_OBJECT_CLASS class, CK_OBJECT_HANDLE *ret_object); int pkcs11_token_find_x509_certificate(CK_FUNCTION_LIST *m, CK_SESSION_HANDLE session, P11KitUri *search_uri, CK_OBJECT_HANDLE *ret_object); @@ -71,7 +71,7 @@ typedef int (*pkcs11_find_token_callback_t)(CK_FUNCTION_LIST *m, CK_SESSION_HAND int pkcs11_find_token(const char *pkcs11_uri, pkcs11_find_token_callback_t callback, void *userdata); #if HAVE_OPENSSL -int pkcs11_acquire_public_key(const char *uri, const char *askpw_friendly_name, const char *askpw_icon_name, EVP_PKEY **ret_pkey, char **ret_pin_used); +int pkcs11_acquire_public_key(const char *uri, const char *askpw_friendly_name, const char *askpw_icon, const char *askpw_credential, AskPasswordFlags askpw_flags, EVP_PKEY **ret_pkey, char **ret_pin_used); #endif typedef struct { @@ -82,7 +82,7 @@ typedef struct { void *decrypted_key; size_t decrypted_key_size; bool free_encrypted_key; - bool headless; + const char *askpw_credential; AskPasswordFlags askpw_flags; } pkcs11_crypt_device_callback_data; @@ -110,7 +110,7 @@ static inline int dlopen_p11kit(void) { typedef struct { const char *friendly_name; usec_t until; - bool headless; + const char *askpw_credential; AskPasswordFlags askpw_flags; } systemd_pkcs11_plugin_params; diff --git a/src/test/test-ask-password-api.c b/src/test/test-ask-password-api.c index b24159e2aa..8fee07330d 100644 --- a/src/test/test-ask-password-api.c +++ b/src/test/test-ask-password-api.c @@ -5,10 +5,15 @@ #include "tests.h" TEST(ask_password) { - int r; _cleanup_strv_free_ char **ret = NULL; + int r; - r = ask_password_tty(-1, "hello?", "da key", 0, ASK_PASSWORD_CONSOLE_COLOR, NULL, &ret); + static const AskPasswordRequest req = { + .message = "hello?", + .keyring = "da key", + }; + + r = ask_password_tty(-EBADF, &req, /* until= */ 0, /* flags= */ ASK_PASSWORD_CONSOLE_COLOR, /* flag_file= */ NULL, &ret); if (r == -ECANCELED) assert_se(ret == NULL); else { diff --git a/src/tty-ask-password-agent/tty-ask-password-agent.c b/src/tty-ask-password-agent/tty-ask-password-agent.c index 3a30bfe042..df979be5cd 100644 --- a/src/tty-ask-password-agent/tty-ask-password-agent.c +++ b/src/tty-ask-password-agent/tty-ask-password-agent.c @@ -157,7 +157,11 @@ static int agent_ask_password_tty( log_info("Starting password query on %s.", con); } - r = ask_password_tty(tty_fd, message, NULL, until, flags, flag_file, ret); + AskPasswordRequest req = { + .message = message, + }; + + r = ask_password_tty(tty_fd, &req, until, flags, flag_file, ret); if (arg_console) { tty_fd = safe_close(tty_fd); @@ -245,9 +249,13 @@ static int process_one_password_file(const char *filename) { SET_FLAG(flags, ASK_PASSWORD_ECHO, echo); SET_FLAG(flags, ASK_PASSWORD_SILENT, silent); - if (arg_plymouth) - r = ask_password_plymouth(message, not_after, flags, filename, &passwords); - else + if (arg_plymouth) { + AskPasswordRequest req = { + .message = message, + }; + + r = ask_password_plymouth(&req, not_after, flags, filename, &passwords); + } else r = agent_ask_password_tty(message, not_after, flags, filename, &passwords); if (r < 0) { /* If the query went away, that's OK */