ntp: don't allow long MACs in NTPv4 packets with extension fields

MAC longer than 24 octets in NTPv4 packet is supported only for
compatibility with some pre-RFC7822 chrony versions. They didn't use
any extension fields.
This commit is contained in:
Miroslav Lichvar 2020-02-03 14:03:57 +01:00
parent aca1daf7c9
commit 7661a6e95b

View file

@ -282,19 +282,20 @@ NAU_ParsePacket(NTP_Packet *packet, NTP_PacketInfo *info)
/* Parse the rest of the NTPv4 packet */ /* Parse the rest of the NTPv4 packet */
while (remainder > 0) { while (remainder > 0) {
/* Check if the remaining data is a valid MAC. There is a limit on MAC /* Check if the remaining data is a MAC */
length in NTPv4 packets to allow deterministic parsing of extension if (remainder >= NTP_MIN_MAC_LENGTH && remainder <= NTP_MAX_V4_MAC_LENGTH)
fields (RFC 7822), but we need to support longer MACs to not break break;
compatibility with older chrony clients. This needs to be done before
trying to parse the data as an extension field. */
if (remainder >= NTP_MIN_MAC_LENGTH && remainder <= NTP_MAX_MAC_LENGTH) { /* The NTPv4-specific limit for MAC length enables deterministic parsing of
info->auth.mac.key_id = ntohl(*(uint32_t *)(data + parsed)); packets with extension fields (RFC 7822), but we support longer MACs in
if (remainder <= NTP_MAX_V4_MAC_LENGTH || packets with no extension fields for compatibility with older chrony
KEY_CheckAuth(info->auth.mac.key_id, data, parsed, (void *)(data + parsed + 4), clients. Check if the longer MAC would authenticate the packet before
remainder - 4, NTP_MAX_MAC_LENGTH - 4)) trying to parse the data as an extension field. */
break; if (parsed == NTP_HEADER_LENGTH &&
} remainder > NTP_MAX_V4_MAC_LENGTH && remainder <= NTP_MAX_MAC_LENGTH &&
KEY_CheckAuth(ntohl(*(uint32_t *)(data + parsed)), data, parsed,
(void *)(data + parsed + 4), remainder - 4, NTP_MAX_MAC_LENGTH - 4))
break;
/* Check if this is a valid NTPv4 extension field and skip it */ /* Check if this is a valid NTPv4 extension field and skip it */
if (!NEF_ParseField(packet, info->length, parsed, &ef_length, &ef_type, NULL, NULL)) { if (!NEF_ParseField(packet, info->length, parsed, &ef_length, &ef_type, NULL, NULL)) {