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