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  
20  package org.apache.ws.security.components.crypto;
21  
22  import org.apache.ws.security.WSPasswordCallback;
23  import org.apache.ws.security.WSSecurityException;
24  import org.apache.ws.security.util.Loader;
25  
26  import java.io.FileInputStream;
27  import java.io.IOException;
28  import java.io.InputStream;
29  import java.math.BigInteger;
30  import java.security.GeneralSecurityException;
31  import java.security.Key;
32  import java.security.KeyStore;
33  import java.security.KeyStoreException;
34  import java.security.MessageDigest;
35  import java.security.NoSuchAlgorithmException;
36  import java.security.NoSuchProviderException;
37  import java.security.PrivateKey;
38  import java.security.PublicKey;
39  import java.security.UnrecoverableKeyException;
40  import java.security.cert.CertPath;
41  import java.security.cert.CertPathValidator;
42  import java.security.cert.CertStore;
43  import java.security.cert.Certificate;
44  import java.security.cert.CertificateEncodingException;
45  import java.security.cert.CertificateException;
46  import java.security.cert.CertificateFactory;
47  import java.security.cert.CollectionCertStoreParameters;
48  import java.security.cert.PKIXParameters;
49  import java.security.cert.TrustAnchor;
50  import java.security.cert.X509CRL;
51  import java.security.cert.X509Certificate;
52  import java.util.Arrays;
53  import java.util.Collections;
54  import java.util.Enumeration;
55  import java.util.HashSet;
56  import java.util.List;
57  import java.util.Properties;
58  import java.util.Set;
59  
60  import javax.security.auth.callback.Callback;
61  import javax.security.auth.callback.CallbackHandler;
62  import javax.security.auth.callback.UnsupportedCallbackException;
63  import javax.security.auth.x500.X500Principal;
64  
65  /**
66   * A Crypto implementation based on two Java KeyStore objects, one being the keystore, and one
67   * being the truststore.
68   */
69  public class Merlin extends CryptoBase {
70      
71      /*
72       * Deprecated types
73       */
74      public static final String OLD_KEYSTORE_FILE = 
75          "org.apache.ws.security.crypto.merlin.file";
76      
77      /*
78       * Crypto providers
79       */
80      public static final String CRYPTO_KEYSTORE_PROVIDER = 
81          "org.apache.ws.security.crypto.merlin.keystore.provider";
82      public static final String CRYPTO_CERT_PROVIDER =
83          "org.apache.ws.security.crypto.merlin.cert.provider";
84      
85      /*
86       * KeyStore configuration types
87       */
88      public static final String KEYSTORE_FILE = 
89          "org.apache.ws.security.crypto.merlin.keystore.file";
90      public static final String KEYSTORE_PASSWORD =
91          "org.apache.ws.security.crypto.merlin.keystore.password";
92      public static final String KEYSTORE_TYPE =
93          "org.apache.ws.security.crypto.merlin.keystore.type";
94      public static final String KEYSTORE_ALIAS =
95          "org.apache.ws.security.crypto.merlin.keystore.alias";
96      public static final String KEYSTORE_PRIVATE_PASSWORD =
97          "org.apache.ws.security.crypto.merlin.keystore.private.password";
98      
99      /*
100      * TrustStore configuration types
101      */
102     public static final String LOAD_CA_CERTS =
103         "org.apache.ws.security.crypto.merlin.load.cacerts";
104     public static final String TRUSTSTORE_FILE =
105         "org.apache.ws.security.crypto.merlin.truststore.file";
106     public static final String TRUSTSTORE_PASSWORD =
107         "org.apache.ws.security.crypto.merlin.truststore.password";
108     public static final String TRUSTSTORE_TYPE =
109         "org.apache.ws.security.crypto.merlin.truststore.type";
110     
111     /*
112      * CRL configuration
113      */
114     public static final String X509_CRL_FILE = 
115         "org.apache.ws.security.crypto.merlin.x509crl.file";
116     
117     private static final org.apache.commons.logging.Log LOG = 
118         org.apache.commons.logging.LogFactory.getLog(Merlin.class);
119     private static final boolean DO_DEBUG = LOG.isDebugEnabled();
120 
121     protected static CertificateFactory certFact;
122     protected Properties properties = null;
123     protected KeyStore keystore = null;
124     protected KeyStore truststore = null;
125     protected CertStore crlCertStore = null;
126     protected boolean loadCACerts = false;
127     protected boolean privatePasswordSet = false; 
128     
129     public Merlin() {
130         // default constructor
131     }
132     
133     public Merlin(Properties properties) 
134         throws CredentialException, IOException {
135         this(properties, Loader.getClassLoader(Merlin.class));
136     }
137 
138     public Merlin(Properties properties, ClassLoader loader) 
139         throws CredentialException, IOException {
140         loadProperties(properties, loader);
141     }
142     
143     public void loadProperties(Properties properties) 
144         throws CredentialException, IOException {
145         loadProperties(properties, Loader.getClassLoader(Merlin.class));
146     }
147     
148     public void loadProperties(Properties properties, ClassLoader loader) 
149         throws CredentialException, IOException {
150         if (properties == null) {
151             return;
152         }
153         this.properties = properties;
154         //
155         // Load the provider(s)
156         //
157         String provider = properties.getProperty(CRYPTO_KEYSTORE_PROVIDER);
158         if (provider != null) {
159             provider = provider.trim();
160         }
161         String certProvider = properties.getProperty(CRYPTO_CERT_PROVIDER);
162         if (certProvider != null) {
163             setCryptoProvider(certProvider);
164         }
165         //
166         // Load the KeyStore
167         //
168         String alias = properties.getProperty(KEYSTORE_ALIAS);
169         if (alias != null) {
170             alias = alias.trim();
171             defaultAlias = alias;
172         }
173         String keyStoreLocation = properties.getProperty(KEYSTORE_FILE);
174         if (keyStoreLocation == null) {
175             keyStoreLocation = properties.getProperty(OLD_KEYSTORE_FILE);
176         }
177         if (keyStoreLocation != null) {
178             keyStoreLocation = keyStoreLocation.trim();
179             InputStream is = loadInputStream(loader, keyStoreLocation);
180 
181             try {
182                 String passwd = properties.getProperty(KEYSTORE_PASSWORD, "security");
183                 if (passwd != null) {
184                     passwd = passwd.trim();
185                 }
186                 String type = properties.getProperty(KEYSTORE_TYPE, KeyStore.getDefaultType());
187                 if (type != null) {
188                     type = type.trim();
189                 }
190                 keystore = load(is, passwd, provider, type);
191                 if (DO_DEBUG) {
192                     LOG.debug(
193                         "The KeyStore " + keyStoreLocation + " of type " + type 
194                         + " has been loaded"
195                     );
196                 }
197                 String privatePasswd = properties.getProperty(KEYSTORE_PRIVATE_PASSWORD);
198                 if (privatePasswd != null) {
199                     privatePasswordSet = true;
200                 }
201             } finally {
202                 if (is != null) {
203                     is.close();
204                 }
205             }
206         } else {
207             if (DO_DEBUG) {
208                 LOG.debug("The KeyStore is not loaded as KEYSTORE_FILE is null");
209             }
210         }
211         
212         //
213         // Load the TrustStore
214         //
215         String trustStoreLocation = properties.getProperty(TRUSTSTORE_FILE);
216         if (trustStoreLocation != null) {
217             trustStoreLocation = trustStoreLocation.trim();
218             InputStream is = loadInputStream(loader, trustStoreLocation);
219 
220             try {
221                 String passwd = properties.getProperty(TRUSTSTORE_PASSWORD, "changeit");
222                 if (passwd != null) {
223                     passwd = passwd.trim();
224                 }
225                 String type = properties.getProperty(TRUSTSTORE_TYPE, KeyStore.getDefaultType());
226                 if (type != null) {
227                     type = type.trim();
228                 }
229                 truststore = load(is, passwd, provider, type);
230                 if (DO_DEBUG) {
231                     LOG.debug(
232                         "The TrustStore " + trustStoreLocation + " of type " + type 
233                         + " has been loaded"
234                     );
235                 }
236                 loadCACerts = false;
237             } finally {
238                 if (is != null) {
239                     is.close();
240                 }
241             }
242         } else {
243             String loadCacerts = properties.getProperty(LOAD_CA_CERTS, "false");
244             if (loadCacerts != null) {
245                 loadCacerts = loadCacerts.trim();
246             }
247             if (Boolean.valueOf(loadCacerts).booleanValue()) {
248                 String cacertsPath = System.getProperty("java.home") + "/lib/security/cacerts";
249                 if (cacertsPath != null) {
250                     cacertsPath = cacertsPath.trim();
251                 }
252                 InputStream is = new FileInputStream(cacertsPath);
253                 try {
254                     String cacertsPasswd = properties.getProperty(TRUSTSTORE_PASSWORD, "changeit");
255                     if (cacertsPasswd != null) {
256                         cacertsPasswd = cacertsPasswd.trim();
257                     }
258                     truststore = load(is, cacertsPasswd, null, KeyStore.getDefaultType());
259                     if (DO_DEBUG) {
260                         LOG.debug("CA certs have been loaded");
261                     }
262                     loadCACerts = true;
263                 } finally {
264                     if (is != null) {
265                         is.close();
266                     }
267                 }
268             }
269         }
270         //
271         // Load the CRL file
272         //
273         String crlLocation = properties.getProperty(X509_CRL_FILE);
274         if (crlLocation != null) {
275             crlLocation = crlLocation.trim();
276             InputStream is = loadInputStream(loader, crlLocation);
277 
278             try {
279                 CertificateFactory cf = getCertificateFactory();
280                 X509CRL crl = (X509CRL)cf.generateCRL(is);
281                 
282                 if (provider == null || provider.length() == 0) {
283                     crlCertStore = 
284                         CertStore.getInstance(
285                             "Collection",
286                             new CollectionCertStoreParameters(Collections.singletonList(crl))
287                         );
288                 } else {
289                     crlCertStore = 
290                         CertStore.getInstance(
291                             "Collection",
292                             new CollectionCertStoreParameters(Collections.singletonList(crl)),
293                             provider
294                         );
295                 }
296                 if (DO_DEBUG) {
297                     LOG.debug(
298                         "The CRL " + crlLocation + " has been loaded"
299                     );
300                 }
301             } catch (Exception e) {
302                 if (DO_DEBUG) {
303                     LOG.debug(e.getMessage(), e);
304                 }
305                 throw new CredentialException(CredentialException.IO_ERROR, "ioError00", e);
306             } finally {
307                 if (is != null) {
308                     is.close();
309                 }
310             }
311         }
312     }
313 
314     
315     /**
316      * Load a KeyStore object as an InputStream, using the ClassLoader and location arguments
317      */
318     public static InputStream loadInputStream(ClassLoader loader, String location) 
319         throws CredentialException, IOException {
320         InputStream is = null;
321         if (location != null) {
322             java.net.URL url = Loader.getResource(loader, location);
323             if (url != null) {
324                 is = url.openStream();
325             }
326     
327             //
328             // If we don't find it, then look on the file system.
329             //
330             if (is == null) {
331                 try {
332                     is = new FileInputStream(location);
333                 } catch (Exception e) {
334                     if (DO_DEBUG) {
335                         LOG.debug(e.getMessage(), e);
336                     }
337                     throw new CredentialException(
338                         CredentialException.IO_ERROR, "proxyNotFound", new Object[]{location}, e
339                     );
340                 }
341             }
342         }
343         return is;
344     }
345     
346 
347     /**
348      * Loads the keystore from an <code>InputStream </code>.
349      * <p/>
350      *
351      * @param input <code>InputStream</code> to read from
352      * @throws CredentialException
353      */
354     public KeyStore load(InputStream input, String storepass, String provider, String type) 
355         throws CredentialException {
356         KeyStore ks = null;
357         
358         try {
359             if (provider == null || provider.length() == 0) {
360                 ks = KeyStore.getInstance(type);
361             } else {
362                 ks = KeyStore.getInstance(type, provider);
363             }
364                     
365             ks.load(input, (storepass == null || storepass.length() == 0) 
366                 ? new char[0] : storepass.toCharArray());
367         } catch (IOException e) {
368             if (DO_DEBUG) {
369                 LOG.debug(e.getMessage(), e);
370             }
371             throw new CredentialException(CredentialException.IO_ERROR, "ioError00", e);
372         } catch (GeneralSecurityException e) {
373             if (DO_DEBUG) {
374                 LOG.debug(e.getMessage(), e);
375             }
376             throw new CredentialException(CredentialException.SEC_ERROR, "secError00", e);
377         } catch (Exception e) {
378             if (DO_DEBUG) {
379                 LOG.debug(e.getMessage(), e);
380             }
381             throw new CredentialException(CredentialException.FAILURE, "error00", e);
382         }
383         return ks;
384     }
385     
386     //
387     // Accessor methods
388     //
389     
390     /**
391      * Gets the Keystore that was loaded
392      *
393      * @return the Keystore
394      */
395     public KeyStore getKeyStore() {
396         return keystore;
397     }
398     
399     /**
400      * Set the Keystore on this Crypto instance
401      *
402      * @param keyStore the Keystore to set
403      */
404     public void setKeyStore(KeyStore keyStore) {
405         keystore = keyStore;
406     }
407     
408     /**
409      * Gets the trust store that was loaded by the underlying implementation
410      *
411      * @return the trust store
412      */
413     public KeyStore getTrustStore() {
414         return truststore;
415     }
416     
417     /**
418      * Set the trust store on this Crypto instance
419      *
420      * @param trustStore the trust store to set
421      */
422     public void setTrustStore(KeyStore trustStore) {
423         truststore = trustStore;
424     }
425     
426     /**
427      * Set the CertStore from which to obtain a list of CRLs for Certificate Revocation
428      * checking.
429      * @param crlCertStore the CertStore from which to obtain a list of CRLs for Certificate 
430      * Revocation checking.
431      */
432     public void setCRLCertStore(CertStore crlCertStore) {
433         this.crlCertStore = crlCertStore;
434     }
435     
436     /**
437      * Get the CertStore from which to obtain a list of CRLs for Certificate Revocation
438      * checking.
439      * @return the CertStore from which to obtain a list of CRLs for Certificate 
440      * Revocation checking.
441      */
442     public CertStore getCRLCertStore() {
443         return crlCertStore;
444     }
445     
446     /**
447      * Singleton certificate factory for this Crypto instance.
448      * <p/>
449      *
450      * @return Returns a <code>CertificateFactory</code> to construct
451      *         X509 certificates
452      * @throws org.apache.ws.security.WSSecurityException
453      */
454     @Override
455     public CertificateFactory getCertificateFactory() throws WSSecurityException {
456         String provider = getCryptoProvider();
457         String keyStoreProvider = null;
458         if (keystore != null) {
459             keyStoreProvider = keystore.getProvider().getName();
460         }
461 
462         //Try to find a CertificateFactory that generates certs that are fully
463         //compatible with the certs in the KeyStore  (Sun -> Sun, BC -> BC, etc...)
464         CertificateFactory factory = null;
465         if (provider != null) {
466             factory = certFactMap.get(provider);
467         } else if (keyStoreProvider != null) {
468             factory = 
469                 certFactMap.get(mapKeystoreProviderToCertProvider(keyStoreProvider));
470             if (factory == null) {
471                 factory = certFactMap.get(keyStoreProvider);                
472             }
473         } else {
474             factory = certFactMap.get("DEFAULT");
475         }
476         if (factory == null) {
477             try {
478                 if (provider == null || provider.length() == 0) {
479                     if (keyStoreProvider != null && keyStoreProvider.length() != 0) {
480                         try {
481                             factory = 
482                                 CertificateFactory.getInstance(
483                                     "X.509", mapKeystoreProviderToCertProvider(keyStoreProvider)
484                                 );
485                             certFactMap.put(keyStoreProvider, factory);
486                             certFactMap.put(
487                                 mapKeystoreProviderToCertProvider(keyStoreProvider), factory
488                             );
489                         } catch (Exception ex) {
490                             LOG.debug(ex);
491                             //Ignore, we'll just use the default since they didn't specify one.
492                             //Hopefully that will work for them.
493                         }
494                     }
495                     if (factory == null) {
496                         factory = CertificateFactory.getInstance("X.509");
497                         certFactMap.put("DEFAULT", factory);
498                     }
499                 } else {
500                     factory = CertificateFactory.getInstance("X.509", provider);
501                     certFactMap.put(provider, factory);
502                 }
503                 certFactMap.put(factory.getProvider().getName(), factory);
504             } catch (CertificateException e) {
505                 throw new WSSecurityException(
506                     WSSecurityException.SECURITY_TOKEN_UNAVAILABLE, "unsupportedCertType",
507                     null, e
508                 );
509             } catch (NoSuchProviderException e) {
510                 throw new WSSecurityException(
511                     WSSecurityException.SECURITY_TOKEN_UNAVAILABLE, "noSecProvider",
512                     null, e
513                 );
514             }
515         }
516         return factory;
517     }
518     
519     private String mapKeystoreProviderToCertProvider(String s) {
520         if ("SunJSSE".equals(s)) {
521             return "SUN";
522         }
523         return s;
524     }
525     
526     /**
527      * Retrieves the identifier name of the default certificate. This should be the certificate 
528      * that is used for signature and encryption. This identifier corresponds to the certificate 
529      * that should be used whenever KeyInfo is not present in a signed or an encrypted 
530      * message. May return null. The identifier is implementation specific, e.g. it could be the
531      * KeyStore alias.
532      *
533      * @return name of the default X509 certificate.
534      */
535     @Override
536     public String getDefaultX509Identifier() throws WSSecurityException {
537         if (defaultAlias != null) {
538             return defaultAlias;
539         }
540         
541         if (keystore != null) {
542             try {
543                 Enumeration<String> as = keystore.aliases();
544                 if (as.hasMoreElements()) {
545                     String alias = as.nextElement();
546                     if (!as.hasMoreElements()) {
547                         defaultAlias = alias;
548                         return alias;
549                     }
550                 }
551             } catch (KeyStoreException ex) {
552                 throw new WSSecurityException(
553                     WSSecurityException.FAILURE, "keystore", null, ex
554                 );
555             } 
556         }
557         return null;
558     }
559     
560     //
561     // Keystore-specific Crypto functionality methods
562     //
563 
564     /**
565      * Get an X509Certificate (chain) corresponding to the CryptoType argument. The supported
566      * types are as follows:
567      * 
568      * TYPE.ISSUER_SERIAL - A certificate (chain) is located by the issuer name and serial number
569      * TYPE.THUMBPRINT_SHA1 - A certificate (chain) is located by the SHA1 of the (root) cert
570      * TYPE.SKI_BYTES - A certificate (chain) is located by the SKI bytes of the (root) cert
571      * TYPE.SUBJECT_DN - A certificate (chain) is located by the Subject DN of the (root) cert
572      * TYPE.ALIAS - A certificate (chain) is located by an alias, which for this implementation
573      * means an alias of the keystore or truststore.
574      */
575     public X509Certificate[] getX509Certificates(CryptoType cryptoType) throws WSSecurityException {
576         if (cryptoType == null) {
577             return null;
578         }
579         CryptoType.TYPE type = cryptoType.getType();
580         X509Certificate[] certs = null;
581         switch (type) {
582         case ISSUER_SERIAL: {
583             certs = getX509Certificates(cryptoType.getIssuer(), cryptoType.getSerial());
584             break;
585         }
586         case THUMBPRINT_SHA1: {
587             certs = getX509Certificates(cryptoType.getBytes());
588             break;
589         }
590         case SKI_BYTES: {
591             certs = getX509CertificatesSKI(cryptoType.getBytes());
592             break;
593         }
594         case SUBJECT_DN: {
595             certs = getX509CertificatesSubjectDN(cryptoType.getSubjectDN());
596             break;
597         }
598         case ALIAS: {
599             certs = getX509Certificates(cryptoType.getAlias());
600             break;
601         }
602         }
603         return certs;
604     }
605 
606     /**
607      * Get the implementation-specific identifier corresponding to the cert parameter. In this 
608      * case, the identifier corresponds to a KeyStore alias.
609      * @param cert The X509Certificate for which to search for an identifier
610      * @return the identifier corresponding to the cert parameter
611      * @throws WSSecurityException
612      */
613     public String getX509Identifier(X509Certificate cert) throws WSSecurityException {
614         String identifier = null;
615         
616         if (keystore != null) {
617             identifier = getIdentifier(cert, keystore);
618         }
619         
620         if (identifier == null && truststore != null) {
621             identifier = getIdentifier(cert, truststore);
622         }
623         
624         return identifier;
625     }
626     
627     /**
628      * Gets the private key corresponding to the certificate.
629      *
630      * @param certificate The X509Certificate corresponding to the private key
631      * @param callbackHandler The callbackHandler needed to get the password
632      * @return The private key
633      */
634     public PrivateKey getPrivateKey(
635         X509Certificate certificate, 
636         CallbackHandler callbackHandler
637     ) throws WSSecurityException {
638         if (keystore == null) {
639             throw new WSSecurityException("The keystore is null");
640         }
641         if (callbackHandler == null) {
642             throw new WSSecurityException("The CallbackHandler is null");
643         }
644         
645         String identifier = getIdentifier(certificate, keystore);
646         try {
647             if (identifier == null || !keystore.isKeyEntry(identifier)) {
648                 String msg = "Cannot find key for alias: [" + identifier + "]";
649                 String logMsg = createKeyStoreErrorMessage(keystore);
650                 LOG.error(msg + logMsg);
651                 throw new WSSecurityException(msg);
652             }
653             String password = getPassword(identifier, callbackHandler);
654             if (password == null && privatePasswordSet) {
655                 password = properties.getProperty(KEYSTORE_PRIVATE_PASSWORD);
656                 if (password != null) {
657                     password = password.trim();
658                 }
659             }
660             Key keyTmp = keystore.getKey(identifier, password == null 
661                                          ? new char[]{} : password.toCharArray());
662             if (!(keyTmp instanceof PrivateKey)) {
663                 String msg = "Key is not a private key, alias: [" + identifier + "]";
664                 String logMsg = createKeyStoreErrorMessage(keystore);
665                 LOG.error(msg + logMsg);
666                 throw new WSSecurityException(msg);
667             }
668             return (PrivateKey) keyTmp;
669         } catch (KeyStoreException ex) {
670             throw new WSSecurityException(
671                 WSSecurityException.FAILURE, "noPrivateKey", new Object[]{ex.getMessage()}, ex
672             );
673         } catch (UnrecoverableKeyException ex) {
674             throw new WSSecurityException(
675                 WSSecurityException.FAILURE, "noPrivateKey", new Object[]{ex.getMessage()}, ex
676             );
677         } catch (NoSuchAlgorithmException ex) {
678             throw new WSSecurityException(
679                 WSSecurityException.FAILURE, "noPrivateKey", new Object[]{ex.getMessage()}, ex
680             );
681         }
682     }
683     
684     /**
685      * Gets the private key corresponding to the identifier.
686      *
687      * @param identifier The implementation-specific identifier corresponding to the key
688      * @param password The password needed to get the key
689      * @return The private key
690      */
691     public PrivateKey getPrivateKey(
692         String identifier,
693         String password
694     ) throws WSSecurityException {
695         if (keystore == null) {
696             throw new WSSecurityException("The keystore is null");
697         }
698         try {
699             if (identifier == null || !keystore.isKeyEntry(identifier)) {
700                 String msg = "Cannot find key for alias: [" + identifier + "]";
701                 String logMsg = createKeyStoreErrorMessage(keystore);
702                 LOG.error(msg + logMsg);
703                 throw new WSSecurityException(msg);
704             }
705             if (password == null && privatePasswordSet) {
706                 password = properties.getProperty(KEYSTORE_PRIVATE_PASSWORD);
707                 if (password != null) {
708                     password = password.trim();
709                 }
710             }
711             Key keyTmp = keystore.getKey(identifier, password == null 
712                                          ? new char[]{} : password.toCharArray());
713             if (!(keyTmp instanceof PrivateKey)) {
714                 String msg = "Key is not a private key, alias: [" + identifier + "]";
715                 String logMsg = createKeyStoreErrorMessage(keystore);
716                 LOG.error(msg + logMsg);
717                 throw new WSSecurityException(msg);
718             }
719             return (PrivateKey) keyTmp;
720         } catch (KeyStoreException ex) {
721             throw new WSSecurityException(
722                 WSSecurityException.FAILURE, "noPrivateKey", new Object[]{ex.getMessage()}, ex
723             );
724         } catch (UnrecoverableKeyException ex) {
725             throw new WSSecurityException(
726                 WSSecurityException.FAILURE, "noPrivateKey", new Object[]{ex.getMessage()}, ex
727             );
728         } catch (NoSuchAlgorithmException ex) {
729             throw new WSSecurityException(
730                 WSSecurityException.FAILURE, "noPrivateKey", new Object[]{ex.getMessage()}, ex
731             );
732         }
733     }
734     
735     /**
736      * Evaluate whether a given certificate chain should be trusted.
737      * Uses the CertPath API to validate a given certificate chain.
738      *
739      * @param certs Certificate chain to validate
740      * @return true if the certificate chain is valid, false otherwise
741      * @throws WSSecurityException
742      */
743     @Deprecated
744     public boolean verifyTrust(X509Certificate[] certs) throws WSSecurityException {
745         return verifyTrust(certs, false);
746     }
747     
748     /**
749      * Evaluate whether a given certificate chain should be trusted.
750      * Uses the CertPath API to validate a given certificate chain.
751      *
752      * @param certs Certificate chain to validate
753      * @param enableRevocation whether to enable CRL verification or not
754      * @return true if the certificate chain is valid, false otherwise
755      * @throws WSSecurityException
756      */
757     public boolean verifyTrust(
758         X509Certificate[] certs, 
759         boolean enableRevocation
760     ) throws WSSecurityException {
761         try {
762             // Generate cert path
763             List<X509Certificate> certList = Arrays.asList(certs);
764             CertPath path = getCertificateFactory().generateCertPath(certList);
765 
766             Set<TrustAnchor> set = new HashSet<TrustAnchor>();
767             if (truststore != null) {
768                 Enumeration<String> truststoreAliases = truststore.aliases();
769                 while (truststoreAliases.hasMoreElements()) {
770                     String alias = truststoreAliases.nextElement();
771                     X509Certificate cert = 
772                         (X509Certificate) truststore.getCertificate(alias);
773                     if (cert != null) {
774                         TrustAnchor anchor = 
775                             new TrustAnchor(cert, cert.getExtensionValue(NAME_CONSTRAINTS_OID));
776                         set.add(anchor);
777                     }
778                 }
779             }
780 
781             //
782             // Add certificates from the keystore - only if there is no TrustStore, apart from
783             // the case that the truststore is the JDK CA certs. This behaviour is preserved
784             // for backwards compatibility reasons
785             //
786             if (keystore != null && (truststore == null || loadCACerts)) {
787                 Enumeration<String> aliases = keystore.aliases();
788                 while (aliases.hasMoreElements()) {
789                     String alias = aliases.nextElement();
790                     X509Certificate cert = 
791                         (X509Certificate) keystore.getCertificate(alias);
792                     if (cert != null) {
793                         TrustAnchor anchor = 
794                             new TrustAnchor(cert, cert.getExtensionValue(NAME_CONSTRAINTS_OID));
795                         set.add(anchor);
796                     }
797                 }
798             }
799 
800             PKIXParameters param = new PKIXParameters(set);
801             param.setRevocationEnabled(enableRevocation);
802             if (enableRevocation && crlCertStore != null) {
803                 param.addCertStore(crlCertStore);
804             }
805 
806             // Verify the trust path using the above settings
807             String provider = getCryptoProvider();
808             CertPathValidator validator = null;
809             if (provider == null || provider.length() == 0) {
810                 validator = CertPathValidator.getInstance("PKIX");
811             } else {
812                 validator = CertPathValidator.getInstance("PKIX", provider);
813             }
814             validator.validate(path, param);
815             return true;
816         } catch (java.security.NoSuchProviderException e) {
817                 throw new WSSecurityException(
818                     WSSecurityException.FAILURE, "certpath",
819                     new Object[] { e.getMessage() }, e
820                 );
821         } catch (java.security.NoSuchAlgorithmException e) {
822                 throw new WSSecurityException(
823                     WSSecurityException.FAILURE,
824                     "certpath", new Object[] { e.getMessage() },
825                     e
826                 );
827         } catch (java.security.cert.CertificateException e) {
828                 throw new WSSecurityException(
829                     WSSecurityException.FAILURE, "certpath", 
830                     new Object[] { e.getMessage() }, e
831                 );
832         } catch (java.security.InvalidAlgorithmParameterException e) {
833                 throw new WSSecurityException(
834                     WSSecurityException.FAILURE, "certpath",
835                     new Object[] { e.getMessage() }, e
836                 );
837         } catch (java.security.cert.CertPathValidatorException e) {
838                 throw new WSSecurityException(
839                     WSSecurityException.FAILURE, "certpath",
840                     new Object[] { e.getMessage() }, e
841                 );
842         } catch (java.security.KeyStoreException e) {
843                 throw new WSSecurityException(
844                     WSSecurityException.FAILURE, "certpath",
845                     new Object[] { e.getMessage() }, e
846                 );
847         } catch (NullPointerException e) {
848                 // NPE thrown by JDK 1.7 for one of the test cases
849                 throw new WSSecurityException(
850                     WSSecurityException.FAILURE, "certpath",
851                     new Object[] { e.getMessage() }, e
852                 );
853         }
854     }
855     
856     /**
857      * Evaluate whether a given public key should be trusted.
858      * 
859      * @param publicKey The PublicKey to be evaluated
860      * @return whether the PublicKey parameter is trusted or not
861      */
862     public boolean verifyTrust(PublicKey publicKey) throws WSSecurityException {
863         //
864         // If the public key is null, do not trust the signature
865         //
866         if (publicKey == null) {
867             return false;
868         }
869         
870         //
871         // Search the keystore for the transmitted public key (direct trust)
872         //
873         boolean trust = findPublicKeyInKeyStore(publicKey, keystore);
874         if (trust) {
875             return true;
876         } else {
877             //
878             // Now search the truststore for the transmitted public key (direct trust)
879             //
880             trust = findPublicKeyInKeyStore(publicKey, truststore);
881             if (trust) {
882                 return true;
883             }
884         }
885         return false;
886     }
887     
888     /**
889      * Get an X509 Certificate (chain) according to a given serial number and issuer string.
890      *
891      * @param issuer The Issuer String
892      * @param serialNumber The serial number of the certificate
893      * @return an X509 Certificate (chain) corresponding to the found certificate(s)
894      * @throws WSSecurityException
895      */
896     private X509Certificate[] getX509Certificates(
897         String issuer, 
898         BigInteger serialNumber
899     ) throws WSSecurityException {
900         //
901         // Convert the subject DN to a java X500Principal object first. This is to ensure
902         // interop with a DN constructed from .NET, where e.g. it uses "S" instead of "ST".
903         // Then convert it to a BouncyCastle X509Name, which will order the attributes of
904         // the DN in a particular way (see WSS-168). If the conversion to an X500Principal
905         // object fails (e.g. if the DN contains "E" instead of "EMAILADDRESS"), then fall
906         // back on a direct conversion to a BC X509Name
907         //
908         Object issuerName = null;
909         try {
910             X500Principal issuerRDN = new X500Principal(issuer);
911             issuerName = createBCX509Name(issuerRDN.getName());
912         } catch (java.lang.IllegalArgumentException ex) {
913             issuerName = createBCX509Name(issuer);
914         }
915         Certificate[] certs = null;
916         if (keystore != null) {
917             certs = getCertificates(issuerName, serialNumber, keystore);
918         }
919 
920         //If we can't find the issuer in the keystore then look at the truststore
921         if ((certs == null || certs.length == 0) && truststore != null) {
922             certs = getCertificates(issuerName, serialNumber, truststore);
923         }
924         
925         if ((certs == null || certs.length == 0)) {
926             return null;
927         }
928         
929         X509Certificate[] x509certs = new X509Certificate[certs.length];
930         for (int i = 0; i < certs.length; i++) {
931             x509certs[i] = (X509Certificate) certs[i];
932         }
933         return x509certs;
934     }
935     
936     /**
937      * Get an X509 Certificate (chain) of the X500Principal argument in the supplied KeyStore 
938      * @param subjectRDN either an X500Principal or a BouncyCastle X509Name instance.
939      * @param store The KeyStore
940      * @return an X509 Certificate (chain)
941      * @throws WSSecurityException
942      */
943     private Certificate[] getCertificates(
944         Object issuerRDN, 
945         BigInteger serialNumber, 
946         KeyStore store
947     ) throws WSSecurityException {
948         try {
949             for (Enumeration<String> e = store.aliases(); e.hasMoreElements();) {
950                 String alias = e.nextElement();
951                 Certificate cert = null;
952                 Certificate[] certs = store.getCertificateChain(alias);
953                 if (certs == null || certs.length == 0) {
954                     // no cert chain, so lets check if getCertificate gives us a result.
955                     cert = store.getCertificate(alias);
956                     if (cert == null) {
957                         continue;
958                     }
959                     certs = new Certificate[]{cert};
960                 } else {
961                     cert = certs[0];
962                 }
963                 if (cert instanceof X509Certificate) {
964                     X509Certificate x509cert = (X509Certificate) cert;
965                     if (x509cert.getSerialNumber().compareTo(serialNumber) == 0) {
966                         Object certName = 
967                             createBCX509Name(x509cert.getIssuerX500Principal().getName());
968                         if (certName.equals(issuerRDN)) {
969                             return certs;
970                         }
971                     }
972                 }
973             }
974         } catch (KeyStoreException e) {
975             throw new WSSecurityException(
976                 WSSecurityException.FAILURE, "keystore", null, e
977             );
978         }
979         return new Certificate[]{};
980     }
981     
982     /**
983      * Get an X509 Certificate (chain) according to a given Thumbprint.
984      *
985      * @param thumbprint The SHA1 thumbprint info bytes
986      * @return the X509 Certificate (chain) that was found (can be null)
987      * @throws WSSecurityException if problems during keystore handling or wrong certificate
988      */
989     private X509Certificate[] getX509Certificates(byte[] thumbprint) throws WSSecurityException {
990         MessageDigest sha = null;
991         
992         try {
993             sha = MessageDigest.getInstance("SHA1");
994         } catch (NoSuchAlgorithmException e) {
995             throw new WSSecurityException(
996                 WSSecurityException.FAILURE, "noSHA1availabe", null, e
997             );
998         }
999         Certificate[] certs = null;
1000         if (keystore != null) {
1001             certs = getCertificates(thumbprint, keystore, sha);
1002         }
1003 
1004         //If we can't find the issuer in the keystore then look at the truststore
1005         if ((certs == null || certs.length == 0) && truststore != null) {
1006             certs = getCertificates(thumbprint, truststore, sha);
1007         }
1008         
1009         if ((certs == null || certs.length == 0)) {
1010             return null;
1011         }
1012         
1013         X509Certificate[] x509certs = new X509Certificate[certs.length];
1014         for (int i = 0; i < certs.length; i++) {
1015             x509certs[i] = (X509Certificate) certs[i];
1016         }
1017         return x509certs;
1018     }
1019 
1020     /**
1021      * Get an X509 Certificate (chain) of the X500Principal argument in the supplied KeyStore 
1022      * @param subjectRDN either an X500Principal or a BouncyCastle X509Name instance.
1023      * @param store The KeyStore
1024      * @return an X509 Certificate (chain)
1025      * @throws WSSecurityException
1026      */
1027     private Certificate[] getCertificates(
1028         byte[] thumbprint, 
1029         KeyStore store,
1030         MessageDigest sha
1031     ) throws WSSecurityException {
1032         try {
1033             for (Enumeration<String> e = store.aliases(); e.hasMoreElements();) {
1034                 String alias = e.nextElement();
1035                 Certificate cert = null;
1036                 Certificate[] certs = store.getCertificateChain(alias);
1037                 if (certs == null || certs.length == 0) {
1038                     // no cert chain, so lets check if getCertificate gives us a result.
1039                     cert = store.getCertificate(alias);
1040                     if (cert == null) {
1041                         continue;
1042                     }
1043                     certs = new Certificate[]{cert};
1044                 } else {
1045                     cert = certs[0];
1046                 }
1047                 if (cert instanceof X509Certificate) {
1048                     X509Certificate x509cert = (X509Certificate) cert;
1049                     try {
1050                         sha.update(x509cert.getEncoded());
1051                     } catch (CertificateEncodingException ex) {
1052                         throw new WSSecurityException(
1053                             WSSecurityException.SECURITY_TOKEN_UNAVAILABLE, "encodeError",
1054                             null, ex
1055                         );
1056                     }
1057                     byte[] data = sha.digest();
1058 
1059                     if (Arrays.equals(data, thumbprint)) {
1060                         return certs;
1061                     }
1062                 }
1063             }
1064         } catch (KeyStoreException e) {
1065             throw new WSSecurityException(
1066                 WSSecurityException.FAILURE, "keystore", null, e
1067             );
1068         }
1069         return new Certificate[]{};
1070     }
1071     
1072     /**
1073      * Get an X509 Certificate (chain) according to a given SubjectKeyIdentifier.
1074      *
1075      * @param skiBytes The SKI bytes
1076      * @return the X509 certificate (chain) that was found (can be null)
1077      */
1078     private X509Certificate[] getX509CertificatesSKI(byte[] skiBytes) throws WSSecurityException {
1079         Certificate[] certs = null;
1080         if (keystore != null) {
1081             certs = getCertificates(skiBytes, keystore);
1082         }
1083 
1084         //If we can't find the issuer in the keystore then look at the truststore
1085         if ((certs == null || certs.length == 0) && truststore != null) {
1086             certs = getCertificates(skiBytes, truststore);
1087         }
1088         
1089         if ((certs == null || certs.length == 0)) {
1090             return null;
1091         }
1092         
1093         X509Certificate[] x509certs = new X509Certificate[certs.length];
1094         for (int i = 0; i < certs.length; i++) {
1095             x509certs[i] = (X509Certificate) certs[i];
1096         }
1097         return x509certs;
1098     }
1099     
1100     /**
1101      * Get an X509 Certificate (chain) of the X500Principal argument in the supplied KeyStore 
1102      * @param subjectRDN either an X500Principal or a BouncyCastle X509Name instance.
1103      * @param store The KeyStore
1104      * @return an X509 Certificate (chain)
1105      * @throws WSSecurityException
1106      */
1107     private Certificate[] getCertificates(
1108         byte[] skiBytes, 
1109         KeyStore store
1110     ) throws WSSecurityException {
1111         try {
1112             for (Enumeration<String> e = store.aliases(); e.hasMoreElements();) {
1113                 String alias = e.nextElement();
1114                 Certificate cert = null;
1115                 Certificate[] certs = store.getCertificateChain(alias);
1116                 if (certs == null || certs.length == 0) {
1117                     // no cert chain, so lets check if getCertificate gives us a result.
1118                     cert = store.getCertificate(alias);
1119                     if (cert == null) {
1120                         continue;
1121                     }
1122                     certs = new Certificate[]{cert};
1123                 } else {
1124                     cert = certs[0];
1125                 }
1126                 if (cert instanceof X509Certificate) {
1127                     X509Certificate x509cert = (X509Certificate) cert;
1128                     byte[] data = getSKIBytesFromCert(x509cert);
1129                     if (data.length == skiBytes.length && Arrays.equals(data, skiBytes)) {
1130                         return certs;
1131                     }
1132                 }
1133             }
1134         } catch (KeyStoreException e) {
1135             throw new WSSecurityException(
1136                 WSSecurityException.FAILURE, "keystore", null, e
1137             );
1138         }
1139         return new Certificate[]{};
1140     }
1141     
1142     /**
1143      * Get an X509 Certificate (chain) according to a given DN of the subject of the certificate
1144      *
1145      * @param subjectDN The DN of subject to look for
1146      * @return An X509 Certificate (chain) with the same DN as given in the parameters
1147      * @throws WSSecurityException
1148      */
1149     private X509Certificate[] getX509CertificatesSubjectDN(String subjectDN) throws WSSecurityException {
1150         //
1151         // Convert the subject DN to a java X500Principal object first. This is to ensure
1152         // interop with a DN constructed from .NET, where e.g. it uses "S" instead of "ST".
1153         // Then convert it to a BouncyCastle X509Name, which will order the attributes of
1154         // the DN in a particular way (see WSS-168). If the conversion to an X500Principal
1155         // object fails (e.g. if the DN contains "E" instead of "EMAILADDRESS"), then fall
1156         // back on a direct conversion to a BC X509Name
1157         //
1158         Object subject;
1159         try {
1160             X500Principal subjectRDN = new X500Principal(subjectDN);
1161             subject = createBCX509Name(subjectRDN.getName());
1162         } catch (java.lang.IllegalArgumentException ex) {
1163             subject = createBCX509Name(subjectDN);
1164         }
1165         
1166         Certificate[] certs = null;
1167         if (keystore != null) {
1168             certs = getCertificates(subject, keystore);
1169         }
1170 
1171         //If we can't find the issuer in the keystore then look at the truststore
1172         if ((certs == null || certs.length == 0) && truststore != null) {
1173             certs = getCertificates(subject, truststore);
1174         }
1175         
1176         if ((certs == null || certs.length == 0)) {
1177             return null;
1178         }
1179         
1180         X509Certificate[] x509certs = new X509Certificate[certs.length];
1181         for (int i = 0; i < certs.length; i++) {
1182             x509certs[i] = (X509Certificate) certs[i];
1183         }
1184         return x509certs;
1185     }
1186     
1187     /**
1188      * Get an X509 Certificate (chain) that correspond to the identifier. For this implementation,
1189      * the identifier corresponds to the KeyStore alias.
1190      * 
1191      * @param identifier The identifier that corresponds to the returned certs
1192      * @return an X509 Certificate (chain) that corresponds to the identifier
1193      */
1194     private X509Certificate[] getX509Certificates(String identifier) throws WSSecurityException {
1195         Certificate[] certs = null;
1196         try {
1197             if (keystore != null) {
1198                 // There's a chance that there can only be a set of trust stores
1199                 certs = keystore.getCertificateChain(identifier);
1200                 if (certs == null || certs.length == 0) {
1201                     // no cert chain, so lets check if getCertificate gives us a result.
1202                     Certificate cert = keystore.getCertificate(identifier);
1203                     if (cert != null) {
1204                         certs = new Certificate[]{cert};
1205                     }
1206                 }
1207             }
1208 
1209             if (certs == null && truststore != null) {
1210                 // Now look into the trust stores
1211                 certs = truststore.getCertificateChain(identifier);
1212                 if (certs == null) {
1213                     Certificate cert = truststore.getCertificate(identifier);
1214                     if (cert != null) {
1215                         certs = new Certificate[]{cert};
1216                     }
1217                 }
1218             }
1219 
1220             if (certs == null) {
1221                 return null;
1222             }
1223         } catch (KeyStoreException e) {
1224             throw new WSSecurityException(WSSecurityException.FAILURE, "keystore", null, e);
1225         }
1226 
1227         X509Certificate[] x509certs = new X509Certificate[certs.length];
1228         for (int i = 0; i < certs.length; i++) {
1229             x509certs[i] = (X509Certificate) certs[i];
1230         }
1231         return x509certs;
1232     }
1233     
1234     /**
1235      * Find the Public Key in a keystore. 
1236      */
1237     private boolean findPublicKeyInKeyStore(PublicKey publicKey, KeyStore keyStoreToSearch) {
1238         if (keyStoreToSearch == null) {
1239             return false;
1240         }
1241         try {
1242             for (Enumeration<String> e = keyStoreToSearch.aliases(); e.hasMoreElements();) {
1243                 String alias = e.nextElement();
1244                 Certificate[] certs = keyStoreToSearch.getCertificateChain(alias);
1245                 Certificate cert;
1246                 if (certs == null || certs.length == 0) {
1247                     // no cert chain, so lets check if getCertificate gives us a result.
1248                     cert = keyStoreToSearch.getCertificate(alias);
1249                     if (cert == null) {
1250                         continue;
1251                     }
1252                 } else {
1253                     cert = certs[0];
1254                 }
1255                 if (!(cert instanceof X509Certificate)) {
1256                     continue;
1257                 }
1258                 X509Certificate x509cert = (X509Certificate) cert;
1259                 if (publicKey.equals(x509cert.getPublicKey())) {
1260                     return true;
1261                 }
1262             }
1263         } catch (KeyStoreException e) {
1264             return false;
1265         }
1266         return false;
1267     }
1268     
1269     /**
1270      * Get an X509 Certificate (chain) of the X500Principal argument in the supplied KeyStore 
1271      * @param subjectRDN either an X500Principal or a BouncyCastle X509Name instance.
1272      * @param store The KeyStore
1273      * @return an X509 Certificate (chain)
1274      * @throws WSSecurityException
1275      */
1276     private Certificate[] getCertificates(Object subjectRDN, KeyStore store) 
1277         throws WSSecurityException {
1278         try {
1279             for (Enumeration<String> e = store.aliases(); e.hasMoreElements();) {
1280                 String alias = e.nextElement();
1281                 Certificate cert = null;
1282                 Certificate[] certs = store.getCertificateChain(alias);
1283                 if (certs == null || certs.length == 0) {
1284                     // no cert chain, so lets check if getCertificate gives us a result.
1285                     cert = store.getCertificate(alias);
1286                     if (cert == null) {
1287                         continue;
1288                     }
1289                     certs = new Certificate[]{cert};
1290                 } else {
1291                     cert = certs[0];
1292                 }
1293                 if (cert instanceof X509Certificate) {
1294                     X500Principal foundRDN = ((X509Certificate) cert).getSubjectX500Principal();
1295                     Object certName = createBCX509Name(foundRDN.getName());
1296 
1297                     if (subjectRDN.equals(certName)) {
1298                         return certs;
1299                     }
1300                 }
1301             }
1302         } catch (KeyStoreException e) {
1303             throw new WSSecurityException(
1304                 WSSecurityException.FAILURE, "keystore", null, e
1305             );
1306         }
1307         return new Certificate[]{};
1308     }
1309     
1310     private static String createKeyStoreErrorMessage(KeyStore keystore) throws KeyStoreException {
1311         Enumeration<String> aliases = keystore.aliases();
1312         StringBuilder sb = new StringBuilder(keystore.size() * 7);
1313         boolean firstAlias = true;
1314         while (aliases.hasMoreElements()) {
1315             if (!firstAlias) {
1316                 sb.append(", ");
1317             }
1318             sb.append(aliases.nextElement());
1319             firstAlias = false;
1320         }
1321         String msg = " in keystore of type [" + keystore.getType()
1322             + "] from provider [" + keystore.getProvider()
1323             + "] with size [" + keystore.size() + "] and aliases: {"
1324             + sb.toString() + "}";
1325         return msg;
1326     }
1327     
1328     /**
1329      * Get an implementation-specific identifier that corresponds to the X509Certificate. In
1330      * this case, the identifier is the KeyStore alias.
1331      * @param cert The X509Certificate corresponding to the returned identifier
1332      * @param store The KeyStore to search
1333      * @return An implementation-specific identifier that corresponds to the X509Certificate
1334      */
1335     private String getIdentifier(X509Certificate cert, KeyStore store)
1336         throws WSSecurityException {
1337         try {
1338             for (Enumeration<String> e = store.aliases(); e.hasMoreElements();) {
1339                 String alias = e.nextElement();
1340                 
1341                 Certificate[] certs = store.getCertificateChain(alias);
1342                 Certificate retrievedCert = null;
1343                 if (certs == null || certs.length == 0) {
1344                     // no cert chain, so lets check if getCertificate gives us a  result.
1345                     retrievedCert = store.getCertificate(alias);
1346                     if (retrievedCert == null) {
1347                         continue;
1348                     }
1349                 } else {
1350                     retrievedCert = certs[0];
1351                 }
1352                 if (!(retrievedCert instanceof X509Certificate)) {
1353                     continue;
1354                 }
1355                 if (retrievedCert.equals(cert)) {
1356                     return alias;
1357                 }
1358             }
1359         } catch (KeyStoreException e) {
1360             throw new WSSecurityException(WSSecurityException.FAILURE, "keystore", null, e);
1361         }
1362         return null;
1363     }
1364     
1365     /**
1366      * Get a password from the CallbackHandler
1367      * @param identifier The identifier to give to the Callback
1368      * @param cb The CallbackHandler
1369      * @return The password retrieved from the CallbackHandler
1370      * @throws WSSecurityException
1371      */
1372     private String getPassword(
1373         String identifier,
1374         CallbackHandler cb
1375     ) throws WSSecurityException {
1376         WSPasswordCallback pwCb = 
1377             new WSPasswordCallback(identifier, WSPasswordCallback.DECRYPT);
1378         try {
1379             Callback[] callbacks = new Callback[]{pwCb};
1380             cb.handle(callbacks);
1381         } catch (IOException e) {
1382             throw new WSSecurityException(
1383                 WSSecurityException.FAILURE,
1384                 "noPassword",
1385                 new Object[]{identifier}, 
1386                 e
1387             );
1388         } catch (UnsupportedCallbackException e) {
1389             throw new WSSecurityException(
1390                 WSSecurityException.FAILURE,
1391                 "noPassword",
1392                 new Object[]{identifier}, 
1393                 e
1394             );
1395         }
1396 
1397         return pwCb.getPassword();
1398     }
1399     
1400     
1401 }