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

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


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

commit 460b031756875e6234b313f38744fa5ec02ee669
Author: Mridul Pathak <[email protected]>
AuthorDate: Fri Aug 7 11:09:28 2026 +0530

    Fixed: MultiTrustManager doing flat cert-equality checks instead of real 
X.509 chain validation (OFBIZ-13476) (#1545)
    
    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;
     }
 }

Reply via email to