Hi,

Thank you for the review

On Mon, Feb 15, 2021 at 01:42:57PM +0100, Claudio Jeker wrote:
> Please do not define variables in the middle of functions. 

now fixed

> > +   AUTHORITY_INFO_ACCESS_free(info);
> > +
> > +   return aia;
> > +}
> 
> I really don't like the way x509_get_aia() is different to
> x509_get_ski_ext and x509_get_aki_ext. The way the x509 extensions are
> handled in rpki-client is strange. In x509_get_exts() the code walks over
> all extensions and looks for the NID we're interested in.

Yes, they are different in style. I think x509_get_{ski,aki}_ext() might
be 'the odd ones out': http://man.openbsd.org/X509_EXTENSION_get_data states:

    "Most applications will want to parse or encode and add an
    extension: they should use the extension encode and decode functions
    instead such as X509_add1_ext_i2d(3) and X509_get_ext_d2i(3)."

Which is why I wrote x509_get_aia() to use X509_get_ext_d2i(3).

> x509_get_aia() makes this approach even more strange by actually not using
> the ext but instead do a lookup from the x509 object directly. So why call
> it in the for loop at all. Just do it directly.
> 
> Also the way the code is written in x509_get_exts() implies that x509
> allows the same extension to be added more then once. Is that really true?
> Wouldn't that be an error regarding RFC6487.

https://tools.ietf.org/html/rfc5280#section-4.2.2.1 reads:
    "An authorityInfoAccess extension may include multiple instances of
    the id-ad-caIssuers accessMethod."

Then https://tools.ietf.org/html/rfc6487#section-4.8.7 narrows it down:
    "In this profile, a single reference to the publication point of the
    immediate superior certificate MUST be present"

which is why i put "if (sk_ACCESS_DESCRIPTION_num(info) != 1) {" in
x509_get_aia().

> Anyway I would prefer if x509_get_ski_ext(), x509_get_aki_ext() and
> x509_get_aia() all work the same way.

Perhaps x509_get_ski_ext() and x509_get_aki_ext() can be modified to use
X509_get_ext_d2i(3) too.

> You forgot to add *aia to at the start where *ski = *aki = NULL;

fixed.

> With the style and initialisation issue fixed I think this can go in
> but as mentioned more x509 cleanup needs to follow.

OK?

