Author: coheigea
Date: Wed Feb 27 00:59:24 2013
New Revision: 1450560
URL: http://svn.apache.org/r1450560
Log:
[WSS-426] - Support future TTL in the StaX code for Timestamps
Modified:
webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/ext/WSSSecurityProperties.java
webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/validate/TimestampValidatorImpl.java
webservices/wss4j/trunk/ws-security-stax/src/test/java/org/apache/wss4j/stax/test/TimestampTest.java
Modified:
webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/ext/WSSSecurityProperties.java
URL:
http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/ext/WSSSecurityProperties.java?rev=1450560&r1=1450559&r2=1450560&view=diff
==============================================================================
---
webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/ext/WSSSecurityProperties.java
(original)
+++
webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/ext/WSSSecurityProperties.java
Wed Feb 27 00:59:24 2013
@@ -52,6 +52,7 @@ public class WSSSecurityProperties exten
private final Map<QName, Validator> validators = new HashMap<QName,
Validator>();
private Integer timestampTTL = 300;
+ private Integer timeStampFutureTTL = 60;
private boolean strictTimestampCheck = true;
/**
@@ -110,6 +111,7 @@ public class WSSSecurityProperties exten
this.ignoredBSPRules.addAll(wssSecurityProperties.ignoredBSPRules);
this.validators.putAll(wssSecurityProperties.validators);
this.timestampTTL = wssSecurityProperties.timestampTTL;
+ this.timeStampFutureTTL = wssSecurityProperties.timeStampFutureTTL;
this.strictTimestampCheck = wssSecurityProperties.strictTimestampCheck;
this.handleCustomPasswordTypes =
wssSecurityProperties.handleCustomPasswordTypes;
this.usernameTokenPasswordType =
wssSecurityProperties.usernameTokenPasswordType;
@@ -599,4 +601,12 @@ public class WSSSecurityProperties exten
public void setCrlCertStore(CertStore crlCertStore) {
this.crlCertStore = crlCertStore;
}
+
+ public Integer getTimeStampFutureTTL() {
+ return timeStampFutureTTL;
+ }
+
+ public void setTimeStampFutureTTL(Integer timeStampFutureTTL) {
+ this.timeStampFutureTTL = timeStampFutureTTL;
+ }
}
Modified:
webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/validate/TimestampValidatorImpl.java
URL:
http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/validate/TimestampValidatorImpl.java?rev=1450560&r1=1450559&r2=1450560&view=diff
==============================================================================
---
webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/validate/TimestampValidatorImpl.java
(original)
+++
webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/validate/TimestampValidatorImpl.java
Wed Feb 27 00:59:24 2013
@@ -25,7 +25,7 @@ import org.apache.wss4j.common.ext.WSSec
import org.apache.wss4j.stax.ext.WSSConstants;
import javax.xml.datatype.XMLGregorianCalendar;
-import java.util.Calendar;
+import java.util.Date;
import java.util.GregorianCalendar;
/**
@@ -46,7 +46,7 @@ public class TimestampValidatorImpl impl
try {
// Validate whether the security semantics have expired
//created and expires is optional per spec. But we enforce the
created element in the validation
- Calendar crea = null;
+ Date createdDate = null;
if (timestampType.getCreated() != null) {
XMLGregorianCalendar created;
try {
@@ -55,10 +55,10 @@ public class TimestampValidatorImpl impl
throw new
WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY, e);
}
log.debug("Timestamp created: " + created);
- crea = created.toGregorianCalendar();
+ createdDate = created.toGregorianCalendar().getTime();
}
- Calendar exp = null;
+ Date expiresDate = null;
if (timestampType.getExpires() != null) {
XMLGregorianCalendar expires;
try {
@@ -67,33 +67,63 @@ public class TimestampValidatorImpl impl
throw new
WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY, e);
}
log.debug("Timestamp expires: " + expires);
- exp = expires.toGregorianCalendar();
+ expiresDate = expires.toGregorianCalendar().getTime();
}
- Calendar rightNow = Calendar.getInstance();
- Calendar ttl = Calendar.getInstance();
- ttl.add(Calendar.SECOND,
-tokenContext.getWssSecurityProperties().getTimestampTTL());
+ Date rightNow = new Date();
+ int ttl =
tokenContext.getWssSecurityProperties().getTimestampTTL();
+ int futureTTL =
tokenContext.getWssSecurityProperties().getTimeStampFutureTTL();
- if (exp != null &&
tokenContext.getWssSecurityProperties().isStrictTimestampCheck() &&
exp.before(rightNow)) {
+ if (expiresDate != null &&
tokenContext.getWssSecurityProperties().isStrictTimestampCheck()
+ && expiresDate.before(rightNow)) {
log.debug("Time now: " +
WSSConstants.datatypeFactory.newXMLGregorianCalendar(new
GregorianCalendar()).toXMLFormat());
throw new
WSSecurityException(WSSecurityException.ErrorCode.MESSAGE_EXPIRED,
"invalidTimestamp",
"The security semantics of the message have expired");
}
- if (crea != null &&
tokenContext.getWssSecurityProperties().isStrictTimestampCheck() &&
crea.before(ttl)) {
+ if (createdDate != null && !verifyCreated(createdDate, ttl,
futureTTL)) {
log.debug("Time now: " +
WSSConstants.datatypeFactory.newXMLGregorianCalendar(new
GregorianCalendar()).toXMLFormat());
throw new
WSSecurityException(WSSecurityException.ErrorCode.MESSAGE_EXPIRED,
"invalidTimestamp",
"The security semantics of the message have expired");
}
- if (crea != null && crea.after(rightNow)) {
- log.debug("Time now: " +
WSSConstants.datatypeFactory.newXMLGregorianCalendar(new
GregorianCalendar()).toXMLFormat());
- throw new
WSSecurityException(WSSecurityException.ErrorCode.MESSAGE_EXPIRED,
"invalidTimestamp",
- "The security semantics of the message is invalid");
- }
-
} catch (IllegalArgumentException e) {
throw new
WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY, e);
}
}
+
+ /**
+ * Return true if the "Created" value is before the current time minus the
timeToLive
+ * argument, and if the Created value is not "in the future".
+ */
+ private boolean verifyCreated(
+ Date createdDate,
+ int timeToLive,
+ int futureTimeToLive
+ ) {
+ Date validCreation = new Date();
+ long currentTime = validCreation.getTime();
+ if (futureTimeToLive > 0) {
+ validCreation.setTime(currentTime + ((long)futureTimeToLive *
1000L));
+ }
+ // Check to see if the created time is in the future
+ if (createdDate.after(validCreation)) {
+ log.debug("Validation of Timestamp: The message was created in the
future!");
+ return false;
+ }
+
+ // Calculate the time that is allowed for the message to travel
+ currentTime -= ((long)timeToLive * 1000L);
+ validCreation.setTime(currentTime);
+
+ // Validate the time it took the message to travel
+ if (createdDate.before(validCreation)) {
+ log.debug("Validation of Timestamp: The message was created too
long ago");
+ return false;
+ }
+
+ log.debug("Validation of Timestamp: Everything is ok");
+
+ return true;
+ }
}
Modified:
webservices/wss4j/trunk/ws-security-stax/src/test/java/org/apache/wss4j/stax/test/TimestampTest.java
URL:
http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-stax/src/test/java/org/apache/wss4j/stax/test/TimestampTest.java?rev=1450560&r1=1450559&r2=1450560&view=diff
==============================================================================
---
webservices/wss4j/trunk/ws-security-stax/src/test/java/org/apache/wss4j/stax/test/TimestampTest.java
(original)
+++
webservices/wss4j/trunk/ws-security-stax/src/test/java/org/apache/wss4j/stax/test/TimestampTest.java
Wed Feb 27 00:59:24 2013
@@ -252,6 +252,50 @@ public class TimestampTest extends Abstr
}
@Test
+ public void testTimestampInNearFutureInbound() throws Exception {
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ {
+ InputStream sourceDocument =
this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
+ String action = WSHandlerConstants.TIMESTAMP;
+ Properties outboundProperties = new Properties();
+ outboundProperties.setProperty(WSHandlerConstants.TTL_TIMESTAMP,
"1");
+ Document securedDocument =
doOutboundSecurityWithWSS4J(sourceDocument, action, outboundProperties);
+
+ //some test that we can really sure we get what we want from WSS4J
+ NodeList nodeList =
securedDocument.getElementsByTagNameNS(WSSConstants.TAG_wsu_Timestamp.getNamespaceURI(),
WSSConstants.TAG_wsu_Timestamp.getLocalPart());
+
Assert.assertEquals(nodeList.item(0).getParentNode().getLocalName(),
WSSConstants.TAG_wsse_Security.getLocalPart());
+
+ Element created = (Element) ((Element)
nodeList.item(0)).getElementsByTagNameNS(WSSConstants.TAG_wsu_Created.getNamespaceURI(),
WSSConstants.TAG_wsu_Created.getLocalPart()).item(0);
+ Element expires = (Element) ((Element)
nodeList.item(0)).getElementsByTagNameNS(WSSConstants.TAG_wsu_Expires.getNamespaceURI(),
WSSConstants.TAG_wsu_Expires.getLocalPart()).item(0);
+
+ DatatypeFactory datatypeFactory = DatatypeFactory.newInstance();
+ GregorianCalendar gregorianCalendarCreated = new
GregorianCalendar();
+ gregorianCalendarCreated.add(Calendar.SECOND, 40);
+ XMLGregorianCalendar xmlGregorianCalendarCreated =
datatypeFactory.newXMLGregorianCalendar(gregorianCalendarCreated);
+ created.setTextContent(xmlGregorianCalendarCreated.toXMLFormat());
+
+ GregorianCalendar gregorianCalendarExpires = new
GregorianCalendar();
+ gregorianCalendarExpires.add(Calendar.SECOND, 300);
+ XMLGregorianCalendar xmlGregorianCalendarExpires =
datatypeFactory.newXMLGregorianCalendar(gregorianCalendarExpires);
+
+ expires.setTextContent(xmlGregorianCalendarExpires.toXMLFormat());
+
+ javax.xml.transform.Transformer transformer =
TRANSFORMER_FACTORY.newTransformer();
+ transformer.transform(new DOMSource(securedDocument), new
StreamResult(baos));
+ }
+
+ //done timestamp; now test timestamp-verification:
+ {
+ WSSSecurityProperties securityProperties = new
WSSSecurityProperties();
+ InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties);
+ XMLStreamReader xmlStreamReader =
wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new
ByteArrayInputStream(baos.toByteArray())));
+
+ StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(),
xmlStreamReader);
+ }
+ }
+
+ @Test
public void testTimestampInFutureInbound() throws Exception {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
@@ -298,10 +342,21 @@ public class TimestampTest extends Abstr
} catch (XMLStreamException e) {
Assert.assertNotNull(e.getCause());
Assert.assertTrue(e.getCause() instanceof WSSecurityException);
- Assert.assertEquals(e.getCause().getMessage(), "Invalid
timestamp: The security semantics of the message is invalid");
+ Assert.assertEquals(e.getCause().getMessage(), "Invalid
timestamp: The security semantics of the message have expired");
Assert.assertEquals(((WSSecurityException)
e.getCause()).getFaultCode(), WSSecurityException.MESSAGE_EXPIRED);
}
}
+
+ // now allow future TTL of 2 hours +
+ {
+ WSSSecurityProperties securityProperties = new
WSSSecurityProperties();
+ securityProperties.setTimeStampFutureTTL((2 * 60 * 60) + 100);
+
+ InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties);
+ XMLStreamReader xmlStreamReader =
wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new
ByteArrayInputStream(baos.toByteArray())));
+
+ StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(),
xmlStreamReader);
+ }
}
@Test