8230435: Replace wildcard address with loopback or local host in tests - part 22

Fixes tests to use the loopback address whenever possible. It also fixes some safe publishing issues, or add diagnostics in some of the tests.

Reviewed-by: michaelm
This commit is contained in:
Daniel Fuchs 2019-09-04 18:10:07 +01:00
parent 7b49c40ee9
commit f71db3074c
15 changed files with 200 additions and 52 deletions
test/jdk
com/sun/net/httpserver/bugs/8199849
java/net
javax/net/ssl/templates
sun/net

@ -157,7 +157,7 @@ public class BasicAuthenticatorCharset {
String defaultCharset = System.getProperty("file.encoding"); String defaultCharset = System.getProperty("file.encoding");
boolean isUTF8 = defaultCharset.equalsIgnoreCase("UTF-8"); boolean isUTF8 = defaultCharset.equalsIgnoreCase("UTF-8");
testHandler = new Handler(); testHandler = new Handler();
InetSocketAddress addr = new InetSocketAddress(0); InetSocketAddress addr = new InetSocketAddress(InetAddress.getLoopbackAddress(), 0);
testHttpServer = HttpServer.create(addr, 0); testHttpServer = HttpServer.create(addr, 0);
// Set the passing credentials OLD client // Set the passing credentials OLD client

@ -38,8 +38,8 @@ import jdk.test.lib.net.URIBuilder;
public class B4678055 implements HttpCallback { public class B4678055 implements HttpCallback {
static int count = 0; static volatile int count = 0;
static String authstring; static volatile String authstring;
void errorReply (HttpTransaction req, String reply) throws IOException { void errorReply (HttpTransaction req, String reply) throws IOException {
req.addResponseHeader ("Connection", "close"); req.addResponseHeader ("Connection", "close");
@ -56,6 +56,7 @@ public class B4678055 implements HttpCallback {
public void request (HttpTransaction req) { public void request (HttpTransaction req) {
try { try {
System.out.println("Server handling case: "+ count);
authstring = req.getRequestHeader ("Authorization"); authstring = req.getRequestHeader ("Authorization");
System.out.println (authstring); System.out.println (authstring);
switch (count) { switch (count) {
@ -95,6 +96,7 @@ public class B4678055 implements HttpCallback {
} }
count ++; count ++;
} catch (IOException e) { } catch (IOException e) {
System.err.println("Unexpected exception for case " + count + ": " + e);
e.printStackTrace(); e.printStackTrace();
} }
} }
@ -143,6 +145,8 @@ public class B4678055 implements HttpCallback {
client(serverURL + "d2/foo.html"); client(serverURL + "d2/foo.html");
client(serverURL + "d2/foo.html"); client(serverURL + "d2/foo.html");
} catch (Exception e) { } catch (Exception e) {
System.out.println("Client got exception: " + e);
System.out.println("Terminating server");
if (server != null) { if (server != null) {
server.terminate(); server.terminate();
} }
@ -156,10 +160,13 @@ public class B4678055 implements HttpCallback {
if (!checkFinalAuth()) { if (!checkFinalAuth()) {
except ("Wrong authorization string received from client"); except ("Wrong authorization string received from client");
} }
System.out.println("Terminating server");
server.terminate(); server.terminate();
} }
public static void except (String s) { public static void except (String s) {
System.out.println("Check failed: " + s);
System.out.println("Terminating server");
server.terminate(); server.terminate();
throw new RuntimeException (s); throw new RuntimeException (s);
} }
@ -169,7 +176,7 @@ public class B4678055 implements HttpCallback {
super (); super ();
} }
int count = 0; volatile int count = 0;
public PasswordAuthentication getPasswordAuthentication () { public PasswordAuthentication getPasswordAuthentication () {
PasswordAuthentication pw; PasswordAuthentication pw;

@ -24,6 +24,7 @@
/** /**
* @test * @test
* @bug 4361783 * @bug 4361783
* @key intermittent
* @summary Test to see if ICMP Port Unreachable on non-connected * @summary Test to see if ICMP Port Unreachable on non-connected
* DatagramSocket causes a SocketException "socket closed" * DatagramSocket causes a SocketException "socket closed"
* exception on Windows 2000. * exception on Windows 2000.
@ -43,7 +44,7 @@ public class PortUnreachable {
public void serverSend() { public void serverSend() {
try { try {
InetAddress addr = InetAddress.getLocalHost(); InetAddress addr = InetAddress.getLocalHost();
Thread.currentThread().sleep(1000); Thread.sleep(1000);
// send a delayed packet which should mean a delayed icmp // send a delayed packet which should mean a delayed icmp
// port unreachable // port unreachable
byte b[] = "A late msg".getBytes(); byte b[] = "A late msg".getBytes();
@ -64,26 +65,70 @@ public class PortUnreachable {
DatagramSocket recreateServerSocket (int serverPort) throws Exception { DatagramSocket recreateServerSocket (int serverPort) throws Exception {
DatagramSocket serverSocket = null; DatagramSocket serverSocket = null;
int retryCount = 0; int retryCount = 0;
long sleeptime = 0;
System.out.println("Attempting to recreate server socket with port: " + System.out.println("Attempting to recreate server socket with port: " +
serverPort); serverPort);
// it's possible that this method intermittently fails, if some other
// process running on the machine grabs the port we want before us,
// and doesn't release it before the 5 * 500 ms are elapsed...
while (serverSocket == null) { while (serverSocket == null) {
try { try {
serverSocket = new DatagramSocket(serverPort, InetAddress.getLocalHost()); serverSocket = new DatagramSocket(serverPort, InetAddress.getLocalHost());
} catch (BindException bEx) { } catch (BindException bEx) {
if (retryCount++ < 5) { if (retryCount++ < 5) {
Thread.sleep(500); sleeptime += sleepAtLeast(500);
} else { } else {
System.out.println("Give up after 5 retries"); System.out.println("Give up after 5 retries and " + sleeptime(sleeptime));
System.out.println("Has some other process grabbed port " + serverPort + "?");
throw bEx; throw bEx;
} }
} }
} }
System.out.println("PortUnreachableTest.recreateServerSocket: returning socket == " System.out.println("PortUnreachableTest.recreateServerSocket: returning socket == "
+ serverSocket.getLocalAddress() + ":" + serverSocket.getLocalPort()); + serverSocket.getLocalAddress() + ":" + serverSocket.getLocalPort()
+ " obtained at " + attempt(retryCount) + " attempt with " + sleeptime(sleeptime));
return serverSocket; return serverSocket;
} }
long sleepAtLeast(long millis) throws Exception {
long start = System.nanoTime();
long ms = millis;
while (ms > 0) {
assert ms < Long.MAX_VALUE/1000_000L;
Thread.sleep(ms);
long elapsedms = (System.nanoTime() - start)/1000_000L;
ms = millis - elapsedms;
}
return millis - ms;
}
String attempt(int retry) {
switch (retry) {
case 0: return "first";
case 1: return "second";
case 2: return "third";
default: return retry + "th";
}
}
String sleeptime(long millis) {
if (millis == 0) return "no sleep";
long sec = millis / 1000L;
long ms = millis % 1000L;
String sleeptime = "";
if (millis > 0) {
if (sec > 0) {
sleeptime = "" + sec + " s" +
(ms > 0 ? " " : "");
}
if (ms > 0 ) {
sleeptime += ms + " ms";
}
} else sleeptime = millis + " ms"; // should not happen
return sleeptime + " of sleep time";
}
PortUnreachable() throws Exception { PortUnreachable() throws Exception {
clientSock = new DatagramSocket(new InetSocketAddress(InetAddress.getLocalHost(), 0)); clientSock = new DatagramSocket(new InetSocketAddress(InetAddress.getLocalHost(), 0));
clientPort = clientSock.getLocalPort(); clientPort = clientSock.getLocalPort();
@ -126,4 +171,3 @@ public class PortUnreachable {
} }
} }

@ -73,7 +73,9 @@ class RedirLimitServer extends Thread {
// Read until the end of a HTTP request // Read until the end of a HTTP request
void readOneRequest(InputStream is) throws IOException { void readOneRequest(InputStream is) throws IOException {
int requestEndCount = 0, r; int requestEndCount = 0, r;
StringBuilder sb = new StringBuilder();
while ((r = is.read()) != -1) { while ((r = is.read()) != -1) {
sb.append((char)r);
if (r == requestEnd[requestEndCount]) { if (r == requestEnd[requestEndCount]) {
requestEndCount++; requestEndCount++;
if (requestEndCount == 4) { if (requestEndCount == 4) {
@ -83,6 +85,7 @@ class RedirLimitServer extends Thread {
requestEndCount = 0; requestEndCount = 0;
} }
} }
System.out.println("Server got request: " + sb.toString());
} }
public void run() { public void run() {
@ -90,15 +93,19 @@ class RedirLimitServer extends Thread {
readyToStart.countDown(); readyToStart.countDown();
for (int i=0; i<NUM_REDIRECTS; i++) { for (int i=0; i<NUM_REDIRECTS; i++) {
try (Socket s = ss.accept()) { try (Socket s = ss.accept()) {
System.out.println("Server accepted socket: " + s);
s.setSoTimeout(TIMEOUT); s.setSoTimeout(TIMEOUT);
readOneRequest(s.getInputStream()); readOneRequest(s.getInputStream());
System.out.println("Redirecting to: /redirect" + i);
String reply = reply1 + port + "/redirect" + i + reply2; String reply = reply1 + port + "/redirect" + i + reply2;
s.getOutputStream().write(reply.getBytes()); s.getOutputStream().write(reply.getBytes());
} }
} }
try (Socket s = ss.accept()) { try (Socket s = ss.accept()) {
System.out.println("Server accepted socket: " + s);
s.setSoTimeout(TIMEOUT); s.setSoTimeout(TIMEOUT);
readOneRequest(s.getInputStream()); readOneRequest(s.getInputStream());
System.out.println("Replying...");
s.getOutputStream().write(reply3.getBytes()); s.getOutputStream().write(reply3.getBytes());
} }
} catch (Exception e) { } catch (Exception e) {

@ -56,7 +56,8 @@ public class Responses {
* "HTTP/1.1 404 " * "HTTP/1.1 404 "
*/ */
static class HttpServer implements Runnable { static class HttpServer implements Runnable {
ServerSocket ss; final ServerSocket ss;
volatile boolean shutdown;
public HttpServer() { public HttpServer() {
try { try {
@ -83,6 +84,7 @@ public class Responses {
} }
public void shutdown() throws IOException { public void shutdown() throws IOException {
shutdown = true;
ss.close(); ss.close();
} }
@ -90,7 +92,7 @@ public class Responses {
Object[][] tests = getTests(); Object[][] tests = getTests();
try { try {
for (;;) { while(!shutdown) {
Socket s = ss.accept(); Socket s = ss.accept();
BufferedReader in = new BufferedReader( BufferedReader in = new BufferedReader(
@ -101,6 +103,7 @@ public class Responses {
int pos2 = req.indexOf(' ', pos1+1); int pos2 = req.indexOf(' ', pos1+1);
int i = Integer.parseInt(req.substring(pos1+2, pos2)); int i = Integer.parseInt(req.substring(pos1+2, pos2));
System.out.println("Server replying to >" + tests[i][0] + "<");
PrintStream out = new PrintStream( PrintStream out = new PrintStream(
new BufferedOutputStream( new BufferedOutputStream(
@ -117,6 +120,9 @@ public class Responses {
s.close(); s.close();
} }
} catch (Exception e) { } catch (Exception e) {
if (!shutdown) {
e.printStackTrace();
}
} }
} }
} }
@ -170,6 +176,7 @@ public class Responses {
actualPhrase + ", expected: " + expectedPhrase); actualPhrase + ", expected: " + expectedPhrase);
} }
} catch (IOException e) { } catch (IOException e) {
System.err.println("Test failed for >" + tests[i][0] + "<: " + e);
e.printStackTrace(); e.printStackTrace();
failures++; failures++;
} }

@ -45,6 +45,7 @@ import javax.net.ssl.SSLServerSocketFactory;
import javax.net.ssl.SSLSocket; import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManagerFactory; import javax.net.ssl.TrustManagerFactory;
import java.net.InetAddress;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.SocketTimeoutException; import java.net.SocketTimeoutException;
import java.security.KeyStore; import java.security.KeyStore;
@ -221,6 +222,11 @@ public class SSLSocketTemplate {
*/ */
protected volatile int serverPort = 0; protected volatile int serverPort = 0;
/*
* What's the server address? null means binding to the wildcard.
*/
protected volatile InetAddress serverAddress = null;
/* /*
* Define the server side of the test. * Define the server side of the test.
*/ */
@ -228,8 +234,13 @@ public class SSLSocketTemplate {
// kick start the server side service // kick start the server side service
SSLContext context = createServerSSLContext(); SSLContext context = createServerSSLContext();
SSLServerSocketFactory sslssf = context.getServerSocketFactory(); SSLServerSocketFactory sslssf = context.getServerSocketFactory();
SSLServerSocket sslServerSocket = InetAddress serverAddress = this.serverAddress;
(SSLServerSocket)sslssf.createServerSocket(serverPort); SSLServerSocket sslServerSocket = serverAddress == null ?
(SSLServerSocket)sslssf.createServerSocket(serverPort)
: (SSLServerSocket)sslssf.createServerSocket();
if (serverAddress != null) {
sslServerSocket.bind(new InetSocketAddress(serverAddress, serverPort));
}
configureServerSocket(sslServerSocket); configureServerSocket(sslServerSocket);
serverPort = sslServerSocket.getLocalPort(); serverPort = sslServerSocket.getLocalPort();
@ -317,8 +328,11 @@ public class SSLSocketTemplate {
try (SSLSocket sslSocket = (SSLSocket)sslsf.createSocket()) { try (SSLSocket sslSocket = (SSLSocket)sslsf.createSocket()) {
try { try {
configureClientSocket(sslSocket); configureClientSocket(sslSocket);
sslSocket.connect( InetAddress serverAddress = this.serverAddress;
new InetSocketAddress("localhost", serverPort), 15000); InetSocketAddress connectAddress = serverAddress == null
? new InetSocketAddress("localhost", serverPort)
: new InetSocketAddress(serverAddress, serverPort);
sslSocket.connect(connectAddress, 15000);
} catch (IOException ioe) { } catch (IOException ioe) {
// The server side may be impacted by naughty test cases or // The server side may be impacted by naughty test cases or
// third party routines, and cannot accept connections. // third party routines, and cannot accept connections.

@ -101,8 +101,22 @@ public class DefaultCaching {
static void sleep(int seconds) { static void sleep(int seconds) {
try { try {
Thread.sleep(seconds * 1000); sleepms(seconds * 1000);
} catch (InterruptedException e) {} } catch (InterruptedException e) {
e.printStackTrace();
}
}
static long sleepms(long millis) throws InterruptedException {
long start = System.nanoTime();
long ms = millis;
while (ms > 0) {
assert ms < Long.MAX_VALUE/1000_000L;
Thread.sleep(ms);
long elapsedms = (System.nanoTime() - start)/1000_000L;
ms = millis - elapsedms;
}
return millis - ms;
} }
static void test(String host, String address, boolean shouldSucceed) { static void test(String host, String address, boolean shouldSucceed) {
@ -114,7 +128,7 @@ public class DefaultCaching {
+ addr + ")"); + addr + ")");
} }
if (!address.equals(addr.getHostAddress())) { if (!address.equals(addr.getHostAddress())) {
throw new RuntimeException(host+":"+address+": compare failed (found " throw new RuntimeException(host+"/"+address+": compare failed (found "
+ addr + ")"); + addr + ")");
} }
System.out.println("test: " + host + "/" + address System.out.println("test: " + host + "/" + address

@ -85,7 +85,7 @@ public class AuthHeaderTest implements HttpCallback {
static void client (String u) throws Exception { static void client (String u) throws Exception {
URL url = new URL (u); URL url = new URL (u);
System.out.println ("client opening connection to: " + u); System.out.println ("client opening connection to: " + u);
URLConnection urlc = url.openConnection (); URLConnection urlc = url.openConnection (Proxy.NO_PROXY);
InputStream is = urlc.getInputStream (); InputStream is = urlc.getInputStream ();
read (is); read (is);
is.close(); is.close();

@ -84,13 +84,17 @@ public class RetryPost
throw new RuntimeException("Failed: POST request being retried"); throw new RuntimeException("Failed: POST request being retried");
} catch (SocketException se) { } catch (SocketException se) {
System.out.println("Got expected exception: " + se);
// this is what we expect to happen and is OK. // this is what we expect to happen and is OK.
if (shouldRetry && httpHandler.getCallCount() != 2) if (shouldRetry && httpHandler.getCallCount() != 2) {
se.printStackTrace(System.out);
throw new RuntimeException("Failed: Handler should have been called twice. " + throw new RuntimeException("Failed: Handler should have been called twice. " +
"It was called "+ httpHandler.getCallCount() + " times"); "It was called "+ httpHandler.getCallCount() + " times");
else if (!shouldRetry && httpHandler.getCallCount() != 1) } else if (!shouldRetry && httpHandler.getCallCount() != 1) {
se.printStackTrace(System.out);
throw new RuntimeException("Failed: Handler should have only been called once" + throw new RuntimeException("Failed: Handler should have only been called once" +
"It was called "+ httpHandler.getCallCount() + " times"); "It was called "+ httpHandler.getCallCount() + " times");
}
} finally { } finally {
httpServer.stop(1); httpServer.stop(1);
executorService.shutdown(); executorService.shutdown();

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -59,6 +59,7 @@ import java.io.DataOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.net.Authenticator; import java.net.Authenticator;
import java.net.InetAddress;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.PasswordAuthentication; import java.net.PasswordAuthentication;
import java.net.Proxy; import java.net.Proxy;
@ -80,6 +81,10 @@ import static java.nio.charset.StandardCharsets.US_ASCII;
public class ProxyAuthTest extends SSLSocketTemplate { public class ProxyAuthTest extends SSLSocketTemplate {
private static boolean expectSuccess; private static boolean expectSuccess;
ProxyAuthTest() {
serverAddress = InetAddress.getLoopbackAddress();
}
/* /*
* Run the test case. * Run the test case.
*/ */
@ -143,18 +148,25 @@ public class ProxyAuthTest extends SSLSocketTemplate {
*/ */
HttpsURLConnection.setDefaultHostnameVerifier(new NameVerifier()); HttpsURLConnection.setDefaultHostnameVerifier(new NameVerifier());
InetSocketAddress paddr = InetSocketAddress paddr = InetSocketAddress
new InetSocketAddress("localhost", ps.getPort()); .createUnresolved(ps.getInetAddress().getHostAddress(),
ps.getPort());
Proxy proxy = new Proxy(Proxy.Type.HTTP, paddr); Proxy proxy = new Proxy(Proxy.Type.HTTP, paddr);
InetAddress serverAddress = this.serverAddress;
String host = serverAddress == null
? "localhost"
: serverAddress.getHostAddress();
if (host.indexOf(':') > -1) host = "[" + host + "]";
URL url = new URL( URL url = new URL(
"https://" + "localhost:" + serverPort + "/index.html"); "https://" + host + ":" + serverPort + "/index.html");
System.out.println("URL: " + url);
BufferedReader in = null; BufferedReader in = null;
HttpsURLConnection uc = (HttpsURLConnection) url.openConnection(proxy); HttpsURLConnection uc = (HttpsURLConnection) url.openConnection(proxy);
try { try {
in = new BufferedReader(new InputStreamReader(uc.getInputStream())); in = new BufferedReader(new InputStreamReader(uc.getInputStream()));
String inputLine; String inputLine;
System.out.print("Client recieved from the server: "); System.out.print("Client received from the server: ");
while ((inputLine = in.readLine()) != null) { while ((inputLine = in.readLine()) != null) {
System.out.println(inputLine); System.out.println(inputLine);
} }
@ -226,7 +238,8 @@ public class ProxyAuthTest extends SSLSocketTemplate {
} }
private static ProxyTunnelServer setupProxy() throws IOException { private static ProxyTunnelServer setupProxy() throws IOException {
ProxyTunnelServer pserver = new ProxyTunnelServer(); InetAddress loopback = InetAddress.getLoopbackAddress();
ProxyTunnelServer pserver = new ProxyTunnelServer(loopback);
/* /*
* register a system wide authenticator and setup the proxy for * register a system wide authenticator and setup the proxy for

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -61,9 +61,14 @@ public class ProxyTunnelServer extends Thread {
static boolean needAuth = false; static boolean needAuth = false;
public ProxyTunnelServer() throws IOException { public ProxyTunnelServer() throws IOException {
this(null); // use wildcard
}
public ProxyTunnelServer(InetAddress proxyAddress) throws IOException {
if (ss == null) { if (ss == null) {
ss = (ServerSocket) ServerSocketFactory.getDefault(). ss = (ServerSocket) ServerSocketFactory.getDefault().
createServerSocket(0); createServerSocket();
ss.bind(new InetSocketAddress(proxyAddress, 0));
} }
setDaemon(true); setDaemon(true);
} }
@ -274,9 +279,9 @@ public class ProxyTunnelServer extends Thread {
serverName = connectInfo.substring(0, endi); serverName = connectInfo.substring(0, endi);
serverPort = Integer.parseInt(connectInfo.substring(endi+1)); serverPort = Integer.parseInt(connectInfo.substring(endi+1));
} catch (Exception e) { } catch (Exception e) {
throw new IOException("Proxy recieved a request: " throw new IOException("Proxy received a request: "
+ connectStr); + connectStr, e);
} }
serverInetAddr = InetAddress.getByName(serverName); serverInetAddr = InetAddress.getByName(serverName);
} }
@ -284,6 +289,10 @@ public class ProxyTunnelServer extends Thread {
return ss.getLocalPort(); return ss.getLocalPort();
} }
public InetAddress getInetAddress() {
return ss.getInetAddress();
}
/* /*
* do "basic" authentication, authInfo is of the form: * do "basic" authentication, authInfo is of the form:
* Basic <encoded username":"password> * Basic <encoded username":"password>

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -139,8 +139,8 @@ public class B6216082 {
// Both the https server and the proxy let the // Both the https server and the proxy let the
// system pick up an ephemeral port. // system pick up an ephemeral port.
httpTrans = new SimpleHttpTransaction(); httpTrans = new SimpleHttpTransaction();
server = new TestHttpsServer(httpTrans, 1, 10, 0); server = new TestHttpsServer(httpTrans, 1, 10, firstNonLoAddress, 0);
proxy = new TunnelProxy(1, 10, 0); proxy = new TunnelProxy(1, 10, firstNonLoAddress, 0);
} }
public static void makeHttpCall() throws Exception { public static void makeHttpCall() throws Exception {

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -47,12 +47,14 @@ public class B6226610 {
proxy = new HeaderCheckerProxyTunnelServer(); proxy = new HeaderCheckerProxyTunnelServer();
proxy.start(); proxy.start();
String hostname = InetAddress.getLocalHost().getHostName(); InetAddress localHost = InetAddress.getLocalHost();
String hostname = localHost.getHostName();
String hostAddress = localHost.getHostAddress();
try { try {
URL u = new URL("https://" + hostname + "/"); URL u = new URL("https://" + hostname + "/");
System.out.println("Connecting to " + u); System.out.println("Connecting to " + u);
InetSocketAddress proxyAddr = new InetSocketAddress(hostname, proxy.getLocalPort()); InetSocketAddress proxyAddr = InetSocketAddress.createUnresolved(hostAddress, proxy.getLocalPort());
java.net.URLConnection c = u.openConnection(new Proxy(Proxy.Type.HTTP, proxyAddr)); java.net.URLConnection c = u.openConnection(new Proxy(Proxy.Type.HTTP, proxyAddr));
/* I want this header to go to the destination server only, protected /* I want this header to go to the destination server only, protected
@ -96,7 +98,8 @@ class HeaderCheckerProxyTunnelServer extends Thread
public HeaderCheckerProxyTunnelServer() throws IOException public HeaderCheckerProxyTunnelServer() throws IOException
{ {
if (ss == null) { if (ss == null) {
ss = new ServerSocket(0); ss = new ServerSocket();
ss.bind(new InetSocketAddress(InetAddress.getLocalHost(), 0));
} }
} }
@ -143,16 +146,16 @@ class HeaderCheckerProxyTunnelServer extends Thread
retrieveConnectInfo(statusLine); retrieveConnectInfo(statusLine);
if (mheader.findValue("X-TestHeader") != null) { if (mheader.findValue("X-TestHeader") != null) {
System.out.println("Proxy should not receive user defined headers for tunneled requests"); System.out.println("Proxy should not receive user defined headers for tunneled requests");
failed = true; failed = true;
} }
// 6973030 // 6973030
String value; String value;
if ((value = mheader.findValue("Proxy-Connection")) == null || if ((value = mheader.findValue("Proxy-Connection")) == null ||
!value.equals("keep-alive")) { !value.equals("keep-alive")) {
System.out.println("Proxy-Connection:keep-alive not being sent"); System.out.println("Proxy-Connection:keep-alive not being sent");
failed = true; failed = true;
} }
//This will allow the main thread to terminate without trying to perform the SSL handshake. //This will allow the main thread to terminate without trying to perform the SSL handshake.
@ -206,8 +209,8 @@ class HeaderCheckerProxyTunnelServer extends Thread
serverPort = Integer.parseInt(connectInfo.substring(endi+1)); serverPort = Integer.parseInt(connectInfo.substring(endi+1));
} catch (Exception e) { } catch (Exception e) {
throw new IOException("Proxy recieved a request: " throw new IOException("Proxy recieved a request: "
+ connectStr); + connectStr, e);
} }
serverInetAddr = InetAddress.getByName(serverName); serverInetAddr = InetAddress.getByName(serverName);
} }
} }

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -34,6 +34,7 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.net.Authenticator; import java.net.Authenticator;
import java.net.Proxy; import java.net.Proxy;
import java.net.InetAddress;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.PasswordAuthentication; import java.net.PasswordAuthentication;
import java.net.ServerSocket; import java.net.ServerSocket;
@ -51,9 +52,11 @@ public class HttpsProxyStackOverflow {
static void doClient(BadAuthProxyServer server) throws IOException { static void doClient(BadAuthProxyServer server) throws IOException {
// url doesn't matter since we will never make the connection // url doesn't matter since we will never make the connection
URL url = new URL("https://anythingwilldo/"); URL url = new URL("https://anythingwilldo/");
InetAddress loopback = InetAddress.getLoopbackAddress();
String loopbackAddress = loopback.getHostAddress();
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection( HttpsURLConnection conn = (HttpsURLConnection) url.openConnection(
new Proxy(Proxy.Type.HTTP, new Proxy(Proxy.Type.HTTP,
new InetSocketAddress("localhost", server.getPort()))); InetSocketAddress.createUnresolved(loopbackAddress, server.getPort())));
try (InputStream is = conn.getInputStream()) { try (InputStream is = conn.getInputStream()) {
} catch(IOException unused) { } catch(IOException unused) {
// no real server, IOException is expected. // no real server, IOException is expected.
@ -70,8 +73,11 @@ public class HttpsProxyStackOverflow {
return new PasswordAuthentication("xyz", "xyz".toCharArray()); return new PasswordAuthentication("xyz", "xyz".toCharArray());
} }
}); });
InetAddress loopback = InetAddress.getLoopbackAddress();
BadAuthProxyServer server = new BadAuthProxyServer(new ServerSocket(0)); InetSocketAddress address = new InetSocketAddress(loopback, 0);
ServerSocket ss = new ServerSocket();
ss.bind(address);
BadAuthProxyServer server = new BadAuthProxyServer(ss);
Thread serverThread = new Thread(server); Thread serverThread = new Thread(server);
serverThread.start(); serverThread.start();
return server; return server;
@ -113,4 +119,3 @@ public class HttpsProxyStackOverflow {
} }
} }
} }

@ -85,9 +85,30 @@ public class TunnelProxy {
*/ */
public TunnelProxy (int threads, int cperthread, int port) public TunnelProxy (int threads, int cperthread, int port)
throws IOException {
this(threads, cperthread, null, 0);
}
/**
* Create a <code>TunnelProxy<code> instance with the specified number
* of threads and maximum number of connections per thread and running on
* the specified port. The specified number of threads are created to
* handle incoming requests, and each thread is allowed
* to handle a number of simultaneous TCP connections.
* @param cb the callback object which is invoked to handle
* each incoming request
* @param threads the number of threads to create to handle
* requests in parallel
* @param cperthread the number of simultaneous TCP connections
* to handle per thread
* @param address the address to bind to. null means all addresses.
* @param port the port number to bind the server to. <code>Zero</code>
* means choose any free port.
*/
public TunnelProxy (int threads, int cperthread, InetAddress address, int port)
throws IOException { throws IOException {
schan = ServerSocketChannel.open (); schan = ServerSocketChannel.open ();
InetSocketAddress addr = new InetSocketAddress (port); InetSocketAddress addr = new InetSocketAddress (address, port);
schan.socket().bind (addr); schan.socket().bind (addr);
this.threads = threads; this.threads = threads;
this.cperthread = cperthread; this.cperthread = cperthread;