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