#include <fcntl.h>
#include <inttypes.h>
#include <limits.h>
-#include <poll.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include "alloc-util.h"
#include "ask-password-api.h"
-#include "def.h"
+#include "constants.h"
+#include "creds-util.h"
#include "fd-util.h"
#include "fileio.h"
#include "format-util.h"
#include "fs-util.h"
+#include "glyph-util.h"
#include "io-util.h"
-#include "locale-util.h"
+#include "keyring-util.h"
#include "log.h"
#include "macro.h"
#include "memory-util.h"
#include "missing_syscall.h"
-#include "mkdir.h"
+#include "mkdir-label.h"
+#include "nulstr-util.h"
#include "process-util.h"
#include "random-util.h"
#include "signal-util.h"
}
static int retrieve_key(key_serial_t serial, char ***ret) {
- size_t nfinal, m = 100;
+ _cleanup_(erase_and_freep) void *p = NULL;
char **l;
- _cleanup_(erase_and_freep) char *pfinal = NULL;
+ size_t n;
+ int r;
assert(ret);
- for (;;) {
- _cleanup_(erase_and_freep) char *p = NULL;
- long n;
-
- p = new(char, m);
- if (!p)
- return -ENOMEM;
-
- n = keyctl(KEYCTL_READ, (unsigned long) serial, (unsigned long) p, (unsigned long) m, 0);
- if (n < 0)
- return -errno;
- if ((size_t) n <= m) {
- nfinal = (size_t) n;
- pfinal = TAKE_PTR(p);
- break;
- }
-
- if (m > LONG_MAX / 2) /* overflow check */
- return -ENOMEM;
- m *= 2;
- }
+ r = keyring_read(serial, &p, &n);
+ if (r < 0)
+ return r;
- l = strv_parse_nulstr(pfinal, nfinal);
+ l = strv_parse_nulstr(p, n);
if (!l)
return -ENOMEM;
assert(keyname);
- if (!(flags & ASK_PASSWORD_PUSH_CACHE))
+ if (!FLAGS_SET(flags, ASK_PASSWORD_PUSH_CACHE))
return 0;
if (strv_isempty(passwords))
return 0;
if (r < 0)
return r;
+ /* chop off the final NUL byte. We do this because we want to use the separator NUL bytes only if we
+ * have multiple passwords. */
+ n = LESS_BY(n, (size_t) 1);
+
serial = add_key("user", keyname, p, n, KEY_SPEC_USER_KEYRING);
if (serial == -1)
return -errno;
assert(keyname);
assert(ret);
- if (!(flags & ASK_PASSWORD_ACCEPT_CACHED))
+ if (!FLAGS_SET(flags, ASK_PASSWORD_ACCEPT_CACHED))
return -EUNATCH;
r = lookup_key(keyname, &serial);
- if (ERRNO_IS_NOT_SUPPORTED(r) || r == -EPERM) /* when retrieving the distinction between "kernel or
- * container manager don't support or allow this" and
- * "no matching key known" doesn't matter. Note that we
- * propagate EACCESS here (even if EPERM not) since
- * that is used if the keyring is available but we lack
- * access to the key. */
- return -ENOKEY;
- if (r < 0)
+ if (r < 0) {
+ /* when retrieving the distinction between "kernel or container manager don't support
+ * or allow this" and "no matching key known" doesn't matter. Note that we propagate
+ * EACCESS here (even if EPERM not) since that is used if the keyring is available but
+ * we lack access to the key. */
+ if (ERRNO_IS_NOT_SUPPORTED(r) || r == -EPERM)
+ return -ENOKEY;
+
return r;
+ }
return retrieve_key(serial, ret);
}
return 0;
size_t m = utf8_n_codepoints(str);
- if (m == (size_t) -1)
+ if (m == SIZE_MAX)
m = strlen(str); /* Not a valid UTF-8 string? If so, let's backspace the number of bytes
* output. Most likely this happened because we are not in an UTF-8 locale,
* and in that case that is the correct thing to do. And even if it's not,
char ***ret) {
static const union sockaddr_union sa = PLYMOUTH_SOCKET;
- _cleanup_close_ int fd = -1, notify = -1;
+ _cleanup_close_ int fd = -EBADF, notify = -EBADF;
_cleanup_free_ char *packet = NULL;
ssize_t k;
int r, n;
if (notify < 0)
return -errno;
- r = inotify_add_watch(notify, flag_file, IN_ATTRIB); /* for the link count */
- if (r < 0)
+ if (inotify_add_watch(notify, flag_file, IN_ATTRIB) < 0) /* for the link count */
return -errno;
}
if (fd < 0)
return -errno;
- r = connect(fd, &sa.sa, SOCKADDR_UN_LEN(sa.un));
- if (r < 0)
+ if (connect(fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)) < 0)
return -errno;
- if (flags & ASK_PASSWORD_ACCEPT_CACHED) {
+ if (FLAGS_SET(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)
if (r < 0)
return r;
+ CLEANUP_ERASE(buffer);
+
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);
- }
+ usec_t timeout;
- 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;
+ if (until > 0)
+ timeout = usec_sub_unsigned(until, now(CLOCK_MONOTONIC));
+ else
+ timeout = USEC_INFINITY;
- r = -errno;
- goto finish;
- } else if (j == 0) {
- r = -ETIME;
- goto finish;
- }
+ if (flag_file && access(flag_file, F_OK) < 0)
+ return -errno;
- if (pollfd[POLL_SOCKET].revents & POLLNVAL ||
- (notify >= 0 && pollfd[POLL_INOTIFY].revents & POLLNVAL)) {
- r = -EBADF;
- goto finish;
- }
+ r = ppoll_usec(pollfd, notify >= 0 ? 2 : 1, timeout);
+ if (r == -EINTR)
+ continue;
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return -ETIME;
if (notify >= 0 && pollfd[POLL_INOTIFY].revents != 0)
(void) flush_fd(notify);
k = read(fd, buffer + p, sizeof(buffer) - p);
if (k < 0) {
- if (IN_SET(errno, EINTR, EAGAIN))
+ if (ERRNO_IS_TRANSIENT(errno))
continue;
- r = -errno;
- goto finish;
- } else if (k == 0) {
- r = -EIO;
- goto finish;
+ return -errno;
}
+ if (k == 0)
+ return -EIO;
p += k;
if (buffer[0] == 5) {
- if (flags & ASK_PASSWORD_ACCEPT_CACHED) {
+ if (FLAGS_SET(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;
- }
+ if (asprintf(&packet, "*\002%c%s%n", (int) (strlen(message) + 1), message, &n) < 0)
+ return -ENOMEM;
r = loop_write(fd, packet, n+1, true);
if (r < 0)
- goto finish;
+ return r;
flags &= ~ASK_PASSWORD_ACCEPT_CACHED;
p = 0;
}
/* No password, because UI not shown */
- r = -ENOENT;
- goto finish;
+ return -ENOENT;
} else if (IN_SET(buffer[0], 2, 9)) {
uint32_t size;
memcpy(&size, buffer+1, sizeof(size));
size = le32toh(size);
- if (size + 5 > sizeof(buffer)) {
- r = -EIO;
- goto finish;
- }
+ if (size + 5 > sizeof(buffer))
+ return -EIO;
if (p-5 < size)
continue;
l = strv_parse_nulstr(buffer + 5, size);
- if (!l) {
- r = -ENOMEM;
- goto finish;
- }
+ if (!l)
+ return -ENOMEM;
*ret = l;
break;
- } else {
+ } else
/* Unknown packet */
- r = -EIO;
- goto finish;
- }
+ return -EIO;
}
- r = 0;
-
-finish:
- explicit_bzero_safe(buffer, sizeof(buffer));
- return r;
+ return 0;
}
#define NO_ECHO "(no echo) "
};
bool reset_tty = false, dirty = false, use_color = false, press_tab_visible = false;
- _cleanup_close_ int cttyfd = -1, notify = -1;
+ _cleanup_close_ int cttyfd = -EBADF, notify = -EBADF;
struct termios old_termios, new_termios;
char passphrase[LINE_MAX + 1] = {}, *x;
_cleanup_strv_free_erase_ char **l = NULL;
assert(ret);
- if (flags & ASK_PASSWORD_NO_TTY)
+ if (FLAGS_SET(flags, ASK_PASSWORD_NO_TTY))
return -EUNATCH;
if (!message)
message = "Password:";
- if (emoji_enabled())
+ if (!FLAGS_SET(flags, ASK_PASSWORD_HIDE_EMOJI) && emoji_enabled())
message = strjoina(special_glyph(SPECIAL_GLYPH_LOCK_AND_KEY), " ", message);
- if (flag_file || ((flags & ASK_PASSWORD_ACCEPT_CACHED) && keyname)) {
+ if (flag_file || (FLAGS_SET(flags, ASK_PASSWORD_ACCEPT_CACHED) && keyname)) {
notify = inotify_init1(IN_CLOEXEC|IN_NONBLOCK);
if (notify < 0)
return -errno;
if (inotify_add_watch(notify, flag_file, IN_ATTRIB /* for the link count */) < 0)
return -errno;
}
- if ((flags & ASK_PASSWORD_ACCEPT_CACHED) && keyname) {
+ if (FLAGS_SET(flags, ASK_PASSWORD_ACCEPT_CACHED) && keyname) {
r = ask_password_keyring(keyname, flags, ret);
if (r >= 0)
return 0;
return -errno;
}
+ CLEANUP_ERASE(passphrase);
+
/* If the caller didn't specify a TTY, then use the controlling tty, if we can. */
if (ttyfd < 0)
ttyfd = cttyfd = open("/dev/tty", O_RDWR|O_NOCTTY|O_CLOEXEC);
if (tcgetattr(ttyfd, &old_termios) < 0)
return -errno;
- if (flags & ASK_PASSWORD_CONSOLE_COLOR)
+ if (FLAGS_SET(flags, ASK_PASSWORD_CONSOLE_COLOR))
use_color = dev_console_colors_enabled();
else
use_color = colors_enabled();
(void) loop_write(ttyfd, message, strlen(message), false);
(void) loop_write(ttyfd, " ", 1, false);
- if (!(flags & ASK_PASSWORD_SILENT) && !(flags & ASK_PASSWORD_ECHO)) {
+ if (!FLAGS_SET(flags, ASK_PASSWORD_SILENT) && !FLAGS_SET(flags, ASK_PASSWORD_ECHO)) {
if (use_color)
(void) loop_write(ttyfd, ansi_grey(), strlen(ansi_grey()), false);
(void) loop_write(ttyfd, PRESS_TAB, strlen(PRESS_TAB), false);
new_termios.c_cc[VMIN] = 1;
new_termios.c_cc[VTIME] = 0;
- if (tcsetattr(ttyfd, TCSADRAIN, &new_termios) < 0) {
- r = -errno;
+ r = RET_NERRNO(tcsetattr(ttyfd, TCSADRAIN, &new_termios));
+ if (r < 0)
goto finish;
- }
reset_tty = true;
}
for (;;) {
_cleanup_(erase_char) char c;
- int sleep_for = -1, k;
+ usec_t timeout;
ssize_t n;
- if (until > 0) {
- usec_t y;
-
- y = now(CLOCK_MONOTONIC);
+ if (until > 0)
+ timeout = usec_sub_unsigned(until, now(CLOCK_MONOTONIC));
+ else
+ timeout = USEC_INFINITY;
- if (y > until) {
- r = -ETIME;
+ if (flag_file) {
+ r = RET_NERRNO(access(flag_file, F_OK));
+ if (r < 0)
goto finish;
- }
-
- sleep_for = (int) DIV_ROUND_UP(until - y, USEC_PER_MSEC);
}
- if (flag_file)
- if (access(flag_file, F_OK) < 0) {
- r = -errno;
- goto finish;
- }
-
- k = poll(pollfd, notify >= 0 ? 2 : 1, sleep_for);
- if (k < 0) {
- if (errno == EINTR)
- continue;
-
- r = -errno;
+ r = ppoll_usec(pollfd, notify >= 0 ? 2 : 1, timeout);
+ if (r == -EINTR)
+ continue;
+ if (r < 0)
goto finish;
- } else if (k == 0) {
+ if (r == 0) {
r = -ETIME;
goto finish;
}
- if ((pollfd[POLL_TTY].revents & POLLNVAL) ||
- (notify >= 0 && (pollfd[POLL_INOTIFY].revents & POLLNVAL))) {
- r = -EBADF;
- goto finish;
- }
-
if (notify >= 0 && pollfd[POLL_INOTIFY].revents != 0 && keyname) {
(void) flush_fd(notify);
n = read(ttyfd >= 0 ? ttyfd : STDIN_FILENO, &c, 1);
if (n < 0) {
- if (IN_SET(errno, EINTR, EAGAIN))
+ if (ERRNO_IS_TRANSIENT(errno))
continue;
r = -errno;
if (c == 21) { /* C-u */
- if (!(flags & ASK_PASSWORD_SILENT))
+ if (!FLAGS_SET(flags, ASK_PASSWORD_SILENT))
(void) backspace_string(ttyfd, passphrase);
explicit_bzero_safe(passphrase, sizeof(passphrase));
if (p > 0) {
size_t q;
- if (!(flags & ASK_PASSWORD_SILENT))
+ if (!FLAGS_SET(flags, ASK_PASSWORD_SILENT))
(void) backspace_chars(ttyfd, 1);
/* Remove a full UTF-8 codepoint from the end. For that, figure out where the
* last one begins */
q = 0;
for (;;) {
- size_t z;
+ int z;
- z = utf8_encoded_valid_unichar(passphrase + q, (size_t) -1);
- if (z == 0) {
- q = (size_t) -1; /* Invalid UTF8! */
+ z = utf8_encoded_valid_unichar(passphrase + q, SIZE_MAX);
+ if (z <= 0) {
+ q = SIZE_MAX; /* Invalid UTF8! */
break;
}
q += z;
}
- p = codepoint = q == (size_t) -1 ? p - 1 : q;
+ p = codepoint = q == SIZE_MAX ? p - 1 : q;
explicit_bzero_safe(passphrase + p, sizeof(passphrase) - p);
- } else if (!dirty && !(flags & ASK_PASSWORD_SILENT)) {
+ } else if (!dirty && !FLAGS_SET(flags, ASK_PASSWORD_SILENT)) {
flags |= ASK_PASSWORD_SILENT;
} else if (ttyfd >= 0)
(void) loop_write(ttyfd, "\a", 1, false);
- } else if (c == '\t' && !(flags & ASK_PASSWORD_SILENT)) {
+ } else if (c == '\t' && !FLAGS_SET(flags, ASK_PASSWORD_SILENT)) {
(void) backspace_string(ttyfd, passphrase);
flags |= ASK_PASSWORD_SILENT;
} else {
passphrase[p++] = c;
- if (!(flags & ASK_PASSWORD_SILENT) && ttyfd >= 0) {
+ if (!FLAGS_SET(flags, ASK_PASSWORD_SILENT) && ttyfd >= 0) {
/* Check if we got a complete UTF-8 character now. If so, let's output one '*'. */
- n = utf8_encoded_valid_unichar(passphrase + codepoint, (size_t) -1);
+ n = utf8_encoded_valid_unichar(passphrase + codepoint, SIZE_MAX);
if (n >= 0) {
- if (flags & ASK_PASSWORD_ECHO)
+ if (FLAGS_SET(flags, ASK_PASSWORD_ECHO))
(void) loop_write(ttyfd, passphrase + codepoint, n, false);
else
(void) loop_write(ttyfd, "*", 1, false);
}
x = strndup(passphrase, p);
- explicit_bzero_safe(passphrase, sizeof(passphrase));
if (!x) {
r = -ENOMEM;
goto finish;
_cleanup_free_ char *path = NULL;
union sockaddr_union sa;
socklen_t sa_len;
- _cleanup_close_ int fd = -1;
+ _cleanup_close_ int fd = -EBADF;
int r;
assert(ret);
return r;
sa_len = r;
- RUN_WITH_UMASK(0177)
+ WITH_UMASK(0177)
if (bind(fd, &sa.sa, sa_len) < 0)
return -errno;
_FD_MAX
};
- _cleanup_close_ int socket_fd = -1, signal_fd = -1, notify = -1, fd = -1;
+ _cleanup_close_ int socket_fd = -EBADF, signal_fd = -EBADF, notify = -EBADF, fd = -EBADF;
char temp[] = "/run/systemd/ask-password/tmp.XXXXXX";
char final[sizeof(temp)] = "";
_cleanup_free_ char *socket_name = NULL;
assert(ret);
- if (flags & ASK_PASSWORD_NO_AGENT)
+ if (FLAGS_SET(flags, ASK_PASSWORD_NO_AGENT))
return -EUNATCH;
assert_se(sigemptyset(&mask) >= 0);
(void) mkdir_p_label("/run/systemd/ask-password", 0755);
- if ((flags & ASK_PASSWORD_ACCEPT_CACHED) && keyname) {
+ if (FLAGS_SET(flags, ASK_PASSWORD_ACCEPT_CACHED) && keyname) {
r = ask_password_keyring(keyname, flags, ret);
if (r >= 0) {
r = 0;
r = -errno;
goto finish;
}
- if (inotify_add_watch(notify, "/run/systemd/ask-password", IN_ATTRIB /* for mtime */) < 0) {
- r = -errno;
+
+ r = RET_NERRNO(inotify_add_watch(notify, "/run/systemd/ask-password", IN_ATTRIB /* for mtime */));
+ if (r < 0)
goto finish;
- }
}
fd = mkostemp_safe(temp);
"Socket=%s\n"
"AcceptCached=%i\n"
"Echo=%i\n"
- "NotAfter="USEC_FMT"\n",
+ "NotAfter="USEC_FMT"\n"
+ "Silent=%i\n",
getpid_cached(),
socket_name,
- (flags & ASK_PASSWORD_ACCEPT_CACHED) ? 1 : 0,
- (flags & ASK_PASSWORD_ECHO) ? 1 : 0,
- until);
+ FLAGS_SET(flags, ASK_PASSWORD_ACCEPT_CACHED),
+ FLAGS_SET(flags, ASK_PASSWORD_ECHO),
+ until,
+ FLAGS_SET(flags, ASK_PASSWORD_SILENT));
if (message)
fprintf(f, "Message=%s\n", message);
final[sizeof(final)-10] = 's';
final[sizeof(final)-9] = 'k';
- if (rename(temp, final) < 0) {
- r = -errno;
+ r = RET_NERRNO(rename(temp, final));
+ if (r < 0)
goto finish;
- }
zero(pollfd);
pollfd[FD_SOCKET].fd = socket_fd;
char passphrase[LINE_MAX+1];
struct iovec iovec;
struct ucred *ucred;
+ usec_t timeout;
ssize_t n;
- int k;
- usec_t t;
-
- t = now(CLOCK_MONOTONIC);
- if (until > 0 && until <= t) {
- r = -ETIME;
- goto finish;
- }
-
- k = poll(pollfd, notify >= 0 ? _FD_MAX : _FD_MAX - 1, until > 0 ? (int) ((until-t)/USEC_PER_MSEC) : -1);
- if (k < 0) {
- if (errno == EINTR)
- continue;
+ if (until > 0)
+ timeout = usec_sub_unsigned(until, now(CLOCK_MONOTONIC));
+ else
+ timeout = USEC_INFINITY;
- r = -errno;
+ r = ppoll_usec(pollfd, notify >= 0 ? _FD_MAX : _FD_MAX - 1, timeout);
+ if (r == -EINTR)
+ continue;
+ if (r < 0)
goto finish;
- }
-
- if (k <= 0) {
+ if (r == 0) {
r = -ETIME;
goto finish;
}
- if (pollfd[FD_SOCKET].revents & POLLNVAL ||
- pollfd[FD_SIGNAL].revents & POLLNVAL ||
- (notify >= 0 && pollfd[FD_INOTIFY].revents & POLLNVAL)) {
- r = -EBADF;
- goto finish;
- }
-
if (pollfd[FD_SIGNAL].revents & POLLIN) {
r = -EINTR;
goto finish;
};
n = recvmsg_safe(socket_fd, &msghdr, 0);
- if (IN_SET(n, -EAGAIN, -EINTR))
- continue;
- if (n == -EXFULL) {
- log_debug("Got message with truncated control data, ignoring.");
- continue;
- }
if (n < 0) {
+ if (ERRNO_IS_TRANSIENT(n))
+ continue;
+ if (n == -EXFULL) {
+ log_debug("Got message with truncated control data, ignoring.");
+ continue;
+ }
+
r = (int) n;
goto finish;
}
+ CLEANUP_ERASE(passphrase);
+
cmsg_close_all(&msghdr);
- if (n <= 0) {
+ if (n == 0) {
log_debug("Message too short");
continue;
}
l = strv_new("");
else
l = strv_parse_nulstr(passphrase+1, n-1);
- explicit_bzero_safe(passphrase, n);
if (!l) {
r = -ENOMEM;
goto finish;
return r;
}
+static int ask_password_credential(const char *credential_name, AskPasswordFlags flags, char ***ret) {
+ _cleanup_(erase_and_freep) char *buffer = NULL;
+ size_t size;
+ char **l;
+ int r;
+
+ assert(credential_name);
+ assert(ret);
+
+ r = read_credential(credential_name, (void**) &buffer, &size);
+ if (IN_SET(r, -ENXIO, -ENOENT)) /* No credentials passed or this credential not defined? */
+ return -ENOKEY;
+
+ l = strv_parse_nulstr(buffer, size);
+ if (!l)
+ return -ENOMEM;
+
+ *ret = l;
+ return 0;
+}
+
int ask_password_auto(
const char *message,
const char *icon,
- const char *id,
- const char *keyname,
+ const char *id, /* id in "ask-password" protocol */
+ const char *key_name, /* name in kernel keyring */
+ const char *credential_name, /* name in $CREDENTIALS_DIRECTORY directory */
usec_t until,
AskPasswordFlags flags,
char ***ret) {
assert(ret);
- if ((flags & ASK_PASSWORD_ACCEPT_CACHED) &&
- keyname &&
- ((flags & ASK_PASSWORD_NO_TTY) || !isatty(STDIN_FILENO)) &&
- (flags & ASK_PASSWORD_NO_AGENT)) {
- r = ask_password_keyring(keyname, flags, ret);
+ if (!FLAGS_SET(flags, ASK_PASSWORD_NO_CREDENTIAL) && credential_name) {
+ r = ask_password_credential(credential_name, flags, ret);
+ if (r != -ENOKEY)
+ return r;
+ }
+
+ if (FLAGS_SET(flags, ASK_PASSWORD_ACCEPT_CACHED) &&
+ key_name &&
+ (FLAGS_SET(flags, ASK_PASSWORD_NO_TTY) || !isatty(STDIN_FILENO)) &&
+ FLAGS_SET(flags, ASK_PASSWORD_NO_AGENT)) {
+ r = ask_password_keyring(key_name, flags, ret);
if (r != -ENOKEY)
return r;
}
- if (!(flags & ASK_PASSWORD_NO_TTY) && isatty(STDIN_FILENO))
- return ask_password_tty(-1, message, keyname, until, flags, NULL, ret);
+ if (!FLAGS_SET(flags, ASK_PASSWORD_NO_TTY) && isatty(STDIN_FILENO))
+ return ask_password_tty(-1, message, key_name, until, flags, NULL, ret);
- if (!(flags & ASK_PASSWORD_NO_AGENT))
- return ask_password_agent(message, icon, id, keyname, until, flags, ret);
+ if (!FLAGS_SET(flags, ASK_PASSWORD_NO_AGENT))
+ return ask_password_agent(message, icon, id, key_name, until, flags, ret);
return -EUNATCH;
}