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