Merged branch 'jetty-9.4.x' into 'jetty-10.0.x'.

This commit is contained in:
Simone Bordet 2019-10-09 10:22:18 +02:00
commit 783f3b49b0
12 changed files with 335 additions and 189 deletions

View File

@ -19,6 +19,7 @@
package org.eclipse.jetty.client; package org.eclipse.jetty.client;
import java.io.IOException; import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.URI; import java.net.URI;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -34,6 +35,7 @@ import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.HttpScheme; import org.eclipse.jetty.http.HttpScheme;
import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.io.ClientConnectionFactory; import org.eclipse.jetty.io.ClientConnectionFactory;
import org.eclipse.jetty.io.ClientConnector;
import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.util.Promise; import org.eclipse.jetty.util.Promise;
import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Log;
@ -206,7 +208,12 @@ public class HttpProxy extends ProxyConfiguration.Proxy
HttpDestination destination = (HttpDestination)context.get(HttpClientTransport.HTTP_DESTINATION_CONTEXT_KEY); HttpDestination destination = (HttpDestination)context.get(HttpClientTransport.HTTP_DESTINATION_CONTEXT_KEY);
ClientConnectionFactory connectionFactory = this.connectionFactory; ClientConnectionFactory connectionFactory = this.connectionFactory;
if (destination.isSecure()) if (destination.isSecure())
{
// Don't want to do DNS resolution here.
InetSocketAddress address = InetSocketAddress.createUnresolved(destination.getHost(), destination.getPort());
context.put(ClientConnector.REMOTE_SOCKET_ADDRESS_CONTEXT_KEY, address);
connectionFactory = destination.newSslClientConnectionFactory(connectionFactory); connectionFactory = destination.newSslClientConnectionFactory(connectionFactory);
}
var oldConnection = endPoint.getConnection(); var oldConnection = endPoint.getConnection();
var newConnection = connectionFactory.newConnection(endPoint, context); var newConnection = connectionFactory.newConnection(endPoint, context);
endPoint.upgrade(newConnection); endPoint.upgrade(newConnection);

View File

@ -53,10 +53,9 @@ public class ConnectHandlerSSLTest extends AbstractConnectHandlerTest
public void prepare() throws Exception public void prepare() throws Exception
{ {
sslContextFactory = new SslContextFactory.Server(); sslContextFactory = new SslContextFactory.Server();
String keyStorePath = MavenTestingUtils.getTestResourceFile("keystore").getAbsolutePath(); String keyStorePath = MavenTestingUtils.getTestResourceFile("server_keystore.p12").getAbsolutePath();
sslContextFactory.setKeyStorePath(keyStorePath); sslContextFactory.setKeyStorePath(keyStorePath);
sslContextFactory.setKeyStorePassword("storepwd"); sslContextFactory.setKeyStorePassword("storepwd");
sslContextFactory.setKeyManagerPassword("keypwd");
server = new Server(); server = new Server();
serverConnector = new ServerConnector(server, sslContextFactory); serverConnector = new ServerConnector(server, sslContextFactory);
server.addConnector(serverConnector); server.addConnector(serverConnector);

View File

@ -47,7 +47,6 @@ import org.eclipse.jetty.util.thread.QueuedThreadPool;
import org.hamcrest.Matchers; import org.hamcrest.Matchers;
import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.MethodSource;
import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.MatcherAssert.assertThat;
@ -56,36 +55,29 @@ import static org.junit.jupiter.api.Assertions.assertFalse;
public class ForwardProxyServerTest public class ForwardProxyServerTest
{ {
@SuppressWarnings("Duplicates") public static Stream<SslContextFactory.Server> serverTLS()
public static Stream<Arguments> scenarios()
{ {
String keyStorePath = MavenTestingUtils.getTestResourceFile("keystore").getAbsolutePath(); return Stream.of(null, newServerSslContextFactory());
// no server SSL
SslContextFactory.Server scenario1 = null;
// basic server SSL
SslContextFactory.Server scenario2 = new SslContextFactory.Server();
scenario2.setKeyStorePath(keyStorePath);
scenario2.setKeyStorePassword("storepwd");
scenario2.setKeyManagerPassword("keypwd");
// TODO: add more SslContextFactory configurations/scenarios?
return Stream.of(scenario1, scenario2).map(Arguments::of);
} }
private SslContextFactory.Server serverSslContextFactory;
private Server server; private Server server;
private ServerConnector serverConnector; private ServerConnector serverConnector;
private SslContextFactory.Server serverSslContextFactory;
private Server proxy; private Server proxy;
private ServerConnector proxyConnector; private ServerConnector proxyConnector;
public void init(SslContextFactory.Server scenario) private static SslContextFactory.Server newServerSslContextFactory()
{ {
serverSslContextFactory = scenario; SslContextFactory.Server proxyTLS = new SslContextFactory.Server();
String keyStorePath = MavenTestingUtils.getTestResourceFile("server_keystore.p12").getAbsolutePath();
proxyTLS.setKeyStorePath(keyStorePath);
proxyTLS.setKeyStorePassword("storepwd");
return proxyTLS;
} }
protected void startServer(ConnectionFactory connectionFactory) throws Exception protected void startServer(SslContextFactory.Server serverTLS, ConnectionFactory connectionFactory) throws Exception
{ {
serverSslContextFactory = serverTLS;
QueuedThreadPool serverThreads = new QueuedThreadPool(); QueuedThreadPool serverThreads = new QueuedThreadPool();
serverThreads.setName("server"); serverThreads.setName("server");
server = new Server(serverThreads); server = new Server(serverThreads);
@ -128,28 +120,20 @@ public class ForwardProxyServerTest
protected void stopServer() throws Exception protected void stopServer() throws Exception
{ {
if (server != null) if (server != null)
{
server.stop(); server.stop();
server.join();
}
} }
protected void stopProxy() throws Exception protected void stopProxy() throws Exception
{ {
if (proxy != null) if (proxy != null)
{
proxy.stop(); proxy.stop();
proxy.join();
}
} }
@ParameterizedTest @ParameterizedTest
@MethodSource("scenarios") @MethodSource("serverTLS")
public void testRequestTarget(SslContextFactory.Server scenario) throws Exception public void testRequestTarget(SslContextFactory.Server serverTLS) throws Exception
{ {
init(scenario); startServer(serverTLS, new AbstractConnectionFactory("http/1.1")
startServer(new AbstractConnectionFactory("http/1.1")
{ {
@Override @Override
public Connection newConnection(Connector connector, EndPoint endPoint) public Connection newConnection(Connector connector, EndPoint endPoint)
@ -206,15 +190,9 @@ public class ForwardProxyServerTest
}); });
startProxy(); startProxy();
SslContextFactory.Client clientTLS = new SslContextFactory.Client(true);
ClientConnector clientConnector = new ClientConnector(); ClientConnector clientConnector = new ClientConnector();
String keyStorePath = MavenTestingUtils.getTestResourceFile("keystore").getAbsolutePath(); clientConnector.setSslContextFactory(clientTLS);
SslContextFactory.Client clientSsl = new SslContextFactory.Client();
clientSsl.setKeyStorePath(keyStorePath);
clientSsl.setKeyStorePassword("storepwd");
clientSsl.setKeyManagerPassword("keypwd");
clientSsl.setEndpointIdentificationAlgorithm(null);
clientConnector.setSslContextFactory(clientSsl);
HttpClient httpClient = new HttpClient(new HttpClientTransportOverHTTP(clientConnector)); HttpClient httpClient = new HttpClient(new HttpClientTransportOverHTTP(clientConnector));
httpClient.getProxyConfiguration().getProxies().add(newHttpProxy()); httpClient.getProxyConfiguration().getProxies().add(newHttpProxy());
httpClient.start(); httpClient.start();

View File

@ -24,11 +24,16 @@ import java.net.Socket;
import java.net.URI; import java.net.URI;
import java.net.URLEncoder; import java.net.URLEncoder;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.security.KeyStore;
import java.security.Principal;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Stream; import java.util.stream.Stream;
import javax.net.ssl.KeyManager;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.X509ExtendedKeyManager;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream; import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
@ -64,8 +69,8 @@ import org.hamcrest.Matchers;
import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.MethodSource;
import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.MatcherAssert.assertThat;
@ -76,56 +81,46 @@ import static org.junit.jupiter.api.Assumptions.assumeTrue;
public class ForwardProxyTLSServerTest public class ForwardProxyTLSServerTest
{ {
@SuppressWarnings("Duplicates") public static Stream<SslContextFactory.Server> proxyTLS()
public static Stream<Arguments> scenarios()
{ {
String keyStorePath = MavenTestingUtils.getTestResourceFile("keystore").getAbsolutePath(); return Stream.of(null, newProxySslContextFactory());
// no server SSL
SslContextFactory.Server scenario1 = null;
// basic server SSL
SslContextFactory.Server scenario2 = new SslContextFactory.Server();
scenario2.setKeyStorePath(keyStorePath);
scenario2.setKeyStorePassword("storepwd");
scenario2.setKeyManagerPassword("keypwd");
// TODO: add more SslContextFactory configurations/scenarios?
return Stream.of(scenario1, scenario2).map(Arguments::of);
} }
private SslContextFactory.Server proxySslContextFactory;
private Server server; private Server server;
private ServerConnector serverConnector; private ServerConnector serverConnector;
private Server proxy; private Server proxy;
private ServerConnector proxyConnector; private ServerConnector proxyConnector;
private SslContextFactory.Server proxySslContextFactory;
public void init(SslContextFactory.Server scenario)
{
proxySslContextFactory = scenario;
}
protected void startTLSServer(Handler handler) throws Exception protected void startTLSServer(Handler handler) throws Exception
{
SslContextFactory.Server sslContextFactory = newServerSslContextFactory();
startTLSServer(sslContextFactory, handler);
}
protected void startTLSServer(SslContextFactory.Server sslContextFactory, Handler handler) throws Exception
{ {
QueuedThreadPool serverThreads = new QueuedThreadPool(); QueuedThreadPool serverThreads = new QueuedThreadPool();
serverThreads.setName("server"); serverThreads.setName("server");
server = new Server(serverThreads); server = new Server(serverThreads);
serverConnector = new ServerConnector(server, newServerSslContextFactory()); serverConnector = new ServerConnector(server, sslContextFactory);
server.addConnector(serverConnector); server.addConnector(serverConnector);
server.setHandler(handler); server.setHandler(handler);
server.start(); server.start();
} }
protected void startProxy() throws Exception protected void startProxy(SslContextFactory.Server proxyTLS) throws Exception
{ {
startProxy(new ConnectHandler()); startProxy(proxyTLS, new ConnectHandler());
} }
protected void startProxy(ConnectHandler connectHandler) throws Exception protected void startProxy(SslContextFactory.Server proxyTLS, ConnectHandler connectHandler) throws Exception
{ {
proxySslContextFactory = proxyTLS;
QueuedThreadPool proxyThreads = new QueuedThreadPool(); QueuedThreadPool proxyThreads = new QueuedThreadPool();
proxyThreads.setName("proxy"); proxyThreads.setName("proxy");
proxy = new Server(proxyThreads); proxy = new Server(proxyThreads);
proxyConnector = new ServerConnector(proxy, proxySslContextFactory); proxyConnector = new ServerConnector(proxy, proxyTLS);
proxy.addConnector(proxyConnector); proxy.addConnector(proxyConnector);
// Under Windows, it takes a while to detect that a connection // Under Windows, it takes a while to detect that a connection
// attempt fails, so use an explicit timeout // attempt fails, so use an explicit timeout
@ -150,24 +145,24 @@ public class ForwardProxyTLSServerTest
private static SslContextFactory.Server newServerSslContextFactory() private static SslContextFactory.Server newServerSslContextFactory()
{ {
SslContextFactory.Server sslContextFactory = new SslContextFactory.Server(); SslContextFactory.Server sslContextFactory = new SslContextFactory.Server();
configureSslContextFactory(sslContextFactory); String keyStorePath = MavenTestingUtils.getTestResourceFile("server_keystore.p12").getAbsolutePath();
sslContextFactory.setKeyStorePath(keyStorePath);
sslContextFactory.setKeyStorePassword("storepwd");
return sslContextFactory; return sslContextFactory;
} }
private static SslContextFactory.Server newProxySslContextFactory()
{
SslContextFactory.Server proxyTLS = new SslContextFactory.Server();
String keyStorePath = MavenTestingUtils.getTestResourceFile("proxy_keystore.p12").getAbsolutePath();
proxyTLS.setKeyStorePath(keyStorePath);
proxyTLS.setKeyStorePassword("storepwd");
return proxyTLS;
}
private static SslContextFactory.Client newClientSslContextFactory() private static SslContextFactory.Client newClientSslContextFactory()
{ {
SslContextFactory.Client sslContextFactory = new SslContextFactory.Client(); return new SslContextFactory.Client(true);
configureSslContextFactory(sslContextFactory);
sslContextFactory.setEndpointIdentificationAlgorithm(null);
return sslContextFactory;
}
private static void configureSslContextFactory(SslContextFactory sslContextFactory)
{
String keyStorePath = MavenTestingUtils.getTestResourceFile("keystore").getAbsolutePath();
sslContextFactory.setKeyStorePath(keyStorePath);
sslContextFactory.setKeyStorePassword("storepwd");
sslContextFactory.setKeyManagerPassword("keypwd");
} }
@AfterEach @AfterEach
@ -196,12 +191,11 @@ public class ForwardProxyTLSServerTest
} }
@ParameterizedTest @ParameterizedTest
@MethodSource("scenarios") @MethodSource("proxyTLS")
public void testOneExchange(SslContextFactory.Server scenario) throws Exception public void testOneExchange(SslContextFactory.Server proxyTLS) throws Exception
{ {
init(scenario);
startTLSServer(new ServerHandler()); startTLSServer(new ServerHandler());
startProxy(); startProxy(proxyTLS);
HttpClient httpClient = newHttpClient(); HttpClient httpClient = newHttpClient();
httpClient.getProxyConfiguration().getProxies().add(newHttpProxy()); httpClient.getProxyConfiguration().getProxies().add(newHttpProxy());
@ -232,12 +226,11 @@ public class ForwardProxyTLSServerTest
} }
@ParameterizedTest @ParameterizedTest
@MethodSource("scenarios") @MethodSource("proxyTLS")
public void testTwoExchanges(SslContextFactory.Server scenario) throws Exception public void testTwoExchanges(SslContextFactory.Server proxyTLS) throws Exception
{ {
init(scenario);
startTLSServer(new ServerHandler()); startTLSServer(new ServerHandler());
startProxy(); startProxy(proxyTLS);
HttpClient httpClient = newHttpClient(); HttpClient httpClient = newHttpClient();
httpClient.getProxyConfiguration().getProxies().add(newHttpProxy()); httpClient.getProxyConfiguration().getProxies().add(newHttpProxy());
@ -279,12 +272,11 @@ public class ForwardProxyTLSServerTest
} }
@ParameterizedTest @ParameterizedTest
@MethodSource("scenarios") @MethodSource("proxyTLS")
public void testTwoConcurrentExchanges(SslContextFactory.Server scenario) throws Exception public void testTwoConcurrentExchanges(SslContextFactory.Server proxyTLS) throws Exception
{ {
init(scenario);
startTLSServer(new ServerHandler()); startTLSServer(new ServerHandler());
startProxy(); startProxy(proxyTLS);
HttpClient httpClient = newHttpClient(); HttpClient httpClient = newHttpClient();
httpClient.getProxyConfiguration().getProxies().add(newHttpProxy()); httpClient.getProxyConfiguration().getProxies().add(newHttpProxy());
@ -346,15 +338,14 @@ public class ForwardProxyTLSServerTest
} }
@ParameterizedTest @ParameterizedTest
@MethodSource("scenarios") @MethodSource("proxyTLS")
public void testShortIdleTimeoutOverriddenByRequest(SslContextFactory.Server scenario) throws Exception public void testShortIdleTimeoutOverriddenByRequest(SslContextFactory.Server proxyTLS) throws Exception
{ {
init(scenario);
// Short idle timeout for HttpClient. // Short idle timeout for HttpClient.
long idleTimeout = 500; long idleTimeout = 500;
startTLSServer(new ServerHandler()); startTLSServer(new ServerHandler());
startProxy(new ConnectHandler() startProxy(proxyTLS, new ConnectHandler()
{ {
@Override @Override
protected void handleConnect(Request baseRequest, HttpServletRequest request, HttpServletResponse response, String serverAddress) protected void handleConnect(Request baseRequest, HttpServletRequest request, HttpServletResponse response, String serverAddress)
@ -402,12 +393,11 @@ public class ForwardProxyTLSServerTest
} }
@ParameterizedTest @ParameterizedTest
@MethodSource("scenarios") @MethodSource("proxyTLS")
public void testProxyDown(SslContextFactory.Server scenario) throws Exception public void testProxyDown(SslContextFactory.Server proxyTLS) throws Exception
{ {
init(scenario);
startTLSServer(new ServerHandler()); startTLSServer(new ServerHandler());
startProxy(); startProxy(proxyTLS);
int proxyPort = proxyConnector.getLocalPort(); int proxyPort = proxyConnector.getLocalPort();
stopProxy(); stopProxy();
@ -431,14 +421,13 @@ public class ForwardProxyTLSServerTest
} }
@ParameterizedTest @ParameterizedTest
@MethodSource("scenarios") @MethodSource("proxyTLS")
public void testServerDown(SslContextFactory.Server scenario) throws Exception public void testServerDown(SslContextFactory.Server proxyTLS) throws Exception
{ {
init(scenario);
startTLSServer(new ServerHandler()); startTLSServer(new ServerHandler());
int serverPort = serverConnector.getLocalPort(); int serverPort = serverConnector.getLocalPort();
stopServer(); stopServer();
startProxy(); startProxy(proxyTLS);
HttpClient httpClient = newHttpClient(); HttpClient httpClient = newHttpClient();
httpClient.getProxyConfiguration().getProxies().add(newHttpProxy()); httpClient.getProxyConfiguration().getProxies().add(newHttpProxy());
@ -459,12 +448,11 @@ public class ForwardProxyTLSServerTest
} }
@ParameterizedTest @ParameterizedTest
@MethodSource("scenarios") @MethodSource("proxyTLS")
public void testProxyClosesConnection(SslContextFactory.Server scenario) throws Exception public void testProxyClosesConnection(SslContextFactory.Server proxyTLS) throws Exception
{ {
init(scenario);
startTLSServer(new ServerHandler()); startTLSServer(new ServerHandler());
startProxy(new ConnectHandler() startProxy(proxyTLS, new ConnectHandler()
{ {
@Override @Override
protected void handleConnect(Request baseRequest, HttpServletRequest request, HttpServletResponse response, String serverAddress) protected void handleConnect(Request baseRequest, HttpServletRequest request, HttpServletResponse response, String serverAddress)
@ -487,12 +475,11 @@ public class ForwardProxyTLSServerTest
} }
@ParameterizedTest @ParameterizedTest
@MethodSource("scenarios") @MethodSource("proxyTLS")
public void testProxyAuthentication(SslContextFactory.Server scenario) throws Exception public void testProxyAuthentication(SslContextFactory.Server proxyTLS) throws Exception
{ {
init(scenario);
String realm = "test-realm"; String realm = "test-realm";
testProxyAuthentication(realm, new ConnectHandler() testProxyAuthentication(proxyTLS, new ConnectHandler()
{ {
@Override @Override
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
@ -507,16 +494,15 @@ public class ForwardProxyTLSServerTest
} }
super.handle(target, baseRequest, request, response); super.handle(target, baseRequest, request, response);
} }
}); }, realm);
} }
@ParameterizedTest @ParameterizedTest
@MethodSource("scenarios") @MethodSource("proxyTLS")
public void testProxyAuthenticationWithResponseContent(SslContextFactory.Server scenario) throws Exception public void testProxyAuthenticationWithResponseContent(SslContextFactory.Server proxyTLS) throws Exception
{ {
init(scenario);
String realm = "test-realm"; String realm = "test-realm";
testProxyAuthentication(realm, new ConnectHandler() testProxyAuthentication(proxyTLS, new ConnectHandler()
{ {
@Override @Override
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
@ -532,16 +518,15 @@ public class ForwardProxyTLSServerTest
} }
super.handle(target, baseRequest, request, response); super.handle(target, baseRequest, request, response);
} }
}); }, realm);
} }
@ParameterizedTest @ParameterizedTest
@MethodSource("scenarios") @MethodSource("proxyTLS")
public void testProxyAuthenticationWithIncludedAddressWithResponseContent(SslContextFactory.Server scenario) throws Exception public void testProxyAuthenticationWithIncludedAddressWithResponseContent(SslContextFactory.Server proxyTLS) throws Exception
{ {
init(scenario);
String realm = "test-realm"; String realm = "test-realm";
testProxyAuthentication(realm, new ConnectHandler() testProxyAuthentication(proxyTLS, new ConnectHandler()
{ {
@Override @Override
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
@ -557,16 +542,15 @@ public class ForwardProxyTLSServerTest
} }
super.handle(target, baseRequest, request, response); super.handle(target, baseRequest, request, response);
} }
}, true); }, realm, true);
} }
@ParameterizedTest @ParameterizedTest
@MethodSource("scenarios") @MethodSource("proxyTLS")
public void testProxyAuthenticationClosesConnection(SslContextFactory.Server scenario) throws Exception public void testProxyAuthenticationClosesConnection(SslContextFactory.Server proxyTLS) throws Exception
{ {
init(scenario);
String realm = "test-realm"; String realm = "test-realm";
testProxyAuthentication(realm, new ConnectHandler() testProxyAuthentication(proxyTLS, new ConnectHandler()
{ {
@Override @Override
protected boolean handleAuthentication(HttpServletRequest request, HttpServletResponse response, String address) protected boolean handleAuthentication(HttpServletRequest request, HttpServletResponse response, String address)
@ -583,18 +567,18 @@ public class ForwardProxyTLSServerTest
return true; return true;
} }
} }
}); }, realm);
} }
private void testProxyAuthentication(String realm, ConnectHandler connectHandler) throws Exception private void testProxyAuthentication(SslContextFactory.Server proxyTLS, ConnectHandler connectHandler, String realm) throws Exception
{ {
testProxyAuthentication(realm, connectHandler, false); testProxyAuthentication(proxyTLS, connectHandler, realm, false);
} }
private void testProxyAuthentication(String realm, ConnectHandler connectHandler, boolean includeAddress) throws Exception private void testProxyAuthentication(SslContextFactory.Server proxyTLS, ConnectHandler connectHandler, String realm, boolean includeAddress) throws Exception
{ {
startTLSServer(new ServerHandler()); startTLSServer(new ServerHandler());
startProxy(connectHandler); startProxy(proxyTLS, connectHandler);
HttpClient httpClient = newHttpClient(); HttpClient httpClient = newHttpClient();
HttpProxy httpProxy = newHttpProxy(); HttpProxy httpProxy = newHttpProxy();
@ -626,13 +610,104 @@ public class ForwardProxyTLSServerTest
} }
} }
@ParameterizedTest @Test
@MethodSource("scenarios") public void testBothProxyAndServerNeedClientAuth() throws Exception
{
// Keystore server_keystore.p12 contains:
// - alias "mykey": self-signed certificate with private key.
// - alias "client_root": certificate from client_keystore.p12 under the "server" alias.
// Keystore proxy_keystore.p12 contains:
// - alias "mykey": self-signed certificate with private key.
// - alias "client_root": certificate from client_keystore.p12 under the "proxy" alias.
// Keystore client_keystore.p12 contains:
// - alias "proxy": self-signed certificate with private key to send to the proxy.
// - alias "server": self-signed certificate with private key to send to the server.
// - alias "proxy_root": certificate from proxy_keystore under the "mykey" alias.
// - alias "server_root": certificate from server_keystore under the "mykey" alias.
// We want setEndpointIdentificationAlgorithm(null) for all 3 SslContextFactory
// because the certificate common names do not match the host names.
SslContextFactory.Server serverTLS = newServerSslContextFactory();
serverTLS.setEndpointIdentificationAlgorithm(null);
serverTLS.setNeedClientAuth(true);
startTLSServer(serverTLS, new ServerHandler());
int serverPort = serverConnector.getLocalPort();
String serverAlias = "server";
SslContextFactory.Server proxyTLS = newProxySslContextFactory();
proxyTLS.setEndpointIdentificationAlgorithm(null);
proxyTLS.setNeedClientAuth(true);
startProxy(proxyTLS);
int proxyPort = proxyConnector.getLocalPort();
String proxyAlias = "proxy";
SslContextFactory.Client clientSslContextFactory = new SslContextFactory.Client()
{
@Override
protected KeyManager[] getKeyManagers(KeyStore keyStore) throws Exception
{
KeyManager[] keyManagers = super.getKeyManagers(keyStore);
for (int i = 0; i < keyManagers.length; i++)
{
KeyManager keyManager = keyManagers[i];
if (keyManager instanceof X509ExtendedKeyManager)
{
X509ExtendedKeyManager extKeyManager = (X509ExtendedKeyManager)keyManager;
keyManagers[i] = new X509ExtendedKeyManagerWrapper(extKeyManager)
{
@Override
public String chooseEngineClientAlias(String[] keyType, Principal[] issuers, SSLEngine engine)
{
int port = engine.getPeerPort();
if (port == serverPort)
return serverAlias;
else if (port == proxyPort)
return proxyAlias;
else
return super.chooseEngineClientAlias(keyType, issuers, engine);
}
};
}
}
return keyManagers;
}
};
clientSslContextFactory.setKeyStorePath(MavenTestingUtils.getTestResourceFile("client_keystore.p12").getAbsolutePath());
clientSslContextFactory.setKeyStorePassword("storepwd");
clientSslContextFactory.setEndpointIdentificationAlgorithm(null);
ClientConnector clientConnector = new ClientConnector();
clientConnector.setSelectors(1);
clientConnector.setSslContextFactory(clientSslContextFactory);
HttpClient httpClient = new HttpClient(new HttpClientTransportOverHTTP(clientConnector));
httpClient.getProxyConfiguration().getProxies().add(newHttpProxy());
httpClient.start();
try
{
String body = "BODY";
ContentResponse response = httpClient.newRequest("localhost", serverConnector.getLocalPort())
.scheme(HttpScheme.HTTPS.asString())
.method(HttpMethod.GET)
.path("/echo?body=" + URLEncoder.encode(body, StandardCharsets.UTF_8))
.timeout(5, TimeUnit.SECONDS)
.send();
assertEquals(HttpStatus.OK_200, response.getStatus());
String content = response.getContentAsString();
assertEquals(body, content);
}
finally
{
httpClient.stop();
}
}
@Test
@Tag("external") @Tag("external")
@Disabled @Disabled
public void testExternalProxy(SslContextFactory.Server scenario) throws Exception public void testExternalProxy() throws Exception
{ {
init(scenario);
// Free proxy server obtained from http://hidemyass.com/proxy-list/ // Free proxy server obtained from http://hidemyass.com/proxy-list/
String proxyHost = "81.208.25.53"; String proxyHost = "81.208.25.53";
int proxyPort = 3128; int proxyPort = 3128;

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -626,6 +626,9 @@ public class GzipHandler extends HandlerWrapper implements GzipFactory
if (inflate) if (inflate)
{ {
if (LOG.isDebugEnabled())
LOG.debug("{} inflate {}", this, request);
baseRequest.getHttpInput().addInterceptor(new GzipHttpInputInterceptor(baseRequest.getHttpChannel().getByteBufferPool(), _inflateBufferSize)); baseRequest.getHttpInput().addInterceptor(new GzipHttpInputInterceptor(baseRequest.getHttpChannel().getByteBufferPool(), _inflateBufferSize));
for (ListIterator<HttpField> i = baseRequest.getHttpFields().listIterator(); i.hasNext(); ) for (ListIterator<HttpField> i = baseRequest.getHttpFields().listIterator(); i.hasNext(); )
@ -952,4 +955,10 @@ public class GzipHandler extends HandlerWrapper implements GzipFactory
{ {
return new DeflaterPool(capacity, Deflater.DEFAULT_COMPRESSION, true); return new DeflaterPool(capacity, Deflater.DEFAULT_COMPRESSION, true);
} }
@Override
public String toString()
{
return String.format("%s@%x{%s,min=%s,inflate=%s}", getClass().getSimpleName(), hashCode(), getState(), _minGzipSize, _inflateBufferSize);
}
} }

View File

@ -884,7 +884,7 @@ public class SessionHandler extends ScopedHandler
* @param id The session ID stripped of any worker name. * @param id The session ID stripped of any worker name.
* @return A Session or null if none exists. * @return A Session or null if none exists.
*/ */
protected Session getSession(String id) public Session getSession(String id)
{ {
try try
{ {

View File

@ -35,7 +35,6 @@ import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.EventListener; import java.util.EventListener;
import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
@ -43,6 +42,7 @@ import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Scanner; import java.util.Scanner;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.function.Predicate; import java.util.function.Predicate;
@ -740,7 +740,7 @@ public class PathWatcher extends AbstractLifeCycle implements Runnable
private boolean nativeWatchService; private boolean nativeWatchService;
private final List<Config> configs = new ArrayList<>(); private final List<Config> configs = new ArrayList<>();
private final Map<WatchKey, Config> keys = new HashMap<>(); private final Map<WatchKey, Config> keys = new ConcurrentHashMap<>();
private final List<EventListener> listeners = new CopyOnWriteArrayList<>(); //a listener may modify the listener list directly or by stopping the PathWatcher private final List<EventListener> listeners = new CopyOnWriteArrayList<>(); //a listener may modify the listener list directly or by stopping the PathWatcher
private final Map<Path, PathWatchEvent> pending = new LinkedHashMap<>(32, (float)0.75, false); private final Map<Path, PathWatchEvent> pending = new LinkedHashMap<>(32, (float)0.75, false);

View File

@ -26,6 +26,8 @@ import java.net.Socket;
import java.security.InvalidAlgorithmParameterException; import java.security.InvalidAlgorithmParameterException;
import java.security.KeyStore; import java.security.KeyStore;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.security.Principal;
import java.security.PrivateKey;
import java.security.SecureRandom; import java.security.SecureRandom;
import java.security.Security; import java.security.Security;
import java.security.cert.CRL; import java.security.cert.CRL;
@ -99,69 +101,24 @@ import org.eclipse.jetty.util.security.Password;
@ManagedObject @ManagedObject
public abstract class SslContextFactory extends AbstractLifeCycle implements Dumpable public abstract class SslContextFactory extends AbstractLifeCycle implements Dumpable
{ {
public static final TrustManager[] TRUST_ALL_CERTS = new X509TrustManager[]{ public static final TrustManager[] TRUST_ALL_CERTS = new X509TrustManager[]{new X509ExtendedTrustManagerWrapper(null)};
new X509ExtendedTrustManager()
{
@Override
public X509Certificate[] getAcceptedIssuers()
{
return new X509Certificate[0];
}
@Override
public void checkClientTrusted(X509Certificate[] certs, String authType)
{
}
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType, Socket socket)
{
}
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType, SSLEngine engine)
{
}
@Override
public void checkServerTrusted(X509Certificate[] certs, String authType)
{
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType, Socket socket)
{
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType, SSLEngine engine)
{
}
}
};
private static final Logger LOG = Log.getLogger(SslContextFactory.class);
private static final Logger LOG_CONFIG = LOG.getLogger("SslContextFactoryConfig");
public static final String DEFAULT_KEYMANAGERFACTORY_ALGORITHM = KeyManagerFactory.getDefaultAlgorithm(); public static final String DEFAULT_KEYMANAGERFACTORY_ALGORITHM = KeyManagerFactory.getDefaultAlgorithm();
public static final String DEFAULT_TRUSTMANAGERFACTORY_ALGORITHM = TrustManagerFactory.getDefaultAlgorithm(); public static final String DEFAULT_TRUSTMANAGERFACTORY_ALGORITHM = TrustManagerFactory.getDefaultAlgorithm();
/** /**
* String name of key password property. * String name of key password property.
*/ */
public static final String KEYPASSWORD_PROPERTY = "org.eclipse.jetty.ssl.keypassword"; public static final String KEYPASSWORD_PROPERTY = "org.eclipse.jetty.ssl.keypassword";
/** /**
* String name of keystore password property. * String name of keystore password property.
*/ */
public static final String PASSWORD_PROPERTY = "org.eclipse.jetty.ssl.password"; public static final String PASSWORD_PROPERTY = "org.eclipse.jetty.ssl.password";
private static final Logger LOG = Log.getLogger(SslContextFactory.class);
private static final Logger LOG_CONFIG = LOG.getLogger("config");
/** /**
* Default Excluded Protocols List * Default Excluded Protocols List
*/ */
private static final String[] DEFAULT_EXCLUDED_PROTOCOLS = {"SSL", "SSLv2", "SSLv2Hello", "SSLv3"}; private static final String[] DEFAULT_EXCLUDED_PROTOCOLS = {"SSL", "SSLv2", "SSLv2Hello", "SSLv3"};
/** /**
* Default Excluded Cipher Suite List * Default Excluded Cipher Suite List
*/ */
@ -2037,15 +1994,14 @@ public abstract class SslContextFactory extends AbstractLifeCycle implements Dum
_trustStoreResource); _trustStoreResource);
} }
class Factory private static class Factory
{ {
private final KeyStore _keyStore; private final KeyStore _keyStore;
private final KeyStore _trustStore; private final KeyStore _trustStore;
private final SSLContext _context; private final SSLContext _context;
Factory(KeyStore keyStore, KeyStore trustStore, SSLContext context) private Factory(KeyStore keyStore, KeyStore trustStore, SSLContext context)
{ {
super();
_keyStore = keyStore; _keyStore = keyStore;
_trustStore = trustStore; _trustStore = trustStore;
_context = context; _context = context;
@ -2188,4 +2144,126 @@ public abstract class SslContextFactory extends AbstractLifeCycle implements Dum
_wantClientAuth = wantClientAuth; _wantClientAuth = wantClientAuth;
} }
} }
/**
* <p>A wrapper that delegates to another (if not {@code null}) X509ExtendedKeyManager.</p>
*/
public static class X509ExtendedKeyManagerWrapper extends X509ExtendedKeyManager
{
private final X509ExtendedKeyManager keyManager;
public X509ExtendedKeyManagerWrapper(X509ExtendedKeyManager keyManager)
{
this.keyManager = keyManager;
}
@Override
public String[] getClientAliases(String keyType, Principal[] issuers)
{
return keyManager == null ? null : keyManager.getClientAliases(keyType, issuers);
}
@Override
public String chooseClientAlias(String[] keyType, Principal[] issuers, Socket socket)
{
return keyManager == null ? null : keyManager.chooseClientAlias(keyType, issuers, socket);
}
@Override
public String chooseEngineClientAlias(String[] keyType, Principal[] issuers, SSLEngine engine)
{
return keyManager == null ? null : keyManager.chooseEngineClientAlias(keyType, issuers, engine);
}
@Override
public String[] getServerAliases(String keyType, Principal[] issuers)
{
return keyManager == null ? null : keyManager.getServerAliases(keyType, issuers);
}
@Override
public String chooseServerAlias(String keyType, Principal[] issuers, Socket socket)
{
return keyManager == null ? null : keyManager.chooseServerAlias(keyType, issuers, socket);
}
@Override
public String chooseEngineServerAlias(String keyType, Principal[] issuers, SSLEngine engine)
{
return keyManager == null ? null : keyManager.chooseEngineServerAlias(keyType, issuers, engine);
}
@Override
public X509Certificate[] getCertificateChain(String alias)
{
return keyManager == null ? null : keyManager.getCertificateChain(alias);
}
@Override
public PrivateKey getPrivateKey(String alias)
{
return keyManager == null ? null : keyManager.getPrivateKey(alias);
}
}
/**
* <p>A wrapper that delegates to another (if not {@code null}) X509ExtendedTrustManager.</p>
*/
public static class X509ExtendedTrustManagerWrapper extends X509ExtendedTrustManager
{
private final X509ExtendedTrustManager trustManager;
public X509ExtendedTrustManagerWrapper(X509ExtendedTrustManager trustManager)
{
this.trustManager = trustManager;
}
@Override
public X509Certificate[] getAcceptedIssuers()
{
return trustManager == null ? new X509Certificate[0] : trustManager.getAcceptedIssuers();
}
@Override
public void checkClientTrusted(X509Certificate[] certs, String authType) throws CertificateException
{
if (trustManager != null)
trustManager.checkClientTrusted(certs, authType);
}
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType, Socket socket) throws CertificateException
{
if (trustManager != null)
trustManager.checkClientTrusted(chain, authType, socket);
}
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType, SSLEngine engine) throws CertificateException
{
if (trustManager != null)
trustManager.checkClientTrusted(chain, authType, engine);
}
@Override
public void checkServerTrusted(X509Certificate[] certs, String authType) throws CertificateException
{
if (trustManager != null)
trustManager.checkServerTrusted(certs, authType);
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType, Socket socket) throws CertificateException
{
if (trustManager != null)
trustManager.checkServerTrusted(chain, authType, socket);
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType, SSLEngine engine) throws CertificateException
{
if (trustManager != null)
trustManager.checkServerTrusted(chain, authType, engine);
}
}
} }