X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=src%2Fcryptsetup%2Fcryptsetup.c;h=8afff739907fdff6ed1924554619e378199b4403;hb=294bf0c34a53caa25709b794bfeee6a00a2b6ecd;hp=ab4d24ca3bc5bc50782c5a98b59f79bf5299e82c;hpb=1a2d4d70845f483bcb3f704fa092f5fd76580d31;p=thirdparty%2Fsystemd.git diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c index ab4d24ca3bc..8afff739907 100644 --- a/src/cryptsetup/cryptsetup.c +++ b/src/cryptsetup/cryptsetup.c @@ -1,22 +1,4 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ -/*** - This file is part of systemd. - - Copyright 2010 Lennart Poettering - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see . -***/ #include #include @@ -32,22 +14,30 @@ #include "escape.h" #include "fileio.h" #include "log.h" +#include "main-func.h" #include "mount-util.h" #include "parse-util.h" #include "path-util.h" #include "string-util.h" #include "strv.h" +#include "pretty-print.h" #include "util.h" /* internal helper */ #define ANY_LUKS "LUKS" +/* as in src/cryptsetup.h */ +#define CRYPT_SECTOR_SIZE 512 +#define CRYPT_MAX_SECTOR_SIZE 4096 static const char *arg_type = NULL; /* ANY_LUKS, CRYPT_LUKS1, CRYPT_LUKS2, CRYPT_TCRYPT or CRYPT_PLAIN */ static char *arg_cipher = NULL; static unsigned arg_key_size = 0; +#if HAVE_LIBCRYPTSETUP_SECTOR_SIZE +static unsigned arg_sector_size = CRYPT_SECTOR_SIZE; +#endif static int arg_key_slot = CRYPT_ANY_SLOT; static unsigned arg_keyfile_size = 0; -static unsigned arg_keyfile_offset = 0; +static uint64_t arg_keyfile_offset = 0; static char *arg_hash = NULL; static char *arg_header = NULL; static unsigned arg_tries = 3; @@ -64,6 +54,11 @@ static uint64_t arg_offset = 0; static uint64_t arg_skip = 0; static usec_t arg_timeout = USEC_INFINITY; +STATIC_DESTRUCTOR_REGISTER(arg_cipher, freep); +STATIC_DESTRUCTOR_REGISTER(arg_hash, freep); +STATIC_DESTRUCTOR_REGISTER(arg_header, freep); +STATIC_DESTRUCTOR_REGISTER(arg_tcrypt_keyfiles, strv_freep); + /* Options Debian's crypttab knows we don't: precheck= @@ -104,6 +99,29 @@ static int parse_one_option(const char *option) { arg_key_size /= 8; + } else if ((val = startswith(option, "sector-size="))) { + +#if HAVE_LIBCRYPTSETUP_SECTOR_SIZE + r = safe_atou(val, &arg_sector_size); + if (r < 0) { + log_error_errno(r, "Failed to parse %s, ignoring: %m", option); + return 0; + } + + if (arg_sector_size % 2) { + log_error("sector-size= not a multiple of 2, ignoring."); + return 0; + } + + if (arg_sector_size < CRYPT_SECTOR_SIZE || arg_sector_size > CRYPT_MAX_SECTOR_SIZE) { + log_error("sector-size= is outside of %u and %u, ignoring.", CRYPT_SECTOR_SIZE, CRYPT_MAX_SECTOR_SIZE); + return 0; + } +#else + log_error("sector-size= is not supported, compiled with old libcryptsetup."); + return 0; +#endif + } else if ((val = startswith(option, "key-slot="))) { arg_type = ANY_LUKS; @@ -131,13 +149,22 @@ static int parse_one_option(const char *option) { } } else if ((val = startswith(option, "keyfile-offset="))) { + uint64_t off; - r = safe_atou(val, &arg_keyfile_offset); + r = safe_atou64(val, &off); if (r < 0) { log_error_errno(r, "Failed to parse %s, ignoring: %m", option); return 0; } + if ((size_t) off != off) { + /* https://gitlab.com/cryptsetup/cryptsetup/issues/359 */ + log_error("keyfile-offset= value would truncated to %zu, ignoring.", (size_t) off); + return 0; + } + + arg_keyfile_offset = off; + } else if ((val = startswith(option, "hash="))) { r = free_and_strdup(&arg_hash, val); if (r < 0) @@ -249,25 +276,7 @@ static int parse_options(const char *options) { return 0; } -static int disk_major_minor(const char *path, char **ret) { - struct stat st; - - assert(path); - - if (stat(path, &st) < 0) - return -errno; - - if (!S_ISBLK(st.st_mode)) - return -EINVAL; - - if (asprintf(ret, "/dev/block/%d:%d", major(st.st_rdev), minor(st.st_rdev)) < 0) - return -errno; - - return 0; -} - static char* disk_description(const char *path) { - static const char name_fields[] = "ID_PART_ENTRY_NAME\0" "DM_NAME\0" @@ -275,9 +284,8 @@ static char* disk_description(const char *path) { "ID_MODEL\0"; _cleanup_(sd_device_unrefp) sd_device *device = NULL; + const char *i, *name; struct stat st; - const char *i; - int r; assert(path); @@ -287,17 +295,13 @@ static char* disk_description(const char *path) { if (!S_ISBLK(st.st_mode)) return NULL; - r = sd_device_new_from_devnum(&device, 'b', st.st_rdev); - if (r < 0) + if (sd_device_new_from_devnum(&device, 'b', st.st_rdev) < 0) return NULL; - NULSTR_FOREACH(i, name_fields) { - const char *name; - - r = sd_device_get_property_value(device, i, &name); - if (r >= 0 && !isempty(name)) + NULSTR_FOREACH(i, name_fields) + if (sd_device_get_property_value(device, i, &name) >= 0 && + !isempty(name)) return strdup(name); - } return NULL; } @@ -324,7 +328,7 @@ static char *disk_mount_point(const char *label) { } static int get_password(const char *vol, const char *src, usec_t until, bool accept_cached, char ***ret) { - _cleanup_free_ char *description = NULL, *name_buffer = NULL, *mount_point = NULL, *maj_min = NULL, *text = NULL, *escaped_name = NULL; + _cleanup_free_ char *description = NULL, *name_buffer = NULL, *mount_point = NULL, *text = NULL, *disk_path = NULL; _cleanup_strv_free_erase_ char **passwords = NULL; const char *name = NULL; char **p, *id; @@ -337,6 +341,10 @@ static int get_password(const char *vol, const char *src, usec_t until, bool acc description = disk_description(src); mount_point = disk_mount_point(vol); + disk_path = cescape(src); + if (!disk_path) + return log_oom(); + if (description && streq(vol, description)) /* If the description string is simply the * volume name, then let's not show this @@ -355,22 +363,10 @@ static int get_password(const char *vol, const char *src, usec_t until, bool acc name = name_buffer ? name_buffer : vol; - if (asprintf(&text, "Please enter passphrase for disk %s!", name) < 0) + if (asprintf(&text, "Please enter passphrase for disk %s:", name) < 0) return log_oom(); - if (src) - (void) disk_major_minor(src, &maj_min); - - if (maj_min) { - escaped_name = maj_min; - maj_min = NULL; - } else - escaped_name = cescape(name); - - if (!escaped_name) - return log_oom(); - - id = strjoina("cryptsetup:", escaped_name); + id = strjoina("cryptsetup:", disk_path); r = ask_password_auto(text, "drive-harddisk", id, "cryptsetup", until, ASK_PASSWORD_PUSH_CACHE | (accept_cached*ASK_PASSWORD_ACCEPT_CACHED), @@ -383,10 +379,10 @@ static int get_password(const char *vol, const char *src, usec_t until, bool acc assert(strv_length(passwords) == 1); - if (asprintf(&text, "Please enter passphrase for disk %s! (verification)", name) < 0) + if (asprintf(&text, "Please enter passphrase for disk %s (verification):", name) < 0) return log_oom(); - id = strjoina("cryptsetup-verification:", escaped_name); + id = strjoina("cryptsetup-verification:", disk_path); r = ask_password_auto(text, "drive-harddisk", id, "cryptsetup", until, ASK_PASSWORD_PUSH_CACHE, &passwords2); if (r < 0) @@ -418,8 +414,7 @@ static int get_password(const char *vol, const char *src, usec_t until, bool acc *p = c; } - *ret = passwords; - passwords = NULL; + *ret = TAKE_PTR(passwords); return 0; } @@ -506,6 +501,9 @@ static int attach_luks_or_plain(struct crypt_device *cd, struct crypt_params_plain params = { .offset = arg_offset, .skip = arg_skip, +#if HAVE_LIBCRYPTSETUP_SECTOR_SIZE + .sector_size = arg_sector_size, +#endif }; const char *cipher, *cipher_mode; _cleanup_free_ char *truncated_cipher = NULL; @@ -584,33 +582,38 @@ static int attach_luks_or_plain(struct crypt_device *cd, } static int help(void) { + _cleanup_free_ char *link = NULL; + int r; + + r = terminal_urlify_man("systemd-cryptsetup@.service", "8", &link); + if (r < 0) + return log_oom(); printf("%s attach VOLUME SOURCEDEVICE [PASSWORD] [OPTIONS]\n" "%s detach VOLUME\n\n" - "Attaches or detaches an encrypted block device.\n", - program_invocation_short_name, - program_invocation_short_name); + "Attaches or detaches an encrypted block device.\n" + "\nSee the %s for details.\n" + , program_invocation_short_name + , program_invocation_short_name + , link + ); return 0; } -int main(int argc, char *argv[]) { +static int run(int argc, char *argv[]) { _cleanup_(crypt_freep) struct crypt_device *cd = NULL; - int r = -EINVAL; + int r; - if (argc <= 1) { - r = help(); - goto finish; - } + if (argc <= 1) + return help(); if (argc < 3) { log_error("This program requires at least two arguments."); - goto finish; + return -EINVAL; } - log_set_target(LOG_TARGET_AUTO); - log_parse_environment(); - log_open(); + log_setup_service(); umask(0022); @@ -625,7 +628,7 @@ int main(int argc, char *argv[]) { if (argc < 4) { log_error("attach requires at least two arguments."); - goto finish; + return -EINVAL; } if (argc >= 5 && @@ -640,8 +643,9 @@ int main(int argc, char *argv[]) { } if (argc >= 6 && argv[5][0] && !streq(argv[5], "-")) { - if (parse_options(argv[5]) < 0) - goto finish; + r = parse_options(argv[5]); + if (r < 0) + return r; } /* A delicious drop of snake oil */ @@ -652,18 +656,15 @@ int main(int argc, char *argv[]) { r = crypt_init(&cd, arg_header); } else r = crypt_init(&cd, argv[3]); - if (r < 0) { - log_error_errno(r, "crypt_init() failed: %m"); - goto finish; - } + if (r < 0) + return log_error_errno(r, "crypt_init() failed: %m"); crypt_set_log_callback(cd, cryptsetup_log_glue, NULL); status = crypt_status(cd, argv[2]); if (IN_SET(status, CRYPT_ACTIVE, CRYPT_BUSY)) { log_info("Volume %s already active.", argv[2]); - r = 0; - goto finish; + return 0; } if (arg_readonly) @@ -696,7 +697,7 @@ int main(int argc, char *argv[]) { if (r == -EAGAIN) continue; if (r < 0) - goto finish; + return r; } if (streq_ptr(arg_type, CRYPT_TCRYPT)) @@ -714,18 +715,15 @@ int main(int argc, char *argv[]) { key_file = NULL; continue; } - if (r != -EPERM) { - log_error_errno(r, "Failed to activate: %m"); - goto finish; - } + if (r != -EPERM) + return log_error_errno(r, "Failed to activate: %m"); log_warning("Invalid passphrase."); } if (arg_tries != 0 && tries >= arg_tries) { log_error("Too many attempts; giving up."); - r = -EPERM; - goto finish; + return -EPERM; } } else if (streq(argv[1], "detach")) { @@ -733,34 +731,23 @@ int main(int argc, char *argv[]) { r = crypt_init_by_name(&cd, argv[2]); if (r == -ENODEV) { log_info("Volume %s already inactive.", argv[2]); - r = 0; - goto finish; - } - if (r < 0) { - log_error_errno(r, "crypt_init_by_name() failed: %m"); - goto finish; + return 0; } + if (r < 0) + return log_error_errno(r, "crypt_init_by_name() failed: %m"); crypt_set_log_callback(cd, cryptsetup_log_glue, NULL); r = crypt_deactivate(cd, argv[2]); - if (r < 0) { - log_error_errno(r, "Failed to deactivate: %m"); - goto finish; - } + if (r < 0) + return log_error_errno(r, "Failed to deactivate: %m"); } else { log_error("Unknown verb %s.", argv[1]); - goto finish; + return -EINVAL; } - r = 0; - -finish: - free(arg_cipher); - free(arg_hash); - free(arg_header); - strv_free(arg_tcrypt_keyfiles); - - return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; + return 0; } + +DEFINE_MAIN_FUNCTION(run);