1
0
mirror of https://github.com/systemd/systemd.git synced 2025-01-03 05:18:09 +03:00

ask-password-api: add new "hup_fd" field to AskPasswordReq

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.
This commit is contained in:
Lennart Poettering 2024-11-07 11:38:23 +01:00
parent 4770eb1016
commit 921054a53e
21 changed files with 96 additions and 14 deletions

View 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);

View 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);

View 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 (;;) {

View 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);

View 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);

View 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);

View 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(

View 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);

View 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);

View File

@ -4555,6 +4555,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(

View 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);

View 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);

View 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) {

View File

@ -29,6 +29,7 @@ typedef struct AskPasswordRequest {
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) */
usec_t until; /* CLOCK_MONOTONIC time until which to show the prompt */
int hup_fd; /* An extra fd to watch for POLLHUP, in which case to abort the query */
} AskPasswordRequest;
int ask_password_tty(const AskPasswordRequest *req, AskPasswordFlags flags, char ***ret);

View 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);

View 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);

View 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);

View 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);

View 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 */

View 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);

View 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);