Author: coheigea
Date: Fri Jun 7 16:09:20 2013
New Revision: 1490700
URL: http://svn.apache.org/r1490700
Log:
[WSS-441] - Allow the date/time in the security headers to be spoofed
Conflicts:
src/main/java/org/apache/ws/security/WSSConfig.java
src/main/java/org/apache/ws/security/message/token/Timestamp.java
src/main/java/org/apache/ws/security/message/token/UsernameToken.java
src/test/java/org/apache/ws/security/message/TimestampTest.java
src/test/java/org/apache/ws/security/message/UsernameTokenTest.java
Added:
webservices/wss4j/branches/1_6_x-fixes/src/main/java/org/apache/ws/security/util/WSCurrentTimeSource.java
webservices/wss4j/branches/1_6_x-fixes/src/main/java/org/apache/ws/security/util/WSTimeSource.java
Modified:
webservices/wss4j/branches/1_6_x-fixes/src/main/java/org/apache/ws/security/WSSConfig.java
webservices/wss4j/branches/1_6_x-fixes/src/main/java/org/apache/ws/security/message/WSSecTimestamp.java
webservices/wss4j/branches/1_6_x-fixes/src/main/java/org/apache/ws/security/message/WSSecUsernameToken.java
webservices/wss4j/branches/1_6_x-fixes/src/main/java/org/apache/ws/security/message/token/Timestamp.java
webservices/wss4j/branches/1_6_x-fixes/src/main/java/org/apache/ws/security/message/token/UsernameToken.java
webservices/wss4j/branches/1_6_x-fixes/src/test/java/org/apache/ws/security/message/TimestampTest.java
webservices/wss4j/branches/1_6_x-fixes/src/test/java/org/apache/ws/security/message/UsernameTokenTest.java
Modified: webservices/wss4j/branches/1_6_x-fixes/src/main/java/org/apache/ws/security/WSSConfig.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/branches/1_6_x-fixes/src/main/java/org/apache/ws/security/WSSConfig.java?rev=1490700&r1=1490699&r2=1490700&view=diff
==============================================================================
--- webservices/wss4j/branches/1_6_x-fixes/src/main/java/org/apache/ws/security/WSSConfig.java
(original)
+++ webservices/wss4j/branches/1_6_x-fixes/src/main/java/org/apache/ws/security/WSSConfig.java
Fri Jun 7 16:09:20 2013
@@ -34,6 +34,8 @@ import org.apache.ws.security.action.Act
import org.apache.ws.security.processor.Processor;
import org.apache.ws.security.util.Loader;
import org.apache.ws.security.util.UUIDGenerator;
+import org.apache.ws.security.util.WSCurrentTimeSource;
+import org.apache.ws.security.util.WSTimeSource;
import org.apache.ws.security.validate.Validator;
import org.apache.xml.security.utils.XMLUtils;
@@ -300,6 +302,11 @@ public class WSSConfig {
protected boolean passwordsAreEncoded = false;
/**
+ * This allows the user to specify a different time than that of the current System time.
+ */
+ private WSTimeSource currentTime;
+
+ /**
* The default wsu:Id allocator is a simple "start at 1 and increment up"
* thing that is very fast.
*/
@@ -998,4 +1005,14 @@ public class WSSConfig {
this.utFutureTTL = utFutureTTL;
}
+ public WSTimeSource getCurrentTime() {
+ if (currentTime != null) {
+ return currentTime;
+ }
+ return new WSCurrentTimeSource();
+ }
+
+ public void setCurrentTime(WSTimeSource currentTime) {
+ this.currentTime = currentTime;
+ }
}
Modified: webservices/wss4j/branches/1_6_x-fixes/src/main/java/org/apache/ws/security/message/WSSecTimestamp.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/branches/1_6_x-fixes/src/main/java/org/apache/ws/security/message/WSSecTimestamp.java?rev=1490700&r1=1490699&r2=1490700&view=diff
==============================================================================
--- webservices/wss4j/branches/1_6_x-fixes/src/main/java/org/apache/ws/security/message/WSSecTimestamp.java
(original)
+++ webservices/wss4j/branches/1_6_x-fixes/src/main/java/org/apache/ws/security/message/WSSecTimestamp.java
Fri Jun 7 16:09:20 2013
@@ -69,7 +69,8 @@ public class WSSecTimestamp extends WSSe
* @param doc The SOAP envelope as W3C document
*/
public void prepare(Document doc) {
- ts = new Timestamp(getWsConfig().isPrecisionInMilliSeconds(), doc, timeToLive);
+ ts = new Timestamp(getWsConfig().isPrecisionInMilliSeconds(), doc,
+ getWsConfig().getCurrentTime(), timeToLive);
String tsId = getWsConfig().getIdAllocator().createId("TS-", ts);
ts.setID(tsId);
}
Modified: webservices/wss4j/branches/1_6_x-fixes/src/main/java/org/apache/ws/security/message/WSSecUsernameToken.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/branches/1_6_x-fixes/src/main/java/org/apache/ws/security/message/WSSecUsernameToken.java?rev=1490700&r1=1490699&r2=1490700&view=diff
==============================================================================
--- webservices/wss4j/branches/1_6_x-fixes/src/main/java/org/apache/ws/security/message/WSSecUsernameToken.java
(original)
+++ webservices/wss4j/branches/1_6_x-fixes/src/main/java/org/apache/ws/security/message/WSSecUsernameToken.java
Fri Jun 7 16:09:20 2013
@@ -204,7 +204,8 @@ public class WSSecUsernameToken extends
* @param doc The SOAP envelope as W3C document
*/
public void prepare(Document doc) {
- ut = new UsernameToken(getWsConfig().isPrecisionInMilliSeconds(), doc, passwordType);
+ ut = new UsernameToken(getWsConfig().isPrecisionInMilliSeconds(), doc,
+ getWsConfig().getCurrentTime(), passwordType);
ut.setPasswordsAreEncoded(passwordsAreEncoded);
ut.setName(user);
if (useDerivedKey) {
@@ -217,7 +218,7 @@ public class WSSecUsernameToken extends
ut.addNonce(doc);
}
if (created) {
- ut.addCreated(getWsConfig().isPrecisionInMilliSeconds(), doc);
+ ut.addCreated(getWsConfig().isPrecisionInMilliSeconds(), getWsConfig().getCurrentTime(),
doc);
}
ut.setID(getWsConfig().getIdAllocator().createId("UsernameToken-", ut));
}
Modified: webservices/wss4j/branches/1_6_x-fixes/src/main/java/org/apache/ws/security/message/token/Timestamp.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/branches/1_6_x-fixes/src/main/java/org/apache/ws/security/message/token/Timestamp.java?rev=1490700&r1=1490699&r2=1490700&view=diff
==============================================================================
--- webservices/wss4j/branches/1_6_x-fixes/src/main/java/org/apache/ws/security/message/token/Timestamp.java
(original)
+++ webservices/wss4j/branches/1_6_x-fixes/src/main/java/org/apache/ws/security/message/token/Timestamp.java
Fri Jun 7 16:09:20 2013
@@ -23,7 +23,9 @@ import org.apache.ws.security.WSConstant
import org.apache.ws.security.WSSecurityException;
import org.apache.ws.security.util.DOM2Writer;
import org.apache.ws.security.util.DateUtil;
+import org.apache.ws.security.util.WSCurrentTimeSource;
import org.apache.ws.security.util.WSSecurityUtil;
+import org.apache.ws.security.util.WSTimeSource;
import org.apache.ws.security.util.XmlSchemaDateFormat;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
@@ -179,6 +181,17 @@ public class Timestamp {
* @param ttl the time to live (validity of the security semantics) in seconds
*/
public Timestamp(boolean milliseconds, Document doc, int ttl) {
+ this(milliseconds, doc, new WSCurrentTimeSource(), ttl);
+ }
+
+ /**
+ * Constructs a <code>Timestamp</code> object according
+ * to the defined parameters.
+ *
+ * @param doc the SOAP envelope as <code>Document</code>
+ * @param ttl the time to live (validity of the security semantics) in seconds
+ */
+ public Timestamp(boolean milliseconds, Document doc, WSTimeSource timeSource, int ttl)
{
customElements = new ArrayList<Element>();
element =
@@ -197,11 +210,11 @@ public class Timestamp {
doc.createElementNS(
WSConstants.WSU_NS, WSConstants.WSU_PREFIX + ":" + WSConstants.CREATED_LN
);
- createdDate = new Date();
+ createdDate = timeSource.now();
elementCreated.appendChild(doc.createTextNode(zulu.format(createdDate)));
element.appendChild(elementCreated);
if (ttl != 0) {
- expiresDate = new Date();
+ expiresDate = timeSource.now();
expiresDate.setTime(createdDate.getTime() + ((long)ttl * 1000L));
Element elementExpires =
Modified: webservices/wss4j/branches/1_6_x-fixes/src/main/java/org/apache/ws/security/message/token/UsernameToken.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/branches/1_6_x-fixes/src/main/java/org/apache/ws/security/message/token/UsernameToken.java?rev=1490700&r1=1490699&r2=1490700&view=diff
==============================================================================
--- webservices/wss4j/branches/1_6_x-fixes/src/main/java/org/apache/ws/security/message/token/UsernameToken.java
(original)
+++ webservices/wss4j/branches/1_6_x-fixes/src/main/java/org/apache/ws/security/message/token/UsernameToken.java
Fri Jun 7 16:09:20 2013
@@ -26,7 +26,9 @@ import org.apache.ws.security.WSUsername
import org.apache.ws.security.handler.RequestData;
import org.apache.ws.security.util.DOM2Writer;
import org.apache.ws.security.util.DateUtil;
+import org.apache.ws.security.util.WSCurrentTimeSource;
import org.apache.ws.security.util.WSSecurityUtil;
+import org.apache.ws.security.util.WSTimeSource;
import org.apache.ws.security.util.XmlSchemaDateFormat;
import org.apache.ws.security.util.Base64;
import org.w3c.dom.Document;
@@ -258,6 +260,10 @@ public class UsernameToken {
* password required
*/
public UsernameToken(boolean milliseconds, Document doc, String pwType) {
+ this(milliseconds, doc, new WSCurrentTimeSource(), pwType);
+ }
+
+ public UsernameToken(boolean milliseconds, Document doc, WSTimeSource timeSource, String
pwType) {
element =
doc.createElementNS(WSConstants.WSSE_NS, "wsse:" + WSConstants.USERNAME_TOKEN_LN);
@@ -275,7 +281,7 @@ public class UsernameToken {
passwordType = pwType;
if (passwordType.equals(WSConstants.PASSWORD_DIGEST)) {
addNonce(doc);
- addCreated(milliseconds, doc);
+ addCreated(milliseconds, timeSource, doc);
} else {
hashed = false;
}
@@ -322,6 +328,13 @@ public class UsernameToken {
* Creates and adds a Created element to this UsernameToken
*/
public void addCreated(boolean milliseconds, Document doc) {
+ addCreated(milliseconds, new WSCurrentTimeSource(), doc);
+ }
+
+ /**
+ * Creates and adds a Created element to this UsernameToken
+ */
+ public void addCreated(boolean milliseconds, WSTimeSource timeSource, Document doc) {
if (elementCreated != null) {
return;
}
@@ -336,7 +349,7 @@ public class UsernameToken {
doc.createElementNS(
WSConstants.WSU_NS, WSConstants.WSU_PREFIX + ":" + WSConstants.CREATED_LN
);
- Date currentTime = new Date();
+ Date currentTime = timeSource.now();
elementCreated.appendChild(doc.createTextNode(zulu.format(currentTime)));
element.appendChild(elementCreated);
}
Added: webservices/wss4j/branches/1_6_x-fixes/src/main/java/org/apache/ws/security/util/WSCurrentTimeSource.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/branches/1_6_x-fixes/src/main/java/org/apache/ws/security/util/WSCurrentTimeSource.java?rev=1490700&view=auto
==============================================================================
--- webservices/wss4j/branches/1_6_x-fixes/src/main/java/org/apache/ws/security/util/WSCurrentTimeSource.java
(added)
+++ webservices/wss4j/branches/1_6_x-fixes/src/main/java/org/apache/ws/security/util/WSCurrentTimeSource.java
Fri Jun 7 16:09:20 2013
@@ -0,0 +1,34 @@
+/**
+ * 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.ws.security.util;
+
+import java.util.Date;
+
+public class WSCurrentTimeSource implements WSTimeSource {
+
+ /**
+ * Get the current date time
+ * @return the current date/time as a date object
+ */
+ public Date now() {
+ return new Date();
+ }
+
+}
\ No newline at end of file
Added: webservices/wss4j/branches/1_6_x-fixes/src/main/java/org/apache/ws/security/util/WSTimeSource.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/branches/1_6_x-fixes/src/main/java/org/apache/ws/security/util/WSTimeSource.java?rev=1490700&view=auto
==============================================================================
--- webservices/wss4j/branches/1_6_x-fixes/src/main/java/org/apache/ws/security/util/WSTimeSource.java
(added)
+++ webservices/wss4j/branches/1_6_x-fixes/src/main/java/org/apache/ws/security/util/WSTimeSource.java
Fri Jun 7 16:09:20 2013
@@ -0,0 +1,37 @@
+/**
+ * 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.ws.security.util;
+
+import java.util.Date;
+
+/**
+ * This interface allows the Time Source used to set dates and times to be
+ * overridden by the application.
+ *
+ */
+public interface WSTimeSource {
+
+ /**
+ * Get the current date time
+ * @return the current date/time as a date object
+ */
+ public Date now();
+
+}
\ No newline at end of file
Modified: webservices/wss4j/branches/1_6_x-fixes/src/test/java/org/apache/ws/security/message/TimestampTest.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/branches/1_6_x-fixes/src/test/java/org/apache/ws/security/message/TimestampTest.java?rev=1490700&r1=1490699&r2=1490700&view=diff
==============================================================================
--- webservices/wss4j/branches/1_6_x-fixes/src/test/java/org/apache/ws/security/message/TimestampTest.java
(original)
+++ webservices/wss4j/branches/1_6_x-fixes/src/test/java/org/apache/ws/security/message/TimestampTest.java
Fri Jun 7 16:09:20 2013
@@ -27,8 +27,11 @@ import org.apache.ws.security.WSSecurity
import org.apache.ws.security.common.SOAPUtil;
import org.apache.ws.security.message.token.Timestamp;
import org.apache.ws.security.util.WSSecurityUtil;
+import org.apache.ws.security.util.WSTimeSource;
+import org.apache.ws.security.util.XMLUtils;
import org.apache.ws.security.util.XmlSchemaDateFormat;
import org.apache.ws.security.validate.NoOpValidator;
+
import org.w3c.dom.Document;
import org.w3c.dom.Element;
@@ -723,6 +726,51 @@ public class TimestampTest extends org.j
}
/**
+ * This is a test to create a "Spoofed" Timestamp (see WSS-441)
+ */
+ @org.junit.Test
+ public void testSpoofedTimestamp() throws Exception {
+
+ Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
+ WSSecHeader secHeader = new WSSecHeader();
+ secHeader.insertSecurityHeader(doc);
+
+ WSSecTimestamp timestamp = new WSSecTimestamp();
+ timestamp.setTimeToLive(300);
+
+ WSSConfig config = WSSConfig.getNewInstance();
+ WSTimeSource spoofedTimeSource = new WSTimeSource() {
+
+ public Date now() {
+ Date currentTime = new Date();
+ currentTime.setTime(currentTime.getTime() - (500L * 1000L));
+ return currentTime;
+ }
+
+ };
+ config.setCurrentTime(spoofedTimeSource);
+
+ timestamp.setWsConfig(config);
+ Document createdDoc = timestamp.build(doc, secHeader);
+
+ if (LOG.isDebugEnabled()) {
+ String outputString =
+ XMLUtils.PrettyDocumentToString(createdDoc);
+ LOG.debug(outputString);
+ }
+
+ //
+ // Do some processing
+ //
+ try {
+ verify(createdDoc, WSSConfig.getNewInstance());
+ fail("Expected failure on an expired timestamp");
+ } catch (WSSecurityException ex) {
+ assertTrue(ex.getErrorCode() == WSSecurityException.MESSAGE_EXPIRED);
+ }
+ }
+
+ /**
* Verifies the soap envelope
*
* @param env soap envelope
Modified: webservices/wss4j/branches/1_6_x-fixes/src/test/java/org/apache/ws/security/message/UsernameTokenTest.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/branches/1_6_x-fixes/src/test/java/org/apache/ws/security/message/UsernameTokenTest.java?rev=1490700&r1=1490699&r2=1490700&view=diff
==============================================================================
--- webservices/wss4j/branches/1_6_x-fixes/src/test/java/org/apache/ws/security/message/UsernameTokenTest.java
(original)
+++ webservices/wss4j/branches/1_6_x-fixes/src/test/java/org/apache/ws/security/message/UsernameTokenTest.java
Fri Jun 7 16:09:20 2013
@@ -34,6 +34,8 @@ import org.apache.ws.security.handler.WS
import org.apache.ws.security.message.token.UsernameToken;
import org.apache.ws.security.util.Base64;
import org.apache.ws.security.util.WSSecurityUtil;
+import org.apache.ws.security.util.WSTimeSource;
+import org.apache.ws.security.util.XMLUtils;
import org.apache.ws.security.util.XmlSchemaDateFormat;
import org.w3c.dom.Document;
@@ -1027,6 +1029,48 @@ public class UsernameTokenTest extends o
newEngine.processSecurityHeader(doc, null, callbackHandler, null);
}
+ /**
+ * This is a test to create a "Spoofed" UsernameToken (see WSS-441)
+ */
+ @org.junit.Test
+ public void testSpoofedUsernameToken() throws Exception {
+ WSSecUsernameToken builder = new WSSecUsernameToken();
+ builder.setUserInfo("wernerd", "verySecret");
+ Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
+ WSSecHeader secHeader = new WSSecHeader();
+ secHeader.insertSecurityHeader(doc);
+
+ WSSConfig config = WSSConfig.getNewInstance();
+ WSTimeSource spoofedTimeSource = new WSTimeSource() {
+
+ public Date now() {
+ Date currentTime = new Date();
+ currentTime.setTime(currentTime.getTime() - (500L * 1000L));
+ return currentTime;
+ }
+
+ };
+ config.setCurrentTime(spoofedTimeSource);
+
+ builder.setWsConfig(config);
+ Document signedDoc = builder.build(doc, secHeader);
+
+ if (LOG.isDebugEnabled()) {
+ String outputString =
+ XMLUtils.PrettyDocumentToString(signedDoc);
+ LOG.debug(outputString);
+ }
+
+ try {
+ WSSecurityEngine secEngine = new WSSecurityEngine();
+ secEngine.processSecurityHeader(doc, null, callbackHandler, null);
+ fail("The UsernameToken validation should have failed");
+ } catch (WSSecurityException ex) {
+ assertTrue(ex.getErrorCode() == WSSecurityException.MESSAGE_EXPIRED);
+ }
+ }
+
+
private List<WSSecurityEngineResult> verify(Document doc) throws Exception {
return verify(doc, false);
}
|