Merge 'jetty-9.4.x' of github.com:eclipse/jetty.project into jetty-9.4.x

This commit is contained in:
Joakim Erdfelt 2019-12-06 13:24:43 -06:00
commit 2ee079feb1
No known key found for this signature in database
GPG Key ID: 2D0E1FB8FE4B68B4
3 changed files with 110 additions and 11 deletions

View File

@ -30,6 +30,7 @@ import org.eclipse.jetty.client.api.Connection;
import org.eclipse.jetty.io.AbstractConnection;
import org.eclipse.jetty.io.ClientConnectionFactory;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.io.ssl.SslClientConnectionFactory;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.Promise;
@ -195,6 +196,8 @@ public class Socks4Proxy extends ProxyConfiguration.Proxy
try
{
HttpDestination destination = (HttpDestination)context.get(HttpClientTransport.HTTP_DESTINATION_CONTEXT_KEY);
context.put(SslClientConnectionFactory.SSL_PEER_HOST_CONTEXT_KEY, destination.getHost());
context.put(SslClientConnectionFactory.SSL_PEER_PORT_CONTEXT_KEY, destination.getPort());
ClientConnectionFactory connectionFactory = this.connectionFactory;
if (destination.isSecure())
connectionFactory = destination.newSslClientConnectionFactory(null, connectionFactory);

View File

@ -18,6 +18,8 @@
package org.eclipse.jetty.client;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ServerSocketChannel;
@ -25,7 +27,12 @@ import java.nio.channels.SocketChannel;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import org.eclipse.jetty.http.HttpScheme;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@ -44,7 +51,10 @@ public class Socks4ProxyTest
server = ServerSocketChannel.open();
server.bind(new InetSocketAddress("localhost", 0));
client = new HttpClient();
QueuedThreadPool clientThreads = new QueuedThreadPool();
clientThreads.setName("client");
client = new HttpClient(new SslContextFactory.Client());
client.setExecutor(clientThreads);
client.start();
}
@ -61,7 +71,7 @@ public class Socks4ProxyTest
int proxyPort = server.socket().getLocalPort();
client.getProxyConfiguration().getProxies().add(new Socks4Proxy("localhost", proxyPort));
final CountDownLatch latch = new CountDownLatch(1);
CountDownLatch latch = new CountDownLatch(1);
byte ip1 = 127;
byte ip2 = 0;
@ -111,7 +121,7 @@ public class Socks4ProxyTest
"Content-Length: 0\r\n" +
"Connection: close\r\n" +
"\r\n";
channel.write(ByteBuffer.wrap(response.getBytes("UTF-8")));
channel.write(ByteBuffer.wrap(response.getBytes(StandardCharsets.UTF_8)));
assertTrue(latch.await(5, TimeUnit.SECONDS));
}
@ -123,7 +133,7 @@ public class Socks4ProxyTest
int proxyPort = server.socket().getLocalPort();
client.getProxyConfiguration().getProxies().add(new Socks4Proxy("localhost", proxyPort));
final CountDownLatch latch = new CountDownLatch(1);
CountDownLatch latch = new CountDownLatch(1);
String serverHost = "127.0.0.13"; // Test expects an IP address.
int serverPort = proxyPort + 1; // Any port will do
@ -169,7 +179,92 @@ public class Socks4ProxyTest
"Content-Length: 0\r\n" +
"Connection: close\r\n" +
"\r\n";
channel.write(ByteBuffer.wrap(response.getBytes("UTF-8")));
channel.write(ByteBuffer.wrap(response.getBytes(StandardCharsets.UTF_8)));
assertTrue(latch.await(5, TimeUnit.SECONDS));
}
}
@Test
public void testSocks4ProxyWithTLSServer() throws Exception
{
String proxyHost = "localhost";
int proxyPort = server.socket().getLocalPort();
String serverHost = "127.0.0.13"; // Server host different from proxy host.
int serverPort = proxyPort + 1; // Any port will do.
SslContextFactory clientTLS = client.getSslContextFactory();
clientTLS.reload(ssl ->
{
// The client keystore contains the trustedCertEntry for the
// self-signed server certificate, so it acts as a truststore.
ssl.setTrustStorePath("src/test/resources/client_keystore.jks");
ssl.setTrustStorePassword("storepwd");
// Disable TLS hostname verification, but
// enable application hostname verification.
ssl.setEndpointIdentificationAlgorithm(null);
// The hostname must be that of the server, not of the proxy.
ssl.setHostnameVerifier((hostname, session) -> serverHost.equals(hostname));
});
client.getProxyConfiguration().getProxies().add(new Socks4Proxy(proxyHost, proxyPort));
CountDownLatch latch = new CountDownLatch(1);
client.newRequest(serverHost, serverPort)
.scheme(HttpScheme.HTTPS.asString())
.path("/path")
.send(result ->
{
if (result.isSucceeded())
latch.countDown();
else
result.getFailure().printStackTrace();
});
try (SocketChannel channel = server.accept())
{
int socks4MessageLength = 9;
ByteBuffer buffer = ByteBuffer.allocate(socks4MessageLength);
int read = channel.read(buffer);
assertEquals(socks4MessageLength, read);
// Socks4 response.
channel.write(ByteBuffer.wrap(new byte[]{0, 0x5A, 0, 0, 0, 0, 0, 0}));
// Wrap the socket with TLS.
SslContextFactory.Server serverTLS = new SslContextFactory.Server();
serverTLS.setKeyStorePath("src/test/resources/keystore.jks");
serverTLS.setKeyStorePassword("storepwd");
serverTLS.start();
SSLContext sslContext = serverTLS.getSslContext();
SSLSocket sslSocket = (SSLSocket)sslContext.getSocketFactory().createSocket(channel.socket(), serverHost, serverPort, false);
sslSocket.setUseClientMode(false);
// Read the request.
int crlfs = 0;
InputStream input = sslSocket.getInputStream();
while (true)
{
read = input.read();
if (read < 0)
break;
if (read == '\r' || read == '\n')
++crlfs;
else
crlfs = 0;
if (crlfs == 4)
break;
}
// Send the response.
String response =
"HTTP/1.1 200 OK\r\n" +
"Content-Length: 0\r\n" +
"Connection: close\r\n" +
"\r\n";
OutputStream output = sslSocket.getOutputStream();
output.write(response.getBytes(StandardCharsets.UTF_8));
output.flush();
assertTrue(latch.await(5, TimeUnit.SECONDS));
}

View File

@ -28,6 +28,7 @@ import javax.servlet.UnavailableException;
import org.eclipse.jetty.http.BadMessageException;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.io.QuietException;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.server.handler.ContextHandler.Context;
import org.eclipse.jetty.server.handler.ErrorHandler;
@ -406,8 +407,6 @@ public class HttpChannelState
*/
protected Action unhandle()
{
boolean readInterested = false;
synchronized (this)
{
if (LOG.isDebugEnabled())
@ -736,8 +735,10 @@ public class HttpChannelState
}
else
{
LOG.warn(failure.toString());
LOG.debug(failure);
if (!(failure instanceof QuietException))
LOG.warn(failure.toString());
if (LOG.isDebugEnabled())
LOG.debug(failure);
}
}
@ -1340,7 +1341,7 @@ public class HttpChannelState
* but that a handling thread may need to produce (fill/parse)
* it. Typically called by the async read success callback.
*
* @return <code>true</code> if more content may be available
* @return {@code true} if more content may be available
*/
public boolean onReadPossible()
{
@ -1372,7 +1373,7 @@ public class HttpChannelState
* Called to signal that a read has read -1.
* Will wake if the read was called while in ASYNC_WAIT state
*
* @return <code>true</code> if woken
* @return {@code true} if woken
*/
public boolean onReadEof()
{