Source Code Cross Referenced for SocksSocketImpl.java in  » 6.0-JDK-Core » net » java » net » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Home
Java Source Code / Java Documentation
1.6.0 JDK Core
2.6.0 JDK Modules
3.6.0 JDK Modules com.sun
4.6.0 JDK Modules com.sun.java
5.6.0 JDK Modules sun
6.6.0 JDK Platform
7.Ajax
8.Apache Harmony Java SE
9.Aspect oriented
10.Authentication Authorization
11.Blogger System
12.Build
13.Byte Code
14.Cache
15.Chart
16.Chat
17.Code Analyzer
18.Collaboration
19.Content Management System
20.Database Client
21.Database DBMS
22.Database JDBC Connection Pool
23.Database ORM
24.Development
25.EJB Server
26.ERP CRM Financial
27.ESB
28.Forum
29.Game
30.GIS
31.Graphic 3D
32.Graphic Library
33.Groupware
34.HTML Parser
35.IDE
36.IDE Eclipse
37.IDE Netbeans
38.Installer
39.Internationalization Localization
40.Inversion of Control
41.Issue Tracking
42.J2EE
43.J2ME
44.JBoss
45.JMS
46.JMX
47.Library
48.Mail Clients
49.Music
50.Net
51.Parser
52.PDF
53.Portal
54.Profiler
55.Project Management
56.Report
57.RSS RDF
58.Rule Engine
59.Science
60.Scripting
61.Search Engine
62.Security
63.Sevlet Container
64.Source Control
65.Swing Library
66.Template Engine
67.Test Coverage
68.Testing
69.UML
70.Web Crawler
71.Web Framework
72.Web Mail
73.Web Server
74.Web Services
75.Web Services apache cxf 2.2.6
76.Web Services AXIS2
77.Wiki Engine
78.Workflow Engines
79.XML
80.XML UI
Java Source Code / Java Documentation » 6.0 JDK Core » net » java.net 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001        /*
0002         * Copyright 2000-2007 Sun Microsystems, Inc.  All Rights Reserved.
0003         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004         *
0005         * This code is free software; you can redistribute it and/or modify it
0006         * under the terms of the GNU General Public License version 2 only, as
0007         * published by the Free Software Foundation.  Sun designates this
0008         * particular file as subject to the "Classpath" exception as provided
0009         * by Sun in the LICENSE file that accompanied this code.
0010         *
0011         * This code is distributed in the hope that it will be useful, but WITHOUT
0012         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
0014         * version 2 for more details (a copy is included in the LICENSE file that
0015         * accompanied this code).
0016         *
0017         * You should have received a copy of the GNU General Public License version
0018         * 2 along with this work; if not, write to the Free Software Foundation,
0019         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020         *
0021         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022         * CA 95054 USA or visit www.sun.com if you need additional information or
0023         * have any questions.
0024         */
0025        package java.net;
0026
0027        import java.io.IOException;
0028        import java.io.InputStream;
0029        import java.io.OutputStream;
0030        import java.io.BufferedOutputStream;
0031        import java.security.AccessController;
0032        import java.security.PrivilegedExceptionAction;
0033        import java.util.prefs.Preferences;
0034        import sun.net.www.ParseUtil;
0035
0036        /* import org.ietf.jgss.*; */
0037
0038        /**
0039         * SOCKS (V4 & V5) TCP socket implementation (RFC 1928).
0040         * This is a subclass of PlainSocketImpl.
0041         * Note this class should <b>NOT</b> be public.
0042         */
0043
0044        class SocksSocketImpl extends PlainSocketImpl implements  SocksConsts {
0045            private String server = null;
0046            private int port = DEFAULT_PORT;
0047            private InetSocketAddress external_address;
0048            private boolean useV4 = false;
0049            private Socket cmdsock = null;
0050            private InputStream cmdIn = null;
0051            private OutputStream cmdOut = null;
0052
0053            SocksSocketImpl() {
0054                // Nothing needed
0055            }
0056
0057            SocksSocketImpl(String server, int port) {
0058                this .server = server;
0059                this .port = (port == -1 ? DEFAULT_PORT : port);
0060            }
0061
0062            SocksSocketImpl(Proxy proxy) {
0063                SocketAddress a = proxy.address();
0064                if (a instanceof  InetSocketAddress) {
0065                    InetSocketAddress ad = (InetSocketAddress) a;
0066                    // Use getHostString() to avoid reverse lookups
0067                    server = ad.getHostString();
0068                    port = ad.getPort();
0069                }
0070            }
0071
0072            void setV4() {
0073                useV4 = true;
0074            }
0075
0076            private synchronized void privilegedConnect(final String host,
0077                    final int port, final int timeout) throws IOException {
0078                try {
0079                    AccessController
0080                            .doPrivileged(new java.security.PrivilegedExceptionAction() {
0081                                public Object run() throws IOException {
0082                                    super ConnectServer(host, port, timeout);
0083                                    cmdIn = getInputStream();
0084                                    cmdOut = getOutputStream();
0085                                    return null;
0086                                }
0087                            });
0088                } catch (java.security.PrivilegedActionException pae) {
0089                    throw (IOException) pae.getException();
0090                }
0091            }
0092
0093            private void super ConnectServer(String host, int port, int timeout)
0094                    throws IOException {
0095                super .connect(new InetSocketAddress(host, port), timeout);
0096            }
0097
0098            private int readSocksReply(InputStream in, byte[] data)
0099                    throws IOException {
0100                int len = data.length;
0101                int received = 0;
0102                for (int attempts = 0; received < len && attempts < 3; attempts++) {
0103                    int count = in.read(data, received, len - received);
0104                    if (count < 0)
0105                        throw new SocketException(
0106                                "Malformed reply from SOCKS server");
0107                    received += count;
0108                }
0109                return received;
0110            }
0111
0112            /**
0113             * Provides the authentication machanism required by the proxy.
0114             */
0115            private boolean authenticate(byte method, InputStream in,
0116                    BufferedOutputStream out) throws IOException {
0117                byte[] data = null;
0118                int i;
0119                // No Authentication required. We're done then!
0120                if (method == NO_AUTH)
0121                    return true;
0122                /**
0123                 * User/Password authentication. Try, in that order :
0124                 * - The application provided Authenticator, if any
0125                 * - The user preferences java.net.socks.username & 
0126                 *   java.net.socks.password
0127                 * - the user.name & no password (backward compatibility behavior).
0128                 */
0129                if (method == USER_PASSW) {
0130                    String userName;
0131                    String password = null;
0132                    final InetAddress addr = InetAddress.getByName(server);
0133                    PasswordAuthentication pw = (PasswordAuthentication) java.security.AccessController
0134                            .doPrivileged(new java.security.PrivilegedAction() {
0135                                public Object run() {
0136                                    return Authenticator
0137                                            .requestPasswordAuthentication(
0138                                                    server, addr, port,
0139                                                    "SOCKS5",
0140                                                    "SOCKS authentication",
0141                                                    null);
0142                                }
0143                            });
0144                    if (pw != null) {
0145                        userName = pw.getUserName();
0146                        password = new String(pw.getPassword());
0147                    } else {
0148                        final Preferences prefs = Preferences.userRoot().node(
0149                                "/java/net/socks");
0150                        try {
0151                            userName = (String) AccessController
0152                                    .doPrivileged(new java.security.PrivilegedExceptionAction() {
0153                                        public Object run() throws IOException {
0154                                            return prefs.get("username", null);
0155                                        }
0156                                    });
0157                        } catch (java.security.PrivilegedActionException pae) {
0158                            throw (IOException) pae.getException();
0159                        }
0160
0161                        if (userName != null) {
0162                            try {
0163                                password = (String) AccessController
0164                                        .doPrivileged(new java.security.PrivilegedExceptionAction() {
0165                                            public Object run()
0166                                                    throws IOException {
0167                                                return prefs.get("password",
0168                                                        null);
0169                                            }
0170                                        });
0171                            } catch (java.security.PrivilegedActionException pae) {
0172                                throw (IOException) pae.getException();
0173                            }
0174                        } else {
0175                            userName = (String) java.security.AccessController
0176                                    .doPrivileged(new sun.security.action.GetPropertyAction(
0177                                            "user.name"));
0178                        }
0179                    }
0180                    if (userName == null)
0181                        return false;
0182                    out.write(1);
0183                    out.write(userName.length());
0184                    try {
0185                        out.write(userName.getBytes("ISO-8859-1"));
0186                    } catch (java.io.UnsupportedEncodingException uee) {
0187                        assert false;
0188                    }
0189                    if (password != null) {
0190                        out.write(password.length());
0191                        try {
0192                            out.write(password.getBytes("ISO-8859-1"));
0193                        } catch (java.io.UnsupportedEncodingException uee) {
0194                            assert false;
0195                        }
0196                    } else
0197                        out.write(0);
0198                    out.flush();
0199                    data = new byte[2];
0200                    i = readSocksReply(in, data);
0201                    if (i != 2 || data[1] != 0) {
0202                        /* RFC 1929 specifies that the connection MUST be closed if
0203                           authentication fails */
0204                        out.close();
0205                        in.close();
0206                        return false;
0207                    }
0208                    /* Authentication succeeded */
0209                    return true;
0210                }
0211                /**
0212                 * GSSAPI authentication mechanism.
0213                 * Unfortunately the RFC seems out of sync with the Reference
0214                 * implementation. I'll leave this in for future completion.
0215                 */
0216                // 	if (method == GSSAPI) {
0217                // 	    try {
0218                // 		GSSManager manager = GSSManager.getInstance();
0219                // 		GSSName name = manager.createName("SERVICE:socks@"+server,
0220                // 						     null);
0221                // 		GSSContext context = manager.createContext(name, null, null,
0222                // 							   GSSContext.DEFAULT_LIFETIME);
0223                // 		context.requestMutualAuth(true);
0224                // 		context.requestReplayDet(true);
0225                // 		context.requestSequenceDet(true);
0226                // 		context.requestCredDeleg(true);
0227                // 		byte []inToken = new byte[0];
0228                // 		while (!context.isEstablished()) {
0229                // 		    byte[] outToken 
0230                // 			= context.initSecContext(inToken, 0, inToken.length);
0231                // 		    // send the output token if generated
0232                // 		    if (outToken != null) {
0233                // 			out.write(1);
0234                // 			out.write(1);
0235                // 			out.writeShort(outToken.length);
0236                // 			out.write(outToken);
0237                // 			out.flush();
0238                // 			data = new byte[2];
0239                // 			i = readSocksReply(in, data);
0240                // 			if (i != 2 || data[1] == 0xff) {
0241                // 			    in.close();
0242                // 			    out.close();
0243                // 			    return false;
0244                // 			}
0245                // 			i = readSocksReply(in, data);
0246                // 			int len = 0;
0247                // 			len = ((int)data[0] & 0xff) << 8;
0248                // 			len += data[1];
0249                // 			data = new byte[len];
0250                // 			i = readSocksReply(in, data);
0251                // 			if (i == len)
0252                // 			    return true;
0253                // 			in.close();
0254                // 			out.close();
0255                // 		    }
0256                // 		}
0257                // 	    } catch (GSSException e) {
0258                // 		/* RFC 1961 states that if Context initialisation fails the connection
0259                // 		   MUST be closed */
0260                // 		e.printStackTrace();
0261                // 		in.close();
0262                // 		out.close();
0263                // 	    }
0264                // 	}
0265                return false;
0266            }
0267
0268            private void connectV4(InputStream in, OutputStream out,
0269                    InetSocketAddress endpoint) throws IOException {
0270                if (!(endpoint.getAddress() instanceof  Inet4Address)) {
0271                    throw new SocketException(
0272                            "SOCKS V4 requires IPv4 only addresses");
0273                }
0274                out.write(PROTO_VERS4);
0275                out.write(CONNECT);
0276                out.write((endpoint.getPort() >> 8) & 0xff);
0277                out.write((endpoint.getPort() >> 0) & 0xff);
0278                out.write(endpoint.getAddress().getAddress());
0279                String userName = (String) java.security.AccessController
0280                        .doPrivileged(new sun.security.action.GetPropertyAction(
0281                                "user.name"));
0282                try {
0283                    out.write(userName.getBytes("ISO-8859-1"));
0284                } catch (java.io.UnsupportedEncodingException uee) {
0285                    assert false;
0286                }
0287                out.write(0);
0288                out.flush();
0289                byte[] data = new byte[8];
0290                int n = readSocksReply(in, data);
0291                if (n != 8)
0292                    throw new SocketException(
0293                            "Reply from SOCKS server has bad length: " + n);
0294                if (data[0] != 0 && data[0] != 4)
0295                    throw new SocketException(
0296                            "Reply from SOCKS server has bad version");
0297                SocketException ex = null;
0298                switch (data[1]) {
0299                case 90:
0300                    // Success!
0301                    external_address = endpoint;
0302                    break;
0303                case 91:
0304                    ex = new SocketException("SOCKS request rejected");
0305                    break;
0306                case 92:
0307                    ex = new SocketException(
0308                            "SOCKS server couldn't reach destination");
0309                    break;
0310                case 93:
0311                    ex = new SocketException("SOCKS authentication failed");
0312                    break;
0313                default:
0314                    ex = new SocketException(
0315                            "Reply from SOCKS server contains bad status");
0316                    break;
0317                }
0318                if (ex != null) {
0319                    in.close();
0320                    out.close();
0321                    throw ex;
0322                }
0323            }
0324
0325            /**
0326             * Connects the Socks Socket to the specified endpoint. It will first
0327             * connect to the SOCKS proxy and negotiate the access. If the proxy
0328             * grants the connections, then the connect is successful and all
0329             * further traffic will go to the "real" endpoint.
0330             *
0331             * @param	endpoint	the <code>SocketAddress</code> to connect to.
0332             * @param	timeout		the timeout value in milliseconds
0333             * @throws	IOException	if the connection can't be established.
0334             * @throws	SecurityException if there is a security manager and it
0335             *				doesn't allow the connection
0336             * @throws  IllegalArgumentException if endpoint is null or a
0337             *          SocketAddress subclass not supported by this socket
0338             */
0339            protected void connect(SocketAddress endpoint, int timeout)
0340                    throws IOException {
0341                SecurityManager security = System.getSecurityManager();
0342                if (endpoint == null
0343                        || !(endpoint instanceof  InetSocketAddress))
0344                    throw new IllegalArgumentException(
0345                            "Unsupported address type");
0346                InetSocketAddress epoint = (InetSocketAddress) endpoint;
0347                if (security != null) {
0348                    if (epoint.isUnresolved())
0349                        security.checkConnect(epoint.getHostName(), epoint
0350                                .getPort());
0351                    else
0352                        security.checkConnect(epoint.getAddress()
0353                                .getHostAddress(), epoint.getPort());
0354                }
0355                if (server == null) {
0356                    // This is the general case
0357                    // server is not null only when the socket was created with a
0358                    // specified proxy in which case it does bypass the ProxySelector
0359                    ProxySelector sel = (ProxySelector) java.security.AccessController
0360                            .doPrivileged(new java.security.PrivilegedAction() {
0361                                public Object run() {
0362                                    return ProxySelector.getDefault();
0363                                }
0364                            });
0365                    if (sel == null) {
0366                        /*
0367                         * No default proxySelector --> direct connection
0368                         */
0369                        super .connect(epoint, timeout);
0370                        return;
0371                    }
0372                    URI uri = null;
0373                    // Use getHostString() to avoid reverse lookups
0374                    String host = epoint.getHostString();
0375                    // IPv6 litteral?
0376                    if (epoint.getAddress() instanceof  Inet6Address
0377                            && (!host.startsWith("["))
0378                            && (host.indexOf(":") >= 0)) {
0379                        host = "[" + host + "]";
0380                    }
0381                    try {
0382                        uri = new URI("socket://" + ParseUtil.encodePath(host)
0383                                + ":" + epoint.getPort());
0384                    } catch (URISyntaxException e) {
0385                        // This shouldn't happen
0386                        assert false : e;
0387                    }
0388                    Proxy p = null;
0389                    IOException savedExc = null;
0390                    java.util.Iterator<Proxy> iProxy = null;
0391                    iProxy = sel.select(uri).iterator();
0392                    if (iProxy == null || !(iProxy.hasNext())) {
0393                        super .connect(epoint, timeout);
0394                        return;
0395                    }
0396                    while (iProxy.hasNext()) {
0397                        p = iProxy.next();
0398                        if (p == null || p == Proxy.NO_PROXY) {
0399                            super .connect(epoint, timeout);
0400                            return;
0401                        }
0402                        if (p.type() != Proxy.Type.SOCKS)
0403                            throw new SocketException("Unknown proxy type : "
0404                                    + p.type());
0405                        if (!(p.address() instanceof  InetSocketAddress))
0406                            throw new SocketException(
0407                                    "Unknow address type for proxy: " + p);
0408                        // Use getHostString() to avoid reverse lookups
0409                        server = ((InetSocketAddress) p.address())
0410                                .getHostString();
0411                        port = ((InetSocketAddress) p.address()).getPort();
0412
0413                        // Connects to the SOCKS server
0414                        try {
0415                            privilegedConnect(server, port, timeout);
0416                            // Worked, let's get outta here
0417                            break;
0418                        } catch (IOException e) {
0419                            // Ooops, let's notify the ProxySelector
0420                            sel.connectFailed(uri, p.address(), e);
0421                            server = null;
0422                            port = -1;
0423                            savedExc = e;
0424                            // Will continue the while loop and try the next proxy
0425                        }
0426                    }
0427
0428                    /*
0429                     * If server is still null at this point, none of the proxy
0430                     * worked
0431                     */
0432                    if (server == null) {
0433                        throw new SocketException(
0434                                "Can't connect to SOCKS proxy:"
0435                                        + savedExc.getMessage());
0436                    }
0437                } else {
0438                    // Connects to the SOCKS server
0439                    try {
0440                        privilegedConnect(server, port, timeout);
0441                    } catch (IOException e) {
0442                        throw new SocketException(e.getMessage());
0443                    }
0444                }
0445
0446                // cmdIn & cmdOut were intialized during the privilegedConnect() call
0447                BufferedOutputStream out = new BufferedOutputStream(cmdOut, 512);
0448                InputStream in = cmdIn;
0449
0450                if (useV4) {
0451                    // SOCKS Protocol version 4 doesn't know how to deal with 
0452                    // DOMAIN type of addresses (unresolved addresses here)
0453                    if (epoint.isUnresolved())
0454                        throw new UnknownHostException(epoint.toString());
0455                    connectV4(in, out, epoint);
0456                    return;
0457                }
0458
0459                // This is SOCKS V5
0460                out.write(PROTO_VERS);
0461                out.write(2);
0462                out.write(NO_AUTH);
0463                out.write(USER_PASSW);
0464                out.flush();
0465                byte[] data = new byte[2];
0466                int i = readSocksReply(in, data);
0467                if (i != 2 || ((int) data[0]) != PROTO_VERS) {
0468                    // Maybe it's not a V5 sever after all
0469                    // Let's try V4 before we give up
0470                    // SOCKS Protocol version 4 doesn't know how to deal with 
0471                    // DOMAIN type of addresses (unresolved addresses here)
0472                    if (epoint.isUnresolved())
0473                        throw new UnknownHostException(epoint.toString());
0474                    connectV4(in, out, epoint);
0475                    return;
0476                }
0477                if (((int) data[1]) == NO_METHODS)
0478                    throw new SocketException("SOCKS : No acceptable methods");
0479                if (!authenticate(data[1], in, out)) {
0480                    throw new SocketException("SOCKS : authentication failed");
0481                }
0482                out.write(PROTO_VERS);
0483                out.write(CONNECT);
0484                out.write(0);
0485                /* Test for IPV4/IPV6/Unresolved */
0486                if (epoint.isUnresolved()) {
0487                    out.write(DOMAIN_NAME);
0488                    out.write(epoint.getHostName().length());
0489                    try {
0490                        out.write(epoint.getHostName().getBytes("ISO-8859-1"));
0491                    } catch (java.io.UnsupportedEncodingException uee) {
0492                        assert false;
0493                    }
0494                    out.write((epoint.getPort() >> 8) & 0xff);
0495                    out.write((epoint.getPort() >> 0) & 0xff);
0496                } else if (epoint.getAddress() instanceof  Inet6Address) {
0497                    out.write(IPV6);
0498                    out.write(epoint.getAddress().getAddress());
0499                    out.write((epoint.getPort() >> 8) & 0xff);
0500                    out.write((epoint.getPort() >> 0) & 0xff);
0501                } else {
0502                    out.write(IPV4);
0503                    out.write(epoint.getAddress().getAddress());
0504                    out.write((epoint.getPort() >> 8) & 0xff);
0505                    out.write((epoint.getPort() >> 0) & 0xff);
0506                }
0507                out.flush();
0508                data = new byte[4];
0509                i = readSocksReply(in, data);
0510                if (i != 4)
0511                    throw new SocketException(
0512                            "Reply from SOCKS server has bad length");
0513                SocketException ex = null;
0514                int nport, len;
0515                byte[] addr;
0516                switch (data[1]) {
0517                case REQUEST_OK:
0518                    // success!
0519                    switch (data[3]) {
0520                    case IPV4:
0521                        addr = new byte[4];
0522                        i = readSocksReply(in, addr);
0523                        if (i != 4)
0524                            throw new SocketException(
0525                                    "Reply from SOCKS server badly formatted");
0526                        data = new byte[2];
0527                        i = readSocksReply(in, data);
0528                        if (i != 2)
0529                            throw new SocketException(
0530                                    "Reply from SOCKS server badly formatted");
0531                        nport = ((int) data[0] & 0xff) << 8;
0532                        nport += ((int) data[1] & 0xff);
0533                        break;
0534                    case DOMAIN_NAME:
0535                        len = data[1];
0536                        byte[] host = new byte[len];
0537                        i = readSocksReply(in, host);
0538                        if (i != len)
0539                            throw new SocketException(
0540                                    "Reply from SOCKS server badly formatted");
0541                        data = new byte[2];
0542                        i = readSocksReply(in, data);
0543                        if (i != 2)
0544                            throw new SocketException(
0545                                    "Reply from SOCKS server badly formatted");
0546                        nport = ((int) data[0] & 0xff) << 8;
0547                        nport += ((int) data[1] & 0xff);
0548                        break;
0549                    case IPV6:
0550                        len = data[1];
0551                        addr = new byte[len];
0552                        i = readSocksReply(in, addr);
0553                        if (i != len)
0554                            throw new SocketException(
0555                                    "Reply from SOCKS server badly formatted");
0556                        data = new byte[2];
0557                        i = readSocksReply(in, data);
0558                        if (i != 2)
0559                            throw new SocketException(
0560                                    "Reply from SOCKS server badly formatted");
0561                        nport = ((int) data[0] & 0xff) << 8;
0562                        nport += ((int) data[1] & 0xff);
0563                        break;
0564                    default:
0565                        ex = new SocketException(
0566                                "Reply from SOCKS server contains wrong code");
0567                        break;
0568                    }
0569                    break;
0570                case GENERAL_FAILURE:
0571                    ex = new SocketException("SOCKS server general failure");
0572                    break;
0573                case NOT_ALLOWED:
0574                    ex = new SocketException(
0575                            "SOCKS: Connection not allowed by ruleset");
0576                    break;
0577                case NET_UNREACHABLE:
0578                    ex = new SocketException("SOCKS: Network unreachable");
0579                    break;
0580                case HOST_UNREACHABLE:
0581                    ex = new SocketException("SOCKS: Host unreachable");
0582                    break;
0583                case CONN_REFUSED:
0584                    ex = new SocketException("SOCKS: Connection refused");
0585                    break;
0586                case TTL_EXPIRED:
0587                    ex = new SocketException("SOCKS: TTL expired");
0588                    break;
0589                case CMD_NOT_SUPPORTED:
0590                    ex = new SocketException("SOCKS: Command not supported");
0591                    break;
0592                case ADDR_TYPE_NOT_SUP:
0593                    ex = new SocketException(
0594                            "SOCKS: address type not supported");
0595                    break;
0596                }
0597                if (ex != null) {
0598                    in.close();
0599                    out.close();
0600                    throw ex;
0601                }
0602                external_address = epoint;
0603            }
0604
0605            private void bindV4(InputStream in, OutputStream out,
0606                    InetAddress baddr, int lport) throws IOException {
0607                if (!(baddr instanceof  Inet4Address)) {
0608                    throw new SocketException(
0609                            "SOCKS V4 requires IPv4 only addresses");
0610                }
0611                super .bind(baddr, lport);
0612                byte[] addr1 = baddr.getAddress();
0613                /* Test for AnyLocal */
0614                InetAddress naddr = baddr;
0615                if (naddr.isAnyLocalAddress()) {
0616                    naddr = cmdsock.getLocalAddress();
0617                    addr1 = naddr.getAddress();
0618                }
0619                out.write(PROTO_VERS4);
0620                out.write(BIND);
0621                out.write((super .getLocalPort() >> 8) & 0xff);
0622                out.write((super .getLocalPort() >> 0) & 0xff);
0623                out.write(addr1);
0624                String userName = (String) java.security.AccessController
0625                        .doPrivileged(new sun.security.action.GetPropertyAction(
0626                                "user.name"));
0627                try {
0628                    out.write(userName.getBytes("ISO-8859-1"));
0629                } catch (java.io.UnsupportedEncodingException uee) {
0630                    assert false;
0631                }
0632                out.write(0);
0633                out.flush();
0634                byte[] data = new byte[8];
0635                int n = readSocksReply(in, data);
0636                if (n != 8)
0637                    throw new SocketException(
0638                            "Reply from SOCKS server has bad length: " + n);
0639                if (data[0] != 0 && data[0] != 4)
0640                    throw new SocketException(
0641                            "Reply from SOCKS server has bad version");
0642                SocketException ex = null;
0643                switch (data[1]) {
0644                case 90:
0645                    // Success!
0646                    external_address = new InetSocketAddress(baddr, lport);
0647                    break;
0648                case 91:
0649                    ex = new SocketException("SOCKS request rejected");
0650                    break;
0651                case 92:
0652                    ex = new SocketException(
0653                            "SOCKS server couldn't reach destination");
0654                    break;
0655                case 93:
0656                    ex = new SocketException("SOCKS authentication failed");
0657                    break;
0658                default:
0659                    ex = new SocketException(
0660                            "Reply from SOCKS server contains bad status");
0661                    break;
0662                }
0663                if (ex != null) {
0664                    in.close();
0665                    out.close();
0666                    throw ex;
0667                }
0668
0669            }
0670
0671            /**
0672             * Sends the Bind request to the SOCKS proxy. In the SOCKS protocol, bind
0673             * means "accept incoming connection from", so the SocketAddress is the
0674             * the one of the host we do accept connection from.
0675             *
0676             * @param      addr   the Socket address of the remote host.
0677             * @exception  IOException  if an I/O error occurs when binding this socket.
0678             */
0679            protected synchronized void socksBind(InetSocketAddress saddr)
0680                    throws IOException {
0681                if (socket != null) {
0682                    // this is a client socket, not a server socket, don't
0683                    // call the SOCKS proxy for a bind!
0684                    return;
0685                }
0686
0687                // Connects to the SOCKS server
0688
0689                if (server == null) {
0690                    // This is the general case
0691                    // server is not null only when the socket was created with a
0692                    // specified proxy in which case it does bypass the ProxySelector
0693                    ProxySelector sel = (ProxySelector) java.security.AccessController
0694                            .doPrivileged(new java.security.PrivilegedAction() {
0695                                public Object run() {
0696                                    return ProxySelector.getDefault();
0697                                }
0698                            });
0699                    if (sel == null) {
0700                        /*
0701                         * No default proxySelector --> direct connection
0702                         */
0703                        return;
0704                    }
0705                    URI uri = null;
0706                    // Use getHostString() to avoid reverse lookups
0707                    String host = saddr.getHostString();
0708                    // IPv6 litteral?
0709                    if (saddr.getAddress() instanceof  Inet6Address
0710                            && (!host.startsWith("["))
0711                            && (host.indexOf(":") >= 0)) {
0712                        host = "[" + host + "]";
0713                    }
0714                    try {
0715                        uri = new URI("serversocket://"
0716                                + ParseUtil.encodePath(host) + ":"
0717                                + saddr.getPort());
0718                    } catch (URISyntaxException e) {
0719                        // This shouldn't happen
0720                        assert false : e;
0721                    }
0722                    Proxy p = null;
0723                    Exception savedExc = null;
0724                    java.util.Iterator<Proxy> iProxy = null;
0725                    iProxy = sel.select(uri).iterator();
0726                    if (iProxy == null || !(iProxy.hasNext())) {
0727                        return;
0728                    }
0729                    while (iProxy.hasNext()) {
0730                        p = iProxy.next();
0731                        if (p == null || p == Proxy.NO_PROXY) {
0732                            return;
0733                        }
0734                        if (p.type() != Proxy.Type.SOCKS)
0735                            throw new SocketException("Unknown proxy type : "
0736                                    + p.type());
0737                        if (!(p.address() instanceof  InetSocketAddress))
0738                            throw new SocketException(
0739                                    "Unknow address type for proxy: " + p);
0740                        // Use getHostString() to avoid reverse lookups
0741                        server = ((InetSocketAddress) p.address())
0742                                .getHostString();
0743                        port = ((InetSocketAddress) p.address()).getPort();
0744
0745                        // Connects to the SOCKS server
0746                        try {
0747                            AccessController
0748                                    .doPrivileged(new PrivilegedExceptionAction() {
0749                                        public Object run() throws Exception {
0750                                            cmdsock = new Socket(
0751                                                    new PlainSocketImpl());
0752                                            cmdsock
0753                                                    .connect(new InetSocketAddress(
0754                                                            server, port));
0755                                            cmdIn = cmdsock.getInputStream();
0756                                            cmdOut = cmdsock.getOutputStream();
0757                                            return null;
0758                                        }
0759                                    });
0760                        } catch (Exception e) {
0761                            // Ooops, let's notify the ProxySelector
0762                            sel.connectFailed(uri, p.address(),
0763                                    new SocketException(e.getMessage()));
0764                            server = null;
0765                            port = -1;
0766                            cmdsock = null;
0767                            savedExc = e;
0768                            // Will continue the while loop and try the next proxy
0769                        }
0770                    }
0771
0772                    /*
0773                     * If server is still null at this point, none of the proxy
0774                     * worked
0775                     */
0776                    if (server == null || cmdsock == null) {
0777                        throw new SocketException(
0778                                "Can't connect to SOCKS proxy:"
0779                                        + savedExc.getMessage());
0780                    }
0781                } else {
0782                    try {
0783                        AccessController
0784                                .doPrivileged(new PrivilegedExceptionAction() {
0785                                    public Object run() throws Exception {
0786                                        cmdsock = new Socket(
0787                                                new PlainSocketImpl());
0788                                        cmdsock.connect(new InetSocketAddress(
0789                                                server, port));
0790                                        cmdIn = cmdsock.getInputStream();
0791                                        cmdOut = cmdsock.getOutputStream();
0792                                        return null;
0793                                    }
0794                                });
0795                    } catch (Exception e) {
0796                        throw new SocketException(e.getMessage());
0797                    }
0798                }
0799                BufferedOutputStream out = new BufferedOutputStream(cmdOut, 512);
0800                InputStream in = cmdIn;
0801                if (useV4) {
0802                    bindV4(in, out, saddr.getAddress(), saddr.getPort());
0803                    return;
0804                }
0805                out.write(PROTO_VERS);
0806                out.write(2);
0807                out.write(NO_AUTH);
0808                out.write(USER_PASSW);
0809                out.flush();
0810                byte[] data = new byte[2];
0811                int i = readSocksReply(in, data);
0812                if (i != 2 || ((int) data[0]) != PROTO_VERS) {
0813                    // Maybe it's not a V5 sever after all
0814                    // Let's try V4 before we give up
0815                    bindV4(in, out, saddr.getAddress(), saddr.getPort());
0816                    return;
0817                }
0818                if (((int) data[1]) == NO_METHODS)
0819                    throw new SocketException("SOCKS : No acceptable methods");
0820                if (!authenticate(data[1], in, out)) {
0821                    throw new SocketException("SOCKS : authentication failed");
0822                }
0823                // We're OK. Let's issue the BIND command.
0824                out.write(PROTO_VERS);
0825                out.write(BIND);
0826                out.write(0);
0827                int lport = saddr.getPort();
0828                if (saddr.isUnresolved()) {
0829                    out.write(DOMAIN_NAME);
0830                    out.write(saddr.getHostName().length());
0831                    try {
0832                        out.write(saddr.getHostName().getBytes("ISO-8859-1"));
0833                    } catch (java.io.UnsupportedEncodingException uee) {
0834                        assert false;
0835                    }
0836                    out.write((lport >> 8) & 0xff);
0837                    out.write((lport >> 0) & 0xff);
0838                } else if (saddr.getAddress() instanceof  Inet4Address) {
0839                    byte[] addr1 = saddr.getAddress().getAddress();
0840                    out.write(IPV4);
0841                    out.write(addr1);
0842                    out.write((lport >> 8) & 0xff);
0843                    out.write((lport >> 0) & 0xff);
0844                    out.flush();
0845                } else if (saddr.getAddress() instanceof  Inet6Address) {
0846                    byte[] addr1 = saddr.getAddress().getAddress();
0847                    out.write(IPV6);
0848                    out.write(addr1);
0849                    out.write((lport >> 8) & 0xff);
0850                    out.write((lport >> 0) & 0xff);
0851                    out.flush();
0852                } else {
0853                    cmdsock.close();
0854                    throw new SocketException("unsupported address type : "
0855                            + saddr);
0856                }
0857                data = new byte[4];
0858                i = readSocksReply(in, data);
0859                SocketException ex = null;
0860                int len, nport;
0861                byte[] addr;
0862                switch (data[1]) {
0863                case REQUEST_OK:
0864                    // success!
0865                    InetSocketAddress real_end = null;
0866                    switch (data[3]) {
0867                    case IPV4:
0868                        addr = new byte[4];
0869                        i = readSocksReply(in, addr);
0870                        if (i != 4)
0871                            throw new SocketException(
0872                                    "Reply from SOCKS server badly formatted");
0873                        data = new byte[2];
0874                        i = readSocksReply(in, data);
0875                        if (i != 2)
0876                            throw new SocketException(
0877                                    "Reply from SOCKS server badly formatted");
0878                        nport = ((int) data[0] & 0xff) << 8;
0879                        nport += ((int) data[1] & 0xff);
0880                        external_address = new InetSocketAddress(
0881                                new Inet4Address("", addr), nport);
0882                        break;
0883                    case DOMAIN_NAME:
0884                        len = data[1];
0885                        byte[] host = new byte[len];
0886                        i = readSocksReply(in, host);
0887                        if (i != len)
0888                            throw new SocketException(
0889                                    "Reply from SOCKS server badly formatted");
0890                        data = new byte[2];
0891                        i = readSocksReply(in, data);
0892                        if (i != 2)
0893                            throw new SocketException(
0894                                    "Reply from SOCKS server badly formatted");
0895                        nport = ((int) data[0] & 0xff) << 8;
0896                        nport += ((int) data[1] & 0xff);
0897                        external_address = new InetSocketAddress(new String(
0898                                host), nport);
0899                        break;
0900                    case IPV6:
0901                        len = data[1];
0902                        addr = new byte[len];
0903                        i = readSocksReply(in, addr);
0904                        if (i != len)
0905                            throw new SocketException(
0906                                    "Reply from SOCKS server badly formatted");
0907                        data = new byte[2];
0908                        i = readSocksReply(in, data);
0909                        if (i != 2)
0910                            throw new SocketException(
0911                                    "Reply from SOCKS server badly formatted");
0912                        nport = ((int) data[0] & 0xff) << 8;
0913                        nport += ((int) data[1] & 0xff);
0914                        external_address = new InetSocketAddress(
0915                                new Inet6Address("", addr), nport);
0916                        break;
0917                    }
0918                    break;
0919                case GENERAL_FAILURE:
0920                    ex = new SocketException("SOCKS server general failure");
0921                    break;
0922                case NOT_ALLOWED:
0923                    ex = new SocketException(
0924                            "SOCKS: Bind not allowed by ruleset");
0925                    break;
0926                case NET_UNREACHABLE:
0927                    ex = new SocketException("SOCKS: Network unreachable");
0928                    break;
0929                case HOST_UNREACHABLE:
0930                    ex = new SocketException("SOCKS: Host unreachable");
0931                    break;
0932                case CONN_REFUSED:
0933                    ex = new SocketException("SOCKS: Connection refused");
0934                    break;
0935                case TTL_EXPIRED:
0936                    ex = new SocketException("SOCKS: TTL expired");
0937                    break;
0938                case CMD_NOT_SUPPORTED:
0939                    ex = new SocketException("SOCKS: Command not supported");
0940                    break;
0941                case ADDR_TYPE_NOT_SUP:
0942                    ex = new SocketException(
0943                            "SOCKS: address type not supported");
0944                    break;
0945                }
0946                if (ex != null) {
0947                    in.close();
0948                    out.close();
0949                    cmdsock.close();
0950                    cmdsock = null;
0951                    throw ex;
0952                }
0953                cmdIn = in;
0954                cmdOut = out;
0955            }
0956
0957            /**
0958             * Accepts a connection from a specific host. 
0959             *
0960             * @param      s   the accepted connection.
0961             * @param	   saddr the socket address of the host we do accept
0962             *		     connection from
0963             * @exception  IOException  if an I/O error occurs when accepting the
0964             *               connection.
0965             */
0966            protected void acceptFrom(SocketImpl s, InetSocketAddress saddr)
0967                    throws IOException {
0968                if (cmdsock == null) {
0969                    // Not a Socks ServerSocket.
0970                    return;
0971                }
0972                InputStream in = cmdIn;
0973                // Sends the "SOCKS BIND" request.
0974                socksBind(saddr);
0975                in.read();
0976                int i = in.read();
0977                in.read();
0978                SocketException ex = null;
0979                int nport;
0980                byte[] addr;
0981                InetSocketAddress real_end = null;
0982                switch (i) {
0983                case REQUEST_OK:
0984                    // success!
0985                    i = in.read();
0986                    switch (i) {
0987                    case IPV4:
0988                        addr = new byte[4];
0989                        readSocksReply(in, addr);
0990                        nport = in.read() << 8;
0991                        nport += in.read();
0992                        real_end = new InetSocketAddress(new Inet4Address("",
0993                                addr), nport);
0994                        break;
0995                    case DOMAIN_NAME:
0996                        int len = in.read();
0997                        addr = new byte[len];
0998                        readSocksReply(in, addr);
0999                        nport = in.read() << 8;
1000                        nport += in.read();
1001                        real_end = new InetSocketAddress(new String(addr),
1002                                nport);
1003                        break;
1004                    case IPV6:
1005                        addr = new byte[16];
1006                        readSocksReply(in, addr);
1007                        nport = in.read() << 8;
1008                        nport += in.read();
1009                        real_end = new InetSocketAddress(new Inet6Address("",
1010                                addr), nport);
1011                        break;
1012                    }
1013                    break;
1014                case GENERAL_FAILURE:
1015                    ex = new SocketException("SOCKS server general failure");
1016                    break;
1017                case NOT_ALLOWED:
1018                    ex = new SocketException(
1019                            "SOCKS: Accept not allowed by ruleset");
1020                    break;
1021                case NET_UNREACHABLE:
1022                    ex = new SocketException("SOCKS: Network unreachable");
1023                    break;
1024                case HOST_UNREACHABLE:
1025                    ex = new SocketException("SOCKS: Host unreachable");
1026                    break;
1027                case CONN_REFUSED:
1028                    ex = new SocketException("SOCKS: Connection refused");
1029                    break;
1030                case TTL_EXPIRED:
1031                    ex = new SocketException("SOCKS: TTL expired");
1032                    break;
1033                case CMD_NOT_SUPPORTED:
1034                    ex = new SocketException("SOCKS: Command not supported");
1035                    break;
1036                case ADDR_TYPE_NOT_SUP:
1037                    ex = new SocketException(
1038                            "SOCKS: address type not supported");
1039                    break;
1040                }
1041                if (ex != null) {
1042                    cmdIn.close();
1043                    cmdOut.close();
1044                    cmdsock.close();
1045                    cmdsock = null;
1046                    throw ex;
1047                }
1048
1049                /**
1050                 * This is where we have to do some fancy stuff.
1051                 * The datastream from the socket "accepted" by the proxy will
1052                 * come through the cmdSocket. So we have to swap the socketImpls
1053                 */
1054                if (s instanceof  SocksSocketImpl) {
1055                    ((SocksSocketImpl) s).external_address = real_end;
1056                }
1057                if (s instanceof  PlainSocketImpl) {
1058                    PlainSocketImpl psi = (PlainSocketImpl) s;
1059                    psi.setInputStream((SocketInputStream) in);
1060                    psi
1061                            .setFileDescriptor(cmdsock.getImpl()
1062                                    .getFileDescriptor());
1063                    psi.setAddress(cmdsock.getImpl().getInetAddress());
1064                    psi.setPort(cmdsock.getImpl().getPort());
1065                    psi.setLocalPort(cmdsock.getImpl().getLocalPort());
1066                } else {
1067                    s.fd = cmdsock.getImpl().fd;
1068                    s.address = cmdsock.getImpl().address;
1069                    s.port = cmdsock.getImpl().port;
1070                    s.localport = cmdsock.getImpl().localport;
1071                }
1072
1073                // Need to do that so that the socket won't be closed
1074                // when the ServerSocket is closed by the user.
1075                // It kinds of detaches the Socket because it is now
1076                // used elsewhere.
1077                cmdsock = null;
1078            }
1079
1080            /**
1081             * Returns the value of this socket's <code>address</code> field.
1082             *
1083             * @return  the value of this socket's <code>address</code> field.
1084             * @see     java.net.SocketImpl#address
1085             */
1086            protected InetAddress getInetAddress() {
1087                if (external_address != null)
1088                    return external_address.getAddress();
1089                else
1090                    return super .getInetAddress();
1091            }
1092
1093            /**
1094             * Returns the value of this socket's <code>port</code> field.
1095             *
1096             * @return  the value of this socket's <code>port</code> field.
1097             * @see     java.net.SocketImpl#port
1098             */
1099            protected int getPort() {
1100                if (external_address != null)
1101                    return external_address.getPort();
1102                else
1103                    return super .getPort();
1104            }
1105
1106            protected int getLocalPort() {
1107                if (socket != null)
1108                    return super .getLocalPort();
1109                if (external_address != null)
1110                    return external_address.getPort();
1111                else
1112                    return super .getLocalPort();
1113            }
1114
1115            protected void close() throws IOException {
1116                if (cmdsock != null)
1117                    cmdsock.close();
1118                cmdsock = null;
1119                super.close();
1120            }
1121
1122        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.