View Javadoc
1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements. See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership. The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License. You may obtain a copy of the License at
9    *
10   * http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied. See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.wss4j.stax.impl.securityToken;
20  
21  import java.lang.reflect.InvocationHandler;
22  import java.lang.reflect.InvocationTargetException;
23  import java.lang.reflect.Method;
24  import java.lang.reflect.Proxy;
25  import java.security.MessageDigest;
26  import java.security.NoSuchAlgorithmException;
27  import java.security.Principal;
28  import java.security.cert.CertificateEncodingException;
29  import java.security.cert.X509Certificate;
30  import java.util.ArrayList;
31  import java.util.Arrays;
32  import java.util.List;
33  
34  import javax.security.auth.callback.CallbackHandler;
35  import javax.security.auth.x500.X500Principal;
36  
37  import org.apache.wss4j.binding.wss10.KeyIdentifierType;
38  import org.apache.wss4j.binding.wss10.SecurityTokenReferenceType;
39  import org.apache.wss4j.common.bsp.BSPRule;
40  import org.apache.wss4j.common.crypto.Crypto;
41  import org.apache.wss4j.common.ext.WSSecurityException;
42  import org.apache.wss4j.stax.ext.WSInboundSecurityContext;
43  import org.apache.wss4j.stax.ext.WSSConstants;
44  import org.apache.wss4j.stax.ext.WSSSecurityProperties;
45  import org.apache.wss4j.stax.securityToken.KerberosServiceSecurityToken;
46  import org.apache.wss4j.stax.securityToken.SamlSecurityToken;
47  import org.apache.wss4j.stax.securityToken.SecurityTokenReference;
48  import org.apache.wss4j.stax.securityToken.UsernameSecurityToken;
49  import org.apache.wss4j.stax.securityToken.WSSecurityTokenConstants;
50  import org.apache.wss4j.stax.securityToken.X509SecurityToken;
51  import org.apache.wss4j.stax.utils.WSSUtils;
52  import org.apache.xml.security.binding.xmldsig.DSAKeyValueType;
53  import org.apache.xml.security.binding.xmldsig.KeyInfoType;
54  import org.apache.xml.security.binding.xmldsig.KeyValueType;
55  import org.apache.xml.security.binding.xmldsig.RSAKeyValueType;
56  import org.apache.xml.security.binding.xmldsig.X509DataType;
57  import org.apache.xml.security.binding.xmldsig.X509IssuerSerialType;
58  import org.apache.xml.security.binding.xmldsig11.ECKeyValueType;
59  import org.apache.xml.security.exceptions.XMLSecurityException;
60  import org.apache.xml.security.stax.ext.InboundSecurityContext;
61  import org.apache.xml.security.stax.ext.SecurityContext;
62  import org.apache.xml.security.stax.ext.XMLSecurityConstants;
63  import org.apache.xml.security.stax.ext.XMLSecurityProperties;
64  import org.apache.xml.security.stax.ext.XMLSecurityUtils;
65  import org.apache.xml.security.stax.impl.util.IDGenerator;
66  import org.apache.xml.security.stax.securityToken.InboundSecurityToken;
67  import org.apache.xml.security.stax.securityToken.SecurityTokenFactory;
68  import org.apache.xml.security.stax.securityToken.SecurityTokenProvider;
69  import org.apache.xml.security.utils.XMLUtils;
70  
71  /**
72   * Factory to create InboundSecurityToken Objects from keys in XML
73   */
74  public class SecurityTokenFactoryImpl extends SecurityTokenFactory {
75  
76      public SecurityTokenFactoryImpl() {
77      }
78  
79      @Override
80      public InboundSecurityToken getSecurityToken(KeyInfoType keyInfoType, WSSecurityTokenConstants.KeyUsage keyInfoUsage,
81                                            XMLSecurityProperties securityProperties, InboundSecurityContext inboundSecurityContext)
82              throws XMLSecurityException {
83  
84          Crypto crypto = null;
85          if (WSSecurityTokenConstants.KeyUsage_Signature_Verification.equals(keyInfoUsage)) {
86              crypto = ((WSSSecurityProperties) securityProperties).getSignatureVerificationCrypto();
87          } else if (WSSecurityTokenConstants.KeyUsage_Decryption.equals(keyInfoUsage)) {
88              crypto = ((WSSSecurityProperties) securityProperties).getDecryptionCrypto();
89          }
90  
91          if (keyInfoType != null) {
92              final SecurityTokenReferenceType securityTokenReferenceType
93                      = XMLSecurityUtils.getQNameType(keyInfoType.getContent(), WSSConstants.TAG_WSSE_SECURITY_TOKEN_REFERENCE);
94              if (securityTokenReferenceType != null) {
95                  return getSecurityToken(securityTokenReferenceType, crypto,
96                                          ((WSSSecurityProperties)securityProperties).getCallbackHandler(), inboundSecurityContext,
97                                          (WSSSecurityProperties)securityProperties);
98              }
99              final KeyValueType keyValueType
100                     = XMLSecurityUtils.getQNameType(keyInfoType.getContent(), WSSConstants.TAG_dsig_KeyValue);
101             if (keyValueType != null) {
102                 return getSecurityToken(keyValueType, crypto, ((WSSSecurityProperties)securityProperties).getCallbackHandler(),
103                                         inboundSecurityContext,
104                                         (WSSSecurityProperties)securityProperties);
105             }
106 
107         } else if (crypto != null && crypto.getDefaultX509Identifier() != null) {
108             return new X509DefaultSecurityTokenImpl(
109                     (WSInboundSecurityContext) inboundSecurityContext, crypto,
110                     ((WSSSecurityProperties)securityProperties).getCallbackHandler(), crypto.getDefaultX509Identifier(),
111                     crypto.getDefaultX509Identifier(), WSSecurityTokenConstants.KeyIdentifier_NoKeyInfo,
112                     (WSSSecurityProperties)securityProperties
113             );
114         }
115         throw new WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY, "noKeyinfo");
116     }
117 
118     public static InboundSecurityToken getSecurityToken(SecurityTokenReferenceType securityTokenReferenceType,
119                                                         Crypto crypto,
120                                                         final CallbackHandler callbackHandler,
121                                                         InboundSecurityContext inboundSecurityContext,
122                                                         WSSSecurityProperties securityProperties)
123             throws XMLSecurityException {
124 
125         //BSP.R5205 is a joke. In real life we have a lot of cases which prevents a one pass processing.
126         //Say encrypted Tokens, SignedTokens, Signed-Timestamp first...
127 
128         try {
129             if (securityTokenReferenceType == null) {
130                 throw new WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY, "noSecTokRef");
131             }
132 
133             if (securityTokenReferenceType.getAny().size() > 1) {
134                 ((WSInboundSecurityContext) inboundSecurityContext).handleBSPRule(BSPRule.R3061);
135             }
136 
137             if (securityTokenReferenceType.getId() == null) {
138                 securityTokenReferenceType.setId(IDGenerator.generateID(null));
139             }
140 
141             //todo BSP.R3027 KeyName? not supported ATM
142             //todo BSP.R3060,BSP.R3025,BSP.R3056 only one Embedded element? Not supported ATM
143             final X509DataType x509DataType
144                     = XMLSecurityUtils.getQNameType(securityTokenReferenceType.getAny(), WSSConstants.TAG_dsig_X509Data);
145             if (x509DataType != null) {
146                 InboundSecurityToken securityToken =
147                     getSecurityToken(x509DataType, securityTokenReferenceType.getId(), crypto, callbackHandler,
148                                      inboundSecurityContext, securityProperties);
149                 if (securityToken != null) {
150                     return securityToken;
151                 }
152             }
153 
154             String tokenType =
155                     XMLSecurityUtils.getQNameAttribute(
156                         securityTokenReferenceType.getOtherAttributes(), WSSConstants.ATT_WSSE11_TOKEN_TYPE);
157 
158             final KeyIdentifierType keyIdentifierType
159                     = XMLSecurityUtils.getQNameType(securityTokenReferenceType.getAny(), WSSConstants.TAG_WSSE_KEY_IDENTIFIER);
160             if (keyIdentifierType != null) {
161                 InboundSecurityToken securityToken =
162                     getSecurityToken(keyIdentifierType, securityTokenReferenceType.getId(), tokenType, crypto,
163                                      callbackHandler, inboundSecurityContext, securityProperties);
164                 if (securityToken != null) {
165                     return securityToken;
166                 }
167             }
168 
169             final org.apache.wss4j.binding.wss10.ReferenceType referenceType
170                     = XMLSecurityUtils.getQNameType(securityTokenReferenceType.getAny(), WSSConstants.TAG_WSSE_REFERENCE);
171             if (referenceType != null) {
172                 //We do not check for BSP.R3023, BSP.R3022, BSP.R3066, BSP.R3067, BSP.R3024, BSP.R3064, BSP.R3211, BSP.R3059
173                 return getSecurityToken(referenceType, tokenType, inboundSecurityContext, securityProperties);
174             }
175             throw new WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY, "noKeyinfo");
176         } finally {
177             inboundSecurityContext.remove("" + Thread.currentThread().hashCode());
178         }
179     }
180 
181     private static InboundSecurityToken getSecurityToken(X509DataType x509DataType,
182                                                          String securityTokenReferenceId,
183                                                          Crypto crypto,
184                                                          final CallbackHandler callbackHandler,
185                                                          InboundSecurityContext inboundSecurityContext,
186                                                          WSSSecurityProperties securityProperties)
187                                                              throws XMLSecurityException {
188         //Issuer Serial
189         X509IssuerSerialType x509IssuerSerialType = XMLSecurityUtils.getQNameType(
190                 x509DataType.getX509IssuerSerialOrX509SKIOrX509SubjectName(), WSSConstants.TAG_dsig_X509IssuerSerial);
191         if (x509IssuerSerialType != null) {
192             //first look if the token is included in the message (necessary for TokenInclusion policy)...
193             List<SecurityTokenProvider<? extends InboundSecurityToken>> securityTokenProviders =
194                     inboundSecurityContext.getRegisteredSecurityTokenProviders();
195             for (int i = 0; i < securityTokenProviders.size(); i++) {
196                 SecurityTokenProvider<? extends InboundSecurityToken> tokenProvider = securityTokenProviders.get(i);
197                 InboundSecurityToken inboundSecurityToken = tokenProvider.getSecurityToken();
198                 if (inboundSecurityToken instanceof X509SecurityToken) {
199                     X509SecurityToken x509SecurityToken = (X509SecurityToken) inboundSecurityToken;
200 
201                     final X509Certificate x509Certificate = x509SecurityToken.getX509Certificates()[0];
202                     Principal principal = new X500Principal(x509IssuerSerialType.getX509IssuerName());
203                     if (x509Certificate.getSerialNumber().compareTo(x509IssuerSerialType.getX509SerialNumber()) == 0
204                         && x509Certificate.getIssuerX500Principal().equals(principal)) {
205                         return createSecurityTokenProxy(inboundSecurityToken,
206                                 WSSecurityTokenConstants.KeyIdentifier_IssuerSerial);
207                     }
208                 }
209             }
210             //...then if none is found create a new SecurityToken instance
211             return new X509IssuerSerialTokenImpl(
212                     (WSInboundSecurityContext) inboundSecurityContext, crypto, callbackHandler, x509IssuerSerialType,
213                     securityTokenReferenceId, securityProperties);
214         }
215 
216         //Subject Key Identifier
217         byte[] skiBytes =
218                 XMLSecurityUtils.getQNameType(
219                         x509DataType.getX509IssuerSerialOrX509SKIOrX509SubjectName(),
220                         XMLSecurityConstants.TAG_dsig_X509SKI
221                 );
222         if (skiBytes != null) {
223             return new X509SKISecurityTokenImpl(
224                     (WSInboundSecurityContext) inboundSecurityContext, crypto, callbackHandler, skiBytes,
225                     securityTokenReferenceId, securityProperties);
226         }
227 
228         //X509Certificate
229         byte[] x509CertificateBytes = XMLSecurityUtils.getQNameType(
230                 x509DataType.getX509IssuerSerialOrX509SKIOrX509SubjectName(), WSSConstants.TAG_dsig_X509Certificate);
231         if (x509CertificateBytes != null) {
232             return new X509V3SecurityTokenImpl(
233                     (WSInboundSecurityContext) inboundSecurityContext, crypto, callbackHandler,
234                     x509CertificateBytes, securityTokenReferenceId, securityProperties);
235         }
236 
237         return null;
238     }
239 
240     private static InboundSecurityToken getSecurityToken(KeyIdentifierType keyIdentifierType,
241                                                          String securityTokenReferenceId,
242                                                          String tokenType,
243                                                          Crypto crypto,
244                                                          final CallbackHandler callbackHandler,
245                                                          InboundSecurityContext inboundSecurityContext,
246                                                          WSSSecurityProperties securityProperties)
247                                                              throws XMLSecurityException {
248         String valueType = keyIdentifierType.getValueType();
249         if (valueType == null) {
250             ((WSInboundSecurityContext) inboundSecurityContext).handleBSPRule(BSPRule.R3054);
251         }
252         String encodingType = keyIdentifierType.getEncodingType();
253 
254         byte[] binaryContent = null;
255         if (WSSConstants.SOAPMESSAGE_NS10_BASE64_ENCODING.equals(encodingType)) {
256             binaryContent = XMLUtils.decode(keyIdentifierType.getValue());
257         } else if (!WSSConstants.NS_SAML10_TYPE.equals(valueType) && !WSSConstants.NS_SAML20_TYPE.equals(valueType)) {
258             if (encodingType == null) {
259                 ((WSInboundSecurityContext) inboundSecurityContext).handleBSPRule(BSPRule.R3070);
260             } else {
261                 ((WSInboundSecurityContext) inboundSecurityContext).handleBSPRule(BSPRule.R3071);
262             }
263         } else if (encodingType != null
264                 && (WSSConstants.NS_SAML10_TYPE.equals(valueType) || WSSConstants.NS_SAML20_TYPE.equals(valueType))) {
265             ((WSInboundSecurityContext) inboundSecurityContext).handleBSPRule(BSPRule.R6604);
266         }
267 
268         if (WSSConstants.NS_X509_V3_TYPE.equals(valueType)) {
269             return new X509V3SecurityTokenImpl(
270                     (WSInboundSecurityContext) inboundSecurityContext, crypto, callbackHandler,
271                     binaryContent, securityTokenReferenceId, securityProperties);
272         } else if (WSSConstants.NS_X509_SKI.equals(valueType)) {
273             return new X509SKISecurityTokenImpl(
274                     (WSInboundSecurityContext) inboundSecurityContext, crypto, callbackHandler, binaryContent,
275                     securityTokenReferenceId, securityProperties);
276         } else if (WSSConstants.NS_THUMBPRINT.equals(valueType)) {
277             try {
278                 MessageDigest messageDigest = MessageDigest.getInstance("SHA-1");
279                 //first look if the token is included in the message (necessary for TokenInclusion policy)...
280                 List<SecurityTokenProvider<? extends InboundSecurityToken>> securityTokenProviders =
281                         inboundSecurityContext.getRegisteredSecurityTokenProviders();
282                 for (int i = 0; i < securityTokenProviders.size(); i++) {
283                     SecurityTokenProvider<? extends InboundSecurityToken> tokenProvider = securityTokenProviders.get(i);
284                     InboundSecurityToken inboundSecurityToken = tokenProvider.getSecurityToken();
285                     if (inboundSecurityToken instanceof X509SecurityToken) {
286                         X509SecurityToken x509SecurityToken = (X509SecurityToken)inboundSecurityToken;
287                         byte[] tokenDigest = messageDigest.digest(x509SecurityToken.getX509Certificates()[0].getEncoded());
288 
289                         if (Arrays.equals(tokenDigest, binaryContent)) {
290                             return createSecurityTokenProxy(inboundSecurityToken,
291                                     WSSecurityTokenConstants.KEYIDENTIFIER_THUMBPRINT_IDENTIFIER);
292                         }
293                     }
294                 }
295             } catch (NoSuchAlgorithmException e) {
296                 throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, e);
297             } catch (CertificateEncodingException e) {
298                 throw new WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY_TOKEN);
299             }
300 
301             //...then if none is found create a new SecurityToken instance
302             return new X509ThumbprintSHA1SecurityTokenImpl(
303                     (WSInboundSecurityContext) inboundSecurityContext, crypto, callbackHandler, binaryContent,
304                     securityTokenReferenceId, securityProperties);
305         } else if (WSSConstants.NS_ENCRYPTED_KEY_SHA1.equals(valueType)) {
306             return new EncryptedKeySha1SecurityTokenImpl(
307                     (WSInboundSecurityContext) inboundSecurityContext, callbackHandler, keyIdentifierType.getValue(),
308                     securityTokenReferenceId);
309         } else if (WSSConstants.NS_SAML10_TYPE.equals(valueType) || WSSConstants.NS_SAML20_TYPE.equals(valueType)) {
310             if (WSSConstants.NS_SAML20_TYPE.equals(valueType) && !WSSConstants.NS_SAML20_TOKEN_PROFILE_TYPE.equals(tokenType)) {
311                 ((WSInboundSecurityContext) inboundSecurityContext).handleBSPRule(BSPRule.R6617);
312             } else if (WSSConstants.NS_SAML10_TYPE.equals(valueType)
313                 && !WSSConstants.NS_SAML11_TOKEN_PROFILE_TYPE.equals(tokenType)) {
314                 ((WSInboundSecurityContext) inboundSecurityContext).handleBSPRule(BSPRule.R6611);
315             }
316             SecurityTokenProvider<? extends InboundSecurityToken> securityTokenProvider =
317                     inboundSecurityContext.getSecurityTokenProvider(keyIdentifierType.getValue());
318             if (securityTokenProvider != null) {
319                 return createSecurityTokenProxy(securityTokenProvider.getSecurityToken(),
320                     WSSecurityTokenConstants.KEYIDENTIFIER_SECURITY_TOKEN_DIRECT_REFERENCE);
321             }
322 
323             // Delegate to a CallbackHandler, in case the token is not in the request
324             return new SamlSecurityTokenImpl((WSInboundSecurityContext) inboundSecurityContext,
325                                              keyIdentifierType.getValue(),
326                                              WSSecurityTokenConstants.KEYIDENTIFIER_EXTERNAL_REFERENCE,
327                                              securityProperties);
328         } else if (WSSConstants.NS_KERBEROS5_AP_REQ_SHA1.equals(valueType)) {
329             SecurityTokenProvider<? extends InboundSecurityToken> securityTokenProvider =
330                     inboundSecurityContext.getSecurityTokenProvider(keyIdentifierType.getValue());
331             if (securityTokenProvider != null) {
332                 return createSecurityTokenProxy(securityTokenProvider.getSecurityToken(),
333                         WSSecurityTokenConstants.KEYIDENTIFIER_SECURITY_TOKEN_DIRECT_REFERENCE);
334             }
335 
336             try {
337                 //ok we have to find the token via digesting...
338                 MessageDigest messageDigest = MessageDigest.getInstance("SHA-1");
339                 List<SecurityTokenProvider<? extends InboundSecurityToken>> securityTokenProviders =
340                         inboundSecurityContext.getRegisteredSecurityTokenProviders();
341                 for (int i = 0; i < securityTokenProviders.size(); i++) {
342                     SecurityTokenProvider<? extends InboundSecurityToken> tokenProvider = securityTokenProviders.get(i);
343                     InboundSecurityToken inboundSecurityToken = tokenProvider.getSecurityToken();
344                     if (inboundSecurityToken instanceof KerberosServiceSecurityToken) {
345                         KerberosServiceSecurityToken kerberosSecurityToken =
346                             (KerberosServiceSecurityToken)inboundSecurityToken;
347                         byte[] tokenDigest = messageDigest.digest(kerberosSecurityToken.getBinaryContent());
348                         if (Arrays.equals(tokenDigest, binaryContent)) {
349                             return createSecurityTokenProxy(inboundSecurityToken,
350                                     WSSecurityTokenConstants.KEYIDENTIFIER_THUMBPRINT_IDENTIFIER);
351                         }
352                     }
353                 }
354             } catch (NoSuchAlgorithmException e) {
355                 throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, e);
356             }
357 
358             // Finally, just delegate to a Callback as per EncryptedKeySHA1
359             return new EncryptedKeySha1SecurityTokenImpl(
360                     (WSInboundSecurityContext) inboundSecurityContext, callbackHandler,
361                     keyIdentifierType.getValue(), securityTokenReferenceId);
362         } else {
363             //we do enforce BSP compliance here but will fail anyway since we cannot identify the referenced token
364             ((WSInboundSecurityContext) inboundSecurityContext).handleBSPRule(BSPRule.R3063);
365         }
366 
367         return null;
368     }
369 
370     private static InboundSecurityToken getSecurityToken(org.apache.wss4j.binding.wss10.ReferenceType referenceType,
371                                                          String tokenType,
372                                                          InboundSecurityContext inboundSecurityContext,
373                                                          WSSSecurityProperties securityProperties)
374                                                              throws XMLSecurityException {
375         String uri = referenceType.getURI();
376         if (uri == null) {
377             //we do enforce BSP compliance here but will fail anyway since we cannot identify the referenced token
378             ((WSInboundSecurityContext) inboundSecurityContext).handleBSPRule(BSPRule.R3062);
379             throw new WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY, "badReferenceURI");
380         }
381         boolean included = true;
382         if (!uri.startsWith("#")) {
383             included = false;
384             // Delegate to a CallbackHandler, in case the token is not in the request
385             try {
386                 return new ExternalSecurityTokenImpl((WSInboundSecurityContext) inboundSecurityContext,
387                                              uri,
388                                              WSSecurityTokenConstants.KEYIDENTIFIER_EXTERNAL_REFERENCE,
389                                              securityProperties, false);
390             } catch (WSSecurityException ex) { //NOPMD
391                 // just continue
392             }
393             ((WSInboundSecurityContext) inboundSecurityContext).handleBSPRule(BSPRule.R5204);
394         }
395         uri = WSSUtils.dropReferenceMarker(uri);
396         //referenced BST:*/
397         //we have to search BST somewhere in the doc. First we will check for a BST already processed and
398         //stored in the context. Otherwise we will abort now.
399 
400         //prevent recursive key reference DOS:
401         Integer invokeCount = inboundSecurityContext.<Integer>get("" + Thread.currentThread().hashCode());
402         if (invokeCount == null) {
403             invokeCount = 0;
404         }
405         invokeCount++;
406         if (invokeCount == 10) {
407             throw new WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY_TOKEN);
408         }
409         inboundSecurityContext.put("" + Thread.currentThread().hashCode(), invokeCount);
410 
411         SecurityTokenProvider<? extends InboundSecurityToken> securityTokenProvider =
412                 inboundSecurityContext.getSecurityTokenProvider(uri);
413         if (securityTokenProvider == null) {
414             // Delegate to a CallbackHandler, in case the token is not in the request
415             return new ExternalSecurityTokenImpl((WSInboundSecurityContext) inboundSecurityContext,
416                                              uri,
417                                              WSSecurityTokenConstants.KEYIDENTIFIER_EXTERNAL_REFERENCE,
418                                              securityProperties, included);
419         }
420         if (securityTokenProvider.getSecurityToken() instanceof SecurityTokenReference) {
421             ((WSInboundSecurityContext) inboundSecurityContext).handleBSPRule(BSPRule.R3057);
422         } else if (securityTokenProvider.getSecurityToken() instanceof X509PKIPathv1SecurityTokenImpl) {
423             String valueType = referenceType.getValueType();
424             if (!WSSConstants.NS_X509_PKIPATH_V1.equals(valueType)) {
425                 ((WSInboundSecurityContext) inboundSecurityContext).handleBSPRule(BSPRule.R3058);
426             }
427             if (!WSSConstants.NS_X509_PKIPATH_V1.equals(tokenType)) {
428                 ((WSInboundSecurityContext) inboundSecurityContext).handleBSPRule(BSPRule.R5215);
429             }
430         } else if (securityTokenProvider.getSecurityToken() instanceof X509SecurityToken) {
431             String valueType = referenceType.getValueType();
432             if (!WSSConstants.NS_X509_V3_TYPE.equals(valueType)) {
433                 ((WSInboundSecurityContext) inboundSecurityContext).handleBSPRule(BSPRule.R3058);
434             }
435         } else if (securityTokenProvider.getSecurityToken() instanceof UsernameSecurityToken) {
436             String valueType = referenceType.getValueType();
437             if (!WSSConstants.NS_USERNAMETOKEN_PROFILE_USERNAME_TOKEN.equals(valueType)) {
438                 ((WSInboundSecurityContext) inboundSecurityContext).handleBSPRule(BSPRule.R4214);
439             }
440         } else if (securityTokenProvider.getSecurityToken() instanceof SamlSecurityToken) {
441             WSSecurityTokenConstants.TokenType samlTokenType = securityTokenProvider.getSecurityToken().getTokenType();
442             if (WSSecurityTokenConstants.SAML_20_TOKEN.equals(samlTokenType)) {
443                 String valueType = referenceType.getValueType();
444                 if (valueType != null && valueType.length() != 0) {
445                     ((WSInboundSecurityContext) inboundSecurityContext).handleBSPRule(BSPRule.R6614);
446                 }
447                 if (!WSSConstants.NS_SAML20_TOKEN_PROFILE_TYPE.equals(tokenType)) {
448                     ((WSInboundSecurityContext) inboundSecurityContext).handleBSPRule(BSPRule.R6617);
449                 }
450             } else if (WSSecurityTokenConstants.SAML_10_TOKEN.equals(samlTokenType)
451                 && !WSSConstants.NS_SAML11_TOKEN_PROFILE_TYPE.equals(tokenType)) {
452                 ((WSInboundSecurityContext) inboundSecurityContext).handleBSPRule(BSPRule.R6611);
453             }
454         }
455 
456 
457         return createSecurityTokenProxy(securityTokenProvider.getSecurityToken(),
458                 WSSecurityTokenConstants.KEYIDENTIFIER_SECURITY_TOKEN_DIRECT_REFERENCE);
459     }
460 
461     public static InboundSecurityToken getSecurityToken(KeyValueType keyValueType, final Crypto crypto,
462                                                  final CallbackHandler callbackHandler, SecurityContext securityContext,
463                                                  WSSSecurityProperties securityProperties)
464             throws XMLSecurityException {
465 
466         final RSAKeyValueType rsaKeyValueType
467                 = XMLSecurityUtils.getQNameType(keyValueType.getContent(), WSSConstants.TAG_dsig_RSAKeyValue);
468         if (rsaKeyValueType != null) {
469             return new RsaKeyValueSecurityTokenImpl(rsaKeyValueType, (WSInboundSecurityContext) securityContext, crypto,
470                                                     callbackHandler, securityProperties);
471         }
472 
473         final DSAKeyValueType dsaKeyValueType
474                 = XMLSecurityUtils.getQNameType(keyValueType.getContent(), WSSConstants.TAG_dsig_DSAKeyValue);
475         if (dsaKeyValueType != null) {
476             return new DsaKeyValueSecurityTokenImpl(dsaKeyValueType, (WSInboundSecurityContext) securityContext, crypto,
477                                                     callbackHandler, securityProperties);
478         }
479 
480         final ECKeyValueType ecKeyValueType
481                 = XMLSecurityUtils.getQNameType(keyValueType.getContent(), WSSConstants.TAG_dsig11_ECKeyValue);
482         if (ecKeyValueType != null) {
483             return new ECKeyValueSecurityTokenImpl(ecKeyValueType, (WSInboundSecurityContext) securityContext, crypto,
484                                                    callbackHandler, securityProperties);
485         }
486         throw new WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY, "unsupportedKeyInfo");
487     }
488 
489     private static InboundSecurityToken createSecurityTokenProxy(
490             final InboundSecurityToken inboundSecurityToken,
491             final WSSecurityTokenConstants.KeyIdentifier keyIdentifier) {
492 
493         List<Class<?>> implementedInterfaces = new ArrayList<>();
494         getImplementedInterfaces(inboundSecurityToken.getClass(), implementedInterfaces);
495         Class<?>[] interfaces = implementedInterfaces.toArray(new Class<?>[implementedInterfaces.size()]);
496 
497         return (InboundSecurityToken) Proxy.newProxyInstance(
498                 inboundSecurityToken.getClass().getClassLoader(),
499                 interfaces,
500                 new InvocationHandler() {
501 
502                     @Override
503                     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
504                         if (method.getName().equals("getKeyIdentifier")) {
505                             return keyIdentifier;
506                         }
507                         try {
508                             return method.invoke(inboundSecurityToken, args);
509                         } catch (InvocationTargetException e) {
510                             throw e.getTargetException();
511                         }
512                     }
513                 }
514         );
515     }
516 
517     private static void getImplementedInterfaces(Class<?> clazz, List<Class<?>> interfaceList) {
518         if (clazz == null) {
519             return;
520         }
521         Class<?>[] interfaces = clazz.getInterfaces();
522         for (int i = 0; i < interfaces.length; i++) {
523             Class<?> anInterface = interfaces[i];
524 
525             if (!interfaceList.contains(anInterface)) {
526                 interfaceList.add(anInterface);
527             }
528             getImplementedInterfaces(anInterface, interfaceList);
529         }
530         getImplementedInterfaces(clazz.getSuperclass(), interfaceList);
531     }
532 }