/** * 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.common.SecurityTestUtil; 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.Test; import org.w3c.dom.Document; import org.w3c.dom.Element; /** * WS-Security Test Case for Timestamps. */ public class TimestampTest extends org.junit.Assert { private static final org.slf4j.Logger LOG = org.slf4j.LoggerFactory.getLogger(TimestampTest.class); @org.junit.AfterClass public static void cleanup() throws Exception { SecurityTestUtil.cleanup(); } /** * 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); assertTrue(actionResult != null); Timestamp receivedTimestamp = (Timestamp)actionResult.get(WSSecurityEngineResult.TAG_TIMESTAMP); assertTrue(receivedTimestamp != null); 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); assertTrue(actionResult != null); Timestamp receivedTimestamp = (Timestamp)actionResult.get(WSSecurityEngineResult.TAG_TIMESTAMP); assertTrue(receivedTimestamp != null); } @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); assertTrue(actionResult != null); Timestamp receivedTimestamp = (Timestamp)actionResult.get(WSSecurityEngineResult.TAG_TIMESTAMP); assertTrue(receivedTimestamp != null); } /** * 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); assertTrue(actionResult != null); } @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); assertTrue(actionResult != null); } 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); } }