View Javadoc

1   /*
2    * Copyright 2006 the original author or authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.springframework.ws.soap.security.xwss.callback;
18  
19  import java.io.IOException;
20  import java.math.BigInteger;
21  import java.security.GeneralSecurityException;
22  import java.security.InvalidAlgorithmParameterException;
23  import java.security.KeyStore;
24  import java.security.PrivateKey;
25  import java.security.PublicKey;
26  import java.security.cert.CertPathBuilder;
27  import java.security.cert.CertPathBuilderException;
28  import java.security.cert.Certificate;
29  import java.security.cert.CertificateExpiredException;
30  import java.security.cert.CertificateNotYetValidException;
31  import java.security.cert.PKIXBuilderParameters;
32  import java.security.cert.X509CertSelector;
33  import java.security.cert.X509Certificate;
34  import java.util.Arrays;
35  import java.util.Enumeration;
36  import javax.crypto.SecretKey;
37  
38  import com.sun.xml.wss.impl.callback.CertificateValidationCallback;
39  import com.sun.xml.wss.impl.callback.DecryptionKeyCallback;
40  import com.sun.xml.wss.impl.callback.EncryptionKeyCallback;
41  import com.sun.xml.wss.impl.callback.SignatureKeyCallback;
42  import com.sun.xml.wss.impl.callback.SignatureVerificationKeyCallback;
43  import org.apache.xml.security.utils.RFC2253Parser;
44  
45  import org.springframework.beans.factory.InitializingBean;
46  import org.springframework.ws.soap.security.support.KeyStoreUtils;
47  
48  /**
49   * Callback handler that uses Java Security <code>KeyStore</code>s to handle cryptographic callbacks. Allows for
50   * specific key stores to be set for various cryptographic operations.
51   * <p/>
52   * This handler requires one or more key stores to be set. You can configure them in your application context by using a
53   * <code>KeyStoreFactoryBean</code>. The exact stores to be set depends on the cryptographic operations that are to be
54   * performed by this handler. The table underneath show the key store to be used for each operation: <table border="1">
55   * <tr> <td><strong>Cryptographic operation</strong></td> <td><strong>Key store used</strong></td> </tr> <tr>
56   * <td>Certificate validation</td> <td>first <code>keyStore</code>, then <code>trustStore</code></td> </tr> <tr>
57   * <td>Decryption based on private key</td> <td><code>keyStore</code></td> </tr> <tr> <td>Decryption based on symmetric
58   * key</td> <td><code>symmetricStore</code></td> </tr> <tr> <td>Encryption based on certificate</td>
59   * <td><code>trustStore</code></td> </tr> <tr> <td>Encryption based on symmetric key</td>
60   * <td><code>symmetricStore</code></td> </tr> <tr> <td>Signing</td> <td><code>keyStore</code></td> </tr> <tr>
61   * <td>Signature verification</td> <td><code>trustStore</code></td> </tr> </table>
62   * <p/>
63   * <h3>Default key stores</h3> If the <code>symmetricStore</code> is not set, it will default to the
64   * <code>keyStore</code>. If the key or trust store is not set, this handler will use the standard Java mechanism to
65   * load or create it. See {@link #loadDefaultKeyStore()} and {@link #loadDefaultTrustStore()}.
66   * <p/>
67   * <h3>Examples</h3> For instance, if you want to use the <code>KeyStoreCallbackHandler</code> to validate incoming
68   * certificates or signatures, you would use a trust store, like so:
69   * <pre>
70   * &lt;bean id="keyStoreHandler" class="org.springframework.ws.soap.security.xwss.callback.KeyStoreCallbackHandler"&gt;
71   *     &lt;property name="trustStore" ref="trustStore"/&gt;
72   * &lt;/bean&gt;
73   * <p/>
74   * &lt;bean id="trustStore" class="org.springframework.ws.soap.security.support.KeyStoreFactoryBean"&gt;
75   *     &lt;property name="location" value="classpath:truststore.jks"/&gt;
76   *     &lt;property name="password" value="changeit"/&gt;
77   * &lt;/bean&gt;
78   * </pre>
79   * If you want to use it to decrypt incoming certificates or sign outgoing messages, you would use a key store, like
80   * so:
81   * <pre>
82   * &lt;bean id="keyStoreHandler" class="org.springframework.ws.soap.security.xwss.callback.KeyStoreCallbackHandler"&gt;
83   *     &lt;property name="keyStore" ref="keyStore"/&gt;
84   *     &lt;property name="privateKeyPassword" value="changeit"/&gt;
85   * &lt;/bean&gt;
86   * <p/>
87   * &lt;bean id="keyStore" class="org.springframework.ws.soap.security.support.KeyStoreFactoryBean"&gt;
88   *     &lt;property name="location" value="classpath:keystore.jks"/&gt;
89   *     &lt;property name="password" value="changeit"/&gt;
90   * &lt;/bean&gt;
91   * </pre>
92   * <p/>
93   * <h3>Handled callbacks</h3> This class handles <code>CertificateValidationCallback</code>s,
94   * <code>DecryptionKeyCallback</code>s, <code>EncryptionKeyCallback</code>s, <code>SignatureKeyCallback</code>s, and
95   * <code>SignatureVerificationKeyCallback</code>s. It throws an <code>UnsupportedCallbackException</code> for others.
96   *
97   * @author Arjen Poutsma
98   * @see KeyStore
99   * @see org.springframework.ws.soap.security.support.KeyStoreFactoryBean
100  * @see CertificateValidationCallback
101  * @see DecryptionKeyCallback
102  * @see EncryptionKeyCallback
103  * @see SignatureKeyCallback
104  * @see SignatureVerificationKeyCallback
105  * @see <a href="http://java.sun.com/j2se/1.4.2/docs/guide/security/jsse/JSSERefGuide.html#X509TrustManager">The
106  *      standard Java trust store mechanism</a>
107  * @since 1.0.0
108  */
109 public class KeyStoreCallbackHandler extends CryptographyCallbackHandler implements InitializingBean {
110 
111     private static final String X_509_CERTIFICATE_TYPE = "X.509";
112 
113     private static final String SUBJECT_KEY_IDENTIFIER_OID = "2.5.29.14";
114 
115     private KeyStore keyStore;
116 
117     private KeyStore symmetricStore;
118 
119     private KeyStore trustStore;
120 
121     private String defaultAlias;
122 
123     private char[] privateKeyPassword;
124 
125     private char[] symmetricKeyPassword;
126 
127     private static X509Certificate getCertificate(String alias, KeyStore store) throws IOException {
128         try {
129             return (X509Certificate) store.getCertificate(alias);
130         }
131         catch (GeneralSecurityException e) {
132             throw new IOException(e.getMessage());
133         }
134     }
135 
136     private static X509Certificate getCertificate(PublicKey pk, KeyStore store) throws IOException {
137         try {
138             Enumeration aliases = store.aliases();
139             while (aliases.hasMoreElements()) {
140                 String alias = (String) aliases.nextElement();
141                 Certificate cert = store.getCertificate(alias);
142                 if (cert == null || !X_509_CERTIFICATE_TYPE.equals(cert.getType())) {
143                     continue;
144                 }
145                 X509Certificate x509Cert = (X509Certificate) cert;
146                 if (x509Cert.getPublicKey().equals(pk)) {
147                     return x509Cert;
148                 }
149             }
150         }
151         catch (GeneralSecurityException e) {
152             throw new IOException(e.getMessage());
153         }
154         return null;
155     }
156 
157     /** Sets the key store alias for the default certificate and private key. */
158     public void setDefaultAlias(String defaultAlias) {
159         this.defaultAlias = defaultAlias;
160     }
161 
162     /**
163      * Sets the default key store. This property is required for decription based on private keys, and signing. If this
164      * property is not set, a default key store is loaded.
165      *
166      * @see org.springframework.ws.soap.security.support.KeyStoreFactoryBean
167      * @see #loadDefaultTrustStore()
168      */
169     public void setKeyStore(KeyStore keyStore) {
170         this.keyStore = keyStore;
171     }
172 
173     /**
174      * Sets the password used to retrieve private keys from the keystore. This property is required for decription based
175      * on private keys, and signing.
176      */
177     public void setPrivateKeyPassword(String privateKeyPassword) {
178         if (privateKeyPassword != null) {
179             this.privateKeyPassword = privateKeyPassword.toCharArray();
180         }
181     }
182 
183     /**
184      * Sets the password used to retrieve keys from the symmetric keystore. If this property is not set, it default to
185      * the private key password.
186      *
187      * @see #setPrivateKeyPassword(String)
188      */
189     public void setSymmetricKeyPassword(String symmetricKeyPassword) {
190         if (symmetricKeyPassword != null) {
191             this.symmetricKeyPassword = symmetricKeyPassword.toCharArray();
192         }
193     }
194 
195     /**
196      * Sets the key store used for encryption and decryption using symmetric keys. If this property is not set, it
197      * defaults to the <code>keyStore</code> property.
198      *
199      * @see org.springframework.ws.soap.security.support.KeyStoreFactoryBean
200      * @see #setKeyStore(java.security.KeyStore)
201      */
202     public void setSymmetricStore(KeyStore symmetricStore) {
203         this.symmetricStore = symmetricStore;
204     }
205 
206     /**
207      * Sets the key store used for signature verifications and encryptions. If this property is not set, a default key
208      * store will be loaded.
209      *
210      * @see org.springframework.ws.soap.security.support.KeyStoreFactoryBean
211      * @see #loadDefaultTrustStore()
212      */
213     public void setTrustStore(KeyStore trustStore) {
214         this.trustStore = trustStore;
215     }
216 
217     public void afterPropertiesSet() throws Exception {
218         if (keyStore == null) {
219             loadDefaultKeyStore();
220         }
221         if (trustStore == null) {
222             loadDefaultTrustStore();
223         }
224         if (symmetricStore == null) {
225             symmetricStore = keyStore;
226         }
227         if (symmetricKeyPassword == null) {
228             symmetricKeyPassword = privateKeyPassword;
229         }
230     }
231 
232     protected final void handleAliasPrivKeyCertRequest(SignatureKeyCallback callback,
233                                                        SignatureKeyCallback.AliasPrivKeyCertRequest request)
234             throws IOException {
235         PrivateKey privateKey = getPrivateKey(request.getAlias());
236         X509Certificate certificate = getCertificate(request.getAlias());
237         request.setPrivateKey(privateKey);
238         request.setX509Certificate(certificate);
239     }
240 
241     protected final void handleAliasSymmetricKeyRequest(DecryptionKeyCallback callback,
242                                                         DecryptionKeyCallback.AliasSymmetricKeyRequest request)
243             throws IOException {
244         SecretKey secretKey = getSymmetricKey(request.getAlias());
245         request.setSymmetricKey(secretKey);
246     }
247 
248     //
249     // Encryption
250     //
251 
252     protected final void handleAliasSymmetricKeyRequest(EncryptionKeyCallback callback,
253                                                         EncryptionKeyCallback.AliasSymmetricKeyRequest request)
254             throws IOException {
255         SecretKey secretKey = getSymmetricKey(request.getAlias());
256         request.setSymmetricKey(secretKey);
257     }
258 
259     protected final void handleAliasX509CertificateRequest(EncryptionKeyCallback callback,
260                                                            EncryptionKeyCallback.AliasX509CertificateRequest request)
261             throws IOException {
262         X509Certificate certificate = getCertificateFromTrustStore(request.getAlias());
263         request.setX509Certificate(certificate);
264     }
265 
266     //
267     // Certificate validation
268     //
269 
270     protected final void handleCertificateValidationCallback(CertificateValidationCallback callback) {
271         callback.setValidator(new KeyStoreCertificateValidator());
272     }
273 
274     //
275     // Signing
276     //
277 
278     protected final void handleDefaultPrivKeyCertRequest(SignatureKeyCallback callback,
279                                                          SignatureKeyCallback.DefaultPrivKeyCertRequest request)
280             throws IOException {
281         PrivateKey privateKey = getPrivateKey(defaultAlias);
282         X509Certificate certificate = getCertificate(defaultAlias);
283         request.setPrivateKey(privateKey);
284         request.setX509Certificate(certificate);
285     }
286 
287     protected final void handleDefaultX509CertificateRequest(EncryptionKeyCallback callback,
288                                                              EncryptionKeyCallback.DefaultX509CertificateRequest request)
289             throws IOException {
290         X509Certificate certificate = getCertificateFromTrustStore(defaultAlias);
291         request.setX509Certificate(certificate);
292     }
293 
294     protected final void handlePublicKeyBasedPrivKeyCertRequest(SignatureKeyCallback callback,
295                                                                 SignatureKeyCallback.PublicKeyBasedPrivKeyCertRequest request)
296             throws IOException {
297         PrivateKey privateKey = getPrivateKey(request.getPublicKey());
298         X509Certificate certificate = getCertificate(request.getPublicKey());
299         request.setPrivateKey(privateKey);
300         request.setX509Certificate(certificate);
301     }
302 
303     //
304     // Decryption
305     //
306     protected final void handlePublicKeyBasedPrivKeyRequest(DecryptionKeyCallback callback,
307                                                             DecryptionKeyCallback.PublicKeyBasedPrivKeyRequest request)
308             throws IOException {
309         PrivateKey key = getPrivateKey(request.getPublicKey());
310         request.setPrivateKey(key);
311     }
312 
313     protected final void handlePublicKeyBasedRequest(EncryptionKeyCallback callback,
314                                                      EncryptionKeyCallback.PublicKeyBasedRequest request)
315             throws IOException {
316         X509Certificate certificate = getCertificateFromTrustStore(request.getPublicKey());
317         request.setX509Certificate(certificate);
318     }
319 
320     protected final void handlePublicKeyBasedRequest(SignatureVerificationKeyCallback callback,
321                                                      SignatureVerificationKeyCallback.PublicKeyBasedRequest request)
322             throws IOException {
323         X509Certificate certificate = getCertificateFromTrustStore(request.getPublicKey());
324         request.setX509Certificate(certificate);
325     }
326 
327     protected final void handleX509CertificateBasedRequest(DecryptionKeyCallback callback,
328                                                            DecryptionKeyCallback.X509CertificateBasedRequest request)
329             throws IOException {
330         PrivateKey privKey = getPrivateKey(request.getX509Certificate());
331         request.setPrivateKey(privKey);
332     }
333 
334     protected final void handleX509IssuerSerialBasedRequest(DecryptionKeyCallback callback,
335                                                             DecryptionKeyCallback.X509IssuerSerialBasedRequest request)
336             throws IOException {
337         PrivateKey key = getPrivateKey(request.getIssuerName(), request.getSerialNumber());
338         request.setPrivateKey(key);
339     }
340 
341     protected final void handleX509IssuerSerialBasedRequest(SignatureVerificationKeyCallback callback,
342                                                             SignatureVerificationKeyCallback.X509IssuerSerialBasedRequest request)
343             throws IOException {
344         X509Certificate certificate = getCertificateFromTrustStore(request.getIssuerName(), request.getSerialNumber());
345         request.setX509Certificate(certificate);
346     }
347 
348     protected final void handleX509SubjectKeyIdentifierBasedRequest(DecryptionKeyCallback callback,
349                                                                     DecryptionKeyCallback.X509SubjectKeyIdentifierBasedRequest request)
350             throws IOException {
351         PrivateKey key = getPrivateKey(request.getSubjectKeyIdentifier());
352         request.setPrivateKey(key);
353     }
354 
355     //
356     // Signature verification
357     //
358 
359     protected final void handleX509SubjectKeyIdentifierBasedRequest(SignatureVerificationKeyCallback callback,
360                                                                     SignatureVerificationKeyCallback.X509SubjectKeyIdentifierBasedRequest request)
361             throws IOException {
362         X509Certificate certificate = getCertificateFromTrustStore(request.getSubjectKeyIdentifier());
363         request.setX509Certificate(certificate);
364     }
365 
366     // Certificate methods
367 
368     protected X509Certificate getCertificate(String alias) throws IOException {
369         return getCertificate(alias, keyStore);
370     }
371 
372     protected X509Certificate getCertificate(PublicKey pk) throws IOException {
373         return getCertificate(pk, keyStore);
374     }
375 
376     protected X509Certificate getCertificateFromTrustStore(String alias) throws IOException {
377         return getCertificate(alias, trustStore);
378     }
379 
380     protected X509Certificate getCertificateFromTrustStore(byte[] subjectKeyIdentifier) throws IOException {
381         try {
382             Enumeration aliases = trustStore.aliases();
383             while (aliases.hasMoreElements()) {
384                 String alias = (String) aliases.nextElement();
385                 Certificate cert = trustStore.getCertificate(alias);
386                 if (cert == null || !X_509_CERTIFICATE_TYPE.equals(cert.getType())) {
387                     continue;
388                 }
389                 X509Certificate x509Cert = (X509Certificate) cert;
390                 byte[] keyId = getSubjectKeyIdentifier(x509Cert);
391                 if (keyId == null) {
392                     // Cert does not contain a key identifier
393                     continue;
394                 }
395                 if (Arrays.equals(subjectKeyIdentifier, keyId)) {
396                     return x509Cert;
397                 }
398             }
399         }
400         catch (GeneralSecurityException e) {
401             throw new IOException(e.getMessage());
402         }
403         return null;
404     }
405 
406     protected X509Certificate getCertificateFromTrustStore(PublicKey pk) throws IOException {
407         return getCertificate(pk, trustStore);
408     }
409 
410     protected X509Certificate getCertificateFromTrustStore(String issuerName, BigInteger serialNumber)
411             throws IOException {
412         try {
413             Enumeration aliases = trustStore.aliases();
414             while (aliases.hasMoreElements()) {
415                 String alias = (String) aliases.nextElement();
416                 Certificate cert = trustStore.getCertificate(alias);
417                 if (cert == null || !X_509_CERTIFICATE_TYPE.equals(cert.getType())) {
418                     continue;
419                 }
420                 X509Certificate x509Cert = (X509Certificate) cert;
421                 String thisIssuerName = RFC2253Parser.normalize(x509Cert.getIssuerDN().getName());
422                 BigInteger thisSerialNumber = x509Cert.getSerialNumber();
423                 if (thisIssuerName.equals(issuerName) && thisSerialNumber.equals(serialNumber)) {
424                     return x509Cert;
425                 }
426             }
427         }
428         catch (GeneralSecurityException e) {
429             throw new IOException(e.getMessage());
430         }
431         return null;
432     }
433 
434     // Private Key methods
435 
436     protected PrivateKey getPrivateKey(String alias) throws IOException {
437         try {
438             return (PrivateKey) keyStore.getKey(alias, privateKeyPassword);
439         }
440         catch (GeneralSecurityException e) {
441             throw new IOException(e.getMessage());
442         }
443     }
444 
445     protected PrivateKey getPrivateKey(PublicKey publicKey) throws IOException {
446         try {
447             Enumeration aliases = keyStore.aliases();
448             while (aliases.hasMoreElements()) {
449                 String alias = (String) aliases.nextElement();
450                 if (keyStore.isKeyEntry(alias)) {
451                     // Just returning the first one here
452                     return (PrivateKey) keyStore.getKey(alias, privateKeyPassword);
453                 }
454             }
455         }
456         catch (GeneralSecurityException e) {
457             throw new IOException(e.getMessage());
458         }
459         return null;
460     }
461 
462     protected PrivateKey getPrivateKey(X509Certificate certificate) throws IOException {
463         try {
464             Enumeration aliases = keyStore.aliases();
465             while (aliases.hasMoreElements()) {
466                 String alias = (String) aliases.nextElement();
467                 if (!keyStore.isKeyEntry(alias)) {
468                     continue;
469                 }
470                 Certificate cert = keyStore.getCertificate(alias);
471                 if (cert != null && cert.equals(certificate)) {
472                     return (PrivateKey) keyStore.getKey(alias, privateKeyPassword);
473                 }
474             }
475         }
476         catch (GeneralSecurityException e) {
477             throw new IOException(e.getMessage());
478         }
479         return null;
480     }
481 
482     protected PrivateKey getPrivateKey(byte[] keyIdentifier) throws IOException {
483         try {
484             Enumeration aliases = keyStore.aliases();
485             while (aliases.hasMoreElements()) {
486                 String alias = (String) aliases.nextElement();
487                 if (!keyStore.isKeyEntry(alias)) {
488                     continue;
489                 }
490                 Certificate cert = keyStore.getCertificate(alias);
491                 if (cert == null || !"X.509".equals(cert.getType())) {
492                     continue;
493                 }
494                 X509Certificate x509Cert = (X509Certificate) cert;
495                 byte[] keyId = getSubjectKeyIdentifier(x509Cert);
496                 if (keyId == null) {
497                     // Cert does not contain a key identifier
498                     continue;
499                 }
500                 if (Arrays.equals(keyIdentifier, keyId)) {
501                     return (PrivateKey) keyStore.getKey(alias, privateKeyPassword);
502                 }
503             }
504         }
505         catch (GeneralSecurityException e) {
506             throw new IOException(e.getMessage());
507         }
508         return null;
509     }
510 
511     protected PrivateKey getPrivateKey(String issuerName, BigInteger serialNumber) throws IOException {
512         try {
513             Enumeration aliases = keyStore.aliases();
514             while (aliases.hasMoreElements()) {
515                 String alias = (String) aliases.nextElement();
516                 if (!keyStore.isKeyEntry(alias)) {
517                     continue;
518                 }
519                 Certificate cert = keyStore.getCertificate(alias);
520                 if (cert == null || !"X.509".equals(cert.getType())) {
521                     continue;
522                 }
523                 X509Certificate x509Cert = (X509Certificate) cert;
524                 String thisIssuerName = RFC2253Parser.normalize(x509Cert.getIssuerDN().getName());
525                 BigInteger thisSerialNumber = x509Cert.getSerialNumber();
526                 if (thisIssuerName.equals(issuerName) && thisSerialNumber.equals(serialNumber)) {
527                     return (PrivateKey) keyStore.getKey(alias, privateKeyPassword);
528                 }
529             }
530         }
531         catch (GeneralSecurityException e) {
532             throw new IOException(e.getMessage());
533         }
534         return null;
535     }
536 
537     // Utility methods
538 
539     protected final byte[] getSubjectKeyIdentifier(X509Certificate cert) {
540         byte[] subjectKeyIdentifier = cert.getExtensionValue(SUBJECT_KEY_IDENTIFIER_OID);
541         if (subjectKeyIdentifier == null) {
542             return null;
543         }
544         byte[] dest = new byte[subjectKeyIdentifier.length - 4];
545         System.arraycopy(subjectKeyIdentifier, 4, dest, 0, subjectKeyIdentifier.length - 4);
546         return dest;
547     }
548 
549     //
550     // Symmetric key methods
551     //
552 
553     protected SecretKey getSymmetricKey(String alias) throws IOException {
554         try {
555             return (SecretKey) symmetricStore.getKey(alias, symmetricKeyPassword);
556         }
557         catch (GeneralSecurityException e) {
558             throw new IOException(e.getMessage());
559         }
560     }
561 
562     /** Loads the key store indicated by system properties. Delegates to {@link KeyStoreUtils#loadDefaultKeyStore()}. */
563     protected void loadDefaultKeyStore() {
564         try {
565             keyStore = KeyStoreUtils.loadDefaultKeyStore();
566             if (logger.isDebugEnabled()) {
567                 logger.debug("Loaded default key store");
568             }
569         }
570         catch (Exception ex) {
571             logger.warn("Could not open default key store", ex);
572         }
573     }
574 
575     /** Loads a default trust store. Delegates to {@link KeyStoreUtils#loadDefaultTrustStore()}. */
576     protected void loadDefaultTrustStore() {
577         try {
578             trustStore = KeyStoreUtils.loadDefaultTrustStore();
579             if (logger.isDebugEnabled()) {
580                 logger.debug("Loaded default trust store");
581             }
582         }
583         catch (Exception ex) {
584             logger.warn("Could not open default trust store", ex);
585         }
586     }
587 
588     //
589     // Inner classes
590     //
591 
592     private class KeyStoreCertificateValidator implements CertificateValidationCallback.CertificateValidator {
593 
594         public boolean validate(X509Certificate certificate)
595                 throws CertificateValidationCallback.CertificateValidationException {
596             if (isOwnedCert(certificate)) {
597                 if (logger.isDebugEnabled()) {
598                     logger.debug("Certificate with DN [" + certificate.getSubjectX500Principal().getName() +
599                             "] is in private keystore");
600                 }
601                 return true;
602             }
603             else if (trustStore == null) {
604                 return false;
605             }
606 
607             try {
608                 certificate.checkValidity();
609             }
610             catch (CertificateExpiredException e) {
611                 if (logger.isDebugEnabled()) {
612                     logger.debug("Certificate with DN [" + certificate.getSubjectX500Principal().getName() +
613                             "] has expired");
614                 }
615                 return false;
616             }
617             catch (CertificateNotYetValidException e) {
618                 if (logger.isDebugEnabled()) {
619                     logger.debug("Certificate with DN [" + certificate.getSubjectX500Principal().getName() +
620                             "] is not yet valid");
621                 }
622                 return false;
623             }
624 
625             X509CertSelector certSelector = new X509CertSelector();
626             certSelector.setCertificate(certificate);
627 
628             PKIXBuilderParameters parameters;
629             CertPathBuilder builder;
630             try {
631                 parameters = new PKIXBuilderParameters(trustStore, certSelector);
632                 parameters.setRevocationEnabled(false);
633                 builder = CertPathBuilder.getInstance("PKIX");
634             }
635             catch (GeneralSecurityException ex) {
636                 throw new CertificateValidationCallback.CertificateValidationException(
637                         "Could not create PKIX CertPathBuilder", ex);
638             }
639 
640             try {
641                 builder.build(parameters);
642             }
643             catch (CertPathBuilderException e) {
644                 if (logger.isDebugEnabled()) {
645                     logger.debug("Certification path of certificate with DN [" +
646                             certificate.getSubjectX500Principal().getName() + "] could not be validated");
647                 }
648                 return false;
649             }
650             catch (InvalidAlgorithmParameterException e) {
651                 if (logger.isDebugEnabled()) {
652                     logger.debug("Algorithm of certificate with DN [" +
653                             certificate.getSubjectX500Principal().getName() + "] could not be validated");
654                 }
655                 return false;
656             }
657             if (logger.isDebugEnabled()) {
658                 logger.debug("Certificate with DN [" + certificate.getSubjectX500Principal().getName() + "] validated");
659             }
660             return true;
661         }
662 
663         private boolean isOwnedCert(X509Certificate cert)
664                 throws CertificateValidationCallback.CertificateValidationException {
665             if (keyStore == null) {
666                 return false;
667             }
668             try {
669                 Enumeration aliases = keyStore.aliases();
670                 while (aliases.hasMoreElements()) {
671                     String alias = (String) aliases.nextElement();
672                     if (keyStore.isKeyEntry(alias)) {
673                         X509Certificate x509Cert = (X509Certificate) keyStore.getCertificate(alias);
674                         if (x509Cert != null) {
675                             if (x509Cert.equals(cert)) {
676                                 return true;
677                             }
678                         }
679                     }
680                 }
681                 return false;
682             }
683             catch (GeneralSecurityException e) {
684                 throw new CertificateValidationCallback.CertificateValidationException(
685                         "Could not determine whether certificate is contained in main key store", e);
686             }
687         }
688     }
689 }