/*
* cryptsetup - setup cryptographic volumes for dm-crypt
*
- * Copyright (C) 2004, Christophe Saout <christophe@saout.de>
- * Copyright (C) 2004-2007, Clemens Fruhwirth <clemens@endorphin.org>
- * Copyright (C) 2009-2012, Red Hat, Inc. All rights reserved.
- * Copyright (C) 2009-2012, Milan Broz
+ * Copyright (C) 2004 Jana Saout <jana@saout.de>
+ * Copyright (C) 2004-2007 Clemens Fruhwirth <clemens@endorphin.org>
+ * Copyright (C) 2009-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2009-2023 Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
#include "cryptsetup.h"
#include <signal.h>
-int opt_verbose = 0;
-int opt_debug = 0;
-int opt_batch_mode = 0;
-
/* interrupt handling */
volatile int quit = 0;
static int signals_blocked = 0;
*r = -EINTR;
}
-__attribute__((format(printf, 5, 6)))
-void clogger(struct crypt_device *cd, int level, const char *file, int line,
- const char *format, ...)
+void tool_log(int level, const char *msg, void *usrptr)
{
- va_list argp;
- char *target = NULL;
-
- va_start(argp, format);
-
- if (vasprintf(&target, format, argp) > 0) {
- if (level >= 0) {
- crypt_log(cd, level, target);
-#ifdef CRYPT_DEBUG
- } else if (opt_debug)
- printf("# %s:%d %s\n", file ?: "?", line, target);
-#else
- } else if (opt_debug)
- printf("# %s\n", target);
-#endif
- }
+ struct tools_log_params *params = (struct tools_log_params *)usrptr;
- va_end(argp);
- free(target);
-}
-
-void tool_log(int level, const char *msg, void *usrptr __attribute__((unused)))
-{
- switch(level) {
+ switch (level) {
case CRYPT_LOG_NORMAL:
- fputs(msg, stdout);
+ fprintf(stdout, "%s", msg);
break;
case CRYPT_LOG_VERBOSE:
- if (opt_verbose)
- fputs(msg, stdout);
+ if (params && params->verbose)
+ fprintf(stdout, "%s", msg);
break;
case CRYPT_LOG_ERROR:
- fputs(msg, stderr);
+ fprintf(stderr, "%s", msg);
break;
+ case CRYPT_LOG_DEBUG_JSON:
case CRYPT_LOG_DEBUG:
- if (opt_debug)
- printf("# %s\n", msg);
- break;
- default:
- fprintf(stderr, "Internal error on logging class for msg: %s", msg);
+ if (params && params->debug)
+ fprintf(stdout, "# %s", msg);
break;
}
}
void quiet_log(int level, const char *msg, void *usrptr)
{
- if (!opt_verbose && (level == CRYPT_LOG_ERROR || level == CRYPT_LOG_NORMAL))
- level = CRYPT_LOG_VERBOSE;
+ struct tools_log_params *params = (struct tools_log_params *)usrptr;
+
+ if ((!params || !params->verbose) && (level == CRYPT_LOG_ERROR || level == CRYPT_LOG_NORMAL))
+ return;
tool_log(level, msg, usrptr);
}
-int yesDialog(const char *msg, void *usrptr __attribute__((unused)))
+static int _dialog(const char *msg, void *usrptr, int default_answer)
{
+ const char *fail_msg = (const char *)usrptr;
char *answer = NULL;
size_t size = 0;
- int r = 1, block;
+ int r = default_answer, block;
block = tools_signals_blocked();
if (block)
set_int_block(0);
- if(isatty(STDIN_FILENO) && !opt_batch_mode) {
- log_std("\nWARNING!\n========\n");
- log_std("%s\n\nAre you sure? (Type uppercase yes): ", msg);
+ if (isatty(STDIN_FILENO)) {
+ log_std(_("\nWARNING!\n========\n"));
+ /* TRANSLATORS: User must type "YES" (in capital letters), do not translate this word. */
+ log_std(_("%s\n\nAre you sure? (Type 'yes' in capital letters): "), msg);
+ fflush(stdout);
if(getline(&answer, &size, stdin) == -1) {
r = 0;
/* Aborted by signal */
if (!quit)
- log_err(_("Error reading response from terminal.\n"));
+ log_err(_("Error reading response from terminal."));
else
log_dbg("Query interrupted on signal.");
- } else if(strcmp(answer, "YES\n"))
- r = 0;
+ } else {
+ r = !strcmp(answer, "YES\n");
+ if (!r && fail_msg)
+ log_err("%s", fail_msg);
+ }
}
if (block && !quit)
return r;
}
-void show_status(int errcode)
+int yesDialog(const char *msg, void *usrptr)
{
- char error[256], *error_;
-
- if(!opt_verbose)
- return;
+ return _dialog(msg, usrptr, 1);
+}
- if(!errcode) {
- log_std(_("Command successful.\n"));
- return;
- }
+int noDialog(const char *msg, void *usrptr)
+{
+ return _dialog(msg, usrptr, 0);
+}
- crypt_get_error(error, sizeof(error));
+void show_status(int errcode)
+{
+ char *crypt_error;
- if (!error[0]) {
- error_ = strerror_r(-errcode, error, sizeof(error));
- if (error_ != error) {
- strncpy(error, error_, sizeof(error));
- error[sizeof(error) - 1] = '\0';
- }
+ if (!errcode) {
+ log_verbose(_("Command successful."));
+ return;
}
- log_err(_("Command failed with code %i"), -errcode);
- if (*error)
- log_err(": %s\n", error);
+ if (errcode < 0)
+ errcode = translate_errno(errcode);
+
+ if (errcode == 1)
+ crypt_error = _("wrong or missing parameters");
+ else if (errcode == 2)
+ crypt_error = _("no permission or bad passphrase");
+ else if (errcode == 3)
+ crypt_error = _("out of memory");
+ else if (errcode == 4)
+ crypt_error = _("wrong device or file specified");
+ else if (errcode == 5)
+ crypt_error = _("device already exists or device is busy");
else
- log_err(".\n");
+ crypt_error = _("unknown error");
+
+ log_verbose(_("Command failed with code %i (%s)."), -errcode, crypt_error);
}
const char *uuid_or_device(const char *spec)
strcpy(device, "/dev/disk/by-uuid/");
ptr = &device[strlen(device)];
i = uuid_len;
- while ((s = spec[i++]) && i < PATH_MAX) {
+ while ((s = spec[i++]) && i < (PATH_MAX - 13)) {
if (!isxdigit(s) && s != '-')
return spec; /* Bail it out */
if (isalpha(s))
{
poptPrintUsage(popt_context, stderr, 0);
if (error)
- log_err("%s: %s\n", more, error);
+ log_err("%s: %s", more, error);
+ tools_cleanup();
poptFreeContext(popt_context);
exit(exitcode);
}
}
return r;
}
+
+void tools_keyslot_msg(int keyslot, crypt_object_op op)
+{
+ if (keyslot < 0)
+ return;
+
+ if (op == CREATED)
+ log_verbose(_("Key slot %i created."), keyslot);
+ else if (op == UNLOCKED)
+ log_verbose(_("Key slot %i unlocked."), keyslot);
+ else if (op == REMOVED)
+ log_verbose(_("Key slot %i removed."), keyslot);
+}
+
+void tools_token_msg(int token, crypt_object_op op)
+{
+ if (token < 0)
+ return;
+
+ if (op == CREATED)
+ log_verbose(_("Token %i created."), token);
+ else if (op == REMOVED)
+ log_verbose(_("Token %i removed."), token);
+}
+
+void tools_token_error_msg(int error, const char *type, int token, bool pin_provided)
+{
+ if (error >= 0)
+ return;
+
+ if (error == -ENOANO) {
+ if (pin_provided)
+ log_verbose(_("No token could be unlocked with this PIN."));
+ else if (token != CRYPT_ANY_TOKEN)
+ log_verbose(_("Token %i requires PIN."), token);
+ else if (type)
+ log_verbose(_("Token (type %s) requires PIN."), type);
+ } else if (error == -EPERM) {
+ if (token != CRYPT_ANY_TOKEN)
+ log_verbose(_("Token %i cannot unlock assigned keyslot(s) (wrong keyslot passphrase)."), token);
+ else if (type)
+ log_verbose(_("Token (type %s) cannot unlock assigned keyslot(s) (wrong keyslot passphrase)."), type);
+ } if (error == -EAGAIN) {
+ if (token != CRYPT_ANY_TOKEN)
+ log_verbose(_("Token %i requires additional missing resource."), token);
+ else if (type)
+ log_verbose(_("Token (type %s) requires additional missing resource."), type);
+ } if (error == -ENOENT) {
+ if (type)
+ log_verbose(_("No usable token (type %s) is available."), type);
+ else
+ log_verbose(_("No usable token is available."));
+ }
+}
+
+/*
+ * Device size string parsing, suffixes:
+ * s|S - 512 bytes sectors
+ * k |K |m |M |g |G |t |T - 1024 base
+ * kiB|KiB|miB|MiB|giB|GiB|tiB|TiB - 1024 base
+ * kb |KB |mM |MB |gB |GB |tB |TB - 1000 base
+ */
+int tools_string_to_size(const char *s, uint64_t *size)
+{
+ char *endp = NULL;
+ size_t len;
+ uint64_t mult_base, mult, tmp;
+
+ *size = strtoull(s, &endp, 10);
+ if (!isdigit(s[0]) ||
+ (errno == ERANGE && *size == ULLONG_MAX) ||
+ (errno != 0 && *size == 0))
+ return -EINVAL;
+
+ if (!endp || !*endp)
+ return 0;
+
+ len = strlen(endp);
+ /* Allow "B" and "iB" suffixes */
+ if (len > 3 ||
+ (len == 3 && (endp[1] != 'i' || endp[2] != 'B')) ||
+ (len == 2 && endp[1] != 'B'))
+ return -EINVAL;
+
+ if (len == 1 || len == 3)
+ mult_base = 1024;
+ else
+ mult_base = 1000;
+
+ mult = 1;
+ switch (endp[0]) {
+ case 's':
+ case 'S': mult = 512;
+ break;
+ case 't':
+ case 'T': mult *= mult_base;
+ /* Fall through */
+ case 'g':
+ case 'G': mult *= mult_base;
+ /* Fall through */
+ case 'm':
+ case 'M': mult *= mult_base;
+ /* Fall through */
+ case 'k':
+ case 'K': mult *= mult_base;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ tmp = *size * mult;
+ if (*size && (tmp / *size) != mult) {
+ log_dbg("Device size overflow.");
+ return -EINVAL;
+ }
+
+ *size = tmp;
+ return 0;
+}
+
+/*
+ * Keyfile - is standard input treated as a binary file (no EOL handling).
+ */
+int tools_is_stdin(const char *key_file)
+{
+ if (!key_file)
+ return 1;
+
+ return strcmp(key_file, "-") ? 0 : 1;
+}
+
+int tools_read_vk(const char *file, char **key, int keysize)
+{
+ int fd = -1, r = -EINVAL;
+
+ if (keysize <= 0 || !key)
+ return -EINVAL;
+
+ *key = crypt_safe_alloc(keysize);
+ if (!*key)
+ return -ENOMEM;
+
+ fd = open(file, O_RDONLY);
+ if (fd == -1) {
+ log_err(_("Cannot read keyfile %s."), file);
+ goto out;
+ }
+
+ if (read_buffer(fd, *key, keysize) != keysize) {
+ log_err(_("Cannot read %d bytes from keyfile %s."), keysize, file);
+ goto out;
+ }
+ r = 0;
+out:
+ if (fd != -1)
+ close(fd);
+
+ if (r) {
+ crypt_safe_free(*key);
+ *key = NULL;
+ }
+
+ return r;
+}
+
+int tools_write_mk(const char *file, const char *key, int keysize)
+{
+ int fd, r = -EINVAL;
+
+ if (keysize <= 0 || !key)
+ return -EINVAL;
+
+ fd = open(file, O_CREAT|O_EXCL|O_WRONLY, S_IRUSR);
+ if (fd < 0) {
+ log_err(_("Cannot open keyfile %s for write."), file);
+ return r;
+ }
+
+ if (write_buffer(fd, key, keysize) == keysize)
+ r = 0;
+ else
+ log_err(_("Cannot write to keyfile %s."), file);
+
+ close(fd);
+ return r;
+}
+
+void tools_package_version(const char *name, bool use_pwlibs)
+{
+ bool udev = false, blkid = false, keyring = false, fips = false;
+ bool kernel_capi = false, pwquality = false, passwdqc = false;
+#ifdef USE_UDEV
+ udev = true;
+#endif
+#ifdef HAVE_BLKID
+ blkid = true;
+#endif
+#ifdef KERNEL_KEYRING
+ keyring = true;
+#endif
+#ifdef ENABLE_FIPS
+ fips = true;
+#endif
+#ifdef ENABLE_AF_ALG
+ kernel_capi = true;
+#endif
+#if defined(ENABLE_PWQUALITY)
+ pwquality = true;
+#elif defined(ENABLE_PASSWDQC)
+ passwdqc = true;
+#endif
+ log_std("%s %s flags: %s%s%s%s%s%s%s\n", name, PACKAGE_VERSION,
+ udev ? "UDEV " : "",
+ blkid ? "BLKID " : "",
+ keyring ? "KEYRING " : "",
+ fips ? "FIPS " : "",
+ kernel_capi ? "KERNEL_CAPI " : "",
+ pwquality && use_pwlibs ? "PWQUALITY " : "",
+ passwdqc && use_pwlibs ? "PASSWDQC " : "");
+}