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:33 UTC
(ofbiz-framework) branch trunk updated: Fixed: MultiTrustManager doing flat cert-equality checks instead of real X.509 chain validation (OFBIZ-13476) (#1545)
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 <mr...@gmail.com>
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;
}
}