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=44ebc584914a6b5092835f0560e8ca09c7e7c299;hp=55be807cf20eb634b44b6939288d2febaef7e6d7;hb=2f07de3b6cacf44462635ab0fff56391b491e454;hpb=3bdf9c1d0a241eff2d17591854172725682b27cd diff --git a/src/shared/ask-password-api.c b/src/shared/ask-password-api.c index 55be807cf..44ebc5849 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 @@ -52,13 +52,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 +74,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 +86,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; @@ -109,7 +113,6 @@ int ask_password_tty( } zero(pollfd); - pollfd[POLL_TTY].fd = ttyfd >= 0 ? ttyfd : STDIN_FILENO; pollfd[POLL_TTY].events = POLLIN; pollfd[POLL_INOTIFY].fd = notify; @@ -139,8 +142,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; @@ -157,8 +160,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; @@ -208,36 +211,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; @@ -248,41 +248,40 @@ static int create_socket(char **name) { union { struct sockaddr sa; struct sockaddr_un un; - } sa; - int one = 1, r; + } sa = { + .un.sun_family = AF_UNIX, + }; + int one = 1; + int r = 0; char *c; - mode_t u; assert(name); - if ((fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0)) < 0) { - log_error("socket() failed: %m"); - return -errno; - } + fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); + if (fd < 0) + return log_error_errno(errno, "socket() failed: %m"); - zero(sa); - sa.un.sun_family = AF_UNIX; - 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()); - u = umask(0177); - r = bind(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path)); - umask(u); + RUN_WITH_UMASK(0177) { + r = bind(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path)); + } 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; } - if (!(c = strdup(sa.un.sun_path))) { - r = -ENOMEM; - log_error("Out of memory"); + c = strdup(sa.un.sun_path); + if (!c) { + r = log_oom(); goto fail; } @@ -290,7 +289,7 @@ static int create_socket(char **name) { return fd; fail: - close_nointr_nofail(fd); + safe_close(fd); return r; } @@ -298,7 +297,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) { @@ -310,13 +311,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]; - mode_t u; + int r; assert(_passphrases); @@ -324,49 +324,51 @@ int ask_password_agent( sigset_add_many(&mask, SIGINT, SIGTERM, -1); assert_se(sigprocmask(SIG_BLOCK, &mask, &oldmask) == 0); - mkdir_p("/run/systemd/ask-password", 0755); - - u = umask(0022); - fd = mkostemp(temp, O_CLOEXEC|O_CREAT|O_WRONLY); - umask(u); + mkdir_p_label("/run/systemd/ask-password", 0755); + 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); @@ -374,10 +376,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; } @@ -389,7 +394,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; } @@ -421,12 +426,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; } @@ -459,17 +464,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; @@ -525,22 +532,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); @@ -552,7 +545,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); @@ -560,18 +554,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); }