1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
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.
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.
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/>.
25 #include <libcryptsetup.h>
29 #include "ask-password-api.h"
31 static unsigned opt_tries
= 0;
32 static char *opt_cipher
= NULL
;
33 static unsigned opt_size
= 0;
34 static char *opt_hash
= NULL
;
35 static bool opt_readonly
= false;
36 static bool opt_verify
= false;
37 static usec_t arg_timeout
= 0;
39 static int parse_one_option(const char *option
) {
42 /* Handled outside of this tool */
43 if (streq(option
, "swap") ||
44 streq(option
, "tmp") ||
45 streq(option
, "noauto"))
48 if (startswith(option
, "cipher=")) {
51 if (!(t
= strdup(option
+7)))
57 } else if (startswith(option
, "size=")) {
59 if (safe_atou(option
+5, &opt_size
) < 0) {
60 log_error("size= parse failure, ignoring.");
64 } else if (startswith(option
, "hash=")) {
67 if (!(t
= strdup(option
+5)))
73 } else if (startswith(option
, "tries=")) {
75 if (safe_atou(option
+6, &opt_tries
) < 0) {
76 log_error("tries= parse failure, ignoring.");
80 } else if (streq(option
, "readonly"))
82 else if (streq(option
, "verify"))
84 else if (startswith(option
, "timeout=")) {
86 if (parse_usec(option
+8, &arg_timeout
) < 0) {
87 log_error("timeout= parse failure, ignoring.");
92 log_error("Encountered unknown /etc/crypttab option '%s', ignoring.", option
);
97 static int parse_options(const char *options
) {
104 FOREACH_WORD_SEPARATOR(w
, l
, options
, ",", state
) {
108 if (!(o
= strndup(w
, l
)))
111 r
= parse_one_option(o
);
121 static void log_glue(int level
, const char *msg
, void *usrptr
) {
123 log_full(level
== CRYPT_LOG_ERROR
? LOG_ERR
:
124 level
== CRYPT_LOG_VERBOSE
? LOG_INFO
:
125 level
== CRYPT_LOG_DEBUG
? LOG_DEBUG
:
130 static int password_glue(const char *msg
, char *buf
, size_t length
, void *usrptr
) {
132 char *password
= NULL
;
135 until
= now(CLOCK_MONOTONIC
) + (arg_timeout
> 0 ? arg_timeout
: 60 * USEC_PER_SEC
);
137 if ((k
= ask_password_agent(msg
, "drive-harddisk", until
, &password
)) < 0)
140 strncpy(buf
, password
, length
-1);
148 int main(int argc
, char *argv
[]) {
149 int r
= EXIT_FAILURE
;
150 struct crypt_device
*cd
= NULL
;
153 log_error("This program requires at least two arguments.");
157 log_set_target(LOG_TARGET_SYSLOG_OR_KMSG
);
158 log_parse_environment();
161 if (streq(argv
[1], "attach") ||
162 streq(argv
[1], "format-and-attach")) {
165 const char *key_file
= NULL
;
168 log_error("attach requires at least two arguments.");
172 if (argc
>= 5 && argv
[4][0] && !streq(argv
[4], "-")) {
174 if (!path_is_absolute(argv
[4]))
175 log_error("Password file path %s is not absolute. Ignoring.", argv
[4]);
180 if (argc
>= 6 && argv
[5][0] && !streq(argv
[5], "-"))
181 parse_options(argv
[5]);
183 if ((k
= crypt_init(&cd
, argv
[3]))) {
184 log_error("crypt_init() failed: %s", strerror(-k
));
188 crypt_set_log_callback(cd
, log_glue
, NULL
);
189 crypt_set_password_callback(cd
, password_glue
, NULL
);
191 if (streq(argv
[1], "format-and-attach")) {
193 /* Format with random key and attach */
195 log_error("Formatting not yet supported.");
198 } else if ((k
= crypt_load(cd
, CRYPT_LUKS1
, NULL
))) {
199 log_error("crypt_load() failed: %s", strerror(-k
));
204 flags
|= CRYPT_ACTIVATE_READONLY
;
207 crypt_set_password_retry(cd
, 1);
208 k
= crypt_activate_by_keyfile(cd
, argv
[2], CRYPT_ANY_SLOT
, key_file
, 0, flags
);
210 crypt_set_password_retry(cd
, opt_tries
> 0 ? opt_tries
: 3);
211 k
= crypt_activate_by_passphrase(cd
, argv
[2], CRYPT_ANY_SLOT
, NULL
, 0, flags
);
215 log_error("Failed to activate: %s", strerror(-k
));
219 } else if (streq(argv
[1], "detach")) {
222 if ((k
= crypt_init_by_name(&cd
, argv
[2]))) {
223 log_error("crypt_init() failed: %s", strerror(-k
));
227 crypt_set_log_callback(cd
, log_glue
, NULL
);
229 if ((k
= crypt_deactivate(cd
, argv
[2])) < 0) {
230 log_error("Failed to deactivate: %s", strerror(-k
));
235 log_error("Unknown verb %s.", argv
[1]);