]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/ask-password/ask-password.c
ask-password: allow to control lock and key emoji
[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;
490aed58 27
c7d7adf5
YW
28STATIC_DESTRUCTOR_REGISTER(arg_message, freep);
29
37ec0fdd
LP
30static int help(void) {
31 _cleanup_free_ char *link = NULL;
32 int r;
33
34 r = terminal_urlify_man("systemd-ask-password", "1", &link);
35 if (r < 0)
36 return log_oom();
37
8806bb4b
LP
38 printf("%1$s [OPTIONS...] MESSAGE\n\n"
39 "%3$sQuery the user for a system passphrase, via the TTY or an UI agent.%4$s\n\n"
e287086b
LP
40 " -h --help Show this help\n"
41 " --icon=NAME Icon name\n"
42 " --id=ID Query identifier (e.g. \"cryptsetup:/dev/sda5\")\n"
43 " --keyname=NAME Kernel key name for caching passwords (e.g. \"cryptsetup\")\n"
8806bb4b
LP
44 " --credential=NAME\n"
45 " Credential name for LoadCredential=/SetCredential=\n"
46 " credentials\n"
e287086b
LP
47 " --timeout=SEC Timeout in seconds\n"
48 " --echo Do not mask input (useful for usernames)\n"
e390c34d
CH
49 " --emoji=yes|no|auto\n"
50 " Show a lock and key emoji\n"
e287086b
LP
51 " --no-tty Ask question via agent even on TTY\n"
52 " --accept-cached Accept cached passwords\n"
53 " --multiple List multiple passwords if available\n"
a5a4e365 54 " --no-output Do not print password to standard output\n"
8806bb4b 55 "\nSee the %2$s for details.\n",
bc556335 56 program_invocation_short_name,
8806bb4b
LP
57 link,
58 ansi_highlight(),
59 ansi_normal());
37ec0fdd
LP
60
61 return 0;
490aed58
LP
62}
63
64static int parse_argv(int argc, char *argv[]) {
65
66 enum {
67 ARG_ICON = 0x100,
1b39d4b9 68 ARG_TIMEOUT,
64845bdc 69 ARG_ECHO,
e390c34d 70 ARG_EMOJI,
21bc923a
LP
71 ARG_NO_TTY,
72 ARG_ACCEPT_CACHED,
9fa1de96 73 ARG_MULTIPLE,
e287086b
LP
74 ARG_ID,
75 ARG_KEYNAME,
a5a4e365 76 ARG_NO_OUTPUT,
37ec0fdd 77 ARG_VERSION,
8806bb4b 78 ARG_CREDENTIAL,
490aed58
LP
79 };
80
81 static const struct option options[] = {
21bc923a 82 { "help", no_argument, NULL, 'h' },
37ec0fdd 83 { "version", no_argument, NULL, ARG_VERSION },
21bc923a
LP
84 { "icon", required_argument, NULL, ARG_ICON },
85 { "timeout", required_argument, NULL, ARG_TIMEOUT },
64845bdc 86 { "echo", no_argument, NULL, ARG_ECHO },
e390c34d 87 { "emoji", required_argument, NULL, ARG_EMOJI },
21bc923a
LP
88 { "no-tty", no_argument, NULL, ARG_NO_TTY },
89 { "accept-cached", no_argument, NULL, ARG_ACCEPT_CACHED },
90 { "multiple", no_argument, NULL, ARG_MULTIPLE },
9fa1de96 91 { "id", required_argument, NULL, ARG_ID },
e287086b 92 { "keyname", required_argument, NULL, ARG_KEYNAME },
a5a4e365 93 { "no-output", no_argument, NULL, ARG_NO_OUTPUT },
8806bb4b 94 { "credential", required_argument, NULL, ARG_CREDENTIAL },
eb9da376 95 {}
490aed58
LP
96 };
97
e390c34d 98 const char *emoji = NULL;
490aed58
LP
99 int c;
100
101 assert(argc >= 0);
102 assert(argv);
103
601185b4 104 while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
490aed58
LP
105
106 switch (c) {
107
108 case 'h':
37ec0fdd
LP
109 return help();
110
111 case ARG_VERSION:
112 return version();
490aed58
LP
113
114 case ARG_ICON:
115 arg_icon = optarg;
116 break;
117
118 case ARG_TIMEOUT:
baaa35ad
ZJS
119 if (parse_sec(optarg, &arg_timeout) < 0)
120 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
121 "Failed to parse --timeout parameter %s",
122 optarg);
490aed58
LP
123 break;
124
64845bdc 125 case ARG_ECHO:
e287086b 126 arg_flags |= ASK_PASSWORD_ECHO;
64845bdc
DS
127 break;
128
e390c34d
CH
129 case ARG_EMOJI:
130 emoji = optarg;
131 break;
132
1b39d4b9 133 case ARG_NO_TTY:
e287086b 134 arg_flags |= ASK_PASSWORD_NO_TTY;
1b39d4b9
LP
135 break;
136
21bc923a 137 case ARG_ACCEPT_CACHED:
e287086b 138 arg_flags |= ASK_PASSWORD_ACCEPT_CACHED;
21bc923a
LP
139 break;
140
141 case ARG_MULTIPLE:
142 arg_multiple = true;
143 break;
144
9fa1de96
DH
145 case ARG_ID:
146 arg_id = optarg;
147 break;
148
e287086b 149 case ARG_KEYNAME:
8806bb4b 150 arg_key_name = optarg;
e287086b
LP
151 break;
152
a5a4e365
CH
153 case ARG_NO_OUTPUT:
154 arg_no_output = true;
155 break;
156
8806bb4b
LP
157 case ARG_CREDENTIAL:
158 arg_credential_name = optarg;
159 break;
160
490aed58
LP
161 case '?':
162 return -EINVAL;
163
164 default:
eb9da376 165 assert_not_reached("Unhandled option");
490aed58 166 }
490aed58 167
e390c34d
CH
168 if (isempty(emoji) || streq(emoji, "auto"))
169 SET_FLAG(arg_flags, ASK_PASSWORD_HIDE_EMOJI, FLAGS_SET(arg_flags, ASK_PASSWORD_ECHO));
170 else {
171 int r;
172 bool b;
173
174 r = parse_boolean_argument("--emoji=", emoji, &b);
175 if (r < 0)
176 return r;
177 SET_FLAG(arg_flags, ASK_PASSWORD_HIDE_EMOJI, !b);
178 }
179
e287086b
LP
180 if (argc > optind) {
181 arg_message = strv_join(argv + optind, " ");
182 if (!arg_message)
183 return log_oom();
490aed58
LP
184 }
185
1b39d4b9 186 return 1;
490aed58
LP
187}
188
c7d7adf5 189static int run(int argc, char *argv[]) {
ab84f5b9 190 _cleanup_strv_free_erase_ char **l = NULL;
7dcda352 191 usec_t timeout;
e287086b
LP
192 char **p;
193 int r;
1b39d4b9 194
1a043959 195 log_show_color(true);
1b39d4b9
LP
196 log_parse_environment();
197 log_open();
198
601185b4
ZJS
199 r = parse_argv(argc, argv);
200 if (r <= 0)
c7d7adf5 201 return r;
1b39d4b9 202
7dcda352 203 if (arg_timeout > 0)
496db330 204 timeout = usec_add(now(CLOCK_MONOTONIC), arg_timeout);
7dcda352
LP
205 else
206 timeout = 0;
207
8806bb4b 208 r = ask_password_auto(arg_message, arg_icon, arg_id, arg_key_name, arg_credential_name ?: "password", timeout, arg_flags, &l);
c7d7adf5
YW
209 if (r < 0)
210 return log_error_errno(r, "Failed to query password: %m");
21bc923a 211
e287086b 212 STRV_FOREACH(p, l) {
a5a4e365
CH
213 if (!arg_no_output)
214 puts(*p);
ec863ba6 215
e287086b
LP
216 if (!arg_multiple)
217 break;
7f4e0805 218 }
1b39d4b9 219
c7d7adf5 220 return 0;
1b39d4b9 221}
c7d7adf5
YW
222
223DEFINE_MAIN_FUNCTION(run);