]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
machine-credential: add low-level machine_credential_add() as common back-end for... 38982/head
authorLennart Poettering <lennart@poettering.net>
Thu, 18 Sep 2025 07:20:00 +0000 (09:20 +0200)
committerLennart Poettering <lennart@poettering.net>
Fri, 19 Sep 2025 15:08:03 +0000 (17:08 +0200)
src/shared/machine-credential.c
src/shared/machine-credential.h

index 407bd18bff2eb77fe654c8e714e68fc8b8fe1d49..ace10b43dba6004e90bfcd73ffb385608e1b0e64 100644 (file)
@@ -5,6 +5,7 @@
 #include "escape.h"
 #include "extract-word.h"
 #include "fileio.h"
+#include "iovec-util.h"
 #include "log.h"
 #include "machine-credential.h"
 #include "memory-util.h"
@@ -39,63 +40,107 @@ MachineCredential* machine_credential_find(MachineCredentialContext *ctx, const
         return NULL;
 }
 
-int machine_credential_set(MachineCredentialContext *ctx, const char *cred_str) {
+int machine_credential_add(
+                MachineCredentialContext *ctx,
+                const char *id,
+                const char *value,
+                size_t size) {
+
+        assert(ctx);
+        assert(id);
+        assert(value || size == 0);
+
+        if (!credential_name_valid(id))
+                return -EINVAL;
+
+        if (machine_credential_find(ctx, id))
+                return -EEXIST;
+
+        if (size == SIZE_MAX)
+                size = strlen_ptr(value);
+
         _cleanup_(machine_credential_done) MachineCredential cred = {};
-        ssize_t l;
+        cred.id = strdup(id);
+        if (!cred.id)
+                return -ENOMEM;
+
+        cred.data = memdup(value, size);
+        if (!cred.data)
+                return -ENOMEM;
+
+        cred.size = size;
+
+        if (!GREEDY_REALLOC(ctx->credentials, ctx->n_credentials + 1))
+                return -ENOMEM;
+
+        ctx->credentials[ctx->n_credentials++] = TAKE_STRUCT(cred);
+        return 0;
+}
+
+static int machine_credential_add_and_log(
+                MachineCredentialContext *ctx,
+                const char *id,
+                const char *value,
+                size_t size) {
+
         int r;
 
         assert(ctx);
+        assert(id);
+        assert(value || size == 0);
+
+        r = machine_credential_add(ctx, id, value, size);
+        if (r == -EEXIST)
+                return log_error_errno(r, "Duplicated credential '%s', refusing.", id);
+        if (r == -EINVAL)
+                return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Credential name is not valid: %s", id);
+        if (r == -ENOMEM)
+                return log_oom();
+        if (r < 0)
+                return log_error_errno(r, "Failed to add credential '%s': %m", id);
 
-        const char *p = ASSERT_PTR(cred_str);
+        return 0;
+}
 
-        r = extract_first_word(&p, &cred.id, ":", EXTRACT_DONT_COALESCE_SEPARATORS);
+
+int machine_credential_set(MachineCredentialContext *ctx, const char *cred_str) {
+        int r;
+
+        assert(ctx);
+
+        const char *p = ASSERT_PTR(cred_str);
+        _cleanup_free_ char *id = NULL;
+        r = extract_first_word(&p, &id, ":", EXTRACT_DONT_COALESCE_SEPARATORS);
         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_str);
 
-        if (!credential_name_valid(cred.id))
-                return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Credential name is not valid: %s", cred.id);
-
-        if (machine_credential_find(ctx, cred.id))
-                return log_error_errno(SYNTHETIC_ERRNO(EEXIST), "Duplicate credential '%s', refusing.", cred.id);
-
-        l = cunescape(p, UNESCAPE_ACCEPT_NUL, &cred.data);
+        _cleanup_free_ char *data = NULL;
+        ssize_t l;
+        l = cunescape(p, UNESCAPE_ACCEPT_NUL, &data);
         if (l < 0)
                 return log_error_errno(l, "Failed to unescape credential data: %s", p);
-        cred.size = l;
 
-        if (!GREEDY_REALLOC(ctx->credentials, ctx->n_credentials + 1))
-                return log_oom();
-
-        ctx->credentials[ctx->n_credentials++] = TAKE_STRUCT(cred);
-
-        return 0;
+        return machine_credential_add_and_log(ctx, id, data, l);
 }
 
 int machine_credential_load(MachineCredentialContext *ctx, const char *cred_path) {
-        _cleanup_(machine_credential_done) MachineCredential cred = {};
-        _cleanup_free_ char *path_alloc = NULL;
-        ReadFullFileFlags flags = READ_FULL_FILE_SECURE;
         int r;
 
         assert(ctx);
 
         const char *p = ASSERT_PTR(cred_path);
-
-        r = extract_first_word(&p, &cred.id, ":", EXTRACT_DONT_COALESCE_SEPARATORS);
+        _cleanup_free_ char *id = NULL;
+        r = extract_first_word(&p, &id, ":", EXTRACT_DONT_COALESCE_SEPARATORS);
         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(cred.id))
