mirror of
https://gitlab.com/chrony/chrony.git
synced 2025-12-04 04:35:06 -05:00
Compare commits
62 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d327cfea5a | ||
|
|
c94e7c72e7 | ||
|
|
f3aea33ad4 | ||
|
|
48709d9c4a | ||
|
|
4779adcb50 | ||
|
|
01e29ec685 | ||
|
|
e4cccc115d | ||
|
|
8e9716d5d4 | ||
|
|
a96d288027 | ||
|
|
545d2563ef | ||
|
|
1494ef1df3 | ||
|
|
698f270b5b | ||
|
|
f15f6a86b0 | ||
|
|
5d60d611ae | ||
|
|
6e71e902c8 | ||
|
|
473cb3c968 | ||
|
|
df43ebe9e0 | ||
|
|
642173e864 | ||
|
|
944cf6e318 | ||
|
|
a655eab34f | ||
|
|
f020d479e0 | ||
|
|
de752b28de | ||
|
|
f41d370e6a | ||
|
|
a97830d9d6 | ||
|
|
ea4fc47cda | ||
|
|
0e08ca7c89 | ||
|
|
068cd3c311 | ||
|
|
455b8e4b44 | ||
|
|
d9a363606b | ||
|
|
59ad433b6b | ||
|
|
35b3a42ed9 | ||
|
|
0639205617 | ||
|
|
3916c3366b | ||
|
|
f0a33e7b28 | ||
|
|
c9b8f8bc70 | ||
|
|
983b0723f6 | ||
|
|
02c38934ea | ||
|
|
c28c2cde43 | ||
|
|
349323dec7 | ||
|
|
ddfaf2e542 | ||
|
|
3177474ae8 | ||
|
|
cc535632d1 | ||
|
|
cb8ee57b9e | ||
|
|
c0b19b3fea | ||
|
|
8235da6885 | ||
|
|
f6625717cd | ||
|
|
fdfcabd79b | ||
|
|
2bb88b45c6 | ||
|
|
9820c22c1d | ||
|
|
bcd7bad467 | ||
|
|
83ea9fe284 | ||
|
|
c74d6e458d | ||
|
|
ff466439fc | ||
|
|
0fcdf4389b | ||
|
|
9cb9021c87 | ||
|
|
9c36236742 | ||
|
|
adebb027be | ||
|
|
7d3798d7cd | ||
|
|
b7c7c293e5 | ||
|
|
9ca250755f | ||
|
|
bd3b36865e | ||
|
|
538e1c5eb1 |
9
NEWS
9
NEWS
@@ -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
|
||||
====================
|
||||
|
||||
11
candm.h
11
candm.h
@@ -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;
|
||||
@@ -764,7 +764,8 @@ typedef struct {
|
||||
IPAddr ip_addr;
|
||||
uint8_t state_char;
|
||||
uint8_t authentication;
|
||||
uint8_t pad[2];
|
||||
uint8_t leap;
|
||||
uint8_t pad;
|
||||
uint16_t conf_options;
|
||||
uint16_t eff_options;
|
||||
uint32_t last_sample_ago;
|
||||
|
||||
91
client.c
91
client.c
@@ -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
|
||||
|
||||
/* ================================================== */
|
||||
@@ -1006,36 +1001,17 @@ process_cmd_dfreq(CMD_Request *msg, char *line)
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
static void
|
||||
cvt_to_sec_usec(double x, long *sec, long *usec) {
|
||||
long s, us;
|
||||
s = (long) x;
|
||||
us = (long)(0.5 + 1.0e6 * (x - (double) s));
|
||||
while (us >= 1000000) {
|
||||
us -= 1000000;
|
||||
s += 1;
|
||||
}
|
||||
while (us < 0) {
|
||||
us += 1000000;
|
||||
s -= 1;
|
||||
}
|
||||
|
||||
*sec = s;
|
||||
*usec = us;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
static void
|
||||
process_cmd_doffset(CMD_Request *msg, char *line)
|
||||
{
|
||||
struct timeval tv;
|
||||
double doffset;
|
||||
long sec, usec;
|
||||
|
||||
msg->command = htons(REQ_DOFFSET);
|
||||
if (sscanf(line, "%lf", &doffset) == 1) {
|
||||
cvt_to_sec_usec(doffset, &sec, &usec);
|
||||
msg->data.doffset.sec = htonl(sec);
|
||||
msg->data.doffset.usec = htonl(usec);
|
||||
UTI_DoubleToTimeval(doffset, &tv);
|
||||
msg->data.doffset.sec = htonl(tv.tv_sec);
|
||||
msg->data.doffset.usec = htonl(tv.tv_usec);
|
||||
} else {
|
||||
msg->data.doffset.sec = htonl(0);
|
||||
msg->data.doffset.usec = htonl(0);
|
||||
@@ -1267,7 +1243,7 @@ give_help(void)
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
/* Tab-completion when editline/readline is available */
|
||||
/* Tab-completion when editline is available */
|
||||
|
||||
#ifdef FEAT_READLINE
|
||||
|
||||
@@ -1887,19 +1863,19 @@ print_report(const char *format, ...)
|
||||
integer = va_arg(ap, int);
|
||||
switch (integer) {
|
||||
case LEAP_Normal:
|
||||
string = "Normal";
|
||||
string = width != 1 ? "Normal" : "N";
|
||||
break;
|
||||
case LEAP_InsertSecond:
|
||||
string = "Insert second";
|
||||
string = width != 1 ? "Insert second" : "+";
|
||||
break;
|
||||
case LEAP_DeleteSecond:
|
||||
string = "Delete second";
|
||||
string = width != 1 ? "Delete second" : "-";
|
||||
break;
|
||||
case LEAP_Unsynchronised:
|
||||
string = "Not synchronised";
|
||||
string = width != 1 ? "Not synchronised" : "?";
|
||||
break;
|
||||
default:
|
||||
string = "Invalid";
|
||||
string = width != 1 ? "Invalid" : "?";
|
||||
break;
|
||||
}
|
||||
printf("%s", string);
|
||||
@@ -2054,7 +2030,7 @@ get_source_name(IPAddr *ip_addr, char *buf, int size)
|
||||
|
||||
/* Make sure the name is printable */
|
||||
for (i = 0; i < size && buf[i] != '\0'; i++) {
|
||||
if (!isgraph(buf[i]))
|
||||
if (!isgraph((unsigned char)buf[i]))
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2146,8 +2122,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 +2165,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 +2177,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:
|
||||
@@ -2581,9 +2557,9 @@ process_cmd_selectdata(char *line)
|
||||
printf( "| | | | |\n");
|
||||
}
|
||||
|
||||
print_header("S Name/IP Address Auth COpts EOpts Last Score Interval ");
|
||||
print_header("S Name/IP Address Auth COpts EOpts Last Score Interval Leap");
|
||||
|
||||
/* "S NNNNNNNNNNNNNNNNNNNNNNNNN A OOOO- OOOO- LLLL SSSSS LLLLLLL LLLLLLL" */
|
||||
/* "S NNNNNNNNNNNNNNNNNNNNNNNNN A OOOO- OOOO- LLLL SSSSS IIIIIII IIIIIII L" */
|
||||
|
||||
for (i = 0; i < n_sources; i++) {
|
||||
request.command = htons(REQ_SELECT_DATA);
|
||||
@@ -2601,7 +2577,7 @@ process_cmd_selectdata(char *line)
|
||||
conf_options = ntohs(reply.data.select_data.conf_options);
|
||||
eff_options = ntohs(reply.data.select_data.eff_options);
|
||||
|
||||
print_report("%c %-25s %c %c%c%c%c%c %c%c%c%c%c %I %5.1f %+S %+S\n",
|
||||
print_report("%c %-25s %c %c%c%c%c%c %c%c%c%c%c %I %5.1f %+S %+S %1L\n",
|
||||
reply.data.select_data.state_char,
|
||||
name,
|
||||
reply.data.select_data.authentication ? 'Y' : 'N',
|
||||
@@ -2619,6 +2595,7 @@ process_cmd_selectdata(char *line)
|
||||
UTI_FloatNetworkToHost(reply.data.select_data.score),
|
||||
UTI_FloatNetworkToHost(reply.data.select_data.lo_limit),
|
||||
UTI_FloatNetworkToHost(reply.data.select_data.hi_limit),
|
||||
reply.data.select_data.leap,
|
||||
REPORT_END);
|
||||
}
|
||||
|
||||
@@ -3476,7 +3453,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",
|
||||
@@ -3488,8 +3465,22 @@ display_gpl(void)
|
||||
static void
|
||||
print_help(const char *progname)
|
||||
{
|
||||
printf("Usage: %s [-h HOST] [-p PORT] [-n] [-N] [-c] [-d] [-4|-6] [-m] [COMMAND]\n",
|
||||
progname);
|
||||
printf("Usage: %s [OPTION]... [COMMAND]...\n\n"
|
||||
"Options:\n"
|
||||
" -4\t\tUse IPv4 addresses only\n"
|
||||
" -6\t\tUse IPv6 addresses only\n"
|
||||
" -n\t\tDon't resolve hostnames\n"
|
||||
" -N\t\tPrint original source names\n"
|
||||
" -c\t\tEnable CSV format\n"
|
||||
#if DEBUG > 0
|
||||
" -d\t\tEnable debug messages\n"
|
||||
#endif
|
||||
" -m\t\tAccept multiple commands\n"
|
||||
" -h HOST\tSpecify server (%s)\n"
|
||||
" -p PORT\tSpecify UDP port (%d)\n"
|
||||
" -v, --version\tPrint version and exit\n"
|
||||
" --help\tPrint usage and exit\n",
|
||||
progname, DEFAULT_COMMAND_SOCKET",127.0.0.1,::1", DEFAULT_CANDM_PORT);
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
@@ -3511,7 +3502,7 @@ main(int argc, char **argv)
|
||||
int opt, ret = 1, multi = 0, family = IPADDR_UNSPEC;
|
||||
int port = DEFAULT_CANDM_PORT;
|
||||
|
||||
/* Parse (undocumented) long command-line options */
|
||||
/* Parse long command-line options */
|
||||
for (optind = 1; optind < argc; optind++) {
|
||||
if (!strcmp("--help", argv[optind])) {
|
||||
print_help(progname);
|
||||
|
||||
@@ -169,7 +169,7 @@ compare_total_hits(Record *x, Record *y)
|
||||
static Record *
|
||||
get_record(IPAddr *ip)
|
||||
{
|
||||
uint32_t last_hit, oldest_hit = 0;
|
||||
uint32_t last_hit = 0, oldest_hit = 0;
|
||||
Record *record, *oldest_record;
|
||||
unsigned int first, i, j;
|
||||
|
||||
|
||||
52
cmdmon.c
52
cmdmon.c
@@ -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,13 +294,20 @@ 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))
|
||||
if (message->addr_type == SCK_ADDR_IP &&
|
||||
!SCK_IsLinkLocalIPAddress(&message->remote_addr.ip.ip_addr))
|
||||
message->if_index = INVALID_IF_INDEX;
|
||||
|
||||
if (!SCK_SendMessage(sock_fd, message, 0))
|
||||
@@ -572,11 +579,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 +588,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) {
|
||||
@@ -1320,6 +1327,7 @@ handle_select_data(CMD_Request *rx_message, CMD_Reply *tx_message)
|
||||
UTI_IPHostToNetwork(&report.ip_addr, &tx_message->data.select_data.ip_addr);
|
||||
tx_message->data.select_data.state_char = report.state_char;
|
||||
tx_message->data.select_data.authentication = report.authentication;
|
||||
tx_message->data.select_data.leap = report.leap;
|
||||
tx_message->data.select_data.conf_options = htons(convert_select_options(report.conf_options));
|
||||
tx_message->data.select_data.eff_options = htons(convert_select_options(report.eff_options));
|
||||
tx_message->data.select_data.last_sample_ago = htonl(report.last_sample_ago);
|
||||
@@ -1427,7 +1435,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 +1445,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 +1454,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 +1741,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);
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
23
conf.c
23
conf.c
@@ -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;
|
||||
@@ -421,6 +422,10 @@ CNF_Finalise(void)
|
||||
Free(((NTP_Source *)ARR_GetElement(ntp_sources, i))->params.name);
|
||||
for (i = 0; i < ARR_GetSize(ntp_source_dirs); i++)
|
||||
Free(*(char **)ARR_GetElement(ntp_source_dirs, i));
|
||||
for (i = 0; i < ARR_GetSize(refclock_sources); i++) {
|
||||
Free(((RefclockParameters *)ARR_GetElement(refclock_sources, i))->driver_name);
|
||||
Free(((RefclockParameters *)ARR_GetElement(refclock_sources, i))->driver_parameter);
|
||||
}
|
||||
|
||||
ARR_DestroyInstance(init_sources);
|
||||
ARR_DestroyInstance(ntp_sources);
|
||||
@@ -544,6 +549,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")) {
|
||||
@@ -1836,10 +1843,14 @@ CNF_AddSources(void)
|
||||
void
|
||||
CNF_AddRefclocks(void)
|
||||
{
|
||||
RefclockParameters *refclock;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ARR_GetSize(refclock_sources); i++) {
|
||||
RCL_AddRefclock((RefclockParameters *)ARR_GetElement(refclock_sources, i));
|
||||
refclock = ARR_GetElement(refclock_sources, i);
|
||||
RCL_AddRefclock(refclock);
|
||||
Free(refclock->driver_name);
|
||||
Free(refclock->driver_parameter);
|
||||
}
|
||||
|
||||
ARR_SetSize(refclock_sources, 0);
|
||||
@@ -2048,6 +2059,14 @@ CNF_GetMaxSlewRate(void)
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
double
|
||||
CNF_GetClockPrecision(void)
|
||||
{
|
||||
return clock_precision;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
double
|
||||
CNF_GetMaxDistance(void)
|
||||
{
|
||||
|
||||
1
conf.h
1
conf.h
@@ -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);
|
||||
|
||||
74
configure
vendored
74
configure
vendored
@@ -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/[^=]*=//;'`
|
||||
;;
|
||||
@@ -709,11 +689,11 @@ fi
|
||||
|
||||
if test_code 'arc4random_buf()' 'stdlib.h' '' '' 'arc4random_buf(NULL, 0);'; then
|
||||
add_def HAVE_ARC4RANDOM
|
||||
fi
|
||||
|
||||
if test_code 'getrandom()' 'stdlib.h sys/random.h' '' '' \
|
||||
'return getrandom(NULL, 256, 0);'; then
|
||||
add_def HAVE_GETRANDOM
|
||||
else
|
||||
if test_code 'getrandom()' 'stdlib.h sys/random.h' '' '' \
|
||||
'return getrandom(NULL, 256, 0);'; then
|
||||
add_def HAVE_GETRANDOM
|
||||
fi
|
||||
fi
|
||||
|
||||
RECVMMSG_CODE='
|
||||
@@ -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
|
||||
priv_ops="NAME2IPADDRESS RELOADDNS"
|
||||
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
|
||||
|
||||
@@ -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_::
|
||||
@@ -1563,9 +1608,12 @@ to the clients, which means they should use the same server for NTS-KE and NTP.
|
||||
|
||||
[[ntsrotate]]*ntsrotate* _interval_::
|
||||
This directive specifies the rotation interval (in seconds) of the server key
|
||||
which encrypts the NTS cookies. New keys are generated automatically. The
|
||||
server keeps two previous keys to give the clients time to get new cookies
|
||||
encrypted by the latest key. The default interval is 604800 seconds (1 week).
|
||||
which encrypts the NTS cookies. New keys are generated automatically from the
|
||||
_/dev/urandom_ device. The server keeps two previous keys to give the clients
|
||||
time to get new cookies encrypted by the latest key. The interval is measured
|
||||
as the server's operating time, i.e. the actual interval can be longer if
|
||||
*chronyd* is not running continuously. The default interval is 604800 seconds
|
||||
(1 week).
|
||||
+
|
||||
The automatic rotation of the keys can be disabled by setting *ntsrotate* to 0.
|
||||
In this case the keys are assumed to be managed externally. *chronyd* will not
|
||||
@@ -1822,7 +1870,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 +2251,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 +2268,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 +2282,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 +2319,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:
|
||||
+
|
||||
@@ -2458,7 +2514,7 @@ the following methods:
|
||||
stratum 1 and stratum 2 servers. You should find one or more servers that are
|
||||
near to you. Check that their access policy allows you to use their
|
||||
facilities.
|
||||
* Use public servers from the http://www.pool.ntp.org/[pool.ntp.org] project.
|
||||
* Use public servers from the https://www.pool.ntp.org/[pool.ntp.org] project.
|
||||
|
||||
Assuming that your NTP servers are called _foo.example.net_, _bar.example.net_
|
||||
and _baz.example.net_, your _chrony.conf_ file could contain as a minimum:
|
||||
@@ -2497,6 +2553,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
|
||||
@@ -2736,7 +2806,7 @@ information to be saved.
|
||||
=== Public NTP server
|
||||
|
||||
*chronyd* can be configured to operate as a public NTP server, e.g. to join the
|
||||
http://www.pool.ntp.org/en/join.html[pool.ntp.org] project. The configuration
|
||||
https://www.pool.ntp.org/en/join.html[pool.ntp.org] project. The configuration
|
||||
is similar to the NTP client with permanent connection, except it needs to
|
||||
allow client access from all addresses. It is recommended to find at least four
|
||||
good servers (e.g. from the pool, or on the NTP homepage). If the server has a
|
||||
|
||||
@@ -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.
|
||||
@@ -120,10 +118,14 @@ This option is ignored and is provided only for compatibility.
|
||||
*-a*::
|
||||
This option is ignored and is provided only for compatibility.
|
||||
|
||||
*-v*::
|
||||
*-v*, *--version*::
|
||||
With this option *chronyc* displays its version number on the terminal and
|
||||
exits.
|
||||
|
||||
*--help*::
|
||||
With this option *chronyc* displays a help message on the terminal and
|
||||
exits.
|
||||
|
||||
== COMMANDS
|
||||
|
||||
This section describes each of the commands available within the *chronyc*
|
||||
@@ -183,10 +185,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 +321,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.
|
||||
@@ -423,11 +432,11 @@ lines are shown as a reminder of the meanings of the columns.
|
||||
An example of the output is shown below.
|
||||
+
|
||||
----
|
||||
S Name/IP Address Auth COpts EOpts Last Score Interval
|
||||
====================================================================
|
||||
D foo.example.net Y ----- --TR- 4 1.0 -61ms +62ms
|
||||
* bar.example.net N ----- ----- 0 1.0 -6846us +7305us
|
||||
+ baz.example.net N ----- ----- 10 1.0 -7381us +7355us
|
||||
S Name/IP Address Auth COpts EOpts Last Score Interval Leap
|
||||
=======================================================================
|
||||
D foo.example.net Y ----- --TR- 4 1.0 -61ms +62ms N
|
||||
* bar.example.net N ----- ----- 0 1.0 -6846us +7305us N
|
||||
+ baz.example.net N ----- ----- 10 1.0 -7381us +7355us N
|
||||
----
|
||||
+
|
||||
The columns are as follows:
|
||||
@@ -499,6 +508,12 @@ be reselected and the scores will be reset to 1.
|
||||
This column displays the lower and upper endpoint of the interval which was
|
||||
expected to contain the true offset of the local clock considering the root
|
||||
distance at the time of the selection.
|
||||
*Leap*:::
|
||||
This column displays the current leap status of the source.
|
||||
* _N_ indicates the normal status (no leap second).
|
||||
* _+_ indicates that a leap second will be inserted at the end of the month.
|
||||
* _-_ indicates that a leap second will be deleted at the end of the month.
|
||||
* _?_ indicates the unknown status (i.e. no valid measurement was made).
|
||||
|
||||
[[reselect]]*reselect*::
|
||||
To avoid excessive switching between sources, *chronyd* can stay synchronised
|
||||
@@ -1328,10 +1343,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 +1368,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 +1437,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*::
|
||||
|
||||
@@ -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,14 +184,15 @@ 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*::
|
||||
*-v*, *--version*::
|
||||
With this option *chronyd* will print version number to the terminal and exit.
|
||||
|
||||
*-h*, *--help*::
|
||||
With this option *chronyd* will print a help message to the terminal and exit.
|
||||
|
||||
== FILES
|
||||
|
||||
_@SYSCONFDIR@/chrony.conf_
|
||||
|
||||
273
doc/faq.adoc
273
doc/faq.adoc
@@ -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,13 +62,13 @@ 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.
|
||||
|
||||
If you want to use public NTP servers from the
|
||||
http://www.pool.ntp.org/[pool.ntp.org] project, the minimal _chrony.conf_ file
|
||||
https://www.pool.ntp.org/[pool.ntp.org] project, the minimal _chrony.conf_ file
|
||||
could be:
|
||||
|
||||
----
|
||||
@@ -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,52 @@ 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), `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 before the second source is selected, depending on its polling
|
||||
interval. 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).
|
||||
|
||||
=== Does selected source drop new measurements?
|
||||
|
||||
`chronyd` can drop a large number of successive NTP measurements if they are
|
||||
not passing some of the NTP tests. The `sources` command can report for a
|
||||
selected source the fully-reachable value of 377 in the Reach column and at the
|
||||
same time a LastRx value that is much larger than the current polling interval.
|
||||
If the source is online, this indicates that a number of measurements was
|
||||
dropped. You can use the `ntpdata` command to check the NTP tests for the last
|
||||
measurement. Usually, it is the test C which fails.
|
||||
|
||||
This can be an issue when there is a long-lasting increase in the measured
|
||||
delay, e.g. due to a routing change in the network. Unfortunately, `chronyd`
|
||||
does not know for how long it should wait for the delay to come back to the
|
||||
original values, or whether it is a permanent increase and it should start from
|
||||
scratch.
|
||||
|
||||
The test C is an adaptive filter. It can take many hours before it accepts
|
||||
a measurement with the larger delay, and even much longer before it drops all
|
||||
measurements with smaller delay, which determine an expected delay used by the
|
||||
test. You can use the `reset sources` command to drop all measurements
|
||||
immediately (available in chrony 4.0 and later). If this issue happens
|
||||
frequently, you can effectively disable the test by setting the
|
||||
`maxdelaydevratio` option to a very large value (e.g. 1000000), or speed up the
|
||||
recovery by increasing the clock error rate with the `maxclockerror` directive.
|
||||
|
||||
=== Using a PPS reference clock?
|
||||
|
||||
A pulse-per-second (PPS) reference clock requires a non-PPS time source to
|
||||
@@ -409,15 +501,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 +518,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 +551,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 +566,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 +595,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 +610,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 +627,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 +644,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?
|
||||
|
||||
@@ -94,13 +94,13 @@ want to enable the support, specify the `--disable-asyncdns` flag to
|
||||
|
||||
If development files for the https://www.lysator.liu.se/~nisse/nettle/[Nettle],
|
||||
https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS[NSS], or
|
||||
http://www.libtom.net/LibTomCrypt/[libtomcrypt] library are available,
|
||||
https://www.libtom.net/LibTomCrypt/[libtomcrypt] library are available,
|
||||
`chronyd` will be built with support for other cryptographic hash functions
|
||||
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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Use public servers from the pool.ntp.org project.
|
||||
# Please consider joining the pool (http://www.pool.ntp.org/join.html).
|
||||
# Please consider joining the pool (https://www.pool.ntp.org/join.html).
|
||||
pool pool.ntp.org iburst
|
||||
|
||||
# Record the rate at which the system clock gains/losses time.
|
||||
|
||||
2
keys.c
2
keys.c
@@ -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
28
local.c
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
|
||||
48
main.c
48
main.c
@@ -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
|
||||
@@ -374,8 +374,34 @@ go_daemon(void)
|
||||
static void
|
||||
print_help(const char *progname)
|
||||
{
|
||||
printf("Usage: %s [-4|-6] [-n|-d] [-p|-q|-Q] [-r] [-R] [-s] [-t TIMEOUT] [-f FILE|COMMAND...]\n",
|
||||
progname);
|
||||
printf("Usage: %s [OPTION]... [DIRECTIVE]...\n\n"
|
||||
"Options:\n"
|
||||
" -4\t\tUse IPv4 addresses only\n"
|
||||
" -6\t\tUse IPv6 addresses only\n"
|
||||
" -f FILE\tSpecify configuration file (%s)\n"
|
||||
" -n\t\tDon't run as daemon\n"
|
||||
" -d\t\tDon't run as daemon and log to stderr\n"
|
||||
#if DEBUG > 0
|
||||
" -d -d\t\tEnable debug messages\n"
|
||||
#endif
|
||||
" -l FILE\tLog to file\n"
|
||||
" -L LEVEL\tSet logging threshold (0)\n"
|
||||
" -p\t\tPrint configuration and exit\n"
|
||||
" -q\t\tSet clock and exit\n"
|
||||
" -Q\t\tLog offset and exit\n"
|
||||
" -r\t\tReload dump files\n"
|
||||
" -R\t\tAdapt configuration for restart\n"
|
||||
" -s\t\tSet clock from RTC\n"
|
||||
" -t SECONDS\tExit after elapsed time\n"
|
||||
" -u USER\tSpecify user (%s)\n"
|
||||
" -U\t\tDon't check for root\n"
|
||||
" -F LEVEL\tSet system call filter level (0)\n"
|
||||
" -P PRIORITY\tSet process priority (0)\n"
|
||||
" -m\t\tLock memory\n"
|
||||
" -x\t\tDon't control clock\n"
|
||||
" -v, --version\tPrint version and exit\n"
|
||||
" -h, --help\tPrint usage and exit\n",
|
||||
progname, DEFAULT_CONF_FILE, DEFAULT_USER);
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
@@ -411,13 +437,13 @@ 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();
|
||||
|
||||
LOG_Initialise();
|
||||
|
||||
/* Parse (undocumented) long command-line options */
|
||||
/* Parse long command-line options */
|
||||
for (optind = 1; optind < argc; optind++) {
|
||||
if (!strcmp("--help", argv[optind])) {
|
||||
print_help(progname);
|
||||
@@ -431,7 +457,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 +488,7 @@ int main
|
||||
break;
|
||||
case 'p':
|
||||
print_config = 1;
|
||||
client_only = 1;
|
||||
user_check = 0;
|
||||
nofork = 1;
|
||||
system_log = 0;
|
||||
break;
|
||||
@@ -479,6 +505,7 @@ int main
|
||||
ref_mode = REF_ModePrintOnce;
|
||||
nofork = 1;
|
||||
client_only = 1;
|
||||
user_check = 0;
|
||||
clock_control = 0;
|
||||
system_log = 0;
|
||||
break;
|
||||
@@ -497,6 +524,9 @@ int main
|
||||
case 'u':
|
||||
user = optarg;
|
||||
break;
|
||||
case 'U':
|
||||
user_check = 0;
|
||||
break;
|
||||
case 'v':
|
||||
print_version();
|
||||
return 0;
|
||||
@@ -509,7 +539,7 @@ int main
|
||||
}
|
||||
}
|
||||
|
||||
if (getuid() && !client_only)
|
||||
if (user_check && getuid() != 0)
|
||||
LOG_FATAL("Not superuser");
|
||||
|
||||
/* Turn into a daemon */
|
||||
@@ -595,7 +625,7 @@ int main
|
||||
|
||||
/* Drop root privileges if the specified user has a non-zero UID */
|
||||
if (!geteuid() && (pw->pw_uid || pw->pw_gid))
|
||||
SYS_DropRoot(pw->pw_uid, pw->pw_gid);
|
||||
SYS_DropRoot(pw->pw_uid, pw->pw_gid, SYS_MAIN_PROCESS);
|
||||
|
||||
REF_Initialise();
|
||||
SST_Initialise();
|
||||
|
||||
5
ntp.h
5
ntp.h
@@ -116,10 +116,11 @@ typedef struct {
|
||||
/* Enumeration for authentication modes of NTP packets */
|
||||
typedef enum {
|
||||
NTP_AUTH_NONE = 0, /* No authentication */
|
||||
NTP_AUTH_SYMMETRIC, /* MAC using symmetric key (RFC 1305, RFC 5905) */
|
||||
NTP_AUTH_SYMMETRIC, /* NTP MAC or CMAC using a symmetric key
|
||||
(RFC 1305, RFC 5905, RFC 8573) */
|
||||
NTP_AUTH_MSSNTP, /* MS-SNTP authenticator field */
|
||||
NTP_AUTH_MSSNTP_EXT, /* MS-SNTP extended authenticator field */
|
||||
NTP_AUTH_NTS, /* Network Time Security (RFC ????) */
|
||||
NTP_AUTH_NTS, /* Network Time Security (RFC 8915) */
|
||||
} NTP_AuthMode;
|
||||
|
||||
/* Structure describing an NTP packet */
|
||||
|
||||
21
ntp_auth.c
21
ntp_auth.c
@@ -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
|
||||
@@ -175,7 +175,7 @@ NAU_CreateNtsInstance(IPSockAddr *nts_address, const char *name, const IPSockAdd
|
||||
void
|
||||
NAU_DestroyInstance(NAU_Instance instance)
|
||||
{
|
||||
if (instance->nts)
|
||||
if (instance->mode == NTP_AUTH_NTS)
|
||||
NNC_DestroyInstance(instance->nts);
|
||||
Free(instance);
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
14
ntp_core.c
14
ntp_core.c
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
2
ntp_io.c
2
ntp_io.c
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -444,8 +444,8 @@ process_resolved_name(struct UnresolvedSource *us, IPAddr *ip_addrs, int n_addrs
|
||||
DEBUG_LOG("(%d) %s", i + 1, UTI_IPToString(&new_addr.ip_addr));
|
||||
|
||||
if (us->pool_id != INVALID_POOL) {
|
||||
/* In the pool resolving mode, try to replace all sources from
|
||||
the pool which don't have a real address yet */
|
||||
/* In the pool resolving mode, try to replace a source from
|
||||
the pool which does not have a real address yet */
|
||||
for (j = 0; j < ARR_GetSize(records); j++) {
|
||||
record = get_record(j);
|
||||
if (!record->remote_addr || record->pool_id != us->pool_id ||
|
||||
@@ -454,7 +454,8 @@ process_resolved_name(struct UnresolvedSource *us, IPAddr *ip_addrs, int n_addrs
|
||||
old_addr = *record->remote_addr;
|
||||
new_addr.port = old_addr.port;
|
||||
if (replace_source_connectable(&old_addr, &new_addr))
|
||||
break;
|
||||
;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
new_addr.port = us->address.port;
|
||||
@@ -671,7 +672,7 @@ NSR_AddSourceByName(char *name, int port, int pool, NTP_Source_Type type,
|
||||
|
||||
/* Make sure the name is at least printable and has no spaces */
|
||||
for (i = 0; name[i] != '\0'; i++) {
|
||||
if (!isgraph(name[i]))
|
||||
if (!isgraph((unsigned char)name[i]))
|
||||
return NSR_InvalidName;
|
||||
}
|
||||
|
||||
|
||||
@@ -196,7 +196,7 @@ process_response(NKC_Instance inst)
|
||||
inst->server_name[length] = '\0';
|
||||
|
||||
/* Make sure the name is printable and has no spaces */
|
||||
for (i = 0; i < length && isgraph(inst->server_name[i]); i++)
|
||||
for (i = 0; i < length && isgraph((unsigned char)inst->server_name[i]); i++)
|
||||
;
|
||||
if (i != length) {
|
||||
DEBUG_LOG("Invalid server name");
|
||||
@@ -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);
|
||||
|
||||
@@ -556,7 +556,7 @@ error:
|
||||
|
||||
#define MAX_WORDS 2
|
||||
|
||||
static void
|
||||
static int
|
||||
load_keys(void)
|
||||
{
|
||||
char *dump_dir, line[1024], *words[MAX_WORDS];
|
||||
@@ -568,11 +568,11 @@ load_keys(void)
|
||||
|
||||
dump_dir = CNF_GetNtsDumpDir();
|
||||
if (!dump_dir)
|
||||
return;
|
||||
return 0;
|
||||
|
||||
f = UTI_OpenFile(dump_dir, DUMP_FILENAME, NULL, 'r', 0);
|
||||
if (!f)
|
||||
return;
|
||||
return 0;
|
||||
|
||||
if (!fgets(line, sizeof (line), f) || strcmp(line, DUMP_IDENTIFIER) != 0 ||
|
||||
!fgets(line, sizeof (line), f) || UTI_SplitString(line, words, MAX_WORDS) != 2 ||
|
||||
@@ -607,11 +607,13 @@ load_keys(void)
|
||||
|
||||
fclose(f);
|
||||
|
||||
return;
|
||||
return 1;
|
||||
|
||||
error:
|
||||
DEBUG_LOG("Could not %s server keys", "load");
|
||||
fclose(f);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
@@ -646,7 +648,7 @@ run_helper(uid_t uid, gid_t gid, int scfilter_level)
|
||||
LOG_SetMinSeverity(log_severity);
|
||||
|
||||
if (!geteuid() && (uid || gid))
|
||||
SYS_DropRoot(uid, gid);
|
||||
SYS_DropRoot(uid, gid, SYS_NTSKE_HELPER);
|
||||
|
||||
NKS_Initialise();
|
||||
|
||||
@@ -764,10 +766,12 @@ NKS_Initialise(void)
|
||||
server_sock_fd4 = open_socket(IPADDR_INET4);
|
||||
server_sock_fd6 = open_socket(IPADDR_INET6);
|
||||
|
||||
load_keys();
|
||||
|
||||
key_rotation_interval = MAX(CNF_GetNtsRotate(), 0);
|
||||
|
||||
/* Reload saved keys, or save the new keys */
|
||||
if (!load_keys())
|
||||
save_keys();
|
||||
|
||||
if (key_rotation_interval > 0) {
|
||||
key_delay = key_rotation_interval - (SCH_GetLastEventMonoTime() - last_server_key_ts);
|
||||
SCH_AddTimeoutByDelay(MAX(key_delay, 0.0), key_timeout, NULL);
|
||||
|
||||
@@ -825,21 +825,27 @@ NKSN_GetRecord(NKSN_Instance inst, int *critical, int *type, int *body_length,
|
||||
int
|
||||
NKSN_GetKeys(NKSN_Instance inst, SIV_Algorithm siv, NKE_Key *c2s, NKE_Key *s2c)
|
||||
{
|
||||
c2s->length = SIV_GetKeyLength(siv);
|
||||
s2c->length = SIV_GetKeyLength(siv);
|
||||
assert(c2s->length <= sizeof (c2s->key));
|
||||
assert(s2c->length <= sizeof (s2c->key));
|
||||
int length = SIV_GetKeyLength(siv);
|
||||
|
||||
if (length <= 0 || length > sizeof (c2s->key) || length > sizeof (s2c->key)) {
|
||||
DEBUG_LOG("Invalid algorithm");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (gnutls_prf_rfc5705(inst->tls_session,
|
||||
sizeof (NKE_EXPORTER_LABEL) - 1, NKE_EXPORTER_LABEL,
|
||||
sizeof (NKE_EXPORTER_CONTEXT_C2S) - 1, NKE_EXPORTER_CONTEXT_C2S,
|
||||
c2s->length, (char *)c2s->key) < 0)
|
||||
return 0;
|
||||
if (gnutls_prf_rfc5705(inst->tls_session,
|
||||
length, (char *)c2s->key) < 0 ||
|
||||
gnutls_prf_rfc5705(inst->tls_session,
|
||||
sizeof (NKE_EXPORTER_LABEL) - 1, NKE_EXPORTER_LABEL,
|
||||
sizeof (NKE_EXPORTER_CONTEXT_S2C) - 1, NKE_EXPORTER_CONTEXT_S2C,
|
||||
s2c->length, (char *)s2c->key) < 0)
|
||||
length, (char *)s2c->key) < 0) {
|
||||
DEBUG_LOG("Could not export key");
|
||||
return 0;
|
||||
}
|
||||
|
||||
c2s->length = length;
|
||||
s2c->length = length;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -112,6 +112,7 @@ NNA_GenerateAuthEF(NTP_Packet *packet, NTP_PacketInfo *info, SIV_Instance siv,
|
||||
if (!SIV_Encrypt(siv, nonce, nonce_length, packet, assoc_length,
|
||||
plaintext, plaintext_length, ciphertext, ciphertext_length)) {
|
||||
DEBUG_LOG("SIV encrypt failed");
|
||||
info->length = assoc_length;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
@@ -266,8 +273,6 @@ get_cookies(NNC_Instance inst)
|
||||
inst->last_nke_success = now;
|
||||
inst->cookie_index = 0;
|
||||
|
||||
inst->nak_response = 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -276,6 +281,13 @@ get_cookies(NNC_Instance inst)
|
||||
int
|
||||
NNC_PrepareForAuth(NNC_Instance inst)
|
||||
{
|
||||
inst->auth_ready = 0;
|
||||
|
||||
/* Prepare data for the next request and invalidate any responses to the
|
||||
previous request */
|
||||
UTI_GetRandomBytes(inst->uniq_id, sizeof (inst->uniq_id));
|
||||
UTI_GetRandomBytes(inst->nonce, sizeof (inst->nonce));
|
||||
|
||||
/* Try to reload saved keys and cookies (once for the NTS-KE address) */
|
||||
if (!inst->load_attempt) {
|
||||
load_cookies(inst);
|
||||
@@ -288,6 +300,8 @@ NNC_PrepareForAuth(NNC_Instance inst)
|
||||
return 0;
|
||||
}
|
||||
|
||||
inst->nak_response = 0;
|
||||
|
||||
if (!inst->siv)
|
||||
inst->siv = SIV_CreateInstance(inst->context.algorithm);
|
||||
|
||||
@@ -297,9 +311,7 @@ NNC_PrepareForAuth(NNC_Instance inst)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Prepare data for NNC_GenerateRequestAuth() */
|
||||
UTI_GetRandomBytes(inst->uniq_id, sizeof (inst->uniq_id));
|
||||
UTI_GetRandomBytes(inst->nonce, sizeof (inst->nonce));
|
||||
inst->auth_ready = 1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -314,14 +326,22 @@ 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)
|
||||
return 0;
|
||||
|
||||
inst->auth_ready = 0;
|
||||
|
||||
if (inst->num_cookies <= 0 || !inst->siv)
|
||||
return 0;
|
||||
|
||||
if (info->mode != MODE_CLIENT)
|
||||
return 0;
|
||||
|
||||
cookie = &inst->cookies[inst->cookie_index];
|
||||
req_cookies = MIN(NTS_MAX_COOKIES - inst->num_cookies + 1,
|
||||
inst->num_cookies--;
|
||||
inst->cookie_index = (inst->cookie_index + 1) % NTS_MAX_COOKIES;
|
||||
|
||||
req_cookies = MIN(NTS_MAX_COOKIES - inst->num_cookies,
|
||||
MAX_TOTAL_COOKIE_LENGTH / (cookie->length + 4));
|
||||
|
||||
if (!NEF_AddField(packet, info, NTP_EF_NTS_UNIQUE_IDENTIFIER,
|
||||
@@ -343,9 +363,6 @@ NNC_GenerateRequestAuth(NNC_Instance inst, NTP_Packet *packet,
|
||||
(const unsigned char *)"", 0, NTP_MAX_V4_MAC_LENGTH + 4))
|
||||
return 0;
|
||||
|
||||
inst->num_cookies--;
|
||||
inst->cookie_index = (inst->cookie_index + 1) % NTS_MAX_COOKIES;
|
||||
inst->nak_response = 0;
|
||||
inst->ok_response = 0;
|
||||
|
||||
return 1;
|
||||
@@ -427,7 +444,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 +523,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);
|
||||
@@ -529,7 +541,7 @@ save_cookies(NNC_Instance inst)
|
||||
FILE *f;
|
||||
int i;
|
||||
|
||||
if (inst->num_cookies < 1 || !UTI_IsIPReal(&inst->nts_address.ip_addr))
|
||||
if (inst->num_cookies < 1 || !inst->name || !UTI_IsIPReal(&inst->nts_address.ip_addr))
|
||||
return;
|
||||
|
||||
dump_dir = CNF_GetNtsDumpDir();
|
||||
@@ -546,9 +558,10 @@ save_cookies(NNC_Instance inst)
|
||||
context_time = inst->last_nke_success - SCH_GetLastEventMonoTime();
|
||||
context_time += UTI_TimespecToDouble(&now);
|
||||
|
||||
if (fprintf(f, "%s%.1f\n%s %d\n%u %d ",
|
||||
DUMP_IDENTIFIER, context_time, UTI_IPToString(&inst->ntp_address->ip_addr),
|
||||
inst->ntp_address->port, inst->context_id, (int)inst->context.algorithm) < 0 ||
|
||||
if (fprintf(f, "%s%s\n%.1f\n%s %d\n%u %d ",
|
||||
DUMP_IDENTIFIER, inst->name, context_time,
|
||||
UTI_IPToString(&inst->ntp_address->ip_addr), inst->ntp_address->port,
|
||||
inst->context_id, (int)inst->context.algorithm) < 0 ||
|
||||
!UTI_BytesToHex(inst->context.s2c.key, inst->context.s2c.length, buf, sizeof (buf)) ||
|
||||
fprintf(f, "%s ", buf) < 0 ||
|
||||
!UTI_BytesToHex(inst->context.c2s.key, inst->context.c2s.length, buf, sizeof (buf)) ||
|
||||
@@ -609,6 +622,8 @@ load_cookies(NNC_Instance inst)
|
||||
inst->siv = NULL;
|
||||
|
||||
if (!fgets(line, sizeof (line), f) || strcmp(line, DUMP_IDENTIFIER) != 0 ||
|
||||
!fgets(line, sizeof (line), f) || UTI_SplitString(line, words, MAX_WORDS) != 1 ||
|
||||
!inst->name || strcmp(words[0], inst->name) != 0 ||
|
||||
!fgets(line, sizeof (line), f) || UTI_SplitString(line, words, MAX_WORDS) != 1 ||
|
||||
sscanf(words[0], "%lf", &context_time) != 1 ||
|
||||
!fgets(line, sizeof (line), f) || UTI_SplitString(line, words, MAX_WORDS) != 2 ||
|
||||
|
||||
@@ -96,11 +96,11 @@ NNS_CheckRequestAuth(NTP_Packet *packet, NTP_PacketInfo *info, uint32_t *kod)
|
||||
NKE_Cookie cookie;
|
||||
void *ef_body;
|
||||
|
||||
*kod = 0;
|
||||
|
||||
if (!server)
|
||||
return 0;
|
||||
|
||||
*kod = 0;
|
||||
|
||||
server->num_cookies = 0;
|
||||
server->req_tx = packet->transmit_ts;
|
||||
|
||||
|
||||
@@ -181,7 +181,7 @@ RCL_AddRefclock(RefclockParameters *params)
|
||||
LOG_FATAL("refclock tai option requires leapsectz");
|
||||
|
||||
inst->data = NULL;
|
||||
inst->driver_parameter = params->driver_parameter;
|
||||
inst->driver_parameter = Strdup(params->driver_parameter);
|
||||
inst->driver_parameter_length = 0;
|
||||
inst->driver_poll = params->driver_poll;
|
||||
inst->poll = params->poll;
|
||||
@@ -261,8 +261,6 @@ RCL_AddRefclock(RefclockParameters *params)
|
||||
params->driver_name, UTI_RefidToString(inst->ref_id),
|
||||
inst->poll, inst->driver_poll, params->filter_length);
|
||||
|
||||
Free(params->driver_name);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
10
reports.h
10
reports.h
@@ -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 */
|
||||
@@ -183,6 +190,7 @@ typedef struct {
|
||||
IPAddr ip_addr;
|
||||
char state_char;
|
||||
int authentication;
|
||||
NTP_Leap leap;
|
||||
int conf_options;
|
||||
int eff_options;
|
||||
uint32_t last_sample_ago;
|
||||
|
||||
4
sched.c
4
sched.c
@@ -799,14 +799,14 @@ SCH_MainLoop(void)
|
||||
LCL_ReadRawTime(&now);
|
||||
LCL_CookTime(&now, &cooked, &err);
|
||||
|
||||
update_monotonic_time(&now, &last_select_ts_raw);
|
||||
|
||||
/* Check if the time didn't jump unexpectedly */
|
||||
if (!check_current_time(&saved_now, &now, status == 0, &saved_tv, ptv)) {
|
||||
/* Cook the time again after handling the step */
|
||||
LCL_CookTime(&now, &cooked, &err);
|
||||
}
|
||||
|
||||
update_monotonic_time(&cooked, &last_select_ts);
|
||||
|
||||
last_select_ts_raw = now;
|
||||
last_select_ts = cooked;
|
||||
last_select_ts_err = err;
|
||||
|
||||
@@ -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;
|
||||
|
||||
10
siv_nettle.c
10
siv_nettle.c
@@ -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)
|
||||
|
||||
74
socket.c
74
socket.c
@@ -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
|
||||
@@ -742,18 +742,10 @@ process_header(struct msghdr *msg, int msg_length, int sock_fd, int flags,
|
||||
SCK_Message *message)
|
||||
{
|
||||
struct cmsghdr *cmsg;
|
||||
int r = 1;
|
||||
|
||||
if (msg->msg_iovlen != 1) {
|
||||
DEBUG_LOG("Unexpected iovlen");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (msg->msg_namelen > sizeof (union sockaddr_all)) {
|
||||
DEBUG_LOG("Truncated source address");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (msg->msg_namelen > sizeof (((struct sockaddr *)msg->msg_name)->sa_family)) {
|
||||
if (msg->msg_namelen <= sizeof (union sockaddr_all) &&
|
||||
msg->msg_namelen > sizeof (((struct sockaddr *)msg->msg_name)->sa_family)) {
|
||||
switch (((struct sockaddr *)msg->msg_name)->sa_family) {
|
||||
case AF_INET:
|
||||
#ifdef FEAT_IPV6
|
||||
@@ -767,26 +759,38 @@ process_header(struct msghdr *msg, int msg_length, int sock_fd, int flags,
|
||||
message->remote_addr.path = ((struct sockaddr_un *)msg->msg_name)->sun_path;
|
||||
break;
|
||||
default:
|
||||
init_message_addresses(message, SCK_ADDR_UNSPEC);
|
||||
DEBUG_LOG("Unexpected address");
|
||||
return 0;
|
||||
r = 0;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
init_message_addresses(message, SCK_ADDR_UNSPEC);
|
||||
|
||||
if (msg->msg_namelen > sizeof (union sockaddr_all)) {
|
||||
DEBUG_LOG("Truncated source address");
|
||||
r = 0;
|
||||
}
|
||||
}
|
||||
|
||||
init_message_nonaddress(message);
|
||||
|
||||
message->data = msg->msg_iov[0].iov_base;
|
||||
message->length = msg_length;
|
||||
if (msg->msg_iovlen == 1) {
|
||||
message->data = msg->msg_iov[0].iov_base;
|
||||
message->length = msg_length;
|
||||
} else {
|
||||
DEBUG_LOG("Unexpected iovlen");
|
||||
r = 0;
|
||||
}
|
||||
|
||||
if (msg->msg_flags & MSG_TRUNC) {
|
||||
log_message(sock_fd, 1, message, "Truncated", NULL);
|
||||
return 0;
|
||||
r = 0;
|
||||
}
|
||||
|
||||
if (msg->msg_flags & MSG_CTRUNC) {
|
||||
log_message(sock_fd, 1, message, "Truncated cmsg in", NULL);
|
||||
return 0;
|
||||
r = 0;
|
||||
}
|
||||
|
||||
for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) {
|
||||
@@ -873,25 +877,31 @@ process_header(struct msghdr *msg, int msg_length, int sock_fd, int flags,
|
||||
if (err.ee_errno != ENOMSG || err.ee_info != SCM_TSTAMP_SND ||
|
||||
err.ee_origin != SO_EE_ORIGIN_TIMESTAMPING) {
|
||||
log_message(sock_fd, 1, message, "Unexpected extended error in", NULL);
|
||||
return 0;
|
||||
r = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
|
||||
if (!(flags & SCK_FLAG_MSG_DESCRIPTOR) || cmsg->cmsg_len != CMSG_LEN(sizeof (int))) {
|
||||
unsigned int i;
|
||||
int i, fd;
|
||||
|
||||
DEBUG_LOG("Unexpected SCM_RIGHTS");
|
||||
for (i = 0; CMSG_LEN((i + 1) * sizeof (int)) <= cmsg->cmsg_len; i++)
|
||||
close(((int *)CMSG_DATA(cmsg))[i]);
|
||||
return 0;
|
||||
for (i = 0; CMSG_LEN((i + 1) * sizeof (int)) <= cmsg->cmsg_len; i++) {
|
||||
memcpy(&fd, (char *)CMSG_DATA(cmsg) + i * sizeof (int), sizeof (fd));
|
||||
close(fd);
|
||||
}
|
||||
r = 0;
|
||||
} else {
|
||||
memcpy(&message->descriptor, CMSG_DATA(cmsg), sizeof (message->descriptor));
|
||||
}
|
||||
message->descriptor = *(int *)CMSG_DATA(cmsg);
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
if (!r && message->descriptor != INVALID_SOCK_FD)
|
||||
close(message->descriptor);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
@@ -901,7 +911,7 @@ receive_messages(int sock_fd, int flags, int max_messages, int *num_messages)
|
||||
{
|
||||
struct MessageHeader *hdr;
|
||||
SCK_Message *messages;
|
||||
unsigned int i, n;
|
||||
unsigned int i, n, n_ok;
|
||||
int ret, recv_flags = 0;
|
||||
|
||||
assert(initialised);
|
||||
@@ -945,18 +955,20 @@ receive_messages(int sock_fd, int flags, int max_messages, int *num_messages)
|
||||
|
||||
received_messages = n;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
for (i = n_ok = 0; i < n; i++) {
|
||||
hdr = ARR_GetElement(recv_headers, i);
|
||||
if (!process_header(&hdr->msg_hdr, hdr->msg_len, sock_fd, flags, &messages[i]))
|
||||
return NULL;
|
||||
if (!process_header(&hdr->msg_hdr, hdr->msg_len, sock_fd, flags, &messages[n_ok]))
|
||||
continue;
|
||||
|
||||
log_message(sock_fd, 1, &messages[i],
|
||||
log_message(sock_fd, 1, &messages[n_ok],
|
||||
flags & SCK_FLAG_MSG_ERRQUEUE ? "Received error" : "Received", NULL);
|
||||
|
||||
n_ok++;
|
||||
}
|
||||
|
||||
*num_messages = n;
|
||||
*num_messages = n_ok;
|
||||
|
||||
return messages;
|
||||
return n_ok > 0 ? messages : NULL;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
12
sources.c
12
sources.c
@@ -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;
|
||||
}
|
||||
|
||||
@@ -1611,6 +1610,7 @@ SRC_GetSelectReport(int index, RPT_SelectReport *report)
|
||||
report->ip_addr.family = IPADDR_UNSPEC;
|
||||
report->state_char = get_status_char(inst->status);
|
||||
report->authentication = inst->authenticated;
|
||||
report->leap = inst->leap;
|
||||
report->conf_options = inst->conf_sel_options;
|
||||
report->eff_options = inst->sel_options;
|
||||
report->last_sample_ago = inst->sel_info.last_sample_ago;
|
||||
|
||||
2
stubs.c
2
stubs.c
@@ -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 */
|
||||
|
||||
|
||||
12
sys.c
12
sys.c
@@ -97,16 +97,16 @@ SYS_Finalise(void)
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
void SYS_DropRoot(uid_t uid, gid_t gid)
|
||||
void SYS_DropRoot(uid_t uid, gid_t gid, SYS_ProcessContext context)
|
||||
{
|
||||
#if defined(LINUX) && defined (FEAT_PRIVDROP)
|
||||
SYS_Linux_DropRoot(uid, gid, !null_driver);
|
||||
SYS_Linux_DropRoot(uid, gid, context, !null_driver);
|
||||
#elif defined(SOLARIS) && defined(FEAT_PRIVDROP)
|
||||
SYS_Solaris_DropRoot(uid, gid);
|
||||
SYS_Solaris_DropRoot(uid, gid, context);
|
||||
#elif (defined(NETBSD) || defined(FREEBSD)) && defined(FEAT_PRIVDROP)
|
||||
SYS_NetBSD_DropRoot(uid, gid);
|
||||
SYS_NetBSD_DropRoot(uid, gid, context, !null_driver);
|
||||
#elif defined(MACOSX) && defined(FEAT_PRIVDROP)
|
||||
SYS_MacOSX_DropRoot(uid, gid);
|
||||
SYS_MacOSX_DropRoot(uid, gid, context);
|
||||
#else
|
||||
LOG_FATAL("dropping root privileges not supported");
|
||||
#endif
|
||||
@@ -114,7 +114,7 @@ void SYS_DropRoot(uid_t uid, gid_t gid)
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
void SYS_EnableSystemCallFilter(int level, SYS_SystemCallContext context)
|
||||
void SYS_EnableSystemCallFilter(int level, SYS_ProcessContext context)
|
||||
{
|
||||
#if defined(LINUX) && defined(FEAT_SCFILTER)
|
||||
SYS_Linux_EnableSystemCallFilter(level, context);
|
||||
|
||||
10
sys.h
10
sys.h
@@ -35,17 +35,17 @@ extern void SYS_Initialise(int clock_control);
|
||||
/* Called at the end of the run to do final clean-up */
|
||||
extern void SYS_Finalise(void);
|
||||
|
||||
/* Drop root privileges to the specified user and group */
|
||||
extern void SYS_DropRoot(uid_t uid, gid_t gid);
|
||||
|
||||
typedef enum {
|
||||
SYS_MAIN_PROCESS,
|
||||
SYS_NTSKE_HELPER,
|
||||
} SYS_SystemCallContext;
|
||||
} SYS_ProcessContext;
|
||||
|
||||
/* Switch to the specified user and group in given context */
|
||||
extern void SYS_DropRoot(uid_t uid, gid_t gid, SYS_ProcessContext context);
|
||||
|
||||
/* Enable a system call filter to allow only system calls
|
||||
which chronyd normally needs after initialization */
|
||||
extern void SYS_EnableSystemCallFilter(int level, SYS_SystemCallContext context);
|
||||
extern void SYS_EnableSystemCallFilter(int level, SYS_ProcessContext context);
|
||||
|
||||
extern void SYS_SetScheduler(int SchedPriority);
|
||||
extern void SYS_LockMemory(void);
|
||||
|
||||
25
sys_linux.c
25
sys_linux.c
@@ -426,7 +426,7 @@ SYS_Linux_Finalise(void)
|
||||
|
||||
#ifdef FEAT_PRIVDROP
|
||||
void
|
||||
SYS_Linux_DropRoot(uid_t uid, gid_t gid, int clock_control)
|
||||
SYS_Linux_DropRoot(uid_t uid, gid_t gid, SYS_ProcessContext context, int clock_control)
|
||||
{
|
||||
char cap_text[256];
|
||||
cap_t cap;
|
||||
@@ -437,16 +437,23 @@ 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);
|
||||
|
||||
/* Helpers don't need any capabilities */
|
||||
if (context != SYS_MAIN_PROCESS)
|
||||
cap_text[0] = '\0';
|
||||
|
||||
if ((cap = cap_from_text(cap_text)) == NULL) {
|
||||
LOG_FATAL("cap_from_text() failed");
|
||||
}
|
||||
@@ -477,7 +484,7 @@ void check_seccomp_applicability(void)
|
||||
/* ================================================== */
|
||||
|
||||
void
|
||||
SYS_Linux_EnableSystemCallFilter(int level, SYS_SystemCallContext context)
|
||||
SYS_Linux_EnableSystemCallFilter(int level, SYS_ProcessContext context)
|
||||
{
|
||||
const int syscalls[] = {
|
||||
/* Clock */
|
||||
@@ -533,7 +540,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),
|
||||
|
||||
@@ -33,9 +33,9 @@ extern void SYS_Linux_Initialise(void);
|
||||
|
||||
extern void SYS_Linux_Finalise(void);
|
||||
|
||||
extern void SYS_Linux_DropRoot(uid_t uid, gid_t gid, int clock_control);
|
||||
extern void SYS_Linux_DropRoot(uid_t uid, gid_t gid, SYS_ProcessContext context, int clock_control);
|
||||
|
||||
extern void SYS_Linux_EnableSystemCallFilter(int level, SYS_SystemCallContext context);
|
||||
extern void SYS_Linux_EnableSystemCallFilter(int level, SYS_ProcessContext context);
|
||||
|
||||
extern int SYS_Linux_CheckKernelVersion(int req_major, int req_minor);
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -415,9 +415,10 @@ SYS_MacOSX_SetScheduler(int SchedPriority)
|
||||
/* ================================================== */
|
||||
|
||||
#ifdef FEAT_PRIVDROP
|
||||
void SYS_MacOSX_DropRoot(uid_t uid, gid_t gid)
|
||||
void SYS_MacOSX_DropRoot(uid_t uid, gid_t gid, SYS_ProcessContext context)
|
||||
{
|
||||
PRV_StartHelper();
|
||||
if (context == SYS_MAIN_PROCESS)
|
||||
PRV_StartHelper();
|
||||
|
||||
UTI_DropRoot(uid, gid);
|
||||
}
|
||||
|
||||
@@ -30,8 +30,10 @@
|
||||
#ifndef GOT_SYS_MACOSX_H
|
||||
#define GOT_SYS_MACOSX_H
|
||||
|
||||
#include "sys.h"
|
||||
|
||||
void SYS_MacOSX_SetScheduler(int SchedPriority);
|
||||
void SYS_MacOSX_DropRoot(uid_t uid, gid_t gid);
|
||||
void SYS_MacOSX_DropRoot(uid_t uid, gid_t gid, SYS_ProcessContext context);
|
||||
void SYS_MacOSX_Initialise(void);
|
||||
void SYS_MacOSX_Finalise(void);
|
||||
|
||||
|
||||
@@ -131,7 +131,7 @@ SYS_NetBSD_Finalise(void)
|
||||
|
||||
#ifdef FEAT_PRIVDROP
|
||||
void
|
||||
SYS_NetBSD_DropRoot(uid_t uid, gid_t gid)
|
||||
SYS_NetBSD_DropRoot(uid_t uid, gid_t gid, SYS_ProcessContext context, int clock_control)
|
||||
{
|
||||
#ifdef NETBSD
|
||||
int fd;
|
||||
@@ -139,11 +139,15 @@ SYS_NetBSD_DropRoot(uid_t uid, gid_t gid)
|
||||
|
||||
/* On NetBSD the helper is used only for socket binding, but on FreeBSD
|
||||
it's used also for setting and adjusting the system clock */
|
||||
PRV_StartHelper();
|
||||
if (context == SYS_MAIN_PROCESS)
|
||||
PRV_StartHelper();
|
||||
|
||||
UTI_DropRoot(uid, gid);
|
||||
|
||||
#ifdef NETBSD
|
||||
if (!clock_control)
|
||||
return;
|
||||
|
||||
/* Check if we have write access to /dev/clockctl */
|
||||
fd = open("/dev/clockctl", O_WRONLY);
|
||||
if (fd < 0)
|
||||
|
||||
@@ -28,10 +28,12 @@
|
||||
#ifndef GOT_SYS_NETBSD_H
|
||||
#define GOT_SYS_NETBSD_H
|
||||
|
||||
#include "sys.h"
|
||||
|
||||
void SYS_NetBSD_Initialise(void);
|
||||
|
||||
void SYS_NetBSD_Finalise(void);
|
||||
|
||||
void SYS_NetBSD_DropRoot(uid_t uid, gid_t gid);
|
||||
void SYS_NetBSD_DropRoot(uid_t uid, gid_t gid, SYS_ProcessContext context, int clock_control);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -55,9 +55,10 @@ SYS_Solaris_Finalise(void)
|
||||
|
||||
#ifdef FEAT_PRIVDROP
|
||||
void
|
||||
SYS_Solaris_DropRoot(uid_t uid, gid_t gid)
|
||||
SYS_Solaris_DropRoot(uid_t uid, gid_t gid, SYS_ProcessContext context)
|
||||
{
|
||||
PRV_StartHelper();
|
||||
if (context == SYS_MAIN_PROCESS)
|
||||
PRV_StartHelper();
|
||||
UTI_DropRoot(uid, gid);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -27,10 +27,12 @@
|
||||
#ifndef GOT_SYS_SOLARIS_H
|
||||
#define GOT_SYS_SOLARIS_H
|
||||
|
||||
#include "sys.h"
|
||||
|
||||
void SYS_Solaris_Initialise(void);
|
||||
|
||||
void SYS_Solaris_Finalise(void);
|
||||
|
||||
void SYS_Solaris_DropRoot(uid_t uid, gid_t gid);
|
||||
void SYS_Solaris_DropRoot(uid_t uid, gid_t gid, SYS_ProcessContext context);
|
||||
|
||||
#endif
|
||||
|
||||
23
sys_timex.c
23
sys_timex.c
@@ -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);
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ check_file_messages "20.*123\.1.* 111 111 1111" 99 103 measurements.log || test_
|
||||
check_file_messages "20.*123\.1.* 111 001 0000" 0 0 measurements.log || test_fail
|
||||
check_file_messages " 2 1 .* 4460 " 350 390 log.packets || test_fail
|
||||
check_file_messages "." 6 6 ntskeys || test_fail
|
||||
check_file_messages "." 11 12 192.168.123.1.nts || test_fail
|
||||
check_file_messages "." 12 13 192.168.123.1.nts || test_fail
|
||||
rm -f tmp/measurements.log
|
||||
|
||||
export CLKNETSIM_START_DATE=$(date -d 'Jan 1 00:00:00 UTC 2010 + 40000 sec' +'%s')
|
||||
@@ -83,7 +83,7 @@ check_file_messages "20.*123\.1.* 111 001 0000" 0 0 measurements.log || test_fai
|
||||
check_file_messages " 2 1 .* 4460 " 6 10 log.packets || test_fail
|
||||
check_file_messages "^9\.......e+03 2 1 .* 4460 " 6 10 log.packets || test_fail
|
||||
check_file_messages "." 6 6 ntskeys || test_fail
|
||||
check_file_messages "." 11 12 192.168.123.1.nts || test_fail
|
||||
check_file_messages "." 12 13 192.168.123.1.nts || test_fail
|
||||
rm -f tmp/measurements.log
|
||||
|
||||
client_conf="
|
||||
|
||||
@@ -64,7 +64,7 @@ check_chronyc_output "^Name/IP address Mode KeyID Type KLen Last Atm
|
||||
run_chronyc "clients" || test_fail
|
||||
check_chronyc_output "^Hostname NTP Drop Int IntL Last Cmd Drop Int Last
|
||||
===============================================================================
|
||||
127\.0\.0\.1 [1-9] 0 - - [0-9] 0 0 - -$" \
|
||||
127\.0\.0\.1 [0-9 ]+ 0 [-0-9 ]+ - [0-9] 0 0 - -$" \
|
||||
|| test_fail
|
||||
|
||||
run_chronyc "ntpdata $server" || test_fail
|
||||
@@ -75,7 +75,7 @@ Leap status : Normal
|
||||
Version : 4
|
||||
Mode : Server
|
||||
Stratum : 10
|
||||
Poll interval : -6 \(0 seconds\)
|
||||
Poll interval : (-6|[0345]) \([0-9]+ seconds\)
|
||||
Precision : [0-9 +-]+ \(0\.[0-9]+ seconds\)
|
||||
Root delay : 0\.000000 seconds
|
||||
Root dispersion : 0\.000000 seconds
|
||||
@@ -96,9 +96,9 @@ Total RX : [0-9]+
|
||||
Total valid RX : [0-9]+$" || test_fail
|
||||
|
||||
run_chronyc "selectdata" || test_fail
|
||||
check_chronyc_output "^S Name/IP Address Auth COpts EOpts Last Score Interval +
|
||||
====================================================================
|
||||
M 127\.0\.0\.1 N ----- ----- 0 1\.0 \+0ns \+0ns$" || test_fail
|
||||
check_chronyc_output "^S Name/IP Address Auth COpts EOpts Last Score Interval Leap
|
||||
=======================================================================
|
||||
M 127\.0\.0\.1 N ----- ----- 0 1\.0 \+0ns \+0ns \?$" || test_fail
|
||||
|
||||
run_chronyc "serverstats" || test_fail
|
||||
check_chronyc_output "^NTP packets received : [0-9]+
|
||||
|
||||
305
test/unit/ntp_auth.c
Normal file
305
test/unit/ntp_auth.c
Normal 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
|
||||
@@ -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>
|
||||
@@ -72,7 +73,7 @@ get_random_key_id(void)
|
||||
uint32_t id;
|
||||
|
||||
do {
|
||||
id = random() % 6 + 2;
|
||||
id = random() % 8 + 2;
|
||||
} while (!KEY_KeyKnown(id));
|
||||
|
||||
return id;
|
||||
@@ -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
|
||||
|
||||
@@ -4,3 +4,5 @@
|
||||
5 SHA1 HEX:B71744EA01FBF01CA30D173ECDDF901952AE356A
|
||||
6 SHA512 HEX:DE027482F22B201FC20863F58C74095E7906089F
|
||||
7 SHA512 HEX:DE027482F22B201FC20863F58C74095E7906089F
|
||||
8 AES128 HEX:5D5E8A31D4B459A66D445259E147CFB5
|
||||
9 AES128 HEX:5D5E8A31D4B459A66D445259E147CFB5
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -81,6 +81,9 @@ test_unit(void)
|
||||
sample.root_dispersion = sample.peer_dispersion;
|
||||
sample.stratum = 1;
|
||||
|
||||
if (random() % 2)
|
||||
SRC_SetLeapStatus(srcs[j], random() % 4);
|
||||
|
||||
DEBUG_LOG("source %d sample %d offset %f delay %f disp %f", j, k,
|
||||
sample.offset, sample.peer_delay, sample.peer_dispersion);
|
||||
|
||||
@@ -132,6 +135,12 @@ test_unit(void)
|
||||
TEST_CHECK(!trusted || !passed || (passed_lo >= trusted_lo && passed_hi <= trusted_hi));
|
||||
TEST_CHECK(!passed || !trusted || trusted_passed >= 1);
|
||||
TEST_CHECK(!passed || !required || required_passed > 0);
|
||||
|
||||
for (l = 0; l <= j; l++) {
|
||||
TEST_CHECK(sources[l]->leap_vote ==
|
||||
(sources[l]->status >= SRC_NONPREFERRED &&
|
||||
(!trusted || sources[l]->sel_options & SRC_SELECT_TRUST)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -330,9 +330,12 @@ void test_unit(void) {
|
||||
TEST_CHECK(UTI_HexToBytes(buf, buf, sizeof (buf)) == 7);
|
||||
TEST_CHECK(memcmp(buf, "\xAB\x12\x34\x56\x78\x00\x01", 7) == 0);
|
||||
|
||||
TEST_CHECK(UTI_BytesToHex("", 0, buf, 0) == 0);
|
||||
TEST_CHECK(UTI_BytesToHex("\xAB\x12\x34\x56\x78\x00\x01", 7, buf, 14) == 0);
|
||||
TEST_CHECK(UTI_BytesToHex("\xAB\x12\x34\x56\x78\x00\x01", 7, buf, 15) == 1);
|
||||
TEST_CHECK(strcmp(buf, "AB123456780001") == 0);
|
||||
TEST_CHECK(UTI_BytesToHex("\xAB\x12\x34\x56\x78\x00\x01", 0, buf, 15) == 1);
|
||||
TEST_CHECK(strcmp(buf, "") == 0);
|
||||
|
||||
TEST_CHECK(snprintf(buf, sizeof (buf), "%s", "") < sizeof (buf));
|
||||
TEST_CHECK(UTI_SplitString(buf, words, 3) == 0);
|
||||
|
||||
7
util.c
7
util.c
@@ -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
|
||||
@@ -1417,6 +1417,11 @@ UTI_BytesToHex(const void *buf, unsigned int buf_len, char *hex, unsigned int he
|
||||
{
|
||||
unsigned int i, l;
|
||||
|
||||
if (hex_len < 1)
|
||||
return 0;
|
||||
|
||||
hex[0] = '\0';
|
||||
|
||||
for (i = l = 0; i < buf_len; i++, l += 2) {
|
||||
if (l + 2 >= hex_len ||
|
||||
snprintf(hex + l, hex_len - l, "%02hhX", ((const char *)buf)[i]) != 2)
|
||||
|
||||
Reference in New Issue
Block a user