RPKI: Add contextual out-of-bound checks in RTR Prefix PDU handler

RFC 6810 and RFC 8210 specify that the "Max Length" value MUST NOT be
less than the Prefix Length element (underflow). On the other side,
overflow of the Max Length element also is possible, it being an 8-bit
unsigned integer allows for values larger than 32 or 128. This also
implicitly ensures there is no overflow of "Length" value.

When a PDU is received where the Max Length field is corrputed, the RTR
client (BIRD) should immediately terminate the session, flush all data
learned from that cache, and log an error for the operator.

Minor changes done by commiter.
This commit is contained in:
Job Snijders 2021-12-18 16:35:28 +01:00 committed by Ondrej Zajicek (work)
parent 00410fd6c1
commit b9f38727a7

View file

@ -737,6 +737,33 @@ rpki_handle_prefix_pdu(struct rpki_cache *cache, const struct pdu_header *pdu)
net_addr_union addr = {}; net_addr_union addr = {};
rpki_prefix_pdu_2_net_addr(pdu, &addr); rpki_prefix_pdu_2_net_addr(pdu, &addr);
if (type == IPV4_PREFIX)
{
if ((addr.roa4.pxlen > addr.roa4.max_pxlen) ||
(addr.roa4.max_pxlen > IP4_MAX_PREFIX_LENGTH))
{
RPKI_WARN(cache->p, "Received corrupt packet from RPKI cache server: invalid pxlen or max_pxlen");
byte tmp[pdu->len];
const struct pdu_header *hton_pdu = rpki_pdu_back_to_network_byte_order((void *) tmp, (const void *) pdu);
rpki_send_error_pdu(cache, CORRUPT_DATA, pdu->len, hton_pdu, "Corrupted PDU: invalid pxlen or max_pxlen");
rpki_cache_change_state(cache, RPKI_CS_ERROR_FATAL);
return RPKI_ERROR;
}
}
else
{
if ((addr.roa6.pxlen > addr.roa6.max_pxlen) ||
(addr.roa6.max_pxlen > IP6_MAX_PREFIX_LENGTH))
{
RPKI_WARN(cache->p, "Received corrupt packet from RPKI cache server: invalid pxlen or max_pxlen");
byte tmp[pdu->len];
const struct pdu_header *hton_pdu = rpki_pdu_back_to_network_byte_order((void *) tmp, (const void *) pdu);
rpki_send_error_pdu(cache, CORRUPT_DATA, pdu->len, hton_pdu, "Corrupted PDU: invalid pxlen or max_pxlen");
rpki_cache_change_state(cache, RPKI_CS_ERROR_FATAL);
return RPKI_ERROR;
}
}
if (cf->ignore_max_length) if (cf->ignore_max_length)
{ {
if (type == IPV4_PREFIX) if (type == IPV4_PREFIX)