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.handler;
21
22 import java.util.*;
23
24 import javax.security.auth.callback.CallbackHandler;
25
26 import org.apache.wss4j.common.bsp.BSPRule;
27 import org.apache.wss4j.common.crypto.Crypto;
28 import org.apache.wss4j.common.crypto.CryptoFactory;
29 import org.apache.wss4j.common.ext.WSSecurityException;
30 import org.apache.wss4j.common.saml.builder.SAML2Constants;
31 import org.apache.wss4j.common.util.SOAPUtil;
32 import org.apache.wss4j.common.util.XMLUtils;
33 import org.apache.wss4j.dom.WSConstants;
34 import org.apache.wss4j.dom.common.CustomHandler;
35 import org.apache.wss4j.dom.common.KeystoreCallbackHandler;
36 import org.apache.wss4j.dom.common.SAML2CallbackHandler;
37
38 import org.apache.wss4j.dom.engine.WSSecurityEngine;
39 import org.apache.wss4j.dom.engine.WSSecurityEngineResult;
40 import org.apache.wss4j.dom.message.WSSecHeader;
41 import org.apache.wss4j.dom.message.token.SignatureConfirmation;
42
43 import org.junit.jupiter.api.Test;
44 import org.w3c.dom.Document;
45 import org.w3c.dom.Element;
46
47 import static org.junit.jupiter.api.Assertions.assertFalse;
48 import static org.junit.jupiter.api.Assertions.assertNotNull;
49 import static org.junit.jupiter.api.Assertions.assertNull;
50 import static org.junit.jupiter.api.Assertions.assertTrue;
51 import static org.junit.jupiter.api.Assertions.fail;
52
53
54
55
56 public class SignatureConfirmationTest {
57 private static final org.slf4j.Logger LOG =
58 org.slf4j.LoggerFactory.getLogger(SignatureConfirmationTest.class);
59 private WSSecurityEngine secEngine = new WSSecurityEngine();
60 private CallbackHandler callbackHandler = new KeystoreCallbackHandler();
61 private Crypto crypto;
62
63 public SignatureConfirmationTest() throws Exception {
64 crypto = CryptoFactory.getInstance();
65 }
66
67
68
69
70 @SuppressWarnings("unchecked")
71 @Test
72 public void
73 testRequestSavedSignature() throws Exception {
74 final RequestData reqData = new RequestData();
75 java.util.Map<String, Object> msgContext = new java.util.TreeMap<>();
76 msgContext.put(WSHandlerConstants.ENABLE_SIGNATURE_CONFIRMATION, "true");
77 msgContext.put(WSHandlerConstants.SIG_PROP_FILE, "crypto.properties");
78 msgContext.put("password", "security");
79 reqData.setMsgContext(msgContext);
80 reqData.setUsername("16c73ab6-b892-458f-abf5-2f875f74882e");
81
82 final Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
83 CustomHandler handler = new CustomHandler();
84 HandlerAction action = new HandlerAction(WSConstants.SIGN);
85 handler.send(
86 doc,
87 reqData,
88 Collections.singletonList(action),
89 true
90 );
91 if (LOG.isDebugEnabled()) {
92 LOG.debug("After Signing....");
93 String outputString =
94 XMLUtils.prettyDocumentToString(doc);
95 LOG.debug(outputString);
96 }
97
98 msgContext = (java.util.Map<String, Object>)reqData.getMsgContext();
99 Set<Integer> savedSignatures =
100 (Set<Integer>)msgContext.get(WSHandlerConstants.SEND_SIGV);
101 assertTrue(savedSignatures != null && savedSignatures.size() == 1);
102 Integer signatureValue = savedSignatures.iterator().next();
103 assertTrue(signatureValue != null && signatureValue != 0);
104 }
105
106
107
108
109
110
111 @SuppressWarnings("unchecked")
112 @Test
113 public void
114 testRequestNotSavedSignature() throws Exception {
115 final RequestData reqData = new RequestData();
116 java.util.Map<String, Object> msgContext = new java.util.TreeMap<>();
117 msgContext.put(WSHandlerConstants.ENABLE_SIGNATURE_CONFIRMATION, "false");
118 msgContext.put(WSHandlerConstants.SIG_PROP_FILE, "crypto.properties");
119 msgContext.put("password", "security");
120 reqData.setMsgContext(msgContext);
121 reqData.setUsername("16c73ab6-b892-458f-abf5-2f875f74882e");
122
123 final Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
124 CustomHandler handler = new CustomHandler();
125 HandlerAction action = new HandlerAction(WSConstants.SIGN);
126 handler.send(
127 doc,
128 reqData,
129 Collections.singletonList(action),
130 true
131 );
132 if (LOG.isDebugEnabled()) {
133 LOG.debug("After Signing....");
134 String outputString =
135 XMLUtils.prettyDocumentToString(doc);
136 LOG.debug(outputString);
137 }
138
139 msgContext = (java.util.Map<String, Object>)reqData.getMsgContext();
140 Set<Integer> savedSignatures =
141 (Set<Integer>)msgContext.get(WSHandlerConstants.SEND_SIGV);
142 assertNull(savedSignatures);
143 }
144
145
146
147
148
149
150 @SuppressWarnings("unchecked")
151 @Test
152 public void
153 testSignatureConfirmationResponse() throws Exception {
154 final RequestData reqData = new RequestData();
155 java.util.Map<String, Object> msgContext = new java.util.TreeMap<>();
156 msgContext.put(WSHandlerConstants.ENABLE_SIGNATURE_CONFIRMATION, "true");
157 msgContext.put(WSHandlerConstants.SIG_PROP_FILE, "crypto.properties");
158 msgContext.put("password", "security");
159 reqData.setMsgContext(msgContext);
160 reqData.setUsername("16c73ab6-b892-458f-abf5-2f875f74882e");
161
162 Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
163 CustomHandler handler = new CustomHandler();
164 HandlerAction action = new HandlerAction(WSConstants.SIGN);
165 handler.send(
166 doc,
167 reqData,
168 Collections.singletonList(action),
169 true
170 );
171 if (LOG.isDebugEnabled()) {
172 LOG.debug("After Signing....");
173 String outputString =
174 XMLUtils.prettyDocumentToString(doc);
175 LOG.debug(outputString);
176 }
177
178 msgContext = (java.util.Map<String, Object>)reqData.getMsgContext();
179 Set<Integer> savedSignatures =
180 (Set<Integer>)msgContext.get(WSHandlerConstants.SEND_SIGV);
181 assertTrue(savedSignatures != null && savedSignatures.size() == 1);
182 Integer signatureValue = savedSignatures.iterator().next();
183 assertTrue(signatureValue != null && signatureValue != 0);
184
185
186
187
188 WSHandlerResult results = verify(doc);
189 doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
190 msgContext = (java.util.Map<String, Object>)reqData.getMsgContext();
191 List<WSHandlerResult> receivedResults = new ArrayList<>();
192 receivedResults.add(results);
193 msgContext.put(WSHandlerConstants.RECV_RESULTS, receivedResults);
194 action = new HandlerAction(WSConstants.NO_SECURITY);
195 handler.send(
196 doc,
197 reqData,
198 Collections.singletonList(action),
199 false
200 );
201 String outputString =
202 XMLUtils.prettyDocumentToString(doc);
203 if (LOG.isDebugEnabled()) {
204 LOG.debug("Signature Confirmation response....");
205 LOG.debug(outputString);
206 }
207 assertTrue(outputString.contains("SignatureConfirmation"));
208 assertTrue(outputString.contains("Value"));
209 }
210
211
212
213
214
215 @SuppressWarnings("unchecked")
216 @Test
217 public void
218 testSignatureConfirmationProcessing() throws Exception {
219 final RequestData reqData = new RequestData();
220 java.util.Map<String, Object> msgContext = new java.util.TreeMap<>();
221 msgContext.put(WSHandlerConstants.ENABLE_SIGNATURE_CONFIRMATION, "true");
222 msgContext.put(WSHandlerConstants.SIG_PROP_FILE, "crypto.properties");
223 msgContext.put("password", "security");
224 reqData.setMsgContext(msgContext);
225 reqData.setUsername("16c73ab6-b892-458f-abf5-2f875f74882e");
226
227 Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
228 CustomHandler handler = new CustomHandler();
229 HandlerAction action = new HandlerAction(WSConstants.SIGN);
230 handler.send(
231 doc,
232 reqData,
233 Collections.singletonList(action),
234 true
235 );
236 if (LOG.isDebugEnabled()) {
237 LOG.debug("After Signing....");
238 String outputString =
239 XMLUtils.prettyDocumentToString(doc);
240 LOG.debug(outputString);
241 }
242
243
244
245
246 WSHandlerResult results = verify(doc);
247 doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
248 msgContext = (java.util.Map<String, Object>)reqData.getMsgContext();
249 List<WSHandlerResult> receivedResults = new ArrayList<>();
250 receivedResults.add(results);
251 msgContext.put(WSHandlerConstants.RECV_RESULTS, receivedResults);
252 handler.send(
253 doc,
254 reqData,
255 Collections.singletonList(action),
256 false
257 );
258 String outputString =
259 XMLUtils.prettyDocumentToString(doc);
260 if (LOG.isDebugEnabled()) {
261 LOG.debug("Signature Confirmation response....");
262 LOG.debug(outputString);
263 }
264
265
266
267
268 results = verify(doc);
269 WSSecurityEngineResult scResult =
270 results.getActionResults().get(WSConstants.SC).get(0);
271 assertNotNull(scResult);
272 assertNotNull(scResult.get(WSSecurityEngineResult.TAG_SIGNATURE_CONFIRMATION));
273 handler.signatureConfirmation(reqData, results);
274 }
275
276
277
278
279
280
281 @Test
282 public void testWsuId() throws Exception {
283 Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
284 WSSecHeader secHeader = new WSSecHeader(doc);
285 secHeader.insertSecurityHeader();
286
287 Random random = new Random();
288 byte[] randomBytes = new byte[20];
289 random.nextBytes(randomBytes);
290 SignatureConfirmation sigConf = new SignatureConfirmation(doc, randomBytes);
291 Element sigConfElement = sigConf.getElement();
292 secHeader.getSecurityHeaderElement().appendChild(sigConfElement);
293
294 if (LOG.isDebugEnabled()) {
295 String outputString =
296 XMLUtils.prettyDocumentToString(doc);
297 LOG.debug(outputString);
298 }
299
300
301 WSSecurityEngine newEngine = new WSSecurityEngine();
302 try {
303 newEngine.processSecurityHeader(doc, null, callbackHandler, crypto);
304 fail("Failure expected on a request with no wsu:Id");
305 } catch (WSSecurityException ex) {
306 assertTrue(ex.getErrorCode() == WSSecurityException.ErrorCode.INVALID_SECURITY);
307 }
308
309 RequestData data = new RequestData();
310 data.setCallbackHandler(callbackHandler);
311 data.setSigVerCrypto(crypto);
312 data.setIgnoredBSPRules(Collections.singletonList(BSPRule.R5441));
313 newEngine.processSecurityHeader(doc, data);
314 }
315
316 @SuppressWarnings("unchecked")
317 @Test
318 public void testSignatureResponseForUnsignedRequest() throws Exception {
319 final RequestData reqData = new RequestData();
320 java.util.Map<String, Object> msgContext = new java.util.TreeMap<>();
321 msgContext.put(WSHandlerConstants.ENABLE_SIGNATURE_CONFIRMATION, "true");
322 msgContext.put(WSHandlerConstants.SIG_PROP_FILE, "crypto.properties");
323 msgContext.put("password", "security");
324 reqData.setMsgContext(msgContext);
325 reqData.setUsername("16c73ab6-b892-458f-abf5-2f875f74882e");
326
327 Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
328 CustomHandler handler = new CustomHandler();
329 HandlerAction action = new HandlerAction(WSConstants.NO_SECURITY);
330 handler.send(
331 doc,
332 reqData,
333 Collections.singletonList(action),
334 true
335 );
336 if (LOG.isDebugEnabled()) {
337 LOG.debug("After Signing....");
338 String outputString =
339 XMLUtils.prettyDocumentToString(doc);
340 LOG.debug(outputString);
341 }
342
343
344
345
346 WSHandlerResult results = verify(doc);
347 doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
348 msgContext = (java.util.Map<String, Object>)reqData.getMsgContext();
349 List<WSHandlerResult> receivedResults = new ArrayList<>();
350 receivedResults.add(results);
351 msgContext.put(WSHandlerConstants.RECV_RESULTS, receivedResults);
352 action = new HandlerAction(WSConstants.NO_SECURITY);
353 handler.send(
354 doc,
355 reqData,
356 Collections.singletonList(action),
357 false
358 );
359 String outputString =
360 XMLUtils.prettyDocumentToString(doc);
361 if (LOG.isDebugEnabled()) {
362 LOG.debug("Signature Confirmation response....");
363 LOG.debug(outputString);
364 }
365 assertTrue(outputString.contains("SignatureConfirmation"));
366
367 assertFalse(outputString.contains("Value"));
368 }
369
370 @SuppressWarnings("unchecked")
371 @Test
372 public void
373 testSAMLSignatureConfirmationProcessing() throws Exception {
374 final RequestData reqData = new RequestData();
375
376 SAML2CallbackHandler samlCallbackHandler = new SAML2CallbackHandler();
377 samlCallbackHandler.setConfirmationMethod(SAML2Constants.CONF_BEARER);
378 samlCallbackHandler.setStatement(SAML2CallbackHandler.Statement.AUTHN);
379 samlCallbackHandler.setIssuer("www.example.com");
380 samlCallbackHandler.setSignAssertion(true);
381 samlCallbackHandler.setIssuerCrypto(crypto);
382 samlCallbackHandler.setIssuerName("16c73ab6-b892-458f-abf5-2f875f74882e");
383 samlCallbackHandler.setIssuerPassword("security");
384
385 java.util.Map<String, Object> msgContext = new java.util.TreeMap<>();
386 msgContext.put(WSHandlerConstants.ENABLE_SIGNATURE_CONFIRMATION, "true");
387 msgContext.put(WSHandlerConstants.SAML_CALLBACK_REF, samlCallbackHandler);
388 reqData.setMsgContext(msgContext);
389
390 Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
391 CustomHandler handler = new CustomHandler();
392 HandlerAction action = new HandlerAction(WSConstants.ST_UNSIGNED);
393 handler.send(
394 doc,
395 reqData,
396 Collections.singletonList(action),
397 true
398 );
399 if (LOG.isDebugEnabled()) {
400 LOG.debug("After Signing....");
401 String outputString =
402 XMLUtils.prettyDocumentToString(doc);
403 LOG.debug(outputString);
404 }
405
406
407
408
409 WSHandlerResult results = verify(doc);
410 doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
411 msgContext = (java.util.Map<String, Object>)reqData.getMsgContext();
412 List<WSHandlerResult> receivedResults = new ArrayList<>();
413 receivedResults.add(results);
414 msgContext.put(WSHandlerConstants.RECV_RESULTS, receivedResults);
415 handler.send(
416 doc,
417 reqData,
418 Collections.singletonList(new HandlerAction(WSConstants.NO_SECURITY)),
419 false
420 );
421 String outputString =
422 XMLUtils.prettyDocumentToString(doc);
423 if (LOG.isDebugEnabled()) {
424 LOG.debug("Signature Confirmation response....");
425 LOG.debug(outputString);
426 }
427
428
429
430
431 results = verify(doc);
432 WSSecurityEngineResult scResult =
433 results.getActionResults().get(WSConstants.SC).get(0);
434 assertNotNull(scResult);
435 assertNotNull(scResult.get(WSSecurityEngineResult.TAG_SIGNATURE_CONFIRMATION));
436 handler.signatureConfirmation(reqData, results);
437 }
438
439
440
441
442
443
444
445
446 private WSHandlerResult verify(Document doc) throws Exception {
447 WSHandlerResult results =
448 secEngine.processSecurityHeader(doc, null, callbackHandler, crypto);
449 if (LOG.isDebugEnabled()) {
450 LOG.debug("Verfied and decrypted message:");
451 String outputString =
452 XMLUtils.prettyDocumentToString(doc);
453 LOG.debug(outputString);
454 }
455 return results;
456 }
457
458 }