| // ======================================================================== |
| // Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd. |
| // ------------------------------------------------------------------------ |
| // All rights reserved. This program and the accompanying materials |
| // are made available under the terms of the Eclipse Public License v1.0 |
| // and Apache License v2.0 which accompanies this distribution. |
| // The Eclipse Public License is available at |
| // http://www.eclipse.org/legal/epl-v10.html |
| // The Apache License v2.0 is available at |
| // http://www.opensource.org/licenses/apache2.0.php |
| // You may elect to redistribute this code under either of these licenses. |
| // ======================================================================== |
| |
| package org.eclipse.jetty.exssl; |
| |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.nio.channels.SelectionKey; |
| import java.nio.channels.SocketChannel; |
| import java.security.KeyStore; |
| import java.security.SecureRandom; |
| import java.security.Security; |
| import java.security.cert.CRL; |
| import java.security.cert.CertStore; |
| import java.security.cert.CertificateFactory; |
| import java.security.cert.CollectionCertStoreParameters; |
| import java.security.cert.PKIXBuilderParameters; |
| import java.security.cert.X509CertSelector; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Collection; |
| import java.util.List; |
| |
| import javax.net.ssl.CertPathTrustManagerParameters; |
| import javax.net.ssl.KeyManager; |
| import javax.net.ssl.KeyManagerFactory; |
| import javax.net.ssl.SSLContext; |
| import javax.net.ssl.SSLEngine; |
| import javax.net.ssl.SSLSession; |
| import javax.net.ssl.SSLSocket; |
| import javax.net.ssl.TrustManager; |
| import javax.net.ssl.TrustManagerFactory; |
| import javax.net.ssl.X509KeyManager; |
| |
| import org.eclipse.jetty.http.HttpParser; |
| import org.eclipse.jetty.http.HttpSchemes; |
| import org.eclipse.jetty.http.security.Password; |
| import org.eclipse.jetty.io.Buffer; |
| import org.eclipse.jetty.io.Buffers; |
| import org.eclipse.jetty.io.Connection; |
| import org.eclipse.jetty.io.EndPoint; |
| import org.eclipse.jetty.io.ThreadLocalBuffers; |
| import org.eclipse.jetty.io.bio.SocketEndPoint; |
| import org.eclipse.jetty.io.nio.DirectNIOBuffer; |
| import org.eclipse.jetty.io.nio.IndirectNIOBuffer; |
| import org.eclipse.jetty.io.nio.SelectChannelEndPoint; |
| import org.eclipse.jetty.io.nio.SelectorManager.SelectSet; |
| import org.eclipse.jetty.io.nio.SslSelectChannelEndPoint; |
| import org.eclipse.jetty.server.HttpConnection; |
| import org.eclipse.jetty.server.Request; |
| import org.eclipse.jetty.server.nio.SelectChannelConnector; |
| import org.eclipse.jetty.server.ssl.SslCertificates; |
| import org.eclipse.jetty.util.log.Log; |
| import org.eclipse.jetty.util.resource.Resource; |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * SslSelectChannelConnector. |
| * |
| * @org.apache.xbean.XBean element="sslConnector" description="Creates an NIO ssl connector" |
| * |
| * |
| * |
| */ |
| public class EnhancedSslSelectChannelConnector extends SelectChannelConnector implements EnhancedSslConnector |
| { |
| /** Excluded cipher suites. */ |
| private String _excludeCipherSuites[]=null; |
| /** Included cipher suites. */ |
| private String _includeCipherSuites[]=null; |
| |
| /** KeyStore path. */ |
| private String _keystorePath=DEFAULT_KEYSTORE; |
| /** KeyStore provider name */ |
| private String _keystoreProvider; |
| /** KeyStore type */ |
| private String _keystoreType="JKS"; |
| /** SSL key alias */ |
| private String _keyAlias; |
| |
| /** TrustStore path */ |
| private String _truststorePath; |
| /** TrustStore provider name */ |
| private String _truststoreProvider; |
| /** TrustStore type */ |
| private String _truststoreType="JKS"; |
| |
| /** Set to true if client certificate authentication is required */ |
| private boolean _needClientAuth=false; |
| /** Set to true if client certificate authentication is desired */ |
| private boolean _wantClientAuth=false; |
| /** Set to true if renegotiation is allowed */ |
| private boolean _allowRenegotiate=false; |
| |
| /** KeyStore password */ |
| private transient Password _password; |
| /** Key password */ |
| private transient Password _keyPassword; |
| /** TrustStore password */ |
| private transient Password _trustPassword; |
| |
| /** SSL Provider name */ |
| private String _sslProvider; |
| /** SSL Protocol name */ |
| private String _sslProtocol="TLS"; |
| |
| /** SecureRandom algorithm */ |
| private String _secureRandomAlgorithm; |
| /** KeyManager factory algorithm */ |
| private String _sslKeyManagerFactoryAlgorithm=DEFAULT_KEYSTORE_ALGORITHM; |
| /** TrustManager factory algorithm */ |
| private String _sslTrustManagerFactoryAlgorithm=DEFAULT_TRUSTSTORE_ALGORITHM; |
| |
| /** Path to file that contains Certificate Revocation List */ |
| private String _crlPath; |
| /** Maximum certification path length (n - number of intermediate certs, -1 for unlimited) */ |
| private int _maxCertPathLength = -1; |
| |
| /** SSL context */ |
| private SSLContext _context; |
| private Buffers _sslBuffers; |
| |
| /* ------------------------------------------------------------ */ |
| public EnhancedSslSelectChannelConnector() |
| { |
| setUseDirectBuffers(false); |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * Allow the Listener a chance to customise the request. before the server |
| * does its stuff. <br> |
| * This allows the required attributes to be set for SSL requests. <br> |
| * The requirements of the Servlet specs are: |
| * <ul> |
| * <li> an attribute named "javax.servlet.request.ssl_session_id" of type |
| * String (since Servlet Spec 3.0).</li> |
| * <li> an attribute named "javax.servlet.request.cipher_suite" of type |
| * String.</li> |
| * <li> an attribute named "javax.servlet.request.key_size" of type Integer.</li> |
| * <li> an attribute named "javax.servlet.request.X509Certificate" of type |
| * java.security.cert.X509Certificate[]. This is an array of objects of type |
| * X509Certificate, the order of this array is defined as being in ascending |
| * order of trust. The first certificate in the chain is the one set by the |
| * client, the next is the one used to authenticate the first, and so on. |
| * </li> |
| * </ul> |
| * |
| * @param endpoint |
| * The Socket the request arrived on. This should be a |
| * {@link SocketEndPoint} wrapping a {@link SSLSocket}. |
| * @param request |
| * HttpRequest to be customised. |
| */ |
| @Override |
| public void customize(EndPoint endpoint, Request request) throws IOException |
| { |
| request.setScheme(HttpSchemes.HTTPS); |
| super.customize(endpoint,request); |
| |
| SslSelectChannelEndPoint sslHttpChannelEndpoint=(SslSelectChannelEndPoint)endpoint; |
| SSLEngine sslEngine=sslHttpChannelEndpoint.getSSLEngine(); |
| SSLSession sslSession=sslEngine.getSession(); |
| |
| SslCertificates.customize(sslSession,endpoint,request); |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * @return True if SSL re-negotiation is allowed (default false) |
| */ |
| public boolean isAllowRenegotiate() |
| { |
| return _allowRenegotiate; |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * Set if SSL re-negotiation is allowed. CVE-2009-3555 discovered |
| * a vulnerability in SSL/TLS with re-negotiation. If your JVM |
| * does not have CVE-2009-3555 fixed, then re-negotiation should |
| * not be allowed. |
| * @param allowRenegotiate true if re-negotiation is allowed (default false) |
| */ |
| public void setAllowRenegotiate(boolean allowRenegotiate) |
| { |
| _allowRenegotiate = allowRenegotiate; |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * @see org.eclipse.jetty.server.ssl.SslConnector#getExcludeCipherSuites() |
| */ |
| public String[] getExcludeCipherSuites() |
| { |
| return _excludeCipherSuites; |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * @see org.eclipse.jetty.server.ssl.SslConnector#setExcludeCipherSuites(java.lang.String[]) |
| */ |
| public void setExcludeCipherSuites(String[] cipherSuites) |
| { |
| this._excludeCipherSuites=cipherSuites; |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * @see org.eclipse.jetty.server.ssl.SslConnector#getExcludeCipherSuites() |
| */ |
| public String[] getIncludeCipherSuites() |
| { |
| return _includeCipherSuites; |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * @see org.eclipse.jetty.server.ssl.SslConnector#setExcludeCipherSuites(java.lang.String[]) |
| */ |
| public void setIncludeCipherSuites(String[] cipherSuites) |
| { |
| this._includeCipherSuites=cipherSuites; |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * @see org.eclipse.jetty.server.ssl.SslConnector#setPassword(java.lang.String) |
| */ |
| public void setPassword(String password) |
| { |
| _password=Password.getPassword(PASSWORD_PROPERTY,password,null); |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * @see org.eclipse.jetty.server.ssl.SslConnector#setTrustPassword(java.lang.String) |
| */ |
| public void setTrustPassword(String password) |
| { |
| _trustPassword=Password.getPassword(PASSWORD_PROPERTY,password,null); |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * @see org.eclipse.jetty.server.ssl.SslConnector#setKeyPassword(java.lang.String) |
| */ |
| public void setKeyPassword(String password) |
| { |
| _keyPassword=Password.getPassword(KEYPASSWORD_PROPERTY,password,null); |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * @deprecated use {@link #getSslKeyManagerFactoryAlgorithm()} or |
| * {@link #getSslTrustManagerFactoryAlgorithm()} |
| */ |
| @Deprecated |
| public String getAlgorithm() |
| { |
| return getSslKeyManagerFactoryAlgorithm(); |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * @deprecated use {@link #setSslKeyManagerFactoryAlgorithm(String)} or |
| * {@link #setSslTrustManagerFactoryAlgorithm(String)} |
| */ |
| @Deprecated |
| public void setAlgorithm(String algorithm) |
| { |
| setSslKeyManagerFactoryAlgorithm(algorithm); |
| setSslTrustManagerFactoryAlgorithm(algorithm); |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * @see org.eclipse.jetty.server.ssl.SslConnector#getProtocol() |
| */ |
| public String getProtocol() |
| { |
| return _sslProtocol; |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * @see org.eclipse.jetty.server.ssl.SslConnector#setProtocol(java.lang.String) |
| */ |
| public void setProtocol(String protocol) |
| { |
| _sslProtocol=protocol; |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * @see org.eclipse.jetty.server.ssl.SslConnector#setKeystore(java.lang.String) |
| */ |
| public void setKeystore(String keystore) |
| { |
| _keystorePath=keystore; |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * @see org.eclipse.jetty.server.ssl.SslConnector#getKeystore() |
| */ |
| public String getKeystore() |
| { |
| return _keystorePath; |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * @see org.eclipse.jetty.server.ssl.SslConnector#getKeystoreType() |
| */ |
| public String getKeystoreType() |
| { |
| return (_keystoreType); |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * @see org.eclipse.jetty.server.ssl.SslConnector#getNeedClientAuth() |
| */ |
| public boolean getNeedClientAuth() |
| { |
| return _needClientAuth; |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * @see org.eclipse.jetty.server.ssl.SslConnector#getWantClientAuth() |
| */ |
| public boolean getWantClientAuth() |
| { |
| return _wantClientAuth; |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * @see org.eclipse.jetty.server.ssl.SslConnector#setNeedClientAuth(boolean) |
| */ |
| public void setNeedClientAuth(boolean needClientAuth) |
| { |
| _needClientAuth=needClientAuth; |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * @see org.eclipse.jetty.server.ssl.SslConnector#setWantClientAuth(boolean) |
| */ |
| public void setWantClientAuth(boolean wantClientAuth) |
| { |
| _wantClientAuth=wantClientAuth; |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * @see org.eclipse.jetty.server.ssl.SslConnector#setKeystoreType(java.lang.String) |
| */ |
| public void setKeystoreType(String keystoreType) |
| { |
| _keystoreType=keystoreType; |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * @see org.eclipse.jetty.server.ssl.SslConnector#getProvider() |
| */ |
| public String getProvider() |
| { |
| return _sslProvider; |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * @see org.eclipse.jetty.server.ssl.SslConnector#getSecureRandomAlgorithm() |
| */ |
| public String getSecureRandomAlgorithm() |
| { |
| return (this._secureRandomAlgorithm); |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * @see org.eclipse.jetty.server.ssl.SslConnector#getSslKeyManagerFactoryAlgorithm() |
| */ |
| public String getSslKeyManagerFactoryAlgorithm() |
| { |
| return (this._sslKeyManagerFactoryAlgorithm); |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * @see org.eclipse.jetty.server.ssl.SslConnector#getSslTrustManagerFactoryAlgorithm() |
| */ |
| public String getSslTrustManagerFactoryAlgorithm() |
| { |
| return (this._sslTrustManagerFactoryAlgorithm); |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * @see org.eclipse.jetty.server.ssl.SslConnector#getTruststore() |
| */ |
| public String getTruststore() |
| { |
| return _truststorePath; |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * @see org.eclipse.jetty.server.ssl.SslConnector#getTruststoreType() |
| */ |
| public String getTruststoreType() |
| { |
| return _truststoreType; |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * @see org.eclipse.jetty.server.ssl.SslConnector#setProvider(java.lang.String) |
| */ |
| public void setProvider(String provider) |
| { |
| _sslProvider=provider; |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * @see org.eclipse.jetty.server.ssl.SslConnector#setSecureRandomAlgorithm(java.lang.String) |
| */ |
| public void setSecureRandomAlgorithm(String algorithm) |
| { |
| this._secureRandomAlgorithm=algorithm; |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * @see org.eclipse.jetty.server.ssl.SslConnector#setSslKeyManagerFactoryAlgorithm(java.lang.String) |
| */ |
| public void setSslKeyManagerFactoryAlgorithm(String algorithm) |
| { |
| this._sslKeyManagerFactoryAlgorithm=algorithm; |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * @see org.eclipse.jetty.server.ssl.SslConnector#setSslTrustManagerFactoryAlgorithm(java.lang.String) |
| */ |
| public void setSslTrustManagerFactoryAlgorithm(String algorithm) |
| { |
| this._sslTrustManagerFactoryAlgorithm=algorithm; |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * @see org.eclipse.jetty.server.ssl.SslConnector#setTruststore(java.lang.String) |
| */ |
| public void setTruststore(String truststore) |
| { |
| _truststorePath=truststore; |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * @see org.eclipse.jetty.server.ssl.SslConnector#setTruststoreType(java.lang.String) |
| */ |
| public void setTruststoreType(String truststoreType) |
| { |
| _truststoreType=truststoreType; |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * @see org.eclipse.jetty.server.ssl.SslConnector#setSslContext(javax.net.ssl.SSLContext) |
| */ |
| public void setSslContext(SSLContext sslContext) |
| { |
| _context = sslContext; |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * @see org.eclipse.jetty.server.ssl.SslConnector#setSslContext(javax.net.ssl.SSLContext) |
| */ |
| public SSLContext getSslContext() |
| { |
| try |
| { |
| if (_context == null) |
| _context=createSSLContext(); |
| } |
| catch(Exception e) |
| { |
| throw new RuntimeException(e); |
| } |
| |
| return _context; |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * By default, we're confidential, given we speak SSL. But, if we've been |
| * told about an confidential port, and said port is not our port, then |
| * we're not. This allows separation of listeners providing INTEGRAL versus |
| * CONFIDENTIAL constraints, such as one SSL listener configured to require |
| * client certs providing CONFIDENTIAL, whereas another SSL listener not |
| * requiring client certs providing mere INTEGRAL constraints. |
| */ |
| @Override |
| public boolean isConfidential(Request request) |
| { |
| final int confidentialPort=getConfidentialPort(); |
| return confidentialPort==0||confidentialPort==request.getServerPort(); |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * By default, we're integral, given we speak SSL. But, if we've been told |
| * about an integral port, and said port is not our port, then we're not. |
| * This allows separation of listeners providing INTEGRAL versus |
| * CONFIDENTIAL constraints, such as one SSL listener configured to require |
| * client certs providing CONFIDENTIAL, whereas another SSL listener not |
| * requiring client certs providing mere INTEGRAL constraints. |
| */ |
| @Override |
| public boolean isIntegral(Request request) |
| { |
| final int integralPort=getIntegralPort(); |
| return integralPort==0||integralPort==request.getServerPort(); |
| } |
| |
| /* ------------------------------------------------------------------------------- */ |
| @Override |
| protected SelectChannelEndPoint newEndPoint(SocketChannel channel, SelectSet selectSet, SelectionKey key) throws IOException |
| { |
| SslSelectChannelEndPoint endp = new SslSelectChannelEndPoint(_sslBuffers,channel,selectSet,key,createSSLEngine(), EnhancedSslSelectChannelConnector.this._maxIdleTime); |
| endp.setAllowRenegotiate(_allowRenegotiate); |
| return endp; |
| } |
| |
| /* ------------------------------------------------------------------------------- */ |
| @Override |
| protected Connection newConnection(SocketChannel channel, SelectChannelEndPoint endpoint) |
| { |
| HttpConnection connection=(HttpConnection)super.newConnection(channel,endpoint); |
| ((HttpParser)connection.getParser()).setForceContentBuffer(true); |
| return connection; |
| } |
| |
| /* ------------------------------------------------------------ */ |
| protected SSLEngine createSSLEngine() throws IOException |
| { |
| SSLEngine engine = null; |
| try |
| { |
| engine = _context.createSSLEngine(); |
| engine.setUseClientMode(false); |
| |
| if (_wantClientAuth) |
| engine.setWantClientAuth(_wantClientAuth); |
| if (_needClientAuth) |
| engine.setNeedClientAuth(_needClientAuth); |
| |
| if ((_excludeCipherSuites != null && _excludeCipherSuites.length > 0) || (_includeCipherSuites != null && _includeCipherSuites.length > 0)) |
| { |
| List<String> includedCSList; |
| if (_includeCipherSuites != null) |
| { |
| includedCSList = Arrays.asList(_includeCipherSuites); |
| } |
| else |
| { |
| includedCSList = new ArrayList<String>(); |
| } |
| List<String> excludedCSList; |
| if (_excludeCipherSuites != null) |
| { |
| excludedCSList = Arrays.asList(_excludeCipherSuites); |
| } |
| else |
| { |
| excludedCSList = new ArrayList<String>(); |
| } |
| String[] enabledCipherSuites = engine.getEnabledCipherSuites(); |
| List<String> enabledCSList = new ArrayList<String>(Arrays.asList(enabledCipherSuites)); |
| |
| String[] supportedCipherSuites = engine.getSupportedCipherSuites(); |
| List<String> supportedCSList = Arrays.asList(supportedCipherSuites); |
| |
| for (String cipherName : includedCSList) |
| { |
| if ((!enabledCSList.contains(cipherName)) && supportedCSList.contains(cipherName)) |
| { |
| enabledCSList.add(cipherName); |
| } |
| } |
| |
| for (String cipherName : excludedCSList) |
| { |
| if (enabledCSList.contains(cipherName)) |
| { |
| enabledCSList.remove(cipherName); |
| } |
| } |
| enabledCipherSuites = enabledCSList.toArray(new String[0]); |
| |
| engine.setEnabledCipherSuites(enabledCipherSuites); |
| } |
| } |
| catch (Exception e) |
| { |
| Log.warn("Error creating sslEngine -- closing this connector",e); |
| close(); |
| throw new IllegalStateException(e); |
| } |
| return engine; |
| } |
| |
| @Override |
| protected void doStart() throws Exception |
| { |
| if (_context == null) |
| _context=createSSLContext(); |
| |
| SSLEngine engine=createSSLEngine(); |
| SSLSession ssl_session=engine.getSession(); |
| |
| ThreadLocalBuffers buffers = new ThreadLocalBuffers() |
| { |
| @Override |
| protected Buffer newBuffer(int size) |
| { |
| if (getUseDirectBuffers()) |
| return new DirectNIOBuffer(size); |
| return new IndirectNIOBuffer(size); |
| } |
| @Override |
| protected Buffer newHeader(int size) |
| { |
| if (getUseDirectBuffers()) |
| return new DirectNIOBuffer(size); |
| return new IndirectNIOBuffer(size); |
| } |
| @Override |
| protected boolean isHeader(Buffer buffer) |
| { |
| return true; |
| } |
| }; |
| buffers.setBufferSize(ssl_session.getApplicationBufferSize()); |
| buffers.setHeaderSize(ssl_session.getApplicationBufferSize()); |
| _sslBuffers=buffers; |
| |
| if (getRequestHeaderSize()<ssl_session.getApplicationBufferSize()) |
| setRequestHeaderSize(ssl_session.getApplicationBufferSize()); |
| if (getRequestBufferSize()<ssl_session.getApplicationBufferSize()) |
| setRequestBufferSize(ssl_session.getApplicationBufferSize()); |
| |
| super.doStart(); |
| } |
| |
| public Buffers getSslBuffers() |
| { |
| return _sslBuffers; |
| } |
| |
| public void setKeystoreProvider(String keystoreProvider) |
| { |
| _keystoreProvider = keystoreProvider; |
| } |
| |
| public String getKeystoreProvider() |
| { |
| return _keystoreProvider; |
| } |
| |
| public void setTruststoreProvider(String truststoreProvider) |
| { |
| _truststoreProvider = truststoreProvider; |
| } |
| |
| public String getTruststoreProvider() |
| { |
| return _truststoreProvider; |
| } |
| |
| public void setCrlPath(String crlPath) |
| { |
| _crlPath = crlPath; |
| } |
| |
| public String getCrlPath() |
| { |
| return _crlPath; |
| } |
| |
| /* ------------------------------------------------------------ */ |
| protected SSLContext createSSLContext() throws Exception |
| { |
| KeyStore keyStore = getKeyStore(_keystorePath, _keystoreType, _keystoreProvider, _password==null?null:_password.toString()); |
| KeyStore trustStore = getTrustStore(_truststorePath, _truststoreType, _truststoreProvider, _trustPassword == null ? null : _trustPassword.toString()); |
| Collection<? extends CRL> crls = loadCRL(_crlPath); |
| |
| KeyManager[] keyManagers = getKeyManagers(keyStore, trustStore, crls); |
| TrustManager[] trustManagers = getTrustManagers(trustStore, crls); |
| |
| SecureRandom secureRandom = |
| _secureRandomAlgorithm == null ? null : SecureRandom.getInstance(_secureRandomAlgorithm); |
| SSLContext context = _sslProvider == null ? SSLContext.getInstance(_sslProtocol) : |
| SSLContext.getInstance(_sslProtocol,_sslProvider); |
| context.init(keyManagers,trustManagers,secureRandom); |
| |
| return context; |
| } |
| |
| /* ------------------------------------------------------------ */ |
| protected KeyManager[] getKeyManagers(KeyStore keyStore, KeyStore trustStore, Collection<? extends CRL> crls) throws Exception |
| { |
| KeyManagerFactory keyManagerFactory=KeyManagerFactory.getInstance(_sslKeyManagerFactoryAlgorithm); |
| keyManagerFactory.init(keyStore,_keyPassword==null?(_password==null?null:_password.toString().toCharArray()):_keyPassword.toString().toCharArray()); |
| KeyManager[] managers = keyManagerFactory.getKeyManagers(); |
| |
| if (_keyAlias != null) |
| { |
| for (int idx=0; idx < managers.length; idx++) |
| { |
| if (managers[idx] instanceof X509KeyManager) |
| { |
| managers[idx] = new SslKeyManager(_keyAlias, (X509KeyManager)managers[idx], |
| new CertificateValidator(keyStore, trustStore, crls)); |
| } |
| } |
| } |
| |
| return managers; |
| } |
| |
| /* ------------------------------------------------------------ */ |
| protected TrustManager[] getTrustManagers(KeyStore trustStore, Collection<? extends CRL> crls) throws Exception |
| { |
| TrustManager[] managers = null; |
| if (trustStore != null) |
| { |
| // Revocation checking is only supported for PKIX algorithm |
| if (_sslTrustManagerFactoryAlgorithm.equalsIgnoreCase("PKIX")) |
| { |
| PKIXBuilderParameters pbParams = |
| new PKIXBuilderParameters(trustStore, new X509CertSelector()); |
| |
| // Enable revocation checking |
| pbParams.setRevocationEnabled(true); |
| |
| // Set maximum certification path length |
| pbParams.setMaxPathLength(_maxCertPathLength); |
| |
| if (crls != null && !crls.isEmpty()) |
| { |
| pbParams.addCertStore(CertStore.getInstance("Collection", |
| new CollectionCertStoreParameters(crls))); |
| } |
| |
| // Enable On-Line Certificate Status Protocol (OCSP) support |
| Security.setProperty("ocsp.enable", "true"); |
| |
| // Enable Certificate Revocation List Distribution Points (CRLDP) support |
| System.setProperty("com.sun.security.enableCRLDP","true"); |
| |
| TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(_sslTrustManagerFactoryAlgorithm); |
| trustManagerFactory.init(new CertPathTrustManagerParameters(pbParams)); |
| |
| managers = trustManagerFactory.getTrustManagers(); |
| } |
| else |
| { |
| TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(_sslTrustManagerFactoryAlgorithm); |
| trustManagerFactory.init(trustStore); |
| |
| managers = trustManagerFactory.getTrustManagers(); |
| } |
| } |
| |
| return managers; |
| } |
| |
| private Collection<? extends CRL> loadCRL(String crlPath) throws Exception |
| { |
| Collection<? extends CRL> crlList = null; |
| |
| InputStream in = null; |
| try { |
| in = Resource.newResource(crlPath).getInputStream(); |
| crlList = CertificateFactory.getInstance("X.509").generateCRLs(in); |
| } |
| finally |
| { |
| if (in != null) |
| { |
| in.close(); |
| } |
| } |
| |
| return crlList; |
| } |
| |
| /* ------------------------------------------------------------ */ |
| protected KeyStore getKeyStore(String storePath, String storeType, String storeProvider, String storePassword) throws Exception |
| { |
| if (storePath == null) |
| return null; |
| |
| KeyStore keystore = null; |
| InputStream inStream = null; |
| try |
| { |
| if (storeProvider != null) |
| { |
| keystore = KeyStore.getInstance(storeType, storeProvider); |
| } |
| else |
| { |
| keystore = KeyStore.getInstance(storeType); |
| } |
| |
| inStream = Resource.newResource(storePath).getInputStream(); |
| keystore.load(inStream, storePassword == null ? null : storePassword.toCharArray()); |
| |
| return keystore; |
| } |
| finally |
| { |
| if (inStream != null) |
| { |
| inStream.close(); |
| } |
| } |
| } |
| |
| protected KeyStore getTrustStore(String trustPath, String trustType, String trustProvider, String trustPassword) throws Exception |
| { |
| if (trustPath==null) |
| { |
| trustPath = System.getProperty("javax.net.ssl.trustStore"); |
| trustType = System.getProperty("javax.net.ssl.trustStoreType"); |
| trustProvider = System.getProperty("javax.net.ssl.trustStoreProvider"); |
| trustPassword = System.getProperty("javax.net.ssl.trustStorePassword"); |
| } |
| |
| if (trustPath==null) |
| { |
| trustPath = _keystorePath; |
| trustType = _keystoreType; |
| trustProvider = _keystoreProvider; |
| trustPassword = _password.toString(); |
| _sslTrustManagerFactoryAlgorithm = _sslKeyManagerFactoryAlgorithm; |
| } |
| |
| return getKeyStore(trustPath, trustType, trustProvider, trustPassword); |
| } |
| } |