/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* 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.
*/
/* import org.ietf.jgss.*; */
/**
* SOCKS (V4 & V5) TCP socket implementation (RFC 1928).
* This is a subclass of PlainSocketImpl.
* Note this class should <b>NOT</b> be public.
*/
private boolean useV4 = false;
/* true if the Proxy has been set programatically */
SocksSocketImpl() {
// Nothing needed
}
}
if (a instanceof InetSocketAddress) {
// Use getHostString() to avoid reverse lookups
}
}
void setV4() {
useV4 = true;
}
final int port,
final int timeout)
throws IOException
{
try {
cmdIn = getInputStream();
cmdOut = getOutputStream();
return null;
}
});
}
}
int timeout) throws IOException {
}
if (deadlineMillis == 0L)
return 0;
if (remaining > 0)
return (int) remaining;
throw new SocketTimeoutException();
}
}
int received = 0;
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");
}
return received;
}
/**
* Provides the authentication machanism required by the proxy.
*/
}
long deadlineMillis) throws IOException {
// No Authentication required. We're done then!
return true;
/**
* - The application provided Authenticator, if any
* - the user.name & no password (backward compatibility behavior).
*/
if (method == USER_PASSW) {
public PasswordAuthentication run() {
}
});
} else {
}
return false;
try {
assert false;
}
try {
assert false;
}
} else
byte[] data = new byte[2];
/* RFC 1929 specifies that the connection MUST be closed if
authentication fails */
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;
}
long deadlineMillis) throws IOException {
throw new SocketException("SOCKS V4 requires IPv4 only addresses");
}
try {
assert false;
}
byte[] data = new byte[8];
if (n != 8)
throw new SocketException("Reply from SOCKS server has bad length: " + n);
throw new SocketException("Reply from SOCKS server has bad version");
switch (data[1]) {
case 90:
// Success!
break;
case 91:
break;
case 92:
break;
case 93:
break;
default:
break;
}
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.
*
* @param endpoint the <code>SocketAddress</code> 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
*/
final long deadlineMillis;
if (timeout == 0) {
deadlineMillis = 0L;
} else {
}
throw new IllegalArgumentException("Unsupported address type");
if (epoint.isUnresolved())
else
}
// 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
public ProxySelector run() {
return ProxySelector.getDefault();
}
});
/*
* No default proxySelector --> direct connection
*/
return;
}
// Use getHostString() to avoid reverse lookups
// IPv6 litteral?
}
try {
} catch (URISyntaxException e) {
// This shouldn't happen
assert false : e;
}
return;
}
return;
}
if (!(p.address() instanceof InetSocketAddress))
throw new SocketException("Unknow address type for proxy: " + p);
// Use getHostString() to avoid reverse lookups
if (p instanceof SocksProxy) {
useV4 = true;
}
}
// Connects to the SOCKS server
try {
// Worked, let's get outta here
break;
} catch (IOException e) {
// Ooops, let's notify the ProxySelector
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
*/
throw new SocketException("Can't connect to SOCKS proxy:"
+ savedExc.getMessage());
}
} else {
// Connects to the SOCKS server
try {
} catch (IOException e) {
throw new SocketException(e.getMessage());
}
}
// cmdIn & cmdOut were intialized during the privilegedConnect() call
if (useV4) {
// SOCKS Protocol version 4 doesn't know how to deal with
// DOMAIN type of addresses (unresolved addresses here)
if (epoint.isUnresolved())
return;
}
// This is SOCKS V5
byte[] data = new byte[2];
// 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())
return;
}
throw new SocketException("SOCKS : No acceptable methods");
throw new SocketException("SOCKS : authentication failed");
}
/* Test for IPV4/IPV6/Unresolved */
if (epoint.isUnresolved()) {
try {
assert false;
}
} else {
}
data = new byte[4];
if (i != 4)
throw new SocketException("Reply from SOCKS server has bad length");
int len;
byte[] addr;
switch (data[1]) {
case REQUEST_OK:
// success!
switch(data[3]) {
case IPV4:
addr = new byte[4];
if (i != 4)
throw new SocketException("Reply from SOCKS server badly formatted");
data = new byte[2];
if (i != 2)
throw new SocketException("Reply from SOCKS server badly formatted");
break;
case DOMAIN_NAME:
if (i != len)
throw new SocketException("Reply from SOCKS server badly formatted");
data = new byte[2];
if (i != 2)
throw new SocketException("Reply from SOCKS server badly formatted");
break;
case IPV6:
if (i != len)
throw new SocketException("Reply from SOCKS server badly formatted");
data = new byte[2];
if (i != 2)
throw new SocketException("Reply from SOCKS server badly formatted");
break;
default:
break;
}
break;
case GENERAL_FAILURE:
break;
case NOT_ALLOWED:
break;
case NET_UNREACHABLE:
break;
case HOST_UNREACHABLE:
break;
case CONN_REFUSED:
break;
case TTL_EXPIRED:
break;
case CMD_NOT_SUPPORTED:
break;
case ADDR_TYPE_NOT_SUP:
break;
}
throw ex;
}
}
int lport) throws IOException {
if (!(baddr instanceof Inet4Address)) {
throw new SocketException("SOCKS V4 requires IPv4 only addresses");
}
/* Test for AnyLocal */
if (naddr.isAnyLocalAddress()) {
new PrivilegedAction<InetAddress>() {
public InetAddress run() {
return cmdsock.getLocalAddress();
}
});
}
try {
assert false;
}
byte[] data = new byte[8];
if (n != 8)
throw new SocketException("Reply from SOCKS server has bad length: " + n);
throw new SocketException("Reply from SOCKS server has bad version");
switch (data[1]) {
case 90:
// Success!
break;
case 91:
break;
case 92:
break;
case 93:
break;
default:
break;
}
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
* the one of the host we do accept connection from.
*
* @param addr the Socket address of the remote host.
* @exception IOException if an I/O error occurs when binding this socket.
*/
// this is a client socket, not a server socket, don't
// call the SOCKS proxy for a bind!
return;
}
// Connects to the SOCKS server
// 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
public ProxySelector run() {
return ProxySelector.getDefault();
}
});
/*
* No default proxySelector --> direct connection
*/
return;
}
// Use getHostString() to avoid reverse lookups
// IPv6 litteral?
}
try {
} catch (URISyntaxException e) {
// This shouldn't happen
assert false : e;
}
return;
}
return;
}
if (!(p.address() instanceof InetSocketAddress))
throw new SocketException("Unknow address type for proxy: " + p);
// Use getHostString() to avoid reverse lookups
if (p instanceof SocksProxy) {
useV4 = true;
}
}
// Connects to the SOCKS server
try {
new PrivilegedExceptionAction<Void>() {
return null;
}
});
} catch (Exception e) {
// Ooops, let's notify the ProxySelector
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
*/
throw new SocketException("Can't connect to SOCKS proxy:"
+ savedExc.getMessage());
}
} else {
try {
new PrivilegedExceptionAction<Void>() {
return null;
}
});
} catch (Exception e) {
throw new SocketException(e.getMessage());
}
}
if (useV4) {
return;
}
byte[] data = new byte[2];
// Maybe it's not a V5 sever after all
// Let's try V4 before we give up
return;
}
throw new SocketException("SOCKS : No acceptable methods");
throw new SocketException("SOCKS : authentication failed");
}
// We're OK. Let's issue the BIND command.
if (saddr.isUnresolved()) {
try {
assert false;
}
} else {
}
data = new byte[4];
byte[] addr;
switch (data[1]) {
case REQUEST_OK:
// success!
switch(data[3]) {
case IPV4:
addr = new byte[4];
if (i != 4)
throw new SocketException("Reply from SOCKS server badly formatted");
data = new byte[2];
if (i != 2)
throw new SocketException("Reply from SOCKS server badly formatted");
break;
case DOMAIN_NAME:
if (i != len)
throw new SocketException("Reply from SOCKS server badly formatted");
data = new byte[2];
if (i != 2)
throw new SocketException("Reply from SOCKS server badly formatted");
break;
case IPV6:
if (i != len)
throw new SocketException("Reply from SOCKS server badly formatted");
data = new byte[2];
if (i != 2)
throw new SocketException("Reply from SOCKS server badly formatted");
break;
}
break;
case GENERAL_FAILURE:
break;
case NOT_ALLOWED:
break;
case NET_UNREACHABLE:
break;
case HOST_UNREACHABLE:
break;
case CONN_REFUSED:
break;
case TTL_EXPIRED:
break;
case CMD_NOT_SUPPORTED:
break;
case ADDR_TYPE_NOT_SUP:
break;
}
throw ex;
}
}
/**
* 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.
*/
// Not a Socks ServerSocket.
return;
}
// Sends the "SOCKS BIND" request.
int nport;
byte[] addr;
switch (i) {
case REQUEST_OK:
// success!
switch(i) {
case IPV4:
addr = new byte[4];
real_end =
break;
case DOMAIN_NAME:
break;
case IPV6:
addr = new byte[16];
real_end =
break;
}
break;
case GENERAL_FAILURE:
break;
case NOT_ALLOWED:
break;
case NET_UNREACHABLE:
break;
case HOST_UNREACHABLE:
break;
case CONN_REFUSED:
break;
case TTL_EXPIRED:
break;
case CMD_NOT_SUPPORTED:
break;
case ADDR_TYPE_NOT_SUP:
break;
}
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) {
}
if (s instanceof PlainSocketImpl) {
} else {
}
// 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.
}
/**
* Returns the value of this socket's <code>address</code> field.
*
* @return the value of this socket's <code>address</code> field.
* @see java.net.SocketImpl#address
*/
if (external_address != null)
return external_address.getAddress();
else
return super.getInetAddress();
}
/**
* Returns the value of this socket's <code>port</code> field.
*
* @return the value of this socket's <code>port</code> field.
* @see java.net.SocketImpl#port
*/
protected int getPort() {
if (external_address != null)
return external_address.getPort();
else
return super.getPort();
}
protected int getLocalPort() {
return super.getLocalPort();
if (external_address != null)
return external_address.getPort();
else
return super.getLocalPort();
}
super.close();
}
if (applicationSetProxy) {
try {
} else {
}
return userName;
}
}