diff options
author | Rob Austein <sra@hactrn.net> | 2009-05-28 22:48:58 +0000 |
---|---|---|
committer | Rob Austein <sra@hactrn.net> | 2009-05-28 22:48:58 +0000 |
commit | 67f483fc0f0278c9a696ea43478c39be332760aa (patch) | |
tree | 4788e4e965eff9750ac4d1bdcb09c8d78efc6e3a | |
parent | 61d552461e397acbce0cb1e7be11539e8fa4b25b (diff) |
Handle ROAs containing nested prefixes.
svn path=/rcynic/rcynic.c; revision=2458
-rw-r--r-- | rcynic/rcynic.c | 49 |
1 files changed, 49 insertions, 0 deletions
diff --git a/rcynic/rcynic.c b/rcynic/rcynic.c index 27ce1dda..ef4e12f8 100644 --- a/rcynic/rcynic.c +++ b/rcynic/rcynic.c @@ -2356,6 +2356,10 @@ static int check_roa_1(const rcynic_ctx_t *rc, ee_resources = X509_get_ext_d2i(sk_X509_value(signers, 0), NID_sbgp_ipAddrBlock, NULL, NULL); + /* + * Extract prefixes from ROA and convert them into a resource set. + */ + if (!(roa_resources = sk_IPAddressFamily_new_null())) goto error; @@ -2380,6 +2384,51 @@ static int check_roa_1(const rcynic_ctx_t *rc, } } + /* + * ROAs can include nested prefixes, so direct translation to + * resource sets could include overlapping ranges, which is illegal. + * So we have to remove nested stuff before whacking into canonical + * form. Fortunately, this is relatively easy, since we know these + * are just prefixes, not ranges: in a list of prefixes sorted by + * the RFC 3779 rules, the first element of a set of nested prefixes + * will always be the least specific. + */ + + for (i = 0; i < sk_IPAddressFamily_num(roa_resources); i++) { + IPAddressFamily *f = sk_IPAddressFamily_value(roa_resources, i); + + if ((afi = v3_addr_get_afi(f)) == 0) { + logmsg(rc, log_data_err, "Bad AFI extracting data from ROA %s", uri); + goto error; + } + + if (f->ipAddressChoice->type == IPAddressChoice_addressesOrRanges) { + IPAddressOrRanges *aors = f->ipAddressChoice->u.addressesOrRanges; + + sk_IPAddressOrRange_sort(aors); + + for (j = 0; j < sk_IPAddressOrRange_num(aors) - 1; j++) { + IPAddressOrRange *a = sk_IPAddressOrRange_value(aors, j); + IPAddressOrRange *b = sk_IPAddressOrRange_value(aors, j + 1); + unsigned char a_min[ADDR_RAW_BUF_LEN], a_max[ADDR_RAW_BUF_LEN]; + unsigned char b_min[ADDR_RAW_BUF_LEN], b_max[ADDR_RAW_BUF_LEN]; + int length; + + if ((length = v3_addr_get_range(a, afi, a_min, a_max, ADDR_RAW_BUF_LEN)) == 0 || + (length = v3_addr_get_range(b, afi, b_min, b_max, ADDR_RAW_BUF_LEN)) == 0) { + logmsg(rc, log_data_err, "Trouble extracting addresses from ROA %s", uri); + goto error; + } + + if (memcmp(a_max, b_max, length) >= 0) { + sk_IPAddressOrRange_delete(aors, j + 1); + IPAddressOrRange_free(b); + --j; + } + } + } + } + if (!v3_addr_canonize(roa_resources)) { logmsg(rc, log_data_err, "Failed to put resources from ROA %s into canonical resource set form", uri); goto error; |