Compare commits

...

16 Commits

Author SHA1 Message Date
Miroslav Lichvar
dc52b61dad doc: update NEWS 2015-04-27 12:58:19 +02:00
Miroslav Lichvar
bbf4c3186b doc: update chrony description 2015-04-27 12:58:19 +02:00
Miroslav Lichvar
f72016a78e doc: document when smoothtime function is activated 2015-04-27 12:27:55 +02:00
Miroslav Lichvar
29b587a9c5 sys: fix TMX_ResetOffset() to set status back correctly 2015-04-27 12:27:55 +02:00
Miroslav Lichvar
cec4f2b140 reference: use 2012 leap second in leapsectz test 2015-04-24 12:16:47 +02:00
Miroslav Lichvar
05278c3b4c sources: ignore reselect distance when combining with refclock 2015-04-20 12:59:12 +02:00
Miroslav Lichvar
1769b8ea0f use return to exit from main function 2015-04-17 17:34:02 +02:00
Miroslav Lichvar
5686bd87d7 client: improve usage line 2015-04-17 17:33:38 +02:00
Miroslav Lichvar
1cda2db45d main: print usage with -h option 2015-04-17 17:30:38 +02:00
Miroslav Lichvar
fdf9640349 ntp: don't log error when socket() fails for client only socket 2015-04-14 15:59:55 +02:00
Miroslav Lichvar
8f2d5d99f1 doc: don't mention ancient systems
Also, don't try to track working versions of supported systems, assume
current versions are ok.
2015-04-13 17:18:19 +02:00
Miroslav Lichvar
61272e7ce8 update copyright years 2015-04-10 11:06:32 +02:00
Miroslav Lichvar
88b76f49cc doc: warn that unauthenticated peers are vulnerable to DoS attack 2015-04-10 10:52:30 +02:00
Miroslav Lichvar
ad942e352d sys: clamp frequency set in generic driver on exit 2015-04-10 10:22:28 +02:00
Miroslav Lichvar
39c2bcd462 util: don't allow time too close to 32-bit time_t overflow
In UTI_IsTimeOffsetSane() consider time in one year interval before
32-bit time_t overflow (in 2038) as invalid. Hopefully everything will
be using 64-bit time_t when that time comes.
2015-04-10 10:05:15 +02:00
Miroslav Lichvar
ae10664b24 doc: fix CVE-ID in NEWS
CVE-2015-1853 is for chrony, CVE-2015-1799 is for ntp.
2015-04-08 08:44:42 +02:00
17 changed files with 132 additions and 135 deletions

5
NEWS
View File

@@ -15,7 +15,7 @@ Enhancements
* Improve source selection
* Handle offline sources as unreachable
* Open NTP server port only when necessary (client access is allowed by
allow directive/command, peer or broadcast is configured)
allow directive/command or peer/broadcast is configured)
* Change default bindcmdaddress to loopback address
* Change default maxdelay to 3 seconds
* Change default stratumweight to 0.001
@@ -30,6 +30,7 @@ Bug fixes
---------
* Add sanity checks for time and frequency offset
* Don't report synchronised status during leap second
* Don't combine reference clocks with close NTP sources
* Fix accepting requests from configured sources
* Fix initial fallback drift setting
@@ -39,7 +40,7 @@ New in version 1.31.1
Security fixes
--------------
* Protect authenticated symmetric NTP associations against DoS attacks
(CVE-2015-1799)
(CVE-2015-1853)
* Fix access configuration with subnet size indivisible by 4 (CVE-2015-1821)
* Fix initialization of reply slots for authenticated commands (CVE-2015-1822)

81
README
View File

