diff --git a/VERSION.txt b/VERSION.txt index fee83e2715a..8f60067ce9d 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1,5 +1,6 @@ jetty-7.0.0.RC2-SNAPSHOT + 283844 Webapp / TLD errors are not clear + + 283375 improved extensibility of SSL connectors jetty-7.0.0.RC1 15 June 2009 + JETTY-1066 283357 400 response for bad URIs diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/ssl/SslConnector.java b/jetty-server/src/main/java/org/eclipse/jetty/server/ssl/SslConnector.java new file mode 100644 index 00000000000..d6ef93a5ef9 --- /dev/null +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/ssl/SslConnector.java @@ -0,0 +1,220 @@ +package org.eclipse.jetty.server.ssl; + +import java.io.File; +import java.security.SecureRandom; + +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLEngine; +import javax.net.ssl.TrustManagerFactory; + +import org.eclipse.jetty.server.Connector; + + +/* ------------------------------------------------------------ */ +/** The interface for SSL connectors and their configuration methods. + * + */ +public interface SslConnector extends Connector +{ + + /** Default value for the keystore location path. */ + public static final String DEFAULT_KEYSTORE = System.getProperty("user.home") + File.separator + ".keystore"; + + /** String name of key password property. */ + public static final String KEYPASSWORD_PROPERTY = "org.eclipse.jetty.ssl.keypassword"; + + /** String name of keystore password property. */ + public static final String PASSWORD_PROPERTY = "org.eclipse.jetty.jetty.ssl.password"; + + + /* ------------------------------------------------------------ */ + /** + * @return The array of Ciphersuite names to exclude from + * {@link SSLEngine#setEnabledCipherSuites(String[])} + */ + public abstract String[] getExcludeCipherSuites(); + + /* ------------------------------------------------------------ */ + /** + * @param cipherSuites The array of Ciphersuite names to exclude from + * {@link SSLEngine#setEnabledCipherSuites(String[])} + */ + public abstract void setExcludeCipherSuites(String[] cipherSuites); + + /* ------------------------------------------------------------ */ + /** + * @param password The password for the key store + */ + public abstract void setPassword(String password); + + /* ------------------------------------------------------------ */ + /** + * @param password The password for the trust store + */ + public abstract void setTrustPassword(String password); + + /* ------------------------------------------------------------ */ + /** + * @param password The password (if any) for the specific key within + * the key store + */ + public abstract void setKeyPassword(String password); + + /* ------------------------------------------------------------ */ + /** + * @return The SSL protocol (default "TLS") passed to {@link SSLContext#getInstance(String, String)} + */ + public abstract String getProtocol(); + + /* ------------------------------------------------------------ */ + /** + * @param protocol The SSL protocol (default "TLS") passed to {@link SSLContext#getInstance(String, String)} + + */ + public abstract void setProtocol(String protocol); + + /* ------------------------------------------------------------ */ + /** + * @param keystore The file or URL of the SSL Key store. + */ + public abstract void setKeystore(String keystore); + + /* ------------------------------------------------------------ */ + /** + * @return The file or URL of the SSL Key store. + */ + public abstract String getKeystore(); + + /* ------------------------------------------------------------ */ + /** + * @return The type of the key store (default "JKS") + */ + public abstract String getKeystoreType(); + + /* ------------------------------------------------------------ */ + /** + * @return True if SSL needs client authentication. + * @see SSLEngine#getNeedClientAuth() + */ + public abstract boolean getNeedClientAuth(); + + /* ------------------------------------------------------------ */ + /** + * @return True if SSL wants client authentication. + * @see SSLEngine#getWantClientAuth() + */ + public abstract boolean getWantClientAuth(); + + /* ------------------------------------------------------------ */ + /** + * @param needClientAuth True if SSL needs client authentication. + * @see SSLEngine#getNeedClientAuth() + */ + public abstract void setNeedClientAuth(boolean needClientAuth); + + /* ------------------------------------------------------------ */ + /** + * @param wantClientAuth True if SSL wants client authentication. + * @see SSLEngine#getWantClientAuth() + */ + public abstract void setWantClientAuth(boolean wantClientAuth); + + /* ------------------------------------------------------------ */ + /** + * @param keystoreType The type of the key store (default "JKS") + */ + public abstract void setKeystoreType(String keystoreType); + + /* ------------------------------------------------------------ */ + /** + * @return The SSL provider name, which if set is passed to + * {@link SSLContext#getInstance(String, String)} + */ + public abstract String getProvider(); + + /* ------------------------------------------------------------ */ + /** + * @return The algorithm name, which if set is passed to + * {@link SecureRandom#getInstance(String)} to obtain the {@link SecureRandom} + * instance passed to {@link SSLContext#init(javax.net.ssl.KeyManager[], javax.net.ssl.TrustManager[], SecureRandom)} + */ + public abstract String getSecureRandomAlgorithm(); + + /* ------------------------------------------------------------ */ + /** + * @return The algorithm name (default "SunX509") used by the {@link KeyManagerFactory} + */ + public abstract String getSslKeyManagerFactoryAlgorithm(); + + /* ------------------------------------------------------------ */ + /** + * @return The algorithm name (default "SunX509") used by the {@link TrustManagerFactory} + */ + public abstract String getSslTrustManagerFactoryAlgorithm(); + + /* ------------------------------------------------------------ */ + /** + * @return The file name or URL of the trust store location + */ + public abstract String getTruststore(); + + /* ------------------------------------------------------------ */ + /** + * @return The type of the trust store (default "JKS") + */ + public abstract String getTruststoreType(); + + /* ------------------------------------------------------------ */ + /** + * @param provider The SSL provider name, which if set is passed to + * {@link SSLContext#getInstance(String, String)} + */ + public abstract void setProvider(String provider); + + /* ------------------------------------------------------------ */ + /** + * @param algorithm The algorithm name, which if set is passed to + * {@link SecureRandom#getInstance(String)} to obtain the {@link SecureRandom} + * instance passed to {@link SSLContext#init(javax.net.ssl.KeyManager[], javax.net.ssl.TrustManager[], SecureRandom)} + + */ + public abstract void setSecureRandomAlgorithm(String algorithm); + + /* ------------------------------------------------------------ */ + /** + * @param algorithm The algorithm name (default "SunX509") used by + * the {@link KeyManagerFactory} + */ + public abstract void setSslKeyManagerFactoryAlgorithm(String algorithm); + + /* ------------------------------------------------------------ */ + /** + * @param algorithm The algorithm name (default "SunX509") used by the {@link TrustManagerFactory} + */ + public abstract void setSslTrustManagerFactoryAlgorithm(String algorithm); + + /* ------------------------------------------------------------ */ + /** + * @param truststore The file name or URL of the trust store location + */ + public abstract void setTruststore(String truststore); + + /* ------------------------------------------------------------ */ + /** + * @param truststoreType The type of the trust store (default "JKS") + */ + public abstract void setTruststoreType(String truststoreType); + + /* ------------------------------------------------------------ */ + /** + * @param sslContext Set a preconfigured SSLContext + */ + public abstract void setSslContext(SSLContext sslContext); + + /* ------------------------------------------------------------ */ + /** + * @return The SSLContext + */ + public abstract SSLContext getSslContext(); +} \ No newline at end of file diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/ssl/SslSelectChannelConnector.java b/jetty-server/src/main/java/org/eclipse/jetty/server/ssl/SslSelectChannelConnector.java index b4429b1d8bc..123fbe895ef 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/ssl/SslSelectChannelConnector.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/ssl/SslSelectChannelConnector.java @@ -14,14 +14,12 @@ package org.eclipse.jetty.server.ssl; import java.io.ByteArrayInputStream; -import java.io.File; 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.X509Certificate; import java.util.ArrayList; import java.util.Arrays; @@ -66,7 +64,7 @@ import org.eclipse.jetty.util.resource.Resource; * * */ -public class SslSelectChannelConnector extends SelectChannelConnector +public class SslSelectChannelConnector extends SelectChannelConnector implements SslConnector { /** * The name of the SSLSession attribute that will contain any cached @@ -74,20 +72,11 @@ public class SslSelectChannelConnector extends SelectChannelConnector */ static final String CACHED_INFO_ATTR=CachedInfo.class.getName(); - /** Default value for the keystore location path. */ - public static final String DEFAULT_KEYSTORE=System.getProperty("user.home")+File.separator+".keystore"; - - /** String name of key password property. */ - public static final String KEYPASSWORD_PROPERTY="jetty.ssl.keypassword"; - - /** String name of keystore password property. */ - public static final String PASSWORD_PROPERTY="jetty.ssl.password"; - /** Default value for the cipher Suites. */ private String _excludeCipherSuites[]=null; /** Default value for the keystore location path. */ - private String _keystore=DEFAULT_KEYSTORE; + private String _keystorePath=DEFAULT_KEYSTORE; private String _keystoreType="JKS"; // type of the key store /** Set to true if we require client certificate authentication. */ @@ -98,18 +87,11 @@ public class SslSelectChannelConnector extends SelectChannelConnector private transient Password _keyPassword; private transient Password _trustPassword; private String _protocol="TLS"; - private String _algorithm="SunX509"; // cert algorithm private String _provider; private String _secureRandomAlgorithm; // cert algorithm - private String _sslKeyManagerFactoryAlgorithm=(Security.getProperty("ssl.KeyManagerFactory.algorithm")==null?"SunX509":Security - .getProperty("ssl.KeyManagerFactory.algorithm")); // cert - // algorithm - - private String _sslTrustManagerFactoryAlgorithm=(Security.getProperty("ssl.TrustManagerFactory.algorithm")==null?"SunX509":Security - .getProperty("ssl.TrustManagerFactory.algorithm")); // cert - // algorithm - - private String _truststore; + private String _sslKeyManagerFactoryAlgorithm="SunX509"; + private String _sslTrustManagerFactoryAlgorithm="SunX509"; + private String _truststorePath; private String _truststoreType="JKS"; // type of the key store private SSLContext _context; Buffers _sslBuffers; @@ -241,104 +223,130 @@ public class SslSelectChannelConnector extends SelectChannelConnector { } + /* ------------------------------------------------------------ */ /** - * - * @deprecated As of Java Servlet API 2.0, with no replacement. - * + * @see org.eclipse.jetty.server.ssl.SslConnector#getExcludeCipherSuites() */ - public String[] getCipherSuites() - { - return getExcludeCipherSuites(); - } - public String[] getExcludeCipherSuites() { return _excludeCipherSuites; } + /* ------------------------------------------------------------ */ /** - * - * @deprecated As of Java Servlet API 2.0, with no replacement. - * - * + * @see org.eclipse.jetty.server.ssl.SslConnector#setExcludeCipherSuites(java.lang.String[]) */ - public void setCipherSuites(String[] cipherSuites) - { - setExcludeCipherSuites(cipherSuites); - } - public void setExcludeCipherSuites(String[] cipherSuites) { this._excludeCipherSuites=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()} + */ public String getAlgorithm() { - return (this._algorithm); + return getSslKeyManagerFactoryAlgorithm(); } /* ------------------------------------------------------------ */ + /** + * @deprecated use {@link #setSslKeyManagerFactoryAlgorithm(String)} or + * {@link #setSslTrustManagerFactoryAlgorithm(String)} + */ public void setAlgorithm(String algorithm) { - this._algorithm=algorithm; + setSslKeyManagerFactoryAlgorithm(algorithm); + setSslTrustManagerFactoryAlgorithm(algorithm); } /* ------------------------------------------------------------ */ + /** + * @see org.eclipse.jetty.server.ssl.SslConnector#getProtocol() + */ public String getProtocol() { return _protocol; } /* ------------------------------------------------------------ */ + /** + * @see org.eclipse.jetty.server.ssl.SslConnector#setProtocol(java.lang.String) + */ public void setProtocol(String protocol) { _protocol=protocol; } /* ------------------------------------------------------------ */ + /** + * @see org.eclipse.jetty.server.ssl.SslConnector#setKeystore(java.lang.String) + */ public void setKeystore(String keystore) { - _keystore=keystore; + _keystorePath=keystore; } /* ------------------------------------------------------------ */ + /** + * @see org.eclipse.jetty.server.ssl.SslConnector#getKeystore() + */ public String getKeystore() { - return _keystore; + 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; @@ -346,100 +354,168 @@ public class SslSelectChannelConnector extends SelectChannelConnector /* ------------------------------------------------------------ */ /** - * Set the value of the needClientAuth property - * - * @param needClientAuth - * true iff we require client certificate authentication. + * @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 _provider; } + /* ------------------------------------------------------------ */ + /** + * @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 _truststore; + return _truststorePath; } /* ------------------------------------------------------------ */ + /** + * @see org.eclipse.jetty.server.ssl.SslConnector#getTruststoreType() + */ public String getTruststoreType() { return _truststoreType; } /* ------------------------------------------------------------ */ - public void setProvider(String _provider) + /** + * @see org.eclipse.jetty.server.ssl.SslConnector#setProvider(java.lang.String) + */ + public void setProvider(String provider) { - this._provider=_provider; + _provider=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) { - _truststore=truststore; + _truststorePath=truststore; } + /* ------------------------------------------------------------ */ + /** + * @see org.eclipse.jetty.server.ssl.SslConnector#setTruststoreType(java.lang.String) + */ public void setTruststoreType(String truststoreType) { _truststoreType=truststoreType; } - - public void setSslContext(SSLContext sslContext) { - this._context = sslContext; - } - + + /* ------------------------------------------------------------ */ + /** + * @see org.eclipse.jetty.server.ssl.SslConnector#setSslContext(javax.net.ssl.SSLContext) + */ + public void setSslContext(SSLContext sslContext) + { + _context = sslContext; + } + + /* ------------------------------------------------------------ */ + /** + * @throws Exception + * @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 @@ -529,9 +605,8 @@ public class SslSelectChannelConnector extends SelectChannelConnector protected void doStart() throws Exception { - if (_context == null) { + if (_context == null) _context=createSSLContext(); - } SSLEngine engine=createSSLEngine(); SSLSession ssl_session=engine.getSession(); @@ -568,60 +643,12 @@ public class SslSelectChannelConnector extends SelectChannelConnector super.doStart(); } + /* ------------------------------------------------------------ */ protected SSLContext createSSLContext() throws Exception { - if (_truststore==null) - { - _truststore=_keystore; - _truststoreType=_keystoreType; - } + KeyManager[] keyManagers=getKeyManagers(); - InputStream keystoreInputStream = null; - - KeyManager[] keyManagers=null; - KeyStore keyStore = null; - try - { - if (_keystore!=null) - { - keystoreInputStream=Resource.newResource(_keystore).getInputStream(); - keyStore = KeyStore.getInstance(_keystoreType); - keyStore.load(keystoreInputStream,_password==null?null:_password.toString().toCharArray()); - } - } - finally - { - if (keystoreInputStream != null) - keystoreInputStream.close(); - } - - KeyManagerFactory keyManagerFactory=KeyManagerFactory.getInstance(_sslKeyManagerFactoryAlgorithm); - keyManagerFactory.init(keyStore,_keyPassword==null?(_password==null?null:_password.toString().toCharArray()):_keyPassword.toString().toCharArray()); - keyManagers=keyManagerFactory.getKeyManagers(); - - - TrustManager[] trustManagers=null; - InputStream truststoreInputStream = null; - KeyStore trustStore = null; - try - { - if (_truststore!=null) - { - truststoreInputStream = Resource.newResource(_truststore).getInputStream(); - trustStore=KeyStore.getInstance(_truststoreType); - trustStore.load(truststoreInputStream,_trustPassword==null?null:_trustPassword.toString().toCharArray()); - } - } - finally - { - if (truststoreInputStream != null) - truststoreInputStream.close(); - } - - - TrustManagerFactory trustManagerFactory=TrustManagerFactory.getInstance(_sslTrustManagerFactoryAlgorithm); - trustManagerFactory.init(trustStore); - trustManagers=trustManagerFactory.getTrustManagers(); + TrustManager[] trustManagers=getTrustManagers(); SecureRandom secureRandom=_secureRandomAlgorithm==null?null:SecureRandom.getInstance(_secureRandomAlgorithm); SSLContext context=_provider==null?SSLContext.getInstance(_protocol):SSLContext.getInstance(_protocol,_provider); @@ -629,6 +656,57 @@ public class SslSelectChannelConnector extends SelectChannelConnector return context; } + /* ------------------------------------------------------------ */ + protected KeyManager[] getKeyManagers() throws Exception + { + KeyStore keyStore = getKeyStore(_keystorePath, _keystoreType, _password.toString()); + + KeyManagerFactory keyManagerFactory=KeyManagerFactory.getInstance(_sslKeyManagerFactoryAlgorithm); + keyManagerFactory.init(keyStore,_keyPassword==null?(_password==null?null:_password.toString().toCharArray()):_keyPassword.toString().toCharArray()); + return keyManagerFactory.getKeyManagers(); + } + + /* ------------------------------------------------------------ */ + protected TrustManager[] getTrustManagers() throws Exception + { + if (_truststorePath==null) + { + _truststorePath=_keystorePath; + _truststoreType=_keystoreType; + _trustPassword = _password; + _sslTrustManagerFactoryAlgorithm = _sslKeyManagerFactoryAlgorithm; + } + + KeyStore trustStore = getKeyStore(_truststorePath, _truststoreType, _trustPassword.toString()); + + TrustManagerFactory trustManagerFactory=TrustManagerFactory.getInstance(_sslTrustManagerFactoryAlgorithm); + trustManagerFactory.init(trustStore); + return trustManagerFactory.getTrustManagers(); + } + + /* ------------------------------------------------------------ */ + protected KeyStore getKeyStore(String keystorePath, String keystoreType, String keystorePassword) throws Exception + { + KeyStore keystore; + InputStream keystoreInputStream = null; + try + { + if (keystorePath!=null) + keystoreInputStream = Resource.newResource(keystorePath).getInputStream(); + keystore=KeyStore.getInstance(keystoreType); + keystore.load(keystoreInputStream,keystorePassword==null?null:keystorePassword.toString().toCharArray()); + return keystore; + } + finally + { + if (keystoreInputStream != null) + keystoreInputStream.close(); + } + } + + /* ------------------------------------------------------------ */ + /* ------------------------------------------------------------ */ + /* ------------------------------------------------------------ */ /** * Simple bundle of information that is cached in the SSLSession. Stores the * effective keySize and the client certificate chain. diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/ssl/SslSocketConnector.java b/jetty-server/src/main/java/org/eclipse/jetty/server/ssl/SslSocketConnector.java index 4238526acdb..2715c83d978 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/ssl/SslSocketConnector.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/ssl/SslSocketConnector.java @@ -54,38 +54,26 @@ import org.eclipse.jetty.util.resource.Resource; /* ------------------------------------------------------------ */ /** - * JSSE Socket Listener. + * SSL Socket Connector. * - * This specialization of HttpListener is an abstract listener that can be used as the basis for a + * This specialization of SocketConnector is an abstract listener that can be used as the basis for a * specific JSSE listener. * - * This is heavily based on the work from Court Demas, which in turn is based on the work from Forge - * Research. + * The original of this class was heavily based on the work from Court Demas, which in turn is + * based on the work from Forge Research. Since JSSE, this class has evolved significantly from + * that early work. * * @org.apache.xbean.XBean element="sslSocketConnector" description="Creates an ssl socket connector" * * - * - * - * */ -public class SslSocketConnector extends SocketConnector +public class SslSocketConnector extends SocketConnector implements SslConnector { /** * The name of the SSLSession attribute that will contain any cached information. */ static final String CACHED_INFO_ATTR = CachedInfo.class.getName(); - /** Default value for the keystore location path. */ - public static final String DEFAULT_KEYSTORE = System.getProperty("user.home") + File.separator - + ".keystore"; - - /** String name of key password property. */ - public static final String KEYPASSWORD_PROPERTY = "jetty.ssl.keypassword"; - - /** String name of keystore password property. */ - public static final String PASSWORD_PROPERTY = "jetty.ssl.password"; - /** * Return the chain of X509 certificates used to negotiate the SSL Session. *

@@ -135,7 +123,7 @@ public class SslSocketConnector extends SocketConnector private String _excludeCipherSuites[] = null; /** Default value for the keystore location path. */ - private String _keystore=DEFAULT_KEYSTORE ; + private String _keystorePath=DEFAULT_KEYSTORE ; private String _keystoreType = "JKS"; // type of the key store /** Set to true if we require client certificate authentication. */ @@ -149,7 +137,7 @@ public class SslSocketConnector extends SocketConnector private String _sslKeyManagerFactoryAlgorithm = (Security.getProperty("ssl.KeyManagerFactory.algorithm")==null?"SunX509":Security.getProperty("ssl.KeyManagerFactory.algorithm")); // cert algorithm private String _sslTrustManagerFactoryAlgorithm = (Security.getProperty("ssl.TrustManagerFactory.algorithm")==null?"SunX509":Security.getProperty("ssl.TrustManagerFactory.algorithm")); // cert algorithm - private String _truststore; + private String _truststorePath; private String _truststoreType = "JKS"; // type of the key store /** Set to true if we would like client certificate authentication. */ @@ -187,49 +175,76 @@ public class SslSocketConnector extends SocketConnector super.configure(socket); } + /* ------------------------------------------------------------ */ + protected SSLContext createSSLContext() throws Exception + { + KeyManager[] keyManagers = getKeyManagers(); + TrustManager[] trustManagers = getTrustManagers(); + SecureRandom secureRandom = _secureRandomAlgorithm==null?null:SecureRandom.getInstance(_secureRandomAlgorithm); + SSLContext context = _provider==null?SSLContext.getInstance(_protocol):SSLContext.getInstance(_protocol, _provider); + context.init(keyManagers, trustManagers, secureRandom); + return context; + } + /* ------------------------------------------------------------ */ protected SSLServerSocketFactory createFactory() throws Exception { - SSLContext context = _context; - if (context == null) { - if (_truststore==null) - { - _truststore=_keystore; - _truststoreType=_keystoreType; - } - - KeyManager[] keyManagers = null; - InputStream keystoreInputStream = null; - if (_keystore != null) - keystoreInputStream = Resource.newResource(_keystore).getInputStream(); - KeyStore keyStore = KeyStore.getInstance(_keystoreType); - keyStore.load(keystoreInputStream, _password==null?null:_password.toString().toCharArray()); - - KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(_sslKeyManagerFactoryAlgorithm); - keyManagerFactory.init(keyStore,_keyPassword==null?null:_keyPassword.toString().toCharArray()); - keyManagers = keyManagerFactory.getKeyManagers(); - - TrustManager[] trustManagers = null; - InputStream truststoreInputStream = null; - if (_truststore != null) - truststoreInputStream = Resource.newResource(_truststore).getInputStream(); - KeyStore trustStore = KeyStore.getInstance(_truststoreType); - trustStore.load(truststoreInputStream,_trustPassword==null?null:_trustPassword.toString().toCharArray()); - - TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(_sslTrustManagerFactoryAlgorithm); - trustManagerFactory.init(trustStore); - trustManagers = trustManagerFactory.getTrustManagers(); - - - SecureRandom secureRandom = _secureRandomAlgorithm==null?null:SecureRandom.getInstance(_secureRandomAlgorithm); - - context = _provider==null?SSLContext.getInstance(_protocol):SSLContext.getInstance(_protocol, _provider); - - context.init(keyManagers, trustManagers, secureRandom); - } + if (_context==null) + _context=createSSLContext(); - return context.getServerSocketFactory(); + return _context.getServerSocketFactory(); + } + + + /* ------------------------------------------------------------ */ + protected KeyManager[] getKeyManagers() throws Exception + { + KeyStore keyStore = getKeyStore(_keystorePath, _keystoreType, _password.toString()); + + KeyManagerFactory keyManagerFactory=KeyManagerFactory.getInstance(_sslKeyManagerFactoryAlgorithm); + keyManagerFactory.init(keyStore,_keyPassword==null?(_password==null?null:_password.toString().toCharArray()):_keyPassword.toString().toCharArray()); + return keyManagerFactory.getKeyManagers(); + } + + protected TrustManager[] getTrustManagers() throws Exception + { + if (_truststorePath==null) + { + _truststorePath=_keystorePath; + _truststoreType=_keystoreType; + //TODO is this right? it wasn't in the code before refactoring + _trustPassword = _password; + _sslTrustManagerFactoryAlgorithm = _sslKeyManagerFactoryAlgorithm; + } + KeyStore trustStore = getKeyStore(_truststorePath, _truststoreType, _trustPassword.toString()); + + TrustManagerFactory trustManagerFactory=TrustManagerFactory.getInstance(_sslTrustManagerFactoryAlgorithm); + trustManagerFactory.init(trustStore); + return trustManagerFactory.getTrustManagers(); + } + + protected KeyStore getKeyStore(String keystorePath, String keystoreType, String keystorePassword) throws Exception + { + KeyStore keystore; + InputStream keystoreInputStream = null; + try + { + if (keystorePath!=null) + { + keystoreInputStream = Resource.newResource(keystorePath).getInputStream(); + keystore=KeyStore.getInstance(keystoreType); + keystore.load(keystoreInputStream,keystorePassword==null?null:keystorePassword.toString().toCharArray()); + return keystore; + } + + return null; + } + finally + { + if (keystoreInputStream != null) + keystoreInputStream.close(); + } } /* ------------------------------------------------------------ */ @@ -309,7 +324,7 @@ public class SslSocketConnector extends SocketConnector /* ------------------------------------------------------------ */ public String getKeystore() { - return _keystore; + return _keystorePath; } /* ------------------------------------------------------------ */ @@ -356,7 +371,7 @@ public class SslSocketConnector extends SocketConnector /* ------------------------------------------------------------ */ public String getTruststore() { - return _truststore; + return _truststorePath; } /* ------------------------------------------------------------ */ @@ -483,7 +498,7 @@ public class SslSocketConnector extends SocketConnector */ public void setKeystore(String keystore) { - _keystore = keystore; + _keystorePath = keystore; } /* ------------------------------------------------------------ */ @@ -547,7 +562,7 @@ public class SslSocketConnector extends SocketConnector public void setTruststore(String truststore) { - _truststore = truststore; + _truststorePath = truststore; } @@ -561,6 +576,26 @@ public class SslSocketConnector extends SocketConnector _context = sslContext; } + /* ------------------------------------------------------------ */ + /** + * @throws Exception + * @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; + } + /* ------------------------------------------------------------ */ /** * Set the value of the _wantClientAuth property. This property is used when @@ -574,6 +609,7 @@ public class SslSocketConnector extends SocketConnector _wantClientAuth = wantClientAuth; } + /* ------------------------------------------------------------ */ /** * Set the time in milliseconds for so_timeout during ssl handshaking * @param msec a non-zero value will be used to set so_timeout during @@ -584,11 +620,14 @@ public class SslSocketConnector extends SocketConnector _handshakeTimeout = msec; } - + + /* ------------------------------------------------------------ */ public int getHandshakeTimeout () { return _handshakeTimeout; } + + /* ------------------------------------------------------------ */ /** * Simple bundle of information that is cached in the SSLSession. Stores the effective keySize * and the client certificate chain. @@ -623,7 +662,8 @@ public class SslSocketConnector extends SocketConnector } } - + + /* ------------------------------------------------------------ */ public class SslConnection extends Connection { public SslConnection(Socket socket) throws IOException @@ -662,4 +702,23 @@ public class SslSocketConnector extends SocketConnector } } + /* ------------------------------------------------------------ */ + /** + * Unsupported. + * @see org.eclipse.jetty.server.ssl.SslConnector#getAlgorithm() + */ + public String getAlgorithm() + { + throw new UnsupportedOperationException(); + } + + /* ------------------------------------------------------------ */ + /** + * Unsupported. + * @see org.eclipse.jetty.server.ssl.SslConnector#setAlgorithm(java.lang.String) + */ + public void setAlgorithm(String algorithm) + { + throw new UnsupportedOperationException(); + } }