]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
creds-util: move pick_up_credentials() from network-generator
authorYu Watanabe <watanabe.yu+github@gmail.com>
Fri, 5 Apr 2024 03:21:30 +0000 (12:21 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Tue, 16 Apr 2024 00:42:20 +0000 (09:42 +0900)
The function is quite general, and can be used at other places.
Let's move to our shared library.

src/network/generator/main.c
src/shared/creds-util.c
src/shared/creds-util.h

index 0455d5f5c3f8617a4df7474c0051ae719e4fc153..5a26a54fc568cc625ccc272235f823c9769683f8 100644 (file)
@@ -3,7 +3,6 @@
 #include <getopt.h>
 
 #include "build.h"
-#include "copy.h"
 #include "creds-util.h"
 #include "fd-util.h"
 #include "fs-util.h"
@@ -14,7 +13,6 @@
 #include "network-generator.h"
 #include "path-util.h"
 #include "proc-cmdline.h"
-#include "recurse-dir.h"
 
 #define NETWORK_UNIT_DIRECTORY "/run/systemd/network/"
 
@@ -143,76 +141,6 @@ static int context_save(Context *context) {
         return r;
 }
 
-static int pick_up_credentials(void) {
-        _cleanup_close_ int credential_dir_fd = -EBADF;
-        int r, ret = 0;
-
-        credential_dir_fd = open_credentials_dir();
-        if (IN_SET(credential_dir_fd, -ENXIO, -ENOENT)) /* Credential env var not set, or dir doesn't exist. */
-                return 0;
-        if (credential_dir_fd < 0)
-                return log_error_errno(credential_dir_fd, "Failed to open credentials directory: %m");
-
-        _cleanup_free_ DirectoryEntries *des = NULL;
-        r = readdir_all(credential_dir_fd, RECURSE_DIR_SORT|RECURSE_DIR_IGNORE_DOT|RECURSE_DIR_ENSURE_TYPE, &des);
-        if (r < 0)
-                return log_error_errno(r, "Failed to enumerate credentials: %m");
-
-        FOREACH_ARRAY(i, des->entries, des->n_entries) {
-                static const struct {
-                        const char *credential_prefix;
-                        const char *filename_suffix;
-                } table[] = {
-                        { "network.link.",    ".link"    },
-                        { "network.netdev.",  ".netdev"  },
-                        { "network.network.", ".network" },
-                };
-
-                _cleanup_free_ char *fn = NULL;
-                struct dirent *de = *i;
-
-                if (de->d_type != DT_REG)
-                        continue;
-
-                FOREACH_ARRAY(t, table, ELEMENTSOF(table)) {
-                        const char *e = startswith(de->d_name, t->credential_prefix);
-
-                        if (e) {
-                                fn = strjoin(e, t->filename_suffix);
-                                if (!fn)
-                                        return log_oom();
-
-                                break;
-                        }
-                }
-
-                if (!fn)
-                        continue;
-
-                if (!filename_is_valid(fn)) {
-                        log_warning("Passed credential '%s' would result in invalid filename '%s', ignoring.", de->d_name, fn);
-                        continue;
-                }
-
-                _cleanup_free_ char *output = path_join(NETWORK_UNIT_DIRECTORY, fn);
-                if (!output)
-                        return log_oom();
-
-                r = copy_file_at(
-                                credential_dir_fd, de->d_name,
-                                AT_FDCWD, output,
-                                /* open_flags= */ 0,
-                                0644,
-                                /* flags= */ 0);
-                if (r < 0)
-                        RET_GATHER(ret, log_warning_errno(r, "Failed to copy credential %s → file %s: %m", de->d_name, output));
-                else
-                        log_info("Installed %s from credential.", output);
-        }
-
-        return ret;
-}
-
 static int help(void) {
         printf("%s [OPTIONS...] [-- KERNEL_CMDLINE]\n"
                "  -h --help                       Show this help\n"
@@ -304,7 +232,13 @@ static int run(int argc, char *argv[]) {
                 return log_warning_errno(r, "Failed to merge multiple command line options: %m");
 
         RET_GATHER(ret, context_save(&context));
-        RET_GATHER(ret, pick_up_credentials());
+
+        static const PickUpCredential table[] = {
+                { "network.link.",    NETWORK_UNIT_DIRECTORY, ".link"    },
+                { "network.netdev.",  NETWORK_UNIT_DIRECTORY, ".netdev"  },
+                { "network.network.", NETWORK_UNIT_DIRECTORY, ".network" },
+        };
+        RET_GATHER(ret, pick_up_credentials(table, ELEMENTSOF(table)));
 
         return ret;
 }
index ba8aee335541aab8add01185327f622b6b5bc8a8..bd2af6d172477df28534fa476871634db3a6d0ca 100644 (file)
@@ -12,6 +12,7 @@
 #include "capability-util.h"
 #include "chattr-util.h"
 #include "constants.h"
+#include "copy.h"
 #include "creds-util.h"
 #include "efi-api.h"
 #include "env-util.h"
 #include "fs-util.h"
 #include "io-util.h"
 #include "memory-util.h"
-#include "mkdir.h"
+#include "mkdir-label.h"
 #include "openssl-util.h"
 #include "parse-util.h"
 #include "path-util.h"
 #include "random-util.h"
+#include "recurse-dir.h"
 #include "sparse-endian.h"
 #include "stat-util.h"
 #include "tmpfile-util.h"
@@ -1652,3 +1654,90 @@ int ipc_decrypt_credential(const char *validate_name, usec_t validate_timestamp,
 
         return 0;
 }
+
+static int pick_up_credential_one(
+                int credential_dir_fd,
+                const char *credential_name,
+                const PickUpCredential *table_entry) {
+
+        _cleanup_free_ char *fn = NULL, *target_path = NULL;
+        const char *e;
+        int r;
+
+        assert(credential_dir_fd >= 0);
+        assert(credential_name);
+        assert(table_entry);
+
+        e = startswith(credential_name, table_entry->credential_prefix);
+        if (!e)
+                return 0; /* unmatched */
+
+        fn = strjoin(e, table_entry->filename_suffix);
+        if (!fn)
+                return log_oom();
+
+        if (!filename_is_valid(fn))
+                return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
+                                         "Passed credential '%s' would result in invalid filename '%s'.",
+                                         credential_name, fn);
+
+        r = mkdir_p_label(table_entry->target_dir, 0755);
+        if (r < 0)
+                return log_warning_errno(r, "Failed to create '%s': %m", table_entry->target_dir);
+
+        target_path = path_join(table_entry->target_dir, fn);
+        if (!target_path)
+                return log_oom();
+
+        r = copy_file_at(
+                        credential_dir_fd, credential_name,
+                        AT_FDCWD, target_path,
+                        /* open_flags= */ 0,
+                        0644,
+                        /* flags= */ 0);
+        if (r < 0)
+                return log_warning_errno(r, "Failed to copy credential %s → file %s: %m",
+                                         credential_name, target_path);
+
+        log_info("Installed %s from credential.", target_path);
+        return 1; /* done */
+}
+
+int pick_up_credentials(const PickUpCredential *table, size_t n_table_entry) {
+        _cleanup_close_ int credential_dir_fd = -EBADF;
+        int r, ret = 0;
+
+        assert(table);
+        assert(n_table_entry > 0);
+
+        credential_dir_fd = open_credentials_dir();
+        if (IN_SET(credential_dir_fd, -ENXIO, -ENOENT)) {
+                /* Credential env var not set, or dir doesn't exist. */
+                log_debug("No credentials found.");
+                return 0;
+        }
+        if (credential_dir_fd < 0)
+                return log_error_errno(credential_dir_fd, "Failed to open credentials directory: %m");
+
+        _cleanup_free_ DirectoryEntries *des = NULL;
+        r = readdir_all(credential_dir_fd, RECURSE_DIR_SORT|RECURSE_DIR_IGNORE_DOT|RECURSE_DIR_ENSURE_TYPE, &des);
+        if (r < 0)
+                return log_error_errno(r, "Failed to enumerate credentials: %m");
+
+        FOREACH_ARRAY(i, des->entries, des->n_entries) {
+                struct dirent *de = *i;
+
+                if (de->d_type != DT_REG)
+                        continue;
+
+                FOREACH_ARRAY(t, table, n_table_entry) {
+                        r = pick_up_credential_one(credential_dir_fd, de->d_name, t);
+                        if (r != 0) {
+                                RET_GATHER(ret, r);
+                                break; /* Done, or failed. Let's move to the next credential. */
+                        }
+                }
+        }
+
+        return ret;
+}
index e56292c79588617b1253876fc1a4f5b3c064c546..b80755b7d7b04a01ef2e4335d63e08fdb703bbb1 100644 (file)
@@ -93,3 +93,11 @@ int decrypt_credential_and_warn(const char *validate_name, usec_t validate_times
 
 int ipc_encrypt_credential(const char *name, usec_t timestamp, usec_t not_after, uid_t uid, const struct iovec *input, CredentialFlags flags, struct iovec *ret);
 int ipc_decrypt_credential(const char *validate_name, usec_t validate_timestamp, uid_t uid, const struct iovec *input, CredentialFlags flags, struct iovec *ret);
+
+typedef struct PickUpCredential {
+        const char *credential_prefix;
+        const char *target_dir;
+        const char *filename_suffix;
+} PickUpCredential;
+
+int pick_up_credentials(const PickUpCredential *table, size_t n_table_entry);