+New in version 2.0
+==================
+
+Enhancements
+------------
+* Update to NTP version 4 (RFC 5905)
+* Add pool directive to specify pool of NTP servers
+* Add minsources directive to set required number of selectable sources
+* Add minsamples and maxsamples options for all sources
+* Add tempcomp configuration with list of points
+* Allow unlimited number of NTP sources, refclocks and keys
+* Allow unreachable sources to remain selected
+* 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)
+* Change default bindcmdaddress to loopback address
+* Change default stratumweight to 0.001
+* Update adjtimex synchronisation status
+* Use system headers for adjtimex
+* Check for memory allocation errors
+* Reduce memory usage
+* Add configure options to compile without NTP, cmdmon, refclock support
+* Extend makestep command to set automatic clock stepping
+
+Bug fixes
+---------
+* Fix accepting requests from configured sources when acquisitionport
+ is equal to server port
+* Fix allocation of slots saving replies to authenticated commands
+
+ New in version 1.31.1
+ =====================
+
+ Security fixes
+ --------------
+ * Protect authenticated symmetric NTP associations against DoS attacks
+ (CVE-2015-1799)
+ * Fix access configuration with subnet size indivisible by 4 (CVE-2015-1821)
+ * Fix initialization of reply slots for authenticated commands (CVE-2015-1822)
+
New in version 1.31
===================
pkt_root_delay = UTI_Int32ToDouble(message->root_delay);
pkt_root_dispersion = UTI_Int32ToDouble(message->root_dispersion);
- /* Perform packet validity tests */
-
- /* Test 1 requires that pkt.xmt != peer.org. This protects
- against receiving a duplicate packet */
-
- if ((message->transmit_ts.hi == inst->remote_orig.hi) &&
- (message->transmit_ts.lo == inst->remote_orig.lo)) {
- test1 = 0; /* Failed */
- } else {
- test1 = 1; /* Success */
- }
+ UTI_Int64ToTimeval(&message->receive_ts, &remote_receive_tv);
+ UTI_Int64ToTimeval(&message->transmit_ts, &remote_transmit_tv);
+ UTI_Int64ToTimeval(&message->reference_ts, &remote_reference_tv);
- /* Test 2 requires pkt.org == peer.xmt. This ensures the source
- is responding to the latest packet we sent to it. */
- if ((message->originate_ts.hi != inst->local_ntp_tx.hi) ||
- (message->originate_ts.lo != inst->local_ntp_tx.lo)) {
- test2 = 0; /* Failed */
- } else {
- test2 = 1; /* Success */
+ /* Check if the packet is valid per RFC 5905, section 8.
+ The test values are 1 when passed and 0 when failed. */
+
+ /* Test 1 checks for duplicate packet */
+ test1 = message->transmit_ts.hi != inst->remote_orig.hi ||
+ message->transmit_ts.lo != inst->remote_orig.lo;
+
+ /* Test 2 checks for bogus packet. This ensures the source is responding to
+ the latest packet we sent to it. */
+ test2 = message->originate_ts.hi == inst->local_ntp_tx.hi &&
+ message->originate_ts.lo == inst->local_ntp_tx.lo;
+
+ /* Test 3 checks for invalid timestamps. This can happen when the
+ association if not properly 'up'. */
+ test3 = (message->originate_ts.hi || message->originate_ts.lo) &&
+ (message->receive_ts.hi || message->receive_ts.lo) &&
+ (message->reference_ts.hi || message->reference_ts.lo) &&
+ (message->transmit_ts.hi || message->transmit_ts.lo);
+
+ /* Test 4 would check for denied access. It would always pass as this
+ function is called only for known sources. */
+
+ /* Test 5 checks for authentication failure. If we expect authenticated info
+ from this peer/server and the packet doesn't have it or the authentication
+ is bad, it's got to fail. If the peer or server sends us an authenticated
+ frame, but we're not bothered about whether he authenticates or not, just
+ ignore the test. */
+ test5 = inst->do_auth ? check_packet_auth(message, length, NULL, NULL) : 1;
+
+ /* Test 6 checks for unsynchronised server */
+ test6 = pkt_leap != LEAP_Unsynchronised &&
+ message->stratum < NTP_MAX_STRATUM &&
+ message->stratum != NTP_INVALID_STRATUM;
+
+ /* Test 7 checks for bad data. The root distance must be smaller than a
+ defined maximum and the transmit time must not be before the time of
+ the last synchronisation update. */
+ test7 = pkt_root_delay / 2.0 + pkt_root_dispersion < NTP_MAX_DISPERSION &&
+ UTI_CompareTimevals(&remote_reference_tv, &remote_transmit_tv) < 1;
+
+ /* The packet is considered valid if the tests above passed */
+ valid_packet = test1 && test2 && test3 && test5 && test6 && test7;
+
+ /* Check for Kiss-o'-Death codes */
+ kod_rate = 0;
+ if (test1 && test2 && test5 && pkt_leap == LEAP_Unsynchronised &&
+ message->stratum == NTP_INVALID_STRATUM) {
+ if (pkt_refid == KOD_RATE)
+ kod_rate = 1;
}
- /* Regardless of any validity checks we apply, we are required to
- save these fields from the packet into the ntp source instance record.
- Note we can't do this assignment before test 1 has been carried out. */
- inst->remote_orig = message->transmit_ts;
- inst->local_rx = *now;
- /* Test 3 requires that pkt.org != 0 and pkt.rec != 0. If
- either of these are true it means the association is not properly
- 'up'. */
-
- if (((message->originate_ts.hi == 0) && (message->originate_ts.lo == 0)) ||
- ((message->receive_ts.hi == 0) && (message->receive_ts.lo == 0))) {
- test3 = 0; /* Failed */
- } else {
- test3 = 1; /* Success */
++ /* The transmit timestamp and local receive timestamp must not be saved when
++ the authentication test failed to prevent denial-of-service attacks on
++ symmetric associations using authentication */
++ if (test5) {
++ inst->remote_orig = message->transmit_ts;
++ inst->local_rx = *now;
+ }
- SRC_GetFrequencyRange(inst->source, &source_freq_lo, &source_freq_hi);
+ /* This protects against replay of the last packet we sent */
+ if (test2)
+ inst->local_ntp_tx.hi = inst->local_ntp_tx.lo = 0;
- UTI_Int64ToTimeval(&message->receive_ts, &remote_receive_tv);
- UTI_Int64ToTimeval(&message->transmit_ts, &remote_transmit_tv);
+ if (valid_packet) {
+ precision = LCL_GetSysPrecisionAsQuantum();
- if (test3) {
+ SRC_GetFrequencyRange(inst->source, &source_freq_lo, &source_freq_hi);
UTI_AverageDiffTimevals(&remote_receive_tv, &remote_transmit_tv,
&remote_average, &remote_interval);