#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"
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)) {
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)
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);
}