mirror of
https://github.com/systemd/systemd.git
synced 2025-02-03 17:47:28 +03:00
Merge pull request #13632 from fbuihuu/ask-password-some-reworks
Ask password some reworks
This commit is contained in:
commit
e0a0c64cb9
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
|
@ -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,
|
||||
@ -371,6 +552,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 +655,7 @@ int ask_password_tty(
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
|
||||
skipped:
|
||||
if (keyname)
|
||||
(void) add_to_keyring_and_log(keyname, flags, l);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -11,7 +11,6 @@
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <sys/inotify.h>
|
||||
#include <sys/prctl.h>
|
||||
#include <sys/signalfd.h>
|
||||
#include <sys/socket.h>
|
||||
@ -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"
|
||||
@ -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;
|
||||
@ -318,7 +137,40 @@ static bool wall_tty_match(const char *path, void *userdata) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parse_password(const char *filename) {
|
||||
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;
|
||||
uint64_t not_after = 0;
|
||||
@ -355,25 +207,28 @@ static int parse_password(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,44 +237,31 @@ static int parse_password(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();
|
||||
}
|
||||
return log_error_errno(r, "Failed to query password: %m");
|
||||
}
|
||||
|
||||
/* 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;
|
||||
|
||||
r = send_passwords(socket_name, passwords);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to send: %m");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -449,7 +291,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;
|
||||
@ -462,7 +304,7 @@ static int show_passwords(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 +314,6 @@ static int show_passwords(void) {
|
||||
if (de->d_type != DT_REG)
|
||||
continue;
|
||||
|
||||
if (hidden_or_backup_file(de->d_name))
|
||||
continue;
|
||||
|
||||
if (!startswith(de->d_name, "ask."))
|
||||
continue;
|
||||
|
||||
@ -482,7 +321,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,10 +329,10 @@ static int show_passwords(void) {
|
||||
return r;
|
||||
}
|
||||
|
||||
static int watch_passwords(void) {
|
||||
static int process_and_watch_password_files(bool watch) {
|
||||
enum {
|
||||
FD_INOTIFY,
|
||||
FD_SIGNAL,
|
||||
FD_INOTIFY,
|
||||
_FD_MAX
|
||||
};
|
||||
|
||||
@ -506,36 +345,51 @@ static int watch_passwords(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");
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
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);
|
||||
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 (;;) {
|
||||
r = show_passwords();
|
||||
if (r < 0)
|
||||
log_error_errno(r, "Failed to show 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
|
||||
/* 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");
|
||||
}
|
||||
|
||||
if (!watch)
|
||||
break;
|
||||
|
||||
if (poll(pollfd, watch ? _FD_MAX : _FD_MAX-1, timeout) < 0) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
|
||||
@ -856,10 +710,7 @@ static int run(int argc, char *argv[]) {
|
||||
(void) release_terminal();
|
||||
}
|
||||
|
||||
if (IN_SET(arg_action, ACTION_WATCH, ACTION_WALL))
|
||||
return watch_passwords();
|
||||
else
|
||||
return show_passwords();
|
||||
return process_and_watch_password_files(arg_action != ACTION_QUERY);
|
||||
}
|
||||
|
||||
DEFINE_MAIN_FUNCTION(run);
|
||||
|
Loading…
x
Reference in New Issue
Block a user