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