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