mirror of
https://github.com/openjdk/jdk.git
synced 2026-03-13 09:23:20 +00:00
8216986: Remove unused code from SocksSocketImpl
Reviewed-by: alanb
This commit is contained in:
parent
288ebae13c
commit
0fc677a674
@ -197,14 +197,4 @@ import java.util.Set;
|
||||
else
|
||||
return super.getPort();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getLocalPort() {
|
||||
if (socket != null)
|
||||
return super.getLocalPort();
|
||||
if (external_address != null)
|
||||
return external_address.getPort();
|
||||
else
|
||||
return super.getLocalPort();
|
||||
}
|
||||
}
|
||||
|
||||
@ -28,14 +28,11 @@ import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.security.PrivilegedExceptionAction;
|
||||
|
||||
import jdk.internal.util.StaticProperty;
|
||||
import sun.net.SocksProxy;
|
||||
import sun.net.spi.DefaultProxySelector;
|
||||
import sun.net.www.ParseUtil;
|
||||
/* import org.ietf.jgss.*; */
|
||||
|
||||
/**
|
||||
* SOCKS (V4 & V5) TCP socket implementation (RFC 1928).
|
||||
@ -51,19 +48,11 @@ class SocksSocketImpl extends PlainSocketImpl implements SocksConsts {
|
||||
private Socket cmdsock = null;
|
||||
private InputStream cmdIn = null;
|
||||
private OutputStream cmdOut = null;
|
||||
/* true if the Proxy has been set programmatically */
|
||||
private boolean applicationSetProxy; /* false */
|
||||
|
||||
|
||||
SocksSocketImpl() {
|
||||
// Nothing needed
|
||||
}
|
||||
|
||||
SocksSocketImpl(String server, int port) {
|
||||
this.server = server;
|
||||
this.serverPort = (port == -1 ? DEFAULT_PORT : port);
|
||||
}
|
||||
|
||||
SocksSocketImpl(Proxy proxy) {
|
||||
SocketAddress a = proxy.address();
|
||||
if (a instanceof InetSocketAddress) {
|
||||
@ -75,10 +64,6 @@ class SocksSocketImpl extends PlainSocketImpl implements SocksConsts {
|
||||
useV4 = useV4(proxy);
|
||||
}
|
||||
|
||||
void setV4() {
|
||||
useV4 = true;
|
||||
}
|
||||
|
||||
private static boolean useV4(Proxy proxy) {
|
||||
if (proxy instanceof SocksProxy
|
||||
&& ((SocksProxy)proxy).protocolVersion() == 4) {
|
||||
@ -123,10 +108,6 @@ class SocksSocketImpl extends PlainSocketImpl implements SocksConsts {
|
||||
throw new SocketTimeoutException();
|
||||
}
|
||||
|
||||
private int readSocksReply(InputStream in, byte[] data) throws IOException {
|
||||
return readSocksReply(in, data, 0L);
|
||||
}
|
||||
|
||||
private int readSocksReply(InputStream in, byte[] data, long deadlineMillis) throws IOException {
|
||||
int len = data.length;
|
||||
int received = 0;
|
||||
@ -144,14 +125,6 @@ class SocksSocketImpl extends PlainSocketImpl implements SocksConsts {
|
||||
return received;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the authentication mechanism required by the proxy.
|
||||
*/
|
||||
private boolean authenticate(byte method, InputStream in,
|
||||
BufferedOutputStream out) throws IOException {
|
||||
return authenticate(method, in, out, 0L);
|
||||
}
|
||||
|
||||
private boolean authenticate(byte method, InputStream in,
|
||||
BufferedOutputStream out,
|
||||
long deadlineMillis) throws IOException {
|
||||
@ -212,60 +185,6 @@ class SocksSocketImpl extends PlainSocketImpl implements SocksConsts {
|
||||
/* Authentication succeeded */
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* GSSAPI authentication mechanism.
|
||||
* Unfortunately the RFC seems out of sync with the Reference
|
||||
* implementation. I'll leave this in for future completion.
|
||||
*/
|
||||
// if (method == GSSAPI) {
|
||||
// try {
|
||||
// GSSManager manager = GSSManager.getInstance();
|
||||
// GSSName name = manager.createName("SERVICE:socks@"+server,
|
||||
// null);
|
||||
// GSSContext context = manager.createContext(name, null, null,
|
||||
// GSSContext.DEFAULT_LIFETIME);
|
||||
// context.requestMutualAuth(true);
|
||||
// context.requestReplayDet(true);
|
||||
// context.requestSequenceDet(true);
|
||||
// context.requestCredDeleg(true);
|
||||
// byte []inToken = new byte[0];
|
||||
// while (!context.isEstablished()) {
|
||||
// byte[] outToken
|
||||
// = context.initSecContext(inToken, 0, inToken.length);
|
||||
// // send the output token if generated
|
||||
// if (outToken != null) {
|
||||
// out.write(1);
|
||||
// out.write(1);
|
||||
// out.writeShort(outToken.length);
|
||||
// out.write(outToken);
|
||||
// out.flush();
|
||||
// data = new byte[2];
|
||||
// i = readSocksReply(in, data, deadlineMillis);
|
||||
// if (i != 2 || data[1] == 0xff) {
|
||||
// in.close();
|
||||
// out.close();
|
||||
// return false;
|
||||
// }
|
||||
// i = readSocksReply(in, data, deadlineMillis);
|
||||
// int len = 0;
|
||||
// len = ((int)data[0] & 0xff) << 8;
|
||||
// len += data[1];
|
||||
// data = new byte[len];
|
||||
// i = readSocksReply(in, data, deadlineMillis);
|
||||
// if (i == len)
|
||||
// return true;
|
||||
// in.close();
|
||||
// out.close();
|
||||
// }
|
||||
// }
|
||||
// } catch (GSSException e) {
|
||||
// /* RFC 1961 states that if Context initialisation fails the connection
|
||||
// MUST be closed */
|
||||
// e.printStackTrace();
|
||||
// in.close();
|
||||
// out.close();
|
||||
// }
|
||||
// }
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -590,450 +509,6 @@ class SocksSocketImpl extends PlainSocketImpl implements SocksConsts {
|
||||
external_address = epoint;
|
||||
}
|
||||
|
||||
private void bindV4(InputStream in, OutputStream out,
|
||||
InetAddress baddr,
|
||||
int lport) throws IOException {
|
||||
if (!(baddr instanceof Inet4Address)) {
|
||||
throw new SocketException("SOCKS V4 requires IPv4 only addresses");
|
||||
}
|
||||
super.bind(baddr, lport);
|
||||
byte[] addr1 = baddr.getAddress();
|
||||
/* Test for AnyLocal */
|
||||
InetAddress naddr = baddr;
|
||||
if (naddr.isAnyLocalAddress()) {
|
||||
naddr = AccessController.doPrivileged(
|
||||
new PrivilegedAction<>() {
|
||||
public InetAddress run() {
|
||||
return cmdsock.getLocalAddress();
|
||||
|
||||
}
|
||||
});
|
||||
addr1 = naddr.getAddress();
|
||||
}
|
||||
out.write(PROTO_VERS4);
|
||||
out.write(BIND);
|
||||
out.write((super.getLocalPort() >> 8) & 0xff);
|
||||
out.write((super.getLocalPort() >> 0) & 0xff);
|
||||
out.write(addr1);
|
||||
String userName = getUserName();
|
||||
try {
|
||||
out.write(userName.getBytes("ISO-8859-1"));
|
||||
} catch (java.io.UnsupportedEncodingException uee) {
|
||||
assert false;
|
||||
}
|
||||
out.write(0);
|
||||
out.flush();
|
||||
byte[] data = new byte[8];
|
||||
int n = readSocksReply(in, data);
|
||||
if (n != 8)
|
||||
throw new SocketException("Reply from SOCKS server has bad length: " + n);
|
||||
if (data[0] != 0 && data[0] != 4)
|
||||
throw new SocketException("Reply from SOCKS server has bad version");
|
||||
SocketException ex = null;
|
||||
switch (data[1]) {
|
||||
case 90:
|
||||
// Success!
|
||||
external_address = new InetSocketAddress(baddr, lport);
|
||||
break;
|
||||
case 91:
|
||||
ex = new SocketException("SOCKS request rejected");
|
||||
break;
|
||||
case 92:
|
||||
ex = new SocketException("SOCKS server couldn't reach destination");
|
||||
break;
|
||||
case 93:
|
||||
ex = new SocketException("SOCKS authentication failed");
|
||||
break;
|
||||
default:
|
||||
ex = new SocketException("Reply from SOCKS server contains bad status");
|
||||
break;
|
||||
}
|
||||
if (ex != null) {
|
||||
in.close();
|
||||
out.close();
|
||||
throw ex;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the Bind request to the SOCKS proxy. In the SOCKS protocol, bind
|
||||
* means "accept incoming connection from", so the SocketAddress is
|
||||
* the one of the host we do accept connection from.
|
||||
*
|
||||
* @param saddr the Socket address of the remote host.
|
||||
* @exception IOException if an I/O error occurs when binding this socket.
|
||||
*/
|
||||
protected synchronized void socksBind(InetSocketAddress saddr) throws IOException {
|
||||
if (socket != null) {
|
||||
// this is a client socket, not a server socket, don't
|
||||
// call the SOCKS proxy for a bind!
|
||||
return;
|
||||
}
|
||||
|
||||
// Connects to the SOCKS server
|
||||
|
||||
if (server == null) {
|
||||
// This is the general case
|
||||
// server is not null only when the socket was created with a
|
||||
// specified proxy in which case it does bypass the ProxySelector
|
||||
ProxySelector sel = java.security.AccessController.doPrivileged(
|
||||
new java.security.PrivilegedAction<>() {
|
||||
public ProxySelector run() {
|
||||
return ProxySelector.getDefault();
|
||||
}
|
||||
});
|
||||
if (sel == null) {
|
||||
/*
|
||||
* No default proxySelector --> direct connection
|
||||
*/
|
||||
return;
|
||||
}
|
||||
URI uri;
|
||||
// Use getHostString() to avoid reverse lookups
|
||||
String host = saddr.getHostString();
|
||||
// IPv6 literal?
|
||||
if (saddr.getAddress() instanceof Inet6Address &&
|
||||
(!host.startsWith("[")) && (host.indexOf(':') >= 0)) {
|
||||
host = "[" + host + "]";
|
||||
}
|
||||
try {
|
||||
uri = new URI("serversocket://" + ParseUtil.encodePath(host) + ":"+ saddr.getPort());
|
||||
} catch (URISyntaxException e) {
|
||||
// This shouldn't happen
|
||||
assert false : e;
|
||||
uri = null;
|
||||
}
|
||||
Proxy p = null;
|
||||
Exception savedExc = null;
|
||||
java.util.Iterator<Proxy> iProxy = null;
|
||||
iProxy = sel.select(uri).iterator();
|
||||
if (iProxy == null || !(iProxy.hasNext())) {
|
||||
return;
|
||||
}
|
||||
while (iProxy.hasNext()) {
|
||||
p = iProxy.next();
|
||||
if (p == null || p.type() != Proxy.Type.SOCKS) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(p.address() instanceof InetSocketAddress))
|
||||
throw new SocketException("Unknown address type for proxy: " + p);
|
||||
// Use getHostString() to avoid reverse lookups
|
||||
server = ((InetSocketAddress) p.address()).getHostString();
|
||||
serverPort = ((InetSocketAddress) p.address()).getPort();
|
||||
useV4 = useV4(p);
|
||||
|
||||
// Connects to the SOCKS server
|
||||
try {
|
||||
AccessController.doPrivileged(
|
||||
new PrivilegedExceptionAction<>() {
|
||||
public Void run() throws Exception {
|
||||
cmdsock = new Socket(new PlainSocketImpl());
|
||||
cmdsock.connect(new InetSocketAddress(server, serverPort));
|
||||
cmdIn = cmdsock.getInputStream();
|
||||
cmdOut = cmdsock.getOutputStream();
|
||||
return null;
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
// Ooops, let's notify the ProxySelector
|
||||
sel.connectFailed(uri,p.address(),new SocketException(e.getMessage()));
|
||||
server = null;
|
||||
serverPort = -1;
|
||||
cmdsock = null;
|
||||
savedExc = e;
|
||||
// Will continue the while loop and try the next proxy
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If server is still null at this point, none of the proxy
|
||||
* worked
|
||||
*/
|
||||
if (server == null || cmdsock == null) {
|
||||
throw new SocketException("Can't connect to SOCKS proxy:"
|
||||
+ savedExc.getMessage());
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
AccessController.doPrivileged(
|
||||
new PrivilegedExceptionAction<>() {
|
||||
public Void run() throws Exception {
|
||||
cmdsock = new Socket(new PlainSocketImpl());
|
||||
cmdsock.connect(new InetSocketAddress(server, serverPort));
|
||||
cmdIn = cmdsock.getInputStream();
|
||||
cmdOut = cmdsock.getOutputStream();
|
||||
return null;
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
throw new SocketException(e.getMessage());
|
||||
}
|
||||
}
|
||||
BufferedOutputStream out = new BufferedOutputStream(cmdOut, 512);
|
||||
InputStream in = cmdIn;
|
||||
if (useV4) {
|
||||
bindV4(in, out, saddr.getAddress(), saddr.getPort());
|
||||
return;
|
||||
}
|
||||
out.write(PROTO_VERS);
|
||||
out.write(2);
|
||||
out.write(NO_AUTH);
|
||||
out.write(USER_PASSW);
|
||||
out.flush();
|
||||
byte[] data = new byte[2];
|
||||
int i = readSocksReply(in, data);
|
||||
if (i != 2 || ((int)data[0]) != PROTO_VERS) {
|
||||
// Maybe it's not a V5 sever after all
|
||||
// Let's try V4 before we give up
|
||||
bindV4(in, out, saddr.getAddress(), saddr.getPort());
|
||||
return;
|
||||
}
|
||||
if (((int)data[1]) == NO_METHODS)
|
||||
throw new SocketException("SOCKS : No acceptable methods");
|
||||
if (!authenticate(data[1], in, out)) {
|
||||
throw new SocketException("SOCKS : authentication failed");
|
||||
}
|
||||
// We're OK. Let's issue the BIND command.
|
||||
out.write(PROTO_VERS);
|
||||
out.write(BIND);
|
||||
out.write(0);
|
||||
int lport = saddr.getPort();
|
||||
if (saddr.isUnresolved()) {
|
||||
out.write(DOMAIN_NAME);
|
||||
out.write(saddr.getHostName().length());
|
||||
try {
|
||||
out.write(saddr.getHostName().getBytes("ISO-8859-1"));
|
||||
} catch (java.io.UnsupportedEncodingException uee) {
|
||||
assert false;
|
||||
}
|
||||
out.write((lport >> 8) & 0xff);
|
||||
out.write((lport >> 0) & 0xff);
|
||||
} else if (saddr.getAddress() instanceof Inet4Address) {
|
||||
byte[] addr1 = saddr.getAddress().getAddress();
|
||||
out.write(IPV4);
|
||||
out.write(addr1);
|
||||
out.write((lport >> 8) & 0xff);
|
||||
out.write((lport >> 0) & 0xff);
|
||||
out.flush();
|
||||
} else if (saddr.getAddress() instanceof Inet6Address) {
|
||||
byte[] addr1 = saddr.getAddress().getAddress();
|
||||
out.write(IPV6);
|
||||
out.write(addr1);
|
||||
out.write((lport >> 8) & 0xff);
|
||||
out.write((lport >> 0) & 0xff);
|
||||
out.flush();
|
||||
} else {
|
||||
cmdsock.close();
|
||||
throw new SocketException("unsupported address type : " + saddr);
|
||||
}
|
||||
data = new byte[4];
|
||||
i = readSocksReply(in, data);
|
||||
SocketException ex = null;
|
||||
int len, nport;
|
||||
byte[] addr;
|
||||
switch (data[1]) {
|
||||
case REQUEST_OK:
|
||||
// success!
|
||||
switch(data[3]) {
|
||||
case IPV4:
|
||||
addr = new byte[4];
|
||||
i = readSocksReply(in, addr);
|
||||
if (i != 4)
|
||||
throw new SocketException("Reply from SOCKS server badly formatted");
|
||||
data = new byte[2];
|
||||
i = readSocksReply(in, data);
|
||||
if (i != 2)
|
||||
throw new SocketException("Reply from SOCKS server badly formatted");
|
||||
nport = ((int)data[0] & 0xff) << 8;
|
||||
nport += ((int)data[1] & 0xff);
|
||||
external_address =
|
||||
new InetSocketAddress(new Inet4Address("", addr) , nport);
|
||||
break;
|
||||
case DOMAIN_NAME:
|
||||
len = data[1];
|
||||
byte[] host = new byte[len];
|
||||
i = readSocksReply(in, host);
|
||||
if (i != len)
|
||||
throw new SocketException("Reply from SOCKS server badly formatted");
|
||||
data = new byte[2];
|
||||
i = readSocksReply(in, data);
|
||||
if (i != 2)
|
||||
throw new SocketException("Reply from SOCKS server badly formatted");
|
||||
nport = ((int)data[0] & 0xff) << 8;
|
||||
nport += ((int)data[1] & 0xff);
|
||||
external_address = new InetSocketAddress(new String(host), nport);
|
||||
break;
|
||||
case IPV6:
|
||||
len = data[1];
|
||||
addr = new byte[len];
|
||||
i = readSocksReply(in, addr);
|
||||
if (i != len)
|
||||
throw new SocketException("Reply from SOCKS server badly formatted");
|
||||
data = new byte[2];
|
||||
i = readSocksReply(in, data);
|
||||
if (i != 2)
|
||||
throw new SocketException("Reply from SOCKS server badly formatted");
|
||||
nport = ((int)data[0] & 0xff) << 8;
|
||||
nport += ((int)data[1] & 0xff);
|
||||
external_address =
|
||||
new InetSocketAddress(new Inet6Address("", addr), nport);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case GENERAL_FAILURE:
|
||||
ex = new SocketException("SOCKS server general failure");
|
||||
break;
|
||||
case NOT_ALLOWED:
|
||||
ex = new SocketException("SOCKS: Bind not allowed by ruleset");
|
||||
break;
|
||||
case NET_UNREACHABLE:
|
||||
ex = new SocketException("SOCKS: Network unreachable");
|
||||
break;
|
||||
case HOST_UNREACHABLE:
|
||||
ex = new SocketException("SOCKS: Host unreachable");
|
||||
break;
|
||||
case CONN_REFUSED:
|
||||
ex = new SocketException("SOCKS: Connection refused");
|
||||
break;
|
||||
case TTL_EXPIRED:
|
||||
ex = new SocketException("SOCKS: TTL expired");
|
||||
break;
|
||||
case CMD_NOT_SUPPORTED:
|
||||
ex = new SocketException("SOCKS: Command not supported");
|
||||
break;
|
||||
case ADDR_TYPE_NOT_SUP:
|
||||
ex = new SocketException("SOCKS: address type not supported");
|
||||
break;
|
||||
}
|
||||
if (ex != null) {
|
||||
in.close();
|
||||
out.close();
|
||||
cmdsock.close();
|
||||
cmdsock = null;
|
||||
throw ex;
|
||||
}
|
||||
cmdIn = in;
|
||||
cmdOut = out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Accepts a connection from a specific host.
|
||||
*
|
||||
* @param s the accepted connection.
|
||||
* @param saddr the socket address of the host we do accept
|
||||
* connection from
|
||||
* @exception IOException if an I/O error occurs when accepting the
|
||||
* connection.
|
||||
*/
|
||||
protected void acceptFrom(SocketImpl s, InetSocketAddress saddr) throws IOException {
|
||||
if (cmdsock == null) {
|
||||
// Not a Socks ServerSocket.
|
||||
return;
|
||||
}
|
||||
InputStream in = cmdIn;
|
||||
// Sends the "SOCKS BIND" request.
|
||||
socksBind(saddr);
|
||||
in.read();
|
||||
int i = in.read();
|
||||
in.read();
|
||||
SocketException ex = null;
|
||||
int nport;
|
||||
byte[] addr;
|
||||
InetSocketAddress real_end = null;
|
||||
switch (i) {
|
||||
case REQUEST_OK:
|
||||
// success!
|
||||
i = in.read();
|
||||
switch(i) {
|
||||
case IPV4:
|
||||
addr = new byte[4];
|
||||
readSocksReply(in, addr);
|
||||
nport = in.read() << 8;
|
||||
nport += in.read();
|
||||
real_end =
|
||||
new InetSocketAddress(new Inet4Address("", addr) , nport);
|
||||
break;
|
||||
case DOMAIN_NAME:
|
||||
int len = in.read();
|
||||
addr = new byte[len];
|
||||
readSocksReply(in, addr);
|
||||
nport = in.read() << 8;
|
||||
nport += in.read();
|
||||
real_end = new InetSocketAddress(new String(addr), nport);
|
||||
break;
|
||||
case IPV6:
|
||||
addr = new byte[16];
|
||||
readSocksReply(in, addr);
|
||||
nport = in.read() << 8;
|
||||
nport += in.read();
|
||||
real_end =
|
||||
new InetSocketAddress(new Inet6Address("", addr), nport);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case GENERAL_FAILURE:
|
||||
ex = new SocketException("SOCKS server general failure");
|
||||
break;
|
||||
case NOT_ALLOWED:
|
||||
ex = new SocketException("SOCKS: Accept not allowed by ruleset");
|
||||
break;
|
||||
case NET_UNREACHABLE:
|
||||
ex = new SocketException("SOCKS: Network unreachable");
|
||||
break;
|
||||
case HOST_UNREACHABLE:
|
||||
ex = new SocketException("SOCKS: Host unreachable");
|
||||
break;
|
||||
case CONN_REFUSED:
|
||||
ex = new SocketException("SOCKS: Connection refused");
|
||||
break;
|
||||
case TTL_EXPIRED:
|
||||
ex = new SocketException("SOCKS: TTL expired");
|
||||
break;
|
||||
case CMD_NOT_SUPPORTED:
|
||||
ex = new SocketException("SOCKS: Command not supported");
|
||||
break;
|
||||
case ADDR_TYPE_NOT_SUP:
|
||||
ex = new SocketException("SOCKS: address type not supported");
|
||||
break;
|
||||
}
|
||||
if (ex != null) {
|
||||
cmdIn.close();
|
||||
cmdOut.close();
|
||||
cmdsock.close();
|
||||
cmdsock = null;
|
||||
throw ex;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is where we have to do some fancy stuff.
|
||||
* The datastream from the socket "accepted" by the proxy will
|
||||
* come through the cmdSocket. So we have to swap the socketImpls
|
||||
*/
|
||||
if (s instanceof SocksSocketImpl) {
|
||||
((SocksSocketImpl)s).external_address = real_end;
|
||||
}
|
||||
if (s instanceof PlainSocketImpl) {
|
||||
PlainSocketImpl psi = (PlainSocketImpl) s;
|
||||
psi.setInputStream((SocketInputStream) in);
|
||||
psi.setFileDescriptor(cmdsock.getImpl().getFileDescriptor());
|
||||
psi.setAddress(cmdsock.getImpl().getInetAddress());
|
||||
psi.setPort(cmdsock.getImpl().getPort());
|
||||
psi.setLocalPort(cmdsock.getImpl().getLocalPort());
|
||||
} else {
|
||||
s.fd = cmdsock.getImpl().fd;
|
||||
s.address = cmdsock.getImpl().address;
|
||||
s.port = cmdsock.getImpl().port;
|
||||
s.localport = cmdsock.getImpl().localport;
|
||||
}
|
||||
|
||||
// Need to do that so that the socket won't be closed
|
||||
// when the ServerSocket is closed by the user.
|
||||
// It kinds of detaches the Socket because it is now
|
||||
// used elsewhere.
|
||||
cmdsock = null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@ -1064,16 +539,6 @@ class SocksSocketImpl extends PlainSocketImpl implements SocksConsts {
|
||||
return super.getPort();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getLocalPort() {
|
||||
if (socket != null)
|
||||
return super.getLocalPort();
|
||||
if (external_address != null)
|
||||
return external_address.getPort();
|
||||
else
|
||||
return super.getLocalPort();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void close() throws IOException {
|
||||
if (cmdsock != null)
|
||||
@ -1083,14 +548,6 @@ class SocksSocketImpl extends PlainSocketImpl implements SocksConsts {
|
||||
}
|
||||
|
||||
private String getUserName() {
|
||||
String userName = "";
|
||||
if (applicationSetProxy) {
|
||||
try {
|
||||
userName = System.getProperty("user.name");
|
||||
} catch (SecurityException se) { /* swallow Exception */ }
|
||||
} else {
|
||||
userName = StaticProperty.userName();
|
||||
}
|
||||
return userName;
|
||||
return StaticProperty.userName();
|
||||
}
|
||||
}
|
||||
|
||||
@ -24,7 +24,7 @@ import java.net.*;
|
||||
import java.io.*;
|
||||
import java.util.HashMap;
|
||||
|
||||
public class SocksServer extends Thread {
|
||||
public class SocksServer extends Thread implements Closeable {
|
||||
// Some useful SOCKS constant
|
||||
|
||||
static final int PROTO_VERS4 = 4;
|
||||
@ -503,7 +503,7 @@ public class SocksServer extends Thread {
|
||||
return port;
|
||||
}
|
||||
|
||||
public void terminate() {
|
||||
public void close() {
|
||||
done = true;
|
||||
try { server.close(); } catch (IOException unused) {}
|
||||
}
|
||||
|
||||
@ -26,36 +26,80 @@
|
||||
* @bug 4727547
|
||||
* @summary SocksSocketImpl throws NullPointerException
|
||||
* @build SocksServer
|
||||
* @run main SocksV4Test
|
||||
* @run main/othervm SocksV4Test
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.*;
|
||||
|
||||
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.
|
||||
try (SocksServer srvr = new SocksServer(0, false);
|
||||
ServerSocket ss = new ServerSocket(0)) {
|
||||
|
||||
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("localhost", proxyPort));
|
||||
// Let's create an unresolved address
|
||||
InetSocketAddress ad = new InetSocketAddress("127.0.0.1", 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);
|
||||
|
||||
// Create a SOCKS V4 proxy
|
||||
SocksServer srvr = new SocksServer(0, true);
|
||||
srvr.start();
|
||||
Proxy sp = new Proxy(Proxy.Type.SOCKS,
|
||||
new InetSocketAddress("localhost", 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");
|
||||
} finally {
|
||||
srvr.terminate();
|
||||
try (SocksServer srvr = new SocksServer(0, true)) {
|
||||
srvr.start();
|
||||
Proxy sp = new Proxy(Proxy.Type.SOCKS,
|
||||
new InetSocketAddress("localhost", 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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -38,33 +38,40 @@ import sun.net.www.*;
|
||||
|
||||
public class ProxyTunnelServer extends Thread {
|
||||
|
||||
private static ServerSocket ss = null;
|
||||
private final ServerSocket ss;
|
||||
/*
|
||||
* holds the registered user's username and password
|
||||
* only one such entry is maintained
|
||||
*/
|
||||
private String userPlusPass;
|
||||
private volatile String userPlusPass;
|
||||
|
||||
// client requesting for a tunnel
|
||||
private Socket clientSocket = null;
|
||||
private volatile Socket clientSocket = null;
|
||||
|
||||
/*
|
||||
* Origin server's address and port that the client
|
||||
* wants to establish the tunnel for communication.
|
||||
*/
|
||||
private InetAddress serverInetAddr;
|
||||
private int serverPort;
|
||||
private volatile InetAddress serverInetAddr;
|
||||
private volatile int serverPort;
|
||||
|
||||
/*
|
||||
* denote whether the proxy needs to authorize
|
||||
* CONNECT requests.
|
||||
*/
|
||||
static boolean needAuth = false;
|
||||
|
||||
volatile boolean needAuth = false;
|
||||
|
||||
public ProxyTunnelServer() throws IOException {
|
||||
if (ss == null) {
|
||||
ss = (ServerSocket) ServerSocketFactory.getDefault().
|
||||
createServerSocket(0);
|
||||
ss = new ServerSocket(0);
|
||||
}
|
||||
|
||||
static private void close(Closeable c) {
|
||||
try {
|
||||
if (c != null)
|
||||
c.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@ -72,6 +79,11 @@ public class ProxyTunnelServer extends Thread {
|
||||
needAuth = auth;
|
||||
}
|
||||
|
||||
public void terminate() {
|
||||
close(ss);
|
||||
close(clientSocket);
|
||||
}
|
||||
|
||||
/*
|
||||
* register users with the proxy, by providing username and
|
||||
* password. The username and password are used for authorizing the
|
||||
@ -81,10 +93,16 @@ public class ProxyTunnelServer extends Thread {
|
||||
userPlusPass = uname + ":" + passwd;
|
||||
}
|
||||
|
||||
volatile boolean makeTunnel;
|
||||
|
||||
public void doTunnel(boolean tunnel) {
|
||||
makeTunnel = tunnel;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
clientSocket = ss.accept();
|
||||
processRequests();
|
||||
processRequests(makeTunnel);
|
||||
} catch (Exception e) {
|
||||
System.out.println("Proxy Failed: " + e);
|
||||
e.printStackTrace();
|
||||
@ -105,7 +123,7 @@ public class ProxyTunnelServer extends Thread {
|
||||
* if there is a match, connection is set in tunneling mode. If
|
||||
* needAuth is set to false, Proxy-Authorization checks are not made
|
||||
*/
|
||||
private void processRequests() throws Exception {
|
||||
private void processRequests(boolean makeTunnel) throws Exception {
|
||||
|
||||
InputStream in = clientSocket.getInputStream();
|
||||
MessageHeader mheader = new MessageHeader(in);
|
||||
@ -125,6 +143,13 @@ public class ProxyTunnelServer extends Thread {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (makeTunnel) {
|
||||
retrieveConnectInfo(statusLine);
|
||||
doTunnel();
|
||||
return;
|
||||
}
|
||||
|
||||
respondForConnect(needAuth);
|
||||
|
||||
// connection set to the tunneling mode
|
||||
@ -178,6 +203,9 @@ public class ProxyTunnelServer extends Thread {
|
||||
* direction.
|
||||
*/
|
||||
private void doTunnel() throws Exception {
|
||||
OutputStream out = clientSocket.getOutputStream();
|
||||
out.write("HTTP/1.1 200 OK\r\n\r\n".getBytes());
|
||||
out.flush();
|
||||
|
||||
Socket serverSocket = new Socket(serverInetAddr, serverPort);
|
||||
ProxyTunnel clientToServer = new ProxyTunnel(
|
||||
@ -202,10 +230,10 @@ public class ProxyTunnelServer extends Thread {
|
||||
* socket, until both sockets are open and EOF has not been received.
|
||||
*/
|
||||
class ProxyTunnel extends Thread {
|
||||
Socket sockIn;
|
||||
Socket sockOut;
|
||||
InputStream input;
|
||||
OutputStream output;
|
||||
final Socket sockIn;
|
||||
final Socket sockOut;
|
||||
final InputStream input;
|
||||
final OutputStream output;
|
||||
|
||||
public ProxyTunnel(Socket sockIn, Socket sockOut)
|
||||
throws Exception {
|
||||
|
||||
@ -25,6 +25,7 @@
|
||||
* @test
|
||||
* @bug 4620362
|
||||
* @modules java.base/sun.net.www
|
||||
* @build ProxyTunnelServer
|
||||
* @run main/othervm TunnelThroughProxy
|
||||
* @summary JSSE not returning proper exception on unknown host
|
||||
*/
|
||||
@ -34,8 +35,13 @@ import java.io.*;
|
||||
|
||||
public class TunnelThroughProxy {
|
||||
public static void main(String[] args) throws Exception {
|
||||
nonexistingHostTest();
|
||||
getLocalPortTest();
|
||||
}
|
||||
|
||||
static void nonexistingHostTest() throws Exception {
|
||||
ProxyTunnelServer proxy = setupProxy(false);
|
||||
try {
|
||||
setupProxy();
|
||||
URL u = new URL("https://www.nonexistent-site.com/");
|
||||
URLConnection uc = u.openConnection();
|
||||
InputStream is = uc.getInputStream();
|
||||
@ -44,16 +50,48 @@ public class TunnelThroughProxy {
|
||||
if (!e.getMessage().matches(".*HTTP\\/.*500.*")) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
} finally {
|
||||
proxy.terminate();
|
||||
}
|
||||
}
|
||||
static void setupProxy() throws IOException {
|
||||
|
||||
|
||||
static void getLocalPortTest() throws Exception {
|
||||
ProxyTunnelServer proxy = setupProxy(true);
|
||||
try {
|
||||
int proxyPort = proxy.getPort();
|
||||
ServerSocket server = new ServerSocket(0);
|
||||
int serverPort = server.getLocalPort();
|
||||
|
||||
Socket sock;
|
||||
sock = new Socket(new Proxy(Proxy.Type.HTTP, new InetSocketAddress("127.0.0.1", proxyPort)));
|
||||
InetSocketAddress dest = new InetSocketAddress("127.0.0.1", serverPort);
|
||||
sock.connect(dest);
|
||||
int localPort = sock.getLocalPort();
|
||||
if (localPort == proxyPort)
|
||||
throw new RuntimeException("Fail: socket has wrong local port");
|
||||
// check that tunnel really works
|
||||
Socket sock1 = server.accept();
|
||||
OutputStream os = sock1.getOutputStream();
|
||||
os.write(99);
|
||||
os.flush();
|
||||
if (sock.getInputStream().read() != 99)
|
||||
throw new RuntimeException("Tunnel does not work");
|
||||
} finally {
|
||||
proxy.terminate();
|
||||
}
|
||||
}
|
||||
|
||||
static ProxyTunnelServer setupProxy(boolean makeTunnel) throws IOException {
|
||||
ProxyTunnelServer pserver = new ProxyTunnelServer();
|
||||
pserver.doTunnel(makeTunnel);
|
||||
int proxyPort = pserver.getPort();
|
||||
|
||||
// disable proxy authentication
|
||||
pserver.needUserAuth(false);
|
||||
pserver.start();
|
||||
System.setProperty("https.proxyHost", "localhost");
|
||||
System.setProperty("https.proxyPort", String.valueOf(
|
||||
pserver.getPort()));
|
||||
System.setProperty("https.proxyPort", String.valueOf(proxyPort));
|
||||
return pserver;
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user