cert_parse_inner() now only uses the ta flag to change behaviour of
loading the various x509 extensions (AKI, SKI, AIA und CRL DP).

This diff changes these functions to work always. Make AKI, AIA and CRL DP
optional and have the code calling those functions check if they must have
the extension. I modelled the functions after x509_get_expire() so they
return 0 on failure and 1 on success.

Adjust the code to work with these new functions. Most checks for the
optional attributes are already present.
-- 
:wq Claudio

Index: cert.c
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/cert.c,v
retrieving revision 1.58
diff -u -p -r1.58 cert.c
--- cert.c      1 Apr 2022 13:27:38 -0000       1.58
+++ cert.c      1 Apr 2022 14:46:25 -0000
@@ -1058,7 +1058,7 @@ certificate_policies(struct parse *p, X5
  * is also dereferenced.
  */
 static struct cert *
-cert_parse_inner(const char *fn, const unsigned char *der, size_t len, int ta)
+cert_parse_inner(const char *fn, const unsigned char *der, size_t len)
 {
        int              rc = 0, extsz, c;
        int              sia_present = 0;
@@ -1132,12 +1132,14 @@ cert_parse_inner(const char *fn, const u
                        goto out;
        }
 
-       p.res->aki = x509_get_aki(x, ta, p.fn);
-       p.res->ski = x509_get_ski(x, p.fn);
-       if (!ta) {
-               p.res->aia = x509_get_aia(x, p.fn);
-               p.res->crl = x509_get_crl(x, p.fn);
-       }
+       if (!x509_get_aki(x, p.fn, &p.res->aki))
+               goto out;
+       if (!x509_get_ski(x, p.fn, &p.res->ski))
+               goto out;
+       if (!x509_get_aia(x, p.fn, &p.res->aia))
+               goto out;
+       if (!x509_get_crl(x, p.fn, &p.res->crl))
+               goto out;
        if (!x509_get_expire(x, p.fn, &p.res->expires))
                goto out;
        p.res->purpose = x509_get_purpose(x, p.fn);
@@ -1198,7 +1200,7 @@ cert_parse(const char *fn, const unsigne
 {
        struct cert     *p;
 
-       if ((p = cert_parse_inner(fn, der, len, 0)) == NULL)
+       if ((p = cert_parse_inner(fn, der, len)) == NULL)
                return NULL;
 
        if (p->aki == NULL) {
@@ -1212,8 +1214,12 @@ cert_parse(const char *fn, const unsigne
                goto badcert;
        }
        if (p->aia == NULL) {
-               warnx("%s: RFC 6487 section 8.4.7: "
-                   "non-trust anchor missing AIA", fn);
+               warnx("%s: RFC 6487 section 8.4.7: AIA: extension missing", fn);
+               goto badcert;
+       }
+       if (p->crl == NULL) {
+               warnx("%s: RFC 6487 section 4.8.6: CRL: "
+                   "no CRL distribution point extension", fn);
                goto badcert;
        }
        return p;
@@ -1231,7 +1237,7 @@ ta_parse(const char *fn, const unsigned 
        EVP_PKEY        *pk = NULL, *opk = NULL;
        struct cert     *p;
 
-       if ((p = cert_parse_inner(fn, der, len, 1)) == NULL)
+       if ((p = cert_parse_inner(fn, der, len)) == NULL)
                return NULL;
 
        /* first check pubkey against the one from the TAL */
Index: extern.h
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/extern.h,v
retrieving revision 1.122
diff -u -p -r1.122 extern.h
--- extern.h    31 Mar 2022 12:00:00 -0000      1.122
+++ extern.h    1 Apr 2022 13:46:32 -0000
@@ -578,11 +578,11 @@ struct ibuf       *io_buf_recvfd(int, struct i
 /* X509 helpers. */
 
 void            x509_init_oid(void);
-char           *x509_get_aia(X509 *, const char *);
-char           *x509_get_aki(X509 *, int, const char *);
-char           *x509_get_ski(X509 *, const char *);
+int             x509_get_aia(X509 *, const char *, char **);
+int             x509_get_aki(X509 *, const char *, char **);
+int             x509_get_ski(X509 *, const char *, char **);
 int             x509_get_expire(X509 *, const char *, time_t *);
-char           *x509_get_crl(X509 *, const char *);
+int             x509_get_crl(X509 *, const char *, char **);
 char           *x509_crl_get_aki(X509_CRL *, const char *);
 char           *x509_get_pubkey(X509 *, const char *);
 enum cert_purpose       x509_get_purpose(X509 *, const char *);
Index: gbr.c
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/gbr.c,v
retrieving revision 1.14
diff -u -p -r1.14 gbr.c
--- gbr.c       18 Jan 2022 16:24:55 -0000      1.14
+++ gbr.c       1 Apr 2022 14:53:47 -0000
@@ -63,19 +63,24 @@ gbr_parse(X509 **x509, const char *fn, c
                err(1, NULL);
        free(cms);
 
-       p.res->aia = x509_get_aia(*x509, fn);
-       p.res->aki = x509_get_aki(*x509, 0, fn);
-       p.res->ski = x509_get_ski(*x509, fn);
+       if (!x509_get_aia(*x509, fn, &p.res->aia))
+               goto out;
+       if (!x509_get_aki(*x509, fn, &p.res->aki))
+               goto out;
+       if (!x509_get_ski(*x509, fn, &p.res->ski))
+               goto out;
        if (p.res->aia == NULL || p.res->aki == NULL || p.res->ski == NULL) {
                warnx("%s: RFC 6487 section 4.8: "
                    "missing AIA, AKI or SKI X509 extension", fn);
-               gbr_free(p.res);
-               X509_free(*x509);
-               *x509 = NULL;
-               return NULL;
+               goto out;
        }
-
        return p.res;
+
+out:
+       gbr_free(p.res);
+       X509_free(*x509);
+       *x509 = NULL;
+       return NULL;
 }
 
 /*
Index: mft.c
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/mft.c,v
retrieving revision 1.54
diff -u -p -r1.54 mft.c
--- mft.c       31 Mar 2022 12:00:00 -0000      1.54
+++ mft.c       1 Apr 2022 13:52:47 -0000
@@ -444,9 +444,12 @@ mft_parse(X509 **x509, const char *fn, c
        if ((p.res = calloc(1, sizeof(struct mft))) == NULL)
                err(1, NULL);
 
-       p.res->aia = x509_get_aia(*x509, fn);
-       p.res->aki = x509_get_aki(*x509, 0, fn);
-       p.res->ski = x509_get_ski(*x509, fn);
+       if (!x509_get_aia(*x509, fn, &p.res->aia))
+               goto out;
+       if (!x509_get_aki(*x509, fn, &p.res->aki))
+               goto out;
+       if (!x509_get_ski(*x509, fn, &p.res->ski))
+               goto out;
        if (p.res->aia == NULL || p.res->aki == NULL || p.res->ski == NULL) {
                warnx("%s: RFC 6487 section 4.8: "
                    "missing AIA, AKI or SKI X509 extension", fn);
Index: parser.c
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/parser.c,v
retrieving revision 1.64
diff -u -p -r1.64 parser.c
--- parser.c    10 Feb 2022 15:33:47 -0000      1.64
+++ parser.c    1 Apr 2022 14:17:05 -0000
@@ -360,7 +360,11 @@ proc_parser_mft_pre(char *file, const un
 
        a = valid_ski_aki(file, &auths, mft->ski, mft->aki);
        /* load CRL by hand, since it is referenced by the MFT itself */
-       c = x509_get_crl(x509, file);
+       if (!x509_get_crl(x509, file, &c) || c == NULL) {
+               mft_free(mft);
+               X509_free(x509);
+               return NULL;
+       }
        crlfile = strrchr(c, '/');
        if (crlfile != NULL)
                crlfile++;
@@ -1078,7 +1082,7 @@ proc_parser_file(char *file, unsigned ch
                struct crl *c;
                char *crl_uri;
 
-               crl_uri = x509_get_crl(x509, file);
+               x509_get_crl(x509, file, &crl_uri);
                parse_load_crl(crl_uri);
                free(crl_uri);
                if (auth_find(&auths, aki) == NULL)
Index: roa.c
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/roa.c,v
retrieving revision 1.38
diff -u -p -r1.38 roa.c
--- roa.c       10 Feb 2022 15:33:47 -0000      1.38
+++ roa.c       1 Apr 2022 14:00:48 -0000
@@ -351,9 +351,12 @@ roa_parse(X509 **x509, const char *fn, c
        if ((p.res = calloc(1, sizeof(struct roa))) == NULL)
                err(1, NULL);
 
-       p.res->aia = x509_get_aia(*x509, fn);
-       p.res->aki = x509_get_aki(*x509, 0, fn);
-       p.res->ski = x509_get_ski(*x509, fn);
+       if (!x509_get_aia(*x509, fn, &p.res->aia))
+               goto out;
+       if (!x509_get_aki(*x509, fn, &p.res->aki))
+               goto out;
+       if (!x509_get_ski(*x509, fn, &p.res->ski))
+               goto out;
        if (p.res->aia == NULL || p.res->aki == NULL || p.res->ski == NULL) {
                warnx("%s: RFC 6487 section 4.8: "
                    "missing AIA, AKI or SKI X509 extension", fn);
Index: x509.c
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/x509.c,v
retrieving revision 1.37
diff -u -p -r1.37 x509.c
--- x509.c      25 Mar 2022 08:19:04 -0000      1.37
+++ x509.c      1 Apr 2022 14:06:23 -0000
@@ -83,22 +83,18 @@ x509_init_oid(void)
  * Returns the AKI or NULL if it could not be parsed.
  * The AKI is formatted as a hex string.
  */
-char *
-x509_get_aki(X509 *x, int ta, const char *fn)
+int
+x509_get_aki(X509 *x, const char *fn, char **aki)
 {
        const unsigned char     *d;
        AUTHORITY_KEYID         *akid;
        ASN1_OCTET_STRING       *os;
-       int                      dsz, crit;
-       char                    *res = NULL;
+       int                      dsz, crit, rc = 0;
 
+       *aki = NULL;
        akid = X509_get_ext_d2i(x, NID_authority_key_identifier, &crit, NULL);
-       if (akid == NULL) {
-               if (!ta)
-                       warnx("%s: RFC 6487 section 4.8.3: AKI: "
-                           "extension missing", fn);
-               return NULL;
-       }
+       if (akid == NULL)
+               return 1;
        if (crit != 0) {
                warnx("%s: RFC 6487 section 4.8.3: "
                    "AKI: extension not non-critical", fn);
@@ -128,11 +124,11 @@ x509_get_aki(X509 *x, int ta, const char
                goto out;
        }
 
-       res = hex_encode(d, dsz);
-
+       *aki = hex_encode(d, dsz);
+       rc = 1;
 out:
        AUTHORITY_KEYID_free(akid);
-       return res;
+       return rc;
 }
 
 /*
@@ -140,18 +136,18 @@ out:
  * Returns the SKI or NULL if it could not be parsed.
  * The SKI is formatted as a hex string.
  */
-char *
-x509_get_ski(X509 *x, const char *fn)
+int
+x509_get_ski(X509 *x, const char *fn, char **ski)
 {
        const unsigned char     *d;
        ASN1_OCTET_STRING       *os;
-       int                      dsz, crit;
-       char                    *res = NULL;
+       int                      dsz, crit, rc = 0;
 
+       *ski = NULL;
        os = X509_get_ext_d2i(x, NID_subject_key_identifier, &crit, NULL);
        if (os == NULL) {
                warnx("%s: RFC 6487 section 4.8.2: SKI: extension missing", fn);
-               return NULL;
+               goto out;
        }
        if (crit != 0) {
                warnx("%s: RFC 6487 section 4.8.2: "
@@ -169,10 +165,11 @@ x509_get_ski(X509 *x, const char *fn)
                goto out;
        }
 
-       res = hex_encode(d, dsz);
+       *ski = hex_encode(d, dsz);
+       rc = 1;
 out:
        ASN1_OCTET_STRING_free(os);
-       return res;
+       return rc;
 }
 
 /*
@@ -281,19 +278,18 @@ x509_get_pubkey(X509 *x, const char *fn)
  * 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)
+int
+x509_get_aia(X509 *x, const char *fn, char **aia)
 {
        ACCESS_DESCRIPTION              *ad;
        AUTHORITY_INFO_ACCESS           *info;
-       char                            *aia = NULL;
-       int                              crit;
+       int                              crit, rc = 0;
 
+       *aia = NULL;
        info = X509_get_ext_d2i(x, NID_info_access, &crit, NULL);
-       if (info == NULL) {
-               warnx("%s: RFC 6487 section 4.8.7: AIA: extension missing", fn);
-               return NULL;
-       }
+       if (info == NULL)
+               return 1;
+
        if (crit != 0) {
                warnx("%s: RFC 6487 section 4.8.7: "
                    "AIA: extension not non-critical", fn);
@@ -325,15 +321,16 @@ x509_get_aia(X509 *x, const char *fn)
                goto out;
        }
 
-       aia = strndup(
+       *aia = strndup(
            ASN1_STRING_get0_data(ad->location->d.uniformResourceIdentifier),
            ASN1_STRING_length(ad->location->d.uniformResourceIdentifier));
-       if (aia == NULL)
+       if (*aia == NULL)
                err(1, NULL);
+       rc = 1;
 
 out:
        AUTHORITY_INFO_ACCESS_free(info);
-       return aia;
+       return rc;
 }
 
 /*
@@ -364,21 +361,19 @@ x509_get_expire(X509 *x, const char *fn,
  * Returns NULL on failure, the crl URI on success which has to be freed
  * after use.
  */
-char *
-x509_get_crl(X509 *x, const char *fn)
+int
+x509_get_crl(X509 *x, const char *fn, char **crl)
 {
        CRL_DIST_POINTS         *crldp;
        DIST_POINT              *dp;
        GENERAL_NAME            *name;
-       char                    *crl = NULL;
-       int                      crit;
+       int                      crit, rc = 0;
 
+       *crl = NULL;
        crldp = X509_get_ext_d2i(x, NID_crl_distribution_points, &crit, NULL);
-       if (crldp == NULL) {
-               warnx("%s: RFC 6487 section 4.8.6: CRL: "
-                   "no CRL distribution point extension", fn);
-               return NULL;
-       }
+       if (crldp == NULL)
+               return 1;
+
        if (crit != 0) {
                warnx("%s: RFC 6487 section 4.8.6: "
                    "CRL distribution point: extension not non-critical", fn);
@@ -425,14 +420,15 @@ x509_get_crl(X509 *x, const char *fn)
                goto out;
        }
 
-       crl = strndup(ASN1_STRING_get0_data(name->d.uniformResourceIdentifier),
+       *crl = strndup(ASN1_STRING_get0_data(name->d.uniformResourceIdentifier),
            ASN1_STRING_length(name->d.uniformResourceIdentifier));
-       if (crl == NULL)
+       if (*crl == NULL)
                err(1, NULL);
+       rc = 1;
 
 out:
        CRL_DIST_POINTS_free(crldp);
-       return crl;
+       return rc;
 }
 
 /*

Reply via email to