]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/hostname/hostnamed.c
Merge pull request #30284 from YHNdnzj/fstab-wantedby-defaultdeps
[thirdparty/systemd.git] / src / hostname / hostnamed.c
index ea19dfbb0412b397e8158ac133b87424b7ce19ba..893eb4cc0f15be02265cdc8f037419fdea805d62 100644 (file)
@@ -59,6 +59,7 @@ typedef enum {
         PROP_OS_PRETTY_NAME,
         PROP_OS_CPE_NAME,
         PROP_OS_HOME_URL,
+        PROP_OS_SUPPORT_END,
         _PROP_MAX,
         _PROP_INVALID = -EINVAL,
 } HostProperty;
@@ -146,6 +147,7 @@ static void context_read_machine_info(Context *c) {
 }
 
 static void context_read_os_release(Context *c) {
+        _cleanup_free_ char *os_name = NULL, *os_pretty_name = NULL;
         struct stat current_stat = {};
         int r;
 
@@ -159,24 +161,52 @@ static void context_read_os_release(Context *c) {
         context_reset(c,
                       (UINT64_C(1) << PROP_OS_PRETTY_NAME) |
                       (UINT64_C(1) << PROP_OS_CPE_NAME) |
-                      (UINT64_C(1) << PROP_OS_HOME_URL));
+                      (UINT64_C(1) << PROP_OS_HOME_URL) |
+                      (UINT64_C(1) << PROP_OS_SUPPORT_END));
 
         r = parse_os_release(NULL,
-                             "PRETTY_NAME", &c->data[PROP_OS_PRETTY_NAME],
-                             "CPE_NAME", &c->data[PROP_OS_CPE_NAME],
-                             "HOME_URL", &c->data[PROP_OS_HOME_URL]);
+                             "PRETTY_NAME", &os_pretty_name,
+                             "NAME",        &os_name,
+                             "CPE_NAME",    &c->data[PROP_OS_CPE_NAME],
+                             "HOME_URL",    &c->data[PROP_OS_HOME_URL],
+                             "SUPPORT_END", &c->data[PROP_OS_SUPPORT_END]);
         if (r < 0 && r != -ENOENT)
                 log_warning_errno(r, "Failed to read os-release file, ignoring: %m");
 
+        if (free_and_strdup(&c->data[PROP_OS_PRETTY_NAME], os_release_pretty_name(os_pretty_name, os_name)) < 0)
+                log_oom();
+
         c->etc_os_release_stat = current_stat;
 }
 
