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 binddevice, bindacqdevice, bindcmddevice directives
* Add confdir directive to better support fragmented configuration
* Add sourcedir directive and "reload sources" command to support
dynamic NTP sources specified in files
* Add sourcedir directive and "reload sources" command to support dynamic
NTP sources specified in files
* Add clockprecision directive
* Add dscp directive to set Differentiated Services Code Point (DSCP)
* Add -L option to limit log messages by severity
* 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
* Avoid replacing NTP sources with sources that have unreachable address
* Improve pools to repeat name resolution to get "maxsources" sources
@@ -38,6 +40,9 @@ Bug fixes
Removed features
----------------
* 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
====================

View File

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

View File

@@ -4,7 +4,7 @@
**********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003
* 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
* it under the terms of version 2 of the GNU General Public License as
@@ -44,12 +44,7 @@
#include "util.h"
#ifdef FEAT_READLINE
#ifdef USE_EDITLINE
#include <editline/readline.h>
#else
#include <readline/readline.h>
#include <readline/history.h>
#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
@@ -2146,8 +2141,8 @@ process_cmd_sources(char *line)
if (verbose) {
printf("\n");
printf(" .-- Source mode '^' = server, '=' = peer, '#' = local clock.\n");
printf(" / .- Source state '*' = current synced, '+' = combined , '-' = not combined,\n");
printf("| / '?' = unreachable, 'x' = time may be in error, '~' = time too variable.\n");
printf(" / .- Source state '*' = current best, '+' = combined, '-' = not combined,\n");
printf("| / 'x' = may be in error, '~' = too variable, '?' = unusable.\n");
printf("|| .- xxxx [ yyyy ] +/- zzzz\n");
printf("|| Reachability register (octal) -. | xxxx = adjusted 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)) {
case RPY_SD_ST_SYNC:
case RPY_SD_ST_SELECTED:
state_ch = '*';
break;
case RPY_SD_ST_UNREACH:
case RPY_SD_ST_NONSELECTABLE:
state_ch = '?';
break;
case RPY_SD_ST_FALSETICKER:
@@ -2201,10 +2196,10 @@ process_cmd_sources(char *line)
case RPY_SD_ST_JITTERY:
state_ch = '~';
break;
case RPY_SD_ST_CANDIDATE:
case RPY_SD_ST_UNSELECTED:
state_ch = '+';
break;
case RPY_SD_ST_OUTLIER:
case RPY_SD_ST_SELECTABLE:
state_ch = '-';
break;
default:
@@ -3476,7 +3471,7 @@ static void
display_gpl(void)
{
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"
"you are welcome to redistribute it under certain conditions. See the\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) 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
* it under the terms of version 2 of the GNU General Public License as
@@ -294,10 +294,16 @@ CAM_OpenUnixSocket(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);
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
interface */
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.poll = htons(report.poll);
switch (report.state) {
case RPT_SYNC:
tx_message->data.source_data.state = htons(RPY_SD_ST_SYNC);
break;
case RPT_UNREACH:
tx_message->data.source_data.state = htons(RPY_SD_ST_UNREACH);
case RPT_NONSELECTABLE:
tx_message->data.source_data.state = htons(RPY_SD_ST_NONSELECTABLE);
break;
case RPT_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:
tx_message->data.source_data.state = htons(RPY_SD_ST_JITTERY);
break;
case RPT_CANDIDATE:
tx_message->data.source_data.state = htons(RPY_SD_ST_CANDIDATE);
case RPT_SELECTABLE:
tx_message->data.source_data.state = htons(RPY_SD_ST_SELECTABLE);
break;
case RPT_OUTLIER:
tx_message->data.source_data.state = htons(RPY_SD_ST_OUTLIER);
case RPT_UNSELECTED:
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;
}
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) {
tx_message.status = htons(STT_BADPKTVERSION);
transmit_reply(sock_fd, sck_message);
transmit_reply(sock_fd, read_length, sck_message);
}
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);
tx_message.status = htons(STT_INVALID);
transmit_reply(sock_fd, sck_message);
transmit_reply(sock_fd, read_length, sck_message);
return;
}
@@ -1446,7 +1452,7 @@ read_from_cmd_socket(int sock_fd, int event, void *anything)
expected_length);
tx_message.status = htons(STT_BADPKTLENGTH);
transmit_reply(sock_fd, sck_message);
transmit_reply(sock_fd, read_length, sck_message);
return;
}
@@ -1733,19 +1739,7 @@ read_from_cmd_socket(int sock_fd, int event, void *anything)
}
/* Transmit the response */
{
/* 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
}
transmit_reply(sock_fd, read_length, sck_message);
}
/* ================================================== */

13
conf.c
View File

@@ -3,7 +3,7 @@
**********************************************************************
* 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
* 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_drift = 500000.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 double max_distance = 3.0;
@@ -544,6 +545,8 @@ CNF_ParseLine(const char *filename, int number, char *line)
parse_broadcast(p);
} else if (!strcasecmp(command, "clientloglimit")) {
parse_clientloglimit(p);
} else if (!strcasecmp(command, "clockprecision")) {
parse_double(p, &clock_precision);
} else if (!strcasecmp(command, "cmdallow")) {
parse_allow_deny(p, cmd_restrictions, 1);
} else if (!strcasecmp(command, "cmddeny")) {
@@ -2048,6 +2051,14 @@ CNF_GetMaxSlewRate(void)
/* ================================================== */
double
CNF_GetClockPrecision(void)
{
return clock_precision;
}
/* ================================================== */
double
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_GetCorrectionTimeRatio(void);
extern double CNF_GetMaxSlewRate(void);
extern double CNF_GetClockPrecision(void);
extern SRC_AuthSelectMode CNF_GetAuthSelectMode(void);
extern double CNF_GetMaxDistance(void);

62
configure vendored
View File

@@ -5,7 +5,7 @@
#
# Copyright (C) Richard P. Curnow 1997-2003
# 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
#
# =======================================================================
@@ -108,11 +108,7 @@ for instance \`--prefix=$HOME'.
For better control, use the options below.
--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
--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
--without-nettle Don't use nettle 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_refclock=1
feat_readline=1
try_readline=1
try_editline=1
feat_sechash=1
try_nettle=1
@@ -241,9 +236,6 @@ try_clockctl=0
feat_scfilter=0
try_seccomp=-1
priv_ops=""
readline_lib=""
readline_inc=""
ncurses_lib=""
feat_ipv6=1
feat_phc=1
try_phc=0
@@ -274,21 +266,9 @@ do
--disable-readline )
feat_readline=0
;;
--without-readline )
try_readline=0
;;
--without-editline )
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=* )
SETPREFIX=`echo $option | sed -e 's/[^=]*=//;'`
;;
@@ -804,10 +784,12 @@ if [ $feat_scfilter = "1" ] && [ $try_seccomp = "1" ] && \
'seccomp_init(SCMP_ACT_KILL);'
then
add_def FEAT_SCFILTER
# NAME2IPADDRESS shouldn't be enabled with other operations as the helper
# process works on one request at the time and the async resolver could
# block the main thread
if [ $feat_ntp = "1" ]; then
# NAME2IPADDRESS shouldn't be enabled together with a privops operation
# used by the main thread as the helper process works on one request at
# a time and the async resolver would block the main thread
priv_ops="NAME2IPADDRESS RELOADDNS"
fi
EXTRA_LIBS="$EXTRA_LIBS -lseccomp"
fi
@@ -876,37 +858,11 @@ fi
READLINE_LINK=""
if [ $feat_readline = "1" ]; then
if [ $try_editline = "1" ]; then
if test_code editline 'stdio.h editline/readline.h' \
"$readline_inc" "$readline_lib -ledit" \
if test_code editline 'stdio.h editline/readline.h' '' '-ledit' \
'add_history(readline("prompt"));'
then
add_def FEAT_READLINE
add_def USE_EDITLINE
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"
READLINE_LINK="-ledit"
fi
fi
@@ -972,7 +928,7 @@ if [ $feat_ntp = "1" ] && [ $feat_nts = "1" ] && [ $try_gnutls = "1" ]; then
test_link="`pkg_config --libs gnutls`"
if test_code 'gnutls' 'gnutls/gnutls.h' \
"$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_prf_rfc5705(NULL, 0, "", 0, "", 16, NULL);'
then

View File

@@ -3,7 +3,7 @@
// Copyright (C) Richard P. Curnow 1997-2003
// Copyright (C) Stephen Wadeley 2016
// 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
// it under the terms of version 2 of the GNU General Public License as
@@ -32,12 +32,14 @@ chrony.conf - chronyd configuration file
== DESCRIPTION
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.
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
occur in any order in the file and they are not case-sensitive.
following sections describe each of the directives in turn. The directives are
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*
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
will never be influenced by that of a client.
+
The *server* directive is immediately followed by either the name of the
server, or its IP address. The *server* directive supports the following
options:
This directive can be used multiple times to specify multiple servers.
+
The directive is immediately followed by either the name of the
server, or its IP address. It supports the following options:
+
*minpoll* _poll_:::
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
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
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
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*
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
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*:
+
*PPS*:::
@@ -610,12 +619,13 @@ behaviour, whereas the *settime* command allows samples of manually entered
time to be provided.)
[[acquisitionport]]*acquisitionport* _port_::
By default, *chronyd* uses a separate client socket for each configured server
and their source port is chosen arbitrarily by the operating system. However,
you can use the *acquisitionport* directive to explicitly specify a port and
use only one socket (per IPv4 or IPv6 address family) for all configured servers.
This can be useful for getting through some firewalls. If set to 0, the source
port of the socket will be chosen arbitrarily.
By default, *chronyd* as an NTP client opens a new socket for each request with
the source port chosen randomly by the operating system. The *acquisitionport*
directive can be used to specify the source port and use only one socket (per
IPv4 or IPv6 address family) for all configured servers. This can be useful for
getting through some firewalls. It should not be used if not necessary as there
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
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_::
The *bindacqaddress* directive specifies a local IP address to which
*chronyd* will bind its NTP client sockets. The syntax is similar to the
<<bindaddress,*bindaddress*>> and <<bindcmdaddress,*bindcmdaddress*>>
*chronyd* will bind its NTP and NTS-KE client sockets. The syntax is similar to
the <<bindaddress,*bindaddress*>> and <<bindcmdaddress,*bindcmdaddress*>>
directives.
+
For each of the IPv4 and IPv6 protocols, only one *bindacqaddress* directive
@@ -908,6 +918,27 @@ distances are in milliseconds.
=== 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_::
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
@@ -1039,7 +1070,7 @@ A recommended configuration to enable a server leap smear is:
----
leapsecmode slew
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
@@ -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
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
UTC and it will take 17 hours 34 minutes to finish. The frequency offset will
be changing by 0.001 ppm per second and will reach a maximum of 31.623 ppm. The
*leaponly* option makes the duration of the leap smear constant and allows the
clients to safely synchronise with multiple identically configured leap
smearing servers.
UTC and it will take 62500 seconds (about 17.36 hours) to finish. The frequency
offset will be changing by 0.001024 ppm per second and will reach a maximum of
32 ppm in 31250 seconds. The *leaponly* option makes the duration of the leap
smear constant and allows the clients to safely synchronise with multiple
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_::
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
+
----
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
@@ -1272,12 +1309,15 @@ _tempcomp.log_ file if enabled by the <<log,*log tempcomp*>> directive.
[[allow]]*allow* [*all*] [_subnet_]::
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
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.
+
This directive can be used multiple times.
+
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_]::
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*
directive.
[[bindaddress]]*bindaddress* _address_::
The *bindaddress* directive binds the socket on which *chronyd* listens for NTP
requests to a local address of the computer. On systems other than Linux, the
address of the computer needs to be already configured when *chronyd* is
started.
The *bindaddress* directive binds the sockets on which *chronyd* listens for
NTP and NTS-KE requests to a local address of the computer. On systems other
than Linux, the address of the computer needs to be already configured when
*chronyd* is started.
+
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.
[[binddevice]]*binddevice* _interface_::
The *binddevice* directive binds the NTP server sockets to a network device
specified by the interface name. This directive can specify only one interface
and it is supported on Linux only.
The *binddevice* directive binds the NTP and NTS-KE server sockets to a network
device specified by the interface name. This directive can specify only one
interface and it is supported on Linux only.
+
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
synchronise.
+
This directive can be used multiple times to specify multiple addresses.
+
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
other servers with the *local* directive. This ensures only the server with the
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
*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:
+
----
local stratum 10 orphan
local stratum 10 orphan distance 0.1
----
[[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
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*
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.
+
@@ -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
be replaced by adding files to a different directory.
+
This directive can be used multiple times.
+
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
network interface by a networking script.
+
This directive can be used multiple times.
+
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
required to exist.
+
This directive can be used multiple times.
+
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
*chronyc*.
+
If the specified interface is _*_, *chronyd* will try to enable HW timestamping
on all available interfaces.
This directive can be used multiple times to enable HW timestamping on multiple
interfaces. If the specified interface is _*_, *chronyd* will try to enable HW
timestamping on all available interfaces.
+
The *hwtimestamp* directive has the following options:
+
@@ -2497,6 +2550,20 @@ makestep 1.0 3
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
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) 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
// 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
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,
the prompt is not shown.
the prompt will not be shown.
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
@@ -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
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
from the network if they were authenticated with a password, but that is no
longer supported.
if it is from localhost.
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.
@@ -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
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
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.
*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*:::
This is a long-term average of the offset value.
*Frequency*:::
@@ -317,18 +317,23 @@ The columns are as follows:
This indicates the mode of the source. _^_ means a server, _=_ means a peer
and _#_ indicates a locally connected reference clock.
*S*:::
This column indicates the state of the source.
* _*_ indicates the source to which *chronyd* is currently synchronised.
* _+_ indicates acceptable sources which are combined with the selected
source.
* _-_ indicates acceptable sources which are excluded by the combining
algorithm.
* _?_ indicates sources to which connectivity has been lost or whose packets
do not pass all tests. It is also shown at start-up, until at least 3 samples
have been gathered from it.
* _x_ indicates a clock which *chronyd* thinks is a falseticker (i.e. its
time is inconsistent with a majority of other sources).
This column indicates the selection state of the source.
* _*_ indicates the best source which is currently selected for
synchronisation.
* _+_ indicates other sources selected for synchronisation, which are combined
with the best source.
* _-_ indicates a source which is considered to be selectable for
synchronisation, but not currently selected.
* _x_ indicates a source which *chronyd* thinks is a falseticker (i.e. its
time is inconsistent with a majority of other sources, or sources specified
with the *trust* option).
* _~_ 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*:::
This shows the name or the IP address of the source, or reference ID for reference
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
# chronyc cyclelogs
# ls -l /var/log/chrony
-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
# rm /var/log/chrony/measurements1.log
----
[[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
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
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*::
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
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*::
[[quit]]*quit*::

View File

@@ -55,7 +55,7 @@ IPv6 sockets will be created.
*-f* _file_::
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*::
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_::
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
<<chrony.conf.adoc#user,*user*>> directive. The default value is
<<chrony.conf.adoc#user,*user*>> directive. The compiled-in default value is
_@DEFAULT_USER@_.
+
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
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_::
This option configures a system call filter when *chronyd* is compiled with
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
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
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
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
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
option allows *chronyd* to run without the capability to adjust or set the
system clock (e.g. in some containers) in order to operate as an NTP server. It
is not recommended to run *chronyd* (with or without *-x*) when another process
is controlling the system clock.
option allows *chronyd* to be started without the capability to adjust or set
the system clock (e.g. in some containers) to operate as an NTP server.
*-v*::
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
//
// 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
// it under the terms of version 2 of the GNU General Public License as
@@ -24,17 +24,20 @@
=== How does `chrony` compare to `ntpd`?
`chronyd` was designed to work well in a wide range of conditions and it can
usually synchronise the system clock faster and with better time accuracy. It
doesn't implement some of the less useful NTP modes like broadcast client or
multicast server/client.
`chrony` and `ntpd` are two different implementations of the Network Time
Protocol (NTP).
`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,
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
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`
will probably work much better for you.
will probably work better for you.
For a more detailed comparison of features and performance, see the
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.
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
system time is periodically copied to the RTC. It is supported on Linux and
macOS.
@@ -75,52 +78,36 @@ makestep 1 3
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
the NTP port and allow `chronyd` to reply to client requests. `allow` with no
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
the others as clients of it. Add a `local` directive to the server's
_chrony.conf_ file. This configuration will be better because
It depends on the requirements. Usually, the best configuration is to make one
computer the server, with the others as clients of it. Add a `local` directive
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 NTP server(s) is less
* if your external connection goes down, the computers on the LAN
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
increasing interval until it succeeds. The `online` command can be issued from
`chronyc` to force `chronyd` to try to resolve the names immediately.
=== 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`
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
If you do not need to use `chronyc`, or you want to run `chronyc` only
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
completely by adding `cmdport 0` to the configuration file.
domain socket), you can disable the IPv4 and IPv6 command sockets (by default
listening on localhost) by adding `cmdport 0` to the configuration file.
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
@@ -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
(seccomp) facility, you can enable a system call filter with the `-F` option.
It will significantly reduce the kernel attack surface and possibly prevent
kernel exploits from the `chronyd` process if it's compromised. It's
recommended to enable the filter only when it's known to work on the version of
kernel exploits from the `chronyd` process if it is compromised. 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 also system
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
normal operation.
=== 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
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
time and combine measurements from multiple sources.
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
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
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
shorter polling intervals may significantly improve the accuracy of the system
clock.
shorter polling intervals might significantly improve the accuracy of the
system clock.
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
@@ -174,7 +161,7 @@ temperature change).
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
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
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
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
@@ -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
(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
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
excessive rate, a sub-second polling interval may be specified. A median filter
If it is acceptable for NTP clients in the network to send requests at a high
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
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.
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:
----
@@ -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
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
the `maxsamples` option, and a timeout can be specified with the `-t` option.
The following command would take only up to about 1 second.
the `maxsamples` option to one (supported in `chrony` version 4.0), and a
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'
----
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`?
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
changes in the frequency and offset of the clock. The `maxslewrate` and
@@ -279,10 +278,56 @@ maxchange 1000 1 1
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
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?
They were removed in version 2.2. Authentication is no longer supported in the
@@ -299,11 +344,11 @@ following questions.
=== Behind a firewall?
Check the `Reach` value printed by the ``chronyc``'s `sources` command. If it's
zero, it means `chronyd` did not get any valid responses from the NTP server
Check the `Reach` value printed by the ``chronyc``'s `sources` command. If it
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
packets may be blocked. Try using a tool like `wireshark` or `tcpdump` to see
if you're getting any responses from the server.
packets might be blocked. Try using a tool like `wireshark` or `tcpdump` to see
if you are getting any responses from the server.
When `chronyd` is receiving responses from the servers, the output of the
`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?
Check that you're using ``chronyc``'s `online` and `offline` commands
appropriately. The `activity` command prints the number of sources that are
currently online and offline. For example:
Check that the ``chronyc``'s `online` and `offline` commands are used
appropriately (e.g. in the system networking scripts). The `activity` command
prints the number of sources that are currently online and offline. For
example:
----
200 OK
@@ -349,9 +395,9 @@ makestep 1 3
----
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
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
to
@@ -363,7 +409,7 @@ makestep 1 -1
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
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
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
----
=== 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?
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
the computer where `chronyd` is running) has a `cmdallow` entry for the
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,
`ps -auxw`) to see if it's running. Or try `netstat -a` and see if the ports
123/udp and 323/udp are listening. If `chronyd` is not running, you may have a
problem with the way you are trying to start it (e.g. at boot time).
`ps -auxw`) to see if it is running. Or try `netstat -a` and see if the UDP
port 323 is listening. If `chronyd` is not running, you might have a problem
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
323/udp. You need to amend the firewall configuration in this case.
Perhaps you have a firewall set up in a way that blocks packets on the UDP
port 323. You need to amend the firewall configuration in this case.
=== 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
_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
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
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).
=== What is the reference ID reported by the `tracking` command?
=== 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
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
@@ -463,7 +528,7 @@ Only by the source code. See _cmdmon.c_ (`chronyd` side) and _client.c_
=== What is the real-time clock (RTC)?
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.
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
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
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.
=== 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
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
system clock is synchronised. If you want to use ``chronyd``'s RTC monitoring
(`rtcfile` directive), it's important to disable `hwclock` in the shutdown
procedure. If you don't, it will over-write the RTC with a new value, unknown
(`rtcfile` directive), it is important to disable `hwclock` in the shutdown
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
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.
@@ -507,7 +572,7 @@ things
=== 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?
@@ -522,7 +587,7 @@ observe backward steps.
=== Can `chronyd` be driven from broadcast/multicast NTP servers?
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
(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
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?
@@ -555,9 +621,21 @@ offline, `chronyd` would make new measurements immediately after issuing the
`online` command.
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.
=== 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
=== 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
`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,
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`
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
The `configure` and `make` procedures have some extra options that may be

View File

@@ -8,9 +8,11 @@ Wants=time-sync.target
[Service]
Type=oneshot
# Wait up to ~10 minutes for chronyd to synchronize and the remaining
# clock 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
# Wait for chronyd to update the clock and the remaining
# correction to be less than 0.1 seconds
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
StandardOutput=null

2
keys.c
View File

@@ -3,7 +3,7 @@
**********************************************************************
* 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
* 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
static void
calculate_sys_precision(void)
static double
measure_clock_precision(void)
{
struct timespec ts, old_ts;
int iters, diff, best;
@@ -135,18 +135,7 @@ calculate_sys_precision(void)
assert(best > 0);
precision_quantum = 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);
return 1.0e-9 * best;
}
/* ================================================== */
@@ -170,7 +159,16 @@ LCL_Initialise(void)
current_freq_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
never stop or run backwards */

