View Javadoc

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