From 6c15a28454c80a4d777b1b59826893ab5901b75d Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 5 Apr 2024 12:21:30 +0900 Subject: [PATCH] creds-util: move pick_up_credentials() from network-generator The function is quite general, and can be used at other places. Let's move to our shared library. --- src/network/generator/main.c | 80 +++---------------------------- src/shared/creds-util.c | 91 +++++++++++++++++++++++++++++++++++- src/shared/creds-util.h | 8 ++++ 3 files changed, 105 insertions(+), 74 deletions(-) diff --git a/src/network/generator/main.c b/src/network/generator/main.c index 0455d5f5c3f..5a26a54fc56 100644 --- a/src/network/generator/main.c +++ b/src/network/generator/main.c @@ -3,7 +3,6 @@ #include #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; } diff --git a/src/shared/creds-util.c b/src/shared/creds-util.c index ba8aee33554..bd2af6d1724 100644 --- a/src/shared/creds-util.c +++ b/src/shared/creds-util.c @@ -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" @@ -21,11 +22,12 @@ #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; +} diff --git a/src/shared/creds-util.h b/src/shared/creds-util.h index e56292c7958..b80755b7d7b 100644 --- a/src/shared/creds-util.h +++ b/src/shared/creds-util.h @@ -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); -- 2.39.2