chiark / gitweb /
cryptsetup: lock ourselves into memory as long as we deal with passwords
[elogind.git] / src / 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 General Public License as published by
10   the Free Software Foundation; either version 2 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   General Public License for more details.
17
18   You should have received a copy of the GNU 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 "ask-password-api.h"
42
43 static const char *arg_icon = NULL;
44 static const char *arg_message = NULL;
45 static bool arg_use_tty = true;
46 static usec_t arg_timeout = 60 * USEC_PER_SEC;
47
48 static int help(void) {
49
50         printf("%s [OPTIONS...] MESSAGE\n\n"
51                "Query the user for a system passphrase, via the TTY or an UI agent.\n\n"
52                "  -h --help         Show this help\n"
53                "     --icon=NAME    Icon name\n"
54                "     --timeout=SEC Timeout in sec\n"
55                "     --no-tty       Ask question via agent even on TTY\n",
56                program_invocation_short_name);
57
58         return 0;
59 }
60
61 static int parse_argv(int argc, char *argv[]) {
62
63         enum {
64                 ARG_ICON = 0x100,
65                 ARG_TIMEOUT,
66                 ARG_NO_TTY
67         };
68
69         static const struct option options[] = {
70                 { "help",      no_argument,       NULL, 'h'         },
71                 { "icon",      required_argument, NULL, ARG_ICON    },
72                 { "timeout",   required_argument, NULL, ARG_TIMEOUT },
73                 { "no-tty",    no_argument,       NULL, ARG_NO_TTY  },
74                 { NULL,        0,                 NULL, 0           }
75         };
76
77         int c;
78
79         assert(argc >= 0);
80         assert(argv);
81
82         while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) {
83
84                 switch (c) {
85
86                 case 'h':
87                         help();
88                         return 0;
89
90                 case ARG_ICON:
91                         arg_icon = optarg;
92                         break;
93
94                 case ARG_TIMEOUT:
95                         if (parse_usec(optarg, &arg_timeout) < 0 || arg_timeout <= 0) {
96                                 log_error("Failed to parse --timeout parameter %s", optarg);
97                                 return -EINVAL;
98                         }
99                         break;
100
101                 case ARG_NO_TTY:
102                         arg_use_tty = false;
103                         break;
104
105                 case '?':
106                         return -EINVAL;
107
108                 default:
109                         log_error("Unknown option code %c", c);
110                         return -EINVAL;
111                 }
112         }
113
114         if (optind != argc-1) {
115                 help();
116                 return -EINVAL;
117         }
118
119         arg_message = argv[optind];
120         return 1;
121 }
122
123 int main(int argc, char *argv[]) {
124         int r;
125         char *password = NULL;
126
127         log_parse_environment();
128         log_open();
129
130         if ((r = parse_argv(argc, argv)) <= 0)
131                 goto finish;
132
133         if (arg_use_tty && isatty(STDIN_FILENO))
134                 r = ask_password_tty(arg_message, now(CLOCK_MONOTONIC) + arg_timeout, NULL, &password);
135         else
136                 r = ask_password_agent(arg_message, arg_icon, now(CLOCK_MONOTONIC) + arg_timeout, &password);
137
138         if (r >= 0) {
139                 fputs(password, stdout);
140                 fflush(stdout);
141         }
142
143 finish:
144         free(password);
145
146         return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
147 }