View Javadoc

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