]> git.ipfire.org Git - thirdparty/ntp.git/commitdiff
[Sec 3114] Broadcast Mode Replay Prevention DoS
authorJuergen Perlinger <perlinger@ntp.org>
Thu, 20 Oct 2016 18:13:40 +0000 (20:13 +0200)
committerJuergen Perlinger <perlinger@ntp.org>
Thu, 20 Oct 2016 18:13:40 +0000 (20:13 +0200)
bk: 58090954cV4QaVXVunDIzKXbBc3TVA

ChangeLog
ntpd/ntp_proto.c

index 0805467dc6b9b1ce7768a039f6a2d87af37546b9..02e91f937252888e5dd723a5a803f0ca667ab1c9 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+---
+* [Sec 3114] Broadcast Mode Replay Prevention DoS
+  - applied patches by Matthew Van Gundy. <perlinger@ntp.org>
+
 ---
 (4.2.8p8) 2016/06/02 Released by Harlan Stenn <stenn@ntp.org>
 
index 513b99f683e3db8935e283aadbc5f51ea3f916e5..8b2abde7e8ef74922636fe30edca36bf92583842 100644 (file)
@@ -1462,10 +1462,33 @@ receive(
                                ++bail;
                        }
 
-                       /* Alert if time from the server is non-monotonic */
-                       tdiff = p_xmt;
-                       L_SUB(&tdiff, &peer->bxmt);
-                       if (tdiff.l_i < 0) {
+                       /* Alert if time from the server is non-monotonic.
+                        *
+                        * Note this check will not trigger for
+                        * backsteps smaller than the poll interval.
+                        *
+                        * [Bug 3114] But watch for the the initial
+                        * state, when peer->bxmt is all-zero!
+                        *
+                        * Another gotcha to avoid here: After some
+                        * time, we must heed to time stamps, even when
+                        * they are in the past. Otherwise we would
+                        * never be able to catch up with a backstep of
+                        * our broadcast server until the server has
+                        * revored the backstep: The last bxmt now
+                        * survives a cleanout of the peer structure and
+                        * would create another form of DoS.
+                        */
+                       deadband = (1u << (pkt->ppoll + 2));
+                       if (L_ISZERO(&peer->bxmt)) {
+                               tdiff.l_ui = tdiff.l_uf = 0;
+                       } else {
+                               tdiff = p_xmt;
+                               L_SUB(&tdiff, &peer->bxmt);
+                       }
+                       if (tdiff.l_i < 0 &&
+                           (current_time - peer->timereceived) < deadband)
+                       {
                                msyslog(LOG_INFO, "receive: broadcast packet from %s contains non-monotonic timestamp: %#010x.%08x -> %#010x.%08x",
                                        stoa(&rbufp->recv_srcadr),
                                        peer->bxmt.l_ui, peer->bxmt.l_uf,
@@ -1474,8 +1497,6 @@ receive(
                                ++bail;
                        }
 
-                       peer->bxmt = p_xmt;
-
                        if (bail) {
                                peer->timelastrec = current_time;
                                sys_declined++;
@@ -1813,6 +1834,13 @@ receive(
        }
        peer->xmt = p_xmt;
 
+       /*
+        * Now that we know the packet is correctly authenticated,
+        * update peer->bxmt if needed
+        */
+       if (MODE_BROADCAST == hismode)
+               peer->bxmt = p_xmt;
+       
        /*
         * Set the peer ppoll to the maximum of the packet ppoll and the
         * peer minpoll. If a kiss-o'-death, set the peer minpoll to
@@ -2695,6 +2723,7 @@ peer_clear(
        )
 {
        u_char  u;
+       l_fp    bxmt = peer->bxmt;      /* bcast clients retain this! */
 
 #ifdef AUTOKEY
        /*
@@ -2731,6 +2760,10 @@ peer_clear(
        peer->flash = peer_unfit(peer);
        peer->jitter = LOGTOD(sys_precision);
 
+       /* Don't throw away our broadcast replay protection */
+       if (peer->hmode == MODE_BCLIENT)
+               peer->bxmt = bxmt;
+
        /*
         * If interleave mode, initialize the alternate origin switch.
         */