1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.wss4j.dom.message;
21
22 import java.text.MessageFormat;
23 import java.util.Map;
24 import java.util.ResourceBundle;
25 import java.util.TreeMap;
26
27 import javax.crypto.KeyGenerator;
28 import javax.crypto.SecretKey;
29 import javax.security.auth.callback.CallbackHandler;
30
31 import org.apache.wss4j.common.util.SOAPUtil;
32 import org.apache.wss4j.dom.WSConstants;
33 import org.apache.wss4j.dom.common.CustomHandler;
34 import org.apache.wss4j.dom.common.KeystoreCallbackHandler;
35
36 import org.apache.wss4j.dom.engine.WSSConfig;
37 import org.apache.wss4j.dom.engine.WSSecurityEngine;
38 import org.apache.wss4j.common.crypto.Crypto;
39 import org.apache.wss4j.common.crypto.CryptoFactory;
40 import org.apache.wss4j.common.ext.WSSecurityException;
41 import org.apache.wss4j.common.util.KeyUtils;
42 import org.apache.wss4j.common.util.XMLUtils;
43 import org.apache.wss4j.dom.handler.RequestData;
44 import org.apache.wss4j.dom.handler.WSHandlerConstants;
45 import org.apache.wss4j.dom.handler.WSHandlerResult;
46 import org.apache.wss4j.dom.util.WSSecurityUtil;
47
48 import org.junit.jupiter.api.Test;
49 import org.w3c.dom.Document;
50 import org.w3c.dom.Element;
51
52 import static org.junit.jupiter.api.Assertions.assertEquals;
53 import static org.junit.jupiter.api.Assertions.assertTrue;
54 import static org.junit.jupiter.api.Assertions.fail;
55
56
57
58
59
60
61 public class RequireSignedEncryptedDataElementsTest {
62 private static final org.slf4j.Logger LOG =
63 org.slf4j.LoggerFactory.getLogger(RequireSignedEncryptedDataElementsTest.class);
64 private static ResourceBundle resources = ResourceBundle.getBundle("messages.wss4j_errors");
65 private static final String SOAPMSG =
66 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
67 + "<SOAP-ENV:Envelope "
68 + "xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" "
69 + "xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" "
70 + "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">"
71 + "<SOAP-ENV:Body>"
72 + "<add xmlns=\"http://ws.apache.org/counter/counter_port_type\">"
73 + "<value xmlns=\"http://blah.com\">15</value>"
74 + "</add>"
75 + "</SOAP-ENV:Body>"
76 + "</SOAP-ENV:Envelope>";
77 private WSSecurityEngine secEngine = new WSSecurityEngine();
78 private CallbackHandler callbackHandler = new KeystoreCallbackHandler();
79 private Crypto crypto;
80
81 public RequireSignedEncryptedDataElementsTest() throws Exception {
82 crypto = CryptoFactory.getInstance();
83 WSSConfig.init();
84 }
85
86 @Test
87 public void testEncryptedKeyRefAndDuplicatedEncDataInWsseHeader() throws Exception {
88 Document encryptedSignedDoc = getRequestDocument();
89 RequestData reqData = getRequestData(true);
90 verify(encryptedSignedDoc, reqData);
91
92 encryptedSignedDoc = getRequestDocument();
93 reqData = getRequestData(false);
94 TestMessageTransformer.duplicateEncryptedDataInWsseHeader(encryptedSignedDoc.getDocumentElement(), false);
95 verify(encryptedSignedDoc, reqData);
96
97 encryptedSignedDoc = getRequestDocument();
98 reqData = getRequestData(true);
99 Element newEncData = TestMessageTransformer.duplicateEncryptedDataInWsseHeader(encryptedSignedDoc.getDocumentElement(), false);
100 try {
101 verify(encryptedSignedDoc, reqData);
102 fail("WSSecurityException expected");
103 } catch (WSSecurityException e) {
104 checkFailure(newEncData, e);
105 }
106 }
107
108 @Test
109 public void testEncryptedKeyRefAndDuplicatedEncDataInWsseWrapperHeader() throws Exception {
110 Document encryptedSignedDoc = getRequestDocument();
111 RequestData reqData = getRequestData(true);
112 verify(encryptedSignedDoc, reqData);
113
114 encryptedSignedDoc = getRequestDocument();
115 reqData = getRequestData(false);
116 TestMessageTransformer.duplicateEncryptedDataInWsseWrapperHeader(encryptedSignedDoc.getDocumentElement(), false);
117 verify(encryptedSignedDoc, reqData);
118
119 encryptedSignedDoc = getRequestDocument();
120 reqData = getRequestData(true);
121 Element newEncData = TestMessageTransformer.duplicateEncryptedDataInWsseWrapperHeader(encryptedSignedDoc.getDocumentElement(), false);
122 try {
123 verify(encryptedSignedDoc, reqData);
124 fail("WSSecurityException expected");
125 } catch (WSSecurityException e) {
126 checkFailure(newEncData, e);
127 }
128 }
129
130 @Test
131 public void testEncryptedKeyRefAndDuplicatedEncDataInExternalWrapperElement() throws Exception {
132 Document encryptedSignedDoc = getRequestDocument();
133 RequestData reqData = getRequestData(true);
134 verify(encryptedSignedDoc, reqData);
135
136 encryptedSignedDoc = getRequestDocument();
137 reqData = getRequestData(false);
138 TestMessageTransformer.duplicateEncryptedDataInExternalWrapperElement(encryptedSignedDoc.getDocumentElement(), false);
139 verify(encryptedSignedDoc, reqData);
140
141 encryptedSignedDoc = getRequestDocument();
142 reqData = getRequestData(true);
143 Element newEncData = TestMessageTransformer.duplicateEncryptedDataInExternalWrapperElement(encryptedSignedDoc.getDocumentElement(), false);
144 try {
145 verify(encryptedSignedDoc, reqData);
146 fail("WSSecurityException expected");
147 } catch (WSSecurityException e) {
148 checkFailure(newEncData, e);
149 }
150 }
151
152 @Test
153 public void testReferenceListAndDuplicatedEncDataInWsseHeader() throws Exception {
154 Document encryptedSignedDoc = getRequestDocument();
155 RequestData reqData = getRequestData(true);
156 verify(encryptedSignedDoc, reqData);
157
158 encryptedSignedDoc = getRequestDocument();
159 reqData = getRequestData(false);
160 TestMessageTransformer.duplicateEncryptedDataInWsseHeader(encryptedSignedDoc.getDocumentElement(), true);
161 verify(encryptedSignedDoc, reqData);
162
163 encryptedSignedDoc = getRequestDocument();
164 reqData = getRequestData(true);
165 Element newEncData = TestMessageTransformer.duplicateEncryptedDataInWsseHeader(encryptedSignedDoc.getDocumentElement(), true);
166 try {
167 verify(encryptedSignedDoc, reqData);
168 fail("WSSecurityException expected");
169 } catch (WSSecurityException e) {
170 checkFailure(newEncData, e);
171 }
172 }
173
174 @Test
175 public void testReferenceListAndDuplicatedEncDataInWsseWrapperHeader() throws Exception {
176 Document encryptedSignedDoc = getRequestDocument();
177 RequestData reqData = getRequestData(true);
178 verify(encryptedSignedDoc, reqData);
179
180 encryptedSignedDoc = getRequestDocument();
181 reqData = getRequestData(false);
182 TestMessageTransformer.duplicateEncryptedDataInWsseWrapperHeader(encryptedSignedDoc.getDocumentElement(), true);
183 verify(encryptedSignedDoc, reqData);
184
185 encryptedSignedDoc = getRequestDocument();
186 reqData = getRequestData(true);
187 Element newEncData = TestMessageTransformer.duplicateEncryptedDataInWsseWrapperHeader(encryptedSignedDoc.getDocumentElement(), true);
188 try {
189 verify(encryptedSignedDoc, reqData);
190 fail("WSSecurityException expected");
191 } catch (WSSecurityException e) {
192 checkFailure(newEncData, e);
193 }
194 }
195
196 @Test
197 public void testReferenceListAndDuplicatedEncDataInExternalWrapperElement() throws Exception {
198 Document encryptedSignedDoc = getRequestDocument();
199 RequestData reqData = getRequestData(true);
200 verify(encryptedSignedDoc, reqData);
201
202 encryptedSignedDoc = getRequestDocument();
203 reqData = getRequestData(false);
204 TestMessageTransformer.duplicateEncryptedDataInExternalWrapperElement(encryptedSignedDoc.getDocumentElement(), true);
205 verify(encryptedSignedDoc, reqData);
206
207 encryptedSignedDoc = getRequestDocument();
208 reqData = getRequestData(true);
209 Element newEncData = TestMessageTransformer.duplicateEncryptedDataInExternalWrapperElement(encryptedSignedDoc.getDocumentElement(), true);
210 try {
211 verify(encryptedSignedDoc, reqData);
212 fail("WSSecurityException expected");
213 } catch (WSSecurityException e) {
214 checkFailure(newEncData, e);
215 }
216 }
217
218 @Test
219 public void testAdditionalEncryptedDataWithEmbeddedEncryptedKeyInWsseHeader() throws Exception {
220 Document encryptedSignedDoc = getRequestDocument();
221 RequestData reqData = getRequestData(true);
222 verify(encryptedSignedDoc, reqData);
223
224 encryptedSignedDoc = getRequestDocument();
225 reqData = getRequestData(true);
226 Element newEncData = TestMessageTransformer.addEncryptedDataWithEmbeddedEncryptedKeyInWsseHeader(encryptedSignedDoc.getDocumentElement());
227 try {
228 verify(encryptedSignedDoc, reqData);
229 fail("WSSecurityException expected");
230 } catch (WSSecurityException e) {
231 checkFailure(newEncData, e);
232 }
233 }
234
235 @Test
236 public void testEncryptedKeyRefAndDuplicatedEncDataInWsseWrapperBody() throws Exception {
237 Document encryptedSignedDoc = getRequestDocumentEncryptionFirst();
238 RequestData reqData = getRequestData(false);
239 TestMessageTransformer.duplicateEncryptedDataInWrapperBody(encryptedSignedDoc.getDocumentElement());
240 try {
241 verify(encryptedSignedDoc, reqData);
242 fail("WSSecurityException expected");
243 } catch (WSSecurityException e) {
244 assertTrue(e.getMessage().contains("The signature or decryption was invalid"));
245 }
246
247 encryptedSignedDoc = getRequestDocumentEncryptionFirst();
248 TestMessageTransformer.duplicateEncryptedDataInWrapperBody(encryptedSignedDoc.getDocumentElement());
249 reqData = getRequestData(true);
250
251 try {
252 verify(encryptedSignedDoc, reqData);
253 fail("WSSecurityException expected");
254 } catch (WSSecurityException e) {
255 assertTrue(e.getMessage().contains("is not signed"));
256 }
257 }
258
259 @Test
260 public void testEncryptedKeyRefAndDuplicatedEncDataAfterWsseWrapperBody() throws Exception {
261 Document encryptedSignedDoc = getRequestDocumentEncryptionFirst();
262 TestMessageTransformer.duplicateEncryptedDataAfterWrapperBody(encryptedSignedDoc.getDocumentElement());
263
264 RequestData reqData = getRequestData(true);
265 try {
266 verify(encryptedSignedDoc, reqData);
267 fail("WSSecurityException expected");
268 } catch (WSSecurityException e) {
269 assertTrue(e.getMessage().contains("is not signed"));
270 }
271 }
272
273 private static void checkFailure(Element attackElement, WSSecurityException e) {
274 final String mex = MessageFormat.format(resources.getString("elementNotSigned"), attackElement);
275 assertTrue(e.getMessage().contains(mex));
276 assertEquals(WSSecurityException.ErrorCode.FAILED_CHECK, e.getErrorCode());
277 }
278
279 private RequestData getRequestData(boolean reqSignedEncData) throws WSSecurityException {
280 RequestData reqData = new RequestData();
281 Map<String, Object> messageContext = new TreeMap<>();
282 messageContext = new TreeMap<>();
283 messageContext.put(WSHandlerConstants.REQUIRE_SIGNED_ENCRYPTED_DATA_ELEMENTS, Boolean.toString(reqSignedEncData));
284 reqData.setMsgContext(messageContext);
285 CustomHandler handler = new CustomHandler();
286 handler.receive(WSSecurityUtil.decodeAction("Encrypt Signature"), reqData);
287 reqData.setCallbackHandler(callbackHandler);
288 reqData.setSigVerCrypto(crypto);
289 reqData.setDecCrypto(crypto);
290 return reqData;
291 }
292
293 private Document getRequestDocument() throws Exception {
294 Document doc = SOAPUtil.toSOAPPart(SOAPMSG);
295 WSSecHeader secHeader = new WSSecHeader(doc);
296 secHeader.insertSecurityHeader();
297
298 WSSecEncrypt encrypt = new WSSecEncrypt(secHeader);
299 WSSecSignature sign = new WSSecSignature(secHeader);
300 encrypt.setUserInfo("16c73ab6-b892-458f-abf5-2f875f74882e");
301 sign.setUserInfo("16c73ab6-b892-458f-abf5-2f875f74882e", "security");
302 LOG.info("Before Encryption....");
303
304 KeyGenerator keyGen = KeyUtils.getKeyGenerator(WSConstants.AES_128);
305 SecretKey symmetricKey = keyGen.generateKey();
306 Document encryptedDoc = encrypt.build(crypto, symmetricKey);
307
308 if (LOG.isDebugEnabled()) {
309 LOG.debug("After Encryption....");
310 String outputString =
311 XMLUtils.prettyDocumentToString(encryptedDoc);
312 LOG.debug(outputString);
313 }
314
315 Document encryptedSignedDoc = sign.build(crypto);
316
317 if (LOG.isDebugEnabled()) {
318 LOG.debug("After Signing....");
319 String outputString =
320 XMLUtils.prettyDocumentToString(encryptedSignedDoc);
321 LOG.debug(outputString);
322 }
323 return encryptedSignedDoc;
324 }
325
326 private Document getRequestDocumentEncryptionFirst() throws Exception {
327 Document doc = SOAPUtil.toSOAPPart(SOAPMSG);
328 WSSecHeader secHeader = new WSSecHeader(doc);
329 secHeader.insertSecurityHeader();
330
331 WSSecEncrypt encrypt = new WSSecEncrypt(secHeader);
332 WSSecSignature sign = new WSSecSignature(secHeader);
333 encrypt.setUserInfo("16c73ab6-b892-458f-abf5-2f875f74882e");
334 sign.setUserInfo("16c73ab6-b892-458f-abf5-2f875f74882e", "security");
335 LOG.info("Before Encryption....");
336
337 Document signedDoc = sign.build(crypto);
338
339 if (LOG.isDebugEnabled()) {
340 LOG.debug("After Signing....");
341 String outputString =
342 XMLUtils.prettyDocumentToString(signedDoc);
343 LOG.debug(outputString);
344 }
345
346 KeyGenerator keyGen = KeyUtils.getKeyGenerator(WSConstants.AES_128);
347 SecretKey symmetricKey = keyGen.generateKey();
348 Document encryptedDoc = encrypt.build(crypto, symmetricKey);
349
350 if (LOG.isDebugEnabled()) {
351 LOG.debug("After Encryption....");
352 String outputString =
353 XMLUtils.prettyDocumentToString(encryptedDoc);
354 LOG.debug(outputString);
355 }
356
357 return encryptedDoc;
358 }
359
360
361 private WSHandlerResult verify(Document doc, RequestData reqData) throws Exception {
362 Element elem = WSSecurityUtil.getSecurityHeader(doc, null);
363 WSHandlerResult resultList =
364 secEngine.processSecurityHeader(elem, reqData);
365 if (LOG.isDebugEnabled()) {
366 String outputString =
367 XMLUtils.prettyDocumentToString(doc);
368 LOG.debug(outputString);
369 }
370
371 return resultList;
372 }
373
374 }