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.str;
21
22 import java.security.Principal;
23 import java.security.cert.CertificateEncodingException;
24 import java.security.cert.X509Certificate;
25 import java.util.Arrays;
26 import java.util.List;
27
28 import javax.xml.namespace.QName;
29
30 import org.apache.wss4j.common.crypto.Crypto;
31 import org.apache.wss4j.common.ext.WSPasswordCallback;
32 import org.apache.wss4j.common.ext.WSSecurityException;
33 import org.apache.wss4j.common.principal.CustomTokenPrincipal;
34 import org.apache.wss4j.common.principal.SAMLTokenPrincipalImpl;
35 import org.apache.wss4j.common.principal.WSDerivedKeyTokenPrincipal;
36 import org.apache.wss4j.common.saml.OpenSAMLUtil;
37 import org.apache.wss4j.common.saml.SAMLKeyInfo;
38 import org.apache.wss4j.common.saml.SAMLUtil;
39 import org.apache.wss4j.common.saml.SamlAssertionWrapper;
40 import org.apache.wss4j.common.token.BinarySecurity;
41 import org.apache.wss4j.common.token.Reference;
42 import org.apache.wss4j.common.token.SecurityTokenReference;
43 import org.apache.wss4j.common.util.KeyUtils;
44 import org.apache.wss4j.common.util.XMLUtils;
45 import org.apache.wss4j.dom.WSConstants;
46 import org.apache.wss4j.dom.WSDocInfo;
47 import org.apache.wss4j.dom.engine.WSSecurityEngineResult;
48 import org.apache.wss4j.dom.handler.RequestData;
49 import org.apache.wss4j.dom.message.token.DerivedKeyToken;
50 import org.apache.wss4j.dom.message.token.SecurityContextToken;
51 import org.apache.wss4j.dom.message.token.UsernameToken;
52 import org.apache.wss4j.dom.processor.Processor;
53 import org.apache.wss4j.dom.saml.WSSSAMLKeyInfoProcessor;
54 import org.w3c.dom.Element;
55
56
57
58
59
60 public class SignatureSTRParser implements STRParser {
61
62
63
64
65
66
67
68
69 public STRParserResult parseSecurityTokenReference(STRParserParameters parameters) throws WSSecurityException {
70
71 if (parameters == null || parameters.getData() == null || parameters.getData().getWsDocInfo() == null
72 || parameters.getStrElement() == null) {
73 throw new WSSecurityException(
74 WSSecurityException.ErrorCode.FAILURE, "invalidSTRParserParameter"
75 );
76 }
77
78 SecurityTokenReference secRef =
79 new SecurityTokenReference(parameters.getStrElement(), parameters.getData().getBSPEnforcer());
80
81
82
83
84
85 String uri = null;
86 if (secRef.getReference() != null) {
87 uri = secRef.getReference().getURI();
88 uri = XMLUtils.getIDFromReference(uri);
89 } else if (secRef.containsKeyIdentifier()) {
90 uri = secRef.getKeyIdentifierValue();
91 }
92
93 WSSecurityEngineResult result = parameters.getData().getWsDocInfo().getResult(uri);
94 if (result != null) {
95 return processPreviousResult(result, secRef, parameters);
96 }
97
98 return processSTR(secRef, uri, parameters);
99 }
100
101
102
103
104
105
106
107
108
109 private Principal createPrincipalFromSAML(
110 SamlAssertionWrapper samlAssertion, STRParserResult parserResult, byte[] secretKey
111 ) throws WSSecurityException {
112 SAMLTokenPrincipalImpl samlPrincipal = new SAMLTokenPrincipalImpl(samlAssertion);
113 String confirmMethod = null;
114 List<String> methods = samlAssertion.getConfirmationMethods();
115 if (methods != null && !methods.isEmpty()) {
116 confirmMethod = methods.get(0);
117 }
118 boolean holderOfKey = OpenSAMLUtil.isMethodHolderOfKey(confirmMethod);
119 if (holderOfKey && samlAssertion.isSigned()) {
120 parserResult.setTrustedCredential(true);
121 } else if (!holderOfKey && secretKey != null && secretKey.length > 0) {
122
123
124
125
126
127 throw new WSSecurityException(
128 WSSecurityException.ErrorCode.FAILED_CHECK, "invalidSAMLsecurity"
129 );
130 }
131 return samlPrincipal;
132 }
133
134
135
136
137 private void parseSAMLKeyIdentifier(
138 SecurityTokenReference secRef,
139 RequestData data,
140 STRParserResult parserResult
141 ) throws WSSecurityException {
142 String valueType = secRef.getKeyIdentifierValueType();
143 byte[] secretKey = STRParserUtil.getSecretKeyFromToken(secRef.getKeyIdentifierValue(), valueType,
144 WSPasswordCallback.SECRET_KEY, data);
145 if (secretKey == null || secretKey.length == 0) {
146 SamlAssertionWrapper samlAssertion =
147 STRParserUtil.getAssertionFromKeyIdentifier(
148 secRef, secRef.getElement(), data
149 );
150 STRParserUtil.checkSamlTokenBSPCompliance(secRef, samlAssertion, data.getBSPEnforcer());
151
152 SAMLKeyInfo samlKi =
153 SAMLUtil.getCredentialFromSubject(samlAssertion,
154 new WSSSAMLKeyInfoProcessor(data), data.getSigVerCrypto());
155 X509Certificate[] foundCerts = samlKi.getCerts();
156 if (foundCerts != null && foundCerts.length > 0) {
157 parserResult.setCerts(new X509Certificate[]{foundCerts[0]});
158 }
159 secretKey = samlKi.getSecret();
160 parserResult.setPublicKey(samlKi.getPublicKey());
161 parserResult.setPrincipal(createPrincipalFromSAML(samlAssertion, parserResult, secretKey));
162 }
163 parserResult.setSecretKey(secretKey);
164 }
165
166
167
168
169 private void parseBSTKeyIdentifier(
170 SecurityTokenReference secRef,
171 Crypto crypto,
172 RequestData data,
173 STRParserResult parserResult
174 ) throws WSSecurityException {
175 STRParserUtil.checkBinarySecurityBSPCompliance(secRef, null, data.getBSPEnforcer());
176
177 String valueType = secRef.getKeyIdentifierValueType();
178 if (WSConstants.WSS_KRB_KI_VALUE_TYPE.equals(valueType)) {
179 byte[] secretKey =
180 STRParserUtil.getSecretKeyFromToken(secRef.getKeyIdentifierValue(), valueType,
181 WSPasswordCallback.SECRET_KEY, data);
182 if (secretKey == null || secretKey.length == 0) {
183 byte[] keyBytes = secRef.getSKIBytes();
184 List<WSSecurityEngineResult> resultsList =
185 data.getWsDocInfo().getResultsByTag(WSConstants.BST);
186 for (WSSecurityEngineResult bstResult : resultsList) {
187 BinarySecurity bstToken =
188 (BinarySecurity)bstResult.get(WSSecurityEngineResult.TAG_BINARY_SECURITY_TOKEN);
189 byte[] tokenDigest = KeyUtils.generateDigest(bstToken.getToken());
190 if (Arrays.equals(tokenDigest, keyBytes)) {
191 secretKey = (byte[])bstResult.get(WSSecurityEngineResult.TAG_SECRET);
192 parserResult.setPrincipal((Principal)bstResult.get(WSSecurityEngineResult.TAG_PRINCIPAL));
193 break;
194 }
195 }
196 } else {
197 parserResult.setPrincipal(new CustomTokenPrincipal(secRef.getKeyIdentifierValue()));
198 }
199 parserResult.setSecretKey(secretKey);
200 } else {
201 X509Certificate[] foundCerts = secRef.getKeyIdentifier(crypto);
202 if (foundCerts == null || foundCerts.length == 0) {
203
204 if (SecurityTokenReference.SKI_URI.equals(valueType)) {
205 byte[] skiBytes = secRef.getSKIBytes();
206 List<WSSecurityEngineResult> resultsList =
207 data.getWsDocInfo().getResultsByTag(WSConstants.BST);
208 for (WSSecurityEngineResult bstResult : resultsList) {
209 X509Certificate[] certs =
210 (X509Certificate[])bstResult.get(WSSecurityEngineResult.TAG_X509_CERTIFICATES);
211 if (certs != null && certs.length > 0
212 && Arrays.equals(skiBytes, crypto.getSKIBytesFromCert(certs[0]))) {
213 parserResult.setPrincipal((Principal)bstResult.get(WSSecurityEngineResult.TAG_PRINCIPAL));
214 foundCerts = certs;
215 break;
216 }
217 }
218 } else if (SecurityTokenReference.THUMB_URI.equals(valueType)) {
219 String kiValue = secRef.getKeyIdentifierValue();
220 List<WSSecurityEngineResult> resultsList =
221 data.getWsDocInfo().getResultsByTag(WSConstants.BST);
222 for (WSSecurityEngineResult bstResult : resultsList) {
223 X509Certificate[] certs =
224 (X509Certificate[])bstResult.get(WSSecurityEngineResult.TAG_X509_CERTIFICATES);
225 if (certs != null && certs.length > 0) {
226 try {
227 byte[] digest = KeyUtils.generateDigest(certs[0].getEncoded());
228 if (Arrays.equals(org.apache.xml.security.utils.XMLUtils.decode(kiValue), digest)) {
229 parserResult.setPrincipal((Principal)bstResult.get(WSSecurityEngineResult.TAG_PRINCIPAL));
230 foundCerts = certs;
231 break;
232 }
233 } catch (CertificateEncodingException ex) {
234 throw new WSSecurityException(
235 WSSecurityException.ErrorCode.SECURITY_TOKEN_UNAVAILABLE, ex, "encodeError"
236 );
237 }
238 }
239 }
240 }
241 }
242 if (foundCerts != null && foundCerts.length > 0) {
243 parserResult.setCerts(new X509Certificate[]{foundCerts[0]});
244 }
245 }
246 }
247
248
249
250
251 private STRParserResult processPreviousResult(
252 WSSecurityEngineResult result,
253 SecurityTokenReference secRef,
254 STRParserParameters parameters
255 ) throws WSSecurityException {
256
257 STRParserResult parserResult = new STRParserResult();
258 RequestData data = parameters.getData();
259
260 Integer action = (Integer) result.get(WSSecurityEngineResult.TAG_ACTION);
261 if (action != null
262 && (WSConstants.UT_NOPASSWORD == action.intValue() || WSConstants.UT == action.intValue())) {
263 STRParserUtil.checkUsernameTokenBSPCompliance(secRef, data.getBSPEnforcer());
264
265 UsernameToken usernameToken =
266 (UsernameToken)result.get(WSSecurityEngineResult.TAG_USERNAME_TOKEN);
267
268 parserResult.setSecretKey((byte[])result.get(WSSecurityEngineResult.TAG_SECRET));
269
270 parserResult.setPrincipal(usernameToken.createPrincipal());
271 } else if (action != null && WSConstants.BST == action.intValue()) {
272 BinarySecurity token =
273 (BinarySecurity)result.get(
274 WSSecurityEngineResult.TAG_BINARY_SECURITY_TOKEN
275 );
276 STRParserUtil.checkBinarySecurityBSPCompliance(secRef, token, data.getBSPEnforcer());
277
278 parserResult.setCerts(
279 (X509Certificate[])result.get(WSSecurityEngineResult.TAG_X509_CERTIFICATES));
280 parserResult.setSecretKey((byte[])result.get(WSSecurityEngineResult.TAG_SECRET));
281 Boolean validatedToken =
282 (Boolean)result.get(WSSecurityEngineResult.TAG_VALIDATED_TOKEN);
283 if (validatedToken) {
284 parserResult.setTrustedCredential(true);
285 }
286 } else if (action != null && WSConstants.ENCR == action.intValue()) {
287 STRParserUtil.checkEncryptedKeyBSPCompliance(secRef, data.getBSPEnforcer());
288
289 parserResult.setSecretKey((byte[])result.get(WSSecurityEngineResult.TAG_SECRET));
290 String id = (String)result.get(WSSecurityEngineResult.TAG_ID);
291 parserResult.setPrincipal(new CustomTokenPrincipal(id));
292 } else if (action != null && WSConstants.SCT == action.intValue()) {
293 parserResult.setSecretKey((byte[])result.get(WSSecurityEngineResult.TAG_SECRET));
294 SecurityContextToken sct =
295 (SecurityContextToken)result.get(
296 WSSecurityEngineResult.TAG_SECURITY_CONTEXT_TOKEN
297 );
298 parserResult.setPrincipal(new CustomTokenPrincipal(sct.getIdentifier()));
299 } else if (action != null && WSConstants.DKT == action.intValue()) {
300 DerivedKeyToken dkt =
301 (DerivedKeyToken)result.get(WSSecurityEngineResult.TAG_DERIVED_KEY_TOKEN);
302 int keyLength = dkt.getLength();
303 if (keyLength <= 0 && parameters.getDerivationKeyLength() > 0) {
304 keyLength = parameters.getDerivationKeyLength();
305 }
306 byte[] secret = (byte[])result.get(WSSecurityEngineResult.TAG_SECRET);
307 Principal principal = dkt.createPrincipal();
308 ((WSDerivedKeyTokenPrincipal)principal).setSecret(secret);
309 parserResult.setPrincipal(principal);
310 parserResult.setSecretKey(dkt.deriveKey(keyLength, secret));
311 } else if (action != null
312 && (WSConstants.ST_UNSIGNED == action.intValue() || WSConstants.ST_SIGNED == action.intValue())) {
313 SamlAssertionWrapper samlAssertion =
314 (SamlAssertionWrapper)result.get(WSSecurityEngineResult.TAG_SAML_ASSERTION);
315 STRParserUtil.checkSamlTokenBSPCompliance(secRef, samlAssertion, data.getBSPEnforcer());
316
317 SAMLKeyInfo keyInfo = samlAssertion.getSubjectKeyInfo();
318 if (keyInfo == null) {
319 throw new WSSecurityException(
320 WSSecurityException.ErrorCode.FAILURE, "invalidSAMLsecurity"
321 );
322 }
323 X509Certificate[] foundCerts = keyInfo.getCerts();
324 if (foundCerts != null && foundCerts.length > 0) {
325 parserResult.setCerts(new X509Certificate[]{foundCerts[0]});
326 }
327 parserResult.setSecretKey(keyInfo.getSecret());
328 parserResult.setPublicKey(keyInfo.getPublicKey());
329 parserResult.setPrincipal(createPrincipalFromSAML(samlAssertion, parserResult, keyInfo.getSecret()));
330 }
331
332 REFERENCE_TYPE referenceType = getReferenceType(secRef);
333 if (referenceType != null) {
334 parserResult.setReferenceType(referenceType);
335 }
336
337 return parserResult;
338 }
339
340 private STRParserResult processSTR(
341 SecurityTokenReference secRef,
342 String uri,
343 STRParserParameters parameters
344 ) throws WSSecurityException {
345 STRParserResult parserResult = new STRParserResult();
346 RequestData data = parameters.getData();
347 WSDocInfo wsDocInfo = data.getWsDocInfo();
348 Element strElement = parameters.getStrElement();
349
350 if (secRef.containsReference()) {
351 Reference reference = secRef.getReference();
352
353 byte[] secretKey = STRParserUtil.getSecretKeyFromToken(uri, reference.getValueType(),
354 WSPasswordCallback.SECRET_KEY,
355 data);
356 Principal principal = new CustomTokenPrincipal(uri);
357
358 if (secretKey == null || secretKey.length == 0) {
359 Element token =
360 STRParserUtil.getTokenElement(strElement.getOwnerDocument(), wsDocInfo, data.getCallbackHandler(),
361 uri, reference.getValueType());
362 QName el = new QName(token.getNamespaceURI(), token.getLocalName());
363 if (el.equals(WSConstants.BINARY_TOKEN)) {
364 Processor proc = data.getWssConfig().getProcessor(WSConstants.BINARY_TOKEN);
365 List<WSSecurityEngineResult> bstResult = proc.handleToken(token, parameters.getData());
366 BinarySecurity bstToken =
367 (BinarySecurity)bstResult.get(0).get(WSSecurityEngineResult.TAG_BINARY_SECURITY_TOKEN);
368 STRParserUtil.checkBinarySecurityBSPCompliance(
369 secRef, bstToken, data.getBSPEnforcer()
370 );
371
372 parserResult.setCerts(
373 (X509Certificate[])bstResult.get(0).get(WSSecurityEngineResult.TAG_X509_CERTIFICATES));
374 secretKey = (byte[])bstResult.get(0).get(WSSecurityEngineResult.TAG_SECRET);
375 principal = (Principal)bstResult.get(0).get(WSSecurityEngineResult.TAG_PRINCIPAL);
376 } else if (el.equals(WSConstants.SAML_TOKEN) || el.equals(WSConstants.SAML2_TOKEN)) {
377 Processor proc = data.getWssConfig().getProcessor(WSConstants.SAML_TOKEN);
378
379
380
381 Element processedToken =
382 STRParserUtil.findProcessedTokenElement(
383 strElement.getOwnerDocument(), wsDocInfo,
384 data.getCallbackHandler(), uri, secRef.getReference().getValueType()
385 );
386 SamlAssertionWrapper samlAssertion = null;
387 if (processedToken == null) {
388 List<WSSecurityEngineResult> samlResult = proc.handleToken(token, data);
389 samlAssertion =
390 (SamlAssertionWrapper)samlResult.get(0).get(
391 WSSecurityEngineResult.TAG_SAML_ASSERTION
392 );
393 } else {
394 samlAssertion = new SamlAssertionWrapper(processedToken);
395 samlAssertion.parseSubject(
396 new WSSSAMLKeyInfoProcessor(data), data.getSigVerCrypto()
397 );
398 }
399 STRParserUtil.checkSamlTokenBSPCompliance(secRef, samlAssertion, data.getBSPEnforcer());
400
401 SAMLKeyInfo keyInfo = samlAssertion.getSubjectKeyInfo();
402 X509Certificate[] foundCerts = keyInfo.getCerts();
403 if (foundCerts != null && foundCerts.length > 0) {
404 parserResult.setCerts(new X509Certificate[]{foundCerts[0]});
405 }
406 secretKey = keyInfo.getSecret();
407 principal = createPrincipalFromSAML(samlAssertion, parserResult, secretKey);
408 } else if (el.equals(WSConstants.ENCRYPTED_KEY)) {
409 STRParserUtil.checkEncryptedKeyBSPCompliance(secRef, data.getBSPEnforcer());
410 Processor proc = data.getWssConfig().getProcessor(WSConstants.ENCRYPTED_KEY);
411 List<WSSecurityEngineResult> encrResult = proc.handleToken(token, data);
412 secretKey =
413 (byte[])encrResult.get(0).get(WSSecurityEngineResult.TAG_SECRET);
414 principal = new CustomTokenPrincipal(token.getAttributeNS(null, "Id"));
415 }
416 }
417
418 parserResult.setSecretKey(secretKey);
419 parserResult.setPrincipal(principal);
420 } else if (secRef.containsX509Data() || secRef.containsX509IssuerSerial()) {
421 parserResult.setReferenceType(REFERENCE_TYPE.ISSUER_SERIAL);
422 Crypto crypto = data.getSigVerCrypto();
423 X509Certificate[] foundCerts = secRef.getX509IssuerSerial(crypto);
424 if (foundCerts != null && foundCerts.length > 0) {
425 parserResult.setCerts(new X509Certificate[]{foundCerts[0]});
426 }
427 } else if (secRef.containsKeyIdentifier()) {
428 if (secRef.getKeyIdentifierValueType().equals(SecurityTokenReference.ENC_KEY_SHA1_URI)) {
429 STRParserUtil.checkEncryptedKeyBSPCompliance(secRef, data.getBSPEnforcer());
430
431 String id = secRef.getKeyIdentifierValue();
432 parserResult.setSecretKey(
433 STRParserUtil.getSecretKeyFromToken(id, SecurityTokenReference.ENC_KEY_SHA1_URI,
434 WSPasswordCallback.SECRET_KEY, data));
435 parserResult.setPrincipal(new CustomTokenPrincipal(id));
436 } else if (WSConstants.WSS_SAML_KI_VALUE_TYPE.equals(secRef.getKeyIdentifierValueType())
437 || WSConstants.WSS_SAML2_KI_VALUE_TYPE.equals(secRef.getKeyIdentifierValueType())) {
438 parseSAMLKeyIdentifier(secRef, data, parserResult);
439 } else {
440 Crypto crypto = data.getSigVerCrypto();
441 parseBSTKeyIdentifier(secRef, crypto, data, parserResult);
442 }
443 } else {
444 throw new WSSecurityException(
445 WSSecurityException.ErrorCode.INVALID_SECURITY,
446 "unsupportedKeyInfo", new Object[] {strElement.toString()});
447 }
448
449 REFERENCE_TYPE referenceType = getReferenceType(secRef);
450 if (referenceType != null) {
451 parserResult.setReferenceType(referenceType);
452 }
453
454 return parserResult;
455 }
456
457 private REFERENCE_TYPE getReferenceType(SecurityTokenReference secRef) {
458 if (secRef.containsReference()) {
459 return REFERENCE_TYPE.DIRECT_REF;
460 } else if (secRef.containsKeyIdentifier()) {
461 if (SecurityTokenReference.THUMB_URI.equals(secRef.getKeyIdentifierValueType())) {
462 return REFERENCE_TYPE.THUMBPRINT_SHA1;
463 } else {
464 return REFERENCE_TYPE.KEY_IDENTIFIER;
465 }
466 }
467
468 return null;
469 }
470
471 }