Files
systemd/src/cryptsetup/cryptsetup-keyfile.c
Kamil Szczęk 53b6c99018 cryptsetup: make key discovery more robust
Currently, if user doesn't specify a key file, /etc/cryptsetup-keys.d/
and /run/cryptsetup-keys.d/ will be searched for a key file with name
matching the volume name. But current implementation has an important
flaw. When the auto-discovered key is a socket file - it will read the
key only once, while the socket might provide different keys for
different types of tokens. The issue is fixed by trying to discover the
key on each unlock attempt, this way we can populate the socket bind
name with something the key provider might use to differentiate between
different keys it has to provide.
2024-06-27 12:58:45 +02:00

56 lines
2.1 KiB
C

/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "cryptsetup-keyfile.h"
#include "fileio.h"
#include "path-util.h"
#include "strv.h"
int find_key_file(const char *key_file, char **search_path, const char *bindname, struct iovec *ret_key) {
int r;
assert(key_file);
assert(ret_key);
if (strv_isempty(search_path) || path_is_absolute(key_file)) {
r = read_full_file_full(
AT_FDCWD, key_file, UINT64_MAX, SIZE_MAX,
READ_FULL_FILE_SECURE|READ_FULL_FILE_WARN_WORLD_READABLE|READ_FULL_FILE_CONNECT_SOCKET,
bindname,
(char**) &ret_key->iov_base, &ret_key->iov_len);
if (r == -E2BIG)
return log_error_errno(r, "Key file '%s' too large.", key_file);
if (r < 0)
return log_error_errno(r, "Failed to load key file '%s': %m", key_file);
return 1;
}
STRV_FOREACH(i, search_path) {
_cleanup_free_ char *joined = NULL;
joined = path_join(*i, key_file);
if (!joined)
return log_oom();
r = read_full_file_full(
AT_FDCWD, joined, UINT64_MAX, SIZE_MAX,
READ_FULL_FILE_SECURE|READ_FULL_FILE_WARN_WORLD_READABLE|READ_FULL_FILE_CONNECT_SOCKET,
bindname,
(char**) &ret_key->iov_base, &ret_key->iov_len);
if (r >= 0)
return 1;
if (r == -E2BIG) {
log_warning_errno(r, "Key file '%s' too large, ignoring.", key_file);
continue;
}
if (r != -ENOENT)
return log_error_errno(r, "Failed to load key file '%s': %m", key_file);
}
/* Search path supplied, but file not found, report by returning NULL, but not failing */
*ret_key = IOVEC_MAKE(NULL, 0);
return 0;
}