This is a second chunk split out of the diff mentioned in my previous mail. It factors the parsing of ASIdentifiers and IPAddrBlocks out of sbgp_assysnum() and sbgp_ipaddrblk() and makes the latter only extract the info from the X509_EXTENSION. This should not change anything, but the logic is a bit tricky.
We could initialize *as and *asz, as well as *ips and *ipsz to NULL/0, at the top of the two new sbgp_parse_*. Index: cert.c =================================================================== RCS file: /cvs/src/usr.sbin/rpki-client/cert.c,v retrieving revision 1.115 diff -u -p -r1.115 cert.c --- cert.c 12 Sep 2023 09:33:30 -0000 1.115 +++ cert.c 23 Sep 2023 11:03:48 -0000 @@ -153,74 +153,56 @@ sbgp_as_inherit(const char *fn, struct c return append_as(fn, ases, asz, &as); } -/* - * Parse RFC 6487 4.8.11 X509v3 extension, with syntax documented in RFC - * 3779 starting in section 3.2. - * Returns zero on failure, non-zero on success. - */ -static int -sbgp_assysnum(struct parse *p, X509_EXTENSION *ext) +int +sbgp_parse_assysnum(const char *fn, const ASIdentifiers *asidentifiers, + struct cert_as **as, size_t *asz) { - ASIdentifiers *asidentifiers = NULL; const ASIdOrRanges *aors = NULL; - size_t asz; - int i, rc = 0; - - if (!X509_EXTENSION_get_critical(ext)) { - warnx("%s: RFC 6487 section 4.8.11: autonomousSysNum: " - "extension not critical", p->fn); - goto out; - } - - if ((asidentifiers = X509V3_EXT_d2i(ext)) == NULL) { - warnx("%s: RFC 6487 section 4.8.11: autonomousSysNum: " - "failed extension parse", p->fn); - goto out; - } + size_t sz; + int i; if (asidentifiers->rdi != NULL) { warnx("%s: RFC 6487 section 4.8.11: autonomousSysNum: " - "should not have RDI values", p->fn); - goto out; + "should not have RDI values", fn); + return 0; } if (asidentifiers->asnum == NULL) { warnx("%s: RFC 6487 section 4.8.11: autonomousSysNum: " - "no AS number resource set", p->fn); - goto out; + "no AS number resource set", fn); + return 0; } switch (asidentifiers->asnum->type) { case ASIdentifierChoice_inherit: - asz = 1; + sz = 1; break; case ASIdentifierChoice_asIdsOrRanges: aors = asidentifiers->asnum->u.asIdsOrRanges; - asz = sk_ASIdOrRange_num(aors); + sz = sk_ASIdOrRange_num(aors); break; default: warnx("%s: RFC 3779 section 3.2.3.2: ASIdentifierChoice: " - "unknown type %d", p->fn, asidentifiers->asnum->type); - goto out; + "unknown type %d", fn, asidentifiers->asnum->type); + return 0; } - if (asz == 0) { - warnx("%s: RFC 6487 section 4.8.11: empty asIdsOrRanges", - p->fn); - goto out; + if (sz == 0) { + warnx("%s: RFC 6487 section 4.8.11: empty asIdsOrRanges", fn); + return 0; } - if (asz >= MAX_AS_SIZE) { + if (sz >= MAX_AS_SIZE) { warnx("%s: too many AS number entries: limit %d", - p->fn, MAX_AS_SIZE); - goto out; + fn, MAX_AS_SIZE); + return 0; } - p->res->as = calloc(asz, sizeof(struct cert_as)); - if (p->res->as == NULL) + *as = calloc(sz, sizeof(struct cert_as)); + if (*as == NULL) err(1, NULL); if (aors == NULL) { - if (!sbgp_as_inherit(p->fn, p->res->as, &p->res->asz)) - goto out; + if (!sbgp_as_inherit(fn, *as, asz)) + return 0; } for (i = 0; i < sk_ASIdOrRange_num(aors); i++) { @@ -229,22 +211,49 @@ sbgp_assysnum(struct parse *p, X509_EXTE aor = sk_ASIdOrRange_value(aors, i); switch (aor->type) { case ASIdOrRange_id: - if (!sbgp_as_id(p->fn, p->res->as, &p->res->asz, - aor->u.id)) - goto out; + if (!sbgp_as_id(fn, *as, asz, aor->u.id)) + return 0; break; case ASIdOrRange_range: - if (!sbgp_as_range(p->fn, p->res->as, &p->res->asz, - aor->u.range)) - goto out; + if (!sbgp_as_range(fn, *as, asz, aor->u.range)) + return 0; break; default: warnx("%s: RFC 3779 section 3.2.3.5: ASIdOrRange: " - "unknown type %d", p->fn, aor->type); - goto out; + "unknown type %d", fn, aor->type); + return 0; } } + return 1; +} + +/* + * Parse RFC 6487 4.8.11 X509v3 extension, with syntax documented in RFC + * 3779 starting in section 3.2. + * Returns zero on failure, non-zero on success. + */ +static int +sbgp_assysnum(struct parse *p, X509_EXTENSION *ext) +{ + ASIdentifiers *asidentifiers = NULL; + int rc = 0; + + if (!X509_EXTENSION_get_critical(ext)) { + warnx("%s: RFC 6487 section 4.8.11: autonomousSysNum: " + "extension not critical", p->fn); + goto out; + } + + if ((asidentifiers = X509V3_EXT_d2i(ext)) == NULL) { + warnx("%s: RFC 6487 section 4.8.11: autonomousSysNum: " + "failed extension parse", p->fn); + goto out; + } + + if (!sbgp_parse_assysnum(p->fn, asidentifiers, &p->res->as, &p->res->asz)) + goto out; + rc = 1; out: ASIdentifiers_free(asidentifiers); @@ -331,33 +340,16 @@ sbgp_addr_inherit(const char *fn, struct return append_ip(fn, ips, ipsz, &ip); } -/* - * Parse an sbgp-ipAddrBlock X509 extension, RFC 6487 4.8.10, with - * syntax documented in RFC 3779 starting in section 2.2. - * Returns zero on failure, non-zero on success. - */ -static int -sbgp_ipaddrblk(struct parse *p, X509_EXTENSION *ext) +int +sbgp_parse_ipaddrblk(const char *fn, const IPAddrBlocks *addrblk, + struct cert_ip **ips, size_t *ipsz) { - STACK_OF(IPAddressFamily) *addrblk = NULL; - const IPAddressFamily *af; - const IPAddressOrRanges *aors; - const IPAddressOrRange *aor; - enum afi afi; - size_t ipsz; - int i, j, rc = 0; - - if (!X509_EXTENSION_get_critical(ext)) { - warnx("%s: RFC 6487 section 4.8.10: sbgp-ipAddrBlock: " - "extension not critical", p->fn); - goto out; - } - - if ((addrblk = X509V3_EXT_d2i(ext)) == NULL) { - warnx("%s: RFC 6487 section 4.8.10: sbgp-ipAddrBlock: " - "failed extension parse", p->fn); - goto out; - } + const IPAddressFamily *af; + const IPAddressOrRanges *aors; + const IPAddressOrRange *aor; + enum afi afi; + size_t sz; + int i, j; for (i = 0; i < sk_IPAddressFamily_num(addrblk); i++) { af = sk_IPAddressFamily_value(addrblk, i); @@ -365,39 +357,37 @@ sbgp_ipaddrblk(struct parse *p, X509_EXT switch (af->ipAddressChoice->type) { case IPAddressChoice_inherit: aors = NULL; - ipsz = p->res->ipsz + 1; + sz = *ipsz + 1; break; case IPAddressChoice_addressesOrRanges: aors = af->ipAddressChoice->u.addressesOrRanges; - ipsz = p->res->ipsz + sk_IPAddressOrRange_num(aors); + sz = *ipsz + sk_IPAddressOrRange_num(aors); break; default: warnx("%s: RFC 3779: IPAddressChoice: unknown type %d", - p->fn, af->ipAddressChoice->type); - goto out; + fn, af->ipAddressChoice->type); + return 0; } - if (ipsz == p->res->ipsz) { + if (sz == *ipsz) { warnx("%s: RFC 6487 section 4.8.10: " - "empty ipAddressesOrRanges", p->fn); - goto out; + "empty ipAddressesOrRanges", fn); + return 0; } - if (ipsz >= MAX_IP_SIZE) - goto out; - p->res->ips = recallocarray(p->res->ips, p->res->ipsz, ipsz, - sizeof(struct cert_ip)); - if (p->res->ips == NULL) + if (sz >= MAX_IP_SIZE) + return 0; + *ips = recallocarray(*ips, *ipsz, sz, sizeof(struct cert_ip)); + if (*ips == NULL) err(1, NULL); - if (!ip_addr_afi_parse(p->fn, af->addressFamily, &afi)) { - warnx("%s: RFC 3779: invalid AFI", p->fn); - goto out; + if (!ip_addr_afi_parse(fn, af->addressFamily, &afi)) { + warnx("%s: RFC 3779: invalid AFI", fn); + return 0; } if (aors == NULL) { - if (!sbgp_addr_inherit(p->fn, p->res->ips, - &p->res->ipsz, afi)) - goto out; + if (!sbgp_addr_inherit(fn, *ips, ipsz, afi)) + return 0; continue; } @@ -405,22 +395,51 @@ sbgp_ipaddrblk(struct parse *p, X509_EXT aor = sk_IPAddressOrRange_value(aors, j); switch (aor->type) { case IPAddressOrRange_addressPrefix: - if (!sbgp_addr(p->fn, p->res->ips, - &p->res->ipsz, afi, aor->u.addressPrefix)) - goto out; + if (!sbgp_addr(fn, *ips, ipsz, afi, + aor->u.addressPrefix)) + return 0; break; case IPAddressOrRange_addressRange: - if (!sbgp_addr_range(p->fn, p->res->ips, - &p->res->ipsz, afi, aor->u.addressRange)) - goto out; + if (!sbgp_addr_range(fn, *ips, ipsz, afi, + aor->u.addressRange)) + return 0; break; default: warnx("%s: RFC 3779: IPAddressOrRange: " - "unknown type %d", p->fn, aor->type); - goto out; + "unknown type %d", fn, aor->type); + return 0; } } } + + return 1; +} + +/* + * Parse an sbgp-ipAddrBlock X509 extension, RFC 6487 4.8.10, with + * syntax documented in RFC 3779 starting in section 2.2. + * Returns zero on failure, non-zero on success. + */ +static int +sbgp_ipaddrblk(struct parse *p, X509_EXTENSION *ext) +{ + STACK_OF(IPAddressFamily) *addrblk = NULL; + int rc = 0; + + if (!X509_EXTENSION_get_critical(ext)) { + warnx("%s: RFC 6487 section 4.8.10: sbgp-ipAddrBlock: " + "extension not critical", p->fn); + goto out; + } + + if ((addrblk = X509V3_EXT_d2i(ext)) == NULL) { + warnx("%s: RFC 6487 section 4.8.10: sbgp-ipAddrBlock: " + "failed extension parse", p->fn); + goto out; + } + + if (!sbgp_parse_ipaddrblk(p->fn, addrblk, &p->res->ips, &p->res->ipsz)) + goto out; if (p->res->ipsz == 0) { warnx("%s: RFC 6487 section 4.8.10: empty ipAddrBlock", p->fn); Index: extern.h =================================================================== RCS file: /cvs/src/usr.sbin/rpki-client/extern.h,v retrieving revision 1.189 diff -u -p -r1.189 extern.h --- extern.h 12 Sep 2023 09:33:30 -0000 1.189 +++ extern.h 23 Sep 2023 11:04:23 -0000 @@ -721,6 +721,9 @@ int sbgp_addr(const char *, struct cer int sbgp_addr_range(const char *, struct cert_ip *, size_t *, enum afi, const IPAddressRange *); +int sbgp_parse_ipaddrblk(const char *, const IPAddrBlocks *, + struct cert_ip **, size_t *); + /* Work with RFC 3779 AS numbers, ranges. */ int as_id_parse(const ASN1_INTEGER *, uint32_t *); @@ -733,6 +736,9 @@ int sbgp_as_id(const char *, struct ce const ASN1_INTEGER *); int sbgp_as_range(const char *, struct cert_as *, size_t *, const ASRange *); + +int sbgp_parse_assysnum(const char *, const ASIdentifiers *, + struct cert_as **, size_t *); /* Parser-specific */ void entity_free(struct entity *);