Auto sync2gitlab import of chrony-4.1-1.el8.src.rpm

This commit is contained in:
James Antill 2022-05-26 01:07:53 -04:00
parent f68ea09d12
commit d8bd1eecb1
12 changed files with 1714 additions and 1 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
/chrony-4.1.tar.gz
/clknetsim-f89702.tar.gz

1
EMPTY
View File

@ -1 +0,0 @@

29
chrony-defconfig.patch Normal file
View File

@ -0,0 +1,29 @@
diff -up chrony-4.1/examples/chrony.conf.example2.defconfig chrony-4.1/examples/chrony.conf.example2
--- chrony-4.1/examples/chrony.conf.example2.defconfig 2021-05-12 13:06:15.000000000 +0200
+++ chrony-4.1/examples/chrony.conf.example2 2019-05-10 12:22:57.000000000 +0200
@@ -1,5 +1,5 @@
# Use public servers from the pool.ntp.org project.
-# Please consider joining the pool (https://www.pool.ntp.org/join.html).
+# Please consider joining the pool (http://www.pool.ntp.org/join.html).
pool pool.ntp.org iburst
# Record the rate at which the system clock gains/losses time.
@@ -25,18 +25,9 @@ rtcsync
# Serve time even if not synchronized to a time source.
#local stratum 10
-# Require authentication (nts or key option) for all NTP sources.
-#authselectmode require
-
# Specify file containing keys for NTP authentication.
#keyfile /etc/chrony.keys
-# Save NTS keys and cookies.
-ntsdumpdir /var/lib/chrony
-
-# Insert/delete leap seconds by slewing instead of stepping.
-#leapsecmode slew
-
# Get TAI-UTC offset and leap seconds from the system tz database.
#leapsectz right/UTC

8
chrony-dnssrv@.service Normal file
View File

@ -0,0 +1,8 @@
[Unit]
Description=DNS SRV lookup of %I for chrony
After=chronyd.service network-online.target
Wants=network-online.target
[Service]
Type=oneshot
ExecStart=/usr/libexec/chrony-helper update-dnssrv-servers %I

9
chrony-dnssrv@.timer Normal file
View File

@ -0,0 +1,9 @@
[Unit]
Description=Periodic DNS SRV lookup of %I for chrony
[Timer]
OnActiveSec=0
OnUnitInactiveSec=1h
[Install]
WantedBy=timers.target

View File

@ -0,0 +1,100 @@
From: Robert Fairley <rfairley@redhat.com>
Date: Wed, 17 Jun 2020 10:14:19 -0400
Subject: [PATCH] examples/nm-dispatcher.dhcp: use sysconfig
Use the PEERNTP and NTPSERVERARGS environment variables from
/etc/sysconfig/network{-scripts}.
Co-Authored-By: Christian Glombek <cglombek@redhat.com>
diff --git a/examples/chrony.nm-dispatcher.dhcp b/examples/chrony.nm-dispatcher.dhcp
index 6ea4c37..a6ad35a 100644
--- a/examples/chrony.nm-dispatcher.dhcp
+++ b/examples/chrony.nm-dispatcher.dhcp
@@ -6,16 +6,24 @@
chronyc=/usr/bin/chronyc
default_server_options=iburst
-server_dir=/var/run/chrony-dhcp
+server_dir=/run/chrony-dhcp
dhcp_server_file=$server_dir/$interface.sources
# DHCP4_NTP_SERVERS is passed from DHCP options by NetworkManager.
nm_dhcp_servers=$DHCP4_NTP_SERVERS
+[ -f /etc/sysconfig/network ] && . /etc/sysconfig/network
+[ -f /etc/sysconfig/network-scripts/ifcfg-"${interface}" ] && \
+ . /etc/sysconfig/network-scripts/ifcfg-"${interface}"
+
add_servers_from_dhcp() {
rm -f "$dhcp_server_file"
+
+ # Don't add NTP servers if PEERNTP=no specified; return early.
+ [ "$PEERNTP" = "no" ] && return
+
for server in $nm_dhcp_servers; do
- echo "server $server $default_server_options" >> "$dhcp_server_file"
+ echo "server $server ${NTPSERVERARGS:-$default_server_options}" >> "$dhcp_server_file"
done
$chronyc reload sources > /dev/null 2>&1 || :
}
--
2.29.2
Use chrony-helper instead of chronyc to avoid changes in default chrony.conf
diff -up chrony-4.1/examples/chrony.nm-dispatcher.dhcp.nm-dispatcher-dhcp chrony-4.1/examples/chrony.nm-dispatcher.dhcp
--- chrony-4.1/examples/chrony.nm-dispatcher.dhcp.nm-dispatcher-dhcp 2021-06-09 11:10:30.997416152 +0200
+++ chrony-4.1/examples/chrony.nm-dispatcher.dhcp 2021-06-09 11:16:23.598381336 +0200
@@ -9,11 +9,12 @@ export LC_ALL=C
interface=$1
action=$2
-chronyc=/usr/bin/chronyc
+helper=/usr/libexec/chrony-helper
default_server_options=iburst
-server_dir=/run/chrony-dhcp
+server_dir=/run/chrony-helper
-dhcp_server_file=$server_dir/$interface.sources
+dhcp_server_tmpfile=$server_dir/tmp-nm-dhcp.$interface
+dhcp_server_file=$server_dir/nm-dhcp.$interface
# DHCP4_NTP_SERVERS is passed from DHCP options by NetworkManager.
nm_dhcp_servers=$DHCP4_NTP_SERVERS
@@ -24,24 +24,30 @@ nm_dhcp_servers=$DHCP4_NTP_SERVERS
add_servers_from_dhcp() {
rm -f "$dhcp_server_file"
+ # Remove servers saved by the dhclient script before it detected NM.
+ rm -f "/var/lib/dhclient/chrony.servers.$interface"
+
# Don't add NTP servers if PEERNTP=no specified; return early.
[ "$PEERNTP" = "no" ] && return
+ # Create the directory with correct SELinux context.
+ $helper create-helper-directory > /dev/null 2>&1
+
for server in $nm_dhcp_servers; do
- echo "server $server ${NTPSERVERARGS:-$default_server_options}" >> "$dhcp_server_file"
+ echo "$server ${NTPSERVERARGS:-$default_server_options}" >> "$dhcp_server_tmpfile"
done
+ [ -e "$dhcp_server_tmpfile" ] && mv "$dhcp_server_tmpfile" "$dhcp_server_file"
- $chronyc reload sources > /dev/null 2>&1 || :
+
+ $helper update-daemon > /dev/null 2>&1 || :
}
clear_servers_from_dhcp() {
if [ -f "$dhcp_server_file" ]; then
rm -f "$dhcp_server_file"
- $chronyc reload sources > /dev/null 2>&1 || :
+ $helper update-daemon > /dev/null 2>&1 || :
fi
}
-mkdir -p $server_dir
-
if [ "$action" = "up" ] || [ "$action" = "dhcp4-change" ]; then
add_servers_from_dhcp
elif [ "$action" = "down" ]; then

View File

@ -0,0 +1,12 @@
diff -up chrony-4.1/examples/chronyd.service.service-helper chrony-4.1/examples/chronyd.service
--- chrony-4.1/examples/chronyd.service.service-helper 2021-05-12 13:06:15.000000000 +0200
+++ chrony-4.1/examples/chronyd.service 2021-06-15 09:01:56.948968576 +0200
@@ -10,6 +10,8 @@ Type=forking
PIDFile=/run/chrony/chronyd.pid
EnvironmentFile=-/etc/sysconfig/chronyd
ExecStart=/usr/sbin/chronyd $OPTIONS
+ExecStartPost=/usr/libexec/chrony-helper update-daemon
+ExecStopPost=/usr/libexec/chrony-helper remove-daemon-state
PrivateTmp=yes
ProtectHome=yes
ProtectSystem=full

