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;
}
}