View File

@@ -3,7 +3,7 @@
**********************************************************************
* 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
* 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) 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
* 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 scfilter_level = 0, lock_memory = 0, sched_priority = 0;
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();
@@ -431,7 +431,7 @@ int main
optind = 1;
/* 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) {
case '4':
case '6':
@@ -462,7 +462,7 @@ int main
break;
case 'p':
print_config = 1;
client_only = 1;
user_check = 0;
nofork = 1;
system_log = 0;
break;
@@ -479,6 +479,7 @@ int main
ref_mode = REF_ModePrintOnce;
nofork = 1;
client_only = 1;
user_check = 0;
clock_control = 0;
system_log = 0;
break;
@@ -497,6 +498,9 @@ int main
case 'u':
user = optarg;
break;
case 'U':
user_check = 0;
break;
case 'v':
print_version();
return 0;
@@ -509,7 +513,7 @@ int main
}
}
if (getuid() && !client_only)
if (user_check && getuid() != 0)
LOG_FATAL("Not superuser");
/* Turn into a daemon */

View File

@@ -2,7 +2,7 @@
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
* 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)
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 */
if (!NEF_ParseField(packet, info->length, parsed, &ef_length, &ef_type, NULL, NULL)) {
/* Invalid MAC or format error */
DEBUG_LOG("Invalid format or MAC");
DEBUG_LOG("Invalid format");
return 0;
}
@@ -340,9 +328,6 @@ NAU_ParsePacket(NTP_Packet *packet, NTP_PacketInfo *info)
/* No MAC */
return 1;
} 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.mac.start = parsed;
info->auth.mac.length = remainder;

