316382: support a more strict SSL option with certificates
git-svn-id: svn+ssh://dev.eclipse.org/svnroot/rt/org.eclipse.jetty/sandbox/trunk@2776 7e9141cc-0065-0410-87d8-b60c137991c4
diff --git a/jetty-exssl/src/main/java/org/eclipse/jetty/client/HttpClient.java b/jetty-exssl/src/main/java/org/eclipse/jetty/client/HttpClient.java
index 5bf5fc9..207f6f6 100644
--- a/jetty-exssl/src/main/java/org/eclipse/jetty/client/HttpClient.java
+++ b/jetty-exssl/src/main/java/org/eclipse/jetty/client/HttpClient.java
@@ -716,7 +716,7 @@
/* ------------------------------------------------------------ */
public void setKeyStorePassword(String keyStorePassword)
{
- _sslContextFactory.setKeyStorePassword(keyStorePassword);
+ _sslContextFactory.setKeystorePassword(keyStorePassword);
}
/* ------------------------------------------------------------ */
@@ -728,7 +728,7 @@
/* ------------------------------------------------------------ */
public void setTrustStorePassword(String trustStorePassword)
{
- _sslContextFactory.setTrustStorePassword(trustStorePassword);
+ _sslContextFactory.setTruststorePassword(trustStorePassword);
}
/* ------------------------------------------------------------ */
diff --git a/jetty-exssl/src/main/java/org/eclipse/jetty/exssl/SslSelectChannelConnector.java b/jetty-exssl/src/main/java/org/eclipse/jetty/exssl/SslSelectChannelConnector.java
index 1508157..7b9af6b 100644
--- a/jetty-exssl/src/main/java/org/eclipse/jetty/exssl/SslSelectChannelConnector.java
+++ b/jetty-exssl/src/main/java/org/eclipse/jetty/exssl/SslSelectChannelConnector.java
@@ -173,7 +173,7 @@
*/
public void setPassword(String password)
{
- _sslContextFactory.setKeyStorePassword(password);
+ _sslContextFactory.setKeystorePassword(password);
}
/* ------------------------------------------------------------ */
@@ -182,7 +182,7 @@
*/
public void setTrustPassword(String password)
{
- _sslContextFactory.setTrustStorePassword(password);
+ _sslContextFactory.setTruststorePassword(password);
}
/* ------------------------------------------------------------ */
@@ -488,7 +488,17 @@
SSLEngine engine = null;
try
{
+ engine = _sslContextFactory.getSslContext().createSSLEngine();
+ engine.setUseClientMode(false);
+ if (_sslContextFactory.getWantClientAuth())
+ engine.setWantClientAuth(_sslContextFactory.getWantClientAuth());
+ if (_sslContextFactory.getWantClientAuth())
+ engine.setNeedClientAuth(_sslContextFactory.getNeedClientAuth());
+
+ engine.setEnabledCipherSuites(
+ _sslContextFactory.selectCipherSuites(engine.getEnabledCipherSuites(),
+ engine.getSupportedCipherSuites()));
}
catch (Exception e)
{
diff --git a/jetty-exssl/src/main/java/org/eclipse/jetty/exssl/SslSocketConnector.java b/jetty-exssl/src/main/java/org/eclipse/jetty/exssl/SslSocketConnector.java
index b826344..a27929e 100644
--- a/jetty-exssl/src/main/java/org/eclipse/jetty/exssl/SslSocketConnector.java
+++ b/jetty-exssl/src/main/java/org/eclipse/jetty/exssl/SslSocketConnector.java
@@ -286,8 +286,10 @@
factory.createServerSocket(port,backlog):
factory.createServerSocket(port,backlog,InetAddress.getByName(host)));
- socket.setWantClientAuth(_sslContextFactory.getWantClientAuth());
- socket.setNeedClientAuth(_sslContextFactory.getNeedClientAuth());
+ if (_sslContextFactory.getWantClientAuth())
+ socket.setWantClientAuth(_sslContextFactory.getWantClientAuth());
+ if (_sslContextFactory.getNeedClientAuth())
+ socket.setNeedClientAuth(_sslContextFactory.getNeedClientAuth());
socket.setEnabledCipherSuites(_sslContextFactory.selectCipherSuites(
socket.getEnabledCipherSuites(),
@@ -345,13 +347,13 @@
/* ------------------------------------------------------------ */
public void setPassword(String password)
{
- _sslContextFactory.setKeyStorePassword(password);
+ _sslContextFactory.setKeystorePassword(password);
}
/* ------------------------------------------------------------ */
public void setTrustPassword(String password)
{
- _sslContextFactory.setTrustStorePassword(password);
+ _sslContextFactory.setTruststorePassword(password);
}
/* ------------------------------------------------------------ */
diff --git a/jetty-exssl/src/main/java/org/eclipse/jetty/io/SslContextFactory.java b/jetty-exssl/src/main/java/org/eclipse/jetty/io/SslContextFactory.java
index 6c1bcb5..4092637 100644
--- a/jetty-exssl/src/main/java/org/eclipse/jetty/io/SslContextFactory.java
+++ b/jetty-exssl/src/main/java/org/eclipse/jetty/io/SslContextFactory.java
@@ -19,7 +19,6 @@
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
-import java.io.IOException;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.SecureRandom;
@@ -469,7 +468,7 @@
* @param password
* The password for the key store
*/
- public SslContextFactory setKeyStorePassword(String password)
+ public SslContextFactory setKeystorePassword(String password)
{
_keystorePassword = Password.getPassword(PASSWORD_PROPERTY,password,null);
@@ -493,7 +492,7 @@
* @param password
* The password for the trust store
*/
- public SslContextFactory setTrustStorePassword(String password)
+ public SslContextFactory setTruststorePassword(String password)
{
_truststorePassword = Password.getPassword(PASSWORD_PROPERTY,password,null);
@@ -749,6 +748,8 @@
/* ------------------------------------------------------------ */
public SSLContext createSSLContext() throws Exception
{
+ // verify that keystore and truststore
+ // parameters are set up correctly
checkConfig();
KeyStore keyStore = getKeyStore(_keystoreInputStream, _keystorePath, _keystoreType,
@@ -757,20 +758,20 @@
_truststoreProvider, _truststorePassword==null? null: _truststorePassword.toString());
Collection<? extends CRL> crls = loadCRL(_crlPath);
- if (_certAlias == null)
+ if (_validateCerts && keyStore != null)
{
- List<String> aliases = Collections.list(keyStore.aliases());
- _certAlias = aliases.size() == 1?aliases.get(0):null;
- }
+ if (_certAlias == null)
+ {
+ List<String> aliases = Collections.list(keyStore.aliases());
+ _certAlias = aliases.size() == 1 ? aliases.get(0) : null;
+ }
+
+ Certificate cert = _certAlias == null?null:keyStore.getCertificate(_certAlias);
+ if (cert == null)
+ {
+ throw new Exception("No certificate found in the keystore" + (_certAlias==null ? "":" for alias " + _certAlias));
+ }
- Certificate cert = _certAlias == null?null:keyStore.getCertificate(_certAlias);
- if (cert == null)
- {
- throw new Exception("No certificate found in the keystore" + (_certAlias == null?"":" for alias " + _certAlias));
- }
-
- if (_validateCerts)
- {
CertificateValidator validator = new CertificateValidator(trustStore,crls);
validator.validate(keyStore, cert);
}
@@ -917,7 +918,8 @@
protected void checkConfig()
{
/*
- * if the keystore exists but the trust store doesn't use the keystore as the trust store
+ * if the keystore exists but the trust store
+ * does not, use the keystore as the trust store
*/
if (_keystoreInputStream != null || _keystorePath != null)
{
@@ -932,7 +934,7 @@
}
}
- // It's the same stream and we cannot read it twice, so we read it once in memory
+ // It's the same stream we cannot read it twice, so read it once in memory
if (_keystoreInputStream != null && _keystoreInputStream == _truststoreInputStream)
{
try
diff --git a/jetty-exssl/src/test/java/org/eclipse/jetty/client/ContentExchangeTest.java b/jetty-exssl/src/test/java/org/eclipse/jetty/client/ContentExchangeTest.java
index 3267530..b1321af 100644
--- a/jetty-exssl/src/test/java/org/eclipse/jetty/client/ContentExchangeTest.java
+++ b/jetty-exssl/src/test/java/org/eclipse/jetty/client/ContentExchangeTest.java
@@ -213,12 +213,20 @@
throws Exception
{
_client = new HttpClient();
- _client.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
+ configureClient(_client);
+
if (realm != null)
_client.setRealmResolver(new SimpleRealmResolver(realm));
+
_client.start();
}
+ protected void configureClient(HttpClient client)
+ throws Exception
+ {
+ client.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
+ }
+
protected void stopClient()
throws Exception
{
diff --git a/jetty-exssl/src/test/java/org/eclipse/jetty/exssl/CertificateValidationTestBase.java b/jetty-exssl/src/test/java/org/eclipse/jetty/exssl/CertificateValidationTestBase.java
deleted file mode 100644
index c823bd3..0000000
--- a/jetty-exssl/src/test/java/org/eclipse/jetty/exssl/CertificateValidationTestBase.java
+++ /dev/null
@@ -1,79 +0,0 @@
-package org.eclipse.jetty.exssl;
-
-import java.io.File;
-import java.lang.reflect.Constructor;
-import java.security.cert.CertificateException;
-
-import org.eclipse.jetty.io.SslContextFactory;
-import org.eclipse.jetty.server.Server;
-import org.eclipse.jetty.server.ssl.SslConnector;
-import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
-import org.junit.After;
-import org.junit.Test;
-
-public abstract class CertificateValidationTestBase
-{
- protected Server _server;
- protected Class<? extends SslConnector> _klass;
-
- @After
- public void tearDown()
- {
- try
- {
- _server.stop();
- _server = null;
- }
- catch (Exception ex) {}
- }
-
- protected void doTest(String keystore) throws Exception
- {
- String keypath = MavenTestingUtils.getTestResourceFile(keystore).getAbsolutePath();
- String trustpath = new File(System.getProperty("java.home"),"./lib/security/cacerts").getAbsolutePath();
- String crlpath = MavenTestingUtils.getTestResourceFile("crlfile.pem").getAbsolutePath();
-
- SslContextFactory sslContextFactory = new SslContextFactory();
- sslContextFactory.setValidateCerts(true);
- sslContextFactory.setKeystore(keypath);
- sslContextFactory.setKeyStorePassword("webtide");
- sslContextFactory.setKeyManagerPassword("webtide");
- sslContextFactory.setTruststore(trustpath);
- sslContextFactory.setTrustStorePassword("changeit");
- sslContextFactory.setCrlPath(crlpath);
-
- Constructor<? extends SslConnector> constructor = _klass.getConstructor(SslContextFactory.class);
- SslConnector connector = constructor.newInstance(sslContextFactory);
- connector.setPort(0);
-
- _server = new Server();
- _server.addConnector(connector);
- _server.start();
-
- Thread.sleep(1000);
- }
-
- @Test
- public void validCertificateTest() throws Exception
- {
- doTest("jetty-valid.keystore"); // certificate is valid until Jan 1, 2050
- }
-
- @Test(expected = CertificateException.class)
- public void revokedCertificateTest() throws Exception
- {
- doTest("jetty-revoked.keystore"); // certificate is valid until Jan 1, 2050
- }
-
- @Test(expected = CertificateException.class)
- public void notvalidCertificateTest() throws Exception
- {
- doTest("jetty-notvalid.keystore"); // certificate is valid from Jan 1, 2049
- }
-
- @Test(expected = CertificateException.class)
- public void expiredCertificateTest() throws Exception
- {
- doTest("jetty-expired.keystore"); // certificate is valid until Dec 31, 2000
- }
-}
diff --git a/jetty-exssl/src/test/java/org/eclipse/jetty/exssl/CertificateValidatorTest.java b/jetty-exssl/src/test/java/org/eclipse/jetty/exssl/CertificateValidatorTest.java
new file mode 100644
index 0000000..aa64a15
--- /dev/null
+++ b/jetty-exssl/src/test/java/org/eclipse/jetty/exssl/CertificateValidatorTest.java
@@ -0,0 +1,53 @@
+package org.eclipse.jetty.exssl;
+
+import java.io.File;
+import java.security.cert.CertificateException;
+
+import org.eclipse.jetty.io.SslContextFactory;
+import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
+import org.junit.Test;
+
+public class CertificateValidatorTest
+{
+ protected void doTest(String keystore) throws Exception
+ {
+ String keypath = MavenTestingUtils.getTestResourceFile(keystore).getAbsolutePath();
+ String trustpath = new File(System.getProperty("java.home"),"./lib/security/cacerts").getAbsolutePath();
+ String crlpath = MavenTestingUtils.getTestResourceFile("crlfile.pem").getAbsolutePath();
+
+ SslContextFactory factory = new SslContextFactory();
+ factory.setValidateCerts(true);
+ factory.setKeystore(keypath);
+ factory.setKeystorePassword("webtide");
+ factory.setKeyManagerPassword("webtide");
+ factory.setTruststore(trustpath);
+ factory.setTruststorePassword("changeit");
+ factory.setCrlPath(crlpath);
+
+ factory.createSSLContext();
+ }
+
+ @Test
+ public void validCertificateTest() throws Exception
+ {
+ doTest("jetty-valid.keystore"); // certificate is valid until Jan 1, 2050
+ }
+
+ @Test(expected = CertificateException.class)
+ public void revokedCertificateTest() throws Exception
+ {
+ doTest("jetty-revoked.keystore"); // certificate is valid until Jan 1, 2050
+ }
+
+ @Test(expected = CertificateException.class)
+ public void notvalidCertificateTest() throws Exception
+ {
+ doTest("jetty-notvalid.keystore"); // certificate is valid from Jan 1, 2049
+ }
+
+ @Test(expected = CertificateException.class)
+ public void expiredCertificateTest() throws Exception
+ {
+ doTest("jetty-expired.keystore"); // certificate is valid until Dec 31, 2000
+ }
+}
diff --git a/jetty-exssl/src/test/java/org/eclipse/jetty/exssl/SslSelectChannelValidationTest.java b/jetty-exssl/src/test/java/org/eclipse/jetty/exssl/SslSelectChannelValidationTest.java
index 56fadd6..955ce72 100644
--- a/jetty-exssl/src/test/java/org/eclipse/jetty/exssl/SslSelectChannelValidationTest.java
+++ b/jetty-exssl/src/test/java/org/eclipse/jetty/exssl/SslSelectChannelValidationTest.java
@@ -1,12 +1,12 @@
package org.eclipse.jetty.exssl;
-import org.junit.Before;
+import org.eclipse.jetty.client.HttpClient;
-public class SslSelectChannelValidationTest extends CertificateValidationTestBase
+public class SslSelectChannelValidationTest extends SslValidationTestBase
{
- @Before
- public void setUp()
+ static
{
- _klass = SslSelectChannelConnector.class;
+ __klass = SslSelectChannelConnector.class;
+ __konnector = HttpClient.CONNECTOR_SELECT_CHANNEL;
}
}
diff --git a/jetty-exssl/src/test/java/org/eclipse/jetty/exssl/SslSocketValidationTest.java b/jetty-exssl/src/test/java/org/eclipse/jetty/exssl/SslSocketValidationTest.java
index 5337d27..8f52403 100644
--- a/jetty-exssl/src/test/java/org/eclipse/jetty/exssl/SslSocketValidationTest.java
+++ b/jetty-exssl/src/test/java/org/eclipse/jetty/exssl/SslSocketValidationTest.java
@@ -1,12 +1,12 @@
package org.eclipse.jetty.exssl;
-import org.junit.Before;
+import org.eclipse.jetty.client.HttpClient;
-public class SslSocketValidationTest extends CertificateValidationTestBase
+public class SslSocketValidationTest extends SslValidationTestBase
{
- @Before
- public void setUp()
+ static
{
- _klass = SslSocketConnector.class;
+ __klass = SslSocketConnector.class;
+ __konnector = HttpClient.CONNECTOR_SOCKET;
}
}
diff --git a/jetty-exssl/src/test/java/org/eclipse/jetty/exssl/SslValidationTestBase.java b/jetty-exssl/src/test/java/org/eclipse/jetty/exssl/SslValidationTestBase.java
new file mode 100644
index 0000000..f835623
--- /dev/null
+++ b/jetty-exssl/src/test/java/org/eclipse/jetty/exssl/SslValidationTestBase.java
@@ -0,0 +1,71 @@
+package org.eclipse.jetty.exssl;
+
+import java.io.File;
+import java.lang.reflect.Constructor;
+
+import org.eclipse.jetty.client.HttpClient;
+import org.eclipse.jetty.client.SslContentExchangeTest;
+import org.eclipse.jetty.io.SslContextFactory;
+import org.eclipse.jetty.server.Handler;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.handler.HandlerCollection;
+import org.eclipse.jetty.server.ssl.SslConnector;
+import org.eclipse.jetty.servlet.DefaultServlet;
+import org.eclipse.jetty.servlet.ServletContextHandler;
+import org.eclipse.jetty.servlet.ServletHolder;
+import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
+import org.junit.Ignore;
+
+public abstract class SslValidationTestBase extends SslContentExchangeTest
+{
+ protected static Class<? extends SslConnector> __klass;
+ protected static int __konnector;
+
+ @Override
+ protected void configureServer(Server server)
+ throws Exception
+ {
+ setProtocol("https");
+
+ // certificate is valid until Jan 1, 2050
+ String keypath = MavenTestingUtils.getTestResourceFile("jetty-valid.keystore").getAbsolutePath();
+ String trustpath = new File(System.getProperty("java.home"),"./lib/security/cacerts").getAbsolutePath();
+ String crlpath = MavenTestingUtils.getTestResourceFile("crlfile.pem").getAbsolutePath();
+
+ SslContextFactory srvFactory = new SslContextFactory();
+ srvFactory.setValidateCerts(true);
+ srvFactory.setKeystore(keypath);
+ srvFactory.setKeystorePassword("webtide");
+ srvFactory.setKeyManagerPassword("webtide");
+ srvFactory.setTruststore(trustpath);
+ srvFactory.setTruststorePassword("changeit");
+ srvFactory.setCrlPath(crlpath);
+
+ Constructor<? extends SslConnector> constructor = __klass.getConstructor(SslContextFactory.class);
+ SslConnector connector = constructor.newInstance(srvFactory);
+ server.addConnector(connector);
+
+ Handler handler = new TestHandler(getBasePath());
+
+ ServletContextHandler root = new ServletContextHandler();
+ root.setContextPath("/");
+ root.setResourceBase(getBasePath());
+ ServletHolder servletHolder = new ServletHolder( new DefaultServlet() );
+ servletHolder.setInitParameter( "gzip", "true" );
+ root.addServlet( servletHolder, "/*" );
+
+ HandlerCollection handlers = new HandlerCollection();
+ handlers.setHandlers(new Handler[]{handler, root});
+ server.setHandler( handlers );
+ }
+
+// @Override
+// protected void configureClient(HttpClient client)
+// throws Exception
+// {
+// String trustpath = new File(System.getProperty("java.home"),"./lib/security/cacerts").getAbsolutePath();
+// client.setTrustStoreLocation(trustpath);
+// client.setTrustStorePassword("changeit");
+// client.setConnectorType(__konnector);
+// }
+}