if (remainder >= NTP_MIN_MAC_LENGTH && remainder <= NTP_MAX_V4_MAC_LENGTH)
break;
- /* The NTPv4-specific limit for MAC length enables deterministic parsing of
- packets with extension fields (RFC 7822), but we support longer MACs in
- packets with no extension fields for compatibility with older chrony
- clients. Check if the longer MAC would authenticate the packet before
- trying to parse the data as an extension field. */
- 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,
- data + parsed + 4, remainder - 4, NTP_MAX_MAC_LENGTH - 4))
- break;
-
/* 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)) {
- /* Invalid MAC or format error */
- DEBUG_LOG("Invalid format or MAC");
+ DEBUG_LOG("Invalid format");
return 0;
}
/* No MAC */
return 1;
} else if (remainder >= NTP_MIN_MAC_LENGTH) {
- /* This is not 100% reliable as a MAC could fail to authenticate and could
- pass as an extension field, leaving reminder smaller than the minimum MAC
- length */
info->auth.mode = NTP_AUTH_SYMMETRIC;
info->auth.mac.start = parsed;
info->auth.mac.length = remainder;
CLG_LogAuthNtpRequest();
}
- /* If it is an NTPv4 packet with a long MAC and no extension fields,
- respond with an NTPv3 packet to avoid breaking RFC 7822 and keep
- the length symmetric. Otherwise, respond with the same version. */
- if (info.version == 4 && info.ext_fields == 0 && info.auth.mode == NTP_AUTH_SYMMETRIC &&
- info.auth.mac.length > NTP_MAX_V4_MAC_LENGTH)
- version = 3;
- else
- version = info.version;
-
local_ntp_rx = local_ntp_tx = NULL;
tx_ts = NULL;
interleaved = 0;
poll = CLG_GetNtpMinPoll();
poll = MAX(poll, message->poll);
+ /* Respond with the same version */
+ version = info.version;
+
/* Send a reply */
transmit_packet(my_mode, interleaved, poll, version, kod, NULL,
&message->receive_ts, &message->transmit_ts,
key_id = get_random_key_id();
auth_len = KEY_GetAuthLength(key_id);
assert(auth_len);
- if (NTP_LVM_TO_VERSION(res->lvm) == 4 && random() % 2)
+ if (NTP_LVM_TO_VERSION(res->lvm) == 4)
auth_len = MIN(auth_len, NTP_MAX_V4_MAC_LENGTH - 4);
if (KEY_GenerateAuth(key_id, (unsigned char *)res, NTP_HEADER_LENGTH,
if (!valid_auth && authenticated) {
assert(auth_len);
- switch (random() % 4) {
+ switch (random() % 5) {
case 0:
key_id++;
break;
break;
case 3:
res_length = NTP_HEADER_LENGTH + 4 * (random() % ((4 + auth_len) / 4));
- if (NTP_LVM_TO_VERSION(res->lvm) == 4 &&
- res_length == NTP_HEADER_LENGTH + NTP_MAX_V4_MAC_LENGTH)
- res_length -= 4;
+ break;
+ case 4:
+ if (NTP_LVM_TO_VERSION(res->lvm) == 4 && random() % 2 &&
+ KEY_GetAuthLength(key_id) > NTP_MAX_V4_MAC_LENGTH - 4) {
+ auth_len += 4 + 4 * (random() %
+ ((KEY_GetAuthLength(key_id) - NTP_MAX_V4_MAC_LENGTH - 4) / 4));
+ if (KEY_GenerateAuth(key_id, (unsigned char *)res, NTP_HEADER_LENGTH,
+ res->extensions + 4, auth_len) != auth_len)
+ assert(0);
+ res_length = NTP_HEADER_LENGTH + 4 + auth_len;
+ } else {
+ memset((unsigned char *)res + res_length, 0, 4);
+ res_length += 4;
+ }
break;
default:
assert(0);