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_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);
|
||||
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);
|
||||
/* 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);
|
||||
|
||||
|
|
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 */
|
||||
#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. */
|
||||
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);
|
||||
|
||||
|
|
Loading…
Reference in a new issue