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