X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fask-password.c;h=1d89eafa97b30f23f91a831d25958e3cd2623a8a;hb=472ff3d64a870dcd767ecf61e07d89d8fb2f272d;hp=2c9b027d0041dab7e920db4319b3767e3408fa22;hpb=490aed584944b684026a3fd01f8d81f2881e38d6;p=elogind.git diff --git a/src/ask-password.c b/src/ask-password.c index 2c9b027d0..1d89eafa9 100644 --- a/src/ask-password.c +++ b/src/ask-password.c @@ -31,6 +31,9 @@ #include #include #include +#include +#include +#include #include "log.h" #include "macro.h" @@ -38,6 +41,7 @@ static const char *arg_icon = NULL; static const char *arg_message = NULL; +static bool arg_use_tty = true; static usec_t arg_timeout = 60 * USEC_PER_SEC; static int create_socket(char **name) { @@ -58,9 +62,9 @@ static int create_socket(char **name) { zero(sa); sa.un.sun_family = AF_UNIX; - snprintf(sa.un.sun_path+1, sizeof(sa.un.sun_path)-1, "/org/freedesktop/systemd1/ask-password/%llu", random_ull()); + snprintf(sa.un.sun_path, sizeof(sa.un.sun_path)-1, "/dev/.systemd/ask-password/sck.%llu", random_ull()); - if (bind(fd, &sa.sa, sizeof(sa_family_t) + 1 + strlen(sa.un.sun_path+1)) < 0) { + if (bind(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path)) < 0) { r = -errno; log_error("bind() failed: %m"); goto fail; @@ -72,7 +76,7 @@ static int create_socket(char **name) { goto fail; } - if (!(c = strdup(sa.un.sun_path+1))) { + if (!(c = strdup(sa.un.sun_path))) { r = -ENOMEM; log_error("Out of memory"); goto fail; @@ -90,10 +94,11 @@ fail: static int help(void) { printf("%s [OPTIONS...] MESSAGE\n\n" - "Query the user for a passphrase.\n\n" + "Query the user for a system passphrase, via the TTY or an UI agent.\n\n" " -h --help Show this help\n" " --icon=NAME Icon name\n" - " --timeout=USEC Timeout in usec\n", + " --timeout=SEC Timeout in sec\n" + " --no-tty Ask question via agent even on TTY\n", program_invocation_short_name); return 0; @@ -103,13 +108,15 @@ static int parse_argv(int argc, char *argv[]) { enum { ARG_ICON = 0x100, - ARG_TIMEOUT + ARG_TIMEOUT, + ARG_NO_TTY }; static const struct option options[] = { { "help", no_argument, NULL, 'h' }, { "icon", required_argument, NULL, ARG_ICON }, { "timeout", required_argument, NULL, ARG_TIMEOUT }, + { "no-tty", no_argument, NULL, ARG_NO_TTY }, { NULL, 0, NULL, 0 } }; @@ -137,6 +144,10 @@ static int parse_argv(int argc, char *argv[]) { } break; + case ARG_NO_TTY: + arg_use_tty = false; + break; + case '?': return -EINVAL; @@ -152,29 +163,31 @@ static int parse_argv(int argc, char *argv[]) { } arg_message = argv[optind]; - return 0; + return 1; } -int main(int argc, char *argv[]) { +static int ask_agent(void) { + enum { + FD_SOCKET, + FD_SIGNAL, + _FD_MAX + }; + char temp[] = "/dev/.systemd/ask-password/tmp.XXXXXX"; char final[sizeof(temp)] = ""; - int fd = -1, r = EXIT_FAILURE, k; + int fd = -1, r; FILE *f = NULL; char *socket_name = NULL; - int socket_fd, signal_fd; + int socket_fd = -1, signal_fd = -1; sigset_t mask; usec_t not_after; + struct pollfd pollfd[_FD_MAX]; - log_parse_environment(); - log_open(); - - if ((k = parse_argv(argc, argv)) < 0) { - r = k < 0 ? EXIT_FAILURE : EXIT_SUCCESS; - goto finish; - } + mkdir_p("/dev/.systemd/ask-password", 0755); if ((fd = mkostemp(temp, O_CLOEXEC|O_CREAT|O_WRONLY)) < 0) { log_error("Failed to create password file: %m"); + r = -errno; goto finish; } @@ -182,6 +195,7 @@ int main(int argc, char *argv[]) { if (!(f = fdopen(fd, "w"))) { log_error("Failed to allocate FILE: %m"); + r = -errno; goto finish; } @@ -193,18 +207,23 @@ int main(int argc, char *argv[]) { if ((signal_fd = signalfd(-1, &mask, SFD_NONBLOCK|SFD_CLOEXEC)) < 0) { log_error("signalfd(): %m"); + r = -errno; goto finish; } - if ((socket_fd = create_socket(&socket_name)) < 0) + if ((socket_fd = create_socket(&socket_name)) < 0) { + r = socket_fd; goto finish; + } not_after = now(CLOCK_MONOTONIC) + arg_timeout; fprintf(f, "[Ask]\n" + "PID=%lu\n" "Socket=%s\n" "NotAfter=%llu\n", + (unsigned long) getpid(), socket_name, (unsigned long long) not_after); @@ -218,6 +237,7 @@ int main(int argc, char *argv[]) { if (ferror(f)) { log_error("Failed to write query file: %m"); + r = -errno; goto finish; } @@ -229,16 +249,17 @@ int main(int argc, char *argv[]) { if (rename(temp, final) < 0) { log_error("Failed to rename query file: %m"); + r = -errno; goto finish; } - for (;;) { - enum { - FD_SOCKET, - FD_SIGNAL, - _FD_MAX - }; + zero(pollfd); + pollfd[FD_SOCKET].fd = socket_fd; + pollfd[FD_SOCKET].events = POLLIN; + pollfd[FD_SIGNAL].fd = signal_fd; + pollfd[FD_SIGNAL].events = POLLIN; + for (;;) { char passphrase[LINE_MAX+1]; struct msghdr msghdr; struct iovec iovec; @@ -248,25 +269,21 @@ int main(int argc, char *argv[]) { uint8_t buf[CMSG_SPACE(sizeof(struct ucred))]; } control; ssize_t n; - struct pollfd pollfd[_FD_MAX]; - - zero(pollfd); - pollfd[FD_SOCKET].fd = socket_fd; - pollfd[FD_SOCKET].events = POLLIN; - pollfd[FD_SIGNAL].fd = signal_fd; - pollfd[FD_SIGNAL].events = POLLIN; + int k; - if ((k = poll(pollfd, 2, arg_timeout/USEC_PER_MSEC)) < 0) { + if ((k = poll(pollfd, _FD_MAX, arg_timeout/USEC_PER_MSEC)) < 0) { if (errno == EINTR) continue; - log_error("poll() failed: %s", strerror(-r)); + log_error("poll() failed: %m"); + r = -errno; goto finish; } if (k <= 0) { log_notice("Timed out"); + r = -ETIME; goto finish; } @@ -275,6 +292,7 @@ int main(int argc, char *argv[]) { if (pollfd[FD_SOCKET].revents != POLLIN) { log_error("Unexpected poll() event."); + r = -EIO; goto finish; } @@ -296,6 +314,7 @@ int main(int argc, char *argv[]) { continue; log_error("recvmsg() failed: %m"); + r = -errno; goto finish; } @@ -321,9 +340,11 @@ int main(int argc, char *argv[]) { if (passphrase[0] == '+') { passphrase[n] = 0; fputs(passphrase+1, stdout); - } else if (passphrase[0] == '-') + fflush(stdout); + } else if (passphrase[0] == '-') { + r = -ECANCELED; goto finish; - else { + } else { log_error("Invalid packet"); continue; } @@ -331,15 +352,23 @@ int main(int argc, char *argv[]) { break; } - r = EXIT_SUCCESS; + r = 0; finish: if (fd >= 0) close_nointr_nofail(fd); + if (socket_name) { + unlink(socket_name); + free(socket_name); + } + if (socket_fd >= 0) close_nointr_nofail(socket_fd); + if (signal_fd >= 0) + close_nointr_nofail(signal_fd); + if (f) fclose(f); @@ -350,3 +379,28 @@ finish: return r; } + +int main(int argc, char *argv[]) { + int r; + + log_parse_environment(); + log_open(); + + if ((r = parse_argv(argc, argv)) <= 0) + goto finish; + + if (arg_use_tty && isatty(STDIN_FILENO)) { + char *password = NULL; + + if ((r = ask_password_tty(arg_message, now(CLOCK_MONOTONIC) + arg_timeout, NULL, &password)) >= 0) { + fputs(password, stdout); + fflush(stdout); + free(password); + } + + } else + r = ask_agent(); + +finish: + return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; +}