On Tue, May 10, 2022 at 08:43:45PM +0200, Theo Buehler wrote:
> The ASIdentifiers code is a bit strangely factored presumably due to
> constraints of the low-level shoveling. I kept the coarse structure
> of the code and left some house keeping for later. The changes in
> sbgp_asrange() and sbgp_asid() should be easy.
>
> The in-tree sbgp_assysnum() is tricky to follow. The main thing to
> note is that the for loop at the end really only inspects asnum (and
> ignores rdi). Since RDI is forbidden in RFC 6487, I added a check
> and error. All the complicated gymnastics can be dropped and what
> remains is a bit stricter and what it does should be rather obvious.
>
> With this diff, ASN1_TYPE and ASN1_frame() uses are gone from cert.c.
Works for me, the result is again already much cleaner.
OK claudio@
> Index: cert.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/rpki-client/cert.c,v
> retrieving revision 1.74
> diff -u -p -r1.74 cert.c
> --- cert.c 10 May 2022 16:43:53 -0000 1.74
> +++ cert.c 10 May 2022 18:13:02 -0000
> @@ -34,13 +34,6 @@
> #include "extern.h"
>
> /*
> - * Type of ASIdentifier (RFC 3779, 3.2.3).
> - */
> -#define ASID_TYPE_ASNUM 0x00
> -#define ASID_TYPE_RDI 0x01
> -#define ASID_TYPE_MAX ASID_TYPE_RDI
> -
> -/*
> * A parsing sequence of a file (which may just be <stdin>).
> */
> struct parse {
> @@ -128,70 +121,36 @@ sbgp_addr(struct parse *p, struct cert_i
> * Returns zero on failure, non-zero on success.
> */
> static int
> -sbgp_asrange(struct parse *p, const unsigned char *d, size_t dsz)
> +sbgp_asrange(struct parse *p, const ASRange *range)
> {
> struct cert_as as;
> - 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 3.2.3.8: ASRange: "
> - "failed ASN.1 sequence parse", p->fn);
> - goto out;
> - }
> - if (sk_ASN1_TYPE_num(seq) != 2) {
> - warnx("%s: RFC 3779 section 3.2.3.8: ASRange: "
> - "want 2 elements, have %d", p->fn,
> - sk_ASN1_TYPE_num(seq));
> - goto out;
> - }
>
> memset(&as, 0, sizeof(struct cert_as));
> as.type = CERT_AS_RANGE;
>
> - t = sk_ASN1_TYPE_value(seq, 0);
> - if (t->type != V_ASN1_INTEGER) {
> - warnx("%s: RFC 3779 section 3.2.3.8: ASRange: "
> - "want ASN.1 integer, have %s (NID %d)",
> - p->fn, ASN1_tag2str(t->type), t->type);
> - goto out;
> - }
> - if (!as_id_parse(t->value.integer, &as.range.min)) {
> + if (!as_id_parse(range->min, &as.range.min)) {
> warnx("%s: RFC 3779 section 3.2.3.8 (via RFC 1930): "
> "malformed AS identifier", p->fn);
> - goto out;
> + return 0;
> }
>
> - t = sk_ASN1_TYPE_value(seq, 1);
> - if (t->type != V_ASN1_INTEGER) {
> - warnx("%s: RFC 3779 section 3.2.3.8: ASRange: "
> - "want ASN.1 integer, have %s (NID %d)",
> - p->fn, ASN1_tag2str(t->type), t->type);
> - goto out;
> - }
> - if (!as_id_parse(t->value.integer, &as.range.max)) {
> + if (!as_id_parse(range->max, &as.range.max)) {
> warnx("%s: RFC 3779 section 3.2.3.8 (via RFC 1930): "
> "malformed AS identifier", p->fn);
> - goto out;
> + return 0;
> }
>
> if (as.range.max == as.range.min) {
> warnx("%s: RFC 3379 section 3.2.3.8: ASRange: "
> "range is singular", p->fn);
> - goto out;
> + return 0;
> } else if (as.range.max < as.range.min) {
> warnx("%s: RFC 3379 section 3.2.3.8: ASRange: "
> "range is out of order", p->fn);
> - goto out;
> + return 0;
> }
>
> - if (!append_as(p, &as))
> - goto out;
> - rc = 1;
> -out:
> - sk_ASN1_TYPE_pop_free(seq, ASN1_TYPE_free);
> - return rc;
> + return append_as(p, &as);
> }
>
> /*
> @@ -224,80 +183,46 @@ sbgp_asid(struct parse *p, const ASN1_IN
> * Returns zero on failure, non-zero on success.
> */
> static int
> -sbgp_asnum(struct parse *p, const unsigned char *d, size_t dsz)
> +sbgp_asnum(struct parse *p, const ASIdentifierChoice *aic)
> {
> struct cert_as as;
> - ASN1_TYPE *t, *tt;
> - ASN1_SEQUENCE_ANY *seq = NULL;
> - int i, rc = 0;
> - const unsigned char *sv = d;
> -
> - /* We can either be a null (inherit) or sequence. */
> -
> - if ((t = d2i_ASN1_TYPE(NULL, &d, dsz)) == NULL) {
> - cryptowarnx("%s: RFC 3779 section 3.2.3.2: ASIdentifierChoice: "
> - "failed ASN.1 type parse", p->fn);
> - goto out;
> - }
> -
> - /*
> - * Section 3779 3.2.3.3 is to inherit with an ASN.1 NULL type,
> - * which is the easy case.
> - */
> + const ASIdOrRanges *aors = NULL;
> + const ASIdOrRange *aor;
> + int i;
>
> - switch (t->type) {
> - case V_ASN1_NULL:
> + switch (aic->type) {
> + case ASIdentifierChoice_inherit:
> memset(&as, 0, sizeof(struct cert_as));
> as.type = CERT_AS_INHERIT;
> - if (!append_as(p, &as))
> - goto out;
> - rc = 1;
> - goto out;
> - case V_ASN1_SEQUENCE:
> + return append_as(p, &as);
> + case ASIdentifierChoice_asIdsOrRanges:
> + aors = aic->u.asIdsOrRanges;
> break;
> default:
> warnx("%s: RFC 3779 section 3.2.3.2: ASIdentifierChoice: "
> - "want ASN.1 sequence or null, have %s (NID %d)",
> - p->fn, ASN1_tag2str(t->type), t->type);
> - goto out;
> - }
> -
> - /* This is RFC 3779 3.2.3.4. */
> -
> - if ((seq = d2i_ASN1_SEQUENCE_ANY(NULL, &sv, dsz)) == NULL) {
> - cryptowarnx("%s: RFC 3779 section 3.2.3.2: ASIdentifierChoice: "
> - "failed ASN.1 sequence parse", p->fn);
> - goto out;
> + "unknown type %d", p->fn, aic->type);
> + return 0;
> }
>
> - /* Accepts RFC 3779 3.2.3.6 or 3.2.3.7 (sequence). */
> -
> - for (i = 0; i < sk_ASN1_TYPE_num(seq); i++) {
> - tt = sk_ASN1_TYPE_value(seq, i);
> - switch (tt->type) {
> - case V_ASN1_INTEGER:
> - if (!sbgp_asid(p, tt->value.integer))
> - goto out;
> + for (i = 0; i < sk_ASIdOrRange_num(aors); i++) {
> + aor = sk_ASIdOrRange_value(aors, i);
> + switch (aor->type) {
> + case ASIdOrRange_id:
> + if (!sbgp_asid(p, aor->u.id))
> + return 0;
> break;
> - case V_ASN1_SEQUENCE:
> - d = tt->value.asn1_string->data;
> - dsz = tt->value.asn1_string->length;
> - if (!sbgp_asrange(p, d, dsz))
> - goto out;
> + case ASIdOrRange_range:
> + if (!sbgp_asrange(p, aor->u.range))
> + return 0;
> break;
> default:
> warnx("%s: RFC 3779 section 3.2.3.5: ASIdOrRange: "
> - "want ASN.1 sequence or integer, have %s (NID %d)",
> - p->fn, ASN1_tag2str(tt->type), tt->type);
> - goto out;
> + "unknown type %d", p->fn, aor->type);
> + return 0;
> }
> }
>
> - rc = 1;
> -out:
> - ASN1_TYPE_free(t);
> - sk_ASN1_TYPE_pop_free(seq, ASN1_TYPE_free);
> - return rc;
> + return 1;
> }
>
> /*
> @@ -308,12 +233,8 @@ out:
> static int
> sbgp_assysnum(struct parse *p, X509_EXTENSION *ext)
> {
> - unsigned char *sv = NULL;
> - const unsigned char *d;
> - ASN1_SEQUENCE_ANY *seq = NULL, *sseq = NULL;
> - const ASN1_TYPE *t;
> - int dsz, rc = 0, i, ptag;
> - long plen;
> + ASIdentifiers *asidentifiers = NULL;
> + int rc = 0;
>
> if (!X509_EXTENSION_get_critical(ext)) {
> cryptowarnx("%s: RFC 6487 section 4.8.11: autonomousSysNum: "
> @@ -321,98 +242,30 @@ sbgp_assysnum(struct parse *p, X509_EXTE
> goto out;
> }
>
> - if ((dsz = i2d_X509_EXTENSION(ext, &sv)) < 0) {
> + if ((asidentifiers = X509V3_EXT_d2i(ext)) == NULL) {
> cryptowarnx("%s: RFC 6487 section 4.8.11: autonomousSysNum: "
> "failed extension parse", p->fn);
> goto out;
> }
>
> - /* Start with RFC 3779, section 3.2 top-level. */
> -
> - d = sv;
> - if ((seq = d2i_ASN1_SEQUENCE_ANY(NULL, &d, dsz)) == NULL) {
> - cryptowarnx("%s: RFC 6487 section 4.8.11: autonomousSysNum: "
> - "failed ASN.1 sequence parse", p->fn);
> - goto out;
> - }
> - if (sk_ASN1_TYPE_num(seq) != 3) {
> - warnx("%s: RFC 6487 section 4.8.11: autonomousSysNum: "
> - "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.11: autonomousSysNum: "
> - "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) {
> + if (asidentifiers->rdi != NULL) {
> warnx("%s: RFC 6487 section 4.8.11: autonomousSysNum: "
> - "want ASN.1 boolean, have %s (NID %d)",
> - p->fn, ASN1_tag2str(t->type), t->type);
> + "should not have RDI values", p->fn);
> goto out;
> }
>
> - t = sk_ASN1_TYPE_value(seq, 2);
> - if (t->type != V_ASN1_OCTET_STRING) {
> + if (asidentifiers->asnum == NULL) {
> warnx("%s: RFC 6487 section 4.8.11: autonomousSysNum: "
> - "want ASN.1 octet string, have %s (NID %d)",
> - p->fn, ASN1_tag2str(t->type), t->type);
> + "no AS number resource set", p->fn);
> goto out;
> }
>
> - /* Within RFC 3779 3.2.3, check 3.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 3.2.3.1: ASIdentifiers: "
> - "failed ASN.1 sequence parse", p->fn);
> + if (!sbgp_asnum(p, asidentifiers->asnum))
> goto out;
> - }
> -
> - /* Scan through for private 3.2.3.2 classes. */
> -
> - for (i = 0; i < sk_ASN1_TYPE_num(sseq); i++) {
> - t = sk_ASN1_TYPE_value(sseq, i);
> - if (t->type != V_ASN1_OTHER) {
> - warnx("%s: RFC 3779 section 3.2.3.1: ASIdentifiers: "
> - "want ASN.1 explicit, have %s (NID %d)", p->fn,
> - ASN1_tag2str(t->type), t->type);
> - goto out;
> - }
> -
> - /* Use the low-level ASN1_frame. */
> -
> - d = t->value.asn1_string->data;
> - dsz = t->value.asn1_string->length;
> - if (!ASN1_frame(p->fn, dsz, &d, &plen, &ptag))
> - goto out;
> -
> - /* Ignore bad AS identifiers and RDI entries. */
> -
> - if (ptag > ASID_TYPE_MAX) {
> - warnx("%s: RFC 3779 section 3.2.3.1: ASIdentifiers: "
> - "unknown explicit tag 0x%02x", p->fn, ptag);
> - goto out;
> - } else if (ptag == ASID_TYPE_RDI)
> - continue;
> -
> - if (!sbgp_asnum(p, d, plen))
> - 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:
> + ASIdentifiers_free(asidentifiers);
> return rc;
> }
>
>
--
:wq Claudio