View Javadoc

1   //========================================================================
2   //Copyright (c) Webtide LLC
3   //------------------------------------------------------------------------
4   //All rights reserved. This program and the accompanying materials
5   //are made available under the terms of the Eclipse Public License v1.0
6   //and Apache License v2.0 which accompanies this distribution.
7   //
8   //The Eclipse Public License is available at
9   //http://www.eclipse.org/legal/epl-v10.html
10  //
11  //The Apache License v2.0 is available at
12  //http://www.apache.org/licenses/LICENSE-2.0.txt
13  //
14  //You may elect to redistribute this code under either of these licenses.
15  //========================================================================
16  
17  package org.eclipse.jetty.http.ssl;
18  
19  import java.io.ByteArrayInputStream;
20  import java.io.ByteArrayOutputStream;
21  import java.io.File;
22  import java.io.IOException;
23  import java.io.InputStream;
24  import java.security.InvalidParameterException;
25  import java.security.KeyStore;
26  import java.security.SecureRandom;
27  import java.security.Security;
28  import java.security.cert.CRL;
29  import java.security.cert.CertStore;
30  import java.security.cert.Certificate;
31  import java.security.cert.CollectionCertStoreParameters;
32  import java.security.cert.PKIXBuilderParameters;
33  import java.security.cert.X509CertSelector;
34  import java.util.Arrays;
35  import java.util.Collection;
36  import java.util.Collections;
37  import java.util.HashSet;
38  import java.util.List;
39  import java.util.Set;
40  import javax.net.ssl.CertPathTrustManagerParameters;
41  import javax.net.ssl.KeyManager;
42  import javax.net.ssl.KeyManagerFactory;
43  import javax.net.ssl.SSLContext;
44  import javax.net.ssl.SSLEngine;
45  import javax.net.ssl.SSLSessionContext;
46  import javax.net.ssl.TrustManager;
47  import javax.net.ssl.TrustManagerFactory;
48  import javax.net.ssl.X509KeyManager;
49  import javax.net.ssl.X509TrustManager;
50  
51  import org.eclipse.jetty.http.security.Password;
52  import org.eclipse.jetty.util.IO;
53  import org.eclipse.jetty.util.component.AbstractLifeCycle;
54  import org.eclipse.jetty.util.resource.Resource;
55  import org.eclipse.jetty.util.security.CertificateUtils;
56  import org.eclipse.jetty.util.security.CertificateValidator;
57  
58  
59  /* ------------------------------------------------------------ */
60  /**
61   * SslContextFactory is used to configure SSL connectors
62   * as well as HttpClient. It holds all SSL parameters and
63   * creates SSL context based on these parameters to be
64   * used by the SSL connectors.
65   */
66  public class SslContextFactory extends AbstractLifeCycle
67  {
68      public static final String DEFAULT_KEYMANAGERFACTORY_ALGORITHM =
69          (Security.getProperty("ssl.KeyManagerFactory.algorithm") == null ?
70                  "SunX509" : Security.getProperty("ssl.KeyManagerFactory.algorithm"));
71      public static final String DEFAULT_TRUSTMANAGERFACTORY_ALGORITHM =
72          (Security.getProperty("ssl.TrustManagerFactory.algorithm") == null ?
73                  "SunX509" : Security.getProperty("ssl.TrustManagerFactory.algorithm"));
74  
75      /** Default value for the keystore location path. */
76      public static final String DEFAULT_KEYSTORE_PATH =
77          System.getProperty("user.home") + File.separator + ".keystore";
78  
79      /** String name of key password property. */
80      public static final String KEYPASSWORD_PROPERTY = "org.eclipse.jetty.ssl.keypassword";
81  
82      /** String name of keystore password property. */
83      public static final String PASSWORD_PROPERTY = "org.eclipse.jetty.ssl.password";
84  
85      /** Excluded cipher suites. */
86      private Set<String> _excludeCipherSuites = null;
87      /** Included cipher suites. */
88      private Set<String> _includeCipherSuites = null;
89  
90      /** Keystore path. */
91      private String _keyStorePath;
92      /** Keystore provider name */
93      private String _keyStoreProvider;
94      /** Keystore type */
95      private String _keyStoreType = "JKS";
96      /** Keystore input stream */
97      private InputStream _keyStoreInputStream;
98  
99      /** SSL certificate alias */
100     private String _certAlias;
101 
102     /** Truststore path */
103     private String _trustStorePath;
104     /** Truststore provider name */
105     private String _trustStoreProvider;
106     /** Truststore type */
107     private String _trustStoreType = "JKS";
108     /** Truststore input stream */
109     private InputStream _trustStoreInputStream;
110 
111     /** Set to true if client certificate authentication is required */
112     private boolean _needClientAuth = false;
113     /** Set to true if client certificate authentication is desired */
114     private boolean _wantClientAuth = false;
115 
116     /** Set to true if renegotiation is allowed */
117     private boolean _allowRenegotiate = true;
118 
119     /** Keystore password */
120     private transient Password _keyStorePassword;
121     /** Key manager password */
122     private transient Password _keyManagerPassword;
123     /** Truststore password */
124     private transient Password _trustStorePassword;
125 
126     /** SSL provider name */
127     private String _sslProvider;
128     /** SSL protocol name */
129     private String _sslProtocol = "TLS";
130 
131     /** SecureRandom algorithm */
132     private String _secureRandomAlgorithm;
133     /** KeyManager factory algorithm */
134     private String _keyManagerFactoryAlgorithm = DEFAULT_KEYMANAGERFACTORY_ALGORITHM;
135     /** TrustManager factory algorithm */
136     private String _trustManagerFactoryAlgorithm = DEFAULT_TRUSTMANAGERFACTORY_ALGORITHM;
137 
138     /** Set to true if SSL certificate validation is required */
139     private boolean _validateCerts;
140     /** Set to true if SSL certificate of the peer validation is required */
141     private boolean _validatePeerCerts;
142     /** Maximum certification path length (n - number of intermediate certs, -1 for unlimited) */
143     private int _maxCertPathLength = -1;
144     /** Path to file that contains Certificate Revocation List */
145     private String _crlPath;
146     /** Set to true to enable CRL Distribution Points (CRLDP) support */
147     private boolean _enableCRLDP = false;
148     /** Set to true to enable On-Line Certificate Status Protocol (OCSP) support */
149     private boolean _enableOCSP = false;
150     /** Location of OCSP Responder */
151     private String _ocspResponderURL;
152 
153     /** SSL keystore */
154     private KeyStore _keyStore;
155     /** SSL truststore */
156     private KeyStore _trustStore;
157     /** Set to true to enable SSL Session caching */
158     private boolean _sessionCachingEnabled = true;
159     /** SSL session cache size */
160     private int _sslSessionCacheSize;
161     /** SSL session timeout */
162     private int _sslSessionTimeout;
163 
164     /** SSL context */
165     private SSLContext _context;
166 
167     /* ------------------------------------------------------------ */
168     /**
169      * Construct an instance of SslContextFactory
170      * Default constructor for use in XmlConfiguration files
171      */
172     public SslContextFactory()
173     {
174     }
175 
176     /* ------------------------------------------------------------ */
177     /**
178      * Construct an instance of SslContextFactory
179      * @param keyStorePath default keystore location
180      */
181     public SslContextFactory(String keyStorePath)
182     {
183         _keyStorePath = keyStorePath;
184     }
185 
186     /* ------------------------------------------------------------ */
187     /**
188      * Create the SSLContext object and start the lifecycle
189      * @see org.eclipse.jetty.util.component.AbstractLifeCycle#doStart()
190      */
191     @Override
192     protected void doStart() throws Exception
193     {
194         if (_context == null)
195         {
196             if (_keyStoreInputStream == null && _keyStorePath == null &&
197                     _trustStoreInputStream == null && _trustStorePath == null )
198             {
199                 // Create a trust manager that does not validate certificate chains
200                 TrustManager trustAllCerts = new X509TrustManager()
201                 {
202                     public java.security.cert.X509Certificate[] getAcceptedIssuers()
203                     {
204                         return null;
205                     }
206 
207                     public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType)
208                     {
209                     }
210 
211                     public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType)
212                     {
213                     }
214                 };
215 
216                 _context = SSLContext.getInstance(_sslProtocol);
217                 _context.init(null, new TrustManager[]{trustAllCerts}, null);
218             }
219             else
220             {
221                 createSSLContext();
222             }
223         }
224     }
225 
226     /* ------------------------------------------------------------ */
227     /**
228      * @return The array of cipher suite names to exclude from
229      * {@link SSLEngine#setEnabledCipherSuites(String[])}
230      */
231     public String[] getExcludeCipherSuites()
232     {
233         return _excludeCipherSuites.toArray(new String[_excludeCipherSuites.size()]);
234     }
235 
236     /* ------------------------------------------------------------ */
237     /**
238      * @param cipherSuites
239      *            The array of cipher suite names to exclude from
240      *            {@link SSLEngine#setEnabledCipherSuites(String[])}
241      */
242     public void setExcludeCipherSuites(String[] cipherSuites)
243     {
244         checkStarted();
245 
246         _excludeCipherSuites = new HashSet<String>(Arrays.asList(cipherSuites));
247     }
248 
249     /* ------------------------------------------------------------ */
250     /**
251      * @return The array of cipher suite names to include in
252      * {@link SSLEngine#setEnabledCipherSuites(String[])}
253      */
254     public String[] getIncludeCipherSuites()
255     {
256         return _includeCipherSuites.toArray(new String[_includeCipherSuites.size()]);
257     }
258 
259     /* ------------------------------------------------------------ */
260     /**
261      * @param cipherSuites
262      *            The array of cipher suite names to include in
263      *            {@link SSLEngine#setEnabledCipherSuites(String[])}
264      */
265     public void setIncludeCipherSuites(String[] cipherSuites)
266     {
267         checkStarted();
268 
269         _includeCipherSuites = new HashSet<String>(Arrays.asList(cipherSuites));
270     }
271 
272     /* ------------------------------------------------------------ */
273     /**
274      * @return The file or URL of the SSL Key store.
275      */
276     public String getKeyStore()
277     {
278         return _keyStorePath;
279     }
280 
281     /* ------------------------------------------------------------ */
282     /**
283      * @param keyStorePath
284      *            The file or URL of the SSL Key store.
285      */
286     public void setKeyStore(String keyStorePath)
287     {
288         checkStarted();
289 
290         _keyStorePath = keyStorePath;
291     }
292 
293     /* ------------------------------------------------------------ */
294     /**
295      * @return The provider of the key store
296      */
297     public String getKeyStoreProvider()
298     {
299         return _keyStoreProvider;
300     }
301 
302     /* ------------------------------------------------------------ */
303     /**
304      * @param keyStoreProvider
305      *            The provider of the key store
306      */
307     public void setKeyStoreProvider(String keyStoreProvider)
308     {
309         checkStarted();
310 
311         _keyStoreProvider = keyStoreProvider;
312     }
313 
314     /* ------------------------------------------------------------ */
315     /**
316      * @return The type of the key store (default "JKS")
317      */
318     public String getKeyStoreType()
319     {
320         return (_keyStoreType);
321     }
322 
323     /* ------------------------------------------------------------ */
324     /**
325      * @param keyStoreType
326      *            The type of the key store (default "JKS")
327      */
328     public void setKeyStoreType(String keyStoreType)
329     {
330         checkStarted();
331 
332         _keyStoreType = keyStoreType;
333     }
334 
335     /* ------------------------------------------------------------ */
336     /** Get the _keyStoreInputStream.
337      * @return the _keyStoreInputStream
338      *
339      * @deprecated
340      */
341     @Deprecated
342     public InputStream getKeyStoreInputStream()
343     {
344         checkConfig();
345 
346         return _keyStoreInputStream;
347     }
348 
349     /* ------------------------------------------------------------ */
350     /** Set the keyStoreInputStream.
351      * @param keyStoreInputStream the InputStream to the KeyStore
352      *
353      * @deprecated
354      */
355     @Deprecated
356     public void setKeyStoreInputStream(InputStream keyStoreInputStream)
357     {
358         checkStarted();
359 
360         _keyStoreInputStream = keyStoreInputStream;
361     }
362 
363     /* ------------------------------------------------------------ */
364     /**
365      * @return Alias of SSL certificate for the connector
366      */
367     public String getCertAlias()
368     {
369         return _certAlias;
370     }
371 
372     /* ------------------------------------------------------------ */
373     /**
374      * @param certAlias
375      *            Alias of SSL certificate for the connector
376      */
377     public void setCertAlias(String certAlias)
378     {
379         checkStarted();
380 
381         _certAlias = certAlias;
382     }
383 
384     /* ------------------------------------------------------------ */
385     /**
386      * @return The file name or URL of the trust store location
387      */
388     public String getTrustStore()
389     {
390         return _trustStorePath;
391     }
392 
393     /* ------------------------------------------------------------ */
394     /**
395      * @param trustStorePath
396      *            The file name or URL of the trust store location
397      */
398     public void setTrustStore(String trustStorePath)
399     {
400         checkStarted();
401 
402         _trustStorePath = trustStorePath;
403     }
404 
405     /* ------------------------------------------------------------ */
406     /**
407      * @return The provider of the trust store
408      */
409     public String getTrustStoreProvider()
410     {
411         return _trustStoreProvider;
412     }
413 
414     /* ------------------------------------------------------------ */
415     /**
416      * @param trustStoreProvider
417      *            The provider of the trust store
418      */
419     public void setTrustStoreProvider(String trustStoreProvider)
420     {
421         checkStarted();
422 
423         _trustStoreProvider = trustStoreProvider;
424     }
425 
426     /* ------------------------------------------------------------ */
427     /**
428      * @return The type of the trust store (default "JKS")
429      */
430     public String getTrustStoreType()
431     {
432         return _trustStoreType;
433     }
434 
435     /* ------------------------------------------------------------ */
436     /**
437      * @param trustStoreType
438      *            The type of the trust store (default "JKS")
439      */
440     public void setTrustStoreType(String trustStoreType)
441     {
442         checkStarted();
443 
444         _trustStoreType = trustStoreType;
445     }
446 
447     /* ------------------------------------------------------------ */
448     /** Get the _trustStoreInputStream.
449      * @return the _trustStoreInputStream
450      *
451      * @deprecated
452      */
453     @Deprecated
454     public InputStream getTrustStoreInputStream()
455     {
456         checkConfig();
457 
458         return _trustStoreInputStream;
459     }
460 
461     /* ------------------------------------------------------------ */
462     /** Set the _trustStoreInputStream.
463      * @param trustStoreInputStream the InputStream to the TrustStore
464      *
465      * @deprecated
466      */
467     @Deprecated
468     public void setTrustStoreInputStream(InputStream trustStoreInputStream)
469     {
470         checkStarted();
471 
472         _trustStoreInputStream = trustStoreInputStream;
473     }
474 
475     /* ------------------------------------------------------------ */
476     /**
477      * @return True if SSL needs client authentication.
478      * @see SSLEngine#getNeedClientAuth()
479      */
480     public boolean getNeedClientAuth()
481     {
482         return _needClientAuth;
483     }
484 
485     /* ------------------------------------------------------------ */
486     /**
487      * @param needClientAuth
488      *            True if SSL needs client authentication.
489      * @see SSLEngine#getNeedClientAuth()
490      */
491     public void setNeedClientAuth(boolean needClientAuth)
492     {
493         checkStarted();
494 
495         _needClientAuth = needClientAuth;
496     }
497 
498     /* ------------------------------------------------------------ */
499     /**
500      * @return True if SSL wants client authentication.
501      * @see SSLEngine#getWantClientAuth()
502      */
503     public boolean getWantClientAuth()
504     {
505         return _wantClientAuth;
506     }
507 
508     /* ------------------------------------------------------------ */
509     /**
510      * @param wantClientAuth
511      *            True if SSL wants client authentication.
512      * @see SSLEngine#getWantClientAuth()
513      */
514     public void setWantClientAuth(boolean wantClientAuth)
515     {
516         checkStarted();
517 
518         _wantClientAuth = wantClientAuth;
519     }
520 
521     /* ------------------------------------------------------------ */
522     /**
523      * @return true if SSL certificate has to be validated
524      * @deprecated
525      */
526     @Deprecated
527     public boolean getValidateCerts()
528     {
529         return _validateCerts;
530     }
531 
532     /* ------------------------------------------------------------ */
533     /**
534      * @return true if SSL certificate has to be validated
535      */
536     public boolean isValidateCerts()
537     {
538         return _validateCerts;
539     }
540 
541     /* ------------------------------------------------------------ */
542     /**
543      * @param validateCerts
544      *            true if SSL certificates have to be validated
545      */
546     public void setValidateCerts(boolean validateCerts)
547     {
548         checkStarted();
549 
550         _validateCerts = validateCerts;
551     }
552 
553     /* ------------------------------------------------------------ */
554     /**
555      * @return true if SSL certificates of the peer have to be validated
556      */
557     public boolean isValidatePeerCerts()
558     {
559         return _validatePeerCerts;
560     }
561 
562     /* ------------------------------------------------------------ */
563     /**
564      * @param validatePeerCerts
565      *            true if SSL certificates of the peer have to be validated
566      */
567     public void setValidatePeerCerts(boolean validatePeerCerts)
568     {
569         checkStarted();
570 
571         _validatePeerCerts = validatePeerCerts;
572     }
573 
574     /* ------------------------------------------------------------ */
575     /**
576      * @return True if SSL re-negotiation is allowed (default false)
577      */
578     public boolean isAllowRenegotiate()
579     {
580         return _allowRenegotiate;
581     }
582 
583     /* ------------------------------------------------------------ */
584     /**
585      * Set if SSL re-negotiation is allowed. CVE-2009-3555 discovered
586      * a vulnerability in SSL/TLS with re-negotiation.  If your JVM
587      * does not have CVE-2009-3555 fixed, then re-negotiation should
588      * not be allowed.  CVE-2009-3555 was fixed in Sun java 1.6 with a ban
589      * of renegotiates in u19 and with RFC5746 in u22.
590      *
591      * @param allowRenegotiate
592      *            true if re-negotiation is allowed (default false)
593      */
594     public void setAllowRenegotiate(boolean allowRenegotiate)
595     {
596         checkStarted();
597 
598         _allowRenegotiate = allowRenegotiate;
599     }
600 
601     /* ------------------------------------------------------------ */
602     /**
603      * @param password
604      *            The password for the key store
605      */
606     public void setKeyStorePassword(String password)
607     {
608         checkStarted();
609 
610         _keyStorePassword = Password.getPassword(PASSWORD_PROPERTY,password,null);
611     }
612 
613     /* ------------------------------------------------------------ */
614     /**
615      * @param password
616      *            The password (if any) for the specific key within the key store
617      */
618     public void setKeyManagerPassword(String password)
619     {
620         checkStarted();
621 
622         _keyManagerPassword = Password.getPassword(KEYPASSWORD_PROPERTY,password,null);
623     }
624 
625     /* ------------------------------------------------------------ */
626     /**
627      * @param password
628      *            The password for the trust store
629      */
630     public void setTrustStorePassword(String password)
631     {
632         checkStarted();
633 
634         _trustStorePassword = Password.getPassword(PASSWORD_PROPERTY,password,null);
635     }
636 
637     /* ------------------------------------------------------------ */
638     /**
639      * @return The SSL provider name, which if set is passed to
640      * {@link SSLContext#getInstance(String, String)}
641      */
642     public String getProvider()
643     {
644         return _sslProvider;
645     }
646 
647     /* ------------------------------------------------------------ */
648     /**
649      * @param provider
650      *            The SSL provider name, which if set is passed to
651      *            {@link SSLContext#getInstance(String, String)}
652      */
653     public void setProvider(String provider)
654     {
655         checkStarted();
656 
657         _sslProvider = provider;
658     }
659 
660     /* ------------------------------------------------------------ */
661     /**
662      * @return The SSL protocol (default "TLS") passed to
663      * {@link SSLContext#getInstance(String, String)}
664      */
665     public String getProtocol()
666     {
667         return _sslProtocol;
668     }
669 
670     /* ------------------------------------------------------------ */
671     /**
672      * @param protocol
673      *            The SSL protocol (default "TLS") passed to
674      *            {@link SSLContext#getInstance(String, String)}
675      */
676     public void setProtocol(String protocol)
677     {
678         checkStarted();
679 
680         _sslProtocol = protocol;
681     }
682 
683     /* ------------------------------------------------------------ */
684     /**
685      * @return The algorithm name, which if set is passed to
686      * {@link SecureRandom#getInstance(String)} to obtain the {@link SecureRandom} instance passed to
687      * {@link SSLContext#init(javax.net.ssl.KeyManager[], javax.net.ssl.TrustManager[], SecureRandom)}
688      */
689     public String getSecureRandomAlgorithm()
690     {
691         return _secureRandomAlgorithm;
692     }
693 
694     /* ------------------------------------------------------------ */
695     /**
696      * @param algorithm
697      *            The algorithm name, which if set is passed to
698      *            {@link SecureRandom#getInstance(String)} to obtain the {@link SecureRandom} instance passed to
699      *            {@link SSLContext#init(javax.net.ssl.KeyManager[], javax.net.ssl.TrustManager[], SecureRandom)}
700      */
701     public void setSecureRandomAlgorithm(String algorithm)
702     {
703         checkStarted();
704 
705         _secureRandomAlgorithm = algorithm;
706     }
707 
708     /* ------------------------------------------------------------ */
709     /**
710      * @return The algorithm name (default "SunX509") used by the {@link KeyManagerFactory}
711      */
712     public String getSslKeyManagerFactoryAlgorithm()
713     {
714         return (_keyManagerFactoryAlgorithm);
715     }
716 
717     /* ------------------------------------------------------------ */
718     /**
719      * @param algorithm
720      *            The algorithm name (default "SunX509") used by the {@link KeyManagerFactory}
721      */
722     public void setSslKeyManagerFactoryAlgorithm(String algorithm)
723     {
724         checkStarted();
725 
726         _keyManagerFactoryAlgorithm = algorithm;
727     }
728 
729     /* ------------------------------------------------------------ */
730     /**
731      * @return The algorithm name (default "SunX509") used by the {@link TrustManagerFactory}
732      */
733     public String getTrustManagerFactoryAlgorithm()
734     {
735         return (_trustManagerFactoryAlgorithm);
736     }
737 
738     /* ------------------------------------------------------------ */
739     /**
740      * @param algorithm
741      *            The algorithm name (default "SunX509") used by the {@link TrustManagerFactory}
742      */
743     public void setTrustManagerFactoryAlgorithm(String algorithm)
744     {
745         checkStarted();
746 
747         _trustManagerFactoryAlgorithm = algorithm;
748     }
749 
750     /* ------------------------------------------------------------ */
751     /**
752      * @return Path to file that contains Certificate Revocation List
753      */
754     public String getCrlPath()
755     {
756         return _crlPath;
757     }
758 
759     /* ------------------------------------------------------------ */
760     /**
761      * @param crlPath
762      *            Path to file that contains Certificate Revocation List
763      */
764     public void setCrlPath(String crlPath)
765     {
766         checkStarted();
767 
768         _crlPath = crlPath;
769     }
770 
771     /* ------------------------------------------------------------ */
772     /**
773      * @return Maximum number of intermediate certificates in
774      * the certification path (-1 for unlimited)
775      */
776     public int getMaxCertPathLength()
777     {
778         return _maxCertPathLength;
779     }
780 
781     /* ------------------------------------------------------------ */
782     /**
783      * @param maxCertPathLength
784      *            maximum number of intermediate certificates in
785      *            the certification path (-1 for unlimited)
786      */
787     public void setMaxCertPathLength(int maxCertPathLength)
788     {
789         checkStarted();
790 
791         _maxCertPathLength = maxCertPathLength;
792     }
793 
794     /* ------------------------------------------------------------ */
795     /**
796      * @return The SSLContext
797      */
798     public SSLContext getSslContext()
799     {
800         return _context;
801     }
802 
803     /* ------------------------------------------------------------ */
804     /**
805      * @param sslContext
806      *            Set a preconfigured SSLContext
807      */
808     public void setSslContext(SSLContext sslContext)
809     {
810         checkStarted();
811 
812         _context = sslContext;
813     }
814 
815     /* ------------------------------------------------------------ */
816     /**
817      * @throws Exception
818      */
819     protected void createSSLContext() throws Exception
820     {
821         // verify that keystore and truststore
822         // parameters are set up correctly
823         checkConfig();
824 
825         KeyStore keyStore = loadKeyStore();
826         KeyStore trustStore = loadTrustStore();
827 
828         Collection<? extends CRL> crls = loadCRL(_crlPath);
829 
830         if (_validateCerts && keyStore != null)
831         {
832             if (_certAlias == null)
833             {
834                 List<String> aliases = Collections.list(keyStore.aliases());
835                 _certAlias = aliases.size() == 1 ? aliases.get(0) : null;
836             }
837 
838             Certificate cert = _certAlias == null?null:keyStore.getCertificate(_certAlias);
839             if (cert == null)
840             {
841                 throw new Exception("No certificate found in the keystore" + (_certAlias==null ? "":" for alias " + _certAlias));
842             }
843 
844             CertificateValidator validator = new CertificateValidator(trustStore, crls);
845             validator.setMaxCertPathLength(_maxCertPathLength);
846             validator.setEnableCRLDP(_enableCRLDP);
847             validator.setEnableOCSP(_enableOCSP);
848             validator.setOcspResponderURL(_ocspResponderURL);
849             validator.validate(keyStore, cert);
850         }
851 
852         KeyManager[] keyManagers = getKeyManagers(keyStore);
853         TrustManager[] trustManagers = getTrustManagers(trustStore,crls);
854 
855         SecureRandom secureRandom = (_secureRandomAlgorithm == null)?null:SecureRandom.getInstance(_secureRandomAlgorithm);
856         _context = (_sslProvider == null)?SSLContext.getInstance(_sslProtocol):SSLContext.getInstance(_sslProtocol,_sslProvider);
857         _context.init(keyManagers,trustManagers,secureRandom);
858 
859         SSLSessionContext sslSessionContext = _context.getServerSessionContext();
860         sslSessionContext.setSessionCacheSize(_sslSessionCacheSize);
861         sslSessionContext.setSessionTimeout(_sslSessionTimeout);
862     }
863 
864     /* ------------------------------------------------------------ */
865     /**
866      * Override this method to provide alternate way to load a keystore.
867      *
868      * @return the key store instance
869      * @throws Exception
870      */
871     protected KeyStore loadKeyStore() throws Exception
872     {
873         return _keyStore != null ? _keyStore : getKeyStore(_keyStoreInputStream,
874                 _keyStorePath, _keyStoreType, _keyStoreProvider,
875                 _keyStorePassword==null? null: _keyStorePassword.toString());
876     }
877 
878     /* ------------------------------------------------------------ */
879     /**
880      * Override this method to provide alternate way to load a truststore.
881      *
882      * @return the key store instance
883      * @throws Exception
884      */
885     protected KeyStore loadTrustStore() throws Exception
886     {
887         return _trustStore != null ? _trustStore : getKeyStore(_trustStoreInputStream,
888                 _trustStorePath, _trustStoreType,  _trustStoreProvider,
889                 _trustStorePassword==null? null: _trustStorePassword.toString());
890     }
891 
892     /* ------------------------------------------------------------ */
893     /**
894      * Loads keystore using an input stream or a file path in the same
895      * order of precedence.
896      *
897      * Required for integrations to be able to override the mechanism
898      * used to load a keystore in order to provide their own implementation.
899      *
900      * @param storeStream keystore input stream
901      * @param storePath path of keystore file
902      * @param storeType keystore type
903      * @param storeProvider keystore provider
904      * @param storePassword keystore password
905      * @return created keystore
906      * @throws Exception
907      *
908      * @deprecated
909      */
910     @Deprecated
911     protected KeyStore getKeyStore(InputStream storeStream, String storePath, String storeType, String storeProvider, String storePassword) throws Exception
912     {
913         return CertificateUtils.getKeyStore(storeStream, storePath, storeType, storeProvider, storePassword);
914     }
915 
916     /* ------------------------------------------------------------ */
917     /**
918      * Loads certificate revocation list (CRL) from a file.
919      *
920      * Required for integrations to be able to override the mechanism used to
921      * load CRL in order to provide their own implementation.
922      *
923      * @param crlPath path of certificate revocation list file
924      * @return Collection of CRL's
925      * @throws Exception
926      */
927     protected Collection<? extends CRL> loadCRL(String crlPath) throws Exception
928     {
929         return CertificateUtils.loadCRL(crlPath);
930     }
931 
932     /* ------------------------------------------------------------ */
933     protected KeyManager[] getKeyManagers(KeyStore keyStore) throws Exception
934     {
935         KeyManager[] managers = null;
936 
937         if (keyStore != null)
938         {
939             KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(_keyManagerFactoryAlgorithm);
940             keyManagerFactory.init(keyStore,_keyManagerPassword == null?(_keyStorePassword == null?null:_keyStorePassword.toString().toCharArray()):_keyManagerPassword.toString().toCharArray());
941             managers = keyManagerFactory.getKeyManagers();
942 
943             if (_certAlias != null)
944             {
945                 for (int idx = 0; idx < managers.length; idx++)
946                 {
947                     if (managers[idx] instanceof X509KeyManager)
948                     {
949                         managers[idx] = new AliasedX509ExtendedKeyManager(_certAlias,(X509KeyManager)managers[idx]);
950                     }
951                 }
952             }
953         }
954 
955         return managers;
956     }
957 
958     /* ------------------------------------------------------------ */
959     protected TrustManager[] getTrustManagers(KeyStore trustStore, Collection<? extends CRL> crls) throws Exception
960     {
961         TrustManager[] managers = null;
962         if (trustStore != null)
963         {
964             // Revocation checking is only supported for PKIX algorithm
965             if (_validatePeerCerts && _trustManagerFactoryAlgorithm.equalsIgnoreCase("PKIX"))
966             {
967                 PKIXBuilderParameters pbParams = new PKIXBuilderParameters(trustStore,new X509CertSelector());
968 
969                 // Set maximum certification path length
970                 pbParams.setMaxPathLength(_maxCertPathLength);
971 
972                 // Make sure revocation checking is enabled
973                 pbParams.setRevocationEnabled(true);
974 
975                 if (crls != null && !crls.isEmpty())
976                 {
977                     pbParams.addCertStore(CertStore.getInstance("Collection",new CollectionCertStoreParameters(crls)));
978                 }
979 
980                 if (_enableCRLDP)
981                 {
982                     // Enable Certificate Revocation List Distribution Points (CRLDP) support
983                     System.setProperty("com.sun.security.enableCRLDP","true");
984                 }
985 
986                 if (_enableOCSP)
987                 {
988                     // Enable On-Line Certificate Status Protocol (OCSP) support
989                     Security.setProperty("ocsp.enable","true");
990 
991                     if (_ocspResponderURL != null)
992                     {
993                         // Override location of OCSP Responder
994                         Security.setProperty("ocsp.responderURL", _ocspResponderURL);
995                     }
996                 }
997 
998                 TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(_trustManagerFactoryAlgorithm);
999                 trustManagerFactory.init(new CertPathTrustManagerParameters(pbParams));
1000 
1001                 managers = trustManagerFactory.getTrustManagers();
1002             }
1003             else
1004             {
1005                 TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(_trustManagerFactoryAlgorithm);
1006                 trustManagerFactory.init(trustStore);
1007 
1008                 managers = trustManagerFactory.getTrustManagers();
1009             }
1010         }
1011 
1012         return managers;
1013     }
1014 
1015     /* ------------------------------------------------------------ */
1016     /**
1017      * Check configuration. Ensures that if keystore has been
1018      * configured but there's no truststore, that keystore is
1019      * used as truststore.
1020      * @return true SslContextFactory configuration can be used in server connector.
1021      */
1022     public boolean checkConfig()
1023     {
1024         boolean check = true;
1025         if (_keyStore == null && _keyStoreInputStream == null && _keyStorePath == null)
1026         {
1027             // configuration doesn't have a valid keystore
1028             check = false;
1029         }
1030         else
1031         {
1032              // if the keystore has been configured but there is no
1033              // truststore configured, use the keystore as the truststore
1034             if (_trustStore == null && _trustStoreInputStream == null && _trustStorePath == null)
1035             {
1036                 _trustStore = _keyStore;
1037                 _trustStorePath = _keyStorePath;
1038                 _trustStoreInputStream = _keyStoreInputStream;
1039                 _trustStoreType = _keyStoreType;
1040                 _trustStoreProvider = _keyStoreProvider;
1041                 _trustStorePassword = _keyStorePassword;
1042                 _trustManagerFactoryAlgorithm = _keyManagerFactoryAlgorithm;
1043             }
1044         }
1045 
1046         // It's the same stream we cannot read it twice, so read it once in memory
1047         if (_keyStoreInputStream != null && _keyStoreInputStream == _trustStoreInputStream)
1048         {
1049             try
1050             {
1051                 ByteArrayOutputStream baos = new ByteArrayOutputStream();
1052                 IO.copy(_keyStoreInputStream, baos);
1053                 _keyStoreInputStream.close();
1054 
1055                 _keyStoreInputStream = new ByteArrayInputStream(baos.toByteArray());
1056                 _trustStoreInputStream = new ByteArrayInputStream(baos.toByteArray());
1057             }
1058             catch (Exception ex)
1059             {
1060                 throw new RuntimeException(ex);
1061             }
1062         }
1063 
1064         return check;
1065     }
1066 
1067     /* ------------------------------------------------------------ */
1068     /**
1069      * Select cipher suites to be used by the connector
1070      * based on configured inclusion and exclusion lists
1071      * as well as enabled and supported cipher suite lists.
1072      * @param enabledCipherSuites Array of enabled cipher suites
1073      * @param supportedCipherSuites Array of supported cipher suites
1074      * @return Array of cipher suites to enable
1075      */
1076     public String[] selectCipherSuites(String[] enabledCipherSuites, String[] supportedCipherSuites)
1077     {
1078         Set<String> selectedCipherSuites = null;
1079         if (enabledCipherSuites != null)
1080         {
1081             selectedCipherSuites = new HashSet<String>(Arrays.asList(enabledCipherSuites));
1082         }
1083         else
1084         {
1085             selectedCipherSuites = new HashSet<String>();
1086         }
1087 
1088         if ((supportedCipherSuites != null && supportedCipherSuites.length > 0) &&
1089             (_includeCipherSuites != null && _includeCipherSuites.size() > 0))
1090         {
1091             Set<String> supportedCSList = new HashSet<String>(Arrays.asList(supportedCipherSuites));
1092 
1093             for (String cipherName : _includeCipherSuites)
1094             {
1095                 if ((!selectedCipherSuites.contains(cipherName)) &&
1096                     supportedCSList.contains(cipherName))
1097                 {
1098                     selectedCipherSuites.add(cipherName);
1099                 }
1100             }
1101         }
1102 
1103         if (_excludeCipherSuites != null && _excludeCipherSuites.size() > 0)
1104         {
1105             for (String cipherName : _excludeCipherSuites)
1106             {
1107                 if (selectedCipherSuites.contains(cipherName))
1108                 {
1109                     selectedCipherSuites.remove(cipherName);
1110                 }
1111             }
1112         }
1113 
1114         return selectedCipherSuites.toArray(new String[selectedCipherSuites.size()]);
1115     }
1116 
1117     /* ------------------------------------------------------------ */
1118     /**
1119      * Check if the lifecycle has been started and throw runtime exception
1120      */
1121     protected void checkStarted()
1122     {
1123         if (isStarted())
1124         {
1125             throw new IllegalStateException("Cannot modify configuration after SslContextFactory was started");
1126         }
1127     }
1128 
1129     /* ------------------------------------------------------------ */
1130     /**
1131      * @return true if CRL Distribution Points support is enabled
1132      */
1133     public boolean isEnableCRLDP()
1134     {
1135         return _enableCRLDP;
1136     }
1137 
1138     /* ------------------------------------------------------------ */
1139     /** Enables CRL Distribution Points Support
1140      * @param enableCRLDP true - turn on, false - turns off
1141      */
1142     public void setEnableCRLDP(boolean enableCRLDP)
1143     {
1144         checkStarted();
1145 
1146         _enableCRLDP = enableCRLDP;
1147     }
1148 
1149     /* ------------------------------------------------------------ */
1150     /**
1151      * @return true if On-Line Certificate Status Protocol support is enabled
1152      */
1153     public boolean isEnableOCSP()
1154     {
1155         return _enableOCSP;
1156     }
1157 
1158     /* ------------------------------------------------------------ */
1159     /** Enables On-Line Certificate Status Protocol support
1160      * @param enableOCSP true - turn on, false - turn off
1161      */
1162     public void setEnableOCSP(boolean enableOCSP)
1163     {
1164         checkStarted();
1165 
1166         _enableOCSP = enableOCSP;
1167     }
1168 
1169     /* ------------------------------------------------------------ */
1170     /**
1171      * @return Location of the OCSP Responder
1172      */
1173     public String getOcspResponderURL()
1174     {
1175         return _ocspResponderURL;
1176     }
1177 
1178     /* ------------------------------------------------------------ */
1179     /** Set the location of the OCSP Responder.
1180      * @param ocspResponderURL location of the OCSP Responder
1181      */
1182     public void setOcspResponderURL(String ocspResponderURL)
1183     {
1184         checkStarted();
1185 
1186         _ocspResponderURL = ocspResponderURL;
1187     }
1188 
1189     /* ------------------------------------------------------------ */
1190     /** Set the key store.
1191      * @param keyStore the key store to set
1192      */
1193     public void setKeyStore(KeyStore keyStore)
1194     {
1195         checkStarted();
1196 
1197         _keyStore = keyStore;
1198     }
1199 
1200     /* ------------------------------------------------------------ */
1201     /** Set the trust store.
1202      * @param trustStore the trust store to set
1203      */
1204     public void setTrustStore(KeyStore trustStore)
1205     {
1206         checkStarted();
1207 
1208         _trustStore = trustStore;
1209     }
1210 
1211     /* ------------------------------------------------------------ */
1212     /** Set the key store resource.
1213      * @param resource the key store resource to set
1214      */
1215     public void setKeyStoreResource(Resource resource)
1216     {
1217         checkStarted();
1218 
1219         try
1220         {
1221             _keyStoreInputStream = resource.getInputStream();
1222         }
1223         catch (IOException e)
1224         {
1225              throw new InvalidParameterException("Unable to get resource "+
1226                      "input stream for resource "+resource.toString());
1227         }
1228     }
1229 
1230     /* ------------------------------------------------------------ */
1231     /** Set the trust store resource.
1232      * @param resource the trust store resource to set
1233      */
1234     public void setTrustStore(Resource resource)
1235     {
1236         checkStarted();
1237 
1238         try
1239         {
1240             _trustStoreInputStream = resource.getInputStream();
1241         }
1242         catch (IOException e)
1243         {
1244              throw new InvalidParameterException("Unable to get resource "+
1245                      "input stream for resource "+resource.toString());
1246         }
1247     }
1248 
1249     /* ------------------------------------------------------------ */
1250     /**
1251     * @return true if SSL Session caching is enabled
1252     */
1253     public boolean isSessionCachingEnabled()
1254     {
1255         return _sessionCachingEnabled;
1256     }
1257 
1258     /* ------------------------------------------------------------ */
1259     /** Set the flag to enable SSL Session caching.
1260     * @param enableSessionCaching the value of the flag
1261     */
1262     public void setSessionCachingEnabled(boolean enableSessionCaching)
1263     {
1264         _sessionCachingEnabled = enableSessionCaching;
1265     }
1266 
1267     /* ------------------------------------------------------------ */
1268     /** Get SSL session cache size.
1269      * @return SSL session cache size
1270      */
1271     public int getSslSessionCacheSize()
1272     {
1273         return _sslSessionCacheSize;
1274     }
1275 
1276     /* ------------------------------------------------------------ */
1277     /** SEt SSL session cache size.
1278      * @param sslSessionCacheSize SSL session cache size to set
1279      */
1280     public void setSslSessionCacheSize(int sslSessionCacheSize)
1281     {
1282         _sslSessionCacheSize = sslSessionCacheSize;
1283     }
1284 
1285     /* ------------------------------------------------------------ */
1286     /** Get SSL session timeout.
1287      * @return SSL session timeout
1288      */
1289     public int getSslSessionTimeout()
1290     {
1291         return _sslSessionTimeout;
1292     }
1293 
1294     /* ------------------------------------------------------------ */
1295     /** Set SSL session timeout.
1296      * @param sslSessionTimeout SSL session timeout to set
1297      */
1298     public void setSslSessionTimeout(int sslSessionTimeout)
1299     {
1300         _sslSessionTimeout = sslSessionTimeout;
1301     }
1302 }