Branch data 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 : 16 : STATIC_DESTRUCTOR_REGISTER(arg_message, freep);
26 : :
27 : 12 : static int help(void) {
28 : 12 : _cleanup_free_ char *link = NULL;
29 : : int r;
30 : :
31 : 12 : r = terminal_urlify_man("systemd-ask-password", "1", &link);
32 [ - + ]: 12 : if (r < 0)
33 : 0 : return log_oom();
34 : :
35 : 12 : 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 : 12 : return 0;
53 : : }
54 : :
55 : 16 : 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 [ - + ]: 16 : assert(argc >= 0);
88 [ - + ]: 16 : assert(argv);
89 : :
90 [ + - ]: 16 : while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
91 : :
92 [ + - - - : 16 : switch (c) {
- - - - -
- - + - ]
93 : :
94 : 12 : case 'h':
95 : 12 : 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 : 4 : case '?':
140 : 4 : 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 : 16 : static int run(int argc, char *argv[]) {
156 : 16 : _cleanup_strv_free_erase_ char **l = NULL;
157 : : usec_t timeout;
158 : : char **p;
159 : : int r;
160 : :
161 : 16 : log_show_color(true);
162 : 16 : log_parse_environment();
163 : 16 : log_open();
164 : :
165 : 16 : r = parse_argv(argc, argv);
166 [ + - ]: 16 : if (r <= 0)
167 : 16 : 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 : 16 : DEFINE_MAIN_FUNCTION(run);
|