25
chrony.dhclient Normal file
View File

@ -0,0 +1,25 @@
#!/bin/bash
SERVERFILE=$SAVEDIR/chrony.servers.$interface
chrony_config() {
# Disable modifications if called from a NM dispatcher script
[ -n "$NM_DISPATCHER_ACTION" ] && return 0
rm -f "$SERVERFILE"
if [ "$PEERNTP" != "no" ]; then
for server in $new_ntp_servers; do
echo "$server ${NTPSERVERARGS:-iburst}" >> "$SERVERFILE"
done
/usr/libexec/chrony-helper update-daemon || :
fi
}
chrony_restore() {
[ -n "$NM_DISPATCHER_ACTION" ] && return 0
if [ -f "$SERVERFILE" ]; then
rm -f "$SERVERFILE"
/usr/libexec/chrony-helper update-daemon || :
fi
}

279
chrony.helper Normal file
View File

@ -0,0 +1,279 @@
#!/bin/bash
# This script configures running chronyd to use NTP servers obtained from
# DHCP and _ntp._udp DNS SRV records. Files with servers from DHCP are managed
# externally (e.g. by a dhclient script). Files with servers from DNS SRV
# records are updated here using the dig utility. The script can also list
# and set static sources in the chronyd configuration file.
chronyc=/usr/bin/chronyc
chrony_conf=/etc/chrony.conf
chrony_service=chronyd.service
helper_dir=/run/chrony-helper
added_servers_file=$helper_dir/added_servers
network_sysconfig_file=/etc/sysconfig/network
nm_servers_files="$helper_dir/nm-dhcp.*"
dhclient_servers_files="/var/lib/dhclient/chrony.servers.*"
dnssrv_servers_files="$helper_dir/dnssrv@*"
dnssrv_timer_prefix=chrony-dnssrv@
. $network_sysconfig_file &> /dev/null
chrony_command() {
$chronyc -a -n -m "$1"
}
is_running() {
chrony_command "tracking" &> /dev/null
}
get_servers_files() {
[ "$PEERNTP" != "no" ] && echo "$nm_servers_files"
[ "$PEERNTP" != "no" ] && echo "$dhclient_servers_files"
echo "$dnssrv_servers_files"
}
is_update_needed() {
for file in $(get_servers_files) $added_servers_file; do
[ -e "$file" ] && return 0
done
return 1
}
remove_daemon_state() {
rm -f $added_servers_file
}
update_daemon() {
local all_servers_with_args all_servers added_servers
if ! is_running; then
remove_daemon_state
return 0
fi
all_servers_with_args=$(cat $(get_servers_files) 2> /dev/null)
all_servers=$(
echo "$all_servers_with_args" |
while read -r server serverargs; do
echo "$server"
done | sort -u)
added_servers=$( (
cat $added_servers_file 2> /dev/null
echo "$all_servers_with_args" |
while read -r server serverargs; do
[ -z "$server" ] && continue
chrony_command "add server $server $serverargs" &> /dev/null &&
echo "$server"
done) | sort -u)
comm -23 <(echo -n "$added_servers") <(echo -n "$all_servers") |
while read -r server; do
chrony_command "delete $server" &> /dev/null
done
added_servers=$(comm -12 <(echo -n "$added_servers") <(echo -n "$all_servers"))
if [ -n "$added_servers" ]; then
echo "$added_servers" > $added_servers_file
else
rm -f $added_servers_file
fi
}
get_dnssrv_servers() {
local name=$1 output
if ! command -v dig &> /dev/null; then
echo "Missing dig (DNS lookup utility)" >&2
return 1
fi
output=$(dig "$name" srv +short +ndots=2 +search 2> /dev/null) || return 0
echo "$output" | while read -r _ _ port target; do
server=${target%.}
[ -z "$server" ] && continue
echo "$server port $port ${NTPSERVERARGS:-iburst}"
done
}
check_dnssrv_name() {
local name=$1
if [ -z "$name" ]; then
echo "No DNS SRV name specified" >&2
return 1
fi
if [ "${name:0:9}" != _ntp._udp ]; then
echo "DNS SRV name $name doesn't start with _ntp._udp" >&2
return 1
fi
}
update_dnssrv_servers() {
local name=$1
local srv_file=$helper_dir/dnssrv@$name servers
check_dnssrv_name "$name" || return 1
servers=$(get_dnssrv_servers "$name")
if [ -n "$servers" ]; then
echo "$servers" > "$srv_file"
else
rm -f "$srv_file"
fi
}
set_dnssrv_timer() {
local state=$1 name=$2
local srv_file=$helper_dir/dnssrv@$name servers
local timer
timer=$dnssrv_timer_prefix$(systemd-escape "$name").timer || return 1
check_dnssrv_name "$name" || return 1
if [ "$state" = enable ]; then
systemctl enable "$timer"
systemctl start "$timer"
elif [ "$state" = disable ]; then
systemctl stop "$timer"
systemctl disable "$timer"
rm -f "$srv_file"
fi
}
list_dnssrv_timers() {
systemctl --all --full -t timer list-units | grep "^$dnssrv_timer_prefix" | \
sed "s|^$dnssrv_timer_prefix\(.*\)\.timer.*|\1|" |
while read -r name; do
systemd-escape --unescape "$name"
done
}
prepare_helper_dir() {
mkdir -p $helper_dir
exec 100> $helper_dir/lock
if ! flock -w 20 100; then
echo "Failed to lock $helper_dir" >&2
return 1
fi
}
is_source_line() {
local pattern="^[ \t]*(server|pool|peer|refclock)[ \t]+[^ \t]+"
[[ "$1" =~ $pattern ]]
}
list_static_sources() {
while read -r line; do
if is_source_line "$line"; then
echo "$line"
fi
done < $chrony_conf
}
set_static_sources() {
local new_config tmp_conf
new_config=$(
sources=$(
while read -r line; do
is_source_line "$line" && echo "$line"
done)
while read -r line; do
if ! is_source_line "$line"; then
echo "$line"
continue
fi
tmp_sources=$(
local removed=0
echo "$sources" | while read -r line2; do
if [ "$removed" -ne 0 ] || [ "$line" != "$line2" ]; then
echo "$line2"
else
removed=1
fi
done)
[ "$sources" == "$tmp_sources" ] && continue
sources=$tmp_sources
echo "$line"
done < $chrony_conf
echo "$sources"
)
tmp_conf=${chrony_conf}.tmp
cp -a $chrony_conf $tmp_conf &&
echo "$new_config" > $tmp_conf &&
mv $tmp_conf $chrony_conf || return 1
systemctl try-restart $chrony_service
}
print_help() {
echo "Usage: $0 COMMAND"
echo
echo "Commands:"
echo " create-helper-directory"
echo " update-daemon"
echo " remove-daemon-state"
echo " update-dnssrv-servers NAME"
echo " enable-dnssrv NAME"
echo " disable-dnssrv NAME"
echo " list-dnssrv"
echo " list-static-sources"
echo " set-static-sources < sources.list"
echo " is-running"
echo " command CHRONYC-COMMAND"
}
case "$1" in
create-helper-directory)
prepare_helper_dir
;;
update-daemon|add-dhclient-servers|remove-dhclient-servers)
is_update_needed || exit 0
prepare_helper_dir && update_daemon
;;
remove-daemon-state)
remove_daemon_state
;;
update-dnssrv-servers)
prepare_helper_dir && update_dnssrv_servers "$2" && update_daemon
;;
enable-dnssrv)
set_dnssrv_timer enable "$2"
;;
disable-dnssrv)
set_dnssrv_timer disable "$2" && prepare_helper_dir && update_daemon
;;
list-dnssrv)
list_dnssrv_timers
;;
list-static-sources)
list_static_sources
;;
set-static-sources)
set_static_sources
;;
is-running)
is_running
;;
command|forced-command)
chrony_command "$2"
;;
*)
print_help
exit 2
esac
exit $?

