Download raw body.
rpki-client: add CRLDP parsing to cert_parse_extensions()
Add a version of x509_get_crl() to cert_parse_extensions(). One change
is that we disallow TA certs and the other is that the deserialization
matches the other handlers. Also populate cert->crl directly.
I added comments to the extensions covered by cert_check_purpose().
Visibly, the only missing extensions in the switch are SKI and AKI,
which will come next.
As with the other nearly duplicated code, the old x509_get_crl()
will be removed later on.
Index: cert.c
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/cert.c,v
diff -u -p -r1.177 cert.c
--- cert.c 1 Jul 2025 19:12:08 -0000 1.177
+++ cert.c 1 Jul 2025 19:24:29 -0000
@@ -502,6 +502,105 @@ sbgp_ipaddrblk(const char *fn, struct ce
}
/*
+ * Parse CRL distribution point per RFC 6487, section 4.8.6.
+ */
+static int
+cert_crldp(const char *fn, struct cert *cert, X509_EXTENSION *ext)
+{
+ CRL_DIST_POINTS *crldp = NULL;
+ DIST_POINT *dp;
+ GENERAL_NAMES *names;
+ GENERAL_NAME *name;
+ int i, rc = 0;
+
+ assert(cert->crl == NULL);
+
+ if (cert->purpose == CERT_PURPOSE_TA) {
+ warnx("%s: RFC 6487 section 4.8.6: CRL distribution point "
+ "must be omitted from TA certificates", fn);
+ goto out;
+ }
+
+ if (X509_EXTENSION_get_critical(ext)) {
+ warnx("%s: RFC 6487 section 4.8.6: CRL distribution point "
+ "extension not non-critical", fn);
+ goto out;
+ }
+
+ if ((crldp = X509V3_EXT_d2i(ext)) == NULL) {
+ warnx("%s: RFC 6487 section 4.8.6: CRL distribution point: "
+ "failed extension parse", fn);
+ goto out;
+ }
+
+ if (sk_DIST_POINT_num(crldp) != 1) {
+ warnx("%s: RFC 6487 section 4.8.6: CRL distribution point: "
+ "want 1 element, have %d", fn, sk_DIST_POINT_num(crldp));
+ goto out;
+ }
+
+ dp = sk_DIST_POINT_value(crldp, 0);
+ if (dp->CRLissuer != NULL) {
+ warnx("%s: RFC 6487 section 4.8.6: CRL CRLIssuer field"
+ " disallowed", fn);
+ goto out;
+ }
+ if (dp->reasons != NULL) {
+ warnx("%s: RFC 6487 section 4.8.6: CRL Reasons field"
+ " disallowed", fn);
+ goto out;
+ }
+ if (dp->distpoint == NULL) {
+ warnx("%s: RFC 6487 section 4.8.6: CRL: "
+ "no distribution point name", fn);
+ goto out;
+ }
+ if (dp->distpoint->dpname != NULL) {
+ warnx("%s: RFC 6487 section 4.8.6: nameRelativeToCRLIssuer"
+ " disallowed", fn);
+ goto out;
+ }
+
+ /* Need to hardcode the alternative 0 due to missing macro or enum. */
+ if (dp->distpoint->type != 0) {
+ warnx("%s: RFC 6487 section 4.8.6: CRL DistributionPointName:"
+ " expected fullName, have %d", fn, dp->distpoint->type);
+ goto out;
+ }
+
+ names = dp->distpoint->name.fullname;
+ for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
+ char *crl = NULL;
+
+ name = sk_GENERAL_NAME_value(names, i);
+
+ if (!x509_location(fn, "CRL distribution point", name, &crl))
+ goto out;
+
+ if (cert->crl == NULL && strncasecmp(crl, RSYNC_PROTO,
+ RSYNC_PROTO_LEN) == 0) {
+ cert->crl = crl;
+ continue;
+ }
+ if (verbose)
+ warnx("%s: ignoring CRL distribution point %s",
+ fn, crl);
+ free(crl);
+ }
+
+ if (cert->crl == NULL) {
+ warnx("%s: RFC 6487 section 4.8.6: no rsync URI in "
+ "CRL distribution point", fn);
+ goto out;
+ }
+
+ rc = 1;
+ out:
+ CRL_DIST_POINTS_free(crldp);
+ return rc;
+}
+
+/*
* Parse "Authority Information Access" extension for non-TA certs,
* RFC 6487, section 4.8.7.
* Returns zero on failure, non-zero on success.
@@ -1132,6 +1231,7 @@ cert_parse_extensions(const char *fn, st
case NID_basic_constraints:
if (bc++ > 0)
goto dup;
+ /* handled in cert_check_purpose() */
break;
case NID_subject_key_identifier:
if (ski++ > 0)
@@ -1144,14 +1244,18 @@ cert_parse_extensions(const char *fn, st
case NID_key_usage:
if (ku++ > 0)
goto dup;
+ /* handled in cert_check_purpose() */
break;
case NID_ext_key_usage:
if (eku++ > 0)
goto dup;
+ /* handled in cert_check_purpose() */
break;
case NID_crl_distribution_points:
if (crldp++ > 0)
goto dup;
+ if (!cert_crldp(fn, cert, ext))
+ goto out;
break;
case NID_info_access:
if (aia++ > 0)
@@ -1332,8 +1436,6 @@ cert_parse_pre(const char *fn, const uns
if (!x509_get_aki(x, fn, &cert->aki))
goto out;
if (!x509_get_ski(x, fn, &cert->ski))
- goto out;
- if (!x509_get_crl(x, fn, &cert->crl))
goto out;
if (!x509_get_notbefore(x, fn, &cert->notbefore))
goto out;
rpki-client: add CRLDP parsing to cert_parse_extensions()