[openssl-commits] [openssl] master update

Matt Caswell matt at openssl.org
Wed Feb 25 09:16:05 UTC 2015


The branch master has been updated
       via  fa7b01115bc33d9b40936688bb3c952dc93b645a (commit)
       via  25690b7f5f3d78a52c1377b823b40c6a0e12022b (commit)
       via  15dba5be6a4482a9ad7e5b846291f31e97e338ca (commit)
       via  da084a5ec6cebd67ae27f2463ebe4a50bb840fa5 (commit)
      from  5b8aa1a2af738f93b535798bfc07069aada264e1 (commit)


- Log -----------------------------------------------------------------
commit fa7b01115bc33d9b40936688bb3c952dc93b645a
Author: Matt Caswell <matt at openssl.org>
Date:   Tue Jan 27 11:15:15 2015 +0000

    Add documentation for the -no_alt_chains option for various apps, as well as
    the X509_V_FLAG_NO_ALT_CHAINS flag.
    
    Reviewed-by: Dr. Stephen Henson <steve at openssl.org>

commit 25690b7f5f3d78a52c1377b823b40c6a0e12022b
Author: Matt Caswell <matt at openssl.org>
Date:   Tue Jan 27 10:50:38 2015 +0000

    Add -no_alt_chains option to apps to implement the new
    X509_V_FLAG_NO_ALT_CHAINS flag. Using this option means that when building
    certificate chains, the first chain found will be the one used. Without this
    flag, if the first chain found is not trusted then we will keep looking to
    see if we can build an alternative chain instead.
    
    Reviewed-by: Dr. Stephen Henson <steve at openssl.org>

commit 15dba5be6a4482a9ad7e5b846291f31e97e338ca
Author: Matt Caswell <matt at openssl.org>
Date:   Tue Jan 27 10:35:27 2015 +0000

    Add flag to inhibit checking for alternate certificate chains. Setting this
    behaviour will force behaviour as per previous versions of OpenSSL
    
    Reviewed-by: Dr. Stephen Henson <steve at openssl.org>

commit da084a5ec6cebd67ae27f2463ebe4a50bb840fa5
Author: Matt Caswell <matt at openssl.org>
Date:   Tue Jan 27 10:03:29 2015 +0000

    In certain situations the server provided certificate chain may no longer be
    valid. However the issuer of the leaf, or some intermediate cert is in fact
    in the trust store.
    
    When building a trust chain if the first attempt fails, then try to see if
    alternate chains could be constructed that are trusted.
    
    RT3637
    RT3621
    
    Reviewed-by: Dr. Stephen Henson <steve at openssl.org>

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

Summary of changes:
 apps/apps.c                                |    2 +
 apps/cms.c                                 |    2 +
 apps/ocsp.c                                |    2 +
 apps/s_client.c                            |    2 +
 apps/s_server.c                            |    2 +
 apps/smime.c                               |    2 +
 apps/verify.c                              |    2 +-
 crypto/x509/x509_vfy.c                     |  177 +++++++++++++++++-----------
 crypto/x509/x509_vfy.h                     |    6 +
 doc/apps/cms.pod                           |   11 +-
 doc/apps/ocsp.pod                          |   13 +-
 doc/apps/s_client.pod                      |   14 ++-
 doc/apps/s_server.pod                      |    9 +-
 doc/apps/smime.pod                         |    8 +-
 doc/apps/verify.pod                        |   13 ++
 doc/crypto/X509_VERIFY_PARAM_set_flags.pod |    8 +-
 16 files changed, 184 insertions(+), 89 deletions(-)

