X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fcryptsetup%2Fcryptsetup.c;h=26141a01b087b9bfa429386f7b436892f79d9760;hp=94570eb82d07ac9b836907d86b8cadfb34305176;hb=3f4d56a069d8aedc0a784b6f4a2c049db76289b7;hpb=a2a5291b3f5ab6ed4c92f51d0fd10a03047380d8 diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c index 94570eb82..26141a01b 100644 --- a/src/cryptsetup/cryptsetup.c +++ b/src/cryptsetup/cryptsetup.c @@ -43,6 +43,7 @@ static int arg_key_slot = CRYPT_ANY_SLOT; static unsigned arg_keyfile_size = 0; static unsigned arg_keyfile_offset = 0; static char *arg_hash = NULL; +static char *arg_header = NULL; static unsigned arg_tries = 3; static bool arg_readonly = false; static bool arg_verify = false; @@ -68,7 +69,7 @@ static int parse_one_option(const char *option) { assert(option); /* Handled outside of this tool */ - if (streq(option, "noauto") || streq(option, "nofail")) + if (STR_IN_SET(option, "noauto", "auto", "nofail", "fail")) return 0; if (startswith(option, "cipher=")) { @@ -136,6 +137,23 @@ static int parse_one_option(const char *option) { free(arg_hash); arg_hash = t; + } else if (startswith(option, "header=")) { + arg_type = CRYPT_LUKS1; + + if (!path_is_absolute(option+7)) { + log_error("Header path '%s' is not absolute, refusing.", option+7); + return -EINVAL; + } + + if (arg_header) { + log_error("Duplicate header= options, refusing."); + return -EINVAL; + } + + arg_header = strdup(option+7); + if (!arg_header) + return log_oom(); + } else if (startswith(option, "tries=")) { if (safe_atou(option+6, &arg_tries) < 0) { @@ -280,10 +298,8 @@ static int get_password(const char *name, usec_t until, bool accept_cached, char id = strappenda("cryptsetup:", escaped_name); r = ask_password_auto(text, "drive-harddisk", id, until, accept_cached, passwords); - if (r < 0) { - log_error("Failed to query password: %s", strerror(-r)); - return r; - } + if (r < 0) + return log_error_errno(r, "Failed to query password: %m"); if (arg_verify) { _cleanup_strv_free_ char **passwords2 = NULL; @@ -296,10 +312,8 @@ static int get_password(const char *name, usec_t until, bool accept_cached, char id = strappenda("cryptsetup-verification:", escaped_name); r = ask_password_auto(text, "drive-harddisk", id, until, false, &passwords2); - if (r < 0) { - log_error("Failed to query verification password: %s", strerror(-r)); - return r; - } + if (r < 0) + return log_error_errno(r, "Failed to query verification password: %m"); assert(strv_length(passwords2) == 1); @@ -355,7 +369,7 @@ static int attach_tcrypt(struct crypt_device *cd, if (key_file) { r = read_one_line_file(key_file, &passphrase); if (r < 0) { - log_error("Failed to read password file '%s': %s", key_file, strerror(-r)); + log_error_errno(r, "Failed to read password file '%s': %m", key_file); return -EAGAIN; } @@ -379,6 +393,7 @@ static int attach_tcrypt(struct crypt_device *cd, static int attach_luks_or_plain(struct crypt_device *cd, const char *name, const char *key_file, + const char *data_device, char **passwords, uint32_t flags) { int r = 0; @@ -388,8 +403,16 @@ static int attach_luks_or_plain(struct crypt_device *cd, assert(name); assert(key_file || passwords); - if (!arg_type || streq(arg_type, CRYPT_LUKS1)) + if (!arg_type || streq(arg_type, CRYPT_LUKS1)) { r = crypt_load(cd, CRYPT_LUKS1, NULL); + if (r < 0) { + log_error("crypt_load() failed on device %s.\n", crypt_get_device_name(cd)); + return r; + } + + if (data_device) + r = crypt_set_data_device(cd, data_device); + } if ((!arg_type && r < 0) || streq_ptr(arg_type, CRYPT_PLAIN)) { struct crypt_params_plain params = {}; @@ -400,7 +423,9 @@ static int attach_luks_or_plain(struct crypt_device *cd, /* plain isn't a real hash type. it just means "use no hash" */ if (!streq(arg_hash, "plain")) params.hash = arg_hash; - } else + } else if (!key_file) + /* for CRYPT_PLAIN, the behaviour of cryptsetup + * package is to not hash when a key file is provided */ params.hash = "ripemd160"; if (arg_cipher) { @@ -436,10 +461,8 @@ static int attach_luks_or_plain(struct crypt_device *cd, pass_volume_key = (params.hash == NULL); } - if (r < 0) { - log_error("Loading of cryptographic parameters failed: %s", strerror(-r)); - return r; - } + if (r < 0) + return log_error_errno(r, "Loading of cryptographic parameters failed: %m"); log_info("Set cipher %s, mode %s, key size %i bits for device %s.", crypt_get_cipher(cd), @@ -452,7 +475,7 @@ static int attach_luks_or_plain(struct crypt_device *cd, key_file, arg_keyfile_size, arg_keyfile_offset, flags); if (r < 0) { - log_error("Failed to activate with key file '%s': %s", key_file, strerror(-r)); + log_error_errno(r, "Failed to activate with key file '%s': %m", key_file); return -EAGAIN; } } else { @@ -563,9 +586,14 @@ int main(int argc, char *argv[]) { } name = name_buffer ? name_buffer : argv[2]; - k = crypt_init(&cd, argv[3]); + if (arg_header) { + log_debug("LUKS header: %s", arg_header); + k = crypt_init(&cd, arg_header); + } else + k = crypt_init(&cd, argv[3]); + if (k) { - log_error("crypt_init() failed: %s", strerror(-k)); + log_error_errno(k, "crypt_init() failed: %m"); goto finish; } @@ -596,7 +624,7 @@ int main(int argc, char *argv[]) { /* Ideally we'd do this on the open fd, but since this is just a * warning it's OK to do this in two steps. */ - if (stat(key_file, &st) >= 0 && (st.st_mode & 0005)) + if (stat(key_file, &st) >= 0 && S_ISREG(st.st_mode) && (st.st_mode & 0005)) log_warning("Key file %s is world-readable. This is not a good idea!", key_file); } @@ -614,14 +642,19 @@ int main(int argc, char *argv[]) { if (streq_ptr(arg_type, CRYPT_TCRYPT)) k = attach_tcrypt(cd, argv[2], key_file, passwords, flags); else - k = attach_luks_or_plain(cd, argv[2], key_file, passwords, flags); + k = attach_luks_or_plain(cd, + argv[2], + key_file, + arg_header ? argv[3] : NULL, + passwords, + flags); if (k >= 0) break; else if (k == -EAGAIN) { key_file = NULL; continue; } else if (k != -EPERM) { - log_error("Failed to activate: %s", strerror(-k)); + log_error_errno(k, "Failed to activate: %m"); goto finish; } @@ -639,7 +672,7 @@ int main(int argc, char *argv[]) { k = crypt_init_by_name(&cd, argv[2]); if (k) { - log_error("crypt_init() failed: %s", strerror(-k)); + log_error_errno(k, "crypt_init() failed: %m"); goto finish; } @@ -647,7 +680,7 @@ int main(int argc, char *argv[]) { k = crypt_deactivate(cd, argv[2]); if (k < 0) { - log_error("Failed to deactivate: %s", strerror(-k)); + log_error_errno(k, "Failed to deactivate: %m"); goto finish; } @@ -665,6 +698,7 @@ finish: free(arg_cipher); free(arg_hash); + free(arg_header); strv_free(arg_tcrypt_keyfiles); return r;