]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/shared/ask-password-api.c
test-ask-password-api: add a manual test for password reading
[thirdparty/systemd.git] / src / shared / ask-password-api.c
CommitLineData
7f4e0805
LP
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright 2010 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
5430f7f2
LP
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
7f4e0805
LP
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5430f7f2 16 Lesser General Public License for more details.
7f4e0805 17
5430f7f2 18 You should have received a copy of the GNU Lesser General Public License
7f4e0805
LP
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
00843602 21
7f4e0805
LP
22#include <errno.h>
23#include <fcntl.h>
a8fbdf54
TA
24#include <inttypes.h>
25#include <limits.h>
00843602 26#include <poll.h>
a8fbdf54 27#include <signal.h>
00843602 28#include <stdbool.h>
7f4e0805 29#include <stddef.h>
a8fbdf54
TA
30#include <stdint.h>
31#include <stdio.h>
32#include <stdlib.h>
00843602
LP
33#include <string.h>
34#include <sys/inotify.h>
7f4e0805 35#include <sys/signalfd.h>
00843602 36#include <sys/socket.h>
a8fbdf54
TA
37#include <sys/stat.h>
38#include <sys/time.h>
39#include <sys/uio.h>
00843602
LP
40#include <sys/un.h>
41#include <termios.h>
42#include <unistd.h>
7f4e0805 43
b5efdb8a 44#include "alloc-util.h"
3ffd4af2
LP
45#include "ask-password-api.h"
46#include "fd-util.h"
0d39fa9c 47#include "fileio.h"
6482f626 48#include "formats-util.h"
c004493c 49#include "io-util.h"
a8fbdf54
TA
50#include "log.h"
51#include "macro.h"
e287086b 52#include "missing.h"
49e942b2 53#include "mkdir.h"
3df3e884 54#include "random-util.h"
24882e06 55#include "signal-util.h"
00843602 56#include "socket-util.h"
07630cea 57#include "string-util.h"
00843602
LP
58#include "strv.h"
59#include "terminal-util.h"
a8fbdf54 60#include "time-util.h"
affb60b1 61#include "umask-util.h"
00843602 62#include "util.h"
7f4e0805 63
e287086b
LP
64#define KEYRING_TIMEOUT_USEC ((5 * USEC_PER_MINUTE) / 2)
65
66static int lookup_key(const char *keyname, key_serial_t *ret) {
67 key_serial_t serial;
68
69 assert(keyname);
70 assert(ret);
71
72 serial = request_key("user", keyname, NULL, 0);
73 if (serial == -1)
9c4615fb 74 return negative_errno();
e287086b
LP
75
76 *ret = serial;
77 return 0;
78}
79
80static int retrieve_key(key_serial_t serial, char ***ret) {
81 _cleanup_free_ char *p = NULL;
82 long m = 100, n;
83 char **l;
84
85 assert(ret);
86
87 for (;;) {
88 p = new(char, m);
89 if (!p)
90 return -ENOMEM;
91
92 n = keyctl(KEYCTL_READ, (unsigned long) serial, (unsigned long) p, (unsigned long) m, 0);
93 if (n < 0)
94 return -errno;
95
96 if (n < m)
97 break;
98
1602b008 99 memory_erase(p, n);
e287086b
LP
100 free(p);
101 m *= 2;
102 }
103
104 l = strv_parse_nulstr(p, n);
105 if (!l)
106 return -ENOMEM;
107
1602b008
LP
108 memory_erase(p, n);
109
e287086b
LP
110 *ret = l;
111 return 0;
112}
113
114static int add_to_keyring(const char *keyname, AskPasswordFlags flags, char **passwords) {
ab84f5b9 115 _cleanup_strv_free_erase_ char **l = NULL;
e287086b
LP
116 _cleanup_free_ char *p = NULL;
117 key_serial_t serial;
118 size_t n;
119 int r;
120
121 assert(keyname);
122 assert(passwords);
123
124 if (!(flags & ASK_PASSWORD_PUSH_CACHE))
125 return 0;
126
127 r = lookup_key(keyname, &serial);
128 if (r >= 0) {
129 r = retrieve_key(serial, &l);
130 if (r < 0)
131 return r;
132 } else if (r != -ENOKEY)
133 return r;
134
135 r = strv_extend_strv(&l, passwords, true);
136 if (r <= 0)
137 return r;
138
139 r = strv_make_nulstr(l, &p, &n);
140 if (r < 0)
141 return r;
142
143 /* Truncate trailing NUL */
144 assert(n > 0);
145 assert(p[n-1] == 0);
146
147 serial = add_key("user", keyname, p, n-1, KEY_SPEC_USER_KEYRING);
1602b008 148 memory_erase(p, n);
e287086b
LP
149 if (serial == -1)
150 return -errno;
151
152 if (keyctl(KEYCTL_SET_TIMEOUT,
153 (unsigned long) serial,
154 (unsigned long) DIV_ROUND_UP(KEYRING_TIMEOUT_USEC, USEC_PER_SEC), 0, 0) < 0)
155 log_debug_errno(errno, "Failed to adjust timeout: %m");
156
157 log_debug("Added key to keyring as %" PRIi32 ".", serial);
158
159 return 1;
160}
161
162static int add_to_keyring_and_log(const char *keyname, AskPasswordFlags flags, char **passwords) {
163 int r;
164
165 assert(keyname);
166 assert(passwords);
167
168 r = add_to_keyring(keyname, flags, passwords);
169 if (r < 0)
170 return log_debug_errno(r, "Failed to add password to keyring: %m");
171
172 return 0;
173}
174
175int ask_password_keyring(const char *keyname, AskPasswordFlags flags, char ***ret) {
176
177 key_serial_t serial;
178 int r;
179
180 assert(keyname);
181 assert(ret);
182
183 if (!(flags & ASK_PASSWORD_ACCEPT_CACHED))
184 return -EUNATCH;
185
186 r = lookup_key(keyname, &serial);
187 if (r == -ENOSYS) /* when retrieving the distinction doesn't matter */
188 return -ENOKEY;
189 if (r < 0)
190 return r;
191
192 return retrieve_key(serial, ret);
193}
194
58fc840b
LP
195static void backspace_chars(int ttyfd, size_t p) {
196
197 if (ttyfd < 0)
198 return;
199
200 while (p > 0) {
201 p--;
202
203 loop_write(ttyfd, "\b \b", 3, false);
204 }
205}
206
7f4e0805
LP
207int ask_password_tty(
208 const char *message,
e287086b 209 const char *keyname,
7f4e0805 210 usec_t until,
e287086b 211 AskPasswordFlags flags,
7f4e0805 212 const char *flag_file,
e287086b 213 char **ret) {
7f4e0805
LP
214
215 struct termios old_termios, new_termios;
981e4cd3 216 char passphrase[LINE_MAX], *x;
7f4e0805 217 size_t p = 0;
981e4cd3
LP
218 int r;
219 _cleanup_close_ int ttyfd = -1, notify = -1;
7f4e0805
LP
220 struct pollfd pollfd[2];
221 bool reset_tty = false;
441dfe09 222 bool dirty = false;
7f4e0805
LP
223 enum {
224 POLL_TTY,
225 POLL_INOTIFY
226 };
227
e287086b
LP
228 assert(ret);
229
230 if (flags & ASK_PASSWORD_NO_TTY)
231 return -EUNATCH;
232
233 if (!message)
234 message = "Password:";
7f4e0805
LP
235
236 if (flag_file) {
981e4cd3
LP
237 notify = inotify_init1(IN_CLOEXEC|IN_NONBLOCK);
238 if (notify < 0) {
7f4e0805
LP
239 r = -errno;
240 goto finish;
241 }
242
243 if (inotify_add_watch(notify, flag_file, IN_ATTRIB /* for the link count */) < 0) {
244 r = -errno;
245 goto finish;
246 }
247 }
248
981e4cd3
LP
249 ttyfd = open("/dev/tty", O_RDWR|O_NOCTTY|O_CLOEXEC);
250 if (ttyfd >= 0) {
7f4e0805
LP
251
252 if (tcgetattr(ttyfd, &old_termios) < 0) {
253 r = -errno;
254 goto finish;
255 }
256
00843602 257 loop_write(ttyfd, ANSI_HIGHLIGHT, strlen(ANSI_HIGHLIGHT), false);
7f4e0805 258 loop_write(ttyfd, message, strlen(message), false);
bd1db33f 259 loop_write(ttyfd, " ", 1, false);
00843602 260 loop_write(ttyfd, ANSI_NORMAL, strlen(ANSI_NORMAL), false);
7f4e0805
LP
261
262 new_termios = old_termios;
263 new_termios.c_lflag &= ~(ICANON|ECHO);
264 new_termios.c_cc[VMIN] = 1;
265 new_termios.c_cc[VTIME] = 0;
266
267 if (tcsetattr(ttyfd, TCSADRAIN, &new_termios) < 0) {
268 r = -errno;
269 goto finish;
270 }
271
272 reset_tty = true;
273 }
274
275 zero(pollfd);
7f4e0805
LP
276 pollfd[POLL_TTY].fd = ttyfd >= 0 ? ttyfd : STDIN_FILENO;
277 pollfd[POLL_TTY].events = POLLIN;
278 pollfd[POLL_INOTIFY].fd = notify;
279 pollfd[POLL_INOTIFY].events = POLLIN;
280
281 for (;;) {
282 char c;
283 int sleep_for = -1, k;
284 ssize_t n;
285
286 if (until > 0) {
287 usec_t y;
288
289 y = now(CLOCK_MONOTONIC);
290
291 if (y > until) {
7ded2e28 292 r = -ETIME;
7f4e0805
LP
293 goto finish;
294 }
295
296 sleep_for = (int) ((until - y) / USEC_PER_MSEC);
297 }
298
299 if (flag_file)
300 if (access(flag_file, F_OK) < 0) {
301 r = -errno;
302 goto finish;
303 }
304
e287086b 305 k = poll(pollfd, notify >= 0 ? 2 : 1, sleep_for);
981e4cd3 306 if (k < 0) {
7f4e0805
LP
307 if (errno == EINTR)
308 continue;
309
310 r = -errno;
311 goto finish;
312 } else if (k == 0) {
ccc80078 313 r = -ETIME;
7f4e0805
LP
314 goto finish;
315 }
316
e287086b 317 if (notify >= 0 && pollfd[POLL_INOTIFY].revents != 0)
7f4e0805
LP
318 flush_fd(notify);
319
320 if (pollfd[POLL_TTY].revents == 0)
321 continue;
322
981e4cd3
LP
323 n = read(ttyfd >= 0 ? ttyfd : STDIN_FILENO, &c, 1);
324 if (n < 0) {
7f4e0805
LP
325 if (errno == EINTR || errno == EAGAIN)
326 continue;
327
328 r = -errno;
329 goto finish;
330
331 } else if (n == 0)
332 break;
333
334 if (c == '\n')
335 break;
58fc840b 336 else if (c == 21) { /* C-u */
7f4e0805 337
e287086b 338 if (!(flags & ASK_PASSWORD_SILENT))
58fc840b
LP
339 backspace_chars(ttyfd, p);
340 p = 0;
7f4e0805
LP
341
342 } else if (c == '\b' || c == 127) {
58fc840b
LP
343
344 if (p > 0) {
345
e287086b 346 if (!(flags & ASK_PASSWORD_SILENT))
58fc840b
LP
347 backspace_chars(ttyfd, 1);
348
7f4e0805 349 p--;
e287086b 350 } else if (!dirty && !(flags & ASK_PASSWORD_SILENT)) {
441dfe09 351
e287086b 352 flags |= ASK_PASSWORD_SILENT;
441dfe09
LP
353
354 /* There are two ways to enter silent
355 * mode. Either by pressing backspace
e287086b
LP
356 * as first key (and only as first
357 * key), or ... */
441dfe09
LP
358 if (ttyfd >= 0)
359 loop_write(ttyfd, "(no echo) ", 10, false);
360
58fc840b
LP
361 } else if (ttyfd >= 0)
362 loop_write(ttyfd, "\a", 1, false);
7f4e0805 363
e287086b 364 } else if (c == '\t' && !(flags & ASK_PASSWORD_SILENT)) {
58fc840b
LP
365
366 backspace_chars(ttyfd, p);
e287086b 367 flags |= ASK_PASSWORD_SILENT;
58fc840b 368
441dfe09
LP
369 /* ... or by pressing TAB at any time. */
370
58fc840b
LP
371 if (ttyfd >= 0)
372 loop_write(ttyfd, "(no echo) ", 10, false);
7f4e0805 373 } else {
036eeac5
LP
374 if (p >= sizeof(passphrase)-1) {
375 loop_write(ttyfd, "\a", 1, false);
376 continue;
377 }
378
7f4e0805
LP
379 passphrase[p++] = c;
380
e287086b
LP
381 if (!(flags & ASK_PASSWORD_SILENT) && ttyfd >= 0)
382 loop_write(ttyfd, (flags & ASK_PASSWORD_ECHO) ? &c : "*", 1, false);
441dfe09
LP
383
384 dirty = true;
7f4e0805 385 }
1602b008
LP
386
387 c = 'x';
7f4e0805
LP
388 }
389
981e4cd3 390 x = strndup(passphrase, p);
1602b008 391 memory_erase(passphrase, p);
981e4cd3 392 if (!x) {
7f4e0805
LP
393 r = -ENOMEM;
394 goto finish;
395 }
396
e287086b
LP
397 if (keyname)
398 (void) add_to_keyring_and_log(keyname, flags, STRV_MAKE(x));
399
400 *ret = x;
7f4e0805
LP
401 r = 0;
402
403finish:
981e4cd3
LP
404 if (ttyfd >= 0 && reset_tty) {
405 loop_write(ttyfd, "\n", 1, false);
406 tcsetattr(ttyfd, TCSADRAIN, &old_termios);
7f4e0805
LP
407 }
408
409 return r;
410}
411
412static int create_socket(char **name) {
00843602 413 union sockaddr_union sa = {
b92bea5d
ZJS
414 .un.sun_family = AF_UNIX,
415 };
00843602
LP
416 _cleanup_close_ int fd = -1;
417 static const int one = 1;
7f4e0805 418 char *c;
00843602 419 int r;
7f4e0805
LP
420
421 assert(name);
422
e62d8c39 423 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
4a62c710 424 if (fd < 0)
00843602 425 return -errno;
7f4e0805 426
9bf3b535 427 snprintf(sa.un.sun_path, sizeof(sa.un.sun_path)-1, "/run/systemd/ask-password/sck.%" PRIx64, random_u64());
7f4e0805 428
5c0d398d 429 RUN_WITH_UMASK(0177) {
00843602
LP
430 if (bind(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path)) < 0)
431 return -errno;
5c0d398d 432 }
1d6702e8 433
00843602
LP
434 if (setsockopt(fd, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one)) < 0)
435 return -errno;
7f4e0805 436
e62d8c39 437 c = strdup(sa.un.sun_path);
00843602
LP
438 if (!c)
439 return -ENOMEM;
7f4e0805
LP
440
441 *name = c;
7f4e0805 442
00843602
LP
443 r = fd;
444 fd = -1;
7f4e0805
LP
445
446 return r;
447}
448
7f4e0805
LP
449int ask_password_agent(
450 const char *message,
451 const char *icon,
9fa1de96 452 const char *id,
e287086b 453 const char *keyname,
7f4e0805 454 usec_t until,
e287086b
LP
455 AskPasswordFlags flags,
456 char ***ret) {
7f4e0805
LP
457
458 enum {
459 FD_SOCKET,
460 FD_SIGNAL,
461 _FD_MAX
462 };
463
e287086b 464 _cleanup_close_ int socket_fd = -1, signal_fd = -1, fd = -1;
2b583ce6 465 char temp[] = "/run/systemd/ask-password/tmp.XXXXXX";
7f4e0805 466 char final[sizeof(temp)] = "";
981e4cd3 467 _cleanup_free_ char *socket_name = NULL;
e287086b
LP
468 _cleanup_strv_free_ char **l = NULL;
469 _cleanup_fclose_ FILE *f = NULL;
7f4e0805 470 struct pollfd pollfd[_FD_MAX];
e287086b 471 sigset_t mask, oldmask;
981e4cd3 472 int r;
7f4e0805 473
e287086b 474 assert(ret);
21bc923a 475
e287086b
LP
476 if (flags & ASK_PASSWORD_NO_AGENT)
477 return -EUNATCH;
00843602 478
72c0a2c2
LP
479 assert_se(sigemptyset(&mask) >= 0);
480 assert_se(sigset_add_many(&mask, SIGINT, SIGTERM, -1) >= 0);
481 assert_se(sigprocmask(SIG_BLOCK, &mask, &oldmask) >= 0);
f9b72cd8 482
00843602 483 (void) mkdir_p_label("/run/systemd/ask-password", 0755);
7f4e0805 484
2d5bdf5b 485 fd = mkostemp_safe(temp, O_WRONLY|O_CLOEXEC);
1d6702e8 486 if (fd < 0) {
709f6e46 487 r = fd;
7f4e0805
LP
488 goto finish;
489 }
490
00843602 491 (void) fchmod(fd, 0644);
7f4e0805 492
981e4cd3
LP
493 f = fdopen(fd, "w");
494 if (!f) {
00843602 495 r = -errno;
7f4e0805
LP
496 goto finish;
497 }
498
499 fd = -1;
500
981e4cd3
LP
501 signal_fd = signalfd(-1, &mask, SFD_NONBLOCK|SFD_CLOEXEC);
502 if (signal_fd < 0) {
00843602 503 r = -errno;
7f4e0805
LP
504 goto finish;
505 }
506
981e4cd3
LP
507 socket_fd = create_socket(&socket_name);
508 if (socket_fd < 0) {
7f4e0805
LP
509 r = socket_fd;
510 goto finish;
511 }
512
513 fprintf(f,
514 "[Ask]\n"
de0671ee 515 "PID="PID_FMT"\n"
7f4e0805 516 "Socket=%s\n"
21bc923a 517 "AcceptCached=%i\n"
64845bdc 518 "Echo=%i\n"
de0671ee
ZJS
519 "NotAfter="USEC_FMT"\n",
520 getpid(),
7f4e0805 521 socket_name,
e287086b
LP
522 (flags & ASK_PASSWORD_ACCEPT_CACHED) ? 1 : 0,
523 (flags & ASK_PASSWORD_ECHO) ? 1 : 0,
de0671ee 524 until);
7f4e0805
LP
525
526 if (message)
527 fprintf(f, "Message=%s\n", message);
528
529 if (icon)
530 fprintf(f, "Icon=%s\n", icon);
531
9fa1de96
DH
532 if (id)
533 fprintf(f, "Id=%s\n", id);
534
dacd6cee 535 r = fflush_and_check(f);
00843602 536 if (r < 0)
7f4e0805 537 goto finish;
7f4e0805
LP
538
539 memcpy(final, temp, sizeof(temp));
540
541 final[sizeof(final)-11] = 'a';
542 final[sizeof(final)-10] = 's';
543 final[sizeof(final)-9] = 'k';
544
545 if (rename(temp, final) < 0) {
00843602 546 r = -errno;
7f4e0805
LP
547 goto finish;
548 }
549
550 zero(pollfd);
551 pollfd[FD_SOCKET].fd = socket_fd;
552 pollfd[FD_SOCKET].events = POLLIN;
553 pollfd[FD_SIGNAL].fd = signal_fd;
554 pollfd[FD_SIGNAL].events = POLLIN;
555
556 for (;;) {
557 char passphrase[LINE_MAX+1];
558 struct msghdr msghdr;
559 struct iovec iovec;
560 struct ucred *ucred;
561 union {
562 struct cmsghdr cmsghdr;
563 uint8_t buf[CMSG_SPACE(sizeof(struct ucred))];
564 } control;
565 ssize_t n;
566 int k;
567 usec_t t;
568
569 t = now(CLOCK_MONOTONIC);
570
7dcda352 571 if (until > 0 && until <= t) {
7f4e0805
LP
572 r = -ETIME;
573 goto finish;
574 }
575
981e4cd3
LP
576 k = poll(pollfd, _FD_MAX, until > 0 ? (int) ((until-t)/USEC_PER_MSEC) : -1);
577 if (k < 0) {
7f4e0805
LP
578 if (errno == EINTR)
579 continue;
580
00843602 581 r = -errno;
7f4e0805
LP
582 goto finish;
583 }
584
585 if (k <= 0) {
7f4e0805
LP
586 r = -ETIME;
587 goto finish;
588 }
589
21bc923a
LP
590 if (pollfd[FD_SIGNAL].revents & POLLIN) {
591 r = -EINTR;
592 goto finish;
593 }
7f4e0805
LP
594
595 if (pollfd[FD_SOCKET].revents != POLLIN) {
7f4e0805
LP
596 r = -EIO;
597 goto finish;
598 }
599
600 zero(iovec);
601 iovec.iov_base = passphrase;
21bc923a 602 iovec.iov_len = sizeof(passphrase);
7f4e0805
LP
603
604 zero(control);
605 zero(msghdr);
606 msghdr.msg_iov = &iovec;
607 msghdr.msg_iovlen = 1;
608 msghdr.msg_control = &control;
609 msghdr.msg_controllen = sizeof(control);
610
981e4cd3
LP
611 n = recvmsg(socket_fd, &msghdr, 0);
612 if (n < 0) {
7f4e0805
LP
613 if (errno == EAGAIN ||
614 errno == EINTR)
615 continue;
616
00843602 617 r = -errno;
7f4e0805
LP
618 goto finish;
619 }
620
1c8da044
LP
621 cmsg_close_all(&msghdr);
622
7f4e0805 623 if (n <= 0) {
00843602 624 log_debug("Message too short");
7f4e0805
LP
625 continue;
626 }
627
628 if (msghdr.msg_controllen < CMSG_LEN(sizeof(struct ucred)) ||
629 control.cmsghdr.cmsg_level != SOL_SOCKET ||
630 control.cmsghdr.cmsg_type != SCM_CREDENTIALS ||
631 control.cmsghdr.cmsg_len != CMSG_LEN(sizeof(struct ucred))) {
00843602 632 log_debug("Received message without credentials. Ignoring.");
7f4e0805
LP
633 continue;
634 }
635
636 ucred = (struct ucred*) CMSG_DATA(&control.cmsghdr);
637 if (ucred->uid != 0) {
00843602 638 log_debug("Got request from unprivileged user. Ignoring.");
7f4e0805
LP
639 continue;
640 }
641
642 if (passphrase[0] == '+') {
e287086b 643 /* An empty message refers to the empty password */
8254a475
LP
644 if (n == 1)
645 l = strv_new("", NULL);
646 else
647 l = strv_parse_nulstr(passphrase+1, n-1);
1602b008 648 memory_erase(passphrase, n);
8254a475 649 if (!l) {
7f4e0805
LP
650 r = -ENOMEM;
651 goto finish;
652 }
653
21bc923a 654 if (strv_length(l) <= 0) {
e287086b 655 l = strv_free(l);
00843602 656 log_debug("Invalid packet");
21bc923a
LP
657 continue;
658 }
659
e287086b
LP
660 break;
661 }
21bc923a 662
e287086b 663 if (passphrase[0] == '-') {
7f4e0805
LP
664 r = -ECANCELED;
665 goto finish;
7f4e0805
LP
666 }
667
e287086b 668 log_debug("Invalid packet");
7f4e0805
LP
669 }
670
e287086b
LP
671 if (keyname)
672 (void) add_to_keyring_and_log(keyname, flags, l);
673
674 *ret = l;
675 l = NULL;
7f4e0805
LP
676 r = 0;
677
678finish:
981e4cd3 679 if (socket_name)
00843602 680 (void) unlink(socket_name);
7f4e0805 681
00843602 682 (void) unlink(temp);
7f4e0805
LP
683
684 if (final[0])
00843602 685 (void) unlink(final);
7f4e0805 686
f9b72cd8 687 assert_se(sigprocmask(SIG_SETMASK, &oldmask, NULL) == 0);
7f4e0805
LP
688 return r;
689}
260ab287 690
00843602
LP
691int ask_password_auto(
692 const char *message,
693 const char *icon,
694 const char *id,
e287086b 695 const char *keyname,
00843602 696 usec_t until,
e287086b
LP
697 AskPasswordFlags flags,
698 char ***ret) {
00843602
LP
699
700 int r;
701
e287086b 702 assert(ret);
21bc923a 703
e287086b
LP
704 if ((flags & ASK_PASSWORD_ACCEPT_CACHED) && keyname) {
705 r = ask_password_keyring(keyname, flags, ret);
706 if (r != -ENOKEY)
707 return r;
708 }
709
710 if (!(flags & ASK_PASSWORD_NO_TTY) && isatty(STDIN_FILENO)) {
21bc923a
LP
711 char *s = NULL, **l = NULL;
712
e287086b 713 r = ask_password_tty(message, keyname, until, flags, NULL, &s);
981e4cd3 714 if (r < 0)
21bc923a
LP
715 return r;
716
1602b008
LP
717 r = strv_push(&l, s);
718 if (r < 0) {
719 string_erase(s);
720 free(s);
00843602 721 return -ENOMEM;
1602b008 722 }
21bc923a 723
e287086b 724 *ret = l;
00843602
LP
725 return 0;
726 }
727
e287086b
LP
728 if (!(flags & ASK_PASSWORD_NO_AGENT))
729 return ask_password_agent(message, icon, id, keyname, until, flags, ret);
730
731 return -EUNATCH;
260ab287 732}