]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
ask-password-api: add new "hup_fd" field to AskPasswordReq
authorLennart Poettering <lennart@poettering.net>
Thu, 7 Nov 2024 10:38:23 +0000 (11:38 +0100)
committerLennart Poettering <lennart@poettering.net>
Thu, 2 Jan 2025 15:38:44 +0000 (16:38 +0100)
This new field allows specification of an fd on which the password
prompt logic will look for POLLHUP events for, and if seen will abort
the query.

The usecase for this is that when we query for a pw on behalf of a
Varlink client we can abort the query automatically if the client dies.

21 files changed:
src/ask-password/ask-password.c
src/bootctl/bootctl-install.c
src/cryptenroll/cryptenroll-password.c
src/cryptenroll/cryptenroll-tpm2.c
src/cryptsetup/cryptsetup.c
src/firstboot/firstboot.c
src/home/homectl.c
src/keyutil/keyutil.c
src/measure/measure.c
src/pcrlock/pcrlock.c
src/repart/repart.c
src/sbsign/sbsign.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 d3afc377813b5e2c63de7f3e421781d571517281..154aaa030e8a3c69be808a98f9d453d85309224a 100644 (file)
@@ -259,6 +259,7 @@ static int run(int argc, char *argv[]) {
                 .keyring = arg_key_name,
                 .credential = arg_credential_name ?: "password",
                 .until = timeout,
+                .hup_fd = -EBADF,
         };
 
         r = ask_password_auto(&req, arg_flags, &l);
index 76deba56e7bbb9149c5128925cc9c4de4cd97c45..884521bcfa9513fcf22636ff177c191c8cec2952 100644 (file)
@@ -989,6 +989,7 @@ int verb_install(int argc, char *argv[], void *userdata) {
                                         .keyring = arg_private_key,
                                         .credential = "bootctl.private-key-pin",
                                         .until = USEC_INFINITY,
+                                        .hup_fd = -EBADF,
                                 },
                                 &private_key,
                                 &ui);
index 56a3bb44566e7770de1e6fb95f54943383a55b0a..c6888cc83b1066c6320f9db80fa10d5c8daba02d 100644 (file)
@@ -62,6 +62,7 @@ int load_volume_key_password(
                         .keyring = "cryptenroll",
                         .credential = "cryptenroll.passphrase",
                         .until = USEC_INFINITY,
+                        .hup_fd = -EBADF,
                 };
 
                 for (;;) {
@@ -138,6 +139,7 @@ int enroll_password(
                         .keyring = "cryptenroll",
                         .credential = "cryptenroll.new-passphrase",
                         .until = USEC_INFINITY,
+                        .hup_fd = -EBADF,
                 };
 
                 for (;;) {
index 42d5a9cd036cc47a608933b8f256993a5de74c8e..fd03fecc62911ef61048c7a66256de8460bdee9f 100644 (file)
@@ -125,6 +125,7 @@ static int get_pin(char **ret_pin_str, TPM2Flags *ret_flags) {
                                 .keyring = "tpm2-pin",
                                 .credential = "cryptenroll.new-tpm2-pin",
                                 .until = USEC_INFINITY,
+                                .hup_fd = -EBADF,
                         };
 
                         pin = strv_free_erase(pin);
index cb3b591186a63969038c71350ec1df79eba78a1f..e5f21bbce7756ff783139e3be4dd45657d20c9c2 100644 (file)
@@ -913,6 +913,7 @@ static int get_password(
                 .keyring = "cryptsetup",
                 .credential = "cryptsetup.passphrase",
                 .until = until,
+                .hup_fd = -EBADF,
         };
 
         if (ignore_cached)
@@ -1430,6 +1431,7 @@ static int crypt_activate_by_token_pin_ask_password(
                         .keyring = keyring,
                         .credential = credential,
                         .until = until,
+                        .hup_fd = -EBADF,
                 };
 
                 r = ask_password_auto(&req, flags, &pins);
index 5658255358c37d3d0eda28f13254e6453c614cb0..15abb53be8454181d3c70e701ed900a9b637ed2f 100644 (file)
@@ -738,6 +738,7 @@ static int prompt_root_password(int rfd) {
                         .tty_fd = -EBADF,
                         .message = msg1,
                         .until = USEC_INFINITY,
+                        .hup_fd = -EBADF,
                 };
 
                 r = ask_password_tty(&req, /* flags= */ 0, &a);
index 611fb966fe60eaf43cbb9892ad42bb4c5fe7d34f..104c35454b517f24180a80d31b573eed4c06c6da 100644 (file)
@@ -269,6 +269,7 @@ static int acquire_existing_password(
                 .keyring = "home-password",
                 .credential = "home.password",
                 .until = USEC_INFINITY,
+                .hup_fd = -EBADF,
         };
 
         r = ask_password_auto(&req, flags, &password);
@@ -329,6 +330,7 @@ static int acquire_recovery_key(
                 .keyring = "home-recovery-key",
                 .credential = "home.recovery-key",
                 .until = USEC_INFINITY,
+                .hup_fd = -EBADF,
         };
 
         r = ask_password_auto(&req, flags, &recovery_key);
@@ -385,6 +387,7 @@ static int acquire_token_pin(
                 .keyring = "token-pin",
                 .credential = "home.token-pin",
                 .until = USEC_INFINITY,
+                .hup_fd = -EBADF,
         };
 
         r = ask_password_auto(&req, flags, &pin);
@@ -1241,6 +1244,7 @@ static int acquire_new_password(
                         .keyring = "home-password",
                         .credential = "home.new-password",
                         .until = USEC_INFINITY,
+                        .hup_fd = -EBADF,
                 };
 
                 r = ask_password_auto(
index bae742157286bca5ea1a1cdccabb783a1581c753..23459e48f590a0182cdd7bce82b7051361da18fb 100644 (file)
@@ -187,6 +187,7 @@ static int verb_validate(int argc, char *argv[], void *userdata) {
                                 .keyring = arg_private_key,
                                 .credential = "keyutil.private-key-pin",
                                 .until = USEC_INFINITY,
+                                .hup_fd = -EBADF,
                         },
                         &private_key,
                         &ui);
@@ -245,6 +246,7 @@ static int verb_public(int argc, char *argv[], void *userdata) {
                                         .keyring = arg_private_key,
                                         .credential = "keyutil.private-key-pin",
                                         .until = USEC_INFINITY,
+                                        .hup_fd = -EBADF,
                                 },
                                 &private_key,
                                 &ui);
index fbd039da7915f26e99e5e59500d6c5775314c399..18461797b7e991c55897ea3347bc52dcf896e02e 100644 (file)
@@ -893,6 +893,7 @@ static int verb_sign(int argc, char *argv[], void *userdata) {
                                         .keyring = arg_private_key,
                                         .credential = "measure.private-key-pin",
                                         .until = USEC_INFINITY,
+                                        .hup_fd = -EBADF,
                                 },
                                 &privkey,
                                 &ui);
