diff options
Diffstat (limited to 'src/org/jivesoftware/smack/proxy/Socks4ProxySocketFactory.java')
-rw-r--r-- | src/org/jivesoftware/smack/proxy/Socks4ProxySocketFactory.java | 216 |
1 files changed, 216 insertions, 0 deletions
diff --git a/src/org/jivesoftware/smack/proxy/Socks4ProxySocketFactory.java b/src/org/jivesoftware/smack/proxy/Socks4ProxySocketFactory.java new file mode 100644 index 0000000..6a32c11 --- /dev/null +++ b/src/org/jivesoftware/smack/proxy/Socks4ProxySocketFactory.java @@ -0,0 +1,216 @@ +/** + * $RCSfile$ + * $Revision$ + * $Date$ + * + * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.smack.proxy; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.InetAddress; +import java.net.Socket; +import java.net.UnknownHostException; +import javax.net.SocketFactory; + +/** + * Socket factory for socks4 proxy + * + * @author Atul Aggarwal + */ +public class Socks4ProxySocketFactory + extends SocketFactory +{ + private ProxyInfo proxy; + + public Socks4ProxySocketFactory(ProxyInfo proxy) + { + this.proxy = proxy; + } + + public Socket createSocket(String host, int port) + throws IOException, UnknownHostException + { + return socks4ProxifiedSocket(host,port); + + } + + public Socket createSocket(String host ,int port, InetAddress localHost, + int localPort) + throws IOException, UnknownHostException + { + return socks4ProxifiedSocket(host,port); + } + + public Socket createSocket(InetAddress host, int port) + throws IOException + { + return socks4ProxifiedSocket(host.getHostAddress(),port); + } + + public Socket createSocket( InetAddress address, int port, + InetAddress localAddress, int localPort) + throws IOException + { + return socks4ProxifiedSocket(address.getHostAddress(),port); + + } + + private Socket socks4ProxifiedSocket(String host, int port) + throws IOException + { + Socket socket = null; + InputStream in = null; + OutputStream out = null; + String proxy_host = proxy.getProxyAddress(); + int proxy_port = proxy.getProxyPort(); + String user = proxy.getProxyUsername(); + String passwd = proxy.getProxyPassword(); + + try + { + socket=new Socket(proxy_host, proxy_port); + in=socket.getInputStream(); + out=socket.getOutputStream(); + socket.setTcpNoDelay(true); + + byte[] buf=new byte[1024]; + int index=0; + + /* + 1) CONNECT + + The client connects to the SOCKS server and sends a CONNECT request when + it wants to establish a connection to an application server. The client + includes in the request packet the IP address and the port number of the + destination host, and userid, in the following format. + + +----+----+----+----+----+----+----+----+----+----+....+----+ + | VN | CD | DSTPORT | DSTIP | USERID |NULL| + +----+----+----+----+----+----+----+----+----+----+....+----+ + # of bytes: 1 1 2 4 variable 1 + + VN is the SOCKS protocol version number and should be 4. CD is the + SOCKS command code and should be 1 for CONNECT request. NULL is a byte + of all zero bits. + */ + + index=0; + buf[index++]=4; + buf[index++]=1; + + buf[index++]=(byte)(port>>>8); + buf[index++]=(byte)(port&0xff); + + try + { + InetAddress addr=InetAddress.getByName(host); + byte[] byteAddress = addr.getAddress(); + for (int i = 0; i < byteAddress.length; i++) + { + buf[index++]=byteAddress[i]; + } + } + catch(UnknownHostException uhe) + { + throw new ProxyException(ProxyInfo.ProxyType.SOCKS4, + uhe.toString(), uhe); + } + + if(user!=null) + { + System.arraycopy(user.getBytes(), 0, buf, index, user.length()); + index+=user.length(); + } + buf[index++]=0; + out.write(buf, 0, index); + + /* + The SOCKS server checks to see whether such a request should be granted + based on any combination of source IP address, destination IP address, + destination port number, the userid, and information it may obtain by + consulting IDENT, cf. RFC 1413. If the request is granted, the SOCKS + server makes a connection to the specified port of the destination host. + A reply packet is sent to the client when this connection is established, + or when the request is rejected or the operation fails. + + +----+----+----+----+----+----+----+----+ + | VN | CD | DSTPORT | DSTIP | + +----+----+----+----+----+----+----+----+ + # of bytes: 1 1 2 4 + + VN is the version of the reply code and should be 0. CD is the result + code with one of the following values: + + 90: request granted + 91: request rejected or failed + 92: request rejected becasue SOCKS server cannot connect to + identd on the client + 93: request rejected because the client program and identd + report different user-ids + + The remaining fields are ignored. + */ + + int len=6; + int s=0; + while(s<len) + { + int i=in.read(buf, s, len-s); + if(i<=0) + { + throw new ProxyException(ProxyInfo.ProxyType.SOCKS4, + "stream is closed"); + } + s+=i; + } + if(buf[0]!=0) + { + throw new ProxyException(ProxyInfo.ProxyType.SOCKS4, + "server returns VN "+buf[0]); + } + if(buf[1]!=90) + { + try + { + socket.close(); + } + catch(Exception eee) + { + } + String message="ProxySOCKS4: server returns CD "+buf[1]; + throw new ProxyException(ProxyInfo.ProxyType.SOCKS4,message); + } + byte[] temp = new byte[2]; + in.read(temp, 0, 2); + return socket; + } + catch(RuntimeException e) + { + throw e; + } + catch(Exception e) + { + try + { + if(socket!=null)socket.close(); + } + catch(Exception eee) + { + } + throw new ProxyException(ProxyInfo.ProxyType.SOCKS4, e.toString()); + } + } +} |