Permalink
Browse files

[WSS-348] - Switched StaX layer to use common ReplayCache functionaltiy

git-svn-id: https://svn.apache.org/repos/asf/webservices/wss4j/trunk@1464926 13f79535-47bb-0310-9956-ffa450edef68
  • Loading branch information...
1 parent 3e01e28 commit 97b4a3d2cdc80f593b5ffc17cd38ddeed11987b2 @coheigea coheigea committed Apr 5, 2013
@@ -51,6 +51,12 @@
<version>${cxf.version}</version>
<scope>compile</scope>
</dependency>
+ <dependency>
+ <groupId>commons-lang</groupId>
+ <artifactId>commons-lang</artifactId>
+ <version>2.6</version>
+ <scope>compile</scope>
+ </dependency>
<dependency>
<groupId>org.apache.santuario</groupId>
View
@@ -45,7 +45,6 @@
<xerces.version>2.9.1</xerces.version>
<xmlsec.version>2.0.0-SNAPSHOT</xmlsec.version>
<opensaml.version>2.5.3</opensaml.version>
- <jcs.version>1.3</jcs.version>
<testng.version>6.5.2</testng.version>
<junit.version>4.8.2</junit.version>
<xml.apis.version>1.3.04</xml.apis.version>
@@ -76,11 +75,6 @@
<version>${woodstox.core.asl.version}</version>
</dependency>
<dependency>
- <groupId>jcs</groupId>
- <artifactId>jcs</artifactId>
- <version>${jcs.version}</version>
- </dependency>
- <dependency>
<groupId>org.opensaml</groupId>
<artifactId>opensaml</artifactId>
<version>${opensaml.version}</version>
@@ -209,7 +209,7 @@
</exclusion>
</exclusions>
</dependency>
- <dependency>
+ <dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache-core</artifactId>
<scope>runtime</scope>
@@ -18,7 +18,6 @@
*/
package org.apache.wss4j.policy.stax;
-import org.apache.commons.lang.StringUtils;
import org.apache.wss4j.policy.model.XPath;
import javax.xml.namespace.QName;
@@ -32,7 +31,7 @@
String[] xPathElements = xPath.getXPath().split("/");
for (int j = 0; j < xPathElements.length; j++) {
String xPathElement = xPathElements[j];
- if (StringUtils.isEmpty(xPathElement)) {
+ if (xPathElement == null || "".equals(xPathElement)) {
continue;
}
String[] elementParts = xPathElement.split(":");
@@ -64,73 +64,6 @@
<scope>compile</scope>
</dependency>
<dependency>
- <groupId>jcs</groupId>
- <artifactId>jcs</artifactId>
- <scope>compile</scope>
- <exclusions>
- <exclusion>
- <groupId>javax.sql</groupId>
- <artifactId>jdbc-stdext</artifactId>
- </exclusion>
- <exclusion>
- <groupId>commons-dbcp</groupId>
- <artifactId>commons-dbcp</artifactId>
- </exclusion>
- <exclusion>
- <groupId>commons-logging</groupId>
- <artifactId>commons-logging-api</artifactId>
- </exclusion>
- <exclusion>
- <groupId>commons-pool</groupId>
- <artifactId>commons-pool</artifactId>
- </exclusion>
- <exclusion>
- <groupId>mysql</groupId>
- <artifactId>mysql-connector-java</artifactId>
- </exclusion>
- <exclusion>
- <groupId>hsqldb</groupId>
- <artifactId>hsqldb</artifactId>
- </exclusion>
- <exclusion>
- <groupId>log4j</groupId>
- <artifactId>log4j</artifactId>
- </exclusion>
- <exclusion>
- <groupId>servletapi</groupId>
- <artifactId>servletapi</artifactId>
- </exclusion>
- <exclusion>
- <groupId>tomcat</groupId>
- <artifactId>tomcat-util</artifactId>
- </exclusion>
- <exclusion>
- <groupId>velocity</groupId>
- <artifactId>velocity</artifactId>
- </exclusion>
- <exclusion>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- </exclusion>
- <exclusion>
- <groupId>xmlrpc</groupId>
- <artifactId>xmlrpc</artifactId>
- </exclusion>
- <exclusion>
- <groupId>xerces</groupId>
- <artifactId>xerces</artifactId>
- </exclusion>
- <exclusion>
- <groupId>xml-apis</groupId>
- <artifactId>xml-apis</artifactId>
- </exclusion>
- <exclusion>
- <groupId>berkeleydb</groupId>
- <artifactId>berkeleydb</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
- <dependency>
<groupId>org.apache.santuario</groupId>
<artifactId>xmlsec</artifactId>
<scope>compile</scope>
@@ -207,6 +140,11 @@
</exclusions>
</dependency>
<dependency>
+ <groupId>net.sf.ehcache</groupId>
+ <artifactId>ehcache-core</artifactId>
+ <scope>runtime</scope>
+ </dependency>
+ <dependency>
<groupId>org.apache.wss4j</groupId>
<artifactId>wss4j-ws-security-dom</artifactId>
<version>${project.version}</version>
@@ -35,11 +35,15 @@
import javax.xml.namespace.QName;
import org.apache.wss4j.common.bsp.BSPRule;
+import org.apache.wss4j.common.cache.ReplayCache;
+import org.apache.wss4j.common.cache.ReplayCacheFactory;
import org.apache.wss4j.common.crypto.Crypto;
import org.apache.wss4j.common.crypto.Merlin;
+import org.apache.wss4j.common.ext.WSSecurityException;
import org.apache.wss4j.stax.securityToken.WSSecurityTokenConstants;
import org.apache.wss4j.stax.validate.Validator;
import org.apache.xml.security.stax.ext.XMLSecurityProperties;
+import org.apache.xml.security.utils.Base64;
/**
* Main configuration class to supply keys etc.
@@ -86,6 +90,8 @@
private boolean useReqSigCertForEncryption = false;
private String encryptionCompressionAlgorithm;
private boolean enableRevocation = false;
+ private ReplayCache timestampReplayCache;
+ private ReplayCache nonceReplayCache;
public WSSSecurityProperties() {
super();
@@ -122,6 +128,8 @@ public WSSSecurityProperties(WSSSecurityProperties wssSecurityProperties) {
this.useReqSigCertForEncryption = wssSecurityProperties.useReqSigCertForEncryption;
this.encryptionCompressionAlgorithm = wssSecurityProperties.encryptionCompressionAlgorithm;
this.enableRevocation = wssSecurityProperties.enableRevocation;
+ this.timestampReplayCache = wssSecurityProperties.timestampReplayCache;
+ this.nonceReplayCache = wssSecurityProperties.nonceReplayCache;
}
/**
@@ -627,4 +635,51 @@ public Integer getUtFutureTTL() {
public void setUtFutureTTL(Integer utFutureTTL) {
this.utFutureTTL = utFutureTTL;
}
+
+ /**
+ * Set the replay cache for Timestamps
+ */
+ public void setTimestampReplayCache(ReplayCache newCache) {
+ timestampReplayCache = newCache;
+ }
+
+ /**
+ * Get the replay cache for Timestamps
+ * @throws WSSecurityException
+ */
+ public ReplayCache getTimestampReplayCache() throws WSSecurityException {
+ if (timestampReplayCache == null) {
+ timestampReplayCache = createCache("wss4j-timestamp-cache-");
+ }
+
+ return timestampReplayCache;
+ }
+
+ private synchronized ReplayCache createCache(String key) throws WSSecurityException {
+ ReplayCacheFactory replayCacheFactory = ReplayCacheFactory.newInstance();
+ byte[] nonceValue = new byte[10];
+ WSSConstants.secureRandom.nextBytes(nonceValue);
+ String cacheKey = key + Base64.encode(nonceValue);
+ return replayCacheFactory.newReplayCache(cacheKey, null);
+ }
+
+ /**
+ * Set the replay cache for Nonces
+ */
+ public void setNonceReplayCache(ReplayCache newCache) {
+ nonceReplayCache = newCache;
+ }
+
+ /**
+ * Get the replay cache for Nonces
+ * @throws WSSecurityException
+ */
+ public ReplayCache getNonceReplayCache() throws WSSecurityException {
+ if (nonceReplayCache == null) {
+ nonceReplayCache = createCache("wss4j-nonce-cache-");
+ }
+
+ return nonceReplayCache;
+ }
+
}
@@ -18,14 +18,12 @@
*/
package org.apache.wss4j.stax.impl.processor.input;
-import org.apache.jcs.JCS;
-import org.apache.jcs.access.exception.CacheException;
-import org.apache.jcs.engine.ElementAttributes;
import org.apache.wss4j.binding.wss10.EncodedString;
import org.apache.wss4j.binding.wss10.PasswordString;
import org.apache.wss4j.binding.wss10.UsernameTokenType;
import org.apache.wss4j.binding.wsu10.AttributedDateTime;
import org.apache.wss4j.common.bsp.BSPRule;
+import org.apache.wss4j.common.cache.ReplayCache;
import org.apache.wss4j.common.ext.WSSecurityException;
import org.apache.wss4j.common.util.DateUtil;
import org.apache.wss4j.stax.ext.WSInboundSecurityContext;
@@ -58,17 +56,6 @@
*/
public class UsernameTokenInputHandler extends AbstractInputSecurityHeaderHandler {
- private static final String cacheRegionName = "usernameToken";
- private static final JCS cache;
-
- static {
- try {
- cache = JCS.getInstance(cacheRegionName);
- } catch (CacheException e) {
- throw new RuntimeException(e);
- }
- }
-
@Override
public void handle(final InputProcessorChain inputProcessorChain, final XMLSecurityProperties securityProperties,
Deque<XMLSecEvent> eventQueue, Integer index) throws XMLSecurityException {
@@ -84,35 +71,35 @@ public void handle(final InputProcessorChain inputProcessorChain, final XMLSecur
if (usernameTokenType.getId() == null) {
usernameTokenType.setId(IDGenerator.generateID(null));
}
+
+ // Verify Created
+ final WSSSecurityProperties wssSecurityProperties = (WSSSecurityProperties) securityProperties;
+ Date createdDate = verifyCreated(wssSecurityProperties, usernameTokenType);
+ ReplayCache replayCache = wssSecurityProperties.getNonceReplayCache();
final EncodedString encodedNonce =
XMLSecurityUtils.getQNameType(usernameTokenType.getAny(), WSSConstants.TAG_wsse_Nonce);
- if (encodedNonce != null) {
+ if (encodedNonce != null && replayCache != null) {
+ // Check for replay attacks
String nonce = encodedNonce.getValue();
- /*
- It is RECOMMENDED that used nonces be cached for a period at least as long as
- the timestamp freshness limitation period, above, and that UsernameToken with
- nonces that have already been used (and are thus in the cache) be rejected
- */
- if (cache.get(nonce) != null) {
+ if (replayCache.contains(nonce)) {
throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_AUTHENTICATION);
}
- ElementAttributes elementAttributes = new ElementAttributes();
- elementAttributes.setMaxLifeSeconds(300);
- try {
- cache.put(nonce, nonce, elementAttributes);
- } catch (CacheException e) {
- throw new WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY, e);
+
+ // If no Created, then just cache for the default time
+ // Otherwise, cache for the configured TTL of the UsernameToken Created time, as any
+ // older token will just get rejected anyway
+ int utTTL = wssSecurityProperties.getUtTTL();
+ if (createdDate == null || utTTL <= 0) {
+ replayCache.add(nonce);
+ } else {
+ replayCache.add(nonce, utTTL + 1L);
}
}
final WSInboundSecurityContext wsInboundSecurityContext = (WSInboundSecurityContext) inputProcessorChain.getSecurityContext();
- final WSSSecurityProperties wssSecurityProperties = (WSSSecurityProperties) securityProperties;
final List<QName> elementPath = getElementPath(eventQueue);
- // Verify Created
- verifyCreated(wssSecurityProperties, usernameTokenType);
-
final TokenContext tokenContext = new TokenContext(wssSecurityProperties, wsInboundSecurityContext, xmlSecEvents, elementPath);
UsernameTokenValidator usernameTokenValidator =
@@ -206,7 +193,7 @@ private void checkBSPCompliance(InputProcessorChain inputProcessorChain, Usernam
}
- private void verifyCreated(
+ private Date verifyCreated(
WSSSecurityProperties wssSecurityProperties,
UsernameTokenType usernameTokenType
) throws WSSecurityException {
@@ -231,6 +218,8 @@ private void verifyCreated(
if (!DateUtil.verifyCreated(createdDate, ttl, futureTTL)) {
throw new WSSecurityException(WSSecurityException.ErrorCode.MESSAGE_EXPIRED);
}
+ return createdDate;
}
+ return null;
}
}
Oops, something went wrong. Retry.

0 comments on commit 97b4a3d

Please sign in to comment.