Line data Source code
1 : /* SPDX-License-Identifier: LGPL-2.1+ */
2 :
3 : #include <errno.h>
4 : #include <getopt.h>
5 : #include <stddef.h>
6 : #include <unistd.h>
7 :
8 : #include "ask-password-api.h"
9 : #include "def.h"
10 : #include "log.h"
11 : #include "macro.h"
12 : #include "main-func.h"
13 : #include "pretty-print.h"
14 : #include "strv.h"
15 :
16 : static const char *arg_icon = NULL;
17 : static const char *arg_id = NULL;
18 : static const char *arg_keyname = NULL;
19 : static char *arg_message = NULL;
20 : static usec_t arg_timeout = DEFAULT_TIMEOUT_USEC;
21 : static bool arg_multiple = false;
22 : static bool arg_no_output = false;
23 : static AskPasswordFlags arg_flags = ASK_PASSWORD_PUSH_CACHE;
24 :
25 4 : STATIC_DESTRUCTOR_REGISTER(arg_message, freep);
26 :
27 3 : static int help(void) {
28 3 : _cleanup_free_ char *link = NULL;
29 : int r;
30 :
31 3 : r = terminal_urlify_man("systemd-ask-password", "1", &link);
32 3 : if (r < 0)
33 0 : return log_oom();
34 :
35 3 : printf("%s [OPTIONS...] MESSAGE\n\n"
36 : "Query the user for a system passphrase, via the TTY or an UI agent.\n\n"
37 : " -h --help Show this help\n"
38 : " --icon=NAME Icon name\n"
39 : " --id=ID Query identifier (e.g. \"cryptsetup:/dev/sda5\")\n"
40 : " --keyname=NAME Kernel key name for caching passwords (e.g. \"cryptsetup\")\n"
41 : " --timeout=SEC Timeout in seconds\n"
42 : " --echo Do not mask input (useful for usernames)\n"
43 : " --no-tty Ask question via agent even on TTY\n"
44 : " --accept-cached Accept cached passwords\n"
45 : " --multiple List multiple passwords if available\n"
46 : " --no-output Do not print password to standard output\n"
47 : "\nSee the %s for details.\n"
48 : , program_invocation_short_name
49 : , link
50 : );
51 :
52 3 : return 0;
53 : }
54 :
55 4 : static int parse_argv(int argc, char *argv[]) {
56 :
57 : enum {
58 : ARG_ICON = 0x100,
59 : ARG_TIMEOUT,
60 : ARG_ECHO,
61 : ARG_NO_TTY,
62 : ARG_ACCEPT_CACHED,
63 : ARG_MULTIPLE,
64 : ARG_ID,
65 : ARG_KEYNAME,
66 : ARG_NO_OUTPUT,
67 : ARG_VERSION,
68 : };
69 :
70 : static const struct option options[] = {
71 : { "help", no_argument, NULL, 'h' },
72 : { "version", no_argument, NULL, ARG_VERSION },
73 : { "icon", required_argument, NULL, ARG_ICON },
74 : { "timeout", required_argument, NULL, ARG_TIMEOUT },
75 : { "echo", no_argument, NULL, ARG_ECHO },
76 : { "no-tty", no_argument, NULL, ARG_NO_TTY },
77 : { "accept-cached", no_argument, NULL, ARG_ACCEPT_CACHED },
78 : { "multiple", no_argument, NULL, ARG_MULTIPLE },
79 : { "id", required_argument, NULL, ARG_ID },
80 : { "keyname", required_argument, NULL, ARG_KEYNAME },
81 : { "no-output", no_argument, NULL, ARG_NO_OUTPUT },
82 : {}
83 : };
84 :
85 : int c;
86 :
87 4 : assert(argc >= 0);
88 4 : assert(argv);
89 :
90 4 : while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
91 :
92 4 : switch (c) {
93 :
94 3 : case 'h':
95 3 : return help();
96 :
97 0 : case ARG_VERSION:
98 0 : return version();
99 :
100 0 : case ARG_ICON:
101 0 : arg_icon = optarg;
102 0 : break;
103 :
104 0 : case ARG_TIMEOUT:
105 0 : if (parse_sec(optarg, &arg_timeout) < 0)
106 0 : return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
107 : "Failed to parse --timeout parameter %s",
108 : optarg);
109 0 : break;
110 :
111 0 : case ARG_ECHO:
112 0 : arg_flags |= ASK_PASSWORD_ECHO;
113 0 : break;
114 :
115 0 : case ARG_NO_TTY:
116 0 : arg_flags |= ASK_PASSWORD_NO_TTY;
117 0 : break;
118 :
119 0 : case ARG_ACCEPT_CACHED:
120 0 : arg_flags |= ASK_PASSWORD_ACCEPT_CACHED;
121 0 : break;
122 :
123 0 : case ARG_MULTIPLE:
124 0 : arg_multiple = true;
125 0 : break;
126 :
127 0 : case ARG_ID:
128 0 : arg_id = optarg;
129 0 : break;
130 :
131 0 : case ARG_KEYNAME:
132 0 : arg_keyname = optarg;
133 0 : break;
134 :
135 0 : case ARG_NO_OUTPUT:
136 0 : arg_no_output = true;
137 0 : break;
138 :
139 1 : case '?':
140 1 : return -EINVAL;
141 :
142 0 : default:
143 0 : assert_not_reached("Unhandled option");
144 : }
145 :
146 0 : if (argc > optind) {
147 0 : arg_message = strv_join(argv + optind, " ");
148 0 : if (!arg_message)
149 0 : return log_oom();
150 : }
151 :
152 0 : return 1;
153 : }
154 :
155 4 : static int run(int argc, char *argv[]) {
156 4 : _cleanup_strv_free_erase_ char **l = NULL;
157 : usec_t timeout;
158 : char **p;
159 : int r;
160 :
161 4 : log_show_color(true);
162 4 : log_parse_environment();
163 4 : log_open();
164 :
165 4 : r = parse_argv(argc, argv);
166 4 : if (r <= 0)
167 4 : return r;
168 :
169 0 : if (arg_timeout > 0)
170 0 : timeout = now(CLOCK_MONOTONIC) + arg_timeout;
171 : else
172 0 : timeout = 0;
173 :
174 0 : r = ask_password_auto(arg_message, arg_icon, arg_id, arg_keyname, timeout, arg_flags, &l);
175 0 : if (r < 0)
176 0 : return log_error_errno(r, "Failed to query password: %m");
177 :
178 0 : STRV_FOREACH(p, l) {
179 0 : if (!arg_no_output)
180 0 : puts(*p);
181 :
182 0 : if (!arg_multiple)
183 0 : break;
184 : }
185 :
186 0 : return 0;
187 : }
188 :
189 4 : DEFINE_MAIN_FUNCTION(run);
|