1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
9 #include "alloc-util.h"
11 #include "hexdecoct.h"
12 #include "id128-util.h"
16 #include "missing_syscall.h"
17 #include "random-util.h"
18 #include "user-util.h"
21 _public_
char *sd_id128_to_string(sd_id128_t id
, char s
[_SD_ARRAY_STATIC SD_ID128_STRING_MAX
]) {
24 assert_return(s
, NULL
);
26 for (n
= 0; n
< 16; n
++) {
27 s
[n
*2] = hexchar(id
.bytes
[n
] >> 4);
28 s
[n
*2+1] = hexchar(id
.bytes
[n
] & 0xF);
36 _public_
int sd_id128_from_string(const char s
[], sd_id128_t
*ret
) {
41 assert_return(s
, -EINVAL
);
43 for (n
= 0, i
= 0; n
< 16;) {
47 /* Is this a GUID? Then be nice, and skip over
52 else if (IN_SET(i
, 13, 18, 23)) {
62 a
= unhexchar(s
[i
++]);
66 b
= unhexchar(s
[i
++]);
70 t
.bytes
[n
++] = (a
<< 4) | b
;
73 if (i
!= (is_guid
? 36 : 32))
84 _public_
int sd_id128_get_machine(sd_id128_t
*ret
) {
85 static thread_local sd_id128_t saved_machine_id
= {};
88 assert_return(ret
, -EINVAL
);
90 if (sd_id128_is_null(saved_machine_id
)) {
91 r
= id128_read("/etc/machine-id", ID128_PLAIN
, &saved_machine_id
);
95 if (sd_id128_is_null(saved_machine_id
))
99 *ret
= saved_machine_id
;
103 _public_
int sd_id128_get_boot(sd_id128_t
*ret
) {
104 static thread_local sd_id128_t saved_boot_id
= {};
107 assert_return(ret
, -EINVAL
);
109 if (sd_id128_is_null(saved_boot_id
)) {
110 r
= id128_read("/proc/sys/kernel/random/boot_id", ID128_UUID
, &saved_boot_id
);
115 *ret
= saved_boot_id
;
119 static int get_invocation_from_keyring(sd_id128_t
*ret
) {
120 _cleanup_free_
char *description
= NULL
;
121 char *d
, *p
, *g
, *u
, *e
;
129 #define MAX_PERMS ((unsigned long) (KEY_POS_VIEW|KEY_POS_READ|KEY_POS_SEARCH| \
130 KEY_USR_VIEW|KEY_USR_READ|KEY_USR_SEARCH))
134 key
= request_key("user", "invocation_id", NULL
, 0);
136 /* Keyring support not available? No invocation key stored? */
137 if (IN_SET(errno
, ENOSYS
, ENOKEY
))
144 description
= new(char, sz
);
148 c
= keyctl(KEYCTL_DESCRIBE
, key
, (unsigned long) description
, sz
, 0);
152 if ((size_t) c
<= sz
)
159 /* The kernel returns a final NUL in the string, verify that. */
160 assert(description
[c
-1] == 0);
162 /* Chop off the final description string */
163 d
= strrchr(description
, ';');
168 /* Look for the permissions */
169 p
= strrchr(description
, ';');
174 perms
= strtoul(p
+ 1, &e
, 16);
177 if (e
== p
+ 1) /* Read at least one character */
179 if (e
!= d
) /* Must reached the end */
182 if ((perms
& ~MAX_PERMS
) != 0)
187 /* Look for the group ID */
188 g
= strrchr(description
, ';');
191 r
= parse_gid(g
+ 1, &gid
);
198 /* Look for the user ID */
199 u
= strrchr(description
, ';');
202 r
= parse_uid(u
+ 1, &uid
);
208 c
= keyctl(KEYCTL_READ
, key
, (unsigned long) ret
, sizeof(sd_id128_t
), 0);
211 if (c
!= sizeof(sd_id128_t
))
217 static int get_invocation_from_environment(sd_id128_t
*ret
) {
222 e
= secure_getenv("INVOCATION_ID");
226 return sd_id128_from_string(e
, ret
);
229 _public_
int sd_id128_get_invocation(sd_id128_t
*ret
) {
230 static thread_local sd_id128_t saved_invocation_id
= {};
233 assert_return(ret
, -EINVAL
);
235 if (sd_id128_is_null(saved_invocation_id
)) {
236 /* We first check the environment. The environment variable is primarily relevant for user
237 * services, and sufficiently safe as long as no privilege boundary is involved. */
238 r
= get_invocation_from_environment(&saved_invocation_id
);
239 if (r
< 0 && r
!= -ENXIO
)
242 /* The kernel keyring is relevant for system services (as for user services we don't store
243 * the invocation ID in the keyring, as there'd be no trust benefit in that). */
244 r
= get_invocation_from_keyring(&saved_invocation_id
);
249 *ret
= saved_invocation_id
;
253 _public_
int sd_id128_randomize(sd_id128_t
*ret
) {
257 assert_return(ret
, -EINVAL
);
259 /* We allow usage if x86-64 RDRAND here. It might not be trusted enough for keeping secrets, but it should be
261 r
= genuine_random_bytes(&t
, sizeof t
, RANDOM_ALLOW_RDRAND
);
265 /* Turn this into a valid v4 UUID, to be nice. Note that we
266 * only guarantee this for newly generated UUIDs, not for
267 * pre-existing ones. */
269 *ret
= id128_make_v4_uuid(t
);
273 static int get_app_specific(sd_id128_t base
, sd_id128_t app_id
, sd_id128_t
*ret
) {
274 _cleanup_(khash_unrefp
) khash
*h
= NULL
;
281 r
= khash_new_with_key(&h
, "hmac(sha256)", &base
, sizeof(base
));
285 r
= khash_put(h
, &app_id
, sizeof(app_id
));
289 r
= khash_digest_data(h
, &p
);
293 /* We chop off the trailing 16 bytes */
294 memcpy(&result
, p
, MIN(khash_get_size(h
), sizeof(result
)));
296 *ret
= id128_make_v4_uuid(result
);
300 _public_
int sd_id128_get_machine_app_specific(sd_id128_t app_id
, sd_id128_t
*ret
) {
304 assert_return(ret
, -EINVAL
);
306 r
= sd_id128_get_machine(&id
);
310 return get_app_specific(id
, app_id
, ret
);
313 _public_
int sd_id128_get_boot_app_specific(sd_id128_t app_id
, sd_id128_t
*ret
) {
317 assert_return(ret
, -EINVAL
);
319 r
= sd_id128_get_boot(&id
);
323 return get_app_specific(id
, app_id
, ret
);