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.token;
21
22 import org.apache.wss4j.common.util.SOAPUtil;
23 import org.apache.wss4j.dom.WSConstants;
24 import org.apache.wss4j.dom.common.KeystoreCallbackHandler;
25
26 import org.apache.wss4j.dom.engine.WSSConfig;
27 import org.apache.wss4j.dom.engine.WSSecurityEngine;
28 import org.apache.wss4j.dom.engine.WSSecurityEngineResult;
29 import org.apache.wss4j.common.WSEncryptionPart;
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.token.BinarySecurity;
34 import org.apache.wss4j.common.util.KeyUtils;
35 import org.apache.wss4j.common.util.XMLUtils;
36 import org.apache.wss4j.dom.handler.RequestData;
37 import org.apache.wss4j.dom.handler.WSHandlerResult;
38 import org.apache.wss4j.dom.message.WSSecEncrypt;
39 import org.apache.wss4j.dom.message.WSSecSignature;
40 import org.apache.wss4j.dom.message.WSSecHeader;
41 import org.apache.wss4j.dom.message.WSSecTimestamp;
42 import org.apache.wss4j.dom.util.WSSecurityUtil;
43 import org.apache.wss4j.dom.validate.Credential;
44 import org.apache.wss4j.dom.validate.Validator;
45
46 import org.junit.jupiter.api.Test;
47 import org.w3c.dom.Document;
48
49 import javax.crypto.KeyGenerator;
50 import javax.crypto.SecretKey;
51 import javax.security.auth.callback.CallbackHandler;
52 import javax.xml.crypto.dsig.SignatureMethod;
53
54 import java.util.Arrays;
55
56 import static org.junit.jupiter.api.Assertions.assertNotNull;
57 import static org.junit.jupiter.api.Assertions.assertTrue;
58 import static org.junit.jupiter.api.Assertions.fail;
59
60
61
62
63 public class BSTKerberosTest {
64 private static final org.slf4j.Logger LOG =
65 org.slf4j.LoggerFactory.getLogger(BSTKerberosTest.class);
66 private static final String AP_REQ = WSConstants.WSS_GSS_KRB_V5_AP_REQ;
67 private static final String BASE64_NS =
68 WSConstants.SOAPMESSAGE_NS + "#Base64Binary";
69 private WSSecurityEngine secEngine = new WSSecurityEngine();
70 private CallbackHandler callbackHandler = new KeystoreCallbackHandler();
71 private Crypto crypto;
72
73 public BSTKerberosTest() throws Exception {
74 WSSConfig.init();
75 crypto = CryptoFactory.getInstance();
76 }
77
78
79
80
81 @Test
82 public void testCreateBinarySecurityToken() throws Exception {
83 Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
84
85 WSSecHeader secHeader = new WSSecHeader(doc);
86 secHeader.insertSecurityHeader();
87
88 BinarySecurity bst = new BinarySecurity(doc);
89 bst.setValueType(AP_REQ);
90 bst.setEncodingType(BASE64_NS);
91 bst.setToken("12345678".getBytes());
92 WSSecurityUtil.prependChildElement(secHeader.getSecurityHeaderElement(), bst.getElement());
93
94 if (LOG.isDebugEnabled()) {
95 String outputString =
96 XMLUtils.prettyDocumentToString(doc);
97 LOG.debug(outputString);
98 }
99
100 assertTrue(AP_REQ.equals(bst.getValueType()));
101 assertTrue(BASE64_NS.equals(bst.getEncodingType()));
102 assertNotNull(bst.getToken());
103 }
104
105
106
107
108
109 @Test
110 public void testSignBST() throws Exception {
111 Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
112
113 WSSecHeader secHeader = new WSSecHeader(doc);
114 secHeader.insertSecurityHeader();
115
116 BinarySecurity bst = new BinarySecurity(doc);
117 bst.setValueType(AP_REQ);
118 bst.setEncodingType(BASE64_NS);
119 bst.setToken("12345678".getBytes());
120 bst.setID("Id-" + bst.hashCode());
121 WSSecurityUtil.prependChildElement(secHeader.getSecurityHeaderElement(), bst.getElement());
122
123 WSSecSignature sign = new WSSecSignature(secHeader);
124 sign.setUserInfo("16c73ab6-b892-458f-abf5-2f875f74882e", "security");
125 sign.setKeyIdentifierType(WSConstants.ISSUER_SERIAL);
126
127 WSEncryptionPart encP =
128 new WSEncryptionPart(bst.getID());
129 sign.getParts().add(encP);
130
131 Document signedDoc = sign.build(crypto);
132
133 if (LOG.isDebugEnabled()) {
134 String outputString =
135 XMLUtils.prettyDocumentToString(signedDoc);
136 LOG.debug(outputString);
137 }
138
139 verify(signedDoc);
140 }
141
142
143
144
145 @Test
146 public void testSignBSTTimestamp() throws Exception {
147 Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
148
149 WSSecHeader secHeader = new WSSecHeader(doc);
150 secHeader.insertSecurityHeader();
151
152 BinarySecurity bst = new BinarySecurity(doc);
153 bst.setValueType(AP_REQ);
154 bst.setEncodingType(BASE64_NS);
155 bst.setToken("12345678".getBytes());
156 bst.setID("Id-" + bst.hashCode());
157 WSSecurityUtil.prependChildElement(secHeader.getSecurityHeaderElement(), bst.getElement());
158
159 WSSecTimestamp timestamp = new WSSecTimestamp(secHeader);
160 timestamp.setTimeToLive(600);
161 timestamp.build();
162
163 WSSecSignature sign = new WSSecSignature(secHeader);
164 sign.setUserInfo("16c73ab6-b892-458f-abf5-2f875f74882e", "security");
165 sign.setKeyIdentifierType(WSConstants.ISSUER_SERIAL);
166
167 sign.getParts().add(new WSEncryptionPart(bst.getID()));
168 sign.getParts().add(new WSEncryptionPart(timestamp.getId()));
169
170 Document signedDoc = sign.build(crypto);
171
172 if (LOG.isDebugEnabled()) {
173 String outputString =
174 XMLUtils.prettyDocumentToString(signedDoc);
175 LOG.debug(outputString);
176 }
177
178 verify(signedDoc);
179 }
180
181
182
183
184 @Test
185 public void testProcessToken() throws Exception {
186 Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
187
188 WSSecHeader secHeader = new WSSecHeader(doc);
189 secHeader.insertSecurityHeader();
190
191 BinarySecurity bst = new BinarySecurity(doc);
192 bst.setValueType(AP_REQ);
193 bst.setEncodingType(BASE64_NS);
194 bst.setToken("12345678".getBytes());
195 WSSecurityUtil.prependChildElement(secHeader.getSecurityHeaderElement(), bst.getElement());
196
197 if (LOG.isDebugEnabled()) {
198 String outputString =
199 XMLUtils.prettyDocumentToString(doc);
200 LOG.debug(outputString);
201 }
202
203 WSHandlerResult results = verify(doc);
204 WSSecurityEngineResult actionResult =
205 results.getActionResults().get(WSConstants.BST).get(0);
206 BinarySecurity token =
207 (BinarySecurity)actionResult.get(WSSecurityEngineResult.TAG_BINARY_SECURITY_TOKEN);
208 assertNotNull(token);
209
210 assertTrue(AP_REQ.equals(token.getValueType()));
211 assertTrue(BASE64_NS.equals(token.getEncodingType()));
212 assertNotNull(token.getToken());
213 }
214
215
216
217
218 @Test
219 public void testProcessTokenCustomValidator() throws Exception {
220 Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
221
222 WSSecHeader secHeader = new WSSecHeader(doc);
223 secHeader.insertSecurityHeader();
224
225 BinarySecurity bst = new BinarySecurity(doc);
226 bst.setValueType(AP_REQ);
227 bst.setEncodingType(BASE64_NS);
228 bst.setToken("12345678".getBytes());
229 WSSecurityUtil.prependChildElement(secHeader.getSecurityHeaderElement(), bst.getElement());
230
231 if (LOG.isDebugEnabled()) {
232 String outputString =
233 XMLUtils.prettyDocumentToString(doc);
234 LOG.debug(outputString);
235 }
236
237 WSSecurityEngine customEngine = new WSSecurityEngine();
238 WSSConfig wssConfig = WSSConfig.getNewInstance();
239 wssConfig.setValidator(WSConstants.BINARY_TOKEN, new KerberosValidator());
240 customEngine.setWssConfig(wssConfig);
241 customEngine.processSecurityHeader(doc, null, callbackHandler, crypto);
242
243 bst.setToken("12345679".getBytes());
244 try {
245 customEngine.processSecurityHeader(doc, null, callbackHandler, crypto);
246 fail("Failure expected on a bad token");
247 } catch (WSSecurityException ex) {
248 assertTrue(ex.getErrorCode() == WSSecurityException.ErrorCode.FAILED_AUTHENTICATION);
249 }
250 }
251
252
253
254
255 @Test
256 public void testKerberosSignatureDRCreation() throws Exception {
257 Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
258
259 WSSecHeader secHeader = new WSSecHeader(doc);
260 secHeader.insertSecurityHeader();
261
262 BinarySecurity bst = new BinarySecurity(doc);
263 bst.setValueType(AP_REQ);
264 bst.setEncodingType(BASE64_NS);
265
266 KeyGenerator keyGen = KeyGenerator.getInstance("AES");
267 keyGen.init(128);
268 SecretKey key = keyGen.generateKey();
269 byte[] keyData = key.getEncoded();
270
271 bst.setToken(keyData);
272 bst.setID("Id-" + bst.hashCode());
273 WSSecurityUtil.prependChildElement(secHeader.getSecurityHeaderElement(), bst.getElement());
274
275 WSSecSignature sign = new WSSecSignature(secHeader);
276 sign.setSignatureAlgorithm(SignatureMethod.HMAC_SHA1);
277 sign.setKeyIdentifierType(WSConstants.CUSTOM_SYMM_SIGNING);
278 sign.setCustomTokenValueType(AP_REQ);
279 sign.setCustomTokenId(bst.getID());
280 sign.setSecretKey(keyData);
281
282 Document signedDoc = sign.build(crypto);
283
284 if (LOG.isDebugEnabled()) {
285 String outputString =
286 XMLUtils.prettyDocumentToString(signedDoc);
287 LOG.debug(outputString);
288 }
289 }
290
291
292
293
294 @Test
295 public void testKerberosSignatureKICreation() throws Exception {
296 Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
297
298 WSSecHeader secHeader = new WSSecHeader(doc);
299 secHeader.insertSecurityHeader();
300
301 BinarySecurity bst = new BinarySecurity(doc);
302 bst.setValueType(AP_REQ);
303 bst.setEncodingType(BASE64_NS);
304
305 KeyGenerator keyGen = KeyGenerator.getInstance("AES");
306 keyGen.init(128);
307 SecretKey key = keyGen.generateKey();
308 byte[] keyData = key.getEncoded();
309
310 bst.setToken(keyData);
311 bst.setID("Id-" + bst.hashCode());
312 WSSecurityUtil.prependChildElement(secHeader.getSecurityHeaderElement(), bst.getElement());
313
314 WSSecSignature sign = new WSSecSignature(secHeader);
315 sign.setSignatureAlgorithm(SignatureMethod.HMAC_SHA1);
316 sign.setKeyIdentifierType(WSConstants.CUSTOM_KEY_IDENTIFIER);
317 sign.setCustomTokenValueType(WSConstants.WSS_KRB_KI_VALUE_TYPE);
318
319 byte[] digestBytes = KeyUtils.generateDigest(keyData);
320 sign.setCustomTokenId(org.apache.xml.security.utils.XMLUtils.encodeToString(digestBytes));
321 sign.setSecretKey(keyData);
322
323 Document signedDoc = sign.build(crypto);
324
325 if (LOG.isDebugEnabled()) {
326 String outputString =
327 XMLUtils.prettyDocumentToString(signedDoc);
328 LOG.debug(outputString);
329 }
330 }
331
332
333
334
335 @Test
336 public void testKerberosEncryptionDRCreation() throws Exception {
337 Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
338
339 WSSecHeader secHeader = new WSSecHeader(doc);
340 secHeader.insertSecurityHeader();
341
342 BinarySecurity bst = new BinarySecurity(doc);
343 bst.setValueType(AP_REQ);
344 bst.setEncodingType(BASE64_NS);
345
346 KeyGenerator keyGen = KeyGenerator.getInstance("AES");
347 keyGen.init(128);
348 SecretKey key = keyGen.generateKey();
349 byte[] keyData = key.getEncoded();
350
351 bst.setToken(keyData);
352 bst.setID("Id-" + bst.hashCode());
353 WSSecurityUtil.prependChildElement(secHeader.getSecurityHeaderElement(), bst.getElement());
354
355 WSSecEncrypt builder = new WSSecEncrypt(secHeader);
356 builder.setSymmetricEncAlgorithm(WSConstants.AES_128);
357 builder.setEncryptSymmKey(false);
358 builder.setCustomReferenceValue(AP_REQ);
359 builder.setEncKeyId(bst.getID());
360 Document encryptedDoc = builder.build(crypto, key);
361
362 if (LOG.isDebugEnabled()) {
363 String outputString =
364 XMLUtils.prettyDocumentToString(encryptedDoc);
365 LOG.debug(outputString);
366 }
367 }
368
369
370
371
372 @Test
373 public void testKerberosEncryptionKICreation() throws Exception {
374 Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
375
376 WSSecHeader secHeader = new WSSecHeader(doc);
377 secHeader.insertSecurityHeader();
378
379 BinarySecurity bst = new BinarySecurity(doc);
380 bst.setValueType(AP_REQ);
381 bst.setEncodingType(BASE64_NS);
382
383 KeyGenerator keyGen = KeyGenerator.getInstance("AES");
384 keyGen.init(128);
385 SecretKey key = keyGen.generateKey();
386 byte[] keyData = key.getEncoded();
387
388 bst.setToken(keyData);
389 bst.setID("Id-" + bst.hashCode());
390 WSSecurityUtil.prependChildElement(secHeader.getSecurityHeaderElement(), bst.getElement());
391
392 WSSecEncrypt builder = new WSSecEncrypt(secHeader);
393 builder.setSymmetricEncAlgorithm(WSConstants.AES_128);
394 builder.setEncryptSymmKey(false);
395 builder.setCustomReferenceValue(WSConstants.WSS_KRB_KI_VALUE_TYPE);
396
397 byte[] digestBytes = KeyUtils.generateDigest(keyData);
398 builder.setEncKeyId(org.apache.xml.security.utils.XMLUtils.encodeToString(digestBytes));
399
400 Document encryptedDoc = builder.build(crypto, key);
401
402 if (LOG.isDebugEnabled()) {
403 String outputString =
404 XMLUtils.prettyDocumentToString(encryptedDoc);
405 LOG.debug(outputString);
406 }
407 }
408
409
410
411
412
413
414
415
416
417
418 private WSHandlerResult verify(Document doc) throws Exception {
419 WSHandlerResult results =
420 secEngine.processSecurityHeader(doc, null, callbackHandler, crypto);
421 if (LOG.isDebugEnabled()) {
422 LOG.debug("Verfied and decrypted message:");
423 String outputString =
424 XMLUtils.prettyDocumentToString(doc);
425 LOG.debug(outputString);
426 }
427 return results;
428 }
429
430
431
432
433
434 private static class KerberosValidator implements Validator {
435
436 public Credential validate(Credential credential, RequestData data) throws WSSecurityException {
437 BinarySecurity token = credential.getBinarySecurityToken();
438 if (token == null) {
439 throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE);
440 }
441
442 if (!AP_REQ.equals(token.getValueType())) {
443 throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE);
444 }
445
446 byte[] tokenBytes = token.getToken();
447 if (!Arrays.equals(tokenBytes, "12345678".getBytes())) {
448 throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_AUTHENTICATION);
449 }
450 return credential;
451 }
452
453 }
454
455 }