X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Futils_tools.c;h=a0e2ebceafb4e57096648bd91cdf7bb985afeeef;hb=420ad62f0bb77970a6ba234bde9e1405f7df7789;hp=23e4acb42c3e0947a7496cb8801ece1b2fef78fa;hpb=a3777a6b2cde2c7133141474dd4c428220a3e9cc;p=platform%2Fupstream%2Fcryptsetup.git diff --git a/src/utils_tools.c b/src/utils_tools.c index 23e4acb..a0e2ebc 100644 --- a/src/utils_tools.c +++ b/src/utils_tools.c @@ -1,10 +1,10 @@ /* * cryptsetup - setup cryptographic volumes for dm-crypt * - * Copyright (C) 2004, Jana Saout - * Copyright (C) 2004-2007, Clemens Fruhwirth - * Copyright (C) 2009-2012, Red Hat, Inc. All rights reserved. - * Copyright (C) 2009-2014, Milan Broz + * Copyright (C) 2004 Jana Saout + * Copyright (C) 2004-2007 Clemens Fruhwirth + * 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 @@ -24,10 +24,6 @@ #include "cryptsetup.h" #include -int opt_verbose = 0; -int opt_debug = 0; -int opt_batch_mode = 0; - /* interrupt handling */ volatile int quit = 0; static int signals_blocked = 0; @@ -74,85 +70,67 @@ void check_signal(int *r) *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) @@ -162,37 +140,42 @@ int yesDialog(const char *msg, void *usrptr __attribute__((unused))) return r; } -void show_status(int errcode) +int yesDialog(const char *msg, void *usrptr) { - char error[256]; - - 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) { -#ifdef STRERROR_R_CHAR_P /* GNU-specific strerror_r */ - char *error_ = strerror_r(-errcode, error, sizeof(error)); - if (error_ != error) - strncpy(error, error_, sizeof(error)); -#else /* POSIX strerror_r variant */ - if (strerror_r(-errcode, error, sizeof(error))) - *error = '\0'; -#endif - 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) @@ -206,7 +189,7 @@ 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)) @@ -226,7 +209,8 @@ __attribute__ ((noreturn)) void usage(poptContext popt_context, { 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); } @@ -262,3 +246,223 @@ int translate_errno(int r) } 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 " : ""); +}