On Mon, Sep 11, 2023 at 09:31:03AM +0200, Theo Buehler wrote: > > - * This only parses the RFC 3779 extensions since these are necessary for > > - * validation. > > Isn't this still true? You don't really parse the subject name.
I took 'parse' to mean something like 'inspects', and since it also inspects the X.509 version, KeyUsage, and soon Subject it seemed a misleading comment to me :-) I incorporated your feedback, OK? Index: cert.c =================================================================== RCS file: /cvs/src/usr.sbin/rpki-client/cert.c,v retrieving revision 1.114 diff -u -p -r1.114 cert.c --- cert.c 29 Jun 2023 10:28:25 -0000 1.114 +++ cert.c 11 Sep 2023 23:44:58 -0000 @@ -594,9 +594,7 @@ certificate_policies(struct parse *p, X5 } /* - * Lightweight version of cert_parse_pre() for ASPA, ROA, and RSC EE certs. - * This only parses the RFC 3779 extensions since these are necessary for - * validation. + * Lightweight version of cert_parse_pre() for EE certs. * Returns cert on success and NULL on failure. */ struct cert * @@ -616,6 +614,9 @@ cert_parse_ee_cert(const char *fn, X509 goto out; } + if (!x509_valid_subject(fn, x)) + goto out; + if (X509_get_key_usage(x) != KU_DIGITAL_SIGNATURE) { warnx("%s: RFC 6487 section 4.8.4: KU must be digitalSignature", fn); @@ -726,6 +727,9 @@ cert_parse_pre(const char *fn, const uns fn); goto out; } + + if (!x509_valid_subject(p.fn, x)) + goto out; /* Look for X509v3 extensions. */ Index: extern.h =================================================================== RCS file: /cvs/src/usr.sbin/rpki-client/extern.h,v retrieving revision 1.188 diff -u -p -r1.188 extern.h --- extern.h 29 Jun 2023 14:33:35 -0000 1.188 +++ extern.h 11 Sep 2023 23:44:58 -0000 @@ -839,6 +839,7 @@ int x509_location(const char *, const GENERAL_NAME *, char **); int x509_inherits(X509 *); int x509_any_inherits(X509 *); +int x509_valid_subject(const char *, const X509 *); time_t x509_find_expires(time_t, struct auth *, struct crl_tree *); /* printers */ Index: x509.c =================================================================== RCS file: /cvs/src/usr.sbin/rpki-client/x509.c,v retrieving revision 1.73 diff -u -p -r1.73 x509.c --- x509.c 23 Jun 2023 15:32:15 -0000 1.73 +++ x509.c 11 Sep 2023 23:44:59 -0000 @@ -861,6 +861,86 @@ x509_location(const char *fn, const char } /* + * Check that the subject only contains commonName and serialNumber. + * Return 0 on failure. + */ +int +x509_valid_subject(const char *fn, const X509 *x) +{ + const X509_NAME *xn; + const X509_NAME_ENTRY *ne; + const ASN1_OBJECT *ao; + const ASN1_STRING *as; + int cn = 0, sn = 0; + int i, nid; + + if ((xn = X509_get_subject_name(x)) == NULL) { + warnx("%s: X509_get_subject_name", fn); + return 0; + } + + for (i = 0; i < X509_NAME_entry_count(xn); i++) { + if ((ne = X509_NAME_get_entry(xn, i)) == NULL) { + warnx("%s: X509_NAME_get_entry", fn); + return 0; + } + if ((ao = X509_NAME_ENTRY_get_object(ne)) == NULL) { + warnx("%s: X509_NAME_ENTRY_get_object", fn); + return 0; + } + + nid = OBJ_obj2nid(ao); + switch (nid) { + case NID_commonName: + if (cn++ > 0) { + warnx("%s: duplicate commonName in subject", + fn); + return 0; + } + if ((as = X509_NAME_ENTRY_get_data(ne)) == NULL) { + warnx("%s: X509_NAME_ENTRY_get_data failed", + fn); + return 0; + } +/* + * The following check can be enabled after AFRINIC re-issues CA certs. + * https://lists.afrinic.net/pipermail/dbwg/2023-March/000436.html + */ +#if 0 + if (as->type != V_ASN1_PRINTABLESTRING) { + warnx("%s: RFC 6487 section 4.5: commonName is" + " not PrintableString", fn); + return 0; + } +#endif + break; + case NID_serialNumber: + if (sn++ > 0) { + warnx("%s: duplicate serialNumber in subject", + fn); + return 0; + } + break; + case NID_undef: + warnx("%s: OBJ_obj2nid failed", fn); + return 0; + default: + warnx("%s: RFC 6487 section 4.5: unexpected attribute " + "%s", fn, OBJ_nid2sn(nid)); + return 0; + } + } + + if (cn == 0) { + warnx("%s: RFC 6487 section 4.5: subject missing commonName", + fn); + return 0; + } + + return 1; +} + +/* * Convert an ASN1_INTEGER into a hexstring. * Returned string needs to be freed by the caller. */