1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.ws.security.str;
21
22 import org.apache.ws.security.CustomTokenPrincipal;
23 import org.apache.ws.security.SAMLTokenPrincipal;
24 import org.apache.ws.security.WSConstants;
25 import org.apache.ws.security.WSDerivedKeyTokenPrincipal;
26 import org.apache.ws.security.WSDocInfo;
27 import org.apache.ws.security.WSPasswordCallback;
28 import org.apache.ws.security.WSSecurityEngine;
29 import org.apache.ws.security.WSSecurityEngineResult;
30 import org.apache.ws.security.WSSecurityException;
31 import org.apache.ws.security.components.crypto.Crypto;
32 import org.apache.ws.security.handler.RequestData;
33 import org.apache.ws.security.message.token.BinarySecurity;
34 import org.apache.ws.security.message.token.DerivedKeyToken;
35 import org.apache.ws.security.message.token.Reference;
36 import org.apache.ws.security.message.token.SecurityContextToken;
37 import org.apache.ws.security.message.token.SecurityTokenReference;
38 import org.apache.ws.security.message.token.UsernameToken;
39 import org.apache.ws.security.processor.Processor;
40 import org.apache.ws.security.saml.SAMLKeyInfo;
41 import org.apache.ws.security.saml.SAMLUtil;
42 import org.apache.ws.security.saml.ext.AssertionWrapper;
43 import org.apache.ws.security.saml.ext.OpenSAMLUtil;
44 import org.apache.ws.security.util.Base64;
45 import org.apache.ws.security.util.WSSecurityUtil;
46 import org.w3c.dom.Element;
47
48 import java.security.Principal;
49 import java.security.PublicKey;
50 import java.security.cert.CertificateEncodingException;
51 import java.security.cert.X509Certificate;
52 import java.util.Arrays;
53 import java.util.List;
54 import java.util.Map;
55
56 import javax.security.auth.callback.Callback;
57 import javax.xml.namespace.QName;
58
59
60
61
62
63 public class SignatureSTRParser implements STRParser {
64
65
66
67
68 public static final String SIGNATURE_METHOD = "signature_method";
69
70
71
72
73
74 public static final String SECRET_KEY_LENGTH = "secret_key_length";
75
76 private X509Certificate[] certs;
77
78 private byte[] secretKey;
79
80 private PublicKey publicKey;
81
82 private Principal principal;
83
84 private boolean trustedCredential;
85
86 private REFERENCE_TYPE referenceType;
87
88
89
90
91
92
93
94
95
96
97 public void parseSecurityTokenReference(
98 Element strElement,
99 RequestData data,
100 WSDocInfo wsDocInfo,
101 Map<String, Object> parameters
102 ) throws WSSecurityException {
103 boolean bspCompliant = true;
104 Crypto crypto = data.getSigCrypto();
105 if (data.getWssConfig() != null) {
106 bspCompliant = data.getWssConfig().isWsiBSPCompliant();
107 }
108 SecurityTokenReference secRef = new SecurityTokenReference(strElement, bspCompliant);
109
110
111
112
113
114 String uri = null;
115 if (secRef.containsReference()) {
116 uri = secRef.getReference().getURI();
117 if (uri.charAt(0) == '#') {
118 uri = uri.substring(1);
119 }
120 referenceType = REFERENCE_TYPE.DIRECT_REF;
121 } else if (secRef.containsKeyIdentifier()) {
122 uri = secRef.getKeyIdentifierValue();
123 if (SecurityTokenReference.THUMB_URI.equals(secRef.getKeyIdentifierValueType())) {
124 referenceType = REFERENCE_TYPE.THUMBPRINT_SHA1;
125 } else {
126 referenceType = REFERENCE_TYPE.KEY_IDENTIFIER;
127 }
128 }
129
130 WSSecurityEngineResult result = wsDocInfo.getResult(uri);
131 if (result != null) {
132 processPreviousResult(result, secRef, data, parameters, bspCompliant);
133 } else if (secRef.containsReference()) {
134 Reference reference = secRef.getReference();
135
136 secretKey = getSecretKeyFromToken(uri, reference.getValueType(), data);
137 principal = new CustomTokenPrincipal(uri);
138
139 if (secretKey == null) {
140 Element token =
141 secRef.getTokenElement(strElement.getOwnerDocument(), wsDocInfo, data.getCallbackHandler());
142 QName el = new QName(token.getNamespaceURI(), token.getLocalName());
143 if (el.equals(WSSecurityEngine.BINARY_TOKEN)) {
144 Processor proc = data.getWssConfig().getProcessor(WSSecurityEngine.BINARY_TOKEN);
145 List<WSSecurityEngineResult> bstResult =
146 proc.handleToken(token, data, wsDocInfo);
147 BinarySecurity bstToken =
148 (BinarySecurity)bstResult.get(0).get(WSSecurityEngineResult.TAG_BINARY_SECURITY_TOKEN);
149 if (bspCompliant) {
150 BSPEnforcer.checkBinarySecurityBSPCompliance(secRef, bstToken);
151 }
152 certs = (X509Certificate[])bstResult.get(0).get(WSSecurityEngineResult.TAG_X509_CERTIFICATES);
153 secretKey = (byte[])bstResult.get(0).get(WSSecurityEngineResult.TAG_SECRET);
154 principal = (Principal)bstResult.get(0).get(WSSecurityEngineResult.TAG_PRINCIPAL);
155 } else if (el.equals(WSSecurityEngine.SAML_TOKEN)
156 || el.equals(WSSecurityEngine.SAML2_TOKEN)) {
157 Processor proc = data.getWssConfig().getProcessor(WSSecurityEngine.SAML_TOKEN);
158
159
160
161 Element processedToken =
162 secRef.findProcessedTokenElement(
163 strElement.getOwnerDocument(), wsDocInfo,
164 data.getCallbackHandler(), uri, secRef.getReference().getValueType()
165 );
166 AssertionWrapper assertion = null;
167 if (processedToken == null) {
168 List<WSSecurityEngineResult> samlResult =
169 proc.handleToken(token, data, wsDocInfo);
170 assertion =
171 (AssertionWrapper)samlResult.get(0).get(
172 WSSecurityEngineResult.TAG_SAML_ASSERTION
173 );
174 } else {
175 assertion = new AssertionWrapper(processedToken);
176 assertion.parseHOKSubject(data, wsDocInfo);
177 }
178 if (bspCompliant) {
179 BSPEnforcer.checkSamlTokenBSPCompliance(secRef, assertion);
180 }
181 SAMLKeyInfo keyInfo = assertion.getSubjectKeyInfo();
182 X509Certificate[] foundCerts = keyInfo.getCerts();
183 if (foundCerts != null && foundCerts.length > 0) {
184 certs = new X509Certificate[]{foundCerts[0]};
185 }
186 secretKey = keyInfo.getSecret();
187 principal = createPrincipalFromSAML(assertion);
188 } else if (el.equals(WSSecurityEngine.ENCRYPTED_KEY)) {
189 if (bspCompliant) {
190 BSPEnforcer.checkEncryptedKeyBSPCompliance(secRef);
191 }
192 Processor proc = data.getWssConfig().getProcessor(WSSecurityEngine.ENCRYPTED_KEY);
193 List<WSSecurityEngineResult> encrResult =
194 proc.handleToken(token, data, wsDocInfo);
195 secretKey =
196 (byte[])encrResult.get(0).get(WSSecurityEngineResult.TAG_SECRET);
197 principal = new CustomTokenPrincipal(token.getAttribute("Id"));
198 }
199 }
200 } else if (secRef.containsX509Data() || secRef.containsX509IssuerSerial()) {
201 referenceType = REFERENCE_TYPE.ISSUER_SERIAL;
202 X509Certificate[] foundCerts = secRef.getX509IssuerSerial(crypto);
203 if (foundCerts != null && foundCerts.length > 0) {
204 certs = new X509Certificate[]{foundCerts[0]};
205 }
206 } else if (secRef.containsKeyIdentifier()) {
207 if (secRef.getKeyIdentifierValueType().equals(SecurityTokenReference.ENC_KEY_SHA1_URI)) {
208 if (bspCompliant) {
209 BSPEnforcer.checkEncryptedKeyBSPCompliance(secRef);
210 }
211 String id = secRef.getKeyIdentifierValue();
212 secretKey =
213 getSecretKeyFromToken(id, SecurityTokenReference.ENC_KEY_SHA1_URI, data);
214 principal = new CustomTokenPrincipal(id);
215 } else if (WSConstants.WSS_SAML_KI_VALUE_TYPE.equals(secRef.getKeyIdentifierValueType())
216 || WSConstants.WSS_SAML2_KI_VALUE_TYPE.equals(secRef.getKeyIdentifierValueType())) {
217 parseSAMLKeyIdentifier(secRef, wsDocInfo, data, bspCompliant);
218 } else {
219 parseBSTKeyIdentifier(secRef, crypto, wsDocInfo, data, bspCompliant);
220 }
221 } else {
222 throw new WSSecurityException(
223 WSSecurityException.INVALID_SECURITY,
224 "unsupportedKeyInfo",
225 new Object[]{strElement.toString()}
226 );
227 }
228
229 if (certs != null && certs.length > 0 && principal == null) {
230 principal = certs[0].getSubjectX500Principal();
231 }
232 }
233
234
235
236
237
238 public X509Certificate[] getCertificates() {
239 return certs;
240 }
241
242
243
244
245
246 public Principal getPrincipal() {
247 return principal;
248 }
249
250
251
252
253
254 public PublicKey getPublicKey() {
255 return publicKey;
256 }
257
258
259
260
261
262 public byte[] getSecretKey() {
263 return secretKey;
264 }
265
266
267
268
269
270
271
272
273 public boolean isTrustedCredential() {
274 return trustedCredential;
275 }
276
277
278
279
280
281 public REFERENCE_TYPE getCertificatesReferenceType() {
282 return referenceType;
283 }
284
285
286
287
288
289
290 private Principal createPrincipalFromSAML(
291 AssertionWrapper assertion
292 ) {
293 SAMLTokenPrincipal samlPrincipal = new SAMLTokenPrincipal(assertion);
294 String confirmMethod = null;
295 List<String> methods = assertion.getConfirmationMethods();
296 if (methods != null && methods.size() > 0) {
297 confirmMethod = methods.get(0);
298 }
299 if (OpenSAMLUtil.isMethodHolderOfKey(confirmMethod) && assertion.isSigned()) {
300 trustedCredential = true;
301 }
302 return samlPrincipal;
303 }
304
305
306
307
308
309
310
311
312
313 private byte[] getSecretKeyFromToken(
314 String id,
315 String type,
316 RequestData data
317 ) throws WSSecurityException {
318 if (id.charAt(0) == '#') {
319 id = id.substring(1);
320 }
321 WSPasswordCallback pwcb =
322 new WSPasswordCallback(id, null, type, WSPasswordCallback.SECRET_KEY, data);
323 try {
324 Callback[] callbacks = new Callback[]{pwcb};
325 if (data.getCallbackHandler() != null) {
326 data.getCallbackHandler().handle(callbacks);
327 return pwcb.getKey();
328 }
329 } catch (Exception e) {
330 throw new WSSecurityException(
331 WSSecurityException.FAILURE,
332 "noPassword",
333 new Object[] {id},
334 e
335 );
336 }
337
338 return null;
339 }
340
341
342
343
344 private void parseSAMLKeyIdentifier(
345 SecurityTokenReference secRef,
346 WSDocInfo wsDocInfo,
347 RequestData data,
348 boolean bspCompliant
349 ) throws WSSecurityException {
350 String valueType = secRef.getKeyIdentifierValueType();
351 secretKey = getSecretKeyFromToken(secRef.getKeyIdentifierValue(), valueType, data);
352 if (secretKey == null) {
353 AssertionWrapper assertion =
354 SAMLUtil.getAssertionFromKeyIdentifier(
355 secRef, secRef.getElement(), data, wsDocInfo
356 );
357 if (bspCompliant) {
358 BSPEnforcer.checkSamlTokenBSPCompliance(secRef, assertion);
359 }
360 SAMLKeyInfo samlKi =
361 SAMLUtil.getCredentialFromSubject(assertion, data, wsDocInfo, bspCompliant);
362 X509Certificate[] foundCerts = samlKi.getCerts();
363 if (foundCerts != null && foundCerts.length > 0) {
364 certs = new X509Certificate[]{foundCerts[0]};
365 }
366 secretKey = samlKi.getSecret();
367 publicKey = samlKi.getPublicKey();
368 principal = createPrincipalFromSAML(assertion);
369 }
370 }
371
372
373
374
375 private void parseBSTKeyIdentifier(
376 SecurityTokenReference secRef,
377 Crypto crypto,
378 WSDocInfo wsDocInfo,
379 RequestData data,
380 boolean bspCompliant
381 ) throws WSSecurityException {
382 if (bspCompliant) {
383 BSPEnforcer.checkBinarySecurityBSPCompliance(secRef, null);
384 }
385 String valueType = secRef.getKeyIdentifierValueType();
386 if (WSConstants.WSS_KRB_KI_VALUE_TYPE.equals(valueType)) {
387 secretKey =
388 getSecretKeyFromToken(secRef.getKeyIdentifierValue(), valueType, data);
389 if (secretKey == null) {
390 byte[] keyBytes = secRef.getSKIBytes();
391 List<WSSecurityEngineResult> resultsList =
392 wsDocInfo.getResultsByTag(WSConstants.BST);
393 for (WSSecurityEngineResult bstResult : resultsList) {
394 BinarySecurity bstToken =
395 (BinarySecurity)bstResult.get(WSSecurityEngineResult.TAG_BINARY_SECURITY_TOKEN);
396 byte[] tokenDigest = WSSecurityUtil.generateDigest(bstToken.getToken());
397 if (Arrays.equals(tokenDigest, keyBytes)) {
398 secretKey = (byte[])bstResult.get(WSSecurityEngineResult.TAG_SECRET);
399 principal = (Principal)bstResult.get(WSSecurityEngineResult.TAG_PRINCIPAL);
400 break;
401 }
402 }
403 } else {
404 principal = new CustomTokenPrincipal(secRef.getKeyIdentifierValue());
405 }
406 } else {
407 X509Certificate[] foundCerts = secRef.getKeyIdentifier(crypto);
408 if (foundCerts == null) {
409
410 if (SecurityTokenReference.SKI_URI.equals(valueType)) {
411 byte[] skiBytes = secRef.getSKIBytes();
412 List<WSSecurityEngineResult> resultsList =
413 wsDocInfo.getResultsByTag(WSConstants.BST);
414 for (WSSecurityEngineResult bstResult : resultsList) {
415 X509Certificate[] certs =
416 (X509Certificate[])bstResult.get(WSSecurityEngineResult.TAG_X509_CERTIFICATES);
417 if (certs != null
418 && Arrays.equals(skiBytes, crypto.getSKIBytesFromCert(certs[0]))) {
419 principal = (Principal)bstResult.get(WSSecurityEngineResult.TAG_PRINCIPAL);
420 foundCerts = certs;
421 break;
422 }
423 }
424 } else if (SecurityTokenReference.THUMB_URI.equals(valueType)) {
425 String kiValue = secRef.getKeyIdentifierValue();
426 List<WSSecurityEngineResult> resultsList =
427 wsDocInfo.getResultsByTag(WSConstants.BST);
428 for (WSSecurityEngineResult bstResult : resultsList) {
429 X509Certificate[] certs =
430 (X509Certificate[])bstResult.get(WSSecurityEngineResult.TAG_X509_CERTIFICATES);
431 if (certs != null) {
432 try {
433 byte[] digest = WSSecurityUtil.generateDigest(certs[0].getEncoded());
434 if (Arrays.equals(Base64.decode(kiValue), digest)) {
435 principal = (Principal)bstResult.get(WSSecurityEngineResult.TAG_PRINCIPAL);
436 foundCerts = certs;
437 break;
438 }
439 } catch (CertificateEncodingException ex) {
440 throw new WSSecurityException(
441 WSSecurityException.SECURITY_TOKEN_UNAVAILABLE, "encodeError",
442 null, ex
443 );
444 }
445 }
446 }
447 }
448 }
449 if (foundCerts != null) {
450 certs = new X509Certificate[]{foundCerts[0]};
451 }
452 }
453 }
454
455
456
457
458 private void processPreviousResult(
459 WSSecurityEngineResult result,
460 SecurityTokenReference secRef,
461 RequestData data,
462 Map<String, Object> parameters,
463 boolean bspCompliant
464 ) throws WSSecurityException {
465 int action = ((Integer)result.get(WSSecurityEngineResult.TAG_ACTION)).intValue();
466 if (WSConstants.UT_NOPASSWORD == action || WSConstants.UT == action) {
467 if (bspCompliant) {
468 BSPEnforcer.checkUsernameTokenBSPCompliance(secRef);
469 }
470 UsernameToken usernameToken =
471 (UsernameToken)result.get(WSSecurityEngineResult.TAG_USERNAME_TOKEN);
472
473 usernameToken.setRawPassword(data);
474 if (usernameToken.isDerivedKey()) {
475 secretKey = (byte[])result.get(WSSecurityEngineResult.TAG_SECRET);
476 } else {
477 int keyLength = ((Integer)parameters.get(SECRET_KEY_LENGTH)).intValue();
478 secretKey = usernameToken.getSecretKey(keyLength);
479 }
480 principal = usernameToken.createPrincipal();
481 } else if (WSConstants.BST == action) {
482 if (bspCompliant) {
483 BinarySecurity token =
484 (BinarySecurity)result.get(
485 WSSecurityEngineResult.TAG_BINARY_SECURITY_TOKEN
486 );
487 BSPEnforcer.checkBinarySecurityBSPCompliance(secRef, token);
488 }
489 certs =
490 (X509Certificate[])result.get(WSSecurityEngineResult.TAG_X509_CERTIFICATES);
491 secretKey = (byte[])result.get(WSSecurityEngineResult.TAG_SECRET);
492 Boolean validatedToken =
493 (Boolean)result.get(WSSecurityEngineResult.TAG_VALIDATED_TOKEN);
494 if (validatedToken.booleanValue()) {
495 trustedCredential = true;
496 }
497 } else if (WSConstants.ENCR == action) {
498 if (bspCompliant) {
499 BSPEnforcer.checkEncryptedKeyBSPCompliance(secRef);
500 }
501 secretKey = (byte[])result.get(WSSecurityEngineResult.TAG_SECRET);
502 String id = (String)result.get(WSSecurityEngineResult.TAG_ID);
503 principal = new CustomTokenPrincipal(id);
504 } else if (WSConstants.SCT == action) {
505 secretKey = (byte[])result.get(WSSecurityEngineResult.TAG_SECRET);
506 SecurityContextToken sct =
507 (SecurityContextToken)result.get(
508 WSSecurityEngineResult.TAG_SECURITY_CONTEXT_TOKEN
509 );
510 principal = new CustomTokenPrincipal(sct.getIdentifier());
511 } else if (WSConstants.DKT == action) {
512 DerivedKeyToken dkt =
513 (DerivedKeyToken)result.get(WSSecurityEngineResult.TAG_DERIVED_KEY_TOKEN);
514 int keyLength = dkt.getLength();
515 if (keyLength <= 0) {
516 String algorithm = (String)parameters.get(SIGNATURE_METHOD);
517 keyLength = WSSecurityUtil.getKeyLength(algorithm);
518 }
519 byte[] secret = (byte[])result.get(WSSecurityEngineResult.TAG_SECRET);
520 secretKey = dkt.deriveKey(keyLength, secret);
521 principal = dkt.createPrincipal();
522 ((WSDerivedKeyTokenPrincipal)principal).setSecret(secret);
523 } else if (WSConstants.ST_UNSIGNED == action || WSConstants.ST_SIGNED == action) {
524 AssertionWrapper assertion =
525 (AssertionWrapper)result.get(WSSecurityEngineResult.TAG_SAML_ASSERTION);
526 if (bspCompliant) {
527 BSPEnforcer.checkSamlTokenBSPCompliance(secRef, assertion);
528 }
529 SAMLKeyInfo keyInfo = assertion.getSubjectKeyInfo();
530 if (keyInfo == null) {
531 throw new WSSecurityException(
532 WSSecurityException.FAILURE, "invalidSAMLsecurity"
533 );
534 }
535 X509Certificate[] foundCerts = keyInfo.getCerts();
536 if (foundCerts != null) {
537 certs = new X509Certificate[]{foundCerts[0]};
538 }
539 secretKey = keyInfo.getSecret();
540 publicKey = keyInfo.getPublicKey();
541 principal = createPrincipalFromSAML(assertion);
542 }
543 }
544
545
546 }