blob: e483f4b2b69d4dceb43a71e19afb9b049f48f10c [file] [log] [blame]
/**
* 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.wss4j.dom.message;
import java.time.Instant;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import org.apache.wss4j.common.bsp.BSPEnforcer;
import org.apache.wss4j.common.bsp.BSPRule;
import org.apache.wss4j.common.ext.WSSecurityException;
import org.apache.wss4j.common.util.DateUtil;
import org.apache.wss4j.common.util.WSTimeSource;
import org.apache.wss4j.common.util.XMLUtils;
import org.apache.wss4j.dom.WSConstants;
import org.apache.wss4j.dom.common.SOAPUtil;
import org.apache.wss4j.dom.engine.WSSConfig;
import org.apache.wss4j.dom.engine.WSSecurityEngine;
import org.apache.wss4j.dom.engine.WSSecurityEngineResult;
import org.apache.wss4j.dom.handler.RequestData;
import org.apache.wss4j.dom.handler.WSHandlerResult;
import org.apache.wss4j.dom.message.token.Timestamp;
import org.apache.wss4j.dom.validate.NoOpValidator;
import org.junit.jupiter.api.Test;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
/**
* WS-Security Test Case for Timestamps.
*/
public class TimestampTest {
private static final org.slf4j.Logger LOG =
org.slf4j.LoggerFactory.getLogger(TimestampTest.class);
/**
* This is a test for processing a valid Timestamp.
*/
@Test
public void testValidTimestamp() throws Exception {
Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
WSSecHeader secHeader = new WSSecHeader(doc);
secHeader.insertSecurityHeader();
WSSecTimestamp timestamp = new WSSecTimestamp(secHeader);
timestamp.setTimeToLive(300);
Document createdDoc = timestamp.build();
if (LOG.isDebugEnabled()) {
String outputString =
XMLUtils.prettyDocumentToString(createdDoc);
LOG.debug(outputString);
}
//
// Do some processing
//
WSHandlerResult wsResult = verify(createdDoc);
WSSecurityEngineResult actionResult =
wsResult.getActionResults().get(WSConstants.TS).get(0);
assertNotNull(actionResult);
Timestamp receivedTimestamp =
(Timestamp)actionResult.get(WSSecurityEngineResult.TAG_TIMESTAMP);
assertNotNull(receivedTimestamp);
Timestamp clone = new Timestamp(receivedTimestamp.getElement(), new BSPEnforcer(true));
assertTrue(clone.equals(receivedTimestamp));
assertTrue(clone.hashCode() == receivedTimestamp.hashCode());
}
/**
* This is a test for processing a valid Timestamp with no expires element
*/
@Test
public void testValidTimestampNoExpires() throws Exception {
Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
WSSecHeader secHeader = new WSSecHeader(doc);
secHeader.insertSecurityHeader();
WSSecTimestamp timestamp = new WSSecTimestamp(secHeader);
timestamp.setTimeToLive(0);
Document createdDoc = timestamp.build();
if (LOG.isDebugEnabled()) {
String outputString =
XMLUtils.prettyDocumentToString(createdDoc);
LOG.debug(outputString);
}
//
// Do some processing
//
WSHandlerResult wsResult = verify(createdDoc);
WSSecurityEngineResult actionResult =
wsResult.getActionResults().get(WSConstants.TS).get(0);
assertNotNull(actionResult);
Timestamp receivedTimestamp =
(Timestamp)actionResult.get(WSSecurityEngineResult.TAG_TIMESTAMP);
assertNotNull(receivedTimestamp);
}
@Test
public void testInvalidTimestampNoExpires() throws Exception {
Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
WSSecHeader secHeader = new WSSecHeader(doc);
secHeader.insertSecurityHeader();
WSSecTimestamp timestamp = new WSSecTimestamp(secHeader);
timestamp.setTimeToLive(0);
Document createdDoc = timestamp.build();
if (LOG.isDebugEnabled()) {
String outputString =
XMLUtils.prettyDocumentToString(createdDoc);
LOG.debug(outputString);
}
//
// Do some processing
//
WSSecurityEngine secEngine = new WSSecurityEngine();
RequestData requestData = new RequestData();
requestData.setWssConfig(WSSConfig.getNewInstance());
requestData.setRequireTimestampExpires(true);
try {
secEngine.processSecurityHeader(doc, requestData);
fail("Failure expected on no Expires Element");
} catch (WSSecurityException ex) {
assertTrue(ex.getErrorCode() == WSSecurityException.ErrorCode.SECURITY_ERROR);
}
requestData.setWssConfig(WSSConfig.getNewInstance());
requestData.setRequireTimestampExpires(false);
WSHandlerResult wsResult = secEngine.processSecurityHeader(doc, requestData);
WSSecurityEngineResult actionResult =
wsResult.getActionResults().get(WSConstants.TS).get(0);
assertNotNull(actionResult);
Timestamp receivedTimestamp =
(Timestamp)actionResult.get(WSSecurityEngineResult.TAG_TIMESTAMP);
assertNotNull(receivedTimestamp);
}
/**
* This is a test for processing an expired Timestamp.
*/
@Test
public void testExpiredTimestamp() throws Exception {
Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
WSSecHeader secHeader = new WSSecHeader(doc);
secHeader.insertSecurityHeader();
WSSecTimestamp timestamp = new WSSecTimestamp(secHeader);
timestamp.setTimeToLive(-1);
Document createdDoc = timestamp.build();
if (LOG.isDebugEnabled()) {
String outputString =
XMLUtils.prettyDocumentToString(createdDoc);
LOG.debug(outputString);
}
try {
verify(createdDoc);
fail("Expected failure on an expired timestamp");
} catch (WSSecurityException ex) {
assertTrue(ex.getErrorCode() == WSSecurityException.ErrorCode.MESSAGE_EXPIRED);
}
}
/**
* This is a test for processing an "old" Timestamp, i.e. one with a "Created" element that is
* out of date
*/
@Test
public void testOldTimestamp() throws Exception {
Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
WSSecHeader secHeader = new WSSecHeader(doc);
secHeader.insertSecurityHeader();
WSSecTimestamp timestamp = new WSSecTimestamp(secHeader);
Document createdDoc = timestamp.build();
if (LOG.isDebugEnabled()) {
String outputString =
XMLUtils.prettyDocumentToString(createdDoc);
LOG.debug(outputString);
}
//
// Do some processing
//
RequestData requestData = new RequestData();
requestData.setWssConfig(WSSConfig.getNewInstance());
requestData.setTimeStampTTL(-1);
try {
verify(createdDoc, requestData);
fail("The timestamp validation should have failed");
} catch (WSSecurityException ex) {
assertTrue(ex.getErrorCode() == WSSecurityException.ErrorCode.MESSAGE_EXPIRED);
}
}
/**
* This is a test for processing an Timestamp where the "Created" element is in the (near)
* future. It should be accepted by default when it is created 30 seconds in the future,
* and then rejected once we configure "0 seconds" for future-time-to-live.
*/
@Test
public void testNearFutureCreated() throws Exception {
Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
WSSecHeader secHeader = new WSSecHeader(doc);
secHeader.insertSecurityHeader();
Element timestampElement =
doc.createElementNS(
WSConstants.WSU_NS, WSConstants.WSU_PREFIX + ":" + WSConstants.TIMESTAMP_TOKEN_LN
);
Element elementCreated =
doc.createElementNS(
WSConstants.WSU_NS, WSConstants.WSU_PREFIX + ":" + WSConstants.CREATED_LN
);
ZonedDateTime now = ZonedDateTime.now(ZoneOffset.UTC).plusSeconds(30L);
elementCreated.appendChild(doc.createTextNode(DateUtil.getDateTimeFormatter(true).format(now)));
timestampElement.appendChild(elementCreated);
secHeader.getSecurityHeaderElement().appendChild(timestampElement);
if (LOG.isDebugEnabled()) {
String outputString =
XMLUtils.prettyDocumentToString(doc);
LOG.debug(outputString);
}
//
// Do some processing
//
RequestData requestData = new RequestData();
requestData.setWssConfig(WSSConfig.getNewInstance());
requestData.setTimeStampFutureTTL(0);
try {
verify(doc, requestData);
fail("The timestamp validation should have failed");
} catch (WSSecurityException ex) {
assertTrue(ex.getErrorCode() == WSSecurityException.ErrorCode.MESSAGE_EXPIRED);
}
}
/**
* This is a test for processing an Timestamp where the "Created" element is in the future.
* A Timestamp that is 120 seconds in the future should be rejected by default.
*/
@Test
public void testFutureCreated() throws Exception {
Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
WSSecHeader secHeader = new WSSecHeader(doc);
secHeader.insertSecurityHeader();
Element timestampElement =
doc.createElementNS(
WSConstants.WSU_NS, WSConstants.WSU_PREFIX + ":" + WSConstants.TIMESTAMP_TOKEN_LN
);
Element elementCreated =
doc.createElementNS(
WSConstants.WSU_NS, WSConstants.WSU_PREFIX + ":" + WSConstants.CREATED_LN
);
ZonedDateTime now = ZonedDateTime.now(ZoneOffset.UTC).plusSeconds(120L);
elementCreated.appendChild(doc.createTextNode(DateUtil.getDateTimeFormatter(true).format(now)));
timestampElement.appendChild(elementCreated);
secHeader.getSecurityHeaderElement().appendChild(timestampElement);
if (LOG.isDebugEnabled()) {
String outputString =
XMLUtils.prettyDocumentToString(doc);
LOG.debug(outputString);
}
//
// Do some processing
//
try {
verify(doc);
fail("The timestamp validation should have failed");
} catch (WSSecurityException ex) {
assertTrue(ex.getErrorCode() == WSSecurityException.ErrorCode.MESSAGE_EXPIRED);
}
}
/**
* This is a test for processing an Timestamp where the "Created" element is greater than
* the expiration time.
*/
@Test
public void testExpiresBeforeCreated() throws Exception {
Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
WSSecHeader secHeader = new WSSecHeader(doc);
secHeader.insertSecurityHeader();
Element timestampElement =
doc.createElementNS(
WSConstants.WSU_NS, WSConstants.WSU_PREFIX + ":" + WSConstants.TIMESTAMP_TOKEN_LN
);
Element elementCreated =
doc.createElementNS(
WSConstants.WSU_NS, WSConstants.WSU_PREFIX + ":" + WSConstants.CREATED_LN
);
ZonedDateTime now = ZonedDateTime.now(ZoneOffset.UTC);
elementCreated.appendChild(doc.createTextNode(DateUtil.getDateTimeFormatter(true).format(now)));
timestampElement.appendChild(elementCreated);
Element elementExpires =
doc.createElementNS(
WSConstants.WSU_NS, WSConstants.WSU_PREFIX + ":" + WSConstants.EXPIRES_LN
);
now = now.minusSeconds(300L);
elementExpires.appendChild(doc.createTextNode(DateUtil.getDateTimeFormatter(true).format(now)));
timestampElement.appendChild(elementExpires);
secHeader.getSecurityHeaderElement().appendChild(timestampElement);
if (LOG.isDebugEnabled()) {
String outputString =
XMLUtils.prettyDocumentToString(doc);
LOG.debug(outputString);
}
//
// Do some processing
//
try {
verify(doc);
fail("The timestamp validation should have failed");
} catch (WSSecurityException ex) {
assertTrue(ex.getErrorCode() == WSSecurityException.ErrorCode.MESSAGE_EXPIRED);
}
}
/**
* This is a test for processing multiple Timestamps in the security header
*/
@Test
public void testMultipleTimestamps() throws Exception {
Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
WSSecHeader secHeader = new WSSecHeader(doc);
secHeader.insertSecurityHeader();
WSSecTimestamp timestamp = new WSSecTimestamp(secHeader);
timestamp.setTimeToLive(300);
Document createdDoc = timestamp.build();
timestamp = new WSSecTimestamp(secHeader);
timestamp.setTimeToLive(60);
createdDoc = timestamp.build();
if (LOG.isDebugEnabled()) {
String outputString =
XMLUtils.prettyDocumentToString(createdDoc);
LOG.debug(outputString);
}
//
// Do some processing
//
try {
verify(createdDoc);
fail("Expected failure on multiple timestamps");
} catch (WSSecurityException ex) {
assertTrue(ex.getErrorCode() == WSSecurityException.ErrorCode.INVALID_SECURITY);
}
verify(createdDoc, Collections.singletonList(BSPRule.R3227));
}
/**
* This is a test for processing an Timestamp where it contains multiple "Created" elements.
* This Timestamp should be rejected.
*/
@Test
public void testMultipleCreated() throws Exception {
Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
WSSecHeader secHeader = new WSSecHeader(doc);
secHeader.insertSecurityHeader();
Element timestampElement =
doc.createElementNS(
WSConstants.WSU_NS, WSConstants.WSU_PREFIX + ":" + WSConstants.TIMESTAMP_TOKEN_LN
);
Element elementCreated =
doc.createElementNS(
WSConstants.WSU_NS, WSConstants.WSU_PREFIX + ":" + WSConstants.CREATED_LN
);
ZonedDateTime now = ZonedDateTime.now(ZoneOffset.UTC);
elementCreated.appendChild(doc.createTextNode(DateUtil.getDateTimeFormatter(true).format(now)));
timestampElement.appendChild(elementCreated);
timestampElement.appendChild(elementCreated.cloneNode(true));
secHeader.getSecurityHeaderElement().appendChild(timestampElement);
if (LOG.isDebugEnabled()) {
String outputString =
XMLUtils.prettyDocumentToString(doc);
LOG.debug(outputString);
}
//
// Do some processing
//
try {
verify(doc);
fail("The timestamp validation should have failed on multiple Created elements");
} catch (WSSecurityException ex) {
assertTrue(ex.getErrorCode() == WSSecurityException.ErrorCode.INVALID_SECURITY);
}
verify(doc, Collections.singletonList(BSPRule.R3203));
}
/**
* This is a test for processing an Timestamp where it contains no "Created" element.
* This Timestamp should be rejected.
*/
@Test
public void testNoCreated() throws Exception {
Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
WSSecHeader secHeader = new WSSecHeader(doc);
secHeader.insertSecurityHeader();
Element timestampElement =
doc.createElementNS(
WSConstants.WSU_NS, WSConstants.WSU_PREFIX + ":" + WSConstants.TIMESTAMP_TOKEN_LN
);
Element elementExpires =
doc.createElementNS(
WSConstants.WSU_NS, WSConstants.WSU_PREFIX + ":" + WSConstants.EXPIRES_LN
);
ZonedDateTime now = ZonedDateTime.now(ZoneOffset.UTC).plusSeconds(300L);
elementExpires.appendChild(doc.createTextNode(DateUtil.getDateTimeFormatter(true).format(now)));
timestampElement.appendChild(elementExpires);
secHeader.getSecurityHeaderElement().appendChild(timestampElement);
if (LOG.isDebugEnabled()) {
String outputString =
XMLUtils.prettyDocumentToString(doc);
LOG.debug(outputString);
}
//
// Do some processing
//
try {
verify(doc);
fail("The timestamp validation should have failed on no Created element");
} catch (WSSecurityException ex) {
assertTrue(ex.getErrorCode() == WSSecurityException.ErrorCode.INVALID_SECURITY);
}
List<BSPRule> rules = new ArrayList<>();
rules.add(BSPRule.R3203);
rules.add(BSPRule.R3221);
verify(doc, rules);
}
/**
* This is a test for processing an Timestamp where it contains multiple "Expires" elements.
* This Timestamp should be rejected.
*/
@Test
public void testMultipleExpires() throws Exception {
Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
WSSecHeader secHeader = new WSSecHeader(doc);
secHeader.insertSecurityHeader();
Element timestampElement =
doc.createElementNS(
WSConstants.WSU_NS, WSConstants.WSU_PREFIX + ":" + WSConstants.TIMESTAMP_TOKEN_LN
);
Element elementCreated =
doc.createElementNS(
WSConstants.WSU_NS, WSConstants.WSU_PREFIX + ":" + WSConstants.CREATED_LN
);
ZonedDateTime now = ZonedDateTime.now(ZoneOffset.UTC);
elementCreated.appendChild(doc.createTextNode(DateUtil.getDateTimeFormatter(true).format(now)));
timestampElement.appendChild(elementCreated);
Element elementExpires =
doc.createElementNS(
WSConstants.WSU_NS, WSConstants.WSU_PREFIX + ":" + WSConstants.EXPIRES_LN
);
now = now.plusSeconds(300L);
elementExpires.appendChild(doc.createTextNode(DateUtil.getDateTimeFormatter(true).format(now)));
timestampElement.appendChild(elementExpires);
timestampElement.appendChild(elementExpires.cloneNode(true));
secHeader.getSecurityHeaderElement().appendChild(timestampElement);
if (LOG.isDebugEnabled()) {
String outputString =
XMLUtils.prettyDocumentToString(doc);
LOG.debug(outputString);
}
//
// Do some processing
//
try {
verify(doc);
fail("The timestamp validation should have failed on multiple Expires elements");
} catch (WSSecurityException ex) {
assertTrue(ex.getErrorCode() == WSSecurityException.ErrorCode.INVALID_SECURITY);
}
verify(doc, Collections.singletonList(BSPRule.R3224));
}
/**
* This is a test for processing an Timestamp where it contains an "Expires" element before
* the Created element. This Timestamp should be rejected as per the BSP spec.
*/
@Test
public void testExpiresInFrontOfCreated() throws Exception {
Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
WSSecHeader secHeader = new WSSecHeader(doc);
secHeader.insertSecurityHeader();
Element timestampElement =
doc.createElementNS(
WSConstants.WSU_NS, WSConstants.WSU_PREFIX + ":" + WSConstants.TIMESTAMP_TOKEN_LN
);
Element elementCreated =
doc.createElementNS(
WSConstants.WSU_NS, WSConstants.WSU_PREFIX + ":" + WSConstants.EXPIRES_LN
);
ZonedDateTime now = ZonedDateTime.now(ZoneOffset.UTC).plusSeconds(300L);
elementCreated.appendChild(doc.createTextNode(DateUtil.getDateTimeFormatter(true).format(now)));
timestampElement.appendChild(elementCreated);
Element elementExpires =
doc.createElementNS(
WSConstants.WSU_NS, WSConstants.WSU_PREFIX + ":" + WSConstants.CREATED_LN
);
now = ZonedDateTime.now(ZoneOffset.UTC);
elementExpires.appendChild(doc.createTextNode(DateUtil.getDateTimeFormatter(true).format(now)));
timestampElement.appendChild(elementExpires);
secHeader.getSecurityHeaderElement().appendChild(timestampElement);
if (LOG.isDebugEnabled()) {
String outputString =
XMLUtils.prettyDocumentToString(doc);
LOG.debug(outputString);
}
//
// Do some processing
//
try {
verify(doc);
fail("The timestamp validation should have failed");
} catch (WSSecurityException ex) {
assertTrue(ex.getErrorCode() == WSSecurityException.ErrorCode.INVALID_SECURITY);
}
verify(doc, Collections.singletonList(BSPRule.R3221));
}
/**
* This is a test for processing an Timestamp where it contains a Created element with
* seconds > 60. This should be rejected as per the BSP spec.
*/
@Test
public void testCreatedSeconds() throws Exception {
Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
WSSecHeader secHeader = new WSSecHeader(doc);
secHeader.insertSecurityHeader();
Element timestampElement =
doc.createElementNS(
WSConstants.WSU_NS, WSConstants.WSU_PREFIX + ":" + WSConstants.TIMESTAMP_TOKEN_LN
);
Element elementCreated =
doc.createElementNS(
WSConstants.WSU_NS, WSConstants.WSU_PREFIX + ":" + WSConstants.CREATED_LN
);
elementCreated.appendChild(doc.createTextNode("2011-02-08T13:13:84.535Z"));
timestampElement.appendChild(elementCreated);
secHeader.getSecurityHeaderElement().appendChild(timestampElement);
if (LOG.isDebugEnabled()) {
String outputString =
XMLUtils.prettyDocumentToString(doc);
LOG.debug(outputString);
}
//
// Do some processing - disable the validator to make sure that the Timestamp processor
// is rejecting the Timestamp
//
WSSConfig wssConfig = WSSConfig.getNewInstance();
wssConfig.setValidator(WSConstants.TIMESTAMP, new NoOpValidator());
try {
verify(doc, wssConfig, new ArrayList<>());
fail("The timestamp validation should have failed");
} catch (WSSecurityException ex) {
assertTrue(ex.getErrorCode() == WSSecurityException.ErrorCode.INVALID_SECURITY);
}
}
/**
* This is a test for processing an Timestamp where it contains a Created element with
* a ValueType. This should be rejected as per the BSP spec.
*/
@Test
public void testCreatedValueType() throws Exception {
Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
WSSecHeader secHeader = new WSSecHeader(doc);
secHeader.insertSecurityHeader();
Element timestampElement =
doc.createElementNS(
WSConstants.WSU_NS, WSConstants.WSU_PREFIX + ":" + WSConstants.TIMESTAMP_TOKEN_LN
);
Element elementCreated =
doc.createElementNS(
WSConstants.WSU_NS, WSConstants.WSU_PREFIX + ":" + WSConstants.CREATED_LN
);
ZonedDateTime now = ZonedDateTime.now(ZoneOffset.UTC);
elementCreated.appendChild(doc.createTextNode(DateUtil.getDateTimeFormatter(true).format(now)));
elementCreated.setAttributeNS(null, "ValueType", WSConstants.WSS_SAML_KI_VALUE_TYPE);
timestampElement.appendChild(elementCreated);
secHeader.getSecurityHeaderElement().appendChild(timestampElement);
if (LOG.isDebugEnabled()) {
String outputString =
XMLUtils.prettyDocumentToString(doc);
LOG.debug(outputString);
}
//
// Do some processing
//
try {
verify(doc);
fail("The timestamp validation should have failed");
} catch (WSSecurityException ex) {
assertTrue(ex.getErrorCode() == WSSecurityException.ErrorCode.INVALID_SECURITY);
}
// Now it should pass...
WSSConfig wssConfig = WSSConfig.getNewInstance();
wssConfig.setValidator(WSConstants.TIMESTAMP, new NoOpValidator());
verify(doc, wssConfig, Collections.singletonList(BSPRule.R3225));
}
/**
* This is a test for processing an Timestamp where it contains a CustomElement. This should
* be rejected as per the BSP spec.
*/
@Test
public void testCustomElement() throws Exception {
Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
WSSecHeader secHeader = new WSSecHeader(doc);
secHeader.insertSecurityHeader();
Element timestampElement =
doc.createElementNS(
WSConstants.WSU_NS, WSConstants.WSU_PREFIX + ":" + WSConstants.TIMESTAMP_TOKEN_LN
);
Element elementCreated =
doc.createElementNS(
WSConstants.WSU_NS, WSConstants.WSU_PREFIX + ":" + WSConstants.CREATED_LN
);
ZonedDateTime now = ZonedDateTime.now(ZoneOffset.UTC);
elementCreated.appendChild(doc.createTextNode(DateUtil.getDateTimeFormatter(true).format(now)));
timestampElement.appendChild(elementCreated);
Element elementExpires =
doc.createElementNS(
WSConstants.WSU_NS, WSConstants.WSU_PREFIX + ":" + WSConstants.EXPIRES_LN
);
now = now.plusSeconds(300L);
elementExpires.appendChild(doc.createTextNode(DateUtil.getDateTimeFormatter(true).format(now)));
timestampElement.appendChild(elementExpires);
Element elementCustom =
doc.createElementNS(
WSConstants.WSU_NS, WSConstants.WSU_PREFIX + ":" + "Custom"
);
timestampElement.appendChild(elementCustom);
secHeader.getSecurityHeaderElement().appendChild(timestampElement);
if (LOG.isDebugEnabled()) {
String outputString =
XMLUtils.prettyDocumentToString(doc);
LOG.debug(outputString);
}
//
// Do some processing
//
try {
verify(doc);
fail("The timestamp validation should have failed");
} catch (WSSecurityException ex) {
assertTrue(ex.getErrorCode() == WSSecurityException.ErrorCode.INVALID_SECURITY);
}
// Now it should pass...
verify(doc, Collections.singletonList(BSPRule.R3222));
}
/**
* This is a test to create a "Spoofed" Timestamp (see WSS-441)
*/
@Test
public void testSpoofedTimestamp() throws Exception {
Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
WSSecHeader secHeader = new WSSecHeader(doc);
secHeader.insertSecurityHeader();
WSSecTimestamp timestamp = new WSSecTimestamp(secHeader);
timestamp.setTimeToLive(300);
WSTimeSource spoofedTimeSource = new WSTimeSource() {
public Instant now() {
return Instant.now().minusSeconds(500L);
}
};
timestamp.setWsTimeSource(spoofedTimeSource);
Document createdDoc = timestamp.build();
if (LOG.isDebugEnabled()) {
String outputString =
XMLUtils.prettyDocumentToString(createdDoc);
LOG.debug(outputString);
}
//
// Do some processing
//
try {
verify(createdDoc);
fail("Expected failure on an expired timestamp");
} catch (WSSecurityException ex) {
assertTrue(ex.getErrorCode() == WSSecurityException.ErrorCode.MESSAGE_EXPIRED);
}
}
@Test
public void testTimestampNoMilliseconds() throws Exception {
Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
WSSecHeader secHeader = new WSSecHeader(doc);
secHeader.insertSecurityHeader();
WSSecTimestamp timestamp = new WSSecTimestamp(secHeader);
timestamp.setPrecisionInMilliSeconds(false);
timestamp.setTimeToLive(300);
Document createdDoc = timestamp.build();
if (LOG.isDebugEnabled()) {
String outputString =
XMLUtils.prettyDocumentToString(createdDoc);
LOG.debug(outputString);
}
//
// Do some processing
//
WSHandlerResult wsResult = verify(createdDoc);
WSSecurityEngineResult actionResult =
wsResult.getActionResults().get(WSConstants.TS).get(0);
assertNotNull(actionResult);
}
@Test
public void testThaiLocaleVerification() throws Exception {
Locale defaultLocale = Locale.getDefault();
try {
Locale.setDefault(new Locale("th", "TH"));
Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
WSSecHeader secHeader = new WSSecHeader(doc);
secHeader.insertSecurityHeader();
WSSecTimestamp timestamp = new WSSecTimestamp(secHeader);
timestamp.setTimeToLive(300);
Document createdDoc = timestamp.build();
//
// Do some processing
//
WSHandlerResult wsResult = verify(createdDoc);
WSSecurityEngineResult actionResult =
wsResult.getActionResults().get(WSConstants.TS).get(0);
assertNotNull(actionResult);
} finally {
Locale.setDefault(defaultLocale);
}
}
/**
* Verifies the soap envelope
*/
private WSHandlerResult verify(
Document doc
) throws Exception {
WSSecurityEngine secEngine = new WSSecurityEngine();
RequestData requestData = new RequestData();
requestData.setWssConfig(WSSConfig.getNewInstance());
return secEngine.processSecurityHeader(doc, requestData);
}
private WSHandlerResult verify(
Document doc, RequestData requestData
) throws Exception {
WSSecurityEngine secEngine = new WSSecurityEngine();
return secEngine.processSecurityHeader(doc, requestData);
}
/**
* Verifies the soap envelope
*/
private WSHandlerResult verify(
Document doc, List<BSPRule> ignoredRules
) throws Exception {
WSSecurityEngine secEngine = new WSSecurityEngine();
RequestData requestData = new RequestData();
requestData.setIgnoredBSPRules(ignoredRules);
return secEngine.processSecurityHeader(doc, requestData);
}
/**
* Verifies the soap envelope
*/
private WSHandlerResult verify(
Document doc, WSSConfig wssConfig, List<BSPRule> ignoredRules
) throws Exception {
WSSecurityEngine secEngine = new WSSecurityEngine();
RequestData requestData = new RequestData();
requestData.setWssConfig(wssConfig);
requestData.setIgnoredBSPRules(ignoredRules);
return secEngine.processSecurityHeader(doc, requestData);
}
}