]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/cryptsetup/cryptsetup.c
Merge pull request #118 from haraldh/set_consume2
[thirdparty/systemd.git] / src / cryptsetup / cryptsetup.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 <string.h>
23 #include <errno.h>
24 #include <sys/mman.h>
25 #include <mntent.h>
26
27 #include <libcryptsetup.h>
28
29 #include "fileio.h"
30 #include "log.h"
31 #include "util.h"
32 #include "path-util.h"
33 #include "strv.h"
34 #include "ask-password-api.h"
35 #include "sd-device.h"
36 #include "device-util.h"
37
38 static const char *arg_type = NULL; /* CRYPT_LUKS1, CRYPT_TCRYPT or CRYPT_PLAIN */
39 static char *arg_cipher = NULL;
40 static unsigned arg_key_size = 0;
41 static int arg_key_slot = CRYPT_ANY_SLOT;
42 static unsigned arg_keyfile_size = 0;
43 static unsigned arg_keyfile_offset = 0;
44 static char *arg_hash = NULL;
45 static char *arg_header = NULL;
46 static unsigned arg_tries = 3;
47 static bool arg_readonly = false;
48 static bool arg_verify = false;
49 static bool arg_discards = false;
50 static bool arg_tcrypt_hidden = false;
51 static bool arg_tcrypt_system = false;
52 static char **arg_tcrypt_keyfiles = NULL;
53 static uint64_t arg_offset = 0;
54 static uint64_t arg_skip = 0;
55 static usec_t arg_timeout = 0;
56
57 /* Options Debian's crypttab knows we don't:
58
59 precheck=
60 check=
61 checkargs=
62 noearly=
63 loud=
64 keyscript=
65 */
66
67 static int parse_one_option(const char *option) {
68 assert(option);
69
70 /* Handled outside of this tool */
71 if (STR_IN_SET(option, "noauto", "auto", "nofail", "fail"))
72 return 0;
73
74 if (startswith(option, "cipher=")) {
75 char *t;
76
77 t = strdup(option+7);
78 if (!t)
79 return log_oom();
80
81 free(arg_cipher);
82 arg_cipher = t;
83
84 } else if (startswith(option, "size=")) {
85
86 if (safe_atou(option+5, &arg_key_size) < 0) {
87 log_error("size= parse failure, ignoring.");
88 return 0;
89 }
90
91 if (arg_key_size % 8) {
92 log_error("size= not a multiple of 8, ignoring.");
93 return 0;
94 }
95
96 arg_key_size /= 8;
97
98 } else if (startswith(option, "key-slot=")) {
99
100 arg_type = CRYPT_LUKS1;
101 if (safe_atoi(option+9, &arg_key_slot) < 0) {
102 log_error("key-slot= parse failure, ignoring.");
103 return 0;
104 }
105
106 } else if (startswith(option, "tcrypt-keyfile=")) {
107
108 arg_type = CRYPT_TCRYPT;
109 if (path_is_absolute(option+15)) {
110 if (strv_extend(&arg_tcrypt_keyfiles, option + 15) < 0)
111 return log_oom();
112 } else
113 log_error("Key file path '%s' is not absolute. Ignoring.", option+15);
114
115 } else if (startswith(option, "keyfile-size=")) {
116
117 if (safe_atou(option+13, &arg_keyfile_size) < 0) {
118 log_error("keyfile-size= parse failure, ignoring.");
119 return 0;
120 }
121
122 } else if (startswith(option, "keyfile-offset=")) {
123
124 if (safe_atou(option+15, &arg_keyfile_offset) < 0) {
125 log_error("keyfile-offset= parse failure, ignoring.");
126 return 0;
127 }
128
129 } else if (startswith(option, "hash=")) {
130 char *t;
131
132 t = strdup(option+5);
133 if (!t)
134 return log_oom();
135
136 free(arg_hash);
137 arg_hash = t;
138
139 } else if (startswith(option, "header=")) {
140 arg_type = CRYPT_LUKS1;
141
142 if (!path_is_absolute(option+7)) {
143 log_error("Header path '%s' is not absolute, refusing.", option+7);
144 return -EINVAL;
145 }
146
147 if (arg_header) {
148 log_error("Duplicate header= options, refusing.");
149 return -EINVAL;
150 }
151
152 arg_header = strdup(option+7);
153 if (!arg_header)
154 return log_oom();
155
156 } else if (startswith(option, "tries=")) {
157
158 if (safe_atou(option+6, &arg_tries) < 0) {
159 log_error("tries= parse failure, ignoring.");
160 return 0;
161 }
162
163 } else if (STR_IN_SET(option, "readonly", "read-only"))
164 arg_readonly = true;
165 else if (streq(option, "verify"))
166 arg_verify = true;
167 else if (STR_IN_SET(option, "allow-discards", "discard"))
168 arg_discards = true;
169 else if (streq(option, "luks"))
170 arg_type = CRYPT_LUKS1;
171 else if (streq(option, "tcrypt"))
172 arg_type = CRYPT_TCRYPT;
173 else if (streq(option, "tcrypt-hidden")) {
174 arg_type = CRYPT_TCRYPT;
175 arg_tcrypt_hidden = true;
176 } else if (streq(option, "tcrypt-system")) {
177 arg_type = CRYPT_TCRYPT;
178 arg_tcrypt_system = true;
179 } else if (STR_IN_SET(option, "plain", "swap", "tmp"))
180 arg_type = CRYPT_PLAIN;
181 else if (startswith(option, "timeout=")) {
182
183 if (parse_sec(option+8, &arg_timeout) < 0) {
184 log_error("timeout= parse failure, ignoring.");
185 return 0;
186 }
187
188 } else if (startswith(option, "offset=")) {
189
190 if (safe_atou64(option+7, &arg_offset) < 0) {
191 log_error("offset= parse failure, refusing.");
192 return -EINVAL;
193 }
194
195 } else if (startswith(option, "skip=")) {
196
197 if (safe_atou64(option+5, &arg_skip) < 0) {
198 log_error("skip= parse failure, refusing.");
199 return -EINVAL;
200 }
201
202 } else if (!streq(option, "none"))
203 log_error("Encountered unknown /etc/crypttab option '%s', ignoring.", option);
204
205 return 0;
206 }
207
208 static int parse_options(const char *options) {
209 const char *word, *state;
210 size_t l;
211 int r;
212
213 assert(options);
214
215 FOREACH_WORD_SEPARATOR(word, l, options, ",", state) {
216 _cleanup_free_ char *o;
217
218 o = strndup(word, l);
219 if (!o)
220 return -ENOMEM;
221 r = parse_one_option(o);
222 if (r < 0)
223 return r;
224 }
225
226 /* sanity-check options */
227 if (arg_type != NULL && !streq(arg_type, CRYPT_PLAIN)) {
228 if (arg_offset)
229 log_warning("offset= ignored with type %s", arg_type);
230 if (arg_skip)
231 log_warning("skip= ignored with type %s", arg_type);
232 }
233
234 return 0;
235 }
236
237 static void log_glue(int level, const char *msg, void *usrptr) {
238 log_debug("%s", msg);
239 }
240
241 static int disk_major_minor(const char *path, char **ret) {
242 struct stat st;
243
244 assert(path);
245
246 if (stat(path, &st) < 0)
247 return -errno;
248
249 if (!S_ISBLK(st.st_mode))
250 return -EINVAL;
251
252 if (asprintf(ret, "/dev/block/%d:%d", major(st.st_rdev), minor(st.st_rdev)) < 0)
253 return -errno;
254
255 return 0;
256 }
257
258 static char* disk_description(const char *path) {
259
260 static const char name_fields[] =
261 "ID_PART_ENTRY_NAME\0"
262 "DM_NAME\0"
263 "ID_MODEL_FROM_DATABASE\0"
264 "ID_MODEL\0";
265
266 _cleanup_device_unref_ sd_device *device = NULL;
267 struct stat st;
268 const char *i;
269 int r;
270
271 assert(path);
272
273 if (stat(path, &st) < 0)
274 return NULL;
275
276 if (!S_ISBLK(st.st_mode))
277 return NULL;
278
279 r = sd_device_new_from_devnum(&device, 'b', st.st_rdev);
280 if (r < 0)
281 return NULL;
282
283 NULSTR_FOREACH(i, name_fields) {
284 const char *name;
285
286 r = sd_device_get_property_value(device, i, &name);
287 if (r >= 0 && !isempty(name))
288 return strdup(name);
289 }
290
291 return NULL;
292 }
293
294 static char *disk_mount_point(const char *label) {
295 _cleanup_free_ char *device = NULL;
296 _cleanup_endmntent_ FILE *f = NULL;
297 struct mntent *m;
298
299 /* Yeah, we don't support native systemd unit files here for now */
300
301 if (asprintf(&device, "/dev/mapper/%s", label) < 0)
302 return NULL;
303
304 f = setmntent("/etc/fstab", "r");
305 if (!f)
306 return NULL;
307
308 while ((m = getmntent(f)))
309 if (path_equal(m->mnt_fsname, device))
310 return strdup(m->mnt_dir);
311
312 return NULL;
313 }
314
315 static int get_password(const char *vol, const char *src, usec_t until, bool accept_cached, char ***passwords) {
316 int r = 0;
317 char **p;
318 _cleanup_free_ char *text = NULL;
319 _cleanup_free_ char *escaped_name = NULL;
320 char *id;
321 const char *name = NULL;
322 _cleanup_free_ char *description = NULL, *name_buffer = NULL,
323 *mount_point = NULL, *maj_min = NULL;
324
325 assert(vol);
326 assert(src);
327 assert(passwords);
328
329 description = disk_description(src);
330 mount_point = disk_mount_point(vol);
331
332 if (description && streq(vol, description)) {
333 /* If the description string is simply the
334 * volume name, then let's not show this
335 * twice */
336 free(description);
337 description = NULL;
338 }
339
340 if (mount_point && description)
341 r = asprintf(&name_buffer, "%s (%s) on %s", description, vol, mount_point);
342 else if (mount_point)
343 r = asprintf(&name_buffer, "%s on %s", vol, mount_point);
344 else if (description)
345 r = asprintf(&name_buffer, "%s (%s)", description, vol);
346
347 if (r < 0)
348 return log_oom();
349
350 name = name_buffer ? name_buffer : vol;
351
352 if (asprintf(&text, "Please enter passphrase for disk %s!", name) < 0)
353 return log_oom();
354
355 if (src)
356 (void) disk_major_minor(src, &maj_min);
357
358 if (maj_min) {
359 escaped_name = maj_min;
360 maj_min = NULL;
361 } else
362 escaped_name = cescape(name);
363
364 if (!escaped_name)
365 return log_oom();
366
367 id = strjoina("cryptsetup:", escaped_name);
368
369 r = ask_password_auto(text, "drive-harddisk", id, until, accept_cached, passwords);
370 if (r < 0)
371 return log_error_errno(r, "Failed to query password: %m");
372
373 if (arg_verify) {
374 _cleanup_strv_free_ char **passwords2 = NULL;
375
376 assert(strv_length(*passwords) == 1);
377
378 if (asprintf(&text, "Please enter passphrase for disk %s! (verification)", name) < 0)
379 return log_oom();
380
381 id = strjoina("cryptsetup-verification:", escaped_name);
382
383 r = ask_password_auto(text, "drive-harddisk", id, until, false, &passwords2);
384 if (r < 0)
385 return log_error_errno(r, "Failed to query verification password: %m");
386
387 assert(strv_length(passwords2) == 1);
388
389 if (!streq(*passwords[0], passwords2[0])) {
390 log_warning("Passwords did not match, retrying.");
391 return -EAGAIN;
392 }
393 }
394
395 strv_uniq(*passwords);
396
397 STRV_FOREACH(p, *passwords) {
398 char *c;
399
400 if (strlen(*p)+1 >= arg_key_size)
401 continue;
402
403 /* Pad password if necessary */
404 if (!(c = new(char, arg_key_size)))
405 return log_oom();
406
407 strncpy(c, *p, arg_key_size);
408 free(*p);
409 *p = c;
410 }
411
412 return 0;
413 }
414
415 static int attach_tcrypt(struct crypt_device *cd,
416 const char *name,
417 const char *key_file,
418 char **passwords,
419 uint32_t flags) {
420 int r = 0;
421 _cleanup_free_ char *passphrase = NULL;
422 struct crypt_params_tcrypt params = {
423 .flags = CRYPT_TCRYPT_LEGACY_MODES,
424 .keyfiles = (const char **)arg_tcrypt_keyfiles,
425 .keyfiles_count = strv_length(arg_tcrypt_keyfiles)
426 };
427
428 assert(cd);
429 assert(name);
430 assert(key_file || (passwords && passwords[0]));
431
432 if (arg_tcrypt_hidden)
433 params.flags |= CRYPT_TCRYPT_HIDDEN_HEADER;
434
435 if (arg_tcrypt_system)
436 params.flags |= CRYPT_TCRYPT_SYSTEM_HEADER;
437
438 if (key_file) {
439 r = read_one_line_file(key_file, &passphrase);
440 if (r < 0) {
441 log_error_errno(r, "Failed to read password file '%s': %m", key_file);
442 return -EAGAIN;
443 }
444
445 params.passphrase = passphrase;
446 } else
447 params.passphrase = passwords[0];
448 params.passphrase_size = strlen(params.passphrase);
449
450 r = crypt_load(cd, CRYPT_TCRYPT, &params);
451 if (r < 0) {
452 if (key_file && r == -EPERM) {
453 log_error("Failed to activate using password file '%s'.", key_file);
454 return -EAGAIN;
455 }
456 return r;
457 }
458
459 return crypt_activate_by_volume_key(cd, name, NULL, 0, flags);
460 }
461
462 static int attach_luks_or_plain(struct crypt_device *cd,
463 const char *name,
464 const char *key_file,
465 const char *data_device,
466 char **passwords,
467 uint32_t flags) {
468 int r = 0;
469 bool pass_volume_key = false;
470
471 assert(cd);
472 assert(name);
473 assert(key_file || passwords);
474
475 if (!arg_type || streq(arg_type, CRYPT_LUKS1)) {
476 r = crypt_load(cd, CRYPT_LUKS1, NULL);
477 if (r < 0) {
478 log_error("crypt_load() failed on device %s.\n", crypt_get_device_name(cd));
479 return r;
480 }
481
482 if (data_device)
483 r = crypt_set_data_device(cd, data_device);
484 }
485
486 if ((!arg_type && r < 0) || streq_ptr(arg_type, CRYPT_PLAIN)) {
487 struct crypt_params_plain params = {
488 .offset = arg_offset,
489 .skip = arg_skip,
490 };
491 const char *cipher, *cipher_mode;
492 _cleanup_free_ char *truncated_cipher = NULL;
493
494 if (arg_hash) {
495 /* plain isn't a real hash type. it just means "use no hash" */
496 if (!streq(arg_hash, "plain"))
497 params.hash = arg_hash;
498 } else if (!key_file)
499 /* for CRYPT_PLAIN, the behaviour of cryptsetup
500 * package is to not hash when a key file is provided */
501 params.hash = "ripemd160";
502
503 if (arg_cipher) {
504 size_t l;
505
506 l = strcspn(arg_cipher, "-");
507 truncated_cipher = strndup(arg_cipher, l);
508 if (!truncated_cipher)
509 return log_oom();
510
511 cipher = truncated_cipher;
512 cipher_mode = arg_cipher[l] ? arg_cipher+l+1 : "plain";
513 } else {
514 cipher = "aes";
515 cipher_mode = "cbc-essiv:sha256";
516 }
517
518 /* for CRYPT_PLAIN limit reads
519 * from keyfile to key length, and
520 * ignore keyfile-size */
521 arg_keyfile_size = arg_key_size;
522
523 /* In contrast to what the name
524 * crypt_setup() might suggest this
525 * doesn't actually format anything,
526 * it just configures encryption
527 * parameters when used for plain
528 * mode. */
529 r = crypt_format(cd, CRYPT_PLAIN, cipher, cipher_mode,
530 NULL, NULL, arg_keyfile_size, &params);
531
532 /* hash == NULL implies the user passed "plain" */
533 pass_volume_key = (params.hash == NULL);
534 }
535
536 if (r < 0)
537 return log_error_errno(r, "Loading of cryptographic parameters failed: %m");
538
539 log_info("Set cipher %s, mode %s, key size %i bits for device %s.",
540 crypt_get_cipher(cd),
541 crypt_get_cipher_mode(cd),
542 crypt_get_volume_key_size(cd)*8,
543 crypt_get_device_name(cd));
544
545 if (key_file) {
546 r = crypt_activate_by_keyfile_offset(cd, name, arg_key_slot,
547 key_file, arg_keyfile_size,
548 arg_keyfile_offset, flags);
549 if (r < 0) {
550 log_error_errno(r, "Failed to activate with key file '%s': %m", key_file);
551 return -EAGAIN;
552 }
553 } else {
554 char **p;
555
556 STRV_FOREACH(p, passwords) {
557 if (pass_volume_key)
558 r = crypt_activate_by_volume_key(cd, name, *p, arg_key_size, flags);
559 else
560 r = crypt_activate_by_passphrase(cd, name, arg_key_slot, *p, strlen(*p), flags);
561
562 if (r >= 0)
563 break;
564 }
565 }
566
567 return r;
568 }
569
570 static int help(void) {
571
572 printf("%s attach VOLUME SOURCEDEVICE [PASSWORD] [OPTIONS]\n"
573 "%s detach VOLUME\n\n"
574 "Attaches or detaches an encrypted block device.\n",
575 program_invocation_short_name,
576 program_invocation_short_name);
577
578 return 0;
579 }
580
581 int main(int argc, char *argv[]) {
582 int r = EXIT_FAILURE;
583 struct crypt_device *cd = NULL;
584
585 if (argc <= 1) {
586 help();
587 return EXIT_SUCCESS;
588 }
589
590 if (argc < 3) {
591 log_error("This program requires at least two arguments.");
592 return EXIT_FAILURE;
593 }
594
595 log_set_target(LOG_TARGET_AUTO);
596 log_parse_environment();
597 log_open();
598
599 umask(0022);
600
601 if (streq(argv[1], "attach")) {
602 uint32_t flags = 0;
603 int k;
604 unsigned tries;
605 usec_t until;
606 crypt_status_info status;
607 const char *key_file = NULL;
608
609 /* Arguments: systemd-cryptsetup attach VOLUME SOURCE-DEVICE [PASSWORD] [OPTIONS] */
610
611 if (argc < 4) {
612 log_error("attach requires at least two arguments.");
613 goto finish;
614 }
615
616 if (argc >= 5 &&
617 argv[4][0] &&
618 !streq(argv[4], "-") &&
619 !streq(argv[4], "none")) {
620
621 if (!path_is_absolute(argv[4]))
622 log_error("Password file path '%s' is not absolute. Ignoring.", argv[4]);
623 else
624 key_file = argv[4];
625 }
626
627 if (argc >= 6 && argv[5][0] && !streq(argv[5], "-")) {
628 if (parse_options(argv[5]) < 0)
629 goto finish;
630 }
631
632 /* A delicious drop of snake oil */
633 mlockall(MCL_FUTURE);
634
635 if (arg_header) {
636 log_debug("LUKS header: %s", arg_header);
637 k = crypt_init(&cd, arg_header);
638 } else
639 k = crypt_init(&cd, argv[3]);
640
641 if (k) {
642 log_error_errno(k, "crypt_init() failed: %m");
643 goto finish;
644 }
645
646 crypt_set_log_callback(cd, log_glue, NULL);
647
648 status = crypt_status(cd, argv[2]);
649 if (status == CRYPT_ACTIVE || status == CRYPT_BUSY) {
650 log_info("Volume %s already active.", argv[2]);
651 r = EXIT_SUCCESS;
652 goto finish;
653 }
654
655 if (arg_readonly)
656 flags |= CRYPT_ACTIVATE_READONLY;
657
658 if (arg_discards)
659 flags |= CRYPT_ACTIVATE_ALLOW_DISCARDS;
660
661 if (arg_timeout > 0)
662 until = now(CLOCK_MONOTONIC) + arg_timeout;
663 else
664 until = 0;
665
666 arg_key_size = (arg_key_size > 0 ? arg_key_size : (256 / 8));
667
668 if (key_file) {
669 struct stat st;
670
671 /* Ideally we'd do this on the open fd, but since this is just a
672 * warning it's OK to do this in two steps. */
673 if (stat(key_file, &st) >= 0 && S_ISREG(st.st_mode) && (st.st_mode & 0005))
674 log_warning("Key file %s is world-readable. This is not a good idea!", key_file);
675 }
676
677 for (tries = 0; arg_tries == 0 || tries < arg_tries; tries++) {
678 _cleanup_strv_free_ char **passwords = NULL;
679
680 if (!key_file) {
681 k = get_password(argv[2], argv[3], until, tries == 0 && !arg_verify, &passwords);
682 if (k == -EAGAIN)
683 continue;
684 else if (k < 0)
685 goto finish;
686 }
687
688 if (streq_ptr(arg_type, CRYPT_TCRYPT))
689 k = attach_tcrypt(cd, argv[2], key_file, passwords, flags);
690 else
691 k = attach_luks_or_plain(cd,
692 argv[2],
693 key_file,
694 arg_header ? argv[3] : NULL,
695 passwords,
696 flags);
697 if (k >= 0)
698 break;
699 else if (k == -EAGAIN) {
700 key_file = NULL;
701 continue;
702 } else if (k != -EPERM) {
703 log_error_errno(k, "Failed to activate: %m");
704 goto finish;
705 }
706
707 log_warning("Invalid passphrase.");
708 }
709
710 if (arg_tries != 0 && tries >= arg_tries) {
711 log_error("Too many attempts; giving up.");
712 r = EXIT_FAILURE;
713 goto finish;
714 }
715
716 } else if (streq(argv[1], "detach")) {
717 int k;
718
719 k = crypt_init_by_name(&cd, argv[2]);
720 if (k) {
721 log_error_errno(k, "crypt_init() failed: %m");
722 goto finish;
723 }
724
725 crypt_set_log_callback(cd, log_glue, NULL);
726
727 k = crypt_deactivate(cd, argv[2]);
728 if (k < 0) {
729 log_error_errno(k, "Failed to deactivate: %m");
730 goto finish;
731 }
732
733 } else {
734 log_error("Unknown verb %s.", argv[1]);
735 goto finish;
736 }
737
738 r = EXIT_SUCCESS;
739
740 finish:
741
742 if (cd)
743 crypt_free(cd);
744
745 free(arg_cipher);
746 free(arg_hash);
747 free(arg_header);
748 strv_free(arg_tcrypt_keyfiles);
749
750 return r;
751 }