Index: usr.sbin/rpki-client/cert.c
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/cert.c,v
retrieving revision 1.25
diff -u -p -r1.25 cert.c
--- usr.sbin/rpki-client/cert.c 8 Feb 2021 09:22:53 -0000       1.25
+++ usr.sbin/rpki-client/cert.c 15 Feb 2021 16:54:05 -0000
@@ -1079,6 +1079,11 @@ cert_parse_inner(X509 **xp, const char *
                case NID_crl_distribution_points:
                        /* ignored here, handled later */
                        break;
+               case NID_info_access:
+                       free(p.res->aia);
+                       p.res->aia = x509_get_aia(x, p.fn);
+                       c = (p.res->aia != NULL);
+                       break;
                case NID_authority_key_identifier:
                        free(p.res->aki);
                        p.res->aki = x509_get_aki_ext(ext, p.fn);
Index: usr.sbin/rpki-client/gbr.c
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/gbr.c,v
retrieving revision 1.4
diff -u -p -r1.4 gbr.c
--- usr.sbin/rpki-client/gbr.c  4 Feb 2021 08:58:19 -0000       1.4
+++ usr.sbin/rpki-client/gbr.c  15 Feb 2021 16:54:05 -0000
@@ -62,7 +62,7 @@ gbr_parse(X509 **x509, const char *fn)
                err(1, NULL);
        if ((p.res->vcard = strndup(cms, cmsz)) == NULL)
                err(1, NULL);
-       if (!x509_get_ski_aki(*x509, fn, &p.res->ski, &p.res->aki)) {
+       if (!x509_get_exts(*x509, fn, &p.res->ski, &p.res->aki, &p.res->aia)) {
                gbr_free(p.res);
                X509_free(*x509);
                *x509 = NULL;
Index: usr.sbin/rpki-client/mft.c
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/mft.c,v
retrieving revision 1.25
diff -u -p -r1.25 mft.c
--- usr.sbin/rpki-client/mft.c  4 Feb 2021 08:58:19 -0000       1.25
+++ usr.sbin/rpki-client/mft.c  15 Feb 2021 16:54:05 -0000
@@ -395,7 +395,7 @@ mft_parse(X509 **x509, const char *fn)
                err(1, NULL);
        if ((p.res->file = strdup(fn)) == NULL)
                err(1, NULL);
-       if (!x509_get_ski_aki(*x509, fn, &p.res->ski, &p.res->aki))
+       if (!x509_get_exts(*x509, fn, &p.res->ski, &p.res->aki, &p.res->aia))
                goto out;
 
        /*
Index: usr.sbin/rpki-client/roa.c
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/roa.c,v
retrieving revision 1.13
diff -u -p -r1.13 roa.c
--- usr.sbin/rpki-client/roa.c  4 Feb 2021 08:58:19 -0000       1.13
+++ usr.sbin/rpki-client/roa.c  15 Feb 2021 16:54:05 -0000
@@ -349,7 +349,7 @@ roa_parse(X509 **x509, const char *fn)
 
        if ((p.res = calloc(1, sizeof(struct roa))) == NULL)
                err(1, NULL);
-       if (!x509_get_ski_aki(*x509, fn, &p.res->ski, &p.res->aki))
+       if (!x509_get_exts(*x509, fn, &p.res->ski, &p.res->aki, &p.res->aia))
                goto out;
        if (!roa_parse_econtent(cms, cmsz, &p))
                goto out;
Index: usr.sbin/rpki-client/x509.c
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/x509.c,v
retrieving revision 1.14
diff -u -p -r1.14 x509.c
--- usr.sbin/rpki-client/x509.c 12 Sep 2020 15:46:48 -0000      1.14
+++ usr.sbin/rpki-client/x509.c 15 Feb 2021 16:54:05 -0000
@@ -169,18 +169,64 @@ out:
 }
 
 /*
- * Wraps around x509_get_ski_ext and x509_get_aki_ext.
+ * Parse the Authority Information Access (AIA) extension
+ * See RFC 6487, section 4.8.7 for details.
+ * Returns NULL on failure, on success returns the AIA URI
+ * (which has to be freed after use).
+ */
+char *
+x509_get_aia(X509 *x, const char *fn)
+{
+       ACCESS_DESCRIPTION              *ad;
+       AUTHORITY_INFO_ACCESS           *info;
+       char                            *aia = NULL;
+
+       info = X509_get_ext_d2i(x, NID_info_access, NULL, NULL);
+       if (!info) {
+               warnx("%s: RFC 6487 section 4.8.7: AIA: extension missing", fn);
+               return NULL;
+       }
+       if (sk_ACCESS_DESCRIPTION_num(info) != 1) {
+               warnx("%s: RFC 6487 section 4.8.7: AIA: "
+                   "want 1 element, have %d", fn,
+                   sk_ACCESS_DESCRIPTION_num(info));
+               return NULL;
+       }
+
+       ad = sk_ACCESS_DESCRIPTION_value(info, 0);
+       if (OBJ_obj2nid(ad->method) != NID_ad_ca_issuers) {
+               warnx("%s: RFC 6487 section 4.8.7: AIA: "
+                   "expected caIssuers, have %d", fn, OBJ_obj2nid(ad->method));
+               return NULL;
+       }
+       if (ad->location->type != GEN_URI) {
+               warnx("%s: RFC 6487 section 4.8.7: AIA: "
+                   "want GEN_URI type, have %d", fn, ad->location->type);
+               return NULL;
+       }
+
+       aia = strndup(
+           ASN1_STRING_get0_data(ad->location->d.uniformResourceIdentifier),
+           ASN1_STRING_length(ad->location->d.uniformResourceIdentifier));
+
+       AUTHORITY_INFO_ACCESS_free(info);
+
+       return aia;
+}
+
+/*
+ * Wraps around x509_get_ski_ext, x509_get_aki_ext, and x509_get_aia.
  * Returns zero on failure (out pointers are NULL) or non-zero on
  * success (out pointers must be freed).
  */
 int
-x509_get_ski_aki(X509 *x, const char *fn, char **ski, char **aki)
+x509_get_exts(X509 *x, const char *fn, char **ski, char **aki, char **aia)
 {
        X509_EXTENSION          *ext = NULL;
        const ASN1_OBJECT       *obj;
        int                      extsz, i;
 
-       *ski = *aki = NULL;
+       *ski = *aki = *aia = NULL;
 
        if ((extsz = X509_get_ext_count(x)) < 0)
                cryptoerrx("X509_get_ext_count");
@@ -199,21 +245,38 @@ x509_get_ski_aki(X509 *x, const char *fn
                        free(*aki);
                        *aki = x509_get_aki_ext(ext, fn);
                        break;
+               case NID_info_access:
+                       free(*aia);
+                       *aia = x509_get_aia(x, fn);
+                       break;
                }
        }
 
+       if (*aia == NULL) {
+               cryptowarnx("%s: RFC 6487 section 4.8.7: AIA: "
+                   "missing AIA X509 extension", fn);
+               free(*ski);
+               free(*aki);
+               *ski = NULL;
+               *aki = NULL;
+               return 0;
+       }
        if (*aki == NULL) {
                cryptowarnx("%s: RFC 6487 section 4.8.3: AKI: "
                    "missing AKI X509 extension", fn);
                free(*ski);
+               free(*aia);
                *ski = NULL;
+               *aia = NULL;
                return 0;
        }
        if (*ski == NULL) {
-               cryptowarnx("%s: RFC 6487 section 4.8.2: AKI: "
+               cryptowarnx("%s: RFC 6487 section 4.8.2: SKI: "
                    "missing SKI X509 extension", fn);
                free(*aki);
+               free(*aia);
                *aki = NULL;
+               *aia = NULL;
                return 0;
        }
 
Index: usr.sbin/rpki-client/extern.h
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/extern.h,v
retrieving revision 1.42
diff -u -p -r1.42 extern.h
--- usr.sbin/rpki-client/extern.h       8 Feb 2021 09:22:53 -0000       1.42
+++ usr.sbin/rpki-client/extern.h       15 Feb 2021 16:54:05 -0000
@@ -116,6 +116,7 @@ struct cert {
        char            *mft; /* manifest (rsync:// uri) */
        char            *notify; /* RRDP notify (https:// uri) */
        char            *crl; /* CRL location (rsync:// or NULL) */
+       char            *aia; /* AIA (or NULL, for trust anchor) */
        char            *aki; /* AKI (or NULL, for trust anchor) */
        char            *ski; /* SKI */
        int              valid; /* validated resources */
@@ -157,6 +158,7 @@ struct mft {
        int              stale; /* if a stale manifest */
        char            *ski; /* SKI */
        char            *aki; /* AKI */
+       char            *aia; /* AIA */
 };
 
 /*
@@ -183,6 +185,7 @@ struct roa {
        int              valid; /* validated resources */
        char            *ski; /* SKI */
        char            *aki; /* AKI */
+       char            *aia; /* AIA */
        char            *tal; /* basename of TAL for this cert */
 };
 
@@ -193,6 +196,7 @@ struct gbr {
        char            *vcard;
        char            *ski; /* SKI */
        char            *aki; /* AKI */
+       char            *aia; /* AIA */
 };
 
 /*
@@ -248,7 +252,7 @@ struct auth *auth_find(struct auth_tree 
 
 /*
  * Resource types specified by the RPKI profiles.
- * There are others (e.g., gbr) that we don't consider.
+ * There might be others we don't consider.
  */
 enum rtype {
        RTYPE_EOF = 0,
@@ -418,9 +422,10 @@ void                io_str_read(int, char **);
 
 /* X509 helpers. */
 
+char           *x509_get_aia(X509 *, const char *);
 char           *x509_get_aki_ext(X509_EXTENSION *, const char *);
 char           *x509_get_ski_ext(X509_EXTENSION *, const char *);
-int             x509_get_ski_aki(X509 *, const char *, char **, char **);
+int             x509_get_exts(X509 *, const char *, char **, char **, char **);
 char           *x509_get_crl(X509 *, const char *);
 char           *x509_crl_get_aki(X509_CRL *);
 
Index: regress/usr.sbin/rpki-client/test-cert.c
===================================================================
RCS file: /cvs/src/regress/usr.sbin/rpki-client/test-cert.c,v
retrieving revision 1.8
diff -u -p -r1.8 test-cert.c
--- regress/usr.sbin/rpki-client/test-cert.c    8 Feb 2021 09:28:58 -0000       
1.8
+++ regress/usr.sbin/rpki-client/test-cert.c    15 Feb 2021 16:54:05 -0000
@@ -52,6 +52,8 @@ cert_print(const struct cert *p)
        printf("Subject key identifier: %s\n", p->ski);
        if (p->aki != NULL)
                printf("Authority key identifier: %s\n", p->aki);
+       if (p->aia != NULL)
+               printf("Authority info access: %s\n", p->aia);
 
        for (i = 0; i < p->asz; i++)
                switch (p->as[i].type) {
Index: regress/usr.sbin/rpki-client/test-gbr.c
===================================================================
RCS file: /cvs/src/regress/usr.sbin/rpki-client/test-gbr.c,v
retrieving revision 1.1
diff -u -p -r1.1 test-gbr.c
--- regress/usr.sbin/rpki-client/test-gbr.c     9 Dec 2020 11:30:44 -0000       
1.1
+++ regress/usr.sbin/rpki-client/test-gbr.c     15 Feb 2021 16:54:05 -0000
@@ -42,6 +42,7 @@ gbr_print(const struct gbr *p)
 
        printf("Subject key identifier: %s\n", p->ski);
        printf("Authority key identifier: %s\n", p->aki);
+       printf("Authority info access: %s\n", p->aia);
        printf("vcard:\n%s", p->vcard);
 }
 
Index: regress/usr.sbin/rpki-client/test-mft.c
===================================================================
RCS file: /cvs/src/regress/usr.sbin/rpki-client/test-mft.c,v
retrieving revision 1.10
diff -u -p -r1.10 test-mft.c
--- regress/usr.sbin/rpki-client/test-mft.c     9 Nov 2020 16:13:02 -0000       
1.10
+++ regress/usr.sbin/rpki-client/test-mft.c     15 Feb 2021 16:54:05 -0000
@@ -54,6 +54,7 @@ mft_print(const struct mft *p)
 
        printf("Subject key identifier: %s\n", p->ski);
        printf("Authority key identifier: %s\n", p->aki);
+       printf("Authority info access: %s\n", p->aia);
        for (i = 0; i < p->filesz; i++) {
                b64_ntop(p->files[i].hash, sizeof(p->files[i].hash),
                    hash, sizeof(hash));
Index: regress/usr.sbin/rpki-client/test-roa.c
===================================================================
RCS file: /cvs/src/regress/usr.sbin/rpki-client/test-roa.c,v
retrieving revision 1.8
diff -u -p -r1.8 test-roa.c
--- regress/usr.sbin/rpki-client/test-roa.c     29 Jan 2021 10:15:42 -0000      
1.8
+++ regress/usr.sbin/rpki-client/test-roa.c     15 Feb 2021 16:54:05 -0000
@@ -42,6 +42,7 @@ roa_print(const struct roa *p)
 
        printf("Subject key identifier: %s\n", p->ski);
        printf("Authority key identifier: %s\n", p->aki);
+       printf("Authority info access: %s\n", p->aia);
        printf("asID: %" PRIu32 "\n", p->asid);
        for (i = 0; i < p->ipsz; i++) {
                ip_addr_print(&p->ips[i].addr,
Index: regress/usr.sbin/rpki-client/Makefile.inc
===================================================================
RCS file: /cvs/src/regress/usr.sbin/rpki-client/Makefile.inc,v
retrieving revision 1.6
diff -u -p -r1.6 Makefile.inc
--- regress/usr.sbin/rpki-client/Makefile.inc   3 Feb 2021 10:45:12 -0000       
1.6
+++ regress/usr.sbin/rpki-client/Makefile.inc   15 Feb 2021 16:54:05 -0000
@@ -4,9 +4,9 @@
 
 PROGS += test-ip
 PROGS += test-cert
+PROGS += test-gbr
 PROGS += test-mft
 PROGS += test-roa
-PROGS += test-gbr
 PROGS += test-tal
 
 .for p in ${PROGS}

Reply via email to