2 // ========================================================================
3 // Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
4 // ------------------------------------------------------------------------
5 // All rights reserved. This program and the accompanying materials
6 // are made available under the terms of the Eclipse Public License v1.0
7 // and Apache License v2.0 which accompanies this distribution.
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 Set<String> _includeProtocols = null;
121 /** Excluded cipher suites. */
122 private final Set<String> _excludeCipherSuites = new LinkedHashSet<>();
123 /** Included cipher suites. */
124 private Set<String> _includeCipherSuites = null;
126 /** Keystore path. */
127 private String _keyStorePath;
128 /** Keystore provider name */
129 private String _keyStoreProvider;
131 private String _keyStoreType = "JKS";
132 /** Keystore input stream */
133 private InputStream _keyStoreInputStream;
135 /** SSL certificate alias */
136 private String _certAlias;
138 /** Truststore path */
139 private String _trustStorePath;
140 /** Truststore provider name */
141 private String _trustStoreProvider;
142 /** Truststore type */
143 private String _trustStoreType = "JKS";
144 /** Truststore input stream */
145 private InputStream _trustStoreInputStream;
147 /** Set to true if client certificate authentication is required */
148 private boolean _needClientAuth = false;
149 /** Set to true if client certificate authentication is desired */
150 private boolean _wantClientAuth = false;
152 /** Keystore password */
153 private transient Password _keyStorePassword;
154 /** Key manager password */
155 private transient Password _keyManagerPassword;
156 /** Truststore password */
157 private transient Password _trustStorePassword;
159 /** SSL provider name */
160 private String _sslProvider;
161 /** SSL protocol name */
162 private String _sslProtocol = "TLS";
164 /** SecureRandom algorithm */
165 private String _secureRandomAlgorithm;
166 /** KeyManager factory algorithm */
167 private String _keyManagerFactoryAlgorithm = DEFAULT_KEYMANAGERFACTORY_ALGORITHM;
168 /** TrustManager factory algorithm */
169 private String _trustManagerFactoryAlgorithm = DEFAULT_TRUSTMANAGERFACTORY_ALGORITHM;
171 /** Set to true if SSL certificate validation is required */
172 private boolean _validateCerts;
173 /** Set to true if SSL certificate of the peer validation is required */
174 private boolean _validatePeerCerts;
175 /** Maximum certification path length (n - number of intermediate certs, -1 for unlimited) */
176 private int _maxCertPathLength = -1;
177 /** Path to file that contains Certificate Revocation List */
178 private String _crlPath;
179 /** Set to true to enable CRL Distribution Points (CRLDP) support */
180 private boolean _enableCRLDP = false;
181 /** Set to true to enable On-Line Certificate Status Protocol (OCSP) support */
182 private boolean _enableOCSP = false;
183 /** Location of OCSP Responder */
184 private String _ocspResponderURL;
187 private KeyStore _keyStore;
188 /** SSL truststore */
189 private KeyStore _trustStore;
190 /** Set to true to enable SSL Session caching */
191 private boolean _sessionCachingEnabled = true;
192 /** SSL session cache size */
193 private int _sslSessionCacheSize;
194 /** SSL session timeout */
195 private int _sslSessionTimeout;
198 private SSLContext _context;
200 /** EndpointIdentificationAlgorithm - when set to "HTTPS" hostname verification will be enabled */
201 private String _endpointIdentificationAlgorithm = null;
203 /** Whether to blindly trust certificates */
204 private boolean _trustAll;
206 /** Whether TLS renegotiation is allowed */
207 private boolean _renegotiationAllowed = true;
210 * Construct an instance of SslContextFactory
211 * Default constructor for use in XmlConfiguration files
213 public SslContextFactory()
219 * Construct an instance of SslContextFactory
220 * Default constructor for use in XmlConfiguration files
221 * @param trustAll whether to blindly trust all certificates
222 * @see #setTrustAll(boolean)
224 public SslContextFactory(boolean trustAll)
226 setTrustAll(trustAll);
230 * Construct an instance of SslContextFactory
231 * @param keyStorePath default keystore location
233 public SslContextFactory(String keyStorePath)
235 _keyStorePath = keyStorePath;
239 * Create the SSLContext object and start the lifecycle
240 * @see org.eclipse.jetty.util.component.AbstractLifeCycle#doStart()
243 protected void doStart() throws Exception
245 if (_context == null)
247 if (_keyStore==null && _keyStoreInputStream == null && _keyStorePath == null &&
248 _trustStore==null && _trustStoreInputStream == null && _trustStorePath == null )
250 TrustManager[] trust_managers=null;
254 LOG.debug("No keystore or trust store configured. ACCEPTING UNTRUSTED CERTIFICATES!!!!!");
255 // Create a trust manager that does not validate certificate chains
256 trust_managers = TRUST_ALL_CERTS;
259 SecureRandom secureRandom = (_secureRandomAlgorithm == null)?null:SecureRandom.getInstance(_secureRandomAlgorithm);
260 SSLContext context = SSLContext.getInstance(_sslProtocol);
261 context.init(null, trust_managers, secureRandom);
266 // verify that keystore and truststore
267 // parameters are set up correctly
270 KeyStore keyStore = loadKeyStore();
271 KeyStore trustStore = loadTrustStore();
273 Collection<? extends CRL> crls = loadCRL(_crlPath);
275 if (_validateCerts && keyStore != null)
277 if (_certAlias == null)
279 List<String> aliases = Collections.list(keyStore.aliases());
280 _certAlias = aliases.size() == 1 ? aliases.get(0) : null;
283 Certificate cert = _certAlias == null?null:keyStore.getCertificate(_certAlias);
286 throw new Exception("No certificate found in the keystore" + (_certAlias==null ? "":" for alias " + _certAlias));
289 CertificateValidator validator = new CertificateValidator(trustStore, crls);
290 validator.setMaxCertPathLength(_maxCertPathLength);
291 validator.setEnableCRLDP(_enableCRLDP);
292 validator.setEnableOCSP(_enableOCSP);
293 validator.setOcspResponderURL(_ocspResponderURL);
294 validator.validate(keyStore, cert);
297 KeyManager[] keyManagers = getKeyManagers(keyStore);
298 TrustManager[] trustManagers = getTrustManagers(trustStore,crls);
300 SecureRandom secureRandom = (_secureRandomAlgorithm == null)?null:SecureRandom.getInstance(_secureRandomAlgorithm);
301 SSLContext context = _sslProvider == null ? SSLContext.getInstance(_sslProtocol) : SSLContext.getInstance(_sslProtocol,_sslProvider);
302 context.init(keyManagers,trustManagers,secureRandom);
306 SSLEngine engine = newSSLEngine();
307 LOG.debug("Enabled Protocols {} of {}",Arrays.asList(engine.getEnabledProtocols()),Arrays.asList(engine.getSupportedProtocols()));
308 if (LOG.isDebugEnabled())
309 LOG.debug("Enabled Ciphers {} of {}",Arrays.asList(engine.getEnabledCipherSuites()),Arrays.asList(engine.getSupportedCipherSuites()));
314 protected void doStop() throws Exception
321 * @return The array of protocol names to exclude from
322 * {@link SSLEngine#setEnabledProtocols(String[])}
324 public String[] getExcludeProtocols()
326 return _excludeProtocols.toArray(new String[_excludeProtocols.size()]);
331 * The array of protocol names to exclude from
332 * {@link SSLEngine#setEnabledProtocols(String[])}
334 public void setExcludeProtocols(String... protocols)
337 _excludeProtocols.clear();
338 _excludeProtocols.addAll(Arrays.asList(protocols));
342 * @param protocol Protocol names to add to {@link SSLEngine#setEnabledProtocols(String[])}
344 public void addExcludeProtocols(String... protocol)
347 _excludeProtocols.addAll(Arrays.asList(protocol));
351 * @return The array of protocol names to include in
352 * {@link SSLEngine#setEnabledProtocols(String[])}
354 public String[] getIncludeProtocols()
356 return _includeProtocols.toArray(new String[_includeProtocols.size()]);
361 * The array of protocol names to include in
362 * {@link SSLEngine#setEnabledProtocols(String[])}
364 public void setIncludeProtocols(String... protocols)
367 _includeProtocols = new LinkedHashSet<>(Arrays.asList(protocols));
371 * @return The array of cipher suite names to exclude from
372 * {@link SSLEngine#setEnabledCipherSuites(String[])}
374 public String[] getExcludeCipherSuites()
376 return _excludeCipherSuites.toArray(new String[_excludeCipherSuites.size()]);
380 * You can either use the exact cipher suite name or a a regular expression.
381 * @param cipherSuites
382 * The array of cipher suite names to exclude from
383 * {@link SSLEngine#setEnabledCipherSuites(String[])}
385 public void setExcludeCipherSuites(String... cipherSuites)
388 _excludeCipherSuites.clear();
389 _excludeCipherSuites.addAll(Arrays.asList(cipherSuites));
393 * @param cipher Cipher names to add to {@link SSLEngine#setEnabledCipherSuites(String[])}
395 public void addExcludeCipherSuites(String... cipher)
398 _excludeCipherSuites.addAll(Arrays.asList(cipher));
402 * @return The array of cipher suite names to include in
403 * {@link SSLEngine#setEnabledCipherSuites(String[])}
405 public String[] getIncludeCipherSuites()
407 return _includeCipherSuites.toArray(new String[_includeCipherSuites.size()]);
411 * You can either use the exact cipher suite name or a a regular expression.
412 * @param cipherSuites
413 * The array of cipher suite names to include in
414 * {@link SSLEngine#setEnabledCipherSuites(String[])}
416 public void setIncludeCipherSuites(String... cipherSuites)
419 _includeCipherSuites = new LinkedHashSet<>(Arrays.asList(cipherSuites));
423 * @return The file or URL of the SSL Key store.
425 public String getKeyStorePath()
427 return _keyStorePath;
431 * @param keyStorePath
432 * The file or URL of the SSL Key store.
434 public void setKeyStorePath(String keyStorePath)
437 _keyStorePath = keyStorePath;
441 * @return The provider of the key store
443 public String getKeyStoreProvider()
445 return _keyStoreProvider;
449 * @param keyStoreProvider
450 * The provider of the key store
452 public void setKeyStoreProvider(String keyStoreProvider)
455 _keyStoreProvider = keyStoreProvider;
459 * @return The type of the key store (default "JKS")
461 public String getKeyStoreType()
463 return (_keyStoreType);
467 * @param keyStoreType
468 * The type of the key store (default "JKS")
470 public void setKeyStoreType(String keyStoreType)
473 _keyStoreType = keyStoreType;
477 * @return Alias of SSL certificate for the connector
479 public String getCertAlias()
486 * Alias of SSL certificate for the connector
488 public void setCertAlias(String certAlias)
491 _certAlias = certAlias;
495 * @return The file name or URL of the trust store location
497 public String getTrustStore()
499 return _trustStorePath;
503 * @param trustStorePath
504 * The file name or URL of the trust store location
506 public void setTrustStorePath(String trustStorePath)
509 _trustStorePath = trustStorePath;
513 * @return The provider of the trust store
515 public String getTrustStoreProvider()
517 return _trustStoreProvider;
521 * @param trustStoreProvider
522 * The provider of the trust store
524 public void setTrustStoreProvider(String trustStoreProvider)
527 _trustStoreProvider = trustStoreProvider;
531 * @return The type of the trust store (default "JKS")
533 public String getTrustStoreType()
535 return _trustStoreType;
539 * @param trustStoreType
540 * The type of the trust store (default "JKS")
542 public void setTrustStoreType(String trustStoreType)
545 _trustStoreType = trustStoreType;
549 * @return True if SSL needs client authentication.
550 * @see SSLEngine#getNeedClientAuth()
552 public boolean getNeedClientAuth()
554 return _needClientAuth;
558 * @param needClientAuth
559 * True if SSL needs client authentication.
560 * @see SSLEngine#getNeedClientAuth()
562 public void setNeedClientAuth(boolean needClientAuth)
565 _needClientAuth = needClientAuth;
569 * @return True if SSL wants client authentication.
570 * @see SSLEngine#getWantClientAuth()
572 public boolean getWantClientAuth()
574 return _wantClientAuth;
578 * @param wantClientAuth
579 * True if SSL wants client authentication.
580 * @see SSLEngine#getWantClientAuth()
582 public void setWantClientAuth(boolean wantClientAuth)
585 _wantClientAuth = wantClientAuth;
589 * @return true if SSL certificate has to be validated
591 public boolean isValidateCerts()
593 return _validateCerts;
597 * @param validateCerts
598 * true if SSL certificates have to be validated
600 public void setValidateCerts(boolean validateCerts)
603 _validateCerts = validateCerts;
607 * @return true if SSL certificates of the peer have to be validated
609 public boolean isValidatePeerCerts()
611 return _validatePeerCerts;
615 * @param validatePeerCerts
616 * true if SSL certificates of the peer have to be validated
618 public void setValidatePeerCerts(boolean validatePeerCerts)
621 _validatePeerCerts = validatePeerCerts;
627 * The password for the key store
629 public void setKeyStorePassword(String password)
632 _keyStorePassword = Password.getPassword(PASSWORD_PROPERTY,password,null);
637 * The password (if any) for the specific key within the key store
639 public void setKeyManagerPassword(String password)
642 _keyManagerPassword = Password.getPassword(KEYPASSWORD_PROPERTY,password,null);
647 * The password for the trust store
649 public void setTrustStorePassword(String password)
652 _trustStorePassword = Password.getPassword(PASSWORD_PROPERTY,password,null);
656 * @return The SSL provider name, which if set is passed to
657 * {@link SSLContext#getInstance(String, String)}
659 public String getProvider()
666 * The SSL provider name, which if set is passed to
667 * {@link SSLContext#getInstance(String, String)}
669 public void setProvider(String provider)
672 _sslProvider = provider;
676 * @return The SSL protocol (default "TLS") passed to
677 * {@link SSLContext#getInstance(String, String)}
679 public String getProtocol()
686 * The SSL protocol (default "TLS") passed to
687 * {@link SSLContext#getInstance(String, String)}
689 public void setProtocol(String protocol)
692 _sslProtocol = protocol;
696 * @return The algorithm name, which if set is passed to
697 * {@link SecureRandom#getInstance(String)} to obtain the {@link SecureRandom} instance passed to
698 * {@link SSLContext#init(javax.net.ssl.KeyManager[], javax.net.ssl.TrustManager[], SecureRandom)}
700 public String getSecureRandomAlgorithm()
702 return _secureRandomAlgorithm;
707 * The algorithm name, which if set is passed to
708 * {@link SecureRandom#getInstance(String)} to obtain the {@link SecureRandom} instance passed to
709 * {@link SSLContext#init(javax.net.ssl.KeyManager[], javax.net.ssl.TrustManager[], SecureRandom)}
711 public void setSecureRandomAlgorithm(String algorithm)
714 _secureRandomAlgorithm = algorithm;
718 * @return The algorithm name (default "SunX509") used by the {@link KeyManagerFactory}
720 public String getSslKeyManagerFactoryAlgorithm()
722 return (_keyManagerFactoryAlgorithm);
727 * The algorithm name (default "SunX509") used by the {@link KeyManagerFactory}
729 public void setSslKeyManagerFactoryAlgorithm(String algorithm)
732 _keyManagerFactoryAlgorithm = algorithm;
736 * @return The algorithm name (default "SunX509") used by the {@link TrustManagerFactory}
738 public String getTrustManagerFactoryAlgorithm()
740 return (_trustManagerFactoryAlgorithm);
744 * @return True if all certificates should be trusted if there is no KeyStore or TrustStore
746 public boolean isTrustAll()
752 * @param trustAll True if all certificates should be trusted if there is no KeyStore or TrustStore
754 public void setTrustAll(boolean trustAll)
756 _trustAll = trustAll;
758 setEndpointIdentificationAlgorithm(null);
763 * The algorithm name (default "SunX509") used by the {@link TrustManagerFactory}
764 * Use the string "TrustAll" to install a trust manager that trusts all.
766 public void setTrustManagerFactoryAlgorithm(String algorithm)
769 _trustManagerFactoryAlgorithm = algorithm;
773 * @return whether TLS renegotiation is allowed (true by default)
775 public boolean isRenegotiationAllowed()
777 return _renegotiationAllowed;
781 * @param renegotiationAllowed whether TLS renegotiation is allowed
783 public void setRenegotiationAllowed(boolean renegotiationAllowed)
785 _renegotiationAllowed = renegotiationAllowed;
789 * @return Path to file that contains Certificate Revocation List
791 public String getCrlPath()
798 * Path to file that contains Certificate Revocation List
800 public void setCrlPath(String crlPath)
807 * @return Maximum number of intermediate certificates in
808 * the certification path (-1 for unlimited)
810 public int getMaxCertPathLength()
812 return _maxCertPathLength;
816 * @param maxCertPathLength
817 * maximum number of intermediate certificates in
818 * the certification path (-1 for unlimited)
820 public void setMaxCertPathLength(int maxCertPathLength)
823 _maxCertPathLength = maxCertPathLength;
827 * @return The SSLContext
829 public SSLContext getSslContext()
832 throw new IllegalStateException(getState());
838 * Set a preconfigured SSLContext
840 public void setSslContext(SSLContext sslContext)
843 _context = sslContext;
847 * When set to "HTTPS" hostname verification will be enabled
849 * @param endpointIdentificationAlgorithm Set the endpointIdentificationAlgorithm
851 public void setEndpointIdentificationAlgorithm(String endpointIdentificationAlgorithm)
853 this._endpointIdentificationAlgorithm = endpointIdentificationAlgorithm;
857 * Override this method to provide alternate way to load a keystore.
859 * @return the key store instance
860 * @throws Exception if the keystore cannot be loaded
862 protected KeyStore loadKeyStore() throws Exception
864 return _keyStore != null ? _keyStore : CertificateUtils.getKeyStore(_keyStoreInputStream,
865 _keyStorePath, _keyStoreType, _keyStoreProvider,
866 _keyStorePassword==null? null: _keyStorePassword.toString());
870 * Override this method to provide alternate way to load a truststore.
872 * @return the key store instance
873 * @throws Exception if the truststore cannot be loaded
875 protected KeyStore loadTrustStore() throws Exception
877 return _trustStore != null ? _trustStore : CertificateUtils.getKeyStore(_trustStoreInputStream,
878 _trustStorePath, _trustStoreType, _trustStoreProvider,
879 _trustStorePassword==null? null: _trustStorePassword.toString());
883 * Loads certificate revocation list (CRL) from a file.
885 * Required for integrations to be able to override the mechanism used to
886 * load CRL in order to provide their own implementation.
888 * @param crlPath path of certificate revocation list file
889 * @return Collection of CRL's
890 * @throws Exception if the certificate revocation list cannot be loaded
892 protected Collection<? extends CRL> loadCRL(String crlPath) throws Exception
894 return CertificateUtils.loadCRL(crlPath);
897 protected KeyManager[] getKeyManagers(KeyStore keyStore) throws Exception
899 KeyManager[] managers = null;
901 if (keyStore != null)
903 KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(_keyManagerFactoryAlgorithm);
904 keyManagerFactory.init(keyStore,_keyManagerPassword == null?(_keyStorePassword == null?null:_keyStorePassword.toString().toCharArray()):_keyManagerPassword.toString().toCharArray());
905 managers = keyManagerFactory.getKeyManagers();
907 if (_certAlias != null)
909 for (int idx = 0; idx < managers.length; idx++)
911 if (managers[idx] instanceof X509KeyManager)
913 managers[idx] = new AliasedX509ExtendedKeyManager(_certAlias,(X509KeyManager)managers[idx]);
922 protected TrustManager[] getTrustManagers(KeyStore trustStore, Collection<? extends CRL> crls) throws Exception
924 TrustManager[] managers = null;
925 if (trustStore != null)
927 // Revocation checking is only supported for PKIX algorithm
928 if (_validatePeerCerts && _trustManagerFactoryAlgorithm.equalsIgnoreCase("PKIX"))
930 PKIXBuilderParameters pbParams = new PKIXBuilderParameters(trustStore,new X509CertSelector());
932 // Set maximum certification path length
933 pbParams.setMaxPathLength(_maxCertPathLength);
935 // Make sure revocation checking is enabled
936 pbParams.setRevocationEnabled(true);
938 if (crls != null && !crls.isEmpty())
940 pbParams.addCertStore(CertStore.getInstance("Collection",new CollectionCertStoreParameters(crls)));
945 // Enable Certificate Revocation List Distribution Points (CRLDP) support
946 System.setProperty("com.sun.security.enableCRLDP","true");
951 // Enable On-Line Certificate Status Protocol (OCSP) support
952 Security.setProperty("ocsp.enable","true");
954 if (_ocspResponderURL != null)
956 // Override location of OCSP Responder
957 Security.setProperty("ocsp.responderURL", _ocspResponderURL);
961 TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(_trustManagerFactoryAlgorithm);
962 trustManagerFactory.init(new CertPathTrustManagerParameters(pbParams));
964 managers = trustManagerFactory.getTrustManagers();
968 TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(_trustManagerFactoryAlgorithm);
969 trustManagerFactory.init(trustStore);
971 managers = trustManagerFactory.getTrustManagers();
979 * Check KeyStore Configuration. Ensures that if keystore has been
980 * configured but there's no truststore, that keystore is
981 * used as truststore.
982 * @throws IllegalStateException if SslContextFactory configuration can't be used.
984 public void checkKeyStore()
986 if (_context != null)
989 if (_keyStore == null && _keyStoreInputStream == null && _keyStorePath == null)
990 throw new IllegalStateException("SSL doesn't have a valid keystore");
992 // if the keystore has been configured but there is no
993 // truststore configured, use the keystore as the truststore
994 if (_trustStore == null && _trustStoreInputStream == null && _trustStorePath == null)
996 _trustStore = _keyStore;
997 _trustStorePath = _keyStorePath;
998 _trustStoreInputStream = _keyStoreInputStream;
999 _trustStoreType = _keyStoreType;
1000 _trustStoreProvider = _keyStoreProvider;
1001 _trustStorePassword = _keyStorePassword;
1002 _trustManagerFactoryAlgorithm = _keyManagerFactoryAlgorithm;
1005 // It's the same stream we cannot read it twice, so read it once in memory
1006 if (_keyStoreInputStream != null && _keyStoreInputStream == _trustStoreInputStream)
1010 ByteArrayOutputStream baos = new ByteArrayOutputStream();
1011 IO.copy(_keyStoreInputStream, baos);
1012 _keyStoreInputStream.close();
1014 _keyStoreInputStream = new ByteArrayInputStream(baos.toByteArray());
1015 _trustStoreInputStream = new ByteArrayInputStream(baos.toByteArray());
1017 catch (Exception ex)
1019 throw new IllegalStateException(ex);
1025 * Select protocols to be used by the connector
1026 * based on configured inclusion and exclusion lists
1027 * as well as enabled and supported protocols.
1028 * @param enabledProtocols Array of enabled protocols
1029 * @param supportedProtocols Array of supported protocols
1030 * @return Array of protocols to enable
1032 public String[] selectProtocols(String[] enabledProtocols, String[] supportedProtocols)
1034 Set<String> selected_protocols = new LinkedHashSet<>();
1036 // Set the starting protocols - either from the included or enabled list
1037 if (_includeProtocols!=null)
1039 // Use only the supported included protocols
1040 for (String protocol : _includeProtocols)
1041 if(Arrays.asList(supportedProtocols).contains(protocol))
1042 selected_protocols.add(protocol);
1045 selected_protocols.addAll(Arrays.asList(enabledProtocols));
1048 // Remove any excluded protocols
1049 selected_protocols.removeAll(_excludeProtocols);
1051 return selected_protocols.toArray(new String[selected_protocols.size()]);
1055 * Select cipher suites to be used by the connector
1056 * based on configured inclusion and exclusion lists
1057 * as well as enabled and supported cipher suite lists.
1058 * @param enabledCipherSuites Array of enabled cipher suites
1059 * @param supportedCipherSuites Array of supported cipher suites
1060 * @return Array of cipher suites to enable
1062 public String[] selectCipherSuites(String[] enabledCipherSuites, String[] supportedCipherSuites)
1064 Set<String> selected_ciphers = new CopyOnWriteArraySet<>();
1066 // Set the starting ciphers - either from the included or enabled list
1067 if (_includeCipherSuites!=null)
1068 processIncludeCipherSuites(supportedCipherSuites, selected_ciphers);
1070 selected_ciphers.addAll(Arrays.asList(enabledCipherSuites));
1072 removeExcludedCipherSuites(selected_ciphers);
1074 return selected_ciphers.toArray(new String[selected_ciphers.size()]);
1077 private void processIncludeCipherSuites(String[] supportedCipherSuites, Set<String> selected_ciphers)
1079 for (String cipherSuite : _includeCipherSuites)
1081 Pattern p = Pattern.compile(cipherSuite);
1082 for (String supportedCipherSuite : supportedCipherSuites)
1084 Matcher m = p.matcher(supportedCipherSuite);
1086 selected_ciphers.add(supportedCipherSuite);
1091 private void removeExcludedCipherSuites(Set<String> selected_ciphers)
1093 for (String excludeCipherSuite : _excludeCipherSuites)
1095 Pattern excludeCipherPattern = Pattern.compile(excludeCipherSuite);
1096 for (String selectedCipherSuite : selected_ciphers)
1098 Matcher m = excludeCipherPattern.matcher(selectedCipherSuite);
1100 selected_ciphers.remove(selectedCipherSuite);
1106 * Check if the lifecycle has been started and throw runtime exception
1108 protected void checkNotStarted()
1111 throw new IllegalStateException("Cannot modify configuration when "+getState());
1115 * @return true if CRL Distribution Points support is enabled
1117 public boolean isEnableCRLDP()
1119 return _enableCRLDP;
1122 /** Enables CRL Distribution Points Support
1123 * @param enableCRLDP true - turn on, false - turns off
1125 public void setEnableCRLDP(boolean enableCRLDP)
1128 _enableCRLDP = enableCRLDP;
1132 * @return true if On-Line Certificate Status Protocol support is enabled
1134 public boolean isEnableOCSP()
1139 /** Enables On-Line Certificate Status Protocol support
1140 * @param enableOCSP true - turn on, false - turn off
1142 public void setEnableOCSP(boolean enableOCSP)
1145 _enableOCSP = enableOCSP;
1149 * @return Location of the OCSP Responder
1151 public String getOcspResponderURL()
1153 return _ocspResponderURL;
1156 /** Set the location of the OCSP Responder.
1157 * @param ocspResponderURL location of the OCSP Responder
1159 public void setOcspResponderURL(String ocspResponderURL)
1162 _ocspResponderURL = ocspResponderURL;
1165 /** Set the key store.
1166 * @param keyStore the key store to set
1168 public void setKeyStore(KeyStore keyStore)
1171 _keyStore = keyStore;
1174 /** Set the trust store.
1175 * @param trustStore the trust store to set
1177 public void setTrustStore(KeyStore trustStore)
1180 _trustStore = trustStore;
1183 /** Set the key store resource.
1184 * @param resource the key store resource to set
1186 public void setKeyStoreResource(Resource resource)
1191 _keyStoreInputStream = resource.getInputStream();
1193 catch (IOException e)
1195 throw new InvalidParameterException("Unable to get resource "+
1196 "input stream for resource "+resource.toString());
1200 /** Set the trust store resource.
1201 * @param resource the trust store resource to set
1203 public void setTrustStoreResource(Resource resource)
1208 _trustStoreInputStream = resource.getInputStream();
1210 catch (IOException e)
1212 throw new InvalidParameterException("Unable to get resource "+
1213 "input stream for resource "+resource.toString());
1218 * @return true if SSL Session caching is enabled
1220 public boolean isSessionCachingEnabled()
1222 return _sessionCachingEnabled;
1225 /** Set the flag to enable SSL Session caching.
1226 * @param enableSessionCaching the value of the flag
1228 public void setSessionCachingEnabled(boolean enableSessionCaching)
1230 _sessionCachingEnabled = enableSessionCaching;
1233 /** Get SSL session cache size.
1234 * @return SSL session cache size
1236 public int getSslSessionCacheSize()
1238 return _sslSessionCacheSize;
1241 /** SEt SSL session cache size.
1242 * @param sslSessionCacheSize SSL session cache size to set
1244 public void setSslSessionCacheSize(int sslSessionCacheSize)
1246 _sslSessionCacheSize = sslSessionCacheSize;
1249 /** Get SSL session timeout.
1250 * @return SSL session timeout
1252 public int getSslSessionTimeout()
1254 return _sslSessionTimeout;
1257 /** Set SSL session timeout.
1258 * @param sslSessionTimeout SSL session timeout to set
1260 public void setSslSessionTimeout(int sslSessionTimeout)
1262 _sslSessionTimeout = sslSessionTimeout;
1266 public SSLServerSocket newSslServerSocket(String host,int port,int backlog) throws IOException
1268 SSLServerSocketFactory factory = _context.getServerSocketFactory();
1270 SSLServerSocket socket =
1271 (SSLServerSocket) (host==null ?
1272 factory.createServerSocket(port,backlog):
1273 factory.createServerSocket(port,backlog,InetAddress.getByName(host)));
1275 if (getWantClientAuth())
1276 socket.setWantClientAuth(getWantClientAuth());
1277 if (getNeedClientAuth())
1278 socket.setNeedClientAuth(getNeedClientAuth());
1280 socket.setEnabledCipherSuites(selectCipherSuites(
1281 socket.getEnabledCipherSuites(),
1282 socket.getSupportedCipherSuites()));
1283 socket.setEnabledProtocols(selectProtocols(socket.getEnabledProtocols(),socket.getSupportedProtocols()));
1288 public SSLSocket newSslSocket() throws IOException
1290 SSLSocketFactory factory = _context.getSocketFactory();
1292 SSLSocket socket = (SSLSocket)factory.createSocket();
1294 if (getWantClientAuth())
1295 socket.setWantClientAuth(getWantClientAuth());
1296 if (getNeedClientAuth())
1297 socket.setNeedClientAuth(getNeedClientAuth());
1299 socket.setEnabledCipherSuites(selectCipherSuites(
1300 socket.getEnabledCipherSuites(),
1301 socket.getSupportedCipherSuites()));
1302 socket.setEnabledProtocols(selectProtocols(socket.getEnabledProtocols(),socket.getSupportedProtocols()));
1308 * Factory method for "scratch" {@link SSLEngine}s, usually only used for retrieving configuration
1309 * information such as the application buffer size or the list of protocols/ciphers.
1311 * This method should not be used for creating {@link SSLEngine}s that are used in actual socket
1314 * @return a new, "scratch" {@link SSLEngine}
1316 public SSLEngine newSSLEngine()
1319 throw new IllegalStateException("!STARTED");
1320 SSLEngine sslEngine=_context.createSSLEngine();
1321 customize(sslEngine);
1326 * General purpose factory method for creating {@link SSLEngine}s, although creation of
1327 * {@link SSLEngine}s on the server-side should prefer {@link #newSSLEngine(InetSocketAddress)}.
1329 * @param host the remote host
1330 * @param port the remote port
1331 * @return a new {@link SSLEngine}
1333 public SSLEngine newSSLEngine(String host, int port)
1336 throw new IllegalStateException("!STARTED");
1337 SSLEngine sslEngine=isSessionCachingEnabled()
1338 ? _context.createSSLEngine(host, port)
1339 : _context.createSSLEngine();
1340 customize(sslEngine);
1345 * Server-side only factory method for creating {@link SSLEngine}s.
1347 * If the given {@code address} is null, it is equivalent to {@link #newSSLEngine()}, otherwise
1348 * {@link #newSSLEngine(String, int)} is called.
1350 * If {@link #getNeedClientAuth()} is {@code true}, then the host name is passed to
1351 * {@link #newSSLEngine(String, int)}, possibly incurring in a reverse DNS lookup, which takes time
1352 * and may hang the selector (since this method is usually called by the selector thread).
1354 * Otherwise, the host address is passed to {@link #newSSLEngine(String, int)} without DNS lookup
1357 * Clients that wish to create {@link SSLEngine} instances must use {@link #newSSLEngine(String, int)}.
1359 * @param address the remote peer address
1360 * @return a new {@link SSLEngine}
1362 public SSLEngine newSSLEngine(InetSocketAddress address)
1364 if (address == null)
1365 return newSSLEngine();
1367 boolean useHostName = getNeedClientAuth();
1368 String hostName = useHostName ? address.getHostName() : address.getAddress().getHostAddress();
1369 return newSSLEngine(hostName, address.getPort());
1372 public void customize(SSLEngine sslEngine)
1374 SSLParameters sslParams = sslEngine.getSSLParameters();
1375 sslParams.setEndpointIdentificationAlgorithm(_endpointIdentificationAlgorithm);
1376 sslEngine.setSSLParameters(sslParams);
1378 if (getWantClientAuth())
1379 sslEngine.setWantClientAuth(getWantClientAuth());
1380 if (getNeedClientAuth())
1381 sslEngine.setNeedClientAuth(getNeedClientAuth());
1383 sslEngine.setEnabledCipherSuites(selectCipherSuites(
1384 sslEngine.getEnabledCipherSuites(),
1385 sslEngine.getSupportedCipherSuites()));
1387 sslEngine.setEnabledProtocols(selectProtocols(sslEngine.getEnabledProtocols(),sslEngine.getSupportedProtocols()));
1390 public static X509Certificate[] getCertChain(SSLSession sslSession)
1394 Certificate[] javaxCerts=sslSession.getPeerCertificates();
1395 if (javaxCerts==null||javaxCerts.length==0)
1398 int length=javaxCerts.length;
1399 X509Certificate[] javaCerts=new X509Certificate[length];
1401 java.security.cert.CertificateFactory cf=java.security.cert.CertificateFactory.getInstance("X.509");
1402 for (int i=0; i<length; i++)
1404 byte bytes[]=javaxCerts[i].getEncoded();
1405 ByteArrayInputStream stream=new ByteArrayInputStream(bytes);
1406 javaCerts[i]=(X509Certificate)cf.generateCertificate(stream);
1411 catch (SSLPeerUnverifiedException pue)
1417 LOG.warn(Log.EXCEPTION,e);
1423 * Given the name of a TLS/SSL cipher suite, return an int representing it effective stream
1424 * cipher key strength. i.e. How much entropy material is in the key material being fed into the
1425 * encryption routines.
1428 * This is based on the information on effective key lengths in RFC 2246 - The TLS Protocol
1429 * Version 1.0, Appendix C. CipherSuite definitions:
1433 * Cipher Type Key Bits
1436 * IDEA_CBC Block 128
1437 * RC2_CBC_40 * Block 40
1438 * RC4_40 * Stream 40
1439 * RC4_128 Stream 128
1440 * DES40_CBC * Block 40
1442 * 3DES_EDE_CBC Block 168
1445 * @param cipherSuite String name of the TLS cipher suite.
1446 * @return int indicating the effective key entropy bit-length.
1448 public static int deduceKeyLength(String cipherSuite)
1450 // Roughly ordered from most common to least common.
1451 if (cipherSuite == null)
1453 else if (cipherSuite.contains("WITH_AES_256_"))
1455 else if (cipherSuite.contains("WITH_RC4_128_"))
1457 else if (cipherSuite.contains("WITH_AES_128_"))
1459 else if (cipherSuite.contains("WITH_RC4_40_"))
1461 else if (cipherSuite.contains("WITH_3DES_EDE_CBC_"))
1463 else if (cipherSuite.contains("WITH_IDEA_CBC_"))
1465 else if (cipherSuite.contains("WITH_RC2_CBC_40_"))
1467 else if (cipherSuite.contains("WITH_DES40_CBC_"))
1469 else if (cipherSuite.contains("WITH_DES_CBC_"))
1476 public String toString()
1478 return String.format("%s@%x(%s,%s)",
1479 getClass().getSimpleName(),