View File

@@ -3,7 +3,7 @@
**********************************************************************
* 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
* 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();
}
/* 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;
tx_ts = NULL;
interleaved = 0;
@@ -2133,6 +2124,9 @@ NCR_ProcessRxUnknown(NTP_Remote_Address *remote_addr, NTP_Local_Address *local_a
poll = CLG_GetNtpMinPoll();
poll = MAX(poll, message->poll);
/* Respond with the same version */
version = info.version;
/* Send a reply */
transmit_packet(my_mode, interleaved, poll, version, kod, NULL,
&message->receive_ts, &message->transmit_ts,

View File

@@ -2,7 +2,7 @@
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
* 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) 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
* 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;
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
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) 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
* 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;
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 */
if (snprintf(label, sizeof (label), "%s (%s)",
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 */
if (!NKSN_StartSession(inst->session, sock_fd, label, client_credentials, CLIENT_TIMEOUT)) {
SCK_CloseSocket(sock_fd);

View File

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

View File

@@ -3,7 +3,7 @@
**********************************************************************
* 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
* 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 poll;
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;
unsigned long latest_meas_ago; /* seconds */

View File

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

View File

@@ -39,6 +39,7 @@
struct SIV_Instance_Record {
struct siv_cmac_aes128_ctx siv;
int key_set;
};
/* ================================================== */
@@ -52,6 +53,7 @@ SIV_CreateInstance(SIV_Algorithm algorithm)
return NULL;
instance = MallocNew(struct SIV_Instance_Record);
instance->key_set = 0;
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);
instance->key_set = 1;
return 1;
}
@@ -108,6 +112,9 @@ SIV_Encrypt(SIV_Instance instance,
const void *plaintext, int plaintext_length,
unsigned char *ciphertext, int ciphertext_length)
{
if (!instance->key_set)
return 0;
if (nonce_length < SIV_MIN_NONCE_SIZE || assoc_length < 0 ||
plaintext_length < 0 || plaintext_length > 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,
void *plaintext, int plaintext_length)
{
if (!instance->key_set)
return 0;
if (nonce_length < SIV_MIN_NONCE_SIZE || assoc_length < 0 ||
plaintext_length < 0 || plaintext_length > ciphertext_length ||
plaintext_length + SIV_DIGEST_SIZE != ciphertext_length)

View File

@@ -4,7 +4,7 @@
**********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003
* 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
* 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) 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
* 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:
report->state = RPT_JITTERY;
break;
case SRC_UNTRUSTED:
case SRC_WAITS_SOURCES:
case SRC_NONPREFERRED:
case SRC_WAITS_UPDATE:
case SRC_DISTANT:
case SRC_OUTLIER:
report->state = RPT_OUTLIER;
report->state = RPT_SELECTABLE;
break;
case SRC_UNSELECTED:
report->state = RPT_CANDIDATE;
report->state = RPT_UNSELECTED;
break;
case SRC_SELECTED:
report->state = RPT_SYNC;
report->state = RPT_SELECTED;
break;
default:
report->state = RPT_UNREACH;
report->state = RPT_NONSELECTABLE;
break;
}

View File

@@ -49,7 +49,7 @@
#include "sched.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 */

View File

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

View File

@@ -4,7 +4,7 @@
**********************************************************************
* Copyright (C) Richard P. Curnow 1997-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
* 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
read_frequency(void)
{
@@ -77,7 +96,7 @@ read_frequency(void)
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);
return txc.freq / -FREQ_SCALE;
return convert_timex_frequency(&txc);
}
/* ================================================== */

