From: Lennart Poettering Date: Mon, 19 Feb 2024 15:35:12 +0000 (+0100) Subject: ask-password: rework how we pass request meta info when asking passwords X-Git-Tag: v256-rc1~797^2~12 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=d08fd4c314f93e955586337e56ece4ce21c9c329;p=thirdparty%2Fsystemd.git ask-password: rework how we pass request meta info when asking passwords Rather than adding more and more parameters to ask_password_auto(), let's pass a structure of the fields that often are constant anyway. This way, callers can fill in what they need, and we take the filled structure which we can pass around internally as one. This is in particular preparation for adding one more field in one of the next commits. --- diff --git a/src/ask-password/ask-password.c b/src/ask-password/ask-password.c index bf4c93e2dc9..371d3163328 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-password.c b/src/cryptenroll/cryptenroll-password.c index c35b6092c8c..a9f52bceeb4 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("cryptsetup:", 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("cryptsetup:", 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-tpm2.c b/src/cryptenroll/cryptenroll-tpm2.c index fb862a33290..def3acda69b 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.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"); diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c index 1caaa514d5d..06fc32ea270 100644 --- a/src/cryptsetup/cryptsetup.c +++ b/src/cryptsetup/cryptsetup.c @@ -798,11 +798,10 @@ 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); @@ -822,11 +821,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(); + + AskPasswordRequest req = { + .message = text, + .icon = "drive-harddisk", + .id = id, + .keyring = "cryptsetup", + .credential = "cryptsetup.passphrase", + }; - r = ask_password_auto(text, "drive-harddisk", id, "cryptsetup", "cryptsetup.passphrase", until, - flags | (accept_cached*ASK_PASSWORD_ACCEPT_CACHED), - &passwords); + 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 +846,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(); + + req.message = text; + req.id = id; - r = ask_password_auto(text, "drive-harddisk", id, "cryptsetup", "cryptsetup.passphrase", until, flags, &passwords2); + r = ask_password_auto(&req, until, flags, &passwords2); if (r < 0) return log_error_errno(r, "Failed to query verification password: %m"); @@ -1252,8 +1270,8 @@ static int crypt_activate_by_token_pin_ask_password( 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; @@ -1283,7 +1301,15 @@ static int crypt_activate_by_token_pin_ask_password( 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; diff --git a/src/firstboot/firstboot.c b/src/firstboot/firstboot.c index 76af4e4ed52..d9d2e282519 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.c b/src/home/homectl.c index 5357e791a5f..3a839c73eaa 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 1dd3d86a73c..e1f25b62d93 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 = "systemd-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 6d71245549d..a9d9cde97bf 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,7 @@ int ask_password_plymouth( assert(ret); - if (!message) - message = "Password:"; + const char *message = req && req->message ? req->message : "Password:"; if (flag_file) { notify = inotify_init1(IN_CLOEXEC|IN_NONBLOCK); @@ -357,8 +355,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, @@ -384,13 +381,13 @@ int ask_password_tty( 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 +396,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 +484,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 +626,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 +676,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) { @@ -715,8 +709,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 +769,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 +833,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 +919,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 +938,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 +961,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 +970,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 7464e7f6def..fced27798f2 100644 --- a/src/shared/ask-password-api.h +++ b/src/shared/ask-password-api.h @@ -17,7 +17,16 @@ typedef enum AskPasswordFlags { ASK_PASSWORD_HIDE_EMOJI = 1 << 8, /* hide the lock and key emoji */ } 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 2d59a630a65..9771726da4c 100644 --- a/src/shared/cryptsetup-fido2.c +++ b/src/shared/cryptsetup-fido2.c @@ -118,8 +118,15 @@ int acquire_fido2_key( if (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, ask_password_flags, &pins); if (r < 0) return log_error_errno(r, "Failed to ask for user password: %m"); diff --git a/src/shared/cryptsetup-tpm2.c b/src/shared/cryptsetup-tpm2.c index 297ef6fe4a3..d120e4e1fb8 100644 --- a/src/shared/cryptsetup-tpm2.c +++ b/src/shared/cryptsetup-tpm2.c @@ -29,13 +29,16 @@ static int get_pin(usec_t until, AskPasswordFlags ask_password_flags, bool headl "PIN querying disabled via 'headless' option. " "Use the '$PIN' environment variable."); + static const AskPasswordRequest req = { + .message = "Please enter TPM2 PIN:", + .icon = "drive-harddisk", + .keyring = "tpm2-pin", + .credential = "cryptsetup.tpm2-pin", + }; + pin = strv_free_erase(pin); r = ask_password_auto( - "Please enter TPM2 PIN:", - "drive-harddisk", - NULL, - "tpm2-pin", - "cryptsetup.tpm2-pin", + &req, until, ask_password_flags, &pin); diff --git a/src/shared/dissect-image.c b/src/shared/dissect-image.c index d7c705184ab..179ee46e434 100644 --- a/src/shared/dissect-image.c +++ b/src/shared/dissect-image.c @@ -2991,7 +2991,14 @@ int dissected_image_decrypt_interactively( z = strv_free(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 43efa3529ae..18ad00097a9 100644 --- a/src/shared/libfido2-util.c +++ b/src/shared/libfido2-util.c @@ -838,8 +838,14 @@ int fido2_generate_hmac_hash( for (;;) { _cleanup_strv_free_erase_ char **pin = NULL; - - r = ask_password_auto("Please enter security token PIN:", askpw_icon_name, NULL, "fido2-pin", "fido2-pin", USEC_INFINITY, 0, &pin); + AskPasswordRequest req = { + .message = "Please enter security token PIN:", + .icon = askpw_icon_name, + .keyring = "fido2-pin", + .credential = "fido2-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/pkcs11-util.c b/src/shared/pkcs11-util.c index 832d8af7e4b..6d7568d69bf 100644 --- a/src/shared/pkcs11-util.c +++ b/src/shared/pkcs11-util.c @@ -375,8 +375,16 @@ int pkcs11_token_login( if (r < 0) return log_oom(); + AskPasswordRequest req = { + .message = text, + .icon = icon_name, + .id = id, + .keyring = key_name, + .credential = credential_name, + }; + /* 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, ask_password_flags, &passwords); if (r < 0) return log_error_errno(r, "Failed to query PIN for security token '%s': %m", token_label); } diff --git a/src/test/test-ask-password-api.c b/src/test/test-ask-password-api.c index b24159e2aa7..8fee07330d2 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; + + static const AskPasswordRequest req = { + .message = "hello?", + .keyring = "da key", + }; - r = ask_password_tty(-1, "hello?", "da key", 0, ASK_PASSWORD_CONSOLE_COLOR, NULL, &ret); + 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 3a30bfe042e..df979be5cd7 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 */