ProxySOCKS4.java

Go to the documentation of this file.
00001 /* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
00002 /*
00003 Copyright (c) 2006-2011 ymnk, JCraft,Inc. All rights reserved.
00004 
00005 Redistribution and use in source and binary forms, with or without
00006 modification, are permitted provided that the following conditions are met:
00007 
00008   1. Redistributions of source code must retain the above copyright notice,
00009      this list of conditions and the following disclaimer.
00010 
00011   2. Redistributions in binary form must reproduce the above copyright 
00012      notice, this list of conditions and the following disclaimer in 
00013      the documentation and/or other materials provided with the distribution.
00014 
00015   3. The names of the authors may not be used to endorse or promote products
00016      derived from this software without specific prior written permission.
00017 
00018 THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
00019 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
00020 FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
00021 INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
00022 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00023 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
00024 OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00025 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00026 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
00027 EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00028 */
00029 
00030 /*
00031  This file depends on following documents,
00032    - SOCKS: A protocol for TCP proxy across firewalls, Ying-Da Lee
00033      http://www.socks.nec.com/protocol/socks4.protocol
00034 
00035      (not accessible any more, but a copy was found here:
00036        http://www.ufasoft.com/doc/socks4_protocol.htm  -- P.E.)
00037  */
00038 
00039 package com.jcraft.jsch;
00040 
00041 import java.io.*;
00042 import java.net.*;
00043 
00044 
00052 public class ProxySOCKS4 implements Proxy{
00053   private static int DEFAULTPORT=1080;
00054   private String proxy_host;
00055   private int proxy_port;
00056   private InputStream in;
00057   private OutputStream out;
00058   private Socket socket;
00059   private String user;
00060   private String passwd;
00061 
00067   public ProxySOCKS4(String proxy_host){
00068     int port=DEFAULTPORT;
00069     String host=proxy_host;
00070     if(proxy_host.indexOf(':')!=-1){
00071       try{
00072     host=proxy_host.substring(0, proxy_host.indexOf(':'));
00073     port=Integer.parseInt(proxy_host.substring(proxy_host.indexOf(':')+1));
00074       }
00075       catch(Exception e){
00076       }
00077     }
00078     this.proxy_host=host;
00079     this.proxy_port=port;
00080   }
00086   public ProxySOCKS4(String proxy_host, int proxy_port){
00087     this.proxy_host=proxy_host;
00088     this.proxy_port=proxy_port;
00089   }
00090 
00091 
00101   public void setUserPasswd(String user, String passwd){
00102     this.user=user;
00103     this.passwd=passwd;
00104   }
00105 
00106   // javadoc from interface -- P.E.
00107   public void connect(SocketFactory socket_factory, String host, int port, int timeout) throws JSchException{
00108     try{
00109       if(socket_factory==null){
00110         socket=Util.createSocket(proxy_host, proxy_port, timeout);
00111         //socket=new Socket(proxy_host, proxy_port);    
00112         in=socket.getInputStream();
00113         out=socket.getOutputStream();
00114       }
00115       else{
00116         socket=socket_factory.createSocket(proxy_host, proxy_port);
00117         in=socket_factory.getInputStream(socket);
00118         out=socket_factory.getOutputStream(socket);
00119       }
00120       if(timeout>0){
00121         socket.setSoTimeout(timeout);
00122       }
00123       socket.setTcpNoDelay(true);
00124 
00125       byte[] buf=new byte[1024];
00126       int index=0;
00127 
00128 /*
00129    1) CONNECT
00130    
00131    The client connects to the SOCKS server and sends a CONNECT request when
00132    it wants to establish a connection to an application server. The client
00133    includes in the request packet the IP address and the port number of the
00134    destination host, and userid, in the following format.
00135    
00136                +----+----+----+----+----+----+----+----+----+----+....+----+
00137                | VN | CD | DSTPORT |      DSTIP        | USERID       |NULL|
00138                +----+----+----+----+----+----+----+----+----+----+....+----+
00139    # of bytes:   1    1      2              4           variable       1
00140    
00141    VN is the SOCKS protocol version number and should be 4. CD is the
00142    SOCKS command code and should be 1 for CONNECT request. NULL is a byte
00143    of all zero bits.
00144 */
00145      
00146       index=0;
00147       buf[index++]=4;
00148       buf[index++]=1;
00149 
00150       buf[index++]=(byte)(port>>>8);
00151       buf[index++]=(byte)(port&0xff);
00152 
00153       try{
00154         InetAddress addr=InetAddress.getByName(host);
00155         byte[] byteAddress = addr.getAddress();
00156         for (int i = 0; i < byteAddress.length; i++) {
00157           buf[index++]=byteAddress[i];
00158         }
00159       }
00160       catch(UnknownHostException uhe){
00161         throw new JSchException("ProxySOCKS4: "+uhe.toString(), uhe);
00162       }
00163 
00164       if(user!=null){
00165         System.arraycopy(Util.str2byte(user), 0, buf, index, user.length());
00166         index+=user.length();
00167       }
00168       buf[index++]=0;
00169       out.write(buf, 0, index);
00170 
00171 /*
00172    The SOCKS server checks to see whether such a request should be granted
00173    based on any combination of source IP address, destination IP address,
00174    destination port number, the userid, and information it may obtain by
00175    consulting IDENT, cf. RFC 1413.  If the request is granted, the SOCKS
00176    server makes a connection to the specified port of the destination host.
00177    A reply packet is sent to the client when this connection is established,
00178    or when the request is rejected or the operation fails. 
00179    
00180                +----+----+----+----+----+----+----+----+
00181                | VN | CD | DSTPORT |      DSTIP        |
00182                +----+----+----+----+----+----+----+----+
00183    # of bytes:   1    1      2              4
00184    
00185    VN is the version of the reply code and should be 0. CD is the result
00186    code with one of the following values:
00187    
00188    90: request granted
00189    91: request rejected or failed
00190    92: request rejected becasue SOCKS server cannot connect to
00191        identd on the client
00192    93: request rejected because the client program and identd
00193        report different user-ids
00194    
00195    The remaining fields are ignored.
00196 */
00197 
00198       int len=8;
00199       int s=0;
00200       while(s<len){
00201         int i=in.read(buf, s, len-s);
00202         if(i<=0){
00203           throw new JSchException("ProxySOCKS4: stream is closed");
00204         }
00205         s+=i;
00206       }
00207       if(buf[0]!=0){
00208         throw new JSchException("ProxySOCKS4: server returns VN "+buf[0]);
00209       }
00210       if(buf[1]!=90){
00211         try{ socket.close(); }
00212     catch(Exception eee){
00213     }
00214         String message="ProxySOCKS4: server returns CD "+buf[1];
00215         throw new JSchException(message);
00216       }
00217     }
00218     catch(RuntimeException e){
00219       throw e;
00220     }
00221     catch(Exception e){
00222       try{ if(socket!=null)socket.close(); }
00223       catch(Exception eee){
00224       }
00225       throw new JSchException("ProxySOCKS4: "+e.toString());
00226     }
00227   }
00228 
00229   // javadoc from interface -- P.E.
00230   public InputStream getInputStream(){ return in; }
00231 
00232   // javadoc from interface -- P.E.
00233   public OutputStream getOutputStream(){ return out; }
00234 
00235   // javadoc from interface -- P.E.
00236   public Socket getSocket(){ return socket; }
00237 
00238   // javadoc from interface -- P.E.
00239   public void close(){
00240     try{
00241       if(in!=null)in.close();
00242       if(out!=null)out.close();
00243       if(socket!=null)socket.close();
00244     }
00245     catch(Exception e){
00246     }
00247     in=null;
00248     out=null;
00249     socket=null;
00250   }
00251 
00255   public static int getDefaultPort(){
00256     return DEFAULTPORT;
00257   }
00258 }

Generated on 5 May 2015 for HPCVIEWER by  doxygen 1.6.1