577
chrony.spec Normal file
View File

@ -0,0 +1,577 @@
%global _hardened_build 1
%global clknetsim_ver f89702
%global ntp2chrony_ver 2a0512
%bcond_without debug
%bcond_without nts
Name: chrony
Version: 4.1
Release: 1%{?dist}
Summary: An NTP client/server
Group: System Environment/Daemons
License: GPLv2
URL: https://chrony.tuxfamily.org
Source0: https://download.tuxfamily.org/chrony/chrony-%{version}%{?prerelease}.tar.gz
Source1: chrony.dhclient
Source2: chrony.helper
Source3: chrony-dnssrv@.service
Source4: chrony-dnssrv@.timer
# simulator for test suite
Source10: https://github.com/mlichvar/clknetsim/archive/%{clknetsim_ver}/clknetsim-%{clknetsim_ver}.tar.gz
# script for converting ntp configuration to chrony
Source11: https://github.com/mlichvar/ntp2chrony/raw/%{ntp2chrony_ver}/ntp2chrony/ntp2chrony.py
%{?gitpatch:Patch0: chrony-%{version}%{?prerelease}-%{gitpatch}.patch.gz}
# modify NetworkManager DHCP dispatcher to work with chrony-helper and
# follow distribution-specific configuration
Patch1: chrony-nm-dispatcher-dhcp.patch
# add NTP servers from DHCP when starting service
Patch2: chrony-service-helper.patch
# revert upstream changes in packaged chrony.conf example
Patch3: chrony-defconfig.patch
BuildRequires: libcap-devel libedit-devel nettle-devel pps-tools-devel
%ifarch %{ix86} x86_64 %{arm} aarch64 mipsel mips64el ppc64 ppc64le s390 s390x
BuildRequires: libseccomp-devel
%endif
BuildRequires: gcc gcc-c++ make bison systemd
BuildRequires: kernel-headers > 4.18.0-87
%{?with_nts:BuildRequires: gnutls-devel gnutls-utils}
Requires(pre): shadow-utils
%{?systemd_requires}
# install timedated implementation that can control chronyd service
Recommends: timedatex
# suggest drivers for hardware reference clocks
Suggests: ntp-refclock
%description
chrony is a versatile implementation of the Network Time Protocol (NTP).
It can synchronise the system clock with NTP servers, reference clocks
(e.g. GPS receiver), and manual input using wristwatch and keyboard. It
can also operate as an NTPv4 (RFC 5905) server and peer to provide a time
service to other computers in the network.
%if 0%{!?vendorzone:1}
%global vendorzone %(source /etc/os-release && echo ${ID}.)
%endif
%prep
%setup -q -n %{name}-%{version}%{?prerelease} -a 10
%{?gitpatch:%patch0 -p1}
%patch1 -p1 -b .nm-dispatcher-dhcp
%patch2 -p1 -b .service-helper
%patch3 -p1 -b .defconfig
%{?gitpatch: echo %{version}-%{gitpatch} > version.txt}
# review changes in packaged configuration files and scripts
md5sum -c <<-EOF | (! grep -v 'OK$')
bc563c1bcf67b2da774bd8c2aef55a06 examples/chrony-wait.service
e473a9fab7fe200cacce3dca8b66290b examples/chrony.conf.example2
96999221eeef476bd49fe97b97503126 examples/chrony.keys.example
6a3178c4670de7de393d9365e2793740 examples/chrony.logrotate
fabb5b3f127b802c27c82837feff0fe6 examples/chrony.nm-dispatcher.dhcp
8f5a98fcb400a482d355b929d04b5518 examples/chrony.nm-dispatcher.onoffline
56d221eba8ce8a2e03d3e0dd87999a81 examples/chronyd.service
EOF
# don't allow packaging without vendor zone
test -n "%{vendorzone}"
# use example chrony.conf as the default config with some modifications:
# - use our vendor zone (2.*pool.ntp.org names include IPv6 addresses)
# - enable leapsectz to get TAI-UTC offset and leap seconds from tzdata
# - enable keyfile
sed -e 's|^\(pool \)\(pool.ntp.org\)|\12.%{vendorzone}\2|' \
-e 's|#\(leapsectz\)|\1|' \
-e 's|#\(keyfile\)|\1|' \
< examples/chrony.conf.example2 > chrony.conf
touch -r examples/chrony.conf.example2 chrony.conf
# regenerate the file from getdate.y
rm -f getdate.c
mv clknetsim-%{clknetsim_ver}* test/simulation/clknetsim
install -m 644 -p %{SOURCE11} ntp2chrony.py
%build
%configure \
%{?with_debug: --enable-debug} \
--enable-ntp-signd \
--enable-scfilter \
%{!?with_nts: --disable-nts} \
--chronyrundir=/run/chrony \
--docdir=%{_docdir} \
--with-ntp-era=$(date -d '1970-01-01 00:00:00+00:00' +'%s') \
--with-user=chrony \
--with-hwclockfile=%{_sysconfdir}/adjtime \
--with-pidfile=/run/chrony/chronyd.pid \
--with-sendmail=%{_sbindir}/sendmail
make %{?_smp_mflags}
%install
make install DESTDIR=$RPM_BUILD_ROOT
rm -rf $RPM_BUILD_ROOT%{_docdir}
mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/{sysconfig,logrotate.d}
mkdir -p $RPM_BUILD_ROOT%{_localstatedir}/{lib,log}/chrony
mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/NetworkManager/dispatcher.d
mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/dhcp/dhclient.d
mkdir -p $RPM_BUILD_ROOT%{_libexecdir}
mkdir -p $RPM_BUILD_ROOT{%{_unitdir},%{_prefix}/lib/systemd/ntp-units.d}
install -m 644 -p chrony.conf $RPM_BUILD_ROOT%{_sysconfdir}/chrony.conf
install -m 640 -p examples/chrony.keys.example \
$RPM_BUILD_ROOT%{_sysconfdir}/chrony.keys
install -m 755 -p examples/chrony.nm-dispatcher.onoffline \
$RPM_BUILD_ROOT%{_sysconfdir}/NetworkManager/dispatcher.d/20-chrony-onoffline
install -m 755 -p examples/chrony.nm-dispatcher.dhcp \
$RPM_BUILD_ROOT%{_sysconfdir}/NetworkManager/dispatcher.d/20-chrony-dhcp
install -m 755 -p %{SOURCE1} \
$RPM_BUILD_ROOT%{_sysconfdir}/dhcp/dhclient.d/chrony.sh
install -m 644 -p examples/chrony.logrotate \
$RPM_BUILD_ROOT%{_sysconfdir}/logrotate.d/chrony
install -m 644 -p examples/chronyd.service \
$RPM_BUILD_ROOT%{_unitdir}/chronyd.service
install -m 644 -p examples/chrony-wait.service \
$RPM_BUILD_ROOT%{_unitdir}/chrony-wait.service
install -m 644 -p %{SOURCE3} $RPM_BUILD_ROOT%{_unitdir}/chrony-dnssrv@.service
install -m 644 -p %{SOURCE4} $RPM_BUILD_ROOT%{_unitdir}/chrony-dnssrv@.timer
install -m 755 -p %{SOURCE2} $RPM_BUILD_ROOT%{_libexecdir}/chrony-helper
cat > $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig/chronyd <<EOF
# Command-line options for chronyd
OPTIONS=""
EOF
touch $RPM_BUILD_ROOT%{_localstatedir}/lib/chrony/{drift,rtc}
echo 'chronyd.service' > \
$RPM_BUILD_ROOT%{_prefix}/lib/systemd/ntp-units.d/50-chronyd.list
%check
# set random seed to get deterministic results
export CLKNETSIM_RANDOM_SEED=24502
make %{?_smp_mflags} -C test/simulation/clknetsim
make quickcheck
%pre
getent group chrony > /dev/null || /usr/sbin/groupadd -r chrony
getent passwd chrony > /dev/null || /usr/sbin/useradd -r -g chrony \
-d %{_localstatedir}/lib/chrony -s /sbin/nologin chrony
:
%post
# fix PIDFile in local chronyd.service on upgrades from chrony < 3.3-2
if grep -q 'PIDFile=%{_localstatedir}/run/chronyd.pid' \
%{_sysconfdir}/systemd/system/chronyd.service 2> /dev/null && \
! grep -qi '^[ '$'\t'']*pidfile' %{_sysconfdir}/chrony.conf 2> /dev/null
then
sed -i '/PIDFile=/s|/run/|/run/chrony/|' \
%{_sysconfdir}/systemd/system/chronyd.service
fi
# workaround for late reload of unit file (#1614751)
%{_bindir}/systemctl daemon-reload
%systemd_post chronyd.service chrony-wait.service
%preun
%systemd_preun chronyd.service chrony-wait.service
%postun
%systemd_postun_with_restart chronyd.service
%files
%{!?_licensedir:%global license %%doc}
%license COPYING
%doc FAQ NEWS README ntp2chrony.py
%config(noreplace) %{_sysconfdir}/chrony.conf
%config(noreplace) %verify(not md5 size mtime) %attr(640,root,chrony) %{_sysconfdir}/chrony.keys
%config(noreplace) %{_sysconfdir}/logrotate.d/chrony
%config(noreplace) %{_sysconfdir}/sysconfig/chronyd
%{_sysconfdir}/NetworkManager/dispatcher.d/20-chrony*
%{_sysconfdir}/dhcp/dhclient.d/chrony.sh
%{_bindir}/chronyc
%{_sbindir}/chronyd
%{_libexecdir}/chrony-helper
%{_prefix}/lib/systemd/ntp-units.d/*.list
%{_unitdir}/chrony*.service
%{_unitdir}/chrony*.timer
%{_mandir}/man[158]/%{name}*.[158]*
%dir %attr(750,chrony,chrony) %{_localstatedir}/lib/chrony
%ghost %attr(-,chrony,chrony) %{_localstatedir}/lib/chrony/drift
%ghost %attr(-,chrony,chrony) %{_localstatedir}/lib/chrony/rtc
%dir %attr(750,chrony,chrony) %{_localstatedir}/log/chrony
%changelog
* Tue Jun 15 2021 Miroslav Lichvar <mlichvar@redhat.com> 4.1-1
- update to 4.1 (#1895003 #1847853 #1929157)
- add NetworkManager dispatcher script to add servers from DHCP even without
dhclient (#1933139)
- restrict permissions of /var/lib/chrony and /var/log/chrony (#1939295)
- reset chrony-helper state after stopping chronyd (#1971697)
- add gcc-c++ and make to build requirements
- move default paths in /var/run to /run
* Tue May 21 2019 Miroslav Lichvar <mlichvar@redhat.com> 3.5-1
- update to 3.5 (#1685469 #1677218)
- fix shellcheck warnings in helper scripts (#1711948)
- update ntp2chrony script
* Mon Aug 13 2018 Miroslav Lichvar <mlichvar@redhat.com> 3.3-3
- fix PIDFile in local chronyd.service on upgrades from chrony < 3.3-2
(#1614800)
- add workaround for late reload of unit file (#1614751)
* Mon Jun 18 2018 Miroslav Lichvar <mlichvar@redhat.com> 3.3-2
- move pidfile to /var/run/chrony to allow chronyd to remove it on exit
(#1584585)
- avoid blocking in getrandom system call (#1592425)
* Thu Apr 05 2018 Miroslav Lichvar <mlichvar@redhat.com> 3.3-1
- update to 3.3
- enable keyfile by default again
- update ntp2chrony script
* Mon Mar 19 2018 Miroslav Lichvar <mlichvar@redhat.com> 3.3-0.2.pre1
- include ntp2chrony script in documentation (#1530987)
* Thu Mar 15 2018 Miroslav Lichvar <mlichvar@redhat.com> 3.3-0.1.pre1
- update to 3.3-pre1
- switch to nettle for crypto hashing
- add gcc to build requirements
* Wed Feb 07 2018 Fedora Release Engineering <releng@fedoraproject.org> - 3.2-4
- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild
* Tue Jan 30 2018 Miroslav Lichvar <mlichvar@redhat.com> 3.2-3
- use systemd macro for scriptlet dependencies
* Thu Jan 25 2018 Miroslav Lichvar <mlichvar@redhat.com> 3.2-2
- fix chronyc getting stuck in infinite loop after clock step
- don't allow packaging without vendor zone
- suggest ntp-refclock
- remove obsolete dependency
- update description
* Fri Sep 15 2017 Miroslav Lichvar <mlichvar@redhat.com> 3.2-1
- update to 3.2
- get TAI-UTC offset and leap seconds from tzdata by default
* Tue Aug 29 2017 Miroslav Lichvar <mlichvar@redhat.com> 3.2-0.4.pre2
- update to 3.2-pre2
* Wed Aug 02 2017 Fedora Release Engineering <releng@fedoraproject.org> - 3.2-0.3.pre1
- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Binutils_Mass_Rebuild
* Wed Jul 26 2017 Fedora Release Engineering <releng@fedoraproject.org> - 3.2-0.2.pre1
- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild
* Tue Jul 25 2017 Miroslav Lichvar <mlichvar@redhat.com> 3.2-0.1.pre1
- update to 3.2-pre1
* Thu May 04 2017 Miroslav Lichvar <mlichvar@redhat.com> 3.1-5
- check PEERNTP variable before loading existing dhclient files
* Thu Apr 20 2017 Miroslav Lichvar <mlichvar@redhat.com> 3.1-4
- use ID from /etc/os-release to set pool.ntp.org vendor zone (#1443599)
- fix seccomp filter for new glibc once again
- don't drop PHC samples with zero delay
* Mon Mar 13 2017 Miroslav Lichvar <mlichvar@redhat.com> 3.1-3
- fix seccomp filter for new glibc
* Fri Feb 10 2017 Fedora Release Engineering <releng@fedoraproject.org> - 3.1-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild
* Tue Jan 31 2017 Miroslav Lichvar <mlichvar@redhat.com> 3.1-1
- update to 3.1
- enable seccomp support on more archs
- package chronyd sysconfig file
* Tue Jan 24 2017 Miroslav Lichvar <mlichvar@redhat.com> 3.1-0.1.pre1
- update to 3.1-pre1
* Mon Jan 16 2017 Miroslav Lichvar <mlichvar@redhat.com> 3.0-1
- update to 3.0
* Fri Jan 06 2017 Miroslav Lichvar <mlichvar@redhat.com> 3.0-0.3.pre3
- update to 3.0-pre3
* Thu Dec 15 2016 Miroslav Lichvar <mlichvar@redhat.com> 3.0-0.2.pre2
- update to 3.0-pre2
- enable support for MS-SNTP authentication in Samba
* Fri Dec 09 2016 Miroslav Lichvar <mlichvar@redhat.com> 3.0-0.1.pre1
- update to 3.0-pre1
* Mon Nov 21 2016 Miroslav Lichvar <mlichvar@redhat.com> 2.4.1-1
- update to 2.4.1
* Thu Oct 27 2016 Miroslav Lichvar <mlichvar@redhat.com> 2.4-4
- avoid AVC denials in chrony-wait service (#1350815)
* Tue Sep 13 2016 Miroslav Lichvar <mlichvar@redhat.com> 2.4-3
- fix chrony-helper to escape names of systemd units (#1374767)
* Tue Jun 28 2016 Miroslav Lichvar <mlichvar@redhat.com> 2.4-2
- fix chrony-helper to exit with correct status (#1350531)
* Tue Jun 07 2016 Miroslav Lichvar <mlichvar@redhat.com> 2.4-1
- update to 2.4
- don't require info
* Mon May 16 2016 Miroslav Lichvar <mlichvar@redhat.com> 2.4-0.1.pre1
- update to 2.4-pre1
- extend chrony-helper to allow management of static sources (#1331655)
* Tue Feb 16 2016 Miroslav Lichvar <mlichvar@redhat.com> 2.3-1
- update to 2.3
* Tue Feb 02 2016 Miroslav Lichvar <mlichvar@redhat.com> 2.3-0.1.pre1
- update to 2.3-pre1
* Thu Jan 21 2016 Miroslav Lichvar <mlichvar@redhat.com> 2.2.1-1
- update to 2.2.1 (CVE-2016-1567)
- set NTP era split explicitly
* Mon Oct 19 2015 Miroslav Lichvar <mlichvar@redhat.com> 2.2-1
- update to 2.2
* Fri Oct 09 2015 Miroslav Lichvar <mlichvar@redhat.com> 2.2-0.2.pre2
- update to 2.2-pre2
- require libseccomp-devel on supported archs only
* Fri Oct 02 2015 Miroslav Lichvar <mlichvar@redhat.com> 2.2-0.1.pre1
- update to 2.2-pre1
- enable seccomp support
- use weak dependency for timedatex on Fedora 24 and later
* Tue Jun 23 2015 Miroslav Lichvar <mlichvar@redhat.com> 2.1.1-1
- update to 2.1.1
- add -n option to gzip command to not save timestamp
* Mon Jun 22 2015 Miroslav Lichvar <mlichvar@redhat.com> 2.1-1
- update to 2.1
- extend chrony-helper to allow using servers from DNS SRV records (#1234406)
- set random seed in testing to get deterministic results
* Wed Jun 17 2015 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 2.1-0.2.pre1
- Rebuilt for https://fedoraproject.org/wiki/Fedora_23_Mass_Rebuild
* Wed Jun 10 2015 Miroslav Lichvar <mlichvar@redhat.com> 2.1-0.1.pre1
- update to 2.1-pre1
* Mon Apr 27 2015 Miroslav Lichvar <mlichvar@redhat.com> 2.0-1
- update to 2.0
* Wed Apr 08 2015 Miroslav Lichvar <mlichvar@redhat.com> 2.0-0.3.pre2
- update to 2.0-pre2 (CVE-2015-1853 CVE-2015-1821 CVE-2015-1822)
* Thu Jan 29 2015 Miroslav Lichvar <mlichvar@redhat.com> 2.0-0.2.pre1
- require timedatex (#1136905)
* Tue Jan 27 2015 Miroslav Lichvar <mlichvar@redhat.com> 2.0-0.1.pre1
- update to 2.0-pre1
* Thu Sep 11 2014 Miroslav Lichvar <mlichvar@redhat.com> 1.31-1
- update to 1.31
- add servers from DHCP with iburst option by default
- use upstream configuration files and scripts
- don't package configuration examples
- compress chrony.txt
* Thu Aug 21 2014 Miroslav Lichvar <mlichvar@redhat.com> 1.31-0.1.pre1
- update to 1.31-pre1
- use license macro if available
* Sat Aug 16 2014 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.30-3
- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_22_Mass_Rebuild
* Fri Aug 15 2014 Miroslav Lichvar <mlichvar@redhat.com> 1.30-2
- reconnect client sockets (#1124059)
* Tue Jul 01 2014 Miroslav Lichvar <mlichvar@redhat.com> 1.30-1
- update to 1.30
- enable debug messages
* Mon Jun 09 2014 Miroslav Lichvar <mlichvar@redhat.com> 1.30-0.1.pre1
- update to 1.30-pre1
- execute test suite
- avoid calling systemctl in helper script
- call chronyc directly from logrotate and NM dispatcher scripts
- add conflict with systemd-timesyncd service
* Sat Jun 07 2014 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.29.1-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild
* Fri Jan 31 2014 Miroslav Lichvar <mlichvar@redhat.com> 1.29.1-1
- update to 1.29.1 (CVE-2014-0021)
- replace hardening build flags with _hardened_build
* Tue Nov 19 2013 Miroslav Lichvar <mlichvar@redhat.com> 1.29-3
- let systemd remove pid file (#974305)
* Thu Oct 03 2013 Miroslav Lichvar <mlichvar@redhat.com> 1.29-2
- add ordering dependency to not start chronyd before ntpd stopped
* Thu Aug 08 2013 Miroslav Lichvar <mlichvar@redhat.com> 1.29-1
- update to 1.29 (CVE-2012-4502, CVE-2012-4503)
* Sat Aug 03 2013 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.28-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_20_Mass_Rebuild
* Wed Jul 17 2013 Miroslav Lichvar <mlichvar@redhat.com> 1.28-1
- update to 1.28
- change default makestep limit to 10 seconds
* Mon Jun 24 2013 Miroslav Lichvar <mlichvar@redhat.com> 1.28-0.2.pre1
- buildrequire systemd-units
* Fri Jun 21 2013 Miroslav Lichvar <mlichvar@redhat.com> 1.28-0.1.pre1
- update to 1.28-pre1
- listen for commands only on localhost by default
* Thu May 09 2013 Miroslav Lichvar <mlichvar@redhat.com> 1.27-3
- disable chrony-wait service by default (#961047)
- drop old systemd scriptlets
- don't own ntp-units.d directory
- move files from /lib
- remove unncessary dependency on syslog target
* Tue Mar 12 2013 Miroslav Lichvar <mlichvar@redhat.com> 1.27-2
- suppress error messages from tr when generating key (#907914)
- fix delta calculation with extreme frequency offsets
* Fri Feb 01 2013 Miroslav Lichvar <mlichvar@redhat.com> 1.27-1
- update to 1.27
- start chrony-wait service with chronyd
- start chronyd service after sntp
- remove obsolete macros
* Tue Sep 11 2012 Miroslav Lichvar <mlichvar@redhat.com> 1.27-0.5.pre1.git1ca844
- update to git snapshot 1ca844
- update systemd integration (#846303)
- use systemd macros if available (#850151)
- use correct vendor pool.ntp.org zone on RHEL (#845981)
- don't log output of chrony-wait service
* Wed Jul 18 2012 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.27-0.4.pre1
- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild
* Fri Apr 27 2012 Miroslav Lichvar <mlichvar@redhat.com> 1.27-0.3.pre1
- update service file for systemd-timedated-ntp target (#816493)
* Fri Apr 06 2012 Miroslav Lichvar <mlichvar@redhat.com> 1.27-0.2.pre1
use systemctl is-active instead of status in chrony-helper (#794771)
* Tue Feb 28 2012 Miroslav Lichvar <mlichvar@redhat.com> 1.27-0.1.pre1
- update to 1.27-pre1
- generate SHA1 command key instead of MD5
* Wed Feb 15 2012 Miroslav Lichvar <mlichvar@redhat.com> 1.26-6.20110831gitb088b7
- remove old servers on DHCP update (#787042)
* Fri Feb 10 2012 Miroslav Lichvar <mlichvar@redhat.com> 1.26-5.20110831gitb088b7
- improve chrony-helper to keep track of servers added from DHCP (#787042)
- fix dhclient script to always return with zero exit code (#767859)
* Thu Jan 12 2012 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.26-4.20110831gitb088b7
- Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild
* Tue Sep 06 2011 Miroslav Lichvar <mlichvar@redhat.com> 1.26-3.20110831gitb088b7
- update to git snapshot 20110831gitb088b7
- on first start generate password with 16 chars
- change systemd service type to forking
- add forced-command to chrony-helper (#735821)
* Mon Aug 15 2011 Miroslav Lichvar <mlichvar@redhat.com> 1.26-2
- fix iburst with very high jitters and long delays
- use timepps header from pps-tools-devel
* Wed Jul 13 2011 Miroslav Lichvar <mlichvar@redhat.com> 1.26-1
- update to 1.26
- read options from sysconfig file if it exists
* Fri Jun 24 2011 Miroslav Lichvar <mlichvar@redhat.com> 1.26-0.1.pre1
- update to 1.26-pre1
- fix service name in %%triggerun
- drop SysV init script
- add chrony-wait service
* Fri May 06 2011 Bill Nottingham <notting@redhat.com> 1.25-2
- fix systemd scriptlets for the upgrade case
* Wed May 04 2011 Miroslav Lichvar <mlichvar@redhat.com> 1.25-1
- update to 1.25
* Wed Apr 20 2011 Miroslav Lichvar <mlichvar@redhat.com> 1.25-0.3.pre2
- update to 1.25-pre2
- link with -Wl,-z,relro,-z,now options
* Tue Feb 08 2011 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.25-0.2.pre1
- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild
* Tue Feb 01 2011 Miroslav Lichvar <mlichvar@redhat.com> 1.25-0.1.pre1
- update to 1.25-pre1
- use iburst, four pool servers, rtcsync, stratumweight in default config
- add systemd support
- drop sysconfig file
- suppress install-info errors
* Thu Apr 29 2010 Miroslav Lichvar <mlichvar@redhat.com> 1.24-4.20100428git73d775
- update to 20100428git73d775
- replace initstepslew directive with makestep in default config
- add NetworkManager dispatcher script
- add dhclient script
- retry server/peer name resolution at least once to workaround
NetworkManager race condition on boot
- don't verify chrony.keys
* Fri Mar 12 2010 Miroslav Lichvar <mlichvar@redhat.com> 1.24-3.20100302git5fb555
- update to snapshot 20100302git5fb555
- compile with PPS API support
* Thu Feb 04 2010 Miroslav Lichvar <mlichvar@redhat.com> 1.24-1
- update to 1.24 (#555367, CVE-2010-0292 CVE-2010-0293 CVE-2010-0294)
- modify default config
- step clock on start if it is off by more than 100 seconds
- disable client log
- build with -fPIE on sparc
* Tue Dec 15 2009 Miroslav Lichvar <mlichvar@redhat.com> 1.24-0.1.pre1
- update to 1.24-pre1
* Fri Jul 24 2009 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.23-7.20081106gitbe42b4
- Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild
* Fri Jul 17 2009 Miroslav Lichvar <mlichvar@redhat.com> 1.23-6.20081106gitbe42b4
- switch to editline
- support arbitrary chronyc commands in init script
* Mon Jun 08 2009 Dan Horak <dan[at]danny.cz> 1.23-5.20081106gitbe42b4
- add patch with support for s390/s390x
* Mon Mar 09 2009 Miroslav Lichvar <mlichvar@redhat.com> 1.23-4.20081106gitbe42b4
- fix building with broken libcap header (#483548)
* Mon Feb 23 2009 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.23-3.20081106gitbe42b4
- Rebuilt for https://fedoraproject.org/wiki/Fedora_11_Mass_Rebuild
* Wed Nov 19 2008 Miroslav Lichvar <mlichvar@redhat.com> 1.23-2.20081106gitbe42b4
- fix info uninstall
- generate random command key in init script
- support cyclelogs, online, offline commands in init script
- add logrotate script
* Tue Nov 11 2008 Miroslav Lichvar <mlichvar@redhat.com> 1.23-1.20081106gitbe42b4
- initial release

671
ntp2chrony.py Normal file
View File

@ -0,0 +1,671 @@
#!/usr/bin/python
#
# Convert ntp configuration to chrony
#
# Copyright (C) 2018-2019 Miroslav Lichvar <mlichvar@redhat.com>
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
import argparse
import ipaddress
import logging
import os
import os.path
import re
import subprocess
import sys
# python2 compatibility hacks
if sys.version_info[0] < 3:
from io import open
reload(sys)
sys.setdefaultencoding("utf-8")
class NtpConfiguration(object):
def __init__(self, root_dir, ntp_conf, step_tickers):
self.root_dir = root_dir if root_dir != "/" else ""
self.ntp_conf_path = ntp_conf
self.step_tickers_path = step_tickers
# Read and write files using an 8-bit transparent encoding
self.file_encoding = "latin-1"
self.enabled_services = set()
self.step_tickers = []
self.time_sources = []
self.fudges = {}
self.restrictions = {
# Built-in defaults
ipaddress.ip_network(u"0.0.0.0/0"): set(),
ipaddress.ip_network(u"::/0"): set(),
}
self.keyfile = ""
self.keys = []
self.trusted_keys = []
self.driftfile = ""
self.statistics = []
self.leapfile = ""
self.tos_options = {}
self.ignored_directives = set()
self.ignored_lines = []
#self.detect_enabled_services()
self.parse_step_tickers()
self.parse_ntp_conf()
def detect_enabled_services(self):
for service in ["ntpdate", "ntpd", "ntp-wait"]:
if os.path.islink("{}/etc/systemd/system/multi-user.target.wants/{}.service"
.format(self.root_dir, service)):
self.enabled_services.add(service)
logging.info("Enabled services found in /etc/systemd/system: %s",
" ".join(self.enabled_services))
def parse_step_tickers(self):
if not self.step_tickers_path:
return
path = os.path.join(self.root_dir, self.step_tickers_path)
if not os.path.isfile(path):
logging.info("Missing %s", path)
return
with open(path, encoding=self.file_encoding) as f:
for line in f:
line = line[:line.find('#')]
words = line.split()
if not words:
continue
self.step_tickers.extend(words)
def parse_ntp_conf(self, path=None):
if path is None:
path = os.path.join(self.root_dir, self.ntp_conf_path)
with open(path, encoding=self.file_encoding) as f:
logging.info("Reading %s", path)
for line in f:
line = line[:line.find('#')]
words = line.split()
if not words:
continue
if not self.parse_directive(words):
self.ignored_lines.append(line)
def parse_directive(self, words):
name = words.pop(0)
if name.startswith("logconfig"):
name = "logconfig"
if words:
if name in ["server", "peer", "pool"]:
return self.parse_source(name, words)
elif name == "fudge":
return self.parse_fudge(words)
elif name == "restrict":
return self.parse_restrict(words)
elif name == "tos":
return self.parse_tos(words)
elif name == "includefile":
return self.parse_includefile(words)
elif name == "keys":
return self.parse_keys(words)
elif name == "trustedkey":
return self.parse_trustedkey(words)
elif name == "driftfile":
self.driftfile = words[0]
elif name == "statistics":
self.statistics = words
elif name == "leapfile":
self.leapfile = words[0]
else:
self.ignored_directives.add(name)
return False
else:
self.ignored_directives.add(name)
return False
return True
def parse_source(self, source_type, words):
ipv4_only = False
ipv6_only = False
source = {
"type": source_type,
"options": []
}
if words[0] == "-4":
ipv4_only = True
words.pop(0)
elif words[0] == "-6":
ipv6_only = True
words.pop(0)
if not words:
return False
source["address"] = words.pop(0)
# Check if -4/-6 corresponds to the address and ignore hostnames
if ipv4_only or ipv6_only:
try:
version = ipaddress.ip_address(source["address"]).version
if (ipv4_only and version != 4) or (ipv6_only and version != 6):
return False
except ValueError:
return False
if source["address"].startswith("127.127."):
if not source["address"].startswith("127.127.1."):
# Ignore non-LOCAL refclocks
return False
while words:
if len(words) >= 2 and words[0] in ["minpoll", "maxpoll", "version", "key"]:
source["options"].append((words[0], words[1]))
words = words[2:]
elif words[0] in ["burst", "iburst", "noselect", "prefer", "true", "xleave"]:
source["options"].append((words[0],))
words.pop(0)
else:
return False
self.time_sources.append(source)
return True
def parse_fudge(self, words):
address = words.pop(0)
options = {}
while words:
if len(words) >= 2 and words[0] in ["stratum"]:
if not words[1].isdigit():
return False
options[words[0]] = int(words[1])
words = words[2:]
elif len(words) >= 2:
words = words[2:]
else:
return False
self.fudges[address] = options
return True
def parse_restrict(self, words):
ipv4_only = False
ipv6_only = False
flags = set()
mask = ""
if words[0] == "-4":
ipv4_only = True
words.pop(0)
elif words[0] == "-6":
ipv6_only = True
words.pop(0)
if not words:
return False
address = words.pop(0)
while words:
if len(words) >= 2 and words[0] == "mask":
mask = words[1]
words = words[2:]
else:
if words[0] not in ["kod", "nomodify", "notrap", "nopeer", "noquery",
"limited", "ignore", "noserve"]:
return False
flags.add(words[0])
words.pop(0)
# Convert to IP network(s), ignoring restrictions with hostnames
networks = []
if address == "default" and not mask:
if not ipv6_only:
networks.append(ipaddress.ip_network(u"0.0.0.0/0"))
if not ipv4_only:
networks.append(ipaddress.ip_network(u"::/0"))
else:
try:
if mask:
networks.append(ipaddress.ip_network(u"{}/{}".format(address, mask)))
else:
networks.append(ipaddress.ip_network(address))
except ValueError:
return False
if (ipv4_only and networks[-1].version != 4) or \
(ipv6_only and networks[-1].version != 6):
return False
for network in networks:
self.restrictions[network] = flags
return True
def parse_tos(self, words):
options = {}
while words:
if len(words) >= 2 and words[0] in ["minsane", "orphan"]:
if not words[1].isdigit():
return False
options[words[0]] = int(words[1])
words = words[2:]
elif len(words) >= 2 and words[0] in ["maxdist"]:
# Check if it is a float value
if not words[1].replace('.', '', 1).isdigit():
return False
options[words[0]] = float(words[1])
words = words[2:]
else:
return False
self.tos_options.update(options)
return True
def parse_includefile(self, words):
path = os.path.join(self.root_dir, words[0])
if not os.path.isfile(path):
return False
self.parse_ntp_conf(path)
return True
def parse_keys(self, words):
keyfile = words[0]
path = os.path.join(self.root_dir, keyfile)
if not os.path.isfile(path):
logging.info("Missing %s", path)
return False
with open(path, encoding=self.file_encoding) as f:
logging.info("Reading %s", path)
keys = []
for line in f:
words = line.split()
if len(words) < 3 or not words[0].isdigit():
continue
keys.append((int(words[0]), words[1], words[2]))
self.keyfile = keyfile
self.keys = keys
return True
def parse_trustedkey(self, words):
key_ranges = []
for word in words:
if word.isdigit():
key_ranges.append((int(word), int(word)))
elif re.match("^[0-9]+-[0-9]+$", word):
first, last = word.split("-")
key_ranges.append((int(first), int(last)))
else:
return False
self.trusted_keys = key_ranges
return True
def write_chrony_configuration(self, chrony_conf_path, chrony_keys_path,
dry_run=False, backup=False):
chrony_conf = self.get_chrony_conf(chrony_keys_path)
logging.debug("Generated %s:\n%s", chrony_conf_path, chrony_conf)
if not dry_run:
self.write_file(chrony_conf_path, 0o644, chrony_conf, backup)
chrony_keys = self.get_chrony_keys()
if chrony_keys:
logging.debug("Generated %s:\n%s", chrony_keys_path, chrony_keys)
if not dry_run:
self.write_file(chrony_keys_path, 0o640, chrony_keys, backup)
def get_processed_time_sources(self):
# Convert {0,1,2,3}.*pool.ntp.org servers to 2.*pool.ntp.org pools
# Make shallow copies of all sources (only type will be modified)
time_sources = [s.copy() for s in self.time_sources]
pools = {}
for source in time_sources:
if source["type"] != "server":
continue
m = re.match("^([0123])(\\.\\w+)?\\.pool\\.ntp\\.org$", source["address"])
if m is None:
continue
number = m.group(1)
zone = m.group(2)
if zone not in pools:
pools[zone] = []
pools[zone].append((int(number), source))
remove_servers = set()
for zone, pool in pools.items():
# sort and skip all pools not in [0, 3] range
pool.sort()
if [number for number, source in pool] != [0, 1, 2, 3]:
# only exact group of 4 servers can be converted, nothing to do here
continue
# verify that parameters are the same for all servers in the pool
if not all([p[1]["options"] == pool[0][1]["options"] for p in pool]):
break
remove_servers.update([pool[i][1]["address"] for i in [0, 1, 3]])
pool[2][1]["type"] = "pool"
processed_sources = []
for source in time_sources:
if source["type"] == "server" and source["address"] in remove_servers:
continue
processed_sources.append(source)
return processed_sources
def get_chrony_conf_sources(self):
conf = ""
if self.step_tickers:
conf += "# Specify NTP servers used for initial correction.\n"
conf += "initstepslew 0.1 {}\n".format(" ".join(self.step_tickers))
conf += "\n"
conf += "# Specify time sources.\n"
for source in self.get_processed_time_sources():
address = source["address"]
if address.startswith("127.127."):
if address.startswith("127.127.1."):
continue
# No other refclocks are expected from the parser
assert False
else:
conf += "{} {}".format(source["type"], address)
for option in source["options"]:
if option[0] in ["minpoll", "maxpoll", "version", "key",
"iburst", "noselect", "prefer", "xleave"]:
conf += " {}".format(" ".join(option))
elif option[0] == "burst":
conf += " presend 6"
elif option[0] == "true":
conf += " trust"
else:
# No other options are expected from the parser
assert False
conf += "\n"
conf += "\n"
return conf
def get_chrony_conf_allows(self):
allowed_networks = filter(lambda n: "ignore" not in self.restrictions[n] and
"noserve" not in self.restrictions[n],
self.restrictions.keys())
conf = ""
for network in sorted(allowed_networks, key=lambda n: (n.version, n)):
if network.num_addresses > 1:
conf += "allow {}\n".format(network)
else:
conf += "allow {}\n".format(network.network_address)
if conf:
conf = "# Allow NTP client access.\n" + conf
conf += "\n"
return conf
def get_chrony_conf_cmdallows(self):
allowed_networks = filter(lambda n: "ignore" not in self.restrictions[n] and
"noquery" not in self.restrictions[n] and
n != ipaddress.ip_network(u"127.0.0.1/32") and
n != ipaddress.ip_network(u"::1/128"),
self.restrictions.keys())
ip_versions = set()
conf = ""
for network in sorted(allowed_networks, key=lambda n: (n.version, n)):
ip_versions.add(network.version)
if network.num_addresses > 1:
conf += "cmdallow {}\n".format(network)
else:
conf += "cmdallow {}\n".format(network.network_address)
if conf:
conf = "# Allow remote monitoring.\n" + conf
if 4 in ip_versions:
conf += "bindcmdaddress 0.0.0.0\n"
if 6 in ip_versions:
conf += "bindcmdaddress ::\n"
conf += "\n"
return conf
def get_chrony_conf(self, chrony_keys_path):
local_stratum = 0
maxdistance = 0.0
minsources = 1
orphan_stratum = 0
logs = []
for source in self.time_sources:
address = source["address"]
if address.startswith("127.127.1."):
if address in self.fudges and "stratum" in self.fudges[address]:
local_stratum = self.fudges[address]["stratum"]
else:
local_stratum = 5
if "maxdist" in self.tos_options:
maxdistance = self.tos_options["maxdist"]
if "minsane" in self.tos_options:
minsources = self.tos_options["minsane"]
if "orphan" in self.tos_options:
orphan_stratum = self.tos_options["orphan"]
if "clockstats" in self.statistics:
logs.append("refclocks");
if "loopstats" in self.statistics:
logs.append("tracking")
if "peerstats" in self.statistics:
logs.append("statistics");
if "rawstats" in self.statistics:
logs.append("measurements")
conf = "# This file was converted from {}{}.\n".format(
self.ntp_conf_path,
" and " + self.step_tickers_path if self.step_tickers_path else "")
conf += "\n"
if self.ignored_lines:
conf += "# The following directives were ignored in the conversion:\n"
for line in self.ignored_lines:
# Remove sensitive information
line = re.sub(r"\s+pw\s+\S+", " pw XXX", line.rstrip())
conf += "# " + line + "\n"
conf += "\n"
conf += self.get_chrony_conf_sources()
conf += "# Record the rate at which the system clock gains/losses time.\n"
if not self.driftfile:
conf += "#"
conf += "driftfile /var/lib/chrony/drift\n"
conf += "\n"
conf += "# Allow the system clock to be stepped in the first three updates\n"
conf += "# if its offset is larger than 1 second.\n"
conf += "makestep 1.0 3\n"
conf += "\n"
conf += "# Enable kernel synchronization of the real-time clock (RTC).\n"
conf += "rtcsync\n"
conf += "\n"
conf += "# Enable hardware timestamping on all interfaces that support it.\n"
conf += "#hwtimestamp *\n"
conf += "\n"
if maxdistance > 0.0:
conf += "# Specify the maximum distance of sources to be selectable.\n"
conf += "maxdistance {}\n".format(maxdistance)
conf += "\n"
conf += "# Increase the minimum number of selectable sources required to adjust\n"
conf += "# the system clock.\n"
if minsources > 1:
conf += "minsources {}\n".format(minsources)
else:
conf += "#minsources 2\n"
conf += "\n"
conf += self.get_chrony_conf_allows()
conf += self.get_chrony_conf_cmdallows()
conf += "# Serve time even if not synchronized to a time source.\n"
if orphan_stratum > 0 and orphan_stratum < 16:
conf += "local stratum {} orphan\n".format(orphan_stratum)
elif local_stratum > 0 and local_stratum < 16:
conf += "local stratum {}\n".format(local_stratum)
else:
conf += "#local stratum 10\n"
conf += "\n"
conf += "# Specify file containing keys for NTP authentication.\n"
conf += "keyfile {}\n".format(chrony_keys_path)
conf += "\n"
conf += "# Get TAI-UTC offset and leap seconds from the system tz database.\n"
conf += "leapsectz right/UTC\n"
conf += "\n"
conf += "# Specify directory for log files.\n"
conf += "logdir /var/log/chrony\n"
conf += "\n"
conf += "# Select which information is logged.\n"
if logs:
conf += "log {}\n".format(" ".join(logs))
else:
conf += "#log measurements statistics tracking\n"
return conf
def get_chrony_keys(self):
if not self.keyfile:
return ""
keys = "# This file was converted from {}.\n".format(self.keyfile)
keys += "\n"
for key in self.keys:
key_id = key[0]
key_type = key[1]
password = key[2]
if key_type in ["m", "M"]:
key_type = "MD5"
elif key_type not in ["MD5", "SHA1", "SHA256", "SHA384", "SHA512"]:
continue
prefix = "ASCII" if len(password) <= 20 else "HEX"
for first, last in self.trusted_keys:
if first <= key_id <= last:
trusted = True
break
else:
trusted = False
# Disable keys that were not marked as trusted
if not trusted:
keys += "#"
keys += "{} {} {}:{}\n".format(key_id, key_type, prefix, password)
return keys
def write_file(self, path, mode, content, backup):
path = self.root_dir + path
if backup and os.path.isfile(path):
os.rename(path, path + ".old")
with open(os.open(path, os.O_CREAT | os.O_WRONLY | os.O_EXCL, mode), "w",
encoding=self.file_encoding) as f:
logging.info("Writing %s", path)
f.write(u"" + content)
# Fix SELinux context if restorecon is installed
try:
subprocess.call(["restorecon", path])
except OSError:
pass
def main():
parser = argparse.ArgumentParser(description="Convert ntp configuration to chrony.")
parser.add_argument("-r", "--root", dest="roots", default=["/"], nargs="+",
metavar="DIR", help="specify root directory (default /)")
parser.add_argument("--ntp-conf", action="store", default="/etc/ntp.conf",
metavar="FILE", help="specify ntp config (default /etc/ntp.conf)")
parser.add_argument("--step-tickers", action="store", default="",
metavar="FILE", help="specify ntpdate step-tickers config (no default)")
parser.add_argument("--chrony-conf", action="store", default="/etc/chrony.conf",
metavar="FILE", help="specify chrony config (default /etc/chrony.conf)")
parser.add_argument("--chrony-keys", action="store", default="/etc/chrony.keys",
metavar="FILE", help="specify chrony keyfile (default /etc/chrony.keys)")
parser.add_argument("-b", "--backup", action="store_true", help="backup existing configs before writing")
parser.add_argument("-L", "--ignored-lines", action="store_true", help="print ignored lines")
parser.add_argument("-D", "--ignored-directives", action="store_true",
help="print names of ignored directives")
parser.add_argument("-n", "--dry-run", action="store_true", help="don't make any changes")
parser.add_argument("-v", "--verbose", action="count", default=0, help="increase verbosity")
args = parser.parse_args()
logging.basicConfig(format="%(message)s",
level=[logging.ERROR, logging.INFO, logging.DEBUG][min(args.verbose, 2)])
for root in args.roots:
conf = NtpConfiguration(root, args.ntp_conf, args.step_tickers)
if args.ignored_lines:
for line in conf.ignored_lines:
print(line)
if args.ignored_directives:
for directive in conf.ignored_directives:
print(directive)
conf.write_chrony_configuration(args.chrony_conf, args.chrony_keys, args.dry_run, args.backup)
if __name__ == "__main__":
main()

2
sources Normal file
View File

@ -0,0 +1,2 @@
SHA512 (chrony-4.1.tar.gz) = 5e283d6a56e6852606c681a7c29c5786b102d584178cbd7033ebbc95a8e95533605631363b850a3087cca438a5878db7a317f120aab2fd856487d02fccfbcb1f
SHA512 (clknetsim-f89702.tar.gz) = d88d37472b99e4cc044b6c864dfcf5ebb06ef9e2e009ebce06defa07cd46961220707a69c6ec93e35623403a5b4e0683b78b388bf95bfff470fa771d69579c65