-                return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Credential name is not valid: %s", cred.id);
-
-        if (machine_credential_find(ctx, cred.id))
-                return log_error_errno(SYNTHETIC_ERRNO(EEXIST), "Duplicate credential '%s', refusing.", cred.id);
-
+        ReadFullFileFlags flags = READ_FULL_FILE_SECURE;
+        _cleanup_free_ char *path_alloc = NULL;
         if (is_path(p) && path_is_valid(p))
                 flags |= READ_FULL_FILE_CONNECT_SOCKET;
         else if (credential_name_valid(p)) {
@@ -103,8 +148,7 @@ int machine_credential_load(MachineCredentialContext *ctx, const char *cred_path
 
                 r = get_credentials_dir(&e);
                 if (r < 0)
-                        return log_error_errno(r,
-                                               "Credential not available (no credentials passed at all): %s", cred.id);
+                        return log_error_errno(r, "Credential not available (no credentials passed at all): %s", p);
 
                 path_alloc = path_join(e, p);
                 if (!path_alloc)
@@ -115,17 +159,16 @@ int machine_credential_load(MachineCredentialContext *ctx, const char *cred_path
                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
                                        "Credential source appears to be neither a valid path nor a credential name: %s", p);
 
-        r = read_full_file_full(AT_FDCWD, p, UINT64_MAX, SIZE_MAX,
-                                flags,
-                                NULL,
-                                &cred.data, &cred.size);
+        _cleanup_(iovec_done_erase) struct iovec iov = {};
+        r = read_full_file_full(
+                        AT_FDCWD, p,
+                        /* offset= */ UINT64_MAX,
+                        /* size= */ SIZE_MAX,
+                        flags,
+                        /* bind_name= */ NULL,
+                        (char**) &iov.iov_base, &iov.iov_len);
         if (r < 0)
                 return log_error_errno(r, "Failed to read credential '%s': %m", p);
 
-        if (!GREEDY_REALLOC(ctx->credentials, ctx->n_credentials + 1))
-                return log_oom();
-
-        ctx->credentials[ctx->n_credentials++] = TAKE_STRUCT(cred);
-
-        return 0;
+        return machine_credential_add_and_log(ctx, id, iov.iov_base, iov.iov_len);
 }
index 1b5f4fa1121f97d890b2f2f08e9672ac46aa94c5..244ebd6192a5bcbb41f482a93811c0b3c8fc811a 100644 (file)
@@ -18,5 +18,6 @@ void machine_credential_context_done(MachineCredentialContext *ctx);
 
 MachineCredential* machine_credential_find(MachineCredentialContext *ctx, const char *id);
 
+int machine_credential_add(MachineCredentialContext *ctx, const char *id, const char *value, size_t size);
 int machine_credential_set(MachineCredentialContext *ctx, const char *cred_str);
 int machine_credential_load(MachineCredentialContext *ctx, const char *cred_path);