On Mon, Sep 25, 2023 at 02:47:37PM +0200, Claudio Jeker wrote: > On Sat, Sep 23, 2023 at 01:23:34PM +0200, Theo Buehler wrote: > > 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_*. > > It looks inded like nthing is changed. The thing I dislike a bit is how > **as and *asz are updated inside the sbgp_parse_* functions. There is > return 0 before and after the calloc / recallocarray calls and so it > depends a lot on the caller to be careful here. The code right now is ok.
Thanks for that clue. I didn't particularly like my diff either. The below is better, has less churn and should be easier to review. This way the caller doesn't have to be careful. I left the currently existing variables asz and ipsz untouched since it becomes too confusing. I want to rename asz -> sz and new_asz -> asz in a follow-up, similarly for ipsz. 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 25 Sep 2023 14:29:56 -0000 @@ -153,40 +153,26 @@ 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 **out_as, size_t *out_asz) { - ASIdentifiers *asidentifiers = NULL; const ASIdOrRanges *aors = NULL; - size_t asz; - int i, rc = 0; + struct cert_as *as = NULL; + size_t asz, new_asz = 0; + int i; - 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; - } + assert(*out_as == NULL && *out_asz == 0); if (asidentifiers->rdi != NULL) { warnx("%s: RFC 6487 section 4.8.11: autonomousSysNum: " - "should not have RDI values", p->fn); + "should not have RDI values", fn); goto out; } if (asidentifiers->asnum == NULL) { warnx("%s: RFC 6487 section 4.8.11: autonomousSysNum: " - "no AS number resource set", p->fn); + "no AS number resource set", fn); goto out; } @@ -200,26 +186,25 @@ sbgp_assysnum(struct parse *p, X509_EXTE break; default: warnx("%s: RFC 3779 section 3.2.3.2: ASIdentifierChoice: " - "unknown type %d", p->fn, asidentifiers->asnum->type); + "unknown type %d", fn, asidentifiers->asnum->type); goto out; } if (asz == 0) { - warnx("%s: RFC 6487 section 4.8.11: empty asIdsOrRanges", - p->fn); + warnx("%s: RFC 6487 section 4.8.11: empty asIdsOrRanges", fn); goto out; } if (asz >= MAX_AS_SIZE) { warnx("%s: too many AS number entries: limit %d", - p->fn, MAX_AS_SIZE); + fn, MAX_AS_SIZE); goto out; } - p->res->as = calloc(asz, sizeof(struct cert_as)); - if (p->res->as == NULL) + as = calloc(asz, 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)) + if (!sbgp_as_inherit(fn, as, &new_asz)) goto out; } @@ -229,22 +214,58 @@ 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)) + if (!sbgp_as_id(fn, as, &new_asz, aor->u.id)) goto out; break; case ASIdOrRange_range: - if (!sbgp_as_range(p->fn, p->res->as, &p->res->asz, - aor->u.range)) + if (!sbgp_as_range(fn, as, &new_asz, aor->u.range)) goto out; break; default: warnx("%s: RFC 3779 section 3.2.3.5: ASIdOrRange: " - "unknown type %d", p->fn, aor->type); + "unknown type %d", fn, aor->type); goto out; } } + *out_as = as; + *out_asz = new_asz; + + return 1; + + out: + free(as); + + return 0; +} + +/* + * 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 +352,19 @@ 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 **out_ips, size_t *out_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; + const IPAddressFamily *af; + const IPAddressOrRanges *aors; + const IPAddressOrRange *aor; + enum afi afi; + struct cert_ip *ips = NULL; + size_t ipsz, new_ipsz = 0; + int i, j; - 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; - } + assert(*out_ips == NULL && *out_ipsz == 0); for (i = 0; i < sk_IPAddressFamily_num(addrblk); i++) { af = sk_IPAddressFamily_value(addrblk, i); @@ -365,38 +372,37 @@ sbgp_ipaddrblk(struct parse *p, X509_EXT switch (af->ipAddressChoice->type) { case IPAddressChoice_inherit: aors = NULL; - ipsz = p->res->ipsz + 1; + ipsz = new_ipsz + 1; break; case IPAddressChoice_addressesOrRanges: aors = af->ipAddressChoice->u.addressesOrRanges; - ipsz = p->res->ipsz + sk_IPAddressOrRange_num(aors); + ipsz = new_ipsz + sk_IPAddressOrRange_num(aors); break; default: warnx("%s: RFC 3779: IPAddressChoice: unknown type %d", - p->fn, af->ipAddressChoice->type); + fn, af->ipAddressChoice->type); goto out; } - if (ipsz == p->res->ipsz) { + if (ipsz == new_ipsz) { warnx("%s: RFC 6487 section 4.8.10: " - "empty ipAddressesOrRanges", p->fn); + "empty ipAddressesOrRanges", fn); goto out; } if (ipsz >= MAX_IP_SIZE) goto out; - p->res->ips = recallocarray(p->res->ips, p->res->ipsz, ipsz, + ips = recallocarray(ips, new_ipsz, ipsz, sizeof(struct cert_ip)); - if (p->res->ips == NULL) + if (ips == NULL) err(1, NULL); - if (!ip_addr_afi_parse(p->fn, af->addressFamily, &afi)) { - warnx("%s: RFC 3779: invalid AFI", p->fn); + if (!ip_addr_afi_parse(fn, af->addressFamily, &afi)) { + warnx("%s: RFC 3779: invalid AFI", fn); goto out; } if (aors == NULL) { - if (!sbgp_addr_inherit(p->fn, p->res->ips, - &p->res->ipsz, afi)) + if (!sbgp_addr_inherit(fn, ips, &new_ipsz, afi)) goto out; continue; } @@ -405,22 +411,59 @@ 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)) + if (!sbgp_addr(fn, ips, &new_ipsz, afi, + aor->u.addressPrefix)) goto out; break; case IPAddressOrRange_addressRange: - if (!sbgp_addr_range(p->fn, p->res->ips, - &p->res->ipsz, afi, aor->u.addressRange)) + if (!sbgp_addr_range(fn, ips, &new_ipsz, afi, + aor->u.addressRange)) goto out; break; default: warnx("%s: RFC 3779: IPAddressOrRange: " - "unknown type %d", p->fn, aor->type); + "unknown type %d", fn, aor->type); goto out; } } } + + *out_ips = ips; + *out_ipsz = new_ipsz; + + return 1; + + out: + free(ips); + + return 0; +} + +/* + * 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);