X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Ftty-ask-password-agent.c;h=c3c5f7a8b6bce9c3443226de95972b699ca060dd;hp=8a6e3d331ede5025e01040917f3c3b8f14ddbf8c;hb=9a60da2834074d970ca063c210fe9d2f05c70532;hpb=53d3afa8ca2811093c482b0e14addd1aaa92fb67 diff --git a/src/tty-ask-password-agent.c b/src/tty-ask-password-agent.c index 8a6e3d331..c3c5f7a8b 100644 --- a/src/tty-ask-password-agent.c +++ b/src/tty-ask-password-agent.c @@ -30,6 +30,7 @@ #include #include #include +#include #include "util.h" #include "conf-parser.h" @@ -45,6 +46,7 @@ static enum { } arg_action = ACTION_QUERY; static bool arg_plymouth = false; +static bool arg_console = false; static int ask_password_plymouth(const char *message, usec_t until, const char *flag_file, char **_passphrase) { int fd = -1, notify = -1; @@ -79,9 +81,9 @@ static int ask_password_plymouth(const char *message, usec_t until, const char * zero(sa); sa.sa.sa_family = AF_UNIX; - strncpy(sa.un.sun_path+1, "/ply-boot-protocol", sizeof(sa.un.sun_path)-1); - - if (connect(fd, &sa.sa, sizeof(sa.un)) < 0) { + strncpy(sa.un.sun_path+1, "/org/freedesktop/plymouthd", sizeof(sa.un.sun_path)-1); + if (connect(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + 1 + strlen(sa.un.sun_path+1)) < 0) { + log_error("FIALED TO CONNECT: %m"); r = -errno; goto finish; } @@ -231,7 +233,7 @@ static int parse_password(const char *filename, char **wall) { return -errno; } - if ((r = config_parse(filename, f, NULL, items, false, NULL)) < 0) { + if ((r = config_parse(filename, f, NULL, items, true, NULL)) < 0) { log_error("Failed to parse password file %s: %s", filename, strerror(-r)); goto finish; } @@ -255,7 +257,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-password-agent tool!", + "Please enter password with the systemd-tty-ask-password-agent tool!", *wall ? *wall : "", *wall ? "\r\n\r\n" : "", message, @@ -288,9 +290,23 @@ static int parse_password(const char *filename, char **wall) { if (arg_plymouth) r = ask_password_plymouth(message, not_after, filename, &password); - else + else { + int tty_fd = -1; + + if (arg_console) + if ((tty_fd = acquire_terminal("/dev/console", false, false, false)) < 0) { + r = tty_fd; + goto finish; + } + r = ask_password_tty(message, not_after, filename, &password); + if (arg_console) { + close_nointr_nofail(tty_fd); + release_terminal(); + } + } + if (r < 0) { log_error("Failed to query password: %s", strerror(-r)); goto finish; @@ -335,6 +351,55 @@ finish: return r; } +static int wall_tty_block(void) { + char *p; + const char *t; + int fd; + + if (!(t = ttyname(STDIN_FILENO))) + return -errno; + + if (asprintf(&p, "/dev/.systemd/ask-password-block/%s", file_name_from_path(t)) < 0) + return -ENOMEM; + + mkdir_parents(p, 0700); + mkfifo(p, 0600); + + fd = open(p, O_RDONLY|O_CLOEXEC|O_NONBLOCK|O_NOCTTY); + free(p); + + if (fd < 0) + return -errno; + + return fd; +} + +static bool wall_tty_match(const char *path) { + int fd; + char *p; + + /* We use named pipes to ensure that wall messages suggesting + * password entry are not printed over password prompts + * already shown. We use the fact here that opening a pipe in + * non-blocking mode for write-only will succeed only if + * there's some writer behind it. Using pipes has the + * advantage that the block will automatically go away if the + * process dies. */ + + if (asprintf(&p, "/dev/.systemd/ask-password-block/%s", file_name_from_path(path)) < 0) + return true; + + fd = open(p, O_WRONLY|O_CLOEXEC|O_NONBLOCK|O_NOCTTY); + free(p); + + if (fd < 0) + return true; + + /* What, we managed to open the pipe? Then this tty is filtered. */ + close_nointr_nofail(fd); + return false; +} + static int show_passwords(void) { DIR *d; struct dirent *de; @@ -375,7 +440,7 @@ static int show_passwords(void) { free(p); if (wall) { - utmp_wall(wall); + utmp_wall(wall, wall_tty_match); free(wall); } } @@ -394,11 +459,13 @@ static int watch_passwords(void) { _FD_MAX }; - int notify = -1, signal_fd = -1; + int notify = -1, signal_fd = -1, tty_block_fd = -1; struct pollfd pollfd[_FD_MAX]; sigset_t mask; int r; + tty_block_fd = wall_tty_block(); + mkdir_p("/dev/.systemd/ask-password", 0755); if ((notify = inotify_init1(IN_CLOEXEC)) < 0) { @@ -429,7 +496,7 @@ static int watch_passwords(void) { for (;;) { if ((r = show_passwords()) < 0) - break; + log_error("Failed to show password: %s", strerror(-r)); if (poll(pollfd, _FD_MAX, -1) < 0) { @@ -456,6 +523,9 @@ finish: if (signal_fd >= 0) close_nointr_nofail(signal_fd); + if (tty_block_fd >= 0) + close_nointr_nofail(tty_block_fd); + return r; } @@ -468,7 +538,8 @@ static int help(void) { " --query Process pending password requests\n" " --watch Continously process password requests\n" " --wall Continously forward password requests to wall\n" - " --plymouth Ask question with Plymouth instead of on TTY\n", + " --plymouth Ask question with Plymouth instead of on TTY\n" + " --console Ask question on /dev/console instead of current TTY\n", program_invocation_short_name); return 0; @@ -481,7 +552,8 @@ static int parse_argv(int argc, char *argv[]) { ARG_QUERY, ARG_WATCH, ARG_WALL, - ARG_PLYMOUTH + ARG_PLYMOUTH, + ARG_CONSOLE }; static const struct option options[] = { @@ -491,6 +563,7 @@ static int parse_argv(int argc, char *argv[]) { { "watch", no_argument, NULL, ARG_WATCH }, { "wall", no_argument, NULL, ARG_WALL }, { "plymouth", no_argument, NULL, ARG_PLYMOUTH }, + { "console", no_argument, NULL, ARG_CONSOLE }, { NULL, 0, NULL, 0 } }; @@ -527,6 +600,10 @@ static int parse_argv(int argc, char *argv[]) { arg_plymouth = true; break; + case ARG_CONSOLE: + arg_console = true; + break; + case '?': return -EINVAL; @@ -553,12 +630,20 @@ int main(int argc, char *argv[]) { if ((r = parse_argv(argc, argv)) <= 0) goto finish; + if (arg_console) { + setsid(); + release_terminal(); + } + if (arg_action == ACTION_WATCH || arg_action == ACTION_WALL) r = watch_passwords(); else r = show_passwords(); + if (r < 0) + log_error("Error: %s", strerror(-r)); + finish: return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; }