X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fcryptsetup%2Fcryptsetup.c;h=15dea7b65b47b1c25ad2bfbf4bac312b5b51b0aa;hp=9b9074c52ad0c49af3aa3adfd1cb68caf6c314a7;hb=7376e835289a3f97174a641a1ca4b7dbda997030;hpb=ac1a87b9f2d085ef1f976a79042fe8797da9b329 diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c index 9b9074c52..15dea7b65 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; @@ -88,6 +89,13 @@ static int parse_one_option(const char *option) { return 0; } + if (arg_key_size % 8) { + log_error("size= not a multiple of 8, ignoring."); + return 0; + } + + arg_key_size /= 8; + } else if (startswith(option, "key-slot=")) { arg_type = CRYPT_LUKS1; @@ -129,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) { @@ -168,16 +193,16 @@ static int parse_one_option(const char *option) { } static int parse_options(const char *options) { - char *state, *w; + const char *word, *state; size_t l; int r; assert(options); - FOREACH_WORD_SEPARATOR(w, l, options, ",", state) { + FOREACH_WORD_SEPARATOR(word, l, options, ",", state) { _cleanup_free_ char *o; - o = strndup(w, l); + o = strndup(word, l); if (!o) return -ENOMEM; r = parse_one_option(o); @@ -257,6 +282,8 @@ static int get_password(const char *name, usec_t until, bool accept_cached, char int r; char **p; _cleanup_free_ char *text = NULL; + _cleanup_free_ char *escaped_name = NULL; + char *id; assert(name); assert(passwords); @@ -264,11 +291,15 @@ static int get_password(const char *name, usec_t until, bool accept_cached, char if (asprintf(&text, "Please enter passphrase for disk %s!", name) < 0) return log_oom(); - r = ask_password_auto(text, "drive-harddisk", until, accept_cached, passwords); - if (r < 0) { - log_error("Failed to query password: %s", strerror(-r)); - return r; - } + escaped_name = cescape(name); + if (!escaped_name) + return log_oom(); + + id = strappenda("cryptsetup:", escaped_name); + + r = ask_password_auto(text, "drive-harddisk", id, until, accept_cached, passwords); + if (r < 0) + return log_error_errno(r, "Failed to query password: %m"); if (arg_verify) { _cleanup_strv_free_ char **passwords2 = NULL; @@ -278,11 +309,11 @@ static int get_password(const char *name, usec_t until, bool accept_cached, char if (asprintf(&text, "Please enter passphrase for disk %s! (verification)", name) < 0) return log_oom(); - r = ask_password_auto(text, "drive-harddisk", until, false, &passwords2); - if (r < 0) { - log_error("Failed to query verification password: %s", strerror(-r)); - return r; - } + id = strappenda("cryptsetup-verification:", escaped_name); + + r = ask_password_auto(text, "drive-harddisk", id, until, false, &passwords2); + if (r < 0) + return log_error_errno(r, "Failed to query verification password: %m"); assert(strv_length(passwords2) == 1); @@ -327,7 +358,7 @@ static int attach_tcrypt(struct crypt_device *cd, assert(cd); assert(name); - assert(key_file || passwords); + assert(key_file || (passwords && passwords[0])); if (arg_tcrypt_hidden) params.flags |= CRYPT_TCRYPT_HIDDEN_HEADER; @@ -338,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; } @@ -362,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; @@ -371,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 = {}; @@ -383,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) { @@ -404,7 +446,7 @@ static int attach_luks_or_plain(struct crypt_device *cd, /* for CRYPT_PLAIN limit reads * from keyfile to key length, and * ignore keyfile-size */ - arg_keyfile_size = arg_key_size / 8; + arg_keyfile_size = arg_key_size; /* In contrast to what the name * crypt_setup() might suggest this @@ -419,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), @@ -435,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 { @@ -532,18 +572,28 @@ int main(int argc, char *argv[]) { description = NULL; } + k = 0; if (mount_point && description) - asprintf(&name_buffer, "%s (%s) on %s", description, argv[2], mount_point); + k = asprintf(&name_buffer, "%s (%s) on %s", description, argv[2], mount_point); else if (mount_point) - asprintf(&name_buffer, "%s on %s", argv[2], mount_point); + k = asprintf(&name_buffer, "%s on %s", argv[2], mount_point); else if (description) - asprintf(&name_buffer, "%s (%s)", description, argv[2]); + k = asprintf(&name_buffer, "%s (%s)", description, argv[2]); + if (k < 0) { + log_oom(); + goto finish; + } 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; } @@ -567,7 +617,7 @@ int main(int argc, char *argv[]) { else until = 0; - arg_key_size = (arg_key_size > 0 ? arg_key_size : 256); + arg_key_size = (arg_key_size > 0 ? arg_key_size : (256 / 8)); if (key_file) { struct stat st; @@ -592,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; } @@ -617,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; } @@ -625,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; } @@ -643,6 +698,7 @@ finish: free(arg_cipher); free(arg_hash); + free(arg_header); strv_free(arg_tcrypt_keyfiles); return r;