ntp: don't send packets with RX/TX timestamp equal to another timestamp
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.
This commit is contained in:
parent
f0f18a02a7
commit
2c7ab98370
3 changed files with 49 additions and 13 deletions
41
ntp_core.c
41
ntp_core.c
|
@ -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_rx, /* The RX time of the received packet */
|
||||||
NTP_Local_Timestamp *local_tx, /* The TX time of the previous packet
|
NTP_Local_Timestamp *local_tx, /* The TX time of the previous packet
|
||||||
RESULT : TX time of this packet */
|
RESULT : TX time of this packet */
|
||||||
NTP_int64 *local_ntp_rx, /* RESULT : receive timestamp from this packet */
|
NTP_int64 *local_ntp_rx, /* The receive timestamp from the previous packet
|
||||||
NTP_int64 *local_ntp_tx, /* RESULT : transmit timestamp from this 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_Remote_Address *where_to, /* Where to address the reponse to */
|
||||||
NTP_Local_Address *from /* From what address to send it */
|
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 */
|
/* Originate - this comes from the last packet the source sent us */
|
||||||
message.originate_ts = interleaved ? *remote_ntp_rx : *remote_ntp_tx;
|
message.originate_ts = interleaved ? *remote_ntp_rx : *remote_ntp_tx;
|
||||||
|
|
||||||
/* Prepare random bits which will be added to the receive timestamp */
|
do {
|
||||||
UTI_GetNtp64Fuzz(&ts_fuzz, precision);
|
/* 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.
|
/* 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
|
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
|
the source like we have been running on our latest estimate of
|
||||||
frequency all along */
|
frequency all along */
|
||||||
UTI_TimespecToNtp64(&local_receive, &message.receive_ts, &ts_fuzz);
|
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 {
|
} else {
|
||||||
UTI_ZeroNtp64(&message.originate_ts);
|
UTI_ZeroNtp64(&message.originate_ts);
|
||||||
UTI_ZeroNtp64(&message.receive_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);
|
&message.transmit_ts, &ts_fuzz);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Avoid sending messages with non-zero transmit timestamp equal to the
|
/* Do not send a packet with a non-zero transmit timestamp which is
|
||||||
receive timestamp to allow reliable detection of the interleaved mode */
|
equal to any of the following timestamps:
|
||||||
} while (!UTI_CompareNtp64(&message.transmit_ts, &message.receive_ts) &&
|
- receive (to allow reliable detection of the interleaved mode)
|
||||||
!UTI_IsZeroNtp64(&message.transmit_ts));
|
- 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);
|
ret = NIO_SendPacket(&message, where_to, from, length, local_tx != NULL);
|
||||||
|
|
||||||
|
|
17
util.c
17
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 */
|
/* Seconds part of NTP timestamp correponding to the origin of the time_t format */
|
||||||
#define JAN_1970 0x83aa7e80UL
|
#define JAN_1970 0x83aa7e80UL
|
||||||
|
|
||||||
|
|
4
util.h
4
util.h
|
@ -136,6 +136,10 @@ extern int UTI_IsZeroNtp64(NTP_int64 *ts);
|
||||||
b, and 1 if a is after b. */
|
b, and 1 if a is after b. */
|
||||||
extern int UTI_CompareNtp64(NTP_int64 *a, NTP_int64 *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 */
|
/* Convert a timespec into an NTP timestamp */
|
||||||
extern void UTI_TimespecToNtp64(struct timespec *src, NTP_int64 *dest, NTP_int64 *fuzz);
|
extern void UTI_TimespecToNtp64(struct timespec *src, NTP_int64 *dest, NTP_int64 *fuzz);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue