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.
9 // The Eclipse Public License is available at
10 // http://www.eclipse.org/legal/epl-v10.html
12 // The Apache License v2.0 is available at
13 // http://www.opensource.org/licenses/apache2.0.php
15 // You may elect to redistribute this code under either of these licenses.
16 // ========================================================================
19 package org.eclipse.jetty.util.ssl;
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;
44 import java.util.concurrent.CopyOnWriteArraySet;
45 import java.util.regex.Matcher;
46 import java.util.regex.Pattern;
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;
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;
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.
81 public class SslContextFactory extends AbstractLifeCycle
83 public final static TrustManager[] TRUST_ALL_CERTS = new X509TrustManager[]{new X509TrustManager()
85 public java.security.cert.X509Certificate[] getAcceptedIssuers()
87 return new java.security.cert.X509Certificate[]{};
90 public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType)
94 public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType)
99 static final Logger LOG = Log.getLogger(SslContextFactory.class);
101 public static final String DEFAULT_KEYMANAGERFACTORY_ALGORITHM =
102 (Security.getProperty("ssl.KeyManagerFactory.algorithm") == null ?
103 KeyManagerFactory.getDefaultAlgorithm() : Security.getProperty("ssl.KeyManagerFactory.algorithm"));
105 public static final String DEFAULT_TRUSTMANAGERFACTORY_ALGORITHM =
106 (Security.getProperty("ssl.TrustManagerFactory.algorithm") == null ?
107 TrustManagerFactory.getDefaultAlgorithm() : Security.getProperty("ssl.TrustManagerFactory.algorithm"));
109 /** String name of key password property. */
110 public static final String KEYPASSWORD_PROPERTY = "org.eclipse.jetty.ssl.keypassword";
112 /** String name of keystore password property. */
113 public static final String PASSWORD_PROPERTY = "org.eclipse.jetty.ssl.password";
115 /** Excluded protocols. */
116 private final Set<String> _excludeProtocols = new LinkedHashSet<>();
118 /** Included protocols. */
119 private final Set<String> _includeProtocols = new LinkedHashSet<>();
121 /** Excluded cipher suites. */
122 private final Set<String> _excludeCipherSuites = new LinkedHashSet<>();
124 /** Included cipher suites. */
125 private final Set<String> _includeCipherSuites = new LinkedHashSet<>();
127 /** Keystore path. */
128 private String _keyStorePath;
129 /** Keystore provider name */
130 private String _keyStoreProvider;
132 private String _keyStoreType = "JKS";
133 /** Keystore input stream */
134 private InputStream _keyStoreInputStream;
136 /** SSL certificate alias */
137 private String _certAlias;
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;
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;
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;
160 /** SSL provider name */
161 private String _sslProvider;
162 /** SSL protocol name */
163 private String _sslProtocol = "TLS";
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;
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;
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;
199 private SSLContext _context;
201 /** EndpointIdentificationAlgorithm - when set to "HTTPS" hostname verification will be enabled */
202 private String _endpointIdentificationAlgorithm = null;
204 /** Whether to blindly trust certificates */
205 private boolean _trustAll;
207 /** Whether TLS renegotiation is allowed */
208 private boolean _renegotiationAllowed = true;
211 * Construct an instance of SslContextFactory
212 * Default constructor for use in XmlConfiguration files
214 public SslContextFactory()
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)
225 public SslContextFactory(boolean trustAll)
227 setTrustAll(trustAll);
228 addExcludeProtocols("SSL", "SSLv2", "SSLv2Hello", "SSLv3");
232 * Construct an instance of SslContextFactory
233 * @param keyStorePath default keystore location
235 public SslContextFactory(String keyStorePath)
237 _keyStorePath = keyStorePath;
241 * Create the SSLContext object and start the lifecycle
242 * @see org.eclipse.jetty.util.component.AbstractLifeCycle#doStart()
245 protected void doStart() throws Exception
247 if (_context == null)
249 if (_keyStore==null && _keyStoreInputStream == null && _keyStorePath == null &&
250 _trustStore==null && _trustStoreInputStream == null && _trustStorePath == null )
252 TrustManager[] trust_managers=null;
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;
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);
269 // verify that keystore and truststore
270 // parameters are set up correctly
273 KeyStore keyStore = loadKeyStore();
274 KeyStore trustStore = loadTrustStore();
276 Collection<? extends CRL> crls = loadCRL(_crlPath);
278 if (_validateCerts && keyStore != null)
280 if (_certAlias == null)
282 List<String> aliases = Collections.list(keyStore.aliases());
283 _certAlias = aliases.size() == 1 ? aliases.get(0) : null;
286 Certificate cert = _certAlias == null?null:keyStore.getCertificate(_certAlias);
289 throw new Exception("No certificate found in the keystore" + (_certAlias==null ? "":" for alias " + _certAlias));
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);
300 KeyManager[] keyManagers = getKeyManagers(keyStore);
301 TrustManager[] trustManagers = getTrustManagers(trustStore,crls);
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);
309 SSLEngine engine = newSSLEngine();
310 if (LOG.isDebugEnabled())
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()));
319 protected void doStop() throws Exception
326 * @return The array of protocol names to exclude from
327 * {@link SSLEngine#setEnabledProtocols(String[])}
329 public String[] getExcludeProtocols()
331 return _excludeProtocols.toArray(new String[_excludeProtocols.size()]);
336 * The array of protocol names to exclude from
337 * {@link SSLEngine#setEnabledProtocols(String[])}
339 public void setExcludeProtocols(String... protocols)
342 _excludeProtocols.clear();
343 _excludeProtocols.addAll(Arrays.asList(protocols));
347 * @param protocol Protocol names to add to {@link SSLEngine#setEnabledProtocols(String[])}
349 public void addExcludeProtocols(String... protocol)
352 _excludeProtocols.addAll(Arrays.asList(protocol));
356 * @return The array of protocol names to include in
357 * {@link SSLEngine#setEnabledProtocols(String[])}
359 public String[] getIncludeProtocols()
361 return _includeProtocols.toArray(new String[_includeProtocols.size()]);
366 * The array of protocol names to include in
367 * {@link SSLEngine#setEnabledProtocols(String[])}
369 public void setIncludeProtocols(String... protocols)
372 _includeProtocols.clear();
373 _includeProtocols.addAll(Arrays.asList(protocols));
377 * @return The array of cipher suite names to exclude from
378 * {@link SSLEngine#setEnabledCipherSuites(String[])}
380 public String[] getExcludeCipherSuites()
382 return _excludeCipherSuites.toArray(new String[_excludeCipherSuites.size()]);
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[])}
391 public void setExcludeCipherSuites(String... cipherSuites)
394 _excludeCipherSuites.clear();
395 _excludeCipherSuites.addAll(Arrays.asList(cipherSuites));
399 * @param cipher Cipher names to add to {@link SSLEngine#setEnabledCipherSuites(String[])}
401 public void addExcludeCipherSuites(String... cipher)
404 _excludeCipherSuites.addAll(Arrays.asList(cipher));
408 * @return The array of cipher suite names to include in
409 * {@link SSLEngine#setEnabledCipherSuites(String[])}
411 public String[] getIncludeCipherSuites()
413 return _includeCipherSuites.toArray(new String[_includeCipherSuites.size()]);
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[])}
422 public void setIncludeCipherSuites(String... cipherSuites)
425 _includeCipherSuites.clear();
426 _includeCipherSuites.addAll(Arrays.asList(cipherSuites));
430 * @return The file or URL of the SSL Key store.
432 public String getKeyStorePath()
434 return _keyStorePath;
438 * @param keyStorePath
439 * The file or URL of the SSL Key store.
441 public void setKeyStorePath(String keyStorePath)
444 _keyStorePath = keyStorePath;
448 * @return The provider of the key store
450 public String getKeyStoreProvider()
452 return _keyStoreProvider;
456 * @param keyStoreProvider
457 * The provider of the key store
459 public void setKeyStoreProvider(String keyStoreProvider)
462 _keyStoreProvider = keyStoreProvider;
466 * @return The type of the key store (default "JKS")
468 public String getKeyStoreType()
470 return (_keyStoreType);
474 * @param keyStoreType
475 * The type of the key store (default "JKS")
477 public void setKeyStoreType(String keyStoreType)
480 _keyStoreType = keyStoreType;
484 * @return Alias of SSL certificate for the connector
486 public String getCertAlias()
493 * Alias of SSL certificate for the connector
495 public void setCertAlias(String certAlias)
498 _certAlias = certAlias;
502 * @return The file name or URL of the trust store location
504 public String getTrustStore()
506 return _trustStorePath;
510 * @param trustStorePath
511 * The file name or URL of the trust store location
513 public void setTrustStorePath(String trustStorePath)
516 _trustStorePath = trustStorePath;
520 * @return The provider of the trust store
522 public String getTrustStoreProvider()
524 return _trustStoreProvider;
528 * @param trustStoreProvider
529 * The provider of the trust store
531 public void setTrustStoreProvider(String trustStoreProvider)
534 _trustStoreProvider = trustStoreProvider;
538 * @return The type of the trust store (default "JKS")
540 public String getTrustStoreType()
542 return _trustStoreType;
546 * @param trustStoreType
547 * The type of the trust store (default "JKS")
549 public void setTrustStoreType(String trustStoreType)
552 _trustStoreType = trustStoreType;
556 * @return True if SSL needs client authentication.
557 * @see SSLEngine#getNeedClientAuth()
559 public boolean getNeedClientAuth()
561 return _needClientAuth;
565 * @param needClientAuth
566 * True if SSL needs client authentication.
567 * @see SSLEngine#getNeedClientAuth()
569 public void setNeedClientAuth(boolean needClientAuth)
572 _needClientAuth = needClientAuth;
576 * @return True if SSL wants client authentication.
577 * @see SSLEngine#getWantClientAuth()
579 public boolean getWantClientAuth()
581 return _wantClientAuth;
585 * @param wantClientAuth
586 * True if SSL wants client authentication.
587 * @see SSLEngine#getWantClientAuth()
589 public void setWantClientAuth(boolean wantClientAuth)
592 _wantClientAuth = wantClientAuth;
596 * @return true if SSL certificate has to be validated
598 public boolean isValidateCerts()
600 return _validateCerts;
604 * @param validateCerts
605 * true if SSL certificates have to be validated
607 public void setValidateCerts(boolean validateCerts)
610 _validateCerts = validateCerts;
614 * @return true if SSL certificates of the peer have to be validated
616 public boolean isValidatePeerCerts()
618 return _validatePeerCerts;
622 * @param validatePeerCerts
623 * true if SSL certificates of the peer have to be validated
625 public void setValidatePeerCerts(boolean validatePeerCerts)
628 _validatePeerCerts = validatePeerCerts;
634 * The password for the key store
636 public void setKeyStorePassword(String password)
639 _keyStorePassword = Password.getPassword(PASSWORD_PROPERTY,password,null);
644 * The password (if any) for the specific key within the key store
646 public void setKeyManagerPassword(String password)
649 _keyManagerPassword = Password.getPassword(KEYPASSWORD_PROPERTY,password,null);
654 * The password for the trust store
656 public void setTrustStorePassword(String password)
659 _trustStorePassword = Password.getPassword(PASSWORD_PROPERTY,password,null);
663 * @return The SSL provider name, which if set is passed to
664 * {@link SSLContext#getInstance(String, String)}
666 public String getProvider()
673 * The SSL provider name, which if set is passed to
674 * {@link SSLContext#getInstance(String, String)}
676 public void setProvider(String provider)
679 _sslProvider = provider;
683 * @return The SSL protocol (default "TLS") passed to
684 * {@link SSLContext#getInstance(String, String)}
686 public String getProtocol()
693 * The SSL protocol (default "TLS") passed to
694 * {@link SSLContext#getInstance(String, String)}
696 public void setProtocol(String protocol)
699 _sslProtocol = protocol;
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)}
707 public String getSecureRandomAlgorithm()
709 return _secureRandomAlgorithm;
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)}
718 public void setSecureRandomAlgorithm(String algorithm)
721 _secureRandomAlgorithm = algorithm;
725 * @return The algorithm name (default "SunX509") used by the {@link KeyManagerFactory}
727 public String getSslKeyManagerFactoryAlgorithm()
729 return (_keyManagerFactoryAlgorithm);
734 * The algorithm name (default "SunX509") used by the {@link KeyManagerFactory}
736 public void setSslKeyManagerFactoryAlgorithm(String algorithm)
739 _keyManagerFactoryAlgorithm = algorithm;
743 * @return The algorithm name (default "SunX509") used by the {@link TrustManagerFactory}
745 public String getTrustManagerFactoryAlgorithm()
747 return (_trustManagerFactoryAlgorithm);
751 * @return True if all certificates should be trusted if there is no KeyStore or TrustStore
753 public boolean isTrustAll()
759 * @param trustAll True if all certificates should be trusted if there is no KeyStore or TrustStore
761 public void setTrustAll(boolean trustAll)
763 _trustAll = trustAll;
765 setEndpointIdentificationAlgorithm(null);
770 * The algorithm name (default "SunX509") used by the {@link TrustManagerFactory}
771 * Use the string "TrustAll" to install a trust manager that trusts all.
773 public void setTrustManagerFactoryAlgorithm(String algorithm)
776 _trustManagerFactoryAlgorithm = algorithm;
780 * @return whether TLS renegotiation is allowed (true by default)
782 public boolean isRenegotiationAllowed()
784 return _renegotiationAllowed;
788 * @param renegotiationAllowed whether TLS renegotiation is allowed
790 public void setRenegotiationAllowed(boolean renegotiationAllowed)
792 _renegotiationAllowed = renegotiationAllowed;
796 * @return Path to file that contains Certificate Revocation List
798 public String getCrlPath()
805 * Path to file that contains Certificate Revocation List
807 public void setCrlPath(String crlPath)
814 * @return Maximum number of intermediate certificates in
815 * the certification path (-1 for unlimited)
817 public int getMaxCertPathLength()
819 return _maxCertPathLength;
823 * @param maxCertPathLength
824 * maximum number of intermediate certificates in
825 * the certification path (-1 for unlimited)
827 public void setMaxCertPathLength(int maxCertPathLength)
830 _maxCertPathLength = maxCertPathLength;
834 * @return The SSLContext
836 public SSLContext getSslContext()
839 throw new IllegalStateException(getState());
845 * Set a preconfigured SSLContext
847 public void setSslContext(SSLContext sslContext)
850 _context = sslContext;
854 * When set to "HTTPS" hostname verification will be enabled
856 * @param endpointIdentificationAlgorithm Set the endpointIdentificationAlgorithm
858 public void setEndpointIdentificationAlgorithm(String endpointIdentificationAlgorithm)
860 this._endpointIdentificationAlgorithm = endpointIdentificationAlgorithm;
864 * Override this method to provide alternate way to load a keystore.
866 * @return the key store instance
867 * @throws Exception if the keystore cannot be loaded
869 protected KeyStore loadKeyStore() throws Exception
871 return _keyStore != null ? _keyStore : CertificateUtils.getKeyStore(_keyStoreInputStream,
872 _keyStorePath, _keyStoreType, _keyStoreProvider,
873 _keyStorePassword==null? null: _keyStorePassword.toString());
877 * Override this method to provide alternate way to load a truststore.
879 * @return the key store instance
880 * @throws Exception if the truststore cannot be loaded
882 protected KeyStore loadTrustStore() throws Exception
884 return _trustStore != null ? _trustStore : CertificateUtils.getKeyStore(_trustStoreInputStream,
885 _trustStorePath, _trustStoreType, _trustStoreProvider,
886 _trustStorePassword==null? null: _trustStorePassword.toString());
890 * Loads certificate revocation list (CRL) from a file.
892 * Required for integrations to be able to override the mechanism used to
893 * load CRL in order to provide their own implementation.
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
899 protected Collection<? extends CRL> loadCRL(String crlPath) throws Exception
901 return CertificateUtils.loadCRL(crlPath);
904 protected KeyManager[] getKeyManagers(KeyStore keyStore) throws Exception
906 KeyManager[] managers = null;
908 if (keyStore != null)
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();
914 if (_certAlias != null)
916 for (int idx = 0; idx < managers.length; idx++)
918 if (managers[idx] instanceof X509KeyManager)
920 managers[idx] = new AliasedX509ExtendedKeyManager(_certAlias,(X509KeyManager)managers[idx]);
929 protected TrustManager[] getTrustManagers(KeyStore trustStore, Collection<? extends CRL> crls) throws Exception
931 TrustManager[] managers = null;
932 if (trustStore != null)
934 // Revocation checking is only supported for PKIX algorithm
935 if (_validatePeerCerts && _trustManagerFactoryAlgorithm.equalsIgnoreCase("PKIX"))
937 PKIXBuilderParameters pbParams = new PKIXBuilderParameters(trustStore,new X509CertSelector());
939 // Set maximum certification path length
940 pbParams.setMaxPathLength(_maxCertPathLength);
942 // Make sure revocation checking is enabled
943 pbParams.setRevocationEnabled(true);
945 if (crls != null && !crls.isEmpty())
947 pbParams.addCertStore(CertStore.getInstance("Collection",new CollectionCertStoreParameters(crls)));
952 // Enable Certificate Revocation List Distribution Points (CRLDP) support
953 System.setProperty("com.sun.security.enableCRLDP","true");
958 // Enable On-Line Certificate Status Protocol (OCSP) support
959 Security.setProperty("ocsp.enable","true");
961 if (_ocspResponderURL != null)
963 // Override location of OCSP Responder
964 Security.setProperty("ocsp.responderURL", _ocspResponderURL);
968 TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(_trustManagerFactoryAlgorithm);
969 trustManagerFactory.init(new CertPathTrustManagerParameters(pbParams));
971 managers = trustManagerFactory.getTrustManagers();
975 TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(_trustManagerFactoryAlgorithm);
976 trustManagerFactory.init(trustStore);
978 managers = trustManagerFactory.getTrustManagers();
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.
991 public void checkKeyStore()
993 if (_context != null)
996 if (_keyStore == null && _keyStoreInputStream == null && _keyStorePath == null)
997 throw new IllegalStateException("SSL doesn't have a valid keystore");
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)
1003 _trustStore = _keyStore;
1004 _trustStorePath = _keyStorePath;
1005 _trustStoreInputStream = _keyStoreInputStream;
1006 _trustStoreType = _keyStoreType;
1007 _trustStoreProvider = _keyStoreProvider;
1008 _trustStorePassword = _keyStorePassword;
1009 _trustManagerFactoryAlgorithm = _keyManagerFactoryAlgorithm;
1012 // It's the same stream we cannot read it twice, so read it once in memory
1013 if (_keyStoreInputStream != null && _keyStoreInputStream == _trustStoreInputStream)
1017 ByteArrayOutputStream baos = new ByteArrayOutputStream();
1018 IO.copy(_keyStoreInputStream, baos);
1019 _keyStoreInputStream.close();
1021 _keyStoreInputStream = new ByteArrayInputStream(baos.toByteArray());
1022 _trustStoreInputStream = new ByteArrayInputStream(baos.toByteArray());
1024 catch (Exception ex)
1026 throw new IllegalStateException(ex);
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
1039 public String[] selectProtocols(String[] enabledProtocols, String[] supportedProtocols)
1041 Set<String> selected_protocols = new LinkedHashSet<>();
1043 // Set the starting protocols - either from the included or enabled list
1044 if (!_includeProtocols.isEmpty())
1046 // Use only the supported included protocols
1047 for (String protocol : _includeProtocols)
1048 if(Arrays.asList(supportedProtocols).contains(protocol))
1049 selected_protocols.add(protocol);
1052 selected_protocols.addAll(Arrays.asList(enabledProtocols));
1055 // Remove any excluded protocols
1056 selected_protocols.removeAll(_excludeProtocols);
1058 return selected_protocols.toArray(new String[selected_protocols.size()]);
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
1069 public String[] selectCipherSuites(String[] enabledCipherSuites, String[] supportedCipherSuites)
1071 Set<String> selected_ciphers = new CopyOnWriteArraySet<>();
1073 // Set the starting ciphers - either from the included or enabled list
1074 if (_includeCipherSuites.isEmpty())
1075 selected_ciphers.addAll(Arrays.asList(enabledCipherSuites));
1077 processIncludeCipherSuites(supportedCipherSuites, selected_ciphers);
1079 removeExcludedCipherSuites(selected_ciphers);
1081 return selected_ciphers.toArray(new String[selected_ciphers.size()]);
1084 protected void processIncludeCipherSuites(String[] supportedCipherSuites, Set<String> selected_ciphers)
1086 for (String cipherSuite : _includeCipherSuites)
1088 Pattern p = Pattern.compile(cipherSuite);
1089 for (String supportedCipherSuite : supportedCipherSuites)
1091 Matcher m = p.matcher(supportedCipherSuite);
1093 selected_ciphers.add(supportedCipherSuite);
1098 protected void removeExcludedCipherSuites(Set<String> selected_ciphers)
1100 for (String excludeCipherSuite : _excludeCipherSuites)
1102 Pattern excludeCipherPattern = Pattern.compile(excludeCipherSuite);
1103 for (String selectedCipherSuite : selected_ciphers)
1105 Matcher m = excludeCipherPattern.matcher(selectedCipherSuite);
1107 selected_ciphers.remove(selectedCipherSuite);
1113 * Check if the lifecycle has been started and throw runtime exception
1115 protected void checkNotStarted()
1118 throw new IllegalStateException("Cannot modify configuration when "+getState());
1122 * @return true if CRL Distribution Points support is enabled
1124 public boolean isEnableCRLDP()
1126 return _enableCRLDP;
1129 /** Enables CRL Distribution Points Support
1130 * @param enableCRLDP true - turn on, false - turns off
1132 public void setEnableCRLDP(boolean enableCRLDP)
1135 _enableCRLDP = enableCRLDP;
1139 * @return true if On-Line Certificate Status Protocol support is enabled
1141 public boolean isEnableOCSP()
1146 /** Enables On-Line Certificate Status Protocol support
1147 * @param enableOCSP true - turn on, false - turn off
1149 public void setEnableOCSP(boolean enableOCSP)
1152 _enableOCSP = enableOCSP;
1156 * @return Location of the OCSP Responder
1158 public String getOcspResponderURL()
1160 return _ocspResponderURL;
1163 /** Set the location of the OCSP Responder.
1164 * @param ocspResponderURL location of the OCSP Responder
1166 public void setOcspResponderURL(String ocspResponderURL)
1169 _ocspResponderURL = ocspResponderURL;
1172 /** Set the key store.
1173 * @param keyStore the key store to set
1175 public void setKeyStore(KeyStore keyStore)
1178 _keyStore = keyStore;
1181 /** Set the trust store.
1182 * @param trustStore the trust store to set
1184 public void setTrustStore(KeyStore trustStore)
1187 _trustStore = trustStore;
1190 /** Set the key store resource.
1191 * @param resource the key store resource to set
1193 public void setKeyStoreResource(Resource resource)
1198 _keyStoreInputStream = resource.getInputStream();
1200 catch (IOException e)
1202 throw new InvalidParameterException("Unable to get resource "+
1203 "input stream for resource "+resource.toString());
1207 /** Set the trust store resource.
1208 * @param resource the trust store resource to set
1210 public void setTrustStoreResource(Resource resource)
1215 _trustStoreInputStream = resource.getInputStream();
1217 catch (IOException e)
1219 throw new InvalidParameterException("Unable to get resource "+
1220 "input stream for resource "+resource.toString());
1225 * @return true if SSL Session caching is enabled
1227 public boolean isSessionCachingEnabled()
1229 return _sessionCachingEnabled;
1232 /** Set the flag to enable SSL Session caching.
1233 * @param enableSessionCaching the value of the flag
1235 public void setSessionCachingEnabled(boolean enableSessionCaching)
1237 _sessionCachingEnabled = enableSessionCaching;
1240 /** Get SSL session cache size.
1241 * @return SSL session cache size
1243 public int getSslSessionCacheSize()
1245 return _sslSessionCacheSize;
1248 /** SEt SSL session cache size.
1249 * @param sslSessionCacheSize SSL session cache size to set
1251 public void setSslSessionCacheSize(int sslSessionCacheSize)
1253 _sslSessionCacheSize = sslSessionCacheSize;
1256 /** Get SSL session timeout.
1257 * @return SSL session timeout
1259 public int getSslSessionTimeout()
1261 return _sslSessionTimeout;
1264 /** Set SSL session timeout.
1265 * @param sslSessionTimeout SSL session timeout to set
1267 public void setSslSessionTimeout(int sslSessionTimeout)
1269 _sslSessionTimeout = sslSessionTimeout;
1273 public SSLServerSocket newSslServerSocket(String host,int port,int backlog) throws IOException
1275 SSLServerSocketFactory factory = _context.getServerSocketFactory();
1277 SSLServerSocket socket =
1278 (SSLServerSocket) (host==null ?
1279 factory.createServerSocket(port,backlog):
1280 factory.createServerSocket(port,backlog,InetAddress.getByName(host)));
1282 if (getWantClientAuth())
1283 socket.setWantClientAuth(getWantClientAuth());
1284 if (getNeedClientAuth())
1285 socket.setNeedClientAuth(getNeedClientAuth());
1287 socket.setEnabledCipherSuites(selectCipherSuites(
1288 socket.getEnabledCipherSuites(),
1289 socket.getSupportedCipherSuites()));
1290 socket.setEnabledProtocols(selectProtocols(socket.getEnabledProtocols(),socket.getSupportedProtocols()));
1295 public SSLSocket newSslSocket() throws IOException
1297 SSLSocketFactory factory = _context.getSocketFactory();
1299 SSLSocket socket = (SSLSocket)factory.createSocket();
1301 if (getWantClientAuth())
1302 socket.setWantClientAuth(getWantClientAuth());
1303 if (getNeedClientAuth())
1304 socket.setNeedClientAuth(getNeedClientAuth());
1306 socket.setEnabledCipherSuites(selectCipherSuites(
1307 socket.getEnabledCipherSuites(),
1308 socket.getSupportedCipherSuites()));
1309 socket.setEnabledProtocols(selectProtocols(socket.getEnabledProtocols(),socket.getSupportedProtocols()));
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.
1318 * This method should not be used for creating {@link SSLEngine}s that are used in actual socket
1321 * @return a new, "scratch" {@link SSLEngine}
1323 public SSLEngine newSSLEngine()
1326 throw new IllegalStateException("!STARTED");
1327 SSLEngine sslEngine=_context.createSSLEngine();
1328 customize(sslEngine);
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)}.
1336 * @param host the remote host
1337 * @param port the remote port
1338 * @return a new {@link SSLEngine}
1340 public SSLEngine newSSLEngine(String host, int port)
1343 throw new IllegalStateException("!STARTED");
1344 SSLEngine sslEngine=isSessionCachingEnabled()
1345 ? _context.createSSLEngine(host, port)
1346 : _context.createSSLEngine();
1347 customize(sslEngine);
1352 * Server-side only factory method for creating {@link SSLEngine}s.
1354 * If the given {@code address} is null, it is equivalent to {@link #newSSLEngine()}, otherwise
1355 * {@link #newSSLEngine(String, int)} is called.
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).
1361 * Otherwise, the host address is passed to {@link #newSSLEngine(String, int)} without DNS lookup
1364 * Clients that wish to create {@link SSLEngine} instances must use {@link #newSSLEngine(String, int)}.
1366 * @param address the remote peer address
1367 * @return a new {@link SSLEngine}
1369 public SSLEngine newSSLEngine(InetSocketAddress address)
1371 if (address == null)
1372 return newSSLEngine();
1374 boolean useHostName = getNeedClientAuth();
1375 String hostName = useHostName ? address.getHostName() : address.getAddress().getHostAddress();
1376 return newSSLEngine(hostName, address.getPort());
1379 public void customize(SSLEngine sslEngine)
1381 SSLParameters sslParams = sslEngine.getSSLParameters();
1382 sslParams.setEndpointIdentificationAlgorithm(_endpointIdentificationAlgorithm);
1383 sslEngine.setSSLParameters(sslParams);
1385 if (getWantClientAuth())
1386 sslEngine.setWantClientAuth(getWantClientAuth());
1387 if (getNeedClientAuth())
1388 sslEngine.setNeedClientAuth(getNeedClientAuth());
1390 sslEngine.setEnabledCipherSuites(selectCipherSuites(
1391 sslEngine.getEnabledCipherSuites(),
1392 sslEngine.getSupportedCipherSuites()));
1394 sslEngine.setEnabledProtocols(selectProtocols(sslEngine.getEnabledProtocols(),sslEngine.getSupportedProtocols()));
1397 public static X509Certificate[] getCertChain(SSLSession sslSession)
1401 Certificate[] javaxCerts=sslSession.getPeerCertificates();
1402 if (javaxCerts==null||javaxCerts.length==0)
1405 int length=javaxCerts.length;
1406 X509Certificate[] javaCerts=new X509Certificate[length];
1408 java.security.cert.CertificateFactory cf=java.security.cert.CertificateFactory.getInstance("X.509");
1409 for (int i=0; i<length; i++)
1411 byte bytes[]=javaxCerts[i].getEncoded();
1412 ByteArrayInputStream stream=new ByteArrayInputStream(bytes);
1413 javaCerts[i]=(X509Certificate)cf.generateCertificate(stream);
1418 catch (SSLPeerUnverifiedException pue)
1424 LOG.warn(Log.EXCEPTION,e);
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.
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:
1440 * Cipher Type Key Bits
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
1449 * 3DES_EDE_CBC Block 168
1452 * @param cipherSuite String name of the TLS cipher suite.
1453 * @return int indicating the effective key entropy bit-length.
1455 public static int deduceKeyLength(String cipherSuite)
1457 // Roughly ordered from most common to least common.
1458 if (cipherSuite == null)
1460 else if (cipherSuite.contains("WITH_AES_256_"))
1462 else if (cipherSuite.contains("WITH_RC4_128_"))
1464 else if (cipherSuite.contains("WITH_AES_128_"))
1466 else if (cipherSuite.contains("WITH_RC4_40_"))
1468 else if (cipherSuite.contains("WITH_3DES_EDE_CBC_"))
1470 else if (cipherSuite.contains("WITH_IDEA_CBC_"))
1472 else if (cipherSuite.contains("WITH_RC2_CBC_40_"))
1474 else if (cipherSuite.contains("WITH_DES40_CBC_"))
1476 else if (cipherSuite.contains("WITH_DES_CBC_"))
1483 public String toString()
1485 return String.format("%s@%x(%s,%s)",
1486 getClass().getSimpleName(),