parent
							
								
									79b8b744c7
								
							
						
					
					
						commit
						86d5ebc27b
					
				| 
						 | 
				
			
			@ -0,0 +1,3 @@
 | 
			
		|||
ant compile
 | 
			
		||||
ant jar
 | 
			
		||||
cp bin/jar/asocks.jar ../Orbot/libs
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,22 @@
 | 
			
		|||
<project>
 | 
			
		||||
 | 
			
		||||
    <target name="clean">
 | 
			
		||||
        <delete dir="bin"/>
 | 
			
		||||
    </target>
 | 
			
		||||
 | 
			
		||||
    <target name="compile">
 | 
			
		||||
        <mkdir dir="bin/classes"/>
 | 
			
		||||
        <javac srcdir="src" destdir="bin/classes"/>
 | 
			
		||||
    </target>
 | 
			
		||||
 | 
			
		||||
    <target name="jar">
 | 
			
		||||
        <mkdir dir="bin/jar"/>
 | 
			
		||||
        <jar destfile="bin/jar/asocks.jar" basedir="bin/classes">
 | 
			
		||||
            <manifest>
 | 
			
		||||
            </manifest>
 | 
			
		||||
        </jar>
 | 
			
		||||
    </target>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
</project>
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,257 @@
 | 
			
		|||
package net.sourceforge.jsocks;
 | 
			
		||||
 | 
			
		||||
import java.util.*;
 | 
			
		||||
import java.io.*;
 | 
			
		||||
import java.net.InetAddress;
 | 
			
		||||
import java.net.UnknownHostException;
 | 
			
		||||
 | 
			
		||||
import net.*;
 | 
			
		||||
import net.sourceforge.jsocks.socks.*;
 | 
			
		||||
import net.sourceforge.jsocks.socks.server.*;
 | 
			
		||||
 | 
			
		||||
public class SOCKS{
 | 
			
		||||
 | 
			
