1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #include <errno.h>
4 #include <fcntl.h>
5 #include <unistd.h>
6
7 #include "sd-id128.h"
8
9 #include "alloc-util.h"
10 #include "fd-util.h"
11 #include "hexdecoct.h"
12 #include "hmac.h"
13 #include "id128-util.h"
14 #include "io-util.h"
15 #include "macro.h"
16 #include "missing_syscall.h"
17 #include "random-util.h"
18 #include "user-util.h"
19 #include "util.h"
20
sd_id128_to_string(sd_id128_t id,char s[_SD_ARRAY_STATIC SD_ID128_STRING_MAX])21 _public_ char *sd_id128_to_string(sd_id128_t id, char s[_SD_ARRAY_STATIC SD_ID128_STRING_MAX]) {
22 assert_return(s, NULL);
23
24 for (size_t n = 0; n < 16; n++) {
25 s[n*2] = hexchar(id.bytes[n] >> 4);
26 s[n*2+1] = hexchar(id.bytes[n] & 0xF);
27 }
28
29 s[SD_ID128_STRING_MAX-1] = 0;
30
31 return s;
32 }
33
sd_id128_to_uuid_string(sd_id128_t id,char s[_SD_ARRAY_STATIC SD_ID128_UUID_STRING_MAX])34 _public_ char *sd_id128_to_uuid_string(sd_id128_t id, char s[_SD_ARRAY_STATIC SD_ID128_UUID_STRING_MAX]) {
35 size_t k = 0;
36
37 assert_return(s, NULL);
38
39 /* Similar to sd_id128_to_string() but formats the result as UUID instead of plain hex chars */
40
41 for (size_t n = 0; n < 16; n++) {
42
43 if (IN_SET(n, 4, 6, 8, 10))
44 s[k++] = '-';
45
46 s[k++] = hexchar(id.bytes[n] >> 4);
47 s[k++] = hexchar(id.bytes[n] & 0xF);
48 }
49
50 assert(k == SD_ID128_UUID_STRING_MAX - 1);
51 s[k] = 0;
52
53 return s;
54 }
55
sd_id128_from_string(const char s[],sd_id128_t * ret)56 _public_ int sd_id128_from_string(const char s[], sd_id128_t *ret) {
57 unsigned n, i;
58 sd_id128_t t;
59 bool is_guid = false;
60
61 assert_return(s, -EINVAL);
62
63 for (n = 0, i = 0; n < 16;) {
64 int a, b;
65
66 if (s[i] == '-') {
67 /* Is this a GUID? Then be nice, and skip over
68 * the dashes */
69
70 if (i == 8)
71 is_guid = true;
72 else if (IN_SET(i, 13, 18, 23)) {
73 if (!is_guid)
74 return -EINVAL;
75 } else
76 return -EINVAL;
77
78 i++;
79 continue;
80 }
81
82 a = unhexchar(s[i++]);
83 if (a < 0)
84 return -EINVAL;
85
86 b = unhexchar(s[i++]);
87 if (b < 0)
88 return -EINVAL;
89
90 t.bytes[n++] = (a << 4) | b;
91 }
92
93 if (i != (is_guid ? 36 : 32))
94 return -EINVAL;
95
96 if (s[i] != 0)
97 return -EINVAL;
98
99 if (ret)
100 *ret = t;
101 return 0;
102 }
103
sd_id128_get_machine(sd_id128_t * ret)104 _public_ int sd_id128_get_machine(sd_id128_t *ret) {
105 static thread_local sd_id128_t saved_machine_id = {};
106 int r;
107
108 assert_return(ret, -EINVAL);
109
110 if (sd_id128_is_null(saved_machine_id)) {
111 r = id128_read("/etc/machine-id", ID128_PLAIN, &saved_machine_id);
112 if (r < 0)
113 return r;
114
115 if (sd_id128_is_null(saved_machine_id))
116 return -ENOMEDIUM;
117 }
118
119 *ret = saved_machine_id;
120 return 0;
121 }
122
sd_id128_get_boot(sd_id128_t * ret)123 _public_ int sd_id128_get_boot(sd_id128_t *ret) {
124 static thread_local sd_id128_t saved_boot_id = {};
125 int r;
126
127 assert_return(ret, -EINVAL);
128
129 if (sd_id128_is_null(saved_boot_id)) {
130 r = id128_read("/proc/sys/kernel/random/boot_id", ID128_UUID, &saved_boot_id);
131 if (r < 0)
132 return r;
133 }
134
135 *ret = saved_boot_id;
136 return 0;
137 }
138
get_invocation_from_keyring(sd_id128_t * ret)139 static int get_invocation_from_keyring(sd_id128_t *ret) {
140 _cleanup_free_ char *description = NULL;
141 char *d, *p, *g, *u, *e;
142 unsigned long perms;
143 key_serial_t key;
144 size_t sz = 256;
145 uid_t uid;
146 gid_t gid;
147 int r, c;
148
149 #define MAX_PERMS ((unsigned long) (KEY_POS_VIEW|KEY_POS_READ|KEY_POS_SEARCH| \
150 KEY_USR_VIEW|KEY_USR_READ|KEY_USR_SEARCH))
151
152 assert(ret);
153
154 key = request_key("user", "invocation_id", NULL, 0);
155 if (key == -1) {
156 /* Keyring support not available? No invocation key stored? */
157 if (IN_SET(errno, ENOSYS, ENOKEY))
158 return -ENXIO;
159
160 return -errno;
161 }
162
163 for (;;) {
164 description = new(char, sz);
165 if (!description)
166 return -ENOMEM;
167
168 c = keyctl(KEYCTL_DESCRIBE, key, (unsigned long) description, sz, 0);
169 if (c < 0)
170 return -errno;
171
172 if ((size_t) c <= sz)
173 break;
174
175 sz = c;
176 free(description);
177 }
178
179 /* The kernel returns a final NUL in the string, verify that. */
180 assert(description[c-1] == 0);
181
182 /* Chop off the final description string */
183 d = strrchr(description, ';');
184 if (!d)
185 return -EIO;
186 *d = 0;
187
188 /* Look for the permissions */
189 p = strrchr(description, ';');
190 if (!p)
191 return -EIO;
192
193 errno = 0;
194 perms = strtoul(p + 1, &e, 16);
195 if (errno > 0)
196 return -errno;
197 if (e == p + 1) /* Read at least one character */
198 return -EIO;
199 if (e != d) /* Must reached the end */
200 return -EIO;
201
202 if ((perms & ~MAX_PERMS) != 0)
203 return -EPERM;
204
205 *p = 0;
206
207 /* Look for the group ID */
208 g = strrchr(description, ';');
209 if (!g)
210 return -EIO;
211 r = parse_gid(g + 1, &gid);
212 if (r < 0)
213 return r;
214 if (gid != 0)
215 return -EPERM;
216 *g = 0;
217
218 /* Look for the user ID */
219 u = strrchr(description, ';');
220 if (!u)
221 return -EIO;
222 r = parse_uid(u + 1, &uid);
223 if (r < 0)
224 return r;
225 if (uid != 0)
226 return -EPERM;
227
228 c = keyctl(KEYCTL_READ, key, (unsigned long) ret, sizeof(sd_id128_t), 0);
229 if (c < 0)
230 return -errno;
231 if (c != sizeof(sd_id128_t))
232 return -EIO;
233
234 return 0;
235 }
236
get_invocation_from_environment(sd_id128_t * ret)237 static int get_invocation_from_environment(sd_id128_t *ret) {
238 const char *e;
239
240 assert(ret);
241
242 e = secure_getenv("INVOCATION_ID");
243 if (!e)
244 return -ENXIO;
245
246 return sd_id128_from_string(e, ret);
247 }
248
sd_id128_get_invocation(sd_id128_t * ret)249 _public_ int sd_id128_get_invocation(sd_id128_t *ret) {
250 static thread_local sd_id128_t saved_invocation_id = {};
251 int r;
252
253 assert_return(ret, -EINVAL);
254
255 if (sd_id128_is_null(saved_invocation_id)) {
256 /* We first check the environment. The environment variable is primarily relevant for user
257 * services, and sufficiently safe as long as no privilege boundary is involved. */
258 r = get_invocation_from_environment(&saved_invocation_id);
259 if (r < 0 && r != -ENXIO)
260 return r;
261
262 /* The kernel keyring is relevant for system services (as for user services we don't store
263 * the invocation ID in the keyring, as there'd be no trust benefit in that). */
264 r = get_invocation_from_keyring(&saved_invocation_id);
265 if (r < 0)
266 return r;
267 }
268
269 *ret = saved_invocation_id;
270 return 0;
271 }
272
sd_id128_randomize(sd_id128_t * ret)273 _public_ int sd_id128_randomize(sd_id128_t *ret) {
274 sd_id128_t t;
275 int r;
276
277 assert_return(ret, -EINVAL);
278
279 r = genuine_random_bytes(&t, sizeof(t), 0);
280 if (r < 0)
281 return r;
282
283 /* Turn this into a valid v4 UUID, to be nice. Note that we
284 * only guarantee this for newly generated UUIDs, not for
285 * pre-existing ones. */
286
287 *ret = id128_make_v4_uuid(t);
288 return 0;
289 }
290
get_app_specific(sd_id128_t base,sd_id128_t app_id,sd_id128_t * ret)291 static int get_app_specific(sd_id128_t base, sd_id128_t app_id, sd_id128_t *ret) {
292 uint8_t hmac[SHA256_DIGEST_SIZE];
293 sd_id128_t result;
294
295 assert(ret);
296
297 hmac_sha256(&base, sizeof(base), &app_id, sizeof(app_id), hmac);
298
299 /* Take only the first half. */
300 memcpy(&result, hmac, MIN(sizeof(hmac), sizeof(result)));
301
302 *ret = id128_make_v4_uuid(result);
303 return 0;
304 }
305
sd_id128_get_machine_app_specific(sd_id128_t app_id,sd_id128_t * ret)306 _public_ int sd_id128_get_machine_app_specific(sd_id128_t app_id, sd_id128_t *ret) {
307 sd_id128_t id;
308 int r;
309
310 assert_return(ret, -EINVAL);
311
312 r = sd_id128_get_machine(&id);
313 if (r < 0)
314 return r;
315
316 return get_app_specific(id, app_id, ret);
317 }
318
sd_id128_get_boot_app_specific(sd_id128_t app_id,sd_id128_t * ret)319 _public_ int sd_id128_get_boot_app_specific(sd_id128_t app_id, sd_id128_t *ret) {
320 sd_id128_t id;
321 int r;
322
323 assert_return(ret, -EINVAL);
324
325 r = sd_id128_get_boot(&id);
326 if (r < 0)
327 return r;
328
329 return get_app_specific(id, app_id, ret);
330 }
331