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-2023 Red Hat, Inc. All rights reserved.
7 * Copyright (C) 2009-2023 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"
27 /* interrupt handling */
28 volatile int quit = 0;
29 static int signals_blocked = 0;
31 static void int_handler(int sig __attribute__((__unused__)))
36 int tools_signals_blocked(void)
38 return signals_blocked;
41 void set_int_block(int block)
43 sigset_t signals_open;
45 log_dbg("%slocking interruption on signal.", block ? "B" : "Unb");
47 sigemptyset(&signals_open);
48 sigaddset(&signals_open, SIGINT);
49 sigaddset(&signals_open, SIGTERM);
50 sigprocmask(block ? SIG_SETMASK : SIG_UNBLOCK, &signals_open, NULL);
51 signals_blocked = block;
55 void set_int_handler(int block)
57 struct sigaction sigaction_open;
59 log_dbg("Installing SIGINT/SIGTERM handler.");
60 memset(&sigaction_open, 0, sizeof(struct sigaction));
61 sigaction_open.sa_handler = int_handler;
62 sigaction(SIGINT, &sigaction_open, 0);
63 sigaction(SIGTERM, &sigaction_open, 0);
67 void check_signal(int *r)
73 void tool_log(int level, const char *msg, void *usrptr)
75 struct tools_log_params *params = (struct tools_log_params *)usrptr;
79 case CRYPT_LOG_NORMAL:
80 fprintf(stdout, "%s", msg);
82 case CRYPT_LOG_VERBOSE:
83 if (params && params->verbose)
84 fprintf(stdout, "%s", msg);
87 fprintf(stderr, "%s", msg);
89 case CRYPT_LOG_DEBUG_JSON:
91 if (params && params->debug)
92 fprintf(stdout, "# %s", msg);
97 void quiet_log(int level, const char *msg, void *usrptr)
99 struct tools_log_params *params = (struct tools_log_params *)usrptr;
101 if ((!params || !params->verbose) && (level == CRYPT_LOG_ERROR || level == CRYPT_LOG_NORMAL))
103 tool_log(level, msg, usrptr);
106 static int _dialog(const char *msg, void *usrptr, int default_answer)
108 const char *fail_msg = (const char *)usrptr;
111 int r = default_answer, block;
113 block = tools_signals_blocked();
117 if (isatty(STDIN_FILENO)) {
118 log_std(_("\nWARNING!\n========\n"));
119 /* TRANSLATORS: User must type "YES" (in capital letters), do not translate this word. */
120 log_std(_("%s\n\nAre you sure? (Type 'yes' in capital letters): "), msg);
122 if(getline(&answer, &size, stdin) == -1) {
124 /* Aborted by signal */
126 log_err(_("Error reading response from terminal."));
128 log_dbg("Query interrupted on signal.");
130 r = !strcmp(answer, "YES\n");
132 log_err("%s", fail_msg);
143 int yesDialog(const char *msg, void *usrptr)
145 return _dialog(msg, usrptr, 1);
148 int noDialog(const char *msg, void *usrptr)
150 return _dialog(msg, usrptr, 0);
153 void show_status(int errcode)
158 log_verbose(_("Command successful."));
163 errcode = translate_errno(errcode);
166 crypt_error = _("wrong or missing parameters");
167 else if (errcode == 2)
168 crypt_error = _("no permission or bad passphrase");
169 else if (errcode == 3)
170 crypt_error = _("out of memory");
171 else if (errcode == 4)
172 crypt_error = _("wrong device or file specified");
173 else if (errcode == 5)
174 crypt_error = _("device already exists or device is busy");
176 crypt_error = _("unknown error");
178 log_verbose(_("Command failed with code %i (%s)."), -errcode, crypt_error);
181 const char *uuid_or_device(const char *spec)
183 static char device[PATH_MAX];
185 int i = 0, uuid_len = 5;
187 /* Check if it is correct UUID=<LUKS_UUID> format */
188 if (spec && !strncmp(spec, "UUID=", uuid_len)) {
189 strcpy(device, "/dev/disk/by-uuid/");
190 ptr = &device[strlen(device)];
192 while ((s = spec[i++]) && i < (PATH_MAX - 13)) {
193 if (!isxdigit(s) && s != '-')
194 return spec; /* Bail it out */
206 __attribute__ ((noreturn)) void usage(poptContext popt_context,
207 int exitcode, const char *error,
210 poptPrintUsage(popt_context, stderr, 0);
212 log_err("%s: %s", more, error);
214 poptFreeContext(popt_context);
218 void dbg_version_and_cmd(int argc, const char **argv)
222 log_std("# %s %s processing \"", PACKAGE_NAME, PACKAGE_VERSION);
223 for (i = 0; i < argc; i++) {
226 log_std("%s", argv[i]);
231 /* Translate exit code to simple codes */
232 int translate_errno(int r)
235 case 0: r = EXIT_SUCCESS; break;
237 case -EBUSY: r = 5; break;
239 case -ENODEV: r = 4; break;
240 case -ENOMEM: r = 3; break;
241 case -EPERM: r = 2; break;
245 default: r = EXIT_FAILURE;
250 void tools_keyslot_msg(int keyslot, crypt_object_op op)
256 log_verbose(_("Key slot %i created."), keyslot);
257 else if (op == UNLOCKED)
258 log_verbose(_("Key slot %i unlocked."), keyslot);
259 else if (op == REMOVED)
260 log_verbose(_("Key slot %i removed."), keyslot);
263 void tools_token_msg(int token, crypt_object_op op)
269 log_verbose(_("Token %i created."), token);
270 else if (op == REMOVED)
271 log_verbose(_("Token %i removed."), token);
274 void tools_token_error_msg(int error, const char *type, int token, bool pin_provided)
279 if (error == -ENOANO) {
281 log_verbose(_("No token could be unlocked with this PIN."));
282 else if (token != CRYPT_ANY_TOKEN)
283 log_verbose(_("Token %i requires PIN."), token);
285 log_verbose(_("Token (type %s) requires PIN."), type);
286 } else if (error == -EPERM) {
287 if (token != CRYPT_ANY_TOKEN)
288 log_verbose(_("Token %i cannot unlock assigned keyslot(s) (wrong keyslot passphrase)."), token);
290 log_verbose(_("Token (type %s) cannot unlock assigned keyslot(s) (wrong keyslot passphrase)."), type);
291 } if (error == -EAGAIN) {
292 if (token != CRYPT_ANY_TOKEN)
293 log_verbose(_("Token %i requires additional missing resource."), token);
295 log_verbose(_("Token (type %s) requires additional missing resource."), type);
296 } if (error == -ENOENT) {
298 log_verbose(_("No usable token (type %s) is available."), type);
300 log_verbose(_("No usable token is available."));
305 * Device size string parsing, suffixes:
306 * s|S - 512 bytes sectors
307 * k |K |m |M |g |G |t |T - 1024 base
308 * kiB|KiB|miB|MiB|giB|GiB|tiB|TiB - 1024 base
309 * kb |KB |mM |MB |gB |GB |tB |TB - 1000 base
311 int tools_string_to_size(const char *s, uint64_t *size)
315 uint64_t mult_base, mult, tmp;
317 *size = strtoull(s, &endp, 10);
318 if (!isdigit(s[0]) ||
319 (errno == ERANGE && *size == ULLONG_MAX) ||
320 (errno != 0 && *size == 0))
327 /* Allow "B" and "iB" suffixes */
329 (len == 3 && (endp[1] != 'i' || endp[2] != 'B')) ||
330 (len == 2 && endp[1] != 'B'))
333 if (len == 1 || len == 3)
341 case 'S': mult = 512;
344 case 'T': mult *= mult_base;
347 case 'G': mult *= mult_base;
350 case 'M': mult *= mult_base;
353 case 'K': mult *= mult_base;
360 if (*size && (tmp / *size) != mult) {
361 log_dbg("Device size overflow.");
370 * Keyfile - is standard input treated as a binary file (no EOL handling).
372 int tools_is_stdin(const char *key_file)
377 return strcmp(key_file, "-") ? 0 : 1;
380 int tools_read_vk(const char *file, char **key, int keysize)
382 int fd = -1, r = -EINVAL;
384 if (keysize <= 0 || !key)
387 *key = crypt_safe_alloc(keysize);
391 fd = open(file, O_RDONLY);
393 log_err(_("Cannot read keyfile %s."), file);
397 if (read_buffer(fd, *key, keysize) != keysize) {
398 log_err(_("Cannot read %d bytes from keyfile %s."), keysize, file);
407 crypt_safe_free(*key);
414 int tools_write_mk(const char *file, const char *key, int keysize)
418 if (keysize <= 0 || !key)
421 fd = open(file, O_CREAT|O_EXCL|O_WRONLY, S_IRUSR);
423 log_err(_("Cannot open keyfile %s for write."), file);
427 if (write_buffer(fd, key, keysize) == keysize)
430 log_err(_("Cannot write to keyfile %s."), file);
436 void tools_package_version(const char *name, bool use_pwlibs)
438 bool udev = false, blkid = false, keyring = false, fips = false;
439 bool kernel_capi = false, pwquality = false, passwdqc = false;
446 #ifdef KERNEL_KEYRING
455 #if defined(ENABLE_PWQUALITY)
457 #elif defined(ENABLE_PASSWDQC)
460 log_std("%s %s flags: %s%s%s%s%s%s%s\n", name, PACKAGE_VERSION,
462 blkid ? "BLKID " : "",
463 keyring ? "KEYRING " : "",
465 kernel_capi ? "KERNEL_CAPI " : "",
466 pwquality && use_pwlibs ? "PWQUALITY " : "",
467 passwdqc && use_pwlibs ? "PASSWDQC " : "");