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 org.apache.wss4j.common.util.SOAPUtil;
23 import org.apache.wss4j.dom.WSConstants;
24 import org.apache.wss4j.dom.common.CustomHandler;
25
26 import org.apache.wss4j.dom.common.UsernamePasswordCallbackHandler;
27 import org.apache.wss4j.dom.engine.WSSConfig;
28 import org.apache.wss4j.dom.engine.WSSecurityEngine;
29 import org.apache.wss4j.dom.engine.WSSecurityEngineResult;
30 import org.apache.wss4j.common.crypto.Crypto;
31 import org.apache.wss4j.common.crypto.CryptoFactory;
32 import org.apache.wss4j.common.ext.WSSecurityException;
33 import org.apache.wss4j.common.util.UsernameTokenUtil;
34 import org.apache.wss4j.common.util.XMLUtils;
35 import org.apache.wss4j.dom.handler.HandlerAction;
36 import org.apache.wss4j.dom.handler.RequestData;
37 import org.apache.wss4j.dom.handler.WSHandlerConstants;
38 import org.apache.wss4j.dom.handler.WSHandlerResult;
39
40 import org.junit.jupiter.api.Test;
41 import org.w3c.dom.Document;
42
43 import javax.security.auth.callback.CallbackHandler;
44
45 import java.util.Collections;
46
47 import static org.junit.jupiter.api.Assertions.assertFalse;
48 import static org.junit.jupiter.api.Assertions.assertTrue;
49 import static org.junit.jupiter.api.Assertions.fail;
50
51
52
53
54
55
56
57
58
59 public class UTSignatureTest {
60 private static final org.slf4j.Logger LOG =
61 org.slf4j.LoggerFactory.getLogger(UTSignatureTest.class);
62 private CallbackHandler callbackHandler = new UsernamePasswordCallbackHandler();
63 private Crypto crypto;
64
65 public UTSignatureTest() throws Exception {
66 crypto = CryptoFactory.getInstance();
67 }
68
69
70
71
72 @Test
73 public void testSignature() throws Exception {
74 Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
75 WSSecHeader secHeader = new WSSecHeader(doc);
76 secHeader.insertSecurityHeader();
77
78 WSSecUsernameToken builder = new WSSecUsernameToken(secHeader);
79 builder.setUserInfo("bob", "security");
80 builder.addDerivedKey(1000);
81 byte[] salt = UsernameTokenUtil.generateSalt(true);
82 builder.prepare(salt);
83
84 WSSecSignature sign = new WSSecSignature(secHeader);
85 sign.setCustomTokenValueType(WSConstants.USERNAMETOKEN_NS + "#UsernameToken");
86 sign.setCustomTokenId(builder.getId());
87 sign.setSecretKey(builder.getDerivedKey(salt));
88 sign.setKeyIdentifierType(WSConstants.CUSTOM_SYMM_SIGNING);
89 sign.setSignatureAlgorithm(WSConstants.HMAC_SHA1);
90
91 Document signedDoc = sign.build(null);
92 builder.prependToHeader();
93
94 String outputString =
95 XMLUtils.prettyDocumentToString(signedDoc);
96 assertTrue(outputString.contains("wsse:Username"));
97 assertFalse(outputString.contains("wsse:Password"));
98 assertTrue(outputString.contains("wsse11:Salt"));
99 assertTrue(outputString.contains("wsse11:Iteration"));
100 if (LOG.isDebugEnabled()) {
101 LOG.debug(outputString);
102 }
103
104 WSHandlerResult results = verify(signedDoc);
105 WSSecurityEngineResult actionResult =
106 results.getActionResults().get(WSConstants.UT_SIGN).get(0);
107 java.security.Principal principal =
108 (java.security.Principal) actionResult.get(WSSecurityEngineResult.TAG_PRINCIPAL);
109 assertTrue(principal.getName().contains("bob"));
110
111 try {
112 verify(signedDoc, false);
113 fail("Failure expected on deriving keys from a UsernameToken not allowed");
114 } catch (WSSecurityException ex) {
115 assertTrue(ex.getErrorCode() == WSSecurityException.ErrorCode.FAILED_AUTHENTICATION);
116 }
117 }
118
119
120
121
122
123
124 @Test
125 public void testBadUserSignature() throws Exception {
126 Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
127 WSSecHeader secHeader = new WSSecHeader(doc);
128 secHeader.insertSecurityHeader();
129
130 WSSecUsernameToken builder = new WSSecUsernameToken(secHeader);
131 builder.setUserInfo("colm", "security");
132 builder.addDerivedKey(1000);
133 byte[] salt = UsernameTokenUtil.generateSalt(true);
134 builder.prepare(salt);
135
136 WSSecSignature sign = new WSSecSignature(secHeader);
137 sign.setCustomTokenValueType(WSConstants.USERNAMETOKEN_NS + "#UsernameToken");
138 sign.setCustomTokenId(builder.getId());
139 sign.setSecretKey(builder.getDerivedKey(salt));
140 sign.setKeyIdentifierType(WSConstants.CUSTOM_SYMM_SIGNING);
141 sign.setSignatureAlgorithm(WSConstants.HMAC_SHA1);
142
143 Document signedDoc = sign.build(null);
144 builder.prependToHeader();
145
146 String outputString =
147 XMLUtils.prettyDocumentToString(signedDoc);
148 if (LOG.isDebugEnabled()) {
149 LOG.debug(outputString);
150 }
151
152 try {
153 verify(signedDoc);
154 fail("Failure expected on a bad derived signature");
155 } catch (WSSecurityException ex) {
156 assertTrue(ex.getErrorCode() == WSSecurityException.ErrorCode.FAILED_AUTHENTICATION);
157
158 }
159 }
160
161
162
163
164 @Test
165 public void testHandlerSignature() throws Exception {
166
167 final WSSConfig cfg = WSSConfig.getNewInstance();
168 RequestData reqData = new RequestData();
169 reqData.setWssConfig(cfg);
170 java.util.Map<String, Object> messageContext = new java.util.TreeMap<>();
171 messageContext.put(WSHandlerConstants.PW_CALLBACK_REF, callbackHandler);
172 reqData.setMsgContext(messageContext);
173 reqData.setUsername("bob");
174
175 Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
176 CustomHandler handler = new CustomHandler();
177 HandlerAction action = new HandlerAction(WSConstants.UT_SIGN);
178 handler.send(
179 doc,
180 reqData,
181 Collections.singletonList(action),
182 true
183 );
184
185 String outputString =
186 XMLUtils.prettyDocumentToString(doc);
187 assertTrue(outputString.contains("wsse:Username"));
188 assertFalse(outputString.contains("wsse:Password"));
189 assertTrue(outputString.contains("wsse11:Salt"));
190 assertTrue(outputString.contains("wsse11:Iteration"));
191 if (LOG.isDebugEnabled()) {
192 LOG.debug(outputString);
193 }
194
195 WSHandlerResult results = verify(doc);
196 WSSecurityEngineResult actionResult =
197 results.getActionResults().get(WSConstants.UT_SIGN).get(0);
198 java.security.Principal principal =
199 (java.security.Principal) actionResult.get(WSSecurityEngineResult.TAG_PRINCIPAL);
200 assertTrue(principal.getName().contains("bob"));
201 }
202
203
204
205
206 @Test
207 public void testHandlerSignatureIterations() throws Exception {
208
209 final WSSConfig cfg = WSSConfig.getNewInstance();
210 RequestData reqData = new RequestData();
211 reqData.setWssConfig(cfg);
212 java.util.Map<String, Object> messageContext = new java.util.TreeMap<>();
213 messageContext.put(WSHandlerConstants.PW_CALLBACK_REF, callbackHandler);
214 messageContext.put(WSHandlerConstants.DERIVED_KEY_ITERATIONS, "1234");
215 reqData.setMsgContext(messageContext);
216 reqData.setUsername("bob");
217
218 Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
219 CustomHandler handler = new CustomHandler();
220 HandlerAction action = new HandlerAction(WSConstants.UT_SIGN);
221 handler.send(
222 doc,
223 reqData,
224 Collections.singletonList(action),
225 true
226 );
227
228 String outputString =
229 XMLUtils.prettyDocumentToString(doc);
230 assertTrue(outputString.contains("wsse:Username"));
231 assertFalse(outputString.contains("wsse:Password"));
232 assertTrue(outputString.contains("wsse11:Salt"));
233 assertTrue(outputString.contains("wsse11:Iteration"));
234 assertTrue(outputString.contains("1234"));
235 if (LOG.isDebugEnabled()) {
236 LOG.debug(outputString);
237 }
238
239 WSHandlerResult results = verify(doc);
240 WSSecurityEngineResult actionResult =
241 results.getActionResults().get(WSConstants.UT_SIGN).get(0);
242 java.security.Principal principal =
243 (java.security.Principal) actionResult.get(WSSecurityEngineResult.TAG_PRINCIPAL);
244 assertTrue(principal.getName().contains("bob"));
245 }
246
247
248
249
250
251
252
253 private WSHandlerResult verify(Document doc) throws Exception {
254 return verify(doc, true);
255 }
256
257 private WSHandlerResult verify(
258 Document doc,
259 boolean allowUsernameTokenDerivedKeys
260 ) throws Exception {
261 WSSecurityEngine secEngine = new WSSecurityEngine();
262
263 RequestData requestData = new RequestData();
264 requestData.setAllowUsernameTokenNoPassword(allowUsernameTokenDerivedKeys);
265 requestData.setCallbackHandler(callbackHandler);
266 requestData.setSigVerCrypto(crypto);
267 requestData.setDecCrypto(crypto);
268
269 return secEngine.processSecurityHeader(doc, requestData);
270 }
271
272 }