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.policy.stax.test;
20  
21  import java.util.ArrayList;
22  import java.util.LinkedList;
23  import java.util.List;
24  
25  import javax.xml.namespace.QName;
26  
27  import org.apache.wss4j.common.ext.WSSecurityException;
28  import org.apache.wss4j.policy.stax.PolicyViolationException;
29  import org.apache.wss4j.policy.stax.enforcer.PolicyEnforcer;
30  import org.apache.wss4j.stax.ext.WSSConstants;
31  import org.apache.wss4j.stax.impl.securityToken.SecureConversationSecurityTokenImpl;
32  import org.apache.wss4j.stax.securityEvent.OperationSecurityEvent;
33  import org.apache.wss4j.stax.securityEvent.RequiredElementSecurityEvent;
34  import org.apache.wss4j.stax.securityEvent.SecurityContextTokenSecurityEvent;
35  import org.apache.wss4j.stax.securityEvent.SignedPartSecurityEvent;
36  import org.apache.wss4j.stax.securityEvent.TimestampSecurityEvent;
37  import org.apache.wss4j.stax.securityToken.WSSecurityTokenConstants;
38  import org.apache.xml.security.stax.ext.XMLSecurityConstants;
39  import org.apache.xml.security.stax.ext.stax.XMLSecEventFactory;
40  import org.apache.xml.security.stax.securityEvent.EncryptedElementSecurityEvent;
41  import org.junit.jupiter.api.Test;
42  
43  import static org.junit.jupiter.api.Assertions.assertEquals;
44  import static org.junit.jupiter.api.Assertions.assertTrue;
45  import static org.junit.jupiter.api.Assertions.fail;
46  
47  public class SymmetricBindingTest extends AbstractPolicyTestBase {
48  
49      @Test
50      public void testPolicy() throws Exception {
51          String policyString =
52                  "<sp:SymmetricBinding xmlns:sp=\"http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702\" xmlns:sp3=\"http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200802\">\n" +
53                          "<wsp:Policy xmlns:wsp=\"http://schemas.xmlsoap.org/ws/2004/09/policy\">\n" +
54                          "   <sp:AlgorithmSuite>\n" +
55                          "       <wsp:Policy>\n" +
56                          "           <sp:Basic256/>\n" +
57                          "       </wsp:Policy>\n" +
58                          "   </sp:AlgorithmSuite>\n" +
59                          "<sp:IncludeTimestamp/>\n" +
60                          "<sp:EncryptSignature/>\n" +
61                          "<sp:OnlySignEntireHeadersAndBody/>\n" +
62                          "</wsp:Policy>\n" +
63                          "</sp:SymmetricBinding>";
64          PolicyEnforcer policyEnforcer = buildAndStartPolicyEngine(policyString);
65  
66          TimestampSecurityEvent timestampSecurityEvent = new TimestampSecurityEvent();
67          policyEnforcer.registerSecurityEvent(timestampSecurityEvent);
68  
69          RequiredElementSecurityEvent requiredElementSecurityEvent = new RequiredElementSecurityEvent();
70          List<QName> headerPath = new ArrayList<>();
71          headerPath.addAll(WSSConstants.SOAP_11_WSSE_SECURITY_HEADER_PATH);
72          headerPath.add(WSSConstants.TAG_WSU_TIMESTAMP);
73          requiredElementSecurityEvent.setElementPath(headerPath);
74          policyEnforcer.registerSecurityEvent(requiredElementSecurityEvent);
75  
76          SecurityContextTokenSecurityEvent initiatorTokenSecurityEvent = new SecurityContextTokenSecurityEvent();
77          SecureConversationSecurityTokenImpl securityToken =
78                  new SecureConversationSecurityTokenImpl(
79                          null, "1", WSSecurityTokenConstants.KEYIDENTIFIER_SECURITY_TOKEN_DIRECT_REFERENCE);
80          securityToken.addTokenUsage(WSSecurityTokenConstants.TOKENUSAGE_MAIN_SIGNATURE);
81          initiatorTokenSecurityEvent.setSecurityToken(securityToken);
82          policyEnforcer.registerSecurityEvent(initiatorTokenSecurityEvent);
83  
84          SecurityContextTokenSecurityEvent recipientTokenSecurityEvent = new SecurityContextTokenSecurityEvent();
85          securityToken = new SecureConversationSecurityTokenImpl(
86                  null, "1", WSSecurityTokenConstants.KEYIDENTIFIER_SECURITY_TOKEN_DIRECT_REFERENCE);
87          securityToken.addTokenUsage(WSSecurityTokenConstants.TOKENUSAGE_MAIN_ENCRYPTION);
88          recipientTokenSecurityEvent.setSecurityToken(securityToken);
89          policyEnforcer.registerSecurityEvent(recipientTokenSecurityEvent);
90  
91          List<XMLSecurityConstants.ContentType> protectionOrder = new LinkedList<>();
92          protectionOrder.add(XMLSecurityConstants.ContentType.SIGNATURE);
93          protectionOrder.add(XMLSecurityConstants.ContentType.ENCRYPTION);
94          EncryptedElementSecurityEvent encryptedElementSecurityEvent = new EncryptedElementSecurityEvent(null, true, protectionOrder);
95          headerPath = new ArrayList<>();
96          headerPath.addAll(WSSConstants.SOAP_11_WSSE_SECURITY_HEADER_PATH);
97          headerPath.add(WSSConstants.TAG_dsig_Signature);
98          encryptedElementSecurityEvent.setElementPath(headerPath);
99          policyEnforcer.registerSecurityEvent(encryptedElementSecurityEvent);
100 
101         encryptedElementSecurityEvent = new EncryptedElementSecurityEvent(null, true, protectionOrder);
102         headerPath = new ArrayList<>();
103         headerPath.addAll(WSSConstants.SOAP_11_WSSE_SECURITY_HEADER_PATH);
104         headerPath.add(WSSConstants.TAG_WSSE11_SIG_CONF);
105         encryptedElementSecurityEvent.setElementPath(headerPath);
106         policyEnforcer.registerSecurityEvent(encryptedElementSecurityEvent);
107 
108         OperationSecurityEvent operationSecurityEvent = new OperationSecurityEvent();
109         operationSecurityEvent.setOperation(new QName("definitions"));
110         policyEnforcer.registerSecurityEvent(operationSecurityEvent);
111 
112         SignedPartSecurityEvent signedPartSecurityEvent = new SignedPartSecurityEvent(null, true, protectionOrder);
113         signedPartSecurityEvent.setXmlSecEvent(XMLSecEventFactory.createXmlSecStartElement(WSSConstants.TAG_SOAP11_BODY, null, null));
114         signedPartSecurityEvent.setElementPath(WSSConstants.SOAP_11_BODY_PATH);
115         policyEnforcer.registerSecurityEvent(signedPartSecurityEvent);
116         policyEnforcer.doFinal();
117     }
118 
119     @Test
120     public void testPolicyNotIncludeTimestamp() throws Exception {
121         String policyString =
122                 "<sp:SymmetricBinding xmlns:sp=\"http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702\" xmlns:sp3=\"http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200802\">\n" +
123                         "<wsp:Policy xmlns:wsp=\"http://schemas.xmlsoap.org/ws/2004/09/policy\">\n" +
124                         "   <sp:AlgorithmSuite>\n" +
125                         "       <wsp:Policy>\n" +
126                         "           <sp:Basic256/>\n" +
127                         "       </wsp:Policy>\n" +
128                         "   </sp:AlgorithmSuite>\n" +
129                         "<sp:EncryptSignature/>\n" +
130                         "<sp:ProtectTokens/>\n" +
131                         "<sp:OnlySignEntireHeadersAndBody/>\n" +
132                         "</wsp:Policy>\n" +
133                         "</sp:SymmetricBinding>";
134         PolicyEnforcer policyEnforcer = buildAndStartPolicyEngine(policyString);
135 
136         SecurityContextTokenSecurityEvent initiatorTokenSecurityEvent = new SecurityContextTokenSecurityEvent();
137         SecureConversationSecurityTokenImpl securityToken =
138                 new SecureConversationSecurityTokenImpl(
139                         null, "1", WSSecurityTokenConstants.KEYIDENTIFIER_SECURITY_TOKEN_DIRECT_REFERENCE);
140         securityToken.addTokenUsage(WSSecurityTokenConstants.TOKENUSAGE_MAIN_SIGNATURE);
141         initiatorTokenSecurityEvent.setSecurityToken(securityToken);
142         policyEnforcer.registerSecurityEvent(initiatorTokenSecurityEvent);
143 
144         SecurityContextTokenSecurityEvent recipientTokenSecurityEvent = new SecurityContextTokenSecurityEvent();
145         securityToken = new SecureConversationSecurityTokenImpl(
146                 null, "1", WSSecurityTokenConstants.KEYIDENTIFIER_SECURITY_TOKEN_DIRECT_REFERENCE);
147         securityToken.addTokenUsage(WSSecurityTokenConstants.TOKENUSAGE_MAIN_ENCRYPTION);
148         recipientTokenSecurityEvent.setSecurityToken(securityToken);
149         policyEnforcer.registerSecurityEvent(recipientTokenSecurityEvent);
150 
151         TimestampSecurityEvent timestampSecurityEvent = new TimestampSecurityEvent();
152         policyEnforcer.registerSecurityEvent(timestampSecurityEvent);
153 
154         OperationSecurityEvent operationSecurityEvent = new OperationSecurityEvent();
155         operationSecurityEvent.setOperation(new QName("definitions"));
156         try {
157             policyEnforcer.registerSecurityEvent(operationSecurityEvent);
158             fail("Exception expected");
159         } catch (WSSecurityException e) {
160             assertTrue(e.getCause() instanceof PolicyViolationException);
161             assertEquals(e.getCause().getMessage(),
162                     "Timestamp must not be present");
163             assertEquals(e.getFaultCode(), WSSecurityException.INVALID_SECURITY);
164         }
165     }
166 
167     @Test
168     public void testPolicyWrongProtectionOrder() throws Exception {
169         String policyString =
170                 "<sp:SymmetricBinding xmlns:sp=\"http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702\" xmlns:sp3=\"http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200802\">\n" +
171                         "<wsp:Policy xmlns:wsp=\"http://schemas.xmlsoap.org/ws/2004/09/policy\">\n" +
172                         "   <sp:AlgorithmSuite>\n" +
173                         "       <wsp:Policy>\n" +
174                         "           <sp:Basic256/>\n" +
175                         "       </wsp:Policy>\n" +
176                         "   </sp:AlgorithmSuite>\n" +
177                         "<sp:IncludeTimestamp/>\n" +
178                         "<sp:EncryptBeforeSigning/>\n" +
179                         "<sp:EncryptSignature/>\n" +
180                         "<sp:ProtectTokens/>\n" +
181                         "<sp:OnlySignEntireHeadersAndBody/>\n" +
182                         "</wsp:Policy>\n" +
183                         "</sp:SymmetricBinding>";
184         PolicyEnforcer policyEnforcer = buildAndStartPolicyEngine(policyString);
185         SecurityContextTokenSecurityEvent SecurityContextTokenSecurityEvent = new SecurityContextTokenSecurityEvent();
186         SecureConversationSecurityTokenImpl securityToken =
187                 new SecureConversationSecurityTokenImpl(
188                         null, "1", WSSecurityTokenConstants.KEYIDENTIFIER_SECURITY_TOKEN_DIRECT_REFERENCE);
189         securityToken.addTokenUsage(WSSecurityTokenConstants.TOKENUSAGE_MAIN_ENCRYPTION);
190         SecurityContextTokenSecurityEvent.setSecurityToken(securityToken);
191         policyEnforcer.registerSecurityEvent(SecurityContextTokenSecurityEvent);
192 
193         List<XMLSecurityConstants.ContentType> protectionOrder = new LinkedList<>();
194         protectionOrder.add(XMLSecurityConstants.ContentType.SIGNATURE);
195         protectionOrder.add(XMLSecurityConstants.ContentType.ENCRYPTION);
196         SignedPartSecurityEvent signedPartSecurityEvent = new SignedPartSecurityEvent(null, true, protectionOrder);
197         signedPartSecurityEvent.setElementPath(WSSConstants.SOAP_11_BODY_PATH);
198         policyEnforcer.registerSecurityEvent(signedPartSecurityEvent);
199 
200         OperationSecurityEvent operationSecurityEvent = new OperationSecurityEvent();
201         operationSecurityEvent.setOperation(new QName("definitions"));
202         try {
203             policyEnforcer.registerSecurityEvent(operationSecurityEvent);
204             fail("Exception expected");
205         } catch (WSSecurityException e) {
206             assertTrue(e.getCause() instanceof PolicyViolationException);
207             assertEquals(e.getCause().getMessage(),
208                     "Policy enforces EncryptBeforeSigning but the /{http://schemas.xmlsoap.org/soap/envelope/}Envelope/{http://schemas.xmlsoap.org/soap/envelope/}Body was signed and then encrypted");
209             assertEquals(e.getFaultCode(), WSSecurityException.INVALID_SECURITY);
210         }
211     }
212 
213     @Test
214     public void testPolicySignatureNotEncrypted() throws Exception {
215         String policyString =
216                 "<sp:SymmetricBinding xmlns:sp=\"http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702\" xmlns:sp3=\"http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200802\">\n" +
217                         "<wsp:Policy xmlns:wsp=\"http://schemas.xmlsoap.org/ws/2004/09/policy\">\n" +
218                         "   <sp:AlgorithmSuite>\n" +
219                         "       <wsp:Policy>\n" +
220                         "           <sp:Basic256/>\n" +
221                         "       </wsp:Policy>\n" +
222                         "   </sp:AlgorithmSuite>\n" +
223                         "<sp:IncludeTimestamp/>\n" +
224                         "<sp:EncryptSignature/>\n" +
225                         "<sp:ProtectTokens/>\n" +
226                         "<sp:OnlySignEntireHeadersAndBody/>\n" +
227                         "</wsp:Policy>\n" +
228                         "</sp:SymmetricBinding>";
229         PolicyEnforcer policyEnforcer = buildAndStartPolicyEngine(policyString);
230         TimestampSecurityEvent timestampSecurityEvent = new TimestampSecurityEvent();
231         policyEnforcer.registerSecurityEvent(timestampSecurityEvent);
232 
233         SecurityContextTokenSecurityEvent initiatorTokenSecurityEvent = new SecurityContextTokenSecurityEvent();
234         SecureConversationSecurityTokenImpl securityToken =
235                 new SecureConversationSecurityTokenImpl(
236                         null, "1", WSSecurityTokenConstants.KEYIDENTIFIER_SECURITY_TOKEN_DIRECT_REFERENCE);
237         securityToken.addTokenUsage(WSSecurityTokenConstants.TOKENUSAGE_MAIN_SIGNATURE);
238         initiatorTokenSecurityEvent.setSecurityToken(securityToken);
239         policyEnforcer.registerSecurityEvent(initiatorTokenSecurityEvent);
240 
241         SecurityContextTokenSecurityEvent recipientTokenSecurityEvent = new SecurityContextTokenSecurityEvent();
242         securityToken = new SecureConversationSecurityTokenImpl(
243                 null, "1", WSSecurityTokenConstants.KEYIDENTIFIER_SECURITY_TOKEN_DIRECT_REFERENCE);
244         securityToken.addTokenUsage(WSSecurityTokenConstants.TOKENUSAGE_MAIN_ENCRYPTION);
245         recipientTokenSecurityEvent.setSecurityToken(securityToken);
246         policyEnforcer.registerSecurityEvent(recipientTokenSecurityEvent);
247 
248         List<XMLSecurityConstants.ContentType> protectionOrder = new LinkedList<>();
249         protectionOrder.add(XMLSecurityConstants.ContentType.SIGNATURE);
250         protectionOrder.add(XMLSecurityConstants.ContentType.ENCRYPTION);
251         EncryptedElementSecurityEvent encryptedElementSecurityEvent = new EncryptedElementSecurityEvent(null, false, protectionOrder);
252         List<QName> headerPath = new ArrayList<>();
253         headerPath.addAll(WSSConstants.SOAP_11_WSSE_SECURITY_HEADER_PATH);
254         headerPath.add(WSSConstants.TAG_dsig_Signature);
255         encryptedElementSecurityEvent.setElementPath(headerPath);
256         policyEnforcer.registerSecurityEvent(encryptedElementSecurityEvent);
257 
258         OperationSecurityEvent operationSecurityEvent = new OperationSecurityEvent();
259         operationSecurityEvent.setOperation(new QName("definitions"));
260         try {
261             policyEnforcer.registerSecurityEvent(operationSecurityEvent);
262             fail("Exception expected");
263         } catch (WSSecurityException e) {
264             assertEquals(e.getCause().getMessage(),
265                     "Element /{http://schemas.xmlsoap.org/soap/envelope/}Envelope/{http://schemas.xmlsoap.org/soap/envelope/}Header/{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd}Security/{http://www.w3.org/2000/09/xmldsig#}Signature must be encrypted");
266             assertEquals(e.getFaultCode(), WSSecurityException.INVALID_SECURITY);
267         }
268     }
269 
270     @Test
271     public void testPolicyNotWholeBodySigned() throws Exception {
272         String policyString =
273                 "<sp:SymmetricBinding xmlns:sp=\"http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702\" xmlns:sp3=\"http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200802\">\n" +
274                         "<wsp:Policy xmlns:wsp=\"http://schemas.xmlsoap.org/ws/2004/09/policy\">\n" +
275                         "   <sp:AlgorithmSuite>\n" +
276                         "       <wsp:Policy>\n" +
277                         "           <sp:Basic256/>\n" +
278                         "       </wsp:Policy>\n" +
279                         "   </sp:AlgorithmSuite>\n" +
280                         "<sp:IncludeTimestamp/>\n" +
281                         "<sp:EncryptSignature/>\n" +
282                         "<sp:OnlySignEntireHeadersAndBody/>\n" +
283                         "</wsp:Policy>\n" +
284                         "</sp:SymmetricBinding>";
285         PolicyEnforcer policyEnforcer = buildAndStartPolicyEngine(policyString);
286         TimestampSecurityEvent timestampSecurityEvent = new TimestampSecurityEvent();
287         policyEnforcer.registerSecurityEvent(timestampSecurityEvent);
288 
289         SecurityContextTokenSecurityEvent initiatorTokenSecurityEvent = new SecurityContextTokenSecurityEvent();
290         SecureConversationSecurityTokenImpl securityToken =
291                 new SecureConversationSecurityTokenImpl(
292                         null, "1", WSSecurityTokenConstants.KEYIDENTIFIER_SECURITY_TOKEN_DIRECT_REFERENCE);
293         securityToken.addTokenUsage(WSSecurityTokenConstants.TOKENUSAGE_MAIN_SIGNATURE);
294         initiatorTokenSecurityEvent.setSecurityToken(securityToken);
295         policyEnforcer.registerSecurityEvent(initiatorTokenSecurityEvent);
296 
297         SecurityContextTokenSecurityEvent recipientTokenSecurityEvent = new SecurityContextTokenSecurityEvent();
298         securityToken = new SecureConversationSecurityTokenImpl(
299                 null, "1", WSSecurityTokenConstants.KEYIDENTIFIER_SECURITY_TOKEN_DIRECT_REFERENCE);
300         securityToken.addTokenUsage(WSSecurityTokenConstants.TOKENUSAGE_MAIN_ENCRYPTION);
301         recipientTokenSecurityEvent.setSecurityToken(securityToken);
302         policyEnforcer.registerSecurityEvent(recipientTokenSecurityEvent);
303 
304         List<XMLSecurityConstants.ContentType> protectionOrder = new LinkedList<>();
305         protectionOrder.add(XMLSecurityConstants.ContentType.SIGNATURE);
306         protectionOrder.add(XMLSecurityConstants.ContentType.ENCRYPTION);
307         EncryptedElementSecurityEvent encryptedElementSecurityEvent = new EncryptedElementSecurityEvent(null, true, protectionOrder);
308         List<QName> headerPath = new ArrayList<>();
309         headerPath.addAll(WSSConstants.SOAP_11_WSSE_SECURITY_HEADER_PATH);
310         headerPath.add(WSSConstants.TAG_dsig_Signature);
311         encryptedElementSecurityEvent.setElementPath(headerPath);
312         policyEnforcer.registerSecurityEvent(encryptedElementSecurityEvent);
313 
314         encryptedElementSecurityEvent = new EncryptedElementSecurityEvent(null, true, protectionOrder);
315         headerPath = new ArrayList<>();
316         headerPath.addAll(WSSConstants.SOAP_11_WSSE_SECURITY_HEADER_PATH);
317         headerPath.add(WSSConstants.TAG_WSSE11_SIG_CONF);
318         encryptedElementSecurityEvent.setElementPath(headerPath);
319         policyEnforcer.registerSecurityEvent(encryptedElementSecurityEvent);
320 
321         OperationSecurityEvent operationSecurityEvent = new OperationSecurityEvent();
322         operationSecurityEvent.setOperation(new QName("definitions"));
323         policyEnforcer.registerSecurityEvent(operationSecurityEvent);
324 
325         SignedPartSecurityEvent signedPartSecurityEvent = new SignedPartSecurityEvent(null, true, protectionOrder);
326         QName elementName = new QName("http://www.example.com", "bodyChildElement");
327         signedPartSecurityEvent.setXmlSecEvent(XMLSecEventFactory.createXmlSecStartElement(elementName, null, null));
328         List<QName> elementPath = new ArrayList<>();
329         elementPath.addAll(WSSConstants.SOAP_11_BODY_PATH);
330         elementPath.add(elementName);
331         signedPartSecurityEvent.setElementPath(elementPath);
332         try {
333             policyEnforcer.registerSecurityEvent(signedPartSecurityEvent);
334             fail("Exception expected");
335         } catch (WSSecurityException e) {
336             assertTrue(e.getCause() instanceof PolicyViolationException);
337             assertEquals(e.getCause().getMessage(),
338                     "OnlySignEntireHeadersAndBody not fulfilled, offending element: " +
339                             "/{http://schemas.xmlsoap.org/soap/envelope/}Envelope/{http://schemas.xmlsoap.org/soap/envelope/}Body/{http://www.example.com}bodyChildElement");
340             assertEquals(e.getFaultCode(), WSSecurityException.INVALID_SECURITY);
341         }
342     }
343 }