aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Becker2013-01-17 04:18:29 (EST)
committerThomas Becker2013-01-17 04:28:15 (EST)
commit9ebea3938d473cc897fc71db5e1f266ed17adbff (patch)
treeeeb55fe5d182649e65d2f30944180681025f03a2
parent46e13b305baee73b46359311cac4ff4959c7b500 (diff)
downloadorg.eclipse.jetty.project-9ebea3938d473cc897fc71db5e1f266ed17adbff.zip
org.eclipse.jetty.project-9ebea3938d473cc897fc71db5e1f266ed17adbff.tar.gz
org.eclipse.jetty.project-9ebea3938d473cc897fc71db5e1f266ed17adbff.tar.bz2
393385: Make hostname verification configurable in SslContextFactory and enable it by default (See http://www.ietf.org/rfc/rfc2818.txt section 3.1)
-rw-r--r--jetty-client/src/test/java/org/eclipse/jetty/client/AbstractHttpClientServerTest.java1
-rw-r--r--jetty-client/src/test/java/org/eclipse/jetty/client/HostnameVerificationTest.java128
-rw-r--r--jetty-io/src/test/java/org/eclipse/jetty/io/SelectChannelEndPointSslTest.java14
-rw-r--r--jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/test/AbstractTestOSGi.java4
-rw-r--r--jetty-spdy/spdy-http-server/src/test/java/org/eclipse/jetty/spdy/server/http/SSLExternalServerTest.java1
-rw-r--r--jetty-spdy/spdy-server/src/test/java/org/eclipse/jetty/spdy/server/SSLSynReplyTest.java2
-rw-r--r--jetty-util/src/main/java/org/eclipse/jetty/util/ssl/SslContextFactory.java22
7 files changed, 162 insertions, 10 deletions
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/AbstractHttpClientServerTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/AbstractHttpClientServerTest.java
index e6f19c1..5fc20d1 100644
--- a/jetty-client/src/test/java/org/eclipse/jetty/client/AbstractHttpClientServerTest.java
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/AbstractHttpClientServerTest.java
@@ -61,6 +61,7 @@ public abstract class AbstractHttpClientServerTest
{
if (sslContextFactory != null)
{
+ sslContextFactory.setEndpointIdentificationAlgorithm("");
sslContextFactory.setKeyStorePath("src/test/resources/keystore.jks");
sslContextFactory.setKeyStorePassword("storepwd");
sslContextFactory.setTrustStorePath("src/test/resources/truststore.jks");
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/HostnameVerificationTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/HostnameVerificationTest.java
new file mode 100644
index 0000000..a2eece4
--- /dev/null
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/HostnameVerificationTest.java
@@ -0,0 +1,128 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2013 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.client;
+
+import java.io.IOException;
+import java.util.concurrent.ExecutionException;
+import javax.net.ssl.SSLHandshakeException;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.eclipse.jetty.server.NetworkConnector;
+import org.eclipse.jetty.server.Request;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.ServerConnector;
+import org.eclipse.jetty.server.handler.DefaultHandler;
+import org.eclipse.jetty.util.ssl.SslContextFactory;
+import org.eclipse.jetty.util.thread.QueuedThreadPool;
+import org.junit.Before;
+import org.junit.Test;
+
+import static junit.framework.Assert.fail;
+import static org.hamcrest.CoreMatchers.instanceOf;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+/**
+ * This test class runs tests to make sure that hostname verification (http://www.ietf.org/rfc/rfc2818.txt section 3
+ * .1) is configurable in SslContextFactory and works as expected.
+ */
+public class HostnameVerificationTest
+{
+ private SslContextFactory sslContextFactory = new SslContextFactory();
+ private Server server;
+ private HttpClient client;
+ private NetworkConnector connector;
+
+ @Before
+ public void setUp() throws Exception
+ {
+ if (sslContextFactory != null)
+ {
+ // keystore contains a hostname which doesn't match localhost
+ sslContextFactory.setKeyStorePath("src/test/resources/keystore");
+ sslContextFactory.setKeyStorePassword("abcdef");
+ }
+
+ if (server == null)
+ server = new Server();
+ connector = new ServerConnector(server, sslContextFactory);
+ server.addConnector(connector);
+ server.setHandler(new DefaultHandler()
+ {
+ @Override
+ public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
+ {
+ baseRequest.setHandled(true);
+ response.getWriter().write("foobar");
+ }
+ });
+ server.start();
+
+ QueuedThreadPool executor = new QueuedThreadPool();
+ executor.setName(executor.getName() + "-client");
+ client = new HttpClient(sslContextFactory);
+ client.setExecutor(executor);
+ client.start();
+ }
+
+ /**
+ * This test is supposed to verify that hostname verification works as described in:
+ * http://www.ietf.org/rfc/rfc2818.txt section 3.1. It uses a certificate with a common name different to localhost
+ * and sends a request to localhost. This should fail with a SSLHandshakeException.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void simpleGetWithHostnameVerificationEnabledTest() throws Exception
+ {
+ String uri = "https://localhost:" + connector.getLocalPort() + "/";
+ try
+ {
+ client.GET(uri);
+ fail("sending request to client should have failed with an Exception!");
+ }
+ catch (ExecutionException e)
+ {
+ assertThat("We got a SSLHandshakeException as localhost doesn't match the hostname of the certificate",
+ e.getCause().getCause(), instanceOf(SSLHandshakeException.class));
+ }
+ }
+
+ /**
+ * This test has hostname verification disabled and connecting, ssl handshake and sending the request should just
+ * work fine.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void simpleGetWithHostnameVerificationDisabledTest() throws Exception
+ {
+ sslContextFactory.setEndpointIdentificationAlgorithm("");
+ String uri = "https://localhost:" + connector.getLocalPort() + "/";
+ try
+ {
+ client.GET(uri);
+ }
+ catch (ExecutionException e)
+ {
+ fail("SSLHandshake should work just fine as hostname verification is disabled! " + e.getMessage());
+ }
+ }
+}
diff --git a/jetty-io/src/test/java/org/eclipse/jetty/io/SelectChannelEndPointSslTest.java b/jetty-io/src/test/java/org/eclipse/jetty/io/SelectChannelEndPointSslTest.java
index aae34b7..54e160c 100644
--- a/jetty-io/src/test/java/org/eclipse/jetty/io/SelectChannelEndPointSslTest.java
+++ b/jetty-io/src/test/java/org/eclipse/jetty/io/SelectChannelEndPointSslTest.java
@@ -18,12 +18,6 @@
package org.eclipse.jetty.io;
-import static org.hamcrest.Matchers.greaterThan;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.assertTrue;
-
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
@@ -31,7 +25,6 @@ import java.net.Socket;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.util.concurrent.TimeUnit;
-
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLEngineResult;
import javax.net.ssl.SSLEngineResult.HandshakeStatus;
@@ -47,6 +40,12 @@ import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
+import static org.hamcrest.Matchers.greaterThan;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+
public class SelectChannelEndPointSslTest extends SelectChannelEndPointTest
{
@@ -60,6 +59,7 @@ public class SelectChannelEndPointSslTest extends SelectChannelEndPointTest
__sslCtxFactory.setKeyStorePath(keystore.getAbsolutePath());
__sslCtxFactory.setKeyStorePassword("storepwd");
__sslCtxFactory.setKeyManagerPassword("keypwd");
+ __sslCtxFactory.setEndpointIdentificationAlgorithm("");
__sslCtxFactory.start();
}
diff --git a/jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/test/AbstractTestOSGi.java b/jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/test/AbstractTestOSGi.java
index 235e53a..0c4dcb8 100644
--- a/jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/test/AbstractTestOSGi.java
+++ b/jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/test/AbstractTestOSGi.java
@@ -148,7 +148,9 @@ public class AbstractTestOSGi
protected SslContextFactory getSslContextFactory()
{
- return new SslContextFactory(true);
+ SslContextFactory sslContextFactory = new SslContextFactory(true);
+ sslContextFactory.setEndpointIdentificationAlgorithm("");
+ return sslContextFactory;
}
protected void testHttpServiceGreetings(BundleContext bundleContext, String protocol, int port) throws Exception
diff --git a/jetty-spdy/spdy-http-server/src/test/java/org/eclipse/jetty/spdy/server/http/SSLExternalServerTest.java b/jetty-spdy/spdy-http-server/src/test/java/org/eclipse/jetty/spdy/server/http/SSLExternalServerTest.java
index 7c7465a..0613f92 100644
--- a/jetty-spdy/spdy-http-server/src/test/java/org/eclipse/jetty/spdy/server/http/SSLExternalServerTest.java
+++ b/jetty-spdy/spdy-http-server/src/test/java/org/eclipse/jetty/spdy/server/http/SSLExternalServerTest.java
@@ -52,6 +52,7 @@ public class SSLExternalServerTest extends AbstractHTTPSPDYTest
SslContextFactory sslContextFactory = new SslContextFactory();
// Force TLSv1
sslContextFactory.setIncludeProtocols("TLSv1");
+ sslContextFactory.setEndpointIdentificationAlgorithm("");
return new SPDYClient.Factory(threadPool, null, sslContextFactory, 30000);
}
diff --git a/jetty-spdy/spdy-server/src/test/java/org/eclipse/jetty/spdy/server/SSLSynReplyTest.java b/jetty-spdy/spdy-server/src/test/java/org/eclipse/jetty/spdy/server/SSLSynReplyTest.java
index 0666545..f196722 100644
--- a/jetty-spdy/spdy-server/src/test/java/org/eclipse/jetty/spdy/server/SSLSynReplyTest.java
+++ b/jetty-spdy/spdy-server/src/test/java/org/eclipse/jetty/spdy/server/SSLSynReplyTest.java
@@ -34,6 +34,7 @@ public class SSLSynReplyTest extends SynReplyTest
protected SPDYServerConnector newSPDYServerConnector(Server server, ServerSessionFrameListener listener)
{
SslContextFactory sslContextFactory = newSslContextFactory();
+ sslContextFactory.setEndpointIdentificationAlgorithm("");
return new SPDYServerConnector(server, sslContextFactory, listener);
}
@@ -41,6 +42,7 @@ public class SSLSynReplyTest extends SynReplyTest
protected SPDYClient.Factory newSPDYClientFactory(Executor threadPool)
{
SslContextFactory sslContextFactory = newSslContextFactory();
+ sslContextFactory.setEndpointIdentificationAlgorithm("");
return new SPDYClient.Factory(threadPool, null, sslContextFactory);
}
diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/ssl/SslContextFactory.java b/jetty-util/src/main/java/org/eclipse/jetty/util/ssl/SslContextFactory.java
index a3780c0..a0f4350 100644
--- a/jetty-util/src/main/java/org/eclipse/jetty/util/ssl/SslContextFactory.java
+++ b/jetty-util/src/main/java/org/eclipse/jetty/util/ssl/SslContextFactory.java
@@ -41,12 +41,12 @@ import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
-
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.SSLParameters;
import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLServerSocketFactory;
import javax.net.ssl.SSLSocket;
@@ -111,6 +111,7 @@ public class SslContextFactory extends AbstractLifeCycle
/** Excluded protocols. */
private final Set<String> _excludeProtocols = new LinkedHashSet<>();
+
/** Included protocols. */
private Set<String> _includeProtocols = null;
@@ -196,6 +197,9 @@ public class SslContextFactory extends AbstractLifeCycle
/** SSL context */
private SSLContext _context;
+ /** EndpointIdentificationAlgorithm - when set to "HTTPS" hostname verification will be enabled */
+ private String _endpointIdentificationAlgorithm = "HTTPS";
+
private boolean _trustAll;
/**
@@ -204,7 +208,7 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public SslContextFactory()
{
- _trustAll=true;
+ this(true);
}
/**
@@ -816,6 +820,16 @@ public class SslContextFactory extends AbstractLifeCycle
}
/**
+ * When set to "HTTPS" hostname verification will be enabled
+ *
+ * @param endpointIdentificationAlgorithm Set the endpointIdentificationAlgorithm
+ */
+ public void setEndpointIdentificationAlgorithm(String endpointIdentificationAlgorithm)
+ {
+ this._endpointIdentificationAlgorithm = endpointIdentificationAlgorithm;
+ }
+
+ /**
* Override this method to provide alternate way to load a keystore.
*
* @return the key store instance
@@ -1292,6 +1306,10 @@ public class SslContextFactory extends AbstractLifeCycle
public void customize(SSLEngine sslEngine)
{
+ SSLParameters sslParams = sslEngine.getSSLParameters();
+ sslParams.setEndpointIdentificationAlgorithm(_endpointIdentificationAlgorithm);
+ sslEngine.setSSLParameters(sslParams);
+
if (getWantClientAuth())
sslEngine.setWantClientAuth(getWantClientAuth());
if (getNeedClientAuth())