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