2 * cryptsetup - setup cryptographic volumes for dm-crypt
4 * Copyright (C) 2004 Jana Saout <jana@saout.de>
5 * Copyright (C) 2004-2007 Clemens Fruhwirth <clemens@endorphin.org>
6 * Copyright (C) 2009-2020 Red Hat, Inc. All rights reserved.
7 * Copyright (C) 2009-2020 Milan Broz
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 #include "cryptsetup.h"
30 int opt_debug_json = 0;
31 int opt_batch_mode = 0;
32 int opt_progress_frequency = 0;
34 /* interrupt handling */
35 volatile int quit = 0;
36 static int signals_blocked = 0;
38 static void int_handler(int sig __attribute__((__unused__)))
43 int tools_signals_blocked(void)
45 return signals_blocked;
48 void set_int_block(int block)
50 sigset_t signals_open;
52 log_dbg("%slocking interruption on signal.", block ? "B" : "Unb");
54 sigemptyset(&signals_open);
55 sigaddset(&signals_open, SIGINT);
56 sigaddset(&signals_open, SIGTERM);
57 sigprocmask(block ? SIG_SETMASK : SIG_UNBLOCK, &signals_open, NULL);
58 signals_blocked = block;
62 void set_int_handler(int block)
64 struct sigaction sigaction_open;
66 log_dbg("Installing SIGINT/SIGTERM handler.");
67 memset(&sigaction_open, 0, sizeof(struct sigaction));
68 sigaction_open.sa_handler = int_handler;
69 sigaction(SIGINT, &sigaction_open, 0);
70 sigaction(SIGTERM, &sigaction_open, 0);
74 void check_signal(int *r)
80 #define LOG_MAX_LEN 4096
82 __attribute__((format(printf, 5, 6)))
83 void clogger(struct crypt_device *cd, int level, const char *file, int line,
84 const char *format, ...)
87 char target[LOG_MAX_LEN + 2];
89 va_start(argp, format);
91 if (vsnprintf(&target[0], LOG_MAX_LEN, format, argp) > 0) {
92 /* All verbose and error messages in tools end with EOL. */
93 if (level == CRYPT_LOG_VERBOSE || level == CRYPT_LOG_ERROR ||
94 level == CRYPT_LOG_DEBUG || level == CRYPT_LOG_DEBUG_JSON)
95 strncat(target, "\n", LOG_MAX_LEN);
97 crypt_log(cd, level, target);
103 void tool_log(int level, const char *msg, void *usrptr __attribute__((unused)))
107 case CRYPT_LOG_NORMAL:
108 fprintf(stdout, "%s", msg);
110 case CRYPT_LOG_VERBOSE:
112 fprintf(stdout, "%s", msg);
114 case CRYPT_LOG_ERROR:
115 fprintf(stderr, "%s", msg);
117 case CRYPT_LOG_DEBUG_JSON:
118 case CRYPT_LOG_DEBUG:
120 fprintf(stdout, "# %s", msg);
125 void quiet_log(int level, const char *msg, void *usrptr)
127 if (!opt_verbose && (level == CRYPT_LOG_ERROR || level == CRYPT_LOG_NORMAL))
128 level = CRYPT_LOG_VERBOSE;
129 tool_log(level, msg, usrptr);
132 static int _dialog(const char *msg, void *usrptr, int default_answer)
134 const char *fail_msg = (const char *)usrptr;
137 int r = default_answer, block;
139 block = tools_signals_blocked();
143 if (isatty(STDIN_FILENO) && !opt_batch_mode) {
144 log_std("\nWARNING!\n========\n");
145 log_std("%s\n\nAre you sure? (Type 'yes' in capital letters): ", msg);
147 if(getline(&answer, &size, stdin) == -1) {
149 /* Aborted by signal */
151 log_err(_("Error reading response from terminal."));
153 log_dbg("Query interrupted on signal.");
155 r = !strcmp(answer, "YES\n");
157 log_err("%s", fail_msg);
168 int yesDialog(const char *msg, void *usrptr)
170 return _dialog(msg, usrptr, 1);
173 int noDialog(const char *msg, void *usrptr)
175 return _dialog(msg, usrptr, 0);
178 void show_status(int errcode)
186 log_std(_("Command successful.\n"));
191 errcode = translate_errno(errcode);
194 crypt_error = _("wrong or missing parameters");
195 else if (errcode == 2)
196 crypt_error = _("no permission or bad passphrase");
197 else if (errcode == 3)
198 crypt_error = _("out of memory");
199 else if (errcode == 4)
200 crypt_error = _("wrong device or file specified");
201 else if (errcode == 5)
202 crypt_error = _("device already exists or device is busy");
204 crypt_error = _("unknown error");
206 log_std(_("Command failed with code %i (%s).\n"), -errcode, crypt_error);
209 const char *uuid_or_device(const char *spec)
211 static char device[PATH_MAX];
213 int i = 0, uuid_len = 5;
215 /* Check if it is correct UUID=<LUKS_UUID> format */
216 if (spec && !strncmp(spec, "UUID=", uuid_len)) {
217 strcpy(device, "/dev/disk/by-uuid/");
218 ptr = &device[strlen(device)];
220 while ((s = spec[i++]) && i < (PATH_MAX - 13)) {
221 if (!isxdigit(s) && s != '-')
222 return spec; /* Bail it out */
234 __attribute__ ((noreturn)) void usage(poptContext popt_context,
235 int exitcode, const char *error,
238 poptPrintUsage(popt_context, stderr, 0);
240 log_err("%s: %s", more, error);
241 poptFreeContext(popt_context);
245 void dbg_version_and_cmd(int argc, const char **argv)
249 log_std("# %s %s processing \"", PACKAGE_NAME, PACKAGE_VERSION);
250 for (i = 0; i < argc; i++) {
253 log_std("%s", argv[i]);
258 /* Translate exit code to simple codes */
259 int translate_errno(int r)
262 case 0: r = EXIT_SUCCESS; break;
264 case -EBUSY: r = 5; break;
266 case -ENODEV: r = 4; break;
267 case -ENOMEM: r = 3; break;
268 case -EPERM: r = 2; break;
272 default: r = EXIT_FAILURE;
277 void tools_keyslot_msg(int keyslot, crypt_object_op op)
283 log_verbose(_("Key slot %i created."), keyslot);
284 else if (op == UNLOCKED)
285 log_verbose(_("Key slot %i unlocked."), keyslot);
286 else if (op == REMOVED)
287 log_verbose(_("Key slot %i removed."), keyslot);
290 void tools_token_msg(int token, crypt_object_op op)
296 log_verbose(_("Token %i created."), token);
297 else if (op == REMOVED)
298 log_verbose(_("Token %i removed."), token);
302 * Device size string parsing, suffixes:
303 * s|S - 512 bytes sectors
304 * k |K |m |M |g |G |t |T - 1024 base
305 * kiB|KiB|miB|MiB|giB|GiB|tiB|TiB - 1024 base
306 * kb |KB |mM |MB |gB |GB |tB |TB - 1000 base
308 int tools_string_to_size(struct crypt_device *cd, const char *s, uint64_t *size)
312 uint64_t mult_base, mult, tmp;
314 *size = strtoull(s, &endp, 10);
315 if (!isdigit(s[0]) ||
316 (errno == ERANGE && *size == ULLONG_MAX) ||
317 (errno != 0 && *size == 0))
324 /* Allow "B" and "iB" suffixes */
326 (len == 3 && (endp[1] != 'i' || endp[2] != 'B')) ||
327 (len == 2 && endp[1] != 'B'))
330 if (len == 1 || len == 3)
338 case 'S': mult = 512;
341 case 'T': mult *= mult_base;
344 case 'G': mult *= mult_base;
347 case 'M': mult *= mult_base;
350 case 'K': mult *= mult_base;
357 if (*size && (tmp / *size) != mult) {
358 log_dbg("Device size overflow.");
366 /* Time progress helper */
368 /* The difference in seconds between two times in "timeval" format. */
369 static double time_diff(struct timeval *start, struct timeval *end)
371 return (end->tv_sec - start->tv_sec)
372 + (end->tv_usec - start->tv_usec) / 1E6;
375 void tools_clear_line(void)
377 if (opt_progress_frequency)
379 /* vt100 code clear line */
383 static void tools_time_progress(uint64_t device_size, uint64_t bytes, uint64_t *start_bytes,
384 struct timeval *start_time, struct timeval *end_time)
386 struct timeval now_time;
387 unsigned long long mbytes, eta;
388 double tdiff, uib, frequency;
389 int final = (bytes == device_size);
390 const char *eol, *ustr = "";
395 gettimeofday(&now_time, NULL);
396 if (start_time->tv_sec == 0 && start_time->tv_usec == 0) {
397 *start_time = now_time;
398 *end_time = now_time;
399 *start_bytes = bytes;
403 if (opt_progress_frequency) {
404 frequency = (double)opt_progress_frequency;
411 if (!final && time_diff(end_time, &now_time) < frequency)
414 *end_time = now_time;
416 tdiff = time_diff(start_time, end_time);
420 mbytes = bytes / 1024 / 1024;
421 uib = (double)(bytes - *start_bytes) / tdiff;
423 /* FIXME: calculate this from last minute only. */
424 eta = (unsigned long long)(device_size / uib - tdiff);
426 if (uib > 1073741824.0f) {
427 uib /= 1073741824.0f;
429 } else if (uib > 1048576.0f) {
432 } else if (uib > 1024.0f) {
439 log_std("Finished, time %02llu:%02llu.%03llu, "
440 "%4llu MiB written, speed %5.1f %sB/s\n",
441 (unsigned long long)tdiff / 60,
442 (unsigned long long)tdiff % 60,
443 (unsigned long long)((tdiff - floor(tdiff)) * 1000.0),
446 log_std("Progress: %5.1f%%, ETA %02llu:%02llu, "
447 "%4llu MiB written, speed %5.1f %sB/s%s",
448 (double)bytes / device_size * 100,
449 eta / 60, eta % 60, mbytes, uib, ustr, eol);
453 int tools_wipe_progress(uint64_t size, uint64_t offset, void *usrptr)
455 static struct timeval start_time = {}, end_time = {};
456 static uint64_t start_offset = 0;
459 tools_time_progress(size, offset, &start_offset, &start_time, &end_time);
464 log_err(_("\nWipe interrupted."));
470 static void report_partition(const char *value, const char *device)
473 log_dbg("Device %s already contains a '%s' partition signature.", device, value);
475 log_std(_("WARNING: Device %s already contains a '%s' partition signature.\n"), device, value);
478 static void report_superblock(const char *value, const char *device)
481 log_dbg("Device %s already contains a '%s' superblock signature.", device, value);
483 log_std(_("WARNING: Device %s already contains a '%s' superblock signature.\n"), device, value);
486 int tools_detect_signatures(const char *device, int ignore_luks, size_t *count)
490 struct blkid_handle *h;
498 if (!blk_supported()) {
499 log_dbg("Blkid support disabled.");
503 if ((r = blk_init_by_path(&h, device))) {
504 log_err(_("Failed to initialize device signature probes."));
508 blk_set_chains_for_full_print(h);
510 if (ignore_luks && blk_superblocks_filter_luks(h)) {
515 while ((pr = blk_probe(h)) < PRB_EMPTY) {
516 if (blk_is_partition(h))
517 report_partition(blk_get_partition_type(h), device);
518 else if (blk_is_superblock(h))
519 report_superblock(blk_get_superblock_type(h), device);
521 log_dbg("Internal tools_detect_signatures() error.");
535 int tools_wipe_all_signatures(const char *path)
540 struct blkid_handle *h = NULL;
542 if (!blk_supported()) {
543 log_dbg("Blkid support disabled.");
547 if (stat(path, &st)) {
548 log_err(_("Failed to stat device %s."), path);
553 if (S_ISBLK(st.st_mode))
556 /* better than opening regular file with O_EXCL (undefined) */
557 /* coverity[toctou] */
558 fd = open(path, flags);
561 log_err(_("Device %s is in use. Can not proceed with format operation."), path);
563 log_err(_("Failed to open file %s in read/write mode."), path);
567 if ((r = blk_init_by_fd(&h, fd))) {
568 log_err(_("Failed to initialize device signature probes."));
573 blk_set_chains_for_wipes(h);
575 while ((pr = blk_probe(h)) < PRB_EMPTY) {
576 if (blk_is_partition(h))
577 log_verbose(_("Existing '%s' partition signature (offset: %" PRIi64 " bytes) on device %s will be wiped."),
578 blk_get_partition_type(h), blk_get_offset(h), path);
579 if (blk_is_superblock(h))
580 log_verbose(_("Existing '%s' superblock signature (offset: %" PRIi64 " bytes) on device %s will be wiped."),
581 blk_get_superblock_type(h), blk_get_offset(h), path);
582 if (blk_do_wipe(h)) {
583 log_err(_("Failed to wipe device signature."));
589 if (pr != PRB_EMPTY) {
590 log_err(_("Failed to probe device %s for a signature."), path);
599 int tools_is_cipher_null(const char *cipher)
604 return !strcmp(cipher, "cipher_null") ? 1 : 0;
608 * Keyfile - is standard input treated as a binary file (no EOL handling).
610 int tools_is_stdin(const char *key_file)
615 return strcmp(key_file, "-") ? 0 : 1;
618 int tools_reencrypt_progress(uint64_t size, uint64_t offset, void *usrptr)
620 static struct timeval start_time = {}, end_time = {};
621 static uint64_t start_offset = 0;
624 tools_time_progress(size, offset, &start_offset, &start_time, &end_time);
629 log_err(_("\nReencryption interrupted."));