undefect. CWE-407 — 63 sites patched across 27 ecosystems
Authors: russell@unturf.com · brackishbert@gmail.com · foxhop.net · TimeHexOn.com Patches, unit tests, benchmarks, whitepaper, and outreach briefs. Public domain — no copyright claimed. Use freely.
This commit is contained in:
commit
0a580b313d
70422 changed files with 17213626 additions and 0 deletions
88
test/jdk/java/net/Socks/BadProxySelector.java
Normal file
88
test/jdk/java/net/Socks/BadProxySelector.java
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 7178362
|
||||
* @run main/othervm BadProxySelector
|
||||
*/
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Proxy;
|
||||
import java.net.ProxySelector;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.io.*;
|
||||
|
||||
public class BadProxySelector {
|
||||
public static void main(String[] args) throws Exception {
|
||||
ProxySelector.setDefault(new HTTPProxySelector());
|
||||
try (ServerSocket ss = new ServerSocket(0, 0, InetAddress.getLocalHost());
|
||||
Socket s1 = new Socket(ss.getInetAddress(), ss.getLocalPort());
|
||||
Socket s2 = ss.accept()) {
|
||||
}
|
||||
|
||||
ProxySelector.setDefault(new NullHTTPProxySelector());
|
||||
try (ServerSocket ss = new ServerSocket(0, 0, InetAddress.getLocalHost());
|
||||
Socket s1 = new Socket(ss.getInetAddress(), ss.getLocalPort());
|
||||
Socket s2 = ss.accept()) {
|
||||
}
|
||||
}
|
||||
|
||||
// always returns bogus HTTP proxies
|
||||
private static class HTTPProxySelector extends ProxySelector {
|
||||
@Override
|
||||
public void connectFailed(URI uri, SocketAddress sa, IOException ioe) {}
|
||||
|
||||
@Override
|
||||
public List<Proxy> select(URI uri) {
|
||||
System.out.println(this.getClass().getSimpleName() + " called for " + uri);
|
||||
List<Proxy> proxies = new ArrayList<>();
|
||||
proxies.add(new Proxy(Proxy.Type.HTTP,
|
||||
new InetSocketAddress("localhost", 0)));
|
||||
proxies.add(new Proxy(Proxy.Type.HTTP,
|
||||
new InetSocketAddress("localhost", 0)));
|
||||
return proxies;
|
||||
}
|
||||
}
|
||||
|
||||
private static class NullHTTPProxySelector extends ProxySelector {
|
||||
@Override
|
||||
public void connectFailed(URI uri, SocketAddress sa, IOException ioe) {}
|
||||
|
||||
@Override
|
||||
public List<Proxy> select(URI uri) {
|
||||
System.out.println(this.getClass().getSimpleName() + " called for " + uri);
|
||||
List<Proxy> proxies = new ArrayList<>();
|
||||
proxies.add(null);
|
||||
proxies.add(new Proxy(Proxy.Type.HTTP,
|
||||
new InetSocketAddress("localhost", 0)));
|
||||
return proxies;
|
||||
}
|
||||
}
|
||||
}
|
||||
203
test/jdk/java/net/Socks/SocksIPv6Test.java
Normal file
203
test/jdk/java/net/Socks/SocksIPv6Test.java
Normal file
|
|
@ -0,0 +1,203 @@
|
|||
/*
|
||||
* Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/* @test
|
||||
* @bug 7100957
|
||||
* @modules jdk.httpserver
|
||||
* @library /test/lib
|
||||
* @summary Java doesn't correctly handle the SOCKS protocol when used over IPv6.
|
||||
* @run testng SocksIPv6Test
|
||||
*/
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.net.Authenticator;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.URL;
|
||||
import java.net.Proxy;
|
||||
import java.lang.Override;
|
||||
import java.net.InetAddress;
|
||||
import java.net.Inet6Address;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.SocketException;
|
||||
import java.net.NetworkInterface;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import com.sun.net.httpserver.*;
|
||||
import java.io.BufferedWriter;
|
||||
import org.testng.SkipException;
|
||||
import org.testng.annotations.AfterClass;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import jdk.test.lib.NetworkConfiguration;
|
||||
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
public class SocksIPv6Test {
|
||||
|
||||
private HttpServer server;
|
||||
private SocksServer socks;
|
||||
private String response = "Hello.";
|
||||
|
||||
@BeforeClass
|
||||
public void setUp() throws Exception {
|
||||
if (!ensureInet6AddressFamily() || !ensureIPv6OnLoopback()) {
|
||||
NetworkConfiguration.printSystemConfiguration(System.out);
|
||||
throw new SkipException("Host does not support IPv6");
|
||||
}
|
||||
|
||||
server = HttpServer.create(new InetSocketAddress("::1", 0), 0);
|
||||
server.createContext("/", ex -> {
|
||||
ex.sendResponseHeaders(200, response.length());
|
||||
try (BufferedWriter writer = new BufferedWriter(
|
||||
new OutputStreamWriter(ex.getResponseBody(), "UTF-8"))) {
|
||||
writer.write(response);
|
||||
}
|
||||
ex.close();
|
||||
});
|
||||
server.start();
|
||||
|
||||
socks = new SocksServer(InetAddress.getByName("::1"), 0, false);
|
||||
socks.addUser("user", "pass");
|
||||
socks.start();
|
||||
|
||||
Authenticator.setDefault(new Authenticator() {
|
||||
@Override
|
||||
protected java.net.PasswordAuthentication getPasswordAuthentication() {
|
||||
return new java.net.PasswordAuthentication(
|
||||
"user", "pass".toCharArray());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private boolean ensureIPv6OnLoopback() throws Exception {
|
||||
boolean ipv6 = false;
|
||||
|
||||
List<NetworkInterface> nics = Collections.list(NetworkInterface.getNetworkInterfaces());
|
||||
for (NetworkInterface nic : nics) {
|
||||
if (!nic.isLoopback()) {
|
||||
continue;
|
||||
}
|
||||
List<InetAddress> addrs = Collections.list(nic.getInetAddresses());
|
||||
for (InetAddress addr : addrs) {
|
||||
if (addr instanceof Inet6Address) {
|
||||
ipv6 = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!ipv6)
|
||||
System.out.println("IPv6 is not enabled on loopback. Skipping test suite.");
|
||||
return ipv6;
|
||||
}
|
||||
|
||||
private boolean ensureInet6AddressFamily() throws IOException {
|
||||
try (ServerSocket s = new ServerSocket()) {
|
||||
s.bind(new InetSocketAddress("::1", 0));
|
||||
return true;
|
||||
} catch (SocketException e) {
|
||||
System.out.println("Inet 6 address family is not available. Skipping test suite.");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Test(groups = "unit")
|
||||
public void testSocksOverIPv6() throws Exception {
|
||||
Proxy proxy = new Proxy(Proxy.Type.SOCKS, new InetSocketAddress("::1",
|
||||
socks.getPort()));
|
||||
URL url = new URL("http://[::1]:" + server.getAddress().getPort());
|
||||
java.net.URLConnection conn = url.openConnection(proxy);
|
||||
String actual = "";
|
||||
try (BufferedReader reader = new BufferedReader(
|
||||
new InputStreamReader(conn.getInputStream()))) {
|
||||
actual = reader.readLine();
|
||||
}
|
||||
assertEquals(actual, response);
|
||||
}
|
||||
|
||||
@Test(groups = "unit")
|
||||
public void testSocksOverIPv6Hostname() throws Exception {
|
||||
InetAddress ipv6Loopback = InetAddress.getByName("::1");
|
||||
String ipv6Hostname = ipv6Loopback.getHostName();
|
||||
String ipv6HostAddress = ipv6Loopback.getHostAddress();
|
||||
InetAddress ipv4Loopback;
|
||||
String ipv4Hostname;
|
||||
String ipv4HostAddress;
|
||||
try {
|
||||
ipv4Loopback = InetAddress.getByName("127.0.0.1");
|
||||
ipv4Hostname = ipv4Loopback == null ? null : ipv4Loopback.getHostName();
|
||||
ipv4HostAddress = ipv4Loopback == null ? null : ipv4Loopback.getHostAddress();
|
||||
} catch (IOException io) {
|
||||
ipv4Hostname = null;
|
||||
ipv4HostAddress = null;
|
||||
}
|
||||
|
||||
System.out.println("ipv6Hostname: " + ipv6Hostname + " / " + ipv6HostAddress);
|
||||
System.out.println("ipv4Hostname: " + ipv4Hostname + " / " + ipv4HostAddress);
|
||||
|
||||
if (ipv6Hostname.equals(ipv6HostAddress)) {
|
||||
System.out.println("Unable to get the hostname of the IPv6 loopback "
|
||||
+ "address. Skipping test case.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (ipv4Hostname != null && ipv6Hostname.equals(ipv4Hostname)) {
|
||||
System.out.println("IPv6 and IPv4 loopback addresses map to the"
|
||||
+ " same hostname. Skipping test case.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!InetAddress.getByName(ipv6Hostname).getHostAddress()
|
||||
.equals(ipv6HostAddress)) {
|
||||
System.out.println(ipv6Hostname + " resolves to \""
|
||||
+ InetAddress.getByName(ipv6Hostname).getHostAddress()
|
||||
+ "\", not \"" + ipv6HostAddress +
|
||||
"\". Skipping test case.");
|
||||
return;
|
||||
}
|
||||
|
||||
Proxy proxy = new Proxy(Proxy.Type.SOCKS, new InetSocketAddress(ipv6Hostname,
|
||||
socks.getPort()));
|
||||
URL url = new URL("http://" + ipv6Hostname + ":" + server.getAddress().getPort());
|
||||
java.net.URLConnection conn = url.openConnection(proxy);
|
||||
String actual = "";
|
||||
try (BufferedReader reader = new BufferedReader(
|
||||
new InputStreamReader(conn.getInputStream()))) {
|
||||
actual = reader.readLine();
|
||||
}
|
||||
assertEquals(actual, response);
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public void tearDown() {
|
||||
if (server != null) {
|
||||
server.stop(1);
|
||||
}
|
||||
if (socks != null) {
|
||||
socks.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
134
test/jdk/java/net/Socks/SocksProxyVersion.java
Normal file
134
test/jdk/java/net/Socks/SocksProxyVersion.java
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
/*
|
||||
* Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 6964547 5001942 8129444
|
||||
* @library /test/lib
|
||||
* @run main/othervm SocksProxyVersion
|
||||
* @summary test socksProxyVersion system property
|
||||
*/
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketException;
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.Proxy;
|
||||
import jdk.test.lib.net.IPSupport;
|
||||
|
||||
public class SocksProxyVersion implements Runnable {
|
||||
final ServerSocket ss;
|
||||
volatile boolean failed;
|
||||
volatile boolean stopped = false;
|
||||
volatile int expected;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
if (InetAddress.getLocalHost().isLoopbackAddress()) {
|
||||
System.out.println("Test cannot run. getLocalHost returns a loopback address");
|
||||
return;
|
||||
}
|
||||
new SocksProxyVersion();
|
||||
}
|
||||
|
||||
public SocksProxyVersion() throws Exception {
|
||||
ss = new ServerSocket(0, 0, InetAddress.getLocalHost());
|
||||
int port = ss.getLocalPort();
|
||||
Thread serverThread = new Thread(this);
|
||||
serverThread.start();
|
||||
try (ServerSocket socket = ss) {
|
||||
runTest(port);
|
||||
} finally {
|
||||
stopped = true;
|
||||
}
|
||||
|
||||
serverThread.join();
|
||||
if (failed) {
|
||||
throw new RuntimeException("socksProxyVersion not being set correctly");
|
||||
}
|
||||
}
|
||||
|
||||
final void runTest(int port) throws Exception {
|
||||
/*
|
||||
* Retrieving the IP Address of the machine
|
||||
* since "localhost" is bypassed as a non-proxy host
|
||||
*/
|
||||
String addr = InetAddress.getLocalHost().getHostAddress();
|
||||
|
||||
System.setProperty("socksProxyHost", addr);
|
||||
System.setProperty("socksProxyPort", Integer.toString(port));
|
||||
|
||||
Proxy proxy = new Proxy(Proxy.Type.SOCKS,
|
||||
new InetSocketAddress(addr, port));
|
||||
|
||||
if (IPSupport.hasIPv4()) {
|
||||
// SOCKS V4 (requires IPv4)
|
||||
System.setProperty("socksProxyVersion", "4");
|
||||
this.expected = 4;
|
||||
check(new Socket(), addr, port);
|
||||
check(new Socket(proxy), addr, port);
|
||||
}
|
||||
|
||||
// SOCKS V5
|
||||
System.setProperty("socksProxyVersion", "5");
|
||||
this.expected = 5;
|
||||
check(new Socket(), addr, port);
|
||||
check(new Socket(proxy), addr, port);
|
||||
}
|
||||
|
||||
private void check(Socket socket, String addr, int port)
|
||||
throws IOException
|
||||
{
|
||||
try (Socket s = socket) {
|
||||
socket.connect(new InetSocketAddress(addr, port));
|
||||
} catch (SocketException e) {
|
||||
// java.net.SocketException: Malformed reply from SOCKS server
|
||||
// This exception is OK, since the "server" does not implement
|
||||
// the socks protocol. It just verifies the version and closes.
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
int count = 0;
|
||||
try {
|
||||
while (!stopped) {
|
||||
try (Socket s = ss.accept()) {
|
||||
int version = (s.getInputStream()).read();
|
||||
if (version != expected) {
|
||||
System.out.printf("Iteration: %d, Got: %d, expected: %d%n",
|
||||
count, version, expected);
|
||||
failed = true;
|
||||
}
|
||||
}
|
||||
count++;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
if (!ss.isClosed()) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
// ignore, server socket was closed
|
||||
}
|
||||
}
|
||||
}
|
||||
543
test/jdk/java/net/Socks/SocksServer.java
Normal file
543
test/jdk/java/net/Socks/SocksServer.java
Normal file
|
|
@ -0,0 +1,543 @@
|
|||
/*
|
||||
* Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
import java.net.*;
|
||||
import java.io.*;
|
||||
import java.util.HashMap;
|
||||
|
||||
public class SocksServer extends Thread implements Closeable {
|
||||
// Some useful SOCKS constant
|
||||
|
||||
static final int PROTO_VERS4 = 4;
|
||||
static final int PROTO_VERS = 5;
|
||||
static final int DEFAULT_PORT = 1080;
|
||||
|
||||
static final int NO_AUTH = 0;
|
||||
static final int GSSAPI = 1;
|
||||
static final int USER_PASSW = 2;
|
||||
static final int NO_METHODS = -1;
|
||||
|
||||
static final int CONNECT = 1;
|
||||
static final int BIND = 2;
|
||||
static final int UDP_ASSOC = 3;
|
||||
|
||||
static final int IPV4 = 1;
|
||||
static final int DOMAIN_NAME = 3;
|
||||
static final int IPV6 = 4;
|
||||
|
||||
static final int REQUEST_OK = 0;
|
||||
static final int GENERAL_FAILURE = 1;
|
||||
static final int NOT_ALLOWED = 2;
|
||||
static final int NET_UNREACHABLE = 3;
|
||||
static final int HOST_UNREACHABLE = 4;
|
||||
static final int CONN_REFUSED = 5;
|
||||
static final int TTL_EXPIRED = 6;
|
||||
static final int CMD_NOT_SUPPORTED = 7;
|
||||
static final int ADDR_TYPE_NOT_SUP = 8;
|
||||
|
||||
private int port;
|
||||
private ServerSocket server;
|
||||
private boolean useV4 = false;
|
||||
private HashMap<String,String> users = new HashMap<>();
|
||||
private volatile boolean done = false;
|
||||
// Inner class to handle protocol with client
|
||||
// This is the bulk of the work (protocol handler)
|
||||
class ClientHandler extends Thread {
|
||||
private InputStream in;
|
||||
private OutputStream out;
|
||||
private Socket client;
|
||||
private Socket dest;
|
||||
|
||||
// Simple tunneling class, moving bits from one stream to another
|
||||
|
||||
class Tunnel extends Thread {
|
||||
private InputStream tin;
|
||||
private OutputStream tout;
|
||||
|
||||
Tunnel(InputStream in, OutputStream out) {
|
||||
tin = in;
|
||||
tout = out;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
int b;
|
||||
while (true) {
|
||||
try {
|
||||
b = tin.read();
|
||||
if (b == -1) {
|
||||
tin.close();
|
||||
tout.close();
|
||||
return;
|
||||
}
|
||||
tout.write(b);
|
||||
tout.flush();
|
||||
} catch (IOException e) {
|
||||
// actually exit from the thread
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ClientHandler(Socket s) throws IOException {
|
||||
client = s;
|
||||
in = new BufferedInputStream(client.getInputStream());
|
||||
out = new BufferedOutputStream(client.getOutputStream());
|
||||
}
|
||||
|
||||
private void readBuf(InputStream is, byte[] buf) throws IOException {
|
||||
int l = buf.length;
|
||||
int count = 0;
|
||||
int i;
|
||||
do {
|
||||
i = is.read(buf, count, l - count);
|
||||
if (i == -1)
|
||||
throw new IOException("unexpected EOF");
|
||||
count += i;
|
||||
} while (count < l);
|
||||
}
|
||||
|
||||
|
||||
private boolean userPassAuth() throws IOException {
|
||||
int ver = in.read();
|
||||
int ulen = in.read();
|
||||
if (ulen <= 0)
|
||||
throw new SocketException("SOCKS protocol error");
|
||||
byte[] buf = new byte[ulen];
|
||||
readBuf(in, buf);
|
||||
String uname = new String(buf);
|
||||
String password = null;
|
||||
ulen = in.read();
|
||||
if (ulen < 0)
|
||||
throw new SocketException("SOCKS protocol error");
|
||||
if (ulen > 0) {
|
||||
buf = new byte[ulen];
|
||||
readBuf(in, buf);
|
||||
password = new String(buf);
|
||||
}
|
||||
// Check username/password validity here
|
||||
System.err.println("User: '" + uname);
|
||||
System.err.println("PSWD: '" + password);
|
||||
if (users.containsKey(uname)) {
|
||||
String p1 = users.get(uname);
|
||||
System.err.println("p1 = " + p1);
|
||||
if (p1.equals(password)) {
|
||||
out.write(PROTO_VERS);
|
||||
out.write(REQUEST_OK);
|
||||
out.flush();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
out.write(PROTO_VERS);
|
||||
out.write(NOT_ALLOWED);
|
||||
out.flush();
|
||||
return false;
|
||||
}
|
||||
|
||||
private void purge() throws IOException {
|
||||
boolean done = false;
|
||||
int i = 0;
|
||||
client.setSoTimeout(1000);
|
||||
while(!done && i != -1) {
|
||||
try {
|
||||
i = in.read();
|
||||
} catch(IOException e) {
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Handle the SOCKS version 4 protocl
|
||||
|
||||
private void getRequestV4() throws IOException {
|
||||
int ver = in.read();
|
||||
int cmd = in.read();
|
||||
if (ver == -1 || cmd == -1) {
|
||||
// EOF
|
||||
in.close();
|
||||
out.close();
|
||||
return;
|
||||
}
|
||||
|
||||
if (ver != 0 && ver != 4) {
|
||||
out.write(PROTO_VERS4);
|
||||
out.write(91); // Bad Request
|
||||
out.write(0);
|
||||
out.write(0);
|
||||
out.write(0);
|
||||
out.write(0);
|
||||
out.write(0);
|
||||
out.write(0);
|
||||
out.write(0);
|
||||
out.flush();
|
||||
purge();
|
||||
out.close();
|
||||
in.close();
|
||||
return;
|
||||
}
|
||||
|
||||
if (cmd == CONNECT) {
|
||||
int port = ((in.read() & 0xff) << 8);
|
||||
port += (in.read() & 0xff);
|
||||
byte[] buf = new byte[4];
|
||||
readBuf(in, buf);
|
||||
InetAddress addr = InetAddress.getByAddress(buf);
|
||||
// We don't use the username...
|
||||
int c;
|
||||
do {
|
||||
c = (in.read() & 0xff);
|
||||
} while (c!=0);
|
||||
boolean ok = true;
|
||||
try {
|
||||
dest = new Socket(addr, port);
|
||||
} catch (IOException e) {
|
||||
ok = false;
|
||||
}
|
||||
if (!ok) {
|
||||
out.write(PROTO_VERS4);
|
||||
out.write(91);
|
||||
out.write(0);
|
||||
out.write(0);
|
||||
out.write(buf);
|
||||
out.flush();
|
||||
purge();
|
||||
out.close();
|
||||
in.close();
|
||||
return;
|
||||
}
|
||||
out.write(PROTO_VERS4);
|
||||
out.write(90); // Success
|
||||
out.write((port >> 8) & 0xff);
|
||||
out.write(port & 0xff);
|
||||
out.write(buf);
|
||||
out.flush();
|
||||
InputStream in2 = new BufferedInputStream(dest.getInputStream());
|
||||
OutputStream out2 = new BufferedOutputStream(dest.getOutputStream());
|
||||
|
||||
Tunnel tunnel = new Tunnel(in2, out);
|
||||
tunnel.start();
|
||||
|
||||
int b = 0;
|
||||
do {
|
||||
try {
|
||||
b = in.read();
|
||||
if (b == -1) {
|
||||
in.close();
|
||||
out2.close();
|
||||
return;
|
||||
}
|
||||
out2.write(b);
|
||||
out2.flush();
|
||||
} catch (IOException ex) {
|
||||
}
|
||||
} while (!client.isClosed());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Negociate the authentication scheme with the client
|
||||
private void negociate() throws IOException {
|
||||
int ver = in.read();
|
||||
int n = in.read();
|
||||
byte[] buf = null;
|
||||
if (n > 0) {
|
||||
buf = new byte[n];
|
||||
readBuf(in, buf);
|
||||
}
|
||||
int scheme = NO_AUTH;
|
||||
for (int i = 0; i < n; i++)
|
||||
if (buf[i] == USER_PASSW)
|
||||
scheme = USER_PASSW;
|
||||
out.write(PROTO_VERS);
|
||||
out.write(scheme);
|
||||
out.flush();
|
||||
if (scheme == USER_PASSW)
|
||||
userPassAuth();
|
||||
}
|
||||
|
||||
// Send error message then close the streams
|
||||
private void sendError(int code) {
|
||||
try {
|
||||
out.write(PROTO_VERS);
|
||||
out.write(code);
|
||||
out.write(0);
|
||||
out.write(IPV4);
|
||||
for (int i=0; i<6; i++)
|
||||
out.write(0);
|
||||
out.flush();
|
||||
out.close();
|
||||
} catch (IOException ex) {
|
||||
}
|
||||
}
|
||||
|
||||
// Actually connect the proxy to the destination then initiate tunneling
|
||||
|
||||
private void doConnect(InetSocketAddress addr) throws IOException {
|
||||
dest = new Socket();
|
||||
try {
|
||||
dest.connect(addr, 10000);
|
||||
} catch (SocketTimeoutException ex) {
|
||||
sendError(HOST_UNREACHABLE);
|
||||
return;
|
||||
} catch (ConnectException cex) {
|
||||
sendError(CONN_REFUSED);
|
||||
return;
|
||||
}
|
||||
// Success
|
||||
InetAddress iadd = addr.getAddress();
|
||||
if (iadd instanceof Inet4Address) {
|
||||
out.write(PROTO_VERS);
|
||||
out.write(REQUEST_OK);
|
||||
out.write(0);
|
||||
out.write(IPV4);
|
||||
out.write(iadd.getAddress());
|
||||
} else if (iadd instanceof Inet6Address) {
|
||||
out.write(PROTO_VERS);
|
||||
out.write(REQUEST_OK);
|
||||
out.write(0);
|
||||
out.write(IPV6);
|
||||
out.write(iadd.getAddress());
|
||||
} else {
|
||||
sendError(GENERAL_FAILURE);
|
||||
return;
|
||||
}
|
||||
out.write((addr.getPort() >> 8) & 0xff);
|
||||
out.write((addr.getPort() >> 0) & 0xff);
|
||||
out.flush();
|
||||
|
||||
InputStream in2 = new BufferedInputStream(dest.getInputStream());
|
||||
OutputStream out2 = new BufferedOutputStream(dest.getOutputStream());
|
||||
|
||||
Tunnel tunnel = new Tunnel(in2, out);
|
||||
tunnel.start();
|
||||
|
||||
int b = 0;
|
||||
do {
|
||||
// Note that the socket might be closed from another thread (the tunnel)
|
||||
try {
|
||||
b = in.read();
|
||||
if (b == -1) {
|
||||
in.close();
|
||||
out2.close();
|
||||
return;
|
||||
}
|
||||
out2.write(b);
|
||||
out2.flush();
|
||||
} catch(IOException ioe) {
|
||||
}
|
||||
} while (!client.isClosed());
|
||||
}
|
||||
|
||||
private void doBind(InetSocketAddress addr) throws IOException {
|
||||
ServerSocket svr = new ServerSocket();
|
||||
svr.bind(null);
|
||||
InetSocketAddress bad = (InetSocketAddress) svr.getLocalSocketAddress();
|
||||
out.write(PROTO_VERS);
|
||||
out.write(REQUEST_OK);
|
||||
out.write(0);
|
||||
out.write(IPV4);
|
||||
out.write(bad.getAddress().getAddress());
|
||||
out.write((bad.getPort() >> 8) & 0xff);
|
||||
out.write((bad.getPort() & 0xff));
|
||||
out.flush();
|
||||
dest = svr.accept();
|
||||
bad = (InetSocketAddress) dest.getRemoteSocketAddress();
|
||||
out.write(PROTO_VERS);
|
||||
out.write(REQUEST_OK);
|
||||
out.write(0);
|
||||
out.write(IPV4);
|
||||
out.write(bad.getAddress().getAddress());
|
||||
out.write((bad.getPort() >> 8) & 0xff);
|
||||
out.write((bad.getPort() & 0xff));
|
||||
out.flush();
|
||||
InputStream in2 = dest.getInputStream();
|
||||
OutputStream out2 = dest.getOutputStream();
|
||||
|
||||
Tunnel tunnel = new Tunnel(in2, out);
|
||||
tunnel.start();
|
||||
|
||||
int b = 0;
|
||||
do {
|
||||
// Note that the socket might be close from another thread (the tunnel)
|
||||
try {
|
||||
b = in.read();
|
||||
if (b == -1) {
|
||||
in.close();
|
||||
out2.close();
|
||||
return;
|
||||
}
|
||||
out2.write(b);
|
||||
out2.flush();
|
||||
} catch(IOException ioe) {
|
||||
}
|
||||
} while (!client.isClosed());
|
||||
|
||||
}
|
||||
|
||||
// Handle the SOCKS v5 requests
|
||||
|
||||
private void getRequest() throws IOException {
|
||||
int ver = in.read();
|
||||
int cmd = in.read();
|
||||
if (ver == -1 || cmd == -1) {
|
||||
in.close();
|
||||
out.close();
|
||||
return;
|
||||
}
|
||||
int rsv = in.read();
|
||||
int atyp = in.read();
|
||||
String addr = null;
|
||||
int port = 0;
|
||||
|
||||
switch(atyp) {
|
||||
case IPV4:
|
||||
{
|
||||
byte[] buf = new byte[4];
|
||||
readBuf(in, buf);
|
||||
addr = InetAddress.getByAddress(buf).getHostAddress();
|
||||
}
|
||||
break;
|
||||
case DOMAIN_NAME:
|
||||
{
|
||||
int i = in.read();
|
||||
byte[] buf = new byte[i];
|
||||
readBuf(in, buf);
|
||||
addr = new String(buf);
|
||||
}
|
||||
break;
|
||||
case IPV6:
|
||||
{
|
||||
byte[] buf = new byte[16];
|
||||
readBuf(in, buf);
|
||||
addr = InetAddress.getByAddress(buf).getHostAddress();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
port = ((in.read()&0xff) << 8);
|
||||
port += (in.read()&0xff);
|
||||
|
||||
InetSocketAddress socAddr = new InetSocketAddress(addr, port);
|
||||
switch(cmd) {
|
||||
case CONNECT:
|
||||
doConnect(socAddr);
|
||||
break;
|
||||
case BIND:
|
||||
doBind(socAddr);
|
||||
break;
|
||||
case UDP_ASSOC:
|
||||
// doUDP(socAddr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void run() {
|
||||
String line = null;
|
||||
try {
|
||||
if (useV4) {
|
||||
getRequestV4();
|
||||
} else {
|
||||
negociate();
|
||||
getRequest();
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
try {
|
||||
sendError(GENERAL_FAILURE);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
} finally {
|
||||
try {
|
||||
client.close();
|
||||
} catch (IOException e2) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public SocksServer(int port, boolean v4) throws IOException {
|
||||
this(port);
|
||||
this.useV4 = v4;
|
||||
}
|
||||
|
||||
public SocksServer(int port) throws IOException {
|
||||
this.port = port;
|
||||
server = new ServerSocket();
|
||||
if (port == 0) {
|
||||
server.bind(null);
|
||||
this.port = server.getLocalPort();
|
||||
} else {
|
||||
server.bind(new InetSocketAddress(port));
|
||||
}
|
||||
}
|
||||
|
||||
public SocksServer(InetAddress addr, int port, boolean useV4) throws IOException {
|
||||
this.port = port;
|
||||
this.useV4 = useV4;
|
||||
server = new ServerSocket();
|
||||
if (port == 0 && addr == null) {
|
||||
server.bind(null);
|
||||
this.port = server.getLocalPort();
|
||||
} else if (port == 0 && addr != null) {
|
||||
server.bind(new InetSocketAddress(addr, 0));
|
||||
this.port = server.getLocalPort();
|
||||
} else if (addr == null) {
|
||||
assert port != 0;
|
||||
server.bind(new InetSocketAddress(port));
|
||||
} else {
|
||||
assert port != 0;
|
||||
server.bind(new InetSocketAddress(addr, port));
|
||||
}
|
||||
}
|
||||
|
||||
public SocksServer() throws IOException {
|
||||
this (DEFAULT_PORT);
|
||||
}
|
||||
|
||||
public void addUser(String user, String passwd) {
|
||||
users.put(user, passwd);
|
||||
}
|
||||
|
||||
public int getPort() {
|
||||
return port;
|
||||
}
|
||||
|
||||
public void close() {
|
||||
done = true;
|
||||
try { server.close(); } catch (IOException unused) {}
|
||||
}
|
||||
|
||||
public void run() {
|
||||
ClientHandler cl = null;
|
||||
while (!done) {
|
||||
try {
|
||||
Socket s = server.accept();
|
||||
cl = new ClientHandler(s);
|
||||
cl.start();
|
||||
} catch (IOException ex) {
|
||||
if (cl != null)
|
||||
cl.interrupt();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
111
test/jdk/java/net/Socks/SocksSocketImplTest.java
Normal file
111
test/jdk/java/net/Socks/SocksSocketImplTest.java
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
* Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import org.testng.Assert;
|
||||
import org.testng.annotations.AfterTest;
|
||||
import org.testng.annotations.BeforeTest;
|
||||
import org.testng.annotations.Test;
|
||||
import sun.net.spi.DefaultProxySelector;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.Proxy;
|
||||
import java.net.ProxySelector;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8230310
|
||||
* @summary Tests java.net.SocksSocketImpl
|
||||
* @run testng SocksSocketImplTest
|
||||
* @modules java.base/sun.net.spi:+open
|
||||
*/
|
||||
public class SocksSocketImplTest {
|
||||
|
||||
private ProxySelector previousDefault;
|
||||
|
||||
@BeforeTest
|
||||
public void beforeTest() {
|
||||
previousDefault = ProxySelector.getDefault();
|
||||
ProxySelector.setDefault(new SchemeStrippedProxySelector());
|
||||
}
|
||||
|
||||
@AfterTest
|
||||
public void afterTest() {
|
||||
ProxySelector.setDefault(previousDefault);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a socket connection, which internally triggers proxy selection for the target
|
||||
* address. The test has been configured to use a {@link SchemeStrippedProxySelector ProxySelector}
|
||||
* which throws a {@link IllegalArgumentException}. This test then verifies that this IAE gets wrapped
|
||||
* by {@code java.net.SocksSocketImpl} into an {@link IOException} before being thrown
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void testIOEOnProxySelection() throws Exception {
|
||||
final int backlog = -1;
|
||||
final int port = 0;
|
||||
try (ServerSocket ss = new ServerSocket(port, backlog, InetAddress.getLoopbackAddress());
|
||||
Socket s1 = new Socket(ss.getInetAddress(), ss.getLocalPort());
|
||||
Socket s2 = ss.accept()) {
|
||||
Assert.fail("IOException was expected to be thrown, but wasn't");
|
||||
} catch (IOException ioe) {
|
||||
// expected
|
||||
// now verify the IOE was thrown for the correct expected reason
|
||||
if (!(ioe.getCause() instanceof IllegalArgumentException)) {
|
||||
// rethrow this so that the test output failure will capture the entire/real
|
||||
// cause in its stacktrace
|
||||
throw ioe;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@link ProxySelector} which strips the "scheme" part of the {@link URI}
|
||||
* before delegating the selection to the {@link DefaultProxySelector}.
|
||||
* This is to ensure that the {@code DefaultProxySelector} throws an {@link IllegalArgumentException}
|
||||
* during selection of the proxy
|
||||
*/
|
||||
private static final class SchemeStrippedProxySelector extends DefaultProxySelector {
|
||||
|
||||
@Override
|
||||
public List<Proxy> select(final URI uri) {
|
||||
System.out.println("Proxy selection for " + uri);
|
||||
final URI schemeStrippedURI;
|
||||
try {
|
||||
// strip the scheme and pass the rest
|
||||
schemeStrippedURI = new URI(null, uri.getHost(), uri.getPath(), null);
|
||||
} catch (URISyntaxException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
System.out.println("Scheme stripped URI " + schemeStrippedURI + " is being used to select a proxy");
|
||||
return super.select(schemeStrippedURI);
|
||||
}
|
||||
}
|
||||
}
|
||||
201
test/jdk/java/net/Socks/SocksSocketProxySelectorTest.java
Normal file
201
test/jdk/java/net/Socks/SocksSocketProxySelectorTest.java
Normal file
|
|
@ -0,0 +1,201 @@
|
|||
/*
|
||||
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import org.junit.jupiter.api.Assumptions;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.Inet6Address;
|
||||
import java.net.InetAddress;
|
||||
import java.net.NetworkInterface;
|
||||
import java.net.Proxy;
|
||||
import java.net.ProxySelector;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.SocketException;
|
||||
import java.net.URI;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8318130
|
||||
* @summary Tests that java.net.SocksSocketImpl produces correct arguments
|
||||
* for proxy selector
|
||||
* @run junit/othervm SocksSocketProxySelectorTest
|
||||
*/
|
||||
public class SocksSocketProxySelectorTest {
|
||||
|
||||
public static final String SHORTEN_IPV6 = "((?<=\\[)0)?:(0:)+";
|
||||
|
||||
@BeforeAll
|
||||
public static void beforeTest() {
|
||||
ProxySelector.setDefault(new LoggingProxySelector());
|
||||
}
|
||||
|
||||
// should match the host name
|
||||
public static Stream<String> ipLiterals() {
|
||||
return Stream.of("127.0.0.1",
|
||||
"[::1]",
|
||||
"[fe80::1%1234567890]");
|
||||
}
|
||||
|
||||
// should be wrapped in [ ]
|
||||
public static Stream<String> shortIpv6Literals() {
|
||||
return Stream.of("::1",
|
||||
"fe80::1%1234567890");
|
||||
}
|
||||
|
||||
// with real interface names in scope
|
||||
// should be wrapped in [ ], repeated 0's not trimmed
|
||||
public static Stream<String> linkLocalIpv6Literals() throws SocketException {
|
||||
return NetworkInterface.networkInterfaces()
|
||||
.flatMap(NetworkInterface::inetAddresses)
|
||||
.filter(InetAddress::isLinkLocalAddress)
|
||||
.filter(Inet6Address.class::isInstance)
|
||||
.map(InetAddress::getHostAddress);
|
||||
}
|
||||
|
||||
public static Stream<InetAddress> hostNames() throws UnknownHostException {
|
||||
return Stream.of(
|
||||
InetAddress.getByAddress("localhost", new byte[] {127,0,0,1}),
|
||||
InetAddress.getByAddress("bugs.openjdk.org", new byte[] {127,0,0,1}),
|
||||
InetAddress.getByAddress("xn--kda4b0koi.com", new byte[] {127,0,0,1})
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a socket connection, which internally triggers proxy selection for the target
|
||||
* address. The test has been configured to use a {@link LoggingProxySelector ProxySelector}
|
||||
* which throws an {@link IllegalArgumentException} with hostname in exception message.
|
||||
* The test then verifies that the hostname matches the expected one.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@ParameterizedTest
|
||||
@MethodSource("ipLiterals")
|
||||
public void testIpLiterals(String host) throws Exception {
|
||||
try (Socket s1 = new Socket(host, 80)) {
|
||||
fail("IOException was expected to be thrown, but wasn't");
|
||||
} catch (IOException ioe) {
|
||||
// expected
|
||||
// now verify the IOE was thrown for the correct expected reason
|
||||
if (!(ioe.getCause() instanceof IllegalArgumentException iae)) {
|
||||
// rethrow this so that the test output failure will capture the entire/real
|
||||
// cause in its stacktrace
|
||||
throw ioe;
|
||||
}
|
||||
assertNotNull(iae.getMessage(), "Host not found");
|
||||
assertEquals(host,
|
||||
iae.getMessage().replaceFirst(SHORTEN_IPV6, "::"),
|
||||
"Found unexpected host");
|
||||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("shortIpv6Literals")
|
||||
public void testShortIpv6Literals(String host) throws Exception {
|
||||
try (Socket s1 = new Socket(host, 80)) {
|
||||
fail("IOException was expected to be thrown, but wasn't");
|
||||
} catch (IOException ioe) {
|
||||
// expected
|
||||
// now verify the IOE was thrown for the correct expected reason
|
||||
if (!(ioe.getCause() instanceof IllegalArgumentException iae)) {
|
||||
// rethrow this so that the test output failure will capture the entire/real
|
||||
// cause in its stacktrace
|
||||
throw ioe;
|
||||
}
|
||||
assertNotNull(iae.getMessage(), "Host not found");
|
||||
assertEquals('[' + host + ']',
|
||||
iae.getMessage().replaceFirst(SHORTEN_IPV6, "::"),
|
||||
"Found unexpected host");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLinkLocalIpv6Literals() throws Exception {
|
||||
String host = linkLocalIpv6Literals()
|
||||
.findFirst()
|
||||
.orElseGet(() -> Assumptions.abort("No IPv6 link-local addresses found"));
|
||||
System.err.println(host);
|
||||
try (Socket s1 = new Socket(host, 80)) {
|
||||
fail("IOException was expected to be thrown, but wasn't");
|
||||
} catch (IOException ioe) {
|
||||
// expected
|
||||
// now verify the IOE was thrown for the correct expected reason
|
||||
if (!(ioe.getCause() instanceof IllegalArgumentException iae)) {
|
||||
// rethrow this so that the test output failure will capture the entire/real
|
||||
// cause in its stacktrace
|
||||
throw ioe;
|
||||
}
|
||||
assertNotNull(iae.getMessage(), "Host not found");
|
||||
assertEquals('[' + host + ']',
|
||||
iae.getMessage(),
|
||||
"Found unexpected host");
|
||||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("hostNames")
|
||||
public void testHostNames(InetAddress host) throws Exception {
|
||||
try (Socket s1 = new Socket(host, 80)) {
|
||||
fail("IOException was expected to be thrown, but wasn't");
|
||||
} catch (IOException ioe) {
|
||||
// expected
|
||||
// now verify the IOE was thrown for the correct expected reason
|
||||
if (!(ioe.getCause() instanceof IllegalArgumentException iae)) {
|
||||
// rethrow this so that the test output failure will capture the entire/real
|
||||
// cause in its stacktrace
|
||||
throw ioe;
|
||||
}
|
||||
assertNotNull(iae.getMessage(), "Host not found");
|
||||
assertEquals(host.getHostName(),
|
||||
iae.getMessage(),
|
||||
"Found unexpected host");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@link ProxySelector} which throws an IllegalArgumentException
|
||||
* with the given hostname in exception message
|
||||
*/
|
||||
private static final class LoggingProxySelector extends
|
||||
ProxySelector {
|
||||
|
||||
@Override
|
||||
public List<Proxy> select(final URI uri) {
|
||||
throw new IllegalArgumentException(uri.getHost());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connectFailed(URI uri, SocketAddress sa, IOException ioe) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
125
test/jdk/java/net/Socks/SocksV4Test.java
Normal file
125
test/jdk/java/net/Socks/SocksV4Test.java
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
/*
|
||||
* Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 4727547
|
||||
* @summary SocksSocketImpl throws NullPointerException
|
||||
* @build SocksServer
|
||||
* @run main/othervm SocksV4Test
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.Authenticator;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.PasswordAuthentication;
|
||||
import java.net.Proxy;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
public class SocksV4Test {
|
||||
|
||||
// An unresolvable host
|
||||
static final String HOSTNAME = "doesnot.exist.invalid";
|
||||
static final String USER = "johndoe";
|
||||
static final String PASSWORD = "helloworld";
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
Authenticator.setDefault(new Auth());
|
||||
UHETest();
|
||||
getLocalPortTest();
|
||||
}
|
||||
|
||||
static class Auth extends Authenticator {
|
||||
protected PasswordAuthentication getPasswordAuthentication() {
|
||||
return new PasswordAuthentication(USER, PASSWORD.toCharArray());
|
||||
}
|
||||
}
|
||||
|
||||
public static void getLocalPortTest() throws Exception {
|
||||
// We actually use V5 for this test because that is the default
|
||||
// protocol version used by the client and it doesn't really handle
|
||||
// down grading very well.
|
||||
InetAddress lba = InetAddress.getLoopbackAddress();
|
||||
try (SocksServer srvr = new SocksServer(lba, 0, false);
|
||||
ServerSocket ss = new ServerSocket(0, 0, lba)) {
|
||||
|
||||
srvr.addUser(USER, PASSWORD);
|
||||
int serverPort = ss.getLocalPort();
|
||||
srvr.start();
|
||||
int proxyPort = srvr.getPort();
|
||||
System.out.printf("Server port %d, Proxy port %d\n", serverPort, proxyPort);
|
||||
Proxy sp = new Proxy(Proxy.Type.SOCKS,
|
||||
new InetSocketAddress(lba, proxyPort));
|
||||
// Let's create an unresolved address
|
||||
InetSocketAddress ad = new InetSocketAddress(lba.getHostAddress(), serverPort);
|
||||
try (Socket s = new Socket(sp)) {
|
||||
s.connect(ad, 10000);
|
||||
int pp = s.getLocalPort();
|
||||
System.out.println("Local port = " + pp);
|
||||
if (pp == serverPort || pp == proxyPort)
|
||||
throw new RuntimeException("wrong port returned");
|
||||
} catch (UnknownHostException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
} catch (IOException ioe) {
|
||||
throw new RuntimeException(ioe);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void UHETest() throws Exception {
|
||||
// sanity before running the test
|
||||
assertUnresolvableHost(HOSTNAME);
|
||||
|
||||
InetAddress lba = InetAddress.getLoopbackAddress();
|
||||
// Create a SOCKS V4 proxy
|
||||
try (SocksServer srvr = new SocksServer(lba, 0, true)) {
|
||||
srvr.start();
|
||||
Proxy sp = new Proxy(Proxy.Type.SOCKS,
|
||||
new InetSocketAddress(lba, srvr.getPort()));
|
||||
// Let's create an unresolved address
|
||||
InetSocketAddress ad = new InetSocketAddress(HOSTNAME, 1234);
|
||||
try (Socket s = new Socket(sp)) {
|
||||
s.connect(ad, 10000);
|
||||
} catch (UnknownHostException ex) {
|
||||
// OK, that's what we expected
|
||||
} catch (NullPointerException npe) {
|
||||
// Not OK, this used to be the bug
|
||||
throw new RuntimeException("Got a NUllPointerException");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void assertUnresolvableHost(String host) {
|
||||
InetAddress addr = null;
|
||||
try {
|
||||
addr = InetAddress.getByName(host);
|
||||
} catch (UnknownHostException x) {
|
||||
// OK, expected
|
||||
}
|
||||
if (addr != null)
|
||||
throw new RuntimeException("Test cannot run. resolvable address:" + addr);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue