Commit 8da3880874 for openssl.org

commit 8da3880874acaac2e338665f216e430f78f976f1
Author: Mounir IDRASSI <mounir.idrassi@idrix.fr>
Date:   Tue Aug 4 12:11:39 2026 +0900

    apps/x509.c: failing exit status on every failure path reaching err:

    With -multi, a later certificate failure could return success after an
    earlier certificate succeeded because ret retained the earlier result
    on reaching err:.

    Set ret = 1 at err: so every path reaching it reports failure. Paths
    bypassing err: remain unchanged, including the pre-existing
    X509_VERIFY_PARAM_new() failure under -checkend, which will be addressed
    separately.

    Add a regression test using -multi -checkhost with a two-certificate
    chain whose second certificate fails.

    Fixes #32189

    Reviewed-by: Jakub Zelenka <jakub.zelenka@openssl.foundation>
    Reviewed-by: Todd Short <todd.short@me.com>
    Merge-date: Mon Sep  7 14:01:00 2026
    Merged-from: https://github.com/openssl/openssl/pull/32190

diff --git a/apps/x509.c b/apps/x509.c
index 867961e61d..3fd41465e2 100644
--- a/apps/x509.c
+++ b/apps/x509.c
@@ -1266,6 +1266,8 @@ end_cert_loop:
     goto end;

 err:
+    /* Every path reaching this label is a failure path */
+    ret = 1;
     ERR_print_errors(bio_err);

 end:
diff --git a/test/recipes/25-test_x509.t b/test/recipes/25-test_x509.t
index ce29004782..f4610a9aa5 100644
--- a/test/recipes/25-test_x509.t
+++ b/test/recipes/25-test_x509.t
@@ -17,7 +17,7 @@ use File::Compare qw/compare_text/;

 setup("test_x509");

-plan tests => 155;
+plan tests => 156;

 # Prevent MSys2 filename munging for arguments that look like file paths but
 # aren't
@@ -815,6 +815,22 @@ ok(!run(app(["openssl", "x509", "-multi", "-checkend",
 ok(!run(app(["openssl", "x509", "-checkend", "60", "-in", $c_key])),
     "Bad parse with -checkend returns non-zero");

+# Regression test: with -multi, a failure on a later certificate must set
+# a failing exit status even after an earlier certificate succeeded, i.e.
+# the per-certificate success status must not leak into the final result.
+subtest "x509 -multi later failure is not masked by earlier success" => sub {
+    plan tests => 1;
+
+    # goodcn2-chain.pem holds two certificates without subjectAltName, so
+    # -checkhost falls back to the CN: "www.good.org" matches the first
+    # certificate ("CN=www.good.org") but not the second ("CN=Test NC CA 1")
+    my $chain = srctop_file(@certs, "goodcn2-chain.pem");
+
+    ok(!run(app(["openssl", "x509", "-multi", "-in", $chain, "-noout",
+                 "-checkhost", "www.good.org"])),
+       "-multi returns non-zero when a later certificate fails -checkhost");
+};
+
 # Signing using DER-encoded key and CA cert/key inputs,
 # exercising -keyform, -CAform and -CAkeyform
 subtest 'x509 signing with DER -keyform, -CAform and -CAkeyform' => sub {