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

Kurt Roeckx kurt at openssl.org
Wed May 20 21:20:25 UTC 2015


The branch OpenSSL_1_0_1-stable has been updated
       via  1c687ff4dd5dcc0f05f1d062effdb40e4e41f24f (commit)
       via  c6a39046f576ab0af25bf3ef844812330af2b27b (commit)
       via  cf1bf3f03250113c04dcfb929a1e83c744a14e9d (commit)
       via  f7bf8e02dfcb2c02bc12a59276d0a3ba43e6c204 (commit)
      from  3b509e8cdc5ca6f42fd66a1325c9d0d23a4103c6 (commit)


- Log -----------------------------------------------------------------
commit 1c687ff4dd5dcc0f05f1d062effdb40e4e41f24f
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>
    Reviewed-by: Kurt Roeckx <kurt at roeckx.be>
    
    Conflicts:
    	doc/apps/cms.pod
    	doc/apps/ocsp.pod
    	doc/apps/s_client.pod
    	doc/apps/s_server.pod
    	doc/apps/smime.pod
    	doc/apps/verify.pod

commit c6a39046f576ab0af25bf3ef844812330af2b27b
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>
    Reviewed-by: Kurt Roeckx <kurt at roeckx.be>
    
    Conflicts:
    	apps/cms.c
    	apps/ocsp.c
    	apps/s_client.c
    	apps/s_server.c
    	apps/smime.c
    	apps/verify.c

commit cf1bf3f03250113c04dcfb929a1e83c744a14e9d
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>
    Reviewed-by: Kurt Roeckx <kurt at roeckx.be>

commit f7bf8e02dfcb2c02bc12a59276d0a3ba43e6c204
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: Kurt Roeckx <kurt at roeckx.be>

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

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                     | 167 +++++++++++++++++------------
 crypto/x509/x509_vfy.h                     |   6 ++
 doc/apps/cms.pod                           |   5 +-
 doc/apps/ocsp.pod                          |  11 ++
 doc/apps/s_client.pod                      |   7 +-
 doc/apps/s_server.pod                      |   9 ++
 doc/apps/smime.pod                         |   4 +-
 doc/apps/verify.pod                        |  13 +++
 doc/crypto/X509_VERIFY_PARAM_set_flags.pod |   8 +-
 16 files changed, 172 insertions(+), 72 deletions(-)

