diff options
-rw-r--r-- | man/machine-id.xml | 43 | ||||
-rw-r--r-- | src/machine-id-setup.c | 38 |
2 files changed, 67 insertions, 14 deletions
diff --git a/man/machine-id.xml b/man/machine-id.xml index d0bfbd240d..6ca9990988 100644 --- a/man/machine-id.xml +++ b/man/machine-id.xml @@ -55,10 +55,12 @@ <title>Description</title> <para>The <filename>/etc/machine-id</filename> file - configures the unique machine id of the local system - that is set during installation. It should contain a - single newline-terminated, hexadecimal, lowercase 16 - character machine ID string.</para> + contains the unique machine id of the local system + that is set during installation. The machine ID is a + single newline-terminated, hexadecimal, lowercase 32 + character machine ID string. (When decoded from + hexadecimal this corresponds with a 16 byte/128 bit + string.)</para> <para>The machine ID is usually generated from a random source during system installation and stays @@ -69,7 +71,7 @@ <para>The machine ID does not change based on user configuration, or when hardware is replaced.</para> - <para>This machine id follows the same format and + <para>This machine ID adheres to the same format and logic as the D-Bus machine ID.</para> <para>Programs may use this ID to identify the host @@ -82,13 +84,42 @@ </refsect1> <refsect1> + <title>Relation to OSF UUIDs</title> + + <para>Note that the machine ID historically is not an + OSF UUID as defined by <ulink + url="http://tools.ietf.org/html/rfc4122">RFC + 4122</ulink>, nor a Microsoft GUID. Starting with + systemd v30 newly generated machine IDs however do + qualify as v4 UUIDs.</para> + + <para>In order to maintain compatibility with existing + installations, an application requiring a UUID should + decode the machine ID, and then apply the following + operations to turn it into a valid OSF v4 UUID. With + <literal>id</literal> being an unsigned character + array:</para> + + <programlisting>/* Set UUID version to 4 --- truly random generation */ +id[6] = (id[6] & 0x0F) | 0x40; +/* Set the UUID variant to DCE */ +id[8] = (id[8] & 0x3F) | 0x80;</programlisting> + + <para>(This code is inspired by + <literal>generate_random_uuid()</literal> of + <filename>drivers/char/random.c</filename> from the + kernel sources.)</para> + + </refsect1> + + <refsect1> <title>History</title> <para>The simple configuration file format of <filename>/etc/machine-id</filename> originates in the <filename>/var/lib/dbus/machine-id</filename> file introduced by D-Bus. In fact this latter file might be a - symlink to the + symlink to <varname>/etc/machine-id</varname>.</para> </refsect1> diff --git a/src/machine-id-setup.c b/src/machine-id-setup.c index 98e288e1b5..be51d0dec7 100644 --- a/src/machine-id-setup.c +++ b/src/machine-id-setup.c @@ -32,16 +32,28 @@ #include "util.h" #include "log.h" +static void make_v4_uuid(unsigned char *id) { + /* Stolen from generate_random_uuid() of drivers/char/random.c + * in the kernel sources */ + + /* Set UUID version to 4 --- truly random generation */ + id[6] = (id[6] & 0x0F) | 0x40; + + /* Set the UUID variant to DCE */ + id[8] = (id[8] & 0x3F) | 0x80; +} + static int generate(char id[34]) { int fd; - char buf[16]; - char *p, *q; + unsigned char buf[16], *p; + char *q; ssize_t k; assert(id); /* First, try reading the D-Bus machine id, unless it is a symlink */ - if ((fd = open("/var/lib/dbus/machine-id", O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW)) >= 0) { + fd = open("/var/lib/dbus/machine-id", O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW); + if (fd >= 0) { k = loop_read(fd, id, 33, false); close_nointr_nofail(fd); @@ -56,7 +68,8 @@ static int generate(char id[34]) { } /* If that didn't work, generate a random machine id */ - if ((fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC|O_NOCTTY)) < 0) { + fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC|O_NOCTTY); + if (fd < 0) { log_error("Failed to open /dev/urandom: %m"); return -errno; } @@ -69,6 +82,11 @@ static int generate(char id[34]) { return k < 0 ? (int) k : -EIO; } + /* Turn this into a valid v4 UUID, to be nice. Note that we + * only guarantee this for newly generated UUIDs, not for + * pre-existing ones.*/ + make_v4_uuid(buf); + for (p = buf, q = id; p < buf + sizeof(buf); p++, q += 2) { q[0] = hexchar(*p >> 4); q[1] = hexchar(*p & 15); @@ -96,10 +114,12 @@ int machine_id_setup(void) { * will be owned by root it doesn't matter much, but maybe * people look. */ - if ((fd = open("/etc/machine-id", O_RDWR|O_CREAT|O_CLOEXEC|O_NOCTTY, 0444)) >= 0) + fd = open("/etc/machine-id", O_RDWR|O_CREAT|O_CLOEXEC|O_NOCTTY, 0444); + if (fd >= 0) writable = true; else { - if ((fd = open("/etc/machine-id", O_RDONLY|O_CLOEXEC|O_NOCTTY)) < 0) { + fd = open("/etc/machine-id", O_RDONLY|O_CLOEXEC|O_NOCTTY); + if (fd < 0) { umask(m); log_error("Cannot open /etc/machine-id: %m"); return -errno; @@ -126,7 +146,8 @@ int machine_id_setup(void) { /* Hmm, so, the id currently stored is not useful, then let's * generate one */ - if ((r = generate(id)) < 0) + r = generate(id); + if (r < 0) goto finish; if (S_ISREG(st.st_mode) && writable) { @@ -146,7 +167,8 @@ int machine_id_setup(void) { mkdir_p("/run/systemd", 0755); - if ((r = write_one_line_file("/run/systemd/machine-id", id)) < 0) { + r = write_one_line_file("/run/systemd/machine-id", id); + if (r < 0) { log_error("Cannot write /run/systemd/machine-id: %s", strerror(-r)); unlink("/run/systemd/machine-id"); |