[openssl-commits] [openssl] OpenSSL_1_0_2-stable update

Richard Levitte levitte at openssl.org
Wed Jun 29 21:14:03 UTC 2016


The branch OpenSSL_1_0_2-stable has been updated
       via  6ad8c48291622a6ccc51489b9a230c9a05ca5614 (commit)
       via  30aeb3128199c15760a785d88a4eda9e156d5af6 (commit)
       via  338fb1688fbfb7efe0bdd475b01791a6de5ef94b (commit)
      from  ad64a69e02f7dda422d0f4f53dce7b1278715380 (commit)


- Log -----------------------------------------------------------------
commit 6ad8c48291622a6ccc51489b9a230c9a05ca5614
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>

commit 30aeb3128199c15760a785d88a4eda9e156d5af6
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>

commit 338fb1688fbfb7efe0bdd475b01791a6de5ef94b
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>

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

Summary of changes:
 apps/apps.c            |   2 +
 crypto/x509/x509.h     |   6 ++-
 crypto/x509/x509_err.c |   3 +-
 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, 113 insertions(+), 10 deletions(-)

diff --git a/apps/apps.c b/apps/apps.c
index b1dd970..0385490 100644
--- a/apps/apps.c
+++ b/apps/apps.c
@@ -2374,6 +2374,8 @@ int args_verify(char ***pargs, int *pargc,
         flags |= X509_V_FLAG_PARTIAL_CHAIN;
     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 fc613ce..6fa28eb 100644
--- a/crypto/x509/x509.h
+++ b/crypto/x509/x509.h
@@ -1234,6 +1234,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. */
@@ -1241,6 +1242,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
@@ -1322,7 +1324,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 1e779fe..a2a8e1b 100644
--- a/crypto/x509/x509_err.c
+++ b/crypto/x509/x509_err.c
@@ -1,6 +1,6 @@
 /* crypto/x509/x509_err.c */
 /* ====================================================================
- * Copyright (c) 1999-2012 The OpenSSL Project.  All rights reserved.
+ * Copyright (c) 1999-2016 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -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 4475715..35db095 100644
--- a/crypto/x509/x509_txt.c
+++ b/crypto/x509/x509_txt.c
@@ -208,6 +208,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 f3fe255..389b1c2 100644
--- a/crypto/x509/x509_vfy.c
+++ b/crypto/x509/x509_vfy.c
@@ -713,13 +713,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;
@@ -742,6 +756,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 f54ecc5..5062682 100644
--- a/crypto/x509/x509_vfy.h
+++ b/crypto/x509/x509_vfy.h
@@ -392,6 +392,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 bffa6c0..b376732 100644
--- a/doc/apps/verify.pod
+++ b/doc/apps/verify.pod
@@ -27,6 +27,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>]
@@ -139,6 +140,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<-trusted file>
 
 A file of additional trusted certificates. The file should contain multiple


More information about the openssl-commits mailing list