@@ -3,67 +3,35 @@ This is the README for chrony.
What is chrony?
===============
Chrony is a pair of programs for maintaining the accuracy of computer
clocks.
chrony is a versatile implementation of the Network Time Protocol (NTP).
It can synchronize the system clock with NTP servers, reference clocks
(e.g. GPS receiver), and manual input using wristwatch and keyboard.
It can also operate as an NTPv4 (RFC 5905) server and peer to provide
a time service to other computers in the network.
chronyd is a (background) daemon program that can be started at boot
time. This does most of the work.
It is designed to perform well in a wide range of conditions, including
intermittent network connections, heavily congested networks, changing
temperatures (ordinary computer clocks are sensitive to temperature),
and systems that do not run continuosly, or run on a virtual machine.
chronyc is a command-line interface program which can be used to
monitor chronyd's performance and to change various operating
parameters whilst it is running.
chronyd's main function is to obtain measurements of the true (UTC)
time from one of several sources, and correct the system clock
accordingly. It also works out the rate at which the system clock
gains or loses time and uses this information to keep it accurate
between measurements from the reference.
The reference time can be derived from Network Time Protocol (NTP)
servers, reference clocks, or wristwatch-and-keyboard (via chronyc).
The main source of information about the Network Time Protocol is
http://www.ntp.org.
It is designed so that it can work on computers which only have
intermittent access to reference sources, for example computers which
use a dial-up account to access the Internet or laptops. Of course, it
will work well on computers with permanent connections too.
In addition, on Linux it can monitor the system's real time clock
performance, so the system can maintain accurate time even across
reboots.
Typical accuracies available between 2 machines are
On an ethernet LAN : 100-200 microseconds, often much better
On a V32bis dial-up modem connection : 10's of milliseconds (from one
session to the next)
With a good reference clock the accuracy can reach one microsecond.
chronyd can also operate as an NTPv4 (RFC 5905) server, peer and broadcast
server.
Typical accuracy between two machines on a LAN is in tens, or a few
hundreds, of microseconds; over the Internet, accuracy is typically
within a few milliseconds. With a good hardware reference clock
sub-microsecond accuracy is possible.
Two programs are included in chrony, chronyd is a daemon that can be
started at boot time and chronyc is a command-line interface program
which can be used to monitor chronyd's performance and to change various
operating parameters whilst it is running.
What will chrony run on?
========================
Chrony can be successfully built and run on
1. Linux 2.2.x, 2.3.x, 2.4.x, 2.6.x, 3.x
2. Solaris 2.5/2.5.1/2.6/2.7/2.8 (various platforms)
3. SunOS 4.1.4 (Sparc 2 and Sparc 20)
4. BSD/386 v1.1 has been reported to work using the SunOS 4.1 driver.
5. NetBSD.
Any other system will require a porting exercise. You would need to
start from one of the existing system-specific drivers and look into
the quirks of certain system calls and the kernel on your target
system.
The software is known to work on Linux, FreeBSD, NetBSD and Solaris.
Closely related systems may work too. Any other system will likely
require a porting exercise. You would need to start from one of the
existing system-specific drivers and look into the quirks of certain
system calls and the kernel on your target system.
How do I set it up?
===================
@@ -116,6 +84,11 @@ chrony-dev-request@chrony.tuxfamily.org
as applicable.
License
=======
chrony is distributed under the GNU General Public License version 2.
Author
======

View File

@@ -3,7 +3,7 @@
**********************************************************************
* Copyright (C) Richard P. Curnow 1997,1998,1999,2000,2001,2002,2005
* Copyright (C) Miroslav Lichvar 2009
* Copyright (C) Miroslav Lichvar 2009, 2015
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as

View File

