Check that the subject name in a proxy cert complies to RFC 3820
authorRichard Levitte <levitte@openssl.org>
Sun, 19 Jun 2016 08:55:16 +0000 (10:55 +0200)
committerRichard Levitte <levitte@openssl.org>
Wed, 29 Jun 2016 23:00:19 +0000 (01:00 +0200)
The subject name MUST be the same as the issuer name, with a single CN
entry added.

RT#1852

Reviewed-by: Rich Salz <rsalz@openssl.org>
(cherry picked from commit 338fb1688fbfb7efe0bdd475b01791a6de5ef94b)

crypto/x509/x509.h
crypto/x509/x509_err.c
crypto/x509/x509_txt.c
crypto/x509/x509_vfy.c
crypto/x509/x509_vfy.h

index bd600de43107edbc1a63129330b7c63d27a261de..dc326a725620e07d7796ff5a73e9b602974f33bf 100644 (file)
@@ -1216,6 +1216,7 @@ int X509_TRUST_get_trust(X509_TRUST *xp);
  * The following lines are auto generated by the script mkerr.pl. Any changes
  * made after this point may be overwritten when the script is next run.
  */
+
 void ERR_load_X509_strings(void);
 
 /* Error codes for the X509 functions. */
@@ -1223,6 +1224,7 @@ void ERR_load_X509_strings(void);
 /* Function codes. */
 # define X509_F_ADD_CERT_DIR                              100
 # define X509_F_BY_FILE_CTRL                              101
+# define X509_F_CHECK_NAME_CONSTRAINTS                    106
 # define X509_F_CHECK_POLICY                              145
 # define X509_F_DIR_CTRL                                  102
 # define X509_F_GET_CERT_BY_SUBJECT                       103
@@ -1296,7 +1298,7 @@ void ERR_load_X509_strings(void);
 # define X509_R_WRONG_LOOKUP_TYPE                         112
 # define X509_R_WRONG_TYPE                                122
 
-#ifdef  __cplusplus
+# ifdef  __cplusplus
 }
-#endif
+# endif
 #endif
index a2b8b7fc358fe08df7de64f73da5c81d0485655b..174b65e33130c8b6b1153951b04b02cf2a0a9d43 100644 (file)
@@ -72,6 +72,7 @@
 static ERR_STRING_DATA X509_str_functs[] = {
     {ERR_FUNC(X509_F_ADD_CERT_DIR), "ADD_CERT_DIR"},
     {ERR_FUNC(X509_F_BY_FILE_CTRL), "BY_FILE_CTRL"},
+    {ERR_FUNC(X509_F_CHECK_NAME_CONSTRAINTS), "CHECK_NAME_CONSTRAINTS"},
     {ERR_FUNC(X509_F_CHECK_POLICY), "CHECK_POLICY"},
     {ERR_FUNC(X509_F_DIR_CTRL), "DIR_CTRL"},
     {ERR_FUNC(X509_F_GET_CERT_BY_SUBJECT), "GET_CERT_BY_SUBJECT"},
index 0952813bd2ef3d6a9819b8e5216868cab6fbb2a0..b249d425673123e98ff01855f44665bd9ebe4994 100644 (file)
@@ -187,6 +187,8 @@ const char *X509_verify_cert_error_string(long n)
         return ("Invalid certificate verification context");
     case X509_V_ERR_STORE_LOOKUP:
         return ("Issuer certificate lookup error");
+    case X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION:
+        return ("proxy subject name violation");
 
     default:
         BIO_snprintf(buf, sizeof buf, "error number %ld", n);
index 2e2287e6c9b34a732eb3c97e116ee964c247e0a7..fdbbe8c5879d22ca71897e7f7791d8586dced0b1 100644 (file)
@@ -662,6 +662,81 @@ static int check_name_constraints(X509_STORE_CTX *ctx)
         /* Ignore self issued certs unless last in chain */
         if (i && (x->ex_flags & EXFLAG_SI))
             continue;
+
+        /*
+         * Proxy certificates policy has an extra constraint, where the
+         * certificate subject MUST be the issuer with a single CN entry
+         * added.
+         * (RFC 3820: 3.4, 4.1.3 (a)(4))
+         */
+        if (x->ex_flags & EXFLAG_PROXY) {
+            X509_NAME *tmpsubject = X509_get_subject_name(x);
+            X509_NAME *tmpissuer = X509_get_issuer_name(x);
+            X509_NAME_ENTRY *tmpentry = NULL;
+            int last_object_nid = 0;
+            int err = X509_V_OK;
+            int last_object_loc = X509_NAME_entry_count(tmpsubject) - 1;
+
+            /* Check that there are at least two RDNs */
+            if (last_object_loc < 1) {
+                err = X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION;
+                goto proxy_name_done;
+            }
+
+            /*
+             * Check that there is exactly one more RDN in subject as
+             * there is in issuer.
+             */
+            if (X509_NAME_entry_count(tmpsubject)
+                != X509_NAME_entry_count(tmpissuer) + 1) {
+                err = X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION;
+                goto proxy_name_done;
+            }
+
+            /*
+             * Check that the last subject component isn't part of a
+             * multivalued RDN
+             */
+            if (X509_NAME_get_entry(tmpsubject, last_object_loc)->set
+                == X509_NAME_get_entry(tmpsubject, last_object_loc - 1)->set) {
+                err = X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION;
+                goto proxy_name_done;
+            }
+
+            /*
+             * Check that the last subject RDN is a commonName, and that
+             * all the previous RDNs match the issuer exactly
+             */
+            tmpsubject = X509_NAME_dup(tmpsubject);
+            if (tmpsubject == NULL) {
+                X509err(X509_F_CHECK_NAME_CONSTRAINTS, ERR_R_MALLOC_FAILURE);
+                ctx->error = X509_V_ERR_OUT_OF_MEM;
+                return 0;
+            }
+
+            tmpentry =
+                X509_NAME_delete_entry(tmpsubject, last_object_loc);
+            last_object_nid =
+                OBJ_obj2nid(X509_NAME_ENTRY_get_object(tmpentry));
+
+            if (last_object_nid != NID_commonName
+                || X509_NAME_cmp(tmpsubject, tmpissuer) != 0) {
+                err = X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION;
+            }
+
+            X509_NAME_ENTRY_free(tmpentry);
+            X509_NAME_free(tmpsubject);
+
+         proxy_name_done:
+            if (err != X509_V_OK) {
+                ctx->error = err;
+                ctx->error_depth = i;
+                ctx->current_cert = x;
+                if (!ctx->verify_cb(0, ctx))
+                    return 0;
+            }
+        }
+
         /*
          * Check against constraints for all certificates higher in chain
          * including trust anchor. Trust anchor not strictly speaking needed
index eefca75183e9a9b4349dc0be9d95260420c44fc0..31f9f7f2c41e5a095919949732655aed687b6e2c 100644 (file)
@@ -391,6 +391,8 @@ void X509_STORE_CTX_set_depth(X509_STORE_CTX *ctx, int depth);
 /* Issuer lookup error */
 # define         X509_V_ERR_STORE_LOOKUP                         66
 
+# define         X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION         67
+
 /* Certificate verify flags */
 
 /* Send issuer+subject checks to verify_cb */