package net.sourceforge.jsocks; import java.util.*; import java.io.*; import java.net.*; import net.sourceforge.jsocks.socks.Proxy; 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); } }