]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/ask-password/ask-password.c
basic,shared: move disable_coredumps() to coredump-util.[ch]
[thirdparty/systemd.git] / src / ask-password / ask-password.c
CommitLineData
db9ecf05 1/* SPDX-License-Identifier: LGPL-2.1-or-later */
490aed58 2
490aed58 3#include <errno.h>
490aed58 4#include <getopt.h>
0e098b15 5#include <stddef.h>
00843602 6#include <unistd.h>
490aed58 7
00843602
LP
8#include "ask-password-api.h"
9#include "def.h"
490aed58
LP
10#include "log.h"
11#include "macro.h"
c7d7adf5 12#include "main-func.h"
e390c34d 13#include "parse-argument.h"
294bf0c3 14#include "pretty-print.h"
21bc923a 15#include "strv.h"
8806bb4b 16#include "terminal-util.h"
490aed58
LP
17
18static const char *arg_icon = NULL;
8806bb4b
LP
19static const char *arg_id = NULL; /* identifier for 'ask-password' protocol */
20static const char *arg_key_name = NULL; /* name in kernel keyring */
21static const char *arg_credential_name = NULL; /* name in $CREDENTIALS_DIRECTORY directory */
e287086b 22static char *arg_message = NULL;
7f434cf4 23static usec_t arg_timeout = DEFAULT_TIMEOUT_USEC;
21bc923a 24static bool arg_multiple = false;
a5a4e365 25static bool arg_no_output = false;
e287086b 26static AskPasswordFlags arg_flags = ASK_PASSWORD_PUSH_CACHE;
b80ef40c 27static bool arg_newline = true;
490aed58 28
c7d7adf5
YW
29STATIC_DESTRUCTOR_REGISTER(arg_message, freep);
30
37ec0fdd
LP
31static int help(void) {
32 _cleanup_free_ char *link = NULL;
33 int r;
34
35 r = terminal_urlify_man("systemd-ask-password", "1", &link);
36 if (r < 0)
37 return log_oom();
38
8806bb4b
LP
39 printf("%1$s [OPTIONS...] MESSAGE\n\n"
40 "%3$sQuery the user for a system passphrase, via the TTY or an UI agent.%4$s\n\n"
e287086b
LP
41 " -h --help Show this help\n"
42 " --icon=NAME Icon name\n"
43 " --id=ID Query identifier (e.g. \"cryptsetup:/dev/sda5\")\n"
44 " --keyname=NAME Kernel key name for caching passwords (e.g. \"cryptsetup\")\n"
8806bb4b
LP
45 " --credential=NAME\n"
46 " Credential name for LoadCredential=/SetCredential=\n"
47 " credentials\n"
e287086b 48 " --timeout=SEC Timeout in seconds\n"
49365d1c
LP
49 " --echo=yes|no|masked\n"
50 " Control whether to show password while typing (echo)\n"
51 " -e --echo Equivalent to --echo=yes\n"
e390c34d
CH
52 " --emoji=yes|no|auto\n"
53 " Show a lock and key emoji\n"
e287086b
LP
54 " --no-tty Ask question via agent even on TTY\n"
55 " --accept-cached Accept cached passwords\n"
56 " --multiple List multiple passwords if available\n"
a5a4e365 57 " --no-output Do not print password to standard output\n"
b80ef40c
LP
58 " -n Do not suffix password written to standard output with\n"
59 " newline\n"
8806bb4b 60 "\nSee the %2$s for details.\n",
bc556335 61 program_invocation_short_name,
8806bb4b
LP
62 link,
63 ansi_highlight(),
64 ansi_normal());
37ec0fdd
LP
65
66 return 0;
490aed58
LP
67}
68
69static int parse_argv(int argc, char *argv[]) {
70
71 enum {
72 ARG_ICON = 0x100,
1b39d4b9 73 ARG_TIMEOUT,
e390c34d 74 ARG_EMOJI,
21bc923a
LP
75 ARG_NO_TTY,
76 ARG_ACCEPT_CACHED,
9fa1de96 77 ARG_MULTIPLE,
e287086b
LP
78 ARG_ID,
79 ARG_KEYNAME,
a5a4e365 80 ARG_NO_OUTPUT,
37ec0fdd 81 ARG_VERSION,
8806bb4b 82 ARG_CREDENTIAL,
490aed58
LP
83 };
84
85 static const struct option options[] = {
21bc923a 86 { "help", no_argument, NULL, 'h' },
37ec0fdd 87 { "version", no_argument, NULL, ARG_VERSION },
21bc923a
LP
88 { "icon", required_argument, NULL, ARG_ICON },
89 { "timeout", required_argument, NULL, ARG_TIMEOUT },
49365d1c 90 { "echo", optional_argument, NULL, 'e' },
e390c34d 91 { "emoji", required_argument, NULL, ARG_EMOJI },
21bc923a
LP
92 { "no-tty", no_argument, NULL, ARG_NO_TTY },
93 { "accept-cached", no_argument, NULL, ARG_ACCEPT_CACHED },
94 { "multiple", no_argument, NULL, ARG_MULTIPLE },
9fa1de96 95 { "id", required_argument, NULL, ARG_ID },
e287086b 96 { "keyname", required_argument, NULL, ARG_KEYNAME },
a5a4e365 97 { "no-output", no_argument, NULL, ARG_NO_OUTPUT },
8806bb4b 98 { "credential", required_argument, NULL, ARG_CREDENTIAL },
eb9da376 99 {}
490aed58
LP
100 };
101
e390c34d 102 const char *emoji = NULL;
49365d1c 103 int c, r;
490aed58
LP
104
105 assert(argc >= 0);
106 assert(argv);
107
49365d1c
LP
108 /* Note the asymmetry: the long option --echo= allows an optional argument, the short option does
109 * not. */
b80ef40c 110 while ((c = getopt_long(argc, argv, "+hen", options, NULL)) >= 0)
490aed58
LP
111
112 switch (c) {
113
114 case 'h':
37ec0fdd
LP
115 return help();
116
117 case ARG_VERSION:
118 return version();
490aed58
LP
119
120 case ARG_ICON:
121 arg_icon = optarg;
122 break;
123
124 case ARG_TIMEOUT:
49365d1c
LP
125 r = parse_sec(optarg, &arg_timeout);
126 if (r < 0)
127 return log_error_errno(r, "Failed to parse --timeout= parameter: %s", optarg);
128
490aed58
LP
129 break;
130
49365d1c
LP
131 case 'e':
132 if (!optarg) {
133 /* Short option -e is used, or no argument to long option --echo= */
134 arg_flags |= ASK_PASSWORD_ECHO;
135 arg_flags &= ~ASK_PASSWORD_SILENT;
136 } else if (isempty(optarg) || streq(optarg, "masked"))
137 /* Empty argument or explicit string "masked" for default behaviour. */
138 arg_flags &= ~(ASK_PASSWORD_ECHO|ASK_PASSWORD_SILENT);
139 else {
140 bool b;
141
142 r = parse_boolean_argument("--echo=", optarg, &b);
143 if (r < 0)
144 return r;
145
146 SET_FLAG(arg_flags, ASK_PASSWORD_ECHO, b);
147 SET_FLAG(arg_flags, ASK_PASSWORD_SILENT, !b);
148 }
64845bdc
DS
149 break;
150
e390c34d
CH
151 case ARG_EMOJI:
152 emoji = optarg;
153 break;
154
1b39d4b9 155 case ARG_NO_TTY:
e287086b 156 arg_flags |= ASK_PASSWORD_NO_TTY;
1b39d4b9
LP
157 break;
158
21bc923a 159 case ARG_ACCEPT_CACHED:
e287086b 160 arg_flags |= ASK_PASSWORD_ACCEPT_CACHED;
21bc923a
LP
161 break;
162
163 case ARG_MULTIPLE:
164 arg_multiple = true;
165 break;
166
9fa1de96
DH
167 case ARG_ID:
168 arg_id = optarg;
169 break;
170
e287086b 171 case ARG_KEYNAME:
8806bb4b 172 arg_key_name = optarg;
e287086b
LP
173 break;
174
a5a4e365
CH
175 case ARG_NO_OUTPUT:
176 arg_no_output = true;
177 break;
178
8806bb4b
LP
179 case ARG_CREDENTIAL:
180 arg_credential_name = optarg;
181 break;
182
b80ef40c
LP
183 case 'n':
184 arg_newline = false;
185 break;
186
490aed58
LP
187 case '?':
188 return -EINVAL;
189
190 default:
04499a70 191 assert_not_reached();
490aed58 192 }
490aed58 193
e390c34d
CH
194 if (isempty(emoji) || streq(emoji, "auto"))
195 SET_FLAG(arg_flags, ASK_PASSWORD_HIDE_EMOJI, FLAGS_SET(arg_flags, ASK_PASSWORD_ECHO));
196 else {
e390c34d
CH
197 bool b;
198
199 r = parse_boolean_argument("--emoji=", emoji, &b);
200 if (r < 0)
201 return r;
49365d1c 202
e390c34d
CH
203 SET_FLAG(arg_flags, ASK_PASSWORD_HIDE_EMOJI, !b);
204 }
205
e287086b
LP
206 if (argc > optind) {
207 arg_message = strv_join(argv + optind, " ");
a5116848
LP
208 if (!arg_message)
209 return log_oom();
210 } else if (FLAGS_SET(arg_flags, ASK_PASSWORD_ECHO)) {
211 /* By default ask_password_auto() will query with the string "Password: ", which is not right
212 * when full echo is on, since then it's unlikely a password. Let's hence default to a less
213 * confusing string in that case. */
214
215 arg_message = strdup("Input:");
e287086b
LP
216 if (!arg_message)
217 return log_oom();
490aed58
LP
218 }
219
1b39d4b9 220 return 1;
490aed58
LP
221}
222
c7d7adf5 223static int run(int argc, char *argv[]) {
ab84f5b9 224 _cleanup_strv_free_erase_ char **l = NULL;
7dcda352 225 usec_t timeout;
e287086b 226 int r;
1b39d4b9 227
1a043959 228 log_show_color(true);
1b39d4b9
LP
229 log_parse_environment();
230 log_open();
231
601185b4
ZJS
232 r = parse_argv(argc, argv);
233 if (r <= 0)
c7d7adf5 234 return r;
1b39d4b9 235
7dcda352 236 if (arg_timeout > 0)
496db330 237 timeout = usec_add(now(CLOCK_MONOTONIC), arg_timeout);
7dcda352
LP
238 else
239 timeout = 0;
240
8806bb4b 241 r = ask_password_auto(arg_message, arg_icon, arg_id, arg_key_name, arg_credential_name ?: "password", timeout, arg_flags, &l);
c7d7adf5
YW
242 if (r < 0)
243 return log_error_errno(r, "Failed to query password: %m");
21bc923a 244
e287086b 245 STRV_FOREACH(p, l) {
b80ef40c
LP
246 if (!arg_no_output) {
247 if (arg_newline)
248 puts(*p);
249 else
250 fputs(*p, stdout);
251 }
252
253 fflush(stdout);
ec863ba6 254
e287086b
LP
255 if (!arg_multiple)
256 break;
7f4e0805 257 }
1b39d4b9 258
c7d7adf5 259 return 0;
1b39d4b9 260}
c7d7adf5
YW
261
262DEFINE_MAIN_FUNCTION(run);