You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by co...@apache.org on 2012/03/09 16:50:53 UTC
svn commit: r1298889 - in /cxf/branches/2.5.x-fixes: parent/ rt/ws/security/
rt/ws/security/src/main/java/org/apache/cxf/ws/security/
rt/ws/security/src/main/java/org/apache/cxf/ws/security/cache/
rt/ws/security/src/main/java/org/apache/cxf/ws/security...
Author: coheigea
Date: Fri Mar 9 15:50:52 2012
New Revision: 1298889
URL: http://svn.apache.org/viewvc?rev=1298889&view=rev
Log:
[CXF-1636] - Adding support for caching UsernameToken nonces and Timestamps
Added:
cxf/branches/2.5.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/cache/
cxf/branches/2.5.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/cache/EHCacheReplayCache.java
cxf/branches/2.5.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/cache/EHCacheReplayCacheFactory.java
cxf/branches/2.5.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/cache/MemoryReplayCacheFactory.java
cxf/branches/2.5.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/cache/ReplayCacheFactory.java
cxf/branches/2.5.x-fixes/rt/ws/security/src/main/resources/cxf-ehcache.xml
cxf/branches/2.5.x-fixes/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/ut/SecurityHeaderCacheInterceptor.java
Modified:
cxf/branches/2.5.x-fixes/parent/pom.xml
cxf/branches/2.5.x-fixes/rt/ws/security/pom.xml
cxf/branches/2.5.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/SecurityConstants.java
cxf/branches/2.5.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/WSS4JInInterceptor.java
cxf/branches/2.5.x-fixes/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/ut/UsernameTokenTest.java
cxf/branches/2.5.x-fixes/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/x509/X509TokenTest.java
Modified: cxf/branches/2.5.x-fixes/parent/pom.xml
URL: http://svn.apache.org/viewvc/cxf/branches/2.5.x-fixes/parent/pom.xml?rev=1298889&r1=1298888&r2=1298889&view=diff
==============================================================================
--- cxf/branches/2.5.x-fixes/parent/pom.xml (original)
+++ cxf/branches/2.5.x-fixes/parent/pom.xml Fri Mar 9 15:50:52 2012
@@ -125,7 +125,7 @@
<cxf.cglib.bundle.version>2.2_1</cxf.cglib.bundle.version>
<cxf.fastinfoset.bundle.version>1.2.7_3</cxf.fastinfoset.bundle.version>
<cxf.hazelcast.version>1.9.4</cxf.hazelcast.version>
- <cxf.ehcache.version>2.4.4</cxf.ehcache.version>
+ <cxf.ehcache.version>2.5.1</cxf.ehcache.version>
<!-- various OSGi related versions -->
<cxf.aries.version>0.3.1</cxf.aries.version>
Modified: cxf/branches/2.5.x-fixes/rt/ws/security/pom.xml
URL: http://svn.apache.org/viewvc/cxf/branches/2.5.x-fixes/rt/ws/security/pom.xml?rev=1298889&r1=1298888&r2=1298889&view=diff
==============================================================================
--- cxf/branches/2.5.x-fixes/rt/ws/security/pom.xml (original)
+++ cxf/branches/2.5.x-fixes/rt/ws/security/pom.xml Fri Mar 9 15:50:52 2012
@@ -72,7 +72,12 @@
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
-
+ <dependency>
+ <groupId>net.sf.ehcache</groupId>
+ <artifactId>ehcache-core</artifactId>
+ <version>${cxf.ehcache.version}</version>
+ <scope>compile</scope>
+ </dependency>
<dependency>
<groupId>org.apache.ws.security</groupId>
<artifactId>wss4j</artifactId>
Modified: cxf/branches/2.5.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/SecurityConstants.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.5.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/SecurityConstants.java?rev=1298889&r1=1298888&r2=1298889&view=diff
==============================================================================
--- cxf/branches/2.5.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/SecurityConstants.java (original)
+++ cxf/branches/2.5.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/SecurityConstants.java Fri Mar 9 15:50:52 2012
@@ -138,6 +138,43 @@ public final class SecurityConstants {
public static final String CACHE_ISSUED_TOKEN_IN_ENDPOINT =
"ws-security.cache.issued.token.in.endpoint";
+ /**
+ * Set this to "false" to not cache UsernameToken nonces. The default value is "true" for
+ * message recipients, and "false" for message initiators. Set it to true to cache for
+ * both cases.
+ */
+ public static final String ENABLE_NONCE_CACHE =
+ "ws-security.enable.nonce.cache";
+
+ /**
+ * This holds a reference to a ReplayCache instance used to cache UsernameToken nonces. The
+ * default instance that is used is the EHCacheReplayCache.
+ */
+ public static final String NONCE_CACHE_INSTANCE =
+ "ws-security.nonce.cache.instance";
+
+ /**
+ * Set this to "false" to not cache Timestamp Created Strings (these are only cached in
+ * conjunction with a message Signature). The default value is "true" for message recipients,
+ * and "false" for message initiators. Set it to true to cache for both cases.
+ */
+ public static final String ENABLE_TIMESTAMP_CACHE =
+ "ws-security.enable.timestamp.cache";
+
+ /**
+ * This holds a reference to a ReplayCache instance used to cache Timestamp Created Strings. The
+ * default instance that is used is the EHCacheReplayCache.
+ */
+ public static final String TIMESTAMP_CACHE_INSTANCE =
+ "ws-security.timestamp.cache.instance";
+
+ /**
+ * Set this property to point to a configuration file for the underlying caching implementation.
+ * The default configuration file that is used is cxf-ehcache.xml in this module.
+ */
+ public static final String CACHE_CONFIG_FILE =
+ "ws-security.cache.config.file";
+
public static final Set<String> ALL_PROPERTIES;
static {
@@ -152,7 +189,9 @@ public final class SecurityConstants {
SIGNATURE_TOKEN_VALIDATOR, IS_BSP_COMPLIANT, TIMESTAMP_FUTURE_TTL,
BST_TOKEN_VALIDATOR, SAML_CALLBACK_HANDLER, STS_TOKEN_ON_BEHALF_OF,
KERBEROS_CLIENT, SCT_TOKEN_VALIDATOR, CACHE_ISSUED_TOKEN_IN_ENDPOINT,
- KERBEROS_JAAS_CONTEXT_NAME, KERBEROS_SPN, SPNEGO_CLIENT_ACTION
+ KERBEROS_JAAS_CONTEXT_NAME, KERBEROS_SPN, SPNEGO_CLIENT_ACTION,
+ ENABLE_NONCE_CACHE, NONCE_CACHE_INSTANCE, ENABLE_TIMESTAMP_CACHE,
+ TIMESTAMP_CACHE_INSTANCE, CACHE_CONFIG_FILE
}));
ALL_PROPERTIES = Collections.unmodifiableSet(s);
}
Added: cxf/branches/2.5.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/cache/EHCacheReplayCache.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.5.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/cache/EHCacheReplayCache.java?rev=1298889&view=auto
==============================================================================
--- cxf/branches/2.5.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/cache/EHCacheReplayCache.java (added)
+++ cxf/branches/2.5.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/cache/EHCacheReplayCache.java Fri Mar 9 15:50:52 2012
@@ -0,0 +1,98 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.ws.security.cache;
+
+import java.net.URL;
+
+import net.sf.ehcache.Cache;
+import net.sf.ehcache.CacheManager;
+import net.sf.ehcache.Element;
+
+import org.apache.ws.security.cache.ReplayCache;
+
+/**
+ * An in-memory EHCache implementation of the ReplayCache interface.
+ */
+public class EHCacheReplayCache implements ReplayCache {
+
+ public static final long DEFAULT_TTL = 3600L;
+ private Cache cache;
+ private CacheManager cacheManager;
+
+ public EHCacheReplayCache(String key, URL configFileURL) {
+ if (cacheManager == null) {
+ if (configFileURL == null) {
+ cacheManager = CacheManager.create();
+ } else {
+ cacheManager = CacheManager.create(configFileURL);
+ }
+ }
+ if (!cacheManager.cacheExists(key)) {
+ cache = new Cache(key, 50000, true, false, DEFAULT_TTL, DEFAULT_TTL);
+ cacheManager.addCache(cache);
+ } else {
+ cache = cacheManager.getCache(key);
+ }
+ }
+
+ /**
+ * Add the given identifier to the cache. It will be cached for a default amount of time.
+ * @param identifier The identifier to be added
+ */
+ public void add(String identifier) {
+ add(identifier, DEFAULT_TTL);
+ }
+
+ /**
+ * Add the given identifier to the cache to be cached for the given time
+ * @param identifier The identifier to be added
+ * @param timeToLive The length of time to cache the Identifier in seconds
+ */
+ public void add(String identifier, long timeToLive) {
+ if (identifier == null || "".equals(identifier)) {
+ return;
+ }
+
+ int ttl = (int)timeToLive;
+ if (timeToLive != (long)ttl) {
+ // Default to 60 minutes
+ ttl = 3600;
+ }
+
+ cache.put(new Element(identifier, identifier, false, ttl, ttl));
+ }
+
+ /**
+ * Return true if the given identifier is contained in the cache
+ * @param identifier The identifier to check
+ */
+ public boolean contains(String identifier) {
+ Element element = cache.get(identifier);
+ if (element != null) {
+ if (cache.isExpired(element)) {
+ cache.remove(identifier);
+ return false;
+ }
+ return true;
+ }
+ return false;
+ }
+
+}
Added: cxf/branches/2.5.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/cache/EHCacheReplayCacheFactory.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.5.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/cache/EHCacheReplayCacheFactory.java?rev=1298889&view=auto
==============================================================================
--- cxf/branches/2.5.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/cache/EHCacheReplayCacheFactory.java (added)
+++ cxf/branches/2.5.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/cache/EHCacheReplayCacheFactory.java Fri Mar 9 15:50:52 2012
@@ -0,0 +1,61 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.ws.security.cache;
+
+import java.io.IOException;
+import java.net.URL;
+
+import org.apache.cxf.Bus;
+import org.apache.cxf.common.classloader.ClassLoaderUtils;
+import org.apache.cxf.message.Message;
+import org.apache.cxf.resource.ResourceManager;
+import org.apache.cxf.ws.security.SecurityConstants;
+import org.apache.ws.security.cache.ReplayCache;
+
+/**
+ * A factory to return an EHCacheReplayCache instance.
+ */
+public class EHCacheReplayCacheFactory extends ReplayCacheFactory {
+
+ public ReplayCache newReplayCache(String key, Message message) {
+ URL configFileURL = getConfigFileURL(message);
+ if (configFileURL == null) {
+ String defaultConfigFile = "cxf-ehcache.xml";
+ ResourceManager rm = message.getExchange().get(Bus.class).getExtension(ResourceManager.class);
+ configFileURL = rm.resolveResource(defaultConfigFile, URL.class);
+ try {
+ if (configFileURL == null) {
+ configFileURL =
+ ClassLoaderUtils.getResource(defaultConfigFile, EHCacheReplayCacheFactory.class);
+ }
+ if (configFileURL == null) {
+ configFileURL = new URL(defaultConfigFile);
+ }
+ } catch (IOException e) {
+ // Do nothing
+ }
+ }
+ if (configFileURL != null) {
+ message.setContextualProperty(SecurityConstants.CACHE_CONFIG_FILE, configFileURL);
+ }
+ return new EHCacheReplayCache(key, configFileURL);
+ }
+
+}
Added: cxf/branches/2.5.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/cache/MemoryReplayCacheFactory.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.5.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/cache/MemoryReplayCacheFactory.java?rev=1298889&view=auto
==============================================================================
--- cxf/branches/2.5.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/cache/MemoryReplayCacheFactory.java (added)
+++ cxf/branches/2.5.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/cache/MemoryReplayCacheFactory.java Fri Mar 9 15:50:52 2012
@@ -0,0 +1,35 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.ws.security.cache;
+
+import org.apache.cxf.message.Message;
+import org.apache.ws.security.cache.MemoryReplayCache;
+import org.apache.ws.security.cache.ReplayCache;
+
+/**
+ * A factory to return a MemoryReplayCache instance.
+ */
+public class MemoryReplayCacheFactory extends ReplayCacheFactory {
+
+ public ReplayCache newReplayCache(String key, Message message) {
+ return new MemoryReplayCache();
+ }
+
+}
Added: cxf/branches/2.5.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/cache/ReplayCacheFactory.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.5.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/cache/ReplayCacheFactory.java?rev=1298889&view=auto
==============================================================================
--- cxf/branches/2.5.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/cache/ReplayCacheFactory.java (added)
+++ cxf/branches/2.5.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/cache/ReplayCacheFactory.java Fri Mar 9 15:50:52 2012
@@ -0,0 +1,89 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.ws.security.cache;
+
+import java.io.IOException;
+import java.net.URL;
+
+import org.apache.cxf.Bus;
+import org.apache.cxf.common.classloader.ClassLoaderUtils;
+import org.apache.cxf.message.Message;
+import org.apache.cxf.resource.ResourceManager;
+import org.apache.cxf.ws.security.SecurityConstants;
+import org.apache.ws.security.cache.ReplayCache;
+
+/**
+ * An abstract factory to return a ReplayCache instance. It returns an EHCacheReplayCacheFactory
+ * if EH-Cache is available. Otherwise it returns a MemoryReplayCacheFactory.
+ */
+public abstract class ReplayCacheFactory {
+
+ private static boolean ehCacheInstalled;
+
+ static {
+ try {
+ Class<?> cacheManagerClass =
+ ClassLoaderUtils.loadClass("net.sf.ehcache.CacheManager", ReplayCacheFactory.class);
+ if (cacheManagerClass != null) {
+ ehCacheInstalled = true;
+ }
+ } catch (Exception e) {
+ //ignore
+ }
+ }
+
+ protected static synchronized boolean isEhCacheInstalled() {
+ return ehCacheInstalled;
+ }
+
+ public static ReplayCacheFactory newInstance() {
+ if (isEhCacheInstalled()) {
+ return new EHCacheReplayCacheFactory();
+ }
+
+ return new MemoryReplayCacheFactory();
+ }
+
+ public abstract ReplayCache newReplayCache(String key, Message message);
+
+ protected URL getConfigFileURL(Message message) {
+ Object o = message.getContextualProperty(SecurityConstants.CACHE_CONFIG_FILE);
+ if (o instanceof String) {
+ URL url = null;
+ ResourceManager rm = message.getExchange().get(Bus.class).getExtension(ResourceManager.class);
+ url = rm.resolveResource((String)o, URL.class);
+ try {
+ if (url == null) {
+ url = ClassLoaderUtils.getResource((String)o, ReplayCacheFactory.class);
+ }
+ if (url == null) {
+ url = new URL((String)o);
+ }
+ return url;
+ } catch (IOException e) {
+ // Do nothing
+ }
+ } else if (o instanceof URL) {
+ return (URL)o;
+ }
+ return null;
+ }
+
+}
Modified: cxf/branches/2.5.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/WSS4JInInterceptor.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.5.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/WSS4JInInterceptor.java?rev=1298889&r1=1298888&r2=1298889&view=diff
==============================================================================
--- cxf/branches/2.5.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/WSS4JInInterceptor.java (original)
+++ cxf/branches/2.5.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/WSS4JInInterceptor.java Fri Mar 9 15:50:52 2012
@@ -56,8 +56,10 @@ import org.apache.cxf.message.MessageUti
import org.apache.cxf.phase.Phase;
import org.apache.cxf.phase.PhaseInterceptor;
import org.apache.cxf.security.SecurityContext;
+import org.apache.cxf.service.model.EndpointInfo;
import org.apache.cxf.staxutils.StaxUtils;
import org.apache.cxf.ws.security.SecurityConstants;
+import org.apache.cxf.ws.security.cache.ReplayCacheFactory;
import org.apache.cxf.ws.security.tokenstore.SecurityToken;
import org.apache.cxf.ws.security.tokenstore.TokenStore;
import org.apache.ws.security.CustomTokenPrincipal;
@@ -68,6 +70,7 @@ import org.apache.ws.security.WSSConfig;
import org.apache.ws.security.WSSecurityEngine;
import org.apache.ws.security.WSSecurityEngineResult;
import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.cache.ReplayCache;
import org.apache.ws.security.components.crypto.Crypto;
import org.apache.ws.security.handler.RequestData;
import org.apache.ws.security.handler.WSHandlerConstants;
@@ -236,6 +239,18 @@ public class WSS4JInInterceptor extends
if (passwordTypeStrict == null) {
setProperty(WSHandlerConstants.PASSWORD_TYPE_STRICT, "true");
}
+
+ // Configure replay caching
+ ReplayCache nonceCache =
+ getReplayCache(
+ msg, SecurityConstants.ENABLE_NONCE_CACHE, SecurityConstants.NONCE_CACHE_INSTANCE
+ );
+ reqData.setNonceReplayCache(nonceCache);
+ ReplayCache timestampCache =
+ getReplayCache(
+ msg, SecurityConstants.ENABLE_TIMESTAMP_CACHE, SecurityConstants.TIMESTAMP_CACHE_INSTANCE
+ );
+ reqData.setTimestampReplayCache(timestampCache);
/*
* Get and check the Signature specific parameters first because
@@ -644,7 +659,54 @@ public class WSS4JInInterceptor extends
return ret;
}
-
+ /**
+ * Get a ReplayCache instance. It first checks to see whether caching has been explicitly
+ * enabled or disabled via the booleanKey argument. If it has been set to false then no
+ * replay caching is done (for this booleanKey). If it has not been specified, then caching
+ * is enabled only if we are not the initiator of the exchange. If it has been specified, then
+ * caching is enabled.
+ *
+ * It tries to get an instance of ReplayCache via the instanceKey argument from a
+ * contextual property, and failing that the message exchange. If it can't find any, then it
+ * defaults to using an EH-Cache instance and stores that on the message exchange.
+ */
+ protected ReplayCache getReplayCache(
+ SoapMessage message, String booleanKey, String instanceKey
+ ) {
+ boolean specified = false;
+ Object o = message.getContextualProperty(booleanKey);
+ if (o != null) {
+ if (!MessageUtils.isTrue(o)) {
+ return null;
+ }
+ specified = true;
+ }
+
+ if (!specified && MessageUtils.isRequestor(message)) {
+ return null;
+ }
+ Endpoint ep = message.getExchange().get(Endpoint.class);
+ if (ep != null && ep.getEndpointInfo() != null) {
+ EndpointInfo info = ep.getEndpointInfo();
+ synchronized (info) {
+ ReplayCache replayCache =
+ (ReplayCache)message.getContextualProperty(instanceKey);
+ if (replayCache == null) {
+ replayCache = (ReplayCache)info.getProperty(instanceKey);
+ }
+ if (replayCache == null) {
+ ReplayCacheFactory replayCacheFactory = ReplayCacheFactory.newInstance();
+ replayCache = replayCacheFactory.newReplayCache(instanceKey, message);
+ info.setProperty(instanceKey, replayCache);
+ }
+ return replayCache;
+ }
+ }
+ return null;
+ }
+
+
+
/**
* Create a SoapFault from a WSSecurityException, following the SOAP Message Security
* 1.1 specification, chapter 12 "Error Handling".
Added: cxf/branches/2.5.x-fixes/rt/ws/security/src/main/resources/cxf-ehcache.xml
URL: http://svn.apache.org/viewvc/cxf/branches/2.5.x-fixes/rt/ws/security/src/main/resources/cxf-ehcache.xml?rev=1298889&view=auto
==============================================================================
--- cxf/branches/2.5.x-fixes/rt/ws/security/src/main/resources/cxf-ehcache.xml (added)
+++ cxf/branches/2.5.x-fixes/rt/ws/security/src/main/resources/cxf-ehcache.xml Fri Mar 9 15:50:52 2012
@@ -0,0 +1,16 @@
+<ehcache xsi:noNamespaceSchemaLocation="ehcache.xsd" updateCheck="false" monitoring="autodetect" dynamicConfig="true">
+
+ <diskStore path="java.io.tmpdir"/>
+
+ <defaultCache
+ maxElementsInMemory="50000"
+ eternal="false"
+ timeToIdleSeconds="3600"
+ timeToLiveSeconds="3600"
+ overflowToDisk="true"
+ maxElementsOnDisk="10000000"
+ diskPersistent="false"
+ diskExpiryThreadIntervalSeconds="120"
+ memoryStoreEvictionPolicy="LRU"
+ />
+</ehcache>
Added: cxf/branches/2.5.x-fixes/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/ut/SecurityHeaderCacheInterceptor.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.5.x-fixes/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/ut/SecurityHeaderCacheInterceptor.java?rev=1298889&view=auto
==============================================================================
--- cxf/branches/2.5.x-fixes/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/ut/SecurityHeaderCacheInterceptor.java (added)
+++ cxf/branches/2.5.x-fixes/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/ut/SecurityHeaderCacheInterceptor.java Fri Mar 9 15:50:52 2012
@@ -0,0 +1,117 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.systest.ws.ut;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import javax.xml.namespace.QName;
+import javax.xml.soap.SOAPElement;
+import javax.xml.soap.SOAPException;
+import javax.xml.soap.SOAPHeaderElement;
+import javax.xml.soap.SOAPMessage;
+
+import org.apache.cxf.binding.soap.SoapMessage;
+import org.apache.cxf.interceptor.Fault;
+import org.apache.cxf.message.Message;
+import org.apache.cxf.phase.Phase;
+import org.apache.cxf.phase.PhaseInterceptor;
+import org.apache.cxf.ws.security.wss4j.PolicyBasedWSS4JOutInterceptor;
+import org.apache.ws.security.WSConstants;
+
+/**
+ * Cache the first security header and then use it instead of all subsequent security headers, until
+ * clear() is called.
+ */
+public class SecurityHeaderCacheInterceptor implements PhaseInterceptor<SoapMessage> {
+
+ private static final QName SEC_HEADER =
+ new QName(WSConstants.WSSE_NS, WSConstants.WSSE_LN, WSConstants.WSSE_PREFIX);
+ private Set<String> afterInterceptors = new HashSet<String>();
+ private SOAPHeaderElement cachedSecurityHeader;
+
+ public SecurityHeaderCacheInterceptor() {
+ getAfter().add(PolicyBasedWSS4JOutInterceptor.class.getName());
+ }
+
+ public void handleMessage(SoapMessage mc) throws Fault {
+ SOAPMessage saaj = mc.getContent(SOAPMessage.class);
+ if (cachedSecurityHeader == null) {
+ try {
+ Iterator<?> cachedHeadersIterator =
+ saaj.getSOAPHeader().getChildElements(SEC_HEADER);
+ if (cachedHeadersIterator.hasNext()) {
+ cachedSecurityHeader = (SOAPHeaderElement)cachedHeadersIterator.next();
+ }
+ } catch (SOAPException e) {
+ // Ignore
+ }
+ } else {
+ try {
+ saaj.getSOAPHeader().removeContents();
+
+ SOAPHeaderElement secHeaderElement =
+ saaj.getSOAPHeader().addHeaderElement(SEC_HEADER);
+
+ Iterator<?> cachedHeadersIterator =
+ cachedSecurityHeader.getChildElements();
+ while (cachedHeadersIterator.hasNext()) {
+ secHeaderElement.addChildElement((SOAPElement)cachedHeadersIterator.next());
+ }
+
+ } catch (SOAPException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+ }
+
+ public void clear() {
+ cachedSecurityHeader = null;
+ }
+
+ public void handleFault(SoapMessage arg0) {
+ // Complete
+ }
+
+ public Collection<PhaseInterceptor<? extends Message>> getAdditionalInterceptors() {
+ return null;
+ }
+
+ public Set<String> getAfter() {
+ return afterInterceptors;
+ }
+
+ public Set<String> getBefore() {
+ return Collections.emptySet();
+ }
+
+ public String getId() {
+ return SecurityHeaderCacheInterceptor.class.getName();
+ }
+
+ public String getPhase() {
+ return Phase.PRE_PROTOCOL_ENDING;
+ }
+
+}
Modified: cxf/branches/2.5.x-fixes/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/ut/UsernameTokenTest.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.5.x-fixes/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/ut/UsernameTokenTest.java?rev=1298889&r1=1298888&r2=1298889&view=diff
==============================================================================
--- cxf/branches/2.5.x-fixes/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/ut/UsernameTokenTest.java (original)
+++ cxf/branches/2.5.x-fixes/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/ut/UsernameTokenTest.java Fri Mar 9 15:50:52 2012
@@ -26,11 +26,11 @@ import javax.xml.ws.Service;
import org.apache.cxf.Bus;
import org.apache.cxf.bus.spring.SpringBusFactory;
+import org.apache.cxf.endpoint.Client;
+import org.apache.cxf.frontend.ClientProxy;
import org.apache.cxf.systest.ws.ut.server.Server;
import org.apache.cxf.testutil.common.AbstractBusClientServerTestBase;
-
import org.example.contract.doubleit.DoubleItPortType;
-
import org.junit.BeforeClass;
/**
@@ -214,4 +214,40 @@ public class UsernameTokenTest extends A
assertTrue(ex.getMessage().contains(error));
}
}
+
+ @org.junit.Test
+ public void testPasswordHashedReplay() throws Exception {
+
+ SpringBusFactory bf = new SpringBusFactory();
+ URL busFile = UsernameTokenTest.class.getResource("client/client.xml");
+
+ Bus bus = bf.createBus(busFile.toString());
+ SpringBusFactory.setDefaultBus(bus);
+ SpringBusFactory.setThreadDefaultBus(bus);
+
+ URL wsdl = UsernameTokenTest.class.getResource("DoubleItUt.wsdl");
+ Service service = Service.create(wsdl, SERVICE_QNAME);
+
+ QName portQName = new QName(NAMESPACE, "DoubleItHashedPort");
+ DoubleItPortType utPort =
+ service.getPort(portQName, DoubleItPortType.class);
+ updateAddressPort(utPort, PORT);
+
+ Client cxfClient = ClientProxy.getClient(utPort);
+ SecurityHeaderCacheInterceptor cacheInterceptor =
+ new SecurityHeaderCacheInterceptor();
+ cxfClient.getOutInterceptors().add(cacheInterceptor);
+
+ // Make two invocations with the same UsernameToken
+ utPort.doubleIt(25);
+ try {
+ utPort.doubleIt(25);
+ fail("Failure expected on a replayed UsernameToken");
+ } catch (javax.xml.ws.soap.SOAPFaultException ex) {
+ String error = "A replay attack has been detected";
+ assertTrue(ex.getMessage().contains(error));
+ }
+
+ }
+
}
Modified: cxf/branches/2.5.x-fixes/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/x509/X509TokenTest.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.5.x-fixes/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/x509/X509TokenTest.java?rev=1298889&r1=1298888&r2=1298889&view=diff
==============================================================================
--- cxf/branches/2.5.x-fixes/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/x509/X509TokenTest.java (original)
+++ cxf/branches/2.5.x-fixes/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/x509/X509TokenTest.java Fri Mar 9 15:50:52 2012
@@ -29,6 +29,9 @@ import javax.xml.ws.Service;
import org.apache.cxf.Bus;
import org.apache.cxf.bus.spring.SpringBusFactory;
+import org.apache.cxf.endpoint.Client;
+import org.apache.cxf.frontend.ClientProxy;
+import org.apache.cxf.systest.ws.ut.SecurityHeaderCacheInterceptor;
import org.apache.cxf.systest.ws.x509.server.Server;
import org.apache.cxf.testutil.common.AbstractBusClientServerTestBase;
@@ -344,6 +347,42 @@ public class X509TokenTest extends Abstr
x509Port.doubleIt(25);
}
+ @org.junit.Test
+ public void testAsymmetricSignatureReplay() throws Exception {
+ if (!unrestrictedPoliciesInstalled) {
+ return;
+ }
+
+ SpringBusFactory bf = new SpringBusFactory();
+ URL busFile = X509TokenTest.class.getResource("client/client.xml");
+
+ Bus bus = bf.createBus(busFile.toString());
+ SpringBusFactory.setDefaultBus(bus);
+ SpringBusFactory.setThreadDefaultBus(bus);
+
+ URL wsdl = X509TokenTest.class.getResource("DoubleItX509Signature.wsdl");
+ Service service = Service.create(wsdl, SERVICE_QNAME);
+ QName portQName = new QName(NAMESPACE, "DoubleItAsymmetricSignaturePort");
+ DoubleItPortType x509Port =
+ service.getPort(portQName, DoubleItPortType.class);
+ updateAddressPort(x509Port, PORT);
+
+ Client cxfClient = ClientProxy.getClient(x509Port);
+ SecurityHeaderCacheInterceptor cacheInterceptor =
+ new SecurityHeaderCacheInterceptor();
+ cxfClient.getOutInterceptors().add(cacheInterceptor);
+
+ // Make two invocations with the same security header
+ x509Port.doubleIt(25);
+ try {
+ x509Port.doubleIt(25);
+ fail("Failure expected on a replayed Timestamp");
+ } catch (javax.xml.ws.soap.SOAPFaultException ex) {
+ String error = "A replay attack has been detected";
+ assertTrue(ex.getMessage().contains(error));
+ }
+ }
+
private boolean checkUnrestrictedPoliciesInstalled() {
try {
byte[] data = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};