sockssocketimpl.java
来自「This is a resource based on j2me embedde」· Java 代码 · 共 823 行 · 第 1/2 页
JAVA
823 行
/* * @(#)SocksSocketImpl.java 1.15 06/10/10 * * Copyright 1990-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER * * This program 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 program 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 at /legal/license.txt). * * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa * Clara, CA 95054 or visit www.sun.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.DataOutputStream;import java.io.BufferedReader;import java.io.InputStreamReader;import java.security.AccessController;import java.security.PrivilegedExceptionAction;/* 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. */class SocksSocketImpl extends PlainSocketImpl implements SocksConsts { private String server = null; private int port = DEFAULT_PORT; private InetSocketAddress external_address; private boolean useV4 = false; private Socket cmdsock = null; private InputStream cmdIn = null; private OutputStream cmdOut = null; SocksSocketImpl(String server, int port) { this.server = server; this.port = (port == -1 ? DEFAULT_PORT : port); } void setV4() { useV4 = true; } private synchronized void privilegedConnect(final String host, final int port, final int timeout) throws IOException { try { AccessController.doPrivileged( new java.security.PrivilegedExceptionAction() { public Object 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 int readSocksReply(InputStream in, byte[] data) throws IOException { int len = data.length; int received = 0; for (int attempts = 0; received < len && attempts < 3; attempts++) { int count = in.read(data, received, len - received); if (count < 0) throw new SocketException("Malformed reply from SOCKS server"); received += count; } return received; } /** * Provides the authentication machanism required by the proxy. */ private boolean authenticate(byte method, InputStream in, DataOutputStream out) throws IOException { byte[] data = null; int i; // 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 preferences java.net.socks.username & * java.net.socks.password * - 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 = (PasswordAuthentication) java.security.AccessController.doPrivileged( new java.security.PrivilegedAction() { public Object run() { return Authenticator.requestPasswordAuthentication( server, addr, port, "SOCKS5", "SOCKS authentication", null); } }); if (pw != null) { userName = pw.getUserName(); password = new String(pw.getPassword()); } else { try { userName = (String) AccessController.doPrivileged( new java.security.PrivilegedExceptionAction() { public Object run() throws IOException { return null; } }); } catch (java.security.PrivilegedActionException pae) { throw (IOException) pae.getException(); } if (userName != null) { try { password = (String) AccessController.doPrivileged( new java.security.PrivilegedExceptionAction() { public Object run() throws IOException { return null; } }); } catch (java.security.PrivilegedActionException pae) { throw (IOException) pae.getException(); } } else { userName = (String) java.security.AccessController.doPrivileged( new sun.security.action.GetPropertyAction("user.name")); } } if (userName == null) return false; out.write(1); out.write(userName.length()); out.write(userName.getBytes()); if (password != null) { out.write(password.length()); out.write(password.getBytes()); } else out.write(0); out.flush(); data = new byte[2]; i = readSocksReply(in, data); 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);// if (i != 2 || data[1] == 0xff) {// in.close();// out.close();// return false;// }// i = readSocksReply(in, data);// int len = 0;// len = ((int)data[0] & 0xff) << 8;// len += data[1];// data = new byte[len];// i = readSocksReply(in, data);// 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) throws IOException { 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 = (String) java.security.AccessController.doPrivileged( new sun.security.action.GetPropertyAction("user.name")); out.write(userName.getBytes()); 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 = 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("Replay 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. * * @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 */ protected void connect(SocketAddress endpoint, int timeout) throws IOException { 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()); } // Connects to the SOCKS server try { privilegedConnect(server, port, timeout); } catch (Exception e) { throw new SocketException(e.getMessage()); } // cmdIn & cmdOut were intialized during the privilegedConnect() call DataOutputStream out = new DataOutputStream(cmdOut); 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); 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); if (i != 2 || ((int)data[1]) == NO_METHODS) throw new SocketException("SOCKS : No acceptable methods"); if (!authenticate(data[1], in, out)) { 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()); out.write(epoint.getHostName().getBytes()); 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); if (i != 4) throw new SocketException("Reply from SOCKS server has bad length"); SocketException ex = null; int nport, len; 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); 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); 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)
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?