]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/ask-password/ask-password.c
Merge pull request #17478 from yuwata/split-network-internal
[thirdparty/systemd.git] / src / ask-password / ask-password.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
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 STATIC_DESTRUCTOR_REGISTER(arg_message, freep);
26
27 static int help(void) {
28 _cleanup_free_ char *link = NULL;
29 int r;
30
31 r = terminal_urlify_man("systemd-ask-password", "1", &link);
32 if (r < 0)
33 return log_oom();
34
35 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 return 0;
53 }
54
55 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 assert(argc >= 0);
88 assert(argv);
89
90 while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
91
92 switch (c) {
93
94 case 'h':
95 return help();
96
97 case ARG_VERSION:
98 return version();
99
100 case ARG_ICON:
101 arg_icon = optarg;
102 break;
103
104 case ARG_TIMEOUT:
105 if (parse_sec(optarg, &arg_timeout) < 0)
106 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
107 "Failed to parse --timeout parameter %s",
108 optarg);
109 break;
110
111 case ARG_ECHO:
112 arg_flags |= ASK_PASSWORD_ECHO;
113 break;
114
115 case ARG_NO_TTY:
116 arg_flags |= ASK_PASSWORD_NO_TTY;
117 break;
118
119 case ARG_ACCEPT_CACHED:
120 arg_flags |= ASK_PASSWORD_ACCEPT_CACHED;
121 break;
122
123 case ARG_MULTIPLE:
124 arg_multiple = true;
125 break;
126
127 case ARG_ID:
128 arg_id = optarg;
129 break;
130
131 case ARG_KEYNAME:
132 arg_keyname = optarg;
133 break;
134
135 case ARG_NO_OUTPUT:
136 arg_no_output = true;
137 break;
138
139 case '?':
140 return -EINVAL;
141
142 default:
143 assert_not_reached("Unhandled option");
144 }
145
146 if (argc > optind) {
147 arg_message = strv_join(argv + optind, " ");
148 if (!arg_message)
149 return log_oom();
150 }
151
152 return 1;
153 }
154
155 static int run(int argc, char *argv[]) {
156 _cleanup_strv_free_erase_ char **l = NULL;
157 usec_t timeout;
158 char **p;
159 int r;
160
161 log_show_color(true);
162 log_parse_environment();
163 log_open();
164
165 r = parse_argv(argc, argv);
166 if (r <= 0)
167 return r;
168
169 if (arg_timeout > 0)
170 timeout = now(CLOCK_MONOTONIC) + arg_timeout;
171 else
172 timeout = 0;
173
174 r = ask_password_auto(arg_message, arg_icon, arg_id, arg_keyname, timeout, arg_flags, &l);
175 if (r < 0)
176 return log_error_errno(r, "Failed to query password: %m");
177
178 STRV_FOREACH(p, l) {
179 if (!arg_no_output)
180 puts(*p);
181
182 if (!arg_multiple)
183 break;
184 }
185
186 return 0;
187 }
188
189 DEFINE_MAIN_FUNCTION(run);