summaryrefslogtreecommitdiff
path: root/src/timesync
diff options
context:
space:
mode:
authorDaniel Mack <daniel@zonque.org>2022-02-24 15:47:35 +0100
committerYu Watanabe <watanabe.yu+github@gmail.com>2022-04-09 10:23:14 +0900
commit57b82eaacaf52b8333ae811cdd1b5445453ebb05 (patch)
treec0c6b471a9a3c3deeef94c050732cbba577e9304 /src/timesync
parentf1b42a0b233e2c711184d93e14550dda76aedb9a (diff)
downloadsystemd-57b82eaacaf52b8333ae811cdd1b5445453ebb05.tar.gz
timesyncd: add RUNTIME servers
This new server type can only be set at runtime through a D-Bus method and is exposed for reading through a D-Bus property. `CAP_NET_ADMIN` and a PolKit acknowledge is required for setting runtime servers. Entries submitted that way are used before system and link servers are being looked at.
Diffstat (limited to 'src/timesync')
-rw-r--r--src/timesync/meson.build2
-rw-r--r--src/timesync/org.freedesktop.timesync1.conf4
-rw-r--r--src/timesync/org.freedesktop.timesync1.policy32
-rw-r--r--src/timesync/timesyncd-bus.c62
-rw-r--r--src/timesync/timesyncd-manager.c37
-rw-r--r--src/timesync/timesyncd-manager.h6
-rw-r--r--src/timesync/timesyncd-server.c5
-rw-r--r--src/timesync/timesyncd-server.h1
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"