]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
ask-password: rework how we pass request meta info when asking passwords
authorLennart Poettering <lennart@poettering.net>
Mon, 19 Feb 2024 15:35:12 +0000 (16:35 +0100)
committerLennart Poettering <lennart@poettering.net>
Tue, 20 Feb 2024 15:50:00 +0000 (16:50 +0100)
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.

16 files changed:
src/ask-password/ask-password.c
src/cryptenroll/cryptenroll-password.c
src/cryptenroll/cryptenroll-tpm2.c
src/cryptsetup/cryptsetup.c
src/firstboot/firstboot.c
src/home/homectl.c
src/pcrlock/pcrlock.c
src/shared/ask-password-api.c
src/shared/ask-password-api.h
src/shared/cryptsetup-fido2.c
src/shared/cryptsetup-tpm2.c
src/shared/dissect-image.c
src/shared/libfido2-util.c
src/shared/pkcs11-util.c
src/test/test-ask-password-api.c
src/tty-ask-password-agent/tty-ask-password-agent.c

index bf4c93e2dc917664753171db5dd3c44ea92b0ab0..371d31633288520b8662680766886d9b66221b0c 100644 (file)
@@ -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");
 
index c35b6092c8ca25869ff0c9b3c20b0533ea738717..a9f52bceeb4d3fa560c3054162eb1ad74cb48339 100644 (file)
@@ -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");
 
index fb862a332902691bf790e0124339c2b0e1263e4a..def3acda69bc3f8f81adfb4e73b03b213674e39d 100644 (file)
@@ -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");
index 1caaa514d5da0a7420c62f3bd5aa3bc1c5fe9638..06fc32ea2703cfa53de27d48caa4efb8671f31c0 100644 (file)
@@ -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;
 
index 76af4e4ed52992065187743e8791b3ef4d89d87f..d9d2e282519b6efb4c1427dd1cfc435507ec1915 100644 (file)
@@ -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)
index 5357e791a5fc675bf9d08331d2e319f0e7965062..3a839c73eaad06b589f1c175d3914bbcd1dacb64 100644 (file)
@@ -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");
index 1dd3d86a73c19e39d26b42ff223524dd036fbe62..e1f25b62d93e90c3369647670fa5a3ef68d2d117 100644 (file)
@@ -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);
index 6d71245549d66f3ee84969918d2fa2161061b7b2..a9d9cde97bf952849726ff33c8f332e1dd37f982 100644 (file)
@@ -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;
 }
index 7464e7f6def58c7f33f6a82a889ccd464c650fa9..fced27798f27577c83ba982fd290e9af6f23dbd5 100644 (file)
@@ -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);
index 2d59a630a65b8b013d535ea29dc7d3135a3f7e9e..9771726da4cc586ad35d0e3f03f7c06dcfb64170 100644 (file)
@@ -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");
 
index 297ef6fe4a3f370cb4cefded3b33a2f855c2f12f..d120e4e1fb833eb8b39c7f870993c3e09ef02743 100644 (file)
@@ -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);
index d7c705184ab4e3f33a793a485dc0651c3fc5d053..179ee46e434a8fc697699814a2de026e39183338 100644 (file)
@@ -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");
 
index 43efa3529ae7807c43ca6c0b6d908013aab089da..18ad00097a97cde96e138b6b52655a5a012ac3be 100644 (file)
@@ -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");
 
index 832d8af7e4bcfa6da95849a0f6a9cf25939d3e42..6d7568d69bfc8aa4ec4b2a750ed77a7e9ef32bfd 100644 (file)
@@ -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);
                 }
index b24159e2aa7180d3eaf09ac7da6905151f9f6d3e..8fee07330d28f902b8da0bfba2c213c938834d2a 100644 (file)
@@ -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 {
index 3a30bfe042e437490fe40f1792c244ac6fd1658f..df979be5cd74bb550a1a7ad2b8092fd02d901a11 100644 (file)
@@ -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 */