From 5461cdebfa5e385706592253ce6261f92ce531db Mon Sep 17 00:00:00 2001 From: Franck Bui Date: Tue, 17 Sep 2019 11:03:04 +0200 Subject: [PATCH 1/9] tty-ask-pwd-agent: rename watch_passwords() and show_passwords() Those names were a bit confusing both functions process password files the former relies one the later and waits for new files. Also show_passwords() was not only used to list password files/requests but also to query the user. No functional changes. --- .../tty-ask-password-agent.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) 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 3032f15898..0553abca64 100644 --- a/src/tty-ask-password-agent/tty-ask-password-agent.c +++ b/src/tty-ask-password-agent/tty-ask-password-agent.c @@ -318,7 +318,7 @@ static bool wall_tty_match(const char *path, void *userdata) { return 0; } -static int parse_password(const char *filename) { +static int process_one_password_file(const char *filename) { _cleanup_free_ char *socket_name = NULL, *message = NULL; bool accept_cached = false, echo = false; uint64_t not_after = 0; @@ -449,7 +449,7 @@ static int wall_tty_block(void) { return fd; } -static int show_passwords(void) { +static int process_password_files(void) { _cleanup_closedir_ DIR *d; struct dirent *de; int r = 0; @@ -482,7 +482,7 @@ static int show_passwords(void) { if (!p) return log_oom(); - q = parse_password(p); + q = process_one_password_file(p); if (q < 0 && r == 0) r = q; } @@ -490,7 +490,7 @@ static int show_passwords(void) { return r; } -static int watch_passwords(void) { +static int process_and_watch_password_files(void) { enum { FD_INOTIFY, FD_SIGNAL, @@ -531,9 +531,9 @@ static int watch_passwords(void) { pollfd[FD_SIGNAL].events = POLLIN; for (;;) { - r = show_passwords(); + r = process_password_files(); if (r < 0) - log_error_errno(r, "Failed to show password: %m"); + log_error_errno(r, "Failed to process password: %m"); if (poll(pollfd, _FD_MAX, -1) < 0) { if (errno == EINTR) @@ -857,9 +857,9 @@ static int run(int argc, char *argv[]) { } if (IN_SET(arg_action, ACTION_WATCH, ACTION_WALL)) - return watch_passwords(); + return process_and_watch_password_files(); else - return show_passwords(); + return process_password_files(); } DEFINE_MAIN_FUNCTION(run); From 27c3112dcbd1b5f171c36c32550d9c6331375b0b Mon Sep 17 00:00:00 2001 From: Franck Bui Date: Tue, 17 Sep 2019 11:16:52 +0200 Subject: [PATCH 2/9] fs-util: introduce inotify_add_watch_and_warn() helper The default message for ENOSPC is very misleading: it says that the disk is filled, but in fact the inotify watch limit is the problem. So let's introduce and use a wrapper that simply calls inotify_add_watch(2) and which fixes the error message up in case ENOSPC is returned. --- src/basic/fs-util.c | 15 +++++++ src/basic/fs-util.h | 1 + src/core/manager.c | 8 ++-- src/core/path.c | 39 +++++++++++-------- src/time-wait-sync/time-wait-sync.c | 4 +- .../tty-ask-password-agent.c | 11 ++---- 6 files changed, 49 insertions(+), 29 deletions(-) diff --git a/src/basic/fs-util.c b/src/basic/fs-util.c index b2ac648838..a92241ca02 100644 --- a/src/basic/fs-util.c +++ b/src/basic/fs-util.c @@ -660,6 +660,21 @@ int inotify_add_watch_fd(int fd, int what, uint32_t mask) { return r; } +int inotify_add_watch_and_warn(int fd, const char *pathname, uint32_t mask) { + if (inotify_add_watch(fd, pathname, mask) < 0) { + const char *reason; + + if (errno == ENOSPC) + reason = "inotify watch limit reached"; + else + reason = strerror_safe(errno); + + return log_error_errno(errno, "Failed to add a watch for %s: %s", pathname, reason); + } + + return 0; +} + static bool unsafe_transition(const struct stat *a, const struct stat *b) { /* Returns true if the transition from a to b is safe, i.e. that we never transition from unprivileged to * privileged files or directories. Why bother? So that unprivileged code can't symlink to privileged files diff --git a/src/basic/fs-util.h b/src/basic/fs-util.h index 1f0bdd95b3..fa0f0de9a3 100644 --- a/src/basic/fs-util.h +++ b/src/basic/fs-util.h @@ -72,6 +72,7 @@ union inotify_event_buffer { }; int inotify_add_watch_fd(int fd, int what, uint32_t mask); +int inotify_add_watch_and_warn(int fd, const char *pathname, uint32_t mask); enum { CHASE_PREFIX_ROOT = 1 << 0, /* The specified path will be prefixed by the specified root before beginning the iteration */ diff --git a/src/core/manager.c b/src/core/manager.c index 600718e4bf..5f3cb6ea62 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -295,10 +295,12 @@ static int manager_check_ask_password(Manager *m) { if (m->ask_password_inotify_fd < 0) return log_error_errno(errno, "Failed to create inotify object: %m"); - if (inotify_add_watch(m->ask_password_inotify_fd, "/run/systemd/ask-password", IN_CREATE|IN_DELETE|IN_MOVE) < 0) { - log_error_errno(errno, "Failed to watch \"/run/systemd/ask-password\": %m"); + r = inotify_add_watch_and_warn(m->ask_password_inotify_fd, + "/run/systemd/ask-password", + IN_CREATE|IN_DELETE|IN_MOVE); + if (r < 0) { manager_close_ask_password(m); - return -errno; + return r; } r = sd_event_add_io(m->event, &m->ask_password_event_source, diff --git a/src/core/path.c b/src/core/path.c index ac1289a658..aee94ce7f0 100644 --- a/src/core/path.c +++ b/src/core/path.c @@ -89,24 +89,29 @@ int path_spec_watch(PathSpec *s, sd_event_io_handler_t handler) { break; } - r = log_warning_errno(errno, "Failed to add watch on %s: %s", s->path, errno == ENOSPC ? "too many watches" : strerror_safe(r)); - if (cut) - *cut = tmp; - goto fail; - } else { - exists = true; - - /* Path exists, we don't need to watch parent too closely. */ - if (oldslash) { - char *cut2 = oldslash + (oldslash == s->path); - char tmp2 = *cut2; - *cut2 = '\0'; - - (void) inotify_add_watch(s->inotify_fd, s->path, IN_MOVE_SELF); - /* Error is ignored, the worst can happen is we get spurious events. */ - - *cut2 = tmp2; + /* This second call to inotify_add_watch() should fail like the previous + * one and is done for logging the error in a comprehensive way. */ + r = inotify_add_watch_and_warn(s->inotify_fd, s->path, flags); + if (r < 0) { + if (cut) + *cut = tmp; + goto fail; } + + /* Hmm, we succeeded in adding the watch this time... let's continue. */ + } + exists = true; + + /* Path exists, we don't need to watch parent too closely. */ + if (oldslash) { + char *cut2 = oldslash + (oldslash == s->path); + char tmp2 = *cut2; + *cut2 = '\0'; + + (void) inotify_add_watch(s->inotify_fd, s->path, IN_MOVE_SELF); + /* Error is ignored, the worst can happen is we get spurious events. */ + + *cut2 = tmp2; } if (cut) diff --git a/src/time-wait-sync/time-wait-sync.c b/src/time-wait-sync/time-wait-sync.c index f4d20af2d4..5b27df1f9e 100644 --- a/src/time-wait-sync/time-wait-sync.c +++ b/src/time-wait-sync/time-wait-sync.c @@ -225,9 +225,9 @@ static int run(int argc, char * argv[]) { if (r < 0) return log_error_errno(r, "Failed to create notify event source: %m"); - r = inotify_add_watch(state.inotify_fd, "/run/systemd/", IN_CREATE); + r = inotify_add_watch_and_warn(state.inotify_fd, "/run/systemd/", IN_CREATE); if (r < 0) - return log_error_errno(errno, "Failed to watch /run/systemd/: %m"); + return r; state.run_systemd_wd = r; 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 0553abca64..f57f0ec261 100644 --- a/src/tty-ask-password-agent/tty-ask-password-agent.c +++ b/src/tty-ask-password-agent/tty-ask-password-agent.c @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include @@ -29,6 +28,7 @@ #include "exit-status.h" #include "fd-util.h" #include "fileio.h" +#include "fs-util.h" #include "hashmap.h" #include "io-util.h" #include "macro.h" @@ -510,12 +510,9 @@ static int process_and_watch_password_files(void) { if (notify < 0) return log_error_errno(errno, "Failed to allocate directory watch: %m"); - if (inotify_add_watch(notify, "/run/systemd/ask-password", IN_CLOSE_WRITE|IN_MOVED_TO) < 0) { - if (errno == ENOSPC) - return log_error_errno(errno, "Failed to add /run/systemd/ask-password to directory watch: inotify watch limit reached"); - else - return log_error_errno(errno, "Failed to add /run/systemd/ask-password to directory watch: %m"); - } + r = inotify_add_watch_and_warn(notify, "/run/systemd/ask-password", IN_CLOSE_WRITE|IN_MOVED_TO); + if (r < 0) + return r; assert_se(sigemptyset(&mask) >= 0); assert_se(sigset_add_many(&mask, SIGINT, SIGTERM, -1) >= 0); From 1503bcb12ec9ae775a0b3435c9f2dfdd5204e09e Mon Sep 17 00:00:00 2001 From: Franck Bui Date: Tue, 17 Sep 2019 12:30:31 +0200 Subject: [PATCH 3/9] tty-ask-pwd-agent: minor simplification by using FOREACH_DIRENT instead of FOREACH_DIRENT_ALL --- src/tty-ask-password-agent/tty-ask-password-agent.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) 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 f57f0ec261..72b04e6f0e 100644 --- a/src/tty-ask-password-agent/tty-ask-password-agent.c +++ b/src/tty-ask-password-agent/tty-ask-password-agent.c @@ -462,7 +462,7 @@ static int process_password_files(void) { return log_error_errno(errno, "Failed to open /run/systemd/ask-password: %m"); } - FOREACH_DIRENT_ALL(de, d, return log_error_errno(errno, "Failed to read directory: %m")) { + FOREACH_DIRENT(de, d, return log_error_errno(errno, "Failed to read directory: %m")) { _cleanup_free_ char *p = NULL; int q; @@ -472,9 +472,6 @@ static int process_password_files(void) { if (de->d_type != DT_REG) continue; - if (hidden_or_backup_file(de->d_name)) - continue; - if (!startswith(de->d_name, "ask.")) continue; From d325f2443eceb423a02b26852065a25ed21a992c Mon Sep 17 00:00:00 2001 From: Franck Bui Date: Thu, 19 Sep 2019 15:18:18 +0200 Subject: [PATCH 4/9] tty-ask-pwd-agent: give the possiblity to skip a password prompt If multiple passwords are waiting the agent will prompt for each of them. Give the possiblity to the user to skip some of them by pressing 'C-d'. --- src/shared/ask-password-api.c | 8 ++++++++ .../tty-ask-password-agent.c | 20 +++++++++++++++---- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/shared/ask-password-api.c b/src/shared/ask-password-api.c index c41fa2dea6..46f06fe99b 100644 --- a/src/shared/ask-password-api.c +++ b/src/shared/ask-password-api.c @@ -371,6 +371,13 @@ int ask_password_tty( if (n == 0 || c == '\n' || c == 0) break; + if (c == 4) { /* C-d also known as EOT */ + if (ttyfd >= 0) + (void) loop_write(ttyfd, "(skipped)", 9, false); + + goto skipped; + } + if (c == 21) { /* C-u */ if (!(flags & ASK_PASSWORD_SILENT)) @@ -467,6 +474,7 @@ int ask_password_tty( if (r < 0) goto finish; +skipped: if (keyname) (void) add_to_keyring_and_log(keyname, flags, l); 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 72b04e6f0e..504ba9162d 100644 --- a/src/tty-ask-password-agent/tty-ask-password-agent.c +++ b/src/tty-ask-password-agent/tty-ask-password-agent.c @@ -417,6 +417,9 @@ static int process_one_password_file(const char *filename) { if (r < 0) return log_error_errno(r, "Failed to query password: %m"); + if (strv_isempty(passwords)) + return -ECANCELED; + r = send_passwords(socket_name, passwords); if (r < 0) return log_error_errno(r, "Failed to send: %m"); @@ -525,11 +528,20 @@ static int process_and_watch_password_files(void) { pollfd[FD_SIGNAL].events = POLLIN; for (;;) { - r = process_password_files(); - if (r < 0) - log_error_errno(r, "Failed to process password: %m"); + int timeout = -1; - if (poll(pollfd, _FD_MAX, -1) < 0) { + r = process_password_files(); + if (r < 0) { + if (r == -ECANCELED) + /* Disable poll() timeout since at least one password has + * been skipped and therefore one file remains and is + * unlikely to trigger any events. */ + timeout = 0; + else + log_error_errno(r, "Failed to process password: %m"); + } + + if (poll(pollfd, _FD_MAX, timeout) < 0) { if (errno == EINTR) continue; From 998c6da8ca37326dfc38e16fdf0d30b1c6c20d97 Mon Sep 17 00:00:00 2001 From: Franck Bui Date: Thu, 19 Sep 2019 15:24:15 +0200 Subject: [PATCH 5/9] tty-ask-pwd-agent: treat SIGINT as a request to exit immediately Unlike SIGTERM, SIGINT is now treated as a request to exit as soon as possible. IOW, if SIGINT is received, the agent wont process all remaining passwords before exiting. This allows a more comprehensive behavior when C-c is pressed and when the agent is spawned by systemctl. Before that patch, pressing C-c killed systemctl but left the agent waiting for a password since SIGINT was blocked. The result was pretty clumsy. --- src/tty-ask-password-agent/tty-ask-password-agent.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 504ba9162d..81eca2ec41 100644 --- a/src/tty-ask-password-agent/tty-ask-password-agent.c +++ b/src/tty-ask-password-agent/tty-ask-password-agent.c @@ -515,7 +515,7 @@ static int process_and_watch_password_files(void) { return r; assert_se(sigemptyset(&mask) >= 0); - assert_se(sigset_add_many(&mask, SIGINT, SIGTERM, -1) >= 0); + assert_se(sigset_add_many(&mask, SIGTERM, -1) >= 0); assert_se(sigprocmask(SIG_SETMASK, &mask, NULL) >= 0); signal_fd = signalfd(-1, &mask, SFD_NONBLOCK|SFD_CLOEXEC); From 1322757061e1e41cabf7098c4dc99b83520612e8 Mon Sep 17 00:00:00 2001 From: Franck Bui Date: Thu, 19 Sep 2019 16:38:16 +0200 Subject: [PATCH 6/9] tty-ask-pwd-agent: share the same init code for --query and --watch Previously we would have skipped the init code which consists in setting the signal handling up and the wall tty block thingie. --- .../tty-ask-password-agent.c | 47 ++++++++++--------- 1 file changed, 25 insertions(+), 22 deletions(-) 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 81eca2ec41..8bea524952 100644 --- a/src/tty-ask-password-agent/tty-ask-password-agent.c +++ b/src/tty-ask-password-agent/tty-ask-password-agent.c @@ -490,10 +490,10 @@ static int process_password_files(void) { return r; } -static int process_and_watch_password_files(void) { +static int process_and_watch_password_files(bool watch) { enum { - FD_INOTIFY, FD_SIGNAL, + FD_INOTIFY, _FD_MAX }; @@ -506,26 +506,29 @@ static int process_and_watch_password_files(void) { (void) mkdir_p_label("/run/systemd/ask-password", 0755); - notify = inotify_init1(IN_CLOEXEC); - if (notify < 0) - return log_error_errno(errno, "Failed to allocate directory watch: %m"); - - r = inotify_add_watch_and_warn(notify, "/run/systemd/ask-password", IN_CLOSE_WRITE|IN_MOVED_TO); - if (r < 0) - return r; - assert_se(sigemptyset(&mask) >= 0); assert_se(sigset_add_many(&mask, SIGTERM, -1) >= 0); assert_se(sigprocmask(SIG_SETMASK, &mask, NULL) >= 0); - signal_fd = signalfd(-1, &mask, SFD_NONBLOCK|SFD_CLOEXEC); - if (signal_fd < 0) - return log_error_errno(errno, "Failed to allocate signal file descriptor: %m"); + if (watch) { + signal_fd = signalfd(-1, &mask, SFD_NONBLOCK|SFD_CLOEXEC); + if (signal_fd < 0) + return log_error_errno(errno, "Failed to allocate signal file descriptor: %m"); - pollfd[FD_INOTIFY].fd = notify; - pollfd[FD_INOTIFY].events = POLLIN; - pollfd[FD_SIGNAL].fd = signal_fd; - pollfd[FD_SIGNAL].events = POLLIN; + pollfd[FD_SIGNAL].fd = signal_fd; + pollfd[FD_SIGNAL].events = POLLIN; + + notify = inotify_init1(IN_CLOEXEC); + if (notify < 0) + return log_error_errno(errno, "Failed to allocate directory watch: %m"); + + r = inotify_add_watch_and_warn(notify, "/run/systemd/ask-password", IN_CLOSE_WRITE|IN_MOVED_TO); + if (r < 0) + return r; + + pollfd[FD_INOTIFY].fd = notify; + pollfd[FD_INOTIFY].events = POLLIN; + } for (;;) { int timeout = -1; @@ -541,7 +544,10 @@ static int process_and_watch_password_files(void) { log_error_errno(r, "Failed to process password: %m"); } - if (poll(pollfd, _FD_MAX, timeout) < 0) { + if (!watch) + break; + + if (poll(pollfd, watch ? _FD_MAX : _FD_MAX-1, timeout) < 0) { if (errno == EINTR) continue; @@ -862,10 +868,7 @@ static int run(int argc, char *argv[]) { (void) release_terminal(); } - if (IN_SET(arg_action, ACTION_WATCH, ACTION_WALL)) - return process_and_watch_password_files(); - else - return process_password_files(); + return process_and_watch_password_files(arg_action != ACTION_QUERY); } DEFINE_MAIN_FUNCTION(run); From 825721eb8d4814d7491876f7a4f1ba1173496a0e Mon Sep 17 00:00:00 2001 From: Franck Bui Date: Thu, 19 Sep 2019 19:01:57 +0200 Subject: [PATCH 7/9] tty-ask-pwd-agent: add a FIXME --- src/tty-ask-password-agent/tty-ask-password-agent.c | 3 +++ 1 file changed, 3 insertions(+) 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 8bea524952..b3b7403db2 100644 --- a/src/tty-ask-password-agent/tty-ask-password-agent.c +++ b/src/tty-ask-password-agent/tty-ask-password-agent.c @@ -541,6 +541,9 @@ static int process_and_watch_password_files(bool watch) { * unlikely to trigger any events. */ timeout = 0; else + /* FIXME: we should do something here since otherwise the service + * requesting the password won't notice the error and will wait + * indefinitely. */ log_error_errno(r, "Failed to process password: %m"); } From 87c4444ac9934fe59e04adc69d962ec5aa58a7dd Mon Sep 17 00:00:00 2001 From: Franck Bui Date: Fri, 20 Sep 2019 15:07:31 +0200 Subject: [PATCH 8/9] tty-ask-pwd-agent: small cleanup in process_one_password_file() Split the part dealing which asks for password on tty in a dedicated function making process_one_password_file() hopefully easier to read. No functional changes. --- .../tty-ask-password-agent.c | 108 +++++++++++------- 1 file changed, 64 insertions(+), 44 deletions(-) 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 b3b7403db2..4e67448a37 100644 --- a/src/tty-ask-password-agent/tty-ask-password-agent.c +++ b/src/tty-ask-password-agent/tty-ask-password-agent.c @@ -318,6 +318,39 @@ static bool wall_tty_match(const char *path, void *userdata) { return 0; } +static int agent_ask_password_tty( + const char *message, + usec_t until, + AskPasswordFlags flags, + const char *flag_file, + char ***ret) { + + int tty_fd = -1; + int r; + + if (arg_console) { + const char *con = arg_device ?: "/dev/console"; + + tty_fd = acquire_terminal(con, ACQUIRE_TERMINAL_WAIT, USEC_INFINITY); + if (tty_fd < 0) + return log_error_errno(tty_fd, "Failed to acquire %s: %m", con); + + r = reset_terminal_fd(tty_fd, true); + if (r < 0) + log_warning_errno(r, "Failed to reset terminal, ignoring: %m"); + + } + + r = ask_password_tty(tty_fd, message, NULL, until, flags, flag_file, ret); + + if (arg_console) { + tty_fd = safe_close(tty_fd); + release_terminal(); + } + + return 0; +} + static int process_one_password_file(const char *filename) { _cleanup_free_ char *socket_name = NULL, *message = NULL; bool accept_cached = false, echo = false; @@ -355,25 +388,28 @@ static int process_one_password_file(const char *filename) { if (pid > 0 && !pid_is_alive(pid)) return 0; - if (arg_action == ACTION_LIST) + switch (arg_action) { + case ACTION_LIST: printf("'%s' (PID %u)\n", message, pid); + return 0; - else if (arg_action == ACTION_WALL) { - _cleanup_free_ char *wall = NULL; + case ACTION_WALL: { + _cleanup_free_ char *wall = NULL; - if (asprintf(&wall, - "Password entry required for \'%s\' (PID %u).\r\n" - "Please enter password with the systemd-tty-ask-password-agent tool.", - message, - pid) < 0) - return log_oom(); + if (asprintf(&wall, + "Password entry required for \'%s\' (PID %u).\r\n" + "Please enter password with the systemd-tty-ask-password-agent tool.", + message, + pid) < 0) + return log_oom(); - (void) utmp_wall(wall, NULL, NULL, wall_tty_match, NULL); - - } else { + (void) utmp_wall(wall, NULL, NULL, wall_tty_match, NULL); + return 0; + } + case ACTION_QUERY: + case ACTION_WATCH: { _cleanup_strv_free_erase_ char **passwords = NULL; - - assert(IN_SET(arg_action, ACTION_QUERY, ACTION_WATCH)); + AskPasswordFlags flags = 0; if (access(socket_name, W_OK) < 0) { if (arg_action == ACTION_QUERY) @@ -382,40 +418,22 @@ static int process_one_password_file(const char *filename) { return 0; } + SET_FLAG(flags, ASK_PASSWORD_ACCEPT_CACHED, accept_cached); + SET_FLAG(flags, ASK_PASSWORD_CONSOLE_COLOR, arg_console); + SET_FLAG(flags, ASK_PASSWORD_ECHO, echo); + if (arg_plymouth) - r = ask_password_plymouth(message, not_after, accept_cached ? ASK_PASSWORD_ACCEPT_CACHED : 0, filename, &passwords); - else { - int tty_fd = -1; + r = ask_password_plymouth(message, not_after, flags, filename, &passwords); + else + r = agent_ask_password_tty(message, not_after, flags, filename, &passwords); - if (arg_console) { - const char *con = arg_device ?: "/dev/console"; + if (r < 0) { + /* If the query went away, that's OK */ + if (IN_SET(r, -ETIME, -ENOENT)) + return 0; - tty_fd = acquire_terminal(con, ACQUIRE_TERMINAL_WAIT, USEC_INFINITY); - if (tty_fd < 0) - return log_error_errno(tty_fd, "Failed to acquire %s: %m", con); - - r = reset_terminal_fd(tty_fd, true); - if (r < 0) - log_warning_errno(r, "Failed to reset terminal, ignoring: %m"); - } - - r = ask_password_tty(tty_fd, message, NULL, not_after, - (echo ? ASK_PASSWORD_ECHO : 0) | - (arg_console ? ASK_PASSWORD_CONSOLE_COLOR : 0), - filename, &passwords); - - if (arg_console) { - tty_fd = safe_close(tty_fd); - release_terminal(); - } - } - - /* If the query went away, that's OK */ - if (IN_SET(r, -ETIME, -ENOENT)) - return 0; - - if (r < 0) return log_error_errno(r, "Failed to query password: %m"); + } if (strv_isempty(passwords)) return -ECANCELED; @@ -423,6 +441,8 @@ static int process_one_password_file(const char *filename) { r = send_passwords(socket_name, passwords); if (r < 0) return log_error_errno(r, "Failed to send: %m"); + break; + } } return 0; From 6b2faba7644889a94777f2743395b4eda148aadc Mon Sep 17 00:00:00 2001 From: Franck Bui Date: Fri, 20 Sep 2019 15:13:48 +0200 Subject: [PATCH 9/9] tty-ask-pwd-agent: move ask_password_plymouth() in ask-password-api.c --- src/shared/ask-password-api.c | 181 ++++++++++++++++++ src/shared/ask-password-api.h | 1 + .../tty-ask-password-agent.c | 181 ------------------ 3 files changed, 182 insertions(+), 181 deletions(-) diff --git a/src/shared/ask-password-api.c b/src/shared/ask-password-api.c index 46f06fe99b..a08a53d1b7 100644 --- a/src/shared/ask-password-api.c +++ b/src/shared/ask-password-api.c @@ -34,6 +34,7 @@ #include "memory-util.h" #include "missing.h" #include "mkdir.h" +#include "plymouth-util.h" #include "process-util.h" #include "random-util.h" #include "signal-util.h" @@ -211,6 +212,186 @@ static int backspace_string(int ttyfd, const char *str) { return backspace_chars(ttyfd, m); } +int ask_password_plymouth( + const char *message, + usec_t until, + AskPasswordFlags flags, + const char *flag_file, + char ***ret) { + + static const union sockaddr_union sa = PLYMOUTH_SOCKET; + _cleanup_close_ int fd = -1, notify = -1; + _cleanup_free_ char *packet = NULL; + ssize_t k; + int r, n; + struct pollfd pollfd[2] = {}; + char buffer[LINE_MAX]; + size_t p = 0; + enum { + POLL_SOCKET, + POLL_INOTIFY + }; + + assert(ret); + + if (flag_file) { + notify = inotify_init1(IN_CLOEXEC|IN_NONBLOCK); + if (notify < 0) + return -errno; + + r = inotify_add_watch(notify, flag_file, IN_ATTRIB); /* for the link count */ + if (r < 0) + return -errno; + } + + fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); + if (fd < 0) + return -errno; + + r = connect(fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)); + if (r < 0) + return -errno; + + if (flags & ASK_PASSWORD_ACCEPT_CACHED) { + packet = strdup("c"); + n = 1; + } else if (asprintf(&packet, "*\002%c%s%n", (int) (strlen(message) + 1), message, &n) < 0) + packet = NULL; + if (!packet) + return -ENOMEM; + + r = loop_write(fd, packet, n + 1, true); + if (r < 0) + return r; + + pollfd[POLL_SOCKET].fd = fd; + pollfd[POLL_SOCKET].events = POLLIN; + pollfd[POLL_INOTIFY].fd = notify; + pollfd[POLL_INOTIFY].events = POLLIN; + + for (;;) { + int sleep_for = -1, j; + + if (until > 0) { + usec_t y; + + y = now(CLOCK_MONOTONIC); + + if (y > until) { + r = -ETIME; + goto finish; + } + + sleep_for = (int) ((until - y) / USEC_PER_MSEC); + } + + if (flag_file && access(flag_file, F_OK) < 0) { + r = -errno; + goto finish; + } + + j = poll(pollfd, notify >= 0 ? 2 : 1, sleep_for); + if (j < 0) { + if (errno == EINTR) + continue; + + r = -errno; + goto finish; + } else if (j == 0) { + r = -ETIME; + goto finish; + } + + if (notify >= 0 && pollfd[POLL_INOTIFY].revents != 0) + (void) flush_fd(notify); + + if (pollfd[POLL_SOCKET].revents == 0) + continue; + + k = read(fd, buffer + p, sizeof(buffer) - p); + if (k < 0) { + if (IN_SET(errno, EINTR, EAGAIN)) + continue; + + r = -errno; + goto finish; + } else if (k == 0) { + r = -EIO; + goto finish; + } + + p += k; + + if (p < 1) + continue; + + if (buffer[0] == 5) { + + if (flags & ASK_PASSWORD_ACCEPT_CACHED) { + /* Hmm, first try with cached + * passwords failed, so let's retry + * with a normal password request */ + packet = mfree(packet); + + if (asprintf(&packet, "*\002%c%s%n", (int) (strlen(message) + 1), message, &n) < 0) { + r = -ENOMEM; + goto finish; + } + + r = loop_write(fd, packet, n+1, true); + if (r < 0) + goto finish; + + flags &= ~ASK_PASSWORD_ACCEPT_CACHED; + p = 0; + continue; + } + + /* No password, because UI not shown */ + r = -ENOENT; + goto finish; + + } else if (IN_SET(buffer[0], 2, 9)) { + uint32_t size; + char **l; + + /* One or more answers */ + if (p < 5) + continue; + + memcpy(&size, buffer+1, sizeof(size)); + size = le32toh(size); + if (size + 5 > sizeof(buffer)) { + r = -EIO; + goto finish; + } + + if (p-5 < size) + continue; + + l = strv_parse_nulstr(buffer + 5, size); + if (!l) { + r = -ENOMEM; + goto finish; + } + + *ret = l; + break; + + } else { + /* Unknown packet */ + r = -EIO; + goto finish; + } + } + + r = 0; + +finish: + explicit_bzero_safe(buffer, sizeof(buffer)); + return r; +} + int ask_password_tty( int ttyfd, const char *message, diff --git a/src/shared/ask-password-api.h b/src/shared/ask-password-api.h index 15762b9cde..528e3d0197 100644 --- a/src/shared/ask-password-api.h +++ b/src/shared/ask-password-api.h @@ -16,5 +16,6 @@ typedef enum AskPasswordFlags { } AskPasswordFlags; int ask_password_tty(int tty_fd, const char *message, const char *keyname, 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 *keyname, usec_t until, AskPasswordFlags flag, char ***ret); int ask_password_auto(const char *message, const char *icon, const char *id, const char *keyname, usec_t until, AskPasswordFlags flag, char ***ret); 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 4e67448a37..2e57a628b2 100644 --- a/src/tty-ask-password-agent/tty-ask-password-agent.c +++ b/src/tty-ask-password-agent/tty-ask-password-agent.c @@ -36,7 +36,6 @@ #include "memory-util.h" #include "mkdir.h" #include "path-util.h" -#include "plymouth-util.h" #include "pretty-print.h" #include "process-util.h" #include "set.h" @@ -58,186 +57,6 @@ static bool arg_plymouth = false; static bool arg_console = false; static const char *arg_device = NULL; -static int ask_password_plymouth( - const char *message, - usec_t until, - AskPasswordFlags flags, - const char *flag_file, - char ***ret) { - - static const union sockaddr_union sa = PLYMOUTH_SOCKET; - _cleanup_close_ int fd = -1, notify = -1; - _cleanup_free_ char *packet = NULL; - ssize_t k; - int r, n; - struct pollfd pollfd[2] = {}; - char buffer[LINE_MAX]; - size_t p = 0; - enum { - POLL_SOCKET, - POLL_INOTIFY - }; - - assert(ret); - - if (flag_file) { - notify = inotify_init1(IN_CLOEXEC|IN_NONBLOCK); - if (notify < 0) - return -errno; - - r = inotify_add_watch(notify, flag_file, IN_ATTRIB); /* for the link count */ - if (r < 0) - return -errno; - } - - fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); - if (fd < 0) - return -errno; - - r = connect(fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)); - if (r < 0) - return -errno; - - if (flags & ASK_PASSWORD_ACCEPT_CACHED) { - packet = strdup("c"); - n = 1; - } else if (asprintf(&packet, "*\002%c%s%n", (int) (strlen(message) + 1), message, &n) < 0) - packet = NULL; - if (!packet) - return -ENOMEM; - - r = loop_write(fd, packet, n + 1, true); - if (r < 0) - return r; - - pollfd[POLL_SOCKET].fd = fd; - pollfd[POLL_SOCKET].events = POLLIN; - pollfd[POLL_INOTIFY].fd = notify; - pollfd[POLL_INOTIFY].events = POLLIN; - - for (;;) { - int sleep_for = -1, j; - - if (until > 0) { - usec_t y; - - y = now(CLOCK_MONOTONIC); - - if (y > until) { - r = -ETIME; - goto finish; - } - - sleep_for = (int) ((until - y) / USEC_PER_MSEC); - } - - if (flag_file && access(flag_file, F_OK) < 0) { - r = -errno; - goto finish; - } - - j = poll(pollfd, notify >= 0 ? 2 : 1, sleep_for); - if (j < 0) { - if (errno == EINTR) - continue; - - r = -errno; - goto finish; - } else if (j == 0) { - r = -ETIME; - goto finish; - } - - if (notify >= 0 && pollfd[POLL_INOTIFY].revents != 0) - (void) flush_fd(notify); - - if (pollfd[POLL_SOCKET].revents == 0) - continue; - - k = read(fd, buffer + p, sizeof(buffer) - p); - if (k < 0) { - if (IN_SET(errno, EINTR, EAGAIN)) - continue; - - r = -errno; - goto finish; - } else if (k == 0) { - r = -EIO; - goto finish; - } - - p += k; - - if (p < 1) - continue; - - if (buffer[0] == 5) { - - if (flags & ASK_PASSWORD_ACCEPT_CACHED) { - /* Hmm, first try with cached - * passwords failed, so let's retry - * with a normal password request */ - packet = mfree(packet); - - if (asprintf(&packet, "*\002%c%s%n", (int) (strlen(message) + 1), message, &n) < 0) { - r = -ENOMEM; - goto finish; - } - - r = loop_write(fd, packet, n+1, true); - if (r < 0) - goto finish; - - flags &= ~ASK_PASSWORD_ACCEPT_CACHED; - p = 0; - continue; - } - - /* No password, because UI not shown */ - r = -ENOENT; - goto finish; - - } else if (IN_SET(buffer[0], 2, 9)) { - uint32_t size; - char **l; - - /* One or more answers */ - if (p < 5) - continue; - - memcpy(&size, buffer+1, sizeof(size)); - size = le32toh(size); - if (size + 5 > sizeof(buffer)) { - r = -EIO; - goto finish; - } - - if (p-5 < size) - continue; - - l = strv_parse_nulstr(buffer + 5, size); - if (!l) { - r = -ENOMEM; - goto finish; - } - - *ret = l; - break; - - } else { - /* Unknown packet */ - r = -EIO; - goto finish; - } - } - - r = 0; - -finish: - explicit_bzero_safe(buffer, sizeof(buffer)); - return r; -} - static int send_passwords(const char *socket_name, char **passwords) { _cleanup_(erase_and_freep) char *packet = NULL; _cleanup_close_ int socket_fd = -1;