ask-password-api.c revision 981e4cd325410384cdadd837f34c002699d2d750
0797faae937515a5225a36db4a1ec79480d2555cjorton/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
0797faae937515a5225a36db4a1ec79480d2555cjorton
0797faae937515a5225a36db4a1ec79480d2555cjorton/***
0797faae937515a5225a36db4a1ec79480d2555cjorton This file is part of systemd.
0797faae937515a5225a36db4a1ec79480d2555cjorton
0797faae937515a5225a36db4a1ec79480d2555cjorton Copyright 2010 Lennart Poettering
0797faae937515a5225a36db4a1ec79480d2555cjorton
0797faae937515a5225a36db4a1ec79480d2555cjorton systemd is free software; you can redistribute it and/or modify it
0797faae937515a5225a36db4a1ec79480d2555cjorton under the terms of the GNU Lesser General Public License as published by
0797faae937515a5225a36db4a1ec79480d2555cjorton the Free Software Foundation; either version 2.1 of the License, or
0797faae937515a5225a36db4a1ec79480d2555cjorton (at your option) any later version.
0797faae937515a5225a36db4a1ec79480d2555cjorton
0797faae937515a5225a36db4a1ec79480d2555cjorton systemd is distributed in the hope that it will be useful, but
0797faae937515a5225a36db4a1ec79480d2555cjorton WITHOUT ANY WARRANTY; without even the implied warranty of
0797faae937515a5225a36db4a1ec79480d2555cjorton MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0797faae937515a5225a36db4a1ec79480d2555cjorton Lesser General Public License for more details.
0797faae937515a5225a36db4a1ec79480d2555cjorton
0797faae937515a5225a36db4a1ec79480d2555cjorton You should have received a copy of the GNU Lesser General Public License
0797faae937515a5225a36db4a1ec79480d2555cjorton along with systemd; If not, see <http://www.gnu.org/licenses/>.
0797faae937515a5225a36db4a1ec79480d2555cjorton***/
0797faae937515a5225a36db4a1ec79480d2555cjorton#include <stdbool.h>
0797faae937515a5225a36db4a1ec79480d2555cjorton#include <termios.h>
0797faae937515a5225a36db4a1ec79480d2555cjorton#include <unistd.h>
0797faae937515a5225a36db4a1ec79480d2555cjorton#include <sys/poll.h>
0797faae937515a5225a36db4a1ec79480d2555cjorton#include <sys/inotify.h>
0797faae937515a5225a36db4a1ec79480d2555cjorton#include <errno.h>
0797faae937515a5225a36db4a1ec79480d2555cjorton#include <fcntl.h>
0797faae937515a5225a36db4a1ec79480d2555cjorton#include <sys/socket.h>
0797faae937515a5225a36db4a1ec79480d2555cjorton#include <string.h>
0797faae937515a5225a36db4a1ec79480d2555cjorton#include <sys/un.h>
0797faae937515a5225a36db4a1ec79480d2555cjorton#include <stddef.h>
0797faae937515a5225a36db4a1ec79480d2555cjorton#include <sys/signalfd.h>
0797faae937515a5225a36db4a1ec79480d2555cjorton
0797faae937515a5225a36db4a1ec79480d2555cjorton#include "util.h"
0797faae937515a5225a36db4a1ec79480d2555cjorton#include "mkdir.h"
0797faae937515a5225a36db4a1ec79480d2555cjorton#include "strv.h"
dca6643570b2f028bc7af76329bd7e333bf7493cpquerna
dca6643570b2f028bc7af76329bd7e333bf7493cpquerna#include "ask-password-api.h"
dca6643570b2f028bc7af76329bd7e333bf7493cpquerna
dca6643570b2f028bc7af76329bd7e333bf7493cpquernastatic void backspace_chars(int ttyfd, size_t p) {
0797faae937515a5225a36db4a1ec79480d2555cjorton
0797faae937515a5225a36db4a1ec79480d2555cjorton if (ttyfd < 0)
2685f3814b77577ef7b2523442dab1ca88df1e41jorton return;
0797faae937515a5225a36db4a1ec79480d2555cjorton
0797faae937515a5225a36db4a1ec79480d2555cjorton while (p > 0) {
0797faae937515a5225a36db4a1ec79480d2555cjorton p--;
a10d8ce69c26142323c66adaba109be1b4baa379wrowe
a10d8ce69c26142323c66adaba109be1b4baa379wrowe loop_write(ttyfd, "\b \b", 3, false);
0797faae937515a5225a36db4a1ec79480d2555cjorton }
0797faae937515a5225a36db4a1ec79480d2555cjorton}
0797faae937515a5225a36db4a1ec79480d2555cjorton
0797faae937515a5225a36db4a1ec79480d2555cjortonint ask_password_tty(
0797faae937515a5225a36db4a1ec79480d2555cjorton const char *message,
eab15974b1d8bbcb6d4f9ec75527b39ffded82aajorton usec_t until,
0797faae937515a5225a36db4a1ec79480d2555cjorton const char *flag_file,
bf8ae84ccab0e10cacda6098f6a696577752c433wrowe char **_passphrase) {
bf8ae84ccab0e10cacda6098f6a696577752c433wrowe
bf8ae84ccab0e10cacda6098f6a696577752c433wrowe struct termios old_termios, new_termios;
bf8ae84ccab0e10cacda6098f6a696577752c433wrowe char passphrase[LINE_MAX], *x;
8c4aed3f92674325e17d8360ee2797beda3a1472jorton size_t p = 0;
bf8ae84ccab0e10cacda6098f6a696577752c433wrowe int r;
8c4aed3f92674325e17d8360ee2797beda3a1472jorton _cleanup_close_ int ttyfd = -1, notify = -1;
0797faae937515a5225a36db4a1ec79480d2555cjorton struct pollfd pollfd[2];
eab15974b1d8bbcb6d4f9ec75527b39ffded82aajorton bool reset_tty = false;
0797faae937515a5225a36db4a1ec79480d2555cjorton bool silent_mode = false;
eab15974b1d8bbcb6d4f9ec75527b39ffded82aajorton bool dirty = false;
eab15974b1d8bbcb6d4f9ec75527b39ffded82aajorton enum {
0797faae937515a5225a36db4a1ec79480d2555cjorton POLL_TTY,
eab15974b1d8bbcb6d4f9ec75527b39ffded82aajorton POLL_INOTIFY
eab15974b1d8bbcb6d4f9ec75527b39ffded82aajorton };
0797faae937515a5225a36db4a1ec79480d2555cjorton
eab15974b1d8bbcb6d4f9ec75527b39ffded82aajorton assert(message);
eab15974b1d8bbcb6d4f9ec75527b39ffded82aajorton assert(_passphrase);
0797faae937515a5225a36db4a1ec79480d2555cjorton
0797faae937515a5225a36db4a1ec79480d2555cjorton if (flag_file) {
0797faae937515a5225a36db4a1ec79480d2555cjorton notify = inotify_init1(IN_CLOEXEC|IN_NONBLOCK);
2685f3814b77577ef7b2523442dab1ca88df1e41jorton if (notify < 0) {
0797faae937515a5225a36db4a1ec79480d2555cjorton r = -errno;
501e60e433e1914c64f642114fbb4fb9be9e2ca9jorton goto finish;
501e60e433e1914c64f642114fbb4fb9be9e2ca9jorton }
501e60e433e1914c64f642114fbb4fb9be9e2ca9jorton
0797faae937515a5225a36db4a1ec79480d2555cjorton if (inotify_add_watch(notify, flag_file, IN_ATTRIB /* for the link count */) < 0) {
2685f3814b77577ef7b2523442dab1ca88df1e41jorton r = -errno;
2685f3814b77577ef7b2523442dab1ca88df1e41jorton goto finish;
0797faae937515a5225a36db4a1ec79480d2555cjorton }
0797faae937515a5225a36db4a1ec79480d2555cjorton }
2685f3814b77577ef7b2523442dab1ca88df1e41jorton
0797faae937515a5225a36db4a1ec79480d2555cjorton ttyfd = open("/dev/tty", O_RDWR|O_NOCTTY|O_CLOEXEC);
0797faae937515a5225a36db4a1ec79480d2555cjorton if (ttyfd >= 0) {
0797faae937515a5225a36db4a1ec79480d2555cjorton
8c4aed3f92674325e17d8360ee2797beda3a1472jorton if (tcgetattr(ttyfd, &old_termios) < 0) {
8c4aed3f92674325e17d8360ee2797beda3a1472jorton r = -errno;
8c4aed3f92674325e17d8360ee2797beda3a1472jorton goto finish;
8c4aed3f92674325e17d8360ee2797beda3a1472jorton }
8c4aed3f92674325e17d8360ee2797beda3a1472jorton
0797faae937515a5225a36db4a1ec79480d2555cjorton loop_write(ttyfd, ANSI_HIGHLIGHT_ON, sizeof(ANSI_HIGHLIGHT_ON)-1, false);
fca945cb6bed035dcc6bbced5e327bbd4d8420abjorton loop_write(ttyfd, message, strlen(message), false);
0797faae937515a5225a36db4a1ec79480d2555cjorton loop_write(ttyfd, " ", 1, false);
0797faae937515a5225a36db4a1ec79480d2555cjorton loop_write(ttyfd, ANSI_HIGHLIGHT_OFF, sizeof(ANSI_HIGHLIGHT_OFF)-1, false);
0797faae937515a5225a36db4a1ec79480d2555cjorton
0797faae937515a5225a36db4a1ec79480d2555cjorton new_termios = old_termios;
0797faae937515a5225a36db4a1ec79480d2555cjorton new_termios.c_lflag &= ~(ICANON|ECHO);
2685f3814b77577ef7b2523442dab1ca88df1e41jorton new_termios.c_cc[VMIN] = 1;
fca945cb6bed035dcc6bbced5e327bbd4d8420abjorton new_termios.c_cc[VTIME] = 0;
fca945cb6bed035dcc6bbced5e327bbd4d8420abjorton
2685f3814b77577ef7b2523442dab1ca88df1e41jorton if (tcsetattr(ttyfd, TCSADRAIN, &new_termios) < 0) {
0797faae937515a5225a36db4a1ec79480d2555cjorton r = -errno;
0797faae937515a5225a36db4a1ec79480d2555cjorton goto finish;
0797faae937515a5225a36db4a1ec79480d2555cjorton }
0797faae937515a5225a36db4a1ec79480d2555cjorton
0797faae937515a5225a36db4a1ec79480d2555cjorton reset_tty = true;
0797faae937515a5225a36db4a1ec79480d2555cjorton }
8c4aed3f92674325e17d8360ee2797beda3a1472jorton
8c4aed3f92674325e17d8360ee2797beda3a1472jorton zero(pollfd);
8c4aed3f92674325e17d8360ee2797beda3a1472jorton pollfd[POLL_TTY].fd = ttyfd >= 0 ? ttyfd : STDIN_FILENO;
8c4aed3f92674325e17d8360ee2797beda3a1472jorton pollfd[POLL_TTY].events = POLLIN;
8c4aed3f92674325e17d8360ee2797beda3a1472jorton pollfd[POLL_INOTIFY].fd = notify;
8c4aed3f92674325e17d8360ee2797beda3a1472jorton pollfd[POLL_INOTIFY].events = POLLIN;
8c4aed3f92674325e17d8360ee2797beda3a1472jorton
8c4aed3f92674325e17d8360ee2797beda3a1472jorton for (;;) {
8c4aed3f92674325e17d8360ee2797beda3a1472jorton char c;
8c4aed3f92674325e17d8360ee2797beda3a1472jorton int sleep_for = -1, k;
8c4aed3f92674325e17d8360ee2797beda3a1472jorton ssize_t n;
0797faae937515a5225a36db4a1ec79480d2555cjorton
0797faae937515a5225a36db4a1ec79480d2555cjorton if (until > 0) {
0797faae937515a5225a36db4a1ec79480d2555cjorton usec_t y;
0797faae937515a5225a36db4a1ec79480d2555cjorton
0797faae937515a5225a36db4a1ec79480d2555cjorton y = now(CLOCK_MONOTONIC);
0797faae937515a5225a36db4a1ec79480d2555cjorton
eab15974b1d8bbcb6d4f9ec75527b39ffded82aajorton if (y > until) {
0797faae937515a5225a36db4a1ec79480d2555cjorton r = -ETIME;
eab15974b1d8bbcb6d4f9ec75527b39ffded82aajorton goto finish;
0797faae937515a5225a36db4a1ec79480d2555cjorton }
0797faae937515a5225a36db4a1ec79480d2555cjorton
0797faae937515a5225a36db4a1ec79480d2555cjorton sleep_for = (int) ((until - y) / USEC_PER_MSEC);
0797faae937515a5225a36db4a1ec79480d2555cjorton }
0797faae937515a5225a36db4a1ec79480d2555cjorton
fca945cb6bed035dcc6bbced5e327bbd4d8420abjorton if (flag_file)
a10d8ce69c26142323c66adaba109be1b4baa379wrowe if (access(flag_file, F_OK) < 0) {
fca945cb6bed035dcc6bbced5e327bbd4d8420abjorton r = -errno;
0b310e2cb91c7ca69a95637c05fae2fb124d7fcfpquerna goto finish;
0797faae937515a5225a36db4a1ec79480d2555cjorton }
0797faae937515a5225a36db4a1ec79480d2555cjorton
0797faae937515a5225a36db4a1ec79480d2555cjorton k = poll(pollfd, notify > 0 ? 2 : 1, sleep_for);
0797faae937515a5225a36db4a1ec79480d2555cjorton if (k < 0) {
0797faae937515a5225a36db4a1ec79480d2555cjorton if (errno == EINTR)
0797faae937515a5225a36db4a1ec79480d2555cjorton continue;
a91a59d0b0ceed7cd5621fe8757eda5ff6a043a8pquerna
eab15974b1d8bbcb6d4f9ec75527b39ffded82aajorton r = -errno;
a91a59d0b0ceed7cd5621fe8757eda5ff6a043a8pquerna goto finish;
0797faae937515a5225a36db4a1ec79480d2555cjorton } else if (k == 0) {
a91a59d0b0ceed7cd5621fe8757eda5ff6a043a8pquerna r = -ETIME;
0797faae937515a5225a36db4a1ec79480d2555cjorton goto finish;
a91a59d0b0ceed7cd5621fe8757eda5ff6a043a8pquerna }
0797faae937515a5225a36db4a1ec79480d2555cjorton
eab15974b1d8bbcb6d4f9ec75527b39ffded82aajorton if (notify > 0 && pollfd[POLL_INOTIFY].revents != 0)
a91a59d0b0ceed7cd5621fe8757eda5ff6a043a8pquerna flush_fd(notify);
0797faae937515a5225a36db4a1ec79480d2555cjorton
a91a59d0b0ceed7cd5621fe8757eda5ff6a043a8pquerna if (pollfd[POLL_TTY].revents == 0)
0797faae937515a5225a36db4a1ec79480d2555cjorton continue;
a91a59d0b0ceed7cd5621fe8757eda5ff6a043a8pquerna
0797faae937515a5225a36db4a1ec79480d2555cjorton n = read(ttyfd >= 0 ? ttyfd : STDIN_FILENO, &c, 1);
0797faae937515a5225a36db4a1ec79480d2555cjorton if (n < 0) {
0797faae937515a5225a36db4a1ec79480d2555cjorton if (errno == EINTR || errno == EAGAIN)
0797faae937515a5225a36db4a1ec79480d2555cjorton continue;
0797faae937515a5225a36db4a1ec79480d2555cjorton
0797faae937515a5225a36db4a1ec79480d2555cjorton r = -errno;
0797faae937515a5225a36db4a1ec79480d2555cjorton goto finish;
0797faae937515a5225a36db4a1ec79480d2555cjorton
4b0e00b3346b3e8fd53219d060f4cf6676847a06jim } else if (n == 0)
0797faae937515a5225a36db4a1ec79480d2555cjorton break;
0797faae937515a5225a36db4a1ec79480d2555cjorton
eab15974b1d8bbcb6d4f9ec75527b39ffded82aajorton if (c == '\n')
eab15974b1d8bbcb6d4f9ec75527b39ffded82aajorton break;
0797faae937515a5225a36db4a1ec79480d2555cjorton else if (c == 21) { /* C-u */
0797faae937515a5225a36db4a1ec79480d2555cjorton
0797faae937515a5225a36db4a1ec79480d2555cjorton if (!silent_mode)
0797faae937515a5225a36db4a1ec79480d2555cjorton backspace_chars(ttyfd, p);
0797faae937515a5225a36db4a1ec79480d2555cjorton p = 0;
0797faae937515a5225a36db4a1ec79480d2555cjorton
0797faae937515a5225a36db4a1ec79480d2555cjorton } else if (c == '\b' || c == 127) {
0797faae937515a5225a36db4a1ec79480d2555cjorton
0797faae937515a5225a36db4a1ec79480d2555cjorton if (p > 0) {
501e60e433e1914c64f642114fbb4fb9be9e2ca9jorton
501e60e433e1914c64f642114fbb4fb9be9e2ca9jorton if (!silent_mode)
a10d8ce69c26142323c66adaba109be1b4baa379wrowe backspace_chars(ttyfd, 1);
501e60e433e1914c64f642114fbb4fb9be9e2ca9jorton
501e60e433e1914c64f642114fbb4fb9be9e2ca9jorton p--;
0797faae937515a5225a36db4a1ec79480d2555cjorton } else if (!dirty && !silent_mode) {
0797faae937515a5225a36db4a1ec79480d2555cjorton
0797faae937515a5225a36db4a1ec79480d2555cjorton silent_mode = true;
0797faae937515a5225a36db4a1ec79480d2555cjorton
0797faae937515a5225a36db4a1ec79480d2555cjorton /* There are two ways to enter silent
0797faae937515a5225a36db4a1ec79480d2555cjorton * mode. Either by pressing backspace
0797faae937515a5225a36db4a1ec79480d2555cjorton * as first key (and only as first key),
0797faae937515a5225a36db4a1ec79480d2555cjorton * or ... */
0797faae937515a5225a36db4a1ec79480d2555cjorton if (ttyfd >= 0)
0797faae937515a5225a36db4a1ec79480d2555cjorton loop_write(ttyfd, "(no echo) ", 10, false);
a10d8ce69c26142323c66adaba109be1b4baa379wrowe
0797faae937515a5225a36db4a1ec79480d2555cjorton } else if (ttyfd >= 0)
0797faae937515a5225a36db4a1ec79480d2555cjorton loop_write(ttyfd, "\a", 1, false);
0797faae937515a5225a36db4a1ec79480d2555cjorton
0797faae937515a5225a36db4a1ec79480d2555cjorton } else if (c == '\t' && !silent_mode) {
0797faae937515a5225a36db4a1ec79480d2555cjorton
0797faae937515a5225a36db4a1ec79480d2555cjorton backspace_chars(ttyfd, p);
a10d8ce69c26142323c66adaba109be1b4baa379wrowe silent_mode = true;
0797faae937515a5225a36db4a1ec79480d2555cjorton
0797faae937515a5225a36db4a1ec79480d2555cjorton /* ... or by pressing TAB at any time. */
0797faae937515a5225a36db4a1ec79480d2555cjorton
0797faae937515a5225a36db4a1ec79480d2555cjorton if (ttyfd >= 0)
0797faae937515a5225a36db4a1ec79480d2555cjorton loop_write(ttyfd, "(no echo) ", 10, false);
0797faae937515a5225a36db4a1ec79480d2555cjorton } else {
0797faae937515a5225a36db4a1ec79480d2555cjorton if (p >= sizeof(passphrase)-1) {
0797faae937515a5225a36db4a1ec79480d2555cjorton loop_write(ttyfd, "\a", 1, false);
0797faae937515a5225a36db4a1ec79480d2555cjorton continue;
0797faae937515a5225a36db4a1ec79480d2555cjorton }
a10d8ce69c26142323c66adaba109be1b4baa379wrowe
0797faae937515a5225a36db4a1ec79480d2555cjorton passphrase[p++] = c;
0797faae937515a5225a36db4a1ec79480d2555cjorton
0797faae937515a5225a36db4a1ec79480d2555cjorton if (!silent_mode && ttyfd >= 0)
0797faae937515a5225a36db4a1ec79480d2555cjorton loop_write(ttyfd, "*", 1, false);
0797faae937515a5225a36db4a1ec79480d2555cjorton
0797faae937515a5225a36db4a1ec79480d2555cjorton dirty = true;
a10d8ce69c26142323c66adaba109be1b4baa379wrowe }
a10d8ce69c26142323c66adaba109be1b4baa379wrowe }
0797faae937515a5225a36db4a1ec79480d2555cjorton
0797faae937515a5225a36db4a1ec79480d2555cjorton x = strndup(passphrase, p);
0797faae937515a5225a36db4a1ec79480d2555cjorton if (!x) {
0797faae937515a5225a36db4a1ec79480d2555cjorton r = -ENOMEM;
0797faae937515a5225a36db4a1ec79480d2555cjorton goto finish;
eab15974b1d8bbcb6d4f9ec75527b39ffded82aajorton }
0797faae937515a5225a36db4a1ec79480d2555cjorton
eab15974b1d8bbcb6d4f9ec75527b39ffded82aajorton *_passphrase = x;
0797faae937515a5225a36db4a1ec79480d2555cjorton r = 0;
0797faae937515a5225a36db4a1ec79480d2555cjorton
0797faae937515a5225a36db4a1ec79480d2555cjortonfinish:
0797faae937515a5225a36db4a1ec79480d2555cjorton if (ttyfd >= 0 && reset_tty) {
0797faae937515a5225a36db4a1ec79480d2555cjorton loop_write(ttyfd, "\n", 1, false);
0797faae937515a5225a36db4a1ec79480d2555cjorton tcsetattr(ttyfd, TCSADRAIN, &old_termios);
0797faae937515a5225a36db4a1ec79480d2555cjorton }
eab15974b1d8bbcb6d4f9ec75527b39ffded82aajorton
0797faae937515a5225a36db4a1ec79480d2555cjorton return r;
0797faae937515a5225a36db4a1ec79480d2555cjorton}
0797faae937515a5225a36db4a1ec79480d2555cjorton
0797faae937515a5225a36db4a1ec79480d2555cjortonstatic int create_socket(char **name) {
0797faae937515a5225a36db4a1ec79480d2555cjorton int fd;
0797faae937515a5225a36db4a1ec79480d2555cjorton union {
0797faae937515a5225a36db4a1ec79480d2555cjorton struct sockaddr sa;
0797faae937515a5225a36db4a1ec79480d2555cjorton struct sockaddr_un un;
0797faae937515a5225a36db4a1ec79480d2555cjorton } sa = {
0797faae937515a5225a36db4a1ec79480d2555cjorton .un.sun_family = AF_UNIX,
0797faae937515a5225a36db4a1ec79480d2555cjorton };
0797faae937515a5225a36db4a1ec79480d2555cjorton int one = 1;
0797faae937515a5225a36db4a1ec79480d2555cjorton int r = 0;
0797faae937515a5225a36db4a1ec79480d2555cjorton char *c;
0797faae937515a5225a36db4a1ec79480d2555cjorton
0797faae937515a5225a36db4a1ec79480d2555cjorton assert(name);
072f7e449a76d28b580de6e89a1723713ab9adb1jorton
072f7e449a76d28b580de6e89a1723713ab9adb1jorton fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
072f7e449a76d28b580de6e89a1723713ab9adb1jorton if (fd < 0) {
072f7e449a76d28b580de6e89a1723713ab9adb1jorton log_error("socket() failed: %m");
0797faae937515a5225a36db4a1ec79480d2555cjorton return -errno;
0797faae937515a5225a36db4a1ec79480d2555cjorton }
0797faae937515a5225a36db4a1ec79480d2555cjorton
0797faae937515a5225a36db4a1ec79480d2555cjorton snprintf(sa.un.sun_path, sizeof(sa.un.sun_path)-1, "/run/systemd/ask-password/sck.%" PRIx64, random_u64());
0797faae937515a5225a36db4a1ec79480d2555cjorton
a10d8ce69c26142323c66adaba109be1b4baa379wrowe RUN_WITH_UMASK(0177) {
a10d8ce69c26142323c66adaba109be1b4baa379wrowe r = bind(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path));
0797faae937515a5225a36db4a1ec79480d2555cjorton }
0797faae937515a5225a36db4a1ec79480d2555cjorton
0797faae937515a5225a36db4a1ec79480d2555cjorton if (r < 0) {
0797faae937515a5225a36db4a1ec79480d2555cjorton r = -errno;
0797faae937515a5225a36db4a1ec79480d2555cjorton log_error("bind() failed: %m");
0797faae937515a5225a36db4a1ec79480d2555cjorton goto fail;
0797faae937515a5225a36db4a1ec79480d2555cjorton }
0797faae937515a5225a36db4a1ec79480d2555cjorton
0797faae937515a5225a36db4a1ec79480d2555cjorton if (setsockopt(fd, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one)) < 0) {
0797faae937515a5225a36db4a1ec79480d2555cjorton r = -errno;
0797faae937515a5225a36db4a1ec79480d2555cjorton log_error("SO_PASSCRED failed: %m");
0797faae937515a5225a36db4a1ec79480d2555cjorton goto fail;
0797faae937515a5225a36db4a1ec79480d2555cjorton }
0797faae937515a5225a36db4a1ec79480d2555cjorton
0797faae937515a5225a36db4a1ec79480d2555cjorton c = strdup(sa.un.sun_path);
eab15974b1d8bbcb6d4f9ec75527b39ffded82aajorton if (!c) {
0797faae937515a5225a36db4a1ec79480d2555cjorton r = log_oom();
eab15974b1d8bbcb6d4f9ec75527b39ffded82aajorton goto fail;
0797faae937515a5225a36db4a1ec79480d2555cjorton }
0797faae937515a5225a36db4a1ec79480d2555cjorton
0797faae937515a5225a36db4a1ec79480d2555cjorton *name = c;
0797faae937515a5225a36db4a1ec79480d2555cjorton return fd;
0797faae937515a5225a36db4a1ec79480d2555cjorton
0797faae937515a5225a36db4a1ec79480d2555cjortonfail:
0797faae937515a5225a36db4a1ec79480d2555cjorton safe_close(fd);
70003ce816d7851e49ecb0cdc5137becd647ed18niq
0797faae937515a5225a36db4a1ec79480d2555cjorton return r;
a10d8ce69c26142323c66adaba109be1b4baa379wrowe}
0797faae937515a5225a36db4a1ec79480d2555cjorton
0797faae937515a5225a36db4a1ec79480d2555cjortonint ask_password_agent(
0797faae937515a5225a36db4a1ec79480d2555cjorton const char *message,
0797faae937515a5225a36db4a1ec79480d2555cjorton const char *icon,
0797faae937515a5225a36db4a1ec79480d2555cjorton usec_t until,
a10d8ce69c26142323c66adaba109be1b4baa379wrowe bool accept_cached,
0797faae937515a5225a36db4a1ec79480d2555cjorton char ***_passphrases) {
0797faae937515a5225a36db4a1ec79480d2555cjorton
0797faae937515a5225a36db4a1ec79480d2555cjorton enum {
0797faae937515a5225a36db4a1ec79480d2555cjorton FD_SOCKET,
0797faae937515a5225a36db4a1ec79480d2555cjorton FD_SIGNAL,
0797faae937515a5225a36db4a1ec79480d2555cjorton _FD_MAX
a10d8ce69c26142323c66adaba109be1b4baa379wrowe };
a10d8ce69c26142323c66adaba109be1b4baa379wrowe
0797faae937515a5225a36db4a1ec79480d2555cjorton char temp[] = "/run/systemd/ask-password/tmp.XXXXXX";
0797faae937515a5225a36db4a1ec79480d2555cjorton char final[sizeof(temp)] = "";
0797faae937515a5225a36db4a1ec79480d2555cjorton _cleanup_fclose_ FILE *f = NULL;
0797faae937515a5225a36db4a1ec79480d2555cjorton _cleanup_free_ char *socket_name = NULL;
a10d8ce69c26142323c66adaba109be1b4baa379wrowe _cleanup_close_ int socket_fd = -1, signal_fd = -1, fd = -1;
0797faae937515a5225a36db4a1ec79480d2555cjorton sigset_t mask, oldmask;
0797faae937515a5225a36db4a1ec79480d2555cjorton struct pollfd pollfd[_FD_MAX];
0797faae937515a5225a36db4a1ec79480d2555cjorton int r;
0797faae937515a5225a36db4a1ec79480d2555cjorton
0797faae937515a5225a36db4a1ec79480d2555cjorton assert(_passphrases);
0797faae937515a5225a36db4a1ec79480d2555cjorton
0797faae937515a5225a36db4a1ec79480d2555cjorton assert_se(sigemptyset(&mask) == 0);
0797faae937515a5225a36db4a1ec79480d2555cjorton sigset_add_many(&mask, SIGINT, SIGTERM, -1);
501e60e433e1914c64f642114fbb4fb9be9e2ca9jorton assert_se(sigprocmask(SIG_BLOCK, &mask, &oldmask) == 0);
501e60e433e1914c64f642114fbb4fb9be9e2ca9jorton
501e60e433e1914c64f642114fbb4fb9be9e2ca9jorton mkdir_p_label("/run/systemd/ask-password", 0755);
0797faae937515a5225a36db4a1ec79480d2555cjorton
0797faae937515a5225a36db4a1ec79480d2555cjorton fd = mkostemp_safe(temp, O_WRONLY|O_CLOEXEC);
0797faae937515a5225a36db4a1ec79480d2555cjorton if (fd < 0) {
0797faae937515a5225a36db4a1ec79480d2555cjorton log_error("Failed to create password file: %m");
0797faae937515a5225a36db4a1ec79480d2555cjorton r = -errno;
0797faae937515a5225a36db4a1ec79480d2555cjorton goto finish;
0797faae937515a5225a36db4a1ec79480d2555cjorton }
0797faae937515a5225a36db4a1ec79480d2555cjorton
0797faae937515a5225a36db4a1ec79480d2555cjorton fchmod(fd, 0644);
0797faae937515a5225a36db4a1ec79480d2555cjorton
0797faae937515a5225a36db4a1ec79480d2555cjorton f = fdopen(fd, "w");
0797faae937515a5225a36db4a1ec79480d2555cjorton if (!f) {
0797faae937515a5225a36db4a1ec79480d2555cjorton log_error("Failed to allocate FILE: %m");
eab15974b1d8bbcb6d4f9ec75527b39ffded82aajorton r = -errno;
0797faae937515a5225a36db4a1ec79480d2555cjorton goto finish;
eab15974b1d8bbcb6d4f9ec75527b39ffded82aajorton }
0797faae937515a5225a36db4a1ec79480d2555cjorton
0797faae937515a5225a36db4a1ec79480d2555cjorton fd = -1;
501e60e433e1914c64f642114fbb4fb9be9e2ca9jorton
0797faae937515a5225a36db4a1ec79480d2555cjorton signal_fd = signalfd(-1, &mask, SFD_NONBLOCK|SFD_CLOEXEC);
0797faae937515a5225a36db4a1ec79480d2555cjorton if (signal_fd < 0) {
0797faae937515a5225a36db4a1ec79480d2555cjorton log_error("signalfd(): %m");
0797faae937515a5225a36db4a1ec79480d2555cjorton r = -errno;
501e60e433e1914c64f642114fbb4fb9be9e2ca9jorton goto finish;
0797faae937515a5225a36db4a1ec79480d2555cjorton }
0797faae937515a5225a36db4a1ec79480d2555cjorton
2685f3814b77577ef7b2523442dab1ca88df1e41jorton socket_fd = create_socket(&socket_name);
0797faae937515a5225a36db4a1ec79480d2555cjorton if (socket_fd < 0) {
0797faae937515a5225a36db4a1ec79480d2555cjorton r = socket_fd;
0797faae937515a5225a36db4a1ec79480d2555cjorton goto finish;
0797faae937515a5225a36db4a1ec79480d2555cjorton }
a10d8ce69c26142323c66adaba109be1b4baa379wrowe
a10d8ce69c26142323c66adaba109be1b4baa379wrowe fprintf(f,
a10d8ce69c26142323c66adaba109be1b4baa379wrowe "[Ask]\n"
a10d8ce69c26142323c66adaba109be1b4baa379wrowe "PID=%lu\n"
0797faae937515a5225a36db4a1ec79480d2555cjorton "Socket=%s\n"
0797faae937515a5225a36db4a1ec79480d2555cjorton "AcceptCached=%i\n"
0797faae937515a5225a36db4a1ec79480d2555cjorton "NotAfter=%llu\n",
a10d8ce69c26142323c66adaba109be1b4baa379wrowe (unsigned long) getpid(),
0797faae937515a5225a36db4a1ec79480d2555cjorton socket_name,
0797faae937515a5225a36db4a1ec79480d2555cjorton accept_cached ? 1 : 0,
0797faae937515a5225a36db4a1ec79480d2555cjorton (unsigned long long) until);
a10d8ce69c26142323c66adaba109be1b4baa379wrowe
a10d8ce69c26142323c66adaba109be1b4baa379wrowe if (message)
0797faae937515a5225a36db4a1ec79480d2555cjorton fprintf(f, "Message=%s\n", message);
3e7ce568813f1895b2e8e68e2223653884497bdawrowe
0797faae937515a5225a36db4a1ec79480d2555cjorton if (icon)
a10d8ce69c26142323c66adaba109be1b4baa379wrowe fprintf(f, "Icon=%s\n", icon);
0797faae937515a5225a36db4a1ec79480d2555cjorton
0797faae937515a5225a36db4a1ec79480d2555cjorton fflush(f);
0797faae937515a5225a36db4a1ec79480d2555cjorton
a10d8ce69c26142323c66adaba109be1b4baa379wrowe if (ferror(f)) {
0797faae937515a5225a36db4a1ec79480d2555cjorton log_error("Failed to write query file: %m");
0797faae937515a5225a36db4a1ec79480d2555cjorton r = -errno;
0797faae937515a5225a36db4a1ec79480d2555cjorton goto finish;
0797faae937515a5225a36db4a1ec79480d2555cjorton }
0797faae937515a5225a36db4a1ec79480d2555cjorton
0797faae937515a5225a36db4a1ec79480d2555cjorton memcpy(final, temp, sizeof(temp));
0797faae937515a5225a36db4a1ec79480d2555cjorton
0797faae937515a5225a36db4a1ec79480d2555cjorton final[sizeof(final)-11] = 'a';
0797faae937515a5225a36db4a1ec79480d2555cjorton final[sizeof(final)-10] = 's';
0797faae937515a5225a36db4a1ec79480d2555cjorton final[sizeof(final)-9] = 'k';
0797faae937515a5225a36db4a1ec79480d2555cjorton
0797faae937515a5225a36db4a1ec79480d2555cjorton if (rename(temp, final) < 0) {
0797faae937515a5225a36db4a1ec79480d2555cjorton log_error("Failed to rename query file: %m");
0797faae937515a5225a36db4a1ec79480d2555cjorton r = -errno;
0797faae937515a5225a36db4a1ec79480d2555cjorton goto finish;
0797faae937515a5225a36db4a1ec79480d2555cjorton }
0797faae937515a5225a36db4a1ec79480d2555cjorton
0797faae937515a5225a36db4a1ec79480d2555cjorton zero(pollfd);
0797faae937515a5225a36db4a1ec79480d2555cjorton pollfd[FD_SOCKET].fd = socket_fd;
0797faae937515a5225a36db4a1ec79480d2555cjorton pollfd[FD_SOCKET].events = POLLIN;
0797faae937515a5225a36db4a1ec79480d2555cjorton pollfd[FD_SIGNAL].fd = signal_fd;
0797faae937515a5225a36db4a1ec79480d2555cjorton pollfd[FD_SIGNAL].events = POLLIN;
0797faae937515a5225a36db4a1ec79480d2555cjorton
0797faae937515a5225a36db4a1ec79480d2555cjorton for (;;) {
0797faae937515a5225a36db4a1ec79480d2555cjorton char passphrase[LINE_MAX+1];
eab15974b1d8bbcb6d4f9ec75527b39ffded82aajorton struct msghdr msghdr;
0797faae937515a5225a36db4a1ec79480d2555cjorton struct iovec iovec;
eab15974b1d8bbcb6d4f9ec75527b39ffded82aajorton struct ucred *ucred;
0797faae937515a5225a36db4a1ec79480d2555cjorton union {
0797faae937515a5225a36db4a1ec79480d2555cjorton struct cmsghdr cmsghdr;
0797faae937515a5225a36db4a1ec79480d2555cjorton uint8_t buf[CMSG_SPACE(sizeof(struct ucred))];
0797faae937515a5225a36db4a1ec79480d2555cjorton } control;
0797faae937515a5225a36db4a1ec79480d2555cjorton ssize_t n;
0797faae937515a5225a36db4a1ec79480d2555cjorton int k;
a10d8ce69c26142323c66adaba109be1b4baa379wrowe usec_t t;
a10d8ce69c26142323c66adaba109be1b4baa379wrowe
0797faae937515a5225a36db4a1ec79480d2555cjorton t = now(CLOCK_MONOTONIC);
a10d8ce69c26142323c66adaba109be1b4baa379wrowe
a10d8ce69c26142323c66adaba109be1b4baa379wrowe if (until > 0 && until <= t) {
0797faae937515a5225a36db4a1ec79480d2555cjorton log_notice("Timed out");
a10d8ce69c26142323c66adaba109be1b4baa379wrowe r = -ETIME;
a10d8ce69c26142323c66adaba109be1b4baa379wrowe goto finish;
a10d8ce69c26142323c66adaba109be1b4baa379wrowe }
0797faae937515a5225a36db4a1ec79480d2555cjorton
a10d8ce69c26142323c66adaba109be1b4baa379wrowe k = poll(pollfd, _FD_MAX, until > 0 ? (int) ((until-t)/USEC_PER_MSEC) : -1);
0797faae937515a5225a36db4a1ec79480d2555cjorton if (k < 0) {
0797faae937515a5225a36db4a1ec79480d2555cjorton if (errno == EINTR)
0797faae937515a5225a36db4a1ec79480d2555cjorton continue;
0797faae937515a5225a36db4a1ec79480d2555cjorton
0797faae937515a5225a36db4a1ec79480d2555cjorton log_error("poll() failed: %m");
0797faae937515a5225a36db4a1ec79480d2555cjorton r = -errno;
0797faae937515a5225a36db4a1ec79480d2555cjorton goto finish;
0797faae937515a5225a36db4a1ec79480d2555cjorton }
0797faae937515a5225a36db4a1ec79480d2555cjorton
0797faae937515a5225a36db4a1ec79480d2555cjorton if (k <= 0) {
0797faae937515a5225a36db4a1ec79480d2555cjorton log_notice("Timed out");
0797faae937515a5225a36db4a1ec79480d2555cjorton r = -ETIME;
0797faae937515a5225a36db4a1ec79480d2555cjorton goto finish;
eab15974b1d8bbcb6d4f9ec75527b39ffded82aajorton }
0797faae937515a5225a36db4a1ec79480d2555cjorton
eab15974b1d8bbcb6d4f9ec75527b39ffded82aajorton if (pollfd[FD_SIGNAL].revents & POLLIN) {
0797faae937515a5225a36db4a1ec79480d2555cjorton r = -EINTR;
0797faae937515a5225a36db4a1ec79480d2555cjorton goto finish;
0797faae937515a5225a36db4a1ec79480d2555cjorton }
0797faae937515a5225a36db4a1ec79480d2555cjorton
0797faae937515a5225a36db4a1ec79480d2555cjorton if (pollfd[FD_SOCKET].revents != POLLIN) {
0797faae937515a5225a36db4a1ec79480d2555cjorton log_error("Unexpected poll() event.");
a10d8ce69c26142323c66adaba109be1b4baa379wrowe r = -EIO;
0797faae937515a5225a36db4a1ec79480d2555cjorton goto finish;
0797faae937515a5225a36db4a1ec79480d2555cjorton }
0797faae937515a5225a36db4a1ec79480d2555cjorton
0797faae937515a5225a36db4a1ec79480d2555cjorton zero(iovec);
0797faae937515a5225a36db4a1ec79480d2555cjorton iovec.iov_base = passphrase;
0797faae937515a5225a36db4a1ec79480d2555cjorton iovec.iov_len = sizeof(passphrase);
0797faae937515a5225a36db4a1ec79480d2555cjorton
0797faae937515a5225a36db4a1ec79480d2555cjorton zero(control);
8aac9d0a02da972909738eb84a5902199f3298cftrawick zero(msghdr);
0797faae937515a5225a36db4a1ec79480d2555cjorton msghdr.msg_iov = &iovec;
a10d8ce69c26142323c66adaba109be1b4baa379wrowe msghdr.msg_iovlen = 1;
0797faae937515a5225a36db4a1ec79480d2555cjorton msghdr.msg_control = &control;
0797faae937515a5225a36db4a1ec79480d2555cjorton msghdr.msg_controllen = sizeof(control);
2685f3814b77577ef7b2523442dab1ca88df1e41jorton
2685f3814b77577ef7b2523442dab1ca88df1e41jorton n = recvmsg(socket_fd, &msghdr, 0);
0797faae937515a5225a36db4a1ec79480d2555cjorton if (n < 0) {
0797faae937515a5225a36db4a1ec79480d2555cjorton if (errno == EAGAIN ||
0797faae937515a5225a36db4a1ec79480d2555cjorton errno == EINTR)
0797faae937515a5225a36db4a1ec79480d2555cjorton continue;
a10d8ce69c26142323c66adaba109be1b4baa379wrowe
a10d8ce69c26142323c66adaba109be1b4baa379wrowe log_error("recvmsg() failed: %m");
a10d8ce69c26142323c66adaba109be1b4baa379wrowe r = -errno;
0797faae937515a5225a36db4a1ec79480d2555cjorton goto finish;
0797faae937515a5225a36db4a1ec79480d2555cjorton }
a10d8ce69c26142323c66adaba109be1b4baa379wrowe
a10d8ce69c26142323c66adaba109be1b4baa379wrowe if (n <= 0) {
0797faae937515a5225a36db4a1ec79480d2555cjorton log_error("Message too short");
0797faae937515a5225a36db4a1ec79480d2555cjorton continue;
0797faae937515a5225a36db4a1ec79480d2555cjorton }
eab15974b1d8bbcb6d4f9ec75527b39ffded82aajorton
0797faae937515a5225a36db4a1ec79480d2555cjorton if (msghdr.msg_controllen < CMSG_LEN(sizeof(struct ucred)) ||
eab15974b1d8bbcb6d4f9ec75527b39ffded82aajorton control.cmsghdr.cmsg_level != SOL_SOCKET ||
0797faae937515a5225a36db4a1ec79480d2555cjorton control.cmsghdr.cmsg_type != SCM_CREDENTIALS ||
0797faae937515a5225a36db4a1ec79480d2555cjorton control.cmsghdr.cmsg_len != CMSG_LEN(sizeof(struct ucred))) {
0797faae937515a5225a36db4a1ec79480d2555cjorton log_warning("Received message without credentials. Ignoring.");
0797faae937515a5225a36db4a1ec79480d2555cjorton continue;
0797faae937515a5225a36db4a1ec79480d2555cjorton }
0797faae937515a5225a36db4a1ec79480d2555cjorton
0797faae937515a5225a36db4a1ec79480d2555cjorton ucred = (struct ucred*) CMSG_DATA(&control.cmsghdr);
0797faae937515a5225a36db4a1ec79480d2555cjorton if (ucred->uid != 0) {
0797faae937515a5225a36db4a1ec79480d2555cjorton log_warning("Got request from unprivileged user. Ignoring.");
0797faae937515a5225a36db4a1ec79480d2555cjorton continue;
0797faae937515a5225a36db4a1ec79480d2555cjorton }
0797faae937515a5225a36db4a1ec79480d2555cjorton
a10d8ce69c26142323c66adaba109be1b4baa379wrowe if (passphrase[0] == '+') {
a10d8ce69c26142323c66adaba109be1b4baa379wrowe char **l;
0797faae937515a5225a36db4a1ec79480d2555cjorton
0797faae937515a5225a36db4a1ec79480d2555cjorton if (n == 1)
a10d8ce69c26142323c66adaba109be1b4baa379wrowe l = strv_new("", NULL);
a10d8ce69c26142323c66adaba109be1b4baa379wrowe else
0797faae937515a5225a36db4a1ec79480d2555cjorton l = strv_parse_nulstr(passphrase+1, n-1);
a10d8ce69c26142323c66adaba109be1b4baa379wrowe /* An empty message refers to the empty password */
0797faae937515a5225a36db4a1ec79480d2555cjorton
a10d8ce69c26142323c66adaba109be1b4baa379wrowe if (!l) {
a10d8ce69c26142323c66adaba109be1b4baa379wrowe r = -ENOMEM;
0797faae937515a5225a36db4a1ec79480d2555cjorton goto finish;
0797faae937515a5225a36db4a1ec79480d2555cjorton }
0797faae937515a5225a36db4a1ec79480d2555cjorton
250fbbb51225da0dfc973743b795b04dc9740027wrowe if (strv_length(l) <= 0) {
cf25139efeb705911e931b68a521d8b65ff922eewrowe strv_free(l);
bd2f929f6974a82e4fd33e0393d2b0c91f6f033atrawick log_error("Invalid packet");
bd2f929f6974a82e4fd33e0393d2b0c91f6f033atrawick continue;
a10d8ce69c26142323c66adaba109be1b4baa379wrowe }
250fbbb51225da0dfc973743b795b04dc9740027wrowe
250fbbb51225da0dfc973743b795b04dc9740027wrowe *_passphrases = l;
250fbbb51225da0dfc973743b795b04dc9740027wrowe
250fbbb51225da0dfc973743b795b04dc9740027wrowe } else if (passphrase[0] == '-') {
250fbbb51225da0dfc973743b795b04dc9740027wrowe r = -ECANCELED;
250fbbb51225da0dfc973743b795b04dc9740027wrowe goto finish;
250fbbb51225da0dfc973743b795b04dc9740027wrowe } else {
250fbbb51225da0dfc973743b795b04dc9740027wrowe log_error("Invalid packet");
250fbbb51225da0dfc973743b795b04dc9740027wrowe continue;
3e7ce568813f1895b2e8e68e2223653884497bdawrowe }
250fbbb51225da0dfc973743b795b04dc9740027wrowe
3e7ce568813f1895b2e8e68e2223653884497bdawrowe break;
250fbbb51225da0dfc973743b795b04dc9740027wrowe }
250fbbb51225da0dfc973743b795b04dc9740027wrowe
250fbbb51225da0dfc973743b795b04dc9740027wrowe r = 0;
250fbbb51225da0dfc973743b795b04dc9740027wrowe
250fbbb51225da0dfc973743b795b04dc9740027wrowefinish:
250fbbb51225da0dfc973743b795b04dc9740027wrowe if (socket_name)
250fbbb51225da0dfc973743b795b04dc9740027wrowe unlink(socket_name);
250fbbb51225da0dfc973743b795b04dc9740027wrowe
250fbbb51225da0dfc973743b795b04dc9740027wrowe unlink(temp);
250fbbb51225da0dfc973743b795b04dc9740027wrowe
250fbbb51225da0dfc973743b795b04dc9740027wrowe if (final[0])
250fbbb51225da0dfc973743b795b04dc9740027wrowe unlink(final);
250fbbb51225da0dfc973743b795b04dc9740027wrowe
250fbbb51225da0dfc973743b795b04dc9740027wrowe assert_se(sigprocmask(SIG_SETMASK, &oldmask, NULL) == 0);
250fbbb51225da0dfc973743b795b04dc9740027wrowe
250fbbb51225da0dfc973743b795b04dc9740027wrowe return r;
250fbbb51225da0dfc973743b795b04dc9740027wrowe}
250fbbb51225da0dfc973743b795b04dc9740027wrowe
250fbbb51225da0dfc973743b795b04dc9740027wroweint ask_password_auto(const char *message, const char *icon, usec_t until, bool accept_cached, char ***_passphrases) {
cf25139efeb705911e931b68a521d8b65ff922eewrowe assert(message);
cf25139efeb705911e931b68a521d8b65ff922eewrowe assert(_passphrases);
250fbbb51225da0dfc973743b795b04dc9740027wrowe
250fbbb51225da0dfc973743b795b04dc9740027wrowe if (isatty(STDIN_FILENO)) {
250fbbb51225da0dfc973743b795b04dc9740027wrowe int r;
250fbbb51225da0dfc973743b795b04dc9740027wrowe char *s = NULL, **l = NULL;
250fbbb51225da0dfc973743b795b04dc9740027wrowe
250fbbb51225da0dfc973743b795b04dc9740027wrowe r = ask_password_tty(message, until, NULL, &s);
250fbbb51225da0dfc973743b795b04dc9740027wrowe if (r < 0)
250fbbb51225da0dfc973743b795b04dc9740027wrowe return r;
250fbbb51225da0dfc973743b795b04dc9740027wrowe
250fbbb51225da0dfc973743b795b04dc9740027wrowe r = strv_consume(&l, s);
250fbbb51225da0dfc973743b795b04dc9740027wrowe if (r < 0)
250fbbb51225da0dfc973743b795b04dc9740027wrowe return r;
250fbbb51225da0dfc973743b795b04dc9740027wrowe
250fbbb51225da0dfc973743b795b04dc9740027wrowe *_passphrases = l;
250fbbb51225da0dfc973743b795b04dc9740027wrowe return r;
250fbbb51225da0dfc973743b795b04dc9740027wrowe } else
250fbbb51225da0dfc973743b795b04dc9740027wrowe return ask_password_agent(message, icon, until, accept_cached, _passphrases);
250fbbb51225da0dfc973743b795b04dc9740027wrowe}
250fbbb51225da0dfc973743b795b04dc9740027wrowe