From 782902f2171e6f17885928e4b55b32180fd80b18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Sat, 26 Aug 2023 12:12:01 +0200 Subject: [PATCH 01/13] id128: add option -P to only show value We have '-P' in systemctl with similar meaning. Partially closes https://github.com/systemd/systemd/issues/27514. --- man/systemd-id128.xml | 8 ++++++++ src/id128/id128.c | 16 ++++++++++++++-- test/units/testsuite-74.id128.sh | 3 ++- 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/man/systemd-id128.xml b/man/systemd-id128.xml index 2211550451..6cb51fa777 100644 --- a/man/systemd-id128.xml +++ b/man/systemd-id128.xml @@ -96,6 +96,14 @@ + + + + + Only print the value. May be combined with + /. + + diff --git a/src/id128/id128.c b/src/id128/id128.c index a8c5c9ac6c..c22376d4fc 100644 --- a/src/id128/id128.c +++ b/src/id128/id128.c @@ -16,6 +16,7 @@ static Id128PrettyPrintMode arg_mode = ID128_PRINT_ID128; static sd_id128_t arg_app = {}; +static bool arg_value = false; static int verb_new(int argc, char **argv, void *userdata) { return id128_print_new(arg_mode); @@ -85,7 +86,10 @@ static int show_one(Table **table, const char *name, sd_id128_t uuid, bool first puts(""); return 0; - } else { + } else if (arg_value) + return id128_pretty_print(uuid, arg_mode); + + else { if (!*table) { *table = table_new("name", "id"); if (!*table) @@ -191,6 +195,7 @@ static int parse_argv(int argc, char *argv[]) { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, ARG_VERSION }, { "pretty", no_argument, NULL, 'p' }, + { "value", no_argument, NULL, 'P' }, { "app-specific", required_argument, NULL, 'a' }, { "uuid", no_argument, NULL, 'u' }, {}, @@ -201,7 +206,7 @@ static int parse_argv(int argc, char *argv[]) { assert(argc >= 0); assert(argv); - while ((c = getopt_long(argc, argv, "hpa:u", options, NULL)) >= 0) + while ((c = getopt_long(argc, argv, "hpa:uP", options, NULL)) >= 0) switch (c) { case 'h': @@ -212,6 +217,13 @@ static int parse_argv(int argc, char *argv[]) { case 'p': arg_mode = ID128_PRINT_PRETTY; + arg_value = false; + break; + + case 'P': + arg_value = true; + if (arg_mode == ID128_PRINT_PRETTY) + arg_mode = ID128_PRINT_ID128; break; case 'a': diff --git a/test/units/testsuite-74.id128.sh b/test/units/testsuite-74.id128.sh index 213333d9d1..4e2e1257dc 100755 --- a/test/units/testsuite-74.id128.sh +++ b/test/units/testsuite-74.id128.sh @@ -9,7 +9,8 @@ set -o pipefail systemd-id128 --help systemd-id128 help systemd-id128 show -systemd-id128 show --pretty | tail -n10 +systemd-id128 show --pretty | tail +systemd-id128 show --value | tail systemd-id128 show 4f68bce3e8cd4db196e7fbcaf984b709 # root-x86-64 systemd-id128 show --pretty 4f68bce3e8cd4db196e7fbcaf984b709 From f1c0ad52790bb05a672c1e4219c2ff8cf301a6f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Sat, 26 Aug 2023 12:22:46 +0200 Subject: [PATCH 02/13] shared/id128-print: fix indentation, reduce variable scope --- src/shared/id128-print.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/shared/id128-print.c b/src/shared/id128-print.c index f232767adf..c9509b28f0 100644 --- a/src/shared/id128-print.c +++ b/src/shared/id128-print.c @@ -11,12 +11,10 @@ #include "terminal-util.h" int id128_pretty_print_sample(const char *name, sd_id128_t id) { - _cleanup_free_ char *man_link = NULL, *mod_link = NULL; - const char *on, *off; - unsigned i; + _cleanup_free_ char *man_link = NULL, *mod_link = NULL; - on = ansi_highlight(); - off = ansi_normal(); + const char *on = ansi_highlight(), + *off = ansi_normal(); if (terminal_urlify("man:systemd-id128(1)", "systemd-id128(1)", &man_link) < 0) return log_oom(); @@ -34,8 +32,8 @@ int id128_pretty_print_sample(const char *name, sd_id128_t id) { on, SD_ID128_FORMAT_VAL(id), off, man_link, on, name); - for (i = 0; i < 16; i++) - printf("%02x%s", id.bytes[i], i != 15 ? "," : ""); + for (size_t i = 0; i < 16; i++) + printf("%02x%s", id.bytes[i], i < 15 ? "," : ""); printf(")%s\n\n", off); printf("As Python constant:\n" From 0f7735d7a9232e04d40adb0a8604e62e69af57c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Sat, 26 Aug 2023 12:34:34 +0200 Subject: [PATCH 03/13] sd-id128: avoid one memcpy By aligning the output buffer, we can just use the result directly, no need to copy stuff around. --- src/libsystemd/sd-id128/sd-id128.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/libsystemd/sd-id128/sd-id128.c b/src/libsystemd/sd-id128/sd-id128.c index 6a82a7f7b8..be6da9c88a 100644 --- a/src/libsystemd/sd-id128/sd-id128.c +++ b/src/libsystemd/sd-id128/sd-id128.c @@ -339,17 +339,18 @@ _public_ int sd_id128_randomize(sd_id128_t *ret) { } static int get_app_specific(sd_id128_t base, sd_id128_t app_id, sd_id128_t *ret) { - uint8_t hmac[SHA256_DIGEST_SIZE]; - sd_id128_t result; + assert_cc(sizeof(sd_id128_t) < SHA256_DIGEST_SIZE); /* Check that we don't need to pad with zeros. */ + union { + uint8_t hmac[SHA256_DIGEST_SIZE]; + sd_id128_t result; + } buf; assert(ret); - hmac_sha256(&base, sizeof(base), &app_id, sizeof(app_id), hmac); + hmac_sha256(&base, sizeof(base), &app_id, sizeof(app_id), buf.hmac); /* Take only the first half. */ - memcpy(&result, hmac, MIN(sizeof(hmac), sizeof(result))); - - *ret = id128_make_v4_uuid(result); + *ret = id128_make_v4_uuid(buf.result); return 0; } From 62b4bee9bc2b079ee966da68d5be77a74c48cea7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Sat, 26 Aug 2023 13:03:38 +0200 Subject: [PATCH 04/13] sd-id128: export sd_id128_get_app_specific() We exported sd_id128_get_machine_app_specific() and sd_id128_get_boot_app_specific(). But those operate on the current machine, and sometimes the user might want to do the same calculation for a different machine, or an earlier boot, etc. We expose the underlying implementation to make this easy. --- src/libsystemd/libsystemd.sym | 5 +++++ src/libsystemd/sd-id128/sd-id128.c | 8 ++++---- src/systemd/sd-id128.h | 1 + src/test/test-id128.c | 4 ++++ 4 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/libsystemd/libsystemd.sym b/src/libsystemd/libsystemd.sym index ea13e02719..56a8831f0f 100644 --- a/src/libsystemd/libsystemd.sym +++ b/src/libsystemd/libsystemd.sym @@ -828,3 +828,8 @@ global: sd_journal_step_one; sd_session_get_leader; } LIBSYSTEMD_253; + +LIBSYSTEMD_255 { +global: + sd_id128_get_app_specific; +} LIBSYSTEMD_254; diff --git a/src/libsystemd/sd-id128/sd-id128.c b/src/libsystemd/sd-id128/sd-id128.c index be6da9c88a..adc73e4fdc 100644 --- a/src/libsystemd/sd-id128/sd-id128.c +++ b/src/libsystemd/sd-id128/sd-id128.c @@ -338,14 +338,14 @@ _public_ int sd_id128_randomize(sd_id128_t *ret) { return 0; } -static int get_app_specific(sd_id128_t base, sd_id128_t app_id, sd_id128_t *ret) { +_public_ int sd_id128_get_app_specific(sd_id128_t base, sd_id128_t app_id, sd_id128_t *ret) { assert_cc(sizeof(sd_id128_t) < SHA256_DIGEST_SIZE); /* Check that we don't need to pad with zeros. */ union { uint8_t hmac[SHA256_DIGEST_SIZE]; sd_id128_t result; } buf; - assert(ret); + assert_return(ret, -EINVAL); hmac_sha256(&base, sizeof(base), &app_id, sizeof(app_id), buf.hmac); @@ -364,7 +364,7 @@ _public_ int sd_id128_get_machine_app_specific(sd_id128_t app_id, sd_id128_t *re if (r < 0) return r; - return get_app_specific(id, app_id, ret); + return sd_id128_get_app_specific(id, app_id, ret); } _public_ int sd_id128_get_boot_app_specific(sd_id128_t app_id, sd_id128_t *ret) { @@ -377,5 +377,5 @@ _public_ int sd_id128_get_boot_app_specific(sd_id128_t app_id, sd_id128_t *ret) if (r < 0) return r; - return get_app_specific(id, app_id, ret); + return sd_id128_get_app_specific(id, app_id, ret); } diff --git a/src/systemd/sd-id128.h b/src/systemd/sd-id128.h index 3303c374ce..a984a9d85e 100644 --- a/src/systemd/sd-id128.h +++ b/src/systemd/sd-id128.h @@ -50,6 +50,7 @@ int sd_id128_get_machine(sd_id128_t *ret); int sd_id128_get_boot(sd_id128_t *ret); int sd_id128_get_invocation(sd_id128_t *ret); +int sd_id128_get_app_specific(sd_id128_t base, sd_id128_t app_id, sd_id128_t *ret); int sd_id128_get_machine_app_specific(sd_id128_t app_id, sd_id128_t *ret); int sd_id128_get_boot_app_specific(sd_id128_t app_id, sd_id128_t *ret); diff --git a/src/test/test-id128.c b/src/test/test-id128.c index 58dc88110e..912e8c9aaa 100644 --- a/src/test/test-id128.c +++ b/src/test/test-id128.c @@ -172,6 +172,10 @@ TEST(id128) { assert_se(lseek(fd, 0, SEEK_SET) == 0); assert_se(id128_read_fd(fd, ID128_FORMAT_ANY, NULL) == -EUCLEAN); + assert_se(sd_id128_get_app_specific(SD_ID128_MAKE(51,df,0b,4b,c3,b0,4c,97,80,e2,99,b9,8c,a3,73,b8), + SD_ID128_MAKE(f0,3d,aa,eb,1c,33,4b,43,a7,32,17,29,44,bf,77,2e), &id) >= 0); + assert_se(sd_id128_equal(id, SD_ID128_MAKE(1d,ee,59,54,e7,5c,4d,6f,b9,6c,c6,c0,4c,a1,8a,86))); + if (sd_booted() > 0 && sd_id128_get_machine(NULL) >= 0) { assert_se(sd_id128_get_machine_app_specific(SD_ID128_MAKE(f0,3d,aa,eb,1c,33,4b,43,a7,32,17,29,44,bf,77,2e), &id) >= 0); assert_se(sd_id128_get_machine_app_specific(SD_ID128_MAKE(f0,3d,aa,eb,1c,33,4b,43,a7,32,17,29,44,bf,77,2e), &id2) >= 0); From b5c27ebca449c41fbd8a4e37ade98e963c370dd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Sat, 26 Aug 2023 13:07:32 +0200 Subject: [PATCH 05/13] man: document sd_id128_get_app_specific --- man/rules/meson.build | 3 ++- man/sd_id128_get_machine.xml | 41 +++++++++++++++++++++++++----------- 2 files changed, 31 insertions(+), 13 deletions(-) diff --git a/man/rules/meson.build b/man/rules/meson.build index eaaf4adb1b..2884cc32b4 100644 --- a/man/rules/meson.build +++ b/man/rules/meson.build @@ -672,7 +672,8 @@ manpages = [ ''], ['sd_id128_get_machine', '3', - ['sd_id128_get_boot', + ['sd_id128_get_app_specific', + 'sd_id128_get_boot', 'sd_id128_get_boot_app_specific', 'sd_id128_get_invocation', 'sd_id128_get_machine_app_specific'], diff --git a/man/sd_id128_get_machine.xml b/man/sd_id128_get_machine.xml index 40b9b6f582..fc13ae50f4 100644 --- a/man/sd_id128_get_machine.xml +++ b/man/sd_id128_get_machine.xml @@ -17,6 +17,7 @@ sd_id128_get_machine + sd_id128_get_app_specific sd_id128_get_machine_app_specific sd_id128_get_boot sd_id128_get_boot_app_specific @@ -33,6 +34,13 @@ sd_id128_t *ret + + int sd_id128_get_app_specific + sd_id128_t base + sd_id128_t app_id + sd_id128_t *ret + + int sd_id128_get_machine_app_specific sd_id128_t app_id @@ -69,16 +77,25 @@ ID from this machine ID, in an irreversible (cryptographically secure) way. To make this easy sd_id128_get_machine_app_specific() is provided, see below. + sd_id128_get_app_specific() returns a machine ID that is a combination of the + base and app_id parameters. Internally, this function + calculates HMAC-SHA256 of the app_id parameter keyed by the + base parameter, and truncates this result to fit in + sd_id128_t and turns it into a valid Variant 1 Version 4 UUID, in accordance + with RFC 4122. Neither of the two input + parameters can be calculated from the output parameter ret. + sd_id128_get_machine_app_specific() is similar to - sd_id128_get_machine(), but retrieves a machine ID that is specific to the application that is - identified by the indicated application ID. It is recommended to use this function instead of - sd_id128_get_machine() when passing an ID to untrusted environments, in order to make sure - that the original machine ID may not be determined externally. This way, the ID used by the application remains - stable on a given machine, but cannot be easily correlated with IDs used in other applications on the same - machine. The application-specific ID should be generated via a tool like systemd-id128 new, - and may be compiled into the application. This function will return the same application-specific ID for each - combination of machine ID and application ID. Internally, this function calculates HMAC-SHA256 of the application - ID, keyed by the machine ID. + sd_id128_get_machine(), but retrieves a machine ID that is specific to the + application that is identified by the indicated application ID. It is recommended to use this function + instead of sd_id128_get_machine() when passing an ID to untrusted environments, in + order to make sure that the original machine ID may not be determined externally. This way, the ID used + by the application remains stable on a given machine, but cannot be easily correlated with IDs used in + other applications on the same machine. The application-specific ID should be generated via a tool like + systemd-id128 new, and may be compiled into the application. This function will return + the same application-specific ID for each combination of machine ID and application ID. Internally, this + function calls sd_id128_get_app_specific() with the result from + sd_id128_get_machine() and the app_id parameter. sd_id128_get_boot() returns the boot ID of the executing kernel. This reads and parses the /proc/sys/kernel/random/boot_id file exposed by the kernel. It is randomly generated early @@ -89,9 +106,9 @@ derive an application specific ID using sd_id128_get_boot_app_specific(), see below. sd_id128_get_boot_app_specific() is analogous to - sd_id128_get_machine_app_specific() but returns an ID that changes between boots. Some - machines may be used for a long time without rebooting, hence the boot ID may remain constant for a long time, and - has properties similar to the machine ID during that time. + sd_id128_get_machine_app_specific(), but returns an ID that changes between + boots. Some machines may be used for a long time without rebooting, hence the boot ID may remain constant + for a long time, and has properties similar to the machine ID during that time. sd_id128_get_invocation() returns the invocation ID of the currently executed service. In its current implementation, this tries to read and parse the following: From f4e518e812cd157e0118e893fd9bcac9132e6eee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Sat, 26 Aug 2023 13:29:01 +0200 Subject: [PATCH 06/13] systemd-id128: properly document the show verb https://github.com/systemd/systemd/issues/27514 requested this functionality among other things, but it is already implemented. The man page was also missing 'show' in the synopsis, so add that, along with an example. --- man/systemd-id128.xml | 35 +++++++++++++++++++++++++++++++---- src/id128/id128.c | 2 +- 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/man/systemd-id128.xml b/man/systemd-id128.xml index 6cb51fa777..c4521ea945 100644 --- a/man/systemd-id128.xml +++ b/man/systemd-id128.xml @@ -44,6 +44,13 @@ OPTIONS invocation-id + + + systemd-id128 + OPTIONS + show + NAME|UUID + @@ -76,9 +83,10 @@ With show, well-known IDs are printed (for now, only GPT partition type UUIDs), along with brief identifier strings. When no arguments are specified, all known IDs are shown. When - arguments are specified, they must be the identifiers or ID values of one or more known IDs, which are - then printed. Combine with to list the IDs in UUID style, i.e. the way GPT - partition type UUIDs are usually shown. + arguments are specified, they may be the identifiers or ID values of one or more known IDs, which are + then printed with their name, or arbitrary IDs, which are then printed with a placeholder name. Combine + with to list the IDs in UUID style, i.e. the way GPT partition type UUIDs are + usually shown. @@ -137,7 +145,26 @@ Exit status - On success, 0 is returned, a non-zero failure code otherwise. + On success 0 is returned, and a non-zero failure code otherwise. + + + + Examples + + + Show a well-known UUID + +$ systemd-id128 show -P user-home +773f91ef66d449b5bd83d683bf40ad16 + +$ systemd-id128 show -Pu user-home +773f91ef-66d4-49b5-bd83-d683bf40ad16 + +$ systemd-id128 show 773f91ef-66d4-49b5-bd83-d683bf40ad16 +NAME ID +user-home 773f91ef66d449b5bd83d683bf40ad16 + + diff --git a/src/id128/id128.c b/src/id128/id128.c index c22376d4fc..0ec2df059a 100644 --- a/src/id128/id128.c +++ b/src/id128/id128.c @@ -166,7 +166,7 @@ static int help(void) { " machine-id Print the ID of current machine\n" " boot-id Print the ID of current boot\n" " invocation-id Print the ID of current invocation\n" - " show [NAME] Print one or more well-known GPT partition type IDs\n" + " show [NAME|UUID] Print one or more UUIDs\n" " help Show this help\n" "\nOptions:\n" " -h --help Show this help\n" From 7c9de5d85d7df4177418e5cb8444b94086ce287b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Sat, 26 Aug 2023 15:10:25 +0200 Subject: [PATCH 07/13] id128-util: add id128_from_string_not_null() --- src/libsystemd/sd-id128/id128-util.c | 17 +++++++++++++++++ src/libsystemd/sd-id128/id128-util.h | 2 ++ src/test/test-id128.c | 8 ++++++++ 3 files changed, 27 insertions(+) diff --git a/src/libsystemd/sd-id128/id128-util.c b/src/libsystemd/sd-id128/id128-util.c index ee9e91c58d..9d391de166 100644 --- a/src/libsystemd/sd-id128/id128-util.c +++ b/src/libsystemd/sd-id128/id128-util.c @@ -13,6 +13,23 @@ #include "string-util.h" #include "sync-util.h" +int id128_from_string_nonzero(const char *s, sd_id128_t *ret) { + sd_id128_t t; + int r; + + assert(ret); + + r = sd_id128_from_string(ASSERT_PTR(s), &t); + if (r < 0) + return r; + + if (sd_id128_is_null(t)) + return -ENXIO; + + *ret = t; + return 0; +} + bool id128_is_valid(const char *s) { size_t l; diff --git a/src/libsystemd/sd-id128/id128-util.h b/src/libsystemd/sd-id128/id128-util.h index bd3e201361..80c36e5a7b 100644 --- a/src/libsystemd/sd-id128/id128-util.h +++ b/src/libsystemd/sd-id128/id128-util.h @@ -21,6 +21,8 @@ typedef enum Id128Flag { ID128_REFUSE_NULL = 1 << 3, /* Refuse all zero ID with -ENOMEDIUM. */ } Id128Flag; +int id128_from_string_nonzero(const char *s, sd_id128_t *ret); + int id128_read_fd(int fd, Id128Flag f, sd_id128_t *ret); int id128_read_at(int dir_fd, const char *path, Id128Flag f, sd_id128_t *ret); static inline int id128_read(const char *path, Id128Flag f, sd_id128_t *ret) { diff --git a/src/test/test-id128.c b/src/test/test-id128.c index 912e8c9aaa..ca204d3718 100644 --- a/src/test/test-id128.c +++ b/src/test/test-id128.c @@ -20,6 +20,7 @@ #define ID128_WALDI SD_ID128_MAKE(01, 02, 03, 04, 05, 06, 07, 08, 09, 0a, 0b, 0c, 0d, 0e, 0f, 10) #define STR_WALDI "0102030405060708090a0b0c0d0e0f10" #define UUID_WALDI "01020304-0506-0708-090a-0b0c0d0e0f10" +#define STR_NULL "00000000000000000000000000000000" TEST(id128) { sd_id128_t id, id2; @@ -75,6 +76,13 @@ TEST(id128) { assert_se(sd_id128_from_string("01020304-0506-0708-090a0b0c0d0e0f10", &id) < 0); assert_se(sd_id128_from_string("010203040506-0708-090a-0b0c0d0e0f10", &id) < 0); + assert_se(id128_from_string_nonzero(STR_WALDI, &id) == 0); + assert_se(id128_from_string_nonzero(STR_NULL, &id) == -ENXIO); + assert_se(id128_from_string_nonzero("01020304-0506-0708-090a-0b0c0d0e0f101", &id) < 0); + assert_se(id128_from_string_nonzero("01020304-0506-0708-090a-0b0c0d0e0f10-", &id) < 0); + assert_se(id128_from_string_nonzero("01020304-0506-0708-090a0b0c0d0e0f10", &id) < 0); + assert_se(id128_from_string_nonzero("010203040506-0708-090a-0b0c0d0e0f10", &id) < 0); + assert_se(id128_is_valid(STR_WALDI)); assert_se(id128_is_valid(UUID_WALDI)); assert_se(!id128_is_valid("")); From aea3f594db3d11966fb0ead86c07d83dfeb5fe69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Sat, 26 Aug 2023 15:13:05 +0200 Subject: [PATCH 08/13] various: use id128_from_string_not_null() No functional change. In config_parse_address_generation_type() we would set the output parameter and then say it's ignored, so it _looked_ like an error in the code, but the variable was always initialized to SD_ID128_NULL anyway, so the code was actually fine. --- src/core/main.c | 18 ++---------------- src/network/networkd-address-generation.c | 11 +++-------- src/nspawn/nspawn.c | 9 ++++----- src/partition/repart.c | 10 ++++------ src/shared/conf-parser.c | 17 ++++++----------- 5 files changed, 19 insertions(+), 46 deletions(-) diff --git a/src/core/main.c b/src/core/main.c index df9cfa21aa..7a8652df03 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -242,20 +242,6 @@ static int console_setup(void) { return 0; } -static int set_machine_id(const char *m) { - sd_id128_t t; - assert(m); - - if (sd_id128_from_string(m, &t) < 0) - return -EINVAL; - - if (sd_id128_is_null(t)) - return -EINVAL; - - arg_machine_id = t; - return 0; -} - static int parse_proc_cmdline_item(const char *key, const char *value, void *data) { int r; @@ -392,7 +378,7 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat if (proc_cmdline_value_missing(key, value)) return 0; - r = set_machine_id(value); + r = id128_from_string_nonzero(value, &arg_machine_id); if (r < 0) log_warning_errno(r, "MachineID '%s' is not valid, ignoring: %m", value); @@ -1045,7 +1031,7 @@ static int parse_argv(int argc, char *argv[]) { break; case ARG_MACHINE_ID: - r = set_machine_id(optarg); + r = id128_from_string_nonzero(optarg, &arg_machine_id); if (r < 0) return log_error_errno(r, "MachineID '%s' is not valid: %m", optarg); break; diff --git a/src/network/networkd-address-generation.c b/src/network/networkd-address-generation.c index 769cccf748..79fde024a3 100644 --- a/src/network/networkd-address-generation.c +++ b/src/network/networkd-address-generation.c @@ -370,16 +370,11 @@ int config_parse_address_generation_type( } if (comma) { - r = sd_id128_from_string(comma + 1, &secret_key); + r = id128_from_string_nonzero(comma + 1, &secret_key); if (r < 0) { log_syntax(unit, LOG_WARNING, filename, line, r, - "Failed to parse secret key in %s=, ignoring assignment: %s", - lvalue, rvalue); - return 0; - } - if (sd_id128_is_null(secret_key)) { - log_syntax(unit, LOG_WARNING, filename, line, 0, - "Secret key in %s= cannot be null, ignoring assignment: %s", + r == -ENXIO ? "Secret key in %s= cannot be null, ignoring assignment: %s" + : "Failed to parse secret key in %s=, ignoring assignment: %s", lvalue, rvalue); return 0; } diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index d3ae547746..9e74ead8d5 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -976,13 +976,12 @@ static int parse_argv(int argc, char *argv[]) { break; case ARG_UUID: - r = sd_id128_from_string(optarg, &arg_uuid); - if (r < 0) - return log_error_errno(r, "Invalid UUID: %s", optarg); - - if (sd_id128_is_null(arg_uuid)) + r = id128_from_string_nonzero(optarg, &arg_uuid); + if (r == -ENXIO) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Machine UUID may not be all zeroes."); + if (r < 0) + return log_error_errno(r, "Invalid UUID: %s", optarg); arg_settings_mask |= SETTING_MACHINE_ID; break; diff --git a/src/partition/repart.c b/src/partition/repart.c index e403012e92..b6fe9ef79e 100644 --- a/src/partition/repart.c +++ b/src/partition/repart.c @@ -2438,11 +2438,8 @@ static int context_load_partition_table(Context *context) { if (r < 0) return log_error_errno(r, "Failed to get current GPT disk label UUID: %m"); - r = sd_id128_from_string(disk_uuid_string, &disk_uuid); - if (r < 0) - return log_error_errno(r, "Failed to parse current GPT disk label UUID: %m"); - - if (sd_id128_is_null(disk_uuid)) { + r = id128_from_string_nonzero(disk_uuid_string, &disk_uuid); + if (r == -ENXIO) { r = derive_uuid(context->seed, "disk-uuid", &disk_uuid); if (r < 0) return log_error_errno(r, "Failed to acquire disk GPT uuid: %m"); @@ -2450,7 +2447,8 @@ static int context_load_partition_table(Context *context) { r = fdisk_set_disklabel_id(c); if (r < 0) return log_error_errno(r, "Failed to set GPT disk label: %m"); - } + } else if (r < 0) + return log_error_errno(r, "Failed to parse current GPT disk label UUID: %m"); r = fdisk_get_partitions(c, &t); if (r < 0) diff --git a/src/shared/conf-parser.c b/src/shared/conf-parser.c index ec4b53b2e8..68c4b2ca1a 100644 --- a/src/shared/conf-parser.c +++ b/src/shared/conf-parser.c @@ -19,6 +19,7 @@ #include "fileio.h" #include "fs-util.h" #include "hostname-util.h" +#include "id128-util.h" #include "in-addr-util.h" #include "log.h" #include "macro.h" @@ -944,25 +945,19 @@ int config_parse_id128( void *data, void *userdata) { - sd_id128_t t, *result = data; + sd_id128_t *result = data; int r; assert(filename); assert(lvalue); assert(rvalue); - r = sd_id128_from_string(rvalue, &t); - if (r < 0) { + r = id128_from_string_nonzero(rvalue, result); + if (r == -ENXIO) + log_syntax(unit, LOG_WARNING, filename, line, r, "128-bit ID/UUID is all 0, ignoring: %s", rvalue); + else if (r < 0) log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse 128-bit ID/UUID, ignoring: %s", rvalue); - return 0; - } - if (sd_id128_is_null(t)) { - log_syntax(unit, LOG_WARNING, filename, line, 0, "128-bit ID/UUID is all 0, ignoring: %s", rvalue); - return 0; - } - - *result = t; return 0; } From b37e8184a5a376749fbf68674ed6d7a4fc9901aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Sat, 26 Aug 2023 13:39:02 +0200 Subject: [PATCH 09/13] id128: allow combining --app with show This effectively exposes sd_id128_get_app_specific() on the commandline. Fixes https://github.com/systemd/systemd/issues/27514. --- man/systemd-id128.xml | 47 +++++++++++++++++++++++++------- src/id128/id128.c | 14 ++++++++-- src/test/test-id128.c | 1 + test/units/testsuite-74.id128.sh | 8 ++++++ 4 files changed, 57 insertions(+), 13 deletions(-) diff --git a/man/systemd-id128.xml b/man/systemd-id128.xml index c4521ea945..bf71a7c3a8 100644 --- a/man/systemd-id128.xml +++ b/man/systemd-id128.xml @@ -70,12 +70,6 @@ With boot-id, the identifier of the current boot will be printed. - Both machine-id and boot-id may be combined - with the switch to - generate application-specific IDs. See - sd_id128_get_machine3 - for the discussion when this is useful. - With invocation-id, the identifier of the current service invocation will be printed. This is available in systemd services. See systemd.exec5. @@ -87,6 +81,12 @@ then printed with their name, or arbitrary IDs, which are then printed with a placeholder name. Combine with to list the IDs in UUID style, i.e. the way GPT partition type UUIDs are usually shown. + + machine-id, boot-id, and show may be + combined with the switch to generate + application-specific IDs. See + sd_id128_get_machine3 + for the discussion when this is useful. @@ -116,10 +116,14 @@ - With this option, an identifier that is the result of hashing the - application identifier app-id and the machine identifier will be - printed. The app-id argument must be a valid sd-id128 string - identifying the application. + With this option, identifiers will be printed that are the result of hashing the + application identifier app-id and another ID. The + app-id argument must be a valid sd-id128 string identifying the + application. When used with machine-id, the other ID will be the machine ID as + described in + machine-id5, when + used with boot-id, the other ID will be the boot ID, and when used with + show, the other ID or IDs should be specified via the positional arguments. @@ -165,6 +169,29 @@ NAME ID user-home 773f91ef66d449b5bd83d683bf40ad16 + + + Generate an application-specific UUID + + +$ systemd-id128 machine-id -u +3a9d668b-4db7-4939-8a4a-5e78a03bffb7 + +$ systemd-id128 new -u +1fb8f24b-02df-458d-9659-cc8ace68e28a + +$ systemd-id128 --app=1fb8f24b-02df-458d-9659-cc8ace68e28a +47b82cb1-5339-43da-b2a6-1c350aef1bd1 + +$ systemd-id128 -Pu show 3a9d668b-4db7-4939-8a4a-5e78a03bffb7 --app=1fb8f24b-02df-458d-9659-cc8ace68e28a +47b82cb1-5339-43da-b2a6-1c350aef1bd1 + + + On a given machine with the ID 3a9d668b-4db7-4939-8a4a-5e78a03bffb7, for the application + 1fb8f24b-02df-458d-9659-cc8ace68e28a, we generate an application-specific machine ID. If we want to + later recreate the same calculation on a different machine, we need to specify both IDs explicitly. + + diff --git a/src/id128/id128.c b/src/id128/id128.c index 0ec2df059a..29cd2e2dc0 100644 --- a/src/id128/id128.c +++ b/src/id128/id128.c @@ -68,8 +68,16 @@ static int verb_invocation_id(int argc, char **argv, void *userdata) { } static int show_one(Table **table, const char *name, sd_id128_t uuid, bool first) { + sd_id128_t u; int r; + assert(table); + + if (sd_id128_is_null(arg_app)) + u = uuid; + else + assert_se(sd_id128_get_app_specific(uuid, arg_app, &u) == 0); + if (arg_mode == ID128_PRINT_PRETTY) { _cleanup_free_ char *id = NULL; @@ -79,7 +87,7 @@ static int show_one(Table **table, const char *name, sd_id128_t uuid, bool first ascii_strupper(id); - r = id128_pretty_print_sample(id, uuid); + r = id128_pretty_print_sample(id, u); if (r < 0) return r; if (!first) @@ -87,7 +95,7 @@ static int show_one(Table **table, const char *name, sd_id128_t uuid, bool first return 0; } else if (arg_value) - return id128_pretty_print(uuid, arg_mode); + return id128_pretty_print(u, arg_mode); else { if (!*table) { @@ -100,7 +108,7 @@ static int show_one(Table **table, const char *name, sd_id128_t uuid, bool first return table_add_many(*table, TABLE_STRING, name, arg_mode == ID128_PRINT_ID128 ? TABLE_ID128 : TABLE_UUID, - uuid); + u); } } diff --git a/src/test/test-id128.c b/src/test/test-id128.c index ca204d3718..10c061b917 100644 --- a/src/test/test-id128.c +++ b/src/test/test-id128.c @@ -180,6 +180,7 @@ TEST(id128) { assert_se(lseek(fd, 0, SEEK_SET) == 0); assert_se(id128_read_fd(fd, ID128_FORMAT_ANY, NULL) == -EUCLEAN); + /* build/systemd-id128 -a f03daaeb1c334b43a732172944bf772e show 51df0b4bc3b04c9780e299b98ca373b8 */ assert_se(sd_id128_get_app_specific(SD_ID128_MAKE(51,df,0b,4b,c3,b0,4c,97,80,e2,99,b9,8c,a3,73,b8), SD_ID128_MAKE(f0,3d,aa,eb,1c,33,4b,43,a7,32,17,29,44,bf,77,2e), &id) >= 0); assert_se(sd_id128_equal(id, SD_ID128_MAKE(1d,ee,59,54,e7,5c,4d,6f,b9,6c,c6,c0,4c,a1,8a,86))); diff --git a/test/units/testsuite-74.id128.sh b/test/units/testsuite-74.id128.sh index 4e2e1257dc..c1b80d660e 100755 --- a/test/units/testsuite-74.id128.sh +++ b/test/units/testsuite-74.id128.sh @@ -13,6 +13,14 @@ systemd-id128 show --pretty | tail systemd-id128 show --value | tail systemd-id128 show 4f68bce3e8cd4db196e7fbcaf984b709 # root-x86-64 systemd-id128 show --pretty 4f68bce3e8cd4db196e7fbcaf984b709 +systemd-id128 show root-x86-64 +systemd-id128 show --pretty root-x86-64 +[[ "$(systemd-id128 show 4f68bce3e8cd4db196e7fbcaf984b709)" = "$(systemd-id128 show root-x86-64)" ]] +[[ "$(systemd-id128 show 4f68bce3-e8cd-4db1-96e7-fbcaf984b709)" = "$(systemd-id128 show root-x86-64)" ]] + +systemd-id128 show root-x86-64 --app-specific=4f68bce3e8cd4db196e7fbcaf984b709 +systemd-id128 show --pretty root-x86-64 --app-specific=4f68bce3e8cd4db196e7fbcaf984b709 +[[ "$(systemd-id128 show root-x86-64 --app-specific=4f68bce3e8cd4db196e7fbcaf984b709 -P)" = "8ee5535e7cb14c249e1d28b8dfbb939c" ]] [[ "$(systemd-id128 new | wc -c)" -eq 33 ]] systemd-id128 new -p From fa96afb4c4ad1d5e82839dddb686398601784d53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Sat, 26 Aug 2023 14:03:14 +0200 Subject: [PATCH 10/13] sd-id128: do not allow null 'app_id' param If it is null, we get the 'base' param unchanged: $ build/systemd-id128 show 00000000000000000000000000000001 \ --app-specific=00000000000000000000000000000000 00000000000000000000000000000001 This is not good, because it breaks our promise that the base (usually either machine-id or boot-id) cannot be derived from the result. Some application using the library could use a null app id, inadvertently exposing the machine or boot id. (This could happen because of forgotten initialization, or maybe because the app id is configurable, and the user configures it wrongly.) Note: the other way the secret is not exposed: $ build/systemd-id128 show 00000000000000000000000000000000 \ --app-specific=00000000000000000000000000000002 4f63080959264900b0d88d999dae2d3a Normally systemd would not allow a null machine-id or boot-id, but we can let the user do the calculation that if they want to. --- man/sd_id128_get_machine.xml | 5 ++++- src/id128/id128.c | 4 +++- src/libsystemd/sd-id128/sd-id128.c | 1 + src/test/test-id128.c | 4 ++++ 4 files changed, 12 insertions(+), 2 deletions(-) diff --git a/man/sd_id128_get_machine.xml b/man/sd_id128_get_machine.xml index fc13ae50f4..31e4b02d9b 100644 --- a/man/sd_id128_get_machine.xml +++ b/man/sd_id128_get_machine.xml @@ -198,7 +198,10 @@ -ENXIO Returned by sd_id128_get_invocation() if no invocation ID is - set. + set. Also returned by sd_id128_get_app_specific(), + sd_id128_get_machine_app_specific(), and + sd_id128_get_boot_app_specific() when the app_id + parameter is all zeros. diff --git a/src/id128/id128.c b/src/id128/id128.c index 29cd2e2dc0..18e0880805 100644 --- a/src/id128/id128.c +++ b/src/id128/id128.c @@ -235,7 +235,9 @@ static int parse_argv(int argc, char *argv[]) { break; case 'a': - r = sd_id128_from_string(optarg, &arg_app); + r = id128_from_string_nonzero(optarg, &arg_app); + if (r == -ENXIO) + return log_error_errno(r, "Application ID cannot be all zeros."); if (r < 0) return log_error_errno(r, "Failed to parse \"%s\" as application-ID: %m", optarg); break; diff --git a/src/libsystemd/sd-id128/sd-id128.c b/src/libsystemd/sd-id128/sd-id128.c index adc73e4fdc..9fda79ae26 100644 --- a/src/libsystemd/sd-id128/sd-id128.c +++ b/src/libsystemd/sd-id128/sd-id128.c @@ -346,6 +346,7 @@ _public_ int sd_id128_get_app_specific(sd_id128_t base, sd_id128_t app_id, sd_id } buf; assert_return(ret, -EINVAL); + assert_return(!sd_id128_is_null(app_id), -ENXIO); hmac_sha256(&base, sizeof(base), &app_id, sizeof(app_id), buf.hmac); diff --git a/src/test/test-id128.c b/src/test/test-id128.c index 10c061b917..ae7df27d8f 100644 --- a/src/test/test-id128.c +++ b/src/test/test-id128.c @@ -192,6 +192,10 @@ TEST(id128) { assert_se(sd_id128_get_machine_app_specific(SD_ID128_MAKE(51,df,0b,4b,c3,b0,4c,97,80,e2,99,b9,8c,a3,73,b8), &id2) >= 0); assert_se(!sd_id128_equal(id, id2)); } + + /* Check return values */ + assert_se(sd_id128_get_app_specific(SD_ID128_ALLF, SD_ID128_NULL, &id) == -ENXIO); + assert_se(sd_id128_get_app_specific(SD_ID128_NULL, SD_ID128_ALLF, &id) == 0); } TEST(sd_id128_get_invocation) { From 716126c069d8454450914bb2d2917d6367872da7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Sun, 27 Aug 2023 14:56:32 +0300 Subject: [PATCH 11/13] id128: rework conditional to reduce indentation --- src/id128/id128.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/src/id128/id128.c b/src/id128/id128.c index 18e0880805..9e0a3488dd 100644 --- a/src/id128/id128.c +++ b/src/id128/id128.c @@ -93,23 +93,22 @@ static int show_one(Table **table, const char *name, sd_id128_t uuid, bool first if (!first) puts(""); return 0; + } - } else if (arg_value) + if (arg_value) return id128_pretty_print(u, arg_mode); - else { - if (!*table) { - *table = table_new("name", "id"); - if (!*table) - return log_oom(); - table_set_width(*table, 0); - } - - return table_add_many(*table, - TABLE_STRING, name, - arg_mode == ID128_PRINT_ID128 ? TABLE_ID128 : TABLE_UUID, - u); + if (!*table) { + *table = table_new("name", "id"); + if (!*table) + return log_oom(); + table_set_width(*table, 0); } + + return table_add_many(*table, + TABLE_STRING, name, + arg_mode == ID128_PRINT_ID128 ? TABLE_ID128 : TABLE_UUID, + u); } static int verb_show(int argc, char **argv, void *userdata) { From ed856ea15c95f47884d91140137e13a1d603af1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Tue, 29 Aug 2023 14:50:04 +0300 Subject: [PATCH 12/13] TODO: add entry about service and socket units --- TODO | 2 ++ 1 file changed, 2 insertions(+) diff --git a/TODO b/TODO index eda525dc44..260220cb29 100644 --- a/TODO +++ b/TODO @@ -315,6 +315,8 @@ Features: aforementioned journald subscription varlink service, to enable activation-by-message id and similar. +* .service with invalid Sockets= starts successfully. + * landlock: lock down RuntimeDirectory= via landlock, so that services lose ability to write anywehere else below /run/. Similar for StateDirectory=. Benefit would be clear delegation via unit files: services From 437e217a4833e718bae4bd8c12aa0490570bf121 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Tue, 29 Aug 2023 17:23:22 +0300 Subject: [PATCH 13/13] man: add version information I'm keeping this as a separate commit. It is the first time version information is manually added after 6a73a4f7c466887a03c9939300ba6864203b1b3f and we might want to revert this later. --- man/systemd-id128.xml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/man/systemd-id128.xml b/man/systemd-id128.xml index bf71a7c3a8..32226363cb 100644 --- a/man/systemd-id128.xml +++ b/man/systemd-id128.xml @@ -86,7 +86,8 @@ combined with the switch to generate application-specific IDs. See sd_id128_get_machine3 - for the discussion when this is useful. + for the discussion when this is useful. Support for show --app-specific= was added in + version 255. @@ -109,7 +110,9 @@ Only print the value. May be combined with - /. + /. + +