Compare commits

...

31 Commits

Author SHA1 Message Date
Miroslav Lichvar
0639205617 doc: update NEWS 2020-09-16 12:09:52 +02:00
Miroslav Lichvar
3916c3366b update copyright years 2020-09-16 12:09:52 +02:00
Miroslav Lichvar
f0a33e7b28 client: drop support for GNU readline
GNU readline switched to GPLv3+ in version 6.0, which is incompatible
with the chrony's GPLv2 license.

Drop support for the readline library. Only editline is supported now.
2020-09-16 12:09:52 +02:00
Miroslav Lichvar
c9b8f8bc70 doc: update and improve FAQ 2020-09-16 12:09:50 +02:00
Miroslav Lichvar
983b0723f6 doc: improve chronyd man page 2020-09-16 12:07:19 +02:00
Miroslav Lichvar
02c38934ea main: add option to disable check for root
The -U option can be used to start chronyd under a non-root user if it
is provided with all capabilities and access to files, directories, and
devices, needed to operate correctly in the specified configuration. It
is not recommended in cases where the configuration is unknown.
2020-09-16 11:39:16 +02:00
Miroslav Lichvar
c28c2cde43 sys_linux: don't keep NET_BIND_SERVICE for unprivileged port
Don't keep the NET_BIND_SERVICE capability if the configured NTP port is
not privileged (i.e. not smaller than 1024).
2020-09-16 11:15:29 +02:00
Miroslav Lichvar
349323dec7 sys_linux: don't keep NET_RAW on new kernels
It seems the NET_RAW capability is no longer needed to bind a socket to
a device since Linux 5.7.
2020-09-16 11:15:29 +02:00
Miroslav Lichvar
ddfaf2e542 ntp: log error when SIOCSHWTSTAMP fails with EPERM
Increase the severity of the log message to "error" when
the SIOCSHWTSTAMP ioctl fails due missing the NET_ADMIN capability.
2020-09-16 11:15:29 +02:00
Miroslav Lichvar
3177474ae8 configure: require TLS1.3 support in gnutls
Before enabling NTS support, explicitly check for TLS1.3 support in
gnutls, which is required by NTS.
2020-09-16 11:15:29 +02:00
Miroslav Lichvar
cc535632d1 test: add ntp_auth unit test 2020-09-16 11:15:29 +02:00
Miroslav Lichvar
cb8ee57b9e test: fix ntp_core unit test
Fix setting of key_id in the response.

Fixes: f6625717cd ("test: improve ntp_core unit test")
2020-09-16 11:15:16 +02:00
Miroslav Lichvar
c0b19b3fea doc: improve chrony.conf man page 2020-09-10 15:04:27 +02:00
Miroslav Lichvar
8235da6885 doc: improve chronyc man page 2020-09-10 14:16:48 +02:00
Miroslav Lichvar
f6625717cd test: improve ntp_core unit test 2020-09-10 13:32:39 +02:00
Miroslav Lichvar
fdfcabd79b ntp: drop support for long NTPv4 MACs
Don't accept NTPv4 packets which have a MAC longer than 24 octets to
strictly follow RFC 7822, which specifies the maximum length of a MAC
and the minimum length of the last extension field to avoid an ambiguity
in parsing of the packet.

This removes an ugly hack that was needed to accept packets that
contained one or more extension fields without a MAC, before RFC 7822
was written and NTP implementations started using truncated MACs.

The long MACs were used by chrony in versions 2.x when configured to
authenticate a server or peer with a key using a 256-bit or longer hash
(e.g. SHA256). For compatibility with chrony >= 4.0, these clients/peers
will need to have "version 3" added to the server/peer line in
chrony.conf.
2020-09-10 13:31:57 +02:00
Miroslav Lichvar
2bb88b45c6 siv: return error if key is not set
Avoid encryption or decryption using uninitialized data, or causing a
crash, if a key was not set for the SIV instance.
2020-09-10 09:36:35 +02:00
Miroslav Lichvar
9820c22c1d nts: improve NTP client code
Reset the client instance more thoroughly and make sure the
nonce cannot be reused.
2020-09-10 09:36:35 +02:00
Miroslav Lichvar
bcd7bad467 client: improve help message for sources command 2020-09-10 09:36:35 +02:00
Miroslav Lichvar
83ea9fe284 cmdmon: rename status constants
Change the naming of reported selection status in the sources report to
better match the internal status.
2020-09-10 09:36:35 +02:00
Miroslav Lichvar
c74d6e458d sources: don't report untrusted sources as selectable
Show untrusted sources with the '?' symbol instead of '-' to make them
consistent with not selectable and selectable sources in the selectdata
description.
2020-09-10 09:36:35 +02:00
Miroslav Lichvar
ff466439fc configure: fix building with -NTP -CMDMON +SCFILTER
Don't enable privileged operations using the nameserv code unless
NTP is enabled.
2020-09-10 09:36:35 +02:00
Miroslav Lichvar
0fcdf4389b nts: log early client NTS-KE socket errors
Log an error message when SCK_OpenTcpSocket() fails in the NTS-KE
client, e.g. when connect() fails due to the port not being allowed in
the SELinux policy.
2020-09-10 09:36:35 +02:00
Miroslav Lichvar
9cb9021c87 cmdmon: remove unused test code 2020-09-09 14:14:54 +02:00
Miroslav Lichvar
9c36236742 cmdmon: check response length before sending
Before sending a cmdmon response, make sure it is not longer than the
request to avoid amplification in case the response/padding length is
incorrectly specified for a request.
2020-09-09 14:14:54 +02:00
Vincent Blut
adebb027be sys_linux: allow readlinkat in seccomp filter 2020-09-01 14:29:43 +02:00
Miroslav Lichvar
7d3798d7cd examples: improve chrony-wait service
Use the systemd TimeoutStartSec setting to report a timeout instead of
an error and reduce the timeout to 3 minutes.
2020-09-01 12:05:06 +02:00
Miroslav Lichvar
b7c7c293e5 conf: add clockprecision directive
Make the precision of the system clock configurable. This can be useful
on servers using hardware timestamping to reduce the amount of noise
added to the NTP timestamps and improve stability of NTP measurements.
2020-09-01 11:21:46 +02:00
Miroslav Lichvar
9ca250755f sys_linux: allow lstat and readlink in seccomp filter
These syscalls seem to be needed when gnutls is loading system trusted
certificates due to p11-kit >= 0.23.21 getting the program name from
/proc/self/exe.
2020-09-01 09:42:31 +02:00
Bryan Christianson
bd3b36865e test: extend frequency in ntp_adjtime() test
Extend the frequency range in the test to cover negative frequencies.
2020-08-31 10:17:21 +02:00
Bryan Christianson
538e1c5eb1 sys_timex: add workaround for broken ntp_adjtime() on macOS
On macOS 11.0 (Big Sur) beta, ntp_adjtime() incorrectly returns
timex.freq as an unsigned number. This patch is a workaround for the bug
and should be removed when Apple fix the problem (assuming they will).
2020-08-31 10:16:51 +02:00
41 changed files with 886 additions and 403 deletions

9
NEWS
View File

@@ -8,11 +8,13 @@ Enhancements
* Add authselectmode directive to control selection of unauthenticated sources * Add authselectmode directive to control selection of unauthenticated sources
* Add binddevice, bindacqdevice, bindcmddevice directives * Add binddevice, bindacqdevice, bindcmddevice directives
* Add confdir directive to better support fragmented configuration * Add confdir directive to better support fragmented configuration
* Add sourcedir directive and "reload sources" command to support * Add sourcedir directive and "reload sources" command to support dynamic
dynamic NTP sources specified in files NTP sources specified in files
* Add clockprecision directive
* Add dscp directive to set Differentiated Services Code Point (DSCP) * Add dscp directive to set Differentiated Services Code Point (DSCP)
* Add -L option to limit log messages by severity * Add -L option to limit log messages by severity
* Add -p option to print whole configuration with included files * Add -p option to print whole configuration with included files
* Add -U option to allow start under non-root user
* Allow maxsamples to be set to 1 for faster update with -q/-Q option * Allow maxsamples to be set to 1 for faster update with -q/-Q option
* Avoid replacing NTP sources with sources that have unreachable address * Avoid replacing NTP sources with sources that have unreachable address
* Improve pools to repeat name resolution to get "maxsources" sources * Improve pools to repeat name resolution to get "maxsources" sources
@@ -38,6 +40,9 @@ Bug fixes
Removed features Removed features
---------------- ----------------
* Drop support for RIPEMD keys (RMD128, RMD160, RMD256, RMD320) * Drop support for RIPEMD keys (RMD128, RMD160, RMD256, RMD320)
* Drop support for long (non-standard) MACs in NTPv4 packets (chrony 2.x
clients using non-MD5/SHA1 keys need to use option "version 3")
* Drop support for line editing with GNU Readline
New in version 3.5.1 New in version 3.5.1
==================== ====================

View File

@@ -553,12 +553,12 @@ typedef struct {
#define RPY_SD_MD_PEER 1 #define RPY_SD_MD_PEER 1
#define RPY_SD_MD_REF 2 #define RPY_SD_MD_REF 2
#define RPY_SD_ST_SYNC 0 #define RPY_SD_ST_SELECTED 0
#define RPY_SD_ST_UNREACH 1 #define RPY_SD_ST_NONSELECTABLE 1
#define RPY_SD_ST_FALSETICKER 2 #define RPY_SD_ST_FALSETICKER 2
#define RPY_SD_ST_JITTERY 3 #define RPY_SD_ST_JITTERY 3
#define RPY_SD_ST_CANDIDATE 4 #define RPY_SD_ST_UNSELECTED 4
#define RPY_SD_ST_OUTLIER 5 #define RPY_SD_ST_SELECTABLE 5
typedef struct { typedef struct {
IPAddr ip_addr; IPAddr ip_addr;

View File

@@ -4,7 +4,7 @@
********************************************************************** **********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003 * Copyright (C) Richard P. Curnow 1997-2003
* Copyright (C) Lonnie Abelbeck 2016, 2018 * Copyright (C) Lonnie Abelbeck 2016, 2018
* Copyright (C) Miroslav Lichvar 2009-2018 * Copyright (C) Miroslav Lichvar 2009-2020
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as * it under the terms of version 2 of the GNU General Public License as
@@ -44,12 +44,7 @@
#include "util.h" #include "util.h"
#ifdef FEAT_READLINE #ifdef FEAT_READLINE
#ifdef USE_EDITLINE
#include <editline/readline.h> #include <editline/readline.h>
#else
#include <readline/readline.h>
#include <readline/history.h>
#endif
#endif #endif
/* ================================================== */ /* ================================================== */
@@ -1267,7 +1262,7 @@ give_help(void)
} }
/* ================================================== */ /* ================================================== */
/* Tab-completion when editline/readline is available */ /* Tab-completion when editline is available */
#ifdef FEAT_READLINE #ifdef FEAT_READLINE
@@ -2146,8 +2141,8 @@ process_cmd_sources(char *line)
if (verbose) { if (verbose) {
printf("\n"); printf("\n");
printf(" .-- Source mode '^' = server, '=' = peer, '#' = local clock.\n"); printf(" .-- Source mode '^' = server, '=' = peer, '#' = local clock.\n");
printf(" / .- Source state '*' = current synced, '+' = combined , '-' = not combined,\n"); printf(" / .- Source state '*' = current best, '+' = combined, '-' = not combined,\n");
printf("| / '?' = unreachable, 'x' = time may be in error, '~' = time too variable.\n"); printf("| / 'x' = may be in error, '~' = too variable, '?' = unusable.\n");
printf("|| .- xxxx [ yyyy ] +/- zzzz\n"); printf("|| .- xxxx [ yyyy ] +/- zzzz\n");
printf("|| Reachability register (octal) -. | xxxx = adjusted offset,\n"); printf("|| Reachability register (octal) -. | xxxx = adjusted offset,\n");
printf("|| Log2(Polling interval) --. | | yyyy = measured offset,\n"); printf("|| Log2(Polling interval) --. | | yyyy = measured offset,\n");
@@ -2189,10 +2184,10 @@ process_cmd_sources(char *line)
} }
switch (ntohs(reply.data.source_data.state)) { switch (ntohs(reply.data.source_data.state)) {
case RPY_SD_ST_SYNC: case RPY_SD_ST_SELECTED:
state_ch = '*'; state_ch = '*';
break; break;
case RPY_SD_ST_UNREACH: case RPY_SD_ST_NONSELECTABLE:
state_ch = '?'; state_ch = '?';
break; break;
case RPY_SD_ST_FALSETICKER: case RPY_SD_ST_FALSETICKER:
@@ -2201,10 +2196,10 @@ process_cmd_sources(char *line)
case RPY_SD_ST_JITTERY: case RPY_SD_ST_JITTERY:
state_ch = '~'; state_ch = '~';
break; break;
case RPY_SD_ST_CANDIDATE: case RPY_SD_ST_UNSELECTED:
state_ch = '+'; state_ch = '+';
break; break;
case RPY_SD_ST_OUTLIER: case RPY_SD_ST_SELECTABLE:
state_ch = '-'; state_ch = '-';
break; break;
default: default:
@@ -3476,7 +3471,7 @@ static void
display_gpl(void) display_gpl(void)
{ {
printf("chrony version %s\n" printf("chrony version %s\n"
"Copyright (C) 1997-2003, 2007, 2009-2019 Richard P. Curnow and others\n" "Copyright (C) 1997-2003, 2007, 2009-2020 Richard P. Curnow and others\n"
"chrony comes with ABSOLUTELY NO WARRANTY. This is free software, and\n" "chrony comes with ABSOLUTELY NO WARRANTY. This is free software, and\n"
"you are welcome to redistribute it under certain conditions. See the\n" "you are welcome to redistribute it under certain conditions. See the\n"
"GNU General Public License version 2 for details.\n\n", "GNU General Public License version 2 for details.\n\n",

View File

@@ -3,7 +3,7 @@
********************************************************************** **********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003 * Copyright (C) Richard P. Curnow 1997-2003
* Copyright (C) Miroslav Lichvar 2009-2016, 2018 * Copyright (C) Miroslav Lichvar 2009-2016, 2018-2020
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as * it under the terms of version 2 of the GNU General Public License as
@@ -294,10 +294,16 @@ CAM_OpenUnixSocket(void)
/* ================================================== */ /* ================================================== */
static void static void
transmit_reply(int sock_fd, SCK_Message *message) transmit_reply(int sock_fd, int request_length, SCK_Message *message)
{ {
message->length = PKL_ReplyLength((CMD_Reply *)message->data); message->length = PKL_ReplyLength((CMD_Reply *)message->data);
if (request_length < message->length) {
DEBUG_LOG("Response longer than request req_len=%d res_len=%d",
request_length, message->length);
return;
}
/* Don't require responses to non-link-local addresses to use the same /* Don't require responses to non-link-local addresses to use the same
interface */ interface */
if (!SCK_IsLinkLocalIPAddress(&message->remote_addr.ip.ip_addr)) if (!SCK_IsLinkLocalIPAddress(&message->remote_addr.ip.ip_addr))
@@ -572,11 +578,8 @@ handle_source_data(CMD_Request *rx_message, CMD_Reply *tx_message)
tx_message->data.source_data.stratum = htons(report.stratum); tx_message->data.source_data.stratum = htons(report.stratum);
tx_message->data.source_data.poll = htons(report.poll); tx_message->data.source_data.poll = htons(report.poll);
switch (report.state) { switch (report.state) {
case RPT_SYNC: case RPT_NONSELECTABLE:
tx_message->data.source_data.state = htons(RPY_SD_ST_SYNC); tx_message->data.source_data.state = htons(RPY_SD_ST_NONSELECTABLE);
break;
case RPT_UNREACH:
tx_message->data.source_data.state = htons(RPY_SD_ST_UNREACH);
break; break;
case RPT_FALSETICKER: case RPT_FALSETICKER:
tx_message->data.source_data.state = htons(RPY_SD_ST_FALSETICKER); tx_message->data.source_data.state = htons(RPY_SD_ST_FALSETICKER);
@@ -584,11 +587,14 @@ handle_source_data(CMD_Request *rx_message, CMD_Reply *tx_message)
case RPT_JITTERY: case RPT_JITTERY:
tx_message->data.source_data.state = htons(RPY_SD_ST_JITTERY); tx_message->data.source_data.state = htons(RPY_SD_ST_JITTERY);
break; break;
case RPT_CANDIDATE: case RPT_SELECTABLE:
tx_message->data.source_data.state = htons(RPY_SD_ST_CANDIDATE); tx_message->data.source_data.state = htons(RPY_SD_ST_SELECTABLE);
break; break;
case RPT_OUTLIER: case RPT_UNSELECTED:
tx_message->data.source_data.state = htons(RPY_SD_ST_OUTLIER); tx_message->data.source_data.state = htons(RPY_SD_ST_UNSELECTED);
break;
case RPT_SELECTED:
tx_message->data.source_data.state = htons(RPY_SD_ST_SELECTED);
break; break;
} }
switch (report.mode) { switch (report.mode) {
@@ -1427,7 +1433,7 @@ read_from_cmd_socket(int sock_fd, int event, void *anything)
if (rx_message.version >= PROTO_VERSION_MISMATCH_COMPAT_SERVER) { if (rx_message.version >= PROTO_VERSION_MISMATCH_COMPAT_SERVER) {
tx_message.status = htons(STT_BADPKTVERSION); tx_message.status = htons(STT_BADPKTVERSION);
transmit_reply(sock_fd, sck_message); transmit_reply(sock_fd, read_length, sck_message);
} }
return; return;
} }
@@ -1437,7 +1443,7 @@ read_from_cmd_socket(int sock_fd, int event, void *anything)
DEBUG_LOG("Command packet has invalid command %d", rx_command); DEBUG_LOG("Command packet has invalid command %d", rx_command);
tx_message.status = htons(STT_INVALID); tx_message.status = htons(STT_INVALID);
transmit_reply(sock_fd, sck_message); transmit_reply(sock_fd, read_length, sck_message);
return; return;
} }
@@ -1446,7 +1452,7 @@ read_from_cmd_socket(int sock_fd, int event, void *anything)
expected_length); expected_length);
tx_message.status = htons(STT_BADPKTLENGTH); tx_message.status = htons(STT_BADPKTLENGTH);
transmit_reply(sock_fd, sck_message); transmit_reply(sock_fd, read_length, sck_message);
return; return;
} }
@@ -1733,19 +1739,7 @@ read_from_cmd_socket(int sock_fd, int event, void *anything)
} }
/* Transmit the response */ /* Transmit the response */
{ transmit_reply(sock_fd, read_length, sck_message);
/* Include a simple way to lose one message in three to test resend */
static int do_it=1;
if (do_it) {
transmit_reply(sock_fd, sck_message);
}
#if 0
do_it = ((do_it + 1) % 3);
#endif
}
} }
/* ================================================== */ /* ================================================== */

