[openssl-commits] [openssl] OpenSSL_1_0_1-stable update

Richard Levitte levitte at openssl.org
Wed Jun 29 23:07:55 UTC 2016


The branch OpenSSL_1_0_1-stable has been updated
       via  08327bfb261eea4a3c356d6ebff81d838f063d1b (commit)
       via  f7c95287b602191a971c1cec9427029b453a68e8 (commit)
       via  26576cf9cea7841c9abb54e0609cdf09d3f4c663 (commit)
      from  05200ee5c61ecd38cdcacf9c547b0c3877e8cfef (commit)


- Log -----------------------------------------------------------------
commit 08327bfb261eea4a3c356d6ebff81d838f063d1b
Author: Richard Levitte <levitte at openssl.org>
Date:   Sun Jun 19 10:55:43 2016 +0200

    Allow proxy certs to be present when verifying a chain
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (cherry picked from commit 6ad8c48291622a6ccc51489b9a230c9a05ca5614)

commit f7c95287b602191a971c1cec9427029b453a68e8
Author: Richard Levitte <levitte at openssl.org>
Date:   Sun Jun 19 10:55:29 2016 +0200

    Fix proxy certificate pathlength verification
    
    While travelling up the certificate chain, the internal
    proxy_path_length must be updated with the pCPathLengthConstraint
    value, or verification will not work properly.  This corresponds to
    RFC 3820, 4.1.4 (a).
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (cherry picked from commit 30aeb3128199c15760a785d88a4eda9e156d5af6)

commit 26576cf9cea7841c9abb54e0609cdf09d3f4c663
Author: Richard Levitte <levitte at openssl.org>
Date:   Sun Jun 19 10:55:16 2016 +0200

    Check that the subject name in a proxy cert complies to RFC 3820
    
    The subject name MUST be the same as the issuer name, with a single CN
    entry added.
    
    RT#1852
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (cherry picked from commit 338fb1688fbfb7efe0bdd475b01791a6de5ef94b)

-----------------------------------------------------------------------

Summary of changes:
 apps/apps.c            |   2 +
 crypto/x509/x509.h     |   6 ++-
 crypto/x509/x509_err.c |   1 +
 crypto/x509/x509_txt.c |   2 +
 crypto/x509/x509_vfy.c | 103 +++++++++++++++++++++++++++++++++++++++++++++----
 crypto/x509/x509_vfy.h |   2 +
 doc/apps/verify.pod    |   5 +++
 7 files changed, 112 insertions(+), 9 deletions(-)

diff --git a/apps/apps.c b/apps/apps.c
index 8ab4833..ca9179e 100644
--- a/apps/apps.c
+++ b/apps/apps.c
@@ -2241,6 +2241,8 @@ int args_verify(char ***pargs, int *pargc,
         flags |= X509_V_FLAG_CHECK_SS_SIGNATURE;
     else if (!strcmp(arg, "-no_alt_chains"))
         flags |= X509_V_FLAG_NO_ALT_CHAINS;
+    else if (!strcmp(arg, "-allow_proxy_certs"))
+        flags |= X509_V_FLAG_ALLOW_PROXY_CERTS;
     else
         return 0;
 
diff --git a/crypto/x509/x509.h b/crypto/x509/x509.h
index bd600de..dc326a7 100644
--- a/crypto/x509/x509.h
+++ b/crypto/x509/x509.h
@@ -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
diff --git a/crypto/x509/x509_err.c b/crypto/x509/x509_err.c
index a2b8b7f..174b65e 100644
--- a/crypto/x509/x509_err.c
+++ b/crypto/x509/x509_err.c
@@ -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"},
diff --git a/crypto/x509/x509_txt.c b/crypto/x509/x509_txt.c
index 0952813..b249d42 100644
--- a/crypto/x509/x509_txt.c
+++ b/crypto/x509/x509_txt.c
@@ -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);
diff --git a/crypto/x509/x509_vfy.c b/crypto/x509/x509_vfy.c
index 2e2287e..f0fa7f4 100644
--- a/crypto/x509/x509_vfy.c
+++ b/crypto/x509/x509_vfy.c
@@ -633,13 +633,27 @@ static int check_chain_extensions(X509_STORE_CTX *ctx)
          * the next certificate must be a CA certificate.
          */
         if (x->ex_flags & EXFLAG_PROXY) {
-            if (x->ex_pcpathlen != -1 && i > x->ex_pcpathlen) {
-                ctx->error = X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED;
-                ctx->error_depth = i;
-                ctx->current_cert = x;
-                ok = cb(0, ctx);
-                if (!ok)
-                    goto end;
+            /*
+             * RFC3820, 4.1.3 (b)(1) stipulates that if pCPathLengthConstraint
+             * is less than max_path_length, the former should be copied to
+             * the latter, and 4.1.4 (a) stipulates that max_path_length
+             * should be verified to be larger than zero and decrement it.
+             *
+             * Because we're checking the certs in the reverse order, we start
+             * with verifying that proxy_path_length isn't larger than pcPLC,
+             * and copy the latter to the former if it is, and finally,
+             * increment proxy_path_length.
+             */
+            if (x->ex_pcpathlen != -1) {
+                if (proxy_path_length > x->ex_pcpathlen) {
+                    ctx->error = X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED;
+                    ctx->error_depth = i;
+                    ctx->current_cert = x;
+                    ok = cb(0, ctx);
+                    if (!ok)
+                        goto end;
+                }
+                proxy_path_length = x->ex_pcpathlen;
             }
             proxy_path_length++;
             must_be_ca = 0;
@@ -662,6 +676,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
diff --git a/crypto/x509/x509_vfy.h b/crypto/x509/x509_vfy.h
index eefca75..31f9f7f 100644
--- a/crypto/x509/x509_vfy.h
+++ b/crypto/x509/x509_vfy.h
@@ -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 */
diff --git a/doc/apps/verify.pod b/doc/apps/verify.pod
index 18eeee0..450dd7d 100644
--- a/doc/apps/verify.pod
+++ b/doc/apps/verify.pod
@@ -23,6 +23,7 @@ B<openssl> B<verify>
 [B<-use_deltas>]
 [B<-policy_print>]
 [B<-no_alt_chains>]
+[B<-allow_proxy_certs>]
 [B<-untrusted file>]
 [B<-help>]
 [B<-issuer_checks>]
@@ -117,6 +118,10 @@ be found that is trusted. With this option that behaviour is suppressed so that
 only the first chain found is ever used. Using this option will force the
 behaviour to match that of previous OpenSSL versions.
 
+=item B<-allow_proxy_certs>
+
+Allow the verification of proxy certificates.
+
 =item B<-policy_print>
 
 Print out diagnostics related to policy processing.


More information about the openssl-commits mailing list