aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Austein <sra@hactrn.net>2009-05-28 22:48:58 +0000
committerRob Austein <sra@hactrn.net>2009-05-28 22:48:58 +0000
commit67f483fc0f0278c9a696ea43478c39be332760aa (patch)
tree4788e4e965eff9750ac4d1bdcb09c8d78efc6e3a
parent61d552461e397acbce0cb1e7be11539e8fa4b25b (diff)
Handle ROAs containing nested prefixes.
svn path=/rcynic/rcynic.c; revision=2458
-rw-r--r--rcynic/rcynic.c49
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;