From: Sam Leonard Date: Thu, 12 Oct 2023 11:56:08 +0000 (+0100) Subject: nspawn: moved nspawn-creds.[ch] to shared/machine-credential.[ch] X-Git-Tag: v255-rc1~31^2~3 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=e8ac916ec35566cc1daab767ba3fe9449ad25eca;p=thirdparty%2Fsystemd.git nspawn: moved nspawn-creds.[ch] to shared/machine-credential.[ch] This was done in order to allow sharing of this code between systemd-nspawn and systemd-vmspawn. --- diff --git a/src/nspawn/meson.build b/src/nspawn/meson.build index e2605f895bb..2a913b156df 100644 --- a/src/nspawn/meson.build +++ b/src/nspawn/meson.build @@ -3,7 +3,6 @@ libnspawn_core_sources = files( 'nspawn-bind-user.c', 'nspawn-cgroup.c', - 'nspawn-creds.c', 'nspawn-expose-ports.c', 'nspawn-mount.c', 'nspawn-network.c', diff --git a/src/nspawn/nspawn-creds.c b/src/nspawn/nspawn-creds.c deleted file mode 100644 index 0900d8c211e..00000000000 --- a/src/nspawn/nspawn-creds.c +++ /dev/null @@ -1,25 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ - -#include "alloc-util.h" -#include "macro.h" -#include "memory-util.h" -#include "nspawn-creds.h" - -static void credential_free(Credential *cred) { - assert(cred); - - cred->id = mfree(cred->id); - cred->data = erase_and_free(cred->data); - cred->size = 0; -} - -void credential_free_all(Credential *creds, size_t n) { - size_t i; - - assert(creds || n == 0); - - for (i = 0; i < n; i++) - credential_free(creds + i); - - free(creds); -} diff --git a/src/nspawn/nspawn-creds.h b/src/nspawn/nspawn-creds.h deleted file mode 100644 index de0661b204f..00000000000 --- a/src/nspawn/nspawn-creds.h +++ /dev/null @@ -1,12 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -#pragma once - -#include - -typedef struct Credential { - char *id; - void *data; - size_t size; -} Credential; - -void credential_free_all(Credential *creds, size_t n); diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index ca974532839..ed29d9bba93 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -60,6 +60,7 @@ #include "log.h" #include "loop-util.h" #include "loopback-setup.h" +#include "machine-credential.h" #include "macro.h" #include "main-func.h" #include "missing_sched.h" @@ -70,7 +71,6 @@ #include "netlink-util.h" #include "nspawn-bind-user.h" #include "nspawn-cgroup.h" -#include "nspawn-creds.h" #include "nspawn-def.h" #include "nspawn-expose-ports.h" #include "nspawn-mount.h" @@ -229,7 +229,7 @@ static DeviceNode* arg_extra_nodes = NULL; static size_t arg_n_extra_nodes = 0; static char **arg_sysctl = NULL; static ConsoleMode arg_console_mode = _CONSOLE_MODE_INVALID; -static Credential *arg_credentials = NULL; +static MachineCredential *arg_credentials = NULL; static size_t arg_n_credentials = 0; static char **arg_bind_user = NULL; static bool arg_suppress_sync = false; @@ -1567,106 +1567,24 @@ static int parse_argv(int argc, char *argv[]) { arg_pager_flags |= PAGER_DISABLE; break; - case ARG_SET_CREDENTIAL: { - _cleanup_free_ char *word = NULL, *data = NULL; - const char *p = optarg; - Credential *a; - ssize_t l; - - r = extract_first_word(&p, &word, ":", EXTRACT_DONT_COALESCE_SEPARATORS); + case ARG_SET_CREDENTIAL: + r = machine_credential_set(&arg_credentials, &arg_n_credentials, optarg); if (r == -ENOMEM) return log_oom(); if (r < 0) - return log_error_errno(r, "Failed to parse --set-credential= parameter: %m"); - if (r == 0 || !p) - return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Missing value for --set-credential=: %s", optarg); - - if (!credential_name_valid(word)) - return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Credential name is not valid: %s", word); - - for (size_t i = 0; i < arg_n_credentials; i++) - if (streq(arg_credentials[i].id, word)) - return log_error_errno(SYNTHETIC_ERRNO(EEXIST), "Duplicate credential '%s', refusing.", word); - - l = cunescape(p, UNESCAPE_ACCEPT_NUL, &data); - if (l < 0) - return log_error_errno(l, "Failed to unescape credential data: %s", p); - - a = reallocarray(arg_credentials, arg_n_credentials + 1, sizeof(Credential)); - if (!a) - return log_oom(); - - a[arg_n_credentials++] = (Credential) { - .id = TAKE_PTR(word), - .data = TAKE_PTR(data), - .size = l, - }; - - arg_credentials = a; - + return log_error_errno(r, "Failed to set credential from %s: %m", optarg); arg_settings_mask |= SETTING_CREDENTIALS; break; - } - case ARG_LOAD_CREDENTIAL: { - ReadFullFileFlags flags = READ_FULL_FILE_SECURE; - _cleanup_(erase_and_freep) char *data = NULL; - _cleanup_free_ char *word = NULL, *j = NULL; - const char *p = optarg; - Credential *a; - size_t size, i; - - r = extract_first_word(&p, &word, ":", EXTRACT_DONT_COALESCE_SEPARATORS); + case ARG_LOAD_CREDENTIAL: + r = machine_credential_load(&arg_credentials, &arg_n_credentials, optarg); if (r == -ENOMEM) return log_oom(); if (r < 0) - return log_error_errno(r, "Failed to parse --load-credential= parameter: %m"); - if (r == 0 || !p) - return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Missing value for --load-credential=: %s", optarg); - - if (!credential_name_valid(word)) - return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Credential name is not valid: %s", word); - - for (i = 0; i < arg_n_credentials; i++) - if (streq(arg_credentials[i].id, word)) - return log_error_errno(SYNTHETIC_ERRNO(EEXIST), "Duplicate credential '%s', refusing.", word); - - if (path_is_absolute(p)) - flags |= READ_FULL_FILE_CONNECT_SOCKET; - else { - const char *e; - - r = get_credentials_dir(&e); - if (r < 0) - return log_error_errno(r, "Credential not available (no credentials passed at all): %s", word); - - j = path_join(e, p); - if (!j) - return log_oom(); - } - - r = read_full_file_full(AT_FDCWD, j ?: p, UINT64_MAX, SIZE_MAX, - flags, - NULL, - &data, &size); - if (r < 0) - return log_error_errno(r, "Failed to read credential '%s': %m", j ?: p); - - a = reallocarray(arg_credentials, arg_n_credentials + 1, sizeof(Credential)); - if (!a) - return log_oom(); - - a[arg_n_credentials++] = (Credential) { - .id = TAKE_PTR(word), - .data = TAKE_PTR(data), - .size = size, - }; - - arg_credentials = a; + return log_error_errno(r, "Failed to load credential from %s: %m", optarg); arg_settings_mask |= SETTING_CREDENTIALS; break; - } case ARG_BIND_USER: if (!valid_user_group_name(optarg, 0)) @@ -5929,7 +5847,7 @@ finish: expose_port_free_all(arg_expose_ports); rlimit_free_all(arg_rlimit); device_node_array_free(arg_extra_nodes, arg_n_extra_nodes); - credential_free_all(arg_credentials, arg_n_credentials); + machine_credential_free_all(arg_credentials, arg_n_credentials); if (r < 0) return r; diff --git a/src/shared/machine-credential.c b/src/shared/machine-credential.c new file mode 100644 index 00000000000..752bf0da9c5 --- /dev/null +++ b/src/shared/machine-credential.c @@ -0,0 +1,137 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include "alloc-util.h" +#include "creds-util.h" +#include "escape.h" +#include "extract-word.h" +#include "fileio.h" +#include "macro.h" +#include "memory-util.h" +#include "machine-credential.h" +#include "path-util.h" +#include "string-util-fundamental.h" + +static void machine_credential_done(MachineCredential *cred) { + assert(cred); + + cred->id = mfree(cred->id); + cred->data = erase_and_free(cred->data); + cred->size = 0; +} + +void machine_credential_free_all(MachineCredential *creds, size_t n) { + assert(creds || n == 0); + + FOREACH_ARRAY(cred, creds, n) + machine_credential_done(cred); + + free(creds); +} + +int machine_credential_set(MachineCredential **credentials, size_t *n_credentials, const char *cred_string) { + _cleanup_free_ char *word = NULL, *data = NULL; + MachineCredential *creds = *ASSERT_PTR(credentials); + ssize_t l; + size_t n_creds = *ASSERT_PTR(n_credentials); + int r; + const char *p = ASSERT_PTR(cred_string); + + assert(creds || n_creds == 0); + + r = extract_first_word(&p, &word, ":", EXTRACT_DONT_COALESCE_SEPARATORS); + if (r == -ENOMEM) + return r; + if (r < 0) + return log_error_errno(r, "Failed to parse --set-credential= parameter: %m"); + if (r == 0 || !p) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Missing value for --set-credential=: %s", cred_string); + + if (!credential_name_valid(word)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "MachineCredential name is not valid: %s", word); + + FOREACH_ARRAY(cred, creds, n_creds) + if (streq(cred->id, word)) + return log_error_errno(SYNTHETIC_ERRNO(EEXIST), "Duplicate credential '%s', refusing.", word); + + l = cunescape(p, UNESCAPE_ACCEPT_NUL, &data); + if (l < 0) + return log_error_errno(l, "Failed to unescape credential data: %s", p); + + GREEDY_REALLOC(creds, n_creds + 1); + if (!creds) + return -ENOMEM; + + creds[n_creds++] = (MachineCredential) { + .id = TAKE_PTR(word), + .data = TAKE_PTR(data), + .size = l, + }; + + *credentials = creds; + *n_credentials = n_creds; + + return 0; +} + +int machine_credential_load(MachineCredential **credentials, size_t *n_credentials, const char *cred_path) { + ReadFullFileFlags flags = READ_FULL_FILE_SECURE; + _cleanup_(erase_and_freep) char *data = NULL; + _cleanup_free_ char *word = NULL, *j = NULL; + MachineCredential *creds = *ASSERT_PTR(credentials); + size_t size, n_creds = *ASSERT_PTR(n_credentials); + int r; + const char *p = ASSERT_PTR(cred_path); + + assert(creds || n_creds == 0); + + r = extract_first_word(&p, &word, ":", EXTRACT_DONT_COALESCE_SEPARATORS); + if (r == -ENOMEM) + return -ENOMEM; + if (r < 0) + return log_error_errno(r, "Failed to parse --load-credential= parameter: %m"); + if (r == 0 || !p) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Missing value for --load-credential=: %s", cred_path); + + if (!credential_name_valid(word)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "MachineCredential name is not valid: %s", word); + + FOREACH_ARRAY(cred, creds, n_creds) + if (streq(cred->id, word)) + return log_error_errno(SYNTHETIC_ERRNO(EEXIST), "Duplicate credential '%s', refusing.", word); + + if (path_is_absolute(p)) + flags |= READ_FULL_FILE_CONNECT_SOCKET; + else { + const char *e; + + r = get_credentials_dir(&e); + if (r < 0) + return log_error_errno(r, "MachineCredential not available (no credentials passed at all): %s", word); + + j = path_join(e, p); + if (!j) + return -ENOMEM; + } + + r = read_full_file_full(AT_FDCWD, j ?: p, UINT64_MAX, SIZE_MAX, + flags, + NULL, + &data, &size); + if (r < 0) + return log_error_errno(r, "Failed to read credential '%s': %m", j ?: p); + + GREEDY_REALLOC(creds, n_creds + 1); + if (!creds) + return -ENOMEM; + + creds[n_creds++] = (MachineCredential) { + .id = TAKE_PTR(word), + .data = TAKE_PTR(data), + .size = size, + }; + + *credentials = creds; + *n_credentials = n_creds; + + return 0; +} diff --git a/src/shared/machine-credential.h b/src/shared/machine-credential.h new file mode 100644 index 00000000000..c9044a2edcc --- /dev/null +++ b/src/shared/machine-credential.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +#pragma once + +#include + +typedef struct MachineCredential { + char *id; + void *data; + size_t size; +} MachineCredential; + +void machine_credential_free_all(MachineCredential *creds, size_t n); +int machine_credential_set(MachineCredential **credentials, size_t *n_credentials, const char *cred_string); +int machine_credential_load(MachineCredential **credentials, size_t *n_credentials, const char *cred_path); diff --git a/src/shared/meson.build b/src/shared/meson.build index 0ef34d4bc86..67bb0943b76 100644 --- a/src/shared/meson.build +++ b/src/shared/meson.build @@ -111,6 +111,7 @@ shared_sources = files( 'loop-util.c', 'loopback-setup.c', 'lsm-util.c', + 'machine-credential.c', 'machine-id-setup.c', 'machine-pool.c', 'macvlan-util.c',