]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
cryptsetup: modify keyfile search logic to use read_file_full() too
authorLennart Poettering <lennart@poettering.net>
Wed, 4 Nov 2020 17:15:42 +0000 (18:15 +0100)
committerLennart Poettering <lennart@poettering.net>
Tue, 1 Dec 2020 13:27:01 +0000 (14:27 +0100)
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().

src/cryptsetup/cryptsetup-keyfile.c
src/cryptsetup/cryptsetup-keyfile.h
src/cryptsetup/cryptsetup.c

index f849123563db3d5fea9eea4fd64f25c038e6ec7a..a6281fbdeeeafb616c4c75af4f8b0f39fce26ed3 100644 (file)
@@ -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");
-
-                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.");
+                        return log_error_errno(r, "Failed to load key file '%s': %m", key_file);
 
-                key_file_size = st.st_size - key_file_offset;
+                return 1;
         }
 
-        buffer = malloc(key_file_size);
-        if (!buffer)
-                return log_oom();
-
-        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.");
-
-        *ret_key = TAKE_PTR(buffer);
-        *ret_key_size = (size_t) n;
+        STRV_FOREACH(i, search_path) {
+                _cleanup_free_ char *joined;
+
+                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, 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;
 }
index 308f5ebd68dfab3e8b5e03dc1fa4485b8bc057aa..83bd1fbed2bb3a0438193b6b44c22bd96550cf5a 100644 (file)
@@ -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);
index e32cc9207c28a48e6d75aa12390b5be542bddfc7..78d8eec1d7056b0f93b4baffd1eff93d0ead9da6 100644 (file)
@@ -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)