index b22ee57788e18ea4c3906a2265cc609c90a29748..72b13f8fac49e4dfe988a7bdfe91dafd363902ad 100644 (file)
@@ -4556,6 +4556,7 @@ static int make_policy(bool force, RecoveryPinMode recovery_pin_mode) {
                                 .id = "pcrlock-recovery-pin",
                                 .credential = "pcrlock.recovery-pin",
                                 .until = USEC_INFINITY,
+                                .hup_fd = -EBADF,
                         };
 
                         r = ask_password_auto(
index b381d4808ac56cf41e39b5c9d44d4e0593b74663..7934a974355e6948aaa6c2be28219fd8339ca4db 100644 (file)
@@ -8577,6 +8577,7 @@ static int parse_argv(int argc, char *argv[], X509 **ret_certificate, EVP_PKEY *
                                         .keyring = arg_private_key,
                                         .credential = "repart.private-key-pin",
                                         .until = USEC_INFINITY,
+                                        .hup_fd = -EBADF,
                                 },
                                 &private_key,
                                 &ui);
index 5c5c884c98d88b5fba325f953651cebc6ae6d456..92b8284219823aa201f2fe2831a418876e0d7370 100644 (file)
@@ -208,6 +208,7 @@ static int verb_sign(int argc, char *argv[], void *userdata) {
                                 .keyring = arg_private_key,
                                 .credential = "sbsign.private-key-pin",
                                 .until = USEC_INFINITY,
+                                .hup_fd = -EBADF,
                         },
                         &private_key,
                         &ui);
