View Javadoc
1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements. See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership. The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License. You may obtain a copy of the License at
9    *
10   * http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied. See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.wss4j.stax.test;
20  
21  import java.io.ByteArrayInputStream;
22  import java.io.ByteArrayOutputStream;
23  import java.io.InputStream;
24  import java.nio.charset.StandardCharsets;
25  import java.time.ZoneOffset;
26  import java.time.ZonedDateTime;
27  import java.util.ArrayList;
28  import java.util.HashMap;
29  import java.util.List;
30  import java.util.Map;
31  import java.util.Properties;
32  
33  import javax.xml.stream.XMLStreamException;
34  import javax.xml.stream.XMLStreamReader;
35  import javax.xml.stream.XMLStreamWriter;
36  import javax.xml.transform.dom.DOMSource;
37  import javax.xml.transform.stream.StreamResult;
38  
39  import org.apache.wss4j.common.ConfigurationConstants;
40  import org.apache.wss4j.common.bsp.BSPRule;
41  import org.apache.wss4j.common.ext.WSSecurityException;
42  import org.apache.wss4j.common.util.DateUtil;
43  import org.apache.wss4j.dom.handler.WSHandlerConstants;
44  import org.apache.wss4j.stax.ext.WSSConstants;
45  import org.apache.wss4j.stax.ext.WSSSecurityProperties;
46  import org.apache.wss4j.stax.setup.ConfigurationConverter;
47  import org.apache.wss4j.stax.setup.InboundWSSec;
48  import org.apache.wss4j.stax.setup.OutboundWSSec;
49  import org.apache.wss4j.stax.setup.WSSec;
50  import org.apache.wss4j.stax.test.utils.StAX2DOM;
51  import org.apache.wss4j.stax.test.utils.XmlReaderToWriter;
52  import org.apache.xml.security.stax.securityEvent.SecurityEvent;
53  import org.junit.jupiter.api.Test;
54  import org.w3c.dom.Document;
55  import org.w3c.dom.Element;
56  import org.w3c.dom.Node;
57  import org.w3c.dom.NodeList;
58  
59  import static org.junit.jupiter.api.Assertions.fail;
60  import static org.junit.jupiter.api.Assertions.assertEquals;
61  import static org.junit.jupiter.api.Assertions.assertFalse;
62  import static org.junit.jupiter.api.Assertions.assertNotNull;
63  import static org.junit.jupiter.api.Assertions.assertTrue;
64  
65  public class TimestampTest extends AbstractTestBase {
66  
67      @Test
68      public void testTimestampDefaultConfigurationOutbound() throws Exception {
69  
70          ByteArrayOutputStream baos = new ByteArrayOutputStream();
71          {
72              WSSSecurityProperties securityProperties = new WSSSecurityProperties();
73              List<WSSConstants.Action> actions = new ArrayList<>();
74              actions.add(WSSConstants.TIMESTAMP);
75              securityProperties.setActions(actions);
76  
77              OutboundWSSec wsSecOut = WSSec.getOutboundWSSec(securityProperties);
78              XMLStreamWriter xmlStreamWriter = wsSecOut.processOutMessage(baos, StandardCharsets.UTF_8.name(), new ArrayList<SecurityEvent>());
79              XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml"));
80              XmlReaderToWriter.writeAll(xmlStreamReader, xmlStreamWriter);
81              xmlStreamWriter.close();
82  
83              Document document = documentBuilderFactory.newDocumentBuilder().parse(new ByteArrayInputStream(baos.toByteArray()));
84              NodeList nodeList = document.getElementsByTagNameNS(WSSConstants.TAG_WSU_TIMESTAMP.getNamespaceURI(), WSSConstants.TAG_WSU_TIMESTAMP.getLocalPart());
85              assertEquals(nodeList.getLength(), 1);
86              assertEquals(nodeList.item(0).getParentNode().getLocalName(), WSSConstants.TAG_WSSE_SECURITY.getLocalPart());
87  
88              Element created = (Element) ((Element) nodeList.item(0)).getElementsByTagNameNS(WSSConstants.TAG_WSU_CREATED.getNamespaceURI(), WSSConstants.TAG_WSU_CREATED.getLocalPart()).item(0);
89              Element expires = (Element) ((Element) nodeList.item(0)).getElementsByTagNameNS(WSSConstants.TAG_WSU_EXPIRES.getNamespaceURI(), WSSConstants.TAG_WSU_EXPIRES.getLocalPart()).item(0);
90  
91              ZonedDateTime createdDateTime = ZonedDateTime.parse(created.getTextContent());
92              ZonedDateTime expiresDateTime = ZonedDateTime.parse(expires.getTextContent());
93  
94              ZonedDateTime now = ZonedDateTime.now(ZoneOffset.UTC);
95              assertFalse(now.isBefore(createdDateTime));
96              assertTrue(now.isBefore(expiresDateTime));
97  
98              assertTrue(createdDateTime.plusSeconds(301L).isAfter(expiresDateTime));
99          }
100 
101         //done timestamp; now test timestamp verification:
102         {
103             String action = WSHandlerConstants.TIMESTAMP;
104             doInboundSecurityWithWSS4J(documentBuilderFactory.newDocumentBuilder().parse(new ByteArrayInputStream(baos.toByteArray())), action);
105         }
106     }
107 
108     @Test
109     public void testTimestampDefaultConfigurationInbound() throws Exception {
110 
111         ByteArrayOutputStream baos = new ByteArrayOutputStream();
112         {
113             InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
114             String action = WSHandlerConstants.TIMESTAMP;
115             Document securedDocument = doOutboundSecurityWithWSS4J(sourceDocument, action, new Properties());
116 
117             //some test that we can really sure we get what we want from WSS4J
118             NodeList nodeList = securedDocument.getElementsByTagNameNS(WSSConstants.TAG_WSU_TIMESTAMP.getNamespaceURI(), WSSConstants.TAG_WSU_TIMESTAMP.getLocalPart());
119             assertEquals(nodeList.item(0).getParentNode().getLocalName(), WSSConstants.TAG_WSSE_SECURITY.getLocalPart());
120 
121             javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
122             transformer.transform(new DOMSource(securedDocument), new StreamResult(baos));
123         }
124 
125         //done timestamp; now test timestamp-verification:
126         {
127             WSSSecurityProperties securityProperties = new WSSSecurityProperties();
128             InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties);
129             XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())));
130 
131             Document document = StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
132 
133             //header element must still be there
134             NodeList nodeList = document.getElementsByTagNameNS(WSSConstants.TAG_WSU_TIMESTAMP.getNamespaceURI(), WSSConstants.TAG_WSU_TIMESTAMP.getLocalPart());
135             assertEquals(nodeList.getLength(), 1);
136             assertEquals(nodeList.item(0).getParentNode().getLocalName(), WSSConstants.TAG_WSSE_SECURITY.getLocalPart());
137         }
138     }
139 
140     @Test
141     public void testTimestampTTLOutbound() throws Exception {
142 
143         ByteArrayOutputStream baos = new ByteArrayOutputStream();
144         {
145             WSSSecurityProperties securityProperties = new WSSSecurityProperties();
146             List<WSSConstants.Action> actions = new ArrayList<>();
147             actions.add(WSSConstants.TIMESTAMP);
148             securityProperties.setActions(actions);
149             securityProperties.setTimestampTTL(3600);
150 
151             OutboundWSSec wsSecOut = WSSec.getOutboundWSSec(securityProperties);
152             XMLStreamWriter xmlStreamWriter = wsSecOut.processOutMessage(baos, StandardCharsets.UTF_8.name(), new ArrayList<SecurityEvent>());
153             XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml"));
154             XmlReaderToWriter.writeAll(xmlStreamReader, xmlStreamWriter);
155             xmlStreamWriter.close();
156 
157             Document document = documentBuilderFactory.newDocumentBuilder().parse(new ByteArrayInputStream(baos.toByteArray()));
158             NodeList nodeList = document.getElementsByTagNameNS(WSSConstants.TAG_WSU_TIMESTAMP.getNamespaceURI(), WSSConstants.TAG_WSU_TIMESTAMP.getLocalPart());
159             assertEquals(nodeList.getLength(), 1);
160             assertEquals(nodeList.item(0).getParentNode().getLocalName(), WSSConstants.TAG_WSSE_SECURITY.getLocalPart());
161 
162             Element created = (Element) ((Element) nodeList.item(0)).getElementsByTagNameNS(WSSConstants.TAG_WSU_CREATED.getNamespaceURI(), WSSConstants.TAG_WSU_CREATED.getLocalPart()).item(0);
163             Element expires = (Element) ((Element) nodeList.item(0)).getElementsByTagNameNS(WSSConstants.TAG_WSU_EXPIRES.getNamespaceURI(), WSSConstants.TAG_WSU_EXPIRES.getLocalPart()).item(0);
164 
165             ZonedDateTime createdDateTime = ZonedDateTime.parse(created.getTextContent());
166             ZonedDateTime expiresDateTime = ZonedDateTime.parse(expires.getTextContent());
167             
168             assertTrue(createdDateTime.isBefore(expiresDateTime));
169             
170             ZonedDateTime now = ZonedDateTime.now(ZoneOffset.UTC);
171             assertFalse(now.isBefore(createdDateTime));
172             assertTrue(now.isBefore(expiresDateTime));
173 
174             assertTrue(createdDateTime.plusSeconds(3601L).isAfter(expiresDateTime));
175         }
176 
177         //done timestamp; now test timestamp verification:
178         {
179             String action = WSHandlerConstants.TIMESTAMP;
180             doInboundSecurityWithWSS4J(documentBuilderFactory.newDocumentBuilder().parse(new ByteArrayInputStream(baos.toByteArray())), action);
181         }
182     }
183 
184     @Test
185     public void testTimestampExpiredInbound() throws Exception {
186 
187         ByteArrayOutputStream baos = new ByteArrayOutputStream();
188         {
189             InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
190             String action = WSHandlerConstants.TIMESTAMP;
191             Properties outboundProperties = new Properties();
192             outboundProperties.setProperty(WSHandlerConstants.TTL_TIMESTAMP, "1");
193             Document securedDocument = doOutboundSecurityWithWSS4J(sourceDocument, action, outboundProperties);
194 
195             //some test that we can really sure we get what we want from WSS4J
196             NodeList nodeList = securedDocument.getElementsByTagNameNS(WSSConstants.TAG_WSU_TIMESTAMP.getNamespaceURI(), WSSConstants.TAG_WSU_TIMESTAMP.getLocalPart());
197             assertEquals(nodeList.item(0).getParentNode().getLocalName(), WSSConstants.TAG_WSSE_SECURITY.getLocalPart());
198 
199             javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
200             transformer.transform(new DOMSource(securedDocument), new StreamResult(baos));
201         }
202 
203         Thread.sleep(1500);
204 
205         //done timestamp; now test timestamp-verification:
206         {
207             WSSSecurityProperties securityProperties = new WSSSecurityProperties();
208             InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties, false, true);
209             XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())));
210 
211             try {
212                 StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
213                 fail("Expected XMLStreamException");
214             } catch (XMLStreamException e) {
215                 assertNotNull(e.getCause());
216                 assertTrue(e.getCause() instanceof WSSecurityException);
217                 assertEquals(((WSSecurityException) e.getCause()).getFaultCode(), WSSecurityException.MESSAGE_EXPIRED);
218             }
219         }
220     }
221 
222     @Test
223     public void testTimestampExpiredEncryptedInbound() throws Exception {
224 
225         ByteArrayOutputStream baos = new ByteArrayOutputStream();
226         {
227             InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
228             String action = WSHandlerConstants.TIMESTAMP + " " + WSHandlerConstants.ENCRYPTION;
229             Properties outboundProperties = new Properties();
230             outboundProperties.setProperty(WSHandlerConstants.TTL_TIMESTAMP, "1");
231             outboundProperties.setProperty(WSHandlerConstants.ENCRYPTION_PARTS, "{Element}{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd}Timestamp;");
232             Document securedDocument = doOutboundSecurityWithWSS4J(sourceDocument, action, outboundProperties);
233 
234             //some test that we can really sure we get what we want from WSS4J
235             NodeList nodeList = securedDocument.getElementsByTagNameNS(WSSConstants.TAG_xenc_EncryptedKey.getNamespaceURI(), WSSConstants.TAG_xenc_EncryptedKey.getLocalPart());
236             assertEquals(nodeList.item(0).getParentNode().getLocalName(), WSSConstants.TAG_WSSE_SECURITY.getLocalPart());
237 
238             javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
239             transformer.transform(new DOMSource(securedDocument), new StreamResult(baos));
240         }
241 
242         Thread.sleep(1500);
243 
244         //done timestamp; now test timestamp-verification:
245         {
246             WSSSecurityProperties securityProperties = new WSSSecurityProperties();
247             securityProperties.setCallbackHandler(new CallbackHandlerImpl());
248             securityProperties.loadDecryptionKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
249             InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties, false, true);
250             XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())));
251 
252             try {
253                 StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
254                 fail("Expected XMLStreamException");
255             } catch (XMLStreamException e) {
256                 assertNotNull(e.getCause());
257                 assertTrue(e.getCause() instanceof WSSecurityException);
258                 assertEquals(((WSSecurityException) e.getCause()).getFaultCode(), WSSecurityException.MESSAGE_EXPIRED);
259             }
260         }
261     }
262 
263     @Test
264     public void testTimestampInNearFutureInbound() throws Exception {
265 
266         ByteArrayOutputStream baos = new ByteArrayOutputStream();
267         {
268             InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
269             String action = WSHandlerConstants.TIMESTAMP;
270             Properties outboundProperties = new Properties();
271             outboundProperties.setProperty(WSHandlerConstants.TTL_TIMESTAMP, "1");
272             Document securedDocument = doOutboundSecurityWithWSS4J(sourceDocument, action, outboundProperties);
273 
274             //some test that we can really sure we get what we want from WSS4J
275             NodeList nodeList = securedDocument.getElementsByTagNameNS(WSSConstants.TAG_WSU_TIMESTAMP.getNamespaceURI(), WSSConstants.TAG_WSU_TIMESTAMP.getLocalPart());
276             assertEquals(nodeList.item(0).getParentNode().getLocalName(), WSSConstants.TAG_WSSE_SECURITY.getLocalPart());
277 
278             Element created = (Element) ((Element) nodeList.item(0)).getElementsByTagNameNS(WSSConstants.TAG_WSU_CREATED.getNamespaceURI(), WSSConstants.TAG_WSU_CREATED.getLocalPart()).item(0);
279             Element expires = (Element) ((Element) nodeList.item(0)).getElementsByTagNameNS(WSSConstants.TAG_WSU_EXPIRES.getNamespaceURI(), WSSConstants.TAG_WSU_EXPIRES.getLocalPart()).item(0);
280 
281             ZonedDateTime createdDateTime = ZonedDateTime.now(ZoneOffset.UTC).plusSeconds(40L);
282             created.setTextContent(DateUtil.getDateTimeFormatter(true).format(createdDateTime));
283 
284             ZonedDateTime expiresDateTime = ZonedDateTime.now(ZoneOffset.UTC).plusSeconds(300L);
285             expires.setTextContent(DateUtil.getDateTimeFormatter(true).format(expiresDateTime));
286 
287             javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
288             transformer.transform(new DOMSource(securedDocument), new StreamResult(baos));
289         }
290 
291         //done timestamp; now test timestamp-verification:
292         {
293             WSSSecurityProperties securityProperties = new WSSSecurityProperties();
294             InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties);
295             XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())));
296 
297             StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
298         }
299     }
300 
301     @Test
302     public void testTimestampInFutureInbound() throws Exception {
303 
304         ByteArrayOutputStream baos = new ByteArrayOutputStream();
305         {
306             InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
307             String action = WSHandlerConstants.TIMESTAMP;
308             Properties outboundProperties = new Properties();
309             outboundProperties.setProperty(WSHandlerConstants.TTL_TIMESTAMP, "1");
310             Document securedDocument = doOutboundSecurityWithWSS4J(sourceDocument, action, outboundProperties);
311 
312             //some test that we can really sure we get what we want from WSS4J
313             NodeList nodeList = securedDocument.getElementsByTagNameNS(WSSConstants.TAG_WSU_TIMESTAMP.getNamespaceURI(), WSSConstants.TAG_WSU_TIMESTAMP.getLocalPart());
314             assertEquals(nodeList.item(0).getParentNode().getLocalName(), WSSConstants.TAG_WSSE_SECURITY.getLocalPart());
315 
316             Element created = (Element) ((Element) nodeList.item(0)).getElementsByTagNameNS(WSSConstants.TAG_WSU_CREATED.getNamespaceURI(), WSSConstants.TAG_WSU_CREATED.getLocalPart()).item(0);
317             Element expires = (Element) ((Element) nodeList.item(0)).getElementsByTagNameNS(WSSConstants.TAG_WSU_EXPIRES.getNamespaceURI(), WSSConstants.TAG_WSU_EXPIRES.getLocalPart()).item(0);
318 
319             ZonedDateTime createdDateTime = ZonedDateTime.now(ZoneOffset.UTC).plusHours(2L);
320             created.setTextContent(DateUtil.getDateTimeFormatter(true).format(createdDateTime));
321 
322             ZonedDateTime expiresDateTime = ZonedDateTime.now(ZoneOffset.UTC).plusHours(2L).plusSeconds(300L);
323             expires.setTextContent(DateUtil.getDateTimeFormatter(true).format(expiresDateTime));
324             
325             javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
326             transformer.transform(new DOMSource(securedDocument), new StreamResult(baos));
327         }
328 
329         //done timestamp; now test timestamp-verification:
330         {
331             WSSSecurityProperties securityProperties = new WSSSecurityProperties();
332             InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties, false, true);
333             XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())));
334 
335             try {
336                 StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
337                 fail("Expected XMLStreamException");
338             } catch (XMLStreamException e) {
339                 assertNotNull(e.getCause());
340                 assertTrue(e.getCause() instanceof WSSecurityException);
341                 assertEquals(((WSSecurityException) e.getCause()).getFaultCode(), WSSecurityException.MESSAGE_EXPIRED);
342             }
343         }
344 
345         // now allow future TTL of 2 hours +
346         {
347             WSSSecurityProperties securityProperties = new WSSSecurityProperties();
348             securityProperties.setTimeStampFutureTTL(2 * 60 * 60 + 100);
349 
350             InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties);
351             XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())));
352 
353             StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
354         }
355     }
356 
357     @Test
358     public void testTimestampStrictOffInbound() throws Exception {
359 
360         ByteArrayOutputStream baos = new ByteArrayOutputStream();
361         {
362             InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
363             String action = WSHandlerConstants.TIMESTAMP;
364             Properties outboundProperties = new Properties();
365             outboundProperties.setProperty(WSHandlerConstants.TTL_TIMESTAMP, "1");
366             Document securedDocument = doOutboundSecurityWithWSS4J(sourceDocument, action, outboundProperties);
367 
368             //some test that we can really sure we get what we want from WSS4J
369             NodeList nodeList = securedDocument.getElementsByTagNameNS(WSSConstants.TAG_WSU_TIMESTAMP.getNamespaceURI(), WSSConstants.TAG_WSU_TIMESTAMP.getLocalPart());
370             assertEquals(nodeList.item(0).getParentNode().getLocalName(), WSSConstants.TAG_WSSE_SECURITY.getLocalPart());
371 
372             javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
373             transformer.transform(new DOMSource(securedDocument), new StreamResult(baos));
374         }
375 
376         Thread.sleep(1000);
377 
378         //done timestamp; now test timestamp-verification:
379         {
380             WSSSecurityProperties securityProperties = new WSSSecurityProperties();
381             securityProperties.setStrictTimestampCheck(false);
382             InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties);
383             XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())));
384 
385             StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
386         }
387     }
388 
389     @Test
390     public void testTimestampTTLInbound() throws Exception {
391 
392         ByteArrayOutputStream baos = new ByteArrayOutputStream();
393         {
394             InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
395             String action = WSHandlerConstants.TIMESTAMP;
396             Properties outboundProperties = new Properties();
397             outboundProperties.setProperty(WSHandlerConstants.TTL_TIMESTAMP, "300");
398             Document securedDocument = doOutboundSecurityWithWSS4J(sourceDocument, action, outboundProperties);
399 
400             //some test that we can really sure we get what we want from WSS4J
401             NodeList nodeList = securedDocument.getElementsByTagNameNS(WSSConstants.TAG_WSU_TIMESTAMP.getNamespaceURI(), WSSConstants.TAG_WSU_TIMESTAMP.getLocalPart());
402             assertEquals(nodeList.item(0).getParentNode().getLocalName(), WSSConstants.TAG_WSSE_SECURITY.getLocalPart());
403 
404             javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
405             transformer.transform(new DOMSource(securedDocument), new StreamResult(baos));
406         }
407 
408         Thread.sleep(1500);
409 
410         //done timestamp; now test timestamp-verification:
411         {
412             WSSSecurityProperties securityProperties = new WSSSecurityProperties();
413             securityProperties.setTimestampTTL(1);
414             InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties, false, true);
415             XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())));
416 
417             try {
418                 StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
419                 fail("Expected XMLStreamException");
420             } catch (XMLStreamException e) {
421                 assertNotNull(e.getCause());
422                 assertTrue(e.getCause() instanceof WSSecurityException);
423                 assertEquals(((WSSecurityException) e.getCause()).getFaultCode(), WSSecurityException.MESSAGE_EXPIRED);
424             }
425         }
426     }
427 
428     @Test
429     public void testTimestampNoCreatedDateInbound() throws Exception {
430 
431         ByteArrayOutputStream baos = new ByteArrayOutputStream();
432         {
433             InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
434             String action = WSHandlerConstants.TIMESTAMP;
435             Document securedDocument = doOutboundSecurityWithWSS4J(sourceDocument, action, new Properties());
436 
437             //some test that we can really sure we get what we want from WSS4J
438             NodeList nodeList = securedDocument.getElementsByTagNameNS(WSSConstants.TAG_WSU_TIMESTAMP.getNamespaceURI(), WSSConstants.TAG_WSU_TIMESTAMP.getLocalPart());
439             assertEquals(nodeList.item(0).getParentNode().getLocalName(), WSSConstants.TAG_WSSE_SECURITY.getLocalPart());
440             for (int i = 0; i < nodeList.item(0).getChildNodes().getLength(); i++) {
441                 Node node = nodeList.item(0).getChildNodes().item(i);
442                 if (node.getNodeType() == Node.ELEMENT_NODE && node.getLocalName().equals("Created")) {
443                     node.getParentNode().removeChild(node);
444                 }
445             }
446 
447             javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
448             transformer.transform(new DOMSource(securedDocument), new StreamResult(baos));
449         }
450 
451         //done timestamp; now test timestamp-verification:
452         {
453             WSSSecurityProperties securityProperties = new WSSSecurityProperties();
454             securityProperties.addIgnoreBSPRule(BSPRule.R3203);
455             securityProperties.addIgnoreBSPRule(BSPRule.R3221);
456             InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties, false, true);
457             XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())));
458 
459             try {
460                 StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
461                 fail("Expected XMLStreamException");
462             } catch (XMLStreamException e) {
463                 Throwable throwable = e.getCause();
464                 assertNotNull(throwable);
465                 assertTrue(throwable instanceof WSSecurityException);
466                 assertEquals(((WSSecurityException) throwable).getFaultCode(), WSSecurityException.INVALID_SECURITY);
467             }
468         }
469     }
470 
471     @Test
472     public void testTimestampNoExpiresDateInbound() throws Exception {
473 
474         ByteArrayOutputStream baos = new ByteArrayOutputStream();
475         {
476             InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
477             String action = WSHandlerConstants.TIMESTAMP;
478             Document securedDocument = doOutboundSecurityWithWSS4J(sourceDocument, action, new Properties());
479 
480             //some test that we can really sure we get what we want from WSS4J
481             NodeList nodeList = securedDocument.getElementsByTagNameNS(WSSConstants.TAG_WSU_TIMESTAMP.getNamespaceURI(), WSSConstants.TAG_WSU_TIMESTAMP.getLocalPart());
482             assertEquals(nodeList.item(0).getParentNode().getLocalName(), WSSConstants.TAG_WSSE_SECURITY.getLocalPart());
483             for (int i = 0; i < nodeList.item(0).getChildNodes().getLength(); i++) {
484                 Node node = nodeList.item(0).getChildNodes().item(i);
485                 if (node.getNodeType() == Node.ELEMENT_NODE && node.getLocalName().equals("Expires")) {
486                     node.getParentNode().removeChild(node);
487                 }
488             }
489 
490             javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
491             transformer.transform(new DOMSource(securedDocument), new StreamResult(baos));
492         }
493 
494         //done timestamp; now test timestamp-verification:
495         {
496             WSSSecurityProperties securityProperties = new WSSSecurityProperties();
497             InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties);
498             XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())));
499 
500             Document document = StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
501 
502             //header element must still be there
503             NodeList nodeList = document.getElementsByTagNameNS(WSSConstants.TAG_WSU_TIMESTAMP.getNamespaceURI(), WSSConstants.TAG_WSU_TIMESTAMP.getLocalPart());
504             assertEquals(nodeList.getLength(), 1);
505             assertEquals(nodeList.item(0).getParentNode().getLocalName(), WSSConstants.TAG_WSSE_SECURITY.getLocalPart());
506         }
507     }
508 
509     @Test
510     public void testTimestampInvalidNoExpiresDateInbound() throws Exception {
511 
512         ByteArrayOutputStream baos = new ByteArrayOutputStream();
513         {
514             InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
515             String action = WSHandlerConstants.TIMESTAMP;
516             Document securedDocument = doOutboundSecurityWithWSS4J(sourceDocument, action, new Properties());
517 
518             //some test that we can really sure we get what we want from WSS4J
519             NodeList nodeList = securedDocument.getElementsByTagNameNS(WSSConstants.TAG_WSU_TIMESTAMP.getNamespaceURI(), WSSConstants.TAG_WSU_TIMESTAMP.getLocalPart());
520             assertEquals(nodeList.item(0).getParentNode().getLocalName(), WSSConstants.TAG_WSSE_SECURITY.getLocalPart());
521             for (int i = 0; i < nodeList.item(0).getChildNodes().getLength(); i++) {
522                 Node node = nodeList.item(0).getChildNodes().item(i);
523                 if (node.getNodeType() == Node.ELEMENT_NODE && node.getLocalName().equals("Expires")) {
524                     node.getParentNode().removeChild(node);
525                 }
526             }
527 
528             javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
529             transformer.transform(new DOMSource(securedDocument), new StreamResult(baos));
530         }
531 
532         // Require a Timestamp Expires Element - should fail
533         {
534             WSSSecurityProperties securityProperties = new WSSSecurityProperties();
535             securityProperties.setRequireTimestampExpires(true);
536             InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties);
537             XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())));
538 
539             try {
540                 StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
541                 fail("Failure expected on no Expires Element");
542             } catch (XMLStreamException e) {
543                 assertNotNull(e.getCause());
544                 assertTrue(e.getCause() instanceof WSSecurityException);
545             }
546         }
547 
548         // No Timestamp Expires Element required - should pass
549         {
550             WSSSecurityProperties securityProperties = new WSSSecurityProperties();
551             InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties);
552             XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())));
553 
554             Document document = StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
555 
556             //header element must still be there
557             NodeList nodeList = document.getElementsByTagNameNS(WSSConstants.TAG_WSU_TIMESTAMP.getNamespaceURI(), WSSConstants.TAG_WSU_TIMESTAMP.getLocalPart());
558             assertEquals(nodeList.getLength(), 1);
559             assertEquals(nodeList.item(0).getParentNode().getLocalName(), WSSConstants.TAG_WSSE_SECURITY.getLocalPart());
560         }
561     }
562 
563     @Test
564     public void testTimestampNoChildsInbound() throws Exception {
565 
566         ByteArrayOutputStream baos = new ByteArrayOutputStream();
567         {
568             InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
569             String action = WSHandlerConstants.TIMESTAMP;
570             Document securedDocument = doOutboundSecurityWithWSS4J(sourceDocument, action, new Properties());
571 
572             //some test that we can really sure we get what we want from WSS4J
573             NodeList nodeList = securedDocument.getElementsByTagNameNS(WSSConstants.TAG_WSU_TIMESTAMP.getNamespaceURI(), WSSConstants.TAG_WSU_TIMESTAMP.getLocalPart());
574             assertEquals(nodeList.item(0).getParentNode().getLocalName(), WSSConstants.TAG_WSSE_SECURITY.getLocalPart());
575 
576             List<Node> nodesToRemove = new ArrayList<>();
577             for (int i = 0; i < nodeList.item(0).getChildNodes().getLength(); i++) {
578                 Node node = nodeList.item(0).getChildNodes().item(i);
579                 if (node.getNodeType() == Node.ELEMENT_NODE
580                         && (node.getLocalName().equals("Created")) || node.getLocalName().equals("Expires")) {
581                     nodesToRemove.add(node);
582                 }
583             }
584             for (Node node : nodesToRemove) {
585                 node.getParentNode().removeChild(node);
586             }
587 
588             javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
589             transformer.transform(new DOMSource(securedDocument), new StreamResult(baos));
590         }
591 
592         //done timestamp; now test timestamp-verification:
593         {
594             WSSSecurityProperties securityProperties = new WSSSecurityProperties();
595             securityProperties.addIgnoreBSPRule(BSPRule.R3203);
596             InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties, false, true);
597             XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())));
598 
599             try {
600                 StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
601                 fail("Expected XMLStreamException");
602             } catch (XMLStreamException e) {
603                 Throwable throwable = e.getCause();
604                 assertNotNull(throwable);
605                 assertTrue(throwable instanceof WSSecurityException);
606                 assertEquals(((WSSecurityException) throwable).getFaultCode(), WSSecurityException.INVALID_SECURITY);
607             }
608         }
609     }
610 
611     @Test
612     public void testDoubleTimestamp() throws Exception {
613 
614         ByteArrayOutputStream baos = new ByteArrayOutputStream();
615         {
616             InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
617             String action = WSHandlerConstants.TIMESTAMP;
618             Document securedDocument = doOutboundSecurityWithWSS4J(sourceDocument, action, new Properties());
619 
620             //some test that we can really sure we get what we want from WSS4J
621             NodeList nodeList = securedDocument.getElementsByTagNameNS(WSSConstants.TAG_WSU_TIMESTAMP.getNamespaceURI(), WSSConstants.TAG_WSU_TIMESTAMP.getLocalPart());
622             assertEquals(nodeList.item(0).getParentNode().getLocalName(), WSSConstants.TAG_WSSE_SECURITY.getLocalPart());
623 
624             Node parentNode = nodeList.item(0).getParentNode();
625             Node node = nodeList.item(0).cloneNode(true);
626             securedDocument.adoptNode(node);
627             parentNode.appendChild(node);
628 
629             javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
630             transformer.transform(new DOMSource(securedDocument), new StreamResult(baos));
631         }
632 
633         //done timestamp; now test timestamp-verification:
634         {
635             WSSSecurityProperties securityProperties = new WSSSecurityProperties();
636             InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties, false, true);
637             XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())));
638 
639             try {
640                 StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
641                 fail("Expected XMLStreamException");
642             } catch (XMLStreamException e) {
643                 Throwable throwable = e.getCause();
644                 assertNotNull(throwable);
645                 assertTrue(throwable instanceof WSSecurityException);
646                 assertEquals(((WSSecurityException) throwable).getFaultCode(), WSSecurityException.INVALID_SECURITY);
647             }
648         }
649     }
650 
651     @Test
652     public void testTimestampPropertiesOutbound() throws Exception {
653 
654         ByteArrayOutputStream baos = new ByteArrayOutputStream();
655         {
656             Map<String, Object> config = new HashMap<>();
657             config.put(ConfigurationConstants.ACTION, ConfigurationConstants.TIMESTAMP);
658 
659             WSSSecurityProperties securityProperties = ConfigurationConverter.convert(config);
660             OutboundWSSec wsSecOut = WSSec.getOutboundWSSec(securityProperties);
661             XMLStreamWriter xmlStreamWriter = wsSecOut.processOutMessage(baos, StandardCharsets.UTF_8.name(), new ArrayList<SecurityEvent>());
662             XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml"));
663             XmlReaderToWriter.writeAll(xmlStreamReader, xmlStreamWriter);
664             xmlStreamWriter.close();
665 
666             Document document = documentBuilderFactory.newDocumentBuilder().parse(new ByteArrayInputStream(baos.toByteArray()));
667             NodeList nodeList = document.getElementsByTagNameNS(WSSConstants.TAG_WSU_TIMESTAMP.getNamespaceURI(), WSSConstants.TAG_WSU_TIMESTAMP.getLocalPart());
668             assertEquals(nodeList.getLength(), 1);
669             assertEquals(nodeList.item(0).getParentNode().getLocalName(), WSSConstants.TAG_WSSE_SECURITY.getLocalPart());
670 
671             Element created = (Element) ((Element) nodeList.item(0)).getElementsByTagNameNS(WSSConstants.TAG_WSU_CREATED.getNamespaceURI(), WSSConstants.TAG_WSU_CREATED.getLocalPart()).item(0);
672             Element expires = (Element) ((Element) nodeList.item(0)).getElementsByTagNameNS(WSSConstants.TAG_WSU_EXPIRES.getNamespaceURI(), WSSConstants.TAG_WSU_EXPIRES.getLocalPart()).item(0);
673 
674             ZonedDateTime createdDateTime = ZonedDateTime.parse(created.getTextContent());
675             ZonedDateTime expiresDateTime = ZonedDateTime.parse(expires.getTextContent());
676             
677             assertTrue(createdDateTime.isBefore(expiresDateTime));
678             
679             ZonedDateTime now = ZonedDateTime.now(ZoneOffset.UTC);
680             assertFalse(now.isBefore(createdDateTime));
681             assertTrue(now.isBefore(expiresDateTime));
682 
683             assertTrue(createdDateTime.plusSeconds(301L).isAfter(expiresDateTime));
684         }
685 
686         //done timestamp; now test timestamp verification:
687         {
688             String action = WSHandlerConstants.TIMESTAMP;
689             doInboundSecurityWithWSS4J(documentBuilderFactory.newDocumentBuilder().parse(new ByteArrayInputStream(baos.toByteArray())), action);
690         }
691     }
692 
693     @Test
694     public void testTimestampPropertiesInbound() throws Exception {
695 
696         ByteArrayOutputStream baos = new ByteArrayOutputStream();
697         {
698             InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
699             String action = WSHandlerConstants.TIMESTAMP;
700             Document securedDocument = doOutboundSecurityWithWSS4J(sourceDocument, action, new Properties());
701 
702             //some test that we can really sure we get what we want from WSS4J
703             NodeList nodeList = securedDocument.getElementsByTagNameNS(WSSConstants.TAG_WSU_TIMESTAMP.getNamespaceURI(), WSSConstants.TAG_WSU_TIMESTAMP.getLocalPart());
704             assertEquals(nodeList.item(0).getParentNode().getLocalName(), WSSConstants.TAG_WSSE_SECURITY.getLocalPart());
705 
706             javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
707             transformer.transform(new DOMSource(securedDocument), new StreamResult(baos));
708         }
709 
710         //done timestamp; now test timestamp-verification:
711         {
712             Map<String, Object> config = new HashMap<>();
713             config.put(ConfigurationConstants.ACTION, ConfigurationConstants.TIMESTAMP);
714             WSSSecurityProperties securityProperties = ConfigurationConverter.convert(config);
715             InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties);
716 
717             XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())));
718 
719             Document document = StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
720 
721             //header element must still be there
722             NodeList nodeList = document.getElementsByTagNameNS(WSSConstants.TAG_WSU_TIMESTAMP.getNamespaceURI(), WSSConstants.TAG_WSU_TIMESTAMP.getLocalPart());
723             assertEquals(nodeList.getLength(), 1);
724             assertEquals(nodeList.item(0).getParentNode().getLocalName(), WSSConstants.TAG_WSSE_SECURITY.getLocalPart());
725         }
726     }
727 }