View File

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

View File

@@ -52,15 +52,15 @@ test_freqrange(void)
printf("freq range:\n");
for (i = 0; i <= 1000; i += 50) {
for (i = -1000; i <= 1000; i += 50) {
t.modes = MOD_FREQUENCY;
t.freq = i << 16;
t.freq = i * (1 << 16);
printf("%4d ppm => ", i);
if (try_ntpadjtime(&t) < 0)
continue;
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 <conf.h>
#include <keys.h>
#include <ntp_ext.h>
#include <ntp_io.h>
#include <sched.h>
#include <local.h>
@@ -138,7 +139,7 @@ send_response(int interleaved, int authenticated, int allow_update, int valid_ts
{
NTP_Packet *req, *res;
uint32_t key_id = 0;
int auth_len = 0;
int i, auth_len = 0, ef_len, efs;
req = &req_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) {
key_id = ntohl(*(uint32_t *)req->extensions);
if (key_id == 0)
key_id = get_random_key_id();
auth_len = KEY_GetAuthLength(key_id);
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);
if (KEY_GenerateAuth(key_id, (unsigned char *)res, NTP_HEADER_LENGTH,
res->extensions + 4, auth_len) != auth_len)
if (KEY_GenerateAuth(key_id, res, res_length,
(unsigned char *)res + res_length + 4, auth_len) != auth_len)
assert(0);
res_length = NTP_HEADER_LENGTH + 4 + auth_len;
} else {
res_length = NTP_HEADER_LENGTH;
res_length += 4 + auth_len;
}
if (!valid_auth && authenticated) {
assert(auth_len);
switch (random() % 4) {
switch (random() % 5) {
case 0:
key_id++;
break;
case 1:
key_id ^= 1;
if (KEY_GenerateAuth(key_id, (unsigned char *)res, NTP_HEADER_LENGTH,
res->extensions + 4, auth_len) != auth_len)
if (KEY_GenerateAuth(key_id, res, res_length - auth_len - 4,
(unsigned char *)res + res_length - auth_len, auth_len) != auth_len)
assert(0);
break;
case 2:
res->extensions[4 + random() % auth_len]++;
((unsigned char *)res)[res_length - auth_len + random() % auth_len]++;
break;
case 3:
res_length = NTP_HEADER_LENGTH + 4 * (random() % ((4 + auth_len) / 4));
if (NTP_LVM_TO_VERSION(res->lvm) == 4 &&
res_length == NTP_HEADER_LENGTH + NTP_MAX_V4_MAC_LENGTH)
res_length -= 4;
res_length -= 4 + auth_len;
auth_len = 4 * (random() % (auth_len / 4));
res_length += 4 + auth_len;
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;
default:
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

View File

@@ -149,6 +149,17 @@ test_unit(void)
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++) {
r = SIV_SetKey(siv, tests[i].key, j);
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) Miroslav Lichvar 2009, 2012-2018
* Copyright (C) Miroslav Lichvar 2009, 2012-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