chiark / gitweb /
Add more password agent information
[elogind.git] / src / ask-password / ask-password.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2010 Lennart Poettering
7
8   systemd is free software; you can redistribute it and/or modify it
9   under the terms of the GNU Lesser General Public License as published by
10   the Free Software Foundation; either version 2.1 of the License, or
11   (at your option) any later version.
12
13   systemd is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16   Lesser General Public License for more details.
17
18   You should have received a copy of the GNU Lesser General Public License
19   along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <sys/socket.h>
23 #include <sys/poll.h>
24 #include <sys/types.h>
25 #include <assert.h>
26 #include <string.h>
27 #include <errno.h>
28 #include <unistd.h>
29 #include <fcntl.h>
30 #include <sys/un.h>
31 #include <sys/stat.h>
32 #include <sys/signalfd.h>
33 #include <getopt.h>
34 #include <termios.h>
35 #include <limits.h>
36 #include <stddef.h>
37
38 #include "log.h"
39 #include "macro.h"
40 #include "util.h"
41 #include "strv.h"
42 #include "ask-password-api.h"
43 #include "def.h"
44
45 static const char *arg_icon = NULL;
46 static const char *arg_id = NULL;
47 static const char *arg_message = NULL;
48 static bool arg_use_tty = true;
49 static usec_t arg_timeout = DEFAULT_TIMEOUT_USEC;
50 static bool arg_accept_cached = false;
51 static bool arg_multiple = false;
52
53 static int help(void) {
54
55         printf("%s [OPTIONS...] MESSAGE\n\n"
56                "Query the user for a system passphrase, via the TTY or an UI agent.\n\n"
57                "  -h --help          Show this help\n"
58                "     --icon=NAME     Icon name\n"
59                "     --timeout=SEC   Timeout in sec\n"
60                "     --no-tty        Ask question via agent even on TTY\n"
61                "     --accept-cached Accept cached passwords\n"
62                "     --multiple      List multiple passwords if available\n"
63                "     --id=ID         Query identifier (e.g. cryptsetup:/dev/sda5)\n",
64                program_invocation_short_name);
65
66         return 0;
67 }
68
69 static int parse_argv(int argc, char *argv[]) {
70
71         enum {
72                 ARG_ICON = 0x100,
73                 ARG_TIMEOUT,
74                 ARG_NO_TTY,
75                 ARG_ACCEPT_CACHED,
76                 ARG_MULTIPLE,
77                 ARG_ID
78         };
79
80         static const struct option options[] = {
81                 { "help",          no_argument,       NULL, 'h'               },
82                 { "icon",          required_argument, NULL, ARG_ICON          },
83                 { "timeout",       required_argument, NULL, ARG_TIMEOUT       },
84                 { "no-tty",        no_argument,       NULL, ARG_NO_TTY        },
85                 { "accept-cached", no_argument,       NULL, ARG_ACCEPT_CACHED },
86                 { "multiple",      no_argument,       NULL, ARG_MULTIPLE      },
87                 { "id",            required_argument, NULL, ARG_ID            },
88                 {}
89         };
90
91         int c;
92
93         assert(argc >= 0);
94         assert(argv);
95
96         while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) {
97
98                 switch (c) {
99
100                 case 'h':
101                         return help();
102
103                 case ARG_ICON:
104                         arg_icon = optarg;
105                         break;
106
107                 case ARG_TIMEOUT:
108                         if (parse_sec(optarg, &arg_timeout) < 0) {
109                                 log_error("Failed to parse --timeout parameter %s", optarg);
110                                 return -EINVAL;
111                         }
112                         break;
113
114                 case ARG_NO_TTY:
115                         arg_use_tty = false;
116                         break;
117
118                 case ARG_ACCEPT_CACHED:
119                         arg_accept_cached = true;
120                         break;
121
122                 case ARG_MULTIPLE:
123                         arg_multiple = true;
124                         break;
125
126                 case ARG_ID:
127                         arg_id = optarg;
128                         break;
129
130                 case '?':
131                         return -EINVAL;
132
133                 default:
134                         assert_not_reached("Unhandled option");
135                 }
136         }
137
138         if (optind != argc-1) {
139                 help();
140                 return -EINVAL;
141         }
142
143         arg_message = argv[optind];
144         return 1;
145 }
146
147 int main(int argc, char *argv[]) {
148         int r;
149         usec_t timeout;
150
151         log_parse_environment();
152         log_open();
153
154         if ((r = parse_argv(argc, argv)) <= 0)
155                 goto finish;
156
157         if (arg_timeout > 0)
158                 timeout = now(CLOCK_MONOTONIC) + arg_timeout;
159         else
160                 timeout = 0;
161
162         if (arg_use_tty && isatty(STDIN_FILENO)) {
163                 char *password = NULL;
164
165                 if ((r = ask_password_tty(arg_message, timeout, NULL, &password)) >= 0) {
166                         puts(password);
167                         free(password);
168                 }
169
170         } else {
171                 char **l;
172
173                 if ((r = ask_password_agent(arg_message, arg_icon, arg_id, timeout, arg_accept_cached, &l)) >= 0) {
174                         char **p;
175
176                         STRV_FOREACH(p, l) {
177                                 puts(*p);
178
179                                 if (!arg_multiple)
180                                         break;
181                         }
182
183                         strv_free(l);
184                 }
185         }
186
187 finish:
188
189         return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
190 }