/*
 * Copyright (c) 2000, 2015, 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.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * 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.
 */
package java.net;
import java.io.IOException;
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). This is a subclass of PlainSocketImpl. Note this class should NOT be public.
/** * SOCKS (V4 & V5) TCP socket implementation (RFC 1928). * This is a subclass of PlainSocketImpl. * Note this class should <b>NOT</b> be public. */
class SocksSocketImpl extends PlainSocketImpl implements SocksConsts { private String server = null; private int serverPort = DEFAULT_PORT; private InetSocketAddress external_address; private boolean useV4 = false; private Socket cmdsock = null; private InputStream cmdIn = null; private OutputStream cmdOut = null; /* true if the Proxy has been set programatically */ 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) { InetSocketAddress ad = (InetSocketAddress) a; // Use getHostString() to avoid reverse lookups server = ad.getHostString(); serverPort = ad.getPort(); } useV4 = useV4(proxy); } void setV4() { useV4 = true; } private static boolean useV4(Proxy proxy) { if (proxy instanceof SocksProxy && ((SocksProxy)proxy).protocolVersion() == 4) { return true; } return DefaultProxySelector.socksProxyVersion() == 4; } private synchronized void privilegedConnect(final String host, final int port, final int timeout) throws IOException { try { AccessController.doPrivileged( new java.security.PrivilegedExceptionAction<>() { public Void run() throws IOException { superConnectServer(host, port, timeout); cmdIn = getInputStream(); cmdOut = getOutputStream(); return null; } }); } catch (java.security.PrivilegedActionException pae) { throw (IOException) pae.getException(); } } private void superConnectServer(String host, int port, int timeout) throws IOException { super.connect(new InetSocketAddress(host, port), timeout); } private static int remainingMillis(long deadlineMillis) throws IOException { if (deadlineMillis == 0L) return 0; final long remaining = deadlineMillis - System.currentTimeMillis(); if (remaining > 0) return (int) remaining; 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; while (received < len) { int count; try { count = ((SocketInputStream)in).read(data, received, len - received, remainingMillis(deadlineMillis)); } catch (SocketTimeoutException e) { throw new SocketTimeoutException("Connect timed out"); } if (count < 0) throw new SocketException("Malformed reply from SOCKS server"); received += count; } return received; }
Provides the authentication machanism required by the proxy.
/** * Provides the authentication machanism 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 { // No Authentication required. We're done then! if (method == NO_AUTH) return true; /** * User/Password authentication. Try, in that order : * - The application provided Authenticator, if any * - the user.name & no password (backward compatibility behavior). */ if (method == USER_PASSW) { String userName; String password = null; final InetAddress addr = InetAddress.getByName(server); PasswordAuthentication pw = java.security.AccessController.doPrivileged( new java.security.PrivilegedAction<>() { public PasswordAuthentication run() { return Authenticator.requestPasswordAuthentication( server, addr, serverPort, "SOCKS5", "SOCKS authentication", null); } }); if (pw != null) { userName = pw.getUserName(); password = new String(pw.getPassword()); } else { userName = StaticProperty.userName(); } if (userName == null) return false; out.write(1); out.write(userName.length()); try { out.write(userName.getBytes("ISO-8859-1")); } catch (java.io.UnsupportedEncodingException uee) { assert false; } if (password != null) { out.write(password.length()); try { out.write(password.getBytes("ISO-8859-1")); } catch (java.io.UnsupportedEncodingException uee) { assert false; } } else out.write(0); out.flush(); byte[] data = new byte[2]; int i = readSocksReply(in, data, deadlineMillis); if (i != 2 || data[1] != 0) { /* RFC 1929 specifies that the connection MUST be closed if authentication fails */ out.close(); in.close(); return false; } /* 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; } private void connectV4(InputStream in, OutputStream out, InetSocketAddress endpoint, long deadlineMillis) throws IOException { if (!(endpoint.getAddress() instanceof Inet4Address)) { throw new SocketException("SOCKS V4 requires IPv4 only addresses"); } out.write(PROTO_VERS4); out.write(CONNECT); out.write((endpoint.getPort() >> 8) & 0xff); out.write((endpoint.getPort() >> 0) & 0xff); out.write(endpoint.getAddress().getAddress()); 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, deadlineMillis); 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 = endpoint; 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; } }
Connects the Socks Socket to the specified endpoint. It will first connect to the SOCKS proxy and negotiate the access. If the proxy grants the connections, then the connect is successful and all further traffic will go to the "real" endpoint.
Params:
  • endpoint – the SocketAddress to connect to.
  • timeout – the timeout value in milliseconds
Throws:
/** * Connects the Socks Socket to the specified endpoint. It will first * connect to the SOCKS proxy and negotiate the access. If the proxy * grants the connections, then the connect is successful and all * further traffic will go to the "real" endpoint. * * @param endpoint the {@code SocketAddress} to connect to. * @param timeout the timeout value in milliseconds * @throws IOException if the connection can't be established. * @throws SecurityException if there is a security manager and it * doesn't allow the connection * @throws IllegalArgumentException if endpoint is null or a * SocketAddress subclass not supported by this socket */
@Override protected void connect(SocketAddress endpoint, int timeout) throws IOException { final long deadlineMillis; if (timeout == 0) { deadlineMillis = 0L; } else { long finish = System.currentTimeMillis() + timeout; deadlineMillis = finish < 0 ? Long.MAX_VALUE : finish; } SecurityManager security = System.getSecurityManager(); if (endpoint == null || !(endpoint instanceof InetSocketAddress)) throw new IllegalArgumentException("Unsupported address type"); InetSocketAddress epoint = (InetSocketAddress) endpoint; if (security != null) { if (epoint.isUnresolved()) security.checkConnect(epoint.getHostName(), epoint.getPort()); else security.checkConnect(epoint.getAddress().getHostAddress(), epoint.getPort()); } 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 */ super.connect(epoint, remainingMillis(deadlineMillis)); return; } URI uri; // Use getHostString() to avoid reverse lookups String host = epoint.getHostString(); // IPv6 litteral? if (epoint.getAddress() instanceof Inet6Address && (!host.startsWith("[")) && (host.indexOf(':') >= 0)) { host = "[" + host + "]"; } try { uri = new URI("socket://" + ParseUtil.encodePath(host) + ":"+ epoint.getPort()); } catch (URISyntaxException e) { // This shouldn't happen assert false : e; uri = null; } Proxy p = null; IOException savedExc = null; java.util.Iterator<Proxy> iProxy = null; iProxy = sel.select(uri).iterator(); if (iProxy == null || !(iProxy.hasNext())) { super.connect(epoint, remainingMillis(deadlineMillis)); return; } while (iProxy.hasNext()) { p = iProxy.next(); if (p == null || p.type() != Proxy.Type.SOCKS) { super.connect(epoint, remainingMillis(deadlineMillis)); 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 { privilegedConnect(server, serverPort, remainingMillis(deadlineMillis)); // Worked, let's get outta here break; } catch (IOException e) { // Ooops, let's notify the ProxySelector sel.connectFailed(uri,p.address(),e); server = null; serverPort = -1; 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) { throw new SocketException("Can't connect to SOCKS proxy:" + savedExc.getMessage()); } } else { // Connects to the SOCKS server try { privilegedConnect(server, serverPort, remainingMillis(deadlineMillis)); } catch (IOException e) { throw new SocketException(e.getMessage()); } } // cmdIn & cmdOut were initialized during the privilegedConnect() call BufferedOutputStream out = new BufferedOutputStream(cmdOut, 512); InputStream in = cmdIn; if (useV4) { // SOCKS Protocol version 4 doesn't know how to deal with // DOMAIN type of addresses (unresolved addresses here) if (epoint.isUnresolved()) throw new UnknownHostException(epoint.toString()); connectV4(in, out, epoint, deadlineMillis); return; } // This is SOCKS V5 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, deadlineMillis); 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 // SOCKS Protocol version 4 doesn't know how to deal with // DOMAIN type of addresses (unresolved addresses here) if (epoint.isUnresolved()) throw new UnknownHostException(epoint.toString()); connectV4(in, out, epoint, deadlineMillis); return; } if (((int)data[1]) == NO_METHODS) throw new SocketException("SOCKS : No acceptable methods"); if (!authenticate(data[1], in, out, deadlineMillis)) { throw new SocketException("SOCKS : authentication failed"); } out.write(PROTO_VERS); out.write(CONNECT); out.write(0); /* Test for IPV4/IPV6/Unresolved */ if (epoint.isUnresolved()) { out.write(DOMAIN_NAME); out.write(epoint.getHostName().length()); try { out.write(epoint.getHostName().getBytes("ISO-8859-1")); } catch (java.io.UnsupportedEncodingException uee) { assert false; } out.write((epoint.getPort() >> 8) & 0xff); out.write((epoint.getPort() >> 0) & 0xff); } else if (epoint.getAddress() instanceof Inet6Address) { out.write(IPV6); out.write(epoint.getAddress().getAddress()); out.write((epoint.getPort() >> 8) & 0xff); out.write((epoint.getPort() >> 0) & 0xff); } else { out.write(IPV4); out.write(epoint.getAddress().getAddress()); out.write((epoint.getPort() >> 8) & 0xff); out.write((epoint.getPort() >> 0) & 0xff); } out.flush(); data = new byte[4]; i = readSocksReply(in, data, deadlineMillis); if (i != 4) throw new SocketException("Reply from SOCKS server has bad length"); SocketException ex = null; int len; byte[] addr; switch (data[1]) { case REQUEST_OK: // success! switch(data[3]) { case IPV4: addr = new byte[4]; i = readSocksReply(in, addr, deadlineMillis); if (i != 4) throw new SocketException("Reply from SOCKS server badly formatted"); data = new byte[2]; i = readSocksReply(in, data, deadlineMillis); if (i != 2) throw new SocketException("Reply from SOCKS server badly formatted"); break; case DOMAIN_NAME: byte[] lenByte = new byte[1]; i = readSocksReply(in, lenByte, deadlineMillis); if (i != 1) throw new SocketException("Reply from SOCKS server badly formatted"); len = lenByte[0] & 0xFF; byte[] host = new byte[len]; i = readSocksReply(in, host, deadlineMillis); if (i != len) throw new SocketException("Reply from SOCKS server badly formatted"); data = new byte[2]; i = readSocksReply(in, data, deadlineMillis); if (i != 2) throw new SocketException("Reply from SOCKS server badly formatted"); break; case IPV6: len = 16; addr = new byte[len]; i = readSocksReply(in, addr, deadlineMillis); if (i != len) throw new SocketException("Reply from SOCKS server badly formatted"); data = new byte[2]; i = readSocksReply(in, data, deadlineMillis); if (i != 2) throw new SocketException("Reply from SOCKS server badly formatted"); break; default: ex = new SocketException("Reply from SOCKS server contains wrong code"); break; } break; case GENERAL_FAILURE: ex = new SocketException("SOCKS server general failure"); break; case NOT_ALLOWED: ex = new SocketException("SOCKS: Connection 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(); throw ex; } 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.
Params:
  • saddr – the Socket address of the remote host.
Throws:
  • IOException – if an I/O error occurs when binding this socket.
/** * 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 litteral? 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.
Params:
  • s – the accepted connection.
  • saddr – the socket address of the host we do accept connection from
Throws:
  • IOException – if an I/O error occurs when accepting the connection.
/** * 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; }
Returns the value of this socket's address field.
See Also:
Returns: the value of this socket's address field.
/** * Returns the value of this socket's {@code address} field. * * @return the value of this socket's {@code address} field. * @see java.net.SocketImpl#address */
@Override protected InetAddress getInetAddress() { if (external_address != null) return external_address.getAddress(); else return super.getInetAddress(); }
Returns the value of this socket's port field.
See Also:
Returns: the value of this socket's port field.
/** * Returns the value of this socket's {@code port} field. * * @return the value of this socket's {@code port} field. * @see java.net.SocketImpl#port */
@Override protected int getPort() { if (external_address != null) return external_address.getPort(); 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(); } @Override protected void close() throws IOException { if (cmdsock != null) cmdsock.close(); cmdsock = null; super.close(); } private String getUserName() { String userName = ""; if (applicationSetProxy) { try { userName = System.getProperty("user.name"); } catch (SecurityException se) { /* swallow Exception */ } } else { userName = StaticProperty.userName(); } return userName; } }