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