1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.wss4j.dom.message;
21
22 import java.time.Instant;
23 import java.time.ZoneOffset;
24 import java.time.ZonedDateTime;
25 import java.util.ArrayList;
26 import java.util.Collections;
27 import java.util.List;
28 import java.util.Locale;
29
30 import org.apache.wss4j.common.bsp.BSPEnforcer;
31 import org.apache.wss4j.common.bsp.BSPRule;
32 import org.apache.wss4j.common.ext.WSSecurityException;
33 import org.apache.wss4j.common.util.DateUtil;
34 import org.apache.wss4j.common.util.SOAPUtil;
35 import org.apache.wss4j.common.util.WSTimeSource;
36 import org.apache.wss4j.common.util.XMLUtils;
37 import org.apache.wss4j.dom.WSConstants;
38
39 import org.apache.wss4j.dom.engine.WSSConfig;
40 import org.apache.wss4j.dom.engine.WSSecurityEngine;
41 import org.apache.wss4j.dom.engine.WSSecurityEngineResult;
42 import org.apache.wss4j.dom.handler.RequestData;
43 import org.apache.wss4j.dom.handler.WSHandlerResult;
44 import org.apache.wss4j.dom.message.token.Timestamp;
45 import org.apache.wss4j.dom.validate.NoOpValidator;
46
47 import org.junit.jupiter.api.Test;
48 import org.w3c.dom.Document;
49 import org.w3c.dom.Element;
50
51 import static org.junit.jupiter.api.Assertions.assertNotNull;
52 import static org.junit.jupiter.api.Assertions.assertTrue;
53 import static org.junit.jupiter.api.Assertions.fail;
54
55
56
57
58 public class TimestampTest {
59 private static final org.slf4j.Logger LOG =
60 org.slf4j.LoggerFactory.getLogger(TimestampTest.class);
61
62
63
64
65 @Test
66 public void testValidTimestamp() throws Exception {
67
68 Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
69 WSSecHeader secHeader = new WSSecHeader(doc);
70 secHeader.insertSecurityHeader();
71
72 WSSecTimestamp timestamp = new WSSecTimestamp(secHeader);
73 timestamp.setTimeToLive(300);
74 Document createdDoc = timestamp.build();
75
76 if (LOG.isDebugEnabled()) {
77 String outputString =
78 XMLUtils.prettyDocumentToString(createdDoc);
79 LOG.debug(outputString);
80 }
81
82
83
84
85 WSHandlerResult wsResult = verify(createdDoc);
86 WSSecurityEngineResult actionResult =
87 wsResult.getActionResults().get(WSConstants.TS).get(0);
88 assertNotNull(actionResult);
89
90 Timestamp receivedTimestamp =
91 (Timestamp)actionResult.get(WSSecurityEngineResult.TAG_TIMESTAMP);
92 assertNotNull(receivedTimestamp);
93
94 Timestamp clone = new Timestamp(receivedTimestamp.getElement(), new BSPEnforcer(true));
95 assertTrue(clone.equals(receivedTimestamp));
96 assertTrue(clone.hashCode() == receivedTimestamp.hashCode());
97 }
98
99
100
101
102
103 @Test
104 public void testValidTimestampNoExpires() throws Exception {
105
106 Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
107 WSSecHeader secHeader = new WSSecHeader(doc);
108 secHeader.insertSecurityHeader();
109
110 WSSecTimestamp timestamp = new WSSecTimestamp(secHeader);
111 timestamp.setTimeToLive(0);
112 Document createdDoc = timestamp.build();
113
114 if (LOG.isDebugEnabled()) {
115 String outputString =
116 XMLUtils.prettyDocumentToString(createdDoc);
117 LOG.debug(outputString);
118 }
119
120
121
122
123 WSHandlerResult wsResult = verify(createdDoc);
124 WSSecurityEngineResult actionResult =
125 wsResult.getActionResults().get(WSConstants.TS).get(0);
126 assertNotNull(actionResult);
127
128 Timestamp receivedTimestamp =
129 (Timestamp)actionResult.get(WSSecurityEngineResult.TAG_TIMESTAMP);
130 assertNotNull(receivedTimestamp);
131 }
132
133 @Test
134 public void testInvalidTimestampNoExpires() throws Exception {
135
136 Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
137 WSSecHeader secHeader = new WSSecHeader(doc);
138 secHeader.insertSecurityHeader();
139
140 WSSecTimestamp timestamp = new WSSecTimestamp(secHeader);
141 timestamp.setTimeToLive(0);
142 Document createdDoc = timestamp.build();
143
144 if (LOG.isDebugEnabled()) {
145 String outputString =
146 XMLUtils.prettyDocumentToString(createdDoc);
147 LOG.debug(outputString);
148 }
149
150
151
152
153 WSSecurityEngine secEngine = new WSSecurityEngine();
154 RequestData requestData = new RequestData();
155 requestData.setWssConfig(WSSConfig.getNewInstance());
156 requestData.setRequireTimestampExpires(true);
157 try {
158 secEngine.processSecurityHeader(doc, requestData);
159 fail("Failure expected on no Expires Element");
160 } catch (WSSecurityException ex) {
161 assertTrue(ex.getErrorCode() == WSSecurityException.ErrorCode.SECURITY_ERROR);
162 }
163
164 requestData.setWssConfig(WSSConfig.getNewInstance());
165 requestData.setRequireTimestampExpires(false);
166 WSHandlerResult wsResult = secEngine.processSecurityHeader(doc, requestData);
167 WSSecurityEngineResult actionResult =
168 wsResult.getActionResults().get(WSConstants.TS).get(0);
169 assertNotNull(actionResult);
170
171 Timestamp receivedTimestamp =
172 (Timestamp)actionResult.get(WSSecurityEngineResult.TAG_TIMESTAMP);
173 assertNotNull(receivedTimestamp);
174 }
175
176
177
178
179
180 @Test
181 public void testExpiredTimestamp() throws Exception {
182
183 Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
184 WSSecHeader secHeader = new WSSecHeader(doc);
185 secHeader.insertSecurityHeader();
186
187 WSSecTimestamp timestamp = new WSSecTimestamp(secHeader);
188 timestamp.setTimeToLive(-1);
189 Document createdDoc = timestamp.build();
190
191 if (LOG.isDebugEnabled()) {
192 String outputString =
193 XMLUtils.prettyDocumentToString(createdDoc);
194 LOG.debug(outputString);
195 }
196
197 try {
198 verify(createdDoc);
199 fail("Expected failure on an expired timestamp");
200 } catch (WSSecurityException ex) {
201 assertTrue(ex.getErrorCode() == WSSecurityException.ErrorCode.MESSAGE_EXPIRED);
202 }
203 }
204
205
206
207
208
209
210 @Test
211 public void testOldTimestamp() throws Exception {
212
213 Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
214 WSSecHeader secHeader = new WSSecHeader(doc);
215 secHeader.insertSecurityHeader();
216
217 WSSecTimestamp timestamp = new WSSecTimestamp(secHeader);
218 Document createdDoc = timestamp.build();
219
220 if (LOG.isDebugEnabled()) {
221 String outputString =
222 XMLUtils.prettyDocumentToString(createdDoc);
223 LOG.debug(outputString);
224 }
225
226
227
228
229 RequestData requestData = new RequestData();
230 requestData.setWssConfig(WSSConfig.getNewInstance());
231 requestData.setTimeStampTTL(-1);
232 try {
233 verify(createdDoc, requestData);
234 fail("The timestamp validation should have failed");
235 } catch (WSSecurityException ex) {
236 assertTrue(ex.getErrorCode() == WSSecurityException.ErrorCode.MESSAGE_EXPIRED);
237 }
238 }
239
240
241
242
243
244
245
246 @Test
247 public void testNearFutureCreated() throws Exception {
248
249 Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
250 WSSecHeader secHeader = new WSSecHeader(doc);
251 secHeader.insertSecurityHeader();
252
253 Element timestampElement =
254 doc.createElementNS(
255 WSConstants.WSU_NS, WSConstants.WSU_PREFIX + ":" + WSConstants.TIMESTAMP_TOKEN_LN
256 );
257
258 Element elementCreated =
259 doc.createElementNS(
260 WSConstants.WSU_NS, WSConstants.WSU_PREFIX + ":" + WSConstants.CREATED_LN
261 );
262 ZonedDateTime now = ZonedDateTime.now(ZoneOffset.UTC).plusSeconds(30L);
263 elementCreated.appendChild(doc.createTextNode(DateUtil.getDateTimeFormatter(true).format(now)));
264 timestampElement.appendChild(elementCreated);
265
266 secHeader.getSecurityHeaderElement().appendChild(timestampElement);
267
268 if (LOG.isDebugEnabled()) {
269 String outputString =
270 XMLUtils.prettyDocumentToString(doc);
271 LOG.debug(outputString);
272 }
273
274
275
276 RequestData requestData = new RequestData();
277 requestData.setWssConfig(WSSConfig.getNewInstance());
278 requestData.setTimeStampFutureTTL(0);
279 try {
280 verify(doc, requestData);
281 fail("The timestamp validation should have failed");
282 } catch (WSSecurityException ex) {
283 assertTrue(ex.getErrorCode() == WSSecurityException.ErrorCode.MESSAGE_EXPIRED);
284 }
285 }
286
287
288
289
290
291 @Test
292 public void testFutureCreated() throws Exception {
293
294 Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
295 WSSecHeader secHeader = new WSSecHeader(doc);
296 secHeader.insertSecurityHeader();
297
298 Element timestampElement =
299 doc.createElementNS(
300 WSConstants.WSU_NS, WSConstants.WSU_PREFIX + ":" + WSConstants.TIMESTAMP_TOKEN_LN
301 );
302
303 Element elementCreated =
304 doc.createElementNS(
305 WSConstants.WSU_NS, WSConstants.WSU_PREFIX + ":" + WSConstants.CREATED_LN
306 );
307 ZonedDateTime now = ZonedDateTime.now(ZoneOffset.UTC).plusSeconds(120L);
308 elementCreated.appendChild(doc.createTextNode(DateUtil.getDateTimeFormatter(true).format(now)));
309 timestampElement.appendChild(elementCreated);
310
311 secHeader.getSecurityHeaderElement().appendChild(timestampElement);
312
313 if (LOG.isDebugEnabled()) {
314 String outputString =
315 XMLUtils.prettyDocumentToString(doc);
316 LOG.debug(outputString);
317 }
318
319
320
321 try {
322 verify(doc);
323 fail("The timestamp validation should have failed");
324 } catch (WSSecurityException ex) {
325 assertTrue(ex.getErrorCode() == WSSecurityException.ErrorCode.MESSAGE_EXPIRED);
326 }
327 }
328
329
330
331
332
333
334 @Test
335 public void testExpiresBeforeCreated() throws Exception {
336
337 Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
338 WSSecHeader secHeader = new WSSecHeader(doc);
339 secHeader.insertSecurityHeader();
340
341 Element timestampElement =
342 doc.createElementNS(
343 WSConstants.WSU_NS, WSConstants.WSU_PREFIX + ":" + WSConstants.TIMESTAMP_TOKEN_LN
344 );
345
346 Element elementCreated =
347 doc.createElementNS(
348 WSConstants.WSU_NS, WSConstants.WSU_PREFIX + ":" + WSConstants.CREATED_LN
349 );
350 ZonedDateTime now = ZonedDateTime.now(ZoneOffset.UTC);
351 elementCreated.appendChild(doc.createTextNode(DateUtil.getDateTimeFormatter(true).format(now)));
352 timestampElement.appendChild(elementCreated);
353
354 Element elementExpires =
355 doc.createElementNS(
356 WSConstants.WSU_NS, WSConstants.WSU_PREFIX + ":" + WSConstants.EXPIRES_LN
357 );
358 now = now.minusSeconds(300L);
359 elementExpires.appendChild(doc.createTextNode(DateUtil.getDateTimeFormatter(true).format(now)));
360 timestampElement.appendChild(elementExpires);
361
362 secHeader.getSecurityHeaderElement().appendChild(timestampElement);
363
364 if (LOG.isDebugEnabled()) {
365 String outputString =
366 XMLUtils.prettyDocumentToString(doc);
367 LOG.debug(outputString);
368 }
369
370
371
372 try {
373 verify(doc);
374 fail("The timestamp validation should have failed");
375 } catch (WSSecurityException ex) {
376 assertTrue(ex.getErrorCode() == WSSecurityException.ErrorCode.MESSAGE_EXPIRED);
377 }
378 }
379
380
381
382
383 @Test
384 public void testMultipleTimestamps() throws Exception {
385
386 Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
387 WSSecHeader secHeader = new WSSecHeader(doc);
388 secHeader.insertSecurityHeader();
389
390 WSSecTimestamp timestamp = new WSSecTimestamp(secHeader);
391 timestamp.setTimeToLive(300);
392 Document createdDoc = timestamp.build();
393
394 timestamp = new WSSecTimestamp(secHeader);
395 timestamp.setTimeToLive(60);
396 createdDoc = timestamp.build();
397
398 if (LOG.isDebugEnabled()) {
399 String outputString =
400 XMLUtils.prettyDocumentToString(createdDoc);
401 LOG.debug(outputString);
402 }
403
404
405
406
407 try {
408 verify(createdDoc);
409 fail("Expected failure on multiple timestamps");
410 } catch (WSSecurityException ex) {
411 assertTrue(ex.getErrorCode() == WSSecurityException.ErrorCode.INVALID_SECURITY);
412 }
413
414 verify(createdDoc, Collections.singletonList(BSPRule.R3227));
415 }
416
417
418
419
420
421 @Test
422 public void testMultipleCreated() throws Exception {
423
424 Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
425 WSSecHeader secHeader = new WSSecHeader(doc);
426 secHeader.insertSecurityHeader();
427
428 Element timestampElement =
429 doc.createElementNS(
430 WSConstants.WSU_NS, WSConstants.WSU_PREFIX + ":" + WSConstants.TIMESTAMP_TOKEN_LN
431 );
432
433 Element elementCreated =
434 doc.createElementNS(
435 WSConstants.WSU_NS, WSConstants.WSU_PREFIX + ":" + WSConstants.CREATED_LN
436 );
437 ZonedDateTime now = ZonedDateTime.now(ZoneOffset.UTC);
438 elementCreated.appendChild(doc.createTextNode(DateUtil.getDateTimeFormatter(true).format(now)));
439 timestampElement.appendChild(elementCreated);
440 timestampElement.appendChild(elementCreated.cloneNode(true));
441
442 secHeader.getSecurityHeaderElement().appendChild(timestampElement);
443
444 if (LOG.isDebugEnabled()) {
445 String outputString =
446 XMLUtils.prettyDocumentToString(doc);
447 LOG.debug(outputString);
448 }
449
450
451
452 try {
453 verify(doc);
454 fail("The timestamp validation should have failed on multiple Created elements");
455 } catch (WSSecurityException ex) {
456 assertTrue(ex.getErrorCode() == WSSecurityException.ErrorCode.INVALID_SECURITY);
457 }
458
459 verify(doc, Collections.singletonList(BSPRule.R3203));
460 }
461
462
463
464
465
466 @Test
467 public void testEmptyCreated() throws Exception {
468 Document doc = createTimestampWithCreatedContent(null);
469
470 try {
471 verify(doc);
472 fail("The timestamp validation should have failed on an empty Created element");
473 } catch (WSSecurityException ex) {
474 assertTrue(ex.getErrorCode() == WSSecurityException.ErrorCode.INVALID_SECURITY);
475 }
476 }
477
478
479
480
481
482 @Test
483 public void testCreatedWithLeadingComment() throws Exception {
484 ZonedDateTime now = ZonedDateTime.now(ZoneOffset.UTC);
485 Document doc =
486 createTimestampWithCreatedContent(DateUtil.getDateTimeFormatter(true).format(now), true);
487
488 verify(doc);
489 }
490
491 private Document createTimestampWithCreatedContent(String createdText) throws Exception {
492 return createTimestampWithCreatedContent(createdText, false);
493 }
494
495 private Document createTimestampWithCreatedContent(
496 String createdText, boolean leadingComment
497 ) throws Exception {
498 Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
499 WSSecHeader secHeader = new WSSecHeader(doc);
500 secHeader.insertSecurityHeader();
501
502 Element timestampElement =
503 doc.createElementNS(
504 WSConstants.WSU_NS, WSConstants.WSU_PREFIX + ":" + WSConstants.TIMESTAMP_TOKEN_LN
505 );
506
507 Element elementCreated =
508 doc.createElementNS(
509 WSConstants.WSU_NS, WSConstants.WSU_PREFIX + ":" + WSConstants.CREATED_LN
510 );
511 if (leadingComment) {
512 elementCreated.appendChild(doc.createComment("a comment"));
513 }
514 if (createdText != null) {
515 elementCreated.appendChild(doc.createTextNode(createdText));
516 }
517 timestampElement.appendChild(elementCreated);
518
519 secHeader.getSecurityHeaderElement().appendChild(timestampElement);
520
521 if (LOG.isDebugEnabled()) {
522 LOG.debug(XMLUtils.prettyDocumentToString(doc));
523 }
524 return doc;
525 }
526
527
528
529
530
531 @Test
532 public void testNoCreated() throws Exception {
533
534 Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
535 WSSecHeader secHeader = new WSSecHeader(doc);
536 secHeader.insertSecurityHeader();
537
538 Element timestampElement =
539 doc.createElementNS(
540 WSConstants.WSU_NS, WSConstants.WSU_PREFIX + ":" + WSConstants.TIMESTAMP_TOKEN_LN
541 );
542
543 Element elementExpires =
544 doc.createElementNS(
545 WSConstants.WSU_NS, WSConstants.WSU_PREFIX + ":" + WSConstants.EXPIRES_LN
546 );
547 ZonedDateTime now = ZonedDateTime.now(ZoneOffset.UTC).plusSeconds(300L);
548 elementExpires.appendChild(doc.createTextNode(DateUtil.getDateTimeFormatter(true).format(now)));
549 timestampElement.appendChild(elementExpires);
550
551 secHeader.getSecurityHeaderElement().appendChild(timestampElement);
552
553 if (LOG.isDebugEnabled()) {
554 String outputString =
555 XMLUtils.prettyDocumentToString(doc);
556 LOG.debug(outputString);
557 }
558
559
560
561 try {
562 verify(doc);
563 fail("The timestamp validation should have failed on no Created element");
564 } catch (WSSecurityException ex) {
565 assertTrue(ex.getErrorCode() == WSSecurityException.ErrorCode.INVALID_SECURITY);
566 }
567
568 List<BSPRule> rules = new ArrayList<>();
569 rules.add(BSPRule.R3203);
570 rules.add(BSPRule.R3221);
571 verify(doc, rules);
572 }
573
574
575
576
577
578 @Test
579 public void testMultipleExpires() throws Exception {
580
581 Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
582 WSSecHeader secHeader = new WSSecHeader(doc);
583 secHeader.insertSecurityHeader();
584
585 Element timestampElement =
586 doc.createElementNS(
587 WSConstants.WSU_NS, WSConstants.WSU_PREFIX + ":" + WSConstants.TIMESTAMP_TOKEN_LN
588 );
589
590 Element elementCreated =
591 doc.createElementNS(
592 WSConstants.WSU_NS, WSConstants.WSU_PREFIX + ":" + WSConstants.CREATED_LN
593 );
594 ZonedDateTime now = ZonedDateTime.now(ZoneOffset.UTC);
595 elementCreated.appendChild(doc.createTextNode(DateUtil.getDateTimeFormatter(true).format(now)));
596 timestampElement.appendChild(elementCreated);
597
598 Element elementExpires =
599 doc.createElementNS(
600 WSConstants.WSU_NS, WSConstants.WSU_PREFIX + ":" + WSConstants.EXPIRES_LN
601 );
602 now = now.plusSeconds(300L);
603 elementExpires.appendChild(doc.createTextNode(DateUtil.getDateTimeFormatter(true).format(now)));
604 timestampElement.appendChild(elementExpires);
605 timestampElement.appendChild(elementExpires.cloneNode(true));
606
607 secHeader.getSecurityHeaderElement().appendChild(timestampElement);
608
609 if (LOG.isDebugEnabled()) {
610 String outputString =
611 XMLUtils.prettyDocumentToString(doc);
612 LOG.debug(outputString);
613 }
614
615
616
617 try {
618 verify(doc);
619 fail("The timestamp validation should have failed on multiple Expires elements");
620 } catch (WSSecurityException ex) {
621 assertTrue(ex.getErrorCode() == WSSecurityException.ErrorCode.INVALID_SECURITY);
622 }
623
624 verify(doc, Collections.singletonList(BSPRule.R3224));
625 }
626
627
628
629
630
631 @Test
632 public void testExpiresInFrontOfCreated() throws Exception {
633
634 Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
635 WSSecHeader secHeader = new WSSecHeader(doc);
636 secHeader.insertSecurityHeader();
637
638 Element timestampElement =
639 doc.createElementNS(
640 WSConstants.WSU_NS, WSConstants.WSU_PREFIX + ":" + WSConstants.TIMESTAMP_TOKEN_LN
641 );
642
643 Element elementCreated =
644 doc.createElementNS(
645 WSConstants.WSU_NS, WSConstants.WSU_PREFIX + ":" + WSConstants.EXPIRES_LN
646 );
647 ZonedDateTime now = ZonedDateTime.now(ZoneOffset.UTC).plusSeconds(300L);
648 elementCreated.appendChild(doc.createTextNode(DateUtil.getDateTimeFormatter(true).format(now)));
649 timestampElement.appendChild(elementCreated);
650
651 Element elementExpires =
652 doc.createElementNS(
653 WSConstants.WSU_NS, WSConstants.WSU_PREFIX + ":" + WSConstants.CREATED_LN
654 );
655 now = ZonedDateTime.now(ZoneOffset.UTC);
656 elementExpires.appendChild(doc.createTextNode(DateUtil.getDateTimeFormatter(true).format(now)));
657 timestampElement.appendChild(elementExpires);
658
659 secHeader.getSecurityHeaderElement().appendChild(timestampElement);
660
661 if (LOG.isDebugEnabled()) {
662 String outputString =
663 XMLUtils.prettyDocumentToString(doc);
664 LOG.debug(outputString);
665 }
666
667
668
669 try {
670 verify(doc);
671 fail("The timestamp validation should have failed");
672 } catch (WSSecurityException ex) {
673 assertTrue(ex.getErrorCode() == WSSecurityException.ErrorCode.INVALID_SECURITY);
674 }
675
676 verify(doc, Collections.singletonList(BSPRule.R3221));
677 }
678
679
680
681
682
683
684 @Test
685 public void testCreatedSeconds() throws Exception {
686
687 Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
688 WSSecHeader secHeader = new WSSecHeader(doc);
689 secHeader.insertSecurityHeader();
690
691 Element timestampElement =
692 doc.createElementNS(
693 WSConstants.WSU_NS, WSConstants.WSU_PREFIX + ":" + WSConstants.TIMESTAMP_TOKEN_LN
694 );
695
696 Element elementCreated =
697 doc.createElementNS(
698 WSConstants.WSU_NS, WSConstants.WSU_PREFIX + ":" + WSConstants.CREATED_LN
699 );
700 elementCreated.appendChild(doc.createTextNode("2011-02-08T13:13:84.535Z"));
701 timestampElement.appendChild(elementCreated);
702
703 secHeader.getSecurityHeaderElement().appendChild(timestampElement);
704
705 if (LOG.isDebugEnabled()) {
706 String outputString =
707 XMLUtils.prettyDocumentToString(doc);
708 LOG.debug(outputString);
709 }
710
711
712
713
714 WSSConfig wssConfig = WSSConfig.getNewInstance();
715 wssConfig.setValidator(WSConstants.TIMESTAMP, new NoOpValidator());
716 try {
717 verify(doc, wssConfig, new ArrayList<>());
718 fail("The timestamp validation should have failed");
719 } catch (WSSecurityException ex) {
720 assertTrue(ex.getErrorCode() == WSSecurityException.ErrorCode.INVALID_SECURITY);
721 }
722 }
723
724
725
726
727
728
729 @Test
730 public void testCreatedValueType() throws Exception {
731
732 Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
733 WSSecHeader secHeader = new WSSecHeader(doc);
734 secHeader.insertSecurityHeader();
735
736 Element timestampElement =
737 doc.createElementNS(
738 WSConstants.WSU_NS, WSConstants.WSU_PREFIX + ":" + WSConstants.TIMESTAMP_TOKEN_LN
739 );
740
741 Element elementCreated =
742 doc.createElementNS(
743 WSConstants.WSU_NS, WSConstants.WSU_PREFIX + ":" + WSConstants.CREATED_LN
744 );
745 ZonedDateTime now = ZonedDateTime.now(ZoneOffset.UTC);
746 elementCreated.appendChild(doc.createTextNode(DateUtil.getDateTimeFormatter(true).format(now)));
747 elementCreated.setAttributeNS(null, "ValueType", WSConstants.WSS_SAML_KI_VALUE_TYPE);
748 timestampElement.appendChild(elementCreated);
749
750 secHeader.getSecurityHeaderElement().appendChild(timestampElement);
751
752 if (LOG.isDebugEnabled()) {
753 String outputString =
754 XMLUtils.prettyDocumentToString(doc);
755 LOG.debug(outputString);
756 }
757
758
759
760 try {
761 verify(doc);
762 fail("The timestamp validation should have failed");
763 } catch (WSSecurityException ex) {
764 assertTrue(ex.getErrorCode() == WSSecurityException.ErrorCode.INVALID_SECURITY);
765 }
766
767
768 WSSConfig wssConfig = WSSConfig.getNewInstance();
769 wssConfig.setValidator(WSConstants.TIMESTAMP, new NoOpValidator());
770 verify(doc, wssConfig, Collections.singletonList(BSPRule.R3225));
771 }
772
773
774
775
776
777
778
779 @Test
780 public void testCustomElement() throws Exception {
781
782 Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
783 WSSecHeader secHeader = new WSSecHeader(doc);
784 secHeader.insertSecurityHeader();
785
786 Element timestampElement =
787 doc.createElementNS(
788 WSConstants.WSU_NS, WSConstants.WSU_PREFIX + ":" + WSConstants.TIMESTAMP_TOKEN_LN
789 );
790
791 Element elementCreated =
792 doc.createElementNS(
793 WSConstants.WSU_NS, WSConstants.WSU_PREFIX + ":" + WSConstants.CREATED_LN
794 );
795 ZonedDateTime now = ZonedDateTime.now(ZoneOffset.UTC);
796 elementCreated.appendChild(doc.createTextNode(DateUtil.getDateTimeFormatter(true).format(now)));
797 timestampElement.appendChild(elementCreated);
798
799 Element elementExpires =
800 doc.createElementNS(
801 WSConstants.WSU_NS, WSConstants.WSU_PREFIX + ":" + WSConstants.EXPIRES_LN
802 );
803 now = now.plusSeconds(300L);
804 elementExpires.appendChild(doc.createTextNode(DateUtil.getDateTimeFormatter(true).format(now)));
805 timestampElement.appendChild(elementExpires);
806
807 Element elementCustom =
808 doc.createElementNS(
809 WSConstants.WSU_NS, WSConstants.WSU_PREFIX + ":" + "Custom"
810 );
811 timestampElement.appendChild(elementCustom);
812
813 secHeader.getSecurityHeaderElement().appendChild(timestampElement);
814
815 if (LOG.isDebugEnabled()) {
816 String outputString =
817 XMLUtils.prettyDocumentToString(doc);
818 LOG.debug(outputString);
819 }
820
821
822
823 try {
824 verify(doc);
825 fail("The timestamp validation should have failed");
826 } catch (WSSecurityException ex) {
827 assertTrue(ex.getErrorCode() == WSSecurityException.ErrorCode.INVALID_SECURITY);
828 }
829
830
831 verify(doc, Collections.singletonList(BSPRule.R3222));
832 }
833
834
835
836
837 @Test
838 public void testSpoofedTimestamp() throws Exception {
839
840 Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
841 WSSecHeader secHeader = new WSSecHeader(doc);
842 secHeader.insertSecurityHeader();
843
844 WSSecTimestamp timestamp = new WSSecTimestamp(secHeader);
845 timestamp.setTimeToLive(300);
846
847 WSTimeSource spoofedTimeSource = new WSTimeSource() {
848
849 public Instant now() {
850 return Instant.now().minusSeconds(500L);
851 }
852
853 };
854 timestamp.setWsTimeSource(spoofedTimeSource);
855
856 Document createdDoc = timestamp.build();
857
858 if (LOG.isDebugEnabled()) {
859 String outputString =
860 XMLUtils.prettyDocumentToString(createdDoc);
861 LOG.debug(outputString);
862 }
863
864
865
866
867 try {
868 verify(createdDoc);
869 fail("Expected failure on an expired timestamp");
870 } catch (WSSecurityException ex) {
871 assertTrue(ex.getErrorCode() == WSSecurityException.ErrorCode.MESSAGE_EXPIRED);
872 }
873 }
874
875 @Test
876 public void testTimestampNoMilliseconds() throws Exception {
877
878 Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
879 WSSecHeader secHeader = new WSSecHeader(doc);
880 secHeader.insertSecurityHeader();
881
882 WSSecTimestamp timestamp = new WSSecTimestamp(secHeader);
883 timestamp.setPrecisionInMilliSeconds(false);
884 timestamp.setTimeToLive(300);
885 Document createdDoc = timestamp.build();
886
887 if (LOG.isDebugEnabled()) {
888 String outputString =
889 XMLUtils.prettyDocumentToString(createdDoc);
890 LOG.debug(outputString);
891 }
892
893
894
895
896 WSHandlerResult wsResult = verify(createdDoc);
897 WSSecurityEngineResult actionResult =
898 wsResult.getActionResults().get(WSConstants.TS).get(0);
899 assertNotNull(actionResult);
900 }
901
902 @Test
903 public void testThaiLocaleVerification() throws Exception {
904
905 Locale defaultLocale = Locale.getDefault();
906 try {
907 Locale.setDefault(new Locale("th", "TH"));
908
909 Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
910 WSSecHeader secHeader = new WSSecHeader(doc);
911 secHeader.insertSecurityHeader();
912
913 WSSecTimestamp timestamp = new WSSecTimestamp(secHeader);
914 timestamp.setTimeToLive(300);
915 Document createdDoc = timestamp.build();
916
917
918
919
920 WSHandlerResult wsResult = verify(createdDoc);
921 WSSecurityEngineResult actionResult =
922 wsResult.getActionResults().get(WSConstants.TS).get(0);
923 assertNotNull(actionResult);
924 } finally {
925 Locale.setDefault(defaultLocale);
926 }
927 }
928
929
930
931
932 private WSHandlerResult verify(
933 Document doc
934 ) throws Exception {
935 WSSecurityEngine secEngine = new WSSecurityEngine();
936 RequestData requestData = new RequestData();
937 requestData.setWssConfig(WSSConfig.getNewInstance());
938 return secEngine.processSecurityHeader(doc, requestData);
939 }
940
941 private WSHandlerResult verify(
942 Document doc, RequestData requestData
943 ) throws Exception {
944 WSSecurityEngine secEngine = new WSSecurityEngine();
945 return secEngine.processSecurityHeader(doc, requestData);
946 }
947
948
949
950
951 private WSHandlerResult verify(
952 Document doc, List<BSPRule> ignoredRules
953 ) throws Exception {
954 WSSecurityEngine secEngine = new WSSecurityEngine();
955 RequestData requestData = new RequestData();
956 requestData.setIgnoredBSPRules(ignoredRules);
957 return secEngine.processSecurityHeader(doc, requestData);
958 }
959
960
961
962
963 private WSHandlerResult verify(
964 Document doc, WSSConfig wssConfig, List<BSPRule> ignoredRules
965 ) throws Exception {
966 WSSecurityEngine secEngine = new WSSecurityEngine();
967 RequestData requestData = new RequestData();
968 requestData.setWssConfig(wssConfig);
969 requestData.setIgnoredBSPRules(ignoredRules);
970 return secEngine.processSecurityHeader(doc, requestData);
971 }
972
973
974 }