2 This file is part of systemd.
4 Copyright 2011 Lennart Poettering
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
26 #include "alloc-util.h"
28 #include "hexdecoct.h"
29 #include "id128-util.h"
33 #include "random-util.h"
34 #include "user-util.h"
37 _public_ char *sd_id128_to_string(sd_id128_t id, char s[SD_ID128_STRING_MAX]) {
40 assert_return(s, NULL);
42 for (n = 0; n < 16; n++) {
43 s[n*2] = hexchar(id.bytes[n] >> 4);
44 s[n*2+1] = hexchar(id.bytes[n] & 0xF);
52 _public_ int sd_id128_from_string(const char s[], sd_id128_t *ret) {
57 assert_return(s, -EINVAL);
59 for (n = 0, i = 0; n < 16;) {
63 /* Is this a GUID? Then be nice, and skip over
68 else if (i == 13 || i == 18 || i == 23) {
78 a = unhexchar(s[i++]);
82 b = unhexchar(s[i++]);
86 t.bytes[n++] = (a << 4) | b;
89 if (i != (is_guid ? 36 : 32))
100 _public_ int sd_id128_get_machine(sd_id128_t *ret) {
101 static thread_local sd_id128_t saved_machine_id = {};
104 assert_return(ret, -EINVAL);
106 if (sd_id128_is_null(saved_machine_id)) {
107 r = id128_read("/etc/machine-id", ID128_PLAIN, &saved_machine_id);
111 if (sd_id128_is_null(saved_machine_id))
115 *ret = saved_machine_id;
119 _public_ int sd_id128_get_boot(sd_id128_t *ret) {
120 static thread_local sd_id128_t saved_boot_id = {};
123 assert_return(ret, -EINVAL);
125 if (sd_id128_is_null(saved_boot_id)) {
126 r = id128_read("/proc/sys/kernel/random/boot_id", ID128_UUID, &saved_boot_id);
131 *ret = saved_boot_id;
135 static int get_invocation_from_keyring(sd_id128_t *ret) {
137 _cleanup_free_ char *description = NULL;
138 char *d, *p, *g, *u, *e;
146 #define MAX_PERMS ((unsigned long) (KEY_POS_VIEW|KEY_POS_READ|KEY_POS_SEARCH| \
147 KEY_USR_VIEW|KEY_USR_READ|KEY_USR_SEARCH))
151 key = request_key("user", "invocation_id", NULL, 0);
153 /* Keyring support not available? No invocation key stored? */
154 if (IN_SET(errno, ENOSYS, ENOKEY))
161 description = new(char, sz);
165 c = keyctl(KEYCTL_DESCRIBE, key, (unsigned long) description, sz, 0);
169 if ((size_t) c <= sz)
176 /* The kernel returns a final NUL in the string, verify that. */
177 assert(description[c-1] == 0);
179 /* Chop off the final description string */
180 d = strrchr(description, ';');
185 /* Look for the permissions */
186 p = strrchr(description, ';');
191 perms = strtoul(p + 1, &e, 16);
194 if (e == p + 1) /* Read at least one character */
196 if (e != d) /* Must reached the end */
199 if ((perms & ~MAX_PERMS) != 0)
204 /* Look for the group ID */
205 g = strrchr(description, ';');
208 r = parse_gid(g + 1, &gid);
215 /* Look for the user ID */
216 u = strrchr(description, ';');
219 r = parse_uid(u + 1, &uid);
225 c = keyctl(KEYCTL_READ, key, (unsigned long) ret, sizeof(sd_id128_t), 0);
228 if (c != sizeof(sd_id128_t))
234 _public_ int sd_id128_get_invocation(sd_id128_t *ret) {
235 static thread_local sd_id128_t saved_invocation_id = {};
238 assert_return(ret, -EINVAL);
240 if (sd_id128_is_null(saved_invocation_id)) {
242 /* We first try to read the invocation ID from the kernel keyring. This has the benefit that it is not
243 * fakeable by unprivileged code. If the information is not available in the keyring, we use
244 * $INVOCATION_ID but ignore the data if our process was called by less privileged code
245 * (i.e. secure_getenv() instead of getenv()).
247 * The kernel keyring is only relevant for system services (as for user services we don't store the
248 * invocation ID in the keyring, as there'd be no trust benefit in that). The environment variable is
249 * primarily relevant for user services, and sufficiently safe as no privilege boundary is involved. */
251 r = get_invocation_from_keyring(&saved_invocation_id);
258 e = secure_getenv("INVOCATION_ID");
262 r = sd_id128_from_string(e, &saved_invocation_id);
268 *ret = saved_invocation_id;
272 static sd_id128_t make_v4_uuid(sd_id128_t id) {
273 /* Stolen from generate_random_uuid() of drivers/char/random.c
274 * in the kernel sources */
276 /* Set UUID version to 4 --- truly random generation */
277 id.bytes[6] = (id.bytes[6] & 0x0F) | 0x40;
279 /* Set the UUID variant to DCE */
280 id.bytes[8] = (id.bytes[8] & 0x3F) | 0x80;
285 _public_ int sd_id128_randomize(sd_id128_t *ret) {
289 assert_return(ret, -EINVAL);
291 r = dev_urandom(&t, sizeof(t));
295 /* Turn this into a valid v4 UUID, to be nice. Note that we
296 * only guarantee this for newly generated UUIDs, not for
297 * pre-existing ones. */
299 *ret = make_v4_uuid(t);
303 _public_ int sd_id128_get_machine_app_specific(sd_id128_t app_id, sd_id128_t *ret) {
304 _cleanup_(khash_unrefp) khash *h = NULL;
305 sd_id128_t m, result;
309 assert_return(ret, -EINVAL);
311 r = sd_id128_get_machine(&m);
315 r = khash_new_with_key(&h, "hmac(sha256)", &m, sizeof(m));
319 r = khash_put(h, &app_id, sizeof(app_id));
323 r = khash_digest_data(h, &p);
327 /* We chop off the trailing 16 bytes */
328 memcpy(&result, p, MIN(khash_get_size(h), sizeof(result)));
330 *ret = make_v4_uuid(result);