		||||
   static public void usage(){
 | 
			
		||||
      System.out.println(
 | 
			
		||||
      "Usage: java SOCKS [inifile1 inifile2 ...]\n"+
 | 
			
		||||
      "If none inifile is given, uses socks.properties.\n"
 | 
			
		||||
      );
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   static public void main(String[] args){
 | 
			
		||||
 | 
			
		||||
      String[] file_names;
 | 
			
		||||
      int port=1080;
 | 
			
		||||
      String logFile = null;
 | 
			
		||||
      String host = null;
 | 
			
		||||
 | 
			
		||||
      IdentAuthenticator auth = new IdentAuthenticator();
 | 
			
		||||
      OutputStream log = null;
 | 
			
		||||
      InetAddress localIP = null;
 | 
			
		||||
 | 
			
		||||
      if(args.length == 0){
 | 
			
		||||
         file_names = new String[1];
 | 
			
		||||
         file_names[0] = "socks.properties";
 | 
			
		||||
      }else{
 | 
			
		||||
         file_names = args;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
      inform("Loading properties");
 | 
			
		||||
      for(int i=0;i<file_names.length;++i){
 | 
			
		||||
 | 
			
		||||
         inform("Reading file "+file_names[i]);
 | 
			
		||||
 | 
			
		||||
         Properties pr = loadProperties(file_names[i]);
 | 
			
		||||
         if(pr==null){
 | 
			
		||||
           System.err.println("Loading of properties from "+
 | 
			
		||||
                               file_names[i]+"failed.");
 | 
			
		||||
           usage();
 | 
			
		||||
           return;
 | 
			
		||||
         }
 | 
			
		||||
         if(!addAuth(auth,pr)){
 | 
			
		||||
           System.err.println("Error in file "+file_names[i]+".");
 | 
			
		||||
           usage();
 | 
			
		||||
           return;
 | 
			
		||||
         }
 | 
			
		||||
         //First file should contain all global settings,
 | 
			
		||||
         // like port and host and log.
 | 
			
		||||
         if(i==0){
 | 
			
		||||
           String port_s = (String) pr.get("port");
 | 
			
		||||
           if(port_s != null)
 | 
			
		||||
              try{
 | 
			
		||||
                port = Integer.parseInt(port_s);
 | 
			
		||||
              }catch(NumberFormatException nfe){
 | 
			
		||||
                System.err.println("Can't parse port: "+port_s);
 | 
			
		||||
                return;
 | 
			
		||||
              }
 | 
			
		||||
 | 
			
		||||
           serverInit(pr);
 | 
			
		||||
           logFile = (String) pr.get("log");
 | 
			
		||||
           host = (String) pr.get("host");
 | 
			
		||||
         }
 | 
			
		||||
         
 | 
			
		||||
         //inform("Props:"+pr);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if(logFile!=null){
 | 
			
		||||
        if(logFile.equals("-"))
 | 
			
		||||
           log = System.out;
 | 
			
		||||
        else
 | 
			
		||||
           try{
 | 
			
		||||
             log = new FileOutputStream(logFile);
 | 
			
		||||
           }catch(IOException ioe){
 | 
			
		||||
             System.err.println("Can't open log file "+logFile);
 | 
			
		||||
             return;
 | 
			
		||||
           }
 | 
			
		||||
      }
 | 
			
		||||
      if(host!=null)
 | 
			
		||||
         try{
 | 
			
		||||
           localIP = InetAddress.getByName(host);
 | 
			
		||||
         }catch(UnknownHostException uhe){
 | 
			
		||||
           System.err.println("Can't resolve local ip: "+host);
 | 
			
		||||
           return;
 | 
			
		||||
         }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
      inform("Using Ident Authentication scheme:\n"+auth+"\n");
 | 
			
		||||
      ProxyServer server = new ProxyServer(auth);
 | 
			
		||||
      server.start(port,5,localIP);
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   static Properties loadProperties(String file_name){
 | 
			
		||||
 | 
			
		||||
      Properties pr = new Properties();
 | 
			
		||||
 | 
			
		||||
      try{
 | 
			
		||||
         InputStream fin = new FileInputStream(file_name);
 | 
			
		||||
         pr.load(fin);
 | 
			
		||||
         fin.close();
 | 
			
		||||
      }catch(IOException ioe){
 | 
			
		||||
         return null;
 | 
			
		||||
      }
 | 
			
		||||
      return pr;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   static boolean addAuth(IdentAuthenticator ident,Properties pr){
 | 
			
		||||
 | 
			
		||||
      InetRange irange;
 | 
			
		||||
 | 
			
		||||
      String range = (String) pr.get("range");
 | 
			
		||||
      if(range == null) return false;
 | 
			
		||||
      irange = parseInetRange(range);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
      String users = (String) pr.get("users");
 | 
			
		||||
 | 
			
		||||
      if(users == null){
 | 
			
		||||
         ident.add(irange,null);
 | 
			
		||||
         return true;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      Hashtable uhash = new Hashtable();
 | 
			
		||||
 | 
			
		||||
      StringTokenizer st = new StringTokenizer(users,";");
 | 
			
		||||
      while(st.hasMoreTokens())
 | 
			
		||||
         uhash.put(st.nextToken(),"");
 | 
			
		||||
 | 
			
		||||
      ident.add(irange,uhash);
 | 
			
		||||
      return true;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
     Does server initialisation. 
 | 
			
		||||
   */
 | 
			
		||||
   public static void serverInit(Properties props){
 | 
			
		||||
      int val;
 | 
			
		||||
      val = readInt(props,"iddleTimeout");
 | 
			
		||||
      if(val>=0){ 
 | 
			
		||||
        ProxyServer.setIddleTimeout(val);
 | 
			
		||||
        inform("Setting iddle timeout to "+val+" ms.");
 | 
			
		||||
      }
 | 
			
		||||
      val = readInt(props,"acceptTimeout");
 | 
			
		||||
      if(val>=0){
 | 
			
		||||
        ProxyServer.setAcceptTimeout(val);
 | 
			
		||||
        inform("Setting accept timeout to "+val+" ms.");
 | 
			
		||||
      }
 | 
			
		||||
      val = readInt(props,"udpTimeout");
 | 
			
		||||
      if(val>=0){
 | 
			
		||||
        ProxyServer.setUDPTimeout(val);
 | 
			
		||||
        inform("Setting udp timeout to "+val+" ms.");
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      val = readInt(props,"datagramSize");
 | 
			
		||||
      if(val>=0){
 | 
			
		||||
        ProxyServer.setDatagramSize(val);
 | 
			
		||||
        inform("Setting datagram size to "+val+" bytes.");
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      proxyInit(props);
 | 
			
		||||
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
     Initialises proxy, if any specified.
 | 
			
		||||
   */
 | 
			
		||||
   static void proxyInit(Properties props){
 | 
			
		||||
      String proxy_list;
 | 
			
		||||
      Proxy proxy = null;
 | 
			
		||||
      StringTokenizer st;
 | 
			
		||||
 | 
			
		||||
      proxy_list = (String) props.get("proxy");
 | 
			
		||||
      if(proxy_list == null) return;
 | 
			
		||||
 | 
			
		||||
      st = new StringTokenizer(proxy_list,";");
 | 
			
		||||
      while(st.hasMoreTokens()){
 | 
			
		||||
         String proxy_entry = st.nextToken();
 | 
			
		||||
 | 
			
		||||
         Proxy p = Proxy.parseProxy(proxy_entry);
 | 
			
		||||
 | 
			
		||||
         if(p == null)
 | 
			
		||||
            exit("Can't parse proxy entry:"+proxy_entry);
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
         inform("Adding Proxy:"+p);
 | 
			
		||||
 | 
			
		||||
         if(proxy != null) 
 | 
			
		||||
            p.setChainProxy(proxy);
 | 
			
		||||
 | 
			
		||||
         proxy = p;
 | 
			
		||||
 | 
			
		||||
      }
 | 
			
		||||
      if(proxy == null) return;  //Empty list
 | 
			
		||||
 | 
			
		||||
      String direct_hosts = (String) props.get("directHosts");
 | 
			
		||||
      if(direct_hosts!=null){
 | 
			
		||||
        InetRange ir = parseInetRange(direct_hosts);
 | 
			
		||||
        inform("Setting direct hosts:"+ir);
 | 
			
		||||
        proxy.setDirect(ir);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
      ProxyServer.setProxy(proxy);
 | 
			
		||||
   }
 | 
			
		||||
   /**
 | 
			
		||||
     Inits range from the string of semicolon separated ranges.
 | 
			
		||||
   */
 | 
			
		||||
   static InetRange parseInetRange(String source){
 | 
			
		||||
      InetRange irange = new InetRange();
 | 
			
		||||
 | 
			
		||||
      StringTokenizer st = new StringTokenizer(source,";");
 | 
			
		||||
      while(st.hasMoreTokens())
 | 
			
		||||
        irange.add(st.nextToken());
 | 
			
		||||
 | 
			
		||||
      return irange;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
    Integer representaion of the property named name, or -1 if one
 | 
			
		||||
    is not found.
 | 
			
		||||
   */
 | 
			
		||||
   static int readInt(Properties props,String name){
 | 
			
		||||
      int result = -1;
 | 
			
		||||
      String val = (String) props.get(name);
 | 
			
		||||
      if(val==null) return -1;
 | 
			
		||||
      StringTokenizer st = new StringTokenizer(val);
 | 
			
		||||
      if(!st.hasMoreElements()) return -1;
 | 
			
		||||
      try{
 | 
			
		||||
        result = Integer.parseInt(st.nextToken());
 | 
			
		||||
      }catch(NumberFormatException nfe){
 | 
			
		||||
        inform("Bad value for "+name+":"+val);
 | 
			
		||||
      }
 | 
			
		||||
      return result;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
//Display functions
 | 
			
		||||
///////////////////
 | 
			
		||||
 | 
			
		||||
   public static void inform(String s){
 | 
			
		||||
      System.out.println(s);
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   static void exit(String msg){
 | 
			
		||||
      System.err.println("Error:"+msg);
 | 
			
		||||
      System.err.println("Aborting operation");
 | 
			
		||||
      System.exit(0);
 | 
			
		||||
   }
 | 
			
		||||
}
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 926 B  | 
| 
						 | 
				
			
			@ -0,0 +1,386 @@
 | 
			
		|||
package net.sourceforge.jsocks;
 | 
			
		||||
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.io.InputStream;
 | 
			
		||||
import java.io.OutputStream;
 | 
			
		||||
import java.net.DatagramPacket;
 | 
			
		||||
import java.net.ServerSocket;
 | 
			
		||||
import java.net.Socket;
 | 
			
		||||
import java.net.UnknownHostException;
 | 
			
		||||
 | 
			
		||||
import net.sourceforge.jsocks.socks.Proxy;
 | 
			
		||||
import net.sourceforge.jsocks.socks.Socks5DatagramSocket;
 | 
			
		||||
import net.sourceforge.jsocks.socks.Socks5Proxy;
 | 
			
		||||
import net.sourceforge.jsocks.socks.SocksServerSocket;
 | 
			
		||||
import net.sourceforge.jsocks.socks.SocksSocket;
 | 
			
		||||
 | 
			
		||||
public class SocksEcho 
 | 
			
		||||
                       implements 
 | 
			
		||||
                                  Runnable
 | 
			
		||||
                                  {
 | 
			
		||||
 | 
			
		||||
//Network related members
 | 
			
		||||
   Proxy proxy=null;
 | 
			
		||||
   int port;
 | 
			
		||||
   String host;
 | 
			
		||||
   Thread net_thread=null;
 | 
			
		||||
   InputStream in=null;
 | 
			
		||||
   OutputStream out=null;
 | 
			
		||||
   Socket sock=null;
 | 
			
		||||
   ServerSocket server_sock = null;
 | 
			
		||||
   Socks5DatagramSocket udp_sock;
 | 
			
		||||
 | 
			
		||||
   Object net_lock = new Object();
 | 
			
		||||
   int mode=COMMAND_MODE;
 | 
			
		||||
 | 
			
		||||
   //Possible mode states.
 | 
			
		||||
   static final int LISTEN_MODE		= 0;
 | 
			
		||||
   static final int CONNECT_MODE	= 1;
 | 
			
		||||
   static final int UDP_MODE		= 2;
 | 
			
		||||
   static final int COMMAND_MODE	= 3;
 | 
			
		||||
   static final int ABORT_MODE		= 4;
 | 
			
		||||
 | 
			
		||||
   //Maximum datagram size
 | 
			
		||||
   static final int MAX_DATAGRAM_SIZE	= 1024;
 | 
			
		||||
 | 
			
		||||
// Constructors
 | 
			
		||||
////////////////////////////////////
 | 
			
		||||
   public SocksEcho(){
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
          
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
//Runnable interface
 | 
			
		||||
///////////////////////////////
 | 
			
		||||
 | 
			
		||||
public void run(){
 | 
			
		||||
    boolean finished_OK = true;
 | 
			
		||||
    try{
 | 
			
		||||
      switch(mode){
 | 
			
		||||
        case UDP_MODE:
 | 
			
		||||
           startUDP();
 | 
			
		||||
           doUDPPipe();
 | 
			
		||||
           break;
 | 
			
		||||
        case LISTEN_MODE:
 | 
			
		||||
           doAccept();
 | 
			
		||||
           doPipe();
 | 
			
		||||
           break;
 | 
			
		||||
        case CONNECT_MODE:
 | 
			
		||||
           doConnect();
 | 
			
		||||
           doPipe();
 | 
			
		||||
           break;
 | 
			
		||||
        default:
 | 
			
		||||
          warn("Unexpected mode in run() method");
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
   }catch(UnknownHostException uh_ex){
 | 
			
		||||
        if(mode != ABORT_MODE){
 | 
			
		||||
	  finished_OK = false;
 | 
			
		||||
	  status("Host "+host+" has no DNS entry.");
 | 
			
		||||
	  uh_ex.printStackTrace();
 | 
			
		||||
       }
 | 
			
		||||
   }catch(IOException io_ex){
 | 
			
		||||
       if(mode != ABORT_MODE){
 | 
			
		||||
	  finished_OK = false;
 | 
			
		||||
          status(""+io_ex);
 | 
			
		||||
          io_ex.printStackTrace();
 | 
			
		||||
      }
 | 
			
		||||
   }finally{
 | 
			
		||||
      if(mode == ABORT_MODE) status("Connection closed");
 | 
			
		||||
      else if(finished_OK) status("Connection closed by foreign host.");
 | 
			
		||||
 | 
			
		||||
      onDisconnect();
 | 
			
		||||
   }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//Private methods
 | 
			
		||||
////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
// GUI event handlers.
 | 
			
		||||
//////////////////////////
 | 
			
		||||
 | 
			
		||||
   private void onConnect(){
 | 
			
		||||
      if(mode == CONNECT_MODE){
 | 
			
		||||
        status("Diconnecting...");
 | 
			
		||||
        abort_connection();
 | 
			
		||||
        return;
 | 
			
		||||
      }else if(mode != COMMAND_MODE)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
//      if(!readHost()) return;
 | 
			
		||||
  //    if(!readPort()) return;
 | 
			
		||||
 | 
			
		||||
      if(proxy == null){
 | 
			
		||||
         warn("Proxy is not set");
 | 
			
		||||
         onProxy();
 | 
			
		||||
         return;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      startNetThread(CONNECT_MODE);
 | 
			
		||||
      status("Connecting to "+host+":"+port+"  ...");
 | 
			
		||||
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   private void onDisconnect(){
 | 
			
		||||
      synchronized(net_lock){
 | 
			
		||||
         mode = COMMAND_MODE;
 | 
			
		||||
       
 | 
			
		||||
         server_sock = null;
 | 
			
		||||
         sock = null;
 | 
			
		||||
         out = null;
 | 
			
		||||
         in = null;
 | 
			
		||||
         net_thread = null;
 | 
			
		||||
      }
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   private void onAccept(){
 | 
			
		||||
      if(mode == LISTEN_MODE){
 | 
			
		||||
         abort_connection();
 | 
			
		||||
         return;
 | 
			
		||||
      }else if(mode != COMMAND_MODE) return;
 | 
			
		||||
 | 
			
		||||
   //   if(!readHost()) return;
 | 
			
		||||
     // if(!readPort()) port = 0;
 | 
			
		||||
 | 
			
		||||
      if(proxy == null){
 | 
			
		||||
         warn("Proxy is not set");
 | 
			
		||||
         onProxy();
 | 
			
		||||
         return;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      startNetThread(LISTEN_MODE);
 | 
			
		||||
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   private void onUDP(){
 | 
			
		||||
      if(mode == UDP_MODE){
 | 
			
		||||
        abort_connection();
 | 
			
		||||
        return;
 | 
			
		||||
      }else if(mode == ABORT_MODE) return;
 | 
			
		||||
 | 
			
		||||
      if(proxy == null){
 | 
			
		||||
         warn("Proxy is not set");
 | 
			
		||||
         onProxy();
 | 
			
		||||
         return;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      startNetThread(UDP_MODE);
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   private void onInput(){
 | 
			
		||||
      String send_string = "";
 | 
			
		||||
      switch(mode){
 | 
			
		||||
        case ABORT_MODE:  //Fall through
 | 
			
		||||
        case COMMAND_MODE:
 | 
			
		||||
          return;
 | 
			
		||||
        case CONNECT_MODE://Fall through
 | 
			
		||||
        case LISTEN_MODE:
 | 
			
		||||
          synchronized(net_lock){
 | 
			
		||||
            if(out == null) return;
 | 
			
		||||
            send(send_string);
 | 
			
		||||
          }
 | 
			
		||||
          break;
 | 
			
		||||
        case UDP_MODE:
 | 
			
		||||
     //     if(!readHost()) return;
 | 
			
		||||
      //    if(!readPort()) return;
 | 
			
		||||
          sendUDP(send_string,host,port);
 | 
			
		||||
          break;
 | 
			
		||||
        default:
 | 
			
		||||
          print("Unknown mode in onInput():"+mode);
 | 
			
		||||
 | 
			
		||||
      }
 | 
			
		||||
      print(send_string);
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   private void onClear(){
 | 
			
		||||
    
 | 
			
		||||
   }
 | 
			
		||||
   private void onProxy(){
 | 
			
		||||
      Proxy p;
 | 
			
		||||
      p = null;//socks_dialog.getProxy(proxy);
 | 
			
		||||
      if(p != null) proxy = p;
 | 
			
		||||
      if( proxy != null && proxy instanceof Socks5Proxy) 
 | 
			
		||||
         ((Socks5Proxy) proxy).resolveAddrLocally(false);
 | 
			
		||||
   }
 | 
			
		||||
   private void onQuit(){
 | 
			
		||||
     
 | 
			
		||||
      System.exit(0);
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
//Data retrieval functions
 | 
			
		||||
//////////////////////////
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
    * Reads the port field, returns false if parsing fails.
 | 
			
		||||
    */
 | 
			
		||||
   private boolean readPort(int newPort){
 | 
			
		||||
      try{
 | 
			
		||||
         port = newPort;
 | 
			
		||||
      }catch(NumberFormatException nfe){
 | 
			
		||||
         warn("Port invalid!");
 | 
			
		||||
         return false;
 | 
			
		||||
      }
 | 
			
		||||
      return true;
 | 
			
		||||
   }
 | 
			
		||||
   private boolean readHost(){
 | 
			
		||||
      host = "";
 | 
			
		||||
      host.trim();
 | 
			
		||||
      if(host.length() < 1){
 | 
			
		||||
        warn("Host is not set");
 | 
			
		||||
        return false;
 | 
			
		||||
      }
 | 
			
		||||
      return true;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
//Display functions
 | 
			
		||||
///////////////////
 | 
			
		||||
 | 
			
		||||
   private void status(String status){
 | 
			
		||||
      
 | 
			
		||||
   }
 | 
			
		||||
   private void println(String s){
 | 
			
		||||
     
 | 
			
		||||
   }
 | 
			
		||||
   private void print(String s){
 | 
			
		||||
  
 | 
			
		||||
   }
 | 
			
		||||
   private void warn(String s){
 | 
			
		||||
      status(s);
 | 
			
		||||
      //System.err.println(s);
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
//Network related functions
 | 
			
		||||
////////////////////////////
 | 
			
		||||
 | 
			
		||||
   private void startNetThread(int m){
 | 
			
		||||
      mode = m;
 | 
			
		||||
      net_thread = new Thread(this);
 | 
			
		||||
      net_thread.start();
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   private void abort_connection(){
 | 
			
		||||
      synchronized(net_lock){ 
 | 
			
		||||
         if(mode == COMMAND_MODE) return;
 | 
			
		||||
         mode = ABORT_MODE;
 | 
			
		||||
         if(net_thread!=null){
 | 
			
		||||
            try{ 
 | 
			
		||||
              if(sock!=null) sock.close();
 | 
			
		||||
              if(server_sock!=null) server_sock.close();
 | 
			
		||||
              if(udp_sock!=null) udp_sock.close();
 | 
			
		||||
            }catch(IOException ioe){
 | 
			
		||||
            }
 | 
			
		||||
            net_thread.interrupt();
 | 
			
		||||
            net_thread = null;
 | 
			
		||||
         }
 | 
			
		||||
      }
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   private void doAccept() throws IOException{
 | 
			
		||||
 | 
			
		||||
     println("Trying to accept from "+host);
 | 
			
		||||
     status("Trying to accept from "+host);
 | 
			
		||||
     println("Using proxy:"+proxy);
 | 
			
		||||
     server_sock = new SocksServerSocket(proxy,host,port);
 | 
			
		||||
 | 
			
		||||
     //server_sock.setSoTimeout(30000);
 | 
			
		||||
 | 
			
		||||
     println("Listenning on: "+server_sock.getInetAddress()+
 | 
			
		||||
                          ":" +server_sock.getLocalPort());
 | 
			
		||||
     sock = server_sock.accept();
 | 
			
		||||
     println("Accepted from:"+sock.getInetAddress()+":"+
 | 
			
		||||
                              sock.getPort());
 | 
			
		||||
 | 
			
		||||
     status("Accepted from:"+sock.getInetAddress().getHostAddress()
 | 
			
		||||
                        +":"+sock.getPort());
 | 
			
		||||
                                           
 | 
			
		||||
     server_sock.close(); //Even though this doesn't do anything
 | 
			
		||||
   }
 | 
			
		||||
   private void doConnect() throws IOException{
 | 
			
		||||
     println("Trying to connect to:"+host+":"+port);
 | 
			
		||||
     println("Using proxy:"+proxy);
 | 
			
		||||
     sock = new SocksSocket(proxy,host,port);
 | 
			
		||||
     println("Connected to:"+sock.getInetAddress()+":"+port);
 | 
			
		||||
     status("Connected to: "+sock.getInetAddress().getHostAddress()
 | 
			
		||||
                       +":" +port);
 | 
			
		||||
     println("Via-Proxy:"+sock.getLocalAddress()+":"+
 | 
			
		||||
                          sock.getLocalPort());
 | 
			
		||||
 | 
			
		||||
   }
 | 
			
		||||
   private void doPipe() throws IOException{
 | 
			
		||||
      out = sock.getOutputStream();
 | 
			
		||||
      in = sock.getInputStream();
 | 
			
		||||
 | 
			
		||||
      byte[] buf = new byte[1024];
 | 
			
		||||
      int bytes_read;
 | 
			
		||||
      while((bytes_read = in.read(buf)) > 0){
 | 
			
		||||
          print(new String(buf,0,bytes_read));
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
   }
 | 
			
		||||
   private void startUDP() throws IOException{
 | 
			
		||||
     udp_sock = new Socks5DatagramSocket(proxy,0,null);
 | 
			
		||||
     println("UDP started on "+udp_sock.getLocalAddress()+":"+
 | 
			
		||||
                               udp_sock.getLocalPort());
 | 
			
		||||
     status("UDP:"+udp_sock.getLocalAddress().getHostAddress()+":"
 | 
			
		||||
                  +udp_sock.getLocalPort());
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   private void doUDPPipe() throws IOException{
 | 
			
		||||
     DatagramPacket dp = new DatagramPacket(new byte[MAX_DATAGRAM_SIZE],
 | 
			
		||||
                                            MAX_DATAGRAM_SIZE);
 | 
			
		||||
     while(true){
 | 
			
		||||
       udp_sock.receive(dp);
 | 
			
		||||
       print("UDP\n"+
 | 
			
		||||
	     "From:"+dp.getAddress()+":"+dp.getPort()+"\n"+
 | 
			
		||||
	     "\n"+
 | 
			
		||||
             //Java 1.2
 | 
			
		||||
             //new String(dp.getData(),dp.getOffset(),dp.getLength())+"\n"
 | 
			
		||||
             //Java 1.1
 | 
			
		||||
             new String(dp.getData(),0,dp.getLength())+"\n"
 | 
			
		||||
            );
 | 
			
		||||
       dp.setLength(MAX_DATAGRAM_SIZE);
 | 
			
		||||
     }
 | 
			
		||||
   }
 | 
			
		||||
   
 | 
			
		||||
   private void sendUDP(String message,String host,int port){
 | 
			
		||||
      if(!udp_sock.isProxyAlive(100)){
 | 
			
		||||
         status("Proxy closed connection");
 | 
			
		||||
         abort_connection();
 | 
			
		||||
         return;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      try{
 | 
			
		||||
         byte[] data = message.getBytes();
 | 
			
		||||
         DatagramPacket dp = new DatagramPacket(data,data.length,null,port);
 | 
			
		||||
         udp_sock.send(dp,host);
 | 
			
		||||
      }catch(UnknownHostException uhe){
 | 
			
		||||
         status("Host "+host+" has no DNS entry.");
 | 
			
		||||
      }catch(IOException ioe){
 | 
			
		||||
         status("IOException:"+ioe);
 | 
			
		||||
         abort_connection();
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   private void send(String s){
 | 
			
		||||
      try{
 | 
			
		||||
        out.write(s.getBytes());
 | 
			
		||||
      }catch(IOException io_ex){
 | 
			
		||||
        println("IOException:"+io_ex);
 | 
			
		||||
        abort_connection();
 | 
			
		||||
      }
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
   
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// Main 
 | 
			
		||||
////////////////////////////////////
 | 
			
		||||
   public static void main(String[] args){
 | 
			
		||||
      SocksEcho socksecho = new SocksEcho();
 | 
			
		||||
    
 | 
			
		||||
   }
 | 
			
		||||
 }//end class
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							| 
						 | 
				
			
			@ -0,0 +1,19 @@
 | 
			
		|||
package net.sourceforge.jsocks;
 | 
			
		||||
 | 
			
		||||
public class SocksServerException extends Exception {
 | 
			
		||||
 | 
			
		||||
  String message;
 | 
			
		||||
 | 
			
		||||
  public SocksServerException(Exception e) {
 | 
			
		||||
    this.message = e.getMessage();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public SocksServerException(String message) {
 | 
			
		||||
    this.message = message;
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  @Override
 | 
			
		||||
  public String getMessage() {
 | 
			
		||||
    return message;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,15 @@
 | 
			
		|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 | 
			
		||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
 | 
			
		||||
<head>
 | 
			
		||||
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
 | 
			
		||||
  <meta http-equiv="Cache-Control" content="no-cache" />
 | 
			
		||||
  <meta http-equiv="Pragma" content="no-cache" />
 | 
			
		||||
  <title>Moma</title>
 | 
			
		||||
 | 
			
		||||
<link href='include_homepage/styles/display_v4.css'
 | 
			
		||||
      type='text/css' rel='stylesheet'></link>
 | 
			
		||||
<link href='include_homepage/styles/themes/bright2.css' type='text/css' rel='stylesheet' />  <style type='text/css'>
 | 
			
		||||
      </style>
 | 
			
		||||
  <script type="text/javascript" 
 | 
			
		||||
          src="include_homepage/scripts/common_v2.js"></script>
 | 
			
		||||
  <
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,34 @@
 | 
			
		|||
package net.sourceforge.jsocks.socks;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 The Authentication interface provides for performing method specific
 | 
			
		||||
 authentication for SOCKS5 connections.
 | 
			
		||||
*/
 | 
			
		||||
public interface Authentication{
 | 
			
		||||
   /**
 | 
			
		||||
     This method is called when SOCKS5 server have selected a particular
 | 
			
		||||
     authentication method, for whch an implementaion have been registered.
 | 
			
		||||
 | 
			
		||||
     <p>
 | 
			
		||||
     This method should return an array {inputstream,outputstream 
 | 
			
		||||
     [,UDPEncapsulation]}. The reason for that is that SOCKS5 protocol
 | 
			
		||||
     allows to have method specific encapsulation of data on the socket for 
 | 
			
		||||
     purposes of integrity or security. And this encapsulation should be 
 | 
			
		||||
     performed by those streams returned from the method. It is also possible
 | 
			
		||||
     to encapsulate datagrams. If authentication method supports such 
 | 
			
		||||
     encapsulation an instance of the UDPEncapsulation interface should be
 | 
			
		||||
     returned as third element of the array, otherwise either null should be
 | 
			
		||||
     returned as third element, or array should contain only 2 elements.
 | 
			
		||||
 | 
			
		||||
     @param methodId Authentication method selected by the server.
 | 
			
		||||
     @param proxySocket Socket used to conect to the proxy.
 | 
			
		||||
     @return Two or three element array containing 
 | 
			
		||||
             Input/Output streams which should be used on this connection.
 | 
			
		||||
             Third argument is optional and should contain an instance
 | 
			
		||||
             of UDPEncapsulation. It should be provided if the authentication
 | 
			
		||||
             method used requires any encapsulation to be done on the
 | 
			
		||||
             datagrams.
 | 
			
		||||
   */
 | 
			
		||||
   Object[] doSocksAuthentication(int methodId,java.net.Socket proxySocket)
 | 
			
		||||
           throws java.io.IOException;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,92 @@
 | 
			
		|||
/*
 | 
			
		||||
 * This library is free software; you can redistribute it and/or
 | 
			
		||||
 * modify it under the terms of the GNU Lesser General Public
 | 
			
		||||
 * License as published by the Free Software Foundation; either
 | 
			
		||||
 * version 2.1 of the License, or (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This library 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
 | 
			
		||||
 * Lesser General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public
 | 
			
		||||
 * License along with this library; if not, write to the Free Software
 | 
			
		||||
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package net.sourceforge.jsocks.socks;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Exception thrown by various socks classes to indicate errors
 | 
			
		||||
 *  with protocol or unsuccessful server responses.
 | 
			
		||||
 *  
 | 
			
		||||
 *  @author rayc@google.com (Ray Colline)
 | 
			
		||||
 */
 | 
			
		||||
public class AuthenticationException extends Throwable {
 | 
			
		||||
  
 | 
			
		||||
   private AuthErrorType errorType;
 | 
			
		||||
   private String errorString;
 | 
			
		||||
    
 | 
			
		||||
   /**
 | 
			
		||||
    * Create an AuthenticationException with the specified type
 | 
			
		||||
    * 
 | 
			
		||||
    * @param errorType an enum denoting what kind of auth error.
 | 
			
		||||
    */
 | 
			
		||||
   public AuthenticationException(AuthErrorType errorType) {
 | 
			
		||||
       this.errorType = errorType;
 | 
			
		||||
       this.errorString = errorType.toString();
 | 
			
		||||
   }
 | 
			
		||||
   
 | 
			
		||||
   /**
 | 
			
		||||
    * Create an AuthenticationException with both the specified type and
 | 
			
		||||
    * a free-form message
 | 
			
		||||
    * 
 | 
			
		||||
    * @param errorType an enum denoting what kind of auth error.
 | 
			
		||||
    * @param errorString a specific string detailing the error.
 | 
			
		||||
    */
 | 
			
		||||
   public AuthenticationException(AuthErrorType errorType, 
 | 
			
		||||
       String errorString) {
 | 
			
		||||
       this.errorType = errorType;
 | 
			
		||||
       this.errorString = errorString;
 | 
			
		||||
   }
 | 
			
		||||
   
 | 
			
		||||
   /**
 | 
			
		||||
    * Get the error type associated with this exception.
 | 
			
		||||
    * 
 | 
			
		||||
    * @return errorType the type associated with this exception.
 | 
			
		||||
    */
 | 
			
		||||
   public AuthErrorType getErrorType() {
 | 
			
		||||
      return errorType;
 | 
			
		||||
   }
 | 
			
		||||
   
 | 
			
		||||
   /**
 | 
			
		||||
    * Get human readable representation of this exception.
 | 
			
		||||
    * 
 | 
			
		||||
    * @return String representation of this exception.
 | 
			
		||||
    */
 | 
			
		||||
   @Override
 | 
			
		||||
   public String toString() {
 | 
			
		||||
      return errorString;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
    * Returns the message associated with this exception
 | 
			
		||||
    * 
 | 
			
		||||
    * @return String the error string.
 | 
			
		||||
    */
 | 
			
		||||
   @Override
 | 
			
		||||
   public String getMessage() {
 | 
			
		||||
     return errorString;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
    * List of Authentication error types.
 | 
			
		||||
    * 
 | 
			
		||||
    * @author rayc@google.com (Ray Colline)
 | 
			
		||||
    */
 | 
			
		||||
   public enum AuthErrorType {
 | 
			
		||||
     MALFORMED_REQUEST,
 | 
			
		||||
     PASSWORD_TOO_LONG;
 | 
			
		||||
   }
 | 
			
		||||
   
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,17 @@
 | 
			
		|||
package net.sourceforge.jsocks.socks;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  SOCKS5 none authentication. Dummy class does almost nothing.
 | 
			
		||||
*/
 | 
			
		||||
public class AuthenticationNone implements Authentication{
 | 
			
		||||
 | 
			
		||||
    public Object[] doSocksAuthentication(int methodId,
 | 
			
		||||
                                          java.net.Socket proxySocket)
 | 
			
		||||
           throws java.io.IOException{
 | 
			
		||||
 | 
			
		||||
       if(methodId!=0) return null;
 | 
			
		||||
 | 
			
		||||
       return new Object[] { proxySocket.getInputStream(),
 | 
			
		||||
                             proxySocket.getOutputStream()};
 | 
			
		||||
   }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,442 @@
 | 
			
		|||
package net.sourceforge.jsocks.socks;
 | 
			
		||||
 | 
			
		||||
import java.net.InetAddress;
 | 
			
		||||
import java.net.UnknownHostException;
 | 
			
		||||
import java.util.*;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Class InetRange provides the means of defining the range of inetaddresses.
 | 
			
		||||
 * It's used by Proxy class to store and look up addresses of machines, that
 | 
			
		||||
 * should be contacted directly rather then through the proxy.
 | 
			
		||||
 * <P>
 | 
			
		||||
 * InetRange provides several methods to add either standalone addresses, or
 | 
			
		||||
 * ranges (e.g. 100.200.300.0:100.200.300.255, which covers all addresses
 | 
			
		||||
 * on on someones local network). It also provides methods for checking wether
 | 
			
		||||
 * given address is in this range. Any number of ranges and standalone 
 | 
			
		||||
 * addresses can be added to the range.
 | 
			
		||||
 */
 | 
			
		||||
public class InetRange implements Cloneable{
 | 
			
		||||
 | 
			
		||||
    Hashtable host_names;
 | 
			
		||||
    Vector all;
 | 
			
		||||
    Vector end_names;
 | 
			
		||||
 | 
			
		||||
    boolean useSeparateThread = true;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Creates the empty range.
 | 
			
		||||
     */
 | 
			
		||||
    public InetRange(){
 | 
			
		||||
      all = new Vector();
 | 
			
		||||
      host_names = new Hashtable();
 | 
			
		||||
      end_names = new Vector();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     *  Adds another host or range to this range.
 | 
			
		||||
        The String can be one of those:
 | 
			
		||||
        <UL>
 | 
			
		||||
        <li> Host name. eg.(Athena.myhost.com or 45.54.56.65)
 | 
			
		||||
        
 | 
			
		||||
        <li> Range in the form .myhost.net.au <BR>
 | 
			
		||||
             In which case anything that ends with .myhost.net.au will
 | 
			
		||||
             be considered in the range.
 | 
			
		||||
 | 
			
		||||
        <li> Range in the form ddd.ddd.ddd. <BR>
 | 
			
		||||
             This will be treated as range ddd.ddd.ddd.0 to ddd.ddd.ddd.255.
 | 
			
		||||
             It is not necessary to specify 3 first bytes you can use just 
 | 
			
		||||
             one or two. For example 130. will cover address between 130.0.0.0
 | 
			
		||||
             and 13.255.255.255.
 | 
			
		||||
 | 
			
		||||
        <li> Range in the form host_from[: \t\n\r\f]host_to. <br>
 | 
			
		||||
             That is two hostnames or ips separated by either whitespace 
 | 
			
		||||
             or colon.
 | 
			
		||||
        </UL>
 | 
			
		||||
     */
 | 
			
		||||
    public synchronized boolean add(String s){
 | 
			
		||||
      if(s == null) return false;
 | 
			
		||||
 | 
			
		||||
      s = s.trim();
 | 
			
		||||
      if(s.length() == 0) return false;
 | 
			
		||||
 | 
			
		||||
      Object[] entry;
 | 
			
		||||
 | 
			
		||||
      if(s.charAt(s.length()-1) == '.'){
 | 
			
		||||
         //thing like: 111.222.33. 
 | 
			
		||||
         //it is being treated as range 111.222.33.000 - 111.222.33.255
 | 
			
		||||
 | 
			
		||||
         int[] addr = ip2intarray(s);
 | 
			
		||||
         long from,to;
 | 
			
		||||
         from = to = 0;
 | 
			
		||||
 | 
			
		||||
         if(addr == null) return false;
 | 
			
		||||
         for(int i = 0; i< 4;++i){
 | 
			
		||||
            if(addr[i]>=0)
 | 
			
		||||
              from += (((long)addr[i]) << 8*(3-i));
 | 
			
		||||
            else{
 | 
			
		||||
              to = from;
 | 
			
		||||
              while(i<4)
 | 
			
		||||
                to += 255l << 8*(3-i++);
 | 
			
		||||
              break;
 | 
			
		||||
            }
 | 
			
		||||
         }
 | 
			
		||||
         entry = new Object[] {s,null,new Long(from),new Long(to)};
 | 
			
		||||
         all.addElement(entry);
 | 
			
		||||
 | 
			
		||||
      }else if(s.charAt(0) == '.'){
 | 
			
		||||
         //Thing like: .myhost.com
 | 
			
		||||
 | 
			
		||||
         end_names.addElement(s);
 | 
			
		||||
         all.addElement(new Object[]{s,null,null,null});
 | 
			
		||||
      }else{
 | 
			
		||||
         StringTokenizer tokens = new StringTokenizer(s," \t\r\n\f:");
 | 
			
		||||
         if(tokens.countTokens() > 1){
 | 
			
		||||
           entry = new Object[] {s,null,null,null};
 | 
			
		||||
           resolve(entry,tokens.nextToken(),tokens.nextToken());
 | 
			
		||||
           all.addElement(entry);
 | 
			
		||||
         }else{
 | 
			
		||||
           entry = new Object[] {s,null,null,null};
 | 
			
		||||
           all.addElement(entry);
 | 
			
		||||
           host_names.put(s,entry);
 | 
			
		||||
           resolve(entry);
 | 
			
		||||
         }
 | 
			
		||||
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     *  Adds another ip for this range.
 | 
			
		||||
        @param ip IP os the host which should be added to this range.
 | 
			
		||||
     */
 | 
			
		||||
    public synchronized void add(InetAddress ip){
 | 
			
		||||
       long from, to;
 | 
			
		||||
       from = to = ip2long(ip);
 | 
			
		||||
       all.addElement(new Object[]{ip.getHostName(),ip,new Long(from),
 | 
			
		||||
                                                       new Long(to)});
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     *  Adds another range of ips for this range.Any host with ip address
 | 
			
		||||
        greater than or equal to the address of from and smaller than or equal
 | 
			
		||||
        to the address of to will be included in the range.
 | 
			
		||||
        @param from IP from where range starts(including).
 | 
			
		||||
        @param to   IP where range ends(including).
 | 
			
		||||
     */
 | 
			
		||||
    public synchronized void add(InetAddress from,InetAddress to){
 | 
			
		||||
       all.addElement(new Object[]{from.getHostAddress()+":"+to.getHostAddress()
 | 
			
		||||
                            ,null,new Long(ip2long(from)),
 | 
			
		||||
                                  new Long(ip2long(to))});
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Checks wether the givan host is in the range. Attempts to resolve
 | 
			
		||||
       host name if required.
 | 
			
		||||
       @param host Host name to check.
 | 
			
		||||
       @return true If host is in the range, false otherwise.
 | 
			
		||||
     * @see InetRange#contains(String,boolean)
 | 
			
		||||
     */
 | 
			
		||||
    public synchronized boolean contains(String host){
 | 
			
		||||
       return contains(host,true);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     *  Checks wether the given host is in the range.
 | 
			
		||||
     *  <P>
 | 
			
		||||
     *  Algorithm: <BR>
 | 
			
		||||
     *  <ol>
 | 
			
		||||
     *  <li>Look up if the hostname is in the range (in the Hashtable).
 | 
			
		||||
     *  <li>Check if it ends with one of the speciefied endings.
 | 
			
		||||
     *  <li>Check if it is ip(eg.130.220.35.98). If it is check if it is
 | 
			
		||||
     *      in the range.
 | 
			
		||||
     *  <li>If attemptResolve is true, host is name, rather than ip, and
 | 
			
		||||
     *      all previous attempts failed, try to resolve the hostname, and
 | 
			
		||||
     *      check wether the ip associated with the host is in the range.It
 | 
			
		||||
     *      also repeats all previos steps with the hostname obtained from
 | 
			
		||||
     *      InetAddress, but the name is not allways the full name,it is 
 | 
			
		||||
     *      quite likely to be the same. Well it was on my machine.
 | 
			
		||||
     *  </ol>
 | 
			
		||||
       @param host Host name to check.
 | 
			
		||||
       @param attemptResolve Wether to lookup ip address which corresponds
 | 
			
		||||
       to the host,if required.
 | 
			
		||||
       @return true If host is in the range, false otherwise.
 | 
			
		||||
     */
 | 
			
		||||
    public synchronized boolean contains(String host,boolean attemptResolve){
 | 
			
		||||
       if(all.size() ==0) return false; //Empty range
 | 
			
		||||
 | 
			
		||||
       host = host.trim();
 | 
			
		||||
       if(host.length() == 0) return false;
 | 
			
		||||
 | 
			
		||||
       if(checkHost(host)) return true;
 | 
			
		||||
       if(checkHostEnding(host)) return true;
 | 
			
		||||
 | 
			
		||||
       long l = host2long(host);
 | 
			
		||||
       if(l >=0) return contains(l);
 | 
			
		||||
 | 
			
		||||
       if(!attemptResolve) return false;
 | 
			
		||||
 | 
			
		||||
       try{
 | 
			
		||||
          InetAddress ip = InetAddress.getByName(host);
 | 
			
		||||
          return contains(ip);
 | 
			
		||||
       }catch(UnknownHostException uhe){
 | 
			
		||||
 | 
			
		||||
       }
 | 
			
		||||
 | 
			
		||||
       return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Checks wether the given ip is in the range.
 | 
			
		||||
       @param ip Address of the host to check.
 | 
			
		||||
       @return true If host is in the range, false otherwise.
 | 
			
		||||
     */
 | 
			
		||||
    public synchronized boolean contains(InetAddress ip){
 | 
			
		||||
       if(checkHostEnding(ip.getHostName())) return true;
 | 
			
		||||
       if(checkHost(ip.getHostName())) return true;
 | 
			
		||||
       return contains(ip2long(ip));
 | 
			
		||||
    }
 | 
			
		||||
    /**
 | 
			
		||||
       Get all entries in the range as strings. <BR>
 | 
			
		||||
       These strings can be used to delete entries from the range
 | 
			
		||||
       with remove function.
 | 
			
		||||
       @return Array of entries as strings.
 | 
			
		||||
       @see InetRange#remove(String)
 | 
			
		||||
     */
 | 
			
		||||
    public synchronized String[] getAll(){
 | 
			
		||||
       int size = all.size();
 | 
			
		||||
       Object entry[];
 | 
			
		||||
       String all_names[] = new String[size];
 | 
			
		||||
 | 
			
		||||
       for(int i=0;i<size;++i){
 | 
			
		||||
          entry = (Object[]) all.elementAt(i);
 | 
			
		||||
          all_names[i] = (String) entry[0];
 | 
			
		||||
       }
 | 
			
		||||
       return all_names;
 | 
			
		||||
    }
 | 
			
		||||
    /**
 | 
			
		||||
      Removes an entry from this range.<BR>
 | 
			
		||||
      @param s Entry to remove.
 | 
			
		||||
      @return true if successfull.
 | 
			
		||||
     */
 | 
			
		||||
    public synchronized boolean remove(String s){
 | 
			
		||||
      Iterator iterator = all.iterator();
 | 
			
		||||
      
 | 
			
		||||
      while(iterator.hasNext()){
 | 
			
		||||
        Object[] entry = (Object[]) iterator.next();
 | 
			
		||||
        if(s.equals(entry[0])){
 | 
			
		||||
          all.removeElement(entry);
 | 
			
		||||
          end_names.removeElement(s);
 | 
			
		||||
          host_names.remove(s);
 | 
			
		||||
          return true;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Get string representaion of this Range.*/
 | 
			
		||||
    public String toString(){
 | 
			
		||||
       String all[] = getAll();
 | 
			
		||||
       if(all.length == 0) return "";
 | 
			
		||||
 | 
			
		||||
       String s = all[0];
 | 
			
		||||
       for(int i=1;i<all.length;++i)
 | 
			
		||||
          s += "; "+all[i];
 | 
			
		||||
       return s;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Creates a clone of this Object*/
 | 
			
		||||
    public Object clone(){
 | 
			
		||||
      InetRange new_range = new InetRange();
 | 
			
		||||
      new_range.all = (Vector)all.clone();
 | 
			
		||||
      new_range.end_names = (Vector) end_names.clone();
 | 
			
		||||
      new_range.host_names = (Hashtable)host_names.clone();
 | 
			
		||||
      return new_range;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//Private methods
 | 
			
		||||
/////////////////
 | 
			
		||||
    /**
 | 
			
		||||
     * Same as previous but used internally, to avoid
 | 
			
		||||
     * unnecessary convertion of IPs, when checking subranges
 | 
			
		||||
     */
 | 
			
		||||
    private synchronized boolean contains(long ip){
 | 
			
		||||
       Iterator iterator = all.iterator();
 | 
			
		||||
       while(iterator.hasNext()){
 | 
			
		||||
         Object[] obj = (Object[]) iterator.next();
 | 
			
		||||
         Long from = obj[2]==null?null:(Long)obj[2];
 | 
			
		||||
         Long to   = obj[3]==null?null:(Long)obj[3];
 | 
			
		||||
         if(from != null && from.longValue()<= ip 
 | 
			
		||||
                         && to.longValue() >= ip) return true;
 | 
			
		||||
 | 
			
		||||
       }
 | 
			
		||||
       return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private boolean checkHost(String host){
 | 
			
		||||
       return host_names.containsKey(host);
 | 
			
		||||
    }
 | 
			
		||||
    private boolean checkHostEnding(String host){
 | 
			
		||||
       Iterator iterator = end_names.iterator();
 | 
			
		||||
       while(iterator.hasNext()){
 | 
			
		||||
          if(host.endsWith((String) iterator.next())) return true;
 | 
			
		||||
       }
 | 
			
		||||
       return false;
 | 
			
		||||
    }
 | 
			
		||||
    private void resolve(Object[] entry){
 | 
			
		||||
       //First check if it's in the form ddd.ddd.ddd.ddd.
 | 
			
		||||
       long ip = host2long((String) entry[0]);
 | 
			
		||||
       if(ip >= 0){
 | 
			
		||||
         entry[2] = entry[3] = new Long(ip);
 | 
			
		||||
       }else{
 | 
			
		||||
         InetRangeResolver res = new InetRangeResolver(entry);
 | 
			
		||||
         res.resolve(useSeparateThread);
 | 
			
		||||
       }
 | 
			
		||||
    }
 | 
			
		||||
    private void resolve(Object[] entry,String from,String to){
 | 
			
		||||
       long f,t;
 | 
			
		||||
       if((f=host2long(from))>= 0 && (t=host2long(to)) >= 0){
 | 
			
		||||
         entry[2] = new Long(f);
 | 
			
		||||
         entry[3] = new Long(t);
 | 
			
		||||
       }else{
 | 
			
		||||
         InetRangeResolver res = new InetRangeResolver(entry,from,to);
 | 
			
		||||
         res.resolve(useSeparateThread);
 | 
			
		||||
       }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//Class methods
 | 
			
		||||
///////////////
 | 
			
		||||
 | 
			
		||||
    //Converts ipv4 to long value(unsigned int)
 | 
			
		||||
    ///////////////////////////////////////////
 | 
			
		||||
    static long ip2long(InetAddress ip){
 | 
			
		||||
        long l=0;
 | 
			
		||||
        byte[] addr = ip.getAddress();
 | 
			
		||||
 | 
			
		||||
        if(addr.length ==4){ //IPV4
 | 
			
		||||
          for(int i=0;i<4;++i)
 | 
			
		||||
             l += (((long)addr[i] &0xFF) << 8*(3-i));
 | 
			
		||||
        }else{ //IPV6
 | 
			
		||||
          return 0;  //Have no idea how to deal with those
 | 
			
		||||
        }
 | 
			
		||||
        return l;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    long host2long(String host){
 | 
			
		||||
      long ip=0;
 | 
			
		||||
 | 
			
		||||
      //check if it's ddd.ddd.ddd.ddd
 | 
			
		||||
      if(!Character.isDigit(host.charAt(0))) return -1;
 | 
			
		||||
 | 
			
		||||
      int[] addr = ip2intarray(host); 
 | 
			
		||||
      if(addr == null) return -1;
 | 
			
		||||
 | 
			
		||||
      for(int i=0;i<addr.length;++i)
 | 
			
		||||
          ip += ((long)(addr[i]>=0 ? addr[i] : 0)) << 8*(3-i);
 | 
			
		||||
 | 
			
		||||
      return ip;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    static int[] ip2intarray(String host){
 | 
			
		||||
       int[] address = {-1,-1,-1,-1};
 | 
			
		||||
       int i=0;
 | 
			
		||||
       StringTokenizer tokens = new StringTokenizer(host,".");
 | 
			
		||||
       if(tokens.countTokens() > 4) return null;
 | 
			
		||||
       while(tokens.hasMoreTokens()){
 | 
			
		||||
         try{
 | 
			
		||||
           address[i++] = Integer.parseInt(tokens.nextToken()) & 0xFF;
 | 
			
		||||
         }catch(NumberFormatException nfe){
 | 
			
		||||
            return null;
 | 
			
		||||
         }
 | 
			
		||||
 | 
			
		||||
       }
 | 
			
		||||
       return address;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
//* This was the test main function
 | 
			
		||||
//**********************************
 | 
			
		||||
 
 | 
			
		||||
    public static void main(String args[])throws UnknownHostException{
 | 
			
		||||
       int i;
 | 
			
		||||
 | 
			
		||||
       InetRange ir = new InetRange();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
       for(i=0;i<args.length;++i){
 | 
			
		||||
         System.out.println("Adding:" + args[i]);
 | 
			
		||||
         ir.add(args[i]);
 | 
			
		||||
       }
 | 
			
		||||
 | 
			
		||||
       String host;
 | 
			
		||||
       java.io.DataInputStream din = new java.io.DataInputStream(System.in);
 | 
			
		||||
       try{
 | 
			
		||||
          host = din.readLine();
 | 
			
		||||
          while(host!=null){
 | 
			
		||||
            if(ir.contains(host)){
 | 
			
		||||
              System.out.println("Range contains ip:"+host);
 | 
			
		||||
            }else{
 | 
			
		||||
              System.out.println(host+" is not in the range");
 | 
			
		||||
            }
 | 
			
		||||
            host = din.readLine();
 | 
			
		||||
          }
 | 
			
		||||
       }catch(java.io.IOException io_ex){
 | 
			
		||||
          io_ex.printStackTrace();
 | 
			
		||||
       }
 | 
			
		||||
    }
 | 
			
		||||
********************/
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class InetRangeResolver implements Runnable{
 | 
			
		||||
 | 
			
		||||
   Object[] entry;
 | 
			
		||||
 | 
			
		||||
   String from, to;
 | 
			
		||||
 | 
			
		||||
   InetRangeResolver(Object[] entry){
 | 
			
		||||
      this.entry = entry;
 | 
			
		||||
      from = to = null;
 | 
			
		||||
   }
 | 
			
		||||
   InetRangeResolver(Object[] entry,String from,String to){
 | 
			
		||||
      this.entry = entry;
 | 
			
		||||
      this.from  = from;
 | 
			
		||||
      this.to    = to;
 | 
			
		||||
   }
 | 
			
		||||
   public final void resolve(){
 | 
			
		||||
     resolve(true);
 | 
			
		||||
   }
 | 
			
		||||
   public final void resolve(boolean inSeparateThread){
 | 
			
		||||
     if(inSeparateThread){
 | 
			
		||||
       Thread t = new Thread(this);
 | 
			
		||||
       t.start();
 | 
			
		||||
     }else
 | 
			
		||||
       run();
 | 
			
		||||
 | 
			
		||||
   }
 | 
			
		||||
   public void run(){
 | 
			
		||||
     try{
 | 
			
		||||
        if(from == null){
 | 
			
		||||
          InetAddress ip = InetAddress.getByName((String) entry[0]);
 | 
			
		||||
          entry[1] = ip;
 | 
			
		||||
          Long l = new Long(InetRange.ip2long(ip));
 | 
			
		||||
          entry[2] = entry[3] = l;
 | 
			
		||||
        }else{
 | 
			
		||||
          InetAddress f = InetAddress.getByName(from);
 | 
			
		||||
          InetAddress t = InetAddress.getByName(to);
 | 
			
		||||
          entry[2] = new Long(InetRange.ip2long(f));
 | 
			
		||||
          entry[3] = new Long(InetRange.ip2long(t));
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
     }catch(UnknownHostException uhe){
 | 
			
		||||
        //System.err.println("Resolve failed for "+from+','+to+','+entry[0]);
 | 
			
		||||
     }
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,491 @@
 | 
			
		|||
package net.sourceforge.jsocks.socks;
 | 
			
		||||
 | 
			
		||||
import java.net.InetAddress;
 | 
			
		||||
import java.net.Socket;
 | 
			
		||||
import java.net.UnknownHostException;
 | 
			
		||||
import java.io.*;
 | 
			
		||||
 | 
			
		||||
import net.*;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  Abstract class Proxy, base for classes Socks4Proxy and Socks5Proxy.
 | 
			
		||||
  Defines methods for specifying default proxy, to be
 | 
			
		||||
  used by all classes of this package.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
public abstract class Proxy{
 | 
			
		||||
 | 
			
		||||
//Data members
 | 
			
		||||
   protected InetRange directHosts = new InetRange();
 | 
			
		||||
 | 
			
		||||
   protected InetAddress proxyIP = null;
 | 
			
		||||
   protected String proxyHost = null;
 | 
			
		||||
   protected int proxyPort;
 | 
			
		||||
   protected Socket proxySocket = null;
 | 
			
		||||
 | 
			
		||||
   protected InputStream in;
 | 
			
		||||
   protected OutputStream out;
 | 
			
		||||
 | 
			
		||||
   protected int version;
 | 
			
		||||
 | 
			
		||||
   protected Proxy chainProxy = null;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//Protected static/class variables
 | 
			
		||||
   protected static Proxy defaultProxy = null;
 | 
			
		||||
 | 
			
		||||
//Constructors
 | 
			
		||||
//====================
 | 
			
		||||
   Proxy(Proxy chainProxy,
 | 
			
		||||
         String proxyHost,int proxyPort)throws UnknownHostException{ 
 | 
			
		||||
      this.chainProxy = chainProxy;
 | 
			
		||||
      this.proxyHost = proxyHost;
 | 
			
		||||
 | 
			
		||||
      if(chainProxy == null)
 | 
			
		||||
         this.proxyIP   = InetAddress.getByName(proxyHost);
 | 
			
		||||
      
 | 
			
		||||
      this.proxyPort = proxyPort;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
  
 | 
			
		||||
   Proxy(String proxyHost,int proxyPort)throws UnknownHostException{ 
 | 
			
		||||
      this(null,proxyHost,proxyPort);
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   Proxy(Proxy chainProxy,InetAddress proxyIP,int proxyPort){
 | 
			
		||||
      this.chainProxy = chainProxy;
 | 
			
		||||
      this.proxyIP = proxyIP;
 | 
			
		||||
      this.proxyPort = proxyPort;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   Proxy(InetAddress proxyIP,int proxyPort){
 | 
			
		||||
      this(null,proxyIP,proxyPort);
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   Proxy(Proxy p){
 | 
			
		||||
      this.proxyIP = p.proxyIP;
 | 
			
		||||
      this.proxyPort = p.proxyPort;
 | 
			
		||||
      this.version = p.version;
 | 
			
		||||
      this.directHosts = p.directHosts;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
//Public instance methods
 | 
			
		||||
//========================
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
      Get the port on which proxy server is running.
 | 
			
		||||
    * @return Proxy port.
 | 
			
		||||
    */
 | 
			
		||||
   public int getPort(){
 | 
			
		||||
     return proxyPort;
 | 
			
		||||
   }
 | 
			
		||||
   /**
 | 
			
		||||
      Get the ip address of the proxy server host.
 | 
			
		||||
    * @return Proxy InetAddress.
 | 
			
		||||
    */
 | 
			
		||||
   public InetAddress getInetAddress(){
 | 
			
		||||
     return proxyIP;
 | 
			
		||||
   }
 | 
			
		||||
   /**
 | 
			
		||||
    * Adds given ip to the list of direct addresses.
 | 
			
		||||
    * This machine will be accessed without using proxy.
 | 
			
		||||
    */
 | 
			
		||||
   public void addDirect(InetAddress ip){
 | 
			
		||||
      directHosts.add(ip);
 | 
			
		||||
   }
 | 
			
		||||
   /**
 | 
			
		||||
    * Adds host to the list of direct addresses.
 | 
			
		||||
    * This machine will be accessed without using proxy.
 | 
			
		||||
    */
 | 
			
		||||
   public boolean addDirect(String host){
 | 
			
		||||
      return directHosts.add(host);
 | 
			
		||||
   }
 | 
			
		||||
   /**
 | 
			
		||||
    * Adds given range of addresses to the lsit of direct addresses,
 | 
			
		||||
    * machines within this range will be accessed without using proxy.
 | 
			
		||||
    */
 | 
			
		||||
   public void addDirect(InetAddress from,InetAddress to){
 | 
			
		||||
      directHosts.add(from,to);
 | 
			
		||||
   }
 | 
			
		||||
   /**
 | 
			
		||||
    * Sets given InetRange as the list of direct address, previous
 | 
			
		||||
    * list will be discarded, any changes done previously with
 | 
			
		||||
    * addDirect(Inetaddress) will be lost.
 | 
			
		||||
    * The machines in this range will be accessed without using proxy.
 | 
			
		||||
    * @param ir InetRange which should be used to look up direct addresses.
 | 
			
		||||
    * @see InetRange
 | 
			
		||||
    */
 | 
			
		||||
   public void setDirect(InetRange ir){
 | 
			
		||||
     directHosts = ir;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
      Get the list of direct hosts.
 | 
			
		||||
    * @return Current range of direct address as InetRange object.
 | 
			
		||||
    * @see InetRange
 | 
			
		||||
    */
 | 
			
		||||
   public InetRange getDirect(){
 | 
			
		||||
     return directHosts;
 | 
			
		||||
   }
 | 
			
		||||
   /**
 | 
			
		||||
      Check wether the given host is on the list of direct address.
 | 
			
		||||
      @param host Host name to check.
 | 
			
		||||
    * @return true if the given host is specified as the direct addresses.
 | 
			
		||||
    */
 | 
			
		||||
    public boolean isDirect(String host){
 | 
			
		||||
        return directHosts.contains(host);
 | 
			
		||||
    }
 | 
			
		||||
   /**
 | 
			
		||||
      Check wether the given host is on the list of direct addresses.
 | 
			
		||||
      @param host Host address to check.
 | 
			
		||||
    * @return true if the given host is specified as the direct address.
 | 
			
		||||
    */
 | 
			
		||||
    public boolean isDirect(InetAddress host){
 | 
			
		||||
        return directHosts.contains(host);
 | 
			
		||||
    }
 | 
			
		||||
    /**
 | 
			
		||||
      Set the proxy which should be used to connect to given proxy.
 | 
			
		||||
      @param chainProxy Proxy to use to connect to this proxy.
 | 
			
		||||
    */
 | 
			
		||||
    public void setChainProxy(Proxy chainProxy){
 | 
			
		||||
        this.chainProxy = chainProxy;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    /**
 | 
			
		||||
      Get proxy which is used to connect to this proxy.
 | 
			
		||||
      @return Proxy which is used to connect to this proxy, or null
 | 
			
		||||
              if proxy is to be contacted directly.
 | 
			
		||||
    */
 | 
			
		||||
    public Proxy getChainProxy(){
 | 
			
		||||
       return chainProxy;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
       Get string representation of this proxy.
 | 
			
		||||
     * @returns string in the form:proxyHost:proxyPort \t Version versionNumber
 | 
			
		||||
     */
 | 
			
		||||
    public String toString(){
 | 
			
		||||
       return (""+proxyIP.getHostName()+":"+proxyPort+"\tVersion "+version);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//Public Static(Class) Methods
 | 
			
		||||
//==============================
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
    * Sets SOCKS4 proxy as default.
 | 
			
		||||
      @param hostName Host name on which SOCKS4 server is running.
 | 
			
		||||
      @param port Port on which SOCKS4 server is running.
 | 
			
		||||
      @param user Username to use for communications with proxy.
 | 
			
		||||
    */
 | 
			
		||||
   public static void setDefaultProxy(String hostName,int port,String user)
 | 
			
		||||
                             throws UnknownHostException{
 | 
			
		||||
      defaultProxy = new Socks4Proxy(hostName,port,user);
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
    * Sets SOCKS4 proxy as default.
 | 
			
		||||
      @param ipAddress Host address on which SOCKS4 server is running.
 | 
			
		||||
      @param port Port on which SOCKS4 server is running.
 | 
			
		||||
      @param user Username to use for communications with proxy.
 | 
			
		||||
    */
 | 
			
		||||
   public static void setDefaultProxy(InetAddress ipAddress,int port,
 | 
			
		||||
                                      String user){
 | 
			
		||||
      defaultProxy = new Socks4Proxy(ipAddress,port,user);
 | 
			
		||||
   }
 | 
			
		||||
   /**
 | 
			
		||||
    * Sets SOCKS5 proxy as default.
 | 
			
		||||
    * Default proxy only supports no-authentication.
 | 
			
		||||
      @param hostName Host name on which SOCKS5 server is running.
 | 
			
		||||
      @param port Port on which SOCKS5 server is running.
 | 
			
		||||
    */
 | 
			
		||||
   public static void setDefaultProxy(String hostName,int port)
 | 
			
		||||
                             throws UnknownHostException{
 | 
			
		||||
      defaultProxy = new Socks5Proxy(hostName,port);
 | 
			
		||||
   }
 | 
			
		||||
   /**
 | 
			
		||||
    * Sets SOCKS5 proxy as default.
 | 
			
		||||
    * Default proxy only supports no-authentication.
 | 
			
		||||
      @param ipAddress Host address on which SOCKS5 server is running.
 | 
			
		||||
      @param port Port on which SOCKS5 server is running.
 | 
			
		||||
    */
 | 
			
		||||
   public static void setDefaultProxy(InetAddress ipAddress,int port){
 | 
			
		||||
      defaultProxy = new Socks5Proxy(ipAddress,port);
 | 
			
		||||
   }
 | 
			
		||||
   /**
 | 
			
		||||
    * Sets default proxy.
 | 
			
		||||
      @param p Proxy to use as default proxy.
 | 
			
		||||
    */
 | 
			
		||||
   public static void setDefaultProxy(Proxy p){
 | 
			
		||||
     defaultProxy = p;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
      Get current default proxy.
 | 
			
		||||
    * @return Current default proxy, or null if none is set.
 | 
			
		||||
    */
 | 
			
		||||
   public static Proxy getDefaultProxy(){
 | 
			
		||||
     return defaultProxy;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
     Parses strings in the form: host[:port:user:password], and creates
 | 
			
		||||
     proxy from information obtained from parsing.
 | 
			
		||||
     <p>
 | 
			
		||||
     Defaults: port = 1080.<br>
 | 
			
		||||
     If user specified but not password, creates Socks4Proxy, if user
 | 
			
		||||
     not specified creates Socks5Proxy, if both user and password are
 | 
			
		||||
     speciefied creates Socks5Proxy with user/password authentication.
 | 
			
		||||
     @param proxy_entry String in the form host[:port:user:password]
 | 
			
		||||
     @return Proxy created from the string, null if entry was somehow
 | 
			
		||||
             invalid(host unknown for example, or empty string)
 | 
			
		||||
   */
 | 
			
		||||
   public static Proxy parseProxy(String proxy_entry){
 | 
			
		||||
 | 
			
		||||
      String proxy_host;
 | 
			
		||||
      int proxy_port = 1080;
 | 
			
		||||
      String proxy_user = null;
 | 
			
		||||
      String proxy_password = null;
 | 
			
		||||
      Proxy proxy;
 | 
			
		||||
 | 
			
		||||
      java.util.StringTokenizer st = new java.util.StringTokenizer(
 | 
			
		||||
                                         proxy_entry,":");
 | 
			
		||||
      if(st.countTokens() < 1) return null;
 | 
			
		||||
 | 
			
		||||
      proxy_host = st.nextToken();
 | 
			
		||||
      if(st.hasMoreTokens())
 | 
			
		||||
         try{
 | 
			
		||||
           proxy_port = Integer.parseInt(st.nextToken().trim());
 | 
			
		||||
         }catch(NumberFormatException nfe){}
 | 
			
		||||
 | 
			
		||||
      if(st.hasMoreTokens())
 | 
			
		||||
         proxy_user = st.nextToken();
 | 
			
		||||
 | 
			
		||||
      if(st.hasMoreTokens())
 | 
			
		||||
         proxy_password = st.nextToken();
 | 
			
		||||
 | 
			
		||||
      try{
 | 
			
		||||
         if(proxy_user == null)
 | 
			
		||||
           proxy = new Socks5Proxy(proxy_host,proxy_port);
 | 
			
		||||
         else if(proxy_password == null)
 | 
			
		||||
           proxy = new Socks4Proxy(proxy_host,proxy_port,proxy_user);
 | 
			
		||||
         else{
 | 
			
		||||
           proxy = new Socks5Proxy(proxy_host,proxy_port);
 | 
			
		||||
           UserPasswordAuthentication upa = new UserPasswordAuthentication(
 | 
			
		||||
                                            proxy_user, proxy_password);
 | 
			
		||||
 | 
			
		||||
           ((Socks5Proxy)proxy).setAuthenticationMethod(upa.METHOD_ID,upa);
 | 
			
		||||
         }
 | 
			
		||||
      }catch(UnknownHostException uhe){
 | 
			
		||||
         return null;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      return proxy;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//Protected Methods
 | 
			
		||||
//=================
 | 
			
		||||
 | 
			
		||||
   protected void startSession()throws SocksException{
 | 
			
		||||
       try{
 | 
			
		||||
         if(chainProxy == null)
 | 
			
		||||
            proxySocket = new Socket(proxyIP,proxyPort);
 | 
			
		||||
         else if(proxyIP != null)
 | 
			
		||||
            proxySocket = new SocksSocket(chainProxy,proxyIP,proxyPort);
 | 
			
		||||
         else
 | 
			
		||||
            proxySocket = new SocksSocket(chainProxy,proxyHost,proxyPort);
 | 
			
		||||
 | 
			
		||||
         in = proxySocket.getInputStream();
 | 
			
		||||
         out = proxySocket.getOutputStream();
 | 
			
		||||
       }catch(SocksException se){
 | 
			
		||||
         throw se;
 | 
			
		||||
       }catch(IOException io_ex){
 | 
			
		||||
         throw new SocksException(SOCKS_PROXY_IO_ERROR,""+io_ex);
 | 
			
		||||
       }
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   protected abstract Proxy copy();
 | 
			
		||||
   protected abstract ProxyMessage formMessage(int cmd,InetAddress ip,int port);
 | 
			
		||||
   protected abstract ProxyMessage formMessage(int cmd,String host,int port)
 | 
			
		||||
             throws UnknownHostException;
 | 
			
		||||
   protected abstract ProxyMessage formMessage(InputStream in)
 | 
			
		||||
             throws SocksException,
 | 
			
		||||
                    IOException;
 | 
			
		||||
   
 | 
			
		||||
 | 
			
		||||
   protected ProxyMessage connect(InetAddress ip,int port)
 | 
			
		||||
             throws SocksException{
 | 
			
		||||
      try{
 | 
			
		||||
         startSession();
 | 
			
		||||
         ProxyMessage request  = formMessage(SOCKS_CMD_CONNECT,
 | 
			
		||||
			                     ip,port);
 | 
			
		||||
         return exchange(request);
 | 
			
		||||
      }catch(SocksException se){
 | 
			
		||||
         endSession();
 | 
			
		||||
         throw se;
 | 
			
		||||
      }
 | 
			
		||||
   }
 | 
			
		||||
   protected ProxyMessage connect(String host,int port)
 | 
			
		||||
             throws UnknownHostException,SocksException{
 | 
			
		||||
      try{
 | 
			
		||||
         startSession();
 | 
			
		||||
         ProxyMessage request  = formMessage(SOCKS_CMD_CONNECT,
 | 
			
		||||
			                     host,port);
 | 
			
		||||
         return exchange(request);
 | 
			
		||||
      }catch(SocksException se){
 | 
			
		||||
         endSession();
 | 
			
		||||
         throw se;
 | 
			
		||||
      }
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   protected ProxyMessage bind(InetAddress ip,int port)
 | 
			
		||||
             throws SocksException{
 | 
			
		||||
      try{
 | 
			
		||||
         startSession();
 | 
			
		||||
         ProxyMessage request  = formMessage(SOCKS_CMD_BIND,
 | 
			
		||||
				             ip,port);
 | 
			
		||||
         return exchange(request);
 | 
			
		||||
      }catch(SocksException se){
 | 
			
		||||
         endSession();
 | 
			
		||||
         throw se;
 | 
			
		||||
      }
 | 
			
		||||
   }
 | 
			
		||||
   protected ProxyMessage bind(String host,int port)
 | 
			
		||||
             throws UnknownHostException,SocksException{
 | 
			
		||||
      try{
 | 
			
		||||
         startSession();
 | 
			
		||||
         ProxyMessage request  = formMessage(SOCKS_CMD_BIND,
 | 
			
		||||
				             host,port);
 | 
			
		||||
         return exchange(request);
 | 
			
		||||
      }catch(SocksException se){
 | 
			
		||||
         endSession();
 | 
			
		||||
         throw se;
 | 
			
		||||
      }
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   protected ProxyMessage accept()
 | 
			
		||||
             throws IOException,SocksException{
 | 
			
		||||
      ProxyMessage msg;
 | 
			
		||||
      try{
 | 
			
		||||
         msg = formMessage(in);
 | 
			
		||||
      }catch(InterruptedIOException iioe){
 | 
			
		||||
         throw iioe;
 | 
			
		||||
      }catch(IOException io_ex){
 | 
			
		||||
         endSession();
 | 
			
		||||
         throw new SocksException(SOCKS_PROXY_IO_ERROR,"While Trying accept:"
 | 
			
		||||
         +io_ex);
 | 
			
		||||
      }
 | 
			
		||||
      return msg;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   protected ProxyMessage udpAssociate(InetAddress ip,int port)
 | 
			
		||||
             throws SocksException{
 | 
			
		||||
      try{
 | 
			
		||||
         startSession();
 | 
			
		||||
         ProxyMessage request  = formMessage(SOCKS_CMD_UDP_ASSOCIATE,
 | 
			
		||||
				             ip,port);
 | 
			
		||||
         if(request != null)
 | 
			
		||||
           return exchange(request);
 | 
			
		||||
      }catch(SocksException se){
 | 
			
		||||
         endSession();
 | 
			
		||||
         throw se;
 | 
			
		||||
      }
 | 
			
		||||
      //Only get here if request was null
 | 
			
		||||
      endSession();
 | 
			
		||||
      throw new SocksException(SOCKS_METHOD_NOTSUPPORTED,
 | 
			
		||||
      "This version of proxy does not support UDP associate, use version 5");
 | 
			
		||||
   }
 | 
			
		||||
   protected ProxyMessage udpAssociate(String host,int port)
 | 
			
		||||
             throws UnknownHostException,SocksException{
 | 
			
		||||
      try{
 | 
			
		||||
         startSession();
 | 
			
		||||
         ProxyMessage request  = formMessage(SOCKS_CMD_UDP_ASSOCIATE,
 | 
			
		||||
				             host,port);
 | 
			
		||||
         if(request != null) return exchange(request);
 | 
			
		||||
      }catch(SocksException se){
 | 
			
		||||
         endSession();
 | 
			
		||||
         throw se;
 | 
			
		||||
      }
 | 
			
		||||
      //Only get here if request was null
 | 
			
		||||
      endSession();
 | 
			
		||||
      throw new SocksException(SOCKS_METHOD_NOTSUPPORTED,
 | 
			
		||||
      "This version of proxy does not support UDP associate, use version 5");
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
   protected void endSession(){
 | 
			
		||||
      try{
 | 
			
		||||
         if(proxySocket!=null) proxySocket.close();
 | 
			
		||||
         proxySocket = null;
 | 
			
		||||
      }catch(IOException io_ex){
 | 
			
		||||
      }
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
    *Sends the request to SOCKS server
 | 
			
		||||
    */
 | 
			
		||||
   protected void sendMsg(ProxyMessage msg)throws SocksException,
 | 
			
		||||
                                                  IOException{
 | 
			
		||||
      msg.write(out);
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   /** 
 | 
			
		||||
    * Reads the reply from the SOCKS server
 | 
			
		||||
    */
 | 
			
		||||
   protected ProxyMessage readMsg()throws SocksException,
 | 
			
		||||
                                          IOException{
 | 
			
		||||
      return formMessage(in);
 | 
			
		||||
   }
 | 
			
		||||
   /**
 | 
			
		||||
    *Sends the request reads reply and returns it
 | 
			
		||||
    *throws exception if something wrong with IO
 | 
			
		||||
    *or the reply code is not zero
 | 
			
		||||
    */
 | 
			
		||||
   protected ProxyMessage exchange(ProxyMessage request)
 | 
			
		||||
                           throws SocksException{
 | 
			
		||||
      ProxyMessage reply;
 | 
			
		||||
      try{
 | 
			
		||||
         request.write(out);
 | 
			
		||||
         reply = formMessage(in);
 | 
			
		||||
      }catch(SocksException s_ex){
 | 
			
		||||
         throw s_ex;
 | 
			
		||||
      }catch(IOException ioe){
 | 
			
		||||
         throw(new SocksException(SOCKS_PROXY_IO_ERROR,""+ioe));
 | 
			
		||||
      }
 | 
			
		||||
      return reply;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//Private methods
 | 
			
		||||
//===============
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//Constants
 | 
			
		||||
 | 
			
		||||
   public static final int SOCKS_SUCCESS		=0;
 | 
			
		||||
   public static final int SOCKS_FAILURE		=1;
 | 
			
		||||
   public static final int SOCKS_NOT_ALLOWED_BY_RULESET		=2;
 | 
			
		||||
   public static final int SOCKS_BADNETWORK		=3;
 | 
			
		||||
   public static final int SOCKS_HOST_UNREACHABLE	=4;
 | 
			
		||||
   public static final int SOCKS_CONNECTION_REFUSED	=5;
 | 
			
		||||
   public static final int SOCKS_TTL_EXPIRE		=6;
 | 
			
		||||
   public static final int SOCKS_CMD_NOT_SUPPORTED	=7;
 | 
			
		||||
   public static final int SOCKS_ADDR_NOT_SUPPORTED	=8;
 | 
			
		||||
 | 
			
		||||
   public static final int SOCKS_NO_PROXY		=1<<16;
 | 
			
		||||
   public static final int SOCKS_PROXY_NO_CONNECT	=2<<16;
 | 
			
		||||
   public static final int SOCKS_PROXY_IO_ERROR		=3<<16;
 | 
			
		||||
   public static final int SOCKS_AUTH_NOT_SUPPORTED	=4<<16;
 | 
			
		||||
   public static final int SOCKS_AUTH_FAILURE		=5<<16;
 | 
			
		||||
   public static final int SOCKS_JUST_ERROR		=6<<16;
 | 
			
		||||
 | 
			
		||||
   public static final int SOCKS_DIRECT_FAILED		=7<<16;
 | 
			
		||||
   public static final int SOCKS_METHOD_NOTSUPPORTED	=8<<16;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
   static final int SOCKS_CMD_CONNECT 		=0x1;
 | 
			
		||||
   static final int SOCKS_CMD_BIND		=0x2;
 | 
			
		||||
   static final int SOCKS_CMD_UDP_ASSOCIATE	=0x3;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,119 @@
 | 
			
		|||
package net.sourceforge.jsocks.socks;
 | 
			
		||||
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.io.InputStream;
 | 
			
		||||
import java.io.OutputStream;
 | 
			
		||||
import java.io.DataInputStream;
 | 
			
		||||
import java.net.InetAddress;
 | 
			
		||||
import java.net.UnknownHostException;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 Abstract class which describes SOCKS4/5 response/request.
 | 
			
		||||
*/
 | 
			
		||||
public abstract class ProxyMessage{
 | 
			
		||||
   /** Host as an IP address */
 | 
			
		||||
   public InetAddress ip=null;
 | 
			
		||||
   /** SOCKS version, or version of the response for SOCKS4*/
 | 
			
		||||
   public int version;
 | 
			
		||||
   /** Port field of the request/response*/
 | 
			
		||||
   public int port;
 | 
			
		||||
   /** Request/response code as an int*/
 | 
			
		||||
   public int command;
 | 
			
		||||
   /** Host as string.*/
 | 
			
		||||
   public String host=null;
 | 
			
		||||
   /** User field for SOCKS4 request messages*/
 | 
			
		||||
   public String user=null;
 | 
			
		||||
   /** Connection ID */
 | 
			
		||||
   private String connectionId = "N/A";
 | 
			
		||||
 | 
			
		||||
   ProxyMessage(int command,InetAddress ip,int port){
 | 
			
		||||
      this.command = command;
 | 
			
		||||
      this.ip      = ip;
 | 
			
		||||
      this.port    = port;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   ProxyMessage(){
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
     Initialises Message from the stream. Reads server response from
 | 
			
		||||
     given stream.
 | 
			
		||||
     @param in Input stream to read response from.
 | 
			
		||||
     @throws SocksException If server response code is not SOCKS_SUCCESS(0), or
 | 
			
		||||
     if any error with protocol occurs.
 | 
			
		||||
     @throws IOException If any error happens with I/O.
 | 
			
		||||
   */
 | 
			
		||||
   public abstract void read(InputStream in)
 | 
			
		||||
                                    throws SocksException,
 | 
			
		||||
                                           IOException;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
     Initialises Message from the stream. Reads server response or client 
 | 
			
		||||
     request from given stream.
 | 
			
		||||
     
 | 
			
		||||
     @param in Input stream to read response from.
 | 
			
		||||
     @param clinetMode If true read server response, else read client request.
 | 
			
		||||
     @throws SocksException If server response code is not SOCKS_SUCCESS(0) and
 | 
			
		||||
     reading in client mode, or if any error with protocol occurs.
 | 
			
		||||
     @throws IOException If any error happens with I/O.
 | 
			
		||||
   */
 | 
			
		||||
   public abstract void read(InputStream in,boolean client_mode)
 | 
			
		||||
                                    throws SocksException,
 | 
			
		||||
                                           IOException;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
    Writes the message to the stream.
 | 
			
		||||
    @param out Output stream to which message should be written.
 | 
			
		||||
   */
 | 
			
		||||
   public abstract void write(OutputStream out)throws SocksException,
 | 
			
		||||
                                             IOException;
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
    Get the Address field of this message as InetAddress object.
 | 
			
		||||
    @return Host address or null, if one can't be determined.
 | 
			
		||||
   */
 | 
			
		||||
   public InetAddress getInetAddress() throws UnknownHostException{
 | 
			
		||||
     return ip;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
    Get string representaion of this message.
 | 
			
		||||
    @return string representation of this message.
 | 
			
		||||
   */
 | 
			
		||||
   public String toString(){
 | 
			
		||||
      return 
 | 
			
		||||
      "Proxy Message:\n"+
 | 
			
		||||
      "Version:"+ version+"\n"+
 | 
			
		||||
      "Command:"+ command+"\n"+
 | 
			
		||||
      "IP:     "+ ip+"\n"+
 | 
			
		||||
      "Port:   "+ port+"\n"+
 | 
			
		||||
      "User:   "+ user+"\n" ;
 | 
			
		||||
   }
 | 
			
		||||
   
 | 
			
		||||
   public String getConnectionId() {
 | 
			
		||||
     return connectionId;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   public void setConnectionId(String connectionId) {
 | 
			
		||||
     this.connectionId = connectionId;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
//Package methods
 | 
			
		||||
//////////////////
 | 
			
		||||
 | 
			
		||||
   static final String bytes2IPV4(byte[] addr,int offset){
 | 
			
		||||
      String hostName = ""+(addr[offset] & 0xFF);
 | 
			
		||||
      for(int i = offset+1;i<offset+4;++i)
 | 
			
		||||
        hostName+="."+(addr[i] & 0xFF);
 | 
			
		||||
      return hostName;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   static final String bytes2IPV6(byte[] addr,int offset){
 | 
			
		||||
     //Have no idea how they look like!
 | 
			
		||||
     return null;
 | 
			
		||||
   }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,569 @@
 | 
			
		|||
package net.sourceforge.jsocks.socks;
 | 
			
		||||
 | 
			
		||||
import net.*;
 | 
			
		||||
import net.sourceforge.jsocks.socks.server.ServerAuthenticator;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
import java.net.ConnectException;
 | 
			
		||||
import java.net.InetAddress;
 | 
			
		||||
import java.net.NoRouteToHostException;
 | 
			
		||||
import java.net.ServerSocket;
 | 
			
		||||
import java.net.Socket;
 | 
			
		||||
import java.util.Random;
 | 
			
		||||
import java.io.*;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
    SOCKS4 and SOCKS5 proxy, handles both protocols simultaniously.
 | 
			
		||||
    Implements all SOCKS commands, including UDP relaying.
 | 
			
		||||
    <p>
 | 
			
		||||
    In order to use it you will need to implement ServerAuthenticator
 | 
			
		||||
    interface. There is an implementation of this interface which does
 | 
			
		||||
    no authentication ServerAuthenticatorNone, but it is very dangerous
 | 
			
		||||
    to use, as it will give access to your local network to anybody
 | 
			
		||||
    in the world. One should never use this authentication scheme unless
 | 
			
		||||
    one have pretty good reason to do so.
 | 
			
		||||
    There is a couple of other authentication schemes in socks.server package.
 | 
			
		||||
    @see socks.server.ServerAuthenticator
 | 
			
		||||
*/
 | 
			
		||||
public class ProxyServer implements Runnable{
 | 
			
		||||
 | 
			
		||||
   ServerAuthenticator auth;
 | 
			
		||||
   ProxyMessage msg = null;
 | 
			
		||||
 | 
			
		||||
   Socket sock=null,remote_sock=null;
 | 
			
		||||
   ServerSocket ss=null;
 | 
			
		||||
   UDPRelayServer relayServer = null;
 | 
			
		||||
   InputStream in,remote_in;
 | 
			
		||||
   OutputStream out,remote_out;
 | 
			
		||||
 | 
			
		||||
   int mode;
 | 
			
		||||
   static final int START_MODE	= 0;
 | 
			
		||||
   static final int ACCEPT_MODE	= 1;
 | 
			
		||||
   static final int PIPE_MODE	= 2;
 | 
			
		||||
   static final int ABORT_MODE	= 3;
 | 
			
		||||
 | 
			
		||||
   static final int BUF_SIZE	= 8192;
 | 
			
		||||
 | 
			
		||||
   Thread pipe_thread1,pipe_thread2;
 | 
			
		||||
   long lastReadTime;
 | 
			
		||||
 | 
			
		||||
   static int iddleTimeout	= 180000; //3 minutes
 | 
			
		||||
   static int acceptTimeout	= 180000; //3 minutes
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
   static Proxy proxy;
 | 
			
		||||
   
 | 
			
		||||
   private String connectionId;
 | 
			
		||||
   
 | 
			
		||||
 | 
			
		||||
//Public Constructors
 | 
			
		||||
/////////////////////
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
    Creates a proxy server with given Authentication scheme.
 | 
			
		||||
    @param auth Authentication scheme to be used.
 | 
			
		||||
    */
 | 
			
		||||
   public ProxyServer(ServerAuthenticator auth){
 | 
			
		||||
     this.auth = auth;
 | 
			
		||||
     this.connectionId = newConnectionId();
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
//Other constructors
 | 
			
		||||
////////////////////
 | 
			
		||||
 | 
			
		||||
   ProxyServer(ServerAuthenticator auth,Socket s, String connectionId){
 | 
			
		||||
      this.auth  = auth;
 | 
			
		||||
      this.sock  = s;
 | 
			
		||||
      this.connectionId = connectionId;
 | 
			
		||||
      mode = START_MODE;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
//Public methods
 | 
			
		||||
/////////////////
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
    Set proxy.
 | 
			
		||||
    <p>
 | 
			
		||||
    Allows Proxy chaining so that one Proxy server is connected to another
 | 
			
		||||
    and so on. If proxy supports SOCKSv4, then only some SOCKSv5 requests
 | 
			
		||||
    can be handled, UDP would not work, however CONNECT and BIND will be
 | 
			
		||||
    translated.
 | 
			
		||||
 | 
			
		||||
    @param p Proxy which should be used to handle user requests.
 | 
			
		||||
   */
 | 
			
		||||
   public static void setProxy(Proxy p){
 | 
			
		||||
      proxy =p;
 | 
			
		||||
      UDPRelayServer.proxy = proxy;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
    Get proxy.
 | 
			
		||||
    @return Proxy wich is used to handle user requests.
 | 
			
		||||
   */
 | 
			
		||||
   public static Proxy getProxy(){
 | 
			
		||||
      return proxy;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
    Sets the timeout for connections, how long shoud server wait
 | 
			
		||||
    for data to arrive before dropping the connection.<br>
 | 
			
		||||
    Zero timeout implies infinity.<br>
 | 
			
		||||
    Default timeout is 3 minutes.
 | 
			
		||||
   */
 | 
			
		||||
   public static void setIddleTimeout(int timeout){
 | 
			
		||||
      iddleTimeout = timeout;
 | 
			
		||||
   }
 | 
			
		||||
   /**
 | 
			
		||||
    Sets the timeout for BIND command, how long the server should
 | 
			
		||||
    wait for the incoming connection.<br>
 | 
			
		||||
    Zero timeout implies infinity.<br>
 | 
			
		||||
    Default timeout is 3 minutes.
 | 
			
		||||
   */
 | 
			
		||||
   public static void setAcceptTimeout(int timeout){
 | 
			
		||||
      acceptTimeout = timeout;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
    Sets the timeout for UDPRelay server.<br>
 | 
			
		||||
    Zero timeout implies infinity.<br>
 | 
			
		||||
    Default timeout is 3 minutes.
 | 
			
		||||
   */
 | 
			
		||||
   public static void setUDPTimeout(int timeout){
 | 
			
		||||
      UDPRelayServer.setTimeout(timeout);
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
     Sets the size of the datagrams used in the UDPRelayServer.<br>
 | 
			
		||||
     Default size is 64K, a bit more than maximum possible size of the
 | 
			
		||||
     datagram.
 | 
			
		||||
    */
 | 
			
		||||
   public static void setDatagramSize(int size){
 | 
			
		||||
      UDPRelayServer.setDatagramSize(size);
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
     Start the Proxy server at given port.<br>
 | 
			
		||||
     This methods blocks.
 | 
			
		||||
    */
 | 
			
		||||
   public void start(int port){
 | 
			
		||||
      start(port,5,null);
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
     Create a server with the specified port, listen backlog, and local 
 | 
			
		||||
     IP address to bind to. The localIP argument can be used on a multi-homed
 | 
			
		||||
     host for a ServerSocket that will only accept connect requests to one of 
 | 
			
		||||
     its addresses. If localIP is null, it will default accepting connections 
 | 
			
		||||
     on any/all local addresses. The port must be between 0 and 65535, 
 | 
			
		||||
     inclusive. <br>
 | 
			
		||||
     This methods blocks. 
 | 
			
		||||
    */
 | 
			
		||||
   public void start(int port,int backlog,InetAddress localIP){
 | 
			
		||||
      try{
 | 
			
		||||
        ss = new ServerSocket(port,backlog,localIP);
 | 
			
		||||
        while(true){
 | 
			
		||||
          Socket s = ss.accept();
 | 
			
		||||
          String connectionId = newConnectionId();
 | 
			
		||||
          ProxyServer ps = new ProxyServer(auth,s, connectionId);
 | 
			
		||||
          (new Thread(ps)).start();
 | 
			
		||||
        }
 | 
			
		||||
      }catch(IOException ioe){
 | 
			
		||||
        ioe.printStackTrace();
 | 
			
		||||
      }
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
    * Creates new unique ID for this connection.
 | 
			
		||||
    * 
 | 
			
		||||
    * @return a random-enough ID.
 | 
			
		||||
    */
 | 
			
		||||
   private String newConnectionId() {
 | 
			
		||||
    // return "[" + RandomStringUtils.randomAlphanumeric(4) + "]";
 | 
			
		||||
	   return "[" + Math.random()*new java.util.Date().getTime() + "]";
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
     Stop server operation.It would be wise to interrupt thread running the
 | 
			
		||||
     server afterwards.
 | 
			
		||||
    */
 | 
			
		||||
   public void stop(){
 | 
			
		||||
     try{
 | 
			
		||||
       if(ss != null) ss.close();
 | 
			
		||||
     }catch(IOException ioe){
 | 
			
		||||
     }
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
//Runnable interface
 | 
			
		||||
////////////////////
 | 
			
		||||
   public void run(){
 | 
			
		||||
      switch(mode){
 | 
			
		||||
        case START_MODE:
 | 
			
		||||
         try{
 | 
			
		||||
           startSession();
 | 
			
		||||
         }catch(IOException ioe){
 | 
			
		||||
           handleException(ioe);
 | 
			
		||||
           ioe.printStackTrace();
 | 
			
		||||
         }finally{
 | 
			
		||||
           abort();
 | 
			
		||||
           if(auth!=null) auth.endSession();
 | 
			
		||||
         }
 | 
			
		||||
        break;
 | 
			
		||||
        case ACCEPT_MODE:
 | 
			
		||||
          try{
 | 
			
		||||
            doAccept();
 | 
			
		||||
            mode = PIPE_MODE;
 | 
			
		||||
            pipe_thread1.interrupt(); //Tell other thread that connection have
 | 
			
		||||
                                      //been accepted.
 | 
			
		||||
            pipe(remote_in,out);
 | 
			
		||||
          }catch(IOException ioe){
 | 
			
		||||
            //log("Accept exception:"+ioe);
 | 
			
		||||
            handleException(ioe);
 | 
			
		||||
          }finally{
 | 
			
		||||
            abort();
 | 
			
		||||
          }
 | 
			
		||||
        break;
 | 
			
		||||
        case PIPE_MODE:
 | 
			
		||||
         try{
 | 
			
		||||
            pipe(remote_in,out);
 | 
			
		||||
         }catch(IOException ioe){
 | 
			
		||||
         }finally{
 | 
			
		||||
            abort();
 | 
			
		||||
         }
 | 
			
		||||
        break;
 | 
			
		||||
        case ABORT_MODE:
 | 
			
		||||
        break;
 | 
			
		||||
        default:
 | 
			
		||||
      }
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
//Private methods
 | 
			
		||||
/////////////////
 | 
			
		||||
   private void startSession() throws IOException{
 | 
			
		||||
     sock.setSoTimeout(iddleTimeout);
 | 
			
		||||
 | 
			
		||||
     try{
 | 
			
		||||
        auth = auth.startSession(sock);
 | 
			
		||||
     }catch(IOException ioe){
 | 
			
		||||
       auth = null;
 | 
			
		||||
       return;
 | 
			
		||||
     }
 | 
			
		||||
 | 
			
		||||
     if(auth == null){ //Authentication failed
 | 
			
		||||
        return;
 | 
			
		||||
     }
 | 
			
		||||
 | 
			
		||||
     in = auth.getInputStream();
 | 
			
		||||
     out = auth.getOutputStream();
 | 
			
		||||
 | 
			
		||||
     msg = readMsg(in);
 | 
			
		||||
     // Set the connection ID in the message.
 | 
			
		||||
     msg.setConnectionId(connectionId);
 | 
			
		||||
     handleRequest(msg);
 | 
			
		||||
   }
 | 
			
		||||
   
 | 
			
		||||
   private void handleRequest(ProxyMessage msg)
 | 
			
		||||
                throws IOException{
 | 
			
		||||
      if(!auth.checkRequest(msg)) {
 | 
			
		||||
        ProxyMessage response = new Socks5Message(
 | 
			
		||||
            Proxy.SOCKS_NOT_ALLOWED_BY_RULESET);
 | 
			
		||||
        response.write(out);
 | 
			
		||||
        abort();
 | 
			
		||||
        throw new SocksException(Proxy.SOCKS_NOT_ALLOWED_BY_RULESET);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if(msg.ip == null){
 | 
			
		||||
        if(msg instanceof Socks5Message){
 | 
			
		||||
          msg.ip = InetAddress.getByName(msg.host);
 | 
			
		||||
        }else
 | 
			
		||||
          throw new SocksException(Proxy.SOCKS_FAILURE);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      switch(msg.command){
 | 
			
		||||
        case Proxy.SOCKS_CMD_CONNECT:
 | 
			
		||||
          onConnect(msg);
 | 
			
		||||
        break;
 | 
			
		||||
        case Proxy.SOCKS_CMD_BIND:
 | 
			
		||||
          onBind(msg);
 | 
			
		||||
        break;
 | 
			
		||||
        case Proxy.SOCKS_CMD_UDP_ASSOCIATE:
 | 
			
		||||
          onUDP(msg);
 | 
			
		||||
        break;
 | 
			
		||||
        default:
 | 
			
		||||
          throw new SocksException(Proxy.SOCKS_CMD_NOT_SUPPORTED);
 | 
			
		||||
      }
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   private void handleException(IOException ioe){
 | 
			
		||||
      //If we couldn't read the request, return;
 | 
			
		||||
      if(msg == null) return;
 | 
			
		||||
      //If have been aborted by other thread
 | 
			
		||||
      if(mode == ABORT_MODE) return;
 | 
			
		||||
      //If the request was successfully completed, but exception happened later
 | 
			
		||||
      if(mode == PIPE_MODE) return;
 | 
			
		||||
 | 
			
		||||
      int error_code = Proxy.SOCKS_FAILURE;
 | 
			
		||||
 | 
			
		||||
      if(ioe instanceof SocksException)
 | 
			
		||||
          error_code = ((SocksException)ioe).errCode;
 | 
			
		||||
      else if(ioe instanceof NoRouteToHostException)
 | 
			
		||||
          error_code = Proxy.SOCKS_HOST_UNREACHABLE;
 | 
			
		||||
      else if(ioe instanceof ConnectException)
 | 
			
		||||
          error_code = Proxy.SOCKS_CONNECTION_REFUSED;
 | 
			
		||||
      else if(ioe instanceof InterruptedIOException)
 | 
			
		||||
          error_code = Proxy.SOCKS_TTL_EXPIRE;
 | 
			
		||||
 | 
			
		||||
      if(error_code > Proxy.SOCKS_ADDR_NOT_SUPPORTED || error_code < 0){
 | 
			
		||||
          error_code = Proxy.SOCKS_FAILURE; 
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      sendErrorMessage(error_code);
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   private void onConnect(ProxyMessage msg) throws IOException{
 | 
			
		||||
      Socket s;
 | 
			
		||||
      ProxyMessage response = null;
 | 
			
		||||
 | 
			
		||||
      if(proxy == null)
 | 
			
		||||
         s = new Socket(msg.ip,msg.port);
 | 
			
		||||
      else
 | 
			
		||||
         s = new SocksSocket(proxy,msg.ip,msg.port);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
      if(msg instanceof Socks5Message){
 | 
			
		||||
        response = new Socks5Message(Proxy.SOCKS_SUCCESS,
 | 
			
		||||
                                         s.getLocalAddress(),
 | 
			
		||||
                                         s.getLocalPort());
 | 
			
		||||
      }else{
 | 
			
		||||
        response = new Socks4Message(Socks4Message.REPLY_OK,
 | 
			
		||||
                                     s.getLocalAddress(),s.getLocalPort());
 | 
			
		||||
 | 
			
		||||
      }
 | 
			
		||||
      response.write(out);
 | 
			
		||||
      startPipe(s);
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   private void onBind(ProxyMessage msg) throws IOException{
 | 
			
		||||
      ProxyMessage response = null;
 | 
			
		||||
 | 
			
		||||
      if(proxy == null)
 | 
			
		||||
        ss = new ServerSocket(0);
 | 
			
		||||
      else
 | 
			
		||||
        ss = new SocksServerSocket(proxy, msg.ip, msg.port);
 | 
			
		||||
 | 
			
		||||
      ss.setSoTimeout(acceptTimeout);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
      if(msg.version == 5)
 | 
			
		||||
         response = new Socks5Message(Proxy.SOCKS_SUCCESS,ss.getInetAddress(),
 | 
			
		||||
                                                          ss.getLocalPort());
 | 
			
		||||
      else
 | 
			
		||||
         response = new Socks4Message(Socks4Message.REPLY_OK,
 | 
			
		||||
                                      ss.getInetAddress(),
 | 
			
		||||
                                      ss.getLocalPort());
 | 
			
		||||
      response.write(out);
 | 
			
		||||
 | 
			
		||||
      mode = ACCEPT_MODE;
 | 
			
		||||
 | 
			
		||||
      pipe_thread1 = Thread.currentThread();
 | 
			
		||||
      pipe_thread2 = new Thread(this);
 | 
			
		||||
      pipe_thread2.start();
 | 
			
		||||
 | 
			
		||||
      //Make timeout infinit.
 | 
			
		||||
      sock.setSoTimeout(0);
 | 
			
		||||
      int eof=0;
 | 
			
		||||
 | 
			
		||||
      try{
 | 
			
		||||
        while((eof=in.read())>=0){
 | 
			
		||||
          if(mode != ACCEPT_MODE){
 | 
			
		||||
            if(mode != PIPE_MODE) return;//Accept failed
 | 
			
		||||
 | 
			
		||||
            remote_out.write(eof);
 | 
			
		||||
            break;
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }catch(EOFException eofe){
 | 
			
		||||
        //System.out.println("EOF exception");
 | 
			
		||||
        return;//Connection closed while we were trying to accept.
 | 
			
		||||
      }catch(InterruptedIOException iioe){ 
 | 
			
		||||
        //Accept thread interrupted us.
 | 
			
		||||
        //System.out.println("Interrupted");
 | 
			
		||||
        if(mode != PIPE_MODE)
 | 
			
		||||
          return;//If accept thread was not successfull return.
 | 
			
		||||
      }finally{
 | 
			
		||||
        //System.out.println("Finnaly!");
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if(eof < 0)//Connection closed while we were trying to accept;
 | 
			
		||||
        return;
 | 
			
		||||
      
 | 
			
		||||
      //Do not restore timeout, instead timeout is set on the
 | 
			
		||||
      //remote socket. It does not make any difference.
 | 
			
		||||
 | 
			
		||||
      pipe(in,remote_out);
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   private void onUDP(ProxyMessage msg) throws IOException{
 | 
			
		||||
      if(msg.ip.getHostAddress().equals("0.0.0.0"))
 | 
			
		||||
         msg.ip = sock.getInetAddress();
 | 
			
		||||
      relayServer = new UDPRelayServer(msg.ip,msg.port,
 | 
			
		||||
                        Thread.currentThread(),sock,auth);
 | 
			
		||||
 | 
			
		||||
      ProxyMessage response;
 | 
			
		||||
 | 
			
		||||
      response = new Socks5Message(Proxy.SOCKS_SUCCESS,
 | 
			
		||||
                                   relayServer.relayIP,relayServer.relayPort);
 | 
			
		||||
 | 
			
		||||
      response.write(out);
 | 
			
		||||
 | 
			
		||||
      relayServer.start();
 | 
			
		||||
 | 
			
		||||
      //Make timeout infinit.
 | 
			
		||||
      sock.setSoTimeout(0);
 | 
			
		||||
      try{
 | 
			
		||||
        while(in.read()>=0) /*do nothing*/;
 | 
			
		||||
      }catch(EOFException eofe){
 | 
			
		||||
      }
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
//Private methods
 | 
			
		||||
//////////////////
 | 
			
		||||
 | 
			
		||||
   private void doAccept() throws IOException{
 | 
			
		||||
      Socket s;
 | 
			
		||||
      long startTime = System.currentTimeMillis();
 | 
			
		||||
 | 
			
		||||
      while(true){
 | 
			
		||||
         s = ss.accept();
 | 
			
		||||
         if(s.getInetAddress().equals(msg.ip)){
 | 
			
		||||
            //got the connection from the right host
 | 
			
		||||
            //Close listenning socket.
 | 
			
		||||
            ss.close();
 | 
			
		||||
            break;
 | 
			
		||||
         }else if(ss instanceof SocksServerSocket){
 | 
			
		||||
            //We can't accept more then one connection
 | 
			
		||||
            s.close();
 | 
			
		||||
            ss.close();
 | 
			
		||||
            throw new SocksException(Proxy.SOCKS_FAILURE);
 | 
			
		||||
         }else{
 | 
			
		||||
            if(acceptTimeout!=0){ //If timeout is not infinit
 | 
			
		||||
               int newTimeout = acceptTimeout-(int)(System.currentTimeMillis()-
 | 
			
		||||
                                                           startTime);
 | 
			
		||||
               if(newTimeout <= 0) throw new InterruptedIOException(
 | 
			
		||||
                                "In doAccept()");
 | 
			
		||||
               ss.setSoTimeout(newTimeout);
 | 
			
		||||
            }
 | 
			
		||||
            s.close(); //Drop all connections from other hosts
 | 
			
		||||
         }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      //Accepted connection
 | 
			
		||||
      remote_sock = s;
 | 
			
		||||
      remote_in = s.getInputStream();
 | 
			
		||||
      remote_out = s.getOutputStream();
 | 
			
		||||
 | 
			
		||||
      //Set timeout
 | 
			
		||||
      remote_sock.setSoTimeout(iddleTimeout);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
      ProxyMessage response;
 | 
			
		||||
 | 
			
		||||
      if(msg.version == 5)
 | 
			
		||||
         response = new Socks5Message(Proxy.SOCKS_SUCCESS, s.getInetAddress(),
 | 
			
		||||
                                                           s.getPort());
 | 
			
		||||
      else
 | 
			
		||||
         response = new Socks4Message(Socks4Message.REPLY_OK,
 | 
			
		||||
                                      s.getInetAddress(), s.getPort());
 | 
			
		||||
      response.write(out);
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   private ProxyMessage readMsg(InputStream in) throws IOException{
 | 
			
		||||
      PushbackInputStream push_in;  
 | 
			
		||||
      if(in instanceof PushbackInputStream)
 | 
			
		||||
         push_in = (PushbackInputStream) in;
 | 
			
		||||
      else
 | 
			
		||||
         push_in = new PushbackInputStream(in);
 | 
			
		||||
 | 
			
		||||
      int version = push_in.read();
 | 
			
		||||
      push_in.unread(version);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
      ProxyMessage msg;
 | 
			
		||||
 | 
			
		||||
      if(version == 5){
 | 
			
		||||
        msg = new Socks5Message(push_in,false);
 | 
			
		||||
      }else if(version == 4){
 | 
			
		||||
        msg = new Socks4Message(push_in,false);
 | 
			
		||||
      }else{
 | 
			
		||||
        throw new SocksException(Proxy.SOCKS_FAILURE);
 | 
			
		||||
      }
 | 
			
		||||
      return msg;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   private void startPipe(Socket s){
 | 
			
		||||
      mode = PIPE_MODE;
 | 
			
		||||
      remote_sock = s;
 | 
			
		||||
      try{
 | 
			
		||||
         remote_in = s.getInputStream();
 | 
			
		||||
         remote_out = s.getOutputStream();
 | 
			
		||||
         pipe_thread1 = Thread.currentThread();
 | 
			
		||||
         pipe_thread2 = new Thread(this);
 | 
			
		||||
         pipe_thread2.start();
 | 
			
		||||
         pipe(in,remote_out);
 | 
			
		||||
      }catch(IOException ioe){
 | 
			
		||||
      }
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   private void sendErrorMessage(int error_code){
 | 
			
		||||
      ProxyMessage err_msg;
 | 
			
		||||
      if(msg instanceof Socks4Message)
 | 
			
		||||
         err_msg = new Socks4Message(Socks4Message.REPLY_REJECTED);
 | 
			
		||||
      else
 | 
			
		||||
         err_msg = new Socks5Message(error_code);
 | 
			
		||||
      try{
 | 
			
		||||
         err_msg.write(out);
 | 
			
		||||
      }catch(IOException ioe){}
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   private synchronized void abort(){
 | 
			
		||||
      if(mode == ABORT_MODE) return;
 | 
			
		||||
      mode = ABORT_MODE;
 | 
			
		||||
      try{
 | 
			
		||||
         if(remote_sock != null) remote_sock.close();
 | 
			
		||||
         if(sock != null) sock.close();
 | 
			
		||||
         if(relayServer!=null) relayServer.stop();
 | 
			
		||||
         if(ss!=null) ss.close();
 | 
			
		||||
         if(pipe_thread1 != null) pipe_thread1.interrupt();
 | 
			
		||||
         if(pipe_thread2 != null) pipe_thread2.interrupt();
 | 
			
		||||
      }catch(IOException ioe){}
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   private void pipe(InputStream in,OutputStream out) throws IOException{
 | 
			
		||||
      lastReadTime = System.currentTimeMillis();
 | 
			
		||||
      byte[] buf = new byte[BUF_SIZE];
 | 
			
		||||
      int len = 0;
 | 
			
		||||
      while(len >= 0){
 | 
			
		||||
         try{
 | 
			
		||||
           if(len!=0){
 | 
			
		||||
             out.write(buf,0,len);
 | 
			
		||||
             out.flush();
 | 
			
		||||
           }
 | 
			
		||||
           len= in.read(buf);
 | 
			
		||||
           lastReadTime = System.currentTimeMillis();
 | 
			
		||||
         }catch(InterruptedIOException iioe){
 | 
			
		||||
           if(iddleTimeout == 0) return;//Other thread interrupted us.
 | 
			
		||||
           long timeSinceRead = System.currentTimeMillis() - lastReadTime;
 | 
			
		||||
           if(timeSinceRead >= iddleTimeout - 1000) //-1s for adjustment.
 | 
			
		||||
              return;
 | 
			
		||||
           len = 0;
 | 
			
		||||
 | 
			
		||||
         }
 | 
			
		||||
      }
 | 
			
		||||
   }
 | 
			
		||||
   static final String command_names[] = {"CONNECT","BIND","UDP_ASSOCIATE"};
 | 
			
		||||
 | 
			
		||||
   static final String command2String(int cmd){
 | 
			
		||||
      if(cmd > 0 && cmd < 4) return command_names[cmd-1];
 | 
			
		||||
      else return "Unknown Command "+cmd;
 | 
			
		||||
   }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,161 @@
 | 
			
		|||
package net.sourceforge.jsocks.socks;
 | 
			
		||||
 | 
			
		||||
import java.io.*;
 | 
			
		||||
import java.net.InetAddress;
 | 
			
		||||
import java.net.UnknownHostException;
 | 
			
		||||
 | 
			
		||||
import net.*;
 | 
			
		||||
 | 
			
		||||
/** 
 | 
			
		||||
  SOCKS4 Reply/Request message.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
class Socks4Message extends ProxyMessage{
 | 
			
		||||
 | 
			
		||||
   private byte[] msgBytes;
 | 
			
		||||
   private int msgLength;
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
    * Server failed reply, cmd command for failed request
 | 
			
		||||
    */
 | 
			
		||||
   public Socks4Message(int cmd){
 | 
			
		||||
      super(cmd,null,0);
 | 
			
		||||
      this.user    = null;
 | 
			
		||||
 | 
			
		||||
      msgLength = 2;
 | 
			
		||||
      msgBytes = new byte[2];
 | 
			
		||||
 | 
			
		||||
      msgBytes[0] = (byte) 0;
 | 
			
		||||
      msgBytes[1] = (byte) command;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   /** 
 | 
			
		||||
    *  Server successfull reply
 | 
			
		||||
    */
 | 
			
		||||
   public Socks4Message(int cmd,InetAddress ip,int port){
 | 
			
		||||
      this(0,cmd,ip,port,null);
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   /** 
 | 
			
		||||
    *  Client request
 | 
			
		||||
    */
 | 
			
		||||
   public Socks4Message(int cmd,InetAddress ip,int port,String user){
 | 
			
		||||
      this(SOCKS_VERSION,cmd,ip,port,user);
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
    * Most general constructor
 | 
			
		||||
    */
 | 
			
		||||
   public Socks4Message(int version, int cmd,
 | 
			
		||||
                        InetAddress ip,int port,String user){
 | 
			
		||||
      super(cmd,ip,port);
 | 
			
		||||
      this.user    = user;
 | 
			
		||||
      this.version = version;
 | 
			
		||||
 | 
			
		||||
      msgLength = user == null?8:9+user.length();
 | 
			
		||||
      msgBytes = new byte[msgLength];
 | 
			
		||||
 | 
			
		||||
      msgBytes[0] = (byte) version;
 | 
			
		||||
      msgBytes[1] = (byte) command;
 | 
			
		||||
      msgBytes[2] = (byte) (port >> 8);
 | 
			
		||||
      msgBytes[3] = (byte) port;
 | 
			
		||||
 | 
			
		||||
      byte[] addr;
 | 
			
		||||
 | 
			
		||||
      if(ip != null)
 | 
			
		||||
        addr = ip.getAddress();
 | 
			
		||||
      else{
 | 
			
		||||
        addr = new byte[4];
 | 
			
		||||
        addr[0]=addr[1]=addr[2]=addr[3]=0;
 | 
			
		||||
      }
 | 
			
		||||
      System.arraycopy(addr,0,msgBytes,4,4);
 | 
			
		||||
 | 
			
		||||
      if(user != null){
 | 
			
		||||
         byte[] buf = user.getBytes();
 | 
			
		||||
         System.arraycopy(buf,0,msgBytes,8,buf.length);
 | 
			
		||||
         msgBytes[msgBytes.length -1 ] = 0;
 | 
			
		||||
      }
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
    *Initialise from the stream
 | 
			
		||||
    *If clientMode is true attempts to read a server response
 | 
			
		||||
    *otherwise reads a client request
 | 
			
		||||
    *see read for more detail
 | 
			
		||||
    */
 | 
			
		||||
   public Socks4Message(InputStream in, boolean clientMode) throws IOException{
 | 
			
		||||
      msgBytes = null;
 | 
			
		||||
      read(in,clientMode);
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   public void read(InputStream in) throws IOException{
 | 
			
		||||
        read(in,true);
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   public void read(InputStream in, boolean clientMode) throws IOException{
 | 
			
		||||
       DataInputStream d_in = new DataInputStream(in);
 | 
			
		||||
       version= d_in.readUnsignedByte();
 | 
			
		||||
       command = d_in.readUnsignedByte();
 | 
			
		||||
       if(clientMode && command != REPLY_OK){
 | 
			
		||||
          String errMsg;
 | 
			
		||||
          if(command >REPLY_OK && command < REPLY_BAD_IDENTD)
 | 
			
		||||
             errMsg = replyMessage[command-REPLY_OK];
 | 
			
		||||
          else
 | 
			
		||||
             errMsg = "Unknown Reply Code";
 | 
			
		||||
          throw new SocksException(command,errMsg);
 | 
			
		||||
       }
 | 
			
		||||
       port = d_in.readUnsignedShort();
 | 
			
		||||
       byte[] addr = new byte[4];
 | 
			
		||||
       d_in.readFully(addr);
 | 
			
		||||
       ip=bytes2IP(addr);
 | 
			
		||||
       host = ip.getHostName();
 | 
			
		||||
       if(!clientMode){
 | 
			
		||||
          int b = in.read();
 | 
			
		||||
          //Hope there are no idiots with user name bigger than this
 | 
			
		||||
          byte[] userBytes = new byte[256];
 | 
			
		||||
          int i = 0;
 | 
			
		||||
          for(i =0;i<userBytes.length && b>0;++i){
 | 
			
		||||
             userBytes[i] = (byte) b;
 | 
			
		||||
             b = in.read();
 | 
			
		||||
          }
 | 
			
		||||
          user = new String(userBytes,0,i);
 | 
			
		||||
       }
 | 
			
		||||
   }
 | 
			
		||||
   public void write(OutputStream out) throws IOException{
 | 
			
		||||
      if(msgBytes == null){
 | 
			
		||||
         Socks4Message msg = new Socks4Message(version,command,ip,port,user);
 | 
			
		||||
         msgBytes = msg.msgBytes;
 | 
			
		||||
         msgLength = msg.msgLength;
 | 
			
		||||
      }
 | 
			
		||||
      out.write(msgBytes);
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   //Class methods
 | 
			
		||||
   static InetAddress bytes2IP(byte[] addr){
 | 
			
		||||
      String s = bytes2IPV4(addr,0);
 | 
			
		||||
      try{
 | 
			
		||||
         return InetAddress.getByName(s);
 | 
			
		||||
      }catch(UnknownHostException uh_ex){
 | 
			
		||||
        return null;
 | 
			
		||||
      }
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   //Constants
 | 
			
		||||
 | 
			
		||||
   static final String[] replyMessage ={
 | 
			
		||||
          "Request Granted",
 | 
			
		||||
          "Request Rejected or Failed",
 | 
			
		||||
          "Failed request, can't connect to Identd",
 | 
			
		||||
          "Failed request, bad user name"};
 | 
			
		||||
 | 
			
		||||
   static final int SOCKS_VERSION = 4;
 | 
			
		||||
 | 
			
		||||
   public final static int REQUEST_CONNECT		= 1;
 | 
			
		||||
   public final static int REQUEST_BIND   		= 2;
 | 
			
		||||
 | 
			
		||||
   public final static int REPLY_OK 			= 90;
 | 
			
		||||
   public final static int REPLY_REJECTED		= 91;
 | 
			
		||||
   public final static int REPLY_NO_CONNECT		= 92;
 | 
			
		||||
   public final static int REPLY_BAD_IDENTD		= 93;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,123 @@
 | 
			
		|||
package net.sourceforge.jsocks.socks;
 | 
			
		||||
 | 
			
		||||
import java.net.InetAddress;
 | 
			
		||||
import java.net.UnknownHostException;
 | 
			
		||||
import java.io.*;
 | 
			
		||||
 | 
			
		||||
import net.*;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  Proxy which describes SOCKS4 proxy.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
public class Socks4Proxy extends Proxy implements Cloneable{
 | 
			
		||||
 | 
			
		||||
//Data members
 | 
			
		||||
   String user;
 | 
			
		||||
 | 
			
		||||
//Public Constructors
 | 
			
		||||
//====================
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
     Creates the SOCKS4 proxy
 | 
			
		||||
     @param p Proxy to use to connect to this proxy, allows proxy chaining.
 | 
			
		||||
     @param proxyHost Address of the proxy server.
 | 
			
		||||
     @param proxyPort Port of the proxy server
 | 
			
		||||
     @param user User name to use for identification purposes.
 | 
			
		||||
     @throws UnknownHostException If proxyHost can't be resolved.
 | 
			
		||||
    */
 | 
			
		||||
   public Socks4Proxy(Proxy p,String proxyHost,int proxyPort,String user)
 | 
			
		||||
          throws UnknownHostException{ 
 | 
			
		||||
      super(p,proxyHost,proxyPort);
 | 
			
		||||
      this.user = new String(user);
 | 
			
		||||
      version = 4;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
     Creates the SOCKS4 proxy
 | 
			
		||||
     @param proxyHost Address of the proxy server.
 | 
			
		||||
     @param proxyPort Port of the proxy server
 | 
			
		||||
     @param user User name to use for identification purposes.
 | 
			
		||||
     @throws UnknownHostException If proxyHost can't be resolved.
 | 
			
		||||
    */
 | 
			
		||||
   public Socks4Proxy(String proxyHost,int proxyPort,String user)
 | 
			
		||||
          throws UnknownHostException{ 
 | 
			
		||||
      this(null,proxyHost,proxyPort,user);
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
     Creates the SOCKS4 proxy
 | 
			
		||||
     @param p Proxy to use to connect to this proxy, allows proxy chaining.
 | 
			
		||||
     @param proxyIP Address of the proxy server.
 | 
			
		||||
     @param proxyPort Port of the proxy server
 | 
			
		||||
     @param user User name to use for identification purposes.
 | 
			
		||||
    */
 | 
			
		||||
   public Socks4Proxy(Proxy p,InetAddress proxyIP,int proxyPort,String user){
 | 
			
		||||
      super(p,proxyIP,proxyPort);
 | 
			
		||||
      this.user = new String(user);
 | 
			
		||||
      version = 4;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
     Creates the SOCKS4 proxy
 | 
			
		||||
     @param proxyIP Address of the proxy server.
 | 
			
		||||
     @param proxyPort Port of the proxy server
 | 
			
		||||
     @param user User name to use for identification purposes.
 | 
			
		||||
    */
 | 
			
		||||
   public Socks4Proxy(InetAddress proxyIP,int proxyPort,String user){
 | 
			
		||||
      this(null,proxyIP,proxyPort,user);
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
//Public instance methods
 | 
			
		||||
//========================
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
    * Creates a clone of this proxy. Changes made to the clone should not
 | 
			
		||||
    * affect this object. 
 | 
			
		||||
    */
 | 
			
		||||
   public Object clone(){
 | 
			
		||||
      Socks4Proxy newProxy = new Socks4Proxy(proxyIP,proxyPort,user);
 | 
			
		||||
      newProxy.directHosts = (InetRange)directHosts.clone();
 | 
			
		||||
      newProxy.chainProxy = chainProxy;
 | 
			
		||||
      return newProxy;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//Public Static(Class) Methods
 | 
			
		||||
//==============================
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//Protected Methods
 | 
			
		||||
//=================
 | 
			
		||||
 | 
			
		||||
   protected Proxy copy(){
 | 
			
		||||
       Socks4Proxy copy = new Socks4Proxy(proxyIP,proxyPort,user);
 | 
			
		||||
       copy.directHosts = this.directHosts;
 | 
			
		||||
       copy.chainProxy = chainProxy;
 | 
			
		||||
       return copy;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
   protected ProxyMessage formMessage(int cmd,InetAddress ip,int port){
 | 
			
		||||
       switch(cmd){
 | 
			
		||||
         case SOCKS_CMD_CONNECT:
 | 
			
		||||
           cmd = Socks4Message.REQUEST_CONNECT;
 | 
			
		||||
         break;
 | 
			
		||||
         case SOCKS_CMD_BIND:
 | 
			
		||||
           cmd = Socks4Message.REQUEST_BIND;
 | 
			
		||||
         break;
 | 
			
		||||
         default:
 | 
			
		||||
           return null;
 | 
			
		||||
       }
 | 
			
		||||
       return new Socks4Message(cmd,ip,port,user);
 | 
			
		||||
   }
 | 
			
		||||
   protected ProxyMessage formMessage(int cmd,String host,int port)
 | 
			
		||||
             throws UnknownHostException{
 | 
			
		||||
       return formMessage(cmd,InetAddress.getByName(host),port);
 | 
			
		||||
   }
 | 
			
		||||
   protected ProxyMessage formMessage(InputStream in)
 | 
			
		||||
             throws SocksException,
 | 
			
		||||
                    IOException{
 | 
			
		||||
       return new Socks4Message(in,true);
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,492 @@
 | 
			
		|||
package net.sourceforge.jsocks.socks;
 | 
			
		||||
 | 
			
		||||
import java.net.DatagramPacket;
 | 
			
		||||
import java.net.DatagramSocket;
 | 
			
		||||
import java.net.InetAddress;
 | 
			
		||||
import java.io.*;
 | 
			
		||||
 | 
			
		||||
import net.*;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  Datagram socket to interract through the firewall.<BR>
 | 
			
		||||
  Can be used same way as the normal DatagramSocket. One should
 | 
			
		||||
  be carefull though with the datagram sizes used, as additional data
 | 
			
		||||
  is present in both incomming and outgoing datagrams.
 | 
			
		||||
   <p>
 | 
			
		||||
   SOCKS5 protocol allows to send host address as either:
 | 
			
		||||
   <ul>
 | 
			
		||||
    <li> IPV4, normal 4 byte address. (10 bytes header size)
 | 
			
		||||
    <li> IPV6, version 6 ip address (not supported by Java as for now).
 | 
			
		||||
         22 bytes header size.
 | 
			
		||||
    <li> Host name,(7+length of the host name bytes header size).
 | 
			
		||||
   </ul>
 | 
			
		||||
  As with other Socks equivalents, direct addresses are handled
 | 
			
		||||
  transparently, that is data will be send directly when required 
 | 
			
		||||
  by the proxy settings.
 | 
			
		||||
  <p>
 | 
			
		||||
  <b>NOTE:</b><br>
 | 
			
		||||
  Unlike other SOCKS Sockets, it <b>does not</b> support proxy chaining,
 | 
			
		||||
  and will throw an exception if proxy has a chain proxy attached. The
 | 
			
		||||
  reason for that is not my laziness, but rather the restrictions of
 | 
			
		||||
  the SOCKSv5 protocol. Basicaly SOCKSv5 proxy server, needs to know from
 | 
			
		||||
  which host:port datagrams will be send for association, and returns address
 | 
			
		||||
  to which datagrams should be send by the client, but it does not
 | 
			
		||||
  inform client from which host:port it is going to send datagrams, in fact
 | 
			
		||||
  there is even no guarantee they will be send at all and from the same address
 | 
			
		||||
  each time.
 | 
			
		||||
 
 | 
			
		||||
 */
 | 
			
		||||
public class Socks5DatagramSocket extends DatagramSocket{
 | 
			
		||||
 | 
			
		||||
   InetAddress relayIP;
 | 
			
		||||
   int relayPort;
 | 
			
		||||
   Socks5Proxy proxy;
 | 
			
		||||
   private boolean server_mode = false;
 | 
			
		||||
   UDPEncapsulation encapsulation;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
      Construct Datagram socket for communication over SOCKS5 proxy
 | 
			
		||||
      server. This constructor uses default proxy, the one set with
 | 
			
		||||
      Proxy.setDefaultProxy() method. If default proxy is not set or 
 | 
			
		||||
      it is set to version4 proxy, which does not support datagram
 | 
			
		||||
      forwarding, throws SocksException.
 | 
			
		||||
 | 
			
		||||
    */
 | 
			
		||||
   public Socks5DatagramSocket() throws SocksException,
 | 
			
		||||
                                        IOException{
 | 
			
		||||
      this(Proxy.defaultProxy,0,null);
 | 
			
		||||
   }
 | 
			
		||||
   /**
 | 
			
		||||
      Construct Datagram socket for communication over SOCKS5 proxy
 | 
			
		||||
      server. And binds it to the specified local port.
 | 
			
		||||
      This constructor uses default proxy, the one set with
 | 
			
		||||
      Proxy.setDefaultProxy() method. If default proxy is not set or 
 | 
			
		||||
      it is set to version4 proxy, which does not support datagram
 | 
			
		||||
      forwarding, throws SocksException.
 | 
			
		||||
    */
 | 
			
		||||
   public Socks5DatagramSocket(int port) throws SocksException,
 | 
			
		||||
                                                IOException{
 | 
			
		||||
      this(Proxy.defaultProxy,port,null);
 | 
			
		||||
   }
 | 
			
		||||
   /**
 | 
			
		||||
      Construct Datagram socket for communication over SOCKS5 proxy
 | 
			
		||||
      server. And binds it to the specified local port and address.
 | 
			
		||||
      This constructor uses default proxy, the one set with
 | 
			
		||||
      Proxy.setDefaultProxy() method. If default proxy is not set or 
 | 
			
		||||
      it is set to version4 proxy, which does not support datagram
 | 
			
		||||
      forwarding, throws SocksException.
 | 
			
		||||
    */
 | 
			
		||||
   public Socks5DatagramSocket(int port,InetAddress ip) throws SocksException,
 | 
			
		||||
                                        IOException{
 | 
			
		||||
      this(Proxy.defaultProxy,port,ip);
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
     Constructs datagram socket for communication over specified proxy.
 | 
			
		||||
     And binds it to the given local address and port. Address of null 
 | 
			
		||||
     and port of 0, signify any availabale port/address.
 | 
			
		||||
     Might throw SocksException, if:
 | 
			
		||||
     <ol>
 | 
			
		||||
      <li> Given version of proxy does not support UDP_ASSOCIATE.
 | 
			
		||||
      <li> Proxy can't be reached.
 | 
			
		||||
      <li> Authorization fails.
 | 
			
		||||
      <li> Proxy does not want to perform udp forwarding, for any reason.
 | 
			
		||||
     </ol>
 | 
			
		||||
     Might throw IOException if binding dtagram socket to given address/port
 | 
			
		||||
     fails.
 | 
			
		||||
     See java.net.DatagramSocket for more details.
 | 
			
		||||
    */
 | 
			
		||||
   public Socks5DatagramSocket(Proxy p,int port,InetAddress ip)
 | 
			
		||||
                                        throws SocksException,
 | 
			
		||||
                                               IOException{
 | 
			
		||||
      super(port,ip);
 | 
			
		||||
      if(p == null) throw new SocksException(Proxy.SOCKS_NO_PROXY);
 | 
			
		||||
      if(!(p instanceof Socks5Proxy)) 
 | 
			
		||||
         throw new SocksException(-1,"Datagram Socket needs Proxy version 5");
 | 
			
		||||
 | 
			
		||||
      if(p.chainProxy != null)
 | 
			
		||||
           throw new SocksException(Proxy.SOCKS_JUST_ERROR,
 | 
			
		||||
               "Datagram Sockets do not support proxy chaining.");
 | 
			
		||||
 | 
			
		||||
      proxy =(Socks5Proxy) p.copy();
 | 
			
		||||
 | 
			
		||||
      ProxyMessage msg = proxy.udpAssociate(super.getLocalAddress(),
 | 
			
		||||
                                            super.getLocalPort());
 | 
			
		||||
      relayIP = msg.ip;
 | 
			
		||||
      if(relayIP.getHostAddress().equals("0.0.0.0")) relayIP = proxy.proxyIP;
 | 
			
		||||
      relayPort = msg.port;
 | 
			
		||||
 | 
			
		||||
      encapsulation = proxy.udp_encapsulation;
 | 
			
		||||
 | 
			
		||||
      //debug("Datagram Socket:"+getLocalAddress()+":"+getLocalPort()+"\n");
 | 
			
		||||
      //debug("Socks5Datagram: "+relayIP+":"+relayPort+"\n");
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
     Used by UDPRelayServer.
 | 
			
		||||
    */
 | 
			
		||||
   Socks5DatagramSocket(boolean server_mode,UDPEncapsulation encapsulation,
 | 
			
		||||
                        InetAddress relayIP,int relayPort)
 | 
			
		||||
                        throws IOException{
 | 
			
		||||
      super();
 | 
			
		||||
      this.server_mode = server_mode;
 | 
			
		||||
      this.relayIP = relayIP;
 | 
			
		||||
      this.relayPort = relayPort;
 | 
			
		||||
      this.encapsulation = encapsulation;
 | 
			
		||||
      this.proxy = null;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
     Sends the Datagram either through the proxy or directly depending
 | 
			
		||||
     on current proxy settings and destination address. <BR>
 | 
			
		||||
 | 
			
		||||
     <B> NOTE: </B> DatagramPacket size should be at least 10 bytes less
 | 
			
		||||
                    than the systems limit.
 | 
			
		||||
 | 
			
		||||
     <P>
 | 
			
		||||
     See documentation on java.net.DatagramSocket
 | 
			
		||||
     for full details on how to use this method. 
 | 
			
		||||
     @param dp Datagram to send.
 | 
			
		||||
     @throws IOException If error happens with I/O.
 | 
			
		||||
    */
 | 
			
		||||
   public void send(DatagramPacket dp) throws IOException{
 | 
			
		||||
     //If the host should be accessed directly, send it as is.
 | 
			
		||||
     if(!server_mode && proxy.isDirect(dp.getAddress())){
 | 
			
		||||
        super.send(dp);
 | 
			
		||||
        //debug("Sending directly:");
 | 
			
		||||
        return;
 | 
			
		||||
     }
 | 
			
		||||
 | 
			
		||||
     byte[] head = formHeader(dp.getAddress(),dp.getPort());
 | 
			
		||||
     byte[] buf = new byte[head.length + dp.getLength()];
 | 
			
		||||
     byte[] data = dp.getData();
 | 
			
		||||
     //Merge head and data
 | 
			
		||||
     System.arraycopy(head,0,buf,0,head.length);
 | 
			
		||||
     //System.arraycopy(data,dp.getOffset(),buf,head.length,dp.getLength());
 | 
			
		||||
     System.arraycopy(data,0,buf,head.length,dp.getLength());
 | 
			
		||||
 | 
			
		||||
     if(encapsulation != null)
 | 
			
		||||
        buf = encapsulation.udpEncapsulate(buf,true);
 | 
			
		||||
 | 
			
		||||
     super.send(new DatagramPacket(buf,buf.length,relayIP,relayPort));
 | 
			
		||||
   }
 | 
			
		||||
   /**
 | 
			
		||||
     This method allows to send datagram packets with address type DOMAINNAME.
 | 
			
		||||
     SOCKS5 allows to specify host as names rather than ip addresses.Using
 | 
			
		||||
     this method one can send udp datagrams through the proxy, without having
 | 
			
		||||
     to know the ip address of the destination host.
 | 
			
		||||
     <p> 
 | 
			
		||||
     If proxy specified for that socket has an option resolveAddrLocally set
 | 
			
		||||
     to true host will be resolved, and the datagram will be send with address
 | 
			
		||||
     type IPV4, if resolve fails, UnknownHostException is thrown.
 | 
			
		||||
     @param dp Datagram to send, it should contain valid port and data
 | 
			
		||||
     @param host Host name to which datagram should be send.
 | 
			
		||||
     @throws IOException If error happens with I/O, or the host can't be 
 | 
			
		||||
     resolved when proxy settings say that hosts should be resolved locally.
 | 
			
		||||
     @see Socks5Proxy#resolveAddrLocally(boolean)
 | 
			
		||||
    */
 | 
			
		||||
   public void send(DatagramPacket dp, String host) throws IOException{
 | 
			
		||||
     if(proxy.isDirect(host)){
 | 
			
		||||
        dp.setAddress(InetAddress.getByName(host));
 | 
			
		||||
        super.send(dp);
 | 
			
		||||
        return;
 | 
			
		||||
     }
 | 
			
		||||
 | 
			
		||||
     if(((Socks5Proxy)proxy).resolveAddrLocally){
 | 
			
		||||
        dp.setAddress(InetAddress.getByName(host));
 | 
			
		||||
     }
 | 
			
		||||
 | 
			
		||||
     byte[] head = formHeader(host,dp.getPort());
 | 
			
		||||
     byte[] buf = new byte[head.length + dp.getLength()];
 | 
			
		||||
     byte[] data = dp.getData();
 | 
			
		||||
     //Merge head and data
 | 
			
		||||
     System.arraycopy(head,0,buf,0,head.length);
 | 
			
		||||
     //System.arraycopy(data,dp.getOffset(),buf,head.length,dp.getLength());
 | 
			
		||||
     System.arraycopy(data,0,buf,head.length,dp.getLength());
 | 
			
		||||
 | 
			
		||||
     if(encapsulation != null)
 | 
			
		||||
        buf = encapsulation.udpEncapsulate(buf,true);
 | 
			
		||||
 | 
			
		||||
     super.send(new DatagramPacket(buf,buf.length,relayIP,relayPort));
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
    * Receives udp packet. If packet have arrived from the proxy relay server,
 | 
			
		||||
    * it is processed and address and port of the packet are set to the
 | 
			
		||||
    * address and port of sending host.<BR>
 | 
			
		||||
    * If the packet arrived from anywhere else it is not changed.<br>
 | 
			
		||||
    * <B> NOTE: </B> DatagramPacket size should be at least 10 bytes bigger
 | 
			
		||||
    * than the largest packet you expect (this is for IPV4 addresses). 
 | 
			
		||||
    * For hostnames and IPV6 it is even more.
 | 
			
		||||
      @param dp Datagram in which all relevent information will be copied.
 | 
			
		||||
    */
 | 
			
		||||
   public void receive(DatagramPacket dp) throws IOException{
 | 
			
		||||
      super.receive(dp);
 | 
			
		||||
 | 
			
		||||
      if(server_mode){
 | 
			
		||||
        //Drop all datagrams not from relayIP/relayPort
 | 
			
		||||
         int init_length = dp.getLength();
 | 
			
		||||
         int initTimeout = getSoTimeout();
 | 
			
		||||
         long startTime = System.currentTimeMillis();
 | 
			
		||||
 | 
			
		||||
         while(!relayIP.equals(dp.getAddress()) ||
 | 
			
		||||
                relayPort != dp.getPort()){
 | 
			
		||||
 | 
			
		||||
           //Restore datagram size
 | 
			
		||||
           dp.setLength(init_length);
 | 
			
		||||
 | 
			
		||||
           //If there is a non-infinit timeout on this socket
 | 
			
		||||
           //Make sure that it happens no matter how often unexpected
 | 
			
		||||
           //packets arrive.
 | 
			
		||||
           if(initTimeout != 0){
 | 
			
		||||
             int newTimeout = initTimeout - (int)(System.currentTimeMillis() - 
 | 
			
		||||
                                                        startTime);
 | 
			
		||||
             if(newTimeout <= 0) throw new InterruptedIOException(
 | 
			
		||||
                                 "In Socks5DatagramSocket->receive()");
 | 
			
		||||
             setSoTimeout(newTimeout);
 | 
			
		||||
           }
 | 
			
		||||
 | 
			
		||||
           super.receive(dp);
 | 
			
		||||
         }
 | 
			
		||||
 | 
			
		||||
         //Restore timeout settings
 | 
			
		||||
         if(initTimeout != 0) setSoTimeout(initTimeout);
 | 
			
		||||
 | 
			
		||||
      }else if(!relayIP.equals(dp.getAddress()) ||
 | 
			
		||||
                relayPort != dp.getPort()) 
 | 
			
		||||
          return; // Recieved direct packet
 | 
			
		||||
      //If the datagram is not from the relay server, return it it as is.
 | 
			
		||||
 | 
			
		||||
      byte[] data;
 | 
			
		||||
      data = dp.getData();
 | 
			
		||||
 | 
			
		||||
      if(encapsulation != null)
 | 
			
		||||
         data = encapsulation.udpEncapsulate(data,false);
 | 
			
		||||
 | 
			
		||||
      int offset = 0; //Java 1.1
 | 
			
		||||
      //int offset = dp.getOffset(); //Java 1.2
 | 
			
		||||
 | 
			
		||||
      ByteArrayInputStream bIn = new ByteArrayInputStream(data,offset,
 | 
			
		||||
                                                              dp.getLength());
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
      ProxyMessage msg = new Socks5Message(bIn);
 | 
			
		||||
      dp.setPort(msg.port);
 | 
			
		||||
      dp.setAddress(msg.getInetAddress());
 | 
			
		||||
 | 
			
		||||
      //what wasn't read by the Message is the data
 | 
			
		||||
      int data_length = bIn.available();
 | 
			
		||||
      //Shift data to the left
 | 
			
		||||
      System.arraycopy(data,offset+dp.getLength()-data_length,
 | 
			
		||||
                       data,offset,data_length);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
      dp.setLength(data_length);
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
    * Returns port assigned by the proxy, to which datagrams are relayed.
 | 
			
		||||
    * It is not the same port to which other party should send datagrams.
 | 
			
		||||
      @return Port assigned by socks server to which datagrams are send
 | 
			
		||||
      for association.
 | 
			
		||||
    */
 | 
			
		||||
   public int getLocalPort(){
 | 
			
		||||
     if(server_mode) return super.getLocalPort();
 | 
			
		||||
     return relayPort;
 | 
			
		||||
   }
 | 
			
		||||
   /**
 | 
			
		||||
    * Address assigned by the proxy, to which datagrams are send for relay.
 | 
			
		||||
    * It is not necesseraly the same address, to which other party should send
 | 
			
		||||
    * datagrams.
 | 
			
		||||
      @return Address to which datagrams are send for association.
 | 
			
		||||
    */
 | 
			
		||||
   public InetAddress getLocalAddress(){
 | 
			
		||||
     if(server_mode) return super.getLocalAddress();
 | 
			
		||||
     return relayIP;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
    * Closes datagram socket, and proxy connection.
 | 
			
		||||
    */
 | 
			
		||||
   public void close(){
 | 
			
		||||
      if(!server_mode) proxy.endSession();
 | 
			
		||||
      super.close();
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
     This method checks wether proxy still runs udp forwarding service
 | 
			
		||||
     for this socket.
 | 
			
		||||
     <p>
 | 
			
		||||
     This methods checks wether the primary connection to proxy server
 | 
			
		||||
     is active. If it is, chances are that proxy continues to forward
 | 
			
		||||
     datagrams being send from this socket. If it was closed, most likely
 | 
			
		||||
     datagrams are no longer being forwarded by the server.
 | 
			
		||||
     <p>
 | 
			
		||||
     Proxy might decide to stop forwarding datagrams, in which case it
 | 
			
		||||
     should close primary connection. This method allows to check, wether
 | 
			
		||||
     this have been done.
 | 
			
		||||
     <p>
 | 
			
		||||
     You can specify timeout for which we should be checking EOF condition
 | 
			
		||||
     on the primary connection. Timeout is in milliseconds. Specifying 0 as
 | 
			
		||||
     timeout implies infinity, in which case method will block, until 
 | 
			
		||||
     connection to proxy is closed or an error happens, and then return false.
 | 
			
		||||
     <p>
 | 
			
		||||
     One possible scenario is to call isProxyactive(0) in separate thread,
 | 
			
		||||
     and once it returned notify other threads about this event.
 | 
			
		||||
 | 
			
		||||
     @param timeout For how long this method should block, before returning.
 | 
			
		||||
     @return true if connection to proxy is active, false if eof or error
 | 
			
		||||
             condition have been encountered on the connection.
 | 
			
		||||
   */
 | 
			
		||||
   public boolean isProxyAlive(int timeout){
 | 
			
		||||
     if(server_mode) return false;
 | 
			
		||||
     if(proxy != null){
 | 
			
		||||
         try{
 | 
			
		||||
           proxy.proxySocket.setSoTimeout(timeout);
 | 
			
		||||
 | 
			
		||||
           int eof = proxy.in.read();
 | 
			
		||||
           if(eof < 0) return false; // EOF encountered.
 | 
			
		||||
           else return true;         // This really should not happen
 | 
			
		||||
 | 
			
		||||
         }catch(InterruptedIOException iioe){
 | 
			
		||||
            return true;          // read timed out.
 | 
			
		||||
         }catch(IOException ioe){
 | 
			
		||||
            return false;
 | 
			
		||||
         }
 | 
			
		||||
     }
 | 
			
		||||
     return false;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
//PRIVATE METHODS
 | 
			
		||||
//////////////////
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
   private byte[] formHeader(InetAddress ip, int port){
 | 
			
		||||
      Socks5Message request = new Socks5Message(0,ip,port);
 | 
			
		||||
      request.data[0] = 0;
 | 
			
		||||
      return request.data;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
   private byte[] formHeader(String host,int port){
 | 
			
		||||
      Socks5Message request = new Socks5Message(0,host,port);
 | 
			
		||||
      request.data[0] = 0;
 | 
			
		||||
      return request.data;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*======================================================================
 | 
			
		||||
 | 
			
		||||
//Mainly Test functions
 | 
			
		||||
//////////////////////
 | 
			
		||||
 | 
			
		||||
   private String bytes2String(byte[] b){
 | 
			
		||||
      String s="";
 | 
			
		||||
      char[] hex_digit = { '0','1','2','3','4','5','6','7','8','9',
 | 
			
		||||
                           'A','B','C','D','E','F'}; 
 | 
			
		||||
      for(int i=0;i<b.length;++i){
 | 
			
		||||
          int i1 = (b[i] & 0xF0) >> 4;
 | 
			
		||||
          int i2 = b[i] & 0xF;
 | 
			
		||||
          s+=hex_digit[i1];
 | 
			
		||||
          s+=hex_digit[i2];
 | 
			
		||||
          s+=" ";
 | 
			
		||||
      }
 | 
			
		||||
      return s;
 | 
			
		||||
   }
 | 
			
		||||
   private static final void debug(String s){
 | 
			
		||||
      if(DEBUG)
 | 
			
		||||
         System.out.print(s);
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   private static final boolean DEBUG = true;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
   public static void usage(){
 | 
			
		||||
      System.err.print(
 | 
			
		||||
    "Usage: java Socks.SocksDatagramSocket host port [socksHost socksPort]\n");
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   static final int defaultProxyPort = 1080;           //Default Port
 | 
			
		||||
   static final String defaultProxyHost = "www-proxy"; //Default proxy
 | 
			
		||||
 | 
			
		||||
   public static void main(String args[]){
 | 
			
		||||
      int port;
 | 
			
		||||
      String host;
 | 
			
		||||
      int proxyPort;
 | 
			
		||||
      String proxyHost;
 | 
			
		||||
      InetAddress ip;
 | 
			
		||||
 | 
			
		||||
      if(args.length > 1 && args.length < 5){
 | 
			
		||||
	 try{
 | 
			
		||||
 | 
			
		||||
	     host = args[0];
 | 
			
		||||
	     port = Integer.parseInt(args[1]);
 | 
			
		||||
 | 
			
		||||
	     proxyPort =(args.length > 3)? Integer.parseInt(args[3])	     
 | 
			
		||||
	                                 : defaultProxyPort;
 | 
			
		||||
 | 
			
		||||
	     host = args[0];
 | 
			
		||||
	     ip = InetAddress.getByName(host);
 | 
			
		||||
 | 
			
		||||
	     proxyHost =(args.length > 2)? args[2]
 | 
			
		||||
	                                 : defaultProxyHost;
 | 
			
		||||
 | 
			
		||||
	     Proxy.setDefaultProxy(proxyHost,proxyPort);
 | 
			
		||||
	     Proxy p = Proxy.getDefaultProxy();
 | 
			
		||||
	     p.addDirect("lux");
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	     DatagramSocket ds = new Socks5DatagramSocket();
 | 
			
		||||
	                             
 | 
			
		||||
 | 
			
		||||
	     BufferedReader in = new BufferedReader(
 | 
			
		||||
				 new InputStreamReader(System.in));
 | 
			
		||||
             String s;
 | 
			
		||||
 | 
			
		||||
             System.out.print("Enter line:");
 | 
			
		||||
             s = in.readLine();
 | 
			
		||||
 | 
			
		||||
	     while(s != null){
 | 
			
		||||
                byte[] data = (s+"\r\n").getBytes();
 | 
			
		||||
                DatagramPacket dp = new DatagramPacket(data,0,data.length,
 | 
			
		||||
                                        ip,port);
 | 
			
		||||
                System.out.println("Sending to: "+ip+":"+port);
 | 
			
		||||
                ds.send(dp);
 | 
			
		||||
	        dp = new DatagramPacket(new byte[1024],1024);
 | 
			
		||||
 | 
			
		||||
	        System.out.println("Trying to recieve on port:"+
 | 
			
		||||
	                            ds.getLocalPort());
 | 
			
		||||
	        ds.receive(dp);
 | 
			
		||||
	        System.out.print("Recieved:\n"+
 | 
			
		||||
	                         "From:"+dp.getAddress()+":"+dp.getPort()+
 | 
			
		||||
	                         "\n\n"+
 | 
			
		||||
                new String(dp.getData(),dp.getOffset(),dp.getLength())+"\n"
 | 
			
		||||
                );
 | 
			
		||||
                System.out.print("Enter line:");
 | 
			
		||||
                s = in.readLine();
 | 
			
		||||
 | 
			
		||||
	     }
 | 
			
		||||
	     ds.close();
 | 
			
		||||
	     System.exit(1);
 | 
			
		||||
 | 
			
		||||
	 }catch(SocksException s_ex){
 | 
			
		||||
	   System.err.println("SocksException:"+s_ex);
 | 
			
		||||
	   s_ex.printStackTrace();
 | 
			
		||||
	   System.exit(1); 
 | 
			
		||||
	 }catch(IOException io_ex){
 | 
			
		||||
	   io_ex.printStackTrace();
 | 
			
		||||
	   System.exit(1);
 | 
			
		||||
	 }catch(NumberFormatException num_ex){
 | 
			
		||||
	   usage();
 | 
			
		||||
	   num_ex.printStackTrace();
 | 
			
		||||
	   System.exit(1);
 | 
			
		||||
	 }
 | 
			
		||||
 | 
			
		||||
      }else{
 | 
			
		||||
	usage();
 | 
			
		||||
      }
 | 
			
		||||
   }
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,292 @@
 | 
			
		|||
package net.sourceforge.jsocks.socks;
 | 
			
		||||
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.io.InputStream;
 | 
			
		||||
import java.io.OutputStream;
 | 
			
		||||
import java.io.DataInputStream;
 | 
			
		||||
import java.net.InetAddress;
 | 
			
		||||
import java.net.UnknownHostException;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 SOCKS5 request/response message.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
class Socks5Message extends ProxyMessage{
 | 
			
		||||
   /** Address type of given message*/
 | 
			
		||||
   public int addrType;
 | 
			
		||||
 | 
			
		||||
   byte[] data;
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
    Server error response.
 | 
			
		||||
    @param cmd Error code.
 | 
			
		||||
   */
 | 
			
		||||
   public Socks5Message(int cmd){
 | 
			
		||||
      super(cmd,null,0);
 | 
			
		||||
      data = new byte[3];
 | 
			
		||||
      data[0] = SOCKS_VERSION; //Version.
 | 
			
		||||
      data[1] = (byte)cmd;     //Reply code for some kind of failure.
 | 
			
		||||
      data[2] = 0;             //Reserved byte.
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
    Construct client request or server response.
 | 
			
		||||
    @param cmd - Request/Response code.
 | 
			
		||||
    @param ip  - IP field.
 | 
			
		||||
    @paarm port - port field.
 | 
			
		||||
   */
 | 
			
		||||
   public Socks5Message(int cmd,InetAddress ip,int port){
 | 
			
		||||
      super(cmd,ip,port);
 | 
			
		||||
      this.host = ip==null?"0.0.0.0":ip.getHostName();
 | 
			
		||||
      this.version = SOCKS_VERSION;
 | 
			
		||||
 | 
			
		||||
      byte[] addr;
 | 
			
		||||
 | 
			
		||||
      if(ip == null){
 | 
			
		||||
         addr = new byte[4];
 | 
			
		||||
         addr[0]=addr[1]=addr[2]=addr[3]=0;
 | 
			
		||||
      }else
 | 
			
		||||
         addr = ip.getAddress();
 | 
			
		||||
 | 
			
		||||
      addrType = addr.length == 4 ? SOCKS_ATYP_IPV4
 | 
			
		||||
                                  : SOCKS_ATYP_IPV6;
 | 
			
		||||
 
 | 
			
		||||
      data = new byte[6+addr.length];
 | 
			
		||||
      data[0] = (byte) SOCKS_VERSION;		//Version
 | 
			
		||||
      data[1] = (byte) command;			//Command
 | 
			
		||||
      data[2] = (byte) 0;			//Reserved byte
 | 
			
		||||
      data[3] = (byte) addrType;		//Address type
 | 
			
		||||
 
 | 
			
		||||
      //Put Address
 | 
			
		||||
      System.arraycopy(addr,0,data,4,addr.length);
 | 
			
		||||
      //Put port
 | 
			
		||||
      data[data.length-2] = (byte)(port>>8);
 | 
			
		||||
      data[data.length-1] = (byte)(port);
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
    Construct client request or server response.
 | 
			
		||||
    @param cmd - Request/Response code.
 | 
			
		||||
    @param hostName  - IP field as hostName, uses ADDR_TYPE of HOSTNAME.
 | 
			
		||||
    @paarm port - port field.
 | 
			
		||||
   */
 | 
			
		||||
   public Socks5Message(int cmd,String hostName,int port){
 | 
			
		||||
      super(cmd,null,port);
 | 
			
		||||
      this.host = hostName;
 | 
			
		||||
      this.version = SOCKS_VERSION;
 | 
			
		||||
 | 
			
		||||
      //System.out.println("Doing ATYP_DOMAINNAME");
 | 
			
		||||
 | 
			
		||||
      addrType = SOCKS_ATYP_DOMAINNAME;
 | 
			
		||||
      byte addr[] = hostName.getBytes();
 | 
			
		||||
 
 | 
			
		||||
      data =new byte[7+addr.length];
 | 
			
		||||
      data[0] = (byte) SOCKS_VERSION;		//Version
 | 
			
		||||
      data[1] = (byte) command;			//Command
 | 
			
		||||
      data[2] = (byte) 0;			//Reserved byte
 | 
			
		||||
      data[3] = (byte) SOCKS_ATYP_DOMAINNAME;	//Address type
 | 
			
		||||
      data[4] = (byte) addr.length;		//Length of the address
 | 
			
		||||
 | 
			
		||||
      //Put Address
 | 
			
		||||
      System.arraycopy(addr,0,data,5,addr.length);
 | 
			
		||||
      //Put port
 | 
			
		||||
      data[data.length-2] = (byte)(port >>8);
 | 
			
		||||
      data[data.length-1] = (byte)(port);
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
     Initialises Message from the stream. Reads server response from
 | 
			
		||||
     given stream.
 | 
			
		||||
     @param in Input stream to read response from.
 | 
			
		||||
     @throws SocksException If server response code is not SOCKS_SUCCESS(0), or
 | 
			
		||||
     if any error with protocol occurs.
 | 
			
		||||
     @throws IOException If any error happens with I/O.
 | 
			
		||||
   */
 | 
			
		||||
   public Socks5Message(InputStream in) throws SocksException,
 | 
			
		||||
                                              IOException{
 | 
			
		||||
      this(in,true);
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
     Initializes Message from the stream. Reads server response or client 
 | 
			
		||||
     request from given stream.
 | 
			
		||||
     
 | 
			
		||||
     @param in Input stream to read response from.
 | 
			
		||||
     @param clientMode If true read server response, else read client request.
 | 
			
		||||
     @throws SocksException If server response code is not SOCKS_SUCCESS(0) and
 | 
			
		||||
     reading in client mode, or if any error with protocol occurs.
 | 
			
		||||
     @throws IOException If any error happens with I/O.
 | 
			
		||||
   */
 | 
			
		||||
   public Socks5Message(InputStream in,boolean clientMode)throws SocksException,
 | 
			
		||||
                                              IOException{
 | 
			
		||||
      read(in,clientMode);
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
     Initialises Message from the stream. Reads server response from
 | 
			
		||||
     given stream.
 | 
			
		||||
     @param in Input stream to read response from.
 | 
			
		||||
     @throws SocksException If server response code is not SOCKS_SUCCESS(0), or
 | 
			
		||||
     if any error with protocol occurs.
 | 
			
		||||
     @throws IOException If any error happens with I/O.
 | 
			
		||||
   */
 | 
			
		||||
   public void read(InputStream in) throws SocksException,
 | 
			
		||||
                                           IOException{
 | 
			
		||||
       read(in,true);
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
     Initializes Message from the stream. Reads server response or client 
 | 
			
		||||
     request from given stream.
 | 
			
		||||
     
 | 
			
		||||
     @param in Input stream to read response from.
 | 
			
		||||
     @param clientMode If true read server response, else read client request.
 | 
			
		||||
     @throws SocksException If server response code is not SOCKS_SUCCESS(0) and
 | 
			
		||||
     reading in client mode, or if any error with protocol occurs.
 | 
			
		||||
     @throws IOException If any error happens with I/O.
 | 
			
		||||
   */
 | 
			
		||||
   @Override
 | 
			
		||||
   public void read(InputStream in,boolean clientMode) throws SocksException,
 | 
			
		||||
                                           IOException{
 | 
			
		||||
      data = null;
 | 
			
		||||
      ip = null;
 | 
			
		||||
 | 
			
		||||
      DataInputStream di = new DataInputStream(in);
 | 
			
		||||
 | 
			
		||||
      version = di.readUnsignedByte();
 | 
			
		||||
      command = di.readUnsignedByte();
 | 
			
		||||
      if(clientMode && command != 0)
 | 
			
		||||
        throw new SocksException(command);
 | 
			
		||||
 | 
			
		||||
      int reserved = di.readUnsignedByte();
 | 
			
		||||
      addrType = di.readUnsignedByte();
 | 
			
		||||
 | 
			
		||||
      byte addr[];
 | 
			
		||||
 | 
			
		||||
      switch(addrType){
 | 
			
		||||
         case SOCKS_ATYP_IPV4:
 | 
			
		||||
            addr = new byte[4];
 | 
			
		||||
            di.readFully(addr);
 | 
			
		||||
            host = bytes2IPV4(addr,0);
 | 
			
		||||
         break;
 | 
			
		||||
         case SOCKS_ATYP_IPV6:
 | 
			
		||||
           addr = new byte[SOCKS_IPV6_LENGTH];//I believe it is 16 bytes,huge!
 | 
			
		||||
           di.readFully(addr);
 | 
			
		||||
           host = bytes2IPV6(addr,0);
 | 
			
		||||
         break;
 | 
			
		||||
         case SOCKS_ATYP_DOMAINNAME:
 | 
			
		||||
           //System.out.println("Reading ATYP_DOMAINNAME");
 | 
			
		||||
           addr = new byte[di.readUnsignedByte()];//Next byte shows the length
 | 
			
		||||
           di.readFully(addr);
 | 
			
		||||
           host = new String(addr);
 | 
			
		||||
         break;
 | 
			
		||||
         default:
 | 
			
		||||
            throw(new SocksException(Proxy.SOCKS_JUST_ERROR));
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      port = di.readUnsignedShort();
 | 
			
		||||
 | 
			
		||||
      if(addrType != SOCKS_ATYP_DOMAINNAME && doResolveIP){
 | 
			
		||||
         try{
 | 
			
		||||
            ip = InetAddress.getByName(host);
 | 
			
		||||
         }catch(UnknownHostException uh_ex){
 | 
			
		||||
         }
 | 
			
		||||
      }
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
    Writes the message to the stream.
 | 
			
		||||
    @param out Output stream to which message should be written.
 | 
			
		||||
   */
 | 
			
		||||
   public void write(OutputStream out)throws SocksException,
 | 
			
		||||
                                             IOException{
 | 
			
		||||
     if(data == null){
 | 
			
		||||
       Socks5Message msg;
 | 
			
		||||
 | 
			
		||||
       if(addrType == SOCKS_ATYP_DOMAINNAME)
 | 
			
		||||
          msg = new Socks5Message(command,host,port);
 | 
			
		||||
       else{
 | 
			
		||||
          if(ip == null){
 | 
			
		||||
             try{
 | 
			
		||||
               ip = InetAddress.getByName(host);
 | 
			
		||||
             }catch(UnknownHostException uh_ex){
 | 
			
		||||
               throw new SocksException(Proxy.SOCKS_JUST_ERROR);
 | 
			
		||||
             }
 | 
			
		||||
          }
 | 
			
		||||
          msg = new Socks5Message(command,ip,port);
 | 
			
		||||
       }
 | 
			
		||||
       data = msg.data;
 | 
			
		||||
     }
 | 
			
		||||
     out.write(data);
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
    Returns IP field of the message as IP, if the message was created
 | 
			
		||||
    with ATYP of HOSTNAME, it will attempt to resolve the hostname,
 | 
			
		||||
    which might fail.
 | 
			
		||||
    @throws UnknownHostException if host can't be resolved.
 | 
			
		||||
   */
 | 
			
		||||
   public InetAddress getInetAddress() throws UnknownHostException{
 | 
			
		||||
     if(ip!=null) return ip;
 | 
			
		||||
 | 
			
		||||
     return (ip=InetAddress.getByName(host));
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
     Returns string representation of the message.
 | 
			
		||||
   */
 | 
			
		||||
   public String toString(){
 | 
			
		||||
      String s=
 | 
			
		||||
        "Socks5Message:"+"\n"+
 | 
			
		||||
        "VN   "+version+"\n"+
 | 
			
		||||
        "CMD  "+command+"\n"+
 | 
			
		||||
        "ATYP "+addrType+"\n"+
 | 
			
		||||
        "ADDR "+host+"\n"+
 | 
			
		||||
        "PORT "+port+"\n";
 | 
			
		||||
      return s;
 | 
			
		||||
   }
 | 
			
		||||
            
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
    *Wether to resolve hostIP returned from SOCKS server
 | 
			
		||||
    *that is wether to create InetAddress object from the
 | 
			
		||||
    *hostName string
 | 
			
		||||
    */
 | 
			
		||||
   static public boolean resolveIP(){ return doResolveIP;}
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
    *Wether to resolve hostIP returned from SOCKS server
 | 
			
		||||
    *that is wether to create InetAddress object from the
 | 
			
		||||
    *hostName string
 | 
			
		||||
    *@param doResolve Wether to resolve hostIP from SOCKS server.
 | 
			
		||||
    *@return Previous value.
 | 
			
		||||
    */
 | 
			
		||||
   static public boolean resolveIP(boolean doResolve){
 | 
			
		||||
      boolean old = doResolveIP;
 | 
			
		||||
      doResolveIP = doResolve;
 | 
			
		||||
      return old;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   /*
 | 
			
		||||
   private static final void debug(String s){
 | 
			
		||||
      if(DEBUG)
 | 
			
		||||
         System.out.print(s);
 | 
			
		||||
   }
 | 
			
		||||
   private static final boolean DEBUG = false;
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
   //SOCKS5 constants
 | 
			
		||||
   public static final int SOCKS_VERSION		=5;
 | 
			
		||||
 | 
			
		||||
   public static final int SOCKS_ATYP_IPV4		=0x1; //Where is 2??
 | 
			
		||||
   public static final int SOCKS_ATYP_DOMAINNAME	=0x3; //!!!!rfc1928
 | 
			
		||||
   public static final int SOCKS_ATYP_IPV6		=0x4;
 | 
			
		||||
 | 
			
		||||
   public static final int SOCKS_IPV6_LENGTH		=16;
 | 
			
		||||
 | 
			
		||||
   static boolean doResolveIP = true;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,253 @@
 | 
			
		|||
package net.sourceforge.jsocks.socks;
 | 
			
		||||
 | 
			
		||||
import java.net.InetAddress;
 | 
			
		||||
import java.net.Socket;
 | 
			
		||||
import java.net.SocketException;
 | 
			
		||||
import java.net.UnknownHostException;
 | 
			
		||||
import java.io.*;
 | 
			
		||||
import java.util.Hashtable;
 | 
			
		||||
import java.util.Enumeration;
 | 
			
		||||
 | 
			
		||||
import net.*;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 SOCKS5 Proxy.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
public class Socks5Proxy extends Proxy implements Cloneable{
 | 
			
		||||
 | 
			
		||||
//Data members
 | 
			
		||||
   private Hashtable authMethods = new Hashtable();
 | 
			
		||||
   private int selectedMethod;
 | 
			
		||||
 | 
			
		||||
   boolean resolveAddrLocally = true;
 | 
			
		||||
   UDPEncapsulation udp_encapsulation=null;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//Public Constructors
 | 
			
		||||
//====================
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
     Creates SOCKS5 proxy.
 | 
			
		||||
     @param p Proxy to use to connect to this proxy, allows proxy chaining.
 | 
			
		||||
     @param proxyHost Host on which a Proxy server runs.
 | 
			
		||||
     @param proxyPort Port on which a Proxy server listens for connections.
 | 
			
		||||
     @throws UnknownHostException If proxyHost can't be resolved.
 | 
			
		||||
   */
 | 
			
		||||
   public Socks5Proxy(Proxy p,String proxyHost,int proxyPort)
 | 
			
		||||
          throws UnknownHostException{ 
 | 
			
		||||
      super(p,proxyHost,proxyPort);
 | 
			
		||||
      version = 5;
 | 
			
		||||
      setAuthenticationMethod(0,new AuthenticationNone());
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
     Creates SOCKS5 proxy.
 | 
			
		||||
     @param proxyHost Host on which a Proxy server runs.
 | 
			
		||||
     @param proxyPort Port on which a Proxy server listens for connections.
 | 
			
		||||
     @throws UnknownHostException If proxyHost can't be resolved.
 | 
			
		||||
   */
 | 
			
		||||
   public Socks5Proxy(String proxyHost,int proxyPort)
 | 
			
		||||
          throws UnknownHostException{ 
 | 
			
		||||
      this(null,proxyHost,proxyPort);
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
     Creates SOCKS5 proxy.
 | 
			
		||||
     @param p Proxy to use to connect to this proxy, allows proxy chaining.
 | 
			
		||||
     @param proxyIP Host on which a Proxy server runs.
 | 
			
		||||
     @param proxyPort Port on which a Proxy server listens for connections.
 | 
			
		||||
   */
 | 
			
		||||
   public Socks5Proxy(Proxy p,InetAddress proxyIP,int proxyPort){
 | 
			
		||||
      super(p,proxyIP,proxyPort);
 | 
			
		||||
      version = 5;
 | 
			
		||||
      setAuthenticationMethod(0,new AuthenticationNone());
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
     Creates SOCKS5 proxy.
 | 
			
		||||
     @param proxyIP Host on which a Proxy server runs.
 | 
			
		||||
     @param proxyPort Port on which a Proxy server listens for connections.
 | 
			
		||||
   */
 | 
			
		||||
   public Socks5Proxy(InetAddress proxyIP,int proxyPort){
 | 
			
		||||
      this(null,proxyIP,proxyPort);
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
//Public instance methods
 | 
			
		||||
//========================
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
    * Wether to resolve address locally or to let proxy do so.
 | 
			
		||||
      <p>
 | 
			
		||||
      SOCKS5 protocol allows to send host names rather then IPs in the
 | 
			
		||||
      requests, this option controls wether the hostnames should be send
 | 
			
		||||
      to the proxy server as names, or should they be resolved locally.
 | 
			
		||||
      @param doResolve Wether to perform resolution locally.
 | 
			
		||||
      @return Previous settings.
 | 
			
		||||
    */
 | 
			
		||||
   public boolean resolveAddrLocally(boolean doResolve){
 | 
			
		||||
      boolean old = resolveAddrLocally;
 | 
			
		||||
      resolveAddrLocally = doResolve;
 | 
			
		||||
      return old;
 | 
			
		||||
   }
 | 
			
		||||
   /**
 | 
			
		||||
    Get current setting on how the addresses should be handled.
 | 
			
		||||
    @return Current setting for address resolution.
 | 
			
		||||
    @see Socks5Proxy#resolveAddrLocally(boolean doResolve)
 | 
			
		||||
   */
 | 
			
		||||
   public boolean resolveAddrLocally(){
 | 
			
		||||
      return resolveAddrLocally;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
     Adds another authentication method.
 | 
			
		||||
     @param methodId Authentication method id, see rfc1928
 | 
			
		||||
     @param method Implementation of Authentication
 | 
			
		||||
     @see Authentication
 | 
			
		||||
   */
 | 
			
		||||
   public boolean setAuthenticationMethod(int methodId,
 | 
			
		||||
                                          Authentication method){
 | 
			
		||||
      if(methodId<0 || methodId > 255)
 | 
			
		||||
          return false;
 | 
			
		||||
      if(method == null){
 | 
			
		||||
        //Want to remove a particular method
 | 
			
		||||
	return (authMethods.remove(new Integer(methodId)) != null);
 | 
			
		||||
      }else{//Add the method, or rewrite old one
 | 
			
		||||
	authMethods.put(new Integer(methodId),method);
 | 
			
		||||
      }
 | 
			
		||||
      return true;
 | 
			
		||||
   }
 | 
			
		||||
   
 | 
			
		||||
   /**
 | 
			
		||||
    Get authentication method, which corresponds to given method id
 | 
			
		||||
    @param methodId Authentication method id.
 | 
			
		||||
    @return Implementation for given method or null, if one was not set.
 | 
			
		||||
   */
 | 
			
		||||
   public Authentication getAuthenticationMethod(int methodId){
 | 
			
		||||
      Object method = authMethods.get(new Integer(methodId));
 | 
			
		||||
      if(method == null) return null;
 | 
			
		||||
      return (Authentication)method;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
    Creates a clone of this Proxy.
 | 
			
		||||
   */
 | 
			
		||||
   public Object clone(){
 | 
			
		||||
      Socks5Proxy newProxy = new Socks5Proxy(proxyIP,proxyPort);
 | 
			
		||||
      newProxy.authMethods = (Hashtable) this.authMethods.clone();
 | 
			
		||||
      newProxy.directHosts = (InetRange)directHosts.clone();
 | 
			
		||||
      newProxy.resolveAddrLocally = resolveAddrLocally;
 | 
			
		||||
      newProxy.chainProxy = chainProxy;
 | 
			
		||||
      return newProxy;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
//Public Static(Class) Methods
 | 
			
		||||
//==============================
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//Protected Methods
 | 
			
		||||
//=================
 | 
			
		||||
 | 
			
		||||
   protected Proxy copy(){
 | 
			
		||||
       Socks5Proxy copy = new Socks5Proxy(proxyIP,proxyPort);
 | 
			
		||||
       copy.authMethods = this.authMethods; //same Hash, no copy
 | 
			
		||||
       copy.directHosts = this.directHosts;
 | 
			
		||||
       copy.chainProxy = this.chainProxy;
 | 
			
		||||
       copy.resolveAddrLocally = this.resolveAddrLocally;
 | 
			
		||||
       return copy;
 | 
			
		||||
    }
 | 
			
		||||
   /**
 | 
			
		||||
    *
 | 
			
		||||
    *
 | 
			
		||||
    */
 | 
			
		||||
   protected void startSession()throws SocksException{
 | 
			
		||||
      super.startSession();
 | 
			
		||||
      Authentication auth;
 | 
			
		||||
      Socket ps = proxySocket; //The name is too long
 | 
			
		||||
 | 
			
		||||
      try{
 | 
			
		||||
        byte nMethods = (byte) authMethods.size();  //Number of methods
 | 
			
		||||
 | 
			
		||||
        byte[] buf = new byte[2+nMethods]; //2 is for VER,NMETHODS
 | 
			
		||||
        buf[0] = (byte) version;
 | 
			
		||||
        buf[1] = nMethods;                 //Number of methods 
 | 
			
		||||
        int i=2;
 | 
			
		||||
 | 
			
		||||
        Enumeration ids = authMethods.keys();
 | 
			
		||||
        while(ids.hasMoreElements())
 | 
			
		||||
          buf[i++] = (byte)((Integer)ids.nextElement()).intValue();
 | 
			
		||||
 | 
			
		||||
        out.write(buf);
 | 
			
		||||
        out.flush();
 | 
			
		||||
 | 
			
		||||
        int versionNumber  = in.read();
 | 
			
		||||
        selectedMethod = in.read();
 | 
			
		||||
 | 
			
		||||
        if(versionNumber < 0 || selectedMethod < 0){
 | 
			
		||||
          //EOF condition was reached
 | 
			
		||||
          endSession();
 | 
			
		||||
          throw(new SocksException(SOCKS_PROXY_IO_ERROR,
 | 
			
		||||
          "Connection to proxy lost."));
 | 
			
		||||
        }
 | 
			
		||||
        if(versionNumber < version){
 | 
			
		||||
          //What should we do??
 | 
			
		||||
        }
 | 
			
		||||
        if(selectedMethod == 0xFF){ //No method selected
 | 
			
		||||
          ps.close();
 | 
			
		||||
          throw ( new SocksException(SOCKS_AUTH_NOT_SUPPORTED));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        auth = getAuthenticationMethod(selectedMethod);
 | 
			
		||||
        if(auth == null){
 | 
			
		||||
          //This shouldn't happen, unless method was removed by other
 | 
			
		||||
          //thread, or the server stuffed up
 | 
			
		||||
          throw(new SocksException(SOCKS_JUST_ERROR,
 | 
			
		||||
          "Speciefied Authentication not found!"));
 | 
			
		||||
        }
 | 
			
		||||
        Object[] in_out = auth.doSocksAuthentication(selectedMethod,ps);
 | 
			
		||||
        if(in_out == null){
 | 
			
		||||
          //Authentication failed by some reason
 | 
			
		||||
          throw(new SocksException(SOCKS_AUTH_FAILURE));
 | 
			
		||||
        }
 | 
			
		||||
        //Most authentication methods are expected to return
 | 
			
		||||
        //simply the input/output streams associated with
 | 
			
		||||
        //the socket. However if the auth. method requires
 | 
			
		||||
        //some kind of encryption/decryption being done on the
 | 
			
		||||
        //connection it should provide classes to handle I/O.
 | 
			
		||||
 | 
			
		||||
        in = (InputStream) in_out[0];
 | 
			
		||||
        out = (OutputStream) in_out[1];
 | 
			
		||||
        if(in_out.length > 2) 
 | 
			
		||||
          udp_encapsulation = (UDPEncapsulation) in_out[2];
 | 
			
		||||
 | 
			
		||||
      }catch(SocksException s_ex){
 | 
			
		||||
        throw s_ex;
 | 
			
		||||
      }catch(UnknownHostException uh_ex){
 | 
			
		||||
        throw(new SocksException(SOCKS_PROXY_NO_CONNECT));
 | 
			
		||||
      }catch(SocketException so_ex){
 | 
			
		||||
        throw(new SocksException(SOCKS_PROXY_NO_CONNECT));
 | 
			
		||||
      }catch(IOException io_ex){
 | 
			
		||||
        //System.err.println(io_ex);
 | 
			
		||||
        throw(new SocksException(SOCKS_PROXY_IO_ERROR,""+io_ex));
 | 
			
		||||
      }
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   protected ProxyMessage formMessage(int cmd,InetAddress ip,int port){
 | 
			
		||||
       return new Socks5Message(cmd,ip,port);
 | 
			
		||||
   }
 | 
			
		||||
   protected ProxyMessage formMessage(int cmd,String host,int port)
 | 
			
		||||
             throws UnknownHostException{
 | 
			
		||||
       if(resolveAddrLocally)
 | 
			
		||||
          return formMessage(cmd,InetAddress.getByName(host),port);
 | 
			
		||||
       else
 | 
			
		||||
          return new Socks5Message(cmd,host,port);
 | 
			
		||||
   }
 | 
			
		||||
   protected ProxyMessage formMessage(InputStream in)
 | 
			
		||||
             throws SocksException,
 | 
			
		||||
                    IOException{
 | 
			
		||||
       return new Socks5Message(in);
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,78 @@
 | 
			
		|||
package net.sourceforge.jsocks.socks;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 Exception thrown by various socks classes to indicate errors
 | 
			
		||||
 with protocol or unsuccessful server responses.
 | 
			
		||||
*/
 | 
			
		||||
public class SocksException extends java.io.IOException{
 | 
			
		||||
   /**
 | 
			
		||||
    Construct a SocksException with given error code.
 | 
			
		||||
    <p>
 | 
			
		||||
    Tries to look up message which corresponds to this error code.
 | 
			
		||||
    @param errCode Error code for this exception.
 | 
			
		||||
   */
 | 
			
		||||
   public SocksException(int errCode){
 | 
			
		||||
       this.errCode = errCode;
 | 
			
		||||
       if((errCode >> 16) == 0){
 | 
			
		||||
          //Server reply error message
 | 
			
		||||
          errString = errCode <= serverReplyMessage.length ?
 | 
			
		||||
                      serverReplyMessage[errCode] :
 | 
			
		||||
                      UNASSIGNED_ERROR_MESSAGE;
 | 
			
		||||
       }else{
 | 
			
		||||
          //Local error
 | 
			
		||||
          errCode = (errCode >> 16) -1;
 | 
			
		||||
          errString = errCode <= localErrorMessage.length ?
 | 
			
		||||
                      localErrorMessage[errCode] :
 | 
			
		||||
                      UNASSIGNED_ERROR_MESSAGE;
 | 
			
		||||
       }
 | 
			
		||||
   }
 | 
			
		||||
   /**
 | 
			
		||||
    Constructs a SocksException with given error code and message.
 | 
			
		||||
    @param errCode  Error code.
 | 
			
		||||
    @param errString Error Message.
 | 
			
		||||
   */
 | 
			
		||||
   public SocksException(int errCode,String errString){
 | 
			
		||||
       this.errCode = errCode;
 | 
			
		||||
       this.errString = errString;
 | 
			
		||||
   }
 | 
			
		||||
   /**
 | 
			
		||||
    Get the error code associated with this exception.
 | 
			
		||||
    @return Error code associated with this exception.
 | 
			
		||||
   */
 | 
			
		||||
   public int getErrorCode(){
 | 
			
		||||
      return errCode;
 | 
			
		||||
   }
 | 
			
		||||
   /**
 | 
			
		||||
    Get human readable representation of this exception.
 | 
			
		||||
    @return String represntation of this exception.
 | 
			
		||||
   */
 | 
			
		||||
   public String toString(){
 | 
			
		||||
      return errString;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   static final String UNASSIGNED_ERROR_MESSAGE =
 | 
			
		||||
                  "Unknown error message";
 | 
			
		||||
   static final String serverReplyMessage[] = { 
 | 
			
		||||
                  "Succeeded", 
 | 
			
		||||
                  "General SOCKS server failure",
 | 
			
		||||
                  "Connection not allowed by ruleset",
 | 
			
		||||
                  "Network unreachable",
 | 
			
		||||
                  "Host unreachable",
 | 
			
		||||
                  "Connection refused",
 | 
			
		||||
                  "TTL expired",
 | 
			
		||||
                  "Command not supported",
 | 
			
		||||
                  "Address type not supported" };
 | 
			
		||||
 | 
			
		||||
   static final String localErrorMessage[] ={
 | 
			
		||||
                  "SOCKS server not specified",
 | 
			
		||||
                  "Unable to contact SOCKS server",
 | 
			
		||||
                  "IO error",
 | 
			
		||||
                  "None of Authentication methods are supported",
 | 
			
		||||
                  "Authentication failed",
 | 
			
		||||
                  "General SOCKS fault" };
 | 
			
		||||
 | 
			
		||||
   String errString;
 | 
			
		||||
   int errCode;
 | 
			
		||||
 | 
			
		||||
}//End of SocksException class
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,213 @@
 | 
			
		|||
package net.sourceforge.jsocks.socks;
 | 
			
		||||
 | 
			
		||||
import java.net.InetAddress;
 | 
			
		||||
import java.net.ServerSocket;
 | 
			
		||||
import java.net.Socket;
 | 
			
		||||
import java.net.SocketException;
 | 
			
		||||
import java.net.UnknownHostException;
 | 
			
		||||
import java.io.*;
 | 
			
		||||
 | 
			
		||||
import net.*;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
   SocksServerSocket allows to accept connections from one particular
 | 
			
		||||
   host through the SOCKS4 or SOCKS5 proxy.
 | 
			
		||||
*/
 | 
			
		||||
public class SocksServerSocket extends ServerSocket{
 | 
			
		||||
   //Data members
 | 
			
		||||
   protected Proxy proxy;
 | 
			
		||||
   protected String localHost;
 | 
			
		||||
   protected InetAddress localIP;
 | 
			
		||||
   protected int localPort;
 | 
			
		||||
 | 
			
		||||
   boolean doing_direct = false;
 | 
			
		||||
   InetAddress  remoteAddr;
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
    * Creates ServerSocket capable of accepting one connection
 | 
			
		||||
    * through the firewall, uses default Proxy.
 | 
			
		||||
    *@param host Host from which the connection should be recieved.
 | 
			
		||||
    *@param port Port number of the primary connection.
 | 
			
		||||
    */
 | 
			
		||||
   public SocksServerSocket(String host,int port)
 | 
			
		||||
	  throws SocksException,UnknownHostException,IOException{
 | 
			
		||||
      this(Proxy.defaultProxy,host,port);
 | 
			
		||||
   }
 | 
			
		||||
   /**
 | 
			
		||||
    *Creates ServerSocket capable of accepting one connection
 | 
			
		||||
    *through the firewall, uses given proxy.
 | 
			
		||||
    *@param p    Proxy object to use.
 | 
			
		||||
    *@param host Host from which the connection should be recieved.
 | 
			
		||||
    *@param port Port number of the primary connection.
 | 
			
		||||
    */
 | 
			
		||||
   public SocksServerSocket(Proxy p,String host,int port)
 | 
			
		||||
	  throws SocksException,UnknownHostException,IOException{
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
      super(0);
 | 
			
		||||
      if(p == null) throw new SocksException(Proxy.SOCKS_NO_PROXY);
 | 
			
		||||
      //proxy=p;
 | 
			
		||||
      proxy = p.copy();
 | 
			
		||||
      if(proxy.isDirect(host)){
 | 
			
		||||
         remoteAddr = InetAddress.getByName(host);
 | 
			
		||||
         proxy = null;
 | 
			
		||||
         doDirect();
 | 
			
		||||
      }else{
 | 
			
		||||
         processReply(proxy.bind(host,port));
 | 
			
		||||
      }
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
    * Creates ServerSocket capable of accepting one connection
 | 
			
		||||
    * through the firewall, uses default Proxy.
 | 
			
		||||
    *@param ip Host from which the connection should be recieved.
 | 
			
		||||
    *@param port Port number of the primary connection.
 | 
			
		||||
    */
 | 
			
		||||
   public SocksServerSocket(InetAddress ip, int port) throws SocksException,
 | 
			
		||||
                                                             IOException{
 | 
			
		||||
      this(Proxy.defaultProxy,ip,port);
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
    *Creates ServerSocket capable of accepting one connection
 | 
			
		||||
    *through the firewall, uses given proxy.
 | 
			
		||||
    *@param p    Proxy object to use.
 | 
			
		||||
    *@param ip   Host from which the connection should be recieved.
 | 
			
		||||
    *@param port Port number of the primary connection.
 | 
			
		||||
    */
 | 
			
		||||
   public SocksServerSocket(Proxy p,InetAddress ip, int port)
 | 
			
		||||
          throws SocksException,IOException{
 | 
			
		||||
      super(0);
 | 
			
		||||
 | 
			
		||||
      if(p == null) throw new SocksException(Proxy.SOCKS_NO_PROXY);
 | 
			
		||||
      this.proxy = p.copy();
 | 
			
		||||
 | 
			
		||||
      if(proxy.isDirect(ip)){
 | 
			
		||||
         remoteAddr = ip;
 | 
			
		||||
         doDirect();
 | 
			
		||||
      }else{
 | 
			
		||||
         processReply(proxy.bind(ip,port));
 | 
			
		||||
      }
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
    * Accepts the incoming connection.
 | 
			
		||||
    */
 | 
			
		||||
   public Socket accept() throws IOException{
 | 
			
		||||
      Socket s;
 | 
			
		||||
 | 
			
		||||
      if(!doing_direct){
 | 
			
		||||
         if(proxy == null) return null;
 | 
			
		||||
 | 
			
		||||
         ProxyMessage msg = proxy.accept();
 | 
			
		||||
         s = msg.ip == null? new SocksSocket(msg.host,msg.port,proxy)
 | 
			
		||||
                                  : new SocksSocket(msg.ip,msg.port,proxy);
 | 
			
		||||
         //Set timeout back to 0
 | 
			
		||||
         proxy.proxySocket.setSoTimeout(0);
 | 
			
		||||
      }else{ //Direct Connection
 | 
			
		||||
 | 
			
		||||
          //Mimic the proxy behaviour,
 | 
			
		||||
          //only accept connections from the speciefed host.
 | 
			
		||||
          while(true){
 | 
			
		||||
            s = super.accept();
 | 
			
		||||
            if(s.getInetAddress().equals(remoteAddr)){
 | 
			
		||||
               //got the connection from the right host
 | 
			
		||||
               //Close listenning socket.
 | 
			
		||||
               break;
 | 
			
		||||
            }else
 | 
			
		||||
               s.close(); //Drop all connections from other hosts
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
      }
 | 
			
		||||
      proxy = null;
 | 
			
		||||
      //Return accepted socket
 | 
			
		||||
      return s;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
    * Closes the connection to proxy if socket have not been accepted, if
 | 
			
		||||
    * the direct connection is used, closes direct ServerSocket. If the 
 | 
			
		||||
    * client socket have been allready accepted, does nothing.
 | 
			
		||||
    */
 | 
			
		||||
   public void close() throws IOException{
 | 
			
		||||
      super.close();
 | 
			
		||||
      if(proxy != null) proxy.endSession();
 | 
			
		||||
      proxy = null;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
     Get the name of the host proxy is using to listen for incoming
 | 
			
		||||
     connection.
 | 
			
		||||
     <P>
 | 
			
		||||
     Usefull when address is returned by proxy as the hostname.
 | 
			
		||||
     @return the hostname of the address proxy is using to listen
 | 
			
		||||
     for incoming connection.
 | 
			
		||||
    */
 | 
			
		||||
   public String getHost(){
 | 
			
		||||
      return localHost;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
    * Get address assigned by proxy to listen for incomming
 | 
			
		||||
    * connections, or the local machine address if doing direct
 | 
			
		||||
    * connection.
 | 
			
		||||
    */
 | 
			
		||||
   public InetAddress getInetAddress(){
 | 
			
		||||
      if(localIP == null){
 | 
			
		||||
	 try{
 | 
			
		||||
	   localIP = InetAddress.getByName(localHost);
 | 
			
		||||
	 }catch(UnknownHostException e){
 | 
			
		||||
	   return null;
 | 
			
		||||
	 }
 | 
			
		||||
      }
 | 
			
		||||
      return localIP;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
    *  Get port assigned by proxy to listen for incoming connections, or
 | 
			
		||||
       the port chosen by local system, if accepting directly.
 | 
			
		||||
    */
 | 
			
		||||
   public int getLocalPort(){
 | 
			
		||||
      return localPort;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
    Set Timeout.
 | 
			
		||||
 | 
			
		||||
    @param timeout Amount of time in milliseconds, accept should wait for
 | 
			
		||||
                   incoming connection before failing with exception.
 | 
			
		||||
                   Zero timeout implies infinity.
 | 
			
		||||
   */
 | 
			
		||||
   public void setSoTimeout(int timeout) throws SocketException{
 | 
			
		||||
      super.setSoTimeout(timeout);
 | 
			
		||||
      if(!doing_direct) proxy.proxySocket.setSoTimeout(timeout);
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//Private Methods
 | 
			
		||||
//////////////////
 | 
			
		||||
 | 
			
		||||
   private void processReply(ProxyMessage reply)throws SocksException{
 | 
			
		||||
      localPort = reply.port;
 | 
			
		||||
      /*
 | 
			
		||||
       * If the server have assigned same host as it was contacted on
 | 
			
		||||
       * it might return an address of all zeros
 | 
			
		||||
       */
 | 
			
		||||
      if(reply.host.equals("0.0.0.0")){
 | 
			
		||||
         localIP = proxy.proxyIP;
 | 
			
		||||
         localHost = localIP.getHostName();
 | 
			
		||||
      }else{
 | 
			
		||||
         localHost = reply.host;
 | 
			
		||||
         localIP = reply.ip;
 | 
			
		||||
      }
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   private void doDirect(){
 | 
			
		||||
      doing_direct = true;
 | 
			
		||||
      localPort = super.getLocalPort();
 | 
			
		||||
      localIP = super.getInetAddress();
 | 
			
		||||
      localHost = localIP.getHostName();
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,337 @@
 | 
			
		|||
package net.sourceforge.jsocks.socks;
 | 
			
		||||
 | 
			
		||||
import java.net.InetAddress;
 | 
			
		||||
import java.net.Socket;
 | 
			
		||||
import java.net.SocketException;
 | 
			
		||||
import java.net.UnknownHostException;
 | 
			
		||||
import java.io.*;
 | 
			
		||||
 | 
			
		||||
import net.*;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * SocksSocket tryies to look very similar to normal Socket,
 | 
			
		||||
 * while allowing connections through the SOCKS4 or 5 proxy.
 | 
			
		||||
 * To use this class you will have to identify proxy you need
 | 
			
		||||
 * to use, Proxy class allows you to set default proxy, which
 | 
			
		||||
 * will be used by all Socks aware sockets. You can also create
 | 
			
		||||
 * either Socks4Proxy or Socks5Proxy, and use them by passing to the 
 | 
			
		||||
 * appropriate constructors.
 | 
			
		||||
 * <P>
 | 
			
		||||
 * Using Socks package can be as easy as that:
 | 
			
		||||
 *
 | 
			
		||||
 * <pre><tt>
 | 
			
		||||
 *
 | 
			
		||||
 *     import Socks.*;
 | 
			
		||||
 *     ....
 | 
			
		||||
 *
 | 
			
		||||
 *     try{
 | 
			
		||||
 *        //Specify SOCKS5 proxy
 | 
			
		||||
 *        Proxy.setDefaultProxy("socks-proxy",1080);
 | 
			
		||||
 *
 | 
			
		||||
 *        //OR you still use SOCKS4
 | 
			
		||||
 *        //Code below uses SOCKS4 proxy
 | 
			
		||||
 *        //Proxy.setDefaultProxy("socks-proxy",1080,userName);
 | 
			
		||||
 *
 | 
			
		||||
 *        Socket s = SocksSocket("some.host.of.mine",13);
 | 
			
		||||
 *        readTimeFromSock(s);
 | 
			
		||||
 *     }catch(SocksException sock_ex){
 | 
			
		||||
 *        //Usually it will turn in more or less meaningfull message
 | 
			
		||||
 *        System.err.println("SocksException:"+sock_ex);
 | 
			
		||||
 *     }
 | 
			
		||||
 *
 | 
			
		||||
 * </tt></pre>
 | 
			
		||||
 *<P>
 | 
			
		||||
 * However if the need exist for more control, like resolving addresses
 | 
			
		||||
 * remotely, or using some non-trivial authentication schemes, it can be done.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
public class SocksSocket extends Socket{
 | 
			
		||||
   //Data members
 | 
			
		||||
   protected Proxy proxy;
 | 
			
		||||
   protected String localHost, remoteHost;
 | 
			
		||||
   protected InetAddress localIP, remoteIP;
 | 
			
		||||
   protected int localPort,remotePort;
 | 
			
		||||
 | 
			
		||||
   private Socket directSock = null;
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
    * Tryies to connect to given host and port
 | 
			
		||||
    * using default proxy. If no default proxy speciefied
 | 
			
		||||
    * it throws SocksException with error code SOCKS_NO_PROXY.
 | 
			
		||||
      @param host Machine to connect to.
 | 
			
		||||
      @param port Port to which to connect.
 | 
			
		||||
    * @see SocksSocket#SocksSocket(Proxy,String,int)
 | 
			
		||||
    * @see Socks5Proxy#resolveAddrLocally
 | 
			
		||||
    */
 | 
			
		||||
   public SocksSocket(String host,int port)
 | 
			
		||||
	  throws SocksException,UnknownHostException{
 | 
			
		||||
      this(Proxy.defaultProxy,host,port);
 | 
			
		||||
   }
 | 
			
		||||
   /**
 | 
			
		||||
    * Connects to host port using given proxy server.
 | 
			
		||||
      @param p Proxy to use.
 | 
			
		||||
      @param host Machine to connect to.
 | 
			
		||||
      @param port Port to which to connect.
 | 
			
		||||
      @throws UnknownHostException 
 | 
			
		||||
      If one of the following happens:
 | 
			
		||||
      <ol>
 | 
			
		||||
 | 
			
		||||
      <li> Proxy settings say that address should be resolved locally, but
 | 
			
		||||
           this fails.
 | 
			
		||||
      <li> Proxy settings say that the host should be contacted directly but
 | 
			
		||||
           host name can't be resolved. 
 | 
			
		||||
      </ol>
 | 
			
		||||
      @throws SocksException
 | 
			
		||||
      If one of the following happens:
 | 
			
		||||
      <ul>
 | 
			
		||||
       <li> Proxy is is null.
 | 
			
		||||
       <li> Proxy settings say that the host should be contacted directly but
 | 
			
		||||
            this fails.
 | 
			
		||||
       <li> Socks Server can't be contacted.
 | 
			
		||||
       <li> Authentication fails.
 | 
			
		||||
       <li> Connection is not allowed by the SOCKS proxy.
 | 
			
		||||
       <li> SOCKS proxy can't establish the connection.
 | 
			
		||||
       <li> Any IO error occured.
 | 
			
		||||
       <li> Any protocol error occured.
 | 
			
		||||
      </ul>
 | 
			
		||||
      @throws IOexception if anything is wrong with I/O.
 | 
			
		||||
      @see Socks5Proxy#resolveAddrLocally
 | 
			
		||||
    */
 | 
			
		||||
   public SocksSocket(Proxy p,String host,int port)
 | 
			
		||||
	  throws SocksException,UnknownHostException{
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
      if(p == null) throw new SocksException(Proxy.SOCKS_NO_PROXY);
 | 
			
		||||
      //proxy=p;
 | 
			
		||||
      proxy = p.copy();
 | 
			
		||||
      remoteHost = host;
 | 
			
		||||
      remotePort = port;
 | 
			
		||||
      if(proxy.isDirect(host)){
 | 
			
		||||
         remoteIP = InetAddress.getByName(host);
 | 
			
		||||
         doDirect();
 | 
			
		||||
      }
 | 
			
		||||
      else
 | 
			
		||||
         processReply(proxy.connect(host,port));
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
    * Tryies to connect to given ip and port
 | 
			
		||||
    * using default proxy. If no default proxy speciefied
 | 
			
		||||
    * it throws SocksException with error code SOCKS_NO_PROXY.
 | 
			
		||||
      @param ip Machine to connect to.
 | 
			
		||||
      @param port Port to which to connect.
 | 
			
		||||
    * @see SocksSocket#SocksSocket(Proxy,String,int)
 | 
			
		||||
    */
 | 
			
		||||
   public SocksSocket(InetAddress ip, int port) throws SocksException{
 | 
			
		||||
      this(Proxy.defaultProxy,ip,port);
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
      Connects to given ip and port using given Proxy server.
 | 
			
		||||
      @param p Proxy to use.
 | 
			
		||||
      @param ip Machine to connect to.
 | 
			
		||||
      @param port Port to which to connect.
 | 
			
		||||
 | 
			
		||||
    */
 | 
			
		||||
   public SocksSocket(Proxy p,InetAddress ip, int port) throws SocksException{
 | 
			
		||||
      if(p == null) throw new SocksException(Proxy.SOCKS_NO_PROXY);
 | 
			
		||||
      this.proxy = p.copy();
 | 
			
		||||
      this.remoteIP = ip;
 | 
			
		||||
      this.remotePort = port;
 | 
			
		||||
      this.remoteHost = ip.getHostName();
 | 
			
		||||
      if(proxy.isDirect(remoteIP))
 | 
			
		||||
        doDirect();
 | 
			
		||||
      else
 | 
			
		||||
        processReply(proxy.connect(ip,port));
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
    * These 2 constructors are used by the SocksServerSocket.
 | 
			
		||||
    * This socket simply overrides remoteHost, remotePort
 | 
			
		||||
    */
 | 
			
		||||
   protected SocksSocket(String  host,int port,Proxy proxy){
 | 
			
		||||
      this.remotePort = port;
 | 
			
		||||
      this.proxy = proxy;
 | 
			
		||||
      this.localIP = proxy.proxySocket.getLocalAddress();
 | 
			
		||||
      this.localPort = proxy.proxySocket.getLocalPort();
 | 
			
		||||
      this.remoteHost = host;
 | 
			
		||||
   }
 | 
			
		||||
   protected SocksSocket(InetAddress ip,int port,Proxy proxy){
 | 
			
		||||
      remoteIP = ip;
 | 
			
		||||
      remotePort = port;
 | 
			
		||||
      this.proxy = proxy;
 | 
			
		||||
      this.localIP = proxy.proxySocket.getLocalAddress();
 | 
			
		||||
      this.localPort = proxy.proxySocket.getLocalPort();
 | 
			
		||||
      remoteHost = remoteIP.getHostName();
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
    * Same as Socket
 | 
			
		||||
    */
 | 
			
		||||
   public void close() throws IOException{
 | 
			
		||||
      if(proxy!= null)proxy.endSession();
 | 
			
		||||
      proxy = null;
 | 
			
		||||
   }
 | 
			
		||||
   /**
 | 
			
		||||
    * Same as Socket
 | 
			
		||||
    */
 | 
			
		||||
   public InputStream getInputStream(){
 | 
			
		||||
      return proxy.in;
 | 
			
		||||
   }
 | 
			
		||||
   /**
 | 
			
		||||
    * Same as Socket
 | 
			
		||||
    */
 | 
			
		||||
   public OutputStream getOutputStream(){
 | 
			
		||||
      return proxy.out;
 | 
			
		||||
   }
 | 
			
		||||
   /**
 | 
			
		||||
    * Same as Socket
 | 
			
		||||
    */
 | 
			
		||||
   public int getPort(){
 | 
			
		||||
      return remotePort;
 | 
			
		||||
   }
 | 
			
		||||
   /**
 | 
			
		||||
    * Returns remote host name, it is usefull in cases when addresses
 | 
			
		||||
    * are resolved by proxy, and we can't create InetAddress object.
 | 
			
		||||
      @return The name of the host this socket is connected to.
 | 
			
		||||
    */
 | 
			
		||||
   public String getHost(){
 | 
			
		||||
      return remoteHost;
 | 
			
		||||
   }
 | 
			
		||||
   /**
 | 
			
		||||
    * Get remote host as InetAddress object, might return null if 
 | 
			
		||||
    * addresses are resolved by proxy, and it is not possible to resolve
 | 
			
		||||
    * it locally
 | 
			
		||||
      @return Ip address of the host this socket is connected to, or null
 | 
			
		||||
      if address was returned by the proxy as DOMAINNAME and can't be
 | 
			
		||||
      resolved locally.
 | 
			
		||||
    */
 | 
			
		||||
   public InetAddress getInetAddress(){
 | 
			
		||||
      if(remoteIP == null){
 | 
			
		||||
	 try{
 | 
			
		||||
	   remoteIP = InetAddress.getByName(remoteHost);
 | 
			
		||||
	 }catch(UnknownHostException e){
 | 
			
		||||
	   return null;
 | 
			
		||||
	 }
 | 
			
		||||
      }
 | 
			
		||||
      return remoteIP;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
    * Get the port assigned by the proxy for the socket, not
 | 
			
		||||
    * the port on locall machine as in Socket. 
 | 
			
		||||
      @return Port of the socket used on the proxy server.
 | 
			
		||||
    */
 | 
			
		||||
   public int getLocalPort(){
 | 
			
		||||
      return localPort;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
    * Get address assigned by proxy to make a remote connection,
 | 
			
		||||
    * it might be different from the host specified for the proxy.
 | 
			
		||||
    * Can return null if socks server returned this address as hostname
 | 
			
		||||
    * and it can't be resolved locally, use getLocalHost() then.
 | 
			
		||||
      @return Address proxy is using to make a connection.
 | 
			
		||||
    */
 | 
			
		||||
   public InetAddress getLocalAddress(){
 | 
			
		||||
      if(localIP == null){
 | 
			
		||||
	 try{
 | 
			
		||||
	    localIP = InetAddress.getByName(localHost);
 | 
			
		||||
	 }catch(UnknownHostException e){
 | 
			
		||||
	   return null;
 | 
			
		||||
	 }
 | 
			
		||||
      }
 | 
			
		||||
      return localIP;
 | 
			
		||||
   }
 | 
			
		||||
   /**
 | 
			
		||||
      Get name of the host, proxy has assigned to make a remote connection
 | 
			
		||||
      for this socket. This method is usefull when proxy have returned
 | 
			
		||||
      address as hostname, and we can't resolve it on this machine.
 | 
			
		||||
      @return The name of the host proxy is using to make a connection.
 | 
			
		||||
   */
 | 
			
		||||
   public String getLocalHost(){
 | 
			
		||||
      return localHost;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
     Same as socket.
 | 
			
		||||
   */
 | 
			
		||||
   public void setSoLinger(boolean on,int val) throws SocketException{
 | 
			
		||||
      proxy.proxySocket.setSoLinger(on,val);
 | 
			
		||||
   }
 | 
			
		||||
   /**
 | 
			
		||||
     Same as socket.
 | 
			
		||||
   */
 | 
			
		||||
   public int getSoLinger(int timeout) throws SocketException{
 | 
			
		||||
      return proxy.proxySocket.getSoLinger();
 | 
			
		||||
   }
 | 
			
		||||
   /**
 | 
			
		||||
     Same as socket.
 | 
			
		||||
   */
 | 
			
		||||
   public void setSoTimeout(int timeout) throws SocketException{
 | 
			
		||||
      proxy.proxySocket.setSoTimeout(timeout);
 | 
			
		||||
   }
 | 
			
		||||
   /**
 | 
			
		||||
     Same as socket.
 | 
			
		||||
   */
 | 
			
		||||
   public int getSoTimeout(int timeout) throws SocketException{
 | 
			
		||||
      return proxy.proxySocket.getSoTimeout();
 | 
			
		||||
   }
 | 
			
		||||
   /**
 | 
			
		||||
     Same as socket.
 | 
			
		||||
   */
 | 
			
		||||
   public void setTcpNoDelay(boolean on) throws SocketException{
 | 
			
		||||
     proxy.proxySocket.setTcpNoDelay(on);
 | 
			
		||||
   }
 | 
			
		||||
   /**
 | 
			
		||||
     Same as socket.
 | 
			
		||||
   */
 | 
			
		||||
   public boolean getTcpNoDelay() throws SocketException{
 | 
			
		||||
     return proxy.proxySocket.getTcpNoDelay();
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
     Get string representation of the socket.
 | 
			
		||||
   */
 | 
			
		||||
   public String toString(){
 | 
			
		||||
      if(directSock!=null) return "Direct connection:"+directSock;
 | 
			
		||||
      return ("Proxy:"+proxy+";"+"addr:"+remoteHost+",port:"+remotePort
 | 
			
		||||
                                +",localport:"+localPort);
 | 
			
		||||
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
//Private Methods
 | 
			
		||||
//////////////////
 | 
			
		||||
 | 
			
		||||
   private void processReply(ProxyMessage reply)throws SocksException{
 | 
			
		||||
      localPort = reply.port;
 | 
			
		||||
      /*
 | 
			
		||||
       * If the server have assigned same host as it was contacted on
 | 
			
		||||
       * it might return an address of all zeros
 | 
			
		||||
       */
 | 
			
		||||
      if(reply.host.equals("0.0.0.0")){
 | 
			
		||||
         localIP = proxy.proxyIP;
 | 
			
		||||
         localHost = localIP.getHostName();
 | 
			
		||||
      }else{
 | 
			
		||||
         localHost = reply.host;
 | 
			
		||||
         localIP = reply.ip;
 | 
			
		||||
      }
 | 
			
		||||
   }
 | 
			
		||||
   private void doDirect()throws SocksException{
 | 
			
		||||
      try{
 | 
			
		||||
         //System.out.println("IP:"+remoteIP+":"+remotePort);
 | 
			
		||||
         directSock = new Socket(remoteIP,remotePort);
 | 
			
		||||
         proxy.out = directSock.getOutputStream();
 | 
			
		||||
         proxy.in  = directSock.getInputStream();
 | 
			
		||||
         proxy.proxySocket = directSock;
 | 
			
		||||
         localIP = directSock.getLocalAddress();
 | 
			
		||||
         localPort = directSock.getLocalPort();
 | 
			
		||||
      }catch(IOException io_ex){
 | 
			
		||||
         throw new SocksException(Proxy.SOCKS_DIRECT_FAILED,
 | 
			
		||||
                                  "Direct connect failed:"+io_ex);
 | 
			
		||||
      }
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,30 @@
 | 
			
		|||
package net.sourceforge.jsocks.socks;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 This interface provides for datagram encapsulation for SOCKSv5 protocol.
 | 
			
		||||
 <p>
 | 
			
		||||
 SOCKSv5 allows for datagrams to be encapsulated for purposes of integrity
 | 
			
		||||
 and/or authenticity. How it should be done is aggreed during the 
 | 
			
		||||
 authentication stage, and is authentication dependent. This interface is
 | 
			
		||||
 provided to allow this encapsulation.
 | 
			
		||||
 @see Authentication
 | 
			
		||||
*/
 | 
			
		||||
public interface UDPEncapsulation{
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
    This method should provide any authentication depended transformation
 | 
			
		||||
    on datagrams being send from/to the client.
 | 
			
		||||
 | 
			
		||||
    @param data Datagram data (including any SOCKS related bytes), to be
 | 
			
		||||
                encapsulated/decapsulated.
 | 
			
		||||
    @param out  Wether the data is being send out. If true method should 
 | 
			
		||||
                encapsulate/encrypt data, otherwise it should decapsulate/
 | 
			
		||||
                decrypt data.
 | 
			
		||||
    @throw IOException if for some reason data can be transformed correctly.
 | 
			
		||||
    @return Should return byte array containing data after transformation.
 | 
			
		||||
            It is possible to return same array as input, if transformation
 | 
			
		||||
            only involves bit mangling, and no additional data is being
 | 
			
		||||
            added or removed.
 | 
			
		||||
    */
 | 
			
		||||
    byte[] udpEncapsulate(byte[] data, boolean out) throws java.io.IOException;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,217 @@
 | 
			
		|||
package net.sourceforge.jsocks.socks;
 | 
			
		||||
 | 
			
		||||
import net.*;
 | 
			
		||||
import net.sourceforge.jsocks.socks.server.*;
 | 
			
		||||
 | 
			
		||||
import java.net.DatagramPacket;
 | 
			
		||||
import java.net.DatagramSocket;
 | 
			
		||||
import java.net.InetAddress;
 | 
			
		||||
import java.net.Socket;
 | 
			
		||||
import java.net.UnknownHostException;
 | 
			
		||||
import java.io.*;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 UDP Relay server, used by ProxyServer to perform udp forwarding.
 | 
			
		||||
*/
 | 
			
		||||
class UDPRelayServer implements Runnable{
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    DatagramSocket client_sock; 
 | 
			
		||||
    DatagramSocket remote_sock;
 | 
			
		||||
 | 
			
		||||
    Socket controlConnection;
 | 
			
		||||
 | 
			
		||||
    int relayPort;
 | 
			
		||||
    InetAddress relayIP;
 | 
			
		||||
 | 
			
		||||
    Thread pipe_thread1,pipe_thread2;
 | 
			
		||||
    Thread master_thread;
 | 
			
		||||
 | 
			
		||||
    ServerAuthenticator auth;
 | 
			
		||||
 | 
			
		||||
    long lastReadTime;
 | 
			
		||||
 | 
			
		||||
   // private static final Logger LOG = Logger.getLogger(UDPRelayServer.class);
 | 
			
		||||
    
 | 
			
		||||
    static Proxy proxy = null;
 | 
			
		||||
    static int datagramSize = 0xFFFF;//64K, a bit more than max udp size
 | 
			
		||||
    static int iddleTimeout = 180000;//3 minutes
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
      Constructs UDP relay server to communicate with client
 | 
			
		||||
      on given ip and port.
 | 
			
		||||
      @param clientIP Address of the client from whom datagrams
 | 
			
		||||
      will be recieved and to whom they will be forwarded.
 | 
			
		||||
      @param clientPort Clients port.
 | 
			
		||||
      @param master_thread Thread which will be interrupted, when
 | 
			
		||||
      UDP relay server stoppes for some reason.
 | 
			
		||||
      @param controlConnection Socket which will be closed, before
 | 
			
		||||
      interrupting the master thread, it is introduced due to a bug
 | 
			
		||||
      in windows JVM which does not throw InterruptedIOException in
 | 
			
		||||
      threads which block in I/O operation.
 | 
			
		||||
    */
 | 
			
		||||
    public UDPRelayServer(InetAddress clientIP,int clientPort,
 | 
			
		||||
                          Thread master_thread,
 | 
			
		||||
                          Socket controlConnection,
 | 
			
		||||
                          ServerAuthenticator auth)
 | 
			
		||||
                          throws IOException{
 | 
			
		||||
       this.master_thread = master_thread;
 | 
			
		||||
       this.controlConnection = controlConnection;
 | 
			
		||||
       this.auth = auth;
 | 
			
		||||
 | 
			
		||||
       client_sock = new Socks5DatagramSocket(true,auth.getUdpEncapsulation(),
 | 
			
		||||
                                              clientIP,clientPort);
 | 
			
		||||
       relayPort = client_sock.getLocalPort();
 | 
			
		||||
       relayIP   = client_sock.getLocalAddress();
 | 
			
		||||
 | 
			
		||||
       if(relayIP.getHostAddress().equals("0.0.0.0"))
 | 
			
		||||
         relayIP   = InetAddress.getLocalHost();
 | 
			
		||||
 | 
			
		||||
       if(proxy == null)
 | 
			
		||||
          remote_sock = new DatagramSocket();
 | 
			
		||||
       else
 | 
			
		||||
          remote_sock = new Socks5DatagramSocket(proxy,0,null);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//Public methods
 | 
			
		||||
/////////////////
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
    Sets the timeout for UDPRelay server.<br>
 | 
			
		||||
    Zero timeout implies infinity.<br>
 | 
			
		||||
    Default timeout is 3 minutes.
 | 
			
		||||
    */
 | 
			
		||||
 | 
			
		||||
    static public void setTimeout(int timeout){
 | 
			
		||||
      iddleTimeout = timeout;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
     Sets the size of the datagrams used in the UDPRelayServer.<br>
 | 
			
		||||
     Default size is 64K, a bit more than maximum possible size of the
 | 
			
		||||
     datagram.
 | 
			
		||||
    */
 | 
			
		||||
    static public void setDatagramSize(int size){
 | 
			
		||||
      datagramSize = size;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
      Port to which client should send datagram for association.
 | 
			
		||||
    */
 | 
			
		||||
    public int getRelayPort(){
 | 
			
		||||
       return relayPort;
 | 
			
		||||
    }
 | 
			
		||||
    /**
 | 
			
		||||
     IP address to which client should send datagrams for association.
 | 
			
		||||
    */
 | 
			
		||||
    public InetAddress getRelayIP(){
 | 
			
		||||
       return relayIP;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
      Starts udp relay server.
 | 
			
		||||
      Spawns two threads of execution and returns.
 | 
			
		||||
    */
 | 
			
		||||
    public void start() throws IOException{
 | 
			
		||||
       remote_sock.setSoTimeout(iddleTimeout);
 | 
			
		||||
       client_sock.setSoTimeout(iddleTimeout);
 | 
			
		||||
 | 
			
		||||
       log("Starting UDP relay server on "+relayIP+":"+relayPort);
 | 
			
		||||
       log("Remote socket "+remote_sock.getLocalAddress()+":"+
 | 
			
		||||
                            remote_sock.getLocalPort());
 | 
			
		||||
 | 
			
		||||
       pipe_thread1 = new Thread(this,"pipe1");
 | 
			
		||||
       pipe_thread2 = new Thread(this,"pipe2");
 | 
			
		||||
 | 
			
		||||
       lastReadTime = System.currentTimeMillis();
 | 
			
		||||
 | 
			
		||||
       pipe_thread1.start();
 | 
			
		||||
       pipe_thread2.start();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     Stops Relay server.
 | 
			
		||||
     <p>
 | 
			
		||||
     Does not close control connection, does not interrupt master_thread.
 | 
			
		||||
    */
 | 
			
		||||
    public synchronized void stop(){
 | 
			
		||||
       master_thread = null;
 | 
			
		||||
       controlConnection = null;
 | 
			
		||||
       abort();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
//Runnable interface
 | 
			
		||||
////////////////////
 | 
			
		||||
    public void run(){
 | 
			
		||||
       try{
 | 
			
		||||
          if(Thread.currentThread().getName().equals("pipe1"))
 | 
			
		||||
             pipe(remote_sock,client_sock,false);
 | 
			
		||||
          else
 | 
			
		||||
             pipe(client_sock,remote_sock,true);
 | 
			
		||||
       }catch(IOException ioe){
 | 
			
		||||
       }finally{
 | 
			
		||||
          abort();
 | 
			
		||||
          log("UDP Pipe thread "+Thread.currentThread().getName()+" stopped.");
 | 
			
		||||
       }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
//Private methods
 | 
			
		||||
/////////////////
 | 
			
		||||
    private synchronized void abort(){
 | 
			
		||||
       if(pipe_thread1 == null) return;
 | 
			
		||||
 | 
			
		||||
       log("Aborting UDP Relay Server");
 | 
			
		||||
 | 
			
		||||
       remote_sock.close();
 | 
			
		||||
       client_sock.close();
 | 
			
		||||
 | 
			
		||||
       if(controlConnection != null) 
 | 
			
		||||
          try{ controlConnection.close();} catch(IOException ioe){}
 | 
			
		||||
 | 
			
		||||
       if(master_thread!=null) master_thread.interrupt();
 | 
			
		||||
 | 
			
		||||
       pipe_thread1.interrupt();
 | 
			
		||||
       pipe_thread2.interrupt();
 | 
			
		||||
 | 
			
		||||
       pipe_thread1 = null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    static private void log(String s){
 | 
			
		||||
    
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void pipe(DatagramSocket from,DatagramSocket to,boolean out)
 | 
			
		||||
                             throws IOException{
 | 
			
		||||
       byte[] data = new byte[datagramSize];
 | 
			
		||||
       DatagramPacket dp = new DatagramPacket(data,data.length);
 | 
			
		||||
 | 
			
		||||
       while(true){
 | 
			
		||||
          try{
 | 
			
		||||
            from.receive(dp);
 | 
			
		||||
            lastReadTime = System.currentTimeMillis();
 | 
			
		||||
 | 
			
		||||
            if(auth.checkRequest(dp,out))
 | 
			
		||||
               to.send(dp);
 | 
			
		||||
 | 
			
		||||
          }catch(UnknownHostException uhe){
 | 
			
		||||
            log("Dropping datagram for unknown host");
 | 
			
		||||
          }catch(InterruptedIOException iioe){
 | 
			
		||||
            //log("Interrupted: "+iioe);
 | 
			
		||||
            //If we were interrupted by other thread.
 | 
			
		||||
            if(iddleTimeout == 0) return;
 | 
			
		||||
 | 
			
		||||
            //If last datagram was received, long time ago, return.
 | 
			
		||||
            long timeSinceRead = System.currentTimeMillis() - lastReadTime;
 | 
			
		||||
            if(timeSinceRead >= iddleTimeout -100) //-100 for adjustment
 | 
			
		||||
               return;
 | 
			
		||||
          }
 | 
			
		||||
          dp.setLength(data.length);
 | 
			
		||||
       }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,75 @@
 | 
			
		|||
package net.sourceforge.jsocks.socks;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  SOCKS5 User Password authentication scheme.
 | 
			
		||||
*/
 | 
			
		||||
public class UserPasswordAuthentication implements Authentication{
 | 
			
		||||
 | 
			
		||||
   /**SOCKS ID for User/Password authentication method*/
 | 
			
		||||
   public final static int METHOD_ID = 2;
 | 
			
		||||
 | 
			
		||||
   String userName, password;
 | 
			
		||||
   byte[] request;
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
     Create an instance of UserPasswordAuthentication.
 | 
			
		||||
     @param userName User Name to send to SOCKS server.
 | 
			
		||||
     @param password Password to send to SOCKS server.
 | 
			
		||||
   */
 | 
			
		||||
   public UserPasswordAuthentication(String userName,String password){
 | 
			
		||||
     this.userName = userName;
 | 
			
		||||
     this.password = password;
 | 
			
		||||
     formRequest();
 | 
			
		||||
   }
 | 
			
		||||
   /** Get the user name.
 | 
			
		||||
   @return User name.
 | 
			
		||||
   */
 | 
			
		||||
   public String getUser(){
 | 
			
		||||
     return userName;
 | 
			
		||||
   }
 | 
			
		||||
   /** Get password
 | 
			
		||||
   @return Password
 | 
			
		||||
   */
 | 
			
		||||
   public String getPassword(){
 | 
			
		||||
     return password;
 | 
			
		||||
   }
 | 
			
		||||
   /**
 | 
			
		||||
    Does User/Password authentication as defined in rfc1929.
 | 
			
		||||
    @return An array containnig in, out streams, or null if authentication
 | 
			
		||||
    fails.
 | 
			
		||||
   */
 | 
			
		||||
   public Object[] doSocksAuthentication(int methodId,
 | 
			
		||||
                                         java.net.Socket proxySocket)
 | 
			
		||||
                   throws java.io.IOException{
 | 
			
		||||
 | 
			
		||||
      if(methodId != METHOD_ID) return null;
 | 
			
		||||
 | 
			
		||||
      java.io.InputStream in = proxySocket.getInputStream();
 | 
			
		||||
      java.io.OutputStream out = proxySocket.getOutputStream();
 | 
			
		||||
 | 
			
		||||
      out.write(request);
 | 
			
		||||
      int version = in.read();
 | 
			
		||||
      if(version < 0) return null; //Server closed connection
 | 
			
		||||
      int status = in.read();
 | 
			
		||||
      if(status != 0) return null; //Server closed connection, or auth failed.
 | 
			
		||||
 | 
			
		||||
      return new Object[] {in,out};
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
//Private methods
 | 
			
		||||
//////////////////
 | 
			
		||||
 | 
			
		||||
/** Convert UserName password in to binary form, ready to be send to server*/
 | 
			
		||||
   private void formRequest(){
 | 
			
		||||
      byte[] user_bytes = userName.getBytes();
 | 
			
		||||
      byte[] password_bytes = password.getBytes();
 | 
			
		||||
 | 
			
		||||
      request = new byte[3+user_bytes.length+password_bytes.length];
 | 
			
		||||
      request[0] = (byte) 1; 
 | 
			
		||||
      request[1] = (byte) user_bytes.length;
 | 
			
		||||
      System.arraycopy(user_bytes,0,request,2,user_bytes.length);
 | 
			
		||||
      request[2+user_bytes.length] = (byte) password_bytes.length;
 | 
			
		||||
      System.arraycopy(password_bytes,0,
 | 
			
		||||
                       request,3+user_bytes.length,password_bytes.length);
 | 
			
		||||
   }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,161 @@
 | 
			
		|||
package net.sourceforge.jsocks.socks.server;
 | 
			
		||||
 | 
			
		||||
import java.net.ConnectException;
 | 
			
		||||
import java.net.Socket;
 | 
			
		||||
import java.io.*;
 | 
			
		||||
import java.util.StringTokenizer;
 | 
			
		||||
 | 
			
		||||
import net.*;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 Class Ident provides means to obtain user name of the owner of the socket 
 | 
			
		||||
 on remote machine, providing remote machine runs identd daemon.
 | 
			
		||||
 <p>
 | 
			
		||||
 To use it:
 | 
			
		||||
   <tt><pre>
 | 
			
		||||
   Socket s = ss.accept();
 | 
			
		||||
   Ident id = new Ident(s);
 | 
			
		||||
   if(id.successful) goUseUser(id.userName);
 | 
			
		||||
   else handleIdentError(id.errorCode,id.errorMessage)
 | 
			
		||||
   </pre></tt>
 | 
			
		||||
*/
 | 
			
		||||
public class Ident{
 | 
			
		||||
 | 
			
		||||
    /** Error Message can be null.*/
 | 
			
		||||
    public String errorMessage;
 | 
			
		||||
    /** Host type as returned by daemon, can be null, if error happened*/
 | 
			
		||||
    public String hostType;
 | 
			
		||||
    /** User name as returned by the identd daemon, or null, if it failed*/
 | 
			
		||||
    public String userName;
 | 
			
		||||
 | 
			
		||||
    /** If this is true then userName and hostType contain valid values.
 | 
			
		||||
        Else errorCode contain the error code, and errorMessage contains
 | 
			
		||||
        the corresponding message.
 | 
			
		||||
    */
 | 
			
		||||
    public boolean successful;
 | 
			
		||||
    /** Error code*/
 | 
			
		||||
    public int errorCode;
 | 
			
		||||
    /** Identd on port 113 can't be contacted*/
 | 
			
		||||
    public static final int ERR_NO_CONNECT = 1;
 | 
			
		||||
    /** Connection timed out*/
 | 
			
		||||
    public static final int ERR_TIMEOUT = 2;
 | 
			
		||||
    /** Identd daemon responded with ERROR, in this case errorMessage
 | 
			
		||||
        contains the string explanation, as send by the daemon.
 | 
			
		||||
    */
 | 
			
		||||
    public static final int ERR_PROTOCOL = 3;
 | 
			
		||||
    /**
 | 
			
		||||
     When parsing server response protocol error happened.
 | 
			
		||||
    */
 | 
			
		||||
    public static final int ERR_PROTOCOL_INCORRECT = 4;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /** Maximum amount of time we should wait before dropping the
 | 
			
		||||
      connection to identd server.Setting it to 0 implies infinit
 | 
			
		||||
      timeout.
 | 
			
		||||
    */
 | 
			
		||||
    public static final int connectionTimeout = 10000;
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     Constructor tries to connect to Identd daemon on the host of the
 | 
			
		||||
     given socket, and retrieve user name of the owner of given socket 
 | 
			
		||||
     connection on remote machine. After constructor returns public
 | 
			
		||||
     fields are initialised to whatever the server returned.
 | 
			
		||||
     <p>
 | 
			
		||||
     If user name was successfully retrieved successful is set to true,
 | 
			
		||||
     and userName and hostType are set to whatever server returned. If
 | 
			
		||||
     however for some reason user name was not obtained, successful is set
 | 
			
		||||
     to false and errorCode contains the code explaining the reason of
 | 
			
		||||
     failure, and errorMessage contains human readable explanation.
 | 
			
		||||
     <p>
 | 
			
		||||
     Constructor may block, for a while.
 | 
			
		||||
     @param s Socket whose ownership on remote end should be obtained.
 | 
			
		||||
    */
 | 
			
		||||
    public Ident(Socket s ){
 | 
			
		||||
      Socket sock = null;
 | 
			
		||||
      successful = false; //We are pessimistic
 | 
			
		||||
 | 
			
		||||
      try{
 | 
			
		||||
        sock = new Socket(s.getInetAddress(),113);
 | 
			
		||||
        sock.setSoTimeout(connectionTimeout);
 | 
			
		||||
        byte[] request = (""+s.getPort()+" , "+
 | 
			
		||||
                             s.getLocalPort()+"\r\n").getBytes();
 | 
			
		||||
 | 
			
		||||
        sock.getOutputStream().write(request);
 | 
			
		||||
 | 
			
		||||
        BufferedReader in = new BufferedReader(
 | 
			
		||||
                            new InputStreamReader(sock.getInputStream()));
 | 
			
		||||
 | 
			
		||||
        parseResponse(in.readLine());
 | 
			
		||||
 | 
			
		||||
      }catch(InterruptedIOException iioe){
 | 
			
		||||
        errorCode = ERR_TIMEOUT;
 | 
			
		||||
        errorMessage = "Connection to identd timed out.";
 | 
			
		||||
      }catch(ConnectException ce){
 | 
			
		||||
        errorCode = ERR_NO_CONNECT;
 | 
			
		||||
        errorMessage = "Connection to identd server failed.";
 | 
			
		||||
 | 
			
		||||
      }catch(IOException ioe){
 | 
			
		||||
        errorCode = ERR_NO_CONNECT;
 | 
			
		||||
        errorMessage = ""+ioe;
 | 
			
		||||
      }finally{
 | 
			
		||||
        try{ if(sock!=null) sock.close();}catch(IOException ioe){};
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void parseResponse(String response){
 | 
			
		||||
      if(response == null){
 | 
			
		||||
         errorCode = ERR_PROTOCOL_INCORRECT;
 | 
			
		||||
         errorMessage = "Identd server closed connection.";
 | 
			
		||||
         return;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      StringTokenizer st = new StringTokenizer(response,":");
 | 
			
		||||
      if(st.countTokens() < 3){
 | 
			
		||||
         errorCode = ERR_PROTOCOL_INCORRECT;
 | 
			
		||||
         errorMessage = "Can't parse server response.";
 | 
			
		||||
         return;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      st.nextToken(); //Discard first token, it's basically what we have send
 | 
			
		||||
      String command = st.nextToken().trim().toUpperCase();
 | 
			
		||||
 | 
			
		||||
      if(command.equals("USERID") && st.countTokens() >= 2){
 | 
			
		||||
        successful = true;
 | 
			
		||||
        hostType = st.nextToken().trim();
 | 
			
		||||
        userName = st.nextToken("").substring(1);//Get all that is left
 | 
			
		||||
      }else if(command.equals("ERROR")){
 | 
			
		||||
        errorCode = ERR_PROTOCOL;
 | 
			
		||||
        errorMessage = st.nextToken();
 | 
			
		||||
      }else{
 | 
			
		||||
        errorCode = ERR_PROTOCOL_INCORRECT;
 | 
			
		||||
        System.out.println("Opa!");
 | 
			
		||||
        errorMessage = "Can't parse server response.";
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////
 | 
			
		||||
//USED for Testing
 | 
			
		||||
/*
 | 
			
		||||
    public static void main(String[] args) throws IOException{
 | 
			
		||||
 | 
			
		||||
       Socket s = null;
 | 
			
		||||
       s = new Socket("gp101-16", 1391);
 | 
			
		||||
 | 
			
		||||
       Ident id = new Ident(s);
 | 
			
		||||
       if(id.successful){
 | 
			
		||||
         System.out.println("User: "+id.userName);
 | 
			
		||||
         System.out.println("HostType: "+id.hostType);
 | 
			
		||||
       }else{
 | 
			
		||||
         System.out.println("ErrorCode: "+id.errorCode);
 | 
			
		||||
         System.out.println("ErrorMessage: "+id.errorMessage);
 | 
			
		||||
 | 
			
		||||
       }
 | 
			
		||||
 | 
			
		||||
       if(s!= null) s.close();
 | 
			
		||||
    }
 | 
			
		||||
//*/
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,153 @@
 | 
			
		|||
package net.sourceforge.jsocks.socks.server;
 | 
			
		||||
 | 
			
		||||
import java.util.Hashtable;
 | 
			
		||||
import java.util.Iterator;
 | 
			
		||||
import java.util.Vector;
 | 
			
		||||
import java.net.InetAddress;
 | 
			
		||||
import java.net.Socket;
 | 
			
		||||
import java.io.*;
 | 
			
		||||
 | 
			
		||||
import net.*;
 | 
			
		||||
import net.sourceforge.jsocks.socks.InetRange;
 | 
			
		||||
import net.sourceforge.jsocks.socks.ProxyMessage;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  An implementation of socks.ServerAuthentication which provides
 | 
			
		||||
  simple authentication based on the host from which the connection
 | 
			
		||||
  is made and the name of the user on the remote machine, as reported
 | 
			
		||||
  by identd daemon on the remote machine.
 | 
			
		||||
  <p>
 | 
			
		||||
  It can also be used to provide authentication based only on the contacting
 | 
			
		||||
  host address.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
public class IdentAuthenticator extends ServerAuthenticatorNone{
 | 
			
		||||
   /** Vector of InetRanges */
 | 
			
		||||
   Vector hosts;
 | 
			
		||||
 | 
			
		||||
   /** Vector of user hashes*/
 | 
			
		||||
   Vector users;
 | 
			
		||||
 | 
			
		||||
   String user;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
    Constructs empty IdentAuthenticator.
 | 
			
		||||
   */
 | 
			
		||||
   public IdentAuthenticator(){
 | 
			
		||||
      hosts = new Vector();
 | 
			
		||||
      users = new Vector();
 | 
			
		||||
   }
 | 
			
		||||
   /**
 | 
			
		||||
    Used to create instances returned from startSession.
 | 
			
		||||
    @param in Input stream.
 | 
			
		||||
    @param out OutputStream.
 | 
			
		||||
    @param user Username associated with this connection,could be
 | 
			
		||||
                null if name was not required.
 | 
			
		||||
   */
 | 
			
		||||
   IdentAuthenticator(InputStream in,OutputStream out, String user){
 | 
			
		||||
      super(in,out);
 | 
			
		||||
      this.user = user;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
    Adds range of addresses from which connection is allowed. Hashtable
 | 
			
		||||
    users should contain user names as keys and anything as values
 | 
			
		||||
    (value is not used and will be ignored). 
 | 
			
		||||
    @param hostRange Range of ip addresses from which connection is allowed.
 | 
			
		||||
    @param users Hashtable of users for whom connection is allowed, or null
 | 
			
		||||
    to indicate that anybody is allowed to connect from the hosts within given
 | 
			
		||||
    range.
 | 
			
		||||
   */
 | 
			
		||||
   public synchronized void add(InetRange hostRange,Hashtable users){
 | 
			
		||||
      this.hosts.addElement(hostRange);
 | 
			
		||||
      this.users.addElement(users);
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
     Grants permission only to those users, who connect from one of the
 | 
			
		||||
     hosts registered with add(InetRange,Hashtable) and whose names, as
 | 
			
		||||
     reported by identd daemon, are listed for the host the connection
 | 
			
		||||
     came from.
 | 
			
		||||
    */
 | 
			
		||||
   public ServerAuthenticator startSession(Socket s)
 | 
			
		||||
                              throws IOException{
 | 
			
		||||
 | 
			
		||||
     int ind = getRangeIndex(s.getInetAddress());
 | 
			
		||||
     String user = null;
 | 
			
		||||
 | 
			
		||||
     //System.out.println("getRangeReturned:"+ind);
 | 
			
		||||
 | 
			
		||||
     if(ind < 0) return null; //Host is not on the list.
 | 
			
		||||
 | 
			
		||||
     ServerAuthenticatorNone auth = (ServerAuthenticatorNone)
 | 
			
		||||
                                    super.startSession(s);
 | 
			
		||||
 | 
			
		||||
     //System.out.println("super.startSession() returned:"+auth);
 | 
			
		||||
     if(auth == null) return null;
 | 
			
		||||
 | 
			
		||||
     //do the authentication 
 | 
			
		||||
 | 
			
		||||
     Hashtable user_names = (Hashtable) users.elementAt(ind); 
 | 
			
		||||
 | 
			
		||||
     if(user_names != null){ //If need to do authentication
 | 
			
		||||
       Ident ident;
 | 
			
		||||
       ident = new Ident(s);
 | 
			
		||||
       //If can't obtain user name, fail
 | 
			
		||||
       if(!ident.successful) return null;
 | 
			
		||||
       //If user name is not listed for this address, fail
 | 
			
		||||
       if(!user_names.containsKey(ident.userName)) return null;
 | 
			
		||||
       user = ident.userName;
 | 
			
		||||
     }
 | 
			
		||||
     return new IdentAuthenticator(auth.in,auth.out,user);
 | 
			
		||||
 | 
			
		||||
   }
 | 
			
		||||
   /**
 | 
			
		||||
    For SOCKS5 requests allways returns true. For SOCKS4 requests
 | 
			
		||||
    checks wether the user name supplied in the request corresponds
 | 
			
		||||
    to the name obtained from the ident daemon.
 | 
			
		||||
   */
 | 
			
		||||
   public boolean checkRequest(ProxyMessage msg,java.net.Socket s){
 | 
			
		||||
     //If it's version 5 request, or if anybody is permitted, return true;
 | 
			
		||||
     if(msg.version == 5 || user == null) 
 | 
			
		||||
       return true;
 | 
			
		||||
 | 
			
		||||
     if(msg.version != 4) return false; //Who knows?
 | 
			
		||||
 | 
			
		||||
     return user.equals(msg.user);
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
  /** Get String representaion of the IdentAuthenticator.*/
 | 
			
		||||
  public String toString(){
 | 
			
		||||
     String s = "";
 | 
			
		||||
 | 
			
		||||
     for(int i=0;i<hosts.size();++i)
 | 
			
		||||
        s += "Range:"+hosts.elementAt(i)+"\nUsers:"+userNames(i)+"\n";
 | 
			
		||||
     return s;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
//Private Methods
 | 
			
		||||
//////////////////
 | 
			
		||||
  private int getRangeIndex(InetAddress ip){
 | 
			
		||||
     int index = 0;
 | 
			
		||||
     Iterator iterator = hosts.iterator();
 | 
			
		||||
     while(iterator.hasNext()){
 | 
			
		||||
       InetRange ir = (InetRange) iterator.next();
 | 
			
		||||
       if(ir.contains(ip)) return index;
 | 
			
		||||
       index++;
 | 
			
		||||
     }
 | 
			
		||||
     return -1; //Not found
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private String userNames(int i){
 | 
			
		||||
    if(users.elementAt(i) == null) return "Everybody is permitted.";
 | 
			
		||||
    Iterator iterator = ((Hashtable)users.elementAt(i)).keySet().iterator();
 | 
			
		||||
    if(!iterator.hasNext()) return "";
 | 
			
		||||
    String s = iterator.next().toString();
 | 
			
		||||
    while(iterator.hasNext())
 | 
			
		||||
       s += "; "+iterator.next();
 | 
			
		||||
 | 
			
		||||
    return s;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,120 @@
 | 
			
		|||
package net.sourceforge.jsocks.socks.server;
 | 
			
		||||
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.io.InputStream;
 | 
			
		||||
import java.io.OutputStream;
 | 
			
		||||
import java.net.Socket;
 | 
			
		||||
import java.net.DatagramPacket;
 | 
			
		||||
 | 
			
		||||
import net.sourceforge.jsocks.socks.ProxyMessage;
 | 
			
		||||
import net.sourceforge.jsocks.socks.UDPEncapsulation;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 Classes implementing this interface should provide socks server with
 | 
			
		||||
 authentication and authorization of users.
 | 
			
		||||
**/
 | 
			
		||||
public interface ServerAuthenticator{
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
     This method is called when a new connection accepted by the server.
 | 
			
		||||
     <p>
 | 
			
		||||
     At this point no data have been extracted from the connection. It is
 | 
			
		||||
     responsibility of this method to ensure that the next byte in the
 | 
			
		||||
     stream after this method have been called is the first byte of the
 | 
			
		||||
     socks request message. For SOCKSv4 there is no authentication data and
 | 
			
		||||
     the first byte in the stream is part of the request. With SOCKSv5 however
 | 
			
		||||
     there is an authentication data first. It is expected that implementaions
 | 
			
		||||
     will process this authentication data. 
 | 
			
		||||
     <p>
 | 
			
		||||
     If authentication was successful an instance of ServerAuthentication
 | 
			
		||||
     should be returned, it later will be used by the server to perform
 | 
			
		||||
     authorization and some other things. If authentication fails null should
 | 
			
		||||
     be returned, or an exception may be thrown.
 | 
			
		||||
 | 
			
		||||
     @param s Accepted Socket.
 | 
			
		||||
     @return An instance of ServerAuthenticator to be used for this connection
 | 
			
		||||
     or null
 | 
			
		||||
   */
 | 
			
		||||
   ServerAuthenticator startSession(Socket s) throws IOException;
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
    This method should return input stream which should be used on the
 | 
			
		||||
    accepted socket.
 | 
			
		||||
    <p>
 | 
			
		||||
    SOCKSv5 allows to have multiple authentication methods, and these methods
 | 
			
		||||
    might require some kind of transformations being made on the data.
 | 
			
		||||
    <p>
 | 
			
		||||
    This method is called on the object returned from the startSession
 | 
			
		||||
    function.
 | 
			
		||||
   */
 | 
			
		||||
   InputStream getInputStream();
 | 
			
		||||
   /**
 | 
			
		||||
    This method should return output stream to use to write to the accepted
 | 
			
		||||
    socket.
 | 
			
		||||
    <p>
 | 
			
		||||
    SOCKSv5 allows to have multiple authentication methods, and these methods
 | 
			
		||||
    might require some kind of transformations being made on the data.
 | 
			
		||||
    <p>
 | 
			
		||||
    This method is called on the object returned from the startSession
 | 
			
		||||
    function.
 | 
			
		||||
   */
 | 
			
		||||
   OutputStream getOutputStream();
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
    This method should return UDPEncapsulation, which should be used
 | 
			
		||||
    on the datagrams being send in/out.
 | 
			
		||||
    <p>
 | 
			
		||||
    If no transformation should be done on the datagrams, this method
 | 
			
		||||
    should return null.
 | 
			
		||||
    <p>
 | 
			
		||||
    This method is called on the object returned from the startSession
 | 
			
		||||
    function.
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
   UDPEncapsulation getUdpEncapsulation();
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
    This method is called when a request have been read.
 | 
			
		||||
    <p>
 | 
			
		||||
    Implementation should decide wether to grant request or not. Returning
 | 
			
		||||
    true implies granting the request, false means request should be rejected.
 | 
			
		||||
    <p>
 | 
			
		||||
    This method is called on the object returned from the startSession
 | 
			
		||||
    function.
 | 
			
		||||
    @param msg Request message.
 | 
			
		||||
    @return true to grant request, false to reject it.
 | 
			
		||||
   */
 | 
			
		||||
   boolean checkRequest(ProxyMessage msg);
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
    This method is called when datagram is received by the server.
 | 
			
		||||
    <p>
 | 
			
		||||
    Implementaions should decide wether it should be forwarded or dropped.
 | 
			
		||||
    It is expecteed that implementation will use datagram address and port
 | 
			
		||||
    information to make a decision, as well as anything else. Address and
 | 
			
		||||
    port of the datagram are always correspond to remote machine. It is
 | 
			
		||||
    either destination or source address. If out is true address is destination
 | 
			
		||||
    address, else it is a source address, address of the machine from which
 | 
			
		||||
    datagram have been received for the client.
 | 
			
		||||
    <p>
 | 
			
		||||
    Implementaions should return true if the datagram is to be forwarded, and
 | 
			
		||||
    false if the datagram should be dropped.
 | 
			
		||||
    <p>
 | 
			
		||||
    This method is called on the object returned from the startSession
 | 
			
		||||
    function.
 | 
			
		||||
 | 
			
		||||
    @param out If true the datagram is being send out(from the client),
 | 
			
		||||
               otherwise it is an incoming datagram.
 | 
			
		||||
    @return True to forward datagram false drop it silently.
 | 
			
		||||
   */
 | 
			
		||||
   boolean checkRequest(DatagramPacket dp, boolean out);
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
    This method is called when session is completed. Either due to normal
 | 
			
		||||
    termination or due to any error condition.
 | 
			
		||||
    <p>
 | 
			
		||||
    This method is called on the object returned from the startSession
 | 
			
		||||
    function.
 | 
			
		||||
   */
 | 
			
		||||
   void endSession();
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,172 @@
 | 
			
		|||
package net.sourceforge.jsocks.socks.server;
 | 
			
		||||
 | 
			
		||||
import net.sourceforge.jsocks.socks.ProxyMessage;
 | 
			
		||||
import net.sourceforge.jsocks.socks.UDPEncapsulation;
 | 
			
		||||
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.io.InputStream;
 | 
			
		||||
import java.io.OutputStream;
 | 
			
		||||
import java.io.PushbackInputStream;
 | 
			
		||||
import java.net.Socket;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 An implementation of ServerAuthenticator, which does <b>not</b> do
 | 
			
		||||
 any authentication.
 | 
			
		||||
<P>
 | 
			
		||||
<FONT size="+3" color ="FF0000"> Warning!!</font><br> Should not be
 | 
			
		||||
used on machines which are not behind the firewall.
 | 
			
		||||
<p>
 | 
			
		||||
It is only provided to make implementing other authentication schemes
 | 
			
		||||
easier.<br>
 | 
			
		||||
For Example: <tt><pre>
 | 
			
		||||
   class MyAuth extends socks.server.ServerAuthenticator{
 | 
			
		||||
    ...
 | 
			
		||||
    public ServerAuthenticator startSession(java.net.Socket s){
 | 
			
		||||
      if(!checkHost(s.getInetAddress()) return null;
 | 
			
		||||
      return super.startSession(s);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    boolean checkHost(java.net.Inetaddress addr){
 | 
			
		||||
      boolean allow;
 | 
			
		||||
      //Do it somehow
 | 
			
		||||
      return allow;
 | 
			
		||||
    }
 | 
			
		||||
   }
 | 
			
		||||
</pre></tt>
 | 
			
		||||
*/
 | 
			
		||||
public class ServerAuthenticatorNone implements ServerAuthenticator{
 | 
			
		||||
 | 
			
		||||
   static final byte[] socks5response = {5,0};
 | 
			
		||||
 | 
			
		||||
   InputStream in;
 | 
			
		||||
   OutputStream out;
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
    Creates new instance of the ServerAuthenticatorNone.
 | 
			
		||||
   */
 | 
			
		||||
   public ServerAuthenticatorNone(){
 | 
			
		||||
     this.in = null;
 | 
			
		||||
     this.out = null;
 | 
			
		||||
   }
 | 
			
		||||
   /**
 | 
			
		||||
    Constructs new ServerAuthenticatorNone object suitable for returning
 | 
			
		||||
    from the startSession function.
 | 
			
		||||
    @param in Input stream to return from getInputStream method.
 | 
			
		||||
    @param out Output stream to return from getOutputStream method.
 | 
			
		||||
   */
 | 
			
		||||
   public ServerAuthenticatorNone(InputStream in, OutputStream out){
 | 
			
		||||
      this.in = in;
 | 
			
		||||
      this.out = out;
 | 
			
		||||
   }
 | 
			
		||||
   /**
 | 
			
		||||
    Grants access to everyone.Removes authentication related bytes from
 | 
			
		||||
    the stream, when a SOCKS5 connection is being made, selects an
 | 
			
		||||
    authentication NONE.
 | 
			
		||||
    */
 | 
			
		||||
   public ServerAuthenticator startSession(Socket s)
 | 
			
		||||
                                  throws IOException{
 | 
			
		||||
 | 
			
		||||
     PushbackInputStream in =  new PushbackInputStream(s.getInputStream());
 | 
			
		||||
     OutputStream out = s.getOutputStream();
 | 
			
		||||
 | 
			
		||||
     int version = in.read();
 | 
			
		||||
     if(version == 5){
 | 
			
		||||
       if(!selectSocks5Authentication(in,out,0))
 | 
			
		||||
          return null;
 | 
			
		||||
     }else if(version == 4){
 | 
			
		||||
       //Else it is the request message allready, version 4
 | 
			
		||||
       in.unread(version);
 | 
			
		||||
     }else
 | 
			
		||||
       return null;
 | 
			
		||||
     
 | 
			
		||||
 | 
			
		||||
     return new ServerAuthenticatorNone(in,out);
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
     Get input stream.
 | 
			
		||||
     @return Input stream speciefied in the constructor.
 | 
			
		||||
   */
 | 
			
		||||
   public InputStream getInputStream(){
 | 
			
		||||
      return in;
 | 
			
		||||
   }
 | 
			
		||||
   /**
 | 
			
		||||
     Get output stream.
 | 
			
		||||
     @return Output stream speciefied in the constructor.
 | 
			
		||||
   */
 | 
			
		||||
   public OutputStream getOutputStream(){
 | 
			
		||||
      return out;
 | 
			
		||||
   }
 | 
			
		||||
   /**
 | 
			
		||||
     Allways returns null.
 | 
			
		||||
     @return null
 | 
			
		||||
   */
 | 
			
		||||
   public UDPEncapsulation getUdpEncapsulation(){
 | 
			
		||||
      return null;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
    * Checks the request.  For this stub always return true.
 | 
			
		||||
    * 
 | 
			
		||||
    * @returns true if request is OK or false if its not.
 | 
			
		||||
    */
 | 
			
		||||
   public boolean checkRequest(ProxyMessage msg) {
 | 
			
		||||
     return true;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
    * Checks the request.  For this stub always return true.
 | 
			
		||||
    */
 | 
			
		||||
   public boolean checkRequest(java.net.DatagramPacket dp, boolean out){
 | 
			
		||||
     return true;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
    Does nothing.
 | 
			
		||||
    */
 | 
			
		||||
   public void endSession(){
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
     Convinience routine for selecting SOCKSv5 authentication.
 | 
			
		||||
     <p>
 | 
			
		||||
     This method reads in authentication methods that client supports,
 | 
			
		||||
     checks wether it supports given method. If it does, the notification
 | 
			
		||||
     method is written back to client, that this method have been chosen
 | 
			
		||||
     for authentication. If given method was not found, authentication
 | 
			
		||||
     failure message is send to client ([5,FF]).
 | 
			
		||||
     @param in Input stream, version byte should be removed from the stream
 | 
			
		||||
               before calling this method.
 | 
			
		||||
     @param out Output stream.
 | 
			
		||||
     @param methodId Method which should be selected.
 | 
			
		||||
     @return true if methodId was found, false otherwise.
 | 
			
		||||
   */
 | 
			
		||||
   static public boolean selectSocks5Authentication(InputStream in, 
 | 
			
		||||
                                                    OutputStream out,
 | 
			
		||||
                                                    int methodId)
 | 
			
		||||
                                                    throws IOException{
 | 
			
		||||
                                                    
 | 
			
		||||
      int num_methods = in.read();
 | 
			
		||||
      if (num_methods <= 0) return false;
 | 
			
		||||
      byte method_ids[] = new byte[num_methods];
 | 
			
		||||
      byte response[] = new byte[2];
 | 
			
		||||
      boolean found = false;
 | 
			
		||||
 | 
			
		||||
      response[0] = (byte) 5;    //SOCKS version
 | 
			
		||||
      response[1] = (byte) 0xFF; //Not found, we are pessimistic
 | 
			
		||||
 | 
			
		||||
      int bread = 0; //bytes read so far
 | 
			
		||||
      while(bread < num_methods)
 | 
			
		||||
         bread += in.read(method_ids,bread,num_methods-bread);
 | 
			
		||||
 | 
			
		||||
      for(int i=0;i<num_methods;++i)
 | 
			
		||||
         if(method_ids[i] == methodId){
 | 
			
		||||
           found = true;
 | 
			
		||||
           response[1] = (byte) methodId;
 | 
			
		||||
           break;
 | 
			
		||||
         }
 | 
			
		||||
 | 
			
		||||
      out.write(response);
 | 
			
		||||
      return found;
 | 
			
		||||
   }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,73 @@
 | 
			
		|||
package net.sourceforge.jsocks.socks.server;
 | 
			
		||||
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.io.InputStream;
 | 
			
		||||
import java.io.OutputStream;
 | 
			
		||||
import java.net.Socket;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  This class implements SOCKS5 User/Password authentication scheme as
 | 
			
		||||
  defined in rfc1929,the server side of it.
 | 
			
		||||
*/
 | 
			
		||||
public class UserPasswordAuthenticator extends  ServerAuthenticatorNone{
 | 
			
		||||
 | 
			
		||||
   static final int METHOD_ID = 2;
 | 
			
		||||
 | 
			
		||||
   UserValidation validator;
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
    Construct a new UserPasswordAuthentication object, with given
 | 
			
		||||
    UserVlaidation scheme.
 | 
			
		||||
 | 
			
		||||
    @param validator UserValidation to use for validating users.
 | 
			
		||||
   */
 | 
			
		||||
   public UserPasswordAuthenticator(UserValidation validator){
 | 
			
		||||
      this.validator = validator;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   @Override
 | 
			
		||||
   public ServerAuthenticator startSession(Socket s) throws IOException{
 | 
			
		||||
     InputStream in = s.getInputStream();
 | 
			
		||||
     OutputStream out = s.getOutputStream();
 | 
			
		||||
 | 
			
		||||
     if(in.read() != 5) return null; //Drop non version 5 messages.
 | 
			
		||||
 | 
			
		||||
     if(!selectSocks5Authentication(in,out,METHOD_ID)) 
 | 
			
		||||
       return null;
 | 
			
		||||
     if(!doUserPasswordAuthentication(s,in,out))
 | 
			
		||||
       return null;
 | 
			
		||||
 | 
			
		||||
     return new ServerAuthenticatorNone(in,out);
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//Private Methods
 | 
			
		||||
//////////////////
 | 
			
		||||
 | 
			
		||||
   private boolean doUserPasswordAuthentication(Socket s,
 | 
			
		||||
                                                InputStream in,
 | 
			
		||||
                                                OutputStream out) 
 | 
			
		||||
                                                throws IOException{
 | 
			
		||||
     int version = in.read();
 | 
			
		||||
     if(version != 1) return false;
 | 
			
		||||
     int ulen = in.read();
 | 
			
		||||
     if(ulen < 0) return false;
 | 
			
		||||
     byte[] user = new byte[ulen];
 | 
			
		||||
     in.read(user);
 | 
			
		||||
     int plen = in.read();
 | 
			
		||||
     if(plen < 0) return false;
 | 
			
		||||
     byte[] password = new byte[plen];
 | 
			
		||||
     in.read(password);
 | 
			
		||||
 | 
			
		||||
     if(validator.isUserValid(new String(user), new String(password),s)){
 | 
			
		||||
       //System.out.println("user valid");
 | 
			
		||||
       out.write(new byte[]{1,0});
 | 
			
		||||
     }else{
 | 
			
		||||
       //System.out.println("user invalid");
 | 
			
		||||
       out.write(new byte[]{1,1});
 | 
			
		||||
       return false;
 | 
			
		||||
     }
 | 
			
		||||
 | 
			
		||||
     return true;
 | 
			
		||||
   }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,21 @@
 | 
			
		|||
package net.sourceforge.jsocks.socks.server;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  Interface which provides for user validation, based on user name
 | 
			
		||||
  password and where it connects from.
 | 
			
		||||
*/
 | 
			
		||||
public interface UserValidation{
 | 
			
		||||
    /**
 | 
			
		||||
     Implementations of this interface are expected to use some or all
 | 
			
		||||
     of the information provided plus any information they can extract
 | 
			
		||||
     from other sources to decide wether given user should be allowed
 | 
			
		||||
     access to SOCKS server, or whatever you use it for.
 | 
			
		||||
 | 
			
		||||
     @return true to indicate user is valid, false otherwise.
 | 
			
		||||
     @param username User whom implementation should validate.
 | 
			
		||||
     @param password Password this user provided.
 | 
			
		||||
     @param connection Socket which user used to connect to the server.
 | 
			
		||||
    */
 | 
			
		||||
    boolean isUserValid(String username,String password,
 | 
			
		||||
                        java.net.Socket connection);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,125 @@
 | 
			
		|||
package net.sourceforge.jsocks.test;
 | 
			
		||||
 | 
			
		||||
import java.net.InetAddress;
 | 
			
		||||
import java.net.Socket;
 | 
			
		||||
import java.net.UnknownHostException;
 | 
			
		||||
import java.io.*;
 | 
			
		||||
 | 
			
		||||
import net.*;
 | 
			
		||||
 | 
			
		||||
/** Plain SOCKS unaware echo client.*/
 | 
			
		||||
 | 
			
		||||
public class Echo implements Runnable{
 | 
			
		||||
  
 | 
			
		||||
   private int port;
 | 
			
		||||
   private InetAddress peerIp;
 | 
			
		||||
 | 
			
		||||
   private Socket ss;
 | 
			
		||||
   private InputStream in;
 | 
			
		||||
   private OutputStream out;
 | 
			
		||||
 | 
			
		||||
   private static final int BUF_SIZE = 1024;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
   public Echo(String host,int port,String peerHost,int peerPort) 
 | 
			
		||||
	  throws IOException,UnknownHostException{
 | 
			
		||||
      this.peerIp = InetAddress.getByName(peerHost);
 | 
			
		||||
      this.port = port;
 | 
			
		||||
 | 
			
		||||
      ss = new Socket(host, port,peerIp,peerPort);
 | 
			
		||||
      out = ss.getOutputStream();
 | 
			
		||||
      in  = ss.getInputStream();
 | 
			
		||||
      System.out.println("Connected...");
 | 
			
		||||
      System.out.println("TO: "+host+":"+port);
 | 
			
		||||
      System.out.println("LocalAddress: "+ss.getLocalAddress().getHostAddress()
 | 
			
		||||
                                 +":"+ss.getLocalPort());
 | 
			
		||||
 | 
			
		||||
   }
 | 
			
		||||
   public Echo(String host,int port) 
 | 
			
		||||
	  throws IOException,UnknownHostException{
 | 
			
		||||
 | 
			
		||||
      System.out.println("Connecting...");
 | 
			
		||||
      ss = new Socket(host, port);
 | 
			
		||||
      out = ss.getOutputStream();
 | 
			
		||||
      in  = ss.getInputStream();
 | 
			
		||||
      System.out.println("TO: "+host+":"+port);
 | 
			
		||||
      System.out.println("LocalAddress: "+ss.getLocalAddress().getHostAddress()
 | 
			
		||||
                                 +":"+ss.getLocalPort());
 | 
			
		||||
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
   public void send(String s) throws IOException{
 | 
			
		||||
      //System.out.println("Sending:"+s);
 | 
			
		||||
      out.write(s.getBytes());
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   public void run(){
 | 
			
		||||
      byte[] buf = new byte[1024];
 | 
			
		||||
      int bytes_read;
 | 
			
		||||
      try{
 | 
			
		||||
	  while((bytes_read = in.read(buf)) > 0){
 | 
			
		||||
	     System.out.write(buf,0,bytes_read);
 | 
			
		||||
	     System.out.flush();
 | 
			
		||||
	  }
 | 
			
		||||
      }catch(IOException io_ex){
 | 
			
		||||
	 io_ex.printStackTrace();
 | 
			
		||||
      }
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   public static void usage(){
 | 
			
		||||
      System.err.print(
 | 
			
		||||
      "Usage: java Echo host port [peerHost peerPort]\n");
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
   public static void main(String args[]){
 | 
			
		||||
      int port;
 | 
			
		||||
      String host,peerHost;
 | 
			
		||||
      int peerPort;
 | 
			
		||||
      Echo echo = null;
 | 
			
		||||
 | 
			
		||||
      if(args.length > 1){
 | 
			
		||||
	 try{
 | 
			
		||||
 | 
			
		||||
	     host = args[0];
 | 
			
		||||
	     port = Integer.parseInt(args[1]);
 | 
			
		||||
 | 
			
		||||
             if(args.length ==4){
 | 
			
		||||
	        peerHost = args[2];
 | 
			
		||||
	        peerPort =Integer.parseInt(args[3]);
 | 
			
		||||
                echo = new Echo(host,port,peerHost,peerPort);
 | 
			
		||||
             }else{
 | 
			
		||||
                echo = new Echo(host,port);
 | 
			
		||||
	     }
 | 
			
		||||
 | 
			
		||||
             Thread thread = new Thread(echo);
 | 
			
		||||
	     thread.start();
 | 
			
		||||
 | 
			
		||||
	     BufferedReader in = new BufferedReader(
 | 
			
		||||
				 new InputStreamReader(System.in));
 | 
			
		||||
             String s;
 | 
			
		||||
 | 
			
		||||
             s = in.readLine();
 | 
			
		||||
             Thread.currentThread().setPriority(Thread.NORM_PRIORITY);	
 | 
			
		||||
             while(s != null){
 | 
			
		||||
                echo.send(s+"\r\n");
 | 
			
		||||
                s = in.readLine();
 | 
			
		||||
	     }
 | 
			
		||||
	 }catch(IOException io_ex){
 | 
			
		||||
	   io_ex.printStackTrace();
 | 
			
		||||
	   System.exit(1);
 | 
			
		||||
	 }catch(NumberFormatException num_ex){
 | 
			
		||||
	   usage();
 | 
			
		||||
	   num_ex.printStackTrace();
 | 
			
		||||
	   System.exit(1);
 | 
			
		||||
         }finally{
 | 
			
		||||
           if(echo!=null) try{echo.ss.close();}catch(Exception e){}
 | 
			
		||||
         }
 | 
			
		||||
 | 
			
		||||
      }else{
 | 
			
		||||
	usage();
 | 
			
		||||
      }
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
}//End of class
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,129 @@
 | 
			
		|||
package net.sourceforge.jsocks.test;
 | 
			
		||||
 | 
			
		||||
import java.io.*;
 | 
			
		||||
import java.net.InetAddress;
 | 
			
		||||
import java.net.Socket;
 | 
			
		||||
import java.net.UnknownHostException;
 | 
			
		||||
 | 
			
		||||
import net.sourceforge.jsocks.socks.*;
 | 
			
		||||
//import net.sourceforge.jsocks.socks.Proxy;
 | 
			
		||||
 | 
			
		||||
/** SOCKS aware echo client*/
 | 
			
		||||
 | 
			
		||||
public class SocksTest implements Runnable{
 | 
			
		||||
  
 | 
			
		||||
   private int port;
 | 
			
		||||
   private InetAddress hostIP;
 | 
			
		||||
 | 
			
		||||
   private Socket ss;
 | 
			
		||||
   private InputStream in;
 | 
			
		||||
   private OutputStream out;
 | 
			
		||||
 | 
			
		||||
   private static final int BUF_SIZE = 1024;
 | 
			
		||||
   static final int defaultProxyPort = 1080;           //Default Port
 | 
			
		||||
   static final String defaultProxyHost = "www-proxy"; //Default proxy
 | 
			
		||||
 | 
			
		||||
   public SocksTest(String host,int port) 
 | 
			
		||||
	  throws IOException,UnknownHostException,SocksException{
 | 
			
		||||
      this.port = port;
 | 
			
		||||
 | 
			
		||||
      ss = new SocksSocket(host, port);
 | 
			
		||||
      out = ss.getOutputStream();
 | 
			
		||||
      in  = ss.getInputStream();
 | 
			
		||||
      System.out.println("Connected...");
 | 
			
		||||
      System.out.println("TO: "+host+":"+port);
 | 
			
		||||
      System.out.println("ViaProxy: "+ss.getLocalAddress().getHostAddress()
 | 
			
		||||
                                 +":"+ss.getLocalPort());
 | 
			
		||||
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   public void close()throws IOException{
 | 
			
		||||
     ss.close();
 | 
			
		||||
   }
 | 
			
		||||
   public void send(String s) throws IOException{
 | 
			
		||||
      out.write(s.getBytes());
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   public void run(){
 | 
			
		||||
      byte[] buf = new byte[1024];
 | 
			
		||||
      int bytes_read;
 | 
			
		||||
      try{
 | 
			
		||||
	  while((bytes_read = in.read(buf)) > 0){
 | 
			
		||||
	     System.out.write(buf,0,bytes_read);
 | 
			
		||||
	  }
 | 
			
		||||
      }catch(IOException io_ex){
 | 
			
		||||
	 io_ex.printStackTrace();
 | 
			
		||||
      }
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   public static void usage(){
 | 
			
		||||
      System.err.print(
 | 
			
		||||
      "Usage: java SocksTest host port [socksHost socksPort]\n");
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
   public static void main(String args[]){
 | 
			
		||||
      int port;
 | 
			
		||||
      String host;
 | 
			
		||||
      int proxyPort;
 | 
			
		||||
      String proxyHost;
 | 
			
		||||
 | 
			
		||||
      if(args.length > 1 && args.length < 5){
 | 
			
		||||
	 try{
 | 
			
		||||
 | 
			
		||||
	     host = args[0];
 | 
			
		||||
	     port = Integer.parseInt(args[1]);
 | 
			
		||||
 | 
			
		||||
	     proxyPort =(args.length > 3)? Integer.parseInt(args[3])	     
 | 
			
		||||
	                                 : defaultProxyPort;
 | 
			
		||||
 | 
			
		||||
	     host = args[0];
 | 
			
		||||
	     proxyHost =(args.length > 2)? args[2]
 | 
			
		||||
	                                 : defaultProxyHost;
 | 
			
		||||
 | 
			
		||||
	     Proxy.setDefaultProxy(proxyHost,proxyPort,"KOUKY001");
 | 
			
		||||
	     //Proxy.setDefaultProxy(proxyHost,proxyPort);
 | 
			
		||||
	     InetRange inetRange = new InetRange();
 | 
			
		||||
	     inetRange.add(InetAddress.getByName("localhost"));
 | 
			
		||||
	     Proxy.getDefaultProxy().setDirect(inetRange);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	     SocksTest st = new SocksTest(host,port);
 | 
			
		||||
	     Thread thread = new Thread(st);
 | 
			
		||||
	     thread.start();
 | 
			
		||||
 | 
			
		||||
	     BufferedReader in = new BufferedReader(
 | 
			
		||||
				 new InputStreamReader(System.in));
 | 
			
		||||
             String s;
 | 
			
		||||
 | 
			
		||||
             s = in.readLine();
 | 
			
		||||
	     while(s != null){
 | 
			
		||||
                st.send(s+"\r\n");
 | 
			
		||||
		//try{
 | 
			
		||||
		   //Thread.currentThread().sleep(10);
 | 
			
		||||
		//}catch(InterruptedException i_ex){
 | 
			
		||||
		//}
 | 
			
		||||
                s = in.readLine();
 | 
			
		||||
	     }
 | 
			
		||||
	     st.close();
 | 
			
		||||
	     System.exit(1);
 | 
			
		||||
 | 
			
		||||
	 }catch(SocksException s_ex){
 | 
			
		||||
	   System.err.println("SocksException:"+s_ex);
 | 
			
		||||
	   s_ex.printStackTrace();
 | 
			
		||||
	   System.exit(1); 
 | 
			
		||||
	 }catch(IOException io_ex){
 | 
			
		||||
	   io_ex.printStackTrace();
 | 
			
		||||
	   System.exit(1);
 | 
			
		||||
	 }catch(NumberFormatException num_ex){
 | 
			
		||||
	   usage();
 | 
			
		||||
	   num_ex.printStackTrace();
 | 
			
		||||
	   System.exit(1);
 | 
			
		||||
	 }
 | 
			
		||||
 | 
			
		||||
      }else{
 | 
			
		||||
	usage();
 | 
			
		||||
      }
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
}//End of class
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,103 @@
 | 
			
		|||
package net.sourceforge.jsocks.test;
 | 
			
		||||
 | 
			
		||||
import java.net.DatagramPacket;
 | 
			
		||||
import java.net.DatagramSocket;
 | 
			
		||||
import java.net.InetAddress;
 | 
			
		||||
import java.io.*;
 | 
			
		||||
 | 
			
		||||
import net.sourceforge.jsocks.socks.*;
 | 
			
		||||
 | 
			
		||||
/** SOCKS aware UDP echo client.<br>
 | 
			
		||||
    Reads input line by line and sends it to given on command line
 | 
			
		||||
    host and port, using given proxy, then blocks until reply datagram
 | 
			
		||||
    recieved, not really echo, single threaded client, I just used it
 | 
			
		||||
    for testing before UDP actually worked.
 | 
			
		||||
*/
 | 
			
		||||
public class SocksUDPEcho{
 | 
			
		||||
 | 
			
		||||
   public static void usage(){
 | 
			
		||||
      System.err.print(
 | 
			
		||||
    "Usage: java SocksUDPEcho host port [socksHost socksPort]\n");
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   static final int defaultProxyPort = 1080;           //Default Port
 | 
			
		||||
   static final String defaultProxyHost = "www-proxy"; //Default proxy
 | 
			
		||||
 | 
			
		||||
   public static void main(String args[]){
 | 
			
		||||
      int port;
 | 
			
		||||
      String host;
 | 
			
		||||
      int proxyPort;
 | 
			
		||||
      String proxyHost;
 | 
			
		||||
      InetAddress ip;
 | 
			
		||||
 | 
			
		||||
      if(args.length > 1 && args.length < 5){
 | 
			
		||||
	 try{
 | 
			
		||||
 | 
			
		||||
	     host = args[0];
 | 
			
		||||
	     port = Integer.parseInt(args[1]);
 | 
			
		||||
 | 
			
		||||
	     proxyPort =(args.length > 3)? Integer.parseInt(args[3])	     
 | 
			
		||||
	                                 : defaultProxyPort;
 | 
			
		||||
 | 
			
		||||
	     host = args[0];
 | 
			
		||||
	     ip = InetAddress.getByName(host);
 | 
			
		||||
 | 
			
		||||
	     proxyHost =(args.length > 2)? args[2]
 | 
			
		||||
	                                 : defaultProxyHost;
 | 
			
		||||
 | 
			
		||||
	     Proxy.setDefaultProxy(proxyHost,proxyPort);
 | 
			
		||||
	     Proxy p = Proxy.getDefaultProxy();
 | 
			
		||||
	     p.addDirect("lux");
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	     DatagramSocket ds = new Socks5DatagramSocket();
 | 
			
		||||
	                             
 | 
			
		||||
 | 
			
		||||
	     BufferedReader in = new BufferedReader(
 | 
			
		||||
				 new InputStreamReader(System.in));
 | 
			
		||||
             String s;
 | 
			
		||||
 | 
			
		||||
             System.out.print("Enter line:");
 | 
			
		||||
             s = in.readLine();
 | 
			
		||||
 | 
			
		||||
	     while(s != null){
 | 
			
		||||
                byte[] data = (s+"\r\n").getBytes();
 | 
			
		||||
                DatagramPacket dp = new DatagramPacket(data,0,data.length,
 | 
			
		||||
                                        ip,port);
 | 
			
		||||
                System.out.println("Sending to: "+ip+":"+port);
 | 
			
		||||
                ds.send(dp);
 | 
			
		||||
	        dp = new DatagramPacket(new byte[1024],1024);
 | 
			
		||||
 | 
			
		||||
	        System.out.println("Trying to recieve on port:"+
 | 
			
		||||
	                            ds.getLocalPort());
 | 
			
		||||
	        ds.receive(dp);
 | 
			
		||||
	        System.out.print("Recieved:\n"+
 | 
			
		||||
	                         "From:"+dp.getAddress()+":"+dp.getPort()+
 | 
			
		||||
	                         "\n\n"+
 | 
			
		||||
                new String(dp.getData(),dp.getOffset(),dp.getLength())+"\n"
 | 
			
		||||
                );
 | 
			
		||||
                System.out.print("Enter line:");
 | 
			
		||||
                s = in.readLine();
 | 
			
		||||
 | 
			
		||||
	     }
 | 
			
		||||
	     ds.close();
 | 
			
		||||
	     System.exit(1);
 | 
			
		||||
 | 
			
		||||
	 }catch(SocksException s_ex){
 | 
			
		||||
	   System.err.println("SocksException:"+s_ex);
 | 
			
		||||
	   s_ex.printStackTrace();
 | 
			
		||||
	   System.exit(1); 
 | 
			
		||||
	 }catch(IOException io_ex){
 | 
			
		||||
	   io_ex.printStackTrace();
 | 
			
		||||
	   System.exit(1);
 | 
			
		||||
	 }catch(NumberFormatException num_ex){
 | 
			
		||||
	   usage();
 | 
			
		||||
	   num_ex.printStackTrace();
 | 
			
		||||
	   System.exit(1);
 | 
			
		||||
	 }
 | 
			
		||||
 | 
			
		||||
      }else{
 | 
			
		||||
	usage();
 | 
			
		||||
      }
 | 
			
		||||
   }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,241 @@
 | 
			
		|||
package net.sourceforge.jsocks.test;
 | 
			
		||||
 | 
			
		||||
import java.io.*;
 | 
			
		||||
import java.net.InetAddress;
 | 
			
		||||
import java.net.ServerSocket;
 | 
			
		||||
 | 
			
		||||
import net.sourceforge.jsocks.socks.*;
 | 
			
		||||
import net.sourceforge.jsocks.socks.Proxy;
 | 
			
		||||
 | 
			
		||||
public class TestClient extends TestService{
 | 
			
		||||
   /** Proxy which should be used*/
 | 
			
		||||
   Proxy proxy;
 | 
			
		||||
   /** Host on which TestServer is running*/
 | 
			
		||||
   String testHost;
 | 
			
		||||
 | 
			
		||||
   int timeout = 15000;
 | 
			
		||||
   int acceptTimeout = 0;
 | 
			
		||||
 | 
			
		||||
   BufferedReader in;
 | 
			
		||||
   Writer out;
 | 
			
		||||
 | 
			
		||||
   public TestClient(Proxy p,String testHost){
 | 
			
		||||
      this.proxy = p;
 | 
			
		||||
      this.testHost = testHost;
 | 
			
		||||
      if(log == null) log = System.out;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   public void start(){
 | 
			
		||||
      connectTests(true);
 | 
			
		||||
      acceptTests(true);
 | 
			
		||||
      udpTests(true);
 | 
			
		||||
 | 
			
		||||
      connectTests(false);
 | 
			
		||||
      acceptTests(false);
 | 
			
		||||
      udpTests(false);
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   void connectTests(boolean useString){
 | 
			
		||||
      try{
 | 
			
		||||
         open(ECHO, useString);
 | 
			
		||||
         testEcho();
 | 
			
		||||
         s.close();
 | 
			
		||||
 | 
			
		||||
         open(DISCARD, useString);
 | 
			
		||||
         testDiscard();
 | 
			
		||||
         s.close();
 | 
			
		||||
 | 
			
		||||
         open(CHARGEN, useString);
 | 
			
		||||
 | 
			
		||||
         for(int i = 0; i< 3;){
 | 
			
		||||
            try{ 
 | 
			
		||||
               testChargen();
 | 
			
		||||
               break;
 | 
			
		||||
            }catch(InterruptedIOException ioe){
 | 
			
		||||
               log("IO interrupted:"+i);
 | 
			
		||||
               i++;
 | 
			
		||||
            }
 | 
			
		||||
         }
 | 
			
		||||
 | 
			
		||||
         s.close();
 | 
			
		||||
 | 
			
		||||
      }catch(IOException ioe){
 | 
			
		||||
         ioe.printStackTrace();
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   void acceptTests(boolean useString){
 | 
			
		||||
      try{
 | 
			
		||||
         testAccept(ECHO, useString);
 | 
			
		||||
         testEcho();
 | 
			
		||||
         s.close();
 | 
			
		||||
 | 
			
		||||
         testAccept(DISCARD, useString);
 | 
			
		||||
         testDiscard();
 | 
			
		||||
         s.close();
 | 
			
		||||
 | 
			
		||||
         testAccept(CHARGEN, useString);
 | 
			
		||||
 | 
			
		||||
         for(int i = 0; i< 3;){
 | 
			
		||||
            try{ 
 | 
			
		||||
               testChargen();
 | 
			
		||||
               break;
 | 
			
		||||
            }catch(InterruptedIOException ioe){
 | 
			
		||||
               log("IO interrupted:"+i);
 | 
			
		||||
               i++;
 | 
			
		||||
            }
 | 
			
		||||
         }
 | 
			
		||||
         s.close();
 | 
			
		||||
 | 
			
		||||
      }catch(IOException ioe){
 | 
			
		||||
         ioe.printStackTrace();
 | 
			
		||||
      }
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   void udpTests(boolean useString){
 | 
			
		||||
      log("Udp tests are not yet implemented");
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   void testEcho() throws IOException{
 | 
			
		||||
      log("Testing echo.");
 | 
			
		||||
      for(int i=0;i<5;++i){
 | 
			
		||||
         out.write("String number "+i+"\r\n");
 | 
			
		||||
         out.flush();
 | 
			
		||||
         log("Echo:"+in.readLine());;
 | 
			
		||||
      }
 | 
			
		||||
      log("Echo finished");
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   void testDiscard() throws IOException{
 | 
			
		||||
      log("Testing discard");
 | 
			
		||||
      for(int i =0; i < 5;++i){
 | 
			
		||||
         log("Sending discard message:"+i);
 | 
			
		||||
         out.write("Discard message:"+i+"\r\n");
 | 
			
		||||
         out.flush();
 | 
			
		||||
      }
 | 
			
		||||
      log("Discard finished");
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   void testChargen() throws IOException{
 | 
			
		||||
      log("Testing chargen");
 | 
			
		||||
      String s;
 | 
			
		||||
      s = in.readLine();
 | 
			
		||||
      while(s!=null){
 | 
			
		||||
         log("ChGen:"+s);
 | 
			
		||||
         s = in.readLine();
 | 
			
		||||
      }
 | 
			
		||||
      log("Chargen finished.");
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   void testAccept(int service,boolean useString)throws IOException{
 | 
			
		||||
      open(CONNECT,useString);
 | 
			
		||||
 | 
			
		||||
      log("Testing accept");
 | 
			
		||||
      ServerSocket ss;
 | 
			
		||||
 | 
			
		||||
      if(useString)
 | 
			
		||||
        ss = new SocksServerSocket(proxy,testHost,servicePorts[service]);
 | 
			
		||||
      else
 | 
			
		||||
        ss = new SocksServerSocket(proxy,InetAddress.getByName(testHost),
 | 
			
		||||
                                   servicePorts[service]);
 | 
			
		||||
      log("Listenning on "+ss.getInetAddress()+":"+ss.getLocalPort());
 | 
			
		||||
      ss.setSoTimeout(acceptTimeout);
 | 
			
		||||
 
 | 
			
		||||
      out.write(""+ss.getLocalPort()+" "+service+"\r\n");
 | 
			
		||||
      out.flush();
 | 
			
		||||
 | 
			
		||||
      String line = in.readLine();
 | 
			
		||||
      if(line != null){
 | 
			
		||||
        log("Accept failed:"+line);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      s.close();
 | 
			
		||||
 | 
			
		||||
      s = ss.accept();
 | 
			
		||||
      log("Accepted:"+s);
 | 
			
		||||
 | 
			
		||||
      s.setSoTimeout(timeout);
 | 
			
		||||
 | 
			
		||||
      out = new OutputStreamWriter(s.getOutputStream());
 | 
			
		||||
      in  = new BufferedReader(new InputStreamReader(s.getInputStream()));
 | 
			
		||||
 | 
			
		||||
      ss.close();
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   void open(int service,boolean useString) throws IOException{
 | 
			
		||||
 | 
			
		||||
      if(!useString){
 | 
			
		||||
         s = new SocksSocket(proxy,InetAddress.getByName(testHost),
 | 
			
		||||
                                   servicePorts[service]);
 | 
			
		||||
      }else{
 | 
			
		||||
         s = new SocksSocket(proxy,testHost,servicePorts[service]);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      s.setSoTimeout(timeout);
 | 
			
		||||
 | 
			
		||||
      out = new OutputStreamWriter(s.getOutputStream());
 | 
			
		||||
      in  = new BufferedReader(new InputStreamReader(s.getInputStream()));
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   //Main function
 | 
			
		||||
   ///////////////
 | 
			
		||||
 | 
			
		||||
   static void usage(){
 | 
			
		||||
      System.err.println(
 | 
			
		||||
      "Usage: java Testclient testhost proxy [directhosts]");
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   static Proxy initProxy(String ps){
 | 
			
		||||
      java.util.StringTokenizer st = new java.util.StringTokenizer(ps,",;");
 | 
			
		||||
      Proxy proxy = null;
 | 
			
		||||
      while(st.hasMoreElements()){
 | 
			
		||||
         String entry = st.nextToken();
 | 
			
		||||
         Proxy p = Proxy.parseProxy(entry);
 | 
			
		||||
         if( p == null){
 | 
			
		||||
           log("Proxy "+entry+" invalid.");
 | 
			
		||||
           return null;
 | 
			
		||||
         }
 | 
			
		||||
         p.setChainProxy(proxy);
 | 
			
		||||
         proxy = p;
 | 
			
		||||
      }
 | 
			
		||||
      return proxy;
 | 
			
		||||
   }
 | 
			
		||||
   static void addDirectHosts(Proxy p, String directHosts){
 | 
			
		||||
      java.util.StringTokenizer st = new java.util.StringTokenizer(
 | 
			
		||||
                                         directHosts,",;");
 | 
			
		||||
 | 
			
		||||
      while(st.hasMoreElements()){
 | 
			
		||||
         String entry = st.nextToken();
 | 
			
		||||
         log("Adding direct host:"+entry);
 | 
			
		||||
         p.addDirect(entry);
 | 
			
		||||
      }
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   public static void main(String[] argv){
 | 
			
		||||
      if(argv.length < 2){
 | 
			
		||||
        usage();
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      log = System.out;
 | 
			
		||||
 | 
			
		||||
      String testHost = argv[0];
 | 
			
		||||
      String proxyHost = argv[1];
 | 
			
		||||
      String directHosts = argv.length >2 ? argv[2] : null;
 | 
			
		||||
 | 
			
		||||
      Proxy p = initProxy(proxyHost);
 | 
			
		||||
      if(p == null){
 | 
			
		||||
         log("Can't init proxy.");
 | 
			
		||||
         return;
 | 
			
		||||
      }
 | 
			
		||||
      if(directHosts!=null) addDirectHosts(p,directHosts);
 | 
			
		||||
 | 
			
		||||
      if(p instanceof Socks5Proxy)
 | 
			
		||||
         ((Socks5Proxy) p).resolveAddrLocally(false);
 | 
			
		||||
 | 
			
		||||
      TestClient tc = new TestClient(p,testHost);
 | 
			
		||||
      tc.start();
 | 
			
		||||
      
 | 
			
		||||
   }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,83 @@
 | 
			
		|||
package net.sourceforge.jsocks.test;
 | 
			
		||||
 | 
			
		||||
import java.io.*;
 | 
			
		||||
import java.net.ServerSocket;
 | 
			
		||||
import java.net.Socket;
 | 
			
		||||
 | 
			
		||||
import net.*;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  Server to used perform tests for SOCKS library.
 | 
			
		||||
*/
 | 
			
		||||
public class TestServer implements Runnable{
 | 
			
		||||
  static PrintStream log	= null;
 | 
			
		||||
 | 
			
		||||
  int service;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   Creates a TestServer object which will listen on the port associated
 | 
			
		||||
   with given service.
 | 
			
		||||
 | 
			
		||||
   @param service Service to provide
 | 
			
		||||
  */
 | 
			
		||||
  public TestServer(int service){
 | 
			
		||||
    this.service = service;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public void run(){
 | 
			
		||||
     try{
 | 
			
		||||
         server(service);
 | 
			
		||||
     }catch(IOException ioe){
 | 
			
		||||
	 log("Exception:"+ioe);
 | 
			
		||||
	 ioe.printStackTrace();
 | 
			
		||||
     }
 | 
			
		||||
  }
 | 
			
		||||
  //Static functions
 | 
			
		||||
  /////////////////
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
    Listens on the port associated with given service.
 | 
			
		||||
    <p>
 | 
			
		||||
    When connection is accepted, speciefied service is performed.
 | 
			
		||||
    It is being done in separate thread.
 | 
			
		||||
    @return Never returns.
 | 
			
		||||
  */
 | 
			
		||||
  static public void server(int service) throws IOException{
 | 
			
		||||
     ServerSocket ss = new ServerSocket(TestService.servicePorts[service]);
 | 
			
		||||
     Socket s;
 | 
			
		||||
 | 
			
		||||
     s = ss.accept();
 | 
			
		||||
     while(s!=null){
 | 
			
		||||
	TestService st = new TestService(s,service);
 | 
			
		||||
	Thread t = new Thread(st);
 | 
			
		||||
	t.start();
 | 
			
		||||
	s = ss.accept();
 | 
			
		||||
     }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
    Performs logging.
 | 
			
		||||
  */
 | 
			
		||||
  static synchronized void log(String s){
 | 
			
		||||
     if(log != null) log.println(s);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  //Main Function
 | 
			
		||||
  ///////////////
 | 
			
		||||
  public static void main(String[] args){
 | 
			
		||||
      log = System.out;
 | 
			
		||||
      TestService.log = log;
 | 
			
		||||
 | 
			
		||||
      TestServer st;
 | 
			
		||||
      for( int i = 0; i< TestService.serviceNames.length;++i){
 | 
			
		||||
	 log("Starting service "+TestService.serviceNames[i]+" at port "+
 | 
			
		||||
	      TestService.servicePorts[i]+".");
 | 
			
		||||
         st = new TestServer(i);
 | 
			
		||||
	 Thread t = new Thread(st);
 | 
			
		||||
	 t.start();
 | 
			
		||||
      }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,275 @@
 | 
			
		|||
package net.sourceforge.jsocks.test;
 | 
			
		||||
 | 
			
		||||
import java.io.*;
 | 
			
		||||
import java.net.Socket;
 | 
			
		||||
 | 
			
		||||
import net.*;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  Server to used perform tests for SOCKS library.
 | 
			
		||||
*/
 | 
			
		||||
public class TestService implements Runnable{
 | 
			
		||||
  static final String chargenSequence = " !\"#$%&'()*+,-./0123456789:;<=>?@"+
 | 
			
		||||
  "ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefg";
 | 
			
		||||
 | 
			
		||||
  static final String serviceNames[] = {"echo","discard","chargen","connect"};
 | 
			
		||||
  static final int    servicePorts[] = {5678,5679,5680,5681};
 | 
			
		||||
 | 
			
		||||
  static final int ECHO		= 0;
 | 
			
		||||
  static final int DISCARD	= 1;
 | 
			
		||||
  static final int CHARGEN	= 2;
 | 
			
		||||
  static final int CONNECT	= 3;
 | 
			
		||||
 | 
			
		||||
  static final int BUF_SIZE	= 1024;
 | 
			
		||||
 | 
			
		||||
  static final int CHARGEN_WAIT	= 1000;   //1 second
 | 
			
		||||
  static final int MAX_WAIT	= 60000;  //1 minute
 | 
			
		||||
 | 
			
		||||
  static PrintStream log	= null;
 | 
			
		||||
 | 
			
		||||
  //Class constants
 | 
			
		||||
  Socket s;
 | 
			
		||||
  int service;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   Creates new TestService object, which will perform particular
 | 
			
		||||
   service on given socket.
 | 
			
		||||
 | 
			
		||||
   @param s Socket on which to perform service.
 | 
			
		||||
   @param service Service which to provide.
 | 
			
		||||
  */
 | 
			
		||||
  public TestService(Socket s, int service){
 | 
			
		||||
    this.s = s;
 | 
			
		||||
    this.service = service;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   Default constructor.
 | 
			
		||||
  */
 | 
			
		||||
  public TestService(){
 | 
			
		||||
    this.s = null;
 | 
			
		||||
    this.service = -1;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public void run(){
 | 
			
		||||
     try{
 | 
			
		||||
       serve(s,service);
 | 
			
		||||
     }catch(IOException ioe){
 | 
			
		||||
	 log("Exception:"+ioe);
 | 
			
		||||
	 ioe.printStackTrace();
 | 
			
		||||
     }
 | 
			
		||||
     try{ s.close();}catch(IOException ioe){}
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  //Static functions
 | 
			
		||||
  /////////////////
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   Maps service name to the integer id, does it in simple
 | 
			
		||||
   linear search manner.
 | 
			
		||||
   @param serviceName Name of the service whose id one needs.
 | 
			
		||||
   @return Integer identifier for this servuce, or -1, if service
 | 
			
		||||
           can't be found.
 | 
			
		||||
  */
 | 
			
		||||
  static public int getServiceId(String serviceName){
 | 
			
		||||
     serviceName = serviceName.toLowerCase();
 | 
			
		||||
     for(int i = 0;i < serviceNames.length;++i)
 | 
			
		||||
        if(serviceName.equals(serviceNames[i]))
 | 
			
		||||
           return i;
 | 
			
		||||
 | 
			
		||||
     //Couldn't find one.
 | 
			
		||||
     return -1;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
    Performs given service on given socket.
 | 
			
		||||
    <p>
 | 
			
		||||
    Simply looks up and calls associated method.
 | 
			
		||||
    @param s Socket on which to perform service.
 | 
			
		||||
    @param service Id of the service to perform.
 | 
			
		||||
    @return true if service have been found, false otherwise.
 | 
			
		||||
  */
 | 
			
		||||
  static public boolean serve(Socket s, int service) throws IOException{
 | 
			
		||||
    switch(service){
 | 
			
		||||
      case ECHO:
 | 
			
		||||
        echo(s);
 | 
			
		||||
      break;
 | 
			
		||||
      case DISCARD:
 | 
			
		||||
        discard(s);
 | 
			
		||||
      break;
 | 
			
		||||
      case CHARGEN:
 | 
			
		||||
        chargen(s,CHARGEN_WAIT,MAX_WAIT);
 | 
			
		||||
      break;
 | 
			
		||||
      case CONNECT:
 | 
			
		||||
        connect(s);
 | 
			
		||||
      break;
 | 
			
		||||
      default:
 | 
			
		||||
         log("Unknown service:"+service);
 | 
			
		||||
	 return false;
 | 
			
		||||
    }
 | 
			
		||||
     return true;
 | 
			
		||||
  }
 | 
			
		||||
  /**
 | 
			
		||||
    Echos any input on the socket to the output.
 | 
			
		||||
    Echo is being done line by line.
 | 
			
		||||
    @param s Socket on which to perform service.
 | 
			
		||||
  */
 | 
			
		||||
  static public void echo(Socket s) throws IOException{
 | 
			
		||||
    BufferedReader in = new BufferedReader(new InputStreamReader(
 | 
			
		||||
					       s.getInputStream()));
 | 
			
		||||
    OutputStream out = s.getOutputStream();
 | 
			
		||||
 | 
			
		||||
    log("Starting \"echo\" on "+s);
 | 
			
		||||
 | 
			
		||||
    String line = in.readLine();
 | 
			
		||||
    while(line != null){
 | 
			
		||||
       out.write((line+"\n").getBytes());
 | 
			
		||||
       log(line);
 | 
			
		||||
       line = in.readLine();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    log("Echo done.");
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
    Reads input from the socket, and does not write anything back.
 | 
			
		||||
    logs input in line by line fashion.
 | 
			
		||||
    @param s Socket on which to perform service.
 | 
			
		||||
  */
 | 
			
		||||
  static public void discard(Socket s) throws IOException{
 | 
			
		||||
    BufferedReader in = new BufferedReader(new InputStreamReader(
 | 
			
		||||
					       s.getInputStream()));
 | 
			
		||||
    log("Starting discard on "+s);
 | 
			
		||||
 | 
			
		||||
    String line = in.readLine();
 | 
			
		||||
    while(line != null){
 | 
			
		||||
       log(line);
 | 
			
		||||
       line = in.readLine();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    log("Discard finished.");
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
    Generates characters and sends them to the socket.
 | 
			
		||||
    <p>
 | 
			
		||||
    Unlike usual chargen (port 19), each next line of the generated
 | 
			
		||||
    output is send after increasingly larger time intervals. It starts
 | 
			
		||||
    from wait_time (ms), and each next time wait time is doubled.
 | 
			
		||||
    Eg. 1 2 4 8 16 32 64 128 256 512 1024 2048 4096 8192 ... well
 | 
			
		||||
    you got the idea.
 | 
			
		||||
    <p>
 | 
			
		||||
    It starts if either connection is clsoed or the wait time grows
 | 
			
		||||
    bigger than max_wait.
 | 
			
		||||
 | 
			
		||||
    @param s Socket on which to perform service.
 | 
			
		||||
    @param wait_time Time in ms, from which timing sequence should begin.
 | 
			
		||||
    @param max_wait Time in ms, after reaching timeout greater than this
 | 
			
		||||
		    value, chargen will stop.
 | 
			
		||||
  */
 | 
			
		||||
  static public void chargen(Socket s,long wait_time,long max_wait)
 | 
			
		||||
		     throws IOException{
 | 
			
		||||
    byte[] buf = chargenSequence.getBytes();
 | 
			
		||||
    int pos = 0;
 | 
			
		||||
    OutputStream out = s.getOutputStream();
 | 
			
		||||
    InputStream in = s.getInputStream();
 | 
			
		||||
    s.setSoTimeout(100); //0.1 ms
 | 
			
		||||
 | 
			
		||||
    log("Starting \"chargen\" on "+s);
 | 
			
		||||
    while(true){
 | 
			
		||||
       log("Sending message.");
 | 
			
		||||
       out.write(buf,pos,buf.length - pos);
 | 
			
		||||
       out.write(buf,0,pos);       
 | 
			
		||||
       out.write("\n".getBytes());
 | 
			
		||||
       pos++;
 | 
			
		||||
       try{
 | 
			
		||||
	  if(wait_time > max_wait) break;
 | 
			
		||||
 | 
			
		||||
	  log("Going to sleep for "+wait_time+" ms.");
 | 
			
		||||
          Thread.currentThread().sleep(wait_time);
 | 
			
		||||
	  wait_time *= 2;
 | 
			
		||||
	  if(in.read() < 0) break; //Connection closed
 | 
			
		||||
       }catch(InterruptedException ie){
 | 
			
		||||
       }catch(InterruptedIOException ioe){
 | 
			
		||||
       }
 | 
			
		||||
    }
 | 
			
		||||
    log("Chargen finished.");
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
    Models connect back situation.
 | 
			
		||||
    <p>
 | 
			
		||||
    Reads a line from the socket connection, line should be in the
 | 
			
		||||
    form port service_id. Connects back to the remote host to port
 | 
			
		||||
    specified in the line, if successful performs a service speciefied
 | 
			
		||||
    by id on that new connection. If accept was successful closes the
 | 
			
		||||
    control connection, else outputs error message, and then closes
 | 
			
		||||
    the connection.
 | 
			
		||||
 | 
			
		||||
    @param s Control connection.
 | 
			
		||||
  */
 | 
			
		||||
  static public void connect(Socket s)throws IOException{
 | 
			
		||||
    String line = null;
 | 
			
		||||
    Socket sock;
 | 
			
		||||
    int port;
 | 
			
		||||
    int service_id;
 | 
			
		||||
 | 
			
		||||
    BufferedReader in = new BufferedReader(new InputStreamReader(
 | 
			
		||||
					       s.getInputStream()));
 | 
			
		||||
    OutputStream out = s.getOutputStream();
 | 
			
		||||
 | 
			
		||||
    log("Starting \"connect\" on "+s);
 | 
			
		||||
    line = in.readLine();
 | 
			
		||||
    if(line == null) return; //They closed connection
 | 
			
		||||
 | 
			
		||||
    java.util.StringTokenizer st = new java.util.StringTokenizer(line);
 | 
			
		||||
    if(st.countTokens() < 2){ //We need at least 'port' and "id"
 | 
			
		||||
       out.write("Expect: port serviceId.\n".getBytes());
 | 
			
		||||
       log("Invalid arguments.");
 | 
			
		||||
       return;
 | 
			
		||||
    }
 | 
			
		||||
    try{
 | 
			
		||||
       port = Integer.parseInt(st.nextToken());
 | 
			
		||||
       service_id = Integer.parseInt(st.nextToken());
 | 
			
		||||
    }catch(NumberFormatException nfe){
 | 
			
		||||
       out.write("Expect: port serviceId.\n".getBytes());
 | 
			
		||||
       log("Invalid arguments.");
 | 
			
		||||
       return;
 | 
			
		||||
    }
 | 
			
		||||
    try{
 | 
			
		||||
      log("Connecting to "+s.getInetAddress()+":"+port);
 | 
			
		||||
      sock = new Socket(s.getInetAddress(),port);
 | 
			
		||||
    }catch(IOException ioe){
 | 
			
		||||
      out.write(("Connect to "+s.getInetAddress()+
 | 
			
		||||
		 ":"+port+" failed").getBytes());
 | 
			
		||||
      log("Connect failed.");
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    s.close();
 | 
			
		||||
    log("About to serve "+service_id);
 | 
			
		||||
    serve(sock,service_id);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
    Pipes data from the input stream to the output.
 | 
			
		||||
    @param in  Input stream.
 | 
			
		||||
    @param out Output stream.
 | 
			
		||||
  */
 | 
			
		||||
  static public void pipe(InputStream in, OutputStream out)
 | 
			
		||||
                          throws IOException{
 | 
			
		||||
    byte[] buf = new byte[BUF_SIZE];
 | 
			
		||||
    int bread = 0;
 | 
			
		||||
    while(bread >= 0){
 | 
			
		||||
       bread = in.read(buf);
 | 
			
		||||
       out.write(buf,0,bread);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
    Performs logging.
 | 
			
		||||
  */
 | 
			
		||||
  static synchronized void log(String s){
 | 
			
		||||
     if(log != null) log.println(s);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,151 @@
 | 
			
		|||
package net.sourceforge.jsocks.test;
 | 
			
		||||
 | 
			
		||||
import java.net.DatagramPacket;
 | 
			
		||||
import java.net.DatagramSocket;
 | 
			
		||||
import java.net.InetAddress;
 | 
			
		||||
import java.net.UnknownHostException;
 | 
			
		||||
import java.io.*;
 | 
			
		||||
 | 
			
		||||
import net.*;
 | 
			
		||||
/**
 | 
			
		||||
 Plain SOCKS unaware UDP echo server and client.
 | 
			
		||||
*/
 | 
			
		||||
public class UDPEcho implements Runnable{
 | 
			
		||||
  
 | 
			
		||||
   private int port;
 | 
			
		||||
   private InetAddress hostIP;
 | 
			
		||||
   private DatagramSocket sock;
 | 
			
		||||
 | 
			
		||||
   private static final int BUF_SIZE = 1024;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
   public UDPEcho(String host,int port) 
 | 
			
		||||
	  throws IOException,UnknownHostException{
 | 
			
		||||
      this.hostIP = InetAddress.getByName(host);
 | 
			
		||||
      this.port = port;
 | 
			
		||||
      sock = new DatagramSocket();
 | 
			
		||||
      System.out.println("UDP: "+sock.getLocalAddress()+":"+
 | 
			
		||||
                                 sock.getLocalPort());
 | 
			
		||||
      //sock.connect(hostIP,port);
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   public void send(String s) throws IOException{
 | 
			
		||||
      System.out.println("Sending:"+s);
 | 
			
		||||
      DatagramPacket packet = new DatagramPacket(s.getBytes(),
 | 
			
		||||
                                                 s.length(),
 | 
			
		||||
						 hostIP,
 | 
			
		||||
						 port);
 | 
			
		||||
      sock.send(packet);
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   public void run(){
 | 
			
		||||
      byte[] buf = new byte[BUF_SIZE];
 | 
			
		||||
      DatagramPacket incomingData = new DatagramPacket(buf,buf.length);
 | 
			
		||||
      try{
 | 
			
		||||
	  while(true){
 | 
			
		||||
	     sock.receive(incomingData);
 | 
			
		||||
	     System.out.println("UDP From:"+
 | 
			
		||||
			      incomingData.getAddress().getHostAddress()+":"+
 | 
			
		||||
			      incomingData.getPort());
 | 
			
		||||
	     System.out.println(new String(incomingData.getData(),
 | 
			
		||||
                                0,incomingData.getLength()));
 | 
			
		||||
             System.out.flush();
 | 
			
		||||
	     incomingData.setLength(buf.length);
 | 
			
		||||
	  }
 | 
			
		||||
      }catch(IOException io_ex){
 | 
			
		||||
	 io_ex.printStackTrace();
 | 
			
		||||
      }
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   public static void usage(){
 | 
			
		||||
      System.err.print(
 | 
			
		||||
      "Usage: java UDPEcho host port\n"+
 | 
			
		||||
      "OR\n"+
 | 
			
		||||
      "Usage: java UDPEcho port\n");
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   public static void doEcho(int port)throws IOException{
 | 
			
		||||
      byte[] buf = new byte[BUF_SIZE];
 | 
			
		||||
      DatagramPacket packet = new DatagramPacket(buf,buf.length);
 | 
			
		||||
      DatagramSocket sock = new DatagramSocket(port);
 | 
			
		||||
      
 | 
			
		||||
      System.out.println("Starting UDP echo on"+
 | 
			
		||||
                          sock.getLocalAddress().getHostAddress()+
 | 
			
		||||
                          ":"+sock.getLocalPort());
 | 
			
		||||
      while(true){
 | 
			
		||||
	 try{
 | 
			
		||||
	   sock.receive(packet);
 | 
			
		||||
	   sock.send(packet);
 | 
			
		||||
           System.out.print(
 | 
			
		||||
           "UDP From: "+packet.getAddress().getHostAddress()+":"+
 | 
			
		||||
                        packet.getPort()+
 | 
			
		||||
	   "\n"+
 | 
			
		||||
	   new String(packet.getData(),0,packet.getLength())+
 | 
			
		||||
	   "\n"
 | 
			
		||||
	   );
 | 
			
		||||
           System.out.flush();
 | 
			
		||||
           
 | 
			
		||||
	   packet.setLength(buf.length);
 | 
			
		||||
           //packet = new DatagramPacket(buf,buf.length);
 | 
			
		||||
	 }catch(IOException io_ex){
 | 
			
		||||
	 }
 | 
			
		||||
      }
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   public static void main(String args[]){
 | 
			
		||||
      int port;
 | 
			
		||||
      String host;
 | 
			
		||||
 | 
			
		||||
      if(args.length == 1){
 | 
			
		||||
	 try{
 | 
			
		||||
	   port = Integer.parseInt(args[0]);
 | 
			
		||||
 | 
			
		||||
	   doEcho(port);
 | 
			
		||||
 | 
			
		||||
	 }catch(IOException io_ex){
 | 
			
		||||
	   io_ex.printStackTrace();
 | 
			
		||||
	   System.exit(1);
 | 
			
		||||
 | 
			
		||||
	 }catch(NumberFormatException num_ex){
 | 
			
		||||
	   num_ex.printStackTrace();
 | 
			
		||||
	   System.exit(1);
 | 
			
		||||
	 }
 | 
			
		||||
      }else if(args.length == 2){
 | 
			
		||||
	 try{
 | 
			
		||||
	     host = args[0];
 | 
			
		||||
	     port = Integer.parseInt(args[1]);
 | 
			
		||||
 | 
			
		||||
	     UDPEcho ut = new UDPEcho(host,port);
 | 
			
		||||
	     Thread thread = new Thread(ut);
 | 
			
		||||
	     thread.start();
 | 
			
		||||
 | 
			
		||||
	     BufferedReader in = new BufferedReader(
 | 
			
		||||
				 new InputStreamReader(System.in));
 | 
			
		||||
             String s;
 | 
			
		||||
             System.out.print("Enter datagram:");
 | 
			
		||||
             s = in.readLine();
 | 
			
		||||
	     while(s != null){
 | 
			
		||||
		ut.send(s);
 | 
			
		||||
		try{
 | 
			
		||||
		   Thread.currentThread().sleep(100);
 | 
			
		||||
		}catch(InterruptedException i_ex){
 | 
			
		||||
		}
 | 
			
		||||
                System.out.print("Enter datagram:");
 | 
			
		||||
                s = in.readLine();
 | 
			
		||||
	     }
 | 
			
		||||
	     System.exit(1);
 | 
			
		||||
 | 
			
		||||
	 }catch(IOException io_ex){
 | 
			
		||||
	   io_ex.printStackTrace();
 | 
			
		||||
	   System.exit(1);
 | 
			
		||||
	 }catch(NumberFormatException num_ex){
 | 
			
		||||
	   num_ex.printStackTrace();
 | 
			
		||||
	   System.exit(1);
 | 
			
		||||
	 }
 | 
			
		||||
 | 
			
		||||
      }else{
 | 
			
		||||
	usage();
 | 
			
		||||
      }
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
}//End of class
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,41 @@
 | 
			
		|||
package net.sourceforge.jsocks.test;
 | 
			
		||||
 | 
			
		||||
import net.sourceforge.jsocks.socks.*;
 | 
			
		||||
import net.sourceforge.jsocks.socks.server.*;
 | 
			
		||||
 | 
			
		||||
import java.net.Socket;
 | 
			
		||||
 | 
			
		||||
/** Test file for UserPasswordAuthentictor */
 | 
			
		||||
 | 
			
		||||
public class UPSOCKS implements UserValidation{
 | 
			
		||||
    String user, password;
 | 
			
		||||
 | 
			
		||||
    UPSOCKS(String user,String password){
 | 
			
		||||
       this.user = user;
 | 
			
		||||
       this.password = password;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public boolean isUserValid(String user,String password,Socket s){
 | 
			
		||||
       System.err.println("User:"+user+"\tPassword:"+password);
 | 
			
		||||
       System.err.println("Socket:"+s);
 | 
			
		||||
       return (user.equals(this.user) && password.equals(this.password));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static void main(String args[]){
 | 
			
		||||
        String user, password;
 | 
			
		||||
 | 
			
		||||
        if(args.length == 2){
 | 
			
		||||
          user = args[0];
 | 
			
		||||
          password = args[1];
 | 
			
		||||
        }else{
 | 
			
		||||
          user = "user";
 | 
			
		||||
          password = "password";
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        UPSOCKS us = new UPSOCKS(user,password);
 | 
			
		||||
        UserPasswordAuthenticator auth = new UserPasswordAuthenticator(us);
 | 
			
		||||
        ProxyServer server = new ProxyServer(auth);
 | 
			
		||||
 | 
			
		||||
        server.start(1080);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
		Reference in New Issue