mirror of
https://github.com/systemd/systemd
synced 2024-09-06 08:46:19 +00:00
cryptsetup: modify keyfile search logic to use read_file_full() too
Let's move the 3rd way how cryptsetup acquires key files to read_file_full() too. Since load_key_file()'s raison d'etre now is just the search path logic, let's rename the function to find_key_file().
This commit is contained in:
parent
e2c2f868b2
commit
e060ed32e4
|
@ -1,29 +1,18 @@
|
|||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#include "cryptsetup-keyfile.h"
|
||||
#include "fd-util.h"
|
||||
#include "format-util.h"
|
||||
#include "memory-util.h"
|
||||
#include "fileio.h"
|
||||
#include "path-util.h"
|
||||
#include "stat-util.h"
|
||||
#include "strv.h"
|
||||
|
||||
#define KEY_FILE_SIZE_MAX (16U*1024U*1024U) /* 16 MiB */
|
||||
|
||||
int load_key_file(
|
||||
int find_key_file(
|
||||
const char *key_file,
|
||||
char **search_path,
|
||||
size_t key_file_size,
|
||||
uint64_t key_file_offset,
|
||||
const char *bindname,
|
||||
void **ret_key,
|
||||
size_t *ret_key_size) {
|
||||
|
||||
_cleanup_(erase_and_freep) char *buffer = NULL;
|
||||
_cleanup_free_ char *discovered_path = NULL;
|
||||
_cleanup_close_ int fd = -1;
|
||||
ssize_t n;
|
||||
char **i;
|
||||
int r;
|
||||
|
||||
assert(key_file);
|
||||
|
@ -31,80 +20,38 @@ int load_key_file(
|
|||
assert(ret_key_size);
|
||||
|
||||
if (strv_isempty(search_path) || path_is_absolute(key_file)) {
|
||||
fd = open(key_file, O_RDONLY|O_CLOEXEC);
|
||||
if (fd < 0)
|
||||
return log_error_errno(errno, "Failed to load key file '%s': %m", key_file);
|
||||
} else {
|
||||
char **i;
|
||||
|
||||
STRV_FOREACH(i, search_path) {
|
||||
_cleanup_free_ char *joined;
|
||||
|
||||
joined = path_join(*i, key_file);
|
||||
if (!joined)
|
||||
return log_oom();
|
||||
|
||||
fd = open(joined, O_RDONLY|O_CLOEXEC);
|
||||
if (fd >= 0) {
|
||||
discovered_path = TAKE_PTR(joined);
|
||||
break;
|
||||
}
|
||||
if (errno != ENOENT)
|
||||
return log_error_errno(errno, "Failed to load key file '%s': %m", joined);
|
||||
}
|
||||
|
||||
if (!discovered_path) {
|
||||
/* Search path supplied, but file not found, report by returning NULL, but not failing */
|
||||
*ret_key = NULL;
|
||||
*ret_key_size = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(fd >= 0);
|
||||
key_file = discovered_path;
|
||||
}
|
||||
|
||||
if (key_file_size == 0) {
|
||||
struct stat st;
|
||||
|
||||
if (fstat(fd, &st) < 0)
|
||||
return log_error_errno(errno, "Failed to stat key file '%s': %m", key_file);
|
||||
|
||||
r = stat_verify_regular(&st);
|
||||
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, ret_key_size);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Key file is not a regular file: %m");
|
||||
return log_error_errno(r, "Failed to load key file '%s': %m", key_file);
|
||||
|
||||
if (st.st_size == 0)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Key file is empty, refusing.");
|
||||
if ((uint64_t) st.st_size > KEY_FILE_SIZE_MAX) {
|
||||
char buf1[FORMAT_BYTES_MAX], buf2[FORMAT_BYTES_MAX];
|
||||
return log_error_errno(SYNTHETIC_ERRNO(ERANGE),
|
||||
"Key file larger (%s) than allowed maximum size (%s), refusing.",
|
||||
format_bytes(buf1, sizeof(buf1), st.st_size),
|
||||
format_bytes(buf2, sizeof(buf2), KEY_FILE_SIZE_MAX));
|
||||
}
|
||||
|
||||
if (key_file_offset >= (uint64_t) st.st_size)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Key file offset too large for file, refusing.");
|
||||
|
||||
key_file_size = st.st_size - key_file_offset;
|
||||
return 1;
|
||||
}
|
||||
|
||||
buffer = malloc(key_file_size);
|
||||
if (!buffer)
|
||||
return log_oom();
|
||||
STRV_FOREACH(i, search_path) {
|
||||
_cleanup_free_ char *joined;
|
||||
|
||||
if (key_file_offset > 0)
|
||||
n = pread(fd, buffer, key_file_size, key_file_offset);
|
||||
else
|
||||
n = read(fd, buffer, key_file_size);
|
||||
if (n < 0)
|
||||
return log_error_errno(errno, "Failed to read key file '%s': %m", key_file);
|
||||
if (n == 0)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Empty encrypted key found, refusing.");
|
||||
joined = path_join(*i, key_file);
|
||||
if (!joined)
|
||||
return log_oom();
|
||||
|
||||
*ret_key = TAKE_PTR(buffer);
|
||||
*ret_key_size = (size_t) n;
|
||||
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, ret_key_size);
|
||||
if (r >= 0)
|
||||
return 1;
|
||||
if (r != -ENOENT)
|
||||
return log_error_errno(r, "Failed to load key file '%s': %m", key_file);
|
||||
}
|
||||
|
||||
return 1;
|
||||
/* Search path supplied, but file not found, report by returning NULL, but not failing */
|
||||
*ret_key = NULL;
|
||||
*ret_key_size = 0;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -4,10 +4,9 @@
|
|||
#include <inttypes.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
int load_key_file(
|
||||
int find_key_file(
|
||||
const char *key_file,
|
||||
char **search_path,
|
||||
size_t key_file_size,
|
||||
uint64_t key_file_offset,
|
||||
const char *bindname,
|
||||
void **ret_key,
|
||||
size_t *ret_key_size);
|
||||
|
|
|
@ -908,16 +908,22 @@ static int run(int argc, char *argv[]) {
|
|||
(void) mlockall(MCL_FUTURE);
|
||||
|
||||
if (!key_file) {
|
||||
_cleanup_free_ char *bindname = NULL;
|
||||
const char *fn;
|
||||
|
||||
bindname = make_bindname(argv[2]);
|
||||
if (!bindname)
|
||||
return log_oom();
|
||||
|
||||
/* If a key file is not explicitly specified, search for a key in a well defined
|
||||
* search path, and load it. */
|
||||
|
||||
fn = strjoina(argv[2], ".key");
|
||||
r = load_key_file(fn,
|
||||
STRV_MAKE("/etc/cryptsetup-keys.d", "/run/cryptsetup-keys.d"),
|
||||
0, 0, /* Note we leave arg_keyfile_offset/arg_keyfile_size as something that only applies to arg_keyfile! */
|
||||
&key_data, &key_data_size);
|
||||
r = find_key_file(
|
||||
fn,
|
||||
STRV_MAKE("/etc/cryptsetup-keys.d", "/run/cryptsetup-keys.d"),
|
||||
bindname,
|
||||
&key_data, &key_data_size);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r > 0)
|
||||
|
|
Loading…
Reference in a new issue