]> git.ipfire.org Git - thirdparty/chrony.git/commitdiff
ntp: don't send packets with RX/TX timestamp equal to another timestamp
authorMiroslav Lichvar <mlichvar@redhat.com>
Tue, 20 Feb 2018 08:46:08 +0000 (09:46 +0100)
committerMiroslav Lichvar <mlichvar@redhat.com>
Mon, 26 Feb 2018 12:42:04 +0000 (13:42 +0100)
Before sending a new packet, check if the receive/transmit timestamp
is not equal to the origin timestamp or the previous receive/transmit
timestamp in order to prevent the packet from being its own valid
response (in the symmetric mode) and invalidate responses to the
previous packet.

This improves protection against replay attacks in the symmetric mode.

ntp_core.c
util.c
util.h

index 18e66843ae4c90ba32a8ca4e445c2c19e192228d..6d5b8576e082fba49c62343ffcf85f39ce9be94f 100644 (file)
@@ -899,8 +899,10 @@ transmit_packet(NTP_Mode my_mode, /* The mode this machine wants to be */
                 NTP_Local_Timestamp *local_rx, /* The RX time of the received packet */
                 NTP_Local_Timestamp *local_tx, /* The TX time of the previous packet
                                                   RESULT : TX time of this packet */
-                NTP_int64 *local_ntp_rx, /* RESULT : receive timestamp from this packet */
-                NTP_int64 *local_ntp_tx, /* RESULT : transmit timestamp from this packet */
+                NTP_int64 *local_ntp_rx, /* The receive timestamp from the previous packet
+                                            RESULT : receive timestamp from this packet */
+                NTP_int64 *local_ntp_tx, /* The transmit timestamp from the previous packet
+                                            RESULT : transmit timestamp from this packet */
                 NTP_Remote_Address *where_to, /* Where to address the reponse to */
                 NTP_Local_Address *from /* From what address to send it */
                 )
@@ -998,14 +1000,21 @@ transmit_packet(NTP_Mode my_mode, /* The mode this machine wants to be */
     /* Originate - this comes from the last packet the source sent us */
     message.originate_ts = interleaved ? *remote_ntp_rx : *remote_ntp_tx;
 
-    /* Prepare random bits which will be added to the receive timestamp */
-    UTI_GetNtp64Fuzz(&ts_fuzz, precision);
-
-    /* Receive - this is when we received the last packet from the source.
-       This timestamp will have been adjusted so that it will now look to
-       the source like we have been running on our latest estimate of
-       frequency all along */
-    UTI_TimespecToNtp64(&local_receive, &message.receive_ts, &ts_fuzz);
+    do {
+      /* Prepare random bits which will be added to the receive timestamp */
+      UTI_GetNtp64Fuzz(&ts_fuzz, precision);
+
+      /* Receive - this is when we received the last packet from the source.
+         This timestamp will have been adjusted so that it will now look to
+         the source like we have been running on our latest estimate of
+         frequency all along */
+      UTI_TimespecToNtp64(&local_receive, &message.receive_ts, &ts_fuzz);
+
+      /* Do not send a packet with a non-zero receive timestamp equal to the
+         originate timestamp or previous receive timestamp */
+    } while (!UTI_IsZeroNtp64(&message.receive_ts) &&
+             UTI_IsEqualAnyNtp64(&message.receive_ts, &message.originate_ts,
+                                 local_ntp_rx, NULL));
   } else {
     UTI_ZeroNtp64(&message.originate_ts);
     UTI_ZeroNtp64(&message.receive_ts);
@@ -1064,10 +1073,16 @@ transmit_packet(NTP_Mode my_mode, /* The mode this machine wants to be */
                           &message.transmit_ts, &ts_fuzz);
     }
 
-    /* Avoid sending messages with non-zero transmit timestamp equal to the
-       receive timestamp to allow reliable detection of the interleaved mode */
-  } while (!UTI_CompareNtp64(&message.transmit_ts, &message.receive_ts) &&
-           !UTI_IsZeroNtp64(&message.transmit_ts));
+    /* Do not send a packet with a non-zero transmit timestamp which is
+       equal to any of the following timestamps:
+       - receive (to allow reliable detection of the interleaved mode)
+       - originate (to prevent the packet from being its own valid response
+                    in the symmetric mode)
+       - previous transmit (to invalidate responses to the previous packet)
+       (the precision must be at least -30 to prevent an infinite loop!) */
+  } while (!UTI_IsZeroNtp64(&message.transmit_ts) &&
+           UTI_IsEqualAnyNtp64(&message.transmit_ts, &message.receive_ts,
+                               &message.originate_ts, local_ntp_tx));
 
   ret = NIO_SendPacket(&message, where_to, from, length, local_tx != NULL);
 
diff --git a/util.c b/util.c
index 586dcbd705a21447133dfeb5d750b42ede94d788..95c27c0e86dcff803ed855c2109bb0b823f46773 100644 (file)
--- a/util.c
+++ b/util.c
@@ -726,6 +726,23 @@ UTI_CompareNtp64(NTP_int64 *a, NTP_int64 *b)
 
 /* ================================================== */
 
+int
+UTI_IsEqualAnyNtp64(NTP_int64 *a, NTP_int64 *b1, NTP_int64 *b2, NTP_int64 *b3)
+{
+  if (b1 && a->lo == b1->lo && a->hi == b1->hi)
+    return 1;
+
+  if (b2 && a->lo == b2->lo && a->hi == b2->hi)
+    return 1;
+
+  if (b3 && a->lo == b3->lo && a->hi == b3->hi)
+    return 1;
+
+  return 0;
+}
+
+/* ================================================== */
+
 /* Seconds part of NTP timestamp correponding to the origin of the time_t format */
 #define JAN_1970 0x83aa7e80UL
 
diff --git a/util.h b/util.h
index 02d598b51248f8b34d1174d40c75a639ddc6e5b9..40ff72900a5fe7f3512b6f5c0f5bcddae91e4414 100644 (file)
--- a/util.h
+++ b/util.h
@@ -136,6 +136,10 @@ extern int UTI_IsZeroNtp64(NTP_int64 *ts);
    b, and 1 if a is after b. */
 extern int UTI_CompareNtp64(NTP_int64 *a, NTP_int64 *b);
 
+/* Compare an NTP timestamp with up to three other timestamps.  Returns 0
+   if a is not equal to any of b1, b2, and b3, 1 otherwise. */
+extern int UTI_IsEqualAnyNtp64(NTP_int64 *a, NTP_int64 *b1, NTP_int64 *b2, NTP_int64 *b3);
+
 /* Convert a timespec into an NTP timestamp */
 extern void UTI_TimespecToNtp64(struct timespec *src, NTP_int64 *dest, NTP_int64 *fuzz);