13
conf.c
View File

@@ -3,7 +3,7 @@
********************************************************************** **********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003 * Copyright (C) Richard P. Curnow 1997-2003
* Copyright (C) Miroslav Lichvar 2009-2017 * Copyright (C) Miroslav Lichvar 2009-2017, 2020
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as * it under the terms of version 2 of the GNU General Public License as
@@ -100,6 +100,7 @@ static double correction_time_ratio = 3.0;
static double max_clock_error = 1.0; /* in ppm */ static double max_clock_error = 1.0; /* in ppm */
static double max_drift = 500000.0; /* in ppm */ static double max_drift = 500000.0; /* in ppm */
static double max_slew_rate = 1e6 / 12.0; /* in ppm */ static double max_slew_rate = 1e6 / 12.0; /* in ppm */
static double clock_precision = 0.0; /* in seconds */
static SRC_AuthSelectMode authselect_mode = SRC_AUTHSELECT_MIX; static SRC_AuthSelectMode authselect_mode = SRC_AUTHSELECT_MIX;
static double max_distance = 3.0; static double max_distance = 3.0;
@@ -544,6 +545,8 @@ CNF_ParseLine(const char *filename, int number, char *line)
parse_broadcast(p); parse_broadcast(p);
} else if (!strcasecmp(command, "clientloglimit")) { } else if (!strcasecmp(command, "clientloglimit")) {
parse_clientloglimit(p); parse_clientloglimit(p);
} else if (!strcasecmp(command, "clockprecision")) {
parse_double(p, &clock_precision);
} else if (!strcasecmp(command, "cmdallow")) { } else if (!strcasecmp(command, "cmdallow")) {
parse_allow_deny(p, cmd_restrictions, 1); parse_allow_deny(p, cmd_restrictions, 1);
} else if (!strcasecmp(command, "cmddeny")) { } else if (!strcasecmp(command, "cmddeny")) {
@@ -2048,6 +2051,14 @@ CNF_GetMaxSlewRate(void)
/* ================================================== */ /* ================================================== */
double
CNF_GetClockPrecision(void)
{
return clock_precision;
}
/* ================================================== */
double double
CNF_GetMaxDistance(void) CNF_GetMaxDistance(void)
{ {

1
conf.h
View File

@@ -95,6 +95,7 @@ extern double CNF_GetMaxClockError(void);
extern double CNF_GetMaxDrift(void); extern double CNF_GetMaxDrift(void);
extern double CNF_GetCorrectionTimeRatio(void); extern double CNF_GetCorrectionTimeRatio(void);
extern double CNF_GetMaxSlewRate(void); extern double CNF_GetMaxSlewRate(void);
extern double CNF_GetClockPrecision(void);
extern SRC_AuthSelectMode CNF_GetAuthSelectMode(void); extern SRC_AuthSelectMode CNF_GetAuthSelectMode(void);
extern double CNF_GetMaxDistance(void); extern double CNF_GetMaxDistance(void);

64
configure vendored
View File

@@ -5,7 +5,7 @@
# #
# Copyright (C) Richard P. Curnow 1997-2003 # Copyright (C) Richard P. Curnow 1997-2003
# Copyright (C) Bryan Christianson 2016 # Copyright (C) Bryan Christianson 2016
# Copyright (C) Miroslav Lichvar 2009, 2012-2018 # Copyright (C) Miroslav Lichvar 2009, 2012-2020
# Copyright (C) Stefan R. Filipek 2019 # Copyright (C) Stefan R. Filipek 2019
# #
# ======================================================================= # =======================================================================
@@ -108,11 +108,7 @@ for instance \`--prefix=$HOME'.
For better control, use the options below. For better control, use the options below.
--disable-readline Disable line editing support --disable-readline Disable line editing support
--without-readline Don't use GNU readline even if it is available
--without-editline Don't use editline even if it is available --without-editline Don't use editline even if it is available
--with-readline-includes=DIR Specify where readline include directory is
--with-readline-library=DIR Specify where readline lib directory is
--with-ncurses-library=DIR Specify where ncurses lib directory is
--disable-sechash Disable support for hashes other than MD5 --disable-sechash Disable support for hashes other than MD5
--without-nettle Don't use nettle even if it is available --without-nettle Don't use nettle even if it is available
--without-nss Don't use NSS even if it is available --without-nss Don't use NSS even if it is available
@@ -225,7 +221,6 @@ feat_cmdmon=1
feat_ntp=1 feat_ntp=1
feat_refclock=1 feat_refclock=1
feat_readline=1 feat_readline=1
try_readline=1
try_editline=1 try_editline=1
feat_sechash=1 feat_sechash=1
try_nettle=1 try_nettle=1
@@ -241,9 +236,6 @@ try_clockctl=0
feat_scfilter=0 feat_scfilter=0
try_seccomp=-1 try_seccomp=-1
priv_ops="" priv_ops=""
readline_lib=""
readline_inc=""
ncurses_lib=""
feat_ipv6=1 feat_ipv6=1
feat_phc=1 feat_phc=1
try_phc=0 try_phc=0
@@ -274,21 +266,9 @@ do
--disable-readline ) --disable-readline )
feat_readline=0 feat_readline=0
;; ;;
--without-readline )
try_readline=0
;;
--without-editline ) --without-editline )
try_editline=0 try_editline=0
;; ;;
--with-readline-library=* )
readline_lib=-L`echo $option | sed -e 's/^.*=//;'`
;;
--with-readline-includes=* )
readline_inc=-I`echo $option | sed -e 's/^.*=//;'`
;;
--with-ncurses-library=* )
ncurses_lib=-L`echo $option | sed -e 's/^.*=//;'`
;;
--prefix=* | --install_prefix=* ) --prefix=* | --install_prefix=* )
SETPREFIX=`echo $option | sed -e 's/[^=]*=//;'` SETPREFIX=`echo $option | sed -e 's/[^=]*=//;'`
;; ;;
@@ -804,10 +784,12 @@ if [ $feat_scfilter = "1" ] && [ $try_seccomp = "1" ] && \
'seccomp_init(SCMP_ACT_KILL);' 'seccomp_init(SCMP_ACT_KILL);'
then then
add_def FEAT_SCFILTER add_def FEAT_SCFILTER
# NAME2IPADDRESS shouldn't be enabled with other operations as the helper if [ $feat_ntp = "1" ]; then
# process works on one request at the time and the async resolver could # NAME2IPADDRESS shouldn't be enabled together with a privops operation
# block the main thread # used by the main thread as the helper process works on one request at
priv_ops="NAME2IPADDRESS RELOADDNS" # a time and the async resolver would block the main thread
priv_ops="NAME2IPADDRESS RELOADDNS"
fi
EXTRA_LIBS="$EXTRA_LIBS -lseccomp" EXTRA_LIBS="$EXTRA_LIBS -lseccomp"
fi fi
@@ -876,37 +858,11 @@ fi
READLINE_LINK="" READLINE_LINK=""
if [ $feat_readline = "1" ]; then if [ $feat_readline = "1" ]; then
if [ $try_editline = "1" ]; then if [ $try_editline = "1" ]; then
if test_code editline 'stdio.h editline/readline.h' \ if test_code editline 'stdio.h editline/readline.h' '' '-ledit' \
"$readline_inc" "$readline_lib -ledit" \
'add_history(readline("prompt"));' 'add_history(readline("prompt"));'
then then
add_def FEAT_READLINE add_def FEAT_READLINE
add_def USE_EDITLINE READLINE_LINK="-ledit"
MYCPPFLAGS="$MYCPPFLAGS $readline_inc"
READLINE_LINK="$readline_lib -ledit"
fi
fi
if [ "x$READLINE_LINK" = "x" ] && [ $try_readline = "1" ]; then
if test_code readline 'stdio.h readline/readline.h readline/history.h' \
"$readline_inc" "$readline_lib -lreadline" \
'add_history(readline("prompt"));'
then
add_def FEAT_READLINE
MYCPPFLAGS="$MYCPPFLAGS $readline_inc"
READLINE_LINK="$readline_lib -lreadline"
fi
fi
if [ "x$READLINE_LINK" = "x" ] && [ $try_readline = "1" ]; then
if test_code 'readline with -lncurses' \
'stdio.h readline/readline.h readline/history.h' \
"$readline_inc" "$readline_lib $ncurses_lib -lreadline -lncurses" \
'add_history(readline("prompt"));'
then
add_def FEAT_READLINE
MYCPPFLAGS="$MYCPPFLAGS $readline_inc"
READLINE_LINK="$readline_lib $ncurses_lib -lreadline -lncurses"
fi fi
fi fi
@@ -972,7 +928,7 @@ if [ $feat_ntp = "1" ] && [ $feat_nts = "1" ] && [ $try_gnutls = "1" ]; then
test_link="`pkg_config --libs gnutls`" test_link="`pkg_config --libs gnutls`"
if test_code 'gnutls' 'gnutls/gnutls.h' \ if test_code 'gnutls' 'gnutls/gnutls.h' \
"$test_cflags" "$test_link" ' "$test_cflags" "$test_link" '
return gnutls_init(NULL, 0) + return gnutls_init(NULL, 0) + GNUTLS_TLS1_3 +
gnutls_priority_init2(NULL, "", NULL, GNUTLS_PRIORITY_INIT_DEF_APPEND) + gnutls_priority_init2(NULL, "", NULL, GNUTLS_PRIORITY_INIT_DEF_APPEND) +
gnutls_prf_rfc5705(NULL, 0, "", 0, "", 16, NULL);' gnutls_prf_rfc5705(NULL, 0, "", 0, "", 16, NULL);'
then then

View File

@@ -3,7 +3,7 @@
// Copyright (C) Richard P. Curnow 1997-2003 // Copyright (C) Richard P. Curnow 1997-2003
// Copyright (C) Stephen Wadeley 2016 // Copyright (C) Stephen Wadeley 2016
// Copyright (C) Bryan Christianson 2017 // Copyright (C) Bryan Christianson 2017
// Copyright (C) Miroslav Lichvar 2009-2017 // Copyright (C) Miroslav Lichvar 2009-2020
// //
// This program is free software; you can redistribute it and/or modify // This program is free software; you can redistribute it and/or modify
// it under the terms of version 2 of the GNU General Public License as // it under the terms of version 2 of the GNU General Public License as
@@ -32,12 +32,14 @@ chrony.conf - chronyd configuration file
== DESCRIPTION == DESCRIPTION
This file configures the *chronyd* daemon. The compiled-in location is This file configures the *chronyd* daemon. The compiled-in location is
_@SYSCONFDIR@/chrony.conf_, but other locations can be specified on the _@SYSCONFDIR@/chrony.conf_. Other locations can be specified on the
*chronyd* command line with the *-f* option. *chronyd* command line with the *-f* option.
Each directive in the configuration file is placed on a separate line. The Each directive in the configuration file is placed on a separate line. The
following sections describe each of the directives in turn. The directives can following sections describe each of the directives in turn. The directives are
occur in any order in the file and they are not case-sensitive. not case-sensitive. Generally, the directives can occur in any order in the file
and if a directive is specified multiple times, only the last one will be
effective. Exceptions are noted in the descriptions.
The configuration directives can also be specified directly on the *chronyd* The configuration directives can also be specified directly on the *chronyd*
command line. In this case each argument is parsed as a new line and the command line. In this case each argument is parsed as a new line and the
@@ -61,9 +63,10 @@ source. The client-server relationship is strictly hierarchical: a client might
synchronise its system time to that of the server, but the server's system time synchronise its system time to that of the server, but the server's system time
will never be influenced by that of a client. will never be influenced by that of a client.
+ +
The *server* directive is immediately followed by either the name of the This directive can be used multiple times to specify multiple servers.
server, or its IP address. The *server* directive supports the following +
options: The directive is immediately followed by either the name of the
server, or its IP address. It supports the following options:
+ +
*minpoll* _poll_::: *minpoll* _poll_:::
This option specifies the minimum interval between requests sent to the server This option specifies the minimum interval between requests sent to the server
@@ -276,6 +279,8 @@ directive, except that it is used to specify a pool of NTP servers rather than
a single NTP server. The pool name is expected to resolve to multiple addresses a single NTP server. The pool name is expected to resolve to multiple addresses
which might change over time. which might change over time.
+ +
This directive can be used multiple times to specify multiple pools.
+
All options valid in the <<server,*server*>> directive can be used in this All options valid in the <<server,*server*>> directive can be used in this
directive too. There is one option specific to the *pool* directive: directive too. There is one option specific to the *pool* directive:
+ +
@@ -306,6 +311,8 @@ is mainly useful when the NTP implementation of the peer (e.g. *ntpd*) supports
ephemeral symmetric associations and does not need to be configured with an ephemeral symmetric associations and does not need to be configured with an
address of this host. *chronyd* does not support ephemeral associations. address of this host. *chronyd* does not support ephemeral associations.
+ +
This directive can be used multiple times to specify multiple peers.
+
The following options of the *server* directive do not work in the *peer* The following options of the *server* directive do not work in the *peer*
directive: *iburst*, *burst*, *nts*, *presend*. directive: *iburst*, *burst*, *nts*, *presend*.
+ +
@@ -398,6 +405,8 @@ driver-specific parameter. The two parameters are followed by zero or more
refclock options. Some drivers have special options, which can be appended to refclock options. Some drivers have special options, which can be appended to
the driver-specific parameter using the *:* character. the driver-specific parameter using the *:* character.
+ +
This directive can be used multiple times to specify multiple reference clocks.
+
There are four drivers included in *chronyd*: There are four drivers included in *chronyd*:
+ +
*PPS*::: *PPS*:::
@@ -610,12 +619,13 @@ behaviour, whereas the *settime* command allows samples of manually entered
time to be provided.) time to be provided.)
[[acquisitionport]]*acquisitionport* _port_:: [[acquisitionport]]*acquisitionport* _port_::
By default, *chronyd* uses a separate client socket for each configured server By default, *chronyd* as an NTP client opens a new socket for each request with
and their source port is chosen arbitrarily by the operating system. However, the source port chosen randomly by the operating system. The *acquisitionport*
you can use the *acquisitionport* directive to explicitly specify a port and directive can be used to specify the source port and use only one socket (per
use only one socket (per IPv4 or IPv6 address family) for all configured servers. IPv4 or IPv6 address family) for all configured servers. This can be useful for
This can be useful for getting through some firewalls. If set to 0, the source getting through some firewalls. It should not be used if not necessary as there
port of the socket will be chosen arbitrarily. is a small impact on security of the client. If set to 0, the source port of
the permanent socket will be chosen randomly by the operating system.
+ +
It can be set to the same port as is used by the NTP server (which can be It can be set to the same port as is used by the NTP server (which can be
configured with the <<port,*port*>> directive) to use only one socket for all configured with the <<port,*port*>> directive) to use only one socket for all
@@ -632,8 +642,8 @@ You could then persuade the firewall administrator to open that port.
[[bindacqaddress]]*bindacqaddress* _address_:: [[bindacqaddress]]*bindacqaddress* _address_::
The *bindacqaddress* directive specifies a local IP address to which The *bindacqaddress* directive specifies a local IP address to which
*chronyd* will bind its NTP client sockets. The syntax is similar to the *chronyd* will bind its NTP and NTS-KE client sockets. The syntax is similar to
<<bindaddress,*bindaddress*>> and <<bindcmdaddress,*bindcmdaddress*>> the <<bindaddress,*bindaddress*>> and <<bindcmdaddress,*bindcmdaddress*>>
directives. directives.
+ +
For each of the IPv4 and IPv6 protocols, only one *bindacqaddress* directive For each of the IPv4 and IPv6 protocols, only one *bindacqaddress* directive
@@ -908,6 +918,27 @@ distances are in milliseconds.
=== System clock === System clock
[[clockprecision]]*clockprecision* _precision_::
The *clockprecision* directive specifies the precision of the system clock (in
seconds). It is used by *chronyd* to estimate the minimum noise in NTP
measurements and randomise low-order bits of timestamps in NTP responses. By
default, the precision is measured on start as the minimum time to read the
clock.
+
The measured value works well in most cases. However, it generally
overestimates the precision and it can be sensitive to the CPU speed, which can
change over time to save power. In some cases with a high-precision clocksource
(e.g. the Time Stamp Counter of the CPU) and hardware timestamping, setting the
precision on the server to a smaller value can improve stability of clients'
NTP measurements. The server's precision is reported on clients by the
<<chronyc.adoc#ntpdata,*ntpdata*>> command.
+
An example setting the precision to 8 nanoseconds is:
+
----
clockprecision 8e-9
----
[[corrtimeratio]]*corrtimeratio* _ratio_:: [[corrtimeratio]]*corrtimeratio* _ratio_::
When *chronyd* is slewing the system clock to correct an offset, the rate at When *chronyd* is slewing the system clock to correct an offset, the rate at
which it is slewing adds to the frequency error of the clock. On all supported which it is slewing adds to the frequency error of the clock. On all supported
@@ -1039,7 +1070,7 @@ A recommended configuration to enable a server leap smear is:
---- ----
leapsecmode slew leapsecmode slew
maxslewrate 1000 maxslewrate 1000
smoothtime 400 0.001 leaponly smoothtime 400 0.001024 leaponly
---- ----
+ +
The first directive is necessary to disable the clock step which would reset The first directive is necessary to disable the clock step which would reset
@@ -1047,11 +1078,17 @@ the smoothing process. The second directive limits the slewing rate of the
local clock to 1000 ppm, which improves the stability of the smoothing process local clock to 1000 ppm, which improves the stability of the smoothing process
when the local correction starts and ends. The third directive enables the when the local correction starts and ends. The third directive enables the
server time smoothing process. It will start when the clock gets to 00:00:00 server time smoothing process. It will start when the clock gets to 00:00:00
UTC and it will take 17 hours 34 minutes to finish. The frequency offset will UTC and it will take 62500 seconds (about 17.36 hours) to finish. The frequency
be changing by 0.001 ppm per second and will reach a maximum of 31.623 ppm. The offset will be changing by 0.001024 ppm per second and will reach a maximum of
*leaponly* option makes the duration of the leap smear constant and allows the 32 ppm in 31250 seconds. The *leaponly* option makes the duration of the leap
clients to safely synchronise with multiple identically configured leap smear constant and allows the clients to safely synchronise with multiple
smearing servers. identically configured leap smearing servers.
+
The duration of the leap smear can be calculated from the specified wander as
+
----
duration = sqrt(4 / wander)
----
[[leapsectz]]*leapsectz* _timezone_:: [[leapsectz]]*leapsectz* _timezone_::
This directive specifies a timezone in the system tz database which *chronyd* This directive specifies a timezone in the system tz database which *chronyd*
@@ -1221,7 +1258,7 @@ coefficients _T0_, _k0_, _k1_, _k2_.
The frequency compensation is calculated (in ppm) as The frequency compensation is calculated (in ppm) as
+ +
---- ----
k0 + (T - T0) * k1 + (T - T0)^2 * k2 comp = k0 + (T - T0) * k1 + (T - T0)^2 * k2
---- ----
+ +
The result has to be between -10 ppm and 10 ppm, otherwise the measurement is The result has to be between -10 ppm and 10 ppm, otherwise the measurement is
@@ -1272,12 +1309,15 @@ _tempcomp.log_ file if enabled by the <<log,*log tempcomp*>> directive.
[[allow]]*allow* [*all*] [_subnet_]:: [[allow]]*allow* [*all*] [_subnet_]::
The *allow* directive is used to designate a particular subnet from which NTP The *allow* directive is used to designate a particular subnet from which NTP
clients are allowed to access the computer as an NTP server. clients are allowed to access the computer as an NTP server. It also controls
access of NTS-KE clients when NTS is enabled on the server.
+ +
The default is that no clients are allowed access, i.e. *chronyd* operates The default is that no clients are allowed access, i.e. *chronyd* operates
purely as an NTP client. If the *allow* directive is used, *chronyd* will be purely as an NTP client. If the *allow* directive is used, *chronyd* will be
both a client of its servers, and a server to other clients. both a client of its servers, and a server to other clients.
+ +
This directive can be used multiple times.
+
Examples of the use of the directive are as follows: Examples of the use of the directive are as follows:
+ +
---- ----
@@ -1344,18 +1384,19 @@ client access by this computer for it to work.
[[deny]]*deny* [*all*] [_subnet_]:: [[deny]]*deny* [*all*] [_subnet_]::
This is similar to the <<allow,*allow*>> directive, except that it denies NTP This is similar to the <<allow,*allow*>> directive, except that it denies NTP
client access to a particular subnet or host, rather than allowing it. and NTS-KE client access to a particular subnet or host, rather than allowing
it.
+ +
The syntax is identical. The syntax is identical and the directive can be used multiple times too.
+ +
There is also a *deny all* directive with similar behaviour to the *allow all* There is also a *deny all* directive with similar behaviour to the *allow all*
directive. directive.
[[bindaddress]]*bindaddress* _address_:: [[bindaddress]]*bindaddress* _address_::
The *bindaddress* directive binds the socket on which *chronyd* listens for NTP The *bindaddress* directive binds the sockets on which *chronyd* listens for
requests to a local address of the computer. On systems other than Linux, the NTP and NTS-KE requests to a local address of the computer. On systems other
address of the computer needs to be already configured when *chronyd* is than Linux, the address of the computer needs to be already configured when
started. *chronyd* is started.
+ +
An example of the use of the directive is: An example of the use of the directive is:
+ +
@@ -1368,9 +1409,9 @@ directive can be specified. Therefore, it is not useful on computers which
should serve NTP on multiple network interfaces. should serve NTP on multiple network interfaces.
[[binddevice]]*binddevice* _interface_:: [[binddevice]]*binddevice* _interface_::
The *binddevice* directive binds the NTP server sockets to a network device The *binddevice* directive binds the NTP and NTS-KE server sockets to a network
specified by the interface name. This directive can specify only one interface device specified by the interface name. This directive can specify only one
and it is supported on Linux only. interface and it is supported on Linux only.
+ +
An example of the directive is: An example of the directive is:
+ +
@@ -1384,6 +1425,8 @@ chronyd should send packets in the NTP broadcast mode (i.e. make *chronyd* act
as a broadcast server). Broadcast clients on that subnet will be able to as a broadcast server). Broadcast clients on that subnet will be able to
synchronise. synchronise.
+ +
This directive can be used multiple times to specify multiple addresses.
+
The syntax is as follows: The syntax is as follows:
+ +
---- ----
@@ -1483,7 +1526,9 @@ configuration and to be synchronised to one another, without confusing clients
that poll more than one server. Each server needs to be configured to poll all that poll more than one server. Each server needs to be configured to poll all
other servers with the *local* directive. This ensures only the server with the other servers with the *local* directive. This ensures only the server with the
smallest reference ID has the local reference active and others are smallest reference ID has the local reference active and others are
synchronised to it. When that server fails, another will take over. synchronised to it. If that server stops responding, the server with the second
smallest reference ID will take over when its local reference mode activates
(root distance reaches the threshold configured by the *distance* option).
+ +
The *orphan* mode is compatible with the *ntpd*'s orphan mode (enabled by the The *orphan* mode is compatible with the *ntpd*'s orphan mode (enabled by the
*tos orphan* command). *tos orphan* command).
@@ -1492,7 +1537,7 @@ The *orphan* mode is compatible with the *ntpd*'s orphan mode (enabled by the
An example of the directive is: An example of the directive is:
+ +
---- ----
local stratum 10 orphan local stratum 10 orphan distance 0.1
---- ----
[[ntpsigndsocket]]*ntpsigndsocket* _directory_:: [[ntpsigndsocket]]*ntpsigndsocket* _directory_::
@@ -1822,7 +1867,8 @@ The *rtcautotrim* directive is used to keep the RTC close to the system clock
automatically. When the system clock is synchronised and the estimated error automatically. When the system clock is synchronised and the estimated error
between the two clocks is larger than the specified threshold, *chronyd* will between the two clocks is larger than the specified threshold, *chronyd* will
trim the RTC as if the <<chronyc.adoc#trimrtc,*trimrtc*>> command in *chronyc* trim the RTC as if the <<chronyc.adoc#trimrtc,*trimrtc*>> command in *chronyc*
was issued. was issued. The trimming operation is accurate to only about 1 second, which is
the minimum effective threshold.
+ +
This directive is effective only with the <<rtcfile,*rtcfile*>> directive. This directive is effective only with the <<rtcfile,*rtcfile*>> directive.
+ +
@@ -2202,6 +2248,8 @@ name, only the first file in the order of the specified directories will be
included. This enables a fragmented configuration where existing fragments can included. This enables a fragmented configuration where existing fragments can
be replaced by adding files to a different directory. be replaced by adding files to a different directory.
+ +
This directive can be used multiple times.
+
An example of the directive is: An example of the directive is:
+ +
---- ----
@@ -2217,6 +2265,8 @@ reloaded by the <<chronyc.adoc#reload,*reload sources*>> command in
received from a DHCP server, which can be written to a file specific to the received from a DHCP server, which can be written to a file specific to the
network interface by a networking script. network interface by a networking script.
+ +
This directive can be used multiple times.
+
An example of the directive is: An example of the directive is:
+ +
---- ----
@@ -2229,6 +2279,8 @@ files if a wildcard pattern is specified. Unlike with the *confdir* directive,
the full name of the files needs to be specified and at least one file is the full name of the files needs to be specified and at least one file is
required to exist. required to exist.
+ +
This directive can be used multiple times.
+
An example of the directive is: An example of the directive is:
+ +
---- ----
@@ -2264,8 +2316,9 @@ indicated in the _measurements.log_ file if enabled by the <<log,*log
measurements*>> directive, and the <<chronyc.adoc#ntpdata,*ntpdata*>> report in measurements*>> directive, and the <<chronyc.adoc#ntpdata,*ntpdata*>> report in
*chronyc*. *chronyc*.
+ +
If the specified interface is _*_, *chronyd* will try to enable HW timestamping This directive can be used multiple times to enable HW timestamping on multiple
on all available interfaces. interfaces. If the specified interface is _*_, *chronyd* will try to enable HW
timestamping on all available interfaces.
+ +
The *hwtimestamp* directive has the following options: The *hwtimestamp* directive has the following options:
+ +
@@ -2497,6 +2550,20 @@ makestep 1.0 3
rtcsync rtcsync
---- ----
If the servers (or pool) support the Network Time Security (NTS)
authentication mechanism and *chronyd* is compiled with NTS support, the *nts*
option will enable a secure synchronisation to the servers. The configuration
file could look like:
----
server foo.example.net iburst nts
server bar.example.net iburst nts
server baz.example.net iburst nts
driftfile @CHRONYVARDIR@/drift
makestep 1.0 3
rtcsync
----
=== NTP client with infrequent connection to NTP servers === NTP client with infrequent connection to NTP servers
This section shows how to configure *chronyd* for computers that have This section shows how to configure *chronyd* for computers that have

View File

@@ -2,7 +2,7 @@
// //
// Copyright (C) Richard P. Curnow 1997-2003 // Copyright (C) Richard P. Curnow 1997-2003
// Copyright (C) Stephen Wadeley 2016 // Copyright (C) Stephen Wadeley 2016
// Copyright (C) Miroslav Lichvar 2009-2017 // Copyright (C) Miroslav Lichvar 2009-2017, 2019-2020
// //
// This program is free software; you can redistribute it and/or modify // This program is free software; you can redistribute it and/or modify
// it under the terms of version 2 of the GNU General Public License as // it under the terms of version 2 of the GNU General Public License as
@@ -39,7 +39,7 @@ running.
If no commands are specified on the command line, *chronyc* will expect input If no commands are specified on the command line, *chronyc* will expect input
from the user. The prompt _chronyc>_ will be displayed when it is being run from the user. The prompt _chronyc>_ will be displayed when it is being run
from a terminal. If *chronyc*'s input or output are redirected from or to a file, from a terminal. If *chronyc*'s input or output are redirected from or to a file,
the prompt is not shown. the prompt will not be shown.
There are two ways *chronyc* can access *chronyd*. One is the Internet There are two ways *chronyc* can access *chronyd*. One is the Internet
Protocol (IPv4 or IPv6) and the other is a Unix domain socket, which is Protocol (IPv4 or IPv6) and the other is a Unix domain socket, which is
@@ -60,9 +60,7 @@ default, the commands are accepted only from localhost (127.0.0.1 or ::1).
All other commands are allowed only through the Unix domain socket. When sent All other commands are allowed only through the Unix domain socket. When sent
over the network, *chronyd* will respond with a '`Not authorised`' error, even over the network, *chronyd* will respond with a '`Not authorised`' error, even
if it is from localhost. In chrony versions before 2.2 they were allowed if it is from localhost.
from the network if they were authenticated with a password, but that is no
longer supported.
Having full access to *chronyd* via *chronyc* is more or less equivalent to Having full access to *chronyd* via *chronyc* is more or less equivalent to
being able to modify the *chronyd*'s configuration file and restart it. being able to modify the *chronyd*'s configuration file and restart it.
@@ -183,10 +181,12 @@ speeding up or slowing down the system clock until the error has been removed,
and then returning to the system clock's normal speed. A consequence of this is and then returning to the system clock's normal speed. A consequence of this is
that there will be a period when the system clock (as read by other programs) that there will be a period when the system clock (as read by other programs)
will be different from *chronyd*'s estimate of the current true time (which it will be different from *chronyd*'s estimate of the current true time (which it
reports to NTP clients when it is operating in server mode). The value reported reports to NTP clients when it is operating as a server). The value reported
on this line is the difference due to this effect. on this line is the difference due to this effect.
*Last offset*::: *Last offset*:::
This is the estimated local offset on the last clock update. This is the estimated local offset on the last clock update. A positive value
indicates the local time (as previously estimated true time) was ahead of the
time sources.
*RMS offset*::: *RMS offset*:::
This is a long-term average of the offset value. This is a long-term average of the offset value.
*Frequency*::: *Frequency*:::
@@ -317,18 +317,23 @@ The columns are as follows:
This indicates the mode of the source. _^_ means a server, _=_ means a peer This indicates the mode of the source. _^_ means a server, _=_ means a peer
and _#_ indicates a locally connected reference clock. and _#_ indicates a locally connected reference clock.
*S*::: *S*:::
This column indicates the state of the source. This column indicates the selection state of the source.
* _*_ indicates the source to which *chronyd* is currently synchronised. * _*_ indicates the best source which is currently selected for
* _+_ indicates acceptable sources which are combined with the selected synchronisation.
source. * _+_ indicates other sources selected for synchronisation, which are combined
* _-_ indicates acceptable sources which are excluded by the combining with the best source.
algorithm. * _-_ indicates a source which is considered to be selectable for
* _?_ indicates sources to which connectivity has been lost or whose packets synchronisation, but not currently selected.
do not pass all tests. It is also shown at start-up, until at least 3 samples * _x_ indicates a source which *chronyd* thinks is a falseticker (i.e. its
have been gathered from it. time is inconsistent with a majority of other sources, or sources specified
* _x_ indicates a clock which *chronyd* thinks is a falseticker (i.e. its with the *trust* option).
time is inconsistent with a majority of other sources).
* _~_ indicates a source whose time appears to have too much variability. * _~_ indicates a source whose time appears to have too much variability.
* _?_ indicates a source which is not considered to be selectable for
synchronisation for other reasons (e.g. unreachable, not synchronised, or
does not have enough measurements).
{blank}:::
The <<selectdata,*selectdata*>> command can be used to get more details about
the selection state.
*Name/IP address*::: *Name/IP address*:::
This shows the name or the IP address of the source, or reference ID for reference This shows the name or the IP address of the source, or reference ID for reference
clocks. clocks.
@@ -1328,10 +1333,7 @@ purged. An example of how to do this is shown below.
---- ----
# mv /var/log/chrony/measurements.log /var/log/chrony/measurements1.log # mv /var/log/chrony/measurements.log /var/log/chrony/measurements1.log
# chronyc cyclelogs # chronyc cyclelogs
# ls -l /var/log/chrony # rm /var/log/chrony/measurements1.log
-rw-r--r-- 1 root root 0 Jun 8 18:17 measurements.log
-rw-r--r-- 1 root root 12345 Jun 8 18:17 measurements1.log
# rm -f measurements1.log
---- ----
[[dump]]*dump*:: [[dump]]*dump*::
@@ -1356,7 +1358,9 @@ The *reset sources* command causes *chronyd* to drop all measurements and
switch to the unsynchronised state. This command can help *chronyd* with switch to the unsynchronised state. This command can help *chronyd* with
recovery when the measurements are known to be no longer valid or accurate, recovery when the measurements are known to be no longer valid or accurate,
e.g. due to moving the computer to a different network, or resuming the e.g. due to moving the computer to a different network, or resuming the
computer from a low-power state (which resets the system clock). computer from a low-power state (which resets the system clock). *chronyd* will
drop the measurements automatically when it detects the clock has made an
unexpected jump, but the detection is not completely reliable.
[[shutdown]]*shutdown*:: [[shutdown]]*shutdown*::
The *shutdown* command causes *chronyd* to exit. This is equivalent to sending The *shutdown* command causes *chronyd* to exit. This is equivalent to sending
@@ -1423,7 +1427,13 @@ keygen 73 SHA1 256
+ +
which generates a 256-bit SHA1 key with number 73. The printed line should which generates a 256-bit SHA1 key with number 73. The printed line should
then be securely transferred and added to the key files on both server and then be securely transferred and added to the key files on both server and
client, or peers. client, or peers. A different key should be generated for each client or peer.
+
An example using the AES128 cipher is:
+
----
keygen 151 AES128
----
[[exit]]*exit*:: [[exit]]*exit*::
[[quit]]*quit*:: [[quit]]*quit*::

View File

@@ -55,7 +55,7 @@ IPv6 sockets will be created.
*-f* _file_:: *-f* _file_::
This option can be used to specify an alternate location for the configuration This option can be used to specify an alternate location for the configuration
file. The default value is _@SYSCONFDIR@/chrony.conf_. file. The compiled-in default value is _@SYSCONFDIR@/chrony.conf_.
*-n*:: *-n*::
When run in this mode, the program will not detach itself from the terminal. When run in this mode, the program will not detach itself from the terminal.
@@ -137,7 +137,7 @@ running, but still allow it to adjust the frequency of the system clock.
*-u* _user_:: *-u* _user_::
This option sets the name of the system user to which *chronyd* will switch This option sets the name of the system user to which *chronyd* will switch
after start in order to drop root privileges. It overrides the after start in order to drop root privileges. It overrides the
<<chrony.conf.adoc#user,*user*>> directive. The default value is <<chrony.conf.adoc#user,*user*>> directive. The compiled-in default value is
_@DEFAULT_USER@_. _@DEFAULT_USER@_.
+ +
On Linux, *chronyd* needs to be compiled with support for the *libcap* library. On Linux, *chronyd* needs to be compiled with support for the *libcap* library.
@@ -145,6 +145,16 @@ On macOS, FreeBSD, NetBSD and Solaris *chronyd* forks into two processes.
The child process retains root privileges, but can only perform a very limited The child process retains root privileges, but can only perform a very limited
range of privileged system calls on behalf of the parent. range of privileged system calls on behalf of the parent.
*-U*::
This option disables a check for root privileges to allow *chronyd* to be
started under a non-root user, assuming the process will have all capabilities
(e.g. provided by the service manager) and access to all files, directories,
and devices, needed to operate correctly in the specified configuration. Note
that different capabilities might be needed with different configurations and
different Linux kernel versions. Starting *chronyd* under a non-root user is
not recommended when the configuration is not known, or at least limited to
specific directives.
*-F* _level_:: *-F* _level_::
This option configures a system call filter when *chronyd* is compiled with This option configures a system call filter when *chronyd* is compiled with
support for the Linux secure computing (seccomp) facility. In level 1 the support for the Linux secure computing (seccomp) facility. In level 1 the
@@ -152,10 +162,10 @@ process is killed when a forbidden system call is made, in level -1 the SIGSYS
signal is thrown instead and in level 0 the filter is disabled. The default signal is thrown instead and in level 0 the filter is disabled. The default
value is 0. value is 0.
+ +
It's recommended to enable the filter only when it's known to work on the It is recommended to enable the filter only when it is known to work on the
version of the system where *chrony* is installed as the filter needs to allow version of the system where *chrony* is installed as the filter needs to allow
also system calls made from libraries that *chronyd* is using (e.g. libc) and also system calls made from libraries that *chronyd* is using (e.g. libc) and
different versions or implementations of the libraries may make different different versions or implementations of the libraries might make different
system calls. If the filter is missing some system call, *chronyd* could be system calls. If the filter is missing some system call, *chronyd* could be
killed even in normal operation. killed even in normal operation.
@@ -174,10 +184,8 @@ This mode is only supported on Linux.
This option disables the control of the system clock. *chronyd* will not try to This option disables the control of the system clock. *chronyd* will not try to
make any adjustments of the clock. It will assume the clock is free running and make any adjustments of the clock. It will assume the clock is free running and
still track its offset and frequency relative to the estimated true time. This still track its offset and frequency relative to the estimated true time. This
option allows *chronyd* to run without the capability to adjust or set the option allows *chronyd* to be started without the capability to adjust or set
system clock (e.g. in some containers) in order to operate as an NTP server. It the system clock (e.g. in some containers) to operate as an NTP server.
is not recommended to run *chronyd* (with or without *-x*) when another process
is controlling the system clock.
*-v*:: *-v*::
With this option *chronyd* will print version number to the terminal and exit. With this option *chronyd* will print version number to the terminal and exit.

View File

@@ -1,7 +1,7 @@
// This file is part of chrony // This file is part of chrony
// //
// Copyright (C) Richard P. Curnow 1997-2003 // Copyright (C) Richard P. Curnow 1997-2003
// Copyright (C) Miroslav Lichvar 2014-2016 // Copyright (C) Miroslav Lichvar 2014-2016, 2020
// //
// This program is free software; you can redistribute it and/or modify // This program is free software; you can redistribute it and/or modify
// it under the terms of version 2 of the GNU General Public License as // it under the terms of version 2 of the GNU General Public License as
@@ -24,17 +24,20 @@
=== How does `chrony` compare to `ntpd`? === How does `chrony` compare to `ntpd`?
`chronyd` was designed to work well in a wide range of conditions and it can `chrony` and `ntpd` are two different implementations of the Network Time
usually synchronise the system clock faster and with better time accuracy. It Protocol (NTP).
doesn't implement some of the less useful NTP modes like broadcast client or
multicast server/client. `chrony` is a newer implementation, which was designed to work well in a wider
range of conditions. It can usually synchronise the system clock faster and
with better time accuracy. It has many features, but it does not implement some
of the less useful NTP modes like broadcast client or multicast server/client.
If your computer is connected to the Internet only for few minutes at a time, If your computer is connected to the Internet only for few minutes at a time,
the network connection is often congested, you turn your computer off or the network connection is often congested, you turn your computer off or
suspend it frequently, the clock is not very stable (e.g. there are rapid suspend it frequently, the clock is not very stable (e.g. there are rapid
changes in the temperature or it's a virtual machine), or you want to use NTP changes in the temperature or it is a virtual machine), or you want to use NTP
on an isolated network with no hardware reference clocks in sight, `chrony` on an isolated network with no hardware reference clocks in sight, `chrony`
will probably work much better for you. will probably work better for you.
For a more detailed comparison of features and performance, see the For a more detailed comparison of features and performance, see the
https://chrony.tuxfamily.org/comparison.html[comparison page] on the `chrony` https://chrony.tuxfamily.org/comparison.html[comparison page] on the `chrony`
@@ -59,7 +62,7 @@ slewing, which would take a very long time. The `makestep` directive does
that. that.
In order to keep the real-time clock (RTC) close to the true time, so the In order to keep the real-time clock (RTC) close to the true time, so the
system time is reasonably close to the true time when it's initialised on the system time is reasonably close to the true time when it is initialised on the
next boot from the RTC, the `rtcsync` directive enables a mode in which the next boot from the RTC, the `rtcsync` directive enables a mode in which the
system time is periodically copied to the RTC. It is supported on Linux and system time is periodically copied to the RTC. It is supported on Linux and
macOS. macOS.
@@ -75,52 +78,36 @@ makestep 1 3
rtcsync rtcsync
---- ----
=== How do I make an NTP server from an NTP client? === How do I make an NTP server?
You need to add an `allow` directive to the _chrony.conf_ file in order to open You need to add an `allow` directive to the _chrony.conf_ file in order to open
the NTP port and allow `chronyd` to reply to client requests. `allow` with no the NTP port and allow `chronyd` to reply to client requests. `allow` with no
specified subnet allows access from all IPv4 and IPv6 addresses. specified subnet allows access from all IPv4 and IPv6 addresses.
=== I have several computers on a LAN. Should be all clients of an external server? === Should all computers on a LAN be clients of an external server?
The best configuration is usually to make one computer the server, with It depends on the requirements. Usually, the best configuration is to make one
the others as clients of it. Add a `local` directive to the server's computer the server, with the others as clients of it. Add a `local` directive
_chrony.conf_ file. This configuration will be better because to the server's _chrony.conf_ file. This configuration will be better because
* the load on the external connection is less * the load on the external connection is less
* the load on the external NTP server(s) is less * the load on the external NTP server(s) is less
* if your external connection goes down, the computers on the LAN * if your external connection goes down, the computers on the LAN
will maintain a common time with each other. will maintain a common time with each other.
=== Must I specify servers by IP address if DNS is not available on chronyd start? === Must I specify servers by IP address if DNS is not available on `chronyd` start?
No. Starting from version 1.25, `chronyd` will keep trying to resolve No, `chronyd` will keep trying to resolve
the names specified by the `server`, `pool`, and `peer` directives in an the names specified by the `server`, `pool`, and `peer` directives in an
increasing interval until it succeeds. The `online` command can be issued from increasing interval until it succeeds. The `online` command can be issued from
`chronyc` to force `chronyd` to try to resolve the names immediately. `chronyc` to force `chronyd` to try to resolve the names immediately.
=== How can I make `chronyd` more secure? === How can I make `chronyd` more secure?
If you don't need to serve time to NTP clients or peers, you can add `port 0` If you do not need to use `chronyc`, or you want to run `chronyc` only
to the _chrony.conf_ file to completely disable the NTP server functionality
and prevent NTP requests from reaching `chronyd`. Starting from version 2.0,
the NTP server port is open only when client access is allowed by the `allow`
directive or command, an NTP peer is configured, or the `broadcast` directive
is used.
If you don't need to use `chronyc` remotely, you can add the following
directives to the configuration file to bind the command sockets to the
loopback interface. This is done by default since version 2.0.
----
bindcmdaddress 127.0.0.1
bindcmdaddress ::1
----
If you don't need to use `chronyc` at all or you need to run `chronyc` only
under the root or _chrony_ user (which can access `chronyd` through a Unix under the root or _chrony_ user (which can access `chronyd` through a Unix
domain socket since version 2.2), you can disable the internet command sockets domain socket), you can disable the IPv4 and IPv6 command sockets (by default
completely by adding `cmdport 0` to the configuration file. listening on localhost) by adding `cmdport 0` to the configuration file.
You can specify an unprivileged user with the `-u` option, or the `user` You can specify an unprivileged user with the `-u` option, or the `user`
directive in the _chrony.conf_ file, to which `chronyd` will switch after start directive in the _chrony.conf_ file, to which `chronyd` will switch after start
@@ -133,23 +120,23 @@ a very limited range of privileged system calls on behalf of the parent.
Also, if `chronyd` is compiled with support for the Linux secure computing Also, if `chronyd` is compiled with support for the Linux secure computing
(seccomp) facility, you can enable a system call filter with the `-F` option. (seccomp) facility, you can enable a system call filter with the `-F` option.
It will significantly reduce the kernel attack surface and possibly prevent It will significantly reduce the kernel attack surface and possibly prevent
kernel exploits from the `chronyd` process if it's compromised. It's kernel exploits from the `chronyd` process if it is compromised. It is
recommended to enable the filter only when it's known to work on the version of recommended to enable the filter only when it is known to work on the version of
the system where `chrony` is installed as the filter needs to allow also system the system where `chrony` is installed as the filter needs to allow also system
calls made from libraries that `chronyd` is using (e.g. libc) and different calls made from libraries that `chronyd` is using (e.g. libc) and different
versions or implementations of the libraries may make different system calls. versions or implementations of the libraries might make different system calls.
If the filter is missing some system call, `chronyd` could be killed even in If the filter is missing some system call, `chronyd` could be killed even in
normal operation. normal operation.
=== How can I improve the accuracy of the system clock with NTP sources? === How can I improve the accuracy of the system clock with NTP sources?
Select NTP servers that are well synchronised, stable and close to your Select NTP servers that are well synchronised, stable and close to your
network. It's better to use more than one server, three or four is usually network. It is better to use more than one server, three or four is usually
recommended as the minimum, so `chronyd` can detect servers that serve false recommended as the minimum, so `chronyd` can detect servers that serve false
time and combine measurements from multiple sources. time and combine measurements from multiple sources.
If you have a network card with hardware timestamping supported on Linux, it If you have a network card with hardware timestamping supported on Linux, it
can be enabled by the *hwtimestamp* directive in the _chrony.conf_ file. It can be enabled by the `hwtimestamp` directive in the _chrony.conf_ file. It
should make local receive and transmit timestamps of NTP packets much more should make local receive and transmit timestamps of NTP packets much more
accurate. accurate.
@@ -163,8 +150,8 @@ default values are 6 (64 seconds) for `minpoll`, 10 (1024 seconds) for
`maxpoll` and 8 (samples) for `polltarget`. The default values should be used `maxpoll` and 8 (samples) for `polltarget`. The default values should be used
for general servers on the Internet. With your own NTP servers, or if you have for general servers on the Internet. With your own NTP servers, or if you have
permission to poll some servers more frequently, setting these options for permission to poll some servers more frequently, setting these options for
shorter polling intervals may significantly improve the accuracy of the system shorter polling intervals might significantly improve the accuracy of the
clock. system clock.
The optimal polling interval depends mainly on two factors, stability of the The optimal polling interval depends mainly on two factors, stability of the
network latency and stability of the system clock (which mainly depends on the network latency and stability of the system clock (which mainly depends on the
@@ -174,7 +161,7 @@ temperature change).
Generally, if the `sourcestats` command usually reports a small number of Generally, if the `sourcestats` command usually reports a small number of
samples retained for a source (e.g. fewer than 16), a shorter polling interval samples retained for a source (e.g. fewer than 16), a shorter polling interval
should be considered. If the number of samples is usually at the maximum of 64, should be considered. If the number of samples is usually at the maximum of 64,
a longer polling interval may work better. a longer polling interval might work better.
An example of the directive for an NTP server on the Internet that you are An example of the directive for an NTP server on the Internet that you are
allowed to poll frequently could be allowed to poll frequently could be
@@ -210,7 +197,7 @@ server ntp.local minpoll 2 maxpoll 4 xleave
When combined with local hardware timestamping, good network switches, and even When combined with local hardware timestamping, good network switches, and even
shorter polling intervals, a sub-microsecond accuracy and stability of a few shorter polling intervals, a sub-microsecond accuracy and stability of a few
tens of nanoseconds may be possible. For example: tens of nanoseconds might be possible. For example:
---- ----
server ntp.local minpoll 0 maxpoll 0 xleave server ntp.local minpoll 0 maxpoll 0 xleave
@@ -221,10 +208,11 @@ For best stability, the CPU should be running at a constant frequency (i.e.
disabled power saving and performance boosting). Energy-Efficient Ethernet disabled power saving and performance boosting). Energy-Efficient Ethernet
(EEE) should be disabled in the network. The switches should be configured to (EEE) should be disabled in the network. The switches should be configured to
prioritize NTP packets, especially if the network is expected to be heavily prioritize NTP packets, especially if the network is expected to be heavily
loaded. loaded. The `dscp` directive can be used to set the Differentiated Services
Code Point in transmitted NTP packets if needed.
If it is acceptable for NTP clients in the network to send requests at an If it is acceptable for NTP clients in the network to send requests at a high
excessive rate, a sub-second polling interval may be specified. A median filter rate, a sub-second polling interval can be specified. A median filter
can be enabled in order to update the clock at a reduced rate with more stable can be enabled in order to update the clock at a reduced rate with more stable
measurements. For example: measurements. For example:
@@ -237,7 +225,7 @@ hwtimestamp eth0 minpoll -6
Yes. With the `-q` option `chronyd` will set the system clock once and exit. Yes. With the `-q` option `chronyd` will set the system clock once and exit.
With the `-Q` option it will print the measured offset without setting the With the `-Q` option it will print the measured offset without setting the
clock. If you don't want to use a configuration file, NTP servers can be clock. If you do not want to use a configuration file, NTP servers can be
specified on the command line. For example: specified on the command line. For example:
---- ----
@@ -249,17 +237,28 @@ well synchronised and responding to all requests. If not synchronised or
responding, it would take about 10 seconds for `chronyd` to give up and exit responding, it would take about 10 seconds for `chronyd` to give up and exit
with a non-zero status. A faster configuration is possible. A single server can with a non-zero status. A faster configuration is possible. A single server can
be used instead of four servers, the number of measurements can be reduced with be used instead of four servers, the number of measurements can be reduced with
the `maxsamples` option, and a timeout can be specified with the `-t` option. the `maxsamples` option to one (supported in `chrony` version 4.0), and a
The following command would take only up to about 1 second. timeout can be specified with the `-t` option. The following command would take
only up to about one second.
---- ----
# chronyd -q -t 1 'server pool.ntp.org iburst maxsamples 1' # chronyd -q -t 1 'server pool.ntp.org iburst maxsamples 1'
---- ----
It is not recommended to run `chronyd` with the `-q` option periodically (e.g.
from a cron job) as a replacement for the daemon mode, because it performs
significantly worse (e.g. the clock is stepped and its frequency is not
corrected). If you must run it this way and you are using a public NTP server,
make sure `chronyd` does not always start around the first second of a minute,
e.g. by adding a random sleep before the `chronyd` command. Public servers
typically receive large bursts of requests around the first second as there is
a large number of NTP clients started from cron with no delay.
=== Can `chronyd` be configured to control the clock like `ntpd`? === Can `chronyd` be configured to control the clock like `ntpd`?
It is not possible to perfectly emulate `ntpd`, but there are some options that It is not possible to perfectly emulate `ntpd`, but there are some options that
can configure `chronyd` to behave more like `ntpd`. can configure `chronyd` to behave more like `ntpd` if there is a reason to
prefer that.
In the following example the `minsamples` directive slows down the response to In the following example the `minsamples` directive slows down the response to
changes in the frequency and offset of the clock. The `maxslewrate` and changes in the frequency and offset of the clock. The `maxslewrate` and
@@ -279,10 +278,56 @@ maxchange 1000 1 1
maxclockerror 15 maxclockerror 15
---- ----
Note that increasing `minsamples` may cause the offsets in the `tracking` and Note that increasing `minsamples` might cause the offsets in the `tracking` and
`sourcestats` reports/logs to be significantly smaller than the actual offsets `sourcestats` reports/logs to be significantly smaller than the actual offsets
and be unsuitable for monitoring. and be unsuitable for monitoring.
=== Can NTP server be separated from NTP client?
Yes, it is possible to run multiple instances of `chronyd` on the same
computer. One can be configured as an NTP client, and another as a server. They
need to use different pidfiles, NTP ports, command ports, and Unix domain
command sockets. The server instance should be started with the `-x` option to
avoid touching the clock. It can be configured to serve the system time with
the `local` directive, or synchronise its NTP clock to the client instance
running on localhost using a non-standard NTP port.
On Linux, starting with `chrony` version 4.0, it is also possible to run
multiple server instances sharing a port to utilise multiple cores of the CPU.
Note that the client/server interleaved mode requires that all packets from an
address are handled by the same server instance.
=== Should be a leap smear enabled on NTP server?
With the `smoothtime` and `leapsecmode` directives it is possible to enable a
server leap smear in order to hide leap seconds from clients and force them to
follow a slow server's adjustment instead.
This feature should be used only in local networks and only when necessary,
e.g. when the clients cannot be configured to handle the leap seconds as
needed, or their number is so large that configuring them all would be
impractical. The clients should use only one leap-smearing server, or multiple
identically configured leap-smearing servers. Note that some clients can get
leap seconds from external sources (e.g. with the `leapsectz` directive in
`chrony`) and they will not work correctly with a leap smearing server.
=== Does `chrony` support PTP?
No, the Precision Time Protocol (PTP) is not supported and there are no plans
to support it. It is a complex protocol, which shares some issues with the
NTP broadcast mode. One of the main differences between NTP and PTP is that PTP
was designed to be easily supported in hardware (e.g. network switches and
routers) in order to make more stable and accurate measurements. PTP relies on
the hardware support. NTP does not rely on any support in the hardware, but if
it had the same support as PTP, it could perform equally well.
On Linux, `chrony` supports hardware clocks that some NICs have for PTP. They
are called PTP hardware clocks (PHC). They can be used as reference clocks
(specified by the `refclock` directive) and for hardware timestamping of NTP
packets (enabled by the `hwtimestamp` directive) if the NIC can timestamp other
packets than PTP, which is usually the case at least for transmitted packets.
The `ethtool -T` command can be used to verify the timestamping support.
=== What happened to the `commandkey` and `generatecommandkey` directives? === What happened to the `commandkey` and `generatecommandkey` directives?
They were removed in version 2.2. Authentication is no longer supported in the They were removed in version 2.2. Authentication is no longer supported in the
@@ -299,11 +344,11 @@ following questions.
=== Behind a firewall? === Behind a firewall?
Check the `Reach` value printed by the ``chronyc``'s `sources` command. If it's Check the `Reach` value printed by the ``chronyc``'s `sources` command. If it
zero, it means `chronyd` did not get any valid responses from the NTP server is zero, it means `chronyd` did not get any valid responses from the NTP server
you are trying to use. If there is a firewall between you and the server, the you are trying to use. If there is a firewall between you and the server, the
packets may be blocked. Try using a tool like `wireshark` or `tcpdump` to see packets might be blocked. Try using a tool like `wireshark` or `tcpdump` to see
if you're getting any responses from the server. if you are getting any responses from the server.
When `chronyd` is receiving responses from the servers, the output of the When `chronyd` is receiving responses from the servers, the output of the
`sources` command issued few minutes after `chronyd` start might look like `sources` command issued few minutes after `chronyd` start might look like
@@ -320,9 +365,10 @@ MS Name/IP address Stratum Poll Reach LastRx Last sample
=== Are NTP servers specified with the `offline` option? === Are NTP servers specified with the `offline` option?
Check that you're using ``chronyc``'s `online` and `offline` commands Check that the ``chronyc``'s `online` and `offline` commands are used
appropriately. The `activity` command prints the number of sources that are appropriately (e.g. in the system networking scripts). The `activity` command
currently online and offline. For example: prints the number of sources that are currently online and offline. For
example:
---- ----
200 OK 200 OK
@@ -349,9 +395,9 @@ makestep 1 3
---- ----
the clock would be stepped in the first three updates if its offset was larger the clock would be stepped in the first three updates if its offset was larger
than one second. Normally, it's recommended to allow the step only in the first than one second. Normally, it is recommended to allow the step only in the first
few updates, but in some cases (e.g. a computer without an RTC or virtual few updates, but in some cases (e.g. a computer without an RTC or virtual
machine which can be suspended and resumed with an incorrect time) it may be machine which can be suspended and resumed with an incorrect time) it might be
necessary to allow the step on any clock update. The example above would change necessary to allow the step on any clock update. The example above would change
to to
@@ -363,7 +409,7 @@ makestep 1 -1
A common issue with Windows NTP servers is that they report a very large root A common issue with Windows NTP servers is that they report a very large root
dispersion (e.g. three seconds or more), which causes `chronyd` to ignore the dispersion (e.g. three seconds or more), which causes `chronyd` to ignore the
server for being too inaccurate. The `sources` command may show a valid server for being too inaccurate. The `sources` command might show a valid
measurement, but the server is not selected for synchronisation. You can check measurement, but the server is not selected for synchronisation. You can check
the root dispersion of the server with the ``chronyc``'s `ntpdata` command. the root dispersion of the server with the ``chronyc``'s `ntpdata` command.
@@ -374,6 +420,29 @@ synchronisation to such a server. For example:
maxdistance 16.0 maxdistance 16.0
---- ----
=== An unreachable source is selected?
When `chronyd` is configured with multiple time sources, it tries to select the
most accurate and stable sources for synchronisation of the system clock. They
are marked with the _*_ or _+_ symbol in the report printed by the `sources`
command.
When the best source (marked with the _*_ symbol) becomes unreachable (e.g. NTP
server stops responding), or the measurements are no longer accepted (e.g. a
change in network routing adds a delay), `chronyd` will not immediately switch
to the second best source in an attempt to minimise the error of the clock. It
will let the clock run free for as long as its estimated error (in terms of
root distance) based on previous measurements is smaller than the estimated
error of the second source, and there is still an interval which contains some
measurements from both sources.
If the first source was significantly better than the second source, it can
take many hours (up to 64 times the maximum polling interval) before the second
source is selected. If you do not like this behaviour, you can force a faster
reselection by increasing the clock error rate (`maxclockerror` directive),
shortening the polling interval (`maxpoll` option), or reducing the number of
samples (`maxsamples` option).
=== Using a PPS reference clock? === Using a PPS reference clock?
A pulse-per-second (PPS) reference clock requires a non-PPS time source to A pulse-per-second (PPS) reference clock requires a non-PPS time source to
@@ -409,15 +478,15 @@ to be used for synchronisation.
When accessing `chronyd` remotely, make sure that the _chrony.conf_ file (on When accessing `chronyd` remotely, make sure that the _chrony.conf_ file (on
the computer where `chronyd` is running) has a `cmdallow` entry for the the computer where `chronyd` is running) has a `cmdallow` entry for the
computer you are running `chronyc` on and an appropriate `bindcmdaddress` computer you are running `chronyc` on and an appropriate `bindcmdaddress`
directive. This isn't necessary for localhost. directive. This is not necessary for localhost.
Perhaps `chronyd` is not running. Try using the `ps` command (e.g. on Linux, Perhaps `chronyd` is not running. Try using the `ps` command (e.g. on Linux,
`ps -auxw`) to see if it's running. Or try `netstat -a` and see if the ports `ps -auxw`) to see if it is running. Or try `netstat -a` and see if the UDP
123/udp and 323/udp are listening. If `chronyd` is not running, you may have a port 323 is listening. If `chronyd` is not running, you might have a problem
problem with the way you are trying to start it (e.g. at boot time). with the way you are trying to start it (e.g. at boot time).
Perhaps you have a firewall set up in a way that blocks packets on port Perhaps you have a firewall set up in a way that blocks packets on the UDP
323/udp. You need to amend the firewall configuration in this case. port 323. You need to amend the firewall configuration in this case.
=== I keep getting the error `501 Not authorised` === I keep getting the error `501 Not authorised`
@@ -426,20 +495,16 @@ socket instead of the Unix domain socket (e.g. _/var/run/chrony/chronyd.sock_),
which is required for some commands. For security reasons, only the root and which is required for some commands. For security reasons, only the root and
_chrony_ users are allowed to access the socket. _chrony_ users are allowed to access the socket.
It is also possible that the socket doesn't exist. `chronyd` will not create It is also possible that the socket does not exist. `chronyd` will not create
the socket if the directory has a wrong owner or permissions. In this case the socket if the directory has a wrong owner or permissions. In this case
there should be an error message from `chronyd` in the system log. there should be an error message from `chronyd` in the system log.
With versions older than 2.2, which don't use the Unix domain socket, you need === What is the reference ID reported by the `tracking` command?
to authenticate with the `password` command first,
or use the `-a` option to authenticate automatically on start. The
configuration file needs to specify a file which contains keys (`keyfile`
directive) and which key in the key file should be used for `chronyc`
authentication (`commandkey` directive).
=== Why does `chronyc tracking` always print an IPv4 address as reference ID? The reference ID is a 32-bit value used in NTP to prevent synchronisation
loops.
The reference ID is a 32-bit value and in versions before 3.0 it was printed in In `chrony` versions before 3.0 it was printed in the
quad-dotted notation, even if the reference source did not actually have an quad-dotted notation, even if the reference source did not actually have an
IPv4 address. For IPv4 addresses, the reference ID is equal to the address, but IPv4 address. For IPv4 addresses, the reference ID is equal to the address, but
for IPv6 addresses it is the first 32 bits of the MD5 sum of the address. For for IPv6 addresses it is the first 32 bits of the MD5 sum of the address. For
@@ -463,7 +528,7 @@ Only by the source code. See _cmdmon.c_ (`chronyd` side) and _client.c_
=== What is the real-time clock (RTC)? === What is the real-time clock (RTC)?
This is the clock which keeps the time even when your computer is turned off. This is the clock which keeps the time even when your computer is turned off.
It is used to initialise the system clock on boot. It normally doesn't drift It is used to initialise the system clock on boot. It normally does not drift
more than few seconds per day. more than few seconds per day.
There are two approaches how `chronyd` can work with it. One is to use the There are two approaches how `chronyd` can work with it. One is to use the
@@ -478,17 +543,17 @@ monitor the rate at which the RTC gains or loses time. When `chronyd` is
started with the `-s` option on the next boot, it will set the system time from started with the `-s` option on the next boot, it will set the system time from
the RTC and also compensate for the drift it has measured previously. The the RTC and also compensate for the drift it has measured previously. The
`rtcautotrim` directive can be used to keep the RTC close to the true time, but `rtcautotrim` directive can be used to keep the RTC close to the true time, but
it's not strictly necessary if its only purpose is to set the system clock when it is not strictly necessary if its only purpose is to set the system clock when
`chronyd` is started on boot. See the documentation for details. `chronyd` is started on boot. See the documentation for details.
=== I want to use ``chronyd``'s RTC support. Must I disable `hwclock`? === Does `hwclock` have to be disabled?
The `hwclock` program is often set-up by default in the boot and shutdown The `hwclock` program is often set-up by default in the boot and shutdown
scripts with many Linux installations. With the kernel RTC synchronisation scripts with many Linux installations. With the kernel RTC synchronisation
(`rtcsync` directive), the RTC will be set also every 11 minutes as long as the (`rtcsync` directive), the RTC will be set also every 11 minutes as long as the
system clock is synchronised. If you want to use ``chronyd``'s RTC monitoring system clock is synchronised. If you want to use ``chronyd``'s RTC monitoring
(`rtcfile` directive), it's important to disable `hwclock` in the shutdown (`rtcfile` directive), it is important to disable `hwclock` in the shutdown
procedure. If you don't, it will over-write the RTC with a new value, unknown procedure. If you do not that, it will over-write the RTC with a new value, unknown
to `chronyd`. At the next reboot, `chronyd` started with the `-s` option will to `chronyd`. At the next reboot, `chronyd` started with the `-s` option will
compensate this (wrong) time with its estimate of how far the RTC has drifted compensate this (wrong) time with its estimate of how far the RTC has drifted
whilst the power was off, giving a meaningless initial system time. whilst the power was off, giving a meaningless initial system time.
@@ -507,7 +572,7 @@ things
=== I get `Could not open /dev/rtc, Device or resource busy` in my syslog file === I get `Could not open /dev/rtc, Device or resource busy` in my syslog file
Some other program running on the system may be using the device. Some other program running on the system might be using the device.
=== What if my computer does not have an RTC or backup battery? === What if my computer does not have an RTC or backup battery?
@@ -522,7 +587,7 @@ observe backward steps.
=== Can `chronyd` be driven from broadcast/multicast NTP servers? === Can `chronyd` be driven from broadcast/multicast NTP servers?
No, the broadcast/multicast client mode is not supported and there is currently No, the broadcast/multicast client mode is not supported and there is currently
no plan to implement it. While the mode may be useful to simplify configuration no plan to implement it. While this mode can simplify configuration
of clients in large networks, it is inherently less accurate and less secure of clients in large networks, it is inherently less accurate and less secure
(even with authentication) than the ordinary client/server mode. (even with authentication) than the ordinary client/server mode.
@@ -539,7 +604,8 @@ thousands of clients using the ordinary client/server mode.
Yes, the `broadcast` directive can be used to enable the broadcast server mode Yes, the `broadcast` directive can be used to enable the broadcast server mode
to serve time to clients in the network which support the broadcast client mode to serve time to clients in the network which support the broadcast client mode
(it's not supported in `chronyd`, see the previous question). (it is not supported in `chronyd`). Note that this mode should generally be
avoided. See the previous question.
=== Can `chronyd` keep the system clock a fixed offset away from real time? === Can `chronyd` keep the system clock a fixed offset away from real time?
@@ -555,9 +621,21 @@ offline, `chronyd` would make new measurements immediately after issuing the
`online` command. `online` command.
Unless the network connection lasts only few minutes (less than the maximum Unless the network connection lasts only few minutes (less than the maximum
polling interval), the delay is usually not a problem, and it may be acceptable polling interval), the delay is usually not a problem, and it might be acceptable
to keep all sources online all the time. to keep all sources online all the time.
=== Why is an offset measured between two computers synchronised to each another?
When two computers are synchronised to each other using the client/server or
symmetric NTP mode, there is an expectation that NTP measurements between the
two computers made on both ends show an average offset close to zero.
With `chronyd` that can be expected only when the interleaved mode (`xleave`
option) is enabled. Otherwise, `chronyd` will use different transmit timestamps
(e.g. daemon timestamp vs kernel timestamp) for serving time and
synchronisation of its own clock, which creates an asymmetry in the
timestamping and causes the other end to measure a significant offset.
== Operating systems == Operating systems
=== Does `chrony` support Windows? === Does `chrony` support Windows?

View File

@@ -100,7 +100,7 @@ than MD5, which can be used for NTP authentication with a symmetric key. If you
don't want to enable the support, specify the `--disable-sechash` flag to don't want to enable the support, specify the `--disable-sechash` flag to
`configure`. `configure`.
If development files for the editline or readline library are available, If development files for the editline library are available,
`chronyc` will be built with line editing support. If you don't want this, `chronyc` will be built with line editing support. If you don't want this,
specify the `--disable-readline` flag to `configure`. specify the `--disable-readline` flag to `configure`.
@@ -170,43 +170,6 @@ https://github.com/seccomp/libseccomp[libseccomp] library and the
the kernel attack surface and possibly prevent kernel exploits from `chronyd` the kernel attack surface and possibly prevent kernel exploits from `chronyd`
if it is compromised. if it is compromised.
== Support for line editing libraries
`chronyc` can be built with support for line editing, this allows you to use
the cursor keys to replay and edit old commands. Two libraries are supported
which provide such functionality, editline and GNU readline.
Please note that readline since version 6.0 is licensed under GPLv3+ which is
incompatible with chrony's license GPLv2. You should use editline instead if
you don't want to use older readline versions.
The `configure` script will automatically enable the line editing support if
one of the supported libraries is available. If they are both available, the
editline library will be used.
If you don't want to use it (in which case `chronyc` will use a minimal command
line interface), invoke `configure` like this:
----
./configure --disable-readline other-options...
----
If you have editline, readline or ncurses installed in locations that aren't
normally searched by the compiler and linker, you need to use extra options:
`--with-readline-includes=directory_name`::
This defines the name of the directory above the one where `readline.h` is.
`readline.h` is assumed to be in `editline` or `readline` subdirectory of the
named directory.
`--with-readline-library=directory_name`::
This defines the directory containing the `libedit.a` or `libedit.so` file,
or `libreadline.a` or `libreadline.so` file.
`--with-ncurses-library=directory_name`::
This defines the directory containing the `libncurses.a` or `libncurses.so`
file.
== Extra options for package builders == Extra options for package builders
The `configure` and `make` procedures have some extra options that may be The `configure` and `make` procedures have some extra options that may be

View File

@@ -8,9 +8,11 @@ Wants=time-sync.target
[Service] [Service]
Type=oneshot Type=oneshot
# Wait up to ~10 minutes for chronyd to synchronize and the remaining # Wait for chronyd to update the clock and the remaining
# clock correction to be less than 0.1 seconds # correction to be less than 0.1 seconds
ExecStart=/usr/bin/chronyc -h 127.0.0.1,::1 waitsync 600 0.1 0.0 1 ExecStart=/usr/bin/chronyc -h 127.0.0.1,::1 waitsync 0 0.1 0.0 1
# Wait for at most 3 minutes
TimeoutStartSec=180
RemainAfterExit=yes RemainAfterExit=yes
StandardOutput=null StandardOutput=null

2
keys.c
View File

@@ -3,7 +3,7 @@
********************************************************************** **********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003 * Copyright (C) Richard P. Curnow 1997-2003
* Copyright (C) Miroslav Lichvar 2012-2016 * Copyright (C) Miroslav Lichvar 2012-2016, 2019-2020
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as * it under the terms of version 2 of the GNU General Public License as

28
local.c
View File

@@ -108,8 +108,8 @@ static double max_clock_error;
#define NSEC_PER_SEC 1000000000 #define NSEC_PER_SEC 1000000000
static void static double
calculate_sys_precision(void) measure_clock_precision(void)
{ {
struct timespec ts, old_ts; struct timespec ts, old_ts;
int iters, diff, best; int iters, diff, best;
@@ -135,18 +135,7 @@ calculate_sys_precision(void)
assert(best > 0); assert(best > 0);
precision_quantum = 1.0e-9 * best; return 1.0e-9 * best;
/* Get rounded log2 value of the measured precision */
precision_log = 0;
while (best < 707106781) {
precision_log--;
best *= 2;
}
assert(precision_log >= -30);
DEBUG_LOG("Clock precision %.9f (%d)", precision_quantum, precision_log);
} }
/* ================================================== */ /* ================================================== */
@@ -170,7 +159,16 @@ LCL_Initialise(void)
current_freq_ppm = 0.0; current_freq_ppm = 0.0;
temp_comp_ppm = 0.0; temp_comp_ppm = 0.0;
calculate_sys_precision(); precision_quantum = CNF_GetClockPrecision();
if (precision_quantum <= 0.0)
precision_quantum = measure_clock_precision();
precision_quantum = CLAMP(1.0e-9, precision_quantum, 1.0);
precision_log = round(log(precision_quantum) / log(2.0));
/* NTP code doesn't support smaller log than -30 */
assert(precision_log >= -30);
DEBUG_LOG("Clock precision %.9f (%d)", precision_quantum, precision_log);
/* This is the maximum allowed frequency offset in ppm, the time must /* This is the maximum allowed frequency offset in ppm, the time must
never stop or run backwards */ never stop or run backwards */

View File

@@ -3,7 +3,7 @@
********************************************************************** **********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003 * Copyright (C) Richard P. Curnow 1997-2003
* Copyright (C) Miroslav Lichvar 2011-2014, 2018 * Copyright (C) Miroslav Lichvar 2011-2014, 2018-2020
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as * it under the terms of version 2 of the GNU General Public License as

14
main.c
View File

@@ -4,7 +4,7 @@
********************************************************************** **********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003 * Copyright (C) Richard P. Curnow 1997-2003
* Copyright (C) John G. Hasler 2009 * Copyright (C) John G. Hasler 2009
* Copyright (C) Miroslav Lichvar 2012-2018 * Copyright (C) Miroslav Lichvar 2012-2020
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as * it under the terms of version 2 of the GNU General Public License as
@@ -411,7 +411,7 @@ int main
int do_init_rtc = 0, restarted = 0, client_only = 0, timeout = -1; int do_init_rtc = 0, restarted = 0, client_only = 0, timeout = -1;
int scfilter_level = 0, lock_memory = 0, sched_priority = 0; int scfilter_level = 0, lock_memory = 0, sched_priority = 0;
int clock_control = 1, system_log = 1, log_severity = LOGS_INFO; int clock_control = 1, system_log = 1, log_severity = LOGS_INFO;
int config_args = 0, print_config = 0; int user_check = 1, config_args = 0, print_config = 0;
do_platform_checks(); do_platform_checks();
@@ -431,7 +431,7 @@ int main
optind = 1; optind = 1;
/* Parse short command-line options */ /* Parse short command-line options */
while ((opt = getopt(argc, argv, "46df:F:hl:L:mnpP:qQrRst:u:vx")) != -1) { while ((opt = getopt(argc, argv, "46df:F:hl:L:mnpP:qQrRst:u:Uvx")) != -1) {
switch (opt) { switch (opt) {
case '4': case '4':
case '6': case '6':
@@ -462,7 +462,7 @@ int main
break; break;
case 'p': case 'p':
print_config = 1; print_config = 1;
client_only = 1; user_check = 0;
nofork = 1; nofork = 1;
system_log = 0; system_log = 0;
break; break;
@@ -479,6 +479,7 @@ int main
ref_mode = REF_ModePrintOnce; ref_mode = REF_ModePrintOnce;
nofork = 1; nofork = 1;
client_only = 1; client_only = 1;
user_check = 0;
clock_control = 0; clock_control = 0;
system_log = 0; system_log = 0;
break; break;
@@ -497,6 +498,9 @@ int main
case 'u': case 'u':
user = optarg; user = optarg;
break; break;
case 'U':
user_check = 0;
break;
case 'v': case 'v':
print_version(); print_version();
return 0; return 0;
@@ -509,7 +513,7 @@ int main
} }
} }
if (getuid() && !client_only) if (user_check && getuid() != 0)
LOG_FATAL("Not superuser"); LOG_FATAL("Not superuser");
/* Turn into a daemon */ /* Turn into a daemon */

View File

@@ -2,7 +2,7 @@
chronyd/chronyc - Programs for keeping computer clocks accurate. chronyd/chronyc - Programs for keeping computer clocks accurate.
********************************************************************** **********************************************************************
* Copyright (C) Miroslav Lichvar 2019 * Copyright (C) Miroslav Lichvar 2019-2020
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as * it under the terms of version 2 of the GNU General Public License as
@@ -300,21 +300,9 @@ NAU_ParsePacket(NTP_Packet *packet, NTP_PacketInfo *info)
if (remainder >= NTP_MIN_MAC_LENGTH && remainder <= NTP_MAX_V4_MAC_LENGTH) if (remainder >= NTP_MIN_MAC_LENGTH && remainder <= NTP_MAX_V4_MAC_LENGTH)
break; break;
/* The NTPv4-specific limit for MAC length enables deterministic parsing of
packets with extension fields (RFC 7822), but we support longer MACs in
packets with no extension fields for compatibility with older chrony
clients. Check if the longer MAC would authenticate the packet before
trying to parse the data as an extension field. */
if (parsed == NTP_HEADER_LENGTH &&
remainder > NTP_MAX_V4_MAC_LENGTH && remainder <= NTP_MAX_MAC_LENGTH &&
KEY_CheckAuth(ntohl(*(uint32_t *)(data + parsed)), data, parsed,
data + parsed + 4, remainder - 4, NTP_MAX_MAC_LENGTH - 4))
break;
/* Check if this is a valid NTPv4 extension field and skip it */ /* Check if this is a valid NTPv4 extension field and skip it */
if (!NEF_ParseField(packet, info->length, parsed, &ef_length, &ef_type, NULL, NULL)) { if (!NEF_ParseField(packet, info->length, parsed, &ef_length, &ef_type, NULL, NULL)) {
/* Invalid MAC or format error */ DEBUG_LOG("Invalid format");
DEBUG_LOG("Invalid format or MAC");
return 0; return 0;
} }
@@ -340,9 +328,6 @@ NAU_ParsePacket(NTP_Packet *packet, NTP_PacketInfo *info)
/* No MAC */ /* No MAC */
return 1; return 1;
} else if (remainder >= NTP_MIN_MAC_LENGTH) { } else if (remainder >= NTP_MIN_MAC_LENGTH) {
/* This is not 100% reliable as a MAC could fail to authenticate and could
pass as an extension field, leaving reminder smaller than the minimum MAC
length */
info->auth.mode = NTP_AUTH_SYMMETRIC; info->auth.mode = NTP_AUTH_SYMMETRIC;
info->auth.mac.start = parsed; info->auth.mac.start = parsed;
info->auth.mac.length = remainder; info->auth.mac.length = remainder;

View File

@@ -3,7 +3,7 @@
********************************************************************** **********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003 * Copyright (C) Richard P. Curnow 1997-2003
* Copyright (C) Miroslav Lichvar 2009-2018 * Copyright (C) Miroslav Lichvar 2009-2020
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as * it under the terms of version 2 of the GNU General Public License as
@@ -2095,15 +2095,6 @@ NCR_ProcessRxUnknown(NTP_Remote_Address *remote_addr, NTP_Local_Address *local_a
CLG_LogAuthNtpRequest(); CLG_LogAuthNtpRequest();
} }
/* If it is an NTPv4 packet with a long MAC and no extension fields,
respond with an NTPv3 packet to avoid breaking RFC 7822 and keep
the length symmetric. Otherwise, respond with the same version. */
if (info.version == 4 && info.ext_fields == 0 && info.auth.mode == NTP_AUTH_SYMMETRIC &&
info.auth.mac.length > NTP_MAX_V4_MAC_LENGTH)
version = 3;
else
version = info.version;
local_ntp_rx = local_ntp_tx = NULL; local_ntp_rx = local_ntp_tx = NULL;
tx_ts = NULL; tx_ts = NULL;
interleaved = 0; interleaved = 0;
@@ -2133,6 +2124,9 @@ NCR_ProcessRxUnknown(NTP_Remote_Address *remote_addr, NTP_Local_Address *local_a
poll = CLG_GetNtpMinPoll(); poll = CLG_GetNtpMinPoll();
poll = MAX(poll, message->poll); poll = MAX(poll, message->poll);
/* Respond with the same version */
version = info.version;
/* Send a reply */ /* Send a reply */
transmit_packet(my_mode, interleaved, poll, version, kod, NULL, transmit_packet(my_mode, interleaved, poll, version, kod, NULL,
&message->receive_ts, &message->transmit_ts, &message->receive_ts, &message->transmit_ts,

View File

@@ -2,7 +2,7 @@
chronyd/chronyc - Programs for keeping computer clocks accurate. chronyd/chronyc - Programs for keeping computer clocks accurate.
********************************************************************** **********************************************************************
* Copyright (C) Miroslav Lichvar 2019 * Copyright (C) Miroslav Lichvar 2019-2020
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as * it under the terms of version 2 of the GNU General Public License as

View File

@@ -4,7 +4,7 @@
********************************************************************** **********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003 * Copyright (C) Richard P. Curnow 1997-2003
* Copyright (C) Timo Teras 2009 * Copyright (C) Timo Teras 2009
* Copyright (C) Miroslav Lichvar 2009, 2013-2016, 2018 * Copyright (C) Miroslav Lichvar 2009, 2013-2016, 2018-2020
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as * it under the terms of version 2 of the GNU General Public License as

View File

@@ -200,7 +200,8 @@ add_interface(CNF_HwTsInterface *conf_iface)
req.ifr_data = (char *)&ts_config; req.ifr_data = (char *)&ts_config;
if (ioctl(sock_fd, SIOCSHWTSTAMP, &req)) { if (ioctl(sock_fd, SIOCSHWTSTAMP, &req)) {
DEBUG_LOG("ioctl(%s) failed : %s", "SIOCSHWTSTAMP", strerror(errno)); LOG(errno == EPERM ? LOGS_ERR : LOGS_DEBUG,
"ioctl(%s) failed : %s", "SIOCSHWTSTAMP", strerror(errno));
/* Check the current timestamping configuration in case this interface /* Check the current timestamping configuration in case this interface
allows only reading of the configuration and it was already configured allows only reading of the configuration and it was already configured

View File

@@ -3,7 +3,7 @@
********************************************************************** **********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003 * Copyright (C) Richard P. Curnow 1997-2003
* Copyright (C) Miroslav Lichvar 2011-2012, 2014, 2016 * Copyright (C) Miroslav Lichvar 2011-2012, 2014, 2016, 2020
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as * it under the terms of version 2 of the GNU General Public License as

View File

@@ -335,15 +335,17 @@ NKC_Start(NKC_Instance inst)
local_addr.port = 0; local_addr.port = 0;
iface = CNF_GetBindAcquisitionInterface(); iface = CNF_GetBindAcquisitionInterface();
sock_fd = SCK_OpenTcpSocket(&inst->address, &local_addr, iface, 0);
if (sock_fd < 0)
return 0;
/* Make a label containing both the address and name of the server */ /* Make a label containing both the address and name of the server */
if (snprintf(label, sizeof (label), "%s (%s)", if (snprintf(label, sizeof (label), "%s (%s)",
UTI_IPSockAddrToString(&inst->address), inst->name) >= sizeof (label)) UTI_IPSockAddrToString(&inst->address), inst->name) >= sizeof (label))
; ;
sock_fd = SCK_OpenTcpSocket(&inst->address, &local_addr, iface, 0);
if (sock_fd < 0) {
LOG(LOGS_ERR, "Could not connect to %s", label);
return 0;
}
/* Start an NTS-KE session */ /* Start an NTS-KE session */
if (!NKSN_StartSession(inst->session, sock_fd, label, client_credentials, CLIENT_TIMEOUT)) { if (!NKSN_StartSession(inst->session, sock_fd, label, client_credentials, CLIENT_TIMEOUT)) {
SCK_CloseSocket(sock_fd); SCK_CloseSocket(sock_fd);

View File

@@ -53,6 +53,7 @@ struct NNC_Instance_Record {
const IPSockAddr *ntp_address; const IPSockAddr *ntp_address;
IPSockAddr nts_address; IPSockAddr nts_address;
char *name; char *name;
NKC_Instance nke; NKC_Instance nke;
SIV_Instance siv; SIV_Instance siv;
@@ -66,6 +67,7 @@ struct NNC_Instance_Record {
NKE_Cookie cookies[NTS_MAX_COOKIES]; NKE_Cookie cookies[NTS_MAX_COOKIES];
int num_cookies; int num_cookies;
int cookie_index; int cookie_index;
int auth_ready;
int nak_response; int nak_response;
int ok_response; int ok_response;
unsigned char nonce[NTS_MIN_UNPADDED_NONCE_LENGTH]; unsigned char nonce[NTS_MIN_UNPADDED_NONCE_LENGTH];
@@ -82,6 +84,13 @@ static void load_cookies(NNC_Instance inst);
static void static void
reset_instance(NNC_Instance inst) reset_instance(NNC_Instance inst)
{ {
if (inst->nke)
NKC_DestroyInstance(inst->nke);
inst->nke = NULL;
if (inst->siv)
SIV_DestroyInstance(inst->siv);
inst->siv = NULL;
inst->load_attempt = 0; inst->load_attempt = 0;
inst->nke_attempts = 0; inst->nke_attempts = 0;
inst->next_nke_attempt = 0.0; inst->next_nke_attempt = 0.0;
@@ -92,6 +101,7 @@ reset_instance(NNC_Instance inst)
memset(inst->cookies, 0, sizeof (inst->cookies)); memset(inst->cookies, 0, sizeof (inst->cookies));
inst->num_cookies = 0; inst->num_cookies = 0;
inst->cookie_index = 0; inst->cookie_index = 0;
inst->auth_ready = 0;
inst->nak_response = 0; inst->nak_response = 0;
inst->ok_response = 1; inst->ok_response = 1;
memset(inst->nonce, 0, sizeof (inst->nonce)); memset(inst->nonce, 0, sizeof (inst->nonce));
@@ -125,10 +135,7 @@ NNC_DestroyInstance(NNC_Instance inst)
{ {
save_cookies(inst); save_cookies(inst);
if (inst->nke) reset_instance(inst);
NKC_DestroyInstance(inst->nke);
if (inst->siv)
SIV_DestroyInstance(inst->siv);
Free(inst->name); Free(inst->name);
Free(inst); Free(inst);
@@ -276,6 +283,8 @@ get_cookies(NNC_Instance inst)
int int
NNC_PrepareForAuth(NNC_Instance inst) NNC_PrepareForAuth(NNC_Instance inst)
{ {
inst->auth_ready = 0;
/* Try to reload saved keys and cookies (once for the NTS-KE address) */ /* Try to reload saved keys and cookies (once for the NTS-KE address) */
if (!inst->load_attempt) { if (!inst->load_attempt) {
load_cookies(inst); load_cookies(inst);
@@ -301,6 +310,8 @@ NNC_PrepareForAuth(NNC_Instance inst)
UTI_GetRandomBytes(inst->uniq_id, sizeof (inst->uniq_id)); UTI_GetRandomBytes(inst->uniq_id, sizeof (inst->uniq_id));
UTI_GetRandomBytes(inst->nonce, sizeof (inst->nonce)); UTI_GetRandomBytes(inst->nonce, sizeof (inst->nonce));
inst->auth_ready = 1;
return 1; return 1;
} }
@@ -314,7 +325,7 @@ NNC_GenerateRequestAuth(NNC_Instance inst, NTP_Packet *packet,
int i, req_cookies; int i, req_cookies;
void *ef_body; void *ef_body;
if (inst->num_cookies == 0 || !inst->siv) if (!inst->auth_ready || inst->num_cookies == 0 || !inst->siv)
return 0; return 0;
if (info->mode != MODE_CLIENT) if (info->mode != MODE_CLIENT)
@@ -345,6 +356,7 @@ NNC_GenerateRequestAuth(NNC_Instance inst, NTP_Packet *packet,
inst->num_cookies--; inst->num_cookies--;
inst->cookie_index = (inst->cookie_index + 1) % NTS_MAX_COOKIES; inst->cookie_index = (inst->cookie_index + 1) % NTS_MAX_COOKIES;
inst->auth_ready = 0;
inst->nak_response = 0; inst->nak_response = 0;
inst->ok_response = 0; inst->ok_response = 0;
@@ -427,7 +439,7 @@ NNC_CheckResponseAuth(NNC_Instance inst, NTP_Packet *packet,
return 0; return 0;
/* Accept at most one response per request */ /* Accept at most one response per request */
if (inst->ok_response) if (inst->ok_response || inst->auth_ready)
return 0; return 0;
if (!inst->siv || if (!inst->siv ||
@@ -506,11 +518,6 @@ NNC_ChangeAddress(NNC_Instance inst, IPAddr *address)
{ {
save_cookies(inst); save_cookies(inst);
if (inst->nke)
NKC_DestroyInstance(inst->nke);
inst->nke = NULL;
inst->num_cookies = 0;
inst->nts_address.ip_addr = *address; inst->nts_address.ip_addr = *address;
reset_instance(inst); reset_instance(inst);

View File

@@ -3,7 +3,7 @@
********************************************************************** **********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003 * Copyright (C) Richard P. Curnow 1997-2003
* Copyright (C) Miroslav Lichvar 2009-2018 * Copyright (C) Miroslav Lichvar 2009-2018, 2020
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as * it under the terms of version 2 of the GNU General Public License as

View File

@@ -36,7 +36,14 @@ typedef struct {
int stratum; int stratum;
int poll; int poll;
enum {RPT_NTP_CLIENT, RPT_NTP_PEER, RPT_LOCAL_REFERENCE} mode; enum {RPT_NTP_CLIENT, RPT_NTP_PEER, RPT_LOCAL_REFERENCE} mode;
enum {RPT_SYNC, RPT_UNREACH, RPT_FALSETICKER, RPT_JITTERY, RPT_CANDIDATE, RPT_OUTLIER} state; enum {
RPT_NONSELECTABLE,
RPT_FALSETICKER,
RPT_JITTERY,
RPT_SELECTABLE,
RPT_UNSELECTED,
RPT_SELECTED,
} state;
int reachability; int reachability;
unsigned long latest_meas_ago; /* seconds */ unsigned long latest_meas_ago; /* seconds */

View File

@@ -204,6 +204,9 @@ SIV_Encrypt(SIV_Instance instance,
{ {
size_t clen = ciphertext_length; size_t clen = ciphertext_length;
if (!instance->cipher)
return 0;
if (nonce_length < 1 || assoc_length < 0 || if (nonce_length < 1 || assoc_length < 0 ||
plaintext_length < 0 || ciphertext_length < 0) plaintext_length < 0 || ciphertext_length < 0)
return 0; return 0;
@@ -232,6 +235,9 @@ SIV_Decrypt(SIV_Instance instance,
{ {
size_t plen = plaintext_length; size_t plen = plaintext_length;
if (!instance->cipher)
return 0;
if (nonce_length < 1 || assoc_length < 0 || if (nonce_length < 1 || assoc_length < 0 ||
plaintext_length < 0 || ciphertext_length < 0) plaintext_length < 0 || ciphertext_length < 0)
return 0; return 0;

View File

@@ -39,6 +39,7 @@
struct SIV_Instance_Record { struct SIV_Instance_Record {
struct siv_cmac_aes128_ctx siv; struct siv_cmac_aes128_ctx siv;
int key_set;
}; };
/* ================================================== */ /* ================================================== */
@@ -52,6 +53,7 @@ SIV_CreateInstance(SIV_Algorithm algorithm)
return NULL; return NULL;
instance = MallocNew(struct SIV_Instance_Record); instance = MallocNew(struct SIV_Instance_Record);
instance->key_set = 0;
return instance; return instance;
} }
@@ -86,6 +88,8 @@ SIV_SetKey(SIV_Instance instance, const unsigned char *key, int length)
siv_cmac_aes128_set_key(&instance->siv, key); siv_cmac_aes128_set_key(&instance->siv, key);
instance->key_set = 1;
return 1; return 1;
} }
@@ -108,6 +112,9 @@ SIV_Encrypt(SIV_Instance instance,
const void *plaintext, int plaintext_length, const void *plaintext, int plaintext_length,
unsigned char *ciphertext, int ciphertext_length) unsigned char *ciphertext, int ciphertext_length)
{ {
if (!instance->key_set)
return 0;
if (nonce_length < SIV_MIN_NONCE_SIZE || assoc_length < 0 || if (nonce_length < SIV_MIN_NONCE_SIZE || assoc_length < 0 ||
plaintext_length < 0 || plaintext_length > ciphertext_length || plaintext_length < 0 || plaintext_length > ciphertext_length ||
plaintext_length + SIV_DIGEST_SIZE != ciphertext_length) plaintext_length + SIV_DIGEST_SIZE != ciphertext_length)
@@ -130,6 +137,9 @@ SIV_Decrypt(SIV_Instance instance,
const unsigned char *ciphertext, int ciphertext_length, const unsigned char *ciphertext, int ciphertext_length,
void *plaintext, int plaintext_length) void *plaintext, int plaintext_length)
{ {
if (!instance->key_set)
return 0;
if (nonce_length < SIV_MIN_NONCE_SIZE || assoc_length < 0 || if (nonce_length < SIV_MIN_NONCE_SIZE || assoc_length < 0 ||
plaintext_length < 0 || plaintext_length > ciphertext_length || plaintext_length < 0 || plaintext_length > ciphertext_length ||
plaintext_length + SIV_DIGEST_SIZE != ciphertext_length) plaintext_length + SIV_DIGEST_SIZE != ciphertext_length)

View File

@@ -4,7 +4,7 @@
********************************************************************** **********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003 * Copyright (C) Richard P. Curnow 1997-2003
* Copyright (C) Timo Teras 2009 * Copyright (C) Timo Teras 2009
* Copyright (C) Miroslav Lichvar 2009, 2013-2019 * Copyright (C) Miroslav Lichvar 2009, 2013-2020
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as * it under the terms of version 2 of the GNU General Public License as

View File

@@ -3,7 +3,7 @@
********************************************************************** **********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003 * Copyright (C) Richard P. Curnow 1997-2003
* Copyright (C) Miroslav Lichvar 2011-2016, 2018 * Copyright (C) Miroslav Lichvar 2011-2016, 2018, 2020
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as * it under the terms of version 2 of the GNU General Public License as
@@ -1499,22 +1499,21 @@ SRC_ReportSource(int index, RPT_SourceReport *report, struct timespec *now)
case SRC_JITTERY: case SRC_JITTERY:
report->state = RPT_JITTERY; report->state = RPT_JITTERY;
break; break;
case SRC_UNTRUSTED:
case SRC_WAITS_SOURCES: case SRC_WAITS_SOURCES:
case SRC_NONPREFERRED: case SRC_NONPREFERRED:
case SRC_WAITS_UPDATE: case SRC_WAITS_UPDATE:
case SRC_DISTANT: case SRC_DISTANT:
case SRC_OUTLIER: case SRC_OUTLIER:
report->state = RPT_OUTLIER; report->state = RPT_SELECTABLE;
break; break;
case SRC_UNSELECTED: case SRC_UNSELECTED:
report->state = RPT_CANDIDATE; report->state = RPT_UNSELECTED;
break; break;
case SRC_SELECTED: case SRC_SELECTED:
report->state = RPT_SYNC; report->state = RPT_SELECTED;
break; break;
default: default:
report->state = RPT_UNREACH; report->state = RPT_NONSELECTABLE;
break; break;
} }

View File

@@ -49,7 +49,7 @@
#include "sched.h" #include "sched.h"
#include "util.h" #include "util.h"
#ifndef FEAT_ASYNCDNS #if defined(FEAT_NTP) && !defined(FEAT_ASYNCDNS)
/* This is a blocking implementation used when asynchronous resolving is not available */ /* This is a blocking implementation used when asynchronous resolving is not available */

View File

@@ -437,13 +437,16 @@ SYS_Linux_DropRoot(uid_t uid, gid_t gid, int clock_control)
UTI_DropRoot(uid, gid); UTI_DropRoot(uid, gid);
/* Keep CAP_NET_BIND_SERVICE if the NTP server sockets may need to be bound. /* Keep CAP_NET_BIND_SERVICE if the NTP server sockets may need to be bound
Keep CAP_NET_RAW if an NTP socket may need to be bound to a device. to a privileged port.
Keep CAP_NET_RAW if an NTP socket may need to be bound to a device on
kernels before 5.7.
Keep CAP_SYS_TIME if the clock control is enabled. */ Keep CAP_SYS_TIME if the clock control is enabled. */
if (snprintf(cap_text, sizeof (cap_text), "%s %s %s", if (snprintf(cap_text, sizeof (cap_text), "%s %s %s",
CNF_GetNTPPort() ? "cap_net_bind_service=ep" : "", (CNF_GetNTPPort() > 0 && CNF_GetNTPPort() < 1024) ?
CNF_GetBindNtpInterface() || CNF_GetBindAcquisitionInterface() ? "cap_net_bind_service=ep" : "",
"cap_net_raw=ep" : "", (CNF_GetBindNtpInterface() || CNF_GetBindAcquisitionInterface()) &&
!SYS_Linux_CheckKernelVersion(5, 7) ? "cap_net_raw=ep" : "",
clock_control ? "cap_sys_time=ep" : "") >= sizeof (cap_text)) clock_control ? "cap_sys_time=ep" : "") >= sizeof (cap_text))
assert(0); assert(0);
@@ -533,7 +536,11 @@ SYS_Linux_EnableSystemCallFilter(int level, SYS_SystemCallContext context)
SCMP_SYS(getdents), SCMP_SYS(getdents),
SCMP_SYS(getdents64), SCMP_SYS(getdents64),
SCMP_SYS(lseek), SCMP_SYS(lseek),
SCMP_SYS(lstat),
SCMP_SYS(lstat64),
SCMP_SYS(newfstatat), SCMP_SYS(newfstatat),
SCMP_SYS(readlink),
SCMP_SYS(readlinkat),
SCMP_SYS(rename), SCMP_SYS(rename),
SCMP_SYS(renameat), SCMP_SYS(renameat),
SCMP_SYS(renameat2), SCMP_SYS(renameat2),

View File

@@ -4,7 +4,7 @@
********************************************************************** **********************************************************************
* Copyright (C) Richard P. Curnow 1997-2001 * Copyright (C) Richard P. Curnow 1997-2001
* Copyright (C) J. Hannken-Illjes 2001 * Copyright (C) J. Hannken-Illjes 2001
* Copyright (C) Bryan Christianson 2015, 2017 * Copyright (C) Bryan Christianson 2015, 2017, 2020
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as * it under the terms of version 2 of the GNU General Public License as

View File

@@ -68,6 +68,25 @@ static int sys_tai_offset;
/* ================================================== */ /* ================================================== */
static double
convert_timex_frequency(const struct timex *txc)
{
double freq_ppm;
freq_ppm = txc->freq / FREQ_SCALE;
#ifdef MACOSX
/* Temporary workaround for Apple bug treating freq as unsigned number */
if (freq_ppm > 32767) {
freq_ppm -= 65536;
}
#endif
return -freq_ppm;
}
/* ================================================== */
static double static double
read_frequency(void) read_frequency(void)
{ {
@@ -77,7 +96,7 @@ read_frequency(void)
SYS_Timex_Adjust(&txc, 0); SYS_Timex_Adjust(&txc, 0);
return txc.freq / -FREQ_SCALE; return convert_timex_frequency(&txc);
} }
/* ================================================== */ /* ================================================== */
@@ -92,7 +111,7 @@ set_frequency(double freq_ppm)
SYS_Timex_Adjust(&txc, 0); SYS_Timex_Adjust(&txc, 0);
return txc.freq / -FREQ_SCALE; return convert_timex_frequency(&txc);
} }
/* ================================================== */ /* ================================================== */

View File

@@ -17,12 +17,15 @@ for opts in \
"--disable-rtc" \ "--disable-rtc" \
"--disable-sechash" \ "--disable-sechash" \
"--disable-cmdmon" \ "--disable-cmdmon" \
"--disable-cmdmon --enable-scfilter" \
"--disable-ntp" \ "--disable-ntp" \
"--disable-ntp --enable-scfilter" \
"--disable-nts" \ "--disable-nts" \
"--disable-refclock" \ "--disable-refclock" \
"--disable-timestamping" \ "--disable-timestamping" \
"--disable-timestamping --disable-ntp" \ "--disable-timestamping --disable-ntp" \
"--disable-cmdmon --disable-ntp" \ "--disable-cmdmon --disable-ntp" \
"--disable-cmdmon --disable-ntp --enable-scfilter" \
"--disable-cmdmon --disable-refclock" \ "--disable-cmdmon --disable-refclock" \
"--disable-cmdmon --disable-ntp --disable-refclock" "--disable-cmdmon --disable-ntp --disable-refclock"
do do

View File

@@ -52,15 +52,15 @@ test_freqrange(void)
printf("freq range:\n"); printf("freq range:\n");
for (i = 0; i <= 1000; i += 50) { for (i = -1000; i <= 1000; i += 50) {
t.modes = MOD_FREQUENCY; t.modes = MOD_FREQUENCY;
t.freq = i << 16; t.freq = i * (1 << 16);
printf("%4d ppm => ", i); printf("%4d ppm => ", i);
if (try_ntpadjtime(&t) < 0) if (try_ntpadjtime(&t) < 0)
continue; continue;
printf("%4ld ppm : ", t.freq / (1 << 16)); printf("%4ld ppm : ", t.freq / (1 << 16));
printf("%s\n", t.freq == i << 16 ? "ok" : "fail"); printf("%s\n", t.freq == i * (1 << 16) ? "ok" : "fail");
} }
} }

305
test/unit/ntp_auth.c Normal file
View File

@@ -0,0 +1,305 @@
/*
**********************************************************************
* Copyright (C) Miroslav Lichvar 2020
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
**********************************************************************
*/
#include <config.h>
#include <sysincl.h>
#include <conf.h>
#include <keys.h>
#include <local.h>
#include <ntp_ext.h>
#include <ntp_signd.h>
#include <nts_ntp_server.h>
#include <socket.h>
#include "test.h"
#ifdef FEAT_NTP
#include <ntp_auth.c>
static void
prepare_packet(NTP_AuthMode auth_mode, NTP_Packet *packet, NTP_PacketInfo *info, int req)
{
unsigned char buf[64];
int i, version;
NTP_Mode mode;
switch (auth_mode) {
case NTP_AUTH_MSSNTP:
case NTP_AUTH_MSSNTP_EXT:
version = 3;
mode = random() % 2 ? (req ? MODE_CLIENT : MODE_SERVER) :
(req ? MODE_ACTIVE : MODE_PASSIVE);
break;
case NTP_AUTH_NTS:
version = 4;
mode = req ? MODE_CLIENT : MODE_SERVER;
break;
default:
version = 3 + random() % 2;
mode = random() % 2 ? (req ? MODE_CLIENT : MODE_SERVER) :
(req ? MODE_ACTIVE : MODE_PASSIVE);
break;
}
memset(packet, 0, sizeof (*packet));
memset(info, 0, sizeof (*info));
packet->lvm = NTP_LVM(LEAP_Normal, version, mode);
info->length = NTP_HEADER_LENGTH;
info->version = version;
info->mode = mode;
if (version == 4) {
memset(buf, 0, sizeof (buf));
for (i = random() % 5; i > 0; i--)
TEST_CHECK(NEF_AddField(packet, info, 0, buf, sizeof (buf)));
}
}
static void
add_dummy_auth(NTP_AuthMode auth_mode, uint32_t key_id, NTP_Packet *packet, NTP_PacketInfo *info)
{
unsigned char buf[64];
int len, fill;
info->auth.mode = auth_mode;
switch (auth_mode) {
case NTP_AUTH_NONE:
break;
case NTP_AUTH_SYMMETRIC:
case NTP_AUTH_MSSNTP:
case NTP_AUTH_MSSNTP_EXT:
switch (auth_mode) {
case NTP_AUTH_SYMMETRIC:
len = 16 + random() % 2 * 4;
fill = 1 + random() % 255;
break;
case NTP_AUTH_MSSNTP:
len = 16;
fill = 0;
break;
case NTP_AUTH_MSSNTP_EXT:
len = 68;
fill = 0;
break;
default:
assert(0);
}
assert(info->length + 4 + len <= sizeof (*packet));
*(uint32_t *)((unsigned char *)packet + info->length) = htonl(key_id);
info->auth.mac.key_id = key_id;
info->length += 4;
memset((unsigned char *)packet + info->length, fill, len);
info->length += len;
break;
case NTP_AUTH_NTS:
memset(buf, 0, sizeof (buf));
TEST_CHECK(NEF_AddField(packet, info, NTP_EF_NTS_AUTH_AND_EEF, buf, sizeof (buf)));
break;
default:
assert(0);
}
}
void
test_unit(void)
{
int i, j, can_auth_req, can_auth_res;
NTP_PacketInfo req_info, res_info;
NTP_Packet req, res;
NAU_Instance inst;
RPT_AuthReport report;
NTP_AuthMode mode;
IPSockAddr nts_addr;
uint32_t key_id, kod;
char conf[][100] = {
"keyfile ntp_core.keys"
};
CNF_Initialise(0, 0);
for (i = 0; i < sizeof conf / sizeof conf[0]; i++)
CNF_ParseLine(NULL, i + 1, conf[i]);
LCL_Initialise();
TST_SuspendLogging();
KEY_Initialise();
TST_ResumeLogging();
NSD_Initialise();
NNS_Initialise();
SCK_GetAnyLocalIPAddress(IPADDR_INET4, &nts_addr.ip_addr);
nts_addr.port = 0;
for (i = 0; i < 1000; i++) {
TST_SuspendLogging();
key_id = INACTIVE_AUTHKEY;
switch (i % 5) {
case 0:
inst = NAU_CreateNoneInstance();
TEST_CHECK(!NAU_IsAuthEnabled(inst));
TEST_CHECK(NAU_GetSuggestedNtpVersion(inst) == 4);
mode = NTP_AUTH_NONE;
can_auth_req = 1;
can_auth_res = 1;
break;
case 1:
key_id = random() % 7 + 2;
inst = NAU_CreateSymmetricInstance(key_id);
TEST_CHECK(NAU_IsAuthEnabled(inst));
TEST_CHECK(NAU_GetSuggestedNtpVersion(inst) ==
(KEY_KeyKnown(inst->key_id) && KEY_GetAuthLength(inst->key_id) > 20 ? 3 : 4));
mode = NTP_AUTH_SYMMETRIC;
can_auth_req = KEY_KeyKnown(key_id);
can_auth_res = can_auth_req;
break;
case 2:
inst = NAU_CreateNtsInstance(&nts_addr, "test", &nts_addr);
TEST_CHECK(NAU_IsAuthEnabled(inst));
TEST_CHECK(NAU_GetSuggestedNtpVersion(inst) == 4);
mode = NTP_AUTH_NTS;
can_auth_req = 0;
can_auth_res = 0;
break;
case 3:
key_id = 1 + random() % 100;
inst = NULL;
mode = NTP_AUTH_MSSNTP;
can_auth_req = 1;
can_auth_res = 0;
break;
case 4:
key_id = 1 + random() % 100;
inst = NULL;
mode = NTP_AUTH_MSSNTP_EXT;
can_auth_req = 0;
can_auth_res = 0;
break;
default:
assert(0);
}
TST_ResumeLogging();
DEBUG_LOG("iteration %d auth=%d key_id=%d", i, (int)mode, (int)key_id);
prepare_packet(mode, &req, &req_info, 1);
if (inst) {
TEST_CHECK(inst->mode == mode);
TEST_CHECK(inst->key_id == key_id);
NAU_DumpData(inst);
NAU_GetReport(inst, &report);
if (random() % 2)
NAU_ChangeAddress(inst, &nts_addr.ip_addr);
if (inst->mode == NTP_AUTH_NTS) {
TST_SuspendLogging();
for (j = random() % 5; j > 0; j--)
#ifdef FEAT_NTS
TEST_CHECK(!NAU_PrepareRequestAuth(inst));
#else
TEST_CHECK(NAU_PrepareRequestAuth(inst));
#endif
TEST_CHECK(!NAU_GenerateRequestAuth(inst, &req, &req_info));
TST_ResumeLogging();
} else if (can_auth_req) {
TEST_CHECK(NAU_PrepareRequestAuth(inst));
TEST_CHECK(NAU_GenerateRequestAuth(inst, &req, &req_info));
} else {
TEST_CHECK(NAU_PrepareRequestAuth(inst));
TEST_CHECK(!NAU_GenerateRequestAuth(inst, &req, &req_info));
}
}
if (!inst || !can_auth_req)
add_dummy_auth(mode, key_id, &req, &req_info);
TEST_CHECK(req_info.auth.mode == mode);
memset(&req_info.auth, 0, sizeof (req_info.auth));
TEST_CHECK(NAU_ParsePacket(&req, &req_info));
TEST_CHECK(req_info.auth.mode == mode);
TEST_CHECK(req_info.auth.mac.key_id == key_id);
kod = 1;
TEST_CHECK(NAU_CheckRequestAuth(&req, &req_info, &kod) == can_auth_req);
TEST_CHECK(kod == 0);
if (inst) {
for (j = NTP_AUTH_NONE; j <= NTP_AUTH_NTS; j++) {
if (j == mode && j == NTP_AUTH_NONE)
continue;
prepare_packet(j, &res, &res_info, 0);
add_dummy_auth(j, key_id ? key_id : 1, &res, &res_info);
TEST_CHECK(res_info.auth.mode == j);
TEST_CHECK(!NAU_CheckResponseAuth(inst, &res, &res_info));
}
}
prepare_packet(mode, &res, &res_info, 0);
TEST_CHECK(NAU_GenerateResponseAuth(&req, &req_info, &res, &res_info, NULL, NULL, kod) ==
can_auth_res);
if (!can_auth_res)
add_dummy_auth(mode, key_id, &res, &res_info);
memset(&res_info.auth, 0, sizeof (res_info.auth));
TEST_CHECK(NAU_ParsePacket(&res, &res_info));
TEST_CHECK(res_info.auth.mode == mode);
TEST_CHECK(res_info.auth.mac.key_id == key_id);
if (inst) {
if (mode == NTP_AUTH_SYMMETRIC) {
res_info.auth.mac.key_id ^= 1;
TEST_CHECK(!NAU_CheckResponseAuth(inst, &res, &res_info));
res_info.auth.mac.key_id ^= 1;
}
TEST_CHECK(NAU_CheckResponseAuth(inst, &res, &res_info) == can_auth_res);
NAU_GetReport(inst, &report);
NAU_DestroyInstance(inst);
}
}
NNS_Finalise();
NSD_Finalise();
KEY_Finalise();
LCL_Finalise();
CNF_Finalise();
HSH_Finalise();
}
#else
void
test_unit(void)
{
TEST_REQUIRE(0);
}
#endif

View File

@@ -23,6 +23,7 @@
#include <cmdparse.h> #include <cmdparse.h>
#include <conf.h> #include <conf.h>
#include <keys.h> #include <keys.h>
#include <ntp_ext.h>
#include <ntp_io.h> #include <ntp_io.h>
#include <sched.h> #include <sched.h>
#include <local.h> #include <local.h>
@@ -138,7 +139,7 @@ send_response(int interleaved, int authenticated, int allow_update, int valid_ts
{ {
NTP_Packet *req, *res; NTP_Packet *req, *res;
uint32_t key_id = 0; uint32_t key_id = 0;
int auth_len = 0; int i, auth_len = 0, ef_len, efs;
req = &req_buffer; req = &req_buffer;
res = &res_buffer; res = &res_buffer;
@@ -184,51 +185,85 @@ send_response(int interleaved, int authenticated, int allow_update, int valid_ts
} }
} }
res_length = NTP_HEADER_LENGTH;
if (NTP_LVM_TO_VERSION(res->lvm) == 4 && random() % 2) {
unsigned char buf[128];
memset(buf, 0, sizeof (buf));
efs = random() % 5;
for (i = 0; i < efs; i++) {
ef_len = (i + 1 == efs ? NTP_MAX_V4_MAC_LENGTH + 4 : NTP_MIN_EF_LENGTH) +
4 * (random() % 10);
TEST_CHECK(NEF_SetField((unsigned char *)res, sizeof (*res), res_length, 0,
buf, ef_len - 4, &ef_len));
res_length += ef_len;
}
}
if (authenticated) { if (authenticated) {
key_id = ntohl(*(uint32_t *)req->extensions); key_id = ntohl(*(uint32_t *)req->extensions);
if (key_id == 0) if (key_id == 0)
key_id = get_random_key_id(); key_id = get_random_key_id();
auth_len = KEY_GetAuthLength(key_id); auth_len = KEY_GetAuthLength(key_id);
assert(auth_len); assert(auth_len);
if (NTP_LVM_TO_VERSION(res->lvm) == 4 && random() % 2) if (NTP_LVM_TO_VERSION(res->lvm) == 4)
auth_len = MIN(auth_len, NTP_MAX_V4_MAC_LENGTH - 4); auth_len = MIN(auth_len, NTP_MAX_V4_MAC_LENGTH - 4);
if (KEY_GenerateAuth(key_id, (unsigned char *)res, NTP_HEADER_LENGTH, if (KEY_GenerateAuth(key_id, res, res_length,
res->extensions + 4, auth_len) != auth_len) (unsigned char *)res + res_length + 4, auth_len) != auth_len)
assert(0); assert(0);
res_length = NTP_HEADER_LENGTH + 4 + auth_len; res_length += 4 + auth_len;
} else {
res_length = NTP_HEADER_LENGTH;
} }
if (!valid_auth && authenticated) { if (!valid_auth && authenticated) {
assert(auth_len); assert(auth_len);
switch (random() % 4) { switch (random() % 5) {
case 0: case 0:
key_id++; key_id++;
break; break;
case 1: case 1:
key_id ^= 1; key_id ^= 1;
if (KEY_GenerateAuth(key_id, (unsigned char *)res, NTP_HEADER_LENGTH, if (KEY_GenerateAuth(key_id, res, res_length - auth_len - 4,
res->extensions + 4, auth_len) != auth_len) (unsigned char *)res + res_length - auth_len, auth_len) != auth_len)
assert(0); assert(0);
break; break;
case 2: case 2:
res->extensions[4 + random() % auth_len]++; ((unsigned char *)res)[res_length - auth_len + random() % auth_len]++;
break; break;
case 3: case 3:
res_length = NTP_HEADER_LENGTH + 4 * (random() % ((4 + auth_len) / 4)); res_length -= 4 + auth_len;
if (NTP_LVM_TO_VERSION(res->lvm) == 4 && auth_len = 4 * (random() % (auth_len / 4));
res_length == NTP_HEADER_LENGTH + NTP_MAX_V4_MAC_LENGTH) res_length += 4 + auth_len;
res_length -= 4; break;
case 4:
if (NTP_LVM_TO_VERSION(res->lvm) == 4 && random() % 2 &&
KEY_GetAuthLength(key_id) > NTP_MAX_V4_MAC_LENGTH - 4) {
res_length -= 4 + auth_len;
auth_len += 4 + 4 * (random() %
((KEY_GetAuthLength(key_id) - NTP_MAX_V4_MAC_LENGTH - 4) / 4));
if (KEY_GenerateAuth(key_id, res, res_length,
(unsigned char *)res + res_length + 4, auth_len) != auth_len)
assert(0);
res_length += 4 + auth_len;
} else {
memset((unsigned char *)res + res_length, 0, 4);
auth_len += 4;
res_length += 4;
}
break; break;
default: default:
assert(0); assert(0);
} }
} }
*(uint32_t *)res->extensions = htonl(key_id); assert(res_length <= sizeof (*res));
assert(res_length >= NTP_HEADER_LENGTH + auth_len);
if (authenticated)
*(uint32_t *)((unsigned char *)res + res_length - auth_len - 4) = htonl(key_id);
} }
static void static void

View File

@@ -149,6 +149,17 @@ test_unit(void)
TEST_CHECK(SIV_GetKeyLength(tests[i].algorithm) == tests[i].key_length); TEST_CHECK(SIV_GetKeyLength(tests[i].algorithm) == tests[i].key_length);
r = SIV_Encrypt(siv, tests[i].nonce, tests[i].nonce_length,
tests[i].assoc, tests[i].assoc_length,
tests[i].plaintext, tests[i].plaintext_length,
ciphertext, tests[i].ciphertext_length);
TEST_CHECK(!r);
r = SIV_Decrypt(siv, tests[i].nonce, tests[i].nonce_length,
tests[i].assoc, tests[i].assoc_length,
tests[i].ciphertext, tests[i].ciphertext_length,
plaintext, tests[i].plaintext_length);
TEST_CHECK(!r);
for (j = -1; j < 1024; j++) { for (j = -1; j < 1024; j++) {
r = SIV_SetKey(siv, tests[i].key, j); r = SIV_SetKey(siv, tests[i].key, j);
TEST_CHECK(r == (j == tests[i].key_length)); TEST_CHECK(r == (j == tests[i].key_length));

2
util.c
View File

@@ -3,7 +3,7 @@
********************************************************************** **********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003 * Copyright (C) Richard P. Curnow 1997-2003
* Copyright (C) Miroslav Lichvar 2009, 2012-2018 * Copyright (C) Miroslav Lichvar 2009, 2012-2020
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as * it under the terms of version 2 of the GNU General Public License as