This is an automated email from the ASF dual-hosted git repository.
coheigea pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ws-wss4j.git
The following commit(s) were added to refs/heads/master by this push:
new e923119c9 WSS-736 - Only remove security providers on cleanUp that
WSS4J registered (#767)
e923119c9 is described below
commit e923119c967c4c40e19e527db21b9bd9bd7e9f06
Author: Colm O hEigeartaigh <[email protected]>
AuthorDate: Tue Nov 3 07:01:13 2026 +0000
WSS-736 - Only remove security providers on cleanUp that WSS4J registered
(#767)
---
.../wss4j/common/crypto/WSProviderConfig.java | 68 +++++++++++++++-------
.../org/apache/wss4j/dom/engine/WSSConfig.java | 52 +++++++++++------
.../wss4j/dom/components/crypto/WSSConfigTest.java | 38 +++++++++++-
3 files changed, 119 insertions(+), 39 deletions(-)
diff --git
a/ws-security-common/src/main/java/org/apache/wss4j/common/crypto/WSProviderConfig.java
b/ws-security-common/src/main/java/org/apache/wss4j/common/crypto/WSProviderConfig.java
index acdae3796..20067bd20 100644
---
a/ws-security-common/src/main/java/org/apache/wss4j/common/crypto/WSProviderConfig.java
+++
b/ws-security-common/src/main/java/org/apache/wss4j/common/crypto/WSProviderConfig.java
@@ -25,6 +25,8 @@ import java.security.PrivilegedAction;
import java.security.PrivilegedExceptionAction;
import java.security.Provider;
import java.security.Security;
+import java.util.HashMap;
+import java.util.Map;
import org.apache.wss4j.common.util.FIPSUtils;
import org.apache.wss4j.common.util.Loader;
@@ -56,9 +58,12 @@ public final class WSProviderConfig {
*/
private static boolean staticallyInitialized;
- private static boolean santuarioProviderAdded;
- private static boolean bcProviderAdded;
- private static boolean tlProviderAdded;
+ /**
+ * The provider instances registered by this class, keyed by name. On
cleanUp only these
+ * instances are removed, so that a provider of the same name registered
by another copy
+ * of WSS4J (e.g. in another web application) is left alone.
+ */
+ private static final Map<String, Provider> ADDED_PROVIDERS = new
HashMap<>();
private WSProviderConfig() {
// complete
@@ -75,10 +80,6 @@ public final class WSProviderConfig {
return true;
}
});
-
- santuarioProviderAdded = true;
- bcProviderAdded = false;
- tlProviderAdded = false;
}
if (FIPSUtils.isFIPSEnabled()) {
//So far the in-JDK security provider in FIPS mode
@@ -99,7 +100,6 @@ public final class WSProviderConfig {
if (!staticallyInitialized) {
initializeResourceBundles();
setXmlSecIgnoreLineBreak();
- santuarioProviderAdded = addXMLDSigRIInternalProv;
if (addXMLDSigRIInternalProv) {
AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
public Boolean run() {
@@ -109,11 +109,12 @@ public final class WSProviderConfig {
});
}
- bcProviderAdded = addBCProv;
if (addBCProv) {
AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
public Boolean run() {
+ Provider existing = Security.getProvider("BC");
addJceProvider("BC",
"org.bouncycastle.jce.provider.BouncyCastleProvider");
+ recordAddedProvider("BC", existing);
return true;
}
});
@@ -133,11 +134,12 @@ public final class WSProviderConfig {
}
- tlProviderAdded = addTLProv;
if (addTLProv) {
AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
public Boolean run() {
+ Provider existing = Security.getProvider("TLSP");
ThreadLocalSecurityProvider.install();
+ recordAddedProvider("TLSP", existing);
return true;
}
});
@@ -148,18 +150,10 @@ public final class WSProviderConfig {
public static synchronized void cleanUp() {
if (staticallyInitialized) {
- if (santuarioProviderAdded) {
- Security.removeProvider("ApacheXMLDSig");
- santuarioProviderAdded = false;
- }
- if (bcProviderAdded) {
- Security.removeProvider("BC");
- bcProviderAdded = false;
- }
- if (tlProviderAdded) {
- Security.removeProvider("TLSP");
- tlProviderAdded = false;
+ for (Map.Entry<String, Provider> entry :
ADDED_PROVIDERS.entrySet()) {
+ removeJceProvider(entry.getKey(), entry.getValue());
}
+ ADDED_PROVIDERS.clear();
staticallyInitialized = false;
}
@@ -212,8 +206,40 @@ public final class WSProviderConfig {
}
private static void addXMLDSigRIInternal() {
+ Provider existing = Security.getProvider("ApacheXMLDSig");
Security.removeProvider("ApacheXMLDSig");
addJceProvider("ApacheXMLDSig", SantuarioUtil.getSantuarioProvider());
+ recordAddedProvider("ApacheXMLDSig", existing);
+ }
+
+ private static void recordAddedProvider(String name, Provider previous) {
+ Provider current = Security.getProvider(name);
+ if (current != null && current != previous) {
+ ADDED_PROVIDERS.put(name, current);
+ }
+ }
+
+ /**
+ * Remove the JCE security provider registered under the given name, but
only if it is the
+ * given provider instance. A provider of the same name registered by
someone else, e.g. by
+ * a copy of WSS4J loaded by another web application's class loader, is
left in place.
+ *
+ * @param name
+ * The name of the provider
+ * @param provider
+ * The provider instance that was registered by the caller
+ * @return true if the provider was removed
+ */
+ public static boolean removeJceProvider(String name, Provider provider) {
+ Provider current = Security.getProvider(name);
+ if (current != null && current == provider) {
+ Security.removeProvider(name);
+ return true;
+ }
+ if (current != null) {
+ LOG.debug("Not removing provider {} as it was not registered by
this instance of WSS4J", name);
+ }
+ return false;
}
private static void initializeResourceBundles() {
diff --git
a/ws-security-dom/src/main/java/org/apache/wss4j/dom/engine/WSSConfig.java
b/ws-security-dom/src/main/java/org/apache/wss4j/dom/engine/WSSConfig.java
index 733c99eff..c13201bad 100644
--- a/ws-security-dom/src/main/java/org/apache/wss4j/dom/engine/WSSConfig.java
+++ b/ws-security-dom/src/main/java/org/apache/wss4j/dom/engine/WSSConfig.java
@@ -21,6 +21,7 @@ package org.apache.wss4j.dom.engine;
import java.security.AccessController;
import java.security.PrivilegedAction;
+import java.security.Provider;
import java.security.Security;
import java.util.HashMap;
import java.util.Map;
@@ -253,6 +254,13 @@ public final class WSSConfig {
*/
private static boolean staticallyInitialized = false;
+ /**
+ * The provider instances registered by this class, keyed by name. On
cleanUp only these
+ * instances are removed, so that a provider of the same name registered
by another copy
+ * of WSS4J (e.g. in another web application) is left alone.
+ */
+ private static final Map<String, Provider> ADDED_PROVIDERS = new
HashMap<>();
+
/**
* This allows the user to specify a different time than that of the
current System time.
*/
@@ -318,24 +326,18 @@ public final class WSSConfig {
if (addJceProviders) {
AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
public Boolean run() {
- Security.removeProvider("STRTransform");
- WSProviderConfig.appendJceProvider(
+ replaceJceProvider(
"STRTransform",
new
org.apache.wss4j.dom.transform.STRTransformProvider()
);
-
-
Security.removeProvider("AttachmentContentSignatureTransform");
- WSProviderConfig.appendJceProvider(
- "AttachmentContentSignatureTransform",
- new
AttachmentContentSignatureTransformProvider()
+ replaceJceProvider(
+ "AttachmentContentSignatureTransform",
+ new AttachmentContentSignatureTransformProvider()
);
-
-
Security.removeProvider("AttachmentCompleteSignatureTransform");
- WSProviderConfig.appendJceProvider(
- "AttachmentCompleteSignatureTransform",
- new
AttachmentCompleteSignatureTransformProvider()
+ replaceJceProvider(
+ "AttachmentCompleteSignatureTransform",
+ new AttachmentCompleteSignatureTransformProvider()
);
-
return true;
}
});
@@ -347,17 +349,33 @@ public final class WSSConfig {
public static synchronized void cleanUp() {
if (staticallyInitialized) {
- if (addJceProviders) {
- Security.removeProvider("STRTransform");
- Security.removeProvider("AttachmentContentSignatureTransform");
-
Security.removeProvider("AttachmentCompleteSignatureTransform");
+ for (Map.Entry<String, Provider> entry :
ADDED_PROVIDERS.entrySet()) {
+ WSProviderConfig.removeJceProvider(entry.getKey(),
entry.getValue());
}
+ ADDED_PROVIDERS.clear();
WSProviderConfig.cleanUp();
staticallyInitialized = false;
}
}
+ private static void replaceJceProvider(String name, Provider provider) {
+ Provider existing = Security.getProvider(name);
+ if (existing != null
+ && existing.getClass().getClassLoader() !=
provider.getClass().getClassLoader()) {
+ LOG.warn("The security provider {} has already been registered by
a different class loader "
+ + "and will be replaced. If WSS4J is deployed in more than one
web application in the same "
+ + "JVM, the other application may fail to use it. Consider
deploying WSS4J in a class loader "
+ + "shared by all applications, e.g. the container's lib
directory.", name);
+ }
+ Security.removeProvider(name);
+ WSProviderConfig.appendJceProvider(name, provider);
+ Provider current = Security.getProvider(name);
+ if (current != null && current != existing) {
+ ADDED_PROVIDERS.put(name, current);
+ }
+ }
+
/**
* @return a new WSSConfig instance configured with the default values
*/
diff --git
a/ws-security-dom/src/test/java/org/apache/wss4j/dom/components/crypto/WSSConfigTest.java
b/ws-security-dom/src/test/java/org/apache/wss4j/dom/components/crypto/WSSConfigTest.java
index d46c5f739..fb897a831 100644
---
a/ws-security-dom/src/test/java/org/apache/wss4j/dom/components/crypto/WSSConfigTest.java
+++
b/ws-security-dom/src/test/java/org/apache/wss4j/dom/components/crypto/WSSConfigTest.java
@@ -19,14 +19,18 @@
package org.apache.wss4j.dom.components.crypto;
+import java.security.Provider;
import java.security.Security;
+import org.apache.wss4j.common.crypto.SantuarioUtil;
import org.apache.wss4j.common.crypto.WSProviderConfig;
import org.apache.wss4j.dom.engine.WSSConfig;
+import
org.apache.wss4j.dom.transform.AttachmentContentSignatureTransformProvider;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertSame;
/**
* Test loading and removing security providers via WSSConfig
@@ -78,4 +82,36 @@ public class WSSConfigTest {
}
-}
\ No newline at end of file
+ /**
+ * WSS-660: cleanUp must not remove providers that were registered by
someone else, e.g.
+ * by a copy of WSS4J deployed in another web application, after we
registered ours.
+ */
+ @Test
+ public void testCleanUpLeavesForeignProviders() {
+ WSSConfig.cleanUp();
+ WSSConfig.init();
+
+ // Simulate another copy of WSS4J replacing the providers
+ Provider otherTransformProvider = new
AttachmentContentSignatureTransformProvider();
+ Security.removeProvider("AttachmentContentSignatureTransform");
+ Security.addProvider(otherTransformProvider);
+
+ Provider otherSantuarioProvider = SantuarioUtil.getSantuarioProvider();
+ Security.removeProvider("ApacheXMLDSig");
+ Security.addProvider(otherSantuarioProvider);
+
+ try {
+ WSSConfig.cleanUp();
+
+ assertSame(otherTransformProvider,
Security.getProvider("AttachmentContentSignatureTransform"));
+ assertSame(otherSantuarioProvider,
Security.getProvider("ApacheXMLDSig"));
+ // The providers that were still ours are removed
+ assertNull(Security.getProvider("STRTransform"));
+
assertNull(Security.getProvider("AttachmentCompleteSignatureTransform"));
+ } finally {
+ Security.removeProvider("AttachmentContentSignatureTransform");
+ Security.removeProvider("ApacheXMLDSig");
+ }
+ }
+
+}