]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/shared/machine-credential.c
build(deps): bump pkg/arch from `b13e94a` to `b578e90`
[thirdparty/systemd.git] / src / shared / machine-credential.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #include "alloc-util.h"
4 #include "creds-util.h"
5 #include "escape.h"
6 #include "extract-word.h"
7 #include "fileio.h"
8 #include "macro.h"
9 #include "memory-util.h"
10 #include "machine-credential.h"
11 #include "path-util.h"
12 #include "string-util-fundamental.h"
13
14 static void machine_credential_done(MachineCredential *cred) {
15 assert(cred);
16
17 cred->id = mfree(cred->id);
18 cred->data = erase_and_free(cred->data);
19 cred->size = 0;
20 }
21
22 void machine_credential_context_done(MachineCredentialContext *ctx) {
23 assert(ctx);
24
25 FOREACH_ARRAY(cred, ctx->credentials, ctx->n_credentials)
26 machine_credential_done(cred);
27
28 free(ctx->credentials);
29 }
30
31 bool machine_credentials_contains(const MachineCredentialContext *ctx, const char *id) {
32 assert(ctx);
33 assert(id);
34
35 FOREACH_ARRAY(cred, ctx->credentials, ctx->n_credentials)
36 if (streq(cred->id, id))
37 return true;
38
39 return false;
40 }
41
42 int machine_credential_set(MachineCredentialContext *ctx, const char *cred_str) {
43 _cleanup_(machine_credential_done) MachineCredential cred = {};
44 ssize_t l;
45 int r;
46
47 assert(ctx);
48
49 const char *p = ASSERT_PTR(cred_str);
50
51 r = extract_first_word(&p, &cred.id, ":", EXTRACT_DONT_COALESCE_SEPARATORS);
52 if (r < 0)
53 return log_error_errno(r, "Failed to parse --set-credential= parameter: %m");
54 if (r == 0 || !p)
55 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
56 "Missing value for --set-credential=: %s", cred_str);
57
58 if (!credential_name_valid(cred.id))
59 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Credential name is not valid: %s", cred.id);
60
61 if (machine_credentials_contains(ctx, cred.id))
62 return log_error_errno(SYNTHETIC_ERRNO(EEXIST), "Duplicate credential '%s', refusing.", cred.id);
63
64 l = cunescape(p, UNESCAPE_ACCEPT_NUL, &cred.data);
65 if (l < 0)
66 return log_error_errno(l, "Failed to unescape credential data: %s", p);
67 cred.size = l;
68
69 if (!GREEDY_REALLOC(ctx->credentials, ctx->n_credentials + 1))
70 return log_oom();
71
72 ctx->credentials[ctx->n_credentials++] = TAKE_STRUCT(cred);
73
74 return 0;
75 }
76
77 int machine_credential_load(MachineCredentialContext *ctx, const char *cred_path) {
78 _cleanup_(machine_credential_done) MachineCredential cred = {};
79 _cleanup_free_ char *path_alloc = NULL;
80 ReadFullFileFlags flags = READ_FULL_FILE_SECURE;
81 int r;
82
83 assert(ctx);
84
85 const char *p = ASSERT_PTR(cred_path);
86
87 r = extract_first_word(&p, &cred.id, ":", EXTRACT_DONT_COALESCE_SEPARATORS);
88 if (r < 0)
89 return log_error_errno(r, "Failed to parse --load-credential= parameter: %m");
90 if (r == 0 || !p)
91 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Missing value for --load-credential=: %s", cred_path);
92
93 if (!credential_name_valid(cred.id))
94 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Credential name is not valid: %s", cred.id);
95
96 if (machine_credentials_contains(ctx, cred.id))
97 return log_error_errno(SYNTHETIC_ERRNO(EEXIST), "Duplicate credential '%s', refusing.", cred.id);
98
99 if (is_path(p) && path_is_valid(p))
100 flags |= READ_FULL_FILE_CONNECT_SOCKET;
101 else if (credential_name_valid(p)) {
102 const char *e;
103
104 r = get_credentials_dir(&e);
105 if (r < 0)
106 return log_error_errno(r,
107 "Credential not available (no credentials passed at all): %s", cred.id);
108
109 path_alloc = path_join(e, p);
110 if (!path_alloc)
111 return log_oom();
112
113 p = path_alloc;
114 } else
115 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
116 "Credential source appears to be neither a valid path nor a credential name: %s", p);
117
118 r = read_full_file_full(AT_FDCWD, p, UINT64_MAX, SIZE_MAX,
119 flags,
120 NULL,
121 &cred.data, &cred.size);
122 if (r < 0)
123 return log_error_errno(r, "Failed to read credential '%s': %m", p);
124
125 if (!GREEDY_REALLOC(ctx->credentials, ctx->n_credentials + 1))
126 return log_oom();
127
128 ctx->credentials[ctx->n_credentials++] = TAKE_STRUCT(cred);
129
130 return 0;
131 }