diff options
Diffstat (limited to 'src/tty-ask-password-agent/tty-ask-password-agent.c')
-rw-r--r-- | src/tty-ask-password-agent/tty-ask-password-agent.c | 153 |
1 files changed, 79 insertions, 74 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 82cbf95f1e..93cce186f0 100644 --- a/src/tty-ask-password-agent/tty-ask-password-agent.c +++ b/src/tty-ask-password-agent/tty-ask-password-agent.c @@ -19,32 +19,31 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include <stdbool.h> #include <errno.h> +#include <fcntl.h> +#include <getopt.h> +#include <poll.h> +#include <stdbool.h> +#include <stddef.h> #include <string.h> +#include <sys/inotify.h> +#include <sys/signalfd.h> #include <sys/socket.h> #include <sys/un.h> -#include <stddef.h> -#include <poll.h> -#include <sys/inotify.h> #include <unistd.h> -#include <getopt.h> -#include <sys/signalfd.h> -#include <fcntl.h> -#include "util.h" +#include "ask-password-api.h" +#include "conf-parser.h" +#include "def.h" #include "mkdir.h" #include "path-util.h" -#include "conf-parser.h" -#include "utmp-wtmp.h" +#include "process-util.h" +#include "signal-util.h" #include "socket-util.h" -#include "ask-password-api.h" #include "strv.h" -#include "build.h" -#include "def.h" -#include "process-util.h" #include "terminal-util.h" -#include "signal-util.h" +#include "util.h" +#include "utmp-wtmp.h" static enum { ACTION_LIST, @@ -59,9 +58,9 @@ static bool arg_console = false; static int ask_password_plymouth( const char *message, usec_t until, + AskPasswordFlags flags, const char *flag_file, - bool accept_cached, - char ***_passphrases) { + char ***ret) { _cleanup_close_ int fd = -1, notify = -1; union sockaddr_union sa = PLYMOUTH_SOCKET; @@ -76,7 +75,7 @@ static int ask_password_plymouth( POLL_INOTIFY }; - assert(_passphrases); + assert(ret); if (flag_file) { notify = inotify_init1(IN_CLOEXEC|IN_NONBLOCK); @@ -94,17 +93,15 @@ static int ask_password_plymouth( r = connect(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + 1 + strlen(sa.un.sun_path+1)); if (r < 0) - return log_error_errno(errno, "Failed to connect to Plymouth: %m"); + return -errno; - if (accept_cached) { + 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) + } else if (asprintf(&packet, "*\002%c%s%n", (int) (strlen(message) + 1), message, &n) < 0) packet = NULL; - if (!packet) - return log_oom(); + return -ENOMEM; r = loop_write(fd, packet, n + 1, true); if (r < 0) @@ -132,7 +129,7 @@ static int ask_password_plymouth( if (flag_file && access(flag_file, F_OK) < 0) return -errno; - j = poll(pollfd, notify > 0 ? 2 : 1, sleep_for); + j = poll(pollfd, notify >= 0 ? 2 : 1, sleep_for); if (j < 0) { if (errno == EINTR) continue; @@ -141,15 +138,20 @@ static int ask_password_plymouth( } else if (j == 0) return -ETIME; - if (notify > 0 && pollfd[POLL_INOTIFY].revents != 0) + if (notify >= 0 && pollfd[POLL_INOTIFY].revents != 0) flush_fd(notify); if (pollfd[POLL_SOCKET].revents == 0) continue; k = read(fd, buffer + p, sizeof(buffer) - p); - if (k <= 0) - return r = k < 0 ? -errno : -EIO; + if (k < 0) { + if (errno == EINTR || errno == EAGAIN) + continue; + + return -errno; + } else if (k == 0) + return -EIO; p += k; @@ -158,7 +160,7 @@ static int ask_password_plymouth( if (buffer[0] == 5) { - if (accept_cached) { + if (flags & ASK_PASSWORD_ACCEPT_CACHED) { /* Hmm, first try with cached * passwords failed, so let's retry * with a normal password request */ @@ -171,7 +173,7 @@ static int ask_password_plymouth( if (r < 0) return r; - accept_cached = false; + flags &= ~ASK_PASSWORD_ACCEPT_CACHED; p = 0; continue; } @@ -199,7 +201,7 @@ static int ask_password_plymouth( if (!l) return -ENOMEM; - *_passphrases = l; + *ret = l; break; } else @@ -257,7 +259,7 @@ static int parse_password(const char *filename, char **wall) { if (asprintf(&_wall, "%s%sPassword entry required for \'%s\' (PID %u).\r\n" "Please enter password with the systemd-tty-ask-password-agent tool!", - *wall ? *wall : "", + strempty(*wall), *wall ? "\r\n\r\n" : "", message, pid) < 0) @@ -284,7 +286,7 @@ static int parse_password(const char *filename, char **wall) { if (arg_plymouth) { _cleanup_strv_free_ char **passwords = NULL; - r = ask_password_plymouth(message, not_after, filename, accept_cached, &passwords); + r = ask_password_plymouth(message, not_after, accept_cached ? ASK_PASSWORD_ACCEPT_CACHED : 0, filename, &passwords); if (r >= 0) { char **p; @@ -306,19 +308,23 @@ static int parse_password(const char *filename, char **wall) { } } else { - int tty_fd = -1; _cleanup_free_ char *password = NULL; + int tty_fd = -1; if (arg_console) { tty_fd = acquire_terminal("/dev/console", false, false, false, USEC_INFINITY); if (tty_fd < 0) - return tty_fd; + return log_error_errno(tty_fd, "Failed to acquire /dev/console: %m"); + + r = reset_terminal_fd(tty_fd, true); + if (r < 0) + log_warning_errno(r, "Failed to reset terminal, ignoring: %m"); } - r = ask_password_tty(message, not_after, echo, filename, &password); + r = ask_password_tty(message, NULL, not_after, echo ? ASK_PASSWORD_ECHO : 0, filename, &password); if (arg_console) { - safe_close(tty_fd); + tty_fd = safe_close(tty_fd); release_terminal(); } @@ -348,12 +354,9 @@ static int parse_password(const char *filename, char **wall) { sa.un.sun_family = AF_UNIX; strncpy(sa.un.sun_path, socket_name, sizeof(sa.un.sun_path)); - r = sendto(socket_fd, packet, packet_length, MSG_NOSIGNAL, &sa.sa, - offsetof(struct sockaddr_un, sun_path) + strlen(socket_name)); - if (r < 0) { - log_error_errno(errno, "Failed to send: %m"); - return r; - } + r = sendto(socket_fd, packet, packet_length, MSG_NOSIGNAL, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(socket_name)); + if (r < 0) + return log_error_errno(errno, "Failed to send: %m"); } return 0; @@ -361,40 +364,45 @@ static int parse_password(const char *filename, char **wall) { static int wall_tty_block(void) { _cleanup_free_ char *p = NULL; - int fd, r; dev_t devnr; + int fd, r; r = get_ctty_devnr(0, &devnr); + if (r == -ENXIO) /* We have no controlling tty */ + return -ENOTTY; if (r < 0) - return r; + return log_error_errno(r, "Failed to get controlling TTY: %m"); if (asprintf(&p, "/run/systemd/ask-password-block/%u:%u", major(devnr), minor(devnr)) < 0) - return -ENOMEM; + return log_oom(); mkdir_parents_label(p, 0700); mkfifo(p, 0600); fd = open(p, O_RDONLY|O_CLOEXEC|O_NONBLOCK|O_NOCTTY); if (fd < 0) - return -errno; + return log_error_errno(errno, "Failed to open %s: %m", p); return fd; } static bool wall_tty_match(const char *path, void *userdata) { - int fd, r; - struct stat st; _cleanup_free_ char *p = NULL; + _cleanup_close_ int fd = -1; + struct stat st; if (!path_is_absolute(path)) path = strjoina("/dev/", path); - r = lstat(path, &st); - if (r < 0) + if (lstat(path, &st) < 0) { + log_debug_errno(errno, "Failed to stat %s: %m", path); return true; + } - if (!S_ISCHR(st.st_mode)) + if (!S_ISCHR(st.st_mode)) { + log_debug("%s is not a character device.", path); return true; + } /* We use named pipes to ensure that wall messages suggesting * password entry are not printed over password prompts @@ -404,16 +412,19 @@ static bool wall_tty_match(const char *path, void *userdata) { * advantage that the block will automatically go away if the * process dies. */ - if (asprintf(&p, "/run/systemd/ask-password-block/%u:%u", major(st.st_rdev), minor(st.st_rdev)) < 0) + if (asprintf(&p, "/run/systemd/ask-password-block/%u:%u", major(st.st_rdev), minor(st.st_rdev)) < 0) { + log_oom(); return true; + } fd = open(p, O_WRONLY|O_CLOEXEC|O_NONBLOCK|O_NOCTTY); - if (fd < 0) - return true; + if (fd < 0) { + log_debug_errno(errno, "Failed top open the wall pipe: %m"); + return 1; + } /* What, we managed to open the pipe? Then this tty is filtered. */ - safe_close(fd); - return false; + return 0; } static int show_passwords(void) { @@ -426,11 +437,10 @@ static int show_passwords(void) { if (errno == ENOENT) return 0; - log_error_errno(errno, "opendir(/run/systemd/ask-password): %m"); - return -errno; + return log_error_errno(errno, "Failed top open /run/systemd/ask-password: %m"); } - while ((de = readdir(d))) { + FOREACH_DIRENT_ALL(de, d, return log_error_errno(errno, "Failed to read directory: %m")) { _cleanup_free_ char *p = NULL, *wall = NULL; int q; @@ -455,7 +465,7 @@ static int show_passwords(void) { r = q; if (wall) - utmp_wall(wall, NULL, NULL, wall_tty_match, NULL); + (void) utmp_wall(wall, NULL, NULL, wall_tty_match, NULL); } return r; @@ -475,14 +485,14 @@ static int watch_passwords(void) { tty_block_fd = wall_tty_block(); - mkdir_p_label("/run/systemd/ask-password", 0755); + (void) mkdir_p_label("/run/systemd/ask-password", 0755); notify = inotify_init1(IN_CLOEXEC); if (notify < 0) - return -errno; + 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) - return -errno; + return log_error_errno(errno, "Failed to add /run/systemd/ask-password to directory watch: %m"); assert_se(sigemptyset(&mask) >= 0); assert_se(sigset_add_many(&mask, SIGINT, SIGTERM, -1) >= 0); @@ -490,7 +500,7 @@ static int watch_passwords(void) { signal_fd = signalfd(-1, &mask, SFD_NONBLOCK|SFD_CLOEXEC); if (signal_fd < 0) - return -errno; + return log_error_errno(errno, "Failed to allocate signal file descriptor: %m"); pollfd[FD_INOTIFY].fd = notify; pollfd[FD_INOTIFY].events = POLLIN; @@ -510,7 +520,7 @@ static int watch_passwords(void) { } if (pollfd[FD_INOTIFY].revents != 0) - flush_fd(notify); + (void) flush_fd(notify); if (pollfd[FD_SIGNAL].revents != 0) break; @@ -571,9 +581,7 @@ static int parse_argv(int argc, char *argv[]) { return 0; case ARG_VERSION: - puts(PACKAGE_STRING); - puts(SYSTEMD_FEATURES); - return 0; + return version(); case ARG_LIST: arg_action = ACTION_LIST; @@ -628,8 +636,8 @@ int main(int argc, char *argv[]) { goto finish; if (arg_console) { - setsid(); - release_terminal(); + (void) setsid(); + (void) release_terminal(); } if (IN_SET(arg_action, ACTION_WATCH, ACTION_WALL)) @@ -637,9 +645,6 @@ int main(int argc, char *argv[]) { else r = show_passwords(); - if (r < 0) - log_error_errno(r, "Error: %m"); - finish: return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } |