X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fshared%2Fask-password-api.c;h=dfc89d23fd91cadb07d193fea2130bf65265c44f;hp=4557155d45fc36a11afbbf2b75b373112372a7eb;hb=01c94c5d0aff09b4c0e429d483c8eeba40017071;hpb=b92bea5d2a9481de69bb627a7b442a9f58fca43d diff --git a/src/shared/ask-password-api.c b/src/shared/ask-password-api.c index 4557155d4..dfc89d23f 100644 --- a/src/shared/ask-password-api.c +++ b/src/shared/ask-password-api.c @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include #include #include @@ -32,6 +32,7 @@ #include #include "util.h" +#include "formats-util.h" #include "mkdir.h" #include "strv.h" @@ -52,13 +53,15 @@ static void backspace_chars(int ttyfd, size_t p) { int ask_password_tty( const char *message, usec_t until, + bool echo, const char *flag_file, char **_passphrase) { struct termios old_termios, new_termios; - char passphrase[LINE_MAX]; + char passphrase[LINE_MAX], *x; size_t p = 0; - int r, ttyfd = -1, notify = -1; + int r; + _cleanup_close_ int ttyfd = -1, notify = -1; struct pollfd pollfd[2]; bool reset_tty = false; bool silent_mode = false; @@ -72,7 +75,8 @@ int ask_password_tty( assert(_passphrase); if (flag_file) { - if ((notify = inotify_init1(IN_CLOEXEC|IN_NONBLOCK)) < 0) { + notify = inotify_init1(IN_CLOEXEC|IN_NONBLOCK); + if (notify < 0) { r = -errno; goto finish; } @@ -83,7 +87,8 @@ int ask_password_tty( } } - if ((ttyfd = open("/dev/tty", O_RDWR|O_NOCTTY|O_CLOEXEC)) >= 0) { + ttyfd = open("/dev/tty", O_RDWR|O_NOCTTY|O_CLOEXEC); + if (ttyfd >= 0) { if (tcgetattr(ttyfd, &old_termios) < 0) { r = -errno; @@ -138,8 +143,8 @@ int ask_password_tty( goto finish; } - if ((k = poll(pollfd, notify > 0 ? 2 : 1, sleep_for)) < 0) { - + k = poll(pollfd, notify > 0 ? 2 : 1, sleep_for); + if (k < 0) { if (errno == EINTR) continue; @@ -156,8 +161,8 @@ int ask_password_tty( if (pollfd[POLL_TTY].revents == 0) continue; - if ((n = read(ttyfd >= 0 ? ttyfd : STDIN_FILENO, &c, 1)) < 0) { - + n = read(ttyfd >= 0 ? ttyfd : STDIN_FILENO, &c, 1); + if (n < 0) { if (errno == EINTR || errno == EAGAIN) continue; @@ -207,36 +212,33 @@ int ask_password_tty( if (ttyfd >= 0) loop_write(ttyfd, "(no echo) ", 10, false); } else { + if (p >= sizeof(passphrase)-1) { + loop_write(ttyfd, "\a", 1, false); + continue; + } + passphrase[p++] = c; if (!silent_mode && ttyfd >= 0) - loop_write(ttyfd, "*", 1, false); + loop_write(ttyfd, echo ? &c : "*", 1, false); dirty = true; } } - passphrase[p] = 0; - - if (!(*_passphrase = strdup(passphrase))) { + x = strndup(passphrase, p); + if (!x) { r = -ENOMEM; goto finish; } + *_passphrase = x; r = 0; finish: - if (notify >= 0) - close_nointr_nofail(notify); - - if (ttyfd >= 0) { - - if (reset_tty) { - loop_write(ttyfd, "\n", 1, false); - tcsetattr(ttyfd, TCSADRAIN, &old_termios); - } - - close_nointr_nofail(ttyfd); + if (ttyfd >= 0 && reset_tty) { + loop_write(ttyfd, "\n", 1, false); + tcsetattr(ttyfd, TCSADRAIN, &old_termios); } return r; @@ -250,18 +252,17 @@ static int create_socket(char **name) { } sa = { .un.sun_family = AF_UNIX, }; - int one = 1, r; + int one = 1; + int r = 0; char *c; assert(name); fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); - if (fd < 0) { - log_error("socket() failed: %m"); - return -errno; - } + if (fd < 0) + return log_error_errno(errno, "socket() failed: %m"); - snprintf(sa.un.sun_path, sizeof(sa.un.sun_path)-1, "/run/systemd/ask-password/sck.%llu", random_ull()); + snprintf(sa.un.sun_path, sizeof(sa.un.sun_path)-1, "/run/systemd/ask-password/sck.%" PRIx64, random_u64()); RUN_WITH_UMASK(0177) { r = bind(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path)); @@ -269,13 +270,13 @@ static int create_socket(char **name) { if (r < 0) { r = -errno; - log_error("bind() failed: %m"); + log_error_errno(errno, "bind(%s) failed: %m", sa.un.sun_path); goto fail; } if (setsockopt(fd, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one)) < 0) { r = -errno; - log_error("SO_PASSCRED failed: %m"); + log_error_errno(errno, "SO_PASSCRED failed: %m"); goto fail; } @@ -289,7 +290,7 @@ static int create_socket(char **name) { return fd; fail: - close_nointr_nofail(fd); + safe_close(fd); return r; } @@ -297,7 +298,9 @@ fail: int ask_password_agent( const char *message, const char *icon, + const char *id, usec_t until, + bool echo, bool accept_cached, char ***_passphrases) { @@ -309,12 +312,12 @@ int ask_password_agent( char temp[] = "/run/systemd/ask-password/tmp.XXXXXX"; char final[sizeof(temp)] = ""; - int fd = -1, r; - FILE *f = NULL; - char *socket_name = NULL; - int socket_fd = -1, signal_fd = -1; + _cleanup_fclose_ FILE *f = NULL; + _cleanup_free_ char *socket_name = NULL; + _cleanup_close_ int socket_fd = -1, signal_fd = -1, fd = -1; sigset_t mask, oldmask; struct pollfd pollfd[_FD_MAX]; + int r; assert(_passphrases); @@ -324,47 +327,49 @@ int ask_password_agent( mkdir_p_label("/run/systemd/ask-password", 0755); - RUN_WITH_UMASK(0022) { - fd = mkostemp(temp, O_CLOEXEC|O_CREAT|O_WRONLY); - } - + fd = mkostemp_safe(temp, O_WRONLY|O_CLOEXEC); if (fd < 0) { - log_error("Failed to create password file: %m"); + log_error_errno(errno, "Failed to create password file: %m"); r = -errno; goto finish; } fchmod(fd, 0644); - if (!(f = fdopen(fd, "w"))) { - log_error("Failed to allocate FILE: %m"); + f = fdopen(fd, "w"); + if (!f) { + log_error_errno(errno, "Failed to allocate FILE: %m"); r = -errno; goto finish; } fd = -1; - if ((signal_fd = signalfd(-1, &mask, SFD_NONBLOCK|SFD_CLOEXEC)) < 0) { - log_error("signalfd(): %m"); + signal_fd = signalfd(-1, &mask, SFD_NONBLOCK|SFD_CLOEXEC); + if (signal_fd < 0) { + log_error_errno(errno, "signalfd(): %m"); r = -errno; goto finish; } - if ((socket_fd = create_socket(&socket_name)) < 0) { + socket_fd = create_socket(&socket_name); + if (socket_fd < 0) { r = socket_fd; goto finish; } fprintf(f, "[Ask]\n" - "PID=%lu\n" + "PID="PID_FMT"\n" "Socket=%s\n" "AcceptCached=%i\n" - "NotAfter=%llu\n", - (unsigned long) getpid(), + "Echo=%i\n" + "NotAfter="USEC_FMT"\n", + getpid(), socket_name, accept_cached ? 1 : 0, - (unsigned long long) until); + echo ? 1 : 0, + until); if (message) fprintf(f, "Message=%s\n", message); @@ -372,10 +377,13 @@ int ask_password_agent( if (icon) fprintf(f, "Icon=%s\n", icon); + if (id) + fprintf(f, "Id=%s\n", id); + fflush(f); if (ferror(f)) { - log_error("Failed to write query file: %m"); + log_error_errno(errno, "Failed to write query file: %m"); r = -errno; goto finish; } @@ -387,7 +395,7 @@ int ask_password_agent( final[sizeof(final)-9] = 'k'; if (rename(temp, final) < 0) { - log_error("Failed to rename query file: %m"); + log_error_errno(errno, "Failed to rename query file: %m"); r = -errno; goto finish; } @@ -419,12 +427,12 @@ int ask_password_agent( goto finish; } - if ((k = poll(pollfd, _FD_MAX, until > 0 ? (int) ((until-t)/USEC_PER_MSEC) : -1)) < 0) { - + k = poll(pollfd, _FD_MAX, until > 0 ? (int) ((until-t)/USEC_PER_MSEC) : -1); + if (k < 0) { if (errno == EINTR) continue; - log_error("poll() failed: %m"); + log_error_errno(errno, "poll() failed: %m"); r = -errno; goto finish; } @@ -457,17 +465,19 @@ int ask_password_agent( msghdr.msg_control = &control; msghdr.msg_controllen = sizeof(control); - if ((n = recvmsg(socket_fd, &msghdr, 0)) < 0) { - + n = recvmsg(socket_fd, &msghdr, 0); + if (n < 0) { if (errno == EAGAIN || errno == EINTR) continue; - log_error("recvmsg() failed: %m"); + log_error_errno(errno, "recvmsg() failed: %m"); r = -errno; goto finish; } + cmsg_close_all(&msghdr); + if (n <= 0) { log_error("Message too short"); continue; @@ -523,22 +533,8 @@ int ask_password_agent( r = 0; finish: - if (fd >= 0) - close_nointr_nofail(fd); - - if (socket_name) { + 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); unlink(temp); @@ -550,7 +546,8 @@ finish: return r; } -int ask_password_auto(const char *message, const char *icon, usec_t until, bool accept_cached, char ***_passphrases) { +int ask_password_auto(const char *message, const char *icon, const char *id, + usec_t until, bool accept_cached, char ***_passphrases) { assert(message); assert(_passphrases); @@ -558,18 +555,16 @@ int ask_password_auto(const char *message, const char *icon, usec_t until, bool int r; char *s = NULL, **l = NULL; - if ((r = ask_password_tty(message, until, NULL, &s)) < 0) + r = ask_password_tty(message, until, false, NULL, &s); + if (r < 0) return r; - l = strv_new(s, NULL); - free(s); - - if (!l) - return -ENOMEM; + r = strv_consume(&l, s); + if (r < 0) + return r; *_passphrases = l; return r; - } else - return ask_password_agent(message, icon, until, accept_cached, _passphrases); + return ask_password_agent(message, icon, id, until, false, accept_cached, _passphrases); }