+static bool use_dmi_data(void) {
+        int r;
+
+        r = getenv_bool("SYSTEMD_HOSTNAME_FORCE_DMI");
+        if (r >= 0) {
+                log_debug("Honouring $SYSTEMD_HOSTNAME_FORCE_DMI override: %s", yes_no(r));
+                return r;
+        }
+        if (r != -ENXIO)
+                log_debug_errno(r, "Failed to parse $SYSTEMD_HOSTNAME_FORCE_DMI, ignoring: %m");
+
+        if (detect_container() > 0) {
+                log_debug("Running in a container, not using DMI hardware data.");
+                return false;
+        }
+
+        return true;
+}
+
 static int get_dmi_data(const char *database_key, const char *regular_key, char **ret) {
         _cleanup_(sd_device_unrefp) sd_device *device = NULL;
         _cleanup_free_ char *b = NULL;
         const char *s = NULL;
         int r;
 
+        if (!use_dmi_data())
+                return -ENOENT;
+
         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");
@@ -215,6 +245,9 @@ static int get_hardware_firmware_data(const char *sysattr, char **ret) {
 
         assert(sysattr);
 
+        if (!use_dmi_data())
+                return -ENOENT;
+
         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");
@@ -250,8 +283,64 @@ static int get_firmware_vendor(char **ret) {
          return get_hardware_firmware_data("bios_vendor", ret);
 }
 
-static int get_firmware_date(char **ret) {
-         return get_hardware_firmware_data("bios_date", ret);
+static int get_firmware_date(usec_t *ret) {
+         _cleanup_free_ char *bios_date = NULL, *month = NULL, *day = NULL, *year = NULL;
+         int r;
+
+         assert(ret);
+
+         r = get_hardware_firmware_data("bios_date", &bios_date);
+         if (r < 0)
+                return r;
+         if (r == 0) {
+                *ret = USEC_INFINITY;
+                return 0;
+         }
+
+         const char *p = bios_date;
+         r = extract_many_words(&p, "/", EXTRACT_DONT_COALESCE_SEPARATORS, &month, &day, &year, NULL);
+         if (r < 0)
+                return r;
+         if (r != 3) /* less than three args read? */
+                return -EINVAL;
+         if (!isempty(p)) /* more left in the string? */
+                return -EINVAL;
+
+         unsigned m, d, y;
+         r = safe_atou_full(month, 10 | SAFE_ATO_REFUSE_PLUS_MINUS | SAFE_ATO_REFUSE_LEADING_WHITESPACE, &m);
+         if (r < 0)
+                return r;
+         if (m < 1 || m > 12)
+                return -EINVAL;
+         m -= 1;
+
+         r = safe_atou_full(day, 10 | SAFE_ATO_REFUSE_PLUS_MINUS | SAFE_ATO_REFUSE_LEADING_WHITESPACE, &d);
+         if (r < 0)
+                return r;
+         if (d < 1 || d > 31)
+                return -EINVAL;
+
+         r = safe_atou_full(year, 10 | SAFE_ATO_REFUSE_PLUS_MINUS | SAFE_ATO_REFUSE_LEADING_WHITESPACE, &y);
+         if (r < 0)
+                return r;
+         if (y < 1970 || y > (unsigned) INT_MAX)
+                return -EINVAL;
+         y -= 1900;
+
+         struct tm tm = {
+                .tm_mday = d,
+                .tm_mon = m,
+                .tm_year = y,
+         };
+         time_t v = timegm(&tm);
+         if (v == (time_t) -1)
+                return -errno;
+         if (tm.tm_mday != (int) d || tm.tm_mon != (int) m || tm.tm_year != (int) y)
+                return -EINVAL; /* date was not normalized? (e.g. "30th of feb") */
+
+         *ret = (usec_t) v * USEC_PER_SEC;
+
+         return 0;
 }
 
 static const char* valid_chassis(const char *chassis) {
@@ -567,7 +656,7 @@ static int context_write_data_machine_info(Context *c) {
                 return 0;
         }
 
-        r = write_env_file_label("/etc/machine-info", l);
+        r = write_env_file_label(AT_FDCWD, "/etc/machine-info", NULL, l);
         if (r < 0)
                 return r;
 
@@ -661,11 +750,11 @@ static int property_get_firmware_date(
                 void *userdata,
                 sd_bus_error *error) {
 
-        _cleanup_free_ char *firmware_date = NULL;
+        usec_t firmware_date = USEC_INFINITY;
 
         (void) get_firmware_date(&firmware_date);
 
-        return sd_bus_message_append(reply, "s", firmware_date);
+        return sd_bus_message_append(reply, "t", firmware_date);
 }
 static int property_get_hostname(
                 sd_bus *bus,
@@ -825,6 +914,26 @@ static int property_get_os_release_field(
         return sd_bus_message_append(reply, "s", *(char**) userdata);
 }
 
+static int property_get_os_support_end(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                void *userdata,
+                sd_bus_error *error) {
+
+        Context *c = userdata;
+        usec_t eol = USEC_INFINITY;
+
+        context_read_os_release(c);
+
+        if (c->data[PROP_OS_SUPPORT_END])
+                (void) os_release_support_ended(c->data[PROP_OS_SUPPORT_END], /* quiet= */ false, &eol);
+
+        return sd_bus_message_append(reply, "t", eol);
+}
+
 static int property_get_icon_name(
                 sd_bus *bus,
                 const char *path,
@@ -886,6 +995,44 @@ static int property_get_uname_field(
         return sd_bus_message_append(reply, "s", (char*) &u + PTR_TO_SIZE(userdata));
 }
 
+static int property_get_machine_id(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                void *userdata,
+                sd_bus_error *error) {
+
+        sd_id128_t id;
+        int r;
+
+        r = sd_id128_get_machine(&id);
+        if (r < 0)
+                return r;
+
+        return bus_property_get_id128(bus, path, interface, property, reply, &id, error);
+}
+
+static int property_get_boot_id(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                void *userdata,
+                sd_bus_error *error) {
+
+        sd_id128_t id;
+        int r;
+
+        r = sd_id128_get_boot(&id);
+        if (r < 0)
+                return r;
+
+        return bus_property_get_id128(bus, path, interface, property, reply, &id, error);
+}
+
 static int method_set_hostname(sd_bus_message *m, void *userdata, sd_bus_error *error) {
         Context *c = ASSERT_PTR(userdata);
         const char *name;
@@ -907,13 +1054,12 @@ static int method_set_hostname(sd_bus_message *m, void *userdata, sd_bus_error *
 
         context_read_etc_hostname(c);
 
-        r = bus_verify_polkit_async(
+        r = bus_verify_polkit_async_full(
                         m,
-                        CAP_SYS_ADMIN,
                         "org.freedesktop.hostname1.set-hostname",
-                        NULL,
+                        /* details= */ NULL,
                         interactive,
-                        UID_INVALID,
+                        /* good_user= */ UID_INVALID,
                         &c->polkit_registry,
                         error);
         if (r < 0)
@@ -954,13 +1100,12 @@ static int method_set_static_hostname(sd_bus_message *m, void *userdata, sd_bus_
         if (name && !hostname_is_valid(name, 0))
                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid static hostname '%s'", name);
 
-        r = bus_verify_polkit_async(
+        r = bus_verify_polkit_async_full(
                         m,
-                        CAP_SYS_ADMIN,
                         "org.freedesktop.hostname1.set-static-hostname",
-                        NULL,
+                        /* details= */ NULL,
                         interactive,
-                        UID_INVALID,
+                        /* good_user= */ UID_INVALID,
                         &c->polkit_registry,
                         error);
         if (r < 0)
@@ -1030,17 +1175,15 @@ static int set_machine_info(Context *c, sd_bus_message *m, int prop, sd_bus_mess
                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid location '%s'", name);
         }
 
-        /* Since the pretty hostname should always be changed at the
-         * same time as the static one, use the same policy action for
-         * both... */
+        /* Since the pretty hostname should always be changed at the same time as the static one, use the
+         * same policy action for both... */
 
-        r = bus_verify_polkit_async(
+        r = bus_verify_polkit_async_full(
                         m,
-                        CAP_SYS_ADMIN,
                         prop == PROP_PRETTY_HOSTNAME ? "org.freedesktop.hostname1.set-static-hostname" : "org.freedesktop.hostname1.set-machine-info",
-                        NULL,
+                        /* details= */ NULL,
                         interactive,
-                        UID_INVALID,
+                        /* good_user= */ UID_INVALID,
                         &c->polkit_registry,
                         error);
         if (r < 0)
@@ -1112,13 +1255,12 @@ static int method_get_product_uuid(sd_bus_message *m, void *userdata, sd_bus_err
         if (r < 0)
                 return r;
 
-        r = bus_verify_polkit_async(
+        r = bus_verify_polkit_async_full(
                         m,
-                        CAP_SYS_ADMIN,
                         "org.freedesktop.hostname1.get-product-uuid",
-                        NULL,
+                        /* details= */ NULL,
                         interactive,
-                        UID_INVALID,
+                        /* good_user= */ UID_INVALID,
                         &c->polkit_registry,
                         error);
         if (r < 0)
@@ -1159,11 +1301,8 @@ static int method_get_hardware_serial(sd_bus_message *m, void *userdata, sd_bus_
 
         r = bus_verify_polkit_async(
                         m,
-                        CAP_SYS_ADMIN,
                         "org.freedesktop.hostname1.get-hardware-serial",
-                        NULL,
-                        false,
-                        UID_INVALID,
+                        /* details= */ NULL,
                         &c->polkit_registry,
                         error);
         if (r < 0)
@@ -1189,10 +1328,11 @@ static int method_get_hardware_serial(sd_bus_message *m, void *userdata, sd_bus_
 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, *serial = NULL, *firmware_version = NULL,
-                *firmware_vendor = NULL, *firmware_date = NULL;
+                *firmware_vendor = NULL;
+        usec_t firmware_date = USEC_INFINITY, eol = USEC_INFINITY;
         _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;
+        sd_id128_t machine_id, boot_id, product_uuid = SD_ID128_NULL;
         Context *c = ASSERT_PTR(userdata);
         bool privileged;
         struct utsname u;
@@ -1202,13 +1342,10 @@ 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-description",
-                        NULL,
-                        false,
-                        UID_INVALID,
+                        /* details= */ NULL,
                         &c->polkit_registry,
-                        NULL);
+                        error);
         if (r == 0)
                 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
 
@@ -1256,6 +1393,17 @@ static int method_describe(sd_bus_message *m, void *userdata, sd_bus_error *erro
         (void) get_firmware_vendor(&firmware_vendor);
         (void) get_firmware_date(&firmware_date);
 
+        if (c->data[PROP_OS_SUPPORT_END])
+                (void) os_release_support_ended(c->data[PROP_OS_SUPPORT_END], /* quiet= */ false, &eol);
+
+        r = sd_id128_get_machine(&machine_id);
+        if (r < 0)
+                return log_error_errno(r, "Failed to get machine ID: %m");
+
+        r = sd_id128_get_boot(&boot_id);
+        if (r < 0)
+                return log_error_errno(r, "Failed to get boot ID: %m");
+
         r = json_build(&v, JSON_BUILD_OBJECT(
                                        JSON_BUILD_PAIR("Hostname", JSON_BUILD_STRING(hn)),
                                        JSON_BUILD_PAIR("StaticHostname", JSON_BUILD_STRING(c->data[PROP_STATIC_HOSTNAME])),
@@ -1272,12 +1420,15 @@ static int method_describe(sd_bus_message *m, void *userdata, sd_bus_error *erro
                                        JSON_BUILD_PAIR("OperatingSystemPrettyName", JSON_BUILD_STRING(c->data[PROP_OS_PRETTY_NAME])),
                                        JSON_BUILD_PAIR("OperatingSystemCPEName", JSON_BUILD_STRING(c->data[PROP_OS_CPE_NAME])),
                                        JSON_BUILD_PAIR("OperatingSystemHomeURL", JSON_BUILD_STRING(c->data[PROP_OS_HOME_URL])),
+                                       JSON_BUILD_PAIR_FINITE_USEC("OperatingSystemSupportEnd", eol),
                                        JSON_BUILD_PAIR("HardwareVendor", JSON_BUILD_STRING(vendor ?: c->data[PROP_HARDWARE_VENDOR])),
                                        JSON_BUILD_PAIR("HardwareModel", JSON_BUILD_STRING(model ?: c->data[PROP_HARDWARE_MODEL])),
                                        JSON_BUILD_PAIR("HardwareSerial", JSON_BUILD_STRING(serial)),
                                        JSON_BUILD_PAIR("FirmwareVersion", JSON_BUILD_STRING(firmware_version)),
                                        JSON_BUILD_PAIR("FirmwareVendor", JSON_BUILD_STRING(firmware_vendor)),
-                                       JSON_BUILD_PAIR("FirmwareDate", JSON_BUILD_STRING(firmware_date)),
+                                       JSON_BUILD_PAIR_FINITE_USEC("FirmwareDate", firmware_date),
+                                       JSON_BUILD_PAIR_ID128("MachineID", machine_id),
+                                       JSON_BUILD_PAIR_ID128("BootID", boot_id),
                                        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)));
 
@@ -1315,12 +1466,15 @@ static const sd_bus_vtable hostname_vtable[] = {
         SD_BUS_PROPERTY("KernelVersion", "s", property_get_uname_field, offsetof(struct utsname, version), SD_BUS_VTABLE_ABSOLUTE_OFFSET|SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("OperatingSystemPrettyName", "s", property_get_os_release_field, offsetof(Context, data) + sizeof(char*) * PROP_OS_PRETTY_NAME, SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("OperatingSystemCPEName", "s", property_get_os_release_field, offsetof(Context, data) + sizeof(char*) * PROP_OS_CPE_NAME, SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("OperatingSystemSupportEnd", "t", property_get_os_support_end, 0, SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("HomeURL", "s", property_get_os_release_field, offsetof(Context, data) + sizeof(char*) * PROP_OS_HOME_URL, SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("HardwareVendor", "s", property_get_hardware_vendor, 0, SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("HardwareModel", "s", property_get_hardware_model, 0, SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("FirmwareVersion", "s", property_get_firmware_version, 0, SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("FirmwareVendor", "s", property_get_firmware_vendor, 0, SD_BUS_VTABLE_PROPERTY_CONST),
-        SD_BUS_PROPERTY("FirmwareDate", "s", property_get_firmware_date, 0, SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("FirmwareDate", "t", property_get_firmware_date, 0, SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("MachineID", "ay", property_get_machine_id, 0, SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("BootID", "ay", property_get_boot_id, 0, SD_BUS_VTABLE_PROPERTY_CONST),
 
         SD_BUS_METHOD_WITH_ARGS("SetHostname",
                                 SD_BUS_ARGS("s", hostname, "b", interactive),
@@ -1434,7 +1588,7 @@ static int run(int argc, char *argv[]) {
 
         umask(0022);
 
-        r = mac_selinux_init();
+        r = mac_init();
         if (r < 0)
                 return r;