]> git.ipfire.org Git - thirdparty/ntp.git/commitdiff
[Sec 2935] Deja Vu: Replay attack on authenticated broadcast mode.
authorHarlan Stenn <stenn@ntp.org>
Mon, 11 Jan 2016 11:02:53 +0000 (03:02 -0800)
committerHarlan Stenn <stenn@ntp.org>
Mon, 11 Jan 2016 11:02:53 +0000 (03:02 -0800)
bk: 56938bddZ082rJR2isSc8bTl_6L3Mw

ChangeLog
include/ntp.h
ntpd/ntp_proto.c

index 304bd85ab7dc7c851bbe3b0704766c8fed26ba78..8fcfb7ee7f27912d599af951c4be67bd6b302e66 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,8 @@
 ---
+
+* [Sec 2935] Deja Vu: Replay attack on authenticated broadcast mode. HStenn.
+* Make leapsec_query debug messages less verbose.  Harlan Stenn.
+---
 (4.2.8p5) 2016/01/07 Released by Harlan Stenn <stenn@ntp.org>
 
 * [Sec 2956] small-step/big-step.  Close the panic gate earlier.  HStenn.
index adf017cfb847e1fc0a6e534b5efbf4f98d81a01d..25f68100174731ec1f05a75d83a3671f48f0da89 100644 (file)
@@ -350,6 +350,7 @@ struct peer {
        l_fp    dst;            /* destination timestamp */
        l_fp    aorg;           /* origin timestamp */
        l_fp    borg;           /* alternate origin timestamp */
+       l_fp    bxmt;           /* most recent broadcast transmit timestamp */
        double  offset;         /* peer clock offset */
        double  delay;          /* peer roundtrip delay */
        double  jitter;         /* peer jitter (squares) */
index f7704722a9baf17ebb5d9fceb66711d1d0aa586b..e45d48e2170f648c18cac197e6ec62d805f9e864 100644 (file)
@@ -1157,6 +1157,7 @@ receive(
 
                        } else {
                                peer->delay = sys_bdelay;
+                               peer->bxmt = p_xmt;
                        }
                        break;
                }
@@ -1177,6 +1178,7 @@ receive(
                        sys_restricted++;
                        return;                 /* ignore duplicate */
                }
+               peer->bxmt = p_xmt;
 #ifdef AUTOKEY
                if (skeyid > NTP_MAXKEY)
                        crypto_recv(peer, rbufp);
@@ -1286,6 +1288,70 @@ receive(
                        return;
                }
 #endif /* AUTOKEY */
+
+               if (MODE_BROADCAST == hismode) {
+                       u_char poll;
+                       int bail = 0;
+
+                       DPRINTF(2, ("receive: PROCPKT/BROADCAST: prev pkt %ld seconds ago, ppoll: %d, %d secs\n",
+                                   (current_time - peer->timelastrec),
+                                   peer->ppoll, (1 << peer->ppoll)
+                                   ));
+                       /* Things we can check:
+                        *
+                        * Did the poll interval change?
+                        * Is the poll interval in the packet in-range?
+                        * Did this packet arrive too soon?
+                        * Is the timestamp in this packet monotonic
+                        *  with respect to the previous packet?
+                        */
+
+                       /* This is noteworthy, not error-worthy */
+                       if (pkt->ppoll != peer->ppoll) {
+                               msyslog(LOG_INFO, "receive: broadcast poll from %s changed from %ud to %ud",
+                                       stoa(&rbufp->recv_srcadr),
+                                       peer->ppoll, pkt->ppoll);
+                       }
+
+                       poll = min(peer->maxpoll,
+                                  max(peer->minpoll, pkt->ppoll));
+
+                       /* This is error-worthy */
+                       if (pkt->ppoll != poll) {
+                               msyslog(LOG_INFO, "receive: broadcast poll of %ud from %s is out-of-range (%d to %d)!",
+                                       pkt->ppoll, stoa(&rbufp->recv_srcadr),
+                                       peer->minpoll, peer->maxpoll);
+                               ++bail;
+                       }
+
+                       if (  (current_time - peer->timelastrec)
+                           < (1 << pkt->ppoll)) {
+                               msyslog(LOG_INFO, "receive: broadcast packet from %s arrived after %ld, not %d seconds!",
+                                       stoa(&rbufp->recv_srcadr),
+                                       (current_time - peer->timelastrec),
+                                       (1 << pkt->ppoll)
+                                       );
+                               ++bail;
+                       }
+
+                       if (L_ISGT(&peer->bxmt, &p_xmt)) {
+                               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,
+                                       p_xmt.l_ui, p_xmt.l_uf
+                                       );
+                               ++bail;
+                       }
+
+                       peer->bxmt = p_xmt;
+
+                       if (bail) {
+                               peer->timelastrec = current_time;
+                               sys_declined++;
+                               return;
+                       }
+               }
+
                break;
 
        /*
@@ -1511,6 +1577,7 @@ receive(
         * clean. Get on with real work.
         */
        peer->timereceived = current_time;
+       peer->timelastrec = current_time;
        if (is_authentic == AUTH_OK)
                peer->flags |= FLAG_AUTHENTIC;
        else