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