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.IOException;
24  import java.io.InputStream;
25  import java.io.OutputStream;
26  import java.io.PrintWriter;
27  import java.io.StringWriter;
28  import java.nio.charset.StandardCharsets;
29  import java.util.ArrayList;
30  import java.util.EnumSet;
31  import java.util.Iterator;
32  import java.util.List;
33  import java.util.Map;
34  import java.util.Properties;
35  
36  import javax.xml.namespace.QName;
37  import javax.xml.stream.XMLStreamException;
38  import javax.xml.stream.XMLStreamReader;
39  import javax.xml.stream.XMLStreamWriter;
40  import javax.xml.transform.dom.DOMSource;
41  import javax.xml.transform.stream.StreamResult;
42  import javax.xml.xpath.XPathConstants;
43  import javax.xml.xpath.XPathExpression;
44  
45  import org.apache.wss4j.common.bsp.BSPRule;
46  import org.apache.wss4j.common.ext.WSSecurityException;
47  import org.apache.wss4j.dom.handler.WSHandlerConstants;
48  import org.apache.wss4j.stax.ext.WSSConstants;
49  import org.apache.wss4j.stax.ext.WSSSecurityProperties;
50  import org.apache.wss4j.stax.securityEvent.EncryptedPartSecurityEvent;
51  import org.apache.wss4j.stax.securityEvent.OperationSecurityEvent;
52  import org.apache.wss4j.stax.securityEvent.SignedPartSecurityEvent;
53  import org.apache.wss4j.stax.securityEvent.WSSecurityEventConstants;
54  import org.apache.wss4j.stax.setup.InboundWSSec;
55  import org.apache.wss4j.stax.setup.OutboundWSSec;
56  import org.apache.wss4j.stax.setup.WSSec;
57  import org.apache.wss4j.stax.test.utils.StAX2DOM;
58  import org.apache.wss4j.stax.test.utils.XmlReaderToWriter;
59  import org.apache.xml.security.stax.ext.SecurePart;
60  import org.apache.xml.security.stax.securityEvent.EncryptedElementSecurityEvent;
61  import org.apache.xml.security.stax.securityEvent.SecurityEvent;
62  import org.apache.xml.security.stax.securityEvent.SecurityEventListener;
63  import org.apache.xml.security.stax.securityEvent.SignatureValueSecurityEvent;
64  import org.apache.xml.security.stax.securityEvent.SignedElementSecurityEvent;
65  import org.junit.jupiter.api.Test;
66  import org.w3c.dom.Attr;
67  import org.w3c.dom.Document;
68  import org.w3c.dom.Element;
69  import org.w3c.dom.NamedNodeMap;
70  import org.w3c.dom.Node;
71  import org.w3c.dom.NodeList;
72  
73  import static org.junit.jupiter.api.Assertions.assertEquals;
74  import static org.junit.jupiter.api.Assertions.assertFalse;
75  import static org.junit.jupiter.api.Assertions.assertNotNull;
76  import static org.junit.jupiter.api.Assertions.assertTrue;
77  import static org.junit.jupiter.api.Assertions.fail;
78  
79  public class InteroperabilityTest extends AbstractTestBase {
80  
81      @Test
82      public void testInteroperabilityInbound() throws Exception {
83  
84          InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
85  
86          String action = WSHandlerConstants.TIMESTAMP + " " + WSHandlerConstants.SIGNATURE + " " + WSHandlerConstants.ENCRYPTION;
87          Properties properties = new Properties();
88          properties.setProperty(WSHandlerConstants.SIGNATURE_PARTS, "{Element}{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd}Timestamp;{Element}{http://schemas.xmlsoap.org/soap/envelope/}Body;");
89          Document securedDocument = doOutboundSecurityWithWSS4J(sourceDocument, action, properties);
90          ByteArrayOutputStream baos = new ByteArrayOutputStream();
91  
92          javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
93          transformer.transform(new DOMSource(securedDocument), new StreamResult(baos));
94  
95          WSSSecurityProperties securityProperties = new WSSSecurityProperties();
96          securityProperties.setCallbackHandler(new CallbackHandlerImpl());
97          securityProperties.loadSignatureVerificationKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
98          securityProperties.loadDecryptionKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
99  
100         WSSecurityEventConstants.Event[] expectedSecurityEvents = new WSSecurityEventConstants.Event[]{
101                 WSSecurityEventConstants.AlgorithmSuite,
102                 WSSecurityEventConstants.AlgorithmSuite,
103                 WSSecurityEventConstants.AlgorithmSuite,
104                 WSSecurityEventConstants.AlgorithmSuite,
105                 WSSecurityEventConstants.AlgorithmSuite,
106                 WSSecurityEventConstants.AlgorithmSuite,
107                 WSSecurityEventConstants.AlgorithmSuite,
108                 WSSecurityEventConstants.AlgorithmSuite,
109                 WSSecurityEventConstants.X509Token,
110                 WSSecurityEventConstants.X509Token,
111                 WSSecurityEventConstants.SignatureValue,
112                 WSSecurityEventConstants.TIMESTAMP,
113                 WSSecurityEventConstants.SignedElement,
114                 WSSecurityEventConstants.SIGNED_PART,
115                 WSSecurityEventConstants.ENCRYPTED_PART,
116                 WSSecurityEventConstants.OPERATION,
117         };
118         final TestSecurityEventListener securityEventListener = new TestSecurityEventListener(expectedSecurityEvents);
119         Document document = doInboundSecurity(securityProperties,
120                 xmlInputFactory.createXMLStreamReader(
121                         new ByteArrayInputStream(baos.toByteArray())), securityEventListener);
122 
123         //read the whole stream:
124         transformer = TRANSFORMER_FACTORY.newTransformer();
125         transformer.transform(new DOMSource(document), new StreamResult(
126                 new OutputStream() {
127                     @Override
128                     public void write(int b) throws IOException {
129                         // > /dev/null
130                     }
131                 }
132         ));
133         securityEventListener.compare();
134 
135         EncryptedPartSecurityEvent encryptedPartSecurityEvent = securityEventListener.getSecurityEvent(WSSecurityEventConstants.ENCRYPTED_PART);
136         List<SignedElementSecurityEvent> signedElementSecurityEventList = securityEventListener.getSecurityEvents(WSSecurityEventConstants.SignedElement);
137         List<SignedPartSecurityEvent> signedPartSecurityEventList = securityEventListener.getSecurityEvents(WSSecurityEventConstants.SIGNED_PART);
138         SignatureValueSecurityEvent signatureValueSecurityEvent = securityEventListener.getSecurityEvent(WSSecurityEventConstants.SignatureValue);
139         OperationSecurityEvent operationSecurityEvent = securityEventListener.getSecurityEvent(WSSecurityEventConstants.OPERATION);
140         String encryptedPartCorrelationID = encryptedPartSecurityEvent.getCorrelationID();
141         String signedElementCorrelationID1 = signedElementSecurityEventList.get(0).getCorrelationID();
142         String signedElementCorrelationID2 = signedPartSecurityEventList.get(0).getCorrelationID();
143         String signatureValueCorrelationID = signatureValueSecurityEvent.getCorrelationID();
144         String operationCorrelationID = operationSecurityEvent.getCorrelationID();
145 
146         List<SecurityEvent> operationSecurityEvents = new ArrayList<>();
147         List<SecurityEvent> encryptedPartSecurityEvents = new ArrayList<>();
148         List<SecurityEvent> signedElementSecurityEvents1 = new ArrayList<>();
149         List<SecurityEvent> signedElementSecurityEvents2 = new ArrayList<>();
150         List<SecurityEvent> signatureValueSecurityEvents = new ArrayList<>();
151 
152         List<SecurityEvent> securityEvents = securityEventListener.getReceivedSecurityEvents();
153         for (SecurityEvent securityEvent : securityEvents) {
154             if (securityEvent.getCorrelationID().equals(encryptedPartCorrelationID)) {
155                 encryptedPartSecurityEvents.add(securityEvent);
156             } else if (securityEvent.getCorrelationID().equals(signedElementCorrelationID1)) {
157                 signedElementSecurityEvents1.add(securityEvent);
158             } else if (securityEvent.getCorrelationID().equals(signedElementCorrelationID2)) {
159                 signedElementSecurityEvents2.add(securityEvent);
160             } else if (securityEvent.getCorrelationID().equals(signatureValueCorrelationID)) {
161                 signatureValueSecurityEvents.add(securityEvent);
162             } else if (securityEvent.getCorrelationID().equals(operationCorrelationID)) {
163                 operationSecurityEvents.add(securityEvent);
164             }
165         }
166 
167         assertEquals(4, encryptedPartSecurityEvents.size());
168         assertEquals(3, signedElementSecurityEvents1.size());
169         assertEquals(3, signedElementSecurityEvents2.size());
170         assertEquals(4, signatureValueSecurityEvents.size());
171         assertEquals(securityEventListener.getReceivedSecurityEvents().size(),
172                 operationSecurityEvents.size() +
173                         encryptedPartSecurityEvents.size() +
174                         signedElementSecurityEvents1.size() +
175                         signedElementSecurityEvents2.size() +
176                         signatureValueSecurityEvents.size() +
177                         1 //the timestamp
178         );
179     }
180 
181     @Test
182     public void testInteroperabilityInboundSOAP12() throws Exception {
183 
184         InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.2.xml");
185 
186         String action = WSHandlerConstants.TIMESTAMP + " " + WSHandlerConstants.SIGNATURE + " " + WSHandlerConstants.ENCRYPTION;
187         Properties properties = new Properties();
188         properties.setProperty(WSHandlerConstants.SIGNATURE_PARTS, "{Element}{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd}Timestamp;{Element}{http://www.w3.org/2003/05/soap-envelope}Body;");
189         Document securedDocument = doOutboundSecurityWithWSS4J(sourceDocument, action, properties);
190         ByteArrayOutputStream baos = new ByteArrayOutputStream();
191 
192         javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
193         transformer.transform(new DOMSource(securedDocument), new StreamResult(baos));
194 
195         WSSSecurityProperties securityProperties = new WSSSecurityProperties();
196         securityProperties.setCallbackHandler(new CallbackHandlerImpl());
197         securityProperties.loadSignatureVerificationKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
198         securityProperties.loadDecryptionKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
199 
200         WSSecurityEventConstants.Event[] expectedSecurityEvents = new WSSecurityEventConstants.Event[]{
201                 WSSecurityEventConstants.AlgorithmSuite,
202                 WSSecurityEventConstants.AlgorithmSuite,
203                 WSSecurityEventConstants.AlgorithmSuite,
204                 WSSecurityEventConstants.AlgorithmSuite,
205                 WSSecurityEventConstants.AlgorithmSuite,
206                 WSSecurityEventConstants.AlgorithmSuite,
207                 WSSecurityEventConstants.AlgorithmSuite,
208                 WSSecurityEventConstants.AlgorithmSuite,
209                 WSSecurityEventConstants.X509Token,
210                 WSSecurityEventConstants.X509Token,
211                 WSSecurityEventConstants.SignatureValue,
212                 WSSecurityEventConstants.TIMESTAMP,
213                 WSSecurityEventConstants.SignedElement,
214                 WSSecurityEventConstants.SIGNED_PART,
215                 WSSecurityEventConstants.ENCRYPTED_PART,
216                 WSSecurityEventConstants.OPERATION,
217         };
218         final TestSecurityEventListener securityEventListener = new TestSecurityEventListener(expectedSecurityEvents);
219         Document document = doInboundSecurity(
220                 securityProperties,
221                 xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())), securityEventListener);
222 
223         //read the whole stream:
224         transformer = TRANSFORMER_FACTORY.newTransformer();
225         transformer.transform(new DOMSource(document), new StreamResult(
226                 new OutputStream() {
227                     @Override
228                     public void write(int b) throws IOException {
229                         // > /dev/null
230                     }
231                 }
232         ));
233         securityEventListener.compare();
234     }
235 
236     @Test
237     public void testInteroperabilityEncryptedSignatureInbound() throws Exception {
238 
239         InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
240 
241         String action = WSHandlerConstants.TIMESTAMP + " " + WSHandlerConstants.SIGNATURE + " " + WSHandlerConstants.ENCRYPTION;
242         Properties properties = new Properties();
243         properties.setProperty(WSHandlerConstants.SIGNATURE_PARTS, "{Element}{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd}Timestamp;{Element}{http://schemas.xmlsoap.org/soap/envelope/}Body;");
244         properties.setProperty(WSHandlerConstants.ENCRYPTION_PARTS, "{Element}{http://www.w3.org/2000/09/xmldsig#}Signature;{Content}{http://schemas.xmlsoap.org/soap/envelope/}Body;");
245         Document securedDocument = doOutboundSecurityWithWSS4J(sourceDocument, action, properties);
246         ByteArrayOutputStream baos = new ByteArrayOutputStream();
247 
248         javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
249         transformer.transform(new DOMSource(securedDocument), new StreamResult(baos));
250 
251         WSSSecurityProperties securityProperties = new WSSSecurityProperties();
252         securityProperties.setCallbackHandler(new CallbackHandlerImpl());
253         securityProperties.loadSignatureVerificationKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
254         securityProperties.loadDecryptionKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
255 
256         WSSecurityEventConstants.Event[] expectedSecurityEvents = new WSSecurityEventConstants.Event[]{
257                 WSSecurityEventConstants.AlgorithmSuite,
258                 WSSecurityEventConstants.AlgorithmSuite,
259                 WSSecurityEventConstants.AlgorithmSuite,
260                 WSSecurityEventConstants.AlgorithmSuite,
261                 WSSecurityEventConstants.AlgorithmSuite,
262                 WSSecurityEventConstants.AlgorithmSuite,
263                 WSSecurityEventConstants.AlgorithmSuite,
264                 WSSecurityEventConstants.AlgorithmSuite,
265                 WSSecurityEventConstants.AlgorithmSuite,
266                 WSSecurityEventConstants.X509Token,
267                 WSSecurityEventConstants.X509Token,
268                 WSSecurityEventConstants.EncryptedElement,
269                 WSSecurityEventConstants.SignatureValue,
270                 WSSecurityEventConstants.TIMESTAMP,
271                 WSSecurityEventConstants.SignedElement,
272                 WSSecurityEventConstants.SIGNED_PART,
273                 WSSecurityEventConstants.ENCRYPTED_PART,
274                 WSSecurityEventConstants.OPERATION,
275         };
276         final TestSecurityEventListener securityEventListener = new TestSecurityEventListener(expectedSecurityEvents);
277         Document document = doInboundSecurity(
278                 securityProperties,
279                 xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())), securityEventListener);
280 
281         //read the whole stream:
282         transformer = TRANSFORMER_FACTORY.newTransformer();
283         transformer.transform(new DOMSource(document), new StreamResult(
284                 new OutputStream() {
285                     @Override
286                     public void write(int b) throws IOException {
287                         // > /dev/null
288                     }
289                 }
290         ));
291 
292         securityEventListener.compare();
293 
294         EncryptedElementSecurityEvent encryptedElementSecurityEvent = securityEventListener.getSecurityEvent(WSSecurityEventConstants.EncryptedElement);
295         EncryptedPartSecurityEvent encryptedPartSecurityEvent = securityEventListener.getSecurityEvent(WSSecurityEventConstants.ENCRYPTED_PART);
296         List<SignedElementSecurityEvent> signedElementSecurityEventList = securityEventListener.getSecurityEvents(WSSecurityEventConstants.SignedElement);
297         List<SignedPartSecurityEvent> signedPartSecurityEventList = securityEventListener.getSecurityEvents(WSSecurityEventConstants.SIGNED_PART);
298         SignatureValueSecurityEvent signatureValueSecurityEvent = securityEventListener.getSecurityEvent(WSSecurityEventConstants.SignatureValue);
299         OperationSecurityEvent operationSecurityEvent = securityEventListener.getSecurityEvent(WSSecurityEventConstants.OPERATION);
300         String encryptedElementCorrelationID = encryptedElementSecurityEvent.getCorrelationID();
301         String encryptedPartCorrelationID = encryptedPartSecurityEvent.getCorrelationID();
302         String signedElementCorrelationID1 = signedElementSecurityEventList.get(0).getCorrelationID();
303         String signedElementCorrelationID2 = signedPartSecurityEventList.get(0).getCorrelationID();
304         String signatureValueCorrelationID = signatureValueSecurityEvent.getCorrelationID();
305         String operationCorrelationID = operationSecurityEvent.getCorrelationID();
306 
307         List<SecurityEvent> operationSecurityEvents = new ArrayList<>();
308         List<SecurityEvent> encryptedPartSecurityEvents = new ArrayList<>();
309         List<SecurityEvent> encryptedElementSecurityEvents = new ArrayList<>();
310         List<SecurityEvent> signedElementSecurityEvents1 = new ArrayList<>();
311         List<SecurityEvent> signedElementSecurityEvents2 = new ArrayList<>();
312         List<SecurityEvent> signatureValueSecurityEvents = new ArrayList<>();
313 
314         List<SecurityEvent> securityEvents = securityEventListener.getReceivedSecurityEvents();
315         for (SecurityEvent securityEvent : securityEvents) {
316             if (securityEvent.getCorrelationID().equals(encryptedPartCorrelationID)) {
317                 encryptedPartSecurityEvents.add(securityEvent);
318             } else if (securityEvent.getCorrelationID().equals(encryptedElementCorrelationID)) {
319                 encryptedElementSecurityEvents.add(securityEvent);
320             } else if (securityEvent.getCorrelationID().equals(signedElementCorrelationID1)) {
321                 signedElementSecurityEvents1.add(securityEvent);
322             } else if (securityEvent.getCorrelationID().equals(signedElementCorrelationID2)) {
323                 signedElementSecurityEvents2.add(securityEvent);
324             } else if (securityEvent.getCorrelationID().equals(signatureValueCorrelationID)) {
325                 signatureValueSecurityEvents.add(securityEvent);
326             } else if (securityEvent.getCorrelationID().equals(operationCorrelationID)) {
327                 operationSecurityEvents.add(securityEvent);
328             }
329         }
330 
331         assertEquals(3, encryptedPartSecurityEvents.size());
332         assertEquals(3, encryptedElementSecurityEvents.size());
333         assertEquals(3, signedElementSecurityEvents1.size());
334         assertEquals(3, signedElementSecurityEvents2.size());
335         assertEquals(4, signatureValueSecurityEvents.size());
336         assertEquals(securityEventListener.getReceivedSecurityEvents().size(),
337                 operationSecurityEvents.size() +
338                         encryptedPartSecurityEvents.size() +
339                         encryptedElementSecurityEvents.size() +
340                         signedElementSecurityEvents1.size() +
341                         signedElementSecurityEvents2.size() +
342                         signatureValueSecurityEvents.size() +
343                         1 //the timestamp
344         );
345     }
346 
347     //Not supported ATM: Timestamp encrypted and then Signed
348     /*
349     @Test(invocationCount = 1)
350     public void testInteroperabilitySignedEncryptedTimestampInbound() throws Exception {
351 
352         InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
353 
354         String action = WSHandlerConstants.TIMESTAMP + " " + WSHandlerConstants.ENCRYPTION + " " + WSHandlerConstants.SIGNATURE;
355         Properties properties = new Properties();
356         properties.setProperty(WSHandlerConstants.SIGNATURE_PARTS, "{Element}{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd}Timestamp;{Element}{http://schemas.xmlsoap.org/soap/envelope/}Body;");
357         properties.setProperty(WSHandlerConstants.ENCRYPTION_PARTS, "{Content}{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd}Timestamp;{Content}{http://schemas.xmlsoap.org/soap/envelope/}Body;");
358         Document securedDocument = doOutboundSecurityWithWSS4J(sourceDocument, action, properties);
359         ByteArrayOutputStream baos = new ByteArrayOutputStream();
360 
361         javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
362         transformer.transform(new DOMSource(securedDocument), new StreamResult(baos));
363 
364         WSSSecurityProperties securityProperties = new WSSSecurityProperties();
365         securityProperties.setCallbackHandler(new CallbackHandlerImpl());
366         securityProperties.loadSignatureVerificationKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
367         securityProperties.loadDecryptionKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
368 
369         Document document = doInboundSecurity(securityProperties, xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())));
370 
371         //read the whole stream:
372         transformer = TRANSFORMER_FACTORY.newTransformer();
373         //transformer.transform(new DOMSource(document), new StreamResult(System.out));
374         transformer.transform(new DOMSource(document), new StreamResult(
375                 new OutputStream() {
376                     @Override
377                     public void write(int b) throws IOException {
378                         // > /dev/null
379                     }
380                 }
381         ));
382     }
383 */
384 
385     @Test
386     public void testInteroperabilityInboundReverseOrder() throws Exception {
387 
388         InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
389 
390         String action = WSHandlerConstants.ENCRYPTION + " " + WSHandlerConstants.SIGNATURE + " " + WSHandlerConstants.TIMESTAMP;
391         Document securedDocument = doOutboundSecurityWithWSS4J(sourceDocument, action, new Properties());
392         ByteArrayOutputStream baos = new ByteArrayOutputStream();
393 
394         javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
395         transformer.transform(new DOMSource(securedDocument), new StreamResult(baos));
396 
397         WSSSecurityProperties securityProperties = new WSSSecurityProperties();
398         securityProperties.setCallbackHandler(new CallbackHandlerImpl());
399         securityProperties.loadSignatureVerificationKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
400         securityProperties.loadDecryptionKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
401 
402         WSSecurityEventConstants.Event[] expectedSecurityEvents = new WSSecurityEventConstants.Event[]{
403                 WSSecurityEventConstants.AlgorithmSuite,
404                 WSSecurityEventConstants.AlgorithmSuite,
405                 WSSecurityEventConstants.AlgorithmSuite,
406                 WSSecurityEventConstants.AlgorithmSuite,
407                 WSSecurityEventConstants.AlgorithmSuite,
408                 WSSecurityEventConstants.AlgorithmSuite,
409                 WSSecurityEventConstants.X509Token,
410                 WSSecurityEventConstants.X509Token,
411                 WSSecurityEventConstants.TIMESTAMP,
412                 WSSecurityEventConstants.SignatureValue,
413                 WSSecurityEventConstants.SIGNED_PART,
414                 WSSecurityEventConstants.ENCRYPTED_PART,
415                 WSSecurityEventConstants.OPERATION,
416         };
417         final TestSecurityEventListener securityEventListener = new TestSecurityEventListener(expectedSecurityEvents);
418         Document document = doInboundSecurity(
419                 securityProperties,
420                 xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())), securityEventListener);
421 
422         //read the whole stream:
423         transformer = TRANSFORMER_FACTORY.newTransformer();
424         transformer.transform(new DOMSource(document), new StreamResult(
425                 new OutputStream() {
426                     @Override
427                     public void write(int b) throws IOException {
428                         // > /dev/null
429                     }
430                 }
431         ));
432         securityEventListener.compare();
433 
434         EncryptedPartSecurityEvent encryptedPartSecurityEvent = securityEventListener.getSecurityEvent(WSSecurityEventConstants.ENCRYPTED_PART);
435         List<SignedPartSecurityEvent> signedPartSecurityEvents = securityEventListener.getSecurityEvents(WSSecurityEventConstants.SIGNED_PART);
436         SignatureValueSecurityEvent signatureValueSecurityEvent = securityEventListener.getSecurityEvent(WSSecurityEventConstants.SignatureValue);
437         OperationSecurityEvent operationSecurityEvent = securityEventListener.getSecurityEvent(WSSecurityEventConstants.OPERATION);
438         String encryptedPartCorrelationID = encryptedPartSecurityEvent.getCorrelationID();
439         String signedElementCorrelationID1 = signedPartSecurityEvents.get(0).getCorrelationID();
440         String signatureValueCorrelationID = signatureValueSecurityEvent.getCorrelationID();
441         String operationCorrelationID = operationSecurityEvent.getCorrelationID();
442 
443         List<SecurityEvent> operationSecurityEvents = new ArrayList<>();
444         List<SecurityEvent> encryptedPartSecurityEvents = new ArrayList<>();
445         List<SecurityEvent> signedElementSecurityEvents1 = new ArrayList<>();
446         List<SecurityEvent> signatureValueSecurityEvents = new ArrayList<>();
447 
448         List<SecurityEvent> securityEvents = securityEventListener.getReceivedSecurityEvents();
449         for (SecurityEvent securityEvent : securityEvents) {
450             if (securityEvent.getCorrelationID().equals(encryptedPartCorrelationID)) {
451                 encryptedPartSecurityEvents.add(securityEvent);
452             } else if (securityEvent.getCorrelationID().equals(signedElementCorrelationID1)) {
453                 signedElementSecurityEvents1.add(securityEvent);
454             } else if (securityEvent.getCorrelationID().equals(signatureValueCorrelationID)) {
455                 signatureValueSecurityEvents.add(securityEvent);
456             } else if (securityEvent.getCorrelationID().equals(operationCorrelationID)) {
457                 operationSecurityEvents.add(securityEvent);
458             }
459         }
460 
461         assertEquals(4, encryptedPartSecurityEvents.size());
462         assertEquals(3, signedElementSecurityEvents1.size());
463         assertEquals(4, signatureValueSecurityEvents.size());
464         assertEquals(securityEventListener.getReceivedSecurityEvents().size(),
465                 operationSecurityEvents.size() +
466                         encryptedPartSecurityEvents.size() +
467                         signedElementSecurityEvents1.size() +
468                         signatureValueSecurityEvents.size() +
469                         1 //the timestamp
470         );
471     }
472 
473     @Test
474     public void testInteroperabilityOutbound() throws Exception {
475 
476         WSSSecurityProperties securityProperties = new WSSSecurityProperties();
477         securityProperties.setCallbackHandler(new CallbackHandlerImpl());
478         securityProperties.setEncryptionUser("receiver");
479         securityProperties.loadEncryptionKeystore(this.getClass().getClassLoader().getResource("transmitter.jks"), "default".toCharArray());
480         securityProperties.setSignatureUser("transmitter");
481         securityProperties.loadSignatureKeyStore(this.getClass().getClassLoader().getResource("transmitter.jks"), "default".toCharArray());
482         List<WSSConstants.Action> actions = new ArrayList<>();
483         actions.add(WSSConstants.TIMESTAMP);
484         actions.add(WSSConstants.SIGNATURE);
485         actions.add(WSSConstants.ENCRYPTION);
486         securityProperties.setActions(actions);
487 
488         InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
489         ByteArrayOutputStream baos = doOutboundSecurity(securityProperties, sourceDocument);
490 
491         String action = WSHandlerConstants.TIMESTAMP + " " + WSHandlerConstants.SIGNATURE + " " + WSHandlerConstants.ENCRYPTION;
492         doInboundSecurityWithWSS4J(documentBuilderFactory.newDocumentBuilder().parse(new ByteArrayInputStream(baos.toByteArray())), action);
493     }
494 
495     @Test
496     public void testInteroperabilityOutboundReverseOrder() throws Exception {
497 
498         WSSSecurityProperties securityProperties = new WSSSecurityProperties();
499         securityProperties.setCallbackHandler(new CallbackHandlerImpl());
500         securityProperties.setEncryptionUser("receiver");
501         securityProperties.loadEncryptionKeystore(this.getClass().getClassLoader().getResource("transmitter.jks"), "default".toCharArray());
502         securityProperties.setSignatureUser("transmitter");
503         securityProperties.loadSignatureKeyStore(this.getClass().getClassLoader().getResource("transmitter.jks"), "default".toCharArray());
504         List<WSSConstants.Action> actions = new ArrayList<>();
505         actions.add(WSSConstants.ENCRYPTION);
506         actions.add(WSSConstants.SIGNATURE);
507         actions.add(WSSConstants.TIMESTAMP);
508         securityProperties.setActions(actions);
509 
510         InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
511         ByteArrayOutputStream baos = doOutboundSecurity(securityProperties, sourceDocument);
512 
513         String action = WSHandlerConstants.ENCRYPTION + " " + WSHandlerConstants.SIGNATURE + " " + WSHandlerConstants.TIMESTAMP;
514         doInboundSecurityWithWSS4J(documentBuilderFactory.newDocumentBuilder().parse(new ByteArrayInputStream(baos.toByteArray())), action);
515     }
516 
517     @Test
518     public void testInteroperabilityOutboundSignature() throws Exception {
519 
520         WSSSecurityProperties securityProperties = new WSSSecurityProperties();
521         securityProperties.setCallbackHandler(new CallbackHandlerImpl());
522         securityProperties.setEncryptionUser("receiver");
523         securityProperties.loadEncryptionKeystore(this.getClass().getClassLoader().getResource("transmitter.jks"), "default".toCharArray());
524         securityProperties.setSignatureUser("transmitter");
525         securityProperties.loadSignatureKeyStore(this.getClass().getClassLoader().getResource("transmitter.jks"), "default".toCharArray());
526         List<WSSConstants.Action> actions = new ArrayList<>();
527         actions.add(WSSConstants.SIGNATURE);
528         securityProperties.setActions(actions);
529 
530         InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
531         ByteArrayOutputStream baos = doOutboundSecurity(securityProperties, sourceDocument);
532 
533         String action = WSHandlerConstants.SIGNATURE;
534         doInboundSecurityWithWSS4J(documentBuilderFactory.newDocumentBuilder().parse(new ByteArrayInputStream(baos.toByteArray())), action);
535     }
536 
537     @Test
538     public void testInteroperabilityInboundSecurityHeaderTimestampOrder() throws Exception {
539 
540         InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
541 
542         String action = WSHandlerConstants.TIMESTAMP + " " + WSHandlerConstants.SIGNATURE + " " + WSHandlerConstants.ENCRYPTION;
543         Properties properties = new Properties();
544         properties.setProperty(WSHandlerConstants.SIGNATURE_PARTS, "{Element}{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd}Timestamp;{Element}{http://schemas.xmlsoap.org/soap/envelope/}Body;");
545         properties.setProperty(WSHandlerConstants.ENCRYPTION_PARTS, "{Element}{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd}Timestamp;{Content}{http://schemas.xmlsoap.org/soap/envelope/}Body;");
546         Document securedDocument = doOutboundSecurityWithWSS4J(sourceDocument, action, properties);
547         ByteArrayOutputStream baos = new ByteArrayOutputStream();
548 
549         javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
550         transformer.transform(new DOMSource(securedDocument), new StreamResult(baos));
551 
552         XPathExpression xPathExpression = getXPath("/soap:Envelope/soap:Header/wsse:Security/xenc:EncryptedData");
553         Element timeStamp = (Element) xPathExpression.evaluate(securedDocument, XPathConstants.NODE);
554         Element securityHeaderNode = (Element) timeStamp.getParentNode();
555         securityHeaderNode.removeChild(timeStamp);
556 
557         xPathExpression = getXPath("/soap:Envelope/soap:Header/wsse:Security/dsig:Signature");
558         Element signature = (Element) xPathExpression.evaluate(securedDocument, XPathConstants.NODE);
559 
560         securityHeaderNode.insertBefore(timeStamp, signature);
561 
562         WSSSecurityProperties securityProperties = new WSSSecurityProperties();
563         securityProperties.setCallbackHandler(new CallbackHandlerImpl());
564         securityProperties.loadSignatureVerificationKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
565         securityProperties.loadDecryptionKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
566 
567         WSSecurityEventConstants.Event[] expectedSecurityEvents = new WSSecurityEventConstants.Event[]{
568                 WSSecurityEventConstants.AlgorithmSuite,
569                 WSSecurityEventConstants.AlgorithmSuite,
570                 WSSecurityEventConstants.AlgorithmSuite,
571                 WSSecurityEventConstants.AlgorithmSuite,
572                 WSSecurityEventConstants.AlgorithmSuite,
573                 WSSecurityEventConstants.AlgorithmSuite,
574                 WSSecurityEventConstants.AlgorithmSuite,
575                 WSSecurityEventConstants.AlgorithmSuite,
576                 WSSecurityEventConstants.AlgorithmSuite,
577                 WSSecurityEventConstants.X509Token,
578                 WSSecurityEventConstants.X509Token,
579                 WSSecurityEventConstants.SignatureValue,
580                 WSSecurityEventConstants.EncryptedElement,
581                 WSSecurityEventConstants.TIMESTAMP,
582                 WSSecurityEventConstants.SignedElement,
583                 WSSecurityEventConstants.SIGNED_PART,
584                 WSSecurityEventConstants.ENCRYPTED_PART,
585                 WSSecurityEventConstants.OPERATION,
586         };
587         final TestSecurityEventListener securityEventListener = new TestSecurityEventListener(expectedSecurityEvents);
588         Document document = doInboundSecurity(
589                 securityProperties, xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())), securityEventListener);
590 
591         //read the whole stream:
592         transformer = TRANSFORMER_FACTORY.newTransformer();
593         transformer.transform(new DOMSource(document), new StreamResult(
594                 new OutputStream() {
595                     @Override
596                     public void write(int b) throws IOException {
597                         // > /dev/null
598                     }
599                 }
600         ));
601         securityEventListener.compare();
602 
603         EncryptedElementSecurityEvent encryptedElementSecurityEvent = securityEventListener.getSecurityEvent(WSSecurityEventConstants.EncryptedElement);
604         EncryptedPartSecurityEvent encryptedPartSecurityEvent = securityEventListener.getSecurityEvent(WSSecurityEventConstants.ENCRYPTED_PART);
605         List<SignedElementSecurityEvent> signedElementSecurityEvents = securityEventListener.getSecurityEvents(WSSecurityEventConstants.SignedElement);
606         List<SignedPartSecurityEvent> signedPartSecurityEvents = securityEventListener.getSecurityEvents(WSSecurityEventConstants.SIGNED_PART);
607         SignatureValueSecurityEvent signatureValueSecurityEvent = securityEventListener.getSecurityEvent(WSSecurityEventConstants.SignatureValue);
608         OperationSecurityEvent operationSecurityEvent = securityEventListener.getSecurityEvent(WSSecurityEventConstants.OPERATION);
609         String encryptedElementCorrelationID = encryptedElementSecurityEvent.getCorrelationID();
610         String encryptedPartCorrelationID = encryptedPartSecurityEvent.getCorrelationID();
611         String signedElementCorrelationID1 = signedElementSecurityEvents.get(0).getCorrelationID();
612         String signedElementCorrelationID2 = signedPartSecurityEvents.get(0).getCorrelationID();
613         String signatureValueCorrelationID = signatureValueSecurityEvent.getCorrelationID();
614         String operationCorrelationID = operationSecurityEvent.getCorrelationID();
615 
616         List<SecurityEvent> operationSecurityEvents = new ArrayList<>();
617         List<SecurityEvent> encryptedPartSecurityEvents = new ArrayList<>();
618         List<SecurityEvent> encryptedElementSecurityEvents = new ArrayList<>();
619         List<SecurityEvent> signedElementSecurityEvents1 = new ArrayList<>();
620         List<SecurityEvent> signedElementSecurityEvents2 = new ArrayList<>();
621         List<SecurityEvent> signatureValueSecurityEvents = new ArrayList<>();
622 
623         List<SecurityEvent> securityEvents = securityEventListener.getReceivedSecurityEvents();
624         for (SecurityEvent securityEvent : securityEvents) {
625             if (securityEvent.getCorrelationID().equals(encryptedPartCorrelationID)) {
626                 encryptedPartSecurityEvents.add(securityEvent);
627             } else if (securityEvent.getCorrelationID().equals(encryptedElementCorrelationID)) {
628                 encryptedElementSecurityEvents.add(securityEvent);
629             } else if (securityEvent.getCorrelationID().equals(signedElementCorrelationID1)) {
630                 signedElementSecurityEvents1.add(securityEvent);
631             } else if (securityEvent.getCorrelationID().equals(signedElementCorrelationID2)) {
632                 signedElementSecurityEvents2.add(securityEvent);
633             } else if (securityEvent.getCorrelationID().equals(signatureValueCorrelationID)) {
634                 signatureValueSecurityEvents.add(securityEvent);
635             } else if (securityEvent.getCorrelationID().equals(operationCorrelationID)) {
636                 operationSecurityEvents.add(securityEvent);
637             }
638         }
639 
640         assertEquals(3, encryptedPartSecurityEvents.size());
641         assertEquals(3, encryptedElementSecurityEvents.size());
642         assertEquals(3, signedElementSecurityEvents1.size());
643         assertEquals(3, signedElementSecurityEvents2.size());
644         assertEquals(4, signatureValueSecurityEvents.size());
645         assertEquals(securityEventListener.getReceivedSecurityEvents().size(),
646                 operationSecurityEvents.size() +
647                         encryptedPartSecurityEvents.size() +
648                         encryptedElementSecurityEvents.size() +
649                         signedElementSecurityEvents1.size() +
650                         signedElementSecurityEvents2.size() +
651                         signatureValueSecurityEvents.size() +
652                         1 //the timestamp
653         );
654     }
655 
656     @Test
657     public void testEncDecryptionUseReqSigCert() throws Exception {
658 
659         ByteArrayOutputStream baos = new ByteArrayOutputStream();
660         {
661             InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
662             String action = WSHandlerConstants.TIMESTAMP + " " + WSHandlerConstants.SIGNATURE + " " + WSHandlerConstants.ENCRYPTION;
663             Properties properties = new Properties();
664             properties.setProperty(WSHandlerConstants.SIGNATURE_PARTS, "{Element}{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd}Timestamp;{Element}{http://schemas.xmlsoap.org/soap/envelope/}Body;");
665             Map<String, Object> messageContext = doOutboundSecurityWithWSS4J_1(sourceDocument, action, properties);
666             Document securedDocument = (Document) messageContext.get(SECURED_DOCUMENT);
667 
668             //some test that we can really sure we get what we want from WSS4J
669             NodeList nodeList = securedDocument.getElementsByTagNameNS(WSSConstants.TAG_dsig_Signature.getNamespaceURI(), WSSConstants.TAG_dsig_Signature.getLocalPart());
670             assertEquals(nodeList.item(0).getParentNode().getLocalName(), WSSConstants.TAG_WSSE_SECURITY.getLocalPart());
671 
672             javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
673             transformer.transform(new DOMSource(securedDocument), new StreamResult(baos));
674         }
675 
676         final List<SecurityEvent> securityEventList = new ArrayList<>();
677         //done signature; now test sig-verification:
678         {
679             WSSSecurityProperties securityProperties = new WSSSecurityProperties();
680             securityProperties.loadSignatureVerificationKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
681             securityProperties.loadDecryptionKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
682             securityProperties.setCallbackHandler(new CallbackHandlerImpl());
683             InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties);
684 
685             SecurityEventListener securityEventListener = new SecurityEventListener() {
686                 @Override
687                 public void registerSecurityEvent(SecurityEvent securityEvent) throws WSSecurityException {
688                     securityEventList.add(securityEvent);
689                 }
690             };
691 
692             XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())), new ArrayList<SecurityEvent>(), securityEventListener);
693 
694             Document document = StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
695 
696             //header element must still be there
697             NodeList nodeList = document.getElementsByTagNameNS(WSSConstants.TAG_dsig_Signature.getNamespaceURI(), WSSConstants.TAG_dsig_Signature.getLocalPart());
698             assertEquals(nodeList.getLength(), 1);
699             assertEquals(nodeList.item(0).getParentNode().getLocalName(), WSSConstants.TAG_WSSE_SECURITY.getLocalPart());
700         }
701 
702         //so we have a request generated, now do the response:
703         baos = new ByteArrayOutputStream();
704         {
705             WSSSecurityProperties securityProperties = new WSSSecurityProperties();
706             List<WSSConstants.Action> actions = new ArrayList<>();
707             actions.add(WSSConstants.TIMESTAMP);
708             actions.add(WSSConstants.SIGNATURE);
709             actions.add(WSSConstants.ENCRYPTION);
710             securityProperties.setActions(actions);
711             securityProperties.loadSignatureKeyStore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
712             securityProperties.setSignatureUser("receiver");
713             securityProperties.setCallbackHandler(new CallbackHandlerImpl());
714             securityProperties.setUseReqSigCertForEncryption(true);
715 
716             OutboundWSSec wsSecOut = WSSec.getOutboundWSSec(securityProperties);
717             XMLStreamWriter xmlStreamWriter = wsSecOut.processOutMessage(baos, StandardCharsets.UTF_8.name(), securityEventList);
718             XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml"));
719             XmlReaderToWriter.writeAll(xmlStreamReader, xmlStreamWriter);
720             xmlStreamWriter.close();
721 
722             Document document = documentBuilderFactory.newDocumentBuilder().parse(new ByteArrayInputStream(baos.toByteArray()));
723             NodeList nodeList = document.getElementsByTagNameNS(WSSConstants.TAG_dsig_Signature.getNamespaceURI(), WSSConstants.TAG_dsig_Signature.getLocalPart());
724             assertEquals(nodeList.item(0).getParentNode().getLocalName(), WSSConstants.TAG_WSSE_SECURITY.getLocalPart());
725 
726             nodeList = document.getElementsByTagNameNS(WSSConstants.TAG_dsig_Reference.getNamespaceURI(), WSSConstants.TAG_dsig_Reference.getLocalPart());
727             assertEquals(nodeList.getLength(), 1);
728 
729             nodeList = document.getElementsByTagNameNS(WSSConstants.NS_SOAP11, WSSConstants.TAG_SOAP_BODY_LN);
730             assertEquals(nodeList.getLength(), 1);
731             String idAttrValue = ((Element) nodeList.item(0)).getAttributeNS(WSSConstants.ATT_WSU_ID.getNamespaceURI(), WSSConstants.ATT_WSU_ID.getLocalPart());
732             assertNotNull(idAttrValue);
733             assertTrue(idAttrValue.length() > 0);
734         }
735 
736         //verify SigConf response:
737         {
738             String action = WSHandlerConstants.TIMESTAMP + " " + WSHandlerConstants.SIGNATURE + " " + WSHandlerConstants.ENCRYPTION;
739             Properties properties = new Properties();
740             doInboundSecurityWithWSS4J_1(documentBuilderFactory.newDocumentBuilder().parse(new ByteArrayInputStream(baos.toByteArray())), action, properties, true);
741         }
742     }
743 
744     @Test
745     public void testEncryptedSignatureC14NInclusivePartsOutbound() throws Exception {
746 
747         ByteArrayOutputStream baos = new ByteArrayOutputStream();
748         {
749             WSSSecurityProperties securityProperties = new WSSSecurityProperties();
750             List<WSSConstants.Action> actions = new ArrayList<>();
751             actions.add(WSSConstants.SIGNATURE);
752             actions.add(WSSConstants.ENCRYPTION);
753             securityProperties.setActions(actions);
754             securityProperties.loadSignatureKeyStore(this.getClass().getClassLoader().getResource("transmitter.jks"), "default".toCharArray());
755             securityProperties.loadEncryptionKeystore(this.getClass().getClassLoader().getResource("transmitter.jks"), "default".toCharArray());
756             securityProperties.setSignatureUser("transmitter");
757             securityProperties.setEncryptionUser("receiver");
758             securityProperties.addSignaturePart(new SecurePart(new QName("http://www.w3.org/1999/XMLSchema", "complexType"), SecurePart.Modifier.Element));
759             securityProperties.setSignatureCanonicalizationAlgorithm("http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments");
760             securityProperties.setCallbackHandler(new CallbackHandlerImpl());
761 
762             OutboundWSSec wsSecOut = WSSec.getOutboundWSSec(securityProperties);
763             XMLStreamWriter xmlStreamWriter = wsSecOut.processOutMessage(baos, StandardCharsets.UTF_8.name(), new ArrayList<SecurityEvent>());
764             XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml"));
765             XmlReaderToWriter.writeAll(xmlStreamReader, xmlStreamWriter);
766             xmlStreamWriter.close();
767 
768             Document document = documentBuilderFactory.newDocumentBuilder().parse(new ByteArrayInputStream(baos.toByteArray()));
769             NodeList nodeList = document.getElementsByTagNameNS(WSSConstants.TAG_dsig_Signature.getNamespaceURI(), WSSConstants.TAG_dsig_Signature.getLocalPart());
770             assertEquals(nodeList.item(0).getParentNode().getLocalName(), WSSConstants.TAG_WSSE_SECURITY.getLocalPart());
771 
772             nodeList = document.getElementsByTagNameNS(WSSConstants.TAG_dsig_Reference.getNamespaceURI(), WSSConstants.TAG_dsig_Reference.getLocalPart());
773             assertEquals(nodeList.getLength(), 25);
774 
775             nodeList = document.getElementsByTagNameNS("http://www.w3.org/1999/XMLSchema", "complexType");
776             assertEquals(nodeList.getLength(), 0);
777         }
778 
779         //done signature; now test sig-verification:
780         {
781             String action = WSHandlerConstants.SIGNATURE + " " + WSHandlerConstants.ENCRYPTION;
782             Properties properties = new Properties();
783             doInboundSecurityWithWSS4J_1(documentBuilderFactory.newDocumentBuilder().parse(new ByteArrayInputStream(baos.toByteArray())), action, properties, false);
784         }
785     }
786 
787     /**
788      * Inclusive Canonicalization with Encryption is problematic because xenc namespace "leaks"
789      * WSS4J sets the xenc ns on the soap envelope which is not included in the signature on the sending
790      * side. swsssf sets the ns where it belongs and so we don't have this problem. But if we
791      * get an xenc ns on the envelope we will get a signature error. This case can't be handled correctly.
792      * This is also one of the reasons why a exclusive canonicalisation is preferred for SOAP
793      *
794      * @throws Exception
795      */
796     @Test
797     public void testSignatureC14NInclusivePartsInbound() throws Exception {
798         //retest 100 times to make sure we don't have a threading issue
799         for (int i = 0; i < 100; i++) {
800             Document securedDocument;
801             ByteArrayOutputStream baos = new ByteArrayOutputStream();
802             {
803                 WSSSecurityProperties securityProperties = new WSSSecurityProperties();
804                 List<WSSConstants.Action> actions = new ArrayList<>();
805                 actions.add(WSSConstants.SIGNATURE);
806                 actions.add(WSSConstants.ENCRYPTION);
807                 securityProperties.setActions(actions);
808                 securityProperties.loadSignatureKeyStore(this.getClass().getClassLoader().getResource("transmitter.jks"), "default".toCharArray());
809                 securityProperties.loadEncryptionKeystore(this.getClass().getClassLoader().getResource("transmitter.jks"), "default".toCharArray());
810                 securityProperties.setSignatureUser("transmitter");
811                 securityProperties.setEncryptionUser("receiver");
812                 securityProperties.addSignaturePart(new SecurePart(new QName("http://www.w3.org/1999/XMLSchema", "complexType"), SecurePart.Modifier.Element));
813                 securityProperties.setSignatureCanonicalizationAlgorithm("http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments");
814                 securityProperties.setCallbackHandler(new CallbackHandlerImpl());
815 
816                 OutboundWSSec wsSecOut = WSSec.getOutboundWSSec(securityProperties);
817                 XMLStreamWriter xmlStreamWriter = wsSecOut.processOutMessage(baos, StandardCharsets.UTF_8.name(), new ArrayList<SecurityEvent>());
818                 XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml"));
819                 XmlReaderToWriter.writeAll(xmlStreamReader, xmlStreamWriter);
820                 xmlStreamWriter.close();
821 
822                 securedDocument = documentBuilderFactory.newDocumentBuilder().parse(new ByteArrayInputStream(baos.toByteArray()));
823                 NodeList nodeList = securedDocument.getElementsByTagNameNS(WSSConstants.TAG_dsig_Signature.getNamespaceURI(), WSSConstants.TAG_dsig_Signature.getLocalPart());
824                 assertEquals(nodeList.item(0).getParentNode().getLocalName(), WSSConstants.TAG_WSSE_SECURITY.getLocalPart());
825             }
826 
827             {
828                 String action = WSHandlerConstants.SIGNATURE + " " + WSHandlerConstants.ENCRYPTION;
829                 Properties properties = new Properties();
830                 doInboundSecurityWithWSS4J_1(documentBuilderFactory.newDocumentBuilder().parse(new ByteArrayInputStream(baos.toByteArray())), action, properties, false);
831             }
832 
833             //done signature; now test sig-verification:
834             {
835                 WSSSecurityProperties securityProperties = new WSSSecurityProperties();
836                 securityProperties.loadSignatureVerificationKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
837                 securityProperties.loadDecryptionKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
838                 securityProperties.setCallbackHandler(new CallbackHandlerImpl());
839                 securityProperties.addIgnoreBSPRule(BSPRule.R5404);
840                 securityProperties.addIgnoreBSPRule(BSPRule.R5423);
841                 securityProperties.addIgnoreBSPRule(BSPRule.R5412);
842                 InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties);
843 
844                 WSSecurityEventConstants.Event[] expectedSecurityEvents = new WSSecurityEventConstants.Event[]{
845                         WSSecurityEventConstants.AlgorithmSuite,
846                         WSSecurityEventConstants.AlgorithmSuite,
847                         WSSecurityEventConstants.AlgorithmSuite,
848                         WSSecurityEventConstants.AlgorithmSuite,
849                         WSSecurityEventConstants.X509Token,
850                         WSSecurityEventConstants.X509Token,
851                         WSSecurityEventConstants.SignatureValue,
852                         WSSecurityEventConstants.ENCRYPTED_PART,
853                         WSSecurityEventConstants.OPERATION,
854                         WSSecurityEventConstants.AlgorithmSuite,
855                         WSSecurityEventConstants.AlgorithmSuite,
856                         WSSecurityEventConstants.SignedElement,
857                         WSSecurityEventConstants.AlgorithmSuite,
858                         WSSecurityEventConstants.AlgorithmSuite,
859                         WSSecurityEventConstants.SignedElement,
860                         WSSecurityEventConstants.AlgorithmSuite,
861                         WSSecurityEventConstants.AlgorithmSuite,
862                         WSSecurityEventConstants.SignedElement,
863                         WSSecurityEventConstants.AlgorithmSuite,
864                         WSSecurityEventConstants.AlgorithmSuite,
865                         WSSecurityEventConstants.SignedElement,
866                         WSSecurityEventConstants.AlgorithmSuite,
867                         WSSecurityEventConstants.AlgorithmSuite,
868                         WSSecurityEventConstants.SignedElement,
869                         WSSecurityEventConstants.AlgorithmSuite,
870                         WSSecurityEventConstants.AlgorithmSuite,
871                         WSSecurityEventConstants.SignedElement,
872                         WSSecurityEventConstants.AlgorithmSuite,
873                         WSSecurityEventConstants.AlgorithmSuite,
874                         WSSecurityEventConstants.SignedElement,
875                         WSSecurityEventConstants.AlgorithmSuite,
876                         WSSecurityEventConstants.AlgorithmSuite,
877                         WSSecurityEventConstants.SignedElement,
878                         WSSecurityEventConstants.AlgorithmSuite,
879                         WSSecurityEventConstants.AlgorithmSuite,
880                         WSSecurityEventConstants.SignedElement,
881                         WSSecurityEventConstants.AlgorithmSuite,
882                         WSSecurityEventConstants.AlgorithmSuite,
883                         WSSecurityEventConstants.SignedElement,
884                         WSSecurityEventConstants.AlgorithmSuite,
885                         WSSecurityEventConstants.AlgorithmSuite,
886                         WSSecurityEventConstants.SignedElement,
887                         WSSecurityEventConstants.AlgorithmSuite,
888                         WSSecurityEventConstants.AlgorithmSuite,
889                         WSSecurityEventConstants.SignedElement,
890                         WSSecurityEventConstants.AlgorithmSuite,
891                         WSSecurityEventConstants.AlgorithmSuite,
892                         WSSecurityEventConstants.SignedElement,
893                         WSSecurityEventConstants.AlgorithmSuite,
894                         WSSecurityEventConstants.AlgorithmSuite,
895                         WSSecurityEventConstants.SignedElement,
896                         WSSecurityEventConstants.AlgorithmSuite,
897                         WSSecurityEventConstants.AlgorithmSuite,
898                         WSSecurityEventConstants.SignedElement,
899                         WSSecurityEventConstants.AlgorithmSuite,
900                         WSSecurityEventConstants.AlgorithmSuite,
901                         WSSecurityEventConstants.SignedElement,
902                         WSSecurityEventConstants.AlgorithmSuite,
903                         WSSecurityEventConstants.AlgorithmSuite,
904                         WSSecurityEventConstants.SignedElement,
905                         WSSecurityEventConstants.AlgorithmSuite,
906                         WSSecurityEventConstants.AlgorithmSuite,
907                         WSSecurityEventConstants.SignedElement,
908                         WSSecurityEventConstants.AlgorithmSuite,
909                         WSSecurityEventConstants.AlgorithmSuite,
910                         WSSecurityEventConstants.SignedElement,
911                         WSSecurityEventConstants.AlgorithmSuite,
912                         WSSecurityEventConstants.AlgorithmSuite,
913                         WSSecurityEventConstants.SignedElement,
914                         WSSecurityEventConstants.AlgorithmSuite,
915                         WSSecurityEventConstants.AlgorithmSuite,
916                         WSSecurityEventConstants.SignedElement,
917                         WSSecurityEventConstants.AlgorithmSuite,
918                         WSSecurityEventConstants.AlgorithmSuite,
919                         WSSecurityEventConstants.SignedElement,
920                         WSSecurityEventConstants.AlgorithmSuite,
921                         WSSecurityEventConstants.AlgorithmSuite,
922                         WSSecurityEventConstants.SignedElement,
923                         WSSecurityEventConstants.AlgorithmSuite,
924                         WSSecurityEventConstants.AlgorithmSuite,
925                         WSSecurityEventConstants.SignedElement,
926                         WSSecurityEventConstants.AlgorithmSuite,
927                         WSSecurityEventConstants.AlgorithmSuite,
928                         WSSecurityEventConstants.SignedElement,
929                 };
930                 final TestSecurityEventListener securityEventListener = new TestSecurityEventListener(expectedSecurityEvents);
931                 XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(
932                         xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())), null, securityEventListener);
933 
934                 Document document = StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
935 
936                 //header element must still be there
937                 NodeList nodeList = document.getElementsByTagNameNS(WSSConstants.TAG_dsig_Signature.getNamespaceURI(), WSSConstants.TAG_dsig_Signature.getLocalPart());
938                 assertEquals(nodeList.getLength(), 1);
939                 assertEquals(nodeList.item(0).getParentNode().getLocalName(), WSSConstants.TAG_WSSE_SECURITY.getLocalPart());
940 
941                 securityEventListener.compare();
942             }
943         }
944     }
945 
946     @Test
947     public void testInteroperabilitySOAPActionInbound() throws Exception {
948 
949         InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
950 
951         String action = WSHandlerConstants.TIMESTAMP + " " + WSHandlerConstants.SIGNATURE + " " + WSHandlerConstants.ENCRYPTION;
952         Properties properties = new Properties();
953         properties.setProperty(WSHandlerConstants.SIGNATURE_PARTS, "{Element}{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd}Timestamp;{Element}{http://schemas.xmlsoap.org/soap/envelope/}Body;");
954         properties.setProperty(WSHandlerConstants.ACTOR, "test");
955         Document securedDocument = doOutboundSecurityWithWSS4J(sourceDocument, action, properties);
956         ByteArrayOutputStream baos = new ByteArrayOutputStream();
957 
958         javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
959         transformer.transform(new DOMSource(securedDocument), new StreamResult(baos));
960 
961         WSSSecurityProperties securityProperties = new WSSSecurityProperties();
962         securityProperties.setCallbackHandler(new CallbackHandlerImpl());
963         securityProperties.setActor("test");
964         securityProperties.loadSignatureVerificationKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
965         securityProperties.loadDecryptionKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
966 
967         WSSecurityEventConstants.Event[] expectedSecurityEvents = new WSSecurityEventConstants.Event[]{
968                 WSSecurityEventConstants.AlgorithmSuite,
969                 WSSecurityEventConstants.AlgorithmSuite,
970                 WSSecurityEventConstants.AlgorithmSuite,
971                 WSSecurityEventConstants.AlgorithmSuite,
972                 WSSecurityEventConstants.AlgorithmSuite,
973                 WSSecurityEventConstants.AlgorithmSuite,
974                 WSSecurityEventConstants.AlgorithmSuite,
975                 WSSecurityEventConstants.AlgorithmSuite,
976                 WSSecurityEventConstants.X509Token,
977                 WSSecurityEventConstants.X509Token,
978                 WSSecurityEventConstants.SignatureValue,
979                 WSSecurityEventConstants.TIMESTAMP,
980                 WSSecurityEventConstants.SignedElement,
981                 WSSecurityEventConstants.SIGNED_PART,
982                 WSSecurityEventConstants.ENCRYPTED_PART,
983                 WSSecurityEventConstants.OPERATION,
984         };
985         final TestSecurityEventListener securityEventListener = new TestSecurityEventListener(expectedSecurityEvents);
986         Document document = doInboundSecurity(
987                 securityProperties, xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())), securityEventListener);
988 
989         //read the whole stream:
990         transformer = TRANSFORMER_FACTORY.newTransformer();
991         transformer.transform(new DOMSource(document), new StreamResult(
992                 new OutputStream() {
993                     @Override
994                     public void write(int b) throws IOException {
995                         // > /dev/null
996                     }
997                 }
998         ));
999         securityEventListener.compare();
1000     }
1001 
1002     @Test
1003     public void testInteroperabilityInvalidSOAPActionInbound() throws Exception {
1004 
1005         InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
1006 
1007         String action = WSHandlerConstants.TIMESTAMP + " " + WSHandlerConstants.SIGNATURE + " " + WSHandlerConstants.ENCRYPTION;
1008         Properties properties = new Properties();
1009         properties.setProperty(WSHandlerConstants.SIGNATURE_PARTS, "{Element}{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd}Timestamp;{Element}{http://schemas.xmlsoap.org/soap/envelope/}Body;");
1010         properties.setProperty(WSHandlerConstants.ACTOR, "test");
1011         Document securedDocument = doOutboundSecurityWithWSS4J(sourceDocument, action, properties);
1012         ByteArrayOutputStream baos = new ByteArrayOutputStream();
1013 
1014         javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
1015         transformer.transform(new DOMSource(securedDocument), new StreamResult(baos));
1016 
1017         WSSSecurityProperties securityProperties = new WSSSecurityProperties();
1018         securityProperties.setCallbackHandler(new CallbackHandlerImpl());
1019         securityProperties.setActor("anotherTest");
1020         securityProperties.loadSignatureVerificationKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
1021         securityProperties.loadDecryptionKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
1022 
1023         WSSecurityEventConstants.Event[] expectedSecurityEvents = new WSSecurityEventConstants.Event[]{
1024                 WSSecurityEventConstants.NO_SECURITY,
1025                 WSSecurityEventConstants.OPERATION
1026         };
1027         final TestSecurityEventListener securityEventListener = new TestSecurityEventListener(expectedSecurityEvents);
1028         Document document = doInboundSecurity(
1029                 securityProperties, xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())), securityEventListener);
1030 
1031         //read the whole stream:
1032         transformer = TRANSFORMER_FACTORY.newTransformer();
1033         transformer.transform(new DOMSource(document), new StreamResult(
1034                 new OutputStream() {
1035                     @Override
1036                     public void write(int b) throws IOException {
1037                         // > /dev/null
1038                     }
1039                 }
1040         ));
1041         securityEventListener.compare();
1042     }
1043 
1044     @Test
1045     public void testInteroperabilitySOAPRoleInbound() throws Exception {
1046 
1047         InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.2.xml");
1048 
1049         String action = WSHandlerConstants.TIMESTAMP + " " + WSHandlerConstants.SIGNATURE + " " + WSHandlerConstants.ENCRYPTION;
1050         Properties properties = new Properties();
1051         properties.setProperty(WSHandlerConstants.ACTOR, "test");
1052         properties.setProperty(WSHandlerConstants.SIGNATURE_PARTS, "{Element}{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd}Timestamp;{Element}{http://www.w3.org/2003/05/soap-envelope}Body;");
1053         Document securedDocument = doOutboundSecurityWithWSS4J(sourceDocument, action, properties);
1054         ByteArrayOutputStream baos = new ByteArrayOutputStream();
1055 
1056         javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
1057         transformer.transform(new DOMSource(securedDocument), new StreamResult(baos));
1058 
1059         WSSSecurityProperties securityProperties = new WSSSecurityProperties();
1060         securityProperties.setCallbackHandler(new CallbackHandlerImpl());
1061         securityProperties.setActor("test");
1062         securityProperties.loadSignatureVerificationKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
1063         securityProperties.loadDecryptionKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
1064 
1065         WSSecurityEventConstants.Event[] expectedSecurityEvents = new WSSecurityEventConstants.Event[]{
1066                 WSSecurityEventConstants.AlgorithmSuite,
1067                 WSSecurityEventConstants.AlgorithmSuite,
1068                 WSSecurityEventConstants.AlgorithmSuite,
1069                 WSSecurityEventConstants.AlgorithmSuite,
1070                 WSSecurityEventConstants.AlgorithmSuite,
1071                 WSSecurityEventConstants.AlgorithmSuite,
1072                 WSSecurityEventConstants.AlgorithmSuite,
1073                 WSSecurityEventConstants.AlgorithmSuite,
1074                 WSSecurityEventConstants.X509Token,
1075                 WSSecurityEventConstants.X509Token,
1076                 WSSecurityEventConstants.SignatureValue,
1077                 WSSecurityEventConstants.TIMESTAMP,
1078                 WSSecurityEventConstants.SignedElement,
1079                 WSSecurityEventConstants.SIGNED_PART,
1080                 WSSecurityEventConstants.ENCRYPTED_PART,
1081                 WSSecurityEventConstants.OPERATION,
1082         };
1083         final TestSecurityEventListener securityEventListener = new TestSecurityEventListener(expectedSecurityEvents);
1084         Document document = doInboundSecurity(
1085                 securityProperties, xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())), securityEventListener);
1086 
1087         //read the whole stream:
1088         transformer = TRANSFORMER_FACTORY.newTransformer();
1089         transformer.transform(new DOMSource(document), new StreamResult(
1090                 new OutputStream() {
1091                     @Override
1092                     public void write(int b) throws IOException {
1093                         // > /dev/null
1094                     }
1095                 }
1096         ));
1097         securityEventListener.compare();
1098     }
1099 
1100     @Test
1101     public void testInteroperabilityTwoSecurityHeadersSOAPRoleInbound() throws Exception {
1102 
1103         InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.2.xml");
1104 
1105         String action = WSHandlerConstants.TIMESTAMP + " " + WSHandlerConstants.SIGNATURE + " " + WSHandlerConstants.ENCRYPTION;
1106         Properties properties = new Properties();
1107         properties.setProperty(WSHandlerConstants.SIGNATURE_PARTS, "{Element}{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd}Timestamp;{Element}{http://www.w3.org/2003/05/soap-envelope}Body;");
1108         Document securedDocument = doOutboundSecurityWithWSS4J(sourceDocument, action, properties);
1109         ByteArrayOutputStream baos = new ByteArrayOutputStream();
1110 
1111         javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
1112         transformer.transform(new DOMSource(securedDocument), new StreamResult(baos));
1113 
1114         properties.setProperty(WSHandlerConstants.ACTOR, "test");
1115         securedDocument = doOutboundSecurityWithWSS4J(new ByteArrayInputStream(baos.toByteArray()), action, properties);
1116 
1117         transformer = TRANSFORMER_FACTORY.newTransformer();
1118         baos.reset();
1119         transformer.transform(new DOMSource(securedDocument), new StreamResult(baos));
1120 
1121         WSSSecurityProperties securityProperties = new WSSSecurityProperties();
1122         securityProperties.setCallbackHandler(new CallbackHandlerImpl());
1123         securityProperties.setActor("test");
1124         securityProperties.loadSignatureVerificationKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
1125         securityProperties.loadDecryptionKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
1126 
1127         Document document = doInboundSecurity(securityProperties, xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())));
1128 
1129         //read the whole stream:
1130         transformer = TRANSFORMER_FACTORY.newTransformer();
1131         transformer.transform(new DOMSource(document), new StreamResult(
1132                 new OutputStream() {
1133                     @Override
1134                     public void write(int b) throws IOException {
1135                         // > /dev/null
1136                     }
1137                 }
1138         ));
1139     }
1140 
1141     @Test
1142     public void testInteroperabilitySOAPActionOutbound() throws Exception {
1143 
1144         WSSSecurityProperties securityProperties = new WSSSecurityProperties();
1145         securityProperties.setCallbackHandler(new CallbackHandlerImpl());
1146         securityProperties.setActor("test");
1147         securityProperties.setEncryptionUser("receiver");
1148         securityProperties.loadEncryptionKeystore(this.getClass().getClassLoader().getResource("transmitter.jks"), "default".toCharArray());
1149         securityProperties.setSignatureUser("transmitter");
1150         securityProperties.loadSignatureKeyStore(this.getClass().getClassLoader().getResource("transmitter.jks"), "default".toCharArray());
1151         List<WSSConstants.Action> actions = new ArrayList<>();
1152         actions.add(WSSConstants.TIMESTAMP);
1153         actions.add(WSSConstants.SIGNATURE);
1154         actions.add(WSSConstants.ENCRYPTION);
1155         securityProperties.setActions(actions);
1156 
1157         InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
1158         ByteArrayOutputStream baos = doOutboundSecurity(securityProperties, sourceDocument);
1159 
1160         String action = WSHandlerConstants.TIMESTAMP + " " + WSHandlerConstants.SIGNATURE + " " + WSHandlerConstants.ENCRYPTION;
1161         Properties properties = new Properties();
1162         properties.setProperty(WSHandlerConstants.ACTOR, "test");
1163         doInboundSecurityWithWSS4J_1(documentBuilderFactory.newDocumentBuilder().parse(new ByteArrayInputStream(baos.toByteArray())), action, properties, false);
1164     }
1165 
1166     @Test
1167     public void testInteroperabilityInvalidSOAPActionOutbound() throws Exception {
1168 
1169         WSSSecurityProperties securityProperties = new WSSSecurityProperties();
1170         securityProperties.setCallbackHandler(new CallbackHandlerImpl());
1171         securityProperties.setActor("test");
1172         securityProperties.setEncryptionUser("receiver");
1173         securityProperties.loadEncryptionKeystore(this.getClass().getClassLoader().getResource("transmitter.jks"), "default".toCharArray());
1174         securityProperties.setSignatureUser("transmitter");
1175         securityProperties.loadSignatureKeyStore(this.getClass().getClassLoader().getResource("transmitter.jks"), "default".toCharArray());
1176         List<WSSConstants.Action> actions = new ArrayList<>();
1177         actions.add(WSSConstants.TIMESTAMP);
1178         actions.add(WSSConstants.SIGNATURE);
1179         actions.add(WSSConstants.ENCRYPTION);
1180         securityProperties.setActions(actions);
1181 
1182         InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
1183         ByteArrayOutputStream baos = doOutboundSecurity(securityProperties, sourceDocument);
1184 
1185         String action = WSHandlerConstants.TIMESTAMP + " " + WSHandlerConstants.SIGNATURE + " " + WSHandlerConstants.ENCRYPTION;
1186         Properties properties = new Properties();
1187         properties.setProperty(WSHandlerConstants.ACTOR, "anotherTest");
1188         try {
1189             doInboundSecurityWithWSS4J_1(documentBuilderFactory.newDocumentBuilder().parse(new ByteArrayInputStream(baos.toByteArray())), action, properties, false);
1190             fail("Expected WSSecurityException");
1191         } catch (WSSecurityException e) {
1192             assertEquals(e.getMessage(), "WSS4JHandler: Request does not contain required Security header");
1193         }
1194     }
1195 
1196     @Test
1197     public void testInteroperabilitySOAPRoleOutbound() throws Exception {
1198 
1199         WSSSecurityProperties securityProperties = new WSSSecurityProperties();
1200         securityProperties.setCallbackHandler(new CallbackHandlerImpl());
1201         securityProperties.setActor("test");
1202         securityProperties.setEncryptionUser("receiver");
1203         securityProperties.loadEncryptionKeystore(this.getClass().getClassLoader().getResource("transmitter.jks"), "default".toCharArray());
1204         securityProperties.setSignatureUser("transmitter");
1205         securityProperties.loadSignatureKeyStore(this.getClass().getClassLoader().getResource("transmitter.jks"), "default".toCharArray());
1206         List<WSSConstants.Action> actions = new ArrayList<>();
1207         actions.add(WSSConstants.TIMESTAMP);
1208         actions.add(WSSConstants.SIGNATURE);
1209         actions.add(WSSConstants.ENCRYPTION);
1210         securityProperties.setActions(actions);
1211 
1212         InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.2.xml");
1213 
1214         ByteArrayOutputStream baos = doOutboundSecurity(securityProperties, sourceDocument);
1215 
1216         String action = WSHandlerConstants.TIMESTAMP + " " + WSHandlerConstants.SIGNATURE + " " + WSHandlerConstants.ENCRYPTION;
1217         Properties properties = new Properties();
1218         properties.setProperty(WSHandlerConstants.ACTOR, "test");
1219         doInboundSecurityWithWSS4J_1(documentBuilderFactory.newDocumentBuilder().parse(new ByteArrayInputStream(baos.toByteArray())), action, properties, false);
1220     }
1221 
1222     @Test
1223     public void testInteroperabilityTwoSecurityHeadersSOAPRoleOutbound() throws Exception {
1224 
1225         WSSSecurityProperties securityProperties = new WSSSecurityProperties();
1226         securityProperties.setCallbackHandler(new CallbackHandlerImpl());
1227         securityProperties.setEncryptionUser("receiver");
1228         securityProperties.loadEncryptionKeystore(this.getClass().getClassLoader().getResource("transmitter.jks"), "default".toCharArray());
1229         securityProperties.setSignatureUser("transmitter");
1230         securityProperties.loadSignatureKeyStore(this.getClass().getClassLoader().getResource("transmitter.jks"), "default".toCharArray());
1231         List<WSSConstants.Action> actions = new ArrayList<>();
1232         actions.add(WSSConstants.TIMESTAMP);
1233         actions.add(WSSConstants.SIGNATURE);
1234         actions.add(WSSConstants.ENCRYPTION);
1235         securityProperties.setActions(actions);
1236 
1237         InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.2.xml");
1238 
1239         ByteArrayOutputStream baos = doOutboundSecurity(securityProperties, sourceDocument);
1240 
1241         securityProperties.setActor("test");
1242         baos = doOutboundSecurity(securityProperties, new ByteArrayInputStream(baos.toByteArray()));
1243 
1244         String action = WSHandlerConstants.TIMESTAMP + " " + WSHandlerConstants.SIGNATURE + " " + WSHandlerConstants.ENCRYPTION;
1245         Properties properties = new Properties();
1246         properties.setProperty(WSHandlerConstants.ACTOR, "test");
1247         doInboundSecurityWithWSS4J_1(documentBuilderFactory.newDocumentBuilder().parse(new ByteArrayInputStream(baos.toByteArray())), action, properties, false);
1248     }
1249 
1250     @Test
1251     public void testInvalidXML() throws Exception {
1252 
1253         int i = 0;
1254         int e = 10000;
1255 
1256         while (i < e) {
1257 
1258             String action = WSHandlerConstants.USERNAME_TOKEN + " " + WSHandlerConstants.TIMESTAMP + " " + WSHandlerConstants.SIGNATURE + " " + WSHandlerConstants.ENCRYPTION;
1259             Properties properties = new Properties();
1260             InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
1261             Document securedDocument = doOutboundSecurityWithWSS4J(sourceDocument, action, properties);
1262             ByteArrayOutputStream baos = new ByteArrayOutputStream();
1263 
1264             if (i == 0) {
1265                 i = indexOfNode(securedDocument.getDocumentElement(), new NodeIndex(), WSSConstants.TAG_WSSE_SECURITY.getLocalPart()).index;
1266                 e = indexOfNode(securedDocument.getDocumentElement(), new NodeIndex(), "definitions").index;
1267             }
1268             i++;
1269             Node nodeToRemove = nodeOnIndex(securedDocument.getDocumentElement(), new NodeIndex(), i).node;
1270             if (nodeToRemove.getNodeType() == Node.ATTRIBUTE_NODE) {
1271                 ((Attr) nodeToRemove).getOwnerElement().removeAttributeNode((Attr) nodeToRemove);
1272             } else {
1273                 Node parentNode = nodeToRemove.getParentNode();
1274                 parentNode.removeChild(nodeToRemove);
1275             }
1276 
1277             javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
1278             transformer.transform(new DOMSource(securedDocument), new StreamResult(baos));
1279 
1280             WSSSecurityProperties securityProperties = new WSSSecurityProperties();
1281             securityProperties.setCallbackHandler(new CallbackHandlerImpl());
1282             securityProperties.loadSignatureVerificationKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
1283             securityProperties.loadDecryptionKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
1284             Iterator<BSPRule> bspRules = EnumSet.allOf(BSPRule.class).iterator();
1285             while (bspRules.hasNext()) {
1286                 securityProperties.addIgnoreBSPRule(bspRules.next());
1287             }
1288 
1289             try {
1290                 Document document = doInboundSecurity(securityProperties,
1291                         xmlInputFactory.createXMLStreamReader(
1292                                 new ByteArrayInputStream(baos.toByteArray())));
1293 
1294                 //read the whole stream:
1295                 transformer = TRANSFORMER_FACTORY.newTransformer();
1296                 transformer.transform(new DOMSource(document), new StreamResult(
1297                         new OutputStream() {
1298                             @Override
1299                             public void write(int b) throws IOException {
1300                                 // > /dev/null
1301                             }
1302                         }
1303                 ));
1304             } catch (XMLStreamException ex) {
1305                 int k = 0;
1306                 Throwable t = ex.getCause();
1307                 while (t != null && k < 100) {
1308                     StringWriter stringWriter = new StringWriter();
1309                     PrintWriter pw = new PrintWriter(stringWriter);
1310                     ex.printStackTrace(pw);
1311                     assertFalse(t instanceof NullPointerException, stringWriter.toString());
1312                     t = t.getCause();
1313                 }
1314             }
1315         }
1316     }
1317 
1318     private NodeIndex indexOfNode(Node node, NodeIndex index, String name) {
1319         if (node.getLocalName() != null && node.getLocalName().equals(name)) {
1320             return index;
1321         }
1322         index.index++;
1323         if (node.getNodeType() == Node.ELEMENT_NODE) {
1324             NamedNodeMap namedNodeMap = node.getAttributes();
1325             for (int i = 0; i < namedNodeMap.getLength(); i++) {
1326                 NodeIndex n = indexOfNode(namedNodeMap.item(i), index, name);
1327                 if (n != null) {
1328                     return n;
1329                 }
1330             }
1331         }
1332         NodeList nodeList = node.getChildNodes();
1333         for (int i = 0; i < nodeList.getLength(); i++) {
1334             NodeIndex n = indexOfNode(nodeList.item(i), index, name);
1335             if (n != null) {
1336                 return n;
1337             }
1338         }
1339         return null;
1340     }
1341 
1342     private NodeIndex nodeOnIndex(Node node, NodeIndex index, int indexToFind) {
1343         if (index.index == indexToFind) {
1344             index.node = node;
1345             return index;
1346         }
1347         index.index++;
1348         if (node.getNodeType() == Node.ELEMENT_NODE) {
1349             NamedNodeMap namedNodeMap = node.getAttributes();
1350             for (int i = 0; i < namedNodeMap.getLength(); i++) {
1351                 NodeIndex n = nodeOnIndex(namedNodeMap.item(i), index, indexToFind);
1352                 if (n != null) {
1353                     return n;
1354                 }
1355             }
1356         }
1357         NodeList nodeList = node.getChildNodes();
1358         for (int i = 0; i < nodeList.getLength(); i++) {
1359             NodeIndex n = nodeOnIndex(nodeList.item(i), index, indexToFind);
1360             if (n != null) {
1361                 return n;
1362             }
1363         }
1364         return null;
1365     }
1366 
1367     class NodeIndex {
1368         Node node;
1369         int index;
1370     }
1371 }