1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
6 #include <sys/inotify.h>
7 #include <sys/signalfd.h>
12 #include "alloc-util.h"
13 #include "ansi-color.h"
14 #include "ask-password-api.h"
15 #include "creds-util.h"
18 #include "format-util.h"
20 #include "glyph-util.h"
21 #include "inotify-util.h"
23 #include "iovec-util.h"
24 #include "keyring-util.h"
26 #include "missing_syscall.h"
27 #include "nulstr-util.h"
28 #include "parse-util.h"
29 #include "path-lookup.h"
30 #include "plymouth-util.h"
31 #include "process-util.h"
32 #include "random-util.h"
33 #include "signal-util.h"
34 #include "socket-util.h"
35 #include "string-table.h"
36 #include "string-util.h"
38 #include "terminal-util.h"
39 #include "time-util.h"
40 #include "tmpfile-util.h"
41 #include "umask-util.h"
44 #define KEYRING_TIMEOUT_USEC ((5 * USEC_PER_MINUTE) / 2)
46 static const char* keyring_table
[] = {
47 [-KEY_SPEC_THREAD_KEYRING
] = "thread",
48 [-KEY_SPEC_PROCESS_KEYRING
] = "process",
49 [-KEY_SPEC_SESSION_KEYRING
] = "session",
50 [-KEY_SPEC_USER_KEYRING
] = "user",
51 [-KEY_SPEC_USER_SESSION_KEYRING
] = "user-session",
52 [-KEY_SPEC_GROUP_KEYRING
] = "group",
55 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(keyring
, int);
57 static int lookup_key(const char *keyname
, key_serial_t
*ret
) {
63 serial
= request_key("user", keyname
, /* callout_info= */ NULL
, /* destringid= */ 0);
65 return negative_errno();
71 static int retrieve_key(key_serial_t serial
, char ***ret
) {
72 _cleanup_(erase_and_freep
) void *p
= NULL
;
79 r
= keyring_read(serial
, &p
, &n
);
83 l
= strv_parse_nulstr(p
, n
);
91 static int get_ask_password_directory_for_flags(AskPasswordFlags flags
, char **ret
) {
92 if (FLAGS_SET(flags
, ASK_PASSWORD_USER
))
93 return acquire_user_ask_password_directory(ret
);
95 return strdup_to_full(ret
, "/run/systemd/ask-password/"); /* Returns 1, indicating there's a suitable directory */
98 static int touch_ask_password_directory(AskPasswordFlags flags
) {
101 _cleanup_free_
char *p
= NULL
;
102 r
= get_ask_password_directory_for_flags(flags
, &p
);
106 _cleanup_close_
int fd
= open_mkdir(p
, O_CLOEXEC
, 0755);
110 r
= touch_fd(fd
, USEC_INFINITY
);
114 return 1; /* did something */
117 static usec_t
keyring_cache_timeout(void) {
118 static usec_t saved_timeout
= KEYRING_TIMEOUT_USEC
;
119 static bool saved_timeout_set
= false;
122 if (saved_timeout_set
)
123 return saved_timeout
;
125 const char *e
= secure_getenv("SYSTEMD_ASK_PASSWORD_KEYRING_TIMEOUT_SEC");
127 r
= parse_sec(e
, &saved_timeout
);
129 log_debug_errno(r
, "Invalid value in $SYSTEMD_ASK_PASSWORD_KEYRING_TIMEOUT_SEC, ignoring: %s", e
);
132 saved_timeout_set
= true;
134 return saved_timeout
;
137 static key_serial_t
keyring_cache_type(void) {
138 static key_serial_t saved_keyring
= KEY_SPEC_USER_KEYRING
;
139 static bool saved_keyring_set
= false;
142 if (saved_keyring_set
)
143 return saved_keyring
;
145 const char *e
= secure_getenv("SYSTEMD_ASK_PASSWORD_KEYRING_TYPE");
147 key_serial_t keyring
;
149 r
= safe_atoi32(e
, &keyring
);
152 log_debug_errno(keyring
, "Invalid value in $SYSTEMD_ASK_PASSWORD_KEYRING_TYPE, ignoring: %s", e
);
154 saved_keyring
= keyring
;
156 keyring
= keyring_from_string(e
);
158 log_debug_errno(keyring
, "Invalid value in $SYSTEMD_ASK_PASSWORD_KEYRING_TYPE, ignoring: %s", e
);
160 saved_keyring
= -keyring
;
164 saved_keyring_set
= true;
166 return saved_keyring
;
169 static int add_to_keyring(const char *keyname
, AskPasswordFlags flags
, char **passwords
) {
170 _cleanup_strv_free_erase_
char **l
= NULL
;
171 _cleanup_(erase_and_freep
) char *p
= NULL
;
178 if (!FLAGS_SET(flags
, ASK_PASSWORD_PUSH_CACHE
) || keyring_cache_timeout() == 0)
180 if (strv_isempty(passwords
))
183 r
= lookup_key(keyname
, &serial
);
185 r
= retrieve_key(serial
, &l
);
188 } else if (r
!= -ENOKEY
)
191 r
= strv_extend_strv(&l
, passwords
, /* filter_duplicates= */ true);
195 r
= strv_make_nulstr(l
, &p
, &n
);
199 /* chop off the final NUL byte. We do this because we want to use the separator NUL bytes only if we
200 * have multiple passwords. */
201 n
= LESS_BY(n
, (size_t) 1);
203 serial
= add_key("user", keyname
, p
, n
, keyring_cache_type());
207 if (keyring_cache_timeout() != USEC_INFINITY
&&
208 keyctl(KEYCTL_SET_TIMEOUT
,
209 (unsigned long) serial
,
210 (unsigned long) DIV_ROUND_UP(keyring_cache_timeout(), USEC_PER_SEC
), 0, 0) < 0)
211 log_debug_errno(errno
, "Failed to adjust kernel keyring key timeout: %m");
213 /* Tell everyone to check the keyring */
214 (void) touch_ask_password_directory(flags
);
216 log_debug("Added key to kernel keyring as %" PRIi32
".", serial
);
221 static int add_to_keyring_and_log(const char *keyname
, AskPasswordFlags flags
, char **passwords
) {
226 r
= add_to_keyring(keyname
, flags
, passwords
);
228 return log_debug_errno(r
, "Failed to add password to kernel keyring: %m");
233 static int ask_password_keyring(const AskPasswordRequest
*req
, AskPasswordFlags flags
, char ***ret
) {
240 if (!FLAGS_SET(flags
, ASK_PASSWORD_ACCEPT_CACHED
))
243 r
= lookup_key(req
->keyring
, &serial
);
244 if (ERRNO_IS_NEG_NOT_SUPPORTED(r
) || r
== -EPERM
)
245 /* When retrieving, the distinction between "kernel or container manager don't support or
246 * allow this" and "no matching key known" doesn't matter. Note that we propagate EACCESS
247 * here (even if EPERM not) since that is used if the keyring is available, but we lack
248 * access to the key. */
253 _cleanup_strv_free_erase_
char **l
= NULL
;
254 r
= retrieve_key(serial
, &l
);
259 return log_debug_errno(SYNTHETIC_ERRNO(ENOKEY
), "Found an empty password from keyring.");
265 static int backspace_chars(int ttyfd
, size_t p
) {
269 _cleanup_free_
char *buf
= malloc_multiply(3, p
);
273 for (size_t i
= 0; i
< p
; i
++)
274 memcpy(buf
+ 3 * i
, "\b \b", 3);
276 return loop_write(ttyfd
, buf
, 3 * p
);
279 static int backspace_string(int ttyfd
, const char *str
) {
282 /* Backspaces through enough characters to entirely undo printing of the specified string. */
287 size_t m
= utf8_n_codepoints(str
);
289 m
= strlen(str
); /* Not a valid UTF-8 string? If so, let's backspace the number of bytes
290 * output. Most likely this happened because we are not in a UTF-8 locale,
291 * and in that case that is the correct thing to do. And even if it's not,
292 * terminals tend to stop backspacing at the leftmost column, hence
293 * backspacing too much should be mostly OK. */
295 return backspace_chars(ttyfd
, m
);
298 int ask_password_plymouth(
299 const AskPasswordRequest
*req
,
300 AskPasswordFlags flags
,
303 _cleanup_close_
int fd
= -EBADF
, inotify_fd
= -EBADF
;
304 _cleanup_free_
char *packet
= NULL
;
307 char buffer
[LINE_MAX
];
313 if (FLAGS_SET(flags
, ASK_PASSWORD_HEADLESS
))
316 const char *message
= req
->message
?: "Password:";
318 if (req
->flag_file
) {
319 inotify_fd
= inotify_init1(IN_CLOEXEC
|IN_NONBLOCK
);
323 if (inotify_add_watch(inotify_fd
, req
->flag_file
, IN_ATTRIB
) < 0) /* for the link count */
327 fd
= plymouth_connect(SOCK_NONBLOCK
);
331 if (FLAGS_SET(flags
, ASK_PASSWORD_ACCEPT_CACHED
)) {
332 packet
= strdup("c");
334 } else if (asprintf(&packet
, "*\002%c%s%n", (int) (strlen(message
) + 1), message
, &n
) < 0)
339 r
= loop_write_full(fd
, packet
, n
+ 1, USEC_INFINITY
);
343 CLEANUP_ERASE(buffer
);
352 struct pollfd pollfd
[_POLL_MAX
] = {
358 size_t n_pollfd
= POLL_SOCKET
+ 1, inotify_idx
= SIZE_MAX
, hup_fd_idx
= SIZE_MAX
;
360 pollfd
[inotify_idx
= n_pollfd
++] = (struct pollfd
) {
364 if (req
->hup_fd
>= 0)
365 pollfd
[hup_fd_idx
= n_pollfd
++] = (struct pollfd
) {
370 assert(n_pollfd
<= _POLL_MAX
);
376 timeout
= usec_sub_unsigned(req
->until
, now(CLOCK_MONOTONIC
));
378 timeout
= USEC_INFINITY
;
380 if (req
->flag_file
&& access(req
->flag_file
, F_OK
) < 0)
383 r
= ppoll_usec(pollfd
, n_pollfd
, timeout
);
391 if (req
->hup_fd
>= 0 && pollfd
[hup_fd_idx
].revents
& POLLHUP
)
394 if (inotify_fd
>= 0 && pollfd
[inotify_idx
].revents
!= 0)
395 (void) flush_fd(inotify_fd
);
397 if (pollfd
[POLL_SOCKET
].revents
== 0)
400 k
= read(fd
, buffer
+ p
, sizeof(buffer
) - p
);
402 if (ERRNO_IS_TRANSIENT(errno
))
412 if (buffer
[0] == 5) {
414 if (FLAGS_SET(flags
, ASK_PASSWORD_ACCEPT_CACHED
)) {
415 /* Hmm, first try with cached
416 * passwords failed, so let's retry
417 * with a normal password request */
418 packet
= mfree(packet
);
420 if (asprintf(&packet
, "*\002%c%s%n", (int) (strlen(message
) + 1), message
, &n
) < 0)
423 r
= loop_write_full(fd
, packet
, n
+ 1, USEC_INFINITY
);
427 flags
&= ~ASK_PASSWORD_ACCEPT_CACHED
;
432 /* No password, because UI not shown */
435 } else if (IN_SET(buffer
[0], 2, 9)) {
436 _cleanup_strv_free_erase_
char **l
= NULL
;
439 /* One or more answers */
443 memcpy(&size
, buffer
+1, sizeof(size
));
444 size
= le32toh(size
);
445 if (size
+ 5 > sizeof(buffer
))
451 l
= strv_parse_nulstr(buffer
+ 5, size
);
456 return log_debug_errno(SYNTHETIC_ERRNO(ECANCELED
), "Received an empty password.");
467 #define NO_ECHO "(no echo) "
468 #define PRESS_TAB "(press TAB for no echo) "
469 #define SKIPPED "(skipped)"
471 int ask_password_tty(
472 const AskPasswordRequest
*req
,
473 AskPasswordFlags flags
,
476 bool reset_tty
= false, dirty
= false, use_color
= false, press_tab_visible
= false;
477 _cleanup_close_
int cttyfd
= -EBADF
, inotify_fd
= -EBADF
;
478 struct termios old_termios
, new_termios
;
479 char passphrase
[LINE_MAX
+ 1] = {}, *x
;
480 _cleanup_strv_free_erase_
char **l
= NULL
;
481 size_t p
= 0, codepoint
= 0;
487 if (FLAGS_SET(flags
, ASK_PASSWORD_HEADLESS
))
490 if (FLAGS_SET(flags
, ASK_PASSWORD_NO_TTY
))
493 const char *message
= req
->message
?: "Password:";
494 const char *keyring
= req
->keyring
;
496 if (!FLAGS_SET(flags
, ASK_PASSWORD_HIDE_EMOJI
) && emoji_enabled())
497 message
= strjoina(glyph(GLYPH_LOCK_AND_KEY
), " ", message
);
499 if (req
->flag_file
|| (FLAGS_SET(flags
, ASK_PASSWORD_ACCEPT_CACHED
) && keyring
)) {
500 inotify_fd
= inotify_init1(IN_CLOEXEC
|IN_NONBLOCK
);
505 if (inotify_add_watch(inotify_fd
, req
->flag_file
, IN_ATTRIB
/* for the link count */) < 0)
507 if (FLAGS_SET(flags
, ASK_PASSWORD_ACCEPT_CACHED
) && keyring
) {
508 r
= ask_password_keyring(req
, flags
, ret
);
514 /* Let's watch the askpw directory for mtime changes, which we issue above whenever the
516 _cleanup_free_
char *watch_path
= NULL
;
517 r
= get_ask_password_directory_for_flags(flags
, &watch_path
);
521 _cleanup_close_
int watch_fd
= open_mkdir(watch_path
, O_CLOEXEC
|O_RDONLY
, 0755);
525 r
= inotify_add_watch_fd(inotify_fd
, watch_fd
, IN_ONLYDIR
|IN_ATTRIB
/* for mtime */);
531 CLEANUP_ERASE(passphrase
);
533 /* If the caller didn't specify a TTY, then use the controlling tty, if we can. */
536 ttyfd
= cttyfd
= open("/dev/tty", O_RDWR
|O_NOCTTY
|O_CLOEXEC
);
541 if (tcgetattr(ttyfd
, &old_termios
) < 0)
544 if (FLAGS_SET(flags
, ASK_PASSWORD_CONSOLE_COLOR
))
545 use_color
= dev_console_colors_enabled();
547 use_color
= colors_enabled();
550 (void) loop_write(ttyfd
, ANSI_HIGHLIGHT
, SIZE_MAX
);
552 (void) loop_write(ttyfd
, message
, SIZE_MAX
);
553 (void) loop_write(ttyfd
, " ", 1);
555 if (!FLAGS_SET(flags
, ASK_PASSWORD_SILENT
) && !FLAGS_SET(flags
, ASK_PASSWORD_ECHO
)) {
557 (void) loop_write(ttyfd
, ansi_grey(), SIZE_MAX
);
559 (void) loop_write(ttyfd
, PRESS_TAB
, SIZE_MAX
);
560 press_tab_visible
= true;
564 (void) loop_write(ttyfd
, ANSI_NORMAL
, SIZE_MAX
);
566 new_termios
= old_termios
;
567 termios_disable_echo(&new_termios
);
569 r
= RET_NERRNO(tcsetattr(ttyfd
, TCSANOW
, &new_termios
));
583 struct pollfd pollfd
[_POLL_MAX
] = {
585 .fd
= ttyfd
>= 0 ? ttyfd
: STDIN_FILENO
,
589 size_t n_pollfd
= POLL_TTY
+ 1, inotify_idx
= SIZE_MAX
, hup_fd_idx
= SIZE_MAX
;
592 pollfd
[inotify_idx
= n_pollfd
++] = (struct pollfd
) {
596 if (req
->hup_fd
>= 0)
597 pollfd
[hup_fd_idx
= n_pollfd
++] = (struct pollfd
) {
602 assert(n_pollfd
<= _POLL_MAX
);
605 _cleanup_(erase_char
) char c
;
610 timeout
= usec_sub_unsigned(req
->until
, now(CLOCK_MONOTONIC
));
612 timeout
= USEC_INFINITY
;
614 if (req
->flag_file
) {
615 r
= RET_NERRNO(access(req
->flag_file
, F_OK
));
620 r
= ppoll_usec(pollfd
, n_pollfd
, timeout
);
630 if (req
->hup_fd
>= 0 && pollfd
[hup_fd_idx
].revents
& POLLHUP
) {
635 if (inotify_fd
>= 0 && pollfd
[inotify_idx
].revents
!= 0 && keyring
) {
636 (void) flush_fd(inotify_fd
);
638 r
= ask_password_keyring(req
, flags
, ret
);
642 } else if (r
!= -ENOKEY
)
646 if (pollfd
[POLL_TTY
].revents
== 0)
649 n
= read(ttyfd
>= 0 ? ttyfd
: STDIN_FILENO
, &c
, 1);
651 if (ERRNO_IS_TRANSIENT(errno
))
659 if (press_tab_visible
) {
661 backspace_chars(ttyfd
, strlen(PRESS_TAB
));
662 press_tab_visible
= false;
665 /* We treat EOF, newline and NUL byte all as valid end markers */
666 if (n
== 0 || c
== '\n' || c
== 0)
669 if (c
== 4) { /* C-d also known as EOT */
671 (void) loop_write(ttyfd
, SKIPPED
, SIZE_MAX
);
676 if (c
== 21) { /* C-u */
678 if (!FLAGS_SET(flags
, ASK_PASSWORD_SILENT
))
679 (void) backspace_string(ttyfd
, passphrase
);
681 explicit_bzero_safe(passphrase
, sizeof(passphrase
));
684 } else if (IN_SET(c
, '\b', 127)) {
689 if (!FLAGS_SET(flags
, ASK_PASSWORD_SILENT
))
690 (void) backspace_chars(ttyfd
, 1);
692 /* Remove a full UTF-8 codepoint from the end. For that, figure out where the
698 z
= utf8_encoded_valid_unichar(passphrase
+ q
, SIZE_MAX
);
700 q
= SIZE_MAX
; /* Invalid UTF8! */
704 if (q
+ z
>= p
) /* This one brings us over the edge */
710 p
= codepoint
= q
== SIZE_MAX
? p
- 1 : q
;
711 explicit_bzero_safe(passphrase
+ p
, sizeof(passphrase
) - p
);
713 } else if (!dirty
&& !FLAGS_SET(flags
, ASK_PASSWORD_SILENT
)) {
715 flags
|= ASK_PASSWORD_SILENT
;
717 /* There are two ways to enter silent mode. Either by pressing backspace as
718 * first key (and only as first key), or ... */
721 (void) loop_write(ttyfd
, NO_ECHO
, SIZE_MAX
);
723 } else if (ttyfd
>= 0)
724 (void) loop_write(ttyfd
, "\a", 1);
726 } else if (c
== '\t' && !FLAGS_SET(flags
, ASK_PASSWORD_SILENT
)) {
728 (void) backspace_string(ttyfd
, passphrase
);
729 flags
|= ASK_PASSWORD_SILENT
;
731 /* ... or by pressing TAB at any time. */
734 (void) loop_write(ttyfd
, NO_ECHO
, SIZE_MAX
);
736 } else if (char_is_cc(c
) || p
>= sizeof(passphrase
)-1) {
737 /* Don't accept control chars or overly long passphrases */
739 (void) loop_write(ttyfd
, "\a", 1);
744 if (!FLAGS_SET(flags
, ASK_PASSWORD_SILENT
) && ttyfd
>= 0) {
745 /* Check if we got a complete UTF-8 character now. If so, let's output one '*'. */
746 n
= utf8_encoded_valid_unichar(passphrase
+ codepoint
, SIZE_MAX
);
748 if (FLAGS_SET(flags
, ASK_PASSWORD_ECHO
))
749 (void) loop_write(ttyfd
, passphrase
+ codepoint
, n
);
751 (void) loop_write(ttyfd
,
762 x
= strndup(passphrase
, p
);
768 r
= strv_consume(&l
, x
);
774 r
= log_debug_errno(SYNTHETIC_ERRNO(ECANCELED
), "Password query was cancelled.");
777 (void) add_to_keyring_and_log(keyring
, flags
, l
);
784 if (ttyfd
>= 0 && reset_tty
) {
785 (void) loop_write(ttyfd
, "\n", 1);
786 (void) tcsetattr(ttyfd
, TCSANOW
, &old_termios
);
792 static int create_socket(const char *askpwdir
, char **ret
) {
793 _cleanup_free_
char *path
= NULL
;
794 union sockaddr_union sa
;
796 _cleanup_close_
int fd
= -EBADF
;
802 fd
= socket(AF_UNIX
, SOCK_DGRAM
|SOCK_CLOEXEC
|SOCK_NONBLOCK
, 0);
806 if (asprintf(&path
, "%s/sck.%" PRIx64
, askpwdir
, random_u64()) < 0)
809 r
= sockaddr_un_set_path(&sa
.un
, path
);
815 if (bind(fd
, &sa
.sa
, sa_len
) < 0)
818 r
= setsockopt_int(fd
, SOL_SOCKET
, SO_PASSCRED
, true);
822 (void) setsockopt_int(fd
, SOL_SOCKET
, SO_PASSRIGHTS
, false);
824 *ret
= TAKE_PTR(path
);
828 int ask_password_agent(
829 const AskPasswordRequest
*req
,
830 AskPasswordFlags flags
,
833 _cleanup_close_
int socket_fd
= -EBADF
, signal_fd
= -EBADF
, inotify_fd
= -EBADF
, dfd
= -EBADF
;
834 _cleanup_(unlink_and_freep
) char *socket_name
= NULL
;
835 _cleanup_free_
char *temp
= NULL
, *final
= NULL
;
836 _cleanup_strv_free_erase_
char **l
= NULL
;
837 _cleanup_fclose_
FILE *f
= NULL
;
838 sigset_t mask
, oldmask
;
844 if (FLAGS_SET(flags
, ASK_PASSWORD_HEADLESS
))
847 if (FLAGS_SET(flags
, ASK_PASSWORD_NO_AGENT
))
850 /* We don't support the flag file concept for now when querying via the agent logic */
854 assert_se(sigemptyset(&mask
) >= 0);
855 assert_se(sigset_add_many(&mask
, SIGINT
, SIGTERM
) >= 0);
856 assert_se(sigprocmask(SIG_BLOCK
, &mask
, &oldmask
) >= 0);
858 _cleanup_free_
char *askpwdir
= NULL
;
859 r
= get_ask_password_directory_for_flags(flags
, &askpwdir
);
867 dfd
= open_mkdir(askpwdir
, O_RDONLY
|O_CLOEXEC
, 0755);
869 r
= log_debug_errno(dfd
, "Failed to open directory '%s': %m", askpwdir
);
873 if (FLAGS_SET(flags
, ASK_PASSWORD_ACCEPT_CACHED
) && req
->keyring
) {
874 r
= ask_password_keyring(req
, flags
, ret
);
878 } else if (r
!= -ENOKEY
)
881 inotify_fd
= inotify_init1(IN_CLOEXEC
| IN_NONBLOCK
);
882 if (inotify_fd
< 0) {
887 r
= inotify_add_watch_fd(inotify_fd
, dfd
, IN_ONLYDIR
|IN_ATTRIB
/* for mtime */);
892 if (asprintf(&final
, "ask.%" PRIu64
, random_u64()) < 0) {
897 r
= fopen_temporary_at(dfd
, final
, &f
, &temp
);
901 signal_fd
= signalfd(-1, &mask
, SFD_NONBLOCK
|SFD_CLOEXEC
);
907 socket_fd
= create_socket(askpwdir
, &socket_name
);
919 "NotAfter="USEC_FMT
"\n"
923 FLAGS_SET(flags
, ASK_PASSWORD_ACCEPT_CACHED
),
924 FLAGS_SET(flags
, ASK_PASSWORD_ECHO
),
926 FLAGS_SET(flags
, ASK_PASSWORD_SILENT
));
929 fprintf(f
, "Message=%s\n", req
->message
);
932 fprintf(f
, "Icon=%s\n", req
->icon
);
935 fprintf(f
, "Id=%s\n", req
->id
);
937 if (fchmod(fileno(f
), 0644) < 0) {
942 r
= fflush_and_check(f
);
946 if (renameat(dfd
, temp
, dfd
, final
) < 0) {
961 struct pollfd pollfd
[_POLL_MAX
] = {
962 [POLL_SOCKET
] = { .fd
= socket_fd
, .events
= POLLIN
},
963 [POLL_SIGNAL
] = { .fd
= signal_fd
, .events
= POLLIN
},
965 size_t n_pollfd
= POLL_SIGNAL
+ 1, inotify_idx
= SIZE_MAX
, hup_fd_idx
= SIZE_MAX
;
968 pollfd
[inotify_idx
= n_pollfd
++] = (struct pollfd
) {
972 if (req
->hup_fd
>= 0)
973 pollfd
[hup_fd_idx
= n_pollfd
++] = (struct pollfd
) {
978 assert(n_pollfd
<= _POLL_MAX
);
981 CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct ucred
))) control
;
982 char passphrase
[LINE_MAX
+1];
989 timeout
= usec_sub_unsigned(req
->until
, now(CLOCK_MONOTONIC
));
991 timeout
= USEC_INFINITY
;
993 r
= ppoll_usec(pollfd
, n_pollfd
, timeout
);
1003 if (pollfd
[POLL_SIGNAL
].revents
& POLLIN
) {
1008 if (req
->hup_fd
>= 0 && pollfd
[hup_fd_idx
].revents
& POLLHUP
)
1011 if (inotify_fd
>= 0 && pollfd
[inotify_idx
].revents
!= 0) {
1012 (void) flush_fd(inotify_fd
);
1015 r
= ask_password_keyring(req
, flags
, ret
);
1019 } else if (r
!= -ENOKEY
)
1024 if (pollfd
[POLL_SOCKET
].revents
== 0)
1027 if (pollfd
[POLL_SOCKET
].revents
!= POLLIN
) {
1032 iovec
= IOVEC_MAKE(passphrase
, sizeof(passphrase
));
1034 struct msghdr msghdr
= {
1037 .msg_control
= &control
,
1038 .msg_controllen
= sizeof(control
),
1041 n
= recvmsg_safe(socket_fd
, &msghdr
, 0);
1042 if (ERRNO_IS_NEG_TRANSIENT(n
))
1045 log_debug_errno(n
, "Got message with truncated control data (unexpected fds sent?), ignoring.");
1049 log_debug_errno(n
, "Got message with truncated payload data, ignoring.");
1057 CLEANUP_ERASE(passphrase
);
1059 cmsg_close_all(&msghdr
);
1062 log_debug("Message too short");
1066 ucred
= CMSG_FIND_DATA(&msghdr
, SOL_SOCKET
, SCM_CREDENTIALS
, struct ucred
);
1068 log_debug("Received message without credentials. Ignoring.");
1072 if (ucred
->uid
!= getuid() && ucred
->uid
!= 0) {
1073 log_debug("Got response from bad user. Ignoring.");
1077 if (passphrase
[0] == '+') {
1078 /* An empty message refers to the empty password */
1082 l
= strv_parse_nulstr(passphrase
+1, n
-1);
1088 if (strv_isempty(l
)) {
1090 log_debug("Invalid packet");
1097 if (passphrase
[0] == '-') {
1102 log_debug("Invalid packet");
1106 (void) add_to_keyring_and_log(req
->keyring
, flags
, l
);
1114 (void) unlinkat(dfd
, temp
, 0);
1117 (void) unlinkat(dfd
, final
, 0);
1120 assert_se(sigprocmask(SIG_SETMASK
, &oldmask
, NULL
) == 0);
1124 static int ask_password_credential(const AskPasswordRequest
*req
, AskPasswordFlags flags
, char ***ret
) {
1125 _cleanup_(erase_and_freep
) char *buffer
= NULL
;
1126 _cleanup_strv_free_erase_
char **l
= NULL
;
1131 assert(req
->credential
);
1134 r
= read_credential(req
->credential
, (void**) &buffer
, &size
);
1135 if (IN_SET(r
, -ENXIO
, -ENOENT
)) /* No credentials passed or this credential not defined? */
1138 l
= strv_parse_nulstr(buffer
, size
);
1142 if (strv_isempty(l
))
1143 return log_debug_errno(SYNTHETIC_ERRNO(ENOKEY
), "Found an empty password in credential.");
1149 int ask_password_auto(
1150 const AskPasswordRequest
*req
,
1151 AskPasswordFlags flags
,
1159 /* Returns the following well-known errors:
1161 * -ETIME → a timeout was specified and hit
1162 * -EUNATCH → couldn't ask interactively and no cached password available either
1163 * -ENOENT → the specified flag file disappeared
1164 * -ECANCELED → the user explicitly cancelled the request
1165 * -EINTR → SIGINT/SIGTERM where received during the query
1166 * -ENOEXEC → headless mode was requested but no password could be acquired non-interactively
1167 * -ECONNRESET → a POLLHUP has been seen on the specified hup_fd
1170 if (!FLAGS_SET(flags
, ASK_PASSWORD_NO_CREDENTIAL
) && req
->credential
) {
1171 r
= ask_password_credential(req
, flags
, ret
);
1176 if (FLAGS_SET(flags
, ASK_PASSWORD_ACCEPT_CACHED
) &&
1178 (FLAGS_SET(flags
, ASK_PASSWORD_NO_TTY
) || !isatty_safe(STDIN_FILENO
)) &&
1179 FLAGS_SET(flags
, ASK_PASSWORD_NO_AGENT
)) {
1180 r
= ask_password_keyring(req
, flags
, ret
);
1185 if (!FLAGS_SET(flags
, ASK_PASSWORD_NO_TTY
) && isatty_safe(STDIN_FILENO
))
1186 return ask_password_tty(req
, flags
, ret
);
1188 if (!FLAGS_SET(flags
, ASK_PASSWORD_NO_AGENT
))
1189 return ask_password_agent(req
, flags
, ret
);
1194 int acquire_user_ask_password_directory(char **ret
) {
1197 r
= xdg_user_runtime_dir("systemd/ask-password", ret
);