mirror of
https://gitlab.com/chrony/chrony.git
synced 2025-12-04 00:45:07 -05:00
Compare commits
31 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 |
3
candm.h
3
candm.h
@@ -764,7 +764,8 @@ typedef struct {
|
||||
IPAddr ip_addr;
|
||||
uint8_t state_char;
|
||||
uint8_t authentication;
|
||||
uint8_t pad[2];
|
||||
uint8_t leap;
|
||||
uint8_t pad;
|
||||
uint16_t conf_options;
|
||||
uint16_t eff_options;
|
||||
uint32_t last_sample_ago;
|
||||
|
||||
68
client.c
68
client.c
@@ -1001,36 +1001,17 @@ process_cmd_dfreq(CMD_Request *msg, char *line)
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
static void
|
||||
cvt_to_sec_usec(double x, long *sec, long *usec) {
|
||||
long s, us;
|
||||
s = (long) x;
|
||||
us = (long)(0.5 + 1.0e6 * (x - (double) s));
|
||||
while (us >= 1000000) {
|
||||
us -= 1000000;
|
||||
s += 1;
|
||||
}
|
||||
while (us < 0) {
|
||||
us += 1000000;
|
||||
s -= 1;
|
||||
}
|
||||
|
||||
*sec = s;
|
||||
*usec = us;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
static void
|
||||
process_cmd_doffset(CMD_Request *msg, char *line)
|
||||
{
|
||||
struct timeval tv;
|
||||
double doffset;
|
||||
long sec, usec;
|
||||
|
||||
msg->command = htons(REQ_DOFFSET);
|
||||
if (sscanf(line, "%lf", &doffset) == 1) {
|
||||
cvt_to_sec_usec(doffset, &sec, &usec);
|
||||
msg->data.doffset.sec = htonl(sec);
|
||||
msg->data.doffset.usec = htonl(usec);
|
||||
UTI_DoubleToTimeval(doffset, &tv);
|
||||
msg->data.doffset.sec = htonl(tv.tv_sec);
|
||||
msg->data.doffset.usec = htonl(tv.tv_usec);
|
||||
} else {
|
||||
msg->data.doffset.sec = htonl(0);
|
||||
msg->data.doffset.usec = htonl(0);
|
||||
@@ -1882,19 +1863,19 @@ print_report(const char *format, ...)
|
||||
integer = va_arg(ap, int);
|
||||
switch (integer) {
|
||||
case LEAP_Normal:
|
||||
string = "Normal";
|
||||
string = width != 1 ? "Normal" : "N";
|
||||
break;
|
||||
case LEAP_InsertSecond:
|
||||
string = "Insert second";
|
||||
string = width != 1 ? "Insert second" : "+";
|
||||
break;
|
||||
case LEAP_DeleteSecond:
|
||||
string = "Delete second";
|
||||
string = width != 1 ? "Delete second" : "-";
|
||||
break;
|
||||
case LEAP_Unsynchronised:
|
||||
string = "Not synchronised";
|
||||
string = width != 1 ? "Not synchronised" : "?";
|
||||
break;
|
||||
default:
|
||||
string = "Invalid";
|
||||
string = width != 1 ? "Invalid" : "?";
|
||||
break;
|
||||
}
|
||||
printf("%s", string);
|
||||
@@ -2049,7 +2030,7 @@ get_source_name(IPAddr *ip_addr, char *buf, int size)
|
||||
|
||||
/* Make sure the name is printable */
|
||||
for (i = 0; i < size && buf[i] != '\0'; i++) {
|
||||
if (!isgraph(buf[i]))
|
||||
if (!isgraph((unsigned char)buf[i]))
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2576,9 +2557,9 @@ process_cmd_selectdata(char *line)
|
||||
printf( "| | | | |\n");
|
||||
}
|
||||
|
||||
print_header("S Name/IP Address Auth COpts EOpts Last Score Interval ");
|
||||
print_header("S Name/IP Address Auth COpts EOpts Last Score Interval Leap");
|
||||
|
||||
/* "S NNNNNNNNNNNNNNNNNNNNNNNNN A OOOO- OOOO- LLLL SSSSS LLLLLLL LLLLLLL" */
|
||||
/* "S NNNNNNNNNNNNNNNNNNNNNNNNN A OOOO- OOOO- LLLL SSSSS IIIIIII IIIIIII L" */
|
||||
|
||||
for (i = 0; i < n_sources; i++) {
|
||||
request.command = htons(REQ_SELECT_DATA);
|
||||
@@ -2596,7 +2577,7 @@ process_cmd_selectdata(char *line)
|
||||
conf_options = ntohs(reply.data.select_data.conf_options);
|
||||
eff_options = ntohs(reply.data.select_data.eff_options);
|
||||
|
||||
print_report("%c %-25s %c %c%c%c%c%c %c%c%c%c%c %I %5.1f %+S %+S\n",
|
||||
print_report("%c %-25s %c %c%c%c%c%c %c%c%c%c%c %I %5.1f %+S %+S %1L\n",
|
||||
reply.data.select_data.state_char,
|
||||
name,
|
||||
reply.data.select_data.authentication ? 'Y' : 'N',
|
||||
@@ -2614,6 +2595,7 @@ process_cmd_selectdata(char *line)
|
||||
UTI_FloatNetworkToHost(reply.data.select_data.score),
|
||||
UTI_FloatNetworkToHost(reply.data.select_data.lo_limit),
|
||||
UTI_FloatNetworkToHost(reply.data.select_data.hi_limit),
|
||||
reply.data.select_data.leap,
|
||||
REPORT_END);
|
||||
}
|
||||
|
||||
@@ -3483,8 +3465,22 @@ display_gpl(void)
|
||||
static void
|
||||
print_help(const char *progname)
|
||||
{
|
||||
printf("Usage: %s [-h HOST] [-p PORT] [-n] [-N] [-c] [-d] [-4|-6] [-m] [COMMAND]\n",
|
||||
progname);
|
||||
printf("Usage: %s [OPTION]... [COMMAND]...\n\n"
|
||||
"Options:\n"
|
||||
" -4\t\tUse IPv4 addresses only\n"
|
||||
" -6\t\tUse IPv6 addresses only\n"
|
||||
" -n\t\tDon't resolve hostnames\n"
|
||||
" -N\t\tPrint original source names\n"
|
||||
" -c\t\tEnable CSV format\n"
|
||||
#if DEBUG > 0
|
||||
" -d\t\tEnable debug messages\n"
|
||||
#endif
|
||||
" -m\t\tAccept multiple commands\n"
|
||||
" -h HOST\tSpecify server (%s)\n"
|
||||
" -p PORT\tSpecify UDP port (%d)\n"
|
||||
" -v, --version\tPrint version and exit\n"
|
||||
" --help\tPrint usage and exit\n",
|
||||
progname, DEFAULT_COMMAND_SOCKET",127.0.0.1,::1", DEFAULT_CANDM_PORT);
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
@@ -3506,7 +3502,7 @@ main(int argc, char **argv)
|
||||
int opt, ret = 1, multi = 0, family = IPADDR_UNSPEC;
|
||||
int port = DEFAULT_CANDM_PORT;
|
||||
|
||||
/* Parse (undocumented) long command-line options */
|
||||
/* Parse long command-line options */
|
||||
for (optind = 1; optind < argc; optind++) {
|
||||
if (!strcmp("--help", argv[optind])) {
|
||||
print_help(progname);
|
||||
|
||||
@@ -169,7 +169,7 @@ compare_total_hits(Record *x, Record *y)
|
||||
static Record *
|
||||
get_record(IPAddr *ip)
|
||||
{
|
||||
uint32_t last_hit, oldest_hit = 0;
|
||||
uint32_t last_hit = 0, oldest_hit = 0;
|
||||
Record *record, *oldest_record;
|
||||
unsigned int first, i, j;
|
||||
|
||||
|
||||
4
cmdmon.c
4
cmdmon.c
@@ -306,7 +306,8 @@ transmit_reply(int sock_fd, int request_length, SCK_Message *message)
|
||||
|
||||
/* Don't require responses to non-link-local addresses to use the same
|
||||
interface */
|
||||
if (!SCK_IsLinkLocalIPAddress(&message->remote_addr.ip.ip_addr))
|
||||
if (message->addr_type == SCK_ADDR_IP &&
|
||||
!SCK_IsLinkLocalIPAddress(&message->remote_addr.ip.ip_addr))
|
||||
message->if_index = INVALID_IF_INDEX;
|
||||
|
||||
if (!SCK_SendMessage(sock_fd, message, 0))
|
||||
@@ -1326,6 +1327,7 @@ handle_select_data(CMD_Request *rx_message, CMD_Reply *tx_message)
|
||||
UTI_IPHostToNetwork(&report.ip_addr, &tx_message->data.select_data.ip_addr);
|
||||
tx_message->data.select_data.state_char = report.state_char;
|
||||
tx_message->data.select_data.authentication = report.authentication;
|
||||
tx_message->data.select_data.leap = report.leap;
|
||||
tx_message->data.select_data.conf_options = htons(convert_select_options(report.conf_options));
|
||||
tx_message->data.select_data.eff_options = htons(convert_select_options(report.eff_options));
|
||||
tx_message->data.select_data.last_sample_ago = htonl(report.last_sample_ago);
|
||||
|
||||
10
conf.c
10
conf.c
@@ -422,6 +422,10 @@ CNF_Finalise(void)
|
||||
Free(((NTP_Source *)ARR_GetElement(ntp_sources, i))->params.name);
|
||||
for (i = 0; i < ARR_GetSize(ntp_source_dirs); i++)
|
||||
Free(*(char **)ARR_GetElement(ntp_source_dirs, i));
|
||||
for (i = 0; i < ARR_GetSize(refclock_sources); i++) {
|
||||
Free(((RefclockParameters *)ARR_GetElement(refclock_sources, i))->driver_name);
|
||||
Free(((RefclockParameters *)ARR_GetElement(refclock_sources, i))->driver_parameter);
|
||||
}
|
||||
|
||||
ARR_DestroyInstance(init_sources);
|
||||
ARR_DestroyInstance(ntp_sources);
|
||||
@@ -1839,10 +1843,14 @@ CNF_AddSources(void)
|
||||
void
|
||||
CNF_AddRefclocks(void)
|
||||
{
|
||||
RefclockParameters *refclock;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ARR_GetSize(refclock_sources); i++) {
|
||||
RCL_AddRefclock((RefclockParameters *)ARR_GetElement(refclock_sources, i));
|
||||
refclock = ARR_GetElement(refclock_sources, i);
|
||||
RCL_AddRefclock(refclock);
|
||||
Free(refclock->driver_name);
|
||||
Free(refclock->driver_parameter);
|
||||
}
|
||||
|
||||
ARR_SetSize(refclock_sources, 0);
|
||||
|
||||
4
configure
vendored
4
configure
vendored
@@ -689,12 +689,12 @@ fi
|
||||
|
||||
if test_code 'arc4random_buf()' 'stdlib.h' '' '' 'arc4random_buf(NULL, 0);'; then
|
||||
add_def HAVE_ARC4RANDOM
|
||||
fi
|
||||
|
||||
else
|
||||
if test_code 'getrandom()' 'stdlib.h sys/random.h' '' '' \
|
||||
'return getrandom(NULL, 256, 0);'; then
|
||||
add_def HAVE_GETRANDOM
|
||||
fi
|
||||
fi
|
||||
|
||||
RECVMMSG_CODE='
|
||||
struct mmsghdr hdr;
|
||||
|
||||
@@ -1608,9 +1608,12 @@ to the clients, which means they should use the same server for NTS-KE and NTP.
|
||||
|
||||
[[ntsrotate]]*ntsrotate* _interval_::
|
||||
This directive specifies the rotation interval (in seconds) of the server key
|
||||
which encrypts the NTS cookies. New keys are generated automatically. The
|
||||
server keeps two previous keys to give the clients time to get new cookies
|
||||
encrypted by the latest key. The default interval is 604800 seconds (1 week).
|
||||
which encrypts the NTS cookies. New keys are generated automatically from the
|
||||
_/dev/urandom_ device. The server keeps two previous keys to give the clients
|
||||
time to get new cookies encrypted by the latest key. The interval is measured
|
||||
as the server's operating time, i.e. the actual interval can be longer if
|
||||
*chronyd* is not running continuously. The default interval is 604800 seconds
|
||||
(1 week).
|
||||
+
|
||||
The automatic rotation of the keys can be disabled by setting *ntsrotate* to 0.
|
||||
In this case the keys are assumed to be managed externally. *chronyd* will not
|
||||
@@ -2511,7 +2514,7 @@ the following methods:
|
||||
stratum 1 and stratum 2 servers. You should find one or more servers that are
|
||||
near to you. Check that their access policy allows you to use their
|
||||
facilities.
|
||||
* Use public servers from the http://www.pool.ntp.org/[pool.ntp.org] project.
|
||||
* Use public servers from the https://www.pool.ntp.org/[pool.ntp.org] project.
|
||||
|
||||
Assuming that your NTP servers are called _foo.example.net_, _bar.example.net_
|
||||
and _baz.example.net_, your _chrony.conf_ file could contain as a minimum:
|
||||
@@ -2803,7 +2806,7 @@ information to be saved.
|
||||
=== Public NTP server
|
||||
|
||||
*chronyd* can be configured to operate as a public NTP server, e.g. to join the
|
||||
http://www.pool.ntp.org/en/join.html[pool.ntp.org] project. The configuration
|
||||
https://www.pool.ntp.org/en/join.html[pool.ntp.org] project. The configuration
|
||||
is similar to the NTP client with permanent connection, except it needs to
|
||||
allow client access from all addresses. It is recommended to find at least four
|
||||
good servers (e.g. from the pool, or on the NTP homepage). If the server has a
|
||||
|
||||
@@ -118,10 +118,14 @@ This option is ignored and is provided only for compatibility.
|
||||
*-a*::
|
||||
This option is ignored and is provided only for compatibility.
|
||||
|
||||
*-v*::
|
||||
*-v*, *--version*::
|
||||
With this option *chronyc* displays its version number on the terminal and
|
||||
exits.
|
||||
|
||||
*--help*::
|
||||
With this option *chronyc* displays a help message on the terminal and
|
||||
exits.
|
||||
|
||||
== COMMANDS
|
||||
|
||||
This section describes each of the commands available within the *chronyc*
|
||||
@@ -428,11 +432,11 @@ lines are shown as a reminder of the meanings of the columns.
|
||||
An example of the output is shown below.
|
||||
+
|
||||
----
|
||||
S Name/IP Address Auth COpts EOpts Last Score Interval
|
||||
====================================================================
|
||||
D foo.example.net Y ----- --TR- 4 1.0 -61ms +62ms
|
||||
* bar.example.net N ----- ----- 0 1.0 -6846us +7305us
|
||||
+ baz.example.net N ----- ----- 10 1.0 -7381us +7355us
|
||||
S Name/IP Address Auth COpts EOpts Last Score Interval Leap
|
||||
=======================================================================
|
||||
D foo.example.net Y ----- --TR- 4 1.0 -61ms +62ms N
|
||||
* bar.example.net N ----- ----- 0 1.0 -6846us +7305us N
|
||||
+ baz.example.net N ----- ----- 10 1.0 -7381us +7355us N
|
||||
----
|
||||
+
|
||||
The columns are as follows:
|
||||
@@ -504,6 +508,12 @@ be reselected and the scores will be reset to 1.
|
||||
This column displays the lower and upper endpoint of the interval which was
|
||||
expected to contain the true offset of the local clock considering the root
|
||||
distance at the time of the selection.
|
||||
*Leap*:::
|
||||
This column displays the current leap status of the source.
|
||||
* _N_ indicates the normal status (no leap second).
|
||||
* _+_ indicates that a leap second will be inserted at the end of the month.
|
||||
* _-_ indicates that a leap second will be deleted at the end of the month.
|
||||
* _?_ indicates the unknown status (i.e. no valid measurement was made).
|
||||
|
||||
[[reselect]]*reselect*::
|
||||
To avoid excessive switching between sources, *chronyd* can stay synchronised
|
||||
|
||||
@@ -187,9 +187,12 @@ still track its offset and frequency relative to the estimated true time. This
|
||||
option allows *chronyd* to be started without the capability to adjust or set
|
||||
the system clock (e.g. in some containers) to operate as an NTP server.
|
||||
|
||||
*-v*::
|
||||
*-v*, *--version*::
|
||||
With this option *chronyd* will print version number to the terminal and exit.
|
||||
|
||||
*-h*, *--help*::
|
||||
With this option *chronyd* will print a help message to the terminal and exit.
|
||||
|
||||
== FILES
|
||||
|
||||
_@SYSCONFDIR@/chrony.conf_
|
||||
|
||||
39
doc/faq.adoc
39
doc/faq.adoc
@@ -68,7 +68,7 @@ system time is periodically copied to the RTC. It is supported on Linux and
|
||||
macOS.
|
||||
|
||||
If you want to use public NTP servers from the
|
||||
http://www.pool.ntp.org/[pool.ntp.org] project, the minimal _chrony.conf_ file
|
||||
https://www.pool.ntp.org/[pool.ntp.org] project, the minimal _chrony.conf_ file
|
||||
could be:
|
||||
|
||||
----
|
||||
@@ -428,8 +428,7 @@ are marked with the _*_ or _+_ symbol in the report printed by the `sources`
|
||||
command.
|
||||
|
||||
When the best source (marked with the _*_ symbol) becomes unreachable (e.g. NTP
|
||||
server stops responding), or the measurements are no longer accepted (e.g. a
|
||||
change in network routing adds a delay), `chronyd` will not immediately switch
|
||||
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
|
||||
@@ -437,11 +436,35 @@ error of the second source, and there is still an interval which contains some
|
||||
measurements from both sources.
|
||||
|
||||
If the first source was significantly better than the second source, it can
|
||||
take many hours (up to 64 times the maximum polling interval) before the second
|
||||
source is selected. If you do not like this behaviour, you can force a faster
|
||||
reselection by increasing the clock error rate (`maxclockerror` directive),
|
||||
shortening the polling interval (`maxpoll` option), or reducing the number of
|
||||
samples (`maxsamples` option).
|
||||
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?
|
||||
|
||||
|
||||
@@ -94,7 +94,7 @@ want to enable the support, specify the `--disable-asyncdns` flag to
|
||||
|
||||
If development files for the https://www.lysator.liu.se/~nisse/nettle/[Nettle],
|
||||
https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS[NSS], or
|
||||
http://www.libtom.net/LibTomCrypt/[libtomcrypt] library are available,
|
||||
https://www.libtom.net/LibTomCrypt/[libtomcrypt] library are available,
|
||||
`chronyd` will be built with support for other cryptographic hash functions
|
||||
than MD5, which can be used for NTP authentication with a symmetric key. If you
|
||||
don't want to enable the support, specify the `--disable-sechash` flag to
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Use public servers from the pool.ntp.org project.
|
||||
# Please consider joining the pool (http://www.pool.ntp.org/join.html).
|
||||
# Please consider joining the pool (https://www.pool.ntp.org/join.html).
|
||||
pool pool.ntp.org iburst
|
||||
|
||||
# Record the rate at which the system clock gains/losses time.
|
||||
|
||||
34
main.c
34
main.c
@@ -374,8 +374,34 @@ go_daemon(void)
|
||||
static void
|
||||
print_help(const char *progname)
|
||||
{
|
||||
printf("Usage: %s [-4|-6] [-n|-d] [-p|-q|-Q] [-r] [-R] [-s] [-t TIMEOUT] [-f FILE|COMMAND...]\n",
|
||||
progname);
|
||||
printf("Usage: %s [OPTION]... [DIRECTIVE]...\n\n"
|
||||
"Options:\n"
|
||||
" -4\t\tUse IPv4 addresses only\n"
|
||||
" -6\t\tUse IPv6 addresses only\n"
|
||||
" -f FILE\tSpecify configuration file (%s)\n"
|
||||
" -n\t\tDon't run as daemon\n"
|
||||
" -d\t\tDon't run as daemon and log to stderr\n"
|
||||
#if DEBUG > 0
|
||||
" -d -d\t\tEnable debug messages\n"
|
||||
#endif
|
||||
" -l FILE\tLog to file\n"
|
||||
" -L LEVEL\tSet logging threshold (0)\n"
|
||||
" -p\t\tPrint configuration and exit\n"
|
||||
" -q\t\tSet clock and exit\n"
|
||||
" -Q\t\tLog offset and exit\n"
|
||||
" -r\t\tReload dump files\n"
|
||||
" -R\t\tAdapt configuration for restart\n"
|
||||
" -s\t\tSet clock from RTC\n"
|
||||
" -t SECONDS\tExit after elapsed time\n"
|
||||
" -u USER\tSpecify user (%s)\n"
|
||||
" -U\t\tDon't check for root\n"
|
||||
" -F LEVEL\tSet system call filter level (0)\n"
|
||||
" -P PRIORITY\tSet process priority (0)\n"
|
||||
" -m\t\tLock memory\n"
|
||||
" -x\t\tDon't control clock\n"
|
||||
" -v, --version\tPrint version and exit\n"
|
||||
" -h, --help\tPrint usage and exit\n",
|
||||
progname, DEFAULT_CONF_FILE, DEFAULT_USER);
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
@@ -417,7 +443,7 @@ int main
|
||||
|
||||
LOG_Initialise();
|
||||
|
||||
/* Parse (undocumented) long command-line options */
|
||||
/* Parse long command-line options */
|
||||
for (optind = 1; optind < argc; optind++) {
|
||||
if (!strcmp("--help", argv[optind])) {
|
||||
print_help(progname);
|
||||
@@ -599,7 +625,7 @@ int main
|
||||
|
||||
/* Drop root privileges if the specified user has a non-zero UID */
|
||||
if (!geteuid() && (pw->pw_uid || pw->pw_gid))
|
||||
SYS_DropRoot(pw->pw_uid, pw->pw_gid);
|
||||
SYS_DropRoot(pw->pw_uid, pw->pw_gid, SYS_MAIN_PROCESS);
|
||||
|
||||
REF_Initialise();
|
||||
SST_Initialise();
|
||||
|
||||
5
ntp.h
5
ntp.h
@@ -116,10 +116,11 @@ typedef struct {
|
||||
/* Enumeration for authentication modes of NTP packets */
|
||||
typedef enum {
|
||||
NTP_AUTH_NONE = 0, /* No authentication */
|
||||
NTP_AUTH_SYMMETRIC, /* MAC using symmetric key (RFC 1305, RFC 5905) */
|
||||
NTP_AUTH_SYMMETRIC, /* NTP MAC or CMAC using a symmetric key
|
||||
(RFC 1305, RFC 5905, RFC 8573) */
|
||||
NTP_AUTH_MSSNTP, /* MS-SNTP authenticator field */
|
||||
NTP_AUTH_MSSNTP_EXT, /* MS-SNTP extended authenticator field */
|
||||
NTP_AUTH_NTS, /* Network Time Security (RFC ????) */
|
||||
NTP_AUTH_NTS, /* Network Time Security (RFC 8915) */
|
||||
} NTP_AuthMode;
|
||||
|
||||
/* Structure describing an NTP packet */
|
||||
|
||||
@@ -175,7 +175,7 @@ NAU_CreateNtsInstance(IPSockAddr *nts_address, const char *name, const IPSockAdd
|
||||
void
|
||||
NAU_DestroyInstance(NAU_Instance instance)
|
||||
{
|
||||
if (instance->nts)
|
||||
if (instance->mode == NTP_AUTH_NTS)
|
||||
NNC_DestroyInstance(instance->nts);
|
||||
Free(instance);
|
||||
}
|
||||
|
||||
@@ -444,8 +444,8 @@ process_resolved_name(struct UnresolvedSource *us, IPAddr *ip_addrs, int n_addrs
|
||||
DEBUG_LOG("(%d) %s", i + 1, UTI_IPToString(&new_addr.ip_addr));
|
||||
|
||||
if (us->pool_id != INVALID_POOL) {
|
||||
/* In the pool resolving mode, try to replace all sources from
|
||||
the pool which don't have a real address yet */
|
||||
/* In the pool resolving mode, try to replace a source from
|
||||
the pool which does not have a real address yet */
|
||||
for (j = 0; j < ARR_GetSize(records); j++) {
|
||||
record = get_record(j);
|
||||
if (!record->remote_addr || record->pool_id != us->pool_id ||
|
||||
@@ -454,6 +454,7 @@ process_resolved_name(struct UnresolvedSource *us, IPAddr *ip_addrs, int n_addrs
|
||||
old_addr = *record->remote_addr;
|
||||
new_addr.port = old_addr.port;
|
||||
if (replace_source_connectable(&old_addr, &new_addr))
|
||||
;
|
||||
break;
|
||||
}
|
||||
} 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 */
|
||||
for (i = 0; name[i] != '\0'; i++) {
|
||||
if (!isgraph(name[i]))
|
||||
if (!isgraph((unsigned char)name[i]))
|
||||
return NSR_InvalidName;
|
||||
}
|
||||
|
||||
|
||||
@@ -196,7 +196,7 @@ process_response(NKC_Instance inst)
|
||||
inst->server_name[length] = '\0';
|
||||
|
||||
/* Make sure the name is printable and has no spaces */
|
||||
for (i = 0; i < length && isgraph(inst->server_name[i]); i++)
|
||||
for (i = 0; i < length && isgraph((unsigned char)inst->server_name[i]); i++)
|
||||
;
|
||||
if (i != length) {
|
||||
DEBUG_LOG("Invalid server name");
|
||||
|
||||
@@ -556,7 +556,7 @@ error:
|
||||
|
||||
#define MAX_WORDS 2
|
||||
|
||||
static void
|
||||
static int
|
||||
load_keys(void)
|
||||
{
|
||||
char *dump_dir, line[1024], *words[MAX_WORDS];
|
||||
@@ -568,11 +568,11 @@ load_keys(void)
|
||||
|
||||
dump_dir = CNF_GetNtsDumpDir();
|
||||
if (!dump_dir)
|
||||
return;
|
||||
return 0;
|
||||
|
||||
f = UTI_OpenFile(dump_dir, DUMP_FILENAME, NULL, 'r', 0);
|
||||
if (!f)
|
||||
return;
|
||||
return 0;
|
||||
|
||||
if (!fgets(line, sizeof (line), f) || strcmp(line, DUMP_IDENTIFIER) != 0 ||
|
||||
!fgets(line, sizeof (line), f) || UTI_SplitString(line, words, MAX_WORDS) != 2 ||
|
||||
@@ -607,11 +607,13 @@ load_keys(void)
|
||||
|
||||
fclose(f);
|
||||
|
||||
return;
|
||||
return 1;
|
||||
|
||||
error:
|
||||
DEBUG_LOG("Could not %s server keys", "load");
|
||||
fclose(f);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
@@ -646,7 +648,7 @@ run_helper(uid_t uid, gid_t gid, int scfilter_level)
|
||||
LOG_SetMinSeverity(log_severity);
|
||||
|
||||
if (!geteuid() && (uid || gid))
|
||||
SYS_DropRoot(uid, gid);
|
||||
SYS_DropRoot(uid, gid, SYS_NTSKE_HELPER);
|
||||
|
||||
NKS_Initialise();
|
||||
|
||||
@@ -764,10 +766,12 @@ NKS_Initialise(void)
|
||||
server_sock_fd4 = open_socket(IPADDR_INET4);
|
||||
server_sock_fd6 = open_socket(IPADDR_INET6);
|
||||
|
||||
load_keys();
|
||||
|
||||
key_rotation_interval = MAX(CNF_GetNtsRotate(), 0);
|
||||
|
||||
/* Reload saved keys, or save the new keys */
|
||||
if (!load_keys())
|
||||
save_keys();
|
||||
|
||||
if (key_rotation_interval > 0) {
|
||||
key_delay = key_rotation_interval - (SCH_GetLastEventMonoTime() - last_server_key_ts);
|
||||
SCH_AddTimeoutByDelay(MAX(key_delay, 0.0), key_timeout, NULL);
|
||||
|
||||
@@ -825,21 +825,27 @@ NKSN_GetRecord(NKSN_Instance inst, int *critical, int *type, int *body_length,
|
||||
int
|
||||
NKSN_GetKeys(NKSN_Instance inst, SIV_Algorithm siv, NKE_Key *c2s, NKE_Key *s2c)
|
||||
{
|
||||
c2s->length = SIV_GetKeyLength(siv);
|
||||
s2c->length = SIV_GetKeyLength(siv);
|
||||
assert(c2s->length <= sizeof (c2s->key));
|
||||
assert(s2c->length <= sizeof (s2c->key));
|
||||
int length = SIV_GetKeyLength(siv);
|
||||
|
||||
if (length <= 0 || length > sizeof (c2s->key) || length > sizeof (s2c->key)) {
|
||||
DEBUG_LOG("Invalid algorithm");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (gnutls_prf_rfc5705(inst->tls_session,
|
||||
sizeof (NKE_EXPORTER_LABEL) - 1, NKE_EXPORTER_LABEL,
|
||||
sizeof (NKE_EXPORTER_CONTEXT_C2S) - 1, NKE_EXPORTER_CONTEXT_C2S,
|
||||
c2s->length, (char *)c2s->key) < 0)
|
||||
return 0;
|
||||
if (gnutls_prf_rfc5705(inst->tls_session,
|
||||
length, (char *)c2s->key) < 0 ||
|
||||
gnutls_prf_rfc5705(inst->tls_session,
|
||||
sizeof (NKE_EXPORTER_LABEL) - 1, NKE_EXPORTER_LABEL,
|
||||
sizeof (NKE_EXPORTER_CONTEXT_S2C) - 1, NKE_EXPORTER_CONTEXT_S2C,
|
||||
s2c->length, (char *)s2c->key) < 0)
|
||||
length, (char *)s2c->key) < 0) {
|
||||
DEBUG_LOG("Could not export key");
|
||||
return 0;
|
||||
}
|
||||
|
||||
c2s->length = length;
|
||||
s2c->length = length;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -112,6 +112,7 @@ NNA_GenerateAuthEF(NTP_Packet *packet, NTP_PacketInfo *info, SIV_Instance siv,
|
||||
if (!SIV_Encrypt(siv, nonce, nonce_length, packet, assoc_length,
|
||||
plaintext, plaintext_length, ciphertext, ciphertext_length)) {
|
||||
DEBUG_LOG("SIV encrypt failed");
|
||||
info->length = assoc_length;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -273,8 +273,6 @@ get_cookies(NNC_Instance inst)
|
||||
inst->last_nke_success = now;
|
||||
inst->cookie_index = 0;
|
||||
|
||||
inst->nak_response = 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -285,6 +283,11 @@ NNC_PrepareForAuth(NNC_Instance inst)
|
||||
{
|
||||
inst->auth_ready = 0;
|
||||
|
||||
/* Prepare data for the next request and invalidate any responses to the
|
||||
previous request */
|
||||
UTI_GetRandomBytes(inst->uniq_id, sizeof (inst->uniq_id));
|
||||
UTI_GetRandomBytes(inst->nonce, sizeof (inst->nonce));
|
||||
|
||||
/* Try to reload saved keys and cookies (once for the NTS-KE address) */
|
||||
if (!inst->load_attempt) {
|
||||
load_cookies(inst);
|
||||
@@ -297,6 +300,8 @@ NNC_PrepareForAuth(NNC_Instance inst)
|
||||
return 0;
|
||||
}
|
||||
|
||||
inst->nak_response = 0;
|
||||
|
||||
if (!inst->siv)
|
||||
inst->siv = SIV_CreateInstance(inst->context.algorithm);
|
||||
|
||||
@@ -306,10 +311,6 @@ NNC_PrepareForAuth(NNC_Instance inst)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Prepare data for NNC_GenerateRequestAuth() */
|
||||
UTI_GetRandomBytes(inst->uniq_id, sizeof (inst->uniq_id));
|
||||
UTI_GetRandomBytes(inst->nonce, sizeof (inst->nonce));
|
||||
|
||||
inst->auth_ready = 1;
|
||||
|
||||
return 1;
|
||||
@@ -325,14 +326,22 @@ NNC_GenerateRequestAuth(NNC_Instance inst, NTP_Packet *packet,
|
||||
int i, req_cookies;
|
||||
void *ef_body;
|
||||
|
||||
if (!inst->auth_ready || inst->num_cookies == 0 || !inst->siv)
|
||||
if (!inst->auth_ready)
|
||||
return 0;
|
||||
|
||||
inst->auth_ready = 0;
|
||||
|
||||
if (inst->num_cookies <= 0 || !inst->siv)
|
||||
return 0;
|
||||
|
||||
if (info->mode != MODE_CLIENT)
|
||||
return 0;
|
||||
|
||||
cookie = &inst->cookies[inst->cookie_index];
|
||||
req_cookies = MIN(NTS_MAX_COOKIES - inst->num_cookies + 1,
|
||||
inst->num_cookies--;
|
||||
inst->cookie_index = (inst->cookie_index + 1) % NTS_MAX_COOKIES;
|
||||
|
||||
req_cookies = MIN(NTS_MAX_COOKIES - inst->num_cookies,
|
||||
MAX_TOTAL_COOKIE_LENGTH / (cookie->length + 4));
|
||||
|
||||
if (!NEF_AddField(packet, info, NTP_EF_NTS_UNIQUE_IDENTIFIER,
|
||||
@@ -354,10 +363,6 @@ NNC_GenerateRequestAuth(NNC_Instance inst, NTP_Packet *packet,
|
||||
(const unsigned char *)"", 0, NTP_MAX_V4_MAC_LENGTH + 4))
|
||||
return 0;
|
||||
|
||||
inst->num_cookies--;
|
||||
inst->cookie_index = (inst->cookie_index + 1) % NTS_MAX_COOKIES;
|
||||
inst->auth_ready = 0;
|
||||
inst->nak_response = 0;
|
||||
inst->ok_response = 0;
|
||||
|
||||
return 1;
|
||||
@@ -536,7 +541,7 @@ save_cookies(NNC_Instance inst)
|
||||
FILE *f;
|
||||
int i;
|
||||
|
||||
if (inst->num_cookies < 1 || !UTI_IsIPReal(&inst->nts_address.ip_addr))
|
||||
if (inst->num_cookies < 1 || !inst->name || !UTI_IsIPReal(&inst->nts_address.ip_addr))
|
||||
return;
|
||||
|
||||
dump_dir = CNF_GetNtsDumpDir();
|
||||
@@ -553,9 +558,10 @@ save_cookies(NNC_Instance inst)
|
||||
context_time = inst->last_nke_success - SCH_GetLastEventMonoTime();
|
||||
context_time += UTI_TimespecToDouble(&now);
|
||||
|
||||
if (fprintf(f, "%s%.1f\n%s %d\n%u %d ",
|
||||
DUMP_IDENTIFIER, context_time, UTI_IPToString(&inst->ntp_address->ip_addr),
|
||||
inst->ntp_address->port, inst->context_id, (int)inst->context.algorithm) < 0 ||
|
||||
if (fprintf(f, "%s%s\n%.1f\n%s %d\n%u %d ",
|
||||
DUMP_IDENTIFIER, inst->name, context_time,
|
||||
UTI_IPToString(&inst->ntp_address->ip_addr), inst->ntp_address->port,
|
||||
inst->context_id, (int)inst->context.algorithm) < 0 ||
|
||||
!UTI_BytesToHex(inst->context.s2c.key, inst->context.s2c.length, buf, sizeof (buf)) ||
|
||||
fprintf(f, "%s ", buf) < 0 ||
|
||||
!UTI_BytesToHex(inst->context.c2s.key, inst->context.c2s.length, buf, sizeof (buf)) ||
|
||||
@@ -616,6 +622,8 @@ load_cookies(NNC_Instance inst)
|
||||
inst->siv = NULL;
|
||||
|
||||
if (!fgets(line, sizeof (line), f) || strcmp(line, DUMP_IDENTIFIER) != 0 ||
|
||||
!fgets(line, sizeof (line), f) || UTI_SplitString(line, words, MAX_WORDS) != 1 ||
|
||||
!inst->name || strcmp(words[0], inst->name) != 0 ||
|
||||
!fgets(line, sizeof (line), f) || UTI_SplitString(line, words, MAX_WORDS) != 1 ||
|
||||
sscanf(words[0], "%lf", &context_time) != 1 ||
|
||||
!fgets(line, sizeof (line), f) || UTI_SplitString(line, words, MAX_WORDS) != 2 ||
|
||||
|
||||
@@ -96,11 +96,11 @@ NNS_CheckRequestAuth(NTP_Packet *packet, NTP_PacketInfo *info, uint32_t *kod)
|
||||
NKE_Cookie cookie;
|
||||
void *ef_body;
|
||||
|
||||
*kod = 0;
|
||||
|
||||
if (!server)
|
||||
return 0;
|
||||
|
||||
*kod = 0;
|
||||
|
||||
server->num_cookies = 0;
|
||||
server->req_tx = packet->transmit_ts;
|
||||
|
||||
|
||||
@@ -181,7 +181,7 @@ RCL_AddRefclock(RefclockParameters *params)
|
||||
LOG_FATAL("refclock tai option requires leapsectz");
|
||||
|
||||
inst->data = NULL;
|
||||
inst->driver_parameter = params->driver_parameter;
|
||||
inst->driver_parameter = Strdup(params->driver_parameter);
|
||||
inst->driver_parameter_length = 0;
|
||||
inst->driver_poll = params->driver_poll;
|
||||
inst->poll = params->poll;
|
||||
@@ -261,8 +261,6 @@ RCL_AddRefclock(RefclockParameters *params)
|
||||
params->driver_name, UTI_RefidToString(inst->ref_id),
|
||||
inst->poll, inst->driver_poll, params->filter_length);
|
||||
|
||||
Free(params->driver_name);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -190,6 +190,7 @@ typedef struct {
|
||||
IPAddr ip_addr;
|
||||
char state_char;
|
||||
int authentication;
|
||||
NTP_Leap leap;
|
||||
int conf_options;
|
||||
int eff_options;
|
||||
uint32_t last_sample_ago;
|
||||
|
||||
4
sched.c
4
sched.c
@@ -799,14 +799,14 @@ SCH_MainLoop(void)
|
||||
LCL_ReadRawTime(&now);
|
||||
LCL_CookTime(&now, &cooked, &err);
|
||||
|
||||
update_monotonic_time(&now, &last_select_ts_raw);
|
||||
|
||||
/* Check if the time didn't jump unexpectedly */
|
||||
if (!check_current_time(&saved_now, &now, status == 0, &saved_tv, ptv)) {
|
||||
/* Cook the time again after handling the step */
|
||||
LCL_CookTime(&now, &cooked, &err);
|
||||
}
|
||||
|
||||
update_monotonic_time(&cooked, &last_select_ts);
|
||||
|
||||
last_select_ts_raw = now;
|
||||
last_select_ts = cooked;
|
||||
last_select_ts_err = err;
|
||||
|
||||
68
socket.c
68
socket.c
@@ -742,18 +742,10 @@ process_header(struct msghdr *msg, int msg_length, int sock_fd, int flags,
|
||||
SCK_Message *message)
|
||||
{
|
||||
struct cmsghdr *cmsg;
|
||||
int r = 1;
|
||||
|
||||
if (msg->msg_iovlen != 1) {
|
||||
DEBUG_LOG("Unexpected iovlen");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (msg->msg_namelen > sizeof (union sockaddr_all)) {
|
||||
DEBUG_LOG("Truncated source address");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (msg->msg_namelen > sizeof (((struct sockaddr *)msg->msg_name)->sa_family)) {
|
||||
if (msg->msg_namelen <= sizeof (union sockaddr_all) &&
|
||||
msg->msg_namelen > sizeof (((struct sockaddr *)msg->msg_name)->sa_family)) {
|
||||
switch (((struct sockaddr *)msg->msg_name)->sa_family) {
|
||||
case AF_INET:
|
||||
#ifdef FEAT_IPV6
|
||||
@@ -767,26 +759,38 @@ process_header(struct msghdr *msg, int msg_length, int sock_fd, int flags,
|
||||
message->remote_addr.path = ((struct sockaddr_un *)msg->msg_name)->sun_path;
|
||||
break;
|
||||
default:
|
||||
init_message_addresses(message, SCK_ADDR_UNSPEC);
|
||||
DEBUG_LOG("Unexpected address");
|
||||
return 0;
|
||||
r = 0;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
init_message_addresses(message, SCK_ADDR_UNSPEC);
|
||||
|
||||
if (msg->msg_namelen > sizeof (union sockaddr_all)) {
|
||||
DEBUG_LOG("Truncated source address");
|
||||
r = 0;
|
||||
}
|
||||
}
|
||||
|
||||
init_message_nonaddress(message);
|
||||
|
||||
if (msg->msg_iovlen == 1) {
|
||||
message->data = msg->msg_iov[0].iov_base;
|
||||
message->length = msg_length;
|
||||
} else {
|
||||
DEBUG_LOG("Unexpected iovlen");
|
||||
r = 0;
|
||||
}
|
||||
|
||||
if (msg->msg_flags & MSG_TRUNC) {
|
||||
log_message(sock_fd, 1, message, "Truncated", NULL);
|
||||
return 0;
|
||||
r = 0;
|
||||
}
|
||||
|
||||
if (msg->msg_flags & MSG_CTRUNC) {
|
||||
log_message(sock_fd, 1, message, "Truncated cmsg in", NULL);
|
||||
return 0;
|
||||
r = 0;
|
||||
}
|
||||
|
||||
for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) {
|
||||
@@ -873,25 +877,31 @@ process_header(struct msghdr *msg, int msg_length, int sock_fd, int flags,
|
||||
if (err.ee_errno != ENOMSG || err.ee_info != SCM_TSTAMP_SND ||
|
||||
err.ee_origin != SO_EE_ORIGIN_TIMESTAMPING) {
|
||||
log_message(sock_fd, 1, message, "Unexpected extended error in", NULL);
|
||||
return 0;
|
||||
r = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
|
||||
if (!(flags & SCK_FLAG_MSG_DESCRIPTOR) || cmsg->cmsg_len != CMSG_LEN(sizeof (int))) {
|
||||
unsigned int i;
|
||||
int i, fd;
|
||||
|
||||
DEBUG_LOG("Unexpected SCM_RIGHTS");
|
||||
for (i = 0; CMSG_LEN((i + 1) * sizeof (int)) <= cmsg->cmsg_len; i++)
|
||||
close(((int *)CMSG_DATA(cmsg))[i]);
|
||||
return 0;
|
||||
for (i = 0; CMSG_LEN((i + 1) * sizeof (int)) <= cmsg->cmsg_len; i++) {
|
||||
memcpy(&fd, (char *)CMSG_DATA(cmsg) + i * sizeof (int), sizeof (fd));
|
||||
close(fd);
|
||||
}
|
||||
r = 0;
|
||||
} else {
|
||||
memcpy(&message->descriptor, CMSG_DATA(cmsg), sizeof (message->descriptor));
|
||||
}
|
||||
message->descriptor = *(int *)CMSG_DATA(cmsg);
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
if (!r && message->descriptor != INVALID_SOCK_FD)
|
||||
close(message->descriptor);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
@@ -901,7 +911,7 @@ receive_messages(int sock_fd, int flags, int max_messages, int *num_messages)
|
||||
{
|
||||
struct MessageHeader *hdr;
|
||||
SCK_Message *messages;
|
||||
unsigned int i, n;
|
||||
unsigned int i, n, n_ok;
|
||||
int ret, recv_flags = 0;
|
||||
|
||||
assert(initialised);
|
||||
@@ -945,18 +955,20 @@ receive_messages(int sock_fd, int flags, int max_messages, int *num_messages)
|
||||
|
||||
received_messages = n;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
for (i = n_ok = 0; i < n; i++) {
|
||||
hdr = ARR_GetElement(recv_headers, i);
|
||||
if (!process_header(&hdr->msg_hdr, hdr->msg_len, sock_fd, flags, &messages[i]))
|
||||
return NULL;
|
||||
if (!process_header(&hdr->msg_hdr, hdr->msg_len, sock_fd, flags, &messages[n_ok]))
|
||||
continue;
|
||||
|
||||
log_message(sock_fd, 1, &messages[i],
|
||||
log_message(sock_fd, 1, &messages[n_ok],
|
||||
flags & SCK_FLAG_MSG_ERRQUEUE ? "Received error" : "Received", NULL);
|
||||
|
||||
n_ok++;
|
||||
}
|
||||
|
||||
*num_messages = n;
|
||||
*num_messages = n_ok;
|
||||
|
||||
return messages;
|
||||
return n_ok > 0 ? messages : NULL;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
@@ -1610,6 +1610,7 @@ SRC_GetSelectReport(int index, RPT_SelectReport *report)
|
||||
report->ip_addr.family = IPADDR_UNSPEC;
|
||||
report->state_char = get_status_char(inst->status);
|
||||
report->authentication = inst->authenticated;
|
||||
report->leap = inst->leap;
|
||||
report->conf_options = inst->conf_sel_options;
|
||||
report->eff_options = inst->sel_options;
|
||||
report->last_sample_ago = inst->sel_info.last_sample_ago;
|
||||
|
||||
12
sys.c
12
sys.c
@@ -97,16 +97,16 @@ SYS_Finalise(void)
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
void SYS_DropRoot(uid_t uid, gid_t gid)
|
||||
void SYS_DropRoot(uid_t uid, gid_t gid, SYS_ProcessContext context)
|
||||
{
|
||||
#if defined(LINUX) && defined (FEAT_PRIVDROP)
|
||||
SYS_Linux_DropRoot(uid, gid, !null_driver);
|
||||
SYS_Linux_DropRoot(uid, gid, context, !null_driver);
|
||||
#elif defined(SOLARIS) && defined(FEAT_PRIVDROP)
|
||||
SYS_Solaris_DropRoot(uid, gid);
|
||||
SYS_Solaris_DropRoot(uid, gid, context);
|
||||
#elif (defined(NETBSD) || defined(FREEBSD)) && defined(FEAT_PRIVDROP)
|
||||
SYS_NetBSD_DropRoot(uid, gid);
|
||||
SYS_NetBSD_DropRoot(uid, gid, context, !null_driver);
|
||||
#elif defined(MACOSX) && defined(FEAT_PRIVDROP)
|
||||
SYS_MacOSX_DropRoot(uid, gid);
|
||||
SYS_MacOSX_DropRoot(uid, gid, context);
|
||||
#else
|
||||
LOG_FATAL("dropping root privileges not supported");
|
||||
#endif
|
||||
@@ -114,7 +114,7 @@ void SYS_DropRoot(uid_t uid, gid_t gid)
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
void SYS_EnableSystemCallFilter(int level, SYS_SystemCallContext context)
|
||||
void SYS_EnableSystemCallFilter(int level, SYS_ProcessContext context)
|
||||
{
|
||||
#if defined(LINUX) && defined(FEAT_SCFILTER)
|
||||
SYS_Linux_EnableSystemCallFilter(level, context);
|
||||
|
||||
10
sys.h
10
sys.h
@@ -35,17 +35,17 @@ extern void SYS_Initialise(int clock_control);
|
||||
/* Called at the end of the run to do final clean-up */
|
||||
extern void SYS_Finalise(void);
|
||||
|
||||
/* Drop root privileges to the specified user and group */
|
||||
extern void SYS_DropRoot(uid_t uid, gid_t gid);
|
||||
|
||||
typedef enum {
|
||||
SYS_MAIN_PROCESS,
|
||||
SYS_NTSKE_HELPER,
|
||||
} SYS_SystemCallContext;
|
||||
} SYS_ProcessContext;
|
||||
|
||||
/* Switch to the specified user and group in given context */
|
||||
extern void SYS_DropRoot(uid_t uid, gid_t gid, SYS_ProcessContext context);
|
||||
|
||||
/* Enable a system call filter to allow only system calls
|
||||
which chronyd normally needs after initialization */
|
||||
extern void SYS_EnableSystemCallFilter(int level, SYS_SystemCallContext context);
|
||||
extern void SYS_EnableSystemCallFilter(int level, SYS_ProcessContext context);
|
||||
|
||||
extern void SYS_SetScheduler(int SchedPriority);
|
||||
extern void SYS_LockMemory(void);
|
||||
|
||||
@@ -426,7 +426,7 @@ SYS_Linux_Finalise(void)
|
||||
|
||||
#ifdef FEAT_PRIVDROP
|
||||
void
|
||||
SYS_Linux_DropRoot(uid_t uid, gid_t gid, int clock_control)
|
||||
SYS_Linux_DropRoot(uid_t uid, gid_t gid, SYS_ProcessContext context, int clock_control)
|
||||
{
|
||||
char cap_text[256];
|
||||
cap_t cap;
|
||||
@@ -450,6 +450,10 @@ SYS_Linux_DropRoot(uid_t uid, gid_t gid, int clock_control)
|
||||
clock_control ? "cap_sys_time=ep" : "") >= sizeof (cap_text))
|
||||
assert(0);
|
||||
|
||||
/* Helpers don't need any capabilities */
|
||||
if (context != SYS_MAIN_PROCESS)
|
||||
cap_text[0] = '\0';
|
||||
|
||||
if ((cap = cap_from_text(cap_text)) == NULL) {
|
||||
LOG_FATAL("cap_from_text() failed");
|
||||
}
|
||||
@@ -480,7 +484,7 @@ void check_seccomp_applicability(void)
|
||||
/* ================================================== */
|
||||
|
||||
void
|
||||
SYS_Linux_EnableSystemCallFilter(int level, SYS_SystemCallContext context)
|
||||
SYS_Linux_EnableSystemCallFilter(int level, SYS_ProcessContext context)
|
||||
{
|
||||
const int syscalls[] = {
|
||||
/* Clock */
|
||||
|
||||
@@ -33,9 +33,9 @@ extern void SYS_Linux_Initialise(void);
|
||||
|
||||
extern void SYS_Linux_Finalise(void);
|
||||
|
||||
extern void SYS_Linux_DropRoot(uid_t uid, gid_t gid, int clock_control);
|
||||
extern void SYS_Linux_DropRoot(uid_t uid, gid_t gid, SYS_ProcessContext context, int clock_control);
|
||||
|
||||
extern void SYS_Linux_EnableSystemCallFilter(int level, SYS_SystemCallContext context);
|
||||
extern void SYS_Linux_EnableSystemCallFilter(int level, SYS_ProcessContext context);
|
||||
|
||||
extern int SYS_Linux_CheckKernelVersion(int req_major, int req_minor);
|
||||
|
||||
|
||||
@@ -415,8 +415,9 @@ SYS_MacOSX_SetScheduler(int SchedPriority)
|
||||
/* ================================================== */
|
||||
|
||||
#ifdef FEAT_PRIVDROP
|
||||
void SYS_MacOSX_DropRoot(uid_t uid, gid_t gid)
|
||||
void SYS_MacOSX_DropRoot(uid_t uid, gid_t gid, SYS_ProcessContext context)
|
||||
{
|
||||
if (context == SYS_MAIN_PROCESS)
|
||||
PRV_StartHelper();
|
||||
|
||||
UTI_DropRoot(uid, gid);
|
||||
|
||||
@@ -30,8 +30,10 @@
|
||||
#ifndef GOT_SYS_MACOSX_H
|
||||
#define GOT_SYS_MACOSX_H
|
||||
|
||||
#include "sys.h"
|
||||
|
||||
void SYS_MacOSX_SetScheduler(int SchedPriority);
|
||||
void SYS_MacOSX_DropRoot(uid_t uid, gid_t gid);
|
||||
void SYS_MacOSX_DropRoot(uid_t uid, gid_t gid, SYS_ProcessContext context);
|
||||
void SYS_MacOSX_Initialise(void);
|
||||
void SYS_MacOSX_Finalise(void);
|
||||
|
||||
|
||||
@@ -131,7 +131,7 @@ SYS_NetBSD_Finalise(void)
|
||||
|
||||
#ifdef FEAT_PRIVDROP
|
||||
void
|
||||
SYS_NetBSD_DropRoot(uid_t uid, gid_t gid)
|
||||
SYS_NetBSD_DropRoot(uid_t uid, gid_t gid, SYS_ProcessContext context, int clock_control)
|
||||
{
|
||||
#ifdef NETBSD
|
||||
int fd;
|
||||
@@ -139,11 +139,15 @@ SYS_NetBSD_DropRoot(uid_t uid, gid_t gid)
|
||||
|
||||
/* On NetBSD the helper is used only for socket binding, but on FreeBSD
|
||||
it's used also for setting and adjusting the system clock */
|
||||
if (context == SYS_MAIN_PROCESS)
|
||||
PRV_StartHelper();
|
||||
|
||||
UTI_DropRoot(uid, gid);
|
||||
|
||||
#ifdef NETBSD
|
||||
if (!clock_control)
|
||||
return;
|
||||
|
||||
/* Check if we have write access to /dev/clockctl */
|
||||
fd = open("/dev/clockctl", O_WRONLY);
|
||||
if (fd < 0)
|
||||
|
||||
@@ -28,10 +28,12 @@
|
||||
#ifndef GOT_SYS_NETBSD_H
|
||||
#define GOT_SYS_NETBSD_H
|
||||
|
||||
#include "sys.h"
|
||||
|
||||
void SYS_NetBSD_Initialise(void);
|
||||
|
||||
void SYS_NetBSD_Finalise(void);
|
||||
|
||||
void SYS_NetBSD_DropRoot(uid_t uid, gid_t gid);
|
||||
void SYS_NetBSD_DropRoot(uid_t uid, gid_t gid, SYS_ProcessContext context, int clock_control);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -55,8 +55,9 @@ SYS_Solaris_Finalise(void)
|
||||
|
||||
#ifdef FEAT_PRIVDROP
|
||||
void
|
||||
SYS_Solaris_DropRoot(uid_t uid, gid_t gid)
|
||||
SYS_Solaris_DropRoot(uid_t uid, gid_t gid, SYS_ProcessContext context)
|
||||
{
|
||||
if (context == SYS_MAIN_PROCESS)
|
||||
PRV_StartHelper();
|
||||
UTI_DropRoot(uid, gid);
|
||||
}
|
||||
|
||||
@@ -27,10 +27,12 @@
|
||||
#ifndef GOT_SYS_SOLARIS_H
|
||||
#define GOT_SYS_SOLARIS_H
|
||||
|
||||
#include "sys.h"
|
||||
|
||||
void SYS_Solaris_Initialise(void);
|
||||
|
||||
void SYS_Solaris_Finalise(void);
|
||||
|
||||
void SYS_Solaris_DropRoot(uid_t uid, gid_t gid);
|
||||
void SYS_Solaris_DropRoot(uid_t uid, gid_t gid, SYS_ProcessContext context);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -63,7 +63,7 @@ check_file_messages "20.*123\.1.* 111 111 1111" 99 103 measurements.log || test_
|
||||
check_file_messages "20.*123\.1.* 111 001 0000" 0 0 measurements.log || test_fail
|
||||
check_file_messages " 2 1 .* 4460 " 350 390 log.packets || test_fail
|
||||
check_file_messages "." 6 6 ntskeys || test_fail
|
||||
check_file_messages "." 11 12 192.168.123.1.nts || test_fail
|
||||
check_file_messages "." 12 13 192.168.123.1.nts || test_fail
|
||||
rm -f tmp/measurements.log
|
||||
|
||||
export CLKNETSIM_START_DATE=$(date -d 'Jan 1 00:00:00 UTC 2010 + 40000 sec' +'%s')
|
||||
@@ -83,7 +83,7 @@ check_file_messages "20.*123\.1.* 111 001 0000" 0 0 measurements.log || test_fai
|
||||
check_file_messages " 2 1 .* 4460 " 6 10 log.packets || test_fail
|
||||
check_file_messages "^9\.......e+03 2 1 .* 4460 " 6 10 log.packets || test_fail
|
||||
check_file_messages "." 6 6 ntskeys || test_fail
|
||||
check_file_messages "." 11 12 192.168.123.1.nts || test_fail
|
||||
check_file_messages "." 12 13 192.168.123.1.nts || test_fail
|
||||
rm -f tmp/measurements.log
|
||||
|
||||
client_conf="
|
||||
|
||||
@@ -64,7 +64,7 @@ check_chronyc_output "^Name/IP address Mode KeyID Type KLen Last Atm
|
||||
run_chronyc "clients" || test_fail
|
||||
check_chronyc_output "^Hostname NTP Drop Int IntL Last Cmd Drop Int Last
|
||||
===============================================================================
|
||||
127\.0\.0\.1 [1-9] 0 - - [0-9] 0 0 - -$" \
|
||||
127\.0\.0\.1 [0-9 ]+ 0 [-0-9 ]+ - [0-9] 0 0 - -$" \
|
||||
|| test_fail
|
||||
|
||||
run_chronyc "ntpdata $server" || test_fail
|
||||
@@ -75,7 +75,7 @@ Leap status : Normal
|
||||
Version : 4
|
||||
Mode : Server
|
||||
Stratum : 10
|
||||
Poll interval : -6 \(0 seconds\)
|
||||
Poll interval : (-6|[0345]) \([0-9]+ seconds\)
|
||||
Precision : [0-9 +-]+ \(0\.[0-9]+ seconds\)
|
||||
Root delay : 0\.000000 seconds
|
||||
Root dispersion : 0\.000000 seconds
|
||||
@@ -96,9 +96,9 @@ Total RX : [0-9]+
|
||||
Total valid RX : [0-9]+$" || test_fail
|
||||
|
||||
run_chronyc "selectdata" || test_fail
|
||||
check_chronyc_output "^S Name/IP Address Auth COpts EOpts Last Score Interval +
|
||||
====================================================================
|
||||
M 127\.0\.0\.1 N ----- ----- 0 1\.0 \+0ns \+0ns$" || test_fail
|
||||
check_chronyc_output "^S Name/IP Address Auth COpts EOpts Last Score Interval Leap
|
||||
=======================================================================
|
||||
M 127\.0\.0\.1 N ----- ----- 0 1\.0 \+0ns \+0ns \?$" || test_fail
|
||||
|
||||
run_chronyc "serverstats" || test_fail
|
||||
check_chronyc_output "^NTP packets received : [0-9]+
|
||||
|
||||
@@ -73,7 +73,7 @@ get_random_key_id(void)
|
||||
uint32_t id;
|
||||
|
||||
do {
|
||||
id = random() % 6 + 2;
|
||||
id = random() % 8 + 2;
|
||||
} while (!KEY_KeyKnown(id));
|
||||
|
||||
return id;
|
||||
|
||||
@@ -4,3 +4,5 @@
|
||||
5 SHA1 HEX:B71744EA01FBF01CA30D173ECDDF901952AE356A
|
||||
6 SHA512 HEX:DE027482F22B201FC20863F58C74095E7906089F
|
||||
7 SHA512 HEX:DE027482F22B201FC20863F58C74095E7906089F
|
||||
8 AES128 HEX:5D5E8A31D4B459A66D445259E147CFB5
|
||||
9 AES128 HEX:5D5E8A31D4B459A66D445259E147CFB5
|
||||
|
||||
@@ -81,6 +81,9 @@ test_unit(void)
|
||||
sample.root_dispersion = sample.peer_dispersion;
|
||||
sample.stratum = 1;
|
||||
|
||||
if (random() % 2)
|
||||
SRC_SetLeapStatus(srcs[j], random() % 4);
|
||||
|
||||
DEBUG_LOG("source %d sample %d offset %f delay %f disp %f", j, k,
|
||||
sample.offset, sample.peer_delay, sample.peer_dispersion);
|
||||
|
||||
@@ -132,6 +135,12 @@ test_unit(void)
|
||||
TEST_CHECK(!trusted || !passed || (passed_lo >= trusted_lo && passed_hi <= trusted_hi));
|
||||
TEST_CHECK(!passed || !trusted || trusted_passed >= 1);
|
||||
TEST_CHECK(!passed || !required || required_passed > 0);
|
||||
|
||||
for (l = 0; l <= j; l++) {
|
||||
TEST_CHECK(sources[l]->leap_vote ==
|
||||
(sources[l]->status >= SRC_NONPREFERRED &&
|
||||
(!trusted || sources[l]->sel_options & SRC_SELECT_TRUST)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -330,9 +330,12 @@ void test_unit(void) {
|
||||
TEST_CHECK(UTI_HexToBytes(buf, buf, sizeof (buf)) == 7);
|
||||
TEST_CHECK(memcmp(buf, "\xAB\x12\x34\x56\x78\x00\x01", 7) == 0);
|
||||
|
||||
TEST_CHECK(UTI_BytesToHex("", 0, buf, 0) == 0);
|
||||
TEST_CHECK(UTI_BytesToHex("\xAB\x12\x34\x56\x78\x00\x01", 7, buf, 14) == 0);
|
||||
TEST_CHECK(UTI_BytesToHex("\xAB\x12\x34\x56\x78\x00\x01", 7, buf, 15) == 1);
|
||||
TEST_CHECK(strcmp(buf, "AB123456780001") == 0);
|
||||
TEST_CHECK(UTI_BytesToHex("\xAB\x12\x34\x56\x78\x00\x01", 0, buf, 15) == 1);
|
||||
TEST_CHECK(strcmp(buf, "") == 0);
|
||||
|
||||
TEST_CHECK(snprintf(buf, sizeof (buf), "%s", "") < sizeof (buf));
|
||||
TEST_CHECK(UTI_SplitString(buf, words, 3) == 0);
|
||||
|
||||
5
util.c
5
util.c
@@ -1417,6 +1417,11 @@ UTI_BytesToHex(const void *buf, unsigned int buf_len, char *hex, unsigned int he
|
||||
{
|
||||
unsigned int i, l;
|
||||
|
||||
if (hex_len < 1)
|
||||
return 0;
|
||||
|
||||
hex[0] = '\0';
|
||||
|
||||
for (i = l = 0; i < buf_len; i++, l += 2) {
|
||||
if (l + 2 >= hex_len ||
|
||||
snprintf(hex + l, hex_len - l, "%02hhX", ((const char *)buf)[i]) != 2)
|
||||
|
||||
Reference in New Issue
Block a user