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