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.
*/