On Tue, May 10, 2022 at 01:27:17PM +0200, Theo Buehler wrote:
> This is a straightforward conversion to letting libcrypto's RFC 3779
> code parse a cert's IPAddrBlocks. The magic happens in X509V3_EXT_d2i()
> in sbgp_ipaddrblk(). After that, we simply have to walk the returned
> structure. The fact that it parsed only means that it is well-formed as
> far as the templating goes. Notably, at this point we will not yet have
> called X509v3_addr_is_canonical(), so no additional validation of the
> extension has happened beforehand.
>
> This does not use any of the X509v3_addr_* API apart from the types.
>
> There's more cleanup that can be done, e.g. the reaching through and
> copying of struct ip is a bit weird. This also fixes at least one leak
> in sbgp_addr_range().
Lovley. The new code is so much shorter. Also the necessary sacrifice to
understand the code went from a rhino to a chicken. Big improvement.
OK claudio@
> Index: cert.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/rpki-client/cert.c,v
> retrieving revision 1.71
> diff -u -p -r1.71 cert.c
> --- cert.c 21 Apr 2022 12:59:03 -0000 1.71
> +++ cert.c 10 May 2022 10:29:57 -0000
> @@ -423,49 +423,18 @@ out:
> */
> static int
> sbgp_addr_range(struct parse *p, struct cert_ip *ip,
> - const unsigned char *d, size_t dsz)
> + const IPAddressRange *range)
> {
> - ASN1_SEQUENCE_ANY *seq;
> - const ASN1_TYPE *t;
> - int rc = 0;
> -
> - if ((seq = d2i_ASN1_SEQUENCE_ANY(NULL, &d, dsz)) == NULL) {
> - cryptowarnx("%s: RFC 3779 section 2.2.3.9: IPAddressRange: "
> - "failed ASN.1 sequence parse", p->fn);
> - goto out;
> - }
> - if (sk_ASN1_TYPE_num(seq) != 2) {
> - warnx("%s: RFC 3779 section 2.2.3.9: IPAddressRange: "
> - "want 2 elements, have %d", p->fn, sk_ASN1_TYPE_num(seq));
> - goto out;
> - }
> -
> - t = sk_ASN1_TYPE_value(seq, 0);
> - if (t->type != V_ASN1_BIT_STRING) {
> - warnx("%s: RFC 3779 section 2.2.3.9: IPAddressRange: "
> - "want ASN.1 bit string, have %s (NID %d)",
> - p->fn, ASN1_tag2str(t->type), t->type);
> - goto out;
> - }
> - if (!ip_addr_parse(t->value.bit_string,
> - ip->afi, p->fn, &ip->range.min)) {
> + if (!ip_addr_parse(range->min, ip->afi, p->fn, &ip->range.min)) {
> warnx("%s: RFC 3779 section 2.2.3.9: IPAddressRange: "
> "invalid IP address", p->fn);
> - goto out;
> + return 0;
> }
>
> - t = sk_ASN1_TYPE_value(seq, 1);
> - if (t->type != V_ASN1_BIT_STRING) {
> - warnx("%s: RFC 3779 section 2.2.3.9: IPAddressRange: "
> - "want ASN.1 bit string, have %s (NID %d)",
> - p->fn, ASN1_tag2str(t->type), t->type);
> - goto out;
> - }
> - if (!ip_addr_parse(t->value.bit_string,
> - ip->afi, p->fn, &ip->range.max)) {
> + if (!ip_addr_parse(range->max, ip->afi, p->fn, &ip->range.max)) {
> warnx("%s: RFC 3779 section 2.2.3.9: IPAddressRange: "
> "invalid IP address", p->fn);
> - goto out;
> + return 0;
> }
>
> if (!ip_cert_compose_ranges(ip)) {
> @@ -474,10 +443,7 @@ sbgp_addr_range(struct parse *p, struct
> return 0;
> }
>
> - rc = append_ip(p, ip);
> -out:
> - sk_ASN1_TYPE_pop_free(seq, ASN1_TYPE_free);
> - return rc;
> + return append_ip(p, ip);
> }
>
> /*
> @@ -488,48 +454,35 @@ out:
> */
> static int
> sbgp_addr_or_range(struct parse *p, struct cert_ip *ip,
> - const unsigned char *d, size_t dsz)
> + const IPAddressOrRanges *aors)
> {
> struct cert_ip nip;
> - ASN1_SEQUENCE_ANY *seq;
> - const ASN1_TYPE *t;
> + const IPAddressOrRange *aor;
> int i, rc = 0;
>
> - if ((seq = d2i_ASN1_SEQUENCE_ANY(NULL, &d, dsz)) == NULL) {
> - cryptowarnx("%s: RFC 3779 section 2.2.3.7: IPAddressOrRange: "
> - "failed ASN.1 sequence parse", p->fn);
> - goto out;
> - }
> -
> - /* Either RFC 3779 2.2.3.8 or 2.2.3.9. */
> -
> - for (i = 0; i < sk_ASN1_TYPE_num(seq); i++) {
> + for (i = 0; i < sk_IPAddressOrRange_num(aors); i++) {
> nip = *ip;
> - t = sk_ASN1_TYPE_value(seq, i);
> - switch (t->type) {
> - case V_ASN1_BIT_STRING:
> + aor = sk_IPAddressOrRange_value(aors, i);
> + switch (aor->type) {
> + case IPAddressOrRange_addressPrefix:
> nip.type = CERT_IP_ADDR;
> - if (!sbgp_addr(p, &nip, t->value.bit_string))
> + if (!sbgp_addr(p, &nip, aor->u.addressPrefix))
> goto out;
> break;
> - case V_ASN1_SEQUENCE:
> + case IPAddressOrRange_addressRange:
> nip.type = CERT_IP_RANGE;
> - d = t->value.asn1_string->data;
> - dsz = t->value.asn1_string->length;
> - if (!sbgp_addr_range(p, &nip, d, dsz))
> + if (!sbgp_addr_range(p, &nip, aor->u.addressRange))
> goto out;
> break;
> default:
> warnx("%s: RFC 3779 section 2.2.3.7: IPAddressOrRange: "
> - "want ASN.1 sequence or bit string, have %s (NID
> %d)",
> - p->fn, ASN1_tag2str(t->type), t->type);
> + "unknown type %d", p->fn, aor->type);
> goto out;
> }
> }
>
> rc = 1;
> -out:
> - sk_ASN1_TYPE_pop_free(seq, ASN1_TYPE_free);
> + out:
> return rc;
> }
>
> @@ -543,68 +496,39 @@ out:
> * Returns zero no failure, non-zero on success.
> */
> static int
> -sbgp_ipaddrfam(struct parse *p, const unsigned char *d, size_t dsz)
> +sbgp_ipaddrfam(struct parse *p, const IPAddressFamily *af)
> {
> struct cert_ip ip;
> - ASN1_SEQUENCE_ANY *seq;
> - const ASN1_TYPE *t;
> + const IPAddressChoice *choice;
> int rc = 0;
>
> memset(&ip, 0, sizeof(struct cert_ip));
>
> - if ((seq = d2i_ASN1_SEQUENCE_ANY(NULL, &d, dsz)) == NULL) {
> - cryptowarnx("%s: RFC 3779 section 2.2.3.2: IPAddressFamily: "
> - "failed ASN.1 sequence parse", p->fn);
> - goto out;
> - }
> - if (sk_ASN1_TYPE_num(seq) != 2) {
> - warnx("%s: RFC 3779 section 2.2.3.2: IPAddressFamily: "
> - "want 2 elements, have %d",
> - p->fn, sk_ASN1_TYPE_num(seq));
> - goto out;
> - }
> -
> - /* Get address family, RFC 3779, 2.2.3.3. */
> -
> - t = sk_ASN1_TYPE_value(seq, 0);
> - if (t->type != V_ASN1_OCTET_STRING) {
> - warnx("%s: RFC 3779 section 2.2.3.2: addressFamily: "
> - "want ASN.1 octet string, have %s (NID %d)",
> - p->fn, ASN1_tag2str(t->type), t->type);
> - goto out;
> - }
> -
> - if (!ip_addr_afi_parse(p->fn, t->value.octet_string, &ip.afi)) {
> + if (!ip_addr_afi_parse(p->fn, af->addressFamily, &ip.afi)) {
> warnx("%s: RFC 3779 section 2.2.3.2: addressFamily: "
> "invalid AFI", p->fn);
> goto out;
> }
>
> - /* Either sequence or null (inherit), RFC 3779 sec. 2.2.3.4. */
> -
> - t = sk_ASN1_TYPE_value(seq, 1);
> - switch (t->type) {
> - case V_ASN1_SEQUENCE:
> - d = t->value.asn1_string->data;
> - dsz = t->value.asn1_string->length;
> - if (!sbgp_addr_or_range(p, &ip, d, dsz))
> + choice = af->ipAddressChoice;
> + switch (choice->type) {
> + case IPAddressChoice_addressesOrRanges:
> + if (!sbgp_addr_or_range(p, &ip, choice->u.addressesOrRanges))
> goto out;
> break;
> - case V_ASN1_NULL:
> + case IPAddressChoice_inherit:
> ip.type = CERT_IP_INHERIT;
> if (!append_ip(p, &ip))
> goto out;
> break;
> default:
> warnx("%s: RFC 3779 section 2.2.3.2: IPAddressChoice: "
> - "want ASN.1 sequence or null, have %s (NID %d)",
> - p->fn, ASN1_tag2str(t->type), t->type);
> + "unknown type %d", p->fn, choice->type);
> goto out;
> }
>
> rc = 1;
> -out:
> - sk_ASN1_TYPE_pop_free(seq, ASN1_TYPE_free);
> + out:
> return rc;
> }
>
> @@ -616,12 +540,9 @@ out:
> static int
> sbgp_ipaddrblk(struct parse *p, X509_EXTENSION *ext)
> {
> - int dsz, rc = 0;
> - unsigned char *sv = NULL;
> - const unsigned char *d;
> - ASN1_SEQUENCE_ANY *seq = NULL, *sseq = NULL;
> - const ASN1_TYPE *t = NULL;
> - int i;
> + STACK_OF(IPAddressFamily) *addrblk = NULL;
> + const IPAddressFamily *af;
> + int i, rc = 0;
>
> if (!X509_EXTENSION_get_critical(ext)) {
> cryptowarnx("%s: RFC 6487 section 4.8.10: sbgp-ipAddrBlock: "
> @@ -629,81 +550,22 @@ sbgp_ipaddrblk(struct parse *p, X509_EXT
> goto out;
> }
>
> - if ((dsz = i2d_X509_EXTENSION(ext, &sv)) < 0) {
> + if ((addrblk = X509V3_EXT_d2i(ext)) == NULL) {
> cryptowarnx("%s: RFC 6487 section 4.8.10: sbgp-ipAddrBlock: "
> "failed extension parse", p->fn);
> goto out;
> }
> - d = sv;
> -
> - if ((seq = d2i_ASN1_SEQUENCE_ANY(NULL, &d, dsz)) == NULL) {
> - cryptowarnx("%s: RFC 6487 section 4.8.10: sbgp-ipAddrBlock: "
> - "failed ASN.1 sequence parse", p->fn);
> - goto out;
> - }
> - if (sk_ASN1_TYPE_num(seq) != 3) {
> - warnx("%s: RFC 6487 section 4.8.10: sbgp-ipAddrBlock: "
> - "want 3 elements, have %d",
> - p->fn, sk_ASN1_TYPE_num(seq));
> - goto out;
> - }
> -
> - t = sk_ASN1_TYPE_value(seq, 0);
> - if (t->type != V_ASN1_OBJECT) {
> - warnx("%s: RFC 6487 section 4.8.10: sbgp-ipAddrBlock: "
> - "want ASN.1 object, have %s (NID %d)",
> - p->fn, ASN1_tag2str(t->type), t->type);
> - goto out;
> - }
> -
> - t = sk_ASN1_TYPE_value(seq, 1);
> - if (t->type != V_ASN1_BOOLEAN) {
> - warnx("%s: RFC 6487 section 4.8.10: sbgp-ipAddrBlock: "
> - "want ASN.1 boolean, have %s (NID %d)",
> - p->fn, ASN1_tag2str(t->type), t->type);
> - goto out;
> - }
> -
> - t = sk_ASN1_TYPE_value(seq, 2);
> - if (t->type != V_ASN1_OCTET_STRING) {
> - warnx("%s: RFC 6487 section 4.8.10: sbgp-ipAddrBlock: "
> - "want ASN.1 octet string, have %s (NID %d)",
> - p->fn, ASN1_tag2str(t->type), t->type);
> - goto out;
> - }
> -
> - /* The blocks sequence, RFC 3779 2.2.3.1. */
> -
> - d = t->value.octet_string->data;
> - dsz = t->value.octet_string->length;
> -
> - if ((sseq = d2i_ASN1_SEQUENCE_ANY(NULL, &d, dsz)) == NULL) {
> - cryptowarnx("%s: RFC 3779 section 2.2.3.1: IPAddrBlocks: "
> - "failed ASN.1 sequence parse", p->fn);
> - goto out;
> - }
>
> /* Each sequence element contains RFC 3779 sec. 2.2.3.2. */
> -
> - for (i = 0; i < sk_ASN1_TYPE_num(sseq); i++) {
> - t = sk_ASN1_TYPE_value(sseq, i);
> - if (t->type != V_ASN1_SEQUENCE) {
> - warnx("%s: RFC 3779 section 2.2.3.2: IPAddressFamily: "
> - "want ASN.1 sequence, have %s (NID %d)",
> - p->fn, ASN1_tag2str(t->type), t->type);
> - goto out;
> - }
> - d = t->value.asn1_string->data;
> - dsz = t->value.asn1_string->length;
> - if (!sbgp_ipaddrfam(p, d, dsz))
> + for (i = 0; i < sk_IPAddressFamily_num(addrblk); i++) {
> + af = sk_IPAddressFamily_value(addrblk, i);
> + if (!sbgp_ipaddrfam(p, af))
> goto out;
> }
>
> rc = 1;
> -out:
> - sk_ASN1_TYPE_pop_free(seq, ASN1_TYPE_free);
> - sk_ASN1_TYPE_pop_free(sseq, ASN1_TYPE_free);
> - free(sv);
> + out:
> + sk_IPAddressFamily_pop_free(addrblk, IPAddressFamily_free);
> return rc;
> }
>
>
--
:wq Claudio