1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
3 #include "alloc-util.h"
4 #include "creds-util.h"
6 #include "extract-word.h"
9 #include "memory-util.h"
10 #include "machine-credential.h"
11 #include "path-util.h"
12 #include "string-util-fundamental.h"
14 static void machine_credential_done(MachineCredential
*cred
) {
17 cred
->id
= mfree(cred
->id
);
18 cred
->data
= erase_and_free(cred
->data
);
22 void machine_credential_context_done(MachineCredentialContext
*ctx
) {
25 FOREACH_ARRAY(cred
, ctx
->credentials
, ctx
->n_credentials
)
26 machine_credential_done(cred
);
28 free(ctx
->credentials
);
31 bool machine_credentials_contains(const MachineCredentialContext
*ctx
, const char *id
) {
35 FOREACH_ARRAY(cred
, ctx
->credentials
, ctx
->n_credentials
)
36 if (streq(cred
->id
, id
))
42 int machine_credential_set(MachineCredentialContext
*ctx
, const char *cred_str
) {
43 _cleanup_(machine_credential_done
) MachineCredential cred
= {};
49 const char *p
= ASSERT_PTR(cred_str
);
51 r
= extract_first_word(&p
, &cred
.id
, ":", EXTRACT_DONT_COALESCE_SEPARATORS
);
53 return log_error_errno(r
, "Failed to parse --set-credential= parameter: %m");
55 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
56 "Missing value for --set-credential=: %s", cred_str
);
58 if (!credential_name_valid(cred
.id
))
59 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "Credential name is not valid: %s", cred
.id
);
61 if (machine_credentials_contains(ctx
, cred
.id
))
62 return log_error_errno(SYNTHETIC_ERRNO(EEXIST
), "Duplicate credential '%s', refusing.", cred
.id
);
64 l
= cunescape(p
, UNESCAPE_ACCEPT_NUL
, &cred
.data
);
66 return log_error_errno(l
, "Failed to unescape credential data: %s", p
);
69 if (!GREEDY_REALLOC(ctx
->credentials
, ctx
->n_credentials
+ 1))
72 ctx
->credentials
[ctx
->n_credentials
++] = TAKE_STRUCT(cred
);
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
;
85 const char *p
= ASSERT_PTR(cred_path
);
87 r
= extract_first_word(&p
, &cred
.id
, ":", EXTRACT_DONT_COALESCE_SEPARATORS
);
89 return log_error_errno(r
, "Failed to parse --load-credential= parameter: %m");
91 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "Missing value for --load-credential=: %s", cred_path
);
93 if (!credential_name_valid(cred
.id
))
94 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "Credential name is not valid: %s", cred
.id
);
96 if (machine_credentials_contains(ctx
, cred
.id
))
97 return log_error_errno(SYNTHETIC_ERRNO(EEXIST
), "Duplicate credential '%s', refusing.", cred
.id
);
99 if (is_path(p
) && path_is_valid(p
))
100 flags
|= READ_FULL_FILE_CONNECT_SOCKET
;
101 else if (credential_name_valid(p
)) {
104 r
= get_credentials_dir(&e
);
106 return log_error_errno(r
,
107 "Credential not available (no credentials passed at all): %s", cred
.id
);
109 path_alloc
= path_join(e
, p
);
115 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
116 "Credential source appears to be neither a valid path nor a credential name: %s", p
);
118 r
= read_full_file_full(AT_FDCWD
, p
, UINT64_MAX
, SIZE_MAX
,
121 &cred
.data
, &cred
.size
);
123 return log_error_errno(r
, "Failed to read credential '%s': %m", p
);
125 if (!GREEDY_REALLOC(ctx
->credentials
, ctx
->n_credentials
+ 1))
128 ctx
->credentials
[ctx
->n_credentials
++] = TAKE_STRUCT(cred
);