summaryrefslogtreecommitdiff
path: root/src/hostname
diff options
context:
space:
mode:
authorYu Watanabe <watanabe.yu+github@gmail.com>2022-01-23 03:12:35 +0900
committerLuca Boccassi <luca.boccassi@gmail.com>2022-01-24 21:09:37 +0000
commit9697662915e47a4797b05003cb1970fe2b01e530 (patch)
tree62cfef6e12b0052fc87562a6834685b867efd012 /src/hostname
parentf338a496e48392929400916ebb0eb9819dec1e2b (diff)
downloadsystemd-9697662915e47a4797b05003cb1970fe2b01e530.tar.gz
hostname: expose hardware serial through dbus
Closes #22119.
Diffstat (limited to 'src/hostname')
-rw-r--r--src/hostname/hostnamed.c89
-rw-r--r--src/hostname/org.freedesktop.hostname1.policy20
2 files changed, 105 insertions, 4 deletions
diff --git a/src/hostname/hostnamed.c b/src/hostname/hostnamed.c
index 8a9a180d63..4637ac8817 100644
--- a/src/hostname/hostnamed.c
+++ b/src/hostname/hostnamed.c
@@ -205,6 +205,33 @@ static int get_hardware_model(char **ret) {
return get_dmi_data("ID_MODEL_FROM_DATABASE", "ID_MODEL", ret);
}
+static int get_hardware_serial(char **ret) {
+ _cleanup_(sd_device_unrefp) sd_device *device = NULL;
+ _cleanup_free_ char *b = NULL;
+ const char *s = NULL;
+ int r;
+
+ r = sd_device_new_from_syspath(&device, "/sys/class/dmi/id");
+ if (r < 0)
+ return log_debug_errno(r, "Failed to open /sys/class/dmi/id device, ignoring: %m");
+
+ (void) sd_device_get_sysattr_value(device, "product_serial", &s);
+ if (isempty(s))
+ /* Fallback to board serial */
+ (void) sd_device_get_sysattr_value(device, "board_serial", &s);
+
+ if (!isempty(s)) {
+ b = strdup(s);
+ if (!b)
+ return -ENOMEM;
+ }
+
+ if (ret)
+ *ret = TAKE_PTR(b);
+
+ return !isempty(s);
+}
+
static const char* valid_chassis(const char *chassis) {
assert(chassis);
@@ -1051,8 +1078,51 @@ static int method_get_product_uuid(sd_bus_message *m, void *userdata, sd_bus_err
return sd_bus_send(NULL, reply, NULL);
}
+static int method_get_hardware_serial(sd_bus_message *m, void *userdata, sd_bus_error *error) {
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+ _cleanup_free_ char *serial = NULL;
+ Context *c = userdata;
+ int interactive, r;
+
+ assert(m);
+ assert(c);
+
+ r = sd_bus_message_read(m, "b", &interactive);
+ if (r < 0)
+ return r;
+
+ r = bus_verify_polkit_async(
+ m,
+ CAP_SYS_ADMIN,
+ "org.freedesktop.hostname1.get-hardware-serial",
+ NULL,
+ interactive,
+ UID_INVALID,
+ &c->polkit_registry,
+ error);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
+
+ r = get_hardware_serial(&serial);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_new_method_return(m, &reply);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_append(reply, "s", serial);
+ if (r < 0)
+ return r;
+
+ return sd_bus_send(NULL, reply, NULL);
+}
+
static int method_describe(sd_bus_message *m, void *userdata, sd_bus_error *error) {
- _cleanup_free_ char *hn = NULL, *dhn = NULL, *in = NULL, *text = NULL, *chassis = NULL, *vendor = NULL, *model = NULL;
+ _cleanup_free_ char *hn = NULL, *dhn = NULL, *in = NULL, *text = NULL,
+ *chassis = NULL, *vendor = NULL, *model = NULL, *serial = NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
_cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
sd_id128_t product_uuid = SD_ID128_NULL;
@@ -1067,7 +1137,7 @@ static int method_describe(sd_bus_message *m, void *userdata, sd_bus_error *erro
r = bus_verify_polkit_async(
m,
CAP_SYS_ADMIN,
- "org.freedesktop.hostname1.get-product-uuid",
+ "org.freedesktop.hostname1.get-description",
NULL,
false,
UID_INVALID,
@@ -1111,8 +1181,11 @@ static int method_describe(sd_bus_message *m, void *userdata, sd_bus_error *erro
if (isempty(c->data[PROP_MODEL]))
(void) get_hardware_model(&model);
- if (privileged) /* The product UUID is only available to privileged clients */
- id128_get_product(&product_uuid);
+ if (privileged) {
+ /* The product UUID and hardware serial is only available to privileged clients */
+ (void) id128_get_product(&product_uuid);
+ (void) get_hardware_serial(&serial);
+ }
r = json_build(&v, JSON_BUILD_OBJECT(
JSON_BUILD_PAIR("Hostname", JSON_BUILD_STRING(hn)),
@@ -1132,6 +1205,7 @@ static int method_describe(sd_bus_message *m, void *userdata, sd_bus_error *erro
JSON_BUILD_PAIR("OperatingSystemHomeURL", JSON_BUILD_STRING(c->data[PROP_OS_HOME_URL])),
JSON_BUILD_PAIR("HardwareVendor", JSON_BUILD_STRING(vendor ?: c->data[PROP_VENDOR])),
JSON_BUILD_PAIR("HardwareModel", JSON_BUILD_STRING(model ?: c->data[PROP_MODEL])),
+ JSON_BUILD_PAIR("HardwareSerial", JSON_BUILD_STRING(serial)),
JSON_BUILD_PAIR_CONDITION(!sd_id128_is_null(product_uuid), "ProductUUID", JSON_BUILD_ID128(product_uuid)),
JSON_BUILD_PAIR_CONDITION(sd_id128_is_null(product_uuid), "ProductUUID", JSON_BUILD_NULL)));
@@ -1229,6 +1303,13 @@ static const sd_bus_vtable hostname_vtable[] = {
SD_BUS_PARAM(uuid),
method_get_product_uuid,
SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_NAMES("GetHardwareSerial",
+ "b",
+ SD_BUS_PARAM(interactive),
+ "s",
+ SD_BUS_PARAM(serial),
+ method_get_hardware_serial,
+ SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD_WITH_ARGS("Describe",
SD_BUS_NO_ARGS,
SD_BUS_RESULT("s", json),
diff --git a/src/hostname/org.freedesktop.hostname1.policy b/src/hostname/org.freedesktop.hostname1.policy
index dacea0ff0a..a86cead53e 100644
--- a/src/hostname/org.freedesktop.hostname1.policy
+++ b/src/hostname/org.freedesktop.hostname1.policy
@@ -57,4 +57,24 @@
</defaults>
</action>
+ <action id="org.freedesktop.hostname1.get-hardware-serial">
+ <description gettext-domain="systemd">Get hardware serial number</description>
+ <message gettext-domain="systemd">Authentication is required to get hardware serial number.</message>
+ <defaults>
+ <allow_any>auth_admin_keep</allow_any>
+ <allow_inactive>auth_admin_keep</allow_inactive>
+ <allow_active>auth_admin_keep</allow_active>
+ </defaults>
+ </action>
+
+ <action id="org.freedesktop.hostname1.get-description">
+ <description gettext-domain="systemd">Get system description</description>
+ <message gettext-domain="systemd">Authentication is required to get system description.</message>
+ <defaults>
+ <allow_any>auth_admin_keep</allow_any>
+ <allow_inactive>auth_admin_keep</allow_inactive>
+ <allow_active>auth_admin_keep</allow_active>
+ </defaults>
+ </action>
+
</policyconfig>