You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ofbiz.apache.org by mr...@apache.org on 2026/08/07 05:39:56 UTC

(ofbiz-framework) branch release24.09 updated: Fixed: MultiTrustManager doing flat cert-equality checks instead of real X.509 chain validation (OFBIZ-13476)

This is an automated email from the ASF dual-hosted git repository.

mridulpathak pushed a commit to branch release24.09
in repository https://gitbox.apache.org/repos/asf/ofbiz-framework.git


The following commit(s) were added to refs/heads/release24.09 by this push:
     new 0324d41362 Fixed: MultiTrustManager doing flat cert-equality checks instead of real X.509 chain validation (OFBIZ-13476)
0324d41362 is described below

commit 0324d413627d6f07c6a02e672a2cdcc5bcac4c0b
Author: Mridul Pathak <mr...@gmail.com>
AuthorDate: Fri Aug 7 11:09:51 2026 +0530

    Fixed: MultiTrustManager doing flat cert-equality checks instead of real X.509 chain validation (OFBIZ-13476)
    
    MultiTrustManager.isTrusted() only accepted certificates that were byte-identical to one already stored in a configured trust KeyStore, instead of validating the certificate chain up to a trusted root. This rejected any real, externally-issued certificate (e.g. Google Trust Services certs used by the OAuth2 endpoints surfaced in OFBIZ-13474) even when the correct root CA was present and trusted. checkClientTrusted/checkServerTrusted now delegate to a standard TrustManagerFactory-backe [...]
---
 .../apache/ofbiz/base/util/MultiTrustManager.java  | 69 ++++++++++++++--------
 1 file changed, 46 insertions(+), 23 deletions(-)

diff --git a/framework/base/src/main/java/org/apache/ofbiz/base/util/MultiTrustManager.java b/framework/base/src/main/java/org/apache/ofbiz/base/util/MultiTrustManager.java
index 26b53f42fb..3ce5e43131 100644
--- a/framework/base/src/main/java/org/apache/ofbiz/base/util/MultiTrustManager.java
+++ b/framework/base/src/main/java/org/apache/ofbiz/base/util/MultiTrustManager.java
@@ -19,6 +19,8 @@
 
 package org.apache.ofbiz.base.util;
 
+import java.io.IOException;
+import java.security.GeneralSecurityException;
 import java.security.KeyStore;
 import java.security.KeyStoreException;
 import java.security.cert.Certificate;
@@ -28,6 +30,8 @@ import java.util.Enumeration;
 import java.util.LinkedList;
 import java.util.List;
 
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
 import javax.net.ssl.X509TrustManager;
 
 /**
@@ -67,21 +71,37 @@ public class MultiTrustManager implements X509TrustManager {
 
     @Override
     public void checkClientTrusted(X509Certificate[] certs, String alg) throws CertificateException {
-        if (isTrusted(certs)) {
+        CertificateException trustFailure;
+        try {
+            getDelegateTrustManager().checkClientTrusted(certs, alg);
             return;
+        } catch (CertificateException e) {
+            trustFailure = e;
+        } catch (RuntimeException e) {
+            // The JDK's own X509TrustManager implementation can throw an unchecked exception
+            // (e.g. when there are no trust anchors at all) instead of a CertificateException.
+            trustFailure = new CertificateException(e);
         }
         if (!"true".equals(UtilProperties.getPropertyValue("certificate", "client.all-trusted", "true"))) {
-            throw new CertificateException("No trusted certificate found");
+            throw trustFailure;
         }
     }
 
     @Override
     public void checkServerTrusted(X509Certificate[] certs, String alg) throws CertificateException {
-        if (isTrusted(certs)) {
+        CertificateException trustFailure;
+        try {
+            getDelegateTrustManager().checkServerTrusted(certs, alg);
             return;
+        } catch (CertificateException e) {
+            trustFailure = e;
+        } catch (RuntimeException e) {
+            // The JDK's own X509TrustManager implementation can throw an unchecked exception
+            // (e.g. when there are no trust anchors at all) instead of a CertificateException.
+            trustFailure = new CertificateException(e);
         }
         if (!"true".equals(UtilProperties.getPropertyValue("certificate", "server.all-trusted", "true"))) {
-            throw new CertificateException("No trusted certificate found");
+            throw trustFailure;
         }
     }
 
@@ -123,28 +143,31 @@ public class MultiTrustManager implements X509TrustManager {
     }
 
     /**
-     * Is trusted boolean.
-     * @param cert the cert
-     * @return the boolean
+     * Builds a standard {@link X509TrustManager} backed by a {@link TrustManagerFactory}, initialized
+     * with a KeyStore containing every trust anchor currently returned by {@link #getAcceptedIssuers()}
+     * (i.e. the system truststore plus every configured component truststore, unchanged). Delegating to
+     * this real trust manager gives genuine certificate path validation instead of a flat equality check.
+     * @return the delegate trust manager
      */
-    private boolean isTrusted(X509Certificate[] cert) {
-        if (cert != null) {
-            X509Certificate[] issuers = this.getAcceptedIssuers();
-            for (X509Certificate issuer : issuers) {
-                for (X509Certificate c : cert) {
-                    if (Debug.verboseOn()) {
-                        Debug.logVerbose("--- Checking cert: " + issuer.getSubjectX500Principal() + " vs " + c.getSubjectX500Principal(), MODULE);
-                    }
-                    if (issuer.equals(c)) {
-                        if (Debug.verboseOn()) {
-                            Debug.logVerbose("--- Found trusted cert: " + issuer.getSerialNumber().toString(16) + " : "
-                                    + issuer.getSubjectX500Principal(), MODULE);
-                        }
-                        return true;
-                    }
+    private X509TrustManager getDelegateTrustManager() throws CertificateException {
+        try {
+            KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
+            trustStore.load(null, null);
+            int i = 0;
+            for (X509Certificate issuer : getAcceptedIssuers()) {
+                trustStore.setCertificateEntry("trust-anchor-" + i++, issuer);
+            }
+
+            TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
+            tmf.init(trustStore);
+            for (TrustManager tm : tmf.getTrustManagers()) {
+                if (tm instanceof X509TrustManager) {
+                    return (X509TrustManager) tm;
                 }
             }
+            throw new CertificateException("No X509TrustManager available from TrustManagerFactory");
+        } catch (GeneralSecurityException | IOException e) {
+            throw new CertificateException(e);
         }
-        return false;
     }
 }