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