package org.eclipse.jetty.client; import java.io.BufferedReader; import java.io.File; import java.io.InputStreamReader; import java.io.OutputStream; import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLServerSocket; import javax.net.ssl.SSLSocket; import org.eclipse.jetty.http.HttpMethods; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.toolchain.test.MavenTestingUtils; import org.eclipse.jetty.util.ssl.SslContextFactory; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; public class SslBytesClientTest extends SslBytesTest { private ExecutorService threadPool; private HttpClient client; private SimpleProxy proxy; private SSLServerSocket acceptor; @Before public void init() throws Exception { threadPool = Executors.newCachedThreadPool(); client = new HttpClient(); client.setMaxConnectionsPerAddress(1); client.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL); File keyStore = MavenTestingUtils.getTestResourceFile("keystore"); SslContextFactory cf = client.getSslContextFactory(); cf.setKeyStorePath(keyStore.getAbsolutePath()); cf.setKeyStorePassword("storepwd"); cf.setKeyManagerPassword("keypwd"); client.start(); SSLContext sslContext = cf.getSslContext(); acceptor = (SSLServerSocket)sslContext.getServerSocketFactory().createServerSocket(0); int serverPort = acceptor.getLocalPort(); proxy = new SimpleProxy(threadPool, "localhost", serverPort); proxy.start(); logger.debug(":{} <==> :{}", proxy.getPort(), serverPort); } @After public void destroy() throws Exception { if (acceptor != null) acceptor.close(); if (proxy != null) proxy.stop(); if (client != null) client.stop(); if (threadPool != null) threadPool.shutdownNow(); } @Test public void testHandshake() throws Exception { ContentExchange exchange = new ContentExchange(true); exchange.setURL("https://localhost:" + proxy.getPort()); String method = HttpMethods.GET; exchange.setMethod(method); client.send(exchange); Assert.assertTrue(proxy.awaitClient(5, TimeUnit.SECONDS)); final SSLSocket server = (SSLSocket)acceptor.accept(); server.setUseClientMode(false); Future<Object> handshake = threadPool.submit(new Callable<Object>() { public Object call() throws Exception { server.startHandshake(); return null; } }); // Client Hello TLSRecord record = proxy.readFromClient(); Assert.assertEquals(TLSRecord.Type.HANDSHAKE, record.getType()); proxy.flushToServer(record); // Server Hello + Certificate + Server Done record = proxy.readFromServer(); Assert.assertEquals(TLSRecord.Type.HANDSHAKE, record.getType()); proxy.flushToClient(record); // Client Key Exchange record = proxy.readFromClient(); Assert.assertEquals(TLSRecord.Type.HANDSHAKE, record.getType()); proxy.flushToServer(record); // Change Cipher Spec record = proxy.readFromClient(); Assert.assertEquals(TLSRecord.Type.CHANGE_CIPHER_SPEC, record.getType()); proxy.flushToServer(record); // Client Done record = proxy.readFromClient(); Assert.assertEquals(TLSRecord.Type.HANDSHAKE, record.getType()); proxy.flushToServer(record); // Change Cipher Spec record = proxy.readFromServer(); Assert.assertEquals(TLSRecord.Type.CHANGE_CIPHER_SPEC, record.getType()); proxy.flushToClient(record); // Server Done record = proxy.readFromServer(); Assert.assertEquals(TLSRecord.Type.HANDSHAKE, record.getType()); proxy.flushToClient(record); Assert.assertNull(handshake.get(5, TimeUnit.SECONDS)); SimpleProxy.AutomaticFlow automaticProxyFlow = proxy.startAutomaticFlow(); // Read request BufferedReader reader = new BufferedReader(new InputStreamReader(server.getInputStream(), "UTF-8")); String line = reader.readLine(); Assert.assertTrue(line.startsWith(method)); while (line.length() > 0) line = reader.readLine(); // Write response OutputStream output = server.getOutputStream(); output.write(("HTTP/1.1 200 OK\r\n" + "Content-Length: 0\r\n" + "\r\n").getBytes("UTF-8")); output.flush(); Assert.assertTrue(automaticProxyFlow.stop(5, TimeUnit.SECONDS)); Assert.assertEquals(HttpExchange.STATUS_COMPLETED, exchange.waitForDone()); Assert.assertEquals(HttpStatus.OK_200, exchange.getResponseStatus()); } }