From: Juergen Perlinger Date: Thu, 20 Oct 2016 18:13:40 +0000 (+0200) Subject: [Sec 3114] Broadcast Mode Replay Prevention DoS X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d723ec8f934e9be7184a2c0056cd734e0301316d;p=thirdparty%2Fntp.git [Sec 3114] Broadcast Mode Replay Prevention DoS bk: 58090954cV4QaVXVunDIzKXbBc3TVA --- diff --git a/ChangeLog b/ChangeLog index 0805467dc..02e91f937 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +--- +* [Sec 3114] Broadcast Mode Replay Prevention DoS + - applied patches by Matthew Van Gundy. + --- (4.2.8p8) 2016/06/02 Released by Harlan Stenn diff --git a/ntpd/ntp_proto.c b/ntpd/ntp_proto.c index 513b99f68..8b2abde7e 100644 --- a/ntpd/ntp_proto.c +++ b/ntpd/ntp_proto.c @@ -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. */