@@ -56,34 +56,30 @@ Copyright @copyright{} 2009-2014 Miroslav Lichvar
@c {{{ S:Overview
@node Overview
@section Overview
Chrony is a software package for maintaining the accuracy of computer
system clocks. It consists of a pair of programs :
chrony is a versatile implementation of the Network Time Protocol (NTP).
It can synchronize the system clock with NTP servers, reference clocks
(e.g. GPS receiver), and manual input using wristwatch and keyboard.
It can also operate as an NTPv4 (RFC 5905) server and peer to provide
a time service to other computers in the network.
@itemize @bullet
@item @code{chronyd}. This is a daemon which runs in background on the
system. It obtains measurements (e.g. via the network) of the system's
offset relative to other systems, and adjusts the system time
accordingly. For isolated systems, the user can periodically enter the
correct time by hand (using @code{chronyc}). In either case,
@code{chronyd} determines the rate at which the computer gains or loses
time, and compensates for this.
It is designed to perform well in a wide range of conditions, including
intermittent network connections, heavily congested networks, changing
temperatures (ordinary computer clocks are sensitive to temperature),
and systems that do not run continuosly, or run on a virtual machine.
@code{chronyd} can also act as an NTP server, and provide a time-of-day service
to other computers. A typical set-up is to run @code{chronyd} on a gateway
computer that has a dial-up link to the Internet, and use it to serve time to
computers on a private LAN sitting behind the gateway. The IP addresses that
can act as clients of @code{chronyd} can be tightly controlled. The default is
no client access.
Typical accuracy between two machines on a LAN is in tens, or a few
hundreds, of microseconds; over the Internet, accuracy is typically
within a few milliseconds. With a good hardware reference clock
sub-microsecond accuracy is possible.
@item @code{chronyc}. This is a command-line driven control and
monitoring program. An administrator can use this to fine-tune various
parameters within the daemon, add or delete servers etc whilst the
daemon is running.
Two programs are included in chrony, @code{chronyd} is a daemon that can
be started at boot time and @code{chronyc} is a command-line interface
program which can be used to monitor @code{chronyd}'s performance and to
change various operating parameters whilst it is running.
The IP addresses from which @code{chronyc} clients may connect can be tightly
controlled. The default is just the computer that @code{chronyd} itself is
running on.
@end itemize
@c }}}
@c {{{ S:Acknowledgments
@node Acknowledgements
@@ -123,24 +119,10 @@ different operating systems may provide different function calls to
achieve this, and even where the same function is used it may have
different quirks in its behaviour.
The software is known to work in the following environments:
@itemize @bullet
@item Linux 2.2 and newer
@item NetBSD
@item BSD/386
@item Solaris 2.3/2.5/2.5.1/2.6/2.7/2.8 on Sparc (Sparc 20, Ultrasparc) and
i386
@item SunOS 4.1.4 on Sparc 2 and Sparc20.
@end itemize
Closely related systems may work too, but they have not been tested.
Porting the software to other system (particularly to those supporting
an @code{adjtime} system call) should not be difficult, however it
requires access to such systems to test out the driver.
The software is known to work on Linux, FreeBSD, NetBSD and Solaris. Closely
related systems may work too. Porting the software to other systems
(particularly to those supporting an @code{adjtime} system call) should not be
difficult, however it requires access to such systems to test out the driver.
@c }}}
@c {{{ S:Other programs
@node Other time synchronisation packages
@@ -305,8 +287,7 @@ Particular areas that need addressing are :
@item Porting to other Unices
This involves creating equivalents of sys_solaris.c, sys_linux.c etc for the
new system. Note, the Linux driver has been reported as working on a range of
different architectures (Alpha, Sparc, MIPS as well as x86 of course).
new system.
@item Porting to Windows NT
@@ -1012,9 +993,8 @@ configuration file. This option is useful if you want to stop and
restart @code{chronyd} briefly for any reason, e.g. to install a new
version. However, it only makes sense on systems where the kernel can
maintain clock compensation whilst not under @code{chronyd's} control.
The only version where this happens so far is Linux. On systems where
this is not the case, e.g. Solaris and SunOS the option should not be
used.
The only version where this happens so far is Linux. On other systems
this option should not be used.
@item -R
When this option is used, the @code{initstepslew} directive and the
@code{makestep} directive used with a positive limit will be ignored.
@@ -2543,6 +2523,21 @@ be reported using the @code{clients} command in @code{chronyc}.
The syntax of this directive is identical to that for the @code{server}
directive (@pxref{server directive}), except that it is used to specify
an NTP peer rather than an NTP server.
Please note that NTP peers that are not configured with a key to enable
authentication are vulnerable to a denial-of-service attack. An attacker
knowing that NTP hosts A and B are peering with each other can send a packet
with random timestamps to host A with source address of B which will set the
NTP state variables on A to the values sent by the attacker. Host A will then
send on its next poll to B a packet with originate timestamp that doesn't match
the transmit timestamp of B and the packet will be dropped. If the attacker
does this periodically for both hosts, they won't be able to synchronize to
each other.
This attack can be prevented by enabling authentication with the key option, or
using the @code{server} directive on both sides to specify the other host as a
server instead of peer, the only drawback is that it will double the network
traffic between the two hosts.
@c }}}
@c {{{ pidfile
@node pidfile directive
@@ -3059,7 +3054,9 @@ directive or command.
The directive takes two arguments, the maximum frequency offset of the smoothed
time to the tracked NTP time (in ppm) and the maximum rate at which the
frequency offset is allowed to change (in ppm per second).
frequency offset is allowed to change (in ppm per second). The smoothing
process is activated when 1/10000 of the estimated skew of the local clock
falls below the maximum rate of frequency change.
An example suitable for clients using @code{ntpd} and 1024 second polling
interval could be
@@ -4165,9 +4162,7 @@ password
@end example
The computer will respond with a @samp{Password:} prompt, at which you
should enter the password and press return. (Note that the no-echo mode
is limited to 8 characters on SunOS 4.1 due to limitations in the system
library. Other systems do not have this restriction.)
should enter the password and press return.
The password can be encoded as a string of characters not containing a space
with optional @code{ASCII:} prefix or as a hexadecimal number with @code{HEX:}
@@ -4551,7 +4546,7 @@ true time (which it reports to NTP clients when it is operating in
server mode). The value reported on this line is the difference due to
this effect.
On systems such as Solaris and SunOS, @code{chronyd} has no means to
On systems other than Linux, @code{chronyd} doesn't
adjust the fundamental rate of the system clock, so keeps the system
time correct by periodically making offsets to it as though an error had
been measured. The build up of these offsets will be observed in this

View File

@@ -70,8 +70,7 @@ option is useful if you want to stop and restart \fBchronyd\fR briefly for any
reason, e.g. to install a new version. However, it only makes sense on
systems where the kernel can maintain clock compensation whilst not under
\fBchronyd\fR's control. The only version where this happens so far is Linux.
On systems where this is not the case, e.g. Solaris and SunOS the option
should not be used.
On other systems this option should not be used.
.TP
.B \-R
When this option is used, the \fIinitstepslew\fR directive and the

View File

@@ -2729,10 +2729,11 @@ main(int argc, char **argv)
family = IPADDR_INET6;
} else if (!strcmp("-v", *argv) || !strcmp("--version",*argv)) {
printf("chronyc (chrony) version %s (%s)\n", CHRONY_VERSION, CHRONYC_FEATURES);
exit(0);
return 0;
} else if (!strncmp(*argv, "-", 1)) {
fprintf(stderr, "Usage : %s [-h <hostname>] [-p <port-number>] [-n] [-4|-6] [-m] [-a] [-f <file>]] [command]\n", progname);
exit(1);
fprintf(stderr, "Usage: %s [-h HOST] [-p PORT] [-n] [-4|-6] [-a] [-f FILE] [-m] [COMMAND]\n",
progname);
return 1;
} else {
break; /* And process remainder of line as a command */
}

View File

@@ -3,7 +3,7 @@
**********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003
* Copyright (C) Miroslav Lichvar 2013
* Copyright (C) Miroslav Lichvar 2013-2014
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as

2
conf.c
View File

@@ -3,7 +3,7 @@
**********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003
* Copyright (C) Miroslav Lichvar 2009-2014
* Copyright (C) Miroslav Lichvar 2009-2015
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as

View File

@@ -3,7 +3,7 @@
**********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003
* Copyright (C) Miroslav Lichvar 2011, 2014
* Copyright (C) Miroslav Lichvar 2011, 2014-2015
*
* 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

9
main.c
View File

@@ -347,6 +347,7 @@ int main
(int argc, char **argv)
{
const char *conf_file = DEFAULT_CONF_FILE;
const char *progname = argv[0];
char *user = NULL;
int debug = 0, nofork = 0, address_family = IPADDR_UNSPEC;
int do_init_rtc = 0, restarted = 0;
@@ -386,7 +387,7 @@ int main
} else if (!strcmp("-v", *argv) || !strcmp("--version",*argv)) {
/* This write to the terminal is OK, it comes before we turn into a daemon */
printf("chronyd (chrony) version %s (%s)\n", CHRONY_VERSION, CHRONYD_FEATURES);
exit(0);
return 0;
} else if (!strcmp("-n", *argv)) {
nofork = 1;
} else if (!strcmp("-d", *argv)) {
@@ -405,6 +406,10 @@ int main
address_family = IPADDR_INET4;
} else if (!strcmp("-6", *argv)) {
address_family = IPADDR_INET6;
} else if (!strcmp("-h", *argv) || !strcmp("--help", *argv)) {
printf("Usage: %s [-4|-6] [-n|-d] [-q|-Q] [-r] [-R] [-s] [-f FILE|COMMAND...]\n",
progname);
return 0;
} else if (*argv[0] == '-') {
LOG_FATAL(LOGF_Main, "Unrecognized command line option [%s]", *argv);
} else {
@@ -417,7 +422,7 @@ int main
if (getuid() != 0) {
/* This write to the terminal is OK, it comes before we turn into a daemon */
fprintf(stderr,"Not superuser\n");
exit(1);
return 1;
}
/* Turn into a daemon */

View File

@@ -3,7 +3,7 @@
**********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003
* Copyright (C) Miroslav Lichvar 2009-2014
* Copyright (C) Miroslav Lichvar 2009-2015
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as

View File

@@ -4,7 +4,7 @@
**********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003
* Copyright (C) Timo Teras 2009
* Copyright (C) Miroslav Lichvar 2009, 2013-2014
* Copyright (C) Miroslav Lichvar 2009, 2013-2015
*
* 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
@@ -97,8 +97,13 @@ prepare_socket(int family, int port_number, int client_only)
sock_fd = socket(family, SOCK_DGRAM, 0);
if (sock_fd < 0) {
LOG(LOGS_ERR, LOGF_NtpIO, "Could not open %s NTP socket : %s",
family == AF_INET ? "IPv4" : "IPv6", strerror(errno));
if (!client_only) {
LOG(LOGS_ERR, LOGF_NtpIO, "Could not open %s NTP socket : %s",
family == AF_INET ? "IPv4" : "IPv6", strerror(errno));
} else {
DEBUG_LOG(LOGF_NtpIO, "Could not open %s NTP socket : %s",
family == AF_INET ? "IPv4" : "IPv6", strerror(errno));
}
return INVALID_SOCK_FD;
}

View File

@@ -3,7 +3,7 @@
**********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003
* Copyright (C) Miroslav Lichvar 2009-2014
* Copyright (C) Miroslav Lichvar 2009-2015
*
* 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
@@ -248,9 +248,9 @@ REF_Initialise(void)
leap_tzname = CNF_GetLeapSecTimezone();
if (leap_tzname) {
/* Check that the timezone has good data for Jun 30 2008 and Dec 31 2008 */
if (get_tz_leap(1214784000) == LEAP_Normal &&
get_tz_leap(1230681600) == LEAP_InsertSecond) {
/* Check that the timezone has good data for Jun 30 2012 and Dec 31 2012 */
if (get_tz_leap(1341014400) == LEAP_InsertSecond &&
get_tz_leap(1356912000) == LEAP_Normal) {
LOG(LOGS_INFO, LOGF_Reference, "Using %s timezone to obtain leap second data", leap_tzname);
} else {
LOG(LOGS_WARN, LOGF_Reference, "Timezone %s failed leap second check, ignoring", leap_tzname);

View File

@@ -513,7 +513,7 @@ combine_sources(int n_sel_sources, struct timeval *ref_time, double *offset,
{
struct timeval src_ref_time;
double src_offset, src_offset_sd, src_frequency, src_skew;
double src_root_delay, src_root_dispersion, elapsed;
double src_root_delay, src_root_dispersion, sel_src_distance, elapsed;
double offset_weight, sum_offset_weight, sum_offset, sum2_offset_sd;
double frequency_weight, sum_frequency_weight, sum_frequency, inv_sum2_skew;
int i, index, combined;
@@ -524,6 +524,10 @@ combine_sources(int n_sel_sources, struct timeval *ref_time, double *offset,
sum_offset_weight = sum_offset = sum2_offset_sd = 0.0;
sum_frequency_weight = sum_frequency = inv_sum2_skew = 0.0;
sel_src_distance = sources[selected_source_index]->sel_info.root_distance;
if (sources[selected_source_index]->type == SRC_NTP)
sel_src_distance += reselect_distance;
for (i = combined = 0; i < n_sel_sources; i++) {
index = sel_sources[i];
SST_GetTrackingData(sources[index]->stats, &src_ref_time,
@@ -536,8 +540,7 @@ combine_sources(int n_sel_sources, struct timeval *ref_time, double *offset,
are not close, or it was recently marked as distant */
if (index != selected_source_index &&
(sources[index]->sel_info.root_distance > combine_limit *
(reselect_distance + sources[selected_source_index]->sel_info.root_distance) ||
(sources[index]->sel_info.root_distance > combine_limit * sel_src_distance ||
fabs(*frequency - src_frequency) >
combine_limit * (*skew + src_skew + LCL_GetMaxClockError()))) {
/* Use a smaller penalty in first few updates */

View File

@@ -107,6 +107,18 @@ handle_step(struct timeval *raw, struct timeval *cooked, double dfreq,
}
}
/* ================================================== */
static double
clamp_freq(double freq)
{
if (freq > max_freq)
return max_freq;
if (freq < -max_freq)
return -max_freq;
return freq;
}
/* ================================================== */
/* End currently running slew and start a new one */
@@ -144,11 +156,7 @@ update_slew(void)
corr_freq = max_corr_freq;
/* Get the new real frequency and clamp it */
total_freq = base_freq + corr_freq * (1.0e6 - base_freq);
if (total_freq > max_freq)
total_freq = max_freq;
else if (total_freq < -max_freq)
total_freq = -max_freq;
total_freq = clamp_freq(base_freq + corr_freq * (1.0e6 - base_freq));
/* Set the new frequency (the actual frequency returned by the call may be
slightly different from the requested frequency due to rounding) */
@@ -330,7 +338,7 @@ SYS_Generic_Finalise(void)
slew_timer_running = 0;
}
(*drv_set_freq)(base_freq);
(*drv_set_freq)(clamp_freq(base_freq));
}
/* ================================================== */

9
util.c
View File

@@ -3,7 +3,7 @@
**********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003
* Copyright (C) Miroslav Lichvar 2009, 2012-2013
* Copyright (C) Miroslav Lichvar 2009, 2012-2014
*
* 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
@@ -609,6 +609,9 @@ UTI_Int64ToTimeval(NTP_int64 *src,
/* Maximum offset between two sane times */
#define MAX_OFFSET 4294967296.0
/* Minimum allowed distance from maximum 32-bit time_t */
#define MIN_ENDOFTIME_DISTANCE (365 * 24 * 3600)
int
UTI_IsTimeOffsetSane(struct timeval *tv, double offset)
{
@@ -629,6 +632,10 @@ UTI_IsTimeOffsetSane(struct timeval *tv, double offset)
/* Check if it's in the interval to which NTP time is mapped */
if (t < (double)NTP_ERA_SPLIT || t > (double)(NTP_ERA_SPLIT + (1LL << 32)))
return 0;
#else
/* Don't get too close to 32-bit time_t overflow */
if (t > (double)(0x7fffffff - MIN_ENDOFTIME_DISTANCE))
return 0;
#endif
return 1;

View File

@@ -71,7 +71,7 @@ TMX_ResetOffset(void)
/* Set status back */
txc.modes = ADJ_STATUS;
txc.modes = status;
txc.status = status;
if (adjtimex(&txc) < 0)
return -1;