diff --git a/apps/apps.c b/apps/apps.c
index bf044d4..8412e24 100644
--- a/apps/apps.c
+++ b/apps/apps.c
@@ -2362,6 +2362,8 @@ int args_verify(char ***pargs, int *pargc,
         flags |= X509_V_FLAG_SUITEB_192_LOS;
     else if (!strcmp(arg, "-partial_chain"))
         flags |= X509_V_FLAG_PARTIAL_CHAIN;
+    else if (!strcmp(arg, "-no_alt_chains"))
+        flags |= X509_V_FLAG_NO_ALT_CHAINS;
     else
         return 0;
 
diff --git a/apps/cms.c b/apps/cms.c
index fbb5607..479d1dd 100644
--- a/apps/cms.c
+++ b/apps/cms.c
@@ -646,6 +646,8 @@ int MAIN(int argc, char **argv)
         BIO_printf(bio_err,
                    "-trusted_first use locally trusted certificates first when building trust chain\n");
         BIO_printf(bio_err,
+                   "-no_alt_chains only ever use the first certificate chain found\n");
+        BIO_printf(bio_err,
                    "-crl_check     check revocation status of signer's certificate using CRLs\n");
         BIO_printf(bio_err,
                    "-crl_check_all check revocation status of signer's certificate chain using CRLs\n");
diff --git a/apps/ocsp.c b/apps/ocsp.c
index 4b9d6f6..b0b3069 100644
--- a/apps/ocsp.c
+++ b/apps/ocsp.c
@@ -538,6 +538,8 @@ int MAIN(int argc, char **argv)
         BIO_printf(bio_err,
                    "-trusted_first       use locally trusted CA's first when building trust chain\n");
         BIO_printf(bio_err,
+                   "-no_alt_chains       only ever use the first certificate chain found\n");
+        BIO_printf(bio_err,
                    "-VAfile file         validator certificates file\n");
         BIO_printf(bio_err,
                    "-validity_period n   maximum validity discrepancy in seconds\n");
diff --git a/apps/s_client.c b/apps/s_client.c
index 1607c6e..bc82239 100644
--- a/apps/s_client.c
+++ b/apps/s_client.c
@@ -321,6 +321,8 @@ static void sc_usage(void)
     BIO_printf(bio_err,
                " -trusted_first - Use local CA's first when building trust chain\n");
     BIO_printf(bio_err,
+               " -no_alt_chains - only ever use the first certificate chain found\n");
+    BIO_printf(bio_err,
                " -reconnect    - Drop and re-make the connection with the same Session-ID\n");
     BIO_printf(bio_err,
                " -pause        - sleep(1) after each read(2) and write(2) system call\n");
diff --git a/apps/s_server.c b/apps/s_server.c
index 573bc87..4311d6d 100644
--- a/apps/s_server.c
+++ b/apps/s_server.c
@@ -509,6 +509,8 @@ static void sv_usage(void)
     BIO_printf(bio_err,
                " -trusted_first - Use locally trusted CA's first when building trust chain\n");
     BIO_printf(bio_err,
+               " -no_alt_chains - only ever use the first certificate chain found\n");
+    BIO_printf(bio_err,
                " -nocert       - Don't use any certificates (Anon-DH)\n");
     BIO_printf(bio_err,
                " -cipher arg   - play with 'openssl ciphers' to see what goes here\n");
diff --git a/apps/smime.c b/apps/smime.c
index 5efe51f..930978f 100644
--- a/apps/smime.c
+++ b/apps/smime.c
@@ -444,6 +444,8 @@ int MAIN(int argc, char **argv)
         BIO_printf(bio_err,
                    "-trusted_first use locally trusted CA's first when building trust chain\n");
         BIO_printf(bio_err,
+                   "-no_alt_chains only ever use the first certificate chain found\n");
+        BIO_printf(bio_err,
                    "-crl_check     check revocation status of signer's certificate using CRLs\n");
         BIO_printf(bio_err,
                    "-crl_check_all check revocation status of signer's certificate chain using CRLs\n");
diff --git a/apps/verify.c b/apps/verify.c
index 8f963f8..e771be2 100644
--- a/apps/verify.c
+++ b/apps/verify.c
@@ -236,7 +236,7 @@ int MAIN(int argc, char **argv)
  end:
     if (ret == 1) {
         BIO_printf(bio_err,
-                   "usage: verify [-verbose] [-CApath path] [-CAfile file] [-trusted_first] [-purpose purpose] [-crl_check]");
+                   "usage: verify [-verbose] [-CApath path] [-CAfile file] [-trusted_first] [-purpose purpose] [-crl_check] [-no_alt_chains]");
 #ifndef OPENSSL_NO_ENGINE
         BIO_printf(bio_err, " [-engine e]");
 #endif
diff --git a/crypto/x509/x509_vfy.c b/crypto/x509/x509_vfy.c
index cc9665e..bb6e1ce 100644
--- a/crypto/x509/x509_vfy.c
+++ b/crypto/x509/x509_vfy.c
@@ -182,11 +182,11 @@ static X509 *lookup_cert_match(X509_STORE_CTX *ctx, X509 *x)
 
 int X509_verify_cert(X509_STORE_CTX *ctx)
 {
-    X509 *x, *xtmp, *chain_ss = NULL;
+    X509 *x, *xtmp, *xtmp2, *chain_ss = NULL;
     int bad_chain = 0;
     X509_VERIFY_PARAM *param = ctx->param;
     int depth, i, ok = 0;
-    int num;
+    int num, j, retry;
     int (*cb) (int xok, X509_STORE_CTX *xctx);
     STACK_OF(X509) *sktmp = NULL;
     if (ctx->cert == NULL) {
@@ -271,91 +271,128 @@ int X509_verify_cert(X509_STORE_CTX *ctx)
         break;
     }
 
+    /* Remember how many untrusted certs we have */
+    j = num;
     /*
      * at this point, chain should contain a list of untrusted certificates.
      * We now need to add at least one trusted one, if possible, otherwise we
      * complain.
      */
 
-    /*
-     * Examine last certificate in chain and see if it is self signed.
-     */
-
-    i = sk_X509_num(ctx->chain);
-    x = sk_X509_value(ctx->chain, i - 1);
-    if (cert_self_signed(x)) {
-        /* we have a self signed certificate */
-        if (sk_X509_num(ctx->chain) == 1) {
-            /*
-             * We have a single self signed certificate: see if we can find
-             * it in the store. We must have an exact match to avoid possible
-             * impersonation.
-             */
-            ok = ctx->get_issuer(&xtmp, ctx, x);
-            if ((ok <= 0) || X509_cmp(x, xtmp)) {
-                ctx->error = X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT;
-                ctx->current_cert = x;
-                ctx->error_depth = i - 1;
-                if (ok == 1)
-                    X509_free(xtmp);
-                bad_chain = 1;
-                ok = cb(0, ctx);
-                if (!ok)
-                    goto end;
+    do {
+        /*
+         * Examine last certificate in chain and see if it is self signed.
+         */
+        i = sk_X509_num(ctx->chain);
+        x = sk_X509_value(ctx->chain, i - 1);
+        if (cert_self_signed(x)) {
+            /* we have a self signed certificate */
+            if (sk_X509_num(ctx->chain) == 1) {
+                /*
+                 * We have a single self signed certificate: see if we can
+                 * find it in the store. We must have an exact match to avoid
+                 * possible impersonation.
+                 */
+                ok = ctx->get_issuer(&xtmp, ctx, x);
+                if ((ok <= 0) || X509_cmp(x, xtmp)) {
+                    ctx->error = X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT;
+                    ctx->current_cert = x;
+                    ctx->error_depth = i - 1;
+                    if (ok == 1)
+                        X509_free(xtmp);
+                    bad_chain = 1;
+                    ok = cb(0, ctx);
+                    if (!ok)
+                        goto end;
+                } else {
+                    /*
+                     * We have a match: replace certificate with store
+                     * version so we get any trust settings.
+                     */
+                    X509_free(x);
+                    x = xtmp;
+                    (void)sk_X509_set(ctx->chain, i - 1, x);
+                    ctx->last_untrusted = 0;
+                }
             } else {
                 /*
-                 * We have a match: replace certificate with store version so
-                 * we get any trust settings.
+                 * extract and save self signed certificate for later use
                  */
-                X509_free(x);
-                x = xtmp;
-                (void)sk_X509_set(ctx->chain, i - 1, x);
-                ctx->last_untrusted = 0;
+                chain_ss = sk_X509_pop(ctx->chain);
+                ctx->last_untrusted--;
+                num--;
+                j--;
+                x = sk_X509_value(ctx->chain, num - 1);
             }
-        } else {
-            /*
-             * extract and save self signed certificate for later use
-             */
-            chain_ss = sk_X509_pop(ctx->chain);
-            ctx->last_untrusted--;
-            num--;
-            x = sk_X509_value(ctx->chain, num - 1);
         }
-    }
-
-    /* We now lookup certs from the certificate store */
-    for (;;) {
-        /* If we have enough, we break */
-        if (depth < num)
-            break;
+        /* We now lookup certs from the certificate store */
+        for (;;) {
+            /* If we have enough, we break */
+            if (depth < num)
+                break;
+            /* If we are self signed, we break */
+            if (cert_self_signed(x))
+                break;
+            ok = ctx->get_issuer(&xtmp, ctx, x);
 
-        /* If we are self signed, we break */
-        if (cert_self_signed(x))
-            break;
+            if (ok < 0)
+                return ok;
+            if (ok == 0)
+                break;
+            x = xtmp;
+            if (!sk_X509_push(ctx->chain, x)) {
+                X509_free(xtmp);
+                X509err(X509_F_X509_VERIFY_CERT, ERR_R_MALLOC_FAILURE);
+                return 0;
+            }
+            num++;
+        }
 
-        ok = ctx->get_issuer(&xtmp, ctx, x);
+        /* we now have our chain, lets check it... */
+        i = check_trust(ctx);
 
-        if (ok < 0)
-            return ok;
-        if (ok == 0)
-            break;
+        /* If explicitly rejected error */
+        if (i == X509_TRUST_REJECTED)
+            goto end;
+        /*
+         * If it's not explicitly trusted then check if there is an alternative
+         * chain that could be used. We only do this if we haven't already
+         * checked via TRUSTED_FIRST and the user hasn't switched off alternate
+         * chain checking
+         */
+        retry = 0;
+        if (i != X509_TRUST_TRUSTED
+            && !(ctx->param->flags & X509_V_FLAG_TRUSTED_FIRST)
+            && !(ctx->param->flags & X509_V_FLAG_NO_ALT_CHAINS)) {
+            while (j-- > 1) {
+                xtmp2 = sk_X509_value(ctx->chain, j - 1);
+                ok = ctx->get_issuer(&xtmp, ctx, xtmp2);
+                if (ok < 0)
+                    goto end;
+                /* Check if we found an alternate chain */
+                if (ok > 0) {
+                    /*
+                     * Free up the found cert we'll add it again later
+                     */
+                    X509_free(xtmp);
 
-        x = xtmp;
-        if (!sk_X509_push(ctx->chain, x)) {
-            X509_free(xtmp);
-            X509err(X509_F_X509_VERIFY_CERT, ERR_R_MALLOC_FAILURE);
-            return 0;
+                    /*
+                     * Dump all the certs above this point - we've found an
+                     * alternate chain
+                     */
+                    while (num > j) {
+                        xtmp = sk_X509_pop(ctx->chain);
+                        X509_free(xtmp);
+                        num--;
+                        ctx->last_untrusted--;
+                    }
+                    retry = 1;
+                    break;
+                }
+            }
         }
-        num++;
-    }
+    } while (retry);
 
-    /* we now have our chain, lets check it... */
-
-    i = check_trust(ctx);
-
-    /* If explicitly rejected error */
-    if (i == X509_TRUST_REJECTED)
-        goto end;
     /*
      * If not explicitly trusted then indicate error unless it's a single
      * self signed certificate in which case we've indicated an error already
diff --git a/crypto/x509/x509_vfy.h b/crypto/x509/x509_vfy.h
index 03e43e5..e41b5e2 100644
--- a/crypto/x509/x509_vfy.h
+++ b/crypto/x509/x509_vfy.h
@@ -419,6 +419,12 @@ void X509_STORE_CTX_set_depth(X509_STORE_CTX *ctx, int depth);
 # define X509_V_FLAG_SUITEB_128_LOS              0x30000
 /* Allow partial chains if at least one certificate is in trusted store */
 # define X509_V_FLAG_PARTIAL_CHAIN               0x80000
+/*
+ * If the initial chain is not trusted, do not attempt to build an alternative
+ * chain. Alternate chain checking was introduced in 1.1.0. Setting this flag
+ * will force the behaviour to match that of previous versions.
+ */
+# define X509_V_FLAG_NO_ALT_CHAINS               0x100000
 
 # define X509_VP_FLAG_DEFAULT                    0x1
 # define X509_VP_FLAG_OVERWRITE                  0x2
diff --git a/doc/apps/cms.pod b/doc/apps/cms.pod
index 4dabd3b..af1240a 100644
--- a/doc/apps/cms.pod
+++ b/doc/apps/cms.pod
@@ -54,6 +54,7 @@ B<openssl> B<cms>
 [B<-suiteB_128_only>]
 [B<-suiteB_192>]
 [B<-trusted_first>]
+[B<-no_alt_chains>]
 [B<-use_deltas>]
 [B<-verify_depth num>]
 [B<-verify_email email>]
@@ -459,11 +460,11 @@ address matches that specified in the From: address.
 B<explicit_policy>, B<-extended_crl>, B<-ignore_critical>, B<-inhibit_any>,
 B<-inhibit_map>, B<-issuer_checks>, B<-partial_chain>, B<-policy>,
 B<-policy_check>, B<-policy_print>, B<-purpose>, B<-suiteB_128>,
-B<-suiteB_128_only>, B<-suiteB_192>, B<-trusted_first>, B<-use_deltas>,
-B<-verify_depth>, B<-verify_email>, B<-verify_hostname>, B<-verify_ip>,
-B<-verify_name>, B<-x509_strict>
+B<-suiteB_128_only>, B<-suiteB_192>, B<-trusted_first>, B<-no_alt_chains>,
+B<-use_deltas>, B<-verify_depth>, B<-verify_email>, B<-verify_hostname>,
+B<-verify_ip>, B<-verify_name>, B<-x509_strict>
 
-Set various certificate chain valiadition options. See the
+Set various certificate chain validation options. See the
 L<B<verify>|verify(1)> manual page for details.
 
 =back
@@ -697,4 +698,6 @@ Support for RSA-OAEP and RSA-PSS was first added to OpenSSL 1.1.0.
 The use of non-RSA keys with B<-encrypt> and B<-decrypt> was first added
 to OpenSSL 1.1.0.
 
+The -no_alt_chains options was first added to OpenSSL 1.1.0.
+
 =cut
diff --git a/doc/apps/ocsp.pod b/doc/apps/ocsp.pod
index b32086c..d5565c9 100644
--- a/doc/apps/ocsp.pod
+++ b/doc/apps/ocsp.pod
@@ -48,6 +48,7 @@ B<openssl> B<ocsp>
 [B<-suiteB_128_only>]
 [B<-suiteB_192>]
 [B<-trusted_first>]
+[B<-no_alt_chains>]
 [B<-use_deltas>]
 [B<-verify_depth num>]
 [B<-verify_email email>]
@@ -173,9 +174,9 @@ the signature on the OCSP response.
 B<explicit_policy>, B<-extended_crl>, B<-ignore_critical>, B<-inhibit_any>,
 B<-inhibit_map>, B<-issuer_checks>, B<-partial_chain>, B<-policy>,
 B<-policy_check>, B<-policy_print>, B<-purpose>, B<-suiteB_128>,
-B<-suiteB_128_only>, B<-suiteB_192>, B<-trusted_first>, B<-use_deltas>,
-B<-verify_depth>, B<-verify_email>, B<-verify_hostname>, B<-verify_ip>,
-B<-verify_name>, B<-x509_strict>
+B<-suiteB_128_only>, B<-suiteB_192>, B<-trusted_first>, B<-no_alt_chains>,
+B<-use_deltas>, B<-verify_depth>, B<-verify_email>, B<-verify_hostname>,
+B<-verify_ip>, B<-verify_name>, B<-x509_strict>
 
 Set different certificate verification options.
 See L<B<verify>|verify(1)> manual page for details.
@@ -416,3 +417,9 @@ second file.
 
  openssl ocsp -index demoCA/index.txt -rsigner rcert.pem -CA demoCA/cacert.pem
      -reqin req.der -respout resp.der
+
+=head1 HISTORY
+
+The -no_alt_chains options was first added to OpenSSL 1.1.0.
+
+=cut
diff --git a/doc/apps/s_client.pod b/doc/apps/s_client.pod
index 17308b4..92f6e4a 100644
--- a/doc/apps/s_client.pod
+++ b/doc/apps/s_client.pod
@@ -19,7 +19,6 @@ B<openssl> B<s_client>
 [B<-pass arg>]
 [B<-CApath directory>]
 [B<-CAfile filename>]
-[B<-trusted_first>]
 [B<-attime timestamp>]
 [B<-check_ss_sig>]
 [B<-crl_check>]
@@ -39,6 +38,7 @@ B<openssl> B<s_client>
 [B<-suiteB_128_only>]
 [B<-suiteB_192>]
 [B<-trusted_first>]
+[B<-no_alt_chains>]
 [B<-use_deltas>]
 [B<-verify_depth num>]
 [B<-verify_email email>]
@@ -155,11 +155,11 @@ and to use when attempting to build the client certificate chain.
 B<explicit_policy>, B<-extended_crl>, B<-ignore_critical>, B<-inhibit_any>,
 B<-inhibit_map>, B<-issuer_checks>, B<-partial_chain>, B<-policy>,
 B<-policy_check>, B<-policy_print>, B<-purpose>, B<-suiteB_128>,
-B<-suiteB_128_only>, B<-suiteB_192>, B<-trusted_first>, B<-use_deltas>,
-B<-verify_depth>, B<-verify_email>, B<-verify_hostname>, B<-verify_ip>,
-B<-verify_name>, B<-x509_strict>
+B<-suiteB_128_only>, B<-suiteB_192>, B<-trusted_first>, B<-no_alt_chains>,
+B<-use_deltas>, B<-verify_depth>, B<-verify_email>, B<-verify_hostname>,
+B<-verify_ip>, B<-verify_name>, B<-x509_strict>
 
-Set various certificate chain valiadition options. See the
+Set various certificate chain validation options. See the
 L<B<verify>|verify(1)> manual page for details.
 
 =item B<-reconnect>
@@ -411,4 +411,8 @@ information whenever a session is renegotiated.
 
 L<sess_id(1)|sess_id(1)>, L<s_server(1)|s_server(1)>, L<ciphers(1)|ciphers(1)>
 
+=head1 HISTORY
+
+The -no_alt_chains options was first added to OpenSSL 1.1.0.
+
 =cut
diff --git a/doc/apps/s_server.pod b/doc/apps/s_server.pod
index 1cc965f..a442452 100644
--- a/doc/apps/s_server.pod
+++ b/doc/apps/s_server.pod
@@ -51,6 +51,7 @@ B<openssl> B<s_server>
 [B<-suiteB_128_only>]
 [B<-suiteB_192>]
 [B<-trusted_first>]
+[B<-no_alt_chains>]
 [B<-use_deltas>]
 [B<-verify_depth num>]
 [B<-verify_return_error>]
@@ -218,8 +219,8 @@ anonymous ciphersuite or PSK) this option has no effect.
 B<-ignore_critical>, B<-inhibit_any>, B<-inhibit_map>, B<-issuer_checks>,
 B<-partial_chain>, B<-policy>, B<-policy_check>, B<-policy_print>, B<-purpose>,
 B<-suiteB_128>, B<-suiteB_128_only>, B<-suiteB_192>, B<-trusted_first>,
-B<-use_deltas>, B<-verify_depth>, B<-verify_email>, B<-verify_hostname>,
-B<-verify_ip>, B<-verify_name>, B<-x509_strict>
+B<-no_alt_chains>, B<-use_deltas>, B<-verify_depth>, B<-verify_email>,
+B<-verify_hostname>, B<-verify_ip>, B<-verify_name>, B<-x509_strict>
 
 Set different peer certificate verification options.
 See the L<B<verify>|verify(1)> manual page for details.
@@ -481,4 +482,8 @@ unknown cipher suites a client says it supports.
 
 L<sess_id(1)|sess_id(1)>, L<s_client(1)|s_client(1)>, L<ciphers(1)|ciphers(1)>
 
+=head1 HISTORY
+
+The -no_alt_chains options was first added to OpenSSL 1.1.0.
+
 =cut
diff --git a/doc/apps/smime.pod b/doc/apps/smime.pod
index c85a44b..31a85fb 100644
--- a/doc/apps/smime.pod
+++ b/doc/apps/smime.pod
@@ -36,6 +36,7 @@ B<openssl> B<smime>
 [B<-suiteB_128_only>]
 [B<-suiteB_192>]
 [B<-trusted_first>]
+[B<-no_alt_chains>]
 [B<-use_deltas>]
 [B<-verify_depth num>]
 [B<-verify_email email>]
@@ -291,9 +292,9 @@ address matches that specified in the From: address.
 B<explicit_policy>, B<-extended_crl>, B<-ignore_critical>, B<-inhibit_any>,
 B<-inhibit_map>, B<-issuer_checks>, B<-partial_chain>, B<-policy>,
 B<-policy_check>, B<-policy_print>, B<-purpose>, B<-suiteB_128>,
-B<-suiteB_128_only>, B<-suiteB_192>, B<-trusted_first>, B<-use_deltas>,
-B<-verify_depth>, B<-verify_email>, B<-verify_hostname>, B<-verify_ip>,
-B<-verify_name>, B<-x509_strict>
+B<-suiteB_128_only>, B<-suiteB_192>, B<-trusted_first>, B<-no_alt_chains>,
+B<-use_deltas>, B<-verify_depth>, B<-verify_email>, B<-verify_hostname>,
+B<-verify_ip>, B<-verify_name>, B<-x509_strict>
 
 Set various options of certificate chain verification. See
 L<B<verify>|verify(1)> manual page for details.
@@ -475,5 +476,6 @@ structures may cause parsing errors.
 The use of multiple B<-signer> options and the B<-resign> command were first
 added in OpenSSL 1.0.0
 
+The -no_alt_chains options was first added to OpenSSL 1.1.0.
 
 =cut
diff --git a/doc/apps/verify.pod b/doc/apps/verify.pod
index a5a0063..d422913 100644
--- a/doc/apps/verify.pod
+++ b/doc/apps/verify.pod
@@ -30,6 +30,7 @@ B<openssl> B<verify>
 [B<-suiteB_128_only>]
 [B<-suiteB_192>]
 [B<-trusted_first>]
+[B<-no_alt_chains>]
 [B<-untrusted file>]
 [B<-use_deltas>]
 [B<-verbose>]
@@ -164,6 +165,14 @@ Use certificates in CA file or CA directory before certificates in untrusted
 file when building the trust chain to verify certificates.
 This is mainly useful in environments with Bridge CA or Cross-Certified CAs.
 
+=item B<-no_alt_chains>
+
+When building a certificate chain, if the first certificate chain found is not
+trusted, then OpenSSL will continue to check to see if an alternative chain can
+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 OpenSSL versions prior to 1.1.0. 
+
 =item B<-untrusted file>
 
 A file of untrusted certificates. The file should contain multiple certificates
@@ -469,4 +478,8 @@ B<20 X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY> error codes.
 
 L<x509(1)|x509(1)>
 
+=head1 HISTORY
+
+The -no_alt_chains options was first added to OpenSSL 1.1.0.
+
 =cut
diff --git a/doc/crypto/X509_VERIFY_PARAM_set_flags.pod b/doc/crypto/X509_VERIFY_PARAM_set_flags.pod
index 347d48d..d19dc12 100644
--- a/doc/crypto/X509_VERIFY_PARAM_set_flags.pod
+++ b/doc/crypto/X509_VERIFY_PARAM_set_flags.pod
@@ -197,6 +197,12 @@ verification. If this flag is set then additional status codes will be sent
 to the verification callback and it B<must> be prepared to handle such cases
 without assuming they are hard errors.
 
+The B<X509_V_FLAG_NO_ALT_CHAINS> flag suppresses checking for alternative
+chains. By default, when building a certificate chain, if the first certificate
+chain found is not trusted, then OpenSSL will continue to check to see if an
+alternative chain can be found that is trusted. With this flag set the behaviour
+will match that of OpenSSL versions prior to 1.1.0.
+
 =head1 NOTES
 
 The above functions should be used to manipulate verification parameters
@@ -233,6 +239,6 @@ L<X509_check_ip(3)|X509_check_ip(3)>
 
 =head1 HISTORY
 
-TBA
+The B<X509_V_FLAG_NO_ALT_CHAINS> flag was added in OpenSSL 1.1.0
 
 =cut


More information about the openssl-commits mailing list