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

Reply via email to