diff --git a/apps/apps.c b/apps/apps.c
index 5b7aedc..6801238 100644
--- a/apps/apps.c
+++ b/apps/apps.c
@@ -2238,6 +2238,8 @@ int args_verify(char ***pargs, int *pargc,
         flags |= X509_V_FLAG_NOTIFY_POLICY;
     else if (!strcmp(arg, "-check_ss_sig"))
         flags |= X509_V_FLAG_CHECK_SS_SIGNATURE;
+    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 0cc4b46..d7645c0 100644
--- a/apps/cms.c
+++ b/apps/cms.c
@@ -581,6 +581,8 @@ int MAIN(int argc, char **argv)
                    "-CApath dir    trusted certificates directory\n");
         BIO_printf(bio_err, "-CAfile file   trusted certificates file\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 71def26..572f064 100644
--- a/apps/ocsp.c
+++ b/apps/ocsp.c
@@ -519,6 +519,8 @@ int MAIN(int argc, char **argv)
         BIO_printf(bio_err,
                    "-CAfile file         trusted certificates file\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 b9b7975..28737b6 100644
--- a/apps/s_client.c
+++ b/apps/s_client.c
@@ -323,6 +323,8 @@ static void sc_usage(void)
     BIO_printf(bio_err, " -CApath arg   - PEM format directory of CA's\n");
     BIO_printf(bio_err, " -CAfile arg   - PEM format file of CA's\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 7e501d2..b58e5e0 100644
--- a/apps/s_server.c
+++ b/apps/s_server.c
@@ -541,6 +541,8 @@ static void sv_usage(void)
     BIO_printf(bio_err, " -CApath arg   - PEM format directory of CA's\n");
     BIO_printf(bio_err, " -CAfile arg   - PEM format file of CA's\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 7b351f6..53e43c5 100644
--- a/apps/smime.c
+++ b/apps/smime.c
@@ -442,6 +442,8 @@ int MAIN(int argc, char **argv)
                    "-CApath dir    trusted certificates directory\n");
         BIO_printf(bio_err, "-CAfile file   trusted certificates file\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 7295c76..e29f9bb 100644
--- a/apps/verify.c
+++ b/apps/verify.c
@@ -227,7 +227,7 @@ int MAIN(int argc, char **argv)
     if (ret == 1) {
         BIO_printf(bio_err,
                    "usage: verify [-verbose] [-CApath path] [-CAfile file] [-purpose purpose] [-crl_check]");
-        BIO_printf(bio_err, " [-attime timestamp]");
+        BIO_printf(bio_err, " [-no_alt_chains] [-attime timestamp]");
 #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 559b5cd..29dd86c 100644
--- a/crypto/x509/x509_vfy.c
+++ b/crypto/x509/x509_vfy.c
@@ -151,11 +151,11 @@ static int x509_subject_cmp(X509 **a, X509 **b)
 
 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) {
@@ -224,85 +224,118 @@ 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 (ctx->check_issued(ctx, x, 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 (ctx->check_issued(ctx, x, 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;
-
-        /* If we are self signed, we break */
-        if (ctx->check_issued(ctx, x, x))
-            break;
-
-        ok = ctx->get_issuer(&xtmp, ctx, x);
+        /* 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 (ctx->check_issued(ctx, x, x))
+                break;
+            ok = ctx->get_issuer(&xtmp, ctx, x);
+            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++;
+        }
 
-        if (ok < 0)
-            return ok;
-        if (ok == 0)
-            break;
+        /*
+         * If we haven't got a least one certificate from our store then check
+         * if there is an alternative chain that could be used.  We only do this
+         * if the user hasn't switched off alternate chain checking
+         */
+        retry = 0;
+        if (j == ctx->last_untrusted &&
+            !(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++;
-    }
-
-    /* we now have our chain, lets check it... */
+    } while (retry);
 
     /* Is last certificate looked up self signed? */
     if (!ctx->check_issued(ctx, x, x)) {
diff --git a/crypto/x509/x509_vfy.h b/crypto/x509/x509_vfy.h
index 1f8c0ec..aacdf55 100644
--- a/crypto/x509/x509_vfy.h
+++ b/crypto/x509/x509_vfy.h
@@ -405,6 +405,12 @@ void X509_STORE_CTX_set_depth(X509_STORE_CTX *ctx, int depth);
 # define X509_V_FLAG_USE_DELTAS                  0x2000
 /* Check selfsigned CA signature */
 # define X509_V_FLAG_CHECK_SS_SIGNATURE          0x4000
+/*
+ * If the initial chain is not trusted, do not attempt to build an alternative
+ * chain. Alternate chain checking was introduced in 1.0.1n/1.0.2b. 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 75b6988..9a24082 100644
--- a/doc/apps/cms.pod
+++ b/doc/apps/cms.pod
@@ -35,6 +35,7 @@ B<openssl> B<cms>
 [B<-print>]
 [B<-CAfile file>]
 [B<-CApath dir>]
+[B<-no_alt_chains>]
 [B<-md digest>]
 [B<-[cipher]>]
 [B<-nointern>]
@@ -406,7 +407,7 @@ portion of a message so they may be included manually. If signing
 then many S/MIME mail clients check the signers certificate's email
 address matches that specified in the From: address.
 
-=item B<-purpose, -ignore_critical, -issuer_checks, -crl_check, -crl_check_all, -policy_check, -extended_crl, -x509_strict, -policy -check_ss_sig>
+=item B<-purpose, -ignore_critical, -issuer_checks, -crl_check, -crl_check_all, -policy_check, -extended_crl, -x509_strict, -policy -check_ss_sig -no_alt_chains>
 
 Set various certificate chain valiadition option. See the
 L<B<verify>|verify(1)> manual page for details.
@@ -614,4 +615,6 @@ 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.0.1n and 1.0.2b.
+
 =cut
diff --git a/doc/apps/ocsp.pod b/doc/apps/ocsp.pod
index 2372b37..fdb900c 100644
--- a/doc/apps/ocsp.pod
+++ b/doc/apps/ocsp.pod
@@ -29,6 +29,7 @@ B<openssl> B<ocsp>
 [B<-path>]
 [B<-CApath dir>]
 [B<-CAfile file>]
+[B<-no_alt_chains>]]
 [B<-VAfile file>]
 [B<-validity_period n>]
 [B<-status_age n>]
@@ -143,6 +144,10 @@ connection timeout to the OCSP responder in seconds
 file or pathname containing trusted CA certificates. These are used to verify
 the signature on the OCSP response.
 
+=item B<-no_alt_chains>
+
+See L<B<verify>|verify(1)> manual page for details.
+
 =item B<-verify_other file>
 
 file containing additional certificates to search when attempting to locate
@@ -379,3 +384,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.0.1n and 1.0.2b.
+
+=cut
diff --git a/doc/apps/s_client.pod b/doc/apps/s_client.pod
index b021c73..d92ec93 100644
--- a/doc/apps/s_client.pod
+++ b/doc/apps/s_client.pod
@@ -19,6 +19,7 @@ B<openssl> B<s_client>
 [B<-pass arg>]
 [B<-CApath directory>]
 [B<-CAfile filename>]
+[B<-no_alt_chains>]
 [B<-reconnect>]
 [B<-pause>]
 [B<-showcerts>]
@@ -116,7 +117,7 @@ also used when building the client certificate chain.
 A file containing trusted certificates to use during server authentication
 and to use when attempting to build the client certificate chain.
 
-=item B<-purpose, -ignore_critical, -issuer_checks, -crl_check, -crl_check_all, -policy_check, -extended_crl, -x509_strict, -policy -check_ss_sig>
+=item B<-purpose, -ignore_critical, -issuer_checks, -crl_check, -crl_check_all, -policy_check, -extended_crl, -x509_strict, -policy -check_ss_sig -no_alt_chains>
 
 Set various certificate chain valiadition option. See the
 L<B<verify>|verify(1)> manual page for details.
@@ -347,4 +348,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.0.1n and 1.0.2b.
+
 =cut
diff --git a/doc/apps/s_server.pod b/doc/apps/s_server.pod
index 2105b60..491038e 100644
--- a/doc/apps/s_server.pod
+++ b/doc/apps/s_server.pod
@@ -33,6 +33,7 @@ B<openssl> B<s_server>
 [B<-state>]
 [B<-CApath directory>]
 [B<-CAfile filename>]
+[B<-no_alt_chains>]
 [B<-nocert>]
 [B<-cipher cipherlist>]
 [B<-serverpref>]
@@ -178,6 +179,10 @@ and to use when attempting to build the server certificate chain. The list
 is also used in the list of acceptable client CAs passed to the client when
 a certificate is requested.
 
+=item B<-no_alt_chains>
+
+See the L<B<verify>|verify(1)> manual page for details.
+
 =item B<-state>
 
 prints out the SSL session states.
@@ -398,4 +403,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.0.1n and 1.0.2b.
+
 =cut
diff --git a/doc/apps/smime.pod b/doc/apps/smime.pod
index d39a59a..94a8823 100644
--- a/doc/apps/smime.pod
+++ b/doc/apps/smime.pod
@@ -15,6 +15,7 @@ B<openssl> B<smime>
 [B<-pk7out>]
 [B<-[cipher]>]
 [B<-in file>]
+[B<-no_alt_chains>]
 [B<-certfile file>]
 [B<-signer file>]
 [B<-recip  file>]
@@ -259,7 +260,7 @@ portion of a message so they may be included manually. If signing
 then many S/MIME mail clients check the signers certificate's email
 address matches that specified in the From: address.
 
-=item B<-purpose, -ignore_critical, -issuer_checks, -crl_check, -crl_check_all, -policy_check, -extended_crl, -x509_strict, -policy -check_ss_sig>
+=item B<-purpose, -ignore_critical, -issuer_checks, -crl_check, -crl_check_all, -policy_check, -extended_crl, -x509_strict, -policy -check_ss_sig -no_alt_chains>
 
 Set various options of certificate chain verification. See
 L<B<verify>|verify(1)> manual page for details.
@@ -441,5 +442,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.0.1n and 1.0.2b.
 
 =cut
diff --git a/doc/apps/verify.pod b/doc/apps/verify.pod
index 0c8e492..18eeee0 100644
--- a/doc/apps/verify.pod
+++ b/doc/apps/verify.pod
@@ -22,6 +22,7 @@ B<openssl> B<verify>
 [B<-extended_crl>]
 [B<-use_deltas>]
 [B<-policy_print>]
+[B<-no_alt_chains>]
 [B<-untrusted file>]
 [B<-help>]
 [B<-issuer_checks>]
@@ -108,6 +109,14 @@ Set policy variable inhibit-any-policy (see RFC5280).
 
 Set policy variable inhibit-policy-mapping (see RFC5280).
 
+=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 previous OpenSSL versions.
+
 =item B<-policy_print>
 
 Print out diagnostics related to policy processing.
@@ -409,4 +418,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.0.1n and 1.0.2b.
+
 =cut
diff --git a/doc/crypto/X509_VERIFY_PARAM_set_flags.pod b/doc/crypto/X509_VERIFY_PARAM_set_flags.pod
index 46cac2b..9d86d46 100644
--- a/doc/crypto/X509_VERIFY_PARAM_set_flags.pod
+++ b/doc/crypto/X509_VERIFY_PARAM_set_flags.pod
@@ -133,6 +133,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.0.1n and 1.0.2b.
+
 =head1 NOTES
 
 The above functions should be used to manipulate verification parameters
@@ -166,6 +172,6 @@ L<X509_verify_cert(3)|X509_verify_cert(3)>
 
 =head1 HISTORY
 
-TBA
+The B<X509_V_FLAG_NO_ALT_CHAINS> flag was added in OpenSSL 1.0.1n and 1.0.2b
 
 =cut


More information about the openssl-commits mailing list