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