Compare commits
No commits in common. "master" and "4.6-pre1" have entirely different histories.
41 changed files with 117 additions and 650 deletions
15
NEWS
15
NEWS
|
@ -1,17 +1,3 @@
|
|||
New in version 4.6.1
|
||||
====================
|
||||
|
||||
Enhancements
|
||||
------------
|
||||
* Add ntsaeads directive to enable only selected AEAD algorithms for NTS
|
||||
|
||||
Workarounds
|
||||
-----------
|
||||
* Negotiate use of compliant NTS keys with AES-128-GCM-SIV AEAD algorithm
|
||||
(by default the keys are generated differently than in RFC 8915 for
|
||||
compatibility with chrony server and client versions 4.4, 4.5, and 4.6)
|
||||
* Switch to compliant NTS keys if first response from server is NTS NAK
|
||||
|
||||
New in version 4.6
|
||||
==================
|
||||
|
||||
|
@ -22,7 +8,6 @@ Enhancements
|
|||
* Add kod option to ratelimit directive for server KoD RATE support
|
||||
* Add leapseclist directive to read NIST/IERS leap-seconds.list file
|
||||
* Add ptpdomain directive to set PTP domain for NTP over PTP
|
||||
* Allow disabling pidfile
|
||||
* Improve copy server option to accept unsynchronised status instantly
|
||||
* Log one selection failure on start
|
||||
* Add offset command to modify source offset correction
|
||||
|
|
1
README
1
README
|
@ -75,7 +75,6 @@ Lonnie Abelbeck <lonnie@abelbeck.com>
|
|||
Benny Lyne Amorsen <benny@amorsen.dk>
|
||||
Andrew Bishop <amb@gedanken.demon.co.uk>
|
||||
Vincent Blut <vincent.debian@free.fr>
|
||||
Luca Boccassi <bluca@debian.org>
|
||||
Stephan I. Boettcher <stephan@nevis1.columbia.edu>
|
||||
David Bohman <debohman@gmail.com>
|
||||
Goswin Brederlow <brederlo@informatik.uni-tuebingen.de>
|
||||
|
|
4
client.c
4
client.c
|
@ -4,7 +4,7 @@
|
|||
**********************************************************************
|
||||
* Copyright (C) Richard P. Curnow 1997-2003
|
||||
* Copyright (C) Lonnie Abelbeck 2016, 2018
|
||||
* Copyright (C) Miroslav Lichvar 2009-2024
|
||||
* Copyright (C) Miroslav Lichvar 2009-2023
|
||||
*
|
||||
* 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
|
||||
|
@ -3440,7 +3440,7 @@ static void
|
|||
display_gpl(void)
|
||||
{
|
||||
printf("chrony version %s\n"
|
||||
"Copyright (C) 1997-2003, 2007, 2009-2024 Richard P. Curnow and others\n"
|
||||
"Copyright (C) 1997-2003, 2007, 2009-2023 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",
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
**********************************************************************
|
||||
* Copyright (C) Richard P. Curnow 1997-2003
|
||||
* Copyright (C) Miroslav Lichvar 2009, 2015-2017, 2021, 2024
|
||||
* Copyright (C) Miroslav Lichvar 2009, 2015-2017, 2021
|
||||
*
|
||||
* 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
|
||||
|
|
2
cmdmon.c
2
cmdmon.c
|
@ -3,7 +3,7 @@
|
|||
|
||||
**********************************************************************
|
||||
* Copyright (C) Richard P. Curnow 1997-2003
|
||||
* Copyright (C) Miroslav Lichvar 2009-2016, 2018-2024
|
||||
* Copyright (C) Miroslav Lichvar 2009-2016, 2018-2023
|
||||
*
|
||||
* 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
|
||||
|
|
104
conf.c
104
conf.c
|
@ -3,7 +3,7 @@
|
|||
|
||||
**********************************************************************
|
||||
* Copyright (C) Richard P. Curnow 1997-2003
|
||||
* Copyright (C) Miroslav Lichvar 2009-2017, 2020, 2024
|
||||
* 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
|
||||
|
@ -57,7 +57,6 @@ static int parse_string(char *line, char **result);
|
|||
static int parse_int(char *line, int *result);
|
||||
static int parse_double(char *line, double *result);
|
||||
static int parse_null(char *line);
|
||||
static int parse_ints(char *line, ARR_Instance array);
|
||||
|
||||
static void parse_allow_deny(char *line, ARR_Instance restrictions, int allow);
|
||||
static void parse_authselectmode(char *);
|
||||
|
@ -79,7 +78,6 @@ static void parse_makestep(char *);
|
|||
static void parse_maxchange(char *);
|
||||
static void parse_ntsserver(char *, ARR_Instance files);
|
||||
static void parse_ntstrustedcerts(char *);
|
||||
static void parse_pidfile(char *line);
|
||||
static void parse_ratelimit(char *line, int *enabled, int *interval,
|
||||
int *burst, int *leak, int *kod);
|
||||
static void parse_refclock(char *);
|
||||
|
@ -262,10 +260,7 @@ static char *user;
|
|||
/* Address refresh interval */
|
||||
static int refresh = 1209600; /* 2 weeks */
|
||||
|
||||
#define DEFAULT_NTS_AEADS "30 15"
|
||||
|
||||
/* NTS server and client configuration */
|
||||
static ARR_Instance nts_aeads; /* array of int */
|
||||
static char *nts_dump_dir = NULL;
|
||||
static char *nts_ntp_server = NULL;
|
||||
static ARR_Instance nts_server_cert_files; /* array of (char *) */
|
||||
|
@ -299,15 +294,15 @@ typedef struct {
|
|||
NTP_Source_Type type;
|
||||
int pool;
|
||||
CPS_NTP_Source params;
|
||||
NSR_Status status;
|
||||
uint32_t conf_id;
|
||||
} NTP_Source;
|
||||
|
||||
/* Array of NTP_Source */
|
||||
static ARR_Instance ntp_sources;
|
||||
/* Array of (char *) */
|
||||
static ARR_Instance ntp_source_dirs;
|
||||
/* Flag indicating ntp_sources is used for sourcedirs after config load */
|
||||
/* Array of uint32_t corresponding to ntp_sources (for sourcedirs reload) */
|
||||
static ARR_Instance ntp_source_ids;
|
||||
/* Flag indicating ntp_sources and ntp_source_ids are used for sourcedirs */
|
||||
static int conf_ntp_sources_added = 0;
|
||||
|
||||
/* Array of RefclockParameters */
|
||||
|
@ -401,8 +396,6 @@ check_number_of_args(char *line, int num)
|
|||
void
|
||||
CNF_Initialise(int r, int client_only)
|
||||
{
|
||||
char buf[10];
|
||||
|
||||
restarted = r;
|
||||
|
||||
hwts_interfaces = ARR_CreateInstance(sizeof (CNF_HwTsInterface));
|
||||
|
@ -410,15 +403,13 @@ CNF_Initialise(int r, int client_only)
|
|||
init_sources = ARR_CreateInstance(sizeof (IPAddr));
|
||||
ntp_sources = ARR_CreateInstance(sizeof (NTP_Source));
|
||||
ntp_source_dirs = ARR_CreateInstance(sizeof (char *));
|
||||
ntp_source_ids = ARR_CreateInstance(sizeof (uint32_t));
|
||||
refclock_sources = ARR_CreateInstance(sizeof (RefclockParameters));
|
||||
broadcasts = ARR_CreateInstance(sizeof (NTP_Broadcast_Destination));
|
||||
|
||||
ntp_restrictions = ARR_CreateInstance(sizeof (AllowDeny));
|
||||
cmd_restrictions = ARR_CreateInstance(sizeof (AllowDeny));
|
||||
|
||||
nts_aeads = ARR_CreateInstance(sizeof (int));
|
||||
snprintf(buf, sizeof (buf), DEFAULT_NTS_AEADS);
|
||||
parse_ints(buf, nts_aeads);
|
||||
nts_server_cert_files = ARR_CreateInstance(sizeof (char *));
|
||||
nts_server_key_files = ARR_CreateInstance(sizeof (char *));
|
||||
nts_trusted_certs_paths = ARR_CreateInstance(sizeof (char *));
|
||||
|
@ -472,13 +463,13 @@ CNF_Finalise(void)
|
|||
ARR_DestroyInstance(init_sources);
|
||||
ARR_DestroyInstance(ntp_sources);
|
||||
ARR_DestroyInstance(ntp_source_dirs);
|
||||
ARR_DestroyInstance(ntp_source_ids);
|
||||
ARR_DestroyInstance(refclock_sources);
|
||||
ARR_DestroyInstance(broadcasts);
|
||||
|
||||
ARR_DestroyInstance(ntp_restrictions);
|
||||
ARR_DestroyInstance(cmd_restrictions);
|
||||
|
||||
ARR_DestroyInstance(nts_aeads);
|
||||
ARR_DestroyInstance(nts_server_cert_files);
|
||||
ARR_DestroyInstance(nts_server_key_files);
|
||||
ARR_DestroyInstance(nts_trusted_certs_paths);
|
||||
|
@ -689,8 +680,6 @@ CNF_ParseLine(const char *filename, int number, char *line)
|
|||
no_system_cert = parse_null(p);
|
||||
} else if (!strcasecmp(command, "ntpsigndsocket")) {
|
||||
parse_string(p, &ntp_signd_socket);
|
||||
} else if (!strcasecmp(command, "ntsaeads")) {
|
||||
parse_ints(p, nts_aeads);
|
||||
} else if (!strcasecmp(command, "ntsratelimit")) {
|
||||
parse_ratelimit(p, &nts_ratelimit_enabled, &nts_ratelimit_interval,
|
||||
&nts_ratelimit_burst, &nts_ratelimit_leak, NULL);
|
||||
|
@ -716,7 +705,7 @@ CNF_ParseLine(const char *filename, int number, char *line)
|
|||
} else if (!strcasecmp(command, "peer")) {
|
||||
parse_source(p, command, 1);
|
||||
} else if (!strcasecmp(command, "pidfile")) {
|
||||
parse_pidfile(p);
|
||||
parse_string(p, &pidfile);
|
||||
} else if (!strcasecmp(command, "pool")) {
|
||||
parse_source(p, command, 1);
|
||||
} else if (!strcasecmp(command, "port")) {
|
||||
|
@ -818,25 +807,6 @@ parse_null(char *line)
|
|||
|
||||
/* ================================================== */
|
||||
|
||||
static int
|
||||
parse_ints(char *line, ARR_Instance array)
|
||||
{
|
||||
char *s;
|
||||
int v;
|
||||
|
||||
ARR_SetSize(array, 0);
|
||||
|
||||
while (*line) {
|
||||
s = line;
|
||||
line = CPS_SplitWord(line);
|
||||
parse_int(s, &v);
|
||||
ARR_AppendElement(array, &v);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
static void
|
||||
parse_source(char *line, char *type, int fatal)
|
||||
{
|
||||
|
@ -867,9 +837,6 @@ parse_source(char *line, char *type, int fatal)
|
|||
}
|
||||
|
||||
source.params.name = Strdup(source.params.name);
|
||||
source.status = NSR_NoSuchSource;
|
||||
source.conf_id = 0;
|
||||
|
||||
ARR_AppendElement(ntp_sources, &source);
|
||||
}
|
||||
|
||||
|
@ -1561,20 +1528,6 @@ parse_hwtimestamp(char *line)
|
|||
|
||||
/* ================================================== */
|
||||
|
||||
static void
|
||||
parse_pidfile(char *line)
|
||||
{
|
||||
parse_string(line, &pidfile);
|
||||
|
||||
/* / disables the PID file handling */
|
||||
if (strcmp(pidfile, "/") == 0) {
|
||||
Free(pidfile);
|
||||
pidfile = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
static const char *
|
||||
get_basename(const char *path)
|
||||
{
|
||||
|
@ -1741,6 +1694,7 @@ reload_source_dirs(void)
|
|||
{
|
||||
NTP_Source *prev_sources, *new_sources, *source;
|
||||
unsigned int i, j, prev_size, new_size, unresolved;
|
||||
uint32_t *prev_ids, *new_ids;
|
||||
char buf[MAX_LINE_LENGTH];
|
||||
NSR_Status s;
|
||||
int d, pass;
|
||||
|
@ -1749,9 +1703,13 @@ reload_source_dirs(void)
|
|||
if (!conf_ntp_sources_added)
|
||||
return;
|
||||
|
||||
prev_size = ARR_GetSize(ntp_sources);
|
||||
prev_size = ARR_GetSize(ntp_source_ids);
|
||||
if (ARR_GetSize(ntp_sources) != prev_size)
|
||||
assert(0);
|
||||
|
||||
/* Save the current sources */
|
||||
/* Save the current sources and their configuration IDs */
|
||||
prev_ids = MallocArray(uint32_t, prev_size);
|
||||
memcpy(prev_ids, ARR_GetElements(ntp_source_ids), prev_size * sizeof (prev_ids[0]));
|
||||
prev_sources = MallocArray(NTP_Source, prev_size);
|
||||
memcpy(prev_sources, ARR_GetElements(ntp_sources), prev_size * sizeof (prev_sources[0]));
|
||||
|
||||
|
@ -1769,6 +1727,8 @@ reload_source_dirs(void)
|
|||
|
||||
new_size = ARR_GetSize(ntp_sources);
|
||||
new_sources = ARR_GetElements(ntp_sources);
|
||||
ARR_SetSize(ntp_source_ids, new_size);
|
||||
new_ids = ARR_GetElements(ntp_source_ids);
|
||||
unresolved = 0;
|
||||
|
||||
LOG_SetContext(LOGC_SourceFile);
|
||||
|
@ -1783,31 +1743,31 @@ reload_source_dirs(void)
|
|||
d = i < prev_size ? -1 : 1;
|
||||
|
||||
/* Remove missing sources before adding others to avoid conflicts */
|
||||
if (pass == 0 && d < 0 && prev_sources[i].status == NSR_Success) {
|
||||
NSR_RemoveSourcesById(prev_sources[i].conf_id);
|
||||
if (pass == 0 && d < 0 && prev_sources[i].params.name[0] != '\0') {
|
||||
NSR_RemoveSourcesById(prev_ids[i]);
|
||||
}
|
||||
|
||||
/* Add new sources and sources that could not be added before */
|
||||
if (pass == 1 && (d > 0 || (d == 0 && prev_sources[i].status != NSR_Success))) {
|
||||
/* Add new sources */
|
||||
if (pass == 1 && d > 0) {
|
||||
source = &new_sources[j];
|
||||
s = NSR_AddSourceByName(source->params.name, source->params.family, source->params.port,
|
||||
source->pool, source->type, &source->params.params,
|
||||
&source->conf_id);
|
||||
source->status = s;
|
||||
&new_ids[j]);
|
||||
|
||||
if (s == NSR_UnresolvedName) {
|
||||
unresolved++;
|
||||
} else if (s != NSR_Success && (d > 0 || s != prev_sources[i].status)) {
|
||||
} else if (s != NSR_Success) {
|
||||
LOG(LOGS_ERR, "Could not add source %s : %s",
|
||||
source->params.name, NSR_StatusToString(s));
|
||||
|
||||
/* Mark the source as not present */
|
||||
source->params.name[0] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
/* Keep unchanged sources */
|
||||
if (pass == 1 && d == 0) {
|
||||
new_sources[j].status = prev_sources[i].status;
|
||||
new_sources[j].conf_id = prev_sources[i].conf_id;
|
||||
}
|
||||
if (pass == 1 && d == 0)
|
||||
new_ids[j] = prev_ids[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1816,6 +1776,7 @@ reload_source_dirs(void)
|
|||
for (i = 0; i < prev_size; i++)
|
||||
Free(prev_sources[i].params.name);
|
||||
Free(prev_sources);
|
||||
Free(prev_ids);
|
||||
|
||||
if (unresolved > 0)
|
||||
NSR_ResolveSources();
|
||||
|
@ -1914,6 +1875,7 @@ CNF_AddSources(void)
|
|||
|
||||
/* The arrays will be used for sourcedir (re)loading */
|
||||
ARR_SetSize(ntp_sources, 0);
|
||||
ARR_SetSize(ntp_source_ids, 0);
|
||||
conf_ntp_sources_added = 1;
|
||||
|
||||
reload_source_dirs();
|
||||
|
@ -2630,14 +2592,6 @@ CNF_GetRefresh(void)
|
|||
|
||||
/* ================================================== */
|
||||
|
||||
ARR_Instance
|
||||
CNF_GetNtsAeads(void)
|
||||
{
|
||||
return nts_aeads;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
char *
|
||||
CNF_GetNtsDumpDir(void)
|
||||
{
|
||||
|
|
2
conf.h
2
conf.h
|
@ -29,7 +29,6 @@
|
|||
#define GOT_CONF_H
|
||||
|
||||
#include "addressing.h"
|
||||
#include "array.h"
|
||||
#include "reference.h"
|
||||
#include "sources.h"
|
||||
|
||||
|
@ -164,7 +163,6 @@ extern int CNF_GetPtpDomain(void);
|
|||
|
||||
extern int CNF_GetRefresh(void);
|
||||
|
||||
extern ARR_Instance CNF_GetNtsAeads(void);
|
||||
extern char *CNF_GetNtsDumpDir(void);
|
||||
extern char *CNF_GetNtsNtpServer(void);
|
||||
extern int CNF_GetNtsServerCertAndKeyFiles(const char ***certs, const char ***keys);
|
||||
|
|
|
@ -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-2024
|
||||
// Copyright (C) Miroslav Lichvar 2009-2023
|
||||
//
|
||||
// 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
|
||||
|
@ -126,15 +126,6 @@ mechanism. Unlike with the *key* option, the server and client do not need to
|
|||
share a key in a key file. NTS has a Key Establishment (NTS-KE) protocol using
|
||||
the Transport Layer Security (TLS) protocol to get the keys and cookies
|
||||
required by NTS for authentication of NTP packets.
|
||||
+
|
||||
With this option, the hostname specified in the server or pool directive is the
|
||||
NTS-KE server or pool of NTS-KE servers respectively. The NTP server usually
|
||||
runs on the same host, but it can be separated from the NTS-KE server (the
|
||||
hostname or address of the NTP server is provided to the client by the NTS-KE
|
||||
server).
|
||||
+
|
||||
The NTS-KE server can be specified by IP address if it is included in the
|
||||
server's certificate as a Subject Alternative Name (SAN).
|
||||
*certset* _ID_:::
|
||||
This option specifies which set of trusted certificates should be used to verify
|
||||
the server's certificate when the *nts* option is enabled. Sets of certificates
|
||||
|
@ -833,34 +824,6 @@ changes in the frequency and offset of the clock. The offsets in the
|
|||
<<chronyc.adoc#sourcestats,*sourcestats*>> reports (and the _tracking.log_ and
|
||||
_statistics.log_ files) may be smaller than the actual offsets.
|
||||
|
||||
[[ntsaeads1]]*ntsaeads* _ID_...::
|
||||
This directive specifies a list of IDs of Authenticated Encryption with
|
||||
Associated Data (AEAD) algorithms enabled for NTS authentication of NTP
|
||||
messages. The algorithms are specified in decreasing order of priority.
|
||||
Algorithms that are not supported by the installed version of the crypto
|
||||
library (Nettle, GnuTLS) are ignored.
|
||||
+
|
||||
The following IDs are supported:
|
||||
+
|
||||
* 15: AES-SIV-CMAC-256
|
||||
* 30: AES-128-GCM-SIV
|
||||
{blank}::
|
||||
+
|
||||
The default list of IDs is _30 15_. AES-128-GCM-SIV is preferred over
|
||||
AES-SIV-CMAC-256 for shorter keys, which makes NTS cookies shorter and improves
|
||||
reliability of NTS in networks that block or limit rate of longer NTP messages.
|
||||
+
|
||||
The ID of the used algorithm is reported for each server by the
|
||||
<<chronyc.adoc#authdata,*authdata*>> command.
|
||||
+
|
||||
An example of the directive is:
|
||||
+
|
||||
----
|
||||
ntsaeads 15
|
||||
----
|
||||
+
|
||||
This list is used also by the <<ntsaeads2,NTS server>>.
|
||||
|
||||
[[ntsdumpdir1]]*ntsdumpdir* _directory_::
|
||||
This directive specifies a directory for the client to save NTS cookies it
|
||||
received from the server in order to avoid making an NTS-KE request when
|
||||
|
@ -1807,43 +1770,6 @@ per process that the NTS server will accept. The default value is 100. The
|
|||
maximum practical value is half of the system *FD_SETSIZE* constant (usually
|
||||
1024).
|
||||
|
||||
[[ntsaeads2]]*ntsaeads* _ID_...::
|
||||
This directive specifies a list of IDs of Authenticated Encryption with
|
||||
Associated Data (AEAD) algorithms enabled for NTS authentication of NTP
|
||||
messages. *chronyd* as a server uses the first enabled algorithm from the list
|
||||
provided by the client. Algorithms that are not supported by the installed
|
||||
version of the crypto library (Nettle, GnuTLS) are ignored.
|
||||
+
|
||||
The following IDs are supported:
|
||||
+
|
||||
* 15: AES-SIV-CMAC-256
|
||||
* 30: AES-128-GCM-SIV
|
||||
{blank}::
|
||||
+
|
||||
The default list of IDs is _30 15_. AES-128-GCM-SIV is preferred over
|
||||
AES-SIV-CMAC-256 for shorter keys, which makes NTS cookies shorter and improves
|
||||
reliability of NTS in networks that block or limit rate of longer NTP messages.
|
||||
+
|
||||
An example of the directive is:
|
||||
+
|
||||
----
|
||||
ntsaeads 15
|
||||
----
|
||||
+
|
||||
This list is used also by the <<ntsaeads1,NTS client>>.
|
||||
+
|
||||
Note the the NTS specification (RFC 8915) requires servers to support
|
||||
AES-SIV-CMAC-256, i.e. 15 should be always included in the specified list.
|
||||
+
|
||||
The AES-128-GCM-SIV keys used by *chronyd* do not comply to RFC 8915 for
|
||||
compatibility with older *chrony* clients unless the use of compliant keys is
|
||||
negotiated with an
|
||||
https://chrony-project.org/doc/spec/nts-compliant-128gcm.html[NTS-KE record].
|
||||
Support for this record was added in version 4.6.1. As a client, *chronyd* can
|
||||
interoperate with a server that uses compliant keys, but does not support the
|
||||
negotiation, if it responds to incorrectly authenticated requests with an NTS
|
||||
NAK.
|
||||
|
||||
[[ntsdumpdir2]]*ntsdumpdir* _directory_::
|
||||
This directive specifies a directory where *chronyd* operating as an NTS server
|
||||
can save the keys which encrypt NTS cookies provided to clients. The keys are
|
||||
|
@ -2821,11 +2747,7 @@ source is specified in the configuration file with a key shorter than 80 bits.
|
|||
+
|
||||
The recommended key types are AES ciphers and SHA3 hash functions. MD5 should
|
||||
be avoided unless no other type is supported on the server and client, or
|
||||
peers. A major weakness of MD5 for the NTP MAC is a length extension attack,
|
||||
where a man-in-the-middle attacker can add arbitrary extension fields to the
|
||||
NTP message and update the MAC to pass the verification of the extended
|
||||
message. The *extfield* option (enabling processing of the specified extension
|
||||
field) should not be used for NTP sources authenticated with an MD5 key.
|
||||
peers.
|
||||
+
|
||||
The <<chronyc.adoc#keygen,*keygen*>> command of *chronyc* can be used to
|
||||
generate random keys for the key file. By default, it generates 160-bit MD5 or
|
||||
|
@ -2850,8 +2772,6 @@ e.g.:
|
|||
----
|
||||
pidfile /run/chronyd.pid
|
||||
----
|
||||
+
|
||||
Setting this directive to _/_ disables writing and checking of the PID file.
|
||||
|
||||
[[ptpport]]*ptpport* _port_::
|
||||
The *ptpport* directive enables *chronyd* to send and receive NTP messages
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
//
|
||||
// Copyright (C) Richard P. Curnow 1997-2003
|
||||
// Copyright (C) Stephen Wadeley 2016
|
||||
// Copyright (C) Miroslav Lichvar 2009-2017, 2019-2024
|
||||
// Copyright (C) Miroslav Lichvar 2009-2017, 2019-2023
|
||||
//
|
||||
// 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
|
||||
|
@ -364,12 +364,9 @@ a measurement is being made every 64 seconds. *chronyd* automatically varies
|
|||
the polling rate in response to prevailing conditions.
|
||||
*Reach*:::
|
||||
This shows the source's reachability register printed as an octal number. The
|
||||
register has 8 bits. It is shifted to left by one bit with each poll and it is
|
||||
updated by 1 when a valid NTP response, or just a sample in case of a reference
|
||||
clock, is received from the source. A value of 377 indicates that a valid
|
||||
response or sample was received for all of the last 8 polls. Note that samples
|
||||
can be dropped if they are not considered good enough for synchronisation, but
|
||||
the reachability register will still have 1s for their polls.
|
||||
register has 8 bits and is updated on every received or missed packet from
|
||||
the source. A value of 377 indicates that a valid reply was received for all
|
||||
from the last eight transmissions.
|
||||
*LastRx*:::
|
||||
This column shows how long ago the last good sample (which is shown in the next
|
||||
column) was received from the source. Measurements that failed some tests are
|
||||
|
|
60
doc/faq.adoc
60
doc/faq.adoc
|
@ -2,7 +2,7 @@
|
|||
//
|
||||
// Copyright (C) Richard P. Curnow 1997-2003
|
||||
// Copyright (C) Luke Valenta 2023
|
||||
// Copyright (C) Miroslav Lichvar 2014-2016, 2020-2024
|
||||
// Copyright (C) Miroslav Lichvar 2014-2016, 2020-2023
|
||||
//
|
||||
// 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
|
||||
|
@ -772,17 +772,6 @@ print all sources, even those that do not have a known address yet, with their
|
|||
names as they were specified in the configuration. This can be useful to verify
|
||||
that the names specified in the configuration are used as expected.
|
||||
|
||||
When DNSSEC is enabled, it will not work until the time is synchronized, as it
|
||||
requires validating a signature timestamp and its expiration date, so if the
|
||||
system time is too far in the future or the past DNSSEC validation will fail and
|
||||
`chronyd` will be unable to resolve the address of the NTP server. In such cases,
|
||||
if hostnames are the only options and bare IP addresses cannot be used, DNSSEC
|
||||
can be disabled for `chronyd` using resolver-specific mechanisms, if available,
|
||||
although of course that means losing the protection afforded by DNSSEC.
|
||||
For example, when using systemd-resolved, the `SYSTEMD_NSS_RESOLVE_VALIDATE=0`
|
||||
environment variable can be set, for example in the `chronyd` systemd unit via
|
||||
`Environment=SYSTEMD_NSS_RESOLVE_VALIDATE=0`.
|
||||
|
||||
=== Is `chronyd` allowed to step the system clock?
|
||||
|
||||
By default, `chronyd` adjusts the clock gradually by slowing it down or
|
||||
|
@ -1166,53 +1155,6 @@ There are several different clocks used by `chronyd`:
|
|||
synchronised by `chronyd`. Its offset is tracked relative to the NTP clock in
|
||||
order to convert the hardware timestamps.
|
||||
|
||||
=== How accurate is my system clock?
|
||||
|
||||
`chronyd` does not know how accurate really is the clock it is synchronizing.
|
||||
Even if the measured offset of the clock is stable to nanoseconds, it could be
|
||||
off by milliseconds due to asymmetric network delay, e.g. caused by asymmetric
|
||||
routing or queuing delays in network switches. NTP provides root delay and root
|
||||
dispersion to enable clients to estimate the maximum error of their clock.
|
||||
|
||||
Root delay measures the sum of round-trip times between all NTP servers on the
|
||||
path from the client to the primary time source (e.g. a GPS receiver). Half of
|
||||
the root delay is the maximum error due to asymmetric delays, assuming one
|
||||
direction (e.g. from the client to the server) has a zero delay and the other
|
||||
direction (from the server to the client) takes all of the measured delay. The
|
||||
root delay also covers timestamping errors if the server implementation and
|
||||
hardware meet the NTP requirement for transmit timestamps to never be late and
|
||||
receive timestamps to never be early.
|
||||
|
||||
If you have additional information about the hardware and network between the
|
||||
client and primary time source, you could modify the root delay to get a better
|
||||
estimate of the maximum error. For example, from the physical distance of the
|
||||
server and signal propagation speed in the cables a minimum symmetric
|
||||
round-trip delay can be calculated and subtracted from the root delay measured
|
||||
by NTP.
|
||||
|
||||
Root dispersion estimates errors due to instability of clocks and NTP
|
||||
measurements. `chronyd` adjusts the rate at which root dispersion grows between
|
||||
updates of the clock according to the stability of its NTP measurements. The
|
||||
minimum rate is set by the the `maxclockerror` directive. By default it is 1
|
||||
ppm (1 microsecond per second).
|
||||
|
||||
The estimated maximum error of the NTP clock is the sum of the root dispersion
|
||||
and half of the root delay. This value is called root distance. The current
|
||||
values of root dispersion and delay are included in the `tracking` report.
|
||||
|
||||
The estimated maximum error of the system clock, which is synchronized to the
|
||||
NTP clock, is the sum of the root distance and remaining correction of the
|
||||
system clock provided as `System time` in the `tracking` report. A maximum
|
||||
value of this estimate between updates of the clock is included in the
|
||||
`tracking` log.
|
||||
|
||||
Note that the resolution of the root delay and root dispersion fields in NTP
|
||||
messages is about 15 microseconds and `chronyd` rounds the values up, i.e. the
|
||||
minimum root distance an NTP client can normally observe is about 22.5
|
||||
microseconds. An NTP extension field containing root delay and dispersion in a
|
||||
better resolution of about 4 nanoseconds can be enabled by the `extfield F323`
|
||||
option.
|
||||
|
||||
== Operating systems
|
||||
|
||||
=== Does `chrony` support Windows?
|
||||
|
|
2
leapdb.h
2
leapdb.h
|
@ -2,7 +2,7 @@
|
|||
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
||||
|
||||
**********************************************************************
|
||||
* Copyright (C) Patrick Oppenlander 2024
|
||||
* Copyright (C) Patrick Oppenlander 2023
|
||||
*
|
||||
* 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
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
**********************************************************************
|
||||
* Copyright (C) Richard P. Curnow 1997-2003
|
||||
* Copyright (C) Miroslav Lichvar 2009-2024
|
||||
* Copyright (C) Miroslav Lichvar 2009-2023
|
||||
*
|
||||
* 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
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
**********************************************************************
|
||||
* Copyright (C) Richard P. Curnow 1997-2003
|
||||
* Copyright (C) Miroslav Lichvar 2011-2012, 2014, 2016, 2020-2024
|
||||
* Copyright (C) Miroslav Lichvar 2011-2012, 2014, 2016, 2020-2023
|
||||
*
|
||||
* 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
|
||||
|
@ -219,14 +219,8 @@ NSR_Finalise(void)
|
|||
ARR_DestroyInstance(pools);
|
||||
|
||||
SCH_RemoveTimeout(resolving_id);
|
||||
|
||||
/* Leave the unresolved sources allocated if the async resolver is running
|
||||
to avoid reading the name from freed memory. The handler will not be
|
||||
called as the scheduler should no longer be running at this point. */
|
||||
if (!resolving_source) {
|
||||
while (unresolved_sources)
|
||||
remove_unresolved_source(unresolved_sources);
|
||||
}
|
||||
while (unresolved_sources)
|
||||
remove_unresolved_source(unresolved_sources);
|
||||
|
||||
initialised = 0;
|
||||
}
|
||||
|
|
3
nts_ke.h
3
nts_ke.h
|
@ -40,7 +40,6 @@
|
|||
#define NKE_RECORD_COOKIE 5
|
||||
#define NKE_RECORD_NTPV4_SERVER_NEGOTIATION 6
|
||||
#define NKE_RECORD_NTPV4_PORT_NEGOTIATION 7
|
||||
#define NKE_RECORD_COMPLIANT_128GCM_EXPORT 1024
|
||||
|
||||
#define NKE_NEXT_PROTOCOL_NTPV4 0
|
||||
|
||||
|
@ -50,6 +49,8 @@
|
|||
|
||||
#define NKE_ALPN_NAME "ntske/1"
|
||||
#define NKE_EXPORTER_LABEL "EXPORTER-network-time-security"
|
||||
#define NKE_EXPORTER_CONTEXT_C2S "\x0\x0\x0\xf\x0"
|
||||
#define NKE_EXPORTER_CONTEXT_S2C "\x0\x0\x0\xf\x1"
|
||||
|
||||
#define NKE_MAX_MESSAGE_LENGTH 16384
|
||||
#define NKE_MAX_RECORD_BODY_LENGTH 256
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
||||
|
||||
**********************************************************************
|
||||
* Copyright (C) Miroslav Lichvar 2020-2021, 2024
|
||||
* Copyright (C) Miroslav Lichvar 2020-2021
|
||||
*
|
||||
* 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
|
||||
|
@ -50,9 +50,7 @@ struct NKC_Instance_Record {
|
|||
int got_response;
|
||||
int resolving_name;
|
||||
|
||||
int compliant_128gcm;
|
||||
NKE_Context context;
|
||||
NKE_Context alt_context;
|
||||
NKE_Cookie cookies[NKE_MAX_COOKIES];
|
||||
int num_cookies;
|
||||
char server_name[NKE_MAX_RECORD_BODY_LENGTH + 2];
|
||||
|
@ -100,14 +98,12 @@ name_resolve_handler(DNS_Status status, int n_addrs, IPAddr *ip_addrs, void *arg
|
|||
|
||||
/* ================================================== */
|
||||
|
||||
#define MAX_AEAD_ALGORITHMS 4
|
||||
|
||||
static int
|
||||
prepare_request(NKC_Instance inst)
|
||||
{
|
||||
NKSN_Instance session = inst->session;
|
||||
uint16_t data[MAX_AEAD_ALGORITHMS];
|
||||
int i, aead_algorithm, length;
|
||||
uint16_t data[2];
|
||||
int length;
|
||||
|
||||
NKSN_BeginMessage(session);
|
||||
|
||||
|
@ -115,24 +111,15 @@ prepare_request(NKC_Instance inst)
|
|||
if (!NKSN_AddRecord(session, 1, NKE_RECORD_NEXT_PROTOCOL, data, sizeof (data[0])))
|
||||
return 0;
|
||||
|
||||
for (i = length = 0; i < ARR_GetSize(CNF_GetNtsAeads()) && length < MAX_AEAD_ALGORITHMS;
|
||||
i++) {
|
||||
aead_algorithm = *(int *)ARR_GetElement(CNF_GetNtsAeads(), i);
|
||||
if (SIV_GetKeyLength(aead_algorithm) > 0)
|
||||
data[length++] = htons(aead_algorithm);
|
||||
}
|
||||
length = 0;
|
||||
if (SIV_GetKeyLength(AEAD_AES_128_GCM_SIV) > 0)
|
||||
data[length++] = htons(AEAD_AES_128_GCM_SIV);
|
||||
if (SIV_GetKeyLength(AEAD_AES_SIV_CMAC_256) > 0)
|
||||
data[length++] = htons(AEAD_AES_SIV_CMAC_256);
|
||||
if (!NKSN_AddRecord(session, 1, NKE_RECORD_AEAD_ALGORITHM, data,
|
||||
length * sizeof (data[0])))
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < length; i++) {
|
||||
if (data[i] == htons(AEAD_AES_128_GCM_SIV)) {
|
||||
if (!NKSN_AddRecord(session, 0, NKE_RECORD_COMPLIANT_128GCM_EXPORT, NULL, 0))
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!NKSN_EndMessage(session))
|
||||
return 0;
|
||||
|
||||
|
@ -152,8 +139,6 @@ process_response(NKC_Instance inst)
|
|||
assert(sizeof (data) % sizeof (uint16_t) == 0);
|
||||
assert(sizeof (uint16_t) == 2);
|
||||
|
||||
inst->compliant_128gcm = 0;
|
||||
inst->alt_context.algorithm = AEAD_SIV_INVALID;
|
||||
inst->num_cookies = 0;
|
||||
inst->ntp_address.ip_addr.family = IPADDR_UNSPEC;
|
||||
inst->ntp_address.port = 0;
|
||||
|
@ -180,31 +165,15 @@ process_response(NKC_Instance inst)
|
|||
next_protocol = NKE_NEXT_PROTOCOL_NTPV4;
|
||||
break;
|
||||
case NKE_RECORD_AEAD_ALGORITHM:
|
||||
if (length != 2) {
|
||||
DEBUG_LOG("Unexpected AEAD algorithm");
|
||||
if (length != 2 || (ntohs(data[0]) != AEAD_AES_SIV_CMAC_256 &&
|
||||
ntohs(data[0]) != AEAD_AES_128_GCM_SIV) ||
|
||||
SIV_GetKeyLength(ntohs(data[0])) <= 0) {
|
||||
DEBUG_LOG("Unexpected NTS-KE AEAD algorithm");
|
||||
error = 1;
|
||||
break;
|
||||
}
|
||||
for (i = 0; i < ARR_GetSize(CNF_GetNtsAeads()); i++) {
|
||||
if (ntohs(data[0]) == *(int *)ARR_GetElement(CNF_GetNtsAeads(), i) &&
|
||||
SIV_GetKeyLength(ntohs(data[0])) > 0) {
|
||||
aead_algorithm = ntohs(data[0]);
|
||||
inst->context.algorithm = aead_algorithm;
|
||||
}
|
||||
}
|
||||
if (aead_algorithm < 0) {
|
||||
DEBUG_LOG("Unexpected AEAD algorithm");
|
||||
error = 1;
|
||||
}
|
||||
break;
|
||||
case NKE_RECORD_COMPLIANT_128GCM_EXPORT:
|
||||
if (length != 0) {
|
||||
DEBUG_LOG("Non-empty compliant-128gcm record");
|
||||
error = 1;
|
||||
break;
|
||||
}
|
||||
DEBUG_LOG("Compliant AES-128-GCM-SIV export");
|
||||
inst->compliant_128gcm = 1;
|
||||
aead_algorithm = ntohs(data[0]);
|
||||
inst->context.algorithm = aead_algorithm;
|
||||
break;
|
||||
case NKE_RECORD_ERROR:
|
||||
if (length == 2)
|
||||
|
@ -286,7 +255,6 @@ process_response(NKC_Instance inst)
|
|||
static int
|
||||
handle_message(void *arg)
|
||||
{
|
||||
SIV_Algorithm exporter_algorithm;
|
||||
NKC_Instance inst = arg;
|
||||
|
||||
if (!process_response(inst)) {
|
||||
|
@ -294,25 +262,8 @@ handle_message(void *arg)
|
|||
return 0;
|
||||
}
|
||||
|
||||
exporter_algorithm = inst->context.algorithm;
|
||||
|
||||
/* With AES-128-GCM-SIV, set the algorithm ID in the RFC5705 key exporter
|
||||
context incorrectly for compatibility with older chrony servers unless
|
||||
the server confirmed support for the compliant context. Generate both
|
||||
sets of keys in case the server uses the compliant context, but does not
|
||||
support the negotiation record, assuming it will respond with an NTS NAK
|
||||
to a request authenticated with the noncompliant key. */
|
||||
if (exporter_algorithm == AEAD_AES_128_GCM_SIV && !inst->compliant_128gcm) {
|
||||
inst->alt_context.algorithm = inst->context.algorithm;
|
||||
if (!NKSN_GetKeys(inst->session, inst->alt_context.algorithm, exporter_algorithm,
|
||||
NKE_NEXT_PROTOCOL_NTPV4, &inst->alt_context.c2s, &inst->alt_context.s2c))
|
||||
return 0;
|
||||
|
||||
exporter_algorithm = AEAD_AES_SIV_CMAC_256;
|
||||
}
|
||||
|
||||
if (!NKSN_GetKeys(inst->session, inst->context.algorithm, exporter_algorithm,
|
||||
NKE_NEXT_PROTOCOL_NTPV4, &inst->context.c2s, &inst->context.s2c))
|
||||
if (!NKSN_GetKeys(inst->session, inst->context.algorithm,
|
||||
&inst->context.c2s, &inst->context.s2c))
|
||||
return 0;
|
||||
|
||||
if (inst->server_name[0] != '\0') {
|
||||
|
@ -477,7 +428,7 @@ NKC_IsActive(NKC_Instance inst)
|
|||
/* ================================================== */
|
||||
|
||||
int
|
||||
NKC_GetNtsData(NKC_Instance inst, NKE_Context *context, NKE_Context *alt_context,
|
||||
NKC_GetNtsData(NKC_Instance inst, NKE_Context *context,
|
||||
NKE_Cookie *cookies, int *num_cookies, int max_cookies,
|
||||
IPSockAddr *ntp_address)
|
||||
{
|
||||
|
@ -487,7 +438,6 @@ NKC_GetNtsData(NKC_Instance inst, NKE_Context *context, NKE_Context *alt_context
|
|||
return 0;
|
||||
|
||||
*context = inst->context;
|
||||
*alt_context = inst->alt_context;
|
||||
|
||||
for (i = 0; i < inst->num_cookies && i < max_cookies; i++)
|
||||
cookies[i] = inst->cookies[i];
|
||||
|
|
|
@ -46,7 +46,7 @@ extern int NKC_Start(NKC_Instance inst);
|
|||
extern int NKC_IsActive(NKC_Instance inst);
|
||||
|
||||
/* Get the NTS data if the session was successful */
|
||||
extern int NKC_GetNtsData(NKC_Instance inst, NKE_Context *context, NKE_Context *alt_context,
|
||||
extern int NKC_GetNtsData(NKC_Instance inst, NKE_Context *context,
|
||||
NKE_Cookie *cookies, int *num_cookies, int max_cookies,
|
||||
IPSockAddr *ntp_address);
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
||||
|
||||
**********************************************************************
|
||||
* Copyright (C) Miroslav Lichvar 2020, 2022, 2024
|
||||
* Copyright (C) Miroslav Lichvar 2020, 2022
|
||||
*
|
||||
* 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
|
||||
|
@ -337,10 +337,8 @@ helper_signal(int x)
|
|||
/* ================================================== */
|
||||
|
||||
static int
|
||||
prepare_response(NKSN_Instance session, int error, int next_protocol, int aead_algorithm,
|
||||
int compliant_128gcm)
|
||||
prepare_response(NKSN_Instance session, int error, int next_protocol, int aead_algorithm)
|
||||
{
|
||||
SIV_Algorithm exporter_algorithm;
|
||||
NKE_Context context;
|
||||
NKE_Cookie cookie;
|
||||
char *ntp_server;
|
||||
|
@ -373,11 +371,6 @@ prepare_response(NKSN_Instance session, int error, int next_protocol, int aead_a
|
|||
if (!NKSN_AddRecord(session, 1, NKE_RECORD_AEAD_ALGORITHM, &datum, sizeof (datum)))
|
||||
return 0;
|
||||
|
||||
if (aead_algorithm == AEAD_AES_128_GCM_SIV && compliant_128gcm) {
|
||||
if (!NKSN_AddRecord(session, 0, NKE_RECORD_COMPLIANT_128GCM_EXPORT, NULL, 0))
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (CNF_GetNTPPort() != NTP_PORT) {
|
||||
datum = htons(CNF_GetNTPPort());
|
||||
if (!NKSN_AddRecord(session, 1, NKE_RECORD_NTPV4_PORT_NEGOTIATION, &datum, sizeof (datum)))
|
||||
|
@ -392,16 +385,8 @@ prepare_response(NKSN_Instance session, int error, int next_protocol, int aead_a
|
|||
}
|
||||
|
||||
context.algorithm = aead_algorithm;
|
||||
exporter_algorithm = aead_algorithm;
|
||||
|
||||
/* With AES-128-GCM-SIV, set the algorithm ID in the RFC5705 key exporter
|
||||
context incorrectly for compatibility with older chrony clients unless
|
||||
the client requested the compliant context */
|
||||
if (exporter_algorithm == AEAD_AES_128_GCM_SIV && !compliant_128gcm)
|
||||
exporter_algorithm = AEAD_AES_SIV_CMAC_256;
|
||||
|
||||
if (!NKSN_GetKeys(session, aead_algorithm, exporter_algorithm,
|
||||
NKE_NEXT_PROTOCOL_NTPV4, &context.c2s, &context.s2c))
|
||||
if (!NKSN_GetKeys(session, aead_algorithm, &context.c2s, &context.s2c))
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < NKE_MAX_COOKIES; i++) {
|
||||
|
@ -426,8 +411,7 @@ process_request(NKSN_Instance session)
|
|||
int next_protocol_records = 0, aead_algorithm_records = 0;
|
||||
int next_protocol_values = 0, aead_algorithm_values = 0;
|
||||
int next_protocol = -1, aead_algorithm = -1, error = -1;
|
||||
int i, j, critical, type, length;
|
||||
int compliant_128gcm = 0;
|
||||
int i, critical, type, length;
|
||||
uint16_t data[NKE_MAX_RECORD_BODY_LENGTH / sizeof (uint16_t)];
|
||||
|
||||
assert(NKE_MAX_RECORD_BODY_LENGTH % sizeof (uint16_t) == 0);
|
||||
|
@ -462,21 +446,11 @@ process_request(NKSN_Instance session)
|
|||
|
||||
for (i = 0; i < MIN(length, sizeof (data)) / 2; i++) {
|
||||
aead_algorithm_values++;
|
||||
/* Use the first enabled and supported algorithm */
|
||||
for (j = 0; j < ARR_GetSize(CNF_GetNtsAeads()); j++) {
|
||||
if (ntohs(data[i]) == *(int *)ARR_GetElement(CNF_GetNtsAeads(), j) &&
|
||||
aead_algorithm < 0 && SIV_GetKeyLength(ntohs(data[i])) > 0)
|
||||
aead_algorithm = ntohs(data[i]);
|
||||
}
|
||||
/* Use the first supported algorithm */
|
||||
if (aead_algorithm < 0 && SIV_GetKeyLength(ntohs(data[i])) > 0)
|
||||
aead_algorithm = ntohs(data[i]);
|
||||
}
|
||||
break;
|
||||
case NKE_RECORD_COMPLIANT_128GCM_EXPORT:
|
||||
if (length != 0) {
|
||||
error = NKE_ERROR_BAD_REQUEST;
|
||||
break;
|
||||
}
|
||||
compliant_128gcm = 1;
|
||||
break;
|
||||
case NKE_RECORD_ERROR:
|
||||
case NKE_RECORD_WARNING:
|
||||
case NKE_RECORD_COOKIE:
|
||||
|
@ -495,7 +469,7 @@ process_request(NKSN_Instance session)
|
|||
error = NKE_ERROR_BAD_REQUEST;
|
||||
}
|
||||
|
||||
if (!prepare_response(session, error, next_protocol, aead_algorithm, compliant_128gcm))
|
||||
if (!prepare_response(session, error, next_protocol, aead_algorithm))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
|
|
|
@ -877,42 +877,22 @@ NKSN_GetRecord(NKSN_Instance inst, int *critical, int *type, int *body_length,
|
|||
/* ================================================== */
|
||||
|
||||
int
|
||||
NKSN_GetKeys(NKSN_Instance inst, SIV_Algorithm algorithm, SIV_Algorithm exporter_algorithm,
|
||||
int next_protocol, NKE_Key *c2s, NKE_Key *s2c)
|
||||
NKSN_GetKeys(NKSN_Instance inst, SIV_Algorithm siv, NKE_Key *c2s, NKE_Key *s2c)
|
||||
{
|
||||
int length = SIV_GetKeyLength(algorithm);
|
||||
struct {
|
||||
uint16_t next_protocol;
|
||||
uint16_t algorithm;
|
||||
uint8_t is_s2c;
|
||||
uint8_t _pad;
|
||||
} context;
|
||||
|
||||
if (!inst->tls_session)
|
||||
return 0;
|
||||
int length = SIV_GetKeyLength(siv);
|
||||
|
||||
if (length <= 0 || length > sizeof (c2s->key) || length > sizeof (s2c->key)) {
|
||||
DEBUG_LOG("Invalid algorithm");
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(sizeof (context) == 6);
|
||||
context.next_protocol = htons(next_protocol);
|
||||
context.algorithm = htons(exporter_algorithm);
|
||||
|
||||
context.is_s2c = 0;
|
||||
if (gnutls_prf_rfc5705(inst->tls_session,
|
||||
sizeof (NKE_EXPORTER_LABEL) - 1, NKE_EXPORTER_LABEL,
|
||||
sizeof (context) - 1, (char *)&context,
|
||||
length, (char *)c2s->key) < 0) {
|
||||
DEBUG_LOG("Could not export key");
|
||||
return 0;
|
||||
}
|
||||
|
||||
context.is_s2c = 1;
|
||||
if (gnutls_prf_rfc5705(inst->tls_session,
|
||||
sizeof (NKE_EXPORTER_CONTEXT_C2S) - 1, NKE_EXPORTER_CONTEXT_C2S,
|
||||
length, (char *)c2s->key) < 0 ||
|
||||
gnutls_prf_rfc5705(inst->tls_session,
|
||||
sizeof (NKE_EXPORTER_LABEL) - 1, NKE_EXPORTER_LABEL,
|
||||
sizeof (context) - 1, (char *)&context,
|
||||
sizeof (NKE_EXPORTER_CONTEXT_S2C) - 1, NKE_EXPORTER_CONTEXT_S2C,
|
||||
length, (char *)s2c->key) < 0) {
|
||||
DEBUG_LOG("Could not export key");
|
||||
return 0;
|
||||
|
|
|
@ -77,11 +77,8 @@ extern int NKSN_EndMessage(NKSN_Instance inst);
|
|||
extern int NKSN_GetRecord(NKSN_Instance inst, int *critical, int *type, int *body_length,
|
||||
void *body, int buffer_length);
|
||||
|
||||
/* Export NTS keys for a specified algorithm (for compatibility reasons the
|
||||
RFC5705 exporter context is allowed to have a different algorithm) */
|
||||
extern int NKSN_GetKeys(NKSN_Instance inst, SIV_Algorithm algorithm,
|
||||
SIV_Algorithm exporter_algorithm,
|
||||
int next_protocol, NKE_Key *c2s, NKE_Key *s2c);
|
||||
/* Export NTS keys for a specified algorithm */
|
||||
extern int NKSN_GetKeys(NKSN_Instance inst, SIV_Algorithm siv, NKE_Key *c2s, NKE_Key *s2c);
|
||||
|
||||
/* Check if the session has stopped */
|
||||
extern int NKSN_IsStopped(NKSN_Instance inst);
|
||||
|
|
|
@ -72,7 +72,6 @@ struct NNC_Instance_Record {
|
|||
double last_nke_success;
|
||||
|
||||
NKE_Context context;
|
||||
NKE_Context alt_context;
|
||||
unsigned int context_id;
|
||||
NKE_Cookie cookies[NTS_MAX_COOKIES];
|
||||
int num_cookies;
|
||||
|
@ -106,7 +105,6 @@ reset_instance(NNC_Instance inst)
|
|||
inst->last_nke_success = 0.0;
|
||||
|
||||
memset(&inst->context, 0, sizeof (inst->context));
|
||||
memset(&inst->alt_context, 0, sizeof (inst->alt_context));
|
||||
inst->context_id = 0;
|
||||
memset(inst->cookies, 0, sizeof (inst->cookies));
|
||||
inst->num_cookies = 0;
|
||||
|
@ -167,21 +165,6 @@ check_cookies(NNC_Instance inst)
|
|||
if (inst->num_cookies > 0 &&
|
||||
((inst->nak_response && !inst->ok_response) ||
|
||||
SCH_GetLastEventMonoTime() - inst->last_nke_success > CNF_GetNtsRefresh())) {
|
||||
|
||||
/* Before dropping the cookies, check whether there is an alternate set of
|
||||
keys available (exported with the compliant context for AES-128-GCM-SIV)
|
||||
and the NAK was the only valid response after the last NTS-KE session,
|
||||
indicating we use incorrect keys and switching to the other set of keys
|
||||
for the following NTP requests might work */
|
||||
if (inst->alt_context.algorithm != AEAD_SIV_INVALID &&
|
||||
inst->alt_context.algorithm == inst->context.algorithm &&
|
||||
inst->nke_attempts > 0 && inst->nak_response && !inst->ok_response) {
|
||||
inst->context = inst->alt_context;
|
||||
inst->alt_context.algorithm = AEAD_SIV_INVALID;
|
||||
DEBUG_LOG("Switched to compliant keys");
|
||||
return 1;
|
||||
}
|
||||
|
||||
inst->num_cookies = 0;
|
||||
DEBUG_LOG("Dropped cookies");
|
||||
}
|
||||
|
@ -278,7 +261,7 @@ get_cookies(NNC_Instance inst)
|
|||
assert(sizeof (inst->cookies) / sizeof (inst->cookies[0]) == NTS_MAX_COOKIES);
|
||||
|
||||
/* Get the new keys, cookies and NTP address if the session was successful */
|
||||
got_data = NKC_GetNtsData(inst->nke, &inst->context, &inst->alt_context,
|
||||
got_data = NKC_GetNtsData(inst->nke, &inst->context,
|
||||
inst->cookies, &inst->num_cookies, NTS_MAX_COOKIES,
|
||||
&ntp_address);
|
||||
|
||||
|
@ -537,7 +520,6 @@ NNC_CheckResponseAuth(NNC_Instance inst, NTP_Packet *packet,
|
|||
new NTS-KE session to be started as soon as the cookies run out. */
|
||||
inst->nke_attempts = 0;
|
||||
inst->next_nke_attempt = 0.0;
|
||||
inst->alt_context.algorithm = AEAD_SIV_INVALID;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -661,7 +643,6 @@ load_cookies(NNC_Instance inst)
|
|||
sscanf(words[0], "%u", &context_id) != 1 || sscanf(words[1], "%d", &algorithm) != 1)
|
||||
goto error;
|
||||
|
||||
inst->alt_context.algorithm = AEAD_SIV_INVALID;
|
||||
inst->context.algorithm = algorithm;
|
||||
inst->context.s2c.length = UTI_HexToBytes(words[2], inst->context.s2c.key,
|
||||
sizeof (inst->context.s2c.key));
|
||||
|
@ -706,7 +687,6 @@ error:
|
|||
fclose(f);
|
||||
|
||||
memset(&inst->context, 0, sizeof (inst->context));
|
||||
memset(&inst->alt_context, 0, sizeof (inst->alt_context));
|
||||
inst->num_cookies = 0;
|
||||
}
|
||||
|
||||
|
|
14
refclock.c
14
refclock.c
|
@ -63,7 +63,6 @@ struct RCL_Instance_Record {
|
|||
int driver_poll;
|
||||
int driver_polled;
|
||||
int poll;
|
||||
int reached;
|
||||
int leap_status;
|
||||
int local;
|
||||
int pps_forced;
|
||||
|
@ -176,7 +175,6 @@ RCL_AddRefclock(RefclockParameters *params)
|
|||
inst->driver_poll = params->driver_poll;
|
||||
inst->poll = params->poll;
|
||||
inst->driver_polled = 0;
|
||||
inst->reached = 0;
|
||||
inst->leap_status = LEAP_Normal;
|
||||
inst->local = params->local;
|
||||
inst->pps_forced = params->pps_forced;
|
||||
|
@ -667,12 +665,6 @@ RCL_AddCookedPulse(RCL_Instance instance, struct timespec *cooked_time,
|
|||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
RCL_UpdateReachability(RCL_Instance instance)
|
||||
{
|
||||
instance->reached++;
|
||||
}
|
||||
|
||||
double
|
||||
RCL_GetPrecision(RCL_Instance instance)
|
||||
{
|
||||
|
@ -800,9 +792,6 @@ poll_timeout(void *arg)
|
|||
if (!(inst->driver->poll && inst->driver_polled < (1 << (inst->poll - inst->driver_poll)))) {
|
||||
inst->driver_polled = 0;
|
||||
|
||||
SRC_UpdateReachability(inst->source, inst->reached > 0);
|
||||
inst->reached = 0;
|
||||
|
||||
if (SPF_GetFilteredSample(inst->filter, &sample)) {
|
||||
double local_freq, local_offset;
|
||||
struct timespec local_ref_time;
|
||||
|
@ -818,6 +807,7 @@ poll_timeout(void *arg)
|
|||
inst->leap_status = LEAP_Unsynchronised;
|
||||
}
|
||||
|
||||
SRC_UpdateReachability(inst->source, 1);
|
||||
SRC_UpdateStatus(inst->source, stratum, inst->leap_status);
|
||||
SRC_AccumulateSample(inst->source, &sample);
|
||||
SRC_SelectSource(inst->source);
|
||||
|
@ -826,6 +816,8 @@ poll_timeout(void *arg)
|
|||
follow_local(inst, &local_ref_time, local_freq, local_offset);
|
||||
|
||||
log_sample(inst, &sample.time, 1, 0, 0.0, sample.offset, sample.peer_dispersion);
|
||||
} else {
|
||||
SRC_UpdateReachability(inst->source, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -81,7 +81,6 @@ extern int RCL_AddSample(RCL_Instance instance, struct timespec *sample_time,
|
|||
extern int RCL_AddPulse(RCL_Instance instance, struct timespec *pulse_time, double second);
|
||||
extern int RCL_AddCookedPulse(RCL_Instance instance, struct timespec *cooked_time,
|
||||
double second, double dispersion, double raw_correction);
|
||||
extern void RCL_UpdateReachability(RCL_Instance instance);
|
||||
extern double RCL_GetPrecision(RCL_Instance instance);
|
||||
extern int RCL_GetDriverPoll(RCL_Instance instance);
|
||||
|
||||
|
|
|
@ -154,8 +154,6 @@ static void process_ext_pulse(RCL_Instance instance, struct timespec *phc_ts)
|
|||
}
|
||||
phc->last_extts = *phc_ts;
|
||||
|
||||
RCL_UpdateReachability(instance);
|
||||
|
||||
if (!HCL_CookTime(phc->clock, phc_ts, &local_ts, &local_err))
|
||||
return;
|
||||
|
||||
|
@ -206,9 +204,6 @@ static int phc_poll(RCL_Instance instance)
|
|||
if (n_readings < 1)
|
||||
return 0;
|
||||
|
||||
if (!phc->extpps)
|
||||
RCL_UpdateReachability(instance);
|
||||
|
||||
if (!HCL_ProcessReadings(phc->clock, n_readings, readings, &phc_ts, &sys_ts, &phc_err))
|
||||
return 0;
|
||||
|
||||
|
|
|
@ -143,8 +143,6 @@ static int pps_poll(RCL_Instance instance)
|
|||
|
||||
pps->last_seq = seq;
|
||||
|
||||
RCL_UpdateReachability(instance);
|
||||
|
||||
return RCL_AddPulse(instance, &ts, 1.0e-9 * ts.tv_nsec);
|
||||
}
|
||||
|
||||
|
|
|
@ -109,8 +109,6 @@ static int shm_poll(RCL_Instance instance)
|
|||
|
||||
shm->valid = 0;
|
||||
|
||||
RCL_UpdateReachability(instance);
|
||||
|
||||
receive_ts.tv_sec = t.receiveTimeStampSec;
|
||||
clock_ts.tv_sec = t.clockTimeStampSec;
|
||||
|
||||
|
|
|
@ -129,8 +129,6 @@ static void read_sample(int sockfd, int event, void *anything)
|
|||
UTI_TimevalToTimespec(&sample.tv, &sys_ts);
|
||||
UTI_NormaliseTimespec(&sys_ts);
|
||||
|
||||
RCL_UpdateReachability(instance);
|
||||
|
||||
if (!UTI_IsTimeOffsetSane(&sys_ts, sample.offset))
|
||||
return;
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
**********************************************************************
|
||||
* Copyright (C) Richard P. Curnow 1997-2003
|
||||
* Copyright (C) Miroslav Lichvar 2009-2018, 2020, 2022
|
||||
* Copyright (C) Andy Fiddaman 2024
|
||||
*
|
||||
* 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
|
||||
|
|
1
siv.h
1
siv.h
|
@ -36,7 +36,6 @@
|
|||
|
||||
/* Identifiers of SIV algorithms following the IANA AEAD registry */
|
||||
typedef enum {
|
||||
AEAD_SIV_INVALID = 0,
|
||||
AEAD_AES_SIV_CMAC_256 = 15,
|
||||
AEAD_AES_SIV_CMAC_384 = 16,
|
||||
AEAD_AES_SIV_CMAC_512 = 17,
|
||||
|
|
11
sources.c
11
sources.c
|
@ -3,7 +3,7 @@
|
|||
|
||||
**********************************************************************
|
||||
* Copyright (C) Richard P. Curnow 1997-2003
|
||||
* Copyright (C) Miroslav Lichvar 2011-2016, 2018, 2020-2024
|
||||
* Copyright (C) Miroslav Lichvar 2011-2016, 2018, 2020-2023
|
||||
*
|
||||
* 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
|
||||
|
@ -526,6 +526,11 @@ SRC_UpdateReachability(SRC_Instance inst, int reachable)
|
|||
if (inst->reachability_size < SOURCE_REACH_BITS)
|
||||
inst->reachability_size++;
|
||||
|
||||
/* Source selection can change with unreachable sources */
|
||||
if (inst->reachability == 0) {
|
||||
SRC_SelectSource(NULL);
|
||||
}
|
||||
|
||||
/* Check if special reference update mode failed */
|
||||
if (REF_GetMode() != REF_ModeNormal && special_mode_end()) {
|
||||
REF_SetUnsynchronised();
|
||||
|
@ -534,10 +539,6 @@ SRC_UpdateReachability(SRC_Instance inst, int reachable)
|
|||
/* Try to replace unreachable NTP sources */
|
||||
if (inst->reachability == 0 && inst->reachability_size == SOURCE_REACH_BITS)
|
||||
handle_bad_source(inst);
|
||||
|
||||
/* Source selection can change with unreachable sources */
|
||||
if (inst->reachability == 0)
|
||||
SRC_SelectSource(NULL);
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
|
|
@ -36,7 +36,7 @@ Update interval : 16\.. seconds
|
|||
.*$" || test_fail
|
||||
|
||||
if echo "$refclock" | grep -q 'PHC.*nocrossts'; then
|
||||
check_file_messages "20.* GPS.*[0-9] N " 620 750 refclocks.log || test_fail
|
||||
check_file_messages "20.* GPS.*[0-9] N " 650 750 refclocks.log || test_fail
|
||||
else
|
||||
check_file_messages "20.* GPS.*[0-9] N " 997 1001 refclocks.log || test_fail
|
||||
fi
|
||||
|
@ -64,7 +64,7 @@ Stratum.*: 1
|
|||
Root delay : 0\.000000001 seconds
|
||||
.*$" || test_fail
|
||||
|
||||
check_file_messages "20.* PPS1.*[0-9] N " 610 740 refclocks.log || test_fail
|
||||
check_file_messages "20.* PPS1.*[0-9] N " 620 740 refclocks.log || test_fail
|
||||
check_file_messages "20.* PPS1.*- N " 60 63 refclocks.log || test_fail
|
||||
rm -f tmp/refclocks.log
|
||||
|
||||
|
@ -89,15 +89,14 @@ Root delay : 0\.000000001 seconds
|
|||
check_file_messages "20.* PPS1.*- N " 60 63 refclocks.log || test_fail
|
||||
rm -f tmp/refclocks.log
|
||||
|
||||
min_sync_time=80
|
||||
max_sync_time=180
|
||||
min_sync_time=100
|
||||
max_sync_time=220
|
||||
chronyc_start=220
|
||||
client_conf="
|
||||
refclock SHM 0 refid NMEA offset 0.35 delay 0.1
|
||||
refclock PPS /dev/pps0
|
||||
logdir tmp
|
||||
log refclocks
|
||||
maxupdateskew 10000"
|
||||
log refclocks"
|
||||
|
||||
run_test || test_fail
|
||||
check_chronyd_exit || test_fail
|
||||
|
@ -109,37 +108,11 @@ Stratum.*: 1
|
|||
Root delay : 0\.000000001 seconds
|
||||
.*$" || test_fail
|
||||
|
||||
check_file_messages "20.* PPS1.*[0-9] N " 800 960 refclocks.log || test_fail
|
||||
check_file_messages "20.* PPS1.*[0-9] N " 800 940 refclocks.log || test_fail
|
||||
check_file_messages "20.* PPS1.*- N " 50 63 refclocks.log || test_fail
|
||||
rm -f tmp/refclocks.log
|
||||
fi
|
||||
|
||||
export CLKNETSIM_PHC_JITTER_OFF=$[2 * 25 * 492]
|
||||
export CLKNETSIM_PHC_JITTER_ON=$[2 * 25 * 8]
|
||||
export CLKNETSIM_PHC_JITTER=1e-6
|
||||
refclock_offset=0.0
|
||||
refclock_jitter=1e-9
|
||||
min_sync_time=5
|
||||
max_sync_time=7
|
||||
time_max_limit=1e-7
|
||||
time_rms_limit=1e-8
|
||||
client_conf="refclock PHC /dev/ptp0:nocrossts poll 0
|
||||
logdir tmp
|
||||
log refclocks"
|
||||
chronyc_start=500
|
||||
chronyc_conf="sources"
|
||||
|
||||
run_test || test_fail
|
||||
check_chronyd_exit || test_fail
|
||||
check_source_selection || test_fail
|
||||
check_sync || test_fail
|
||||
check_chronyc_output "^MS.*
|
||||
=*
|
||||
#\* PHC0 0 0 377 8 .*$" || test_fail
|
||||
|
||||
unset CLKNETSIM_PHC_JITTER_OFF
|
||||
unset CLKNETSIM_PHC_JITTER_ON
|
||||
export CLKNETSIM_PHC_JITTER=1e-7
|
||||
refclock_offset="(+ 0.399 (sum 1e-3))"
|
||||
refclock_jitter=1e-6
|
||||
servers=1
|
||||
|
|
|
@ -21,7 +21,6 @@ EOF
|
|||
|
||||
clients=2
|
||||
peers=2
|
||||
freq_max_limit=1e-3
|
||||
max_sync_time=1000
|
||||
client_server_options="minpoll 6 maxpoll 6"
|
||||
client_peer_options="minpoll 6 maxpoll 6"
|
||||
|
@ -31,7 +30,6 @@ check_chronyd_exit || test_fail
|
|||
check_source_selection || test_fail
|
||||
check_sync || test_fail
|
||||
|
||||
freq_max_limit=$default_freq_max_limit
|
||||
base_delay="(+ 1e-4 (* -1 (equal 0.1 from 3) (equal 0.1 to 1)))"
|
||||
client_peer_options=""
|
||||
|
||||
|
|
|
@ -58,7 +58,7 @@ MS Name/IP address Stratum Poll Reach LastRx Last sample
|
|||
\^\? 192\.168\.123\.2 0 [0-9]+ 0 - \+0ns\[ \+0ns\] \+/- 0ns
|
||||
Name/IP Address NP NR Span Frequency Freq Skew Offset Std Dev
|
||||
==============================================================================
|
||||
SHM0 [0-9 ]+ [0-9 ]+ [0-9 ]+ [ +-][012]\.... [0-9 ]+\.... [0-9 +-]+[un]s [0-9 ]+[un]s
|
||||
SHM0 [0-9 ]+ [0-9 ]+ [0-9 ]+ [ +-][01]\.... [0-9 ]+\.... [0-9 +-]+[un]s [0-9 ]+[un]s
|
||||
192\.168\.123\.1 [0-9 ]+ [0-9 ]+ [0-9 ]+ [ +-][01]\.... [0-9 ]+\.... [0-9 +-]+[un]s [0-9 ]+[un]s
|
||||
192\.168\.123\.2 0 0 0 \+0\.000 2000\.000 \+0ns 4000ms
|
||||
210 n_samples = 0
|
||||
|
|
|
@ -313,31 +313,4 @@ check_sync && test_fail
|
|||
check_file_messages " 3 1 .* 123 " 0 0 log.packets || test_fail
|
||||
check_file_messages " 3 2 .* 123 " 0 0 log.packets || test_fail
|
||||
|
||||
for server_aead in "" "15" "30"; do
|
||||
for client_aead in "" "15" "30"; do
|
||||
server_conf="
|
||||
ntsaeads $server_aead
|
||||
ntsserverkey tmp/server1.key
|
||||
ntsservercert tmp/server1.crt
|
||||
ntsprocesses 0"
|
||||
client_conf="
|
||||
nosystemcert
|
||||
ntsaeads $client_aead
|
||||
ntstrustedcerts tmp/server1.crt
|
||||
ntstrustedcerts tmp/server2.crt"
|
||||
client_server_conf=""
|
||||
|
||||
run_test || test_fail
|
||||
check_chronyd_exit || test_fail
|
||||
if [ -n "$server_aead" ] && [ "$server_aead" == "$client_aead" ] &&
|
||||
( [ "$server_aead" != "30" ] || check_config_h '.*_SIV_GCM 1' ); then
|
||||
check_source_selection || test_fail
|
||||
check_sync || test_fail
|
||||
else
|
||||
check_source_selection && test_fail
|
||||
check_sync && test_fail
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
||||
test_pass
|
||||
|
|
|
@ -53,28 +53,4 @@ check_log_messages "2010-01-01T0[5-9]:.*Source 192.168.123.. replaced with" 0 15
|
|||
check_file_messages "20.*192.168.123.* 11.1 6 6 " 20 500 measurements.log || test_fail
|
||||
rm -f tmp/measurements.log
|
||||
|
||||
# 2 replaceable falsetickers and 1 replaceable unreachable server
|
||||
servers=6
|
||||
falsetickers=2
|
||||
base_delay="(+ 1e-4 (* -1 (equal 0.1 to 3)))"
|
||||
client_server_conf="
|
||||
server nodes-4-1.net1.clk
|
||||
server nodes-5-2.net1.clk
|
||||
server nodes-6-3.net1.clk"
|
||||
|
||||
run_test || test_fail
|
||||
check_chronyd_exit || test_fail
|
||||
check_source_selection && test_fail
|
||||
check_packet_interval || test_fail
|
||||
check_sync || test_fail
|
||||
|
||||
check_log_messages "Can't synchronise: no majority" 1 1 || test_fail
|
||||
check_log_messages "Detected falseticker" 0 2 || test_fail
|
||||
check_log_messages "Source 192.168.123.. replaced with" 3 60 || test_fail
|
||||
check_log_messages "Source 192.168.123.1 replaced with" 1 25 || test_fail
|
||||
check_log_messages "Source 192.168.123.2 replaced with" 1 25 || test_fail
|
||||
check_log_messages "Source 192.168.123.3 replaced with" 1 25 || test_fail
|
||||
check_file_messages "20.*192.168.123.* 11.1 6 6 " 50 800 measurements.log || test_fail
|
||||
rm -f tmp/measurements.log
|
||||
|
||||
test_pass
|
||||
|
|
|
@ -77,32 +77,7 @@ check_chronyc_output "^[^=]*
|
|||
.. 127\.123\.5\.3 *[05] 7 [^^]*
|
||||
.. 127\.123\.5\.6 [^^]*$" || test_fail
|
||||
|
||||
run_chronyc "reload sources" || test_fail
|
||||
run_chronyc "reload sources" || test_fail
|
||||
|
||||
rm $TEST_DIR/conf5.d/{3,5,6}.sources
|
||||
echo "server 127.123.5.7" > $TEST_DIR/conf5.d/7.sources
|
||||
|
||||
run_chronyc "reload sources" || test_fail
|
||||
|
||||
run_chronyc "sources" || test_fail
|
||||
check_chronyc_output "^[^=]*
|
||||
=*
|
||||
.. 127\.123\.1\.1 [^^]*
|
||||
.. 127\.123\.1\.3 [^^]*
|
||||
.. 127\.123\.1\.4 [^^]*
|
||||
.. 127\.123\.3\.1 [^^]*
|
||||
.. 127\.123\.2\.2 [^^]*
|
||||
.. 127\.123\.2\.3 [^^]*
|
||||
.. 127\.123\.4\.4 [^^]*
|
||||
.. 127\.123\.1\.2 *[05] 6 [^^]*
|
||||
.. 127\.123\.5\.2 *[05] 5 [^^]*
|
||||
.. 127\.123\.5\.7 [^^]*$" || test_fail
|
||||
|
||||
run_chronyc "reload sources" || test_fail
|
||||
|
||||
stop_chronyd || test_fail
|
||||
check_chronyd_message_count "Could not add source.*\.5\.5.*in use" 1 1 || test_fail
|
||||
check_chronyd_message_count "Could not add source" 1 1 || test_fail
|
||||
|
||||
test_pass
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
**********************************************************************
|
||||
* Copyright (C) Miroslav Lichvar 2016, 2021, 2024
|
||||
* Copyright (C) Miroslav Lichvar 2016, 2021
|
||||
*
|
||||
* 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
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
**********************************************************************
|
||||
* Copyright (C) Patrick Oppenlander 2024
|
||||
* Copyright (C) Patrick Oppenlander 2023
|
||||
*
|
||||
* 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
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
**********************************************************************
|
||||
* Copyright (C) Miroslav Lichvar 2020, 2024
|
||||
* 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
|
||||
|
@ -23,24 +23,8 @@
|
|||
|
||||
#ifdef FEAT_NTS
|
||||
|
||||
#include <local.h>
|
||||
#include <nts_ke_session.h>
|
||||
#include <util.h>
|
||||
|
||||
#define NKSN_GetKeys get_keys
|
||||
|
||||
static int
|
||||
get_keys(NKSN_Instance session, SIV_Algorithm algorithm, SIV_Algorithm exporter_algorithm,
|
||||
int next_protocol, NKE_Key *c2s, NKE_Key *s2c)
|
||||
{
|
||||
c2s->length = SIV_GetKeyLength(algorithm);
|
||||
UTI_GetRandomBytes(c2s->key, c2s->length);
|
||||
s2c->length = SIV_GetKeyLength(algorithm);
|
||||
UTI_GetRandomBytes(s2c->key, s2c->length);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#include <nts_ke_client.c>
|
||||
#include <local.h>
|
||||
|
||||
static void
|
||||
prepare_response(NKSN_Instance session, int valid)
|
||||
|
@ -104,17 +88,12 @@ prepare_response(NKSN_Instance session, int valid)
|
|||
|
||||
if (random() % 2) {
|
||||
length = random() % (sizeof (data) + 1);
|
||||
TEST_CHECK(NKSN_AddRecord(session, 0, 2000 + random() % 1000, data, length));
|
||||
TEST_CHECK(NKSN_AddRecord(session, 0, 1000 + random() % 1000, data, length));
|
||||
}
|
||||
|
||||
if (random() % 2)
|
||||
TEST_CHECK(NKSN_AddRecord(session, 0, NKE_RECORD_COMPLIANT_128GCM_EXPORT, NULL, 0));
|
||||
|
||||
if (index != 8) {
|
||||
for (i = random() % NKE_MAX_COOKIES; i >= 0; i--) {
|
||||
for (i = 0; i < NKE_MAX_COOKIES; i++) {
|
||||
length = (random() % sizeof (data) + 1) / 4 * 4;
|
||||
if (i == 0 && length == 0)
|
||||
length = 4;
|
||||
if (index == 9)
|
||||
length += (length < sizeof (data) ? 1 : -1) * (random() % 3 + 1);
|
||||
TEST_CHECK(NKSN_AddRecord(session, 0, NKE_RECORD_COOKIE, data, length));
|
||||
|
@ -124,16 +103,12 @@ prepare_response(NKSN_Instance session, int valid)
|
|||
TEST_CHECK(NKSN_EndMessage(session));
|
||||
}
|
||||
|
||||
#define MAX_COOKIES (2 * NKE_MAX_COOKIES)
|
||||
|
||||
void
|
||||
test_unit(void)
|
||||
{
|
||||
NKE_Context context, alt_context;
|
||||
NKE_Cookie cookies[MAX_COOKIES];
|
||||
int i, j, r, valid, num_cookies;
|
||||
NKC_Instance inst;
|
||||
IPSockAddr addr;
|
||||
int i, r, valid;
|
||||
|
||||
char conf[][100] = {
|
||||
"nosystemcert",
|
||||
|
@ -152,33 +127,10 @@ test_unit(void)
|
|||
TEST_CHECK(inst);
|
||||
|
||||
for (i = 0; i < 10000; i++) {
|
||||
inst->got_response = 0;
|
||||
valid = random() % 2;
|
||||
prepare_response(inst->session, valid);
|
||||
r = handle_message(inst);
|
||||
r = process_response(inst);
|
||||
TEST_CHECK(r == valid);
|
||||
|
||||
memset(&context, 0, sizeof (context));
|
||||
memset(&alt_context, 0, sizeof (alt_context));
|
||||
num_cookies = 0;
|
||||
|
||||
r = NKC_GetNtsData(inst, &context, &alt_context,
|
||||
cookies, &num_cookies, random() % MAX_COOKIES + 1, &addr);
|
||||
TEST_CHECK(r == valid);
|
||||
if (r) {
|
||||
TEST_CHECK(context.algorithm != AEAD_SIV_INVALID);
|
||||
TEST_CHECK(context.c2s.length > 0);
|
||||
TEST_CHECK(context.c2s.length == SIV_GetKeyLength(context.algorithm));
|
||||
TEST_CHECK(context.s2c.length == SIV_GetKeyLength(context.algorithm));
|
||||
if (alt_context.algorithm != AEAD_SIV_INVALID) {
|
||||
TEST_CHECK(context.c2s.length > 0);
|
||||
TEST_CHECK(alt_context.c2s.length == SIV_GetKeyLength(alt_context.algorithm));
|
||||
TEST_CHECK(alt_context.s2c.length == SIV_GetKeyLength(alt_context.algorithm));
|
||||
}
|
||||
TEST_CHECK(num_cookies > 0 && num_cookies <= NKE_MAX_COOKIES);
|
||||
for (j = 0; j < num_cookies; j++)
|
||||
TEST_CHECK(cookies[j].length > 0 && cookies[j].length % 4 == 0);
|
||||
}
|
||||
}
|
||||
|
||||
NKC_DestroyInstance(inst);
|
||||
|
|
|
@ -30,12 +30,11 @@
|
|||
#define NKSN_GetKeys get_keys
|
||||
|
||||
static int
|
||||
get_keys(NKSN_Instance session, SIV_Algorithm algorithm, SIV_Algorithm exporter_algorithm,
|
||||
int next_protocol, NKE_Key *c2s, NKE_Key *s2c)
|
||||
get_keys(NKSN_Instance session, SIV_Algorithm siv, NKE_Key *c2s, NKE_Key *s2c)
|
||||
{
|
||||
c2s->length = SIV_GetKeyLength(algorithm);
|
||||
c2s->length = SIV_GetKeyLength(siv);
|
||||
UTI_GetRandomBytes(c2s->key, c2s->length);
|
||||
s2c->length = SIV_GetKeyLength(algorithm);
|
||||
s2c->length = SIV_GetKeyLength(siv);
|
||||
UTI_GetRandomBytes(s2c->key, s2c->length);
|
||||
return 1;
|
||||
}
|
||||
|
@ -92,7 +91,7 @@ prepare_request(NKSN_Instance session, int valid)
|
|||
|
||||
if (index == 8) {
|
||||
length = random() % (sizeof (data) + 1);
|
||||
TEST_CHECK(NKSN_AddRecord(session, 1, 2000 + random() % 1000, data, length));
|
||||
TEST_CHECK(NKSN_AddRecord(session, 1, 1000 + random() % 1000, data, length));
|
||||
}
|
||||
|
||||
if (random() % 2) {
|
||||
|
@ -106,12 +105,9 @@ prepare_request(NKSN_Instance session, int valid)
|
|||
TEST_CHECK(NKSN_AddRecord(session, 0, NKE_RECORD_NTPV4_PORT_NEGOTIATION, data, length));
|
||||
}
|
||||
|
||||
if (random() % 2)
|
||||
TEST_CHECK(NKSN_AddRecord(session, 0, NKE_RECORD_COMPLIANT_128GCM_EXPORT, NULL, 0));
|
||||
|
||||
if (random() % 2) {
|
||||
length = random() % (sizeof (data) + 1);
|
||||
TEST_CHECK(NKSN_AddRecord(session, 0, 2000 + random() % 1000, data, length));
|
||||
TEST_CHECK(NKSN_AddRecord(session, 0, 1000 + random() % 1000, data, length));
|
||||
}
|
||||
|
||||
TEST_CHECK(NKSN_EndMessage(session));
|
||||
|
@ -178,8 +174,7 @@ test_unit(void)
|
|||
|
||||
for (i = 0; i < 10000; i++) {
|
||||
context.algorithm = AEAD_AES_SIV_CMAC_256;
|
||||
get_keys(session, context.algorithm, random() % 100, NKE_NEXT_PROTOCOL_NTPV4,
|
||||
&context.c2s, &context.s2c);
|
||||
get_keys(session, context.algorithm, &context.c2s, &context.s2c);
|
||||
memset(&cookie, 0, sizeof (cookie));
|
||||
TEST_CHECK(NKS_GenerateCookie(&context, &cookie));
|
||||
TEST_CHECK(NKS_DecodeCookie(&cookie, &context2));
|
||||
|
|
|
@ -116,19 +116,9 @@ verify_message(NKSN_Instance inst)
|
|||
|
||||
TEST_CHECK(!NKSN_GetRecord(inst, &critical, &t, &length, buffer, sizeof (buffer)));
|
||||
|
||||
for (i = 0; i < 10; i++) {
|
||||
TEST_CHECK(NKSN_GetKeys(inst, AEAD_AES_SIV_CMAC_256, random(), random(), &c2s, &s2c));
|
||||
TEST_CHECK(c2s.length == SIV_GetKeyLength(AEAD_AES_SIV_CMAC_256));
|
||||
TEST_CHECK(s2c.length == SIV_GetKeyLength(AEAD_AES_SIV_CMAC_256));
|
||||
|
||||
if (SIV_GetKeyLength(AEAD_AES_128_GCM_SIV) > 0) {
|
||||
TEST_CHECK(NKSN_GetKeys(inst, AEAD_AES_128_GCM_SIV, random(), random(), &c2s, &s2c));
|
||||
TEST_CHECK(c2s.length == SIV_GetKeyLength(AEAD_AES_128_GCM_SIV));
|
||||
TEST_CHECK(s2c.length == SIV_GetKeyLength(AEAD_AES_128_GCM_SIV));
|
||||
} else {
|
||||
TEST_CHECK(!NKSN_GetKeys(inst, AEAD_AES_128_GCM_SIV, random(), random(), &c2s, &s2c));
|
||||
}
|
||||
}
|
||||
TEST_CHECK(NKSN_GetKeys(inst, AEAD_AES_SIV_CMAC_256, &c2s, &s2c));
|
||||
TEST_CHECK(c2s.length == SIV_GetKeyLength(AEAD_AES_SIV_CMAC_256));
|
||||
TEST_CHECK(s2c.length == SIV_GetKeyLength(AEAD_AES_SIV_CMAC_256));
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -176,7 +166,6 @@ test_unit(void)
|
|||
const char *cert, *key;
|
||||
int sock_fds[2], i;
|
||||
uint32_t cert_id;
|
||||
NKE_Key c2s, s2c;
|
||||
|
||||
LCL_Initialise();
|
||||
TST_RegisterDummyDrivers();
|
||||
|
@ -201,9 +190,6 @@ test_unit(void)
|
|||
TEST_CHECK(NKSN_StartSession(server, sock_fds[0], "client", server_cred, 4.0));
|
||||
TEST_CHECK(NKSN_StartSession(client, sock_fds[1], "server", client_cred, 4.0));
|
||||
|
||||
TEST_CHECK(!NKSN_GetKeys(server, AEAD_AES_SIV_CMAC_256, 0, 0, &c2s, &s2c));
|
||||
TEST_CHECK(!NKSN_GetKeys(client, AEAD_AES_SIV_CMAC_256, 0, 0, &c2s, &s2c));
|
||||
|
||||
send_message(client);
|
||||
|
||||
request_received = response_received = 0;
|
||||
|
@ -215,9 +201,6 @@ test_unit(void)
|
|||
TEST_CHECK(NKSN_IsStopped(server));
|
||||
TEST_CHECK(NKSN_IsStopped(client));
|
||||
|
||||
TEST_CHECK(!NKSN_GetKeys(server, AEAD_AES_SIV_CMAC_256, 0, 0, &c2s, &s2c));
|
||||
TEST_CHECK(!NKSN_GetKeys(client, AEAD_AES_SIV_CMAC_256, 0, 0, &c2s, &s2c));
|
||||
|
||||
TEST_CHECK(request_received);
|
||||
TEST_CHECK(response_received);
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
#define NKC_IsActive(inst) (random() % 2)
|
||||
#define NKC_GetRetryFactor(inst) (1)
|
||||
|
||||
static int get_nts_data(NKC_Instance inst, NKE_Context *context, NKE_Context *alt_context,
|
||||
static int get_nts_data(NKC_Instance inst, NKE_Context *context,
|
||||
NKE_Cookie *cookies, int *num_cookies, int max_cookies,
|
||||
IPSockAddr *ntp_address);
|
||||
#define NKC_GetNtsData get_nts_data
|
||||
|
@ -41,7 +41,7 @@ static int get_nts_data(NKC_Instance inst, NKE_Context *context, NKE_Context *al
|
|||
#include <nts_ntp_client.c>
|
||||
|
||||
static int
|
||||
get_nts_data(NKC_Instance inst, NKE_Context *context, NKE_Context *alt_context,
|
||||
get_nts_data(NKC_Instance inst, NKE_Context *context,
|
||||
NKE_Cookie *cookies, int *num_cookies, int max_cookies,
|
||||
IPSockAddr *ntp_address)
|
||||
{
|
||||
|
@ -60,14 +60,6 @@ get_nts_data(NKC_Instance inst, NKE_Context *context, NKE_Context *alt_context,
|
|||
context->s2c.length = SIV_GetKeyLength(context->algorithm);
|
||||
UTI_GetRandomBytes(context->s2c.key, context->s2c.length);
|
||||
|
||||
if (random() % 2) {
|
||||
*alt_context = *context;
|
||||
UTI_GetRandomBytes(alt_context->c2s.key, alt_context->c2s.length);
|
||||
UTI_GetRandomBytes(alt_context->s2c.key, alt_context->s2c.length);
|
||||
} else {
|
||||
alt_context->algorithm = AEAD_SIV_INVALID;
|
||||
}
|
||||
|
||||
*num_cookies = random() % max_cookies + 1;
|
||||
for (i = 0; i < *num_cookies; i++) {
|
||||
cookies[i].length = random() % (sizeof (cookies[i].cookie) + 1);
|
||||
|
|
Loading…
Reference in a new issue