summaryrefslogtreecommitdiffstats
path: root/src/shared/machine-credential.c
blob: 17f7afc4a0fdf8cf0a8186b4f6e9a87a776fe087 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
/* 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;
        ssize_t l;
        int r;
        const char *p = ASSERT_PTR(cred_string);

        assert(credentials && n_credentials);
        assert(*credentials || *n_credentials == 0);

        r = extract_first_word(&p, &word, ":", 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_string);

        if (!credential_name_valid(word))
                return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Credential name is not valid: %s", word);

        FOREACH_ARRAY(cred, *credentials, *n_credentials)
                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);

        if (!GREEDY_REALLOC(*credentials, *n_credentials + 1))
                return log_oom();

        (*credentials)[(*n_credentials)++] = (MachineCredential) {
                .id = TAKE_PTR(word),
                .data = TAKE_PTR(data),
                .size = l,
        };

        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;
        const char *p = ASSERT_PTR(cred_path);
        size_t size;
        int r;

        assert(credentials && n_credentials);
        assert(*credentials || *n_credentials == 0);

        r = extract_first_word(&p, &word, ":", 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(word))
                return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Credential name is not valid: %s", word);

        FOREACH_ARRAY(cred, *credentials, *n_credentials)
                if (streq(cred->id, word))
                        return log_error_errno(SYNTHETIC_ERRNO(EEXIST), "Duplicate credential '%s', refusing.", word);

        if (is_path(p) && path_is_valid(p))
                flags |= READ_FULL_FILE_CONNECT_SOCKET;
        else if (credential_name_valid(p)) {
                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();

                p = j;
        } else
                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,
                                &data, &size);
        if (r < 0)
                return log_error_errno(r, "Failed to read credential '%s': %m", p);

        if (!GREEDY_REALLOC(*credentials, *n_credentials + 1))
                return log_oom();

        (*credentials)[(*n_credentials)++] = (MachineCredential) {
                .id = TAKE_PTR(word),
                .data = TAKE_PTR(data),
                .size = size,
        };

        return 0;
}