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