index 39e6277b376e63ad2a8fbade18a47e780781ad1b..502b22ee89efa806deb24ff1ce597c87cd3d411b 100644 (file)
@@ -355,15 +355,30 @@ int ask_password_plymouth(
 
         enum {
                 POLL_SOCKET,
-                POLL_INOTIFY, /* Must be last, because optional */
+                POLL_TWO,
+                POLL_THREE,
                 _POLL_MAX,
         };
 
         struct pollfd pollfd[_POLL_MAX] = {
-                [POLL_SOCKET]  = { .fd = fd,         .events = POLLIN },
-                [POLL_INOTIFY] = { .fd = inotify_fd, .events = POLLIN },
+                [POLL_SOCKET] = {
+                        .fd = fd,
+                        .events = POLLIN,
+                },
         };
-        size_t n_pollfd = inotify_fd >= 0 ? _POLL_MAX : _POLL_MAX-1;
+        size_t n_pollfd = POLL_SOCKET + 1, inotify_idx = SIZE_MAX, hup_fd_idx = SIZE_MAX;
+        if (inotify_fd >= 0)
+                pollfd[inotify_idx = n_pollfd++] = (struct pollfd) {
+                        .fd = inotify_fd,
+                        .events = POLLIN,
+                };
+        if (req->hup_fd >= 0)
+                pollfd[hup_fd_idx = n_pollfd++] = (struct pollfd) {
+                        .fd = req->hup_fd,
+                        .events = POLLHUP,
+                };
+
+        assert(n_pollfd <= _POLL_MAX);
 
         for (;;) {
                 usec_t timeout;
@@ -384,7 +399,10 @@ int ask_password_plymouth(
                 if (r == 0)
                         return -ETIME;
 
-                if (inotify_fd >= 0 && pollfd[POLL_INOTIFY].revents != 0)
+                if (req->hup_fd >= 0 && pollfd[hup_fd_idx].revents & POLLHUP)
+                        return -ECONNRESET;
+
+                if (inotify_fd >= 0 && pollfd[inotify_idx].revents != 0)
                         (void) flush_fd(inotify_fd);
 
                 if (pollfd[POLL_SOCKET].revents == 0)
@@ -567,15 +585,31 @@ int ask_password_tty(
 
         enum {
                 POLL_TTY,
-                POLL_INOTIFY, /* Must be last, because optional */
+                POLL_TWO,
+                POLL_THREE,
                 _POLL_MAX,
         };
 
         struct pollfd pollfd[_POLL_MAX] = {
-                [POLL_TTY]     = { .fd = ttyfd >= 0 ? ttyfd : STDIN_FILENO, .events = POLLIN },
-                [POLL_INOTIFY] = { .fd = inotify_fd,                        .events = POLLIN },
+                [POLL_TTY]     = {
+                        .fd = ttyfd >= 0 ? ttyfd : STDIN_FILENO,
+                        .events = POLLIN,
+                },
         };
-        size_t n_pollfd = inotify_fd >= 0 ? _POLL_MAX : _POLL_MAX-1;
+        size_t n_pollfd = POLL_TTY + 1, inotify_idx = SIZE_MAX, hup_fd_idx = SIZE_MAX;
+
+        if (inotify_fd >= 0)
+                pollfd[inotify_idx = n_pollfd++] = (struct pollfd) {
+                        .fd = inotify_fd,
+                        .events = POLLIN,
+                };
+        if (req->hup_fd >= 0)
+                pollfd[hup_fd_idx = n_pollfd++] = (struct pollfd) {
+                        .fd = req->hup_fd,
+                        .events = POLLHUP,
+                };
+
+        assert(n_pollfd <= _POLL_MAX);
 
         for (;;) {
                 _cleanup_(erase_char) char c;
@@ -603,7 +637,12 @@ int ask_password_tty(
                         goto finish;
                 }
 
-                if (inotify_fd >= 0 && pollfd[POLL_INOTIFY].revents != 0 && keyring) {
+                if (req->hup_fd >= 0 && pollfd[hup_fd_idx].revents & POLLHUP) {
+                        r = -ECONNRESET;
+                        goto finish;
+                }
+
+                if (inotify_fd >= 0 && pollfd[inotify_idx].revents != 0 && keyring) {
                         (void) flush_fd(inotify_fd);
 
                         r = ask_password_keyring(req, flags, ret);
@@ -924,16 +963,29 @@ int ask_password_agent(
         enum {
                 POLL_SOCKET,
                 POLL_SIGNAL,
-                POLL_INOTIFY, /* Must be last, because optional */
+                POLL_THREE,
+                POLL_FOUR,
                 _POLL_MAX
         };
 
         struct pollfd pollfd[_POLL_MAX] = {
                 [POLL_SOCKET]  = { .fd = socket_fd,  .events = POLLIN },
                 [POLL_SIGNAL]  = { .fd = signal_fd,  .events = POLLIN },
-                [POLL_INOTIFY] = { .fd = inotify_fd, .events = POLLIN },
         };
-        size_t n_pollfd = inotify_fd >= 0 ? _POLL_MAX : _POLL_MAX - 1;
+        size_t n_pollfd = POLL_SIGNAL + 1, inotify_idx = SIZE_MAX, hup_fd_idx = SIZE_MAX;
+
+        if (inotify_fd >= 0)
+                pollfd[inotify_idx = n_pollfd++] = (struct pollfd) {
+                        .fd = inotify_fd,
+                        .events = POLLIN,
+                };
+        if (req->hup_fd >= 0)
+                pollfd[hup_fd_idx = n_pollfd ++] = (struct pollfd) {
+                        .fd = req->hup_fd,
+                        .events = POLLHUP,
+                };
+
+        assert(n_pollfd <= _POLL_MAX);
 
         for (;;) {
                 CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct ucred))) control;
@@ -963,7 +1015,10 @@ int ask_password_agent(
                         goto finish;
                 }
 
-                if (inotify_fd >= 0 && pollfd[POLL_INOTIFY].revents != 0) {
+                if (req->hup_fd >= 0 && pollfd[hup_fd_idx].revents & POLLHUP)
+                        return -ECONNRESET;
+
+                if (inotify_fd >= 0 && pollfd[inotify_idx].revents != 0) {
                         (void) flush_fd(inotify_fd);
 
                         if (req && req->keyring) {
index fe453522fcad95109b835a37b2ec2b3459b2ec98..03c6d1abdbbabb821d0d7d8ea89c053fc09619ec 100644 (file)
@@ -28,6 +28,7 @@ typedef struct AskPasswordRequest {
         const char *credential;      /* $CREDENTIALS_DIRECTORY credential name */
         const char *flag_file;       /* Once this flag file disappears abort the query */
         int tty_fd;                  /* If querying on a TTY, the TTY to query on (or -EBADF) */
+        int hup_fd;                  /* An extra fd to watch for POLLHUP, in which case to abort the query */
         usec_t until;                /* CLOCK_MONOTONIC time until which to show the prompt (if zero: forever) */
 } AskPasswordRequest;
 
index 070908d5257bb5725cf53fd44797f75627403775..8d4c1791837d188fade8fdaf89fd2d34fc5c848a 100644 (file)
@@ -118,6 +118,7 @@ int acquire_fido2_key(
                         .keyring = "fido2-pin",
                         .credential = "cryptsetup.fido2-pin",
                         .until = until,
+                        .hup_fd = -EBADF,
                 };
 
                 pins = strv_free_erase(pins);
index 7a1275eb381f037ec108fa8ba9c3d594cdb6198d..c1cd67bacd72701b089577ce3ba4b416d984faa2 100644 (file)
@@ -41,6 +41,7 @@ static int get_pin(
                         .keyring = "tpm2-pin",
                         .credential = askpw_credential,
                         .until = until,
+                        .hup_fd = -EBADF,
                 };
 
                 pin = strv_free_erase(pin);
index 3feda770af9bce810a258759cbecea6cb0e442a2..86a549477c3f8e14ab1f5ca72612f51c3a047eb3 100644 (file)
@@ -3083,6 +3083,7 @@ int dissected_image_decrypt_interactively(
                         .keyring = "dissect",
                         .credential = "dissect.passphrase",
                         .until = USEC_INFINITY,
+                        .hup_fd = -EBADF,
                 };
 
                 r = ask_password_auto(&req, /* flags= */ 0, &z);
index 200068dce441bc8e68363f198b8eae8cc45c4743..101641e7fe4596b1cd2c777bec35ded4c5759b0f 100644 (file)
@@ -863,6 +863,7 @@ int fido2_generate_hmac_hash(
                                 .keyring = "fido2-pin",
                                 .credential = askpw_credential,
                                 .until = USEC_INFINITY,
+                                .hup_fd = -EBADF,
                         };
 
                         r = ask_password_auto(&req, /* flags= */ 0, &pin);
index 8d14b2f8f7e321b6894c50ed19e08c92c1f6edb1..a38a91279d7040a8b443f8d7b196fb16c9081317 100644 (file)
@@ -387,6 +387,7 @@ int pkcs11_token_login(
                                 .keyring = askpw_keyring,
                                 .credential = askpw_credential,
                                 .until = until,
+                                .hup_fd = -EBADF,
                         };
 
                         /* We never cache PINs, simply because it's fatal if we use wrong PINs, since usually there are only 3 tries */
index 38afe0c6efc1ce76bc298fee09a0e941f2653947..d79c4764896d41954bc7c3ac469a2f28939198f9 100644 (file)
@@ -13,6 +13,7 @@ TEST(ask_password) {
                 .message = "hello?",
                 .keyring = "da key",
                 .until = USEC_INFINITY,
+                .hup_fd = -EBADF,
         };
 
         r = ask_password_tty(&req, /* flags= */ ASK_PASSWORD_CONSOLE_COLOR, &ret);
index 31292d5acf5542ff82d853bac7c6bb9278df71f6..094810dcb39032763c7240a0afe2fd7719bdaaec 100644 (file)
@@ -152,6 +152,7 @@ static int agent_ask_password_tty(
                 .message = message,
                 .flag_file = flag_file,
                 .until = until,
+                .hup_fd = -EBADF,
         };
 
         r = ask_password_tty(&req, flags, ret);
@@ -260,6 +261,7 @@ static int process_one_password_file(const char *filename, FILE *f) {
                                         .message = message,
                                         .flag_file = filename,
                                         .until = not_after,
+                                        .hup_fd = -EBADF,
                                 };
 
                                 r = ask_password_plymouth(&req, flags, &passwords);