mirror of
https://gitlab.com/chrony/chrony.git
synced 2025-12-04 04:25: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 authselectmode directive to control selection of unauthenticated sources
|
||||||
* Add binddevice, bindacqdevice, bindcmddevice directives
|
* Add binddevice, bindacqdevice, bindcmddevice directives
|
||||||
* Add confdir directive to better support fragmented configuration
|
* Add confdir directive to better support fragmented configuration
|
||||||
* Add sourcedir directive and "reload sources" command to support
|
* Add sourcedir directive and "reload sources" command to support dynamic
|
||||||
dynamic NTP sources specified in files
|
NTP sources specified in files
|
||||||
|
* Add clockprecision directive
|
||||||
* Add dscp directive to set Differentiated Services Code Point (DSCP)
|
* Add dscp directive to set Differentiated Services Code Point (DSCP)
|
||||||
* Add -L option to limit log messages by severity
|
* Add -L option to limit log messages by severity
|
||||||
* Add -p option to print whole configuration with included files
|
* Add -p option to print whole configuration with included files
|
||||||
|
* Add -U option to allow start under non-root user
|
||||||
* Allow maxsamples to be set to 1 for faster update with -q/-Q option
|
* Allow maxsamples to be set to 1 for faster update with -q/-Q option
|
||||||
* Avoid replacing NTP sources with sources that have unreachable address
|
* Avoid replacing NTP sources with sources that have unreachable address
|
||||||
* Improve pools to repeat name resolution to get "maxsources" sources
|
* Improve pools to repeat name resolution to get "maxsources" sources
|
||||||
@@ -38,6 +40,9 @@ Bug fixes
|
|||||||
Removed features
|
Removed features
|
||||||
----------------
|
----------------
|
||||||
* Drop support for RIPEMD keys (RMD128, RMD160, RMD256, RMD320)
|
* Drop support for RIPEMD keys (RMD128, RMD160, RMD256, RMD320)
|
||||||
|
* Drop support for long (non-standard) MACs in NTPv4 packets (chrony 2.x
|
||||||
|
clients using non-MD5/SHA1 keys need to use option "version 3")
|
||||||
|
* Drop support for line editing with GNU Readline
|
||||||
|
|
||||||
New in version 3.5.1
|
New in version 3.5.1
|
||||||
====================
|
====================
|
||||||
|
|||||||
11
candm.h
11
candm.h
@@ -553,12 +553,12 @@ typedef struct {
|
|||||||
#define RPY_SD_MD_PEER 1
|
#define RPY_SD_MD_PEER 1
|
||||||
#define RPY_SD_MD_REF 2
|
#define RPY_SD_MD_REF 2
|
||||||
|
|
||||||
#define RPY_SD_ST_SYNC 0
|
#define RPY_SD_ST_SELECTED 0
|
||||||
#define RPY_SD_ST_UNREACH 1
|
#define RPY_SD_ST_NONSELECTABLE 1
|
||||||
#define RPY_SD_ST_FALSETICKER 2
|
#define RPY_SD_ST_FALSETICKER 2
|
||||||
#define RPY_SD_ST_JITTERY 3
|
#define RPY_SD_ST_JITTERY 3
|
||||||
#define RPY_SD_ST_CANDIDATE 4
|
#define RPY_SD_ST_UNSELECTED 4
|
||||||
#define RPY_SD_ST_OUTLIER 5
|
#define RPY_SD_ST_SELECTABLE 5
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
IPAddr ip_addr;
|
IPAddr ip_addr;
|
||||||
@@ -764,7 +764,8 @@ typedef struct {
|
|||||||
IPAddr ip_addr;
|
IPAddr ip_addr;
|
||||||
uint8_t state_char;
|
uint8_t state_char;
|
||||||
uint8_t authentication;
|
uint8_t authentication;
|
||||||
uint8_t pad[2];
|
uint8_t leap;
|
||||||
|
uint8_t pad;
|
||||||
uint16_t conf_options;
|
uint16_t conf_options;
|
||||||
uint16_t eff_options;
|
uint16_t eff_options;
|
||||||
uint32_t last_sample_ago;
|
uint32_t last_sample_ago;
|
||||||
|
|||||||
91
client.c
91
client.c
@@ -4,7 +4,7 @@
|
|||||||
**********************************************************************
|
**********************************************************************
|
||||||
* Copyright (C) Richard P. Curnow 1997-2003
|
* Copyright (C) Richard P. Curnow 1997-2003
|
||||||
* Copyright (C) Lonnie Abelbeck 2016, 2018
|
* Copyright (C) Lonnie Abelbeck 2016, 2018
|
||||||
* Copyright (C) Miroslav Lichvar 2009-2018
|
* Copyright (C) Miroslav Lichvar 2009-2020
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of version 2 of the GNU General Public License as
|
* it under the terms of version 2 of the GNU General Public License as
|
||||||
@@ -44,12 +44,7 @@
|
|||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
#ifdef FEAT_READLINE
|
#ifdef FEAT_READLINE
|
||||||
#ifdef USE_EDITLINE
|
|
||||||
#include <editline/readline.h>
|
#include <editline/readline.h>
|
||||||
#else
|
|
||||||
#include <readline/readline.h>
|
|
||||||
#include <readline/history.h>
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
@@ -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
|
static void
|
||||||
process_cmd_doffset(CMD_Request *msg, char *line)
|
process_cmd_doffset(CMD_Request *msg, char *line)
|
||||||
{
|
{
|
||||||
|
struct timeval tv;
|
||||||
double doffset;
|
double doffset;
|
||||||
long sec, usec;
|
|
||||||
msg->command = htons(REQ_DOFFSET);
|
msg->command = htons(REQ_DOFFSET);
|
||||||
if (sscanf(line, "%lf", &doffset) == 1) {
|
if (sscanf(line, "%lf", &doffset) == 1) {
|
||||||
cvt_to_sec_usec(doffset, &sec, &usec);
|
UTI_DoubleToTimeval(doffset, &tv);
|
||||||
msg->data.doffset.sec = htonl(sec);
|
msg->data.doffset.sec = htonl(tv.tv_sec);
|
||||||
msg->data.doffset.usec = htonl(usec);
|
msg->data.doffset.usec = htonl(tv.tv_usec);
|
||||||
} else {
|
} else {
|
||||||
msg->data.doffset.sec = htonl(0);
|
msg->data.doffset.sec = htonl(0);
|
||||||
msg->data.doffset.usec = 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
|
#ifdef FEAT_READLINE
|
||||||
|
|
||||||
@@ -1887,19 +1863,19 @@ print_report(const char *format, ...)
|
|||||||
integer = va_arg(ap, int);
|
integer = va_arg(ap, int);
|
||||||
switch (integer) {
|
switch (integer) {
|
||||||
case LEAP_Normal:
|
case LEAP_Normal:
|
||||||
string = "Normal";
|
string = width != 1 ? "Normal" : "N";
|
||||||
break;
|
break;
|
||||||
case LEAP_InsertSecond:
|
case LEAP_InsertSecond:
|
||||||
string = "Insert second";
|
string = width != 1 ? "Insert second" : "+";
|
||||||
break;
|
break;
|
||||||
case LEAP_DeleteSecond:
|
case LEAP_DeleteSecond:
|
||||||
string = "Delete second";
|
string = width != 1 ? "Delete second" : "-";
|
||||||
break;
|
break;
|
||||||
case LEAP_Unsynchronised:
|
case LEAP_Unsynchronised:
|
||||||
string = "Not synchronised";
|
string = width != 1 ? "Not synchronised" : "?";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
string = "Invalid";
|
string = width != 1 ? "Invalid" : "?";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
printf("%s", string);
|
printf("%s", string);
|
||||||
@@ -2054,7 +2030,7 @@ get_source_name(IPAddr *ip_addr, char *buf, int size)
|
|||||||
|
|
||||||
/* Make sure the name is printable */
|
/* Make sure the name is printable */
|
||||||
for (i = 0; i < size && buf[i] != '\0'; i++) {
|
for (i = 0; i < size && buf[i] != '\0'; i++) {
|
||||||
if (!isgraph(buf[i]))
|
if (!isgraph((unsigned char)buf[i]))
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2146,8 +2122,8 @@ process_cmd_sources(char *line)
|
|||||||
if (verbose) {
|
if (verbose) {
|
||||||
printf("\n");
|
printf("\n");
|
||||||
printf(" .-- Source mode '^' = server, '=' = peer, '#' = local clock.\n");
|
printf(" .-- Source mode '^' = server, '=' = peer, '#' = local clock.\n");
|
||||||
printf(" / .- Source state '*' = current synced, '+' = combined , '-' = not combined,\n");
|
printf(" / .- Source state '*' = current best, '+' = combined, '-' = not combined,\n");
|
||||||
printf("| / '?' = unreachable, 'x' = time may be in error, '~' = time too variable.\n");
|
printf("| / 'x' = may be in error, '~' = too variable, '?' = unusable.\n");
|
||||||
printf("|| .- xxxx [ yyyy ] +/- zzzz\n");
|
printf("|| .- xxxx [ yyyy ] +/- zzzz\n");
|
||||||
printf("|| Reachability register (octal) -. | xxxx = adjusted offset,\n");
|
printf("|| Reachability register (octal) -. | xxxx = adjusted offset,\n");
|
||||||
printf("|| Log2(Polling interval) --. | | yyyy = measured offset,\n");
|
printf("|| Log2(Polling interval) --. | | yyyy = measured offset,\n");
|
||||||
@@ -2189,10 +2165,10 @@ process_cmd_sources(char *line)
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch (ntohs(reply.data.source_data.state)) {
|
switch (ntohs(reply.data.source_data.state)) {
|
||||||
case RPY_SD_ST_SYNC:
|
case RPY_SD_ST_SELECTED:
|
||||||
state_ch = '*';
|
state_ch = '*';
|
||||||
break;
|
break;
|
||||||
case RPY_SD_ST_UNREACH:
|
case RPY_SD_ST_NONSELECTABLE:
|
||||||
state_ch = '?';
|
state_ch = '?';
|
||||||
break;
|
break;
|
||||||
case RPY_SD_ST_FALSETICKER:
|
case RPY_SD_ST_FALSETICKER:
|
||||||
@@ -2201,10 +2177,10 @@ process_cmd_sources(char *line)
|
|||||||
case RPY_SD_ST_JITTERY:
|
case RPY_SD_ST_JITTERY:
|
||||||
state_ch = '~';
|
state_ch = '~';
|
||||||
break;
|
break;
|
||||||
case RPY_SD_ST_CANDIDATE:
|
case RPY_SD_ST_UNSELECTED:
|
||||||
state_ch = '+';
|
state_ch = '+';
|
||||||
break;
|
break;
|
||||||
case RPY_SD_ST_OUTLIER:
|
case RPY_SD_ST_SELECTABLE:
|
||||||
state_ch = '-';
|
state_ch = '-';
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -2581,9 +2557,9 @@ process_cmd_selectdata(char *line)
|
|||||||
printf( "| | | | |\n");
|
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++) {
|
for (i = 0; i < n_sources; i++) {
|
||||||
request.command = htons(REQ_SELECT_DATA);
|
request.command = htons(REQ_SELECT_DATA);
|
||||||
@@ -2601,7 +2577,7 @@ process_cmd_selectdata(char *line)
|
|||||||
conf_options = ntohs(reply.data.select_data.conf_options);
|
conf_options = ntohs(reply.data.select_data.conf_options);
|
||||||
eff_options = ntohs(reply.data.select_data.eff_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,
|
reply.data.select_data.state_char,
|
||||||
name,
|
name,
|
||||||
reply.data.select_data.authentication ? 'Y' : 'N',
|
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.score),
|
||||||
UTI_FloatNetworkToHost(reply.data.select_data.lo_limit),
|
UTI_FloatNetworkToHost(reply.data.select_data.lo_limit),
|
||||||
UTI_FloatNetworkToHost(reply.data.select_data.hi_limit),
|
UTI_FloatNetworkToHost(reply.data.select_data.hi_limit),
|
||||||
|
reply.data.select_data.leap,
|
||||||
REPORT_END);
|
REPORT_END);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3476,7 +3453,7 @@ static void
|
|||||||
display_gpl(void)
|
display_gpl(void)
|
||||||
{
|
{
|
||||||
printf("chrony version %s\n"
|
printf("chrony version %s\n"
|
||||||
"Copyright (C) 1997-2003, 2007, 2009-2019 Richard P. Curnow and others\n"
|
"Copyright (C) 1997-2003, 2007, 2009-2020 Richard P. Curnow and others\n"
|
||||||
"chrony comes with ABSOLUTELY NO WARRANTY. This is free software, and\n"
|
"chrony comes with ABSOLUTELY NO WARRANTY. This is free software, and\n"
|
||||||
"you are welcome to redistribute it under certain conditions. See the\n"
|
"you are welcome to redistribute it under certain conditions. See the\n"
|
||||||
"GNU General Public License version 2 for details.\n\n",
|
"GNU General Public License version 2 for details.\n\n",
|
||||||
@@ -3488,8 +3465,22 @@ display_gpl(void)
|
|||||||
static void
|
static void
|
||||||
print_help(const char *progname)
|
print_help(const char *progname)
|
||||||
{
|
{
|
||||||
printf("Usage: %s [-h HOST] [-p PORT] [-n] [-N] [-c] [-d] [-4|-6] [-m] [COMMAND]\n",
|
printf("Usage: %s [OPTION]... [COMMAND]...\n\n"
|
||||||
progname);
|
"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 opt, ret = 1, multi = 0, family = IPADDR_UNSPEC;
|
||||||
int port = DEFAULT_CANDM_PORT;
|
int port = DEFAULT_CANDM_PORT;
|
||||||
|
|
||||||
/* Parse (undocumented) long command-line options */
|
/* Parse long command-line options */
|
||||||
for (optind = 1; optind < argc; optind++) {
|
for (optind = 1; optind < argc; optind++) {
|
||||||
if (!strcmp("--help", argv[optind])) {
|
if (!strcmp("--help", argv[optind])) {
|
||||||
print_help(progname);
|
print_help(progname);
|
||||||
|
|||||||
@@ -169,7 +169,7 @@ compare_total_hits(Record *x, Record *y)
|
|||||||
static Record *
|
static Record *
|
||||||
get_record(IPAddr *ip)
|
get_record(IPAddr *ip)
|
||||||
{
|
{
|
||||||
uint32_t last_hit, oldest_hit = 0;
|
uint32_t last_hit = 0, oldest_hit = 0;
|
||||||
Record *record, *oldest_record;
|
Record *record, *oldest_record;
|
||||||
unsigned int first, i, j;
|
unsigned int first, i, j;
|
||||||
|
|
||||||
|
|||||||
52
cmdmon.c
52
cmdmon.c
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
**********************************************************************
|
**********************************************************************
|
||||||
* Copyright (C) Richard P. Curnow 1997-2003
|
* Copyright (C) Richard P. Curnow 1997-2003
|
||||||
* Copyright (C) Miroslav Lichvar 2009-2016, 2018
|
* Copyright (C) Miroslav Lichvar 2009-2016, 2018-2020
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of version 2 of the GNU General Public License as
|
* it under the terms of version 2 of the GNU General Public License as
|
||||||
@@ -294,13 +294,20 @@ CAM_OpenUnixSocket(void)
|
|||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
transmit_reply(int sock_fd, SCK_Message *message)
|
transmit_reply(int sock_fd, int request_length, SCK_Message *message)
|
||||||
{
|
{
|
||||||
message->length = PKL_ReplyLength((CMD_Reply *)message->data);
|
message->length = PKL_ReplyLength((CMD_Reply *)message->data);
|
||||||
|
|
||||||
|
if (request_length < message->length) {
|
||||||
|
DEBUG_LOG("Response longer than request req_len=%d res_len=%d",
|
||||||
|
request_length, message->length);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Don't require responses to non-link-local addresses to use the same
|
/* Don't require responses to non-link-local addresses to use the same
|
||||||
interface */
|
interface */
|
||||||
if (!SCK_IsLinkLocalIPAddress(&message->remote_addr.ip.ip_addr))
|
if (message->addr_type == SCK_ADDR_IP &&
|
||||||
|
!SCK_IsLinkLocalIPAddress(&message->remote_addr.ip.ip_addr))
|
||||||
message->if_index = INVALID_IF_INDEX;
|
message->if_index = INVALID_IF_INDEX;
|
||||||
|
|
||||||
if (!SCK_SendMessage(sock_fd, message, 0))
|
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.stratum = htons(report.stratum);
|
||||||
tx_message->data.source_data.poll = htons(report.poll);
|
tx_message->data.source_data.poll = htons(report.poll);
|
||||||
switch (report.state) {
|
switch (report.state) {
|
||||||
case RPT_SYNC:
|
case RPT_NONSELECTABLE:
|
||||||
tx_message->data.source_data.state = htons(RPY_SD_ST_SYNC);
|
tx_message->data.source_data.state = htons(RPY_SD_ST_NONSELECTABLE);
|
||||||
break;
|
|
||||||
case RPT_UNREACH:
|
|
||||||
tx_message->data.source_data.state = htons(RPY_SD_ST_UNREACH);
|
|
||||||
break;
|
break;
|
||||||
case RPT_FALSETICKER:
|
case RPT_FALSETICKER:
|
||||||
tx_message->data.source_data.state = htons(RPY_SD_ST_FALSETICKER);
|
tx_message->data.source_data.state = htons(RPY_SD_ST_FALSETICKER);
|
||||||
@@ -584,11 +588,14 @@ handle_source_data(CMD_Request *rx_message, CMD_Reply *tx_message)
|
|||||||
case RPT_JITTERY:
|
case RPT_JITTERY:
|
||||||
tx_message->data.source_data.state = htons(RPY_SD_ST_JITTERY);
|
tx_message->data.source_data.state = htons(RPY_SD_ST_JITTERY);
|
||||||
break;
|
break;
|
||||||
case RPT_CANDIDATE:
|
case RPT_SELECTABLE:
|
||||||
tx_message->data.source_data.state = htons(RPY_SD_ST_CANDIDATE);
|
tx_message->data.source_data.state = htons(RPY_SD_ST_SELECTABLE);
|
||||||
break;
|
break;
|
||||||
case RPT_OUTLIER:
|
case RPT_UNSELECTED:
|
||||||
tx_message->data.source_data.state = htons(RPY_SD_ST_OUTLIER);
|
tx_message->data.source_data.state = htons(RPY_SD_ST_UNSELECTED);
|
||||||
|
break;
|
||||||
|
case RPT_SELECTED:
|
||||||
|
tx_message->data.source_data.state = htons(RPY_SD_ST_SELECTED);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
switch (report.mode) {
|
switch (report.mode) {
|
||||||
@@ -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);
|
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.state_char = report.state_char;
|
||||||
tx_message->data.select_data.authentication = report.authentication;
|
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.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.eff_options = htons(convert_select_options(report.eff_options));
|
||||||
tx_message->data.select_data.last_sample_ago = htonl(report.last_sample_ago);
|
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) {
|
if (rx_message.version >= PROTO_VERSION_MISMATCH_COMPAT_SERVER) {
|
||||||
tx_message.status = htons(STT_BADPKTVERSION);
|
tx_message.status = htons(STT_BADPKTVERSION);
|
||||||
transmit_reply(sock_fd, sck_message);
|
transmit_reply(sock_fd, read_length, sck_message);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1437,7 +1445,7 @@ read_from_cmd_socket(int sock_fd, int event, void *anything)
|
|||||||
DEBUG_LOG("Command packet has invalid command %d", rx_command);
|
DEBUG_LOG("Command packet has invalid command %d", rx_command);
|
||||||
|
|
||||||
tx_message.status = htons(STT_INVALID);
|
tx_message.status = htons(STT_INVALID);
|
||||||
transmit_reply(sock_fd, sck_message);
|
transmit_reply(sock_fd, read_length, sck_message);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1446,7 +1454,7 @@ read_from_cmd_socket(int sock_fd, int event, void *anything)
|
|||||||
expected_length);
|
expected_length);
|
||||||
|
|
||||||
tx_message.status = htons(STT_BADPKTLENGTH);
|
tx_message.status = htons(STT_BADPKTLENGTH);
|
||||||
transmit_reply(sock_fd, sck_message);
|
transmit_reply(sock_fd, read_length, sck_message);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1733,19 +1741,7 @@ read_from_cmd_socket(int sock_fd, int event, void *anything)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Transmit the response */
|
/* Transmit the response */
|
||||||
{
|
transmit_reply(sock_fd, read_length, sck_message);
|
||||||
/* Include a simple way to lose one message in three to test resend */
|
|
||||||
|
|
||||||
static int do_it=1;
|
|
||||||
|
|
||||||
if (do_it) {
|
|
||||||
transmit_reply(sock_fd, sck_message);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
do_it = ((do_it + 1) % 3);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|||||||
23
conf.c
23
conf.c
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
**********************************************************************
|
**********************************************************************
|
||||||
* Copyright (C) Richard P. Curnow 1997-2003
|
* Copyright (C) Richard P. Curnow 1997-2003
|
||||||
* Copyright (C) Miroslav Lichvar 2009-2017
|
* Copyright (C) Miroslav Lichvar 2009-2017, 2020
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of version 2 of the GNU General Public License as
|
* it under the terms of version 2 of the GNU General Public License as
|
||||||
@@ -100,6 +100,7 @@ static double correction_time_ratio = 3.0;
|
|||||||
static double max_clock_error = 1.0; /* in ppm */
|
static double max_clock_error = 1.0; /* in ppm */
|
||||||
static double max_drift = 500000.0; /* in ppm */
|
static double max_drift = 500000.0; /* in ppm */
|
||||||
static double max_slew_rate = 1e6 / 12.0; /* in ppm */
|
static double max_slew_rate = 1e6 / 12.0; /* in ppm */
|
||||||
|
static double clock_precision = 0.0; /* in seconds */
|
||||||
|
|
||||||
static SRC_AuthSelectMode authselect_mode = SRC_AUTHSELECT_MIX;
|
static SRC_AuthSelectMode authselect_mode = SRC_AUTHSELECT_MIX;
|
||||||
static double max_distance = 3.0;
|
static double max_distance = 3.0;
|
||||||
@@ -421,6 +422,10 @@ CNF_Finalise(void)
|
|||||||
Free(((NTP_Source *)ARR_GetElement(ntp_sources, i))->params.name);
|
Free(((NTP_Source *)ARR_GetElement(ntp_sources, i))->params.name);
|
||||||
for (i = 0; i < ARR_GetSize(ntp_source_dirs); i++)
|
for (i = 0; i < ARR_GetSize(ntp_source_dirs); i++)
|
||||||
Free(*(char **)ARR_GetElement(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(init_sources);
|
||||||
ARR_DestroyInstance(ntp_sources);
|
ARR_DestroyInstance(ntp_sources);
|
||||||
@@ -544,6 +549,8 @@ CNF_ParseLine(const char *filename, int number, char *line)
|
|||||||
parse_broadcast(p);
|
parse_broadcast(p);
|
||||||
} else if (!strcasecmp(command, "clientloglimit")) {
|
} else if (!strcasecmp(command, "clientloglimit")) {
|
||||||
parse_clientloglimit(p);
|
parse_clientloglimit(p);
|
||||||
|
} else if (!strcasecmp(command, "clockprecision")) {
|
||||||
|
parse_double(p, &clock_precision);
|
||||||
} else if (!strcasecmp(command, "cmdallow")) {
|
} else if (!strcasecmp(command, "cmdallow")) {
|
||||||
parse_allow_deny(p, cmd_restrictions, 1);
|
parse_allow_deny(p, cmd_restrictions, 1);
|
||||||
} else if (!strcasecmp(command, "cmddeny")) {
|
} else if (!strcasecmp(command, "cmddeny")) {
|
||||||
@@ -1836,10 +1843,14 @@ CNF_AddSources(void)
|
|||||||
void
|
void
|
||||||
CNF_AddRefclocks(void)
|
CNF_AddRefclocks(void)
|
||||||
{
|
{
|
||||||
|
RefclockParameters *refclock;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
for (i = 0; i < ARR_GetSize(refclock_sources); 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);
|
ARR_SetSize(refclock_sources, 0);
|
||||||
@@ -2048,6 +2059,14 @@ CNF_GetMaxSlewRate(void)
|
|||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
|
double
|
||||||
|
CNF_GetClockPrecision(void)
|
||||||
|
{
|
||||||
|
return clock_precision;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
double
|
double
|
||||||
CNF_GetMaxDistance(void)
|
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_GetMaxDrift(void);
|
||||||
extern double CNF_GetCorrectionTimeRatio(void);
|
extern double CNF_GetCorrectionTimeRatio(void);
|
||||||
extern double CNF_GetMaxSlewRate(void);
|
extern double CNF_GetMaxSlewRate(void);
|
||||||
|
extern double CNF_GetClockPrecision(void);
|
||||||
|
|
||||||
extern SRC_AuthSelectMode CNF_GetAuthSelectMode(void);
|
extern SRC_AuthSelectMode CNF_GetAuthSelectMode(void);
|
||||||
extern double CNF_GetMaxDistance(void);
|
extern double CNF_GetMaxDistance(void);
|
||||||
|
|||||||
66
configure
vendored
66
configure
vendored
@@ -5,7 +5,7 @@
|
|||||||
#
|
#
|
||||||
# Copyright (C) Richard P. Curnow 1997-2003
|
# Copyright (C) Richard P. Curnow 1997-2003
|
||||||
# Copyright (C) Bryan Christianson 2016
|
# Copyright (C) Bryan Christianson 2016
|
||||||
# Copyright (C) Miroslav Lichvar 2009, 2012-2018
|
# Copyright (C) Miroslav Lichvar 2009, 2012-2020
|
||||||
# Copyright (C) Stefan R. Filipek 2019
|
# Copyright (C) Stefan R. Filipek 2019
|
||||||
#
|
#
|
||||||
# =======================================================================
|
# =======================================================================
|
||||||
@@ -108,11 +108,7 @@ for instance \`--prefix=$HOME'.
|
|||||||
|
|
||||||
For better control, use the options below.
|
For better control, use the options below.
|
||||||
--disable-readline Disable line editing support
|
--disable-readline Disable line editing support
|
||||||
--without-readline Don't use GNU readline even if it is available
|
|
||||||
--without-editline Don't use editline even if it is available
|
--without-editline Don't use editline even if it is available
|
||||||
--with-readline-includes=DIR Specify where readline include directory is
|
|
||||||
--with-readline-library=DIR Specify where readline lib directory is
|
|
||||||
--with-ncurses-library=DIR Specify where ncurses lib directory is
|
|
||||||
--disable-sechash Disable support for hashes other than MD5
|
--disable-sechash Disable support for hashes other than MD5
|
||||||
--without-nettle Don't use nettle even if it is available
|
--without-nettle Don't use nettle even if it is available
|
||||||
--without-nss Don't use NSS even if it is available
|
--without-nss Don't use NSS even if it is available
|
||||||
@@ -225,7 +221,6 @@ feat_cmdmon=1
|
|||||||
feat_ntp=1
|
feat_ntp=1
|
||||||
feat_refclock=1
|
feat_refclock=1
|
||||||
feat_readline=1
|
feat_readline=1
|
||||||
try_readline=1
|
|
||||||
try_editline=1
|
try_editline=1
|
||||||
feat_sechash=1
|
feat_sechash=1
|
||||||
try_nettle=1
|
try_nettle=1
|
||||||
@@ -241,9 +236,6 @@ try_clockctl=0
|
|||||||
feat_scfilter=0
|
feat_scfilter=0
|
||||||
try_seccomp=-1
|
try_seccomp=-1
|
||||||
priv_ops=""
|
priv_ops=""
|
||||||
readline_lib=""
|
|
||||||
readline_inc=""
|
|
||||||
ncurses_lib=""
|
|
||||||
feat_ipv6=1
|
feat_ipv6=1
|
||||||
feat_phc=1
|
feat_phc=1
|
||||||
try_phc=0
|
try_phc=0
|
||||||
@@ -274,21 +266,9 @@ do
|
|||||||
--disable-readline )
|
--disable-readline )
|
||||||
feat_readline=0
|
feat_readline=0
|
||||||
;;
|
;;
|
||||||
--without-readline )
|
|
||||||
try_readline=0
|
|
||||||
;;
|
|
||||||
--without-editline )
|
--without-editline )
|
||||||
try_editline=0
|
try_editline=0
|
||||||
;;
|
;;
|
||||||
--with-readline-library=* )
|
|
||||||
readline_lib=-L`echo $option | sed -e 's/^.*=//;'`
|
|
||||||
;;
|
|
||||||
--with-readline-includes=* )
|
|
||||||
readline_inc=-I`echo $option | sed -e 's/^.*=//;'`
|
|
||||||
;;
|
|
||||||
--with-ncurses-library=* )
|
|
||||||
ncurses_lib=-L`echo $option | sed -e 's/^.*=//;'`
|
|
||||||
;;
|
|
||||||
--prefix=* | --install_prefix=* )
|
--prefix=* | --install_prefix=* )
|
||||||
SETPREFIX=`echo $option | sed -e 's/[^=]*=//;'`
|
SETPREFIX=`echo $option | sed -e 's/[^=]*=//;'`
|
||||||
;;
|
;;
|
||||||
@@ -709,12 +689,12 @@ fi
|
|||||||
|
|
||||||
if test_code 'arc4random_buf()' 'stdlib.h' '' '' 'arc4random_buf(NULL, 0);'; then
|
if test_code 'arc4random_buf()' 'stdlib.h' '' '' 'arc4random_buf(NULL, 0);'; then
|
||||||
add_def HAVE_ARC4RANDOM
|
add_def HAVE_ARC4RANDOM
|
||||||
fi
|
else
|
||||||
|
|
||||||
if test_code 'getrandom()' 'stdlib.h sys/random.h' '' '' \
|
if test_code 'getrandom()' 'stdlib.h sys/random.h' '' '' \
|
||||||
'return getrandom(NULL, 256, 0);'; then
|
'return getrandom(NULL, 256, 0);'; then
|
||||||
add_def HAVE_GETRANDOM
|
add_def HAVE_GETRANDOM
|
||||||
fi
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
RECVMMSG_CODE='
|
RECVMMSG_CODE='
|
||||||
struct mmsghdr hdr;
|
struct mmsghdr hdr;
|
||||||
@@ -804,10 +784,12 @@ if [ $feat_scfilter = "1" ] && [ $try_seccomp = "1" ] && \
|
|||||||
'seccomp_init(SCMP_ACT_KILL);'
|
'seccomp_init(SCMP_ACT_KILL);'
|
||||||
then
|
then
|
||||||
add_def FEAT_SCFILTER
|
add_def FEAT_SCFILTER
|
||||||
# NAME2IPADDRESS shouldn't be enabled with other operations as the helper
|
if [ $feat_ntp = "1" ]; then
|
||||||
# process works on one request at the time and the async resolver could
|
# NAME2IPADDRESS shouldn't be enabled together with a privops operation
|
||||||
# block the main thread
|
# used by the main thread as the helper process works on one request at
|
||||||
|
# a time and the async resolver would block the main thread
|
||||||
priv_ops="NAME2IPADDRESS RELOADDNS"
|
priv_ops="NAME2IPADDRESS RELOADDNS"
|
||||||
|
fi
|
||||||
EXTRA_LIBS="$EXTRA_LIBS -lseccomp"
|
EXTRA_LIBS="$EXTRA_LIBS -lseccomp"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -876,37 +858,11 @@ fi
|
|||||||
READLINE_LINK=""
|
READLINE_LINK=""
|
||||||
if [ $feat_readline = "1" ]; then
|
if [ $feat_readline = "1" ]; then
|
||||||
if [ $try_editline = "1" ]; then
|
if [ $try_editline = "1" ]; then
|
||||||
if test_code editline 'stdio.h editline/readline.h' \
|
if test_code editline 'stdio.h editline/readline.h' '' '-ledit' \
|
||||||
"$readline_inc" "$readline_lib -ledit" \
|
|
||||||
'add_history(readline("prompt"));'
|
'add_history(readline("prompt"));'
|
||||||
then
|
then
|
||||||
add_def FEAT_READLINE
|
add_def FEAT_READLINE
|
||||||
add_def USE_EDITLINE
|
READLINE_LINK="-ledit"
|
||||||
MYCPPFLAGS="$MYCPPFLAGS $readline_inc"
|
|
||||||
READLINE_LINK="$readline_lib -ledit"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "x$READLINE_LINK" = "x" ] && [ $try_readline = "1" ]; then
|
|
||||||
if test_code readline 'stdio.h readline/readline.h readline/history.h' \
|
|
||||||
"$readline_inc" "$readline_lib -lreadline" \
|
|
||||||
'add_history(readline("prompt"));'
|
|
||||||
then
|
|
||||||
add_def FEAT_READLINE
|
|
||||||
MYCPPFLAGS="$MYCPPFLAGS $readline_inc"
|
|
||||||
READLINE_LINK="$readline_lib -lreadline"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "x$READLINE_LINK" = "x" ] && [ $try_readline = "1" ]; then
|
|
||||||
if test_code 'readline with -lncurses' \
|
|
||||||
'stdio.h readline/readline.h readline/history.h' \
|
|
||||||
"$readline_inc" "$readline_lib $ncurses_lib -lreadline -lncurses" \
|
|
||||||
'add_history(readline("prompt"));'
|
|
||||||
then
|
|
||||||
add_def FEAT_READLINE
|
|
||||||
MYCPPFLAGS="$MYCPPFLAGS $readline_inc"
|
|
||||||
READLINE_LINK="$readline_lib $ncurses_lib -lreadline -lncurses"
|
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -972,7 +928,7 @@ if [ $feat_ntp = "1" ] && [ $feat_nts = "1" ] && [ $try_gnutls = "1" ]; then
|
|||||||
test_link="`pkg_config --libs gnutls`"
|
test_link="`pkg_config --libs gnutls`"
|
||||||
if test_code 'gnutls' 'gnutls/gnutls.h' \
|
if test_code 'gnutls' 'gnutls/gnutls.h' \
|
||||||
"$test_cflags" "$test_link" '
|
"$test_cflags" "$test_link" '
|
||||||
return gnutls_init(NULL, 0) +
|
return gnutls_init(NULL, 0) + GNUTLS_TLS1_3 +
|
||||||
gnutls_priority_init2(NULL, "", NULL, GNUTLS_PRIORITY_INIT_DEF_APPEND) +
|
gnutls_priority_init2(NULL, "", NULL, GNUTLS_PRIORITY_INIT_DEF_APPEND) +
|
||||||
gnutls_prf_rfc5705(NULL, 0, "", 0, "", 16, NULL);'
|
gnutls_prf_rfc5705(NULL, 0, "", 0, "", 16, NULL);'
|
||||||
then
|
then
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
// Copyright (C) Richard P. Curnow 1997-2003
|
// Copyright (C) Richard P. Curnow 1997-2003
|
||||||
// Copyright (C) Stephen Wadeley 2016
|
// Copyright (C) Stephen Wadeley 2016
|
||||||
// Copyright (C) Bryan Christianson 2017
|
// Copyright (C) Bryan Christianson 2017
|
||||||
// Copyright (C) Miroslav Lichvar 2009-2017
|
// Copyright (C) Miroslav Lichvar 2009-2020
|
||||||
//
|
//
|
||||||
// This program is free software; you can redistribute it and/or modify
|
// This program is free software; you can redistribute it and/or modify
|
||||||
// it under the terms of version 2 of the GNU General Public License as
|
// it under the terms of version 2 of the GNU General Public License as
|
||||||
@@ -32,12 +32,14 @@ chrony.conf - chronyd configuration file
|
|||||||
== DESCRIPTION
|
== DESCRIPTION
|
||||||
|
|
||||||
This file configures the *chronyd* daemon. The compiled-in location is
|
This file configures the *chronyd* daemon. The compiled-in location is
|
||||||
_@SYSCONFDIR@/chrony.conf_, but other locations can be specified on the
|
_@SYSCONFDIR@/chrony.conf_. Other locations can be specified on the
|
||||||
*chronyd* command line with the *-f* option.
|
*chronyd* command line with the *-f* option.
|
||||||
|
|
||||||
Each directive in the configuration file is placed on a separate line. The
|
Each directive in the configuration file is placed on a separate line. The
|
||||||
following sections describe each of the directives in turn. The directives can
|
following sections describe each of the directives in turn. The directives are
|
||||||
occur in any order in the file and they are not case-sensitive.
|
not case-sensitive. Generally, the directives can occur in any order in the file
|
||||||
|
and if a directive is specified multiple times, only the last one will be
|
||||||
|
effective. Exceptions are noted in the descriptions.
|
||||||
|
|
||||||
The configuration directives can also be specified directly on the *chronyd*
|
The configuration directives can also be specified directly on the *chronyd*
|
||||||
command line. In this case each argument is parsed as a new line and the
|
command line. In this case each argument is parsed as a new line and the
|
||||||
@@ -61,9 +63,10 @@ source. The client-server relationship is strictly hierarchical: a client might
|
|||||||
synchronise its system time to that of the server, but the server's system time
|
synchronise its system time to that of the server, but the server's system time
|
||||||
will never be influenced by that of a client.
|
will never be influenced by that of a client.
|
||||||
+
|
+
|
||||||
The *server* directive is immediately followed by either the name of the
|
This directive can be used multiple times to specify multiple servers.
|
||||||
server, or its IP address. The *server* directive supports the following
|
+
|
||||||
options:
|
The directive is immediately followed by either the name of the
|
||||||
|
server, or its IP address. It supports the following options:
|
||||||
+
|
+
|
||||||
*minpoll* _poll_:::
|
*minpoll* _poll_:::
|
||||||
This option specifies the minimum interval between requests sent to the server
|
This option specifies the minimum interval between requests sent to the server
|
||||||
@@ -276,6 +279,8 @@ directive, except that it is used to specify a pool of NTP servers rather than
|
|||||||
a single NTP server. The pool name is expected to resolve to multiple addresses
|
a single NTP server. The pool name is expected to resolve to multiple addresses
|
||||||
which might change over time.
|
which might change over time.
|
||||||
+
|
+
|
||||||
|
This directive can be used multiple times to specify multiple pools.
|
||||||
|
+
|
||||||
All options valid in the <<server,*server*>> directive can be used in this
|
All options valid in the <<server,*server*>> directive can be used in this
|
||||||
directive too. There is one option specific to the *pool* directive:
|
directive too. There is one option specific to the *pool* directive:
|
||||||
+
|
+
|
||||||
@@ -306,6 +311,8 @@ is mainly useful when the NTP implementation of the peer (e.g. *ntpd*) supports
|
|||||||
ephemeral symmetric associations and does not need to be configured with an
|
ephemeral symmetric associations and does not need to be configured with an
|
||||||
address of this host. *chronyd* does not support ephemeral associations.
|
address of this host. *chronyd* does not support ephemeral associations.
|
||||||
+
|
+
|
||||||
|
This directive can be used multiple times to specify multiple peers.
|
||||||
|
+
|
||||||
The following options of the *server* directive do not work in the *peer*
|
The following options of the *server* directive do not work in the *peer*
|
||||||
directive: *iburst*, *burst*, *nts*, *presend*.
|
directive: *iburst*, *burst*, *nts*, *presend*.
|
||||||
+
|
+
|
||||||
@@ -398,6 +405,8 @@ driver-specific parameter. The two parameters are followed by zero or more
|
|||||||
refclock options. Some drivers have special options, which can be appended to
|
refclock options. Some drivers have special options, which can be appended to
|
||||||
the driver-specific parameter using the *:* character.
|
the driver-specific parameter using the *:* character.
|
||||||
+
|
+
|
||||||
|
This directive can be used multiple times to specify multiple reference clocks.
|
||||||
|
+
|
||||||
There are four drivers included in *chronyd*:
|
There are four drivers included in *chronyd*:
|
||||||
+
|
+
|
||||||
*PPS*:::
|
*PPS*:::
|
||||||
@@ -610,12 +619,13 @@ behaviour, whereas the *settime* command allows samples of manually entered
|
|||||||
time to be provided.)
|
time to be provided.)
|
||||||
|
|
||||||
[[acquisitionport]]*acquisitionport* _port_::
|
[[acquisitionport]]*acquisitionport* _port_::
|
||||||
By default, *chronyd* uses a separate client socket for each configured server
|
By default, *chronyd* as an NTP client opens a new socket for each request with
|
||||||
and their source port is chosen arbitrarily by the operating system. However,
|
the source port chosen randomly by the operating system. The *acquisitionport*
|
||||||
you can use the *acquisitionport* directive to explicitly specify a port and
|
directive can be used to specify the source port and use only one socket (per
|
||||||
use only one socket (per IPv4 or IPv6 address family) for all configured servers.
|
IPv4 or IPv6 address family) for all configured servers. This can be useful for
|
||||||
This can be useful for getting through some firewalls. If set to 0, the source
|
getting through some firewalls. It should not be used if not necessary as there
|
||||||
port of the socket will be chosen arbitrarily.
|
is a small impact on security of the client. If set to 0, the source port of
|
||||||
|
the permanent socket will be chosen randomly by the operating system.
|
||||||
+
|
+
|
||||||
It can be set to the same port as is used by the NTP server (which can be
|
It can be set to the same port as is used by the NTP server (which can be
|
||||||
configured with the <<port,*port*>> directive) to use only one socket for all
|
configured with the <<port,*port*>> directive) to use only one socket for all
|
||||||
@@ -632,8 +642,8 @@ You could then persuade the firewall administrator to open that port.
|
|||||||
|
|
||||||
[[bindacqaddress]]*bindacqaddress* _address_::
|
[[bindacqaddress]]*bindacqaddress* _address_::
|
||||||
The *bindacqaddress* directive specifies a local IP address to which
|
The *bindacqaddress* directive specifies a local IP address to which
|
||||||
*chronyd* will bind its NTP client sockets. The syntax is similar to the
|
*chronyd* will bind its NTP and NTS-KE client sockets. The syntax is similar to
|
||||||
<<bindaddress,*bindaddress*>> and <<bindcmdaddress,*bindcmdaddress*>>
|
the <<bindaddress,*bindaddress*>> and <<bindcmdaddress,*bindcmdaddress*>>
|
||||||
directives.
|
directives.
|
||||||
+
|
+
|
||||||
For each of the IPv4 and IPv6 protocols, only one *bindacqaddress* directive
|
For each of the IPv4 and IPv6 protocols, only one *bindacqaddress* directive
|
||||||
@@ -908,6 +918,27 @@ distances are in milliseconds.
|
|||||||
|
|
||||||
=== System clock
|
=== System clock
|
||||||
|
|
||||||
|
[[clockprecision]]*clockprecision* _precision_::
|
||||||
|
The *clockprecision* directive specifies the precision of the system clock (in
|
||||||
|
seconds). It is used by *chronyd* to estimate the minimum noise in NTP
|
||||||
|
measurements and randomise low-order bits of timestamps in NTP responses. By
|
||||||
|
default, the precision is measured on start as the minimum time to read the
|
||||||
|
clock.
|
||||||
|
+
|
||||||
|
The measured value works well in most cases. However, it generally
|
||||||
|
overestimates the precision and it can be sensitive to the CPU speed, which can
|
||||||
|
change over time to save power. In some cases with a high-precision clocksource
|
||||||
|
(e.g. the Time Stamp Counter of the CPU) and hardware timestamping, setting the
|
||||||
|
precision on the server to a smaller value can improve stability of clients'
|
||||||
|
NTP measurements. The server's precision is reported on clients by the
|
||||||
|
<<chronyc.adoc#ntpdata,*ntpdata*>> command.
|
||||||
|
+
|
||||||
|
An example setting the precision to 8 nanoseconds is:
|
||||||
|
+
|
||||||
|
----
|
||||||
|
clockprecision 8e-9
|
||||||
|
----
|
||||||
|
|
||||||
[[corrtimeratio]]*corrtimeratio* _ratio_::
|
[[corrtimeratio]]*corrtimeratio* _ratio_::
|
||||||
When *chronyd* is slewing the system clock to correct an offset, the rate at
|
When *chronyd* is slewing the system clock to correct an offset, the rate at
|
||||||
which it is slewing adds to the frequency error of the clock. On all supported
|
which it is slewing adds to the frequency error of the clock. On all supported
|
||||||
@@ -1039,7 +1070,7 @@ A recommended configuration to enable a server leap smear is:
|
|||||||
----
|
----
|
||||||
leapsecmode slew
|
leapsecmode slew
|
||||||
maxslewrate 1000
|
maxslewrate 1000
|
||||||
smoothtime 400 0.001 leaponly
|
smoothtime 400 0.001024 leaponly
|
||||||
----
|
----
|
||||||
+
|
+
|
||||||
The first directive is necessary to disable the clock step which would reset
|
The first directive is necessary to disable the clock step which would reset
|
||||||
@@ -1047,11 +1078,17 @@ the smoothing process. The second directive limits the slewing rate of the
|
|||||||
local clock to 1000 ppm, which improves the stability of the smoothing process
|
local clock to 1000 ppm, which improves the stability of the smoothing process
|
||||||
when the local correction starts and ends. The third directive enables the
|
when the local correction starts and ends. The third directive enables the
|
||||||
server time smoothing process. It will start when the clock gets to 00:00:00
|
server time smoothing process. It will start when the clock gets to 00:00:00
|
||||||
UTC and it will take 17 hours 34 minutes to finish. The frequency offset will
|
UTC and it will take 62500 seconds (about 17.36 hours) to finish. The frequency
|
||||||
be changing by 0.001 ppm per second and will reach a maximum of 31.623 ppm. The
|
offset will be changing by 0.001024 ppm per second and will reach a maximum of
|
||||||
*leaponly* option makes the duration of the leap smear constant and allows the
|
32 ppm in 31250 seconds. The *leaponly* option makes the duration of the leap
|
||||||
clients to safely synchronise with multiple identically configured leap
|
smear constant and allows the clients to safely synchronise with multiple
|
||||||
smearing servers.
|
identically configured leap smearing servers.
|
||||||
|
+
|
||||||
|
The duration of the leap smear can be calculated from the specified wander as
|
||||||
|
+
|
||||||
|
----
|
||||||
|
duration = sqrt(4 / wander)
|
||||||
|
----
|
||||||
|
|
||||||
[[leapsectz]]*leapsectz* _timezone_::
|
[[leapsectz]]*leapsectz* _timezone_::
|
||||||
This directive specifies a timezone in the system tz database which *chronyd*
|
This directive specifies a timezone in the system tz database which *chronyd*
|
||||||
@@ -1221,7 +1258,7 @@ coefficients _T0_, _k0_, _k1_, _k2_.
|
|||||||
The frequency compensation is calculated (in ppm) as
|
The frequency compensation is calculated (in ppm) as
|
||||||
+
|
+
|
||||||
----
|
----
|
||||||
k0 + (T - T0) * k1 + (T - T0)^2 * k2
|
comp = k0 + (T - T0) * k1 + (T - T0)^2 * k2
|
||||||
----
|
----
|
||||||
+
|
+
|
||||||
The result has to be between -10 ppm and 10 ppm, otherwise the measurement is
|
The result has to be between -10 ppm and 10 ppm, otherwise the measurement is
|
||||||
@@ -1272,12 +1309,15 @@ _tempcomp.log_ file if enabled by the <<log,*log tempcomp*>> directive.
|
|||||||
|
|
||||||
[[allow]]*allow* [*all*] [_subnet_]::
|
[[allow]]*allow* [*all*] [_subnet_]::
|
||||||
The *allow* directive is used to designate a particular subnet from which NTP
|
The *allow* directive is used to designate a particular subnet from which NTP
|
||||||
clients are allowed to access the computer as an NTP server.
|
clients are allowed to access the computer as an NTP server. It also controls
|
||||||
|
access of NTS-KE clients when NTS is enabled on the server.
|
||||||
+
|
+
|
||||||
The default is that no clients are allowed access, i.e. *chronyd* operates
|
The default is that no clients are allowed access, i.e. *chronyd* operates
|
||||||
purely as an NTP client. If the *allow* directive is used, *chronyd* will be
|
purely as an NTP client. If the *allow* directive is used, *chronyd* will be
|
||||||
both a client of its servers, and a server to other clients.
|
both a client of its servers, and a server to other clients.
|
||||||
+
|
+
|
||||||
|
This directive can be used multiple times.
|
||||||
|
+
|
||||||
Examples of the use of the directive are as follows:
|
Examples of the use of the directive are as follows:
|
||||||
+
|
+
|
||||||
----
|
----
|
||||||
@@ -1344,18 +1384,19 @@ client access by this computer for it to work.
|
|||||||
|
|
||||||
[[deny]]*deny* [*all*] [_subnet_]::
|
[[deny]]*deny* [*all*] [_subnet_]::
|
||||||
This is similar to the <<allow,*allow*>> directive, except that it denies NTP
|
This is similar to the <<allow,*allow*>> directive, except that it denies NTP
|
||||||
client access to a particular subnet or host, rather than allowing it.
|
and NTS-KE client access to a particular subnet or host, rather than allowing
|
||||||
|
it.
|
||||||
+
|
+
|
||||||
The syntax is identical.
|
The syntax is identical and the directive can be used multiple times too.
|
||||||
+
|
+
|
||||||
There is also a *deny all* directive with similar behaviour to the *allow all*
|
There is also a *deny all* directive with similar behaviour to the *allow all*
|
||||||
directive.
|
directive.
|
||||||
|
|
||||||
[[bindaddress]]*bindaddress* _address_::
|
[[bindaddress]]*bindaddress* _address_::
|
||||||
The *bindaddress* directive binds the socket on which *chronyd* listens for NTP
|
The *bindaddress* directive binds the sockets on which *chronyd* listens for
|
||||||
requests to a local address of the computer. On systems other than Linux, the
|
NTP and NTS-KE requests to a local address of the computer. On systems other
|
||||||
address of the computer needs to be already configured when *chronyd* is
|
than Linux, the address of the computer needs to be already configured when
|
||||||
started.
|
*chronyd* is started.
|
||||||
+
|
+
|
||||||
An example of the use of the directive is:
|
An example of the use of the directive is:
|
||||||
+
|
+
|
||||||
@@ -1368,9 +1409,9 @@ directive can be specified. Therefore, it is not useful on computers which
|
|||||||
should serve NTP on multiple network interfaces.
|
should serve NTP on multiple network interfaces.
|
||||||
|
|
||||||
[[binddevice]]*binddevice* _interface_::
|
[[binddevice]]*binddevice* _interface_::
|
||||||
The *binddevice* directive binds the NTP server sockets to a network device
|
The *binddevice* directive binds the NTP and NTS-KE server sockets to a network
|
||||||
specified by the interface name. This directive can specify only one interface
|
device specified by the interface name. This directive can specify only one
|
||||||
and it is supported on Linux only.
|
interface and it is supported on Linux only.
|
||||||
+
|
+
|
||||||
An example of the directive is:
|
An example of the directive is:
|
||||||
+
|
+
|
||||||
@@ -1384,6 +1425,8 @@ chronyd should send packets in the NTP broadcast mode (i.e. make *chronyd* act
|
|||||||
as a broadcast server). Broadcast clients on that subnet will be able to
|
as a broadcast server). Broadcast clients on that subnet will be able to
|
||||||
synchronise.
|
synchronise.
|
||||||
+
|
+
|
||||||
|
This directive can be used multiple times to specify multiple addresses.
|
||||||
|
+
|
||||||
The syntax is as follows:
|
The syntax is as follows:
|
||||||
+
|
+
|
||||||
----
|
----
|
||||||
@@ -1483,7 +1526,9 @@ configuration and to be synchronised to one another, without confusing clients
|
|||||||
that poll more than one server. Each server needs to be configured to poll all
|
that poll more than one server. Each server needs to be configured to poll all
|
||||||
other servers with the *local* directive. This ensures only the server with the
|
other servers with the *local* directive. This ensures only the server with the
|
||||||
smallest reference ID has the local reference active and others are
|
smallest reference ID has the local reference active and others are
|
||||||
synchronised to it. When that server fails, another will take over.
|
synchronised to it. If that server stops responding, the server with the second
|
||||||
|
smallest reference ID will take over when its local reference mode activates
|
||||||
|
(root distance reaches the threshold configured by the *distance* option).
|
||||||
+
|
+
|
||||||
The *orphan* mode is compatible with the *ntpd*'s orphan mode (enabled by the
|
The *orphan* mode is compatible with the *ntpd*'s orphan mode (enabled by the
|
||||||
*tos orphan* command).
|
*tos orphan* command).
|
||||||
@@ -1492,7 +1537,7 @@ The *orphan* mode is compatible with the *ntpd*'s orphan mode (enabled by the
|
|||||||
An example of the directive is:
|
An example of the directive is:
|
||||||
+
|
+
|
||||||
----
|
----
|
||||||
local stratum 10 orphan
|
local stratum 10 orphan distance 0.1
|
||||||
----
|
----
|
||||||
|
|
||||||
[[ntpsigndsocket]]*ntpsigndsocket* _directory_::
|
[[ntpsigndsocket]]*ntpsigndsocket* _directory_::
|
||||||
@@ -1563,9 +1608,12 @@ to the clients, which means they should use the same server for NTS-KE and NTP.
|
|||||||
|
|
||||||
[[ntsrotate]]*ntsrotate* _interval_::
|
[[ntsrotate]]*ntsrotate* _interval_::
|
||||||
This directive specifies the rotation interval (in seconds) of the server key
|
This directive specifies the rotation interval (in seconds) of the server key
|
||||||
which encrypts the NTS cookies. New keys are generated automatically. The
|
which encrypts the NTS cookies. New keys are generated automatically from the
|
||||||
server keeps two previous keys to give the clients time to get new cookies
|
_/dev/urandom_ device. The server keeps two previous keys to give the clients
|
||||||
encrypted by the latest key. The default interval is 604800 seconds (1 week).
|
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.
|
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
|
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
|
automatically. When the system clock is synchronised and the estimated error
|
||||||
between the two clocks is larger than the specified threshold, *chronyd* will
|
between the two clocks is larger than the specified threshold, *chronyd* will
|
||||||
trim the RTC as if the <<chronyc.adoc#trimrtc,*trimrtc*>> command in *chronyc*
|
trim the RTC as if the <<chronyc.adoc#trimrtc,*trimrtc*>> command in *chronyc*
|
||||||
was issued.
|
was issued. The trimming operation is accurate to only about 1 second, which is
|
||||||
|
the minimum effective threshold.
|
||||||
+
|
+
|
||||||
This directive is effective only with the <<rtcfile,*rtcfile*>> directive.
|
This directive is effective only with the <<rtcfile,*rtcfile*>> directive.
|
||||||
+
|
+
|
||||||
@@ -2202,6 +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
|
included. This enables a fragmented configuration where existing fragments can
|
||||||
be replaced by adding files to a different directory.
|
be replaced by adding files to a different directory.
|
||||||
+
|
+
|
||||||
|
This directive can be used multiple times.
|
||||||
|
+
|
||||||
An example of the directive is:
|
An example of the directive is:
|
||||||
+
|
+
|
||||||
----
|
----
|
||||||
@@ -2217,6 +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
|
received from a DHCP server, which can be written to a file specific to the
|
||||||
network interface by a networking script.
|
network interface by a networking script.
|
||||||
+
|
+
|
||||||
|
This directive can be used multiple times.
|
||||||
|
+
|
||||||
An example of the directive is:
|
An example of the directive is:
|
||||||
+
|
+
|
||||||
----
|
----
|
||||||
@@ -2229,6 +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
|
the full name of the files needs to be specified and at least one file is
|
||||||
required to exist.
|
required to exist.
|
||||||
+
|
+
|
||||||
|
This directive can be used multiple times.
|
||||||
|
+
|
||||||
An example of the directive is:
|
An example of the directive is:
|
||||||
+
|
+
|
||||||
----
|
----
|
||||||
@@ -2264,8 +2319,9 @@ indicated in the _measurements.log_ file if enabled by the <<log,*log
|
|||||||
measurements*>> directive, and the <<chronyc.adoc#ntpdata,*ntpdata*>> report in
|
measurements*>> directive, and the <<chronyc.adoc#ntpdata,*ntpdata*>> report in
|
||||||
*chronyc*.
|
*chronyc*.
|
||||||
+
|
+
|
||||||
If the specified interface is _*_, *chronyd* will try to enable HW timestamping
|
This directive can be used multiple times to enable HW timestamping on multiple
|
||||||
on all available interfaces.
|
interfaces. If the specified interface is _*_, *chronyd* will try to enable HW
|
||||||
|
timestamping on all available interfaces.
|
||||||
+
|
+
|
||||||
The *hwtimestamp* directive has the following options:
|
The *hwtimestamp* directive has the following options:
|
||||||
+
|
+
|
||||||
@@ -2458,7 +2514,7 @@ the following methods:
|
|||||||
stratum 1 and stratum 2 servers. You should find one or more servers that are
|
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
|
near to you. Check that their access policy allows you to use their
|
||||||
facilities.
|
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_
|
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:
|
and _baz.example.net_, your _chrony.conf_ file could contain as a minimum:
|
||||||
@@ -2497,6 +2553,20 @@ makestep 1.0 3
|
|||||||
rtcsync
|
rtcsync
|
||||||
----
|
----
|
||||||
|
|
||||||
|
If the servers (or pool) support the Network Time Security (NTS)
|
||||||
|
authentication mechanism and *chronyd* is compiled with NTS support, the *nts*
|
||||||
|
option will enable a secure synchronisation to the servers. The configuration
|
||||||
|
file could look like:
|
||||||
|
|
||||||
|
----
|
||||||
|
server foo.example.net iburst nts
|
||||||
|
server bar.example.net iburst nts
|
||||||
|
server baz.example.net iburst nts
|
||||||
|
driftfile @CHRONYVARDIR@/drift
|
||||||
|
makestep 1.0 3
|
||||||
|
rtcsync
|
||||||
|
----
|
||||||
|
|
||||||
=== NTP client with infrequent connection to NTP servers
|
=== NTP client with infrequent connection to NTP servers
|
||||||
|
|
||||||
This section shows how to configure *chronyd* for computers that have
|
This section shows how to configure *chronyd* for computers that have
|
||||||
@@ -2736,7 +2806,7 @@ information to be saved.
|
|||||||
=== Public NTP server
|
=== Public NTP server
|
||||||
|
|
||||||
*chronyd* can be configured to operate as a public NTP server, e.g. to join the
|
*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
|
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
|
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
|
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) Richard P. Curnow 1997-2003
|
||||||
// Copyright (C) Stephen Wadeley 2016
|
// Copyright (C) Stephen Wadeley 2016
|
||||||
// Copyright (C) Miroslav Lichvar 2009-2017
|
// Copyright (C) Miroslav Lichvar 2009-2017, 2019-2020
|
||||||
//
|
//
|
||||||
// This program is free software; you can redistribute it and/or modify
|
// This program is free software; you can redistribute it and/or modify
|
||||||
// it under the terms of version 2 of the GNU General Public License as
|
// it under the terms of version 2 of the GNU General Public License as
|
||||||
@@ -39,7 +39,7 @@ running.
|
|||||||
If no commands are specified on the command line, *chronyc* will expect input
|
If no commands are specified on the command line, *chronyc* will expect input
|
||||||
from the user. The prompt _chronyc>_ will be displayed when it is being run
|
from the user. The prompt _chronyc>_ will be displayed when it is being run
|
||||||
from a terminal. If *chronyc*'s input or output are redirected from or to a file,
|
from a terminal. If *chronyc*'s input or output are redirected from or to a file,
|
||||||
the prompt is not shown.
|
the prompt will not be shown.
|
||||||
|
|
||||||
There are two ways *chronyc* can access *chronyd*. One is the Internet
|
There are two ways *chronyc* can access *chronyd*. One is the Internet
|
||||||
Protocol (IPv4 or IPv6) and the other is a Unix domain socket, which is
|
Protocol (IPv4 or IPv6) and the other is a Unix domain socket, which is
|
||||||
@@ -60,9 +60,7 @@ default, the commands are accepted only from localhost (127.0.0.1 or ::1).
|
|||||||
|
|
||||||
All other commands are allowed only through the Unix domain socket. When sent
|
All other commands are allowed only through the Unix domain socket. When sent
|
||||||
over the network, *chronyd* will respond with a '`Not authorised`' error, even
|
over the network, *chronyd* will respond with a '`Not authorised`' error, even
|
||||||
if it is from localhost. In chrony versions before 2.2 they were allowed
|
if it is from localhost.
|
||||||
from the network if they were authenticated with a password, but that is no
|
|
||||||
longer supported.
|
|
||||||
|
|
||||||
Having full access to *chronyd* via *chronyc* is more or less equivalent to
|
Having full access to *chronyd* via *chronyc* is more or less equivalent to
|
||||||
being able to modify the *chronyd*'s configuration file and restart it.
|
being able to modify the *chronyd*'s configuration file and restart it.
|
||||||
@@ -120,10 +118,14 @@ This option is ignored and is provided only for compatibility.
|
|||||||
*-a*::
|
*-a*::
|
||||||
This option is ignored and is provided only for compatibility.
|
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
|
With this option *chronyc* displays its version number on the terminal and
|
||||||
exits.
|
exits.
|
||||||
|
|
||||||
|
*--help*::
|
||||||
|
With this option *chronyc* displays a help message on the terminal and
|
||||||
|
exits.
|
||||||
|
|
||||||
== COMMANDS
|
== COMMANDS
|
||||||
|
|
||||||
This section describes each of the commands available within the *chronyc*
|
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
|
and then returning to the system clock's normal speed. A consequence of this is
|
||||||
that there will be a period when the system clock (as read by other programs)
|
that there will be a period when the system clock (as read by other programs)
|
||||||
will be different from *chronyd*'s estimate of the current true time (which it
|
will be different from *chronyd*'s estimate of the current true time (which it
|
||||||
reports to NTP clients when it is operating in server mode). The value reported
|
reports to NTP clients when it is operating as a server). The value reported
|
||||||
on this line is the difference due to this effect.
|
on this line is the difference due to this effect.
|
||||||
*Last offset*:::
|
*Last offset*:::
|
||||||
This is the estimated local offset on the last clock update.
|
This is the estimated local offset on the last clock update. A positive value
|
||||||
|
indicates the local time (as previously estimated true time) was ahead of the
|
||||||
|
time sources.
|
||||||
*RMS offset*:::
|
*RMS offset*:::
|
||||||
This is a long-term average of the offset value.
|
This is a long-term average of the offset value.
|
||||||
*Frequency*:::
|
*Frequency*:::
|
||||||
@@ -317,18 +321,23 @@ The columns are as follows:
|
|||||||
This indicates the mode of the source. _^_ means a server, _=_ means a peer
|
This indicates the mode of the source. _^_ means a server, _=_ means a peer
|
||||||
and _#_ indicates a locally connected reference clock.
|
and _#_ indicates a locally connected reference clock.
|
||||||
*S*:::
|
*S*:::
|
||||||
This column indicates the state of the source.
|
This column indicates the selection state of the source.
|
||||||
* _*_ indicates the source to which *chronyd* is currently synchronised.
|
* _*_ indicates the best source which is currently selected for
|
||||||
* _+_ indicates acceptable sources which are combined with the selected
|
synchronisation.
|
||||||
source.
|
* _+_ indicates other sources selected for synchronisation, which are combined
|
||||||
* _-_ indicates acceptable sources which are excluded by the combining
|
with the best source.
|
||||||
algorithm.
|
* _-_ indicates a source which is considered to be selectable for
|
||||||
* _?_ indicates sources to which connectivity has been lost or whose packets
|
synchronisation, but not currently selected.
|
||||||
do not pass all tests. It is also shown at start-up, until at least 3 samples
|
* _x_ indicates a source which *chronyd* thinks is a falseticker (i.e. its
|
||||||
have been gathered from it.
|
time is inconsistent with a majority of other sources, or sources specified
|
||||||
* _x_ indicates a clock which *chronyd* thinks is a falseticker (i.e. its
|
with the *trust* option).
|
||||||
time is inconsistent with a majority of other sources).
|
|
||||||
* _~_ indicates a source whose time appears to have too much variability.
|
* _~_ indicates a source whose time appears to have too much variability.
|
||||||
|
* _?_ indicates a source which is not considered to be selectable for
|
||||||
|
synchronisation for other reasons (e.g. unreachable, not synchronised, or
|
||||||
|
does not have enough measurements).
|
||||||
|
{blank}:::
|
||||||
|
The <<selectdata,*selectdata*>> command can be used to get more details about
|
||||||
|
the selection state.
|
||||||
*Name/IP address*:::
|
*Name/IP address*:::
|
||||||
This shows the name or the IP address of the source, or reference ID for reference
|
This shows the name or the IP address of the source, or reference ID for reference
|
||||||
clocks.
|
clocks.
|
||||||
@@ -423,11 +432,11 @@ lines are shown as a reminder of the meanings of the columns.
|
|||||||
An example of the output is shown below.
|
An example of the output is shown below.
|
||||||
+
|
+
|
||||||
----
|
----
|
||||||
S Name/IP Address Auth COpts EOpts Last Score Interval
|
S Name/IP Address Auth COpts EOpts Last Score Interval Leap
|
||||||
====================================================================
|
=======================================================================
|
||||||
D foo.example.net Y ----- --TR- 4 1.0 -61ms +62ms
|
D foo.example.net Y ----- --TR- 4 1.0 -61ms +62ms N
|
||||||
* bar.example.net N ----- ----- 0 1.0 -6846us +7305us
|
* bar.example.net N ----- ----- 0 1.0 -6846us +7305us N
|
||||||
+ baz.example.net N ----- ----- 10 1.0 -7381us +7355us
|
+ baz.example.net N ----- ----- 10 1.0 -7381us +7355us N
|
||||||
----
|
----
|
||||||
+
|
+
|
||||||
The columns are as follows:
|
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
|
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
|
expected to contain the true offset of the local clock considering the root
|
||||||
distance at the time of the selection.
|
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*::
|
[[reselect]]*reselect*::
|
||||||
To avoid excessive switching between sources, *chronyd* can stay synchronised
|
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
|
# mv /var/log/chrony/measurements.log /var/log/chrony/measurements1.log
|
||||||
# chronyc cyclelogs
|
# chronyc cyclelogs
|
||||||
# ls -l /var/log/chrony
|
# rm /var/log/chrony/measurements1.log
|
||||||
-rw-r--r-- 1 root root 0 Jun 8 18:17 measurements.log
|
|
||||||
-rw-r--r-- 1 root root 12345 Jun 8 18:17 measurements1.log
|
|
||||||
# rm -f measurements1.log
|
|
||||||
----
|
----
|
||||||
|
|
||||||
[[dump]]*dump*::
|
[[dump]]*dump*::
|
||||||
@@ -1356,7 +1368,9 @@ The *reset sources* command causes *chronyd* to drop all measurements and
|
|||||||
switch to the unsynchronised state. This command can help *chronyd* with
|
switch to the unsynchronised state. This command can help *chronyd* with
|
||||||
recovery when the measurements are known to be no longer valid or accurate,
|
recovery when the measurements are known to be no longer valid or accurate,
|
||||||
e.g. due to moving the computer to a different network, or resuming the
|
e.g. due to moving the computer to a different network, or resuming the
|
||||||
computer from a low-power state (which resets the system clock).
|
computer from a low-power state (which resets the system clock). *chronyd* will
|
||||||
|
drop the measurements automatically when it detects the clock has made an
|
||||||
|
unexpected jump, but the detection is not completely reliable.
|
||||||
|
|
||||||
[[shutdown]]*shutdown*::
|
[[shutdown]]*shutdown*::
|
||||||
The *shutdown* command causes *chronyd* to exit. This is equivalent to sending
|
The *shutdown* command causes *chronyd* to exit. This is equivalent to sending
|
||||||
@@ -1423,7 +1437,13 @@ keygen 73 SHA1 256
|
|||||||
+
|
+
|
||||||
which generates a 256-bit SHA1 key with number 73. The printed line should
|
which generates a 256-bit SHA1 key with number 73. The printed line should
|
||||||
then be securely transferred and added to the key files on both server and
|
then be securely transferred and added to the key files on both server and
|
||||||
client, or peers.
|
client, or peers. A different key should be generated for each client or peer.
|
||||||
|
+
|
||||||
|
An example using the AES128 cipher is:
|
||||||
|
+
|
||||||
|
----
|
||||||
|
keygen 151 AES128
|
||||||
|
----
|
||||||
|
|
||||||
[[exit]]*exit*::
|
[[exit]]*exit*::
|
||||||
[[quit]]*quit*::
|
[[quit]]*quit*::
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ IPv6 sockets will be created.
|
|||||||
|
|
||||||
*-f* _file_::
|
*-f* _file_::
|
||||||
This option can be used to specify an alternate location for the configuration
|
This option can be used to specify an alternate location for the configuration
|
||||||
file. The default value is _@SYSCONFDIR@/chrony.conf_.
|
file. The compiled-in default value is _@SYSCONFDIR@/chrony.conf_.
|
||||||
|
|
||||||
*-n*::
|
*-n*::
|
||||||
When run in this mode, the program will not detach itself from the terminal.
|
When run in this mode, the program will not detach itself from the terminal.
|
||||||
@@ -137,7 +137,7 @@ running, but still allow it to adjust the frequency of the system clock.
|
|||||||
*-u* _user_::
|
*-u* _user_::
|
||||||
This option sets the name of the system user to which *chronyd* will switch
|
This option sets the name of the system user to which *chronyd* will switch
|
||||||
after start in order to drop root privileges. It overrides the
|
after start in order to drop root privileges. It overrides the
|
||||||
<<chrony.conf.adoc#user,*user*>> directive. The default value is
|
<<chrony.conf.adoc#user,*user*>> directive. The compiled-in default value is
|
||||||
_@DEFAULT_USER@_.
|
_@DEFAULT_USER@_.
|
||||||
+
|
+
|
||||||
On Linux, *chronyd* needs to be compiled with support for the *libcap* library.
|
On Linux, *chronyd* needs to be compiled with support for the *libcap* library.
|
||||||
@@ -145,6 +145,16 @@ On macOS, FreeBSD, NetBSD and Solaris *chronyd* forks into two processes.
|
|||||||
The child process retains root privileges, but can only perform a very limited
|
The child process retains root privileges, but can only perform a very limited
|
||||||
range of privileged system calls on behalf of the parent.
|
range of privileged system calls on behalf of the parent.
|
||||||
|
|
||||||
|
*-U*::
|
||||||
|
This option disables a check for root privileges to allow *chronyd* to be
|
||||||
|
started under a non-root user, assuming the process will have all capabilities
|
||||||
|
(e.g. provided by the service manager) and access to all files, directories,
|
||||||
|
and devices, needed to operate correctly in the specified configuration. Note
|
||||||
|
that different capabilities might be needed with different configurations and
|
||||||
|
different Linux kernel versions. Starting *chronyd* under a non-root user is
|
||||||
|
not recommended when the configuration is not known, or at least limited to
|
||||||
|
specific directives.
|
||||||
|
|
||||||
*-F* _level_::
|
*-F* _level_::
|
||||||
This option configures a system call filter when *chronyd* is compiled with
|
This option configures a system call filter when *chronyd* is compiled with
|
||||||
support for the Linux secure computing (seccomp) facility. In level 1 the
|
support for the Linux secure computing (seccomp) facility. In level 1 the
|
||||||
@@ -152,10 +162,10 @@ process is killed when a forbidden system call is made, in level -1 the SIGSYS
|
|||||||
signal is thrown instead and in level 0 the filter is disabled. The default
|
signal is thrown instead and in level 0 the filter is disabled. The default
|
||||||
value is 0.
|
value is 0.
|
||||||
+
|
+
|
||||||
It's recommended to enable the filter only when it's known to work on the
|
It is recommended to enable the filter only when it is known to work on the
|
||||||
version of the system where *chrony* is installed as the filter needs to allow
|
version of the system where *chrony* is installed as the filter needs to allow
|
||||||
also system calls made from libraries that *chronyd* is using (e.g. libc) and
|
also system calls made from libraries that *chronyd* is using (e.g. libc) and
|
||||||
different versions or implementations of the libraries may make different
|
different versions or implementations of the libraries might make different
|
||||||
system calls. If the filter is missing some system call, *chronyd* could be
|
system calls. If the filter is missing some system call, *chronyd* could be
|
||||||
killed even in normal operation.
|
killed even in normal operation.
|
||||||
|
|
||||||
@@ -174,14 +184,15 @@ This mode is only supported on Linux.
|
|||||||
This option disables the control of the system clock. *chronyd* will not try to
|
This option disables the control of the system clock. *chronyd* will not try to
|
||||||
make any adjustments of the clock. It will assume the clock is free running and
|
make any adjustments of the clock. It will assume the clock is free running and
|
||||||
still track its offset and frequency relative to the estimated true time. This
|
still track its offset and frequency relative to the estimated true time. This
|
||||||
option allows *chronyd* to run without the capability to adjust or set the
|
option allows *chronyd* to be started without the capability to adjust or set
|
||||||
system clock (e.g. in some containers) in order to operate as an NTP server. It
|
the system clock (e.g. in some containers) to operate as an NTP server.
|
||||||
is not recommended to run *chronyd* (with or without *-x*) when another process
|
|
||||||
is controlling the system clock.
|
|
||||||
|
|
||||||
*-v*::
|
*-v*, *--version*::
|
||||||
With this option *chronyd* will print version number to the terminal and exit.
|
With this option *chronyd* will print version number to the terminal and exit.
|
||||||
|
|
||||||
|
*-h*, *--help*::
|
||||||
|
With this option *chronyd* will print a help message to the terminal and exit.
|
||||||
|
|
||||||
== FILES
|
== FILES
|
||||||
|
|
||||||
_@SYSCONFDIR@/chrony.conf_
|
_@SYSCONFDIR@/chrony.conf_
|
||||||
|
|||||||
273
doc/faq.adoc
273
doc/faq.adoc
@@ -1,7 +1,7 @@
|
|||||||
// This file is part of chrony
|
// This file is part of chrony
|
||||||
//
|
//
|
||||||
// Copyright (C) Richard P. Curnow 1997-2003
|
// Copyright (C) Richard P. Curnow 1997-2003
|
||||||
// Copyright (C) Miroslav Lichvar 2014-2016
|
// Copyright (C) Miroslav Lichvar 2014-2016, 2020
|
||||||
//
|
//
|
||||||
// This program is free software; you can redistribute it and/or modify
|
// This program is free software; you can redistribute it and/or modify
|
||||||
// it under the terms of version 2 of the GNU General Public License as
|
// it under the terms of version 2 of the GNU General Public License as
|
||||||
@@ -24,17 +24,20 @@
|
|||||||
|
|
||||||
=== How does `chrony` compare to `ntpd`?
|
=== How does `chrony` compare to `ntpd`?
|
||||||
|
|
||||||
`chronyd` was designed to work well in a wide range of conditions and it can
|
`chrony` and `ntpd` are two different implementations of the Network Time
|
||||||
usually synchronise the system clock faster and with better time accuracy. It
|
Protocol (NTP).
|
||||||
doesn't implement some of the less useful NTP modes like broadcast client or
|
|
||||||
multicast server/client.
|
`chrony` is a newer implementation, which was designed to work well in a wider
|
||||||
|
range of conditions. It can usually synchronise the system clock faster and
|
||||||
|
with better time accuracy. It has many features, but it does not implement some
|
||||||
|
of the less useful NTP modes like broadcast client or multicast server/client.
|
||||||
|
|
||||||
If your computer is connected to the Internet only for few minutes at a time,
|
If your computer is connected to the Internet only for few minutes at a time,
|
||||||
the network connection is often congested, you turn your computer off or
|
the network connection is often congested, you turn your computer off or
|
||||||
suspend it frequently, the clock is not very stable (e.g. there are rapid
|
suspend it frequently, the clock is not very stable (e.g. there are rapid
|
||||||
changes in the temperature or it's a virtual machine), or you want to use NTP
|
changes in the temperature or it is a virtual machine), or you want to use NTP
|
||||||
on an isolated network with no hardware reference clocks in sight, `chrony`
|
on an isolated network with no hardware reference clocks in sight, `chrony`
|
||||||
will probably work much better for you.
|
will probably work better for you.
|
||||||
|
|
||||||
For a more detailed comparison of features and performance, see the
|
For a more detailed comparison of features and performance, see the
|
||||||
https://chrony.tuxfamily.org/comparison.html[comparison page] on the `chrony`
|
https://chrony.tuxfamily.org/comparison.html[comparison page] on the `chrony`
|
||||||
@@ -59,13 +62,13 @@ slewing, which would take a very long time. The `makestep` directive does
|
|||||||
that.
|
that.
|
||||||
|
|
||||||
In order to keep the real-time clock (RTC) close to the true time, so the
|
In order to keep the real-time clock (RTC) close to the true time, so the
|
||||||
system time is reasonably close to the true time when it's initialised on the
|
system time is reasonably close to the true time when it is initialised on the
|
||||||
next boot from the RTC, the `rtcsync` directive enables a mode in which the
|
next boot from the RTC, the `rtcsync` directive enables a mode in which the
|
||||||
system time is periodically copied to the RTC. It is supported on Linux and
|
system time is periodically copied to the RTC. It is supported on Linux and
|
||||||
macOS.
|
macOS.
|
||||||
|
|
||||||
If you want to use public NTP servers from the
|
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:
|
could be:
|
||||||
|
|
||||||
----
|
----
|
||||||
@@ -75,52 +78,36 @@ makestep 1 3
|
|||||||
rtcsync
|
rtcsync
|
||||||
----
|
----
|
||||||
|
|
||||||
=== How do I make an NTP server from an NTP client?
|
=== How do I make an NTP server?
|
||||||
|
|
||||||
You need to add an `allow` directive to the _chrony.conf_ file in order to open
|
You need to add an `allow` directive to the _chrony.conf_ file in order to open
|
||||||
the NTP port and allow `chronyd` to reply to client requests. `allow` with no
|
the NTP port and allow `chronyd` to reply to client requests. `allow` with no
|
||||||
specified subnet allows access from all IPv4 and IPv6 addresses.
|
specified subnet allows access from all IPv4 and IPv6 addresses.
|
||||||
|
|
||||||
=== I have several computers on a LAN. Should be all clients of an external server?
|
=== Should all computers on a LAN be clients of an external server?
|
||||||
|
|
||||||
The best configuration is usually to make one computer the server, with
|
It depends on the requirements. Usually, the best configuration is to make one
|
||||||
the others as clients of it. Add a `local` directive to the server's
|
computer the server, with the others as clients of it. Add a `local` directive
|
||||||
_chrony.conf_ file. This configuration will be better because
|
to the server's _chrony.conf_ file. This configuration will be better because
|
||||||
|
|
||||||
* the load on the external connection is less
|
* the load on the external connection is less
|
||||||
* the load on the external NTP server(s) is less
|
* the load on the external NTP server(s) is less
|
||||||
* if your external connection goes down, the computers on the LAN
|
* if your external connection goes down, the computers on the LAN
|
||||||
will maintain a common time with each other.
|
will maintain a common time with each other.
|
||||||
|
|
||||||
=== Must I specify servers by IP address if DNS is not available on chronyd start?
|
=== Must I specify servers by IP address if DNS is not available on `chronyd` start?
|
||||||
|
|
||||||
No. Starting from version 1.25, `chronyd` will keep trying to resolve
|
No, `chronyd` will keep trying to resolve
|
||||||
the names specified by the `server`, `pool`, and `peer` directives in an
|
the names specified by the `server`, `pool`, and `peer` directives in an
|
||||||
increasing interval until it succeeds. The `online` command can be issued from
|
increasing interval until it succeeds. The `online` command can be issued from
|
||||||
`chronyc` to force `chronyd` to try to resolve the names immediately.
|
`chronyc` to force `chronyd` to try to resolve the names immediately.
|
||||||
|
|
||||||
=== How can I make `chronyd` more secure?
|
=== How can I make `chronyd` more secure?
|
||||||
|
|
||||||
If you don't need to serve time to NTP clients or peers, you can add `port 0`
|
If you do not need to use `chronyc`, or you want to run `chronyc` only
|
||||||
to the _chrony.conf_ file to completely disable the NTP server functionality
|
|
||||||
and prevent NTP requests from reaching `chronyd`. Starting from version 2.0,
|
|
||||||
the NTP server port is open only when client access is allowed by the `allow`
|
|
||||||
directive or command, an NTP peer is configured, or the `broadcast` directive
|
|
||||||
is used.
|
|
||||||
|
|
||||||
If you don't need to use `chronyc` remotely, you can add the following
|
|
||||||
directives to the configuration file to bind the command sockets to the
|
|
||||||
loopback interface. This is done by default since version 2.0.
|
|
||||||
|
|
||||||
----
|
|
||||||
bindcmdaddress 127.0.0.1
|
|
||||||
bindcmdaddress ::1
|
|
||||||
----
|
|
||||||
|
|
||||||
If you don't need to use `chronyc` at all or you need to run `chronyc` only
|
|
||||||
under the root or _chrony_ user (which can access `chronyd` through a Unix
|
under the root or _chrony_ user (which can access `chronyd` through a Unix
|
||||||
domain socket since version 2.2), you can disable the internet command sockets
|
domain socket), you can disable the IPv4 and IPv6 command sockets (by default
|
||||||
completely by adding `cmdport 0` to the configuration file.
|
listening on localhost) by adding `cmdport 0` to the configuration file.
|
||||||
|
|
||||||
You can specify an unprivileged user with the `-u` option, or the `user`
|
You can specify an unprivileged user with the `-u` option, or the `user`
|
||||||
directive in the _chrony.conf_ file, to which `chronyd` will switch after start
|
directive in the _chrony.conf_ file, to which `chronyd` will switch after start
|
||||||
@@ -133,23 +120,23 @@ a very limited range of privileged system calls on behalf of the parent.
|
|||||||
Also, if `chronyd` is compiled with support for the Linux secure computing
|
Also, if `chronyd` is compiled with support for the Linux secure computing
|
||||||
(seccomp) facility, you can enable a system call filter with the `-F` option.
|
(seccomp) facility, you can enable a system call filter with the `-F` option.
|
||||||
It will significantly reduce the kernel attack surface and possibly prevent
|
It will significantly reduce the kernel attack surface and possibly prevent
|
||||||
kernel exploits from the `chronyd` process if it's compromised. It's
|
kernel exploits from the `chronyd` process if it is compromised. It is
|
||||||
recommended to enable the filter only when it's known to work on the version of
|
recommended to enable the filter only when it is known to work on the version of
|
||||||
the system where `chrony` is installed as the filter needs to allow also system
|
the system where `chrony` is installed as the filter needs to allow also system
|
||||||
calls made from libraries that `chronyd` is using (e.g. libc) and different
|
calls made from libraries that `chronyd` is using (e.g. libc) and different
|
||||||
versions or implementations of the libraries may make different system calls.
|
versions or implementations of the libraries might make different system calls.
|
||||||
If the filter is missing some system call, `chronyd` could be killed even in
|
If the filter is missing some system call, `chronyd` could be killed even in
|
||||||
normal operation.
|
normal operation.
|
||||||
|
|
||||||
=== How can I improve the accuracy of the system clock with NTP sources?
|
=== How can I improve the accuracy of the system clock with NTP sources?
|
||||||
|
|
||||||
Select NTP servers that are well synchronised, stable and close to your
|
Select NTP servers that are well synchronised, stable and close to your
|
||||||
network. It's better to use more than one server, three or four is usually
|
network. It is better to use more than one server, three or four is usually
|
||||||
recommended as the minimum, so `chronyd` can detect servers that serve false
|
recommended as the minimum, so `chronyd` can detect servers that serve false
|
||||||
time and combine measurements from multiple sources.
|
time and combine measurements from multiple sources.
|
||||||
|
|
||||||
If you have a network card with hardware timestamping supported on Linux, it
|
If you have a network card with hardware timestamping supported on Linux, it
|
||||||
can be enabled by the *hwtimestamp* directive in the _chrony.conf_ file. It
|
can be enabled by the `hwtimestamp` directive in the _chrony.conf_ file. It
|
||||||
should make local receive and transmit timestamps of NTP packets much more
|
should make local receive and transmit timestamps of NTP packets much more
|
||||||
accurate.
|
accurate.
|
||||||
|
|
||||||
@@ -163,8 +150,8 @@ default values are 6 (64 seconds) for `minpoll`, 10 (1024 seconds) for
|
|||||||
`maxpoll` and 8 (samples) for `polltarget`. The default values should be used
|
`maxpoll` and 8 (samples) for `polltarget`. The default values should be used
|
||||||
for general servers on the Internet. With your own NTP servers, or if you have
|
for general servers on the Internet. With your own NTP servers, or if you have
|
||||||
permission to poll some servers more frequently, setting these options for
|
permission to poll some servers more frequently, setting these options for
|
||||||
shorter polling intervals may significantly improve the accuracy of the system
|
shorter polling intervals might significantly improve the accuracy of the
|
||||||
clock.
|
system clock.
|
||||||
|
|
||||||
The optimal polling interval depends mainly on two factors, stability of the
|
The optimal polling interval depends mainly on two factors, stability of the
|
||||||
network latency and stability of the system clock (which mainly depends on the
|
network latency and stability of the system clock (which mainly depends on the
|
||||||
@@ -174,7 +161,7 @@ temperature change).
|
|||||||
Generally, if the `sourcestats` command usually reports a small number of
|
Generally, if the `sourcestats` command usually reports a small number of
|
||||||
samples retained for a source (e.g. fewer than 16), a shorter polling interval
|
samples retained for a source (e.g. fewer than 16), a shorter polling interval
|
||||||
should be considered. If the number of samples is usually at the maximum of 64,
|
should be considered. If the number of samples is usually at the maximum of 64,
|
||||||
a longer polling interval may work better.
|
a longer polling interval might work better.
|
||||||
|
|
||||||
An example of the directive for an NTP server on the Internet that you are
|
An example of the directive for an NTP server on the Internet that you are
|
||||||
allowed to poll frequently could be
|
allowed to poll frequently could be
|
||||||
@@ -210,7 +197,7 @@ server ntp.local minpoll 2 maxpoll 4 xleave
|
|||||||
|
|
||||||
When combined with local hardware timestamping, good network switches, and even
|
When combined with local hardware timestamping, good network switches, and even
|
||||||
shorter polling intervals, a sub-microsecond accuracy and stability of a few
|
shorter polling intervals, a sub-microsecond accuracy and stability of a few
|
||||||
tens of nanoseconds may be possible. For example:
|
tens of nanoseconds might be possible. For example:
|
||||||
|
|
||||||
----
|
----
|
||||||
server ntp.local minpoll 0 maxpoll 0 xleave
|
server ntp.local minpoll 0 maxpoll 0 xleave
|
||||||
@@ -221,10 +208,11 @@ For best stability, the CPU should be running at a constant frequency (i.e.
|
|||||||
disabled power saving and performance boosting). Energy-Efficient Ethernet
|
disabled power saving and performance boosting). Energy-Efficient Ethernet
|
||||||
(EEE) should be disabled in the network. The switches should be configured to
|
(EEE) should be disabled in the network. The switches should be configured to
|
||||||
prioritize NTP packets, especially if the network is expected to be heavily
|
prioritize NTP packets, especially if the network is expected to be heavily
|
||||||
loaded.
|
loaded. The `dscp` directive can be used to set the Differentiated Services
|
||||||
|
Code Point in transmitted NTP packets if needed.
|
||||||
|
|
||||||
If it is acceptable for NTP clients in the network to send requests at an
|
If it is acceptable for NTP clients in the network to send requests at a high
|
||||||
excessive rate, a sub-second polling interval may be specified. A median filter
|
rate, a sub-second polling interval can be specified. A median filter
|
||||||
can be enabled in order to update the clock at a reduced rate with more stable
|
can be enabled in order to update the clock at a reduced rate with more stable
|
||||||
measurements. For example:
|
measurements. For example:
|
||||||
|
|
||||||
@@ -237,7 +225,7 @@ hwtimestamp eth0 minpoll -6
|
|||||||
|
|
||||||
Yes. With the `-q` option `chronyd` will set the system clock once and exit.
|
Yes. With the `-q` option `chronyd` will set the system clock once and exit.
|
||||||
With the `-Q` option it will print the measured offset without setting the
|
With the `-Q` option it will print the measured offset without setting the
|
||||||
clock. If you don't want to use a configuration file, NTP servers can be
|
clock. If you do not want to use a configuration file, NTP servers can be
|
||||||
specified on the command line. For example:
|
specified on the command line. For example:
|
||||||
|
|
||||||
----
|
----
|
||||||
@@ -249,17 +237,28 @@ well synchronised and responding to all requests. If not synchronised or
|
|||||||
responding, it would take about 10 seconds for `chronyd` to give up and exit
|
responding, it would take about 10 seconds for `chronyd` to give up and exit
|
||||||
with a non-zero status. A faster configuration is possible. A single server can
|
with a non-zero status. A faster configuration is possible. A single server can
|
||||||
be used instead of four servers, the number of measurements can be reduced with
|
be used instead of four servers, the number of measurements can be reduced with
|
||||||
the `maxsamples` option, and a timeout can be specified with the `-t` option.
|
the `maxsamples` option to one (supported in `chrony` version 4.0), and a
|
||||||
The following command would take only up to about 1 second.
|
timeout can be specified with the `-t` option. The following command would take
|
||||||
|
only up to about one second.
|
||||||
|
|
||||||
----
|
----
|
||||||
# chronyd -q -t 1 'server pool.ntp.org iburst maxsamples 1'
|
# chronyd -q -t 1 'server pool.ntp.org iburst maxsamples 1'
|
||||||
----
|
----
|
||||||
|
|
||||||
|
It is not recommended to run `chronyd` with the `-q` option periodically (e.g.
|
||||||
|
from a cron job) as a replacement for the daemon mode, because it performs
|
||||||
|
significantly worse (e.g. the clock is stepped and its frequency is not
|
||||||
|
corrected). If you must run it this way and you are using a public NTP server,
|
||||||
|
make sure `chronyd` does not always start around the first second of a minute,
|
||||||
|
e.g. by adding a random sleep before the `chronyd` command. Public servers
|
||||||
|
typically receive large bursts of requests around the first second as there is
|
||||||
|
a large number of NTP clients started from cron with no delay.
|
||||||
|
|
||||||
=== Can `chronyd` be configured to control the clock like `ntpd`?
|
=== Can `chronyd` be configured to control the clock like `ntpd`?
|
||||||
|
|
||||||
It is not possible to perfectly emulate `ntpd`, but there are some options that
|
It is not possible to perfectly emulate `ntpd`, but there are some options that
|
||||||
can configure `chronyd` to behave more like `ntpd`.
|
can configure `chronyd` to behave more like `ntpd` if there is a reason to
|
||||||
|
prefer that.
|
||||||
|
|
||||||
In the following example the `minsamples` directive slows down the response to
|
In the following example the `minsamples` directive slows down the response to
|
||||||
changes in the frequency and offset of the clock. The `maxslewrate` and
|
changes in the frequency and offset of the clock. The `maxslewrate` and
|
||||||
@@ -279,10 +278,56 @@ maxchange 1000 1 1
|
|||||||
maxclockerror 15
|
maxclockerror 15
|
||||||
----
|
----
|
||||||
|
|
||||||
Note that increasing `minsamples` may cause the offsets in the `tracking` and
|
Note that increasing `minsamples` might cause the offsets in the `tracking` and
|
||||||
`sourcestats` reports/logs to be significantly smaller than the actual offsets
|
`sourcestats` reports/logs to be significantly smaller than the actual offsets
|
||||||
and be unsuitable for monitoring.
|
and be unsuitable for monitoring.
|
||||||
|
|
||||||
|
=== Can NTP server be separated from NTP client?
|
||||||
|
|
||||||
|
Yes, it is possible to run multiple instances of `chronyd` on the same
|
||||||
|
computer. One can be configured as an NTP client, and another as a server. They
|
||||||
|
need to use different pidfiles, NTP ports, command ports, and Unix domain
|
||||||
|
command sockets. The server instance should be started with the `-x` option to
|
||||||
|
avoid touching the clock. It can be configured to serve the system time with
|
||||||
|
the `local` directive, or synchronise its NTP clock to the client instance
|
||||||
|
running on localhost using a non-standard NTP port.
|
||||||
|
|
||||||
|
On Linux, starting with `chrony` version 4.0, it is also possible to run
|
||||||
|
multiple server instances sharing a port to utilise multiple cores of the CPU.
|
||||||
|
Note that the client/server interleaved mode requires that all packets from an
|
||||||
|
address are handled by the same server instance.
|
||||||
|
|
||||||
|
=== Should be a leap smear enabled on NTP server?
|
||||||
|
|
||||||
|
With the `smoothtime` and `leapsecmode` directives it is possible to enable a
|
||||||
|
server leap smear in order to hide leap seconds from clients and force them to
|
||||||
|
follow a slow server's adjustment instead.
|
||||||
|
|
||||||
|
This feature should be used only in local networks and only when necessary,
|
||||||
|
e.g. when the clients cannot be configured to handle the leap seconds as
|
||||||
|
needed, or their number is so large that configuring them all would be
|
||||||
|
impractical. The clients should use only one leap-smearing server, or multiple
|
||||||
|
identically configured leap-smearing servers. Note that some clients can get
|
||||||
|
leap seconds from external sources (e.g. with the `leapsectz` directive in
|
||||||
|
`chrony`) and they will not work correctly with a leap smearing server.
|
||||||
|
|
||||||
|
=== Does `chrony` support PTP?
|
||||||
|
|
||||||
|
No, the Precision Time Protocol (PTP) is not supported and there are no plans
|
||||||
|
to support it. It is a complex protocol, which shares some issues with the
|
||||||
|
NTP broadcast mode. One of the main differences between NTP and PTP is that PTP
|
||||||
|
was designed to be easily supported in hardware (e.g. network switches and
|
||||||
|
routers) in order to make more stable and accurate measurements. PTP relies on
|
||||||
|
the hardware support. NTP does not rely on any support in the hardware, but if
|
||||||
|
it had the same support as PTP, it could perform equally well.
|
||||||
|
|
||||||
|
On Linux, `chrony` supports hardware clocks that some NICs have for PTP. They
|
||||||
|
are called PTP hardware clocks (PHC). They can be used as reference clocks
|
||||||
|
(specified by the `refclock` directive) and for hardware timestamping of NTP
|
||||||
|
packets (enabled by the `hwtimestamp` directive) if the NIC can timestamp other
|
||||||
|
packets than PTP, which is usually the case at least for transmitted packets.
|
||||||
|
The `ethtool -T` command can be used to verify the timestamping support.
|
||||||
|
|
||||||
=== What happened to the `commandkey` and `generatecommandkey` directives?
|
=== What happened to the `commandkey` and `generatecommandkey` directives?
|
||||||
|
|
||||||
They were removed in version 2.2. Authentication is no longer supported in the
|
They were removed in version 2.2. Authentication is no longer supported in the
|
||||||
@@ -299,11 +344,11 @@ following questions.
|
|||||||
|
|
||||||
=== Behind a firewall?
|
=== Behind a firewall?
|
||||||
|
|
||||||
Check the `Reach` value printed by the ``chronyc``'s `sources` command. If it's
|
Check the `Reach` value printed by the ``chronyc``'s `sources` command. If it
|
||||||
zero, it means `chronyd` did not get any valid responses from the NTP server
|
is zero, it means `chronyd` did not get any valid responses from the NTP server
|
||||||
you are trying to use. If there is a firewall between you and the server, the
|
you are trying to use. If there is a firewall between you and the server, the
|
||||||
packets may be blocked. Try using a tool like `wireshark` or `tcpdump` to see
|
packets might be blocked. Try using a tool like `wireshark` or `tcpdump` to see
|
||||||
if you're getting any responses from the server.
|
if you are getting any responses from the server.
|
||||||
|
|
||||||
When `chronyd` is receiving responses from the servers, the output of the
|
When `chronyd` is receiving responses from the servers, the output of the
|
||||||
`sources` command issued few minutes after `chronyd` start might look like
|
`sources` command issued few minutes after `chronyd` start might look like
|
||||||
@@ -320,9 +365,10 @@ MS Name/IP address Stratum Poll Reach LastRx Last sample
|
|||||||
|
|
||||||
=== Are NTP servers specified with the `offline` option?
|
=== Are NTP servers specified with the `offline` option?
|
||||||
|
|
||||||
Check that you're using ``chronyc``'s `online` and `offline` commands
|
Check that the ``chronyc``'s `online` and `offline` commands are used
|
||||||
appropriately. The `activity` command prints the number of sources that are
|
appropriately (e.g. in the system networking scripts). The `activity` command
|
||||||
currently online and offline. For example:
|
prints the number of sources that are currently online and offline. For
|
||||||
|
example:
|
||||||
|
|
||||||
----
|
----
|
||||||
200 OK
|
200 OK
|
||||||
@@ -349,9 +395,9 @@ makestep 1 3
|
|||||||
----
|
----
|
||||||
|
|
||||||
the clock would be stepped in the first three updates if its offset was larger
|
the clock would be stepped in the first three updates if its offset was larger
|
||||||
than one second. Normally, it's recommended to allow the step only in the first
|
than one second. Normally, it is recommended to allow the step only in the first
|
||||||
few updates, but in some cases (e.g. a computer without an RTC or virtual
|
few updates, but in some cases (e.g. a computer without an RTC or virtual
|
||||||
machine which can be suspended and resumed with an incorrect time) it may be
|
machine which can be suspended and resumed with an incorrect time) it might be
|
||||||
necessary to allow the step on any clock update. The example above would change
|
necessary to allow the step on any clock update. The example above would change
|
||||||
to
|
to
|
||||||
|
|
||||||
@@ -363,7 +409,7 @@ makestep 1 -1
|
|||||||
|
|
||||||
A common issue with Windows NTP servers is that they report a very large root
|
A common issue with Windows NTP servers is that they report a very large root
|
||||||
dispersion (e.g. three seconds or more), which causes `chronyd` to ignore the
|
dispersion (e.g. three seconds or more), which causes `chronyd` to ignore the
|
||||||
server for being too inaccurate. The `sources` command may show a valid
|
server for being too inaccurate. The `sources` command might show a valid
|
||||||
measurement, but the server is not selected for synchronisation. You can check
|
measurement, but the server is not selected for synchronisation. You can check
|
||||||
the root dispersion of the server with the ``chronyc``'s `ntpdata` command.
|
the root dispersion of the server with the ``chronyc``'s `ntpdata` command.
|
||||||
|
|
||||||
@@ -374,6 +420,52 @@ synchronisation to such a server. For example:
|
|||||||
maxdistance 16.0
|
maxdistance 16.0
|
||||||
----
|
----
|
||||||
|
|
||||||
|
=== An unreachable source is selected?
|
||||||
|
|
||||||
|
When `chronyd` is configured with multiple time sources, it tries to select the
|
||||||
|
most accurate and stable sources for synchronisation of the system clock. They
|
||||||
|
are marked with the _*_ or _+_ symbol in the report printed by the `sources`
|
||||||
|
command.
|
||||||
|
|
||||||
|
When the best source (marked with the _*_ symbol) becomes unreachable (e.g. NTP
|
||||||
|
server stops responding), `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?
|
=== Using a PPS reference clock?
|
||||||
|
|
||||||
A pulse-per-second (PPS) reference clock requires a non-PPS time source to
|
A pulse-per-second (PPS) reference clock requires a non-PPS time source to
|
||||||
@@ -409,15 +501,15 @@ to be used for synchronisation.
|
|||||||
When accessing `chronyd` remotely, make sure that the _chrony.conf_ file (on
|
When accessing `chronyd` remotely, make sure that the _chrony.conf_ file (on
|
||||||
the computer where `chronyd` is running) has a `cmdallow` entry for the
|
the computer where `chronyd` is running) has a `cmdallow` entry for the
|
||||||
computer you are running `chronyc` on and an appropriate `bindcmdaddress`
|
computer you are running `chronyc` on and an appropriate `bindcmdaddress`
|
||||||
directive. This isn't necessary for localhost.
|
directive. This is not necessary for localhost.
|
||||||
|
|
||||||
Perhaps `chronyd` is not running. Try using the `ps` command (e.g. on Linux,
|
Perhaps `chronyd` is not running. Try using the `ps` command (e.g. on Linux,
|
||||||
`ps -auxw`) to see if it's running. Or try `netstat -a` and see if the ports
|
`ps -auxw`) to see if it is running. Or try `netstat -a` and see if the UDP
|
||||||
123/udp and 323/udp are listening. If `chronyd` is not running, you may have a
|
port 323 is listening. If `chronyd` is not running, you might have a problem
|
||||||
problem with the way you are trying to start it (e.g. at boot time).
|
with the way you are trying to start it (e.g. at boot time).
|
||||||
|
|
||||||
Perhaps you have a firewall set up in a way that blocks packets on port
|
Perhaps you have a firewall set up in a way that blocks packets on the UDP
|
||||||
323/udp. You need to amend the firewall configuration in this case.
|
port 323. You need to amend the firewall configuration in this case.
|
||||||
|
|
||||||
=== I keep getting the error `501 Not authorised`
|
=== I keep getting the error `501 Not authorised`
|
||||||
|
|
||||||
@@ -426,20 +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
|
which is required for some commands. For security reasons, only the root and
|
||||||
_chrony_ users are allowed to access the socket.
|
_chrony_ users are allowed to access the socket.
|
||||||
|
|
||||||
It is also possible that the socket doesn't exist. `chronyd` will not create
|
It is also possible that the socket does not exist. `chronyd` will not create
|
||||||
the socket if the directory has a wrong owner or permissions. In this case
|
the socket if the directory has a wrong owner or permissions. In this case
|
||||||
there should be an error message from `chronyd` in the system log.
|
there should be an error message from `chronyd` in the system log.
|
||||||
|
|
||||||
With versions older than 2.2, which don't use the Unix domain socket, you need
|
=== What is the reference ID reported by the `tracking` command?
|
||||||
to authenticate with the `password` command first,
|
|
||||||
or use the `-a` option to authenticate automatically on start. The
|
|
||||||
configuration file needs to specify a file which contains keys (`keyfile`
|
|
||||||
directive) and which key in the key file should be used for `chronyc`
|
|
||||||
authentication (`commandkey` directive).
|
|
||||||
|
|
||||||
=== Why does `chronyc tracking` always print an IPv4 address as reference ID?
|
The reference ID is a 32-bit value used in NTP to prevent synchronisation
|
||||||
|
loops.
|
||||||
|
|
||||||
The reference ID is a 32-bit value and in versions before 3.0 it was printed in
|
In `chrony` versions before 3.0 it was printed in the
|
||||||
quad-dotted notation, even if the reference source did not actually have an
|
quad-dotted notation, even if the reference source did not actually have an
|
||||||
IPv4 address. For IPv4 addresses, the reference ID is equal to the address, but
|
IPv4 address. For IPv4 addresses, the reference ID is equal to the address, but
|
||||||
for IPv6 addresses it is the first 32 bits of the MD5 sum of the address. For
|
for IPv6 addresses it is the first 32 bits of the MD5 sum of the address. For
|
||||||
@@ -463,7 +551,7 @@ Only by the source code. See _cmdmon.c_ (`chronyd` side) and _client.c_
|
|||||||
=== What is the real-time clock (RTC)?
|
=== What is the real-time clock (RTC)?
|
||||||
|
|
||||||
This is the clock which keeps the time even when your computer is turned off.
|
This is the clock which keeps the time even when your computer is turned off.
|
||||||
It is used to initialise the system clock on boot. It normally doesn't drift
|
It is used to initialise the system clock on boot. It normally does not drift
|
||||||
more than few seconds per day.
|
more than few seconds per day.
|
||||||
|
|
||||||
There are two approaches how `chronyd` can work with it. One is to use the
|
There are two approaches how `chronyd` can work with it. One is to use the
|
||||||
@@ -478,17 +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
|
started with the `-s` option on the next boot, it will set the system time from
|
||||||
the RTC and also compensate for the drift it has measured previously. The
|
the RTC and also compensate for the drift it has measured previously. The
|
||||||
`rtcautotrim` directive can be used to keep the RTC close to the true time, but
|
`rtcautotrim` directive can be used to keep the RTC close to the true time, but
|
||||||
it's not strictly necessary if its only purpose is to set the system clock when
|
it is not strictly necessary if its only purpose is to set the system clock when
|
||||||
`chronyd` is started on boot. See the documentation for details.
|
`chronyd` is started on boot. See the documentation for details.
|
||||||
|
|
||||||
=== I want to use ``chronyd``'s RTC support. Must I disable `hwclock`?
|
=== Does `hwclock` have to be disabled?
|
||||||
|
|
||||||
The `hwclock` program is often set-up by default in the boot and shutdown
|
The `hwclock` program is often set-up by default in the boot and shutdown
|
||||||
scripts with many Linux installations. With the kernel RTC synchronisation
|
scripts with many Linux installations. With the kernel RTC synchronisation
|
||||||
(`rtcsync` directive), the RTC will be set also every 11 minutes as long as the
|
(`rtcsync` directive), the RTC will be set also every 11 minutes as long as the
|
||||||
system clock is synchronised. If you want to use ``chronyd``'s RTC monitoring
|
system clock is synchronised. If you want to use ``chronyd``'s RTC monitoring
|
||||||
(`rtcfile` directive), it's important to disable `hwclock` in the shutdown
|
(`rtcfile` directive), it is important to disable `hwclock` in the shutdown
|
||||||
procedure. If you don't, it will over-write the RTC with a new value, unknown
|
procedure. If you do not that, it will over-write the RTC with a new value, unknown
|
||||||
to `chronyd`. At the next reboot, `chronyd` started with the `-s` option will
|
to `chronyd`. At the next reboot, `chronyd` started with the `-s` option will
|
||||||
compensate this (wrong) time with its estimate of how far the RTC has drifted
|
compensate this (wrong) time with its estimate of how far the RTC has drifted
|
||||||
whilst the power was off, giving a meaningless initial system time.
|
whilst the power was off, giving a meaningless initial system time.
|
||||||
@@ -507,7 +595,7 @@ things
|
|||||||
|
|
||||||
=== I get `Could not open /dev/rtc, Device or resource busy` in my syslog file
|
=== I get `Could not open /dev/rtc, Device or resource busy` in my syslog file
|
||||||
|
|
||||||
Some other program running on the system may be using the device.
|
Some other program running on the system might be using the device.
|
||||||
|
|
||||||
=== What if my computer does not have an RTC or backup battery?
|
=== What if my computer does not have an RTC or backup battery?
|
||||||
|
|
||||||
@@ -522,7 +610,7 @@ observe backward steps.
|
|||||||
=== Can `chronyd` be driven from broadcast/multicast NTP servers?
|
=== Can `chronyd` be driven from broadcast/multicast NTP servers?
|
||||||
|
|
||||||
No, the broadcast/multicast client mode is not supported and there is currently
|
No, the broadcast/multicast client mode is not supported and there is currently
|
||||||
no plan to implement it. While the mode may be useful to simplify configuration
|
no plan to implement it. While this mode can simplify configuration
|
||||||
of clients in large networks, it is inherently less accurate and less secure
|
of clients in large networks, it is inherently less accurate and less secure
|
||||||
(even with authentication) than the ordinary client/server mode.
|
(even with authentication) than the ordinary client/server mode.
|
||||||
|
|
||||||
@@ -539,7 +627,8 @@ thousands of clients using the ordinary client/server mode.
|
|||||||
|
|
||||||
Yes, the `broadcast` directive can be used to enable the broadcast server mode
|
Yes, the `broadcast` directive can be used to enable the broadcast server mode
|
||||||
to serve time to clients in the network which support the broadcast client mode
|
to serve time to clients in the network which support the broadcast client mode
|
||||||
(it's not supported in `chronyd`, see the previous question).
|
(it is not supported in `chronyd`). Note that this mode should generally be
|
||||||
|
avoided. See the previous question.
|
||||||
|
|
||||||
=== Can `chronyd` keep the system clock a fixed offset away from real time?
|
=== Can `chronyd` keep the system clock a fixed offset away from real time?
|
||||||
|
|
||||||
@@ -555,9 +644,21 @@ offline, `chronyd` would make new measurements immediately after issuing the
|
|||||||
`online` command.
|
`online` command.
|
||||||
|
|
||||||
Unless the network connection lasts only few minutes (less than the maximum
|
Unless the network connection lasts only few minutes (less than the maximum
|
||||||
polling interval), the delay is usually not a problem, and it may be acceptable
|
polling interval), the delay is usually not a problem, and it might be acceptable
|
||||||
to keep all sources online all the time.
|
to keep all sources online all the time.
|
||||||
|
|
||||||
|
=== Why is an offset measured between two computers synchronised to each another?
|
||||||
|
|
||||||
|
When two computers are synchronised to each other using the client/server or
|
||||||
|
symmetric NTP mode, there is an expectation that NTP measurements between the
|
||||||
|
two computers made on both ends show an average offset close to zero.
|
||||||
|
|
||||||
|
With `chronyd` that can be expected only when the interleaved mode (`xleave`
|
||||||
|
option) is enabled. Otherwise, `chronyd` will use different transmit timestamps
|
||||||
|
(e.g. daemon timestamp vs kernel timestamp) for serving time and
|
||||||
|
synchronisation of its own clock, which creates an asymmetry in the
|
||||||
|
timestamping and causes the other end to measure a significant offset.
|
||||||
|
|
||||||
== Operating systems
|
== Operating systems
|
||||||
|
|
||||||
=== Does `chrony` support Windows?
|
=== Does `chrony` support Windows?
|
||||||
|
|||||||
@@ -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],
|
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
|
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
|
`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
|
than MD5, which can be used for NTP authentication with a symmetric key. If you
|
||||||
don't want to enable the support, specify the `--disable-sechash` flag to
|
don't want to enable the support, specify the `--disable-sechash` flag to
|
||||||
`configure`.
|
`configure`.
|
||||||
|
|
||||||
If development files for the editline or readline library are available,
|
If development files for the editline library are available,
|
||||||
`chronyc` will be built with line editing support. If you don't want this,
|
`chronyc` will be built with line editing support. If you don't want this,
|
||||||
specify the `--disable-readline` flag to `configure`.
|
specify the `--disable-readline` flag to `configure`.
|
||||||
|
|
||||||
@@ -170,43 +170,6 @@ https://github.com/seccomp/libseccomp[libseccomp] library and the
|
|||||||
the kernel attack surface and possibly prevent kernel exploits from `chronyd`
|
the kernel attack surface and possibly prevent kernel exploits from `chronyd`
|
||||||
if it is compromised.
|
if it is compromised.
|
||||||
|
|
||||||
== Support for line editing libraries
|
|
||||||
|
|
||||||
`chronyc` can be built with support for line editing, this allows you to use
|
|
||||||
the cursor keys to replay and edit old commands. Two libraries are supported
|
|
||||||
which provide such functionality, editline and GNU readline.
|
|
||||||
|
|
||||||
Please note that readline since version 6.0 is licensed under GPLv3+ which is
|
|
||||||
incompatible with chrony's license GPLv2. You should use editline instead if
|
|
||||||
you don't want to use older readline versions.
|
|
||||||
|
|
||||||
The `configure` script will automatically enable the line editing support if
|
|
||||||
one of the supported libraries is available. If they are both available, the
|
|
||||||
editline library will be used.
|
|
||||||
|
|
||||||
If you don't want to use it (in which case `chronyc` will use a minimal command
|
|
||||||
line interface), invoke `configure` like this:
|
|
||||||
|
|
||||||
----
|
|
||||||
./configure --disable-readline other-options...
|
|
||||||
----
|
|
||||||
|
|
||||||
If you have editline, readline or ncurses installed in locations that aren't
|
|
||||||
normally searched by the compiler and linker, you need to use extra options:
|
|
||||||
|
|
||||||
`--with-readline-includes=directory_name`::
|
|
||||||
This defines the name of the directory above the one where `readline.h` is.
|
|
||||||
`readline.h` is assumed to be in `editline` or `readline` subdirectory of the
|
|
||||||
named directory.
|
|
||||||
|
|
||||||
`--with-readline-library=directory_name`::
|
|
||||||
This defines the directory containing the `libedit.a` or `libedit.so` file,
|
|
||||||
or `libreadline.a` or `libreadline.so` file.
|
|
||||||
|
|
||||||
`--with-ncurses-library=directory_name`::
|
|
||||||
This defines the directory containing the `libncurses.a` or `libncurses.so`
|
|
||||||
file.
|
|
||||||
|
|
||||||
== Extra options for package builders
|
== Extra options for package builders
|
||||||
|
|
||||||
The `configure` and `make` procedures have some extra options that may be
|
The `configure` and `make` procedures have some extra options that may be
|
||||||
|
|||||||
@@ -8,9 +8,11 @@ Wants=time-sync.target
|
|||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
Type=oneshot
|
Type=oneshot
|
||||||
# Wait up to ~10 minutes for chronyd to synchronize and the remaining
|
# Wait for chronyd to update the clock and the remaining
|
||||||
# clock correction to be less than 0.1 seconds
|
# correction to be less than 0.1 seconds
|
||||||
ExecStart=/usr/bin/chronyc -h 127.0.0.1,::1 waitsync 600 0.1 0.0 1
|
ExecStart=/usr/bin/chronyc -h 127.0.0.1,::1 waitsync 0 0.1 0.0 1
|
||||||
|
# Wait for at most 3 minutes
|
||||||
|
TimeoutStartSec=180
|
||||||
RemainAfterExit=yes
|
RemainAfterExit=yes
|
||||||
StandardOutput=null
|
StandardOutput=null
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# Use public servers from the pool.ntp.org project.
|
# 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
|
pool pool.ntp.org iburst
|
||||||
|
|
||||||
# Record the rate at which the system clock gains/losses time.
|
# 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) Richard P. Curnow 1997-2003
|
||||||
* Copyright (C) Miroslav Lichvar 2012-2016
|
* Copyright (C) Miroslav Lichvar 2012-2016, 2019-2020
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of version 2 of the GNU General Public License as
|
* it under the terms of version 2 of the GNU General Public License as
|
||||||
|
|||||||
28
local.c
28
local.c
@@ -108,8 +108,8 @@ static double max_clock_error;
|
|||||||
|
|
||||||
#define NSEC_PER_SEC 1000000000
|
#define NSEC_PER_SEC 1000000000
|
||||||
|
|
||||||
static void
|
static double
|
||||||
calculate_sys_precision(void)
|
measure_clock_precision(void)
|
||||||
{
|
{
|
||||||
struct timespec ts, old_ts;
|
struct timespec ts, old_ts;
|
||||||
int iters, diff, best;
|
int iters, diff, best;
|
||||||
@@ -135,18 +135,7 @@ calculate_sys_precision(void)
|
|||||||
|
|
||||||
assert(best > 0);
|
assert(best > 0);
|
||||||
|
|
||||||
precision_quantum = 1.0e-9 * best;
|
return 1.0e-9 * best;
|
||||||
|
|
||||||
/* Get rounded log2 value of the measured precision */
|
|
||||||
precision_log = 0;
|
|
||||||
while (best < 707106781) {
|
|
||||||
precision_log--;
|
|
||||||
best *= 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(precision_log >= -30);
|
|
||||||
|
|
||||||
DEBUG_LOG("Clock precision %.9f (%d)", precision_quantum, precision_log);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
@@ -170,7 +159,16 @@ LCL_Initialise(void)
|
|||||||
current_freq_ppm = 0.0;
|
current_freq_ppm = 0.0;
|
||||||
temp_comp_ppm = 0.0;
|
temp_comp_ppm = 0.0;
|
||||||
|
|
||||||
calculate_sys_precision();
|
precision_quantum = CNF_GetClockPrecision();
|
||||||
|
if (precision_quantum <= 0.0)
|
||||||
|
precision_quantum = measure_clock_precision();
|
||||||
|
|
||||||
|
precision_quantum = CLAMP(1.0e-9, precision_quantum, 1.0);
|
||||||
|
precision_log = round(log(precision_quantum) / log(2.0));
|
||||||
|
/* NTP code doesn't support smaller log than -30 */
|
||||||
|
assert(precision_log >= -30);
|
||||||
|
|
||||||
|
DEBUG_LOG("Clock precision %.9f (%d)", precision_quantum, precision_log);
|
||||||
|
|
||||||
/* This is the maximum allowed frequency offset in ppm, the time must
|
/* This is the maximum allowed frequency offset in ppm, the time must
|
||||||
never stop or run backwards */
|
never stop or run backwards */
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
**********************************************************************
|
**********************************************************************
|
||||||
* Copyright (C) Richard P. Curnow 1997-2003
|
* Copyright (C) Richard P. Curnow 1997-2003
|
||||||
* Copyright (C) Miroslav Lichvar 2011-2014, 2018
|
* Copyright (C) Miroslav Lichvar 2011-2014, 2018-2020
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of version 2 of the GNU General Public License as
|
* it under the terms of version 2 of the GNU General Public License as
|
||||||
|
|||||||
48
main.c
48
main.c
@@ -4,7 +4,7 @@
|
|||||||
**********************************************************************
|
**********************************************************************
|
||||||
* Copyright (C) Richard P. Curnow 1997-2003
|
* Copyright (C) Richard P. Curnow 1997-2003
|
||||||
* Copyright (C) John G. Hasler 2009
|
* Copyright (C) John G. Hasler 2009
|
||||||
* Copyright (C) Miroslav Lichvar 2012-2018
|
* Copyright (C) Miroslav Lichvar 2012-2020
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of version 2 of the GNU General Public License as
|
* it under the terms of version 2 of the GNU General Public License as
|
||||||
@@ -374,8 +374,34 @@ go_daemon(void)
|
|||||||
static void
|
static void
|
||||||
print_help(const char *progname)
|
print_help(const char *progname)
|
||||||
{
|
{
|
||||||
printf("Usage: %s [-4|-6] [-n|-d] [-p|-q|-Q] [-r] [-R] [-s] [-t TIMEOUT] [-f FILE|COMMAND...]\n",
|
printf("Usage: %s [OPTION]... [DIRECTIVE]...\n\n"
|
||||||
progname);
|
"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 do_init_rtc = 0, restarted = 0, client_only = 0, timeout = -1;
|
||||||
int scfilter_level = 0, lock_memory = 0, sched_priority = 0;
|
int scfilter_level = 0, lock_memory = 0, sched_priority = 0;
|
||||||
int clock_control = 1, system_log = 1, log_severity = LOGS_INFO;
|
int clock_control = 1, system_log = 1, log_severity = LOGS_INFO;
|
||||||
int config_args = 0, print_config = 0;
|
int user_check = 1, config_args = 0, print_config = 0;
|
||||||
|
|
||||||
do_platform_checks();
|
do_platform_checks();
|
||||||
|
|
||||||
LOG_Initialise();
|
LOG_Initialise();
|
||||||
|
|
||||||
/* Parse (undocumented) long command-line options */
|
/* Parse long command-line options */
|
||||||
for (optind = 1; optind < argc; optind++) {
|
for (optind = 1; optind < argc; optind++) {
|
||||||
if (!strcmp("--help", argv[optind])) {
|
if (!strcmp("--help", argv[optind])) {
|
||||||
print_help(progname);
|
print_help(progname);
|
||||||
@@ -431,7 +457,7 @@ int main
|
|||||||
optind = 1;
|
optind = 1;
|
||||||
|
|
||||||
/* Parse short command-line options */
|
/* Parse short command-line options */
|
||||||
while ((opt = getopt(argc, argv, "46df:F:hl:L:mnpP:qQrRst:u:vx")) != -1) {
|
while ((opt = getopt(argc, argv, "46df:F:hl:L:mnpP:qQrRst:u:Uvx")) != -1) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case '4':
|
case '4':
|
||||||
case '6':
|
case '6':
|
||||||
@@ -462,7 +488,7 @@ int main
|
|||||||
break;
|
break;
|
||||||
case 'p':
|
case 'p':
|
||||||
print_config = 1;
|
print_config = 1;
|
||||||
client_only = 1;
|
user_check = 0;
|
||||||
nofork = 1;
|
nofork = 1;
|
||||||
system_log = 0;
|
system_log = 0;
|
||||||
break;
|
break;
|
||||||
@@ -479,6 +505,7 @@ int main
|
|||||||
ref_mode = REF_ModePrintOnce;
|
ref_mode = REF_ModePrintOnce;
|
||||||
nofork = 1;
|
nofork = 1;
|
||||||
client_only = 1;
|
client_only = 1;
|
||||||
|
user_check = 0;
|
||||||
clock_control = 0;
|
clock_control = 0;
|
||||||
system_log = 0;
|
system_log = 0;
|
||||||
break;
|
break;
|
||||||
@@ -497,6 +524,9 @@ int main
|
|||||||
case 'u':
|
case 'u':
|
||||||
user = optarg;
|
user = optarg;
|
||||||
break;
|
break;
|
||||||
|
case 'U':
|
||||||
|
user_check = 0;
|
||||||
|
break;
|
||||||
case 'v':
|
case 'v':
|
||||||
print_version();
|
print_version();
|
||||||
return 0;
|
return 0;
|
||||||
@@ -509,7 +539,7 @@ int main
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getuid() && !client_only)
|
if (user_check && getuid() != 0)
|
||||||
LOG_FATAL("Not superuser");
|
LOG_FATAL("Not superuser");
|
||||||
|
|
||||||
/* Turn into a daemon */
|
/* Turn into a daemon */
|
||||||
@@ -595,7 +625,7 @@ int main
|
|||||||
|
|
||||||
/* Drop root privileges if the specified user has a non-zero UID */
|
/* Drop root privileges if the specified user has a non-zero UID */
|
||||||
if (!geteuid() && (pw->pw_uid || pw->pw_gid))
|
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();
|
REF_Initialise();
|
||||||
SST_Initialise();
|
SST_Initialise();
|
||||||
|
|||||||
5
ntp.h
5
ntp.h
@@ -116,10 +116,11 @@ typedef struct {
|
|||||||
/* Enumeration for authentication modes of NTP packets */
|
/* Enumeration for authentication modes of NTP packets */
|
||||||
typedef enum {
|
typedef enum {
|
||||||
NTP_AUTH_NONE = 0, /* No authentication */
|
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, /* MS-SNTP authenticator field */
|
||||||
NTP_AUTH_MSSNTP_EXT, /* MS-SNTP extended 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;
|
} NTP_AuthMode;
|
||||||
|
|
||||||
/* Structure describing an NTP packet */
|
/* 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.
|
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
||||||
|
|
||||||
**********************************************************************
|
**********************************************************************
|
||||||
* Copyright (C) Miroslav Lichvar 2019
|
* Copyright (C) Miroslav Lichvar 2019-2020
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of version 2 of the GNU General Public License as
|
* it under the terms of version 2 of the GNU General Public License as
|
||||||
@@ -175,7 +175,7 @@ NAU_CreateNtsInstance(IPSockAddr *nts_address, const char *name, const IPSockAdd
|
|||||||
void
|
void
|
||||||
NAU_DestroyInstance(NAU_Instance instance)
|
NAU_DestroyInstance(NAU_Instance instance)
|
||||||
{
|
{
|
||||||
if (instance->nts)
|
if (instance->mode == NTP_AUTH_NTS)
|
||||||
NNC_DestroyInstance(instance->nts);
|
NNC_DestroyInstance(instance->nts);
|
||||||
Free(instance);
|
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)
|
if (remainder >= NTP_MIN_MAC_LENGTH && remainder <= NTP_MAX_V4_MAC_LENGTH)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* The NTPv4-specific limit for MAC length enables deterministic parsing of
|
|
||||||
packets with extension fields (RFC 7822), but we support longer MACs in
|
|
||||||
packets with no extension fields for compatibility with older chrony
|
|
||||||
clients. Check if the longer MAC would authenticate the packet before
|
|
||||||
trying to parse the data as an extension field. */
|
|
||||||
if (parsed == NTP_HEADER_LENGTH &&
|
|
||||||
remainder > NTP_MAX_V4_MAC_LENGTH && remainder <= NTP_MAX_MAC_LENGTH &&
|
|
||||||
KEY_CheckAuth(ntohl(*(uint32_t *)(data + parsed)), data, parsed,
|
|
||||||
data + parsed + 4, remainder - 4, NTP_MAX_MAC_LENGTH - 4))
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* Check if this is a valid NTPv4 extension field and skip it */
|
/* Check if this is a valid NTPv4 extension field and skip it */
|
||||||
if (!NEF_ParseField(packet, info->length, parsed, &ef_length, &ef_type, NULL, NULL)) {
|
if (!NEF_ParseField(packet, info->length, parsed, &ef_length, &ef_type, NULL, NULL)) {
|
||||||
/* Invalid MAC or format error */
|
DEBUG_LOG("Invalid format");
|
||||||
DEBUG_LOG("Invalid format or MAC");
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -340,9 +328,6 @@ NAU_ParsePacket(NTP_Packet *packet, NTP_PacketInfo *info)
|
|||||||
/* No MAC */
|
/* No MAC */
|
||||||
return 1;
|
return 1;
|
||||||
} else if (remainder >= NTP_MIN_MAC_LENGTH) {
|
} else if (remainder >= NTP_MIN_MAC_LENGTH) {
|
||||||
/* This is not 100% reliable as a MAC could fail to authenticate and could
|
|
||||||
pass as an extension field, leaving reminder smaller than the minimum MAC
|
|
||||||
length */
|
|
||||||
info->auth.mode = NTP_AUTH_SYMMETRIC;
|
info->auth.mode = NTP_AUTH_SYMMETRIC;
|
||||||
info->auth.mac.start = parsed;
|
info->auth.mac.start = parsed;
|
||||||
info->auth.mac.length = remainder;
|
info->auth.mac.length = remainder;
|
||||||
|
|||||||
14
ntp_core.c
14
ntp_core.c
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
**********************************************************************
|
**********************************************************************
|
||||||
* Copyright (C) Richard P. Curnow 1997-2003
|
* Copyright (C) Richard P. Curnow 1997-2003
|
||||||
* Copyright (C) Miroslav Lichvar 2009-2018
|
* Copyright (C) Miroslav Lichvar 2009-2020
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of version 2 of the GNU General Public License as
|
* it under the terms of version 2 of the GNU General Public License as
|
||||||
@@ -2095,15 +2095,6 @@ NCR_ProcessRxUnknown(NTP_Remote_Address *remote_addr, NTP_Local_Address *local_a
|
|||||||
CLG_LogAuthNtpRequest();
|
CLG_LogAuthNtpRequest();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If it is an NTPv4 packet with a long MAC and no extension fields,
|
|
||||||
respond with an NTPv3 packet to avoid breaking RFC 7822 and keep
|
|
||||||
the length symmetric. Otherwise, respond with the same version. */
|
|
||||||
if (info.version == 4 && info.ext_fields == 0 && info.auth.mode == NTP_AUTH_SYMMETRIC &&
|
|
||||||
info.auth.mac.length > NTP_MAX_V4_MAC_LENGTH)
|
|
||||||
version = 3;
|
|
||||||
else
|
|
||||||
version = info.version;
|
|
||||||
|
|
||||||
local_ntp_rx = local_ntp_tx = NULL;
|
local_ntp_rx = local_ntp_tx = NULL;
|
||||||
tx_ts = NULL;
|
tx_ts = NULL;
|
||||||
interleaved = 0;
|
interleaved = 0;
|
||||||
@@ -2133,6 +2124,9 @@ NCR_ProcessRxUnknown(NTP_Remote_Address *remote_addr, NTP_Local_Address *local_a
|
|||||||
poll = CLG_GetNtpMinPoll();
|
poll = CLG_GetNtpMinPoll();
|
||||||
poll = MAX(poll, message->poll);
|
poll = MAX(poll, message->poll);
|
||||||
|
|
||||||
|
/* Respond with the same version */
|
||||||
|
version = info.version;
|
||||||
|
|
||||||
/* Send a reply */
|
/* Send a reply */
|
||||||
transmit_packet(my_mode, interleaved, poll, version, kod, NULL,
|
transmit_packet(my_mode, interleaved, poll, version, kod, NULL,
|
||||||
&message->receive_ts, &message->transmit_ts,
|
&message->receive_ts, &message->transmit_ts,
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
||||||
|
|
||||||
**********************************************************************
|
**********************************************************************
|
||||||
* Copyright (C) Miroslav Lichvar 2019
|
* Copyright (C) Miroslav Lichvar 2019-2020
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of version 2 of the GNU General Public License as
|
* it under the terms of version 2 of the GNU General Public License as
|
||||||
|
|||||||
2
ntp_io.c
2
ntp_io.c
@@ -4,7 +4,7 @@
|
|||||||
**********************************************************************
|
**********************************************************************
|
||||||
* Copyright (C) Richard P. Curnow 1997-2003
|
* Copyright (C) Richard P. Curnow 1997-2003
|
||||||
* Copyright (C) Timo Teras 2009
|
* Copyright (C) Timo Teras 2009
|
||||||
* Copyright (C) Miroslav Lichvar 2009, 2013-2016, 2018
|
* Copyright (C) Miroslav Lichvar 2009, 2013-2016, 2018-2020
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of version 2 of the GNU General Public License as
|
* it under the terms of version 2 of the GNU General Public License as
|
||||||
|
|||||||
@@ -200,7 +200,8 @@ add_interface(CNF_HwTsInterface *conf_iface)
|
|||||||
req.ifr_data = (char *)&ts_config;
|
req.ifr_data = (char *)&ts_config;
|
||||||
|
|
||||||
if (ioctl(sock_fd, SIOCSHWTSTAMP, &req)) {
|
if (ioctl(sock_fd, SIOCSHWTSTAMP, &req)) {
|
||||||
DEBUG_LOG("ioctl(%s) failed : %s", "SIOCSHWTSTAMP", strerror(errno));
|
LOG(errno == EPERM ? LOGS_ERR : LOGS_DEBUG,
|
||||||
|
"ioctl(%s) failed : %s", "SIOCSHWTSTAMP", strerror(errno));
|
||||||
|
|
||||||
/* Check the current timestamping configuration in case this interface
|
/* Check the current timestamping configuration in case this interface
|
||||||
allows only reading of the configuration and it was already configured
|
allows only reading of the configuration and it was already configured
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
**********************************************************************
|
**********************************************************************
|
||||||
* Copyright (C) Richard P. Curnow 1997-2003
|
* Copyright (C) Richard P. Curnow 1997-2003
|
||||||
* Copyright (C) Miroslav Lichvar 2011-2012, 2014, 2016
|
* Copyright (C) Miroslav Lichvar 2011-2012, 2014, 2016, 2020
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of version 2 of the GNU General Public License as
|
* it under the terms of version 2 of the GNU General Public License as
|
||||||
@@ -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));
|
DEBUG_LOG("(%d) %s", i + 1, UTI_IPToString(&new_addr.ip_addr));
|
||||||
|
|
||||||
if (us->pool_id != INVALID_POOL) {
|
if (us->pool_id != INVALID_POOL) {
|
||||||
/* In the pool resolving mode, try to replace all sources from
|
/* In the pool resolving mode, try to replace a source from
|
||||||
the pool which don't have a real address yet */
|
the pool which does not have a real address yet */
|
||||||
for (j = 0; j < ARR_GetSize(records); j++) {
|
for (j = 0; j < ARR_GetSize(records); j++) {
|
||||||
record = get_record(j);
|
record = get_record(j);
|
||||||
if (!record->remote_addr || record->pool_id != us->pool_id ||
|
if (!record->remote_addr || record->pool_id != us->pool_id ||
|
||||||
@@ -454,6 +454,7 @@ process_resolved_name(struct UnresolvedSource *us, IPAddr *ip_addrs, int n_addrs
|
|||||||
old_addr = *record->remote_addr;
|
old_addr = *record->remote_addr;
|
||||||
new_addr.port = old_addr.port;
|
new_addr.port = old_addr.port;
|
||||||
if (replace_source_connectable(&old_addr, &new_addr))
|
if (replace_source_connectable(&old_addr, &new_addr))
|
||||||
|
;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -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 */
|
/* Make sure the name is at least printable and has no spaces */
|
||||||
for (i = 0; name[i] != '\0'; i++) {
|
for (i = 0; name[i] != '\0'; i++) {
|
||||||
if (!isgraph(name[i]))
|
if (!isgraph((unsigned char)name[i]))
|
||||||
return NSR_InvalidName;
|
return NSR_InvalidName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -196,7 +196,7 @@ process_response(NKC_Instance inst)
|
|||||||
inst->server_name[length] = '\0';
|
inst->server_name[length] = '\0';
|
||||||
|
|
||||||
/* Make sure the name is printable and has no spaces */
|
/* 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) {
|
if (i != length) {
|
||||||
DEBUG_LOG("Invalid server name");
|
DEBUG_LOG("Invalid server name");
|
||||||
@@ -335,15 +335,17 @@ NKC_Start(NKC_Instance inst)
|
|||||||
local_addr.port = 0;
|
local_addr.port = 0;
|
||||||
iface = CNF_GetBindAcquisitionInterface();
|
iface = CNF_GetBindAcquisitionInterface();
|
||||||
|
|
||||||
sock_fd = SCK_OpenTcpSocket(&inst->address, &local_addr, iface, 0);
|
|
||||||
if (sock_fd < 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* Make a label containing both the address and name of the server */
|
/* Make a label containing both the address and name of the server */
|
||||||
if (snprintf(label, sizeof (label), "%s (%s)",
|
if (snprintf(label, sizeof (label), "%s (%s)",
|
||||||
UTI_IPSockAddrToString(&inst->address), inst->name) >= sizeof (label))
|
UTI_IPSockAddrToString(&inst->address), inst->name) >= sizeof (label))
|
||||||
;
|
;
|
||||||
|
|
||||||
|
sock_fd = SCK_OpenTcpSocket(&inst->address, &local_addr, iface, 0);
|
||||||
|
if (sock_fd < 0) {
|
||||||
|
LOG(LOGS_ERR, "Could not connect to %s", label);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Start an NTS-KE session */
|
/* Start an NTS-KE session */
|
||||||
if (!NKSN_StartSession(inst->session, sock_fd, label, client_credentials, CLIENT_TIMEOUT)) {
|
if (!NKSN_StartSession(inst->session, sock_fd, label, client_credentials, CLIENT_TIMEOUT)) {
|
||||||
SCK_CloseSocket(sock_fd);
|
SCK_CloseSocket(sock_fd);
|
||||||
|
|||||||
@@ -556,7 +556,7 @@ error:
|
|||||||
|
|
||||||
#define MAX_WORDS 2
|
#define MAX_WORDS 2
|
||||||
|
|
||||||
static void
|
static int
|
||||||
load_keys(void)
|
load_keys(void)
|
||||||
{
|
{
|
||||||
char *dump_dir, line[1024], *words[MAX_WORDS];
|
char *dump_dir, line[1024], *words[MAX_WORDS];
|
||||||
@@ -568,11 +568,11 @@ load_keys(void)
|
|||||||
|
|
||||||
dump_dir = CNF_GetNtsDumpDir();
|
dump_dir = CNF_GetNtsDumpDir();
|
||||||
if (!dump_dir)
|
if (!dump_dir)
|
||||||
return;
|
return 0;
|
||||||
|
|
||||||
f = UTI_OpenFile(dump_dir, DUMP_FILENAME, NULL, 'r', 0);
|
f = UTI_OpenFile(dump_dir, DUMP_FILENAME, NULL, 'r', 0);
|
||||||
if (!f)
|
if (!f)
|
||||||
return;
|
return 0;
|
||||||
|
|
||||||
if (!fgets(line, sizeof (line), f) || strcmp(line, DUMP_IDENTIFIER) != 0 ||
|
if (!fgets(line, sizeof (line), f) || strcmp(line, DUMP_IDENTIFIER) != 0 ||
|
||||||
!fgets(line, sizeof (line), f) || UTI_SplitString(line, words, MAX_WORDS) != 2 ||
|
!fgets(line, sizeof (line), f) || UTI_SplitString(line, words, MAX_WORDS) != 2 ||
|
||||||
@@ -607,11 +607,13 @@ load_keys(void)
|
|||||||
|
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
|
||||||
return;
|
return 1;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
DEBUG_LOG("Could not %s server keys", "load");
|
DEBUG_LOG("Could not %s server keys", "load");
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
@@ -646,7 +648,7 @@ run_helper(uid_t uid, gid_t gid, int scfilter_level)
|
|||||||
LOG_SetMinSeverity(log_severity);
|
LOG_SetMinSeverity(log_severity);
|
||||||
|
|
||||||
if (!geteuid() && (uid || gid))
|
if (!geteuid() && (uid || gid))
|
||||||
SYS_DropRoot(uid, gid);
|
SYS_DropRoot(uid, gid, SYS_NTSKE_HELPER);
|
||||||
|
|
||||||
NKS_Initialise();
|
NKS_Initialise();
|
||||||
|
|
||||||
@@ -764,10 +766,12 @@ NKS_Initialise(void)
|
|||||||
server_sock_fd4 = open_socket(IPADDR_INET4);
|
server_sock_fd4 = open_socket(IPADDR_INET4);
|
||||||
server_sock_fd6 = open_socket(IPADDR_INET6);
|
server_sock_fd6 = open_socket(IPADDR_INET6);
|
||||||
|
|
||||||
load_keys();
|
|
||||||
|
|
||||||
key_rotation_interval = MAX(CNF_GetNtsRotate(), 0);
|
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) {
|
if (key_rotation_interval > 0) {
|
||||||
key_delay = key_rotation_interval - (SCH_GetLastEventMonoTime() - last_server_key_ts);
|
key_delay = key_rotation_interval - (SCH_GetLastEventMonoTime() - last_server_key_ts);
|
||||||
SCH_AddTimeoutByDelay(MAX(key_delay, 0.0), key_timeout, NULL);
|
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
|
int
|
||||||
NKSN_GetKeys(NKSN_Instance inst, SIV_Algorithm siv, NKE_Key *c2s, NKE_Key *s2c)
|
NKSN_GetKeys(NKSN_Instance inst, SIV_Algorithm siv, NKE_Key *c2s, NKE_Key *s2c)
|
||||||
{
|
{
|
||||||
c2s->length = SIV_GetKeyLength(siv);
|
int length = SIV_GetKeyLength(siv);
|
||||||
s2c->length = SIV_GetKeyLength(siv);
|
|
||||||
assert(c2s->length <= sizeof (c2s->key));
|
if (length <= 0 || length > sizeof (c2s->key) || length > sizeof (s2c->key)) {
|
||||||
assert(s2c->length <= sizeof (s2c->key));
|
DEBUG_LOG("Invalid algorithm");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (gnutls_prf_rfc5705(inst->tls_session,
|
if (gnutls_prf_rfc5705(inst->tls_session,
|
||||||
sizeof (NKE_EXPORTER_LABEL) - 1, NKE_EXPORTER_LABEL,
|
sizeof (NKE_EXPORTER_LABEL) - 1, NKE_EXPORTER_LABEL,
|
||||||
sizeof (NKE_EXPORTER_CONTEXT_C2S) - 1, NKE_EXPORTER_CONTEXT_C2S,
|
sizeof (NKE_EXPORTER_CONTEXT_C2S) - 1, NKE_EXPORTER_CONTEXT_C2S,
|
||||||
c2s->length, (char *)c2s->key) < 0)
|
length, (char *)c2s->key) < 0 ||
|
||||||
return 0;
|
gnutls_prf_rfc5705(inst->tls_session,
|
||||||
if (gnutls_prf_rfc5705(inst->tls_session,
|
|
||||||
sizeof (NKE_EXPORTER_LABEL) - 1, NKE_EXPORTER_LABEL,
|
sizeof (NKE_EXPORTER_LABEL) - 1, NKE_EXPORTER_LABEL,
|
||||||
sizeof (NKE_EXPORTER_CONTEXT_S2C) - 1, NKE_EXPORTER_CONTEXT_S2C,
|
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;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
c2s->length = length;
|
||||||
|
s2c->length = length;
|
||||||
|
|
||||||
return 1;
|
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,
|
if (!SIV_Encrypt(siv, nonce, nonce_length, packet, assoc_length,
|
||||||
plaintext, plaintext_length, ciphertext, ciphertext_length)) {
|
plaintext, plaintext_length, ciphertext, ciphertext_length)) {
|
||||||
DEBUG_LOG("SIV encrypt failed");
|
DEBUG_LOG("SIV encrypt failed");
|
||||||
|
info->length = assoc_length;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ struct NNC_Instance_Record {
|
|||||||
const IPSockAddr *ntp_address;
|
const IPSockAddr *ntp_address;
|
||||||
IPSockAddr nts_address;
|
IPSockAddr nts_address;
|
||||||
char *name;
|
char *name;
|
||||||
|
|
||||||
NKC_Instance nke;
|
NKC_Instance nke;
|
||||||
SIV_Instance siv;
|
SIV_Instance siv;
|
||||||
|
|
||||||
@@ -66,6 +67,7 @@ struct NNC_Instance_Record {
|
|||||||
NKE_Cookie cookies[NTS_MAX_COOKIES];
|
NKE_Cookie cookies[NTS_MAX_COOKIES];
|
||||||
int num_cookies;
|
int num_cookies;
|
||||||
int cookie_index;
|
int cookie_index;
|
||||||
|
int auth_ready;
|
||||||
int nak_response;
|
int nak_response;
|
||||||
int ok_response;
|
int ok_response;
|
||||||
unsigned char nonce[NTS_MIN_UNPADDED_NONCE_LENGTH];
|
unsigned char nonce[NTS_MIN_UNPADDED_NONCE_LENGTH];
|
||||||
@@ -82,6 +84,13 @@ static void load_cookies(NNC_Instance inst);
|
|||||||
static void
|
static void
|
||||||
reset_instance(NNC_Instance inst)
|
reset_instance(NNC_Instance inst)
|
||||||
{
|
{
|
||||||
|
if (inst->nke)
|
||||||
|
NKC_DestroyInstance(inst->nke);
|
||||||
|
inst->nke = NULL;
|
||||||
|
if (inst->siv)
|
||||||
|
SIV_DestroyInstance(inst->siv);
|
||||||
|
inst->siv = NULL;
|
||||||
|
|
||||||
inst->load_attempt = 0;
|
inst->load_attempt = 0;
|
||||||
inst->nke_attempts = 0;
|
inst->nke_attempts = 0;
|
||||||
inst->next_nke_attempt = 0.0;
|
inst->next_nke_attempt = 0.0;
|
||||||
@@ -92,6 +101,7 @@ reset_instance(NNC_Instance inst)
|
|||||||
memset(inst->cookies, 0, sizeof (inst->cookies));
|
memset(inst->cookies, 0, sizeof (inst->cookies));
|
||||||
inst->num_cookies = 0;
|
inst->num_cookies = 0;
|
||||||
inst->cookie_index = 0;
|
inst->cookie_index = 0;
|
||||||
|
inst->auth_ready = 0;
|
||||||
inst->nak_response = 0;
|
inst->nak_response = 0;
|
||||||
inst->ok_response = 1;
|
inst->ok_response = 1;
|
||||||
memset(inst->nonce, 0, sizeof (inst->nonce));
|
memset(inst->nonce, 0, sizeof (inst->nonce));
|
||||||
@@ -125,10 +135,7 @@ NNC_DestroyInstance(NNC_Instance inst)
|
|||||||
{
|
{
|
||||||
save_cookies(inst);
|
save_cookies(inst);
|
||||||
|
|
||||||
if (inst->nke)
|
reset_instance(inst);
|
||||||
NKC_DestroyInstance(inst->nke);
|
|
||||||
if (inst->siv)
|
|
||||||
SIV_DestroyInstance(inst->siv);
|
|
||||||
|
|
||||||
Free(inst->name);
|
Free(inst->name);
|
||||||
Free(inst);
|
Free(inst);
|
||||||
@@ -266,8 +273,6 @@ get_cookies(NNC_Instance inst)
|
|||||||
inst->last_nke_success = now;
|
inst->last_nke_success = now;
|
||||||
inst->cookie_index = 0;
|
inst->cookie_index = 0;
|
||||||
|
|
||||||
inst->nak_response = 0;
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -276,6 +281,13 @@ get_cookies(NNC_Instance inst)
|
|||||||
int
|
int
|
||||||
NNC_PrepareForAuth(NNC_Instance inst)
|
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) */
|
/* Try to reload saved keys and cookies (once for the NTS-KE address) */
|
||||||
if (!inst->load_attempt) {
|
if (!inst->load_attempt) {
|
||||||
load_cookies(inst);
|
load_cookies(inst);
|
||||||
@@ -288,6 +300,8 @@ NNC_PrepareForAuth(NNC_Instance inst)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inst->nak_response = 0;
|
||||||
|
|
||||||
if (!inst->siv)
|
if (!inst->siv)
|
||||||
inst->siv = SIV_CreateInstance(inst->context.algorithm);
|
inst->siv = SIV_CreateInstance(inst->context.algorithm);
|
||||||
|
|
||||||
@@ -297,9 +311,7 @@ NNC_PrepareForAuth(NNC_Instance inst)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Prepare data for NNC_GenerateRequestAuth() */
|
inst->auth_ready = 1;
|
||||||
UTI_GetRandomBytes(inst->uniq_id, sizeof (inst->uniq_id));
|
|
||||||
UTI_GetRandomBytes(inst->nonce, sizeof (inst->nonce));
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -314,14 +326,22 @@ NNC_GenerateRequestAuth(NNC_Instance inst, NTP_Packet *packet,
|
|||||||
int i, req_cookies;
|
int i, req_cookies;
|
||||||
void *ef_body;
|
void *ef_body;
|
||||||
|
|
||||||
if (inst->num_cookies == 0 || !inst->siv)
|
if (!inst->auth_ready)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
inst->auth_ready = 0;
|
||||||
|
|
||||||
|
if (inst->num_cookies <= 0 || !inst->siv)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (info->mode != MODE_CLIENT)
|
if (info->mode != MODE_CLIENT)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
cookie = &inst->cookies[inst->cookie_index];
|
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));
|
MAX_TOTAL_COOKIE_LENGTH / (cookie->length + 4));
|
||||||
|
|
||||||
if (!NEF_AddField(packet, info, NTP_EF_NTS_UNIQUE_IDENTIFIER,
|
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))
|
(const unsigned char *)"", 0, NTP_MAX_V4_MAC_LENGTH + 4))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
inst->num_cookies--;
|
|
||||||
inst->cookie_index = (inst->cookie_index + 1) % NTS_MAX_COOKIES;
|
|
||||||
inst->nak_response = 0;
|
|
||||||
inst->ok_response = 0;
|
inst->ok_response = 0;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
@@ -427,7 +444,7 @@ NNC_CheckResponseAuth(NNC_Instance inst, NTP_Packet *packet,
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Accept at most one response per request */
|
/* Accept at most one response per request */
|
||||||
if (inst->ok_response)
|
if (inst->ok_response || inst->auth_ready)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (!inst->siv ||
|
if (!inst->siv ||
|
||||||
@@ -506,11 +523,6 @@ NNC_ChangeAddress(NNC_Instance inst, IPAddr *address)
|
|||||||
{
|
{
|
||||||
save_cookies(inst);
|
save_cookies(inst);
|
||||||
|
|
||||||
if (inst->nke)
|
|
||||||
NKC_DestroyInstance(inst->nke);
|
|
||||||
|
|
||||||
inst->nke = NULL;
|
|
||||||
inst->num_cookies = 0;
|
|
||||||
inst->nts_address.ip_addr = *address;
|
inst->nts_address.ip_addr = *address;
|
||||||
|
|
||||||
reset_instance(inst);
|
reset_instance(inst);
|
||||||
@@ -529,7 +541,7 @@ save_cookies(NNC_Instance inst)
|
|||||||
FILE *f;
|
FILE *f;
|
||||||
int i;
|
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;
|
return;
|
||||||
|
|
||||||
dump_dir = CNF_GetNtsDumpDir();
|
dump_dir = CNF_GetNtsDumpDir();
|
||||||
@@ -546,9 +558,10 @@ save_cookies(NNC_Instance inst)
|
|||||||
context_time = inst->last_nke_success - SCH_GetLastEventMonoTime();
|
context_time = inst->last_nke_success - SCH_GetLastEventMonoTime();
|
||||||
context_time += UTI_TimespecToDouble(&now);
|
context_time += UTI_TimespecToDouble(&now);
|
||||||
|
|
||||||
if (fprintf(f, "%s%.1f\n%s %d\n%u %d ",
|
if (fprintf(f, "%s%s\n%.1f\n%s %d\n%u %d ",
|
||||||
DUMP_IDENTIFIER, context_time, UTI_IPToString(&inst->ntp_address->ip_addr),
|
DUMP_IDENTIFIER, inst->name, context_time,
|
||||||
inst->ntp_address->port, inst->context_id, (int)inst->context.algorithm) < 0 ||
|
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)) ||
|
!UTI_BytesToHex(inst->context.s2c.key, inst->context.s2c.length, buf, sizeof (buf)) ||
|
||||||
fprintf(f, "%s ", buf) < 0 ||
|
fprintf(f, "%s ", buf) < 0 ||
|
||||||
!UTI_BytesToHex(inst->context.c2s.key, inst->context.c2s.length, buf, sizeof (buf)) ||
|
!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;
|
inst->siv = NULL;
|
||||||
|
|
||||||
if (!fgets(line, sizeof (line), f) || strcmp(line, DUMP_IDENTIFIER) != 0 ||
|
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 ||
|
!fgets(line, sizeof (line), f) || UTI_SplitString(line, words, MAX_WORDS) != 1 ||
|
||||||
sscanf(words[0], "%lf", &context_time) != 1 ||
|
sscanf(words[0], "%lf", &context_time) != 1 ||
|
||||||
!fgets(line, sizeof (line), f) || UTI_SplitString(line, words, MAX_WORDS) != 2 ||
|
!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;
|
NKE_Cookie cookie;
|
||||||
void *ef_body;
|
void *ef_body;
|
||||||
|
|
||||||
|
*kod = 0;
|
||||||
|
|
||||||
if (!server)
|
if (!server)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
*kod = 0;
|
|
||||||
|
|
||||||
server->num_cookies = 0;
|
server->num_cookies = 0;
|
||||||
server->req_tx = packet->transmit_ts;
|
server->req_tx = packet->transmit_ts;
|
||||||
|
|
||||||
|
|||||||
@@ -181,7 +181,7 @@ RCL_AddRefclock(RefclockParameters *params)
|
|||||||
LOG_FATAL("refclock tai option requires leapsectz");
|
LOG_FATAL("refclock tai option requires leapsectz");
|
||||||
|
|
||||||
inst->data = NULL;
|
inst->data = NULL;
|
||||||
inst->driver_parameter = params->driver_parameter;
|
inst->driver_parameter = Strdup(params->driver_parameter);
|
||||||
inst->driver_parameter_length = 0;
|
inst->driver_parameter_length = 0;
|
||||||
inst->driver_poll = params->driver_poll;
|
inst->driver_poll = params->driver_poll;
|
||||||
inst->poll = params->poll;
|
inst->poll = params->poll;
|
||||||
@@ -261,8 +261,6 @@ RCL_AddRefclock(RefclockParameters *params)
|
|||||||
params->driver_name, UTI_RefidToString(inst->ref_id),
|
params->driver_name, UTI_RefidToString(inst->ref_id),
|
||||||
inst->poll, inst->driver_poll, params->filter_length);
|
inst->poll, inst->driver_poll, params->filter_length);
|
||||||
|
|
||||||
Free(params->driver_name);
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
**********************************************************************
|
**********************************************************************
|
||||||
* Copyright (C) Richard P. Curnow 1997-2003
|
* Copyright (C) Richard P. Curnow 1997-2003
|
||||||
* Copyright (C) Miroslav Lichvar 2009-2018
|
* Copyright (C) Miroslav Lichvar 2009-2018, 2020
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of version 2 of the GNU General Public License as
|
* it under the terms of version 2 of the GNU General Public License as
|
||||||
|
|||||||
10
reports.h
10
reports.h
@@ -36,7 +36,14 @@ typedef struct {
|
|||||||
int stratum;
|
int stratum;
|
||||||
int poll;
|
int poll;
|
||||||
enum {RPT_NTP_CLIENT, RPT_NTP_PEER, RPT_LOCAL_REFERENCE} mode;
|
enum {RPT_NTP_CLIENT, RPT_NTP_PEER, RPT_LOCAL_REFERENCE} mode;
|
||||||
enum {RPT_SYNC, RPT_UNREACH, RPT_FALSETICKER, RPT_JITTERY, RPT_CANDIDATE, RPT_OUTLIER} state;
|
enum {
|
||||||
|
RPT_NONSELECTABLE,
|
||||||
|
RPT_FALSETICKER,
|
||||||
|
RPT_JITTERY,
|
||||||
|
RPT_SELECTABLE,
|
||||||
|
RPT_UNSELECTED,
|
||||||
|
RPT_SELECTED,
|
||||||
|
} state;
|
||||||
|
|
||||||
int reachability;
|
int reachability;
|
||||||
unsigned long latest_meas_ago; /* seconds */
|
unsigned long latest_meas_ago; /* seconds */
|
||||||
@@ -183,6 +190,7 @@ typedef struct {
|
|||||||
IPAddr ip_addr;
|
IPAddr ip_addr;
|
||||||
char state_char;
|
char state_char;
|
||||||
int authentication;
|
int authentication;
|
||||||
|
NTP_Leap leap;
|
||||||
int conf_options;
|
int conf_options;
|
||||||
int eff_options;
|
int eff_options;
|
||||||
uint32_t last_sample_ago;
|
uint32_t last_sample_ago;
|
||||||
|
|||||||
4
sched.c
4
sched.c
@@ -799,14 +799,14 @@ SCH_MainLoop(void)
|
|||||||
LCL_ReadRawTime(&now);
|
LCL_ReadRawTime(&now);
|
||||||
LCL_CookTime(&now, &cooked, &err);
|
LCL_CookTime(&now, &cooked, &err);
|
||||||
|
|
||||||
|
update_monotonic_time(&now, &last_select_ts_raw);
|
||||||
|
|
||||||
/* Check if the time didn't jump unexpectedly */
|
/* Check if the time didn't jump unexpectedly */
|
||||||
if (!check_current_time(&saved_now, &now, status == 0, &saved_tv, ptv)) {
|
if (!check_current_time(&saved_now, &now, status == 0, &saved_tv, ptv)) {
|
||||||
/* Cook the time again after handling the step */
|
/* Cook the time again after handling the step */
|
||||||
LCL_CookTime(&now, &cooked, &err);
|
LCL_CookTime(&now, &cooked, &err);
|
||||||
}
|
}
|
||||||
|
|
||||||
update_monotonic_time(&cooked, &last_select_ts);
|
|
||||||
|
|
||||||
last_select_ts_raw = now;
|
last_select_ts_raw = now;
|
||||||
last_select_ts = cooked;
|
last_select_ts = cooked;
|
||||||
last_select_ts_err = err;
|
last_select_ts_err = err;
|
||||||
|
|||||||
@@ -204,6 +204,9 @@ SIV_Encrypt(SIV_Instance instance,
|
|||||||
{
|
{
|
||||||
size_t clen = ciphertext_length;
|
size_t clen = ciphertext_length;
|
||||||
|
|
||||||
|
if (!instance->cipher)
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (nonce_length < 1 || assoc_length < 0 ||
|
if (nonce_length < 1 || assoc_length < 0 ||
|
||||||
plaintext_length < 0 || ciphertext_length < 0)
|
plaintext_length < 0 || ciphertext_length < 0)
|
||||||
return 0;
|
return 0;
|
||||||
@@ -232,6 +235,9 @@ SIV_Decrypt(SIV_Instance instance,
|
|||||||
{
|
{
|
||||||
size_t plen = plaintext_length;
|
size_t plen = plaintext_length;
|
||||||
|
|
||||||
|
if (!instance->cipher)
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (nonce_length < 1 || assoc_length < 0 ||
|
if (nonce_length < 1 || assoc_length < 0 ||
|
||||||
plaintext_length < 0 || ciphertext_length < 0)
|
plaintext_length < 0 || ciphertext_length < 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
10
siv_nettle.c
10
siv_nettle.c
@@ -39,6 +39,7 @@
|
|||||||
|
|
||||||
struct SIV_Instance_Record {
|
struct SIV_Instance_Record {
|
||||||
struct siv_cmac_aes128_ctx siv;
|
struct siv_cmac_aes128_ctx siv;
|
||||||
|
int key_set;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
@@ -52,6 +53,7 @@ SIV_CreateInstance(SIV_Algorithm algorithm)
|
|||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
instance = MallocNew(struct SIV_Instance_Record);
|
instance = MallocNew(struct SIV_Instance_Record);
|
||||||
|
instance->key_set = 0;
|
||||||
|
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
@@ -86,6 +88,8 @@ SIV_SetKey(SIV_Instance instance, const unsigned char *key, int length)
|
|||||||
|
|
||||||
siv_cmac_aes128_set_key(&instance->siv, key);
|
siv_cmac_aes128_set_key(&instance->siv, key);
|
||||||
|
|
||||||
|
instance->key_set = 1;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,6 +112,9 @@ SIV_Encrypt(SIV_Instance instance,
|
|||||||
const void *plaintext, int plaintext_length,
|
const void *plaintext, int plaintext_length,
|
||||||
unsigned char *ciphertext, int ciphertext_length)
|
unsigned char *ciphertext, int ciphertext_length)
|
||||||
{
|
{
|
||||||
|
if (!instance->key_set)
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (nonce_length < SIV_MIN_NONCE_SIZE || assoc_length < 0 ||
|
if (nonce_length < SIV_MIN_NONCE_SIZE || assoc_length < 0 ||
|
||||||
plaintext_length < 0 || plaintext_length > ciphertext_length ||
|
plaintext_length < 0 || plaintext_length > ciphertext_length ||
|
||||||
plaintext_length + SIV_DIGEST_SIZE != ciphertext_length)
|
plaintext_length + SIV_DIGEST_SIZE != ciphertext_length)
|
||||||
@@ -130,6 +137,9 @@ SIV_Decrypt(SIV_Instance instance,
|
|||||||
const unsigned char *ciphertext, int ciphertext_length,
|
const unsigned char *ciphertext, int ciphertext_length,
|
||||||
void *plaintext, int plaintext_length)
|
void *plaintext, int plaintext_length)
|
||||||
{
|
{
|
||||||
|
if (!instance->key_set)
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (nonce_length < SIV_MIN_NONCE_SIZE || assoc_length < 0 ||
|
if (nonce_length < SIV_MIN_NONCE_SIZE || assoc_length < 0 ||
|
||||||
plaintext_length < 0 || plaintext_length > ciphertext_length ||
|
plaintext_length < 0 || plaintext_length > ciphertext_length ||
|
||||||
plaintext_length + SIV_DIGEST_SIZE != ciphertext_length)
|
plaintext_length + SIV_DIGEST_SIZE != ciphertext_length)
|
||||||
|
|||||||
70
socket.c
70
socket.c
@@ -4,7 +4,7 @@
|
|||||||
**********************************************************************
|
**********************************************************************
|
||||||
* Copyright (C) Richard P. Curnow 1997-2003
|
* Copyright (C) Richard P. Curnow 1997-2003
|
||||||
* Copyright (C) Timo Teras 2009
|
* Copyright (C) Timo Teras 2009
|
||||||
* Copyright (C) Miroslav Lichvar 2009, 2013-2019
|
* Copyright (C) Miroslav Lichvar 2009, 2013-2020
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of version 2 of the GNU General Public License as
|
* it under the terms of version 2 of the GNU General Public License as
|
||||||
@@ -742,18 +742,10 @@ process_header(struct msghdr *msg, int msg_length, int sock_fd, int flags,
|
|||||||
SCK_Message *message)
|
SCK_Message *message)
|
||||||
{
|
{
|
||||||
struct cmsghdr *cmsg;
|
struct cmsghdr *cmsg;
|
||||||
|
int r = 1;
|
||||||
|
|
||||||
if (msg->msg_iovlen != 1) {
|
if (msg->msg_namelen <= sizeof (union sockaddr_all) &&
|
||||||
DEBUG_LOG("Unexpected iovlen");
|
msg->msg_namelen > sizeof (((struct sockaddr *)msg->msg_name)->sa_family)) {
|
||||||
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)) {
|
|
||||||
switch (((struct sockaddr *)msg->msg_name)->sa_family) {
|
switch (((struct sockaddr *)msg->msg_name)->sa_family) {
|
||||||
case AF_INET:
|
case AF_INET:
|
||||||
#ifdef FEAT_IPV6
|
#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;
|
message->remote_addr.path = ((struct sockaddr_un *)msg->msg_name)->sun_path;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
init_message_addresses(message, SCK_ADDR_UNSPEC);
|
||||||
DEBUG_LOG("Unexpected address");
|
DEBUG_LOG("Unexpected address");
|
||||||
return 0;
|
r = 0;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
init_message_addresses(message, SCK_ADDR_UNSPEC);
|
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);
|
init_message_nonaddress(message);
|
||||||
|
|
||||||
|
if (msg->msg_iovlen == 1) {
|
||||||
message->data = msg->msg_iov[0].iov_base;
|
message->data = msg->msg_iov[0].iov_base;
|
||||||
message->length = msg_length;
|
message->length = msg_length;
|
||||||
|
} else {
|
||||||
|
DEBUG_LOG("Unexpected iovlen");
|
||||||
|
r = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (msg->msg_flags & MSG_TRUNC) {
|
if (msg->msg_flags & MSG_TRUNC) {
|
||||||
log_message(sock_fd, 1, message, "Truncated", NULL);
|
log_message(sock_fd, 1, message, "Truncated", NULL);
|
||||||
return 0;
|
r = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (msg->msg_flags & MSG_CTRUNC) {
|
if (msg->msg_flags & MSG_CTRUNC) {
|
||||||
log_message(sock_fd, 1, message, "Truncated cmsg in", NULL);
|
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)) {
|
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 ||
|
if (err.ee_errno != ENOMSG || err.ee_info != SCM_TSTAMP_SND ||
|
||||||
err.ee_origin != SO_EE_ORIGIN_TIMESTAMPING) {
|
err.ee_origin != SO_EE_ORIGIN_TIMESTAMPING) {
|
||||||
log_message(sock_fd, 1, message, "Unexpected extended error in", NULL);
|
log_message(sock_fd, 1, message, "Unexpected extended error in", NULL);
|
||||||
return 0;
|
r = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
|
if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
|
||||||
if (!(flags & SCK_FLAG_MSG_DESCRIPTOR) || cmsg->cmsg_len != CMSG_LEN(sizeof (int))) {
|
if (!(flags & SCK_FLAG_MSG_DESCRIPTOR) || cmsg->cmsg_len != CMSG_LEN(sizeof (int))) {
|
||||||
unsigned int i;
|
int i, fd;
|
||||||
|
|
||||||
DEBUG_LOG("Unexpected SCM_RIGHTS");
|
DEBUG_LOG("Unexpected SCM_RIGHTS");
|
||||||
for (i = 0; CMSG_LEN((i + 1) * sizeof (int)) <= cmsg->cmsg_len; i++)
|
for (i = 0; CMSG_LEN((i + 1) * sizeof (int)) <= cmsg->cmsg_len; i++) {
|
||||||
close(((int *)CMSG_DATA(cmsg))[i]);
|
memcpy(&fd, (char *)CMSG_DATA(cmsg) + i * sizeof (int), sizeof (fd));
|
||||||
return 0;
|
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;
|
struct MessageHeader *hdr;
|
||||||
SCK_Message *messages;
|
SCK_Message *messages;
|
||||||
unsigned int i, n;
|
unsigned int i, n, n_ok;
|
||||||
int ret, recv_flags = 0;
|
int ret, recv_flags = 0;
|
||||||
|
|
||||||
assert(initialised);
|
assert(initialised);
|
||||||
@@ -945,18 +955,20 @@ receive_messages(int sock_fd, int flags, int max_messages, int *num_messages)
|
|||||||
|
|
||||||
received_messages = n;
|
received_messages = n;
|
||||||
|
|
||||||
for (i = 0; i < n; i++) {
|
for (i = n_ok = 0; i < n; i++) {
|
||||||
hdr = ARR_GetElement(recv_headers, i);
|
hdr = ARR_GetElement(recv_headers, i);
|
||||||
if (!process_header(&hdr->msg_hdr, hdr->msg_len, sock_fd, flags, &messages[i]))
|
if (!process_header(&hdr->msg_hdr, hdr->msg_len, sock_fd, flags, &messages[n_ok]))
|
||||||
return NULL;
|
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);
|
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) Richard P. Curnow 1997-2003
|
||||||
* Copyright (C) Miroslav Lichvar 2011-2016, 2018
|
* Copyright (C) Miroslav Lichvar 2011-2016, 2018, 2020
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of version 2 of the GNU General Public License as
|
* it under the terms of version 2 of the GNU General Public License as
|
||||||
@@ -1499,22 +1499,21 @@ SRC_ReportSource(int index, RPT_SourceReport *report, struct timespec *now)
|
|||||||
case SRC_JITTERY:
|
case SRC_JITTERY:
|
||||||
report->state = RPT_JITTERY;
|
report->state = RPT_JITTERY;
|
||||||
break;
|
break;
|
||||||
case SRC_UNTRUSTED:
|
|
||||||
case SRC_WAITS_SOURCES:
|
case SRC_WAITS_SOURCES:
|
||||||
case SRC_NONPREFERRED:
|
case SRC_NONPREFERRED:
|
||||||
case SRC_WAITS_UPDATE:
|
case SRC_WAITS_UPDATE:
|
||||||
case SRC_DISTANT:
|
case SRC_DISTANT:
|
||||||
case SRC_OUTLIER:
|
case SRC_OUTLIER:
|
||||||
report->state = RPT_OUTLIER;
|
report->state = RPT_SELECTABLE;
|
||||||
break;
|
break;
|
||||||
case SRC_UNSELECTED:
|
case SRC_UNSELECTED:
|
||||||
report->state = RPT_CANDIDATE;
|
report->state = RPT_UNSELECTED;
|
||||||
break;
|
break;
|
||||||
case SRC_SELECTED:
|
case SRC_SELECTED:
|
||||||
report->state = RPT_SYNC;
|
report->state = RPT_SELECTED;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
report->state = RPT_UNREACH;
|
report->state = RPT_NONSELECTABLE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1611,6 +1610,7 @@ SRC_GetSelectReport(int index, RPT_SelectReport *report)
|
|||||||
report->ip_addr.family = IPADDR_UNSPEC;
|
report->ip_addr.family = IPADDR_UNSPEC;
|
||||||
report->state_char = get_status_char(inst->status);
|
report->state_char = get_status_char(inst->status);
|
||||||
report->authentication = inst->authenticated;
|
report->authentication = inst->authenticated;
|
||||||
|
report->leap = inst->leap;
|
||||||
report->conf_options = inst->conf_sel_options;
|
report->conf_options = inst->conf_sel_options;
|
||||||
report->eff_options = inst->sel_options;
|
report->eff_options = inst->sel_options;
|
||||||
report->last_sample_ago = inst->sel_info.last_sample_ago;
|
report->last_sample_ago = inst->sel_info.last_sample_ago;
|
||||||
|
|||||||
2
stubs.c
2
stubs.c
@@ -49,7 +49,7 @@
|
|||||||
#include "sched.h"
|
#include "sched.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
#ifndef FEAT_ASYNCDNS
|
#if defined(FEAT_NTP) && !defined(FEAT_ASYNCDNS)
|
||||||
|
|
||||||
/* This is a blocking implementation used when asynchronous resolving is not available */
|
/* This is a blocking implementation used when asynchronous resolving is not available */
|
||||||
|
|
||||||
|
|||||||
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)
|
#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)
|
#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)
|
#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)
|
#elif defined(MACOSX) && defined(FEAT_PRIVDROP)
|
||||||
SYS_MacOSX_DropRoot(uid, gid);
|
SYS_MacOSX_DropRoot(uid, gid, context);
|
||||||
#else
|
#else
|
||||||
LOG_FATAL("dropping root privileges not supported");
|
LOG_FATAL("dropping root privileges not supported");
|
||||||
#endif
|
#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)
|
#if defined(LINUX) && defined(FEAT_SCFILTER)
|
||||||
SYS_Linux_EnableSystemCallFilter(level, context);
|
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 */
|
/* Called at the end of the run to do final clean-up */
|
||||||
extern void SYS_Finalise(void);
|
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 {
|
typedef enum {
|
||||||
SYS_MAIN_PROCESS,
|
SYS_MAIN_PROCESS,
|
||||||
SYS_NTSKE_HELPER,
|
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
|
/* Enable a system call filter to allow only system calls
|
||||||
which chronyd normally needs after initialization */
|
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_SetScheduler(int SchedPriority);
|
||||||
extern void SYS_LockMemory(void);
|
extern void SYS_LockMemory(void);
|
||||||
|
|||||||
25
sys_linux.c
25
sys_linux.c
@@ -426,7 +426,7 @@ SYS_Linux_Finalise(void)
|
|||||||
|
|
||||||
#ifdef FEAT_PRIVDROP
|
#ifdef FEAT_PRIVDROP
|
||||||
void
|
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];
|
char cap_text[256];
|
||||||
cap_t cap;
|
cap_t cap;
|
||||||
@@ -437,16 +437,23 @@ SYS_Linux_DropRoot(uid_t uid, gid_t gid, int clock_control)
|
|||||||
|
|
||||||
UTI_DropRoot(uid, gid);
|
UTI_DropRoot(uid, gid);
|
||||||
|
|
||||||
/* Keep CAP_NET_BIND_SERVICE if the NTP server sockets may need to be bound.
|
/* Keep CAP_NET_BIND_SERVICE if the NTP server sockets may need to be bound
|
||||||
Keep CAP_NET_RAW if an NTP socket may need to be bound to a device.
|
to a privileged port.
|
||||||
|
Keep CAP_NET_RAW if an NTP socket may need to be bound to a device on
|
||||||
|
kernels before 5.7.
|
||||||
Keep CAP_SYS_TIME if the clock control is enabled. */
|
Keep CAP_SYS_TIME if the clock control is enabled. */
|
||||||
if (snprintf(cap_text, sizeof (cap_text), "%s %s %s",
|
if (snprintf(cap_text, sizeof (cap_text), "%s %s %s",
|
||||||
CNF_GetNTPPort() ? "cap_net_bind_service=ep" : "",
|
(CNF_GetNTPPort() > 0 && CNF_GetNTPPort() < 1024) ?
|
||||||
CNF_GetBindNtpInterface() || CNF_GetBindAcquisitionInterface() ?
|
"cap_net_bind_service=ep" : "",
|
||||||
"cap_net_raw=ep" : "",
|
(CNF_GetBindNtpInterface() || CNF_GetBindAcquisitionInterface()) &&
|
||||||
|
!SYS_Linux_CheckKernelVersion(5, 7) ? "cap_net_raw=ep" : "",
|
||||||
clock_control ? "cap_sys_time=ep" : "") >= sizeof (cap_text))
|
clock_control ? "cap_sys_time=ep" : "") >= sizeof (cap_text))
|
||||||
assert(0);
|
assert(0);
|
||||||
|
|
||||||
|
/* Helpers don't need any capabilities */
|
||||||
|
if (context != SYS_MAIN_PROCESS)
|
||||||
|
cap_text[0] = '\0';
|
||||||
|
|
||||||
if ((cap = cap_from_text(cap_text)) == NULL) {
|
if ((cap = cap_from_text(cap_text)) == NULL) {
|
||||||
LOG_FATAL("cap_from_text() failed");
|
LOG_FATAL("cap_from_text() failed");
|
||||||
}
|
}
|
||||||
@@ -477,7 +484,7 @@ void check_seccomp_applicability(void)
|
|||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
void
|
void
|
||||||
SYS_Linux_EnableSystemCallFilter(int level, SYS_SystemCallContext context)
|
SYS_Linux_EnableSystemCallFilter(int level, SYS_ProcessContext context)
|
||||||
{
|
{
|
||||||
const int syscalls[] = {
|
const int syscalls[] = {
|
||||||
/* Clock */
|
/* Clock */
|
||||||
@@ -533,7 +540,11 @@ SYS_Linux_EnableSystemCallFilter(int level, SYS_SystemCallContext context)
|
|||||||
SCMP_SYS(getdents),
|
SCMP_SYS(getdents),
|
||||||
SCMP_SYS(getdents64),
|
SCMP_SYS(getdents64),
|
||||||
SCMP_SYS(lseek),
|
SCMP_SYS(lseek),
|
||||||
|
SCMP_SYS(lstat),
|
||||||
|
SCMP_SYS(lstat64),
|
||||||
SCMP_SYS(newfstatat),
|
SCMP_SYS(newfstatat),
|
||||||
|
SCMP_SYS(readlink),
|
||||||
|
SCMP_SYS(readlinkat),
|
||||||
SCMP_SYS(rename),
|
SCMP_SYS(rename),
|
||||||
SCMP_SYS(renameat),
|
SCMP_SYS(renameat),
|
||||||
SCMP_SYS(renameat2),
|
SCMP_SYS(renameat2),
|
||||||
|
|||||||
@@ -33,9 +33,9 @@ extern void SYS_Linux_Initialise(void);
|
|||||||
|
|
||||||
extern void SYS_Linux_Finalise(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);
|
extern int SYS_Linux_CheckKernelVersion(int req_major, int req_minor);
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
**********************************************************************
|
**********************************************************************
|
||||||
* Copyright (C) Richard P. Curnow 1997-2001
|
* Copyright (C) Richard P. Curnow 1997-2001
|
||||||
* Copyright (C) J. Hannken-Illjes 2001
|
* Copyright (C) J. Hannken-Illjes 2001
|
||||||
* Copyright (C) Bryan Christianson 2015, 2017
|
* Copyright (C) Bryan Christianson 2015, 2017, 2020
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of version 2 of the GNU General Public License as
|
* it under the terms of version 2 of the GNU General Public License as
|
||||||
@@ -415,8 +415,9 @@ SYS_MacOSX_SetScheduler(int SchedPriority)
|
|||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
#ifdef FEAT_PRIVDROP
|
#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)
|
||||||
{
|
{
|
||||||
|
if (context == SYS_MAIN_PROCESS)
|
||||||
PRV_StartHelper();
|
PRV_StartHelper();
|
||||||
|
|
||||||
UTI_DropRoot(uid, gid);
|
UTI_DropRoot(uid, gid);
|
||||||
|
|||||||
@@ -30,8 +30,10 @@
|
|||||||
#ifndef GOT_SYS_MACOSX_H
|
#ifndef GOT_SYS_MACOSX_H
|
||||||
#define GOT_SYS_MACOSX_H
|
#define GOT_SYS_MACOSX_H
|
||||||
|
|
||||||
|
#include "sys.h"
|
||||||
|
|
||||||
void SYS_MacOSX_SetScheduler(int SchedPriority);
|
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_Initialise(void);
|
||||||
void SYS_MacOSX_Finalise(void);
|
void SYS_MacOSX_Finalise(void);
|
||||||
|
|
||||||
|
|||||||
@@ -131,7 +131,7 @@ SYS_NetBSD_Finalise(void)
|
|||||||
|
|
||||||
#ifdef FEAT_PRIVDROP
|
#ifdef FEAT_PRIVDROP
|
||||||
void
|
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
|
#ifdef NETBSD
|
||||||
int fd;
|
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
|
/* On NetBSD the helper is used only for socket binding, but on FreeBSD
|
||||||
it's used also for setting and adjusting the system clock */
|
it's used also for setting and adjusting the system clock */
|
||||||
|
if (context == SYS_MAIN_PROCESS)
|
||||||
PRV_StartHelper();
|
PRV_StartHelper();
|
||||||
|
|
||||||
UTI_DropRoot(uid, gid);
|
UTI_DropRoot(uid, gid);
|
||||||
|
|
||||||
#ifdef NETBSD
|
#ifdef NETBSD
|
||||||
|
if (!clock_control)
|
||||||
|
return;
|
||||||
|
|
||||||
/* Check if we have write access to /dev/clockctl */
|
/* Check if we have write access to /dev/clockctl */
|
||||||
fd = open("/dev/clockctl", O_WRONLY);
|
fd = open("/dev/clockctl", O_WRONLY);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
|
|||||||
@@ -28,10 +28,12 @@
|
|||||||
#ifndef GOT_SYS_NETBSD_H
|
#ifndef GOT_SYS_NETBSD_H
|
||||||
#define GOT_SYS_NETBSD_H
|
#define GOT_SYS_NETBSD_H
|
||||||
|
|
||||||
|
#include "sys.h"
|
||||||
|
|
||||||
void SYS_NetBSD_Initialise(void);
|
void SYS_NetBSD_Initialise(void);
|
||||||
|
|
||||||
void SYS_NetBSD_Finalise(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
|
#endif
|
||||||
|
|||||||
@@ -55,8 +55,9 @@ SYS_Solaris_Finalise(void)
|
|||||||
|
|
||||||
#ifdef FEAT_PRIVDROP
|
#ifdef FEAT_PRIVDROP
|
||||||
void
|
void
|
||||||
SYS_Solaris_DropRoot(uid_t uid, gid_t gid)
|
SYS_Solaris_DropRoot(uid_t uid, gid_t gid, SYS_ProcessContext context)
|
||||||
{
|
{
|
||||||
|
if (context == SYS_MAIN_PROCESS)
|
||||||
PRV_StartHelper();
|
PRV_StartHelper();
|
||||||
UTI_DropRoot(uid, gid);
|
UTI_DropRoot(uid, gid);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,10 +27,12 @@
|
|||||||
#ifndef GOT_SYS_SOLARIS_H
|
#ifndef GOT_SYS_SOLARIS_H
|
||||||
#define GOT_SYS_SOLARIS_H
|
#define GOT_SYS_SOLARIS_H
|
||||||
|
|
||||||
|
#include "sys.h"
|
||||||
|
|
||||||
void SYS_Solaris_Initialise(void);
|
void SYS_Solaris_Initialise(void);
|
||||||
|
|
||||||
void SYS_Solaris_Finalise(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
|
#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
|
static double
|
||||||
read_frequency(void)
|
read_frequency(void)
|
||||||
{
|
{
|
||||||
@@ -77,7 +96,7 @@ read_frequency(void)
|
|||||||
|
|
||||||
SYS_Timex_Adjust(&txc, 0);
|
SYS_Timex_Adjust(&txc, 0);
|
||||||
|
|
||||||
return txc.freq / -FREQ_SCALE;
|
return convert_timex_frequency(&txc);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
@@ -92,7 +111,7 @@ set_frequency(double freq_ppm)
|
|||||||
|
|
||||||
SYS_Timex_Adjust(&txc, 0);
|
SYS_Timex_Adjust(&txc, 0);
|
||||||
|
|
||||||
return txc.freq / -FREQ_SCALE;
|
return convert_timex_frequency(&txc);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|||||||
@@ -17,12 +17,15 @@ for opts in \
|
|||||||
"--disable-rtc" \
|
"--disable-rtc" \
|
||||||
"--disable-sechash" \
|
"--disable-sechash" \
|
||||||
"--disable-cmdmon" \
|
"--disable-cmdmon" \
|
||||||
|
"--disable-cmdmon --enable-scfilter" \
|
||||||
"--disable-ntp" \
|
"--disable-ntp" \
|
||||||
|
"--disable-ntp --enable-scfilter" \
|
||||||
"--disable-nts" \
|
"--disable-nts" \
|
||||||
"--disable-refclock" \
|
"--disable-refclock" \
|
||||||
"--disable-timestamping" \
|
"--disable-timestamping" \
|
||||||
"--disable-timestamping --disable-ntp" \
|
"--disable-timestamping --disable-ntp" \
|
||||||
"--disable-cmdmon --disable-ntp" \
|
"--disable-cmdmon --disable-ntp" \
|
||||||
|
"--disable-cmdmon --disable-ntp --enable-scfilter" \
|
||||||
"--disable-cmdmon --disable-refclock" \
|
"--disable-cmdmon --disable-refclock" \
|
||||||
"--disable-cmdmon --disable-ntp --disable-refclock"
|
"--disable-cmdmon --disable-ntp --disable-refclock"
|
||||||
do
|
do
|
||||||
|
|||||||
@@ -52,15 +52,15 @@ test_freqrange(void)
|
|||||||
|
|
||||||
printf("freq range:\n");
|
printf("freq range:\n");
|
||||||
|
|
||||||
for (i = 0; i <= 1000; i += 50) {
|
for (i = -1000; i <= 1000; i += 50) {
|
||||||
t.modes = MOD_FREQUENCY;
|
t.modes = MOD_FREQUENCY;
|
||||||
t.freq = i << 16;
|
t.freq = i * (1 << 16);
|
||||||
printf("%4d ppm => ", i);
|
printf("%4d ppm => ", i);
|
||||||
if (try_ntpadjtime(&t) < 0)
|
if (try_ntpadjtime(&t) < 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
printf("%4ld ppm : ", t.freq / (1 << 16));
|
printf("%4ld ppm : ", t.freq / (1 << 16));
|
||||||
printf("%s\n", t.freq == i << 16 ? "ok" : "fail");
|
printf("%s\n", t.freq == i * (1 << 16) ? "ok" : "fail");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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 "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 " 2 1 .* 4460 " 350 390 log.packets || test_fail
|
||||||
check_file_messages "." 6 6 ntskeys || 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
|
rm -f tmp/measurements.log
|
||||||
|
|
||||||
export CLKNETSIM_START_DATE=$(date -d 'Jan 1 00:00:00 UTC 2010 + 40000 sec' +'%s')
|
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 " 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 "^9\.......e+03 2 1 .* 4460 " 6 10 log.packets || test_fail
|
||||||
check_file_messages "." 6 6 ntskeys || 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
|
rm -f tmp/measurements.log
|
||||||
|
|
||||||
client_conf="
|
client_conf="
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ check_chronyc_output "^Name/IP address Mode KeyID Type KLen Last Atm
|
|||||||
run_chronyc "clients" || test_fail
|
run_chronyc "clients" || test_fail
|
||||||
check_chronyc_output "^Hostname NTP Drop Int IntL Last Cmd Drop Int Last
|
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
|
|| test_fail
|
||||||
|
|
||||||
run_chronyc "ntpdata $server" || test_fail
|
run_chronyc "ntpdata $server" || test_fail
|
||||||
@@ -75,7 +75,7 @@ Leap status : Normal
|
|||||||
Version : 4
|
Version : 4
|
||||||
Mode : Server
|
Mode : Server
|
||||||
Stratum : 10
|
Stratum : 10
|
||||||
Poll interval : -6 \(0 seconds\)
|
Poll interval : (-6|[0345]) \([0-9]+ seconds\)
|
||||||
Precision : [0-9 +-]+ \(0\.[0-9]+ seconds\)
|
Precision : [0-9 +-]+ \(0\.[0-9]+ seconds\)
|
||||||
Root delay : 0\.000000 seconds
|
Root delay : 0\.000000 seconds
|
||||||
Root dispersion : 0\.000000 seconds
|
Root dispersion : 0\.000000 seconds
|
||||||
@@ -96,9 +96,9 @@ Total RX : [0-9]+
|
|||||||
Total valid RX : [0-9]+$" || test_fail
|
Total valid RX : [0-9]+$" || test_fail
|
||||||
|
|
||||||
run_chronyc "selectdata" || test_fail
|
run_chronyc "selectdata" || test_fail
|
||||||
check_chronyc_output "^S Name/IP Address Auth COpts EOpts Last Score Interval +
|
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
|
M 127\.0\.0\.1 N ----- ----- 0 1\.0 \+0ns \+0ns \?$" || test_fail
|
||||||
|
|
||||||
run_chronyc "serverstats" || test_fail
|
run_chronyc "serverstats" || test_fail
|
||||||
check_chronyc_output "^NTP packets received : [0-9]+
|
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 <cmdparse.h>
|
||||||
#include <conf.h>
|
#include <conf.h>
|
||||||
#include <keys.h>
|
#include <keys.h>
|
||||||
|
#include <ntp_ext.h>
|
||||||
#include <ntp_io.h>
|
#include <ntp_io.h>
|
||||||
#include <sched.h>
|
#include <sched.h>
|
||||||
#include <local.h>
|
#include <local.h>
|
||||||
@@ -72,7 +73,7 @@ get_random_key_id(void)
|
|||||||
uint32_t id;
|
uint32_t id;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
id = random() % 6 + 2;
|
id = random() % 8 + 2;
|
||||||
} while (!KEY_KeyKnown(id));
|
} while (!KEY_KeyKnown(id));
|
||||||
|
|
||||||
return id;
|
return id;
|
||||||
@@ -138,7 +139,7 @@ send_response(int interleaved, int authenticated, int allow_update, int valid_ts
|
|||||||
{
|
{
|
||||||
NTP_Packet *req, *res;
|
NTP_Packet *req, *res;
|
||||||
uint32_t key_id = 0;
|
uint32_t key_id = 0;
|
||||||
int auth_len = 0;
|
int i, auth_len = 0, ef_len, efs;
|
||||||
|
|
||||||
req = &req_buffer;
|
req = &req_buffer;
|
||||||
res = &res_buffer;
|
res = &res_buffer;
|
||||||
@@ -184,51 +185,85 @@ send_response(int interleaved, int authenticated, int allow_update, int valid_ts
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
res_length = NTP_HEADER_LENGTH;
|
||||||
|
|
||||||
|
if (NTP_LVM_TO_VERSION(res->lvm) == 4 && random() % 2) {
|
||||||
|
unsigned char buf[128];
|
||||||
|
|
||||||
|
memset(buf, 0, sizeof (buf));
|
||||||
|
efs = random() % 5;
|
||||||
|
|
||||||
|
for (i = 0; i < efs; i++) {
|
||||||
|
ef_len = (i + 1 == efs ? NTP_MAX_V4_MAC_LENGTH + 4 : NTP_MIN_EF_LENGTH) +
|
||||||
|
4 * (random() % 10);
|
||||||
|
TEST_CHECK(NEF_SetField((unsigned char *)res, sizeof (*res), res_length, 0,
|
||||||
|
buf, ef_len - 4, &ef_len));
|
||||||
|
res_length += ef_len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (authenticated) {
|
if (authenticated) {
|
||||||
key_id = ntohl(*(uint32_t *)req->extensions);
|
key_id = ntohl(*(uint32_t *)req->extensions);
|
||||||
if (key_id == 0)
|
if (key_id == 0)
|
||||||
key_id = get_random_key_id();
|
key_id = get_random_key_id();
|
||||||
auth_len = KEY_GetAuthLength(key_id);
|
auth_len = KEY_GetAuthLength(key_id);
|
||||||
assert(auth_len);
|
assert(auth_len);
|
||||||
if (NTP_LVM_TO_VERSION(res->lvm) == 4 && random() % 2)
|
if (NTP_LVM_TO_VERSION(res->lvm) == 4)
|
||||||
auth_len = MIN(auth_len, NTP_MAX_V4_MAC_LENGTH - 4);
|
auth_len = MIN(auth_len, NTP_MAX_V4_MAC_LENGTH - 4);
|
||||||
|
|
||||||
if (KEY_GenerateAuth(key_id, (unsigned char *)res, NTP_HEADER_LENGTH,
|
if (KEY_GenerateAuth(key_id, res, res_length,
|
||||||
res->extensions + 4, auth_len) != auth_len)
|
(unsigned char *)res + res_length + 4, auth_len) != auth_len)
|
||||||
assert(0);
|
assert(0);
|
||||||
res_length = NTP_HEADER_LENGTH + 4 + auth_len;
|
res_length += 4 + auth_len;
|
||||||
} else {
|
|
||||||
res_length = NTP_HEADER_LENGTH;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!valid_auth && authenticated) {
|
if (!valid_auth && authenticated) {
|
||||||
assert(auth_len);
|
assert(auth_len);
|
||||||
|
|
||||||
switch (random() % 4) {
|
switch (random() % 5) {
|
||||||
case 0:
|
case 0:
|
||||||
key_id++;
|
key_id++;
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
key_id ^= 1;
|
key_id ^= 1;
|
||||||
if (KEY_GenerateAuth(key_id, (unsigned char *)res, NTP_HEADER_LENGTH,
|
if (KEY_GenerateAuth(key_id, res, res_length - auth_len - 4,
|
||||||
res->extensions + 4, auth_len) != auth_len)
|
(unsigned char *)res + res_length - auth_len, auth_len) != auth_len)
|
||||||
assert(0);
|
assert(0);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
res->extensions[4 + random() % auth_len]++;
|
((unsigned char *)res)[res_length - auth_len + random() % auth_len]++;
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
res_length = NTP_HEADER_LENGTH + 4 * (random() % ((4 + auth_len) / 4));
|
res_length -= 4 + auth_len;
|
||||||
if (NTP_LVM_TO_VERSION(res->lvm) == 4 &&
|
auth_len = 4 * (random() % (auth_len / 4));
|
||||||
res_length == NTP_HEADER_LENGTH + NTP_MAX_V4_MAC_LENGTH)
|
res_length += 4 + auth_len;
|
||||||
res_length -= 4;
|
break;
|
||||||
|
case 4:
|
||||||
|
if (NTP_LVM_TO_VERSION(res->lvm) == 4 && random() % 2 &&
|
||||||
|
KEY_GetAuthLength(key_id) > NTP_MAX_V4_MAC_LENGTH - 4) {
|
||||||
|
res_length -= 4 + auth_len;
|
||||||
|
auth_len += 4 + 4 * (random() %
|
||||||
|
((KEY_GetAuthLength(key_id) - NTP_MAX_V4_MAC_LENGTH - 4) / 4));
|
||||||
|
if (KEY_GenerateAuth(key_id, res, res_length,
|
||||||
|
(unsigned char *)res + res_length + 4, auth_len) != auth_len)
|
||||||
|
assert(0);
|
||||||
|
res_length += 4 + auth_len;
|
||||||
|
} else {
|
||||||
|
memset((unsigned char *)res + res_length, 0, 4);
|
||||||
|
auth_len += 4;
|
||||||
|
res_length += 4;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*(uint32_t *)res->extensions = htonl(key_id);
|
assert(res_length <= sizeof (*res));
|
||||||
|
assert(res_length >= NTP_HEADER_LENGTH + auth_len);
|
||||||
|
|
||||||
|
if (authenticated)
|
||||||
|
*(uint32_t *)((unsigned char *)res + res_length - auth_len - 4) = htonl(key_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|||||||
@@ -4,3 +4,5 @@
|
|||||||
5 SHA1 HEX:B71744EA01FBF01CA30D173ECDDF901952AE356A
|
5 SHA1 HEX:B71744EA01FBF01CA30D173ECDDF901952AE356A
|
||||||
6 SHA512 HEX:DE027482F22B201FC20863F58C74095E7906089F
|
6 SHA512 HEX:DE027482F22B201FC20863F58C74095E7906089F
|
||||||
7 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);
|
TEST_CHECK(SIV_GetKeyLength(tests[i].algorithm) == tests[i].key_length);
|
||||||
|
|
||||||
|
r = SIV_Encrypt(siv, tests[i].nonce, tests[i].nonce_length,
|
||||||
|
tests[i].assoc, tests[i].assoc_length,
|
||||||
|
tests[i].plaintext, tests[i].plaintext_length,
|
||||||
|
ciphertext, tests[i].ciphertext_length);
|
||||||
|
TEST_CHECK(!r);
|
||||||
|
r = SIV_Decrypt(siv, tests[i].nonce, tests[i].nonce_length,
|
||||||
|
tests[i].assoc, tests[i].assoc_length,
|
||||||
|
tests[i].ciphertext, tests[i].ciphertext_length,
|
||||||
|
plaintext, tests[i].plaintext_length);
|
||||||
|
TEST_CHECK(!r);
|
||||||
|
|
||||||
for (j = -1; j < 1024; j++) {
|
for (j = -1; j < 1024; j++) {
|
||||||
r = SIV_SetKey(siv, tests[i].key, j);
|
r = SIV_SetKey(siv, tests[i].key, j);
|
||||||
TEST_CHECK(r == (j == tests[i].key_length));
|
TEST_CHECK(r == (j == tests[i].key_length));
|
||||||
|
|||||||
@@ -81,6 +81,9 @@ test_unit(void)
|
|||||||
sample.root_dispersion = sample.peer_dispersion;
|
sample.root_dispersion = sample.peer_dispersion;
|
||||||
sample.stratum = 1;
|
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,
|
DEBUG_LOG("source %d sample %d offset %f delay %f disp %f", j, k,
|
||||||
sample.offset, sample.peer_delay, sample.peer_dispersion);
|
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(!trusted || !passed || (passed_lo >= trusted_lo && passed_hi <= trusted_hi));
|
||||||
TEST_CHECK(!passed || !trusted || trusted_passed >= 1);
|
TEST_CHECK(!passed || !trusted || trusted_passed >= 1);
|
||||||
TEST_CHECK(!passed || !required || required_passed > 0);
|
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(UTI_HexToBytes(buf, buf, sizeof (buf)) == 7);
|
||||||
TEST_CHECK(memcmp(buf, "\xAB\x12\x34\x56\x78\x00\x01", 7) == 0);
|
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, 14) == 0);
|
||||||
TEST_CHECK(UTI_BytesToHex("\xAB\x12\x34\x56\x78\x00\x01", 7, buf, 15) == 1);
|
TEST_CHECK(UTI_BytesToHex("\xAB\x12\x34\x56\x78\x00\x01", 7, buf, 15) == 1);
|
||||||
TEST_CHECK(strcmp(buf, "AB123456780001") == 0);
|
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(snprintf(buf, sizeof (buf), "%s", "") < sizeof (buf));
|
||||||
TEST_CHECK(UTI_SplitString(buf, words, 3) == 0);
|
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) Richard P. Curnow 1997-2003
|
||||||
* Copyright (C) Miroslav Lichvar 2009, 2012-2018
|
* Copyright (C) Miroslav Lichvar 2009, 2012-2020
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of version 2 of the GNU General Public License as
|
* it under the terms of version 2 of the GNU General Public License as
|
||||||
@@ -1417,6 +1417,11 @@ UTI_BytesToHex(const void *buf, unsigned int buf_len, char *hex, unsigned int he
|
|||||||
{
|
{
|
||||||
unsigned int i, l;
|
unsigned int i, l;
|
||||||
|
|
||||||
|
if (hex_len < 1)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
hex[0] = '\0';
|
||||||
|
|
||||||
for (i = l = 0; i < buf_len; i++, l += 2) {
|
for (i = l = 0; i < buf_len; i++, l += 2) {
|
||||||
if (l + 2 >= hex_len ||
|
if (l + 2 >= hex_len ||
|
||||||
snprintf(hex + l, hex_len - l, "%02hhX", ((const char *)buf)[i]) != 2)
|
snprintf(hex + l, hex_len - l, "%02hhX", ((const char *)buf)[i]) != 2)
|
||||||
|
|||||||
Reference in New Issue
Block a user