diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/timesync/meson.build | 2 | ||||
-rw-r--r-- | src/timesync/org.freedesktop.timesync1.conf | 4 | ||||
-rw-r--r-- | src/timesync/org.freedesktop.timesync1.policy | 32 | ||||
-rw-r--r-- | src/timesync/timesyncd-bus.c | 62 | ||||
-rw-r--r-- | src/timesync/timesyncd-manager.c | 37 | ||||
-rw-r--r-- | src/timesync/timesyncd-manager.h | 6 | ||||
-rw-r--r-- | src/timesync/timesyncd-server.c | 5 | ||||
-rw-r--r-- | src/timesync/timesyncd-server.h | 1 |
8 files changed, 139 insertions, 10 deletions
diff --git a/src/timesync/meson.build b/src/timesync/meson.build index 35467026a8..15ca7d2fd5 100644 --- a/src/timesync/meson.build +++ b/src/timesync/meson.build @@ -50,6 +50,8 @@ if conf.get('ENABLE_TIMESYNCD') == 1 install_dir : dbussystemservicedir) install_data('80-systemd-timesync.list', install_dir : ntpservicelistdir) + install_data('org.freedesktop.timesync1.policy', + install_dir : polkitpolicydir) endif ############################################################ diff --git a/src/timesync/org.freedesktop.timesync1.conf b/src/timesync/org.freedesktop.timesync1.conf index eccdbec718..8c74b36d6e 100644 --- a/src/timesync/org.freedesktop.timesync1.conf +++ b/src/timesync/org.freedesktop.timesync1.conf @@ -36,6 +36,10 @@ send_interface="org.freedesktop.DBus.Properties" send_member="GetAll"/> + <allow send_destination="org.freedesktop.timesync1" + send_interface="org.freedesktop.timesync1.Manager" + send_member="SetRuntimeNTPServers"/> + <allow receive_sender="org.freedesktop.timesync1"/> </policy> diff --git a/src/timesync/org.freedesktop.timesync1.policy b/src/timesync/org.freedesktop.timesync1.policy new file mode 100644 index 0000000000..e13e8df829 --- /dev/null +++ b/src/timesync/org.freedesktop.timesync1.policy @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> <!--*-nxml-*--> +<!DOCTYPE policyconfig PUBLIC "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN" + "http://www.freedesktop.org/standards/PolicyKit/1/policyconfig.dtd"> + +<!-- + SPDX-License-Identifier: LGPL-2.1-or-later + + This file is part of systemd. + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. +--> + +<policyconfig> + + <vendor>The systemd Project</vendor> + <vendor_url>https://systemd.io</vendor_url> + + <action id="org.freedesktop.timesync1.set-runtime-servers"> + <description gettext-domain="systemd">Set runtime NTP servers</description> + <message gettext-domain="systemd">Authentication is required to set runtime NTP servers.</message> + <defaults> + <allow_any>auth_admin</allow_any> + <allow_inactive>auth_admin</allow_inactive> + <allow_active>auth_admin_keep</allow_active> + </defaults> + <annotate key="org.freedesktop.policykit.owner">unix-user:systemd-timesync</annotate> + </action> + +</policyconfig> diff --git a/src/timesync/timesyncd-bus.c b/src/timesync/timesyncd-bus.c index b738dfd3cc..7b929d9347 100644 --- a/src/timesync/timesyncd-bus.c +++ b/src/timesync/timesyncd-bus.c @@ -1,18 +1,24 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ +#include <sys/capability.h> + #include "sd-bus.h" #include "alloc-util.h" #include "bus-get-properties.h" #include "bus-internal.h" #include "bus-log-control-api.h" +#include "bus-polkit.h" #include "bus-protocol.h" #include "bus-util.h" +#include "dns-domain.h" #include "in-addr-util.h" #include "log.h" #include "macro.h" +#include "strv.h" #include "time-util.h" #include "timesyncd-bus.h" +#include "user-util.h" static int property_get_servers( sd_bus *bus, @@ -43,6 +49,54 @@ static int property_get_servers( return sd_bus_message_close_container(reply); } +static int method_set_runtime_servers(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_strv_free_ char **msg_names = NULL; + Manager *m = userdata; + int r; + + assert(m); + assert(message); + + r = sd_bus_message_read_strv(message, &msg_names); + if (r < 0) + return r; + + STRV_FOREACH(name, msg_names) { + r = dns_name_is_valid_or_address(*name); + if (r < 0) + return log_error_errno(r, "Failed to check validity of NTP server name or address '%s': %m", *name); + if (r == 0) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid NTP server name or address, refusing: %s", *name); + } + + r = bus_verify_polkit_async(message, CAP_NET_ADMIN, + "org.freedesktop.timesync1.set-runtime-servers", + NULL, true, UID_INVALID, + &m->polkit_registry, error); + if (r < 0) + return r; + if (r == 0) + /* Polkit will call us back */ + return 1; + + manager_flush_runtime_servers(m); + + STRV_FOREACH(name, msg_names) { + r = server_name_new(m, NULL, SERVER_RUNTIME, *name); + if (r < 0) { + manager_flush_runtime_servers(m); + + return log_error_errno(r, "Failed to add runtime server '%s': %m", *name); + } + } + + m->exhausted_servers = true; + manager_set_server_name(m, NULL); + (void) manager_connect(m); + + return sd_bus_reply_method_return(message, NULL); +} + static int property_get_current_server_name( sd_bus *bus, const char *path, @@ -162,6 +216,7 @@ static const sd_bus_vtable manager_vtable[] = { SD_BUS_PROPERTY("LinkNTPServers", "as", property_get_servers, offsetof(Manager, link_servers), 0), SD_BUS_PROPERTY("SystemNTPServers", "as", property_get_servers, offsetof(Manager, system_servers), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("RuntimeNTPServers", "as", property_get_servers, offsetof(Manager, runtime_servers), 0), SD_BUS_PROPERTY("FallbackNTPServers", "as", property_get_servers, offsetof(Manager, fallback_servers), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("ServerName", "s", property_get_current_server_name, offsetof(Manager, current_server_name), 0), SD_BUS_PROPERTY("ServerAddress", "(iay)", property_get_current_server_address, offsetof(Manager, current_server_address), 0), @@ -172,6 +227,13 @@ static const sd_bus_vtable manager_vtable[] = { SD_BUS_PROPERTY("NTPMessage", "(uuuuittayttttbtt)", property_get_ntp_message, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("Frequency", "x", NULL, offsetof(Manager, drift_freq), 0), + SD_BUS_METHOD_WITH_NAMES("SetRuntimeNTPServers", + "as", + SD_BUS_PARAM(runtime_servers), + NULL,, + method_set_runtime_servers, + SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_VTABLE_END }; diff --git a/src/timesync/timesyncd-manager.c b/src/timesync/timesyncd-manager.c index ee2b24e2b1..40fd4d3464 100644 --- a/src/timesync/timesyncd-manager.c +++ b/src/timesync/timesyncd-manager.c @@ -14,6 +14,7 @@ #include "sd-messages.h" #include "alloc-util.h" +#include "bus-polkit.h" #include "dns-domain.h" #include "event-util.h" #include "fd-util.h" @@ -825,22 +826,25 @@ int manager_connect(Manager *m) { bool restart = true; /* Our current server name list is exhausted, - * let's find the next one to iterate. First - * we try the system list, then the link list. - * After having processed the link list we - * jump back to the system list. However, if - * both lists are empty, we change to the - * fallback list. */ + * let's find the next one to iterate. First we try the runtime list, then the system list, + * then the link list. After having processed the link list we jump back to the system list + * if no runtime server list. + * However, if all lists are empty, we change to the fallback list. */ if (!m->current_server_name || m->current_server_name->type == SERVER_LINK) { - f = m->system_servers; + f = m->runtime_servers; + if (!f) + f = m->system_servers; if (!f) f = m->link_servers; } else { f = m->link_servers; - if (!f) - f = m->system_servers; - else + if (f) restart = false; + else { + f = m->runtime_servers; + if (!f) + f = m->system_servers; + } } if (!f) @@ -925,6 +929,16 @@ void manager_flush_server_names(Manager *m, ServerType t) { if (t == SERVER_FALLBACK) while (m->fallback_servers) server_name_free(m->fallback_servers); + + if (t == SERVER_RUNTIME) + manager_flush_runtime_servers(m); +} + +void manager_flush_runtime_servers(Manager *m) { + assert(m); + + while (m->runtime_servers) + server_name_free(m->runtime_servers); } Manager* manager_free(Manager *m) { @@ -934,6 +948,7 @@ Manager* manager_free(Manager *m) { manager_disconnect(m); manager_flush_server_names(m, SERVER_SYSTEM); manager_flush_server_names(m, SERVER_LINK); + manager_flush_server_names(m, SERVER_RUNTIME); manager_flush_server_names(m, SERVER_FALLBACK); sd_event_source_unref(m->event_retry); @@ -948,6 +963,8 @@ Manager* manager_free(Manager *m) { sd_bus_flush_close_unref(m->bus); + bus_verify_polkit_async_registry_free(m->polkit_registry); + return mfree(m); } diff --git a/src/timesync/timesyncd-manager.h b/src/timesync/timesyncd-manager.h index f9d6567bdb..e595c7ddfc 100644 --- a/src/timesync/timesyncd-manager.h +++ b/src/timesync/timesyncd-manager.h @@ -8,6 +8,7 @@ #include "sd-network.h" #include "sd-resolve.h" +#include "hashmap.h" #include "list.h" #include "ratelimit.h" #include "time-util.h" @@ -41,6 +42,7 @@ struct Manager { LIST_HEAD(ServerName, system_servers); LIST_HEAD(ServerName, link_servers); + LIST_HEAD(ServerName, runtime_servers); LIST_HEAD(ServerName, fallback_servers); bool have_fallbacks:1; @@ -63,6 +65,9 @@ struct Manager { sd_event_source *event_timeout; bool talking; + /* PolicyKit */ + Hashmap *polkit_registry; + /* last sent packet */ struct timespec trans_time_mon; struct timespec trans_time; @@ -121,6 +126,7 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free); void manager_set_server_name(Manager *m, ServerName *n); void manager_set_server_address(Manager *m, ServerAddress *a); void manager_flush_server_names(Manager *m, ServerType t); +void manager_flush_runtime_servers(Manager *m); int manager_connect(Manager *m); void manager_disconnect(Manager *m); diff --git a/src/timesync/timesyncd-server.c b/src/timesync/timesyncd-server.c index dd16891734..002a6117cc 100644 --- a/src/timesync/timesyncd-server.c +++ b/src/timesync/timesyncd-server.c @@ -85,6 +85,9 @@ int server_name_new( } else if (type == SERVER_FALLBACK) { LIST_FIND_TAIL(names, m->fallback_servers, tail); LIST_INSERT_AFTER(names, m->fallback_servers, tail, n); + } else if (type == SERVER_RUNTIME) { + LIST_FIND_TAIL(names, m->runtime_servers, tail); + LIST_INSERT_AFTER(names, m->runtime_servers, tail, n); } else assert_not_reached(); @@ -114,6 +117,8 @@ ServerName *server_name_free(ServerName *n) { LIST_REMOVE(names, n->manager->link_servers, n); else if (n->type == SERVER_FALLBACK) LIST_REMOVE(names, n->manager->fallback_servers, n); + else if (n->type == SERVER_RUNTIME) + LIST_REMOVE(names, n->manager->runtime_servers, n); else assert_not_reached(); diff --git a/src/timesync/timesyncd-server.h b/src/timesync/timesyncd-server.h index 8e9e408ecc..ca994bf6ae 100644 --- a/src/timesync/timesyncd-server.h +++ b/src/timesync/timesyncd-server.h @@ -11,6 +11,7 @@ typedef enum ServerType { SERVER_SYSTEM, SERVER_FALLBACK, SERVER_LINK, + SERVER_RUNTIME, } ServerType; #include "timesyncd-manager.h" |